Skip to content

Commit ca479e0

Browse files
committed
Store names in special forms to facilitate debugging.
1 parent d04fc5d commit ca479e0

File tree

10 files changed

+78
-49
lines changed

10 files changed

+78
-49
lines changed

Sources/LispKit/Compiler/EvalError.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ public enum EvalError: Int, Hashable {
8585
public var message: String {
8686
switch self {
8787
case .illegalKeywordUsage:
88-
return "syntactic keywords may not be used as expressions: $0"
88+
return "illegal usage of syntactic keyword as expression: $0"
8989
case .illegalFormalParameter:
9090
return "illegal formal parameter: $0"
9191
case .illegalFormalRestParameter:

Sources/LispKit/Data/Environment.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,9 @@ public final class Environment: Reference, CustomStringConvertible {
110110
self.bindings = [:]
111111
super.init()
112112
self.box = WeakBox(self)
113-
self.define(context.symbols.`import`, as: .special(SpecialForm(Environment.compileImport)))
113+
self.define(context.symbols.`import`,
114+
as: .special(SpecialForm(context.symbols.`import`.description,
115+
Environment.compileImport)))
114116
}
115117

116118
/// Initializes an empty environment for executing a program read from `filename`.

Sources/LispKit/Data/Expr.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -818,7 +818,7 @@ extension Expr: CustomStringConvertible {
818818
return "#<procedure \(proc.name)>"
819819
}
820820
case .special(let special):
821-
return "#<special \(special.identityString)>"
821+
return "#<special \(special.name)>"
822822
case .env(let environment):
823823
var type: String = ""
824824
switch environment.kind {

Sources/LispKit/Data/Procedure.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ public final class Procedure: Reference, CustomStringConvertible {
261261
}
262262
}
263263

264-
/// Returns the original name of this procedure if it exists and is known. This method either
264+
/// Returns the original name of this procedure if it exists and is known.
265265
public var originalName: String? {
266266
switch self.kind {
267267
case .primitive(let str, _, _):

Sources/LispKit/Data/SpecialForm.swift

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,20 @@ public final class SpecialForm: Reference, CustomStringConvertible {
3535
/// Special form kind
3636
internal let kind: Kind
3737

38+
/// Original name of the special form, if available; this is the name of the special
39+
/// form at definition time.
40+
public let originalName: String?
41+
3842
/// Initializer for primitive special forms
39-
public init(_ compiler: @escaping FormCompiler) {
43+
public init(_ name: String?, _ compiler: @escaping FormCompiler) {
4044
self.kind = .primitive(compiler)
45+
self.originalName = name
4146
}
4247

4348
/// Initializer for special forms based on macro transformers
44-
public init(_ transformer: Procedure) {
49+
public init(_ name: String?, _ transformer: Procedure) {
4550
self.kind = .macro(transformer)
51+
self.originalName = name
4652
}
4753

4854
public func mark(_ tag: UInt8) {
@@ -54,8 +60,23 @@ public final class SpecialForm: Reference, CustomStringConvertible {
5460
}
5561
}
5662

63+
/// Returns the name of this special form. This method either returns the name of a primitive
64+
/// special form or a macro transformer. If the name isn't available, the identity is returned
65+
/// as a hex string.
66+
public var name: String {
67+
guard let originalName = self.originalName else {
68+
return self.identityString
69+
}
70+
switch self.kind {
71+
case .primitive(_):
72+
return originalName
73+
case .macro(_):
74+
return "\(originalName)@\(self.identityString)"
75+
}
76+
}
77+
5778
/// A textual description
5879
public var description: String {
59-
return "special:\(self.identityString)"
80+
return "special:" + self.name
6081
}
6182
}

Sources/LispKit/Primitives/BaseLibrary.swift

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -41,32 +41,32 @@ public final class BaseLibrary: NativeLibrary {
4141
self.define(Procedure("equal?", isEqual, compileEqual))
4242
self.define(Procedure("eqv?", isEqv, compileEqv))
4343
self.define(Procedure("eq?", isEq, compileEq))
44-
self.define("quote", as: SpecialForm(compileQuote))
45-
self.define("quasiquote", as: SpecialForm(compileQuasiquote))
46-
self.define("lambda", as: SpecialForm(compileLambda))
47-
self.define("case-lambda", as: SpecialForm(compileCaseLambda))
44+
self.define(SpecialForm("quote", compileQuote))
45+
self.define(SpecialForm("quasiquote", compileQuasiquote))
46+
self.define(SpecialForm("lambda", compileLambda))
47+
self.define(SpecialForm("case-lambda", compileCaseLambda))
4848

4949
// Definition primitives
50-
self.define("define", as: SpecialForm(compileDefine))
51-
self.define("define-values", as: SpecialForm(compileDefineValues))
52-
self.define("define-syntax", as: SpecialForm(compileDefineSyntax))
53-
self.define("define-library", as: SpecialForm(compileDefineLibrary))
54-
self.define("syntax-rules", as: SpecialForm(compileSyntaxRules))
55-
self.define("set!", as: SpecialForm(compileSet))
50+
self.define(SpecialForm("define", compileDefine))
51+
self.define(SpecialForm("define-values", compileDefineValues))
52+
self.define(SpecialForm("define-syntax", compileDefineSyntax))
53+
self.define(SpecialForm("define-library", compileDefineLibrary))
54+
self.define(SpecialForm("syntax-rules", compileSyntaxRules))
55+
self.define(SpecialForm("set!", compileSet))
5656

5757
// Delayed execution
5858
self.define(Procedure("promise?", isPromise))
5959
self.define(Procedure("make-promise", makePromise))
6060
self.define(Procedure("eager", makePromise))
61-
self.define("delay", as: SpecialForm(compileDelay))
62-
self.define("delay-force", as: SpecialForm(compileDelayForce))
63-
self.define("lazy", as: SpecialForm(compileDelayForce))
61+
self.define(SpecialForm("delay", compileDelay))
62+
self.define(SpecialForm("delay-force", compileDelayForce))
63+
self.define(SpecialForm("lazy", compileDelayForce))
6464
self.define(Procedure("stream?", isStream))
6565
self.define(Procedure("make-stream", makeStream))
6666
self.define(Procedure("stream-eager", makeStream))
67-
self.define("stream-delay", as: SpecialForm(compileStreamDelay))
68-
self.define("stream-delay-force", as: SpecialForm(compileStreamDelayForce))
69-
self.define("stream-lazy", as: SpecialForm(compileStreamDelayForce))
67+
self.define(SpecialForm("stream-delay", compileStreamDelay))
68+
self.define(SpecialForm("stream-delay-force", compileStreamDelayForce))
69+
self.define(SpecialForm("stream-lazy", compileStreamDelayForce))
7070
self.define(Procedure("force", compileForce, in: self.context))
7171

7272
// Symbol primitives
@@ -79,14 +79,14 @@ public final class BaseLibrary: NativeLibrary {
7979
// Boolean primitives
8080
self.define(Procedure("boolean?", isBoolean))
8181
self.define(Procedure("boolean=?", isBooleanEq))
82-
self.define("and", as: SpecialForm(compileAnd))
83-
self.define("or", as: SpecialForm(compileOr))
82+
self.define(SpecialForm("and", compileAnd))
83+
self.define(SpecialForm("or", compileOr))
8484
self.define(Procedure("not", not, compileNot))
8585

8686
// Conditional & inclusion compilation
87-
self.define("cond-expand", as: SpecialForm(compileCondExpand))
88-
self.define("include", as: SpecialForm(include))
89-
self.define("include-ci", as: SpecialForm(includeCi))
87+
self.define(SpecialForm("cond-expand", compileCondExpand))
88+
self.define(SpecialForm("include", include))
89+
self.define(SpecialForm("include-ci", includeCi))
9090

9191
// Multiple values
9292
self.define(Procedure("values", values, compileValues))
@@ -102,7 +102,7 @@ public final class BaseLibrary: NativeLibrary {
102102
self.define(Procedure("interaction-environment", interactionEnvironment))
103103

104104
// Syntax errors
105-
self.define("syntax-error", as: SpecialForm(compileSyntaxError))
105+
self.define(SpecialForm("syntax-error", compileSyntaxError))
106106

107107
// Helpers
108108
self.define(Procedure("void", BaseLibrary.voidConst))

Sources/LispKit/Primitives/ControlFlowLibrary.swift

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -28,23 +28,23 @@ public final class ControlFlowLibrary: NativeLibrary {
2828

2929
/// Declarations of the library.
3030
public override func declarations() {
31-
self.define("begin", as: SpecialForm(self.compileBegin))
32-
self.define("let", as: SpecialForm(self.compileLet))
33-
self.define("let*", as: SpecialForm(self.compileLetStar))
34-
self.define("letrec", as: SpecialForm(self.compileLetRec))
35-
self.define("letrec*", as: SpecialForm(self.compileLetRecStar))
36-
self.define("let-values", as: SpecialForm(self.compileLetValues))
37-
self.define("let*-values", as: SpecialForm(self.compileLetStarValues))
38-
self.define("let-optionals", as: SpecialForm(self.compileLetOptionals))
39-
self.define("let*-optionals", as: SpecialForm(self.compileLetStarOptionals))
40-
self.define("let-syntax", as: SpecialForm(self.compileLetSyntax))
41-
self.define("letrec-syntax", as: SpecialForm(self.compileLetRecSyntax))
42-
self.define("do", as: SpecialForm(self.compileDo))
43-
self.define("if", as: SpecialForm(self.compileIf))
44-
self.define("when", as: SpecialForm(self.compileWhen))
45-
self.define("unless", as: SpecialForm(self.compileUnless))
46-
self.define("cond", as: SpecialForm(self.compileCond))
47-
self.define("case", as: SpecialForm(self.compileCase))
31+
self.define(SpecialForm("begin", self.compileBegin))
32+
self.define(SpecialForm("let", self.compileLet))
33+
self.define(SpecialForm("let*", self.compileLetStar))
34+
self.define(SpecialForm("letrec", self.compileLetRec))
35+
self.define(SpecialForm("letrec*", self.compileLetRecStar))
36+
self.define(SpecialForm("let-values", self.compileLetValues))
37+
self.define(SpecialForm("let*-values", self.compileLetStarValues))
38+
self.define(SpecialForm("let-optionals", self.compileLetOptionals))
39+
self.define(SpecialForm("let*-optionals", self.compileLetStarOptionals))
40+
self.define(SpecialForm("let-syntax", self.compileLetSyntax))
41+
self.define(SpecialForm("letrec-syntax", self.compileLetRecSyntax))
42+
self.define(SpecialForm("do", self.compileDo))
43+
self.define(SpecialForm("if", self.compileIf))
44+
self.define(SpecialForm("when", self.compileWhen))
45+
self.define(SpecialForm("unless", self.compileUnless))
46+
self.define(SpecialForm("cond", self.compileCond))
47+
self.define(SpecialForm("case", self.compileCase))
4848
}
4949

5050
private func splitBindings(_ bindingList: Expr) throws -> (Expr, Expr) {

Sources/LispKit/Primitives/SystemLibrary.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ public final class SystemLibrary: NativeLibrary {
8686
self.define(Procedure("loaded-libraries", self.loadedLibraries))
8787
self.define(Procedure("loaded-sources", self.loadedSources))
8888
self.define(Procedure("environment-info", self.environmentInfo))
89-
self.define("time", as: SpecialForm(self.compileTime))
89+
self.define(SpecialForm("time", self.compileTime))
9090
self.define(Procedure("seconds-from-gmt", self.secondsFromGmt))
9191
self.define(Procedure("current-second", self.currentSecond))
9292
self.define(Procedure("current-jiffy", self.currentJiffy))

Sources/LispKit/Runtime/NativeLibrary.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,12 @@ open class NativeLibrary: Library {
178178
return self.define(proc.name, as: .procedure(proc), export: export)
179179
}
180180

181+
/// Declares a new special form using the internal name of `spec`.
182+
/// The optional parameter `export` determines whether the definition is exported or internal.
183+
@discardableResult public func define(_ spec: SpecialForm, export: Bool = true) -> Int {
184+
return self.define(spec.name, as: .special(spec), export: export)
185+
}
186+
181187
/// Declares a new definition for the given procedure `proc` and name `name`. The optional
182188
/// parameter `export` determines whether the definition is exported or internal.
183189
@discardableResult public func define(_ name: String,

Sources/LispKit/Runtime/VirtualMachine.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,7 +1018,7 @@ public final class VirtualMachine: TrackedObject {
10181018
case .uninit(let sym):
10191019
throw RuntimeError.eval(.variableNotYetInitialized, .symbol(sym))
10201020
case .special(_):
1021-
throw RuntimeError.eval(.illegalKeywordUsage, .undef) // TODO: can this really happen?
1021+
throw RuntimeError.eval(.illegalKeywordUsage, value)
10221022
default:
10231023
self.push(value)
10241024
}
@@ -1194,7 +1194,7 @@ public final class VirtualMachine: TrackedObject {
11941194
guard case .procedure(let proc) = transformer else {
11951195
throw RuntimeError.eval(.malformedTransformer, transformer)
11961196
}
1197-
self.push(.special(SpecialForm(proc)))
1197+
self.push(.special(SpecialForm(nil, proc)))
11981198
case .compile:
11991199
let environment = try self.pop().asEnvironment()
12001200
let code = try Compiler.compile(expr: .makeList(self.pop()),

0 commit comments

Comments
 (0)