From 14796663b1d91a1593ee30c221281c635d2d0822 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Tue, 2 Jul 2024 16:57:07 -0400 Subject: [PATCH] xo-expression: + binding_path + assoc w/ each Variable --- include/xo/expression/Environment.hpp | 15 +++++++++++++ include/xo/expression/GlobalEnv.hpp | 12 +++++++++- include/xo/expression/LocalEnv.hpp | 6 ++++- include/xo/expression/Variable.hpp | 7 +++++- include/xo/expression/binding_path.hpp | 29 ++++++++++++++++++++++++ src/expression/CMakeLists.txt | 1 + src/expression/LocalEnv.cpp | 31 ++++++++++++++++++++++++++ src/expression/Variable.cpp | 7 ++++++ 8 files changed, 105 insertions(+), 3 deletions(-) create mode 100644 include/xo/expression/binding_path.hpp create mode 100644 src/expression/LocalEnv.cpp diff --git a/include/xo/expression/Environment.hpp b/include/xo/expression/Environment.hpp index 6fec9b32..6baded6d 100644 --- a/include/xo/expression/Environment.hpp +++ b/include/xo/expression/Environment.hpp @@ -12,6 +12,21 @@ namespace xo { namespace ast { class Environment : public ref::Refcount { public: + /** true if this is toplevel (global) environment. + * Toplevel environment doesn't have slot numbers. + * + * Variables that bind in the global environment have unique + * names, which we rely on instead of slot numbers. + **/ + virtual bool is_global_env() const = 0; + + /** lookup binding path for @p vname in this environment. + * + * Reports ingredients needed to address variable at runtime, + * in runtime analog of this environment + **/ + virtual binding_path lookup_binding(const std::string & vname) const = 0; + /** lookup variable-expression @p vname in this environment. * returns llvm::Value representing code that produces a value for vname **/ diff --git a/include/xo/expression/GlobalEnv.hpp b/include/xo/expression/GlobalEnv.hpp index fbc9ef9c..08eb9355 100644 --- a/include/xo/expression/GlobalEnv.hpp +++ b/include/xo/expression/GlobalEnv.hpp @@ -7,6 +7,7 @@ #include "Environment.hpp" #include +#include namespace xo { namespace ast { @@ -23,7 +24,16 @@ namespace xo { // ----- Environment ----- - virtual ref::brw lookup_var(const std::string & vname) const { + virtual bool is_global_env() const override { return true; } + + virtual binding_path lookup_binding(const std::string & vname) const override { + /* i_link: -1 for global environment + * j_slot: not used + */ + return { -1, 0 }; + } + + virtual ref::brw lookup_var(const std::string & vname) const override { auto ix = global_map_.find(vname); if (ix == global_map_.end()) { diff --git a/include/xo/expression/LocalEnv.hpp b/include/xo/expression/LocalEnv.hpp index 42a36f2e..d8fe2178 100644 --- a/include/xo/expression/LocalEnv.hpp +++ b/include/xo/expression/LocalEnv.hpp @@ -47,6 +47,10 @@ namespace xo { // ----- Environment ----- + virtual bool is_global_env() const override { return false; } + + virtual binding_path lookup_binding(const std::string & vname) const override; + virtual ref::brw lookup_var(const std::string & target) const override { for (const auto & arg : argv_) { if (arg->name() == target) @@ -61,7 +65,7 @@ namespace xo { private: LocalEnv(const std::vector> & argv) - : argv_(argv) {} + : origin_{nullptr}, argv_(argv) {} private: /** Lambnda for which this environment created. diff --git a/include/xo/expression/Variable.hpp b/include/xo/expression/Variable.hpp index 471eb873..3f45677e 100644 --- a/include/xo/expression/Variable.hpp +++ b/include/xo/expression/Variable.hpp @@ -6,6 +6,7 @@ #pragma once #include "Expression.hpp" +#include "binding_path.hpp" namespace xo { namespace ast { @@ -42,7 +43,7 @@ namespace xo { return 1; } - virtual void attach_envs(ref::brw /*p*/) override {} + virtual void attach_envs(ref::brw /*p*/) override; virtual void display(std::ostream & os) const override; @@ -55,6 +56,10 @@ namespace xo { private: /** variable name **/ std::string name_; + /** navigate environment via this path to find runtime memory + * location for this variable + **/ + binding_path path_; }; /*Variable*/ inline ref::rp diff --git a/include/xo/expression/binding_path.hpp b/include/xo/expression/binding_path.hpp new file mode 100644 index 00000000..a3692ed1 --- /dev/null +++ b/include/xo/expression/binding_path.hpp @@ -0,0 +1,29 @@ +/* file binding_path.hpp + * + * author: Roland Conybeare, Jul 2024 + */ + +#pragma once + +namespace xo { + namespace ast { + /** @class path + * + * @brief path from the *use* of a variable to the environment + * providing its location. + **/ + struct binding_path { + /** @of parent links to traverse. -1 if global **/ + int i_link_ = -1; + /** for variables bound in some local environment: + * slot# within that environment. + * + * Ignored if @ref i_link_ is -1 + **/ + int j_slot_ = 0; + }; /*binding_path*/ + } /*namespace ast*/ +} /*namespace xo*/ + + +/* end binding_path.hpp */ diff --git a/src/expression/CMakeLists.txt b/src/expression/CMakeLists.txt index ef5cf6f2..50edec01 100644 --- a/src/expression/CMakeLists.txt +++ b/src/expression/CMakeLists.txt @@ -7,6 +7,7 @@ set(SELF_SRCS Lambda.cpp Variable.cpp IfExpr.cpp + LocalEnv.cpp ) xo_add_shared_library4(${SELF_LIB} ${PROJECT_NAME}Targets ${PROJECT_VERSION} 1 ${SELF_SRCS}) diff --git a/src/expression/LocalEnv.cpp b/src/expression/LocalEnv.cpp new file mode 100644 index 00000000..fb724aeb --- /dev/null +++ b/src/expression/LocalEnv.cpp @@ -0,0 +1,31 @@ +/* file LocalEnv.cpp + * + * author: Roland Conybeare + */ + +#include "LocalEnv.hpp" + +namespace xo { + namespace ast { + binding_path + LocalEnv::lookup_binding(const std::string & vname) const + { + int j_slot = 0; + for (const auto & arg : argv_) { + if (arg->name() == vname) + return { 0 /*i_link*/, j_slot }; + ++j_slot; + } + + auto tmp = parent_env_->lookup_binding(vname); + + if (tmp.i_link_ == -1) + return tmp; + else + return { tmp.i_link_ + 1, tmp.j_slot_ }; + } /*lookup_binding*/ + } /*namespace ast*/ +} /*namespace xo*/ + + +/* end LocalEnv.cpp */ diff --git a/src/expression/Variable.cpp b/src/expression/Variable.cpp index 52890ccc..71d47655 100644 --- a/src/expression/Variable.cpp +++ b/src/expression/Variable.cpp @@ -1,9 +1,16 @@ /* @file Variable.cpp */ #include "Variable.hpp" +#include "Environment.hpp" namespace xo { namespace ast { + void + Variable::attach_envs(ref::brw e) { + /** e makes accessible all enclosing lexical scopes **/ + this->path_ = e->lookup_binding(this->name_); + } /*attach_envs*/ + void Variable::display(std::ostream & os) const { os << "