1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-18 18:40:22 +02:00
guile/module/language/elisp
Brian Templeton 7d6816f0c7 store special operators in the function slot
If the function slot of a symbol contains a pair with `special-operator'
in the car and a procedure in the cdr, the procedure is called to
compile the form to Tree-IL. This is similar to other Emacs Lisp
implementations, in which special operators are subrs.

* module/language/elisp/compile-tree-il.scm: Restructured to store
  special operator definitions in the function slot. Import `(language
  elisp runtime)' for `defspecial'. Export special operators so that
  `(language elisp runtime function-slot)' can re-export them.

  (backquote?): Removed; the backquote symbol is defined as a special
  operator, so it's no longer used in `compile-pair'.

  (is-macro?, get-macro): Replaced by `find-operator'.
  (find-operator): New procedure.

  (compile-progn, compile-if, compile-defconst, compile-defvar,
  compile-setq, compile-let, compile-lexical-let, compile-flet,
  compile-let*, compile-lexical-let*, compile-flet*,
  compile-without-void-checks, compile-with-always-lexical,
  compile-guile-ref, compile-guile-primitive, compile-while,
  compile-function, compile-defmacro, compile-defun, #{compile-`}#,
  compile-quote): New special operators with definitions taken from the
  pmatch form in `compile-pair'. There is no special operator `lambda';
  it is now a macro, as in other Elisp implementations.

  (compile-pair): Instead of directly compiling special forms, check for
  a special operator object in the function slot.

* module/language/elisp/runtime.scm: Export `defspecial'.
  (make-id): New function.
  (built-in-macro): Prefix macros with `macro-'.
  (defspecial): New syntax.

* module/language/elisp/runtime/function-slot.scm: Import and re-export
  special operators. Rename imported special operators and macros to
  remove prefixes. Re-export new macro `lambda'.

* module/language/elisp/runtime/macros.scm (macro-lambda): New Elisp
  macro.
2010-08-13 16:35:51 -04:00
..
runtime store special operators in the function slot 2010-08-13 16:35:51 -04:00
bindings.scm reindent 2010-08-13 16:35:50 -04:00
compile-tree-il.scm store special operators in the function slot 2010-08-13 16:35:51 -04:00
lexer.scm handle EOF correctly in parser and lexer 2010-08-13 16:35:51 -04:00
parser.scm handle EOF correctly in parser and lexer 2010-08-13 16:35:51 -04:00
README change remaining %nil -> #nil 2010-04-09 21:06:29 +02:00
runtime.scm store special operators in the function slot 2010-08-13 16:35:51 -04:00
spec.scm reindent 2010-08-13 16:35:50 -04:00

Guile's Emacs Lisp compiler
===========================

This is more or less a lot of work in progress.  Here are some notes as well
as status information.

Already implemented:
  * progn, prog1, prog2
  * if, cond, when, unless
  * not, and, or
  * referencing and setting (setq) variables
  * set, symbol-value, makunbound, boundp functions
  * fset, symbol-function, fmakunbound, fboundp
  * funcall, apply (also with raw lists as arguments and the like!)
  * eval
  * while, dotimes, dolist
  * catch, throw, unwind-protect
  * let, let*
  * lambda expressions, function calls using list notation
  * some built-ins (mainly numbers/arithmetic)
  * defconst, defvar, defun
  * macros
  * quotation and backquotation with unquote/unquote-splicing
  * specific elisp reader

Especially still missing:
  * more general built-ins
  * advice?
  * defsubst and inlining
  * recursive macros
  * anonymous macros

Other ideas and things to think about:
  * #nil vs. #f/'() handling in Guile

Compiler options implemented:
  * #:disable-void-check ['all / '(sym1 sym2 sym3)] to disable the check
    for void value on access either completely or for some symbols
  * #:always-lexical (usable same as disable-void-check) to always bind
    certain or all symbols lexically (including lambda arguments)

Extensions over original elisp:
  * guile-ref, guile-primitive
  * flet and flet*
  * lexical-let and lexical-let*
  * without-void-checks, with-always-lexical


Details to the implemented extensions
=====================================

guile-ref and guile-primitive:
------------------------------

(guile-ref module sym) is a new special construct to access symbols from the
Guile-world.  Actually, (guile-ref module sym) is the same as (@ module sym)
would be in Scheme.  Both module and sym must be statically given and are not
evaluated.

(guile-primitive sym) does the same to access a Guile primitive directly, which
is slightly faster where applicable.

flet and flet*:
---------------

These constructs behave exactly like let and let*, except that they bind the
function slots rather than the value slots, and so make dynamic scoping
available for functions, too.

The distinction between flet and flet* is probably less useful than the one
between let and let*, but it was easy to implement both flet and flet*
based on the existing let and let* code, so not having both of them seemed
a little inconsistent.

lexical-let and lexical-let*:
-----------------------------

lexical-let and lexical-let* are constructs provided by the elisp package
'cl originally, but in Guile they are natively implemented because using
lexical instead of dynamic binding gives better performance in this case.

They work just like let and let*, but bind their target symbols lexically.
Some oberservations with the Emacs 'cl implementation that we mimic in Guile
for compatibility:

  * Ordinary let's within the lexical scope of a lexical-let still establish new
    *lexical* bindings for symbols already lexically bound.  So once lexical,
    always lexical (on a per-symbol basis).

  * However, lambda constructs within the lexical scope of a lexical-let where
    one of their arguments is already lexically bound still bind it dynamically
    for their scope.

  * On the other hand, symbols lexically bound that are not rebound via the
    argument-list build lexical closures just well.

  * If symbols are accessed where they are not known at compile-time (like
    symbol-value or set primitives), this always refers to the dynamic binding
    and never the lexical one.  That's very nice to the implementor...

without-void-checks:
--------------------

Disable void checks in addition to the compiler option for all or some symbols
in the lexical scope of this construct:

(without-void-checks all body...) or
(without-void-checks (sym1 sym2 ...) body...

with-always-lexical:
--------------------

As without-void-checks but adds to list of symbols that should always be bound
lexically.  This lexical binding includes lambda arguments (if the symbols
match up with the list), which can not be bound lexically otherwise.