1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-16 00:30:21 +02:00

update docs, clean up VM vestiges, macro docs, fix (/ a b c)

* doc/ref/api-procedures.texi (Compiled Procedures): Fix for API changes.

* doc/ref/compiler.texi (Compiling to the Virtual Machine): Replace GHIL
  docs with Tree-IL docs. Update the bits about the Scheme compiler to
  talk about Tree-IL and the expander instead of GHIL. Remove
  <glil-argument>. Add placeholder sections for assembly and bytecode.

* doc/ref/vm.texi: Update examples with what currently happens. Reword
  some things. Fix a couple errors.

* libguile/vm-i-system.c (externals): Remove this instruction, it's not
  used.

* module/ice-9/documentation.scm (object-documentation): If the object is
  a macro, try to return documentation on the macro transformer.

* module/language/assembly/disassemble.scm (disassemble-load-program):
  Fix problem in which we skipped the first element of the object vector,
  because of changes to procedure layouts a few months ago.

* module/language/scheme/spec.scm (read-file): Remove read-file
  definition.

* module/language/tree-il.scm: Reorder exports. Remove <lexical>, it was
  a compat shim to something that was never released. Fix `location'.

* module/language/tree-il/primitives.scm (/): Fix expander for more than
  two args to /.

* module/system/base/compile.scm (read-file-in): Remove unused
  definition.

* module/system/base/language.scm (system): Remove language-read-file.

* module/language/ecmascript/spec.scm (ecmascript): Remove read-file
  definition.
This commit is contained in:
Andy Wingo 2009-05-24 13:09:01 +02:00
parent a755136ba8
commit 81fd315299
12 changed files with 317 additions and 455 deletions

View file

@ -162,18 +162,10 @@ appropriate module first, though:
Returns @code{#t} iff @var{obj} is a compiled procedure. Returns @code{#t} iff @var{obj} is a compiled procedure.
@end deffn @end deffn
@deffn {Scheme Procedure} program-bytecode program @deffn {Scheme Procedure} program-objcode program
@deffnx {C Function} scm_program_bytecode (program) @deffnx {C Function} scm_program_objcode (program)
Returns the object code associated with this program, as a Returns the object code associated with this program. @xref{Object
@code{u8vector}. Code}, for more information.
@end deffn
@deffn {Scheme Procedure} program-base program
@deffnx {C Function} scm_program_base (program)
Returns the address in memory corresponding to the start of
@var{program}'s object code, as an integer. This is useful mostly when
you map the value of an instruction pointer from the VM to actual
instructions.
@end deffn @end deffn
@deffn {Scheme Procedure} program-objects program @deffn {Scheme Procedure} program-objects program
@ -184,9 +176,9 @@ vector. @xref{VM Programs}, for more information.
@deffn {Scheme Procedure} program-module program @deffn {Scheme Procedure} program-module program
@deffnx {C Function} scm_program_module (program) @deffnx {C Function} scm_program_module (program)
Returns the module that was current when this program was created. Returns the module that was current when this program was created. Can
Free variables in this program are looked up with respect to this return @code{#f} if the compiler could determine that this information
module. was unnecessary.
@end deffn @end deffn
@deffn {Scheme Procedure} program-external program @deffn {Scheme Procedure} program-external program
@ -250,9 +242,9 @@ REPL. The only tricky bit is that @var{extp} is a boolean, declaring
whether the binding is heap-allocated or not. @xref{VM Concepts}, for whether the binding is heap-allocated or not. @xref{VM Concepts}, for
more information. more information.
Note that bindings information are stored in a program as part of its Note that bindings information is stored in a program as part of its
metadata thunk, so including them in the generated object code does metadata thunk, so including it in the generated object code does not
not impose a runtime performance penalty. impose a runtime performance penalty.
@end deffn @end deffn
@deffn {Scheme Procedure} program-sources program @deffn {Scheme Procedure} program-sources program

View file

@ -22,8 +22,10 @@ know how to compile your .scm file.
@menu @menu
* Compiler Tower:: * Compiler Tower::
* The Scheme Compiler:: * The Scheme Compiler::
* GHIL:: * Tree-IL::
* GLIL:: * GLIL::
* Assembly::
* Bytecode::
* Object Code:: * Object Code::
* Extending the Compiler:: * Extending the Compiler::
@end menu @end menu
@ -52,7 +54,7 @@ They are registered with the @code{define-language} form.
@deffn {Scheme Syntax} define-language @ @deffn {Scheme Syntax} define-language @
name title version reader printer @ name title version reader printer @
[parser=#f] [read-file=#f] [compilers='()] [evaluator=#f] [parser=#f] [compilers='()] [decompilers='()] [evaluator=#f]
Define a language. Define a language.
This syntax defines a @code{#<language>} object, bound to @var{name} This syntax defines a @code{#<language>} object, bound to @var{name}
@ -62,17 +64,15 @@ for Scheme:
@example @example
(define-language scheme (define-language scheme
#:title "Guile Scheme" #:title "Guile Scheme"
#:version "0.5" #:version "0.5"
#:reader read #:reader read
#:read-file read-file #:compilers `((tree-il . ,compile-tree-il)
#:compilers `((,ghil . ,compile-ghil)) (ghil . ,compile-ghil))
#:evaluator (lambda (x module) (primitive-eval x)) #:decompilers `((tree-il . ,decompile-tree-il))
#:printer write) #:evaluator (lambda (x module) (primitive-eval x))
#:printer write)
@end example @end example
In this example, from @code{(language scheme spec)}, @code{read-file}
reads expressions from a port and wraps them in a @code{begin} block.
@end deffn @end deffn
The interesting thing about having languages defined this way is that The interesting thing about having languages defined this way is that
@ -85,12 +85,12 @@ Guile Scheme interpreter 0.5 on Guile 1.9.0
Copyright (C) 2001-2008 Free Software Foundation, Inc. Copyright (C) 2001-2008 Free Software Foundation, Inc.
Enter `,help' for help. Enter `,help' for help.
scheme@@(guile-user)> ,language ghil scheme@@(guile-user)> ,language tree-il
Guile High Intermediate Language (GHIL) interpreter 0.3 on Guile 1.9.0 Tree Intermediate Language interpreter 1.0 on Guile 1.9.0
Copyright (C) 2001-2008 Free Software Foundation, Inc. Copyright (C) 2001-2008 Free Software Foundation, Inc.
Enter `,help' for help. Enter `,help' for help.
ghil@@(guile-user)> tree-il@@(guile-user)>
@end example @end example
Languages can be looked up by name, as they were above. Languages can be looked up by name, as they were above.
@ -128,8 +128,10 @@ The normal tower of languages when compiling Scheme goes like this:
@itemize @itemize
@item Scheme, which we know and love @item Scheme, which we know and love
@item Guile High Intermediate Language (GHIL) @item Tree Intermediate Language (Tree-IL)
@item Guile Low Intermediate Language (GLIL) @item Guile Low Intermediate Language (GLIL)
@item Assembly
@item Bytecode
@item Object code @item Object code
@end itemize @end itemize
@ -137,8 +139,14 @@ Object code may be serialized to disk directly, though it has a cookie
and version prepended to the front. But when compiling Scheme at and version prepended to the front. But when compiling Scheme at
run time, you want a Scheme value, e.g. a compiled procedure. For this run time, you want a Scheme value, e.g. a compiled procedure. For this
reason, so as not to break the abstraction, Guile defines a fake reason, so as not to break the abstraction, Guile defines a fake
language, @code{value}. Compiling to @code{value} loads the object language at the bottom of the tower:
code into a procedure, and wakes the sleeping giant.
@itemize
@item Value
@end itemize
Compiling to @code{value} loads the object code into a procedure, and
wakes the sleeping giant.
Perhaps this strangeness can be explained by example: Perhaps this strangeness can be explained by example:
@code{compile-file} defaults to compiling to object code, because it @code{compile-file} defaults to compiling to object code, because it
@ -156,340 +164,254 @@ different worlds indefinitely, as shown by the following quine:
@node The Scheme Compiler @node The Scheme Compiler
@subsection The Scheme Compiler @subsection The Scheme Compiler
The job of the Scheme compiler is to expand all macros and to resolve The job of the Scheme compiler is to expand all macros and all of
all symbols to lexical variables. Its target language, GHIL, is fairly Scheme to its most primitive expressions. The definition of
close to Scheme itself, so this process is not very complicated. ``primitive'' is given by the inventory of constructs provided by
Tree-IL, the target language of the Scheme compiler: procedure
applications, conditionals, lexical references, etc. This is described
more fully in the next section.
The Scheme compiler is driven by a table of @dfn{translators}, The tricky and amusing thing about the Scheme-to-Tree-IL compiler is
declared with the @code{define-scheme-translator} form, defined in the that it is completely implemented by the macro expander. Since the
module, @code{(language scheme compile-ghil)}. macro expander has to run over all of the source code already in order
to expand macros, it might as well do the analysis at the same time,
producing Tree-IL expressions directly.
@deffn {Scheme Syntax} define-scheme-translator head clause1 clause2... Because this compiler is actually the macro expander, it is
The best documentation of this form is probably an example. Here is extensible. Any macro which the user writes becomes part of the
the translator for @code{if}: compiler.
@example The Scheme-to-Tree-IL expander may be invoked using the generic
(define-scheme-translator if @code{compile} procedure:
;; (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
The match syntax is from the @code{pmatch} macro, defined in @lisp
@code{(system base pmatch)}. The result of a clause should be a valid (compile '(+ 1 2) #:from 'scheme #:to 'tree-il)
GHIL value. If no clause matches, a syntax error is signalled. @result{}
#<<application> src: #f
proc: #<<toplevel-ref> src: #f name: +>
args: (#<<const> src: #f exp: 1>
#<<const> src: #f exp: 2>)>
@end lisp
In the body of the clauses, the following bindings are introduced: Or, since Tree-IL is so close to Scheme, it is often useful to expand
@itemize Scheme to Tree-IL, then translate back to Scheme. For that reason the
@item @code{e}, the current environment expander provides two interfaces. The former is equivalent to calling
@item @code{l}, the current source location (or @code{#f}) @code{(sc-expand '(+ 1 2) 'c)}, where the @code{'c} is for
@item @code{retrans}, a procedure that may be called to compile ``compile''. With @code{'e} (the default), the result is translated
subexpressions back to Scheme:
@end itemize
Note that translators are looked up by @emph{value}, not by name. That @lisp
is to say, the translator is keyed under the @emph{value} of (sc-expand '(+ 1 2))
@code{if}, which normally prints as @code{#<primitive-builtin-macro! @result{} (+ 1 2)
if>}. (sc-expand '(let ((x 10)) (* x x)))
@end deffn @result{} (let ((x84 10)) (* x84 x84))
@end lisp
Users can extend the compiler by defining new translators. The second example shows that as part of its job, the macro expander
Additionally, some forms can be inlined directly to renames lexically-bound variables. The original names are preserved
instructions -- @xref{Inlined Scheme Instructions}, for a list. The when compiling to Tree-IL, but can't be represented in Scheme: a
actual inliners are defined in @code{(language scheme inline)}: lexical binding only has one name. It is for this reason that the
@emph{native} output of the expander is @emph{not} Scheme. There's too
much information we would lose if we translated to Scheme directly:
lexical variable names, source locations, and module hygiene.
@deffn {Scheme Syntax} define-inline head arity1 result1 arity2 result2... Note however that @code{sc-expand} does not have the same signature as
Defines an inliner for @code{head}. As in @code{compile-tree-il}. @code{compile-tree-il} is a small wrapper
@code{define-scheme-translator}, inliners are keyed by value and not around @code{sc-expand}, to make it conform to the general form of
by name. compiler procedures in Guile's language tower.
Expressions are matched on their arities. For example: Compiler procedures take two arguments, an expression and an
environment. They return three values: the compiled expression, the
corresponding environment for the target language, and a
``continuation environment''. The compiled expression and environment
will serve as input to the next language's compiler. The
``continuation environment'' can be used to compile another expression
from the same source language within the same module.
@example For example, you might compile the expression, @code{(define-module
(define-inline eq? (foo))}. This will result in a Tree-IL expression and environment. But
(x y) (eq? x y)) if you compiled a second expression, you would want to take into
@end example account the compile-time effect of compiling the previous expression,
which puts the user in the @code{(foo)} module. That is purpose of the
``continuation environment''; you would pass it as the environment
when compiling the subsequent expression.
This inlines calls to the Scheme procedure, @code{eq?}, to the For Scheme, an environment may be one of two things:
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 @itemize
@item @code{#f}, in which case compilation is performed in the context @item @code{#f}, in which case compilation is performed in the context
of the current module; of the current module; or
@item a module, which specifies the context of the compilation; or @item a module, which specifies the context of the compilation.
@item a @dfn{compile environment}, which specifies lexical variables
as well.
@end itemize @end itemize
The format of a compile environment for scheme is @code{(@var{module} @node Tree-IL
@var{lexicals} . @var{externals})}, though users are strongly @subsection Tree-IL
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 Tree Intermediate Language (Tree-IL) is a structured intermediate
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
Guile High Intermediate Language (GHIL) is a structured intermediate
language that is close in expressive power to Scheme. It is an language that is close in expressive power to Scheme. It is an
expanded, pre-analyzed Scheme. expanded, pre-analyzed Scheme.
GHIL is ``structured'' in the sense that its representation is based Tree-IL is ``structured'' in the sense that its representation is
on records, not S-expressions. This gives a rigidity to the language based on records, not S-expressions. This gives a rigidity to the
that ensures that compiling to a lower-level language only requires a language that ensures that compiling to a lower-level language only
limited set of transformations. Practically speaking, consider the requires a limited set of transformations. Practically speaking,
GHIL type, @code{<ghil-quote>}, which has fields named @code{env}, consider the Tree-IL type, @code{<const>}, which has two fields,
@code{loc}, and @code{exp}. Instances of this type are records created @code{src} and @code{exp}. Instances of this type are records created
via @code{make-ghil-quote}, and whose fields are accessed as via @code{make-const}, and whose fields are accessed as
@code{ghil-quote-env}, @code{ghil-quote-loc}, and @code{const-src}, and @code{const-exp}. There is also a predicate,
@code{ghil-quote-exp}. There is also a predicate, @code{ghil-quote?}. @code{const?}. @xref{Records}, for more information on records.
@xref{Records}, for more information on records.
Expressions of GHIL name their environments explicitly, and all @c alpha renaming
variables are referenced by identity in addition to by name.
@code{(language ghil)} defines a number of routines to deal explicitly
with variables and environments:
@deftp {Scheme Variable} <ghil-toplevel-env> [table='()] All Tree-IL types have a @code{src} slot, which holds source location
A toplevel environment. The @var{table} holds all toplevel variables information for the expression. This information, if present, will be
that have been resolved in this environment. residualized into the compiled object code, allowing backtraces to
@end deftp show source information. The format of @code{src} is the same as that
@deftp {Scheme Variable} <ghil-env> parent [table='()] [variables='()] returned by Guile's @code{source-properties} function. @xref{Source
A lexical environment. @var{parent} will be the enclosing lexical Properties}, for more information.
environment, or a toplevel environment. @var{table} holds an alist
mapping symbols to variables bound in this environment, while
@var{variables} holds a cumulative list of all variables ever defined
in this environment.
Lexical environments correspond to procedures. Bindings introduced Although Tree-IL objects are represented internally using records,
e.g. by Scheme's @code{let} add to the bindings in a lexical there is also an equivalent S-expression external representation for
environment. An example of a case in which a variable might be in each kind of Tree-IL. For example, an the S-expression representation
@var{variables} but not in @var{table} would be a variable that is in of @code{#<const src: #f exp: 3>} expression would be:
the same procedure, but is out of scope.
@end deftp
@deftp {Scheme Variable} <ghil-var> env name kind [index=#f]
A variable. @var{kind} is one of @code{argument}, @code{local},
@code{external}, @code{toplevel}, @code{public}, or @code{private};
see the procedures below for more information. @var{index} is used in
compilation.
@end deftp
@deffn {Scheme Procedure} ghil-var-is-bound? env sym
Recursively look up a variable named @var{sym} in @var{env}, and
return it or @code{#f} if none is found.
@end deffn
@deffn {Scheme Procedure} ghil-var-for-ref! env sym
Recursively look up a variable named @var{sym} in @var{env}, and
return it. If the symbol was not bound, return a new toplevel
variable.
@end deffn
@deffn {Scheme Procedure} ghil-var-for-set! env sym
Like @code{ghil-var-for-ref!}, except that the returned variable will
be marked as @code{external}. @xref{Variables and the VM}.
@end deffn
@deffn {Scheme Procedure} ghil-var-define! toplevel-env sym
Return an existing or new toplevel variable named @var{sym}.
@var{toplevel-env} must be a toplevel environment.
@end deffn
@deffn {Scheme Procedure} ghil-var-at-module! env modname sym interface?
Return a variable that will be resolved at run-time with respect to a
specific module named @var{modname}. If @var{interface?} is true, the
variable will be of type @code{public}, otherwise @code{private}.
@end deffn
@deffn {Scheme Procedure} call-with-ghil-environment env syms func
Bind @var{syms} to fresh variables within a new lexical environment
whose parent is @var{env}, and call @var{func} as @code{(@var{func}
@var{new-env} @var{new-vars})}.
@end deffn
@deffn {Scheme Procedure} call-with-ghil-bindings env syms func
Like @code{call-with-ghil-environment}, except the existing
environment @var{env} is re-used. For that reason, @var{func} is
invoked as @code{(@var{func} @var{new-vars})}
@end deffn
In the aforementioned @code{<ghil-quote>} type, the @var{env} slot
holds a pointer to the environment in which the expression occurs. The
@var{loc} slot holds source location information, so that errors
corresponding to this expression can be mapped back to the initial
expression in the higher-level language, e.g. Scheme. @xref{Compiled
Procedures}, for more information on source location objects.
GHIL also has a declarative serialization format, which makes writing
and reading it a tractable problem for the human mind. Since all GHIL
language constructs contain @code{env} and @code{loc} pointers, they
are left out of the serialization. (Serializing @code{env} structures
would be difficult, as they are often circular.) What is left is the
type of expression, and the remaining slots defined in the expression
type.
For example, an S-expression representation of the @code{<ghil-quote>}
expression would be:
@example @example
(quote 3) (const 3)
@end example @end example
It's deceptively like Scheme. The general rule is, for a type defined Users may program with this format directly at the REPL:
as @code{<ghil-@var{foo}> env loc @var{slot1} @var{slot2}...}, the
S-expression representation will be @code{(@var{foo} @var{slot1}
@var{slot2}...)}. Users may program with this format directly at the
REPL:
@example @example
scheme@@(guile-user)> ,language ghil scheme@@(guile-user)> ,language tree-il
Guile High Intermediate Language (GHIL) interpreter 0.3 on Guile 1.9.0 Tree Intermediate Language interpreter 1.0 on Guile 1.9.0
Copyright (C) 2001-2008 Free Software Foundation, Inc. Copyright (C) 2001-2008 Free Software Foundation, Inc.
Enter `,help' for help. Enter `,help' for help.
ghil@@(guile-user)> (call (ref +) (quote 32) (quote 10)) tree-il@@(guile-user)> (apply (primitive +) (const 32) (const 10))
@result{} 42 @result{} 42
@end example @end example
For convenience, some slots are serialized as rest arguments; those The @code{src} fields are left out of the external representation.
are noted below. The other caveat is that variables are serialized as
their names only, and not their identities.
@deftp {Scheme Variable} <ghil-void> env loc @deftp {Scheme Variable} <void> src
The unspecified value. @deftpx {External Representation} (void)
An empty expression. In practice, equivalent to Scheme's @code{(if #f
#f)}.
@end deftp @end deftp
@deftp {Scheme Variable} <ghil-quote> env loc exp @deftp {Scheme Variable} <const> src exp
A quoted expression. @deftpx {External Representation} (const @var{exp})
A constant.
@end deftp
@deftp {Scheme Variable} <primitive-ref> src name
@deftpx {External Representation} (primitive @var{name})
A reference to a ``primitive''. A primitive is a procedure that, when
compiled, may be open-coded. For example, @code{cons} is usually
recognized as a primitive, so that it compiles down to a single
instruction.
Note that unlike in Scheme, there are no self-quoting expressions; all Compilation of Tree-IL usually begins with a pass that resolves some
constants must come from @code{quote} expressions. @code{<module-ref>} and @code{<toplevel-ref>} expressions to
@code{<primitive-ref>} expressions. The actual compilation pass
has special cases for applications of certain primitives, like
@code{apply} or @code{cons}.
@end deftp @end deftp
@deftp {Scheme Variable} <ghil-quasiquote> env loc exp @deftp {Scheme Variable} <lexical-ref> src name gensym
A quasiquoted expression. The expression is treated as a constant, @deftpx {External Representation} (lexical @var{name} @var{gensym})
except for embedded @code{unquote} and @code{unquote-splicing} forms. A reference to a lexically-bound variable. The @var{name} is the
original name of the variable in the source program. @var{gensym} is a
unique identifier for this variable.
@end deftp @end deftp
@deftp {Scheme Variable} <ghil-unquote> env loc exp @deftp {Scheme Variable} <lexical-set> src name gensym exp
Like Scheme's @code{unquote}; only valid within a quasiquote. @deftpx {External Representation} (set! (lexical @var{name} @var{gensym}) @var{exp})
Sets a lexically-bound variable.
@end deftp @end deftp
@deftp {Scheme Variable} <ghil-unquote-splicing> env loc exp @deftp {Scheme Variable} <module-ref> src mod name public?
Like Scheme's @code{unquote-splicing}; only valid within a quasiquote. @deftpx {External Representation} (@@ @var{mod} @var{name})
@deftpx {External Representation} (@@@@ @var{mod} @var{name})
A reference to a variable in a specific module. @var{mod} should be
the name of the module, e.g. @code{(guile-user)}.
If @var{public?} is true, the variable named @var{name} will be looked
up in @var{mod}'s public interface, and serialized with @code{@@};
otherwise it will be looked up among the module's private bindings,
and is serialized with @code{@@@@}.
@end deftp @end deftp
@deftp {Scheme Variable} <ghil-ref> env loc var @deftp {Scheme Variable} <module-set> src mod name public? exp
A variable reference. Note that for purposes of serialization, @deftpx {External Representation} (set! (@@ @var{mod} @var{name}) @var{exp})
@var{var} is serialized as its name, as a symbol. @deftpx {External Representation} (set! (@@@@ @var{mod} @var{name}) @var{exp})
Sets a variable in a specific module.
@end deftp @end deftp
@deftp {Scheme Variable} <ghil-set> env loc var val @deftp {Scheme Variable} <toplevel-ref> src name
A variable mutation. @var{var} is serialized as a symbol. @deftpx {External Representation} (toplevel @var{name})
References a variable from the current procedure's module.
@end deftp @end deftp
@deftp {Scheme Variable} <ghil-define> env loc var val @deftp {Scheme Variable} <toplevel-set> src name exp
A toplevel variable definition. See @code{ghil-var-define!}. @deftpx {External Representation} (set! (toplevel @var{name}) @var{exp})
Sets a variable in the current procedure's module.
@end deftp @end deftp
@deftp {Scheme Variable} <ghil-if> env loc test then else @deftp {Scheme Variable} <toplevel-define> src name exp
@deftpx {External Representation} (define (toplevel @var{name}) @var{exp})
Defines a new top-level variable in the current procedure's module.
@end deftp
@deftp {Scheme Variable} <conditional> src test then else
@deftpx {External Representation} (if @var{test} @var{then} @var{else})
A conditional. Note that @var{else} is not optional. A conditional. Note that @var{else} is not optional.
@end deftp @end deftp
@deftp {Scheme Variable} <ghil-and> env loc . exps @deftp {Scheme Variable} <application> src proc args
Like Scheme's @code{and}. @deftpx {External Representation} (apply @var{proc} . @var{args})
@end deftp
@deftp {Scheme Variable} <ghil-or> env loc . exps
Like Scheme's @code{or}.
@end deftp
@deftp {Scheme Variable} <ghil-begin> env loc . body
Like Scheme's @code{begin}.
@end deftp
@deftp {Scheme Variable} <ghil-bind> env loc vars exprs . body
Like a deconstructed @code{let}: each element of @var{vars} will be
bound to the corresponding GHIL expression in @var{exprs}.
Note that for purposes of the serialization format, @var{exprs} are
evaluated before the new bindings are added to the environment. For
@code{letrec} semantics, there also exists a @code{bindrec} parse
flavor. This is useful for writing GHIL at the REPL, but the
serializer does not currently have the cleverness needed to determine
whether a @code{<ghil-bind>} has @code{let} or @code{letrec}
semantics, and thus only serializes @code{<ghil-bind>} as @code{bind}.
@end deftp
@deftp {Scheme Variable} <ghil-mv-bind> env loc vars 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{vars} and @var{rest}.
@end deftp
@deftp {Scheme Variable} <ghil-lambda> env loc vars rest meta . body
A closure. @var{vars} is the argument list, serialized 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 deftp
@deftp {Scheme Variable} <ghil-call> env loc proc . args
A procedure call. A procedure call.
@end deftp @end deftp
@deftp {Scheme Variable} <ghil-mv-call> env loc producer consumer @deftp {Scheme Variable} <sequence> src exps
Like Scheme's @code{call-with-values}. @deftpx {External Representation} (begin . @var{exps})
Like Scheme's @code{begin}.
@end deftp @end deftp
@deftp {Scheme Variable} <ghil-inline> env loc op . args @deftp {Scheme Variable} <lambda> src names vars meta body
An inlined VM instruction. @var{op} should be the instruction name as @deftpx {External Representation} (lambda @var{names} @var{vars} @var{meta} @var{body})
a symbol, and @var{args} should be its arguments, as GHIL expressions. A closure. @var{names} is original binding form, as given in the
source code, which may be an improper list. @var{vars} are gensyms
corresponding to the @var{names}. @var{meta} is an association list of
properties. The actual @var{body} is a single Tree-IL expression.
@end deftp @end deftp
@deftp {Scheme Variable} <ghil-values> env loc . values @deftp {Scheme Variable} <let> src names vars vals exp
Like Scheme's @code{values}. @deftpx {External Representation} (let @var{names} @var{vars} @var{vals} @var{exp})
Lexical binding, like Scheme's @code{let}. @var{names} are the
original binding names, @var{vars} are gensyms corresponding to the
@var{names}, and @var{vals} are Tree-IL expressions for the values.
@var{exp} is a single Tree-IL expression.
@end deftp @end deftp
@deftp {Scheme Variable} <ghil-values*> env loc . values @deftp {Scheme Variable} <letrec> src names vars vals exp
@var{values} are as in the Scheme expression, @code{(apply values . @deftpx {External Representation} (letrec @var{names} @var{vars} @var{vals} @var{exp})
@var{vals})}. A version of @code{<let>} that creates recursive bindings, like
@end deftp Scheme's @code{letrec}.
@deftp {Scheme Variable} <ghil-reified-env> env loc
Produces, at run-time, a reification of the environment at compile
time. Used in the implementation of Scheme's
@code{compile-time-environment}.
@end deftp @end deftp
GHIL implements a compiler to GLIL that recursively traverses GHIL @c FIXME -- need to revive this one
expressions, writing out GLIL expressions into a linear list. The @c @deftp {Scheme Variable} <ghil-mv-bind> src vars rest producer . body
compiler also keeps some state as to whether the current expression is @c Like Scheme's @code{receive} -- binds the values returned by
in tail context, and whether its value will be used in future @c applying @code{producer}, which should be a thunk, to the
computations. This state allows the compiler not to emit code for @c @code{lambda}-like bindings described by @var{vars} and @var{rest}.
constant expressions that will not be used (e.g. docstrings), and to @c @end deftp
perform tail calls when in tail position.
Just as the Scheme to GHIL compiler introduced new hidden state---the Tree-IL implements a compiler to GLIL that recursively traverses
environment---the GHIL to GLIL compiler introduces more state, the Tree-IL expressions, writing out GLIL expressions into a linear list.
stack. While not represented explicitly, the stack is present in the The compiler also keeps some state as to whether the current
compilation of each GHIL expression: compiling a GHIL expression expression is in tail context, and whether its value will be used in
should leave the run-time value stack in the same state. For example, future computations. This state allows the compiler not to emit code
if the intermediate value stack has two elements before evaluating an for constant expressions that will not be used (e.g. docstrings), and
@code{if} expression, it should have two elements after that to perform tail calls when in tail position.
expression.
In the future, there will be a pass at the beginning of the
Tree-IL->GLIL compilation step to perform inlining, copy propagation,
dead code elimination, and constant folding.
Interested readers are encouraged to read the implementation in Interested readers are encouraged to read the implementation in
@code{(language ghil compile-glil)} for more details. @code{(language tree-il compile-glil)} for more details.
@node GLIL @node GLIL
@subsection GLIL @subsection GLIL
Guile Low Intermediate Language (GLIL) is a structured intermediate Guile Low Intermediate Language (GLIL) is a structured intermediate
language whose expressions closely mirror the functionality of Guile's language whose expressions more closely approximate Guile's VM
VM instruction set. instruction set.
Its expression types are defined in @code{(language glil)}, and as Its expression types are defined in @code{(language glil)}, and as
with GHIL, some of its fields parse as rest arguments. with GHIL, some of its fields parse as rest arguments.
@ -544,14 +466,11 @@ Pushes a constant value onto the stack. @var{obj} must be a number,
string, symbol, keyword, boolean, character, or a pair or vector or string, symbol, keyword, boolean, character, or a pair or vector or
list thereof, or the empty list. list thereof, or the empty list.
@end deftp @end deftp
@deftp {Scheme Variable} <glil-argument> op index
Accesses an argument on the stack. If @var{op} is @code{ref}, the
argument is pushed onto the stack; if it is @code{set}, the argument
is set from the top value on the stack, which is popped off.
@end deftp
@deftp {Scheme Variable} <glil-local> op index @deftp {Scheme Variable} <glil-local> op index
Like @code{<glil-argument>}, but for local variables. @xref{Stack Accesses a lexically variable from the stack. If @var{op} is
Layout}, for more information. @code{ref}, the value is pushed onto the stack; if it is @code{set},
the variable is set from the top value on the stack, which is popped
off. @xref{Stack Layout}, for more information.
@end deftp @end deftp
@deftp {Scheme Variable} <glil-external> op depth index @deftp {Scheme Variable} <glil-external> op depth index
Accesses a heap-allocated variable, addressed by @var{depth}, the nth Accesses a heap-allocated variable, addressed by @var{depth}, the nth
@ -607,6 +526,12 @@ Just as in all of Guile's compilers, an environment is passed to the
GLIL-to-object code compiler, and one is returned as well, along with GLIL-to-object code compiler, and one is returned as well, along with
the object code. the object code.
@node Assembly
@subsection Assembly
@node Bytecode
@subsection Bytecode
@node Object Code @node Object Code
@subsection Object Code @subsection Object Code

View file

@ -111,7 +111,7 @@ The registers that a VM has are as follows:
In other architectures, the instruction pointer is sometimes called In other architectures, the instruction pointer is sometimes called
the ``program counter'' (pc). This set of registers is pretty typical the ``program counter'' (pc). This set of registers is pretty typical
for stack machines; their exact meanings in the context of Guile's VM for stack machines; their exact meanings in the context of Guile's VM
is described in the next section. are described in the next section.
A virtual machine executes by loading a compiled procedure, and A virtual machine executes by loading a compiled procedure, and
executing the object code associated with that procedure. Of course, executing the object code associated with that procedure. Of course,
@ -119,14 +119,17 @@ that procedure may call other procedures, tail-call others, ad
infinitum---indeed, within a guile whose modules have all been infinitum---indeed, within a guile whose modules have all been
compiled to object code, one might never leave the virtual machine. compiled to object code, one might never leave the virtual machine.
@c wingo: I wish the following were true, but currently we just use @c wingo: The following is true, but I don't know in what context to
@c the one engine. This kind of thing is possible tho. @c describe it. A documentation FIXME.
@c A VM may have one of three engines: reckless, regular, or debugging. @c A VM may have one of three engines: reckless, regular, or debugging.
@c Reckless engine is fastest but dangerous. Regular engine is normally @c Reckless engine is fastest but dangerous. Regular engine is normally
@c fail-safe and reasonably fast. Debugging engine is safest and @c fail-safe and reasonably fast. Debugging engine is safest and
@c functional but very slow. @c functional but very slow.
@c (Actually we have just a regular and a debugging engine; normally
@c we use the latter, it's almost as fast as the ``regular'' engine.)
@node Stack Layout @node Stack Layout
@subsection Stack Layout @subsection Stack Layout
@ -174,7 +177,7 @@ The structure of the fixed part of an application frame is as follows:
In the above drawing, the stack grows upward. The intermediate values In the above drawing, the stack grows upward. The intermediate values
stored in the application of this frame are stored above stored in the application of this frame are stored above
@code{SCM_FRAME_UPPER_ADDRESS (fp)}. @code{bp} refers to the @code{SCM_FRAME_UPPER_ADDRESS (fp)}. @code{bp} refers to the
@code{struct scm_program*} data associated with the program at @code{struct scm_objcode} data associated with the program at
@code{fp - 1}. @code{nargs} and @code{nlocs} are properties of the @code{fp - 1}. @code{nargs} and @code{nlocs} are properties of the
compiled procedure, which will be discussed later. compiled procedure, which will be discussed later.
@ -226,7 +229,7 @@ programs are implemented, @xref{VM Programs}.
@node Variables and the VM @node Variables and the VM
@subsection Variables and the VM @subsection Variables and the VM
Let's think about the following Scheme code as an example: Consider the following Scheme code as an example:
@example @example
(define (foo a) (define (foo a)
@ -236,22 +239,15 @@ Let's think about the following Scheme code as an example:
Within the lambda expression, "foo" is a top-level variable, "a" is a Within the lambda expression, "foo" is a top-level variable, "a" is a
lexically captured variable, and "b" is a local variable. lexically captured variable, and "b" is a local variable.
That is to say: @code{b} may safely be allocated on the stack, as @code{b} may safely be allocated on the stack, as there is no enclosed
there is no enclosed procedure that references it, nor is it ever procedure that references it, nor is it ever mutated.
mutated.
@code{a}, on the other hand, is referenced by an enclosed procedure, @code{a}, on the other hand, is referenced by an enclosed procedure,
that of the lambda. Thus it must be allocated on the heap, as it may that of the lambda. Thus it must be allocated on the heap, as it may
(and will) outlive the dynamic extent of the invocation of @code{foo}. (and will) outlive the dynamic extent of the invocation of @code{foo}.
@code{foo} is a toplevel variable, as mandated by Scheme's semantics: @code{foo} is a top-level variable, because it names the procedure
@code{foo}, which is here defined at the top-level.
@example
(define proc (foo 'bar)) ; assuming prev. definition of @code{foo}
(define foo 42) ; redefinition
(proc 'baz)
@result{} (42 bar baz)
@end example
Note that variables that are mutated (via @code{set!}) must be Note that variables that are mutated (via @code{set!}) must be
allocated on the heap, even if they are local variables. This is allocated on the heap, even if they are local variables. This is
@ -276,6 +272,7 @@ You can pick apart these pieces with the accessors in @code{(system vm
program)}. @xref{Compiled Procedures}, for a full API reference. program)}. @xref{Compiled Procedures}, for a full API reference.
@cindex object table @cindex object table
@cindex object array
The object array of a compiled procedure, also known as the The object array of a compiled procedure, also known as the
@dfn{object table}, holds all Scheme objects whose values are known @dfn{object table}, holds all Scheme objects whose values are known
not to change across invocations of the procedure: constant strings, not to change across invocations of the procedure: constant strings,
@ -293,31 +290,27 @@ instruction, which uses the object vector, and are almost as fast as
local variable references. local variable references.
We can see how these concepts tie together by disassembling the We can see how these concepts tie together by disassembling the
@code{foo} function to see what is going on: @code{foo} function we defined earlier to see what is going on:
@smallexample @smallexample
scheme@@(guile-user)> (define (foo a) (lambda (b) (list foo a b))) scheme@@(guile-user)> (define (foo a) (lambda (b) (list foo a b)))
scheme@@(guile-user)> ,x foo scheme@@(guile-user)> ,x foo
Disassembly of #<program foo (a)>: Disassembly of #<program foo (a)>:
Bytecode:
0 (local-ref 0) ;; `a' (arg) 0 (local-ref 0) ;; `a' (arg)
2 (external-set 0) ;; `a' (arg) 2 (external-set 0) ;; `a' (arg)
4 (object-ref 0) ;; #<program #(0 28 #f) (b)> 4 (object-ref 1) ;; #<program b70d2910 at <unknown port>:0:16 (b)>
6 (make-closure) at (unknown file):0:16 6 (make-closure)
7 (return) 7 (return)
---------------------------------------- ----------------------------------------
Disassembly of #<program #(0 28 #f) (b)>: Disassembly of #<program b70d2910 at <unknown port>:0:16 (b)>:
Bytecode: 0 (toplevel-ref 1) ;; `foo'
2 (external-ref 0) ;; (closure variable)
0 (toplevel-ref 0) ;; `list' 4 (local-ref 0) ;; `b' (arg)
2 (toplevel-ref 1) ;; `foo' 6 (list 0 3) ;; 3 elements at (unknown file):0:28
4 (external-ref 0) ;; (closure variable) 9 (return)
6 (local-ref 0) ;; `b' (arg)
8 (goto/args 3) at (unknown file):0:28
@end smallexample @end smallexample
At @code{ip} 0 and 2, we do the copy from argument to heap for At @code{ip} 0 and 2, we do the copy from argument to heap for
@ -336,8 +329,9 @@ Control Instructions}, for more details.
Then we see a reference to an external variable, corresponding to Then we see a reference to an external variable, corresponding to
@code{a}. The disassembler doesn't have enough information to give a @code{a}. The disassembler doesn't have enough information to give a
name to that variable, so it just marks it as being a ``closure name to that variable, so it just marks it as being a ``closure
variable''. Finally we see the reference to @code{b}, then a tail call variable''. Finally we see the reference to @code{b}, then the
(@code{goto/args}) with three arguments. @code{list} opcode, an inline implementation of the @code{list} scheme
routine.
@node Instruction Set @node Instruction Set
@subsection Instruction Set @subsection Instruction Set
@ -365,7 +359,8 @@ their own test-and-branch instructions:
@end example @end example
In addition, some Scheme primitives have their own inline In addition, some Scheme primitives have their own inline
implementations, e.g. @code{cons}. implementations, e.g. @code{cons}, and @code{list}, as we saw in the
previous section.
So Guile's instruction set is a @emph{complete} instruction set, in So Guile's instruction set is a @emph{complete} instruction set, in
that it provides the instructions that are suited to the problem, and that it provides the instructions that are suited to the problem, and
@ -421,12 +416,6 @@ efficient in the future via addressing by frame and index. Currently,
external variables are all consed onto a list, which results in O(N) external variables are all consed onto a list, which results in O(N)
lookup time. 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}. @xref{The Scheme Compiler}.
@end deffn
@deffn Instruction toplevel-ref index @deffn Instruction toplevel-ref index
Push the value of the toplevel binding whose location is stored in at Push the value of the toplevel binding whose location is stored in at
position @var{index} in the object table. position @var{index} in the object table.
@ -440,11 +429,11 @@ created.
Alternately, the lookup may be performed relative to a particular Alternately, the lookup may be performed relative to a particular
module, determined at compile-time (e.g. via @code{@@} or module, determined at compile-time (e.g. via @code{@@} or
@code{@@@@}). In that case, the cell in the object table holds a list: @code{@@@@}). In that case, the cell in the object table holds a list:
@code{(@var{modname} @var{sym} @var{interface?})}. The symbol @code{(@var{modname} @var{sym} @var{public?})}. The symbol @var{sym}
@var{sym} will be looked up in the module named @var{modname} (a list will be looked up in the module named @var{modname} (a list of
of symbols). The lookup will be performed against the module's public symbols). The lookup will be performed against the module's public
interface, unless @var{interface?} is @code{#f}, which it is for interface, unless @var{public?} is @code{#f}, which it is for example
example when compiling @code{@@@@}. when compiling @code{@@@@}.
In any case, if the symbol is unbound, an error is signalled. In any case, if the symbol is unbound, an error is signalled.
Otherwise the initial form is replaced with the looked-up variable, an Otherwise the initial form is replaced with the looked-up variable, an
@ -550,8 +539,9 @@ may be encoded in 1, 2, or 4 bytes.
@deffn Instruction load-integer length @deffn Instruction load-integer length
@deffnx Instruction load-unsigned-integer length @deffnx Instruction load-unsigned-integer length
Load a 32-bit integer (respectively unsigned integer) from the Load a 32-bit integer or unsigned integer from the instruction stream.
instruction stream. The bytes of the integer are read in order of decreasing significance
(i.e., big-endian).
@end deffn @end deffn
@deffn Instruction load-number length @deffn Instruction load-number length
Load an arbitrary number from the instruction stream. The number is Load an arbitrary number from the instruction stream. The number is
@ -573,43 +563,23 @@ the current toplevel environment, creating the binding if necessary.
Push the variable corresponding to the binding. Push the variable corresponding to the binding.
@end deffn @end deffn
@deffn Instruction load-program length @deffn Instruction load-program
Load bytecode from the instruction stream, and push a compiled Load bytecode from the instruction stream, and push a compiled
procedure. This instruction pops the following values from the stack: procedure.
@itemize This instruction pops one value from the stack: the program's object
@item Optionally, a thunk, which when called should return metadata table, as a vector, or @code{#f} in the case that the program has no
associated with this program---for example its name, the names of its object table. A program that does not reference toplevel bindings and
arguments, its documentation string, debugging information, etc. does not use @code{object-ref} does not need an object table.
Normally, this thunk its itself a compiled procedure (with no This instruction is unlike the rest of the loading instructions,
metadata). Metadata is represented this way so that the initial load because instead of parsing its data, it directly maps the instruction
of a procedure is fast: the VM just mmap's the thunk and goes. The stream onto a C structure, @code{struct scm_objcode}. @xref{Object
symbols and pairs associated with the metadata are only created if the Code}, for more information.
user asks for them.
For information on the format of the thunk's return value,
@xref{Compiled Procedures}.
@item Optionally, the program's object table, as a vector.
A program that does not reference toplevel bindings and does not use
@code{object-ref} does not need an object table.
@item Finally, either one immediate integer or four immediate integers
representing the arity of the program.
In the four-fixnum case, the values are respectively the number of
arguments taken by the function (@var{nargs}), the number of @dfn{rest
arguments} (@var{nrest}, 0 or 1), the number of local variables
(@var{nlocs}) and the number of external variables (@var{nexts})
(@pxref{Environment Control Instructions}).
The common single-fixnum case represents all of these values within a
16-bit bitmask.
@end itemize
The resulting compiled procedure will not have any ``external'' The resulting compiled procedure will not have any ``external''
variables captured, so it will be loaded only once but may be used variables captured, so it may be loaded only once but used many times
many times to create closures. to create closures.
@end deffn @end deffn
Finally, while this instruction is not strictly a ``loading'' Finally, while this instruction is not strictly a ``loading''
@ -620,7 +590,10 @@ here:
Pop the program object from the stack, capture the current set of Pop the program object from the stack, capture the current set of
``external'' variables, and assign those external variables to a copy ``external'' variables, and assign those external variables to a copy
of the program. Push the new program object, which shares state with of the program. Push the new program object, which shares state with
the original program. Also captures the current module. the original program.
At the time of this writing, the space overhead of closures is 4 words
per closure.
@end deffn @end deffn
@node Procedural Instructions @node Procedural Instructions
@ -640,22 +613,24 @@ set to the returned value.
@deffn Instruction call nargs @deffn Instruction call nargs
Call the procedure located at @code{sp[-nargs]} with the @var{nargs} Call the procedure located at @code{sp[-nargs]} with the @var{nargs}
arguments located from @code{sp[0]} to @code{sp[-nargs + 1]}. arguments located from @code{sp[-nargs + 1]} to @code{sp[0]}.
For compiled procedures, this instruction sets up a new stack frame,
as described in @ref{Stack Layout}, and then dispatches to the first
instruction in the called procedure, relying on the called procedure
to return one value to the newly-created continuation. Because the new
frame pointer will point to sp[-nargs + 1], the arguments don't have
to be shuffled around -- they are already in place.
For non-compiled procedures (continuations, primitives, and For non-compiled procedures (continuations, primitives, and
interpreted procedures), @code{call} will pop the procedure and interpreted procedures), @code{call} will pop the procedure and
arguments off the stack, and push the result of calling arguments off the stack, and push the result of calling
@code{scm_apply}. @code{scm_apply}.
For compiled procedures, this instruction sets up a new stack frame,
as described in @ref{Stack Layout}, and then dispatches to the first
instruction in the called procedure, relying on the called procedure
to return one value to the newly-created continuation.
@end deffn @end deffn
@deffn Instruction goto/args nargs @deffn Instruction goto/args nargs
Like @code{call}, but reusing the current continuation. This Like @code{call}, but reusing the current continuation. This
instruction implements tail calling as required by RnRS. instruction implements tail calls as required by RnRS.
For compiled procedures, that means that @code{goto/args} reuses the For compiled procedures, that means that @code{goto/args} reuses the
current frame instead of building a new one. The @code{goto/*} current frame instead of building a new one. The @code{goto/*}
@ -726,14 +701,14 @@ values. This is an optimization for the common @code{(apply values
@deffn Instruction truncate-values nbinds nrest @deffn Instruction truncate-values nbinds nrest
Used in multiple-value continuations, this instruction takes the Used in multiple-value continuations, this instruction takes the
values that are on the stack (including the number-of-value marker) values that are on the stack (including the number-of-values marker)
and truncates them for a binding construct. and truncates them for a binding construct.
For example, a call to @code{(receive (x y . z) (foo) ...)} would, For example, a call to @code{(receive (x y . z) (foo) ...)} would,
logically speaking, pop off the values returned from @code{(foo)} and logically speaking, pop off the values returned from @code{(foo)} and
push them as three values, corresponding to @code{x}, @code{y}, and push them as three values, corresponding to @code{x}, @code{y}, and
@code{z}. In that case, @var{nbinds} would be 3, and @var{nrest} would @code{z}. In that case, @var{nbinds} would be 3, and @var{nrest} would
be 1 (to indicate that one of the bindings was a rest arguments). be 1 (to indicate that one of the bindings was a rest argument).
Signals an error if there is an insufficient number of values. Signals an error if there is an insufficient number of values.
@end deffn @end deffn
@ -779,12 +754,14 @@ Push @var{value}, an 8-bit character, onto the stack.
@deffn Instruction list n @deffn Instruction list n
Pops off the top @var{n} values off of the stack, consing them up into Pops off the top @var{n} values off of the stack, consing them up into
a list, then pushes that list on the stack. What was the topmost value a list, then pushes that list on the stack. What was the topmost value
will be the last element in the list. will be the last element in the list. @var{n} is a two-byte value,
most significant byte first.
@end deffn @end deffn
@deffn Instruction vector n @deffn Instruction vector n
Create and fill a vector with the top @var{n} values from the stack, Create and fill a vector with the top @var{n} values from the stack,
popping off those values and pushing on the resulting vector. popping off those values and pushing on the resulting vector. @var{n}
is a two-byte value, like in @code{vector}.
@end deffn @end deffn
@deffn Instruction mark @deffn Instruction mark
@ -850,9 +827,8 @@ Pushes ``the unspecified value'' onto the stack.
@subsubsection Inlined Scheme Instructions @subsubsection Inlined Scheme Instructions
The Scheme compiler can recognize the application of standard Scheme The Scheme compiler can recognize the application of standard Scheme
procedures, or unbound variables that look like they are bound to procedures. It tries to inline these small operations to avoid the
standard Scheme procedures. It tries to inline these small operations overhead of creating new stack frames.
to avoid the overhead of creating new stack frames.
Since most of these operations are historically implemented as C Since most of these operations are historically implemented as C
primitives, not inlining them would entail constantly calling out from primitives, not inlining them would entail constantly calling out from
@ -876,12 +852,12 @@ stream.
@deffnx Instruction eqv? x y @deffnx Instruction eqv? x y
@deffnx Instruction equal? x y @deffnx Instruction equal? x y
@deffnx Instruction pair? x y @deffnx Instruction pair? x y
@deffnx Instruction list? x y @deffnx Instruction list? x
@deffnx Instruction set-car! pair x @deffnx Instruction set-car! pair x
@deffnx Instruction set-cdr! pair x @deffnx Instruction set-cdr! pair x
@deffnx Instruction slot-ref struct n @deffnx Instruction slot-ref struct n
@deffnx Instruction slot-set struct n x @deffnx Instruction slot-set struct n x
@deffnx Instruction cons x @deffnx Instruction cons x y
@deffnx Instruction car x @deffnx Instruction car x
@deffnx Instruction cdr x @deffnx Instruction cdr x
Inlined implementations of their Scheme equivalents. Inlined implementations of their Scheme equivalents.

View file

@ -410,12 +410,6 @@ VM_DEFINE_INSTRUCTION (29, toplevel_set, "toplevel-set", 1, 1, 0)
NEXT; NEXT;
} }
VM_DEFINE_INSTRUCTION (30, externals, "externals", 0, 0, 1)
{
PUSH (external);
NEXT;
}
/* /*
* branch and jump * branch and jump

View file

@ -198,6 +198,8 @@ OBJECT can be a procedure, macro or any object that has its
(object-property object 'documentation) (object-property object 'documentation)
(and (program? object) (and (program? object)
(program-documentation object)) (program-documentation object))
(and (macro? object)
(object-documentation (macro-transformer object)))
(and (procedure? object) (and (procedure? object)
(not (closure? object)) (not (closure? object))
(procedure-name object) (procedure-name object)

View file

@ -82,7 +82,7 @@
(if (program? x) (if (program? x)
(begin (display "----------------------------------------\n") (begin (display "----------------------------------------\n")
(disassemble x)))) (disassemble x))))
(cddr (vector->list objs)))))) (cdr (vector->list objs))))))
(else (else
(error "bad load-program form" asm)))) (error "bad load-program form" asm))))

View file

@ -33,7 +33,6 @@
#:title "Guile ECMAScript" #:title "Guile ECMAScript"
#:version "3.0" #:version "3.0"
#:reader (lambda () (read-ecmascript/1 (current-input-port))) #:reader (lambda () (read-ecmascript/1 (current-input-port)))
#:read-file read-ecmascript
#:compilers `((ghil . ,compile-ghil)) #:compilers `((ghil . ,compile-ghil))
;; a pretty-printer would be interesting. ;; a pretty-printer would be interesting.
#:printer write #:printer write

View file

@ -32,12 +32,6 @@
(read-enable 'positions) (read-enable 'positions)
(define (read-file port)
(do ((x (read port) (read port))
(l '() (cons x l)))
((eof-object? x)
(cons 'begin (reverse! l)))))
;;; ;;;
;;; Language definition ;;; Language definition
;;; ;;;
@ -46,7 +40,6 @@
#:title "Guile Scheme" #:title "Guile Scheme"
#:version "0.5" #:version "0.5"
#:reader read #:reader read
#:read-file read-file
#:compilers `((tree-il . ,compile-tree-il) #:compilers `((tree-il . ,compile-tree-il)
(ghil . ,compile-ghil)) (ghil . ,compile-ghil))
#:decompilers `((tree-il . ,decompile-tree-il)) #:decompilers `((tree-il . ,decompile-tree-il))

View file

@ -21,12 +21,8 @@
#:use-module (system base syntax) #:use-module (system base syntax)
#:export (tree-il-src #:export (tree-il-src
<lexical> make-lexical
lexical-name lexical-gensym
<void> void? make-void void-src <void> void? make-void void-src
<application> application? make-application application-src application-proc application-args <const> const? make-const const-src const-exp
<conditional> conditional? make-conditional conditional-src conditional-test conditional-then conditional-else
<primitive-ref> primitive-ref? make-primitive-ref primitive-ref-src primitive-ref-name <primitive-ref> primitive-ref? make-primitive-ref primitive-ref-src primitive-ref-name
<lexical-ref> lexical-ref? make-lexical-ref lexical-ref-src lexical-ref-name lexical-ref-gensym <lexical-ref> lexical-ref? make-lexical-ref lexical-ref-src lexical-ref-name lexical-ref-gensym
<lexical-set> lexical-set? make-lexical-set lexical-set-src lexical-set-name lexical-set-gensym lexical-set-exp <lexical-set> lexical-set? make-lexical-set lexical-set-src lexical-set-name lexical-set-gensym lexical-set-exp
@ -35,9 +31,10 @@
<toplevel-ref> toplevel-ref? make-toplevel-ref toplevel-ref-src toplevel-ref-name <toplevel-ref> toplevel-ref? make-toplevel-ref toplevel-ref-src toplevel-ref-name
<toplevel-set> toplevel-set? make-toplevel-set toplevel-set-src toplevel-set-name toplevel-set-exp <toplevel-set> toplevel-set? make-toplevel-set toplevel-set-src toplevel-set-name toplevel-set-exp
<toplevel-define> toplevel-define? make-toplevel-define toplevel-define-src toplevel-define-name toplevel-define-exp <toplevel-define> toplevel-define? make-toplevel-define toplevel-define-src toplevel-define-name toplevel-define-exp
<lambda> lambda? make-lambda lambda-src lambda-names lambda-vars lambda-meta lambda-body <conditional> conditional? make-conditional conditional-src conditional-test conditional-then conditional-else
<const> const? make-const const-src const-exp <application> application? make-application application-src application-proc application-args
<sequence> sequence? make-sequence sequence-src sequence-exps <sequence> sequence? make-sequence sequence-src sequence-exps
<lambda> lambda? make-lambda lambda-src lambda-names lambda-vars lambda-meta lambda-body
<let> let? make-let let-src let-names let-vars let-vals let-exp <let> let? make-let let-src let-names let-vars let-vals let-exp
<letrec> letrec? make-letrec letrec-src letrec-names letrec-vars letrec-vals letrec-exp <letrec> letrec? make-letrec letrec-src letrec-names letrec-vars letrec-vals letrec-exp
@ -50,8 +47,7 @@
(define-type (<tree-il> #:common-slots (src)) (define-type (<tree-il> #:common-slots (src))
(<void>) (<void>)
(<application> proc args) (<const> exp)
(<conditional> test then else)
(<primitive-ref> name) (<primitive-ref> name)
(<lexical-ref> name gensym) (<lexical-ref> name gensym)
(<lexical-set> name gensym exp) (<lexical-set> name gensym exp)
@ -60,28 +56,19 @@
(<toplevel-ref> name) (<toplevel-ref> name)
(<toplevel-set> name exp) (<toplevel-set> name exp)
(<toplevel-define> name exp) (<toplevel-define> name exp)
(<lambda> names vars meta body) (<conditional> test then else)
(<const> exp) (<application> proc args)
(<sequence> exps) (<sequence> exps)
(<lambda> names vars meta body)
(<let> names vars vals exp) (<let> names vars vals exp)
(<letrec> names vars vals exp)) (<letrec> names vars vals exp))
(define <lexical> <lexical-ref>)
(define lexical? lexical-ref?)
(define make-lexical make-lexical-ref)
(define lexical-name lexical-ref-name)
(define lexical-gensym lexical-ref-gensym)
;; FIXME: use this in psyntax
(define (location x) (define (location x)
(and (pair? x) (and (pair? x)
(let ((props (source-properties x))) (let ((props (source-properties x)))
(and (not (null? props)) (and (pair? props) props))))
(vector (assq-ref props 'line)
(assq-ref props 'column)
(assq-ref props 'filename))))))
(define (parse-tree-il exp) (define (parse-tree-il exp)
(let ((loc (location exp)) (let ((loc (location exp))

View file

@ -152,7 +152,7 @@
(define-primitive-expander / (define-primitive-expander /
(x) (/ 1 x) (x) (/ 1 x)
(x y z . rest) (div x (* y z . rest))) (x y z . rest) (/ x (* y z . rest)))
(define-primitive-expander caar (x) (car (car x))) (define-primitive-expander caar (x) (car (car x)))
(define-primitive-expander cadr (x) (car (cdr x))) (define-primitive-expander cadr (x) (car (cdr x)))

View file

@ -135,11 +135,6 @@
;;; Compiler interface ;;; Compiler interface
;;; ;;;
(define (read-file-in file lang)
(call-with-input-file file
(or (language-read-file lang)
(error "language has no #:read-file" lang))))
(define (compile-passes from to opts) (define (compile-passes from to opts)
(map cdr (map cdr
(or (lookup-compilation-order from to) (or (lookup-compilation-order from to)

View file

@ -23,7 +23,7 @@
#:use-module (system base syntax) #:use-module (system base syntax)
#:export (define-language language? lookup-language make-language #:export (define-language language? lookup-language make-language
language-name language-title language-version language-reader language-name language-title language-version language-reader
language-printer language-parser language-read-file language-printer language-parser
language-compilers language-decompilers language-evaluator language-compilers language-decompilers language-evaluator
language-joiner language-joiner
@ -42,7 +42,6 @@
reader reader
printer printer
(parser #f) (parser #f)
(read-file #f)
(compilers '()) (compilers '())
(decompilers '()) (decompilers '())
(evaluator #f) (evaluator #f)