xo-expression2: + DIfElseExpr + utest

This commit is contained in:
Roland Conybeare 2026-01-27 10:09:26 -05:00
commit 0fcb548587
15 changed files with 1027 additions and 3 deletions

View file

@ -150,6 +150,32 @@ xo_add_genfacetimpl(
# ----------------------------------------------------------------
# note: manual target; generated code committed to git
xo_add_genfacetimpl(
TARGET xo-expression2-facetimpl-expression-ifelseexpr
FACET_PKG xo_expression2
FACET Expression
REPR IfElseExpr
INPUT idl/IExpression_DIfElseExpr.json5
OUTPUT_HPP_DIR include/xo/expression2
OUTPUT_IMPL_SUBDIR detail
OUTPUT_CPP_DIR src/expression2
)
# note: manual target; generated code committed to git
xo_add_genfacetimpl(
TARGET xo-expression2-facetimpl-printable-ifelseexpr
FACET_PKG xo_printable2
FACET Printable
REPR IfElseExpr
INPUT idl/IPrintable_DIfElseExpr.json5
OUTPUT_HPP_DIR include/xo/expression2
OUTPUT_IMPL_SUBDIR detail
OUTPUT_CPP_DIR src/expression2
)
# ----------------------------------------------------------------
# note: manual target; generated code committed to git
xo_add_genfacetimpl(
TARGET xo-expression2-facetimpl-gcobject-uniquestring

View file

@ -0,0 +1,12 @@
{
mode: "implementation",
includes: [ "\"Expression.hpp\"" ],
local_types: [ ],
namespace1: "xo",
namespace2: "scm",
facet_idl: "idl/Expression.json5",
brief: "provide AExpression interface for DIfElseExpr state",
using_doxygen: true,
repr: "DIfElseExpr",
doc: ["doc for IExpression+DIfElseExpr" ],
}

View file

@ -0,0 +1,13 @@
{
mode: "implementation",
includes: [ "<xo/printable2/Printable.hpp>",
"<xo/printable2/detail/IPrintable_Xfer.hpp>" ],
local_types: [ ],
namespace1: "xo",
namespace2: "scm",
facet_idl: "idl/Printable.json5",
brief: "provide APrintable interface for DIfElseExpr",
using_doxygen: true,
repr: "DIfElseExpr",
doc: [ "implement APrintable for DIfElseExpr" ],
}

View file

@ -0,0 +1,230 @@
/** @file DIfElseExpr.hpp
*
* @author Roland Conybeare, Jan 2026
**/
#pragma once
#include "Expression.hpp"
#include "TypeRef.hpp"
#include "exprtype.hpp"
#include <xo/alloc2/Allocator.hpp>
//#include <vector>
#include <string>
//#include <cstdint>
namespace xo {
namespace scm {
/** @class DIfExpr
* @brief abstract syntax tree for a function definition
**/
class DIfElseExpr {
public:
using AAllocator = xo::mm::AAllocator;
using TypeDescr = xo::reflect::TypeDescr;
using ppindentinfo = xo::print::ppindentinfo;
public:
/** @defgroup scm-ifelseexpr-constructors **/
///@{
/**
* @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
**/
DIfElseExpr(TypeRef ifexpr_type,
obj<AExpression> test_expr,
obj<AExpression> when_true,
obj<AExpression> when_false);
/** create if-else expression using memory from @p mm.
* @p when_false can be null
**/
static obj<AExpression,DIfElseExpr> make(obj<AAllocator> mm,
obj<AExpression> test,
obj<AExpression> when_true,
obj<AExpression> when_false);
/** create expression for conditional execution of
* @p when_true or @p when_false, depending on result
* of evaluating expression @p test
**/
static DIfElseExpr * _make(obj<AAllocator> mm,
obj<AExpression> test,
obj<AExpression> when_true,
obj<AExpression> when_false);
///@}
/** @defgroup scm-ifelseexpr-access-methods **/
///@{
obj<AExpression> test() const noexcept { return test_; }
obj<AExpression> when_true() const noexcept { return when_true_; }
obj<AExpression> when_false() const noexcept { return when_false_; }
///@}
/** @defgroup scm-ifelseexpr-expression-facet **/
///@{
exprtype extype() const noexcept { return exprtype::ifexpr; }
TypeRef typeref() const noexcept { return typeref_; }
TypeDescr valuetype() const noexcept { return typeref_.td(); }
void assign_valuetype(TypeDescr td) noexcept;
///@}
/** @defgroup scm-ifelseexpr-printable-facet **/
///@{
bool pretty(const ppindentinfo & ppii) const;
///@}
#ifdef NOT_YET
virtual std::set<std::string> get_free_variables() const override {
std::set<std::string> retval = test_->get_free_variables();
std::set<std::string> 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<Expression> 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<SymbolTable> p) override {
test_->attach_envs(p);
when_true_->attach_envs(p);
when_false_->attach_envs(p);
}
#endif
#ifdef NOT_USING
virtual std::int32_t find_free_vars(std::set<bp<Variable>> * 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
#ifdef NOPE
virtual void display(std::ostream & os) const override;
virtual std::uint32_t pretty_print(const ppindentinfo & ppi) const override;
#endif
protected:
#ifdef NOT_YET
/**
* @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<Expression> test,
rp<Expression> when_true,
rp<Expression> when_false)
: Expression(exprtype::ifexpr, ifexpr_type),
test_{std::move(test)},
when_true_{std::move(when_true)},
when_false_{std::move(when_false)} {}
static TypeDescr check_consistent_valuetype(const rp<Expression> & when_true,
const rp<Expression> & when_false);
/** determine if-expr valuetype **/
void establish_valuetype();
#endif
private:
/** expression value always has type consistent
* with this description
**/
TypeRef typeref_;
/** if:
* (if x y z)
*
* executes x; if true execute y; otherwise execute z
**/
obj<AExpression> test_;
obj<AExpression> when_true_;
obj<AExpression> when_false_;
}; /*IfExpr*/
#ifdef NOPE
inline rp<IfExpr>
make_ifexpr(const rp<Expression> & test,
const rp<Expression> & when_true,
const rp<Expression> & when_false)
{
return IfExpr::make(test, when_true, when_false);
}
class IfExprAccess : public IfExpr {
public:
static rp<IfExprAccess> make(rp<Expression> test,
rp<Expression> when_true,
rp<Expression> when_false);
static rp<IfExprAccess> make_empty();
void assign_test(rp<Expression> x) { test_ = std::move(x); }
void assign_when_true(rp<Expression> x);
void assign_when_false(rp<Expression> x);
private:
IfExprAccess(TypeDescr ifexpr_type,
rp<Expression> test,
rp<Expression> when_true,
rp<Expression> when_false)
: IfExpr(ifexpr_type,
std::move(test),
std::move(when_true),
std::move(when_false)) {}
};
#endif
} /*namespace scm*/
} /*namespace xo*/
/* end DIfElseExpr.hpp */

View file

@ -0,0 +1,66 @@
/** @file IExpression_DIfElseExpr.hpp
*
* Generated automagically from ingredients:
* 1. code generator:
* [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet]
* arguments:
* --input [idl/IExpression_DIfElseExpr.json5]
* 2. jinja2 template for abstract facet .hpp file:
* [iface_facet_repr.hpp.j2]
* 3. idl for facet methods
* [idl/IExpression_DIfElseExpr.json5]
**/
#pragma once
#include "Expression.hpp"
#include "Expression.hpp"
#include "DIfElseExpr.hpp"
namespace xo { namespace scm { class IExpression_DIfElseExpr; } }
namespace xo {
namespace facet {
template <>
struct FacetImplementation<xo::scm::AExpression,
xo::scm::DIfElseExpr>
{
using ImplType = xo::scm::IExpression_Xfer
<xo::scm::DIfElseExpr,
xo::scm::IExpression_DIfElseExpr>;
};
}
}
namespace xo {
namespace scm {
/** @class IExpression_DIfElseExpr
**/
class IExpression_DIfElseExpr {
public:
/** @defgroup scm-expression-difelseexpr-type-traits **/
///@{
using TypeDescr = xo::scm::AExpression::TypeDescr;
using Copaque = xo::scm::AExpression::Copaque;
using Opaque = xo::scm::AExpression::Opaque;
///@}
/** @defgroup scm-expression-difelseexpr-methods **/
///@{
// const methods
/** expression type (constant | apply | ..) **/
static exprtype extype(const DIfElseExpr & self) noexcept;
/** placeholder for type giving possible values for this expression **/
static TypeRef typeref(const DIfElseExpr & self) noexcept;
/** type giving possible values for this expression. Maybe null before typecheck **/
static TypeDescr valuetype(const DIfElseExpr & self) noexcept;
// non-const methods
/** assing to valuetype member. Useful when scaffolding expressions **/
static void assign_valuetype(DIfElseExpr & self, TypeDescr td) noexcept;
///@}
};
} /*namespace scm*/
} /*namespace xo*/
/* end */

View file

@ -0,0 +1,62 @@
/** @file IPrintable_DIfElseExpr.hpp
*
* Generated automagically from ingredients:
* 1. code generator:
* [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet]
* arguments:
* --input [idl/IPrintable_DIfElseExpr.json5]
* 2. jinja2 template for abstract facet .hpp file:
* [iface_facet_repr.hpp.j2]
* 3. idl for facet methods
* [idl/IPrintable_DIfElseExpr.json5]
**/
#pragma once
#include "Printable.hpp"
#include <xo/printable2/Printable.hpp>
#include <xo/printable2/detail/IPrintable_Xfer.hpp>
#include "DIfElseExpr.hpp"
namespace xo { namespace scm { class IPrintable_DIfElseExpr; } }
namespace xo {
namespace facet {
template <>
struct FacetImplementation<xo::print::APrintable,
xo::scm::DIfElseExpr>
{
using ImplType = xo::print::IPrintable_Xfer
<xo::scm::DIfElseExpr,
xo::scm::IPrintable_DIfElseExpr>;
};
}
}
namespace xo {
namespace scm {
/** @class IPrintable_DIfElseExpr
**/
class IPrintable_DIfElseExpr {
public:
/** @defgroup scm-printable-difelseexpr-type-traits **/
///@{
using ppindentinfo = xo::print::APrintable::ppindentinfo;
using Copaque = xo::print::APrintable::Copaque;
using Opaque = xo::print::APrintable::Opaque;
///@}
/** @defgroup scm-printable-difelseexpr-methods **/
///@{
// const methods
/** Pretty-printing support for this object.
See [xo-indentlog/xo/indentlog/pretty.hpp] **/
static bool pretty(const DIfElseExpr & self, const ppindentinfo & ppii);
// non-const methods
///@}
};
} /*namespace scm*/
} /*namespace xo*/
/* end */

View file

@ -38,9 +38,9 @@ namespace xo {
#endif
/** variable reference **/
variable,
#ifdef NOT_YET
/** if-then-else **/
ifexpr,
#ifdef NOT_YET
/** sequence **/
sequence,
/** type conversion **/

View file

@ -8,6 +8,7 @@ set(SELF_SRCS
DVariable.cpp
DDefineExpr.cpp
DApplyExpr.cpp
DIfElseExpr.cpp
TypeRef.cpp
@ -25,6 +26,9 @@ set(SELF_SRCS
IExpression_DApplyExpr.cpp
IPrintable_DApplyExpr.cpp
IExpression_DIfElseExpr.cpp
IPrintable_DIfElseExpr.cpp
DLocalSymtab.cpp
DGlobalSymtab.cpp

View file

@ -1,5 +1,5 @@
/** @file DDefineExpr.cpp
*
*
* @author Roland Conybeare, Jan 2026
**/

View file

@ -0,0 +1,184 @@
/** @file DIfElseExpr.cpp
*
* @author Roland Conybeare, Jan 2026
**/
#include "DIfElseExpr.hpp"
#include "detail/IExpression_DIfElseExpr.hpp"
#include <xo/printable2/Printable.hpp>
#include <xo/facet/FacetRegistry.hpp>
#include <xo/reflectutil/typeseq.hpp>
namespace xo {
using xo::print::APrintable;
using xo::reflect::typeseq;
using xo::facet::FacetRegistry;
namespace scm {
DIfElseExpr::DIfElseExpr(TypeRef ifexpr_tref,
obj<AExpression> test_expr,
obj<AExpression> when_true,
obj<AExpression> when_false)
: typeref_{ifexpr_tref},
test_{test_expr},
when_true_{when_true},
when_false_{when_false}
{}
obj<AExpression,DIfElseExpr>
DIfElseExpr::make(obj<AAllocator> mm,
obj<AExpression> test,
obj<AExpression> when_true,
obj<AExpression> when_false)
{
return obj<AExpression,DIfElseExpr>
(_make(mm,
test, when_true, when_false));
}
DIfElseExpr *
DIfElseExpr::_make(obj<AAllocator> mm,
obj<AExpression> test,
obj<AExpression> when_true,
obj<AExpression> when_false)
{
void * mem = mm.alloc(typeseq::id<DIfElseExpr>(),
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);
}
void
DIfElseExpr::assign_valuetype(TypeDescr td) noexcept
{
typeref_.resolve(td);
}
bool
DIfElseExpr::pretty(const ppindentinfo & ppii) const
{
auto test
= FacetRegistry::instance().try_variant<APrintable,
AExpression>(test_);
auto when_true
= FacetRegistry::instance().try_variant<APrintable,
AExpression>(when_true_);
auto when_false
= FacetRegistry::instance().try_variant<APrintable,
AExpression>(when_false_);
return ppii.pps()->pretty_struct
(ppii,
"DIfElseExpr",
refrtag("typeref", typeref_),
refrtag("test", test),
refrtag("when_true", when_true),
refrtag("when_false", when_false));
}
// ----------------------------------------------------------------
#ifdef NOPE
auto IfExpr::check_consistent_valuetype(const rp<Expression> & when_true,
const rp<Expression> & 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>
IfExpr::make(const rp<Expression> & test,
const rp<Expression> & when_true,
const rp<Expression> & 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 << "<IfExpr"
<< xtag("test", test_)
<< xtag("when_true", when_true_);
if (when_false_)
os << xtag("when_false", when_false_);
os << ">";
} /*display*/
std::uint32_t
IfExpr::pretty_print(const ppindentinfo & ppii) const {
return ppii.pps()->pretty_struct(ppii, "IfExpr",
refrtag("test", test_),
refrtag("when_true", when_true_),
refrtag("when_false", when_false_));
}
rp<IfExprAccess>
IfExprAccess::make(rp<Expression> test,
rp<Expression> when_true,
rp<Expression> 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>
IfExprAccess::make_empty()
{
return new IfExprAccess(nullptr /*ifexpr_valuetype*/,
nullptr /*test*/,
nullptr /*when_true*/,
nullptr /*when_false*/);
}
void
IfExprAccess::assign_when_true(rp<Expression> x)
{
this->when_true_ = std::move(x);
}
void
IfExprAccess::assign_when_false(rp<Expression> x)
{
this->when_false_ = std::move(x);
}
#endif
} /*namespace scm*/
} /*namespace xo*/
/* end DIfElseExpr.cpp */

View file

@ -0,0 +1,45 @@
/** @file IExpression_DIfElseExpr.cpp
*
* Generated automagically from ingredients:
* 1. code generator:
* [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet]
* arguments:
* --input [idl/IExpression_DIfElseExpr.json5]
* 2. jinja2 template for abstract facet .hpp file:
* [iface_facet_any.hpp.j2]
* 3. idl for facet methods
* [idl/IExpression_DIfElseExpr.json5]
**/
#include "detail/IExpression_DIfElseExpr.hpp"
namespace xo {
namespace scm {
auto
IExpression_DIfElseExpr::extype(const DIfElseExpr & self) noexcept -> exprtype
{
return self.extype();
}
auto
IExpression_DIfElseExpr::typeref(const DIfElseExpr & self) noexcept -> TypeRef
{
return self.typeref();
}
auto
IExpression_DIfElseExpr::valuetype(const DIfElseExpr & self) noexcept -> TypeDescr
{
return self.valuetype();
}
auto
IExpression_DIfElseExpr::assign_valuetype(DIfElseExpr & self, TypeDescr td) noexcept -> void
{
self.assign_valuetype(td);
}
} /*namespace scm*/
} /*namespace xo*/
/* end IExpression_DIfElseExpr.cpp */

View file

@ -0,0 +1,28 @@
/** @file IPrintable_DIfElseExpr.cpp
*
* Generated automagically from ingredients:
* 1. code generator:
* [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet]
* arguments:
* --input [idl/IPrintable_DIfElseExpr.json5]
* 2. jinja2 template for abstract facet .hpp file:
* [iface_facet_any.hpp.j2]
* 3. idl for facet methods
* [idl/IPrintable_DIfElseExpr.json5]
**/
#include "detail/IPrintable_DIfElseExpr.hpp"
namespace xo {
namespace scm {
auto
IPrintable_DIfElseExpr::pretty(const DIfElseExpr & self, const ppindentinfo & ppii) -> bool
{
return self.pretty(ppii);
}
} /*namespace scm*/
} /*namespace xo*/
/* end IPrintable_DIfElseExpr.cpp */

View file

@ -20,6 +20,9 @@
#include <xo/expression2/detail/IExpression_DApplyExpr.hpp>
#include <xo/expression2/detail/IPrintable_DApplyExpr.hpp>
#include <xo/expression2/detail/IExpression_DIfElseExpr.hpp>
#include <xo/expression2/detail/IPrintable_DIfElseExpr.hpp>
#include <xo/gc/detail/AGCObject.hpp>
#include <xo/printable2/detail/APrintable.hpp>
#include <xo/facet/FacetRegistry.hpp>
@ -44,7 +47,8 @@ namespace xo {
// +- Constant
// +- Variable
// +- DefineExpr
// \- ApplyExpr
// +- ApplyExpr
// \- IfElseExpr
FacetRegistry::register_impl<AExpression, DConstant>();
FacetRegistry::register_impl<APrintable, DConstant>();
@ -58,11 +62,15 @@ namespace xo {
FacetRegistry::register_impl<AExpression, DApplyExpr>();
FacetRegistry::register_impl<APrintable, DApplyExpr>();
FacetRegistry::register_impl<AExpression, DIfElseExpr>();
FacetRegistry::register_impl<APrintable, DIfElseExpr>();
log && log(xtag("DUniqueString.tseq", typeseq::id<DUniqueString>()));
log && log(xtag("DDefineExpr.tseq", typeseq::id<DDefineExpr>()));
log && log(xtag("DVariable.tseq", typeseq::id<DVariable>()));
log && log(xtag("DConstant.tseq", typeseq::id<DConstant>()));
log && log(xtag("DApplyExpr.tseq", typeseq::id<DApplyExpr>()));
log && log(xtag("DIfElseExpr.tseq", typeseq::id<DIfElseExpr>()));
log && log(xtag("AExpression.tqseq", typeseq::id<AExpression>()));

View file

@ -9,6 +9,7 @@ set(UTEST_SRCS
DVariable.test.cpp
DApplyExpr.test.cpp
DDefineExpr.test.cpp
DIfElseExpr.test.cpp
)
xo_add_utest_executable(${UTEST_EXE} ${UTEST_SRCS})

345
utest/DIfElseExpr.test.cpp Normal file
View file

@ -0,0 +1,345 @@
/** @file DIfElseExpr.test.cpp
*
* @author Roland Conybeare, Jan 2026
**/
#include "init_expression2.hpp"
#include <xo/expression2/DIfElseExpr.hpp>
#include <xo/expression2/detail/IExpression_DIfElseExpr.hpp>
#include <xo/expression2/detail/IPrintable_DIfElseExpr.hpp>
#include <xo/expression2/DConstant.hpp>
#include <xo/expression2/detail/IExpression_DConstant.hpp>
#include <xo/object2/DFloat.hpp>
#include <xo/object2/DBoolean.hpp>
#include <xo/object2/number/IGCObject_DFloat.hpp>
#include <xo/object2/boolean/IGCObject_DBoolean.hpp>
#include <xo/gc/CollectorTypeRegistry.hpp>
#include <xo/gc/DX1Collector.hpp>
#include <xo/gc/detail/IAllocator_DX1Collector.hpp>
#include <xo/gc/detail/ICollector_DX1Collector.hpp>
#include <xo/printable2/Printable.hpp>
#include <xo/facet/FacetRegistry.hpp>
#include <xo/reflect/Reflect.hpp>
#include <xo/indentlog/scope.hpp>
#include <catch2/catch.hpp>
#include <sstream>
namespace ut {
using xo::S_expression2_tag;
using xo::scm::DIfElseExpr;
using xo::scm::DConstant;
using xo::scm::DFloat;
using xo::scm::DBoolean;
using xo::scm::AExpression;
using xo::mm::CollectorTypeRegistry;
using xo::mm::AAllocator;
using xo::mm::ACollector;
using xo::mm::AGCObject;
using xo::mm::DX1Collector;
using xo::mm::CollectorConfig;
using xo::mm::ArenaConfig;
using xo::print::APrintable;
using xo::print::ppstate_standalone;
using xo::print::ppconfig;
using xo::facet::FacetRegistry;
using xo::facet::with_facet;
using xo::facet::obj;
using xo::reflect::Reflect;
using xo::InitEvidence;
using xo::InitSubsys;
using xo::scope;
static InitEvidence s_init = InitSubsys<S_expression2_tag>::require();
TEST_CASE("DIfElseExpr-init", "[expression2][DIfElseExpr]")
{
REQUIRE(s_init.evidence());
}
TEST_CASE("DIfElseExpr-make", "[expression2][DIfElseExpr]")
{
REQUIRE(s_init.evidence());
CollectorConfig cfg{
.name_ = "difelseexpr_make_test",
.arena_config_ = ArenaConfig{
.size_ = 8192,
.store_header_flag_ = true},
.object_types_z_ = 16384,
.gc_trigger_v_{{4096, 4096}},
.debug_flag_ = false,
};
DX1Collector gc(cfg);
auto alloc = with_facet<AAllocator>::mkobj(&gc);
auto coll = with_facet<ACollector>::mkobj(&gc);
bool ok = CollectorTypeRegistry::instance().install_types(coll);
REQUIRE(ok);
// Create test expression: constant true
obj<AGCObject> bval = DBoolean::box<AGCObject>(alloc, true);
auto test_expr = DConstant::make(alloc, bval);
REQUIRE(test_expr.data() != nullptr);
// Create when_true expression: constant 1.0
obj<AGCObject> fval1 = DFloat::box<AGCObject>(alloc, 1.0);
auto when_true_expr = DConstant::make(alloc, fval1);
REQUIRE(when_true_expr.data() != nullptr);
// Create when_false expression: constant 2.0
obj<AGCObject> fval2 = DFloat::box<AGCObject>(alloc, 2.0);
auto when_false_expr = DConstant::make(alloc, fval2);
REQUIRE(when_false_expr.data() != nullptr);
// Create if-else expression: if true then 1.0 else 2.0
auto ifexpr = DIfElseExpr::make(alloc, test_expr, when_true_expr, when_false_expr);
REQUIRE(ifexpr.data() != nullptr);
}
TEST_CASE("DIfElseExpr-test", "[expression2][DIfElseExpr]")
{
REQUIRE(s_init.evidence());
CollectorConfig cfg{
.name_ = "difelseexpr_test_test",
.arena_config_ = ArenaConfig{
.size_ = 8192,
.store_header_flag_ = true},
.object_types_z_ = 16384,
.gc_trigger_v_{{4096, 4096}},
.debug_flag_ = false,
};
DX1Collector gc(cfg);
auto alloc = with_facet<AAllocator>::mkobj(&gc);
auto coll = with_facet<ACollector>::mkobj(&gc);
bool ok = CollectorTypeRegistry::instance().install_types(coll);
REQUIRE(ok);
obj<AGCObject> bval = DBoolean::box<AGCObject>(alloc, true);
auto test_expr = DConstant::make(alloc, bval);
obj<AGCObject> fval1 = DFloat::box<AGCObject>(alloc, 1.0);
auto when_true_expr = DConstant::make(alloc, fval1);
obj<AGCObject> fval2 = DFloat::box<AGCObject>(alloc, 2.0);
auto when_false_expr = DConstant::make(alloc, fval2);
auto ifexpr = DIfElseExpr::make(alloc, test_expr, when_true_expr, when_false_expr);
REQUIRE(ifexpr.data() != nullptr);
obj<AExpression> test = ifexpr.data()->test();
REQUIRE(test.data() != nullptr);
REQUIRE(test.extype() == xo::scm::exprtype::constant);
}
TEST_CASE("DIfElseExpr-when-true", "[expression2][DIfElseExpr]")
{
REQUIRE(s_init.evidence());
CollectorConfig cfg{
.name_ = "difelseexpr_when_true_test",
.arena_config_ = ArenaConfig{
.size_ = 8192,
.store_header_flag_ = true},
.object_types_z_ = 16384,
.gc_trigger_v_{{4096, 4096}},
.debug_flag_ = false,
};
DX1Collector gc(cfg);
auto alloc = with_facet<AAllocator>::mkobj(&gc);
auto coll = with_facet<ACollector>::mkobj(&gc);
bool ok = CollectorTypeRegistry::instance().install_types(coll);
REQUIRE(ok);
obj<AGCObject> bval = DBoolean::box<AGCObject>(alloc, true);
auto test_expr = DConstant::make(alloc, bval);
obj<AGCObject> fval1 = DFloat::box<AGCObject>(alloc, 1.0);
auto when_true_expr = DConstant::make(alloc, fval1);
obj<AGCObject> fval2 = DFloat::box<AGCObject>(alloc, 2.0);
auto when_false_expr = DConstant::make(alloc, fval2);
auto ifexpr = DIfElseExpr::make(alloc, test_expr, when_true_expr, when_false_expr);
REQUIRE(ifexpr.data() != nullptr);
obj<AExpression> wt = ifexpr.data()->when_true();
REQUIRE(wt.data() != nullptr);
REQUIRE(wt.extype() == xo::scm::exprtype::constant);
}
TEST_CASE("DIfElseExpr-when-false", "[expression2][DIfElseExpr]")
{
REQUIRE(s_init.evidence());
CollectorConfig cfg{
.name_ = "difelseexpr_when_false_test",
.arena_config_ = ArenaConfig{
.size_ = 8192,
.store_header_flag_ = true},
.object_types_z_ = 16384,
.gc_trigger_v_{{4096, 4096}},
.debug_flag_ = false,
};
DX1Collector gc(cfg);
auto alloc = with_facet<AAllocator>::mkobj(&gc);
auto coll = with_facet<ACollector>::mkobj(&gc);
bool ok = CollectorTypeRegistry::instance().install_types(coll);
REQUIRE(ok);
obj<AGCObject> bval = DBoolean::box<AGCObject>(alloc, false);
auto test_expr = DConstant::make(alloc, bval);
obj<AGCObject> fval1 = DFloat::box<AGCObject>(alloc, 1.0);
auto when_true_expr = DConstant::make(alloc, fval1);
obj<AGCObject> fval2 = DFloat::box<AGCObject>(alloc, 2.0);
auto when_false_expr = DConstant::make(alloc, fval2);
auto ifexpr = DIfElseExpr::make(alloc, test_expr, when_true_expr, when_false_expr);
REQUIRE(ifexpr.data() != nullptr);
obj<AExpression> wf = ifexpr.data()->when_false();
REQUIRE(wf.data() != nullptr);
REQUIRE(wf.extype() == xo::scm::exprtype::constant);
}
TEST_CASE("DIfElseExpr-extype", "[expression2][DIfElseExpr]")
{
REQUIRE(s_init.evidence());
CollectorConfig cfg{
.name_ = "difelseexpr_extype_test",
.arena_config_ = ArenaConfig{
.size_ = 8192,
.store_header_flag_ = true},
.object_types_z_ = 16384,
.gc_trigger_v_{{4096, 4096}},
.debug_flag_ = false,
};
DX1Collector gc(cfg);
auto alloc = with_facet<AAllocator>::mkobj(&gc);
auto coll = with_facet<ACollector>::mkobj(&gc);
bool ok = CollectorTypeRegistry::instance().install_types(coll);
REQUIRE(ok);
obj<AGCObject> bval = DBoolean::box<AGCObject>(alloc, true);
auto test_expr = DConstant::make(alloc, bval);
obj<AGCObject> fval1 = DFloat::box<AGCObject>(alloc, 1.0);
auto when_true_expr = DConstant::make(alloc, fval1);
obj<AGCObject> fval2 = DFloat::box<AGCObject>(alloc, 2.0);
auto when_false_expr = DConstant::make(alloc, fval2);
auto ifexpr = DIfElseExpr::make(alloc, test_expr, when_true_expr, when_false_expr);
REQUIRE(ifexpr.data() != nullptr);
REQUIRE(ifexpr.data()->extype() == xo::scm::exprtype::ifexpr);
}
TEST_CASE("DIfElseExpr-valuetype", "[expression2][DIfElseExpr]")
{
REQUIRE(s_init.evidence());
CollectorConfig cfg{
.name_ = "difelseexpr_valuetype_test",
.arena_config_ = ArenaConfig{
.size_ = 8192,
.store_header_flag_ = true},
.object_types_z_ = 16384,
.gc_trigger_v_{{4096, 4096}},
.debug_flag_ = false,
};
DX1Collector gc(cfg);
auto alloc = with_facet<AAllocator>::mkobj(&gc);
auto coll = with_facet<ACollector>::mkobj(&gc);
bool ok = CollectorTypeRegistry::instance().install_types(coll);
REQUIRE(ok);
obj<AGCObject> bval = DBoolean::box<AGCObject>(alloc, true);
auto test_expr = DConstant::make(alloc, bval);
obj<AGCObject> fval1 = DFloat::box<AGCObject>(alloc, 1.0);
auto when_true_expr = DConstant::make(alloc, fval1);
obj<AGCObject> fval2 = DFloat::box<AGCObject>(alloc, 2.0);
auto when_false_expr = DConstant::make(alloc, fval2);
auto ifexpr = DIfElseExpr::make(alloc, test_expr, when_true_expr, when_false_expr);
REQUIRE(ifexpr.data() != nullptr);
// valuetype may be null before type resolution
// just verify we can call it
ifexpr.data()->valuetype();
}
TEST_CASE("DIfElseExpr-pretty", "[expression2][DIfElseExpr][pp]")
{
scope log(XO_DEBUG(true));
REQUIRE(s_init.evidence());
CollectorConfig cfg{
.name_ = "difelseexpr_pretty_test",
.arena_config_ = ArenaConfig{
.size_ = 8192,
.store_header_flag_ = true},
.object_types_z_ = 16384,
.gc_trigger_v_{{4096, 4096}},
.debug_flag_ = false,
};
DX1Collector gc(cfg);
auto alloc = with_facet<AAllocator>::mkobj(&gc);
auto coll = with_facet<ACollector>::mkobj(&gc);
bool ok = CollectorTypeRegistry::instance().install_types(coll);
REQUIRE(ok);
obj<AGCObject> bval = DBoolean::box<AGCObject>(alloc, true);
auto test_expr = DConstant::make(alloc, bval);
obj<AGCObject> fval1 = DFloat::box<AGCObject>(alloc, 1.0);
auto when_true_expr = DConstant::make(alloc, fval1);
obj<AGCObject> fval2 = DFloat::box<AGCObject>(alloc, 2.0);
auto when_false_expr = DConstant::make(alloc, fval2);
auto ifexpr = DIfElseExpr::make(alloc,
test_expr,
when_true_expr, when_false_expr);
REQUIRE(ifexpr.data() != nullptr);
std::stringstream ss;
ppconfig ppc;
ppstate_standalone pps(&ss, 0, &ppc);
obj<APrintable,DIfElseExpr> ifexpr_pr(ifexpr.data());
pps.pretty(ifexpr_pr);
std::string output = ss.str();
log && log(output);
CHECK(output.find("DIfElseExpr") != std::string::npos);
}
}
/* end DIfElseExpr.test.cpp */