File functionFactory.h
File List > jac > machine > functionFactory.h
Go to the documentation of this file
#pragma once
#include <functional>
#include "class.h"
#include "funcUtil.h"
#include "values.h"
namespace jac {
namespace detail {
class CallableBase {
public:
virtual Value invoke(ContextRef ctx, ValueWeak thisVal, ValueVectorWeak args) = 0;
virtual ~CallableBase() = default;
};
template<typename Func, typename Signature, bool withThis, bool variadic>
class CallableHolder;
template<typename Func, typename Res, typename... Args>
class CallableHolder<Func, std::function<Res(Args...)>, false, false> final : public CallableBase {
Func _func;
public:
explicit CallableHolder(Func func) : _func(std::move(func)) {}
Value invoke(ContextRef ctx, ValueWeak thisVal, ValueVectorWeak args) override {
return processCall<Func, Res, Args...>(ctx, thisVal, args, _func);
}
};
template<typename Func, typename Res>
class CallableHolder<Func, std::function<Res(ValueVectorWeak)>, false, true> final : public CallableBase {
Func _func;
public:
explicit CallableHolder(Func func) : _func(std::move(func)) {}
Value invoke(ContextRef ctx, ValueWeak thisVal, ValueVectorWeak args) override {
return processCallVariadic<Func, Res>(ctx, thisVal, args, _func);
}
};
template<typename Func, typename Res, typename... Args>
class CallableHolder<Func, std::function<Res(ContextRef, ValueWeak, Args...)>, true, false> final : public CallableBase {
Func _func;
public:
explicit CallableHolder(Func func) : _func(std::move(func)) {}
Value invoke(ContextRef ctx, ValueWeak thisVal, ValueVectorWeak args) override {
return processCallThis<Func, Res, Args...>(ctx, thisVal, args, _func);
}
};
template<typename Func, typename Res>
class CallableHolder<Func, std::function<Res(ContextRef, ValueWeak, ValueVectorWeak)>, true, true> final : public CallableBase {
Func _func;
public:
explicit CallableHolder(Func func) : _func(std::move(func)) {}
Value invoke(ContextRef ctx, ValueWeak thisVal, ValueVectorWeak args) override {
return processCallThisVariadic<Func, Res>(ctx, thisVal, args, _func);
}
};
struct CallableProtoBuilder : public ProtoBuilder::Opaque<CallableBase>, public ProtoBuilder::Callable {
static Value callFunction(ContextRef ctx, ValueWeak funcObj, ValueWeak thisVal, ValueVectorWeak args) {
return getOpaque(ctx, funcObj)->invoke(ctx, thisVal, args);
}
};
using CallableClass = Class<CallableProtoBuilder>;
} // namespace detail
class FunctionFactory {
ContextRef _context;
template<bool withThis, bool variadic, typename Func>
Function makeFunction(Func func) {
using Signature = decltype(std::function(func));
using Holder = detail::CallableHolder<Func, Signature, withThis, variadic>;
detail::CallableClass::init("CppFunction");
return static_cast<Value>(detail::CallableClass::createInstance(_context, new Holder(std::move(func)))).to<Function>();
}
public:
FunctionFactory(ContextRef context) : _context(context) {}
template<class Func>
Function newFunction(Func func) {
return makeFunction<false, false>(std::move(func));
}
template<class Func>
Function newFunctionVariadic(Func func) {
return makeFunction<false, true>(std::move(func));
}
template<class Func>
Function newFunctionThis(Func func) {
return makeFunction<true, false>(std::move(func));
}
template<class Func>
Function newFunctionThisVariadic(Func func) {
return makeFunction<true, true>(std::move(func));
}
};
} // namespace jac