Last active
August 29, 2015 14:03
-
-
Save piscisaureus/b94c77e22c8db34a5d51 to your computer and use it in GitHub Desktop.
nni
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <functional> | |
#include <iostream> | |
class JSAny { | |
void* substance; | |
}; | |
class JSBool : public JSAny { | |
public: | |
JSBool() {} | |
static JSBool From(JSAny& v) { | |
JSBool b; | |
return b; | |
} | |
}; | |
class JSInt : public JSAny { | |
public: | |
JSInt(){}; | |
JSInt(int a){}; | |
static JSInt From(JSAny& v) { | |
JSInt a; | |
return a; | |
} | |
}; | |
class JSUndefined : public JSAny { | |
public: | |
JSUndefined(void){}; | |
}; | |
class JSArgumentList { | |
public: | |
JSAny any; | |
JSAny get(int index) { return any; } | |
size_t length() { return 0; } | |
}; | |
template <typename T> | |
T convert(JSArgumentList& list, int& index) { | |
std::cout << index << std::endl; | |
return T::From(list.get(index++)); | |
} | |
template <typename ReturnType, typename Function, typename... Arguments> | |
struct void_to_undefined { | |
static ReturnType Call(Function& function, Arguments&... arguments) { | |
return function(arguments...); | |
}; | |
}; | |
template <typename Function, typename... Arguments> | |
struct void_to_undefined<void, Function, Arguments...> { | |
static JSUndefined Call(Function& function, Arguments&... arguments) { | |
function(arguments...); | |
return JSUndefined(); | |
}; | |
}; | |
template <typename ReturnType, typename... Arguments> | |
class JSFunction { | |
public: | |
typedef std::function<ReturnType(Arguments...)> ImplementationType; | |
typedef typename std::conditional<std::is_void<ReturnType>::value, | |
JSUndefined, | |
ReturnType>::type JSReturnType; | |
JSFunction(ImplementationType& func) : implementation(func) {} | |
JSReturnType operator()(Arguments&... arguments) { | |
return void_to_undefined<ReturnType, | |
ImplementationType, | |
Arguments...>::Call(implementation, arguments...); | |
}; | |
JSAny RuntimeCall(JSArgumentList& arguments) { | |
int index = 0; | |
return operator()(convert<Arguments>(arguments, index)...); | |
}; | |
ImplementationType implementation; | |
}; | |
template <bool is_class, typename Callable> | |
struct callable_signature_helper {}; | |
template <typename ReturnType, typename... Arguments> | |
struct callable_signature_helper<false, ReturnType (*)(Arguments...)> { | |
typedef std::function<ReturnType(Arguments...)> function; | |
typedef JSFunction<ReturnType, Arguments...> js_function; | |
}; | |
template <typename Callable> | |
struct callable_signature_helper<true, Callable> | |
: public callable_signature_helper<true, decltype(&Callable::operator())> { | |
}; | |
template <typename Class, typename ReturnType, typename... Arguments> | |
struct callable_signature_helper<true, | |
ReturnType (Class::*)(Arguments...) const> { | |
typedef std::function<ReturnType(Arguments...)> function; | |
typedef JSFunction<ReturnType, Arguments...> js_function; | |
}; | |
template <typename Callable> | |
struct callable_signature | |
: public callable_signature_helper<std::is_class<Callable>::value, | |
Callable> {}; | |
template <typename Callable> | |
typename callable_signature<Callable>::js_function function(Callable callable) { | |
return callable_signature<Callable>::js_function( | |
static_cast<typename callable_signature<Callable>::function>(callable)); | |
} | |
JSInt Test2(JSBool a, JSInt b) { | |
std::cout << "hello2" << std::endl; | |
return 42; | |
} | |
class TestClass { | |
public: | |
static void Test3(JSBool a, JSInt b) { std::cout << "hello3" << std::endl; } | |
}; | |
int main(int argc, const char** argv) { | |
auto fn1 = function([](JSBool a, JSInt b) -> JSInt { | |
std::cout << "hello" << std::endl; | |
return 42; | |
}); | |
auto fn2 = function(Test2); | |
auto fn3 = function(TestClass::Test3); | |
JSArgumentList arguments; | |
fn1.RuntimeCall(arguments); | |
fn2.RuntimeCall(arguments); | |
fn3.RuntimeCall(arguments); | |
JSBool a; | |
JSInt b; | |
auto test1 = fn1(a, b); | |
auto test2 = fn2(a, b); | |
auto test3 = fn3(a, b); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment