-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathpackage.lisp
193 lines (146 loc) · 6.42 KB
/
package.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
(in-package :common-lisp-user)
(defpackage :editor-hints.named-readtables
(:use :common-lisp)
(:nicknames :named-readtables)
(:export
#:defreadtable
#:in-readtable
#:make-readtable
#:merge-readtables-into
#:find-readtable
#:ensure-readtable
#:rename-readtable
#:readtable-name
#:register-readtable
#:unregister-readtable
#:copy-named-readtable
#:list-all-named-readtables
;; Types
#:named-readtable-designator
;; Conditions
#:reader-macro-conflict
#:readtable-does-already-exist
#:readtable-does-not-exist
)
(:documentation
"
* What are Named-Readtables?
Named-Readtables is a library that provides a namespace for
readtables akin to the already-existing namespace of packages. In
particular:
* you can associate readtables with names, and retrieve
readtables by names;
* you can associate source files with readtable names, and be
sure that the right readtable is active when compiling/loading
the file;
* similiarly, your development environment now has a chance to
automatically determine what readtable should be active while
processing source forms on interactive commands. (E.g. think of
`C-c C-c' in Slime [yet to be done])
It follows that Named-Readtables is a facility for using readtables in
a localized way.
Additionally, it also attempts to become a facility for using
readtables in a _modular_ way. In particular:
* it provides a macro to specify the content of a readtable at a
glance;
* it makes it possible to use multiple inheritance between readtables.
* Notes on the API
The API heavily imitates the API of packages. This has the nice
property that any experienced Common Lisper will take it up without
effort.
DEFREADTABLE - DEFPACKAGE
IN-READTABLE - IN-PACKAGE
MERGE-READTABLES-INTO - USE-PACKAGE
MAKE-READTABLE - MAKE-PACKAGE
UNREGISTER-READTABLE - DELETE-PACKAGE
RENAME-READTABLE - RENAME-PACKAGE
FIND-READTABLE - FIND-PACKAGE
READTABLE-NAME - PACKAGE-NAME
LIST-ALL-NAMED-READTABLES - LIST-ALL-PACKAGES
* Important API idiosyncrasies
There are three major differences between the API of Named-Readtables,
and the API of packages.
1. Readtable names are symbols not strings.
Time has shown that the fact that packages are named by
strings causes severe headache because of the potential of
package names colliding with each other.
Hence, readtables are named by symbols lest to make the
situation worse than it already is. Consequently, readtables
named CL-ORACLE:SQL-SYNTAX and CL-MYSQL:SQL-SYNTAX can
happily coexist next to each other. Or, taken to an extreme,
SCHEME:SYNTAX and ELISP:SYNTAX.
If, for example to duly signify the importance of your cool
readtable hack, you really think it deserves a global name,
you can always resort to keywords.
2. The inheritance is resolved statically, not dynamically.
A package that uses another package will have access to all
the other package's exported symbols, even to those that will
be added after its definition. I.e. the inheritance is
resolved at run-time, that is dynamically.
Unfortunately, we cannot do the same for readtables in a
portable manner.
Therefore, we do not talk about \"using\" another readtable
but about \"merging\" the other readtable's definition into
the readtable we are going to define. I.e. the inheritance is
resolved once at definition time, that is statically.
(Such merging can more or less be implemented portably albeit
at a certain cost. Most of the time, this cost manifests
itself at the time a readtable is defined, i.e. once at
compile-time, so it may not bother you. Nonetheless, we
provide extra support for Sbcl, ClozureCL, and AllegroCL at
the moment. Patches for your implementation of choice are
welcome, of course.)
3. DEFREADTABLE does not have compile-time effects.
If you define a package via DEFPACKAGE, you can make that
package the currently active package for the subsequent
compilation of the same file via IN-PACKAGE. The same is,
however, not true for DEFREADTABLE and IN-READTABLE for the
following reason:
It's unlikely that the need for special reader-macros arises
for a problem which can be solved in just one file. Most
often, you're going to define the reader macro functions, and
set up the corresponding readtable in an extra file.
If DEFREADTABLE had compile-time effects, you'd have to wrap
each definition of a reader-macro function in an EVAL-WHEN to
make its definition available at compile-time. Because that's
simply not the common case, DEFREADTABLE does not have a
compile-time effect.
If you want to use a readtable within the same file as its
definition, wrap the DEFREADTABLE and the reader-macro
function definitions in an explicit EVAL-WHEN.
* Preregistered Readtables
- NIL, :STANDARD, and :COMMON-LISP designate the /standard readtable/.
- :MODERN designates a _case-preserving_ /standard-readtable/.
- :CURRENT designates the /current readtable/.
* Examples
> (defreadtable elisp:syntax
> (:merge :standard)
> (:macro-char #\\? #'elisp::read-character-literal t)
> (:macro-char #\\[ #'elisp::read-vector-literal t)
> ...
> (:case :preserve))
>
> (defreadtable scheme:syntax
> (:merge :standard)
> (:macro-char #\\[ #'(lambda (stream char)
> (read-delimited-list #\\] stream)))
> (:macro-char #\\# :dispatch)
> (:dispatch-macro-char #\\# #\\t #'scheme::read-#t)
> (:dispatch-macro-char #\\# #\\f #'scheme::read-#f)
> ...
> (:case :preserve))
>
> (in-readtable elisp:syntax)
>
> ...
>
> (in-readtable scheme:syntax)
>
> ...
* Acknowledgements
Thanks to Robert Goldman for making me want to write this library.
Thanks to Stephen Compall, Ariel Badichi, David Lichteblau, Bart
Botta, David Crawford, and Pascal Costanza for being early adopters,
providing comments and bugfixes.
"))
(pushnew :named-readtables *features*)