Build the untagged dispatch as a plan before emitting it
Why
The dispatch of a switch on an untagged variant was decided in two places, the literal side in compile_switch and the payload side in compile_untagged_cases, each with part of the facts, while printing JavaScript.
Untagged_dispatch.plan builds the dispatch as a tree of tests and statements from the variant's facts and the match's arms, making today's decisions in one place; Lam_compile.compile_untagged_plan prints it. ounit tests pin plans as data. The output is unchanged except that a body of an if is no longer compiled in a switch context.
Generated code changed (a loop left from an arm of an if):
@unboxed type t = TextItem(string) | CountItem(float)for i in 0 to Array.length(values) - 1 { switch values->Array.getUnsafe(i) { | TextItem(text) => seen->Array.push(text) | CountItem(_) => break }}
Before (JS):
loop_0: for (let i = 0, i_finish = values.length; i < i_finish; ++i) { ... } else { break loop_0; }}
After (JS):
for (let i = 0, i_finish = values.length; i < i_finish; ++i) { ... } else { break; }}