@@ -60,7 +60,7 @@ class FlowAnalysis<Statement, Expression, Variable, Type> {
6060 final FunctionBodyAccess <Variable > functionBody;
6161
6262 /// The stack of states of variables that are not definitely assigned.
63- final List <State <Variable , Type >> _stack = [];
63+ final List <FlowModel <Variable , Type >> _stack = [];
6464
6565 /// The mapping from labeled [Statement] s to the index in the [_stack]
6666 /// where the first related element is located. The number of elements
@@ -71,16 +71,16 @@ class FlowAnalysis<Statement, Expression, Variable, Type> {
7171 /// List of all variables passed to [add] .
7272 final List <Variable > _addedVariables = [];
7373
74- State <Variable , Type > _current;
74+ FlowModel <Variable , Type > _current;
7575
7676 /// The last boolean condition, for [_conditionTrue] and [_conditionFalse] .
7777 Expression _condition;
7878
7979 /// The state when [_condition] evaluates to `true` .
80- State <Variable , Type > _conditionTrue;
80+ FlowModel <Variable , Type > _conditionTrue;
8181
8282 /// The state when [_condition] evaluates to `false` .
83- State <Variable , Type > _conditionFalse;
83+ FlowModel <Variable , Type > _conditionFalse;
8484
8585 /// If assertions are enabled, keeps track of all variables that have been
8686 /// passed into the API (other than through a call to [add] ). The [finish]
@@ -100,7 +100,7 @@ class FlowAnalysis<Statement, Expression, Variable, Type> {
100100 TypeOperations <Variable , Type > typeOperations,
101101 FunctionBodyAccess <Variable > functionBody,
102102 ) {
103- var emptySet = State <Variable , Type >(false ).notAssigned;
103+ var emptySet = FlowModel <Variable , Type >(false ).notAssigned;
104104 return FlowAnalysis ._(
105105 nodeOperations,
106106 typeOperations,
@@ -115,7 +115,7 @@ class FlowAnalysis<Statement, Expression, Variable, Type> {
115115 this .functionBody,
116116 this ._emptySet,
117117 ) {
118- _current = State <Variable , Type >(true );
118+ _current = FlowModel <Variable , Type >(true );
119119 }
120120
121121 /// Return `true` if the current state is reachable.
@@ -357,8 +357,8 @@ class FlowAnalysis<Statement, Expression, Variable, Type> {
357357 }
358358
359359 void ifStatement_end (bool hasElse) {
360- State <Variable , Type > afterThen;
361- State <Variable , Type > afterElse;
360+ FlowModel <Variable , Type > afterThen;
361+ FlowModel <Variable , Type > afterElse;
362362 if (hasElse) {
363363 afterThen = _stack.removeLast ();
364364 afterElse = _current;
@@ -604,9 +604,9 @@ class FlowAnalysis<Statement, Expression, Variable, Type> {
604604 }
605605 }
606606
607- State <Variable , Type > _join (
608- State <Variable , Type > first, State <Variable , Type > second) =>
609- State .join (typeOperations, first, second);
607+ FlowModel <Variable , Type > _join (
608+ FlowModel <Variable , Type > first, FlowModel <Variable , Type > second) =>
609+ FlowModel .join (typeOperations, first, second);
610610
611611 /// If assertions are enabled, records that the given variable has been
612612 /// referenced. The [finish] method will verify that all referenced variables
@@ -629,27 +629,14 @@ class FlowAnalysis<Statement, Expression, Variable, Type> {
629629 }
630630}
631631
632- /// Accessor for function body information.
633- abstract class FunctionBodyAccess <Variable > {
634- bool isPotentiallyMutatedInClosure (Variable variable);
635-
636- bool isPotentiallyMutatedInScope (Variable variable);
637- }
638-
639- /// Operations on nodes, abstracted from concrete node interfaces.
640- abstract class NodeOperations <Expression > {
641- /// If the [node] is a parenthesized expression, recursively unwrap it.
642- Expression unwrapParenthesized (Expression node);
643- }
644-
645- /// An instance of the [State] class represents the information gathered by flow
646- /// analysis at a single point in the control flow of the function or method
647- /// being analyzed.
632+ /// An instance of the [FlowModel] class represents the information gathered by
633+ /// flow analysis at a single point in the control flow of the function or
634+ /// method being analyzed.
648635///
649636/// Instances of this class are immutable, so the methods below that "update"
650637/// the state actually leave `this` unchanged and return a new state object.
651638@visibleForTesting
652- class State <Variable , Type > {
639+ class FlowModel <Variable , Type > {
653640 /// Indicates whether this point in the control flow is reachable.
654641 final bool reachable;
655642
@@ -675,14 +662,14 @@ class State<Variable, Type> {
675662 /// Creates a state object with the given [reachable] status. All variables
676663 /// are assumed to be unpromoted and already assigned, so joining another
677664 /// state with this one will have no effect on it.
678- State (bool reachable)
665+ FlowModel (bool reachable)
679666 : this ._(
680667 reachable,
681668 _VariableSet <Variable >._(const []),
682669 const {},
683670 );
684671
685- State ._(
672+ FlowModel ._(
686673 this .reachable,
687674 this .notAssigned,
688675 this .promoted,
@@ -691,14 +678,14 @@ class State<Variable, Type> {
691678 /// Updates the state to track a newly declared local [variable] . The
692679 /// optional [assigned] boolean indicates whether the variable is assigned at
693680 /// the point of declaration.
694- State <Variable , Type > add (Variable variable, {bool assigned: false }) {
681+ FlowModel <Variable , Type > add (Variable variable, {bool assigned: false }) {
695682 var newNotAssigned = assigned ? notAssigned : notAssigned.add (variable);
696683
697684 if (identical (newNotAssigned, notAssigned)) {
698685 return this ;
699686 }
700687
701- return State <Variable , Type >._(
688+ return FlowModel <Variable , Type >._(
702689 reachable,
703690 newNotAssigned,
704691 promoted,
@@ -710,7 +697,7 @@ class State<Variable, Type> {
710697 ///
711698 /// TODO(paulberry): should this method mark the variable as definitely
712699 /// assigned? Does it matter?
713- State <Variable , Type > markNonNullable (
700+ FlowModel <Variable , Type > markNonNullable (
714701 TypeOperations <Variable , Type > typeOperations, Variable variable) {
715702 var previousType = promoted[variable];
716703 previousType ?? = typeOperations.variableType (variable);
@@ -719,7 +706,7 @@ class State<Variable, Type> {
719706 if (! typeOperations.isSameType (type, previousType)) {
720707 var newPromoted = < Variable , Type > {}..addAll (promoted);
721708 newPromoted[variable] = type;
722- return State <Variable , Type >._(
709+ return FlowModel <Variable , Type >._(
723710 reachable,
724711 notAssigned,
725712 newPromoted,
@@ -738,7 +725,7 @@ class State<Variable, Type> {
738725 ///
739726 /// TODO(paulberry): if the type is non-nullable, should this method mark the
740727 /// variable as definitely assigned? Does it matter?
741- State <Variable , Type > promote (
728+ FlowModel <Variable , Type > promote (
742729 TypeOperations <Variable , Type > typeOperations,
743730 Variable variable,
744731 Type type,
@@ -750,7 +737,7 @@ class State<Variable, Type> {
750737 ! typeOperations.isSameType (type, previousType)) {
751738 var newPromoted = < Variable , Type > {}..addAll (promoted);
752739 newPromoted[variable] = type;
753- return State <Variable , Type >._(
740+ return FlowModel <Variable , Type >._(
754741 reachable,
755742 notAssigned,
756743 newPromoted,
@@ -779,12 +766,12 @@ class State<Variable, Type> {
779766 /// and only remove promotions if it can be shown that they aren't restored
780767 /// later in the loop body. If we switch to a fixed point analysis, we should
781768 /// be able to remove this method.
782- State <Variable , Type > removePromotedAll (Set <Variable > variables) {
769+ FlowModel <Variable , Type > removePromotedAll (Set <Variable > variables) {
783770 var newPromoted = _removePromotedAll (promoted, variables);
784771
785772 if (identical (newPromoted, promoted)) return this ;
786773
787- return State <Variable , Type >._(
774+ return FlowModel <Variable , Type >._(
788775 reachable,
789776 notAssigned,
790777 newPromoted,
@@ -811,10 +798,10 @@ class State<Variable, Type> {
811798 /// state from the `try` block). Variables that are assigned in the `finally`
812799 /// block are considered "unsafe" because the assignment might have cancelled
813800 /// the effect of any promotion that occurred inside the `try` block.
814- State <Variable , Type > restrict (
801+ FlowModel <Variable , Type > restrict (
815802 TypeOperations <Variable , Type > typeOperations,
816803 _VariableSet <Variable > emptySet,
817- State <Variable , Type > other,
804+ FlowModel <Variable , Type > other,
818805 Set <Variable > unsafe,
819806 ) {
820807 var newReachable = reachable && other.reachable;
@@ -883,10 +870,10 @@ class State<Variable, Type> {
883870
884871 /// Updates the state to indicate whether the control flow path is
885872 /// [reachable] .
886- State <Variable , Type > setReachable (bool reachable) {
873+ FlowModel <Variable , Type > setReachable (bool reachable) {
887874 if (this .reachable == reachable) return this ;
888875
889- return State <Variable , Type >._(
876+ return FlowModel <Variable , Type >._(
890877 reachable,
891878 notAssigned,
892879 promoted,
@@ -901,7 +888,7 @@ class State<Variable, Type> {
901888 /// previous type promotion is removed.
902889 ///
903890 /// TODO(paulberry): allow for writes that preserve type promotions.
904- State <Variable , Type > write (TypeOperations <Variable , Type > typeOperations,
891+ FlowModel <Variable , Type > write (TypeOperations <Variable , Type > typeOperations,
905892 _VariableSet <Variable > emptySet, Variable variable) {
906893 var newNotAssigned = typeOperations.isLocalVariable (variable)
907894 ? notAssigned.remove (emptySet, variable)
@@ -914,7 +901,7 @@ class State<Variable, Type> {
914901 return this ;
915902 }
916903
917- return State <Variable , Type >._(
904+ return FlowModel <Variable , Type >._(
918905 reachable,
919906 newNotAssigned,
920907 newPromoted,
@@ -971,10 +958,10 @@ class State<Variable, Type> {
971958 /// are kept only if they are common to both input states; if a variable is
972959 /// promoted to one type in one state and a subtype in the other state, the
973960 /// less specific type promotion is kept.
974- static State <Variable , Type > join <Variable , Type >(
961+ static FlowModel <Variable , Type > join <Variable , Type >(
975962 TypeOperations <Variable , Type > typeOperations,
976- State <Variable , Type > first,
977- State <Variable , Type > second,
963+ FlowModel <Variable , Type > first,
964+ FlowModel <Variable , Type > second,
978965 ) {
979966 if (first == null ) return second;
980967 if (second == null ) return first;
@@ -985,9 +972,9 @@ class State<Variable, Type> {
985972 var newReachable = first.reachable || second.reachable;
986973 var newNotAssigned = first.notAssigned.union (second.notAssigned);
987974 var newPromoted =
988- State .joinPromoted (typeOperations, first.promoted, second.promoted);
975+ FlowModel .joinPromoted (typeOperations, first.promoted, second.promoted);
989976
990- return State ._identicalOrNew (
977+ return FlowModel ._identicalOrNew (
991978 first,
992979 second,
993980 newReachable,
@@ -1036,11 +1023,11 @@ class State<Variable, Type> {
10361023 return result;
10371024 }
10381025
1039- /// Creates a new [State ] object, unless it is equivalent to either [first] or
1040- /// [second] , in which case one of those objects is re-used.
1041- static State <Variable , Type > _identicalOrNew <Variable , Type >(
1042- State <Variable , Type > first,
1043- State <Variable , Type > second,
1026+ /// Creates a new [FlowModel ] object, unless it is equivalent to either
1027+ /// [first] or [ second] , in which case one of those objects is re-used.
1028+ static FlowModel <Variable , Type > _identicalOrNew <Variable , Type >(
1029+ FlowModel <Variable , Type > first,
1030+ FlowModel <Variable , Type > second,
10441031 bool newReachable,
10451032 _VariableSet <Variable > newNotAssigned,
10461033 Map <Variable , Type > newPromoted,
@@ -1056,7 +1043,7 @@ class State<Variable, Type> {
10561043 return second;
10571044 }
10581045
1059- return State <Variable , Type >._(
1046+ return FlowModel <Variable , Type >._(
10601047 newReachable,
10611048 newNotAssigned,
10621049 newPromoted,
@@ -1079,6 +1066,19 @@ class State<Variable, Type> {
10791066 }
10801067}
10811068
1069+ /// Accessor for function body information.
1070+ abstract class FunctionBodyAccess <Variable > {
1071+ bool isPotentiallyMutatedInClosure (Variable variable);
1072+
1073+ bool isPotentiallyMutatedInScope (Variable variable);
1074+ }
1075+
1076+ /// Operations on nodes, abstracted from concrete node interfaces.
1077+ abstract class NodeOperations <Expression > {
1078+ /// If the [node] is a parenthesized expression, recursively unwrap it.
1079+ Expression unwrapParenthesized (Expression node);
1080+ }
1081+
10821082/// Operations on types, abstracted from concrete type interfaces.
10831083abstract class TypeOperations <Variable , Type > {
10841084 /// Return `true` if the [variable] is a local variable, not a parameter.
0 commit comments