/** @file DIfElseExpr.cpp * * @author Roland Conybeare, Jan 2026 **/ #include "DIfElseExpr.hpp" #include "detail/IExpression_DIfElseExpr.hpp" #include #include #include #include namespace xo { using xo::mm::AGCObject; using xo::print::APrintable; using xo::reflect::typeseq; using xo::facet::FacetRegistry; namespace scm { DIfElseExpr::DIfElseExpr(TypeRef ifexpr_tref, obj test_expr, obj when_true, obj when_false) : typeref_{ifexpr_tref}, test_{test_expr}, when_true_{when_true}, when_false_{when_false} {} obj DIfElseExpr::make(obj mm, obj test, obj when_true, obj when_false) { return obj (_make(mm, test, when_true, when_false)); } DIfElseExpr * DIfElseExpr::_make(obj mm, obj test, obj when_true, obj when_false) { void * mem = mm.alloc(typeseq::id(), sizeof(DIfElseExpr)); // just crete typevar here, then rely on type checking // later auto prefix = TypeRef::prefix_type::from_chars("if"); TypeRef tref = TypeRef::dwim(prefix, nullptr); return new (mem) DIfElseExpr(tref, test, when_true, when_false); } obj DIfElseExpr::make_empty(obj mm) { return obj(_make_empty(mm)); } DIfElseExpr * DIfElseExpr::_make_empty(obj mm) { return _make(mm, obj() /*test*/, obj() /*when_true*/, obj() /*when_false*/); } void DIfElseExpr::assign_valuetype(TypeDescr td) noexcept { typeref_.resolve(td); } // GCObject facet std::size_t DIfElseExpr::shallow_size() const noexcept { return sizeof(DIfElseExpr); } DIfElseExpr * DIfElseExpr::shallow_copy(obj mm) const noexcept { DIfElseExpr * copy = (DIfElseExpr *)mm.alloc_copy((std::byte *)this); if (copy) *copy = *this; return copy; } std::size_t DIfElseExpr::forward_children(obj gc) noexcept { typeref_.forward_children(gc); // GC needs to locate AGCObject iface for each member. { auto gco = test_.to_facet(); gc.forward_inplace(gco.iface(), (void **)&(test_.data_)); } { auto gco = when_true_.to_facet(); gc.forward_inplace(gco.iface(), (void **)&(when_true_.data_)); } { auto gco = when_false_.to_facet(); gc.forward_inplace(gco.iface(), (void **)&(when_false_.data_)); } return shallow_size(); } // ----- printable facet ----- bool DIfElseExpr::pretty(const ppindentinfo & ppii) const { auto test = FacetRegistry::instance().try_variant(test_); auto when_true = FacetRegistry::instance().try_variant(when_true_); auto when_false = FacetRegistry::instance().try_variant(when_false_); bool test_present = test; bool when_true_present = when_true; bool when_false_present = when_false; return ppii.pps()->pretty_struct (ppii, "DIfElseExpr", refrtag("typeref", typeref_), refrtag("test", test, test_present), refrtag("when_true", when_true, when_true_present), refrtag("when_false", when_false, when_false_present)); } // ---------------------------------------------------------------- #ifdef NOPE 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, const rp & when_false) { /** TODO: verify test returns _boolean_ type **/ if (when_true->valuetype() != when_false->valuetype()) { throw std::runtime_error (tostr("IfExpr::make:" " types {T1,T2} found for branches of if-expr" " where equal types expected", xtag("T1", when_true->valuetype()->canonical_name()), xtag("T2", when_false->valuetype()->canonical_name()))); } /* arbitrary choice here */ auto ifexpr_type = when_true->valuetype(); return new IfExpr(ifexpr_type, test, when_true, when_false); } /*make*/ void IfExpr::display(std::ostream & os) const { os << ""; } /*display*/ std::uint32_t IfExpr::pretty_print(const ppindentinfo & ppii) const { return ppii.pps()->pretty_struct(ppii, "IfExpr"); #ifdef NOT_YET return ppii.pps()->pretty_struct(ppii, "IfExpr", refrtag("test", test_), refrtag("when_true", when_true_), refrtag("when_false", when_false_)); #endif } 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); } #endif } /*namespace scm*/ } /*namespace xo*/ /* end DIfElseExpr.cpp */