diff --git a/include/xo/expression/LocalEnv.hpp b/include/xo/expression/LocalEnv.hpp index 3106dc6c..ec3d4c81 100644 --- a/include/xo/expression/LocalEnv.hpp +++ b/include/xo/expression/LocalEnv.hpp @@ -35,6 +35,11 @@ namespace xo { int n_arg() const { return argv_.size(); } TypeDescr fn_arg(uint32_t i) const { return argv_[i]->valuetype(); } + /** report binding path for a formal parameter. + * Returns sentinel if @p vname doesn't appear in @ref argv_ + **/ + binding_path lookup_local_binding(const std::string & vname) const; + /** single-assign this environment's origin **/ void assign_origin(Lambda * p) { assert(origin_ == nullptr); diff --git a/src/expression/LocalEnv.cpp b/src/expression/LocalEnv.cpp index fb724aeb..8b834278 100644 --- a/src/expression/LocalEnv.cpp +++ b/src/expression/LocalEnv.cpp @@ -8,7 +8,7 @@ namespace xo { namespace ast { binding_path - LocalEnv::lookup_binding(const std::string & vname) const + LocalEnv::lookup_local_binding(const std::string & vname) const { int j_slot = 0; for (const auto & arg : argv_) { @@ -17,12 +17,25 @@ namespace xo { ++j_slot; } - auto tmp = parent_env_->lookup_binding(vname); + return { -2 /*i_link: sentinel*/, 0 }; + } /*lookup_local_binding*/ - if (tmp.i_link_ == -1) - return tmp; + binding_path + LocalEnv::lookup_binding(const std::string & vname) const + { + { + auto local = this->lookup_local_binding(vname); + + if (local.i_link_ == 0) + return local; + } + + auto free = parent_env_->lookup_binding(vname); + + if (free.i_link_ == -1) + return free; else - return { tmp.i_link_ + 1, tmp.j_slot_ }; + return { free.i_link_ + 1, free.j_slot_ }; } /*lookup_binding*/ } /*namespace ast*/ } /*namespace xo*/