[ << ] | [ < ] | [ Up ] | [ > ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
9.4.1 Compiler Tower
Guile’s compiler is quite simple, actually – its compilers, to put it more accurately. Guile defines a tower of languages, starting at Scheme and progressively simplifying down to languages that resemble the VM instruction set (see section Instruction Set).
Each language knows how to compile to the next, so each step is simple and understandable. Furthermore, this set of languages is not hardcoded into Guile, so it is possible for the user to add new high-level languages, new passes, or even different compilation targets.
Languages are registered in the module, (system base language)
:
(use-modules (system base language))
They are registered with the define-language
form.
- Scheme Syntax: define-language [#:name] [#:title] [#:reader] [#:printer] [#:parser=#f] [#:compilers='()] [#:decompilers='()] [#:evaluator=#f] [#:joiner=#f] [#:for-humans?=#t] [#:make-default-environment=make-fresh-user-module]
Define a language.
This syntax defines a
#<language>
object, bound to name in the current environment. In addition, the language will be added to the global language set. For example, this is the language definition for Scheme:(define-language scheme #:title "Scheme" #:reader (lambda (port env) ...) #:compilers `((tree-il . ,compile-tree-il)) #:decompilers `((tree-il . ,decompile-tree-il)) #:evaluator (lambda (x module) (primitive-eval x)) #:printer write #:make-default-environment (lambda () ...))
The interesting thing about having languages defined this way is that they present a uniform interface to the read-eval-print loop. This allows the user to change the current language of the REPL:
scheme@(guile-user)> ,language tree-il Happy hacking with Tree Intermediate Language! To switch back, type `,L scheme'. tree-il@(guile-user)> ,L scheme Happy hacking with Scheme! To switch back, type `,L tree-il'. scheme@(guile-user)>
Languages can be looked up by name, as they were above.
- Scheme Procedure: lookup-language name
Looks up a language named name, autoloading it if necessary.
Languages are autoloaded by looking for a variable named name in a module named
(language name spec)
.The language object will be returned, or
#f
if there does not exist a language with that name.
Defining languages this way allows us to programmatically determine the necessary steps for compiling code from one language to another.
- Scheme Procedure: lookup-compilation-order from to
Recursively traverses the set of languages to which from can compile, depth-first, and return the first path that can transform from to to. Returns
#f
if no path is found.This function memoizes its results in a cache that is invalidated by subsequent calls to
define-language
, so it should be quite fast.
There is a notion of a “current language”, which is maintained in the
current-language
parameter, defined in the core (guile)
module. This language is normally Scheme, and may be rebound by the
user. The run-time compilation interfaces
(see section Reading and Evaluating Scheme Code) also allow you to choose other source
and target languages.
The normal tower of languages when compiling Scheme goes like this:
- Scheme
- Tree Intermediate Language (Tree-IL)
- Guile Lowlevel Intermediate Language (GLIL)
- Assembly
- Bytecode
- Objcode
Object code may be serialized to disk directly, though it has a cookie and version prepended to the front. But when compiling Scheme at run time, you want a Scheme value: for example, a compiled procedure. For this reason, so as not to break the abstraction, Guile defines a fake language at the bottom of the tower:
- Value
Compiling to value
loads the object code into a procedure, and
wakes the sleeping giant.
Perhaps this strangeness can be explained by example:
compile-file
defaults to compiling to object code, because it
produces object code that has to live in the barren world outside the
Guile runtime; but compile
defaults to compiling to
value
, as its product re-enters the Guile world.
Indeed, the process of compilation can circulate through these different worlds indefinitely, as shown by the following quine:
((lambda (x) ((compile x) x)) '(lambda (x) ((compile x) x)))
[ << ] | [ < ] | [ Up ] | [ > ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This document was generated on April 20, 2013 using texi2html 5.0.