Next: compiler lifting api, Previous: compiler lifting examples, Up: compiler lifting [Index]
This compiler pass performs substitutions of binding references with the purpose of optimising their implementation. One of the possible results is to reduce the number of free variables non–combinator functions are closed upon; if all the free variables are removed: some non–combinator functions can be implemented as combinators.
This has already been discussed. Whenever a function is recognised to be a combinator: every reference to it is substituted with a form building and returning a new closure object; as example, the core language form:
(let ((f (lambda () '1))) (f))
is transformed into:
(codes ((lambda (label: asmlabel:f:clambda) () (constant 1))) (jmpcall asmlabel:f:clambda:case-0 (closure-maker (code-loc asmlabel:f:clambda) no-freevars)))
In the following core language expression:
(let ((a ((primitive read)))) (let ((b a)) b))
the binding b
is a synonym for a
, so it is transformed into:
(codes () (bind ((a_0 (funcall (primref read)))) a_0))
In the following recordised code:
(fix ((a_0 (lambda () ?body))) (bind ((b_0 a_0)) (fix ((c_0 (lambda () (funcall b_0)))) c_0)))
the returned value looks like a closure upon the binding b_0
, but
in truth it is known at compile–time that b_0
is an immutable
binding referencing a clambda
struct and also which
clambda
is referenced; so the function bound to c_0
is
just a combinator; more: everywhere a reference to b_0
appears we
can substitute it with a reference to a_0
, and so we can
transform the code to:
(fix ((a_0 (lambda () ?body))) (bind ((b_0 a_0)) (fix ((c_0 (lambda () (funcall a_0)))) c_0)))
NOTE While synonym binding elimination is performed by this compiler pass: it should have already been performed by the source optimiser.
Next: compiler lifting api, Previous: compiler lifting examples, Up: compiler lifting [Index]