103 lines
3.3 KiB
C++
103 lines
3.3 KiB
C++
/** @file DPrimitive.hpp
|
|
*
|
|
* @author Roland Conybeare, Jan 2025
|
|
**/
|
|
|
|
#pragma once
|
|
|
|
#include "RuntimeContext.hpp"
|
|
#include <xo/object2/DArray.hpp>
|
|
#include <xo/gc/GCObjectConversion.hpp>
|
|
#include <xo/gc/GCObject.hpp>
|
|
#include <xo/alloc2/Allocator.hpp>
|
|
#include <xo/facet/FacetRegistry.hpp>
|
|
|
|
#include <tuple>
|
|
#include <type_traits>
|
|
#include <utility>
|
|
#include <string_view>
|
|
|
|
namespace xo {
|
|
namespace scm {
|
|
/** @brief Extract return type and argument types from a function type.
|
|
*
|
|
* Primary template (undefined) - specializations handle specific cases
|
|
**/
|
|
template <typename Fn>
|
|
struct FnTraits;
|
|
|
|
/** specialization for function pointers **/
|
|
template <typename R, typename... Args>
|
|
struct FnTraits<R(*)(Args...)> {
|
|
/** function return type **/
|
|
using return_type = R;
|
|
/** tuple type for function arguments **/
|
|
using args_tuple = std::tuple<Args...>;
|
|
/** number of arguments **/
|
|
static constexpr std::size_t n_args = sizeof...(Args);
|
|
|
|
/** arg_type<i> is the type of the i'th argument to Fn **/
|
|
template <std::size_t I>
|
|
using arg_type = std::tuple_element_t<I, args_tuple>;
|
|
};
|
|
|
|
/** specialization for function references **/
|
|
template <typename R, typename... Args>
|
|
struct FnTraits<R(&)(Args...)> : FnTraits<R(*)(Args...)> {};
|
|
|
|
/** specialization for plain function types **/
|
|
template <typename R, typename... Args>
|
|
struct FnTraits<R(Args...)> : FnTraits<R(*)(Args...)> {};
|
|
|
|
template <typename Fn>
|
|
class Primitive {
|
|
public:
|
|
using AAllocator = xo::mm::AAllocator;
|
|
using AGCObject = xo::mm::AGCObject;
|
|
using DArray = xo::scm::DArray;
|
|
using Traits = FnTraits<Fn>;
|
|
|
|
public:
|
|
Primitive(std::string_view name, Fn fn) : name_{name}, fn_{fn} {}
|
|
|
|
bool is_nary() const noexcept { return false; }
|
|
static constexpr std::int32_t n_args() noexcept { return Traits::n_args; }
|
|
|
|
obj<AGCObject> apply_nocheck(const DArray * args) {
|
|
return _apply_nocheck(args,
|
|
std::make_index_sequence<Traits::n_args>{});
|
|
}
|
|
|
|
private:
|
|
template <std::size_t... Is>
|
|
obj<AGCObject> _apply_nocheck(const DArray * args,
|
|
std::index_sequence<Is...>)
|
|
{
|
|
using xo::facet::FacetRegistry;
|
|
|
|
using R = typename Traits::return_type;
|
|
|
|
assert(args);
|
|
assert(args->size() > 0);
|
|
|
|
obj<ARuntimeContext> rcx
|
|
= FacetRegistry::instance().variant<ARuntimeContext>(args->at(0));
|
|
obj<AAllocator> mm = rcx.allocator();
|
|
|
|
R result
|
|
= fn_(GCObjectConversion<typename Traits::template arg_type<Is>>::from_gco(mm, args->at(Is))... );
|
|
|
|
return GCObjectConversion<R>::to_gco(mm, result);
|
|
}
|
|
|
|
private:
|
|
/** name of this primitive **/
|
|
std::string_view name_;
|
|
/** function implementation **/
|
|
Fn fn_;
|
|
}; /*Primitive*/
|
|
|
|
} /*namespace scm*/
|
|
} /*namespace xo*/
|
|
|
|
/* end DPrimitive.hpp */
|