X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=guile18%2Flang%2Felisp%2FREADME;fp=guile18%2Flang%2Felisp%2FREADME;h=1cecb381f755eda14325e99afb290065f63a82c2;hb=139c38d9204dd07f6b235f83bae644faedbc63fd;hp=0000000000000000000000000000000000000000;hpb=652ed35a2013489d0a14fede6307cd2595abb2c4;p=lilypond.git diff --git a/guile18/lang/elisp/README b/guile18/lang/elisp/README new file mode 100644 index 0000000000..1cecb381f7 --- /dev/null +++ b/guile18/lang/elisp/README @@ -0,0 +1,303 @@ + -*- outline -*- + +This directory holds the Scheme side of a translator for Emacs Lisp. + +* Usage + +To load up the base Elisp environment: + + (use-modules (lang elisp base)) + +Then you can switch into this module + + (define-module (lang elisp base)) + +and start typing away in Elisp, or evaluate an individual Elisp +expression from Scheme: + + (eval EXP (resolve-module '(lang elisp base))) + +A more convenient, higher-level interface is provided by (lang elisp +interface): + + (use-modules (lang elisp interface)) + +With this interface, you can evaluate an Elisp expression + + (eval-elisp EXP) + +load an Elisp file with no effect on the Scheme world + + (load-elisp-file "/home/neil/Guile/cvs/guile-core/lang/elisp/example.el") + +load an Elisp file, automatically importing top level definitions into +Scheme + + (use-elisp-file "/home/neil/Guile/cvs/guile-core/lang/elisp/example.el") + +export Scheme objects to Elisp + + (export-to-elisp + - * my-func 'my-var) + +and try to bootstrap a complete Emacs environment: + + (load-emacs) + +* Status + +Please see the STATUS file for the full position. + +** Trying to load a complete Emacs environment. + +To try this, type `(use-modules (lang elisp interface))' and then +`(load-emacs)'. The following output shows how far I get when I try +this. + +guile> (use-modules (lang elisp interface)) +guile> (load-emacs) +Calling loadup.el to clothe the bare Emacs... +Loading /usr/share/emacs/20.7/lisp/loadup.el... +Using load-path ("/usr/share/emacs/20.7/lisp/" "/usr/share/emacs/20.7/lisp/emacs-lisp/") +Loading /usr/share/emacs/20.7/lisp/byte-run.el... +Loading /usr/share/emacs/20.7/lisp/byte-run.el...done +Loading /usr/share/emacs/20.7/lisp/subr.el... +Loading /usr/share/emacs/20.7/lisp/subr.el...done +Loading /usr/share/emacs/20.7/lisp/version.el... +Loading /usr/share/emacs/20.7/lisp/version.el...done +Loading /usr/share/emacs/20.7/lisp/map-ynp.el... +Loading /usr/share/emacs/20.7/lisp/map-ynp.el...done +Loading /usr/share/emacs/20.7/lisp/widget.el... +Loading /usr/share/emacs/20.7/lisp/emacs-lisp/cl.el... +Loading /usr/share/emacs/20.7/lisp/emacs-lisp/cl.el...done +Loading /usr/share/emacs/20.7/lisp/widget.el...done +Loading /usr/share/emacs/20.7/lisp/custom.el... +Loading /usr/share/emacs/20.7/lisp/custom.el...done +Loading /usr/share/emacs/20.7/lisp/cus-start.el... +Note, built-in variable `abbrev-all-caps' not bound + ... [many other variable not bound messages] ... +Loading /usr/share/emacs/20.7/lisp/cus-start.el...done +Loading /usr/share/emacs/20.7/lisp/international/mule.el... +: In procedure make-char-table in expression (@fop make-char-table (# #)): +: Symbol's function definition is void +ABORT: (misc-error) + +Type "(backtrace)" to get more information or "(debug)" to enter the debugger. +guile> + +That's 3279 lines ("wc -l") of Elisp code already, which isn't bad! + +I think that progress beyond this point basically means implementing +multilingual and multibyte strings properly for Guile. Which is a +_lot_ of work and requires IMO a very clear plan for Guile's role with +respect to Emacs. + +* Design + +When thinking about how to implement an Elisp translator for Guile, it +is important to realize that the great power of Emacs does not arise +from Elisp (seen as a language in syntactic terms) alone, but from the +combination of this language with the collection of primitives +provided by the Emacs C source code. Therefore, to be of practical +use, an Elisp translator needs to be more than just a transformer that +translates sexps to Scheme expressions. + +The finished translator should consist of several parts... + +** Syntax transformation + +Although syntax transformation isn't all we need, we do still need it! + +This part is implemented by the (lang elisp transform) module; it is +close to complete and seems to work pretty reliably. + +Note that transformed expressions use the `@fop' and `@bind' macros +provided by... + +** C support for transformed expressions + +For performance and historical reasons (and perhaps necessity - I +haven't thought about it enough yet), some of the transformation +support is written in C. + +*** @fop + +The `@fop' macro is used to dispatch Elisp applications. Its first +argument is a symbol, and this symbol's function slot is examined to +find a procedure or macro to apply to the remaining arguments. `@fop' +also handles aliasing (`defalias'): in this case the function slot +contains another symbol. + +Once `@fop' has found the appropriate procedure or macro to apply, it +returns an application expression in which that procedure or macro +replaces the `@fop' and the original symbol. Hence no Elisp-specific +evaluator support is required to perform the application. + +*** @bind + +Currently, Elisp variables are the same as Scheme variables, so +variable references are effectively untransformed. + +The `@bind' macro does Elisp-style dynamic variable binding. +Basically, it locates the named top level variables, `set!'s them to +new values, evaluates its body, and then uses `set!' again to restore +the original values. + +Because of the body evaluation, `@bind' requires evaluator support. +In fact, the `@bind' macro code does little more than replace itself +with the memoized SCM_IM_BIND. Most of the work is done by the +evaluator when it hits SCM_IM_BIND. + +One theoretical problem with `@bind' is that any local Scheme variable +in the same scope and with the same name as an Elisp variable will +shadow the Elisp variable. But in practice it's difficult to set up +such a situation; an exception is the translator code itself, so there +we mangle the relevant Scheme variable names a bit to avoid the +problem. + +Other possible problems with this approach are that it might not be +possible to implement buffer local variables properly, and that +`@bind' might become too inefficient when we implement full support +for undefining Scheme variables. So we might in future have to +transform Elisp variable references after all. + +*** Truth value stuff + +Following extensive discussions on the Guile mailing list between +September 2001 and January 2002, we decided to go with Jim Blandy's +proposal. See devel/translation/lisp-and-scheme.text for details. + +- The Elisp nil value is a new immediate SCM_MAKIFLAG, eq?-distinct +from both #f and '() (and of course any other Scheme value). It can +be accessed via the (guile) binding `%nil', and prints as `#nil'. + +- All Elisp primitives treat #nil, #f and '() as identical. + +- Scheme truth-testing primitives have been modified so that they +treat #nil the same as #f. + +- Scheme list-manipulating primitives have been modified so that they +treat #nil the same as '(). + +- The Elisp t value is the same as #t. + +** Emacs editing primitives + +Buffers, keymaps, text properties, windows, frames etc. etc. + +Basically, everything that is implemented as a primitive in the Emacs +C code needs to be implemented either in Scheme or in C for Guile. + +The Scheme files in the primitives subdirectory implement some of +these primitives in Scheme. Not because that is the right decision, +but because this is a proof of concept and it's quicker to write badly +performing code in Scheme. + +Ultimately, most of these primitive definitions should really come +from the Emacs C code itself, translated or preprocessed in a way that +makes it compile with Guile. I think this is pretty close to the work +that Ken Raeburn has been doing on the Emacs codebase. + +** Reading and printing support + +Elisp is close enough to Scheme that it's convenient to coopt the +existing Guile reader rather than to write a new one from scratch, but +there are a few syntactic differences that will require changes in +reading and printing. None of the following changes has yet been +implemented. + +- Character syntax is `?a' rather than `#\a'. (Not done. More + precisely, `?a' in Elisp isn't character syntax but an alternative + integer syntax. Note that we could support most of the `?a' syntax + simply by doing + + (define ?a (char->integer #\a) + (define ?b (char->integer #\b) + + and so on.) + +- Vector syntax is `[1 2 3]' rather than `#(1 2 3)'. + +- When in an Elisp environment, #nil and #t should print as `nil' and + `t'. + +** The Elisp evaluation module (lang elisp base) + +Fundamentally, Guile's module system can't be used to package Elisp +code in the same way it is used for Scheme code, because Elisp +function definitions are stored as symbol properties (in the symbol's +"function slot") and so are global. On the other hand, it is useful +(necessary?) to associate some particular module with Elisp evaluation +because + +- Elisp variables are currently implemented as Scheme variables and so + need to live in some module + +- a syntax transformer is a property of a module. + +Therefore we have the (lang elisp base) module, which acts as the +repository for all Elisp variables and the site of all Elisp +evaluation. + +The initial environment provided by this module is intended to be a +non-Emacs-dependent subset of Elisp. To get the idea, imagine someone +who wants to write an extension function for, say Gnucash, and simply +prefers to write in Elisp rather than in Scheme. He/she therefore +doesn't buffers, keymaps and so on, just the basic language syntax and +core data functions like +, *, concat, length etc., plus specific +functions made available by Gnucash. + +(lang elisp base) achieves this by + +- importing Scheme definitions for some Emacs primitives from the + files in the primitives subdirectory + +- then switching into Elisp syntax. + +After this point, `(eval XXX (resolve-module '(lang elisp base)))' +will evaluate XXX as an Elisp expression in the (lang elisp base) +module. (`eval-elisp' in (lang elisp interface) is a more convenient +wrapper for this.) + +** Full Emacs environment + +The difference between the initial (lang elisp base) environment and a +fully loaded Emacs equivalent is + +- more primitives: buffers, char-tables and many others + +- the bootstrap Elisp code that an undumped Emacs loads during + installation by calling `(load "loadup.el")'. + +We don't have all the missing primitives, but we can already get +through some of loadup.el. The Elisp function `load-emacs' (defined +in (lang elisp base) initiates the loading of loadup.el; (lang elisp +interface) exports `load-emacs' to Scheme. + +`load-emacs' loads so much Elisp code that it's an excellent way to +test the translator. In current practice, it runs for a while and +then fails when it gets to an undefined primitive or a bug in the +translator. Eventually, it should go all the way. (And then we can +worry about adding unexec support to Guile!) For the output that +currently results from calling `(load-emacs)', see above in the Status +section. + +* Resources + +** Ken Raeburn's Guile Emacs page + +http://www.mit.edu/~raeburn/guilemacs/ + +** Keisuke Nishida's Gemacs project + +http://gemacs.sourceforge.net + +** Jim Blandy's nil/#f/() notes + +http://sanpietro.red-bean.com/guile/guile/old/3114.html + +Also now stored as guile-core/devel/translation/lisp-and-scheme.text +in Guile CVS. + +** Mikael Djurfeldt's notes on translation + +See file guile-core/devel/translation/langtools.text in Guile CVS.