mirror of
https://github.com/CPunch/Cosmo.git
synced 2024-11-22 07:20:05 +00:00
multiple return value support added to VM
This commit is contained in:
parent
bf59f70598
commit
48ceca1834
@ -11,30 +11,30 @@ void cosmoB_loadLibrary(CState *state) {
|
|||||||
cosmoM_unfreezeGC(state);
|
cosmoM_unfreezeGC(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
CValue cosmoB_print(CState *state, int nargs, CValue *args) {
|
int cosmoB_print(CState *state, int nargs, CValue *args) {
|
||||||
for (int i = 0; i < nargs; i++) {
|
for (int i = 0; i < nargs; i++) {
|
||||||
CObjString *str = cosmoV_toString(state, args[i]);
|
CObjString *str = cosmoV_toString(state, args[i]);
|
||||||
printf("%s", cosmoO_readCString(str));
|
printf("%s", cosmoO_readCString(str));
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
return cosmoV_newNil(); // print doesn't return any args
|
return 0; // print doesn't return any args
|
||||||
}
|
}
|
||||||
|
|
||||||
CValue cosmoB_foreach(CState *state, int nargs, CValue *args) {
|
int cosmoB_foreach(CState *state, int nargs, CValue *args) {
|
||||||
if (nargs != 2) {
|
if (nargs != 2) {
|
||||||
cosmoV_error(state, "foreach() expected 2 parameters, got %d!", nargs);
|
cosmoV_error(state, "foreach() expected 2 parameters, got %d!", nargs);
|
||||||
return cosmoV_newNil();
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IS_DICT(args[0])) {
|
if (!IS_DICT(args[0])) {
|
||||||
cosmoV_error(state, "foreach() expected first parameter to be <dictionary>, got %s!", cosmoV_typeStr(args[0]));
|
cosmoV_error(state, "foreach() expected first parameter to be <dictionary>, got %s!", cosmoV_typeStr(args[0]));
|
||||||
return cosmoV_newNil();
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IS_CALLABLE(args[1])) {
|
if (!IS_CALLABLE(args[1])) {
|
||||||
cosmoV_error(state, "foreach() expected second parameter to be callable, got %s!", cosmoV_typeStr(args[1]));
|
cosmoV_error(state, "foreach() expected second parameter to be callable, got %s!", cosmoV_typeStr(args[1]));
|
||||||
return cosmoV_newNil();
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// loop through dictonary table, calling args[1] on active entries
|
// loop through dictonary table, calling args[1] on active entries
|
||||||
@ -48,15 +48,14 @@ CValue cosmoB_foreach(CState *state, int nargs, CValue *args) {
|
|||||||
cosmoV_pushValue(state, args[1]);
|
cosmoV_pushValue(state, args[1]);
|
||||||
cosmoV_pushValue(state, entry->key);
|
cosmoV_pushValue(state, entry->key);
|
||||||
cosmoV_pushValue(state, entry->val);
|
cosmoV_pushValue(state, entry->val);
|
||||||
cosmoV_call(state, 2);
|
cosmoV_call(state, 2, 0);
|
||||||
cosmoV_pop(state); // throw away the return value
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return cosmoV_newNil();
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
CValue cosmoB_dsetProto(CState *state, int nargs, CValue *args) {
|
int cosmoB_dsetProto(CState *state, int nargs, CValue *args) {
|
||||||
if (nargs == 2) {
|
if (nargs == 2) {
|
||||||
CObjObject *obj = cosmoV_readObject(args[0]); // object to set proto too
|
CObjObject *obj = cosmoV_readObject(args[0]); // object to set proto too
|
||||||
CObjObject *proto = cosmoV_readObject(args[1]);
|
CObjObject *proto = cosmoV_readObject(args[1]);
|
||||||
@ -66,15 +65,17 @@ CValue cosmoB_dsetProto(CState *state, int nargs, CValue *args) {
|
|||||||
cosmoV_error(state, "Expected 2 parameters, got %d!", nargs);
|
cosmoV_error(state, "Expected 2 parameters, got %d!", nargs);
|
||||||
}
|
}
|
||||||
|
|
||||||
return cosmoV_newNil(); // nothing
|
return 0; // nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
CValue cosmoB_dgetProto(CState *state, int nargs, CValue *args) {
|
int cosmoB_dgetProto(CState *state, int nargs, CValue *args) {
|
||||||
if (nargs != 1) {
|
if (nargs != 1) {
|
||||||
cosmoV_error(state, "Expected 1 parameter, got %d!", nargs);
|
cosmoV_error(state, "Expected 1 parameter, got %d!", nargs);
|
||||||
}
|
}
|
||||||
|
|
||||||
return cosmoV_newObj(cosmoV_readObject(args[0])->proto); // just return the proto
|
cosmoV_pushValue(state, cosmoV_newObj(cosmoV_readObject(args[0])->proto)); // just return the proto
|
||||||
|
|
||||||
|
return 1; // 1 result
|
||||||
}
|
}
|
||||||
|
|
||||||
void cosmoB_loadDebug(CState *state) {
|
void cosmoB_loadDebug(CState *state) {
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
COSMO_API void cosmoB_loadLibrary(CState *state);
|
COSMO_API void cosmoB_loadLibrary(CState *state);
|
||||||
COSMO_API void cosmoB_loadDebug(CState *state);
|
COSMO_API void cosmoB_loadDebug(CState *state);
|
||||||
COSMO_API CValue cosmoB_print(CState *state, int nargs, CValue *args);
|
COSMO_API int cosmoB_print(CState *state, int nargs, CValue *args);
|
||||||
COSMO_API CValue cosmoB_foreach(CState *state, int nargs, CValue *args);
|
COSMO_API int cosmoB_foreach(CState *state, int nargs, CValue *args);
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -93,7 +93,7 @@ int disasmInstr(CChunk *chunk, int offset, int indent) {
|
|||||||
case OP_POP:
|
case OP_POP:
|
||||||
return u8OperandInstruction("OP_POP", chunk, offset);
|
return u8OperandInstruction("OP_POP", chunk, offset);
|
||||||
case OP_CALL:
|
case OP_CALL:
|
||||||
return u8OperandInstruction("OP_CALL", chunk, offset);
|
return u8u8OperandInstruction("OP_CALL", chunk, offset);
|
||||||
case OP_CLOSURE: {
|
case OP_CLOSURE: {
|
||||||
int index = readu16Chunk(chunk, offset + 1);
|
int index = readu16Chunk(chunk, offset + 1);
|
||||||
printf("%-16s [%05d] - ", "OP_CLOSURE", index);
|
printf("%-16s [%05d] - ", "OP_CLOSURE", index);
|
||||||
@ -131,7 +131,7 @@ int disasmInstr(CChunk *chunk, int offset, int indent) {
|
|||||||
case OP_SETOBJECT:
|
case OP_SETOBJECT:
|
||||||
return simpleInstruction("OP_SETOBJECT", offset);
|
return simpleInstruction("OP_SETOBJECT", offset);
|
||||||
case OP_INVOKE:
|
case OP_INVOKE:
|
||||||
return u8OperandInstruction("OP_INVOKE", chunk, offset);
|
return u8u8OperandInstruction("OP_INVOKE", chunk, offset);
|
||||||
case OP_ADD:
|
case OP_ADD:
|
||||||
return simpleInstruction("OP_ADD", offset);
|
return simpleInstruction("OP_ADD", offset);
|
||||||
case OP_SUB:
|
case OP_SUB:
|
||||||
|
10
src/cobj.c
10
src/cobj.c
@ -229,7 +229,7 @@ bool cosmoO_getObject(CState *state, CObjObject *object, CValue key, CValue *val
|
|||||||
if (cosmoO_getIString(state, object, ISTRING_GETTER, val) && IS_OBJECT(*val) && cosmoO_getObject(state, cosmoV_readObject(*val), key, val)) {
|
if (cosmoO_getIString(state, object, ISTRING_GETTER, val) && IS_OBJECT(*val) && cosmoO_getObject(state, cosmoV_readObject(*val), key, val)) {
|
||||||
cosmoV_pushValue(state, *val); // push function
|
cosmoV_pushValue(state, *val); // push function
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(object)); // push object
|
cosmoV_pushValue(state, cosmoV_newObj(object)); // push object
|
||||||
cosmoV_call(state, 1); // call the function with the 1 argument
|
cosmoV_call(state, 1, 1); // call the function with the 1 argument
|
||||||
*val = *cosmoV_pop(state); // set value to the return value of __index
|
*val = *cosmoV_pop(state); // set value to the return value of __index
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -250,8 +250,7 @@ void cosmoO_setObject(CState *state, CObjObject *object, CValue key, CValue val)
|
|||||||
cosmoV_pushValue(state, ret); // push function
|
cosmoV_pushValue(state, ret); // push function
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(object)); // push object
|
cosmoV_pushValue(state, cosmoV_newObj(object)); // push object
|
||||||
cosmoV_pushValue(state, val); // push new value
|
cosmoV_pushValue(state, val); // push new value
|
||||||
cosmoV_call(state, 2);
|
cosmoV_call(state, 2, 0);
|
||||||
cosmoV_pop(state); // pop return value
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,7 +303,7 @@ bool cosmoO_indexObject(CState *state, CObjObject *object, CValue key, CValue *v
|
|||||||
cosmoV_pushValue(state, *val); // push function
|
cosmoV_pushValue(state, *val); // push function
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(object)); // push object
|
cosmoV_pushValue(state, cosmoV_newObj(object)); // push object
|
||||||
cosmoV_pushValue(state, key); // push key
|
cosmoV_pushValue(state, key); // push key
|
||||||
cosmoV_call(state, 2); // call the function with the 2 arguments
|
cosmoV_call(state, 2, 1); // call the function with the 2 arguments
|
||||||
*val = *cosmoV_pop(state); // set value to the return value of __index
|
*val = *cosmoV_pop(state); // set value to the return value of __index
|
||||||
return true;
|
return true;
|
||||||
} else { // there's no __index function defined!
|
} else { // there's no __index function defined!
|
||||||
@ -322,8 +321,7 @@ bool cosmoO_newIndexObject(CState *state, CObjObject *object, CValue key, CValue
|
|||||||
cosmoV_pushValue(state, cosmoV_newObj(object)); // push object
|
cosmoV_pushValue(state, cosmoV_newObj(object)); // push object
|
||||||
cosmoV_pushValue(state, key); // push key & value pair
|
cosmoV_pushValue(state, key); // push key & value pair
|
||||||
cosmoV_pushValue(state, val);
|
cosmoV_pushValue(state, val);
|
||||||
cosmoV_call(state, 3);
|
cosmoV_call(state, 3, 0);
|
||||||
cosmoV_pop(state); // pop return value
|
|
||||||
return true;
|
return true;
|
||||||
} else { // there's no __newindex function defined
|
} else { // there's no __newindex function defined
|
||||||
cosmoV_error(state, "Couldn't set index on object without __newindex function!");
|
cosmoV_error(state, "Couldn't set index on object without __newindex function!");
|
||||||
|
@ -26,7 +26,7 @@ typedef enum {
|
|||||||
#define readFlag(x, flag) (x & (1u << flag))
|
#define readFlag(x, flag) (x & (1u << flag))
|
||||||
#define setFlagOn(x, flag) (x |= (1u << flag))
|
#define setFlagOn(x, flag) (x |= (1u << flag))
|
||||||
|
|
||||||
typedef CValue (*CosmoCFunction)(CState *state, int argCount, CValue *args);
|
typedef int (*CosmoCFunction)(CState *state, int argCount, CValue *args);
|
||||||
|
|
||||||
typedef struct CObj {
|
typedef struct CObj {
|
||||||
CObjType type;
|
CObjType type;
|
||||||
|
@ -26,7 +26,7 @@ typedef enum {
|
|||||||
OP_JMP, // always jumps uint16_t
|
OP_JMP, // always jumps uint16_t
|
||||||
OP_JMPBACK, // jumps -uint16_t
|
OP_JMPBACK, // jumps -uint16_t
|
||||||
OP_POP, // - pops[uint8_t] from stack
|
OP_POP, // - pops[uint8_t] from stack
|
||||||
OP_CALL, // calls top[-uint8_t]
|
OP_CALL, // calls top[-uint8_t] expecting uint8_t results
|
||||||
OP_CLOSURE,
|
OP_CLOSURE,
|
||||||
OP_CLOSE,
|
OP_CLOSE,
|
||||||
OP_NEWDICT,
|
OP_NEWDICT,
|
||||||
|
@ -549,6 +549,7 @@ static void call_(CParseState *pstate, bool canAssign) {
|
|||||||
valuePopped(pstate, argCount + 1); // all of these values will be popped off the stack when returned (+1 for the function)
|
valuePopped(pstate, argCount + 1); // all of these values will be popped off the stack when returned (+1 for the function)
|
||||||
writeu8(pstate, OP_CALL);
|
writeu8(pstate, OP_CALL);
|
||||||
writeu8(pstate, argCount);
|
writeu8(pstate, argCount);
|
||||||
|
writeu8(pstate, 1); // TODO
|
||||||
valuePushed(pstate, 1);
|
valuePushed(pstate, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -603,6 +604,7 @@ static void dot(CParseState *pstate, bool canAssign) {
|
|||||||
uint8_t args = parseArguments(pstate);
|
uint8_t args = parseArguments(pstate);
|
||||||
writeu8(pstate, OP_INVOKE);
|
writeu8(pstate, OP_INVOKE);
|
||||||
writeu8(pstate, args);
|
writeu8(pstate, args);
|
||||||
|
writeu8(pstate, 1); // TODO
|
||||||
valuePopped(pstate, args); // pops the function & the object but pushes a result
|
valuePopped(pstate, args); // pops the function & the object but pushes a result
|
||||||
} else {
|
} else {
|
||||||
writeu8(pstate, OP_LOADCONST);
|
writeu8(pstate, OP_LOADCONST);
|
||||||
|
73
src/cvm.c
73
src/cvm.c
@ -106,20 +106,33 @@ CObjString *cosmoV_concat(CState *state, CObjString *strA, CObjString *strB) {
|
|||||||
return cosmoO_takeString(state, buf, sz);
|
return cosmoO_takeString(state, buf, sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cosmoV_execute(CState *state);
|
int cosmoV_execute(CState *state);
|
||||||
|
|
||||||
static inline void callCFunction(CState *state, CosmoCFunction cfunc, int args, int offset) {
|
static inline void callCFunction(CState *state, CosmoCFunction cfunc, int args, int nresults, int offset) {
|
||||||
StkPtr savedBase = cosmoV_getTop(state, args);
|
StkPtr savedBase = cosmoV_getTop(state, args);
|
||||||
|
|
||||||
cosmoM_freezeGC(state); // we don't want a GC event during c api because we don't actually trust the user to know how to evade the GC
|
cosmoM_freezeGC(state); // we don't want a GC event during c api because we don't actually trust the user to know how to evade the GC
|
||||||
CValue res = cfunc(state, args, savedBase + 1);
|
int nres = cfunc(state, args, savedBase + 1);
|
||||||
cosmoM_unfreezeGC(state);
|
cosmoM_unfreezeGC(state);
|
||||||
|
|
||||||
state->top = savedBase + offset;
|
// remember where the return values are
|
||||||
cosmoV_pushValue(state, res);
|
CValue* results = cosmoV_getTop(state, 0);
|
||||||
|
|
||||||
|
state->top = savedBase + offset; // set stack
|
||||||
|
|
||||||
|
if (nres > nresults) // caller function wasn't expecting this many return values, cap it
|
||||||
|
nres = nresults;
|
||||||
|
|
||||||
|
// push the return value back onto the stack
|
||||||
|
memcpy(state->top, results, sizeof(CValue) * nres); // copies the return values to the top of the stack
|
||||||
|
state->top += nres; // and make sure to move state->top to match
|
||||||
|
|
||||||
|
// now, if the caller function expected more return values, push nils onto the stack
|
||||||
|
for (int i = nres; i < nresults; i++)
|
||||||
|
cosmoV_pushValue(state, cosmoV_newNil());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool call(CState *state, CObjClosure *closure, int args, int offset) {
|
bool call(CState *state, CObjClosure *closure, int args, int nresults, int offset) {
|
||||||
// missmatched args, thats an obvious user error, so error.
|
// missmatched args, thats an obvious user error, so error.
|
||||||
if (args != closure->function->args) {
|
if (args != closure->function->args) {
|
||||||
cosmoV_error(state, "Expected %d parameters for %s, got %d!", closure->function->args, closure->function->name == NULL ? UNNAMEDCHUNK : closure->function->name->str, args);
|
cosmoV_error(state, "Expected %d parameters for %s, got %d!", closure->function->args, closure->function->name == NULL ? UNNAMEDCHUNK : closure->function->name->str, args);
|
||||||
@ -130,29 +143,39 @@ bool call(CState *state, CObjClosure *closure, int args, int offset) {
|
|||||||
pushCallFrame(state, closure, closure->function->args);
|
pushCallFrame(state, closure, closure->function->args);
|
||||||
|
|
||||||
// execute
|
// execute
|
||||||
if (!cosmoV_execute(state))
|
int nres = cosmoV_execute(state);
|
||||||
|
if (nres == -1) // panic state
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// remember where the return value is
|
// remember where the return values are
|
||||||
CValue* result = cosmoV_getTop(state, 0);
|
CValue* results = cosmoV_getTop(state, 0);
|
||||||
|
|
||||||
// pop the callframe and return result :)
|
// pop the callframe and return results :)
|
||||||
popCallFrame(state, offset);
|
popCallFrame(state, offset);
|
||||||
|
|
||||||
|
if (nres > nresults) // caller function wasn't expecting this many return values, cap it
|
||||||
|
nres = nresults;
|
||||||
|
|
||||||
// push the return value back onto the stack
|
// push the return value back onto the stack
|
||||||
cosmoV_pushValue(state, *result);
|
memcpy(state->top, results, sizeof(CValue) * nres); // copies the return values to the top of the stack
|
||||||
|
state->top += nres; // and make sure to move state->top to match
|
||||||
|
|
||||||
|
// now, if the caller function expected more return values, push nils onto the stack
|
||||||
|
for (int i = nres; i < nresults; i++)
|
||||||
|
cosmoV_pushValue(state, cosmoV_newNil());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool invokeMethod(CState* state, CObjObject *obj, CValue func, int args) {
|
bool invokeMethod(CState* state, CObjObject *obj, CValue func, int args, int nresults) {
|
||||||
// first, set the first argument to the object
|
// first, set the first argument to the object
|
||||||
StkPtr temp = cosmoV_getTop(state, args);
|
StkPtr temp = cosmoV_getTop(state, args);
|
||||||
*temp = cosmoV_newObj(obj);
|
*temp = cosmoV_newObj(obj);
|
||||||
|
|
||||||
if (IS_CFUNCTION(func)) {
|
if (IS_CFUNCTION(func)) {
|
||||||
callCFunction(state, cosmoV_readCFunction(func), args+1, 1);
|
callCFunction(state, cosmoV_readCFunction(func), args+1, nresults, 1);
|
||||||
} else if (IS_CLOSURE(func)) {
|
} else if (IS_CLOSURE(func)) {
|
||||||
call(state, cosmoV_readClosure(func), args+1, 1); // offset = 1 so our stack is properly reset
|
call(state, cosmoV_readClosure(func), args+1, nresults, 1); // offset = 1 so our stack is properly reset
|
||||||
} else {
|
} else {
|
||||||
cosmoV_error(state, "Cannot invoke non-function type %s!", cosmoV_typeStr(func));
|
cosmoV_error(state, "Cannot invoke non-function type %s!", cosmoV_typeStr(func));
|
||||||
}
|
}
|
||||||
@ -161,7 +184,7 @@ bool invokeMethod(CState* state, CObjObject *obj, CValue func, int args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// args = # of pass parameters
|
// args = # of pass parameters
|
||||||
COSMOVMRESULT cosmoV_call(CState *state, int args) {
|
COSMOVMRESULT cosmoV_call(CState *state, int args, int nresults) {
|
||||||
StkPtr val = cosmoV_getTop(state, args); // function will always be right above the args
|
StkPtr val = cosmoV_getTop(state, args); // function will always be right above the args
|
||||||
|
|
||||||
if (GET_TYPE(*val) != COSMO_TOBJ) {
|
if (GET_TYPE(*val) != COSMO_TOBJ) {
|
||||||
@ -172,14 +195,14 @@ COSMOVMRESULT cosmoV_call(CState *state, int args) {
|
|||||||
switch (cosmoV_readObj(*val)->type) {
|
switch (cosmoV_readObj(*val)->type) {
|
||||||
case COBJ_CLOSURE: {
|
case COBJ_CLOSURE: {
|
||||||
CObjClosure *closure = (CObjClosure*)cosmoV_readObj(*val);
|
CObjClosure *closure = (CObjClosure*)cosmoV_readObj(*val);
|
||||||
if (!call(state, closure, args, 0)) {
|
if (!call(state, closure, args, nresults, 0)) {
|
||||||
return COSMOVM_RUNTIME_ERR;
|
return COSMOVM_RUNTIME_ERR;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case COBJ_METHOD: {
|
case COBJ_METHOD: {
|
||||||
CObjMethod *method = (CObjMethod*)cosmoV_readObj(*val);
|
CObjMethod *method = (CObjMethod*)cosmoV_readObj(*val);
|
||||||
invokeMethod(state, method->obj, method->func, args);
|
invokeMethod(state, method->obj, method->func, args, nresults);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case COBJ_OBJECT: { // object is being instantiated, making another object
|
case COBJ_OBJECT: { // object is being instantiated, making another object
|
||||||
@ -190,7 +213,7 @@ COSMOVMRESULT cosmoV_call(CState *state, int args) {
|
|||||||
|
|
||||||
// check if they defined an initalizer
|
// check if they defined an initalizer
|
||||||
if (cosmoO_getIString(state, protoObj, ISTRING_INIT, &ret)) {
|
if (cosmoO_getIString(state, protoObj, ISTRING_INIT, &ret)) {
|
||||||
invokeMethod(state, newObj, ret, args);
|
invokeMethod(state, newObj, ret, args, nresults);
|
||||||
} else {
|
} else {
|
||||||
// no default initalizer
|
// no default initalizer
|
||||||
if (args != 0) {
|
if (args != 0) {
|
||||||
@ -206,7 +229,7 @@ COSMOVMRESULT cosmoV_call(CState *state, int args) {
|
|||||||
case COBJ_CFUNCTION: {
|
case COBJ_CFUNCTION: {
|
||||||
// it's a C function, so call it
|
// it's a C function, so call it
|
||||||
CosmoCFunction cfunc = ((CObjCFunction*)cosmoV_readObj(*val))->cfunc;
|
CosmoCFunction cfunc = ((CObjCFunction*)cosmoV_readObj(*val))->cfunc;
|
||||||
callCFunction(state, cfunc, args, 0);
|
callCFunction(state, cfunc, args, nresults, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -288,7 +311,7 @@ COSMO_API bool cosmoV_getObject(CState *state, CObjObject *object, CValue key, C
|
|||||||
} \
|
} \
|
||||||
|
|
||||||
// returns false if panic
|
// returns false if panic
|
||||||
bool cosmoV_execute(CState *state) {
|
int cosmoV_execute(CState *state) {
|
||||||
CCallFrame* frame = &state->callFrame[state->frameCount - 1]; // grabs the current frame
|
CCallFrame* frame = &state->callFrame[state->frameCount - 1]; // grabs the current frame
|
||||||
CValue *constants = frame->closure->function->chunk.constants.values; // cache the pointer :)
|
CValue *constants = frame->closure->function->chunk.constants.values; // cache the pointer :)
|
||||||
|
|
||||||
@ -371,7 +394,8 @@ bool cosmoV_execute(CState *state) {
|
|||||||
}
|
}
|
||||||
case OP_CALL: {
|
case OP_CALL: {
|
||||||
uint8_t args = READBYTE();
|
uint8_t args = READBYTE();
|
||||||
COSMOVMRESULT result = cosmoV_call(state, args);
|
uint8_t nres = READBYTE();
|
||||||
|
COSMOVMRESULT result = cosmoV_call(state, args, nres);
|
||||||
if (result != COSMOVM_OK) {
|
if (result != COSMOVM_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -509,6 +533,7 @@ bool cosmoV_execute(CState *state) {
|
|||||||
}
|
}
|
||||||
case OP_INVOKE: { // this is an optimization made by the parser, instead of allocating a CObjMethod every time we want to invoke a method, we shrink it down into one minimal instruction!
|
case OP_INVOKE: { // this is an optimization made by the parser, instead of allocating a CObjMethod every time we want to invoke a method, we shrink it down into one minimal instruction!
|
||||||
uint8_t args = READBYTE();
|
uint8_t args = READBYTE();
|
||||||
|
uint8_t nres = READBYTE();
|
||||||
StkPtr key = cosmoV_getTop(state, args); // grabs key from stack
|
StkPtr key = cosmoV_getTop(state, args); // grabs key from stack
|
||||||
StkPtr temp = cosmoV_getTop(state, args+1); // grabs object from stack
|
StkPtr temp = cosmoV_getTop(state, args+1); // grabs object from stack
|
||||||
|
|
||||||
@ -524,7 +549,7 @@ 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 invoke the method!
|
// now invoke the method!
|
||||||
invokeMethod(state, object, val, args);
|
invokeMethod(state, object, val, args, nres);
|
||||||
|
|
||||||
// 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;
|
||||||
@ -745,7 +770,7 @@ bool cosmoV_execute(CState *state) {
|
|||||||
case OP_FALSE: cosmoV_pushBoolean(state, false); break;
|
case OP_FALSE: cosmoV_pushBoolean(state, false); break;
|
||||||
case OP_NIL: cosmoV_pushValue(state, cosmoV_newNil()); break;
|
case OP_NIL: cosmoV_pushValue(state, cosmoV_newNil()); break;
|
||||||
case OP_RETURN: {
|
case OP_RETURN: {
|
||||||
return true;
|
return 1;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
CERROR("unknown opcode!");
|
CERROR("unknown opcode!");
|
||||||
@ -758,7 +783,7 @@ bool cosmoV_execute(CState *state) {
|
|||||||
#undef READUINT
|
#undef READUINT
|
||||||
|
|
||||||
// we'll only reach this is state->panic is true
|
// we'll only reach this is state->panic is true
|
||||||
return false;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef NUMBEROP
|
#undef NUMBEROP
|
@ -13,7 +13,7 @@ typedef enum {
|
|||||||
} COSMOVMRESULT;
|
} COSMOVMRESULT;
|
||||||
|
|
||||||
// args = # of pass parameters, nresults = # of expected results
|
// args = # of pass parameters, nresults = # of expected results
|
||||||
COSMO_API COSMOVMRESULT cosmoV_call(CState *state, int args);
|
COSMO_API COSMOVMRESULT cosmoV_call(CState *state, int args, int nresults);
|
||||||
COSMO_API void cosmoV_makeObject(CState *state, int pairs);
|
COSMO_API void cosmoV_makeObject(CState *state, int pairs);
|
||||||
COSMO_API void cosmoV_makeDictionary(CState *state, int pairs);
|
COSMO_API void cosmoV_makeDictionary(CState *state, int pairs);
|
||||||
COSMO_API bool cosmoV_getObject(CState *state, CObjObject *object, CValue key, CValue *val);
|
COSMO_API bool cosmoV_getObject(CState *state, CObjObject *object, CValue key, CValue *val);
|
||||||
|
12
src/main.c
12
src/main.c
@ -9,13 +9,13 @@
|
|||||||
|
|
||||||
static bool _ACTIVE = false;
|
static bool _ACTIVE = false;
|
||||||
|
|
||||||
CValue cosmoB_quitRepl(CState *state, int nargs, CValue *args) {
|
int cosmoB_quitRepl(CState *state, int nargs, CValue *args) {
|
||||||
_ACTIVE = false;
|
_ACTIVE = false;
|
||||||
|
|
||||||
return cosmoV_newNil(); // we don't return anything
|
return 0; // we don't return anything
|
||||||
}
|
}
|
||||||
|
|
||||||
CValue cosmoB_input(CState *state, int nargs, CValue *args) {
|
int cosmoB_input(CState *state, int nargs, CValue *args) {
|
||||||
// input() accepts the same params as print()!
|
// input() accepts the same params as print()!
|
||||||
for (int i = 0; i < nargs; i++) {
|
for (int i = 0; i < nargs; i++) {
|
||||||
CObjString *str = cosmoV_toString(state, args[i]);
|
CObjString *str = cosmoV_toString(state, args[i]);
|
||||||
@ -26,7 +26,9 @@ CValue cosmoB_input(CState *state, int nargs, CValue *args) {
|
|||||||
char line[1024];
|
char line[1024];
|
||||||
fgets(line, sizeof(line), stdin);
|
fgets(line, sizeof(line), stdin);
|
||||||
|
|
||||||
return cosmoV_newObj(cosmoO_copyString(state, line, strlen(line)-1)); // -1 for the \n
|
cosmoV_pushValue(state, cosmoV_newObj(cosmoO_copyString(state, line, strlen(line)-1))); // -1 for the \n
|
||||||
|
|
||||||
|
return 1; // 1 return value
|
||||||
}
|
}
|
||||||
|
|
||||||
static void interpret(CState *state, const char *script, const char *mod) {
|
static void interpret(CState *state, const char *script, const char *mod) {
|
||||||
@ -35,7 +37,7 @@ static void interpret(CState *state, const char *script, const char *mod) {
|
|||||||
if (func != NULL) {
|
if (func != NULL) {
|
||||||
disasmChunk(&func->chunk, func->name != NULL ? func->name->str : "_main", 0);
|
disasmChunk(&func->chunk, func->name != NULL ? func->name->str : "_main", 0);
|
||||||
|
|
||||||
COSMOVMRESULT res = cosmoV_call(state, 0); // 0 args being passed
|
COSMOVMRESULT res = cosmoV_call(state, 0, 0); // 0 args being passed, 0 results expected
|
||||||
|
|
||||||
if (res == COSMOVM_RUNTIME_ERR)
|
if (res == COSMOVM_RUNTIME_ERR)
|
||||||
state->panic = false; // so our repl isn't broken
|
state->panic = false; // so our repl isn't broken
|
||||||
|
Loading…
Reference in New Issue
Block a user