(Implemented as per discussions with @gsathya )
Handle OptionalMemberExpression by adding an 'optional' flag to `PropertyLoad`
instruction, which is set during `BuildHIR` and read during
`CodegenReactiveFunction`.
This commit repurposes CompilerError to represent an aggregate of error details
accumulated during HIR lowering. It also fixes the playground to correctly
render errors again.
Functions can capture variables declared after the definition of the function.
This re runs SSA to map the captured identifiers to the new SSA identifiers if
available.
As discussed, this repurposes OtherStatement as a catch all variant for
unsupported syntax or errors in the source. This also renames the previously
added ErrorTerminal to UnsupportedTerminal for consistency (plus makes it a
little bit less confusing that it's not an actual terminal representing an
Error).
Not loving the name but couldn't think of anything better, open to suggestions!
When `MergeOverlappingReactiveScopes` identified scopes to be merged, it was
currently (oops, my bad) updating the _existing_ scope's id and range. Later,
PropagateScopeDependencies marks outputs of a scope by updating that
identifier's scope instance — so if that scope instance isn't shared, then the
output is lost. This PR fixes MergeOverlappingReactiveScopes to correctly update
all operands for a scope to have the same scope instance.
Makes debugging a little easier as the previous console.error would be logged
out of band with the jest error message. And the jest error would be missing the
error stack.
After some painful debugging I isolated the infinite loop when attempting to use
the BabelPlugin in hir-test rather than manually parsing and traversing it. The
issue is that in the BabelPlugin we were replacing the original
FunctionDeclaration with a new one, which would add it to Babel's traversal
queue. This would effectively create an infinite loop where we would try to
optimize a function that was already compiled by Forget (aside: _should_ running
the compiler multiple times on code work?).
To get around this we can just call the handy `skip` method on the new
FunctionDeclaration to tell Babel to stop traversing it. I'm also moving the
scope check here because I'll remove it from hir-test in a later commit.
Lower member expression if the receiver is in scope. Skip the remaining path
before capturing so we don't recurse down the identifiers in the member
expression.
Avoids printing debug information if it exactly matches what was last printed.
This means when debug printing (eg with `@only`) you'll see things like:
```
BuildReactiveFunctions:
...debug view...
FlattenReactiveLoops: (no change)
PropagateScopeDependencies:
...debug view...
```
Which saves time figuring out if something changed in a given pass.
Per design discussion, this PR changes BuildHIR to maintain the invariant that,
for each distinct variable in the input, that all references to that variable in
the HIR will have the same unique `name` _and_ same unique `id`. Phrased
differently: Identifiers with the same id will have the same name and
vice-versa.
This isn't an invariant we maintain throughout compilation — SSA form changes
the `id`s — but crucially, ensuring that the `name` is also unique allows us to
understand later which identifiers referred to the same original variable and
which were different.
Follow-up PRs will ensure that we maintain variable identifiers in the output as
well, in all cases except shadowing (and for shadowing, we'll rewrite
identifiers inside lambdas).