diff --git a/include/xo/expression/Lambda.hpp b/include/xo/expression/Lambda.hpp index a7f7529d..619913a1 100644 --- a/include/xo/expression/Lambda.hpp +++ b/include/xo/expression/Lambda.hpp @@ -39,6 +39,8 @@ namespace xo { const std::vector> & argv() const { return local_env_->argv(); } const ref::rp & body() const { return body_; } + bool needs_closure_flag() const { return !free_var_set_.empty(); } + // ----- FunctionInterface ----- virtual const std::string & name() const override { return name_; } @@ -50,13 +52,7 @@ namespace xo { // ----- Expression ----- virtual std::set get_free_variables() const override { - std::set retval = body_->get_free_variables(); - - /* but remove formals. */ - for (const auto & var : local_env_->argv()) - retval.erase(var->name()); - - return retval; + return this->free_var_set_; } virtual std::size_t visit_preorder(VisitFn visitor_fn) override { @@ -87,6 +83,9 @@ namespace xo { const ref::rp & local_env, const ref::rp & body); + /** compute free-variable set for this lambda **/ + std::set calc_free_variables() const; + private: /** lambda name. Initially supporting only form like * (define (foo x y z) @@ -103,6 +102,9 @@ namespace xo { /** function body **/ ref::rp body_; + /** free variables for this lambda **/ + std::set free_var_set_; + /** established (once) by @ref attach_envs. * * @note data dependency on ancestor expressions that don't exist yet diff --git a/src/expression/Lambda.cpp b/src/expression/Lambda.cpp index 7ad70ceb..d2fe8222 100644 --- a/src/expression/Lambda.cpp +++ b/src/expression/Lambda.cpp @@ -45,6 +45,19 @@ namespace xo { body); } /*make*/ + std::set + Lambda::calc_free_variables() const + { + std::set retval + = body_->get_free_variables(); + + /* but remove formals. */ + for (const auto & var : local_env_->argv()) + retval.erase(var->name()); + + return retval; + } /*calc_free_variables*/ + Lambda::Lambda(const std::string & name, TypeDescr lambda_type, const rp & local_env, @@ -64,7 +77,8 @@ namespace xo { } ss << ")"; - type_str_ = ss.str(); + this->type_str_ = ss.str(); + this->free_var_set_ = this->calc_free_variables(); body_->attach_envs(local_env_); } /*ctor*/