Support 'else' blocks on for and while loops

This commit is contained in:
K. Lange 2022-05-23 09:41:12 +09:00
parent ece7da299a
commit 4a052191de
3 changed files with 71 additions and 1 deletions

View File

@ -1879,6 +1879,23 @@ static void continueStatement(void) {
current->continues[current->continueCount++] = (struct LoopExit){emitJump(OP_JUMP),parser.previous};
}
static void optionalElse(size_t blockWidth) {
KrkScanner scannerBefore = krk_tellScanner();
Parser parserBefore = parser;
if (blockWidth == 0 || (check(TOKEN_INDENTATION) && (parser.current.length == blockWidth))) {
if (blockWidth) advance();
if (match(TOKEN_ELSE)) {
consume(TOKEN_COLON, "Expected ':' after 'else'.");
beginScope();
block(blockWidth,"else");
endScope();
} else {
krk_rewindScanner(scannerBefore);
parser = parserBefore;
}
}
}
static void whileStatement(void) {
size_t blockWidth = (parser.previous.type == TOKEN_INDENTATION) ? parser.previous.length : 0;
advance();
@ -1900,6 +1917,7 @@ static void whileStatement(void) {
emitLoop(loopStart);
patchJump(exitJump);
emitByte(OP_POP);
optionalElse(blockWidth);
patchBreaks(loopStart);
}
@ -1992,8 +2010,8 @@ static void forStatement(void) {
emitLoop(loopStart);
patchJump(exitJump);
emitByte(OP_POP);
optionalElse(blockWidth);
patchBreaks(loopStart);
endScope();
}

32
test/testLoopElse.krk Normal file
View File

@ -0,0 +1,32 @@
def func(breakPoint):
let j = 0
for i in range(20):
if i == breakPoint:
break
j += 1
else:
print('finished for')
print('out of for')
return j
print(func(20))
print(func(15))
print(func(20))
print(func(15))
def func2(breakPoint):
let i = 0
while i < 20:
if i == breakPoint:
break
i++
else:
print('finished while')
print('out of while')
return i
print(func2(20))
print(func2(15))
print(func2(20))
print(func2(15))

View File

@ -0,0 +1,20 @@
finished for
out of for
20
out of for
15
finished for
out of for
20
out of for
15
finished while
out of while
20
out of while
15
finished while
out of while
20
out of while
15