mirror of https://github.com/mgba-emu/mgba.git
Scripting: Add read-only struct members
This commit is contained in:
parent
1306cfe15e
commit
e80b533549
|
@ -212,20 +212,30 @@ CXX_GUARD_START
|
|||
} \
|
||||
},
|
||||
|
||||
#define mSCRIPT_DEFINE_STRUCT_MEMBER_NAMED(STRUCT, TYPE, EXPORTED_NAME, NAME) { \
|
||||
#define _mSCRIPT_DEFINE_STRUCT_MEMBER(STRUCT, TYPE, EXPORTED_NAME, NAME, RO) { \
|
||||
.type = mSCRIPT_CLASS_INIT_INSTANCE_MEMBER, \
|
||||
.info = { \
|
||||
.member = { \
|
||||
.name = #EXPORTED_NAME, \
|
||||
.type = mSCRIPT_TYPE_MS_ ## TYPE, \
|
||||
.offset = offsetof(struct STRUCT, NAME) \
|
||||
.offset = offsetof(struct STRUCT, NAME), \
|
||||
.readonly = RO \
|
||||
} \
|
||||
} \
|
||||
},
|
||||
|
||||
#define mSCRIPT_DEFINE_STRUCT_MEMBER_NAMED(STRUCT, TYPE, EXPORTED_NAME, NAME) \
|
||||
_mSCRIPT_DEFINE_STRUCT_MEMBER(STRUCT, TYPE, EXPORTED_NAME, NAME, false)
|
||||
|
||||
#define mSCRIPT_DEFINE_STRUCT_CONST_MEMBER_NAMED(STRUCT, TYPE, EXPORTED_NAME, NAME) \
|
||||
_mSCRIPT_DEFINE_STRUCT_MEMBER(STRUCT, TYPE, EXPORTED_NAME, NAME, true)
|
||||
|
||||
#define mSCRIPT_DEFINE_STRUCT_MEMBER(STRUCT, TYPE, NAME) \
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER_NAMED(STRUCT, TYPE, NAME, NAME)
|
||||
|
||||
#define mSCRIPT_DEFINE_STRUCT_CONST_MEMBER(STRUCT, TYPE, NAME) \
|
||||
mSCRIPT_DEFINE_STRUCT_CONST_MEMBER_NAMED(STRUCT, TYPE, NAME, NAME)
|
||||
|
||||
#define mSCRIPT_DEFINE_INHERIT(PARENT) { \
|
||||
.type = mSCRIPT_CLASS_INIT_INHERIT, \
|
||||
.info = { \
|
||||
|
|
|
@ -231,6 +231,7 @@ struct mScriptClassMember {
|
|||
const char* docstring;
|
||||
const struct mScriptType* type;
|
||||
size_t offset;
|
||||
bool readonly;
|
||||
};
|
||||
|
||||
struct mScriptClassCastMember {
|
||||
|
|
|
@ -188,6 +188,9 @@ void explainClass(struct mScriptTypeClass* cls, int level) {
|
|||
}
|
||||
docstring = NULL;
|
||||
}
|
||||
if (details->info.member.readonly) {
|
||||
fprintf(out, "%s readonly: true\n", indent);
|
||||
}
|
||||
fprintf(out, "%s type: %s\n", indent, details->info.member.type->name);
|
||||
break;
|
||||
case mSCRIPT_CLASS_INIT_END:
|
||||
|
|
|
@ -54,6 +54,11 @@ struct TestG {
|
|||
const char* c;
|
||||
};
|
||||
|
||||
struct TestH {
|
||||
int32_t i;
|
||||
int32_t j;
|
||||
};
|
||||
|
||||
static int32_t testAi0(struct TestA* a) {
|
||||
return a->i;
|
||||
}
|
||||
|
@ -198,6 +203,12 @@ mSCRIPT_DEFINE_STRUCT(TestG)
|
|||
mSCRIPT_DEFINE_STRUCT_DEFAULT_SET(TestG, setC)
|
||||
mSCRIPT_DEFINE_END;
|
||||
|
||||
|
||||
mSCRIPT_DEFINE_STRUCT(TestH)
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(TestH, S32, i)
|
||||
mSCRIPT_DEFINE_STRUCT_CONST_MEMBER(TestH, S32, j)
|
||||
mSCRIPT_DEFINE_END;
|
||||
|
||||
M_TEST_DEFINE(testALayout) {
|
||||
struct mScriptTypeClass* cls = mSCRIPT_TYPE_MS_S(TestA)->details.cls;
|
||||
assert_false(cls->init);
|
||||
|
@ -1134,6 +1145,47 @@ M_TEST_DEFINE(testGSet) {
|
|||
assert_false(cls->init);
|
||||
}
|
||||
|
||||
M_TEST_DEFINE(testHSet) {
|
||||
struct mScriptTypeClass* cls = mSCRIPT_TYPE_MS_S(TestH)->details.cls;
|
||||
|
||||
struct TestH s = {
|
||||
.i = 1,
|
||||
.j = 2,
|
||||
};
|
||||
|
||||
struct mScriptValue sval = mSCRIPT_MAKE_S(TestH, &s);
|
||||
struct mScriptValue val;
|
||||
struct mScriptValue compare;
|
||||
|
||||
compare = mSCRIPT_MAKE_S32(1);
|
||||
assert_true(mScriptObjectGet(&sval, "i", &val));
|
||||
assert_true(compare.type->equal(&compare, &val));
|
||||
|
||||
compare = mSCRIPT_MAKE_S32(2);
|
||||
assert_true(mScriptObjectGet(&sval, "j", &val));
|
||||
assert_true(compare.type->equal(&compare, &val));
|
||||
|
||||
val = mSCRIPT_MAKE_S32(3);
|
||||
assert_true(mScriptObjectSet(&sval, "i", &val));
|
||||
assert_int_equal(s.i, 3);
|
||||
|
||||
val = mSCRIPT_MAKE_S32(4);
|
||||
assert_false(mScriptObjectSet(&sval, "j", &val));
|
||||
assert_int_equal(s.j, 2);
|
||||
|
||||
compare = mSCRIPT_MAKE_S32(3);
|
||||
assert_true(mScriptObjectGet(&sval, "i", &val));
|
||||
assert_true(compare.type->equal(&compare, &val));
|
||||
|
||||
compare = mSCRIPT_MAKE_S32(2);
|
||||
assert_true(mScriptObjectGet(&sval, "j", &val));
|
||||
assert_true(compare.type->equal(&compare, &val));
|
||||
|
||||
assert_true(cls->init);
|
||||
mScriptClassDeinit(cls);
|
||||
assert_false(cls->init);
|
||||
}
|
||||
|
||||
M_TEST_SUITE_DEFINE(mScriptClasses,
|
||||
cmocka_unit_test(testALayout),
|
||||
cmocka_unit_test(testASignatures),
|
||||
|
@ -1150,4 +1202,5 @@ M_TEST_SUITE_DEFINE(mScriptClasses,
|
|||
cmocka_unit_test(testEGet),
|
||||
cmocka_unit_test(testFDeinit),
|
||||
cmocka_unit_test(testGSet),
|
||||
cmocka_unit_test(testHSet),
|
||||
)
|
||||
|
|
|
@ -1472,6 +1472,10 @@ bool mScriptObjectSet(struct mScriptValue* obj, const char* member, struct mScri
|
|||
return true;
|
||||
}
|
||||
|
||||
if (m->readonly) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void* rawMember = (void *)((uintptr_t) obj->value.opaque + m->offset);
|
||||
if (m->type != val->type) {
|
||||
if (!mScriptCast(m->type, val, val)) {
|
||||
|
|
Loading…
Reference in New Issue