local-eval will go away
[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 see the STATUS file for the full position.
49
50 ** Trying to load a complete Emacs environment.
51
52 To try this, type `(use-modules (lang elisp interface))' and then
53 `(load-emacs)'. The following output shows how far I get when I try
54 this.
55
56 guile> (use-modules (lang elisp interface))
57 guile> (load-emacs)
58 Calling loadup.el to clothe the bare Emacs...
59 Loading /usr/share/emacs/20.7/lisp/loadup.el...
60 Using load-path ("/usr/share/emacs/20.7/lisp/" "/usr/share/emacs/20.7/lisp/emacs-lisp/")
61 Loading /usr/share/emacs/20.7/lisp/byte-run.el...
62 Loading /usr/share/emacs/20.7/lisp/byte-run.el...done
63 Loading /usr/share/emacs/20.7/lisp/subr.el...
64 Loading /usr/share/emacs/20.7/lisp/subr.el...done
65 Loading /usr/share/emacs/20.7/lisp/version.el...
66 Loading /usr/share/emacs/20.7/lisp/version.el...done
67 Loading /usr/share/emacs/20.7/lisp/map-ynp.el...
68 Loading /usr/share/emacs/20.7/lisp/map-ynp.el...done
69 Loading /usr/share/emacs/20.7/lisp/widget.el...
70 Loading /usr/share/emacs/20.7/lisp/emacs-lisp/cl.el...
71 Loading /usr/share/emacs/20.7/lisp/emacs-lisp/cl.el...done
72 Loading /usr/share/emacs/20.7/lisp/widget.el...done
73 Loading /usr/share/emacs/20.7/lisp/custom.el...
74 Loading /usr/share/emacs/20.7/lisp/custom.el...done
75 Loading /usr/share/emacs/20.7/lisp/cus-start.el...
76 Note, built-in variable `abbrev-all-caps' not bound
77 ... [many other variable not bound messages] ...
78 Loading /usr/share/emacs/20.7/lisp/cus-start.el...done
79 Loading /usr/share/emacs/20.7/lisp/international/mule.el...
80 <unnamed port>: In procedure make-char-table in expression (@fop make-char-table (# #)):
81 <unnamed port>: Symbol's function definition is void
82 ABORT: (misc-error)
83
84 Type "(backtrace)" to get more information or "(debug)" to enter the debugger.
85 guile>
86
87 That's 3279 lines ("wc -l") of Elisp code already, which isn't bad!
88
89 I think that progress beyond this point basically means implementing
90 multilingual and multibyte strings properly for Guile. Which is a
91 _lot_ of work and requires IMO a very clear plan for Guile's role with
92 respect to Emacs.
93
94 * Design
95
96 When thinking about how to implement an Elisp translator for Guile, it
97 is important to realize that the great power of Emacs does not arise
98 from Elisp (seen as a language in syntactic terms) alone, but from the
99 combination of this language with the collection of primitives
100 provided by the Emacs C source code. Therefore, to be of practical
101 use, an Elisp translator needs to be more than just a transformer that
102 translates sexps to Scheme expressions.
103
104 The finished translator should consist of several parts...
105
106 ** Syntax transformation
107
108 Although syntax transformation isn't all we need, we do still need it!
109
110 This part is implemented by the (lang elisp transform) module; it is
111 close to complete and seems to work pretty reliably.
112
113 Note that transformed expressions use the `@fop' and `@bind' macros
114 provided by...
115
116 ** C support for transformed expressions
117
118 For performance and historical reasons (and perhaps necessity - I
119 haven't thought about it enough yet), some of the transformation
120 support is written in C.
121
122 *** @fop
123
124 The `@fop' macro is used to dispatch Elisp applications. Its first
125 argument is a symbol, and this symbol's function slot is examined to
126 find a procedure or macro to apply to the remaining arguments. `@fop'
127 also handles aliasing (`defalias'): in this case the function slot
128 contains another symbol.
129
130 Once `@fop' has found the appropriate procedure or macro to apply, it
131 returns an application expression in which that procedure or macro
132 replaces the `@fop' and the original symbol. Hence no Elisp-specific
133 evaluator support is required to perform the application.
134
135 *** @bind
136
137 Currently, Elisp variables are the same as Scheme variables, so
138 variable references are effectively untransformed.
139
140 The `@bind' macro does Elisp-style dynamic variable binding.
141 Basically, it locates the named top level variables, `set!'s them to
142 new values, evaluates its body, and then uses `set!' again to restore
143 the original values.
144
145 Because of the body evaluation, `@bind' requires evaluator support.
146 In fact, the `@bind' macro code does little more than replace itself
147 with the memoized SCM_IM_BIND. Most of the work is done by the
148 evaluator when it hits SCM_IM_BIND.
149
150 One theoretical problem with `@bind' is that any local Scheme variable
151 in the same scope and with the same name as an Elisp variable will
152 shadow the Elisp variable. But in practice it's difficult to set up
153 such a situation; an exception is the translator code itself, so there
154 we mangle the relevant Scheme variable names a bit to avoid the
155 problem.
156
157 Other possible problems with this approach are that it might not be
158 possible to implement buffer local variables properly, and that
159 `@bind' might become too inefficient when we implement full support
160 for undefining Scheme variables. So we might in future have to
161 transform Elisp variable references after all.
162
163 *** Truth value stuff
164
165 Following extensive discussions on the Guile mailing list between
166 September 2001 and January 2002, we decided to go with Jim Blandy's
167 proposal. See devel/translation/lisp-and-scheme.text for details.
168
169 - The Elisp nil value is a new immediate SCM_MAKIFLAG, eq?-distinct
170 from both #f and '() (and of course any other Scheme value). It can
171 be accessed via the (guile) binding `%nil', and prints as `#nil'.
172
173 - All Elisp primitives treat #nil, #f and '() as identical.
174
175 - Scheme truth-testing primitives have been modified so that they
176 treat #nil the same as #f.
177
178 - Scheme list-manipulating primitives have been modified so that they
179 treat #nil the same as '().
180
181 - The Elisp t value is the same as #t.
182
183 ** Emacs editing primitives
184
185 Buffers, keymaps, text properties, windows, frames etc. etc.
186
187 Basically, everything that is implemented as a primitive in the Emacs
188 C code needs to be implemented either in Scheme or in C for Guile.
189
190 The Scheme files in the primitives subdirectory implement some of
191 these primitives in Scheme. Not because that is the right decision,
192 but because this is a proof of concept and it's quicker to write badly
193 performing code in Scheme.
194
195 Ultimately, most of these primitive definitions should really come
196 from the Emacs C code itself, translated or preprocessed in a way that
197 makes it compile with Guile. I think this is pretty close to the work
198 that Ken Raeburn has been doing on the Emacs codebase.
199
200 ** Reading and printing support
201
202 Elisp is close enough to Scheme that it's convenient to coopt the
203 existing Guile reader rather than to write a new one from scratch, but
204 there are a few syntactic differences that will require changes in
205 reading and printing. None of the following changes has yet been
206 implemented.
207
208 - Character syntax is `?a' rather than `#\a'. (Not done. More
209 precisely, `?a' in Elisp isn't character syntax but an alternative
210 integer syntax. Note that we could support most of the `?a' syntax
211 simply by doing
212
213 (define ?a (char->integer #\a)
214 (define ?b (char->integer #\b)
215
216 and so on.)
217
218 - Vector syntax is `[1 2 3]' rather than `#(1 2 3)'.
219
220 - When in an Elisp environment, #nil and #t should print as `nil' and
221 `t'.
222
223 ** The Elisp evaluation module (lang elisp base)
224
225 Fundamentally, Guile's module system can't be used to package Elisp
226 code in the same way it is used for Scheme code, because Elisp
227 function definitions are stored as symbol properties (in the symbol's
228 "function slot") and so are global. On the other hand, it is useful
229 (necessary?) to associate some particular module with Elisp evaluation
230 because
231
232 - Elisp variables are currently implemented as Scheme variables and so
233 need to live in some module
234
235 - a syntax transformer is a property of a module.
236
237 Therefore we have the (lang elisp base) module, which acts as the
238 repository for all Elisp variables and the site of all Elisp
239 evaluation.
240
241 The initial environment provided by this module is intended to be a
242 non-Emacs-dependent subset of Elisp. To get the idea, imagine someone
243 who wants to write an extension function for, say Gnucash, and simply
244 prefers to write in Elisp rather than in Scheme. He/she therefore
245 doesn't buffers, keymaps and so on, just the basic language syntax and
246 core data functions like +, *, concat, length etc., plus specific
247 functions made available by Gnucash.
248
249 (lang elisp base) achieves this by
250
251 - importing Scheme definitions for some Emacs primitives from the
252 files in the primitives subdirectory
253
254 - then switching into Elisp syntax.
255
256 After this point, `(eval XXX (resolve-module '(lang elisp base)))'
257 will evaluate XXX as an Elisp expression in the (lang elisp base)
258 module. (`eval-elisp' in (lang elisp interface) is a more convenient
259 wrapper for this.)
260
261 ** Full Emacs environment
262
263 The difference between the initial (lang elisp base) environment and a
264 fully loaded Emacs equivalent is
265
266 - more primitives: buffers, char-tables and many others
267
268 - the bootstrap Elisp code that an undumped Emacs loads during
269 installation by calling `(load "loadup.el")'.
270
271 We don't have all the missing primitives, but we can already get
272 through some of loadup.el. The Elisp function `load-emacs' (defined
273 in (lang elisp base) initiates the loading of loadup.el; (lang elisp
274 interface) exports `load-emacs' to Scheme.
275
276 `load-emacs' loads so much Elisp code that it's an excellent way to
277 test the translator. In current practice, it runs for a while and
278 then fails when it gets to an undefined primitive or a bug in the
279 translator. Eventually, it should go all the way. (And then we can
280 worry about adding unexec support to Guile!) For the output that
281 currently results from calling `(load-emacs)', see above in the Status
282 section.
283
284 * Resources
285
286 ** Ken Raeburn's Guile Emacs page
287
288 http://www.mit.edu/~raeburn/guilemacs/
289
290 ** Keisuke Nishida's Gemacs project
291
292 http://gemacs.sourceforge.net
293
294 ** Jim Blandy's nil/#f/() notes
295
296 http://sanpietro.red-bean.com/guile/guile/old/3114.html
297
298 Also now stored as guile-core/devel/translation/lisp-and-scheme.text
299 in Guile CVS.
300
301 ** Mikael Djurfeldt's notes on translation
302
303 See file guile-core/devel/translation/langtools.text in Guile CVS.