Added break and continue support to for loops
This commit is contained in:
@@ -289,7 +289,7 @@ int inspect_instruction(unsigned char* bytecode, unsigned int pc, unsigned int j
|
|||||||
return 8;
|
return 8;
|
||||||
|
|
||||||
case TOY_OPCODE_ESCAPE:
|
case TOY_OPCODE_ESCAPE:
|
||||||
printf(MARKER TOY_CC_DEBUG "ESCAPE relative %s%d (GOTO %u) and pop %d\n" TOY_CC_RESET, MARKER_VALUE(pc, unsigned char),
|
printf(MARKER TOY_CC_DEBUG "ESCAPE relative %s%d (GOTO %u) and pop %d scopes\n" TOY_CC_RESET, MARKER_VALUE(pc, unsigned char),
|
||||||
(*(int*)(bytecode + pc + 4)) > 0 ? "+" : "", //show a + sign when positive
|
(*(int*)(bytecode + pc + 4)) > 0 ? "+" : "", //show a + sign when positive
|
||||||
(*(int*)(bytecode + pc + 4)),
|
(*(int*)(bytecode + pc + 4)),
|
||||||
(*(int*)(bytecode + pc + 4)) + pc + 12,
|
(*(int*)(bytecode + pc + 4)) + pc + 12,
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
|
|
||||||
|
|
||||||
var array = ["foo", "bar"];
|
var array = ["foo", "bar", "buzz", "fizz"];
|
||||||
|
|
||||||
for (var i in array) {
|
for (var i in array) {
|
||||||
|
if (i == "buzz") break; //use break or continue
|
||||||
print i;
|
print i;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
print "done";
|
print "done";
|
||||||
@@ -784,6 +784,41 @@ static unsigned int writeInstructionForThen(Toy_Bytecode** mb, Toy_AstForThen as
|
|||||||
//end of the loop, overwrite the parameter
|
//end of the loop, overwrite the parameter
|
||||||
OVERWRITE_INT(mb, code, thenParamAddr, CURRENT_ADDRESS(mb, code) - (thenParamAddr + 4));
|
OVERWRITE_INT(mb, code, thenParamAddr, CURRENT_ADDRESS(mb, code) - (thenParamAddr + 4));
|
||||||
|
|
||||||
|
//set the break & continue data
|
||||||
|
while ((*mb)->breakEscapes->count > 0) {
|
||||||
|
//extract
|
||||||
|
unsigned int addr = (*mb)->breakEscapes->data[(*mb)->breakEscapes->count - 1].addr;
|
||||||
|
unsigned int depth = (*mb)->breakEscapes->data[(*mb)->breakEscapes->count - 1].depth;
|
||||||
|
|
||||||
|
unsigned int diff = depth - (*mb)->currentScopeDepth;
|
||||||
|
|
||||||
|
OVERWRITE_INT(mb, code, addr, CURRENT_ADDRESS(mb, code) - (addr + 8)); //tell break to come here AFTER reading the instruction
|
||||||
|
OVERWRITE_INT(mb, code, addr, diff);
|
||||||
|
|
||||||
|
//tick down
|
||||||
|
(*mb)->breakEscapes->count--;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((*mb)->continueEscapes->count > 0) {
|
||||||
|
//extract
|
||||||
|
unsigned int addr = (*mb)->continueEscapes->data[(*mb)->continueEscapes->count - 1].addr;
|
||||||
|
unsigned int depth = (*mb)->continueEscapes->data[(*mb)->continueEscapes->count - 1].depth;
|
||||||
|
|
||||||
|
unsigned int diff = depth - (*mb)->currentScopeDepth;
|
||||||
|
|
||||||
|
OVERWRITE_INT(mb, code, addr, beginAddr - (addr + 8)); //tell continue to return to the start AFTER reading the instruction
|
||||||
|
OVERWRITE_INT(mb, code, addr, diff);
|
||||||
|
|
||||||
|
//tick down
|
||||||
|
(*mb)->continueEscapes->count--;
|
||||||
|
}
|
||||||
|
|
||||||
|
//eliminate the value & counter from within the bytecode, so they're cleaned up after breaks
|
||||||
|
EMIT_BYTE(mb, code,TOY_OPCODE_ELIMINATE);
|
||||||
|
EMIT_BYTE(mb, code, 2);
|
||||||
|
EMIT_BYTE(mb, code, 0);
|
||||||
|
EMIT_BYTE(mb, code, 0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-3
@@ -499,9 +499,11 @@ static void processIterate(Toy_VM* vm) {
|
|||||||
|
|
||||||
//check out-of-bounds
|
//check out-of-bounds
|
||||||
if (index >= array->count) {
|
if (index >= array->count) {
|
||||||
Toy_freeValue(counter);
|
//DON'T free the iterable & counter, that's embedded in the bytecode
|
||||||
Toy_freeValue(compound);
|
Toy_pushStack(&vm->stack, compound);
|
||||||
Toy_pushStack(&vm->stack, TOY_VALUE_FROM_NULL()); //force a jump
|
Toy_pushStack(&vm->stack, counter);
|
||||||
|
//force a jump then exit
|
||||||
|
Toy_pushStack(&vm->stack, TOY_VALUE_FROM_NULL());
|
||||||
processJump(vm);
|
processJump(vm);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user