From 9a1a419aef300afc86cc4bac86590639e81353f3 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Tue, 6 Aug 2024 03:20:19 -0400 Subject: [PATCH] xo-exprssion: + DefineExpr --- include/xo/expression/DefineExpr.hpp | 128 +++++++++++++++++++++++++++ src/expression/CMakeLists.txt | 1 + src/expression/DefineExpr.cpp | 99 +++++++++++++++++++++ 3 files changed, 228 insertions(+) create mode 100644 include/xo/expression/DefineExpr.hpp create mode 100644 src/expression/DefineExpr.cpp diff --git a/include/xo/expression/DefineExpr.hpp b/include/xo/expression/DefineExpr.hpp new file mode 100644 index 00000000..e7ffce65 --- /dev/null +++ b/include/xo/expression/DefineExpr.hpp @@ -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 make(std::string name, + rp value); + + + static ref::brw from(ref::brw x) { + return ref::brw::from(x); + } + + const std::string & lhs_name() const { return lhs_name_; } + const rp & rhs() const { return rhs_; } + + std::set calc_free_variables() const; + + // ----- Expression ----- + + virtual std::set 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 xform_layer(TransformFn xform_fn) override { + this->rhs_ = this->rhs_->xform_layer(xform_fn); + + return xform_fn(this); + } + + virtual void attach_envs(ref::brw p) override { + rhs_->attach_envs(p); + } + + virtual void display(std::ostream & os) const override; + + protected: + /** + * + **/ + DefineExpr(TypeDescr rhs_valuetype, + std::string lhs_name, + rp rhs); + + protected: + /** symbol name for this definition **/ + std::string lhs_name_; + /** right-hand side of definition **/ + rp rhs_; + + /** free variables for this definition **/ + std::set 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 make(std::string lhs_name, + rp rhs); + static rp make_empty(); + + void assign_lhs_name(const std::string & x) { + this->lhs_name_ = x; + } + + void assign_rhs(const rp & x); + + private: + DefineExprAccess(TypeDescr rhs_valuetype, + std::string lhs_name, + rp rhs) + : DefineExpr(rhs_valuetype, + std::move(lhs_name), + std::move(rhs)) + {} + }; + + } /*namespace ast*/ +} /*namespace xo*/ + + +/* end DefineExpr.hpp */ diff --git a/src/expression/CMakeLists.txt b/src/expression/CMakeLists.txt index 50edec01..32520c85 100644 --- a/src/expression/CMakeLists.txt +++ b/src/expression/CMakeLists.txt @@ -3,6 +3,7 @@ set(SELF_LIB xo_expression) set(SELF_SRCS Expression.cpp + DefineExpr.cpp Apply.cpp Lambda.cpp Variable.cpp diff --git a/src/expression/DefineExpr.cpp b/src/expression/DefineExpr.cpp new file mode 100644 index 00000000..1c67188c --- /dev/null +++ b/src/expression/DefineExpr.cpp @@ -0,0 +1,99 @@ +/* file DefineExpr.cpp + * + * author: Roland Conybeare + */ + +#include "DefineExpr.hpp" + +namespace xo { + namespace ast { + rp + DefineExpr::make(std::string lhs_name, + rp 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 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 + DefineExpr::calc_free_variables() const + { + std::set 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 << ""; + } /*display*/ + + // ----- DefineExprAccess ----- + + rp + DefineExprAccess::make(std::string lhs_name, + rp 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::make_empty() + { + return new DefineExprAccess(nullptr /*rhs_valuetype*/, + "" /*lhs_name*/, + nullptr /*rhs*/); + } + + void + DefineExprAccess::assign_rhs(const rp & 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 */