#ifndef fk_VM_HPP #define fk_VM_HPP #include "commons.hpp" #include "Program.hpp" #include "NativeFunction.hpp" #include "Lambda.hpp" namespace fk { using global_t = std::variant, std::shared_ptr >; struct Frame { std::shared_ptr program; addr_t ret_addr; size_t stack_sz; std::unordered_map> locals; }; class Module; class VM { public: explicit VM(Module& mod); virtual ~VM(); Frame& frame() { return m_frames.back(); } void mount(std::shared_ptr program); void run(); std::shared_ptr call(std::shared_ptr lambda, size_t ref, std::vector> const& args, Loc const& loc); global_t load_global(addr_t addr) const; void store_global(addr_t addr, global_t value); size_t store_global(global_t value); std::shared_ptr load_local(addr_t addr); void store_local(addr_t addr, std::shared_ptr constant); std::string string() const; void push(addr_t addr); addr_t top(); addr_t pop(); std::shared_ptr run_lambda(VM const& parent, std::shared_ptr lambda, std::vector> args, size_t ref, Loc const& loc); private: Module& m_mod; addr_t m_pc = 0; std::vector m_frames; std::vector m_stack; std::unordered_map m_globals; std::shared_ptr m_return_const; }; } #endif