/** @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 ref::rp make(const ref::rp & test, const ref::rp & when_true, const ref::rp & when_false); /** downcast from Expression **/ static ref::brw from(ref::brw x) { return ref::brw::from(x); } const ref::rp & test() const { return test_; } const ref::rp & when_true() const { return when_true_; } const ref::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 ref::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(ref::brw 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, const ref::rp & test, const ref::rp & when_true, const ref::rp & when_false) : Expression(exprtype::ifexpr, ifexpr_type), test_{test}, when_true_{when_true}, when_false_{when_false} {} private: /** if: * (if x y z) * * executes x; if true execute y; otherwise execute z **/ ref::rp test_; ref::rp when_true_; ref::rp when_false_; }; /*IfExpr*/ inline ref::rp make_ifexpr(const ref::rp & test, const ref::rp & when_true, const ref::rp & when_false) { return IfExpr::make(test, when_true, when_false); } } /*namespace ast*/ } /*namespace xo*/ /** end IfExpr.hpp **/