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

@ -58,6 +58,14 @@ namespace xo {
{lhs, rhs});
}
void
Apply::attach_envs(bp<Environment> p) {
fn_->attach_envs(p);
for (const auto & arg : argv_)
arg->attach_envs(p);
}
void
Apply::display(std::ostream & os) const {
os << "<Apply"

View file

@ -11,6 +11,7 @@ set(SELF_SRCS
Variable.cpp
IfExpr.cpp
Sequence.cpp
GlobalEnv.cpp
LocalEnv.cpp
ConvertExpr.cpp
Primitive.cpp

View file

@ -0,0 +1,26 @@
/* file GlobalEnv.cpp
*
* author: Roland Conybeare, Jul 2025
*/
#include "GlobalEnv.hpp"
#include "Expression.hpp"
namespace xo {
namespace ast {
GlobalEnv::GlobalEnv() = default;
bp<Expression>
GlobalEnv::require_global(const std::string & vname,
bp<Expression> expr)
{
this->global_map_[vname] = expr.get();
return expr;
} /*require_global*/
void
GlobalEnv::print(std::ostream & os) const {
os << "<globalenv" << xtag("size", global_map_.size()) << ">";
}
} /*namespace ast*/
} /*namespace xo*/

View file

@ -66,15 +66,11 @@ namespace xo {
}
rp<Lambda>
Lambda::make(const std::string & name,
const std::vector<rp<Variable>> & argv,
const rp<Expression> & body)
Lambda::make_from_env(const std::string & name,
const rp<LocalEnv> & env,
const rp<Expression> & body)
{
using xo::reflect::FunctionTdx;
rp<LocalEnv> env = LocalEnv::make(argv);
TypeDescr lambda_td = assemble_lambda_td(argv, body);
TypeDescr lambda_td = assemble_lambda_td(env->argv(), body);
rp<Lambda> retval
= new Lambda(name,
@ -86,6 +82,17 @@ namespace xo {
env->assign_origin(retval.get());
return retval;
}
rp<Lambda>
Lambda::make(const std::string & name,
const std::vector<rp<Variable>> & argv,
const rp<Expression> & body,
const rp<Environment> & parent_env)
{
rp<LocalEnv> env = LocalEnv::make(argv, parent_env);
return make_from_env(name, env, body);
} /*make*/
std::set<std::string>
@ -315,10 +322,11 @@ namespace xo {
rp<LambdaAccess>
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)
{
TypeDescr lambda_td = assemble_lambda_td(argv, body);
rp<LocalEnv> env = LocalEnv::make(argv);
rp<LocalEnv> env = LocalEnv::make(argv, parent_env);
rp<LambdaAccess> retval
= new LambdaAccess(name,

View file

@ -4,12 +4,43 @@
*/
#include "LocalEnv.hpp"
#include "xo/indentlog/print/vector.hpp"
namespace xo {
namespace ast {
binding_path
LocalEnv::lookup_local_binding(const std::string & vname) const
rp<LocalEnv>
LocalEnv::make_empty() {
return new LocalEnv(std::vector<rp<Variable>>(), nullptr);
}
rp<LocalEnv>
LocalEnv::make(const std::vector<rp<Variable>> & argv,
const rp<Environment> & parent_env)
{
return new LocalEnv(argv, parent_env);
}
rp<LocalEnv>
LocalEnv::make1(const rp<Variable> & arg1,
const rp<Environment> & parent_env)
{
std::vector<rp<Variable>> argv = { arg1 };
return make(argv, parent_env);
}
LocalEnv::LocalEnv(const std::vector<rp<Variable>> & argv,
const rp<Environment> & parent_env)
: origin_{nullptr},
argv_(argv),
parent_env_{parent_env}
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag), xtag("this", (void*)this), xtag("argv", argv_));
}
binding_path
LocalEnv::lookup_local_binding(const std::string & vname) const {
int j_slot = 0;
for (const auto & arg : argv_) {
if (arg->name() == vname)
@ -21,11 +52,9 @@ namespace xo {
} /*lookup_local_binding*/
binding_path
LocalEnv::lookup_binding(const std::string & vname) const
{
LocalEnv::lookup_binding(const std::string & vname) const {
{
auto local = this->lookup_local_binding(vname);
if (local.i_link_ == 0)
return local;
}
@ -37,6 +66,52 @@ namespace xo {
else
return { free.i_link_ + 1, free.j_slot_ };
} /*lookup_binding*/
bp<Variable>
LocalEnv::lookup_local(const std::string & vname) const {
for (const auto & var : this->argv_) {
if (var->name() == vname)
return var;
}
return bp<Variable>::from_native(nullptr);
}
void
LocalEnv::assign_parent(bp<Environment> p) {
if ((parent_env_.get() != nullptr) && (parent_env_.get() != p.get())) {
throw std::runtime_error(tostr("LocalEnv::assign_parent(P2): already have established parent P1",
xtag("P1", parent_env_),
xtag("P2", p)));
assert(false);
}
parent_env_ = p.promote();
}
void
LocalEnv::upsert_local(bp<Variable> target) {
for (auto & var : this->argv_) {
if (var->name() == target->name()) {
/* replace existing variable. May change its type */
var = target.promote();
return;
}
}
/* control here: target not already present in this frame -> append */
this->argv_.push_back(target.promote());
}
void
LocalEnv::print(std::ostream& os) const {
os << "<localenv"
<< xtag("this", (void*)this)
<< xtag("argv", argv_)
<< ">";
}
} /*namespace ast*/
} /*namespace xo*/

View file

@ -5,6 +5,18 @@
namespace xo {
namespace ast {
std::string
Variable::gensym(const std::string & prefix) {
static std::size_t s_counter = 0;
++s_counter;
char buf[32];
snprintf(buf, sizeof(buf), "%ld", s_counter);
return prefix + std::string(buf);
}
void
Variable::attach_envs(bp<Environment> e) {
/** e makes accessible all enclosing lexical scopes **/