mirror of
https://github.com/CPunch/Cosmo.git
synced 2024-11-21 23:10:05 +00:00
Added '__equal' metamethod, slightly refactored cosmoO_equal
- ISTRING_EQUAL has been added
This commit is contained in:
parent
3890c9dd1e
commit
c83dca2ab2
35
src/cobj.c
35
src/cobj.c
@ -35,7 +35,7 @@ CObj *cosmoO_allocateBase(CState *state, size_t sz, CObjType type) {
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cosmoO_free(CState *state, CObj* obj) {
|
void cosmoO_free(CState *state, CObj *obj) {
|
||||||
#ifdef GC_DEBUG
|
#ifdef GC_DEBUG
|
||||||
printf("freeing %p [", obj);
|
printf("freeing %p [", obj);
|
||||||
printObject(obj);
|
printObject(obj);
|
||||||
@ -95,10 +95,14 @@ void cosmoO_free(CState *state, CObj* obj) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cosmoO_equal(CState *state, CObj* obj1, CObj* obj2) {
|
bool cosmoO_equal(CState *state, CObj *obj1, CObj *obj2) {
|
||||||
if (obj1 == obj2) // its the same object, this compares strings for us since they're interned anyways :)
|
CObjObject *proto1, *proto2;
|
||||||
|
CValue eq1, eq2;
|
||||||
|
|
||||||
|
if (obj1 == obj2) // its the same reference, this compares strings for us since they're interned anyways :)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
// its not the same type, maybe both <ref>'s have the same '__equal' metamethod in their protos?
|
||||||
if (obj1->type != obj2->type)
|
if (obj1->type != obj2->type)
|
||||||
goto _eqFail;
|
goto _eqFail;
|
||||||
|
|
||||||
@ -130,7 +134,30 @@ bool cosmoO_equal(CState *state, CObj* obj1, CObj* obj2) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_eqFail:
|
_eqFail:
|
||||||
// TODO: add support for an '__equal' metamethod
|
// this is pretty expensive (bad lookup caching helps a lot), but it only all gets run if both objects have protos & both have the `__equal` metamethod defined so...
|
||||||
|
// it should stay light for the majority of cases
|
||||||
|
if ((proto1 = cosmoO_grabProto(obj1)) != NULL && (proto2 = cosmoO_grabProto(obj2)) != NULL && // make sure both protos exist
|
||||||
|
cosmoO_getIString(state, proto1, ISTRING_EQUAL, &eq1) && // grab the `__equal` metamethod from the first proto, if fail abort
|
||||||
|
cosmoO_getIString(state, proto2, ISTRING_EQUAL, &eq2) && // grab the `__equal` metamethod from the second proto, if fail abort
|
||||||
|
cosmoV_equal(state, eq1, eq2)) { // compare the two `__equal` metamethods
|
||||||
|
|
||||||
|
// now finally, call the `__equal` metamethod (<object>, <object>)
|
||||||
|
cosmoV_pushValue(state, eq1);
|
||||||
|
cosmoV_pushRef(state, obj1);
|
||||||
|
cosmoV_pushRef(state, obj2);
|
||||||
|
if (cosmoV_call(state, 2, 1) != COSMOVM_OK)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// check return value and make sure it's a boolean
|
||||||
|
if (!IS_BOOLEAN(*cosmoV_getTop(state, 0))) {
|
||||||
|
cosmoV_error(state, "__equal expected to return <boolean>, got %s!", cosmoV_typeStr(*cosmoV_pop(state)));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return the result
|
||||||
|
return cosmoV_readBoolean(*cosmoV_pop(state));
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,6 +50,7 @@ CState *cosmoV_newState() {
|
|||||||
state->iStrings[ISTRING_TOSTRING] = cosmoO_copyString(state, "__tostring", 10);
|
state->iStrings[ISTRING_TOSTRING] = cosmoO_copyString(state, "__tostring", 10);
|
||||||
state->iStrings[ISTRING_TONUMBER] = cosmoO_copyString(state, "__tonumber", 10);
|
state->iStrings[ISTRING_TONUMBER] = cosmoO_copyString(state, "__tonumber", 10);
|
||||||
state->iStrings[ISTRING_INDEX] = cosmoO_copyString(state, "__index", 7);
|
state->iStrings[ISTRING_INDEX] = cosmoO_copyString(state, "__index", 7);
|
||||||
|
state->iStrings[ISTRING_EQUAL] = cosmoO_copyString(state, "__equal", 7);
|
||||||
state->iStrings[ISTRING_NEWINDEX] = cosmoO_copyString(state, "__newindex", 10);
|
state->iStrings[ISTRING_NEWINDEX] = cosmoO_copyString(state, "__newindex", 10);
|
||||||
state->iStrings[ISTRING_COUNT] = cosmoO_copyString(state, "__count", 7);
|
state->iStrings[ISTRING_COUNT] = cosmoO_copyString(state, "__count", 7);
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ typedef enum IStringEnum {
|
|||||||
ISTRING_INIT, // __init
|
ISTRING_INIT, // __init
|
||||||
ISTRING_TOSTRING, // __tostring
|
ISTRING_TOSTRING, // __tostring
|
||||||
ISTRING_TONUMBER, // __tonumber
|
ISTRING_TONUMBER, // __tonumber
|
||||||
|
ISTRING_EQUAL, // __equals
|
||||||
ISTRING_INDEX, // __index
|
ISTRING_INDEX, // __index
|
||||||
ISTRING_NEWINDEX, // __newindex
|
ISTRING_NEWINDEX, // __newindex
|
||||||
ISTRING_COUNT, // __count
|
ISTRING_COUNT, // __count
|
||||||
|
Loading…
Reference in New Issue
Block a user