The `or` case ran extremely slowly before this change. Also exclude
string interpolations from consideration, for correctness, and add some
more tests.
The `when` node now acts as a join point for patterns in the when
clause, with match/no-match completions. This is similar to how `or`
expressions work.
The result of this is that the `when` clause "controls" the body of the
`when`, which allows us to model barrier guards for multi-pattern when
clauses.
For this code
case x
when 1, 2
y
end
The old CFG was
x --> when --> 1 --no-match--> 2 ---no-match---> case
\ \ ^
\ \ |
\ --match----+ |
\ | |
\ | |
------match---------> y --+
The new CFG is
x --> 1 --no-match--> 2 --no-match--> [no-match] when --no-match--> case
\ \ ^
\ \ |
\ --match--> [match] when --match--> y -----+
\ /
\ /
-------match-----
i.e. all patterns flow to the `when` node, which is split based on
whether the pattern matched or not. The body of the when clause then has
a single predecessor `[match] when`, which acts as condition block that
controls `y`.
This recognises barriers of the form
STRINGS = ["foo", "bar"]
case foo
when "some string literal"
foo
when *["other", "strings"]
foo
when *STRINGS
foo
end
where the reads of `foo` inside each `when` are guarded by the comparison
of `foo` with the string literals.
We don't yet recognise this construct:
case foo
when "foo", "bar"
foo
end
This is due to a limitation in the shared barrier guard logic.