@@ -5,6 +5,7 @@
|
|||||||
#include "furvm/module.hpp" // IWYU pragma: keep
|
#include "furvm/module.hpp" // IWYU pragma: keep
|
||||||
#include "furvm/thing.hpp" // IWYU pragma: keep
|
#include "furvm/thing.hpp" // IWYU pragma: keep
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -40,6 +41,7 @@ public:
|
|||||||
std::size_t position; /**< Cursor to a current instruction in the bytecode. */
|
std::size_t position; /**< Cursor to a current instruction in the bytecode. */
|
||||||
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. */
|
||||||
std::vector<thing_h> variables; /**< Frame variables. */
|
std::vector<thing_h> variables; /**< Frame variables. */
|
||||||
};
|
};
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "furvm/handle.hpp" // IWYU pragma: keep
|
#include "furvm/handle.hpp" // IWYU pragma: keep
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <optional>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
@@ -38,6 +39,7 @@ struct import_function {
|
|||||||
*/
|
*/
|
||||||
struct function_sig {
|
struct function_sig {
|
||||||
std::vector<mod_type_h> params;
|
std::vector<mod_type_h> params;
|
||||||
|
std::optional<mod_type_h> returnType;
|
||||||
|
|
||||||
bool operator==(const function_sig& rhs) const { return params == rhs.params; }
|
bool operator==(const function_sig& rhs) const { return params == rhs.params; }
|
||||||
|
|
||||||
|
|||||||
+12
-5
@@ -59,14 +59,19 @@ void executor::push_frame(const mod_h& mod, function function) {
|
|||||||
args.push_back(std::move(arg));
|
args.push_back(std::move(arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct thing_type* returnType = nullptr;
|
||||||
|
if (function.signature().returnType.has_value())
|
||||||
|
returnType = thing_type(mod, *function.signature().returnType.value()); // NOLINT
|
||||||
|
|
||||||
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(), std::move(args) });
|
m_frames.emplace(
|
||||||
|
(struct executor::frame){ mod, function.position(), m_stack.size(), returnType, std::move(args) });
|
||||||
} break;
|
} break;
|
||||||
case function_t::Native: {
|
case function_t::Native: {
|
||||||
m_frames.emplace((struct executor::frame){ mod, 0, m_stack.size(), std::move(args) });
|
m_frames.emplace((struct executor::frame){ mod, 0, m_stack.size(), returnType, std::move(args) });
|
||||||
modInst->get_native_function(function.native())(*this);
|
modInst->get_native_function(function.native())(*this);
|
||||||
m_frames.pop();
|
pop_frame();
|
||||||
} break;
|
} break;
|
||||||
default: throw std::runtime_error("unexpected function type");
|
default: throw std::runtime_error("unexpected function type");
|
||||||
}
|
}
|
||||||
@@ -76,6 +81,10 @@ 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();
|
||||||
|
thing_h returnValue;
|
||||||
|
if (frame.returnType != nullptr) returnValue = pop_thing();
|
||||||
|
if (m_stack.size() != frame.stackBase) throw std::runtime_error("unexhausted stack");
|
||||||
|
if (frame.returnType != nullptr) push_thing(std::move(returnValue));
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,8 +155,6 @@ void executor::step() {
|
|||||||
std::int64_t size = sizeThing->integer();
|
std::int64_t size = sizeThing->integer();
|
||||||
array->resize(size);
|
array->resize(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
push_thing(std::move(array));
|
|
||||||
} break;
|
} break;
|
||||||
case instruction_t::Get: {
|
case instruction_t::Get: {
|
||||||
auto index = pop_thing();
|
auto index = pop_thing();
|
||||||
|
|||||||
+5
-2
@@ -63,6 +63,7 @@ int main(int argc, char** argv) {
|
|||||||
static_cast<furvm::byte>(furvm::instruction_t::Call),
|
static_cast<furvm::byte>(furvm::instruction_t::Call),
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
|
static_cast<furvm::byte>(furvm::instruction_t::Drop),
|
||||||
static_cast<furvm::byte>(furvm::instruction_t::Return),
|
static_cast<furvm::byte>(furvm::instruction_t::Return),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -71,11 +72,13 @@ int main(int argc, char** argv) {
|
|||||||
auto arrayType = mod->emplace_type(charType.id(), 10);
|
auto arrayType = mod->emplace_type(charType.id(), 10);
|
||||||
auto u64Type = mod->emplace_type(furvm::mod_type::U64);
|
auto u64Type = mod->emplace_type(furvm::mod_type::U64);
|
||||||
auto mainFunc = mod->emplace_function("main", furvm::function_sig{}, 0);
|
auto mainFunc = mod->emplace_function("main", furvm::function_sig{}, 0);
|
||||||
mod->emplace_function(furvm::function_sig{ { u64Type } }, "print").dispatch();
|
mod->emplace_function(furvm::function_sig{ { u64Type }, u64Type }, "print").dispatch();
|
||||||
#endif
|
#endif
|
||||||
mod->set_native_function("print", [](furvm::executor& executor) {
|
mod->set_native_function("print", [](furvm::executor& executor) {
|
||||||
print_thing(*executor.load_thing(0));
|
auto arg = std::move(*executor.load_thing(0));
|
||||||
|
print_thing(arg);
|
||||||
std::cout << '\n';
|
std::cout << '\n';
|
||||||
|
executor.push_thing(std::move(arg));
|
||||||
});
|
});
|
||||||
|
|
||||||
furvm::executor_h executor = context->emplace_executor(context);
|
furvm::executor_h executor = context->emplace_executor(context);
|
||||||
|
|||||||
Reference in New Issue
Block a user