1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2026-01-20 22:24:38 +01:00

Massive code reduction in the binding utility by using variadic templates.

Extensive code refactoring surrounding the StackStrF helper to facilitate the new changes.
Various other miscellaneous changes and code refactoring to facilitate the new changes.
This commit is contained in:
Sandu Liviu Catalin
2018-07-30 00:58:27 +03:00
parent 199e9ac502
commit f300e7ff4a
20 changed files with 724 additions and 9507 deletions

View File

@@ -41,38 +41,98 @@ namespace Sqrat {
/// @cond DEV
//
// Squirrel Global Functions
//
template <class R> struct SqGlobalProxy {
template <class... A> static SQInteger Run(HSQUIRRELVM vm, SQInteger idx) {
ArgPop<A...> a(vm, idx);
if (SQ_FAILED(a.Proc())) {
return a.ProcRes();
}
a.Call(vm, [](HSQUIRRELVM vm, A... a) {
typedef R(*M)(A...);
M* method;
sq_getuserdata(vm, -1, reinterpret_cast<SQUserPointer*>(&method), nullptr);
R ret = (*method)(a...);
PushVar(vm, ret);
});
return 1;
}
};
//
// reference return specialization
//
template <class R> struct SqGlobalProxy<R&> {
template <class... A> static SQInteger Run(HSQUIRRELVM vm, SQInteger idx) {
ArgPop<A...> a(vm, idx);
if (SQ_FAILED(a.Proc())) {
return a.ProcRes();
}
a.Call(vm, [](HSQUIRRELVM vm, A... a) {
typedef R&(*M)(A...);
M* method;
sq_getuserdata(vm, -1, reinterpret_cast<SQUserPointer*>(&method), nullptr);
R& ret = (*method)(a...);
PushVarR(vm, ret);
});
return 1;
}
};
//
// void return specialization
//
template <> struct SqGlobalProxy<void> {
template <class... A> static SQInteger Run(HSQUIRRELVM vm, SQInteger idx) {
ArgPop<A...> a(vm, idx);
if (SQ_FAILED(a.Proc())) {
return a.ProcRes();
}
a.Call(vm, [](HSQUIRRELVM vm, A... a) {
typedef void(*M)(A...);
M* method;
sq_getuserdata(vm, -1, reinterpret_cast<SQUserPointer*>(&method), nullptr);
(*method)(a...);
});
return 0;
}
};
template<bool> struct SqGlobalParamCheck {
static inline bool Invalid(SQInteger top, SQInteger count) {
return top != count;
}
};
template<> struct SqGlobalParamCheck<true> {
static inline bool Invalid(SQInteger top, SQInteger count) {
return top < count;
}
};
//
// Squirrel Global Functions
//
template <class R> struct SqGlobal {
// Function proxy
template <SQInteger startIdx, bool overloaded, class... A> static SQFUNCTION GetProxy() noexcept {
typedef R(*M)(A...);
return +[](HSQUIRRELVM vm) noexcept -> SQInteger {
return +[](HSQUIRRELVM vm) noexcept -> SQInteger {
#if !defined (SCRAT_NO_ERROR_CHECKING)
if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != static_cast<SQInteger>(startIdx + sizeof...(A))) {
return sq_throwerror(vm, _SC("wrong number of parameters"));
}
if (!SQRAT_CONST_CONDITION(overloaded) &&
SqGlobalParamCheck< ArgPop<A...>::HASFMT >::Invalid(sq_gettop(vm), startIdx + sizeof...(A))) {
return sq_throwerror(vm, _SC("wrong number of parameters"));
}
#endif
M* method;
sq_getuserdata(vm, -1, reinterpret_cast<SQUserPointer*>(&method), NULL);
SQTRY()
ArgPop<A...> a(vm, startIdx);
SQCATCH_NOEXCEPT(vm) {
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
}
R ret = a.template Eval<R,M>(*method);
SQCATCH_NOEXCEPT(vm) {
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
}
PushVar(vm, ret);
SQCATCH(vm) {
return sq_throwerror(vm, SQWHAT(vm));
}
return 1;
};
try {
return SqGlobalProxy<R>::Run(vm, startIdx);
} catch (const Exception& e) {
return sq_throwerror(vm, e.what());
}
SQ_UNREACHABLE
};
}
};
@@ -83,32 +143,20 @@ template <class R> struct SqGlobal {
template <class R> struct SqGlobal<R&> {
// Function proxy
template <SQInteger startIdx, bool overloaded, class... A> static SQFUNCTION GetProxy() noexcept {
typedef R&(*M)(A...);
return +[](HSQUIRRELVM vm) noexcept -> SQInteger {
return +[](HSQUIRRELVM vm) noexcept -> SQInteger {
#if !defined (SCRAT_NO_ERROR_CHECKING)
if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != static_cast<SQInteger>(startIdx + sizeof...(A))) {
return sq_throwerror(vm, _SC("wrong number of parameters"));
}
if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) &&
SqGlobalParamCheck< ArgPop<A...>::HASFMT >::Invalid(sq_gettop(vm), startIdx + sizeof...(A))) {
return sq_throwerror(vm, _SC("wrong number of parameters"));
}
#endif
M* method;
sq_getuserdata(vm, -1, reinterpret_cast<SQUserPointer*>(&method), NULL);
SQTRY()
ArgPop<A...> a(vm, startIdx);
SQCATCH_NOEXCEPT(vm) {
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
}
R& ret = a.template Eval<R&, M>(*method);
SQCATCH_NOEXCEPT(vm) {
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
}
PushVarR(vm, ret);
SQCATCH(vm) {
return sq_throwerror(vm, SQWHAT(vm));
}
return 1;
};
try {
return SqGlobalProxy<R&>::Run(vm, startIdx);
} catch (const Exception& e) {
return sq_throwerror(vm, e.what());
}
SQ_UNREACHABLE
};
}
};
@@ -119,31 +167,20 @@ template <class R> struct SqGlobal<R&> {
template <> struct SqGlobal<void> {
// Function proxy
template <SQInteger startIdx, bool overloaded, class... A> static SQFUNCTION GetProxy() noexcept {
typedef void(*M)(A...);
return +[](HSQUIRRELVM vm) noexcept -> SQInteger {
return +[](HSQUIRRELVM vm) noexcept -> SQInteger {
#if !defined (SCRAT_NO_ERROR_CHECKING)
if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != static_cast<SQInteger>(startIdx + sizeof...(A))) {
return sq_throwerror(vm, _SC("wrong number of parameters"));
}
if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) &&
SqGlobalParamCheck< ArgPop<A...>::HASFMT >::Invalid(sq_gettop(vm), startIdx + sizeof...(A))) {
return sq_throwerror(vm, _SC("wrong number of parameters"));
}
#endif
M* method;
sq_getuserdata(vm, -1, reinterpret_cast<SQUserPointer*>(&method), NULL);
SQTRY()
ArgPop<A...> a(vm, startIdx);
SQCATCH_NOEXCEPT(vm) {
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
}
a.template Exec<M>(*method);
SQCATCH_NOEXCEPT(vm) {
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
}
SQCATCH(vm) {
return sq_throwerror(vm, SQWHAT(vm));
}
return 0;
};
try {
return SqGlobalProxy<void>::Run(vm, startIdx);
} catch (const Exception& e) {
return sq_throwerror(vm, e.what());
}
SQ_UNREACHABLE
};
}
};
@@ -167,144 +204,6 @@ template <class R,class T,class... A> SQFUNCTION SqMemberGlobalFunc(R& (* /*meth
return SqGlobal<R&>::template GetProxy<1, false, T, A...>();
}
//
// Squirrel Global Functions
//
template <class R> struct SqGlobalFmt {
// Function proxy
template <SQInteger startIdx, bool overloaded, class... A> static SQFUNCTION GetProxy() noexcept {
typedef R(*M)(A...);
return +[](HSQUIRRELVM vm) noexcept -> SQInteger {
#if !defined (SCRAT_NO_ERROR_CHECKING)
if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) < static_cast<SQInteger>(startIdx + sizeof...(A))) {
return sq_throwerror(vm, _SC("wrong number of parameters"));
}
#endif
M* method;
sq_getuserdata(vm, -1, reinterpret_cast<SQUserPointer*>(&method), NULL);
SQTRY()
ArgPop<A...> a(vm, startIdx, true);
SQCATCH_NOEXCEPT(vm) {
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
}
// Validate the format
if (SQ_FAILED(a.Last().value.mRes)) {
return a.Last().value.mRes;
}
R ret = a.template Eval<R,M>(*method);
SQCATCH_NOEXCEPT(vm) {
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
}
PushVar(vm, ret);
SQCATCH(vm) {
return sq_throwerror(vm, SQWHAT(vm));
}
return 1;
};
}
};
//
// reference return specialization
//
template <class R> struct SqGlobalFmt<R&> {
// Function proxy
template <SQInteger startIdx, bool overloaded, class... A> static SQFUNCTION GetProxy() noexcept {
typedef R&(*M)(A...);
return +[](HSQUIRRELVM vm) noexcept -> SQInteger {
#if !defined (SCRAT_NO_ERROR_CHECKING)
if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) < static_cast<SQInteger>(startIdx + sizeof...(A))) {
return sq_throwerror(vm, _SC("wrong number of parameters"));
}
#endif
M* method;
sq_getuserdata(vm, -1, reinterpret_cast<SQUserPointer*>(&method), NULL);
SQTRY()
ArgPop<A...> a(vm, startIdx, true);
SQCATCH_NOEXCEPT(vm) {
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
}
// Validate the format
if (SQ_FAILED(a.Last().value.mRes)) {
return a.Last().value.mRes;
}
R& ret = a.template Eval<R&,M>(*method);
SQCATCH_NOEXCEPT(vm) {
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
}
PushVarR(vm, ret);
SQCATCH(vm) {
return sq_throwerror(vm, SQWHAT(vm));
}
return 1;
};
}
};
//
// void return specialization
//
template <> struct SqGlobalFmt<void> {
// Function proxy
template <SQInteger startIdx, bool overloaded, class... A> static SQFUNCTION GetProxy() noexcept {
typedef void(*M)(A...);
return +[](HSQUIRRELVM vm) noexcept -> SQInteger {
#if !defined (SCRAT_NO_ERROR_CHECKING)
if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) < static_cast<SQInteger>(startIdx + sizeof...(A))) {
return sq_throwerror(vm, _SC("wrong number of parameters"));
}
#endif
M* method;
sq_getuserdata(vm, -1, reinterpret_cast<SQUserPointer*>(&method), NULL);
SQTRY()
ArgPop<A...> a(vm, startIdx, true);
SQCATCH_NOEXCEPT(vm) {
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
}
// Validate the format
if (SQ_FAILED(a.Last().value.mRes)) {
return a.Last().value.mRes;
}
a.template Exec<M>(*method);
SQCATCH_NOEXCEPT(vm) {
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
}
SQCATCH(vm) {
return sq_throwerror(vm, SQWHAT(vm));
}
return 0;
};
}
};
// Formatted Global Function Resolver
template <class R,class... A> SQFUNCTION SqGlobalFmtFunc(R (* /*method*/)(A...)) noexcept {
return SqGlobalFmt<R>::template GetProxy<2, false, A...>();
}
// Formatted Global Function Resolver
template <class R,class... A> SQFUNCTION SqGlobalFmtFunc(R& (* /*method*/)(A...)) noexcept {
return SqGlobalFmt<R&>::template GetProxy<2, false, A...>();
}
// Formatted Member Global Function Resolver
template <class R,class T,class... A> SQFUNCTION SqMemberGlobalFmtFunc(R (* /*method*/)(T, A...)) noexcept {
return SqGlobalFmt<R>::template GetProxy<1, false, T, A...>();
}
// Formatted Member Global Function Resolver
template <class R,class T,class... A> SQFUNCTION SqMemberGlobalFmtFunc(R& (* /*method*/)(T, A...)) noexcept {
return SqGlobalFmt<R&>::template GetProxy<1, false, T, A...>();
}
/// @endcond
}