xo-expression: + Expression::attach_envs()

This commit is contained in:
Roland Conybeare 2024-06-30 19:11:40 -04:00
commit a877af562a
8 changed files with 83 additions and 13 deletions

View file

@ -49,6 +49,13 @@ namespace xo {
return n;
}
virtual void attach_envs(ref::brw<Environment> p) override {
fn_->attach_envs(p);
for (const auto & arg : argv_)
arg->attach_envs(p);
}
virtual void display(std::ostream & os) const override;
private:

View file

@ -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<Environment> /*p*/) override {}
}; /*ConstantInterface*/
} /*namespace ast*/

View file

@ -9,9 +9,14 @@
#include "xo/refcnt/Refcounted.hpp"
#include "exprtype.hpp"
#include <functional>
#include <set>
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<Environment> 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<ref::brw<Lambda>> env) = 0;
/** write human-readable representation to stream **/
virtual void display(std::ostream & os) const = 0;
/** human-readable string representation **/

View file

@ -51,6 +51,20 @@ namespace xo {
return n;
}
virtual void attach_envs(ref::brw<Environment> 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<ref::brw<Variable>> * 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:

View file

@ -8,6 +8,7 @@
#include "Expression.hpp"
#include "FunctionInterface.hpp"
#include "Variable.hpp"
#include "LocalEnv.hpp"
#include <vector>
#include <string>
//#include <cstdint>
@ -35,16 +36,16 @@ namespace xo {
}
const std::string & type_str() const { return type_str_; }
const std::vector<ref::rp<Variable>> & argv() const { return argv_; }
const std::vector<ref::rp<Variable>> & argv() const { return local_env_->argv(); }
const ref::rp<Expression> & 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<Environment> 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<ref::rp<Variable>> & argv,
const ref::rp<LocalEnv> & local_env,
const ref::rp<Expression> & 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<ref::rp<Variable>> argv_;
/** function body **/
ref::rp<Expression> 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<LocalEnv> local_env_;
}; /*Lambda*/
inline ref::rp<Lambda>

View file

@ -53,6 +53,8 @@ namespace xo {
return 1;
}
virtual void attach_envs(ref::brw<Environment> /*p*/) override {}
private:
}; /*PrimitiveInterface*/
} /*namespace ast*/

View file

@ -36,6 +36,13 @@ namespace xo {
return 1;
}
virtual void attach_envs(ref::brw<Environment> /*p*/) override {}
#ifdef NOT_USING
virtual std::int32_t find_free_vars(std::set<ref::brw<Variable>> * p_set) override {
}
#endif
virtual void display(std::ostream & os) const override;
private:

View file

@ -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<rp<Variable>> & argv,
const rp<LocalEnv> & local_env,
const ref::rp<Expression> & 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 << "<Lambda"
<< xtag("name", name_)
<< xtag("argv", argv_)
<< xtag("argv", local_env_->argv())
<< xtag("body", body_)
<< ">";
} /*display*/