Scripting: Start bringing up constructors/destructors

This commit is contained in:
Vicki Pfau 2022-05-13 01:41:52 -07:00
parent bbf6d94fe2
commit 076299a5f6
3 changed files with 113 additions and 6 deletions

View File

@ -208,7 +208,7 @@ CXX_GUARD_START
.size = sizeof(struct STRUCT), \
.name = "struct::" #STRUCT, \
.alloc = NULL, \
.free = NULL, \
.free = mScriptObjectFree, \
.cast = mScriptObjectCast, \
.constType = &mSTStructConst_ ## STRUCT, \
}; \
@ -355,7 +355,6 @@ CXX_GUARD_START
return true; \
} \
#define mSCRIPT_DECLARE_STRUCT_D_METHOD(TYPE, RETURN, NAME, NPARAMS, ...) \
mSCRIPT_DECLARE_STRUCT_METHOD(TYPE, RETURN, NAME, p0->NAME, NPARAMS, __VA_ARGS__)
@ -368,8 +367,8 @@ CXX_GUARD_START
#define mSCRIPT_DECLARE_STRUCT_VOID_CD_METHOD(TYPE, NAME, NPARAMS, ...) \
mSCRIPT_DECLARE_STRUCT_VOID_C_METHOD(TYPE, NAME, p0->NAME, NPARAMS, __VA_ARGS__)
#define mSCRIPT_DEFINE_STRUCT_METHOD_NAMED(TYPE, EXPORTED_NAME, NAME) { \
.type = mSCRIPT_CLASS_INIT_INSTANCE_MEMBER, \
#define _mSCRIPT_DEFINE_STRUCT_BINDING(INIT_TYPE, TYPE, EXPORTED_NAME, NAME) { \
.type = mSCRIPT_CLASS_INIT_ ## INIT_TYPE, \
.info = { \
.member = { \
.name = #EXPORTED_NAME, \
@ -378,9 +377,15 @@ CXX_GUARD_START
}, \
},
#define mSCRIPT_DEFINE_STRUCT_METHOD_NAMED(TYPE, EXPORTED_NAME, NAME) \
_mSCRIPT_DEFINE_STRUCT_BINDING(INSTANCE_MEMBER, TYPE, EXPORTED_NAME, NAME)
#define mSCRIPT_DEFINE_STRUCT_METHOD(TYPE, NAME) mSCRIPT_DEFINE_STRUCT_METHOD_NAMED(TYPE, NAME, NAME)
#define mSCRIPT_DEFINE_STRUCT_DEFAULT_GET(TYPE) mSCRIPT_DEFINE_STRUCT_METHOD_NAMED(TYPE, _get, _get)
#define mSCRIPT_DEFINE_STRUCT_INIT(TYPE) _mSCRIPT_DEFINE_STRUCT_BINDING(INIT, TYPE, _init, _init)
#define mSCRIPT_DEFINE_STRUCT_DEINIT(TYPE) _mSCRIPT_DEFINE_STRUCT_BINDING(DEINIT, TYPE, _deinit, _deinit)
#define mSCRIPT_DEFINE_STRUCT_DEFAULT_GET(TYPE) _mSCRIPT_DEFINE_STRUCT_BINDING(GET, TYPE, _get, _get)
#define mSCRIPT_DEFINE_STRUCT_DEFAULT_SET(TYPE) _mSCRIPT_DEFINE_STRUCT_BINDING(SET, TYPE, _set, _set)
#define mSCRIPT_DEFINE_STRUCT_CAST_TO_MEMBER(TYPE, CAST_TYPE, MEMBER) { \
.type = mSCRIPT_CLASS_INIT_CAST_TO_MEMBER, \
@ -495,6 +500,10 @@ enum mScriptClassInitType {
mSCRIPT_CLASS_INIT_INSTANCE_MEMBER,
mSCRIPT_CLASS_INIT_INHERIT,
mSCRIPT_CLASS_INIT_CAST_TO_MEMBER,
mSCRIPT_CLASS_INIT_INIT,
mSCRIPT_CLASS_INIT_DEINIT,
mSCRIPT_CLASS_INIT_GET,
mSCRIPT_CLASS_INIT_SET,
};
enum {
@ -560,6 +569,10 @@ struct mScriptTypeClass {
const struct mScriptType* parent;
struct Table instanceMembers;
struct Table castToMembers;
struct mScriptClassMember* alloc; // TODO
struct mScriptClassMember* free;
struct mScriptClassMember* get;
struct mScriptClassMember* set; // TODO
};
struct mScriptValue;
@ -643,6 +656,7 @@ bool mScriptObjectGet(struct mScriptValue* obj, const char* member, struct mScri
bool mScriptObjectGetConst(const struct mScriptValue* obj, const char* member, struct mScriptValue*);
bool mScriptObjectSet(struct mScriptValue* obj, const char* member, struct mScriptValue*);
bool mScriptObjectCast(const struct mScriptValue* input, const struct mScriptType* type, struct mScriptValue* output) ;
void mScriptObjectFree(struct mScriptValue* obj);
bool mScriptPopS32(struct mScriptList* list, int32_t* out);
bool mScriptPopU32(struct mScriptList* list, uint32_t* out);

View File

@ -38,6 +38,10 @@ struct TestD {
struct TestE {
};
struct TestF {
int* ref;
};
static int32_t testAi0(struct TestA* a) {
return a->i;
}
@ -67,6 +71,10 @@ static int32_t testGet(struct TestE* e, const char* name) {
return name[0];
}
static void testDeinit(struct TestF* f) {
++*f->ref;
}
#define MEMBER_A_DOCSTRING "Member a"
mSCRIPT_DECLARE_STRUCT(TestA);
@ -124,6 +132,13 @@ mSCRIPT_DEFINE_STRUCT(TestE)
mSCRIPT_DEFINE_STRUCT_DEFAULT_GET(TestE)
mSCRIPT_DEFINE_END;
mSCRIPT_DECLARE_STRUCT(TestF);
mSCRIPT_DECLARE_STRUCT_VOID_METHOD(TestF, _deinit, testDeinit, 0);
mSCRIPT_DEFINE_STRUCT(TestF)
mSCRIPT_DEFINE_STRUCT_DEINIT(TestF)
mSCRIPT_DEFINE_END;
M_TEST_DEFINE(testALayout) {
struct mScriptTypeClass* cls = mSCRIPT_TYPE_MS_S(TestA)->details.cls;
assert_false(cls->init);
@ -910,6 +925,23 @@ M_TEST_DEFINE(testEGet) {
assert_false(cls->init);
}
M_TEST_DEFINE(testFDeinit) {
struct mScriptTypeClass* cls = mSCRIPT_TYPE_MS_S(TestF)->details.cls;
int ref = 0;
struct TestF* s = calloc(1, sizeof(struct TestF));
s->ref = &ref;
struct mScriptValue* val = mScriptValueAlloc(mSCRIPT_TYPE_MS_S(TestF));
val->value.opaque = s;
val->flags = mSCRIPT_VALUE_FLAG_FREE_BUFFER;
mScriptValueDeref(val);
assert_int_equal(ref, 1);
assert_true(cls->init);
mScriptClassDeinit(cls);
assert_false(cls->init);
}
M_TEST_SUITE_DEFINE(mScriptClasses,
cmocka_unit_test(testALayout),
cmocka_unit_test(testASignatures),
@ -924,4 +956,5 @@ M_TEST_SUITE_DEFINE(mScriptClasses,
cmocka_unit_test(testDGet),
cmocka_unit_test(testDSet),
cmocka_unit_test(testEGet),
cmocka_unit_test(testFDeinit),
)

View File

@ -806,6 +806,38 @@ static void _mScriptClassInit(struct mScriptTypeClass* cls, const struct mScript
case mSCRIPT_CLASS_INIT_CAST_TO_MEMBER:
HashTableInsert(&cls->castToMembers, detail->info.castMember.type->name, (char*) detail->info.castMember.member);
break;
case mSCRIPT_CLASS_INIT_INIT:
cls->alloc = calloc(1, sizeof(*member));
memcpy(cls->alloc, &detail->info.member, sizeof(*member));
if (docstring) {
cls->alloc->docstring = docstring;
docstring = NULL;
}
break;
case mSCRIPT_CLASS_INIT_DEINIT:
cls->free = calloc(1, sizeof(*member));
memcpy(cls->free, &detail->info.member, sizeof(*member));
if (docstring) {
cls->free->docstring = docstring;
docstring = NULL;
}
break;
case mSCRIPT_CLASS_INIT_GET:
cls->get = calloc(1, sizeof(*member));
memcpy(cls->get, &detail->info.member, sizeof(*member));
if (docstring) {
cls->get->docstring = docstring;
docstring = NULL;
}
break;
case mSCRIPT_CLASS_INIT_SET:
cls->set = calloc(1, sizeof(*member));
memcpy(cls->set, &detail->info.member, sizeof(*member));
if (docstring) {
cls->set->docstring = docstring;
docstring = NULL;
}
break;
}
}
}
@ -817,6 +849,10 @@ void mScriptClassInit(struct mScriptTypeClass* cls) {
HashTableInit(&cls->instanceMembers, 0, free);
HashTableInit(&cls->castToMembers, 0, NULL);
cls->alloc = NULL;
cls->free = NULL;
cls->get = NULL;
cls->set = NULL;
_mScriptClassInit(cls, cls->details, false);
cls->init = true;
@ -934,7 +970,7 @@ bool mScriptObjectGet(struct mScriptValue* obj, const char* member, struct mScri
struct mScriptClassMember* m = HashTableLookup(&cls->instanceMembers, member);
if (!m) {
struct mScriptValue getMember;
m = HashTableLookup(&cls->instanceMembers, "_get");
m = cls->get;
if (!m || !_accessRawMember(m, obj->value.opaque, obj->type->isConst, &getMember)) {
return false;
}
@ -1084,6 +1120,30 @@ bool mScriptObjectCast(const struct mScriptValue* input, const struct mScriptTyp
return false;
}
void mScriptObjectFree(struct mScriptValue* value) {
if (value->type->base != mSCRIPT_TYPE_OBJECT) {
return;
}
if (value->flags & mSCRIPT_VALUE_FLAG_FREE_BUFFER) {
mScriptClassInit(value->type->details.cls);
if (value->type->details.cls->free) {
struct mScriptValue deinitMember;
if (_accessRawMember(value->type->details.cls->free, value->value.opaque, value->type->isConst, &deinitMember)) {
struct mScriptFrame frame;
mScriptFrameInit(&frame);
struct mScriptValue* this = mScriptListAppend(&frame.arguments);
this->type = mSCRIPT_TYPE_MS_WRAPPER;
this->refs = mSCRIPT_VALUE_UNREF;
this->flags = 0;
this->value.opaque = value;
mScriptInvoke(&deinitMember, &frame);
mScriptFrameDeinit(&frame);
}
}
free(value->value.opaque);
}
}
bool mScriptPopS32(struct mScriptList* list, int32_t* out) {
mSCRIPT_POP(list, S32, val);
*out = val;