From a877af562ae1981214c8aca79df2137ea3347273 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Sun, 30 Jun 2024 19:11:40 -0400 Subject: [PATCH] xo-expression: + Expression::attach_envs() --- include/xo/expression/Apply.hpp | 7 ++++++ include/xo/expression/ConstantInterface.hpp | 6 +++++ include/xo/expression/Expression.hpp | 21 ++++++++++++++++ include/xo/expression/IfExpr.hpp | 14 +++++++++++ include/xo/expression/Lambda.hpp | 25 ++++++++++++++------ include/xo/expression/PrimitiveInterface.hpp | 2 ++ include/xo/expression/Variable.hpp | 7 ++++++ src/expression/Lambda.cpp | 14 ++++++----- 8 files changed, 83 insertions(+), 13 deletions(-) diff --git a/include/xo/expression/Apply.hpp b/include/xo/expression/Apply.hpp index b7cb8c31..666ca5c7 100644 --- a/include/xo/expression/Apply.hpp +++ b/include/xo/expression/Apply.hpp @@ -49,6 +49,13 @@ namespace xo { return n; } + virtual void attach_envs(ref::brw p) override { + fn_->attach_envs(p); + + for (const auto & arg : argv_) + arg->attach_envs(p); + } + virtual void display(std::ostream & os) const override; private: diff --git a/include/xo/expression/ConstantInterface.hpp b/include/xo/expression/ConstantInterface.hpp index 586322c7..cb38f50d 100644 --- a/include/xo/expression/ConstantInterface.hpp +++ b/include/xo/expression/ConstantInterface.hpp @@ -33,6 +33,12 @@ namespace xo { virtual TypeDescr value_td() const = 0; /** reflection-tagged pointer to literal value of this constant **/ virtual TaggedPtr value_tp() const = 0; + + // ----- Expression ----- + + virtual void attach_envs(ref::brw /*p*/) override {} + + }; /*ConstantInterface*/ } /*namespace ast*/ diff --git a/include/xo/expression/Expression.hpp b/include/xo/expression/Expression.hpp index b38eecbd..403c2403 100644 --- a/include/xo/expression/Expression.hpp +++ b/include/xo/expression/Expression.hpp @@ -9,9 +9,14 @@ #include "xo/refcnt/Refcounted.hpp" #include "exprtype.hpp" #include +#include namespace xo { namespace ast { + class Variable; /* see Variable.hpp */ + class Lambda; /* see Lamnbda.hpp */ + class Environment; /* see Environment.hpp */ + /** @class Expression * @brief abstract syntax tree for an EGAD program * @@ -47,6 +52,22 @@ namespace xo { **/ virtual std::size_t visit_preorder(VisitFn visitor_fn) = 0; + /** attach an environment to each lambda expression X in this subtree, + * that will: + * - resolve names matching X's arguments (formal parameters) to + * from @p X.argv + * - resolve free variables from @p parent + **/ + virtual void attach_envs(ref::brw parent) = 0; + + /** append to *p_set the set of free variables in this expression. + * returns the number of free variables introduced + * + * @param env stack of lexcically-enclosing lamnbda expressions, + * in nesting order, i.e. outermost first, innertmost last + **/ + //virtual std::int32_t find_free_vars(std::vector> env) = 0; + /** write human-readable representation to stream **/ virtual void display(std::ostream & os) const = 0; /** human-readable string representation **/ diff --git a/include/xo/expression/IfExpr.hpp b/include/xo/expression/IfExpr.hpp index 6f397b3d..f962c905 100644 --- a/include/xo/expression/IfExpr.hpp +++ b/include/xo/expression/IfExpr.hpp @@ -51,6 +51,20 @@ namespace xo { return n; } + virtual void attach_envs(ref::brw p) override { + test_->attach_envs(p); + when_true_->attach_envs(p); + when_false_->attach_envs(p); + } + +#ifdef NOT_USING + virtual std::int32_t find_free_vars(std::set> * p_set) override { + return (test_->find_free_vars(p_set) + + when_true_->find_free_vars(p_set) + + when_false_->find_free_vars(p_set)); + } +#endif + virtual void display(std::ostream & os) const override; private: diff --git a/include/xo/expression/Lambda.hpp b/include/xo/expression/Lambda.hpp index 20c4425b..791f3548 100644 --- a/include/xo/expression/Lambda.hpp +++ b/include/xo/expression/Lambda.hpp @@ -8,6 +8,7 @@ #include "Expression.hpp" #include "FunctionInterface.hpp" #include "Variable.hpp" +#include "LocalEnv.hpp" #include #include //#include @@ -35,16 +36,16 @@ namespace xo { } const std::string & type_str() const { return type_str_; } - const std::vector> & argv() const { return argv_; } + const std::vector> & argv() const { return local_env_->argv(); } const ref::rp & body() const { return body_; } // ----- FunctionInterface ----- virtual const std::string & name() const override { return name_; } /** return number of arguments expected by this function **/ - virtual int n_arg() const override { return argv_.size(); } + virtual int n_arg() const override { return local_env_->n_arg(); } virtual TypeDescr fn_retval() const override { return body_->valuetype(); } - virtual TypeDescr fn_arg(uint32_t i) const override { return argv_[i]->valuetype(); } + virtual TypeDescr fn_arg(uint32_t i) const override { return local_env_->fn_arg(i); } // ----- Expression ----- @@ -53,7 +54,7 @@ namespace xo { visitor_fn(this); - for (const auto & arg : argv_) + for (const auto & arg : local_env_->argv()) n += arg->visit_preorder(visitor_fn); n += body_->visit_preorder(visitor_fn); @@ -61,6 +62,10 @@ namespace xo { return n; } + virtual void attach_envs(ref::brw p) override { + local_env_->assign_parent(p); + } + virtual void display(std::ostream & os) const override; private: @@ -69,7 +74,7 @@ namespace xo { **/ Lambda(const std::string & name, TypeDescr lambda_type, - const std::vector> & argv, + const ref::rp & local_env, const ref::rp & body); private: @@ -85,10 +90,16 @@ namespace xo { * "double(double,double)" for function of two doubles that returns a double **/ std::string type_str_; - /** formal argument names **/ - std::vector> argv_; /** function body **/ ref::rp body_; + + /** established (once) by @ref attach_envs. + * + * @note data dependency on ancestor expressions that don't exist yet + * when Lambda constructor runs, so we need to assign @ref local_env_ + * later. + **/ + ref::rp local_env_; }; /*Lambda*/ inline ref::rp diff --git a/include/xo/expression/PrimitiveInterface.hpp b/include/xo/expression/PrimitiveInterface.hpp index 907aef2d..184a70d8 100644 --- a/include/xo/expression/PrimitiveInterface.hpp +++ b/include/xo/expression/PrimitiveInterface.hpp @@ -53,6 +53,8 @@ namespace xo { return 1; } + virtual void attach_envs(ref::brw /*p*/) override {} + private: }; /*PrimitiveInterface*/ } /*namespace ast*/ diff --git a/include/xo/expression/Variable.hpp b/include/xo/expression/Variable.hpp index 13e46a98..c4a2eb9a 100644 --- a/include/xo/expression/Variable.hpp +++ b/include/xo/expression/Variable.hpp @@ -36,6 +36,13 @@ namespace xo { return 1; } + virtual void attach_envs(ref::brw /*p*/) override {} + +#ifdef NOT_USING + virtual std::int32_t find_free_vars(std::set> * p_set) override { + } +#endif + virtual void display(std::ostream & os) const override; private: diff --git a/src/expression/Lambda.cpp b/src/expression/Lambda.cpp index 4cd25da9..7ad70ceb 100644 --- a/src/expression/Lambda.cpp +++ b/src/expression/Lambda.cpp @@ -41,23 +41,23 @@ namespace xo { return new Lambda(name, lambda_td, - argv, + LocalEnv::make(argv), body); } /*make*/ Lambda::Lambda(const std::string & name, TypeDescr lambda_type, - const std::vector> & argv, + const rp & local_env, const ref::rp & body) : FunctionInterface(exprtype::lambda, lambda_type), name_{name}, - argv_{argv}, - body_{body} + body_{body}, + local_env_{local_env} { stringstream ss; ss << "double"; ss << "("; - for (std::size_t i = 0; i < argv.size(); ++i) { + for (std::size_t i = 0, n = this->n_arg(); i < n; ++i) { if (i > 0) ss << ","; ss << "double"; @@ -65,13 +65,15 @@ namespace xo { ss << ")"; type_str_ = ss.str(); + + body_->attach_envs(local_env_); } /*ctor*/ void Lambda::display(std::ostream & os) const { os << "argv()) << xtag("body", body_) << ">"; } /*display*/