mirror of https://github.com/mgba-emu/mgba.git
Scripting: Allow basic pointer following
This commit is contained in:
parent
6d8060034f
commit
fc2b94f9f7
|
@ -304,6 +304,8 @@ void mScriptValueWrap(struct mScriptValue* val, struct mScriptValue* out);
|
||||||
struct mScriptValue* mScriptValueUnwrap(struct mScriptValue* val);
|
struct mScriptValue* mScriptValueUnwrap(struct mScriptValue* val);
|
||||||
const struct mScriptValue* mScriptValueUnwrapConst(const struct mScriptValue* val);
|
const struct mScriptValue* mScriptValueUnwrapConst(const struct mScriptValue* val);
|
||||||
|
|
||||||
|
void mScriptValueFollowPointer(struct mScriptValue* ptr, struct mScriptValue* out);
|
||||||
|
|
||||||
struct mScriptValue* mScriptStringCreateEmpty(size_t size);
|
struct mScriptValue* mScriptStringCreateEmpty(size_t size);
|
||||||
struct mScriptValue* mScriptStringCreateFromBytes(const void* string, size_t size);
|
struct mScriptValue* mScriptStringCreateFromBytes(const void* string, size_t size);
|
||||||
struct mScriptValue* mScriptStringCreateFromUTF8(const char* string);
|
struct mScriptValue* mScriptStringCreateFromUTF8(const char* string);
|
||||||
|
|
|
@ -693,6 +693,31 @@ bool _luaWrap(struct mScriptEngineContextLua* luaContext, struct mScriptValue* v
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
struct mScriptValue derefPtr;
|
||||||
|
if (value->type->base == mSCRIPT_TYPE_OPAQUE) {
|
||||||
|
if (!value->type->details.type) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
mScriptValueFollowPointer(value, &derefPtr);
|
||||||
|
switch (derefPtr.type->base) {
|
||||||
|
case mSCRIPT_TYPE_VOID:
|
||||||
|
case mSCRIPT_TYPE_SINT:
|
||||||
|
case mSCRIPT_TYPE_UINT:
|
||||||
|
case mSCRIPT_TYPE_FLOAT:
|
||||||
|
value = &derefPtr;
|
||||||
|
break;
|
||||||
|
case mSCRIPT_TYPE_OBJECT:
|
||||||
|
value = mScriptValueAlloc(derefPtr.type);
|
||||||
|
value->value.opaque = derefPtr.value.opaque;
|
||||||
|
weakref = mScriptContextSetWeakref(luaContext->d.context, value);
|
||||||
|
needsWeakref = true;
|
||||||
|
mScriptContextDisownWeakref(luaContext->d.context, weakref);
|
||||||
|
mScriptValueDeref(value);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (value->type == mSCRIPT_TYPE_MS_WEAKREF) {
|
if (value->type == mSCRIPT_TYPE_MS_WEAKREF) {
|
||||||
weakref = value->value.u32;
|
weakref = value->value.u32;
|
||||||
value = mScriptContextAccessWeakref(luaContext->d.context, value);
|
value = mScriptContextAccessWeakref(luaContext->d.context, value);
|
||||||
|
|
|
@ -22,6 +22,7 @@ struct Test {
|
||||||
void (*vfn0)(struct Test*);
|
void (*vfn0)(struct Test*);
|
||||||
void (*vfn1)(struct Test*, int);
|
void (*vfn1)(struct Test*, int);
|
||||||
int32_t (*icfn0)(const struct Test*);
|
int32_t (*icfn0)(const struct Test*);
|
||||||
|
struct Test* next;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int identityInt(int in) {
|
static int identityInt(int in) {
|
||||||
|
@ -83,6 +84,7 @@ mSCRIPT_DECLARE_STRUCT_VOID_METHOD(Test, v1, testV1, 1, S32, b);
|
||||||
|
|
||||||
mSCRIPT_DEFINE_STRUCT(Test)
|
mSCRIPT_DEFINE_STRUCT(Test)
|
||||||
mSCRIPT_DEFINE_STRUCT_MEMBER(Test, S32, i)
|
mSCRIPT_DEFINE_STRUCT_MEMBER(Test, S32, i)
|
||||||
|
mSCRIPT_DEFINE_STRUCT_MEMBER(Test, PS(Test), next)
|
||||||
mSCRIPT_DEFINE_STRUCT_METHOD(Test, ifn0)
|
mSCRIPT_DEFINE_STRUCT_METHOD(Test, ifn0)
|
||||||
mSCRIPT_DEFINE_STRUCT_METHOD(Test, ifn1)
|
mSCRIPT_DEFINE_STRUCT_METHOD(Test, ifn1)
|
||||||
mSCRIPT_DEFINE_STRUCT_METHOD(Test, icfn0)
|
mSCRIPT_DEFINE_STRUCT_METHOD(Test, icfn0)
|
||||||
|
@ -726,6 +728,42 @@ M_TEST_DEFINE(callList) {
|
||||||
mScriptContextDeinit(&context);
|
mScriptContextDeinit(&context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
M_TEST_DEFINE(linkedList) {
|
||||||
|
SETUP_LUA;
|
||||||
|
|
||||||
|
struct Test first = {
|
||||||
|
.i = 1
|
||||||
|
};
|
||||||
|
struct Test second = {
|
||||||
|
.i = 2
|
||||||
|
};
|
||||||
|
struct mScriptValue a = mSCRIPT_MAKE_S(Test, &first);
|
||||||
|
|
||||||
|
assert_true(lua->setGlobal(lua, "l", &a));
|
||||||
|
TEST_PROGRAM("assert(l)");
|
||||||
|
TEST_PROGRAM("assert(l.i == 1)");
|
||||||
|
TEST_PROGRAM("assert(not l.next)");
|
||||||
|
|
||||||
|
first.next = &second;
|
||||||
|
TEST_PROGRAM("assert(l)");
|
||||||
|
TEST_PROGRAM("assert(l.i == 1)");
|
||||||
|
TEST_PROGRAM("assert(l.next)");
|
||||||
|
TEST_PROGRAM("assert(l.next.i == 2)");
|
||||||
|
TEST_PROGRAM("assert(not l.next.next)");
|
||||||
|
|
||||||
|
TEST_PROGRAM(
|
||||||
|
"n = l.next\n"
|
||||||
|
"function readN()\n"
|
||||||
|
" assert(n)\n"
|
||||||
|
" assert(n.i or not n.i)\n"
|
||||||
|
"end\n"
|
||||||
|
"assert(pcall(readN))\n");
|
||||||
|
// The weakref stored in `n` gets pruned between executions to avoid stale pointers
|
||||||
|
TEST_PROGRAM("assert(not pcall(readN))");
|
||||||
|
|
||||||
|
mScriptContextDeinit(&context);
|
||||||
|
}
|
||||||
|
|
||||||
M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(mScriptLua,
|
M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(mScriptLua,
|
||||||
cmocka_unit_test(create),
|
cmocka_unit_test(create),
|
||||||
cmocka_unit_test(loadGood),
|
cmocka_unit_test(loadGood),
|
||||||
|
@ -744,4 +782,5 @@ M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(mScriptLua,
|
||||||
cmocka_unit_test(tableLookup),
|
cmocka_unit_test(tableLookup),
|
||||||
cmocka_unit_test(tableIterate),
|
cmocka_unit_test(tableIterate),
|
||||||
cmocka_unit_test(callList),
|
cmocka_unit_test(callList),
|
||||||
|
cmocka_unit_test(linkedList)
|
||||||
)
|
)
|
||||||
|
|
|
@ -853,6 +853,21 @@ const struct mScriptValue* mScriptValueUnwrapConst(const struct mScriptValue* va
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mScriptValueFollowPointer(struct mScriptValue* ptr, struct mScriptValue* out) {
|
||||||
|
if (ptr->type->base != mSCRIPT_TYPE_OPAQUE || !ptr->type->details.type) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
out->value.opaque = *(void**) ptr->value.opaque;
|
||||||
|
if (out->value.opaque) {
|
||||||
|
out->type = ptr->type->details.type;
|
||||||
|
} else {
|
||||||
|
out->type = mSCRIPT_TYPE_MS_VOID;
|
||||||
|
}
|
||||||
|
out->refs = mSCRIPT_VALUE_UNREF;
|
||||||
|
out->flags = 0;
|
||||||
|
}
|
||||||
|
|
||||||
struct mScriptValue* mScriptStringCreateEmpty(size_t size) {
|
struct mScriptValue* mScriptStringCreateEmpty(size_t size) {
|
||||||
struct mScriptValue* val = mScriptValueAlloc(mSCRIPT_TYPE_MS_STR);
|
struct mScriptValue* val = mScriptValueAlloc(mSCRIPT_TYPE_MS_STR);
|
||||||
struct mScriptString* internal = val->value.opaque;
|
struct mScriptString* internal = val->value.opaque;
|
||||||
|
|
Loading…
Reference in New Issue