diff --git a/furvm/include/furvm/function.hpp b/furvm/include/furvm/function.hpp index 0fe4165..879b81d 100644 --- a/furvm/include/furvm/function.hpp +++ b/furvm/include/furvm/function.hpp @@ -14,7 +14,7 @@ enum class function_t : std::uint8_t { Native, /**< A native function implemented through furvm API. */ }; -using native_function = std::function; +using native_function = std::function; class function { private: diff --git a/furvm/include/furvm/instruction.hpp b/furvm/include/furvm/instruction.hpp index a73a810..5ec3714 100644 --- a/furvm/include/furvm/instruction.hpp +++ b/furvm/include/furvm/instruction.hpp @@ -65,6 +65,13 @@ enum class instruction_t : byte { */ Mod, + /** + * @brief Calls a function. + * + * Calls a function denoted by next two bytes in little-endian from current frame's module. + */ + Call, + /** * @brief Pops the current call frame. */ diff --git a/furvm/include/furvm/module.hpp b/furvm/include/furvm/module.hpp index 4b557ad..adc4957 100644 --- a/furvm/include/furvm/module.hpp +++ b/furvm/include/furvm/module.hpp @@ -51,6 +51,14 @@ public: * @return The byte. */ constexpr byte byte(std::size_t offset) const { return m_bytecode.at(offset); } +public: + /** + * @brief Returns a function from this module. + * + * @param id Id of the function. + * @return The function. + */ + constexpr const function_p& function_at(function_handle id) const { return m_functions.at(id); } private: module_handle m_id; bytecode_t m_bytecode; diff --git a/furvm/src/executor.cpp b/furvm/src/executor.cpp index e694d59..2adf9f6 100644 --- a/furvm/src/executor.cpp +++ b/furvm/src/executor.cpp @@ -109,6 +109,17 @@ void executor::step() { auto lhs = pop_thing(); push_thing(lhs % rhs); } break; + case instruction_t::Call: { + function_handle funcId = static_cast(frame.mod->byte(frame.position)) | + (static_cast(frame.mod->byte(frame.position + 1)) << 8); + frame.position += 2; + + const function_p& function = frame.mod->function_at(funcId); + switch (function->type()) { + case function_t::Normal: push_frame(function); break; + case function_t::Native: function->native()(*this); break; + } + } break; case instruction_t::Return: { pop_frame(); if (m_frames.empty()) m_flags = m_flags | executor_flags::Done; diff --git a/furvm/src/main.cpp b/furvm/src/main.cpp index 7ae9113..22ad1c1 100644 --- a/furvm/src/main.cpp +++ b/furvm/src/main.cpp @@ -11,17 +11,19 @@ #include #include -static constexpr std::array s_bytecode = { +static constexpr std::array s_bytecode = { furvm::byte(furvm::instruction_t::PushB2I), 67, furvm::byte(furvm::instruction_t::Clone), furvm::byte(furvm::instruction_t::Add), - furvm::byte(furvm::instruction_t::Drop), + furvm::byte(furvm::instruction_t::Call), + 1, + 0, furvm::byte(furvm::instruction_t::Return), }; -void print(const furvm::executor_p& exec) { - std::cout << exec->pop_thing()->int32() << '\n'; +void print(furvm::executor& exec) { + std::cout << exec.pop_thing()->int32() << '\n'; } int main(void) {