From cdb4dd8427d46f5db12e65be4817383b8c18b1a6 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Wed, 3 Jul 2024 16:37:29 -0400 Subject: [PATCH] xo-expression: + Lambda::captured_var_set; assigned in ctor --- include/xo/expression/Lambda.hpp | 3 ++ src/expression/Lambda.cpp | 50 ++++++++++++++++++++++++-------- 2 files changed, 41 insertions(+), 12 deletions(-) diff --git a/include/xo/expression/Lambda.hpp b/include/xo/expression/Lambda.hpp index 91366ca9..40083875 100644 --- a/include/xo/expression/Lambda.hpp +++ b/include/xo/expression/Lambda.hpp @@ -125,6 +125,9 @@ namespace xo { /** free variables for this lambda **/ std::set free_var_set_; + /** variables that appear free in some nested lambda **/ + std::set captured_var_set_; + /** map giving unique identity to each variable appearing in this layer. * includes: * - formal parameters diff --git a/src/expression/Lambda.cpp b/src/expression/Lambda.cpp index 320e1eda..cf9112cd 100644 --- a/src/expression/Lambda.cpp +++ b/src/expression/Lambda.cpp @@ -149,24 +149,50 @@ namespace xo { this->free_var_set_ = this->calc_free_variables(); std::map> nested_lambda_map; + { + this->body_->visit_layer + ([&nested_lambda_map] + (ref::brw expr) + { + if (expr->extype() == exprtype::lambda) { + ref::brw lm = Lambda::from(expr); - this->body_->visit_layer - ([&nested_lambda_map] - (ref::brw expr) - { - if (expr->extype() == exprtype::lambda) { - ref::brw lm = Lambda::from(expr); - - nested_lambda_map[lm->name()] = lm.get(); - } - }); - + nested_lambda_map[lm->name()] = lm.get(); + } + }); + } this->nested_lambda_map_ = std::move(nested_lambda_map); + /* establish the set of captured local vars. + * These are any formal parameters that appear free in + * any layer of a nested lambda. + */ + std::set captured_var_set; + { + for (const auto & ix : nested_lambda_map_) { + std::set nested_free_var_set + = ix.second->get_free_variables(); + + for (const auto & jx : nested_free_var_set) { + /* check whether variable *jx is one of this lambda's formals */ + auto bind = this->local_env_->lookup_local_binding(jx); + + if (bind.i_link_ == 0) { + /* yup, it's a formal parameter of this lambda */ + captured_var_set.insert(jx); + } + } + } + } + + this->captured_var_set_ = std::move(captured_var_set); + /* in particular: - * - establish binding path for each variable + * - establish binding path (intrusively) for each variable + * assigns Variable::path_ */ this->body_->attach_envs(local_env_); + } /*ctor*/ void