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