[[RunningChapter]]

Running Larceny
---------------

Larceny runs in any of four distinct modes:

    R5RS              traditional read/eval/print loop (the default)
    ERR5RS            ERR5RS read/eval/print loop
    R6RS              batch execution of R6RS top-level programs
    Scheme script     batch execution of R6RS Scheme scripts

These modes correspond to the four distinct kinds of Scheme
programs that are described by the current de facto standards
for Scheme.  (IEEE/ANSI Std 1178 is so similar to the R5RS
standard that Larceny implements both languages in R5RS mode.)

[[R5rsSection]]

R5RS mode
~~~~~~~~~

When you start Larceny in R5RS mode (the default), you
will be presented with a banner message and the
read-eval-print loop's prompt:

------------------------------------------------------------
    % larceny
    Larceny vX.Y "<version_name>" (MMM DD YYYY HH:MM:SS, ...)
    larceny.heap, built ...
        
    > 
------------------------------------------------------------

You can enter a Scheme expression at the prompt.
After a complete expression has been read, it will
be evaluated and its results printed.

[NOTE]
================================================================
In native Larceny, the expression is evaluated by
compiling it to native machine code, which is then executed.
In Petit Larceny, the expression is evaluated by
an interpreter because compiling to C, running the
C compiler, and loading the compiled C code would
take too long.  Interpreted code behaves like compiled code,
so most of what this manual says about the compiler is also
true of Petit Larceny's interpreter.
================================================================

By default, Larceny's Twobit compiler makes several
assumptions that allow it to generate faster code;
for example, the compiler assumes Scheme's standard
procedures will not be redefined.
To obtain strict conformance to R5RS semantics, see
the section of this user manual devoted to
<<PerformanceSection, performance>>.


[[Err5rsSection]]

ERR5RS mode
~~~~~~~~~~~

To interact with Larceny's ERR5RS read/eval/print loop,
specify the `-err5rs` option on Larceny's command line:

----------------------------------------------------------------
    % larceny -err5rs
    Larceny v0.95 "First Safety" (...)
    ERR5RS mode (no libraries have been imported)
----------------------------------------------------------------

Since no libraries have been imported, the only forms you
can evaluate are constant literals, variable references
(but no variables have been imported!), procedure calls
(but no procedure values are accessible!), library
definitions, and import forms.  The first thing you'll
want to do is to import some libraries, such as:

----------------------------------------------------------------
    > (import (rnrs base)
              (rnrs io simple)
              (err5rs records syntactic))
----------------------------------------------------------------

Once you have imported `(rnrs base)` or a composite library
that includes it, you can evaluate definitions and use
all other syntax and variables you have imported.


[[Err5rsAutomaticLoadingSection]]

==== Automatic loading

As an extension to ERR5RS, Larceny attempts to load
libraries automatically when they are first imported.
Autoloading makes interactive development and
<<CompilingChapter,separate compilation>>
much more convenient.

All of Larceny's
<<Err5rsPreDefinedSection,predefined libraries>>
can be autoloaded.

To enable autoloading of other ERR5RS/R6RS libraries,
you can:

- use the <<R6RSLibraryPathSection, `-path` command-line option>>
- use the <<R6RSLibraryVariableSection, `LARCENY_LIBPATH`>> environment variable
- use <<current-require-path,`current-require-path`>>
- edit `startup.sch` in Larceny's root directory
- add the libraries to Larceny's `lib` directory


[[Err5rsDynamicLoadingSection]]

==== Dynamic loading

Larceny automatically loads ERR5RS/R6RS libraries when
they are first imported.  This is usually the most
convenient way to load a library, but autoloading
can't be used to load a top-level program.  Explicit
loading is needed for top-level programs, for libraries
that don't reside in Larceny's
<<current-require-path,`current-require-path`>>,
and for libraries that are defined in files whose names
do not follow Larceny's
<<NamingChapter,standard naming conventions>>.

Explicit loading is the only portable way for ERR5RS
programs to load a library.

Explicit loading also makes it possible to write portable
programs whose source files conform to both the R5RS and
ERR5RS.  Two different configuration files, one for the
R5RS and one for ERR5RS, can perform all of the imports
and loads needed to run the program.

For explicit loading of nonstandard libraries, top-level
programs, or unadorned R5RS-style code from a file, you
must first import a suitable load procedure:

----------------------------------------------------------------
    > (import (err5rs load))
----------------------------------------------------------------

Loading a library does not automatically import it.
To use the variables and syntax that are exported by a
library, you must import that library explicitly:

----------------------------------------------------------------
    > (load "lib/R6RS/larceny/benchmarking.sls")
    > (import (larceny benchmarking))
    > (time (vector-for-each + (make-vector 1000000 0)))
    Words allocated: 3095752
    Words reclaimed: 0
    Elapsed time...: 111 ms (User: 104 ms; System: 8 ms)
    Elapsed GC time: 4 ms (CPU: 4 in 8 collections.)
----------------------------------------------------------------

In Larceny, you may omit the call to `load` because the
`(larceny benchmarking)` library will be autoloaded when
it is imported.  In other ERR5RS systems, however, you
may have to load all of the nonstandard libraries that will
be imported by a top-level program or library before you
load that top-level program or library.

You do not have to import those libraries into the ERR5RS
top level, however, unless you want to use the variables
and syntax exported by those libraries in the expressions
and definitions you evaluate at the top level.


[[Err5rsPreDefinedSection]]

==== Predefined libraries

Larceny predefines several nonstandard libraries in addition
to the standard ERR5RS and R6RS libraries, and autoloads them
for your convenience.  The predefined, autoloadable libraries
include:

R6RS standard libraries:

    (rnrs base (6))                        ; R6RS chapter 9
    (rnrs unicode (6))                     ; R6RS library chapter 1
    (rnrs bytevectors (6))                 ; R6RS library chapter 2
    (rnrs lists (6))                       ; R6RS library chapter 3
    (rnrs sorting (6))                     ; R6RS library chapter 4
    (rnrs control (6))                     ; R6RS library chapter 5
    (rnrs exceptions (6))                  ; R6RS library section 7.1
    (rnrs conditions (6))                  ; R6RS library sections 7.2 and 7.3
    (rnrs io ports (6))                    ; R6RS library sections 8.1 and 8.2
    (rnrs io simple (6))                   ; R6RS library sections 8.1 and 8.3
    (rnrs files (6))                       ; R6RS library chapter 9
    (rnrs programs (6))                    ; R6RS library chapter 10
    (rnrs arithmetic fixnums (6))          ; R6RS library section 11.2
    (rnrs arithmetic flonums (6))          ; R6RS library section 11.3
    (rnrs arithmetic bitwise (6))          ; R6RS library section 11.4
    (rnrs syntax-case (6))                 ; R6RS library chapter 12
    (rnrs hashtables (6))                  ; R6RS library chapter 13
    (rnrs enums)                           ; R6RS library chapter 14
    (rnrs (6))                             ; R6RS library chapter 15
    (rnrs eval (6))                        ; R6RS library chapter 16
    (rnrs mutable-pairs (6))               ; R6RS library chapter 17
    (rnrs mutable-strings (6))             ; R6RS library chapter 18
    (rnrs r5rs (6))                        ; R6RS library chapter 19

R6RS standard libraries that are autoloadable but deprecated in Larceny:

    (rnrs records procedural (6))          ; R6RS library section 6.3
    (rnrs records inspection (6))          ; R6RS library section 6.4
    (rnrs records syntactic (6))           ; R6RS library section 6.2

SRFI libraries (which follow the SRFI 97 naming convention):

    (srfi :1 lists)                        ; list library
    (srfi :2 and-let*)                     ; extended `and` and `let*`
    (srfi :5 let)                          ; extended version of `let`
    (srfi :6 basic-string-ports)           ; basic string ports
    (srfi :8 receive)                      ; binding to multiple values
    (srfi :9 records)                      ; defining record types
    (srfi :11 let-values)                  ; syntax for multiple values
    (srfi :13 strings)                     ; string libraries
    (srfi :14 char-set)                    ; character-set library
    (srfi :16 case-lambda)                 ; syntax for variable arity
    (srfi :17 generalized-set!)            ; generalized set!
    (srfi :19 time)                        ; time data types and procedures
    (srfi :23 error)                       ; error reporting mechanism
    (srfi :25 multi-dimensional-arrays)    ; multi-dimensional array primitives
    (srfi :26 cut)                         ; specializing without currying
    (srfi :27 random-bits)                 ; sources of random bits
    (srfi :28 basic-format-strings)        ; basic format strings
    (srfi :29 localization)                ; localization
    (srfi :38 with-shared-structure)       ; i/o for data with shared structure
    (srfi :39 parameters)                  ; parameter objects
    (srfi :41 streams)                     ; streams
    (srfi :42 eager-comprehensions)        ; eager comprehensions
    (srfi :43 vectors)                     ; vector library
    (srfi :45 lazy)                        ; iterative lazy algorithms
    (srfi :48 intermediate-format-strings) ; format
    (srfi :51 rest-values)                 ; rest values hackery
    (srfi :54 cat)                         ; still more formatting
    (srfi :59 vicinities)                  ; vicinity
    (srfi :61 cond)                        ; a more general cond clause
    (srfi :63 arrays)                      ; homogeneous, heterogeneous arrays
    (srfi :64 testing)                     ; an API for test suites
    (srfi :67 compare-procedures)          ; three-way comparison procedures
    (srfi :78 lightweight-testing)         ; lightweight testing
    (srfi :87 case)                        ; a more general case clause
    (srfi :98 os-environment-variables)    ; environment variables
    (srfi :99 records)                     ; ERR5RS records (composite library)
    (srfi :99 records procedural)          ; ERR5RS records (procedural API)
    (srfi :99 records inspection)          ; ERR5RS records (inspection API)
    (srif :99 records syntactic)           ; ERR5RS records (syntactic API)

SRFI libraries that are autoloadable but deprecated in Larceny,
usually because they have been superseded in whole or in part by
R6RS syntax or libraries:

    (srfi :60 integer-bits)                ; integers as bits
    (srfi :66 octet-vectors)               ; octet vectors
    (srfi :69 basic-hash-tables)           ; basic hash tables
    (srfi :71 let)                         ; extensions of let, let*, letrec
    (srfi :74 blobs)                       ; octet-addressed binary blocks
    (srfi :86 mu-and-nu)                   ; mu and nu simulating values etc
    (srfi :95 sorting-and-merging)         ; sorting and merging

Other autoloadable libraries:

    (err5rs records procedural)            ; ERR5RS records (procedural API)
    (err5rs records inspection)            ; ERR5RS records (inspection API)
    (err5rs records syntactic)             ; ERR5RS records (syntactic API)
    (err5rs load)                          ; ERR5RS load procedure
    (rnrs load)                            ; equivalent to (err5rs load)
    (larceny load)                         ; extension of (err5rs load)
    (larceny compiler)                     ; separate compilation (ERR5RS/R6RS)
    (larceny benchmarking)                 ; timing facilities
    (larceny profiling)                    ; profiling of Scheme code
    (larceny records printer)              ; custom printing of records
    (larceny shivers-syntax)               ; syntax favored by Olin Shivers
    (r5rs)                                 ; approximates the R5RS top level
    (explicit-renaming)                    ; macros with explicit renaming


[[ERR5RSLibraryPathSection]]

==== Library path

Larceny's autoload feature locates ERR5RS/R6RS libraries
by performing a depth-first search of the directories
that belong to Larceny's
<<current-require-path,`current-require-path`>>.
Libraries will not be autoloaded unless they are defined
in files whose names follow
<<LibraryTranslationSection, Larceny's standard conventions>>.

The
<<current-require-path,`current-require-path`>>
is initialized by the `startup.sch` file in Larceny's root
directory.

<<R6RSLibraryPathSection, Larceny's `-path` command-line option>>
adds one or more directories to the directories in the
<<current-require-path,`current-require-path`>>.

The <<R6RSLibraryVariableSection, `LARCENY_LIBPATH`>>
environment variable can also be used to add one or more directories
to the directories in the
<<current-require-path,`current-require-path`>>.


[[ERR5RSprimitivesSection]]

==== Importing Larceny's standard procedures

Any of Larceny's R5RS-mode top-level procedures can be imported
into an ERR5RS or R6RS library or program by using an import
declaration with a `primitives` clause that names the R5RS
procedures to be imported.  For example:

----------------------------------------------------------------
    (import (primitives random current-seconds
                        getenv setenv system
                        current-directory file-modification-time
                        system-features vector-like-cas!)
            (rnrs base)
            (rnrs control))
----------------------------------------------------------------

[WARNING]
================================================================
This feature is non-portable.
Other implementations of ERR5RS or the R6RS may not even
have an underlying implementation of the R5RS.
================================================================


[[R6rsSection]]

R6RS mode
~~~~~~~~~

To execute a top-level R6RS program that is contained
within a file named `pgm`, type:

----------------------------------------------------------------
    larceny -r6rs -program pgm
----------------------------------------------------------------

The `-program` option can be omitted, in which case
Larceny will read the top-level program from standard
input:

----------------------------------------------------------------
    larceny -r6rs < pgm
----------------------------------------------------------------

If you omit the `-program` option and do not redirect
standard input, then Larceny will wait patiently
for you to type a complete top-level program into
standard input, terminating it with an end-of-file.

You probably don't want to do that.  Had you wanted
to type R6RS code at Larceny, you'd be using ERR5RS
mode instead.

By default, Larceny's Twobit compiler uses settings
that make good sense for production code but violate
some absolute requirements of the R6RS.  For maximal
adherence to R6RS requirements (at the expense of
portability, interoperability, and/or performance),
see the discussion of
<<compiler-switches, `compiler-switches`>>
in the section on the
<<LarcenyCompilerSection, `(larceny compiler)`>>
library.


[[R6rsPreDefinedSection]]

==== Predefined libraries

The R6RS standard does not specify any way for a
top-level program to define its own libraries.
Portable R6RS programs are therefore limited to
importing a subset of the R6RS standard libraries.

As an extension to the R6RS, Larceny allows R6RS
top-level programs and Scheme scripts to import
any libraries that are
<<Err5rsPreDefinedSection,predefined in Larceny's ERR5RS mode>>.


[[R6RSLibraryPathSection]]

==== Library path

As another extension to the R6RS, Larceny allows
R6RS top-level programs to import any libraries
that can be found in the directories specified by the
`-path` option on Larceny's command line using
<<LibraryTranslationSection, Larceny's standard translation>>
from library names to file names.
On most systems, you can specify multiple directories
by separating them with a colon; under Windows, use a
semicolon as separator instead.  The first directory
listed will be searched first.

[TIP]
================================================================
If you have a set of portable libraries that run under more than
one implementation of the R6RS, and you want to have a special
version of some of those libraries for Larceny, you can put all
your portable versions in one directory and the Larceny-specific
versions in another.  When you run Larceny, use the `-path`
option and specify the Larceny-specific directory first.
================================================================

[NOTE]
================================================================
The `-path` option cannot be used by Scheme scripts,
because command-line options are passed along to the Scheme
script without being interpreted by the `scheme-script` processor.
================================================================

[WARNING]
================================================================
We emphasize that this extension is non-portable.
Other implementations of the R6RS may not provide
anything comparable to Larceny's `-path` option.
Even if they do, their mappings from library names
to file names may be incompatible with Larceny's.
================================================================


[[R6RSLibraryVariableSection]]

==== Library environment variable

As another extension to the R6RS, Larceny allows
R6RS top-level programs to import any libraries
that can be found in directories specified by the
`LARCENY_LIBPATH` environment variable.
The value of that environment variable should be
a string in the same format as for Larceny's `-path`
command-line option, described above.

[WARNING]
================================================================
We emphasize that this extension is non-portable.
Other implementations of the R6RS may not support
anything comparable to Larceny's `LARCENY_LIBPATH`
environment variable.
Even if they do, their mappings from library names
to file names may be incompatible with Larceny's.
================================================================


[[DefiningLibrariesSection]]

==== Defining libraries

As an extension to the R6RS, Larceny allows a top-level
program or Scheme script to define R6RS libraries within
the file that contains the top-level program or Scheme
script, before the import form that begins the top-level
program.  These libraries must be arranged so that no
library depends upon libraries that come later in the
file.

[WARNING]
================================================================
We emphasize that this extension is non-portable.
Other implementations of the R6RS may not allow
R6RS programs to define their own libraries.
================================================================


==== Importing procedures from Larceny's underlying R5RS system

As an extension to the R6RS, Larceny allows any of the
procedures that are predefined at top level in Larceny's
R5RS mode to be imported by using
<<ERR5RSprimitivesSection, a `primitives` clause>>
in an `import` declaration.

[WARNING]
================================================================
This extension is highly non-portable.
Other implementations of the R6RS may not even
have an underlying implementation of the R5RS.
================================================================


[[SchemeScriptsSection]]

Scheme scripts
~~~~~~~~~~~~~~

On most Unix systems (including MacOS X and Linux), Larceny's
`scheme-script` will execute Scheme scripts as described in R6RS
non-normative appendix D, with or without the optional script
header.  To make Scheme scripts executable in their own
right, without executing `scheme-script` directly, add Larceny's
root directory to your path as described in `doc/HOWTO-INSTALL`.

Suppose, for example, that `/home/myself/hello` is an R6RS
Scheme script whose first line is the optional script header
shown below:

----------------------------------------------------------------
#!/usr/bin/env scheme-script
----------------------------------------------------------------

If you do not have execute permission for this script,
or Larceny's root directory is not in your path,
you can still run the script from
Larceny's root directory as follows:
     
----------------------------------------------------------------
    % ./scheme-script /home/myself/hello
----------------------------------------------------------------

If you have execute permission for the script, and Larceny's
root directory is in your path, you can also run the
script as follows:

----------------------------------------------------------------
    % /home/myself/hello
----------------------------------------------------------------

If, in addition, the directory that contains the script is
in your path, you can run the script as follows:

----------------------------------------------------------------
    % hello
----------------------------------------------------------------

You may also pass command-line arguments to a Scheme script.

[WARNING]
================================================================
We emphasize that Scheme scripts are not portable.
Scheme scripts are specified only by a non-binding appendix
to the R6RS, not by the R6RS proper.
Other implementations of the R6RS may not support Scheme
scripts at all, or may give them a semantics incompatible
with Larceny's.
================================================================

On Unix systems, standard input and output can be redirected
in the usual way.  In Larceny, standard input corresponds to
the textual port initially returned by `current-input-port`,
and standard output corresponds to the textual port initially
returned by `current-output-port`.

[WARNING]
================================================================
We emphasize that redirection of standard input and output
is non-portable.
Other implementations of the R6RS may not allow redirection,
or may identify the standard input and output with ports
other than those initially returned by `current-input-port`
and `current-output-port`.
================================================================


[[R5rsScriptSection]]

R5RS scripting
~~~~~~~~~~~~~~

Suppose `hello.sch` contains the following R5RS code:

----------------------------------------------------------------
    (display "Hello world!")
    (newline)
    (exit)
----------------------------------------------------------------

You can run `hello.sch` as a script by executing Larceny as
follows:

----------------------------------------------------------------
    % larceny -nobanner -- hello.sch
----------------------------------------------------------------

You can redirect Larceny's standard input, in which case
you may want to eliminate the herald announcement and the
read/eval/print loop's prompt:

----------------------------------------------------------------
    % larceny -nobanner -- -e "(begin (herald #f) (repl-prompt values))" \
              < hello.sch
----------------------------------------------------------------

For an explanation of why that works, which may suggest other
creative uses of Larceny, ask for help:

----------------------------------------------------------------
    % larceny -help
----------------------------------------------------------------


[[ErrorsSection]]

Errors
~~~~~~

In R6RS modes, errors should result in an error message
followed by a clean exit from the program.

If your program encounters an error in an interactive mode
(R5RS or ERR5RS), it will enter the debugger; this is
believed to be a feature.

Despite its crudity, and to some extent because of it,
Larceny's debugger works at least as well with optimized
compiled code as with interpreted code.

If you type a question mark at the debugger prompt, the
debugger will print a help message.  That message is more
helpful if you understand the Twobit compiler and
Larceny's internal representations and invariants, but
this manual is not the place to explain those things.

The debugging context is saved so you can exit the debugger
and re-enter it from the main read/eval/print loop's prompt:
    
----------------------------------------------------------------    
    > (debug)
----------------------------------------------------------------    

The debugger is pretty much a prototype; you don't need to
tell us how bad it is.

Troubleshooting
~~~~~~~~~~~~~~~

==== Errors when starting Larceny

When attempting to run an R6RS program, you may see
a warning about "`loading source in favor of stale
fasl file`",
following by a long series of error messages about
syntactic keywords used as a variable, ending with
the kind of error you'd expect to see when a large
R6RS program is fed to a Scheme compiler that was
expecting to see R5RS-compatible code.  That means
the R6RS runtime and standard libraries were not
installed correctly, or their source files have been
touched or modified since they were last compiled.
To fix the problem,
<<CompilingStdLibSection, recompile the R6RS standard
libraries>> as described in step 4 of `doc/HOWTO-BUILD`.

The precompiled binary forms of Larceny should run on
most machines with the appropriate processor and operating
system, but the executable program "`larceny.bin`" may be
incompatible with very old or with very new versions of
the processor or operating system.  If that appears to be
the case, you should see whether a newer version of Larceny
fixes the problem.  If not, please report the problem
to us at `larceny@ccs.neu.edu`.
Please report success stories as well.


==== Errors when compiling the ERR5RS/R6RS runtime

If something goes wrong while
<<CompilingStdLibSection,compiling the ERR5RS/R6RS runtime>>,
make sure you are running the copy of Larceny you think
you are running and have read and write permission
for +lib/R6RS+, +lib/SRFI+, and all their subdirectories and files.
If you get an error message about something being
"`expanded against a different build of this library`",
then one or more of the compiled files in +lib/R6RS+ or +lib/SRFI+
or its subdirectories has gone
<<CompilingChapter,stale>>.
Removing all `.slfasl` files from +lib/R6RS+ and +lib/SRFI+ and
their subdirectories will eliminate the stale file(s).

[WARNING]
================================================================
Don't remove the `.sch` or `.sls` files.
================================================================


[[AutoLoadErrorsSection]]

==== Autoloading errors

If Larceny attempts to autoload an imported ERR5RS/R6RS
library but cannot find the library, then the library
may be defined in a file that doesn't follow
<<NamingChapter,Larceny's standard naming conventions>>.
Another possibility is that the `-path` option was
omitted or incorrect.

If an ERR5RS/R6RS library is compiled, then all compiled
libraries and top-level programs that depend upon it must
also be recompiled.  In particular, recompiling the standard
R6RS runtime will invalidate all compiled libraries and
top-level programs.  Larceny's `compile-stale` script
and the
<<compile-stale-libraries,`compile-stale-libraries`>>
procedure of `(larceny compiler)` make it convenient
to recompile all of the libraries and top-level
programs within any given directory in an order
consistent with their dependencies.



[[CrashesSection]]

==== Crashes

Please report all crashes with as much information is possible;
a backtrace from a debugger or a core dump is ideal (but please
do not mail the core dump without contacting us first).
Larceny's run-time system is compiled with full debugging
information by default and a debugger like GDB should be able
to provide at least some clues.


[[PerformanceSection]]

Performance
~~~~~~~~~~~

By default, Larceny's Twobit compiler makes several
assumptions that allow it to generate faster code;
for example, the compiler assumes Scheme's standard
procedures will not be redefined.

To disable certain compiler optimizations that are
incompatible with the R6RS, see the section that
describes the
<<LarcenyCompilerSection, `(larceny compiler)` library>>.

To obtain strict conformance to R5RS semantics at
the expense of slower code, evaluate the expression

----------------------------------------------------------------
    (compiler-switches 'standard)
----------------------------------------------------------------

To make the compiler generate faster code, you can promise not to
redefine standard procedures _and_ not to redefine any top-level
procedure while it is running. To make this promise, evaluate

----------------------------------------------------------------
        (compiler-switches 'fast-safe)
----------------------------------------------------------------

To view the current settings of Twobit's numerous compiler switches,
evaluate

----------------------------------------------------------------    
        (compiler-switches)
----------------------------------------------------------------

All of Twobit's compiler switches are procedures whose setting
can be changed by passing the new value of the switch as an
argument.

// benchmark-block-mode broken for a long time; commenting out below

////////////////////////////////////////////////////////////////////////
To make
<<compile-file,`compile-file`>>
generate faster code, you can promise that none
of the top-level variables that are defined within a file of Scheme
code are redefined or assigned outside of that file unless they are
redefined or assigned within the file. To make this promise, evaluate
    
    
        (benchmark-block-mode #t)
////////////////////////////////////////////////////////////////////////
    

For more information, evaluate

----------------------------------------------------------------
        (help)
----------------------------------------------------------------

[NOTE]
================================================================
Some of the help information that will be printed may be
irrelevant to the heap image you are using.
================================================================

