To make Idea 1 of the OP work with @goto
, scrap the above idea of working with the AST and instead work closer to the IR. Seems easier overall (less special cases).
Draft Pseudo-Code of Idea 1 (with goto):
(assumption: all AST has been lowered to flattened IR, but no Core.Box
es have been inserted yet. There might currently be no point during lowering where this is true, but the concept could be adapted.)
With prior knowledge that a local variable x
is captured by a closure, decide whether to box x
by the following procedure (true for box, false for no-box):
Define assigns(n,x,checked)
to take a line number n
, a symbol x
, and a set of previously explored line numbers checked
. assigns
operates as follows:
- If
n ∈ checked
, return false. - Push
n
intochecked
. - While true:
a. If expression at linen
is aExpr(:(=), x, ...)
, return true.
b. If expression at linen
is a:method
of a closure known to capturex
, pushn
intochecked
. Loop over every sub-expression in its CodeInfo’s.code
. If any is aExpr(:(=), x, ...)
, return true.
c. If expression at linen
is aCore.GotoNode
, returnassigns(ex.label,x,checked)
.
d. If expression at linen
is aCore.GotoIfNot
, returnassigns(n+1,x,checked)||assigns(ex.label,x,checked)
.
e. If expression at linen
is aCore.ReturnNode
, or if there are no more expressions, return false.
f. Incrementn
.
Then, initialize checked
to an empty set; let n
be the line at which the closure :method
is defined; and if assigns(n,x,checked)
, then box x
. If multiple closures are known to capture x
, simply call assigns
on them without emptying checked
to save some computations.
The basic gist is: Explore all expressions that are syntactically reachable in and after the closure’s declaration. If any is an assignment to the captured variable, then box it—but otherwise don’t. Keep a record checked
of labels and methods that have been visited, to avoid repeated work and getting stuck in loops. As before:
cc @simeonschaub you seem to have a pretty good grasp of closure capture boxing; do you mind if I entice you to opine?