mirror of https://github.com/mgba-emu/mgba.git
Scripting: Revamp pointer handling, struct casting
This commit is contained in:
parent
c296ea79ff
commit
aa91ffabfd
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue