mirror of
https://github.com/CPunch/Cosmo.git
synced 2024-11-24 16:11:04 +00:00
made OP_ITER and OP_NEXT use CObjMethods
This commit is contained in:
parent
e5eca7bed6
commit
eede892eb0
@ -17,6 +17,9 @@ proto Range
|
||||
end
|
||||
end
|
||||
|
||||
for i, x in Range(10) do
|
||||
print("was " .. i .. ", now " .. x)
|
||||
end
|
||||
local total = 0
|
||||
for i, x in Range(1000000) do
|
||||
total = total + i
|
||||
end
|
||||
|
||||
print("total: " .. total)
|
@ -36,8 +36,8 @@ typedef enum {
|
||||
OP_SETOBJECT,
|
||||
OP_GETOBJECT,
|
||||
OP_INVOKE,
|
||||
OP_ITER, // if stack[top] is an object, __iter is expected and called, else if stack[top] is a dictionary a dummy iterator object is made (SEE: cosmoV_makeIter())
|
||||
OP_NEXT, // if stack[top] is an object, __next is expected and called, expecting uint8_t return values. if stack[top] after calling is nil, jump uint16_t
|
||||
OP_ITER,
|
||||
OP_NEXT,
|
||||
|
||||
// ARITHMETIC
|
||||
OP_ADD,
|
||||
|
@ -1121,7 +1121,7 @@ static void forEachLoop(CParseState *pstate) {
|
||||
|
||||
consume(pstate, TOKEN_DO, "Expected 'do' before loop block!");
|
||||
|
||||
writeu8(pstate, OP_ITER); // checks if stack[top] is iterable and makes an iterable object wrapper for CObjs like CObjDict
|
||||
writeu8(pstate, OP_ITER); // checks if stack[top] is iterable and pushes the __next method onto the stack for OP_NEXT to call
|
||||
|
||||
int loopStart = getChunk(pstate)->count;
|
||||
|
||||
|
39
src/cvm.c
39
src/cvm.c
@ -149,15 +149,15 @@ bool call(CState *state, CObjClosure *closure, int args, int nresults, int offse
|
||||
if (nres == -1) // panic state
|
||||
return false;
|
||||
|
||||
if (nres > nresults) // caller function wasn't expecting this many return values, cap it
|
||||
nres = nresults;
|
||||
|
||||
// remember where the return values are
|
||||
CValue* results = cosmoV_getTop(state, nres-1);
|
||||
|
||||
// pop the callframe and return results :)
|
||||
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
|
||||
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
|
||||
@ -580,6 +580,17 @@ int cosmoV_execute(CState *state) {
|
||||
cosmoV_pushValue(state, val);
|
||||
cosmoV_pushValue(state, cosmoV_newObj(obj));
|
||||
cosmoV_call(state, 1, 1); // we expect 1 return value on the stack, the iterable object
|
||||
|
||||
StkPtr iobj = cosmoV_getTop(state, 0);
|
||||
|
||||
if (!IS_OBJECT(*iobj)) {
|
||||
cosmoV_error(state, "Expected iterable object! '__iter' returned %s, expected object!", cosmoV_typeStr(*iobj));
|
||||
break;
|
||||
}
|
||||
|
||||
CObjObject *obj = (CObjObject*)cosmoV_readObj(*iobj);
|
||||
|
||||
cosmoV_getObject(state, obj, cosmoV_newObj(state->iStrings[ISTRING_NEXT]), iobj);
|
||||
} else {
|
||||
cosmoV_error(state, "Expected iterable object! '__iter' not defined!");
|
||||
}
|
||||
@ -598,25 +609,17 @@ int cosmoV_execute(CState *state) {
|
||||
uint16_t jump = READUINT();
|
||||
StkPtr temp = cosmoV_getTop(state, 0); // we don't actually pop this off the stack
|
||||
|
||||
if (!IS_OBJECT(*temp)) {
|
||||
cosmoV_error(state, "Couldn't iterate over non-iterator type %s!", cosmoV_typeStr(*temp));
|
||||
if (!IS_METHOD(*temp)) {
|
||||
cosmoV_error(state, "Expected '__next' to be a method, got type %s!", cosmoV_typeStr(*temp));
|
||||
break;
|
||||
}
|
||||
|
||||
CObjObject *obj = (CObjObject*)cosmoV_readObj(*temp);
|
||||
CValue val;
|
||||
cosmoV_pushValue(state, *temp);
|
||||
cosmoV_call(state, 0, nresults);
|
||||
|
||||
if (cosmoO_getIString(state, obj, ISTRING_NEXT, &val)) {
|
||||
cosmoV_pushValue(state, val);
|
||||
cosmoV_pushValue(state, *temp);
|
||||
cosmoV_call(state, 1, nresults);
|
||||
|
||||
if (IS_NIL(*(cosmoV_getTop(state, 0)))) { // __next returned a nil, which means to exit the loop
|
||||
cosmoV_setTop(state, nresults); // pop the return values
|
||||
frame->pc += jump;
|
||||
}
|
||||
} else {
|
||||
cosmoV_error(state, "Expected iterable object! '__next' not defined!");
|
||||
if (IS_NIL(*(cosmoV_getTop(state, 0)))) { // __next returned a nil, which means to exit the loop
|
||||
cosmoV_setTop(state, nresults); // pop the return values
|
||||
frame->pc += jump;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user