diff --git a/cmake/xo_expression2Config.cmake.in b/cmake/xo_expression2Config.cmake.in index ee1852c8..d48c29a4 100644 --- a/cmake/xo_expression2Config.cmake.in +++ b/cmake/xo_expression2Config.cmake.in @@ -8,6 +8,7 @@ include(CMakeFindDependencyMacro) # find_dependency(xo_gc) find_dependency(reflect) +find_dependency(xo_object2) find_dependency(xo_printable2) find_dependency(xo_flatstring) find_dependency(indentlog) diff --git a/idl/Expression.json5 b/idl/Expression.json5 index 9daca006..f156dffe 100644 --- a/idl/Expression.json5 +++ b/idl/Expression.json5 @@ -1,6 +1,9 @@ { mode: "facet", - includes: ["\"TypeRef.hpp\""], + includes: [ "\"TypeRef.hpp\"", + "\"exprtype.hpp\"", + ""], + namespace1: "xo", namespace2: "scm", facet: "Expression", @@ -10,8 +13,24 @@ doc: [ "Representation for executable Schematika expressions" ], - types: [], + types: [ + // using TypeDescr = xo::reflect::TypeDescr; + { + name: "TypeDescr", + doc: ["struct describing a type"], + definition: "xo::reflect::TypeDescr" + }, + ], const_methods: [ + { + name: "extype", + doc: ["expression type (constant | apply | ..)"], + return_type: "exprtype", + args: [], + const: true, + noexcept: true, + attributes: [], + }, { name: "typeref", doc: ["placeholder for type giving possible values for this expression"], diff --git a/include/xo/expression2/DConstant.hpp b/include/xo/expression2/DConstant.hpp index b7cc5cce..29776912 100644 --- a/include/xo/expression2/DConstant.hpp +++ b/include/xo/expression2/DConstant.hpp @@ -3,7 +3,10 @@ * @author Roland Conybeare, Jan 2026 **/ -#include +#include "TypeRef.hpp" +#include "exprtype.hpp" +#include +#include namespace xo { namespace scm { @@ -12,24 +15,36 @@ namespace xo { **/ struct DConstant { public: + using TaggedPtr = xo::reflect::TaggedPtr; using TypeDescr = xo::reflect::TypeDescr; + using AGCObject = xo::mm::AGCObject; + using typeseq = xo::reflect::typeseq; public: - DConstant(TypeDescr td, void * value); + explicit DConstant(obj value) noexcept; - TypeDescr value_td() const { return value_td; } + bool is_resolved() const noexcept { return typeref_.is_resolved(); } - TypeRef typeref() const noexcept; - TypeDescr valuetype() const noexcept; - void assign_valuetype(TypeDescr td) noexcept; + exprtype extype() const noexcept { return exprtype::constant; } + TypeDescr value_td() const noexcept { return typeref_.td(); } + TaggedPtr value_tp() const noexcept { return TaggedPtr(typeref_.td(), value_.data()); } + + TypeRef typeref() const noexcept { return typeref_; } + TypeDescr valuetype() const noexcept { return typeref_.td(); } + obj value() const noexcept { return value_; } + + void assign_valuetype(TypeDescr td) noexcept { typeref_.resolve(td); } private: - /** type for value of this expression **/ - TypeRef type_ref_; - /** type description for destination *value_ **/ - TypeDescr valuetype_; + static TypeDescr _lookup_td(typeseq tseq); + + private: + /** type for value of this expression + * or unification breadcrumb before unification + **/ + TypeRef typeref_; /** literal value **/ - void * value_; + obj value_; }; } /*namespace scm*/ } /*namespace xo*/ diff --git a/include/xo/expression2/Expression.hpp b/include/xo/expression2/Expression.hpp index 311b627d..c6960c07 100644 --- a/include/xo/expression2/Expression.hpp +++ b/include/xo/expression2/Expression.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] + * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] * arguments: * --input [idl/Expression.json5] * 2. jinja2 template for facet .hpp file: diff --git a/include/xo/expression2/TypeRef.hpp b/include/xo/expression2/TypeRef.hpp index 8ee08716..cd789d23 100644 --- a/include/xo/expression2/TypeRef.hpp +++ b/include/xo/expression2/TypeRef.hpp @@ -26,6 +26,11 @@ namespace xo { TypeRef() = default; TypeRef(const type_var & id, TypeDescr td); + /** trivial typeref, where already resolved. + * Require: @p td non-null + **/ + static TypeRef resolved(TypeDescr td); + /** if @p td is non-null * -> type is already resolved * @@ -43,7 +48,10 @@ namespace xo { TypeDescr td() const noexcept { return td_; } /** true iff type at this location has been resolved **/ - bool is_concrete() const noexcept; + bool is_resolved() const noexcept; + + /** resolve TypeRef by supplying final type-description **/ + void resolve(TypeDescr td) noexcept { td_ = td; } private: /** unique (probably generated) name for type at this location **/ diff --git a/include/xo/expression2/detail/AExpression.hpp b/include/xo/expression2/detail/AExpression.hpp index 942c940b..ae53af05 100644 --- a/include/xo/expression2/detail/AExpression.hpp +++ b/include/xo/expression2/detail/AExpression.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] + * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] * arguments: * --input [idl/Expression.json5] * 2. jinja2 template for abstract facet .hpp file: @@ -15,6 +15,8 @@ // includes (via {facet_includes}) #include "TypeRef.hpp" +#include "exprtype.hpp" +#include #include #include #include @@ -35,6 +37,8 @@ public: // types /** integer identifying a type **/ using typeseq = xo::facet::typeseq; + /** struct describing a type **/ + using TypeDescr = xo::reflect::TypeDescr; ///@} /** @defgroup scm-expression-methods **/ @@ -42,6 +46,8 @@ public: // const methods /** RTTI: unique id# for actual runtime data representation **/ virtual typeseq _typeseq() const noexcept = 0; + /** expression type (constant | apply | ..) **/ + virtual exprtype extype(Copaque data) const noexcept = 0; /** placeholder for type giving possible values for this expression **/ virtual TypeRef typeref(Copaque data) const noexcept = 0; /** type giving possible values for this expression. Maybe null before typecheck **/ diff --git a/include/xo/expression2/detail/IExpression_Any.hpp b/include/xo/expression2/detail/IExpression_Any.hpp index 0fac3289..e76cc3a6 100644 --- a/include/xo/expression2/detail/IExpression_Any.hpp +++ b/include/xo/expression2/detail/IExpression_Any.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] + * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] * arguments: * --input [idl/Expression.json5] * 2. jinja2 template for abstract facet .hpp file: @@ -44,6 +44,7 @@ namespace scm { /** integer identifying a type **/ using typeseq = xo::facet::typeseq; + using TypeDescr = AExpression::TypeDescr; ///@} /** @defgroup scm-expression-any-methods **/ @@ -55,6 +56,7 @@ namespace scm { // const methods typeseq _typeseq() const noexcept override { return s_typeseq; } + [[noreturn]] exprtype extype(Copaque) const noexcept override { _fatal(); } [[noreturn]] TypeRef typeref(Copaque) const noexcept override { _fatal(); } [[noreturn]] TypeDescr valuetype(Copaque) const noexcept override { _fatal(); } diff --git a/include/xo/expression2/detail/IExpression_Xfer.hpp b/include/xo/expression2/detail/IExpression_Xfer.hpp index 55abfd05..9f7356bc 100644 --- a/include/xo/expression2/detail/IExpression_Xfer.hpp +++ b/include/xo/expression2/detail/IExpression_Xfer.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] + * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] * arguments: * --input [idl/Expression.json5] * 2. jinja2 template for abstract facet .hpp file: @@ -14,6 +14,8 @@ #pragma once #include "TypeRef.hpp" +#include "exprtype.hpp" +#include namespace xo { namespace scm { @@ -28,6 +30,7 @@ namespace scm { using Impl = IExpression_DRepr; /** integer identifying a type **/ using typeseq = AExpression::typeseq; + using TypeDescr = AExpression::TypeDescr; ///@} /** @defgroup scm-expression-xfer-methods **/ @@ -40,6 +43,9 @@ namespace scm { // const methods typeseq _typeseq() const noexcept override { return s_typeseq; } + exprtype extype(Copaque data) const noexcept override { + return I::extype(_dcast(data)); + } TypeRef typeref(Copaque data) const noexcept override { return I::typeref(_dcast(data)); } diff --git a/include/xo/expression2/detail/RExpression.hpp b/include/xo/expression2/detail/RExpression.hpp index e9b431e3..9afd711f 100644 --- a/include/xo/expression2/detail/RExpression.hpp +++ b/include/xo/expression2/detail/RExpression.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] + * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] * arguments: * --input [idl/Expression.json5] * 2. jinja2 template for abstract facet .hpp file: @@ -31,6 +31,7 @@ public: using ObjectType = Object; using DataPtr = Object::DataPtr; using typeseq = xo::reflect::typeseq; + using TypeDescr = AExpression::TypeDescr; ///@} /** @defgroup scm-expression-router-ctors **/ @@ -44,10 +45,13 @@ public: // const methods typeseq _typeseq() const noexcept { return O::iface()->_typeseq(); } - TypeRef typeref() const noexcept override { + exprtype extype() const noexcept { + return O::iface()->extype(O::data()); + } + TypeRef typeref() const noexcept { return O::iface()->typeref(O::data()); } - TypeDescr valuetype() const noexcept override { + TypeDescr valuetype() const noexcept { return O::iface()->valuetype(O::data()); } diff --git a/include/xo/expression2/exprtype.hpp b/include/xo/expression2/exprtype.hpp new file mode 100644 index 00000000..cf66d39e --- /dev/null +++ b/include/xo/expression2/exprtype.hpp @@ -0,0 +1,84 @@ +/** @file exprtype.hpp + * + * Author: Roland Conybeare + **/ + +#pragma once + +#include +//#include + +namespace xo { + namespace scm { + /** @enum exprtype + * @brief enum to identify subclasses of xo::scm::Expression. + * + **/ + enum class exprtype { + /** sentinel value **/ + invalid = -1, + + /** literal constant. must satisfy both standard_layout_type + trivial **/ + constant, +#ifdef NOT_YET + /** a literal constant that refers to a linkable named function **/ + primitive, + /** variable/function definition **/ + define, + /** variable assignment **/ + assign, + /** function call **/ + apply, + /** function definition **/ + lambda, + /** variable reference **/ + variable, + /** if-then-else **/ + ifexpr, + /** sequence **/ + sequence, + /** type conversion **/ + convert, +#endif + + /** not an expression. comes last, counts entries **/ + N + }; + + inline const char * + expr2str(exprtype x) + { + switch(x) { + case exprtype::invalid: return "?exprtype"; + case exprtype::constant: return "constant"; +#ifdef NOT_YET + case exprtype::primitive: return "primitive"; + case exprtype::define: return "define"; + case exprtype::assign: return "assign"; + case exprtype::apply: return "apply"; + case exprtype::lambda: return "lambda"; + case exprtype::variable: return "variable"; + case exprtype::ifexpr: return "if_expr"; + case exprtype::sequence: return "sequence"; + case exprtype::convert: return "convert"; +#endif + default: break; + } + + return "???exprtype???"; + } + + /** @brief number of built-in expression types, repr convenient for array sizing **/ + static constexpr std::size_t n_exprtype = static_cast(exprtype::N); + + inline std::ostream & + operator<<(std::ostream & os, + exprtype x) + { + os << expr2str(x); + return os; + } + } /*namespace scm*/ +} /*namespace xo*/ + +/* end exprtype.hpp */ diff --git a/src/expression2/CMakeLists.txt b/src/expression2/CMakeLists.txt index c0c794ff..b91033c7 100644 --- a/src/expression2/CMakeLists.txt +++ b/src/expression2/CMakeLists.txt @@ -2,6 +2,7 @@ set(SELF_LIB xo_expression2) set(SELF_SRCS + DConstant.cpp TypeRef.cpp #IExpression_Any.cpp expression2_register_facets.cpp @@ -11,6 +12,7 @@ xo_add_shared_library4(${SELF_LIB} ${PROJECT_NAME}Targets ${PROJECT_VERSION} 1 $ # note: deps here must also appear in cmake/xo_expression2Config.cmake.in xo_dependency(${SELF_LIB} xo_gc) xo_dependency(${SELF_LIB} reflect) +xo_dependency(${SELF_LIB} xo_object2) xo_dependency(${SELF_LIB} xo_printable2) xo_dependency(${SELF_LIB} xo_flatstring) xo_dependency(${SELF_LIB} indentlog) diff --git a/src/expression2/DConstant.cpp b/src/expression2/DConstant.cpp new file mode 100644 index 00000000..fcb38f54 --- /dev/null +++ b/src/expression2/DConstant.cpp @@ -0,0 +1,53 @@ +/** @file DConstant.cpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include "DConstant.hpp" +#include "TypeDescr.hpp" +#include +#include +#include +#include + +namespace xo { + using xo::scm::DFloat; + using xo::scm::DInteger; + using xo::reflect::Reflect; + using xo::reflect::TypeDescr; + using xo::reflect::typeseq; + + namespace scm { + DConstant::DConstant(obj value) noexcept + : + //typeref_{TypeRef::resolved(td)}, + value_{value} + { + // todo: use ObjectConverter here + + auto tseq = value_._typeseq(); + + TypeDescr td = this->_lookup_td(tseq); + + if (td) { + typeref_ = TypeRef::resolved(td); + } + } + + TypeDescr + DConstant::_lookup_td(typeseq tseq) + { + if (tseq == typeseq::id()) { + /* double */ + return Reflect::require(); + } else if (tseq == typeseq::id()) { + /* long */ + return Reflect::require(); + } + + return nullptr; + } + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DConstant.cpp */ diff --git a/src/expression2/TypeRef.cpp b/src/expression2/TypeRef.cpp index 2ceb6132..7b187ecd 100644 --- a/src/expression2/TypeRef.cpp +++ b/src/expression2/TypeRef.cpp @@ -11,6 +11,15 @@ namespace xo { : id_{id}, td_{td} {} + TypeRef + TypeRef::resolved(TypeDescr td) + { + assert(td); + + type_var null; + return TypeRef(null, td); + } + TypeRef TypeRef::dwim(prefix_type prefix, TypeDescr td) { @@ -18,8 +27,7 @@ namespace xo { /* type already resolved * -> we don't need a type variable name */ - type_var null; - return TypeRef(null, td); + return TypeRef::resolved(td); } else { /* type is not resolved yet. * -> give it a unique name, @@ -49,7 +57,7 @@ namespace xo { } bool - TypeRef::is_concrete() const noexcept + TypeRef::is_resolved() const noexcept { return (td_ != nullptr); }