Closed conartist6 closed 1 year ago
This was pretty cool. I've gotten so used to thinking about things in terms of my nice structure logs that I mocked up the log output before writing the code to produce it. I believe this is the correct solution.
Implemented.
Hoisting v1 consisted of building a tree and then trying to work out hoisting after the fact. Grammars provided
isHoistable
((token) => boolean
), and after a tree was constructed leading and trailing hoistables were spliced into their parents match results. I didn't like the solution that much. I didn't like the splicing, and that you could only tell what was happening after the results were built. That said, the solution worked and seems to have been technically sound, which is more than you can say for anything I've tried to replace it with so far.I will note that when I started ripping out v1, I thought it was unsound because at the time I thought I should be hoisting expression parenthesis. I no longer think that's likely to be correct, but the problem would have been the difficulty of distinguishing between
call()
and(call())
. The algorithm, being poorly integrated with the grammar, there existed the potential to accidentally create a malformed node likecall(
.The v2 implementation integrates hoisting fully into the grammar, using
startNode
andendNode
commands that unambiguously identify the correct hoisting.The v2 implementation has a serious flaw though! You can see it in the log from parsing
o = { foo }
.In this situation
foo
is anIdentifier
wrapped in aProperty
here, which means that correct behavior is to take the leading space before theIdentifier
and hoist it not into theProperty
but into the parentObjectExpression
. Unfortunately you can see in the log thatProperty
emitsstartNode
before it referencesIdentifier
. This has to occur so thatref`key`
ends up in the right place, but it also captures the whitespace, which fails to bubble up throughProperty
as it should.I've tried any number of strategies to resolve this problem, but the parameters for a successful solution are remarkably narrow:
startNode
command should be issued at the correct time, and by the grammar generator. Getting this right increases the value of the command stream to plugins.