refactor: Refactorized whole project structure
This commit is contained in:
166
source/NoNut/include/Function.h
Normal file
166
source/NoNut/include/Function.h
Normal file
@@ -0,0 +1,166 @@
|
||||
#ifndef NONUT_CORE_FUNCTION_H
|
||||
#define NONUT_CORE_FUNCTION_H
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include <sqapi.h>
|
||||
#include "Utils.h"
|
||||
|
||||
#define FUNCTION_CTOR(function) function(#function)
|
||||
|
||||
namespace nonut
|
||||
{
|
||||
class Class;
|
||||
|
||||
template <typename ReturnType, typename... Args>
|
||||
class Function
|
||||
{
|
||||
public:
|
||||
// Ctor for functions
|
||||
Function(const String& functionName, const SQObject env = getRootTable()) : envObj(env)
|
||||
{
|
||||
HSQUIRRELVM vm = Sqrat::DefaultVM::Get();
|
||||
sq_pushobject(vm, envObj);
|
||||
sq_pushstring(vm, functionName.c_str(), functionName.length());
|
||||
|
||||
// get the function from the root table
|
||||
if (SQ_FAILED(sq_get(vm, -2)))
|
||||
{
|
||||
sq_pop(vm, 1);
|
||||
throw;
|
||||
}
|
||||
|
||||
// check the type
|
||||
if (const SQObjectType value_type = sq_gettype(vm, -1); value_type != OT_CLOSURE && value_type !=
|
||||
OT_NATIVECLOSURE)
|
||||
{
|
||||
sq_pop(vm, 2);
|
||||
throw;
|
||||
}
|
||||
|
||||
// get function and add ref
|
||||
sq_getstackobj(vm, -1, &funcObj);
|
||||
sq_addref(vm, &funcObj);
|
||||
|
||||
sq_pop(vm, 2);
|
||||
}
|
||||
|
||||
// Ctor for class methods
|
||||
Function(const String& functionName, const SQObject classObjectInstance,
|
||||
const SQObject classObject) : envObj(classObjectInstance)
|
||||
{
|
||||
HSQUIRRELVM vm = Sqrat::DefaultVM::Get();
|
||||
isClassMethod = true; // Prevent release of the resources cause we don't own them
|
||||
sq_pushobject(vm, classObject);
|
||||
sq_pushstring(vm, functionName.c_str(), functionName.length());
|
||||
|
||||
// get the function from the root table
|
||||
if (SQ_FAILED(sq_get(vm, -2)))
|
||||
{
|
||||
sq_pop(vm, 1);
|
||||
throw;
|
||||
}
|
||||
|
||||
// check the type
|
||||
if (const SQObjectType value_type = sq_gettype(vm, -1); value_type != OT_CLOSURE && value_type !=
|
||||
OT_NATIVECLOSURE)
|
||||
{
|
||||
sq_pop(vm, 2);
|
||||
throw;
|
||||
}
|
||||
|
||||
// get function and add ref
|
||||
sq_getstackobj(vm, -1, &funcObj);
|
||||
sq_addref(vm, &funcObj);
|
||||
|
||||
sq_pop(vm, 2);
|
||||
}
|
||||
|
||||
~Function()
|
||||
{
|
||||
if (!isClassMethod)
|
||||
{
|
||||
HSQUIRRELVM vm = Sqrat::DefaultVM::Get();
|
||||
sq_release(vm, &funcObj);
|
||||
sq_release(vm, &envObj);
|
||||
sq_resetobject(&funcObj);
|
||||
sq_resetobject(&envObj);
|
||||
}
|
||||
}
|
||||
|
||||
ReturnType operator()(Args ... args)
|
||||
{
|
||||
HSQUIRRELVM vm = Sqrat::DefaultVM::Get();
|
||||
const auto top = sq_gettop(vm);
|
||||
sq_pushobject(vm, funcObj);
|
||||
sq_pushobject(vm, envObj);
|
||||
auto debug = sq_gettop(vm);
|
||||
(sqPushValue(vm, args), ...);
|
||||
|
||||
if constexpr (std::is_same_v<ReturnType, void>)
|
||||
{
|
||||
debug = sq_gettop(vm);
|
||||
auto returnCode = sq_call(vm, ARG_COUNT + 1, SQFalse, SQFalse); // TODO: HANDLE ERROR RETURN CODE
|
||||
sq_pop(vm, 2);
|
||||
sq_settop(vm, top);
|
||||
return void();
|
||||
}
|
||||
else
|
||||
{
|
||||
auto returnCode = sq_call(vm, ARG_COUNT + 1, SQTrue, SQFalse); // TODO: HANDLE ERROR RETURN CODE
|
||||
|
||||
std::optional<ReturnType> result;
|
||||
|
||||
if constexpr (std::derived_from<ReturnType, CustomType>)
|
||||
{
|
||||
result = std::make_optional<ReturnType>();
|
||||
auto intermediateResult = returnVar<SQObject>();
|
||||
result.value().convert(intermediateResult);
|
||||
sq_release(vm, &intermediateResult);
|
||||
sq_resetobject(&intermediateResult);
|
||||
}
|
||||
else if constexpr (std::derived_from<ReturnType, Class>)
|
||||
{
|
||||
auto intermediateResult = returnVar<SQObject>();
|
||||
//result = std::make_optional<ReturnType>(ReturnType(intermediateResult));
|
||||
result.emplace(ReturnType(intermediateResult));
|
||||
|
||||
sq_release(vm, &intermediateResult);
|
||||
sq_resetobject(&intermediateResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = std::make_optional<ReturnType>(returnVar<ReturnType>());
|
||||
}
|
||||
|
||||
sq_pop(vm, 2);
|
||||
sq_settop(vm, top);
|
||||
return result.value();
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] SQObject getObject() const
|
||||
{
|
||||
return funcObj;
|
||||
}
|
||||
|
||||
private:
|
||||
SQObject funcObj{};
|
||||
SQObject envObj{};
|
||||
bool isClassMethod = false;
|
||||
static constexpr auto ARG_COUNT{sizeof...(Args)};
|
||||
|
||||
static SQObject getRootTable()
|
||||
{
|
||||
HSQUIRRELVM vm = Sqrat::DefaultVM::Get();
|
||||
SQObject rootTable{};
|
||||
sq_pushroottable(vm);
|
||||
sq_getstackobj(vm, -1, &rootTable);
|
||||
sq_addref(vm, &rootTable);
|
||||
sq_pop(vm, 1); // pop root table
|
||||
return rootTable;
|
||||
}
|
||||
};
|
||||
}
|
||||
#endif // NONUT_CORE_FUNCTION_H
|
||||
Reference in New Issue
Block a user