Command processor
=================

The Scheme48 command processor is the main development environment.  It incorporates a read-eval-print loop as well as an interactive inspector and debugger.  It is well-integrated with the module system for rapid dynamic development, which is made even more convenient with the Emacs interface, scheme48.el; see Emacs integration.

Basic commands
--------------

There are several generally useful commands built-in, along with many others described in subsequent sections:

 -- command: ,help
 -- command: ,help command
 -- command: ,?
 -- command: ,? command
     Requests help on commands.  ,? is an alias for ,help.  Plain ,help lists a synopsis of all commands available, as well as all Command processor switches, switches.  ,help COMMAND requests help on the particular command COMMAND.

 -- command: ,exit
 -- command: ,exit status
 -- command: ,exit-when-done
 -- command: ,exit-when-done status
     Exits the command processor.  ,exit immediately exits with an exit status of 0.  ,exit STATUS exits with the status that evaluating the expression STATUS in the interaction environment produces.  ,exit-when-done is like ,exit, but it waits until all threads complete before exiting.

 -- command: ,go expression
     ,go is like ,exit, except that it requires an argument, and it evaluates EXPRESSION in the interaction environment in a tail context with respect to the command processor.  This means that the command processor may no longer be reachable by the garbage collector, and may be collected as garbage during the evaluation of EXPRESSION.  For example, the full Scheme48 command processor is bootstrapped from a minimal one that supports the ,go command.  The full command processor is initiated in an argument to the command, but the minimal one is no longer reachable, so it may be collected as garbage, leaving only the full one.

 -- command: ,run expression
     Evaluates EXPRESSION in the interaction environment.  Alone, this command is not very useful, but it is required in situations such as the Inspector, inspector and Command programs, command programs.

 -- command: ,undefine name
     Removes the binding for NAME in the interaction environment.

 -- command: ,load filename ...
     Loads the contents each FILENAME as Scheme source code into the interaction environment.  Each FILENAME is translated first (see Filenames).  The given filenames may be surrounded or not by double-quotes; however, if a filename contains spaces, it must be surrounded by double-quotes.  The differences between the ,load command and Scheme's load procedure are that ,load does not require its arguments to be quoted, allows arbitrarily many arguments while the load procedure accepts only one filename (and an optional environment), and works even in environments in which load is not bound.

 -- command: ,translate from to
     A convenience for registering a filename translation without needing to open the filenames structure.  For more details on filename translations, see Filenames; this command corresponds with the filename structure's set-translation! procedure.  As with ,load, each of the filenames FROM and TO may be surrounded or not by double-quotes, unless there is a space in the filenames, in which case it must be surrounded by double-quotes.

     Note that in the exec language (see Command programs), translate is the same as the filenames structure's set-translation! procedure, not the procedure named translate from the filenames structure.

Switches
--------

The Scheme48 command processor keeps track of a set of switches, user-settable configurations.

 -- command: ,set switch
 -- command: ,set switch {on|off|?}
 -- command: ,unset switch
 -- command: ,set ?
     ,set SWITCH & ,set SWITCH on set the switch SWITCH on.  ,unset SWITCH & ,set SWITCH off turn SWITCH off.  ,set SWITCH ? gives a brief description of SWITCH's current status.  ,set ? gives information about all the available switches and their current state.

The following switches are defined.  Each switch is listed with its name and its default status.

ask-before-loading (off)
     If this is on, Scheme48 will prompt the user before loading modules' code.  If it is off, it will quietly just load it.

batch (off)
     Batch mode is intended for automated uses of the command processor. With batch mode on, errors cause the command processor to exit, and the prompt is not printed.

break-on-warnings (off)
     If the break-on-warnings switch is on, Condition system, warnings signalled that reach the command processor's handler will cause a Command levels, command level to be pushed, similarly to breakpoints and errors.

inline-values (off)
     Inline-values tells whether or not certain procedures may be integrated in-line.

levels (on)
     Errors will push a new Command levels, command level if this switch is on, or they will just reset back to the top level if levels is off.

load-noisily (off)
     Loading source files will cause messages to be printed if load-noisily is on; otherwise they will be suppressed.

Emacs integration commands
--------------------------

There are several commands that exist mostly for Emacs integration,Emacs integration; although they may be used elsewhere, they are not very useful or convenient without scheme48.el.

 -- command: ,from-file filename
 -- command: ,end
     ,from-file FILENAME proclaims that the code following the command, until an ,end command, comes from FILENAME --- for example, this may be due to an appropriate Emacs command, such as C-c C-l in scheme48.el ---; if this is the first time the command processor has seen code from FILENAME, it is registered to correspond with the interaction environment wherein the ,from-file command was used.  If it is not the first time, the code is evaluated within the package that was registered for FILENAME.

 -- command: ,forget filename
     Clears the command processor's memory of the package to which FILENAME corresponds.

Focus value
-----------

The Scheme48 command processor maintains a current focus value. This is typically the value that the last expression evaluated to, or a list of values if it returned multiple values.  If it evaluated to either zero values or Scheme48's `unspecific' token (see System features), the focus value is unchanged.  At the initial startup of Scheme48, the focus value is set to the arguments passed to Scheme48's virtual machine after the -a argument on the command-line (see Running Scheme48).  The focus value is accessed through the ## syntax; the reader substitutes a special quotation (special so that the compiler will not generate warnings about a regular quote expression containing a weird value) for occurrences of ##. Several commands, such as ,inspect and ,dis, either accept an argument or use the current focus value.  Also, in the Inspector, inspector, the focus object is the object that is currently being inspected.

     > (cons 1 2)
     '(1 . 2)
     > ##
     '(1 . 2)
     > (begin (display "Hello, world!") (newline))
     Hello, world!
     > ##
     '(1 . 2)
     > (cdr ##)
     2
     > (define x 5)
     ; no values returned
     > (+ ## x)
     7
     > (values 1 2 3)
     ; 3 values returned
     1
     2
     3
     > ##
     '(1 2 3) example

Command levels
--------------

The Scheme48 command processor maintains a stack of command levels, or recursive invocations of the command processor.  Each command level retains information about the point from the previous command level at which it was pushed: the threads that were running --- which the command processor suspends ---, including the thread of that command level itself; the continuation of what pushed the level; and, if applicable, the Condition system, condition that caused the command level to be pushed.  Each command level has its own thread scheduler, which controls all threads running at that level, including those threads' children.

Some beginning users may find command levels confusing, particularly those who are new to Scheme or who are familiar with the more simplistic interaction methods of other Scheme systems.  These users may disable the command level system with the Command processor switches, levels switch by writing the command ,set levels off.

 -- command: ,push
 -- command: ,pop
 -- command: ,resume
 -- command: ,resume level
 -- command: ,reset
 -- command: ,reset level
     ,push pushes a new command level.  ,pop pops the current command level.  C-d/^D, or EOF, has the same effect as the ,pop command.  Popping the top command level inquires the user whether to exit or to return to the top level.  ,resume LEVEL pops all command levels down to LEVEL and resumes all threads that were running at LEVEL when it was suspended to push another command level.  ,reset LEVEL resets the command processor to LEVEL, terminating all threads at that level but the command reader thread.  ,resume & ,reset with no argument use the top command level.

 -- command: ,condition
 -- command: ,threads
     ,condition sets the focus value to the condition that caused the command level to be pushed, or prints `no condition' if there was no relevant condition.  ,threads invokes the inspector on the list of threads of the previous command level, or on nothing if the current command level is the top one.

     > ,push
     1> ,push
     2> ,pop
     1> ,reset

     Top level
     > ,open threads formats
     > ,push
     1> ,push
     2> (spawn (lambda ()
                 (let loop ()
                   (sleep 10000)    ; Sleep for ten seconds.
                   (format #t "~&foo~%")
                   (loop)))
               'my-thread)
     2>
     foo
     ,push
     3> ,threads
     ; 2 values returned
      [0] '#{Thread 4 my-thread}
      [1] '#{Thread 3 command-loop}
     3: q
     '(#{Thread 4 my-thread} #{Thread 3 command-loop})
     3> ,resume 1

     foo
     2>
     foo
     ,push
     3> ,reset 1
     Back to 1> ,pop
     > example

Module commands
---------------

Scheme48's command processor is well-integrated with its Module system, module system.  It has several dedicated environments, including the user package and the config package, and can be used to evaluate code within most packages in the Scheme48 image during program development.  The config package includes bindings for Scheme48's configuration language; structure & interface definitions may be evaluated in it.  The command processor also has provisions to support rapid development and module reloading by automatically updating references to redefined variables in compiled code without having to reload all of that code.

 -- command: ,open struct ...
     Opens each STRUCT into the interaction environment, making all of its exported bindings available.  This may have the consequence of loading code to implement those bindings.  If there was code evaluated in the interaction environment that referred to a previously undefined variable for whose name a binding was exported by one of these structures, a message is printed to the effect that that binding is now available, and the code that referred to that undefined variable will be modified to subsequently refer to the newly available binding.

 -- command: ,load-package struct
 -- command: ,reload-package struct
     ,load-package and ,reload-package both load the code associated with the package underlying STRUCT, after ensuring that all of the other structures opened by that package are loaded as well.  ,load-package loads the code only if has not already been loaded; ,reload-package unconditionally loads it.

 -- command: ,user
 -- command: ,user command-or-exp
 -- command: ,config
 -- command: ,config command-or-exp
 -- command: ,for-syntax
 -- command: ,for-syntax command-or-exp
 -- command: ,new-package
 -- command: ,in structure
 -- command: ,in structure command-or-exp
     These all operate on the interaction environment.  ,user sets it to the user package, which is the default at initial startup. ,user COMMAND-OR-EXP temporarily sets the interaction environment to the user package, processes COMMAND-OR-EXP, and reverts the interaction environment to what it was before ,user was invoked.  The ,config & ,for-syntax commands are similar, except that they operate on the config package and the package used for the user package's macros (see Macros in concert with modules).  ,new-package creates a temporary, unnamed package with a vanilla R5RS environment and sets the interaction environment to it.  That new package is not accessible in any way except to the user of the command processor, and it is destroyed after the user switches to another environment (unless the user uses the ,structure command; see below).  ,in STRUCTURE sets the interaction environment to be STRUCTURE's package; STRUCTURE is a name whose value is extracted from the config package.  ,in STRUCTURE COMMAND-OR-EXP sets the interaction environment to STRUCTURE temporarily to process COMMAND-OR-EXP and then reverts it to what it was before the use of ,in.  Note that, within a structure, the bindings available are exactly those bindings that would be available within the structure's static code, ie code in the structure's begin package clauses or code in files referred to by files package clauses.

 -- command: ,user-package-is struct
 -- command: ,config-package-is struct
     ,user-package-is & ,config-package-is set the user & config packages, respectively, to be STRUCT's package. STRUCT is a name whose value is accessed from the current config package.

 -- command: ,structure name interface
     This defines a structure named NAME in the config package that is a view of INTERFACE on the current interaction environment.

SRFI 7
------

Scheme48 supports [SRFI 7] after loading the srfi-7 structure by providing two commands for loading [SRFI 7] programs:

 -- command: ,load-srfi-7-program name filename
 -- command: ,load-srfi-7-script name filename
     These load [SRFI 7] a program into a newly constructed structure, named NAME, which opens whatever other structures are needed by features specified in the program.  ,load-srfi-7-program loads a simple [SRFI 7] program; ,load-srfi-7-script skips the first line, intended for [SRFI 22] Unix scripts.

Debugging commands
------------------

There are a number of commands useful for debugging, along with a continuation inspector, all of which composes a convenient debugger.

 -- command: ,bound? name
 -- command: ,where
 -- command: ,where procedure
     ,bound? prints out binding information about NAME, if it is bound in the interaction environment, or `Not bound' if NAME is unbound.  ,where prints out information about what file and package its procedure argument was created in.  If PROCEDURE is not passed, ,where uses the focus value. If ,where's argument is not a procedure, it informs the user of this fact.  If ,where cannot find the location of its argument's creation, it prints `Source file not recorded.'

 -- command: ,expand
 -- command: ,expand exp
 -- command: ,dis
 -- command: ,dis proc
     ,expand prints out a macro-expansion of EXP, or the focus value if EXP is not provided.  The expression to be expanded should be an ordinary S-expression.  The expansion may contain `generated names' and `qualified names.'  These merely contain lexical context information that allow one to differentiate between identifiers with the same name.  Generated names look like #{Generated NAME UNIQUE-NUMERIC-ID}.  Qualified names appear to be vectors; they look like #(>> INTRODUCER-MACRO NAME UNIQUE-NUMERIC-ID), where INTRODUCER-MACRO is the macro that introduced the name.

     ,dis prints out a disassembly of its procedure, continuation, or template argument.  If PROC is passed, it is evaluated in the interaction environment; if not, ,dis disassembles the focus value.  The disassembly is of Scheme48's virtual machine's byte code. (A description of the byte code is forthcoming, although it does not have much priority to this manual's author.  For now, users can read the rudimentary descriptions of the Scheme48 virtual machine's byte code instruction set in vm/interp/arch.scm of Scheme48's Scheme source.)

 -- command: ,condition
 -- command: ,threads
     For the descriptions of these commands, see Command levels.  These are mentioned here because they are relevant in the context of debugging.

 -- command: ,trace
 -- command: ,trace name ...
 -- command: ,untrace
 -- command: ,untrace name ...
     Traced procedures will print out information about when they are entered and when they exit.  ,trace lists all of the traced procedures' bindings.  ,trace NAME ... sets each NAME in the interaction environment, which should be bound to a procedure, to be a traced procedure over the original procedure. ,untrace resets all traced procedures to their original, untraced procedures.  ,untrace NAME ... untraces each individual traced procedure of NAME ... in the interaction environment.

 -- command: ,preview
     Prints a trace of the previous command level's suspended continuation. This is analogous with stack traces in many debuggers.

 -- command: ,debug
     Invokes the debugger: runs the inspector on the previous command level's saved continuation.  For more details, see Inspector.

 -- command: ,proceed
 -- command: ,proceed exp
     Returns to the continuation of the condition signalling of the previous command level.  Only certain kinds of conditions will push a new command level, however --- breakpoints, errors, and interrupts, and, if the break-on-warnings switch is on, warnings ---; also, certain kinds of errors that do push new command levels do not permit being proceeded from.  In particular, only with a few VM primitives may the ,proceed command be used.  If EXP is passed, it is evaluated in the interaction environment to produce the values to return; if it is not passed, zero values are returned.

Inspector
---------

Scheme48 provides a simple interactive object inspector.  The command processor's prompt's end changes from > to : when in inspection mode.  The inspector is the basis of the debugger, which is, for the most part, merely an inspector of continuations.  In the debugger, the prompt is debug:.  In the inspector, objects are printed followed by menus of their components.  Entries in the menu are printed with the index, which optionally includes a symbolic name, and the value of the component.  For example, a pair whose car is the symbol a and whose cdr is the symbol b would be printed by the inspector like this:

     '(a . b)

      [0: car] 'a
      [1: cdr] 'b example

     The inspector maintains a stack of the focus objects it previously
     inspected.  Selecting a new focus object pushes the current one onto
     the stack; the u command pops the stack.

      -- command: ,inspect
      -- command: ,inspect exp
          Invokes the inspector.  If EXP is present, it is evaluated in the
          user package and its result is inspected (or a list of results, if it
          returned multiple values, is inspected).  If EXP is absent, the
          current focus value is inspected.

     The inspector operates with its own set of commands, separate from the
     regular interaction commands, although regular commands may be invoked
     from the inspector as normal.  Inspector commands are entered with or
     without a preceding comma at the inspector prompt.  Multiple inspector
     commands may be entered on one line; an input may also consist of an
     expression to be evaluated.  If an expression is evaluated, its value
     is selected as the focus object.  Note, however, that, since inspector
     commands are symbols, variables cannot be evaluated just by entering
     their names; one must use either the ,run command or wrap the
     variables in a begin.

     These inspector commands are defined:

      -- inspector command: menu
      -- inspector command: m
          Menu prints a menu for the focus object.  M moves
          forward in the current menu if there are more than sixteen items to be
          displayed.

      -- inspector command: u
          Pops the stack of focus objects, discarding the current one and setting
          the focus object to the current top of the stack.

      -- inspector command: q
          Quits the inspector, going back into the read-eval-print loop.

      -- inspector command: template
          Attempts to coerce the focus object into a template.  If successful,
          this selects it as the new focus object; if not, this prints an error
          to that effect.  Templates are the static components of closures and
          continuations: they contain the code for the procedure, the top-level
          references made by the procedure, literal constants used in the code,
          and any inferior templates of closures that may be constructed by the
          code.

      -- inspector command: d
          Goes down to the parent of the continuation being inspected.  This
          command is valid only in the debugger mode, ie when the focus object
          is a continuation.

Command programs
----------------

The Scheme48 command processor can be controlled programmatically by command programs, programs written in the exec language. This language is essentially a mirror of the commands but in a syntax using S-expressions.  The language also includes all of Scheme.  The exec language is defined as part of the exec package.

 -- command: ,exec
 -- command: ,exec command
     Sets the interaction environment to be the exec package.  If an argument is passed, it is set temporarily, only to run the given command.

Commands in the exec language are invoked as procedures in Scheme. Arguments should be passed as follows:

  * Identifiers, such as those of structure names in the config package, should be passed as literal symbols.  For instance, the command ,in frobbotz would become in the exec language (in 'frobbotz).

  * Filenames should be passed as strings; eg, ,dump frob.image becomes (dump "frob.image").

  * Commands should be represented in list values with the car being the command name and the cdr being the arguments.  Note that when applying a command an argument that is a command invocation is often quoted to produce a list, but the list should not include any quotation; for instance, ,in mumble ,undefine frobnicate would become (in 'mumble '(undefine frobnicate)), even though simply ,undefine frobnicate would become (undefine 'frobnicate).

     The reason for this is that the command invocation in the exec language is different from a list that represents a command invocation passed as an argument to another command; since commands in the exec language are ordinary procedures, the arguments must be quoted, but the quoted arguments are not themselves evaluated: they are applied as commands.

     An argument to a command that expects a command invocation can also be a procedure, which would simply be called with zero arguments.  For instance, (config (lambda () (display (interaction-environment)) (newline))) will call the given procedure with the interaction environment set to the config package.

  * Expressions must be passed using the run command.  For example, the equivalent of ,user (+ 1 2) in the exec language would be (user '(run (+ 1 2))).

Command programs can be loaded by running the ,load command in the exec package.  Scripts to load application bundles are usually written in the exec language and loaded into the exec package.  For example, this command program, when loaded into the exec package, will load foo.scm into the config package, ensure that the package frobbotzim is loaded, and open the quuxim structure in the user package:

     (config '(load "foo.scm"))
     (load-package 'frobbotzim)
     (user '(open quuxim)) lisp

Image-building commands
-----------------------

Since Scheme48's operation revolves about an image-based model, these commands provide a way to save heap images on the file system, which may be resumed by invoking the Scheme48 virtual machine on them as in Running Scheme48.

 -- command: ,build resumer filename
 -- command: ,dump filename
 -- command: ,dump filename message
     ,build evaluates RESUMER, whose value should be a unary procedure, and builds a heap image in FILENAME that, when resumed by the virtual machine, will pass the resumer all of the command-line arguments after the -a argument to the virtual machine.  The run-time system will have been initialized as with Suspending and resuming heap images,usual resumers, and a basic condition handler will have been installed by the time that the resumer is called.  On Unix, RESUMER must return an integer exit status for the process. ,dump dumps the Scheme48 command processor, including all of the current settings, to FILENAME.  If MESSAGE is passed, it should be a string delimited by double-quotes, and it will be printed as part of the welcome banner on startup; its default value, if it is not present, is "(suspended image)".

Resource statistics and control
-------------------------------

Scheme48 provides several devices for querying statistics about various resources and controlling resources, both in the command processor and programmatically.

 -- command: ,collect
     Forces a garbage collection and prints the amount of space in the heap before and after the collection.

 -- command: ,time expression
     Evaluates EXPRESSION and prints how long it took.  Three numbers are printed: run time, GC time, and real time.  The run time is the amount of time in Scheme code; the GC time is the amount of time spent in the garbage collector; and the real time is the actual amount of time that passed during the expression's evaluation.

 -- command: ,keep
 -- command: ,keep kind ...
 -- command: ,flush
 -- command: ,flush kind ...
     Scheme48 maintains several different kinds of information used for debugging information.  ,keep with no arguments shows what kinds of debugging data are preserved and what kinds are not.  ,keep KIND ... requests that the debugging data of the given kinds should be kept; the ,flush command requests the opposite. ,flush with no arguments flushes location names and resets the debug data table.  The following are the kinds of debugging data:

     names
          procedure names

     maps
          environment maps used by the debugger to show local variable names

     files
          filenames where procedures were defined

     source
          source code surrounding continuations, printed by the debugger

     tabulate
          if true, will store debug data records in a global table that can be easily flushed; if false, will store directly in compiled code

     ,flush can also accept location-names, which will flush the table of top-level variables' names (printed, for example, by the ,bound? command); file-packages, which will flush the table that maps filenames to packages in which code from those files should be evaluated; or table, in which case the table of debug data is flushed.

     Removing much debug data can significantly reduce the size of Scheme48 heap images, but it can also make error messages and debugging much more difficult.  Usually, all debug data is retained; only for images that must be small and that do not need to be debuggable should the debugging data flags be turned off.

The spatial structure exports these utilities for displaying various statistics about the heap:

 -- procedure: space returns unspecified
 -- procedure: vector-space [predicate] returns unspecified
 -- procedure: record-space [predicate] returns unspecified
     Space prints out a list of the numbers of all objects and the number of bytes allocated for those objects on the heap, partitioned by the objects' primitive types and whether or not they are immutable (pure) or mutable (impure).  Vector-space prints the number of vectors and the number of bytes used to store those vectors of several different varieties, based on certain heuristics about their form.  If the predicate argument is passed, it gathers only vectors that satisfy that predicate.  Record-space prints out, for each record type in the heap, both the number of all instances of that record type and the number of bytes used to store all of those instances.  Like vector-space, if the predicate argument is passed, record-space will consider only those records that satisfy the predicate.

     All of these three procedures first invoke the garbage collector before gathering statistics.

The traverse structure provides a simple utility for finding paths by which objects refer to one another.

 -- procedure: traverse-breadth-first object returns unspecified
 -- procedure: traverse-depth-first object returns unspecified
     These traverse the heap, starting at OBJECT, recording all objects transitively referred to.  Traverse-breadth-first uses a FIFO-queue-directed breadth-first graph traversal, while traverse-depth-first uses a LIFO-stack-directed depth-first graph traversal.  The traversal halts at any leaves in the graph, which are distinguished by an internal leaf predicate in the module.  See below on set-leaf-predicate! on how to customize this and what the default is.

     The traversal information is recorded in a global resource; it is not thread-safe, and intended only for interactive usage.  The record can be reset by passing some simple object with no references to either traverse-breadth-first or traverse-depth-first; eg, (traverse-depth-first #f).

 -- procedure: trail object returns unspecified
     After traversing the heap from an initial object, (trail OBJECT) prints the path of references and intermediate objects by which the initial object holds a transitive reference to OBJECT.

 -- procedure: set-leaf-predicate! predicate returns unspecified
 -- procedure: usual-leaf-predicate object returns boolean
     Set-leaf-predicate! sets the current leaf predicate to be PREDICATE.  Usual-leaf-predicate is the default leaf predicate; it considers simple numbers (integers and flonums), strings, byte vectors, characters, and immediate objects (true, false, nil, and the unspecific object) to be leaves, and everything else to be branches.