assemblyscript icon indicating copy to clipboard operation
assemblyscript copied to clipboard

Add a ScopeAnalyzer

Open dcodeIO opened this issue 4 years ago • 8 comments

This adds a little ScopeAnalyzer doing a pre-pass on functions, analyzing variable scopes within. Will be helpful to tackle https://github.com/AssemblyScript/assemblyscript/pull/1190 in a more robust way as well as to obtain the information necessary to compile closures. So far all it does is generate diagnostics when something is redeclared that shouldn't be redeclared, and hook into the parser tests to make it testable.

One important implementation criteria is that this works with programmatically generated ASTs, so can't be part of the parser. Not quite happy with the _scope properties on the AST nodes yet, since it would be much nicer if we could serialize the information.

dcodeIO avatar Mar 29 '20 10:03 dcodeIO

I wonder is it open possibilities for doing some ARC early optimizations as well? Or this require Escape Analysis?

MaxGraey avatar Mar 30 '20 14:03 MaxGraey

Not sure, since it neither knows the types nor what exactly a name is referencing after serializing into the AST. The real deal would be a proper checker that does all of this, hmm.

dcodeIO avatar Mar 30 '20 23:03 dcodeIO

Since this PR has been mentioned a couple times recently, perhaps a few notes on why I think it isn't feasible yet. The information it provides currently is "vars bound to this scope", but not "vars not bound to this scope" or "captured by this function". The latter would allow us to prepare captured locals early, in the outer function, while the former triggers too late, that is when a captured variable is first accessed in the inner function. As such this isn't easily forward-compatible to mutable captures.

dcodeIO avatar May 06 '20 19:05 dcodeIO

Keeping this PR open as part of 2020 vacuum. Even though it will most likely not make it in its current form, it might still be a base for a better implementation.

dcodeIO avatar May 16 '20 19:05 dcodeIO

Since this PR has been mentioned a couple times recently, perhaps a few notes on why I think it isn't feasible yet.

Is it not feasible or just not yet done? Could we alter the behaviour of the ScopeAnalyzer to capture when a variable refers to a name from an outer block scope? If not, do you have in mind what would be required to do so?

I'd like to move this forward as the first step towards Closure implementation but I'm not sure if I should use this as a base or if there's something fundamental about it's design that prevents it from detecting enclosed variables that you're referring to in this comment

DuncanUszkay1 avatar Sep 07 '20 17:09 DuncanUszkay1

The issue with this is that the evaluation happens too early, when not all the information closures depend on is available yet (all we know is abstract scopes). The worst case scenario where this fails is a compile time check within a function, where some branches become eliminated and a local may or may not be closed over in the final function, or there's even an inner closure in a closure within such a branch. As such I guess that it'll be necessary to figure out closure-ness during compilation of a function, potentially recompiling if a made assumption did not hold, while propagating that an env is necessary to the enclosing function, which needs to share the environment.

dcodeIO avatar Sep 07 '20 18:09 dcodeIO

The worst case scenario where this fails is a compile time check within a function, where some branches become eliminated and a local may or may not be closed over in the final function, or there's even an inner closure in a closure within such a branch.

Is it possible to run a pass which performs that elimination before the scope analysis and real compilation? Or are these compile time checks not independently resolvable?

I'm not against a recompilation strategy but it seems like eliminating that problem would create easier to follow code 🤔

DuncanUszkay1 avatar Sep 07 '20 18:09 DuncanUszkay1

We don't know the values used in static checks without "compiling" the code, i.e. we can precompute partial expressions. Compiling in this sense means generating Binaryen IR, not necessarily Wasm, which isn't as expensive as it sounds.

dcodeIO avatar Sep 07 '20 19:09 dcodeIO