/* file DefineExpr.hpp * * author: Roland Conybeare, Jul 2024 */ #pragma once #include "Expression.hpp" namespace xo { namespace scm { /** @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) * * Promise: * - memory location of @ref lhs_var_ is determined when parent DefineExpr * constructed, and is stable across calls to @ref DefineExpr::assign_lhs_name **/ class DefineExpr : public Expression { public: static rp make(std::string name, rp value); static bp from(bp x) { return bp::from(x); } const std::string & lhs_name() const; const rp & rhs() const { return rhs_; } const rp& lhs_variable() const { return lhs_var_; } 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(bp p) override { rhs_->attach_envs(p); } virtual void display(std::ostream & os) const override; virtual std::uint32_t pretty_print(const ppindentinfo & ppii) const override; protected: /** * **/ DefineExpr(TypeDescr rhs_valuetype, std::string lhs_name, rp rhs); protected: /** symbol name for this definition **/ rp lhs_var_; /** 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); 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 scm*/ } /*namespace xo*/ /* end DefineExpr.hpp */