Standard environment
====================

Pre-Scheme programs usually open the prescheme structure.  There are several other structures built-in to Pre-Scheme as well, described in the next section.  This section describes the prescheme structure.

Scheme bindings
---------------

Bindings for all the names specified here from R5RS Scheme are available in Pre-Scheme.  The remainder of the sections after this one detail Pre-Scheme specifics that are not a part of Scheme.

 -- syntax: define name value
 -- syntax: define (name . argument-list) value
 -- syntax: if condition consequent [alternate]
 -- syntax: let ((name expression) ...) body
 -- syntax: let* ((name expression) ...) body
 -- syntax: and conjunct ...
 -- syntax: or disjunct ...
 -- syntax: cond cond-clause ...
 -- syntax: do ((name init-exp [step-exp]) ...) (test-exp [return-exp]) body
     These special forms & macros are all unchanged from their R5RS specifications.

 -- syntax: define-syntax name transformer-expression [aux-names]
 -- syntax: let-syntax ((name transformer-expression) ...) body
 -- syntax: letrec-syntax ((name transformer-expression) ...) body
     Pre-Scheme's macro facility is exactly the same as Scheme48's. TRANSFORMER-EXPRESSION may be either a syntax-rules or an explicit renaming transformer, just as in Scheme48; in the latter case, it is evaluated either in a standard Scheme environment or however the for-syntax clause specified of the package in whose code the transformer appeared.  For details on the extra AUX-NAMES operand to define-syntax, see Explicit renaming macros.

 -- procedure: not boolean returns boolean
 -- procedure: eq? valuea valueb returns boolean
 -- procedure: char=? chara charb returns boolean
 -- procedure: char<? chara charb returns boolean
 -- procedure: values value ... returns values
 -- procedure: call-with-values producer consumer returns values
 -- procedure: current-input-port returns input-port
 -- procedure: current-output-port returns output-port
     These procedures are all unchanged from their R5RS specifications.

 -- procedure: + addend ... returns integer
 -- procedure: - integer returns integer
 -- procedure: - minuend subtrahend returns integer
 -- procedure: * multiplicand ... returns integer
 -- procedure: = integera integerb returns boolean
 -- procedure: < integera integerb returns boolean
 -- procedure: > integera integerb returns boolean
 -- procedure: <= integera integerb returns boolean
 -- procedure: >= integera integerb returns boolean
 -- procedure: min integer1 integer2 ... returns integer
 -- procedure: max integer1 integer2 ... returns integer
 -- procedure: abs integer returns integer
 -- procedure: quotient divisor dividend returns integer
 -- procedure: remainder divisor dividend returns integer
 -- procedure: expt base exponent returns integer
     These numerical operations are all unchanged from their R5RS counterparts, except that they are applicable only to fixnums, not to flonums, and they always return fixnums.

Tail call optimization
----------------------

 -- syntax: goto procedure argument ...
     The Pre-Scheme compiler can be forced to optimize tail calls, even those it would not have otherwise optimized, by use of the goto special form, rather than simple procedure calls.  In every respect other than tail call optimization, this is equivalent to calling PROCEDURE with the given arguments.  Note, however, that uses of goto may cause code to blow up if the Pre-Scheme compiler had reason not to optimize the tail call were it not for the goto: it may need to merge the tail-called procedure into the caller's code.

Bitwise manipulation
--------------------

Pre-Scheme provides basic bitwise manipulation operators.

 -- procedure: bitwise-and integera integerb returns integer
 -- procedure: bitwise-ior integera integerb returns integer
 -- procedure: bitwise-xor integera integerb returns integer
 -- procedure: bitwise-not integer returns integer
     Bitwise boolean logical operations.

 -- procedure: shift-left integer count returns integer
 -- procedure: arithmetic-shift-right integer count returns integer
 -- procedure: logical-shift-right integer count returns integer
     Three ways to shift bit strings: shift-left shifts INTEGER left by COUNT, arithmetic-shift-right shifts INTEGER right by COUNT arithmetically, and logical-shift-right shifts INTEGER right by COUNT logically.

Compound data manipulation
--------------------------

Pre-Scheme has somewhat lower-level vector & string facilities than Scheme, with more orientation towards static typing.  It also provides a statically typed record facility, which translates to C structs, though not described here, as it is not in the prescheme structure; see Pre-Scheme record types.

 -- procedure: make-vector length init returns vector
 -- procedure: vector-length vector returns integer
 -- procedure: vector-ref vector index returns value
 -- procedure: vector-set! vector index value returns unit
     Vectors in Pre-Scheme are almost the same as vectors in regular Scheme, but with a few differences.  Make-vector initializes what it returns with null pointers (see below); it uses the required (unlike Scheme) INIT argument only to determine the type of the vector: vectors are statically typed; they can contain only values that have the same static type as INIT.  Vector-length is available only at the top level, where calls to it can be evaluated at compile-time; vectors do not at run-time store their lengths.  Vectors must also be explicitly deallocated.

     Warning: As in C, there is no vector bounds checking at run-time.

 -- procedure: make-string length returns string
 -- procedure: string-length string returns integer
 -- procedure: string-ref string index returns char
 -- procedure: string-set! string index char returns unit
     Strings in Pre-Scheme are the nearly same as strings in R5RS Scheme. The only three differences here are that make-string accepts exactly one argument, strings must be explicitly deallocated, and strings are nul-terminated: string-length operates by scanning for the first ASCII nul character in a string.

     Warning: As in C, there is no string bounds checking at run-time.

 -- procedure: deallocate pointer returns unit
     Deallocates the memory pointed to by pointer.  This is necessary at the end of a string, vector, or record's life, as Pre-Scheme data are not automatically garbage-collected.

 -- procedure: null-pointer returns null-pointer
 -- procedure: null-pointer? pointer returns boolean
     Null-pointer returns the distinguished null pointer object.  It corresponds with 0 in a pointer context or NULL in C. Null-pointer? returns true if POINTER is a null pointer, or false if not.

Error handling
--------------

Pre-Scheme's method of error handling is similar to the most common one in C: error codes.  There is an enumeration errors of some error codes commonly and portably encountered in Pre-Scheme.

 -- enumeration: errors

          (define-enumeration errors
            (no-errors
             parse-error
             file-not-found
             out-of-memory
             invalid-port)) lisp
          Each enumerand has the following meaning:

          no-errors
               Absence of error: success.

          parse-error
               Any kind of parsing error.  The Scheme48 VM uses this when someone
               attempts to resume a malformed suspended heap image.

          file-not-found
               Used when an operation that operates on a file given a string filename
               found that the file for that filename was absent.

          out-of-memory
               When there is no more memory to allocate.

          invalid-port
               Unused.

 -- procedure: error-string error-status returns string
     Returns a string describing the meaning of the errors enumerand ERROR-STATUS.

 -- procedure: error message irritant ...
     Signals a fatal error with the given message & related irritants and halts the program.  On Unix, the program's exit code is -1.

Input & output
--------------

Pre-Scheme's I/O facilities are somewhat different from Scheme's, given the low level and the static type strictness.  There is no exception mechanism in Pre-Scheme; everything is maintained by returning a status token, as in C.  Pre-Scheme's built-in I/O facilities are buffered. (Scheme48's VM does not use Pre-Scheme's built-in I/O facilities to implement Channels, channels --- it builds its own lower-level facilities that are still OS-independent, but, because they're written individually for different OSs, they integrate better as low-level I/O channels with the OS.  On Unix, the Scheme48 VM uses file descriptors; Pre-Scheme's built-in I/O uses stdio. Scheme48's VM uses Pre-Scheme's built-in I/O only to read heap images.) (see Low-level Pre-Scheme memory manipulation, for two other I/O primitives, read-block & write-block, for reading & writing blocks of direct memory.)

 -- procedure: open-input-file filename returns [port status]
 -- procedure: open-output-file filename returns [port status]
 -- procedure: close-input-port input-port returns status
 -- procedure: close-output-port output-port returns status
     Open-input-file & open-output-file open ports for the given filenames.  They each return two values: the newly open port and an errors enumerand status.  Users of these procedures should always check the error status before proceeding to operate with the port. Close-input-port & close-output-port close their port arguments and return the errors enumerand status of the closing.

 -- procedure: read-char input-port returns [char eof? status]
 -- procedure: peek-char input-port returns [char eof? status]
 -- procedure: read-integer input-port returns [integer eof? status]
     Read-char reads & consumes a single character from its INPUT-PORT argument.  Peek-char reads, but does not consume, a single character from INPUT-PORT.  Read-integer parses an integer literal, including sign.  All of these also return two other values: whether or not the file is at the end and any errors enumerand status.  If any error occurred, the first two values returned should be ignored.  If STATUS is (enum errors no-errors), users of these three procedures should then check EOF?; it is true if INPUT-PORT was at the end of the file with nothing more left to read and false otherwise.  Finally, if both STATUS is (enum errors no-errors) and EOF? is false, the first value returned may be safely used.

 -- procedure: write-char char output-port returns status
 -- procedure: newline output-port returns status
 -- procedure: write-string string output-port returns status
 -- procedure: write-integer integer output-port returns status
     These all write particular elements to their OUTPUT-PORT arguments.  Write-char writes individual characters. Newline writes newlines (line-feed, or ASCII codepoint 10, on Unix).  Write-string writes the contents of STRING. Write-integer writes an ASCII representation of INTEGER to port, suitable to be read by read-integer.  These all return an errors enumerand status.  If it is no-errors, the write succeeded.

 -- procedure: force-output output-port returns status
     Forces all buffered output in OUTPUT-PORT.  STATUS tells whether or not the operation was successful.

Access to C functions and macros
--------------------------------

 -- syntax: external c-name ps-type returns procedure
     Special form for accessing C functions & macros.  Calls in Pre-Scheme to the resulting procedure are compiled to calls in C to the function or macro named by C-NAME, which should be a string.  PS-TYPE is the Pre-Scheme type specifiers, Pre-Scheme type that the procedure should have, which is necessary for type inference.