commit 401b458056fd705b48e02b0a06a375054ad25150 Author: Lassi Kortela Date: Wed Aug 3 23:14:40 2022 +0300 Add manual Copy of https://thintz.com/resources/prescheme-documentation diff --git a/www/1.3/index.html b/www/1.3/index.html new file mode 100644 index 0000000..7e07b7e --- /dev/null +++ b/www/1.3/index.html @@ -0,0 +1,1421 @@ + + + + + + +The Nearly Complete Scheme48 PreScheme 1.3 Reference Manual + + + + + + + + + + + + + + + +

The Nearly Complete Scheme48 PreScheme 1.3 Reference Manual

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Table of Contents

+ +
+ + +
+ + + +
+

+Next: , Up: (dir)   [Contents]

+
+ +

The Nearly Complete Scheme48 PreScheme Reference Manual

+ +

This manual is for Scheme48 version 1.3. +

+

Copyright © 2004, 2005, 2006 Taylor Campbell. +All rights reserved. +

+

This manual includes material derived from works bearing the following +notice: +

+

Copyright © 1993–2005 Richard Kelsey, Jonathan Rees, and +Mike Sperber. +All rights reserved. +

+
+

Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +

+ + +
+ +

THIS SOFTWARE IS PROVIDED BY THE AUTHORS “AS IS” AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +

+ + + + + + +
+ +
+

+Previous: , Up: Top   [Contents]

+
+ +

1 Pre-Scheme: A low-level dialect of Scheme

+ +

Pre-Scheme [Kelsey 97] is a low-level dialect of Scheme, designed for +systems programming with higher-level abstractions. For example, the +Scheme48 virtual machine is written in Pre-Scheme. Pre-Scheme is a +particularly interesting alternative to C for many systems programming +tasks, because not only does it operate at about the same level as C, +but it also may be run in a regular high-level Scheme development with +no changes to the source, without resorting to low-level stack munging +with tools such as gdb. Pre-Scheme also supports two extremely +important high-level abstractions of Scheme: macros and higher-order, +anonymous functions. Richard Kelsey’s Pre-Scheme compiler, based on +his PhD research on transformational compilation [Kelsey 89], compiles +Pre-Scheme to efficient C, applying numerous intermediate source +transformations in the process. +

+

This chapter describes details of the differences between Scheme and +Pre-Scheme, listings of the default environment and other packages +available to Pre-Scheme, the operation of Richard Kelsey’s Pre-Scheme +compiler, and how to run Pre-Scheme code as if it were Scheme in a +regular Scheme environment. +

+ + + + + + + + + + +
+ +
+

+Next: , Up: Pre-Scheme   [Contents]

+
+ +

1.1 Differences between Pre-Scheme & Scheme

+ +

Pre-Scheme is often considered either a dialect of Scheme or a subset +of Scheme. However, there are several very important fundamental +differences between the semantics of Pre-Scheme & Scheme to detail. +

+
+
+ + + +
+
There is no garbage collector in Pre-Scheme.
+

All memory management is manual, as in C, although there are two levels +to memory management, for higher- and lower-level purposes: pointers & +addresses. Pointers represent higher-level data that are statically +checked for type coherency, such as vectors of a certain element type, +or strings. Addresses represent direct, low-level memory indices. +

+ + +
+
Pre-Scheme has no closures.
+

Lambda expressions that would require full closures at run-time +— e.g., those whose values are stored in the heap — are not +permitted in Pre-Scheme. However, the Pre-Scheme compiler can hoist +many lambda expressions to the top level, removing the need of +closures for them. (Closures would be much less useful in the absence +of garbage collection, in any case.) If the Pre-Scheme compiler is +unable to move a lambda to a place where it requires no closure, +it signals an error to the user. +

+ + + +
+
Tail call optimization is not universal.
+

The Pre-Scheme compiler optimizes tail calls where it is possible — +typically, just in local loops and top-level procedures that are not +exported from the package, but there are other heuristics —, but it +is not universal. Programmers may force tail call optimization with +Pre-Scheme’s goto special form (see Tail call optimization in Pre-Scheme), but, in situations where the compiler would not have +optimized the tail call, this can make the generated code have to jump +through many hoops to be a tail call — often necessitating code bloat, +because the code of the tail-called procedure is integrated into the +caller’s driver loop —; and, where the compiler would have otherwise +optimized the tail call, goto has no effect anyway. +

+ + +
+
Types are strictly verified with Hindley-Milner type inference.
+

The types of Pre-Scheme programs are statically verified based on +Hindley-Milner type inference, with some modifications specific to +Pre-Scheme. Type information is not retained at run-time; any +tagging must be performed explicitly. +

+ +
+
Pre-Scheme does not support first-class continuations.
+

There is no call-with-current-continuation or other continuation +manipulation interface. It has been suggested that downward-only +continuations, based on C’s setjmp & longjmp, might be +implemented in the future, but this is not yet the case.1 +

+ + +
+
The full numeric tower of R5RS is not supported by Pre-Scheme.
+

Pre-Scheme’s only numeric types are fixnums and flonums, with precision +determined by the architecture on which the Pre-Scheme code runs. +Fixnums are translated to C as the long type; flonums are +translated as the float type. +

+ + + + +
+
Top-level Pre-Scheme code is evaluated at compile-time.
+

Closures actually are available, as long as they may be +eliminated before run-time. Code evaluated at compile-time also does +not require satisfaction of strict static typing. Moreover, certain +procedures, such as vector-length, are available only at +compile-time. +

+
+
+ +
+

+Next: , Previous: , Up: Pre-Scheme   [Contents]

+
+ +

1.2 Type specifiers

+ + + +

Although Pre-Scheme’s static type system is based mostly on +Hindley-Milner type inference, with as little explicit type information +as possible, there are still places where it is necessary to specify +types explicitly; for example, see Pre-Scheme access to C functions and macros. There are several different kinds of types with different +syntax: +

+
+
type-name
+

Symbols denote either record type or base types. Record types are +defined with the define-record-type special form described +later; the following base types are defined: +

+
+
integer
+

Fixed-size integers (fixnums). This type is translated into C as +long. The actual size depends on the size of C’s long, +which on most architectures is 32 bits. +

+
+
float
+

Floating-point data. This type translates to C as double. +

+
+
null
+

Type which has no value. The null type translates to the C +void type. +

+
+
unit
+

Type which has one value. Actually, this, too, translates to C’s +void, so that it has one value is not strictly true. +

+
+
boolean
+

Booleans translate to the C char type. #t is emitted as +TRUE, and #f, as FALSE; these are usually the same +as 1 & 0, respectively. +

+
+
input-port
+
output-port
+

I/O ports. On Unix, since Pre-Scheme uses stdio, these are +translated to FILE *s, stdio file streams. +

+
+
char
+

Characters. The size of characters is dependent on the underlying C +compiler’s implementation of the char type. +

+
+
address
+

Simple addresses for use in Pre-Scheme’s low-level memory manipulation primitives; +see that section for more details. +

+
+ +
+
(=> (argument-type …) return-type …)
+

The types of procedures, known as ‘arrow’ types. +

+
+
(^ type)
+

The type of pointers that point to type. Note that these are +distinct from the address type. Pointer types are statically verified +to be coherent data, with no defined operations except for accessing +offsets in memory from the pointer — i.e. operations such as +vector-ref —; addresses simply index bytes, on which only +direct dereferencing, but also arbitrary address arithmetic, is +available. Pointers and addresses are not interchangeable, and +and there is no way to convert between them, as that would break the +type safety of Pre-Scheme pointers. +

+
+
(tuple type …)
+

Multiple value types, internally used for argument & return types. +

+
+
+ +
+

+Next: , Previous: , Up: Pre-Scheme   [Contents]

+
+ +

1.3 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. +

+ + + + + + + + + + +
+ +
+

+Next: , Up: Standard Pre-Scheme environment   [Contents]

+
+ +

1.3.1 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 --> boolean
+
procedure: eq? valuea
+
procedure: char=? chara
+
procedure: char<? chara
+
procedure: values value … --> values
+
procedure: call-with-values producer consumer --> values
+
procedure: current-input-port --> input-port
+
procedure: current-output-port --> output-port
+

These procedures are all unchanged from their R5RS specifications. +

+ +
+
procedure: + addend … --> integer
+
procedure: - integer --> integer
+
procedure: - minuend subtrahend --> integer
+
procedure: * multiplicand … --> integer
+
procedure: = integera
+
procedure: < integera
+
procedure: > integera
+
procedure: <= integera
+
procedure: >= integera
+
procedure: min integer1
+
procedure: max integer1
+
procedure: abs integer --> integer
+
procedure: quotient divisor dividend --> integer
+
procedure: remainder divisor dividend --> integer
+
procedure: expt base exponent --> 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. +

+ +
+ +
+

+Next: , Previous: , Up: Standard Pre-Scheme environment   [Contents]

+
+ +

1.3.2 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. +

+ +
+ +
+

+Next: , Previous: , Up: Standard Pre-Scheme environment   [Contents]

+
+ +

1.3.3 Bitwise manipulation

+ +

Pre-Scheme provides basic bitwise manipulation operators. +

+
+
procedure: bitwise-and integera
+
procedure: bitwise-ior integera
+
procedure: bitwise-xor integera
+
procedure: bitwise-not integer --> integer
+

Bitwise boolean logical operations. +

+ +
+
procedure: shift-left integer count --> integer
+
procedure: arithmetic-shift-right integer count --> integer
+
procedure: logical-shift-right integer count --> 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. +

+ +
+ +
+

+Next: , Previous: , Up: Standard Pre-Scheme environment   [Contents]

+
+ +

1.3.4 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 --> vector
+
procedure: vector-length vector --> integer
+
procedure: vector-ref vector index --> value
+
procedure: vector-set! vector index value --> 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 --> string
+
procedure: string-length string --> integer
+
procedure: string-ref string index --> char
+
procedure: string-set! string index char --> 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 --> 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 --> null-pointer
+
procedure: null-pointer? pointer --> 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. +

+ +
+ +
+

+Next: , Previous: , Up: Standard Pre-Scheme environment   [Contents]

+
+ +

1.3.5 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))
+

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

+ +
+ +
+

+Next: , Previous: , Up: Standard Pre-Scheme environment   [Contents]

+
+ +

1.3.6 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. +2 +(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 --> [port status]
+
procedure: open-output-file filename --> [port status]
+
procedure: close-input-port input-port --> status
+
procedure: close-output-port output-port --> 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 --> [char eof? status]
+
procedure: peek-char input-port --> [char eof? status]
+
procedure: read-integer input-port --> [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 --> status
+
procedure: newline output-port --> status
+
procedure: write-string string output-port --> status
+
procedure: write-integer integer output-port --> 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 --> status
+

Forces all buffered output in output-port. Status tells +whether or not the operation was successful. +

+ +
+ +
+

+Previous: , Up: Standard Pre-Scheme environment   [Contents]

+
+ +

1.3.7 Access to C functions and macros

+ +
+
syntax: external c-name ps-type --> 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 that the +procedure should have, which is necessary for type inference. +

+
+ +
+

+Next: , Previous: , Up: Pre-Scheme   [Contents]

+
+ +

1.4 More Pre-Scheme packages

+ +

Along with the prescheme structure, there are several other +structures built-in to Pre-Scheme. +

+ + + + + + + +
+ +
+

+Next: , Up: More Pre-Scheme packages   [Contents]

+
+ +

1.4.1 Floating point operation

+ + +

Since Pre-Scheme’s strict static type system would not permit +overloading of the arithmetic operators for integers & floats, it +provides a different set of operators for floats. These names are all +exported by the ps-flonums structure. +

+
+
procedure: fl+ augend addend … --> float
+
procedure: fl- float --> float
+
procedure: fl- minuend subtrahend --> float
+
procedure: fl* multiplier multiplicand … --> float
+
procedure: fl/ divisor dividend --> float
+
procedure: fl= floata
+
procedure: fl< floata
+
procedure: fl> floata
+
procedure: fl<= floata
+
procedure: fl>= floata
+

All of these operations flop correspond as floating point +variations of their op integer equivalents. +

+ +
+ +
+

+Next: , Previous: , Up: More Pre-Scheme packages   [Contents]

+
+ +

1.4.2 Record types

+ + +

The ps-record-types structure defines the following special form +for introducing record types. Pre-Scheme record types are translated +to C as structs. +

+
+
syntax: define-record-type
+
+
(define-record-type type type-descriptor
+  (constructor argument-field-tag …)
+  (field-tag<1> field-type-spec<1>
+    field-accessor<1> [field-modifier<1>])
+  (field-tag<2> field-type-spec<2>
+    field-accessor<2> [field-modifier<2>])
+  …
+  (field-tag<n> field-type-spec<n>
+    field-accessor<n> [field-modifier<n>])
+

Defines a record type. Type is mangled to the C struct type name +(type-descriptor-name is unused unless running Pre-Scheme as +Scheme). Constructor is defined to construct a record of the new +type and initialize the fields argument-type-field … with +its arguments, respectively. If it cannot allocate a sufficient +quantity of memory, constructor returns a null pointer. The +initial values of fields that are not passed to the constructor are +undefined. For each field field<i> specified, +

+
    +
  • field<i> is specified to have the type +field-type-spec<i>; + +
  • field-accessor<i> is defined to be a procedure of one +argument, a record of type type-name, that returns the value of +the field field<i> of that record — its type is defined to +be (=> (type-name) field-type-spec<i>); and + +
  • if present, field-modifier<i> is defined to be a +procedure of two arguments, a record of type type-name and a +value of type field-type-spec, that assigns the value of the +field field<i> in its first argument to be the value of its +second argument; its type is (=> (type-name +field-type-spec) unit). +
+ +

Records must be deallocated explicitly when their lifetime has expired +with deallocate. +

+ +
+ +
+

+Next: , Previous: , Up: More Pre-Scheme packages   [Contents]

+
+ +

1.4.3 Multiple return values

+ + +

Pre-Scheme support multiple return values, like in Scheme. The only +difference is that one cannot operate on multiple return values as +lists, since Pre-Scheme does not have lists. Multiple return values +are implemented in C as returning in C the first value and passing +pointers to the remaining values, which the function returning multiple +values assigns. The prescheme structure exports the two +multiple return value primitives, call-with-values and +values, but the ps-receive structure exports this macro +for more conveniently binding multiple return values. +

+
+
syntax: receive formals producer body
+

Binds the lambda parameter list formals to the multiple +values that producer returns, and evaluates body with the +new variables bound. +

+
+
(receive formals
+         producer
+  body)
+    ≡
+(call-with-values
+    (lambda () producer)
+  (lambda formals
+    body))
+
+ +
+ +
+

+Previous: , Up: More Pre-Scheme packages   [Contents]

+
+ +

1.4.4 Low-level memory manipulation

+ + + + +

Pre-Scheme is a low-level language. It provides very low-level, direct +memory manipulation. ‘Addresses’ index a flat store of sequences of +bytes. While Pre-Scheme ‘pointers’ are statically checked for data +coherency, allow no arbitrary arithmetic, and in general are high-level +abstract data to some extent, addresses are much lower-level, have no +statically checked coherency — the values an address represents are +selected by what operation used to read or write from it —, permit +arbitrary address arithmetic, and are a much more concrete interface +into direct memory. The ps-memory structure exports these +direct memory manipulation primitives. +

+
+
procedure: allocate-memory size --> address
+
procedure: deallocate-memory address --> unit
+

Allocate-memory reserves a sequence of size bytes in the +store and returns an address to the first byte in the sequence. +Deallocate-memory releases the memory at address, which +should have been the initial address of a contiguous byte sequence, as +allocate-memory would return, not an offset address from such an +initial address. +

+ +
+
procedure: unsigned-byte-ref address --> unsigned-byte
+
procedure: unsigned-byte-set! address unsigned-byte --> unit
+
procedure: word-ref address --> word
+
procedure: word-set! address word --> unit
+
procedure: flonum-ref address --> float
+
procedure: flonum-set! address float --> unit
+

Procedures for reading from & storing to memory. +Unsigned-byte-ref & unsigned-byte-set! access & store the +first unsigned byte at address. Word-ref & +word-set! access & store the first word — Pre-Scheme integer +— beginning at address. Flonum-ref & flonum-set! +access & store 64-bit floats beginning at address.. +

+

Bug: Flonum-ref & flonum-set! are unimplemented +in the Pre-Scheme-as-Scheme layer (see Running Pre-Scheme as Scheme). +

+ +
+
procedure: address? value --> boolean
+

Disjoint type predicate for addresses. +

+

Note: Address? is available only at the top +level, where code is evaluated at compile-time. Do not use this in any +place where it may be called at run-time. +

+ +
+
constant: null-address --> address
+

The null address. This is somewhat similar to the null pointer, except +that it is an address. +

+

Note: One acquires the null pointer by calling the +procedure null-pointer, whereas the constant value of the +binding named null-address is the null address. +

+ +
+
procedure: null-address? address --> boolean
+

Null-address? returns true if address is the null +address and false if not. +

+ +
+
procedure: address+ address increment --> address
+
procedure: address- address decrement --> address
+
procedure: address-difference addressa
+

Address arithmetic operators. Address+ adds increment to +address; address- subtracts decrement from +address; and address-difference returns the integer +difference between address<a> and address<b>. +For any address<p> & address<q>, (address+ +address<p> (address-difference address<p> +address<q>)) is equal to address<q>. +

+ +
+
procedure: address= addressa
+
procedure: address< addressa
+
procedure: address> addressa
+
procedure: address<= addressa
+
procedure: address>= addressa
+

Address comparators. +

+ +
+
procedure: integer->address integer --> address
+
procedure: address->integer address --> integer
+

Integers and addresses, although not the same type, may be converted to +and from each other; integer->address & address->integer +perform this conversion. Note that Pre-Scheme pointers may not +be converted to addresses or integers, and the converse is also true. +

+ +
+
procedure: copy-memory! source-address target-address count --> unit
+

Copies count bytes starting at source-address to +target-address. This is similar to C’s memcpy. +

+ +
+
procedure: memory-equal? addressa
+

Compares the two sequences of count bytes starting at addresses +address<a> & address<b>. It returns true if every +byte is equal and false if not. +

+ +
+
procedure: char-pointer->string address size --> string
+
procedure: char-pointer->nul-terminated-string address --> string
+

Char-pointer->string returns a string with size bytes from +the contiguous sequence of bytes starting at address. +Char-pointer->nul-terminated-string does similarly, but it +returns a string whose contents include every byte starting at +address until, but not including, the first 0 byte, i.e. ASCII +nul character, following address. +

+ +
+
procedure: read-block port address count --> [count-read eof? status]
+
procedure: write-block port address count --> status
+

Read-block attempts to read count bytes from port +into memory starting at address. Write-block attempts to +write count bytes to port from the contiguous sequence in +memory starting at address. Read-block returns three +values: the number of bytes read, whether or not the read went to the +end of the file, and the error status (see Pre-Scheme error handling). Write-block returns the error status. +

+
+ +
+

+Next: , Previous: , Up: Pre-Scheme   [Contents]

+
+ +

1.5 Invoking the Pre-Scheme compiler

+ +

Richard Kelsey’s Pre-Scheme compiler is a whole-program compiler based +on techniques from his research in transformational compilation +[Kelsey 89]. It compiles the restricted dialect of Scheme to efficient +C, and provides facilities for programmer direction in several +optimizations. +

+ +

1.5.1 Loading the compiler

+ +

There is a script, a Scheme48 ‘command +program’, that comes with Scheme48 to load the Pre-Scheme compiler, +which is in the file ps-compiler/load-ps-compiler.scm. It must +be loaded from the ps-compiler/ directory, from Scheme48’s main +distribution, into the exec package, after having loaded +../scheme/prescheme/interface.scm & +../scheme/prescheme/package-defs.scm into the config +package. The Pre-Scheme compiler takes some time to load, so it may be +easier to load it once and dump a heap image of the suspended command +processor after having loaded everything; see ‘Image-building +commands’. +

+

To load the Pre-Scheme compiler and dump an image to the file +ps-compiler.image that contains prescheme-compiler in the +user package, send this sequence of commands to the command processor +while in the ps-compiler/ directory of Scheme48’s distribution: +

+
+
,config ,load ../scheme/prescheme/interface.scm
+,config ,load ../scheme/prescheme/package-defs.scm
+,exec ,load load-ps-compiler.scm
+,in prescheme-compiler prescheme-compiler
+,user (define prescheme-compiler ##)
+,dump ps-compiler.image "(Pre-Scheme)"
+ + +

1.5.2 Calling the compiler

+ + +

After having loaded the Pre-Scheme compiler, the +prescheme-compiler structure is the front end to the compiler +that exports the prescheme-compiler procedure. +

+
+
procedure: prescheme-compiler structure-spec config-filenames init-name c-filename command …
+

Invokes the Pre-Scheme compiler. Config-filenames contain module +descriptions (see ‘Module system’) for the components of the program. +Structure-spec may be a symbol or a list of symbols, naming the +important structure or structures. All structures that it relies/they +rely on are traced in the packages’ open clauses. Modules that +are not traced in the dependency graph with root vertices of the given +structure[s] are omitted from the output. C-filename is a string +naming the file to which the C code generated by the Pre-Scheme +compiler should be emitted. Init-name is the name for an +initialization routine, generated automatically by the Pre-Scheme +compiler to initialize some top-level variables. The command +arguments are used to control certain aspects of the compilation. The +following commands are defined: +

+
+
(copy (structure copyable-procedure) …)
+

Specifies that each the body of each copyable-procedure from the +respective structure (from one of config-filenames) may be +integrated & duplicated. +

+
+
(no-copy (structure uncopyable-procedure) …)
+

Specifies that the given procedures may not be integrated. +

+
+
(shadow ((proc-structure procedure) (var-structure variable-to-shadow) …) …)
+

Specifies that, in procedure from proc-structure, the +global variables variable-to-shadow from their respective +var-structures should be shadowed with local variables, which +are more likely to be kept in registers for faster operation on them. +

+
+
(integrate (client-procedure integrable-procedure) …)
+

Forces integrable-procedure to be integrated in +client-procedure. +

+

Note: The integrate command operates on the global +program, not on one particular module; each client-procedure and +integrable-procedure is chosen from all variables defined in the +entirety of the program, across all modules. It is advised that there +be only one of each. +

+
+
(header header-line …)
+

Each header-line is added to the top of the generated C file, +after a cpp inclusion of <stdio.h> and "prescheme.h". +

+
+ +

The command arguments to prescheme-compiler are optional; they +are used only to optimize the compiled program at the programmer’s +request. +

+
+ +
+

+Next: , Previous: , Up: Pre-Scheme   [Contents]

+
+ +

1.6 Example Pre-Scheme compiler usage

+ +

The ps-compiler/compile-vm.scm, +ps-compiler/compile-gc.scm, and +ps-compiler/compile-vm-no-gc.scm files give examples of running +the Pre-Scheme compiler. They are Scheme48 ‘command programs’, to be loaded into the exec package after +having already loaded the Pre-Scheme compiler. compile-vm.scm & +compile-vm-no-gc.scm generate a new scheme48vm.c in the +scheme/vm/ directory — compile-vm.scm includes the +garbage collector, while compile-vm-no-gc.scm does not +3 —, and compile-gc.scm +generates a new scheme48heap.c, scheme48read-image.c, & +scheme48write-image.c in the scheme/vm/ directory. +

+

Here is a somewhat simpler example. It assumes a pre-built image with +the Pre-Scheme compiler loaded is in the ps-compiler.image file +in the current directory (see Invoking the Pre-Scheme compiler, +where there is a description of how to dump an image with the +Pre-Scheme compiler loaded). +

+
+
% ls
+hello.scm               packages.scm            ps-compiler.image
+% cat hello.scm
+(define (main argc argv)
+  (if (= argc 2)
+      (let ((out (current-output-port)))
+        (write-string "Hello, world, " out)
+        (write-string (vector-ref argv 1) out)
+        (write-char #\! out)
+        (newline out)
+        0)
+      (let ((out (current-error-port)))
+        (write-string "Usage: " out)
+        (write-string (vector-ref argv 0) out)
+        (write-string " <user>" out)
+        (newline out)
+        (write-string "  Greets the world & <user>." out)
+        (newline out)
+        -1)))
+% cat packages.scm
+(define-structure hello (export main)
+  (open prescheme)
+  (files hello))
+% scheme48 -i ps-compiler.image
+heap size 3000000 is too small, using 4770088
+Welcome to Scheme 48 1.3 (Pre-Scheme)
+Copyright (c) 1993-2005 by Richard Kelsey and Jonathan Rees.
+Please report bugs to scheme-48-bugs@s48.org.
+Get more information at http://www.s48.org/.
+Type ,? (comma question-mark) for help.
+> (prescheme-compiler 'hello '("packages.scm") 'hello-init "hello.c")
+packages.scm
+ hello.scmChecking types
+ main : ((integer **char) -> integer)
+In-lining single-use procedures
+Call Graph:
+<procedure name>
+  <called non-tail-recursively>
+  <called tail-recursively>
+main  (exported)
+Merging forms
+Translating
+ main
+#{Unspecific}
+> ,exit
+% cat hello.c
+#include <stdio.h>
+#include "prescheme.h"
+
+long main(long, char**);
+
+
+long main(long argc_0X, char **argv_1X)
+{
+  FILE * out_3X;
+  FILE * out_2X;
+ {  if ((1 == argc_0X)) {
+    out_2X = stdout;
+    ps_write_string("Hello, world, ", out_2X);
+    ps_write_string((*(argv_1X + 1)), out_2X);
+    { long ignoreXX;
+    PS_WRITE_CHAR(33, out_2X, ignoreXX) }
+    { long ignoreXX;
+    PS_WRITE_CHAR(10, out_2X, ignoreXX) }
+    return 0;}
+  else {
+    out_3X = stderr;
+    ps_write_string("Usage: ", out_3X);
+    ps_write_string((*(argv_1X + 0)), out_3X);
+    ps_write_string(" <user>", out_3X);
+    { long ignoreXX;
+    PS_WRITE_CHAR(10, out_3X, ignoreXX) }
+    ps_write_string("  Greets the world & <user>.", out_3X);
+    { long ignoreXX;
+    PS_WRITE_CHAR(10, out_3X, ignoreXX) }
+    return -1;}}
+}
+% 
+
+ +
+

+Previous: , Up: Pre-Scheme   [Contents]

+
+ +

1.7 Running Pre-Scheme as Scheme

+ + + + + + +

To facilitate the operation of Pre-Scheme systems within a high-level +Scheme development environment, Scheme48 simply defines the +prescheme, ps-memory, ps-record-types, +ps-flonums, and ps-receive structures in terms of Scheme; +Pre-Scheme structures can be loaded as regular Scheme structures +because of this. Those structures and the interfaces they implement +are defined in the files scheme/prescheme/interface.scm and +scheme/prescheme/package-defs.scm from the main Scheme48 +distribution; simply load these files into the ‘config package’ before loading any Pre-Scheme configuration +files. +

+

The Pre-Scheme emulation layer in Scheme has some shortcomings: +

+ + + + + + +
+
+

Footnotes

+ +

(1)

+

It +may be possible to use Pre-Scheme’s C FFI to manually use setjmp +& longjmp, but the author of this manual cannot attest to this +working.

+

(2)

+

Scheme48’s VM does not use Pre-Scheme’s built-in I/O +facilities to implement ‘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.

+

(3)

+

The actual distribution of Scheme48 separates the garbage +collector and the main virtual machine.

+
+
+ + + + +