From 9025da8168e505e2b0e32b89a0d94db935dace93 Mon Sep 17 00:00:00 2001 From: Tom Willemse Date: Fri, 21 Jan 2022 21:24:26 -0800 Subject: Chapter 24.1 --- clox/src/compiler.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) (limited to 'clox/src/compiler.c') 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)) { -- cgit v1.2.3-54-g00ecf