xo-interpreter: add Primitive object, to expose builtin functions
This commit is contained in:
parent
4488117ac3
commit
2526dcc9b1
23 changed files with 277 additions and 135 deletions
|
|
@ -1,7 +1,7 @@
|
|||
/** @file ex1.cpp **/
|
||||
|
||||
#include "xo/expression/Constant.hpp"
|
||||
#include "xo/expression/Primitive.hpp"
|
||||
#include "xo/expression/PrimitiveExpr.hpp"
|
||||
#include "xo/expression/llvmintrinsic.hpp"
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/** @file Primitive.hpp
|
||||
/** @file PrimitiveExpr.hpp
|
||||
*
|
||||
* Author: Roland Conybeare
|
||||
**/
|
||||
|
|
@ -20,7 +20,7 @@ extern "C" {
|
|||
|
||||
namespace xo {
|
||||
namespace scm {
|
||||
/** @class Primitive
|
||||
/** @class PrimitiveExpr
|
||||
* @brief syntax for a constant that refers to a known function.
|
||||
*
|
||||
* Two cases here:
|
||||
|
|
@ -38,7 +38,7 @@ namespace xo {
|
|||
* won't work here.
|
||||
**/
|
||||
template <typename FunctionPointer>
|
||||
class Primitive: public PrimitiveExprInterface {
|
||||
class PrimitiveExpr: public PrimitiveExprInterface {
|
||||
public:
|
||||
using Reflect = xo::reflect::Reflect;
|
||||
using TaggedPtr = xo::reflect::TaggedPtr;
|
||||
|
|
@ -46,13 +46,13 @@ namespace xo {
|
|||
using fptr_type = FunctionPointer;
|
||||
|
||||
public:
|
||||
static rp<Primitive> make(const std::string & name,
|
||||
static rp<PrimitiveExpr> make(const std::string & name,
|
||||
FunctionPointer fnptr,
|
||||
bool explicit_symbol_def,
|
||||
llvmintrinsic intrinsic) {
|
||||
TypeDescr fn_type = Reflect::require<FunctionPointer>();
|
||||
|
||||
return new Primitive(fn_type, name, fnptr, explicit_symbol_def, intrinsic);
|
||||
return new PrimitiveExpr(fn_type, name, fnptr, explicit_symbol_def, intrinsic);
|
||||
}
|
||||
|
||||
/** see classes below for intrinsics **/
|
||||
|
|
@ -68,7 +68,7 @@ namespace xo {
|
|||
return TaggedPtr(value_td_, erased_ptr);
|
||||
}
|
||||
|
||||
// ----- PrimitiveInterface -----
|
||||
// ----- PrimitiveExprInterface -----
|
||||
|
||||
virtual llvmintrinsic intrinsic() const override { return intrinsic_; }
|
||||
virtual bool explicit_symbol_def() const override { return explicit_symbol_def_; }
|
||||
|
|
@ -84,7 +84,7 @@ namespace xo {
|
|||
// ----- Expression -----
|
||||
|
||||
virtual void display(std::ostream & os) const override {
|
||||
os << "<Primitive"
|
||||
os << "<PrimitiveExpr"
|
||||
<< xtag("name", name_)
|
||||
<< xtag("type", this->value_td()->short_name())
|
||||
<< xtag("value", this->value())
|
||||
|
|
@ -99,14 +99,14 @@ namespace xo {
|
|||
* we don't have pretty printer for native function pointers anyway
|
||||
* + simplifies ppdetail_atomic
|
||||
*/
|
||||
return ppii.pps()->pretty_struct(ppii, "Primitive",
|
||||
return ppii.pps()->pretty_struct(ppii, "PrimitiveExpr",
|
||||
refrtag("name", name_),
|
||||
rtag("type", print::quot(this->valuetype()->short_name())),
|
||||
refrtag("value", (void*)(this->value())));
|
||||
}
|
||||
|
||||
private:
|
||||
Primitive(TypeDescr fn_type,
|
||||
PrimitiveExpr(TypeDescr fn_type,
|
||||
const std::string & name,
|
||||
FunctionPointer fnptr,
|
||||
bool explicit_symbol_def,
|
||||
|
|
@ -119,9 +119,9 @@ namespace xo {
|
|||
intrinsic_{intrinsic}
|
||||
{
|
||||
if (!value_td_->is_function())
|
||||
throw std::runtime_error("Primitive: expected function pointer");
|
||||
throw std::runtime_error("PrimitiveExpr: expected function pointer");
|
||||
if (!value_td_->fn_retval())
|
||||
throw std::runtime_error("Primitive: expected non-null function return value");
|
||||
throw std::runtime_error("PrimitiveExpr: expected non-null function return value");
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -145,75 +145,75 @@ namespace xo {
|
|||
* all others: generate direct use of LLVM intrinsic
|
||||
**/
|
||||
llvmintrinsic intrinsic_;
|
||||
}; /*Primitive*/
|
||||
}; /*PrimitiveExpr*/
|
||||
|
||||
/** adopt function @p x as a callable primitive function named @p name **/
|
||||
template <typename FunctionPointer>
|
||||
rp<Primitive<FunctionPointer>>
|
||||
rp<PrimitiveExpr<FunctionPointer>>
|
||||
make_primitive(const std::string & name,
|
||||
FunctionPointer x,
|
||||
bool explicit_symbol_def,
|
||||
llvmintrinsic intrinsic)
|
||||
{
|
||||
return Primitive<FunctionPointer>::make(name, x, explicit_symbol_def, intrinsic);
|
||||
return PrimitiveExpr<FunctionPointer>::make(name, x, explicit_symbol_def, intrinsic);
|
||||
}
|
||||
|
||||
// NOTE: see xo-reader/src/reader/progress_xs.cpp
|
||||
// binding operators to primitive applications.
|
||||
|
||||
/** builtin primitives :: i64 x i64 -> bool **/
|
||||
class Primitive_cmp_i64 : public Primitive<bool (*)(std::int64_t, std::int64_t)> {
|
||||
class PrimitiveExpr_cmp_i64 : public PrimitiveExpr<bool (*)(std::int64_t, std::int64_t)> {
|
||||
public:
|
||||
using PrimitiveType = Primitive<bool (*)(std::int64_t, std::int64_t)>;
|
||||
using PrimitiveExprType = PrimitiveExpr<bool (*)(std::int64_t, std::int64_t)>;
|
||||
|
||||
public:
|
||||
/** eq2_i64: compare two 64-bit integers for equality **/
|
||||
static rp<PrimitiveType> make_cmp_eq2_i64();
|
||||
static rp<PrimitiveExprType> make_cmp_eq2_i64();
|
||||
/** ne2_i64: compare two 64-bit integers for inequality **/
|
||||
static rp<PrimitiveType> make_cmp_ne2_i64();
|
||||
static rp<PrimitiveExprType> make_cmp_ne2_i64();
|
||||
/** lt2_i64: compare two 64-bit integers for lessthan **/
|
||||
static rp<PrimitiveType> make_cmp_lt2_i64();
|
||||
static rp<PrimitiveExprType> make_cmp_lt2_i64();
|
||||
/** lt2_i64: compare two 64-bit integers for lessthanorequal **/
|
||||
static rp<PrimitiveType> make_cmp_le2_i64();
|
||||
static rp<PrimitiveExprType> make_cmp_le2_i64();
|
||||
/** gt2_i64: compare two 64-bit integers for greaterthan **/
|
||||
static rp<PrimitiveType> make_cmp_gt2_i64();
|
||||
static rp<PrimitiveExprType> make_cmp_gt2_i64();
|
||||
/** ge2_i64: compare two 64-bit integers for greaterthan **/
|
||||
static rp<PrimitiveType> make_cmp_ge2_i64();
|
||||
static rp<PrimitiveExprType> make_cmp_ge2_i64();
|
||||
};
|
||||
|
||||
/** builtin primitives :: i64 x i64 -> i64 **/
|
||||
class Primitive_i64 : public Primitive<std::int64_t (*)(std::int64_t, std::int64_t)> {
|
||||
class PrimitiveExpr_i64 : public PrimitiveExpr<std::int64_t (*)(std::int64_t, std::int64_t)> {
|
||||
public:
|
||||
using PrimitiveType = Primitive<std::int64_t (*)(std::int64_t, std::int64_t)>;
|
||||
using PrimitiveExprType = PrimitiveExpr<std::int64_t (*)(std::int64_t, std::int64_t)>;
|
||||
|
||||
public:
|
||||
/** add2_i64: add two 64-bit integers **/
|
||||
static rp<PrimitiveType> make_add2_i64();
|
||||
static rp<PrimitiveExprType> make_add2_i64();
|
||||
/** sub2_i64: subtract two 64-bit integers **/
|
||||
static rp<PrimitiveType> make_sub2_i64();
|
||||
static rp<PrimitiveExprType> make_sub2_i64();
|
||||
/** mul2_i64: multiply two 64-bit integers **/
|
||||
static rp<PrimitiveType> make_mul2_i64();
|
||||
static rp<PrimitiveExprType> make_mul2_i64();
|
||||
/** div2_i64: divide two 64-bit integers **/
|
||||
static rp<PrimitiveType> make_div2_i64();
|
||||
static rp<PrimitiveExprType> make_div2_i64();
|
||||
};
|
||||
|
||||
/** builtin primitives :: f64 x f64 -> f64 **/
|
||||
class Primitive_f64 : public Primitive<double (*)(double, double)> {
|
||||
class PrimitiveExpr_f64 : public PrimitiveExpr<double (*)(double, double)> {
|
||||
public:
|
||||
using PrimitiveType = Primitive<double (*)(double, double)>;
|
||||
using PrimitiveExprType = PrimitiveExpr<double (*)(double, double)>;
|
||||
|
||||
public:
|
||||
/** add2_f64: add two 64-bit floating-point numbers **/
|
||||
static rp<PrimitiveType> make_add2_f64();
|
||||
static rp<PrimitiveExprType> make_add2_f64();
|
||||
/** sub2_f64: subtract two 64-bit floating-point numbers **/
|
||||
static rp<PrimitiveType> make_sub2_f64();
|
||||
static rp<PrimitiveExprType> make_sub2_f64();
|
||||
/** mul2_f64: multiply two 64-bit floating-point numbers **/
|
||||
static rp<PrimitiveType> make_mul2_f64();
|
||||
static rp<PrimitiveExprType> make_mul2_f64();
|
||||
/** div2_f64: divide two 64-bit floating-point numbers **/
|
||||
static rp<PrimitiveType> make_div2_f64();
|
||||
static rp<PrimitiveExprType> make_div2_f64();
|
||||
};
|
||||
} /*namespace scm*/
|
||||
} /*namespace xo*/
|
||||
|
||||
|
||||
/** end Primitive.hpp **/
|
||||
/** end PrimitiveExpr.hpp **/
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
/* @file Apply.cpp */
|
||||
|
||||
#include "Apply.hpp"
|
||||
#include "Primitive.hpp"
|
||||
#include "PrimitiveExpr.hpp"
|
||||
#include "exprtype.hpp"
|
||||
#include "pretty_expression.hpp"
|
||||
#include "xo/indentlog/print/vector.hpp"
|
||||
|
|
@ -36,7 +36,7 @@ namespace xo {
|
|||
Apply::make_cmp_eq_i64(const rp<Expression> & lhs,
|
||||
const rp<Expression> & rhs)
|
||||
{
|
||||
return Apply::make(Primitive_cmp_i64::make_cmp_eq2_i64(),
|
||||
return Apply::make(PrimitiveExpr_cmp_i64::make_cmp_eq2_i64(),
|
||||
{lhs, rhs});
|
||||
}
|
||||
|
||||
|
|
@ -44,7 +44,7 @@ namespace xo {
|
|||
Apply::make_cmp_ne_i64(const rp<Expression> & lhs,
|
||||
const rp<Expression> & rhs)
|
||||
{
|
||||
return Apply::make(Primitive_cmp_i64::make_cmp_ne2_i64(),
|
||||
return Apply::make(PrimitiveExpr_cmp_i64::make_cmp_ne2_i64(),
|
||||
{lhs, rhs});
|
||||
}
|
||||
|
||||
|
|
@ -52,7 +52,7 @@ namespace xo {
|
|||
Apply::make_cmp_lt_i64(const rp<Expression> & lhs,
|
||||
const rp<Expression> & rhs)
|
||||
{
|
||||
return Apply::make(Primitive_cmp_i64::make_cmp_lt2_i64(),
|
||||
return Apply::make(PrimitiveExpr_cmp_i64::make_cmp_lt2_i64(),
|
||||
{lhs, rhs});
|
||||
}
|
||||
|
||||
|
|
@ -60,7 +60,7 @@ namespace xo {
|
|||
Apply::make_cmp_le_i64(const rp<Expression> & lhs,
|
||||
const rp<Expression> & rhs)
|
||||
{
|
||||
return Apply::make(Primitive_cmp_i64::make_cmp_le2_i64(),
|
||||
return Apply::make(PrimitiveExpr_cmp_i64::make_cmp_le2_i64(),
|
||||
{lhs, rhs});
|
||||
}
|
||||
|
||||
|
|
@ -68,7 +68,7 @@ namespace xo {
|
|||
Apply::make_cmp_gt_i64(const rp<Expression> & lhs,
|
||||
const rp<Expression> & rhs)
|
||||
{
|
||||
return Apply::make(Primitive_cmp_i64::make_cmp_gt2_i64(),
|
||||
return Apply::make(PrimitiveExpr_cmp_i64::make_cmp_gt2_i64(),
|
||||
{lhs, rhs});
|
||||
}
|
||||
|
||||
|
|
@ -76,7 +76,7 @@ namespace xo {
|
|||
Apply::make_cmp_ge_i64(const rp<Expression> & lhs,
|
||||
const rp<Expression> & rhs)
|
||||
{
|
||||
return Apply::make(Primitive_cmp_i64::make_cmp_ge2_i64(),
|
||||
return Apply::make(PrimitiveExpr_cmp_i64::make_cmp_ge2_i64(),
|
||||
{lhs, rhs});
|
||||
}
|
||||
|
||||
|
|
@ -86,7 +86,7 @@ namespace xo {
|
|||
Apply::make_add2_i64(const rp<Expression> & lhs,
|
||||
const rp<Expression> & rhs)
|
||||
{
|
||||
return Apply::make(Primitive_i64::make_add2_i64(),
|
||||
return Apply::make(PrimitiveExpr_i64::make_add2_i64(),
|
||||
{lhs, rhs});
|
||||
}
|
||||
|
||||
|
|
@ -94,7 +94,7 @@ namespace xo {
|
|||
Apply::make_sub2_i64(const rp<Expression> & lhs,
|
||||
const rp<Expression> & rhs)
|
||||
{
|
||||
return Apply::make(Primitive_i64::make_sub2_i64(),
|
||||
return Apply::make(PrimitiveExpr_i64::make_sub2_i64(),
|
||||
{lhs, rhs});
|
||||
}
|
||||
|
||||
|
|
@ -102,7 +102,7 @@ namespace xo {
|
|||
Apply::make_mul2_i64(const rp<Expression> & lhs,
|
||||
const rp<Expression> & rhs)
|
||||
{
|
||||
return Apply::make(Primitive_i64::make_mul2_i64(),
|
||||
return Apply::make(PrimitiveExpr_i64::make_mul2_i64(),
|
||||
{lhs, rhs});
|
||||
}
|
||||
|
||||
|
|
@ -110,7 +110,7 @@ namespace xo {
|
|||
Apply::make_div2_i64(const rp<Expression> & lhs,
|
||||
const rp<Expression> & rhs)
|
||||
{
|
||||
return Apply::make(Primitive_i64::make_div2_i64(),
|
||||
return Apply::make(PrimitiveExpr_i64::make_div2_i64(),
|
||||
{lhs, rhs});
|
||||
}
|
||||
|
||||
|
|
@ -120,7 +120,7 @@ namespace xo {
|
|||
Apply::make_add2_f64(const rp<Expression> & lhs,
|
||||
const rp<Expression> & rhs)
|
||||
{
|
||||
return Apply::make(Primitive_f64::make_add2_f64(),
|
||||
return Apply::make(PrimitiveExpr_f64::make_add2_f64(),
|
||||
{lhs, rhs});
|
||||
}
|
||||
|
||||
|
|
@ -128,7 +128,7 @@ namespace xo {
|
|||
Apply::make_sub2_f64(const rp<Expression> & lhs,
|
||||
const rp<Expression> & rhs)
|
||||
{
|
||||
return Apply::make(Primitive_f64::make_sub2_f64(),
|
||||
return Apply::make(PrimitiveExpr_f64::make_sub2_f64(),
|
||||
{lhs, rhs});
|
||||
}
|
||||
|
||||
|
|
@ -136,7 +136,7 @@ namespace xo {
|
|||
Apply::make_mul2_f64(const rp<Expression> & lhs,
|
||||
const rp<Expression> & rhs)
|
||||
{
|
||||
return Apply::make(Primitive_f64::make_mul2_f64(),
|
||||
return Apply::make(PrimitiveExpr_f64::make_mul2_f64(),
|
||||
{lhs, rhs});
|
||||
}
|
||||
|
||||
|
|
@ -144,7 +144,7 @@ namespace xo {
|
|||
Apply::make_div2_f64(const rp<Expression> & lhs,
|
||||
const rp<Expression> & rhs)
|
||||
{
|
||||
return Apply::make(Primitive_f64::make_div2_f64(),
|
||||
return Apply::make(PrimitiveExpr_f64::make_div2_f64(),
|
||||
{lhs, rhs});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ set(SELF_SRCS
|
|||
GlobalSymtab.cpp
|
||||
LocalSymtab.cpp
|
||||
ConvertExpr.cpp
|
||||
Primitive.cpp
|
||||
PrimitiveExpr.cpp
|
||||
typeinf/type_ref.cpp
|
||||
typeinf/type_unifier.cpp
|
||||
typeinf/TypeBlueprint.cpp
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* @file Primitive.cpp */
|
||||
/* @file PrimitiveExpr.cpp */
|
||||
|
||||
#include "Primitive.hpp"
|
||||
#include "PrimitiveExpr.hpp"
|
||||
#include <cstdint>
|
||||
|
||||
extern "C" {
|
||||
|
|
@ -86,12 +86,12 @@ extern "C" {
|
|||
namespace xo {
|
||||
namespace scm {
|
||||
auto
|
||||
Primitive_cmp_i64::make_cmp_eq2_i64() -> rp<PrimitiveType>
|
||||
PrimitiveExpr_cmp_i64::make_cmp_eq2_i64() -> rp<PrimitiveExprType>
|
||||
{
|
||||
static rp<PrimitiveType> s_retval;
|
||||
static rp<PrimitiveExprType> s_retval;
|
||||
|
||||
if (!s_retval)
|
||||
s_retval = Primitive::make("cmp_eq2_i64",
|
||||
s_retval = PrimitiveExpr::make("cmp_eq2_i64",
|
||||
&cmp_eq2_i64,
|
||||
true /*explicit_symbol_def*/,
|
||||
llvmintrinsic::i_eq);
|
||||
|
|
@ -100,12 +100,12 @@ namespace xo {
|
|||
}
|
||||
|
||||
auto
|
||||
Primitive_cmp_i64::make_cmp_ne2_i64() -> rp<PrimitiveType>
|
||||
PrimitiveExpr_cmp_i64::make_cmp_ne2_i64() -> rp<PrimitiveExprType>
|
||||
{
|
||||
static rp<PrimitiveType> s_retval;
|
||||
static rp<PrimitiveExprType> s_retval;
|
||||
|
||||
if (!s_retval)
|
||||
s_retval = Primitive::make("cmp_ne2_i64",
|
||||
s_retval = PrimitiveExpr::make("cmp_ne2_i64",
|
||||
&cmp_ne2_i64,
|
||||
true /*explicit_symbol_def*/,
|
||||
llvmintrinsic::i_ne);
|
||||
|
|
@ -114,12 +114,12 @@ namespace xo {
|
|||
}
|
||||
|
||||
auto
|
||||
Primitive_cmp_i64::make_cmp_lt2_i64() -> rp<PrimitiveType>
|
||||
PrimitiveExpr_cmp_i64::make_cmp_lt2_i64() -> rp<PrimitiveExprType>
|
||||
{
|
||||
static rp<PrimitiveType> s_retval;
|
||||
static rp<PrimitiveExprType> s_retval;
|
||||
|
||||
if (!s_retval)
|
||||
s_retval = Primitive::make("cmp_lt2_i64",
|
||||
s_retval = PrimitiveExpr::make("cmp_lt2_i64",
|
||||
&cmp_lt2_i64,
|
||||
true /*explicit_symbol_def*/,
|
||||
llvmintrinsic::i_slt);
|
||||
|
|
@ -128,12 +128,12 @@ namespace xo {
|
|||
}
|
||||
|
||||
auto
|
||||
Primitive_cmp_i64::make_cmp_le2_i64() -> rp<PrimitiveType>
|
||||
PrimitiveExpr_cmp_i64::make_cmp_le2_i64() -> rp<PrimitiveExprType>
|
||||
{
|
||||
static rp<PrimitiveType> s_retval;
|
||||
static rp<PrimitiveExprType> s_retval;
|
||||
|
||||
if (!s_retval)
|
||||
s_retval = Primitive::make("cmp_le2_i64",
|
||||
s_retval = PrimitiveExpr::make("cmp_le2_i64",
|
||||
&cmp_le2_i64,
|
||||
true /*explicit_symbol_def*/,
|
||||
llvmintrinsic::i_sle);
|
||||
|
|
@ -142,12 +142,12 @@ namespace xo {
|
|||
}
|
||||
|
||||
auto
|
||||
Primitive_cmp_i64::make_cmp_gt2_i64() -> rp<PrimitiveType>
|
||||
PrimitiveExpr_cmp_i64::make_cmp_gt2_i64() -> rp<PrimitiveExprType>
|
||||
{
|
||||
static rp<PrimitiveType> s_retval;
|
||||
static rp<PrimitiveExprType> s_retval;
|
||||
|
||||
if (!s_retval)
|
||||
s_retval = Primitive::make("cmp_gt2_i64",
|
||||
s_retval = PrimitiveExpr::make("cmp_gt2_i64",
|
||||
&cmp_gt2_i64,
|
||||
true /*explicit_symbol_def*/,
|
||||
llvmintrinsic::i_sgt);
|
||||
|
|
@ -156,12 +156,12 @@ namespace xo {
|
|||
}
|
||||
|
||||
auto
|
||||
Primitive_cmp_i64::make_cmp_ge2_i64() -> rp<PrimitiveType>
|
||||
PrimitiveExpr_cmp_i64::make_cmp_ge2_i64() -> rp<PrimitiveExprType>
|
||||
{
|
||||
static rp<PrimitiveType> s_retval;
|
||||
static rp<PrimitiveExprType> s_retval;
|
||||
|
||||
if (!s_retval)
|
||||
s_retval = Primitive::make("cmp_ge2_i64",
|
||||
s_retval = PrimitiveExpr::make("cmp_ge2_i64",
|
||||
&cmp_ge2_i64,
|
||||
true /*explicit_symbol_def*/,
|
||||
llvmintrinsic::i_sge);
|
||||
|
|
@ -172,12 +172,12 @@ namespace xo {
|
|||
/* TODO: remaining integer arithmetic */
|
||||
|
||||
auto
|
||||
Primitive_i64::make_add2_i64() -> rp<PrimitiveType>
|
||||
PrimitiveExpr_i64::make_add2_i64() -> rp<PrimitiveExprType>
|
||||
{
|
||||
static rp<PrimitiveType> s_retval;
|
||||
static rp<PrimitiveExprType> s_retval;
|
||||
|
||||
if (!s_retval)
|
||||
s_retval = Primitive::make("add2_i64",
|
||||
s_retval = PrimitiveExpr::make("add2_i64",
|
||||
&add2_i64,
|
||||
true /*explicit_symbol_def*/,
|
||||
llvmintrinsic::i_add);
|
||||
|
|
@ -186,12 +186,12 @@ namespace xo {
|
|||
}
|
||||
|
||||
auto
|
||||
Primitive_i64::make_sub2_i64() -> rp<PrimitiveType>
|
||||
PrimitiveExpr_i64::make_sub2_i64() -> rp<PrimitiveExprType>
|
||||
{
|
||||
static rp<PrimitiveType> s_retval;
|
||||
static rp<PrimitiveExprType> s_retval;
|
||||
|
||||
if (!s_retval)
|
||||
s_retval = Primitive::make("sub2_i64",
|
||||
s_retval = PrimitiveExpr::make("sub2_i64",
|
||||
&sub2_i64,
|
||||
true /*explicit_symbol_def*/,
|
||||
llvmintrinsic::i_sub);
|
||||
|
|
@ -200,12 +200,12 @@ namespace xo {
|
|||
}
|
||||
|
||||
auto
|
||||
Primitive_i64::make_mul2_i64() -> rp<PrimitiveType>
|
||||
PrimitiveExpr_i64::make_mul2_i64() -> rp<PrimitiveExprType>
|
||||
{
|
||||
static rp<PrimitiveType> s_retval;
|
||||
static rp<PrimitiveExprType> s_retval;
|
||||
|
||||
if (!s_retval)
|
||||
s_retval = Primitive::make("mul2_i64",
|
||||
s_retval = PrimitiveExpr::make("mul2_i64",
|
||||
&mul2_i64,
|
||||
true /*explicit_symbol_def*/,
|
||||
llvmintrinsic::i_mul);
|
||||
|
|
@ -214,12 +214,12 @@ namespace xo {
|
|||
}
|
||||
|
||||
auto
|
||||
Primitive_i64::make_div2_i64() -> rp<PrimitiveType>
|
||||
PrimitiveExpr_i64::make_div2_i64() -> rp<PrimitiveExprType>
|
||||
{
|
||||
static rp<PrimitiveType> s_retval;
|
||||
static rp<PrimitiveExprType> s_retval;
|
||||
|
||||
if (!s_retval)
|
||||
s_retval = Primitive::make("div2_i64",
|
||||
s_retval = PrimitiveExpr::make("div2_i64",
|
||||
&div2_i64,
|
||||
true /*explicit_symbol+def*/,
|
||||
llvmintrinsic::i_sdiv);
|
||||
|
|
@ -229,12 +229,12 @@ namespace xo {
|
|||
// ----- floating-point arithmetic -----
|
||||
|
||||
auto
|
||||
Primitive_f64::make_add2_f64() -> rp<PrimitiveType>
|
||||
PrimitiveExpr_f64::make_add2_f64() -> rp<PrimitiveExprType>
|
||||
{
|
||||
static rp<PrimitiveType> s_retval;
|
||||
static rp<PrimitiveExprType> s_retval;
|
||||
|
||||
if (!s_retval)
|
||||
s_retval = Primitive::make("add2_f64",
|
||||
s_retval = PrimitiveExpr::make("add2_f64",
|
||||
&add2_f64,
|
||||
true /*explicit_symbol_def*/,
|
||||
llvmintrinsic::fp_add);
|
||||
|
|
@ -243,12 +243,12 @@ namespace xo {
|
|||
}
|
||||
|
||||
auto
|
||||
Primitive_f64::make_sub2_f64() -> rp<PrimitiveType>
|
||||
PrimitiveExpr_f64::make_sub2_f64() -> rp<PrimitiveExprType>
|
||||
{
|
||||
static rp<PrimitiveType> s_retval;
|
||||
static rp<PrimitiveExprType> s_retval;
|
||||
|
||||
if (!s_retval)
|
||||
s_retval = Primitive::make("sub2_f64",
|
||||
s_retval = PrimitiveExpr::make("sub2_f64",
|
||||
&sub2_f64,
|
||||
true /*explicit_symbol_def*/,
|
||||
llvmintrinsic::fp_sub);
|
||||
|
|
@ -257,12 +257,12 @@ namespace xo {
|
|||
}
|
||||
|
||||
auto
|
||||
Primitive_f64::make_mul2_f64() -> rp<PrimitiveType>
|
||||
PrimitiveExpr_f64::make_mul2_f64() -> rp<PrimitiveExprType>
|
||||
{
|
||||
static rp<PrimitiveType> s_retval;
|
||||
static rp<PrimitiveExprType> s_retval;
|
||||
|
||||
if (!s_retval)
|
||||
s_retval = Primitive::make("mul2_f64",
|
||||
s_retval = PrimitiveExpr::make("mul2_f64",
|
||||
&mul2_f64,
|
||||
true /*explicit_symbol_def*/,
|
||||
llvmintrinsic::fp_mul);
|
||||
|
|
@ -271,12 +271,12 @@ namespace xo {
|
|||
}
|
||||
|
||||
auto
|
||||
Primitive_f64::make_div2_f64() -> rp<PrimitiveType>
|
||||
PrimitiveExpr_f64::make_div2_f64() -> rp<PrimitiveExprType>
|
||||
{
|
||||
static rp<PrimitiveType> s_retval;
|
||||
static rp<PrimitiveExprType> s_retval;
|
||||
|
||||
if (!s_retval)
|
||||
s_retval = Primitive::make("div2_f64",
|
||||
s_retval = PrimitiveExpr::make("div2_f64",
|
||||
&div2_f64,
|
||||
true /*explicit_symbol_def*/,
|
||||
llvmintrinsic::fp_div);
|
||||
|
|
@ -288,4 +288,4 @@ namespace xo {
|
|||
} /*namespace xo*/
|
||||
|
||||
|
||||
/* end Primitive.cpp */
|
||||
/* end PrimitiveExpr.cpp */
|
||||
18
xo-interpreter/include/xo/interpreter/BuiltinPrimitives.hpp
Normal file
18
xo-interpreter/include/xo/interpreter/BuiltinPrimitives.hpp
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
/** @file BuiltinPrimitives.hpp
|
||||
*
|
||||
* @author Roland Conybeare, Nov 2025
|
||||
**/
|
||||
|
||||
#include "xo/alloc/IAlloc.hpp"
|
||||
#include "GlobalEnv.hpp"
|
||||
|
||||
namespace xo {
|
||||
namespace scm {
|
||||
struct BuiltinPrimitives {
|
||||
public:
|
||||
static void install(gc::IAlloc * mm, gp<GlobalEnv> env);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/* end BuiltinPrimitives.hpp */
|
||||
|
|
@ -87,7 +87,7 @@ namespace xo {
|
|||
**/
|
||||
rp<LocalSymtab> symtab_;
|
||||
/** environment contents **/
|
||||
CVector<gp<Object>> slot_v_;
|
||||
obj::CVector<gp<Object>> slot_v_;
|
||||
};
|
||||
} /*namespace scm*/
|
||||
} /*namespace xo*/
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "VsmInstr.hpp"
|
||||
#include "CVector.hpp"
|
||||
#include "xo/object/CVector.hpp"
|
||||
#include "xo/alloc/Object.hpp"
|
||||
|
||||
namespace xo {
|
||||
|
|
@ -73,7 +73,7 @@ namespace xo {
|
|||
gp<VsmStackFrame> parent_;
|
||||
|
||||
/** stored state **/
|
||||
CVector<gp<Object>> slot_v_;
|
||||
obj::CVector<gp<Object>> slot_v_;
|
||||
|
||||
/** proceed to this continuation when popping this frame **/
|
||||
const VsmInstr * cont_ = nullptr;
|
||||
|
|
|
|||
39
xo-interpreter/src/interpreter/BuiltinPrimitives.cpp
Normal file
39
xo-interpreter/src/interpreter/BuiltinPrimitives.cpp
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/** @file BuiltinPrimitives.cpp
|
||||
*
|
||||
* @author Roland Conybeare, Nov 2025
|
||||
**/
|
||||
|
||||
#include "BuiltinPrimitives.hpp"
|
||||
#include "ObjectConversion.hpp"
|
||||
#include "Integer.hpp"
|
||||
#include "Primitive.hpp"
|
||||
#include "xo/reflect/Reflect.hpp"
|
||||
#include <cstdint>
|
||||
|
||||
namespace xo {
|
||||
using xo::reflect::Reflect;
|
||||
using xo::reflect::TypeDescr;
|
||||
|
||||
namespace scm {
|
||||
int64_t
|
||||
add64(int64_t x, int64_t y)
|
||||
{
|
||||
return x + y;
|
||||
}
|
||||
|
||||
void
|
||||
BuiltinPrimitives::install(gc::IAlloc * mm, gp<GlobalEnv> env)
|
||||
{
|
||||
{
|
||||
gp<Object> rhs = xo::obj::make_primitive(mm, add64);
|
||||
TypeDescr td = Reflect::require<decltype(add64)>();
|
||||
rp<Variable> lhs = Variable::make("add", td);
|
||||
gp<Object> * addr = env->establish_var(lhs.borrow());
|
||||
|
||||
*addr = rhs;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* end BuiltinPrimitives.cpp */
|
||||
|
|
@ -4,6 +4,7 @@ set(SELF_LIB xo_interpreter)
|
|||
set(SELF_SRCS
|
||||
init_interpreter.cpp
|
||||
Schematika.cpp
|
||||
BuiltinPrimitives.cpp
|
||||
LocalEnv.cpp
|
||||
GlobalEnv.cpp
|
||||
VirtualSchematikaMachine.cpp
|
||||
|
|
|
|||
|
|
@ -162,7 +162,7 @@ namespace xo {
|
|||
*
|
||||
* note: placement here works b/c CVector<T> not used anywhere else
|
||||
*/
|
||||
using VectorType = CVector<gp<Object>>;
|
||||
using VectorType = obj::CVector<gp<Object>>;
|
||||
|
||||
/* custom reflection for array of Object pointers.
|
||||
* Can use StlVectorTdx here, treating CVector<T> as a vector
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "Schematika.hpp"
|
||||
#include "VirtualSchematikaMachine.hpp"
|
||||
#include "BuiltinPrimitives.hpp"
|
||||
#include "GlobalEnv.hpp"
|
||||
#include "xo/reader/reader.hpp"
|
||||
#include <replxx.hxx>
|
||||
|
|
@ -69,7 +70,9 @@ namespace xo {
|
|||
{
|
||||
up<IAlloc> mm = GC::make(cfg.gc_config_);
|
||||
rp<GlobalSymtab> symtab = GlobalSymtab::make_empty();
|
||||
gp<Env> env = GlobalEnv::make_empty(mm.get(), symtab);
|
||||
gp<GlobalEnv> env = GlobalEnv::make_empty(mm.get(), symtab);
|
||||
|
||||
BuiltinPrimitives::install(mm.get(), env);
|
||||
|
||||
return std::make_unique<Impl>(cfg, std::move(mm), env);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -140,7 +140,7 @@ namespace xo {
|
|||
/* reflect CVector<gp<Object>>.
|
||||
* duplicates similar code in LocalEnv::reflect_self()
|
||||
*/
|
||||
using VectorType = CVector<gp<Object>>;
|
||||
using VectorType = obj::CVector<gp<Object>>;
|
||||
|
||||
/* custom reflection for array of Object pointers.
|
||||
* Can use StlVectorTdx here, treating CVector<T> as a vector
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include "xo/jit/MachPipeline.hpp"
|
||||
#include "xo/expression/Constant.hpp"
|
||||
#include "xo/expression/Primitive.hpp"
|
||||
#include "xo/expression/PrimitiveExpr.hpp"
|
||||
#include "xo/expression/Apply.hpp"
|
||||
#include "xo/expression/Lambda.hpp"
|
||||
#include "xo/expression/Variable.hpp"
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
#include "xo/jit/MachPipeline.hpp"
|
||||
#include "xo/jit/activation_record.hpp"
|
||||
#include "xo/expression/Constant.hpp"
|
||||
#include "xo/expression/Primitive.hpp"
|
||||
#include "xo/expression/PrimitiveExpr.hpp"
|
||||
#include "xo/expression/Apply.hpp"
|
||||
#include "xo/expression/Lambda.hpp"
|
||||
#include "xo/expression/Variable.hpp"
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
#include <cstdint>
|
||||
|
||||
namespace xo {
|
||||
namespace scm {
|
||||
namespace obj {
|
||||
/** gc-only vector.
|
||||
* Used in both LocalEnv and VsmStackFrame
|
||||
**/
|
||||
|
|
@ -33,18 +33,13 @@ namespace xo {
|
|||
ElementType operator[](std::size_t i) const { return v_[i]; }
|
||||
ElementType & operator[](std::size_t i) { return v_[i]; }
|
||||
|
||||
friend class LocalEnv;
|
||||
friend class VsmStackFrame;
|
||||
|
||||
private:
|
||||
public:
|
||||
/** number of elements in @ref v_ **/
|
||||
std::size_t n_ = 0;
|
||||
/** contiguous array of pointers **/
|
||||
ElementType * v_ = nullptr;
|
||||
};
|
||||
|
||||
|
||||
} /*namespace scm*/
|
||||
} /*namespace obj*/
|
||||
} /*namespace xo*/
|
||||
|
||||
/* end CVector.hpp */
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "Number.hpp"
|
||||
#include "ObjectConversion.hpp"
|
||||
#include "xo/indentlog/print/tag.hpp"
|
||||
|
||||
namespace xo {
|
||||
namespace obj {
|
||||
|
|
@ -37,6 +39,29 @@ namespace xo {
|
|||
private:
|
||||
int_type value_ = 0;
|
||||
};
|
||||
|
||||
template <typename IntType>
|
||||
struct ObjectConversion_Integer {
|
||||
static gp<Object> to_object(gc::IAlloc * mm, IntType x) {
|
||||
return new (MMPtr(mm)) Integer(x);
|
||||
}
|
||||
static IntType from_object(gc::IAlloc *, gp<Object> x) {
|
||||
gp<Integer> x_int = Integer::from(x);
|
||||
if (x_int.get()) {
|
||||
return x_int->value();
|
||||
} else {
|
||||
throw std::runtime_error(tostr("ObjectConversion_Integer: x found where Integer expected", xtag("x", x)));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ObjectConversion<int64_t> : public ObjectConversion_Integer<int64_t> {};
|
||||
template <>
|
||||
struct ObjectConversion<int32_t> : public ObjectConversion_Integer<int32_t> {};
|
||||
template <>
|
||||
struct ObjectConversion<int16_t> : public ObjectConversion_Integer<int16_t> {};
|
||||
|
||||
} /*namespace obj*/
|
||||
} /*namespace xo*/
|
||||
|
||||
|
|
|
|||
20
xo-object/include/xo/object/ObjectConversion.hpp
Normal file
20
xo-object/include/xo/object/ObjectConversion.hpp
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/** @file ObjectConversion.hpp
|
||||
*
|
||||
* @author Roland Conybeare, Nov 2025
|
||||
**/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Object.hpp"
|
||||
|
||||
namespace xo {
|
||||
namespace obj {
|
||||
template <typename T>
|
||||
struct ObjectConversion {
|
||||
static gp<Object> to_object(gc::IAlloc * mm, const T & x) = delete;
|
||||
static T from_object(gc::IAlloc * mm, gp<Object> x) = delete;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/* end ObjectConversion.hpp */
|
||||
|
|
@ -6,7 +6,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "Procedure.hpp"
|
||||
#include "CVector.hpp"
|
||||
#include "ObjectConversion.hpp"
|
||||
#include "xo/reflect/Reflect.hpp"
|
||||
|
||||
namespace xo {
|
||||
namespace obj {
|
||||
|
|
@ -25,15 +26,14 @@ namespace xo {
|
|||
using function_type = Fn;
|
||||
|
||||
public:
|
||||
explicit PrimitiveBase(Converter & cvt, Fn impl) : converter_{cvt}, impl_{std::move(impl)} {}
|
||||
explicit PrimitiveBase(Fn impl) : 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;
|
||||
virtual gp<Object> apply_nocheck(gc::IAlloc * mm, const CVector<gp<Object>> & args) override = 0;
|
||||
|
||||
protected:
|
||||
Converter & converter_;
|
||||
Fn impl_;
|
||||
};
|
||||
|
||||
|
|
@ -41,29 +41,60 @@ namespace xo {
|
|||
class Primitive : public PrimitiveBase<Fn> {
|
||||
};
|
||||
|
||||
template <Ret, Arg1, Arg2>
|
||||
template <typename Ret, typename Arg1, typename Arg2>
|
||||
class Primitive<Ret (*)(Arg1, Arg2)> : public PrimitiveBase<Ret (*)(Arg1, Arg2)> {
|
||||
public:
|
||||
using Super = PrimitiveBase<Ret (*)(Arg1, Arg2)>;
|
||||
using function_type = Ret (*)(Arg1, Arg2);
|
||||
using TaggedPtr = xo::reflect::TaggedPtr;
|
||||
|
||||
public:
|
||||
explicit Primitive(Converter & cvt, function_type fn) : PrimitiveBase<Ret (*)(Arg1, Arg2)>{cvt, fn} {}
|
||||
explicit Primitive(function_type fn) : PrimitiveBase<Ret (*)(Arg1, Arg2)>{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]
|
||||
virtual gp<Object> apply_nocheck(gc::IAlloc * mm,
|
||||
const CVector<gp<Object>> & args) final override {
|
||||
/* note: args[0] will be this procedure.
|
||||
* actual i'th function argument in args[i+1]
|
||||
*/
|
||||
Arg1 arg1 = ObjectConversion<Arg1>::from_object(mm, args[1]);
|
||||
Arg2 arg2 = ObjectConversion<Arg2>::from_object(mm, args[2]);
|
||||
|
||||
Ret retval = (*Super::impl_)(arg1, arg2);
|
||||
|
||||
return ObjectConversion<Ret>::to_object(mm, retval);
|
||||
}
|
||||
|
||||
private:
|
||||
// inherited from Object..
|
||||
|
||||
virtual TaggedPtr self_tp() const final override {
|
||||
using xo::reflect::Reflect;
|
||||
|
||||
return Reflect::make_tp(const_cast<Primitive*>(this));
|
||||
}
|
||||
virtual void display(std::ostream & os) const final override {
|
||||
os << "<primitive>";
|
||||
}
|
||||
virtual std::size_t _shallow_size() const final override {
|
||||
return sizeof(*this);
|
||||
}
|
||||
virtual Object *_shallow_copy(gc::IAlloc * mm) const final override {
|
||||
Cpof cpof(mm, this);
|
||||
return new (cpof) Primitive(*this);
|
||||
}
|
||||
std::size_t _forward_children(gc::IAlloc *) final override {
|
||||
return _shallow_size();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Fn>
|
||||
gp<Primitive<Fn>>
|
||||
make_primitive(gc::IAlloc * mm, Fn fn) {
|
||||
return new (MMPtr(mm)) Primitive<Fn>(fn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,11 @@
|
|||
#pragma once
|
||||
|
||||
#include "Object.hpp"
|
||||
#include "CVector.hpp"
|
||||
|
||||
namespace xo {
|
||||
namespace gc { class IAlloc; }; // see xo-alloc: xo/alloc/IAlloc.hpp
|
||||
|
||||
namespace obj {
|
||||
/** @class ProcedureInterface
|
||||
* @brief Interface to a dynamically-typed procedure
|
||||
|
|
@ -15,7 +18,7 @@ namespace xo {
|
|||
class Procedure : public Object {
|
||||
public:
|
||||
virtual std::size_t n_args() const = 0;
|
||||
virtual gp<Object> apply_nocheck(const CVector<gp<Object>> & args) = 0;
|
||||
virtual gp<Object> apply_nocheck(gc::IAlloc * mm, const CVector<gp<Object>> & args) = 0;
|
||||
|
||||
// inherited from Object..
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
#include "xo/expression/Expression.hpp"
|
||||
#include "xo/expression/Apply.hpp"
|
||||
#include "xo/expression/PrimitiveExprInterface.hpp"
|
||||
#include "xo/expression/Primitive.hpp"
|
||||
#include "xo/expression/PrimitiveExpr.hpp"
|
||||
#include "xo/expression/ConstantInterface.hpp"
|
||||
#include "xo/expression/Constant.hpp"
|
||||
#include "xo/expression/Variable.hpp"
|
||||
|
|
@ -22,7 +22,7 @@ namespace xo {
|
|||
using xo::scm::Expression;
|
||||
using xo::scm::make_apply;
|
||||
using xo::scm::PrimitiveExprInterface;
|
||||
using xo::scm::Primitive;
|
||||
using xo::scm::PrimitiveExpr;
|
||||
using xo::scm::make_primitive;
|
||||
using xo::scm::ConstantInterface;
|
||||
using xo::scm::Constant;
|
||||
|
|
@ -106,14 +106,14 @@ namespace xo {
|
|||
|
||||
using int32_t = std::int32_t;
|
||||
|
||||
py::class_<Primitive<int32_t (*)(int32_t, int32_t)>,
|
||||
py::class_<PrimitiveExpr<int32_t (*)(int32_t, int32_t)>,
|
||||
PrimitiveExprInterface,
|
||||
rp<Primitive<int32_t (*)(int32_t, int32_t)>>>(m, "Primitive_i32_i32")
|
||||
rp<PrimitiveExpr<int32_t (*)(int32_t, int32_t)>>>(m, "PrimitiveExpr_i32_i32")
|
||||
;
|
||||
|
||||
py::class_<Primitive<double (*)(double)>,
|
||||
py::class_<PrimitiveExpr<double (*)(double)>,
|
||||
PrimitiveExprInterface,
|
||||
rp<Primitive<double (*)(double)>>>(m, "Primitive_double_double")
|
||||
rp<PrimitiveExpr<double (*)(double)>>>(m, "PrimitiveExpr_double_double")
|
||||
;
|
||||
using Fn_dbl_dbl_type = double (*)(double);
|
||||
|
||||
|
|
@ -135,9 +135,9 @@ namespace xo {
|
|||
llvmintrinsic::fp_cos); },
|
||||
py::doc("create primitive representing the ::cos() function"));
|
||||
|
||||
py::class_<Primitive<double (*)(double, double)>,
|
||||
py::class_<PrimitiveExpr<double (*)(double, double)>,
|
||||
PrimitiveExprInterface,
|
||||
rp<Primitive<double (*)(double, double)>>>(m, "Primitive_double_double_double")
|
||||
rp<PrimitiveExpr<double (*)(double, double)>>>(m, "PrimitiveExpr_double_double_double")
|
||||
;
|
||||
|
||||
m.def("make_pow_pm",
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
#include "xo/pyexpression/pyexpression.hpp"
|
||||
#include "xo/jit/MachPipeline.hpp"
|
||||
#include "xo/jit/intrinsics.hpp"
|
||||
#include "xo/expression/Primitive.hpp"
|
||||
#include "xo/expression/PrimitiveExpr.hpp"
|
||||
#include "xo/pyutil/pycaller.hpp"
|
||||
#include "xo/pyutil/pyutil.hpp"
|
||||
#include <llvm/Config/llvm-config.h>
|
||||
|
|
|
|||
|
|
@ -99,21 +99,28 @@ namespace xo {
|
|||
*
|
||||
* Example
|
||||
* T * p = new T(...);
|
||||
* DestructorAux<T>::dtor(p);
|
||||
* InvokerAux<T>::dtor(p);
|
||||
**/
|
||||
template <typename T>
|
||||
struct InvokerAux : public Invoker {
|
||||
virtual void dtor(void * addr) const override {
|
||||
T * obj = static_cast<T *>(addr);
|
||||
T * obj = reinterpret_cast<T *>(addr);
|
||||
|
||||
obj->~T();
|
||||
}
|
||||
};
|
||||
|
||||
/** no dtor for void **/
|
||||
template<>
|
||||
struct InvokerAux<void> : public Invoker {
|
||||
virtual void dtor(void *) const override {}
|
||||
};
|
||||
|
||||
/** no dtor for function types **/
|
||||
template <typename Ret, typename... Args>
|
||||
struct InvokerAux<Ret(Args...)> : public Invoker {
|
||||
virtual void dtor(void *) const override {}
|
||||
};
|
||||
} /*namespace detail*/
|
||||
} /*namespace reflect*/
|
||||
} /*namespace xo*/
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue