Exercise 1: Omitting Clauses in a for Loop — Possible Solution ==================================================================== RESULTS ------------------------------ var i = 0; for (; i < 3; i = i + 1) { print i; } -> ['0', '1', '2'] for (var j = 0; j < 3;) { print j; j = j + 1; } -> ['0', '1', '2'] Both produce identical, correct output to a normal three-clause for loop. TRACING THE DESUGARING CODE ------------------------------ def for_statement(self): self.expect('(') if self.match(';'): initializer = None elif self.peek()[0] == 'VAR': self.advance() initializer = self.var_declaration() else: initializer = self.expression_statement() ... For "for (; i < 3; i = i + 1)": immediately after the opening '(', the very next token IS a ';' -- so `self.match(';')` succeeds, consuming it, and `initializer` is set to None directly. No var_declaration() or expression_statement() call happens at all for the initializer slot. condition = None if self.peek()[0] == ';' else self.parse_expression() self.expect(';') increment = None if self.peek()[0] == ')' else self.parse_expression() self.expect(')') For "for (var j = 0; j < 3;)": after the condition `j < 3` and its following ';' are consumed normally, the very next token is ')' -- so `increment` is set to None directly, and `self.parse_expression()` is never called for the increment slot. if increment is not None: body = BlockStmt([body, ExpressionStmt(increment)]) body = WhileStmt(condition if condition is not None else Literal(True), body) if initializer is not None: body = BlockStmt([initializer, body]) return body For the first program (initializer=None), the final `if initializer is not None:` check is False, so the outer BlockStmt wrapping never happens -- the desugared result is just the bare WhileStmt itself (the caller's own surrounding block, `{ var i = 0; for (...) {...} }` in the exercise, is what actually provides `i`'s scope here, since it was declared before the for loop rather than inside it). For the second program (increment=None), the `if increment is not None:` check is False, so `body` is never wrapped in an extra BlockStmt for the increment -- the loop body is used exactly as written, and the increment `j = j + 1;` inside the { } braces the user wrote is what actually advances j each iteration, doing by hand what the desugaring's own increment-injection would otherwise do automatically. WHY THIS WORKS AS AN ANSWER ------------------------------ Each of the three for-loop clauses corresponds to exactly one `if ... is None` check in for_statement(), and each of those checks controls one, independent piece of assembly (whether to prepend an initializer, what condition to loop on, whether to append an increment). Because the three checks are independent of each other, any single clause can be omitted without touching how the other two are handled -- omitting the initializer doesn't change how the increment gets appended, and vice versa. This is a direct, structural consequence of desugaring for into existing pieces rather than writing a dedicated ForStmt interpreter method that would have needed its own, separate handling for every combination of present/absent clauses.