Direct-style continuations on unoptimized core
When not opimizing core, continuations are not inlined, complicating the direct-style analysis.
For the example in #842, this currently yields:
repro.js:365
let v_r_0 = undefined;
^
SyntaxError: Identifier 'v_r_0' has already been declared
since the generated code looks like this:
function println_0(ans_0, ks_0, k_0) {
let v_r_0 = undefined;
let v_r_0 = undefined;
switch (ans_0.__tag) {
case 0: return () => b_k_0(ks_0);
case 1: break;
}
const v_r_1 = $effekt.println("n");
v_r_0 = v_r_1;
return () => k_0(v_r_0, ks_0);
const v_r_2 = $effekt.println("y");
v_r_0 = v_r_2;
return () => k_0(v_r_0, ks_0);
}
Disabling the direct style optimization by commenting out this
https://github.com/effekt-lang/effekt/blob/5599ca1101e0d52538ba84adaa9e1bfdc1c716be/effekt/shared/src/main/scala/effekt/generator/js/TransformerCps.scala#L223-L228
resolves the issue, but is slow.
This is the CPS IR for println
let k3755 = { (v_r_27793745) | ks3756 =>
jump k3754(v_r_27793745) @ ks3756
}
let b_k_27763741 = { () | ks3757 =>
let v_r_27753743 = println1("y")
jump k3755(v_r_27753743) @ ks3757
}
let k3753 = { (v_r_27793745) | ks3758 =>
jump k3754(v_r_27793745) @ ks3758
}
let b_k_27783742 = { () | ks3759 =>
let v_r_27773744 = println1("n")
jump k3753(v_r_27773744) @ ks3759
}
ans2747 match {
case Yes2753 () => {
jump b_k_27763741() @ ks3760
}
case No2754 () => {
jump b_k_27783742() @ ks3760
}
}
which it believes is direct style in k3755.
It also suffices to make the rhs of this
https://github.com/effekt-lang/effekt/blob/5599ca1101e0d52538ba84adaa9e1bfdc1c716be/effekt/shared/src/main/scala/effekt/generator/js/TransformerCps.scala#L514
to always return false, which effectively requires all branches to return to the same continuation. This again might be too conservative since under certain conditions we can convert a program to direct style (for the fast path), but still keep non-local jumps to other continuations.