diff --git a/examples/block.zn b/examples/block.zn new file mode 100644 index 0000000..43a4cc0 --- /dev/null +++ b/examples/block.zn @@ -0,0 +1,20 @@ +($ a 2) +(assert= 2 a) + +(: + ($ a 9) + (assert= 9 a) + + (: + ($ a 42) + (assert= 42 a) + ) + + (assert= 9 a) +) + +(assert= 2 a) + +(:($ b 43)) + +(assert-fail b) \ No newline at end of file diff --git a/examples/vardecl.zn b/examples/vardecl.zn index efc0dd0..1f4bbbf 100644 --- a/examples/vardecl.zn +++ b/examples/vardecl.zn @@ -5,4 +5,4 @@ ($ b ($ c 9)) (assert= 9 b) -(assert= 9 c) \ No newline at end of file +(assert= 9 c) diff --git a/libstd/macro.cpp b/libstd/macro.cpp index c7c30ac..0e788f1 100644 --- a/libstd/macro.cpp +++ b/libstd/macro.cpp @@ -6,6 +6,7 @@ void assert_fail(Node const& node, Module& mod) { mod.static_pass().execute(*node.child_at(1)); mod.compiler().compile(*node.child_at(1), mod.program()); + Loc loc = node.loc(); std::cerr << loc.file_path().string() << ":" << loc.line(); @@ -29,6 +30,25 @@ void declare(Node const& node, Module &mod) assert(entry); size_t addr = mod.sym().gen_addr(); - mod.sym().declare(ident, addr); + mod.sym().declare(ident, addr, entry->scope); mod.program().append(OPCODE_STORE_LOCAL, addr); } + +void block(Node const& node, Module& mod) +{ + mod.sym().enter_scope(); + + for (size_t i=1; i"; case TYPE_INT: return std::to_string(std::get(*m_value)); + case TYPE_REF: { + return "(*m_value)) + ">"; + } break; + default: { std::cerr << "cannot stringify " << (TypeStr[m_type] + strlen("TYPE_")) diff --git a/src/StaticPass.cpp b/src/StaticPass.cpp index 3eb9b97..f4fb74e 100644 --- a/src/StaticPass.cpp +++ b/src/StaticPass.cpp @@ -96,7 +96,7 @@ namespace zn case NODE_IDENT: { std::string ident = node.repr(); auto sym = m_sym.find_any(ident); - + if (sym) assert(sym->scope <= m_sym.scope()); if (sym == std::nullopt) { std::stringstream ss; diff --git a/src/SymTable.cpp b/src/SymTable.cpp index ef003de..6e6c9cb 100644 --- a/src/SymTable.cpp +++ b/src/SymTable.cpp @@ -12,15 +12,18 @@ namespace zn void SymTable::prepare(std::string const& name, Type type) { - m_syms.push_back(Sym {name, std::nullopt, type}); + m_syms.push_back(Sym {name, std::nullopt, type, nullptr, m_scope}); } - void SymTable::declare(std::string const& name, size_t addr) + void SymTable::declare(std::string const& name, + size_t addr, + int scope) { auto itr = std::find_if(std::begin(m_syms), std::end(m_syms), - [name](auto const& sym){ - return sym.name == name; + [name, scope](auto const& sym){ + return sym.name == name + && sym.scope == scope; }); if (itr == std::end(m_syms)) @@ -28,39 +31,61 @@ namespace zn abort(); } - itr->addr = addr; + 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, TYPE_FUNCTION, prototype}); + m_syms.push_back(Sym {name, addr, TYPE_FUNCTION, prototype, m_scope}); } std::optional SymTable::find(std::string const& name) { + std::optional best; + for (size_t i=0; i m_syms[*best].scope + && m_syms[*best].scope < m_scope))) { - return m_syms[i]; + best = i; } } + if (best) + { + return m_syms[*best]; + } + return std::nullopt; } std::optional SymTable::find_any(std::string const& name) { + std::optional best; + for (size_t i=0; i m_syms[*best].scope + && m_syms[*best].scope <= m_scope))) { - return m_syms[i]; + best = i; } } + if (best) + { + return m_syms[*best]; + } + return std::nullopt; } @@ -70,4 +95,30 @@ namespace zn addr++; return addr; } + + void SymTable::enter_scope() + { + m_scope++; + } + + void SymTable::leave_scope() + { + m_scope--; + } + + std::string SymTable::string() const + { + std::stringstream ss; + + ss << "======== " << m_scope << " ========\n"; + + for (auto sym: m_syms) + { + ss << sym.scope << "\t" << sym.name << " " + << (sym.addr ? "[" + std::to_string(*sym.addr) + "]" : "[nil]") + << "\n"; + } + + return ss.str(); + } } diff --git a/src/SymTable.hpp b/src/SymTable.hpp index 3fad32d..3550b5e 100644 --- a/src/SymTable.hpp +++ b/src/SymTable.hpp @@ -3,6 +3,7 @@ #include "common.hpp" #include "Prototype.hpp" +#include "Node.hpp" namespace zn { @@ -11,6 +12,7 @@ namespace zn std::optional addr; Type type; std::shared_ptr prototype = nullptr; + int scope = 0; }; class SymTable @@ -19,10 +21,13 @@ namespace zn explicit SymTable(); virtual ~SymTable(); + int scope() const { return m_scope; } 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(std::string const& name, + size_t addr, + int scope); void declare_function(std::string const& name, size_t addr, @@ -33,8 +38,13 @@ namespace zn size_t gen_addr(); + void enter_scope(); + void leave_scope(); + + std::string string() const; private: std::vector m_syms; + int m_scope = 0; }; }