Pass 1 collects information needed for optimization while
converting a Scheme definition or expression into the front end's
intermediate form.
It performs
integrate-usual-procedures
compiler switch
is true, then Pass 1 performs some
+
and make-vector
.
As an example, Pass 1 converts
(define reverse-map (lambda (f l) (define (loop l x) (if (pair? l) (loop (cdr l) (cons (f (car l)) x)) x)) (loop l '())))
into a forbiddingly large intermediate form that is equivalent to
((lambda () (begin (set! reverse-map (lambda (.f|1 .l|1) ((lambda (.loop|2) (begin (set! .loop|2 (lambda (.l|3 .x|3) (if (pair? .l|3) (.loop|2 ((lambda (.x|6|9) (begin (.check! (pair? .x|6|9) '1 .x|6|9) (.cdr:pair .x|6|9))) .l|3) (cons (.f|1 ((lambda (.x|15|18) (begin (.check! (pair? .x|15|18) '0 .x|15|18) (.car:pair .x|15|18))) .l|3)) .x|3)) .x|3))) (.loop|2 .l|1 '()))) (unspecified)))) 'reverse-map)))
This would be a legal expression of IEEE Scheme, except the renamed identifers are illegal: They have been prefixed by a period and contain a vertical bar. These illegal characters prevent any conflict with the names of legal global variables, which are not renamed. When Twobit is used as a preprocessor, legal but obscure sequences of characters are used instead of the period and vertical bar.
The internal definition
of loop
has been converted
into a LET
that binds .loop|2
to a newly
allocated location whose contents are undefined, and then stores
the result of a lambda expression into that location.
That is a literal rendering of the official semantics for an
internal definition in Scheme, but most optimizing compilers do not
expand internal definitions and LETREC
s to such a low
level.
Calls to certain of Scheme's standard library procedures, including
car
and cdr
, have been expanded into calls
to low-level procedures that are protected by explicit run-time checks.
The output of Pass 1 has several important properties:
Since there are no internal definitions in the output of Pass 1, Pass 2 has only seven kinds of expression to optimize.