Scripting: Start adding type-aware casting

This commit is contained in:
Vicki Pfau 2021-08-30 20:03:14 -07:00
parent 9955d0d19b
commit cbae6a61e5
2 changed files with 65 additions and 69 deletions

View File

@ -225,6 +225,7 @@ struct mScriptType {
void (*free)(struct mScriptValue*);
uint32_t (*hash)(const struct mScriptValue*);
bool (*equal)(const struct mScriptValue*, const struct mScriptValue*);
bool (*cast)(const struct mScriptValue*, const struct mScriptType*, struct mScriptValue*);
};
struct mScriptValue {

View File

@ -16,6 +16,7 @@ static void _allocString(struct mScriptValue*);
static void _freeString(struct mScriptValue*);
static uint32_t _hashString(const struct mScriptValue*);
static bool _castScalar(const struct mScriptValue*, const struct mScriptType*, struct mScriptValue*);
static uint32_t _hashScalar(const struct mScriptValue*);
static uint32_t _valHash(const void* val, size_t len, uint32_t seed);
@ -38,6 +39,7 @@ const struct mScriptType mSTVoid = {
.free = NULL,
.hash = NULL,
.equal = _typeEqual,
.cast = NULL,
};
const struct mScriptType mSTSInt32 = {
@ -48,6 +50,7 @@ const struct mScriptType mSTSInt32 = {
.free = NULL,
.hash = _hashScalar,
.equal = _s32Equal,
.cast = _castScalar,
};
const struct mScriptType mSTUInt32 = {
@ -58,6 +61,7 @@ const struct mScriptType mSTUInt32 = {
.free = NULL,
.hash = _hashScalar,
.equal = _u32Equal,
.cast = _castScalar,
};
const struct mScriptType mSTFloat32 = {
@ -68,6 +72,7 @@ const struct mScriptType mSTFloat32 = {
.free = NULL,
.hash = NULL,
.equal = _f32Equal,
.cast = _castScalar,
};
const struct mScriptType mSTString = {
@ -168,6 +173,60 @@ uint32_t _hashScalar(const struct mScriptValue* val) {
return x;
}
bool _castScalar(const struct mScriptValue* input, const struct mScriptType* type, struct mScriptValue* output) {
switch (type->base) {
case mSCRIPT_TYPE_SINT:
switch (input->type->base) {
case mSCRIPT_TYPE_SINT:
output->value.s32 = input->value.s32;
break;
case mSCRIPT_TYPE_UINT:
output->value.s32 = input->value.u32;
break;
case mSCRIPT_TYPE_FLOAT:
output->value.s32 = input->value.f32;
break;
default:
return false;
}
break;
case mSCRIPT_TYPE_UINT:
switch (input->type->base) {
case mSCRIPT_TYPE_SINT:
output->value.u32 = input->value.s32;
break;
case mSCRIPT_TYPE_UINT:
output->value.u32 = input->value.u32;
break;
case mSCRIPT_TYPE_FLOAT:
output->value.u32 = input->value.f32;
break;
default:
return false;
}
break;
case mSCRIPT_TYPE_FLOAT:
switch (input->type->base) {
case mSCRIPT_TYPE_SINT:
output->value.f32 = input->value.s32;
break;
case mSCRIPT_TYPE_UINT:
output->value.f32 = input->value.u32;
break;
case mSCRIPT_TYPE_FLOAT:
output->value.f32 = input->value.f32;
break;
default:
return false;
}
break;
default:
return false;
}
output->type = type;
return true;
}
uint32_t _valHash(const void* val, size_t len, uint32_t seed) {
UNUSED(len);
const struct mScriptValue* value = val;
@ -427,76 +486,12 @@ bool mScriptPopPointer(struct mScriptList* list, void** out) {
}
bool mScriptCast(const struct mScriptType* type, const struct mScriptValue* input, struct mScriptValue* output) {
switch (type->base) {
case mSCRIPT_TYPE_VOID:
return false;
case mSCRIPT_TYPE_SINT:
switch (input->type->base) {
case mSCRIPT_TYPE_SINT:
output->value.s32 = input->value.s32;
break;
case mSCRIPT_TYPE_UINT:
output->value.s32 = input->value.u32;
break;
case mSCRIPT_TYPE_FLOAT:
switch (input->type->size) {
case 4:
output->value.s32 = input->value.f32;
break;
default:
return false;
}
break;
default:
return false;
}
break;
case mSCRIPT_TYPE_UINT:
switch (input->type->base) {
case mSCRIPT_TYPE_SINT:
output->value.u32 = input->value.s32;
break;
case mSCRIPT_TYPE_UINT:
output->value.u32 = input->value.u32;
break;
case mSCRIPT_TYPE_FLOAT:
switch (input->type->size) {
case 4:
output->value.u32 = input->value.f32;
break;
default:
return false;
}
break;
default:
return false;
}
break;
case mSCRIPT_TYPE_FLOAT:
switch (input->type->base) {
case mSCRIPT_TYPE_SINT:
output->value.f32 = input->value.s32;
break;
case mSCRIPT_TYPE_UINT:
output->value.f32 = input->value.u32;
break;
case mSCRIPT_TYPE_FLOAT:
switch (input->type->size) {
case 4:
output->value.f32 = input->value.f32;
break;
default:
return false;
}
break;
default:
return false;
}
break;
default:
return false;
if (type->cast && type->cast(input, type, output)) {
return true;
}
if (input->type->cast && input->type->cast(input, type, output)) {
return true;
}
output->type = type;
return true;
}