@@ -9,6 +9,7 @@ import 'package:kernel/ast.dart'
99 Arguments,
1010 Block,
1111 BlockExpression,
12+ DartType,
1213 Expression,
1314 ExpressionStatement,
1415 ForInStatement,
@@ -18,7 +19,9 @@ import 'package:kernel/ast.dart'
1819 MethodInvocation,
1920 Name,
2021 Procedure,
22+ SetLiteral,
2123 Statement,
24+ StaticInvocation,
2225 TreeNode,
2326 VariableDeclaration,
2427 VariableGet;
@@ -31,72 +34,113 @@ import 'collections.dart' show SpreadElement;
3134
3235import '../source/source_loader.dart' show SourceLoader;
3336
37+ import 'redirecting_factory_body.dart' show RedirectingFactoryBody;
38+
3439class CollectionTransformer extends Transformer {
3540 final CoreTypes coreTypes;
3641 final Procedure listAdd;
42+ final Procedure setFactory;
43+ final Procedure setAdd;
44+
45+ static Procedure _findSetFactory (CoreTypes coreTypes) {
46+ Procedure factory = coreTypes.index.getMember ('dart:core' , 'Set' , '' );
47+ RedirectingFactoryBody body = factory ? .function? .body;
48+ return body? .target;
49+ }
3750
3851 CollectionTransformer (SourceLoader loader)
3952 : coreTypes = loader.coreTypes,
40- listAdd = loader.coreTypes.index.getMember ('dart:core' , 'List' , 'add' );
53+ listAdd = loader.coreTypes.index.getMember ('dart:core' , 'List' , 'add' ),
54+ setFactory = _findSetFactory (loader.coreTypes),
55+ setAdd = loader.coreTypes.index.getMember ('dart:core' , 'Set' , 'add' );
4156
42- @override
43- TreeNode visitListLiteral (ListLiteral node) {
57+ TreeNode _translateListOrSet (
58+ Expression node, DartType elementType, List <Expression > elements,
59+ {bool isSet: false , bool isConst: false }) {
60+ // Translate elements in place up to the first spread if any.
4461 int i = 0 ;
45- for (; i < node.expressions .length; ++ i) {
46- if (node.expressions [i] is SpreadElement ) break ;
47- node.expressions [i] = node.expressions [i].accept (this )..parent = node;
62+ for (; i < elements .length; ++ i) {
63+ if (elements [i] is SpreadElement ) break ;
64+ elements [i] = elements [i].accept (this )..parent = node;
4865 }
4966
50- if (i == node.expressions.length) return node;
67+ // If there was no spread, we are done.
68+ if (i == elements.length) return node;
5169
52- if (node. isConst) {
70+ if (isConst) {
5371 // We don't desugar const lists here. Remove spread for now so that they
5472 // don't leak out.
55- for (; i < node.expressions .length; ++ i) {
56- Expression element = node.expressions [i];
73+ for (; i < elements .length; ++ i) {
74+ Expression element = elements [i];
5775 if (element is SpreadElement ) {
58- element.parent.replaceChild (
59- element,
60- InvalidExpression ('unimplemented spread element' )
61- ..fileOffset = element.fileOffset);
76+ elements[i] = InvalidExpression ('unimplemented spread element' )
77+ ..fileOffset = element.fileOffset
78+ ..parent = node;
79+ } else {
80+ elements[i] = element.accept (this )..parent = node;
6281 }
6382 }
83+ return node;
6484 }
6585
66- VariableDeclaration list = new VariableDeclaration .forValue (
67- new ListLiteral ([], typeArgument: node.typeArgument),
68- type: new InterfaceType (coreTypes.listClass, [node.typeArgument]),
69- isFinal: true );
70- List <Statement > body = [list];
86+ // Build a block expression and create an empty list.
87+ VariableDeclaration result;
88+ if (isSet) {
89+ result = new VariableDeclaration .forValue (
90+ new StaticInvocation (
91+ setFactory, new Arguments ([], types: [elementType])),
92+ type: new InterfaceType (coreTypes.setClass, [elementType]),
93+ isFinal: true );
94+ } else {
95+ result = new VariableDeclaration .forValue (
96+ new ListLiteral ([], typeArgument: elementType),
97+ type: new InterfaceType (coreTypes.listClass, [elementType]),
98+ isFinal: true );
99+ }
100+ List <Statement > body = [result];
101+ // Add the elements up to the first spread.
71102 for (int j = 0 ; j < i; ++ j) {
72103 body.add (new ExpressionStatement (new MethodInvocation (
73- new VariableGet (list ),
104+ new VariableGet (result ),
74105 new Name ('add' ),
75- new Arguments ([node.expressions [j]]),
76- listAdd)));
106+ new Arguments ([elements [j]]),
107+ isSet ? setAdd : listAdd)));
77108 }
78- for (; i < node.expressions.length; ++ i) {
79- Expression element = node.expressions[i];
109+ // Translate the elements starting with the first spread.
110+ for (; i < elements.length; ++ i) {
111+ Expression element = elements[i];
80112 if (element is SpreadElement ) {
81- VariableDeclaration elt = new VariableDeclaration ( null ,
82- type: node.typeArgument , isFinal: true );
113+ VariableDeclaration elt =
114+ new VariableDeclaration ( null , type: elementType , isFinal: true );
83115 body.add (new ForInStatement (
84116 elt,
85117 element.expression.accept (this ),
86118 new ExpressionStatement (new MethodInvocation (
87- new VariableGet (list ),
119+ new VariableGet (result ),
88120 new Name ('add' ),
89121 new Arguments ([new VariableGet (elt)]),
90- listAdd))));
122+ isSet ? setAdd : listAdd))));
91123 } else {
92124 body.add (new ExpressionStatement (new MethodInvocation (
93- new VariableGet (list ),
125+ new VariableGet (result ),
94126 new Name ('add' ),
95127 new Arguments ([element.accept (this )]),
96- listAdd)));
128+ isSet ? setAdd : listAdd)));
97129 }
98130 }
99131
100- return new BlockExpression (new Block (body), new VariableGet (list));
132+ return new BlockExpression (new Block (body), new VariableGet (result));
133+ }
134+
135+ @override
136+ TreeNode visitListLiteral (ListLiteral node) {
137+ return _translateListOrSet (node, node.typeArgument, node.expressions,
138+ isConst: node.isConst, isSet: false );
139+ }
140+
141+ @override
142+ TreeNode visitSetLiteral (SetLiteral node) {
143+ return _translateListOrSet (node, node.typeArgument, node.expressions,
144+ isConst: node.isConst, isSet: true );
101145 }
102146}
0 commit comments