Scripting: Add static dispatch to classes

This commit is contained in:
Vicki Pfau 2022-04-28 21:49:39 -07:00
parent e912450e85
commit 3179419f52
2 changed files with 148 additions and 10 deletions

View File

@ -296,50 +296,63 @@ CXX_GUARD_START
} \
};
#define mSCRIPT_DECLARE_STRUCT_D_METHOD(TYPE, RETURN, NAME, NPARAMS, ...) \
#define mSCRIPT_DECLARE_STRUCT_METHOD(TYPE, RETURN, NAME, FUNCTION, NPARAMS, ...) \
typedef _mAPPLY(mSCRIPT_TYPE_C_ ## RETURN) (*_mSTStructFunctionType_ ## TYPE ## _ ## NAME)(_mAPPLY(_mCOMMA_ ## NPARAMS(struct TYPE* , mSCRIPT_PREFIX_ ## NPARAMS(mSCRIPT_TYPE_C_, __VA_ARGS__)))); \
_mSCRIPT_DECLARE_STRUCT_METHOD(TYPE, NAME, S, 1, mSCRIPT_TYPE_MS_ ## RETURN, NPARAMS, __VA_ARGS__) \
\
static bool _mSTStructBinding_ ## TYPE ## _ ## NAME(struct mScriptFrame* frame, void* ctx) { \
UNUSED(ctx); \
_mSCRIPT_STRUCT_METHOD_POP(TYPE, S, NPARAMS, __VA_ARGS__); \
_mSCRIPT_CALL(RETURN, p0->NAME, _mSUCC ## NPARAMS); \
_mSCRIPT_CALL(RETURN, FUNCTION, _mSUCC ## NPARAMS); \
return true; \
} \
#define mSCRIPT_DECLARE_STRUCT_VOID_D_METHOD(TYPE, NAME, NPARAMS, ...) \
#define mSCRIPT_DECLARE_STRUCT_VOID_METHOD(TYPE, NAME, FUNCTION, NPARAMS, ...) \
typedef void (*_mSTStructFunctionType_ ## TYPE ## _ ## NAME)(_mAPPLY(_mCOMMA_ ## NPARAMS(struct TYPE* , mSCRIPT_PREFIX_ ## NPARAMS(mSCRIPT_TYPE_C_, __VA_ARGS__)))); \
_mSCRIPT_DECLARE_STRUCT_METHOD(TYPE, NAME, S, 0, , NPARAMS, __VA_ARGS__) \
\
static bool _mSTStructBinding_ ## TYPE ## _ ## NAME(struct mScriptFrame* frame, void* ctx) { \
UNUSED(ctx); \
_mSCRIPT_STRUCT_METHOD_POP(TYPE, S, NPARAMS, __VA_ARGS__); \
_mSCRIPT_CALL_VOID(p0->NAME, _mSUCC ## NPARAMS); \
_mSCRIPT_CALL_VOID(FUNCTION, _mSUCC ## NPARAMS); \
return true; \
} \
#define mSCRIPT_DECLARE_STRUCT_CD_METHOD(TYPE, RETURN, NAME, NPARAMS, ...) \
#define mSCRIPT_DECLARE_STRUCT_C_METHOD(TYPE, RETURN, NAME, FUNCTION, NPARAMS, ...) \
typedef _mAPPLY(mSCRIPT_TYPE_C_ ## RETURN) (*_mSTStructFunctionType_ ## TYPE ## _ ## NAME)(_mAPPLY(_mCOMMA_ ## NPARAMS(struct TYPE* , mSCRIPT_PREFIX_ ## NPARAMS(mSCRIPT_TYPE_C_, __VA_ARGS__)))); \
_mSCRIPT_DECLARE_STRUCT_METHOD(TYPE, NAME, CS, 1, mSCRIPT_TYPE_MS_ ## RETURN, NPARAMS, __VA_ARGS__) \
\
static bool _mSTStructBinding_ ## TYPE ## _ ## NAME(struct mScriptFrame* frame, void* ctx) { \
UNUSED(ctx); \
_mSCRIPT_STRUCT_METHOD_POP(TYPE, CS, NPARAMS, __VA_ARGS__); \
_mSCRIPT_CALL(RETURN, p0->NAME, _mSUCC ## NPARAMS); \
_mSCRIPT_CALL(RETURN, FUNCTION, _mSUCC ## NPARAMS); \
return true; \
} \
#define mSCRIPT_DECLARE_STRUCT_VOID_CD_METHOD(TYPE, NAME, NPARAMS, ...) \
#define mSCRIPT_DECLARE_STRUCT_VOID_C_METHOD(TYPE, NAME, FUNCTION, NPARAMS, ...) \
typedef void (*_mSTStructFunctionType_ ## TYPE ## _ ## NAME)(_mAPPLY(_mCOMMA_ ## NPARAMS(struct TYPE* , mSCRIPT_PREFIX_ ## NPARAMS(mSCRIPT_TYPE_C_, __VA_ARGS__)))); \
_mSCRIPT_DECLARE_STRUCT_METHOD(TYPE, NAME, CS, 0, , NPARAMS, __VA_ARGS__) \
\
static bool _mSTStructBinding_ ## TYPE ## _ ## NAME(struct mScriptFrame* frame, void* ctx) { \
UNUSED(ctx); \
_mSCRIPT_STRUCT_METHOD_POP(TYPE, CS, NPARAMS, __VA_ARGS__); \
_mSCRIPT_CALL_VOID(p0->NAME, _mSUCC ## NPARAMS); \
_mSCRIPT_CALL_VOID(FUNCTION, _mSUCC ## NPARAMS); \
return true; \
} \
#define mSCRIPT_DECLARE_STRUCT_D_METHOD(TYPE, RETURN, NAME, NPARAMS, ...) \
mSCRIPT_DECLARE_STRUCT_METHOD(TYPE, RETURN, NAME, p0->NAME, NPARAMS, __VA_ARGS__)
#define mSCRIPT_DECLARE_STRUCT_VOID_D_METHOD(TYPE, NAME, NPARAMS, ...) \
mSCRIPT_DECLARE_STRUCT_VOID_METHOD(TYPE, NAME, p0->NAME, NPARAMS, __VA_ARGS__)
#define mSCRIPT_DECLARE_STRUCT_CD_METHOD(TYPE, RETURN, NAME, NPARAMS, ...) \
mSCRIPT_DECLARE_STRUCT_C_METHOD(TYPE, RETURN, NAME, p0->NAME, NPARAMS, __VA_ARGS__)
#define mSCRIPT_DECLARE_STRUCT_VOID_CD_METHOD(TYPE, NAME, NPARAMS, ...) \
mSCRIPT_DECLARE_STRUCT_VOID_C_METHOD(TYPE, NAME, p0->NAME, NPARAMS, __VA_ARGS__)
#define mSCRIPT_DEFINE_STRUCT_METHOD(TYPE, NAME) { \
.type = mSCRIPT_CLASS_INIT_INSTANCE_MEMBER, \
.info = { \

View File

@ -54,6 +54,12 @@ mSCRIPT_DECLARE_STRUCT_CD_METHOD(TestA, S32, icfn0, 0);
mSCRIPT_DECLARE_STRUCT_CD_METHOD(TestA, S32, icfn1, 1, S32);
mSCRIPT_DECLARE_STRUCT_VOID_D_METHOD(TestA, vfn0, 0);
mSCRIPT_DECLARE_STRUCT_VOID_D_METHOD(TestA, vfn1, 1, S32);
mSCRIPT_DECLARE_STRUCT_METHOD(TestA, S32, i0, testAi0, 0);
mSCRIPT_DECLARE_STRUCT_METHOD(TestA, S32, i1, testAi1, 1, S32);
mSCRIPT_DECLARE_STRUCT_C_METHOD(TestA, S32, ic0, testAic0, 0);
mSCRIPT_DECLARE_STRUCT_C_METHOD(TestA, S32, ic1, testAic1, 1, S32);
mSCRIPT_DECLARE_STRUCT_VOID_METHOD(TestA, v0, testAv0, 0);
mSCRIPT_DECLARE_STRUCT_VOID_METHOD(TestA, v1, testAv1, 1, S32);
mSCRIPT_DEFINE_STRUCT(TestA)
mSCRIPT_DEFINE_DOCSTRING(MEMBER_A_DOCSTRING)
@ -67,6 +73,12 @@ mSCRIPT_DEFINE_STRUCT(TestA)
mSCRIPT_DEFINE_STRUCT_METHOD(TestA, icfn1)
mSCRIPT_DEFINE_STRUCT_METHOD(TestA, vfn0)
mSCRIPT_DEFINE_STRUCT_METHOD(TestA, vfn1)
mSCRIPT_DEFINE_STRUCT_METHOD(TestA, i0)
mSCRIPT_DEFINE_STRUCT_METHOD(TestA, i1)
mSCRIPT_DEFINE_STRUCT_METHOD(TestA, ic0)
mSCRIPT_DEFINE_STRUCT_METHOD(TestA, ic1)
mSCRIPT_DEFINE_STRUCT_METHOD(TestA, v0)
mSCRIPT_DEFINE_STRUCT_METHOD(TestA, v1)
mSCRIPT_DEFINE_DOCSTRING(MEMBER_A_DOCSTRING)
mSCRIPT_DEFINE_STATIC_MEMBER(S32, s_i)
@ -188,7 +200,119 @@ M_TEST_DEFINE(testATranslation) {
assert_false(cls->init);
}
M_TEST_DEFINE(testAFunctions) {
M_TEST_DEFINE(testAStatic) {
struct mScriptTypeClass* cls = mSCRIPT_TYPE_MS_S(TestA)->details.cls;
assert_false(cls->init);
mScriptClassInit(cls);
assert_true(cls->init);
struct TestA s = {
.i = 1,
};
struct mScriptValue sval = mSCRIPT_MAKE_S(TestA, &s);
struct mScriptValue val;
struct mScriptFrame frame;
int32_t rval;
assert_true(mScriptObjectGet(&sval, "i0", &val));
mScriptFrameInit(&frame);
mSCRIPT_PUSH(&frame.arguments, S(TestA), &s);
assert_true(mScriptInvoke(&val, &frame));
assert_true(mScriptPopS32(&frame.returnValues, &rval));
assert_int_equal(rval, 1);
mScriptFrameDeinit(&frame);
assert_true(mScriptObjectGet(&sval, "i1", &val));
mScriptFrameInit(&frame);
mSCRIPT_PUSH(&frame.arguments, S(TestA), &s);
mSCRIPT_PUSH(&frame.arguments, S32, 1);
assert_true(mScriptInvoke(&val, &frame));
assert_true(mScriptPopS32(&frame.returnValues, &rval));
assert_int_equal(rval, 2);
mScriptFrameDeinit(&frame);
assert_true(mScriptObjectGet(&sval, "ic0", &val));
mScriptFrameInit(&frame);
mSCRIPT_PUSH(&frame.arguments, CS(TestA), &s);
assert_true(mScriptInvoke(&val, &frame));
assert_true(mScriptPopS32(&frame.returnValues, &rval));
assert_int_equal(rval, 1);
mScriptFrameDeinit(&frame);
assert_true(mScriptObjectGet(&sval, "ic0", &val));
mScriptFrameInit(&frame);
mSCRIPT_PUSH(&frame.arguments, S(TestA), &s);
assert_true(mScriptInvoke(&val, &frame));
assert_true(mScriptPopS32(&frame.returnValues, &rval));
assert_int_equal(rval, 1);
mScriptFrameDeinit(&frame);
assert_true(mScriptObjectGet(&sval, "ic1", &val));
mScriptFrameInit(&frame);
mSCRIPT_PUSH(&frame.arguments, CS(TestA), &s);
mSCRIPT_PUSH(&frame.arguments, S32, 1);
assert_true(mScriptInvoke(&val, &frame));
assert_true(mScriptPopS32(&frame.returnValues, &rval));
assert_int_equal(rval, 2);
mScriptFrameDeinit(&frame);
assert_true(mScriptObjectGet(&sval, "ic1", &val));
mScriptFrameInit(&frame);
mSCRIPT_PUSH(&frame.arguments, S(TestA), &s);
mSCRIPT_PUSH(&frame.arguments, S32, 1);
assert_true(mScriptInvoke(&val, &frame));
assert_true(mScriptPopS32(&frame.returnValues, &rval));
assert_int_equal(rval, 2);
mScriptFrameDeinit(&frame);
assert_true(mScriptObjectGet(&sval, "v0", &val));
mScriptFrameInit(&frame);
mSCRIPT_PUSH(&frame.arguments, S(TestA), &s);
assert_true(mScriptInvoke(&val, &frame));
mScriptFrameDeinit(&frame);
assert_true(mScriptObjectGet(&sval, "i0", &val));
mScriptFrameInit(&frame);
mSCRIPT_PUSH(&frame.arguments, S(TestA), &s);
assert_true(mScriptInvoke(&val, &frame));
assert_true(mScriptPopS32(&frame.returnValues, &rval));
assert_int_equal(rval, 2);
mScriptFrameDeinit(&frame);
assert_true(mScriptObjectGet(&sval, "ic0", &val));
mScriptFrameInit(&frame);
mSCRIPT_PUSH(&frame.arguments, CS(TestA), &s);
assert_true(mScriptInvoke(&val, &frame));
assert_true(mScriptPopS32(&frame.returnValues, &rval));
assert_int_equal(rval, 2);
mScriptFrameDeinit(&frame);
assert_true(mScriptObjectGet(&sval, "v1", &val));
mScriptFrameInit(&frame);
mSCRIPT_PUSH(&frame.arguments, S(TestA), &s);
mSCRIPT_PUSH(&frame.arguments, S32, 2);
assert_true(mScriptInvoke(&val, &frame));
mScriptFrameDeinit(&frame);
assert_true(mScriptObjectGet(&sval, "i0", &val));
mScriptFrameInit(&frame);
mSCRIPT_PUSH(&frame.arguments, S(TestA), &s);
assert_true(mScriptInvoke(&val, &frame));
assert_true(mScriptPopS32(&frame.returnValues, &rval));
assert_int_equal(rval, 4);
mScriptFrameDeinit(&frame);
assert_true(mScriptObjectGet(&sval, "ic0", &val));
mScriptFrameInit(&frame);
mSCRIPT_PUSH(&frame.arguments, CS(TestA), &s);
assert_true(mScriptInvoke(&val, &frame));
assert_true(mScriptPopS32(&frame.returnValues, &rval));
assert_int_equal(rval, 4);
mScriptFrameDeinit(&frame);
assert_true(cls->init);
mScriptClassDeinit(cls);
assert_false(cls->init);
}
M_TEST_DEFINE(testADynamic) {
struct mScriptTypeClass* cls = mSCRIPT_TYPE_MS_S(TestA)->details.cls;
assert_false(cls->init);
mScriptClassInit(cls);
@ -319,4 +443,5 @@ M_TEST_DEFINE(testAFunctions) {
M_TEST_SUITE_DEFINE(mScriptClasses,
cmocka_unit_test(testALayout),
cmocka_unit_test(testATranslation),
cmocka_unit_test(testAFunctions))
cmocka_unit_test(testAStatic),
cmocka_unit_test(testADynamic))