diff --git a/include/xo/expression2/Binding.hpp b/include/xo/expression2/Binding.hpp index 97f74c27..805ebeb9 100644 --- a/include/xo/expression2/Binding.hpp +++ b/include/xo/expression2/Binding.hpp @@ -12,6 +12,8 @@ namespace xo { namespace scm { class Binding { public: + using slot_type = int32_t; + static constexpr int32_t c_link_sentinel = -2; static constexpr int32_t c_link_global = -1; @@ -22,7 +24,7 @@ namespace xo { static Binding null() { return Binding(); } /** global bindings are located by symbol name **/ - static Binding global() { return Binding(c_link_global, 0); } + static Binding global(int32_t j_slot) { return Binding(c_link_global, j_slot); } static Binding local(int32_t j_slot) { return Binding(0, j_slot); } static Binding relative(int32_t i_link, Binding def); diff --git a/include/xo/expression2/DGlobalSymtab.hpp b/include/xo/expression2/DGlobalSymtab.hpp index 91117888..0aca15c6 100644 --- a/include/xo/expression2/DGlobalSymtab.hpp +++ b/include/xo/expression2/DGlobalSymtab.hpp @@ -6,6 +6,8 @@ #pragma once #include "Binding.hpp" +#include "DVariable.hpp" +#include #include namespace xo { @@ -23,7 +25,8 @@ namespace xo { public: using key_type = const DUniqueString *; using value_type = Binding; - using repr_type = xo::map::DArenaHashMap; + using repr_type = xo::map::DArenaHashMap; + using AAllocator = xo::mm::AAllocator; using MemorySizeVisitor = xo::mm::MemorySizeVisitor; public: @@ -31,6 +34,17 @@ namespace xo { void visit_pools(const MemorySizeVisitor & visitor) const; public: + /** lookup global symbol with name @p sym **/ + DVariable * lookup_variable(const DUniqueString * sym) const noexcept; + + /** establish binding for @p sym, with type described by @p typeref, + * replacing existing global (if present) with the same name. + * Use memory from @p mm to create variable-expr + **/ + DVariable * establish_variable(obj mm, + const DUniqueString * sym, + TypeRef typeref); + /** @defgroup xo-expression2-symboltable-facet symboltable facet**/ ///@{ @@ -49,6 +63,13 @@ namespace xo { /** map symbols -> bindings **/ repr_type map_; + /** array of variables. + * When S is a unique-string for a global symbol, then: + * 1. map_[S] is unique global index i(S) for S. + * 2. vars_[i(S)] is variable-expr var(S) for S + * 3. var(S)->name == S + **/ + DArray * vars_ = nullptr; }; } /*namespace scm*/ diff --git a/include/xo/expression2/DLocalSymtab.hpp b/include/xo/expression2/DLocalSymtab.hpp index 6a75422d..f4073226 100644 --- a/include/xo/expression2/DLocalSymtab.hpp +++ b/include/xo/expression2/DLocalSymtab.hpp @@ -73,7 +73,7 @@ namespace xo { return slots_[ix.j_slot()].var_; } - /** increase slot size (provided beleow capacity) to append + /** increase slot size (provided below capacity) to append * binding for one local variable. Local variable will be allocated * from @p mm, named @p name, with type described by @p typeref. **/ diff --git a/src/expression2/DGlobalSymtab.cpp b/src/expression2/DGlobalSymtab.cpp index c11761d9..10e1665f 100644 --- a/src/expression2/DGlobalSymtab.cpp +++ b/src/expression2/DGlobalSymtab.cpp @@ -5,20 +5,108 @@ #include "DGlobalSymtab.hpp" #include "DUniqueString.hpp" +#include +#include +#include +#include #include namespace xo { + using xo::mm::AGCObject; + namespace scm { +#ifdef NOT_YET + DVariable * + DGlobalSymtab::lookup_binding(Binding ix) noexcept + { + assert(ix.i_link() == -1); + assert(ix.j_slot() >= 0); + assert(vars_); + assert(std::uint64_t(ix.j_slot()) < vars_->size()); + + auto var_gco = obj::from((*vars_)[ix.j_slot()]);; + auto var = var_gco.to_facet(); + + assert(var.data()); + + return var.data(); + } +#endif + + DVariable * + DGlobalSymtab::lookup_variable(const DUniqueString * sym) const noexcept + { + Binding existing = this->lookup_binding(sym); + + if (existing.is_null()) + return nullptr; + + auto var_gco = obj::from((*vars_)[existing.j_slot()]); + auto var = var_gco.to_facet(); + + assert(var.data()); + + return var.data(); + } + + DVariable * + DGlobalSymtab::establish_variable(obj mm, + const DUniqueString * sym, + TypeRef typeref) + { + DVariable * var = this->lookup_variable(sym); + + if (!var) { + assert(vars_); + + DArray::size_type n = vars_->size(); + + /** make sure vars_ has room **/ + if (n == vars_->capacity()) { + // reallocate with more capacity + DArray * vars_2x = DArray::copy(mm, vars_, vars_->capacity() * 2); + + assert(vars_2x); + + this->vars_ = vars_2x; + } + + /** create new variable **/ + Binding binding = Binding::global(n); + var = DVariable::make(mm, sym, typeref, binding); + + if (!var) { + // something terribly wrong + assert(false); + return var; + } + + map_[sym] = binding.j_slot(); + + bool ok = vars_->push_back(obj(var)); + + if (!ok) + assert(false); + } + + return var; + } + Binding DGlobalSymtab::lookup_binding(const DUniqueString * sym) const noexcept { - (void)sym; + assert(sym); scope log(XO_DEBUG(true), "stub"); log && log(xtag("sym", std::string_view(*sym))); - return Binding(); + auto ix = map_.find(sym); + + if (ix == map_.end()) + return Binding::null(); + + return Binding::global(ix->second); } } /*namespace scm*/