Skip to content

Simplify binder flow. (alternate approach)#2843

Merged
CyrusNajmabadi merged 40 commits into
masterfrom
binderSimplification3
Jun 3, 2015
Merged

Simplify binder flow. (alternate approach)#2843
CyrusNajmabadi merged 40 commits into
masterfrom
binderSimplification3

Conversation

@CyrusNajmabadi
Copy link
Copy Markdown
Contributor

This approach differs from PR #2832 in that it no longer uses SymbolFlags to control recursion and container setting logic in the binder. Instead, we simply use the kind of the node we're currently on to determine what to do. I personally think this is much cleaner and simpler, but i'm sending it out to see what other people think. If you've already reviewed the previous PR, then you only have to start looking at this one with the commits starting on April 20th.

CR notes: I recommend reading this CR one commit at a time to better understand what's going on.

Previously, it was very difficult to reason about the flow of the binder. Different parts of the binder recursed in different ways. For example, some codepaths called bindChildren. Others called forEachChild(node, bind). Some codepaths did not recurse, but were called from paths that woudl then later break out and recurse. This made it very easy to end up doing something wrong if you accidentally returned early. It was also very difficult to know if you should should recurse if you were in bind or bindDeclaration or bindAnonymousDeclaration. The answer was always "it depends".

I've gone in and completely unified the recursion logic in the binder. The top level logic looks like this now:

bind(node: Node) {
    // dispatch and bind this node only
    // recurse and bind children
}

That's it. Individual binding functions never need to worry about recursing. Instead, they just deal with the node they have, and they top level bind driver will always be responsible for recursing. This makes things much easier to reason about and provides a consistent framework for future binding code to follow.

We now only recurse in a single place in the binder.  The rest of the binding
code is only concerned with how to bind a single node to a symbol and add that
symbol to a symbol table.  Recursion is handled as a separate concern, greatly
simplifying binder flow.
Don't use SymbolFlags to direct how we handle containers in the binder.  Instead,
Just determine what we should do based on the .kind of the node itself, and nothing
more.
@DanielRosenwasser
Copy link
Copy Markdown
Member

@CyrusNajmabadi should CatchClause have a container flags value of ContainerFlags.IsBlockScopedContainer | ContainerFlags.HasLocals?

Comment thread src/compiler/binder.ts Outdated
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we use bit shifts instead of hex values? personally I find bit shifts easier to reason about current\subsequent values of the flag since next value of the shift is always +1 to the current one

@vladima
Copy link
Copy Markdown
Contributor

vladima commented Apr 21, 2015

looks good!

@JsonFreeman
Copy link
Copy Markdown
Contributor

👍 I think this is a good augmentation of your prior change #2832

@JsonFreeman
Copy link
Copy Markdown
Contributor

Any movement on this?

CyrusNajmabadi added a commit that referenced this pull request Jun 3, 2015
Simplify binder flow. (alternate approach)
@CyrusNajmabadi CyrusNajmabadi merged commit fc445aa into master Jun 3, 2015
@CyrusNajmabadi CyrusNajmabadi deleted the binderSimplification3 branch June 3, 2015 01:00
@microsoft microsoft locked and limited conversation to collaborators Jun 18, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants