xo-reader xo-expression: nested lambdas working properly + docs

This commit is contained in:
Roland Conybeare 2025-07-06 14:13:44 -05:00
commit f164a3ab67
12 changed files with 198 additions and 39 deletions

View file

@ -98,12 +98,7 @@ namespace xo {
return xform_fn(this);
}
virtual void attach_envs(bp<Environment> p) override {
fn_->attach_envs(p);
for (const auto & arg : argv_)
arg->attach_envs(p);
}
virtual void attach_envs(bp<Environment> p) override;
virtual void display(std::ostream & os) const override;

View file

@ -33,7 +33,15 @@ namespace xo {
* returns llvm::Value representing code that produces a value for vname
**/
virtual bp<Expression> lookup_var(const std::string & vname) const = 0;
virtual void print(std::ostream & os) const = 0;
};
inline std::ostream &
operator<< (std::ostream & os, const Environment & x) {
x.print(os);
return os;
}
} /*namespace ast*/
} /*namespace xo*/

View file

@ -17,10 +17,7 @@ namespace xo {
static rp<GlobalEnv> make() { return new GlobalEnv(); }
bp<Expression> require_global(const std::string & vname,
bp<Expression> expr) {
global_map_[vname] = expr.get();
return expr;
} /*require_global*/
bp<Expression> expr);
// ----- Environment -----
@ -44,8 +41,10 @@ namespace xo {
return ix->second;
}
virtual void print(std::ostream & os) const override;
private:
GlobalEnv() = default;
GlobalEnv();
private:
/* for assignable globals, need to allocate memory

View file

@ -26,10 +26,21 @@ namespace xo {
* @p name Name for this lambda -- must be unique
* @p argv Formal parameters, in left-to-right order
* @p body Expression for body of this function
* @p parent_env Environment for enclosing lexical scope
**/
static rp<Lambda> make(const std::string & name,
const std::vector<rp<Variable>> & argv,
const rp<Expression> & body);
const rp<Expression> & body,
const rp<Environment> & parent_env);
/**
* @p name Name for this lambda -- must be unique
* @p env Environment with {name,type} for each formal parameter
* @p body Expression for body of function
**/
static rp<Lambda> make_from_env(const std::string & name,
const rp<LocalEnv> & env,
const rp<Expression> & body);
/** downcast from Expression **/
static bp<Lambda> from(bp<Expression> x) {
@ -174,16 +185,18 @@ namespace xo {
inline rp<Lambda>
make_lambda(const std::string & name,
const std::vector<rp<Variable>> & argv,
const rp<Expression> & body)
const rp<Expression> & body,
const rp<Environment> & parent_env)
{
return Lambda::make(name, argv, body);
return Lambda::make(name, argv, body, parent_env);
}
class LambdaAccess : public Lambda {
public:
static rp<LambdaAccess> make(const std::string & name,
const std::vector<rp<Variable>> & argv,
const rp<Expression> & body);
const rp<Expression> & body,
const rp<Environment> & parent_env);
static rp<LambdaAccess> make_empty();
/** assign body + compute derived members

View file

@ -25,10 +25,13 @@ namespace xo {
using TypeDescr = xo::reflect::TypeDescr;
public:
static rp<LocalEnv> make_empty();
/** named ctor idiom. Create instance with local variables per @p argv **/
static rp<LocalEnv> make(const std::vector<rp<Variable>> & argv) {
return new LocalEnv(argv);
}
static rp<LocalEnv> make(const std::vector<rp<Variable>> & argv,
const rp<Environment> & parent_env);
/** Create instance with single local variable @ap argv1 **/
static rp<LocalEnv> make1(const rp<Variable> & arg1,
const rp<Environment> & parent_env);
Lambda * origin() const { return origin_; }
const std::vector<rp<Variable>> & argv() const { return argv_; }
@ -48,10 +51,14 @@ namespace xo {
}
/** single-assign this environment's parent **/
void assign_parent(bp<Environment> p) {
assert(parent_env_.get() == nullptr);
parent_env_ = p.get();
}
void assign_parent(bp<Environment> p);
/** create/replace local variable @p target.
* Narrow use case: intended for when LocalEnv represents a top-level session environment
**/
void upsert_local(bp<Variable> target);
bp<Variable> lookup_local(const std::string & vname) const;
// ----- Environment -----
@ -71,9 +78,10 @@ namespace xo {
return parent_env_->lookup_var(target);
}
virtual void print(std::ostream & os) const override;
private:
LocalEnv(const std::vector<rp<Variable>> & argv)
: origin_{nullptr}, argv_(argv) {}
LocalEnv(const std::vector<rp<Variable>> & argv, const rp<Environment> & parent_env);
private:
/** Lambnda for which this environment created.
@ -93,6 +101,7 @@ namespace xo {
**/
rp<Environment> parent_env_;
};
} /*namespace ast*/
} /*namespace xo*/

View file

@ -16,6 +16,11 @@ namespace xo {
**/
class Variable : public Expression {
public:
/** Generate unique symbol-name beginning with @p prefix.
* Relies on static counter
**/
static std::string gensym(const std::string & prefix);
/** create expression representing a variable
* identified by @p name, that can take on values
* described by @p var_type.