Skip to content

Commit

Permalink
Faulty implementation of for loop
Browse files Browse the repository at this point in the history
  • Loading branch information
theSalted committed Jul 1, 2024
1 parent c8a1fbc commit 997f599
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 4 deletions.
14 changes: 10 additions & 4 deletions Sources/Lox/Interpreter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,13 @@ public final class Interpreter: StatementVisitor, ExpressionVisitor {

public func visit(_ stmt: If) -> Value? {
if determineTruthy(evaluate(stmt.condition)) {
execute(stmt.then)
if case .failure(let error) = execute(stmt.then) {
return .failure(error)
}
} else if let `else` = stmt.else {
execute(`else`)
if case .failure(let error) = execute(`else`) {
return .failure(error)
}
}

return nil
Expand Down Expand Up @@ -262,7 +266,10 @@ public final class Interpreter: StatementVisitor, ExpressionVisitor {

public func visit(_ stmt: While) -> Value? {
while determineTruthy(evaluate(stmt.condition)) {
execute(stmt.body)

if case .failure(let error) = execute(stmt.body) {
return .failure(error)
}
}
return nil
}
Expand All @@ -273,7 +280,6 @@ public final class Interpreter: StatementVisitor, ExpressionVisitor {
}

extension Interpreter {
@discardableResult
private func execute(_ stmt: Statement) -> Value? {
let value = stmt.accept(visitor: self)
return value
Expand Down
38 changes: 38 additions & 0 deletions Sources/Lox/Parser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ public class Parser {
}

private func statement() throws -> Statement {
if match(.for) { return try forStatement() }
if match(.if) { return try ifStatement() }
if match(.print) { return try printStatement() }
if match(.while) { return try whileStatement() }
Expand All @@ -66,6 +67,43 @@ public class Parser {
return try expressionStatement()
}

private func forStatement() throws -> Statement {
do { try consume(.leftParenthesis) }
catch { throw reportError("Expect '(' after for 'for'.", token: latestToken) }

let initializer: Statement?
if match(.semicolon) {
initializer = nil
} else if match(.var) {
initializer = try variableDeclaration()
} else {
initializer = try expressionStatement()
}

let condition: Expression = matchLatest(.semicolon) ? Literal(value: true) : try expression()
do { try consume(.semicolon) }
catch { throw reportError("Expect ';' after loop condition.", token: latestToken) }

let increment: Expression? = matchLatest(.rightParenthesis) ? nil : try expression()
do { try consume(.rightParenthesis) }
catch { throw reportError("Expect ')' after for clauses.", token: latestToken) }

var body = try statement()

if let increment {
body = Block(statements: [body, Expr(expression: increment)])
}

body = While(condition: condition, body: body)

if let initializer {
body = Block(statements: [initializer, body])
}


return body
}

private func whileStatement() throws -> Statement {
do { try consume(.leftParenthesis) }
catch { throw reportError("Expect '(' after 'while'.", token: latestToken) }
Expand Down

0 comments on commit 997f599

Please sign in to comment.