Next: compiler lifting, Previous: compiler vars, Up: compiler [Index]
We can think of clambda
structs as representing code that,
once compiled, becomes the machine code stored in code objects
implementing Scheme functions. This compiler pass wraps each
clambda
struct into a closure-maker
struct, which
represents code that, executed at run–time, builds and returns a
closure object using the clambda
’s code object as
implementation. While wrapping clambda
, a list of variable
references that are free in the body of the clambda
is
gathered for future use.
NOTE The true purpose of this compiler pass is to gather lists of free variables referenced by
clambda
bodies. We might introduce the closure makers at a later pass and store the lists of free variables in theclambda
structs; we introduce the closure makers here because it helps a bit in reasoning about the transformations.
Upon entering this compiler pass:
bind
structs:
(bind ((?lhs ?rhs) ...) ?body)
the ?lhs are var
structs; the ?rhs are
non–clambda
structs; the var
in ?lhs do
not appear in the ?rhs expressions.
fix
structs:
(fix ((?lhs ?rhs) ...) ?body)
the ?lhs are var
structs; the ?rhs are
clambda
structs; the var
in ?lhs might appear
in the ?rhs expressions.
clambda
appear only as right–hand side
expressions of fix
structs.
This compiler pass transforms:
(fix ((?lhs ?clambda-rhs) ...) ?body)
into:
(fix ((?lhs (closure-maker ?clambda-rhs)) ...) ?body)
The following bindings are exported by the library (vicare
compiler)
.
Perform code transformations traversing the whole hierarchy in input, which must be a struct instance representing recordised code, and building a new hierarchy of recordised code; return the new hierarchy.
This function wraps each clambda
struct in the input
recordised code into closure-maker
structures, compiling a
list of free variables referenced by each clambda
.
This example generates a function with no free variables:
(lambda () '1) → (fix ((tmp_0 (closure-maker (lambda () (constant 1)) no-freevars))) tmp_0)
This example generates a multi–clause function with no free variables:
(case-lambda (() '1) ((a) a)) → (fix ((tmp_0 (closure-maker (case-lambda (() (constant 1)) ((a_0) a_0)) no-freevars))) tmp_0)
This example generates a function with a free variable:
(let ((a ((primitive read)))) (lambda () a)) → (bind ((a_0 (funcall (primref read)))) (fix ((tmp_0 (closure-maker (lambda () a_0) (freevars: a_0)))) tmp_0))
This example generates a recursive function with no free variables other than the reference to itself:
(letrec ((f (lambda () (f)))) f) → (fix ((f_0 (closure-maker (lambda () (jmpcall asmlabel:f:clambda:case-0 f_0)) (freevars: f_0)))) f_0)
The core language form:
(library-letrec* ((a a.loc (lambda () '1)) (b b.loc (lambda () '2)) (c c.loc (lambda () '3)) (d d.loc '4)) (quote #!void))
is transformed into:
(fix ((a_0 (closure-maker (lambda () (constant 1)) no-freevars)) (b_0 (closure-maker (lambda () (constant 2)) no-freevars)) (c_0 (closure-maker (lambda () (constant 3)) no-freevars))) (seq (funcall (primref $set-symbol-value/proc!) (constant a.loc) a_0) (funcall (primref $init-symbol-value!) (constant b.loc) b_0) (funcall (primref $init-symbol-value!) (constant c.loc) c_0) (bind ((d_0 (constant 4))) (seq (funcall (primref $init-symbol-value!) (constant d.loc) d_0) (constant #!void)))))
Next: compiler lifting, Previous: compiler vars, Up: compiler [Index]