Next: , Previous: , Up: compiler lifting   [Index]


17.20.3 Combinators and non–combinators

To discuss the transformations we define:

combinator

A Scheme function without free variables; a combinator does not capture any binding. The closure object implementing a combinator can be created once and for all at compile–time; for example:

(define (compute x y z)
  (define (lincomb a b c)
    (+ (* a b) (* a c)))
  (lincomb x y z))

assuming function integration is disabled: the closure object implementing the function lincomb can be created once at compile–time and reused at every call to compute.

non–combinator

A Scheme function with free variables, whose current value must be captured at run–time. To implement a non–combinator: a new closure object must be created at run–time every time the control flow reaches the lambda form, to capture the current values of the free variables; for example:

(define (adder x)
  (lambda (x)
    (+ x y)))

at every call to the function adder a new closure object must be created and returned, capturing the value of the argument x.

We want to discuss how to recognise combinators and non–combinators among the bindings defined by a fix struct. Let’s consider the recordised code:

(bind ((?lhs1 ?rhs1) ...)
  (fix ((?lhs0 ?rhs0) ...)
    (bind ((?lhs2 ?rhs2) ...)
      ?body)))

at this point in the sequence of compiler passes, we know that all the ?rhs0 are closure-maker structs. The var structs ?lhs0 and ?lhs1 may appear in the body of each ?rhs0, while the internally defined var structs ?lhs2 cannot; so the ?lhs2 do not influence the nature of the ?rhs0 expressions: we can ignore all the internally defined bindings. So let’s switch to inspect the recordised code:

(bind ((?lhs1 ?rhs1) ...)
  (fix ((?lhs0 ?rhs0) ...)
    ?body))

the var structs ?lhs0 and ?lhs1 may appear in the body of each ?rhs0; this includes the case of recursive ?rhs0, in which a ?lhs0 var appears in the list of free variables of the associated ?rhs0.


Next: , Previous: , Up: compiler lifting   [Index]