@@ -21,6 +21,7 @@ struct instruction_argument {
|
||||
Constant,
|
||||
Type,
|
||||
Variable,
|
||||
GlobalVariable,
|
||||
Function,
|
||||
Offset,
|
||||
|
||||
@@ -78,6 +79,8 @@ struct instruction {
|
||||
Lengthof,
|
||||
Load,
|
||||
Store,
|
||||
LoadGlobal,
|
||||
StoreGlobal,
|
||||
Call,
|
||||
Jump,
|
||||
JumpNotZero,
|
||||
|
||||
@@ -6,10 +6,14 @@
|
||||
#include "furvm/function.hpp"
|
||||
#include "furvm/fwd.hpp"
|
||||
#include "furvm/handle.hpp"
|
||||
#include "furvm/thing.hpp"
|
||||
|
||||
#include <functional>
|
||||
#include <istream>
|
||||
#include <limits>
|
||||
#include <optional>
|
||||
#include <ostream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
@@ -348,6 +352,33 @@ public:
|
||||
}
|
||||
|
||||
const handle_container<mod_type_h>& types() const { return m_types; }
|
||||
public:
|
||||
void set_global_variable_count(std::uint16_t count) {
|
||||
m_globalVariables.resize(count);
|
||||
m_globalVariables.shrink_to_fit();
|
||||
}
|
||||
|
||||
std::uint16_t get_global_variable_count() const { return static_cast<std::uint16_t>(m_globalVariables.size()); }
|
||||
|
||||
void store_global_variable(std::uint16_t var, thing<>&& thing) {
|
||||
if (var >= m_globalVariables.size()) throw std::runtime_error("invalid slot");
|
||||
m_globalVariables.emplace(m_globalVariables.cbegin() + var, std::move(thing));
|
||||
}
|
||||
|
||||
void store_global_variable(std::uint16_t var, const thing<>& thing) {
|
||||
if (var >= m_globalVariables.size()) throw std::runtime_error("invalid slot");
|
||||
m_globalVariables.emplace(m_globalVariables.cbegin() + var, thing);
|
||||
}
|
||||
|
||||
thing<>& load_global_variable(std::uint16_t var) {
|
||||
if (var >= m_globalVariables.size()) throw std::runtime_error("invalid slot");
|
||||
return m_globalVariables[var];
|
||||
}
|
||||
|
||||
const thing<>& load_global_variable(std::uint16_t var) const {
|
||||
if (var >= m_globalVariables.size()) throw std::runtime_error("invalid slot");
|
||||
return m_globalVariables[var];
|
||||
}
|
||||
public:
|
||||
/**
|
||||
* @brief Prints the module in a bytecode form to an output stream.
|
||||
@@ -376,6 +407,8 @@ private:
|
||||
|
||||
handle_container<mod_type_h> m_types;
|
||||
|
||||
std::vector<thing<>> m_globalVariables;
|
||||
|
||||
std::unordered_map<std::string, native_function> m_nativeFunctions;
|
||||
};
|
||||
|
||||
|
||||
@@ -326,6 +326,12 @@ void executor::step() {
|
||||
case instruction_t::Store: {
|
||||
store_thing(instr.arg.u16, std::move(pop_thing()));
|
||||
} break;
|
||||
case instruction_t::LoadGlobal: {
|
||||
push_thing(make_reference(frame.mod->load_global_variable(instr.arg.u16)));
|
||||
} break;
|
||||
case instruction_t::StoreGlobal: {
|
||||
frame.mod->store_global_variable(instr.arg.u16, std::move(pop_thing()));
|
||||
} break;
|
||||
case instruction_t::Call: {
|
||||
push_frame(frame.mod, *frame.mod->function_at(instr.arg.u16));
|
||||
} break;
|
||||
|
||||
@@ -27,6 +27,8 @@ const std::size_t instruction_argument::s_sizes[instruction_argument::Count] = {
|
||||
4,
|
||||
// Variable:
|
||||
2,
|
||||
// GlobalVariable:
|
||||
2,
|
||||
// Function:
|
||||
4,
|
||||
// Offset:
|
||||
@@ -54,6 +56,8 @@ const bool instruction_argument::s_signedness[instruction_argument::Count] = {
|
||||
false,
|
||||
// Variable:
|
||||
false,
|
||||
// GlobalVariable:
|
||||
false,
|
||||
// Function:
|
||||
false,
|
||||
// Offset:
|
||||
@@ -125,6 +129,10 @@ const instruction_argument_t instruction::s_arguments[instruction::Count] = {
|
||||
instruction_argument::Variable,
|
||||
// Store:
|
||||
instruction_argument::Variable,
|
||||
// LoadGlobal:
|
||||
instruction_argument::GlobalVariable,
|
||||
// StoreGlobal:
|
||||
instruction_argument::GlobalVariable,
|
||||
// Call:
|
||||
instruction_argument::Function,
|
||||
// Jump:
|
||||
|
||||
@@ -88,6 +88,8 @@ std::ostream& mod::serialize(std::ostream& os) const {
|
||||
}
|
||||
}
|
||||
|
||||
detail::serialize(os, static_cast<std::uint16_t>(m_globalVariables.size()));
|
||||
|
||||
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()));
|
||||
}
|
||||
@@ -197,6 +199,10 @@ mod mod::load(std::istream& is) {
|
||||
}
|
||||
}
|
||||
|
||||
std::uint16_t globalVariables = 0;
|
||||
detail::load(is, globalVariables);
|
||||
mod.set_global_variable_count(globalVariables);
|
||||
|
||||
std::uint64_t bytecodeLength = 0;
|
||||
detail::load(is, bytecodeLength);
|
||||
mod.bytecode().resize(bytecodeLength);
|
||||
|
||||
Reference in New Issue
Block a user