refactor: improve functions

Closes: #49
This commit is contained in:
2026-07-08 00:19:37 +02:00
parent 7de645d323
commit d49b4f5bc7
10 changed files with 188 additions and 122 deletions
+2 -2
View File
@@ -22,8 +22,8 @@ void executor::push_frame(const mod_h& mod, function function) {
}
std::vector<thing_h> args;
args.reserve(function.param_count());
for (size_t i = 0; i < function.param_count(); ++i)
args.reserve(function.signature().params.size());
while (args.size() < args.capacity())
args.push_back(pop_thing());
switch (function.type()) {
+7 -7
View File
@@ -7,7 +7,7 @@
namespace furvm {
function::function(const mod_h& mod, const function_h& function)
: m_type(function_t::Import), m_paramCount(0), m_value(import_function{ mod.id(), function.id() }) {}
: m_type(function_t::Import), m_value(import_function{ mod.id(), function.id() }) {}
function::~function() {
switch (m_type) {
@@ -23,7 +23,7 @@ function::~function() {
}
function::function(function&& other) noexcept
: m_type(other.m_type), m_paramCount(other.m_paramCount) {
: m_type(other.m_type), m_signature(std::move(other.m_signature)) {
switch (m_type) {
case function_t::Normal: {
m_value.position = other.m_value.position;
@@ -42,8 +42,8 @@ function::function(function&& other) noexcept
function& function::operator=(function&& other) noexcept {
if (this == &other) return *this;
m_type = other.m_type;
m_paramCount = other.m_paramCount;
m_type = other.m_type;
m_signature = other.m_signature;
switch (m_type) {
case function_t::Normal: {
m_value.position = other.m_value.position;
@@ -62,7 +62,7 @@ function& function::operator=(function&& other) noexcept {
}
function::function(const function& other)
: m_type(other.m_type), m_paramCount(other.m_paramCount) {
: m_type(other.m_type), m_signature(other.m_signature) {
switch (m_type) {
case function_t::Normal: {
m_value.position = other.m_value.position;
@@ -80,8 +80,8 @@ function::function(const function& other)
function& function::operator=(const function& other) {
if (this == &other) return *this;
m_type = other.m_type;
m_paramCount = other.m_paramCount;
m_type = other.m_type;
m_signature = other.m_signature;
switch (m_type) {
case function_t::Normal: {
m_value.position = other.m_value.position;
+4 -4
View File
@@ -58,10 +58,10 @@ int main(int argc, char** argv) {
static_cast<furvm::byte>(furvm::instruction_t::Return),
};
furvm::mod_h mod = context->emplace("main", s_bytecode, s_bytecode + sizeof(s_bytecode));
mod->emplace_type(std::make_shared<furvm::type>(context->at("core")->type_at(2), 10)).dispatch();
auto mainFunc = mod->emplace_function_named("main", 0, 0);
mod->emplace_function(1, "print").dispatch();
furvm::mod_h mod = context->emplace("main", s_bytecode, s_bytecode + sizeof(s_bytecode));
furvm::type_h intType = mod->emplace_type(std::make_shared<furvm::type>(context->at("core")->type_at(2), 10));
auto mainFunc = mod->emplace_function("main", furvm::function_sig{}, 0);
mod->emplace_function(furvm::function_sig{ { intType } }, "print").dispatch();
#endif
mod->set_native_function("print", [](furvm::executor& executor) { print_thing(*executor.load_thing(0)); });
+88 -67
View File
@@ -1,6 +1,7 @@
#include "furvm/module.hpp"
#include "furvm/detail/serialization.hpp"
#include "furvm/function.hpp"
#include "furvm/fwd.hpp"
#include "furvm/type.hpp"
@@ -17,34 +18,6 @@ std::ostream& mod::serialize(std::ostream& os) const {
os.write(MAGIC, sizeof(MAGIC));
detail::serialize(os, std::uint32_t(0)); // version
function_id funcCount = m_functions.cend() - m_functions.cbegin();
detail::serialize(os, funcCount);
for (function_id id = 0; id < funcCount; ++id) {
if (!m_functions.contains(id)) {
detail::serialize(os, "");
detail::serialize(os, 0);
detail::serialize(os, std::uint8_t(0xFF)); // null function
continue;
}
function_h func = m_functions.at(id);
detail::serialize(os, m_functionMap.at(func.id()));
detail::serialize(os, func->param_count());
detail::serialize(os, std::uint8_t(func->type()));
switch (func->type()) {
case function_t::Normal: {
detail::serialize(os, func->position());
} break;
case function_t::Native: {
detail::serialize(os, func->native());
} break;
case function_t::Import: {
detail::serialize(os, func->imp().mod);
detail::serialize(os, func->imp().function);
} break;
}
}
type_id typeCount = type_id(m_types.cend() - m_types.cbegin());
detail::serialize(os, typeCount);
for (type_id id = 0; id < typeCount; ++id) {
@@ -67,6 +40,45 @@ std::ostream& mod::serialize(std::ostream& os) const {
}
}
function_id funcCount = m_functions.cend() - m_functions.cbegin();
detail::serialize(os, funcCount);
for (function_id id = 0; id < funcCount; ++id) {
if (!m_functions.contains(id)) {
detail::serialize(os, "");
detail::serialize(os, 0);
detail::serialize(os, std::uint8_t(0xFF)); // null function
continue;
}
// Function name
function_h func = m_functions.at(id);
if (auto it = m_functionMap.find(func.id()); it != m_functionMap.end()) {
detail::serialize(os, it->second.first);
} else {
detail::serialize(os, "");
}
// Function signature
detail::serialize(os, func->signature().params.size());
for (std::uint32_t i = 0; i < func->signature().params.size(); ++i)
detail::serialize(os, func->signature().params[i].id());
// Function body/value
detail::serialize(os, std::uint8_t(func->type()));
switch (func->type()) {
case function_t::Normal: {
detail::serialize(os, func->position());
} break;
case function_t::Native: {
detail::serialize(os, func->native());
} break;
case function_t::Import: {
detail::serialize(os, func->imp().mod);
detail::serialize(os, func->imp().function);
} break;
}
}
detail::serialize(os, std::uint64_t(m_bytecode.size()));
return os.write(reinterpret_cast<const char*>(m_bytecode.data()), static_cast<std::streamsize>(m_bytecode.size()));
}
@@ -81,45 +93,6 @@ mod mod::load(std::istream& is) {
mod mod;
function_id functionCount = 0;
detail::load(is, functionCount);
for (function_id id = 0; id < functionCount; ++id) {
std::string name;
detail::load(is, name);
std::uint32_t paramCount = 0;
detail::load(is, paramCount);
std::uint8_t type = 0;
detail::load(is, type);
if (type == 0xFF) continue;
switch ((function_t)type) {
case function_t::Normal: {
decltype(std::declval<function>().position()) offset = 0;
detail::load(is, offset);
if (name.empty())
mod.emplace_function_named(std::move(name), id, paramCount, offset).dispatch();
else
mod.emplace_function(id, paramCount, offset).dispatch();
} break;
case function_t::Native: {
std::string native;
detail::load(is, native);
if (name.empty())
mod.emplace_function_named(std::move(name), id, paramCount, std::move(native)).dispatch();
else
mod.emplace_function(id, paramCount, std::move(native)).dispatch();
} break;
case function_t::Import: {
std::string modName;
detail::load(is, modName);
function_id function = 0;
detail::load(is, function);
mod.emplace_function(id, std::move(modName), function).dispatch();
} break;
default: throw std::runtime_error("unknown function type");
}
}
type_id typeCount = 0;
detail::load(is, typeCount);
for (type_id id = 0; id < typeCount; ++id) {
@@ -151,6 +124,54 @@ mod mod::load(std::istream& is) {
}
}
function_id functionCount = 0;
detail::load(is, functionCount);
for (function_id id = 0; id < functionCount; ++id) {
std::string name;
detail::load(is, name);
function_sig signature;
std::uint32_t paramCount = 0;
detail::load(is, paramCount);
signature.params.reserve(paramCount);
while (signature.params.size() < paramCount) {
thing_id param{ 0 };
detail::load(is, param);
signature.params.emplace_back(mod.type_at(param));
}
std::uint8_t type = 0;
detail::load(is, type);
if (type == 0xFF) continue;
switch ((function_t)type) {
case function_t::Normal: {
decltype(std::declval<function>().position()) offset = 0;
detail::load(is, offset);
if (name.empty())
mod.emplace_function(std::move(name), id, std::move(signature), offset).dispatch();
else
mod.emplace_function(id, std::move(signature), offset).dispatch();
} break;
case function_t::Native: {
std::string native;
detail::load(is, native);
if (name.empty())
mod.emplace_function(std::move(name), id, std::move(signature), std::move(native)).dispatch();
else
mod.emplace_function(id, std::move(signature), std::move(native)).dispatch();
} break;
case function_t::Import: {
std::string modName;
detail::load(is, modName);
function_id function = 0;
detail::load(is, function);
mod.emplace_function(id, std::move(modName), function).dispatch();
} break;
default: throw std::runtime_error("unknown function type");
}
}
std::uint64_t bytecodeLength = 0;
detail::load(is, bytecodeLength);
mod.bytecode().resize(bytecodeLength);