diff --git a/furvm/include/furvm/executor.hpp b/furvm/include/furvm/executor.hpp index 8bf43c6..5f82db3 100644 --- a/furvm/include/furvm/executor.hpp +++ b/furvm/include/furvm/executor.hpp @@ -5,6 +5,7 @@ #include "furvm/module.hpp" // IWYU pragma: keep #include "furvm/thing.hpp" // IWYU pragma: keep +#include #include #include #include @@ -40,7 +41,8 @@ public: 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::vector variables; /**< Frame variables. */ + thing_type* returnType; /**< Return type. */ + std::vector variables; /**< Frame variables. */ }; public: /** diff --git a/furvm/include/furvm/function.hpp b/furvm/include/furvm/function.hpp index 7aef9e0..8177cc1 100644 --- a/furvm/include/furvm/function.hpp +++ b/furvm/include/furvm/function.hpp @@ -6,6 +6,7 @@ #include "furvm/handle.hpp" // IWYU pragma: keep #include +#include #include #include #include @@ -37,7 +38,8 @@ struct import_function { * @brief Function signature. */ struct function_sig { - std::vector params; + std::vector params; + std::optional returnType; bool operator==(const function_sig& rhs) const { return params == rhs.params; } diff --git a/furvm/src/executor.cpp b/furvm/src/executor.cpp index 4c1c6b4..ff8e313 100644 --- a/furvm/src/executor.cpp +++ b/furvm/src/executor.cpp @@ -59,14 +59,19 @@ void executor::push_frame(const mod_h& mod, function function) { 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()) { 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; 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); - m_frames.pop(); + pop_frame(); } break; 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(); struct executor::frame frame = m_frames.top(); 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; } @@ -146,8 +155,6 @@ void executor::step() { std::int64_t size = sizeThing->integer(); array->resize(size); } - - push_thing(std::move(array)); } break; case instruction_t::Get: { auto index = pop_thing(); diff --git a/furvm/src/main.cpp b/furvm/src/main.cpp index 596c45b..d884881 100644 --- a/furvm/src/main.cpp +++ b/furvm/src/main.cpp @@ -63,6 +63,7 @@ int main(int argc, char** argv) { static_cast(furvm::instruction_t::Call), 1, 0, + static_cast(furvm::instruction_t::Drop), static_cast(furvm::instruction_t::Return), }; @@ -71,11 +72,13 @@ int main(int argc, char** argv) { auto arrayType = mod->emplace_type(charType.id(), 10); auto u64Type = mod->emplace_type(furvm::mod_type::U64); 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 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'; + executor.push_thing(std::move(arg)); }); furvm::executor_h executor = context->emplace_executor(context);