aboutsummaryrefslogtreecommitdiffstats
path: root/clox/src/compiler.c
diff options
context:
space:
mode:
authorGravatar Tom Willemse2022-01-21 21:24:26 -0800
committerGravatar Tom Willemse2022-01-21 21:24:26 -0800
commit9025da8168e505e2b0e32b89a0d94db935dace93 (patch)
tree162fa69ce309ab3eb0359ba59d1180c02d4869ec /clox/src/compiler.c
parent37ac05af6d0aa57ccc5ea805af262a407fedeeae (diff)
downloadcrafting-interpreters-9025da8168e505e2b0e32b89a0d94db935dace93.tar.gz
crafting-interpreters-9025da8168e505e2b0e32b89a0d94db935dace93.zip
Chapter 24.1
Diffstat (limited to 'clox/src/compiler.c')
-rw-r--r--clox/src/compiler.c47
1 files changed, 47 insertions, 0 deletions
diff --git a/clox/src/compiler.c b/clox/src/compiler.c
index beda5d5..aed21f7 100644
--- a/clox/src/compiler.c
+++ b/clox/src/compiler.c
@@ -288,6 +288,51 @@ static void expressionStatement() {
emitByte(OP_POP);
}
+static void forStatement() {
+ beginScope();
+ consume(TOKEN_LEFT_PAREN, "Expect '(' after 'for'.");
+ if (match(TOKEN_SEMICOLON)) {
+ // No initializer
+ } else if (match(TOKEN_VAR)) {
+ varDeclaration();
+ } else {
+ expressionStatement();
+ }
+
+ int loopStart = currentChunk()->count;
+ int exitJump = -1;
+ if (!match(TOKEN_SEMICOLON)) {
+ expression();
+ consume(TOKEN_SEMICOLON, "Expect ';' after loop condition.");
+
+ // Jump out of the loop if the condition is false.
+ exitJump = emitJump(OP_JUMP_IF_FALSE);
+ emitByte(OP_POP); /* Condition. */
+ }
+
+ if (!match(TOKEN_RIGHT_PAREN)) {
+ int bodyJump = emitJump(OP_JUMP);
+ int incrementStart = currentChunk()->count;
+ expression();
+ emitByte(OP_POP);
+ consume(TOKEN_RIGHT_PAREN, "Expect ')' after for clauses.");
+
+ emitLoop(loopStart);
+ loopStart = incrementStart;
+ patchJump(bodyJump);
+ }
+
+ statement();
+ emitLoop(loopStart);
+
+ if (exitJump != -1) {
+ patchJump(exitJump);
+ emitByte(OP_POP); /* Condition. */
+ }
+
+ endScope();
+}
+
static void ifStatement() {
consume(TOKEN_LEFT_PAREN, "Expect '(' after 'if'.");
expression();
@@ -366,6 +411,8 @@ static void declaration() {
static void statement() {
if (match(TOKEN_PRINT)) {
printStatement();
+ } else if (match(TOKEN_FOR)) {
+ forStatement();
} else if (match(TOKEN_IF)) {
ifStatement();
} else if (match(TOKEN_WHILE)) {