|
|
|
|
/******************************************************************************
|
|
|
|
|
* 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;
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|