Open rakudrama opened 7 years ago
One thing to note is that the *
variants, e.g. sync*
can enter the state machine after it is finished.
moveNext()
continues to return false
.
This means that the transformed program should have a state that is 'stuck' at 'finished'.
In the case of sync*
, we could swizzle out the _body
in _SyncStarIterator
to a special 'stuck at finished' body to remove this constraint.
The general purpose rewritten code has several shortcomings
[ ] Some expressions are needlessly assigned to temporaries. This is usually when
await
is a subexpression.We should never put $async$self (aka captured 'this') in a temporary. The JavaScript could come with a side-table of property accesses that are insensitive to evaluation order, to prevent other cases like
J
.[ ] Return statements are transformed into code that uses the state-machine to
goto
a single return case. These should rather be generated in-place. Doing so would often result in smaller minified code and fewer case statements and might allow the elimination of thereturnValue
variable. To do this well, the transformer will require awareness of when the continuation is a return, since the return can be after a join point or outside a loop.[ ] Receiver type checks and argument type checks are compiled to
if (test) return e
wheree
always throws. These should be left as-is and not be transformed into async return code.[ ] If there is no exception control flow, the rethrow code can be folded into the error code test, eliminating the
handler
andcurrentError
variables and the case label.[ ] Straight-line code might not need the loop (with the above changes it might never use 'break' to reach the
switch
twice)Example: