mirror of https://github.com/mgba-emu/mgba.git
Scripting: Add basic inheritance + struct struct member access + const casting
This commit is contained in:
parent
9ddada00f2
commit
7c9ea1ec9b
|
@ -202,6 +202,7 @@ CXX_GUARD_START
|
|||
.alloc = NULL, \
|
||||
.free = NULL, \
|
||||
.cast = _mSTStructCast_ ## STRUCT, \
|
||||
.constType = &mSTStructConst_ ## STRUCT, \
|
||||
}; \
|
||||
const struct mScriptType mSTStructConst_ ## STRUCT = { \
|
||||
.base = mSCRIPT_TYPE_OBJECT, \
|
||||
|
@ -255,6 +256,13 @@ CXX_GUARD_START
|
|||
}, \
|
||||
},
|
||||
|
||||
#define mSCRIPT_DEFINE_INHERIT(PARENT) { \
|
||||
.type = mSCRIPT_CLASS_INIT_INHERIT, \
|
||||
.info = { \
|
||||
.parent = mSCRIPT_TYPE_MS_S(PARENT) \
|
||||
} \
|
||||
},
|
||||
|
||||
#define _mSCRIPT_STRUCT_METHOD_POP(TYPE, S, NPARAMS, ...) \
|
||||
_mDEFER(_mDEFER(_mCAT(mSCRIPT_POP_, _mSUCC ## NPARAMS)) (&frame->arguments, _mCOMMA_ ## NPARAMS(S(TYPE), __VA_ARGS__))); \
|
||||
if (mScriptListSize(&frame->arguments)) { \
|
||||
|
@ -493,7 +501,7 @@ struct mScriptClassInitDetails {
|
|||
enum mScriptClassInitType type;
|
||||
union {
|
||||
const char* comment;
|
||||
const struct mScriptTypeClass* parent;
|
||||
const struct mScriptType* parent;
|
||||
struct mScriptClassMember member;
|
||||
} info;
|
||||
};
|
||||
|
@ -501,6 +509,7 @@ struct mScriptClassInitDetails {
|
|||
struct mScriptTypeClass {
|
||||
bool init;
|
||||
const struct mScriptClassInitDetails* details;
|
||||
const struct mScriptType* parent;
|
||||
struct Table staticMembers;
|
||||
struct Table instanceMembers;
|
||||
};
|
||||
|
@ -518,6 +527,7 @@ struct mScriptType {
|
|||
struct mScriptTypeClass* cls;
|
||||
void* opaque;
|
||||
} details;
|
||||
const struct mScriptType* constType;
|
||||
void (*alloc)(struct mScriptValue*);
|
||||
void (*free)(struct mScriptValue*);
|
||||
uint32_t (*hash)(const struct mScriptValue*);
|
||||
|
|
|
@ -21,6 +21,20 @@ struct TestA {
|
|||
int32_t (*icfn1)(const struct TestA*, int);
|
||||
};
|
||||
|
||||
struct TestB {
|
||||
struct TestA d;
|
||||
int32_t i3;
|
||||
};
|
||||
|
||||
struct TestC {
|
||||
int32_t i;
|
||||
};
|
||||
|
||||
struct TestD {
|
||||
struct TestC a;
|
||||
struct TestC b;
|
||||
};
|
||||
|
||||
static int32_t testAi0(struct TestA* a) {
|
||||
return a->i;
|
||||
}
|
||||
|
@ -87,7 +101,24 @@ mSCRIPT_DEFINE_STRUCT(TestA)
|
|||
mSCRIPT_DEFINE_STATIC_MEMBER(S16, s_hUnaligned)
|
||||
mSCRIPT_DEFINE_END;
|
||||
|
||||
mSCRIPT_DEFINE_STRUCT(TestB)
|
||||
mSCRIPT_DEFINE_INHERIT(TestA)
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(TestB, S32, i3)
|
||||
mSCRIPT_DEFINE_END;
|
||||
|
||||
mSCRIPT_DEFINE_STRUCT(TestC)
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(TestC, S32, i)
|
||||
mSCRIPT_DEFINE_END;
|
||||
|
||||
mSCRIPT_DEFINE_STRUCT(TestD)
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(TestD, S(TestC), a)
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(TestD, S(TestC), b)
|
||||
mSCRIPT_DEFINE_END;
|
||||
|
||||
mSCRIPT_EXPORT_STRUCT(TestA);
|
||||
mSCRIPT_EXPORT_STRUCT(TestB);
|
||||
mSCRIPT_EXPORT_STRUCT(TestC);
|
||||
mSCRIPT_EXPORT_STRUCT(TestD);
|
||||
|
||||
M_TEST_DEFINE(testALayout) {
|
||||
struct mScriptTypeClass* cls = mSCRIPT_TYPE_MS_S(TestA)->details.cls;
|
||||
|
@ -492,9 +523,331 @@ M_TEST_DEFINE(testADynamic) {
|
|||
assert_false(cls->init);
|
||||
}
|
||||
|
||||
M_TEST_DEFINE(testBLayout) {
|
||||
struct mScriptTypeClass* cls = mSCRIPT_TYPE_MS_S(TestB)->details.cls;
|
||||
assert_false(cls->init);
|
||||
mScriptClassInit(cls);
|
||||
assert_true(cls->init);
|
||||
|
||||
struct mScriptClassMember* member;
|
||||
|
||||
// Instance members
|
||||
member = HashTableLookup(&cls->instanceMembers, "i");
|
||||
assert_non_null(member);
|
||||
assert_string_equal(member->name, "i");
|
||||
assert_string_equal(member->docstring, MEMBER_A_DOCSTRING);
|
||||
assert_ptr_equal(member->type, mSCRIPT_TYPE_MS_S32);
|
||||
assert_int_equal(member->offset, 0);
|
||||
|
||||
member = HashTableLookup(&cls->instanceMembers, "i2");
|
||||
assert_non_null(member);
|
||||
assert_string_equal(member->name, "i2");
|
||||
assert_null(member->docstring);
|
||||
assert_ptr_equal(member->type, mSCRIPT_TYPE_MS_S32);
|
||||
assert_int_equal(member->offset, sizeof(int32_t));
|
||||
|
||||
member = HashTableLookup(&cls->instanceMembers, "b8");
|
||||
assert_non_null(member);
|
||||
assert_string_equal(member->name, "b8");
|
||||
assert_null(member->docstring);
|
||||
assert_ptr_equal(member->type, mSCRIPT_TYPE_MS_S8);
|
||||
assert_int_equal(member->offset, sizeof(int32_t) * 2);
|
||||
|
||||
member = HashTableLookup(&cls->instanceMembers, "hUnaligned");
|
||||
assert_non_null(member);
|
||||
assert_string_equal(member->name, "hUnaligned");
|
||||
assert_null(member->docstring);
|
||||
assert_ptr_equal(member->type, mSCRIPT_TYPE_MS_S16);
|
||||
assert_int_not_equal(member->offset, sizeof(int32_t) * 2 + 1);
|
||||
size_t hOffset = member->offset;
|
||||
|
||||
member = HashTableLookup(&cls->instanceMembers, "i3");
|
||||
assert_non_null(member);
|
||||
assert_string_equal(member->name, "i3");
|
||||
assert_null(member->docstring);
|
||||
assert_ptr_equal(member->type, mSCRIPT_TYPE_MS_S32);
|
||||
assert_true(member->offset >= hOffset + sizeof(int16_t));
|
||||
|
||||
member = HashTableLookup(&cls->instanceMembers, "_super");
|
||||
assert_non_null(member);
|
||||
assert_string_equal(member->name, "_super");
|
||||
assert_null(member->docstring);
|
||||
assert_ptr_equal(member->type, mSCRIPT_TYPE_MS_S(TestA));
|
||||
assert_int_equal(member->offset, 0);
|
||||
|
||||
member = HashTableLookup(&cls->instanceMembers, "unknown");
|
||||
assert_null(member);
|
||||
|
||||
mScriptClassDeinit(cls);
|
||||
assert_false(cls->init);
|
||||
}
|
||||
|
||||
M_TEST_DEFINE(testBGet) {
|
||||
struct mScriptTypeClass* cls = mSCRIPT_TYPE_MS_S(TestB)->details.cls;
|
||||
|
||||
struct TestB s = {
|
||||
.d = {
|
||||
.i = 1,
|
||||
.i2 = 2,
|
||||
.b8 = 3,
|
||||
.hUnaligned = 4
|
||||
},
|
||||
.i3 = 5
|
||||
};
|
||||
|
||||
struct mScriptValue sval = mSCRIPT_MAKE_S(TestB, &s);
|
||||
struct mScriptValue super;
|
||||
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, "i2", &val));
|
||||
assert_true(compare.type->equal(&compare, &val));
|
||||
|
||||
compare = mSCRIPT_MAKE_S32(3);
|
||||
assert_true(mScriptObjectGet(&sval, "b8", &val));
|
||||
assert_true(compare.type->equal(&compare, &val));
|
||||
|
||||
compare = mSCRIPT_MAKE_S32(4);
|
||||
assert_true(mScriptObjectGet(&sval, "hUnaligned", &val));
|
||||
assert_true(compare.type->equal(&compare, &val));
|
||||
|
||||
compare = mSCRIPT_MAKE_S32(5);
|
||||
assert_true(mScriptObjectGet(&sval, "i3", &val));
|
||||
assert_true(compare.type->equal(&compare, &val));
|
||||
|
||||
// Superclass explicit access
|
||||
assert_true(mScriptObjectGet(&sval, "_super", &super));
|
||||
assert_true(super.type == mSCRIPT_TYPE_MS_S(TestA));
|
||||
|
||||
compare = mSCRIPT_MAKE_S32(1);
|
||||
assert_true(mScriptObjectGet(&super, "i", &val));
|
||||
assert_true(compare.type->equal(&compare, &val));
|
||||
|
||||
compare = mSCRIPT_MAKE_S32(2);
|
||||
assert_true(mScriptObjectGet(&super, "i2", &val));
|
||||
assert_true(compare.type->equal(&compare, &val));
|
||||
|
||||
compare = mSCRIPT_MAKE_S32(3);
|
||||
assert_true(mScriptObjectGet(&super, "b8", &val));
|
||||
assert_true(compare.type->equal(&compare, &val));
|
||||
|
||||
compare = mSCRIPT_MAKE_S32(4);
|
||||
assert_true(mScriptObjectGet(&super, "hUnaligned", &val));
|
||||
assert_true(compare.type->equal(&compare, &val));
|
||||
|
||||
assert_false(mScriptObjectGet(&super, "i3", &val));
|
||||
|
||||
// Test const-correctness
|
||||
sval = mSCRIPT_MAKE_CS(TestB, &s);
|
||||
assert_true(mScriptObjectGet(&sval, "_super", &super));
|
||||
assert_true(super.type == mSCRIPT_TYPE_MS_CS(TestA));
|
||||
|
||||
assert_true(cls->init);
|
||||
mScriptClassDeinit(cls);
|
||||
assert_false(cls->init);
|
||||
}
|
||||
|
||||
M_TEST_DEFINE(testBSet) {
|
||||
struct mScriptTypeClass* cls = mSCRIPT_TYPE_MS_S(TestB)->details.cls;
|
||||
|
||||
struct TestB s = {
|
||||
.d = {
|
||||
.i = 1,
|
||||
.i2 = 2,
|
||||
.b8 = 3,
|
||||
.hUnaligned = 4
|
||||
},
|
||||
.i3 = 5
|
||||
};
|
||||
|
||||
struct mScriptValue sval = mSCRIPT_MAKE_S(TestB, &s);
|
||||
struct mScriptValue super;
|
||||
struct mScriptValue val;
|
||||
|
||||
val = mSCRIPT_MAKE_S32(2);
|
||||
assert_true(mScriptObjectSet(&sval, "i", &val));
|
||||
assert_int_equal(s.d.i, 2);
|
||||
|
||||
val = mSCRIPT_MAKE_S32(3);
|
||||
assert_true(mScriptObjectSet(&sval, "i2", &val));
|
||||
assert_int_equal(s.d.i2, 3);
|
||||
|
||||
val = mSCRIPT_MAKE_S32(4);
|
||||
assert_true(mScriptObjectSet(&sval, "b8", &val));
|
||||
assert_int_equal(s.d.b8, 4);
|
||||
|
||||
val = mSCRIPT_MAKE_S32(5);
|
||||
assert_true(mScriptObjectSet(&sval, "hUnaligned", &val));
|
||||
assert_int_equal(s.d.hUnaligned, 5);
|
||||
|
||||
val = mSCRIPT_MAKE_S32(6);
|
||||
assert_true(mScriptObjectSet(&sval, "i3", &val));
|
||||
assert_int_equal(s.i3, 6);
|
||||
|
||||
// Superclass explicit access
|
||||
assert_true(mScriptObjectGet(&sval, "_super", &super));
|
||||
assert_true(super.type == mSCRIPT_TYPE_MS_S(TestA));
|
||||
|
||||
val = mSCRIPT_MAKE_S32(3);
|
||||
assert_true(mScriptObjectSet(&super, "i", &val));
|
||||
assert_int_equal(s.d.i, 3);
|
||||
|
||||
val = mSCRIPT_MAKE_S32(4);
|
||||
assert_true(mScriptObjectSet(&super, "i2", &val));
|
||||
assert_int_equal(s.d.i2, 4);
|
||||
|
||||
val = mSCRIPT_MAKE_S32(5);
|
||||
assert_true(mScriptObjectSet(&super, "b8", &val));
|
||||
assert_int_equal(s.d.b8, 5);
|
||||
|
||||
val = mSCRIPT_MAKE_S32(6);
|
||||
assert_true(mScriptObjectSet(&super, "hUnaligned", &val));
|
||||
assert_int_equal(s.d.hUnaligned, 6);
|
||||
|
||||
val = mSCRIPT_MAKE_S32(7);
|
||||
assert_false(mScriptObjectSet(&super, "i3", &val));
|
||||
assert_int_equal(s.i3, 6);
|
||||
|
||||
// Const access
|
||||
sval = mSCRIPT_MAKE_CS(TestB, &s);
|
||||
|
||||
val = mSCRIPT_MAKE_S32(4);
|
||||
assert_false(mScriptObjectSet(&sval, "i", &val));
|
||||
assert_int_equal(s.d.i, 3);
|
||||
|
||||
val = mSCRIPT_MAKE_S32(5);
|
||||
assert_false(mScriptObjectSet(&sval, "i2", &val));
|
||||
assert_int_equal(s.d.i2, 4);
|
||||
|
||||
val = mSCRIPT_MAKE_S32(6);
|
||||
assert_false(mScriptObjectSet(&sval, "b8", &val));
|
||||
assert_int_equal(s.d.b8, 5);
|
||||
|
||||
val = mSCRIPT_MAKE_S32(7);
|
||||
assert_false(mScriptObjectSet(&sval, "hUnaligned", &val));
|
||||
assert_int_equal(s.d.hUnaligned, 6);
|
||||
|
||||
val = mSCRIPT_MAKE_S32(8);
|
||||
assert_false(mScriptObjectSet(&sval, "i3", &val));
|
||||
assert_int_equal(s.i3, 6);
|
||||
|
||||
assert_true(cls->init);
|
||||
mScriptClassDeinit(cls);
|
||||
assert_false(cls->init);
|
||||
}
|
||||
|
||||
M_TEST_DEFINE(testDLayout) {
|
||||
struct mScriptTypeClass* cls = mSCRIPT_TYPE_MS_S(TestD)->details.cls;
|
||||
assert_false(cls->init);
|
||||
mScriptClassInit(cls);
|
||||
assert_true(cls->init);
|
||||
|
||||
struct mScriptClassMember* member;
|
||||
|
||||
// Instance members
|
||||
member = HashTableLookup(&cls->instanceMembers, "a");
|
||||
assert_non_null(member);
|
||||
assert_string_equal(member->name, "a");
|
||||
assert_null(member->docstring);
|
||||
assert_ptr_equal(member->type, mSCRIPT_TYPE_MS_S(TestC));
|
||||
assert_int_equal(member->offset, 0);
|
||||
|
||||
member = HashTableLookup(&cls->instanceMembers, "b");
|
||||
assert_non_null(member);
|
||||
assert_string_equal(member->name, "b");
|
||||
assert_null(member->docstring);
|
||||
assert_ptr_equal(member->type, mSCRIPT_TYPE_MS_S(TestC));
|
||||
assert_int_equal(member->offset, sizeof(struct TestC));
|
||||
|
||||
mScriptClassDeinit(cls);
|
||||
assert_false(cls->init);
|
||||
}
|
||||
|
||||
M_TEST_DEFINE(testDGet) {
|
||||
struct mScriptTypeClass* cls = mSCRIPT_TYPE_MS_S(TestD)->details.cls;
|
||||
|
||||
struct TestD s = {
|
||||
.a = { 1 },
|
||||
.b = { 2 },
|
||||
};
|
||||
|
||||
struct mScriptValue sval = mSCRIPT_MAKE_S(TestD, &s);
|
||||
struct mScriptValue val;
|
||||
struct mScriptValue member;
|
||||
struct mScriptValue compare;
|
||||
|
||||
compare = mSCRIPT_MAKE_S32(1);
|
||||
assert_true(mScriptObjectGet(&sval, "a", &member));
|
||||
assert_true(mScriptObjectGet(&member, "i", &val));
|
||||
assert_true(compare.type->equal(&compare, &val));
|
||||
|
||||
compare = mSCRIPT_MAKE_S32(2);
|
||||
assert_true(mScriptObjectGet(&sval, "b", &member));
|
||||
assert_true(mScriptObjectGet(&member, "i", &val));
|
||||
assert_true(compare.type->equal(&compare, &val));
|
||||
|
||||
assert_true(cls->init);
|
||||
mScriptClassDeinit(cls);
|
||||
assert_false(cls->init);
|
||||
}
|
||||
|
||||
M_TEST_DEFINE(testDSet) {
|
||||
struct mScriptTypeClass* cls = mSCRIPT_TYPE_MS_S(TestD)->details.cls;
|
||||
|
||||
struct TestD s = {
|
||||
.a = { 1 },
|
||||
.b = { 2 },
|
||||
};
|
||||
|
||||
struct mScriptValue sval = mSCRIPT_MAKE_S(TestD, &s);
|
||||
struct mScriptValue member;
|
||||
struct mScriptValue val;
|
||||
|
||||
val = mSCRIPT_MAKE_S32(2);
|
||||
assert_true(mScriptObjectGet(&sval, "a", &member));
|
||||
assert_true(mScriptObjectSet(&member, "i", &val));
|
||||
assert_int_equal(s.a.i, 2);
|
||||
assert_int_equal(s.b.i, 2);
|
||||
|
||||
val = mSCRIPT_MAKE_S32(3);
|
||||
assert_true(mScriptObjectGet(&sval, "b", &member));
|
||||
assert_true(mScriptObjectSet(&member, "i", &val));
|
||||
assert_int_equal(s.a.i, 2);
|
||||
assert_int_equal(s.b.i, 3);
|
||||
|
||||
sval = mSCRIPT_MAKE_CS(TestD, &s);
|
||||
|
||||
val = mSCRIPT_MAKE_S32(4);
|
||||
assert_true(mScriptObjectGet(&sval, "a", &member));
|
||||
assert_false(mScriptObjectSet(&member, "i", &val));
|
||||
assert_int_equal(s.a.i, 2);
|
||||
assert_int_equal(s.b.i, 3);
|
||||
|
||||
val = mSCRIPT_MAKE_S32(5);
|
||||
assert_true(mScriptObjectGet(&sval, "b", &member));
|
||||
assert_false(mScriptObjectSet(&member, "i", &val));
|
||||
assert_int_equal(s.a.i, 2);
|
||||
assert_int_equal(s.b.i, 3);
|
||||
|
||||
assert_true(cls->init);
|
||||
mScriptClassDeinit(cls);
|
||||
assert_false(cls->init);
|
||||
}
|
||||
|
||||
M_TEST_SUITE_DEFINE(mScriptClasses,
|
||||
cmocka_unit_test(testALayout),
|
||||
cmocka_unit_test(testAGet),
|
||||
cmocka_unit_test(testASet),
|
||||
cmocka_unit_test(testAStatic),
|
||||
cmocka_unit_test(testADynamic))
|
||||
cmocka_unit_test(testADynamic),
|
||||
cmocka_unit_test(testBLayout),
|
||||
cmocka_unit_test(testBGet),
|
||||
cmocka_unit_test(testBSet),
|
||||
cmocka_unit_test(testDLayout),
|
||||
cmocka_unit_test(testDGet),
|
||||
cmocka_unit_test(testDSet))
|
||||
|
|
|
@ -741,33 +741,34 @@ void mScriptFrameDeinit(struct mScriptFrame* frame) {
|
|||
mScriptListDeinit(&frame->arguments);
|
||||
}
|
||||
|
||||
void mScriptClassInit(struct mScriptTypeClass* cls) {
|
||||
if (cls->init) {
|
||||
return;
|
||||
}
|
||||
HashTableInit(&cls->staticMembers, 0, free);
|
||||
HashTableInit(&cls->instanceMembers, 0, free);
|
||||
size_t staticOffset = 0;
|
||||
static void _mScriptClassInit(struct mScriptTypeClass* cls, const struct mScriptClassInitDetails* details, bool child) {
|
||||
const char* docstring = NULL;
|
||||
size_t staticOffset = 0;
|
||||
|
||||
size_t i;
|
||||
for (i = 0; cls->details[i].type != mSCRIPT_CLASS_INIT_END; ++i) {
|
||||
const struct mScriptClassInitDetails* details = &cls->details[i];
|
||||
for (i = 0; details[i].type != mSCRIPT_CLASS_INIT_END; ++i) {
|
||||
const struct mScriptClassInitDetails* detail = &details[i];
|
||||
struct mScriptClassMember* member;
|
||||
|
||||
switch (details->type) {
|
||||
switch (detail->type) {
|
||||
case mSCRIPT_CLASS_INIT_END:
|
||||
break;
|
||||
case mSCRIPT_CLASS_INIT_DOCSTRING:
|
||||
docstring = details->info.comment;
|
||||
docstring = detail->info.comment;
|
||||
break;
|
||||
case mSCRIPT_CLASS_INIT_INHERIT:
|
||||
// TODO
|
||||
abort();
|
||||
member = calloc(1, sizeof(*member));
|
||||
member->name = "_super";
|
||||
member->type = detail->info.parent;
|
||||
if (!child) {
|
||||
cls->parent = detail->info.parent;
|
||||
}
|
||||
HashTableInsert(&cls->instanceMembers, member->name, member);
|
||||
_mScriptClassInit(cls, detail->info.parent->details.cls->details, true);
|
||||
break;
|
||||
case mSCRIPT_CLASS_INIT_INSTANCE_MEMBER:
|
||||
member = calloc(1, sizeof(*member));
|
||||
memcpy(member, &details->info.member, sizeof(*member));
|
||||
memcpy(member, &detail->info.member, sizeof(*member));
|
||||
if (docstring) {
|
||||
member->docstring = docstring;
|
||||
docstring = NULL;
|
||||
|
@ -775,27 +776,40 @@ void mScriptClassInit(struct mScriptTypeClass* cls) {
|
|||
HashTableInsert(&cls->instanceMembers, member->name, member);
|
||||
break;
|
||||
case mSCRIPT_CLASS_INIT_STATIC_MEMBER:
|
||||
if (!child) {
|
||||
member = calloc(1, sizeof(*member));
|
||||
memcpy(member, &details->info.member, sizeof(*member));
|
||||
memcpy(member, &detail->info.member, sizeof(*member));
|
||||
if (docstring) {
|
||||
member->docstring = docstring;
|
||||
docstring = NULL;
|
||||
}
|
||||
|
||||
// Alignment check
|
||||
if (staticOffset & (details->info.member.type->size - 1)) {
|
||||
size_t size = details->info.member.type->size;
|
||||
if (staticOffset & (detail->info.member.type->size - 1)) {
|
||||
size_t size = detail->info.member.type->size;
|
||||
if (size > MAX_ALIGNMENT) {
|
||||
size = MAX_ALIGNMENT;
|
||||
}
|
||||
staticOffset = (staticOffset & ~(size - 1)) + size;
|
||||
}
|
||||
member->offset = staticOffset;
|
||||
staticOffset += details->info.member.type->size;
|
||||
staticOffset += detail->info.member.type->size;
|
||||
HashTableInsert(&cls->staticMembers, member->name, member);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mScriptClassInit(struct mScriptTypeClass* cls) {
|
||||
if (cls->init) {
|
||||
return;
|
||||
}
|
||||
HashTableInit(&cls->staticMembers, 0, free);
|
||||
HashTableInit(&cls->instanceMembers, 0, free);
|
||||
|
||||
_mScriptClassInit(cls, cls->details, false);
|
||||
|
||||
cls->init = true;
|
||||
}
|
||||
|
||||
|
@ -880,6 +894,15 @@ bool mScriptObjectGet(struct mScriptValue* obj, const char* member, struct mScri
|
|||
val->type = m->type;
|
||||
m->type->alloc(val);
|
||||
break;
|
||||
case mSCRIPT_TYPE_OBJECT:
|
||||
val->refs = mSCRIPT_VALUE_UNREF;
|
||||
val->value.opaque = rawMember;
|
||||
if (obj->type->isConst && !m->type->isConst) {
|
||||
val->type = m->type->constType;
|
||||
} else {
|
||||
val->type = m->type;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue