From 0f89542e116b02d9c025c9b10a7217e5cfeb95c9 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Sat, 26 Jul 2025 17:28:41 -0400 Subject: [PATCH 01/12] xo-expression xo-reader: type unifier + misc improvements --- include/xo/reflect/TypeDescr.hpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/include/xo/reflect/TypeDescr.hpp b/include/xo/reflect/TypeDescr.hpp index 53247ad0..57deb81d 100644 --- a/include/xo/reflect/TypeDescr.hpp +++ b/include/xo/reflect/TypeDescr.hpp @@ -518,11 +518,21 @@ namespace xo { }; /*TypeDescrBase*/ inline std::ostream & - operator<<(std::ostream & os, TypeDescrBase const & x) { + operator<<(std::ostream & os, const TypeDescrBase & x) { x.display(os); return os; } /*operator<<*/ + inline std::ostream & + operator<<(std::ostream & os, const TypeDescrBase * p) { + if (p) + p->display(os); + else + os << ""; + return os; + } + + /* tag to drive overload resolution */ struct reflected_types_printer {}; From dc26b9780225fed5029e097b5a11537a05fcb0fa Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Sun, 27 Jul 2025 13:35:20 -0400 Subject: [PATCH 02/12] xo-reader: integer arithmetic + parser + pretty-printing adds --- include/xo/reflect/TypeDescr.hpp | 16 ++++++++++------ src/reflect/TypeDescr.cpp | 21 +++++++++++++++++++++ 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/include/xo/reflect/TypeDescr.hpp b/include/xo/reflect/TypeDescr.hpp index 57deb81d..8896ed3a 100644 --- a/include/xo/reflect/TypeDescr.hpp +++ b/include/xo/reflect/TypeDescr.hpp @@ -240,13 +240,13 @@ namespace xo { TypeDescrExtra * tdextra() const { return tdextra_.get(); } Metatype metatype() const { return tdextra_->metatype(); } - /* true iff the type represented by *this is the same as the type - * represented by T. + /** true iff the type represented by _c *this is the same as the type + * represented by @tparam T * - * Warning: comparing typeinfo address can give false negatives. - * suspect this is caused by problems coalescing linker symbols - * in the clang toolchain. - */ + * Warning: comparing typeinfo address can give false negatives. + * suspect this is caused by problems coalescing linker symbols + * in the clang toolchain. + **/ template [[deprecated]] bool is_native() const { @@ -317,6 +317,10 @@ namespace xo { } } /*recover_native2*/ + bool is_i128() const; + bool is_i64() const; + bool is_f64() const; + bool is_pointer() const { return this->tdextra_->is_pointer(); } bool is_vector() const { return this->tdextra_->is_vector(); } bool is_struct() const { return this->tdextra_->is_struct(); } diff --git a/src/reflect/TypeDescr.cpp b/src/reflect/TypeDescr.cpp index 4d048015..8b40678f 100644 --- a/src/reflect/TypeDescr.cpp +++ b/src/reflect/TypeDescr.cpp @@ -254,6 +254,22 @@ namespace xo { { } + bool + TypeDescrBase::is_i64() const + { + static_assert(sizeof(long long) == 8); + + return Reflect::is_native(this); + } + + bool + TypeDescrBase::is_f64() const + { + static_assert(sizeof(double) == 8); + + return Reflect::is_native(this); + } + TaggedPtr TypeDescrBase::most_derived_self_tp(void * object) const { @@ -311,6 +327,11 @@ namespace xo { #endif TypeDescrTable::TypeDescrTable() { + /* want long == i64 */ + static_assert(sizeof(long) == 8); + /* want double == f64 */ + static_assert(sizeof(double) == 8); + Reflect::require(); Reflect::require(); Reflect::require(); From ecbfc79c1d2f13a7794abe1d7ce77d38cdad5dbf Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Sun, 27 Jul 2025 14:31:39 -0400 Subject: [PATCH 03/12] xo-reflect: bugfix is_i64 on linux (gcc / wsl2) --- src/reflect/TypeDescr.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/reflect/TypeDescr.cpp b/src/reflect/TypeDescr.cpp index 8b40678f..676225f2 100644 --- a/src/reflect/TypeDescr.cpp +++ b/src/reflect/TypeDescr.cpp @@ -257,9 +257,11 @@ namespace xo { bool TypeDescrBase::is_i64() const { - static_assert(sizeof(long long) == 8); + // FIXME: on apple/clang may need to use long long - return Reflect::is_native(this); + static_assert(sizeof(std::int64_t) == 8); + + return Reflect::is_native(this); } bool From 6ba04457018da7e35ad6b774d660b48cb25e042f Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Sun, 16 Nov 2025 20:10:23 -0500 Subject: [PATCH 04/12] xo-interpreter adds + explict mm arg to ctors (retiring Object::mm) --- include/xo/reflect/EstablishTypeDescr.hpp | 8 ++++---- src/reflect/CMakeLists.txt | 2 +- src/reflect/TypeDescr.cpp | 21 +++++++++++++++++++-- src/reflect/init_reflect.cpp | 20 ++++++++++---------- 4 files changed, 34 insertions(+), 17 deletions(-) diff --git a/include/xo/reflect/EstablishTypeDescr.hpp b/include/xo/reflect/EstablishTypeDescr.hpp index 0f18d84a..e461a91a 100644 --- a/include/xo/reflect/EstablishTypeDescr.hpp +++ b/include/xo/reflect/EstablishTypeDescr.hpp @@ -39,10 +39,10 @@ namespace xo { template static TypeDescrW establish() { - TypeDescrW td = TypeDescrBase::require(&typeid(T), - std::string(type_name()), - nullptr /*tdextra*/, - nullptr /*invoker*/); + static TypeDescrW td = TypeDescrBase::require(&typeid(T), + std::string(type_name()), + nullptr /*tdextra*/, + nullptr /*invoker*/); #ifdef NOT_USING std::function to_self_tp; diff --git a/src/reflect/CMakeLists.txt b/src/reflect/CMakeLists.txt index 87417066..c9a95d66 100644 --- a/src/reflect/CMakeLists.txt +++ b/src/reflect/CMakeLists.txt @@ -13,7 +13,7 @@ set(SELF_SRCS xo_add_shared_library4(${SELF_LIB} ${PROJECT_NAME}Targets ${PROJECT_VERSION} 1 ${SELF_SRCS}) xo_dependency(${SELF_LIB} refcnt) xo_dependency(${SELF_LIB} indentlog) -xo_dependency(${SELF_LIB} subsys) +xo_headeronly_dependency(${SELF_LIB} subsys) #xo_boost_dependency(${SELF_LIB}) # end CMakeLists.txt diff --git a/src/reflect/TypeDescr.cpp b/src/reflect/TypeDescr.cpp index 676225f2..de5f4ada 100644 --- a/src/reflect/TypeDescr.cpp +++ b/src/reflect/TypeDescr.cpp @@ -57,6 +57,10 @@ namespace xo { detail::Invoker * invoker, std::unique_ptr tdextra) { + scope log(XO_DEBUG(false)); + + log && log(xtag("canonical_name", canonical_name)); + if (native_tinfo) { /* 1. lookup by tinfo hash_code in s_type_table_map * Not available for manually-constructed type descriptions. @@ -64,19 +68,29 @@ namespace xo { { auto ix = s_native_type_table_map.find(TypeInfoRef(native_tinfo)); - if ((ix != s_native_type_table_map.end()) && ix->second) + if ((ix != s_native_type_table_map.end()) && ix->second) { + log && log("TypeDescrBase::require" + ": using s_native_type_table_map[TypeInfoRef(native_tinfo)]"); + return ix->second; + } } /* 2. lookup by tinfo hash_code in s_coalesced_type_table_map */ { auto ix = s_coalesced_type_table_map.find(TypeInfoRef(native_tinfo)); - if ((ix != s_coalesced_type_table_map.end()) && ix->second) + if ((ix != s_coalesced_type_table_map.end()) && ix->second) { + log && log("TypeDescrBase::require" + ": using s_coalesced_type_table_map[TypeInfoRef(native_tinfo)]"); + return ix->second; + } } } + log && log("TypeDescrBase::require: try lookup by canonical name"); + /* 3. lookup by canonical_name, before we create a new slot. * * Have to accept that on clang type_info objects aren't always unique (!$@#!!) @@ -85,6 +99,7 @@ namespace xo { auto ix = s_canonical_type_table_map.find(canonical_name); if (ix != s_canonical_type_table_map.end()) { + /** assume existing slot, with same canonical name, * represents the same type as native_tinfo **/ @@ -145,6 +160,8 @@ namespace xo { TypeId new_td_id = TypeId::allocate(); + log && log("TypeDescrBase::require", xtag("new_td_id", new_td_id)); + if (s_type_table_v.size() <= new_td_id.id()) s_type_table_v.resize(new_td_id.id() + 1); diff --git a/src/reflect/init_reflect.cpp b/src/reflect/init_reflect.cpp index d95bf2e3..bcfa34be 100644 --- a/src/reflect/init_reflect.cpp +++ b/src/reflect/init_reflect.cpp @@ -7,17 +7,17 @@ #include "xo/subsys/Subsystem.hpp" namespace xo { - void - InitSubsys::init() - { - /* placeholder -- expecting there to be non-trivial content soon */ - } /*init*/ + void + InitSubsys::init() + { + /* placeholder -- expecting there to be non-trivial content soon */ + } /*init*/ - InitEvidence - InitSubsys::require() - { - return Subsystem::provide("reflect", &init); - } /*require*/ + InitEvidence + InitSubsys::require() + { + return Subsystem::provide("reflect", &init); + } /*require*/ } /*namespace xo*/ /* end init_reflect.cpp */ From 5e2cff3f9dda1415d8f0ad881301aac32633b03e Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Mon, 17 Nov 2025 10:41:35 -0500 Subject: [PATCH 05/12] xo-interpreter CVector for StackFrame reflection + OSX imgui edits --- include/xo/reflect/Reflect.hpp | 3 --- include/xo/reflect/struct/StructMember.hpp | 9 +++++---- include/xo/reflect/vector/VectorTdx.hpp | 2 +- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/include/xo/reflect/Reflect.hpp b/include/xo/reflect/Reflect.hpp index f75c3e44..52213dd8 100644 --- a/include/xo/reflect/Reflect.hpp +++ b/include/xo/reflect/Reflect.hpp @@ -254,15 +254,12 @@ namespace xo { template static TaggedRcptr make_rctp(T * x) { return TaggedPtrMaker::make_rctp(x); } - private: - template static detail::InvokerAux * get_final_invoker() { static detail::InvokerAux s_final_invoker; return &s_final_invoker; } - }; /*Reflect*/ // ----- MakeTagged ----- diff --git a/include/xo/reflect/struct/StructMember.hpp b/include/xo/reflect/struct/StructMember.hpp index e7b76413..2e138a4f 100644 --- a/include/xo/reflect/struct/StructMember.hpp +++ b/include/xo/reflect/struct/StructMember.hpp @@ -61,8 +61,9 @@ namespace xo { using Memptr = MemberT OwnerT::*; public: - GeneralStructMemberAccessor(Memptr memptr) : member_td_{EstablishTypeDescr::establish()}, - memptr_{memptr} {} + GeneralStructMemberAccessor(Memptr memptr) + : member_td_{EstablishTypeDescr::establish()}, + memptr_{memptr} {} GeneralStructMemberAccessor(GeneralStructMemberAccessor const & x) = default; virtual ~GeneralStructMemberAccessor() = default; @@ -214,8 +215,8 @@ namespace xo { } /*for_descendant*/ StructMember & operator=(StructMember && x) { - member_name_ = std::move(x.member_name_); - accessor_ = std::move(x.accessor_); + this->member_name_ = std::move(x.member_name_); + this->accessor_ = std::move(x.accessor_); return *this; } diff --git a/include/xo/reflect/vector/VectorTdx.hpp b/include/xo/reflect/vector/VectorTdx.hpp index ebd318c2..0919e8fd 100644 --- a/include/xo/reflect/vector/VectorTdx.hpp +++ b/include/xo/reflect/vector/VectorTdx.hpp @@ -17,7 +17,7 @@ namespace xo { /* named ctor idiom. create new instance for a vector type */ //static std::unique_ptr make(); - /** @brief true if array elements are stored at regularly-spaced offsetts **/ + /** @brief true if array elements are stored at regularly-spaced offsets **/ virtual bool has_contiguous_storage() const = 0; // ----- Inherited from TypeDescrExtra ----- From ce6fa08abb05b27cdbbf502744434e4869fba08c Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Wed, 19 Nov 2025 21:34:13 -0500 Subject: [PATCH 06/12] xo-interpreter: ObjectConverter + VirtualSchmatikaMachineFlyweight --- include/xo/reflect/TypeDrivenMap.hpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/include/xo/reflect/TypeDrivenMap.hpp b/include/xo/reflect/TypeDrivenMap.hpp index 3eb42660..d972780f 100644 --- a/include/xo/reflect/TypeDrivenMap.hpp +++ b/include/xo/reflect/TypeDrivenMap.hpp @@ -14,21 +14,24 @@ namespace xo { template class TypeDrivenMap { public: - Value const * lookup(TypeId id) const { return this->lookup_slot(id); } + TypeDrivenMap() = default; + + const Value * lookup(TypeId id) const { return this->lookup_slot(id); } + const Value * lookup(TypeDescr td) { return this->lookup_slot(td->id()); } Value * require(TypeId id) { return this->require_slot(id); } Value * require(TypeDescr td) { return this->require_slot(td->id()); } private: - Value const * lookup_slot(TypeId id) const { - if (this->contents_v_.size() <= id.id()) + const Value * lookup_slot(TypeId id) const { + if (contents_v_.size() <= id.id()) return nullptr; return &(this->contents_v_[id.id()]); } /*lookup_slot*/ Value * require_slot(TypeId id) { - if (this->contents_v_.size() <= id.id()) + if (contents_v_.size() <= id.id()) this->contents_v_.resize(id.id() + 1); return &(this->contents_v_[id.id()]); From aff30a1ee36aaa8c3facb8496009b83115dd705c Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Thu, 27 Nov 2025 11:03:41 -0500 Subject: [PATCH 07/12] xo-interpreter: add Primitive object, to expose builtin functions --- include/xo/reflect/TypeDescr.hpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/include/xo/reflect/TypeDescr.hpp b/include/xo/reflect/TypeDescr.hpp index 8896ed3a..d39d64e8 100644 --- a/include/xo/reflect/TypeDescr.hpp +++ b/include/xo/reflect/TypeDescr.hpp @@ -99,21 +99,28 @@ namespace xo { * * Example * T * p = new T(...); - * DestructorAux::dtor(p); + * InvokerAux::dtor(p); **/ template struct InvokerAux : public Invoker { virtual void dtor(void * addr) const override { - T * obj = static_cast(addr); + T * obj = reinterpret_cast(addr); obj->~T(); } }; + /** no dtor for void **/ template<> struct InvokerAux : public Invoker { virtual void dtor(void *) const override {} }; + + /** no dtor for function types **/ + template + struct InvokerAux : public Invoker { + virtual void dtor(void *) const override {} + }; } /*namespace detail*/ } /*namespace reflect*/ } /*namespace xo*/ From a2b24b8a2eec5766b32dffed756c1acdd3104ff5 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Wed, 3 Dec 2025 15:36:59 -0500 Subject: [PATCH 08/12] xo-alloc / xo-ordinaltree: + concepts + allocator-aware --- include/xo/reflect/Object.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/xo/reflect/Object.hpp b/include/xo/reflect/Object.hpp index 91a5cedd..768b6058 100644 --- a/include/xo/reflect/Object.hpp +++ b/include/xo/reflect/Object.hpp @@ -35,6 +35,7 @@ namespace xo { **/ TypeId type_id_; }; + } /*namespace obj*/ } /*namespace xo*/ From d7ed6044149efc6961af837c08e67538cca571df Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Sun, 25 Jan 2026 10:02:58 -0500 Subject: [PATCH 09/12] xo-reflect: minor: const in TypeDriveMap.lookup method --- include/xo/reflect/TypeDrivenMap.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/xo/reflect/TypeDrivenMap.hpp b/include/xo/reflect/TypeDrivenMap.hpp index d972780f..2568887d 100644 --- a/include/xo/reflect/TypeDrivenMap.hpp +++ b/include/xo/reflect/TypeDrivenMap.hpp @@ -17,7 +17,7 @@ namespace xo { TypeDrivenMap() = default; const Value * lookup(TypeId id) const { return this->lookup_slot(id); } - const Value * lookup(TypeDescr td) { return this->lookup_slot(td->id()); } + const Value * lookup(TypeDescr td) const { return this->lookup_slot(td->id()); } Value * require(TypeId id) { return this->require_slot(id); } Value * require(TypeDescr td) { return this->require_slot(td->id()); } From 08658613d54f98710963bf7b5b1837f737ed6352 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Mon, 26 Jan 2026 19:26:54 -0500 Subject: [PATCH 10/12] xo-reflect: + pretty printing for xo::reflect::TypeDescr --- include/xo/reflect/TypeDescr.hpp | 30 ++++++++++++++++++++++++++++-- src/reflect/TypeDescr.cpp | 13 +++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/include/xo/reflect/TypeDescr.hpp b/include/xo/reflect/TypeDescr.hpp index d39d64e8..4b3ca87b 100644 --- a/include/xo/reflect/TypeDescr.hpp +++ b/include/xo/reflect/TypeDescr.hpp @@ -3,7 +3,8 @@ #pragma once #include "TypeDescrExtra.hpp" -#include "xo/cxxutil/demangle.hpp" +#include +#include #include #include #include @@ -15,6 +16,8 @@ #include namespace xo { + namespace print { class ppindentinfo; } + namespace reflect { class TaggedPtr; /* see [reflect/TaggedPtr.hpp] */ @@ -202,6 +205,9 @@ namespace xo { /* run-time description for a native c++ type */ class TypeDescrBase { + public: + using ppindentinfo = xo::print::ppindentinfo; + public: /* type-description objects for a type T is unique, * --> can always use its address @@ -391,6 +397,9 @@ namespace xo { TypeDescr fn_arg(uint32_t i) const { return this->tdextra_->fn_arg(i); } bool fn_is_noexcept() const { return this->tdextra_->fn_is_noexcept(); } + /** pretty-printer support, using @p ppii **/ + bool pretty(const ppindentinfo & ppii) const; + void display(std::ostream & os) const; std::string display_string() const; @@ -543,7 +552,6 @@ namespace xo { return os; } - /* tag to drive overload resolution */ struct reflected_types_printer {}; @@ -567,6 +575,24 @@ namespace xo { static TypeDescrTable s_instance; }; } /*namespace reflect*/ + + namespace print { + template <> + struct ppdetail { + static bool print_pretty(const ppindentinfo & ppii, + const xo::reflect::TypeDescrBase & td) { + return td.pretty(ppii); + } + }; + + template <> + struct ppdetail { + static bool print_pretty(const ppindentinfo & ppii, + xo::reflect::TypeDescr td) { + return td ? td->pretty(ppii) : true; + } + }; + } /*namespace print*/ } /*namespace xo*/ namespace std { diff --git a/src/reflect/TypeDescr.cpp b/src/reflect/TypeDescr.cpp index de5f4ada..c6cb1664 100644 --- a/src/reflect/TypeDescr.cpp +++ b/src/reflect/TypeDescr.cpp @@ -301,6 +301,19 @@ namespace xo { return this->tdextra_->child_tp(i, object); } /*child_tp*/ + bool + TypeDescrBase::pretty(const ppindentinfo & ppii) const + { + return ppii.pps()->pretty_struct + (ppii, + "TypeDescr", + refrtag("id", id_), + refrtag("canonical_name", canonical_name_), + refrtag("complete", complete_flag_), + refrtag("metatype", this->metatype())); + + } + void TypeDescrBase::display(std::ostream & os) const { From 0cb04f152bd35a5bd78f238b566d19f34eabc87f Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Mon, 26 Jan 2026 20:27:14 -0500 Subject: [PATCH 11/12] xo-reflect: compile nit --- include/xo/reflect/TypeDescr.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/xo/reflect/TypeDescr.hpp b/include/xo/reflect/TypeDescr.hpp index 4b3ca87b..f22f96bd 100644 --- a/include/xo/reflect/TypeDescr.hpp +++ b/include/xo/reflect/TypeDescr.hpp @@ -16,8 +16,6 @@ #include namespace xo { - namespace print { class ppindentinfo; } - namespace reflect { class TaggedPtr; /* see [reflect/TaggedPtr.hpp] */ From f0dcacad6f569d6e5e9ed45d473201a431c63b92 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Fri, 27 Feb 2026 19:38:53 +1100 Subject: [PATCH 12/12] xo-cmake: setup to make share target available via cmake install --- cmake/reflectConfig.cmake.in | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/reflectConfig.cmake.in b/cmake/reflectConfig.cmake.in index ce449a35..b7c79684 100644 --- a/cmake/reflectConfig.cmake.in +++ b/cmake/reflectConfig.cmake.in @@ -5,4 +5,5 @@ find_dependency(refcnt) find_dependency(indentlog) find_dependency(subsys) include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Share.cmake") check_required_components("@PROJECT_NAME@")