xo-exprssion: + DefineExpr
This commit is contained in:
parent
e8a590b0d4
commit
9a1a419aef
3 changed files with 228 additions and 0 deletions
128
include/xo/expression/DefineExpr.hpp
Normal file
128
include/xo/expression/DefineExpr.hpp
Normal file
|
|
@ -0,0 +1,128 @@
|
||||||
|
/* file DefineExpr.hpp
|
||||||
|
*
|
||||||
|
* author: Roland Conybeare, Jul 2024
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Expression.hpp"
|
||||||
|
|
||||||
|
namespace xo {
|
||||||
|
namespace ast {
|
||||||
|
/** @class DefineExpr
|
||||||
|
* @brief Provide definition for a constant, variable or function
|
||||||
|
*
|
||||||
|
* At toplevel, introduces a new global variable.
|
||||||
|
* In a nested context,
|
||||||
|
*
|
||||||
|
* def foo = rhsexpr
|
||||||
|
* body...
|
||||||
|
*
|
||||||
|
* is equivalent to
|
||||||
|
*
|
||||||
|
* (lambda (foo) body...)(rhsexpr)
|
||||||
|
**/
|
||||||
|
class DefineExpr : public Expression {
|
||||||
|
public:
|
||||||
|
static rp<DefineExpr> make(std::string name,
|
||||||
|
rp<Expression> value);
|
||||||
|
|
||||||
|
|
||||||
|
static ref::brw<DefineExpr> from(ref::brw<Expression> x) {
|
||||||
|
return ref::brw<DefineExpr>::from(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string & lhs_name() const { return lhs_name_; }
|
||||||
|
const rp<Expression> & rhs() const { return rhs_; }
|
||||||
|
|
||||||
|
std::set<std::string> calc_free_variables() const;
|
||||||
|
|
||||||
|
// ----- Expression -----
|
||||||
|
|
||||||
|
virtual std::set<std::string> get_free_variables() const override {
|
||||||
|
return this->free_var_set_;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::size_t visit_preorder(VisitFn visitor_fn) override {
|
||||||
|
std::size_t n = 1;
|
||||||
|
|
||||||
|
visitor_fn(this);
|
||||||
|
|
||||||
|
n += rhs_->visit_preorder(visitor_fn);
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::size_t visit_layer(VisitFn visitor_fn) override {
|
||||||
|
std::size_t n = 1;
|
||||||
|
|
||||||
|
visitor_fn(this);
|
||||||
|
|
||||||
|
n += this->rhs_->visit_layer(visitor_fn);
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual rp<Expression> xform_layer(TransformFn xform_fn) override {
|
||||||
|
this->rhs_ = this->rhs_->xform_layer(xform_fn);
|
||||||
|
|
||||||
|
return xform_fn(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void attach_envs(ref::brw<Environment> p) override {
|
||||||
|
rhs_->attach_envs(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void display(std::ostream & os) const override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
DefineExpr(TypeDescr rhs_valuetype,
|
||||||
|
std::string lhs_name,
|
||||||
|
rp<Expression> rhs);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/** symbol name for this definition **/
|
||||||
|
std::string lhs_name_;
|
||||||
|
/** right-hand side of definition **/
|
||||||
|
rp<Expression> rhs_;
|
||||||
|
|
||||||
|
/** free variables for this definition **/
|
||||||
|
std::set<std::string> free_var_set_;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @class DefineExprAccess
|
||||||
|
* @brief DefineExpr with writeable members.
|
||||||
|
*
|
||||||
|
* Convenient when scaffolding a parser,
|
||||||
|
* e.g. see xo-parser
|
||||||
|
**/
|
||||||
|
class DefineExprAccess : public DefineExpr {
|
||||||
|
public:
|
||||||
|
static rp<DefineExprAccess> make(std::string lhs_name,
|
||||||
|
rp<Expression> rhs);
|
||||||
|
static rp<DefineExprAccess> make_empty();
|
||||||
|
|
||||||
|
void assign_lhs_name(const std::string & x) {
|
||||||
|
this->lhs_name_ = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
void assign_rhs(const rp<Expression> & x);
|
||||||
|
|
||||||
|
private:
|
||||||
|
DefineExprAccess(TypeDescr rhs_valuetype,
|
||||||
|
std::string lhs_name,
|
||||||
|
rp<Expression> rhs)
|
||||||
|
: DefineExpr(rhs_valuetype,
|
||||||
|
std::move(lhs_name),
|
||||||
|
std::move(rhs))
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
} /*namespace ast*/
|
||||||
|
} /*namespace xo*/
|
||||||
|
|
||||||
|
|
||||||
|
/* end DefineExpr.hpp */
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
set(SELF_LIB xo_expression)
|
set(SELF_LIB xo_expression)
|
||||||
set(SELF_SRCS
|
set(SELF_SRCS
|
||||||
Expression.cpp
|
Expression.cpp
|
||||||
|
DefineExpr.cpp
|
||||||
Apply.cpp
|
Apply.cpp
|
||||||
Lambda.cpp
|
Lambda.cpp
|
||||||
Variable.cpp
|
Variable.cpp
|
||||||
|
|
|
||||||
99
src/expression/DefineExpr.cpp
Normal file
99
src/expression/DefineExpr.cpp
Normal file
|
|
@ -0,0 +1,99 @@
|
||||||
|
/* file DefineExpr.cpp
|
||||||
|
*
|
||||||
|
* author: Roland Conybeare
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "DefineExpr.hpp"
|
||||||
|
|
||||||
|
namespace xo {
|
||||||
|
namespace ast {
|
||||||
|
rp<DefineExpr>
|
||||||
|
DefineExpr::make(std::string lhs_name,
|
||||||
|
rp<Expression> rhs)
|
||||||
|
{
|
||||||
|
TypeDescr rhs_valuetype = nullptr;
|
||||||
|
|
||||||
|
if (rhs)
|
||||||
|
rhs_valuetype = rhs->valuetype();
|
||||||
|
|
||||||
|
return new DefineExpr(rhs_valuetype,
|
||||||
|
std::move(lhs_name),
|
||||||
|
std::move(rhs));
|
||||||
|
} /*make*/
|
||||||
|
|
||||||
|
DefineExpr::DefineExpr(TypeDescr rhs_valuetype,
|
||||||
|
std::string lhs_name,
|
||||||
|
rp<Expression> rhs)
|
||||||
|
: Expression(exprtype::define, rhs_valuetype),
|
||||||
|
lhs_name_{std::move(lhs_name)},
|
||||||
|
rhs_{std::move(rhs)}
|
||||||
|
{
|
||||||
|
this->free_var_set_ = this->calc_free_variables();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<std::string>
|
||||||
|
DefineExpr::calc_free_variables() const
|
||||||
|
{
|
||||||
|
std::set<std::string> retval;
|
||||||
|
|
||||||
|
if (rhs_)
|
||||||
|
retval = rhs_->get_free_variables();
|
||||||
|
|
||||||
|
/* but remove this variable */
|
||||||
|
if (!this->lhs_name().empty())
|
||||||
|
retval.erase(this->lhs_name());
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
} /*calc_free_variables*/
|
||||||
|
|
||||||
|
void
|
||||||
|
DefineExpr::display(std::ostream & os) const {
|
||||||
|
os << "<Define"
|
||||||
|
<< xtag("name", lhs_name_)
|
||||||
|
<< xtag("rhs", rhs_)
|
||||||
|
<< ">";
|
||||||
|
} /*display*/
|
||||||
|
|
||||||
|
// ----- DefineExprAccess -----
|
||||||
|
|
||||||
|
rp<DefineExprAccess>
|
||||||
|
DefineExprAccess::make(std::string lhs_name,
|
||||||
|
rp<Expression> rhs)
|
||||||
|
{
|
||||||
|
TypeDescr rhs_valuetype = nullptr;
|
||||||
|
|
||||||
|
if (rhs)
|
||||||
|
rhs_valuetype = rhs->valuetype();
|
||||||
|
|
||||||
|
return new DefineExprAccess(rhs_valuetype,
|
||||||
|
std::move(lhs_name),
|
||||||
|
std::move(rhs));
|
||||||
|
}
|
||||||
|
|
||||||
|
rp<DefineExprAccess>
|
||||||
|
DefineExprAccess::make_empty()
|
||||||
|
{
|
||||||
|
return new DefineExprAccess(nullptr /*rhs_valuetype*/,
|
||||||
|
"" /*lhs_name*/,
|
||||||
|
nullptr /*rhs*/);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DefineExprAccess::assign_rhs(const rp<Expression> & x)
|
||||||
|
{
|
||||||
|
assert(x);
|
||||||
|
|
||||||
|
this->rhs_ = x;
|
||||||
|
|
||||||
|
if (x) {
|
||||||
|
this->assign_valuetype(x->valuetype());
|
||||||
|
}
|
||||||
|
|
||||||
|
this->free_var_set_ = this->calc_free_variables();
|
||||||
|
}
|
||||||
|
|
||||||
|
} /*namespace ast*/
|
||||||
|
} /*namespace xo*/
|
||||||
|
|
||||||
|
|
||||||
|
/* end DefineExpr.cpp */
|
||||||
Loading…
Add table
Add a link
Reference in a new issue