Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(218)

Side by Side Diff: tests/compiler/dart2js/kernel/test_helpers.dart

Issue 2879593004: Reorganize equivalence test helpers (Closed)
Patch Set: Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
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.
4
5 library dart2js.kernel.equivalence;
6
7 import 'package:compiler/src/common/backend_api.dart';
8 import 'package:compiler/src/common/resolution.dart';
9 import 'package:compiler/src/common/work.dart';
10 import 'package:compiler/src/constants/expressions.dart';
11 import 'package:compiler/src/constants/values.dart';
12 import 'package:compiler/src/compiler.dart';
13 import 'package:compiler/src/elements/elements.dart';
14 import 'package:compiler/src/elements/entities.dart';
15 import 'package:compiler/src/elements/resolution_types.dart';
16 import 'package:compiler/src/elements/types.dart';
17 import 'package:compiler/src/enqueue.dart';
18 import 'package:compiler/src/kernel/elements.dart';
19 import 'package:compiler/src/kernel/element_map_impl.dart';
20 import 'package:compiler/src/serialization/equivalence.dart';
21 import 'package:compiler/src/ssa/kernel_impact.dart';
22 import 'package:compiler/src/universe/world_impact.dart';
23 import 'package:compiler/src/util/util.dart';
24
25 class KernelEquivalence {
26 final WorldDeconstructionForTesting testing;
27
28 /// Set of mixin applications assumed to be equivalent.
29 ///
30 /// We need co-inductive reasoning because mixin applications are compared
31 /// structurally and therefore, in the case of generic mixin applications,
32 /// meet themselves through the equivalence check of their type variables.
33 Set<Pair<ClassEntity, ClassEntity>> assumedMixinApplications =
34 new Set<Pair<ClassEntity, ClassEntity>>();
35
36 KernelEquivalence(KernelToElementMapImpl builder)
37 : testing = new WorldDeconstructionForTesting(builder);
38
39 TestStrategy get defaultStrategy => new TestStrategy(
40 elementEquivalence: entityEquivalence,
41 typeEquivalence: typeEquivalence,
42 constantEquivalence: constantEquivalence,
43 constantValueEquivalence: constantValueEquivalence);
44
45 bool entityEquivalence(Element a, Entity b, {TestStrategy strategy}) {
46 if (identical(a, b)) return true;
47 if (a == null || b == null) return false;
48 strategy ??= defaultStrategy;
49 switch (a.kind) {
50 case ElementKind.GENERATIVE_CONSTRUCTOR:
51 if (b is KGenerativeConstructor) {
52 return strategy.test(a, b, 'name', a.name, b.name) &&
53 strategy.testElements(
54 a, b, 'enclosingClass', a.enclosingClass, b.enclosingClass);
55 }
56 return false;
57 case ElementKind.FACTORY_CONSTRUCTOR:
58 if (b is KFactoryConstructor) {
59 return strategy.test(a, b, 'name', a.name, b.name) &&
60 strategy.testElements(
61 a, b, 'enclosingClass', a.enclosingClass, b.enclosingClass);
62 }
63 return false;
64 case ElementKind.CLASS:
65 if (b is KClass) {
66 List<InterfaceType> aMixinTypes = [];
67 List<InterfaceType> bMixinTypes = [];
68 ClassElement aClass = a;
69 if (aClass.isUnnamedMixinApplication) {
70 if (!testing.isUnnamedMixinApplication(b)) {
71 return false;
72 }
73 while (aClass.isMixinApplication) {
74 MixinApplicationElement aMixinApplication = aClass;
75 aMixinTypes.add(aMixinApplication.mixinType);
76 aClass = aMixinApplication.superclass;
77 }
78 KClass bClass = b;
79 while (bClass != null) {
80 InterfaceType mixinType = testing.getMixinTypeForClass(bClass);
81 if (mixinType == null) break;
82 bMixinTypes.add(mixinType);
83 bClass = testing.getSuperclassForClass(bClass);
84 }
85 if (aMixinTypes.isNotEmpty || aMixinTypes.isNotEmpty) {
86 Pair<ClassEntity, ClassEntity> pair =
87 new Pair<ClassEntity, ClassEntity>(aClass, bClass);
88 if (assumedMixinApplications.contains(pair)) {
89 return true;
90 } else {
91 assumedMixinApplications.add(pair);
92 bool result = strategy.testTypeLists(
93 a, b, 'mixinTypes', aMixinTypes, bMixinTypes);
94 assumedMixinApplications.remove(pair);
95 return result;
96 }
97 }
98 } else {
99 if (testing.isUnnamedMixinApplication(b)) {
100 return false;
101 }
102 }
103 return strategy.test(a, b, 'name', a.name, b.name) &&
104 strategy.testElements(a, b, 'library', a.library, b.library);
105 }
106 return false;
107 case ElementKind.LIBRARY:
108 if (b is KLibrary) {
109 LibraryElement libraryA = a;
110 return libraryA.canonicalUri == b.canonicalUri;
111 }
112 return false;
113 case ElementKind.FUNCTION:
114 if (b is KMethod) {
115 return strategy.test(a, b, 'name', a.name, b.name) &&
116 strategy.testElements(
117 a, b, 'enclosingClass', a.enclosingClass, b.enclosingClass) &&
118 strategy.testElements(a, b, 'library', a.library, b.library);
119 } else if (b is KLocalFunction) {
120 LocalFunctionElement aLocalFunction = a;
121 return strategy.test(a, b, 'name', a.name, b.name ?? '') &&
122 strategy.testElements(a, b, 'executableContext',
123 aLocalFunction.executableContext, b.executableContext) &&
124 strategy.testElements(a, b, 'memberContext',
125 aLocalFunction.memberContext, b.memberContext);
126 }
127 return false;
128 case ElementKind.GETTER:
129 if (b is KGetter) {
130 return strategy.test(a, b, 'name', a.name, b.name) &&
131 strategy.testElements(
132 a, b, 'enclosingClass', a.enclosingClass, b.enclosingClass) &&
133 strategy.testElements(a, b, 'library', a.library, b.library);
134 }
135 return false;
136 case ElementKind.SETTER:
137 if (b is KSetter) {
138 return strategy.test(a, b, 'name', a.name, b.name) &&
139 strategy.testElements(
140 a, b, 'enclosingClass', a.enclosingClass, b.enclosingClass) &&
141 strategy.testElements(a, b, 'library', a.library, b.library);
142 }
143 return false;
144 case ElementKind.FIELD:
145 if (b is KField) {
146 return strategy.test(a, b, 'name', a.name, b.name) &&
147 strategy.testElements(
148 a, b, 'enclosingClass', a.enclosingClass, b.enclosingClass) &&
149 strategy.testElements(a, b, 'library', a.library, b.library);
150 }
151 return false;
152 case ElementKind.TYPE_VARIABLE:
153 if (b is KTypeVariable) {
154 TypeVariableElement aElement = a;
155 return strategy.test(a, b, 'index', aElement.index, b.index) &&
156 strategy.testElements(a, b, 'typeDeclaration',
157 aElement.typeDeclaration, b.typeDeclaration);
158 }
159 return false;
160 default:
161 throw new UnsupportedError('Unsupported equivalence: '
162 '$a (${a.runtimeType}) vs $b (${b.runtimeType})');
163 }
164 }
165
166 bool typeEquivalence(ResolutionDartType a, DartType b,
167 {TestStrategy strategy}) {
168 if (identical(a, b)) return true;
169 if (a == null || b == null) return false;
170 strategy ??= defaultStrategy;
171 switch (a.kind) {
172 case ResolutionTypeKind.DYNAMIC:
173 return b is DynamicType;
174 case ResolutionTypeKind.VOID:
175 return b is VoidType;
176 case ResolutionTypeKind.INTERFACE:
177 if (b is InterfaceType) {
178 ResolutionInterfaceType aType = a;
179 return strategy.testElements(a, b, 'element', a.element, b.element) &&
180 strategy.testTypeLists(
181 a, b, 'typeArguments', aType.typeArguments, b.typeArguments);
182 }
183 return false;
184 case ResolutionTypeKind.TYPE_VARIABLE:
185 if (b is TypeVariableType) {
186 return strategy.testElements(a, b, 'element', a.element, b.element);
187 }
188 return false;
189 case ResolutionTypeKind.FUNCTION:
190 if (b is FunctionType) {
191 ResolutionFunctionType aType = a;
192 return strategy.testTypes(
193 a, b, 'returnType', aType.returnType, b.returnType) &&
194 strategy.testTypeLists(a, b, 'parameterTypes',
195 aType.parameterTypes, b.parameterTypes) &&
196 strategy.testTypeLists(a, b, 'optionalParameterTypes',
197 aType.optionalParameterTypes, b.optionalParameterTypes) &&
198 strategy.testLists(a, b, 'namedParameters', aType.namedParameters,
199 b.namedParameters) &&
200 strategy.testTypeLists(a, b, 'namedParameterTypes',
201 aType.namedParameterTypes, b.namedParameterTypes);
202 }
203 return false;
204 default:
205 throw new UnsupportedError('Unsupported equivalence: '
206 '$a (${a.runtimeType}) vs $b (${b.runtimeType})');
207 }
208 }
209
210 bool constantEquivalence(ConstantExpression exp1, ConstantExpression exp2,
211 {TestStrategy strategy}) {
212 strategy ??= defaultStrategy;
213 return areConstantsEquivalent(exp1, exp2, strategy: strategy);
214 }
215
216 bool constantValueEquivalence(ConstantValue value1, ConstantValue value2,
217 {TestStrategy strategy}) {
218 strategy ??= defaultStrategy;
219 return areConstantValuesEquivalent(value1, value2, strategy: strategy);
220 }
221 }
222
223 class KernelTestWorkItemBuilder implements WorkItemBuilder {
224 final Compiler _compiler;
225
226 KernelTestWorkItemBuilder(this._compiler);
227
228 @override
229 WorkItem createWorkItem(MemberEntity entity) {
230 return new KernelTestWorkItem(
231 _compiler, _compiler.backend.impactTransformer, entity);
232 }
233 }
234
235 class KernelTestWorkItem implements ResolutionWorkItem {
236 final Compiler _compiler;
237 final ImpactTransformer _impactTransformer;
238 final MemberElement element;
239
240 KernelTestWorkItem(this._compiler, this._impactTransformer, this.element);
241
242 @override
243 WorldImpact run() {
244 ResolutionImpact resolutionImpact = build(_compiler, element.resolvedAst);
245 return _impactTransformer.transformResolutionImpact(resolutionImpact);
246 }
247 }
248
249 /// Visitor the performers unaliasing of all typedefs nested within a
250 /// [ResolutionDartType].
251 class Unaliaser
252 extends BaseResolutionDartTypeVisitor<dynamic, ResolutionDartType> {
253 const Unaliaser();
254
255 @override
256 ResolutionDartType visit(ResolutionDartType type, [_]) =>
257 type.accept(this, null);
258
259 @override
260 ResolutionDartType visitType(ResolutionDartType type, _) => type;
261
262 List<ResolutionDartType> visitList(List<ResolutionDartType> types) =>
263 types.map(visit).toList();
264
265 @override
266 ResolutionDartType visitInterfaceType(ResolutionInterfaceType type, _) {
267 return type.createInstantiation(visitList(type.typeArguments));
268 }
269
270 @override
271 ResolutionDartType visitTypedefType(ResolutionTypedefType type, _) {
272 return visit(type.unaliased);
273 }
274
275 @override
276 ResolutionDartType visitFunctionType(ResolutionFunctionType type, _) {
277 return new ResolutionFunctionType.synthesized(
278 visit(type.returnType),
279 visitList(type.parameterTypes),
280 visitList(type.optionalParameterTypes),
281 type.namedParameters,
282 visitList(type.namedParameterTypes));
283 }
284 }
285
286 /// Perform unaliasing of all typedefs nested within a [ResolutionDartType].
287 ResolutionDartType unalias(ResolutionDartType type) {
288 return const Unaliaser().visit(type);
289 }
290
291 bool elementFilter(Entity element) {
292 if (element is ConstructorElement && element.isRedirectingFactory) {
293 // Redirecting factory constructors are skipped in kernel.
294 return false;
295 }
296 if (element is ClassElement) {
297 for (ConstructorElement constructor in element.constructors) {
298 if (!constructor.isRedirectingFactory) {
299 return true;
300 }
301 }
302 // The class cannot itself be instantiated.
303 return false;
304 }
305 return true;
306 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698