We currently lower switch case test values within the wrong scope: the test
value really should be a value block rather than a `Place`. Until then, this PR
adds a bailout for complex test values: we allow primitives and identifiers
which should cover most real-world use-cases.
No need for InferAliasForStores to know about the semantics of each instruction
anymore. It's just a simple pass that iterates over every operand and lvalue.
The FunctionExpression is special cased because it's slightly different but I
have a follow up that removes this special casing.
This doesn't change codegen as the lvalue is unused but it lets us make this
pass be semantically the same across all instructions -- "alias lvalue and
operands of an instr".
Adds limited support for UpdateExpressions (`x++`). We now support the postfix
form (`x++` ok, `++x` is a todo) and only when the argument is an identifier. We
can relax these restrictions with more work, but this PR should be sufficient
for the examples we've seen so far.
Support TypeCastExpressions — `(x: TypeAnnotation)`. This is pretty
straightforward, it's semantically identical to a raw identifier.
One catch is that our prettier config is hard-coded to use the babel-ts parser,
i wasn't sure how to make that dynamic based on the file extension so for now i
just ignored .flow.js files in our pretter config.
```
function useBar(props) {
let z;
if (props.a) {
if (props.b) {
z = baz();
}
}
return z;
}
```
Currently fails with
```
InvariantViolation: A phi cannot have two operands initialized before its
declaration
```
Changes ReactiveWhileTerminal’s test to use the new value block representation.
This means logical and condition expressions will work as while test values now.
Updates some passes from ReactiveScopes/ to use the visitor added in the
previous PR. The +124/-354 line count on this diff tells the story — the new
visitor avoids a lot of boilerplate and helps focus on the logic not the
traversal.
Note that there are a few passes which transform the function such as
adding/removing scopes. A follow-up will extend the visitor to support that and
convert the remaining passes.
This adds a truly general-purpose visitor pattern for ReactiveFunction, modeled
on what's worked well in Relay Compiler. All types of node that have children
get a visitFoo/traverseFoo pair of functions. By default the visitFoo() function
delegates to the traverseFoo() function, but the visit variant is meant to be
overridden and can delegate to the traverseFoo() variant — this gives you
precise control so that you can save/restore state before/after traversing
children.
Probably the only interesting thing is that visitLValue() does not call
visitPlace() by default though it technically could. So far that is making sense
in the passes i converted.
Note that once all passes are updated to use this, i'll delete the other visitor
helpers for ReactiveFunction.
There's a bug with assignment expression in normal value blocks due to LeaveSSA.
Until that's resolved i'm temporarily distinguishing "loop" blocks and "value"
blocks, and disallowing assignment expressions in value blocks specifically.
Support conditional expressions from AST -> HIR -> ReactiveFunction -> AST. This
also helps make the patterns for value block handling more clear, so i was able
to extract some reusable logic in the HIR -> ReactiveFunction conversion phase.
Implements the conversion from LogicalTerminal into a ReactiveLogicalValue (and
ReactiveSequenveValue if necessary). The implementation is a bit rough, i clean
it up in subsequent PRs which revealed parts of the logic that could be shared w
ternaries.
Extends ReactiveInstruction's value type to be a regular InstructionValue *or* a
LogicalValue. LogicalValue is operator, left, and right. It's really convenient
that we've already distinguished Instruction/ReactiveInstruction now — while the
_helpers_ here are updated to handle this new value type, the types ensure that
HIR can never encounter a LogicalValue.
The actual conversion of logical terminals into this value is complex and is
later in the stack.
Changes the lowering for LogicalExpression to use the new 'logical' terminal.
Whereas before we tried to more directly model the semantics of `??` by
generating an `if (<lhs> != null)`, we now generate a branch terminal that looks
at the lhs.
The HIR -> ReactiveFunction construction for logical and branch terminals are
placeholders while I refactor the ReactiveFunction representation to support
value blocks.