diff --git a/runtime/main.cpp b/runtime/main.cpp index 51c3ac3..1c1ee44 100644 --- a/runtime/main.cpp +++ b/runtime/main.cpp @@ -63,7 +63,7 @@ auto compile_asm(const std::vector& lines) -> std::vector break; } case AsmLineType::Loc: { - locs.insert_or_assign(std::get(line.value).value, ip + 1); + locs.insert_or_assign(std::get(line.value).value, ip); break; } case AsmLineType::Ref: { @@ -75,9 +75,15 @@ auto compile_asm(const std::vector& lines) -> std::vector } } for (size_t i = 0; i < output.size(); ++i) { - if (refs.contains(i)) { - output.at(i) = static_cast(locs.at(refs.at(i))); + if (!refs.contains(i)) { + continue; } + if (!locs.contains(refs.at(i))) { + std::cerr << std::format( + "error: label \"{}\" used at {} not defined\n", refs.at(i), i); + continue; + } + output.at(i) = static_cast(locs.at(refs.at(i))); } return output; } @@ -92,19 +98,23 @@ int main() // + a b // } // - // let result = 0; - // let i = 0; - // loop { - // if i >= 10 { - // break; + // fn main() { + // let result = 0; + // let i = 0; + // loop { + // if i >= 10 { + // break; + // } + // result = add(result, 5); + // i = + i 1; // } - // result = add(result, 5); + // result // } auto program_asm = std::vector { // clang-format off SourceMap, 0, 0, 0, PushPtr, R("main"), - Pop, + Call, 0, PushPtr, R("_exit"), Jump, Pop, @@ -112,15 +122,17 @@ int main() SourceMap, 19, 2, 5, Add, Return, + L("main"), SourceMap, 28, 5, 1, PushInt, 0, + PushInt, 0, SourceMap, 44, 6, 1, PushInt, 0, SourceMap, 55, 7, 1, - L("1"), + L("0"), SourceMap, 66, 8, 5, - LoadLocal, 1, - PushInt, 0, + LoadLocal, 2, + PushInt, 10, LessThan, Not, PushPtr, R("1"), @@ -128,22 +140,25 @@ int main() SourceMap, 87, 9, 9, PushPtr, R("2"), Jump, + L("1"), SourceMap, 104, 11, 5, - LoadLocal, 0, + LoadLocal, 1, PushInt, 5, PushPtr, R("add"), Call, 2, - StoreLocal, 0, + StoreLocal, 1, SourceMap, 133, 12, 5, - LoadLocal, 1, + LoadLocal, 2, PushInt, 1, Add, - StoreLocal, 1, + StoreLocal, 2, PushPtr, R("0"), Jump, L("2"), + LoadLocal, 1, + StoreLocal, 0, + Pop, Pop, - PushNull, Return, L("_exit"), SourceMap, 147, 15, 1 @@ -156,6 +171,5 @@ int main() .code_coverage = true, }); vm.run_until_done(); - - vm.print_stack(); + std::cout << std::format("done\n{}\n", vm.stack_repr_string()); } diff --git a/runtime/value.hpp b/runtime/value.hpp index 59cf55c..bbb28db 100644 --- a/runtime/value.hpp +++ b/runtime/value.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include #include @@ -50,6 +51,15 @@ struct Ptr { uint32_t value; }; +// clang-format off +template struct ValueTypeToType { }; +template <> struct ValueTypeToType { using Type = Null; }; +template <> struct ValueTypeToType { using Type = Int; }; +template <> struct ValueTypeToType { using Type = Bool; }; +template <> struct ValueTypeToType { using Type = String; }; +template <> struct ValueTypeToType { using Type = Ptr; }; +// clang-format on + class Value { public: Value(Null&& value) @@ -80,120 +90,42 @@ public: inline auto type() const -> ValueType { return m_type; }; - inline auto as_null() -> Null& + template inline auto as() -> ValueTypeToType::Type& { - // try { - return std::get(value); + return std::get::Type>(value); } catch (const std::bad_variant_access& ex) { - std::cout << std::format("tried to unwrap {} as Null\n", - value_type_to_string(this->m_type)); - throw; - } - } - inline auto as_null() const -> const Null& - { - // - try { - return std::get(value); - } catch (const std::bad_variant_access& ex) { - std::cout << std::format("tried to unwrap {} as Null\n", - value_type_to_string(this->m_type)); - throw; + std::cerr << std::format("error: tried to unwrap {} as {}\n", + value_type_to_string(this->m_type), value_type_to_string(VT)); + std::exit(1); } } - inline auto as_int() -> Int& + template + inline auto as() const -> const ValueTypeToType::Type& { - // try { - return std::get(value); + return std::get::Type>(value); } catch (const std::bad_variant_access& ex) { - std::cout << std::format("tried to unwrap {} as Int\n", - value_type_to_string(this->m_type)); - throw; - } - } - inline auto as_int() const -> const Int& - { - // - try { - return std::get(value); - } catch (const std::bad_variant_access& ex) { - std::cout << std::format("tried to unwrap {} as Int\n", - value_type_to_string(this->m_type)); - throw; + std::cerr << std::format("error: tried to unwrap {} as {}\n", + value_type_to_string(this->m_type), value_type_to_string(VT)); + std::exit(1); } } - inline auto as_bool() -> Bool& - { - // - try { - return std::get(value); - } catch (const std::bad_variant_access& ex) { - std::cout << std::format("tried to unwrap {} as Bool\n", - value_type_to_string(this->m_type)); - throw; - } - } - inline auto as_bool() const -> const Bool& - { - // - try { - return std::get(value); - } catch (const std::bad_variant_access& ex) { - std::cout << std::format("tried to unwrap {} as Bool\n", - value_type_to_string(this->m_type)); - throw; - } - } + // clang-format off + inline auto as_null() -> Null& { return as(); } + inline auto as_int() -> Int& { return as(); } + inline auto as_bool() -> Bool& { return as(); } + inline auto as_string() -> String& { return as(); } + inline auto as_ptr() -> Ptr& { return as(); } - inline auto as_string() -> String& - { - // - try { - return std::get(value); - } catch (const std::bad_variant_access& ex) { - std::cout << std::format("tried to unwrap {} as String\n", - value_type_to_string(this->m_type)); - throw; - } - } - inline auto as_string() const -> const String& - { - // - try { - return std::get(value); - } catch (const std::bad_variant_access& ex) { - std::cout << std::format("tried to unwrap {} as String\n", - value_type_to_string(this->m_type)); - throw; - } - } - - inline auto as_ptr() -> Ptr& - { - // - try { - return std::get(value); - } catch (const std::bad_variant_access& ex) { - std::cout << std::format("tried to unwrap {} as Ptr\n", - value_type_to_string(this->m_type)); - throw; - } - } - inline auto as_ptr() const -> const Ptr& - { - // - try { - return std::get(value); - } catch (const std::bad_variant_access& ex) { - std::cout << std::format("tried to unwrap {} as Ptr\n", - value_type_to_string(this->m_type)); - throw; - } - } + inline auto as_null() const -> const Null& { return as(); } + inline auto as_int() const -> const Int& { return as(); } + inline auto as_bool() const -> const Bool& { return as(); } + inline auto as_string() const -> const String& { return as(); } + inline auto as_ptr() const -> const Ptr& { return as(); } + // clang-format on inline auto to_string() const -> std::string { diff --git a/runtime/vm.cpp b/runtime/vm.cpp index 01ed15d..476339f 100644 --- a/runtime/vm.cpp +++ b/runtime/vm.cpp @@ -4,11 +4,70 @@ #include #include #include +#include #include #include using namespace sliger; +inline auto maybe_op_to_string(uint32_t value) -> std::string +{ + switch (static_cast(value)) { + case Op::Nop: + return "Nop"; + case Op::PushNull: + return "PushNull"; + case Op::PushInt: + return "PushInt"; + case Op::PushBool: + return "PushBool"; + case Op::PushString: + return "PushString"; + case Op::PushPtr: + return "PushPtr"; + case Op::Pop: + return "Pop"; + case Op::LoadLocal: + return "LoadLocal"; + case Op::StoreLocal: + return "StoreLocal"; + case Op::Call: + return "Call"; + case Op::Return: + return "Return"; + case Op::Jump: + return "Jump"; + case Op::JumpIfFalse: + return "JumpIfFalse"; + case Op::Add: + return "Add"; + case Op::Subtract: + return "Subtract"; + case Op::Multiply: + return "Multiply"; + case Op::Divide: + return "Divide"; + case Op::Remainder: + return "Remainder"; + case Op::Equal: + return "Equal"; + case Op::LessThan: + return "LessThan"; + case Op::And: + return "And"; + case Op::Or: + return "Or"; + case Op::Xor: + return "Xor"; + case Op::Not: + return "Not"; + case Op::SourceMap: + return "SourceMap"; + default: + return std::to_string(value); + } +} + void VM::run_until_done() { while (!done()) { @@ -19,15 +78,15 @@ void VM::run_until_done() void VM::run_n_instructions(size_t amount) { for (size_t i = 0; !done() and i < amount; ++i) { + run_instruction(); } } void VM::run_instruction() { - std::cout << "stack:\n"; - this->print_stack(); - std::cout << std::format("pc = {}\n", this->pc); + std::cout << std::format(" {:>4}: {:<12}{}\n", this->pc, + maybe_op_to_string(this->program[this->pc]), stack_repr_string()); auto op = eat_op(); switch (op) { case Op::Nop: diff --git a/runtime/vm.hpp b/runtime/vm.hpp index 86964ba..a225cec 100644 --- a/runtime/vm.hpp +++ b/runtime/vm.hpp @@ -156,11 +156,18 @@ public: return this->stack; } - inline void print_stack() const + inline auto stack_repr_string() const -> std::string { - for (const auto& value : view_stack()) { - std::cout << std::format(" {}\n", value.to_repr_string()); + auto result = std::string(); + result += "→"; + const auto& stack = view_stack(); + for (size_t i = 0; i < stack.size(); ++i) { + if (i != 0) { + result += " "; + } + result += stack[stack.size() - i - 1].to_repr_string(); } + return result; } private: