explain control flow a bit
This commit is contained in:
Родитель
e71a6c81b5
Коммит
8683f92291
|
@ -137,7 +137,44 @@ TODO: Finish this
|
|||
|
||||
## Control Flow
|
||||
|
||||
TODO: Missing completely
|
||||
Like symbols, control flow involves a walk of the tree, setting some information for certain kinds of nodes and skipping all other nodes.
|
||||
For control flow, nodes that can narrow or otherwise introduce type information are the relevant ones.
|
||||
Containers and declarations are the same as for symbol binding, so those concepts are reused.
|
||||
Declarations introduce type information; containers form the scope where type information is relevant.
|
||||
Other nodes may narrow, so they also interact with control flow.
|
||||
|
||||
The control flow graph is a directed acyclic graph; that means each relevant node points to its antecedents (parents).
|
||||
Specifically, each node can have a `flowNode`; this flow node has a `kind` and one or more `antecedents`.
|
||||
As the binder walks the tree, `bindWorker` assigns the current flow node to specific nodes that can introduce type information.
|
||||
Specific nodes that affect control flow alter the current flow node, such as `bindWhileStatement`.
|
||||
|
||||
Here's an example:
|
||||
|
||||
```ts
|
||||
function f(x: string | number) {
|
||||
if (typeof x === 'string') {
|
||||
return x
|
||||
} else {
|
||||
console.log(x)
|
||||
}
|
||||
return x
|
||||
}
|
||||
```
|
||||
|
||||
Here, the binder creates a `FlowStart` for `x: string | number`.
|
||||
Then when it walks the `if/else`, it creates two `FlowCondition` nodes, each with an antecedent of the original `FlowStart`.
|
||||
The two nodes correspond to the `then` body—where the condition `typeof x === "string"` is true—and the `else` body—where it's false.
|
||||
For `return x` inside the `then` body, it creates an Unreachable flow node.
|
||||
It also creates a post-if `FlowLabel` that joins the control flow between the two branches of the conditional.
|
||||
|
||||
During checking of various references of `x`, control flow analysis will walk up the tree until it finds a control flow node, at which point it runs back through the control flow graph until it reaches a `FlowStart`.
|
||||
For example, to check the first `x` reference in `typeof x === "string"`, it walks up *past* the `if` — the condition is not contained in the flow of the `then` or the `else` bodies — and reaches FlowStart.
|
||||
The type here is `string | number`.
|
||||
But in the first `return x`, the first flow node it reaches is the `FlowCondition` for the `then` branch of the if/else.
|
||||
That check narrows `string | number` to `string`.
|
||||
Finally, the last `return x` starts with the post-if flow node, which unions the types that result from the `then` and `else` branches.
|
||||
But because the `then` branch returns, it doesn't contribute anything to the union; the resulting type is just `number`.
|
||||
|
||||
|
||||
## Emit flags
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче