Skip to content

Commit 79db146

Browse files
committed
Refactor from FlowKind to FlowFlags
1 parent e9122a9 commit 79db146

3 files changed

Lines changed: 80 additions & 77 deletions

File tree

src/compiler/binder.ts

Lines changed: 45 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,8 @@ namespace ts {
129129
let Symbol: { new (flags: SymbolFlags, name: string): Symbol };
130130
let classifiableNames: Map<string>;
131131

132-
const unreachableFlow: FlowNode = { kind: FlowKind.Unreachable };
133-
const reportedUnreachableFlow: FlowNode = { kind: FlowKind.Unreachable };
132+
const unreachableFlow: FlowNode = { flags: FlowFlags.Unreachable };
133+
const reportedUnreachableFlow: FlowNode = { flags: FlowFlags.Unreachable };
134134

135135
function bindSourceFile(f: SourceFile, opts: CompilerOptions) {
136136
file = f;
@@ -471,7 +471,7 @@ namespace ts {
471471
savedActiveLabels = activeLabels;
472472

473473
hasExplicitReturn = false;
474-
currentFlow = { kind: FlowKind.Start };
474+
currentFlow = { flags: FlowFlags.Start };
475475
currentBreakTarget = undefined;
476476
currentContinueTarget = undefined;
477477
activeLabels = undefined;
@@ -483,7 +483,7 @@ namespace ts {
483483

484484
bindReachableStatement(node);
485485

486-
if (currentFlow.kind !== FlowKind.Unreachable && isFunctionLikeKind(kind) && nodeIsPresent((<FunctionLikeDeclaration>node).body)) {
486+
if (!(currentFlow.flags & FlowFlags.Unreachable) && isFunctionLikeKind(kind) && nodeIsPresent((<FunctionLikeDeclaration>node).body)) {
487487
flags |= NodeFlags.HasImplicitReturn;
488488
if (hasExplicitReturn) {
489489
flags |= NodeFlags.HasExplicitReturn;
@@ -639,50 +639,50 @@ namespace ts {
639639
return false;
640640
}
641641

642-
function createFlowLabel(): FlowLabel {
642+
function createBranchLabel(): FlowLabel {
643643
return {
644-
kind: FlowKind.Label,
644+
flags: FlowFlags.BranchLabel,
645645
antecedents: undefined
646646
};
647647
}
648648

649-
function createFlowLoopLabel(): FlowLabel {
649+
function createLoopLabel(): FlowLabel {
650650
return {
651-
kind: FlowKind.LoopLabel,
651+
flags: FlowFlags.LoopLabel,
652652
antecedents: undefined
653653
};
654654
}
655655

656656
function addAntecedent(label: FlowLabel, antecedent: FlowNode): void {
657-
if (antecedent.kind !== FlowKind.Unreachable && !contains(label.antecedents, antecedent)) {
657+
if (!(antecedent.flags & FlowFlags.Unreachable) && !contains(label.antecedents, antecedent)) {
658658
(label.antecedents || (label.antecedents = [])).push(antecedent);
659659
}
660660
}
661661

662-
function createFlowCondition(antecedent: FlowNode, expression: Expression, assumeTrue: boolean): FlowNode {
663-
if (antecedent.kind === FlowKind.Unreachable) {
662+
function createFlowCondition(flags: FlowFlags, antecedent: FlowNode, expression: Expression): FlowNode {
663+
if (antecedent.flags & FlowFlags.Unreachable) {
664664
return antecedent;
665665
}
666666
if (!expression) {
667-
return assumeTrue ? antecedent : unreachableFlow;
667+
return flags & FlowFlags.TrueCondition ? antecedent : unreachableFlow;
668668
}
669-
if (expression.kind === SyntaxKind.TrueKeyword && !assumeTrue || expression.kind === SyntaxKind.FalseKeyword && assumeTrue) {
669+
if (expression.kind === SyntaxKind.TrueKeyword && flags & FlowFlags.FalseCondition ||
670+
expression.kind === SyntaxKind.FalseKeyword && flags & FlowFlags.TrueCondition) {
670671
return unreachableFlow;
671672
}
672673
if (!isNarrowingExpression(expression)) {
673674
return antecedent;
674675
}
675676
return <FlowCondition>{
676-
kind: FlowKind.Condition,
677+
flags,
677678
antecedent,
678679
expression,
679-
assumeTrue
680680
};
681681
}
682682

683683
function createFlowAssignment(antecedent: FlowNode, node: Expression | VariableDeclaration | BindingElement): FlowNode {
684684
return <FlowAssignment>{
685-
kind: FlowKind.Assignment,
685+
flags: FlowFlags.Assignment,
686686
antecedent,
687687
node
688688
};
@@ -747,8 +747,8 @@ namespace ts {
747747
currentTrueTarget = saveTrueTarget;
748748
currentFalseTarget = saveFalseTarget;
749749
if (!node || !isLogicalExpression(node)) {
750-
addAntecedent(trueTarget, createFlowCondition(currentFlow, node, /*assumeTrue*/ true));
751-
addAntecedent(falseTarget, createFlowCondition(currentFlow, node, /*assumeTrue*/ false));
750+
addAntecedent(trueTarget, createFlowCondition(FlowFlags.TrueCondition, currentFlow, node));
751+
addAntecedent(falseTarget, createFlowCondition(FlowFlags.FalseCondition, currentFlow, node));
752752
}
753753
}
754754

@@ -763,9 +763,9 @@ namespace ts {
763763
}
764764

765765
function bindWhileStatement(node: WhileStatement): void {
766-
const preWhileLabel = createFlowLoopLabel();
767-
const preBodyLabel = createFlowLabel();
768-
const postWhileLabel = createFlowLabel();
766+
const preWhileLabel = createLoopLabel();
767+
const preBodyLabel = createBranchLabel();
768+
const postWhileLabel = createBranchLabel();
769769
addAntecedent(preWhileLabel, currentFlow);
770770
currentFlow = preWhileLabel;
771771
bindCondition(node.expression, preBodyLabel, postWhileLabel);
@@ -776,9 +776,9 @@ namespace ts {
776776
}
777777

778778
function bindDoStatement(node: DoStatement): void {
779-
const preDoLabel = createFlowLoopLabel();
780-
const preConditionLabel = createFlowLabel();
781-
const postDoLabel = createFlowLabel();
779+
const preDoLabel = createLoopLabel();
780+
const preConditionLabel = createBranchLabel();
781+
const postDoLabel = createBranchLabel();
782782
addAntecedent(preDoLabel, currentFlow);
783783
currentFlow = preDoLabel;
784784
bindIterativeStatement(node.statement, postDoLabel, preConditionLabel);
@@ -789,9 +789,9 @@ namespace ts {
789789
}
790790

791791
function bindForStatement(node: ForStatement): void {
792-
const preLoopLabel = createFlowLoopLabel();
793-
const preBodyLabel = createFlowLabel();
794-
const postLoopLabel = createFlowLabel();
792+
const preLoopLabel = createLoopLabel();
793+
const preBodyLabel = createBranchLabel();
794+
const postLoopLabel = createBranchLabel();
795795
bind(node.initializer);
796796
addAntecedent(preLoopLabel, currentFlow);
797797
currentFlow = preLoopLabel;
@@ -804,8 +804,8 @@ namespace ts {
804804
}
805805

806806
function bindForInOrForOfStatement(node: ForInStatement | ForOfStatement): void {
807-
const preLoopLabel = createFlowLoopLabel();
808-
const postLoopLabel = createFlowLabel();
807+
const preLoopLabel = createLoopLabel();
808+
const postLoopLabel = createBranchLabel();
809809
addAntecedent(preLoopLabel, currentFlow);
810810
currentFlow = preLoopLabel;
811811
bind(node.expression);
@@ -820,9 +820,9 @@ namespace ts {
820820
}
821821

822822
function bindIfStatement(node: IfStatement): void {
823-
const thenLabel = createFlowLabel();
824-
const elseLabel = createFlowLabel();
825-
const postIfLabel = createFlowLabel();
823+
const thenLabel = createBranchLabel();
824+
const elseLabel = createBranchLabel();
825+
const postIfLabel = createBranchLabel();
826826
bindCondition(node.expression, thenLabel, elseLabel);
827827
currentFlow = finishFlowLabel(thenLabel);
828828
bind(node.thenStatement);
@@ -875,7 +875,7 @@ namespace ts {
875875
}
876876

877877
function bindTryStatement(node: TryStatement): void {
878-
const postFinallyLabel = createFlowLabel();
878+
const postFinallyLabel = createBranchLabel();
879879
const preTryFlow = currentFlow;
880880
// TODO: Every statement in try block is potentially an exit point!
881881
bind(node.tryBlock);
@@ -893,7 +893,7 @@ namespace ts {
893893
}
894894

895895
function bindSwitchStatement(node: SwitchStatement): void {
896-
const postSwitchLabel = createFlowLabel();
896+
const postSwitchLabel = createBranchLabel();
897897
bind(node.expression);
898898
const saveBreakTarget = currentBreakTarget;
899899
const savePreSwitchCaseFlow = preSwitchCaseFlow;
@@ -915,17 +915,17 @@ namespace ts {
915915
for (let i = 0; i < clauses.length; i++) {
916916
const clause = clauses[i];
917917
if (clause.statements.length) {
918-
if (currentFlow.kind === FlowKind.Unreachable) {
918+
if (currentFlow.flags & FlowFlags.Unreachable) {
919919
currentFlow = preSwitchCaseFlow;
920920
}
921921
else {
922-
const preCaseLabel = createFlowLabel();
922+
const preCaseLabel = createBranchLabel();
923923
addAntecedent(preCaseLabel, preSwitchCaseFlow);
924924
addAntecedent(preCaseLabel, currentFlow);
925925
currentFlow = finishFlowLabel(preCaseLabel);
926926
}
927927
bind(clause);
928-
if (currentFlow.kind !== FlowKind.Unreachable && i !== clauses.length - 1 && options.noFallthroughCasesInSwitch) {
928+
if (!(currentFlow.flags & FlowFlags.Unreachable) && i !== clauses.length - 1 && options.noFallthroughCasesInSwitch) {
929929
errorOnFirstToken(clause, Diagnostics.Fallthrough_case_in_switch);
930930
}
931931
}
@@ -951,8 +951,8 @@ namespace ts {
951951
}
952952

953953
function bindLabeledStatement(node: LabeledStatement): void {
954-
const preStatementLabel = createFlowLoopLabel();
955-
const postStatementLabel = createFlowLabel();
954+
const preStatementLabel = createLoopLabel();
955+
const postStatementLabel = createBranchLabel();
956956
bind(node.label);
957957
addAntecedent(preStatementLabel, currentFlow);
958958
const activeLabel = pushActiveLabel(node.label.text, postStatementLabel, preStatementLabel);
@@ -1001,7 +1001,7 @@ namespace ts {
10011001
}
10021002

10031003
function bindLogicalExpression(node: BinaryExpression, trueTarget: FlowLabel, falseTarget: FlowLabel) {
1004-
const preRightLabel = createFlowLabel();
1004+
const preRightLabel = createBranchLabel();
10051005
if (node.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken) {
10061006
bindCondition(node.left, preRightLabel, falseTarget);
10071007
}
@@ -1031,7 +1031,7 @@ namespace ts {
10311031
const operator = node.operatorToken.kind;
10321032
if (operator === SyntaxKind.AmpersandAmpersandToken || operator === SyntaxKind.BarBarToken) {
10331033
if (isTopLevelLogicalExpression(node)) {
1034-
const postExpressionLabel = createFlowLabel();
1034+
const postExpressionLabel = createBranchLabel();
10351035
bindLogicalExpression(node, postExpressionLabel, postExpressionLabel);
10361036
currentFlow = finishFlowLabel(postExpressionLabel);
10371037
}
@@ -1048,9 +1048,9 @@ namespace ts {
10481048
}
10491049

10501050
function bindConditionalExpressionFlow(node: ConditionalExpression) {
1051-
const trueLabel = createFlowLabel();
1052-
const falseLabel = createFlowLabel();
1053-
const postExpressionLabel = createFlowLabel();
1051+
const trueLabel = createBranchLabel();
1052+
const falseLabel = createBranchLabel();
1053+
const postExpressionLabel = createBranchLabel();
10541054
bindCondition(node.condition, trueLabel, falseLabel);
10551055
currentFlow = finishFlowLabel(trueLabel);
10561056
bind(node.whenTrue);
@@ -2065,7 +2065,7 @@ namespace ts {
20652065
}
20662066

20672067
function checkUnreachable(node: Node): boolean {
2068-
if (currentFlow.kind !== FlowKind.Unreachable) {
2068+
if (!(currentFlow.flags & FlowFlags.Unreachable)) {
20692069
return false;
20702070
}
20712071
if (currentFlow === unreachableFlow) {

src/compiler/checker.ts

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7585,27 +7585,28 @@ namespace ts {
75857585

75867586
function getTypeAtFlowNode(flow: FlowNode): Type {
75877587
while (true) {
7588-
switch (flow.kind) {
7589-
case FlowKind.Assignment:
7590-
const type = getTypeAtFlowAssignment(<FlowAssignment>flow);
7591-
if (!type) {
7592-
flow = (<FlowAssignment>flow).antecedent;
7593-
continue;
7594-
}
7595-
return type;
7596-
case FlowKind.Condition:
7597-
return getTypeAtFlowCondition(<FlowCondition>flow);
7598-
case FlowKind.Label:
7599-
case FlowKind.LoopLabel:
7600-
if ((<FlowLabel>flow).antecedents.length === 1) {
7601-
flow = (<FlowLabel>flow).antecedents[0];
7602-
continue;
7603-
}
7604-
return getTypeAtFlowLabel(<FlowLabel>flow);
7605-
case FlowKind.Unreachable:
7606-
// Unreachable code errors are reported in the binding phase. Here we
7607-
// simply return the declared type to reduce follow-on errors.
7608-
return declaredType;
7588+
if (flow.flags & FlowFlags.Assignment) {
7589+
const type = getTypeAtFlowAssignment(<FlowAssignment>flow);
7590+
if (!type) {
7591+
flow = (<FlowAssignment>flow).antecedent;
7592+
continue;
7593+
}
7594+
return type;
7595+
}
7596+
if (flow.flags & FlowFlags.Condition) {
7597+
return getTypeAtFlowCondition(<FlowCondition>flow);
7598+
}
7599+
if (flow.flags & FlowFlags.Label) {
7600+
if ((<FlowLabel>flow).antecedents.length === 1) {
7601+
flow = (<FlowLabel>flow).antecedents[0];
7602+
continue;
7603+
}
7604+
return getTypeAtFlowLabel(<FlowLabel>flow);
7605+
}
7606+
if (flow.flags & FlowFlags.Unreachable) {
7607+
// Unreachable code errors are reported in the binding phase. Here we
7608+
// simply return the declared type to reduce follow-on errors.
7609+
return declaredType;
76097610
}
76107611
// At the top of the flow we have the initial type
76117612
return initialType;
@@ -7644,7 +7645,7 @@ namespace ts {
76447645

76457646
function getTypeAtFlowCondition(flow: FlowCondition) {
76467647
const type = getTypeAtFlowNode(flow.antecedent);
7647-
return type && narrowType(type, flow.expression, flow.assumeTrue);
7648+
return type && narrowType(type, flow.expression, (flow.flags & FlowFlags.TrueCondition) !== 0);
76487649
}
76497650

76507651
function getTypeAtFlowNodeCached(flow: FlowNode) {
@@ -7676,7 +7677,7 @@ namespace ts {
76767677
function getTypeAtFlowLabel(flow: FlowLabel) {
76777678
const antecedentTypes: Type[] = [];
76787679
for (const antecedent of flow.antecedents) {
7679-
const type = flow.kind === FlowKind.LoopLabel ?
7680+
const type = flow.flags & FlowFlags.LoopLabel ?
76807681
getTypeAtFlowNodeCached(antecedent) :
76817682
getTypeAtFlowNode(antecedent);
76827683
if (!type) {

src/compiler/types.ts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1515,17 +1515,20 @@ namespace ts {
15151515
isBracketed: boolean;
15161516
}
15171517

1518-
export const enum FlowKind {
1519-
Unreachable,
1520-
Start,
1521-
Label,
1522-
LoopLabel,
1523-
Assignment,
1524-
Condition
1518+
export const enum FlowFlags {
1519+
Unreachable = 1 << 0,
1520+
Start = 1 << 1,
1521+
BranchLabel = 1 << 2,
1522+
LoopLabel = 1 << 3,
1523+
Assignment = 1 << 4,
1524+
TrueCondition = 1 << 5,
1525+
FalseCondition = 1 << 6,
1526+
Label = BranchLabel | LoopLabel,
1527+
Condition = TrueCondition | FalseCondition
15251528
}
15261529

15271530
export interface FlowNode {
1528-
kind: FlowKind; // Node kind
1531+
flags: FlowFlags;
15291532
id?: number; // Node id used by flow type cache in checker
15301533
}
15311534

@@ -1545,7 +1548,6 @@ namespace ts {
15451548
// node's location in the control flow.
15461549
export interface FlowCondition extends FlowNode {
15471550
expression: Expression;
1548-
assumeTrue: boolean;
15491551
antecedent: FlowNode;
15501552
}
15511553

0 commit comments

Comments
 (0)