diff --git a/include/xo/expression/GeneralizedExpression.hpp b/include/xo/expression/GeneralizedExpression.hpp index 585b22fb..1d513a2d 100644 --- a/include/xo/expression/GeneralizedExpression.hpp +++ b/include/xo/expression/GeneralizedExpression.hpp @@ -38,7 +38,6 @@ namespace xo { /** pretty printing support. See [xo-indentlog/xo/indentlog/pretty.hpp] **/ virtual std::uint32_t pretty_print(const ppindentinfo & ppii) const = 0; - protected: /** useful when scaffolding expressions in a parser **/ void assign_valuetype(TypeDescr x) { valuetype_ = x; } diff --git a/include/xo/expression/IfExpr.hpp b/include/xo/expression/IfExpr.hpp index 946fda9d..462a049f 100644 --- a/include/xo/expression/IfExpr.hpp +++ b/include/xo/expression/IfExpr.hpp @@ -104,7 +104,7 @@ namespace xo { virtual void display(std::ostream & os) const override; virtual std::uint32_t pretty_print(const ppindentinfo & ppi) const override; - private: + protected: /** * @p ifexpr_type type for value produced by if-expression. * same as both when_true->valuetype() and @@ -122,7 +122,13 @@ namespace xo { when_true_{std::move(when_true)}, when_false_{std::move(when_false)} {} - private: + static TypeDescr check_consistent_valuetype(const rp & when_true, + const rp & when_false); + + /** determine if-expr valuetype **/ + void establish_valuetype(); + + protected: /** if: * (if x y z) * @@ -140,6 +146,28 @@ namespace xo { { return IfExpr::make(test, when_true, when_false); } + + class IfExprAccess : public IfExpr { + public: + static rp make(rp test, + rp when_true, + rp when_false); + static rp make_empty(); + + void assign_test(rp x) { test_ = std::move(x); } + void assign_when_true(rp x); + void assign_when_false(rp x); + + private: + IfExprAccess(TypeDescr ifexpr_type, + rp test, + rp when_true, + rp when_false) + : IfExpr(ifexpr_type, + std::move(test), + std::move(when_true), + std::move(when_false)) {} + }; } /*namespace ast*/ } /*namespace xo*/ diff --git a/src/expression/IfExpr.cpp b/src/expression/IfExpr.cpp index f6377ce3..7027f433 100644 --- a/src/expression/IfExpr.cpp +++ b/src/expression/IfExpr.cpp @@ -7,6 +7,21 @@ namespace xo { namespace ast { + auto IfExpr::check_consistent_valuetype(const rp & when_true, + const rp & when_false) -> TypeDescr + { + if (when_true->valuetype() != when_false->valuetype()) + return nullptr; + + return when_true->valuetype(); + } + + void IfExpr::establish_valuetype() + { + if (this->when_true_.get() && this->when_false_.get()) + this->assign_valuetype(check_consistent_valuetype(this->when_true_, this->when_false_)); + } + rp IfExpr::make(const rp & test, const rp & when_true, @@ -36,9 +51,10 @@ namespace xo { IfExpr::display(std::ostream & os) const { os << ""; + << xtag("when_true", when_true_); + if (when_false_) + os << xtag("when_false", when_false_); + os << ">"; } /*display*/ std::uint32_t @@ -48,6 +64,37 @@ namespace xo { refrtag("when_true", when_true_), refrtag("when_false", when_false_)); } + + rp + IfExprAccess::make(rp test, + rp when_true, + rp when_false) + { + auto ifexpr_type = check_consistent_valuetype(when_true, when_false); + + return new IfExprAccess(ifexpr_type, std::move(test), std::move(when_true), std::move(when_false)); + } + + rp + IfExprAccess::make_empty() + { + return new IfExprAccess(nullptr /*ifexpr_valuetype*/, + nullptr /*test*/, + nullptr /*when_true*/, + nullptr /*when_false*/); + } + + void + IfExprAccess::assign_when_true(rp x) + { + this->when_true_ = std::move(x); + } + + void + IfExprAccess::assign_when_false(rp x) + { + this->when_false_ = std::move(x); + } } /*namespace ast*/ } /*namespace xo*/