Skip to content

Commit c76bc9d

Browse files
authored
Merge pull request #17 from igorkulman/builtin-functions
Builtin functions
2 parents 689b626 + 3cb8444 commit c76bc9d

33 files changed

+904
-69
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,4 @@ fastlane/report.xml
6565
fastlane/Preview.html
6666
fastlane/screenshots
6767
fastlane/test_output
68+
/Examples/SPI

Examples/factorial.pas

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
program Main;
2+
var input, result: integer;
3+
4+
function Factorial(number: Integer): Integer;
5+
begin
6+
if (number > 1) then
7+
Factorial := number * Factorial(number-1)
8+
else
9+
Factorial := 1
10+
end;
11+
12+
begin { Main }
13+
writeln('Factorial');
14+
writeln('');
15+
writeln('Enter number and press Enter');
16+
read(input);
17+
result := Factorial(input);
18+
writeln('');
19+
writeln(input,'! = ', result)
20+
end. { Main }

Examples/helloworld.pas

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Program HelloWorld;
2+
Begin
3+
Writeln('Hello World');
4+
End.

Examples/name.pas

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
Program Name;
2+
Var name, surname: String;
3+
4+
Begin
5+
write('Enter your name:');
6+
read(name);
7+
write('Enter your surname:');
8+
read(surname);
9+
writeln();{new line}
10+
writeln();{new line}
11+
writeln('Your full name is: ',name,' ',surname);
12+
End.

Examples/numbers.pas

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Program Numbers;
2+
Var
3+
Num1, Num2, Sum : Integer;
4+
5+
Begin {no semicolon}
6+
Write('Input number 1:');
7+
Read(Num1);
8+
Write('Input number 2:');
9+
Read(Num2);
10+
Sum := Num1 + Num2; {addition}
11+
Writeln();
12+
Writeln(Num1,'+', Num2,'=', Sum);
13+
End.

Images/cli.gif

990 KB
Loading

PascalInterpreter/.swiftlint.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ disabled_rules:
77
- function_body_length
88
- type_body_length
99
- file_length
10+
- large_tuple

PascalInterpreter/PascalInterpreter.xcodeproj/project.pbxproj

Lines changed: 5 additions & 1 deletion
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+
F3D90E131FE6A0C600FA79B3 /* Interpreter+Standard.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3D90E121FE6A0C600FA79B3 /* Interpreter+Standard.swift */; };
3334
F3EF28D01FE12EBF001F36AB /* Frame.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3EF28CF1FE12EBF001F36AB /* Frame.swift */; };
3435
F3EF28D21FE12F4D001F36AB /* Stack.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3EF28D11FE12F4D001F36AB /* Stack.swift */; };
3536
/* End PBXBuildFile section */
@@ -71,6 +72,7 @@
7172
F300A0EC1FDDB77000E5894D /* InterpreterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InterpreterTests.swift; sourceTree = "<group>"; };
7273
F300A0ED1FDDB77000E5894D /* SemanticAnalyzerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SemanticAnalyzerTests.swift; sourceTree = "<group>"; };
7374
F34109A71FE2683900271A57 /* Visitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Visitor.swift; sourceTree = "<group>"; };
75+
F3D90E121FE6A0C600FA79B3 /* Interpreter+Standard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Interpreter+Standard.swift"; sourceTree = "<group>"; };
7476
F3EF28CF1FE12EBF001F36AB /* Frame.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Frame.swift; sourceTree = "<group>"; };
7577
F3EF28D11FE12F4D001F36AB /* Stack.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Stack.swift; sourceTree = "<group>"; };
7678
/* End PBXFileReference section */
@@ -142,8 +144,9 @@
142144
F300A0C51FDDB6BE00E5894D /* Arithmetics.swift */,
143145
F3EF28CF1FE12EBF001F36AB /* Frame.swift */,
144146
F300A0C61FDDB6BE00E5894D /* Interpreter.swift */,
145-
F300A0C41FDDB6BD00E5894D /* Value.swift */,
147+
F3D90E121FE6A0C600FA79B3 /* Interpreter+Standard.swift */,
146148
F3EF28D11FE12F4D001F36AB /* Stack.swift */,
149+
F300A0C41FDDB6BD00E5894D /* Value.swift */,
147150
);
148151
path = Interpreter;
149152
sourceTree = "<group>";
@@ -348,6 +351,7 @@
348351
F300A0C91FDDB6BE00E5894D /* Interpreter.swift in Sources */,
349352
F3EF28D01FE12EBF001F36AB /* Frame.swift in Sources */,
350353
F300A0C71FDDB6BE00E5894D /* Value.swift in Sources */,
354+
F3D90E131FE6A0C600FA79B3 /* Interpreter+Standard.swift in Sources */,
351355
F3EF28D21FE12F4D001F36AB /* Stack.swift in Sources */,
352356
F300A0E71FDDB74800E5894D /* SymbolTable.swift in Sources */,
353357
F300A0D81FDDB6F400E5894D /* AST+Extensions.swift in Sources */,

PascalInterpreter/PascalInterpreter/Interpreter/Frame.swift

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ class Frame {
1212
var integerMemory: [String: Int] = [:]
1313
var realMemory: [String: Double] = [:]
1414
var booleanMemory: [String: Bool] = [:]
15+
var stringMemory: [String: String] = [:]
1516
let scope: ScopedSymbolTable
1617
let previousFrame: Frame?
17-
var returnValue: Value?
18+
var returnValue: Value = .none
1819

1920
init(scope: ScopedSymbolTable, previousFrame: Frame?) {
2021
self.scope = scope
@@ -43,8 +44,8 @@ class Frame {
4344
case .real:
4445
fatalError("Cannot assign Real value to Int variable \(variable)")
4546
}
46-
case .boolean:
47-
fatalError("Cannot assign Boolean value to Int variable \(variable)")
47+
default:
48+
fatalError("Cannot assign \(value) to Int variable \(variable)")
4849
}
4950
case .real:
5051
switch value {
@@ -55,8 +56,8 @@ class Frame {
5556
case let .real(value):
5657
realMemory[variable] = value
5758
}
58-
case .boolean:
59-
fatalError("Cannot assign Boolean value to Real variable \(variable)")
59+
default:
60+
fatalError("Cannot assign \(value) to Real variable \(variable)")
6061
}
6162
case .boolean:
6263
switch value {
@@ -65,6 +66,13 @@ class Frame {
6566
default:
6667
fatalError("Cannot assign \(value) value to Boolean variable \(variable)")
6768
}
69+
case .string:
70+
switch value {
71+
case let .string(string):
72+
stringMemory[variable] = string
73+
default:
74+
fatalError("Cannot assign \(value) value to String variable \(variable)")
75+
}
6876
}
6977
return
7078
}
@@ -86,6 +94,8 @@ class Frame {
8694
return .number(.real(realMemory[variable]!))
8795
case .boolean:
8896
return .boolean(booleanMemory[variable]!)
97+
case .string:
98+
return .string(stringMemory[variable]!)
8999
}
90100
}
91101

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
//
2+
// Interpreter+Standard.swift
3+
// PascalInterpreter
4+
//
5+
// Created by Igor Kulman on 17/12/2017.
6+
// Copyright © 2017 Igor Kulman. All rights reserved.
7+
//
8+
9+
import Foundation
10+
11+
extension Interpreter {
12+
func callBuiltInProcedure(procedure: String, params: [AST], frame: Frame) -> Value {
13+
switch procedure.uppercased() {
14+
case "WRITE":
15+
write(params: params, newLine: false)
16+
return .none
17+
case "WRITELN":
18+
write(params: params, newLine: true)
19+
return .none
20+
case "READ":
21+
read(params: params, frame: frame)
22+
return .none
23+
case "READLN":
24+
read(params: params, frame: frame)
25+
return .none
26+
default:
27+
fatalError("Implement built in procedure \(procedure)")
28+
}
29+
}
30+
31+
private func write(params: [AST], newLine: Bool) {
32+
var s = ""
33+
for param in params {
34+
let value = eval(node: param)
35+
switch value {
36+
case let .boolean(value):
37+
s += value ? "TRUE" : "FALSE"
38+
case let .number(number):
39+
switch number {
40+
case let .integer(value):
41+
s += String(value)
42+
case let .real(value):
43+
s += String(value)
44+
}
45+
case let .string(value):
46+
s += value
47+
case .none:
48+
fatalError("Cannot use WRITE with expression without a value")
49+
}
50+
}
51+
if newLine {
52+
print(s)
53+
} else {
54+
print(s, terminator: "")
55+
}
56+
}
57+
58+
private func read(params: [AST], frame: Frame) {
59+
guard let line = readLine() else {
60+
fatalError("Empty input")
61+
}
62+
63+
let parts = line.components(separatedBy: CharacterSet.whitespaces)
64+
for i in 0 ... params.count - 1 {
65+
let param = params[i]
66+
guard let variable = param as? Variable else {
67+
fatalError("READ parameter must be a variable")
68+
}
69+
guard let symbol = frame.scope.lookup(variable.name), let variableSymbol = symbol as? VariableSymbol, let type = variableSymbol.type as? BuiltInTypeSymbol else {
70+
fatalError("Symbol(variable) not found '\(variable.name)'")
71+
}
72+
switch type {
73+
case .integer:
74+
frame.set(variable: variable.name, value: .number(.integer(Int(parts[i])!)))
75+
case .real:
76+
frame.set(variable: variable.name, value: .number(.real(Double(parts[i])!)))
77+
case .boolean:
78+
frame.set(variable: variable.name, value: .boolean(Bool(parts[i])!))
79+
case .string:
80+
frame.set(variable: variable.name, value: .string((parts[i])))
81+
}
82+
}
83+
}
84+
}

0 commit comments

Comments
 (0)