diff --git a/CMakeLists.txt b/CMakeLists.txt index 84d8b6cf..80c97895 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -106,6 +106,7 @@ add_subdirectory(xo-procedure2) # schematika procedure abstraction + runtime c add_subdirectory(xo-numeric) # experiment w/ facet object model add_subdirectory(xo-ordinaltree) # +add_subdirectory(xo-type) # experiment w/ (fomo) add_subdirectory(xo-tokenizer2) # schematika tokenizer (fomo) add_subdirectory(xo-expression2) # schematika expressions (fomo) add_subdirectory(xo-reader2) # schematika expression parser (fomo) diff --git a/xo-object2/idl/IGCObject_DList.json5 b/xo-object2/idl/IGCObject_DList.json5 index ecb48980..83d1838b 100644 --- a/xo-object2/idl/IGCObject_DList.json5 +++ b/xo-object2/idl/IGCObject_DList.json5 @@ -4,8 +4,6 @@ output_hpp_dir: "include/xo/object2", output_impl_subdir: "list", includes: [ -// "", -// "" ], local_types: [ ], namespace1: "xo", diff --git a/xo-type/CMakeLists.txt b/xo-type/CMakeLists.txt new file mode 100644 index 00000000..e11f53b1 --- /dev/null +++ b/xo-type/CMakeLists.txt @@ -0,0 +1,70 @@ +# xo-type/CMakeLists.txt + +cmake_minimum_required(VERSION 3.10) + +project(xo_type VERSION 1.0) +enable_language(CXX) + +include(GNUInstallDirs) +include(cmake/xo-bootstrap-macros.cmake) + +xo_cxx_toplevel_options3() + +# ---------------------------------------------------------------- +# c++ settings + +# one-time project-specific c++ flags. usually empty +set(PROJECT_CXX_FLAGS "") +add_definitions(${PROJECT_CXX_FLAGS}) + +# ---------------------------------------------------------------- +# facet code generation + +xo_add_genfacet( + TARGET xo-type-facet-type + FACET Type + INPUT idl/Type.json5 + OUTPUT_HPP_DIR include/xo/type + OUTPUT_IMPL_SUBDIR type +) + +# ---------------------------------------------------------------- + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-type-facetimpl-type-atomictype + FACET_PKG xo_type + FACET Type + REPR AtomicType + INPUT idl/IType_DAtomicType.json5 +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-type-facetimpl-gcobject-atomictype + FACET_PKG xo_alloc2 + FACET GCObject + REPR AtomicType + INPUT idl/IGCObject_DAtomicType.json5 +) + +# ---------------------------------------------------------------- + +xo_add_genfacet_all(xo-type-genfacet-all) + +install(DIRECTORY idl/ + DESTINATION share/${PROJECT_NAME}/idl + FILES_MATCHING PATTERN "*.json5") + +# ---------------------------------------------------------------- +# output targets + +add_subdirectory(src/type) +add_subdirectory(utest) + +# ---------------------------------------------------------------- +# cmake export + +xo_export_cmake_config(${PROJECT_NAME} ${PROJECT_VERSION} ${PROJECT_NAME}Targets) + +# end CMakeLists.txt diff --git a/xo-type/cmake/xo-bootstrap-macros.cmake b/xo-type/cmake/xo-bootstrap-macros.cmake new file mode 100644 index 00000000..592272c0 --- /dev/null +++ b/xo-type/cmake/xo-bootstrap-macros.cmake @@ -0,0 +1,41 @@ +# ---------------------------------------------------------------- +# for example: +# $ PREFIX=/usr/local # for example +# $ cmake -DCMAKE_MODULE_PATH=prefix -DCMAKE_INSTALL_PREFIX=$PREFIX -B .build +# +# will get +# CMAKE_MODULE_PATH +# from xo-cmake-config --cmake-module-path +# +# and expect .cmake macros in +# CMAKE_MODULE_PATH/xo_macros/xo_cxx.cmake +# ---------------------------------------------------------------- + +find_program(XO_CMAKE_CONFIG_EXECUTABLE NAMES xo-cmake-config REQUIRED) + +if ("${XO_CMAKE_CONFIG_EXECUTABLE}" STREQUAL "XO_CMAKE_CONFIG_EXECUTABLE-NOT_FOUND") + message(FATAL "could not find xo-cmake-config executable") +endif() + +message(STATUS "XO_CMAKE_CONFIG_EXECUTABLE=${XO_CMAKE_CONFIG_EXECUTABLE}") + +if (XO_SUBMODULE_BUILD) + if (("${CMAKE_MODULE_PATH}" STREQUAL "") OR ("${CMAKE_MODULE_PATH}" STREQUAL prefix)) + # local version of xo-cmake macros + set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/xo-cmake/cmake") + message(STATUS "CMAKE_MODULE_PATH=${CMAKE_MODULE_PATH}") + endif() +else() + if (("${CMAKE_MODULE_PATH}" STREQUAL "") OR ("${CMAKE_MODULE_PATH}" STREQUAL prefix)) + # default to typical install location for xo-project-macros + execute_process(COMMAND ${XO_CMAKE_CONFIG_EXECUTABLE} --cmake-module-path OUTPUT_VARIABLE CMAKE_MODULE_PATH) + message(STATUS "CMAKE_MODULE_PATH=${CMAKE_MODULE_PATH}") + endif() +endif() + +# needs to have been installed somewhere on CMAKE_MODULE_PATH, +# (e.g. from xo-cmake with the same value for CMAKE_INSTALL_PREFIX) +# +include(xo_macros/xo_cxx) + +xo_cxx_bootstrap_message() diff --git a/xo-type/cmake/xo_typeConfig.cmake.in b/xo-type/cmake/xo_typeConfig.cmake.in new file mode 100644 index 00000000..2c4c0d1d --- /dev/null +++ b/xo-type/cmake/xo_typeConfig.cmake.in @@ -0,0 +1,15 @@ +@PACKAGE_INIT@ + +include(CMakeFindDependencyMacro) +find_dependency(xo_alloc2) +find_dependency(xo_facet) + +# note: changes to find_dependency() calls here +# must coordinate with xo_dependency() calls +# in src/type/CMakeLists.txt +# +#find_dependency(xo_indentlog) + +include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Share.cmake") +check_required_components("@PROJECT_NAME@") diff --git a/xo-type/idl/IGCObject_DAtomicType.json5 b/xo-type/idl/IGCObject_DAtomicType.json5 new file mode 100644 index 00000000..4cb85c1b --- /dev/null +++ b/xo-type/idl/IGCObject_DAtomicType.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/type", + output_hpp_dir: "include/xo/type", + output_impl_subdir: "atomic", + includes: [ + ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/GCObject.json5", + brief: "provide AGCObject interface for DAtomicType", + using_doxygen: true, + repr: "DAtomicType", + doc: [ "implement AGCObject for DAtomicType" ], +} diff --git a/xo-type/idl/IType_DAtomicType.json5 b/xo-type/idl/IType_DAtomicType.json5 new file mode 100644 index 00000000..c94c8923 --- /dev/null +++ b/xo-type/idl/IType_DAtomicType.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/type", + output_hpp_dir: "include/xo/type", + output_impl_subdir: "atomic", + includes: [], + local_types: [], + namespace1: "xo", + namespace2: "scm", + + facet_idl: "idl/Type.json5", + brief: "provide AType interface for DAtomicType", + using_doxygen: true, + repr: "DAtomicType", + doc: [ "implement AType for DAtomicType" ], +} diff --git a/xo-type/idl/Type.json5 b/xo-type/idl/Type.json5 new file mode 100644 index 00000000..eeb22334 --- /dev/null +++ b/xo-type/idl/Type.json5 @@ -0,0 +1,53 @@ +{ + mode: "facet", + output_cpp_dir: "src/type", + output_hpp_dir: "include/xo/type", + output_impl_subdir: "type", + includes: [ + "" + ], + user_hpp_includes: [ + ], + namespace1: "xo", + namespace2: "scm", // TODO: change to project namespace if different + pretext: [ + "// pretext if any" + ], + facet: "Type", + detail_subdir: "type", + brief: "Representation for a Schematika type", + using_doxygen: true, + doc: [ + "1. Ability to compare types as members of partial order", + "2. ..." + ], + types: [ + { + name: "obj_AType", + doc: [], + definition: "xo::facet::obj", + } + ], + const_methods: [ + { + name: "metatype", + doc: ["category for this type"], + return_type: "Metatype", + args: [], + const: true, + noexcept: true, + }, + + // TODO: define methods, e.g.: + // { + // name: "my_method", + // doc: ["description"], + // return_type: "bool", + // args: [], + // const: true, + // noexcept: true, + // }, + ], + nonconst_methods: [], + router_facet_explicit_content: [], +} diff --git a/xo-type/include/xo/type/AtomicType.hpp b/xo-type/include/xo/type/AtomicType.hpp new file mode 100644 index 00000000..e5515291 --- /dev/null +++ b/xo-type/include/xo/type/AtomicType.hpp @@ -0,0 +1,12 @@ +/** @file AtomicType.hpp + * + * @author Roland Conybeare, Mar 2026 + **/ + +#pragma once + +#include "DAtomicType.hpp" +#include "atomic/IType_DAtomicType.hpp" +#include "atomic/IGCObject_DAtomicType.hpp" + +/* end AtomicType.hpp */ diff --git a/xo-type/include/xo/type/DAtomicType.hpp b/xo-type/include/xo/type/DAtomicType.hpp new file mode 100644 index 00000000..253b678b --- /dev/null +++ b/xo-type/include/xo/type/DAtomicType.hpp @@ -0,0 +1,48 @@ +/** @file DAtomicType.hpp + * + * @author Roland Conybeare, Mar 2026 + **/ + +#pragma once + +#include "Metatype.hpp" +#include +#include + +namespace xo { + namespace scm { + /** @brief An atomic schematika type + * + * Types that are not parameterized by types or values. + * For example + * unit, bool, i64, f64 + * are atomic in this sense. + **/ + class DAtomicType { + public: + using ACollector = xo::mm::ACollector; + using AAllocator = xo::mm::AAllocator; + + public: + explicit DAtomicType(Metatype m) : metatype_{m} {} + + /** create instance using memory from @p mm with metatype @p mtype **/ + static DAtomicType * _make(obj mm, Metatype mtype); + + Metatype metatype() const noexcept { return metatype_; } + + /** @defgroup xo-scm-atomictype-gcobject-facet **/ + ///@{ + std::size_t shallow_size() const noexcept; + DAtomicType * shallow_copy(obj mm) const noexcept; + std::size_t forward_children(obj gc) noexcept; + ///@} + + private: + Metatype metatype_; + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DAtomicType.hpp */ diff --git a/xo-type/include/xo/type/Metatype.hpp b/xo-type/include/xo/type/Metatype.hpp new file mode 100644 index 00000000..813b1446 --- /dev/null +++ b/xo-type/include/xo/type/Metatype.hpp @@ -0,0 +1,60 @@ +/** @file Metatype.hpp + * + * @author Roland Conybeare, Mar 2026 + **/ + +#pragma once + +#include + +namespace xo { + namespace scm { + class Metatype { + public: + enum class code { + /* void */ + t_unit, + + t_bool, + t_i64, + t_f64, + t_str, + + /* discriminated union */ + t_sum, + /* list */ + t_list, + /* array */ + t_array, + /* function */ + t_function, + /* struct */ + t_struct, + + /* any type at all */ + t_any, + }; + + public: + explicit Metatype(code x) : code_{x} {} + + static Metatype unit() { return Metatype(code::t_unit); } + + /** description string for this type category **/ + const char * _descr() const noexcept; + + code code() const noexcept { return code_; } + + private: + enum code code_; + }; + + inline std::ostream & + operator<<(std::ostream & os, Metatype x) { + os << x._descr(); + return os; + } + } /*namespace scm*/ +} /*namespace xo*/ + +/* end Metatype.hpp */ diff --git a/xo-type/include/xo/type/Type.hpp b/xo-type/include/xo/type/Type.hpp new file mode 100644 index 00000000..97da0453 --- /dev/null +++ b/xo-type/include/xo/type/Type.hpp @@ -0,0 +1,22 @@ +/** @file Type.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/Type.json5] + * 2. jinja2 template for facet .hpp file: + * [facet.hpp.j2] + * 3. idl for facet methods + * [idl/Type.json5] + **/ + +#pragma once + +#include "type/AType.hpp" +#include "type/IType_Any.hpp" +#include "type/IType_Xfer.hpp" +#include "type/RType.hpp" + + +/* end Type.hpp */ diff --git a/xo-type/include/xo/type/atomic/IGCObject_DAtomicType.hpp b/xo-type/include/xo/type/atomic/IGCObject_DAtomicType.hpp new file mode 100644 index 00000000..c1fff453 --- /dev/null +++ b/xo-type/include/xo/type/atomic/IGCObject_DAtomicType.hpp @@ -0,0 +1,65 @@ +/** @file IGCObject_DAtomicType.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DAtomicType.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DAtomicType.json5] + **/ + +#pragma once + +#include "GCObject.hpp" +#include "DAtomicType.hpp" + +namespace xo { namespace scm { class IGCObject_DAtomicType; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::mm::IGCObject_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IGCObject_DAtomicType + **/ + class IGCObject_DAtomicType { + public: + /** @defgroup scm-gcobject-datomictype-type-traits **/ + ///@{ + using size_type = xo::mm::AGCObject::size_type; + using AAllocator = xo::mm::AGCObject::AAllocator; + using ACollector = xo::mm::AGCObject::ACollector; + using Copaque = xo::mm::AGCObject::Copaque; + using Opaque = xo::mm::AGCObject::Opaque; + ///@} + /** @defgroup scm-gcobject-datomictype-methods **/ + ///@{ + // const methods + /** memory consumption for this instance **/ + static size_type shallow_size(const DAtomicType & self) noexcept; + /** copy instance using allocator **/ + static Opaque shallow_copy(const DAtomicType & self, obj mm) noexcept; + + // non-const methods + /** during GC: forward immdiate children **/ + static size_type forward_children(DAtomicType & self, obj gc) noexcept; + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-type/include/xo/type/atomic/IType_DAtomicType.hpp b/xo-type/include/xo/type/atomic/IType_DAtomicType.hpp new file mode 100644 index 00000000..8a351cf9 --- /dev/null +++ b/xo-type/include/xo/type/atomic/IType_DAtomicType.hpp @@ -0,0 +1,59 @@ +/** @file IType_DAtomicType.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IType_DAtomicType.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IType_DAtomicType.json5] + **/ + +#pragma once + +#include "Type.hpp" +#include "DAtomicType.hpp" + +namespace xo { namespace scm { class IType_DAtomicType; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::scm::IType_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IType_DAtomicType + **/ + class IType_DAtomicType { + public: + /** @defgroup scm-type-datomictype-type-traits **/ + ///@{ + using obj_AType = xo::scm::AType::obj_AType; + using Copaque = xo::scm::AType::Copaque; + using Opaque = xo::scm::AType::Opaque; + ///@} + /** @defgroup scm-type-datomictype-methods **/ + ///@{ + // const methods + /** category for this type **/ + static Metatype metatype(const DAtomicType & self) noexcept; + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-type/include/xo/type/init_type.hpp b/xo-type/include/xo/type/init_type.hpp new file mode 100644 index 00000000..d06f33f8 --- /dev/null +++ b/xo-type/include/xo/type/init_type.hpp @@ -0,0 +1,21 @@ +/** @file init_type.hpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#pragma once + +#include + +namespace xo { + /* tag to represent the xo-expression2/ subsystem within ordered initialization */ + enum S_type_tag {}; + + template <> + struct InitSubsys { + static void init(); + static InitEvidence require(); + }; +} /*namespace xo*/ + +/* end init_type.hpp */ diff --git a/xo-type/include/xo/type/type/AType.hpp b/xo-type/include/xo/type/type/AType.hpp new file mode 100644 index 00000000..50389fe7 --- /dev/null +++ b/xo-type/include/xo/type/type/AType.hpp @@ -0,0 +1,77 @@ +/** @file AType.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/Type.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [abstract_facet.hpp.j2] + * 3. idl for facet methods + * [idl/Type.json5] + **/ + +#pragma once + +// includes (via {facet_includes}) +#include +#include +#include +#include + +// pretext if any + +namespace xo { +namespace scm { + +using Copaque = const void *; +using Opaque = void *; + +/** +1. Ability to compare types as members of partial order +2. ... +**/ +class AType { +public: + /** @defgroup scm-type-type-traits **/ + ///@{ + // types + /** integer identifying a type **/ + using typeseq = xo::facet::typeseq; + using Copaque = const void *; + using Opaque = void *; + /** **/ + using obj_AType = xo::facet::obj; + ///@} + + /** @defgroup scm-type-methods **/ + ///@{ + // const methods + /** RTTI: unique id# for actual runtime data representation **/ + virtual typeseq _typeseq() const noexcept = 0; + /** destroy instance @p d; calls c++ dtor only for actual runtime type; does not recover memory **/ + virtual void _drop(Opaque d) const noexcept = 0; + /** category for this type **/ + virtual Metatype metatype(Copaque data) const noexcept = 0; + + // nonconst methods + ///@} +}; /*AType*/ + +/** Implementation IType_DRepr of AType for state DRepr + * should provide a specialization: + * + * template <> + * struct xo::facet::FacetImplementation { + * using Impltype = IType_DRepr; + * }; + * + * then IType_ImplType --> IType_DRepr + **/ +template +using IType_ImplType = xo::facet::FacetImplType; + +} /*namespace scm*/ +} /*namespace xo*/ + +/* AType.hpp */ diff --git a/xo-type/include/xo/type/type/IType_Any.hpp b/xo-type/include/xo/type/type/IType_Any.hpp new file mode 100644 index 00000000..6db13097 --- /dev/null +++ b/xo-type/include/xo/type/type/IType_Any.hpp @@ -0,0 +1,89 @@ +/** @file IType_Any.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/Type.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/Type.json5] + **/ + +#pragma once + +#include "AType.hpp" +#include + +namespace xo { namespace scm { class IType_Any; } } + +namespace xo { +namespace facet { + +template <> +struct FacetImplementation +{ + using ImplType = xo::scm::IType_Any; +}; + +} +} + +namespace xo { +namespace scm { + + /** @class IType_Any + * @brief AType implementation for empty variant instance + **/ + class IType_Any : public AType { + public: + /** @defgroup scm-type-any-type-traits **/ + ///@{ + + /** integer identifying a type **/ + using typeseq = xo::facet::typeseq; + using obj_AType = AType::obj_AType; + + ///@} + /** @defgroup scm-type-any-methods **/ + ///@{ + + const AType * iface() const { return std::launder(this); } + + // from AType + + // builtin methods + typeseq _typeseq() const noexcept override { return s_typeseq; } + [[noreturn]] void _drop(Opaque) const noexcept override { _fatal(); } + + // const methods + [[noreturn]] Metatype metatype(Copaque) const noexcept override { _fatal(); } + + // nonconst methods + + ///@} + + private: + /** @defgraoup scm-type-any-private-methods **/ + ///@{ + + [[noreturn]] static void _fatal(); + + ///@} + + public: + /** @defgroup scm-type-any-member-vars **/ + ///@{ + + static typeseq s_typeseq; + static bool _valid; + + ///@} + }; + +} /*namespace scm */ +} /*namespace xo */ + +/* IType_Any.hpp */ diff --git a/xo-type/include/xo/type/type/IType_Xfer.hpp b/xo-type/include/xo/type/type/IType_Xfer.hpp new file mode 100644 index 00000000..ead6c45e --- /dev/null +++ b/xo-type/include/xo/type/type/IType_Xfer.hpp @@ -0,0 +1,84 @@ +/** @file IType_Xfer.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/Type.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/Type.json5] + **/ + +#pragma once + +#include + +namespace xo { +namespace scm { + /** @class IType_Xfer + **/ + template + class IType_Xfer : public AType { + public: + /** @defgroup scm-type-xfer-type-traits **/ + ///@{ + /** actual implementation (not generated; often delegates to DRepr) **/ + using Impl = IType_DRepr; + /** integer identifying a type **/ + using typeseq = AType::typeseq; + using obj_AType = AType::obj_AType; + ///@} + + /** @defgroup scm-type-xfer-methods **/ + ///@{ + + static const DRepr & _dcast(Copaque d) { return *(const DRepr *)d; } + static DRepr & _dcast(Opaque d) { return *(DRepr *)d; } + + // from AType + + // builtin methods + typeseq _typeseq() const noexcept override { return s_typeseq; } + void _drop(Opaque d) const noexcept override { _dcast(d).~DRepr(); } + + // const methods + Metatype metatype(Copaque data) const noexcept override { + return I::metatype(_dcast(data)); + } + + // non-const methods + + ///@} + + private: + using I = Impl; + + public: + /** @defgroup scm-type-xfer-member-vars **/ + ///@{ + + /** typeseq for template parameter DRepr **/ + static typeseq s_typeseq; + /** true iff satisfies facet implementation **/ + static bool _valid; + + ///@} + }; + + template + xo::facet::typeseq + IType_Xfer::s_typeseq + = xo::facet::typeseq::id(); + + template + bool + IType_Xfer::_valid + = xo::facet::valid_facet_implementation(); + +} /*namespace scm */ +} /*namespace xo*/ + +/* end IType_Xfer.hpp */ diff --git a/xo-type/include/xo/type/type/RType.hpp b/xo-type/include/xo/type/type/RType.hpp new file mode 100644 index 00000000..a6376fe0 --- /dev/null +++ b/xo-type/include/xo/type/type/RType.hpp @@ -0,0 +1,85 @@ +/** @file RType.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/Type.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/Type.json5] + **/ + +#pragma once + +#include "AType.hpp" + +namespace xo { +namespace scm { + +/** @class RType + **/ +template +class RType : public Object { +private: + using O = Object; + +public: + /** @defgroup scm-type-router-type-traits **/ + ///@{ + using ObjectType = Object; + using DataPtr = Object::DataPtr; + using typeseq = xo::reflect::typeseq; + using obj_AType = AType::obj_AType; + ///@} + + /** @defgroup scm-type-router-ctors **/ + ///@{ + RType() {} + RType(Object::DataPtr data) : Object{std::move(data)} {} + RType(const AType * iface, void * data) + requires std::is_same_v + : Object(iface, data) {} + + ///@} + /** @defgroup scm-type-router-methods **/ + ///@{ + + // explicit injected content + + // builtin methods + typeseq _typeseq() const noexcept { return O::iface()->_typeseq(); } + void _drop() const noexcept { O::iface()->_drop(O::data()); } + + // const methods + Metatype metatype() const noexcept { + return O::iface()->metatype(O::data()); + } + + // non-const methods (still const in router!) + + ///@} + /** @defgroup scm-type-member-vars **/ + ///@{ + + static bool _valid; + + ///@} +}; + +template +bool +RType::_valid = xo::facet::valid_object_router(); + +} /*namespace scm*/ +} /*namespace xo*/ + +namespace xo { namespace facet { + template + struct RoutingFor { + using RoutingType = xo::scm::RType; + }; +} } + +/* end RType.hpp */ diff --git a/xo-type/include/xo/type/type_register_facets.hpp b/xo-type/include/xo/type/type_register_facets.hpp new file mode 100644 index 00000000..f418eab5 --- /dev/null +++ b/xo-type/include/xo/type/type_register_facets.hpp @@ -0,0 +1,15 @@ +/** @file type_register_facets.hpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#pragma once + +namespace xo { + namespace scm { + /** Register type (facet,impl) combinations with FacetRegistry **/ + bool type_register_facets(); + } +} + +/* end type_register_facets.hpp */ diff --git a/xo-type/include/xo/type/type_register_types.hpp b/xo-type/include/xo/type/type_register_types.hpp new file mode 100644 index 00000000..5ab1db0d --- /dev/null +++ b/xo-type/include/xo/type/type_register_types.hpp @@ -0,0 +1,17 @@ +/** @file type_register_types.hpp + * + * @author Roland Conybeare, Dec 2025 + **/ + +#pragma once + +#include + +namespace xo { + namespace scm { + /** Register type (facet,impl) combinations with FacetRegistry **/ + bool type_register_types(obj gc); + } +} + +/* end type_register_types.hpp */ diff --git a/xo-type/src/type/CMakeLists.txt b/xo-type/src/type/CMakeLists.txt new file mode 100644 index 00000000..36f88958 --- /dev/null +++ b/xo-type/src/type/CMakeLists.txt @@ -0,0 +1,25 @@ +# xo-type/src/type/CMakeLists.txt + +set(SELF_LIB xo_type) +set(SELF_SRCS + init_type.cpp + type_register_facets.cpp + type_register_types.cpp + Metatype.cpp + DAtomicType.cpp + IType_DAtomicType.cpp + IGCObject_DAtomicType.cpp +) + +xo_add_shared_library4(${SELF_LIB} ${PROJECT_NAME}Targets ${PROJECT_VERSION} 1 ${SELF_SRCS}) + +# ---------------------------------------------------------------- +# input dependencies +# +# NOTE: dependency set here must be kept consistent with +# xo-type/cmake/xo_typeConfig.cmake.in + +xo_dependency(${SELF_LIB} xo_alloc2) +xo_dependency(${SELF_LIB} xo_facet) + +# end src/type/CMakeLists.txt diff --git a/xo-type/src/type/DAtomicType.cpp b/xo-type/src/type/DAtomicType.cpp new file mode 100644 index 00000000..561e8777 --- /dev/null +++ b/xo-type/src/type/DAtomicType.cpp @@ -0,0 +1,42 @@ +/** @file DAtomicType.cpp + * + * @author Roland Conybeare, Mar 2026 + **/ + +#include "AtomicType.hpp" + +namespace xo { + namespace scm { + + DAtomicType * + DAtomicType::_make(obj mm, Metatype mtype) + { + void * mem = mm.alloc_for(); + + return new (mem) DAtomicType(mtype); + } + + // ----- GCObject facet ----- + + std::size_t + DAtomicType::shallow_size() const noexcept + { + return sizeof(DAtomicType); + } + + DAtomicType * + DAtomicType::shallow_copy(obj mm) const noexcept + { + return mm.std_copy_for(this); + } + + std::size_t + DAtomicType::forward_children(obj) noexcept + { + return this->shallow_size(); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DAtomicType.cpp */ diff --git a/xo-type/src/type/IGCObject_DAtomicType.cpp b/xo-type/src/type/IGCObject_DAtomicType.cpp new file mode 100644 index 00000000..17f3a56a --- /dev/null +++ b/xo-type/src/type/IGCObject_DAtomicType.cpp @@ -0,0 +1,39 @@ +/** @file IGCObject_DAtomicType.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DAtomicType.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DAtomicType.json5] +**/ + +#include "atomic/IGCObject_DAtomicType.hpp" + +namespace xo { + namespace scm { + auto + IGCObject_DAtomicType::shallow_size(const DAtomicType & self) noexcept -> size_type + { + return self.shallow_size(); + } + + auto + IGCObject_DAtomicType::shallow_copy(const DAtomicType & self, obj mm) noexcept -> Opaque + { + return self.shallow_copy(mm); + } + + auto + IGCObject_DAtomicType::forward_children(DAtomicType & self, obj gc) noexcept -> size_type + { + return self.forward_children(gc); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IGCObject_DAtomicType.cpp */ diff --git a/xo-type/src/type/IType_Any.cpp b/xo-type/src/type/IType_Any.cpp new file mode 100644 index 00000000..bb9690fb --- /dev/null +++ b/xo-type/src/type/IType_Any.cpp @@ -0,0 +1,42 @@ +/** @file IType_Any.cpp + * + **/ + +#include "type/IType_Any.hpp" +#include +#include + +namespace xo { +namespace scm { + +using xo::facet::DVariantPlaceholder; +using xo::facet::typeseq; +using xo::facet::valid_facet_implementation; + +void +IType_Any::_fatal() +{ + /* control here on uninitialized IAllocator_Any. + * Initialized instance will have specific implementation type + */ + std::cerr << "fatal" + << ": attempt to call uninitialized" + << " IType_Any method" + << std::endl; + std::terminate(); +} + +typeseq +IType_Any::s_typeseq = typeseq::id(); + +bool +IType_Any::_valid + = valid_facet_implementation(); + +// nonconst methods + + +} /*namespace scm*/ +} /*namespace xo*/ + +/* end IType_Any.cpp */ diff --git a/xo-type/src/type/IType_DAtomicType.cpp b/xo-type/src/type/IType_DAtomicType.cpp new file mode 100644 index 00000000..663653ad --- /dev/null +++ b/xo-type/src/type/IType_DAtomicType.cpp @@ -0,0 +1,28 @@ +/** @file IType_DAtomicType.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IType_DAtomicType.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IType_DAtomicType.json5] +**/ + +#include "atomic/IType_DAtomicType.hpp" + +namespace xo { + namespace scm { + auto + IType_DAtomicType::metatype(const DAtomicType & self) noexcept -> Metatype + { + return self.metatype(); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IType_DAtomicType.cpp */ diff --git a/xo-type/src/type/Metatype.cpp b/xo-type/src/type/Metatype.cpp new file mode 100644 index 00000000..acc82b67 --- /dev/null +++ b/xo-type/src/type/Metatype.cpp @@ -0,0 +1,32 @@ +/** @file Metatype.cpp + * + * @author Roland Conybeare, Nar 2026 + **/ + +#include "Metatype.hpp" + +namespace xo { + namespace scm { + + const char * + Metatype::_descr() const noexcept + { + switch (code_) { + case code::t_any: return "any"; + case code::t_bool: return "bool"; + case code::t_i64: return "i64"; + case code::t_f64: return "f64"; + case code::t_str: return "str"; + case code::t_sum: return "sum"; + case code::t_list: return "list"; + case code::t_array: return "array"; + case code::t_function: return "function"; + case code::t_struct: return "struct"; + case code::t_unit: return "unit"; + } + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end Metatype.cpp */ diff --git a/xo-type/src/type/init_type.cpp b/xo-type/src/type/init_type.cpp new file mode 100644 index 00000000..bbae93d2 --- /dev/null +++ b/xo-type/src/type/init_type.cpp @@ -0,0 +1,40 @@ +/** @file init_type.cpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include "init_type.hpp" +#include "type_register_facets.hpp" +#include "type_register_types.hpp" +#include +#include + +namespace xo { + using xo::scm::type_register_facets; + using xo::scm::type_register_types; + using xo::mm::CollectorTypeRegistry; + + void + InitSubsys::init() + { + type_register_facets(); + + CollectorTypeRegistry::instance().register_types(&type_register_types); + } + + InitEvidence + InitSubsys::require() + { + InitEvidence retval; + + /* direct subsystem deps for xo-type/ */ + retval ^= InitSubsys::require(); + + /* xo-type/'s own initialization code */ + retval ^= Subsystem::provide("type", &init); + + return retval; + } +} /*namespace xo*/ + +/* end init_type.cpp */ diff --git a/xo-type/src/type/type_register_facets.cpp b/xo-type/src/type/type_register_facets.cpp new file mode 100644 index 00000000..6c7bd512 --- /dev/null +++ b/xo-type/src/type/type_register_facets.cpp @@ -0,0 +1,35 @@ +/** @file type_register_facets.cpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#include "type_register_facets.hpp" + +#include +#include +#include + +namespace xo { + using xo::mm::AGCObject; + using xo::facet::FacetRegistry; + //using xo::facet::TypeRegistry; + using xo::reflect::typeseq; + + namespace scm { + + bool + type_register_facets() + { + scope log(XO_DEBUG(true)); + + FacetRegistry::register_impl(); + + log && log(xtag("DAtomicType.tseq", typeseq::id())); + + return true; + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end type_register_facets.cpp */ diff --git a/xo-type/src/type/type_register_types.cpp b/xo-type/src/type/type_register_types.cpp new file mode 100644 index 00000000..e5da5d1d --- /dev/null +++ b/xo-type/src/type/type_register_types.cpp @@ -0,0 +1,34 @@ +/** @file type_register_types.cpp + * + * @author Roland Conybeare, Dec 2025 + **/ + +#include "type_register_types.hpp" + +#include "AtomicType.hpp" +#include +#include +#include + +namespace xo { + using xo::mm::ACollector; + using xo::mm::AGCObject; + using xo::facet::impl_for; + using xo::scope; + + namespace scm { + bool + type_register_types(obj gc) + { + scope log(XO_DEBUG(true)); + + bool ok = true; + + ok &= gc.install_type(impl_for()); + + return ok; + } + } +} /*namespace xo*/ + +/* end type_register_types.cpp */ diff --git a/xo-type/utest/CMakeLists.txt b/xo-type/utest/CMakeLists.txt new file mode 100644 index 00000000..ff79bda4 --- /dev/null +++ b/xo-type/utest/CMakeLists.txt @@ -0,0 +1,16 @@ +# built unittest xo-type/utest + +set(UTEST_EXE utest.type) +set(UTEST_SRCS + type_utest_main.cpp + DAtomicType.test.cpp +# DString.test.cpp +# StringOps.test.cpp +# X1Collector.test.cpp +# Printable.test.cpp +) + +xo_add_utest_executable(${UTEST_EXE} ${UTEST_SRCS}) +xo_self_dependency(${UTEST_EXE} xo_type) +#xo_dependency(${UTEST_EXE} xo_alloc2) +xo_external_target_dependency(${UTEST_EXE} Catch2 Catch2::Catch2) diff --git a/xo-type/utest/DAtomicType.test.cpp b/xo-type/utest/DAtomicType.test.cpp new file mode 100644 index 00000000..6ee26cee --- /dev/null +++ b/xo-type/utest/DAtomicType.test.cpp @@ -0,0 +1,40 @@ +/** @file DAtomicType.test.cpp + * + * @author Roland Conybeare, Mar 2026 + **/ + +#include "init_type.hpp" +#include "AtomicType.hpp" +#include +#include +#include +#include + +namespace xo { + using xo::scm::AType; + using xo::scm::DAtomicType; + using xo::scm::Metatype; + using xo::mm::AAllocator; + using xo::mm::DArena; + using xo::mm::ArenaConfig; + + namespace ut { + static InitEvidence s_init = (InitSubsys::require()); + + TEST_CASE("DAtomicType-make", "[type][DAtomicType]") + { + ArenaConfig cfg { .name_ = "testarena", + .size_ = 4*1024 }; + DArena arena = DArena::map(cfg); + auto alloc = obj(&arena); + + auto f64_type = obj(DAtomicType::_make(alloc, Metatype::unit())); + + REQUIRE(f64_type); + REQUIRE(f64_type.metatype().code() == Metatype::unit().code()); + } + + } /*namespace ut*/ +} /*namespace xo*/ + +/* end DAtomicType.test.cpp */ diff --git a/xo-type/utest/type_utest_main.cpp b/xo-type/utest/type_utest_main.cpp new file mode 100644 index 00000000..d4615d40 --- /dev/null +++ b/xo-type/utest/type_utest_main.cpp @@ -0,0 +1,24 @@ +/* file type_utest_main.cpp */ + +#include + +#define CATCH_CONFIG_RUNNER +#include "catch2/catch.hpp" + +int +main(int argc, char* argv[]) +{ + using xo::Subsystem; + + // Your custom initialization code here + Subsystem::initialize_all(); + + // Run Catch2's test session + int result = Catch::Session().run(argc, argv); + + // cleanup here, if any + + return result; +} + +/* end type_utest_main.cpp */