the local variable k is set to the return continuation for the
sleep function. This continuation is resumed by the timeout function that is
set by the setTimeout call. When the k continuation
is resumed, the sleep function "returns" to the caller, in the same state as
when it was called.

You can think of the value returned by the
function_continuation statement as being a copy of the call stack
(complete with all locals, parameters, and return addresses) at the time of
entry into the current function.

The resume statement

The resume statement takes either one or two arguments. The
first argument is an expression that returns a continuation to resume, and the
second, optional argument is an expression that returns the value for the
resumed continuation's function to return. If the optional second argument is
omitted, the function returns undefined. The syntax is:

The anonymous function in the setTimeout call above shows the
single-argument version of resume. The version of
sleep above will return undefined when its continuation is
resumed. The following, modified version of sleep will return
the number of milliseconds that it was called with:

Note that the first and second arguments to resume must be
separated by a left-pointing arrow token. This slightly-hokey syntax is
intended to convey that the value is passed into the continuation. Also it
makes the grammar unambiguous. :)

You can think of the resume statement as replacing the current
call stack with the stack saved in the continuation and then executing a
return statement. In particular, since they replace the call
stack, resume statements never return.

The suspend statement

The suspend statement suspends the current thread. It accepts no
arguments.

It is frequently the case that a function that captures its own
continuation in one form or another will want to delay its return until some
event has occurred. In the case of the fetchData function (see
the library section), we want to delay returning until
the data has returned from the server, so we save a continuation in an event
handler and execute a suspend statement. In the case of the
sleep function defined above, we want to delay returning until a
specified number of milliseconds have elapsed, so we save a continuation to be
resumed by a timer and then execute a suspend statement.

In the above definition of sleep, if the suspend
statement were missing, then sleep would actually return
twice: Once immediately, and once when the timer fired and resumed its
continuation.

You can think of the suspend statement as discarding the
current call stack.

Extended throw syntax

Of course, there's more ways for a function to exit than by returning. It is
also possible to leave a function by throwing an exception. To make it
possible to cause the function whose continuation was captured to throw an
exception, jwacs extends the syntax of the throw statement to
allow you to throw an exception "into" a continuation:

throw value -> continuation

The usual, 1-argument syntax still works as expected (ie, it throws an
exception in the current control context). However, there is now also an
optional second argument that specifies that an exception is to be thrown into
a continuation. Note that the second argument is separated from the first by
a right-facing arrow (indicating that the exception is thrown into the
exception).

For example:

function strictSleep(msec)
{
var k = function_continuation;
var s = (new Date).getTime();
setTimeout(function() {
var e = (new Date).getTime();
if(e - s < msec)
throw "setTimeout did not sleep for long enough!" -> k;
else
resume k
In the above code, strictSleep verifies that the timeout is not
called until at least msec milliseconds have elapsed. If enough
time has elapsed, then it returns msec as in the definition of
sleep above. However, if enough time has not elapsed, it
throws an error. Note that the exception is thrown into
strictSleep's return stack, not into the timeout
handler's stack, just as it is strictSleep that returns
msec when there is no error, and not the event handler.

You can think of the two-argument version of throw as replacing the current
call stack with the stack saved in the continuation argument, and then
throwing the exception argument.

The import statement

As a convenience, jwacs also provides an import statement for
linking together multiple source files. It has the following syntax:

import [type] "path";

The type can be one of jwacs, jw,
javascript, or js. The type is optional; if
it is omitted it will be inferred from the extension of the path.

The path should be a relative or absolute path to a Javascript or
jwacs source file to include in the web app. (See the compiler section for details of how absolute paths are
resolved). These paths will be passed straight through to the src
attribute of a <script> tag, so use absolute paths with care.

Imports of Javascript files will be turned directly into a
<script> tag in the output html file. jwacs files that are
imported will be transformed into Javascript files, which will then be
referenced from a <script> tag in the output html file.

Ex:

import "../lib/prototype.js";
import "utils.jw";

will cause a <script> tag to be omitted for
../lib/prototype.js and utils.js. The utils.jw
file will be transformed into utils.js.

Some caveats

When talking about replacing/discarding the call stack, it is sometimes
important to remember an important restriction: resume,
suspend, and extended throw statements all replace
the existing call stack, but only back to the nearest non-jwacs
function.

In practice, this means that event handlers called from non-jwacs code (eg,
handlers for built-in events and those called by third-party libraries) will
return undefined as soon as a resume,
suspend, or extended throw statement is executed.
In the following code:

The user will see an "alpha" alert box followed by a "beta" alert box 5
seconds later. However, the anonymous event handler for the "load" event will
return as soon as JwacsLib.sleep is executed, because
JwacsLib.sleep executes a suspend statement.

The jwacs parser does not perform semicolon insertion, so all jwacs
statements must be properly terminated.

Library

tk - this section still needs to be written.

Compiler

There are two ways to use the jwacs compiler: Either as a standalone binary
file that is invoked using command-line arguments, or as a Lisp function that
is invoked from a Lisp program or REPL.

The compiler is invoked on a single jwacs source file. That jwacs file may
contain imports to other Javascript or jwacs files. The compiler transforms
all imported jwacs files (and all jwacs files that they import, and so forth)
into standard Javascript.

Once Javascript files have been generated, an html file is generated by
adding <script> tags to a template html file. If no template
file exists, a standard template is used. (If you don't care about generating
an html file directly, you can ignore these aspects of the output and just use
the Javascript file that will be generated).

Using the jwacs executable

The jwacs executable has the following usage:

jwacs [options] main_source_file

The following options are available:

-t uri-path

URI-path of the template file to use. Default: the name of the main
source file, with new extension ".template". This file will be
generated if it doesn't exist.

-r uri-path

URI-path of the runtime script to use. Default: "jw-rt.js".
This file will be generated if it doesn't exist.

-o uri-path

URI-path of the output file to create. Default: the name of the main
source file with new extension ".html". (Note that this option
controls the name of the html output file, not of the Javascript file that
is generated from the main source file).

-p uri-path=directory[;uri-path=directory ...]

Specifies the mapping between absolute URI paths and the filesystem. See
URI path translation for details.

Using the build-app Lisp function

The build-app function takes one required argument and four
keyword arguments. The required argument is a path specifier designating the
main jwacs source file to transform. The keyword arguments closely mirror the
command-line arguments of the executable (or perhaps it's the other way
around):

:template-uripath

URI-path of the template file to use. Default: the name of the main
source file, with new extension ".template". This file will be
generated if it doesn't exist.

:runtime-uripath

URI-path of the runtime script to use. Default: "jw-rt.js".
This file will be generated if it doesn't exist.

:output-uripath

URI-path of the output file to create. Default: the name of the main
source file with new extension ".html". (Note that this option
controls the name of the html output file, not of the Javascript file that
is generated from the main source file).

:prefix-lookup

Specifies the mapping between absolute URI paths and the filesystem. See
URI path translation for details.

URI path translation

The paths specified by import statements
may be relative paths, in which case files are found in a straightforward
fashion, or they may be absolute paths. If they are absolute paths, then you
must specify a translation from absolute URI paths to file system paths.

When using the executable compiler, use the -p option to specify
the translation. When using the Lisp function, use the
:prefix-lookup keyword argument to specify a list of cons cells;
the CAR of each cell is the path prefix, and the CDR is a pathname that
specifies which filesystem directory that prefix represents.

For example, to indicate that absolute import paths beginning with
/lib/ refer to files in the /home/james/lib directory, and
all other absolute paths refer to files in the /home/james/jwacs
directory, pass the following arguments to the binary:

-p /lib=/home/james/lib;/=/home/james/jwacs

or pass the following list as the :prefix-lookup keyword argument
to build-app: