1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-20 19:50:24 +02:00

update compiler.texi

* doc/ref/compiler.texi (Compiler Tower): Update for removal of version
  from <language>, and add joiner and make-default-environment fields.
  Update examples.
  (The Scheme Compiler): Update for `macroexpand' instead of
  `sc-expand', and that the environment must be a module.
  (Tree-IL): Update for new Tree-IL, and change from "vars" to
  "gensyms".
  (GLIL): Update for new GLIL, including preludes and prompts.
  (Assembly): Update for current output (which seems quite verbose).
  (Bytecode and Objcode): Update for current output, and some procedure
  name changes.
This commit is contained in:
Andy Wingo 2010-05-02 12:46:50 +02:00
parent 93f63467e6
commit 41e64dd73c

View file

@ -53,8 +53,9 @@ Languages are registered in the module, @code{(system base language)}:
They are registered with the @code{define-language} form. 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 reader printer @
[parser=#f] [compilers='()] [decompilers='()] [evaluator=#f] [parser=#f] [compilers='()] [decompilers='()] [evaluator=#f] @
[joiner=#f] [make-default-environment=make-fresh-user-module]
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}
@ -64,13 +65,13 @@ for Scheme:
@example @example
(define-language scheme (define-language scheme
#:title "Guile Scheme" #:title "Scheme"
#:version "0.5" #:reader (lambda (port env) ...)
#:reader read
#:compilers `((tree-il . ,compile-tree-il)) #:compilers `((tree-il . ,compile-tree-il))
#:decompilers `((tree-il . ,decompile-tree-il)) #:decompilers `((tree-il . ,decompile-tree-il))
#:evaluator (lambda (x module) (primitive-eval x)) #:evaluator (lambda (x module) (primitive-eval x))
#:printer write) #:printer write
#:make-default-environment (lambda () ...))
@end example @end example
@end deffn @end deffn
@ -79,17 +80,11 @@ they present a uniform interface to the read-eval-print loop. This
allows the user to change the current language of the REPL: allows the user to change the current language of the REPL:
@example @example
$ guile
Guile Scheme interpreter 0.5 on Guile 1.9.0
Copyright (C) 2001-2008 Free Software Foundation, Inc.
Enter `,help' for help.
scheme@@(guile-user)> ,language tree-il scheme@@(guile-user)> ,language tree-il
Tree Intermediate Language interpreter 1.0 on Guile 1.9.0 Happy hacking with Tree Intermediate Language! To switch back, type `,L scheme'.
Copyright (C) 2001-2008 Free Software Foundation, Inc. tree-il@@(guile-user)> ,L scheme
Happy hacking with Scheme! To switch back, type `,L tree-il'.
Enter `,help' for help. scheme@@(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.
@ -126,9 +121,9 @@ and target languages.
The normal tower of languages when compiling Scheme goes like this: The normal tower of languages when compiling Scheme goes like this:
@itemize @itemize
@item Scheme, which we know and love @item Scheme
@item Tree Intermediate Language (Tree-IL) @item Tree Intermediate Language (Tree-IL)
@item Guile Low Intermediate Language (GLIL) @item Guile Lowlevel Intermediate Language (GLIL)
@item Assembly @item Assembly
@item Bytecode @item Bytecode
@item Objcode @item Objcode
@ -195,14 +190,14 @@ The Scheme-to-Tree-IL expander may be invoked using the generic
Or, since Tree-IL is so close to Scheme, it is often useful to expand Or, since Tree-IL is so close to Scheme, it is often useful to expand
Scheme to Tree-IL, then translate back to Scheme. For that reason the Scheme to Tree-IL, then translate back to Scheme. For that reason the
expander provides two interfaces. The former is equivalent to calling expander provides two interfaces. The former is equivalent to calling
@code{(sc-expand '(+ 1 2) 'c)}, where the @code{'c} is for @code{(macroexpand '(+ 1 2) 'c)}, where the @code{'c} is for
``compile''. With @code{'e} (the default), the result is translated ``compile''. With @code{'e} (the default), the result is translated
back to Scheme: back to Scheme:
@lisp @lisp
(sc-expand '(+ 1 2)) (macroexpand '(+ 1 2))
@result{} (+ 1 2) @result{} (+ 1 2)
(sc-expand '(let ((x 10)) (* x x))) (macroexpand '(let ((x 10)) (* x x)))
@result{} (let ((x84 10)) (* x84 x84)) @result{} (let ((x84 10)) (* x84 x84))
@end lisp @end lisp
@ -214,9 +209,9 @@ lexical binding only has one name. It is for this reason that the
much information we would lose if we translated to Scheme directly: much information we would lose if we translated to Scheme directly:
lexical variable names, source locations, and module hygiene. lexical variable names, source locations, and module hygiene.
Note however that @code{sc-expand} does not have the same signature as Note however that @code{macroexpand} does not have the same signature
@code{compile-tree-il}. @code{compile-tree-il} is a small wrapper as @code{compile-tree-il}. @code{compile-tree-il} is a small wrapper
around @code{sc-expand}, to make it conform to the general form of around @code{macroexpand}, to make it conform to the general form of
compiler procedures in Guile's language tower. compiler procedures in Guile's language tower.
Compiler procedures take three arguments: an expression, an Compiler procedures take three arguments: an expression, an
@ -235,17 +230,10 @@ which puts the user in the @code{(foo)} module. That is purpose of the
``continuation environment''; you would pass it as the environment ``continuation environment''; you would pass it as the environment
when compiling the subsequent expression. when compiling the subsequent expression.
For Scheme, an environment may be one of two things: For Scheme, an environment is a module. By default, the @code{compile}
and @code{compile-file} procedures compile in a fresh module, such
@itemize that bindings and macros introduced by the expression being compiled
@item @code{#f}, in which case compilation is performed in the context are isolated:
of the current module; or
@item a module, which specifies the context of the compilation.
@end itemize
By default, the @code{compile} and @code{compile-file} procedures
compile in a fresh module, such that bindings and macros introduced by
the expression being compiled are isolated:
@example @example
(eq? (current-module) (compile '(current-module))) (eq? (current-module) (compile '(current-module)))
@ -289,12 +277,12 @@ expanded, pre-analyzed Scheme.
Tree-IL is ``structured'' in the sense that its representation is Tree-IL is ``structured'' in the sense that its representation is
based on records, not S-expressions. This gives a rigidity to the based on records, not S-expressions. This gives a rigidity to the
language that ensures that compiling to a lower-level language only language that ensures that compiling to a lower-level language only
requires a limited set of transformations. Practically speaking, requires a limited set of transformations. For example, the Tree-IL
consider the Tree-IL type, @code{<const>}, which has two fields, type @code{<const>} is a record type with two fields, @code{src} and
@code{src} and @code{exp}. Instances of this type are records created @code{exp}. Instances of this type are created via @code{make-const}.
via @code{make-const}, and whose fields are accessed as Fields of this type are accessed via the @code{const-src} and
@code{const-src}, and @code{const-exp}. There is also a predicate, @code{const-exp} procedures. There is also a predicate, @code{const?}.
@code{const?}. @xref{Records}, for more information on records. @xref{Records}, for more information on records.
@c alpha renaming @c alpha renaming
@ -318,10 +306,7 @@ Users may program with this format directly at the REPL:
@example @example
scheme@@(guile-user)> ,language tree-il scheme@@(guile-user)> ,language tree-il
Tree Intermediate Language interpreter 1.0 on Guile 1.9.0 Happy hacking with Tree Intermediate Language! To switch back, type `,L scheme'.
Copyright (C) 2001-2008 Free Software Foundation, Inc.
Enter `,help' for help.
tree-il@@(guile-user)> (apply (primitive +) (const 32) (const 10)) tree-il@@(guile-user)> (apply (primitive +) (const 32) (const 10))
@result{} 42 @result{} 42
@end example @end example
@ -408,25 +393,104 @@ A procedure call.
@deftpx {External Representation} (begin . @var{exps}) @deftpx {External Representation} (begin . @var{exps})
Like Scheme's @code{begin}. Like Scheme's @code{begin}.
@end deftp @end deftp
@deftp {Scheme Variable} <lambda> src names vars meta body @deftp {Scheme Variable} <lambda> src meta body
@deftpx {External Representation} (lambda @var{names} @var{vars} @var{meta} @var{body}) @deftpx {External Representation} (lambda @var{meta} @var{body})
A closure. @var{names} is original binding form, as given in the A closure. @var{meta} is an association list of properties for the
source code, which may be an improper list. @var{vars} are gensyms procedure. @var{body} is a single Tree-IL expression of type
corresponding to the @var{names}. @var{meta} is an association list of @code{<lambda-case>}. As the @code{<lambda-case>} clause can chain to
properties. The actual @var{body} is a single Tree-IL expression. an alternate clause, this makes Tree-IL's @code{<lambda>} have the
expressiveness of Scheme's @code{case-lambda}.
@end deftp @end deftp
@deftp {Scheme Variable} <let> src names vars vals exp @deftp {Scheme Variable} <lambda-case> req opt rest kw inits gensyms body alternate
@deftpx {External Representation} (let @var{names} @var{vars} @var{vals} @var{exp}) @deftpx {External Representation} @
(lambda-case ((@var{req} @var{opt} @var{rest} @var{kw} @var{inits} @var{gensyms})@
@var{body})@
[@var{alternate}])
One clause of a @code{case-lambda}. A @code{lambda} expression in
Scheme is treated as a @code{case-lambda} with one clause.
@var{req} is a list of the procedure's required arguments, as symbols.
@var{opt} is a list of the optional arguments, or @code{#f} if there
are no optional arguments. @var{rest} is the name of the rest
argument, or @code{#f}.
@var{kw} is a list of the form, @code{(@var{allow-other-keys?}
(@var{keyword} @var{name} @var{var}) ...)}, where @var{keyword} is the
keyword corresponding to the argument named @var{name}, and whose
corresponding gensym is @var{var}. @var{inits} are tree-il expressions
corresponding to all of the optional and keyword argumens, evaluated
to bind variables whose value is not supplied by the procedure caller.
Each @var{init} expression is evaluated in the lexical context of
previously bound variables, from left to right.
@var{gensyms} is a list of gensyms corresponding to all arguments:
first all of the required arguments, then the optional arguments if
any, then the rest argument if any, then all of the keyword arguments.
@var{body} is the body of the clause. If the procedure is called with
an appropriate number of arguments, @var{body} is evaluated in tail
position. Otherwise, if there is a @var{consequent}, it should be a
@code{<lambda-case>} expression, representing the next clause to try.
If there is no @var{consequent}, a wrong-number-of-arguments error is
signaled.
@end deftp
@deftp {Scheme Variable} <let> src names gensyms vals exp
@deftpx {External Representation} (let @var{names} @var{gensyms} @var{vals} @var{exp})
Lexical binding, like Scheme's @code{let}. @var{names} are the Lexical binding, like Scheme's @code{let}. @var{names} are the
original binding names, @var{vars} are gensyms corresponding to the original binding names, @var{gensyms} are gensyms corresponding to the
@var{names}, and @var{vals} are Tree-IL expressions for the values. @var{names}, and @var{vals} are Tree-IL expressions for the values.
@var{exp} is a single Tree-IL expression. @var{exp} is a single Tree-IL expression.
@end deftp @end deftp
@deftp {Scheme Variable} <letrec> src names vars vals exp @deftp {Scheme Variable} <letrec> src names gensyms vals exp
@deftpx {External Representation} (letrec @var{names} @var{vars} @var{vals} @var{exp}) @deftpx {External Representation} (letrec @var{names} @var{gensyms} @var{vals} @var{exp})
A version of @code{<let>} that creates recursive bindings, like A version of @code{<let>} that creates recursive bindings, like
Scheme's @code{letrec}. Scheme's @code{letrec}.
@end deftp @end deftp
@deftp {Scheme Variable} <dynlet> fluids vals body
@deftpx {External Representation} (dynlet @var{fluids} @var{vals} @var{body})
Dynamic binding; the equivalent of Scheme's @code{with-fluids}.
@var{fluids} should be a list of Tree-IL expressions that will
evaluate to fluids, and @var{vals} a corresponding list of expressions
to bind to the fluids during the dynamic extent of the evaluation of
@var{body}.
@end deftp
@deftp {Scheme Variable} <dynref> fluid
@deftpx {External Representation} (dynref @var{fluid})
A dynamic variable reference. @var{fluid} should be a Tree-IL
expression evaluating to a fluid.
@end deftp
@deftp {Scheme Variable} <dynset> fluid exp
@deftpx {External Representation} (dynset @var{fluid} @var{exp})
A dynamic variable set. @var{fluid}, a Tree-IL expression evaluating
to a fluid, will be set to the result of evaluating @var{exp}.
@end deftp
@deftp {Scheme Variable} <dynwind> winder body unwinder
@deftpx {External Representation} (dynwind @var{winder} @var{body} @var{unwinder})
A @code{dynamic-wind}. @var{winder} and @var{unwinder} should both
evaluate to thunks. Ensure that the winder and the unwinder are called
before entering and after leaving @var{body}. Note that @var{body} is
an expression, without a thunk wrapper.
@end deftp
@deftp {Scheme Variable} <prompt> tag body handler
@deftpx {External Representation} (prompt @var{tag} @var{body} @var{handler})
A dynamic prompt. Instates a prompt named @var{tag}, an expression,
during the dynamic extent of the execution of @var{body}, also an
expression. If an abort occurs to this prompt, control will be passed
to @var{handler}, a @code{<lambda-case>} expression with no optional
or keyword arguments, and no alternate. The first argument to the
@code{<lambda-case>} will be the captured continuation, and then all
of the values passed to the abort. @xref{Prompts}, for more
information.
@end deftp
@deftp {Scheme Variable} <abort> tag args tail
@deftpx {External Representation} (abort @var{tag} @var{args} @var{tail})
An abort to the nearest prompt with the name @var{tag}, an expression.
@var{args} should be a list of expressions to pass to the prompt's
handler, and @var{tail} should be an expression that will evaluate to
a list of additional arguments. An abort will save the partial
continuation, which may later be reinstated, resulting in the
@code{<abort>} expression evaluating to some number of values.
@end deftp
There are two Tree-IL constructs that are not normally produced by There are two Tree-IL constructs that are not normally produced by
higher-level compilers, but instead are generated during the higher-level compilers, but instead are generated during the
@ -435,17 +499,17 @@ compiler does. Users should not generate these expressions directly,
unless they feel very clever, as the default analysis pass will unless they feel very clever, as the default analysis pass will
generate them as necessary. generate them as necessary.
@deftp {Scheme Variable} <let-values> src names vars exp body @deftp {Scheme Variable} <let-values> src names gensyms exp body
@deftpx {External Representation} (let-values @var{names} @var{vars} @var{exp} @var{body}) @deftpx {External Representation} (let-values @var{names} @var{gensyms} @var{exp} @var{body})
Like Scheme's @code{receive} -- binds the values returned by Like Scheme's @code{receive} -- binds the values returned by
evaluating @code{exp} to the @code{lambda}-like bindings described by evaluating @code{exp} to the @code{lambda}-like bindings described by
@var{vars}. That is to say, @var{vars} may be an improper list. @var{gensyms}. That is to say, @var{gensyms} may be an improper list.
@code{<let-values>} is an optimization of @code{<application>} of the @code{<let-values>} is an optimization of @code{<application>} of the
primitive, @code{call-with-values}. primitive, @code{call-with-values}.
@end deftp @end deftp
@deftp {Scheme Variable} <fix> src names vars vals body @deftp {Scheme Variable} <fix> src names gensyms vals body
@deftpx {External Representation} (fix @var{names} @var{vars} @var{vals} @var{body}) @deftpx {External Representation} (fix @var{names} @var{gensyms} @var{vals} @var{body})
Like @code{<letrec>}, but only for @var{vals} that are unset Like @code{<letrec>}, but only for @var{vals} that are unset
@code{lambda} expressions. @code{lambda} expressions.
@ -470,19 +534,38 @@ Interested readers are encouraged to read the implementation in
@node GLIL @node GLIL
@subsection GLIL @subsection GLIL
Guile Low Intermediate Language (GLIL) is a structured intermediate Guile Lowlevel Intermediate Language (GLIL) is a structured intermediate
language whose expressions more closely approximate Guile's VM language whose expressions more closely approximate Guile's VM
instruction set. Its expression types are defined in @code{(language instruction set. Its expression types are defined in @code{(language
glil)}. glil)}.
@deftp {Scheme Variable} <glil-program> nargs nrest nlocs meta . body @deftp {Scheme Variable} <glil-program> meta . body
A unit of code that at run-time will correspond to a compiled A unit of code that at run-time will correspond to a compiled
procedure. @var{nargs} @var{nrest} and @var{nlocs} collectively define procedure. @var{meta} should be an alist of properties, as in
the program's arity; see @ref{Compiled Procedures}, for more
information. @var{meta} should be an alist of properties, as in
Tree-IL's @code{<lambda>}. @var{body} is an ordered list of GLIL Tree-IL's @code{<lambda>}. @var{body} is an ordered list of GLIL
expressions. expressions.
@end deftp @end deftp
@deftp {Scheme Variable} <glil-std-prelude> nreq nlocs else-label
A prologue for a function with no optional, keyword, or rest
arguments. @var{nreq} is the number of required arguments. @var{nlocs}
the total number of local variables, including the arguments. If the
procedure was not given exactly @var{nreq} arguments, control will
jump to @var{else-label}, if given, or otherwise signal an error.
@end deftp
@deftp {Scheme Variable} <glil-opt-prelude> nreq nopt rest nlocs else-label
A prologue for a function with optional or rest arguments. Like
@code{<glil-std-prelude>}, with the addition that @var{nopt} is the
number of optional arguments (possibly zero) and @var{rest} is an
index of a local variable at which to bind a rest argument, or
@code{#f} if there is no rest argument.
@end deftp
@deftp {Scheme Variable} <glil-kw-prelude> nreq nopt rest kw allow-other-keys? nlocs else-label
A prologue for a function with keyword arguments. Like
@code{<glil-opt-prelude>}, with the addition that @var{kw} is a list
of keyword arguments, and @var{allow-other-keys?} is a flag indicating
whether to allow unknown keys. @xref{Function Prologue Instructions,
@code{bind-kwargs}}, for details on the format of @var{kw}.
@end deftp
@deftp {Scheme Variable} <glil-bind> . vars @deftp {Scheme Variable} <glil-bind> . vars
An advisory expression that notes a liveness extent for a set of An advisory expression that notes a liveness extent for a set of
variables. @var{vars} is a list of @code{(@var{name} @var{type} variables. @var{vars} is a list of @code{(@var{name} @var{type}
@ -529,10 +612,10 @@ list, or a pair or vector of constants.
@end deftp @end deftp
@deftp {Scheme Variable} <glil-lexical> local? boxed? op index @deftp {Scheme Variable} <glil-lexical> local? boxed? op index
Accesses a lexically bound variable. If the variable is not Accesses a lexically bound variable. If the variable is not
@var{local?} it is free. All variables may have @code{ref} and @var{local?} it is free. All variables may have @code{ref},
@code{set} as their @var{op}. Boxed variables may also have the @code{set}, and @code{bound?} as their @var{op}. Boxed variables may
@var{op}s @code{box}, @code{empty-box}, and @code{fix}, which also have the @var{op}s @code{box}, @code{empty-box}, and @code{fix},
correspond in semantics to the VM instructions @code{box}, which correspond in semantics to the VM instructions @code{box},
@code{empty-box}, and @code{fix-closure}. @xref{Stack Layout}, for @code{empty-box}, and @code{fix-closure}. @xref{Stack Layout}, for
more information. more information.
@end deftp @end deftp
@ -565,20 +648,22 @@ corresponding to the multiple-value return address for the call. See
the notes on @code{mv-call} in @ref{Procedure Call and Return the notes on @code{mv-call} in @ref{Procedure Call and Return
Instructions}, for more information. Instructions}, for more information.
@end deftp @end deftp
@deftp {Scheme Variable} <glil-prompt> label escape-only?
Push a dynamic prompt into the stack, with a handler at @var{label}.
@var{escape-only?} is a flag that is propagated to the prompt,
allowing an abort to avoid capturing a continuation in some cases.
@xref{Prompts}, for more information.
@end deftp
Users may enter in GLIL at the REPL as well, though there is a bit Users may enter in GLIL at the REPL as well, though there is a bit
more bookkeeping to do. Since GLIL needs the set of variables to be more bookkeeping to do:
declared explicitly in a @code{<glil-program>}, GLIL expressions must
be wrapped in a thunk that declares the arity of the expression:
@example @example
scheme@@(guile-user)> ,language glil scheme@@(guile-user)> ,language glil
Guile Lowlevel Intermediate Language (GLIL) interpreter 0.3 on Happy hacking with Guile Lowlevel Intermediate Language (GLIL)!
Guile 1.9.0 To switch back, type `,L scheme'.
Copyright (C) 2001-2008 Free Software Foundation, Inc. glil@@(guile-user)> (program () (std-prelude 0 0 #f)
(const 3) (call return 1))
Enter `,help' for help.
glil@@(guile-user)> (program 0 0 0 () (const 3) (call return 1))
@result{} 3 @result{} 3
@end example @end example
@ -624,44 +709,33 @@ to play around with it at the REPL, as can be seen in this annotated
example: example:
@example @example
scheme@@(guile-user)> (compile '(lambda (x) (+ x x)) #:to 'assembly) scheme@@(guile-user)> (compile '(+ 32 10) #:to 'assembly)
(load-program 0 0 0 (load-program
() ; Labels ((:LCASE104 . 6)) ; Labels, unused in this case.
70 ; Length 16 ; Length of the thunk that was compiled.
#f ; Metadata (load-program ; Metadata thunk.
(make-false)
(make-false) ; object table for the returned lambda
(nop)
(nop) ; Alignment. Since assembly has already resolved its labels
(nop) ; to offsets, and programs must be 8-byte aligned since their
(nop) ; object code is mmap'd directly to structures, assembly
(nop) ; has to have the alignment embedded in it.
(nop)
(load-program
1
0
() ()
8 17
(load-program 0 0 0 () 21 #f #f ; No metadata thunk for the metadata thunk.
(load-symbol "x") ; Name and liveness extent for @code{x}. (make-eol)
(make-false) (make-eol)
(make-int8:0) ; Some instruction+arg combinations (make-int8 6)
(make-int8:0) ; have abbreviations. (make-int8 12) ; Liveness extents, source info, and arities,
(make-int8 6) (make-int8:0) ; in a format that Guile knows how to parse.
(list 0 5) (list 0 3)
(list 0 1) (list 0 1)
(make-eol) (list 0 3)
(list 0 2) (return))
(return)) (assert-nargs-ee 0 0) ; Prologue.
; And here, the actual code. (reserve-locals 0 0)
(local-ref 0) (make-int8 32) ; Actual code starts here.
(local-ref 0) (make-int8 10)
(add) (add)
(return) (return)
(nop) (nop)
(nop)) (nop) ; Padding; the metadata thunk is actually
; Return our new procedure. (nop) ; written after the main text.
(return)) (nop))
@end example @end example
Of course you can switch the REPL to assembly and enter in assembly Of course you can switch the REPL to assembly and enter in assembly
@ -679,11 +753,13 @@ structuring and destructuring code on the Scheme level. Bytecode is
the next step down from assembly: the next step down from assembly:
@example @example
scheme@@(guile-user)> (compile '(+ 32 10) #:to 'assembly)
@result{} (load-program 0 0 0 () 6 #f
(make-int8 32) (make-int8 10) (add) (return))
scheme@@(guile-user)> (compile '(+ 32 10) #:to 'bytecode) scheme@@(guile-user)> (compile '(+ 32 10) #:to 'bytecode)
@result{} #u8(0 0 0 0 6 0 0 0 0 0 0 0 0 0 0 0 10 32 10 10 120 52) @result{} #vu8(16 0 0 0 25 0 0 0 ; Header.
45 0 0 52 0 0 ; Prologue.
10 32 10 10 148 66 ; Actual code.
0 0 0 0 ; Padding.
17 0 0 0 0 0 0 0 9 9 10 6 10 ; Metadata thunk.
12 11 18 0 3 18 0 1 18 0 3 66)
@end example @end example
``Objcode'' is bytecode, but mapped directly to a C structure, ``Objcode'' is bytecode, but mapped directly to a C structure,
@ -691,9 +767,6 @@ scheme@@(guile-user)> (compile '(+ 32 10) #:to 'bytecode)
@example @example
struct scm_objcode @{ struct scm_objcode @{
scm_t_uint8 nargs;
scm_t_uint8 nrest;
scm_t_uint16 nlocs;
scm_t_uint32 len; scm_t_uint32 len;
scm_t_uint32 metalen; scm_t_uint32 metalen;
scm_t_uint8 base[0]; scm_t_uint8 base[0];
@ -701,9 +774,8 @@ struct scm_objcode @{
@end example @end example
As one might imagine, objcode imposes a minimum length on the As one might imagine, objcode imposes a minimum length on the
bytecode. Also, the multibyte fields are in native endianness, which bytecode. Also, the @code{len} and @code{metalen} fields are in native
makes objcode (and bytecode) system-dependent. Indeed, in the short endianness, which makes objcode (and bytecode) system-dependent.
example above, all but the last 6 bytes were the program's header.
Objcode also has a couple of important efficiency hacks. First, Objcode also has a couple of important efficiency hacks. First,
objcode may be mapped directly from disk, allowing compiled code to be objcode may be mapped directly from disk, allowing compiled code to be
@ -725,7 +797,7 @@ Returns @code{#f} iff @var{obj} is object code, @code{#f} otherwise.
@deffn {Scheme Procedure} bytecode->objcode bytecode @deffn {Scheme Procedure} bytecode->objcode bytecode
@deffnx {C Function} scm_bytecode_to_objcode (bytecode) @deffnx {C Function} scm_bytecode_to_objcode (bytecode)
Makes a bytecode object from @var{bytecode}, which should be a Makes a bytecode object from @var{bytecode}, which should be a
@code{u8vector}. bytevector. @xref{Bytevectors}.
@end deffn @end deffn
@deffn {Scheme Variable} load-objcode file @deffn {Scheme Variable} load-objcode file
@ -739,12 +811,12 @@ prevent accidental loading of arbitrary garbage.
@deffn {Scheme Variable} write-objcode objcode file @deffn {Scheme Variable} write-objcode objcode file
@deffnx {C Function} scm_write_objcode (objcode) @deffnx {C Function} scm_write_objcode (objcode)
Write object code out to a file, prepending the eight-byte cookie. Write object code out to a file, prepending the sixteen-byte cookie.
@end deffn @end deffn
@deffn {Scheme Variable} objcode->u8vector objcode @deffn {Scheme Variable} objcode->bytecode objcode
@deffnx {C Function} scm_objcode_to_u8vector (objcode) @deffnx {C Function} scm_objcode_to_bytecode (objcode)
Copy object code out to a @code{u8vector} for analysis by Scheme. Copy object code out to a bytevector for analysis by Scheme.
@end deffn @end deffn
The following procedure is actually in @code{(system vm program)}, but The following procedure is actually in @code{(system vm program)}, but
@ -766,13 +838,8 @@ Compiling object code to the fake language, @code{value}, is performed
via loading objcode into a program, then executing that thunk with via loading objcode into a program, then executing that thunk with
respect to the compilation environment. Normally the environment respect to the compilation environment. Normally the environment
propagates through the compiler transparently, but users may specify propagates through the compiler transparently, but users may specify
the compilation environment manually as well: the compilation environment manually as well, as a module.
@deffn {Scheme Procedure} make-objcode-env module free-vars
Make an object code environment. @var{module} should be a Scheme
module, and @var{free-vars} should be a vector of free variables.
@code{#f} is also a valid object code environment.
@end deffn
@node Writing New High-Level Languages @node Writing New High-Level Languages
@subsection Writing New High-Level Languages @subsection Writing New High-Level Languages