* Add non-libguile Elisp support files to CVS trunk. (NB work in progress.)
[bpt/guile.git] / lang / elisp / README
1 -*- outline -*-
2
3 This directory holds the Scheme side of a translator for Emacs Lisp.
4
5 * Usage
6
7 To load up the base Elisp environment:
8
9 (use-modules (lang elisp base))
10
11 Then you can switch into this module
12
13 (define-module (lang elisp base))
14
15 and start typing away in Elisp, or evaluate an individual Elisp
16 expression from Scheme:
17
18 (eval EXP (resolve-module '(lang elisp base)))
19
20 A more convenient, higher-level interface is provided by (lang elisp
21 interface):
22
23 (use-modules (lang elisp interface))
24
25 With this interface, you can evaluate an Elisp expression
26
27 (eval-elisp EXP)
28
29 load an Elisp file with no effect on the Scheme world
30
31 (load-elisp-file "/home/neil/Guile/cvs/guile-core/lang/elisp/example.el")
32
33 load an Elisp file, automatically importing top level definitions into
34 Scheme
35
36 (use-elisp-file "/home/neil/Guile/cvs/guile-core/lang/elisp/example.el")
37
38 export Scheme objects to Elisp
39
40 (export-to-elisp + - * my-func 'my-var)
41
42 and try to bootstrap a complete Emacs environment:
43
44 (load-emacs)
45
46 * Status
47
48 Please note that this is work in progress; the translator is
49 incomplete and not yet widely tested.
50
51 ** Trying to load a complete Emacs environment.
52
53 To try this, type `(use-modules (lang elisp interface))' and then
54 `(load-emacs)'. The following output shows how far I get when I try
55 this.
56
57 guile> (use-modules (lang elisp interface))
58 guile> (load-emacs)
59 Calling loadup.el to clothe the bare Emacs...
60 Loading /usr/share/emacs/20.7/lisp/loadup.el...
61 Using load-path ("/usr/share/emacs/20.7/lisp/" "/usr/share/emacs/20.7/lisp/emacs-lisp/")
62 Loading /usr/share/emacs/20.7/lisp/byte-run.el...
63 Loading /usr/share/emacs/20.7/lisp/byte-run.el...done
64 Loading /usr/share/emacs/20.7/lisp/subr.el...
65 Loading /usr/share/emacs/20.7/lisp/subr.el...done
66 Loading /usr/share/emacs/20.7/lisp/version.el...
67 Loading /usr/share/emacs/20.7/lisp/version.el...done
68 Loading /usr/share/emacs/20.7/lisp/map-ynp.el...
69 Loading /usr/share/emacs/20.7/lisp/map-ynp.el...done
70 Loading /usr/share/emacs/20.7/lisp/widget.el...
71 Loading /usr/share/emacs/20.7/lisp/emacs-lisp/cl.el...
72 Loading /usr/share/emacs/20.7/lisp/emacs-lisp/cl.el...done
73 Loading /usr/share/emacs/20.7/lisp/widget.el...done
74 Loading /usr/share/emacs/20.7/lisp/custom.el...
75 Loading /usr/share/emacs/20.7/lisp/custom.el...done
76 Loading /usr/share/emacs/20.7/lisp/cus-start.el...
77 Note, built-in variable `abbrev-all-caps' not bound
78 ... [many other variable not bound messages] ...
79 Loading /usr/share/emacs/20.7/lisp/cus-start.el...done
80 Loading /usr/share/emacs/20.7/lisp/international/mule.el...
81 <unnamed port>: In procedure make-char-table in expression (@fop make-char-table (# #)):
82 <unnamed port>: Symbol's function definition is void
83 ABORT: (misc-error)
84
85 Type "(backtrace)" to get more information or "(debug)" to enter the debugger.
86 guile>
87
88 That's 3279 lines ("wc -l") of Elisp code already, which isn't bad!
89
90 I think that progress beyond this point basically means implementing
91 multilingual and multibyte strings properly for Guile. Which is a
92 _lot_ of work and requires IMO a very clear plan for Guile's role with
93 respect to Emacs.
94
95 * Design
96
97 When thinking about how to implement an Elisp translator for Guile, it
98 is important to realize that the great power of Emacs does not arise
99 from Elisp (seen as a language in syntactic terms) alone, but from the
100 combination of this language with the collection of primitives
101 provided by the Emacs C source code. Therefore, to be of practical
102 use, an Elisp translator needs to be more than just a transformer that
103 translates sexps to Scheme expressions.
104
105 The finished translator should consist of several parts...
106
107 ** Syntax transformation
108
109 Although syntax transformation isn't all we need, we do still need it!
110
111 This part is implemented by the (lang elisp transform) module; it is
112 close to complete and seems to work pretty reliably.
113
114 Note that transformed expressions use the `@fop' and `@bind' macros
115 provided by...
116
117 ** C support for transformed expressions
118
119 For performance and historical reasons (and perhaps necessity - I
120 haven't thought about it enough yet), some of the transformation
121 support is written in C.
122
123 *** @fop
124
125 The `@fop' macro is used to dispatch Elisp applications. Its first
126 argument is a symbol, and this symbol's function slot is examined to
127 find a procedure or macro to apply to the remaining arguments. `@fop'
128 also handles aliasing (`defalias'): in this case the function slot
129 contains another symbol.
130
131 Once `@fop' has found the appropriate procedure or macro to apply, it
132 returns an application expression in which that procedure or macro
133 replaces the `@fop' and the original symbol. Hence no Elisp-specific
134 evaluator support is required to perform the application.
135
136 *** @bind
137
138 Currently, Elisp variables are the same as Scheme variables, so
139 variable references are effectively untransformed.
140
141 The `@bind' macro does Elisp-style dynamic variable binding.
142 Basically, it locates the named top level variables, `set!'s them to
143 new values, evaluates its body, and then uses `set!' again to restore
144 the original values.
145
146 Because of the body evaluation, `@bind' requires evaluator support.
147 In fact, the `@bind' macro code does little more than replace itself
148 with the memoized SCM_IM_BIND. Most of the work is done by the
149 evaluator when it hits SCM_IM_BIND.
150
151 One theoretical problem with `@bind' is that any local Scheme variable
152 in the same scope and with the same name as an Elisp variable will
153 shadow the Elisp variable. But in practice it's difficult to set up
154 such a situation; an exception is the translator code itself, so there
155 we mangle the relevant Scheme variable names a bit to avoid the
156 problem.
157
158 Other possible problems with this approach are that it might not be
159 possible to implement buffer local variables properly, and that
160 `@bind' might become too inefficient when we implement full support
161 for undefining Scheme variables. So we might in future have to
162 transform Elisp variable references after all.
163
164 *** Truth value stuff
165
166 Lots of stuff to do with providing the special self-evaluating `nil'
167 and `t' symbols, and macros that convert between Scheme and Elisp
168 truth values, and so on.
169
170 I'm hoping that most of this will go away, but I need to show that
171 it's feasible first.
172
173 ** Emacs editing primitives
174
175 Buffers, keymaps, text properties, windows, frames etc. etc.
176
177 Basically, everything that is implemented as a primitive in the Emacs
178 C code needs to be implemented either in Scheme or in C for Guile.
179
180 The Scheme files in the primitives subdirectory implement some of
181 these primitives in Scheme. Not because that is the right decision,
182 but because this is a proof of concept and it's quicker to write badly
183 performing code in Scheme.
184
185 Ultimately, most of these primitive definitions should really come
186 from the Emacs C code itself, translated or preprocessed in a way that
187 makes it compile with Guile. I think this is pretty close to the work
188 that Ken Raeburn has been doing on the Emacs codebase.
189
190 ** Reading and printing support
191
192 Elisp is close enough to Scheme that it's convenient to coopt the
193 existing Guile reader rather than to write a new one from scratch, but
194 there are a few syntactic differences that will require adding Elisp
195 support to the reader.
196
197 - Character syntax is `?a' rather than `#\a'. (Not done. More
198 precisely, `?a' in Elisp isn't character syntax but an alternative
199 integer syntax. Note that we could support most of the `?a' syntax
200 simply by doing
201
202 (define ?a (char->integer #\a)
203 (define ?b (char->integer #\b)
204
205 and so on.)
206
207 - `nil' and `t' should be read (I think) as #f and #t. (Done.)
208
209 - Vector syntax is `[1 2 3]' rather than `#(1 2 3)'. (Not done.)
210
211 Correspondingly, when printing, #f and '() should be written as
212 `nil'. (Not done.)
213
214 ** The Elisp evaluation module (lang elisp base)
215
216 Fundamentally, Guile's module system can't be used to package Elisp
217 code in the same way it is used for Scheme code, because Elisp
218 function definitions are stored as symbol properties (in the symbol's
219 "function slot") and so are global. On the other hand, it is useful
220 (necessary?) to associate some particular module with Elisp evaluation
221 because
222
223 - Elisp variables are currently implemented as Scheme variables and so
224 need to live in some module
225
226 - a syntax transformer is a property of a module.
227
228 Therefore we have the (lang elisp base) module, which acts as the
229 repository for all Elisp variables and the site of all Elisp
230 evaluation.
231
232 The initial environment provided by this module is intended to be a
233 non-Emacs-dependent subset of Elisp. To get the idea, imagine someone
234 who wants to write an extension function for, say Gnucash, and simply
235 prefers to write in Elisp rather than in Scheme. He/she therefore
236 doesn't buffers, keymaps and so on, just the basic language syntax and
237 core data functions like +, *, concat, length etc., plus specific
238 functions made available by Gnucash.
239
240 (lang elisp base) achieves this by
241
242 - importing Scheme definitions for some Emacs primitives from the
243 files in the primitives subdirectory
244
245 - then switching into Elisp syntax.
246
247 After this point, `(eval XXX (resolve-module '(lang elisp base)))'
248 will evaluate XXX as an Elisp expression in the (lang elisp base)
249 module. (`eval-elisp' in (lang elisp interface) is a more convenient
250 wrapper for this.)
251
252 ** Full Emacs environment
253
254 The difference between the initial (lang elisp base) environment and a
255 fully loaded Emacs equivalent is
256
257 - more primitives: buffers, char-tables and many others
258
259 - the bootstrap Elisp code that an undumped Emacs loads during
260 installation by calling `(load "loadup.el")'.
261
262 We don't have all the missing primitives, but we can already get
263 through some of loadup.el. The Elisp function `load-emacs' (defined
264 in (lang elisp base) initiates the loading of loadup.el; (lang elisp
265 interface) exports `load-emacs' to Scheme.
266
267 `load-emacs' loads so much Elisp code that it's an excellent way to
268 test the translator. In current practice, it runs for a while and
269 then fails when it gets to an undefined primitive or a bug in the
270 translator. Eventually, it should go all the way. (And then we can
271 worry about adding unexec support to Guile!) For the output that
272 currently results from calling `(load-emacs)', see above in the Status
273 section.
274
275 * nil, #f and '()
276
277 For Jim Blandy's notes on this, see the reference at the bottom of
278 this file. Currently I'm investigating a different approach, which is
279 better IMO than Jim's proposal because it avoids requiring multiple
280 false values in the Scheme world.
281
282 According to my approach...
283
284 - `nil' and `t' are read (when in Elisp mode) as #f and #t.
285
286 - `(if x ...)', `(while x ...)' etc. are translated to something
287 like `(if (and x (not (null? x))) ...)'.
288
289 - Functions which interpret an argument as a list --
290 `cons', `setcdr', `memq', etc. -- either convert #f to '(), or
291 handle the #f case specially.
292
293 - `eq' treats #f and '() as the same.
294
295 - Optionally, functions which produce '() values -- i.e. the reader
296 and `cdr' -- could convert those immediately to #f. This shouldn't
297 affect the validity of any Elisp code, but it alters the balance of
298 #f and '() values swimming around in that code and so affects what
299 happens if two such values are returned to the Scheme world and then
300 compared. However, since you can never completely solve this
301 problem (unless you are prepared to convert arbitrarily deep
302 structures on entry to the Elisp world, which would kill performance),
303 I'm inclined not to try to solve it at all.
304
305 * Resources
306
307 ** Ken Raeburn's Guile Emacs page
308
309 http://www.mit.edu/~raeburn/guilemacs/
310
311 ** Keisuke Nishida's Gemacs project
312
313 http://gemacs.sourceforge.net
314
315 ** Jim Blandy's nil/#f/() notes
316
317 http://sanpietro.red-bean.com/guile/guile/old/3114.html
318
319 ** Mikael Djurfeldt's notes on translation
320
321 See file guile-cvs/devel/translation/langtools.text in Guile CVS.