diff --git a/include/xo/expression/Environment.hpp b/include/xo/expression/Environment.hpp new file mode 100644 index 00000000..834366c7 --- /dev/null +++ b/include/xo/expression/Environment.hpp @@ -0,0 +1,23 @@ +/* file Environment.hpp + * + * author: Roland Conybeare, Jun 2024 + */ + +#pragma once + +#include "xo/refcnt/Refcounted.hpp" +#include "Variable.hpp" + +namespace xo { + namespace ast { + class Environment : public ref::Refcount { + public: + /** lookup variable-expression @p vname in this environment + **/ + virtual ref::brw lookup_var(const std::string & vname) const = 0; + }; + } /*namespace ast*/ +} /*namespace xo*/ + + +/* end Environment.hpp */ diff --git a/include/xo/expression/GlobalEnv.hpp b/include/xo/expression/GlobalEnv.hpp new file mode 100644 index 00000000..223fc9df --- /dev/null +++ b/include/xo/expression/GlobalEnv.hpp @@ -0,0 +1,46 @@ +/* file GlobalEnv.hpp + * + * author: Roland Conybeare, Jun 2024 + */ + +#pragma once + +#include "Environment.hpp" +#include + +namespace xo { + namespace ast { + class GlobalEnv : public Environment { + public: + ref::brw require_global(ref::brw var) { + const std::string & vname = var->name(); + + auto ix = var_map_.find(vname); + + if (ix == var_map_.end()) { + var_map_[vname] = var.get(); + return var; + } else { + return ix->second; + } + } /*require_global*/ + + // ----- Environment ----- + + virtual ref::brw lookup_var(const std::string & vname) const { + auto ix = var_map_.find(vname); + + if (ix == var_map_.end()) + return ref::brw::from_native(nullptr); + + return ix->second; + } + + private: + std::map> var_map_; + }; + } /*namespace ast*/ +} /*namespace xo*/ + + +/* end GlobalEnv.hpp */ diff --git a/include/xo/expression/LocalEnv.hpp b/include/xo/expression/LocalEnv.hpp new file mode 100644 index 00000000..7f5f12dd --- /dev/null +++ b/include/xo/expression/LocalEnv.hpp @@ -0,0 +1,70 @@ +/* file LocalEnv.hpp + * + * author: Roland Conybeare, Jun 2024 + */ + +#pragma once + +#include "Environment.hpp" + +namespace xo { + namespace ast { + /** @brief LocalEnv + * + * @class Local environment for a lambda. + * Lists the Variables corresponding to this lambda's formal + * parameters, but also links to @ref Environment for + * innermost enclosing @ref Lambda. + **/ + class LocalEnv : public Environment { + public: + using TypeDescr = xo::reflect::TypeDescr; + + public: + /** named ctor idiom. Create instance with local variables per @p argv **/ + static ref::rp make(const std::vector> & argv) { + return new LocalEnv(argv); + } + + const std::vector> & argv() const { return argv_; } + int n_arg() const { return argv_.size(); } + TypeDescr fn_arg(uint32_t i) const { return argv_[i]->valuetype(); } + + /** single-assign this environment's parent **/ + void assign_parent(ref::brw p) { + assert(parent_env_.get() == nullptr); + parent_env_ = p.get(); + } + + // ----- Environment ----- + + virtual ref::brw lookup_var(const std::string & target) const override { + for (const auto & arg : argv_) { + if (arg->name() == target) + return arg; + } + + /* here: target not found in local vars, + * delegate to innermost ancestor + */ + return parent_env_->lookup_var(target); + } + + private: + LocalEnv(const std::vector> & argv) + : argv_(argv) {} + + private: + /** formal argument names **/ + std::vector> argv_; + + /** parent environment. Free variable in this lambda's + * body, will be resolved by referring them to @ref parent_env_. + **/ + ref::rp parent_env_; + }; + } /*namespace ast*/ +} /*namespace xo*/ + + +/* end LocalEnv.hpp */