@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "furvm/fwd.hpp"
|
#include "furvm/fwd.hpp"
|
||||||
#include "furvm/module.hpp" // IWYU pragma: keep
|
#include "furvm/module.hpp" // IWYU pragma: keep
|
||||||
|
#include "furvm/stack.hpp"
|
||||||
#include "furvm/thing.hpp" // IWYU pragma: keep
|
#include "furvm/thing.hpp" // IWYU pragma: keep
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
@@ -39,6 +40,8 @@ public:
|
|||||||
static constexpr executor_flags STATE_FLAGS = executor_flags::JustHit;
|
static constexpr executor_flags STATE_FLAGS = executor_flags::JustHit;
|
||||||
|
|
||||||
using new_frame_callback = std::function<void(executor&)>;
|
using new_frame_callback = std::function<void(executor&)>;
|
||||||
|
|
||||||
|
using stack_thing = thing<stack_allocator>;
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Executor frame.
|
* @brief Executor frame.
|
||||||
@@ -51,7 +54,7 @@ public:
|
|||||||
std::size_t stackBase; /**< Snapshot of the stack size before this frame. */
|
std::size_t stackBase; /**< Snapshot of the stack size before this frame. */
|
||||||
|
|
||||||
thing_type* returnType; /**< Return type. */
|
thing_type* returnType; /**< Return type. */
|
||||||
std::vector<thing<>> variables; /**< Frame variables. */
|
std::vector<stack_thing> variables; /**< Frame variables. */
|
||||||
};
|
};
|
||||||
public:
|
public:
|
||||||
~executor() = default;
|
~executor() = default;
|
||||||
@@ -131,27 +134,27 @@ public:
|
|||||||
* @param thing Thing.
|
* @param thing Thing.
|
||||||
* @return The pushed handle.
|
* @return The pushed handle.
|
||||||
*/
|
*/
|
||||||
thing<>& push_thing(thing<>&& thing);
|
stack_thing& push_thing(stack_thing&& thing);
|
||||||
|
|
||||||
thing<>& push_thing(const thing<>& thing);
|
stack_thing& push_thing(const stack_thing& thing);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Pops a thing from the stack.
|
* @brief Pops a thing from the stack.
|
||||||
*
|
*
|
||||||
* @return A handle to the popped thing.
|
* @return A handle to the popped thing.
|
||||||
*/
|
*/
|
||||||
thing<> pop_thing();
|
stack_thing pop_thing();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the top thing on the stack.
|
* @brief Returns the top thing on the stack.
|
||||||
*
|
*
|
||||||
* @return A handle to the top thing.
|
* @return A handle to the top thing.
|
||||||
*/
|
*/
|
||||||
thing<>& top_thing();
|
stack_thing& top_thing();
|
||||||
|
|
||||||
const thing<>& top_thing() const;
|
const stack_thing& top_thing() const;
|
||||||
|
|
||||||
const std::vector<thing<>>& stack() const { return m_stack; }
|
const std::vector<stack_thing>& stack() const { return m_stack; }
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Stores a thing in a frame variable.
|
* @brief Stores a thing in a frame variable.
|
||||||
@@ -159,7 +162,7 @@ public:
|
|||||||
* @param variable Id of the variable in which the handle will be put.
|
* @param variable Id of the variable in which the handle will be put.
|
||||||
* @param thing Thing handle.
|
* @param thing Thing handle.
|
||||||
*/
|
*/
|
||||||
void store_thing(variable_t variable, const thing<>& thing);
|
void store_thing(variable_t variable, const stack_thing& thing);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Stores a thing in a frame variable.
|
* @brief Stores a thing in a frame variable.
|
||||||
@@ -167,7 +170,7 @@ public:
|
|||||||
* @param variable Id of the variable in which the handle will be put.
|
* @param variable Id of the variable in which the handle will be put.
|
||||||
* @param thing Thing handle.
|
* @param thing Thing handle.
|
||||||
*/
|
*/
|
||||||
void store_thing(variable_t variable, thing<>&& thing);
|
void store_thing(variable_t variable, stack_thing&& thing);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns a thing stored in a variable.
|
* @brief Returns a thing stored in a variable.
|
||||||
@@ -175,9 +178,9 @@ public:
|
|||||||
* @param variable Id of the variable from which the handle will be fetched.
|
* @param variable Id of the variable from which the handle will be fetched.
|
||||||
* @return A handle stored in the variable.
|
* @return A handle stored in the variable.
|
||||||
*/
|
*/
|
||||||
thing<>& load_thing(variable_t variable);
|
stack_thing& load_thing(variable_t variable);
|
||||||
|
|
||||||
const thing<>& load_thing(variable_t variable) const;
|
const stack_thing& load_thing(variable_t variable) const;
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Executes next instruction.
|
* @brief Executes next instruction.
|
||||||
@@ -192,9 +195,10 @@ private:
|
|||||||
private:
|
private:
|
||||||
executor_flags m_flags = executor_flags::Done;
|
executor_flags m_flags = executor_flags::Done;
|
||||||
context* m_context;
|
context* m_context;
|
||||||
|
furvm::stack<std::byte> m_stackStorage;
|
||||||
|
|
||||||
std::stack<frame> m_frames;
|
std::stack<frame> m_frames;
|
||||||
std::vector<thing<>> m_stack;
|
std::vector<stack_thing> m_stack;
|
||||||
|
|
||||||
new_frame_callback m_newFrameCb = nullptr;
|
new_frame_callback m_newFrameCb = nullptr;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#ifndef FURVM_FUNCTION_HPP
|
#ifndef FURVM_FUNCTION_HPP
|
||||||
#define FURVM_FUNCTION_HPP
|
#define FURVM_FUNCTION_HPP
|
||||||
|
|
||||||
#include "furlang/utility/hash.hpp"
|
|
||||||
#include "furvm/fwd.hpp"
|
#include "furvm/fwd.hpp"
|
||||||
#include "furvm/handle.hpp" // IWYU pragma: keep
|
#include "furvm/handle.hpp" // IWYU pragma: keep
|
||||||
|
|
||||||
|
|||||||
@@ -194,6 +194,9 @@ private:
|
|||||||
template <template <typename> typename Allocator>
|
template <template <typename> typename Allocator>
|
||||||
class thing final {
|
class thing final {
|
||||||
friend class executor;
|
friend class executor;
|
||||||
|
|
||||||
|
template <template <typename> class Other>
|
||||||
|
friend class thing;
|
||||||
public:
|
public:
|
||||||
using allocator_type = Allocator<std::byte>; /**< Allocator type. */
|
using allocator_type = Allocator<std::byte>; /**< Allocator type. */
|
||||||
public:
|
public:
|
||||||
@@ -206,7 +209,8 @@ public:
|
|||||||
thing_type type;
|
thing_type type;
|
||||||
};
|
};
|
||||||
public:
|
public:
|
||||||
thing() {}
|
thing(const allocator_type& allocator = {})
|
||||||
|
: m_allocator(allocator) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Constructs a thing.
|
* @brief Constructs a thing.
|
||||||
@@ -230,15 +234,15 @@ public:
|
|||||||
*
|
*
|
||||||
* TODO: Reword the note above.
|
* TODO: Reword the note above.
|
||||||
*/
|
*/
|
||||||
static thing make_reference(const thing& owner) {
|
template <template <typename> class Other = Allocator>
|
||||||
thing ref;
|
static thing make_reference(const thing<Other>& owner, const allocator_type& allocator = {}) {
|
||||||
|
thing ref = { allocator };
|
||||||
ref.m_reference = true;
|
ref.m_reference = true;
|
||||||
ref.m_data = owner.m_data;
|
ref.m_data = owner.m_data;
|
||||||
ref.m_type = owner.m_type;
|
ref.m_type = owner.m_type;
|
||||||
ref.m_size = owner.m_size;
|
ref.m_size = owner.m_size;
|
||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Destructs a thing.
|
* @brief Destructs a thing.
|
||||||
*/
|
*/
|
||||||
@@ -247,7 +251,16 @@ public:
|
|||||||
/**
|
/**
|
||||||
* @brief Move constructor.
|
* @brief Move constructor.
|
||||||
*/
|
*/
|
||||||
thing(thing&& other) noexcept { *this = std::move(other); }
|
thing(thing&& other) noexcept
|
||||||
|
: m_reference(other.m_reference),
|
||||||
|
m_type(other.m_type),
|
||||||
|
m_size(other.m_size),
|
||||||
|
m_data(other.m_data),
|
||||||
|
m_allocator(other.m_allocator) {
|
||||||
|
other.m_type = nullptr;
|
||||||
|
other.m_data = nullptr;
|
||||||
|
other.m_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Move constructor.
|
* @brief Move constructor.
|
||||||
@@ -266,7 +279,16 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
thing(const thing& other) { *this = other; }
|
thing(const thing& other)
|
||||||
|
: m_reference(other.m_reference), m_size(other.m_size), m_allocator(other.m_allocator) {
|
||||||
|
if (m_reference) {
|
||||||
|
m_type = other.m_type;
|
||||||
|
m_data = other.m_data;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
allocate(other.type());
|
||||||
|
other.copy(*this);
|
||||||
|
}
|
||||||
|
|
||||||
thing& operator=(const thing& other) {
|
thing& operator=(const thing& other) {
|
||||||
if (this == &other) return *this;
|
if (this == &other) return *this;
|
||||||
@@ -275,7 +297,38 @@ public:
|
|||||||
|
|
||||||
m_reference = other.m_reference;
|
m_reference = other.m_reference;
|
||||||
m_size = other.m_size;
|
m_size = other.m_size;
|
||||||
m_allocator = other.m_allocator;
|
|
||||||
|
if (m_reference) {
|
||||||
|
m_type = other.m_type;
|
||||||
|
m_data = other.m_data;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
allocate(other.type());
|
||||||
|
other.copy(*this);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <template <typename> class Other>
|
||||||
|
thing(const thing<Other>& other)
|
||||||
|
: m_reference(other.m_reference), m_size(other.m_size) {
|
||||||
|
if (m_reference) {
|
||||||
|
m_type = other.m_type;
|
||||||
|
m_data = other.m_data;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
allocate(other.type());
|
||||||
|
other.copy(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <template <typename> class Other>
|
||||||
|
thing& operator=(const thing<Other>& other) {
|
||||||
|
if (this == &other) return *this;
|
||||||
|
|
||||||
|
free();
|
||||||
|
|
||||||
|
m_reference = other.m_reference;
|
||||||
|
m_size = other.m_size;
|
||||||
|
|
||||||
if (m_reference) {
|
if (m_reference) {
|
||||||
m_type = other.m_type;
|
m_type = other.m_type;
|
||||||
@@ -299,7 +352,8 @@ public:
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
void copy(thing<>& dst) const {
|
template <template <typename> class Other>
|
||||||
|
void copy(thing<Other>& dst) const {
|
||||||
switch (m_type->type) {
|
switch (m_type->type) {
|
||||||
case thing_type::S8:
|
case thing_type::S8:
|
||||||
case thing_type::S16:
|
case thing_type::S16:
|
||||||
@@ -499,7 +553,7 @@ public:
|
|||||||
thing at(thing_type::u64 index) const {
|
thing at(thing_type::u64 index) const {
|
||||||
if (!is(thing_type::Array)) throw bad_thing_access();
|
if (!is(thing_type::Array)) throw bad_thing_access();
|
||||||
|
|
||||||
thing ref = {};
|
thing ref = { m_allocator };
|
||||||
ref.m_reference = true;
|
ref.m_reference = true;
|
||||||
ref.m_size = compute_size_na(*type().value.array.type);
|
ref.m_size = compute_size_na(*type().value.array.type);
|
||||||
|
|
||||||
|
|||||||
+44
-31
@@ -70,6 +70,8 @@ bool executor::compare_thing_types(const thing_type& lhs, const thing_type& rhs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void executor::push_frame(const mod_h& mod, function function) {
|
void executor::push_frame(const mod_h& mod, function function) {
|
||||||
|
m_stackStorage.push_frame();
|
||||||
|
|
||||||
mod_h modInst = mod;
|
mod_h modInst = mod;
|
||||||
while (function.type() == function_t::Import) {
|
while (function.type() == function_t::Import) {
|
||||||
modInst = m_context->at(function.imp().mod);
|
modInst = m_context->at(function.imp().mod);
|
||||||
@@ -77,13 +79,13 @@ void executor::push_frame(const mod_h& mod, function function) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto signature = function.signature();
|
auto signature = function.signature();
|
||||||
std::vector<thing<>> args;
|
std::vector<stack_thing> args;
|
||||||
args.reserve(signature.params.size());
|
args.reserve(signature.params.size());
|
||||||
for (const auto& param : signature.params) {
|
for (const auto& param : signature.params) {
|
||||||
auto arg = pop_thing();
|
auto arg = pop_thing();
|
||||||
if (compare_thing_types(arg.type(), *mod_to_thing_type(mod, *param)))
|
if (compare_thing_types(arg.type(), *mod_to_thing_type(mod, *param)))
|
||||||
throw std::runtime_error("function argument type mismatch");
|
throw std::runtime_error("function argument type mismatch");
|
||||||
args.push_back(std::move(arg));
|
args.emplace_back(std::move(arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
struct thing_type* returnType = nullptr;
|
struct thing_type* returnType = nullptr;
|
||||||
@@ -117,7 +119,7 @@ struct executor::frame executor::pop_frame() {
|
|||||||
if (m_frames.empty()) throw stack_underflow();
|
if (m_frames.empty()) throw stack_underflow();
|
||||||
struct executor::frame frame = m_frames.top();
|
struct executor::frame frame = m_frames.top();
|
||||||
m_frames.pop();
|
m_frames.pop();
|
||||||
std::optional<thing<>> returnValue;
|
std::optional<stack_thing> returnValue;
|
||||||
if (frame.returnType != nullptr) {
|
if (frame.returnType != nullptr) {
|
||||||
returnValue = pop_thing();
|
returnValue = pop_thing();
|
||||||
if (returnValue->type() != *frame.returnType) throw std::runtime_error("function return type mismatch");
|
if (returnValue->type() != *frame.returnType) throw std::runtime_error("function return type mismatch");
|
||||||
@@ -132,6 +134,8 @@ struct executor::frame executor::pop_frame() {
|
|||||||
}
|
}
|
||||||
m_flags = m_flags & ~executor_flags::JustHit;
|
m_flags = m_flags & ~executor_flags::JustHit;
|
||||||
|
|
||||||
|
m_stackStorage.pop_frame();
|
||||||
|
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,49 +143,49 @@ struct executor::frame executor::top_frame() const {
|
|||||||
return m_frames.top();
|
return m_frames.top();
|
||||||
}
|
}
|
||||||
|
|
||||||
thing<>& executor::push_thing(thing<>&& thing) {
|
executor::stack_thing& executor::push_thing(stack_thing&& thing) {
|
||||||
return m_stack.emplace_back(std::move(thing));
|
return m_stack.emplace_back(std::move(thing));
|
||||||
}
|
}
|
||||||
|
|
||||||
thing<>& executor::push_thing(const thing<>& thing) {
|
executor::stack_thing& executor::push_thing(const stack_thing& thing) {
|
||||||
return m_stack.emplace_back(thing);
|
return m_stack.emplace_back(thing);
|
||||||
}
|
}
|
||||||
|
|
||||||
thing<> executor::pop_thing() {
|
executor::stack_thing executor::pop_thing() {
|
||||||
if (m_frames.top().stackBase >= m_stack.size()) throw stack_underflow();
|
if (m_frames.top().stackBase >= m_stack.size()) throw stack_underflow();
|
||||||
auto top = std::move(m_stack.back());
|
auto top = std::move(m_stack.back());
|
||||||
m_stack.pop_back();
|
m_stack.pop_back();
|
||||||
return std::move(top);
|
return std::move(top);
|
||||||
}
|
}
|
||||||
|
|
||||||
thing<>& executor::top_thing() {
|
executor::stack_thing& executor::top_thing() {
|
||||||
if (m_frames.top().stackBase >= m_stack.size()) throw stack_underflow();
|
if (m_frames.top().stackBase >= m_stack.size()) throw stack_underflow();
|
||||||
return m_stack.back();
|
return m_stack.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
const thing<>& executor::top_thing() const {
|
const executor::stack_thing& executor::top_thing() const {
|
||||||
if (m_frames.top().stackBase >= m_stack.size()) throw stack_underflow();
|
if (m_frames.top().stackBase >= m_stack.size()) throw stack_underflow();
|
||||||
return m_stack.back();
|
return m_stack.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
void executor::store_thing(variable_t variable, const thing<>& thing) {
|
void executor::store_thing(variable_t variable, const stack_thing& thing) {
|
||||||
auto& frame = m_frames.top();
|
auto& frame = m_frames.top();
|
||||||
if (frame.variables.size() <= variable) 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<>&& thing) {
|
void executor::store_thing(variable_t variable, stack_thing&& thing) {
|
||||||
auto& frame = m_frames.top();
|
auto& frame = m_frames.top();
|
||||||
if (frame.variables.size() <= variable) 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
thing<>& executor::load_thing(variable_t variable) {
|
executor::stack_thing& executor::load_thing(variable_t variable) {
|
||||||
auto& frame = m_frames.top();
|
auto& frame = m_frames.top();
|
||||||
return frame.variables[variable];
|
return frame.variables[variable];
|
||||||
}
|
}
|
||||||
|
|
||||||
const thing<>& executor::load_thing(variable_t variable) const {
|
const executor::stack_thing& executor::load_thing(variable_t variable) const {
|
||||||
const auto& frame = m_frames.top();
|
const auto& frame = m_frames.top();
|
||||||
return frame.variables[variable];
|
return frame.variables[variable];
|
||||||
}
|
}
|
||||||
@@ -204,38 +208,45 @@ void executor::step() {
|
|||||||
switch (instr.type) {
|
switch (instr.type) {
|
||||||
case instruction_t::NoOperation: break;
|
case instruction_t::NoOperation: break;
|
||||||
case instruction_t::PushS8: {
|
case instruction_t::PushS8: {
|
||||||
push_thing({ (struct thing_type){ thing_type::S8 } }).get<thing_type::s8>() = instr.arg.s8;
|
push_thing({ (struct thing_type){ thing_type::S8 }, { m_stackStorage } }).get<thing_type::s8>() = instr.arg.s8;
|
||||||
} break;
|
} break;
|
||||||
case instruction_t::PushU8: {
|
case instruction_t::PushU8: {
|
||||||
push_thing({ (struct thing_type){ thing_type::U8 } }).get<thing_type::u8>() = instr.arg.u8;
|
push_thing({ (struct thing_type){ thing_type::U8 }, { m_stackStorage } }).get<thing_type::u8>() = instr.arg.u8;
|
||||||
} break;
|
} break;
|
||||||
case instruction_t::PushS16: {
|
case instruction_t::PushS16: {
|
||||||
push_thing({ (struct thing_type){ thing_type::S16 } }).get<thing_type::s16>() = instr.arg.s16;
|
push_thing({ (struct thing_type){ thing_type::S16 }, { m_stackStorage } }).get<thing_type::s16>() =
|
||||||
|
instr.arg.s16;
|
||||||
} break;
|
} break;
|
||||||
case instruction_t::PushU16: {
|
case instruction_t::PushU16: {
|
||||||
push_thing({ (struct thing_type){ thing_type::U16 } }).get<thing_type::u16>() = instr.arg.u16;
|
push_thing({ (struct thing_type){ thing_type::U16 }, { m_stackStorage } }).get<thing_type::u16>() =
|
||||||
|
instr.arg.u16;
|
||||||
} break;
|
} break;
|
||||||
case instruction_t::PushS32: {
|
case instruction_t::PushS32: {
|
||||||
push_thing({ (struct thing_type){ thing_type::S32 } }).get<thing_type::s32>() = instr.arg.s8; // NOLINT
|
push_thing({ (struct thing_type){ thing_type::S32 }, { m_stackStorage } }).get<thing_type::s32>() =
|
||||||
|
instr.arg.s8; // NOLINT
|
||||||
} break;
|
} break;
|
||||||
case instruction_t::PushU32: {
|
case instruction_t::PushU32: {
|
||||||
push_thing({ (struct thing_type){ thing_type::U32 } }).get<thing_type::u32>() =
|
push_thing({ (struct thing_type){ thing_type::U32 }, { m_stackStorage } }).get<thing_type::u32>() =
|
||||||
static_cast<thing_type::u32>(instr.arg.u8);
|
static_cast<thing_type::u32>(instr.arg.u8);
|
||||||
} break;
|
} break;
|
||||||
case instruction_t::PushConstant: {
|
case instruction_t::PushConstant: {
|
||||||
auto constant = frame.mod->constant_at(instr.arg.u16);
|
auto constant = frame.mod->constant_at(instr.arg.u16);
|
||||||
switch (constant.type) {
|
switch (constant.type) {
|
||||||
case constant::S32:
|
case constant::S32:
|
||||||
push_thing({ (struct thing_type){ thing_type::S32 } }).get<thing_type::s32>() = constant.s32; // NOLINT
|
push_thing({ (struct thing_type){ thing_type::S32 }, { m_stackStorage } }).get<thing_type::s32>() =
|
||||||
|
constant.s32; // NOLINT
|
||||||
break;
|
break;
|
||||||
case constant::U32:
|
case constant::U32:
|
||||||
push_thing({ (struct thing_type){ thing_type::U32 } }).get<thing_type::u32>() = constant.u32; // NOLINT
|
push_thing({ (struct thing_type){ thing_type::U32 }, { m_stackStorage } }).get<thing_type::u32>() =
|
||||||
|
constant.u32; // NOLINT
|
||||||
break;
|
break;
|
||||||
case constant::S64:
|
case constant::S64:
|
||||||
push_thing({ (struct thing_type){ thing_type::S64 } }).get<thing_type::s64>() = constant.s64; // NOLINT
|
push_thing({ (struct thing_type){ thing_type::S64 }, { m_stackStorage } }).get<thing_type::s64>() =
|
||||||
|
constant.s64; // NOLINT
|
||||||
break;
|
break;
|
||||||
case constant::U64:
|
case constant::U64:
|
||||||
push_thing({ (struct thing_type){ thing_type::U64 } }).get<thing_type::u64>() = constant.u64; // NOLINT
|
push_thing({ (struct thing_type){ thing_type::U64 }, { m_stackStorage } }).get<thing_type::u64>() =
|
||||||
|
constant.u64; // NOLINT
|
||||||
break;
|
break;
|
||||||
case constant::String: throw std::runtime_error("unimplemented");
|
case constant::String: throw std::runtime_error("unimplemented");
|
||||||
default: throw std::runtime_error("invalid constant");
|
default: throw std::runtime_error("invalid constant");
|
||||||
@@ -246,7 +257,7 @@ void executor::step() {
|
|||||||
if (type.type != thing_type::Array || type.value.array.type == nullptr || type.value.array.type == &type)
|
if (type.type != thing_type::Array || type.value.array.type == nullptr || type.value.array.type == &type)
|
||||||
throw std::runtime_error("invalid array type");
|
throw std::runtime_error("invalid array type");
|
||||||
|
|
||||||
auto& array = push_thing({ type });
|
auto& array = push_thing({ type, { m_stackStorage } });
|
||||||
|
|
||||||
if (type.value.array.size == 0) {
|
if (type.value.array.size == 0) {
|
||||||
auto sizeThing = pop_thing();
|
auto sizeThing = pop_thing();
|
||||||
@@ -281,7 +292,7 @@ void executor::step() {
|
|||||||
push_thing(top_thing());
|
push_thing(top_thing());
|
||||||
} break;
|
} break;
|
||||||
case instruction_t::Reference: {
|
case instruction_t::Reference: {
|
||||||
push_thing(thing<>::make_reference(pop_thing()));
|
push_thing(stack_thing::make_reference(pop_thing(), { m_stackStorage }));
|
||||||
} break;
|
} break;
|
||||||
case instruction_t::Add: {
|
case instruction_t::Add: {
|
||||||
auto rhs = pop_thing();
|
auto rhs = pop_thing();
|
||||||
@@ -340,12 +351,13 @@ void executor::step() {
|
|||||||
} break;
|
} break;
|
||||||
case instruction_t::Pointerof: {
|
case instruction_t::Pointerof: {
|
||||||
auto thing = pop_thing();
|
auto thing = pop_thing();
|
||||||
push_thing({ (struct thing_type){ thing_type::Ptr, m_context->tt_store().at(thing.type().id) } }).get<void*>() =
|
push_thing(
|
||||||
thing.raw();
|
{ (struct thing_type){ thing_type::Ptr, m_context->tt_store().at(thing.type().id) }, { m_stackStorage } })
|
||||||
|
.get<void*>() = thing.raw();
|
||||||
} break;
|
} break;
|
||||||
case instruction_t::Sizeof: {
|
case instruction_t::Sizeof: {
|
||||||
auto thing = pop_thing();
|
auto thing = pop_thing();
|
||||||
auto& size = push_thing({ (struct thing_type){ thing_type::U64 } });
|
auto& size = push_thing({ (struct thing_type){ thing_type::U64 }, { m_stackStorage } });
|
||||||
switch (thing.type().type) {
|
switch (thing.type().type) {
|
||||||
case thing_type::S8:
|
case thing_type::S8:
|
||||||
case thing_type::S16:
|
case thing_type::S16:
|
||||||
@@ -369,19 +381,20 @@ void executor::step() {
|
|||||||
} break;
|
} break;
|
||||||
case instruction_t::Lengthof: {
|
case instruction_t::Lengthof: {
|
||||||
auto thing = pop_thing();
|
auto thing = pop_thing();
|
||||||
push_thing({ (struct thing_type){ thing_type::U64 } }).get<thing_type::u64>() = thing.length();
|
push_thing({ (struct thing_type){ thing_type::U64 }, { m_stackStorage } }).get<thing_type::u64>() =
|
||||||
|
thing.length();
|
||||||
} break;
|
} break;
|
||||||
case instruction_t::Load: {
|
case instruction_t::Load: {
|
||||||
push_thing(std::move(thing<>::make_reference(load_thing(instr.arg.u16))));
|
push_thing(std::move(stack_thing::make_reference(load_thing(instr.arg.u16), { m_stackStorage })));
|
||||||
} break;
|
} break;
|
||||||
case instruction_t::Store: {
|
case instruction_t::Store: {
|
||||||
store_thing(instr.arg.u16, std::move(pop_thing()));
|
store_thing(instr.arg.u16, std::move(pop_thing()));
|
||||||
} break;
|
} break;
|
||||||
case instruction_t::LoadGlobal: {
|
case instruction_t::LoadGlobal: {
|
||||||
push_thing(thing<>::make_reference(frame.mod->load_global_variable(instr.arg.u16)));
|
push_thing(stack_thing::make_reference(frame.mod->load_global_variable(instr.arg.u16), { m_stackStorage }));
|
||||||
} break;
|
} break;
|
||||||
case instruction_t::StoreGlobal: {
|
case instruction_t::StoreGlobal: {
|
||||||
frame.mod->store_global_variable(instr.arg.u16, std::move(pop_thing()));
|
frame.mod->store_global_variable(instr.arg.u16, pop_thing());
|
||||||
} break;
|
} break;
|
||||||
case instruction_t::Call: {
|
case instruction_t::Call: {
|
||||||
push_frame(frame.mod, *frame.mod->function_at(instr.arg.u16));
|
push_frame(frame.mod, *frame.mod->function_at(instr.arg.u16));
|
||||||
|
|||||||
Reference in New Issue
Block a user