Skip to content

Commit

Permalink
While loop
Browse files Browse the repository at this point in the history
  • Loading branch information
theSalted committed Jul 1, 2024
1 parent 70ad862 commit c8a1fbc
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 5 deletions.
4 changes: 4 additions & 0 deletions Sources/Lox/AbstractSyntaxTreePrinter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ public struct AbstractSyntaxTreePrinter: StatementVisitor, ExpressionVisitor {
public func visit(_ expr: Variable) -> String {
expr.name.lexeme
}

public func visit(_ stmt: While) -> String {
parenthesize(name: "while", parts: stmt.condition, stmt.body)
}
}

extension AbstractSyntaxTreePrinter {
Expand Down
15 changes: 15 additions & 0 deletions Sources/Lox/Definitions/Statement.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public protocol StatementVisitor {
func visit(_ stmt: If) -> StatementVisitorReturn
func visit(_ stmt: Block) -> StatementVisitorReturn
func visit(_ stmt: Var) -> StatementVisitorReturn
func visit(_ stmt: While) -> StatementVisitorReturn
func visit(_ stmt: Print) -> StatementVisitorReturn
}

Expand Down Expand Up @@ -74,6 +75,20 @@ public struct Var: Statement {
}
}

public struct While: Statement {
let condition: Expression
let body: Statement

init(condition: Expression, body: Statement) {
self.condition = condition
self.body = body
}

public func accept<V: StatementVisitor, R>(visitor: V) -> R where R == V.StatementVisitorReturn {
return visitor.visit(self)
}
}

public struct Print: Statement {
let expression: Expression

Expand Down
17 changes: 12 additions & 5 deletions Sources/Lox/Interpreter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public final class Interpreter: StatementVisitor, ExpressionVisitor {

func interpret(_ statements: Array<Statement>) {
for statement in statements {
let result = execute(stmt: statement)
let result = execute(statement)
if case let .failure(error) = result {
Lox.reportError(error)
}
Expand Down Expand Up @@ -43,9 +43,9 @@ public final class Interpreter: StatementVisitor, ExpressionVisitor {

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

return nil
Expand Down Expand Up @@ -260,14 +260,21 @@ public final class Interpreter: StatementVisitor, ExpressionVisitor {
}
}

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

public typealias Value = Result<Any, InterpreterError>
public typealias ExpressionVisitorReturn = Value?
public typealias StatementVisitorReturn = Value?
}

extension Interpreter {
@discardableResult
private func execute(stmt: Statement) -> Value? {
private func execute(_ stmt: Statement) -> Value? {
let value = stmt.accept(visitor: self)
return value
}
Expand All @@ -281,7 +288,7 @@ extension Interpreter {
}

for statement in statements {
let result = execute(stmt: statement)
let result = execute(statement)
if case let .failure(error) = result {
return .failure(error)
}
Expand Down
15 changes: 15 additions & 0 deletions Sources/Lox/Parser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,28 @@ public class Parser {
private func statement() throws -> Statement {
if match(.if) { return try ifStatement() }
if match(.print) { return try printStatement() }
if match(.while) { return try whileStatement() }
if match(.leftBrace) {
return Block(statements: try block())
}

return try expressionStatement()
}

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

let condition = try expression()

do { try consume(.rightParenthesis) }
catch { throw reportError("Expect ')' after condition.", token: latestToken) }

let body = try statement()

return While(condition: condition, body: body)
}

private func variableDeclaration() throws -> Statement {
let name: Token
do { name = try consume(.identifier) }
Expand Down
4 changes: 4 additions & 0 deletions Sources/SyntaxDefinitionGenerator/Resources/statement.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
"name": "Var",
"parameterField": "name: Token, initializer: Expression?"
},
{
"name": "While",
"parameterField": "condition: Expression, body: Statement"
},
{
"name": "Print",
"parameterField": "expression: Expression"
Expand Down

0 comments on commit c8a1fbc

Please sign in to comment.