DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download
Index: ┃ T c

⟦5e796fcf8⟧ TextFile

    Length: 8373 (0x20b5)
    Types: TextFile
    Names: »cross.doc«

Derivation

└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
    └─ ⟦this⟧ »EUUGD11/gnu-31mar87/scheme/cross.doc« 

TextFile

This is a preliminary document on the use of the Scheme Cross syntaxer.
This documentation is not all inclusive and the cross syntaxer is 
subject to change without notice.  As a matter of fact, there is a
much better one which will be installed in rel5.

	The scheme interpreter does not run the code that you 
type at it.  The code that we call scheme code such as:

(define (fact n) (if (< n 2) 1 (* n (fact (-1+ n)))))

is transformed into SCode.  SCode is an abstract code representation
that is somewhat simpler than scheme code.  The process of translating
scheme code into scode is called syntaxing.  As an example, the
fragment (< n 2) is syntaxed into an scode object called a
combination.  A combination has two parts, the operator, which in this
case is the variable <, and the list of the operands, which in the
case is the list of the variable n and the number 2.  Since programs
are run in their scode representation, if the scode is optimized, the
program will run faster. The cross syntaxer performs this
optimization.  It is called cross syntaxer rather than SCode optimizer
for historical reasons (it was originally written in PDP10 scheme to
generate the initial load for the implementation which ran on 68000s).

	The normal use for the cross syntaxer is to call the function
SF (which stands for "syntax-file"). SF takes one required argument
which is the name of the source file of scheme code that you want to
cross syntax.  This argument could also be a list of file names.
These names are strings.  The cross syntaxer reads the source file,
syntaxes and optimizes the scode, dumps the scode into a binary file
(with file extension ".bin") and dumps some human readable
information about the code into a specification file (with file
extension ".spc"). When the cross syntaxer is about to process a file
it prints out:

(SYNTAX-FILE {source-file} {scode-output-file} {spec-output-file})

For example, suppose we start out will the following code in the file
"fact.scm".

;;; File fact.scm

(define (fact n)
  (if (< n 2)
      1
      (* n (fact (-1+ n)))))

;;; end of file fact.scm

If we then typed the following at scheme:

]=> (sf "fact.scm")

The cross syntaxer would print out the following:
(SYNTAX-FILE "fact.scm" "fact.bin" "fact.spc")

It will then process the file "fact.scm", output the binary form of the
scode in "fact.bin", and output the spec file in "fact.spc".   If we
wanted to cross syntax several files we could put the file names into
a list.   For instance, if we wanted to cross syntax both fact.scm and
another file "fib.scm", we could type the following at scheme:

]=> (sf (list "fact.scm" "fib.scm"))

The cross syntaxer would then print out as above:
(SYNTAX-FILE "fact.scm" "fact.bin" "fact.spc")

Once it had finished processing this first file it would then print
out the following and process this next file:
(SYNTAX-FILE "fib.scm" "fib.bin" "fib.spc")

If we wanted the bin and spc files to go into another directory, we
could say:

]=> (sf "fact.scm" "mydirectory/")

It would then print out:
(SYNTAX-FILE "fact.scm" "mydirectory/fact.bin" "mydirectory/fact.spc")

Also we could specify different directories for the bin and spec file:

]=> (sf "fact.scm" "bindirectory/" "spcdirectory/")

This would cause the cross syntaxer to print:
(SYNTAX-FILE "fact.scm" "bindirectory/fact.bin" "spcdirectory/fact.spc")

The specification of the output files will also work if the first
argument is a list of filenames.

	Once a file is cross syntaxed and dumped into a bin file, the
scode in the bin file can be loaded into scheme via the normal load
command.  Hence, after cross syntaxing "fact.scm", we could then say:

]=> (load "fact.bin")

When scheme loads binary scode, it will print out a message similar to
the following:

FASLoading file fact.bin

Since it is loading binary scode and doesn't have to parse the text
of the source file, this loading will take less time then loading the
source text.  Hence the loading will be fast, which explains the
strange word FASLoading, which stands for "fast loading".

	One of the optimizations that the cross syntaxer makes is to
put actual primitives in the scode in place of a variable to look up
the value of the primitive.  This process is called primitive
integration or in-lining.  for instance, in the combination (-1+ n),
if the primitive -1+ were in the operator part of the combination
instead of the variable which causes the interpreter to look up the
value of -1+, this combination could be evaluated more quickly as the
expense of the lookup would be avoided.

	several things must be noted.  first, the cross syntaxer must
be told to do this optimization with primitives.  it does not do it
automatically.  second, if this optimization is performed and the
primitive -1+ is integrated into the combination,  redefining -1+ to
be something else has no effect on the evaluation of the combination
as the variable -1+ is never looked up to find it's value.

	the way to tell the cross syntaxer to integrate a primitive is
to have the following declaration at the top of the file of source
code: 

(declare (compilable-primitive-functions
	  {primitive-name}
	  .
	  .
 	 ))

this tells the cross syntaxer to integrate all the primitives listed
after compilable-primitive-functions.  hence, to optimize our
factorial program, we could cross syntax the source file with the
following at the top:

(declare (compilable-primitive-functions -1+))

	Another declaration that is useful is to put a two element
list after compilable-primitive-functions instead of a primitive name.
This tells the cross syntaxer to integrate the second item in the list
whenever it sees an occurance of the first item of the list.  For
instance, if we declared:

(declare (compilable-primitive-functions (decrement -1+)))

and our combination was written as (decrement n), the primitive -1+
would be integrated in place of decrement.

	An important thing to note is that integrations are not always
performed if the cross syntaxer deems them to be unsafe.  For
instance, suppose the file fact contained the follwing:

;;; File fact.scm that defeats the declarations

(declare (compilable-primitive-functions -1+))

(define (-1+ n) (- n 1))

(define (fact n)
  (if (< n 2)
      1
      (* n (fact (-1+ n)))))

;;; end of file fact.scm

	In this case, -1+ would not be integrated, because -1+ is
defined in the file and it is unclear whether fact should use the
primitive or call the compound procedure defined as -1+.

	Another important thing to note is that only primitives can
be integrated.  To find out whether a procedure is a primitive or
not, simply type the name of the procedure at the interpreter and see
what the interpreter returns.  For example:

]=> -1+
#[PRIMITIVE-PROCEDURE -1+]    ;; this is a primitive

]=> <
#[COMPOUND-PROCEDURE <]       ;; this is not

]=> *
#[COMPOUND-PROCEDURE *]       ;; neither is this

	We could futher optimize fact if we could use the primitive
versions of two compound procedures above.  In fact, if we
pretty-printed the two compound procedures, we would see that they use
the primitives &< and &*.  These two primitives always take two
arguments, unlike the compound procedures < and *.  Hence to further
optimize our factorial program, we could change the source file as
follows and cross syntax:

;;; Greatly optimized file fact.scm

(declare (compilable-primitive-functions -1+ &* &<))

(define (fact n)
  (if (&< n 2)
      1
      (&* n (fact (-1+ n)))))

;;; end of file fact.scm

	Once cross syntaxed, this version of fact would run relatively
efficiently because as written, it never needs to look up any free
variables.  The primitives are all in-lined, and the only variables
needed to look up are n which is local to fact because it is an
argument, and fact, which it knows to be itself.

(declare (usual-integrations))

	Tells the cross-syntaxer to integrate all the common
primitives (eq?, cons, etc.)  Note that no renames are performed by
this, so the variable argument arithmetic functions are not affected
by this declaration.

	Note that the student system makes the cross-syntaxer
available only after invoking ENABLE-LANGUAGE-FEATURES.  The
development system always makes the cross-syntaxer available.
The cross-syntaxer is generated by loading the file xbuild.bin, and
thi sis done in the installation process.