vpisarev / ficus

The programming language Ficus
Apache License 2.0
72 stars 9 forks source link

K_Lift declosuring optimization #8

Closed 4ekmah closed 3 years ago

vpisarev commented 3 years ago

@4ekmah,

here is the approximate action plan, as we've discussed:

  1. lift_all() function in k_lift.fx is split into several functions.
  2. K_declosure.fx file is added with a dedicated 'declosuring' step.
  3. The call to lift_all() in compiler.fx is replaced with 3 calls perhaps:
    1. make wrappers for nothow
    2. replace mutable free vars with references
    3. declosure
    4. lambda lifting itself

In the beginning of the steps 3.2, 3.3, 3.4 we collect information about free variables. After the stage 3.2 we do not need to handle mutable free vars explicitly, because they all will be replaced with references, i.e. we will only have immutable free vars. For the step 3.2 we do not need to compute transitive closures of free var sets, it's enough to know that a mutable value is used as free variable in at least one function. For the declosure step we need to compute transitive closure, because the global function foo() may call nested function bar(), which can call another nested-into-foo function baz(), which accesses free variable z declared in foo():

fun foo(x: float) {
    val z = sin(x)
    fun bar(x: float) { baz()*x }
    fun baz() { z + 1 }
    bar(x)
}

in this example bar() does not access free variable 'z' by itself, but it calls baz(), which accesses it. Therefore, at the declosure step bar() should also be extended to take z as parameter. The easiest way to do it is to compute transitive closure of free var sets. After this step we will find out that bar() also has a free variable z.

For the final step, when we will actually form closures and transform function bodies to extract copies of free vars from the closure structures and access them, we also need to compute the sets of free variables and then compute their transitive closures.

Important note: when you debug such transformations, it's recommended to specify -O0 optimization to disable inline function expansion, otherwise some nested functions may just 'disappear'.

vpisarev commented 3 years ago

@4ekmah, finally, I've reviewed the code; looks great! :+1: