refactor(furvm): improve functions
Define native functions inside the module instead of the function itself (native functions hold only the key to the definition), introduce private functions, add parameter count to function and fix some bugs. Closes: #20 Closes: #25
This commit is contained in:
@@ -2,10 +2,12 @@
|
|||||||
#define FURVM_FUNCTION_HPP
|
#define FURVM_FUNCTION_HPP
|
||||||
|
|
||||||
#include "furvm/fwd.hpp"
|
#include "furvm/fwd.hpp"
|
||||||
|
#include "furvm/handle.hpp" // IWYU pragma: keep
|
||||||
|
|
||||||
#include <functional>
|
#include <cstdint>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace furvm {
|
namespace furvm {
|
||||||
@@ -19,7 +21,7 @@ enum class function_t : std::uint8_t {
|
|||||||
/**
|
/**
|
||||||
* @brief A native function.
|
* @brief A native function.
|
||||||
*/
|
*/
|
||||||
using native_function = std::function<void(executor&)>;
|
using native_function = std::string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A function import.
|
* @brief A function import.
|
||||||
@@ -35,31 +37,36 @@ public:
|
|||||||
* @brief Constructs a normal function.
|
* @brief Constructs a normal function.
|
||||||
*
|
*
|
||||||
* @param name Name of the function.
|
* @param name Name of the function.
|
||||||
|
* @param paramCount Paremeter count.
|
||||||
* @param position Offset in bytecode of the function.
|
* @param position Offset in bytecode of the function.
|
||||||
*/
|
*/
|
||||||
template <typename Name>
|
template <typename Name>
|
||||||
function(Name&& name, bytecode_pos position)
|
function(Name&& name, std::uint32_t paramCount, bytecode_pos position)
|
||||||
: m_name(std::forward<Name>(name)), m_type(function_t::Normal), m_value(position) {}
|
: m_name(std::forward<Name>(name)), m_type(function_t::Normal), m_paramCount(paramCount), m_value(position) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Constructs a native function.
|
* @brief Constructs a native function.
|
||||||
*
|
*
|
||||||
* @param name Name of the function.
|
* @param name Name of the function.
|
||||||
* @param native Native function.
|
* @param paramCount Paremeter count.
|
||||||
|
* @param native Native function tag.
|
||||||
*/
|
*/
|
||||||
template <typename Name>
|
template <typename Name,
|
||||||
function(Name&& name, const native_function& native)
|
typename Native,
|
||||||
: m_name(std::forward<Name>(name)), m_type(function_t::Native), m_value(native) {}
|
typename = std::enable_if_t<std::is_constructible_v<native_function, Native>>>
|
||||||
|
function(Name&& name, std::uint32_t paramCount, Native&& native)
|
||||||
|
: m_name(std::forward<Name>(name)),
|
||||||
|
m_type(function_t::Native),
|
||||||
|
m_paramCount(paramCount),
|
||||||
|
m_value(std::forward<Native>(native)) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Constructs an import function.
|
* @brief Constructs an import function.
|
||||||
*
|
*
|
||||||
* @param name Name of the function.
|
* @param paramCount Parameter count.
|
||||||
* @param imp Import function.
|
* @param imp Import function.
|
||||||
*/
|
*/
|
||||||
template <typename Name>
|
function(const mod_h& mod, const function_h& function);
|
||||||
function(Name&& name, const import_function& imp)
|
|
||||||
: m_name(std::forward<Name>(name)), m_type(function_t::Import), m_value(imp) {}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Destructs a function.
|
* @brief Destructs a function.
|
||||||
@@ -99,6 +106,13 @@ public:
|
|||||||
* @return The type.
|
* @return The type.
|
||||||
*/
|
*/
|
||||||
constexpr function_t type() const { return m_type; }
|
constexpr function_t type() const { return m_type; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns this function's parameter count.
|
||||||
|
*
|
||||||
|
* @return The parameter count.
|
||||||
|
*/
|
||||||
|
constexpr std::uint32_t param_count() const { return m_paramCount; }
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Returns normal function's value.
|
* @brief Returns normal function's value.
|
||||||
@@ -123,7 +137,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* @brief Returns import function's value.
|
* @brief Returns import function's value.
|
||||||
*
|
*
|
||||||
* @return The name.
|
* @return The value.
|
||||||
*/
|
*/
|
||||||
const import_function& imp() const {
|
const import_function& imp() const {
|
||||||
if (m_type != function_t::Import) throw std::runtime_error("function type mismatch");
|
if (m_type != function_t::Import) throw std::runtime_error("function type mismatch");
|
||||||
@@ -132,6 +146,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
function_t m_type;
|
function_t m_type;
|
||||||
|
std::uint32_t m_paramCount;
|
||||||
|
|
||||||
union value {
|
union value {
|
||||||
std::size_t position = 0;
|
std::size_t position = 0;
|
||||||
@@ -143,8 +158,9 @@ private:
|
|||||||
value(std::size_t position)
|
value(std::size_t position)
|
||||||
: position(position) {}
|
: position(position) {}
|
||||||
|
|
||||||
value(const native_function& native)
|
template <typename Native, typename = std::enable_if_t<std::is_constructible_v<native_function, Native>>>
|
||||||
: native(native) {}
|
value(Native&& native)
|
||||||
|
: native(std::forward<Native>(native)) {}
|
||||||
|
|
||||||
value(const import_function& imp)
|
value(const import_function& imp)
|
||||||
: imp(imp) {}
|
: imp(imp) {}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include "furvm/fwd.hpp"
|
#include "furvm/fwd.hpp"
|
||||||
#include "furvm/handle.hpp"
|
#include "furvm/handle.hpp"
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
@@ -20,6 +21,8 @@ public:
|
|||||||
using bytecode_t = std::vector<byte>; /**< An alias to a vector of bytes. */
|
using bytecode_t = std::vector<byte>; /**< An alias to a vector of bytes. */
|
||||||
|
|
||||||
static constexpr char MAGIC[4] = { 'F', 'u', 'r', 'M' }; /** Furvm module file magic. */
|
static constexpr char MAGIC[4] = { 'F', 'u', 'r', 'M' }; /** Furvm module file magic. */
|
||||||
|
|
||||||
|
using native_function = std::function<void(executor&)>;
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Constructs a module.
|
* @brief Constructs a module.
|
||||||
@@ -71,11 +74,29 @@ public:
|
|||||||
/**
|
/**
|
||||||
* @brief Emplaces a function in the module's function container.
|
* @brief Emplaces a function in the module's function container.
|
||||||
*
|
*
|
||||||
|
* Emplaces the function in module's function container and name to function map and public functions map.
|
||||||
|
*
|
||||||
* @param args Arguments forwarded into the container's emplace_back function.
|
* @param args Arguments forwarded into the container's emplace_back function.
|
||||||
* @return A handle to the emplaced function.
|
* @return A handle to the emplaced function.
|
||||||
*/
|
*/
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
function_h emplace_function(Args&&... args) {
|
function_h emplace_function(Args&&... args) {
|
||||||
|
function_h function = m_functions.emplace_back(std::forward<Args>(args)...);
|
||||||
|
m_functionMap[function->name()] = function.id();
|
||||||
|
m_publicFunctions[function->name()] = function.id();
|
||||||
|
return std::move(function);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Emplaces a function in the module's function container.
|
||||||
|
*
|
||||||
|
* Emplaces the function in module's function container and name to function map .
|
||||||
|
*
|
||||||
|
* @param args Arguments forwarded into the container's emplace_back function.
|
||||||
|
* @return A handle to the emplaced function.
|
||||||
|
*/
|
||||||
|
template <typename... Args>
|
||||||
|
function_h emplace_function_private(Args&&... args) {
|
||||||
function_h function = m_functions.emplace_back(std::forward<Args>(args)...);
|
function_h function = m_functions.emplace_back(std::forward<Args>(args)...);
|
||||||
m_functionMap[function->name()] = function.id();
|
m_functionMap[function->name()] = function.id();
|
||||||
return std::move(function);
|
return std::move(function);
|
||||||
@@ -87,8 +108,18 @@ public:
|
|||||||
* @param function Function to insert.
|
* @param function Function to insert.
|
||||||
*/
|
*/
|
||||||
template <typename Function>
|
template <typename Function>
|
||||||
void push_back(Function&& function) {
|
auto push_back(Function&& function) {
|
||||||
m_functions.emplace_back(std::forward<Function>(function));
|
return emplace_function(std::forward<Function>(function));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Inserts a function in the module's function container.
|
||||||
|
*
|
||||||
|
* @param function Function to insert.
|
||||||
|
*/
|
||||||
|
template <typename Function>
|
||||||
|
auto push_back_private(Function&& function) {
|
||||||
|
return emplace_function_private(std::forward<Function>(function));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -115,7 +146,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
template <typename NameFwd>
|
template <typename NameFwd>
|
||||||
auto function_at(NameFwd&& name) {
|
auto function_at(NameFwd&& name) {
|
||||||
return function_at(m_functionMap.at(std::forward<NameFwd>(name)));
|
return function_at(m_publicFunctions.at(std::forward<NameFwd>(name)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -126,7 +157,18 @@ public:
|
|||||||
*/
|
*/
|
||||||
template <typename NameFwd>
|
template <typename NameFwd>
|
||||||
auto function_at(NameFwd&& name) const {
|
auto function_at(NameFwd&& name) const {
|
||||||
return function_at(m_functionMap.at(std::forward<NameFwd>(name)));
|
return function_at(m_publicFunctions.at(std::forward<NameFwd>(name)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns an id of a function from the module.
|
||||||
|
*
|
||||||
|
* @param name Name of the function.
|
||||||
|
* @return An id of the function.
|
||||||
|
*/
|
||||||
|
template <typename NameFwd>
|
||||||
|
auto get_function_id(NameFwd&& name) {
|
||||||
|
return m_functionMap.at(std::forward<NameFwd>(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -135,6 +177,16 @@ public:
|
|||||||
* @param id Identifier of the function.
|
* @param id Identifier of the function.
|
||||||
*/
|
*/
|
||||||
void erase_function(function_id id) { m_functions.erase(id); }
|
void erase_function(function_id id) { m_functions.erase(id); }
|
||||||
|
public:
|
||||||
|
template <typename NameFwd, typename Func>
|
||||||
|
void set_native_function(NameFwd&& name, Func&& func) {
|
||||||
|
m_nativeFunctions.emplace(std::forward<NameFwd>(name), std::forward<Func>(func));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename NameFwd>
|
||||||
|
native_function get_native_function(NameFwd&& name) const {
|
||||||
|
return m_nativeFunctions.at(std::forward<NameFwd>(name));
|
||||||
|
}
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Prints the module in a bytecode form to an output stream.
|
* @brief Prints the module in a bytecode form to an output stream.
|
||||||
@@ -147,7 +199,10 @@ private:
|
|||||||
bytecode_t m_bytecode;
|
bytecode_t m_bytecode;
|
||||||
|
|
||||||
std::unordered_map<std::string, function_id> m_functionMap;
|
std::unordered_map<std::string, function_id> m_functionMap;
|
||||||
|
std::unordered_map<std::string, function_id> m_publicFunctions;
|
||||||
handle_container<function_h> m_functions;
|
handle_container<function_h> m_functions;
|
||||||
|
|
||||||
|
std::unordered_map<std::string, native_function> m_nativeFunctions;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace furvm
|
} // namespace furvm
|
||||||
|
|||||||
+21
-14
@@ -9,18 +9,31 @@
|
|||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace furvm {
|
namespace furvm {
|
||||||
|
|
||||||
void executor::push_frame(const mod_h& mod, function function) {
|
void executor::push_frame(const mod_h& mod, function function) {
|
||||||
|
mod_h modInst = mod;
|
||||||
while (function.type() == function_t::Import) {
|
while (function.type() == function_t::Import) {
|
||||||
function = *m_context->module_at(function.imp().mod)->function_at(function.imp().function);
|
modInst = m_context->module_at(function.imp().mod);
|
||||||
|
function = *modInst->function_at(function.imp().function);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<thing_h> args;
|
||||||
|
args.reserve(function.param_count());
|
||||||
|
for (size_t i = 0; i < function.param_count(); ++i)
|
||||||
|
args.push_back(pop_thing());
|
||||||
|
|
||||||
switch (function.type()) {
|
switch (function.type()) {
|
||||||
case function_t::Normal: {
|
case function_t::Normal: {
|
||||||
m_frames.emplace((struct executor::frame){ mod, function.position(), m_stack.size() });
|
m_frames.emplace((struct executor::frame){ mod, function.position(), m_stack.size(), std::move(args) });
|
||||||
|
} break;
|
||||||
|
case function_t::Native: {
|
||||||
|
m_frames.emplace((struct executor::frame){ mod, 0, m_stack.size(), std::move(args) });
|
||||||
|
modInst->get_native_function(function.name())(*this);
|
||||||
|
m_frames.pop();
|
||||||
} break;
|
} break;
|
||||||
case function_t::Native:
|
|
||||||
default: throw std::runtime_error("unexpected function type");
|
default: throw std::runtime_error("unexpected function type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -54,13 +67,13 @@ thing_h executor::thing() const {
|
|||||||
|
|
||||||
void executor::store_thing(variable_t variable, const thing_h& thing) {
|
void executor::store_thing(variable_t variable, const thing_h& thing) {
|
||||||
auto& frame = m_frames.top();
|
auto& frame = m_frames.top();
|
||||||
frame.variables.resize(variable + 1);
|
if (frame.variables.size() <= variable) frame.variables.resize(variable + 1);
|
||||||
frame.variables[variable] = thing;
|
frame.variables[variable] = thing;
|
||||||
}
|
}
|
||||||
|
|
||||||
void executor::store_thing(variable_t variable, thing_h&& thing) {
|
void executor::store_thing(variable_t variable, thing_h&& thing) {
|
||||||
auto& frame = m_frames.top();
|
auto& frame = m_frames.top();
|
||||||
frame.variables.resize(variable + 1);
|
if (frame.variables.size() <= variable) frame.variables.resize(variable + 1);
|
||||||
frame.variables[variable] = std::move(thing);
|
frame.variables[variable] = std::move(thing);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,21 +173,15 @@ void executor::step() {
|
|||||||
function_id funcId = static_cast<std::uint16_t>(frame.mod->byte(frame.position)) |
|
function_id funcId = static_cast<std::uint16_t>(frame.mod->byte(frame.position)) |
|
||||||
(static_cast<std::uint16_t>(frame.mod->byte(frame.position + 1)) << 8);
|
(static_cast<std::uint16_t>(frame.mod->byte(frame.position + 1)) << 8);
|
||||||
frame.position += 2;
|
frame.position += 2;
|
||||||
|
push_frame(frame.mod, *frame.mod->function_at(funcId));
|
||||||
const function_h& function = frame.mod->function_at(funcId);
|
|
||||||
switch (function->type()) {
|
|
||||||
case function_t::Normal:
|
|
||||||
case function_t::Import: push_frame(frame.mod, *function); break;
|
|
||||||
case function_t::Native: function->native()(*this); break;
|
|
||||||
}
|
|
||||||
} break;
|
} break;
|
||||||
case instruction_t::Jump: {
|
case instruction_t::Jump: {
|
||||||
frame.position += frame.mod->byte(frame.position++);
|
frame.position += ((std::int8_t)frame.mod->byte(frame.position)) + 1;
|
||||||
} break;
|
} break;
|
||||||
case instruction_t::JumpNotZero: {
|
case instruction_t::JumpNotZero: {
|
||||||
byte offset = frame.mod->byte(frame.position++);
|
byte offset = frame.mod->byte(frame.position++);
|
||||||
auto cond = pop_thing();
|
auto cond = pop_thing();
|
||||||
if (cond->int32() != 0) frame.position += offset;
|
if (cond->int32() != 0) frame.position += (std::int8_t)offset;
|
||||||
} break;
|
} break;
|
||||||
case instruction_t::Return: {
|
case instruction_t::Return: {
|
||||||
pop_frame();
|
pop_frame();
|
||||||
|
|||||||
+20
-7
@@ -1,14 +1,21 @@
|
|||||||
#include "furvm/function.hpp"
|
#include "furvm/function.hpp"
|
||||||
|
|
||||||
|
#include "furvm/furvm.hpp"
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace furvm {
|
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() }) {}
|
||||||
|
|
||||||
function::~function() {
|
function::~function() {
|
||||||
switch (m_type) {
|
switch (m_type) {
|
||||||
case function_t::Normal:
|
case function_t::Normal:
|
||||||
case function_t::Native:
|
|
||||||
default: break;
|
default: break;
|
||||||
|
case function_t::Native: {
|
||||||
|
m_value.native.~native_function();
|
||||||
|
} break;
|
||||||
case function_t::Import: {
|
case function_t::Import: {
|
||||||
m_value.imp.~import_function();
|
m_value.imp.~import_function();
|
||||||
} break;
|
} break;
|
||||||
@@ -16,7 +23,7 @@ function::~function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function::function(function&& other) noexcept
|
function::function(function&& other) noexcept
|
||||||
: m_name(std::move(other.m_name)), m_type(other.m_type) {
|
: m_name(std::move(other.m_name)), m_type(other.m_type), m_paramCount(other.m_paramCount) {
|
||||||
switch (m_type) {
|
switch (m_type) {
|
||||||
case function_t::Normal: {
|
case function_t::Normal: {
|
||||||
m_value.position = other.m_value.position;
|
m_value.position = other.m_value.position;
|
||||||
@@ -25,8 +32,9 @@ function::function(function&& other) noexcept
|
|||||||
new (&m_value.native) native_function(std::move(other.m_value.native));
|
new (&m_value.native) native_function(std::move(other.m_value.native));
|
||||||
} break;
|
} break;
|
||||||
case function_t::Import: {
|
case function_t::Import: {
|
||||||
m_value.imp = std::move(other.m_value.imp);
|
new (&m_value.imp) import_function(std::move(other.m_value.imp));
|
||||||
} break;
|
} break;
|
||||||
|
default: break;
|
||||||
}
|
}
|
||||||
other.m_value.position = 0;
|
other.m_value.position = 0;
|
||||||
}
|
}
|
||||||
@@ -36,6 +44,7 @@ function& function::operator=(function&& other) noexcept {
|
|||||||
|
|
||||||
m_name = std::move(other.m_name);
|
m_name = std::move(other.m_name);
|
||||||
m_type = other.m_type;
|
m_type = other.m_type;
|
||||||
|
m_paramCount = other.m_paramCount;
|
||||||
switch (m_type) {
|
switch (m_type) {
|
||||||
case function_t::Normal: {
|
case function_t::Normal: {
|
||||||
m_value.position = other.m_value.position;
|
m_value.position = other.m_value.position;
|
||||||
@@ -44,8 +53,9 @@ function& function::operator=(function&& other) noexcept {
|
|||||||
new (&m_value.native) native_function(std::move(other.m_value.native));
|
new (&m_value.native) native_function(std::move(other.m_value.native));
|
||||||
} break;
|
} break;
|
||||||
case function_t::Import: {
|
case function_t::Import: {
|
||||||
m_value.imp = std::move(other.m_value.imp);
|
new (&m_value.imp) import_function(std::move(other.m_value.imp));
|
||||||
} break;
|
} break;
|
||||||
|
default: break;
|
||||||
}
|
}
|
||||||
other.m_value.position = 0;
|
other.m_value.position = 0;
|
||||||
|
|
||||||
@@ -53,7 +63,7 @@ function& function::operator=(function&& other) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function::function(const function& other)
|
function::function(const function& other)
|
||||||
: m_name(other.m_name), m_type(other.m_type) {
|
: m_name(other.m_name), m_type(other.m_type), m_paramCount(other.m_paramCount) {
|
||||||
switch (m_type) {
|
switch (m_type) {
|
||||||
case function_t::Normal: {
|
case function_t::Normal: {
|
||||||
m_value.position = other.m_value.position;
|
m_value.position = other.m_value.position;
|
||||||
@@ -62,8 +72,9 @@ function::function(const function& other)
|
|||||||
new (&m_value.native) native_function(other.m_value.native);
|
new (&m_value.native) native_function(other.m_value.native);
|
||||||
} break;
|
} break;
|
||||||
case function_t::Import: {
|
case function_t::Import: {
|
||||||
m_value.imp = other.m_value.imp;
|
new (&m_value.imp) import_function(other.m_value.imp);
|
||||||
} break;
|
} break;
|
||||||
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,6 +83,7 @@ function& function::operator=(const function& other) {
|
|||||||
|
|
||||||
m_name = other.m_name;
|
m_name = other.m_name;
|
||||||
m_type = other.m_type;
|
m_type = other.m_type;
|
||||||
|
m_paramCount = other.m_paramCount;
|
||||||
switch (m_type) {
|
switch (m_type) {
|
||||||
case function_t::Normal: {
|
case function_t::Normal: {
|
||||||
m_value.position = other.m_value.position;
|
m_value.position = other.m_value.position;
|
||||||
@@ -80,8 +92,9 @@ function& function::operator=(const function& other) {
|
|||||||
new (&m_value.native) native_function(other.m_value.native);
|
new (&m_value.native) native_function(other.m_value.native);
|
||||||
} break;
|
} break;
|
||||||
case function_t::Import: {
|
case function_t::Import: {
|
||||||
m_value.imp = other.m_value.imp;
|
new (&m_value.imp) import_function(other.m_value.imp);
|
||||||
} break;
|
} break;
|
||||||
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
|
|||||||
+16
-5
@@ -13,22 +13,33 @@ static constexpr std::array<furvm::byte, 8> s_bytecode = {
|
|||||||
67,
|
67,
|
||||||
furvm::byte(furvm::instruction_t::Clone),
|
furvm::byte(furvm::instruction_t::Clone),
|
||||||
furvm::byte(furvm::instruction_t::Add),
|
furvm::byte(furvm::instruction_t::Add),
|
||||||
|
furvm::byte(furvm::instruction_t::Call),
|
||||||
|
1,
|
||||||
|
0,
|
||||||
furvm::byte(furvm::instruction_t::Return),
|
furvm::byte(furvm::instruction_t::Return),
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
auto context = std::make_shared<furvm::context>();
|
auto context = std::make_shared<furvm::context>();
|
||||||
|
|
||||||
furvm::mod_h mainModule = context->emplace_module("main", s_bytecode.begin(), s_bytecode.end());
|
furvm::mod_h furlangModule = context->emplace_module("furlang");
|
||||||
furvm::function_h mainFunc = mainModule->emplace_function("main", 0);
|
furvm::function_h printFunc = furlangModule->emplace_function("print", 1, "print");
|
||||||
|
furlangModule->set_native_function("print", [](furvm::executor& executor) {
|
||||||
|
furvm::thing_h thing = executor.load_thing(0);
|
||||||
|
switch (thing->type()) {
|
||||||
|
case furvm::thing_t::Int32: {
|
||||||
|
std::cout << thing->int32() << '\n';
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
mainModule->serialize(std::cout);
|
furvm::mod_h mainModule = context->emplace_module("main", s_bytecode.begin(), s_bytecode.end());
|
||||||
|
furvm::function_h mainFunc = mainModule->emplace_function("main", 0, 0);
|
||||||
|
mainModule->emplace_function(furlangModule, printFunc).dispatch();
|
||||||
|
|
||||||
furvm::executor_h executor = context->emplace_executor(context);
|
furvm::executor_h executor = context->emplace_executor(context);
|
||||||
executor->push_frame(mainModule, *mainFunc);
|
executor->push_frame(mainModule, *mainFunc);
|
||||||
|
|
||||||
static constexpr std::size_t FPC = 3; // Frames per collection
|
|
||||||
|
|
||||||
while ((executor->flags() & furvm::executor_flags::Done) != furvm::executor_flags::Done) {
|
while ((executor->flags() & furvm::executor_flags::Done) != furvm::executor_flags::Done) {
|
||||||
executor->step();
|
executor->step();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,9 +12,10 @@ std::ostream& mod::serialize(std::ostream& os) const {
|
|||||||
detail::serialize(os, std::uint32_t(0)); // version
|
detail::serialize(os, std::uint32_t(0)); // version
|
||||||
|
|
||||||
detail::serialize(os, function_id(m_functionMap.size()));
|
detail::serialize(os, function_id(m_functionMap.size()));
|
||||||
for (const auto& [name, id] : m_functionMap) {
|
for (auto* pair : m_functions) {
|
||||||
detail::serialize(os, name);
|
function_h func = { pair };
|
||||||
function_h func = m_functions.at(id);
|
bool isPublic = m_publicFunctions.find(func->name()) != m_publicFunctions.end();
|
||||||
|
detail::serialize(os, isPublic ? func->name() : ""); // private functions have empty names
|
||||||
detail::serialize(os, std::uint8_t(func->type()));
|
detail::serialize(os, std::uint8_t(func->type()));
|
||||||
switch (func->type()) {
|
switch (func->type()) {
|
||||||
case function_t::Normal: {
|
case function_t::Normal: {
|
||||||
|
|||||||
Reference in New Issue
Block a user