[[RunningChapter]]

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

For a summary of Larceny's command-line options, ask for help:

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


Larceny can run in any of these distinct modes:

    R7RS              R7RS read/eval/print loop or batch execution
    R6RS              batch execution of R7RS/R6RS top-level programs
    R5RS              R5RS read/eval/print loop or batch execution
    Scheme script     batch execution of R7RS/R6RS Scheme scripts

<<R7rsSection,R7RS mode>>
will run R7RS and R6RS programs,
and allows any combination of R7RS and R6RS libraries
to be imported.

<<R6rsSection,R6RS mode>>
is largely redundant with Larceny's R7RS mode, because
every reasonable R6RS program could just as well be
executed in R7RS mode.  There is only one difference between
those two modes: R6RS mode enforces many R6RS mandates that,
among other things, forbid read/eval/print loops and most
extensions to R6RS lexical syntax.

<<R5rsSection,R5RS mode>>
extends the Scheme language described by the R5RS and
IEEE/ANSI Std 1178 by adding R7RS/R6RS lexical syntax and most
of the procedures described by the newer R6RS and R7RS standards.

<<SchemeScriptsSection,Scheme scripts>>
are directly executable R7RS/R6RS programs.


[[Err5rsSection]]
[[R7rsSection]]

R7RS mode
~~~~~~~~~

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

----------------------------------------------------------------
    larceny pgm
----------------------------------------------------------------

or

----------------------------------------------------------------
    larceny -r7 pgm
----------------------------------------------------------------

To interact with Larceny's R7RS read/eval/print loop,
type the `-r7` and omit the program.
You will be presented with a banner message and the
read-eval-print loop's prompt:

----------------------------------------------------------------
    % larceny -r7
    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.
================================================================

The `(scheme base)` library has already been imported,
but you may want to import other libraries as well.
For example:

----------------------------------------------------------------
    > (import (scheme read)
              (scheme write)
              (scheme file)
              (scheme cxr)
              (scheme inexact)
              (scheme complex)
              (scheme char)
              (scheme load))
----------------------------------------------------------------

If you'd rather have Larceny import all of the standard R7RS Red
Edition and
R6RS libraries at startup, along with a few Larceny-specific
procedures, you can use the `-r7r6` option instead of `r7`:

----------------------------------------------------------------
    % larceny -r7r6
    Larceny v1.3 "Grain Alcohol and Rainwater" (...)
----------------------------------------------------------------

Using the `-r7r6` option is equivalent to using the `-r7`
option and then importing the `(larceny r7r6)` library.

[NOTE]
================================================================
Several name conflicts could not be resolved by adding R7RS extensions
to the conflicting R6RS procedure or syntax.  When the `-r7r6`
option is used, the `bytevector-copy!` and `remove` procedures are
imported with R7RS semantics, and the R6RS versions of those
procedures are renamed to `r6rs:bytevector-copy!` and
`r6rs:remove`; the `let-syntax` and `letrec-syntax` macros are
imported with R6RS splicing semantics, as with the `-r7` option,
but non-splicing versions of those macros are imported with the
names `r7rs:let-syntax` and `r7rs:letrec-syntax`.
================================================================

[NOTE]
================================================================
R7RS programs must import all libraries explicitly.  The `-r7` and
`-r7r6` options are therefore equivalent when a program is named
on the command line.  As stated in R7RS section 5.7, the implicit
import of `(scheme base)` is for convenience and ease of use in a
REPL, but R7RS programs do not have exactly the same semantics as
an R7RS REPL.
================================================================

[NOTE]
================================================================
Larceny's `-r7strict` option is similar to the `-r7` option, but
disables several of Larceny's extensions to the R7RS that improve
interoperability between R7RS and R6RS libraries and programs.
See the section describing
<<R7rsDeviationsSection,known deviations from the R7RS standard>>.
================================================================

[WARNING]
================================================================
R7RS programs may contain multiple `import` declarations, but all
of a program's `import` declarations must precede all of the
program's commands and definitions.  As of v1.3, Larceny does not
enforce that restriction unless `-r7strict` is requested, but
Larceny does scan the entire program for `import` declarations
and invokes the executable code of all imported libraries before
the program itself executes its first command or definition.
================================================================

The `features` procedure will return a list of all `cond-expand`
features, including the names of
<<R7rsPreDefinedSection,libraries currently available>>
for import.
That procedure reads
the source code for all library files found in your current
<<R7rsLibraryPathSection,Larceny library path>>, so don't be
surprised if it takes a few seconds.

----------------------------------------------------------------
    > (features)
    (r7rs r6rs larceny larceny-1.3
     exact-closed ratios exact-complex complex ieee-float
     full-unicode full-unicode-strings unicode-7
     ...
     (rnrs arithmetic bitwise (6))
     (rnrs arithmetic fixnums (6))
     (rnrs arithmetic flonums (6))
     (rnrs bytevectors (6))
     ...
     (scheme base)
     (scheme case-lambda)
     (scheme char)
     (scheme complex)
     (scheme cxr)
     ...
     (srfi 1)
     (srfi 1 lists)
     (srfi 2)
     ...)
----------------------------------------------------------------



[[R6rsSection]]

R6RS mode
~~~~~~~~~

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

----------------------------------------------------------------
    larceny -r6 pgm
----------------------------------------------------------------

If the program is omitted,
Larceny will read the top-level program from standard
input:

----------------------------------------------------------------
    larceny -r6 < pgm
----------------------------------------------------------------

If you omit the program 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 Larceny's R7RS
read/eval/print loop 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.
////////////////////////////////////////////////////////////////


[[R5rsSection]]
[[R5rsScriptSection]]

R5RS mode
~~~~~~~~~

To start Larceny in R5RS mode, use the `-r5` option:

------------------------------------------------------------
    % larceny -r5
------------------------------------------------------------

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 -r5 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
----------------------------------------------------------------
////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////
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>>.
////////////////////////////////////////////////////////////////


[[SchemeScriptsSection]]

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

On most Unix systems (including Linux and macOS), 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`,
or edit `scheme-script` to define `LARCENY_ROOT` and copy that
edited `scheme-script` to a directory in your path.

Suppose, for example, that `/home/myself/hello` is an R7RS/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 R7RS or 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 R7RS or 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`.
================================================================


[[ErrorsSection]]

Errors
~~~~~~

In R6RS mode, which is batch-only, 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 R7RS), 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

Although Larceny runs on x86-64 machines, it requires 32-bit
libraries that are not always installed on Linux and macOS
machines.  If those libraries are absent, the operating system
will probably give you a mysterious or misleading error message
when you try to run Larceny.  For example, the operating system's
loader may tell you "larceny.bin not found" even though it's
perfectly obvious that `larceny.bin` is present within Larceny's
root directory.  To install the necessary 32-bit libraries on
Linux machines with x86-compatible processors, someone with
superuser privileges must incant

----------------------------------------------------------------
    sudo apt-get install lib32z1
    sudo apt-get install libc6-i386
----------------------------------------------------------------

[WARNING]
================================================================
The names of those 32-bit packages have changed over time, and
may change again.
================================================================

For Macintosh machines, someone with administrative privileges
must install the
https://developer.apple.com/opensource/[Apple Developer Command Line Tools].

When attempting to run an R7RS/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
R7RS/R6RS program is fed to a Scheme compiler that was
expecting to see R5RS-compatible code.  That means
the R7RS/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, restore or
<<CompilingStdLibSection, recompile the R7RS standard
libraries>>.

The precompiled binary forms of Larceny should run on
most machines that use an 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 R7RS runtime

If something goes wrong while
<<CompilingStdLibSection,compiling the R7RS runtime>>,
make sure you are running the copy of Larceny you think
you are running and have read and write permission
for +lib/R7RS+, +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/R7RS+ or +lib/R6RS+ or +lib/SRFI+
or its subdirectories has gone
<<CompilingChapter,stale>>.
Removing all `.slfasl` files from +lib/R6RS+, +lib/R6RS+, 
+lib/SRFI+, and their subdirectories will eliminate the stale file(s).

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


[[AutoLoadErrorsSection]]

==== Autoloading errors

If Larceny attempts to autoload an imported R7RS/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 one of the `-I` or `-A` options was
omitted or incorrect.

If an R7RS/R6RS library is recompiled, then all compiled
libraries and top-level programs that depend upon it must
also be recompiled.  In particular, recompiling the standard
R7RS 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 performs several optimizations
that are fully compatible with the R7RS but may not be fully compatible
with the older R6RS, R5RS, and IEEE-1178 standards.

When compiling R5RS code, Larceny's Twobit compiler normally
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 at
the expense of slower code, use R5RS mode and
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]
================================================================
That `help` procedure is predefined only in R5RS mode, and
some of the help information that will be printed may be
irrelevant to the heap image you are using.
================================================================

To alter the compiler switches from R7RS mode, or
to disable certain compiler optimizations that are
incompatible with the R6RS, see the section that
describes the
<<LarcenyCompilerSection, `(larceny compiler)` library>>.
