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
clambdabodies. We might introduce the closure makers at a later pass and store the lists of free variables in theclambdastructs; 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]