A module is a set of definitions that the module exports, as well as some actions (expressions evaluated for their side effect). The top-level forms in a Scheme source file compile a module; the source file is the module source. When Kawa compiles the module source, the result is the module class. Each exported definition is translated to a public field in the module class.
You can declare a class using
with the same name as the module class, for example the
following in a file named
(define-simple-class foo ...)
In this case the defined class will serve dual-purpose as the module class.
The definitions that a module exports are accessible to other modules.
These are the "public" definitions, to use Java terminology.
By default, all the identifiers declared at the top-level of a module
are exported, except those defined using
However, a major purpose of using modules is to control the set of
names exported. One reason is to reduce the chance of accidental
name conflicts between separately developed modules. An even more
important reason is to enforce an interface: Client modules should
only use the names that are part of a documented interface, and should
not use internal implementation procedures (since those may change).
If there is a
module-export declaration in the module, then
only those names listed in a
module-export are exported.
There can be more than one
module-export, and they can be
anywhere in the Scheme file. As a matter of good style, I recommend
module-export near the beginning of the file.
Make the definition for each
namebe exported. Note that it is an error if there is no definition for
namein the current module, or if it is defined using
In this module,
fact is public and
worker is private:
(module-export fact) (define (worker x) ...) (define (fact x) ...)
Alternatively, you can write:
(define-private (worker x) ...) (define (fact x) ...)
If you want to just use a Scheme module as a module (i.e.
require it), you don’t care how it gets translated
into a module class. However, Kawa gives you some control over how this
is done, and you can use a Scheme module to define a class which
you can use with other Java classes. This style of class definition
is an alternative to
which lets you define classes and instances fairly conveniently.
The default name of the module class is the main part of the
filename of the Scheme source file (with directories and extensions
sripped off). That can be overridden by the
command-line flag. The package-prefix specified by the
flag is prepended to give the fully-qualified class name.
Sets the name of the generated class, overriding the default. If there is no ‘
.’ in the
name, the package-prefix (specified by the
-PKawa command-line flag) is prepended.
By default, the base class of the generated module class is unspecified;
you cannot count on it being more specific than
However, you can override it with
Specifies that the class generated from the immediately surrounding module should extend (be a sub-class of) the class
Specifies that the class generated from the immediately surrounding module should implement the interfaces listed.
Note that the compiler does not currently check that all the abstract methods requires by the base class or implemented interfaces are actually provided, and have the correct signatures. This will hopefully be fixed, but for now, if you are forgot a method, you will probably get a verifier error
For each top-level exported definition the compiler creates a
corresponding public field with a similar (mangled) name.
By default, there is some indirection: The value of the Scheme variable
is not that of the field itself. Instead, the field is a
gnu.mapping.Symbol object, and the value Scheme variable is
defined to be the value stored in the
Howewer, if you specify an explicit type, then the field will
have the specified type, instead of being a
The indirection using
Symbol is also avoided if you use
If the Scheme definition defines a procedure (which is not re-assigned
in the module), then the compiler assumes the variable as bound as a
constant procedure. The compiler generates one or more methods
corresponding to the body of the Scheme procedure. It also generates
a public field with the same name; the value of the field is an
instance of a subclass of
<gnu.mapping.Procedure> which when
applied will execute the correct method (depending on the actual arguments).
The field is used when the procedure used as a value (such as being passed
as an argument to
map), but when the compiler is able to do so,
it will generate code to call the correct method directly.
You can control the signature of the generated method by declaring
the parameter types and the return type of the method. See the
applet (see Applet compilation) example for how this can be done.
If the procedures has optional parameters, then the compiler will
generate multiple methods, one for each argument list length.
(In rare cases the default expression may be such that this is
not possible, in which case an "variable argument list" method
is generated instead. This only happens when there is a nested
scope inside the default expression, which is very contrived.)
If there are
#!rest arguments, the compiler
generate a "variable argument list" method. This is a method whose
last parameter is either an array or a
<list>, and whose
$V appended to indicate the last parameter is a list.
Top-leval macros (defined using either
defmacro) create a field whose type is currently a sub-class of
kawa.lang.Syntax; this allows importing modules to detect
that the field is a macro and apply the macro at compile time.
Unfortunately, the Java class verifier does not allow fields to have
arbitrary names. Therefore, the name of a field that represents a
Scheme variable is "mangled" (see Mangling) into an acceptable Java name.
The implementation can recover the original name of a field
((gnu.mapping.Named) X).getName() because all the standard
compiler-generate field types implemented the
There are two kinds of module class: A static module is a class (or gets compiled to a class) all of whose public fields a static, and that does not have a public constructor. A JVM can only have a single global instance of a static module. An instance module has a public default constructor, and usually has at least one non-static public field. There can be multiple instances of an instance module; each instance is called a module instance. However, only a single instance of a module can be registered in an environment, so in most cases there is only a single instance of instance modules. Registering an instance in an environment means creating a binding mapping a magic name (derived from the class name) to the instance.
In fact, any Java class class that has the properties of either an instance module or a static module, is a module, and can be loaded or imported as such; the class need not have written using Scheme.
You can control whether a module is compiled to a static or
a non-static class using either a command-line flag to the compiler,
or using the
module-static special form.
module-static is specified, generate a static module
(module-static #t) were specified).
This is (now) the default.
module-static is specified, generate a non-static module
(module-static #f) were specified).
This used to be the default.
module-static is specified, generate a static module
(module-static 'init-run) were specified).
Control whether the generated fields and methods are static. If
'init-runis specified, then the module will be a static module, all definitions will be static. If
'init-runis specified, in addition the module body is evaluated in the class’s static initializer. (Otherwise, it is run the first time it is
require’d.) Otherwise, the module is an instance module. However, the
names that are explicitly listed will be compiled to static fields and methods. If
#fis specified, then all exported names will be compiled to non-static (instance) fields and methods.
By default, if no
If there is a
module-implementsdeclaration, or one of the
--servletcommand-line flags was specified, then
(module-static #f)is implied.
If one of the command-line flags
--module-static-runwas specified, then the default is
Otherwise the default is
(module-static #t). (It used to be
(module-static #f)in older Kawa versions.)
(module-static #t)usually produces more efficient code, and is recommended if a module contains only procedure or macro definitions. (This may become the default.) However, a static module means that all environments in a JVM share the same bindings, which you may not want if you use multiple top-level environments.
The top-level actions of a module will get compiled to a
method. If there is an explicit
method-extends, then the
module class will also automatically implement
(Otherwise, the class does not implement
Runnable, since in that
run method return an
Object rather than
This will likely change.)
Certain compilation options can be be specified either on the command-line when compiling, or in the module itself.
This sets the value of the
valuefor the current module (source file). It takes effect as soon it is seen during the first macro-expansion pass, and is active thereafter (unless overridden by
key:is one of the supported option names (The ending colon make it a Kawa keyword). Valid option keys are:
main:- Generate an application, with a main method.
full-tailcalls:- Use a calling convention that supports proper tail recursion.
warn-undefined-variable:- Warn if no compiler-visible binding for a variable.
warn-unknown-member:- Warn if referencing an unknown method or field.
warn-invoke-unknown-method:- Warn if invoke calls an unknown method (subsumed by warn-unknown-member).
warn-unused:- Warn if a variable is usused or code never executed.
warn-unreachable:- Warn if this code can never be executed.
warn-void-used:- Warn if an expression depends on the value of a void sub-expression (one that never returns a value).
warn-as-error:- Treat a compilation warning as if it were an error.
valuemust be a literal value: either a boolean (
#f), a number, or a string, depending on the
key. (All the options so far are boolean options.)(module-compile-options warn-undefined-variable: #t) ;; This causes a warning message that y is unknown. (define (func x) (list x y))
module-compile-options, but the option is only active within
The module option key
main:has no effect when applied to a particular body via the
with-compile-optionssyntax.(define (func x) (with-compile-options warn-invoke-unknown-method: #f (invoke x 'size)))
You can import a module into the current namespace with
Search for a matching module (class), and add the names exported by that module to the current set of visible names. Normally, the module is specified using
classname. The module can be static module (all public fields must be static), or an instance module (it has a public default constructor).
If the module is a instance module and if no module instance for that class has been registered in the current environment, then a new instance is created and registered (using a "magic" identifier). If the module class either inherits from
java.lang.Runnablethen the corresponding
runmethod is executed. (This is done after the instance is registered so that cycles can be handled.) These actions (creating, registering, and running the module instance) are done both at compile time and at run time, if necessary.
All the public fields of the module class are then incorporated in the current set of local visible names in the current module. (This is for both instance and static modules.) This is done at compile time - no new bindings are created at run-time (except for the magic binding used to register the module instance), and the imported bindings are private to the current module. References to the imported bindings will be compiled as field references, using the module instance (except for static fields).
is specified then that is used to locate the source file for the module, and if necessary, compile it.
'is specified then the
featurenameis looked up (at compile time) in the "feature table" which yields the implementing
Similar functionality as
require, but specified by R6RS.
library-referenceis mapped to a class name by concatenating all the identifiers, separated by dots. For example:(import (gnu kawa slib srfi37))
is equivalent to:(require gnu.kawa.slib.srfi37)
By default, all of an imported library’s exported bindings are made visible within an importing library using the names given to the bindings by the imported library. The precise set of bindings to be imported and the names of those bindings can be adjusted with the
renameforms as described below.
onlyform produces a subset of the bindings from another
import-set, including only the listed
identifiers. The included
identifiers must be in the original
exceptform produces a subset of the bindings from another
import-set, including all but the listed
identifiers. All of the excluded
identifiers must be in the original
prefixform adds the
identifierprefix to each name from another
removes the bindings for
to form an intermediate
import-set, then adds the bindings back for the corresponding
to form the final
identifier1must be in the original
identifier2must not be in the intermediate
import-set, and the
identifier2s must be distinct.
'is available. A following
cond-expandin this scope will match
similar to the same-named macros in SLib, Emacs, and Common Lisp.
However, in Kawa these are not functions, but instead they
are syntax forms that are processed at compile time. That is
why only quoted
featurenames are supported.
This is consistent with Kawa emphasis on compilation and
For some examples, you may want to look in the