Skip to content

Commit fdb5905

Browse files
committed
✨ proper IF statements and working recursion
1 parent ef9c303 commit fdb5905

File tree

11 files changed

+122
-16
lines changed

11 files changed

+122
-16
lines changed

PascalInterpreter/PascalInterpreter/Interpreter/Arithmetics.swift

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,4 +136,50 @@ extension Number {
136136
fatalError("Integer division DIV can only be applied to two integers")
137137
}
138138
}
139+
140+
static func < (left: Number, right: Number) -> Bool {
141+
switch (left, right) {
142+
case let (.integer(left), .integer(right)):
143+
return Double(left) < Double(right)
144+
case let (.real(left), .real(right)):
145+
return left < right
146+
case let (.integer(left), .real(right)):
147+
return Double(left) < right
148+
case let (.real(left), .integer(right)):
149+
return left < Double(right)
150+
}
151+
}
152+
153+
static func > (left: Number, right: Number) -> Bool {
154+
switch (left, right) {
155+
case let (.integer(left), .integer(right)):
156+
return Double(left) > Double(right)
157+
case let (.real(left), .real(right)):
158+
return left > right
159+
case let (.integer(left), .real(right)):
160+
return Double(left) > right
161+
case let (.real(left), .integer(right)):
162+
return left > Double(right)
163+
}
164+
}
165+
}
166+
167+
extension Value {
168+
static func < (lhs: Value, rhs: Value) -> Bool {
169+
switch (lhs, rhs) {
170+
case let (.number(left), .number(right)):
171+
return left < right
172+
default:
173+
fatalError("Cannot compare \(lhs) and \(rhs)")
174+
}
175+
}
176+
177+
static func > (lhs: Value, rhs: Value) -> Bool {
178+
switch (lhs, rhs) {
179+
case let (.number(left), .number(right)):
180+
return left > right
181+
default:
182+
fatalError("Cannot compare \(lhs) and \(rhs)")
183+
}
184+
}
139185
}

PascalInterpreter/PascalInterpreter/Interpreter/Interpreter.swift

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ public class Interpreter {
124124

125125
func eval(call: ProcedureCall) -> Value? {
126126
let current = callStack.peek()!
127-
let newScope = current.scope.level == 1 ? scopes[call.name]! : ScopedSymbolTable(name: call.name, level: scopes[call.name]!.level+1, enclosingScope: scopes[call.name]!)
127+
let newScope = current.scope.level == 1 ? scopes[call.name]! : ScopedSymbolTable(name: call.name, level: scopes[call.name]!.level + 1, enclosingScope: scopes[call.name]!)
128128
let frame = Frame(scope: newScope, previousFrame: current)
129129
callStack.push(frame)
130130
callProcedure(procedure: call.name, params: call.actualParameters, frame: frame)
@@ -137,10 +137,17 @@ public class Interpreter {
137137
let right = eval(node: condition.rightSide)
138138

139139
guard let leftResult = left, let rightResult = right else {
140-
fatalError("Invalid condition \(left) = \(right)")
140+
fatalError("Invalid condition \(String(describing: left)) = \(String(describing: right))")
141141
}
142142

143-
return .boolean(leftResult == rightResult)
143+
switch condition.type {
144+
case .equals:
145+
return .boolean(leftResult == rightResult)
146+
case .greaterThan:
147+
return .boolean(leftResult > rightResult)
148+
case .lessThan:
149+
return .boolean(leftResult < rightResult)
150+
}
144151
}
145152

146153
func eval(ifElse: IfElse) -> Value? {

PascalInterpreter/PascalInterpreter/Lexer/Lexer.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,16 @@ public class Lexer {
231231
return .equals
232232
}
233233

234+
if currentCharacter == ">" {
235+
advance()
236+
return .greaterThan
237+
}
238+
239+
if currentCharacter == "<" {
240+
advance()
241+
return .lessThan
242+
}
243+
234244
fatalError("Unrecognized character \(currentCharacter) at position \(currentPosition)")
235245
}
236246

PascalInterpreter/PascalInterpreter/Lexer/Token+Extensions.swift

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ extension Token: Equatable {
5151
return true
5252
case (.then, .then):
5353
return true
54+
case (.lessThan, .lessThan):
55+
return true
56+
case (.greaterThan, .greaterThan):
57+
return true
5458
default:
5559
return false
5660
}
@@ -168,7 +172,11 @@ extension Token: CustomStringConvertible {
168172
case .then:
169173
return "THEN"
170174
case .equals:
171-
return "EQUALS"
175+
return "EQ"
176+
case .lessThan:
177+
return "LT"
178+
case .greaterThan:
179+
return "GT"
172180
}
173181
}
174182
}

PascalInterpreter/PascalInterpreter/Lexer/Token.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,6 @@ public enum Token {
5454
case `else`
5555
case then
5656
case equals
57+
case lessThan
58+
case greaterThan
5759
}

PascalInterpreter/PascalInterpreter/Parser/AST+Extensions.swift

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,19 @@ extension BinaryOperationType: CustomStringConvertible {
6262
}
6363
}
6464

65+
extension ConditionType: CustomStringConvertible {
66+
public var description: String {
67+
switch self {
68+
case .equals:
69+
return "="
70+
case .greaterThan:
71+
return ">"
72+
case .lessThan:
73+
return "<"
74+
}
75+
}
76+
}
77+
6578
extension AST {
6679
var value: String {
6780
switch self {
@@ -95,8 +108,8 @@ extension AST {
95108
return "\(call.name)()"
96109
case is IfElse:
97110
return "IF"
98-
case is Condition:
99-
return "="
111+
case let condition as Condition:
112+
return condition.type.description
100113
default:
101114
fatalError("Missed AST case \(self)")
102115
}

PascalInterpreter/PascalInterpreter/Parser/AST.swift

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ public enum UnaryOperationType {
2121
case minus
2222
}
2323

24+
public enum ConditionType {
25+
case equals
26+
case lessThan
27+
case greaterThan
28+
}
29+
2430
public enum Number: AST {
2531
case integer(Int)
2632
case real(Double)
@@ -154,10 +160,12 @@ class ProcedureCall: AST {
154160
}
155161

156162
class Condition: AST {
163+
let type: ConditionType
157164
let leftSide: AST
158165
let rightSide: AST
159166

160-
init(leftSide: AST, rightSide: AST) {
167+
init(type: ConditionType, leftSide: AST, rightSide: AST) {
168+
self.type = type
161169
self.leftSide = leftSide
162170
self.rightSide = rightSide
163171
}

PascalInterpreter/PascalInterpreter/Parser/Parser.swift

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -316,15 +316,28 @@ public class Parser {
316316

317317
/**
318318
Rule:
319-
condition: expr = expr
319+
condition: expr (= | < | >) expr
320320
*/
321321
private func condition() -> Condition {
322322
eat(.parenthesis(.left))
323323
let left = expr()
324-
eat(.equals)
324+
var type: ConditionType = .equals
325+
switch currentToken {
326+
case .equals:
327+
eat(.equals)
328+
type = .equals
329+
case .lessThan:
330+
eat(.lessThan)
331+
type = .lessThan
332+
case .greaterThan:
333+
eat(.greaterThan)
334+
type = .greaterThan
335+
default:
336+
fatalError("Invalid condition type \(type)")
337+
}
325338
let right = expr()
326339
eat(.parenthesis(.right))
327-
return Condition(leftSide: left, rightSide: right)
340+
return Condition(type: type, leftSide: left, rightSide: right)
328341
}
329342

330343
/**

PascalInterpreter/PascalInterpreterTests/ParserTests.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ class ParserTests: XCTestCase {
286286
let result = parser.parse()
287287
let xDec = VariableDeclaration(variable: Variable(name: "x"), type: VariableType(type: .real))
288288
let yDec = VariableDeclaration(variable: Variable(name: "y"), type: VariableType(type: .real))
289-
let compound = Compound(children: [Assignment(left: Variable(name: "y"), right: Number.integer(5)), IfElse(condition: Condition(leftSide: Variable(name: "y"), rightSide: Number.integer(5)), trueExpression: Assignment(left: Variable(name: "x"), right: Number.integer(2)), falseExpression: Assignment(left: Variable(name: "x"), right: Number.integer(3)))])
289+
let compound = Compound(children: [Assignment(left: Variable(name: "y"), right: Number.integer(5)), IfElse(condition: Condition(type: .equals, leftSide: Variable(name: "y"), rightSide: Number.integer(5)), trueExpression: Assignment(left: Variable(name: "x"), right: Number.integer(2)), falseExpression: Assignment(left: Variable(name: "x"), right: Number.integer(3)))])
290290
let node = Program(name: "Main", block: Block(declarations: [xDec, yDec], compound: compound))
291291
XCTAssertEqual(result, node)
292292
}
@@ -307,7 +307,7 @@ class ParserTests: XCTestCase {
307307
let result = parser.parse()
308308
let xDec = VariableDeclaration(variable: Variable(name: "x"), type: VariableType(type: .real))
309309
let yDec = VariableDeclaration(variable: Variable(name: "y"), type: VariableType(type: .real))
310-
let compound = Compound(children: [Assignment(left: Variable(name: "y"), right: Number.integer(5)), IfElse(condition: Condition(leftSide: Variable(name: "y"), rightSide: Number.integer(5)), trueExpression: Assignment(left: Variable(name: "x"), right: Number.integer(2)), falseExpression: nil)])
310+
let compound = Compound(children: [Assignment(left: Variable(name: "y"), right: Number.integer(5)), IfElse(condition: Condition(type: .equals, leftSide: Variable(name: "y"), rightSide: Number.integer(5)), trueExpression: Assignment(left: Variable(name: "x"), right: Number.integer(2)), falseExpression: nil)])
311311
let node = Program(name: "Main", block: Block(declarations: [xDec, yDec], compound: compound))
312312
XCTAssertEqual(result, node)
313313
}

PascalInterpreter/PascalInterpreterTests/XCTestCase+FatalError.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ func XCTAssertEqual(_ left: AST, _ right: AST) {
103103
XCTAssert(left.name == right.name)
104104
XCTAssertEqual(left.type, right.type)
105105
case let (left as Condition, right as Condition):
106+
XCTAssertEqual(left.type, right.type)
106107
XCTAssertEqual(left.leftSide, right.leftSide)
107108
XCTAssertEqual(left.rightSide, right.rightSide)
108109
case let (left as IfElse, right as IfElse):
@@ -115,10 +116,10 @@ func XCTAssertEqual(_ left: AST, _ right: AST) {
115116
default:
116117
break
117118
}
119+
XCTAssertEqual(left.condition, right.condition)
118120
if let leftFalse = left.falseExpression, let rightFalse = right.falseExpression {
119121
XCTAssertEqual(leftFalse, rightFalse)
120122
}
121-
XCTAssertEqual(left.condition, right.condition)
122123
default:
123124
XCTFail("\(left) and \(right) are not equal")
124125
}

0 commit comments

Comments
 (0)