/** @file IfExpr.hpp * * Author: Roland Conybeare **/ #pragma once #include "Expression.hpp" #include #include //#include namespace xo { namespace ast { /** @class IfExpr * @brief abstract syntax tree for a function definition * **/ class IfExpr : public Expression { public: using TypeDescr = xo::reflect::TypeDescr; public: /** create expression for conditional execution of * @p when_true or @p when_false, depending on result * of evaluating expression @p test **/ static rp make(const rp & test, const rp & when_true, const rp & when_false); /** downcast from Expression **/ static bp from(bp x) { return bp::from(x); } const rp & test() const { return test_; } const rp & when_true() const { return when_true_; } const rp & when_false() const { return when_false_; } // ----- Expression ----- virtual std::set get_free_variables() const override { std::set retval = test_->get_free_variables(); std::set free_vars; free_vars = when_true_->get_free_variables(); for (const auto & s : free_vars) retval.insert(s); free_vars = when_false_->get_free_variables(); for (const auto & s : free_vars) retval.insert(s); return retval; } virtual std::size_t visit_preorder(VisitFn visitor_fn) override { std::size_t n = 1; 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 std::size_t visit_layer(VisitFn visitor_fn) override { std::size_t n = 1; visitor_fn(this); n += this->test_->visit_layer(visitor_fn); n += this->when_true_->visit_layer(visitor_fn); n += this->when_false_->visit_layer(visitor_fn); return n; } virtual rp 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(bp p) override { test_->attach_envs(p); when_true_->attach_envs(p); when_false_->attach_envs(p); } #ifdef NOT_USING virtual std::int32_t find_free_vars(std::set> * p_set) override { return (test_->find_free_vars(p_set) + when_true_->find_free_vars(p_set) + when_false_->find_free_vars(p_set)); } #endif virtual void display(std::ostream & os) const override; private: /** * @p ifexpr_type type for value produced by if-expression. * same as both when_true->valuetype() and * when_false->valuetype(). * @p test test-expression; always execute * @p when_true then-branch; executes only when test succeeds * @p when_false else-branch; executes only when test fails **/ IfExpr(TypeDescr ifexpr_type, rp test, rp when_true, rp when_false) : Expression(exprtype::ifexpr, ifexpr_type), test_{std::move(test)}, when_true_{std::move(when_true)}, when_false_{std::move(when_false)} {} private: /** if: * (if x y z) * * executes x; if true execute y; otherwise execute z **/ rp test_; rp when_true_; rp when_false_; }; /*IfExpr*/ inline rp make_ifexpr(const rp & test, const rp & when_true, const rp & when_false) { return IfExpr::make(test, when_true, when_false); } } /*namespace ast*/ } /*namespace xo*/ /** end IfExpr.hpp **/