void WhileStatement() { var surroundingLoopState = InnermostLoop; InnermostLoop = LoopState.FromCurrentState(this); Expression(); Consume(TokenType.Colon, "Expect ':' after condition"); var exitJump = EmitJump(OpCode.JumpIfFalse); Emit(OpCode.Pop); Statement(); EmitLoop(InnermostLoop.Start); PatchJump(exitJump); Emit(OpCode.Pop); InnermostLoop.PatchUnresolvedBreaks(this); InnermostLoop = surroundingLoopState; }
void ForStatement() { BeginScope(); // Initializer if (Match(TokenType.Var)) { VarDeclaration(); } else if (Match(TokenType.Semicolon)) { // No initializer } else { ExpressionStatement(); } var surroundingLoopState = InnermostLoop; InnermostLoop = LoopState.FromCurrentState(this); // Condition var exitJump = -1; if (!Match(TokenType.Semicolon)) { Expression(); Consume(TokenType.Semicolon, "Expect ';' after loop condition"); // Jump out if condition is negative exitJump = EmitJump(OpCode.JumpIfFalse); Emit(OpCode.Pop); // Condition } // Increment if (!Match(TokenType.Colon)) { var bodyJump = EmitJump(OpCode.Jump); var incrementStart = CurrentCodePosition(); Expression(); Emit(OpCode.Pop); Consume(TokenType.Colon, "Expect ':' after for clauses"); EmitLoop(InnermostLoop.Start); InnermostLoop.Start = incrementStart; PatchJump(bodyJump); } Statement(); EmitLoop(InnermostLoop.Start); if (exitJump != -1) { PatchJump(exitJump); Emit(OpCode.Pop); // Condition, if Pop has been jumped over above } InnermostLoop.PatchUnresolvedBreaks(this); InnermostLoop = surroundingLoopState; EndScope(); }