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

Side by Side Diff: pkg/compiler/lib/src/kernel/element_map.dart

Issue 2858223004: Rename KernelElementAdapter and element_adapter.dart to IrToElementMap and ir_map.dart (Closed)
Patch Set: Updated cf. comments. 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
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2017, 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.kernel.element_map;
6
7 import 'package:kernel/ast.dart' as ir; 5 import 'package:kernel/ast.dart' as ir;
8 6
9 import '../common.dart'; 7 import '../common.dart';
10 import '../common/names.dart' show Identifiers; 8 import '../common/names.dart';
11 import '../common/resolution.dart';
12 import '../compile_time_constants.dart';
13 import '../constants/constant_system.dart';
14 import '../constants/constructors.dart'; 9 import '../constants/constructors.dart';
15 import '../constants/evaluation.dart';
16 import '../constants/expressions.dart'; 10 import '../constants/expressions.dart';
17 import '../constants/values.dart'; 11 import '../constants/values.dart';
18 import '../common_elements.dart'; 12 import '../common_elements.dart';
19 import '../elements/elements.dart'; 13 import '../elements/elements.dart';
20 import '../elements/entities.dart'; 14 import '../elements/entities.dart';
15 import '../elements/operators.dart';
21 import '../elements/types.dart'; 16 import '../elements/types.dart';
22 import '../environment.dart'; 17 import '../js_backend/backend.dart' show JavaScriptBackend;
23 import '../frontend_strategy.dart';
24 import '../js_backend/constant_system_javascript.dart';
25 import '../js_backend/native_data.dart';
26 import '../js_backend/no_such_method_registry.dart';
27 import '../native/native.dart' as native; 18 import '../native/native.dart' as native;
28 import '../native/resolver.dart';
29 import '../ordered_typeset.dart';
30 import '../ssa/kernel_impact.dart';
31 import '../universe/call_structure.dart'; 19 import '../universe/call_structure.dart';
32 import '../universe/world_builder.dart'; 20 import '../universe/selector.dart';
33 import '../util/util.dart' show Link, LinkBuilder; 21 import 'kernel_debug.dart';
34 import 'element_adapter.dart'; 22
35 import 'elements.dart'; 23 /// Interface that translates between Kernel IR nodes and entities.
36 24 abstract class KernelToElementMap {
37 part 'native_basic_data.dart'; 25 /// Access to the commonly used elements and types.
38 part 'no_such_method_resolver.dart'; 26 CommonElements get commonElements;
39 part 'types.dart'; 27
40 28 /// [ElementEnvironment] for library, class and member lookup.
41 /// Element builder used for creating elements and types corresponding to Kernel 29 ElementEnvironment get elementEnvironment;
42 /// IR nodes. 30
43 class KernelToElementMap extends KernelElementAdapterMixin { 31 /// Returns the [DartType] corresponding to [type].
44 final Environment _environment; 32 DartType getDartType(ir.DartType type);
45 CommonElements _commonElements; 33
46 native.BehaviorBuilder _nativeBehaviorBuilder; 34 /// Returns the list of [DartType]s corresponding to [types].
47 final DiagnosticReporter reporter; 35 List<DartType> getDartTypes(List<ir.DartType> types);
48 ElementEnvironment _elementEnvironment; 36
49 DartTypeConverter _typeConverter; 37 /// Returns the [InterfaceType] corresponding to [type].
50 KernelConstantEnvironment _constantEnvironment; 38 InterfaceType getInterfaceType(ir.InterfaceType type);
51 _KernelDartTypes _types; 39
52 40 /// Return the [InterfaceType] corresponding to the [cls] with the given
53 /// Library environment. Used for fast lookup. 41 /// [typeArguments].
54 _KEnv _env = new _KEnv(); 42 InterfaceType createInterfaceType(
55 43 ir.Class cls, List<ir.DartType> typeArguments);
56 /// List of library environments by `KLibrary.libraryIndex`. This is used for 44
57 /// fast lookup into library classes and members. 45 /// Returns the [CallStructure] corresponding to the [arguments].
58 List<_KLibraryEnv> _libraryEnvs = <_KLibraryEnv>[]; 46 CallStructure getCallStructure(ir.Arguments arguments);
59 47
60 /// List of class environments by `KClass.classIndex`. This is used for 48 /// Returns the [Selector] corresponding to the invocation or getter/setter
61 /// fast lookup into class members. 49 /// access of [node].
62 List<_KClassEnv> _classEnvs = <_KClassEnv>[]; 50 Selector getSelector(ir.Expression node);
63 51
64 Map<ir.Library, KLibrary> _libraryMap = <ir.Library, KLibrary>{}; 52 /// Returns the [ConstructorEntity] corresponding to the generative or factory
65 Map<ir.Class, KClass> _classMap = <ir.Class, KClass>{}; 53 /// constructor [node].
66 Map<ir.TypeParameter, KTypeVariable> _typeVariableMap = 54 ConstructorEntity getConstructor(ir.Member node);
67 <ir.TypeParameter, KTypeVariable>{}; 55
68 56 /// Returns the [MemberEntity] corresponding to the member [node].
69 List<_MemberData> _memberList = <_MemberData>[]; 57 MemberEntity getMember(ir.Member node);
70 58
71 Map<ir.Member, KConstructor> _constructorMap = <ir.Member, KConstructor>{}; 59 /// Returns the [FunctionEntity] corresponding to the procedure [node].
72 Map<ir.Procedure, KFunction> _methodMap = <ir.Procedure, KFunction>{}; 60 FunctionEntity getMethod(ir.Procedure node);
73 Map<ir.Field, KField> _fieldMap = <ir.Field, KField>{}; 61
74 62 /// Returns the [FieldEntity] corresponding to the field [node].
75 Map<ir.TreeNode, KLocalFunction> _localFunctionMap = 63 FieldEntity getField(ir.Field node);
76 <ir.TreeNode, KLocalFunction>{}; 64
77 65 /// Returns the [ClassEntity] corresponding to the class [node].
78 KernelToElementMap(this.reporter, this._environment) { 66 ClassEntity getClass(ir.Class node);
79 _elementEnvironment = new KernelElementEnvironment(this); 67
80 _commonElements = new CommonElements(_elementEnvironment); 68 /// Returns the [Local] corresponding to the [node]. The node must be either
81 _constantEnvironment = new KernelConstantEnvironment(this); 69 /// a [ir.FunctionDeclaration] or [ir.FunctionExpression].
82 _nativeBehaviorBuilder = new KernelBehaviorBuilder(_commonElements); 70 Local getLocalFunction(ir.TreeNode node);
83 _types = new _KernelDartTypes(this); 71
84 _typeConverter = new DartTypeConverter(this); 72 /// Returns the [LibraryEntity] corresponding to the library [node].
85 } 73 LibraryEntity getLibrary(ir.Library node);
86 74
87 /// Adds libraries in [program] to the set of libraries. 75 /// Returns the [Name] corresponding to [name].
88 /// 76 Name getName(ir.Name name);
89 /// The main method of the first program is used as the main method for the 77
90 /// compilation. 78 /// Returns `true` is [node] has a `@Native(...)` annotation.
91 void addProgram(ir.Program program) { 79 bool isNativeClass(ir.Class node);
92 _env.addProgram(program); 80
93 } 81 /// Return `true` if [node] is the `dart:_foreign_helper` library.
94 82 bool isForeignLibrary(ir.Library node);
95 KMethod get _mainFunction { 83
96 return _env.mainMethod != null ? _getMethod(_env.mainMethod) : null; 84 /// Computes the native behavior for reading the native [field].
97 } 85 native.NativeBehavior getNativeBehaviorForFieldLoad(ir.Field field);
98 86
99 KLibrary get _mainLibrary { 87 /// Computes the native behavior for writing to the native [field].
100 return _env.mainMethod != null 88 native.NativeBehavior getNativeBehaviorForFieldStore(ir.Field field);
101 ? _getLibrary(_env.mainMethod.enclosingLibrary) 89
102 : null; 90 /// Computes the native behavior for calling [procedure].
103 } 91 native.NativeBehavior getNativeBehaviorForMethod(ir.Procedure procedure);
104 92
105 Iterable<LibraryEntity> get _libraries { 93 /// Computes the [native.NativeBehavior] for a call to the [JS] function.
106 if (_env.length != _libraryMap.length) { 94 native.NativeBehavior getNativeBehaviorForJsCall(ir.StaticInvocation node);
107 // Create a [KLibrary] for each library. 95
108 _env.forEachLibrary((_KLibraryEnv env) { 96 /// Computes the [native.NativeBehavior] for a call to the [JS_BUILTIN]
109 _getLibrary(env.library, env); 97 /// function.
110 }); 98 native.NativeBehavior getNativeBehaviorForJsBuiltinCall(
111 } 99 ir.StaticInvocation node);
112 return _libraryMap.values; 100
113 } 101 /// Computes the [native.NativeBehavior] for a call to the
114 102 /// [JS_EMBEDDED_GLOBAL] function.
115 @override 103 native.NativeBehavior getNativeBehaviorForJsEmbeddedGlobalCall(
116 CommonElements get commonElements => _commonElements; 104 ir.StaticInvocation node);
117 105
118 @override 106 /// Compute the kind of foreign helper function called by [node], if any.
119 ElementEnvironment get elementEnvironment => _elementEnvironment; 107 ForeignKind getForeignKind(ir.StaticInvocation node);
120 108
121 ConstantEnvironment get constantEnvironment => _constantEnvironment; 109 /// Computes the [InterfaceType] referenced by a call to the
122 110 /// [JS_INTERCEPTOR_CONSTANT] function, if any.
123 DartTypes get types => _types; 111 InterfaceType getInterfaceTypeForJsInterceptorCall(ir.StaticInvocation node);
124 112
125 @override 113 /// Computes the [ConstantValue] for the constant [expression].
126 native.BehaviorBuilder get nativeBehaviorBuilder => _nativeBehaviorBuilder; 114 ConstantValue getConstantValue(ir.Expression expression);
127 115 }
128 @override 116
129 ConstantValue computeConstantValue(ConstantExpression constant) { 117 /// Kinds of foreign functions.
130 return _constantEnvironment.getConstantValue(constant); 118 enum ForeignKind {
131 } 119 JS,
132 120 JS_BUILTIN,
133 LibraryEntity lookupLibrary(Uri uri) { 121 JS_EMBEDDED_GLOBAL,
134 _KLibraryEnv libraryEnv = _env.lookupLibrary(uri); 122 JS_INTERCEPTOR_CONSTANT,
135 if (libraryEnv == null) return null; 123 NONE,
136 return _getLibrary(libraryEnv.library, libraryEnv); 124 }
137 } 125
138 126 abstract class KernelToElementMapMixin implements KernelToElementMap {
139 KLibrary _getLibrary(ir.Library node, [_KLibraryEnv libraryEnv]) { 127 DiagnosticReporter get reporter;
140 return _libraryMap.putIfAbsent(node, () { 128 FunctionType getFunctionType(ir.FunctionNode node);
141 Uri canonicalUri = node.importUri; 129 native.BehaviorBuilder get nativeBehaviorBuilder;
142 _libraryEnvs.add(libraryEnv ?? _env.lookupLibrary(canonicalUri)); 130 ConstantValue computeConstantValue(ConstantExpression constant);
143 String name = node.name; 131
144 if (name == null) { 132 @override
145 // Use the file name as script name. 133 Name getName(ir.Name name) {
146 String path = canonicalUri.path; 134 return new Name(
147 name = path.substring(path.lastIndexOf('/') + 1); 135 name.name, name.isPrivate ? getLibrary(name.library) : null);
148 } 136 }
149 return new KLibrary(_libraryMap.length, name, canonicalUri); 137
138 @override
139 CallStructure getCallStructure(ir.Arguments arguments) {
140 int argumentCount = arguments.positional.length + arguments.named.length;
141 List<String> namedArguments = arguments.named.map((e) => e.name).toList();
142 return new CallStructure(argumentCount, namedArguments);
143 }
144
145 @override
146 Selector getSelector(ir.Expression node) {
147 // TODO(efortuna): This is screaming for a common interface between
148 // PropertyGet and SuperPropertyGet (and same for *Get). Talk to kernel
149 // folks.
150 if (node is ir.PropertyGet) {
151 return getGetterSelector(node.name);
152 }
153 if (node is ir.SuperPropertyGet) {
154 return getGetterSelector(node.name);
155 }
156 if (node is ir.PropertySet) {
157 return getSetterSelector(node.name);
158 }
159 if (node is ir.SuperPropertySet) {
160 return getSetterSelector(node.name);
161 }
162 if (node is ir.InvocationExpression) {
163 return getInvocationSelector(node);
164 }
165 throw new SpannableAssertionFailure(
166 CURRENT_ELEMENT_SPANNABLE,
167 "Can only get the selector for a property get or an invocation: "
168 "${node}");
169 }
170
171 Selector getInvocationSelector(ir.InvocationExpression invocation) {
172 Name name = getName(invocation.name);
173 SelectorKind kind;
174 if (Elements.isOperatorName(invocation.name.name)) {
175 if (name == Names.INDEX_NAME || name == Names.INDEX_SET_NAME) {
176 kind = SelectorKind.INDEX;
177 } else {
178 kind = SelectorKind.OPERATOR;
179 }
180 } else {
181 kind = SelectorKind.CALL;
182 }
183
184 CallStructure callStructure = getCallStructure(invocation.arguments);
185 return new Selector(kind, name, callStructure);
186 }
187
188 Selector getGetterSelector(ir.Name irName) {
189 Name name = new Name(
190 irName.name, irName.isPrivate ? getLibrary(irName.library) : null);
191 return new Selector.getter(name);
192 }
193
194 Selector getSetterSelector(ir.Name irName) {
195 Name name = new Name(
196 irName.name, irName.isPrivate ? getLibrary(irName.library) : null);
197 return new Selector.setter(name);
198 }
199
200 ConstantValue getConstantValue(ir.Expression node) {
201 ConstantExpression constant = new Constantifier(this).visit(node);
202 if (constant == null) {
203 throw new UnsupportedError(
204 'No constant for ${DebugPrinter.prettyPrint(node)}');
205 }
206 return computeConstantValue(constant);
207 }
208
209 /// Converts [annotations] into a list of [ConstantValue]s.
210 List<ConstantValue> getMetadata(List<ir.Expression> annotations) {
211 if (annotations.isEmpty) return const <ConstantValue>[];
212 List<ConstantValue> metadata = <ConstantValue>[];
213 annotations.forEach((ir.Expression node) {
214 metadata.add(getConstantValue(node));
150 }); 215 });
151 } 216 return metadata;
152 217 }
153 MemberEntity lookupLibraryMember(KLibrary library, String name, 218
154 {bool setter: false}) { 219 /// Returns `true` is [node] has a `@Native(...)` annotation.
155 _KLibraryEnv libraryEnv = _libraryEnvs[library.libraryIndex]; 220 // TODO(johnniwinther): Cache this for later use.
156 ir.Member member = libraryEnv.lookupMember(name, setter: setter); 221 bool isNativeClass(ir.Class node) {
157 return member != null ? getMember(member) : null; 222 for (ir.Expression annotation in node.annotations) {
158 } 223 if (annotation is ir.ConstructorInvocation) {
159 224 FunctionEntity target = getConstructor(annotation.target);
160 ClassEntity lookupClass(KLibrary library, String name) { 225 if (target.enclosingClass == commonElements.nativeAnnotationClass) {
161 _KLibraryEnv libraryEnv = _libraryEnvs[library.libraryIndex]; 226 return true;
162 _KClassEnv classEnv = libraryEnv.lookupClass(name);
163 if (classEnv != null) {
164 return _getClass(classEnv.cls, classEnv);
165 }
166 return null;
167 }
168
169 void _forEachClass(KLibrary library, void f(ClassEntity cls)) {
170 _KLibraryEnv libraryEnv = _libraryEnvs[library.libraryIndex];
171 libraryEnv.forEachClass((_KClassEnv classEnv) {
172 if (!classEnv.isUnnamedMixinApplication) {
173 f(_getClass(classEnv.cls, classEnv));
174 }
175 });
176 }
177
178 MemberEntity lookupClassMember(KClass cls, String name,
179 {bool setter: false}) {
180 _KClassEnv classEnv = _classEnvs[cls.classIndex];
181 ir.Member member = classEnv.lookupMember(name, setter: setter);
182 return member != null ? getMember(member) : null;
183 }
184
185 ConstructorEntity lookupConstructor(KClass cls, String name) {
186 _KClassEnv classEnv = _classEnvs[cls.classIndex];
187 ir.Member member = classEnv.lookupConstructor(name);
188 return member != null ? getConstructor(member) : null;
189 }
190
191 KClass _getClass(ir.Class node, [_KClassEnv classEnv]) {
192 return _classMap.putIfAbsent(node, () {
193 KLibrary library = _getLibrary(node.enclosingLibrary);
194 if (classEnv == null) {
195 classEnv = _libraryEnvs[library.libraryIndex].lookupClass(node.name);
196 }
197 _classEnvs.add(classEnv);
198 return new KClass(library, _classMap.length, node.name,
199 isAbstract: node.isAbstract);
200 });
201 }
202
203 Iterable<ConstantValue> _getClassMetadata(KClass cls) {
204 return _classEnvs[cls.classIndex].getMetadata(this);
205 }
206
207 KTypeVariable _getTypeVariable(ir.TypeParameter node) {
208 return _typeVariableMap.putIfAbsent(node, () {
209 if (node.parent is ir.Class) {
210 ir.Class cls = node.parent;
211 int index = cls.typeParameters.indexOf(node);
212 return new KTypeVariable(_getClass(cls), node.name, index);
213 }
214 if (node.parent is ir.FunctionNode) {
215 ir.FunctionNode func = node.parent;
216 int index = func.typeParameters.indexOf(node);
217 if (func.parent is ir.Constructor) {
218 ir.Constructor constructor = func.parent;
219 ir.Class cls = constructor.enclosingClass;
220 return _getTypeVariable(cls.typeParameters[index]);
221 } 227 }
222 if (func.parent is ir.Procedure) { 228 }
223 ir.Procedure procedure = func.parent; 229 }
224 if (procedure.kind == ir.ProcedureKind.Factory) { 230 return false;
225 ir.Class cls = procedure.enclosingClass; 231 }
226 return _getTypeVariable(cls.typeParameters[index]); 232
227 } else { 233 /// Compute the kind of foreign helper function called by [node], if any.
228 return new KTypeVariable(_getMethod(procedure), node.name, index); 234 ForeignKind getForeignKind(ir.StaticInvocation node) {
235 if (isForeignLibrary(node.target.enclosingLibrary)) {
236 switch (node.target.name.name) {
237 case JavaScriptBackend.JS:
238 return ForeignKind.JS;
239 case JavaScriptBackend.JS_BUILTIN:
240 return ForeignKind.JS_BUILTIN;
241 case JavaScriptBackend.JS_EMBEDDED_GLOBAL:
242 return ForeignKind.JS_EMBEDDED_GLOBAL;
243 case JavaScriptBackend.JS_INTERCEPTOR_CONSTANT:
244 return ForeignKind.JS_INTERCEPTOR_CONSTANT;
245 }
246 }
247 return ForeignKind.NONE;
248 }
249
250 /// Return `true` if [node] is the `dart:_foreign_helper` library.
251 bool isForeignLibrary(ir.Library node) {
252 return node.importUri == Uris.dart__foreign_helper;
253 }
254
255 /// Looks up [typeName] for use in the spec-string of a `JS` called.
256 // TODO(johnniwinther): Use this in [native.NativeBehavior] instead of calling
257 // the `ForeignResolver`.
258 // TODO(johnniwinther): Cache the result to avoid redundant lookups?
259 native.TypeLookup typeLookup({bool resolveAsRaw: true}) {
260 DartType lookup(String typeName, {bool required}) {
261 DartType findIn(Uri uri) {
262 LibraryEntity library = elementEnvironment.lookupLibrary(uri);
263 if (library != null) {
264 ClassEntity cls = elementEnvironment.lookupClass(library, typeName);
265 if (cls != null) {
266 // TODO(johnniwinther): Align semantics.
267 return resolveAsRaw
268 ? elementEnvironment.getRawType(cls)
269 : elementEnvironment.getThisType(cls);
229 } 270 }
230 } 271 }
231 } 272 return null;
232 throw new UnsupportedError('Unsupported type parameter type node $node.'); 273 }
274
275 // TODO(johnniwinther): Narrow the set of lookups base on the depending
276 // library.
277 DartType type = findIn(Uris.dart_core);
278 type ??= findIn(Uris.dart__js_helper);
279 type ??= findIn(Uris.dart__interceptors);
280 type ??= findIn(Uris.dart__isolate_helper);
281 type ??= findIn(Uris.dart__native_typed_data);
282 type ??= findIn(Uris.dart_collection);
283 type ??= findIn(Uris.dart_math);
284 type ??= findIn(Uris.dart_html);
285 type ??= findIn(Uris.dart_html_common);
286 type ??= findIn(Uris.dart_svg);
287 type ??= findIn(Uris.dart_web_audio);
288 type ??= findIn(Uris.dart_web_gl);
289 type ??= findIn(Uris.dart_web_sql);
290 type ??= findIn(Uris.dart_indexed_db);
291 type ??= findIn(Uris.dart_typed_data);
292 if (type == null && required) {
293 reporter.reportErrorMessage(CURRENT_ELEMENT_SPANNABLE,
294 MessageKind.GENERIC, {'text': "Type '$typeName' not found."});
295 }
296 return type;
297 }
298
299 return lookup;
300 }
301
302 String _getStringArgument(ir.StaticInvocation node, int index) {
303 return node.arguments.positional[index].accept(new Stringifier());
304 }
305
306 /// Computes the [native.NativeBehavior] for a call to the [JS] function.
307 // TODO(johnniwinther): Cache this for later use.
308 native.NativeBehavior getNativeBehaviorForJsCall(ir.StaticInvocation node) {
309 if (node.arguments.positional.length < 2 ||
310 node.arguments.named.isNotEmpty) {
311 reporter.reportErrorMessage(
312 CURRENT_ELEMENT_SPANNABLE, MessageKind.WRONG_ARGUMENT_FOR_JS);
313 return new native.NativeBehavior();
314 }
315 String specString = _getStringArgument(node, 0);
316 if (specString == null) {
317 reporter.reportErrorMessage(
318 CURRENT_ELEMENT_SPANNABLE, MessageKind.WRONG_ARGUMENT_FOR_JS_FIRST);
319 return new native.NativeBehavior();
320 }
321
322 String codeString = _getStringArgument(node, 1);
323 if (codeString == null) {
324 reporter.reportErrorMessage(
325 CURRENT_ELEMENT_SPANNABLE, MessageKind.WRONG_ARGUMENT_FOR_JS_SECOND);
326 return new native.NativeBehavior();
327 }
328
329 return native.NativeBehavior.ofJsCall(
330 specString,
331 codeString,
332 typeLookup(resolveAsRaw: true),
333 CURRENT_ELEMENT_SPANNABLE,
334 reporter,
335 commonElements);
336 }
337
338 /// Computes the [native.NativeBehavior] for a call to the [JS_BUILTIN]
339 /// function.
340 // TODO(johnniwinther): Cache this for later use.
341 native.NativeBehavior getNativeBehaviorForJsBuiltinCall(
342 ir.StaticInvocation node) {
343 if (node.arguments.positional.length < 1) {
344 reporter.internalError(
345 CURRENT_ELEMENT_SPANNABLE, "JS builtin expression has no type.");
346 return new native.NativeBehavior();
347 }
348 if (node.arguments.positional.length < 2) {
349 reporter.internalError(
350 CURRENT_ELEMENT_SPANNABLE, "JS builtin is missing name.");
351 return new native.NativeBehavior();
352 }
353 String specString = _getStringArgument(node, 0);
354 if (specString == null) {
355 reporter.internalError(
356 CURRENT_ELEMENT_SPANNABLE, "Unexpected first argument.");
357 return new native.NativeBehavior();
358 }
359 return native.NativeBehavior.ofJsBuiltinCall(
360 specString,
361 typeLookup(resolveAsRaw: true),
362 CURRENT_ELEMENT_SPANNABLE,
363 reporter,
364 commonElements);
365 }
366
367 /// Computes the [native.NativeBehavior] for a call to the
368 /// [JS_EMBEDDED_GLOBAL] function.
369 // TODO(johnniwinther): Cache this for later use.
370 native.NativeBehavior getNativeBehaviorForJsEmbeddedGlobalCall(
371 ir.StaticInvocation node) {
372 if (node.arguments.positional.length < 1) {
373 reporter.internalError(CURRENT_ELEMENT_SPANNABLE,
374 "JS embedded global expression has no type.");
375 return new native.NativeBehavior();
376 }
377 if (node.arguments.positional.length < 2) {
378 reporter.internalError(
379 CURRENT_ELEMENT_SPANNABLE, "JS embedded global is missing name.");
380 return new native.NativeBehavior();
381 }
382 if (node.arguments.positional.length > 2 ||
383 node.arguments.named.isNotEmpty) {
384 reporter.internalError(CURRENT_ELEMENT_SPANNABLE,
385 "JS embedded global has more than 2 arguments.");
386 return new native.NativeBehavior();
387 }
388 String specString = _getStringArgument(node, 0);
389 if (specString == null) {
390 reporter.internalError(
391 CURRENT_ELEMENT_SPANNABLE, "Unexpected first argument.");
392 return new native.NativeBehavior();
393 }
394 return native.NativeBehavior.ofJsEmbeddedGlobalCall(
395 specString,
396 typeLookup(resolveAsRaw: true),
397 CURRENT_ELEMENT_SPANNABLE,
398 reporter,
399 commonElements);
400 }
401
402 /// Computes the [InterfaceType] referenced by a call to the
403 /// [JS_INTERCEPTOR_CONSTANT] function, if any.
404 InterfaceType getInterfaceTypeForJsInterceptorCall(ir.StaticInvocation node) {
405 if (node.arguments.positional.length != 1 ||
406 node.arguments.named.isNotEmpty) {
407 reporter.reportErrorMessage(CURRENT_ELEMENT_SPANNABLE,
408 MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT);
409 }
410 ir.Node argument = node.arguments.positional.first;
411 if (argument is ir.TypeLiteral && argument.type is ir.InterfaceType) {
412 return getInterfaceType(argument.type);
413 }
414 return null;
415 }
416
417 /// Computes the native behavior for reading the native [field].
418 // TODO(johnniwinther): Cache this for later use.
419 native.NativeBehavior getNativeBehaviorForFieldLoad(ir.Field field) {
420 DartType type = getDartType(field.type);
421 List<ConstantValue> metadata = getMetadata(field.annotations);
422 // TODO(johnniwinther): Provide the correct value for [isJsInterop].
423 return nativeBehaviorBuilder.buildFieldLoadBehavior(
424 type, metadata, typeLookup(resolveAsRaw: false),
425 isJsInterop: false);
426 }
427
428 /// Computes the native behavior for writing to the native [field].
429 // TODO(johnniwinther): Cache this for later use.
430 native.NativeBehavior getNativeBehaviorForFieldStore(ir.Field field) {
431 DartType type = getDartType(field.type);
432 return nativeBehaviorBuilder.buildFieldStoreBehavior(type);
433 }
434
435 /// Computes the native behavior for calling [procedure].
436 // TODO(johnniwinther): Cache this for later use.
437 native.NativeBehavior getNativeBehaviorForMethod(ir.Procedure procedure) {
438 DartType type = getFunctionType(procedure.function);
439 List<ConstantValue> metadata = getMetadata(procedure.annotations);
440 // TODO(johnniwinther): Provide the correct value for [isJsInterop].
441 return nativeBehaviorBuilder.buildMethodBehavior(
442 type, metadata, typeLookup(resolveAsRaw: false),
443 isJsInterop: false);
444 }
445 }
446
447 /// Visitor that converts string literals and concatenations of string literals
448 /// into the string value.
449 class Stringifier extends ir.ExpressionVisitor<String> {
450 @override
451 String visitStringLiteral(ir.StringLiteral node) => node.value;
452
453 @override
454 String visitStringConcatenation(ir.StringConcatenation node) {
455 StringBuffer sb = new StringBuffer();
456 for (ir.Expression expression in node.expressions) {
457 String value = expression.accept(this);
458 if (value == null) return null;
459 sb.write(value);
460 }
461 return sb.toString();
462 }
463 }
464
465 /// Visitor that converts a kernel constant expression into a
466 /// [ConstantExpression].
467 class Constantifier extends ir.ExpressionVisitor<ConstantExpression> {
468 final bool requireConstant;
469 final KernelToElementMapMixin elementAdapter;
470
471 Constantifier(this.elementAdapter, {this.requireConstant: true});
472
473 CommonElements get _commonElements => elementAdapter.commonElements;
474
475 ConstantExpression visit(ir.Expression node) {
476 ConstantExpression constant = node.accept(this);
477 if (constant == null && requireConstant) {
478 throw new UnsupportedError(
479 "No constant computed for $node (${node.runtimeType})");
480 }
481 return constant;
482 }
483
484 ConstantExpression defaultExpression(ir.Expression node) {
485 throw new UnimplementedError(
486 'Unimplemented constant expression $node (${node.runtimeType})');
487 }
488
489 List<ConstantExpression> _computeList(List<ir.Expression> expressions) {
490 List<ConstantExpression> list = <ConstantExpression>[];
491 for (ir.Expression expression in expressions) {
492 ConstantExpression constant = visit(expression);
493 if (constant == null) return null;
494 list.add(constant);
495 }
496 return list;
497 }
498
499 List<ConstantExpression> _computeArguments(ir.Arguments node) {
500 List<ConstantExpression> arguments = <ConstantExpression>[];
501 for (ir.Expression argument in node.positional) {
502 ConstantExpression constant = visit(argument);
503 if (constant == null) return null;
504 arguments.add(constant);
505 }
506 for (ir.NamedExpression argument in node.named) {
507 ConstantExpression constant = visit(argument.value);
508 if (constant == null) return null;
509 arguments.add(constant);
510 }
511 return arguments;
512 }
513
514 ConstructedConstantExpression _computeConstructorInvocation(
515 ir.Constructor target, ir.Arguments arguments) {
516 return new ConstructedConstantExpression(
517 elementAdapter.createInterfaceType(
518 target.enclosingClass, arguments.types),
519 elementAdapter.getConstructor(target),
520 elementAdapter.getCallStructure(arguments),
521 _computeArguments(arguments));
522 }
523
524 @override
525 ConstantExpression visitConstructorInvocation(ir.ConstructorInvocation node) {
526 return _computeConstructorInvocation(node.target, node.arguments);
527 }
528
529 @override
530 ConstantExpression visitVariableGet(ir.VariableGet node) {
531 if (node.variable.parent is ir.FunctionNode) {
532 ir.FunctionNode function = node.variable.parent;
533 int index = function.positionalParameters.indexOf(node.variable);
534 if (index != -1) {
535 return new PositionalArgumentReference(index);
536 } else {
537 assert(function.namedParameters.contains(node.variable));
538 return new NamedArgumentReference(node.variable.name);
539 }
540 }
541 throw new UnimplementedError(
542 'Unimplemented constant expression $node (${node.runtimeType})');
543 }
544
545 @override
546 ConstantExpression visitStaticGet(ir.StaticGet node) {
547 if (node.target is ir.Field) {
548 return new FieldConstantExpression(elementAdapter.getField(node.target));
549 } else if (node.target is ir.Procedure) {
550 FunctionEntity function = elementAdapter.getMethod(node.target);
551 DartType type = elementAdapter.getFunctionType(node.target.function);
552 return new FunctionConstantExpression(function, type);
553 }
554 throw new UnimplementedError(
555 'Unexpected constant expression $node (${node.runtimeType})');
556 }
557
558 @override
559 ConstantExpression visitNullLiteral(ir.NullLiteral node) {
560 return new NullConstantExpression();
561 }
562
563 @override
564 ConstantExpression visitBoolLiteral(ir.BoolLiteral node) {
565 return new BoolConstantExpression(node.value);
566 }
567
568 @override
569 ConstantExpression visitIntLiteral(ir.IntLiteral node) {
570 return new IntConstantExpression(node.value);
571 }
572
573 @override
574 ConstantExpression visitDoubleLiteral(ir.DoubleLiteral node) {
575 return new DoubleConstantExpression(node.value);
576 }
577
578 @override
579 ConstantExpression visitStringLiteral(ir.StringLiteral node) {
580 return new StringConstantExpression(node.value);
581 }
582
583 @override
584 ConstantExpression visitSymbolLiteral(ir.SymbolLiteral node) {
585 return new SymbolConstantExpression(node.value);
586 }
587
588 @override
589 ConstantExpression visitStringConcatenation(ir.StringConcatenation node) {
590 return new ConcatenateConstantExpression(_computeList(node.expressions));
591 }
592
593 @override
594 ConstantExpression visitMapLiteral(ir.MapLiteral node) {
595 if (!node.isConst) {
596 throw new UnimplementedError(
597 'Unexpected constant expression $node (${node.runtimeType})');
598 }
599 DartType keyType = elementAdapter.getDartType(node.keyType);
600 DartType valueType = elementAdapter.getDartType(node.valueType);
601 List<ConstantExpression> keys = <ConstantExpression>[];
602 List<ConstantExpression> values = <ConstantExpression>[];
603 for (ir.MapEntry entry in node.entries) {
604 keys.add(visit(entry.key));
605 values.add(visit(entry.value));
606 }
607 return new MapConstantExpression(
608 _commonElements.mapType(keyType, valueType), keys, values);
609 }
610
611 @override
612 ConstantExpression visitListLiteral(ir.ListLiteral node) {
613 if (!node.isConst) {
614 throw new UnimplementedError(
615 'Unexpected constant expression $node (${node.runtimeType})');
616 }
617 DartType elementType = elementAdapter.getDartType(node.typeArgument);
618 List<ConstantExpression> values = <ConstantExpression>[];
619 for (ir.Expression value in node.expressions) {
620 values.add(visit(value));
621 }
622 return new ListConstantExpression(
623 _commonElements.listType(elementType), values);
624 }
625
626 @override
627 ConstantExpression visitConditionalExpression(ir.ConditionalExpression node) {
628 ConstantExpression condition = visit(node.condition);
629 ConstantExpression trueExp = visit(node.then);
630 ConstantExpression falseExp = visit(node.otherwise);
631 return new ConditionalConstantExpression(condition, trueExp, falseExp);
632 }
633
634 @override
635 ConstantExpression visitPropertyGet(ir.PropertyGet node) {
636 if (node.name.name != 'length') {
637 throw new UnimplementedError(
638 'Unexpected constant expression $node (${node.runtimeType})');
639 }
640 ConstantExpression receiver = visit(node.receiver);
641 return new StringLengthConstantExpression(receiver);
642 }
643
644 @override
645 ConstantExpression visitMethodInvocation(ir.MethodInvocation node) {
646 // Method invocations are generally not constant expressions but unary
647 // and binary expressions are encoded as method invocations in kernel.
648 if (node.arguments.named.isNotEmpty) {
649 throw new UnimplementedError(
650 'Unexpected constant expression $node (${node.runtimeType})');
651 }
652 if (node.arguments.positional.length == 0) {
653 UnaryOperator operator;
654 if (node.name.name == UnaryOperator.NEGATE.selectorName) {
655 operator = UnaryOperator.NEGATE;
656 } else {
657 operator = UnaryOperator.parse(node.name.name);
658 }
659 if (operator != null) {
660 ConstantExpression expression = visit(node.receiver);
661 return new UnaryConstantExpression(operator, expression);
662 }
663 }
664 if (node.arguments.positional.length == 1) {
665 BinaryOperator operator = BinaryOperator.parse(node.name.name);
666 if (operator != null) {
667 ConstantExpression left = visit(node.receiver);
668 ConstantExpression right = visit(node.arguments.positional.single);
669 return new BinaryConstantExpression(left, operator, right);
670 }
671 }
672 throw new UnimplementedError(
673 'Unexpected constant expression $node (${node.runtimeType})');
674 }
675
676 @override
677 ConstantExpression visitStaticInvocation(ir.StaticInvocation node) {
678 MemberEntity member = elementAdapter.getMember(node.target);
679 if (member == _commonElements.identicalFunction) {
680 if (node.arguments.positional.length == 2 &&
681 node.arguments.named.isEmpty) {
682 ConstantExpression left = visit(node.arguments.positional[0]);
683 ConstantExpression right = visit(node.arguments.positional[1]);
684 return new IdenticalConstantExpression(left, right);
685 }
686 } else if (member.name == 'fromEnvironment' &&
687 node.arguments.positional.length == 1) {
688 ConstantExpression name = visit(node.arguments.positional.single);
689 ConstantExpression defaultValue;
690 if (node.arguments.named.length == 1) {
691 if (node.arguments.named.single.name != 'defaultValue') {
692 throw new UnimplementedError(
693 'Unexpected constant expression $node (${node.runtimeType})');
694 }
695 defaultValue = visit(node.arguments.named.single.value);
696 }
697 if (member.enclosingClass == _commonElements.boolClass) {
698 return new BoolFromEnvironmentConstantExpression(name, defaultValue);
699 } else if (member.enclosingClass == _commonElements.intClass) {
700 return new IntFromEnvironmentConstantExpression(name, defaultValue);
701 } else if (member.enclosingClass == _commonElements.stringClass) {
702 return new StringFromEnvironmentConstantExpression(name, defaultValue);
703 }
704 }
705 throw new UnimplementedError(
706 'Unexpected constant expression $node (${node.runtimeType})');
707 }
708
709 @override
710 ConstantExpression visitLogicalExpression(ir.LogicalExpression node) {
711 BinaryOperator operator = BinaryOperator.parse(node.operator);
712 if (operator != null) {
713 ConstantExpression left = visit(node.left);
714 ConstantExpression right = visit(node.right);
715 return new BinaryConstantExpression(left, operator, right);
716 }
717 throw new UnimplementedError(
718 'Unexpected constant expression $node (${node.runtimeType})');
719 }
720
721 /// Compute the [ConstantConstructor] corresponding to the const constructor
722 /// [node].
723 ConstantConstructor computeConstantConstructor(ir.Constructor node) {
724 assert(node.isConst);
725 ir.Class cls = node.enclosingClass;
726 InterfaceType type = elementAdapter.elementEnvironment
727 .getThisType(elementAdapter.getClass(cls));
728
729 Map<dynamic, ConstantExpression> defaultValues =
730 <dynamic, ConstantExpression>{};
731 int parameterIndex = 0;
732 node.function.positionalParameters
733 .forEach((ir.VariableDeclaration parameter) {
734 if (parameterIndex >= node.function.requiredParameterCount) {
735 if (parameter.initializer != null) {
736 defaultValues[parameterIndex] = parameter.initializer.accept(this);
737 } else {
738 defaultValues[parameterIndex] = new NullConstantExpression();
739 }
740 }
741 parameterIndex++;
233 }); 742 });
234 } 743 node.function.namedParameters.forEach((ir.VariableDeclaration parameter) {
235 744 defaultValues[parameter.name] = parameter.initializer.accept(this);
236 ParameterStructure _getParameterStructure(ir.FunctionNode node) { 745 });
237 // TODO(johnniwinther): Cache the computed function type. 746
238 int requiredParameters = node.requiredParameterCount; 747 bool isRedirecting = node.initializers.length == 1 &&
239 int positionalParameters = node.positionalParameters.length; 748 node.initializers.single is ir.RedirectingInitializer;
240 List<String> namedParameters = 749
241 node.namedParameters.map((p) => p.name).toList()..sort(); 750 Map<FieldEntity, ConstantExpression> fieldMap =
242 return new ParameterStructure( 751 <FieldEntity, ConstantExpression>{};
243 requiredParameters, positionalParameters, namedParameters); 752
244 } 753 void registerField(ir.Field field, ConstantExpression constant) {
245 754 fieldMap[elementAdapter.getField(field)] = constant;
246 KConstructor _getConstructor(ir.Member node) { 755 }
247 return _constructorMap.putIfAbsent(node, () { 756
248 int memberIndex = _memberList.length; 757 if (!isRedirecting) {
249 KConstructor constructor; 758 for (ir.Field field in cls.fields) {
250 KClass enclosingClass = _getClass(node.enclosingClass); 759 if (field.initializer != null) {
251 Name name = getName(node.name); 760 registerField(field, field.initializer.accept(this));
252 bool isExternal = node.isExternal; 761 }
253 762 }
254 ir.FunctionNode functionNode; 763 }
255 if (node is ir.Constructor) { 764
256 functionNode = node.function; 765 ConstructedConstantExpression superConstructorInvocation;
257 constructor = new KGenerativeConstructor(memberIndex, enclosingClass, 766 for (ir.Initializer initializer in node.initializers) {
258 name, _getParameterStructure(functionNode), 767 if (initializer is ir.FieldInitializer) {
259 isExternal: isExternal, isConst: node.isConst); 768 registerField(initializer.field, initializer.value.accept(this));
260 } else if (node is ir.Procedure) { 769 } else if (initializer is ir.SuperInitializer) {
261 functionNode = node.function; 770 superConstructorInvocation = _computeConstructorInvocation(
262 constructor = new KFactoryConstructor(memberIndex, enclosingClass, name, 771 initializer.target, initializer.arguments);
263 _getParameterStructure(functionNode), 772 } else if (initializer is ir.RedirectingInitializer) {
264 isExternal: isExternal, isConst: node.isConst); 773 superConstructorInvocation = _computeConstructorInvocation(
774 initializer.target, initializer.arguments);
265 } else { 775 } else {
266 // TODO(johnniwinther): Convert `node.location` to a [SourceSpan]. 776 throw new UnsupportedError(
267 throw new SpannableAssertionFailure( 777 'Unexpected initializer $node (${node.runtimeType})');
268 NO_LOCATION_SPANNABLE, "Unexpected constructor node: ${node}."); 778 }
269 } 779 }
270 _memberList.add(new _ConstructorData(node, functionNode)); 780 if (isRedirecting) {
271 return constructor; 781 return new RedirectingGenerativeConstantConstructor(
272 }); 782 defaultValues, superConstructorInvocation);
273 } 783 } else {
274 784 return new GenerativeConstantConstructor(
275 KFunction _getMethod(ir.Procedure node) { 785 type, defaultValues, fieldMap, superConstructorInvocation);
276 return _methodMap.putIfAbsent(node, () { 786 }
277 int memberIndex = _memberList.length;
278 KLibrary library;
279 KClass enclosingClass;
280 if (node.enclosingClass != null) {
281 enclosingClass = _getClass(node.enclosingClass);
282 library = enclosingClass.library;
283 } else {
284 library = _getLibrary(node.enclosingLibrary);
285 }
286 Name name = getName(node.name);
287 bool isStatic = node.isStatic;
288 bool isExternal = node.isExternal;
289 bool isAbstract = node.isAbstract;
290 KFunction function;
291 switch (node.kind) {
292 case ir.ProcedureKind.Factory:
293 throw new UnsupportedError("Cannot create method from factory.");
294 case ir.ProcedureKind.Getter:
295 function = new KGetter(memberIndex, library, enclosingClass, name,
296 isStatic: isStatic,
297 isExternal: isExternal,
298 isAbstract: isAbstract);
299 break;
300 case ir.ProcedureKind.Method:
301 case ir.ProcedureKind.Operator:
302 function = new KMethod(memberIndex, library, enclosingClass, name,
303 _getParameterStructure(node.function),
304 isStatic: isStatic,
305 isExternal: isExternal,
306 isAbstract: isAbstract);
307 break;
308 case ir.ProcedureKind.Setter:
309 function = new KSetter(
310 memberIndex, library, enclosingClass, getName(node.name).setter,
311 isStatic: isStatic,
312 isExternal: isExternal,
313 isAbstract: isAbstract);
314 break;
315 }
316 _memberList.add(new _FunctionData(node, node.function));
317 return function;
318 });
319 }
320
321 /// Returns the kernel [ir.Procedure] node for the [method].
322 ir.Procedure _lookupProcedure(KFunction method) {
323 return _memberList[method.memberIndex].node;
324 }
325
326 KField _getField(ir.Field node) {
327 return _fieldMap.putIfAbsent(node, () {
328 int memberIndex = _memberList.length;
329 KLibrary library;
330 KClass enclosingClass;
331 if (node.enclosingClass != null) {
332 enclosingClass = _getClass(node.enclosingClass);
333 library = enclosingClass.library;
334 } else {
335 library = _getLibrary(node.enclosingLibrary);
336 }
337 Name name = getName(node.name);
338 bool isStatic = node.isStatic;
339 _memberList.add(new _FieldData(node));
340 return new KField(memberIndex, library, enclosingClass, name,
341 isStatic: isStatic,
342 isAssignable: node.isMutable,
343 isConst: node.isConst);
344 });
345 }
346
347 KLocalFunction _getLocal(ir.TreeNode node) {
348 return _localFunctionMap.putIfAbsent(node, () {
349 MemberEntity memberContext;
350 Entity executableContext;
351 ir.TreeNode parent = node.parent;
352 while (parent != null) {
353 if (parent is ir.Member) {
354 executableContext = memberContext = getMember(parent);
355 break;
356 }
357 if (parent is ir.FunctionDeclaration ||
358 parent is ir.FunctionExpression) {
359 KLocalFunction localFunction = _getLocal(parent);
360 executableContext = localFunction;
361 memberContext = localFunction.memberContext;
362 break;
363 }
364 parent = parent.parent;
365 }
366 String name;
367 FunctionType functionType;
368 if (node is ir.FunctionDeclaration) {
369 name = node.variable.name;
370 functionType = getFunctionType(node.function);
371 } else if (node is ir.FunctionExpression) {
372 functionType = getFunctionType(node.function);
373 }
374 return new KLocalFunction(
375 name, memberContext, executableContext, functionType);
376 });
377 }
378
379 @override
380 DartType getDartType(ir.DartType type) => _typeConverter.convert(type);
381
382 @override
383 InterfaceType createInterfaceType(
384 ir.Class cls, List<ir.DartType> typeArguments) {
385 return new InterfaceType(getClass(cls), getDartTypes(typeArguments));
386 }
387
388 @override
389 InterfaceType getInterfaceType(ir.InterfaceType type) =>
390 _typeConverter.convert(type);
391
392 @override
393 List<DartType> getDartTypes(List<ir.DartType> types) {
394 // TODO(johnniwinther): Add the type argument to the list literal when we
395 // no longer use resolution types.
396 List<DartType> list = /*<DartType>*/ [];
397 types.forEach((ir.DartType type) {
398 list.add(getDartType(type));
399 });
400 return list;
401 }
402
403 void _ensureThisAndRawType(KClass cls, _KClassEnv env) {
404 if (env.thisType == null) {
405 ir.Class node = env.cls;
406 // TODO(johnniwinther): Add the type argument to the list literal when we
407 // no longer use resolution types.
408 if (node.typeParameters.isEmpty) {
409 env.thisType =
410 env.rawType = new InterfaceType(cls, const/*<DartType>*/ []);
411 } else {
412 env.thisType = new InterfaceType(
413 cls,
414 new List/*<DartType>*/ .generate(node.typeParameters.length,
415 (int index) {
416 return new TypeVariableType(
417 _getTypeVariable(node.typeParameters[index]));
418 }));
419 env.rawType = new InterfaceType(
420 cls,
421 new List/*<DartType>*/ .filled(
422 node.typeParameters.length, const DynamicType()));
423 }
424 }
425 }
426
427 InterfaceType _getThisType(KClass cls) {
428 _KClassEnv env = _classEnvs[cls.classIndex];
429 _ensureThisAndRawType(cls, env);
430 return env.thisType;
431 }
432
433 InterfaceType _getRawType(KClass cls) {
434 _KClassEnv env = _classEnvs[cls.classIndex];
435 _ensureThisAndRawType(cls, env);
436 return env.rawType;
437 }
438
439 InterfaceType _asInstanceOf(InterfaceType type, KClass cls) {
440 OrderedTypeSet orderedTypeSet = _getOrderedTypeSet(type.element);
441 InterfaceType supertype =
442 orderedTypeSet.asInstanceOf(cls, _getHierarchyDepth(cls));
443 if (supertype != null) {
444 supertype = _substByContext(supertype, type);
445 }
446 return supertype;
447 }
448
449 void _ensureSupertypes(KClass cls, _KClassEnv env) {
450 if (env.orderedTypeSet == null) {
451 _ensureThisAndRawType(cls, env);
452
453 ir.Class node = env.cls;
454
455 if (node.supertype == null) {
456 env.orderedTypeSet = new OrderedTypeSet.singleton(env.thisType);
457 } else {
458 InterfaceType processSupertype(ir.Supertype node) {
459 InterfaceType type = _typeConverter.visitSupertype(node);
460 KClass superclass = type.element;
461 _KClassEnv env = _classEnvs[superclass.classIndex];
462 _ensureSupertypes(superclass, env);
463 return type;
464 }
465
466 env.supertype = processSupertype(node.supertype);
467 LinkBuilder<InterfaceType> linkBuilder =
468 new LinkBuilder<InterfaceType>();
469 if (node.mixedInType != null) {
470 linkBuilder
471 .addLast(env.mixedInType = processSupertype(node.mixedInType));
472 }
473 node.implementedTypes.forEach((ir.Supertype supertype) {
474 linkBuilder.addLast(processSupertype(supertype));
475 });
476 Link<InterfaceType> interfaces = linkBuilder.toLink();
477 OrderedTypeSetBuilder setBuilder =
478 new _KernelOrderedTypeSetBuilder(this, cls);
479 env.orderedTypeSet =
480 setBuilder.createOrderedTypeSet(env.supertype, interfaces);
481 }
482 }
483 }
484
485 OrderedTypeSet _getOrderedTypeSet(KClass cls) {
486 _KClassEnv env = _classEnvs[cls.classIndex];
487 _ensureSupertypes(cls, env);
488 return env.orderedTypeSet;
489 }
490
491 int _getHierarchyDepth(KClass cls) {
492 _KClassEnv env = _classEnvs[cls.classIndex];
493 _ensureSupertypes(cls, env);
494 return env.orderedTypeSet.maxDepth;
495 }
496
497 InterfaceType _substByContext(InterfaceType type, InterfaceType context) {
498 return type.subst(
499 context.typeArguments, _getThisType(context.element).typeArguments);
500 }
501
502 InterfaceType _getSuperType(KClass cls) {
503 _KClassEnv env = _classEnvs[cls.classIndex];
504 _ensureSupertypes(cls, env);
505 return env.supertype;
506 }
507
508 bool _isUnnamedMixinApplication(KClass cls) {
509 _KClassEnv env = _classEnvs[cls.classIndex];
510 _ensureSupertypes(cls, env);
511 return env.isUnnamedMixinApplication;
512 }
513
514 void _forEachSupertype(KClass cls, void f(InterfaceType supertype)) {
515 _KClassEnv env = _classEnvs[cls.classIndex];
516 _ensureSupertypes(cls, env);
517 env.orderedTypeSet.supertypes.forEach(f);
518 }
519
520 void _forEachMixin(KClass cls, void f(ClassEntity mixin)) {
521 while (cls != null) {
522 _KClassEnv env = _classEnvs[cls.classIndex];
523 _ensureSupertypes(cls, env);
524 if (env.mixedInType != null) {
525 f(env.mixedInType.element);
526 }
527 cls = env.supertype?.element;
528 }
529 }
530
531 void _forEachClassMember(
532 KClass cls, void f(ClassEntity cls, MemberEntity member)) {
533 _KClassEnv env = _classEnvs[cls.classIndex];
534 env.forEachMember((ir.Member member) {
535 f(cls, getMember(member));
536 });
537 _ensureSupertypes(cls, env);
538 if (env.supertype != null) {
539 _forEachClassMember(env.supertype.element, f);
540 }
541 }
542
543 @override
544 FunctionType getFunctionType(ir.FunctionNode node) {
545 DartType returnType = getDartType(node.returnType);
546 List<DartType> parameterTypes = /*<DartType>*/ [];
547 List<DartType> optionalParameterTypes = /*<DartType>*/ [];
548 for (ir.VariableDeclaration variable in node.positionalParameters) {
549 if (parameterTypes.length == node.requiredParameterCount) {
550 optionalParameterTypes.add(getDartType(variable.type));
551 } else {
552 parameterTypes.add(getDartType(variable.type));
553 }
554 }
555 List<String> namedParameters = <String>[];
556 List<DartType> namedParameterTypes = /*<DartType>*/ [];
557 List<ir.VariableDeclaration> sortedNamedParameters =
558 node.namedParameters.toList()..sort((a, b) => a.name.compareTo(b.name));
559 for (ir.VariableDeclaration variable in sortedNamedParameters) {
560 namedParameters.add(variable.name);
561 namedParameterTypes.add(getDartType(variable.type));
562 }
563 return new FunctionType(returnType, parameterTypes, optionalParameterTypes,
564 namedParameters, namedParameterTypes);
565 }
566
567 LibraryEntity getLibrary(ir.Library node) => _getLibrary(node);
568
569 ir.Library getKernelLibrary(KLibrary entity) =>
570 _libraryEnvs[entity.libraryIndex].library;
571
572 ir.Class getKernelClass(KClass entity) => _classEnvs[entity.classIndex].cls;
573
574 @override
575 Local getLocalFunction(ir.TreeNode node) => _getLocal(node);
576
577 @override
578 ClassEntity getClass(ir.Class node) => _getClass(node);
579
580 @override
581 FieldEntity getField(ir.Field node) => _getField(node);
582
583 TypeVariableEntity getTypeVariable(ir.TypeParameter node) =>
584 _getTypeVariable(node);
585
586 @override
587 FunctionEntity getMethod(ir.Procedure node) => _getMethod(node);
588
589 @override
590 MemberEntity getMember(ir.Member node) {
591 if (node is ir.Field) {
592 return _getField(node);
593 } else if (node is ir.Constructor) {
594 return _getConstructor(node);
595 } else if (node is ir.Procedure) {
596 if (node.kind == ir.ProcedureKind.Factory) {
597 return _getConstructor(node);
598 } else {
599 return _getMethod(node);
600 }
601 }
602 throw new UnsupportedError("Unexpected member: $node");
603 }
604
605 @override
606 FunctionEntity getConstructor(ir.Member node) => _getConstructor(node);
607
608 ConstantConstructor _getConstructorConstant(KConstructor constructor) {
609 _ConstructorData data = _memberList[constructor.memberIndex];
610 return data.getConstructorConstant(this, constructor);
611 }
612
613 ConstantExpression _getFieldConstant(KField field) {
614 _FieldData data = _memberList[field.memberIndex];
615 return data.getFieldConstant(this, field);
616 }
617
618 FunctionType _getFunctionType(KFunction function) {
619 _FunctionData data = _memberList[function.memberIndex];
620 return data.getFunctionType(this);
621 }
622
623 ResolutionImpact computeWorldImpact(KMember member) {
624 return _memberList[member.memberIndex].getWorldImpact(this);
625 } 787 }
626 } 788 }
627
628 /// Environment for fast lookup of program libraries.
629 class _KEnv {
630 final Set<ir.Program> programs = new Set<ir.Program>();
631
632 Map<Uri, _KLibraryEnv> _libraryMap;
633
634 /// TODO(johnniwinther): Handle arbitrary load order if needed.
635 ir.Member get mainMethod => programs.first?.mainMethod;
636
637 void addProgram(ir.Program program) {
638 if (programs.add(program)) {
639 if (_libraryMap != null) {
640 _addLibraries(program);
641 }
642 }
643 }
644
645 void _addLibraries(ir.Program program) {
646 for (ir.Library library in program.libraries) {
647 _libraryMap[library.importUri] = new _KLibraryEnv(library);
648 }
649 }
650
651 void _ensureLibraryMap() {
652 if (_libraryMap == null) {
653 _libraryMap = <Uri, _KLibraryEnv>{};
654 for (ir.Program program in programs) {
655 _addLibraries(program);
656 }
657 }
658 }
659
660 /// Return the [_KLibraryEnv] for the library with the canonical [uri].
661 _KLibraryEnv lookupLibrary(Uri uri) {
662 _ensureLibraryMap();
663 return _libraryMap[uri];
664 }
665
666 /// Calls [f] for each library in this environment.
667 void forEachLibrary(void f(_KLibraryEnv library)) {
668 _ensureLibraryMap();
669 _libraryMap.values.forEach(f);
670 }
671
672 /// Returns the number of libraries in this environment.
673 int get length {
674 _ensureLibraryMap();
675 return _libraryMap.length;
676 }
677 }
678
679 /// Environment for fast lookup of library classes and members.
680 class _KLibraryEnv {
681 final ir.Library library;
682
683 Map<String, _KClassEnv> _classMap;
684 Map<String, ir.Member> _memberMap;
685 Map<String, ir.Member> _setterMap;
686
687 _KLibraryEnv(this.library);
688
689 void _ensureClassMap() {
690 if (_classMap == null) {
691 _classMap = <String, _KClassEnv>{};
692 for (ir.Class cls in library.classes) {
693 _classMap[cls.name] = new _KClassEnv(cls);
694 }
695 }
696 }
697
698 /// Return the [_KClassEnv] for the class [name] in [library].
699 _KClassEnv lookupClass(String name) {
700 _ensureClassMap();
701 return _classMap[name];
702 }
703
704 /// Calls [f] for each class in this library.
705 void forEachClass(void f(_KClassEnv cls)) {
706 _ensureClassMap();
707 _classMap.values.forEach(f);
708 }
709
710 /// Return the [ir.Member] for the member [name] in [library].
711 ir.Member lookupMember(String name, {bool setter: false}) {
712 if (_memberMap == null) {
713 _memberMap = <String, ir.Member>{};
714 _setterMap = <String, ir.Member>{};
715 for (ir.Member member in library.members) {
716 if (member is ir.Procedure) {
717 if (member.kind == ir.ProcedureKind.Setter) {
718 _setterMap[member.name.name] = member;
719 } else {
720 _memberMap[member.name.name] = member;
721 }
722 } else if (member is ir.Field) {
723 _memberMap[member.name.name] = member;
724 if (member.isMutable) {
725 _setterMap[member.name.name] = member;
726 }
727 } else {
728 throw new SpannableAssertionFailure(
729 NO_LOCATION_SPANNABLE, "Unexpected library member node: $member");
730 }
731 }
732 }
733 return _memberMap[name];
734 }
735 }
736
737 /// Environment for fast lookup of class members.
738 class _KClassEnv {
739 final ir.Class cls;
740 final bool isUnnamedMixinApplication;
741
742 InterfaceType thisType;
743 InterfaceType rawType;
744 InterfaceType supertype;
745 InterfaceType mixedInType;
746 OrderedTypeSet orderedTypeSet;
747
748 Map<String, ir.Member> _constructorMap;
749 Map<String, ir.Member> _memberMap;
750 Map<String, ir.Member> _setterMap;
751
752 Iterable<ConstantValue> _metadata;
753
754 _KClassEnv(this.cls)
755 // TODO(johnniwinther): Change this to use a property on [cls] when such
756 // is added to kernel.
757 : isUnnamedMixinApplication = cls.name.contains('+');
758
759 void _ensureMaps() {
760 if (_memberMap == null) {
761 _memberMap = <String, ir.Member>{};
762 _setterMap = <String, ir.Member>{};
763 _constructorMap = <String, ir.Member>{};
764
765 void addMembers(ir.Class c) {
766 for (ir.Member member in c.members) {
767 if (member is ir.Constructor ||
768 member is ir.Procedure &&
769 member.kind == ir.ProcedureKind.Factory) {
770 _constructorMap[member.name.name] = member;
771 } else if (member is ir.Procedure) {
772 if (member.kind == ir.ProcedureKind.Setter) {
773 _setterMap[member.name.name] = member;
774 } else {
775 _memberMap[member.name.name] = member;
776 }
777 } else if (member is ir.Field) {
778 _memberMap[member.name.name] = member;
779 if (member.isMutable) {
780 _setterMap[member.name.name] = member;
781 }
782 _memberMap[member.name.name] = member;
783 } else {
784 throw new SpannableAssertionFailure(
785 NO_LOCATION_SPANNABLE, "Unexpected class member node: $member");
786 }
787 }
788 }
789
790 if (cls.mixedInClass != null) {
791 addMembers(cls.mixedInClass);
792 }
793 addMembers(cls);
794 }
795 }
796
797 /// Return the [ir.Member] for the member [name] in [library].
798 ir.Member lookupMember(String name, {bool setter: false}) {
799 _ensureMaps();
800 return setter ? _setterMap[name] : _memberMap[name];
801 }
802
803 /// Return the [ir.Member] for the member [name] in [library].
804 ir.Member lookupConstructor(String name) {
805 _ensureMaps();
806 return _constructorMap[name];
807 }
808
809 void forEachMember(f(ir.Member member)) {
810 _ensureMaps();
811 _memberMap.values.forEach(f);
812 for (ir.Member member in _setterMap.values) {
813 if (member is ir.Procedure) {
814 f(member);
815 } else {
816 // Skip fields; these are also in _memberMap.
817 }
818 }
819 }
820
821 Iterable<ConstantValue> getMetadata(KernelToElementMap elementMap) {
822 return _metadata ??= elementMap.getMetadata(cls.annotations);
823 }
824 }
825
826 class _MemberData {
827 final ir.Member node;
828 Iterable<ConstantValue> _metadata;
829
830 _MemberData(this.node);
831
832 ResolutionImpact getWorldImpact(KernelToElementMap elementMap) {
833 return buildKernelImpact(node, elementMap);
834 }
835
836 Iterable<ConstantValue> getMetadata(KernelToElementMap elementMap) {
837 return _metadata ??= elementMap.getMetadata(node.annotations);
838 }
839 }
840
841 class _FunctionData extends _MemberData {
842 final ir.FunctionNode functionNode;
843 FunctionType _type;
844 CallStructure _callStructure;
845
846 _FunctionData(ir.Member node, this.functionNode) : super(node);
847
848 FunctionType getFunctionType(KernelToElementMap elementMap) {
849 return _type ??= elementMap.getFunctionType(functionNode);
850 }
851
852 CallStructure get callStructure {
853 return _callStructure ??= new CallStructure(
854 functionNode.positionalParameters.length +
855 functionNode.namedParameters.length,
856 functionNode.namedParameters.map((d) => d.name).toList());
857 }
858 }
859
860 class _ConstructorData extends _FunctionData {
861 ConstantConstructor _constantConstructor;
862
863 _ConstructorData(ir.Member node, ir.FunctionNode functionNode)
864 : super(node, functionNode);
865
866 ConstantConstructor getConstructorConstant(
867 KernelToElementMap elementMap, KConstructor constructor) {
868 if (_constantConstructor == null) {
869 if (node is ir.Constructor && constructor.isConst) {
870 _constantConstructor =
871 new Constantifier(elementMap).computeConstantConstructor(node);
872 } else {
873 throw new SpannableAssertionFailure(
874 constructor,
875 "Unexpected constructor $constructor in "
876 "KernelWorldBuilder._getConstructorConstant");
877 }
878 }
879 return _constantConstructor;
880 }
881 }
882
883 class _FieldData extends _MemberData {
884 ConstantExpression _constant;
885
886 _FieldData(ir.Field node) : super(node);
887
888 ir.Field get node => super.node;
889
890 ConstantExpression getFieldConstant(
891 KernelToElementMap elementMap, KField field) {
892 if (_constant == null) {
893 if (node.isConst) {
894 _constant = new Constantifier(elementMap).visit(node.initializer);
895 } else {
896 throw new SpannableAssertionFailure(
897 field,
898 "Unexpected field $field in "
899 "KernelWorldBuilder._getConstructorConstant");
900 }
901 }
902 return _constant;
903 }
904 }
905
906 class KernelElementEnvironment implements ElementEnvironment {
907 final KernelToElementMap elementMap;
908
909 KernelElementEnvironment(this.elementMap);
910
911 @override
912 DartType get dynamicType => const DynamicType();
913
914 @override
915 LibraryEntity get mainLibrary => elementMap._mainLibrary;
916
917 @override
918 FunctionEntity get mainFunction => elementMap._mainFunction;
919
920 @override
921 Iterable<LibraryEntity> get libraries => elementMap._libraries;
922
923 @override
924 InterfaceType getThisType(ClassEntity cls) {
925 return elementMap._getThisType(cls);
926 }
927
928 @override
929 InterfaceType getRawType(ClassEntity cls) {
930 return elementMap._getRawType(cls);
931 }
932
933 @override
934 bool isGenericClass(ClassEntity cls) {
935 return getThisType(cls).typeArguments.isNotEmpty;
936 }
937
938 @override
939 DartType getTypeVariableBound(TypeVariableEntity typeVariable) {
940 throw new UnimplementedError(
941 'KernelElementEnvironment.getTypeVariableBound');
942 }
943
944 @override
945 InterfaceType createInterfaceType(
946 ClassEntity cls, List<DartType> typeArguments) {
947 return new InterfaceType(cls, typeArguments);
948 }
949
950 @override
951 bool isSubtype(DartType a, DartType b) {
952 return elementMap.types.isSubtype(a, b);
953 }
954
955 @override
956 FunctionType getFunctionType(KFunction function) {
957 return elementMap._getFunctionType(function);
958 }
959
960 @override
961 FunctionType getLocalFunctionType(KLocalFunction function) {
962 return function.functionType;
963 }
964
965 @override
966 DartType getUnaliasedType(DartType type) => type;
967
968 @override
969 ConstructorEntity lookupConstructor(ClassEntity cls, String name,
970 {bool required: false}) {
971 ConstructorEntity constructor = elementMap.lookupConstructor(cls, name);
972 if (constructor == null && required) {
973 throw new SpannableAssertionFailure(
974 CURRENT_ELEMENT_SPANNABLE,
975 "The constructor '$name' was not found in class '${cls.name}' "
976 "in library ${cls.library.canonicalUri}.");
977 }
978 return constructor;
979 }
980
981 @override
982 MemberEntity lookupClassMember(ClassEntity cls, String name,
983 {bool setter: false, bool required: false}) {
984 MemberEntity member =
985 elementMap.lookupClassMember(cls, name, setter: setter);
986 if (member == null && required) {
987 throw new SpannableAssertionFailure(CURRENT_ELEMENT_SPANNABLE,
988 "The member '$name' was not found in ${cls.name}.");
989 }
990 return member;
991 }
992
993 @override
994 ClassEntity getSuperClass(ClassEntity cls,
995 {bool skipUnnamedMixinApplications: false}) {
996 ClassEntity superclass = elementMap._getSuperType(cls)?.element;
997 if (skipUnnamedMixinApplications) {
998 while (superclass != null &&
999 elementMap._isUnnamedMixinApplication(superclass)) {
1000 superclass = elementMap._getSuperType(superclass)?.element;
1001 }
1002 }
1003 return superclass;
1004 }
1005
1006 @override
1007 void forEachSupertype(ClassEntity cls, void f(InterfaceType supertype)) {
1008 elementMap._forEachSupertype(cls, f);
1009 }
1010
1011 @override
1012 void forEachMixin(ClassEntity cls, void f(ClassEntity mixin)) {
1013 elementMap._forEachMixin(cls, f);
1014 }
1015
1016 @override
1017 void forEachClassMember(
1018 ClassEntity cls, void f(ClassEntity declarer, MemberEntity member)) {
1019 elementMap._forEachClassMember(cls, f);
1020 }
1021
1022 @override
1023 MemberEntity lookupLibraryMember(LibraryEntity library, String name,
1024 {bool setter: false, bool required: false}) {
1025 MemberEntity member =
1026 elementMap.lookupLibraryMember(library, name, setter: setter);
1027 if (member == null && required) {
1028 throw new SpannableAssertionFailure(CURRENT_ELEMENT_SPANNABLE,
1029 "The member '${name}' was not found in library '${library.name}'.");
1030 }
1031 return member;
1032 }
1033
1034 @override
1035 ClassEntity lookupClass(LibraryEntity library, String name,
1036 {bool required: false}) {
1037 ClassEntity cls = elementMap.lookupClass(library, name);
1038 if (cls == null && required) {
1039 throw new SpannableAssertionFailure(CURRENT_ELEMENT_SPANNABLE,
1040 "The class '$name' was not found in library '${library.name}'.");
1041 }
1042 return cls;
1043 }
1044
1045 @override
1046 void forEachClass(KLibrary library, void f(ClassEntity cls)) {
1047 elementMap._forEachClass(library, f);
1048 }
1049
1050 @override
1051 LibraryEntity lookupLibrary(Uri uri, {bool required: false}) {
1052 LibraryEntity library = elementMap.lookupLibrary(uri);
1053 if (library == null && required) {
1054 throw new SpannableAssertionFailure(
1055 CURRENT_ELEMENT_SPANNABLE, "The library '$uri' was not found.");
1056 }
1057 return library;
1058 }
1059
1060 @override
1061 CallStructure getCallStructure(KFunction function) {
1062 _FunctionData data = elementMap._memberList[function.memberIndex];
1063 return data.callStructure;
1064 }
1065
1066 @override
1067 bool isDeferredLoadLibraryGetter(KMember member) {
1068 // TODO(johnniwinther): Support these.
1069 return false;
1070 }
1071
1072 @override
1073 Iterable<ConstantValue> getMemberMetadata(KMember member) {
1074 _MemberData memberData = elementMap._memberList[member.memberIndex];
1075 return memberData.getMetadata(elementMap);
1076 }
1077 }
1078
1079 /// Visitor that converts kernel dart types into [DartType].
1080 class DartTypeConverter extends ir.DartTypeVisitor<DartType> {
1081 final KernelToElementMap elementAdapter;
1082 bool topLevel = true;
1083
1084 DartTypeConverter(this.elementAdapter);
1085
1086 DartType convert(ir.DartType type) {
1087 topLevel = true;
1088 return type.accept(this);
1089 }
1090
1091 /// Visit a inner type.
1092 DartType visitType(ir.DartType type) {
1093 topLevel = false;
1094 return type.accept(this);
1095 }
1096
1097 InterfaceType visitSupertype(ir.Supertype node) {
1098 ClassEntity cls = elementAdapter.getClass(node.classNode);
1099 return new InterfaceType(cls, visitTypes(node.typeArguments));
1100 }
1101
1102 List<DartType> visitTypes(List<ir.DartType> types) {
1103 topLevel = false;
1104 return new List.generate(
1105 types.length, (int index) => types[index].accept(this));
1106 }
1107
1108 @override
1109 DartType visitTypeParameterType(ir.TypeParameterType node) {
1110 return new TypeVariableType(elementAdapter.getTypeVariable(node.parameter));
1111 }
1112
1113 @override
1114 DartType visitFunctionType(ir.FunctionType node) {
1115 return new FunctionType(
1116 visitType(node.returnType),
1117 visitTypes(node.positionalParameters
1118 .take(node.requiredParameterCount)
1119 .toList()),
1120 visitTypes(node.positionalParameters
1121 .skip(node.requiredParameterCount)
1122 .toList()),
1123 node.namedParameters.map((n) => n.name).toList(),
1124 node.namedParameters.map((n) => visitType(n.type)).toList());
1125 }
1126
1127 @override
1128 DartType visitInterfaceType(ir.InterfaceType node) {
1129 ClassEntity cls = elementAdapter.getClass(node.classNode);
1130 return new InterfaceType(cls, visitTypes(node.typeArguments));
1131 }
1132
1133 @override
1134 DartType visitVoidType(ir.VoidType node) {
1135 return const VoidType();
1136 }
1137
1138 @override
1139 DartType visitDynamicType(ir.DynamicType node) {
1140 return const DynamicType();
1141 }
1142
1143 @override
1144 DartType visitInvalidType(ir.InvalidType node) {
1145 if (topLevel) {
1146 throw new UnimplementedError(
1147 "Outermost invalid types not currently supported");
1148 }
1149 // Nested invalid types are treated as `dynamic`.
1150 return const DynamicType();
1151 }
1152 }
1153
1154 /// [native.BehaviorBuilder] for kernel based elements.
1155 class KernelBehaviorBuilder extends native.BehaviorBuilder {
1156 final CommonElements commonElements;
1157
1158 KernelBehaviorBuilder(this.commonElements);
1159
1160 @override
1161 bool get trustJSInteropTypeAnnotations {
1162 throw new UnimplementedError(
1163 "KernelNativeBehaviorComputer.trustJSInteropTypeAnnotations");
1164 }
1165
1166 @override
1167 DiagnosticReporter get reporter {
1168 throw new UnimplementedError("KernelNativeBehaviorComputer.reporter");
1169 }
1170
1171 @override
1172 NativeData get nativeData {
1173 throw new UnimplementedError("KernelNativeBehaviorComputer.nativeData");
1174 }
1175 }
1176
1177 /// Constant environment mapping [ConstantExpression]s to [ConstantValue]s using
1178 /// [_EvaluationEnvironment] for the evaluation.
1179 class KernelConstantEnvironment implements ConstantEnvironment {
1180 KernelToElementMap _worldBuilder;
1181 Map<ConstantExpression, ConstantValue> _valueMap =
1182 <ConstantExpression, ConstantValue>{};
1183
1184 KernelConstantEnvironment(this._worldBuilder);
1185
1186 @override
1187 ConstantSystem get constantSystem => const JavaScriptConstantSystem();
1188
1189 @override
1190 ConstantValue getConstantValueForVariable(VariableElement element) {
1191 throw new UnimplementedError(
1192 "KernelConstantEnvironment.getConstantValueForVariable");
1193 }
1194
1195 @override
1196 ConstantValue getConstantValue(ConstantExpression expression) {
1197 return _valueMap.putIfAbsent(expression, () {
1198 return expression.evaluate(
1199 new _EvaluationEnvironment(_worldBuilder), constantSystem);
1200 });
1201 }
1202
1203 @override
1204 bool hasConstantValue(ConstantExpression expression) {
1205 throw new UnimplementedError("KernelConstantEnvironment.hasConstantValue");
1206 }
1207 }
1208
1209 /// Evaluation environment used for computing [ConstantValue]s for
1210 /// kernel based [ConstantExpression]s.
1211 class _EvaluationEnvironment implements EvaluationEnvironment {
1212 final KernelToElementMap _elementMap;
1213
1214 _EvaluationEnvironment(this._elementMap);
1215
1216 @override
1217 CommonElements get commonElements => _elementMap.commonElements;
1218
1219 @override
1220 InterfaceType substByContext(InterfaceType base, InterfaceType target) {
1221 return _elementMap._substByContext(base, target);
1222 }
1223
1224 @override
1225 ConstantConstructor getConstructorConstant(ConstructorEntity constructor) {
1226 return _elementMap._getConstructorConstant(constructor);
1227 }
1228
1229 @override
1230 ConstantExpression getFieldConstant(FieldEntity field) {
1231 return _elementMap._getFieldConstant(field);
1232 }
1233
1234 @override
1235 ConstantExpression getLocalConstant(Local local) {
1236 throw new UnimplementedError("_EvaluationEnvironment.getLocalConstant");
1237 }
1238
1239 @override
1240 String readFromEnvironment(String name) {
1241 return _elementMap._environment.valueOf(name);
1242 }
1243 }
1244
1245 class KernelResolutionWorldBuilder extends KernelResolutionWorldBuilderBase {
1246 final KernelToElementMap elementMap;
1247
1248 KernelResolutionWorldBuilder(this.elementMap, NativeBasicData nativeBasicData,
1249 SelectorConstraintsStrategy selectorConstraintsStrategy)
1250 : super(elementMap.elementEnvironment, elementMap.commonElements,
1251 nativeBasicData, selectorConstraintsStrategy);
1252
1253 @override
1254 Iterable<InterfaceType> getSupertypes(ClassEntity cls) {
1255 return elementMap._getOrderedTypeSet(cls).supertypes;
1256 }
1257
1258 @override
1259 ClassEntity getSuperClass(ClassEntity cls) {
1260 return elementMap._getSuperType(cls)?.element;
1261 }
1262
1263 @override
1264 bool implementsFunction(ClassEntity cls) {
1265 // TODO(johnniwinther): Implement this.
1266 return false;
1267 }
1268
1269 @override
1270 int getHierarchyDepth(ClassEntity cls) {
1271 return elementMap._getHierarchyDepth(cls);
1272 }
1273
1274 @override
1275 ClassEntity getAppliedMixin(ClassEntity cls) {
1276 // TODO(johnniwinther): Implement this.
1277 return null;
1278 }
1279
1280 @override
1281 bool validateClass(ClassEntity cls) => true;
1282
1283 @override
1284 bool checkClass(ClassEntity cls) => true;
1285 }
1286
1287 // Interface for testing equivalence of Kernel-based entities.
1288 class WorldDeconstructionForTesting {
1289 final KernelToElementMap elementMap;
1290
1291 WorldDeconstructionForTesting(this.elementMap);
1292
1293 KClass getSuperclassForClass(KClass cls) {
1294 _KClassEnv env = elementMap._classEnvs[cls.classIndex];
1295 ir.Supertype supertype = env.cls.supertype;
1296 if (supertype == null) return null;
1297 return elementMap.getClass(supertype.classNode);
1298 }
1299
1300 bool isUnnamedMixinApplication(KClass cls) {
1301 return elementMap._isUnnamedMixinApplication(cls);
1302 }
1303
1304 InterfaceType getMixinTypeForClass(KClass cls) {
1305 _KClassEnv env = elementMap._classEnvs[cls.classIndex];
1306 ir.Supertype mixedInType = env.cls.mixedInType;
1307 if (mixedInType == null) return null;
1308 return elementMap.createInterfaceType(
1309 mixedInType.classNode, mixedInType.typeArguments);
1310 }
1311 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/kernel/element_adapter.dart ('k') | pkg/compiler/lib/src/kernel/element_map_impl.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698