xo-exprssion: + Expression::xform_layer()
This commit is contained in:
parent
14796663b1
commit
1d99757bca
8 changed files with 72 additions and 4 deletions
|
|
@ -63,6 +63,15 @@ namespace xo {
|
|||
return n;
|
||||
}
|
||||
|
||||
virtual ref::rp<Expression> xform_layer(TransformFn xform_fn) override {
|
||||
this->fn_ = fn_->xform_layer(xform_fn);
|
||||
|
||||
for (auto & arg : argv_)
|
||||
arg = arg->xform_layer(xform_fn);
|
||||
|
||||
return xform_fn(this);
|
||||
}
|
||||
|
||||
virtual void attach_envs(ref::brw<Environment> p) override {
|
||||
fn_->attach_envs(p);
|
||||
|
||||
|
|
|
|||
|
|
@ -56,6 +56,10 @@ namespace xo {
|
|||
return 1;
|
||||
}
|
||||
|
||||
virtual ref::rp<Expression> xform_layer(TransformFn xform_fn) override {
|
||||
return xform_fn(this);
|
||||
}
|
||||
|
||||
virtual void display(std::ostream & os) const override {
|
||||
os << "<Constant"
|
||||
<< xtag("type", value_td_->short_name())
|
||||
|
|
|
|||
|
|
@ -35,7 +35,10 @@ namespace xo {
|
|||
**/
|
||||
class Expression : public ref::Refcount {
|
||||
public:
|
||||
using VisitFn = std::function<void (ref::brw<Expression>)>;
|
||||
using VisitFn = std::function
|
||||
<void (ref::brw<Expression>)>;
|
||||
using TransformFn = std::function
|
||||
<ref::rp<Expression> (ref::brw<Expression>)>;
|
||||
using TypeDescr = xo::reflect::TypeDescr;
|
||||
|
||||
public:
|
||||
|
|
@ -58,6 +61,9 @@ namespace xo {
|
|||
**/
|
||||
virtual std::size_t visit_preorder(VisitFn visitor_fn) = 0;
|
||||
|
||||
/** traverse ast @ref visit_preorder but do not visit Lambdas **/
|
||||
virtual ref::rp<Expression> xform_layer(TransformFn 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
|
||||
|
|
|
|||
|
|
@ -60,12 +60,21 @@ namespace xo {
|
|||
|
||||
visitor_fn(this);
|
||||
|
||||
n += this->test_->visit_preorder(visitor_fn);
|
||||
n += this->when_true_->visit_preorder(visitor_fn);
|
||||
n += this->when_false_->visit_preorder(visitor_fn);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
virtual ref::rp<Expression> xform_layer(TransformFn xform_fn) override {
|
||||
this->test_ = this->test_->xform_layer(xform_fn);
|
||||
this->when_true_ = this->when_true_->xform_layer(xform_fn);
|
||||
this->when_false_= this->when_false_->xform_layer(xform_fn);
|
||||
|
||||
return xform_fn(this);
|
||||
}
|
||||
|
||||
virtual void attach_envs(ref::brw<Environment> p) override {
|
||||
test_->attach_envs(p);
|
||||
when_true_->attach_envs(p);
|
||||
|
|
|
|||
|
|
@ -68,6 +68,11 @@ namespace xo {
|
|||
return n;
|
||||
}
|
||||
|
||||
virtual ref::rp<Expression> xform_layer(TransformFn /*xform_fn*/) override {
|
||||
/* a layer is bounded by lambdas, don't enter them */
|
||||
return this;
|
||||
}
|
||||
|
||||
virtual void attach_envs(ref::brw<Environment> p) override {
|
||||
local_env_->assign_parent(p);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,6 +57,10 @@ namespace xo {
|
|||
return 1;
|
||||
}
|
||||
|
||||
virtual ref::rp<Expression> xform_layer(TransformFn xform_fn) override {
|
||||
return xform_fn(this);
|
||||
}
|
||||
|
||||
virtual void attach_envs(ref::brw<Environment> /*p*/) override {}
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -43,6 +43,10 @@ namespace xo {
|
|||
return 1;
|
||||
}
|
||||
|
||||
virtual ref::rp<Expression> xform_layer(TransformFn xform_fn) override {
|
||||
return xform_fn(this);
|
||||
}
|
||||
|
||||
virtual void attach_envs(ref::brw<Environment> /*p*/) override;
|
||||
|
||||
virtual void display(std::ostream & os) const override;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include "xo/reflect/TypeDescr.hpp"
|
||||
#include "xo/reflect/function/FunctionTdx.hpp"
|
||||
#include "xo/indentlog/print/vector.hpp"
|
||||
#include <map>
|
||||
|
||||
namespace xo {
|
||||
using xo::reflect::TypeDescrBase;
|
||||
|
|
@ -25,10 +26,12 @@ namespace xo {
|
|||
**/
|
||||
|
||||
std::vector<TypeDescr> arg_td_v;
|
||||
arg_td_v.reserve(argv.size());
|
||||
{
|
||||
arg_td_v.reserve(argv.size());
|
||||
|
||||
for (const auto & arg : argv) {
|
||||
arg_td_v.push_back(arg->valuetype());
|
||||
for (const auto & arg : argv) {
|
||||
arg_td_v.push_back(arg->valuetype());
|
||||
}
|
||||
}
|
||||
|
||||
auto function_info
|
||||
|
|
@ -85,6 +88,30 @@ namespace xo {
|
|||
}
|
||||
ss << ")";
|
||||
|
||||
/* regularize local_env+body: make sure exactly one instance
|
||||
* (i.e. with object identity) of a Variable appears
|
||||
* within one layer of a lambda body.
|
||||
*
|
||||
* Here 'layer' means excluding appearance in any nested lambdas
|
||||
* (i.e. whether or not such appearance would resolve to the same
|
||||
* memory location).
|
||||
*
|
||||
* Motivation is to unify Variables that would use the same
|
||||
* binding_path to resolve their runtime location.
|
||||
*/
|
||||
{
|
||||
std::map<std::string, rp<Variable>> var_map;
|
||||
|
||||
for (const auto & arg : local_env_->argv()) {
|
||||
/* each arg name can appear at most once
|
||||
* in a particular lambda's parameter list
|
||||
*/
|
||||
assert(var_map.find(arg->name()) == var_map.end());
|
||||
|
||||
var_map[arg->name()] = arg;
|
||||
}
|
||||
}
|
||||
|
||||
this->type_str_ = ss.str();
|
||||
this->free_var_set_ = this->calc_free_variables();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue