1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-04-30 03:40:34 +02:00

Improved macro handling; started documenting the issue.

* doc/guile-vm.texi (Compiling Scheme Code): New node.

* module/language/scheme/translate.scm (&current-macro-module): New.
  (translate): Evaluate macros in `&current-macro-module'.
  (trans-pair): Likewise.

git-archimport-id: lcourtes@laas.fr--2005-mobile/guile-vm--mobile--0.6--patch-13
This commit is contained in:
Ludovic Courtes 2006-01-03 23:13:30 +00:00 committed by Ludovic Courtès
parent a316e42d98
commit 9dbbe4bb83
2 changed files with 77 additions and 18 deletions

View file

@ -121,6 +121,7 @@ The Compiler
* Overview::
* The Language Front-Ends::
* GHIL::
* Compiling Scheme Code::
* GLIL::
* The Assembler::
@ -737,6 +738,7 @@ Set}).
* Overview::
* The Language Front-Ends::
* GHIL::
* Compiling Scheme Code::
* GLIL::
* The Assembler::
@end menu
@ -815,12 +817,13 @@ the compiler to handle source written in that language. Of particular
interest is the @code{translator} slot (@pxref{GHIL}).
@end deftp
@deffn @scmproc{} lookup-language symbol
Look for a language front-end named @var{symbol} and return the
@code{<language>} record describing it if found. If @var{symbol}
doesn't denote a language front-end, an error is raised. Note that
this procedure assumes that language @var{symbol} exists if there
exist a @code{(language @var{symbol} spec)} module.
@deffn @scmproc{} lookup-language lang
Look for a language front-end named @var{lang}, a symbol (e.g,
@code{scheme}), and return the @code{<language>} record describing it
if found. If @var{lang} does not denote a language front-end, an
error is raised. Note that this procedure assumes that language
@var{lang} exists if there exist a @code{(language @var{lang} spec)}
module.
@end deffn
The @code{(system base compile)} module defines a procedure similar to
@ -852,7 +855,7 @@ GHIL-to-GLIL compiler described in @xref{GLIL}.
@end deffn
@node GHIL, GLIL, The Language Front-Ends, The Compiler
@node GHIL, Compiling Scheme Code, The Language Front-Ends, The Compiler
@section Guile's High-Level Intermediate Language
GHIL has constructs almost equivalent to those found in Scheme.
@ -895,11 +898,45 @@ close to the fundamental primitives of Scheme.
It is the role of front-end language translators (@pxref{The Language
Front-Ends}) to produce a sequence of GHIL objects from the
human-readable, source programming language.
human-readable, source programming language. The next section
describes the translator for the Scheme language.
[FIXME: Describe more.]
@node Compiling Scheme Code, GLIL, GHIL, The Compiler
@section Compiling Scheme Code
@node GLIL, The Assembler, GHIL, The Compiler
The language object for Scheme, as returned by @code{(lookup-language
'scheme)} (@pxref{The Language Front-Ends}), defines a translator
procedure that returns a sequence of GHIL objects given Scheme code.
Before actually performing this operation, the Scheme translator
expands macros in the original source code.
The macros that may be expanded can come from different sources:
@itemize
@item core Guile macros, such as @code{false-if-exception};
@item macros defined in modules used by the module being compiled,
e.g., @code{receive} in @code{(ice-9 receive)};
@item macros defined within the module being compiled.
@end itemize
@cindex macro
@cindex syntax transformer
@findex define-macro
@findex defmacro
The main complexity in handling macros at compilation time is that
Guile's macros are first-class objects. For instance, when using
@code{define-macro}, one actually defines a @emph{procedure} that
returns code; of course, unlike a ``regular'' procedure, it is
executed when an S-exp is @dfn{memoized} by the evaluator, i.e.,
before the actual evaluation takes place. Worse, it is possible to
turn a procedure into a macro, or @dfn{syntax transformer}, thus
removing, to some extent, the boundary between the macro expansion and
evaluation phases, @inforef{Internal Macros, , guile}.
[FIXME: explain limitations, etc.]
@node GLIL, The Assembler, Compiling Scheme Code, The Compiler
@section Guile's Low-Level Intermediate Language
A GHIL instruction sequence can be compiled into GLIL using the

View file

@ -32,8 +32,16 @@
;; Hash table containing the macros currently defined.
(define &current-macros (make-parameter #f))
;; Module in which macros are evaluated.
(define &current-macro-module (make-parameter #f))
(define (translate x e)
(parameterize ((&current-macros (make-hash-table)))
(parameterize ((&current-macros (make-hash-table))
(&current-macro-module (make-module)))
;; Import only core bindings in the macro module.
(module-use! (&current-macro-module) (resolve-module '(guile-user)))
(call-with-ghil-environment (make-ghil-mod e) '()
(lambda (env vars)
(<ghil-lambda> env #f vars #f (trans env #f x))))))
@ -46,10 +54,15 @@
(define (expand-macro e)
;; Similar to `macroexpand' in `boot-9.scm' except that it does not expand
;; `define-macro' and `defmacro'.
;; FIXME: This does not handle macros defined in modules used by the
;; module being compiled.
(cond
((pair? e)
(let* ((head (car e))
(val (and (symbol? head) (local-ref (list head)))))
(val (and (symbol? head)
(false-if-exception
(module-ref (&current-macro-module) head)))))
(case head
((defmacro define-macro)
;; Normally, these are expanded as `defmacro:transformer' but we
@ -62,7 +75,11 @@
(if (not local-macro)
e
(if (procedure? local-macro)
(expand-macro (apply local-macro (cdr e)))
(expand-macro
(save-module-excursion
(lambda ()
(set-current-module (&current-macro-module))
(apply local-macro (cdr e)))))
(syntax-error #f (format #f "~a: invalid macro" head)
local-macro)))))))))
(#t e)))
@ -152,12 +169,17 @@
(formal-args (if shortcut? (cadr tail) (cdar tail)))
(body (if shortcut? (cddr tail) (cdr tail))))
;; Evaluate the macro in the current macro module.
(hashq-set! (&current-macros) macro-name
;; FIXME: The lambda is evaluated in the current module.
(primitive-eval `(lambda ,formal-args ,@body)))
; (format (current-error-port) "macro `~a': ~a~%"
; macro-name (hashq-ref (&current-macros) macro-name))
(catch #t
(lambda ()
(eval `(lambda ,formal-args ,@body)
(&current-macro-module)))
(lambda (key . args)
(syntax-error l (string-append "failed to evaluate "
"macro `" macro-name
"'")
(cons key args)))))
(make:void)))