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

@ -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 **/