Skip to content

Commit 6c0566d

Browse files
committed
Use URLs instead of file paths for managing sources.
1 parent 7d6dac0 commit 6c0566d

File tree

5 files changed

+73
-24
lines changed

5 files changed

+73
-24
lines changed

Sources/LispKit/Compiler/Scanner.swift

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ public final class Scanner {
3030
/// Input of source code
3131
private let input: TextInput
3232

33+
/// Source id of source code
34+
internal let sourceId: UInt16
35+
3336
/// Buffer for characters read during one invocation of `next`
3437
private var buffer: ScanBuffer
3538

@@ -49,13 +52,23 @@ public final class Scanner {
4952
internal var token: Token
5053

5154
/// Creates a new scanner for the given string.
52-
public convenience init(string: String, foldCase: Bool = false, prescan: Bool = true) {
53-
self.init(input: TextInput(string: string), foldCase: foldCase, prescan: prescan)
55+
public convenience init(string: String,
56+
sourceId: UInt16 = SourceManager.unknownSourceId,
57+
foldCase: Bool = false,
58+
prescan: Bool = true) {
59+
self.init(input: TextInput(string: string),
60+
sourceId: sourceId,
61+
foldCase: foldCase,
62+
prescan: prescan)
5463
}
5564

5665
/// Creates a new scanner for the given string.
57-
public init(input: TextInput, foldCase: Bool = false, prescan: Bool = true) {
66+
public init(input: TextInput,
67+
sourceId: UInt16 = SourceManager.unknownSourceId,
68+
foldCase: Bool = false,
69+
prescan: Bool = true) {
5870
self.input = input
71+
self.sourceId = sourceId
5972
self.buffer = ScanBuffer()
6073
self.foldCase = foldCase
6174
self.pos = Position(1, 1)
@@ -76,6 +89,11 @@ public final class Scanner {
7689
}
7790
}
7891

92+
/// Returns the source position of the current token.
93+
public var sourcePosition: SourcePosition {
94+
return SourcePosition(self.sourceId, self.lpos.line, self.lpos.col)
95+
}
96+
7997
/// Returns true if the current token has one of the given token kinds.
8098
public func hasToken(_ kind: TokenKind...) -> Bool {
8199
for k in kind {

Sources/LispKit/Compiler/SourcePosition.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,10 @@ public struct SourcePosition: Equatable, Hashable, CustomStringConvertible {
6565
}
6666

6767
public func fullDescription(_ sourceManager: SourceManager) -> String {
68-
guard let sourcePath = sourceManager.sourcePath(for: self.sourceId) else {
68+
guard let sourceUrl = sourceManager.sourceUrl(for: self.sourceId) else {
6969
return self.description
7070
}
71-
return "\(sourcePath) \(self.description)"
71+
return "\(sourceUrl.lastPathComponent) \(self.description)"
7272
}
7373

7474
public var description: String {

Sources/LispKit/Primitives/SystemLibrary.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ public final class SystemLibrary: NativeLibrary {
8484
self.define(Procedure("trace-calls", self.traceCalls))
8585
self.define(Procedure("available-symbols", self.availableSymbols))
8686
self.define(Procedure("loaded-libraries", self.loadedLibraries))
87+
self.define(Procedure("loaded-sources", self.loadedSources))
8788
self.define(Procedure("environment-info", self.environmentInfo))
8889
self.define("time", as: SpecialForm(self.compileTime))
8990
self.define(Procedure("seconds-from-gmt", self.secondsFromGmt))
@@ -446,6 +447,14 @@ public final class SystemLibrary: NativeLibrary {
446447
return res
447448
}
448449

450+
private func loadedSources() -> Expr {
451+
var res = Expr.null
452+
for url in self.context.sourceManager.sourceUrls {
453+
res = .pair(.makeString(url.path), res)
454+
}
455+
return res
456+
}
457+
449458
private func environmentInfo() -> Expr {
450459
context.console.print("OBJECT SIZES\n")
451460
context.console.print(" atom size : \(MemoryLayout<Expr>.size) bytes\n")

Sources/LispKit/Runtime/SourceManager.swift

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,47 +21,70 @@
2121
import Foundation
2222

2323
public final class SourceManager {
24-
private var sources: [String]
25-
private var sourceIds: [String: UInt16]
24+
internal var sourceUrls: [URL]
25+
private var sourceIds: [URL: UInt16]
2626

2727
init() {
28-
self.sources = ["console"]
28+
self.sourceUrls = [URL(string: "console")!]
2929
self.sourceIds = [:]
3030
}
3131

3232
public static let consoleSourceId: UInt16 = 0
3333
public static let unknownSourceId: UInt16 = UInt16.max
3434

35+
public func sourceId(for url: URL) -> UInt16? {
36+
return self.sourceIds[self.absoluteUrl(url)]
37+
}
38+
3539
public func sourceId(for path: String) -> UInt16? {
36-
return self.sourceIds[path]
40+
return self.sourceIds[self.absoluteUrl(path)]
3741
}
3842

3943
public func obtainSourceId(for path: String) -> UInt16 {
40-
if let id = self.sourceId(for: path) {
44+
return self.obtainSourceId(for: URL(fileURLWithPath: path))
45+
}
46+
47+
public func obtainSourceId(for url: URL) -> UInt16 {
48+
let canonicalUrl = self.absoluteUrl(url)
49+
if let id = self.sourceIds[canonicalUrl] {
4150
return id
42-
} else if self.sources.count == UInt16.max {
51+
} else if self.sourceUrls.count == UInt16.max {
4352
return SourceManager.unknownSourceId
4453
} else {
45-
self.sources.append(path)
46-
return UInt16(self.sources.count - 1)
54+
let newSourceId = UInt16(self.sourceUrls.count)
55+
self.sourceUrls.append(canonicalUrl)
56+
self.sourceIds[canonicalUrl] = newSourceId
57+
return newSourceId
4758
}
4859
}
4960

50-
public func sourcePath(for sourceId: UInt16) -> String? {
61+
public func sourceUrl(for sourceId: UInt16) -> URL? {
5162
guard sourceId != SourceManager.unknownSourceId else {
5263
return nil
5364
}
54-
return self.sources[Int(sourceId)]
65+
return self.sourceUrls[Int(sourceId)]
5566
}
5667

5768
public func readSource(for sourceId: UInt16) throws -> String {
58-
guard let sourcePath = self.sourcePath(for: sourceId) else {
69+
guard let sourceUrl = self.sourceUrl(for: sourceId) else {
5970
throw EvalError.unknownFile("<path for source id = \(sourceId)>")
6071
}
61-
return try String(contentsOfFile: sourcePath, encoding: String.Encoding.utf8)
72+
return try String(contentsOf: sourceUrl)
73+
}
74+
75+
public func readSource(for url: URL) throws -> String {
76+
return try self.readSource(for: self.obtainSourceId(for: url))
77+
}
78+
79+
public func readSource(for path: String) throws -> String {
80+
return try self.readSource(for: self.obtainSourceId(for: path))
81+
}
82+
83+
private func absoluteUrl(_ url: URL) -> URL {
84+
return url.standardizedFileURL.absoluteURL
6285
}
6386

64-
public func readSource(for filepath: String) throws -> String {
65-
return try self.readSource(for: self.obtainSourceId(for: filepath))
87+
private func absoluteUrl(_ path: String) -> URL {
88+
return self.absoluteUrl(URL(fileURLWithPath: path))
6689
}
6790
}

Sources/LispKit/Runtime/VirtualMachine.swift

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ public final class VirtualMachine: TrackedObject {
292292
in env: Env,
293293
optimize: Bool = true,
294294
foldCase: Bool = false) throws -> Expr {
295-
return try self.eval(str: try String(contentsOfFile: path, encoding: String.Encoding.utf8),
295+
return try self.eval(str: self.context.sourceManager.readSource(for: path),
296296
in: env,
297297
optimize: optimize,
298298
inDirectory: self.context.fileHandler.directory(path),
@@ -349,7 +349,7 @@ public final class VirtualMachine: TrackedObject {
349349

350350
/// Parses the given file and returns a list of parsed expressions.
351351
public func parse(file path: String, foldCase: Bool = false) throws -> Expr {
352-
return try self.parse(str: try String(contentsOfFile: path, encoding: String.Encoding.utf8),
352+
return try self.parse(str: self.context.sourceManager.readSource(for: path),
353353
foldCase: foldCase)
354354
}
355355

@@ -360,9 +360,8 @@ public final class VirtualMachine: TrackedObject {
360360

361361
/// Parses the given string and returns an array of parsed expressions.
362362
public func parseExprs(file path: String, foldCase: Bool = false) throws -> Exprs {
363-
return try self.parseExprs(
364-
str: try String(contentsOfFile: path, encoding: String.Encoding.utf8),
365-
foldCase: foldCase)
363+
return try self.parseExprs(str: self.context.sourceManager.readSource(for: path),
364+
foldCase: foldCase)
366365
}
367366

368367
/// Parses the given string and returns an array of parsed expressions.

0 commit comments

Comments
 (0)