OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 | |
5 // IrNodes are kept in a separate library to have precise control over their | |
6 // dependencies on other parts of the system. | |
7 library dart2js.ir_nodes; | 4 library dart2js.ir_nodes; |
8 | 5 |
9 import '../constants/expressions.dart'; | 6 import '../constants/expressions.dart'; |
10 import '../constants/values.dart' as values show ConstantValue; | 7 import '../constants/values.dart' as values show ConstantValue; |
11 import '../dart_types.dart' show DartType, GenericType, TypeVariableType; | 8 import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType; |
12 import '../dart2jslib.dart' as dart2js show | |
13 CURRENT_ELEMENT_SPANNABLE, | |
14 InternalErrorFunction, | |
15 invariant; | |
16 import '../elements/elements.dart'; | 9 import '../elements/elements.dart'; |
17 import '../io/source_information.dart' show SourceInformation; | 10 import '../io/source_information.dart' show SourceInformation; |
18 import '../universe/universe.dart' show Selector, SelectorKind; | 11 import '../universe/universe.dart' show Selector, SelectorKind; |
19 | 12 |
20 abstract class Node { | 13 abstract class Node { |
21 /// A pointer to the parent node. Is null until set by optimization passes. | 14 /// A pointer to the parent node. Is null until set by optimization passes. |
22 Node parent; | 15 Node parent; |
23 | 16 |
24 accept(Visitor visitor); | 17 accept(Visitor visitor); |
25 } | 18 } |
26 | 19 |
| 20 /// Expressions can be evaluated, and may diverge, throw, and/or have |
| 21 /// side-effects. |
| 22 /// |
| 23 /// Evaluation continues by stepping into a sub-expression, invoking a |
| 24 /// continuation, or throwing an exception. |
| 25 /// |
| 26 /// Expressions do not a return value. Expressions that produce values should |
| 27 /// invoke a [Continuation] with the result as argument. Alternatively, values |
| 28 /// that can be obtained without side-effects, divergence, or throwing |
| 29 /// exceptions can be built using a [LetPrim]. |
27 abstract class Expression extends Node { | 30 abstract class Expression extends Node { |
28 Expression plug(Expression expr) => throw 'impossible'; | 31 Expression plug(Expression expr) => throw 'impossible'; |
29 } | 32 } |
30 | 33 |
31 /// The base class of things that variables can refer to: primitives, | 34 /// The base class of things that variables can refer to: primitives, |
32 /// continuations, function and continuation parameters, etc. | 35 /// continuations, function and continuation parameters, etc. |
33 abstract class Definition<T extends Definition<T>> extends Node { | 36 abstract class Definition<T extends Definition<T>> extends Node { |
34 // The head of a linked-list of occurrences, in no particular order. | 37 // The head of a linked-list of occurrences, in no particular order. |
35 Reference<T> firstRef; | 38 Reference<T> firstRef; |
36 | 39 |
(...skipping 15 matching lines...) Expand all Loading... |
52 previous.next = firstRef; | 55 previous.next = firstRef; |
53 if (firstRef != null) firstRef.previous = previous; | 56 if (firstRef != null) firstRef.previous = previous; |
54 firstRef = other.firstRef; | 57 firstRef = other.firstRef; |
55 other.firstRef = null; | 58 other.firstRef = null; |
56 } | 59 } |
57 } | 60 } |
58 | 61 |
59 /// An expression that cannot throw or diverge and has no side-effects. | 62 /// An expression that cannot throw or diverge and has no side-effects. |
60 /// All primitives are named using the identity of the [Primitive] object. | 63 /// All primitives are named using the identity of the [Primitive] object. |
61 /// | 64 /// |
62 /// Primitives may allocate objects, this is not considered side-effect here. | 65 /// Primitives may allocate objects; this is not considered side-effect here. |
63 /// | 66 /// |
64 /// Although primitives may not mutate state, they may depend on state. | 67 /// Although primitives may not mutate state, they may depend on state. |
| 68 /// |
| 69 /// All primitives except [Parameter] must be bound by a [LetPrim]. |
65 abstract class Primitive extends Definition<Primitive> { | 70 abstract class Primitive extends Definition<Primitive> { |
66 /// The [VariableElement] or [ParameterElement] from which the primitive | 71 /// The [VariableElement] or [ParameterElement] from which the primitive |
67 /// binding originated. | 72 /// binding originated. |
68 Entity hint; | 73 Entity hint; |
69 | 74 |
70 /// Use the given element as a hint for naming this primitive. | 75 /// Use the given element as a hint for naming this primitive. |
71 /// | 76 /// |
72 /// Has no effect if this primitive already has a non-null [element]. | 77 /// Has no effect if this primitive already has a non-null [element]. |
73 void useElementAsHint(Entity hint) { | 78 void useElementAsHint(Entity hint) { |
74 if (this.hint == null) { | 79 if (this.hint == null) { |
(...skipping 23 matching lines...) Expand all Loading... |
98 if (previous == null) { | 103 if (previous == null) { |
99 assert(definition.firstRef == this); | 104 assert(definition.firstRef == this); |
100 definition.firstRef = next; | 105 definition.firstRef = next; |
101 } else { | 106 } else { |
102 previous.next = next; | 107 previous.next = next; |
103 } | 108 } |
104 if (next != null) next.previous = previous; | 109 if (next != null) next.previous = previous; |
105 } | 110 } |
106 } | 111 } |
107 | 112 |
108 /// Binding a value (primitive or constant): 'let val x = V in E'. The bound | 113 /// Evaluates a primitive and binds it to variable: `let val x = V in E`. |
109 /// value is in scope in the body. | 114 /// |
110 /// During one-pass construction a LetVal with an empty body is used to | 115 /// The bound value is in scope in the body. |
111 /// represent the one-hole context 'let val x = V in []'. | 116 /// |
| 117 /// During one-pass construction a LetPrim with an empty body is used to |
| 118 /// represent the one-hole context `let val x = V in []`. |
112 class LetPrim extends Expression implements InteriorNode { | 119 class LetPrim extends Expression implements InteriorNode { |
113 final Primitive primitive; | 120 final Primitive primitive; |
114 Expression body; | 121 Expression body; |
115 | 122 |
116 LetPrim(this.primitive, [this.body = null]); | 123 LetPrim(this.primitive, [this.body = null]); |
117 | 124 |
118 Expression plug(Expression expr) { | 125 Expression plug(Expression expr) { |
119 assert(body == null); | 126 assert(body == null); |
120 return body = expr; | 127 return body = expr; |
121 } | 128 } |
122 | 129 |
123 accept(Visitor visitor) => visitor.visitLetPrim(this); | 130 accept(Visitor visitor) => visitor.visitLetPrim(this); |
124 } | 131 } |
125 | 132 |
126 | 133 |
127 /// Binding continuations. | 134 /// Binding continuations. |
128 /// | 135 /// |
129 /// let cont k0(v0 ...) = E0 | 136 /// let cont k0(v0 ...) = E0 |
130 /// k1(v1 ...) = E1 | 137 /// k1(v1 ...) = E1 |
131 /// ... | 138 /// ... |
132 /// in E | 139 /// in E |
133 /// | 140 /// |
134 /// The bound continuations are in scope in the body and the continuation | 141 /// The bound continuations are in scope in the body and the continuation |
135 /// parameters are in scope in the respective continuation bodies. | 142 /// parameters are in scope in the respective continuation bodies. |
| 143 /// |
136 /// During one-pass construction a LetCont whose first continuation has an empty | 144 /// During one-pass construction a LetCont whose first continuation has an empty |
137 /// body is used to represent the one-hole context | 145 /// body is used to represent the one-hole context |
138 /// 'let cont ... k(v) = [] ... in E'. | 146 /// `let cont ... k(v) = [] ... in E`. |
139 class LetCont extends Expression implements InteriorNode { | 147 class LetCont extends Expression implements InteriorNode { |
140 List<Continuation> continuations; | 148 List<Continuation> continuations; |
141 Expression body; | 149 Expression body; |
142 | 150 |
143 LetCont(Continuation continuation, this.body) | 151 LetCont(Continuation continuation, this.body) |
144 : continuations = <Continuation>[continuation]; | 152 : continuations = <Continuation>[continuation]; |
145 | 153 |
146 LetCont.many(this.continuations, this.body); | 154 LetCont.many(this.continuations, this.body); |
147 | 155 |
148 Expression plug(Expression expr) { | 156 Expression plug(Expression expr) { |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
208 /// Node child = node.body; | 216 /// Node child = node.body; |
209 /// InteriorNode parent = node.parent; | 217 /// InteriorNode parent = node.parent; |
210 /// | 218 /// |
211 /// child.parent = parent; | 219 /// child.parent = parent; |
212 /// parent.body = child; | 220 /// parent.body = child; |
213 abstract class InteriorNode extends Node { | 221 abstract class InteriorNode extends Node { |
214 Expression get body; | 222 Expression get body; |
215 void set body(Expression body); | 223 void set body(Expression body); |
216 } | 224 } |
217 | 225 |
218 /// Invoke a static function or static getter/setter. | 226 /// Invoke a static function. |
| 227 /// |
| 228 /// All optional arguments declared by [target] are passed in explicitly, and |
| 229 /// occur at the end of [arguments] list, in normalized order. |
| 230 /// |
| 231 /// Discussion: |
| 232 /// All information in the [selector] is technically redundant; it will likely |
| 233 /// be removed. |
219 class InvokeStatic extends Expression implements Invoke { | 234 class InvokeStatic extends Expression implements Invoke { |
220 /// [FunctionElement] or [FieldElement]. | 235 final FunctionElement target; |
221 final Entity target; | |
222 | |
223 /** | |
224 * The selector encodes how the function is invoked: number of positional | |
225 * arguments, names used in named arguments. This information is required | |
226 * to build the [StaticCallSiteTypeInformation] for the inference graph. | |
227 */ | |
228 final Selector selector; | 236 final Selector selector; |
229 | |
230 final List<Reference<Primitive>> arguments; | 237 final List<Reference<Primitive>> arguments; |
231 final Reference<Continuation> continuation; | 238 final Reference<Continuation> continuation; |
232 final SourceInformation sourceInformation; | 239 final SourceInformation sourceInformation; |
233 | 240 |
234 InvokeStatic(this.target, | 241 InvokeStatic(this.target, |
235 this.selector, | 242 this.selector, |
236 List<Primitive> args, | 243 List<Primitive> args, |
237 Continuation cont, | 244 Continuation cont, |
238 this.sourceInformation) | 245 this.sourceInformation) |
239 : arguments = _referenceList(args), | 246 : arguments = _referenceList(args), |
240 continuation = new Reference<Continuation>(cont) { | 247 continuation = new Reference<Continuation>(cont); |
241 assert(target is ErroneousElement || selector.name == target.name); | |
242 } | |
243 | 248 |
244 accept(Visitor visitor) => visitor.visitInvokeStatic(this); | 249 accept(Visitor visitor) => visitor.visitInvokeStatic(this); |
245 } | 250 } |
246 | 251 |
247 /// A [CallingConvention] codifies how arguments are matched to parameters when | 252 /// Invoke a method on an object. |
248 /// emitting code for a function call. | 253 /// |
249 class CallingConvention { | 254 /// This includes getters, setters, operators, and index getter/setters. |
250 final String name; | 255 /// |
251 const CallingConvention(this.name); | 256 /// Tearing off a method is treated like a getter invocation (getters and |
252 /// The normal way of calling a Dart function: Positional arguments are | 257 /// tear-offs cannot be distinguished at compile-time). |
253 /// matched with (mandatory and optional) positionals parameters from left to | 258 /// |
254 /// right and named arguments are matched by name. | 259 /// The [selector] records the names of named arguments. The value of named |
255 static const CallingConvention DART = const CallingConvention("Dart call"); | 260 /// arguments occur at the end of the [arguments] list, in normalized order. |
256 /// Intercepted calls have an additional first argument that is the actual | 261 /// |
257 /// receiver of the call. See the documentation of [Interceptor] for more | 262 /// Discussion: |
258 /// information. | 263 /// If the [selector] is a [TypedSelector], the type information contained |
259 static const CallingConvention JS_INTERCEPTED = | 264 /// there is used by optimization passes. This is likely to change. |
260 const CallingConvention("intercepted JavaScript call"); | |
261 } | |
262 | |
263 /// Invoke a method, operator, getter, setter, or index getter/setter. | |
264 /// Converting a method to a function object is treated as a getter invocation. | |
265 class InvokeMethod extends Expression implements Invoke { | 265 class InvokeMethod extends Expression implements Invoke { |
266 Reference<Primitive> receiver; | 266 Reference<Primitive> receiver; |
267 Selector selector; | 267 Selector selector; |
268 CallingConvention callingConvention; | |
269 final List<Reference<Primitive>> arguments; | 268 final List<Reference<Primitive>> arguments; |
270 final Reference<Continuation> continuation; | 269 final Reference<Continuation> continuation; |
271 final SourceInformation sourceInformation; | 270 final SourceInformation sourceInformation; |
272 | 271 |
273 InvokeMethod(Primitive receiver, | 272 InvokeMethod(Primitive receiver, |
274 Selector selector, | 273 this.selector, |
275 List<Primitive> arguments, | 274 List<Primitive> arguments, |
276 Continuation continuation, | 275 Continuation continuation, |
277 {SourceInformation sourceInformation}) | 276 {this.sourceInformation}) |
278 : this.internal(new Reference<Primitive>(receiver), | 277 : this.receiver = new Reference<Primitive>(receiver), |
279 selector, | 278 this.arguments = _referenceList(arguments), |
280 _referenceList(arguments), | 279 this.continuation = new Reference<Continuation>(continuation); |
281 new Reference<Continuation>(continuation), | |
282 sourceInformation); | |
283 | |
284 InvokeMethod.internal(this.receiver, | |
285 this.selector, | |
286 this.arguments, | |
287 this.continuation, | |
288 this.sourceInformation, | |
289 [this.callingConvention = CallingConvention.DART]) { | |
290 assert(isValid); | |
291 } | |
292 | |
293 /// Returns whether the arguments match the selector under the given calling | |
294 /// convention. | |
295 /// | |
296 /// This check is designed to be used in an assert, as it also checks that the | |
297 /// selector, arguments, and calling convention have meaningful values. | |
298 bool get isValid { | |
299 if (selector == null || callingConvention == null) return false; | |
300 if (callingConvention != CallingConvention.DART && | |
301 callingConvention != CallingConvention.JS_INTERCEPTED) { | |
302 return false; | |
303 } | |
304 int numberOfArguments = | |
305 callingConvention == CallingConvention.JS_INTERCEPTED | |
306 ? arguments.length - 1 | |
307 : arguments.length; | |
308 return selector.kind == SelectorKind.CALL || | |
309 selector.kind == SelectorKind.OPERATOR || | |
310 (selector.kind == SelectorKind.GETTER && numberOfArguments == 0) || | |
311 (selector.kind == SelectorKind.SETTER && numberOfArguments == 1) || | |
312 (selector.kind == SelectorKind.INDEX && numberOfArguments == 1) || | |
313 (selector.kind == SelectorKind.INDEX && numberOfArguments == 2); | |
314 } | |
315 | 280 |
316 accept(Visitor visitor) => visitor.visitInvokeMethod(this); | 281 accept(Visitor visitor) => visitor.visitInvokeMethod(this); |
317 } | 282 } |
318 | 283 |
319 /// Invoke [target] on [receiver], bypassing dispatch and override semantics. | 284 /// Invoke [target] on [receiver], bypassing dispatch and override semantics. |
320 /// | 285 /// |
321 /// That is, if [receiver] is an instance of a class that overrides [target] | 286 /// That is, if [receiver] is an instance of a class that overrides [target] |
322 /// with a different implementation, the overriding implementation is bypassed | 287 /// with a different implementation, the overriding implementation is bypassed |
323 /// and [target]'s implementation is invoked. | 288 /// and [target]'s implementation is invoked. |
324 /// | 289 /// |
325 /// As with [InvokeMethod], this can be used to invoke a method, operator, | 290 /// As with [InvokeMethod], this can be used to invoke a method, operator, |
326 /// getter, setter, or index getter/setter. | 291 /// getter, setter, or index getter/setter. |
327 /// | 292 /// |
328 /// If it is known that [target] does not use its receiver argument, then | 293 /// If it is known that [target] does not use its receiver argument, then |
329 /// [receiver] may refer to a null constant primitive. This happens for direct | 294 /// [receiver] may refer to a null constant primitive. This happens for direct |
330 /// invocations to intercepted methods, where the effective receiver is instead | 295 /// invocations to intercepted methods, where the effective receiver is instead |
331 /// passed as a formal parameter. | 296 /// passed as a formal parameter. |
332 /// | 297 /// |
333 /// TODO(sra): Review. A direct call to a method that is mixed into a native | 298 /// TODO(sra): Review. A direct call to a method that is mixed into a native |
334 /// class will still require an explicit argument. | 299 /// class will still require an explicit argument. |
335 /// | 300 /// |
336 /// When targeting Dart, this instruction is used to represent super calls. | 301 /// All optional arguments declared by [target] are passed in explicitly, and |
337 /// Here, [receiver] must always be a reference to `this`, and [target] must be | 302 /// occur at the end of [arguments] list, in normalized order. |
338 /// a method that is available in the super class. | |
339 class InvokeMethodDirectly extends Expression implements Invoke { | 303 class InvokeMethodDirectly extends Expression implements Invoke { |
340 Reference<Primitive> receiver; | 304 Reference<Primitive> receiver; |
341 final Element target; | 305 final FunctionElement target; |
342 final Selector selector; | 306 final Selector selector; |
343 final List<Reference<Primitive>> arguments; | 307 final List<Reference<Primitive>> arguments; |
344 final Reference<Continuation> continuation; | 308 final Reference<Continuation> continuation; |
345 | 309 |
346 InvokeMethodDirectly(Primitive receiver, | 310 InvokeMethodDirectly(Primitive receiver, |
347 this.target, | 311 this.target, |
348 this.selector, | 312 this.selector, |
349 List<Primitive> args, | 313 List<Primitive> arguments, |
350 Continuation cont) | 314 Continuation continuation) |
351 : this.receiver = new Reference<Primitive>(receiver), | 315 : this.receiver = new Reference<Primitive>(receiver), |
352 arguments = _referenceList(args), | 316 this.arguments = _referenceList(arguments), |
353 continuation = new Reference<Continuation>(cont) { | 317 this.continuation = new Reference<Continuation>(continuation); |
354 assert(selector != null); | |
355 assert(selector.kind == SelectorKind.CALL || | |
356 selector.kind == SelectorKind.OPERATOR || | |
357 (selector.kind == SelectorKind.GETTER && arguments.isEmpty) || | |
358 (selector.kind == SelectorKind.SETTER && arguments.length == 1) || | |
359 (selector.kind == SelectorKind.INDEX && arguments.length == 1) || | |
360 (selector.kind == SelectorKind.INDEX && arguments.length == 2)); | |
361 } | |
362 | 318 |
363 accept(Visitor visitor) => visitor.visitInvokeMethodDirectly(this); | 319 accept(Visitor visitor) => visitor.visitInvokeMethodDirectly(this); |
364 } | 320 } |
365 | 321 |
366 /// Non-const call to a constructor. The [target] may be a generative | 322 /// Non-const call to a constructor. |
367 /// constructor, factory, or redirecting factory. | 323 /// |
| 324 /// The [target] may be a generative constructor (forwarding or normal) |
| 325 /// or a non-redirecting factory. |
| 326 /// |
| 327 /// All optional arguments declared by [target] are passed in explicitly, and |
| 328 /// occur in the [arguments] list, in normalized order. |
| 329 /// |
| 330 /// Last in the [arguments] list, after the mandatory and optional arguments, |
| 331 /// the internal representation of each type argument occurs, unless it could |
| 332 /// be determined at build-time that the constructed class has no need for its |
| 333 /// runtime type information. |
| 334 /// |
| 335 /// Note that [InvokeConstructor] does it itself allocate an object. |
| 336 /// The invoked constructor will do that using [CreateInstance]. |
368 class InvokeConstructor extends Expression implements Invoke { | 337 class InvokeConstructor extends Expression implements Invoke { |
369 final DartType type; | 338 final DartType type; |
370 final FunctionElement target; | 339 final ConstructorElement target; |
371 final List<Reference<Primitive>> arguments; | 340 final List<Reference<Primitive>> arguments; |
372 final Reference<Continuation> continuation; | 341 final Reference<Continuation> continuation; |
373 final Selector selector; | 342 final Selector selector; |
374 | 343 |
375 /// The class being instantiated. This is the same as `target.enclosingClass` | |
376 /// and `type.element`. | |
377 ClassElement get targetClass => target.enclosingElement; | |
378 | |
379 /// True if this is an invocation of a factory constructor. | |
380 bool get isFactory => target.isFactoryConstructor; | |
381 | |
382 InvokeConstructor(this.type, | 344 InvokeConstructor(this.type, |
383 this.target, | 345 this.target, |
384 this.selector, | 346 this.selector, |
385 List<Primitive> args, | 347 List<Primitive> args, |
386 Continuation cont) | 348 Continuation cont) |
387 : arguments = _referenceList(args), | 349 : arguments = _referenceList(args), |
388 continuation = new Reference<Continuation>(cont) { | 350 continuation = new Reference<Continuation>(cont); |
389 assert(dart2js.invariant(target, | |
390 target.isErroneous || | |
391 type.isDynamic || | |
392 type.element == target.enclosingClass.declaration, | |
393 message: "Constructor invocation target is not a constructor: " | |
394 "$target.")); | |
395 } | |
396 | 351 |
397 accept(Visitor visitor) => visitor.visitInvokeConstructor(this); | 352 accept(Visitor visitor) => visitor.visitInvokeConstructor(this); |
398 } | 353 } |
399 | 354 |
400 /// "as" casts and "is" checks. | 355 // TODO(asgerf): Make a Primitive for "is" and an Expression for "as". |
401 // We might want to turn "is"-checks into a [Primitive] as it can never diverge. | 356 |
402 // But then we need to special-case for is-checks with an erroneous .type as | 357 /// An "as" cast or an "is" check. |
403 // these will throw. | |
404 class TypeOperator extends Expression { | 358 class TypeOperator extends Expression { |
405 Reference<Primitive> value; | 359 Reference<Primitive> value; |
406 final DartType type; | 360 final DartType type; |
407 | 361 |
408 /// If [type] is a [GenericType], this holds the internal representation of | 362 /// If [type] is an [InterfaceType], this holds the internal representation of |
409 /// the type arguments to [type]. Since these may reference type variables | 363 /// the type arguments to [type]. Since these may reference type variables |
410 /// from the enclosing class, they are not constant. | 364 /// from the enclosing class, they are not constant. |
411 /// | 365 /// |
412 /// If [type] is a [TypeVariableType], this is a singleton list with | 366 /// If [type] is a [TypeVariableType], this is a singleton list with |
413 /// the internal representation of the type held in that type variable. | 367 /// the internal representation of the type held in that type variable. |
414 /// | 368 /// |
415 /// Otherwise the list is empty. | 369 /// Otherwise the list is empty. |
416 final List<Reference<Primitive>> typeArguments; | 370 final List<Reference<Primitive>> typeArguments; |
417 final Reference<Continuation> continuation; | 371 final Reference<Continuation> continuation; |
418 // TODO(johnniwinther): Use `Operator` class to encapsule the operator type. | |
419 final bool isTypeTest; | 372 final bool isTypeTest; |
420 | 373 |
421 TypeOperator(Primitive value, | 374 TypeOperator(Primitive value, |
422 this.type, | 375 this.type, |
423 List<Primitive> typeArguments, | 376 List<Primitive> typeArguments, |
424 Continuation cont, | 377 Continuation cont, |
425 {bool this.isTypeTest}) | 378 {bool this.isTypeTest}) |
426 : this.value = new Reference<Primitive>(value), | 379 : this.value = new Reference<Primitive>(value), |
427 this.typeArguments = _referenceList(typeArguments), | 380 this.typeArguments = _referenceList(typeArguments), |
428 this.continuation = new Reference<Continuation>(cont) { | 381 this.continuation = new Reference<Continuation>(cont) { |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
513 this.value = new Reference<Primitive>(value); | 466 this.value = new Reference<Primitive>(value); |
514 | 467 |
515 accept(Visitor visitor) => visitor.visitSetMutableVariable(this); | 468 accept(Visitor visitor) => visitor.visitSetMutableVariable(this); |
516 | 469 |
517 Expression plug(Expression expr) { | 470 Expression plug(Expression expr) { |
518 assert(body == null); | 471 assert(body == null); |
519 return body = expr; | 472 return body = expr; |
520 } | 473 } |
521 } | 474 } |
522 | 475 |
523 /// Create a potentially recursive function and store it in a [MutableVariable]. | |
524 /// The function can access itself using [GetMutableVariable] on [variable]. | |
525 /// There must not exist a [SetMutableVariable] to [variable]. | |
526 /// | |
527 /// This can be seen as a let rec binding: | |
528 /// | |
529 /// let rec [variable] = [definition] in [body] | |
530 /// | |
531 class DeclareFunction extends Expression | |
532 implements InteriorNode, DartSpecificNode { | |
533 final MutableVariable variable; | |
534 final FunctionDefinition definition; | |
535 Expression body; | |
536 | |
537 DeclareFunction(this.variable, this.definition); | |
538 | |
539 Expression plug(Expression expr) { | |
540 assert(body == null); | |
541 return body = expr; | |
542 } | |
543 | |
544 accept(Visitor visitor) => visitor.visitDeclareFunction(this); | |
545 } | |
546 | |
547 /// Invoke a continuation in tail position. | 476 /// Invoke a continuation in tail position. |
548 class InvokeContinuation extends Expression { | 477 class InvokeContinuation extends Expression { |
549 Reference<Continuation> continuation; | 478 Reference<Continuation> continuation; |
550 List<Reference<Primitive>> arguments; | 479 List<Reference<Primitive>> arguments; |
551 | 480 |
552 // An invocation of a continuation is recursive if it occurs in the body of | 481 // An invocation of a continuation is recursive if it occurs in the body of |
553 // the continuation itself. | 482 // the continuation itself. |
554 bool isRecursive; | 483 bool isRecursive; |
555 | 484 |
556 InvokeContinuation(Continuation cont, List<Primitive> args, | 485 InvokeContinuation(Continuation cont, List<Primitive> args, |
(...skipping 22 matching lines...) Expand all Loading... |
579 | 508 |
580 class IsTrue extends Condition { | 509 class IsTrue extends Condition { |
581 final Reference<Primitive> value; | 510 final Reference<Primitive> value; |
582 | 511 |
583 IsTrue(Primitive val) : value = new Reference<Primitive>(val); | 512 IsTrue(Primitive val) : value = new Reference<Primitive>(val); |
584 | 513 |
585 accept(Visitor visitor) => visitor.visitIsTrue(this); | 514 accept(Visitor visitor) => visitor.visitIsTrue(this); |
586 } | 515 } |
587 | 516 |
588 /// Choose between a pair of continuations based on a condition value. | 517 /// Choose between a pair of continuations based on a condition value. |
| 518 /// |
| 519 /// The two continuations must not declare any parameters. |
589 class Branch extends Expression { | 520 class Branch extends Expression { |
590 final Condition condition; | 521 final Condition condition; |
591 final Reference<Continuation> trueContinuation; | 522 final Reference<Continuation> trueContinuation; |
592 final Reference<Continuation> falseContinuation; | 523 final Reference<Continuation> falseContinuation; |
593 | 524 |
594 Branch(this.condition, Continuation trueCont, Continuation falseCont) | 525 Branch(this.condition, Continuation trueCont, Continuation falseCont) |
595 : trueContinuation = new Reference<Continuation>(trueCont), | 526 : trueContinuation = new Reference<Continuation>(trueCont), |
596 falseContinuation = new Reference<Continuation>(falseCont); | 527 falseContinuation = new Reference<Continuation>(falseCont); |
597 | 528 |
598 accept(Visitor visitor) => visitor.visitBranch(this); | 529 accept(Visitor visitor) => visitor.visitBranch(this); |
599 } | 530 } |
600 | 531 |
601 /// Marker interface for nodes that are only handled in the JavaScript backend. | |
602 /// | |
603 /// These nodes are generated by the unsugar step or the [JsIrBuilder] and need | |
604 /// special translation to the Tree IR, which is implemented in JsTreeBuilder. | |
605 abstract class JsSpecificNode implements Node {} | |
606 | |
607 /// Marker interface for nodes that are only handled inthe Dart backend. | |
608 abstract class DartSpecificNode implements Node {} | |
609 | |
610 /// Directly assigns to a field on a given object. | 532 /// Directly assigns to a field on a given object. |
611 class SetField extends Expression implements InteriorNode, JsSpecificNode { | 533 class SetField extends Expression implements InteriorNode { |
612 final Reference<Primitive> object; | 534 final Reference<Primitive> object; |
613 Element field; | 535 FieldElement field; |
614 final Reference<Primitive> value; | 536 final Reference<Primitive> value; |
615 Expression body; | 537 Expression body; |
616 | 538 |
617 SetField(Primitive object, this.field, Primitive value) | 539 SetField(Primitive object, this.field, Primitive value) |
618 : this.object = new Reference<Primitive>(object), | 540 : this.object = new Reference<Primitive>(object), |
619 this.value = new Reference<Primitive>(value); | 541 this.value = new Reference<Primitive>(value); |
620 | 542 |
621 Expression plug(Expression expr) { | 543 Expression plug(Expression expr) { |
622 assert(body == null); | 544 assert(body == null); |
623 return body = expr; | 545 return body = expr; |
624 } | 546 } |
625 | 547 |
626 accept(Visitor visitor) => visitor.visitSetField(this); | 548 accept(Visitor visitor) => visitor.visitSetField(this); |
627 } | 549 } |
628 | 550 |
629 /// Directly reads from a field on a given object. | 551 /// Directly reads from a field on a given object. |
630 class GetField extends Primitive implements JsSpecificNode { | 552 class GetField extends Primitive { |
631 final Reference<Primitive> object; | 553 final Reference<Primitive> object; |
632 Element field; | 554 FieldElement field; |
633 | 555 |
634 GetField(Primitive object, this.field) | 556 GetField(Primitive object, this.field) |
635 : this.object = new Reference<Primitive>(object); | 557 : this.object = new Reference<Primitive>(object); |
636 | 558 |
637 accept(Visitor visitor) => visitor.visitGetField(this); | 559 accept(Visitor visitor) => visitor.visitGetField(this); |
638 } | 560 } |
639 | 561 |
640 /// Reads the value of a static field or tears off a static method. | 562 /// Reads the value of a static field or tears off a static method. |
641 class GetStatic extends Primitive { | 563 class GetStatic extends Primitive { |
| 564 /// Can be [FieldElement] or [FunctionElement]. |
642 final Element element; | 565 final Element element; |
643 final SourceInformation sourceInformation; | 566 final SourceInformation sourceInformation; |
644 | 567 |
645 GetStatic(this.element, this.sourceInformation); | 568 GetStatic(this.element, this.sourceInformation); |
646 | 569 |
647 accept(Visitor visitor) => visitor.visitGetStatic(this); | 570 accept(Visitor visitor) => visitor.visitGetStatic(this); |
648 } | 571 } |
649 | 572 |
650 /// Sets the value of a static field. | 573 /// Sets the value of a static field. |
651 class SetStatic extends Expression implements InteriorNode { | 574 class SetStatic extends Expression implements InteriorNode { |
652 final Element element; | 575 final FieldElement element; |
653 final Reference<Primitive> value; | 576 final Reference<Primitive> value; |
654 Expression body; | 577 Expression body; |
655 final SourceInformation sourceInformation; | 578 final SourceInformation sourceInformation; |
656 | 579 |
657 SetStatic(this.element, Primitive value, this.sourceInformation) | 580 SetStatic(this.element, Primitive value, this.sourceInformation) |
658 : this.value = new Reference<Primitive>(value); | 581 : this.value = new Reference<Primitive>(value); |
659 | 582 |
660 Expression plug(Expression expr) { | 583 Expression plug(Expression expr) { |
661 assert(body == null); | 584 assert(body == null); |
662 return body = expr; | 585 return body = expr; |
663 } | 586 } |
664 | 587 |
665 accept(Visitor visitor) => visitor.visitSetStatic(this); | 588 accept(Visitor visitor) => visitor.visitSetStatic(this); |
666 } | 589 } |
667 | 590 |
668 /// Reads the value of a lazily initialized static field. | 591 /// Reads the value of a lazily initialized static field. |
669 /// | 592 /// |
670 /// If the field has not yet been initialized, its initializer is evaluated | 593 /// If the field has not yet been initialized, its initializer is evaluated |
671 /// and assigned to the field. | 594 /// and assigned to the field. |
672 /// | 595 /// |
673 /// [continuation] is then invoked with the value of the field as argument. | 596 /// [continuation] is then invoked with the value of the field as argument. |
674 class GetLazyStatic extends Expression { | 597 class GetLazyStatic extends Expression { |
675 final FieldElement element; | 598 final FieldElement element; |
676 final Reference<Continuation> continuation; | 599 final Reference<Continuation> continuation; |
677 final SourceInformation sourceInformation; | 600 final SourceInformation sourceInformation; |
678 | 601 |
679 GetLazyStatic(this.element, | 602 GetLazyStatic(this.element, |
680 Continuation cont, | 603 Continuation continuation, |
681 this.sourceInformation) | 604 this.sourceInformation) |
682 : continuation = new Reference<Continuation>(cont); | 605 : continuation = new Reference<Continuation>(continuation); |
683 | 606 |
684 accept(Visitor visitor) => visitor.visitGetLazyStatic(this); | 607 accept(Visitor visitor) => visitor.visitGetLazyStatic(this); |
685 } | 608 } |
686 | 609 |
687 /// Creates an object for holding boxed variables captured by a closure. | 610 /// Creates an object for holding boxed variables captured by a closure. |
688 class CreateBox extends Primitive implements JsSpecificNode { | 611 class CreateBox extends Primitive { |
689 accept(Visitor visitor) => visitor.visitCreateBox(this); | 612 accept(Visitor visitor) => visitor.visitCreateBox(this); |
690 } | 613 } |
691 | 614 |
692 /// Creates an instance of a class and initializes its fields and runtime type | 615 /// Creates an instance of a class and initializes its fields and runtime type |
693 /// information. | 616 /// information. |
694 class CreateInstance extends Primitive implements JsSpecificNode { | 617 class CreateInstance extends Primitive { |
695 final ClassElement classElement; | 618 final ClassElement classElement; |
696 | 619 |
697 /// Initial values for the fields on the class. | 620 /// Initial values for the fields on the class. |
698 /// The order corresponds to the order of fields on the class. | 621 /// The order corresponds to the order of fields on the class. |
699 final List<Reference<Primitive>> arguments; | 622 final List<Reference<Primitive>> arguments; |
700 | 623 |
701 /// The runtime type information structure which contains the type arguments. | 624 /// The runtime type information structure which contains the type arguments. |
702 /// | 625 /// |
703 /// May be `null` to indicate that no type information is needed because the | 626 /// May be `null` to indicate that no type information is needed because the |
704 /// compiler determined that the type information for instances of this class | 627 /// compiler determined that the type information for instances of this class |
705 /// is not needed at runtime. | 628 /// is not needed at runtime. |
706 final List<Reference<Primitive>> typeInformation; | 629 final List<Reference<Primitive>> typeInformation; |
707 | 630 |
708 CreateInstance(this.classElement, List<Primitive> arguments, | 631 CreateInstance(this.classElement, List<Primitive> arguments, |
709 List<Primitive> typeInformation) | 632 List<Primitive> typeInformation) |
710 : this.arguments = _referenceList(arguments), | 633 : this.arguments = _referenceList(arguments), |
711 this.typeInformation = _referenceList(typeInformation); | 634 this.typeInformation = _referenceList(typeInformation); |
712 | 635 |
713 accept(Visitor visitor) => visitor.visitCreateInstance(this); | 636 accept(Visitor visitor) => visitor.visitCreateInstance(this); |
714 } | 637 } |
715 | 638 |
716 class Identical extends Primitive implements JsSpecificNode { | 639 /// Compare objects for identity. |
| 640 /// |
| 641 /// It is an error pass in a value that does not correspond to a Dart value, |
| 642 /// such as an interceptor or a box. |
| 643 class Identical extends Primitive { |
717 final Reference<Primitive> left; | 644 final Reference<Primitive> left; |
718 final Reference<Primitive> right; | 645 final Reference<Primitive> right; |
719 Identical(Primitive left, Primitive right) | 646 Identical(Primitive left, Primitive right) |
720 : left = new Reference<Primitive>(left), | 647 : left = new Reference<Primitive>(left), |
721 right = new Reference<Primitive>(right); | 648 right = new Reference<Primitive>(right); |
722 accept(Visitor visitor) => visitor.visitIdentical(this); | 649 accept(Visitor visitor) => visitor.visitIdentical(this); |
723 } | 650 } |
724 | 651 |
725 class Interceptor extends Primitive implements JsSpecificNode { | 652 class Interceptor extends Primitive { |
726 final Reference<Primitive> input; | 653 final Reference<Primitive> input; |
727 final Set<ClassElement> interceptedClasses; | 654 final Set<ClassElement> interceptedClasses; |
728 Interceptor(Primitive input, this.interceptedClasses) | 655 Interceptor(Primitive input, this.interceptedClasses) |
729 : this.input = new Reference<Primitive>(input); | 656 : this.input = new Reference<Primitive>(input); |
730 accept(Visitor visitor) => visitor.visitInterceptor(this); | 657 accept(Visitor visitor) => visitor.visitInterceptor(this); |
731 } | 658 } |
732 | 659 |
733 /// Create an instance of [Invocation] for use in a call to `noSuchMethod`. | 660 /// Create an instance of [Invocation] for use in a call to `noSuchMethod`. |
734 class CreateInvocationMirror extends Primitive implements JsSpecificNode { | 661 class CreateInvocationMirror extends Primitive { |
735 final Selector selector; | 662 final Selector selector; |
736 final List<Reference<Primitive>> arguments; | 663 final List<Reference<Primitive>> arguments; |
737 | 664 |
738 CreateInvocationMirror(this.selector, List<Primitive> arguments) | 665 CreateInvocationMirror(this.selector, List<Primitive> arguments) |
739 : this.arguments = _referenceList(arguments); | 666 : this.arguments = _referenceList(arguments); |
740 | 667 |
741 accept(Visitor visitor) => visitor.visitCreateInvocationMirror(this); | 668 accept(Visitor visitor) => visitor.visitCreateInvocationMirror(this); |
742 } | 669 } |
743 | 670 |
744 class Constant extends Primitive { | 671 class Constant extends Primitive { |
745 final ConstantExpression expression; | 672 final ConstantExpression expression; |
746 | 673 |
747 Constant(this.expression); | 674 Constant(this.expression); |
748 | 675 |
749 values.ConstantValue get value => expression.value; | 676 values.ConstantValue get value => expression.value; |
750 | 677 |
751 accept(Visitor visitor) => visitor.visitConstant(this); | 678 accept(Visitor visitor) => visitor.visitConstant(this); |
752 } | 679 } |
753 | 680 |
754 /// Reify the given type variable as a [Type]. | |
755 /// This depends on the current binding of 'this'. | |
756 class ReifyTypeVar extends Primitive implements DartSpecificNode { | |
757 final TypeVariableElement typeVariable; | |
758 | |
759 ReifyTypeVar(this.typeVariable); | |
760 | |
761 values.ConstantValue get constant => null; | |
762 | |
763 accept(Visitor visitor) => visitor.visitReifyTypeVar(this); | |
764 } | |
765 | |
766 class LiteralList extends Primitive { | 681 class LiteralList extends Primitive { |
767 /// The List type being created; this is not the type argument. | 682 /// The List type being created; this is not the type argument. |
768 final GenericType type; | 683 final InterfaceType type; |
769 final List<Reference<Primitive>> values; | 684 final List<Reference<Primitive>> values; |
770 | 685 |
771 LiteralList(this.type, List<Primitive> values) | 686 LiteralList(this.type, List<Primitive> values) |
772 : this.values = _referenceList(values); | 687 : this.values = _referenceList(values); |
773 | 688 |
774 accept(Visitor visitor) => visitor.visitLiteralList(this); | 689 accept(Visitor visitor) => visitor.visitLiteralList(this); |
775 } | 690 } |
776 | 691 |
777 class LiteralMapEntry { | 692 class LiteralMapEntry { |
778 final Reference<Primitive> key; | 693 final Reference<Primitive> key; |
779 final Reference<Primitive> value; | 694 final Reference<Primitive> value; |
780 | 695 |
781 LiteralMapEntry(Primitive key, Primitive value) | 696 LiteralMapEntry(Primitive key, Primitive value) |
782 : this.key = new Reference<Primitive>(key), | 697 : this.key = new Reference<Primitive>(key), |
783 this.value = new Reference<Primitive>(value); | 698 this.value = new Reference<Primitive>(value); |
784 } | 699 } |
785 | 700 |
786 class LiteralMap extends Primitive { | 701 class LiteralMap extends Primitive { |
787 final GenericType type; | 702 final InterfaceType type; |
788 final List<LiteralMapEntry> entries; | 703 final List<LiteralMapEntry> entries; |
789 | 704 |
790 LiteralMap(this.type, this.entries); | 705 LiteralMap(this.type, this.entries); |
791 | 706 |
792 accept(Visitor visitor) => visitor.visitLiteralMap(this); | 707 accept(Visitor visitor) => visitor.visitLiteralMap(this); |
793 } | 708 } |
794 | 709 |
795 /// Create a non-recursive function. | 710 /// Currently unused. |
796 class CreateFunction extends Primitive implements DartSpecificNode { | 711 /// |
| 712 /// Nested functions (from Dart code) are translated to classes by closure |
| 713 /// conversion, hence they are instantiated with [CreateInstance]. |
| 714 /// |
| 715 /// We keep this around for now because it might come in handy when we |
| 716 /// handle async/await in the CPS IR. |
| 717 /// |
| 718 /// Instantiates a nested function. [MutableVariable]s are in scope in the |
| 719 /// inner function, but primitives are not shared across function boundaries. |
| 720 class CreateFunction extends Primitive { |
797 final FunctionDefinition definition; | 721 final FunctionDefinition definition; |
798 | 722 |
799 CreateFunction(this.definition); | 723 CreateFunction(this.definition); |
800 | 724 |
801 accept(Visitor visitor) => visitor.visitCreateFunction(this); | 725 accept(Visitor visitor) => visitor.visitCreateFunction(this); |
802 } | 726 } |
803 | 727 |
804 class Parameter extends Primitive { | 728 class Parameter extends Primitive { |
805 Parameter(Entity hint) { | 729 Parameter(Entity hint) { |
806 super.hint = hint; | 730 super.hint = hint; |
807 } | 731 } |
808 | 732 |
809 // In addition to a parent pointer to the containing Continuation or | 733 // In addition to a parent pointer to the containing Continuation or |
810 // FunctionDefinition, parameters have an index into the list of parameters | 734 // FunctionDefinition, parameters have an index into the list of parameters |
811 // bound by the parent. This gives constant-time access to the continuation | 735 // bound by the parent. This gives constant-time access to the continuation |
812 // from the parent. | 736 // from the parent. |
813 int parentIndex; | 737 int parentIndex; |
814 | 738 |
815 accept(Visitor visitor) => visitor.visitParameter(this); | 739 accept(Visitor visitor) => visitor.visitParameter(this); |
816 | 740 |
817 String toString() => 'Parameter(${hint == null ? null : hint.name})'; | 741 String toString() => 'Parameter(${hint == null ? null : hint.name})'; |
818 } | 742 } |
819 | 743 |
820 /// Continuations are normally bound by 'let cont'. A continuation with one | 744 /// Continuations are normally bound by 'let cont'. A continuation with one |
821 /// parameter and no body is used to represent a function's return continuation. | 745 /// parameter and no body is used to represent a function's return continuation. |
822 /// The return continuation is bound by the Function, not by 'let cont'. | 746 /// The return continuation is bound by the function, not by 'let cont'. |
823 class Continuation extends Definition<Continuation> implements InteriorNode { | 747 class Continuation extends Definition<Continuation> implements InteriorNode { |
824 final List<Parameter> parameters; | 748 final List<Parameter> parameters; |
825 Expression body = null; | 749 Expression body = null; |
826 | 750 |
827 // In addition to a parent pointer to the containing LetCont, continuations | 751 // In addition to a parent pointer to the containing LetCont, continuations |
828 // have an index into the list of continuations bound by the LetCont. This | 752 // have an index into the list of continuations bound by the LetCont. This |
829 // gives constant-time access to the continuation from the parent. | 753 // gives constant-time access to the continuation from the parent. |
830 int parent_index; | 754 int parent_index; |
831 | 755 |
832 // A continuation is recursive if it has any recursive invocations. | 756 // A continuation is recursive if it has any recursive invocations. |
833 bool isRecursive; | 757 bool isRecursive; |
834 | 758 |
835 bool get isReturnContinuation => body == null; | 759 bool get isReturnContinuation => body == null; |
836 | 760 |
837 Continuation(this.parameters, {this.isRecursive: false}); | 761 Continuation(this.parameters, {this.isRecursive: false}); |
838 | 762 |
839 Continuation.retrn() : parameters = <Parameter>[new Parameter(null)]; | 763 Continuation.retrn() : parameters = <Parameter>[new Parameter(null)]; |
840 | 764 |
841 accept(Visitor visitor) => visitor.visitContinuation(this); | 765 accept(Visitor visitor) => visitor.visitContinuation(this); |
842 } | 766 } |
843 | 767 |
844 abstract class RootNode extends Node { | |
845 Element get element; | |
846 | |
847 /// True if there is no body for this root node. | |
848 /// | |
849 /// In some parts of the compiler, empty root nodes are used as placeholders | |
850 /// for abstract methods, external constructors, fields without initializers, | |
851 /// etc. | |
852 bool get isEmpty; | |
853 | |
854 /// List of parameters, or an empty list if this is a field. | |
855 /// For fields, this list is immutable. | |
856 List<Definition> get parameters; | |
857 } | |
858 | |
859 // This is basically a function definition with an empty parameter list and a | |
860 // field element instead of a function element and no const declarations, and | |
861 // never a getter or setter, though that's less important. | |
862 class FieldDefinition extends RootNode implements DartSpecificNode { | |
863 final FieldElement element; | |
864 List<Definition> get parameters => const <Definition>[]; | |
865 final Body body; | |
866 | |
867 FieldDefinition(this.element, this.body); | |
868 | |
869 FieldDefinition.withoutInitializer(this.element) | |
870 : this.body = null; | |
871 | |
872 accept(Visitor visitor) => visitor.visitFieldDefinition(this); | |
873 | |
874 bool get isEmpty => body == null; | |
875 } | |
876 | |
877 /// Identifies a mutable variable. | 768 /// Identifies a mutable variable. |
878 class MutableVariable extends Definition { | 769 class MutableVariable extends Definition { |
879 Entity hint; | 770 Entity hint; |
880 | 771 |
881 MutableVariable(this.hint); | 772 MutableVariable(this.hint); |
882 | 773 |
883 accept(Visitor v) => v.visitMutableVariable(this); | 774 accept(Visitor v) => v.visitMutableVariable(this); |
884 } | 775 } |
885 | 776 |
886 class Body extends InteriorNode { | 777 /// A function definition, consisting of parameters and a body. |
887 Expression body; | 778 /// |
888 final Continuation returnContinuation; | 779 /// There is an explicit parameter for the `this` argument, and a return |
889 Body(this.body, this.returnContinuation); | 780 /// continuation to invoke when returning from the function. |
890 accept(Visitor visitor) => visitor.visitBody(this); | 781 class FunctionDefinition extends InteriorNode { |
891 } | |
892 | |
893 /// A function definition, consisting of parameters and a body. The parameters | |
894 /// include a distinguished continuation parameter (held by the body). | |
895 class FunctionDefinition extends RootNode { | |
896 final ExecutableElement element; | 782 final ExecutableElement element; |
897 final Parameter thisParameter; | 783 final Parameter thisParameter; |
898 /// Mixed list of [Parameter]s and [MutableVariable]s. | 784 final List<Parameter> parameters; |
899 final List<Definition> parameters; | 785 final Continuation returnContinuation; |
900 final Body body; | 786 Expression body; |
901 final List<ConstDeclaration> localConstants; | |
902 | |
903 /// Values for optional parameters. | |
904 final List<ConstantExpression> defaultParameterValues; | |
905 | 787 |
906 FunctionDefinition(this.element, | 788 FunctionDefinition(this.element, |
907 this.thisParameter, | 789 this.thisParameter, |
908 this.parameters, | 790 this.parameters, |
909 this.body, | 791 this.returnContinuation, |
910 this.localConstants, | 792 this.body); |
911 this.defaultParameterValues); | |
912 | |
913 FunctionDefinition.abstract(this.element, | |
914 this.parameters, | |
915 this.defaultParameterValues) | |
916 : body = null, | |
917 thisParameter = null, | |
918 localConstants = const <ConstDeclaration>[]; | |
919 | 793 |
920 accept(Visitor visitor) => visitor.visitFunctionDefinition(this); | 794 accept(Visitor visitor) => visitor.visitFunctionDefinition(this); |
921 | |
922 bool get isEmpty => body == null; | |
923 } | |
924 | |
925 abstract class Initializer extends Node implements DartSpecificNode {} | |
926 | |
927 class FieldInitializer extends Initializer { | |
928 final FieldElement element; | |
929 final Body body; | |
930 | |
931 FieldInitializer(this.element, this.body); | |
932 accept(Visitor visitor) => visitor.visitFieldInitializer(this); | |
933 } | |
934 | |
935 class SuperInitializer extends Initializer { | |
936 final ConstructorElement target; | |
937 final List<Body> arguments; | |
938 final Selector selector; | |
939 SuperInitializer(this.target, this.arguments, this.selector); | |
940 accept(Visitor visitor) => visitor.visitSuperInitializer(this); | |
941 } | |
942 | |
943 class ConstructorDefinition extends RootNode implements DartSpecificNode { | |
944 final ConstructorElement element; | |
945 final Parameter thisParameter; | |
946 /// Mixed list of [Parameter]s and [MutableVariable]s. | |
947 final List<Definition> parameters; | |
948 final Body body; | |
949 final List<ConstDeclaration> localConstants; | |
950 final List<Initializer> initializers; | |
951 | |
952 /// Values for optional parameters. | |
953 final List<ConstantExpression> defaultParameterValues; | |
954 | |
955 ConstructorDefinition(this.element, | |
956 this.thisParameter, | |
957 this.parameters, | |
958 this.body, | |
959 this.initializers, | |
960 this.localConstants, | |
961 this.defaultParameterValues); | |
962 | |
963 // 'Abstract' here means "has no body" and is used to represent external | |
964 // constructors. | |
965 ConstructorDefinition.abstract( | |
966 this.element, | |
967 this.parameters, | |
968 this.defaultParameterValues) | |
969 : body = null, | |
970 initializers = null, | |
971 thisParameter = null, | |
972 localConstants = const <ConstDeclaration>[]; | |
973 | |
974 accept(Visitor visitor) => visitor.visitConstructorDefinition(this); | |
975 | |
976 bool get isEmpty => body == null; | |
977 } | 795 } |
978 | 796 |
979 /// Converts the internal representation of a type to a Dart object of type | 797 /// Converts the internal representation of a type to a Dart object of type |
980 /// [Type]. | 798 /// [Type]. |
981 class ReifyRuntimeType extends Primitive implements JsSpecificNode { | 799 class ReifyRuntimeType extends Primitive { |
982 /// Reference to the internal representation of a type (as produced, for | 800 /// Reference to the internal representation of a type (as produced, for |
983 /// example, by [ReadTypeVariable]). | 801 /// example, by [ReadTypeVariable]). |
984 final Reference<Primitive> value; | 802 final Reference<Primitive> value; |
985 ReifyRuntimeType(Primitive value) | 803 ReifyRuntimeType(Primitive value) |
986 : this.value = new Reference<Primitive>(value); | 804 : this.value = new Reference<Primitive>(value); |
987 | 805 |
988 @override | 806 @override |
989 accept(Visitor visitor) => visitor.visitReifyRuntimeType(this); | 807 accept(Visitor visitor) => visitor.visitReifyRuntimeType(this); |
990 } | 808 } |
991 | 809 |
992 /// Read the value the type variable [variable] from the target object. | 810 /// Read the value the type variable [variable] from the target object. |
993 /// | 811 /// |
994 /// The resulting value is an internal representation (and not neccessarily a | 812 /// The resulting value is an internal representation (and not neccessarily a |
995 /// Dart object), and must be reified by [ReifyRuntimeType], if it should be | 813 /// Dart object), and must be reified by [ReifyRuntimeType], if it should be |
996 /// used as a Dart value. | 814 /// used as a Dart value. |
997 class ReadTypeVariable extends Primitive implements JsSpecificNode { | 815 class ReadTypeVariable extends Primitive { |
998 final TypeVariableType variable; | 816 final TypeVariableType variable; |
999 final Reference<Primitive> target; | 817 final Reference<Primitive> target; |
1000 | 818 |
1001 ReadTypeVariable(this.variable, Primitive target) | 819 ReadTypeVariable(this.variable, Primitive target) |
1002 : this.target = new Reference<Primitive>(target); | 820 : this.target = new Reference<Primitive>(target); |
1003 | 821 |
1004 @override | 822 @override |
1005 accept(Visitor visitor) => visitor.visitReadTypeVariable(this); | 823 accept(Visitor visitor) => visitor.visitReadTypeVariable(this); |
1006 } | 824 } |
1007 | 825 |
1008 /// Representation of a closed type (that is, a type without type variables). | 826 /// Representation of a closed type (that is, a type without type variables). |
1009 /// | 827 /// |
1010 /// The resulting value is constructed from [dartType] by replacing the type | 828 /// The resulting value is constructed from [dartType] by replacing the type |
1011 /// variables with consecutive values from [arguments], in the order generated | 829 /// variables with consecutive values from [arguments], in the order generated |
1012 /// by [DartType.forEachTypeVariable]. The type variables in [dartType] are | 830 /// by [DartType.forEachTypeVariable]. The type variables in [dartType] are |
1013 /// treated as 'holes' in the term, which means that it must be ensured at | 831 /// treated as 'holes' in the term, which means that it must be ensured at |
1014 /// construction, that duplicate occurences of a type variable in [dartType] | 832 /// construction, that duplicate occurences of a type variable in [dartType] |
1015 /// are assigned the same value. | 833 /// are assigned the same value. |
1016 class TypeExpression extends Primitive implements JsSpecificNode { | 834 class TypeExpression extends Primitive { |
1017 final DartType dartType; | 835 final DartType dartType; |
1018 final List<Reference<Primitive>> arguments; | 836 final List<Reference<Primitive>> arguments; |
1019 | 837 |
1020 TypeExpression(this.dartType, | 838 TypeExpression(this.dartType, |
1021 [List<Primitive> arguments = const <Primitive>[]]) | 839 [List<Primitive> arguments = const <Primitive>[]]) |
1022 : this.arguments = _referenceList(arguments); | 840 : this.arguments = _referenceList(arguments); |
1023 | 841 |
1024 @override | 842 @override |
1025 accept(Visitor visitor) { | 843 accept(Visitor visitor) { |
1026 return visitor.visitTypeExpression(this); | 844 return visitor.visitTypeExpression(this); |
1027 } | 845 } |
1028 } | 846 } |
1029 | 847 |
1030 List<Reference<Primitive>> _referenceList(Iterable<Primitive> definitions) { | 848 List<Reference<Primitive>> _referenceList(Iterable<Primitive> definitions) { |
1031 return definitions.map((e) => new Reference<Primitive>(e)).toList(); | 849 return definitions.map((e) => new Reference<Primitive>(e)).toList(); |
1032 } | 850 } |
1033 | 851 |
1034 abstract class Visitor<T> { | 852 abstract class Visitor<T> { |
1035 const Visitor(); | 853 const Visitor(); |
1036 | 854 |
1037 T visit(Node node); | 855 T visit(Node node); |
1038 | 856 |
1039 // Concrete classes. | 857 // Concrete classes. |
1040 T visitFieldDefinition(FieldDefinition node); | |
1041 T visitFunctionDefinition(FunctionDefinition node); | 858 T visitFunctionDefinition(FunctionDefinition node); |
1042 T visitConstructorDefinition(ConstructorDefinition node); | |
1043 T visitBody(Body node); | |
1044 | |
1045 // Initializers | |
1046 T visitFieldInitializer(FieldInitializer node); | |
1047 T visitSuperInitializer(SuperInitializer node); | |
1048 | 859 |
1049 // Expressions. | 860 // Expressions. |
1050 T visitLetPrim(LetPrim node); | 861 T visitLetPrim(LetPrim node); |
1051 T visitLetCont(LetCont node); | 862 T visitLetCont(LetCont node); |
1052 T visitLetHandler(LetHandler node); | 863 T visitLetHandler(LetHandler node); |
1053 T visitLetMutable(LetMutable node); | 864 T visitLetMutable(LetMutable node); |
1054 T visitInvokeContinuation(InvokeContinuation node); | 865 T visitInvokeContinuation(InvokeContinuation node); |
1055 T visitInvokeStatic(InvokeStatic node); | 866 T visitInvokeStatic(InvokeStatic node); |
1056 T visitInvokeMethod(InvokeMethod node); | 867 T visitInvokeMethod(InvokeMethod node); |
1057 T visitInvokeMethodDirectly(InvokeMethodDirectly node); | 868 T visitInvokeMethodDirectly(InvokeMethodDirectly node); |
1058 T visitInvokeConstructor(InvokeConstructor node); | 869 T visitInvokeConstructor(InvokeConstructor node); |
1059 T visitConcatenateStrings(ConcatenateStrings node); | 870 T visitConcatenateStrings(ConcatenateStrings node); |
1060 T visitThrow(Throw node); | 871 T visitThrow(Throw node); |
1061 T visitRethrow(Rethrow node); | 872 T visitRethrow(Rethrow node); |
1062 T visitBranch(Branch node); | 873 T visitBranch(Branch node); |
1063 T visitTypeOperator(TypeOperator node); | 874 T visitTypeOperator(TypeOperator node); |
1064 T visitSetMutableVariable(SetMutableVariable node); | 875 T visitSetMutableVariable(SetMutableVariable node); |
1065 T visitDeclareFunction(DeclareFunction node); | |
1066 T visitSetStatic(SetStatic node); | 876 T visitSetStatic(SetStatic node); |
1067 T visitGetLazyStatic(GetLazyStatic node); | 877 T visitGetLazyStatic(GetLazyStatic node); |
| 878 T visitSetField(SetField node); |
1068 | 879 |
1069 // Definitions. | 880 // Definitions. |
1070 T visitLiteralList(LiteralList node); | 881 T visitLiteralList(LiteralList node); |
1071 T visitLiteralMap(LiteralMap node); | 882 T visitLiteralMap(LiteralMap node); |
1072 T visitConstant(Constant node); | 883 T visitConstant(Constant node); |
1073 T visitReifyTypeVar(ReifyTypeVar node); | |
1074 T visitCreateFunction(CreateFunction node); | 884 T visitCreateFunction(CreateFunction node); |
1075 T visitGetMutableVariable(GetMutableVariable node); | 885 T visitGetMutableVariable(GetMutableVariable node); |
1076 T visitParameter(Parameter node); | 886 T visitParameter(Parameter node); |
1077 T visitContinuation(Continuation node); | 887 T visitContinuation(Continuation node); |
1078 T visitMutableVariable(MutableVariable node); | 888 T visitMutableVariable(MutableVariable node); |
1079 T visitNonTailThrow(NonTailThrow node); | 889 T visitNonTailThrow(NonTailThrow node); |
1080 T visitGetStatic(GetStatic node); | 890 T visitGetStatic(GetStatic node); |
1081 | |
1082 // JavaScript specific nodes. | |
1083 | |
1084 // Conditions. | |
1085 T visitIsTrue(IsTrue node); | |
1086 | |
1087 // Expressions. | |
1088 T visitSetField(SetField node); | |
1089 | |
1090 // Definitions. | |
1091 T visitIdentical(Identical node); | 891 T visitIdentical(Identical node); |
1092 T visitInterceptor(Interceptor node); | 892 T visitInterceptor(Interceptor node); |
1093 T visitCreateInstance(CreateInstance node); | 893 T visitCreateInstance(CreateInstance node); |
1094 T visitGetField(GetField node); | 894 T visitGetField(GetField node); |
1095 T visitCreateBox(CreateBox node); | 895 T visitCreateBox(CreateBox node); |
1096 T visitReifyRuntimeType(ReifyRuntimeType node); | 896 T visitReifyRuntimeType(ReifyRuntimeType node); |
1097 T visitReadTypeVariable(ReadTypeVariable node); | 897 T visitReadTypeVariable(ReadTypeVariable node); |
1098 T visitTypeExpression(TypeExpression node); | 898 T visitTypeExpression(TypeExpression node); |
1099 T visitCreateInvocationMirror(CreateInvocationMirror node); | 899 T visitCreateInvocationMirror(CreateInvocationMirror node); |
| 900 |
| 901 // Conditions. |
| 902 T visitIsTrue(IsTrue node); |
1100 } | 903 } |
1101 | 904 |
1102 /// Recursively visits the entire CPS term, and calls abstract `process*` | 905 /// Recursively visits the entire CPS term, and calls abstract `process*` |
1103 /// (i.e. `processLetPrim`) functions in pre-order. | 906 /// (i.e. `processLetPrim`) functions in pre-order. |
1104 class RecursiveVisitor implements Visitor { | 907 class RecursiveVisitor implements Visitor { |
1105 const RecursiveVisitor(); | 908 const RecursiveVisitor(); |
1106 | 909 |
1107 visit(Node node) => node.accept(this); | 910 visit(Node node) => node.accept(this); |
1108 | 911 |
1109 processReference(Reference ref) {} | 912 processReference(Reference ref) {} |
1110 | 913 |
1111 processBody(Body node) {} | |
1112 visitBody(Body node) { | |
1113 processBody(node); | |
1114 visit(node.returnContinuation); | |
1115 visit(node.body); | |
1116 } | |
1117 | |
1118 processFieldDefinition(FieldDefinition node) {} | |
1119 visitFieldDefinition(FieldDefinition node) { | |
1120 processFieldDefinition(node); | |
1121 if (node.body != null) { | |
1122 visit(node.body); | |
1123 } | |
1124 } | |
1125 | |
1126 processFunctionDefinition(FunctionDefinition node) {} | 914 processFunctionDefinition(FunctionDefinition node) {} |
1127 visitFunctionDefinition(FunctionDefinition node) { | 915 visitFunctionDefinition(FunctionDefinition node) { |
1128 processFunctionDefinition(node); | 916 processFunctionDefinition(node); |
1129 if (node.thisParameter != null) visit(node.thisParameter); | 917 if (node.thisParameter != null) visit(node.thisParameter); |
1130 node.parameters.forEach(visit); | 918 node.parameters.forEach(visit); |
1131 if (node.body != null) { | 919 visit(node.returnContinuation); |
1132 visit(node.body); | |
1133 } | |
1134 } | |
1135 | |
1136 processConstructorDefinition(ConstructorDefinition node) {} | |
1137 visitConstructorDefinition(ConstructorDefinition node) { | |
1138 processConstructorDefinition(node); | |
1139 if (node.thisParameter != null) visit(node.thisParameter); | |
1140 node.parameters.forEach(visit); | |
1141 if (node.initializers != null) { | |
1142 node.initializers.forEach(visit); | |
1143 } | |
1144 if (node.body != null) { | |
1145 visit(node.body); | |
1146 } | |
1147 } | |
1148 | |
1149 processFieldInitializer(FieldInitializer node) {} | |
1150 visitFieldInitializer(FieldInitializer node) { | |
1151 processFieldInitializer(node); | |
1152 visit(node.body); | 920 visit(node.body); |
1153 } | 921 } |
1154 | 922 |
1155 processSuperInitializer(SuperInitializer node) {} | |
1156 visitSuperInitializer(SuperInitializer node) { | |
1157 processSuperInitializer(node); | |
1158 node.arguments.forEach(visit); | |
1159 } | |
1160 | |
1161 // Expressions. | 923 // Expressions. |
1162 | 924 |
1163 processLetPrim(LetPrim node) {} | 925 processLetPrim(LetPrim node) {} |
1164 visitLetPrim(LetPrim node) { | 926 visitLetPrim(LetPrim node) { |
1165 processLetPrim(node); | 927 processLetPrim(node); |
1166 visit(node.primitive); | 928 visit(node.primitive); |
1167 visit(node.body); | 929 visit(node.body); |
1168 } | 930 } |
1169 | 931 |
1170 processLetCont(LetCont node) {} | 932 processLetCont(LetCont node) {} |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1261 } | 1023 } |
1262 | 1024 |
1263 processSetMutableVariable(SetMutableVariable node) {} | 1025 processSetMutableVariable(SetMutableVariable node) {} |
1264 visitSetMutableVariable(SetMutableVariable node) { | 1026 visitSetMutableVariable(SetMutableVariable node) { |
1265 processSetMutableVariable(node); | 1027 processSetMutableVariable(node); |
1266 processReference(node.variable); | 1028 processReference(node.variable); |
1267 processReference(node.value); | 1029 processReference(node.value); |
1268 visit(node.body); | 1030 visit(node.body); |
1269 } | 1031 } |
1270 | 1032 |
1271 processDeclareFunction(DeclareFunction node) {} | |
1272 visitDeclareFunction(DeclareFunction node) { | |
1273 processDeclareFunction(node); | |
1274 visit(node.variable); | |
1275 visit(node.definition); | |
1276 visit(node.body); | |
1277 } | |
1278 | |
1279 processGetLazyStatic(GetLazyStatic node) {} | 1033 processGetLazyStatic(GetLazyStatic node) {} |
1280 visitGetLazyStatic(GetLazyStatic node) { | 1034 visitGetLazyStatic(GetLazyStatic node) { |
1281 processGetLazyStatic(node); | 1035 processGetLazyStatic(node); |
1282 processReference(node.continuation); | 1036 processReference(node.continuation); |
1283 } | 1037 } |
1284 | 1038 |
1285 // Definitions. | |
1286 | |
1287 processLiteralList(LiteralList node) {} | 1039 processLiteralList(LiteralList node) {} |
1288 visitLiteralList(LiteralList node) { | 1040 visitLiteralList(LiteralList node) { |
1289 processLiteralList(node); | 1041 processLiteralList(node); |
1290 node.values.forEach(processReference); | 1042 node.values.forEach(processReference); |
1291 } | 1043 } |
1292 | 1044 |
1293 processLiteralMap(LiteralMap node) {} | 1045 processLiteralMap(LiteralMap node) {} |
1294 visitLiteralMap(LiteralMap node) { | 1046 visitLiteralMap(LiteralMap node) { |
1295 processLiteralMap(node); | 1047 processLiteralMap(node); |
1296 for (LiteralMapEntry entry in node.entries) { | 1048 for (LiteralMapEntry entry in node.entries) { |
1297 processReference(entry.key); | 1049 processReference(entry.key); |
1298 processReference(entry.value); | 1050 processReference(entry.value); |
1299 } | 1051 } |
1300 } | 1052 } |
1301 | 1053 |
1302 processConstant(Constant node) {} | 1054 processConstant(Constant node) {} |
1303 visitConstant(Constant node) { | 1055 visitConstant(Constant node) { |
1304 processConstant(node); | 1056 processConstant(node); |
1305 } | 1057 } |
1306 | 1058 |
1307 processReifyTypeVar(ReifyTypeVar node) {} | |
1308 visitReifyTypeVar(ReifyTypeVar node) { | |
1309 processReifyTypeVar(node); | |
1310 } | |
1311 | |
1312 processCreateFunction(CreateFunction node) {} | 1059 processCreateFunction(CreateFunction node) {} |
1313 visitCreateFunction(CreateFunction node) { | 1060 visitCreateFunction(CreateFunction node) { |
1314 processCreateFunction(node); | 1061 processCreateFunction(node); |
1315 visit(node.definition); | 1062 visit(node.definition); |
1316 } | 1063 } |
1317 | 1064 |
1318 processMutableVariable(node) {} | 1065 processMutableVariable(node) {} |
1319 visitMutableVariable(MutableVariable node) { | 1066 visitMutableVariable(MutableVariable node) { |
1320 processMutableVariable(node); | 1067 processMutableVariable(node); |
1321 } | 1068 } |
1322 | 1069 |
1323 processGetMutableVariable(GetMutableVariable node) {} | 1070 processGetMutableVariable(GetMutableVariable node) {} |
1324 visitGetMutableVariable(GetMutableVariable node) { | 1071 visitGetMutableVariable(GetMutableVariable node) { |
1325 processGetMutableVariable(node); | 1072 processGetMutableVariable(node); |
1326 processReference(node.variable); | 1073 processReference(node.variable); |
1327 } | 1074 } |
1328 | 1075 |
1329 processParameter(Parameter node) {} | 1076 processParameter(Parameter node) {} |
1330 visitParameter(Parameter node) { | 1077 visitParameter(Parameter node) { |
1331 processParameter(node); | 1078 processParameter(node); |
1332 } | 1079 } |
1333 | 1080 |
1334 processContinuation(Continuation node) {} | 1081 processContinuation(Continuation node) {} |
1335 visitContinuation(Continuation node) { | 1082 visitContinuation(Continuation node) { |
1336 processContinuation(node); | 1083 processContinuation(node); |
1337 node.parameters.forEach(visitParameter); | 1084 node.parameters.forEach(visitParameter); |
1338 if (node.body != null) visit(node.body); | 1085 if (node.body != null) visit(node.body); |
1339 } | 1086 } |
1340 | 1087 |
1341 // Conditions. | |
1342 | |
1343 processIsTrue(IsTrue node) {} | 1088 processIsTrue(IsTrue node) {} |
1344 visitIsTrue(IsTrue node) { | 1089 visitIsTrue(IsTrue node) { |
1345 processIsTrue(node); | 1090 processIsTrue(node); |
1346 processReference(node.value); | 1091 processReference(node.value); |
1347 } | 1092 } |
1348 | 1093 |
1349 // JavaScript specific nodes. | |
1350 processIdentical(Identical node) {} | 1094 processIdentical(Identical node) {} |
1351 visitIdentical(Identical node) { | 1095 visitIdentical(Identical node) { |
1352 processIdentical(node); | 1096 processIdentical(node); |
1353 processReference(node.left); | 1097 processReference(node.left); |
1354 processReference(node.right); | 1098 processReference(node.right); |
1355 } | 1099 } |
1356 | 1100 |
1357 processInterceptor(Interceptor node) {} | 1101 processInterceptor(Interceptor node) {} |
1358 visitInterceptor(Interceptor node) { | 1102 visitInterceptor(Interceptor node) { |
1359 processInterceptor(node); | 1103 processInterceptor(node); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1421 processNonTailThrow(node); | 1165 processNonTailThrow(node); |
1422 processReference(node.value); | 1166 processReference(node.value); |
1423 } | 1167 } |
1424 | 1168 |
1425 processCreateInvocationMirror(CreateInvocationMirror node) {} | 1169 processCreateInvocationMirror(CreateInvocationMirror node) {} |
1426 visitCreateInvocationMirror(CreateInvocationMirror node) { | 1170 visitCreateInvocationMirror(CreateInvocationMirror node) { |
1427 processCreateInvocationMirror(node); | 1171 processCreateInvocationMirror(node); |
1428 node.arguments.forEach(processReference); | 1172 node.arguments.forEach(processReference); |
1429 } | 1173 } |
1430 } | 1174 } |
OLD | NEW |