README 11 KB

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