xo-exprssion: + DefineExpr

This commit is contained in:
Roland Conybeare 2024-08-06 03:20:19 -04:00
commit 9a1a419aef
3 changed files with 228 additions and 0 deletions

View 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 */

View file

@ -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

View 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 */