OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library dart2js.constants.constructors; | 5 library dart2js.constants.constructors; |
6 | 6 |
7 import '../dart_types.dart'; | 7 import '../dart_types.dart'; |
8 import '../elements/elements.dart' show | 8 import '../elements/elements.dart' show ConstructorElement, FieldElement; |
9 ConstructorElement, | 9 import '../universe/call_structure.dart' show CallStructure; |
10 FieldElement; | |
11 import '../universe/call_structure.dart' show | |
12 CallStructure; | |
13 import '../util/util.dart'; | 10 import '../util/util.dart'; |
14 import 'evaluation.dart'; | 11 import 'evaluation.dart'; |
15 import 'expressions.dart'; | 12 import 'expressions.dart'; |
16 | 13 |
17 enum ConstantConstructorKind { | 14 enum ConstantConstructorKind { |
18 GENERATIVE, | 15 GENERATIVE, |
19 REDIRECTING_GENERATIVE, | 16 REDIRECTING_GENERATIVE, |
20 REDIRECTING_FACTORY, | 17 REDIRECTING_FACTORY, |
21 } | 18 } |
22 | 19 |
23 /// Definition of a constant constructor. | 20 /// Definition of a constant constructor. |
24 abstract class ConstantConstructor { | 21 abstract class ConstantConstructor { |
25 ConstantConstructorKind get kind; | 22 ConstantConstructorKind get kind; |
26 | 23 |
27 /// Computes the type of the instance created in a const constructor | 24 /// Computes the type of the instance created in a const constructor |
28 /// invocation with type [newType]. | 25 /// invocation with type [newType]. |
29 InterfaceType computeInstanceType(InterfaceType newType); | 26 InterfaceType computeInstanceType(InterfaceType newType); |
30 | 27 |
31 /// Computes the constant expressions of the fields of the created instance | 28 /// Computes the constant expressions of the fields of the created instance |
32 /// in a const constructor invocation with [arguments]. | 29 /// in a const constructor invocation with [arguments]. |
33 Map<FieldElement, ConstantExpression> computeInstanceFields( | 30 Map<FieldElement, ConstantExpression> computeInstanceFields( |
34 List<ConstantExpression> arguments, | 31 List<ConstantExpression> arguments, CallStructure callStructure); |
35 CallStructure callStructure); | |
36 | 32 |
37 accept(ConstantConstructorVisitor visitor, arg); | 33 accept(ConstantConstructorVisitor visitor, arg); |
38 } | 34 } |
39 | 35 |
40 abstract class ConstantConstructorVisitor<R, A> { | 36 abstract class ConstantConstructorVisitor<R, A> { |
41 const ConstantConstructorVisitor(); | 37 const ConstantConstructorVisitor(); |
42 | 38 |
43 R visit(ConstantConstructor constantConstructor, A context) { | 39 R visit(ConstantConstructor constantConstructor, A context) { |
44 return constantConstructor.accept(this, context); | 40 return constantConstructor.accept(this, context); |
45 } | 41 } |
46 | 42 |
47 R visitGenerative(GenerativeConstantConstructor constructor, A arg); | 43 R visitGenerative(GenerativeConstantConstructor constructor, A arg); |
48 R visitRedirectingGenerative( | 44 R visitRedirectingGenerative( |
49 RedirectingGenerativeConstantConstructor constructor, A arg); | 45 RedirectingGenerativeConstantConstructor constructor, A arg); |
50 R visitRedirectingFactory( | 46 R visitRedirectingFactory( |
51 RedirectingFactoryConstantConstructor constructor, A arg); | 47 RedirectingFactoryConstantConstructor constructor, A arg); |
52 } | 48 } |
53 | 49 |
54 /// A generative constant constructor. | 50 /// A generative constant constructor. |
55 class GenerativeConstantConstructor implements ConstantConstructor{ | 51 class GenerativeConstantConstructor implements ConstantConstructor { |
56 final InterfaceType type; | 52 final InterfaceType type; |
57 final Map<dynamic/*int|String*/, ConstantExpression> defaultValues; | 53 final Map<dynamic /*int|String*/, ConstantExpression> defaultValues; |
58 final Map<FieldElement, ConstantExpression> fieldMap; | 54 final Map<FieldElement, ConstantExpression> fieldMap; |
59 final ConstructedConstantExpression superConstructorInvocation; | 55 final ConstructedConstantExpression superConstructorInvocation; |
60 | 56 |
61 GenerativeConstantConstructor( | 57 GenerativeConstantConstructor(this.type, this.defaultValues, this.fieldMap, |
62 this.type, | |
63 this.defaultValues, | |
64 this.fieldMap, | |
65 this.superConstructorInvocation); | 58 this.superConstructorInvocation); |
66 | 59 |
67 ConstantConstructorKind get kind => ConstantConstructorKind.GENERATIVE; | 60 ConstantConstructorKind get kind => ConstantConstructorKind.GENERATIVE; |
68 | 61 |
69 InterfaceType computeInstanceType(InterfaceType newType) { | 62 InterfaceType computeInstanceType(InterfaceType newType) { |
70 return type.substByContext(newType); | 63 return type.substByContext(newType); |
71 } | 64 } |
72 | 65 |
73 Map<FieldElement, ConstantExpression> computeInstanceFields( | 66 Map<FieldElement, ConstantExpression> computeInstanceFields( |
74 List<ConstantExpression> arguments, | 67 List<ConstantExpression> arguments, CallStructure callStructure) { |
75 CallStructure callStructure) { | 68 NormalizedArguments args = |
76 NormalizedArguments args = new NormalizedArguments( | 69 new NormalizedArguments(defaultValues, callStructure, arguments); |
77 defaultValues, callStructure, arguments); | |
78 Map<FieldElement, ConstantExpression> appliedFieldMap = | 70 Map<FieldElement, ConstantExpression> appliedFieldMap = |
79 applyFields(args, superConstructorInvocation); | 71 applyFields(args, superConstructorInvocation); |
80 fieldMap.forEach((FieldElement field, ConstantExpression constant) { | 72 fieldMap.forEach((FieldElement field, ConstantExpression constant) { |
81 appliedFieldMap[field] = constant.apply(args); | 73 appliedFieldMap[field] = constant.apply(args); |
82 }); | 74 }); |
83 return appliedFieldMap; | 75 return appliedFieldMap; |
84 } | 76 } |
85 | 77 |
86 accept(ConstantConstructorVisitor visitor, arg) { | 78 accept(ConstantConstructorVisitor visitor, arg) { |
87 return visitor.visitGenerative(this, arg); | 79 return visitor.visitGenerative(this, arg); |
88 } | 80 } |
89 | 81 |
90 int get hashCode { | 82 int get hashCode { |
91 int hash = Hashing.objectHash(type); | 83 int hash = Hashing.objectHash(type); |
92 hash = Hashing.mapHash(defaultValues, hash); | 84 hash = Hashing.mapHash(defaultValues, hash); |
93 hash = Hashing.mapHash(fieldMap, hash); | 85 hash = Hashing.mapHash(fieldMap, hash); |
94 return Hashing.objectHash(superConstructorInvocation, hash); | 86 return Hashing.objectHash(superConstructorInvocation, hash); |
95 } | 87 } |
96 | 88 |
97 bool operator ==(other) { | 89 bool operator ==(other) { |
98 if (identical(this, other)) return true; | 90 if (identical(this, other)) return true; |
99 if (other is! GenerativeConstantConstructor) return false; | 91 if (other is! GenerativeConstantConstructor) return false; |
100 return | 92 return type == other.type && |
101 type == other.type && | |
102 superConstructorInvocation == other.superConstructorInvocation && | 93 superConstructorInvocation == other.superConstructorInvocation && |
103 mapEquals(defaultValues, other.defaultValues) && | 94 mapEquals(defaultValues, other.defaultValues) && |
104 mapEquals(fieldMap, other.fieldMap); | 95 mapEquals(fieldMap, other.fieldMap); |
105 } | 96 } |
106 | 97 |
107 String toString() { | 98 String toString() { |
108 StringBuffer sb = new StringBuffer(); | 99 StringBuffer sb = new StringBuffer(); |
109 sb.write("{'type': $type"); | 100 sb.write("{'type': $type"); |
110 defaultValues.forEach((key, ConstantExpression expression) { | 101 defaultValues.forEach((key, ConstantExpression expression) { |
111 sb.write(",\n 'default:${key}': ${expression.getText()}"); | 102 sb.write(",\n 'default:${key}': ${expression.getText()}"); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
144 fieldMap.forEach((FieldElement field, ConstantExpression constant) { | 135 fieldMap.forEach((FieldElement field, ConstantExpression constant) { |
145 appliedFieldMap[field] = constant.apply(args); | 136 appliedFieldMap[field] = constant.apply(args); |
146 }); | 137 }); |
147 } | 138 } |
148 return appliedFieldMap; | 139 return appliedFieldMap; |
149 } | 140 } |
150 } | 141 } |
151 | 142 |
152 /// A redirecting generative constant constructor. | 143 /// A redirecting generative constant constructor. |
153 class RedirectingGenerativeConstantConstructor implements ConstantConstructor { | 144 class RedirectingGenerativeConstantConstructor implements ConstantConstructor { |
154 final Map<dynamic/*int|String*/, ConstantExpression> defaultValues; | 145 final Map<dynamic /*int|String*/, ConstantExpression> defaultValues; |
155 final ConstructedConstantExpression thisConstructorInvocation; | 146 final ConstructedConstantExpression thisConstructorInvocation; |
156 | 147 |
157 RedirectingGenerativeConstantConstructor( | 148 RedirectingGenerativeConstantConstructor( |
158 this.defaultValues, | 149 this.defaultValues, this.thisConstructorInvocation); |
159 this.thisConstructorInvocation); | |
160 | 150 |
161 ConstantConstructorKind get kind { | 151 ConstantConstructorKind get kind { |
162 return ConstantConstructorKind.REDIRECTING_GENERATIVE; | 152 return ConstantConstructorKind.REDIRECTING_GENERATIVE; |
163 } | 153 } |
164 | 154 |
165 InterfaceType computeInstanceType(InterfaceType newType) { | 155 InterfaceType computeInstanceType(InterfaceType newType) { |
166 return thisConstructorInvocation.computeInstanceType() | 156 return thisConstructorInvocation |
| 157 .computeInstanceType() |
167 .substByContext(newType); | 158 .substByContext(newType); |
168 } | 159 } |
169 | 160 |
170 Map<FieldElement, ConstantExpression> computeInstanceFields( | 161 Map<FieldElement, ConstantExpression> computeInstanceFields( |
171 List<ConstantExpression> arguments, | 162 List<ConstantExpression> arguments, CallStructure callStructure) { |
172 CallStructure callStructure) { | |
173 NormalizedArguments args = | 163 NormalizedArguments args = |
174 new NormalizedArguments(defaultValues, callStructure, arguments); | 164 new NormalizedArguments(defaultValues, callStructure, arguments); |
175 Map<FieldElement, ConstantExpression> appliedFieldMap = | 165 Map<FieldElement, ConstantExpression> appliedFieldMap = |
176 GenerativeConstantConstructor.applyFields( | 166 GenerativeConstantConstructor.applyFields( |
177 args, thisConstructorInvocation); | 167 args, thisConstructorInvocation); |
178 return appliedFieldMap; | 168 return appliedFieldMap; |
179 } | 169 } |
180 | 170 |
181 accept(ConstantConstructorVisitor visitor, arg) { | 171 accept(ConstantConstructorVisitor visitor, arg) { |
182 return visitor.visitRedirectingGenerative(this, arg); | 172 return visitor.visitRedirectingGenerative(this, arg); |
183 } | 173 } |
184 | 174 |
185 int get hashCode { | 175 int get hashCode { |
186 int hash = Hashing.objectHash(thisConstructorInvocation); | 176 int hash = Hashing.objectHash(thisConstructorInvocation); |
187 return Hashing.mapHash(defaultValues, hash); | 177 return Hashing.mapHash(defaultValues, hash); |
188 } | 178 } |
189 | 179 |
190 bool operator ==(other) { | 180 bool operator ==(other) { |
191 if (identical(this, other)) return true; | 181 if (identical(this, other)) return true; |
192 if (other is! RedirectingGenerativeConstantConstructor) return false; | 182 if (other is! RedirectingGenerativeConstantConstructor) return false; |
193 return | 183 return thisConstructorInvocation == other.thisConstructorInvocation && |
194 thisConstructorInvocation == other.thisConstructorInvocation && | |
195 GenerativeConstantConstructor.mapEquals( | 184 GenerativeConstantConstructor.mapEquals( |
196 defaultValues, other.defaultValues); | 185 defaultValues, other.defaultValues); |
197 } | 186 } |
198 | 187 |
199 String toString() { | 188 String toString() { |
200 StringBuffer sb = new StringBuffer(); | 189 StringBuffer sb = new StringBuffer(); |
201 sb.write("{'type': ${thisConstructorInvocation.type}"); | 190 sb.write("{'type': ${thisConstructorInvocation.type}"); |
202 defaultValues.forEach((key, ConstantExpression expression) { | 191 defaultValues.forEach((key, ConstantExpression expression) { |
203 sb.write(",\n 'default:${key}': ${expression.getText()}"); | 192 sb.write(",\n 'default:${key}': ${expression.getText()}"); |
204 }); | 193 }); |
205 sb.write(",\n 'constructor': ${thisConstructorInvocation.getText()}"); | 194 sb.write(",\n 'constructor': ${thisConstructorInvocation.getText()}"); |
206 sb.write("}"); | 195 sb.write("}"); |
207 return sb.toString(); | 196 return sb.toString(); |
208 } | 197 } |
209 } | 198 } |
210 | 199 |
211 /// A redirecting factory constant constructor. | 200 /// A redirecting factory constant constructor. |
212 class RedirectingFactoryConstantConstructor implements ConstantConstructor { | 201 class RedirectingFactoryConstantConstructor implements ConstantConstructor { |
213 final ConstructedConstantExpression targetConstructorInvocation; | 202 final ConstructedConstantExpression targetConstructorInvocation; |
214 | 203 |
215 RedirectingFactoryConstantConstructor(this.targetConstructorInvocation); | 204 RedirectingFactoryConstantConstructor(this.targetConstructorInvocation); |
216 | 205 |
217 ConstantConstructorKind get kind { | 206 ConstantConstructorKind get kind { |
218 return ConstantConstructorKind.REDIRECTING_FACTORY; | 207 return ConstantConstructorKind.REDIRECTING_FACTORY; |
219 } | 208 } |
220 | 209 |
221 InterfaceType computeInstanceType(InterfaceType newType) { | 210 InterfaceType computeInstanceType(InterfaceType newType) { |
222 return targetConstructorInvocation.computeInstanceType() | 211 return targetConstructorInvocation |
| 212 .computeInstanceType() |
223 .substByContext(newType); | 213 .substByContext(newType); |
224 } | 214 } |
225 | 215 |
226 Map<FieldElement, ConstantExpression> computeInstanceFields( | 216 Map<FieldElement, ConstantExpression> computeInstanceFields( |
227 List<ConstantExpression> arguments, | 217 List<ConstantExpression> arguments, CallStructure callStructure) { |
228 CallStructure callStructure) { | |
229 ConstantConstructor constantConstructor = | 218 ConstantConstructor constantConstructor = |
230 targetConstructorInvocation.target.constantConstructor; | 219 targetConstructorInvocation.target.constantConstructor; |
231 return constantConstructor.computeInstanceFields(arguments, callStructure); | 220 return constantConstructor.computeInstanceFields(arguments, callStructure); |
232 } | 221 } |
233 | 222 |
234 accept(ConstantConstructorVisitor visitor, arg) { | 223 accept(ConstantConstructorVisitor visitor, arg) { |
235 return visitor.visitRedirectingFactory(this, arg); | 224 return visitor.visitRedirectingFactory(this, arg); |
236 } | 225 } |
237 | 226 |
238 int get hashCode { | 227 int get hashCode { |
239 return Hashing.objectHash(targetConstructorInvocation); | 228 return Hashing.objectHash(targetConstructorInvocation); |
240 } | 229 } |
241 | 230 |
242 bool operator ==(other) { | 231 bool operator ==(other) { |
243 if (identical(this, other)) return true; | 232 if (identical(this, other)) return true; |
244 if (other is! RedirectingFactoryConstantConstructor) return false; | 233 if (other is! RedirectingFactoryConstantConstructor) return false; |
245 return targetConstructorInvocation == other.targetConstructorInvocation; | 234 return targetConstructorInvocation == other.targetConstructorInvocation; |
246 } | 235 } |
247 | 236 |
248 String toString() { | 237 String toString() { |
249 StringBuffer sb = new StringBuffer(); | 238 StringBuffer sb = new StringBuffer(); |
250 sb.write("{"); | 239 sb.write("{"); |
251 sb.write("'constructor': ${targetConstructorInvocation.getText()}"); | 240 sb.write("'constructor': ${targetConstructorInvocation.getText()}"); |
252 sb.write("}"); | 241 sb.write("}"); |
253 return sb.toString(); | 242 return sb.toString(); |
254 } | 243 } |
255 } | 244 } |
OLD | NEW |