CObjMethod refactor

This commit is contained in:
CPunch 2020-11-17 15:07:56 -06:00
parent e6a377dfd0
commit aaed92424f
5 changed files with 40 additions and 36 deletions

18
examples/stress.cosmo Normal file
View File

@ -0,0 +1,18 @@
class Test
function __init(self, x)
self.x = x
end
function print(self)
print(self.x)
end
end
-- stressing the GC
local i = 0
while true do
var x = Test("Hello world " .. i)
x.print()
i = i + 1
end

View File

@ -111,7 +111,7 @@ void blackenObject(CState *state, CObj *obj) {
}
case COBJ_METHOD: {
CObjMethod *method = (CObjMethod*)obj;
markObject(state, (CObj*)method->closure);
markValue(state, method->func);
markObject(state, (CObj*)method->obj);
break;
}

View File

@ -123,17 +123,15 @@ CObjCFunction *cosmoO_newCFunction(CState *state, CosmoCFunction func) {
CObjMethod *cosmoO_newCMethod(CState *state, CObjCFunction *func, CObjObject *obj) {
CObjMethod *method = (CObjMethod*)cosmoO_allocateBase(state, sizeof(CObjMethod), COBJ_METHOD);
method->cfunc = func;
method->func = cosmoV_newObj(func);
method->obj = obj;
method->isCFunc = true;
return method;
}
CObjMethod *cosmoO_newMethod(CState *state, CObjClosure *func, CObjObject *obj) {
CObjMethod *method = (CObjMethod*)cosmoO_allocateBase(state, sizeof(CObjMethod), COBJ_METHOD);
method->closure = func;
method->func = cosmoV_newObj(func);
method->obj = obj;
method->isCFunc = false;
return method;
}
@ -297,11 +295,8 @@ void printObject(CObj *o) {
}
case COBJ_METHOD: {
CObjMethod *method = (CObjMethod*)o;
if (method->closure->function->name != NULL) {
printf("<method> %p : %.*s", method->obj, method->closure->function->name->length, method->closure->function->name->str);
} else {
printf("<method> %p : %s", method->obj, UNNAMEDCHUNK);
}
printf("<method> %p : ", method->obj);
printValue(method->func);
break;
}
case COBJ_CLOSURE: {

View File

@ -71,11 +71,7 @@ typedef struct CObjClosure {
typedef struct CObjMethod {
CommonHeader; // "is a " CObj
CObjObject *obj; // obj this method is bound too
union {
CObjClosure *closure;
CObjCFunction *cfunc;
};
bool isCFunc;
CValue func;
} CObjMethod;
typedef struct CObjUpval {

View File

@ -149,12 +149,17 @@ bool call(CState *state, CObjClosure *closure, int args, int offset) {
return true;
}
bool callMethod(CState* state, CObjMethod *method, int args) {
if (method->isCFunc) {
callCFunction(state, method->cfunc->cfunc, args+1, 1);
bool invokeMethod(CState* state, CObjObject *obj, CValue func, int args) {
// first, set the first argument to the object
StkPtr temp = cosmoV_getTop(state, args);
*temp = cosmoV_newObj(obj);
if (IS_CFUNCTION(func)) {
callCFunction(state, cosmoV_readCFunction(func), args+1, 1);
} else if (IS_CLOSURE(func)) {
call(state, cosmoV_readClosure(func), args+1, 1); // offset = 1 so our stack is properly reset
} else {
CObjClosure *closure = method->closure;
call(state, closure, args+1, 1); // offset = 1 so our stack is properly reset
cosmoV_error(state, "Cannot call non-function value!");
}
return true;
@ -179,30 +184,27 @@ COSMOVMRESULT cosmoV_call(CState *state, int args) {
}
case COBJ_METHOD: {
CObjMethod *method = (CObjMethod*)val->val.obj;
*val = cosmoV_newObj(method->obj); // sets the object on the stack so the function can reference it in it's first argument
callMethod(state, method, args);
invokeMethod(state, method->obj, method->func, args);
break;
}
case COBJ_OBJECT: {
CObjObject *protoObj = (CObjObject*)val->val.obj;
CObjObject *newObj = cosmoO_newObject(state);
newObj->proto = protoObj;
*val = cosmoV_newObj(newObj);
CValue ret;
// check if they defined an initalizer
if (cosmoV_getObject(state, protoObj, cosmoV_newObj(state->iStrings[ISTRING_INIT]), &ret) && IS_METHOD(ret)) {
callMethod(state, cosmoV_readMethod(ret), args);
cosmoV_pop(state);
if (cosmoO_getIString(state, protoObj, ISTRING_INIT, &ret)) {
invokeMethod(state, newObj, ret, args);
} else {
// no default initalizer
if (args != 0) {
cosmoV_error(state, "Expected 0 parameters, got %d!", args);
return COSMOVM_RUNTIME_ERR;
}
state->top--;
}
cosmoV_pop(state); // pops the return value, it's unused
cosmoV_pushValue(state, cosmoV_newObj(newObj));
break;
}
@ -443,15 +445,8 @@ bool cosmoV_execute(CState *state) {
cosmoO_getObject(state, object, *key, &val); // we use cosmoO_getObject instead of the cosmoV_getObject wrapper so we get the raw value from the object instead of the CObjMethod wrapper
// now set the key stack location to the object, and call it!
*key = *temp;
if (IS_CLOSURE(val)) {
call(state, cosmoV_readClosure(val), args+1, 1);
} else if (IS_CFUNCTION(val)) {
callCFunction(state, cosmoV_readCFunction(val), args+1, 1);
} else {
cosmoV_error(state, "Cannot call non-function value! got %d", val.val.obj->type);
}
// now invoke the method!
invokeMethod(state, object, val, args);
// moves return value & resets stack (key now points to the stack location of our return value)
*temp = *key;