diff --git a/include/mgba/script/types.h b/include/mgba/script/types.h index 646ee7704..421a7bfb4 100644 --- a/include/mgba/script/types.h +++ b/include/mgba/script/types.h @@ -30,12 +30,15 @@ CXX_GUARD_START #define mSCRIPT_TYPE_C_STR struct mScriptString* #define mSCRIPT_TYPE_C_CHARP const char* #define mSCRIPT_TYPE_C_PTR void* +#define mSCRIPT_TYPE_C_CPTR const void* #define mSCRIPT_TYPE_C_TABLE Table* #define mSCRIPT_TYPE_C_WRAPPER struct mScriptValue* #define mSCRIPT_TYPE_C_WEAKREF uint32_t #define mSCRIPT_TYPE_C_S(STRUCT) struct STRUCT* #define mSCRIPT_TYPE_C_CS(STRUCT) const struct STRUCT* #define mSCRIPT_TYPE_C_S_METHOD(STRUCT, NAME) _mSTStructFunctionType_ ## STRUCT ## _ ## NAME +#define mSCRIPT_TYPE_C_PS(X) void +#define mSCRIPT_TYPE_C_PCS(X) void #define mSCRIPT_TYPE_FIELD_S8 s32 #define mSCRIPT_TYPE_FIELD_U8 s32 @@ -48,7 +51,7 @@ CXX_GUARD_START #define mSCRIPT_TYPE_FIELD_U64 u64 #define mSCRIPT_TYPE_FIELD_F64 f64 #define mSCRIPT_TYPE_FIELD_STR opaque -#define mSCRIPT_TYPE_FIELD_CHARP opaque +#define mSCRIPT_TYPE_FIELD_CHARP copaque #define mSCRIPT_TYPE_FIELD_PTR opaque #define mSCRIPT_TYPE_FIELD_TABLE opaque #define mSCRIPT_TYPE_FIELD_WRAPPER opaque @@ -56,6 +59,8 @@ CXX_GUARD_START #define mSCRIPT_TYPE_FIELD_S(STRUCT) opaque #define mSCRIPT_TYPE_FIELD_CS(STRUCT) copaque #define mSCRIPT_TYPE_FIELD_S_METHOD(STRUCT, NAME) copaque +#define mSCRIPT_TYPE_FIELD_PS(STRUCT) opaque +#define mSCRIPT_TYPE_FIELD_PCS(STRUCT) copaque #define mSCRIPT_TYPE_MS_S8 (&mSTSInt8) #define mSCRIPT_TYPE_MS_U8 (&mSTUInt8) @@ -75,6 +80,8 @@ CXX_GUARD_START #define mSCRIPT_TYPE_MS_S(STRUCT) (&mSTStruct_ ## STRUCT) #define mSCRIPT_TYPE_MS_CS(STRUCT) (&mSTStructConst_ ## STRUCT) #define mSCRIPT_TYPE_MS_S_METHOD(STRUCT, NAME) (&_mSTStructBindingType_ ## STRUCT ## _ ## NAME) +#define mSCRIPT_TYPE_MS_PS(STRUCT) (&mSTStructPtr_ ## STRUCT) +#define mSCRIPT_TYPE_MS_PCS(STRUCT) (&mSTStructConstPtr_ ## STRUCT) #define _mSCRIPT_FIELD_NAME(V) (V)->name @@ -167,18 +174,30 @@ CXX_GUARD_START #define mSCRIPT_DECLARE_STRUCT(STRUCT) \ extern const struct mScriptType mSTStruct_ ## STRUCT; \ - extern const struct mScriptType mSTStructConst_ ## STRUCT; + extern const struct mScriptType mSTStructConst_ ## STRUCT; \ + extern const struct mScriptType mSTStructPtr_ ## STRUCT; \ + extern const struct mScriptType mSTStructPtrConst_ ## STRUCT; #define mSCRIPT_DEFINE_STRUCT(STRUCT) \ const struct mScriptType mSTStruct_ ## STRUCT; \ const struct mScriptType mSTStructConst_ ## STRUCT; \ + const struct mScriptType mSTStructPtr_ ## STRUCT; \ + const struct mScriptType mSTStructPtrConst_ ## STRUCT; \ static struct mScriptTypeClass _mSTStructDetails_ ## STRUCT; \ - static bool _mSTStructCast_ ## STRUCT(const struct mScriptValue* input, const struct mScriptType* type, struct mScriptValue* output) { \ - if (input->type == type || (input->type == &mSTStruct_ ## STRUCT && type == &mSTStructConst_ ## STRUCT)) { \ + static bool _mSTStructPtrCast_ ## STRUCT(const struct mScriptValue* input, const struct mScriptType* type, struct mScriptValue* output) { \ + if (input->type == type || (input->type->constType == type)) { \ output->type = type; \ output->value.opaque = input->value.opaque; \ return true; \ } \ + if (input->type != &mSTStructPtr_ ## STRUCT && input->type != &mSTStructPtrConst_ ## STRUCT) { \ + return false; \ + } \ + if (type == &mSTStructConst_ ## STRUCT || (!input->type->isConst && type == &mSTStruct_ ## STRUCT)) { \ + output->type = type; \ + output->value.opaque = *(void**) input->value.opaque; \ + return true; \ + } \ return false; \ } \ const struct mScriptType mSTStruct_ ## STRUCT = { \ @@ -190,7 +209,7 @@ CXX_GUARD_START .name = "struct::" #STRUCT, \ .alloc = NULL, \ .free = NULL, \ - .cast = _mSTStructCast_ ## STRUCT, \ + .cast = mScriptObjectCast, \ .constType = &mSTStructConst_ ## STRUCT, \ }; \ const struct mScriptType mSTStructConst_ ## STRUCT = { \ @@ -203,7 +222,25 @@ CXX_GUARD_START .name = "const struct::" #STRUCT, \ .alloc = NULL, \ .free = NULL, \ - .cast = _mSTStructCast_ ## STRUCT, \ + .cast = mScriptObjectCast, \ + }; \ + const struct mScriptType mSTStructPtr_ ## STRUCT = { \ + .base = mSCRIPT_TYPE_OPAQUE, \ + .size = sizeof(void*), \ + .name = "ptr struct::" #STRUCT, \ + .alloc = NULL, \ + .free = NULL, \ + .cast = _mSTStructPtrCast_ ## STRUCT, \ + .constType = &mSTStructPtrConst_ ## STRUCT, \ + }; \ + const struct mScriptType mSTStructPtrConst_ ## STRUCT = { \ + .base = mSCRIPT_TYPE_OPAQUE, \ + .isConst = true, \ + .size = sizeof(void*), \ + .name = "ptr const struct::" #STRUCT, \ + .alloc = NULL, \ + .free = NULL, \ + .cast = _mSTStructPtrCast_ ## STRUCT, \ }; \ static struct mScriptTypeClass _mSTStructDetails_ ## STRUCT = { \ .init = false, \ @@ -580,7 +617,9 @@ void mScriptClassInit(struct mScriptTypeClass* cls); void mScriptClassDeinit(struct mScriptTypeClass* cls); bool mScriptObjectGet(struct mScriptValue* obj, const char* member, struct mScriptValue*); +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) ; bool mScriptPopS32(struct mScriptList* list, int32_t* out); bool mScriptPopU32(struct mScriptList* list, uint32_t* out); diff --git a/src/script/types.c b/src/script/types.c index cf57bda5e..4ff7038e8 100644 --- a/src/script/types.c +++ b/src/script/types.c @@ -816,6 +816,86 @@ void mScriptClassDeinit(struct mScriptTypeClass* cls) { cls->init = false; } + +static bool _accessRawMember(struct mScriptClassMember* member, void* raw, bool isConst, struct mScriptValue* val) { + raw = (void*) ((uintptr_t) raw + member->offset); + switch (member->type->base) { + case mSCRIPT_TYPE_SINT: + switch (member->type->size) { + case 1: + *val = mSCRIPT_MAKE_S32(*(int8_t *) raw); + break; + case 2: + *val = mSCRIPT_MAKE_S32(*(int16_t *) raw); + break; + case 4: + *val = mSCRIPT_MAKE_S32(*(int32_t *) raw); + break; + case 8: + *val = mSCRIPT_MAKE_S64(*(int64_t *) raw); + break; + default: + return false; + } + break; + case mSCRIPT_TYPE_UINT: + switch (member->type->size) { + case 1: + *val = mSCRIPT_MAKE_U32(*(uint8_t *) raw); + break; + case 2: + *val = mSCRIPT_MAKE_U32(*(uint16_t *) raw); + break; + case 4: + *val = mSCRIPT_MAKE_U32(*(uint32_t *) raw); + break; + case 8: + *val = mSCRIPT_MAKE_U64(*(uint64_t *) raw); + break; + default: + return false; + } + break; + case mSCRIPT_TYPE_FLOAT: + switch (member->type->size) { + case 4: + *val = mSCRIPT_MAKE_F32(*(mSCRIPT_TYPE_C_F32 *) raw); + break; + case 8: + *val = mSCRIPT_MAKE_F64(*(mSCRIPT_TYPE_C_F64 *) raw); + break; + default: + return false; + } + break; + case mSCRIPT_TYPE_FUNCTION: + val->refs = mSCRIPT_VALUE_UNREF; + val->flags = 0; + val->type = member->type; + member->type->alloc(val); + break; + case mSCRIPT_TYPE_OBJECT: + val->refs = mSCRIPT_VALUE_UNREF; + val->flags = 0; + val->value.opaque = raw; + if (isConst && !member->type->isConst) { + val->type = member->type->constType; + } else { + val->type = member->type; + } + break; + case mSCRIPT_TYPE_OPAQUE: + val->refs = mSCRIPT_VALUE_UNREF; + val->flags = 0; + val->value.opaque = raw; + val->type = member->type; + break; + default: + return false; + } + return true; +} + bool mScriptObjectGet(struct mScriptValue* obj, const char* member, struct mScriptValue* val) { if (obj->type->base == mSCRIPT_TYPE_WRAPPER) { obj = mScriptValueUnwrap(obj); @@ -836,74 +916,28 @@ bool mScriptObjectGet(struct mScriptValue* obj, const char* member, struct mScri return false; } - void* rawMember = (void *)((uintptr_t) obj->value.opaque + m->offset); - switch (m->type->base) { - case mSCRIPT_TYPE_SINT: - switch (m->type->size) { - case 1: - *val = mSCRIPT_MAKE_S32(*(int8_t *) rawMember); - break; - case 2: - *val = mSCRIPT_MAKE_S32(*(int16_t *) rawMember); - break; - case 4: - *val = mSCRIPT_MAKE_S32(*(int32_t *) rawMember); - break; - case 8: - *val = mSCRIPT_MAKE_S64(*(int64_t *) rawMember); - break; - default: - return false; - } - break; - case mSCRIPT_TYPE_UINT: - switch (m->type->size) { - case 1: - *val = mSCRIPT_MAKE_U32(*(uint8_t *) rawMember); - break; - case 2: - *val = mSCRIPT_MAKE_U32(*(uint16_t *) rawMember); - break; - case 4: - *val = mSCRIPT_MAKE_U32(*(uint32_t *) rawMember); - break; - case 8: - *val = mSCRIPT_MAKE_U64(*(uint64_t *) rawMember); - break; - default: - return false; - } - break; - case mSCRIPT_TYPE_FLOAT: - switch (m->type->size) { - case 4: - *val = mSCRIPT_MAKE_F32(*(mSCRIPT_TYPE_C_F32 *) rawMember); - break; - case 8: - *val = mSCRIPT_MAKE_F64(*(mSCRIPT_TYPE_C_F64 *) rawMember); - break; - default: - return false; - } - break; - case mSCRIPT_TYPE_FUNCTION: - val->refs = mSCRIPT_VALUE_UNREF; - 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 _accessRawMember(m, obj->value.opaque, obj->type->isConst, val); +} + +bool mScriptObjectGetConst(const struct mScriptValue* obj, const char* member, struct mScriptValue* val) { + if (obj->type->base == mSCRIPT_TYPE_WRAPPER) { + obj = mScriptValueUnwrapConst(obj); + } + if (obj->type->base != mSCRIPT_TYPE_OBJECT) { return false; } - return true; + + const struct mScriptTypeClass* cls = obj->type->details.cls; + if (!cls) { + return false; + } + + struct mScriptClassMember* m = HashTableLookup(&cls->instanceMembers, member); + if (!m) { + return false; + } + + return _accessRawMember(m, obj->value.opaque, true, val); } bool mScriptObjectSet(struct mScriptValue* obj, const char* member, struct mScriptValue* val) { @@ -985,6 +1019,17 @@ bool mScriptObjectSet(struct mScriptValue* obj, const char* member, struct mScri return true; } +bool mScriptObjectCast(const struct mScriptValue* input, const struct mScriptType* type, struct mScriptValue* output) { + if (input->type == type || (input->type->constType == type)) { + output->type = type; + output->value.opaque = input->value.opaque; + output->refs = mSCRIPT_VALUE_UNREF; + output->flags = 0; + return true; + } + return false; +} + bool mScriptPopS32(struct mScriptList* list, int32_t* out) { mSCRIPT_POP(list, S32, val); *out = val;