diff --git a/include/mgba/script/macros.h b/include/mgba/script/macros.h index 09ef58df0..9ce97f067 100644 --- a/include/mgba/script/macros.h +++ b/include/mgba/script/macros.h @@ -403,6 +403,9 @@ CXX_GUARD_START static const struct mScriptValue _mSTStructBindingDefaults_doc_ ## TYPE ## _ ## NAME[mSCRIPT_PARAMS_MAX]; \ _mSCRIPT_DECLARE_DOC_STRUCT_METHOD(SCOPE, TYPE, NAME, S, 0, 0, NPARAMS, _mIDENT(_mSTStructBindingDefaults_doc_ ## TYPE ## _ ## NAME), __VA_ARGS__) \ +#define mSCRIPT_DEFINE_FUNCTION_BINDING_DEFAULTS(NAME) \ + static const struct mScriptValue _bindingDefaults_ ## NAME[mSCRIPT_PARAMS_MAX] = { + #define mSCRIPT_DEFINE_STRUCT_BINDING_DEFAULTS(TYPE, NAME) \ static const struct mScriptValue _mSTStructBindingDefaults_ ## TYPE ## _ ## NAME[mSCRIPT_PARAMS_MAX] = { \ mSCRIPT_NO_DEFAULT, @@ -449,7 +452,7 @@ CXX_GUARD_START #define mSCRIPT_DEFINE_END { .type = mSCRIPT_CLASS_INIT_END } } } -#define _mSCRIPT_BIND_FUNCTION(NAME, NRET, RETURN, NPARAMS, ...) \ +#define _mSCRIPT_BIND_FUNCTION(NAME, NRET, RETURN, DEFAULTS, NPARAMS, ...) \ static struct mScriptFunction _function_ ## NAME = { \ .call = _binding_ ## NAME \ }; \ @@ -466,6 +469,7 @@ CXX_GUARD_START .count = NPARAMS, \ .entries = { _mCALL(_mIF0_ ## NPARAMS, 0) _mCALL(mSCRIPT_PREFIX_ ## NPARAMS, mSCRIPT_TYPE_MS_, _mEVEN_ ## NPARAMS(__VA_ARGS__)) }, \ .names = { _mCALL(_mIF0_ ## NPARAMS, 0) _mCALL(_mCALL_ ## NPARAMS, _mSTRINGIFY, _mODD_ ## NPARAMS(__VA_ARGS__)) }, \ + .defaults = DEFAULTS, \ }, \ .returnType = { \ .count = NRET, \ @@ -482,7 +486,7 @@ CXX_GUARD_START } \ } -#define mSCRIPT_BIND_FUNCTION(NAME, RETURN, FUNCTION, NPARAMS, ...) \ +#define _mSCRIPT_BIND_N_FUNCTION(NAME, RETURN, FUNCTION, DEFAULTS, NPARAMS, ...) \ static bool _binding_ ## NAME(struct mScriptFrame* frame, void* ctx) { \ UNUSED(ctx); \ _mCALL(mSCRIPT_POP_ ## NPARAMS, &frame->arguments, _mEVEN_ ## NPARAMS(__VA_ARGS__)); \ @@ -492,9 +496,9 @@ CXX_GUARD_START _mSCRIPT_CALL(RETURN, FUNCTION, NPARAMS); \ return true; \ } \ - _mSCRIPT_BIND_FUNCTION(NAME, 1, mSCRIPT_TYPE_MS_ ## RETURN, NPARAMS, __VA_ARGS__) + _mSCRIPT_BIND_FUNCTION(NAME, 1, mSCRIPT_TYPE_MS_ ## RETURN, DEFAULTS, NPARAMS, __VA_ARGS__) -#define mSCRIPT_BIND_VOID_FUNCTION(NAME, FUNCTION, NPARAMS, ...) \ +#define _mSCRIPT_BIND_VOID_FUNCTION(NAME, FUNCTION, DEFAULTS, NPARAMS, ...) \ static bool _binding_ ## NAME(struct mScriptFrame* frame, void* ctx) { \ UNUSED(ctx); \ _mCALL(mSCRIPT_POP_ ## NPARAMS, &frame->arguments, _mEVEN_ ## NPARAMS(__VA_ARGS__)); \ @@ -504,7 +508,21 @@ CXX_GUARD_START _mSCRIPT_CALL_VOID(FUNCTION, NPARAMS); \ return true; \ } \ - _mSCRIPT_BIND_FUNCTION(NAME, 0, 0, NPARAMS, __VA_ARGS__) + _mSCRIPT_BIND_FUNCTION(NAME, 0, 0, NULL, NPARAMS, __VA_ARGS__) + +#define mSCRIPT_BIND_FUNCTION(NAME, RETURN, FUNCTION, NPARAMS, ...) \ + _mSCRIPT_BIND_N_FUNCTION(NAME, RETURN, FUNCTION, NULL, NPARAMS, __VA_ARGS__) + +#define mSCRIPT_BIND_VOID_FUNCTION(NAME, FUNCTION, NPARAMS, ...) \ + _mSCRIPT_BIND_VOID_FUNCTION(NAME, FUNCTION, NULL, NPARAMS, __VA_ARGS__) + +#define mSCRIPT_BIND_FUNCTION_WITH_DEFAULTS(NAME, RETURN, FUNCTION, NPARAMS, ...) \ + static const struct mScriptValue _bindingDefaults_ ## NAME[mSCRIPT_PARAMS_MAX]; \ + _mSCRIPT_BIND_N_FUNCTION(NAME, RETURN, FUNCTION, _mIDENT(_bindingDefaults_ ## NAME), NPARAMS, __VA_ARGS__) + +#define mSCRIPT_BIND_VOID_FUNCTION_WITH_DEFAULTS(NAME, FUNCTION, NPARAMS, ...) \ + static const struct mScriptValue _bindingDefaults_ ## _ ## NAME[mSCRIPT_PARAMS_MAX]; \ + _mSCRIPT_BIND_VOID_FUNCTION(NAME, FUNCTION, _mIDENT(_bindingDefaults_ ## NAME), NPARAMS, __VA_ARGS__) #define _mSCRIPT_DEFINE_DOC_FUNCTION(SCOPE, NAME, NRET, RETURN, NPARAMS, ...) \ static const struct mScriptType _mScriptDocType_ ## NAME = { \ diff --git a/src/script/test/types.c b/src/script/test/types.c index d5e7834b4..25ec29809 100644 --- a/src/script/test/types.c +++ b/src/script/test/types.c @@ -94,6 +94,12 @@ mSCRIPT_BIND_FUNCTION(boundIsHello, S32, isHello, 1, CHARP, str); mSCRIPT_BIND_FUNCTION(boundIsSequential, S32, isSequential, 1, LIST, list); mSCRIPT_BIND_FUNCTION(boundIsNullCharp, BOOL, isNullCharp, 1, CHARP, arg); mSCRIPT_BIND_FUNCTION(boundIsNullStruct, BOOL, isNullStruct, 1, S(Test), arg); +mSCRIPT_BIND_FUNCTION_WITH_DEFAULTS(boundAddIntWithDefaults, S32, addInts, 2, S32, a, S32, b); + +mSCRIPT_DEFINE_FUNCTION_BINDING_DEFAULTS(boundAddIntWithDefaults) + mSCRIPT_NO_DEFAULT, + mSCRIPT_S32(0) +mSCRIPT_DEFINE_DEFAULTS_END; M_TEST_DEFINE(voidArgs) { struct mScriptFrame frame; @@ -170,6 +176,30 @@ M_TEST_DEFINE(addS32) { mScriptFrameDeinit(&frame); } +M_TEST_DEFINE(addS32Defaults) { + struct mScriptFrame frame; + int32_t val; + + mScriptFrameInit(&frame); + mSCRIPT_PUSH(&frame.arguments, S32, 1); + mSCRIPT_PUSH(&frame.arguments, S32, 2); + assert_true(mScriptInvoke(&boundAddIntWithDefaults, &frame)); + assert_true(mScriptPopS32(&frame.returnValues, &val)); + assert_int_equal(val, 3); + mScriptFrameDeinit(&frame); + + mScriptFrameInit(&frame); + mSCRIPT_PUSH(&frame.arguments, S32, 1); + assert_true(mScriptInvoke(&boundAddIntWithDefaults, &frame)); + assert_true(mScriptPopS32(&frame.returnValues, &val)); + assert_int_equal(val, 1); + mScriptFrameDeinit(&frame); + + mScriptFrameInit(&frame); + assert_false(mScriptInvoke(&boundAddIntWithDefaults, &frame)); + mScriptFrameDeinit(&frame); +} + M_TEST_DEFINE(subS32) { struct mScriptFrame frame; mScriptFrameInit(&frame); @@ -1314,6 +1344,7 @@ M_TEST_SUITE_DEFINE(mScript, cmocka_unit_test(identityFunctionF32), cmocka_unit_test(identityFunctionStruct), cmocka_unit_test(addS32), + cmocka_unit_test(addS32Defaults), cmocka_unit_test(subS32), cmocka_unit_test(wrongArgCountLo), cmocka_unit_test(wrongArgCountHi),