You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
lunarium_OLD/src/scripting/wren_state.cpp

197 lines
6.7 KiB
C++

/******************************************************************************
* File - wren_state.cpp
* Author - Joey Pollack
* Date - 2022/10/25 (y/m/d)
* Mod Date - 2022/10/25 (y/m/d)
* Description - Manages the wren vm, runs scripts. This is the main
* interface for wren.
******************************************************************************/
#include "wren_state.h"
#include "wren_script.h"
#include "coreAPI.h"
#include <utils/logger.h>
#include <utils/helpers.h>
namespace lunarium
{
std::vector<FMBinder*> WrenState::mFMBinders;
WrenState::~WrenState()
{
Shutdown();
}
void WrenState::Shutdown()
{
wrenFreeVM(mpVM);
mpVM = nullptr;
}
u32 WrenState::mLogCat = Logger::RegisterCategory("SCRIPT");
OpRes WrenState::Initialize()
{
WrenConfiguration config;
wrenInitConfiguration(&config);
config.writeFn = WrenState::WriteFN;
config.errorFn = WrenState::ErrorFN;
config.bindForeignMethodFn = WrenState::BindForeignMethodFN;
mpVM = wrenNewVM(&config);
CoreAPI::GetInstance().Initialize(*this);
return OpRes::OK();
}
u32 WrenState::GetLogCat() const
{
return mLogCat;
}
void WrenState::RegisterForeignMethodBinder(FMBinder* binder_method)
{
mFMBinders.push_back(binder_method);
}
/////////////////////////////////////////////////////////////////////
// HANDLES
/////////////////////////////////////////////////////////////////////
WrenHandle* WrenState::GetWrenClassHandle(std::string from_module, std::string class_name)
{
// Load the class into slot 0.
wrenEnsureSlots(mpVM, 1);
wrenGetVariable(mpVM, from_module.c_str(), class_name.c_str(), 0);
WrenHandle* handle = wrenGetSlotHandle(mpVM, 0);
return handle;
}
WrenHandle* WrenState::GetWrenMethodHandle(std::string method_signature)
{
WrenHandle* handle = wrenMakeCallHandle(mpVM, method_signature.c_str());
return handle;
}
void WrenState::CallWrenMethod(WrenHandle* method, WrenHandle* receiver, std::vector<WrenParameter> params, std::string name_tag)
{
wrenEnsureSlots(mpVM, params.size() + 1);
for (int i = 0; i < params.size(); i++)
{
switch (params[i].Type)
{
case WrenParamType::WPT_DOUBLE: wrenSetSlotDouble(mpVM, i + 1, params[i].As.Double); break;
case WrenParamType::WPT_BOOL: wrenSetSlotBool(mpVM, i + 1, params[i].As.Bool); break;
case WrenParamType::WPT_STR: wrenSetSlotString(mpVM, i + 1, params[i].As.String); break;
default: Logger::Warn(mLogCat, "Unknown wren parameter type: %d", (int)params[i].Type);
}
}
wrenSetSlotHandle(mpVM, 0, receiver);
WrenInterpretResult result = wrenCall(mpVM, method);
switch (result)
{
case WREN_RESULT_COMPILE_ERROR: Logger::Trace(mLogCat, "Call compile error in module: %s", name_tag.c_str()); break;
case WREN_RESULT_RUNTIME_ERROR: Logger::Trace(mLogCat, "Call runtime error in module: %s", name_tag.c_str()); break;
case WREN_RESULT_SUCCESS: Logger::Trace(mLogCat, "Call %s run successfully", name_tag.c_str()); break;
}
}
void WrenState::ReleaseWrenHandle(WrenHandle* handle)
{
wrenReleaseHandle(mpVM, handle);
}
/////////////////////////////////////////////////////////////////////
// CODE PROCESSING
/////////////////////////////////////////////////////////////////////
void WrenState::RunScript(WrenScript* script)
{
if (!mpVM)
{
Logger::Error(mLogCat, "Could not run script - the VM is nullptr");
return;
}
WrenInterpretResult result = wrenInterpret(mpVM, script->GetModuleName().c_str(), script->GetScriptCode().c_str());
switch (result)
{
case WREN_RESULT_COMPILE_ERROR: Logger::Trace(mLogCat, "Script compile error in module: %s", script->GetModuleName().c_str()); break;
case WREN_RESULT_RUNTIME_ERROR: Logger::Trace(mLogCat, "Script runtime error in module: %s", script->GetModuleName().c_str()); break;
case WREN_RESULT_SUCCESS: Logger::Trace(mLogCat, "Script %s run successfully", script->GetModuleName().c_str()); break;
}
}
void WrenState::RunSnippet(std::string name, std::string code)
{
if (!mpVM)
{
Logger::Error(mLogCat, "Could not run script - the VM is nullptr");
return;
}
WrenInterpretResult result = wrenInterpret(mpVM, name.c_str(), code.c_str());
switch (result)
{
case WREN_RESULT_COMPILE_ERROR: Logger::Trace(mLogCat, "Snippet compile error in module: %s", name.c_str()); break;
case WREN_RESULT_RUNTIME_ERROR: Logger::Trace(mLogCat, "Snippet runtime error in module: %s", name.c_str()); break;
case WREN_RESULT_SUCCESS: Logger::Trace(mLogCat, "Snippet %s run successfully", name.c_str()); break;
}
}
/////////////////////////////////////////////////////////////////////
// VM CALLBACK METHODS
/////////////////////////////////////////////////////////////////////
void WrenState::WriteFN(WrenVM* vm, const char* text)
{
std::string final = String::TrimEnd(text, "\n");
if (final.size() < 1)
return;
Logger::Info(mLogCat, final.c_str());
}
void WrenState::ErrorFN(WrenVM* vm, WrenErrorType type, const char* module, int line, const char* message)
{
switch (type)
{
case WREN_ERROR_COMPILE:
Logger::Error(mLogCat, "Script compile error: [%s line %d] %s\n", module, line, message);
break;
case WREN_ERROR_STACK_TRACE:
Logger::Error(mLogCat, "[%s line %d] in %s\n", module, line, message);
break;
case WREN_ERROR_RUNTIME:
Logger::Error(mLogCat, "Script Runtime Error: %s\n", message);
break;
}
}
WrenForeignMethodFn WrenState::BindForeignMethodFN(WrenVM* vm, const char* module, const char* className, bool isStatic, const char* signature)
{
// Bind methods
// If method not recognized, call any registered FMBinder methods
for (auto iter = mFMBinders.begin(); iter != mFMBinders.end(); iter++)
{
auto FN = ((FMBinder)(*iter))(vm, module, className, isStatic, signature);
if (FN)
{
return FN;
}
}
Logger::Error(mLogCat, "Failed to bind foreign method: %s::%s", className, signature);
return nullptr;
}
}