Kawa is a Scheme environment, written in Java, and that compiles Scheme code into Java byte-codes.
This documents version 1.6.1, updated 11 March 1998.
See the summary of @uref{http://www.cygnus.com/~bothner/kawa/News.txt,recent changes}.
The author of Kawa is Per Bothner <bothner@cygnus.com>. It is a re-write of Kawa 0.2, which was written by R. Alexander Milowski <alex@copsol.com>.
This
is the Kawa home-page.
@uref{http://www.copsol.com/sgmlimpl/tools/kawa/index.html,Copsol's Kawa home-page}
is not maintained by me and so may not be as current.
The
@uref{http://www.cs.indiana.edu/scheme-repository/home.html,Scheme repository}
has various useful information on Scheme, including a pointer to
an online copy of
@uref{http://www-swiss.ai.mit.edu/~jaffer/r4rs_toc.html,R4RS}.
Javadoc generated
@uref{http://www.cygnus.com/~bothner/kawa/api/packages.html,documentation of the Kawa classes} is now available online.
For copyright information on the software and documentation,
see section License.
This package has nothing to do with the
@uref{http://www.tek-tools.com/kawa/,Kawa commercial Java IDE}.
The two packages @uref{http:../gnu.bytecode/,
Kawa is a full Scheme implementation. It implements almost
all of R5RS (for exceptions see section Features of R5RS not implemented), plus some extensions.
By default, symbols are case sensitive.
It is completely written in Java. Scheme functions and files
are automatically compiled into Java byte-codes, providing
reasonable speed. (However, Kawa is not an optimizing compiler,
and does not perform major transformations on the code.)
Kawa provides the usual read-eval-print loop, as well as batch modes.
Kawa is written in an object-oriented style.
Kawa implements most of the features of the expression language of DSSSL,
the Scheme-derived ISO-standard Document Style Semantics and Specification
Language for SGML. Of the core expression language, the only features
missing are character properties,
The current sources release is in
here.
A ready-to-run
A snapshot of the development tree is in
here.
These are all in the @uref{ftp://ftp.cygnus.com/pub/bothner,Kawa ftp site},
which includes other versions and files, including a
Before installing Kawa, you must have Java working on your
system.
You can compile Kawa from the source distribution.
Alternatively, you can install the pre-compiled binary distribution.
You will need a working Java system.
The discussion below assumes you are using the Java Developer's Kit
(JDK) version 1.1.x from JavaSoft (Sun).
(Kawa has also been reported to work with Kaffe, Symantec Cafe, J++,
and JDK 1.2beta.)
You can download free copies of
JDK 1.1.x
for various platforms.
The program
You also need to set
If you have the JDK in directory
The binary release includes only the binary compiled `.class'
versions of the same `.java' source files in the source release.
It does not include any documentation, so you probably want the
source release in addition to the binary release. The purpose
of the binary release is just to save you time and trouble of
compiling the sources.
The binary release comes as a
You can unzip the archive, or you can use it as is.
Assuming the latter, copy the archive to some suitable location,
such as
Then, before you can actually run Kawa, you need to set
On Windows95/WindowsNT, you need to set
Then to run Kawa do:
In your build directory do:
Then you must configure the sources. This you can do
the same way you configure most other GNU software. Normally
you can just run the configure script with no arguments:
This will specify that a later
Thus you need to compile all the .java source files.
Just run make:
You can now test the system by running Kawa in place:
or you can run the test suite:
or you can install the compiled files:
This will install your classes into
To use the installed files, you need to set
I have not yet tried to build Kawa from source on Windows95, though I
understand others have done so. (If you know how, let me know!)
The easiest way to start up Kawa is to run the `kawa'
script. This finds your java interpreter, and sets up `CLASSPATH'
correctly.
If you have installed Kawa such
To run Kawa manually, you must start a Java interpreter.
How you do this depends on the Java interpreter.
For JavaSoft's JDK, you must have the Java interpreter
in your
Then you do:
In either case, you will then get the `#|kawa:1|#' prompt,
which means you are
in the Kawa read-eval-print-loop. If you type a Scheme
expression, Kawa will evaluate it. Kawa will then print the
result (if there is a non-"void" result).
You can pass various flags to Kawa, for example:
At startup, Kawa executes an init file from the user's home
directory.
The init file is named
The options `-C', `-d', `-T', `-P', and `--main'
are used to compile a Scheme file; see section Compiling Scheme to a set of .class files.
If there are further command-line arguments after the options
have been processed, then the first remaining argument names a
file that is read and evaluated. If there is no such argument,
then Kawa enters an interactive read-eval-print loop,
but only if none of the `-c', `-e', `-f', `-s',
`-C', or `--' options were specified.
An alternative interface runs the Java read-eval-print-loop
inside a new window. This is in some ways nicer. One reason
is that it provides better editing. You can also create
new windows. They can either have different top-level
environments or they can share environments. To try it, do:
To close a read-eval-print-loop, you can type the special
literal
If the read-eval-print-loop
is in a new window, you can select `Close' from the `File' menu.
To exit the entire Kawa session, call the
Kawa implements all the required and optional features of R5RS,
with the following exceptions.
The entire "numeric tower" is implemented.
However, some transcendental function only work on reals.
Integral function do not necessarily work on
inexact (floating-point) integers.
(The whole idea of "inexact integer" in R5RS seems rather pointless ...)
Also, call-with-current-continuation is only "upwards" (?).
I.e. once a continuation has been exited, it cannot be invoked.
These restricted continuations can be used to implement catch/throw
(such as the examples in R4RS), but not co-routines or backtracking.
Kawa does not do general tail-call elimination. However, if the
compiler can prove that the procedure being called is the current
function, then the tail call will be replaced by a jump.
This means the procedure must be defined using a letrec, not a
define (because the compiler does not know if someone might
re-define a global definition), and there must be no assignments
(using
The
The multiple-value feature will be in R5RS.
Delivers all of its arguments to its continuation.
Function: call-with-values thunk receiver
Call its thunk argument with a continuation that,
when passed some values, calls the receiver procedure
with those values as arguments.
Special self-evaluating literal used in lambda parameter lists
before optional parameters.
Special self-evaluating literal used in lambda parameter lists
before the rest parameter.
Special self-evaluating literal used in lambda parameter lists
before keyword parameters.
The end-of-file object.
Note that if the Scheme reader sees this literal at top-level,
it is returned literally. This is indistinguishable from
coming to the end of the input file. If you do not want to end reading,
but want the actual value of
The void value. Same as
The Java
Keywords are similar to symbols. The main difference is that keywords are
self-evaluating and therefore do not need to be quoted in expressions.
They are used mainly for specifying keyword arguments.
A keyword is a single token; therefore no whitespace is allowed between
the identifier and the colon (which is not considered part
of the name of the keyword).
Return
Function: keyword->string keyword
Returns the name of keyword as a string.
The name does not include the final
Function: string->keyword string
Returns the keyword whose name is string.
(The string does not include a final
Kawa borrows the extended formal argument list of DSSSL:
When the procedure is applied to a list of actual arguments, the formal and
actual arguments are processed from left to right as follows:
These functions operate on the 2's complement binary representation
of an exact integer.
Returns the bit-wise logical "and" of the arguments.
If no argument is given, the result is -1.
Returns the bit-wise logical "(inclusive) or" of the arguments.
If no argument is given, the result is 0.
Returns the bit-wise logical "exclusive or" of the arguments.
If no argument is given, the result is 0.
Returns the bit-wise logical inverse of the argument.
Perform one of the 16 bitwise operations of x and y,
depending on op.
Returns true if the arguments have any bits in common.
Same as
Returns
Function: arithmetic-shift i j
Shifts i by j.
It is a "left" shift if
The result is equal to
Alias for
Count the number of 1-bits in i, if it is non-negative.
If i is negative, count number of 0-bits.
Return number of bits needed to represent i in an unsigned field.
Regardless of the sign of i, return one less than the number of bits
needed for a field that can represent i as a two's complement integer.
Function: bit-extract n start end
Return the integer formed from the (unsigned) bit-field
starting at start and ending just before end.
Same as
The Record package provides a facility for user to define their own
record data types. A record type is implemented as Java Class
object, and records are extensions of the class
Function: make-record-type type-name field-names
Returns a record-type descriptor, a value representing a new data
type disjoint from all others. The type-name argument must be a
string, but is only used for debugging purposes (such as the printed
representation of a record of the new type). The field-names
argument is a list of symbols naming the fields of a record of the
new type. It is an error if the list contains any duplicates.
In Kawa, returns a newly-created
Function: record-constructor rtd [field-names]
Returns a procedure for constructing new members of the type represented
by rtd. The returned procedure accepts exactly as many arguments
as there are symbols in the given list, field-names; these are
used, in order, as the initial values of those fields in a new record,
which is returned by the constructor procedure. The values of any
fields not named in that list are unspecified. The field-names
argument defaults to the list of field names in the call to
In Kawa, rtd may be any
Function: record-predicate rtd
Returns a procedure for testing membership in the type represented by
rtd. The returned procedure accepts exactly one argument and
returns a true value if the argument is a member of the indicated record
type; it returns a false value otherwise.
In Kawa, the returned procedure checks if the argument is an instance
of rtd or one of its sub-classes.
Function: record-accessor rtd field-name
Returns a procedure for reading the value of a particular field of a
member of the type represented by rtd. The returned procedure
accepts exactly one argument which must be a record of the appropriate
type; it returns the current value of the field named by the symbol
field-name in that record. The symbol field-name must be a
member of the list of field-names in the call to
Function: record-modifier rtd field-name
Returns a procedure for writing the value of a particular field of a
member of the type represented by rtd. The returned procedure
accepts exactly two arguments: first, a record of the appropriate type,
and second, an arbitrary Scheme value; it modifies the field named by
the symbol field-name in that record to contain the given value.
The returned value of the modifier procedure is unspecified. The symbol
field-name must be a member of the list of field-names in the call
to
Returns a true value if obj is a record of any type and a false
value otherwise.
In Kawa, this is true if obj is an instance of
Function: record-type-descriptor record
Returns a record-type descriptor representing the type of the given
record. That is, for example, if the returned descriptor were passed to
Function: record-type-name rtd
Returns the type-name associated with the type represented by rtd. The
returned value is
Function: record-type-field-names rtd
Returns a list of the symbols naming the fields in members of the type
represented by rtd. The returned value is
Function: file-exists? filename
Returns true iff the file named filename actually exists.
Function: file-directory? filename
Returns true iff the file named filename actually exists
and is a directory.
Function: file-readable? filename
Returns true iff the file named filename actually exists
and can be read from.
Function: file-writable? filename
Returns true iff the file named filename actually exists
and can be writen to.
(Undefined if the filename does not exist,
but the file can be created in the directory.)
Function: delete-file filename
Delete the file named filename.
Function: rename-file oldname newname
Renames the file named oldname to newname.
Function: copy-file oldname newname-from path-to
Copy the file named oldname to newname.
The return value is unspecified.
Function: create-directory dirname
Create a new directory named dirname.
Unspecified what happens on error (such as exiting file with the same name).
(Currently returns
Function: call-with-input-string string proc
Create an input port that gets its data from string,
call proc with that port as its one argument, and return
the result from the call of proc
Function: call-with-output-string proc
Create an output port that writes its data to a string,
and call proc with that port as its one argument.
Return a string consisting of the data written to the port.
Forces any pending output on port to be delivered to the output
device and returns an unspecified value. If the port argument is
omitted it defaults to the value returned by
An interactive input port has a prompt procedure associated with it.
The prompt procedure is called before a new line is read. It is passed
the port as an argument, and returns a string, which gets printed as a prompt.
Function: input-port-prompter port
Get the prompt procedure associated with port.
Function: set-input-port-prompter! port prompter
Set the prompt procedure associated with port to prompter,
which must be a one-argument procedure taking an input port,
and returning a string.
Function: default-prompter port
The default prompt procedure. It returns
Function: input-port-line-number port
Get the line number of the current line of port,
which must be a (non-binary) input port.
The initial line is line 1.
Function: set-input-port-line-number! port num
Set line number of the current line of port to num.
Function: input-port-column-number port
Get the column number of the current line of port,
which must be a (non-binary) input port.
The initial column is column 1.
Function: input-port-read-state port
Returns a character indicating the current
A symbol that controls how
Controls how bytes in external files are converted to/from internal
Unicode characters. Can be either a symbol or a boolean.
If
This variable is checked when the file is opened; not when actually
reading or writing. Here is an example of how you can safely
change the encoding temporarily:
Function: catch key thunk handler
Invoke thunk in the dynamic context of handler for
exceptions matching key. If thunk throws to the symbol key,
then handler is invoked this way:
key may be a symbol. The thunk takes no
arguments. If thunk returns normally, that is the return value of
Handler is invoked outside the scope of its own
If the key is
Function: throw key &rest args ...
Invoke the catch form matching key, passing args to the
handler.
If the key is a symbol it will match catches of the same
symbol or of #t.
If there is no handler at all, an error is signaled.
procedure: error message args ...
Raise an error with key
Function: primitive-throw exception
Throws the exception, which must be an instance of a sub-class
of
Syntax: try-finally body handler
Evaluate body, and return its result.
However, before it returns, evaluate handler.
Even if body returns abnormally (by throwing an exception),
handler is evaluated.
(This is implemented just like Java's
Syntax: try-catch body handler ...
Evaluate body, in the conect of the given handler-specs.
Each handler has the form:
Once a handler is selected,
the var is bound to the thrown exception, and the exp in
the handler are executed. The result of the
(This is implemented just like Java's
Function: dynamic-wind in-guard thunk out-guard
All three arguments must be 0-argument procedures.
First calls in-guard, then thunk, then out-guard.
The result of the expression is that of thunk.
If thunk is exited abnormally (by throwing an exception or
invoking a continuation), out-guard is called.
If the continuation of the dynamic-wind is re-entered (which
is not yet possible in Kawa), the in-guard is called again.
This function will be in R5RS.
Function: eval expression [environment]
The default for environment is the result
of
This procedure returns an environment that contains no variable bindings,
but contains (syntactic) bindings for all the syntactic keywords.
The effect of assigning to a variable in this environment (such
as
Function: scheme-report-environment version
The version must be an exact non-negative inetger corresponding to
a version of one of the Revisedversion Reports on Scheme.
The procedure returns an environment that contains exactly the set of
bindings specified in the corresponding report.
This implementation supports version that is 4 or 5.
The effect of assigning to a variable in this environment (such
as
Function: interaction-environment
This procedure return an environment that contains implementation-defined
bindings, as well as top-level user bindings.
Function: environment-bound? environment symbol
Return true
Syntax: fluid-let ((variable init) ...) body ...
Evaluate the init expressions.
Then modify the dynamic bindings for the variables to the
values of the init expressions, and evaluate the body expressions.
Return the result of the last expression in body.
Before returning, restore the original bindings.
The temporary bindings are only visible in the current thread, and its
descendent threads.
As a super-class of numbers, Kawa also provides quantities.
A quantity is a product of a unit and a pure number.
The number part can be an arbitrary complex number.
The unit is a product of integer powers of base units,
such as meter or second.
Kawa quantities are a generalization of the quantities in DSSSL,
which only has length-derived quantities.
The precise syntax of quantity literals may change,
but some examples are
True iff object is a quantity. Note that all numbers are
quantities, but not the other way round.
Returns the pure number part of the quantity q, relative to
primitive (base) units.
If q is a number, returns q.
If q is a unit, yields the magitude of q relative to base units.
Returns the unit of the quantity q.
If q is a number, returns the empty unit.
Function: make-quantity x unit
Returns the product of x (a pure number) and unit.
You can specify a string instead of unit, such as
Syntax: define-unit unit-name expression
Define unit-name as a unit (that can be used in literals)
equal to the quantity expression.
There is a very preliminary interface to create parallel threads.
The interface is similar to the standard
So far, little or no effort has been made into making Kawa
thread-safe. There are no per-thread bindings, and
the current input and output parts are global.
That needs to change.
Creates a new thread that evaluates expression.
The standard
Suspends the current thread for the specified time.
The time can be either a pure number (in secords),
or a quantity whose unit is a time unit (such as
Kawa has first-class types, that you can use in various ways.
Currently, these are mainly useful for interfacing with primitive Java methods
(such as
These types are bound to identifiers having the form
To find which Java classes these types map into, look in
Note that the value of these variables are instances
of
An arbitrary Scheme value - and hence an arbitrary Java object.
The type of Scheme numbers.
The type of Scheme integers.
The type of Scheme symbols.
The type of keyword values. See section Keywords.
The type of Scheme lists (pure and impure, including the empty list).
The type of Scheme pairs. This is a sub-type of
The type of (mutable) Scheme strings.
This is not the same as (non-mutable) Java strings
(which happen to be the same as
The type of Scheme vectors.
The type of Scheme procedures.
The type of Scheme input ports.
The type of Scheme output ports.
More will be added later.
In addition, any Java type can be named using this syntax.
For example
Function: make-process command envp
Creates a
Runs the specified command, and waits for it to finish.
Returns the return code from the command. The return code is an integer,
where 0 conventionally means successful completion.
The command can be any of the types handled by
The value of this variable should be a one-argument procedure.
It is used to convert a command from a Scheme string to a Java
array of the constituent "words".
The default binding, on Unix-like systems, returns a new command to
invoke
Function: tokenize-string-to-string-array command
Uses a
Function: scheme-implementation-version
Returns the Kawa version number as a string.
Returns a new (interned) symbol each time it is called.
The symbol names are implementation-dependent.
Syntax: defmacro name lambda-list form ...
Defines an old-style macro a la Common Lisp,
and installs
If you define a macro with
Variable: command-line-arguments
Any command-line arguments (following flags processed by Kawa itself)
are assigned to the global variable `command-line-arguments',
which is a vector of strings.
A string containing the home directory of the user.
Exits the Kawa interpreter, and ends the Java session.
The integer value code is returned to the operating
system. If code is not specified, zero is returned,
indicating normal (non-error) termination.
Function: scheme-window [shared]
Create a read-eval-print-loop in a new top-level window.
If shared is true, it uses the same environment as the
current
You can create multiple top-level window that can co-exist.
They run in separate threads.
Function: apply proc [arg1 ...] args
Args must be a sequence (list, vector, or string) or a
primitive Java array.
(This is an extension over standard Scheme, which requires that
args be a list.)
Calls the proc (which must be a procedure), using as arguments
the arg1... values plus all the elements of args.
Syntax: constant-fold proc arg1 ...
Same as
Syntax: when condition form...
If condition is true, evaluate each form in order,
returning the value of the last one.
Syntax: unless condition form...
If condition is false, evaluate each form in order,
returning the value of the last one.
Function: vector-append arg...
Creates a new vector, containing the elements from all the args
appended together. Each arg may be a vector or a list.
Function: instance? value type
Returns
Converts or coerces value to a value of type type.
Throws an exception if that cannot be done.
Not supported for type to be a primitive type such as
All Scheme functions and source files are invisibly compiled
into internal Java byte-codes.
A traditional evaluator is only used for top-level directly entered
expressions outside a lambda. (It would have been simpler
to also byte-compile top-level expressions by surrounding them
by a dummy lambda. However, this would create a new Class object
in the Java VM for every top-level expression. This is undesirable
unless you have a VM that can garbage collect Class objects.)
To save speed when loading large Scheme source files, you probably
want to pre-compile them and save them on your local disk.
There are two ways to do this.
You can compile a Scheme source file to a single archive file.
You do this using the
Alternatively, you can compile a Scheme source file to a
collection of `.class' files.
You then use the standard Java class loading mechanism to load the code.
The Java "verifier" does not need to get run, which makes
loading a little faster.
The compiled class files do have to be installed be installed somewhere
in the
To byte-compile a file `foo.scm' do:
This will create `foo.zip', which contains byte-compiled "j-code"
that implements `foo.scm'.
You can later do:
This will load `foo.zip', which should have the same effect as
loading `foo.scm', except you will get the byte-compiled versions.
Invoking `kawa' (or `java kawa.repl') with
the `-C' flag will compile
a `.scm' source file into one or more `.class' files.
You run it as follows:
Note the `-C' must come last, because `Kawa' processes the
arguments and options in order,
Here:
When you actually want to load the classes, the outdirectory
must be in your `CLASSPATH'.
You can use the standard
If you are compiling a Scheme source file (say `foosrc.scm')
that uses macros defined in some other file (say `macs.scm'),
you need to make sure the definitions are visible to the compiler.
One way to do that is with the `-f':
A Java application is a Java class with a special method
(whose name is
Kawa has extensive features so you can work with Java objects
and call Java methods,
All Scheme values are implemented by sub-classes of `java.lang.Object'.
Scheme symbols are implemented using
Scheme integers are implemented by
A Scheme "flonum" is implemented by
A Scheme pair is implemented by
A Scheme vector is implemented by
Scheme characters are implemented using
Scheme strings are implemented using
Scheme procedures are all sub-classes of
Kawa provides a simple yet powerful "Foreign Function Interface",
which allows you to call any (virtual or static) Java method
as if it were a Scheme procedure.
These primitives require you to specify the parameter and return types.
Type specifications are currently required to be string literals
or one of the standard types (see section Standard Types).
A type specifier can be a fully-qualified Java class name
(for example
A type specifier can also be one of the primitive Java types.
The numeric types
Syntax: primitive-constructor class (argtype ...)
Returns a new anonymous procedure, which when called will create
a new object of the specified class, and will then call the
constructor matching the specified argument types.
Syntax: primitive-virtual-method class method rtype (argtype ...)
Returns a new anonymous procedure, which when called will
invoke the instance method whose name is the string method
in the class whose name is class.
Syntax: primitive-static-method class method rtype (argtype ...)
Returns a new anonymous procedure, which when called will
invoke the static method whose name is the string method
in the class whose name is class.
Syntax: primitive-interface-method interface method rtype (argtype ...)
Returns a new anonymous procedure, which when called will
invoke the matching method from the interface whose name is interface.
The macros return procedure values, just like
Some examples using these primitives are `vectors.scm'
and `characters.scm' the directory `kawa/lib' in
the Kawa sources.
The following macros evaluate to procedures that can be used to
access or change the fields of objects or static fields.
The compiler can inline each to a single bytecode instruction
(not counting type conversion).
Syntax: primitive-get-field class fname ftype
Use this to access a field named fname having type type in
class class. Evaluates to a new one-argument procedure,
whose argument is a reference to an object of the specified class.
Calling that procedure returns the value of the specified field.
Syntax: primitive-set-field class fname ftype
Use this to change a field named fname having type type in
class class. Evaluates to a new two-argument procedure,
whose first argument is a reference to an object of the
specified class, and the second argument is the new value.
Calling that procedure sets the field to the specified value.
(This macro's name does not end in a `!', because it does not actually
set the field. Rather, it returns a function for setting the field.)
Syntax: primitive-get-static class fname ftype
Like
Syntax: primitive-set-static class fname ftype
Like
The following macros evaluate to procedures that can be used to
manipulate primitive Java array objects.
The compiler can inline each to a single bytecode instruction
(not counting type conversion).
Syntax: primitive-array-new element-type
Evaluates to a one-argument procedure. Applying the resulting procedure to
an integer count allocates a new Java array of the specified length,
and whose elements have type element-type.
Syntax: primitive-array-set element-type
Evaluates to a three-argument procedure. The first argument of
the resulting procedure must be an array whose elements have type
element-type; the second argument is an index; and the third
argument is a value (coercible to element-type) which replaces
the value specified by the index in the given array.
Syntax: primitive-array-set element-type
Evaluates to a two-argument procedure. The first argument of
the resulting procedure must be an array whose elements have type
element-type; the second argument is an index.
Applying the procedure returns the element at the specified index.
Syntax: primitive-array-new element-type
Evaluates to a one-argument procedure. The argument of
the resulting procedure must be an array whose elements have type
element-type.
Applying the procedure returns the length of the array.
The "top" class created by
If this text is in the file
This will cause the actions in
The following methods are recommended if you need to evaluate a
Scheme expression from a Java method.
(Some details (such as the `throws' lists) may change.)
Static method: Object Scheme.eval (InPort port, Environment env)
Read expressions from port, and evaluate them in the
env environment, until end-of-file is reached.
Return the value of the last expression,
or
Static method: Object Scheme.eval (String string, Environment env)
Read expressions from string, and evaluate them in the
env environment, until the end of the string is reached.
Return the value of the last expression,
or
Static method: Object Scheme.eval (Object sexpr, Environment env)
The sexpr is an S-expression (as may be returned by
For the
If you have a problem installing or using Kawa,
send mail to
This mailing list is used for reporting bugs, patches, discussing
changes to Kawa, and announcing snapshots. If you wish to subscribe
(or later unsubscribe), send a request to
Messages to the mailing list are now
@uref{http://www.cygnus.com/ml/kawa/, archived}.
This is the license for the Kawa software:
Note that the Kawa distribution includes two
packages @uref{http:../gnu.bytecode/,gnu.bytecode}
and @uref{http:../gnu.math/,gnu.math}
which have different terms than Kawa itself
(but which impose no restrictions as long as you do not modify
those two packages).
In general, If the license of Kawa or asociated packages causes
difficulties, let me know.
This software is copyrighted by Per Bothner, Cygnus Support,
R. Alexander Milowski, Copernican Solutions Incorporated, and other parties.
The following terms apply to all files associated with the software
unless explicitly disclaimed in individual files.
The authors hereby grant permission to use, copy, modify, distribute,
and license this software and its documentation for any purpose, provided
that existing copyright notices are retained in all copies and that this
notice is included verbatim in any distributions. No written agreement,
license, or royalty fee is required for any of the authorized uses.
Modifications to this software may be copyrighted by their authors
and need not follow the licensing terms described here, provided that
the new terms are clearly indicated on the first page of each file where
they apply.
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
MODIFICATIONS.
Here is the license for this manual:
Copyright (C) 1996, 1997 Per Bothner
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
are preserved on all copies.
Permission is granted to copy and distribute modified versions of this
manual under the conditions for verbatim copying, provided that the entire
resulting derived work is distributed under the terms of a permission
notice identical to this one.
Permission is granted to copy and distribute translations of this manual
into another language, under the above conditions for modified versions,
except that this permission notice may be stated in a translation approved
by the author.
gnu.bytecode
}
and @uref{http:../gnu.math/,gnu.math
} are used by Kawa,
and distributed with it, but may be independently useful.
Features
external-procedure
,
the time-relationed procedures, and character name escapes in
string literals. Also, Kawa is not generally tail-recursive.
From the full expression language, Kawa additionally is missing
format-number
, format-number-list
, and language objects.
Quantities, keyword values, and the expanded lambda
form
(with optional and keyword parameters) are supported.
Getting Kawa
.zip
archive of the pre-compiled classes is in
here.
.deb
Debian package file of Kawa.
Building and installing Kawa
Getting and running Java
java
is the Java interpreter.
The program javac
is the Java compiler,
and is needed if you want to compile the source release yourself.
Both programs must be in your PATH
.
CLASSPATH
so it includes both the
current directory, and the standard Java library.
After you have installed Kawa, the CLASSPATH
needs to
include wherever you installed Kawa.
$JDK
,
and you are using a Bourne-shell compatible shell
(/bin/sh, ksh, bash, and some others) you can set both variables thus:
PATH=$JDK/bin:$PATH
CLASSPATH=.:$JDK/lib/classes.zip
export PATH CLASSPATH
Installing and using the binary distribution
.zip
archive
`kawa-1.6.1-compiled.zip'.
/usr/local/lib/kawa-compiled.zip
.
CLASSPATH
so it includes the Kawa archive. On Unix, using a Bourne-style shell:
CLASSPATH=/usr/local/lib/kawa-compiled.zip
export CLASSPATH
classpath
in a DOS console.
For example:
set classpath=\kawa\kawa-compiled.zip
java kawa.repl
Installing and using the source distribution
The Kawa release normally comes as a gzip-compressed tar file named
`kawa-1.6.1.tar.gz'.
tar xzf kawa-1.6.1.tar.gz
cd kawa-1.6.1
./configure
make install
will install the
compiled `.class' files into /usr/local/share/java
.
If you want them
to be installed someplace else, such as $PREFIX/share/java
, then
specify that when you run configure:
./configure --prefix $PREFIX
make
This assume that `java' and `javac' are the java interpreter
and compiler, respectively.
If you are using the Kaffe free Java interpreter,
you need to instead say:
make JAVA=kaffe
java kawa.repl
(cd testsuite; make check)
make install
$PREFIX/share/java
(and its
sub-directories). Here $PREFIX
is the directory you specified
to configure with the --prefix
option, or /usr/local
if you
did not specify a --prefix
option.
CLASSPATH
so
that $PREFIX/share/java
is on the path:
CLASSPATH=$PREFIX/share/java
export CLASSPATH
This is done automatically if you use the `kawa' script.
How to start up and run Kawa
$PREFIX/bin
is in your $PATH
,
just do:
kawa
However, `kawa' only works if you have a Unix-like environment.
PATH
.
You must also make sure that the kawa/repl.class
file,
the rest of the Kawa packages, and the standard Java
packages can be found by searching CLASSPATH.
See section Getting and running Java.
java kawa.repl
Command-line arguments
kawa -e '(display (+ 12 4))(newline)'
or:
java kawa.repl -e '(display (+ 12 4))(newline)'
Either causes Kawa to print `16', and then exit.
.kawarc.scm
on Unix-like systems
(those for which the file separator is '/'
),
and kawarc.scm
on other systems.
This is done before the read-eval-print loop
or before the first -f
or -c
argument. (It is not run
for a -e
command, to allow you to set options to override
the defaults.)
~/.kawarc.scm
init file to be run.
~/.kawarc.scm
init file to be run.
-e (scheme-window #t)
.
You can specify multiple `-w' options, and also use `-s'.
Running a Command Interpreter in a new Window
java kawa.repl -w
Exiting Kawa
Kawa normally keeps running as long as there is an active
read-eval-print loop still awaiting input or there is an unfinished
other computation (such as requested by a `-e' of `-f' option).
#!eof
at top level. This is recognized as end-of-file.
Unfortunately, due to thread-related complications, just typing
an end-of-file character (normally ctrl/D until Unix), will not work.
exit
procedure (with 0 or 1 integer arguments).
Features of R5RS not implemented
set!
) to the procedure binding.
define-syntax
primitive is provided, but has some bugs
making it not properly hygienic. Neither let-syntax
nor letrec-syntax
are implemented.
Extensions
Multiple values
Special named constants
#!eof
, you should quote it.
(values)
.
If this is the value of an expression in a read-eval-print loop,
nothing is printed.
null
value. This is not really a Scheme value,
but is useful when interfacing to low-level Java code.
Keywords
keyword = identifier:
#t
if obj is a keyword, and otherwise returns #f
.
#\:
.
#\:
.)
Optional and keyword lambda parameters
lambda-expression = (lambda (formal-arguments) body)
You can of course also use the extended format in a define
:
(define (name formal-arguments) body)
formal-arguments =
req-opt-args . rest-arg or:
req-opt-args rest-key-args
req-opt-args = req-arg* (#!optional opt-arg*)?
rest-key-args = (#!rest rest-arg)? (#!key key-arg*)?
opt-arg = variable | (variable initializer)
req-arg = variable
key-arg = variable | (variable initializer)
rest-arg = variable
#f
. The initializer is evaluated in an
environment in which all the previous formal parameters have been bound.
#!key
was specified, then there shall be an even number of
remaining actual arguments. These are interpreted as a series of pairs,
where the first member of each pair is a keyword specifying the argument name,
and the second is the corresponding value. It shall be an error if the first
member of a pair is not a keyword. It shall be an error if the argument name
is not the same as a variable in a key-args, unless there
is a rest-arg. If the same argument name occurs more than once
in the list of actual arguments, then the first value is used.
If there is no actual argument for a particular key-arg,
then the variable is bound
to the corresponding initializer, if one was specified, and
otherwise to #f
. The initializer is evaluated in an
environment in which all the previous formal parameters have been bound.
Logical Number Operations
(not (zero? (logand i j)))
,
but is more efficient.
#t
iff the bit numbered pos in i is one.
j>0
, and
a "right" shift if j<0
.
(floor (* i (expt 2 j)))
.
arithmetic-shift
.
(arithmetic-shift (bitand n (bitnot (arithmetic-shift -1 end))) (- start))
.
Records
Record
.
These procedures use the Java 1.1 reflection facility.
Class
object that extends
the Record
class. Each record field is implemented as
a public Java instance field.
make-record-type
that created the type represented by rtd;
if the field-names argument is provided, it is an error if it
contains any duplicates or any symbols not in the default list.
Class
that has a public default
constructor, as long as the field-names are public instance
fields. (The fields should have type Object
-- unless you
know what you are doing!)
make-record-type
that created the type represented by rtd. (In Kawa,
the field-name can be any public non-final Object field
of the Class
rtd.)
make-record-type
that created the type represented by
rtd. (In Kawa,
the field-name can be any public non-final Object field
of the Class
rtd.)
kawa.lang.Record
.
record-predicate
, the resulting predicate would return a true
value when passed the given record. In Kawa, record may be any object,
and the value returned is the class of the object.
eqv?
to the type-name argument given in
the call to make-record-type
that created the type represented by
rtd.equal?
to the
field-names argument given in the call to make-record-type
that
created the type represented by rtd.File System Interface
#f
on error, but may change to be more compatible
with scsh.)
Ports
(current-output-port)
.
"#|kawa:L|# "
, where
L is the current line number of port.
When reading a continuation line, the result
is "#|C---:L|# "
, where C
is the character returned
by (input-port-read-state port)
.
The prompt has the form of a comment to make it easier to cut-and-paste.
read
state of the port.
Returns #\Return
if not current doing a read,
#\"
if reading a string; #\|
if reading a comment; #\(
if inside a list; and #\Space
when otherwise in a read
.
The result is intended for use by prompt prcedures, and is not necessarily
correct except when reading a new-line.
read
handles letters when reading a symbol.
If the first letter is `U', then letters in symbols are upper-cased.
If the first letter is `D' or `L', then letters
in symbols are down-cased.
If the first letter is `I', then the case of letters in symbols
is inverted.
Otherwise (the default), the letter is not changed.
(Letters following a `\' are always unchanged.)
port-char-encoding
is #f
, the file is assumed
to be a binary file and no conversion is done.
Otherwise, the file is a text file. The default is #t
, which
uses a locale-dependent conversion. If port-char-encoding
is a symbol, it must be the name of a character encoding known to Java.
For all text files (that is if port-char-encoding
is not #f
),
on input a #\Return
character or
a #\Return
followed by #\Newline
are converted into plain #\Newline
.
(define (open-binary-input-file name)
(fluid-let ((port-char-encoding #f)) (open-input-file name)))
Signalling and recovering from exceptions
(handler key args ...)
catch
.
catch
. If
handler again throws to the same key, a new handler from further
up the call chain is invoked.
#t
, then a throw to any symbol will match
this call to catch
.
misc-error
and a message constructed by
displaying msg and writing args.
This normally prints a stack trace, and brings you back to
the top level, or exits kawa if you are not running interactively.
<java.lang.Throwable>
.
try
-finally
.)
var type exp ...
If an exception is thrown in body, the first handle-spec
is selected such that the thrown exception is an instance of
the handler's type. If no handler is selected,
the exception is propagated through the dynamic execution context
until a matching handler is found. (If no matching handler
is found, then an error message is printed, and the computation terminated.)
try-catch
is the result of body if no exception is thrown, or the
value of the last exp in the selected handler if an
exception is thrown.
try
-catch
.)
Eval and Environments
eval
evaluates expression in the environment indicated
by environment.
(interaction-environment)
.
let
) is undefined.
car
) is undefined.
#t
if there is a binding for symbol
in environment; otherwise returns #f
.
Quantities
10pt
(10 points), 5s
(5 seconds),
and 4cm2
(4 square centimeters).
"cm"
or "s"
(seconds).
Threads
delay
/force
,
where a thread is basically the same as a promise, except that
evaluation may be in parallel.
force
function has generalized to also work
on threads. If waits for the thread's expression to finish
executing, and returns the result.
10s
).
Standard Types
primitive-virtual-function
, but they will be useful
for other purposes (such as declarating variables) later.
<TYPENAME>
.
(This syntax and most of the names are as in RScheme.)
kawa/lang/PrimProcedure.java
.
gnu.bytecode.Type
,
not (as you might at first expect) java.lang.Class
.
<list>
.
<symbol>
).
<java.lang.StringBuffer[]>
represents
an array of references to java.lang.StringBuffer
objects.
Processes
<java.lang.Process>
object, using the specified
command and envp.
The command is converted to an array of Java strings
(that is an object that has type <java.lang.String[]>
.
It can be a Scheme vector or list (whose elements should be
Java strings or Scheme strings); a Java array of Java strings;
or a Scheme string. In the latter case, the command is converted
using command-parse
.
The envp is process environment; it should be either
a Java array of Java strings, or the special #!null
value.
make-process
.
"/bin/sh" "-c"
concatenated with the command string;
on non-Unix-systems, it is bound to tokenize-string-to-string-array
.
java.util.StringTokenizer
to parse the command string
into an array of words. This splits the command using spaces
to delimit words; there is no special processing for quotes or other
special characters.
(This is the same as what java.lang.Runtime.exec(String)
does.)
Miscellaneous
(lambda lambda-list form ...)
as the expansion function for name.
When the translator sees an application of name,
the expansion function is called with the rest of the application
as the actual arguments. The resulting object must be a Scheme
source form that is futher processed (it may be repeatedly macro-expanded).
defmacro
, you (currently) cannot use
the macro in the same compilation as the definition.
This restriction does not apply to macros defined by define-syntax
.
(interaction-environment)
; if not (the default),
a new top-level environment is created.
(proc arg1 ...)
, unless proc and
all the following arguments are compile-time constants.
(That is: They are either constant, or symbols that have a global
binding and no lexical binding.) In that case, proc
is applied to the arguments at compile-time, and the result replaces
the constant-fold
form. If the application raises an exception,
a compile-time error is reported.
For example:
(constant-fold vector 'a 'b 'c)
is equivalent to (quote #(a b c))
, assuming vector
has not been re-bound.
#t
iff value is an instance of type type.
(Undefined if type is a primitive type, such as <int>
.)
<int>
.
Compiling Scheme code to byte-codes
compile-file
function.
The result is a single file that you can move around and load
just like the .scm
source file. You just specify the name
of the archive file to the load
procedure.
Currently, the archive is a "zip" archive and has extension ".zip";
a future release will probably use "Java Archive" (jar) files.
The advantage of compiling to an archive is that it is simple
and transparent. A minor disadvantage is that it causes the
Java "verifier" to be run when functions are loaded from it,
which takes a little extra time.
CLASSPATH
.
Compiling Scheme to an archive file
(compile-file "foo.scm" "foo")
(load "foo")
Compiling Scheme to a set of .class files
kawa [-d outdirectory] [-P prefix] [-T topname] [--main] -C infile
main
method so that the resulting "top" class can
be used as a stand-alone application. See section Compiling Scheme to a standalone application.
load
function to load the code,
by specifying the top-level class, either as a file name
(relative to outdirectory) or a class name.
E.g. if you did:
kawa -d /usr/local/share/java -P my.lib. -T foo -C foosrc.scm
you can use either:
(load "my.lib.foo")
or:
(load "my/lib/foo.class")
kawa -f macs.scm -C foosrc.scm
Compiling Scheme to a standalone application
main
). The application can be invoked directly
by naming it in the Java command.
If you want to generate an application from a Scheme program,
create a Scheme source file with the definitions you need, plus
the top-level actions that you want the application to execute.
You can compile in the regular way decribed in the previous section, but add
the --main
option. For example,
assuming your Scheme file is MyProgram.scm
:
kawa --main -C MyProgram.scm
This will create a MyProgram.class
which you can either load
(as decribed in the previous section), or invoke as an application:
java MyProgram [args]
Your Scheme program can access the command-line arguments args
by using the global variable `command-line-arguments'.
The Scheme-Java interface
Scheme types in Java
java.lang.String
.
(Don't be confused by the fact the Scheme sybols are represented
using Java Strings, while Scheme strings are represented by
kawa.lang.Scheme
. It is just that the semantics of Java strings
match Scheme symbols, but do not match mutable Scheme strings.)
Interned symbols are presented as interned Strings.
(Note that with JDK 1.1 string literals are automatically interned.)
kawa.math.IntNum
.
Use the make static function to create a new IntNum from an int or a long.
Use the intValue or longValue methods to get the int or long value of
an IntNum.
kawa.math.DFloNum
.
kawa.lang.Pair
.
kawa.lang.Vector
.
kawa.lang.Char
.
kawa.lang.FString
.
kawa.lang.Procedure
.
Normally each function (lambda expression) in the source code is
compiled to a separate sub-class of `Procedure'.
The "action" of a `Procedure' is invoked by using one of
the `apply*' methods: `apply0', `apply1',
`apply2', `apply3', `apply4', or `applyN'.
Various sub-class of `Procedure' provide defaults
for the various `apply*' methods. For example,
a `Procedure2' is used by 2-argument procedures.
The `Procedure2' class provides implementations of all
the `apply*' methods except `apply2',
which must be provided by any class that extends Procedure2
.
Calling Java methods from Scheme
<java.lang.StringBuffer>
). In that case,
the actual argument is cast at run time to the named class.
The specification <String>
is an exception:
It causes the toString
method of the actual
argument to be invoked.
<long>
, <int>
, <short>
,
<byte>
, <float>
, and <double>
are converted from the
corresponding Scheme number classes. Similarly, <char>
can be converted to and from Scheme characters. The type
boolean
matches any object, and the result is false
if and only if the actual argument is #f
.
The return type <void>
indicates that no value is returned.
lambda
.
If the macros are used directly as the procedure of a procedure call,
then kawa can inline the correct bytecodes to call the specified methods.
(Note also that neither macro
checks that there really is a method that matches the specification.)
Otherwise, the Java reflection facility is used.
Low-level Operations on Object Fields
primitive-get-field
, but used to access static fields.
Returns a zero-argument function, which when called returns
the value of the static field.
primitive-set-field
, but used to modify static fields.
Returns a one-argument function, which when called sets the
value of the static field to the argument.
Low-level Operations on Java Arrays
Loading a ModuleBody
kawa -C
(see section Compiling Scheme to a set of .class files)
extends the ModuleBody
class. It is actually fairly
easy to write a ModuleBody
by hand in Java, and you can
then use the Scheme load
procedure to cause arbitrary
actions. Here is an example.
(Note that the details are subject to change!)
package MyDev;
import kawa.lang.*;
class MyDevFunc extends Procedure2
{
public Object apply2 (Object arg1, Object arg2)
{
... stuff to control my device ...;
}
}
public class MyDevice extends ModuleBody
{
public Object run (Environment env)
throws WrongArguments, WrongType, GenericError, UnboundSymbol
{
... initialize my device here ...;
// Declare (handle-my-device x y) to call MyDevFunc.apply2 (x, y):
env.define ("handle-my-device", new MyDevFunc ());
// Return the void value (i.e. no value).
return Interpreter.voidObject;
}
}
MyDev/MyDevice.java
, and you compile
it with javac
, you will get MyDev/MyDevice.class
and MyDev/MyDevFunc.class
. Assuming the current directory
is in your CLASSPATH
, you can now do the following in Kawa:
(load "MyDev/MyDevice.class")
or:
(load "MyDev.MyDevice")
MyDevice.run
to be executed.
The current environment is passed in as the parameter env
.
One of those actions is to define the procedure handle-my-device
.
Evaluating Scheme expressions from Java
Interpreter.voidObject
if there is no expression.
Interpreter.voidObject
if there is no expression.
read
).
Evaluate it in the env environment, and return the result.
Environment
in most cases you could use
`Environment.current()'.
Reporting Bugs and the Kawa Mailing List
kawa@cygnus.com
kawa-request@cygnus.com
.
License
Parts of this manual were derived from the SLIB manual,
copyright (C) 1993, 1994 Todd R. Eigenschink and Aubrey Jaffer.
Parts of this manual were derived from ISO/EIC 10179:1996(E)
(Document Style and Specifical Language) - unknown copyright.