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

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

Issue 2663793002: Extract reusable parts of KernelAstAdapter in a mixin. (Closed)
Patch Set: Created 3 years, 10 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
« no previous file with comments | « no previous file | pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 import 'package:kernel/ast.dart' as ir; 5 import 'package:kernel/ast.dart' as ir;
6 6
7 import '../common.dart';
8 import '../common/names.dart';
9 import '../core_types.dart';
7 import '../elements/elements.dart'; 10 import '../elements/elements.dart';
8 import '../elements/entities.dart'; 11 import '../elements/entities.dart';
9 import '../elements/types.dart'; 12 import '../elements/types.dart';
13 import '../js_backend/backend_helpers.dart';
10 import '../native/native.dart' as native; 14 import '../native/native.dart' as native;
11 import '../universe/call_structure.dart'; 15 import '../universe/call_structure.dart';
12 import '../universe/selector.dart'; 16 import '../universe/selector.dart';
13 17
14 /// Interface that translates between Kernel IR nodes and entities. 18 /// Interface that translates between Kernel IR nodes and entities.
15 abstract class KernelElementAdapter { 19 abstract class KernelElementAdapter {
20 /// Access to the commonly used elements and types.
21 CommonElements get commonElements;
22
16 /// Returns the [DartType] corresponding to [type]. 23 /// Returns the [DartType] corresponding to [type].
17 DartType getDartType(ir.DartType type); 24 DartType getDartType(ir.DartType type);
18 25
19 /// Returns the list of [DartType]s corresponding to [types]. 26 /// Returns the list of [DartType]s corresponding to [types].
20 List<DartType> getDartTypes(List<ir.DartType> types); 27 List<DartType> getDartTypes(List<ir.DartType> types);
21 28
22 /// Returns the [InterfaceType] corresponding to [type]. 29 /// Returns the [InterfaceType] corresponding to [type].
23 InterfaceType getInterfaceType(ir.InterfaceType type); 30 InterfaceType getInterfaceType(ir.InterfaceType type);
24 31
25 /// Return the [InterfaceType] corresponding to the [cls] with the given 32 /// Return the [InterfaceType] corresponding to the [cls] with the given
(...skipping 19 matching lines...) Expand all
45 FunctionEntity getMethod(ir.Procedure node); 52 FunctionEntity getMethod(ir.Procedure node);
46 53
47 /// Returns the [FieldEntity] corresponding to the field [node]. 54 /// Returns the [FieldEntity] corresponding to the field [node].
48 FieldEntity getField(ir.Field node); 55 FieldEntity getField(ir.Field node);
49 56
50 /// Returns the [ClassEntity] corresponding to the class [node]. 57 /// Returns the [ClassEntity] corresponding to the class [node].
51 ClassEntity getClass(ir.Class node); 58 ClassEntity getClass(ir.Class node);
52 59
53 /// Returns the [Local] corresponding to the [node]. The node must be either 60 /// Returns the [Local] corresponding to the [node]. The node must be either
54 /// a [ir.FunctionDeclaration] or [ir.FunctionExpression]. 61 /// a [ir.FunctionDeclaration] or [ir.FunctionExpression].
55 Local getLocalFunction(ir.Node node); 62 Local getLocalFunction(ir.TreeNode node);
56 63
57 /// Returns the [LibraryEntity] corresponding to the library [node]. 64 /// Returns the [LibraryEntity] corresponding to the library [node].
58 LibraryEntity getLibrary(ir.Library node); 65 LibraryEntity getLibrary(ir.Library node);
59 66
60 /// Returns the [Name] corresponding to [name]. 67 /// Returns the [Name] corresponding to [name].
61 Name getName(ir.Name name); 68 Name getName(ir.Name name);
62 69
63 /// Returns `true` is [node] has a `@Native(...)` annotation. 70 /// Returns `true` is [node] has a `@Native(...)` annotation.
64 bool isNativeClass(ir.Class node); 71 bool isNativeClass(ir.Class node);
65 72
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 } 104 }
98 105
99 /// Kinds of foreign functions. 106 /// Kinds of foreign functions.
100 enum ForeignKind { 107 enum ForeignKind {
101 JS, 108 JS,
102 JS_BUILTIN, 109 JS_BUILTIN,
103 JS_EMBEDDED_GLOBAL, 110 JS_EMBEDDED_GLOBAL,
104 JS_INTERCEPTOR_CONSTANT, 111 JS_INTERCEPTOR_CONSTANT,
105 NONE, 112 NONE,
106 } 113 }
114
115 abstract class KernelElementAdapterMixin implements KernelElementAdapter {
116 DiagnosticReporter get reporter;
117 CommonElements get commonElements;
118
119 LibraryEntity lookupLibrary(Uri uri);
120 ClassEntity lookupClass(LibraryEntity library, String name);
121 InterfaceType getRawType(ClassEntity cls);
122 InterfaceType getThisType(ClassEntity cls);
123
124 @override
125 Name getName(ir.Name name) {
126 return new Name(
127 name.name, name.isPrivate ? getLibrary(name.library) : null);
128 }
129
130 @override
131 CallStructure getCallStructure(ir.Arguments arguments) {
132 int argumentCount = arguments.positional.length + arguments.named.length;
133 List<String> namedArguments = arguments.named.map((e) => e.name).toList();
134 return new CallStructure(argumentCount, namedArguments);
135 }
136
137 @override
138 Selector getSelector(ir.Expression node) {
139 if (node is ir.PropertyGet) return getGetterSelector(node);
140 if (node is ir.PropertySet) return getSetterSelector(node);
141 if (node is ir.InvocationExpression) return getInvocationSelector(node);
142 throw new SpannableAssertionFailure(CURRENT_ELEMENT_SPANNABLE,
143 "Can only get the selector for a property get or an invocation: ${node}" );
Johnni Winther 2017/01/30 14:40:00 Fixed in later CL (dartfmt doesn't handle this)
144 }
145
146 Selector getInvocationSelector(ir.InvocationExpression invocation) {
147 Name name = getName(invocation.name);
148 SelectorKind kind;
149 if (Elements.isOperatorName(invocation.name.name)) {
150 if (name == Names.INDEX_NAME || name == Names.INDEX_SET_NAME) {
151 kind = SelectorKind.INDEX;
152 } else {
153 kind = SelectorKind.OPERATOR;
154 }
155 } else {
156 kind = SelectorKind.CALL;
157 }
158
159 CallStructure callStructure = getCallStructure(invocation.arguments);
160 return new Selector(kind, name, callStructure);
161 }
162
163 Selector getGetterSelector(ir.PropertyGet getter) {
164 ir.Name irName = getter.name;
165 Name name = new Name(
166 irName.name, irName.isPrivate ? getLibrary(irName.library) : null);
167 return new Selector.getter(name);
168 }
169
170 Selector getSetterSelector(ir.PropertySet setter) {
171 ir.Name irName = setter.name;
172 Name name = new Name(
173 irName.name, irName.isPrivate ? getLibrary(irName.library) : null);
174 return new Selector.setter(name);
175 }
176
177 /// Returns `true` is [node] has a `@Native(...)` annotation.
178 // TODO(johnniwinther): Cache this for later use.
179 bool isNativeClass(ir.Class node) {
180 for (ir.Expression annotation in node.annotations) {
181 if (annotation is ir.ConstructorInvocation) {
182 FunctionEntity target = getConstructor(annotation.target);
183 if (target.enclosingClass == commonElements.nativeAnnotationClass) {
184 return true;
185 }
186 }
187 }
188 return false;
189 }
190
191 /// Compute the kind of foreign helper function called by [node], if any.
192 ForeignKind getForeignKind(ir.StaticInvocation node) {
193 if (isForeignLibrary(node.target.enclosingLibrary)) {
194 switch (node.target.name.name) {
195 case BackendHelpers.JS:
196 return ForeignKind.JS;
197 case BackendHelpers.JS_BUILTIN:
198 return ForeignKind.JS_BUILTIN;
199 case BackendHelpers.JS_EMBEDDED_GLOBAL:
200 return ForeignKind.JS_EMBEDDED_GLOBAL;
201 case BackendHelpers.JS_INTERCEPTOR_CONSTANT:
202 return ForeignKind.JS_INTERCEPTOR_CONSTANT;
203 }
204 }
205 return ForeignKind.NONE;
206 }
207
208 /// Return `true` if [node] is the `dart:_foreign_helper` library.
209 bool isForeignLibrary(ir.Library node) {
210 return node.importUri == BackendHelpers.DART_FOREIGN_HELPER;
211 }
212
213 /// Looks up [typeName] for use in the spec-string of a `JS` called.
214 // TODO(johnniwinther): Use this in [native.NativeBehavior] instead of calling
215 // the `ForeignResolver`.
216 // TODO(johnniwinther): Cache the result to avoid redundant lookups?
217 native.TypeLookup typeLookup({bool resolveAsRaw: true}) {
218 return (String typeName) {
219 DartType findIn(Uri uri) {
220 LibraryEntity library = lookupLibrary(uri);
221 if (library != null) {
222 ClassEntity cls = lookupClass(library, typeName);
223 if (cls != null) {
224 // TODO(johnniwinther): Align semantics.
225 return resolveAsRaw ? getRawType(cls) : getThisType(cls);
226 }
227 }
228 return null;
229 }
230
231 DartType type = findIn(Uris.dart_core);
232 type ??= findIn(BackendHelpers.DART_JS_HELPER);
233 type ??= findIn(BackendHelpers.DART_INTERCEPTORS);
234 type ??= findIn(BackendHelpers.DART_ISOLATE_HELPER);
235 type ??= findIn(Uris.dart_collection);
236 type ??= findIn(Uris.dart_html);
237 type ??= findIn(Uris.dart_svg);
238 type ??= findIn(Uris.dart_web_audio);
239 type ??= findIn(Uris.dart_web_gl);
240 return type;
241 };
242 }
243
244 String _getStringArgument(ir.StaticInvocation node, int index) {
245 return node.arguments.positional[index].accept(new Stringifier());
246 }
247
248 /// Computes the [native.NativeBehavior] for a call to the [JS] function.
249 // TODO(johnniwinther): Cache this for later use.
250 native.NativeBehavior getNativeBehaviorForJsCall(ir.StaticInvocation node) {
251 if (node.arguments.positional.length < 2 ||
252 node.arguments.named.isNotEmpty) {
253 reporter.reportErrorMessage(
254 CURRENT_ELEMENT_SPANNABLE, MessageKind.WRONG_ARGUMENT_FOR_JS);
255 return new native.NativeBehavior();
256 }
257 String specString = _getStringArgument(node, 0);
258 if (specString == null) {
259 reporter.reportErrorMessage(
260 CURRENT_ELEMENT_SPANNABLE, MessageKind.WRONG_ARGUMENT_FOR_JS_FIRST);
261 return new native.NativeBehavior();
262 }
263
264 String codeString = _getStringArgument(node, 1);
265 if (codeString == null) {
266 reporter.reportErrorMessage(
267 CURRENT_ELEMENT_SPANNABLE, MessageKind.WRONG_ARGUMENT_FOR_JS_SECOND);
268 return new native.NativeBehavior();
269 }
270
271 return native.NativeBehavior.ofJsCall(
272 specString,
273 codeString,
274 typeLookup(resolveAsRaw: true),
275 CURRENT_ELEMENT_SPANNABLE,
276 reporter,
277 commonElements);
278 }
279
280 /// Computes the [native.NativeBehavior] for a call to the [JS_BUILTIN]
281 /// function.
282 // TODO(johnniwinther): Cache this for later use.
283 native.NativeBehavior getNativeBehaviorForJsBuiltinCall(
284 ir.StaticInvocation node) {
285 if (node.arguments.positional.length < 1) {
286 reporter.internalError(
287 CURRENT_ELEMENT_SPANNABLE, "JS builtin expression has no type.");
288 return new native.NativeBehavior();
289 }
290 if (node.arguments.positional.length < 2) {
291 reporter.internalError(
292 CURRENT_ELEMENT_SPANNABLE, "JS builtin is missing name.");
293 return new native.NativeBehavior();
294 }
295 String specString = _getStringArgument(node, 0);
296 if (specString == null) {
297 reporter.internalError(
298 CURRENT_ELEMENT_SPANNABLE, "Unexpected first argument.");
299 return new native.NativeBehavior();
300 }
301 return native.NativeBehavior.ofJsBuiltinCall(
302 specString,
303 typeLookup(resolveAsRaw: true),
304 CURRENT_ELEMENT_SPANNABLE,
305 reporter,
306 commonElements);
307 }
308
309 /// Computes the [native.NativeBehavior] for a call to the
310 /// [JS_EMBEDDED_GLOBAL] function.
311 // TODO(johnniwinther): Cache this for later use.
312 native.NativeBehavior getNativeBehaviorForJsEmbeddedGlobalCall(
313 ir.StaticInvocation node) {
314 if (node.arguments.positional.length < 1) {
315 reporter.internalError(CURRENT_ELEMENT_SPANNABLE,
316 "JS embedded global expression has no type.");
317 return new native.NativeBehavior();
318 }
319 if (node.arguments.positional.length < 2) {
320 reporter.internalError(
321 CURRENT_ELEMENT_SPANNABLE, "JS embedded global is missing name.");
322 return new native.NativeBehavior();
323 }
324 if (node.arguments.positional.length > 2 ||
325 node.arguments.named.isNotEmpty) {
326 reporter.internalError(CURRENT_ELEMENT_SPANNABLE,
327 "JS embedded global has more than 2 arguments.");
328 return new native.NativeBehavior();
329 }
330 String specString = _getStringArgument(node, 0);
331 if (specString == null) {
332 reporter.internalError(
333 CURRENT_ELEMENT_SPANNABLE, "Unexpected first argument.");
334 return new native.NativeBehavior();
335 }
336 return native.NativeBehavior.ofJsEmbeddedGlobalCall(
337 specString,
338 typeLookup(resolveAsRaw: true),
339 CURRENT_ELEMENT_SPANNABLE,
340 reporter,
341 commonElements);
342 }
343
344 /// Computes the [InterfaceType] referenced by a call to the
345 /// [JS_INTERCEPTOR_CONSTANT] function, if any.
346 InterfaceType getInterfaceTypeForJsInterceptorCall(ir.StaticInvocation node) {
347 if (node.arguments.positional.length != 1 ||
348 node.arguments.named.isNotEmpty) {
349 reporter.reportErrorMessage(CURRENT_ELEMENT_SPANNABLE,
350 MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT);
351 }
352 ir.Node argument = node.arguments.positional.first;
353 if (argument is ir.TypeLiteral && argument.type is ir.InterfaceType) {
354 return getInterfaceType(argument.type);
355 }
356 return null;
357 }
358 }
359
360 /// Visitor that converts string literals and concatenations of string literals
361 /// into the string value.
362 class Stringifier extends ir.ExpressionVisitor<String> {
363 @override
364 String visitStringLiteral(ir.StringLiteral node) => node.value;
365
366 @override
367 String visitStringConcatenation(ir.StringConcatenation node) {
368 StringBuffer sb = new StringBuffer();
369 for (ir.Expression expression in node.expressions) {
370 String value = expression.accept(this);
371 if (value == null) return null;
372 sb.write(value);
373 }
374 return sb.toString();
375 }
376 }
OLDNEW
« no previous file with comments | « no previous file | pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698