xo-objectd2 xo-printable xo-facet: pp working for List(Integer)
Also streamline facet switching
This commit is contained in:
parent
d5e1e6290b
commit
148d5e9ca0
13 changed files with 379 additions and 8 deletions
|
|
@ -5,11 +5,32 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <xo/alloc2/Allocator.hpp>
|
||||
#include <xo/indentlog/print/ppindentinfo.hpp>
|
||||
#include <cstdint>
|
||||
|
||||
namespace xo {
|
||||
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*/
|
||||
} /*namespace xo*/
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
namespace xo {
|
||||
namespace scm {
|
||||
|
||||
// TODO: consider renaming to DCons
|
||||
struct DList {
|
||||
using size_type = std::size_t;
|
||||
using AGCObject = xo::mm::AGCObject;
|
||||
|
|
@ -22,8 +23,27 @@ namespace xo {
|
|||
DList(xo::obj<AGCObject> h,
|
||||
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 **/
|
||||
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 **/
|
||||
static DList * list(obj<AAllocator> mm,
|
||||
|
|
@ -51,6 +71,22 @@ namespace xo {
|
|||
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 xo*/
|
||||
|
||||
|
|
|
|||
57
include/xo/object2/IPrintable_DInteger.hpp
Normal file
57
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 */
|
||||
|
|
@ -54,4 +54,4 @@ See [xo-indentlog/xo/indentlog/pretty.hpp] **/
|
|||
} /*namespace scm*/
|
||||
} /*namespace xo*/
|
||||
|
||||
/* end */
|
||||
/* end */
|
||||
|
|
|
|||
|
|
@ -13,6 +13,9 @@ namespace xo {
|
|||
* Return true iff all types register successfully.
|
||||
**/
|
||||
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
|
||||
ISequence_Any.cpp
|
||||
ISequence_DList.cpp
|
||||
IPrintable_DFloat.cpp
|
||||
IPrintable_DList.cpp
|
||||
IPrintable_DFloat.cpp
|
||||
IPrintable_DInteger.cpp
|
||||
DList.cpp
|
||||
DFloat.cpp
|
||||
DInteger.cpp
|
||||
object2_register_types.cpp
|
||||
)
|
||||
|
||||
|
|
|
|||
32
src/object2/DInteger.cpp
Normal file
32
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);
|
||||
|
||||
DList *
|
||||
DList::null()
|
||||
DList::_nil()
|
||||
{
|
||||
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::list(obj<AAllocator> mm,
|
||||
obj<AGCObject> h1)
|
||||
{
|
||||
void * mem = mm.alloc(typeseq::id<DList>(), sizeof(DList));
|
||||
|
||||
return new (mem) DList(h1, DList::null());
|
||||
return new (mem) DList(h1, DList::_nil());
|
||||
}
|
||||
|
||||
DList *
|
||||
|
|
@ -112,7 +122,8 @@ namespace xo {
|
|||
|
||||
obj<APrintable> elt
|
||||
= FacetRegistry::instance().variant<APrintable, AGCObject>(l->head_);
|
||||
// what if no converter registered ?
|
||||
|
||||
assert(elt);
|
||||
|
||||
if (!pps->print_upto(elt))
|
||||
return false;
|
||||
|
|
|
|||
28
src/object2/IPrintable_DInteger.cpp
Normal file
28
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 "IGCObject_DList.hpp"
|
||||
#include "IGCObject_DFloat.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 {
|
||||
using xo::print::APrintable;
|
||||
using xo::mm::AAllocator;
|
||||
using xo::mm::ACollector;
|
||||
using xo::mm::AGCObject;
|
||||
using xo::mm::IGCObject_Any;
|
||||
using xo::facet::FacetRegistry;
|
||||
using xo::facet::impl_for;
|
||||
using xo::facet::typeseq;
|
||||
using xo::scope;
|
||||
|
||||
namespace scm {
|
||||
|
||||
bool
|
||||
object2_register_types(obj<ACollector> gc)
|
||||
{
|
||||
scope log(XO_DEBUG(true));
|
||||
|
||||
bool ok = true;
|
||||
|
||||
ok &= gc.install_type(impl_for<AGCObject, DList>());
|
||||
|
|
@ -28,6 +42,31 @@ namespace xo {
|
|||
|
||||
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*/
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ set(UTEST_EXE utest.object2)
|
|||
set(UTEST_SRCS
|
||||
object2_utest_main.cpp
|
||||
X1Collector.test.cpp
|
||||
Printable.test.cpp
|
||||
)
|
||||
|
||||
xo_add_utest_executable(${UTEST_EXE} ${UTEST_SRCS})
|
||||
|
|
|
|||
141
utest/Printable.test.cpp
Normal file
141
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]")
|
||||
{
|
||||
constexpr bool c_debug_flag = true;
|
||||
constexpr bool c_debug_flag = false;
|
||||
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) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue