xo-expression2 xo-gc: DSequenceExpr builds [WIP]
This commit is contained in:
parent
a0c27ca5bd
commit
1da2d17c30
2 changed files with 416 additions and 0 deletions
158
include/xo/object2/GCObjectConverter.hpp
Normal file
158
include/xo/object2/GCObjectConverter.hpp
Normal file
|
|
@ -0,0 +1,158 @@
|
||||||
|
/** @file GCObjectConverter.hpp
|
||||||
|
*
|
||||||
|
* @author Roland Conybeare, Nov 2025
|
||||||
|
**/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <xo/gc/GCObject.hpp>
|
||||||
|
#include <xo/alloc2/Allocator.hpp>
|
||||||
|
#include <xo/reflect/Reflect.hpp>
|
||||||
|
//#include "xo/reflect/TaggedPtr.hpp"
|
||||||
|
#include <xo/reflect/TypeDrivenMap.hpp>
|
||||||
|
|
||||||
|
namespace xo {
|
||||||
|
namespace scm {
|
||||||
|
/* Convert between xo::reflect::TaggedPtr and xo::Object for
|
||||||
|
* a particular wrapped c++ type
|
||||||
|
*/
|
||||||
|
struct Converter {
|
||||||
|
using AAllocator = xo::mm::AAllocator;
|
||||||
|
using AGCObject = xo::mm::AGCObject;
|
||||||
|
using TaggedPtr = xo::reflect::TaggedPtr;
|
||||||
|
/** convert from some reflected T* @p src to
|
||||||
|
* obj<AGCObject> dest
|
||||||
|
* using memory from allocator @p mm
|
||||||
|
**/
|
||||||
|
using ConvertToObjectFn = obj<AGCObject> (*)(obj<AAllocator> mm,
|
||||||
|
TaggedPtr src);
|
||||||
|
/** convert from obj<AGCObject> @p src to some refected T* @p dest
|
||||||
|
* using memory from allocator @p mm.
|
||||||
|
*
|
||||||
|
* NOTE: obj<AGCObject> is gc-aware -> will likely reside in
|
||||||
|
* a collected memory region.
|
||||||
|
**/
|
||||||
|
using ConvertFromObjectFn = TaggedPtr (*)(obj<AAllocator> mm,
|
||||||
|
obj<AGCObject> obj);
|
||||||
|
|
||||||
|
public:
|
||||||
|
Converter() = default;
|
||||||
|
explicit Converter(ConvertToObjectFn to,
|
||||||
|
ConvertFromObjectFn from)
|
||||||
|
: cvt_to_object_{to},
|
||||||
|
cvt_from_object_{from}
|
||||||
|
{}
|
||||||
|
|
||||||
|
/** convert tagged pointer @p tp to new object,
|
||||||
|
* allocated via @p mm.
|
||||||
|
*
|
||||||
|
* Conversion will typically be for some specific type;
|
||||||
|
* see @ref ObjectConverter
|
||||||
|
**/
|
||||||
|
ConvertToObjectFn cvt_to_object_ = nullptr;
|
||||||
|
|
||||||
|
/** convert object to tagged pointer @p,
|
||||||
|
* allocated via @p mm.
|
||||||
|
*
|
||||||
|
* Conversion will typically be for some specific type;
|
||||||
|
* see @ref ObjectConverter
|
||||||
|
**/
|
||||||
|
ConvertFromObjectFn cvt_from_object_ = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @class ObjectConverter
|
||||||
|
* @brief Conversion to/from Object
|
||||||
|
*
|
||||||
|
* For some instance of type T:
|
||||||
|
*
|
||||||
|
* @code
|
||||||
|
* ObjectConverter & converters = ...;
|
||||||
|
* T x = ...;
|
||||||
|
* TaggedPtr tp = Reflect::make_tp(&x);
|
||||||
|
* TypeId tid = tp.td()->id();
|
||||||
|
*
|
||||||
|
* const Converter * cvt = converters.cvt_.lookup(tid);
|
||||||
|
*
|
||||||
|
* if (cvt) {
|
||||||
|
* // cvt is a converter for T instances
|
||||||
|
* gp<Object> obj = (*(cvt->cvt_to_object_))(mm,
|
||||||
|
* @endcode
|
||||||
|
**/
|
||||||
|
class ObjectConverter {
|
||||||
|
public:
|
||||||
|
using AAllocator = xo::mm::AAllocator;
|
||||||
|
using AGCObject = xo::mm::AGCObject;
|
||||||
|
using Reflect = xo::reflect::Reflect;
|
||||||
|
using TaggedPtr = xo::reflect::TaggedPtr;
|
||||||
|
using TypeId = xo::reflect::TypeId;
|
||||||
|
|
||||||
|
/** sets up standard conversions **/
|
||||||
|
ObjectConverter();
|
||||||
|
|
||||||
|
/** singleton instance **/
|
||||||
|
static const ObjectConverter & instance();
|
||||||
|
|
||||||
|
/** establish conversion: use @p fn to convert values of type @tparam T. **/
|
||||||
|
template <typename T>
|
||||||
|
void establish_conversion(Converter::ConvertToObjectFn to,
|
||||||
|
Converter::ConvertFromObjectFn from);
|
||||||
|
|
||||||
|
/** convert tagged poitner @p tp to object. allocates memory only from @p mm.
|
||||||
|
* return nullptr if no converter available and @p throw_flag not set.
|
||||||
|
* throw exception if no converter available and @p throw_flag set.
|
||||||
|
**/
|
||||||
|
obj<AGCObject> tp_to_gco(obj<AAllocator> mm,
|
||||||
|
TaggedPtr tp,
|
||||||
|
bool throw_flag) const;
|
||||||
|
|
||||||
|
/** convert @p x to object.
|
||||||
|
* return converted object; if allocated, using only memory from @p mm.
|
||||||
|
* return nullptr if no converter available, and @p throw_flag not set.
|
||||||
|
* throw exception if no converter available, and @p throw_flag set.
|
||||||
|
**/
|
||||||
|
template <typename T>
|
||||||
|
obj<AGCObject> to_gco(obj<AAllocator> mm, const T & x, bool throw_flag);
|
||||||
|
|
||||||
|
/** convert object @p obj to tagged pointer, with typeid @p target_id.
|
||||||
|
* Allocates memory only from @p mm.
|
||||||
|
* return null TaggedPtr if no converter available and @p throw_flag not set.
|
||||||
|
* Throw exception if no converter available and @p throw_flag set.
|
||||||
|
**/
|
||||||
|
TaggedPtr tp_from_gco(obj<AAllocator> mm,
|
||||||
|
obj<AGCObject> obj,
|
||||||
|
TypeId target_type_id,
|
||||||
|
bool throw_flag) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/** expandable type-driven conversion table.
|
||||||
|
**/
|
||||||
|
xo::reflect::TypeDrivenMap<Converter> cvt_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void
|
||||||
|
ObjectConverter::establish_conversion(Converter::ConvertToObjectFn to,
|
||||||
|
Converter::ConvertFromObjectFn from)
|
||||||
|
{
|
||||||
|
using xo::reflect::TypeDescrW;
|
||||||
|
using xo::reflect::Reflect;
|
||||||
|
|
||||||
|
TypeDescrW td = Reflect::require<T>();
|
||||||
|
Converter * cvt = cvt_.require(td);
|
||||||
|
|
||||||
|
*cvt = Converter(to, from);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
auto
|
||||||
|
ObjectConverter::to_gco(obj<AAllocator> mm, const T & x, bool throw_flag)
|
||||||
|
-> obj<AGCObject>
|
||||||
|
{
|
||||||
|
TaggedPtr x_tp = Reflect::make_tp(&x);
|
||||||
|
|
||||||
|
return tp_to_gco(mm, x_tp, throw_flag);
|
||||||
|
}
|
||||||
|
} /*namespace scm*/
|
||||||
|
} /*namespace xo*/
|
||||||
|
|
||||||
|
/* end GCObjectConverter.hpp */
|
||||||
258
src/object2/GCObjectConverter.cpp
Normal file
258
src/object2/GCObjectConverter.cpp
Normal file
|
|
@ -0,0 +1,258 @@
|
||||||
|
/** @file GCObjectConverter.cpp
|
||||||
|
*
|
||||||
|
* @author Roland Conybeare, Nov 2025
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include "GCObjectConverter.hpp"
|
||||||
|
|
||||||
|
#include "DInteger.hpp"
|
||||||
|
#include "number/IGCObject_DInteger.hpp"
|
||||||
|
|
||||||
|
#include "DFloat.hpp"
|
||||||
|
#include "number/IGCObject_DFloat.hpp"
|
||||||
|
|
||||||
|
#include "DBoolean.hpp"
|
||||||
|
#include "boolean/IGCObject_DBoolean.hpp"
|
||||||
|
|
||||||
|
#include "DString.hpp"
|
||||||
|
#include "string/IGCObject_DString.hpp"
|
||||||
|
|
||||||
|
#include <xo/facet/obj.hpp>
|
||||||
|
#include <xo/reflect/TaggedPtr.hpp>
|
||||||
|
//#include "xo/alloc/Blob.hpp"
|
||||||
|
|
||||||
|
namespace xo {
|
||||||
|
using xo::mm::AGCObject;
|
||||||
|
using xo::reflect::Reflect;
|
||||||
|
using xo::reflect::TaggedPtr;
|
||||||
|
using xo::reflect::TypeId;
|
||||||
|
using xo::facet::obj;
|
||||||
|
using xo::facet::typeseq;
|
||||||
|
using xo::mm::AAllocator;
|
||||||
|
|
||||||
|
namespace scm {
|
||||||
|
namespace {
|
||||||
|
// DInteger <-> T
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
obj<AGCObject>
|
||||||
|
int_to_gco(obj<AAllocator> mm, TaggedPtr src)
|
||||||
|
{
|
||||||
|
T * native = src.recover_native<T>();
|
||||||
|
|
||||||
|
assert(native);
|
||||||
|
|
||||||
|
return DInteger::box<AGCObject>(mm, *native);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
TaggedPtr
|
||||||
|
gco_to_int(obj<AAllocator> mm,
|
||||||
|
obj<AGCObject> obj)
|
||||||
|
{
|
||||||
|
|
||||||
|
/* mm cannot be GC allocator!
|
||||||
|
* That's Object-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
auto int_obj = xo::facet::obj<AGCObject,DInteger>::from(obj); //Integer::from(obj);
|
||||||
|
|
||||||
|
if (!int_obj) {
|
||||||
|
throw std::runtime_error
|
||||||
|
(tostr("Object obj found where Integer expected",
|
||||||
|
xtag("obj", obj)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void * mem = mm.alloc(typeseq::id<T>(), sizeof(T));
|
||||||
|
|
||||||
|
T * p = reinterpret_cast<T *>(mem);
|
||||||
|
|
||||||
|
*p = int_obj.data()->value();
|
||||||
|
|
||||||
|
/* Note:
|
||||||
|
* retval invalidated when
|
||||||
|
* *mm cleared/recycled/collected
|
||||||
|
*/
|
||||||
|
|
||||||
|
return Reflect::make_tp(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
// DFloat <-> T
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
xo::facet::obj<xo::mm::AGCObject>
|
||||||
|
float_to_gco(xo::facet::obj<AAllocator> mm,
|
||||||
|
TaggedPtr src)
|
||||||
|
{
|
||||||
|
T * native = src.recover_native<T>();
|
||||||
|
|
||||||
|
assert(native);
|
||||||
|
|
||||||
|
return DFloat::box<AGCObject>(mm, *native);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
TaggedPtr
|
||||||
|
gco_to_float(obj<AAllocator> mm, obj<AGCObject> obj)
|
||||||
|
{
|
||||||
|
auto float_obj = xo::facet::obj<AGCObject,DFloat>::from(obj);
|
||||||
|
|
||||||
|
if (!float_obj) {
|
||||||
|
throw std::runtime_error
|
||||||
|
(tostr("Object obj found where Float expected",
|
||||||
|
xtag("obj", obj)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void * mem = mm.alloc(typeseq::id<T>(), sizeof(T));
|
||||||
|
|
||||||
|
T * p = reinterpret_cast<T *>(mem);
|
||||||
|
|
||||||
|
*p = float_obj.data()->value();
|
||||||
|
|
||||||
|
/* Note:
|
||||||
|
* retval invalidated when *mm cleared/recycled/collected
|
||||||
|
*/
|
||||||
|
|
||||||
|
return Reflect::make_tp(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
// DBoolean <-> T
|
||||||
|
|
||||||
|
obj<AGCObject>
|
||||||
|
bool_to_gco(obj<AAllocator> mm, TaggedPtr src)
|
||||||
|
{
|
||||||
|
bool * native = src.recover_native<bool>();
|
||||||
|
|
||||||
|
assert(native);
|
||||||
|
|
||||||
|
return DBoolean::box<AGCObject>(mm, *native);
|
||||||
|
}
|
||||||
|
|
||||||
|
TaggedPtr
|
||||||
|
gco_to_bool(obj<AAllocator> /*mm*/,
|
||||||
|
obj<AGCObject> obj)
|
||||||
|
{
|
||||||
|
static bool s_true = true;
|
||||||
|
static bool s_false = false;
|
||||||
|
|
||||||
|
auto bool_obj = xo::facet::obj<AGCObject,DBoolean>::from(obj);
|
||||||
|
|
||||||
|
if (!bool_obj) {
|
||||||
|
throw std::runtime_error
|
||||||
|
(tostr("Object obj found where Boolean expected",
|
||||||
|
xtag("obj", obj)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Reflect::make_tp(bool_obj.data()->value() ? &s_true : &s_false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// DString <-> T
|
||||||
|
// w/
|
||||||
|
// T = std::string
|
||||||
|
|
||||||
|
obj<AGCObject>
|
||||||
|
string_to_gco(obj<AAllocator> mm, TaggedPtr src)
|
||||||
|
{
|
||||||
|
// try std::string..
|
||||||
|
|
||||||
|
std::string * native = src.recover_native<std::string>();
|
||||||
|
|
||||||
|
assert(native);
|
||||||
|
|
||||||
|
DString * dstr = DString::from_str(mm, *native);
|
||||||
|
|
||||||
|
return xo::facet::obj<AGCObject,DString>(dstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
TaggedPtr
|
||||||
|
gco_to_string(obj<AAllocator> mm, obj<AGCObject> obj)
|
||||||
|
{
|
||||||
|
auto string_obj = xo::facet::obj<AGCObject,DString>::from(obj);
|
||||||
|
|
||||||
|
if (!string_obj) {
|
||||||
|
throw std::runtime_error
|
||||||
|
(tostr("Object obj founcd where String expected",
|
||||||
|
xtag("obj", obj)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// still don't have impl for this
|
||||||
|
// Need regular std::allocator interface
|
||||||
|
//
|
||||||
|
|
||||||
|
(void)mm;
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjectConverter::ObjectConverter()
|
||||||
|
{
|
||||||
|
this->establish_conversion<std::int32_t>(&int_to_gco<std::int32_t>,
|
||||||
|
&gco_to_int<std::int32_t>);
|
||||||
|
this->establish_conversion<std::int64_t>(&int_to_gco<std::int64_t>,
|
||||||
|
&gco_to_int<std::int64_t>);
|
||||||
|
|
||||||
|
this->establish_conversion<double>(&float_to_gco<double>,
|
||||||
|
&gco_to_float<double>);
|
||||||
|
|
||||||
|
this->establish_conversion<bool>(&bool_to_gco,
|
||||||
|
&gco_to_bool);
|
||||||
|
|
||||||
|
this->establish_conversion<std::string>(&string_to_gco,
|
||||||
|
&gco_to_string);
|
||||||
|
}
|
||||||
|
|
||||||
|
const ObjectConverter &
|
||||||
|
ObjectConverter::instance() {
|
||||||
|
static ObjectConverter s_instance;
|
||||||
|
|
||||||
|
return s_instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj<AGCObject>
|
||||||
|
ObjectConverter::tp_to_gco(obj<AAllocator> mm,
|
||||||
|
TaggedPtr x_tp,
|
||||||
|
bool throw_flag) const
|
||||||
|
{
|
||||||
|
using xo::reflect::Reflect;
|
||||||
|
using xo::reflect::TaggedPtr;
|
||||||
|
|
||||||
|
const Converter * cvt = cvt_.lookup(x_tp.td());
|
||||||
|
|
||||||
|
if (cvt) {
|
||||||
|
return (cvt->cvt_to_object_)(mm, x_tp);
|
||||||
|
} else {
|
||||||
|
if (throw_flag) {
|
||||||
|
throw std::runtime_error
|
||||||
|
(tostr("no to-object-converter available for instance of type",
|
||||||
|
xtag("id", x_tp.td()->id()),
|
||||||
|
xtag("name", x_tp.td()->short_name())));
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj<AGCObject>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TaggedPtr
|
||||||
|
ObjectConverter::tp_from_gco(obj<AAllocator> mm,
|
||||||
|
obj<AGCObject> obj,
|
||||||
|
TypeId target_id,
|
||||||
|
bool throw_flag) const
|
||||||
|
{
|
||||||
|
const Converter * cvt = cvt_.lookup(target_id);
|
||||||
|
|
||||||
|
if (cvt) {
|
||||||
|
return (cvt->cvt_from_object_)(mm, obj);
|
||||||
|
} else {
|
||||||
|
if (throw_flag) {
|
||||||
|
throw std::runtime_error
|
||||||
|
(tostr("no from-object-converter available for instance of type",
|
||||||
|
xtag("id", target_id)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return TaggedPtr::universal_null();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* end GCObjectConverter.cpp */
|
||||||
Loading…
Add table
Add a link
Reference in a new issue