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
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
|
# -*- mode: org; eval: (auto-fill-mode 1); org-indent-mode: 1; -*-
#+STARTUP: show3levels
* Common Lisp packages for Emacs
This is an experimental implementation of CL packages for Emacs.
The question of the experiment is if it is possible to add CL packages
to Emacs with reasonable effort and reasonable compatibility.
Note that this branch is only known to build and run under macOS. I
don't have access to other systems, so it might not compile or work on
other systems. Patches welcome.
Please see a book like Common Lisp the Language (CLtL2) for a
description of the CL package systen. The book is freely available
from CMU.
** Status
This builds and runs with unchanged Magit, Lsp-mode, and other
packages for me, so it seems to be pretty backwards-compatible. I
can't gurantee anything, of course. If you find a problem, please let
me know.
** User-visible functionality
There are three pre-defined packages.
The keyword package, named "keyword" or "" contains keywords.
The Emacs package, with name "emacs" contains all other symbols. All
code is currently loaded in this package, for compatibility. All
symbols in the package are currently exported.
The "emacs-user" package is intended for user-code, for example in
*scratch*, and uses the Emacs package, so that everything in Emacs can
be used.
These variables are defined:
"*package*" holds the current package like in CL. It's buffer-local,
and you can't set it to a non-package value, to prevent havoc.
"*emacs-package*", "*keyword-package*", "*emacs-user-package*" hold
the package objects. This is mainly for easier debugging and testing.
The variables may go at some point. Or not.
"*package-registry* is a hash-table of registered packages. The
variable may go at some point. Or not.
Various functions related to packages are defined. Depending on the
time when you read this, this may be in some state of incompleteness,
and it probably has bugs. Reports or fixes welcome.
** Implementation notes
*** Where is it?
The C part is in src/pkg.c. I chose that name because package.c
resulted in conflicts in the tests (with package.el).
The Lisp part is in lisp/emacs-lisp/pkg.el. I've done as much of this
in Lisp because that's much easier and faster. If packages are used
in files loaded in loadup, changes might be necessary to make this
possible. I consider this out of scope, ATM.
*** No pure space support
The branch contains a patch by Stefan Monnier that makes it no longer
use pure space. I didn't want to deal with pure space. Note that a
small fix in init_vectors is needed for making Stefan's patch work.
There is nothing preventing the use of pure space though, in
principle.
*** Shorthands
Are currently not supported.
*** Lisp_Package
There is a new Lisp data type Lisp_Package defined in lisp.h.
*** Lisp_Symbol
Struct Lisp_Symbol has lost its interned flag and its next pointer.
Both were an implementation detail of obarrays, which are gone.
All symbols now have a package. Uninterned symbols have a nil
package.
Keywords have the keyword package. Note that keyword symbol names do
not contain the colon. The function symbol-name still returns a
string with a leading colon. I found this was necessary to achieve
backwards-compatibility. At least at this point. The function
cl-symbol-name returns the real name of a keyword, without the colon.
Other symbols have the Emacs package.
*** Obarrays
Obarrays have been removed. Backwards-compatibility is achieved by
the following
- The variable 'obarray' still exists. Its value is now the Emacs
package.
- intern, intern-soft, unintern, mapatoms still accept vectors (former
obarrays). When called with a vector, they secretly create and use
packages. This is done because legacy code uses make-vector instead
of obarray-make to create obarrays.
*** Reader
The variable 'package-prefixes' determines if the reader will
interpret colons in a symbol name as part of a package name or not.
Default is nil.
*** Printer
The printer prints package prefixes if necessary, as in CL.
*** Completions
The completion functions accept packages as collections.
** Problems and how they are approached (currently)
*** Keywords
In CL, keywords are symbols in the keyword package. The leading colon
of a keyword is not part of its symbol name, but a package prefix.
The keyword package has a nickname that is an empty string.
In Emacs, keywords are just symbols whose names start with a colon,
and that is expected in a ton of places both implicity and explicitly
and in various forms.
Current approach:
- Internally, keyword names don't contain the colon, which is TRT.
- symbol-name returns a name with colon for keywords.
- cl-symbol-name returns the symbol name as-is.
- intern and intern-soft when called with a name starting with a colon
interpret that as wanting a keyword.
That's not at all pretty, but in an experiment with symbol-name
behaving like in CL showed serious problems that I couldn't solve so
far without modifying the code.
But see under Ideas and Todos.
*** Fake package qualification
Existing code contains symbols like GUI:xyz which look like GUI is a
package qualification. That's the reason for the variable
package-prefixes which means to interpret the : as part of the symbol
name.
** Ideas / Todo
*** Completions
It might be useful to complete over all symbols in all packages.
I haven't added that.
*** Existing package extensions
There are some language extensions available in CL implementations
that might be nice to have
- Hierarchical packages
- Package locks
- Local nicknames
None of these are implemented.
*** Changing symbol names
A trap that I always fall into, constantly, in Emacs, is to use CL
functions without the cl- prefix. It would be nice to have something
that makes these symbols available without the cl-.
Just ideas:
- (shadow-alias multiple-value-bind cl-multiple-value-bind) or maybe
with regexs. Or something.
- (import sym as another-sym)
*** Package-prefixes in functions
I'm wondering if it would be an idea to record the value of
package-prefixes at the time and in the buffer where functions are
compiled or eval'd.
We could then
- Bbind package-prefixes around the execution of the function to that
value.
- Return a name with leading colon from symbol-value if
package-prefixes is nil, which means the function was compiled or
eval'd in a "traditional" setting. It would return the keyword name
without the leading colon if package-prefixes is t.
- Make intern treat colons differently depending on the value of
package-prefixes. There are some places like transient.el which
intern names with a leading colon which are a pain in the neck.
- Maybe calls to read could also behave differently.
For subrs (native-compiled and C code), there is plenty of room for 1
bit. For byte-compiled functions, see make-bytecode + make-closure.
This should be doable from that perspective. One probably just has to
try it out.
*** Modeline
A mode-line indicator showing the current package and package-prefixes
would be helpful. Can be done with (:eval ...) in global-mode-string
now. Or maybe in a header-line.
*** Tests
Should be much improved.
*** Documentation
Doesn't exist :-).
*** Other
- Add (declare (ignore ...)) and (declare (ignorable ...) goddam :-).
|