From d053058ea37ffaf9b303916599193f49bc143cc1 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 1 Jul 2022 02:02:55 -0700 Subject: [PATCH] Scripting: Add boolean type --- include/mgba/script/macros.h | 1 + include/mgba/script/types.h | 6 + src/core/scripting.c | 16 +- src/script/engines/lua.c | 8 +- src/script/test/types.c | 279 +++++++++++++++++++++++++++++++++++ src/script/types.c | 74 +++++++++- 6 files changed, 370 insertions(+), 14 deletions(-) diff --git a/include/mgba/script/macros.h b/include/mgba/script/macros.h index 3833f6984..e350b4d5d 100644 --- a/include/mgba/script/macros.h +++ b/include/mgba/script/macros.h @@ -459,6 +459,7 @@ CXX_GUARD_START #define mSCRIPT_MAKE_S64(VALUE) mSCRIPT_MAKE(S64, VALUE) #define mSCRIPT_MAKE_U64(VALUE) mSCRIPT_MAKE(U64, VALUE) #define mSCRIPT_MAKE_F64(VALUE) mSCRIPT_MAKE(F64, VALUE) +#define mSCRIPT_MAKE_BOOL(VALUE) mSCRIPT_MAKE(BOOL, VALUE) #define mSCRIPT_MAKE_CHARP(VALUE) mSCRIPT_MAKE(CHARP, VALUE) #define mSCRIPT_MAKE_S(STRUCT, VALUE) mSCRIPT_MAKE(S(STRUCT), VALUE) #define mSCRIPT_MAKE_CS(STRUCT, VALUE) mSCRIPT_MAKE(CS(STRUCT), VALUE) diff --git a/include/mgba/script/types.h b/include/mgba/script/types.h index 7acb0c365..267f6b775 100644 --- a/include/mgba/script/types.h +++ b/include/mgba/script/types.h @@ -27,6 +27,7 @@ CXX_GUARD_START #define mSCRIPT_TYPE_C_S64 int64_t #define mSCRIPT_TYPE_C_U64 uint64_t #define mSCRIPT_TYPE_C_F64 double +#define mSCRIPT_TYPE_C_BOOL bool #define mSCRIPT_TYPE_C_STR struct mScriptString* #define mSCRIPT_TYPE_C_CHARP const char* #define mSCRIPT_TYPE_C_PTR void* @@ -55,6 +56,7 @@ CXX_GUARD_START #define mSCRIPT_TYPE_FIELD_S64 s64 #define mSCRIPT_TYPE_FIELD_U64 u64 #define mSCRIPT_TYPE_FIELD_F64 f64 +#define mSCRIPT_TYPE_FIELD_BOOL u32 #define mSCRIPT_TYPE_FIELD_STR string #define mSCRIPT_TYPE_FIELD_CHARP copaque #define mSCRIPT_TYPE_FIELD_PTR opaque @@ -82,6 +84,7 @@ CXX_GUARD_START #define mSCRIPT_TYPE_MS_S64 (&mSTSInt64) #define mSCRIPT_TYPE_MS_U64 (&mSTUInt64) #define mSCRIPT_TYPE_MS_F64 (&mSTFloat64) +#define mSCRIPT_TYPE_MS_BOOL (&mSTBool) #define mSCRIPT_TYPE_MS_STR (&mSTString) #define mSCRIPT_TYPE_MS_CHARP (&mSTCharPtr) #define mSCRIPT_TYPE_MS_LIST (&mSTList) @@ -109,6 +112,7 @@ CXX_GUARD_START #define mSCRIPT_TYPE_CMP_U64(TYPE) mSCRIPT_TYPE_CMP_GENERIC(mSCRIPT_TYPE_MS_U64, TYPE) #define mSCRIPT_TYPE_CMP_S64(TYPE) mSCRIPT_TYPE_CMP_GENERIC(mSCRIPT_TYPE_MS_S64, TYPE) #define mSCRIPT_TYPE_CMP_F64(TYPE) mSCRIPT_TYPE_CMP_GENERIC(mSCRIPT_TYPE_MS_F64, TYPE) +#define mSCRIPT_TYPE_CMP_BOOL(TYPE) mSCRIPT_TYPE_CMP_GENERIC(mSCRIPT_TYPE_MS_BOOL, TYPE) #define mSCRIPT_TYPE_CMP_STR(TYPE) mSCRIPT_TYPE_CMP_GENERIC(mSCRIPT_TYPE_MS_STR, TYPE) #define mSCRIPT_TYPE_CMP_CHARP(TYPE) mSCRIPT_TYPE_CMP_GENERIC(mSCRIPT_TYPE_MS_CHARP, TYPE) #define mSCRIPT_TYPE_CMP_LIST(TYPE) mSCRIPT_TYPE_CMP_GENERIC(mSCRIPT_TYPE_MS_LIST, TYPE) @@ -165,6 +169,7 @@ extern const struct mScriptType mSTFloat32; extern const struct mScriptType mSTSInt64; extern const struct mScriptType mSTUInt64; extern const struct mScriptType mSTFloat64; +extern const struct mScriptType mSTBool; extern const struct mScriptType mSTString; extern const struct mScriptType mSTCharPtr; extern const struct mScriptType mSTList; @@ -329,6 +334,7 @@ bool mScriptPopF32(struct mScriptList* list, float* out); bool mScriptPopS64(struct mScriptList* list, int64_t* out); bool mScriptPopU64(struct mScriptList* list, uint64_t* out); bool mScriptPopF64(struct mScriptList* list, double* out); +bool mScriptPopBool(struct mScriptList* list, bool* out); bool mScriptPopPointer(struct mScriptList* list, void** out); bool mScriptCast(const struct mScriptType* type, const struct mScriptValue* input, struct mScriptValue* output); diff --git a/src/core/scripting.c b/src/core/scripting.c index 97c2117d0..122888c1c 100644 --- a/src/core/scripting.c +++ b/src/core/scripting.c @@ -413,9 +413,9 @@ static void _mScriptCoreTakeScreenshot(struct mCore* core, const char* filename) } // Loading functions -mSCRIPT_DECLARE_STRUCT_METHOD(mCore, S32, loadFile, mCoreLoadFile, 1, CHARP, path); -mSCRIPT_DECLARE_STRUCT_METHOD(mCore, S32, autoloadSave, mCoreAutoloadSave, 0); -mSCRIPT_DECLARE_STRUCT_METHOD(mCore, S32, loadSaveFile, mCoreLoadSaveFile, 2, CHARP, path, S8, temporary); +mSCRIPT_DECLARE_STRUCT_METHOD(mCore, BOOL, loadFile, mCoreLoadFile, 1, CHARP, path); +mSCRIPT_DECLARE_STRUCT_METHOD(mCore, BOOL, autoloadSave, mCoreAutoloadSave, 0); +mSCRIPT_DECLARE_STRUCT_METHOD(mCore, BOOL, loadSaveFile, mCoreLoadSaveFile, 2, CHARP, path, BOOL, temporary); // Info functions mSCRIPT_DECLARE_STRUCT_CD_METHOD(mCore, S32, platform, 0); @@ -454,12 +454,12 @@ mSCRIPT_DECLARE_STRUCT_METHOD(mCore, WSTR, readRegister, _mScriptCoreReadRegiste mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mCore, writeRegister, _mScriptCoreWriteRegister, 2, CHARP, regName, S32, value); // Savestate functions -mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, S32, saveStateSlot, mCoreSaveState, 2, S32, slot, S32, flags); +mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, BOOL, saveStateSlot, mCoreSaveState, 2, S32, slot, S32, flags); mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, WSTR, saveStateBuffer, _mScriptCoreSaveState, 1, S32, flags); -mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, S32, saveStateFile, _mScriptCoreSaveStateFile, 2, CHARP, path, S32, flags); -mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, S32, loadStateSlot, mCoreLoadState, 2, S32, slot, S32, flags); -mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, S32, loadStateBuffer, _mScriptCoreLoadState, 2, STR, buffer, S32, flags); -mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, S32, loadStateFile, _mScriptCoreLoadStateFile, 2, CHARP, path, S32, flags); +mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, BOOL, saveStateFile, _mScriptCoreSaveStateFile, 2, CHARP, path, S32, flags); +mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, BOOL, loadStateSlot, mCoreLoadState, 2, S32, slot, S32, flags); +mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, BOOL, loadStateBuffer, _mScriptCoreLoadState, 2, STR, buffer, S32, flags); +mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, BOOL, loadStateFile, _mScriptCoreLoadStateFile, 2, CHARP, path, S32, flags); // Miscellaneous functions mSCRIPT_DECLARE_STRUCT_VOID_METHOD_WITH_DEFAULTS(mCore, screenshot, _mScriptCoreTakeScreenshot, 1, CHARP, filename); diff --git a/src/script/engines/lua.c b/src/script/engines/lua.c index 24ceefec8..90601db94 100644 --- a/src/script/engines/lua.c +++ b/src/script/engines/lua.c @@ -335,8 +335,8 @@ struct mScriptValue* _luaCoerce(struct mScriptEngineContextLua* luaContext, bool value->value.f64 = lua_tonumber(luaContext->lua, -1); break; case LUA_TBOOLEAN: - value = mScriptValueAlloc(mSCRIPT_TYPE_MS_S32); - value->value.s32 = lua_toboolean(luaContext->lua, -1); + value = mScriptValueAlloc(mSCRIPT_TYPE_MS_BOOL); + value->value.u32 = lua_toboolean(luaContext->lua, -1); break; case LUA_TSTRING: buffer = lua_tolstring(luaContext->lua, -1, &size); @@ -414,7 +414,9 @@ bool _luaWrap(struct mScriptEngineContextLua* luaContext, struct mScriptValue* v } break; case mSCRIPT_TYPE_UINT: - if (value->type->size <= 4) { + if (value->type == mSCRIPT_TYPE_MS_BOOL) { + lua_pushboolean(luaContext->lua, !!value->value.u32); + } else if (value->type->size <= 4) { lua_pushinteger(luaContext->lua, value->value.u32); } else if (value->type->size == 8) { lua_pushinteger(luaContext->lua, value->value.u64); diff --git a/src/script/test/types.c b/src/script/test/types.c index 9fa83a8a5..6ad38563a 100644 --- a/src/script/test/types.c +++ b/src/script/test/types.c @@ -206,41 +206,58 @@ M_TEST_DEFINE(wrongPopType) { uint64_t u64; float f32; double f64; + bool b; mScriptFrameInit(&frame); mSCRIPT_PUSH(&frame.arguments, S32, 0); assert_false(mScriptPopU32(&frame.arguments, &u32)); assert_false(mScriptPopF32(&frame.arguments, &f32)); + assert_false(mScriptPopBool(&frame.arguments, &b)); mScriptFrameDeinit(&frame); mScriptFrameInit(&frame); mSCRIPT_PUSH(&frame.arguments, S64, 0); assert_false(mScriptPopU64(&frame.arguments, &u64)); assert_false(mScriptPopF64(&frame.arguments, &f64)); + assert_false(mScriptPopBool(&frame.arguments, &b)); mScriptFrameDeinit(&frame); mScriptFrameInit(&frame); mSCRIPT_PUSH(&frame.arguments, U32, 0); assert_false(mScriptPopS32(&frame.arguments, &s32)); assert_false(mScriptPopF32(&frame.arguments, &f32)); + assert_false(mScriptPopBool(&frame.arguments, &b)); mScriptFrameDeinit(&frame); mScriptFrameInit(&frame); mSCRIPT_PUSH(&frame.arguments, U64, 0); assert_false(mScriptPopS64(&frame.arguments, &s64)); assert_false(mScriptPopF64(&frame.arguments, &f64)); + assert_false(mScriptPopBool(&frame.arguments, &b)); mScriptFrameDeinit(&frame); mScriptFrameInit(&frame); mSCRIPT_PUSH(&frame.arguments, F32, 0); assert_false(mScriptPopS32(&frame.arguments, &s32)); assert_false(mScriptPopU32(&frame.arguments, &u32)); + assert_false(mScriptPopBool(&frame.arguments, &b)); mScriptFrameDeinit(&frame); mScriptFrameInit(&frame); mSCRIPT_PUSH(&frame.arguments, F64, 0); assert_false(mScriptPopS64(&frame.arguments, &s64)); assert_false(mScriptPopU64(&frame.arguments, &u64)); + assert_false(mScriptPopBool(&frame.arguments, &b)); + mScriptFrameDeinit(&frame); + + mScriptFrameInit(&frame); + mSCRIPT_PUSH(&frame.arguments, BOOL, 0); + assert_false(mScriptPopS32(&frame.arguments, &s32)); + assert_false(mScriptPopU32(&frame.arguments, &u32)); + assert_false(mScriptPopS64(&frame.arguments, &s64)); + assert_false(mScriptPopU64(&frame.arguments, &u64)); + assert_false(mScriptPopF32(&frame.arguments, &f32)); + assert_false(mScriptPopF64(&frame.arguments, &f64)); mScriptFrameDeinit(&frame); } @@ -382,6 +399,100 @@ M_TEST_DEFINE(coerceFromFloat) { mScriptFrameDeinit(&frame); } +M_TEST_DEFINE(coerceToBool) { + struct mScriptValue a; + struct mScriptValue b; + + a = mSCRIPT_MAKE_S32(0); + assert_true(mScriptCast(mSCRIPT_TYPE_MS_BOOL, &a, &b)); + assert_true(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(false))); + assert_false(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(true))); + + a = mSCRIPT_MAKE_S32(1); + assert_true(mScriptCast(mSCRIPT_TYPE_MS_BOOL, &a, &b)); + assert_true(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(true))); + assert_false(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(false))); + + a = mSCRIPT_MAKE_S32(-1); + assert_true(mScriptCast(mSCRIPT_TYPE_MS_BOOL, &a, &b)); + assert_true(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(true))); + assert_false(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(false))); + + a = mSCRIPT_MAKE_S32(INT_MAX); + assert_true(mScriptCast(mSCRIPT_TYPE_MS_BOOL, &a, &b)); + assert_true(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(true))); + assert_false(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(false))); + + a = mSCRIPT_MAKE_S32(INT_MIN); + assert_true(mScriptCast(mSCRIPT_TYPE_MS_BOOL, &a, &b)); + assert_true(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(true))); + assert_false(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(false))); + + a = mSCRIPT_MAKE_U32(0); + assert_true(mScriptCast(mSCRIPT_TYPE_MS_BOOL, &a, &b)); + assert_true(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(false))); + assert_false(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(true))); + + a = mSCRIPT_MAKE_U32(1); + assert_true(mScriptCast(mSCRIPT_TYPE_MS_BOOL, &a, &b)); + assert_true(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(true))); + assert_false(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(false))); + + a = mSCRIPT_MAKE_U32(UINT_MAX); + assert_true(mScriptCast(mSCRIPT_TYPE_MS_BOOL, &a, &b)); + assert_true(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(true))); + assert_false(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(false))); + + a = mSCRIPT_MAKE_F32(0); + assert_true(mScriptCast(mSCRIPT_TYPE_MS_BOOL, &a, &b)); + assert_true(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(false))); + assert_false(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(true))); + + a = mSCRIPT_MAKE_F32(1); + assert_true(mScriptCast(mSCRIPT_TYPE_MS_BOOL, &a, &b)); + assert_true(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(true))); + assert_false(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(false))); + + a = mSCRIPT_MAKE_F32(1e30f); + assert_true(mScriptCast(mSCRIPT_TYPE_MS_BOOL, &a, &b)); + assert_true(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(true))); + assert_false(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(false))); + + a = mSCRIPT_MAKE_F32(1e-30f); + assert_true(mScriptCast(mSCRIPT_TYPE_MS_BOOL, &a, &b)); + assert_true(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(true))); + assert_false(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(false))); +} + +M_TEST_DEFINE(coerceFromBool) { + struct mScriptValue a; + struct mScriptValue b; + + a = mSCRIPT_MAKE_BOOL(false); + assert_true(mScriptCast(mSCRIPT_TYPE_MS_S32, &a, &b)); + assert_true(mSCRIPT_TYPE_MS_S32->equal(&b, &mSCRIPT_MAKE_S32(0))); + + a = mSCRIPT_MAKE_BOOL(true); + assert_true(mScriptCast(mSCRIPT_TYPE_MS_S32, &a, &b)); + assert_true(mSCRIPT_TYPE_MS_S32->equal(&b, &mSCRIPT_MAKE_S32(1))); + + a = mSCRIPT_MAKE_BOOL(true); + assert_true(mScriptCast(mSCRIPT_TYPE_MS_S32, &a, &b)); + assert_false(mSCRIPT_TYPE_MS_S32->equal(&b, &mSCRIPT_MAKE_S32(-1))); + + a = mSCRIPT_MAKE_BOOL(false); + assert_true(mScriptCast(mSCRIPT_TYPE_MS_U32, &a, &b)); + assert_true(mSCRIPT_TYPE_MS_U32->equal(&b, &mSCRIPT_MAKE_U32(0))); + + a = mSCRIPT_MAKE_BOOL(true); + assert_true(mScriptCast(mSCRIPT_TYPE_MS_U32, &a, &b)); + assert_true(mSCRIPT_TYPE_MS_U32->equal(&b, &mSCRIPT_MAKE_U32(1))); + + a = mSCRIPT_MAKE_BOOL(true); + assert_true(mScriptCast(mSCRIPT_TYPE_MS_U32, &a, &b)); + assert_false(mSCRIPT_TYPE_MS_U32->equal(&b, &mSCRIPT_MAKE_U32(2))); +} + M_TEST_DEFINE(coerceWiden) { struct mScriptFrame frame; mScriptFrameInit(&frame); @@ -471,6 +582,20 @@ M_TEST_DEFINE(s32Equality) { COMPARE_BOOL(false, S32, 0, F64, 0.1); COMPARE_BOOL(true, S32, 0x40000000, F64, 0x40000000); COMPARE_BOOL(true, S32, -0x40000000, F64, -0x40000000); + + // BOOL + COMPARE_BOOL(true, S32, 0, BOOL, false); + COMPARE_BOOL(false, S32, 0, BOOL, true); + COMPARE_BOOL(false, S32, 1, BOOL, false); + COMPARE_BOOL(true, S32, 1, BOOL, true); + COMPARE_BOOL(false, S32, -1, BOOL, false); + COMPARE_BOOL(true, S32, -1, BOOL, true); + COMPARE_BOOL(false, S32, 2, BOOL, false); + COMPARE_BOOL(true, S32, 2, BOOL, true); + COMPARE_BOOL(false, S32, 0x7FFFFFFF, BOOL, false); + COMPARE_BOOL(true, S32, 0x7FFFFFFF, BOOL, true); + COMPARE_BOOL(false, S32, -0x80000000, BOOL, false); + COMPARE_BOOL(true, S32, -0x80000000, BOOL, true); } M_TEST_DEFINE(s64Equality) { @@ -552,6 +677,20 @@ M_TEST_DEFINE(s64Equality) { COMPARE_BOOL(false, S64, 0, F64, 0.1); COMPARE_BOOL(true, S64, 0x4000000000000000LL, F64, 0x4000000000000000LL); COMPARE_BOOL(true, S64, -0x4000000000000000LL, F64, -0x4000000000000000LL); + + // BOOL + COMPARE_BOOL(true, S64, 0, BOOL, false); + COMPARE_BOOL(false, S64, 0, BOOL, true); + COMPARE_BOOL(false, S64, 1, BOOL, false); + COMPARE_BOOL(true, S64, 1, BOOL, true); + COMPARE_BOOL(false, S64, -1, BOOL, false); + COMPARE_BOOL(true, S64, -1, BOOL, true); + COMPARE_BOOL(false, S64, 2, BOOL, false); + COMPARE_BOOL(true, S64, 2, BOOL, true); + COMPARE_BOOL(false, S64, 0x7FFFFFFFFFFFFFFFLL, BOOL, false); + COMPARE_BOOL(true, S64, 0x7FFFFFFFFFFFFFFFLL, BOOL, true); + COMPARE_BOOL(false, S64, -0x8000000000000000LL, BOOL, false); + COMPARE_BOOL(true, S64, -0x8000000000000000LL, BOOL, true); } M_TEST_DEFINE(u32Equality) { @@ -623,6 +762,18 @@ M_TEST_DEFINE(u32Equality) { COMPARE_BOOL(false, U32, 0x80000000U, F64, 0); COMPARE_BOOL(false, U32, 1, F64, 1.1); COMPARE_BOOL(false, U32, 0, F64, 0.1); + + // BOOL + COMPARE_BOOL(true, U32, 0, BOOL, false); + COMPARE_BOOL(false, U32, 0, BOOL, true); + COMPARE_BOOL(false, U32, 1, BOOL, false); + COMPARE_BOOL(true, U32, 1, BOOL, true); + COMPARE_BOOL(false, U32, 2, BOOL, false); + COMPARE_BOOL(true, U32, 2, BOOL, true); + COMPARE_BOOL(false, U32, 0xFFFFFFFFU, BOOL, false); + COMPARE_BOOL(true, U32, 0xFFFFFFFFU, BOOL, true); + COMPARE_BOOL(false, U32, 0x80000000U, BOOL, false); + COMPARE_BOOL(true, U32, 0x80000000U, BOOL, true); } M_TEST_DEFINE(u64Equality) { @@ -701,6 +852,18 @@ M_TEST_DEFINE(u64Equality) { COMPARE_BOOL(false, U64, 0x8000000000000000ULL, F64, 0); COMPARE_BOOL(false, U64, 1, F64, 1.1); COMPARE_BOOL(false, U64, 0, F64, 0.1); + + // BOOL + COMPARE_BOOL(true, U64, 0, BOOL, false); + COMPARE_BOOL(false, U64, 0, BOOL, true); + COMPARE_BOOL(false, U64, 1, BOOL, false); + COMPARE_BOOL(true, U64, 1, BOOL, true); + COMPARE_BOOL(false, U64, 2, BOOL, false); + COMPARE_BOOL(true, U64, 2, BOOL, true); + COMPARE_BOOL(false, U64, 0xFFFFFFFFFFFFFFFFULL, BOOL, false); + COMPARE_BOOL(true, U64, 0xFFFFFFFFFFFFFFFFULL, BOOL, true); + COMPARE_BOOL(false, U64, 0x8000000000000000ULL, BOOL, false); + COMPARE_BOOL(true, U64, 0x8000000000000000ULL, BOOL, true); } M_TEST_DEFINE(f32Equality) { @@ -768,6 +931,18 @@ M_TEST_DEFINE(f32Equality) { COMPARE_BOOL(true, F32, 0x100000000ULL, U64, 0x100000000ULL); COMPARE_BOOL(false, F32, 0x100000000ULL, U64, 0); COMPARE_BOOL(false, F32, 0, U64, 0x100000000ULL); + + // BOOL + COMPARE_BOOL(true, F32, 0, BOOL, false); + COMPARE_BOOL(false, F32, 0, BOOL, true); + COMPARE_BOOL(false, F32, 1, BOOL, false); + COMPARE_BOOL(true, F32, 1, BOOL, true); + COMPARE_BOOL(false, F32, 1.1, BOOL, false); + COMPARE_BOOL(true, F32, 1.1, BOOL, true); + COMPARE_BOOL(false, F32, 0x040000000ULL, BOOL, false); + COMPARE_BOOL(true, F32, 0x040000000ULL, BOOL, true); + COMPARE_BOOL(false, F32, 0x100000000ULL, BOOL, false); + COMPARE_BOOL(true, F32, 0x100000000ULL, BOOL, true); } M_TEST_DEFINE(f64Equality) { @@ -835,6 +1010,107 @@ M_TEST_DEFINE(f64Equality) { COMPARE_BOOL(true, F64, 0x100000000ULL, U64, 0x100000000ULL); COMPARE_BOOL(false, F64, 0x100000000ULL, U64, 0); COMPARE_BOOL(false, F64, 0, U64, 0x100000000ULL); + + // BOOL + COMPARE_BOOL(true, F64, 0, BOOL, false); + COMPARE_BOOL(false, F64, 0, BOOL, true); + COMPARE_BOOL(false, F64, 1, BOOL, false); + COMPARE_BOOL(true, F64, 1, BOOL, true); + COMPARE_BOOL(false, F64, 1.1, BOOL, false); + COMPARE_BOOL(true, F64, 1.1, BOOL, true); + COMPARE_BOOL(false, F64, 0x040000000ULL, BOOL, false); + COMPARE_BOOL(true, F64, 0x040000000ULL, BOOL, true); + COMPARE_BOOL(false, F64, 0x100000000ULL, BOOL, false); + COMPARE_BOOL(true, F64, 0x100000000ULL, BOOL, true); +} + +M_TEST_DEFINE(boolEquality) { + struct mScriptValue a; + struct mScriptValue b; + + // S32 + COMPARE_BOOL(true, BOOL, false, S32, 0); + COMPARE_BOOL(false, BOOL, false, S32, 1); + COMPARE_BOOL(false, BOOL, false, S32, -1); + COMPARE_BOOL(false, BOOL, false, S32, 2); + COMPARE_BOOL(false, BOOL, false, S32, 0x7FFFFFFF); + COMPARE_BOOL(false, BOOL, false, S32, -0x80000000); + COMPARE_BOOL(false, BOOL, true, S32, 0); + COMPARE_BOOL(true, BOOL, true, S32, 1); + COMPARE_BOOL(true, BOOL, true, S32, -1); + COMPARE_BOOL(true, BOOL, true, S32, 2); + COMPARE_BOOL(true, BOOL, true, S32, 0x7FFFFFFF); + COMPARE_BOOL(true, BOOL, true, S32, -0x80000000); + + // S64 + COMPARE_BOOL(true, BOOL, false, S64, 0); + COMPARE_BOOL(false, BOOL, false, S64, 1); + COMPARE_BOOL(false, BOOL, false, S64, -1); + COMPARE_BOOL(false, BOOL, false, S64, 2); + COMPARE_BOOL(false, BOOL, false, S64, INT64_MIN); + COMPARE_BOOL(false, BOOL, false, S64, INT64_MAX); + COMPARE_BOOL(false, BOOL, true, S64, 0); + COMPARE_BOOL(true, BOOL, true, S64, 1); + COMPARE_BOOL(true, BOOL, true, S64, -1); + COMPARE_BOOL(true, BOOL, true, S64, 2); + COMPARE_BOOL(true, BOOL, true, S64, INT64_MIN); + COMPARE_BOOL(true, BOOL, true, S64, INT64_MAX); + + // U32 + COMPARE_BOOL(true, BOOL, false, U32, 0); + COMPARE_BOOL(false, BOOL, false, U32, 1); + COMPARE_BOOL(false, BOOL, false, U32, 2); + COMPARE_BOOL(false, BOOL, false, U32, UINT32_MAX); + COMPARE_BOOL(false, BOOL, true, U32, 0); + COMPARE_BOOL(true, BOOL, true, U32, 1); + COMPARE_BOOL(true, BOOL, true, U32, 2); + COMPARE_BOOL(true, BOOL, true, U32, UINT32_MAX); + + // U64 + COMPARE_BOOL(true, BOOL, false, U64, 0); + COMPARE_BOOL(false, BOOL, false, U64, 1); + COMPARE_BOOL(false, BOOL, false, U64, 2); + COMPARE_BOOL(false, BOOL, false, U64, INT64_MAX); + COMPARE_BOOL(false, BOOL, true, U64, 0); + COMPARE_BOOL(true, BOOL, true, U64, 1); + COMPARE_BOOL(true, BOOL, true, U64, 2); + COMPARE_BOOL(true, BOOL, true, U64, INT64_MAX); + + // F32 + COMPARE_BOOL(true, BOOL, false, F32, 0); + COMPARE_BOOL(false, BOOL, true, F32, 0); + COMPARE_BOOL(false, BOOL, false, F32, 1); + COMPARE_BOOL(true, BOOL, true, F32, 1); + COMPARE_BOOL(false, BOOL, false, F32, 1.1f); + COMPARE_BOOL(true, BOOL, true, F32, 1.1f); + COMPARE_BOOL(false, BOOL, false, F32, 1e30f); + COMPARE_BOOL(true, BOOL, true, F32, 1e30f); + COMPARE_BOOL(false, BOOL, false, F32, -1); + COMPARE_BOOL(true, BOOL, true, F32, -1); + COMPARE_BOOL(false, BOOL, false, F32, -1.1f); + COMPARE_BOOL(true, BOOL, true, F32, -1.1f); + COMPARE_BOOL(false, BOOL, false, F32, -0.1e-30f); + COMPARE_BOOL(true, BOOL, true, F32, -0.1e-30f); + COMPARE_BOOL(false, BOOL, false, F32, -1e30f); + COMPARE_BOOL(true, BOOL, true, F32, -1e30f); + + // F64 + COMPARE_BOOL(true, BOOL, false, F64, 0); + COMPARE_BOOL(false, BOOL, true, F64, 0); + COMPARE_BOOL(false, BOOL, false, F64, 1); + COMPARE_BOOL(true, BOOL, true, F64, 1); + COMPARE_BOOL(false, BOOL, false, F64, 1.1); + COMPARE_BOOL(true, BOOL, true, F64, 1.1); + COMPARE_BOOL(false, BOOL, false, F64, 1e30); + COMPARE_BOOL(true, BOOL, true, F64, 1e30); + COMPARE_BOOL(false, BOOL, false, F64, -1); + COMPARE_BOOL(true, BOOL, true, F64, -1); + COMPARE_BOOL(false, BOOL, false, F64, -1.1); + COMPARE_BOOL(true, BOOL, true, F64, -1.1); + COMPARE_BOOL(false, BOOL, false, F64, -0.1e-300); + COMPARE_BOOL(true, BOOL, true, F64, -0.1e-300); + COMPARE_BOOL(false, BOOL, false, F64, -1e300); + COMPARE_BOOL(true, BOOL, true, F64, -1e300); } M_TEST_DEFINE(stringEquality) { @@ -1002,6 +1278,8 @@ M_TEST_SUITE_DEFINE(mScript, cmocka_unit_test(wrongConst), cmocka_unit_test(coerceToFloat), cmocka_unit_test(coerceFromFloat), + cmocka_unit_test(coerceToBool), + cmocka_unit_test(coerceFromBool), cmocka_unit_test(coerceNarrow), cmocka_unit_test(coerceWiden), cmocka_unit_test(s32Equality), @@ -1010,6 +1288,7 @@ M_TEST_SUITE_DEFINE(mScript, cmocka_unit_test(u64Equality), cmocka_unit_test(f32Equality), cmocka_unit_test(f64Equality), + cmocka_unit_test(boolEquality), cmocka_unit_test(stringEquality), cmocka_unit_test(hashTableBasic), cmocka_unit_test(hashTableString), diff --git a/src/script/types.c b/src/script/types.c index a9df515f2..71d2b7e07 100644 --- a/src/script/types.c +++ b/src/script/types.c @@ -38,6 +38,7 @@ static bool _f32Equal(const struct mScriptValue*, const struct mScriptValue*); static bool _s64Equal(const struct mScriptValue*, const struct mScriptValue*); static bool _u64Equal(const struct mScriptValue*, const struct mScriptValue*); static bool _f64Equal(const struct mScriptValue*, const struct mScriptValue*); +static bool _boolEqual(const struct mScriptValue*, const struct mScriptValue*); static bool _charpEqual(const struct mScriptValue*, const struct mScriptValue*); static bool _stringEqual(const struct mScriptValue*, const struct mScriptValue*); @@ -162,6 +163,17 @@ const struct mScriptType mSTFloat64 = { .cast = _castScalar, }; +const struct mScriptType mSTBool = { + .base = mSCRIPT_TYPE_UINT, + .size = 1, + .name = "bool", + .alloc = NULL, + .free = NULL, + .hash = _hashScalar, + .equal = _boolEqual, + .cast = _castScalar, +}; + const struct mScriptType mSTString = { .base = mSCRIPT_TYPE_STRING, .size = sizeof(struct mScriptString), @@ -394,6 +406,7 @@ AS(Float32, F32); AS(SInt64, S64); AS(UInt64, U64); AS(Float64, F64); +AS(Bool, BOOL); bool _castScalar(const struct mScriptValue* input, const struct mScriptType* type, struct mScriptValue* output) { switch (type->base) { @@ -411,7 +424,13 @@ bool _castScalar(const struct mScriptValue* input, const struct mScriptType* typ } break; case mSCRIPT_TYPE_UINT: - if (type->size <= 4) { + if (type == mSCRIPT_TYPE_MS_BOOL) { + bool b; + if (!_asBool(input, &b)) { + return false; + } + output->value.u32 = b; + } else if (type->size <= 4) { if (!_asUInt32(input, &output->value.u32)) { return false; } @@ -485,6 +504,9 @@ bool _s32Equal(const struct mScriptValue* a, const struct mScriptValue* b) { } break; case mSCRIPT_TYPE_UINT: + if (b->type == mSCRIPT_TYPE_MS_BOOL) { + return !!a->value.s32 == b->value.u32; + } if (a->value.s32 < 0) { return false; } @@ -532,6 +554,9 @@ bool _u32Equal(const struct mScriptValue* a, const struct mScriptValue* b) { } break; case mSCRIPT_TYPE_UINT: + if (b->type == mSCRIPT_TYPE_MS_BOOL) { + return !!a->value.u32 == b->value.u32; + } if (b->type->size <= 4) { val = b->value.u32; } else if (b->type->size == 8) { @@ -554,8 +579,12 @@ bool _u32Equal(const struct mScriptValue* a, const struct mScriptValue* b) { bool _f32Equal(const struct mScriptValue* a, const struct mScriptValue* b) { float val; switch (b->type->base) { - case mSCRIPT_TYPE_SINT: case mSCRIPT_TYPE_UINT: + if (b->type == mSCRIPT_TYPE_MS_BOOL) { + return (!(uint32_t) !a->value.f32)== b->value.u32; + } + // Fall through + case mSCRIPT_TYPE_SINT: case mSCRIPT_TYPE_FLOAT: if (!_asFloat32(b, &val)) { return false; @@ -582,6 +611,9 @@ bool _s64Equal(const struct mScriptValue* a, const struct mScriptValue* b) { } break; case mSCRIPT_TYPE_UINT: + if (b->type == mSCRIPT_TYPE_MS_BOOL) { + return !!a->value.s64 == b->value.u32; + } if (a->value.s64 < 0) { return false; } @@ -629,6 +661,9 @@ bool _u64Equal(const struct mScriptValue* a, const struct mScriptValue* b) { } break; case mSCRIPT_TYPE_UINT: + if (b->type == mSCRIPT_TYPE_MS_BOOL) { + return !!a->value.u64 == b->value.u32; + } if (b->type->size <= 4) { val = b->value.u32; } else if (b->type->size == 8) { @@ -648,8 +683,12 @@ bool _u64Equal(const struct mScriptValue* a, const struct mScriptValue* b) { bool _f64Equal(const struct mScriptValue* a, const struct mScriptValue* b) { double val; switch (b->type->base) { - case mSCRIPT_TYPE_SINT: case mSCRIPT_TYPE_UINT: + if (b->type == mSCRIPT_TYPE_MS_BOOL) { + return (!(uint32_t) !a->value.f64)== b->value.u32; + } + // Fall through + case mSCRIPT_TYPE_SINT: case mSCRIPT_TYPE_FLOAT: if (!_asFloat64(b, &val)) { return false; @@ -663,6 +702,29 @@ bool _f64Equal(const struct mScriptValue* a, const struct mScriptValue* b) { return a->value.f64 == val; } +bool _boolEqual(const struct mScriptValue* a, const struct mScriptValue* b) { + switch (b->type->base) { + case mSCRIPT_TYPE_SINT: + if (b->type->size <= 4) { + return a->value.u32 == !!b->value.s32; + } else if (b->type->size == 8) { + return a->value.u32 == !!b->value.s64; + } + return false; + case mSCRIPT_TYPE_UINT: + if (b->type->size <= 4) { + return a->value.u32 == !!b->value.u32; + } else if (b->type->size == 8) { + return a->value.u32 == !!b->value.u64; + } + return false; + case mSCRIPT_TYPE_VOID: + return false; + default: + return b->type->equal && b->type->equal(b, a); + } +} + bool _charpEqual(const struct mScriptValue* a, const struct mScriptValue* b) { const char* valA = a->value.opaque; const char* valB; @@ -1368,6 +1430,12 @@ bool mScriptPopF64(struct mScriptList* list, double* out) { return true; } +bool mScriptPopBool(struct mScriptList* list, bool* out) { + mSCRIPT_POP(list, BOOL, val); + *out = val; + return true; +} + bool mScriptPopPointer(struct mScriptList* list, void** out) { mSCRIPT_POP(list, PTR, val); *out = val;