Next: , Up: Compiling to Wasm   [Contents][Index]

2.1 Invoking the compiler

In Guile’s compiler tower, Scheme code goes through several transformations before being compiled to VM bytecode. Scheme is lowered to Tree-IL, which is then lowered to Continuation-passing style(CPS), and then finally to Bytecode. Hoot adds an additional backend that compiles CPS to Wasm.

In contrast to Guile’s approach of compiling individual modules, Hoot is a whole-program compiler. The user program and all imported modules are part of the same compilation unit and the result is a single Wasm binary. Currently, Hoot uses the R6RS library system and does not support Guile’s define-module form or R7RS style libraries.

For hooking the Hoot compiler up to a build system such as GNU Make, invoke the guild compile-wasm tool:

guild compile-wasm --load-path=. --output=foo.wasm foo.scm

Like Guile’s built-in compiler, the Hoot compiler can also be invoked within Scheme. The (hoot compile) module provides the interface to the Wasm compiler backend.

Procedure: compile exp [#:import-abi? #f] [#:export-abi? #t] [#:imports %default-program-imports] [#:include-file %include-from-path] [#:extend-load-library (lambda (f) f)] [#:load-library (extend-load-library (builtin-module-loader import-abi?))] [#:optimization-level (default-optimization-level)] [#:warning-level (default-warning-level)] [#:dump-cps? #f] [#:dump-wasm? #f] [#:emit-names? #f] [#:opts '()]

Compile the Scheme expression exp to Wasm and return a Wasm module.

The environment in which exp is evaluated is defined by imports, a list of module names such as (scheme time) or (hoot ffi). If not specified, a default list of imports will be used.

When import-abi? is #t, the Wasm module will be built such that it needs to import its ABI from another module. When export-abi? is #t, the Wasm module will be built such that it exports its ABI functions. A typical use of these flags is to export the ABI from one “main” module and then import that ABI into any additional modules that are being used.

When emit-names? is #t then human-readable names will be embedded in the resulting Wasm object. By default, this is turned off as it greatly increases binary size.

Associating module names with source code is handled by load-library, a procedure that receives the module name as its only argument and returns the source code as an s-expression, or #f if there is no such module. The default loader is capable of loading modules from Hoot’s standard library. It is generally recommended to leave load-library alone and use the default.

To load additional modules, specify extend-load-library instead. extend-load-library is a procedure that receives one argument, load-library, and returns a procedure with the same signature as load-library. Through this extension mechanism, users can load their own modules.

Most of the time, loading user modules from the file system is all that is needed. Hoot has a built-in library-load-path-extension extension procedure for this purpose. To demonstrate, let’s first assume that the code below is saved to example.scm in the current directory:

(library (example)
  (export double)
  (import (scheme base))
  (define (double x) (* x 2)))

The compiler can then be extended to load modules from the current directory like so:

(compile '(double 42)
         #:imports '((scheme base) (example))
         (library-load-path-extension '(".")))

See the Guile manual for more information about invoking Guile’s compiler.

Procedure: read-and-compile port [#:import-abi? #f] [#:export-abi? #t] [#:include-file %include-from-path] [#:extend-load-library (lambda (f) f)] [#:load-library (extend-load-library (builtin-module-loader import-abi?))] [#:optimization-level (default-optimization-level)] [#:warning-level (default-warning-level)] [#:dump-cps? #f] [#:dump-wasm? #f] [#:emit-names? #f] [#:opts '()]

Like compile, but read Scheme expressions from port.

If the first expression is an import form, then only the bindings from those modules will be imported into the compilation unit. If the import form is omitted, a default set of modules will be imported. It is highly recommended to be explicit and use import.

Procedure: compile-file input-file [#:import-abi? #f] [#:export-abi? #t] [#:include-file %include-from-path] [#:extend-load-library (lambda (f) f)] [#:load-library (extend-load-library (builtin-module-loader import-abi?))] [#:optimization-level (default-optimization-level)] [#:warning-level (default-warning-level)] [#:dump-cps? #f] [#:dump-wasm? #f] [#:emit-names? #f] [#:opts '()]

Like read-and-compile, but read the Scheme expression from input-file.

Next: High-level development tools, Up: Compiling to Wasm   [Contents][Index]