Skip to content

Commit 31eafc0

Browse files
committed
♻️ simpler Interpreter memory storage
1 parent 47793f8 commit 31eafc0

File tree

9 files changed

+96
-144
lines changed

9 files changed

+96
-144
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,5 @@ fastlane/Preview.html
6666
fastlane/screenshots
6767
fastlane/test_output
6868
/Examples/SPI
69+
/PascalInterpreter/.DS_Store
70+
.DS_Store

PascalInterpreter/PascalInterpreter.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
F300A0F11FDDB77000E5894D /* InterpreterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F300A0EC1FDDB77000E5894D /* InterpreterTests.swift */; };
3131
F300A0F21FDDB77000E5894D /* SemanticAnalyzerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F300A0ED1FDDB77000E5894D /* SemanticAnalyzerTests.swift */; };
3232
F34109A81FE2683900271A57 /* Visitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = F34109A71FE2683900271A57 /* Visitor.swift */; };
33+
F385A7DB1FF109E5004BAD6F /* Value+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F385A7DA1FF109E5004BAD6F /* Value+Extensions.swift */; };
3334
F3D90E131FE6A0C600FA79B3 /* Interpreter+Standard.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3D90E121FE6A0C600FA79B3 /* Interpreter+Standard.swift */; };
3435
F3EF28D01FE12EBF001F36AB /* Frame.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3EF28CF1FE12EBF001F36AB /* Frame.swift */; };
3536
F3EF28D21FE12F4D001F36AB /* Stack.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3EF28D11FE12F4D001F36AB /* Stack.swift */; };
@@ -72,6 +73,7 @@
7273
F300A0EC1FDDB77000E5894D /* InterpreterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InterpreterTests.swift; sourceTree = "<group>"; };
7374
F300A0ED1FDDB77000E5894D /* SemanticAnalyzerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SemanticAnalyzerTests.swift; sourceTree = "<group>"; };
7475
F34109A71FE2683900271A57 /* Visitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Visitor.swift; sourceTree = "<group>"; };
76+
F385A7DA1FF109E5004BAD6F /* Value+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Value+Extensions.swift"; sourceTree = "<group>"; };
7577
F3D90E121FE6A0C600FA79B3 /* Interpreter+Standard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Interpreter+Standard.swift"; sourceTree = "<group>"; };
7678
F3EF28CF1FE12EBF001F36AB /* Frame.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Frame.swift; sourceTree = "<group>"; };
7779
F3EF28D11FE12F4D001F36AB /* Stack.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Stack.swift; sourceTree = "<group>"; };
@@ -147,6 +149,7 @@
147149
F3D90E121FE6A0C600FA79B3 /* Interpreter+Standard.swift */,
148150
F3EF28D11FE12F4D001F36AB /* Stack.swift */,
149151
F300A0C41FDDB6BD00E5894D /* Value.swift */,
152+
F385A7DA1FF109E5004BAD6F /* Value+Extensions.swift */,
150153
);
151154
path = Interpreter;
152155
sourceTree = "<group>";
@@ -353,6 +356,7 @@
353356
F300A0C71FDDB6BE00E5894D /* Value.swift in Sources */,
354357
F3D90E131FE6A0C600FA79B3 /* Interpreter+Standard.swift in Sources */,
355358
F3EF28D21FE12F4D001F36AB /* Stack.swift in Sources */,
359+
F385A7DB1FF109E5004BAD6F /* Value+Extensions.swift in Sources */,
356360
F300A0E71FDDB74800E5894D /* SymbolTable.swift in Sources */,
357361
F300A0D81FDDB6F400E5894D /* AST+Extensions.swift in Sources */,
358362
F34109A81FE2683900271A57 /* Visitor.swift in Sources */,

PascalInterpreter/PascalInterpreter/Interpreter/Frame.swift

Lines changed: 18 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,7 @@
99
import Foundation
1010

1111
class Frame {
12-
var integerMemory: [String: Int] = [:]
13-
var realMemory: [String: Double] = [:]
14-
var booleanMemory: [String: Bool] = [:]
15-
var stringMemory: [String: String] = [:]
12+
var memory: [String: Value] = [:]
1613
let scope: ScopedSymbolTable
1714
let previousFrame: Frame?
1815
var returnValue: Value = .none
@@ -23,21 +20,7 @@ class Frame {
2320
}
2421

2522
func remove(variable: String) {
26-
if let symbol = scope.lookup(variable, currentScopeOnly: true),
27-
let variableSymbol = symbol as? VariableSymbol,
28-
let type = variableSymbol.type as? BuiltInTypeSymbol {
29-
30-
switch type {
31-
case .integer:
32-
integerMemory.removeValue(forKey: variable)
33-
case .real:
34-
realMemory.removeValue(forKey: variable)
35-
case .boolean:
36-
booleanMemory.removeValue(forKey: variable)
37-
case .string:
38-
stringMemory.removeValue(forKey: variable)
39-
}
40-
}
23+
memory.removeValue(forKey: variable)
4124
}
4225

4326
func set(variable: String, value: Value) {
@@ -52,46 +35,21 @@ class Frame {
5235
let variableSymbol = symbol as? VariableSymbol,
5336
let type = variableSymbol.type as? BuiltInTypeSymbol {
5437

55-
switch type {
56-
case .integer:
57-
switch value {
58-
case let .number(number):
59-
switch number {
60-
case let .integer(value):
61-
integerMemory[variable] = value
62-
case .real:
63-
fatalError("Cannot assign Real value to Int variable \(variable)")
64-
}
65-
default:
66-
fatalError("Cannot assign \(value) to Int variable \(variable)")
67-
}
68-
case .real:
69-
switch value {
70-
case let .number(number):
71-
switch number {
72-
case let .integer(value):
73-
realMemory[variable] = Double(value)
74-
case let .real(value):
75-
realMemory[variable] = value
76-
}
77-
default:
78-
fatalError("Cannot assign \(value) to Real variable \(variable)")
79-
}
80-
case .boolean:
81-
switch value {
82-
case let .boolean(boolean):
83-
booleanMemory[variable] = boolean
84-
default:
85-
fatalError("Cannot assign \(value) value to Boolean variable \(variable)")
86-
}
87-
case .string:
88-
switch value {
89-
case let .string(string):
90-
stringMemory[variable] = string
91-
default:
92-
fatalError("Cannot assign \(value) value to String variable \(variable)")
93-
}
38+
switch (value, type) {
39+
case (.number(.integer), .integer ):
40+
memory[variable] = value
41+
case (.number(.integer(let value)), .real ):
42+
memory[variable] = .number(.real(Double(value)))
43+
case (.number(.real), .real ):
44+
memory[variable] = value
45+
case (.boolean, .boolean ):
46+
memory[variable] = value
47+
case (.string, .string ):
48+
memory[variable] = value
49+
default:
50+
fatalError("Cannot assing \(value) to \(type)")
9451
}
52+
9553
return
9654
}
9755

@@ -101,20 +59,8 @@ class Frame {
10159

10260
func get(variable: String) -> Value {
10361
// variable define in current scole (procedure declataion, etc)
104-
if let symbol = scope.lookup(variable, currentScopeOnly: true),
105-
let variableSymbol = symbol as? VariableSymbol,
106-
let type = variableSymbol.type as? BuiltInTypeSymbol {
107-
108-
switch type {
109-
case .integer:
110-
return .number(.integer(integerMemory[variable]!))
111-
case .real:
112-
return .number(.real(realMemory[variable]!))
113-
case .boolean:
114-
return .boolean(booleanMemory[variable]!)
115-
case .string:
116-
return .string(stringMemory[variable]!)
117-
}
62+
if scope.lookup(variable, currentScopeOnly: true) != nil {
63+
return memory[variable]!
11864
}
11965

12066
// previous scope, eg global

PascalInterpreter/PascalInterpreter/Interpreter/Interpreter.swift

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -236,15 +236,12 @@ public class Interpreter {
236236
eval(node: tree)
237237
}
238238

239-
func getState() -> ([String: Int], [String: Double], [String: Bool], [String: String]) {
240-
return (callStack.peek()!.integerMemory, callStack.peek()!.realMemory, callStack.peek()!.booleanMemory, callStack.peek()!.stringMemory)
239+
func getState() -> ([String: Value]) {
240+
return (callStack.peek()!.memory)
241241
}
242242

243243
public func printState() {
244244
print("Final interpreter memory state (\(callStack.peek()!.scope.name)):")
245-
print("Int: \(callStack.peek()!.integerMemory)")
246-
print("Real: \(callStack.peek()!.realMemory)")
247-
print("Boolean: \(callStack.peek()!.booleanMemory)")
248-
print("String: \(callStack.peek()!.stringMemory)")
245+
print(callStack.peek()!.memory)
249246
}
250247
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//
2+
// Value+Extensions.swift
3+
// PascalInterpreter
4+
//
5+
// Created by Igor Kulman on 25/12/2017.
6+
// Copyright © 2017 Igor Kulman. All rights reserved.
7+
//
8+
9+
import Foundation
10+
11+
extension Value: Equatable {
12+
static func == (lhs: Value, rhs: Value) -> Bool {
13+
switch (lhs, rhs) {
14+
case let (.number(left), .number(right)):
15+
return left == right
16+
case let (.boolean(left), .boolean(right)):
17+
return left == right
18+
case let (.string(left), .string(right)):
19+
return left == right
20+
default:
21+
return false
22+
}
23+
}
24+
}
25+
26+
extension Value: CustomStringConvertible {
27+
public var description: String {
28+
switch self {
29+
case .none:
30+
return "NIL"
31+
case .boolean(let value):
32+
return "BOOLEAN(\(value))"
33+
case .string(let value):
34+
return "STRING(\(value))"
35+
case .number(let number):
36+
switch number {
37+
case .integer(let value):
38+
return "INTEGER(\(value)"
39+
case .real(let value):
40+
return "REAL(\(value)"
41+
}
42+
}
43+
}
44+
}

PascalInterpreter/PascalInterpreter/Interpreter/Value.swift

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,3 @@ enum Value {
1414
case boolean(Bool)
1515
case string(String)
1616
}
17-
18-
extension Value: Equatable {
19-
static func == (lhs: Value, rhs: Value) -> Bool {
20-
switch (lhs, rhs) {
21-
case let (.number(left), .number(right)):
22-
return left == right
23-
case let (.boolean(left), .boolean(right)):
24-
return left == right
25-
case let (.string(left), .string(right)):
26-
return left == right
27-
default:
28-
return false
29-
}
30-
}
31-
}

PascalInterpreter/PascalInterpreter/Lexer/Lexer.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public class Lexer {
4343
"FOR": .for,
4444
"TO": .to,
4545
"DO": .do,
46-
"WHILE": .while,
46+
"WHILE": .while
4747
]
4848

4949
public init(_ text: String) {

PascalInterpreter/PascalInterpreterTests/InterpreterTests.swift

Lines changed: 20 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,8 @@ class InterpreterTests: XCTestCase {
2525

2626
let interpeter = Interpreter(program)
2727
interpeter.interpret()
28-
let (integerState, realState, boolState, stringState) = interpeter.getState()
29-
XCTAssert(integerState == ["a": 2])
30-
XCTAssert(realState == [:])
31-
XCTAssert(boolState == [:])
32-
XCTAssert(stringState == [:])
28+
let state = interpeter.getState()
29+
XCTAssert(state == ["a": Value.number(.integer(2))])
3330
}
3431

3532
func testMoreComplexProgram() {
@@ -51,11 +48,8 @@ class InterpreterTests: XCTestCase {
5148

5249
let interpeter = Interpreter(program)
5350
interpeter.interpret()
54-
let (integerState, realState, boolState, stringState) = interpeter.getState()
55-
XCTAssert(integerState == ["b": 25, "number": 2, "a": 2, "x": 11, "c": 27])
56-
XCTAssert(realState == [:])
57-
XCTAssert(boolState == [:])
58-
XCTAssert(stringState == [:])
51+
let state = interpeter.getState()
52+
XCTAssert(state == ["b": Value.number(.integer(25)), "number": Value.number(.integer(2)), "a": Value.number(.integer(2)), "x": Value.number(.integer(11)), "c": Value.number(.integer(27))])
5953
}
6054

6155
func testProgramWithDeclarations() {
@@ -75,11 +69,8 @@ class InterpreterTests: XCTestCase {
7569

7670
let interpeter = Interpreter(program)
7771
interpeter.interpret()
78-
let (integerState, realState, boolState, stringState) = interpeter.getState()
79-
XCTAssert(integerState == ["b": 25, "a": 2])
80-
XCTAssert(realState == ["y": 5.9971428571428573])
81-
XCTAssert(boolState == [:])
82-
XCTAssert(stringState == [:])
72+
let state = interpeter.getState()
73+
XCTAssert(state == ["b": Value.number(.integer(25)), "a": Value.number(.integer(2)), "y": Value.number(.real( 5.9971428571428573))])
8374
}
8475

8576
func testProgramWithProcedureCallAndNoParameters() {
@@ -103,11 +94,8 @@ class InterpreterTests: XCTestCase {
10394

10495
let interpeter = Interpreter(program)
10596
interpeter.interpret()
106-
let (integerState, realState, boolState, stringState) = interpeter.getState()
107-
XCTAssert(integerState == [:])
108-
XCTAssert(realState == ["x": 7, "y": 5])
109-
XCTAssert(boolState == [:])
110-
XCTAssert(stringState == [:])
97+
let state = interpeter.getState()
98+
XCTAssert(state == ["x": Value.number(.real(7)), "y": Value.number(.real( 5))])
11199
}
112100

113101
func testProgramWithProcedureCallAndParameters() {
@@ -129,11 +117,8 @@ class InterpreterTests: XCTestCase {
129117

130118
let interpeter = Interpreter(program)
131119
interpeter.interpret()
132-
let (integerState, realState, boolState, stringState) = interpeter.getState()
133-
XCTAssert(integerState == [:])
134-
XCTAssert(realState == ["x": 5, "y": 3])
135-
XCTAssert(boolState == [:])
136-
XCTAssert(stringState == [:])
120+
let state = interpeter.getState()
121+
XCTAssert(state == ["x": Value.number(.real(5)), "y": Value.number(.real(3))])
137122
}
138123

139124
func testProgramWithRecursiveFunction() {
@@ -157,11 +142,8 @@ class InterpreterTests: XCTestCase {
157142

158143
let interpeter = Interpreter(program)
159144
interpeter.interpret()
160-
let (integerState, realState, boolState, stringState) = interpeter.getState()
161-
XCTAssert(realState == [:])
162-
XCTAssert(integerState == ["result": 720])
163-
XCTAssert(boolState == [:])
164-
XCTAssert(stringState == [:])
145+
let state = interpeter.getState()
146+
XCTAssert(state == ["result": Value.number(.integer(720))])
165147
}
166148

167149
func testProgramWithRecursiveAndBuiltInFunctions() {
@@ -186,11 +168,8 @@ class InterpreterTests: XCTestCase {
186168

187169
let interpeter = Interpreter(program)
188170
interpeter.interpret()
189-
let (integerState, realState, boolState, stringState) = interpeter.getState()
190-
XCTAssert(realState == [:])
191-
XCTAssert(integerState == ["result": 720])
192-
XCTAssert(boolState == [:])
193-
XCTAssert(stringState == [:])
171+
let state = interpeter.getState()
172+
XCTAssert(state == ["result": Value.number(.integer(720))])
194173
}
195174

196175
func testProgramWithRecursiveFunctionsAndParameterTheSameName() {
@@ -215,11 +194,8 @@ class InterpreterTests: XCTestCase {
215194

216195
let interpeter = Interpreter(program)
217196
interpeter.interpret()
218-
let (integerState, realState, boolState, stringState) = interpeter.getState()
219-
XCTAssert(realState == [:])
220-
XCTAssert(integerState == ["result": 720, "number": 6])
221-
XCTAssert(boolState == [:])
222-
XCTAssert(stringState == [:])
197+
let state = interpeter.getState()
198+
XCTAssert(state == ["result": Value.number(.integer(720)), "number": Value.number(.integer(6))])
223199
}
224200

225201
func testProgramWithRepeatUntil() {
@@ -239,11 +215,8 @@ class InterpreterTests: XCTestCase {
239215

240216
let interpeter = Interpreter(program)
241217
interpeter.interpret()
242-
let (integerState, realState, boolState, stringState) = interpeter.getState()
243-
XCTAssert(realState == [:])
244-
XCTAssert(integerState == ["x": 6])
245-
XCTAssert(boolState == [:])
246-
XCTAssert(stringState == [:])
218+
let state = interpeter.getState()
219+
XCTAssert(state == ["x": Value.number(.integer(6))])
247220
}
248221

249222
func testProgramWithForLoop() {
@@ -262,10 +235,7 @@ class InterpreterTests: XCTestCase {
262235

263236
let interpeter = Interpreter(program)
264237
interpeter.interpret()
265-
let (integerState, realState, boolState, stringState) = interpeter.getState()
266-
XCTAssert(realState == [:])
267-
XCTAssert(integerState == ["x": 6])
268-
XCTAssert(boolState == [:])
269-
XCTAssert(stringState == [:])
238+
let state = interpeter.getState()
239+
XCTAssert(state == ["x": Value.number(.integer(6))])
270240
}
271241
}

0 commit comments

Comments
 (0)