Skip to content

Commit 7d6dac0

Browse files
committed
Implement source code manager.
1 parent 35d98a9 commit 7d6dac0

File tree

5 files changed

+167
-4
lines changed

5 files changed

+167
-4
lines changed

LispKit.xcodeproj/project.pbxproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,8 @@
181181
CCDF99FC1D3D7A3100FD2A57 /* BoxLibrary.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCDF99FB1D3D7A3100FD2A57 /* BoxLibrary.swift */; };
182182
CCE0429E1C9E8C8B00CA7BC4 /* ManagedObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCE0429D1C9E8C8B00CA7BC4 /* ManagedObject.swift */; };
183183
CCE2C47A1D9203DE0047E229 /* Environment.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCE2C4791D9203DE0047E229 /* Environment.swift */; };
184+
CCE4AECE204212EC008BF7E8 /* SourceManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCE4AECD204212EC008BF7E8 /* SourceManager.swift */; };
185+
CCE4AED0204217D8008BF7E8 /* SourcePosition.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCE4AECF204217D8008BF7E8 /* SourcePosition.swift */; };
184186
CCE7CA461F8EC07000FD7ECA /* iteration.sld in Copy pre-installed LispKit libraries */ = {isa = PBXBuildFile; fileRef = CCE7CA451F8D819600FD7ECA /* iteration.sld */; };
185187
CCEEF3911FAF4024006C4581 /* 158.sld in Copy pre-installed SRFI libraries */ = {isa = PBXBuildFile; fileRef = CCEEF3901FAF3F70006C4581 /* 158.sld */; };
186188
CCEEF3931FB3CB50006C4581 /* wt-tree.sld in Copy pre-installed LispKit libraries */ = {isa = PBXBuildFile; fileRef = CCEEF3921FB3CB03006C4581 /* wt-tree.sld */; };
@@ -562,6 +564,8 @@
562564
CCDF99FB1D3D7A3100FD2A57 /* BoxLibrary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = BoxLibrary.swift; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
563565
CCE0429D1C9E8C8B00CA7BC4 /* ManagedObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ManagedObject.swift; sourceTree = "<group>"; };
564566
CCE2C4791D9203DE0047E229 /* Environment.swift */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = Environment.swift; sourceTree = "<group>"; tabWidth = 2; };
567+
CCE4AECD204212EC008BF7E8 /* SourceManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceManager.swift; sourceTree = "<group>"; };
568+
CCE4AECF204217D8008BF7E8 /* SourcePosition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourcePosition.swift; sourceTree = "<group>"; };
565569
CCE7CA451F8D819600FD7ECA /* iteration.sld */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = iteration.sld; sourceTree = "<group>"; };
566570
CCEEF3901FAF3F70006C4581 /* 158.sld */ = {isa = PBXFileReference; lastKnownFileType = text; path = 158.sld; sourceTree = "<group>"; };
567571
CCEEF3921FB3CB03006C4581 /* wt-tree.sld */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "wt-tree.sld"; sourceTree = "<group>"; };
@@ -881,6 +885,7 @@
881885
CCAD52D71C48468F00DBD8EE /* Compiler */ = {
882886
isa = PBXGroup;
883887
children = (
888+
CCE4AECF204217D8008BF7E8 /* SourcePosition.swift */,
884889
CCAD52DC1C48468F00DBD8EE /* Scanner.swift */,
885890
CCAD52DB1C48468F00DBD8EE /* Parser.swift */,
886891
CC0980A61C62BDBC006B7FB1 /* Compiler.swift */,
@@ -946,6 +951,7 @@
946951
CCB585BA1E15AA4D0064BB18 /* Heap.swift */,
947952
CC5033B01CDBE4CD0045A8FA /* Console.swift */,
948953
CCCEB3FE1DF2DAA9009BF66B /* FileHandler.swift */,
954+
CCE4AECD204212EC008BF7E8 /* SourceManager.swift */,
949955
CC3C92431D84C0D800016C28 /* Library.swift */,
950956
CC5A47201C5295E600EFCF76 /* NativeLibrary.swift */,
951957
CC2D124E1DB40E7F009BDC72 /* LibraryManager.swift */,
@@ -1157,6 +1163,7 @@
11571163
CC0980AB1C67E84C006B7FB1 /* Cell.swift in Sources */,
11581164
CC3C92441D84C0D800016C28 /* Library.swift in Sources */,
11591165
CCAD52E61C48468F00DBD8EE /* SyntaxRules.swift in Sources */,
1166+
CCE4AECE204212EC008BF7E8 /* SourceManager.swift in Sources */,
11601167
CCAD52E11C48468F00DBD8EE /* Errors.swift in Sources */,
11611168
CCAD52E71C48468F00DBD8EE /* Type.swift in Sources */,
11621169
CC5A47231C529D4A00EFCF76 /* BaseLibrary.swift in Sources */,
@@ -1221,6 +1228,7 @@
12211228
CC6A3B681C52F17200E962E2 /* SchemeLibrary.swift in Sources */,
12221229
CC5C0A3F1D8EBE0A00CE2E98 /* MultiMap.swift in Sources */,
12231230
CCCEB3FF1DF2DAA9009BF66B /* FileHandler.swift in Sources */,
1231+
CCE4AED0204217D8008BF7E8 /* SourcePosition.swift in Sources */,
12241232
CC55A82B1C5175B000772B02 /* SpecialForm.swift in Sources */,
12251233
);
12261234
runOnlyForDeploymentPostprocessing = 0;

Sources/LispKit/Compiler/Errors.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,10 @@ public extension LispError {
6666
}
6767
return res
6868
}
69-
}
70-
71-
public func ==(lhs: LispError, rhs: LispError) -> Bool {
72-
return lhs.equals(rhs)
69+
70+
public static func ==(lhs: LispError, rhs: LispError) -> Bool {
71+
return lhs.equals(rhs)
72+
}
7373
}
7474

7575

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
//
2+
// SourcePosition.swift
3+
// LispKit
4+
//
5+
// Created by Matthias Zenger on 24/02/2018.
6+
// Copyright © 2018 ObjectHub. All rights reserved.
7+
//
8+
// Licensed under the Apache License, Version 2.0 (the "License");
9+
// you may not use this file except in compliance with the License.
10+
// You may obtain a copy of the License at
11+
//
12+
// http://www.apache.org/licenses/LICENSE-2.0
13+
//
14+
// Unless required by applicable law or agreed to in writing, software
15+
// distributed under the License is distributed on an "AS IS" BASIS,
16+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17+
// See the License for the specific language governing permissions and
18+
// limitations under the License.
19+
//
20+
21+
import Foundation
22+
23+
/// Struct `Position` represents a position in the scanned string in terms of a line and
24+
/// column number.
25+
public struct SourcePosition: Equatable, Hashable, CustomStringConvertible {
26+
public let sourceId: UInt16
27+
public let line: UInt16
28+
public let column: UInt16
29+
30+
public static let unknownLine: UInt16 = 0
31+
public static let unknownColumn: UInt16 = 0
32+
33+
public init(_ sourceId: UInt16, _ line: UInt16, _ column: UInt16) {
34+
self.sourceId = sourceId
35+
self.line = line
36+
self.column = line == SourcePosition.unknownLine ? SourcePosition.unknownColumn : column
37+
}
38+
39+
public init(_ sourceId: UInt16, _ line: UInt, _ column: UInt) {
40+
self.init(sourceId,
41+
line > UInt16.max ? SourcePosition.unknownLine : UInt16(line),
42+
column > UInt16.max ? SourcePosition.unknownColumn : UInt16(column))
43+
}
44+
45+
public init(_ sourceId: UInt16, _ pos: Position) {
46+
self.init(sourceId,
47+
pos.line > UInt16.max ? SourcePosition.unknownLine : UInt16(pos.line),
48+
pos.col > UInt16.max ? SourcePosition.unknownColumn : UInt16(pos.col))
49+
}
50+
51+
public var hashValue: Int {
52+
return ((self.sourceId.hashValue &* 31) &+ self.line.hashValue) &* 31 &+ self.column.hashValue
53+
}
54+
55+
public var isUnknown: Bool {
56+
return self.line == SourcePosition.unknownLine
57+
}
58+
59+
public var columnIsUnknown: Bool {
60+
return self.column == SourcePosition.unknownColumn
61+
}
62+
63+
public var sourceIsUnknown: Bool {
64+
return self.sourceId == SourceManager.unknownSourceId
65+
}
66+
67+
public func fullDescription(_ sourceManager: SourceManager) -> String {
68+
guard let sourcePath = sourceManager.sourcePath(for: self.sourceId) else {
69+
return self.description
70+
}
71+
return "\(sourcePath) \(self.description)"
72+
}
73+
74+
public var description: String {
75+
return self.isUnknown ? ""
76+
: (self.columnIsUnknown ? "\(self.line)" : "\(self.line):\(self.column)")
77+
}
78+
79+
public static func ==(lhs: SourcePosition, rhs: SourcePosition) -> Bool {
80+
return lhs.sourceId == rhs.sourceId &&
81+
lhs.line == rhs.line &&
82+
lhs.column == rhs.column
83+
}
84+
}

Sources/LispKit/Runtime/Context.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ public final class Context {
4545
/// A centralized module for handling files.
4646
public let fileHandler: FileHandler
4747

48+
/// The source manager of this context.
49+
public let sourceManager: SourceManager
50+
4851
/// The managed object pool for freeing up objects with cyclic dependencies.
4952
public let objects: ManagedObjectPool
5053

@@ -99,6 +102,7 @@ public final class Context {
99102
self.heap = Heap()
100103
self.fileHandler = FileHandler(includeInternalResources: includeInternalResources,
101104
includeDocumentPath: includeDocumentPath)
105+
self.sourceManager = SourceManager()
102106
self.objects = ManagedObjectPool()
103107
self.symbols = SymbolTable()
104108
self.inputPort = Port(input: TextInput(source: console))
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
//
2+
// SourceManager.swift
3+
// LispKit
4+
//
5+
// Created by Matthias Zenger on 24.02.18.
6+
// Copyright © 2018 ObjectHub. All rights reserved.
7+
//
8+
// Licensed under the Apache License, Version 2.0 (the "License");
9+
// you may not use this file except in compliance with the License.
10+
// You may obtain a copy of the License at
11+
//
12+
// http://www.apache.org/licenses/LICENSE-2.0
13+
//
14+
// Unless required by applicable law or agreed to in writing, software
15+
// distributed under the License is distributed on an "AS IS" BASIS,
16+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17+
// See the License for the specific language governing permissions and
18+
// limitations under the License.
19+
//
20+
21+
import Foundation
22+
23+
public final class SourceManager {
24+
private var sources: [String]
25+
private var sourceIds: [String: UInt16]
26+
27+
init() {
28+
self.sources = ["console"]
29+
self.sourceIds = [:]
30+
}
31+
32+
public static let consoleSourceId: UInt16 = 0
33+
public static let unknownSourceId: UInt16 = UInt16.max
34+
35+
public func sourceId(for path: String) -> UInt16? {
36+
return self.sourceIds[path]
37+
}
38+
39+
public func obtainSourceId(for path: String) -> UInt16 {
40+
if let id = self.sourceId(for: path) {
41+
return id
42+
} else if self.sources.count == UInt16.max {
43+
return SourceManager.unknownSourceId
44+
} else {
45+
self.sources.append(path)
46+
return UInt16(self.sources.count - 1)
47+
}
48+
}
49+
50+
public func sourcePath(for sourceId: UInt16) -> String? {
51+
guard sourceId != SourceManager.unknownSourceId else {
52+
return nil
53+
}
54+
return self.sources[Int(sourceId)]
55+
}
56+
57+
public func readSource(for sourceId: UInt16) throws -> String {
58+
guard let sourcePath = self.sourcePath(for: sourceId) else {
59+
throw EvalError.unknownFile("<path for source id = \(sourceId)>")
60+
}
61+
return try String(contentsOfFile: sourcePath, encoding: String.Encoding.utf8)
62+
}
63+
64+
public func readSource(for filepath: String) throws -> String {
65+
return try self.readSource(for: self.obtainSourceId(for: filepath))
66+
}
67+
}

0 commit comments

Comments
 (0)