1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-10 05:50:26 +02:00

rename translate.scm to compile-ghil.scm, and more work on compiler.texi

* doc/ref/api-evaluation.texi: Fix some typos and xrefs.

* doc/ref/compiler.texi (The Scheme Compiler): Document the scheme
  compiler, and start documenting the GHIL language.

* doc/ref/guile.texi (Guile Implementation): Whoops, put autoconf after
  the implementation foo. Unless we want it before?

* doc/ref/history.texi (The Emacs Thesis): Fix typo.

* doc/ref/vm.texi (Environment Control Instructions): Rename offset to
  index.

* module/language/ghil.scm (parse-ghil): Fix what I think was a bug --
  the consumer in a mv-call shouldn't be a rest arg.

* module/language/scheme/Makefile.am (SOURCES):
* module/language/scheme/compile-ghil.scm: Rename this file from
  translate.scm.

* module/oop/goops.scm:
* module/language/scheme/spec.scm: Deal with renaming.
This commit is contained in:
Andy Wingo 2009-01-09 17:49:09 +01:00
parent e3ba263de4
commit ca445ba5ec
10 changed files with 208 additions and 47 deletions

View file

@ -424,7 +424,7 @@ desired results. This is known as @dfn{compilation}.
While it is possible to compile simple Scheme expressions such as
@code{(+ 2 2)} or even @code{"Hello world!"}, compilation is most
interesting in th context of procedures. Compiling a lambda expression
interesting in the context of procedures. Compiling a lambda expression
produces a compiled procedure, which is just like a normal procedure
except typically much faster, because it can bypass the generic
interpreter.
@ -446,8 +446,8 @@ computation are fulfilled by macros and closures. Of course one good
counterexample is the REPL itself, or any code that reads expressions
from a port.)
For more information on the compiler itself, @xref{Compiling to the
Virtual Machine}. For information on the virtual machine, @xref{A
For more information on the compiler itself, see @ref{Compiling to the
Virtual Machine}. For information on the virtual machine, see @ref{A
Virtual Machine for Guile}.
@deffn {Scheme Procedure} compile exp [env=#f] [from=(current-language)] [to=value] [opts=()]

View file

@ -68,7 +68,7 @@ for Scheme:
#:version "0.5"
#:reader read
#:read-file read-file
#:compilers `((,ghil . ,translate))
#:compilers `((,ghil . ,compile-ghil))
#:evaluator (lambda (x module) (primitive-eval x))
#:printer write)
@end example
@ -158,28 +158,191 @@ different worlds indefinitely, as shown by the following quine:
@node The Scheme Compiler
@subsection The Scheme Compiler
macro expansion
The job of the Scheme compiler is to expand all macros and to resolve
all symbols to lexical variables. Its target language, GHIL, is fairly
close to Scheme itself, so this process is not very complicated.
define-scheme-translator
The Scheme compiler is driven by a table of @dfn{translators},
declared with the @code{define-scheme-translator} form, defined in the
module, @code{(language scheme compile-ghil)}.
inlining
@deffn {Scheme Syntax} define-scheme-translator head clause1 clause2...
The best documentation of this form is probably an example. Here is
the translator for @code{if}:
format of the environment
@example
(define-scheme-translator if
;; (if TEST THEN [ELSE])
((,test ,then)
(make-ghil-if e l (retrans test) (retrans then) (retrans '(begin))))
((,test ,then ,else)
(make-ghil-if e l (retrans test) (retrans then) (retrans else))))
@end example
compile-time-environment
The match syntax is from the @code{pmatch} macro, defined in
@code{(system base pmatch)}. The result of a clause should be a valid
GHIL value. If no clause matches, a syntax error is signalled.
symbols resolved as local, external, or toplevel
In the body of the clauses, the following bindings are introduced:
@itemize
@item @code{e}, the current environment
@item @code{l}, the current source location (or @code{#f})
@item @code{retrans}, a procedure that may be called to compile
subexpressions
@end itemize
Note that translators are looked up by @emph{value}, not by name. That
is to say, the translator is keyed under the @emph{value} of
@code{if}, which normally prints as @code{#<primitive-builtin-macro!
if>}.
@end deffn
Users can extend the compiler by defining new translators.
Additionally, some forms can be inlined directly to
instructions -- @xref{Inlined Scheme Instructions}, for a list. The
actual inliners are defined in @code{(language scheme inline)}:
@deffn {Scheme Syntax} define-inline head arity1 result1 arity2 result2...
Defines an inliner for @code{head}. As in
@code{define-scheme-translator}, inliners are keyed by value and not
by name.
Expressions are matched on their arities. For example:
@example
(define-inline eq?
(x y) (eq? x y))
@end example
This inlines calls to the Scheme procedure, @code{eq?}, to the
instruction @code{eq?}.
A more complicated example would be:
@example
(define-inline +
() 0
(x) x
(x y) (add x y)
(x y . rest) (add x (+ y . rest)))
@end example
@end deffn
Compilers take two arguments, an expression and an environment, and
return two values as well: an expression in the target language, and
an environment suitable for the target language. The format of the
environment is language-dependent.
For Scheme, an environment may be one of three things:
@itemize
@item @code{#f}, in which case compilation is performed in the context
of the current module;
@item a module, which specifies the context of the compilation; or
@item a @dfn{compile environment}, which specifies lexical variables
as well.
@end itemize
The format of a compile environment for scheme is @code{(@var{module}
@var{lexicals} . @var{externals})}, though users are strongly
discouraged from constructing these environments themselves. Instead,
if you need this functionality -- as in GOOPS' dynamic method compiler
-- capture an environment with @code{compile-time-environment}, then
pass that environment to @code{compile}.
@deffn {Scheme Procedure} compile-time-environment
A special function known to the compiler that, when compiled, will
return a representation of the lexical environment in place at compile
time. Useful for supporting some forms of dynamic compilation. Returns
@code{#f} if called from the interpreter.
@end deffn
@node GHIL
@subsection GHIL
ghil environments
structured, typed intermediate language, close to scheme
with an s-expression representation
,lang ghil
document reified format, as it's more interesting, and gives you an idea
all have environment and location pointers
@deffn {GHIL Expression} quote exp
A quoted expression.
@end deffn
@deffn {GHIL Expression} quasiquote exp
A quasiquoted expression. The parse format understands the normal
@code{unquote} and @code{unquote-splicing} forms as in normal Scheme.
When constructing @var{exp} programmatically, you will need to call
@code{make-ghil-unquote} and @code{make-ghil-unquote-splicing} as
appropriate.
@end deffn
@deffn {GHIL Expression} lambda syms rest meta . body
A closure. @var{syms} is the argument list, as a list of symbols.
@var{rest} is a boolean, which is @code{#t} iff the last argument is a
rest argument. @var{meta} is an association list of properties. The
actual @var{body} should be a list of GHIL expressions.
@end deffn
@deffn {GHIL Expression} void
The unspecified value.
@end deffn
@deffn {GHIL Expression} begin . body
Like Scheme's @code{begin}.
@end deffn
@deffn {GHIL Expression} bind syms exprs . body
Like a deconstructed @code{let}: each element of @var{syms} will be
bound to the corresponding GHIL expression in @var{exprs}.
@end deffn
@deffn {GHIL Expression} bindrec syms exprs . body
As @code{bind} is to @code{let}, so @code{bindrec} is to
@code{letrec}.
@end deffn
@deffn {GHIL Expression} set! sym val
Like Scheme's @code{set!}.
@end deffn
@deffn {GHIL Expression} define sym val
Like Scheme's @code{define}, but without the lambda sugar of course.
@end deffn
@deffn {GHIL Expression} if test then else
A conditional. Note that @var{else} is not optional.
@end deffn
@deffn {GHIL Expression} and . exps
Like Scheme's @code{and}.
@end deffn
@deffn {GHIL Expression} or . exps
Like Scheme's @code{or}.
@end deffn
@deffn {GHIL Expression} mv-bind syms rest producer . body
Like Scheme's @code{receive} -- binds the values returned by
applying @code{producer}, which should be a thunk, to the
@code{lambda}-like bindings described by @var{syms} and @var{rest}.
@end deffn
@deffn {GHIL Expression} call proc . args
A procedure call.
@end deffn
@deffn {GHIL Expression} mv-call producer consumer
Like Scheme's @code{call-with-values}.
@end deffn
@deffn {GHIL Expression} inline op . args
An inlined VM instruction. @var{op} should be the instruction name as
a symbol, and @var{args} should be its arguments, as GHIL expressions.
@end deffn
@deffn {GHIL Expression} values . values
Like Scheme's @code{values}.
@end deffn
@deffn {GHIL Expression} values* . values
@var{values} are as in the Scheme expression, @code{(apply values .
@var{vals})}.
@end deffn
@deffn {GHIL Expression} compile-time-environment
Produces, at runtime, a reification of the environment at compile
time.
@end deffn
ghil environments
ghil-var-for-ref!, ghil-var-for-set!, ghil-var-define!, ghil-var-at-module!
some pre-optimization
real name of the game is closure elimination -- fixing letrec

View file

@ -365,8 +365,6 @@ available through both Scheme and C interfaces.
@include scsh.texi
@include scheme-debugging.texi
@include autoconf.texi
@node Guile Implementation
@chapter Guile Implementation
@ -390,6 +388,8 @@ Also Schemers as closet compiler writers.
@include vm.texi
@include compiler.texi
@include autoconf.texi
@include fdl.texi
@iftex

View file

@ -42,9 +42,9 @@ seen in Emacs' current and continued existence, spanning more than a
quarter-century.
Besides providing for modification of a program by others, extension
languages are good for /intension/ as well. Programs built in ``the
Emacs way'' are pleasurable and easy for their authors to flesh out
with the features that they need.
languages are good for @emph{intension} as well. Programs built in
``the Emacs way'' are pleasurable and easy for their authors to flesh
out with the features that they need.
After the Emacs experience was appreciated more widely, a number of
hackers started to consider how to spread this experience to the rest

View file

@ -388,46 +388,46 @@ These instructions access and mutate the environment of a compiled
procedure -- the local bindings, the ``external'' bindings, and the
toplevel bindings.
@deffn Instruction local-ref offset
@deffn Instruction local-ref index
Push onto the stack the value of the local variable located at
@var{offset} within the current stack frame.
@var{index} within the current stack frame.
Note that arguments and local variables are all in one block. Thus the
first argument, if any, is at offset 0, and local bindings follow the
first argument, if any, is at index 0, and local bindings follow the
arguments.
@end deffn
@deffn Instruction local-set offset
@deffn Instruction local-set index
Pop the Scheme object located on top of the stack and make it the new
value of the local variable located at @var{offset} within the current
value of the local variable located at @var{index} within the current
stack frame.
@end deffn
@deffn Instruction external-ref offset
@deffn Instruction external-ref index
Push the value of the closure variable located at position
@var{offset} within the program's list of external variables.
@var{index} within the program's list of external variables.
@end deffn
@deffn Instruction external-set offset
@deffn Instruction external-set index
Pop the Scheme object located on top of the stack and make it the new
value of the closure variable located at @var{offset} within the
value of the closure variable located at @var{index} within the
program's list of external variables.
@end deffn
The external variable lookup algorithm should probably be made more
efficient in the future via addressing by frame and offset. Currently,
efficient in the future via addressing by frame and index. Currently,
external variables are all consed onto a list, which results in O(N)
lookup time.
@deffn Instruction externals
Pushes the current list of external variables onto the stack. This
instruction is used in the implementation of
@code{compile-time-environment}.
@code{compile-time-environment}. @xref{The Scheme Compiler}.
@end deffn
@deffn Instruction toplevel-ref offset
@deffn Instruction toplevel-ref index
Push the value of the toplevel binding whose location is stored in at
position @var{offset} in the object table.
position @var{index} in the object table.
Initially, a cell in the object table that is used by
@code{toplevel-ref} is initialized to one of two forms. The normal
@ -453,9 +453,9 @@ variable has been successfully resolved.
This instruction pushes the value of the variable onto the stack.
@end deffn
@deffn Instruction toplevel-ref offset
@deffn Instruction toplevel-ref index
Pop a value off the stack, and set it as the value of the toplevel
variable stored at @var{offset} in the object table. If the variable
variable stored at @var{index} in the object table. If the variable
has not yet been looked up, we do the lookup as in
@code{toplevel-ref}.
@end deffn
@ -490,15 +490,13 @@ All the conditional branch instructions described below work in the
same way:
@itemize
@item They take the Scheme object located on the stack and use it as
@item They pop off the Scheme object located on the stack and use it as
the branch condition;
@item If the condition is false, then program execution continues with
the next instruction;
@item If the condition is true, then the instruction pointer is
increased by the offset passed as an argument to the branch
instruction;
@item Finally, when the instruction finished, the condition object is
removed from the stack.
@item Program execution proceeds with the next instruction (that is,
the one to which the instruction pointer points).
@end itemize
Note that the offset passed to the instruction is encoded on two 8-bit

View file

@ -404,7 +404,7 @@
((call ,proc . ,args)
(make-ghil-call env loc (retrans proc) (map retrans args)))
((mv-call ,producer . ,consumer)
((mv-call ,producer ,consumer)
(make-ghil-mv-call env loc (retrans producer) (retrans consumer)))
((inline ,op . ,args)

View file

@ -1,3 +1,3 @@
SOURCES = translate.scm spec.scm inline.scm
SOURCES = compile-ghil.scm spec.scm inline.scm
modpath = language/scheme
include $(top_srcdir)/am/guilec

View file

@ -19,7 +19,7 @@
;;; Code:
(define-module (language scheme translate)
(define-module (language scheme compile-ghil)
#:use-module (system base pmatch)
#:use-module (system base language)
#:use-module (language ghil)
@ -29,7 +29,7 @@
#:use-module (ice-9 optargs)
#:use-module ((ice-9 syncase) #:select (sc-macro))
#:use-module ((system base compile) #:select (syntax-error))
#:export (translate translate-1
#:export (compile-ghil translate-1
*translate-table* define-scheme-translator))
@ -59,7 +59,7 @@
(define (translate x e opts)
(define (compile-ghil x e opts)
(save-module-excursion
(lambda ()
(and=> (cenv-module e) set-current-module)
@ -158,11 +158,11 @@
(define *translate-table* (make-hash-table))
(define-macro (define-scheme-translator sym . clauses)
`(hashq-set! (@ (language scheme translate) *translate-table*)
`(hashq-set! (@ (language scheme compile-ghil) *translate-table*)
,sym
(lambda (e l exp)
(define (retrans x)
((@ (language scheme translate) translate-1) e #f x))
((@ (language scheme compile-ghil) translate-1) e #f x))
(define syntax-error (@ (system base compile) syntax-error))
(pmatch (cdr exp)
,@clauses

View file

@ -21,7 +21,7 @@
(define-module (language scheme spec)
#:use-module (system base language)
#:use-module (language scheme translate)
#:use-module (language scheme compile-ghil)
#:use-module (language ghil spec)
#:export (scheme))
@ -46,7 +46,7 @@
#:version "0.5"
#:reader read
#:read-file read-file
#:compilers `((,ghil . ,translate))
#:compilers `((,ghil . ,compile-ghil))
#:evaluator (lambda (x module) (primitive-eval x))
#:printer write
)

View file

@ -1060,7 +1060,7 @@
(eval-case
((load-toplevel compile-toplevel)
(use-modules ((language scheme translate) :select (define-scheme-translator))
(use-modules ((language scheme compile-ghil) :select (define-scheme-translator))
((language ghil) :select (make-ghil-inline))
(system base pmatch))