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: {
|
case COBJ_METHOD: {
|
||||||
CObjMethod *method = (CObjMethod*)obj;
|
CObjMethod *method = (CObjMethod*)obj;
|
||||||
markObject(state, (CObj*)method->closure);
|
markValue(state, method->func);
|
||||||
markObject(state, (CObj*)method->obj);
|
markObject(state, (CObj*)method->obj);
|
||||||
break;
|
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 *cosmoO_newCMethod(CState *state, CObjCFunction *func, CObjObject *obj) {
|
||||||
CObjMethod *method = (CObjMethod*)cosmoO_allocateBase(state, sizeof(CObjMethod), COBJ_METHOD);
|
CObjMethod *method = (CObjMethod*)cosmoO_allocateBase(state, sizeof(CObjMethod), COBJ_METHOD);
|
||||||
method->cfunc = func;
|
method->func = cosmoV_newObj(func);
|
||||||
method->obj = obj;
|
method->obj = obj;
|
||||||
method->isCFunc = true;
|
|
||||||
return method;
|
return method;
|
||||||
}
|
}
|
||||||
|
|
||||||
CObjMethod *cosmoO_newMethod(CState *state, CObjClosure *func, CObjObject *obj) {
|
CObjMethod *cosmoO_newMethod(CState *state, CObjClosure *func, CObjObject *obj) {
|
||||||
CObjMethod *method = (CObjMethod*)cosmoO_allocateBase(state, sizeof(CObjMethod), COBJ_METHOD);
|
CObjMethod *method = (CObjMethod*)cosmoO_allocateBase(state, sizeof(CObjMethod), COBJ_METHOD);
|
||||||
method->closure = func;
|
method->func = cosmoV_newObj(func);
|
||||||
method->obj = obj;
|
method->obj = obj;
|
||||||
method->isCFunc = false;
|
|
||||||
return method;
|
return method;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,11 +295,8 @@ void printObject(CObj *o) {
|
|||||||
}
|
}
|
||||||
case COBJ_METHOD: {
|
case COBJ_METHOD: {
|
||||||
CObjMethod *method = (CObjMethod*)o;
|
CObjMethod *method = (CObjMethod*)o;
|
||||||
if (method->closure->function->name != NULL) {
|
printf("<method> %p : ", method->obj);
|
||||||
printf("<method> %p : %.*s", method->obj, method->closure->function->name->length, method->closure->function->name->str);
|
printValue(method->func);
|
||||||
} else {
|
|
||||||
printf("<method> %p : %s", method->obj, UNNAMEDCHUNK);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case COBJ_CLOSURE: {
|
case COBJ_CLOSURE: {
|
||||||
|
@ -71,11 +71,7 @@ typedef struct CObjClosure {
|
|||||||
typedef struct CObjMethod {
|
typedef struct CObjMethod {
|
||||||
CommonHeader; // "is a " CObj
|
CommonHeader; // "is a " CObj
|
||||||
CObjObject *obj; // obj this method is bound too
|
CObjObject *obj; // obj this method is bound too
|
||||||
union {
|
CValue func;
|
||||||
CObjClosure *closure;
|
|
||||||
CObjCFunction *cfunc;
|
|
||||||
};
|
|
||||||
bool isCFunc;
|
|
||||||
} CObjMethod;
|
} CObjMethod;
|
||||||
|
|
||||||
typedef struct CObjUpval {
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool callMethod(CState* state, CObjMethod *method, int args) {
|
bool invokeMethod(CState* state, CObjObject *obj, CValue func, int args) {
|
||||||
if (method->isCFunc) {
|
// first, set the first argument to the object
|
||||||
callCFunction(state, method->cfunc->cfunc, args+1, 1);
|
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 {
|
} else {
|
||||||
CObjClosure *closure = method->closure;
|
cosmoV_error(state, "Cannot call non-function value!");
|
||||||
call(state, closure, args+1, 1); // offset = 1 so our stack is properly reset
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -179,30 +184,27 @@ COSMOVMRESULT cosmoV_call(CState *state, int args) {
|
|||||||
}
|
}
|
||||||
case COBJ_METHOD: {
|
case COBJ_METHOD: {
|
||||||
CObjMethod *method = (CObjMethod*)val->val.obj;
|
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
|
invokeMethod(state, method->obj, method->func, args);
|
||||||
callMethod(state, method, args);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case COBJ_OBJECT: {
|
case COBJ_OBJECT: {
|
||||||
CObjObject *protoObj = (CObjObject*)val->val.obj;
|
CObjObject *protoObj = (CObjObject*)val->val.obj;
|
||||||
CObjObject *newObj = cosmoO_newObject(state);
|
CObjObject *newObj = cosmoO_newObject(state);
|
||||||
newObj->proto = protoObj;
|
newObj->proto = protoObj;
|
||||||
*val = cosmoV_newObj(newObj);
|
|
||||||
CValue ret;
|
CValue ret;
|
||||||
|
|
||||||
// check if they defined an initalizer
|
// check if they defined an initalizer
|
||||||
if (cosmoV_getObject(state, protoObj, cosmoV_newObj(state->iStrings[ISTRING_INIT]), &ret) && IS_METHOD(ret)) {
|
if (cosmoO_getIString(state, protoObj, ISTRING_INIT, &ret)) {
|
||||||
callMethod(state, cosmoV_readMethod(ret), args);
|
invokeMethod(state, newObj, ret, args);
|
||||||
cosmoV_pop(state);
|
|
||||||
} else {
|
} else {
|
||||||
// no default initalizer
|
// no default initalizer
|
||||||
if (args != 0) {
|
if (args != 0) {
|
||||||
cosmoV_error(state, "Expected 0 parameters, got %d!", args);
|
cosmoV_error(state, "Expected 0 parameters, got %d!", args);
|
||||||
return COSMOVM_RUNTIME_ERR;
|
return COSMOVM_RUNTIME_ERR;
|
||||||
}
|
}
|
||||||
state->top--;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cosmoV_pop(state); // pops the return value, it's unused
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(newObj));
|
cosmoV_pushValue(state, cosmoV_newObj(newObj));
|
||||||
break;
|
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
|
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!
|
// now invoke the method!
|
||||||
*key = *temp;
|
invokeMethod(state, object, val, args);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// moves return value & resets stack (key now points to the stack location of our return value)
|
// moves return value & resets stack (key now points to the stack location of our return value)
|
||||||
*temp = *key;
|
*temp = *key;
|
||||||
|
Loading…
Reference in New Issue
Block a user