xo-objectd2 xo-printable xo-facet: pp working for List(Integer)
Also streamline facet switching
This commit is contained in:
parent
9ce465e84f
commit
09ee3a20ac
23 changed files with 508 additions and 27 deletions
24
FAQ-DEV.md
Normal file
24
FAQ-DEV.md
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
Error like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
/home/roland/proj/xo-umbrella2-claude1/./xo-facet/include/xo/facet/OObject.hpp:63:19: required from ‘struct xo::facet::OObject<xo::mm::AGCObject, xo::scm::DList>’
|
||||||
|
63 | using ISpecific = FacetImplType<AFacet, DRepr>;
|
||||||
|
| ^~~~~~~~~
|
||||||
|
/home/roland/proj/xo-umbrella2-claude1/./xo-gc/include/xo/gc/detail/RGCObject.hpp:15:16: required from ‘struct xo::mm::RGCObject<xo::facet::OObject<xo::mm::AGCObject, xo::scm::DList> >’
|
||||||
|
15 | struct RGCObject : public Object {
|
||||||
|
| ^~~~~~~~~
|
||||||
|
/home/roland/proj/xo-umbrella2-claude1/./xo-facet/include/xo/facet/obj.hpp:49:16: required from ‘struct xo::facet::obj<xo::mm::AGCObject, xo::scm::DList>’
|
||||||
|
49 | struct obj : public RoutingType<AFacet, OObject<AFacet, DRepr>> {
|
||||||
|
| ^~~
|
||||||
|
/home/roland/proj/xo-umbrella2-claude1/xo-object2/utest/Printable.test.cpp:81:57: required from here
|
||||||
|
81 | auto l0_o = with_facet<AGCObject>::mkobj(l0);
|
||||||
|
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
|
||||||
|
/home/roland/proj/xo-umbrella2-claude1/./xo-facet/include/xo/facet/facet_implementation.hpp:97:15: error: no type named ‘ImplType’ in ‘struct xo::facet::FacetImplementation<xo::mm::AGCObject, xo::scm::DList>’
|
||||||
|
97 | using FacetImplType = FacetImplementation<AFacet, DRepr>::ImplType;
|
||||||
|
| ^~~~~~~~~~~~~
|
||||||
|
```
|
||||||
|
|
||||||
|
means implementation `xo::mm::AGCObject` for `xo::scm::DList` is not availabel to compiler.
|
||||||
|
Either missing implementation or missing header.
|
||||||
|
|
||||||
|
In example implementation would be in a file `IGCObject_DList.hpp`
|
||||||
|
|
@ -76,6 +76,10 @@ namespace utest {
|
||||||
*
|
*
|
||||||
* test function should use REQUIRE_ORCAPTURE() / REQUIRE_ORFAIL().
|
* test function should use REQUIRE_ORCAPTURE() / REQUIRE_ORFAIL().
|
||||||
* It should *not* use REQUIRE() or CHECK().
|
* It should *not* use REQUIRE() or CHECK().
|
||||||
|
*
|
||||||
|
* @p test_name banner for initial log message (only printed on 2nd pass)
|
||||||
|
* @p test_fn function to invoke test pass.
|
||||||
|
* @p n test size/id (cosmetic - printed in log messages)
|
||||||
**/
|
**/
|
||||||
static inline bool bimodal_test(std::string test_name,
|
static inline bool bimodal_test(std::string test_name,
|
||||||
std::function<bool (bool dbg_flag, std::uint32_t n)> test_fn,
|
std::function<bool (bool dbg_flag, std::uint32_t n)> test_fn,
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ public:
|
||||||
{% endif %}
|
{% endif %}
|
||||||
using ObjectType = Object;
|
using ObjectType = Object;
|
||||||
using DataPtr = Object::DataPtr;
|
using DataPtr = Object::DataPtr;
|
||||||
|
using typeseq = xo::reflect::typeseq;
|
||||||
{% for ty in types %}
|
{% for ty in types %}
|
||||||
using {{ty.name}} = {{abstract_facet}}::{{ty.name}};
|
using {{ty.name}} = {{abstract_facet}}::{{ty.name}};
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
@ -53,7 +54,7 @@ public:
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
// const methods
|
// const methods
|
||||||
int32_t _typeseq() const noexcept { return O::iface()->_typeseq(); }
|
typeseq _typeseq() const noexcept { return O::iface()->_typeseq(); }
|
||||||
{% for md in const_methods %}
|
{% for md in const_methods %}
|
||||||
{{md.return_type}} {{md.name}}({{md.args | argsnodata}}) {{md | qualifiers}} override {
|
{{md.return_type}} {{md.name}}({{md.args | argsnodata}}) {{md | qualifiers}} override {
|
||||||
return O::iface()->{{md.name}}({{md.args | argrouting}});
|
return O::iface()->{{md.name}}({{md.args | argrouting}});
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,8 @@
|
||||||
#include "facet_implementation.hpp"
|
#include "facet_implementation.hpp"
|
||||||
#include "typeseq.hpp"
|
#include "typeseq.hpp"
|
||||||
#include "obj.hpp"
|
#include "obj.hpp"
|
||||||
|
#include <xo/indentlog/scope.hpp>
|
||||||
|
#include <xo/indentlog/print/tostr.hpp>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
|
@ -36,6 +38,7 @@ namespace xo {
|
||||||
**/
|
**/
|
||||||
class FacetRegistry {
|
class FacetRegistry {
|
||||||
public:
|
public:
|
||||||
|
using typeseq = xo::reflect::typeseq;
|
||||||
using key_type = std::pair<typeseq, typeseq>;
|
using key_type = std::pair<typeseq, typeseq>;
|
||||||
|
|
||||||
/** hash function for key_type **/
|
/** hash function for key_type **/
|
||||||
|
|
@ -102,7 +105,7 @@ namespace xo {
|
||||||
template <typename AFacet>
|
template <typename AFacet>
|
||||||
const AFacet * lookup(typeseq repr_id) const {
|
const AFacet * lookup(typeseq repr_id) const {
|
||||||
return static_cast<const AFacet *>
|
return static_cast<const AFacet *>
|
||||||
(this->_lookup(typeseq::id<AFacet>(), repr_id));
|
(this->_lookup(typeseq::id<AFacet>(), repr_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Runtime polymorphism:
|
/** Runtime polymorphism:
|
||||||
|
|
@ -113,10 +116,40 @@ namespace xo {
|
||||||
* = ...; // Foo instance with variant impl
|
* = ...; // Foo instance with variant impl
|
||||||
* obj<ABar> bar
|
* obj<ABar> bar
|
||||||
* = FacetRegistry::variant<ABar,AFoo>(foo);
|
* = FacetRegistry::variant<ABar,AFoo>(foo);
|
||||||
|
*
|
||||||
|
* // exception thrown if bar has null data
|
||||||
|
*
|
||||||
|
* assert(bar);
|
||||||
**/
|
**/
|
||||||
template <typename ATo, typename AFrom>
|
template <typename ATo, typename AFrom>
|
||||||
obj<ATo> variant(obj<AFrom> from) {
|
obj<ATo> variant(obj<AFrom> from) {
|
||||||
return variant<ATo>(from._typeseq(), from.data());
|
auto retval = try_variant<ATo>(from);
|
||||||
|
|
||||||
|
if (!retval)
|
||||||
|
throw std::runtime_error(tostr("FacetRegistry::try_variant failed",
|
||||||
|
xtag("AFrom.tseq", typeseq::id<AFrom>()),
|
||||||
|
xtag("ATo.tseq", typeseq::id<ATo>())));
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Runtime polymorphism:
|
||||||
|
* Switch @param from from interface @tp AFrom to interface @tp ATo.
|
||||||
|
*
|
||||||
|
* Use:
|
||||||
|
* obj<AFoo> foo
|
||||||
|
* = ...; // Foo instance with variant impl
|
||||||
|
* obj<ABar> bar
|
||||||
|
* = FacetRegistry::try_variant<ABar,AFoo>(foo);
|
||||||
|
* if (bar) {
|
||||||
|
* // success
|
||||||
|
* } else {
|
||||||
|
* // foo::DataType doesn't appear to support ABar
|
||||||
|
* }
|
||||||
|
**/
|
||||||
|
template <typename ATo, typename AFrom>
|
||||||
|
obj<ATo> try_variant(obj<AFrom> from) {
|
||||||
|
return try_variant<ATo>(from._typeseq(), from.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Runtime polymorphism:
|
/** Runtime polymorphism:
|
||||||
|
|
@ -129,9 +162,24 @@ namespace xo {
|
||||||
* = FacetRegistry::variant<ABar>(foo._typeseq(), foo.opaque_data());
|
* = FacetRegistry::variant<ABar>(foo._typeseq(), foo.opaque_data());
|
||||||
**/
|
**/
|
||||||
template <typename AFacet>
|
template <typename AFacet>
|
||||||
obj<AFacet> variant(typeseq repr_id, void * data) {
|
obj<AFacet> try_variant(typeseq repr_id, void * data) {
|
||||||
const AFacet * iface = this->lookup<AFacet>(repr_id);
|
const AFacet * iface = this->lookup<AFacet>(repr_id);
|
||||||
return obj<AFacet>::variant(iface, data);;
|
|
||||||
|
if (iface)
|
||||||
|
return obj<AFacet>(iface, data);
|
||||||
|
else
|
||||||
|
return obj<AFacet>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump(std::ostream * p_out) {
|
||||||
|
(*p_out) << std::endl;
|
||||||
|
(*p_out) << "<FacetRegistry" << std::endl;
|
||||||
|
for (auto & kv : registry_) {
|
||||||
|
(*p_out)
|
||||||
|
<< " [" << kv.first.first << "," << kv.first.second << "]"
|
||||||
|
<< " -> " << kv.second << std::endl;
|
||||||
|
}
|
||||||
|
(*p_out) << ">" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -142,8 +190,8 @@ namespace xo {
|
||||||
* @param impl pointer to stateless implementation instance
|
* @param impl pointer to stateless implementation instance
|
||||||
**/
|
**/
|
||||||
void _register_impl(typeseq facet_id,
|
void _register_impl(typeseq facet_id,
|
||||||
typeseq repr_id,
|
typeseq repr_id,
|
||||||
const void * impl)
|
const void * impl)
|
||||||
{
|
{
|
||||||
registry_[key_type(facet_id, repr_id)] = impl;
|
registry_[key_type(facet_id, repr_id)] = impl;
|
||||||
}
|
}
|
||||||
|
|
@ -155,12 +203,20 @@ namespace xo {
|
||||||
const void * _lookup(typeseq facet_id,
|
const void * _lookup(typeseq facet_id,
|
||||||
typeseq repr_id) const
|
typeseq repr_id) const
|
||||||
{
|
{
|
||||||
|
scope log(XO_DEBUG(false));
|
||||||
|
log && log(xtag("facet_id", facet_id),
|
||||||
|
xtag("repr_id", repr_id));
|
||||||
|
|
||||||
auto ix = registry_.find(key_type(facet_id, repr_id));
|
auto ix = registry_.find(key_type(facet_id, repr_id));
|
||||||
|
|
||||||
if (ix == registry_.end())
|
const void *retval = nullptr;
|
||||||
return nullptr;
|
|
||||||
else
|
if (ix != registry_.end())
|
||||||
return ix->second;
|
retval = ix->second;
|
||||||
|
|
||||||
|
log && log(xtag("retval", retval));
|
||||||
|
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,32 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <xo/alloc2/Allocator.hpp>
|
||||||
|
#include <xo/indentlog/print/ppindentinfo.hpp>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
namespace xo {
|
namespace xo {
|
||||||
namespace scm {
|
namespace scm {
|
||||||
using DInteger = std::int64_t;
|
struct DInteger {
|
||||||
|
using AAllocator = xo::mm::AAllocator;
|
||||||
|
using ppindentinfo = xo::print::ppindentinfo;
|
||||||
|
|
||||||
|
explicit DInteger(long x) : value_{x} {}
|
||||||
|
|
||||||
|
/** allocate boxed value @p x using memory from @p mm **/
|
||||||
|
static DInteger * make(obj<AAllocator> mm,
|
||||||
|
long x);
|
||||||
|
|
||||||
|
double value() const noexcept { return value_; }
|
||||||
|
|
||||||
|
bool pretty(const ppindentinfo & ppii) const;
|
||||||
|
|
||||||
|
operator long() const noexcept { return value_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
/** boxed integer value **/
|
||||||
|
long value_;
|
||||||
|
};
|
||||||
} /*nmaespace obj*/
|
} /*nmaespace obj*/
|
||||||
} /*namespace xo*/
|
} /*namespace xo*/
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
namespace xo {
|
namespace xo {
|
||||||
namespace scm {
|
namespace scm {
|
||||||
|
|
||||||
|
// TODO: consider renaming to DCons
|
||||||
struct DList {
|
struct DList {
|
||||||
using size_type = std::size_t;
|
using size_type = std::size_t;
|
||||||
using AGCObject = xo::mm::AGCObject;
|
using AGCObject = xo::mm::AGCObject;
|
||||||
|
|
@ -22,8 +23,27 @@ namespace xo {
|
||||||
DList(xo::obj<AGCObject> h,
|
DList(xo::obj<AGCObject> h,
|
||||||
DList * r) : head_{h}, rest_{r} {}
|
DList * r) : head_{h}, rest_{r} {}
|
||||||
|
|
||||||
|
template <typename AConsFacet = AGCObject>
|
||||||
|
static obj<AConsFacet,DList> nil();
|
||||||
|
|
||||||
|
/** shortcut for
|
||||||
|
* cons(mm, cdr, cdr.data())
|
||||||
|
**/
|
||||||
|
template <typename AConsFacet = AGCObject, typename ACdrFacet = AGCObject>
|
||||||
|
static obj<AConsFacet,DList> cons(obj<AAllocator> mm,
|
||||||
|
obj<AGCObject> car,
|
||||||
|
obj<ACdrFacet,DList> cdr);
|
||||||
|
|
||||||
/** sentinel for null list **/
|
/** sentinel for null list **/
|
||||||
static DList * null();
|
static DList * _nil();
|
||||||
|
|
||||||
|
/** list with first element @p car,
|
||||||
|
* followed by contents of list @p cdr.
|
||||||
|
* Shares structure with @p cdr
|
||||||
|
**/
|
||||||
|
static DList * _cons(obj<AAllocator> mm,
|
||||||
|
obj<AGCObject> car,
|
||||||
|
DList * cdr);
|
||||||
|
|
||||||
/** list with one element @p h1, allocated from @p mm **/
|
/** list with one element @p h1, allocated from @p mm **/
|
||||||
static DList * list(obj<AAllocator> mm,
|
static DList * list(obj<AAllocator> mm,
|
||||||
|
|
@ -51,6 +71,22 @@ namespace xo {
|
||||||
DList * rest_ = nullptr;
|
DList * rest_ = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename AConsFacet>
|
||||||
|
obj<AConsFacet,DList>
|
||||||
|
DList::nil()
|
||||||
|
{
|
||||||
|
return obj<AConsFacet,DList>(DList::_nil());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename AConsFacet, typename ACdrFacet>
|
||||||
|
obj<AConsFacet,DList>
|
||||||
|
DList::cons(obj<AAllocator> mm,
|
||||||
|
obj<AGCObject> car,
|
||||||
|
obj<ACdrFacet,DList> cdr)
|
||||||
|
{
|
||||||
|
return obj<AConsFacet,DList>(DList::_cons(mm, car, cdr.data()));
|
||||||
|
}
|
||||||
|
|
||||||
} /*namespace scm*/
|
} /*namespace scm*/
|
||||||
} /*namespace xo*/
|
} /*namespace xo*/
|
||||||
|
|
||||||
|
|
|
||||||
57
xo-object2/include/xo/object2/IPrintable_DInteger.hpp
Normal file
57
xo-object2/include/xo/object2/IPrintable_DInteger.hpp
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
/** @file IPrintable_DInteger.hpp
|
||||||
|
*
|
||||||
|
* Generated automagically from ingredients:
|
||||||
|
* 1. code generator:
|
||||||
|
* [/home/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet]
|
||||||
|
* arguments:
|
||||||
|
* --input [idl/IPrintable_DInteger.json5]
|
||||||
|
* 2. jinja2 template for abstract facet .hpp file:
|
||||||
|
* [iface_facet_any.hpp.j2]
|
||||||
|
* 3. idl for facet methods
|
||||||
|
* [idl/IPrintable_DInteger.json5]
|
||||||
|
**/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <xo/printable2/Printable.hpp>
|
||||||
|
#include <xo/printable2/detail/IPrintable_Xfer.hpp>
|
||||||
|
#include "DInteger.hpp"
|
||||||
|
|
||||||
|
namespace xo { namespace scm { class IPrintable_DInteger; } }
|
||||||
|
|
||||||
|
namespace xo {
|
||||||
|
namespace facet {
|
||||||
|
template <>
|
||||||
|
struct FacetImplementation<xo::print::APrintable,
|
||||||
|
xo::scm::DInteger>
|
||||||
|
{
|
||||||
|
using ImplType = xo::print::IPrintable_Xfer
|
||||||
|
<xo::scm::DInteger,
|
||||||
|
xo::scm::IPrintable_DInteger>;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace xo {
|
||||||
|
namespace scm {
|
||||||
|
/** @class IPrintable_DInteger
|
||||||
|
**/
|
||||||
|
class IPrintable_DInteger {
|
||||||
|
public:
|
||||||
|
/** @defgroup scm-printable-dinteger-type-traits **/
|
||||||
|
///@{
|
||||||
|
using ppindentinfo = xo::print::APrintable::ppindentinfo;
|
||||||
|
///@}
|
||||||
|
/** @defgroup scm-printable-dinteger-methods **/
|
||||||
|
///@{
|
||||||
|
/** Pretty-printing support for this object.
|
||||||
|
See [xo-indentlog/xo/indentlog/pretty.hpp] **/
|
||||||
|
static bool pretty(const DInteger & self, const ppindentinfo & ppii);
|
||||||
|
|
||||||
|
///@}
|
||||||
|
};
|
||||||
|
|
||||||
|
} /*namespace scm*/
|
||||||
|
} /*namespace xo*/
|
||||||
|
|
||||||
|
/* end */
|
||||||
|
|
@ -13,6 +13,9 @@ namespace xo {
|
||||||
* Return true iff all types register successfully.
|
* Return true iff all types register successfully.
|
||||||
**/
|
**/
|
||||||
bool object2_register_types(obj<xo::mm::ACollector> gc);
|
bool object2_register_types(obj<xo::mm::ACollector> gc);
|
||||||
|
|
||||||
|
/** Register object2 (facet,impl) combinations with FacetRegistry **/
|
||||||
|
bool object2_register_facets();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,12 @@ set(SELF_SRCS
|
||||||
IGCObject_DList.cpp
|
IGCObject_DList.cpp
|
||||||
ISequence_Any.cpp
|
ISequence_Any.cpp
|
||||||
ISequence_DList.cpp
|
ISequence_DList.cpp
|
||||||
IPrintable_DFloat.cpp
|
|
||||||
IPrintable_DList.cpp
|
IPrintable_DList.cpp
|
||||||
|
IPrintable_DFloat.cpp
|
||||||
|
IPrintable_DInteger.cpp
|
||||||
DList.cpp
|
DList.cpp
|
||||||
DFloat.cpp
|
DFloat.cpp
|
||||||
|
DInteger.cpp
|
||||||
object2_register_types.cpp
|
object2_register_types.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
32
xo-object2/src/object2/DInteger.cpp
Normal file
32
xo-object2/src/object2/DInteger.cpp
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
/** @file DInteger.cpp
|
||||||
|
*
|
||||||
|
* @author Roland Conybeare, Jan 2026
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include "DInteger.hpp"
|
||||||
|
#include <xo/indentlog/print/pretty.hpp>
|
||||||
|
|
||||||
|
namespace xo {
|
||||||
|
using xo::facet::typeseq;
|
||||||
|
using xo::print::ppdetail_atomic;
|
||||||
|
|
||||||
|
namespace scm {
|
||||||
|
DInteger *
|
||||||
|
DInteger::make(obj<AAllocator> mm,
|
||||||
|
long x)
|
||||||
|
{
|
||||||
|
void * mem = mm.alloc(typeseq::id<DInteger>(),
|
||||||
|
sizeof(DInteger));
|
||||||
|
|
||||||
|
return new (mem) DInteger(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
DInteger::pretty(const ppindentinfo & ppii) const
|
||||||
|
{
|
||||||
|
return ppdetail_atomic<long>::print_pretty(ppii, value_);
|
||||||
|
}
|
||||||
|
} /*namespace scm*/
|
||||||
|
} /*namespace xo*/
|
||||||
|
|
||||||
|
/* end DInteger.cpp */
|
||||||
|
|
@ -19,18 +19,28 @@ namespace xo {
|
||||||
static DList s_null(obj<AGCObject>(), nullptr);
|
static DList s_null(obj<AGCObject>(), nullptr);
|
||||||
|
|
||||||
DList *
|
DList *
|
||||||
DList::null()
|
DList::_nil()
|
||||||
{
|
{
|
||||||
return &s_null;
|
return &s_null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DList *
|
||||||
|
DList::_cons(obj<AAllocator> mm,
|
||||||
|
obj<AGCObject> car,
|
||||||
|
DList * cdr)
|
||||||
|
{
|
||||||
|
void * mem = mm.alloc(typeseq::id<DList>(), sizeof(DList));
|
||||||
|
|
||||||
|
return new (mem) DList(car, cdr);
|
||||||
|
}
|
||||||
|
|
||||||
DList *
|
DList *
|
||||||
DList::list(obj<AAllocator> mm,
|
DList::list(obj<AAllocator> mm,
|
||||||
obj<AGCObject> h1)
|
obj<AGCObject> h1)
|
||||||
{
|
{
|
||||||
void * mem = mm.alloc(typeseq::id<DList>(), sizeof(DList));
|
void * mem = mm.alloc(typeseq::id<DList>(), sizeof(DList));
|
||||||
|
|
||||||
return new (mem) DList(h1, DList::null());
|
return new (mem) DList(h1, DList::_nil());
|
||||||
}
|
}
|
||||||
|
|
||||||
DList *
|
DList *
|
||||||
|
|
@ -112,7 +122,8 @@ namespace xo {
|
||||||
|
|
||||||
obj<APrintable> elt
|
obj<APrintable> elt
|
||||||
= FacetRegistry::instance().variant<APrintable, AGCObject>(l->head_);
|
= FacetRegistry::instance().variant<APrintable, AGCObject>(l->head_);
|
||||||
// what if no converter registered ?
|
|
||||||
|
assert(elt);
|
||||||
|
|
||||||
if (!pps->print_upto(elt))
|
if (!pps->print_upto(elt))
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
28
xo-object2/src/object2/IPrintable_DInteger.cpp
Normal file
28
xo-object2/src/object2/IPrintable_DInteger.cpp
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
/** @file IPrintable_DInteger.cpp
|
||||||
|
*
|
||||||
|
* Generated automagically from ingredients:
|
||||||
|
* 1. code generator:
|
||||||
|
* [/home/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet]
|
||||||
|
* arguments:
|
||||||
|
* --input [idl/IPrintable_DInteger.json5]
|
||||||
|
* 2. jinja2 template for abstract facet .hpp file:
|
||||||
|
* [iface_facet_any.hpp.j2]
|
||||||
|
* 3. idl for facet methods
|
||||||
|
* [idl/IPrintable_DInteger.json5]
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include "IPrintable_DInteger.hpp"
|
||||||
|
|
||||||
|
namespace xo {
|
||||||
|
namespace scm {
|
||||||
|
auto
|
||||||
|
IPrintable_DInteger::pretty(const DInteger & self, const ppindentinfo & ppii) -> bool
|
||||||
|
{
|
||||||
|
return self.pretty(ppii);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} /*namespace scm*/
|
||||||
|
} /*namespace xo*/
|
||||||
|
|
||||||
|
/* end IPrintable_DInteger.cpp */
|
||||||
|
|
@ -4,22 +4,36 @@
|
||||||
**/
|
**/
|
||||||
|
|
||||||
#include "object2_register_types.hpp"
|
#include "object2_register_types.hpp"
|
||||||
|
|
||||||
#include "IGCObject_DList.hpp"
|
#include "IGCObject_DList.hpp"
|
||||||
#include "IGCObject_DFloat.hpp"
|
#include "IGCObject_DFloat.hpp"
|
||||||
#include "IGCObject_DInteger.hpp"
|
#include "IGCObject_DInteger.hpp"
|
||||||
|
|
||||||
|
#include "IPrintable_DList.hpp"
|
||||||
|
//#include "IPrintable_DFloat.hpp"
|
||||||
|
#include "IPrintable_DInteger.hpp"
|
||||||
|
|
||||||
|
#include <xo/facet/FacetRegistry.hpp>
|
||||||
|
#include <xo/indentlog/scope.hpp>
|
||||||
|
|
||||||
namespace xo {
|
namespace xo {
|
||||||
|
using xo::print::APrintable;
|
||||||
|
using xo::mm::AAllocator;
|
||||||
using xo::mm::ACollector;
|
using xo::mm::ACollector;
|
||||||
using xo::mm::AGCObject;
|
using xo::mm::AGCObject;
|
||||||
using xo::mm::IGCObject_Any;
|
using xo::mm::IGCObject_Any;
|
||||||
|
using xo::facet::FacetRegistry;
|
||||||
using xo::facet::impl_for;
|
using xo::facet::impl_for;
|
||||||
using xo::facet::typeseq;
|
using xo::facet::typeseq;
|
||||||
|
using xo::scope;
|
||||||
|
|
||||||
namespace scm {
|
namespace scm {
|
||||||
|
|
||||||
bool
|
bool
|
||||||
object2_register_types(obj<ACollector> gc)
|
object2_register_types(obj<ACollector> gc)
|
||||||
{
|
{
|
||||||
|
scope log(XO_DEBUG(true));
|
||||||
|
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
|
|
||||||
ok &= gc.install_type(impl_for<AGCObject, DList>());
|
ok &= gc.install_type(impl_for<AGCObject, DList>());
|
||||||
|
|
@ -28,6 +42,31 @@ namespace xo {
|
||||||
|
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
object2_register_facets()
|
||||||
|
{
|
||||||
|
scope log(XO_DEBUG(true));
|
||||||
|
|
||||||
|
FacetRegistry::register_impl<AGCObject, DList>();
|
||||||
|
FacetRegistry::register_impl<APrintable, DList>();
|
||||||
|
|
||||||
|
FacetRegistry::register_impl<AGCObject, DFloat>();
|
||||||
|
// FacetRegistry::register_impl<APrintable, DFloat>();
|
||||||
|
|
||||||
|
FacetRegistry::register_impl<AGCObject, DInteger>();
|
||||||
|
FacetRegistry::register_impl<APrintable, DInteger>();
|
||||||
|
|
||||||
|
log && log(xtag("DList.tseq", typeseq::id<DList>()));
|
||||||
|
log && log(xtag("DFloat.tseq", typeseq::id<DFloat>()));
|
||||||
|
log && log(xtag("DInteger.tseq", typeseq::id<DInteger>()));
|
||||||
|
|
||||||
|
log && log(xtag("AAllocator.tseq", typeseq::id<AAllocator>()));
|
||||||
|
log && log(xtag("APrintable.tseq", typeseq::id<APrintable>()));
|
||||||
|
log && log(xtag("AGCObject.tseq", typeseq::id<AGCObject>()));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} /*namespace xo*/
|
} /*namespace xo*/
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ set(UTEST_EXE utest.object2)
|
||||||
set(UTEST_SRCS
|
set(UTEST_SRCS
|
||||||
object2_utest_main.cpp
|
object2_utest_main.cpp
|
||||||
X1Collector.test.cpp
|
X1Collector.test.cpp
|
||||||
|
Printable.test.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
xo_add_utest_executable(${UTEST_EXE} ${UTEST_SRCS})
|
xo_add_utest_executable(${UTEST_EXE} ${UTEST_SRCS})
|
||||||
|
|
|
||||||
141
xo-object2/utest/Printable.test.cpp
Normal file
141
xo-object2/utest/Printable.test.cpp
Normal file
|
|
@ -0,0 +1,141 @@
|
||||||
|
/** @file Printable.test.cpp
|
||||||
|
*
|
||||||
|
* @author Roland Conybeare, Jan 2026
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include "DList.hpp"
|
||||||
|
#include "object2_register_types.hpp"
|
||||||
|
|
||||||
|
#include <xo/object2/DList.hpp>
|
||||||
|
#include <xo/object2/IGCObject_DList.hpp>
|
||||||
|
#include <xo/object2/IPrintable_DList.hpp>
|
||||||
|
|
||||||
|
#include <xo/object2/DInteger.hpp>
|
||||||
|
#include <xo/object2/IGCObject_DInteger.hpp>
|
||||||
|
|
||||||
|
#include <xo/gc/Collector.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/indentlog/scope.hpp>
|
||||||
|
#include <xo/indentlog/print/tag.hpp>
|
||||||
|
|
||||||
|
#include <catch2/catch.hpp>
|
||||||
|
|
||||||
|
namespace ut {
|
||||||
|
using xo::scm::object2_register_types;
|
||||||
|
using xo::scm::object2_register_facets;
|
||||||
|
using xo::scm::DList;
|
||||||
|
using xo::scm::DInteger;
|
||||||
|
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::facet::FacetRegistry;
|
||||||
|
using xo::facet::with_facet;
|
||||||
|
using xo::facet::obj;
|
||||||
|
using xo::facet::typeseq;
|
||||||
|
using xo::print::ppstate_standalone;
|
||||||
|
using xo::print::ppconfig;
|
||||||
|
using xo::scope;
|
||||||
|
using xo::xtag;
|
||||||
|
using std::string;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
struct testcase_pp {
|
||||||
|
explicit testcase_pp(size_t gc_z, size_t gc_threshold, int z, const std::string & expected)
|
||||||
|
: gc_gen_size_{gc_z}, gc_trigger_threshold_{gc_threshold}, expected_{expected} {
|
||||||
|
for (int i = 0; i < z; ++i) {
|
||||||
|
list_.push_back(1000 + 197 * i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t gc_gen_size_ = 0;
|
||||||
|
size_t gc_trigger_threshold_ = 0;
|
||||||
|
std::vector<int> list_;
|
||||||
|
std::string expected_;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<testcase_pp>
|
||||||
|
s_testcase_v = {
|
||||||
|
testcase_pp(16384, 8192, 0, "()"),
|
||||||
|
testcase_pp(16384, 8192, 1, "(1000)"),
|
||||||
|
testcase_pp(16384, 8192, 2, "(1000 1197)"),
|
||||||
|
testcase_pp(16384, 8192, 5, "(1000 1197 1394 1591 1788)"),
|
||||||
|
testcase_pp(16384, 8192, 10, "(1000 1197 1394 1591 1788 1985 2182 2379 2576 2773)"),
|
||||||
|
testcase_pp(16384, 8192, 20, "(...)"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("printable1", "[pp][x1][list]")
|
||||||
|
{
|
||||||
|
constexpr bool c_debug_flag = true;
|
||||||
|
scope log(XO_DEBUG(c_debug_flag));
|
||||||
|
|
||||||
|
bool ok = object2_register_facets();
|
||||||
|
REQUIRE(ok);
|
||||||
|
|
||||||
|
FacetRegistry::instance().dump(&std::cerr);
|
||||||
|
|
||||||
|
for (std::size_t i_tc = 0, n_tc = s_testcase_v.size(); i_tc < n_tc; ++i_tc) {
|
||||||
|
try {
|
||||||
|
const testcase_pp & tc = s_testcase_v[i_tc];
|
||||||
|
|
||||||
|
CollectorConfig cfg{
|
||||||
|
.name_ = "pp_test",
|
||||||
|
.arena_config_ = ArenaConfig{
|
||||||
|
.size_ = tc.gc_gen_size_,
|
||||||
|
.store_header_flag_ = true},
|
||||||
|
.object_types_z_ = 16384,
|
||||||
|
.gc_trigger_v_{{tc.gc_trigger_threshold_,
|
||||||
|
tc.gc_trigger_threshold_}},
|
||||||
|
.debug_flag_ = c_debug_flag
|
||||||
|
};
|
||||||
|
|
||||||
|
DX1Collector gc(cfg);
|
||||||
|
auto gc_o = with_facet<AAllocator>::mkobj(&gc);
|
||||||
|
auto c_o = with_facet<ACollector>::mkobj(&gc);
|
||||||
|
|
||||||
|
bool ok = object2_register_types(c_o);
|
||||||
|
REQUIRE(ok);
|
||||||
|
|
||||||
|
auto l0_o = DList::nil();
|
||||||
|
|
||||||
|
c_o.add_gc_root(&l0_o);
|
||||||
|
|
||||||
|
for(int ip1 = tc.list_.size(); ip1 > 0; --ip1) {
|
||||||
|
// auto xi_o = Integer::make(g_o, ...);
|
||||||
|
DInteger * xi = DInteger::make(gc_o, tc.list_[ip1 - 1]);
|
||||||
|
auto xi_o = with_facet<AGCObject>::mkobj(xi);
|
||||||
|
|
||||||
|
l0_o = DList::cons(gc_o, xi_o, l0_o);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: log_streambuf using DArena
|
||||||
|
std::stringstream ss;
|
||||||
|
ppconfig ppc;
|
||||||
|
ppstate_standalone pps(&ss, 0, &ppc);
|
||||||
|
|
||||||
|
obj<APrintable,DList> l0_po(static_cast<DList*>(l0_o.data()));
|
||||||
|
REQUIRE(l0_po._typeseq() == typeseq::id<DList>());
|
||||||
|
|
||||||
|
pps.pretty(l0_po);
|
||||||
|
|
||||||
|
REQUIRE(ss.str() == string(tc.expected_));
|
||||||
|
} catch (std::exception & ex) {
|
||||||
|
std::cerr << "caught exception: " << ex.what() << std::endl;
|
||||||
|
REQUIRE(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} /* TEST_CASE(printable1) */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* end Printable.test.cpp */
|
||||||
|
|
@ -74,7 +74,7 @@ namespace ut {
|
||||||
|
|
||||||
TEST_CASE("x1", "[gc][x1]")
|
TEST_CASE("x1", "[gc][x1]")
|
||||||
{
|
{
|
||||||
constexpr bool c_debug_flag = true;
|
constexpr bool c_debug_flag = false;
|
||||||
scope log(XO_DEBUG(c_debug_flag));
|
scope log(XO_DEBUG(c_debug_flag));
|
||||||
|
|
||||||
for (std::size_t i_tc = 0, n_tc = s_testcase_v.size(); i_tc < n_tc; ++i_tc) {
|
for (std::size_t i_tc = 0, n_tc = s_testcase_v.size(); i_tc < n_tc; ++i_tc) {
|
||||||
|
|
|
||||||
|
|
@ -18,4 +18,7 @@
|
||||||
#include "detail/IPrintable_Xfer.hpp"
|
#include "detail/IPrintable_Xfer.hpp"
|
||||||
#include "detail/RPrintable.hpp"
|
#include "detail/RPrintable.hpp"
|
||||||
|
|
||||||
|
// todo: additional includes in idl above
|
||||||
|
#include "detail/ppdetail_Printable.hpp"
|
||||||
|
|
||||||
/* end Printable.hpp */
|
/* end Printable.hpp */
|
||||||
|
|
@ -47,7 +47,7 @@ public:
|
||||||
/** Pretty-printing support for this object.
|
/** Pretty-printing support for this object.
|
||||||
See [xo-indentlog/xo/indentlog/pretty.hpp]
|
See [xo-indentlog/xo/indentlog/pretty.hpp]
|
||||||
**/
|
**/
|
||||||
virtual bool pretty(Copaque data, const ppindentinfo & ppii) = 0;
|
virtual bool pretty(Copaque data, const ppindentinfo & ppii) const = 0;
|
||||||
|
|
||||||
// nonconst methods
|
// nonconst methods
|
||||||
///@}
|
///@}
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ namespace print {
|
||||||
|
|
||||||
// const methods
|
// const methods
|
||||||
typeseq _typeseq() const noexcept override { return s_typeseq; }
|
typeseq _typeseq() const noexcept override { return s_typeseq; }
|
||||||
[[noreturn]] bool pretty(Copaque, const ppindentinfo &) override { _fatal(); }
|
[[noreturn]] bool pretty(Copaque, const ppindentinfo &) const override { _fatal(); }
|
||||||
|
|
||||||
// nonconst methods
|
// nonconst methods
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ namespace print {
|
||||||
|
|
||||||
// const methods
|
// const methods
|
||||||
typeseq _typeseq() const noexcept override { return s_typeseq; }
|
typeseq _typeseq() const noexcept override { return s_typeseq; }
|
||||||
bool pretty(Copaque data, const ppindentinfo & ppii) override {
|
bool pretty(Copaque data, const ppindentinfo & ppii) const override {
|
||||||
return I::pretty(_dcast(data), ppii);
|
return I::pretty(_dcast(data), ppii);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ public:
|
||||||
using ObjectType = Object;
|
using ObjectType = Object;
|
||||||
using DataPtr = Object::DataPtr;
|
using DataPtr = Object::DataPtr;
|
||||||
using ppindentinfo = APrintable::ppindentinfo;
|
using ppindentinfo = APrintable::ppindentinfo;
|
||||||
|
using typeseq = xo::facet::typeseq;
|
||||||
///@}
|
///@}
|
||||||
|
|
||||||
/** @defgroup print-printable-router-ctors **/
|
/** @defgroup print-printable-router-ctors **/
|
||||||
|
|
@ -46,8 +47,8 @@ public:
|
||||||
///@{
|
///@{
|
||||||
|
|
||||||
// const methods
|
// const methods
|
||||||
int32_t _typeseq() const noexcept { return O::iface()->_typeseq(); }
|
typeseq _typeseq() const noexcept { return O::iface()->_typeseq(); }
|
||||||
bool pretty(const ppindentinfo & ppii) {
|
bool pretty(const ppindentinfo & ppii) const {
|
||||||
return O::iface()->pretty(O::data(), ppii);
|
return O::iface()->pretty(O::data(), ppii);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
/** @file ppdetail_Printable.hpp
|
||||||
|
*
|
||||||
|
* @author Roland Conybeare, Jan 2026
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include <xo/indentlog/print/pretty.hpp>
|
||||||
|
#include "Printable.hpp"
|
||||||
|
|
||||||
|
namespace xo {
|
||||||
|
namespace print {
|
||||||
|
template <typename DRepr>
|
||||||
|
struct ppdetail<xo::facet::obj<APrintable, DRepr>> {
|
||||||
|
static bool print_pretty(const ppindentinfo & ppii,
|
||||||
|
const xo::facet::obj<APrintable, DRepr> & x) {
|
||||||
|
return x.pretty(ppii);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} /*namespace xo*/
|
||||||
|
|
||||||
|
/* end ppdetail_Printable.hpp */
|
||||||
Loading…
Add table
Add a link
Reference in a new issue