From 073cbb461801457198eea58cee678eee81ab843b Mon Sep 17 00:00:00 2001 From: bog Date: Tue, 19 Sep 2023 06:38:14 +0200 Subject: [PATCH] ADD: vardecl. --- examples/vardecl.zn | 7 +++++++ libstd/macro.cpp | 15 +++++++++++++++ libstd/macro.hpp | 5 +++++ libstd/std.cpp | 1 + src/Compiler.cpp | 4 ++-- src/StaticPass.cpp | 25 ++++++++++++++++++++++++- src/StaticPass.hpp | 1 + src/SymTable.cpp | 40 ++++++++++++++++++++++++++++++++++++++-- src/SymTable.hpp | 9 ++++++++- src/VM.cpp | 44 +++++++++++++++++--------------------------- src/VM.hpp | 7 ++----- src/types.hpp | 9 +++++---- 12 files changed, 125 insertions(+), 42 deletions(-) create mode 100644 examples/vardecl.zn diff --git a/examples/vardecl.zn b/examples/vardecl.zn new file mode 100644 index 0000000..e160255 --- /dev/null +++ b/examples/vardecl.zn @@ -0,0 +1,7 @@ +(assert-fail a) +($ a 34) +(assert= 34 a) + +($ b ($ c 9)) +(assert= 9 b) +(assert= 9 c) \ No newline at end of file diff --git a/libstd/macro.cpp b/libstd/macro.cpp index cafc5e4..234cd7f 100644 --- a/libstd/macro.cpp +++ b/libstd/macro.cpp @@ -22,3 +22,18 @@ void assert_fail(Node const& node, (TYPE_NIL, node.loc(), 0)); program.append(OPCODE_LOAD_CONST, addr); } + +void declare(Node const& node, + Compiler& compiler, + Program& program, + SymTable& sym) +{ + std::string ident = node.child_at(1)->repr(); + compiler.compile(*node.child_at(2), program); + auto entry = sym.find_any(ident); + assert(entry); + size_t addr = sym.gen_addr(); + + sym.declare(ident, addr); + program.append(OPCODE_STORE_LOCAL, addr); +} diff --git a/libstd/macro.hpp b/libstd/macro.hpp index e630c0c..1ba097e 100644 --- a/libstd/macro.hpp +++ b/libstd/macro.hpp @@ -8,4 +8,9 @@ void assert_fail(Node const& node, Program& program, SymTable& sym); +void declare(Node const& node, + Compiler& compiler, + Program& program, + SymTable& sym); + #endif diff --git a/libstd/std.cpp b/libstd/std.cpp index ddbd97d..8db3752 100644 --- a/libstd/std.cpp +++ b/libstd/std.cpp @@ -20,4 +20,5 @@ extern "C" void lib(Zarn& zarn) assert_eq); zarn.register_macro("assert-fail", assert_fail); + zarn.register_macro("$", declare); } diff --git a/src/Compiler.cpp b/src/Compiler.cpp index c8dd27e..64f66ed 100644 --- a/src/Compiler.cpp +++ b/src/Compiler.cpp @@ -100,13 +100,13 @@ namespace zn { auto ref = std::make_shared(TYPE_REF, node.loc(), - (int) sym->addr); + (int) *sym->addr); size_t val = program.add_constant(ref); program.append(OPCODE_LOAD_CONST, val); } else { - program.append(OPCODE_LOAD_LOCAL, sym->addr); + program.append(OPCODE_LOAD_LOCAL, *sym->addr); } } break; diff --git a/src/StaticPass.cpp b/src/StaticPass.cpp index 93ca936..50a04c1 100644 --- a/src/StaticPass.cpp +++ b/src/StaticPass.cpp @@ -27,7 +27,17 @@ namespace zn case NODE_CALL: { std::string ident = node.child_at(0)->repr(); - auto sym = m_sym.find(ident); + auto sym = m_sym.find_any(ident); + + if (ident == "$") + { + std::string varname = node.child_at(1)->repr(); + auto vartype = execute(*node.child_at(2)); + //int index = m_sym.gen_addr(); + m_sym.prepare(varname, *vartype.type); + + return vartype; + } if (sym == std::nullopt) { @@ -75,6 +85,19 @@ namespace zn return proto->get_ret(); } break; + case NODE_IDENT: { + std::string ident = node.repr(); + auto sym = m_sym.find_any(ident); + + if (sym == std::nullopt) + { + std::stringstream ss; + ss << "undeclared var '" << ident << "'"; + m_logger.log(LOG_ERROR, node.loc(), ss.str()); + } + return TypeSlot {sym->type}; + } break; + case NODE_INT: { return TypeSlot {TYPE_INT}; } break; diff --git a/src/StaticPass.hpp b/src/StaticPass.hpp index 1472b19..7ac70aa 100644 --- a/src/StaticPass.hpp +++ b/src/StaticPass.hpp @@ -17,6 +17,7 @@ namespace zn virtual ~StaticPass(); TypeSlot execute(Node const& node); + private: Logger& m_logger; SymTable& m_sym; diff --git a/src/SymTable.cpp b/src/SymTable.cpp index 170bad0..ef003de 100644 --- a/src/SymTable.cpp +++ b/src/SymTable.cpp @@ -10,19 +10,48 @@ namespace zn { } + void SymTable::prepare(std::string const& name, Type type) + { + m_syms.push_back(Sym {name, std::nullopt, type}); + } + void SymTable::declare(std::string const& name, size_t addr) { - m_syms.push_back(Sym {name, addr}); + auto itr = std::find_if(std::begin(m_syms), + std::end(m_syms), + [name](auto const& sym){ + return sym.name == name; + }); + + if (itr == std::end(m_syms)) + { + abort(); + } + + itr->addr = addr; } void SymTable::declare_function(std::string const& name, size_t addr, std::shared_ptr prototype) { - m_syms.push_back(Sym {name, addr, prototype}); + m_syms.push_back(Sym {name, addr, TYPE_FUNCTION, prototype}); } std::optional SymTable::find(std::string const& name) + { + for (size_t i=0; i SymTable::find_any(std::string const& name) { for (size_t i=0; i addr; + Type type; std::shared_ptr prototype = nullptr; }; @@ -18,6 +19,9 @@ namespace zn explicit SymTable(); virtual ~SymTable(); + size_t size() const { return m_syms.size(); } + + void prepare(std::string const& name, Type type); void declare(std::string const& name, size_t addr); void declare_function(std::string const& name, @@ -25,6 +29,9 @@ namespace zn std::shared_ptr prototype); std::optional find(std::string const& name); + std::optional find_any(std::string const& name); + + size_t gen_addr(); private: std::vector m_syms; diff --git a/src/VM.cpp b/src/VM.cpp index a6c92f4..703ddc4 100644 --- a/src/VM.cpp +++ b/src/VM.cpp @@ -35,8 +35,14 @@ namespace zn } break; case OPCODE_LOAD_LOCAL: { - auto constant = frame().locals[to_vm_addr(param)]; - push(program.add_constant(constant)); + auto constant = load_local(param); + size_t addr = program.add_constant(constant); + push(addr); + m_pc++; + } break; + + case OPCODE_STORE_LOCAL: { + store_local(param, frame().program.constant(top())); m_pc++; } break; @@ -97,17 +103,14 @@ namespace zn size_t VM::store_local(int index, std::shared_ptr constant) { - frame().locals.push_back(constant); + frame().locals[index] = constant; size_t addr = frame().locals.size() - 1; - m_addr_mapping[index] = addr; return addr; } std::shared_ptr VM::load_local(int index) const { - size_t addr = to_vm_addr(index); - assert(addr < m_frames.back().locals.size()); - return m_frames.back().locals[addr]; + return m_frames.back().locals.at(index); } size_t VM::store_global(global_var_t var) @@ -116,26 +119,6 @@ namespace zn return m_globals.size() - 1; } - size_t VM::to_vm_addr(int user_addr) const - { - return m_addr_mapping.at(user_addr); - } - - int VM::to_user_addr(size_t vm_addr) const - { - for (auto const& entry: m_addr_mapping) - { - if (entry.second == vm_addr) - { - return entry.first; - } - } - - std::cerr << "cannot find user addr of '" - << vm_addr << "'" << std::endl; - abort(); - } - Frame& VM::frame() { return m_frames.back(); @@ -153,4 +136,11 @@ namespace zn m_stack.pop_back(); return value; } + + int VM::top() + { + assert(m_stack.size() > 0); + int value = m_stack.back(); + return value; + } } diff --git a/src/VM.hpp b/src/VM.hpp index 54b64d6..ca87855 100644 --- a/src/VM.hpp +++ b/src/VM.hpp @@ -9,7 +9,7 @@ namespace zn { struct Frame { Program& program; - std::vector> locals; + std::unordered_map> locals; }; using global_var_t = std::variant>; @@ -30,19 +30,16 @@ namespace zn size_t store_global(global_var_t var); - size_t to_vm_addr(int user_addr) const; - int to_user_addr(size_t vm_addr) const; - private: std::vector m_frames; std::vector m_stack; std::vector m_globals; - std::unordered_map m_addr_mapping; size_t m_pc = 0; Frame& frame(); void push(int value); int pop(); + int top(); }; } diff --git a/src/types.hpp b/src/types.hpp index 1039bdf..02e06c6 100644 --- a/src/types.hpp +++ b/src/types.hpp @@ -3,10 +3,11 @@ #include "common.hpp" -#define TYPES(G) \ - G(TYPE_NIL), \ - G(TYPE_INT), \ - G(TYPE_REF) +#define TYPES(G) \ + G(TYPE_NIL), \ + G(TYPE_INT), \ + G(TYPE_REF), \ + G(TYPE_FUNCTION) namespace zn {