@@ -229,16 +229,16 @@ class AssignedVariablesForTesting<Node, Variable>
229
229
230
230
/// Information tracked by [AssignedVariables] for a single node.
231
231
class AssignedVariablesNodeInfo <Variable > {
232
+ /// The set of local variables that are potentially written in the node.
232
233
final Set <Variable > _written = new Set <Variable >.identity ();
233
234
234
- // The set of local variables that are potentially written in the node.
235
+ /// The set of local variables for which a potential write is captured by a
236
+ /// local function or closure inside the node.
235
237
final Set <Variable > _captured = new Set <Variable >.identity ();
236
238
237
- // The set of local variables for which a potential write is captured by a
238
- // local function or closure inside the node.
239
+ /// The set of local variables that are declared in the node.
239
240
final Set <Variable > _declared = new Set <Variable >.identity ();
240
241
241
- // The set of local variables that are declared in the node.
242
242
String toString () =>
243
243
'AssignedVariablesNodeInfo(_written=$_written , _captured=$_captured , '
244
244
'_declared=$_declared )' ;
@@ -341,6 +341,13 @@ abstract class FlowAnalysis<Node, Statement extends Node, Expression, Variable,
341
341
/// ("?:"). [condition] should be the expression preceding the "?".
342
342
void conditional_thenBegin (Expression condition);
343
343
344
+ /// Register a declaration of the [variable] in the current state.
345
+ /// Should also be called for function parameters.
346
+ ///
347
+ /// A local variable is [initialized] if its declaration has an initializer.
348
+ /// A function parameter is always initialized, so [initialized] is `true` .
349
+ void declare (Variable variable, bool initialized);
350
+
344
351
/// Call this method before visiting the body of a "do-while" statement.
345
352
/// [doStatement] should be the same node that was passed to
346
353
/// [AssignedVariables.endNode] for the do-while statement.
@@ -494,10 +501,6 @@ abstract class FlowAnalysis<Node, Statement extends Node, Expression, Variable,
494
501
/// - Call [ifStatement_end] , passing `true` for `hasElse` .
495
502
void ifStatement_thenBegin (Expression condition);
496
503
497
- /// Register an initialized declaration of the given [variable] in the current
498
- /// state. Should also be called for function parameters.
499
- void initialize (Variable variable);
500
-
501
504
/// Return whether the [variable] is definitely assigned in the current state.
502
505
bool isAssigned (Variable variable);
503
506
@@ -774,6 +777,12 @@ class FlowAnalysisDebug<Node, Statement extends Node, Expression, Variable,
774
777
() => _wrapped.conditional_thenBegin (condition));
775
778
}
776
779
780
+ @override
781
+ void declare (Variable variable, bool initialized) {
782
+ _wrap ('declare($variable , $initialized )' ,
783
+ () => _wrapped.declare (variable, initialized));
784
+ }
785
+
777
786
@override
778
787
void doStatement_bodyBegin (Statement doStatement) {
779
788
return _wrap ('doStatement_bodyBegin($doStatement )' ,
@@ -903,11 +912,6 @@ class FlowAnalysisDebug<Node, Statement extends Node, Expression, Variable,
903
912
() => _wrapped.ifStatement_thenBegin (condition));
904
913
}
905
914
906
- @override
907
- void initialize (Variable variable) {
908
- _wrap ('initialize($variable )' , () => _wrapped.initialize (variable));
909
- }
910
-
911
915
@override
912
916
bool isAssigned (Variable variable) {
913
917
return _wrap ('isAssigned($variable )' , () => _wrapped.isAssigned (variable),
@@ -1152,20 +1156,24 @@ class FlowModel<Variable, Type> {
1152
1156
}());
1153
1157
}
1154
1158
1155
- /// Gets the info for the given [variable] , creating it if it doesn't exist.
1156
- VariableModel <Type > infoFor (Variable variable) =>
1157
- variableInfo[variable] ?? _freshVariableInfo;
1159
+ /// Register a declaration of the [variable] .
1160
+ /// Should also be called for function parameters.
1161
+ ///
1162
+ /// A local variable is [initialized] if its declaration has an initializer.
1163
+ /// A function parameter is always initialized, so [initialized] is `true` .
1164
+ FlowModel <Variable , Type > declare (Variable variable, bool initialized) {
1165
+ VariableModel <Type > newInfoForVar = _freshVariableInfo;
1166
+ if (initialized) {
1167
+ newInfoForVar = newInfoForVar.initialize ();
1168
+ }
1158
1169
1159
- /// Updates the state to indicate that the given [variable] was initialized.
1160
- /// The variable is marked as definitely assigned, and any previous type
1161
- /// promotion is removed.
1162
- FlowModel <Variable , Type > initialize (Variable variable) {
1163
- VariableModel <Type > infoForVar = infoFor (variable);
1164
- VariableModel <Type > newInfoForVar = infoForVar.initialize ();
1165
- if (identical (newInfoForVar, infoForVar)) return this ;
1166
1170
return _updateVariableInfo (variable, newInfoForVar);
1167
1171
}
1168
1172
1173
+ /// Gets the info for the given [variable] , creating it if it doesn't exist.
1174
+ VariableModel <Type > infoFor (Variable variable) =>
1175
+ variableInfo[variable] ?? _freshVariableInfo;
1176
+
1169
1177
/// Updates the state to indicate that the given [writtenVariables] are no
1170
1178
/// longer promoted; they are presumed to have their declared types.
1171
1179
///
@@ -1245,28 +1253,24 @@ class FlowModel<Variable, Type> {
1245
1253
in variableInfo.entries) {
1246
1254
Variable variable = entry.key;
1247
1255
VariableModel <Type > thisModel = entry.value;
1248
- VariableModel <Type > otherModel = other.infoFor (variable);
1256
+ VariableModel <Type > otherModel = other.variableInfo[variable];
1257
+ if (otherModel == null ) {
1258
+ variableInfoMatchesThis = false ;
1259
+ continue ;
1260
+ }
1249
1261
VariableModel <Type > restricted = thisModel.restrict (
1250
1262
typeOperations, otherModel, unsafe.contains (variable));
1251
- if (! identical (restricted, _freshVariableInfo)) {
1252
- newVariableInfo[variable] = restricted;
1253
- }
1263
+ newVariableInfo[variable] = restricted;
1254
1264
if (! identical (restricted, thisModel)) variableInfoMatchesThis = false ;
1255
1265
if (! identical (restricted, otherModel)) variableInfoMatchesOther = false ;
1256
1266
}
1257
- for (MapEntry <Variable , VariableModel <Type >> entry
1258
- in other.variableInfo.entries) {
1259
- Variable variable = entry.key;
1260
- if (variableInfo.containsKey (variable)) continue ;
1261
- VariableModel <Type > thisModel = _freshVariableInfo;
1262
- VariableModel <Type > otherModel = entry.value;
1263
- VariableModel <Type > restricted = thisModel.restrict (
1264
- typeOperations, otherModel, unsafe.contains (variable));
1265
- if (! identical (restricted, _freshVariableInfo)) {
1266
- newVariableInfo[variable] = restricted;
1267
+ if (variableInfoMatchesOther) {
1268
+ for (Variable variable in other.variableInfo.keys) {
1269
+ if (! variableInfo.containsKey (variable)) {
1270
+ variableInfoMatchesOther = false ;
1271
+ break ;
1272
+ }
1267
1273
}
1268
- if (! identical (restricted, thisModel)) variableInfoMatchesThis = false ;
1269
- if (! identical (restricted, otherModel)) variableInfoMatchesOther = false ;
1270
1274
}
1271
1275
assert (variableInfoMatchesThis ==
1272
1276
_variableInfosEqual (newVariableInfo, variableInfo));
@@ -1347,10 +1351,13 @@ class FlowModel<Variable, Type> {
1347
1351
/// previous type promotion is removed.
1348
1352
FlowModel <Variable , Type > write (Variable variable, Type writtenType,
1349
1353
TypeOperations <Variable , Type > typeOperations) {
1350
- VariableModel <Type > infoForVar = infoFor (variable);
1354
+ VariableModel <Type > infoForVar = variableInfo[variable];
1355
+ if (infoForVar == null ) return this ;
1356
+
1351
1357
VariableModel <Type > newInfoForVar =
1352
1358
infoForVar.write (writtenType, typeOperations);
1353
1359
if (identical (newInfoForVar, infoForVar)) return this ;
1360
+
1354
1361
return _updateVariableInfo (variable, newInfoForVar);
1355
1362
}
1356
1363
@@ -2053,6 +2060,11 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
2053
2060
_current = conditionInfo.ifTrue;
2054
2061
}
2055
2062
2063
+ @override
2064
+ void declare (Variable variable, bool initialized) {
2065
+ _current = _current.declare (variable, initialized);
2066
+ }
2067
+
2056
2068
@override
2057
2069
void doStatement_bodyBegin (Statement doStatement) {
2058
2070
AssignedVariablesNodeInfo <Variable > info =
@@ -2267,11 +2279,6 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
2267
2279
_current = conditionInfo.ifTrue;
2268
2280
}
2269
2281
2270
- @override
2271
- void initialize (Variable variable) {
2272
- _current = _current.initialize (variable);
2273
- }
2274
-
2275
2282
@override
2276
2283
bool isAssigned (Variable variable) {
2277
2284
return _current.infoFor (variable).assigned;
@@ -2441,10 +2448,10 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
2441
2448
_stack.last as _TryContext <Variable , Type >;
2442
2449
_current = context._beforeCatch;
2443
2450
if (exceptionVariable != null ) {
2444
- _current = _current.initialize (exceptionVariable);
2451
+ _current = _current.declare (exceptionVariable, true );
2445
2452
}
2446
2453
if (stackTraceVariable != null ) {
2447
- _current = _current.initialize (stackTraceVariable);
2454
+ _current = _current.declare (stackTraceVariable, true );
2448
2455
}
2449
2456
}
2450
2457
0 commit comments