mirror of https://github.com/mgba-emu/mgba.git
Scripting: Add overloads, overload isKeyActive
This commit is contained in:
parent
e3edca1f41
commit
5ff777d301
|
@ -254,7 +254,7 @@ CXX_GUARD_START
|
|||
return false; \
|
||||
}
|
||||
|
||||
#define _mSCRIPT_DECLARE_STRUCT_METHOD(TYPE, NAME, S, NRET, RETURN, NPARAMS, DEFAULTS, ...) \
|
||||
#define _mSCRIPT_DECLARE_STRUCT_METHOD_HEAD(TYPE, NAME) \
|
||||
static bool _mSTStructBinding_ ## TYPE ## _ ## NAME(struct mScriptFrame* frame, void* ctx); \
|
||||
static const struct mScriptFunction _mSTStructBindingFunction_ ## TYPE ## _ ## NAME = { \
|
||||
.call = &_mSTStructBinding_ ## TYPE ## _ ## NAME \
|
||||
|
@ -269,6 +269,9 @@ CXX_GUARD_START
|
|||
.alloc = _mSTStructBindingAlloc_ ## TYPE ## _ ## NAME, \
|
||||
.details = { \
|
||||
.function = { \
|
||||
|
||||
#define _mSCRIPT_DECLARE_STRUCT_METHOD(TYPE, NAME, S, NRET, RETURN, NPARAMS, DEFAULTS, ...) \
|
||||
_mSCRIPT_DECLARE_STRUCT_METHOD_HEAD(TYPE, NAME) \
|
||||
.parameters = { \
|
||||
.count = _mSUCC_ ## NPARAMS, \
|
||||
.entries = { mSCRIPT_TYPE_MS_ ## S(TYPE), _mCALL(mSCRIPT_PREFIX_ ## NPARAMS, mSCRIPT_TYPE_MS_, _mEVEN_ ## NPARAMS(__VA_ARGS__)) }, \
|
||||
|
@ -283,6 +286,23 @@ CXX_GUARD_START
|
|||
} \
|
||||
};
|
||||
|
||||
#define _mSCRIPT_DECLARE_STRUCT_OVERLOADED_METHOD(TYPE, NAME, S, NRET, RETURN) \
|
||||
_mSCRIPT_DECLARE_STRUCT_METHOD_HEAD(TYPE, NAME) \
|
||||
.parameters = { \
|
||||
.count = 1, \
|
||||
.entries = { mSCRIPT_TYPE_MS_ ## S(TYPE) }, \
|
||||
.names = { "this" }, \
|
||||
.defaults = NULL, \
|
||||
.variable = true, \
|
||||
}, \
|
||||
.returnType = { \
|
||||
.count = NRET, \
|
||||
.entries = { RETURN } \
|
||||
}, \
|
||||
}, \
|
||||
} \
|
||||
};
|
||||
|
||||
#define _mSCRIPT_DECLARE_STRUCT_METHOD_SIGNATURE(TYPE, RETURN, NAME, CONST, NPARAMS, ...) \
|
||||
typedef RETURN (*_mSTStructFunctionType_ ## TYPE ## _ ## NAME)(_mCOMMA_ ## NPARAMS(CONST struct TYPE* , mSCRIPT_PREFIX_ ## NPARAMS(mSCRIPT_TYPE_C_, __VA_ARGS__)))
|
||||
|
||||
|
@ -302,6 +322,20 @@ CXX_GUARD_START
|
|||
return true; \
|
||||
} \
|
||||
|
||||
#define _mSCRIPT_DECLARE_STRUCT_OVERLOADED_METHOD_BINDING(TYPE, NAME, T) \
|
||||
static const struct mScriptFunctionOverload _mSTStructBindingOverloads_ ## TYPE ## _ ## NAME[]; \
|
||||
static bool _mSTStructBinding_ ## TYPE ## _ ## NAME(struct mScriptFrame* frame, void* ctx) { \
|
||||
UNUSED(ctx); \
|
||||
const struct mScriptFunctionOverload* overload = mScriptFunctionFindOverload(_mSTStructBindingOverloads_ ## TYPE ## _ ## NAME, &frame->arguments); \
|
||||
if (!overload) { \
|
||||
return false; \
|
||||
} \
|
||||
if (!mScriptCoerceFrame(&overload->type->details.function.parameters, &frame->arguments, &frame->arguments)) { \
|
||||
return false; \
|
||||
} \
|
||||
return overload->function->call(frame, overload->function->context); \
|
||||
}
|
||||
|
||||
#define mSCRIPT_DECLARE_STRUCT_METHOD(TYPE, RETURN, NAME, FUNCTION, NPARAMS, ...) \
|
||||
_mSCRIPT_DECLARE_STRUCT_METHOD_SIGNATURE(TYPE, mSCRIPT_TYPE_C_ ## RETURN, NAME, , NPARAMS, _mEVEN_ ## NPARAMS(__VA_ARGS__)); \
|
||||
_mSCRIPT_DECLARE_STRUCT_METHOD(TYPE, NAME, S, 1, mSCRIPT_TYPE_MS_ ## RETURN, NPARAMS, NULL, __VA_ARGS__) \
|
||||
|
@ -346,6 +380,22 @@ CXX_GUARD_START
|
|||
_mSCRIPT_DECLARE_STRUCT_METHOD(TYPE, NAME, CS, 0, 0, NPARAMS, _mIDENT(_mSTStructBindingDefaults_ ## TYPE ## _ ## NAME, __VA_ARGS__) \
|
||||
_mSCRIPT_DECLARE_STRUCT_VOID_METHOD_BINDING(TYPE, NAME, FUNCTION, CS, NPARAMS, __VA_ARGS__)
|
||||
|
||||
#define mSCRIPT_DECLARE_STRUCT_OVERLOADED_METHOD(TYPE, RETURN, NAME) \
|
||||
_mSCRIPT_DECLARE_STRUCT_OVERLOADED_METHOD(TYPE, NAME, S, 1, mSCRIPT_TYPE_MS_ ## RETURN) \
|
||||
_mSCRIPT_DECLARE_STRUCT_OVERLOADED_METHOD_BINDING(TYPE, NAME, S)
|
||||
|
||||
#define mSCRIPT_DECLARE_STRUCT_OVERLOADED_VOID_METHOD(TYPE, NAME) \
|
||||
_mSCRIPT_DECLARE_STRUCT_OVERLOADED_METHOD(TYPE, NAME, S, 0, 0) \
|
||||
_mSCRIPT_DECLARE_STRUCT_OVERLOADED_METHOD_BINDING(TYPE, NAME, S)
|
||||
|
||||
#define mSCRIPT_DECLARE_STRUCT_OVERLOADED_C_METHOD(TYPE, RETURN, NAME) \
|
||||
_mSCRIPT_DECLARE_STRUCT_OVERLOADED_METHOD(TYPE, NAME, CS, 1, mSCRIPT_TYPE_MS_ ## RETURN) \
|
||||
_mSCRIPT_DECLARE_STRUCT_OVERLOADED_METHOD_BINDING(TYPE, NAME, CS)
|
||||
|
||||
#define mSCRIPT_DECLARE_STRUCT_OVERLOADED_VOID_C_METHOD(TYPE, NAME) \
|
||||
_mSCRIPT_DECLARE_STRUCT_OVERLOADED_METHOD(TYPE, NAME, CS, 0, 0) \
|
||||
_mSCRIPT_DECLARE_STRUCT_OVERLOADED_METHOD_BINDING(TYPE, NAME, CS)
|
||||
|
||||
#define mSCRIPT_DECLARE_STRUCT_D_METHOD(TYPE, RETURN, NAME, NPARAMS, ...) \
|
||||
mSCRIPT_DECLARE_STRUCT_METHOD(TYPE, RETURN, NAME, p0->NAME, NPARAMS, __VA_ARGS__)
|
||||
|
||||
|
@ -417,27 +467,39 @@ CXX_GUARD_START
|
|||
|
||||
#define mSCRIPT_DEFINE_DEFAULTS_END }
|
||||
|
||||
#define _mSCRIPT_DEFINE_STRUCT_BINDING(INIT_TYPE, TYPE, EXPORTED_NAME, NAME) { \
|
||||
#define mSCRIPT_DEFINE_STRUCT_METHOD_OVERLOADS(STRUCT, METHOD) \
|
||||
static const struct mScriptFunctionOverload _mSTStructBindingOverloads_ ## STRUCT ## _ ## METHOD[] = { \
|
||||
|
||||
#define mSCRIPT_DEFINE_STRUCT_METHOD_OVERLOAD(TYPE, FUNCTION) { \
|
||||
.type = &_mSTStructBindingType_ ## TYPE ## _ ## FUNCTION, \
|
||||
.function = &_mSTStructBindingFunction_ ## TYPE ## _ ## FUNCTION \
|
||||
},
|
||||
|
||||
#define mSCRIPT_DEFINE_OVERLOADS_END { NULL, NULL } }
|
||||
|
||||
#define _mSCRIPT_DEFINE_STRUCT_BINDING(INIT_TYPE, TYPE, EXPORTED_NAME, NAME, OVERLOADS) { \
|
||||
.type = mSCRIPT_CLASS_INIT_ ## INIT_TYPE, \
|
||||
.info = { \
|
||||
.member = { \
|
||||
.name = #EXPORTED_NAME, \
|
||||
.type = &_mSTStructBindingType_ ## TYPE ## _ ## NAME \
|
||||
.type = &_mSTStructBindingType_ ## TYPE ## _ ## NAME, \
|
||||
.overloads = OVERLOADS, \
|
||||
} \
|
||||
}, \
|
||||
},
|
||||
|
||||
#define mSCRIPT_DEFINE_STRUCT_METHOD_NAMED(TYPE, EXPORTED_NAME, NAME) \
|
||||
_mSCRIPT_DEFINE_STRUCT_BINDING(INSTANCE_MEMBER, TYPE, EXPORTED_NAME, NAME)
|
||||
_mSCRIPT_DEFINE_STRUCT_BINDING(INSTANCE_MEMBER, TYPE, EXPORTED_NAME, NAME, NULL)
|
||||
|
||||
#define mSCRIPT_DEFINE_STRUCT_METHOD(TYPE, NAME) mSCRIPT_DEFINE_STRUCT_METHOD_NAMED(TYPE, NAME, NAME)
|
||||
#define mSCRIPT_DEFINE_STRUCT_OVERLOADED_METHOD(TYPE, NAME) _mSCRIPT_DEFINE_STRUCT_BINDING(INSTANCE_MEMBER, TYPE, NAME, NAME, _mSTStructBindingOverloads_ ## TYPE ## _ ## NAME)
|
||||
|
||||
#define mSCRIPT_DEFINE_STRUCT_INIT(TYPE) _mSCRIPT_DEFINE_STRUCT_BINDING(INIT, TYPE, _init, _init)
|
||||
#define mSCRIPT_DEFINE_STRUCT_INIT_NAMED(TYPE, NAME) _mSCRIPT_DEFINE_STRUCT_BINDING(INIT, TYPE, _init, NAME)
|
||||
#define mSCRIPT_DEFINE_STRUCT_DEINIT(TYPE) _mSCRIPT_DEFINE_STRUCT_BINDING(DEINIT, TYPE, _deinit, _deinit)
|
||||
#define mSCRIPT_DEFINE_STRUCT_DEINIT_NAMED(TYPE, NAME) _mSCRIPT_DEFINE_STRUCT_BINDING(DEINIT, TYPE, _deinit, NAME)
|
||||
#define mSCRIPT_DEFINE_STRUCT_DEFAULT_GET(TYPE) _mSCRIPT_DEFINE_STRUCT_BINDING(GET, TYPE, _get, _get)
|
||||
#define mSCRIPT_DEFINE_STRUCT_DEFAULT_SET(TYPE, SETTER) _mSCRIPT_DEFINE_STRUCT_BINDING(SET, TYPE, SETTER, SETTER)
|
||||
#define mSCRIPT_DEFINE_STRUCT_INIT(TYPE) _mSCRIPT_DEFINE_STRUCT_BINDING(INIT, TYPE, _init, _init, NULL)
|
||||
#define mSCRIPT_DEFINE_STRUCT_INIT_NAMED(TYPE, NAME) _mSCRIPT_DEFINE_STRUCT_BINDING(INIT, TYPE, _init, NAME, NULL)
|
||||
#define mSCRIPT_DEFINE_STRUCT_DEINIT(TYPE) _mSCRIPT_DEFINE_STRUCT_BINDING(DEINIT, TYPE, _deinit, _deinit, NULL)
|
||||
#define mSCRIPT_DEFINE_STRUCT_DEINIT_NAMED(TYPE, NAME) _mSCRIPT_DEFINE_STRUCT_BINDING(DEINIT, TYPE, _deinit, NAME, NULL)
|
||||
#define mSCRIPT_DEFINE_STRUCT_DEFAULT_GET(TYPE) _mSCRIPT_DEFINE_STRUCT_BINDING(GET, TYPE, _get, _get, NULL)
|
||||
#define mSCRIPT_DEFINE_STRUCT_DEFAULT_SET(TYPE, SETTER) _mSCRIPT_DEFINE_STRUCT_BINDING(SET, TYPE, SETTER, SETTER, NULL)
|
||||
|
||||
#define mSCRIPT_DEFINE_DOC_STRUCT_METHOD(SCOPE, TYPE, NAME) mSCRIPT_DEFINE_STRUCT_METHOD_NAMED(doc_ ## TYPE, NAME, NAME)
|
||||
|
||||
|
|
|
@ -259,6 +259,7 @@ struct mScriptClassMember {
|
|||
const char* name;
|
||||
const char* docstring;
|
||||
const struct mScriptType* type;
|
||||
const struct mScriptFunctionOverload* overloads;
|
||||
size_t offset;
|
||||
bool readonly;
|
||||
};
|
||||
|
@ -275,6 +276,7 @@ struct mScriptClassInitDetails {
|
|||
const struct mScriptType* parent;
|
||||
struct mScriptClassMember member;
|
||||
struct mScriptClassCastMember castMember;
|
||||
const struct mScriptFunctionOverload* overload;
|
||||
} info;
|
||||
};
|
||||
|
||||
|
@ -332,6 +334,11 @@ struct mScriptFunction {
|
|||
void* context;
|
||||
};
|
||||
|
||||
struct mScriptFunctionOverload {
|
||||
const struct mScriptType* type;
|
||||
const struct mScriptFunction* function;
|
||||
};
|
||||
|
||||
struct mScriptValue* mScriptValueAlloc(const struct mScriptType* type);
|
||||
void mScriptValueRef(struct mScriptValue* val);
|
||||
void mScriptValueDeref(struct mScriptValue* val);
|
||||
|
@ -385,7 +392,8 @@ 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);
|
||||
bool mScriptCoerceFrame(const struct mScriptTypeTuple* types, struct mScriptList* frame);
|
||||
bool mScriptCoerceFrame(const struct mScriptTypeTuple* types, const struct mScriptList* input, struct mScriptList* output);
|
||||
const struct mScriptFunctionOverload* mScriptFunctionFindOverload(const struct mScriptFunctionOverload* overloads, struct mScriptList* frame);
|
||||
|
||||
CXX_GUARD_END
|
||||
|
||||
|
|
|
@ -481,7 +481,7 @@ bool mScriptInvoke(const struct mScriptValue* val, struct mScriptFrame* frame) {
|
|||
return false;
|
||||
}
|
||||
const struct mScriptTypeFunction* signature = &val->type->details.function;
|
||||
if (!mScriptCoerceFrame(&signature->parameters, &frame->arguments)) {
|
||||
if (!mScriptCoerceFrame(&signature->parameters, &frame->arguments, &frame->arguments)) {
|
||||
return false;
|
||||
}
|
||||
const struct mScriptFunction* fn = val->value.opaque;
|
||||
|
|
|
@ -35,20 +35,28 @@ struct mScriptInputContext {
|
|||
};
|
||||
|
||||
static void _mScriptInputDeinit(struct mScriptInputContext*);
|
||||
static bool _mScriptInputIsKeyActive(const struct mScriptInputContext*, struct mScriptValue*);
|
||||
static bool _mScriptInputIsKeyActiveStr(const struct mScriptInputContext*, const char*);
|
||||
static bool _mScriptInputIsKeyActiveNum(const struct mScriptInputContext*, uint32_t);
|
||||
static struct mScriptValue* _mScriptInputActiveKeys(const struct mScriptInputContext*);
|
||||
|
||||
mSCRIPT_DECLARE_STRUCT(mScriptInputContext);
|
||||
mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mScriptInputContext, _deinit, _mScriptInputDeinit, 0);
|
||||
mSCRIPT_DECLARE_STRUCT_C_METHOD(mScriptInputContext, BOOL, isKeyActive, _mScriptInputIsKeyActive, 1, WRAPPER, key);
|
||||
mSCRIPT_DECLARE_STRUCT_C_METHOD(mScriptInputContext, BOOL, isKeyActiveStr, _mScriptInputIsKeyActiveStr, 1, CHARP, key);
|
||||
mSCRIPT_DECLARE_STRUCT_C_METHOD(mScriptInputContext, BOOL, isKeyActiveNum, _mScriptInputIsKeyActiveNum, 1, U32, key);
|
||||
mSCRIPT_DECLARE_STRUCT_OVERLOADED_C_METHOD(mScriptInputContext, BOOL, isKeyActive);
|
||||
mSCRIPT_DECLARE_STRUCT_C_METHOD(mScriptInputContext, WLIST, activeKeys, _mScriptInputActiveKeys, 0);
|
||||
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD_OVERLOADS(mScriptInputContext, isKeyActive)
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD_OVERLOAD(mScriptInputContext, isKeyActiveStr)
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD_OVERLOAD(mScriptInputContext, isKeyActiveNum)
|
||||
mSCRIPT_DEFINE_OVERLOADS_END;
|
||||
|
||||
mSCRIPT_DEFINE_STRUCT(mScriptInputContext)
|
||||
mSCRIPT_DEFINE_STRUCT_DEINIT(mScriptInputContext)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Sequence number of the next event to be emitted")
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(mScriptInputContext, U64, seq)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Check if a given keyboard key is currently held. The input can be either the printable character for a key, the numerical Unicode codepoint, or a special value from C.KEY")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mScriptInputContext, isKeyActive)
|
||||
mSCRIPT_DEFINE_STRUCT_OVERLOADED_METHOD(mScriptInputContext, isKeyActive)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Get a list of the currently active keys. The values are Unicode codepoints or special key values from C.KEY, not strings, so make sure to convert as needed")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mScriptInputContext, activeKeys)
|
||||
mSCRIPT_DEFINE_DOCSTRING("The currently active gamepad, if any")
|
||||
|
@ -319,33 +327,18 @@ void _mScriptInputDeinit(struct mScriptInputContext* context) {
|
|||
TableDeinit(&context->activeKeys);
|
||||
}
|
||||
|
||||
bool _mScriptInputIsKeyActive(const struct mScriptInputContext* context, struct mScriptValue* value) {
|
||||
bool _mScriptInputIsKeyActiveStr(const struct mScriptInputContext* context, const char* value) {
|
||||
uint32_t key;
|
||||
struct mScriptValue intValue;
|
||||
size_t length;
|
||||
const char* strbuf;
|
||||
|
||||
switch (value->type->base) {
|
||||
case mSCRIPT_TYPE_SINT:
|
||||
case mSCRIPT_TYPE_UINT:
|
||||
case mSCRIPT_TYPE_FLOAT:
|
||||
if (!mScriptCast(mSCRIPT_TYPE_MS_U32, value, &intValue)) {
|
||||
return false;
|
||||
}
|
||||
key = intValue.value.u32;
|
||||
break;
|
||||
case mSCRIPT_TYPE_STRING:
|
||||
if (value->value.string->length > 1) {
|
||||
return false;
|
||||
}
|
||||
strbuf = value->value.string->buffer;
|
||||
length = value->value.string->size;
|
||||
key = utf8Char(&strbuf, &length);
|
||||
break;
|
||||
default:
|
||||
size_t length = strlen(value);
|
||||
key = utf8Char(&value, &length);
|
||||
if (length > 0) {
|
||||
return false;
|
||||
}
|
||||
void* down = TableLookup(&context->activeKeys, key);
|
||||
return down != NULL;
|
||||
}
|
||||
|
||||
bool _mScriptInputIsKeyActiveNum(const struct mScriptInputContext* context, uint32_t key) {
|
||||
void* down = TableLookup(&context->activeKeys, key);
|
||||
return down != NULL;
|
||||
}
|
||||
|
|
|
@ -57,6 +57,11 @@ struct TestH {
|
|||
int32_t j;
|
||||
};
|
||||
|
||||
struct TestI {
|
||||
uint32_t num;
|
||||
const char* str;
|
||||
};
|
||||
|
||||
static int32_t testAi0(struct TestA* a) {
|
||||
return a->i;
|
||||
}
|
||||
|
@ -114,6 +119,14 @@ static void testSetC(struct TestG* g, const char* name, const char* val) {
|
|||
g->c = val;
|
||||
}
|
||||
|
||||
static void callNum(struct TestI* i, uint32_t num) {
|
||||
i->num = num;
|
||||
}
|
||||
|
||||
static void callStr(struct TestI* i, const char* str) {
|
||||
i->str = str;
|
||||
}
|
||||
|
||||
#define MEMBER_A_DOCSTRING "Member a"
|
||||
|
||||
mSCRIPT_DECLARE_STRUCT(TestA);
|
||||
|
@ -201,12 +214,25 @@ mSCRIPT_DEFINE_STRUCT(TestG)
|
|||
mSCRIPT_DEFINE_STRUCT_DEFAULT_SET(TestG, setC)
|
||||
mSCRIPT_DEFINE_END;
|
||||
|
||||
|
||||
mSCRIPT_DEFINE_STRUCT(TestH)
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(TestH, S32, i)
|
||||
mSCRIPT_DEFINE_STRUCT_CONST_MEMBER(TestH, S32, j)
|
||||
mSCRIPT_DEFINE_END;
|
||||
|
||||
mSCRIPT_DECLARE_STRUCT(TestI);
|
||||
mSCRIPT_DECLARE_STRUCT_VOID_METHOD(TestI, callStr, callStr, 1, CHARP, value);
|
||||
mSCRIPT_DECLARE_STRUCT_VOID_METHOD(TestI, callNum, callNum, 1, U32, value);
|
||||
mSCRIPT_DECLARE_STRUCT_OVERLOADED_VOID_METHOD(TestI, call);
|
||||
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD_OVERLOADS(TestI, call)
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD_OVERLOAD(TestI, callStr)
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD_OVERLOAD(TestI, callNum)
|
||||
mSCRIPT_DEFINE_OVERLOADS_END;
|
||||
|
||||
mSCRIPT_DEFINE_STRUCT(TestI)
|
||||
mSCRIPT_DEFINE_STRUCT_OVERLOADED_METHOD(TestI, call)
|
||||
mSCRIPT_DEFINE_END;
|
||||
|
||||
M_TEST_DEFINE(testALayout) {
|
||||
struct mScriptTypeClass* cls = mSCRIPT_TYPE_MS_S(TestA)->details.cls;
|
||||
assert_false(cls->init);
|
||||
|
@ -1184,6 +1210,44 @@ M_TEST_DEFINE(testHSet) {
|
|||
assert_false(cls->init);
|
||||
}
|
||||
|
||||
M_TEST_DEFINE(testOverloadsBasic) {
|
||||
struct mScriptTypeClass* cls = mSCRIPT_TYPE_MS_S(TestI)->details.cls;
|
||||
assert_false(cls->init);
|
||||
mScriptClassInit(cls);
|
||||
assert_true(cls->init);
|
||||
|
||||
struct TestI s = {
|
||||
.num = 0,
|
||||
.str = NULL,
|
||||
};
|
||||
|
||||
struct mScriptValue sval = mSCRIPT_MAKE_S(TestI, &s);
|
||||
struct mScriptValue fn;
|
||||
struct mScriptFrame frame;
|
||||
|
||||
assert_true(mScriptObjectGet(&sval, "call", &fn));
|
||||
|
||||
mScriptFrameInit(&frame);
|
||||
mSCRIPT_PUSH(&frame.arguments, S(TestI), &s);
|
||||
mSCRIPT_PUSH(&frame.arguments, U32, 1);
|
||||
assert_true(mScriptInvoke(&fn, &frame));
|
||||
mScriptFrameDeinit(&frame);
|
||||
assert_int_equal(s.num, 1);
|
||||
assert_null(s.str);
|
||||
|
||||
mScriptFrameInit(&frame);
|
||||
mSCRIPT_PUSH(&frame.arguments, S(TestI), &s);
|
||||
mSCRIPT_PUSH(&frame.arguments, CHARP, "called");
|
||||
assert_true(mScriptInvoke(&fn, &frame));
|
||||
mScriptFrameDeinit(&frame);
|
||||
assert_int_equal(s.num, 1);
|
||||
assert_string_equal(s.str, "called");
|
||||
|
||||
assert_true(cls->init);
|
||||
mScriptClassDeinit(cls);
|
||||
assert_false(cls->init);
|
||||
}
|
||||
|
||||
M_TEST_SUITE_DEFINE(mScriptClasses,
|
||||
cmocka_unit_test(testALayout),
|
||||
cmocka_unit_test(testASignatures),
|
||||
|
@ -1201,4 +1265,5 @@ M_TEST_SUITE_DEFINE(mScriptClasses,
|
|||
cmocka_unit_test(testFDeinit),
|
||||
cmocka_unit_test(testGSet),
|
||||
cmocka_unit_test(testHSet),
|
||||
cmocka_unit_test(testOverloadsBasic),
|
||||
)
|
||||
|
|
|
@ -172,6 +172,43 @@ M_TEST_DEFINE(clearKeys) {
|
|||
mScriptContextDeinit(&context);
|
||||
}
|
||||
|
||||
M_TEST_DEFINE(numericKeys) {
|
||||
SETUP_LUA;
|
||||
|
||||
TEST_PROGRAM("assert(not input:isKeyActive(C.KEY.F1))");
|
||||
|
||||
TEST_PROGRAM(
|
||||
"activeKey = false\n"
|
||||
"state = nil\n"
|
||||
"function cb(ev)\n"
|
||||
" assert(ev.type == C.EV_TYPE.KEY)\n"
|
||||
" activeKey = ev.key\n"
|
||||
" state = ev.state\n"
|
||||
"end\n"
|
||||
"id = callbacks:add('key', cb)\n"
|
||||
"assert(id)\n"
|
||||
"assert(not activeKey)\n"
|
||||
);
|
||||
|
||||
struct mScriptKeyEvent keyEvent = {
|
||||
.d = { .type = mSCRIPT_EV_TYPE_KEY },
|
||||
.state = mSCRIPT_INPUT_STATE_DOWN,
|
||||
.key = mSCRIPT_KEY_F1
|
||||
};
|
||||
mScriptContextFireEvent(&context, &keyEvent.d);
|
||||
|
||||
TEST_PROGRAM("assert(input:isKeyActive(C.KEY.F1))");
|
||||
TEST_PROGRAM("assert(activeKey == C.KEY.F1)");
|
||||
TEST_PROGRAM("assert(state == C.INPUT_STATE.DOWN)");
|
||||
|
||||
keyEvent.state = mSCRIPT_INPUT_STATE_UP;
|
||||
mScriptContextFireEvent(&context, &keyEvent.d);
|
||||
|
||||
TEST_PROGRAM("assert(not input:isKeyActive(C.KEY.F1))");
|
||||
TEST_PROGRAM("assert(state == C.INPUT_STATE.UP)");
|
||||
|
||||
mScriptContextDeinit(&context);
|
||||
}
|
||||
|
||||
M_TEST_DEFINE(gamepadExport) {
|
||||
SETUP_LUA;
|
||||
|
@ -219,5 +256,6 @@ M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(mScriptInput,
|
|||
cmocka_unit_test(fireKey),
|
||||
cmocka_unit_test(activeKeys),
|
||||
cmocka_unit_test(clearKeys),
|
||||
cmocka_unit_test(numericKeys),
|
||||
cmocka_unit_test(gamepadExport),
|
||||
)
|
||||
|
|
|
@ -372,25 +372,25 @@ M_TEST_DEFINE(wrongConst) {
|
|||
mScriptFrameInit(&frame);
|
||||
mSCRIPT_PUSH(&frame.arguments, S(Test), &a);
|
||||
signature.entries[0] = mSCRIPT_TYPE_MS_S(Test);
|
||||
assert_true(mScriptCoerceFrame(&signature, &frame.arguments));
|
||||
assert_true(mScriptCoerceFrame(&signature, &frame.arguments, &frame.arguments));
|
||||
mScriptFrameDeinit(&frame);
|
||||
|
||||
mScriptFrameInit(&frame);
|
||||
mSCRIPT_PUSH(&frame.arguments, CS(Test), &a);
|
||||
signature.entries[0] = mSCRIPT_TYPE_MS_CS(Test);
|
||||
assert_true(mScriptCoerceFrame(&signature, &frame.arguments));
|
||||
assert_true(mScriptCoerceFrame(&signature, &frame.arguments, &frame.arguments));
|
||||
mScriptFrameDeinit(&frame);
|
||||
|
||||
mScriptFrameInit(&frame);
|
||||
mSCRIPT_PUSH(&frame.arguments, S(Test), &a);
|
||||
signature.entries[0] = mSCRIPT_TYPE_MS_CS(Test);
|
||||
assert_true(mScriptCoerceFrame(&signature, &frame.arguments));
|
||||
assert_true(mScriptCoerceFrame(&signature, &frame.arguments, &frame.arguments));
|
||||
mScriptFrameDeinit(&frame);
|
||||
|
||||
mScriptFrameInit(&frame);
|
||||
mSCRIPT_PUSH(&frame.arguments, CS(Test), &a);
|
||||
signature.entries[0] = mSCRIPT_TYPE_MS_S(Test);
|
||||
assert_false(mScriptCoerceFrame(&signature, &frame.arguments));
|
||||
assert_false(mScriptCoerceFrame(&signature, &frame.arguments, &frame.arguments));
|
||||
mScriptFrameDeinit(&frame);
|
||||
|
||||
mScriptFrameInit(&frame);
|
||||
|
@ -402,7 +402,7 @@ M_TEST_DEFINE(wrongConst) {
|
|||
mSCRIPT_PUSH(&frame.arguments, S(Test), &a);
|
||||
assert_false(mScriptPopCSTest(&frame.arguments, &cb));
|
||||
signature.entries[0] = mSCRIPT_TYPE_MS_CS(Test);
|
||||
assert_true(mScriptCoerceFrame(&signature, &frame.arguments));
|
||||
assert_true(mScriptCoerceFrame(&signature, &frame.arguments, &frame.arguments));
|
||||
assert_true(mScriptPopCSTest(&frame.arguments, &cb));
|
||||
mScriptFrameDeinit(&frame);
|
||||
|
||||
|
@ -410,7 +410,7 @@ M_TEST_DEFINE(wrongConst) {
|
|||
mSCRIPT_PUSH(&frame.arguments, CS(Test), &a);
|
||||
assert_false(mScriptPopSTest(&frame.arguments, &b));
|
||||
signature.entries[0] = mSCRIPT_TYPE_MS_S(Test);
|
||||
assert_false(mScriptCoerceFrame(&signature, &frame.arguments));
|
||||
assert_false(mScriptCoerceFrame(&signature, &frame.arguments, &frame.arguments));
|
||||
assert_false(mScriptPopSTest(&frame.arguments, &b));
|
||||
mScriptFrameDeinit(&frame);
|
||||
|
||||
|
|
|
@ -1238,6 +1238,9 @@ static void _mScriptClassInit(struct mScriptTypeClass* cls, const struct mScript
|
|||
member->docstring = docstring;
|
||||
docstring = NULL;
|
||||
}
|
||||
if (detail->info.member.type->base != mSCRIPT_TYPE_FUNCTION) {
|
||||
abort();
|
||||
}
|
||||
if (detail->info.member.type->details.function.parameters.count != 3) {
|
||||
abort();
|
||||
}
|
||||
|
@ -1773,21 +1776,24 @@ bool mScriptCast(const struct mScriptType* type, const struct mScriptValue* inpu
|
|||
return false;
|
||||
}
|
||||
|
||||
bool mScriptCoerceFrame(const struct mScriptTypeTuple* types, struct mScriptList* frame) {
|
||||
if (types->count < mScriptListSize(frame) && !types->variable) {
|
||||
bool mScriptCoerceFrame(const struct mScriptTypeTuple* types, const struct mScriptList* input, struct mScriptList* output) {
|
||||
if (types->count < mScriptListSize(input) && !types->variable) {
|
||||
return false;
|
||||
}
|
||||
if (types->count > mScriptListSize(frame) && !types->variable && !types->defaults) {
|
||||
if (types->count > mScriptListSize(input) && !types->variable && !types->defaults) {
|
||||
return false;
|
||||
}
|
||||
if (output) {
|
||||
mScriptListResize(output, mScriptListSize(input) - mScriptListSize(output));
|
||||
}
|
||||
size_t i;
|
||||
for (i = 0; i < mScriptListSize(frame) && i < types->count; ++i) {
|
||||
if (types->entries[i] == mScriptListGetPointer(frame, i)->type) {
|
||||
for (i = 0; i < mScriptListSize(input) && i < types->count; ++i) {
|
||||
if (types->entries[i] == mScriptListGetConstPointer(input, i)->type) {
|
||||
continue;
|
||||
}
|
||||
struct mScriptValue* unwrapped = NULL;
|
||||
if (mScriptListGetPointer(frame, i)->type->base == mSCRIPT_TYPE_WRAPPER) {
|
||||
unwrapped = mScriptValueUnwrap(mScriptListGetPointer(frame, i));
|
||||
const struct mScriptValue* unwrapped = NULL;
|
||||
if (mScriptListGetConstPointer(input, i)->type->base == mSCRIPT_TYPE_WRAPPER) {
|
||||
unwrapped = mScriptValueUnwrapConst(mScriptListGetConstPointer(input, i));
|
||||
if (types->entries[i]->base == mSCRIPT_TYPE_WRAPPER) {
|
||||
if (types->entries[i]->details.type == unwrapped->type) {
|
||||
continue;
|
||||
|
@ -1796,7 +1802,12 @@ bool mScriptCoerceFrame(const struct mScriptTypeTuple* types, struct mScriptList
|
|||
continue;
|
||||
}
|
||||
}
|
||||
if (!mScriptCast(types->entries[i], mScriptListGetPointer(frame, i), mScriptListGetPointer(frame, i))) {
|
||||
struct mScriptValue fakeVal;
|
||||
struct mScriptValue* castTo = &fakeVal;
|
||||
if (output) {
|
||||
castTo = mScriptListGetPointer(output, i);
|
||||
}
|
||||
if (!mScriptCast(types->entries[i], mScriptListGetConstPointer(input, i), castTo)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1808,11 +1819,26 @@ bool mScriptCoerceFrame(const struct mScriptTypeTuple* types, struct mScriptList
|
|||
if (!types->defaults[i].type) {
|
||||
return false;
|
||||
}
|
||||
memcpy(mScriptListAppend(frame), &types->defaults[i], sizeof(struct mScriptValue));
|
||||
if (output) {
|
||||
memcpy(mScriptListAppend(output), &types->defaults[i], sizeof(struct mScriptValue));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const struct mScriptFunctionOverload* mScriptFunctionFindOverload(const struct mScriptFunctionOverload* overloads, struct mScriptList* frame) {
|
||||
size_t i;
|
||||
for (i = 0; overloads[i].type; ++i) {
|
||||
if (overloads[i].type->base != mSCRIPT_TYPE_FUNCTION) {
|
||||
continue;
|
||||
}
|
||||
if (mScriptCoerceFrame(&overloads[i].type->details.function.parameters, frame, NULL)) {
|
||||
return &overloads[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void addTypesFromTuple(struct Table* types, const struct mScriptTypeTuple* tuple) {
|
||||
size_t i;
|
||||
for (i = 0; i < tuple->count; ++i) {
|
||||
|
|
|
@ -190,6 +190,14 @@ void explainClass(struct mScriptTypeClass* cls, int level) {
|
|||
fprintf(out, "%s readonly: true\n", indent);
|
||||
}
|
||||
fprintf(out, "%s type: %s\n", indent, details->info.member.type->name);
|
||||
if (details->info.member.overloads) {
|
||||
fprintf(out, "%s overloads:\n", indent);
|
||||
size_t i;
|
||||
for (i = 0; details->info.member.overloads[i].type; ++i) {
|
||||
mScriptTypeAdd(&types, details->info.member.overloads[i].type);
|
||||
fprintf(out, "%s - %s\n", indent, details->info.member.overloads[i].type->name);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case mSCRIPT_CLASS_INIT_END:
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue