mirror of https://github.com/mgba-emu/mgba.git
Scripting: Add root scope function for engines
This commit is contained in:
parent
68845e080a
commit
95336463bf
|
@ -55,6 +55,7 @@ struct mScriptEngineContext {
|
||||||
|
|
||||||
bool (*setGlobal)(struct mScriptEngineContext*, const char* name, struct mScriptValue*);
|
bool (*setGlobal)(struct mScriptEngineContext*, const char* name, struct mScriptValue*);
|
||||||
struct mScriptValue* (*getGlobal)(struct mScriptEngineContext*, const char* name);
|
struct mScriptValue* (*getGlobal)(struct mScriptEngineContext*, const char* name);
|
||||||
|
struct mScriptValue* (*rootScope)(struct mScriptEngineContext*);
|
||||||
|
|
||||||
bool (*load)(struct mScriptEngineContext*, const char* filename, struct VFile*);
|
bool (*load)(struct mScriptEngineContext*, const char* filename, struct VFile*);
|
||||||
bool (*run)(struct mScriptEngineContext*);
|
bool (*run)(struct mScriptEngineContext*);
|
||||||
|
|
|
@ -25,6 +25,7 @@ static void _luaDestroy(struct mScriptEngineContext*);
|
||||||
static bool _luaIsScript(struct mScriptEngineContext*, const char*, struct VFile*);
|
static bool _luaIsScript(struct mScriptEngineContext*, const char*, struct VFile*);
|
||||||
static struct mScriptValue* _luaGetGlobal(struct mScriptEngineContext*, const char* name);
|
static struct mScriptValue* _luaGetGlobal(struct mScriptEngineContext*, const char* name);
|
||||||
static bool _luaSetGlobal(struct mScriptEngineContext*, const char* name, struct mScriptValue*);
|
static bool _luaSetGlobal(struct mScriptEngineContext*, const char* name, struct mScriptValue*);
|
||||||
|
static struct mScriptValue* _luaRootScope(struct mScriptEngineContext*);
|
||||||
static bool _luaLoad(struct mScriptEngineContext*, const char*, struct VFile*);
|
static bool _luaLoad(struct mScriptEngineContext*, const char*, struct VFile*);
|
||||||
static bool _luaRun(struct mScriptEngineContext*);
|
static bool _luaRun(struct mScriptEngineContext*);
|
||||||
static const char* _luaGetError(struct mScriptEngineContext*);
|
static const char* _luaGetError(struct mScriptEngineContext*);
|
||||||
|
@ -214,6 +215,7 @@ static const int _mScriptSocketNumErrors = sizeof(_mScriptSocketErrors) / sizeof
|
||||||
|
|
||||||
#if LUA_VERSION_NUM < 502
|
#if LUA_VERSION_NUM < 502
|
||||||
#define luaL_traceback(L, M, S, level) lua_pushstring(L, S)
|
#define luaL_traceback(L, M, S, level) lua_pushstring(L, S)
|
||||||
|
#define lua_pushglobaltable(L) lua_pushvalue(L, LUA_GLOBALSINDEX)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const struct mScriptType mSTLuaFunc = {
|
const struct mScriptType mSTLuaFunc = {
|
||||||
|
@ -294,6 +296,7 @@ struct mScriptEngineContext* _luaCreate(struct mScriptEngine2* engine, struct mS
|
||||||
.isScript = _luaIsScript,
|
.isScript = _luaIsScript,
|
||||||
.getGlobal = _luaGetGlobal,
|
.getGlobal = _luaGetGlobal,
|
||||||
.setGlobal = _luaSetGlobal,
|
.setGlobal = _luaSetGlobal,
|
||||||
|
.rootScope = _luaRootScope,
|
||||||
.load = _luaLoad,
|
.load = _luaLoad,
|
||||||
.run = _luaRun,
|
.run = _luaRun,
|
||||||
.getError = _luaGetError
|
.getError = _luaGetError
|
||||||
|
@ -395,6 +398,24 @@ bool _luaSetGlobal(struct mScriptEngineContext* ctx, const char* name, struct mS
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct mScriptValue* _luaRootScope(struct mScriptEngineContext* ctx) {
|
||||||
|
struct mScriptEngineContextLua* luaContext = (struct mScriptEngineContextLua*) ctx;
|
||||||
|
|
||||||
|
struct mScriptValue* list = mScriptValueAlloc(mSCRIPT_TYPE_MS_LIST);
|
||||||
|
lua_pushglobaltable(luaContext->lua);
|
||||||
|
lua_pushnil(luaContext->lua);
|
||||||
|
while (lua_next(luaContext->lua, -2) != 0) {
|
||||||
|
struct mScriptValue* key;
|
||||||
|
|
||||||
|
lua_pop(luaContext->lua, 1);
|
||||||
|
key = _luaCoerce(luaContext, false);
|
||||||
|
mScriptValueWrap(key, mScriptListAppend(list->value.list));
|
||||||
|
}
|
||||||
|
lua_pop(luaContext->lua, 1);
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
struct mScriptValue* _luaCoerceFunction(struct mScriptEngineContextLua* luaContext) {
|
struct mScriptValue* _luaCoerceFunction(struct mScriptEngineContextLua* luaContext) {
|
||||||
struct mScriptValue* value = mScriptValueAlloc(&mSTLuaFunc);
|
struct mScriptValue* value = mScriptValueAlloc(&mSTLuaFunc);
|
||||||
struct mScriptFunction* fn = calloc(1, sizeof(*fn));
|
struct mScriptFunction* fn = calloc(1, sizeof(*fn));
|
||||||
|
|
|
@ -259,6 +259,63 @@ M_TEST_DEFINE(setGlobal) {
|
||||||
mScriptContextDeinit(&context);
|
mScriptContextDeinit(&context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
M_TEST_DEFINE(rootScope) {
|
||||||
|
SETUP_LUA;
|
||||||
|
|
||||||
|
struct mScriptValue* baseline = mScriptValueAlloc(mSCRIPT_TYPE_MS_TABLE);
|
||||||
|
|
||||||
|
struct mScriptValue* val;
|
||||||
|
val = lua->rootScope(lua);
|
||||||
|
assert_non_null(val);
|
||||||
|
assert_int_equal(val->type->base, mSCRIPT_TYPE_LIST);
|
||||||
|
|
||||||
|
struct mScriptValue one = mSCRIPT_MAKE_S32(1);
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < mScriptListSize(val->value.list); ++i) {
|
||||||
|
struct mScriptValue* key = mScriptListGetPointer(val->value.list, i);
|
||||||
|
if (key->type->base == mSCRIPT_TYPE_WRAPPER) {
|
||||||
|
key = mScriptValueUnwrap(key);
|
||||||
|
}
|
||||||
|
mScriptTableInsert(baseline, key, &one);
|
||||||
|
}
|
||||||
|
mScriptValueDeref(val);
|
||||||
|
|
||||||
|
TEST_PROGRAM("foo = 1; bar = 2;");
|
||||||
|
|
||||||
|
bool fooFound = false;
|
||||||
|
bool barFound = false;
|
||||||
|
|
||||||
|
val = lua->rootScope(lua);
|
||||||
|
assert_non_null(val);
|
||||||
|
assert_int_equal(val->type->base, mSCRIPT_TYPE_LIST);
|
||||||
|
assert_int_equal(mScriptListSize(val->value.list), mScriptTableSize(baseline) + 2);
|
||||||
|
|
||||||
|
for (i = 0; i < mScriptListSize(val->value.list); ++i) {
|
||||||
|
struct mScriptValue* key = mScriptListGetPointer(val->value.list, i);
|
||||||
|
if (key->type->base == mSCRIPT_TYPE_WRAPPER) {
|
||||||
|
key = mScriptValueUnwrap(key);
|
||||||
|
}
|
||||||
|
if (mScriptTableLookup(baseline, key)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
assert_int_equal(key->type->base, mSCRIPT_TYPE_STRING);
|
||||||
|
|
||||||
|
if (strncmp(key->value.string->buffer, "foo", key->value.string->size) == 0) {
|
||||||
|
fooFound = true;
|
||||||
|
}
|
||||||
|
if (strncmp(key->value.string->buffer, "bar", key->value.string->size) == 0) {
|
||||||
|
barFound = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mScriptValueDeref(val);
|
||||||
|
|
||||||
|
assert_true(fooFound);
|
||||||
|
assert_true(barFound);
|
||||||
|
|
||||||
|
mScriptValueDeref(baseline);
|
||||||
|
mScriptContextDeinit(&context);
|
||||||
|
}
|
||||||
|
|
||||||
M_TEST_DEFINE(callLuaFunc) {
|
M_TEST_DEFINE(callLuaFunc) {
|
||||||
SETUP_LUA;
|
SETUP_LUA;
|
||||||
|
|
||||||
|
@ -658,6 +715,7 @@ M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(mScriptLua,
|
||||||
cmocka_unit_test(runNop),
|
cmocka_unit_test(runNop),
|
||||||
cmocka_unit_test(getGlobal),
|
cmocka_unit_test(getGlobal),
|
||||||
cmocka_unit_test(setGlobal),
|
cmocka_unit_test(setGlobal),
|
||||||
|
cmocka_unit_test(rootScope),
|
||||||
cmocka_unit_test(callLuaFunc),
|
cmocka_unit_test(callLuaFunc),
|
||||||
cmocka_unit_test(callCFunc),
|
cmocka_unit_test(callCFunc),
|
||||||
cmocka_unit_test(globalStructFieldGet),
|
cmocka_unit_test(globalStructFieldGet),
|
||||||
|
|
Loading…
Reference in New Issue