xo-interpreter: Object->TaggedPtr conversion (prep for primitives)
This commit is contained in:
parent
22670cda3d
commit
4488117ac3
16 changed files with 371 additions and 26 deletions
40
xo-alloc/include/xo/alloc/Blob.hpp
Normal file
40
xo-alloc/include/xo/alloc/Blob.hpp
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
/** @file Blob.hpp
|
||||||
|
*
|
||||||
|
* @author Roland Conybeare, Nov 2025
|
||||||
|
**/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Object.hpp"
|
||||||
|
#include "IAlloc.hpp"
|
||||||
|
|
||||||
|
namespace xo {
|
||||||
|
/** Use to allocate opaque binary data,
|
||||||
|
* with object header.
|
||||||
|
*
|
||||||
|
* Not sure if we want to bother implementing reflection for this...
|
||||||
|
**/
|
||||||
|
class Blob : public Object {
|
||||||
|
public:
|
||||||
|
Blob(std::size_t z) : z_{z} {};
|
||||||
|
|
||||||
|
static gp<Blob> make(gc::IAlloc * mm, std::size_t z);
|
||||||
|
|
||||||
|
std::size_t size() const { return z_; }
|
||||||
|
std::byte * data() { return data_; }
|
||||||
|
|
||||||
|
virtual TaggedPtr self_tp() const final override;
|
||||||
|
virtual void display(std::ostream & os) const final override;
|
||||||
|
|
||||||
|
virtual std::size_t _shallow_size() const final override;
|
||||||
|
virtual Object * _shallow_copy(gc::IAlloc * gc) const final override;
|
||||||
|
virtual std::size_t _forward_children(gc::IAlloc * gc) final override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::size_t z_ = 0;
|
||||||
|
/** flexible array, with @ref z_ bytes **/
|
||||||
|
std::byte data_[];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/* end Blob.hpp */
|
||||||
57
xo-alloc/src/alloc/Blob.cpp
Normal file
57
xo-alloc/src/alloc/Blob.cpp
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
/** @file Blob.cpp
|
||||||
|
*
|
||||||
|
* @author Roland Conybeare, Nov 2025
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include "Blob.hpp"
|
||||||
|
#include "xo/reflect/Reflect.hpp"
|
||||||
|
#include "xo/alloc/IAlloc.hpp"
|
||||||
|
|
||||||
|
namespace xo {
|
||||||
|
using xo::reflect::Reflect;
|
||||||
|
using xo::reflect::TaggedPtr;
|
||||||
|
|
||||||
|
gp<Blob>
|
||||||
|
Blob::make(gc::IAlloc * mm, std::size_t z) {
|
||||||
|
std::byte * mem = mm->alloc(sizeof(Blob) + z);
|
||||||
|
|
||||||
|
return new (mem) Blob(z);
|
||||||
|
}
|
||||||
|
|
||||||
|
TaggedPtr
|
||||||
|
Blob::self_tp() const
|
||||||
|
{
|
||||||
|
return Reflect::make_tp(const_cast<Blob*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Blob::display(std::ostream & os) const
|
||||||
|
{
|
||||||
|
os << "<blob" << xtag("z", z_) << ">";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t
|
||||||
|
Blob::_shallow_size() const {
|
||||||
|
return sizeof(Blob) + z_;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object *
|
||||||
|
Blob::_shallow_copy(gc::IAlloc * mm) const {
|
||||||
|
Cpof cpof(mm, this);
|
||||||
|
std::byte * cp_mem = mm->alloc_gc_copy(sizeof(Blob) + z_, this);
|
||||||
|
|
||||||
|
gp<Blob> copy = new (cp_mem) Blob(z_);
|
||||||
|
|
||||||
|
::memcpy(copy->data(), data_, z_);
|
||||||
|
|
||||||
|
return copy.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t
|
||||||
|
Blob::_forward_children(gc::IAlloc *)
|
||||||
|
{
|
||||||
|
return this->_shallow_size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* end Blob.cpp */
|
||||||
|
|
@ -9,6 +9,7 @@ set(SELF_SRCS
|
||||||
GcStatistics.cpp
|
GcStatistics.cpp
|
||||||
ObjectStatistics.cpp
|
ObjectStatistics.cpp
|
||||||
Object.cpp
|
Object.cpp
|
||||||
|
Blob.cpp
|
||||||
Forwarding1.cpp
|
Forwarding1.cpp
|
||||||
generation.cpp
|
generation.cpp
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
/** @file FunctionInterface.hpp
|
/** @file ProcedureExprInterface.hpp
|
||||||
*
|
*
|
||||||
* Author: Roland Conybeare
|
* Author: Roland Conybeare
|
||||||
**/
|
**/
|
||||||
|
|
@ -10,14 +10,14 @@
|
||||||
|
|
||||||
namespace xo {
|
namespace xo {
|
||||||
namespace scm {
|
namespace scm {
|
||||||
class FunctionExprInterface : public Expression {
|
class ProcedureExprInterface : public Expression {
|
||||||
public:
|
public:
|
||||||
FunctionExprInterface(exprtype extype, TypeDescr fn_type)
|
ProcedureExprInterface(exprtype extype, TypeDescr fn_type)
|
||||||
: Expression(extype, fn_type) {}
|
: Expression(extype, fn_type) {}
|
||||||
|
|
||||||
/** downcast from Expression **/
|
/** downcast from Expression **/
|
||||||
static bp<FunctionExprInterface> from(bp<Expression> x) {
|
static bp<ProcedureExprInterface> from(bp<Expression> x) {
|
||||||
return bp<FunctionExprInterface>::from(x);
|
return bp<ProcedureExprInterface>::from(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual const std::string & name() const = 0;
|
virtual const std::string & name() const = 0;
|
||||||
|
|
@ -30,4 +30,4 @@ namespace xo {
|
||||||
} /*namespace scm*/
|
} /*namespace scm*/
|
||||||
} /*namespace xo*/
|
} /*namespace xo*/
|
||||||
|
|
||||||
/** end FunctionInterface.hpp **/
|
/** end ProcedureExprInterface.hpp **/
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Expression.hpp"
|
#include "Expression.hpp"
|
||||||
#include "FunctionExprInterface.hpp"
|
#include "ProcedureExprInterface.hpp"
|
||||||
#include "Variable.hpp"
|
#include "Variable.hpp"
|
||||||
#include "LocalSymtab.hpp"
|
#include "LocalSymtab.hpp"
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
@ -19,7 +19,7 @@ namespace xo {
|
||||||
* @brief abstract syntax tree for a function definition
|
* @brief abstract syntax tree for a function definition
|
||||||
*
|
*
|
||||||
**/
|
**/
|
||||||
class Lambda : public FunctionExprInterface {
|
class Lambda : public ProcedureExprInterface {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @p name. Name for this lambda -- must be unique
|
* @p name. Name for this lambda -- must be unique
|
||||||
|
|
|
||||||
|
|
@ -5,19 +5,19 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "FunctionExprInterface.hpp"
|
#include "ProcedureExprInterface.hpp"
|
||||||
#include "llvmintrinsic.hpp"
|
#include "llvmintrinsic.hpp"
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
namespace xo {
|
namespace xo {
|
||||||
namespace scm {
|
namespace scm {
|
||||||
class PrimitiveExprInterface : public FunctionExprInterface {
|
class PrimitiveExprInterface : public ProcedureExprInterface {
|
||||||
public:
|
public:
|
||||||
using void_function_type = void (*)();
|
using void_function_type = void (*)();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit PrimitiveExprInterface(TypeDescr fn_type)
|
explicit PrimitiveExprInterface(TypeDescr fn_type)
|
||||||
: FunctionExprInterface(exprtype::primitive, fn_type) {}
|
: ProcedureExprInterface(exprtype::primitive, fn_type) {}
|
||||||
|
|
||||||
/** downcast from Expression **/
|
/** downcast from Expression **/
|
||||||
static bp<PrimitiveExprInterface> from(bp<Expression> x) {
|
static bp<PrimitiveExprInterface> from(bp<Expression> x) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
/** @file FunctionExprInterface.hpp
|
||||||
|
*
|
||||||
|
* Author: Roland Conybeare
|
||||||
|
**/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Expression.hpp"
|
||||||
|
//#include <cstdint>
|
||||||
|
|
||||||
|
namespace xo {
|
||||||
|
namespace scm {
|
||||||
|
class ProcedureExprInterface : public Expression {
|
||||||
|
public:
|
||||||
|
ProcedureExprInterface(exprtype extype, TypeDescr fn_type)
|
||||||
|
: Expression(extype, fn_type) {}
|
||||||
|
|
||||||
|
/** downcast from Expression **/
|
||||||
|
static bp<ProcedureExprInterface> from(bp<Expression> x) {
|
||||||
|
return bp<ProcedureExprInterface>::from(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const std::string & name() const = 0;
|
||||||
|
virtual int n_arg() const = 0; // { return this->value_td()->n_fn_arg(); }
|
||||||
|
virtual TypeDescr fn_retval() const = 0; // { return this->value_td()->fn_retval(); }
|
||||||
|
virtual TypeDescr fn_arg(uint32_t i) const = 0; // { return this->value_td()->fn_arg(i); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
}; /*FunctionInterface*/
|
||||||
|
} /*namespace scm*/
|
||||||
|
} /*namespace xo*/
|
||||||
|
|
||||||
|
/** end FunctionExprInterface.hpp **/
|
||||||
|
|
@ -259,7 +259,7 @@ namespace xo {
|
||||||
TypeDescr lambda_td,
|
TypeDescr lambda_td,
|
||||||
const rp<LocalSymtab> & local_env,
|
const rp<LocalSymtab> & local_env,
|
||||||
const rp<Expression> & body)
|
const rp<Expression> & body)
|
||||||
: FunctionExprInterface(exprtype::lambda, lambda_td),
|
: ProcedureExprInterface(exprtype::lambda, lambda_td),
|
||||||
name_{name},
|
name_{name},
|
||||||
body_{body},
|
body_{body},
|
||||||
local_env_{local_env}
|
local_env_{local_env}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ namespace xo {
|
||||||
**/
|
**/
|
||||||
struct type2llvm {
|
struct type2llvm {
|
||||||
public:
|
public:
|
||||||
using FunctionInterface = xo::scm::FunctionExprInterface;
|
using FunctionInterface = xo::scm::ProcedureExprInterface;
|
||||||
using Lambda = xo::scm::Lambda;
|
using Lambda = xo::scm::Lambda;
|
||||||
using TypeDescr = xo::reflect::TypeDescr;
|
using TypeDescr = xo::reflect::TypeDescr;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
/* @file List.hpp
|
/** @file List.hpp
|
||||||
*
|
*
|
||||||
* author: Roland Conybeare, Aug 2025
|
* @author: Roland Conybeare, Aug 2025
|
||||||
*/
|
**/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
|
@ -70,3 +70,5 @@ namespace xo {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
} /*namespace xo*/
|
} /*namespace xo*/
|
||||||
|
|
||||||
|
/* end List.hpp */
|
||||||
|
|
|
||||||
|
|
@ -18,10 +18,11 @@ namespace xo {
|
||||||
struct Converter {
|
struct Converter {
|
||||||
using TaggedPtr = xo::reflect::TaggedPtr;
|
using TaggedPtr = xo::reflect::TaggedPtr;
|
||||||
using ConvertToObjectFn = gp<Object> (*)(gc::IAlloc *, const TaggedPtr &);
|
using ConvertToObjectFn = gp<Object> (*)(gc::IAlloc *, const TaggedPtr &);
|
||||||
|
using ConvertFromObjectFn = TaggedPtr (*)(gc::IAlloc *, gp<Object> obj);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Converter() = default;
|
Converter() = default;
|
||||||
explicit Converter(ConvertToObjectFn f) : cvt_to_object_{f} {}
|
explicit Converter(ConvertToObjectFn to, ConvertFromObjectFn from) : cvt_to_object_{to}, cvt_from_object_{from} {}
|
||||||
|
|
||||||
/** convert tagged pointer @p tp to new object,
|
/** convert tagged pointer @p tp to new object,
|
||||||
* allocated via @p mm.
|
* allocated via @p mm.
|
||||||
|
|
@ -30,6 +31,14 @@ namespace xo {
|
||||||
* see @ref ObjectConverter
|
* see @ref ObjectConverter
|
||||||
**/
|
**/
|
||||||
ConvertToObjectFn cvt_to_object_ = nullptr;
|
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
|
/** @class ObjectConverter
|
||||||
|
|
@ -53,6 +62,7 @@ namespace xo {
|
||||||
class ObjectConverter {
|
class ObjectConverter {
|
||||||
public:
|
public:
|
||||||
using TaggedPtr = xo::reflect::TaggedPtr;
|
using TaggedPtr = xo::reflect::TaggedPtr;
|
||||||
|
using TypeId = xo::reflect::TypeId;
|
||||||
using IAlloc = xo::gc::IAlloc;
|
using IAlloc = xo::gc::IAlloc;
|
||||||
|
|
||||||
/** sets up standard conversions **/
|
/** sets up standard conversions **/
|
||||||
|
|
@ -60,7 +70,7 @@ namespace xo {
|
||||||
|
|
||||||
/** establish conversion: use @p fn to convert values of type @tparam T. **/
|
/** establish conversion: use @p fn to convert values of type @tparam T. **/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void establish_conversion(Converter::ConvertToObjectFn fn);
|
void establish_conversion(Converter::ConvertToObjectFn to, Converter::ConvertFromObjectFn from);
|
||||||
|
|
||||||
/** convert tagged poitner @p tp to object. allocates memory only from @p mm.
|
/** 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.
|
* return nullptr if no converter available and @p throw_flag not set.
|
||||||
|
|
@ -76,6 +86,13 @@ namespace xo {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
gp<Object> to_object(IAlloc * mm, const T & x, bool throw_flag);
|
gp<Object> to_object(IAlloc * mm, const T & x, bool throw_flag);
|
||||||
|
|
||||||
|
/** convert object @p obj to tagged pointer, with typeid @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_object(IAlloc * mm, gp<Object> & obj, TypeId target_id, bool throw_flag);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** expandable type-driven conversion table.
|
/** expandable type-driven conversion table.
|
||||||
**/
|
**/
|
||||||
|
|
@ -84,7 +101,8 @@ namespace xo {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void
|
void
|
||||||
ObjectConverter::establish_conversion(Converter::ConvertToObjectFn fn)
|
ObjectConverter::establish_conversion(Converter::ConvertToObjectFn to,
|
||||||
|
Converter::ConvertFromObjectFn from)
|
||||||
{
|
{
|
||||||
using xo::reflect::TypeDescrW;
|
using xo::reflect::TypeDescrW;
|
||||||
using xo::reflect::Reflect;
|
using xo::reflect::Reflect;
|
||||||
|
|
@ -92,7 +110,7 @@ namespace xo {
|
||||||
TypeDescrW td = Reflect::require<T>();
|
TypeDescrW td = Reflect::require<T>();
|
||||||
Converter * cvt = cvt_.require(td);
|
Converter * cvt = cvt_.require(td);
|
||||||
|
|
||||||
*cvt = Converter(fn);
|
*cvt = Converter(to, from);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|
|
||||||
70
xo-object/include/xo/object/Primitive.hpp
Normal file
70
xo-object/include/xo/object/Primitive.hpp
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
/** @file Primitive.hpp
|
||||||
|
*
|
||||||
|
* @author Roland Conybeare, Nov 2025
|
||||||
|
**/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Procedure.hpp"
|
||||||
|
#include "CVector.hpp"
|
||||||
|
|
||||||
|
namespace xo {
|
||||||
|
namespace obj {
|
||||||
|
// TODO: consider PrimitiveInterface here
|
||||||
|
|
||||||
|
/** @class Primitive
|
||||||
|
* @brief Procedure implemented natively, i.e. in c++
|
||||||
|
*
|
||||||
|
* @tparam FunctionType can be:
|
||||||
|
* - a C-style function signature such as double(*)(double)
|
||||||
|
* - a std::function, such as std::function<double(double)>
|
||||||
|
**/
|
||||||
|
template <typename Fn>
|
||||||
|
class PrimitiveBase : public Procedure {
|
||||||
|
public:
|
||||||
|
using function_type = Fn;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit PrimitiveBase(Converter & cvt, Fn impl) : converter_{cvt}, impl_{std::move(impl)} {}
|
||||||
|
|
||||||
|
// inherited from Procedure..
|
||||||
|
|
||||||
|
virtual std::size_t n_args() const override = 0;
|
||||||
|
virtual gp<Object> apply_nocheck(const CVector<gp<Object>> & args) override = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Converter & converter_;
|
||||||
|
Fn impl_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Fn>
|
||||||
|
class Primitive : public PrimitiveBase<Fn> {
|
||||||
|
};
|
||||||
|
|
||||||
|
template <Ret, Arg1, Arg2>
|
||||||
|
class Primitive<Ret (*)(Arg1, Arg2)> : public PrimitiveBase<Ret (*)(Arg1, Arg2)> {
|
||||||
|
public:
|
||||||
|
using Super = PrimitiveBase<Ret (*)(Arg1, Arg2)>;
|
||||||
|
using function_type = Ret (*)(Arg1, Arg2);
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit Primitive(Converter & cvt, function_type fn) : PrimitiveBase<Ret (*)(Arg1, Arg2)>{cvt, fn} {}
|
||||||
|
|
||||||
|
// inherited from Procedure..
|
||||||
|
|
||||||
|
virtual std::size_t n_args() const final override { return 2; }
|
||||||
|
virtual gp<Object> apply_nocheck(const CVector<gp<Object>> & args) final override {
|
||||||
|
/* note: args[0] will be this procedure. actual i'th function argument in args[i+1]
|
||||||
|
*/
|
||||||
|
|
||||||
|
args[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* end Primitive.hpp */
|
||||||
31
xo-object/include/xo/object/Procedure.hpp
Normal file
31
xo-object/include/xo/object/Procedure.hpp
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
/** @file Procedure.hpp
|
||||||
|
*
|
||||||
|
* @author Roland Conybeare, Nov 2025
|
||||||
|
**/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Object.hpp"
|
||||||
|
|
||||||
|
namespace xo {
|
||||||
|
namespace obj {
|
||||||
|
/** @class ProcedureInterface
|
||||||
|
* @brief Interface to a dynamically-typed procedure
|
||||||
|
**/
|
||||||
|
class Procedure : public Object {
|
||||||
|
public:
|
||||||
|
virtual std::size_t n_args() const = 0;
|
||||||
|
virtual gp<Object> apply_nocheck(const CVector<gp<Object>> & args) = 0;
|
||||||
|
|
||||||
|
// inherited from Object..
|
||||||
|
|
||||||
|
// virtual TaggedPtr self_tp() const override;
|
||||||
|
// virtual void display(std::ostream &) const override;
|
||||||
|
// virtual size_t _shallow_size() const override;
|
||||||
|
// virtual Object * _shallow_copy(gc::IAlloc *) const override;
|
||||||
|
// virtual size_t _forward_children(gc::IAlloc *) override;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* end Procedure.hpp */
|
||||||
|
|
@ -7,9 +7,13 @@
|
||||||
#include "Integer.hpp"
|
#include "Integer.hpp"
|
||||||
#include "Float.hpp"
|
#include "Float.hpp"
|
||||||
#include "Boolean.hpp"
|
#include "Boolean.hpp"
|
||||||
|
#include "TaggedPtr.hpp"
|
||||||
|
#include "xo/alloc/Blob.hpp"
|
||||||
|
|
||||||
namespace xo {
|
namespace xo {
|
||||||
|
using xo::reflect::Reflect;
|
||||||
using xo::reflect::TaggedPtr;
|
using xo::reflect::TaggedPtr;
|
||||||
|
using xo::reflect::TypeId;
|
||||||
using xo::gc::IAlloc;
|
using xo::gc::IAlloc;
|
||||||
|
|
||||||
namespace obj {
|
namespace obj {
|
||||||
|
|
@ -25,6 +29,34 @@ namespace xo {
|
||||||
return Integer::make(mm, *native);
|
return Integer::make(mm, *native);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
TaggedPtr
|
||||||
|
object_to_int(IAlloc * mm, gp<Object> obj)
|
||||||
|
{
|
||||||
|
/* mm cannot be GC allocator!
|
||||||
|
* That's Object-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
gp<Integer> int_obj = Integer::from(obj);
|
||||||
|
|
||||||
|
if (!int_obj.get()) {
|
||||||
|
throw std::runtime_error(tostr("Object obj found where Integer expected",
|
||||||
|
xtag("obj", obj)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate a Blob wrapper to satsify GC memory layout demands */
|
||||||
|
|
||||||
|
gp<Blob> tmp = Blob::make(mm, sizeof(T));
|
||||||
|
|
||||||
|
T * p = reinterpret_cast<T *>(tmp->data());
|
||||||
|
|
||||||
|
*p = int_obj->value();
|
||||||
|
|
||||||
|
/* WARNING: retval invalidated when *mm cleared/recycled/collected */
|
||||||
|
|
||||||
|
return Reflect::make_tp(p);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
gp<Object>
|
gp<Object>
|
||||||
float_to_object(IAlloc * mm, const TaggedPtr & src)
|
float_to_object(IAlloc * mm, const TaggedPtr & src)
|
||||||
|
|
@ -36,6 +68,34 @@ namespace xo {
|
||||||
return Float::make(mm, *native);
|
return Float::make(mm, *native);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
TaggedPtr
|
||||||
|
object_to_float(IAlloc * mm, gp<Object> obj)
|
||||||
|
{
|
||||||
|
/* mm cannot be GC allocator!
|
||||||
|
* That's Object-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
gp<Float> float_obj = Float::from(obj);
|
||||||
|
|
||||||
|
if (!float_obj.get()) {
|
||||||
|
throw std::runtime_error(tostr("Object obj found where Float expected",
|
||||||
|
xtag("obj", obj)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate a Blob wrapper to satsify GC memory layout demands */
|
||||||
|
|
||||||
|
gp<Blob> tmp = Blob::make(mm, sizeof(T));
|
||||||
|
|
||||||
|
T * p = reinterpret_cast<T *>(tmp->data());
|
||||||
|
|
||||||
|
*p = float_obj->value();
|
||||||
|
|
||||||
|
/* WARNING: retval invalidated when *mm cleared/recycled/collected */
|
||||||
|
|
||||||
|
return Reflect::make_tp(p);
|
||||||
|
}
|
||||||
|
|
||||||
gp<Object>
|
gp<Object>
|
||||||
bool_to_object(IAlloc * /*mm*/, const TaggedPtr & src)
|
bool_to_object(IAlloc * /*mm*/, const TaggedPtr & src)
|
||||||
{
|
{
|
||||||
|
|
@ -45,16 +105,32 @@ namespace xo {
|
||||||
|
|
||||||
return Boolean::boolean_obj(*native);
|
return Boolean::boolean_obj(*native);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TaggedPtr
|
||||||
|
object_to_bool(IAlloc * /*mm*/, gp<Object> obj)
|
||||||
|
{
|
||||||
|
static bool s_true = true;
|
||||||
|
static bool s_false = false;
|
||||||
|
|
||||||
|
gp<Boolean> bool_obj = Boolean::from(obj);
|
||||||
|
|
||||||
|
if (!bool_obj.get()) {
|
||||||
|
throw std::runtime_error(tostr("Object obj found where Boolean expected",
|
||||||
|
xtag("obj", obj)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Reflect::make_tp(bool_obj->value() ? &s_true : &s_false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjectConverter::ObjectConverter()
|
ObjectConverter::ObjectConverter()
|
||||||
{
|
{
|
||||||
this->establish_conversion<std::int32_t>(&int_to_object<std::int32_t>);
|
this->establish_conversion<std::int32_t>(&int_to_object<std::int32_t>, &object_to_int<std::int32_t>);
|
||||||
this->establish_conversion<std::int64_t>(&int_to_object<std::int64_t>);
|
this->establish_conversion<std::int64_t>(&int_to_object<std::int64_t>, &object_to_int<std::int64_t>);
|
||||||
|
|
||||||
this->establish_conversion<double>(&float_to_object<double>);
|
this->establish_conversion<double>(&float_to_object<double>, &object_to_float<double>);
|
||||||
|
|
||||||
this->establish_conversion<bool>(&bool_to_object);
|
this->establish_conversion<bool>(&bool_to_object, &object_to_bool);
|
||||||
}
|
}
|
||||||
|
|
||||||
gp<Object>
|
gp<Object>
|
||||||
|
|
@ -69,7 +145,7 @@ namespace xo {
|
||||||
return (cvt->cvt_to_object_)(mm, x_tp);
|
return (cvt->cvt_to_object_)(mm, x_tp);
|
||||||
} else {
|
} else {
|
||||||
if (throw_flag) {
|
if (throw_flag) {
|
||||||
throw std::runtime_error(tostr("no object-converter available for instance of type",
|
throw std::runtime_error(tostr("no to-object-converter available for instance of type",
|
||||||
xtag("id", x_tp.td()->id()),
|
xtag("id", x_tp.td()->id()),
|
||||||
xtag("name", x_tp.td()->short_name())));
|
xtag("name", x_tp.td()->short_name())));
|
||||||
}
|
}
|
||||||
|
|
@ -77,6 +153,23 @@ namespace xo {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TaggedPtr
|
||||||
|
ObjectConverter::tp_from_object(IAlloc * mm, gp<Object> & obj, TypeId target_id, bool throw_flag)
|
||||||
|
{
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -144,7 +144,7 @@ namespace xo {
|
||||||
if (owner_ == owner::unique) {
|
if (owner_ == owner::unique) {
|
||||||
std::byte * mem = reinterpret_cast<std::byte *>(chars_);
|
std::byte * mem = reinterpret_cast<std::byte *>(chars_);
|
||||||
|
|
||||||
copy->chars_ = reinterpret_cast<char *>(Object::mm->alloc_gc_copy(z_chars_, mem));
|
copy->chars_ = reinterpret_cast<char *>(mm->alloc_gc_copy(z_chars_, mem));
|
||||||
strlcpy(copy->chars_, chars_, z_chars_);
|
strlcpy(copy->chars_, chars_, z_chars_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue