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
|
||||||
end
|
end
|
||||||
|
|
||||||
for i, x in Range(10) do
|
local total = 0
|
||||||
print("was " .. i .. ", now " .. x)
|
for i, x in Range(1000000) do
|
||||||
|
total = total + i
|
||||||
end
|
end
|
||||||
|
|
||||||
|
print("total: " .. total)
|
@ -36,8 +36,8 @@ typedef enum {
|
|||||||
OP_SETOBJECT,
|
OP_SETOBJECT,
|
||||||
OP_GETOBJECT,
|
OP_GETOBJECT,
|
||||||
OP_INVOKE,
|
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_ITER,
|
||||||
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_NEXT,
|
||||||
|
|
||||||
// ARITHMETIC
|
// ARITHMETIC
|
||||||
OP_ADD,
|
OP_ADD,
|
||||||
|
@ -1121,7 +1121,7 @@ static void forEachLoop(CParseState *pstate) {
|
|||||||
|
|
||||||
consume(pstate, TOKEN_DO, "Expected 'do' before loop block!");
|
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;
|
int loopStart = getChunk(pstate)->count;
|
||||||
|
|
||||||
|
31
src/cvm.c
31
src/cvm.c
@ -149,15 +149,15 @@ bool call(CState *state, CObjClosure *closure, int args, int nresults, int offse
|
|||||||
if (nres == -1) // panic state
|
if (nres == -1) // panic state
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (nres > nresults) // caller function wasn't expecting this many return values, cap it
|
||||||
|
nres = nresults;
|
||||||
|
|
||||||
// remember where the return values are
|
// remember where the return values are
|
||||||
CValue* results = cosmoV_getTop(state, nres-1);
|
CValue* results = cosmoV_getTop(state, nres-1);
|
||||||
|
|
||||||
// pop the callframe and return results :)
|
// 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
|
||||||
memcpy(state->top, results, sizeof(CValue) * nres); // copies the return values to the top of 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
|
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, val);
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(obj));
|
cosmoV_pushValue(state, cosmoV_newObj(obj));
|
||||||
cosmoV_call(state, 1, 1); // we expect 1 return value on the stack, the iterable object
|
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 {
|
} else {
|
||||||
cosmoV_error(state, "Expected iterable object! '__iter' not defined!");
|
cosmoV_error(state, "Expected iterable object! '__iter' not defined!");
|
||||||
}
|
}
|
||||||
@ -598,26 +609,18 @@ int cosmoV_execute(CState *state) {
|
|||||||
uint16_t jump = READUINT();
|
uint16_t jump = READUINT();
|
||||||
StkPtr temp = cosmoV_getTop(state, 0); // we don't actually pop this off the stack
|
StkPtr temp = cosmoV_getTop(state, 0); // we don't actually pop this off the stack
|
||||||
|
|
||||||
if (!IS_OBJECT(*temp)) {
|
if (!IS_METHOD(*temp)) {
|
||||||
cosmoV_error(state, "Couldn't iterate over non-iterator type %s!", cosmoV_typeStr(*temp));
|
cosmoV_error(state, "Expected '__next' to be a method, got type %s!", cosmoV_typeStr(*temp));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
CObjObject *obj = (CObjObject*)cosmoV_readObj(*temp);
|
|
||||||
CValue val;
|
|
||||||
|
|
||||||
if (cosmoO_getIString(state, obj, ISTRING_NEXT, &val)) {
|
|
||||||
cosmoV_pushValue(state, val);
|
|
||||||
cosmoV_pushValue(state, *temp);
|
cosmoV_pushValue(state, *temp);
|
||||||
cosmoV_call(state, 1, nresults);
|
cosmoV_call(state, 0, nresults);
|
||||||
|
|
||||||
if (IS_NIL(*(cosmoV_getTop(state, 0)))) { // __next returned a nil, which means to exit the loop
|
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
|
cosmoV_setTop(state, nresults); // pop the return values
|
||||||
frame->pc += jump;
|
frame->pc += jump;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
cosmoV_error(state, "Expected iterable object! '__next' not defined!");
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OP_ADD: { // pop 2 values off the stack & try to add them together
|
case OP_ADD: { // pop 2 values off the stack & try to add them together
|
||||||
|
Loading…
Reference in New Issue
Block a user