mirror of
https://github.com/CPunch/Cosmo.git
synced 2024-11-05 08:10:05 +00:00
CObjMethod refactor
This commit is contained in:
parent
e6a377dfd0
commit
aaed92424f
18
examples/stress.cosmo
Normal file
18
examples/stress.cosmo
Normal 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
|
@ -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;
|
||||
}
|
||||
|
13
src/cobj.c
13
src/cobj.c
@ -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: {
|
||||
|
@ -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 {
|
||||
|
37
src/cvm.c
37
src/cvm.c
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user