Skip to content

Commit 6d2b7f4

Browse files
committed
Refactor AST summarization logic for serializing initializer expressions.
This should pave the way for serializing the bodies of expression-type function closures. [email protected] Review URL: https://codereview.chromium.org/2017613003 .
1 parent ac7f892 commit 6d2b7f4

File tree

1 file changed

+37
-40
lines changed

1 file changed

+37
-40
lines changed

pkg/analyzer/lib/src/summary/summarize_ast.dart

Lines changed: 37 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -643,7 +643,7 @@ class _SummarizeAstVisitor extends RecursiveAstVisitor {
643643
}
644644
b.visibleOffset = enclosingBlock?.offset;
645645
b.visibleLength = enclosingBlock?.length;
646-
serializeFunctionBody(b, null, body);
646+
serializeFunctionBody(b, null, body, false);
647647
scopes.removeLast();
648648
assert(scopes.length == oldScopesLength);
649649
return b;
@@ -656,9 +656,19 @@ class _SummarizeAstVisitor extends RecursiveAstVisitor {
656656
*
657657
* If [initializers] is non-`null`, closures occurring inside the initializers
658658
* are serialized first.
659+
*
660+
* If [serializeBodyExpr] is `true`, then the function definition is stored
661+
* in [UnlinkedExecutableBuilder.bodyExpr].
662+
*
663+
* The return value is a map whose keys are the offsets of local function
664+
* nodes representing closures inside [initializers] and [body], and whose
665+
* values are the indices of those local functions relative to their siblings.
659666
*/
660-
void serializeFunctionBody(UnlinkedExecutableBuilder b,
661-
List<ConstructorInitializer> initializers, AstNode body) {
667+
Map<int, int> serializeFunctionBody(
668+
UnlinkedExecutableBuilder b,
669+
List<ConstructorInitializer> initializers,
670+
AstNode body,
671+
bool serializeBodyExpr) {
662672
if (body is BlockFunctionBody || body is ExpressionFunctionBody) {
663673
for (UnlinkedParamBuilder parameter in b.parameters) {
664674
parameter.visibleOffset = body.offset;
@@ -668,21 +678,33 @@ class _SummarizeAstVisitor extends RecursiveAstVisitor {
668678
List<UnlinkedExecutableBuilder> oldExecutables = executables;
669679
List<UnlinkedLabelBuilder> oldLabels = labels;
670680
List<UnlinkedVariableBuilder> oldVariables = variables;
681+
Map<int, int> oldLocalClosureIndexMap = _localClosureIndexMap;
671682
executables = <UnlinkedExecutableBuilder>[];
672683
labels = <UnlinkedLabelBuilder>[];
673684
variables = <UnlinkedVariableBuilder>[];
685+
_localClosureIndexMap = <int, int>{};
674686
if (initializers != null) {
675687
for (ConstructorInitializer initializer in initializers) {
676688
initializer.accept(this);
677689
}
678690
}
679691
body.accept(this);
692+
if (serializeBodyExpr) {
693+
if (body is Expression) {
694+
b.bodyExpr = serializeConstExpr(_localClosureIndexMap, body);
695+
} else {
696+
// TODO(paulberry): serialize other types of function bodies.
697+
}
698+
}
680699
b.localFunctions = executables;
681700
b.localLabels = labels;
682701
b.localVariables = variables;
702+
Map<int, int> localClosureIndexMap = _localClosureIndexMap;
683703
executables = oldExecutables;
684704
labels = oldLabels;
685705
variables = oldVariables;
706+
_localClosureIndexMap = oldLocalClosureIndexMap;
707+
return localClosureIndexMap;
686708
}
687709

688710
/**
@@ -703,15 +725,18 @@ class _SummarizeAstVisitor extends RecursiveAstVisitor {
703725
/**
704726
* If the given [expression] is not `null`, serialize it as an
705727
* [UnlinkedExecutableBuilder], otherwise return `null`.
728+
*
729+
* If [serializeBodyExpr] is `true`, then the initializer expression is stored
730+
* in [UnlinkedExecutableBuilder.bodyExpr].
706731
*/
707732
UnlinkedExecutableBuilder serializeInitializerFunction(
708-
Expression expression) {
733+
Expression expression, bool serializeBodyExpr) {
709734
if (expression == null) {
710735
return null;
711736
}
712737
UnlinkedExecutableBuilder initializer =
713738
new UnlinkedExecutableBuilder(nameOffset: expression.offset);
714-
serializeFunctionBody(initializer, null, expression);
739+
serializeFunctionBody(initializer, null, expression, serializeBodyExpr);
715740
initializer.inferredReturnTypeSlot = assignSlot();
716741
return initializer;
717742
}
@@ -893,18 +918,11 @@ class _SummarizeAstVisitor extends RecursiveAstVisitor {
893918
b.documentationComment = serializeDocumentation(documentationComment);
894919
b.annotations = serializeAnnotations(annotations);
895920
b.codeRange = serializeCodeRange(variables.parent);
896-
Map<int, int> localClosureIndexMap = _withLocalClosureIndexMap(() {
897-
b.initializer = serializeInitializerFunction(variable.initializer);
898-
});
899-
if (variable.isConst ||
921+
bool serializeBodyExpr = variable.isConst ||
900922
variable.isFinal && isField && !isDeclaredStatic ||
901-
variables.type == null) {
902-
Expression initializer = variable.initializer;
903-
if (initializer != null) {
904-
b.initializer.bodyExpr =
905-
serializeConstExpr(localClosureIndexMap, initializer);
906-
}
907-
}
923+
variables.type == null;
924+
b.initializer =
925+
serializeInitializerFunction(variable.initializer, serializeBodyExpr);
908926
if (variable.initializer != null &&
909927
(variables.isFinal || variables.isConst)) {
910928
b.propagatedTypeSlot = assignSlot();
@@ -1023,9 +1041,8 @@ class _SummarizeAstVisitor extends RecursiveAstVisitor {
10231041
b.documentationComment = serializeDocumentation(node.documentationComment);
10241042
b.annotations = serializeAnnotations(node.metadata);
10251043
b.codeRange = serializeCodeRange(node);
1026-
Map<int, int> localClosureIndexMap = _withLocalClosureIndexMap(() {
1027-
serializeFunctionBody(b, node.initializers, node.body);
1028-
});
1044+
Map<int, int> localClosureIndexMap = serializeFunctionBody(
1045+
b, node.initializers, node.body, node.constKeyword != null);
10291046
if (node.constKeyword != null) {
10301047
Set<String> constructorParameterNames =
10311048
node.parameters.parameters.map((p) => p.identifier.name).toSet();
@@ -1044,13 +1061,8 @@ class _SummarizeAstVisitor extends RecursiveAstVisitor {
10441061
UnlinkedParamBuilder visitDefaultFormalParameter(
10451062
DefaultFormalParameter node) {
10461063
UnlinkedParamBuilder b = node.parameter.accept(this);
1047-
b.initializer = serializeInitializerFunction(node.defaultValue);
1064+
b.initializer = serializeInitializerFunction(node.defaultValue, true);
10481065
if (node.defaultValue != null) {
1049-
// Closures can't appear inside default values, so we don't need a
1050-
// localClosureIndexMap.
1051-
Map<int, int> localClosureIndexMap = null;
1052-
b.initializer?.bodyExpr =
1053-
serializeConstExpr(localClosureIndexMap, node.defaultValue);
10541066
b.defaultValueCode = node.defaultValue.toSource();
10551067
}
10561068
b.codeRange = serializeCodeRange(node);
@@ -1316,21 +1328,6 @@ class _SummarizeAstVisitor extends RecursiveAstVisitor {
13161328
enclosingBlock, node.variables, false, null, null, false);
13171329
}
13181330

1319-
/**
1320-
* Execute [callback], gathering any local closures in
1321-
* [_localClosureIndexMap], and return the resulting map.
1322-
*
1323-
* Properly handles cases where one closure is nested within another.
1324-
*/
1325-
Map<int, int> _withLocalClosureIndexMap(void callback()) {
1326-
Map<int, int> prevLocalClosureIndexMap = _localClosureIndexMap;
1327-
_localClosureIndexMap = <int, int>{};
1328-
callback();
1329-
Map<int, int> localClosureIndexMap = _localClosureIndexMap;
1330-
_localClosureIndexMap = prevLocalClosureIndexMap;
1331-
return localClosureIndexMap;
1332-
}
1333-
13341331
/**
13351332
* Helper method to determine if a given [typeName] refers to `dynamic`.
13361333
*/

0 commit comments

Comments
 (0)