@@ -701,12 +701,31 @@ abstract class NodeOperations<Expression> {
701701 Expression unwrapParenthesized (Expression node);
702702}
703703
704+ /// An instance of the [State] class represents the information gathered by flow
705+ /// analysis at a single point in the control flow of the function or method
706+ /// being analyzed.
707+ ///
708+ /// Instances of this class are immuatable, so the methods below that "update"
709+ /// the state actually leave `this` unchanged and return a new state object.
704710@visibleForTesting
705711class State <Variable , Type > {
712+ /// Indicates whether this point in the control flow is reachable.
706713 final bool reachable;
714+
715+ /// The set of variables that are not yet definitely assigned at this point in
716+ /// the control flow.
707717 final _VariableSet <Variable > notAssigned;
718+
719+ /// For each variable whose type is promoted at this point in the control
720+ /// flow, the promoted type. Variables whose type is not promoted are not
721+ /// present in the map. Variables that have gone out of scope are not
722+ /// guaranteed to be present in the map even if they were promoted at the time
723+ /// they went out of scope.
708724 final Map <Variable , Type > promoted;
709725
726+ /// Creates a state object with the given [reachable] status. All variables
727+ /// are assumed to be unpromoted and already assigned, so joining another
728+ /// state with this one will have no effect on it.
710729 State (bool reachable)
711730 : this ._(
712731 reachable,
@@ -720,7 +739,9 @@ class State<Variable, Type> {
720739 this .promoted,
721740 );
722741
723- /// Add a new [variable] to track definite assignment.
742+ /// Updates the state to track a newly declared local [variable] . The
743+ /// optional [assigned] boolean indicates whether the variable is assigned at
744+ /// the point of declaration.
724745 State <Variable , Type > add (Variable variable, {bool assigned: false }) {
725746 var newNotAssigned = assigned ? notAssigned : notAssigned.add (variable);
726747
@@ -735,6 +756,7 @@ class State<Variable, Type> {
735756 );
736757 }
737758
759+ /// Updates the state to indicate that the control flow path is unreachable.
738760 State <Variable , Type > exit () {
739761 return State <Variable , Type >._(
740762 false ,
@@ -743,6 +765,11 @@ class State<Variable, Type> {
743765 );
744766 }
745767
768+ /// Updates the state to indicate that the given [variable] has been
769+ /// determined to contain a non-null value.
770+ ///
771+ /// TODO(paulberry): should this method mark the variable as definitely
772+ /// assigned? Does it matter?
746773 State <Variable , Type > markNonNullable (
747774 TypeOperations <Variable , Type > typeOperations, Variable variable) {
748775 var previousType = promoted[variable];
@@ -762,6 +789,14 @@ class State<Variable, Type> {
762789 return this ;
763790 }
764791
792+ /// Updates the state to indicate that the given [variable] has been
793+ /// determined to satisfy the given [type] .
794+ ///
795+ /// Note that the state is only changed if [type] is a subtype of the
796+ /// variable's previous (possibly promoted) type.
797+ ///
798+ /// TODO(paulberry): if the type is non-nullable, should this method mark the
799+ /// variable as definitely assigned? Does it matter?
765800 State <Variable , Type > promote (
766801 TypeOperations <Variable , Type > typeOperations,
767802 Variable variable,
@@ -784,6 +819,8 @@ class State<Variable, Type> {
784819 return this ;
785820 }
786821
822+ /// Updates the state to indicate that the given [variables] are no longer
823+ /// promoted; they are presumed to have their declared types.
787824 State <Variable , Type > removePromotedAll (Set <Variable > variables) {
788825 var newPromoted = _removePromotedAll (promoted, variables);
789826
@@ -796,6 +833,16 @@ class State<Variable, Type> {
796833 );
797834 }
798835
836+ /// Updates the state to reflect a control path that is known to have
837+ /// previously passed through some [other] state.
838+ ///
839+ /// The control flow path is considered reachable if both this state and the
840+ /// other state are reachable. Variables are considered definitely assigned
841+ /// if they were definitely assigned in either this state or the other state.
842+ /// Variable type promotions are taken from this state, unless the promotion
843+ /// in the other state is more specific, and the variable is "safe". A
844+ /// variable is considered safe if there is no chance that it was assigned
845+ /// more recently than the "other" state.
799846 State <Variable , Type > restrict (
800847 TypeOperations <Variable , Type > typeOperations,
801848 _VariableSet <Variable > emptySet,
@@ -866,6 +913,8 @@ class State<Variable, Type> {
866913 );
867914 }
868915
916+ /// Updates the state to indicate whether the control flow path is
917+ /// [reachable] .
869918 State <Variable , Type > setReachable (bool reachable) {
870919 if (this .reachable == reachable) return this ;
871920
@@ -879,6 +928,11 @@ class State<Variable, Type> {
879928 @override
880929 String toString () => '($reachable , $notAssigned , $promoted )' ;
881930
931+ /// Updates the state to indicate that an assignment was made to the given
932+ /// [variable] . The variable is marked as definitely assigned, and any
933+ /// previous type promotion is removed.
934+ ///
935+ /// TODO(paulberry): allow for writes that preserve type promotions.
882936 State <Variable , Type > write (TypeOperations <Variable , Type > typeOperations,
883937 _VariableSet <Variable > emptySet, Variable variable) {
884938 var newNotAssigned = typeOperations.isLocalVariable (variable)
@@ -899,6 +953,8 @@ class State<Variable, Type> {
899953 );
900954 }
901955
956+ /// Removes a [variable] from a "promoted" [map] , treating the map as
957+ /// immutable.
902958 Map <Variable , Type > _removePromoted (
903959 Map <Variable , Type > map, Variable variable) {
904960 if (map.isEmpty) return const {};
@@ -914,6 +970,8 @@ class State<Variable, Type> {
914970 return result;
915971 }
916972
973+ /// Removes a set of [variable] s from a "promoted" [map] , treating the map as
974+ /// immutable.
917975 Map <Variable , Type > _removePromotedAll (
918976 Map <Variable , Type > map,
919977 Set <Variable > variables,
@@ -936,6 +994,8 @@ class State<Variable, Type> {
936994 return result;
937995 }
938996
997+ /// Creates a new [State] object, unless it is equivalent to either [first] or
998+ /// [second] , in which case one of those objects is re-used.
939999 static State <Variable , Type > _identicalOrNew <Variable , Type >(
9401000 State <Variable , Type > first,
9411001 State <Variable , Type > second,
@@ -961,6 +1021,7 @@ class State<Variable, Type> {
9611021 );
9621022 }
9631023
1024+ /// Determines whether the given "promoted" maps are equivalent.
9641025 static bool _promotionsEqual <Variable , Type >(
9651026 TypeOperations <Variable , Type > typeOperations,
9661027 Map <Variable , Type > p1,
0 commit comments