refactor scopes to add top-level and block scope (related!) #5475
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Problem
This investigation was initially motivated by the desire to add notation for explicit
var
declarations, in particular so that we might be able to attach JSDoc comments to them (see #5377 (comment)). However, I then happened upon the following snippet:coffeescript/src/nodes.coffee
Lines 3224 to 3230 in 817c39a
I realized that "block scope" (as per
let
andconst
) is related toimport
andexport
declarations: because we don't currently have a concept of "block scope", we are also unable to validate module statements, because those must be performed at the top-level scope--not within a block scope!Solution
Scope
is now aware of bothvar
(function) and block scope.TopLevelScope
at the top level.import
/export
bookkeeping.BlockScope
type wherever we introduce a new block scope.if
block or at top-level (module) scope.Result
No external change: this code is largely an internal refactoring! Some code which would definitely have failed at runtime (attempting to assign to an imported symbol) is now caught at compile-time. I believe this is a desirable feature, but it may cause a command to error which didn't before. We could convert this into a warning if that is considered a breakage.
Otherwise, our solution is general, and works for both compilation and ast generation. The snippet at top has been obsoleted, and these tests now use simply
assertErrorFormat()
:coffeescript/test/error_messages.coffee
Lines 1117 to 1133 in 817c39a
There were some tests which incorrectly interpreted the
default
import/export identifier, so these were removed and/or fixed as well.Future Work
This should pave the way for #4985, #5377, #5445, but is completely independent of them.
The big takeaway with this change is that a concept of block scope is intricately related to the top-level scope required for
import
/export
declarations. Having to wrangle the myriad behaviors of ES6 module statements was not exactly fun, but this PR demonstrates that the CoffeeScript compiler is able to have an awareness of block scope without any breaking changes or syntax changes.