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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/cps_ir/cps_ir_builder.dart

Issue 661933002: Split IrBuilder and IrBuilderVisitor. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 2 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 | Annotate | Revision Log
« no previous file with comments | « pkg/analyzer2dart/lib/src/cps_generator.dart ('k') | no next file » | 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) 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 4
5 library dart2js.ir_builder; 5 library dart2js.ir_builder;
6 6
7 import '../constants/expressions.dart'; 7 import '../constants/expressions.dart';
8 import '../constants/values.dart' show PrimitiveConstantValue; 8 import '../constants/values.dart' show PrimitiveConstantValue;
9 import '../dart_backend/dart_backend.dart' show DartBackend; 9 import '../dart_backend/dart_backend.dart' show DartBackend;
10 import '../dart_types.dart'; 10 import '../dart_types.dart';
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
208 final List<ir.InvokeContinuation> _invocations = <ir.InvokeContinuation>[]; 208 final List<ir.InvokeContinuation> _invocations = <ir.InvokeContinuation>[];
209 final List<Environment> _environments = <Environment>[]; 209 final List<Environment> _environments = <Environment>[];
210 210
211 JumpCollector(this.target); 211 JumpCollector(this.target);
212 212
213 bool get isEmpty => _invocations.isEmpty; 213 bool get isEmpty => _invocations.isEmpty;
214 int get length => _invocations.length; 214 int get length => _invocations.length;
215 List<ir.InvokeContinuation> get invocations => _invocations; 215 List<ir.InvokeContinuation> get invocations => _invocations;
216 List<Environment> get environments => _environments; 216 List<Environment> get environments => _environments;
217 217
218 void addJump(IrBuilderVisitor builder) { 218 void addJump(IrBuilder builder) {
219 ir.InvokeContinuation invoke = new ir.InvokeContinuation.uninitialized(); 219 ir.InvokeContinuation invoke = new ir.InvokeContinuation.uninitialized();
220 builder.add(invoke); 220 builder.add(invoke);
221 _invocations.add(invoke); 221 _invocations.add(invoke);
222 _environments.add(builder.environment); 222 _environments.add(builder.environment);
223 builder._current = null; 223 builder._current = null;
224 // TODO(kmillikin): Can we set builder.environment to null to make it 224 // TODO(kmillikin): Can we set builder.environment to null to make it
225 // less likely to mutate it? 225 // less likely to mutate it?
226 } 226 }
227 } 227 }
228 228
229 /// Mixin that provided encapsulated access to nested builders.
230 class IrBuilderMixin {
231 IrBuilder _irBuilder;
232
233 /// Execute [f] with [builder] as the current builder.
234 withBuilder(IrBuilder builder, f()) {
235 assert(builder != null);
236 IrBuilder prev = _irBuilder;
237 _irBuilder = builder;
238 var result = f();
239 _irBuilder = prev;
240 return result;
241 }
242
243 /// The current builder.
244 IrBuilder get irBuilder {
245 assert(_irBuilder != null);
246 return _irBuilder;
247 }
248 }
249
250
251 /// Shared state between nested builders.
252 class IrBuilderSharedState {
253 final ConstantSystem constantSystem;
254
255 /// A stack of collectors for breaks.
256 final List<JumpCollector> breakCollectors = <JumpCollector>[];
257
258 /// A stack of collectors for continues.
259 final List<JumpCollector> continueCollectors = <JumpCollector>[];
260
261 final List<ConstDeclaration> localConstants = <ConstDeclaration>[];
262
263 final Iterable<Entity> closureLocals;
264
265 final FunctionElement currentFunction;
266
267 final ir.Continuation returnContinuation = new ir.Continuation.retrn();
268
269 IrBuilderSharedState(this.constantSystem,
270 this.currentFunction,
271 this.closureLocals);
272 }
273
229 /// A factory for building the cps IR. 274 /// A factory for building the cps IR.
230 class IrBuilder { 275 class IrBuilder {
231 // TODO(johnniwinther): Make these field final and remove the default values 276 // TODO(johnniwinther): Make these field final and remove the default values
232 // when [IrBuilder] is a property of [IrBuilderVisitor] instead of a mixin. 277 // when [IrBuilder] is a property of [IrBuilderVisitor] instead of a mixin.
233 ConstantSystem constantSystem = DART_CONSTANT_SYSTEM;
234 278
235 ir.Continuation returnContinuation = new ir.Continuation.retrn(); 279 final List<ir.Parameter> _parameters = <ir.Parameter>[];
236 280
237 List<ir.Parameter> _parameters = <ir.Parameter>[]; 281 final IrBuilderSharedState state;
238 282
239 /// A map from variable indexes to their values. 283 /// A map from variable indexes to their values.
240 Environment environment = new Environment.empty(); 284 Environment environment;
241
242 List<ConstDeclaration> _localConstants = <ConstDeclaration>[];
243 285
244 // The IR builder maintains a context, which is an expression with a hole in 286 // The IR builder maintains a context, which is an expression with a hole in
245 // it. The hole represents the focus where new expressions can be added. 287 // it. The hole represents the focus where new expressions can be added.
246 // The context is implemented by 'root' which is the root of the expression 288 // The context is implemented by 'root' which is the root of the expression
247 // and 'current' which is the expression that immediately contains the hole. 289 // and 'current' which is the expression that immediately contains the hole.
248 // Not all expressions have a hole (e.g., invocations, which always occur in 290 // Not all expressions have a hole (e.g., invocations, which always occur in
249 // tail position, do not have a hole). Expressions with a hole have a plug 291 // tail position, do not have a hole). Expressions with a hole have a plug
250 // method. 292 // method.
251 // 293 //
252 // Conceptually, visiting a statement takes a context as input and returns 294 // Conceptually, visiting a statement takes a context as input and returns
253 // either a new context or else an expression without a hole if all 295 // either a new context or else an expression without a hole if all
254 // control-flow paths through the statement have exited. An expression 296 // control-flow paths through the statement have exited. An expression
255 // without a hole is represented by a (root, current) pair where root is the 297 // without a hole is represented by a (root, current) pair where root is the
256 // expression and current is null. 298 // expression and current is null.
257 // 299 //
258 // Conceptually again, visiting an expression takes a context as input and 300 // Conceptually again, visiting an expression takes a context as input and
259 // returns either a pair of a new context and a definition denoting 301 // returns either a pair of a new context and a definition denoting
260 // the expression's value, or else an expression without a hole if all 302 // the expression's value, or else an expression without a hole if all
261 // control-flow paths through the expression have exited. 303 // control-flow paths through the expression have exited.
262 // 304 //
263 // We do not pass contexts as arguments or return them. Rather we use the 305 // We do not pass contexts as arguments or return them. Rather we use the
264 // current context (root, current) as the visitor state and mutate current. 306 // current context (root, current) as the visitor state and mutate current.
265 // Visiting a statement returns null; visiting an expression returns the 307 // Visiting a statement returns null; visiting an expression returns the
266 // primitive denoting its value. 308 // primitive denoting its value.
267 309
268 ir.Expression _root = null; 310 ir.Expression _root = null;
269 ir.Expression _current = null; 311 ir.Expression _current = null;
270 312
313 IrBuilder(ConstantSystem constantSystem,
314 FunctionElement currentFunction,
315 Iterable<Entity> closureLocals)
316 : this.state = new IrBuilderSharedState(
317 constantSystem, currentFunction, closureLocals),
318 this.environment = new Environment.empty();
319
320 /// Construct a delimited visitor for visiting a subtree.
321 ///
322 /// The delimited visitor has its own compile-time environment mapping
323 /// local variables to their values, which is initially a copy of the parent
324 /// environment. It has its own context for building an IR expression, so
325 /// the built expression is not plugged into the parent's context.
326 IrBuilder.delimited(IrBuilder parent)
327 : this.state = parent.state,
328 this.environment = new Environment.from(parent.environment);
329
330 /// Construct a visitor for a recursive continuation.
331 ///
332 /// The recursive continuation builder has fresh parameters (i.e. SSA phis)
333 /// for all the local variables in the parent, because the invocation sites
334 /// of the continuation are not all known when the builder is created. The
335 /// recursive invocations will be passed values for all the local variables,
336 /// which may be eliminated later if they are redundant---if they take on
337 /// the same value at all invocation sites.
338 IrBuilder.recursive(IrBuilder parent)
339 : this.state = parent.state,
340 this.environment = new Environment.empty() {
341 parent.environment.index2variable.forEach(createParameter);
342 }
343
344
271 bool get isOpen => _root == null || _current != null; 345 bool get isOpen => _root == null || _current != null;
272 346
273 /// Create a parameter for [parameterElement] and add it to the current 347 /// Create a parameter for [parameterElement] and add it to the current
274 /// environment. If [isClosureVariable] marks whether [parameterElement] is 348 /// environment. If [isClosureVariable] marks whether [parameterElement] is
275 /// accessed from an inner function. 349 /// accessed from an inner function.
276 void createParameter(LocalElement parameterElement, 350 void createParameter(LocalElement parameterElement,
277 {bool isClosureVariable: false}) { 351 {bool isClosureVariable: false}) {
278 ir.Parameter parameter = new ir.Parameter(parameterElement); 352 ir.Parameter parameter = new ir.Parameter(parameterElement);
279 _parameters.add(parameter); 353 _parameters.add(parameter);
280 if (isClosureVariable) { 354 if (isClosureVariable) {
281 add(new ir.SetClosureVariable(parameterElement, parameter)); 355 add(new ir.SetClosureVariable(parameterElement, parameter));
282 } else { 356 } else {
283 environment.extend(parameterElement, parameter); 357 environment.extend(parameterElement, parameter);
284 } 358 }
285 } 359 }
286 360
287 void declareLocalConstant(LocalVariableElement variableElement, 361 void declareLocalConstant(LocalVariableElement variableElement,
288 ConstantExpression value) { 362 ConstantExpression value) {
289 _localConstants.add(new ConstDeclaration(variableElement, value)); 363 state.localConstants.add(new ConstDeclaration(variableElement, value));
290 } 364 }
291 365
292 void declareLocalVariable(LocalVariableElement variableElement, 366 void declareLocalVariable(LocalVariableElement variableElement,
293 {ir.Primitive initialValue, 367 {ir.Primitive initialValue,
294 bool isClosureVariable: false}) { 368 bool isClosureVariable: false}) {
295 assert(isOpen); 369 assert(isOpen);
296 if (initialValue == null) { 370 if (initialValue == null) {
297 // TODO(kmillikin): Consider pooling constants. 371 // TODO(kmillikin): Consider pooling constants.
298 // The initial value is null. 372 // The initial value is null.
299 initialValue = makePrimConst(constantSystem.createNull()); 373 initialValue = makePrimConst(state.constantSystem.createNull());
300 add(new ir.LetPrim(initialValue)); 374 add(new ir.LetPrim(initialValue));
301 } 375 }
302 if (isClosureVariable) { 376 if (isClosureVariable) {
303 add(new ir.SetClosureVariable(variableElement, 377 add(new ir.SetClosureVariable(variableElement,
304 initialValue, 378 initialValue,
305 isDeclaration: true)); 379 isDeclaration: true));
306 } else { 380 } else {
307 // In case a primitive was introduced for the initializer expression, 381 // In case a primitive was introduced for the initializer expression,
308 // use this variable element to help derive a good name for it. 382 // use this variable element to help derive a good name for it.
309 initialValue.useElementAsHint(variableElement); 383 initialValue.useElementAsHint(variableElement);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
345 // are created from analyzer2dart. 419 // are created from analyzer2dart.
346 ir.Node buildPrimConst(PrimitiveConstantValue constant) { 420 ir.Node buildPrimConst(PrimitiveConstantValue constant) {
347 assert(isOpen); 421 assert(isOpen);
348 ir.Node prim = makePrimConst(constant); 422 ir.Node prim = makePrimConst(constant);
349 add(new ir.LetPrim(prim)); 423 add(new ir.LetPrim(prim));
350 return prim; 424 return prim;
351 } 425 }
352 426
353 /// Create an integer literal. 427 /// Create an integer literal.
354 ir.Constant buildIntegerLiteral(int value) { 428 ir.Constant buildIntegerLiteral(int value) {
355 return buildPrimConst(constantSystem.createInt(value)); 429 return buildPrimConst(state.constantSystem.createInt(value));
356 } 430 }
357 431
358 /// Create an double literal. 432 /// Create an double literal.
359 ir.Constant buildDoubleLiteral(double value) { 433 ir.Constant buildDoubleLiteral(double value) {
360 return buildPrimConst(constantSystem.createDouble(value)); 434 return buildPrimConst(state.constantSystem.createDouble(value));
361 } 435 }
362 436
363 /// Create an bool literal. 437 /// Create an bool literal.
364 ir.Constant buildBooleanLiteral(bool value) { 438 ir.Constant buildBooleanLiteral(bool value) {
365 return buildPrimConst(constantSystem.createBool(value)); 439 return buildPrimConst(state.constantSystem.createBool(value));
366 } 440 }
367 441
368 /// Create an null literal. 442 /// Create an null literal.
369 ir.Constant buildNullLiteral() { 443 ir.Constant buildNullLiteral() {
370 return buildPrimConst(constantSystem.createNull()); 444 return buildPrimConst(state.constantSystem.createNull());
371 } 445 }
372 446
373 /// Create a string literal. 447 /// Create a string literal.
374 ir.Constant buildStringLiteral(String value) { 448 ir.Constant buildStringLiteral(String value) {
375 return buildPrimConst( 449 return buildPrimConst(
376 constantSystem.createString(new ast.DartString.literal(value))); 450 state.constantSystem.createString(new ast.DartString.literal(value)));
377 } 451 }
378 452
379 /// Create a get access of [local]. 453 /// Create a get access of [local].
380 ir.Primitive buildGetLocal(Element local) { 454 ir.Primitive buildGetLocal(Element local) {
381 assert(isOpen); 455 assert(isOpen);
382 return environment.lookup(local); 456 return environment.lookup(local);
383 } 457 }
384 458
385 /// Create a get access of the static [element]. 459 /// Create a get access of the static [element].
386 ir.Primitive buildGetStatic(Element element, Selector selector) { 460 ir.Primitive buildGetStatic(Element element, Selector selector) {
387 assert(isOpen); 461 assert(isOpen);
388 assert(selector.isGetter); 462 assert(selector.isGetter);
389 return continueWithExpression( 463 return continueWithExpression(
390 (k) => new ir.InvokeStatic(element, selector, k, [])); 464 (k) => new ir.InvokeStatic(element, selector, k, []));
391 } 465 }
392 466
393 /** 467 /**
394 * Add an explicit `return null` for functions that don't have a return 468 * Add an explicit `return null` for functions that don't have a return
395 * statement on each branch. This includes functions with an empty body, 469 * statement on each branch. This includes functions with an empty body,
396 * such as `foo(){ }`. 470 * such as `foo(){ }`.
397 */ 471 */
398 void ensureReturn() { 472 void ensureReturn() {
399 if (!isOpen) return; 473 if (!isOpen) return;
400 ir.Constant constant = makePrimConst(constantSystem.createNull()); 474 ir.Constant constant = makePrimConst(state.constantSystem.createNull());
401 add(new ir.LetPrim(constant)); 475 add(new ir.LetPrim(constant));
402 add(new ir.InvokeContinuation(returnContinuation, [constant])); 476 add(new ir.InvokeContinuation(state.returnContinuation, [constant]));
403 _current = null; 477 _current = null;
404 } 478 }
405 479
406 /// Create a [ir.FunctionDefinition] for [element] using [_root] as the body. 480 /// Create a [ir.FunctionDefinition] for [element] using [_root] as the body.
407 /// 481 ///
408 /// Parameters must be created before the construction of the body using 482 /// Parameters must be created before the construction of the body using
409 /// [createParameter]. 483 /// [createParameter].
410 ir.FunctionDefinition buildFunctionDefinition( 484 ir.FunctionDefinition buildFunctionDefinition(
411 FunctionElement element, 485 FunctionElement element,
412 List<ConstantExpression> defaults) { 486 List<ConstantExpression> defaults) {
413 if (!element.isAbstract) { 487 if (!element.isAbstract) {
414 ensureReturn(); 488 ensureReturn();
415 return new ir.FunctionDefinition( 489 return new ir.FunctionDefinition(
416 element, returnContinuation, _parameters, _root, 490 element, state.returnContinuation, _parameters, _root,
417 _localConstants, defaults); 491 state.localConstants, defaults);
418 } else { 492 } else {
419 assert(invariant(element, _root == null, 493 assert(invariant(element, _root == null,
420 message: "Non-empty body for abstract method $element: $_root")); 494 message: "Non-empty body for abstract method $element: $_root"));
421 assert(invariant(element, _localConstants.isEmpty, 495 assert(invariant(element, state.localConstants.isEmpty,
422 message: "Local constants for abstract method $element: " 496 message: "Local constants for abstract method $element: "
423 "$_localConstants")); 497 "${state.localConstants}"));
424 return new ir.FunctionDefinition.abstract( 498 return new ir.FunctionDefinition.abstract(
425 element, _parameters, defaults); 499 element, _parameters, defaults);
426 } 500 }
427 } 501 }
428 502
429 /// Create a static invocation of [element] with arguments structure defined 503 /// Create a static invocation of [element] with arguments structure defined
430 /// by [selector] and argument values defined by [arguments]. 504 /// by [selector] and argument values defined by [arguments].
431 ir.Primitive buildStaticInvocation(Element element, 505 ir.Primitive buildStaticInvocation(Element element,
432 Selector selector, 506 Selector selector,
433 List<ir.Definition> arguments) { 507 List<ir.Definition> arguments) {
434 return continueWithExpression( 508 return continueWithExpression(
435 (k) => new ir.InvokeStatic(element, selector, k, arguments)); 509 (k) => new ir.InvokeStatic(element, selector, k, arguments));
436 } 510 }
437 511
438 /// Create a return statement `return value;` or `return;` if [value] is 512 /// Create a return statement `return value;` or `return;` if [value] is
439 /// null. 513 /// null.
440 void buildReturn([ir.Primitive value]) { 514 void buildReturn([ir.Primitive value]) {
441 // Build(Return(e), C) = C'[InvokeContinuation(return, x)] 515 // Build(Return(e), C) = C'[InvokeContinuation(return, x)]
442 // where (C', x) = Build(e, C) 516 // where (C', x) = Build(e, C)
443 // 517 //
444 // Return without a subexpression is translated as if it were return null. 518 // Return without a subexpression is translated as if it were return null.
445 assert(isOpen); 519 assert(isOpen);
446 if (value == null) { 520 if (value == null) {
447 value = makePrimConst(constantSystem.createNull()); 521 value = makePrimConst(state.constantSystem.createNull());
448 add(new ir.LetPrim(value)); 522 add(new ir.LetPrim(value));
449 } 523 }
450 add(new ir.InvokeContinuation(returnContinuation, [value])); 524 add(new ir.InvokeContinuation(state.returnContinuation, [value]));
451 _current = null; 525 _current = null;
452 } 526 }
453 527
528 // Build(BreakStatement L, C) = C[InvokeContinuation(...)]
Johnni Winther 2014/10/17 10:13:46 A lot more functionality should be moved to the Ir
529 //
530 // The continuation and arguments are filled in later after translating
531 // the body containing the break.
532 bool buildBreak(JumpTarget target) {
533 return buildJumpInternal(target, state.breakCollectors);
534 }
535
536 // Build(ContinueStatement L, C) = C[InvokeContinuation(...)]
537 //
538 // The continuation and arguments are filled in later after translating
539 // the body containing the continue.
540 bool buildContinue(JumpTarget target) {
541 return buildJumpInternal(target, state.continueCollectors);
542 }
543
544 bool buildJumpInternal(JumpTarget target,
545 Iterable<JumpCollector> collectors) {
546 assert(isOpen);
547 for (JumpCollector collector in collectors) {
548 if (target == collector.target) {
549 collector.addJump(this);
550 return true;
551 }
552 }
553 return false;
554 }
454 } 555 }
455 556
456 /** 557 /**
457 * A tree visitor that builds [IrNodes]. The visit methods add statements using 558 * A tree visitor that builds [IrNodes]. The visit methods add statements using
458 * to the [builder] and return the last added statement for trees that represent 559 * to the [builder] and return the last added statement for trees that represent
459 * an expression. 560 * an expression.
460 */ 561 */
461 class IrBuilderVisitor extends ResolvedVisitor<ir.Primitive> with IrBuilder { 562 class IrBuilderVisitor extends ResolvedVisitor<ir.Primitive>
563 with IrBuilderMixin {
462 final Compiler compiler; 564 final Compiler compiler;
463 final SourceFile sourceFile; 565 final SourceFile sourceFile;
464 566
465 // In SSA terms, join-point continuation parameters are the phis and the 567 // In SSA terms, join-point continuation parameters are the phis and the
466 // continuation invocation arguments are the corresponding phi inputs. To 568 // continuation invocation arguments are the corresponding phi inputs. To
467 // support name introduction and renaming for source level variables, we use 569 // support name introduction and renaming for source level variables, we use
468 // nested (delimited) visitors for constructing subparts of the IR that will 570 // nested (delimited) visitors for constructing subparts of the IR that will
469 // need renaming. Each source variable is assigned an index. 571 // need renaming. Each source variable is assigned an index.
470 // 572 //
471 // Each nested visitor maintains a list of free variable uses in the body. 573 // Each nested visitor maintains a list of free variable uses in the body.
472 // These are implemented as a list of parameters, each with their own use 574 // These are implemented as a list of parameters, each with their own use
473 // list of references. When the delimited subexpression is plugged into the 575 // list of references. When the delimited subexpression is plugged into the
474 // surrounding context, the free occurrences can be captured or become free 576 // surrounding context, the free occurrences can be captured or become free
475 // occurrences in the next outer delimited subexpression. 577 // occurrences in the next outer delimited subexpression.
476 // 578 //
477 // Each nested visitor maintains a list that maps indexes of variables 579 // Each nested visitor maintains a list that maps indexes of variables
478 // assigned in the delimited subexpression to their reaching definition --- 580 // assigned in the delimited subexpression to their reaching definition ---
479 // that is, the definition in effect at the hole in 'current'. These are 581 // that is, the definition in effect at the hole in 'current'. These are
480 // used to determine if a join-point continuation needs to be passed 582 // used to determine if a join-point continuation needs to be passed
481 // arguments, and what the arguments are. 583 // arguments, and what the arguments are.
482 584
483 /// A stack of collectors for breaks.
484 final List<JumpCollector> breakCollectors;
485 /// A stack of collectors for continues.
486 final List<JumpCollector> continueCollectors;
487
488 FunctionElement currentFunction;
489 final DetectClosureVariables closureLocals;
490
491 /// Construct a top-level visitor. 585 /// Construct a top-level visitor.
492 IrBuilderVisitor(TreeElements elements, this.compiler, this.sourceFile) 586 IrBuilderVisitor(TreeElements elements, this.compiler, this.sourceFile)
493 : breakCollectors = <JumpCollector>[], 587 : super(elements);
494 continueCollectors = <JumpCollector>[],
495 closureLocals = new DetectClosureVariables(elements),
496 super(elements) {
497 constantSystem = compiler.backend.constantSystem;
498 }
499
500 /// Construct a delimited visitor for visiting a subtree.
501 ///
502 /// The delimited visitor has its own compile-time environment mapping
503 /// local variables to their values, which is initially a copy of the parent
504 /// environment. It has its own context for building an IR expression, so
505 /// the built expression is not plugged into the parent's context.
506 IrBuilderVisitor.delimited(IrBuilderVisitor parent)
507 : compiler = parent.compiler,
508 sourceFile = parent.sourceFile,
509 breakCollectors = parent.breakCollectors,
510 continueCollectors = parent.continueCollectors,
511 currentFunction = parent.currentFunction,
512 closureLocals = parent.closureLocals,
513 super(parent.elements) {
514 constantSystem = parent.constantSystem;
515 returnContinuation = parent.returnContinuation;
516 _localConstants = parent._localConstants;
517 environment = new Environment.from(parent.environment);
518 }
519
520 /// Construct a visitor for a recursive continuation.
521 ///
522 /// The recursive continuation builder has fresh parameters (i.e. SSA phis)
523 /// for all the local variables in the parent, because the invocation sites
524 /// of the continuation are not all known when the builder is created. The
525 /// recursive invocations will be passed values for all the local variables,
526 /// which may be eliminated later if they are redundant---if they take on
527 /// the same value at all invocation sites.
528 IrBuilderVisitor.recursive(IrBuilderVisitor parent)
529 : compiler = parent.compiler,
530 sourceFile = parent.sourceFile,
531 breakCollectors = parent.breakCollectors,
532 continueCollectors = parent.continueCollectors,
533 currentFunction = parent.currentFunction,
534 closureLocals = parent.closureLocals,
535 super(parent.elements) {
536 constantSystem = parent.constantSystem;
537 returnContinuation = parent.returnContinuation;
538 _localConstants = parent._localConstants;
539 parent.environment.index2variable.forEach(createParameter);
540 }
541 588
542 /** 589 /**
543 * Builds the [ir.FunctionDefinition] for a function element. In case the 590 * Builds the [ir.FunctionDefinition] for a function element. In case the
544 * function uses features that cannot be expressed in the IR, this function 591 * function uses features that cannot be expressed in the IR, this function
545 * returns `null`. 592 * returns `null`.
546 */ 593 */
547 ir.FunctionDefinition buildFunction(FunctionElement functionElement) { 594 ir.FunctionDefinition buildFunction(FunctionElement functionElement) {
548 return nullIfGiveup(() => buildFunctionInternal(functionElement)); 595 return nullIfGiveup(() => buildFunctionInternal(functionElement));
549 } 596 }
550 597
551 ir.FunctionDefinition buildFunctionInternal(FunctionElement element) { 598 ir.FunctionDefinition buildFunctionInternal(FunctionElement element) {
552 assert(invariant(element, element.isImplementation)); 599 assert(invariant(element, element.isImplementation));
553 currentFunction = element;
554 ast.FunctionExpression function = element.node; 600 ast.FunctionExpression function = element.node;
555 assert(function != null); 601 assert(function != null);
556 assert(!function.modifiers.isExternal); 602 assert(!function.modifiers.isExternal);
557 assert(elements[function] != null); 603 assert(elements[function] != null);
558 604
605 DetectClosureVariables closureLocals = new DetectClosureVariables(elements);
559 closureLocals.visit(function); 606 closureLocals.visit(function);
560 607
561 _root = _current = null; 608 return withBuilder(
609 new IrBuilder(compiler.backend.constantSystem,
610 element, closureLocals.usedFromClosure),
611 () {
612 FunctionSignature signature = element.functionSignature;
613 signature.orderedForEachParameter((ParameterElement parameterElement) {
614 irBuilder.createParameter(
615 parameterElement,
616 isClosureVariable: isClosureVariable(parameterElement));
617 });
562 618
563 FunctionSignature signature = element.functionSignature; 619 List<ConstantExpression> defaults = new List<ConstantExpression>();
564 signature.orderedForEachParameter((ParameterElement parameterElement) { 620 signature.orderedOptionalParameters.forEach((ParameterElement element) {
565 createParameter(parameterElement, 621 defaults.add(getConstantForVariable(element));
566 isClosureVariable: isClosureVariable(parameterElement)); 622 });
623
624 visit(function.body);
625 return irBuilder.buildFunctionDefinition(element, defaults);
567 }); 626 });
568
569 List<ConstantExpression> defaults = new List<ConstantExpression>();
570 signature.orderedOptionalParameters.forEach((ParameterElement element) {
571 defaults.add(getConstantForVariable(element));
572 });
573
574 visit(function.body);
575 return buildFunctionDefinition(element, defaults);
576 } 627 }
577 628
578 ir.Primitive visit(ast.Node node) => node.accept(this); 629 ir.Primitive visit(ast.Node node) => node.accept(this);
579 630
580 // ==== Statements ==== 631 // ==== Statements ====
581 // Build(Block(stamements), C) = C' 632 // Build(Block(stamements), C) = C'
582 // where C' = statements.fold(Build, C) 633 // where C' = statements.fold(Build, C)
583 ir.Primitive visitBlock(ast.Block node) { 634 ir.Primitive visitBlock(ast.Block node) {
584 assert(isOpen); 635 assert(irBuilder.isOpen);
585 for (ast.Node n in node.statements.nodes) { 636 for (ast.Node n in node.statements.nodes) {
586 visit(n); 637 visit(n);
587 if (!isOpen) return null; 638 if (!irBuilder.isOpen) return null;
588 } 639 }
589 return null; 640 return null;
590 } 641 }
591 642
592 // Build(BreakStatement L, C) = C[InvokeContinuation(...)]
593 //
594 // The continuation and arguments are filled in later after translating
595 // the body containing the break.
596 ir.Primitive visitBreakStatement(ast.BreakStatement node) { 643 ir.Primitive visitBreakStatement(ast.BreakStatement node) {
597 assert(isOpen); 644 if (!irBuilder.buildBreak(elements.getTargetOf(node))) {
598 JumpTarget target = elements.getTargetOf(node); 645 compiler.internalError(node, "'break' target not found");
599 for (JumpCollector collector in breakCollectors) {
600 if (target == collector.target) {
601 collector.addJump(this);
602 return null;
603 }
604 } 646 }
605 compiler.internalError(node, "'break' target not found");
606 return null; 647 return null;
607 } 648 }
608 649
609 // Build(ContinueStatement L, C) = C[InvokeContinuation(...)]
610 //
611 // The continuation and arguments are filled in later after translating
612 // the body containing the continue.
613 ir.Primitive visitContinueStatement(ast.ContinueStatement node) { 650 ir.Primitive visitContinueStatement(ast.ContinueStatement node) {
614 assert(isOpen); 651 if (!irBuilder.buildContinue(elements.getTargetOf(node))) {
615 JumpTarget target = elements.getTargetOf(node); 652 compiler.internalError(node, "'continue' target not found");
616 for (JumpCollector collector in continueCollectors) {
617 if (target == collector.target) {
618 collector.addJump(this);
619 return null;
620 }
621 } 653 }
622 compiler.internalError(node, "'continue' target not found");
623 return null; 654 return null;
624 } 655 }
625 656
626 // Build(EmptyStatement, C) = C 657 // Build(EmptyStatement, C) = C
627 ir.Primitive visitEmptyStatement(ast.EmptyStatement node) { 658 ir.Primitive visitEmptyStatement(ast.EmptyStatement node) {
628 assert(isOpen); 659 assert(irBuilder.isOpen);
629 return null; 660 return null;
630 } 661 }
631 662
632 // Build(ExpressionStatement(e), C) = C' 663 // Build(ExpressionStatement(e), C) = C'
633 // where (C', _) = Build(e, C) 664 // where (C', _) = Build(e, C)
634 ir.Primitive visitExpressionStatement(ast.ExpressionStatement node) { 665 ir.Primitive visitExpressionStatement(ast.ExpressionStatement node) {
635 assert(isOpen); 666 assert(irBuilder.isOpen);
636 visit(node.expression); 667 visit(node.expression);
637 return null; 668 return null;
638 } 669 }
639 670
640 671
641 /// Create a non-recursive join-point continuation. 672 /// Create a non-recursive join-point continuation.
642 /// 673 ///
643 /// Given the environment length at the join point and a list of 674 /// Given the environment length at the join point and a list of
644 /// jumps that should reach the join point, create a join-point 675 /// jumps that should reach the join point, create a join-point
645 /// continuation. The join-point continuation has a parameter for each 676 /// continuation. The join-point continuation has a parameter for each
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
727 758
728 // Mutate this.environment to be the environment at the join point. Do 759 // Mutate this.environment to be the environment at the join point. Do
729 // this after adding the continuation invocations, because this.environment 760 // this after adding the continuation invocations, because this.environment
730 // might be collected by the jump collector and so the old environment 761 // might be collected by the jump collector and so the old environment
731 // values are needed for the continuation invocation. 762 // values are needed for the continuation invocation.
732 // 763 //
733 // Iterate to environment.length because environmentLength includes values 764 // Iterate to environment.length because environmentLength includes values
734 // outside the environment which are 'phantom' variables used for the 765 // outside the environment which are 'phantom' variables used for the
735 // values of expressions like &&, ||, and ?:. 766 // values of expressions like &&, ||, and ?:.
736 index = 0; 767 index = 0;
737 for (int i = 0; i < environment.length; ++i) { 768 for (int i = 0; i < irBuilder.environment.length; ++i) {
738 if (common[i] == null) { 769 if (common[i] == null) {
739 environment.index2value[i] = parameters[index++]; 770 irBuilder.environment.index2value[i] = parameters[index++];
740 } 771 }
741 } 772 }
742 773
743 return join; 774 return join;
744 } 775 }
745 776
746 /// Invoke a join-point continuation that contains arguments for all local 777 /// Invoke a join-point continuation that contains arguments for all local
747 /// variables. 778 /// variables.
748 /// 779 ///
749 /// Given the continuation and a list of uninitialized invocations, fill 780 /// Given the continuation and a list of uninitialized invocations, fill
750 /// in each invocation with the continuation and appropriate arguments. 781 /// in each invocation with the continuation and appropriate arguments.
751 void invokeFullJoin(ir.Continuation join, 782 void invokeFullJoin(ir.Continuation join,
752 JumpCollector jumps, 783 JumpCollector jumps,
753 {recursive: false}) { 784 {recursive: false}) {
754 join.isRecursive = recursive; 785 join.isRecursive = recursive;
755 for (int i = 0; i < jumps.length; ++i) { 786 for (int i = 0; i < jumps.length; ++i) {
756 Environment currentEnvironment = jumps.environments[i]; 787 Environment currentEnvironment = jumps.environments[i];
757 ir.InvokeContinuation invoke = jumps.invocations[i]; 788 ir.InvokeContinuation invoke = jumps.invocations[i];
758 invoke.continuation = new ir.Reference(join); 789 invoke.continuation = new ir.Reference(join);
759 invoke.arguments = new List<ir.Reference>.generate( 790 invoke.arguments = new List<ir.Reference>.generate(
760 join.parameters.length, 791 join.parameters.length,
761 (i) => new ir.Reference(currentEnvironment[i])); 792 (i) => new ir.Reference(currentEnvironment[i]));
762 invoke.isRecursive = recursive; 793 invoke.isRecursive = recursive;
763 } 794 }
764 } 795 }
765 796
766 ir.Primitive visitFor(ast.For node) { 797 ir.Primitive visitFor(ast.For node) {
767 assert(isOpen); 798 assert(irBuilder.isOpen);
768 // TODO(kmillikin,sigurdm): Handle closure variables declared in a for-loop. 799 // TODO(kmillikin,sigurdm): Handle closure variables declared in a for-loop.
769 if (node.initializer is ast.VariableDefinitions) { 800 if (node.initializer is ast.VariableDefinitions) {
770 ast.VariableDefinitions definitions = node.initializer; 801 ast.VariableDefinitions definitions = node.initializer;
771 for (ast.Node definition in definitions.definitions.nodes) { 802 for (ast.Node definition in definitions.definitions.nodes) {
772 Element element = elements[definition]; 803 Element element = elements[definition];
773 if (isClosureVariable(element)) { 804 if (isClosureVariable(element)) {
774 return giveup(definition, 'Closure variable in for loop initializer'); 805 return giveup(definition, 'Closure variable in for loop initializer');
775 } 806 }
776 } 807 }
777 } 808 }
(...skipping 15 matching lines...) Expand all
793 // loop(v, ...) 824 // loop(v, ...)
794 // 825 //
795 // If there are no breaks in the body, the break continuation is inlined 826 // If there are no breaks in the body, the break continuation is inlined
796 // in the exit continuation (i.e., the translation of the successor 827 // in the exit continuation (i.e., the translation of the successor
797 // statement occurs in the exit continuation). If there is only one 828 // statement occurs in the exit continuation). If there is only one
798 // invocation of the continue continuation (i.e., no continues in the 829 // invocation of the continue continuation (i.e., no continues in the
799 // body), the continue continuation is inlined in the body. 830 // body), the continue continuation is inlined in the body.
800 831
801 if (node.initializer != null) visit(node.initializer); 832 if (node.initializer != null) visit(node.initializer);
802 833
803 IrBuilderVisitor condBuilder = new IrBuilderVisitor.recursive(this); 834 IrBuilder condBuilder = new IrBuilder.recursive(irBuilder);
804 ir.Primitive condition; 835 ir.Primitive condition;
805 if (node.condition == null) { 836 if (node.condition == null) {
806 // If the condition is empty then the body is entered unconditionally. 837 // If the condition is empty then the body is entered unconditionally.
807 condition = makePrimConst(constantSystem.createBool(true)); 838 condition = irBuilder.makePrimConst(
839 irBuilder.state.constantSystem.createBool(true));
808 condBuilder.add(new ir.LetPrim(condition)); 840 condBuilder.add(new ir.LetPrim(condition));
809 } else { 841 } else {
810 condition = condBuilder.visit(node.condition); 842 condition = withBuilder(condBuilder, () => visit(node.condition));
811 } 843 }
812 844
813 JumpTarget target = elements.getTargetDefinition(node); 845 JumpTarget target = elements.getTargetDefinition(node);
814 JumpCollector breakCollector = new JumpCollector(target); 846 JumpCollector breakCollector = new JumpCollector(target);
815 JumpCollector continueCollector = new JumpCollector(target); 847 JumpCollector continueCollector = new JumpCollector(target);
816 breakCollectors.add(breakCollector); 848 irBuilder.state.breakCollectors.add(breakCollector);
817 continueCollectors.add(continueCollector); 849 irBuilder.state.continueCollectors.add(continueCollector);
818 850
819 IrBuilderVisitor bodyBuilder = new IrBuilderVisitor.delimited(condBuilder); 851 IrBuilder bodyBuilder = new IrBuilder.delimited(condBuilder);
820 bodyBuilder.visit(node.body); 852 withBuilder(bodyBuilder, () => visit(node.body));
821 assert(breakCollectors.last == breakCollector); 853 assert(irBuilder.state.breakCollectors.last == breakCollector);
822 assert(continueCollectors.last == continueCollector); 854 assert(irBuilder.state.continueCollectors.last == continueCollector);
823 breakCollectors.removeLast(); 855 irBuilder.state.breakCollectors.removeLast();
824 continueCollectors.removeLast(); 856 irBuilder.state.continueCollectors.removeLast();
825 857
826 // The binding of the continue continuation should occur as late as 858 // The binding of the continue continuation should occur as late as
827 // possible, that is, at the nearest common ancestor of all the continue 859 // possible, that is, at the nearest common ancestor of all the continue
828 // sites in the body. However, that is difficult to compute here, so it 860 // sites in the body. However, that is difficult to compute here, so it
829 // is instead placed just outside the body of the body continuation. 861 // is instead placed just outside the body of the body continuation.
830 bool hasContinues = !continueCollector.isEmpty; 862 bool hasContinues = !continueCollector.isEmpty;
831 IrBuilderVisitor updateBuilder = hasContinues 863 IrBuilder updateBuilder = hasContinues
832 ? new IrBuilderVisitor.recursive(condBuilder) 864 ? new IrBuilder.recursive(condBuilder)
833 : bodyBuilder; 865 : bodyBuilder;
834 for (ast.Node n in node.update) { 866 for (ast.Node n in node.update) {
835 if (!updateBuilder.isOpen) break; 867 if (!updateBuilder.isOpen) break;
836 updateBuilder.visit(n); 868 withBuilder(updateBuilder, () => visit(n));
837 } 869 }
838 870
839 // Create body entry and loop exit continuations and a branch to them. 871 // Create body entry and loop exit continuations and a branch to them.
840 ir.Continuation bodyContinuation = new ir.Continuation([]); 872 ir.Continuation bodyContinuation = new ir.Continuation([]);
841 ir.Continuation exitContinuation = new ir.Continuation([]); 873 ir.Continuation exitContinuation = new ir.Continuation([]);
842 ir.LetCont branch = 874 ir.LetCont branch =
843 new ir.LetCont(exitContinuation, 875 new ir.LetCont(exitContinuation,
844 new ir.LetCont(bodyContinuation, 876 new ir.LetCont(bodyContinuation,
845 new ir.Branch(new ir.IsTrue(condition), 877 new ir.Branch(new ir.IsTrue(condition),
846 bodyContinuation, 878 bodyContinuation,
(...skipping 29 matching lines...) Expand all
876 // only after it is guaranteed that they are not empty. 908 // only after it is guaranteed that they are not empty.
877 if (hasContinues) { 909 if (hasContinues) {
878 continueContinuation.body = updateBuilder._root; 910 continueContinuation.body = updateBuilder._root;
879 bodyContinuation.body = 911 bodyContinuation.body =
880 new ir.LetCont(continueContinuation, bodyBuilder._root); 912 new ir.LetCont(continueContinuation, bodyBuilder._root);
881 } else { 913 } else {
882 bodyContinuation.body = bodyBuilder._root; 914 bodyContinuation.body = bodyBuilder._root;
883 } 915 }
884 916
885 loopContinuation.body = condBuilder._root; 917 loopContinuation.body = condBuilder._root;
886 add(new ir.LetCont(loopContinuation, 918 irBuilder.add(new ir.LetCont(loopContinuation,
887 new ir.InvokeContinuation(loopContinuation, 919 new ir.InvokeContinuation(loopContinuation,
888 environment.index2value))); 920 irBuilder.environment.index2value)));
889 if (hasBreaks) { 921 if (hasBreaks) {
890 _current = branch; 922 irBuilder._current = branch;
891 environment = condBuilder.environment; 923 irBuilder.environment = condBuilder.environment;
892 breakCollector.addJump(this); 924 breakCollector.addJump(irBuilder);
893 letJoin.continuation = createJoin(environment.length, breakCollector); 925 letJoin.continuation =
894 _current = letJoin; 926 createJoin(irBuilder.environment.length, breakCollector);
927 irBuilder._current = letJoin;
895 } else { 928 } else {
896 _current = condBuilder._current; 929 irBuilder._current = condBuilder._current;
897 environment = condBuilder.environment; 930 irBuilder.environment = condBuilder.environment;
898 } 931 }
899 return null; 932 return null;
900 } 933 }
901 934
902 ir.Primitive visitIf(ast.If node) { 935 ir.Primitive visitIf(ast.If node) {
903 assert(isOpen); 936 assert(irBuilder.isOpen);
904 ir.Primitive condition = visit(node.condition); 937 ir.Primitive condition = visit(node.condition);
905 938
906 // The then and else parts are delimited. 939 // The then and else parts are delimited.
907 IrBuilderVisitor thenBuilder = new IrBuilderVisitor.delimited(this); 940 IrBuilder thenBuilder = new IrBuilder.delimited(irBuilder);
908 IrBuilderVisitor elseBuilder = new IrBuilderVisitor.delimited(this); 941 IrBuilder elseBuilder = new IrBuilder.delimited(irBuilder);
909 thenBuilder.visit(node.thenPart); 942 withBuilder(thenBuilder, () => visit(node.thenPart));
910 if (node.hasElsePart) elseBuilder.visit(node.elsePart); 943 if (node.hasElsePart) {
944 withBuilder(elseBuilder, () => visit(node.elsePart));
945 }
911 946
912 // Build the term 947 // Build the term
913 // (Result =) let cont then() = [[thenPart]] in 948 // (Result =) let cont then() = [[thenPart]] in
914 // let cont else() = [[elsePart]] in 949 // let cont else() = [[elsePart]] in
915 // if condition (then, else) 950 // if condition (then, else)
916 ir.Continuation thenContinuation = new ir.Continuation([]); 951 ir.Continuation thenContinuation = new ir.Continuation([]);
917 ir.Continuation elseContinuation = new ir.Continuation([]); 952 ir.Continuation elseContinuation = new ir.Continuation([]);
918 ir.Expression letElse = 953 ir.Expression letElse =
919 new ir.LetCont(elseContinuation, 954 new ir.LetCont(elseContinuation,
920 new ir.Branch(new ir.IsTrue(condition), 955 new ir.Branch(new ir.IsTrue(condition),
921 thenContinuation, 956 thenContinuation,
922 elseContinuation)); 957 elseContinuation));
923 ir.Expression letThen = new ir.LetCont(thenContinuation, letElse); 958 ir.Expression letThen = new ir.LetCont(thenContinuation, letElse);
924 ir.Expression result = letThen; 959 ir.Expression result = letThen;
925 960
926 ir.Continuation joinContinuation; // Null if there is no join. 961 ir.Continuation joinContinuation; // Null if there is no join.
927 if (thenBuilder.isOpen && elseBuilder.isOpen) { 962 if (thenBuilder.isOpen && elseBuilder.isOpen) {
928 // There is a join-point continuation. Build the term 963 // There is a join-point continuation. Build the term
929 // 'let cont join(x, ...) = [] in Result' and plug invocations of the 964 // 'let cont join(x, ...) = [] in Result' and plug invocations of the
930 // join-point continuation into the then and else continuations. 965 // join-point continuation into the then and else continuations.
931 JumpCollector jumps = new JumpCollector(null); 966 JumpCollector jumps = new JumpCollector(null);
932 jumps.addJump(thenBuilder); 967 jumps.addJump(thenBuilder);
933 jumps.addJump(elseBuilder); 968 jumps.addJump(elseBuilder);
934 joinContinuation = createJoin(environment.length, jumps); 969 joinContinuation = createJoin(irBuilder.environment.length, jumps);
935 result = new ir.LetCont(joinContinuation, result); 970 result = new ir.LetCont(joinContinuation, result);
936 } 971 }
937 972
938 // The then or else term root could be null, but not both. If there is 973 // The then or else term root could be null, but not both. If there is
939 // a join then an InvokeContinuation was just added to both of them. If 974 // a join then an InvokeContinuation was just added to both of them. If
940 // there is no join, then at least one of them is closed and thus has a 975 // there is no join, then at least one of them is closed and thus has a
941 // non-null root by the definition of the predicate isClosed. In the 976 // non-null root by the definition of the predicate isClosed. In the
942 // case that one of them is null, it must be the only one that is open 977 // case that one of them is null, it must be the only one that is open
943 // and thus contains the new hole in the context. This case is handled 978 // and thus contains the new hole in the context. This case is handled
944 // after the branch is plugged into the current hole. 979 // after the branch is plugged into the current hole.
945 thenContinuation.body = thenBuilder._root; 980 thenContinuation.body = thenBuilder._root;
946 elseContinuation.body = elseBuilder._root; 981 elseContinuation.body = elseBuilder._root;
947 982
948 add(result); 983 irBuilder.add(result);
949 if (joinContinuation == null) { 984 if (joinContinuation == null) {
950 // At least one subexpression is closed. 985 // At least one subexpression is closed.
951 if (thenBuilder.isOpen) { 986 if (thenBuilder.isOpen) {
952 _current = (thenBuilder._root == null) ? letThen : thenBuilder._current; 987 irBuilder._current =
953 environment = thenBuilder.environment; 988 (thenBuilder._root == null) ? letThen : thenBuilder._current;
989 irBuilder.environment = thenBuilder.environment;
954 } else if (elseBuilder.isOpen) { 990 } else if (elseBuilder.isOpen) {
955 _current = (elseBuilder._root == null) ? letElse : elseBuilder._current; 991 irBuilder._current =
956 environment = elseBuilder.environment; 992 (elseBuilder._root == null) ? letElse : elseBuilder._current;
993 irBuilder.environment = elseBuilder.environment;
957 } else { 994 } else {
958 _current = null; 995 irBuilder._current = null;
959 } 996 }
960 } 997 }
961 return null; 998 return null;
962 } 999 }
963 1000
964 ir.Primitive visitLabeledStatement(ast.LabeledStatement node) { 1001 ir.Primitive visitLabeledStatement(ast.LabeledStatement node) {
965 ast.Statement body = node.statement; 1002 ast.Statement body = node.statement;
966 return body is ast.Loop 1003 return body is ast.Loop
967 ? visit(body) 1004 ? visit(body)
968 : giveup(node, 'labeled statement'); 1005 : giveup(node, 'labeled statement');
969 } 1006 }
970 1007
971 ir.Primitive visitWhile(ast.While node) { 1008 ir.Primitive visitWhile(ast.While node) {
972 assert(isOpen); 1009 assert(irBuilder.isOpen);
973 // While loops use four named continuations: the entry to the body, the 1010 // While loops use four named continuations: the entry to the body, the
974 // loop exit, the loop back edge (continue), and the loop exit (break). 1011 // loop exit, the loop back edge (continue), and the loop exit (break).
975 // The CPS translation of [[while (condition) body; successor]] is: 1012 // The CPS translation of [[while (condition) body; successor]] is:
976 // 1013 //
977 // let cont continue(x, ...) = 1014 // let cont continue(x, ...) =
978 // let prim cond = [[condition]] in 1015 // let prim cond = [[condition]] in
979 // let cont break() = [[successor]] in 1016 // let cont break() = [[successor]] in
980 // let cont exit() = break(v, ...) in 1017 // let cont exit() = break(v, ...) in
981 // let cont body() = [[body]]; continue(v, ...) in 1018 // let cont body() = [[body]]; continue(v, ...) in
982 // branch cond (body, exit) in 1019 // branch cond (body, exit) in
983 // continue(v, ...) 1020 // continue(v, ...)
984 // 1021 //
985 // If there are no breaks in the body, the break continuation is inlined 1022 // If there are no breaks in the body, the break continuation is inlined
986 // in the exit continuation (i.e., the translation of the successor 1023 // in the exit continuation (i.e., the translation of the successor
987 // statement occurs in the exit continuation). 1024 // statement occurs in the exit continuation).
988 1025
989 // The condition and body are delimited. 1026 // The condition and body are delimited.
990 IrBuilderVisitor condBuilder = new IrBuilderVisitor.recursive(this); 1027 IrBuilder condBuilder = new IrBuilder.recursive(irBuilder);
991 ir.Primitive condition = condBuilder.visit(node.condition); 1028 ir.Primitive condition =
1029 withBuilder(condBuilder, () => visit(node.condition));
992 1030
993 JumpTarget target = elements.getTargetDefinition(node); 1031 JumpTarget target = elements.getTargetDefinition(node);
994 JumpCollector breakCollector = new JumpCollector(target); 1032 JumpCollector breakCollector = new JumpCollector(target);
995 JumpCollector continueCollector = new JumpCollector(target); 1033 JumpCollector continueCollector = new JumpCollector(target);
996 breakCollectors.add(breakCollector); 1034 irBuilder.state.breakCollectors.add(breakCollector);
997 continueCollectors.add(continueCollector); 1035 irBuilder.state.continueCollectors.add(continueCollector);
998 1036
999 IrBuilderVisitor bodyBuilder = new IrBuilderVisitor.delimited(condBuilder); 1037 IrBuilder bodyBuilder = new IrBuilder.delimited(condBuilder);
1000 bodyBuilder.visit(node.body); 1038 withBuilder(bodyBuilder, () => visit(node.body));
1001 assert(breakCollectors.last == breakCollector); 1039 assert(irBuilder.state.breakCollectors.last == breakCollector);
1002 assert(continueCollectors.last == continueCollector); 1040 assert(irBuilder.state.continueCollectors.last == continueCollector);
1003 breakCollectors.removeLast(); 1041 irBuilder.state.breakCollectors.removeLast();
1004 continueCollectors.removeLast(); 1042 irBuilder.state.continueCollectors.removeLast();
1005 1043
1006 // Create body entry and loop exit continuations and a branch to them. 1044 // Create body entry and loop exit continuations and a branch to them.
1007 ir.Continuation bodyContinuation = new ir.Continuation([]); 1045 ir.Continuation bodyContinuation = new ir.Continuation([]);
1008 ir.Continuation exitContinuation = new ir.Continuation([]); 1046 ir.Continuation exitContinuation = new ir.Continuation([]);
1009 ir.LetCont branch = 1047 ir.LetCont branch =
1010 new ir.LetCont(exitContinuation, 1048 new ir.LetCont(exitContinuation,
1011 new ir.LetCont(bodyContinuation, 1049 new ir.LetCont(bodyContinuation,
1012 new ir.Branch(new ir.IsTrue(condition), 1050 new ir.Branch(new ir.IsTrue(condition),
1013 bodyContinuation, 1051 bodyContinuation,
1014 exitContinuation))); 1052 exitContinuation)));
1015 // If there are breaks in the body, then there must be a join-point 1053 // If there are breaks in the body, then there must be a join-point
1016 // continuation for the normal exit and the breaks. 1054 // continuation for the normal exit and the breaks.
1017 bool hasBreaks = !breakCollector.isEmpty; 1055 bool hasBreaks = !breakCollector.isEmpty;
1018 ir.LetCont letJoin; 1056 ir.LetCont letJoin;
1019 if (hasBreaks) { 1057 if (hasBreaks) {
1020 letJoin = new ir.LetCont(null, branch); 1058 letJoin = new ir.LetCont(null, branch);
1021 condBuilder.add(letJoin); 1059 condBuilder.add(letJoin);
1022 condBuilder._current = branch; 1060 condBuilder._current = branch;
1023 } else { 1061 } else {
1024 condBuilder.add(branch); 1062 condBuilder.add(branch);
1025 } 1063 }
1026 ir.Continuation loopContinuation = 1064 ir.Continuation loopContinuation =
1027 new ir.Continuation(condBuilder._parameters); 1065 new ir.Continuation(condBuilder._parameters);
1028 if (bodyBuilder.isOpen) continueCollector.addJump(bodyBuilder); 1066 if (bodyBuilder.isOpen) continueCollector.addJump(bodyBuilder);
1029 invokeFullJoin(loopContinuation, continueCollector, recursive: true); 1067 invokeFullJoin(loopContinuation, continueCollector, recursive: true);
1030 bodyContinuation.body = bodyBuilder._root; 1068 bodyContinuation.body = bodyBuilder._root;
1031 1069
1032 loopContinuation.body = condBuilder._root; 1070 loopContinuation.body = condBuilder._root;
1033 add(new ir.LetCont(loopContinuation, 1071 irBuilder.add(new ir.LetCont(loopContinuation,
1034 new ir.InvokeContinuation(loopContinuation, 1072 new ir.InvokeContinuation(loopContinuation,
1035 environment.index2value))); 1073 irBuilder.environment.index2value)));
1036 if (hasBreaks) { 1074 if (hasBreaks) {
1037 _current = branch; 1075 irBuilder._current = branch;
1038 environment = condBuilder.environment; 1076 irBuilder.environment = condBuilder.environment;
1039 breakCollector.addJump(this); 1077 breakCollector.addJump(irBuilder);
1040 letJoin.continuation = createJoin(environment.length, breakCollector); 1078 letJoin.continuation =
1041 _current = letJoin; 1079 createJoin(irBuilder.environment.length, breakCollector);
1080 irBuilder._current = letJoin;
1042 } else { 1081 } else {
1043 _current = condBuilder._current; 1082 irBuilder._current = condBuilder._current;
1044 environment = condBuilder.environment; 1083 irBuilder.environment = condBuilder.environment;
1045 } 1084 }
1046 return null; 1085 return null;
1047 } 1086 }
1048 1087
1049 ir.Primitive visitForIn(ast.ForIn node) { 1088 ir.Primitive visitForIn(ast.ForIn node) {
1050 // The for-in loop 1089 // The for-in loop
1051 // 1090 //
1052 // for (a in e) s; 1091 // for (a in e) s;
1053 // 1092 //
1054 // Is compiled analogously to: 1093 // Is compiled analogously to:
1055 // 1094 //
1056 // a = e.iterator; 1095 // a = e.iterator;
1057 // while (a.moveNext()) { 1096 // while (a.moveNext()) {
1058 // var n0 = a.current; 1097 // var n0 = a.current;
1059 // s; 1098 // s;
1060 // } 1099 // }
1061 1100
1062 // The condition and body are delimited. 1101 // The condition and body are delimited.
1063 IrBuilderVisitor condBuilder = new IrBuilderVisitor.recursive(this); 1102 IrBuilder condBuilder = new IrBuilder.recursive(irBuilder);
1064 1103
1065 ir.Primitive expressionReceiver = visit(node.expression); 1104 ir.Primitive expressionReceiver = visit(node.expression);
1066 List<ir.Primitive> emptyArguments = new List<ir.Primitive>(); 1105 List<ir.Primitive> emptyArguments = new List<ir.Primitive>();
1067 1106
1068 ir.Parameter iterator = new ir.Parameter(null); 1107 ir.Parameter iterator = new ir.Parameter(null);
1069 ir.Continuation iteratorInvoked = new ir.Continuation([iterator]); 1108 ir.Continuation iteratorInvoked = new ir.Continuation([iterator]);
1070 add(new ir.LetCont(iteratorInvoked, 1109 irBuilder.add(new ir.LetCont(iteratorInvoked,
1071 new ir.InvokeMethod(expressionReceiver, 1110 new ir.InvokeMethod(expressionReceiver,
1072 new Selector.getter("iterator", null), iteratorInvoked, 1111 new Selector.getter("iterator", null), iteratorInvoked,
1073 emptyArguments))); 1112 emptyArguments)));
1074 1113
1075 ir.Parameter condition = new ir.Parameter(null); 1114 ir.Parameter condition = new ir.Parameter(null);
1076 ir.Continuation moveNextInvoked = new ir.Continuation([condition]); 1115 ir.Continuation moveNextInvoked = new ir.Continuation([condition]);
1077 condBuilder.add(new ir.LetCont(moveNextInvoked, 1116 condBuilder.add(new ir.LetCont(moveNextInvoked,
1078 new ir.InvokeMethod(iterator, 1117 new ir.InvokeMethod(iterator,
1079 new Selector.call("moveNext", null, 0), 1118 new Selector.call("moveNext", null, 0),
1080 moveNextInvoked, emptyArguments))); 1119 moveNextInvoked, emptyArguments)));
1081 1120
1082 JumpTarget target = elements.getTargetDefinition(node); 1121 JumpTarget target = elements.getTargetDefinition(node);
1083 JumpCollector breakCollector = new JumpCollector(target); 1122 JumpCollector breakCollector = new JumpCollector(target);
1084 JumpCollector continueCollector = new JumpCollector(target); 1123 JumpCollector continueCollector = new JumpCollector(target);
1085 breakCollectors.add(breakCollector); 1124 irBuilder.state.breakCollectors.add(breakCollector);
1086 continueCollectors.add(continueCollector); 1125 irBuilder.state.continueCollectors.add(continueCollector);
1087 1126
1088 IrBuilderVisitor bodyBuilder = new IrBuilderVisitor.delimited(condBuilder); 1127 IrBuilder bodyBuilder = new IrBuilder.delimited(condBuilder);
1089 ast.Node identifier = node.declaredIdentifier; 1128 ast.Node identifier = node.declaredIdentifier;
1090 Element variableElement = elements.getForInVariable(node); 1129 Element variableElement = elements.getForInVariable(node);
1091 Selector selector = elements.getSelector(identifier); 1130 Selector selector = elements.getSelector(identifier);
1092 1131
1093 // node.declaredIdentifier can be either an ast.VariableDefinitions 1132 // node.declaredIdentifier can be either an ast.VariableDefinitions
1094 // (defining a new local variable) or a send designating some existing 1133 // (defining a new local variable) or a send designating some existing
1095 // variable. 1134 // variable.
1096 ast.Node declaredIdentifier = node.declaredIdentifier; 1135 ast.Node declaredIdentifier = node.declaredIdentifier;
1097 1136
1098 if (declaredIdentifier is ast.VariableDefinitions) { 1137 if (declaredIdentifier is ast.VariableDefinitions) {
1099 bodyBuilder.visit(declaredIdentifier); 1138 withBuilder(bodyBuilder, () => visit(declaredIdentifier));
1100 } 1139 }
1101 1140
1102 ir.Parameter currentValue = new ir.Parameter(null); 1141 ir.Parameter currentValue = new ir.Parameter(null);
1103 ir.Continuation currentInvoked = new ir.Continuation([currentValue]); 1142 ir.Continuation currentInvoked = new ir.Continuation([currentValue]);
1104 bodyBuilder.add(new ir.LetCont(currentInvoked, 1143 bodyBuilder.add(new ir.LetCont(currentInvoked,
1105 new ir.InvokeMethod(iterator, new Selector.getter("current", null), 1144 new ir.InvokeMethod(iterator, new Selector.getter("current", null),
1106 currentInvoked, emptyArguments))); 1145 currentInvoked, emptyArguments)));
1107 if (Elements.isLocal(variableElement)) { 1146 if (Elements.isLocal(variableElement)) {
1108 bodyBuilder.setLocal(variableElement, currentValue); 1147 withBuilder(bodyBuilder, () => setLocal(variableElement, currentValue));
1109 } else if (Elements.isStaticOrTopLevel(variableElement)) { 1148 } else if (Elements.isStaticOrTopLevel(variableElement)) {
1110 bodyBuilder.setStatic(variableElement, selector, currentValue); 1149 withBuilder(bodyBuilder,
1150 () => setStatic(variableElement, selector, currentValue));
1111 } else { 1151 } else {
1112 ir.Primitive receiver = bodyBuilder.lookupThis(); 1152 ir.Primitive receiver =
1113 bodyBuilder.setDynamic(null, receiver, selector, currentValue); 1153 withBuilder(bodyBuilder, () => lookupThis());
1154 withBuilder(bodyBuilder,
1155 () => setDynamic(null, receiver, selector, currentValue));
1114 } 1156 }
1115 1157
1116 bodyBuilder.visit(node.body); 1158 withBuilder(bodyBuilder, () => visit(node.body));
1117 assert(breakCollectors.last == breakCollector); 1159 assert(irBuilder.state.breakCollectors.last == breakCollector);
1118 assert(continueCollectors.last == continueCollector); 1160 assert(irBuilder.state.continueCollectors.last == continueCollector);
1119 breakCollectors.removeLast(); 1161 irBuilder.state.breakCollectors.removeLast();
1120 continueCollectors.removeLast(); 1162 irBuilder.state.continueCollectors.removeLast();
1121 1163
1122 // Create body entry and loop exit continuations and a branch to them. 1164 // Create body entry and loop exit continuations and a branch to them.
1123 ir.Continuation bodyContinuation = new ir.Continuation([]); 1165 ir.Continuation bodyContinuation = new ir.Continuation([]);
1124 ir.Continuation exitContinuation = new ir.Continuation([]); 1166 ir.Continuation exitContinuation = new ir.Continuation([]);
1125 ir.LetCont branch = 1167 ir.LetCont branch =
1126 new ir.LetCont(exitContinuation, 1168 new ir.LetCont(exitContinuation,
1127 new ir.LetCont(bodyContinuation, 1169 new ir.LetCont(bodyContinuation,
1128 new ir.Branch(new ir.IsTrue(condition), 1170 new ir.Branch(new ir.IsTrue(condition),
1129 bodyContinuation, 1171 bodyContinuation,
1130 exitContinuation))); 1172 exitContinuation)));
1131 // If there are breaks in the body, then there must be a join-point 1173 // If there are breaks in the body, then there must be a join-point
1132 // continuation for the normal exit and the breaks. 1174 // continuation for the normal exit and the breaks.
1133 bool hasBreaks = !breakCollector.isEmpty; 1175 bool hasBreaks = !breakCollector.isEmpty;
1134 ir.LetCont letJoin; 1176 ir.LetCont letJoin;
1135 if (hasBreaks) { 1177 if (hasBreaks) {
1136 letJoin = new ir.LetCont(null, branch); 1178 letJoin = new ir.LetCont(null, branch);
1137 condBuilder.add(letJoin); 1179 condBuilder.add(letJoin);
1138 condBuilder._current = branch; 1180 condBuilder._current = branch;
1139 } else { 1181 } else {
1140 condBuilder.add(branch); 1182 condBuilder.add(branch);
1141 } 1183 }
1142 ir.Continuation loopContinuation = 1184 ir.Continuation loopContinuation =
1143 new ir.Continuation(condBuilder._parameters); 1185 new ir.Continuation(condBuilder._parameters);
1144 if (bodyBuilder.isOpen) continueCollector.addJump(bodyBuilder); 1186 if (bodyBuilder.isOpen) continueCollector.addJump(bodyBuilder);
1145 invokeFullJoin(loopContinuation, continueCollector, recursive: true); 1187 invokeFullJoin(loopContinuation, continueCollector, recursive: true);
1146 bodyContinuation.body = bodyBuilder._root; 1188 bodyContinuation.body = bodyBuilder._root;
1147 1189
1148 loopContinuation.body = condBuilder._root; 1190 loopContinuation.body = condBuilder._root;
1149 add(new ir.LetCont(loopContinuation, 1191 irBuilder.add(new ir.LetCont(loopContinuation,
1150 new ir.InvokeContinuation(loopContinuation, 1192 new ir.InvokeContinuation(loopContinuation,
1151 environment.index2value))); 1193 irBuilder.environment.index2value)));
1152 if (hasBreaks) { 1194 if (hasBreaks) {
1153 _current = branch; 1195 irBuilder._current = branch;
1154 environment = condBuilder.environment; 1196 irBuilder.environment = condBuilder.environment;
1155 breakCollector.addJump(this); 1197 breakCollector.addJump(irBuilder);
1156 letJoin.continuation = createJoin(environment.length, breakCollector); 1198 letJoin.continuation =
1157 _current = letJoin; 1199 createJoin(irBuilder.environment.length, breakCollector);
1200 irBuilder._current = letJoin;
1158 } else { 1201 } else {
1159 _current = condBuilder._current; 1202 irBuilder._current = condBuilder._current;
1160 environment = condBuilder.environment; 1203 irBuilder.environment = condBuilder.environment;
1161 } 1204 }
1162 return null; 1205 return null;
1163 } 1206 }
1164 1207
1165 ir.Primitive visitVariableDefinitions(ast.VariableDefinitions node) { 1208 ir.Primitive visitVariableDefinitions(ast.VariableDefinitions node) {
1166 assert(isOpen); 1209 assert(irBuilder.isOpen);
1167 if (node.modifiers.isConst) { 1210 if (node.modifiers.isConst) {
1168 for (ast.SendSet definition in node.definitions.nodes) { 1211 for (ast.SendSet definition in node.definitions.nodes) {
1169 assert(!definition.arguments.isEmpty); 1212 assert(!definition.arguments.isEmpty);
1170 assert(definition.arguments.tail.isEmpty); 1213 assert(definition.arguments.tail.isEmpty);
1171 VariableElement element = elements[definition]; 1214 VariableElement element = elements[definition];
1172 ConstantExpression value = getConstantForVariable(element); 1215 ConstantExpression value = getConstantForVariable(element);
1173 declareLocalConstant(element, value); 1216 irBuilder.declareLocalConstant(element, value);
1174 } 1217 }
1175 } else { 1218 } else {
1176 for (ast.Node definition in node.definitions.nodes) { 1219 for (ast.Node definition in node.definitions.nodes) {
1177 Element element = elements[definition]; 1220 Element element = elements[definition];
1178 ir.Primitive initialValue; 1221 ir.Primitive initialValue;
1179 // Definitions are either SendSets if there is an initializer, or 1222 // Definitions are either SendSets if there is an initializer, or
1180 // Identifiers if there is no initializer. 1223 // Identifiers if there is no initializer.
1181 if (definition is ast.SendSet) { 1224 if (definition is ast.SendSet) {
1182 assert(!definition.arguments.isEmpty); 1225 assert(!definition.arguments.isEmpty);
1183 assert(definition.arguments.tail.isEmpty); 1226 assert(definition.arguments.tail.isEmpty);
1184 initialValue = visit(definition.arguments.head); 1227 initialValue = visit(definition.arguments.head);
1185 } else { 1228 } else {
1186 assert(definition is ast.Identifier); 1229 assert(definition is ast.Identifier);
1187 } 1230 }
1188 declareLocalVariable(element, 1231 irBuilder.declareLocalVariable(element,
1189 initialValue: initialValue, 1232 initialValue: initialValue,
1190 isClosureVariable: isClosureVariable(element)); 1233 isClosureVariable: isClosureVariable(element));
1191 } 1234 }
1192 } 1235 }
1193 return null; 1236 return null;
1194 } 1237 }
1195 1238
1196 // Build(Return(e), C) = C'[InvokeContinuation(return, x)] 1239 // Build(Return(e), C) = C'[InvokeContinuation(return, x)]
1197 // where (C', x) = Build(e, C) 1240 // where (C', x) = Build(e, C)
1198 // 1241 //
1199 // Return without a subexpression is translated as if it were return null. 1242 // Return without a subexpression is translated as if it were return null.
1200 ir.Primitive visitReturn(ast.Return node) { 1243 ir.Primitive visitReturn(ast.Return node) {
1201 assert(isOpen); 1244 assert(irBuilder.isOpen);
1202 assert(invariant(node, node.beginToken.value != 'native')); 1245 assert(invariant(node, node.beginToken.value != 'native'));
1203 if (node.expression == null) { 1246 if (node.expression == null) {
1204 buildReturn(); 1247 irBuilder.buildReturn();
1205 } else { 1248 } else {
1206 buildReturn(visit(node.expression)); 1249 irBuilder.buildReturn(visit(node.expression));
1207 } 1250 }
1208 return null; 1251 return null;
1209 } 1252 }
1210 1253
1211 // ==== Expressions ==== 1254 // ==== Expressions ====
1212 ir.Primitive visitConditional(ast.Conditional node) { 1255 ir.Primitive visitConditional(ast.Conditional node) {
1213 assert(isOpen); 1256 assert(irBuilder.isOpen);
1214 ir.Primitive condition = visit(node.condition); 1257 ir.Primitive condition = visit(node.condition);
1215 1258
1216 // The then and else expressions are delimited. 1259 // The then and else expressions are delimited.
1217 IrBuilderVisitor thenBuilder = new IrBuilderVisitor.delimited(this); 1260 IrBuilder thenBuilder = new IrBuilder.delimited(irBuilder);
1218 IrBuilderVisitor elseBuilder = new IrBuilderVisitor.delimited(this); 1261 IrBuilder elseBuilder = new IrBuilder.delimited(irBuilder);
1219 ir.Primitive thenValue = thenBuilder.visit(node.thenExpression); 1262 ir.Primitive thenValue =
1220 ir.Primitive elseValue = elseBuilder.visit(node.elseExpression); 1263 withBuilder(thenBuilder, () => visit(node.thenExpression));
1264 ir.Primitive elseValue =
1265 withBuilder(elseBuilder, () => visit(node.elseExpression));
1221 1266
1222 // Treat the values of the subexpressions as named values in the 1267 // Treat the values of the subexpressions as named values in the
1223 // environment, so they will be treated as arguments to the join-point 1268 // environment, so they will be treated as arguments to the join-point
1224 // continuation. 1269 // continuation.
1225 assert(environment.length == thenBuilder.environment.length); 1270 assert(irBuilder.environment.length == thenBuilder.environment.length);
1226 assert(environment.length == elseBuilder.environment.length); 1271 assert(irBuilder.environment.length == elseBuilder.environment.length);
1227 thenBuilder.environment.extend(null, thenValue); 1272 thenBuilder.environment.extend(null, thenValue);
1228 elseBuilder.environment.extend(null, elseValue); 1273 elseBuilder.environment.extend(null, elseValue);
1229 JumpCollector jumps = new JumpCollector(null); 1274 JumpCollector jumps = new JumpCollector(null);
1230 jumps.addJump(thenBuilder); 1275 jumps.addJump(thenBuilder);
1231 jumps.addJump(elseBuilder); 1276 jumps.addJump(elseBuilder);
1232 ir.Continuation joinContinuation = 1277 ir.Continuation joinContinuation =
1233 createJoin(environment.length + 1, jumps); 1278 createJoin(irBuilder.environment.length + 1, jumps);
1234 1279
1235 // Build the term 1280 // Build the term
1236 // let cont join(x, ..., result) = [] in 1281 // let cont join(x, ..., result) = [] in
1237 // let cont then() = [[thenPart]]; join(v, ...) in 1282 // let cont then() = [[thenPart]]; join(v, ...) in
1238 // let cont else() = [[elsePart]]; join(v, ...) in 1283 // let cont else() = [[elsePart]]; join(v, ...) in
1239 // if condition (then, else) 1284 // if condition (then, else)
1240 ir.Continuation thenContinuation = new ir.Continuation([]); 1285 ir.Continuation thenContinuation = new ir.Continuation([]);
1241 ir.Continuation elseContinuation = new ir.Continuation([]); 1286 ir.Continuation elseContinuation = new ir.Continuation([]);
1242 thenContinuation.body = thenBuilder._root; 1287 thenContinuation.body = thenBuilder._root;
1243 elseContinuation.body = elseBuilder._root; 1288 elseContinuation.body = elseBuilder._root;
1244 add(new ir.LetCont(joinContinuation, 1289 irBuilder.add(new ir.LetCont(joinContinuation,
1245 new ir.LetCont(thenContinuation, 1290 new ir.LetCont(thenContinuation,
1246 new ir.LetCont(elseContinuation, 1291 new ir.LetCont(elseContinuation,
1247 new ir.Branch(new ir.IsTrue(condition), 1292 new ir.Branch(new ir.IsTrue(condition),
1248 thenContinuation, 1293 thenContinuation,
1249 elseContinuation))))); 1294 elseContinuation)))));
1250 return (thenValue == elseValue) 1295 return (thenValue == elseValue)
1251 ? thenValue 1296 ? thenValue
1252 : joinContinuation.parameters.last; 1297 : joinContinuation.parameters.last;
1253 } 1298 }
1254 1299
1255 // For all simple literals: 1300 // For all simple literals:
1256 // Build(Literal(c), C) = C[let val x = Constant(c) in [], x] 1301 // Build(Literal(c), C) = C[let val x = Constant(c) in [], x]
1257 ir.Primitive visitLiteralBool(ast.LiteralBool node) { 1302 ir.Primitive visitLiteralBool(ast.LiteralBool node) {
1258 assert(isOpen); 1303 assert(irBuilder.isOpen);
1259 return translateConstant(node); 1304 return translateConstant(node);
1260 } 1305 }
1261 1306
1262 ir.Primitive visitLiteralDouble(ast.LiteralDouble node) { 1307 ir.Primitive visitLiteralDouble(ast.LiteralDouble node) {
1263 assert(isOpen); 1308 assert(irBuilder.isOpen);
1264 return translateConstant(node); 1309 return translateConstant(node);
1265 } 1310 }
1266 1311
1267 ir.Primitive visitLiteralInt(ast.LiteralInt node) { 1312 ir.Primitive visitLiteralInt(ast.LiteralInt node) {
1268 assert(isOpen); 1313 assert(irBuilder.isOpen);
1269 return translateConstant(node); 1314 return translateConstant(node);
1270 } 1315 }
1271 1316
1272 ir.Primitive visitLiteralNull(ast.LiteralNull node) { 1317 ir.Primitive visitLiteralNull(ast.LiteralNull node) {
1273 assert(isOpen); 1318 assert(irBuilder.isOpen);
1274 return translateConstant(node); 1319 return translateConstant(node);
1275 } 1320 }
1276 1321
1277 ir.Primitive visitLiteralString(ast.LiteralString node) { 1322 ir.Primitive visitLiteralString(ast.LiteralString node) {
1278 assert(isOpen); 1323 assert(irBuilder.isOpen);
1279 return translateConstant(node); 1324 return translateConstant(node);
1280 } 1325 }
1281 1326
1282 ConstantExpression getConstantForNode(ast.Node node) { 1327 ConstantExpression getConstantForNode(ast.Node node) {
1283 ConstantExpression constant = 1328 ConstantExpression constant =
1284 compiler.backend.constantCompilerTask.compileNode(node, elements); 1329 compiler.backend.constantCompilerTask.compileNode(node, elements);
1285 assert(invariant(node, constant != null, 1330 assert(invariant(node, constant != null,
1286 message: 'No constant computed for $node')); 1331 message: 'No constant computed for $node'));
1287 return constant; 1332 return constant;
1288 } 1333 }
1289 1334
1290 ConstantExpression getConstantForVariable(VariableElement element) { 1335 ConstantExpression getConstantForVariable(VariableElement element) {
1291 ConstantExpression constant = 1336 ConstantExpression constant =
1292 compiler.backend.constants.getConstantForVariable(element); 1337 compiler.backend.constants.getConstantForVariable(element);
1293 assert(invariant(element, constant != null, 1338 assert(invariant(element, constant != null,
1294 message: 'No constant computed for $element')); 1339 message: 'No constant computed for $element'));
1295 return constant; 1340 return constant;
1296 } 1341 }
1297 1342
1298 ir.Primitive visitLiteralList(ast.LiteralList node) { 1343 ir.Primitive visitLiteralList(ast.LiteralList node) {
1299 assert(isOpen); 1344 assert(irBuilder.isOpen);
1300 if (node.isConst) { 1345 if (node.isConst) {
1301 return translateConstant(node); 1346 return translateConstant(node);
1302 } 1347 }
1303 List<ir.Primitive> values = node.elements.nodes.mapToList(visit); 1348 List<ir.Primitive> values = node.elements.nodes.mapToList(visit);
1304 GenericType type = elements.getType(node); 1349 GenericType type = elements.getType(node);
1305 ir.Primitive result = new ir.LiteralList(type, values); 1350 ir.Primitive result = new ir.LiteralList(type, values);
1306 add(new ir.LetPrim(result)); 1351 irBuilder.add(new ir.LetPrim(result));
1307 return result; 1352 return result;
1308 } 1353 }
1309 1354
1310 ir.Primitive visitLiteralMap(ast.LiteralMap node) { 1355 ir.Primitive visitLiteralMap(ast.LiteralMap node) {
1311 assert(isOpen); 1356 assert(irBuilder.isOpen);
1312 if (node.isConst) { 1357 if (node.isConst) {
1313 return translateConstant(node); 1358 return translateConstant(node);
1314 } 1359 }
1315 List<ir.Primitive> keys = new List<ir.Primitive>(); 1360 List<ir.Primitive> keys = new List<ir.Primitive>();
1316 List<ir.Primitive> values = new List<ir.Primitive>(); 1361 List<ir.Primitive> values = new List<ir.Primitive>();
1317 node.entries.nodes.forEach((ast.LiteralMapEntry node) { 1362 node.entries.nodes.forEach((ast.LiteralMapEntry node) {
1318 keys.add(visit(node.key)); 1363 keys.add(visit(node.key));
1319 values.add(visit(node.value)); 1364 values.add(visit(node.value));
1320 }); 1365 });
1321 GenericType type = elements.getType(node); 1366 GenericType type = elements.getType(node);
1322 ir.Primitive result = new ir.LiteralMap(type, keys, values); 1367 ir.Primitive result = new ir.LiteralMap(type, keys, values);
1323 add(new ir.LetPrim(result)); 1368 irBuilder.add(new ir.LetPrim(result));
1324 return result; 1369 return result;
1325 } 1370 }
1326 1371
1327 ir.Primitive visitLiteralSymbol(ast.LiteralSymbol node) { 1372 ir.Primitive visitLiteralSymbol(ast.LiteralSymbol node) {
1328 assert(isOpen); 1373 assert(irBuilder.isOpen);
1329 return translateConstant(node); 1374 return translateConstant(node);
1330 } 1375 }
1331 1376
1332 ir.Primitive visitIdentifier(ast.Identifier node) { 1377 ir.Primitive visitIdentifier(ast.Identifier node) {
1333 assert(isOpen); 1378 assert(irBuilder.isOpen);
1334 // "this" is the only identifier that should be met by the visitor. 1379 // "this" is the only identifier that should be met by the visitor.
1335 assert(node.isThis()); 1380 assert(node.isThis());
1336 return lookupThis(); 1381 return lookupThis();
1337 } 1382 }
1338 1383
1339 ir.Primitive visitParenthesizedExpression( 1384 ir.Primitive visitParenthesizedExpression(
1340 ast.ParenthesizedExpression node) { 1385 ast.ParenthesizedExpression node) {
1341 assert(isOpen); 1386 assert(irBuilder.isOpen);
1342 return visit(node.expression); 1387 return visit(node.expression);
1343 } 1388 }
1344 1389
1345 // Stores the result of visiting a CascadeReceiver, so we can return it from 1390 // Stores the result of visiting a CascadeReceiver, so we can return it from
1346 // its enclosing Cascade. 1391 // its enclosing Cascade.
1347 ir.Primitive _currentCascadeReceiver; 1392 ir.Primitive _currentCascadeReceiver;
1348 1393
1349 ir.Primitive visitCascadeReceiver(ast.CascadeReceiver node) { 1394 ir.Primitive visitCascadeReceiver(ast.CascadeReceiver node) {
1350 assert(isOpen); 1395 assert(irBuilder.isOpen);
1351 return _currentCascadeReceiver = visit(node.expression); 1396 return _currentCascadeReceiver = visit(node.expression);
1352 } 1397 }
1353 1398
1354 ir.Primitive visitCascade(ast.Cascade node) { 1399 ir.Primitive visitCascade(ast.Cascade node) {
1355 assert(isOpen); 1400 assert(irBuilder.isOpen);
1356 var oldCascadeReceiver = _currentCascadeReceiver; 1401 var oldCascadeReceiver = _currentCascadeReceiver;
1357 // Throw away the result of visiting the expression. 1402 // Throw away the result of visiting the expression.
1358 // Instead we return the result of visiting the CascadeReceiver. 1403 // Instead we return the result of visiting the CascadeReceiver.
1359 this.visit(node.expression); 1404 this.visit(node.expression);
1360 ir.Primitive receiver = _currentCascadeReceiver; 1405 ir.Primitive receiver = _currentCascadeReceiver;
1361 _currentCascadeReceiver = oldCascadeReceiver; 1406 _currentCascadeReceiver = oldCascadeReceiver;
1362 return receiver; 1407 return receiver;
1363 } 1408 }
1364 1409
1365 ir.Primitive lookupThis() { 1410 ir.Primitive lookupThis() {
1366 ir.Primitive result = new ir.This(); 1411 ir.Primitive result = new ir.This();
1367 add(new ir.LetPrim(result)); 1412 irBuilder.add(new ir.LetPrim(result));
1368 return result; 1413 return result;
1369 } 1414 }
1370 1415
1371 // ==== Sends ==== 1416 // ==== Sends ====
1372 ir.Primitive visitAssert(ast.Send node) { 1417 ir.Primitive visitAssert(ast.Send node) {
1373 assert(isOpen); 1418 assert(irBuilder.isOpen);
1374 return giveup(node, 'Assert'); 1419 return giveup(node, 'Assert');
1375 } 1420 }
1376 1421
1377 ir.Primitive visitNamedArgument(ast.NamedArgument node) { 1422 ir.Primitive visitNamedArgument(ast.NamedArgument node) {
1378 assert(isOpen); 1423 assert(irBuilder.isOpen);
1379 return visit(node.expression); 1424 return visit(node.expression);
1380 } 1425 }
1381 1426
1382 ir.Primitive translateClosureCall(ir.Primitive receiver, 1427 ir.Primitive translateClosureCall(ir.Primitive receiver,
1383 Selector closureSelector, 1428 Selector closureSelector,
1384 ast.NodeList arguments) { 1429 ast.NodeList arguments) {
1385 Selector namedCallSelector = new Selector(closureSelector.kind, 1430 Selector namedCallSelector = new Selector(closureSelector.kind,
1386 "call", 1431 "call",
1387 closureSelector.library, 1432 closureSelector.library,
1388 closureSelector.argumentCount, 1433 closureSelector.argumentCount,
1389 closureSelector.namedArguments); 1434 closureSelector.namedArguments);
1390 List<ir.Primitive> args = arguments.nodes.mapToList(visit, growable:false); 1435 List<ir.Primitive> args = arguments.nodes.mapToList(visit, growable:false);
1391 return continueWithExpression( 1436 return irBuilder.continueWithExpression(
1392 (k) => new ir.InvokeMethod(receiver, namedCallSelector, k, args)); 1437 (k) => new ir.InvokeMethod(receiver, namedCallSelector, k, args));
1393 } 1438 }
1394 1439
1395 ir.Primitive visitClosureSend(ast.Send node) { 1440 ir.Primitive visitClosureSend(ast.Send node) {
1396 assert(isOpen); 1441 assert(irBuilder.isOpen);
1397 Element element = elements[node]; 1442 Element element = elements[node];
1398 ir.Primitive closureTarget; 1443 ir.Primitive closureTarget;
1399 if (element == null) { 1444 if (element == null) {
1400 closureTarget = visit(node.selector); 1445 closureTarget = visit(node.selector);
1401 } else if (isClosureVariable(element)) { 1446 } else if (isClosureVariable(element)) {
1402 LocalElement local = element; 1447 LocalElement local = element;
1403 closureTarget = new ir.GetClosureVariable(local); 1448 closureTarget = new ir.GetClosureVariable(local);
1404 add(new ir.LetPrim(closureTarget)); 1449 irBuilder.add(new ir.LetPrim(closureTarget));
1405 } else { 1450 } else {
1406 assert(Elements.isLocal(element)); 1451 assert(Elements.isLocal(element));
1407 closureTarget = environment.lookup(element); 1452 closureTarget = irBuilder.environment.lookup(element);
1408 } 1453 }
1409 Selector closureSelector = elements.getSelector(node); 1454 Selector closureSelector = elements.getSelector(node);
1410 return translateClosureCall(closureTarget, closureSelector, 1455 return translateClosureCall(closureTarget, closureSelector,
1411 node.argumentsNode); 1456 node.argumentsNode);
1412 } 1457 }
1413 1458
1414 /// If [node] is null, returns this. 1459 /// If [node] is null, returns this.
1415 /// If [node] is super, returns null (for special handling) 1460 /// If [node] is super, returns null (for special handling)
1416 /// Otherwise visits [node] and returns the result. 1461 /// Otherwise visits [node] and returns the result.
1417 ir.Primitive visitReceiver(ast.Expression node) { 1462 ir.Primitive visitReceiver(ast.Expression node) {
1418 if (node == null) return lookupThis(); 1463 if (node == null) return lookupThis();
1419 if (node.isSuper()) return null; 1464 if (node.isSuper()) return null;
1420 return visit(node); 1465 return visit(node);
1421 } 1466 }
1422 1467
1423 /// Makes an [InvokeMethod] unless [node.receiver.isSuper()], in that case 1468 /// Makes an [InvokeMethod] unless [node.receiver.isSuper()], in that case
1424 /// makes an [InvokeSuperMethod] ignoring [receiver]. 1469 /// makes an [InvokeSuperMethod] ignoring [receiver].
1425 ir.Expression createDynamicInvoke(ast.Send node, 1470 ir.Expression createDynamicInvoke(ast.Send node,
1426 Selector selector, 1471 Selector selector,
1427 ir.Definition receiver, 1472 ir.Definition receiver,
1428 ir.Continuation k, 1473 ir.Continuation k,
1429 List<ir.Definition> arguments) { 1474 List<ir.Definition> arguments) {
1430 return node != null && node.receiver != null && node.receiver.isSuper() 1475 return node != null && node.receiver != null && node.receiver.isSuper()
1431 ? new ir.InvokeSuperMethod(selector, k, arguments) 1476 ? new ir.InvokeSuperMethod(selector, k, arguments)
1432 : new ir.InvokeMethod(receiver, selector, k, arguments); 1477 : new ir.InvokeMethod(receiver, selector, k, arguments);
1433 } 1478 }
1434 1479
1435 ir.Primitive visitDynamicSend(ast.Send node) { 1480 ir.Primitive visitDynamicSend(ast.Send node) {
1436 assert(isOpen); 1481 assert(irBuilder.isOpen);
1437 Selector selector = elements.getSelector(node); 1482 Selector selector = elements.getSelector(node);
1438 ir.Primitive receiver = visitReceiver(node.receiver); 1483 ir.Primitive receiver = visitReceiver(node.receiver);
1439 List<ir.Primitive> arguments = new List<ir.Primitive>(); 1484 List<ir.Primitive> arguments = new List<ir.Primitive>();
1440 for (ast.Node n in node.arguments) { 1485 for (ast.Node n in node.arguments) {
1441 arguments.add(visit(n)); 1486 arguments.add(visit(n));
1442 } 1487 }
1443 return continueWithExpression( 1488 return irBuilder.continueWithExpression(
1444 (k) => createDynamicInvoke(node, selector, receiver, k, arguments)); 1489 (k) => createDynamicInvoke(node, selector, receiver, k, arguments));
1445 } 1490 }
1446 1491
1447 _GetterElements translateGetter(ast.Send node, Selector selector) { 1492 _GetterElements translateGetter(ast.Send node, Selector selector) {
1448 Element element = elements[node]; 1493 Element element = elements[node];
1449 ir.Primitive result; 1494 ir.Primitive result;
1450 ir.Primitive receiver; 1495 ir.Primitive receiver;
1451 ir.Primitive index; 1496 ir.Primitive index;
1452 1497
1453 if (element != null && element.isConst) { 1498 if (element != null && element.isConst) {
1454 // Reference to constant local, top-level or static field 1499 // Reference to constant local, top-level or static field
1455 result = translateConstant(node); 1500 result = translateConstant(node);
1456 } else if (isClosureVariable(element)) { 1501 } else if (isClosureVariable(element)) {
1457 LocalElement local = element; 1502 LocalElement local = element;
1458 result = new ir.GetClosureVariable(local); 1503 result = new ir.GetClosureVariable(local);
1459 add(new ir.LetPrim(result)); 1504 irBuilder.add(new ir.LetPrim(result));
1460 } else if (Elements.isLocal(element)) { 1505 } else if (Elements.isLocal(element)) {
1461 // Reference to local variable 1506 // Reference to local variable
1462 result = buildGetLocal(element); 1507 result = irBuilder.buildGetLocal(element);
1463 } else if (element == null || 1508 } else if (element == null ||
1464 Elements.isInstanceField(element) || 1509 Elements.isInstanceField(element) ||
1465 Elements.isInstanceMethod(element) || 1510 Elements.isInstanceMethod(element) ||
1466 selector.isIndex || 1511 selector.isIndex ||
1467 // TODO(johnniwinther): clean up semantics of resolution. 1512 // TODO(johnniwinther): clean up semantics of resolution.
1468 node.isSuperCall) { 1513 node.isSuperCall) {
1469 // Dynamic dispatch to a getter. Sometimes resolution will suggest a 1514 // Dynamic dispatch to a getter. Sometimes resolution will suggest a
1470 // target element, but in these cases we must still emit a dynamic 1515 // target element, but in these cases we must still emit a dynamic
1471 // dispatch. The target element may be an instance method in case we are 1516 // dispatch. The target element may be an instance method in case we are
1472 // converting a method to a function object. 1517 // converting a method to a function object.
1473 1518
1474 receiver = visitReceiver(node.receiver); 1519 receiver = visitReceiver(node.receiver);
1475 List<ir.Primitive> arguments = new List<ir.Primitive>(); 1520 List<ir.Primitive> arguments = new List<ir.Primitive>();
1476 if (selector.isIndex) { 1521 if (selector.isIndex) {
1477 index = visit(node.arguments.head); 1522 index = visit(node.arguments.head);
1478 arguments.add(index); 1523 arguments.add(index);
1479 } 1524 }
1480 1525
1481 assert(selector.kind == SelectorKind.GETTER || 1526 assert(selector.kind == SelectorKind.GETTER ||
1482 selector.kind == SelectorKind.INDEX); 1527 selector.kind == SelectorKind.INDEX);
1483 result = continueWithExpression( 1528 result = irBuilder.continueWithExpression(
1484 (k) => createDynamicInvoke(node, selector, receiver, k, arguments)); 1529 (k) => createDynamicInvoke(node, selector, receiver, k, arguments));
1485 } else if (element.isField || element.isGetter || element.isErroneous || 1530 } else if (element.isField || element.isGetter || element.isErroneous ||
1486 element.isSetter) { 1531 element.isSetter) {
1487 // TODO(johnniwinther): Change handling of setter selectors. 1532 // TODO(johnniwinther): Change handling of setter selectors.
1488 // Access to a static field or getter (non-static case handled above). 1533 // Access to a static field or getter (non-static case handled above).
1489 // Even if there is only a setter, we compile as if it was a getter, 1534 // Even if there is only a setter, we compile as if it was a getter,
1490 // so the vm can fail at runtime. 1535 // so the vm can fail at runtime.
1491 assert(selector.kind == SelectorKind.GETTER || 1536 assert(selector.kind == SelectorKind.GETTER ||
1492 selector.kind == SelectorKind.SETTER); 1537 selector.kind == SelectorKind.SETTER);
1493 result = buildGetStatic(element, selector); 1538 result = irBuilder.buildGetStatic(element, selector);
1494 } else if (Elements.isStaticOrTopLevelFunction(element)) { 1539 } else if (Elements.isStaticOrTopLevelFunction(element)) {
1495 // Convert a top-level or static function to a function object. 1540 // Convert a top-level or static function to a function object.
1496 result = translateConstant(node); 1541 result = translateConstant(node);
1497 } else { 1542 } else {
1498 throw "Unexpected SendSet getter: $node, $element"; 1543 throw "Unexpected SendSet getter: $node, $element";
1499 } 1544 }
1500 return new _GetterElements( 1545 return new _GetterElements(
1501 result: result,index: index, receiver: receiver); 1546 result: result,index: index, receiver: receiver);
1502 } 1547 }
1503 1548
1504 ir.Primitive visitGetterSend(ast.Send node) { 1549 ir.Primitive visitGetterSend(ast.Send node) {
1505 assert(isOpen); 1550 assert(irBuilder.isOpen);
1506 return translateGetter(node, elements.getSelector(node)).result; 1551 return translateGetter(node, elements.getSelector(node)).result;
1507 1552
1508 } 1553 }
1509 1554
1510 ir.Primitive buildNegation(ir.Primitive condition) { 1555 ir.Primitive buildNegation(ir.Primitive condition) {
1511 // ! e is translated as e ? false : true 1556 // ! e is translated as e ? false : true
1512 1557
1513 // Add a continuation parameter for the result of the expression. 1558 // Add a continuation parameter for the result of the expression.
1514 ir.Parameter resultParameter = new ir.Parameter(null); 1559 ir.Parameter resultParameter = new ir.Parameter(null);
1515 1560
1516 ir.Continuation joinContinuation = new ir.Continuation([resultParameter]); 1561 ir.Continuation joinContinuation = new ir.Continuation([resultParameter]);
1517 ir.Continuation thenContinuation = new ir.Continuation([]); 1562 ir.Continuation thenContinuation = new ir.Continuation([]);
1518 ir.Continuation elseContinuation = new ir.Continuation([]); 1563 ir.Continuation elseContinuation = new ir.Continuation([]);
1519 1564
1520 ir.Constant trueConstant = makePrimConst(constantSystem.createBool(true)); 1565 ir.Constant trueConstant = irBuilder.makePrimConst(
1521 ir.Constant falseConstant = makePrimConst(constantSystem.createBool(false)); 1566 irBuilder.state.constantSystem.createBool(true));
1567 ir.Constant falseConstant = irBuilder.makePrimConst(
1568 irBuilder.state.constantSystem.createBool(false));
1522 1569
1523 thenContinuation.body = new ir.LetPrim(falseConstant) 1570 thenContinuation.body = new ir.LetPrim(falseConstant)
1524 ..plug(new ir.InvokeContinuation(joinContinuation, [falseConstant])); 1571 ..plug(new ir.InvokeContinuation(joinContinuation, [falseConstant]));
1525 elseContinuation.body = new ir.LetPrim(trueConstant) 1572 elseContinuation.body = new ir.LetPrim(trueConstant)
1526 ..plug(new ir.InvokeContinuation(joinContinuation, [trueConstant])); 1573 ..plug(new ir.InvokeContinuation(joinContinuation, [trueConstant]));
1527 1574
1528 add(new ir.LetCont(joinContinuation, 1575 irBuilder.add(new ir.LetCont(joinContinuation,
1529 new ir.LetCont(thenContinuation, 1576 new ir.LetCont(thenContinuation,
1530 new ir.LetCont(elseContinuation, 1577 new ir.LetCont(elseContinuation,
1531 new ir.Branch(new ir.IsTrue(condition), 1578 new ir.Branch(new ir.IsTrue(condition),
1532 thenContinuation, 1579 thenContinuation,
1533 elseContinuation))))); 1580 elseContinuation)))));
1534 return resultParameter; 1581 return resultParameter;
1535 } 1582 }
1536 1583
1537 ir.Primitive translateLogicalOperator(ast.Operator op, 1584 ir.Primitive translateLogicalOperator(ast.Operator op,
1538 ast.Expression left, 1585 ast.Expression left,
1539 ast.Expression right) { 1586 ast.Expression right) {
1540 // e0 && e1 is translated as if e0 ? (e1 == true) : false. 1587 // e0 && e1 is translated as if e0 ? (e1 == true) : false.
1541 // e0 || e1 is translated as if e0 ? true : (e1 == true). 1588 // e0 || e1 is translated as if e0 ? true : (e1 == true).
1542 // The translation must convert both e0 and e1 to booleans and handle 1589 // The translation must convert both e0 and e1 to booleans and handle
1543 // local variable assignments in e1. 1590 // local variable assignments in e1.
1544 1591
1545 ir.Primitive leftValue = visit(left); 1592 ir.Primitive leftValue = visit(left);
1546 IrBuilderVisitor rightBuilder = new IrBuilderVisitor.delimited(this); 1593 IrBuilder rightBuilder = new IrBuilder.delimited(irBuilder);
1547 ir.Primitive rightValue = rightBuilder.visit(right); 1594 ir.Primitive rightValue =
1595 withBuilder(rightBuilder, () => visit(right));
1548 // A dummy empty target for the branch on the left subexpression branch. 1596 // A dummy empty target for the branch on the left subexpression branch.
1549 // This enables using the same infrastructure for join-point continuations 1597 // This enables using the same infrastructure for join-point continuations
1550 // as in visitIf and visitConditional. It will hold a definition of the 1598 // as in visitIf and visitConditional. It will hold a definition of the
1551 // appropriate constant and an invocation of the join-point continuation. 1599 // appropriate constant and an invocation of the join-point continuation.
1552 IrBuilderVisitor emptyBuilder = new IrBuilderVisitor.delimited(this); 1600 IrBuilder emptyBuilder = new IrBuilder.delimited(irBuilder);
1553 // Dummy empty targets for right true and right false. They hold 1601 // Dummy empty targets for right true and right false. They hold
1554 // definitions of the appropriate constant and an invocation of the 1602 // definitions of the appropriate constant and an invocation of the
1555 // join-point continuation. 1603 // join-point continuation.
1556 IrBuilderVisitor rightTrueBuilder = new IrBuilderVisitor.delimited(rightBuil der); 1604 IrBuilder rightTrueBuilder = new IrBuilder.delimited(rightBuilder);
1557 IrBuilderVisitor rightFalseBuilder = new IrBuilderVisitor.delimited(rightBui lder); 1605 IrBuilder rightFalseBuilder = new IrBuilder.delimited(rightBuilder);
1558 1606
1559 // If we don't evaluate the right subexpression, the value of the whole 1607 // If we don't evaluate the right subexpression, the value of the whole
1560 // expression is this constant. 1608 // expression is this constant.
1561 ir.Constant leftBool = emptyBuilder.makePrimConst( 1609 ir.Constant leftBool = emptyBuilder.makePrimConst(
1562 constantSystem.createBool(op.source == '||')); 1610 emptyBuilder.state.constantSystem.createBool(op.source == '||'));
1563 // If we do evaluate the right subexpression, the value of the expression 1611 // If we do evaluate the right subexpression, the value of the expression
1564 // is a true or false constant. 1612 // is a true or false constant.
1565 ir.Constant rightTrue = rightTrueBuilder.makePrimConst( 1613 ir.Constant rightTrue = rightTrueBuilder.makePrimConst(
1566 constantSystem.createBool(true)); 1614 rightTrueBuilder.state.constantSystem.createBool(true));
1567 ir.Constant rightFalse = rightFalseBuilder.makePrimConst( 1615 ir.Constant rightFalse = rightFalseBuilder.makePrimConst(
1568 constantSystem.createBool(false)); 1616 rightFalseBuilder.state.constantSystem.createBool(false));
1569 emptyBuilder.add(new ir.LetPrim(leftBool)); 1617 emptyBuilder.add(new ir.LetPrim(leftBool));
1570 rightTrueBuilder.add(new ir.LetPrim(rightTrue)); 1618 rightTrueBuilder.add(new ir.LetPrim(rightTrue));
1571 rightFalseBuilder.add(new ir.LetPrim(rightFalse)); 1619 rightFalseBuilder.add(new ir.LetPrim(rightFalse));
1572 1620
1573 // Treat the result values as named values in the environment, so they 1621 // Treat the result values as named values in the environment, so they
1574 // will be treated as arguments to the join-point continuation. 1622 // will be treated as arguments to the join-point continuation.
1575 assert(environment.length == emptyBuilder.environment.length); 1623 assert(irBuilder.environment.length == emptyBuilder.environment.length);
1576 assert(environment.length == rightTrueBuilder.environment.length); 1624 assert(irBuilder.environment.length == rightTrueBuilder.environment.length);
1577 assert(environment.length == rightFalseBuilder.environment.length); 1625 assert(irBuilder.environment.length ==
1626 rightFalseBuilder.environment.length);
1578 emptyBuilder.environment.extend(null, leftBool); 1627 emptyBuilder.environment.extend(null, leftBool);
1579 rightTrueBuilder.environment.extend(null, rightTrue); 1628 rightTrueBuilder.environment.extend(null, rightTrue);
1580 rightFalseBuilder.environment.extend(null, rightFalse); 1629 rightFalseBuilder.environment.extend(null, rightFalse);
1581 1630
1582 // Wire up two continuations for the left subexpression, two continuations 1631 // Wire up two continuations for the left subexpression, two continuations
1583 // for the right subexpression, and a three-way join continuation. 1632 // for the right subexpression, and a three-way join continuation.
1584 JumpCollector jumps = new JumpCollector(null); 1633 JumpCollector jumps = new JumpCollector(null);
1585 jumps.addJump(emptyBuilder); 1634 jumps.addJump(emptyBuilder);
1586 jumps.addJump(rightTrueBuilder); 1635 jumps.addJump(rightTrueBuilder);
1587 jumps.addJump(rightFalseBuilder); 1636 jumps.addJump(rightFalseBuilder);
1588 ir.Continuation joinContinuation = 1637 ir.Continuation joinContinuation =
1589 createJoin(environment.length + 1, jumps); 1638 createJoin(irBuilder.environment.length + 1, jumps);
1590 ir.Continuation leftTrueContinuation = new ir.Continuation([]); 1639 ir.Continuation leftTrueContinuation = new ir.Continuation([]);
1591 ir.Continuation leftFalseContinuation = new ir.Continuation([]); 1640 ir.Continuation leftFalseContinuation = new ir.Continuation([]);
1592 ir.Continuation rightTrueContinuation = new ir.Continuation([]); 1641 ir.Continuation rightTrueContinuation = new ir.Continuation([]);
1593 ir.Continuation rightFalseContinuation = new ir.Continuation([]); 1642 ir.Continuation rightFalseContinuation = new ir.Continuation([]);
1594 rightTrueContinuation.body = rightTrueBuilder._root; 1643 rightTrueContinuation.body = rightTrueBuilder._root;
1595 rightFalseContinuation.body = rightFalseBuilder._root; 1644 rightFalseContinuation.body = rightFalseBuilder._root;
1596 // The right subexpression has two continuations. 1645 // The right subexpression has two continuations.
1597 rightBuilder.add( 1646 rightBuilder.add(
1598 new ir.LetCont(rightTrueContinuation, 1647 new ir.LetCont(rightTrueContinuation,
1599 new ir.LetCont(rightFalseContinuation, 1648 new ir.LetCont(rightFalseContinuation,
1600 new ir.Branch(new ir.IsTrue(rightValue), 1649 new ir.Branch(new ir.IsTrue(rightValue),
1601 rightTrueContinuation, 1650 rightTrueContinuation,
1602 rightFalseContinuation)))); 1651 rightFalseContinuation))));
1603 // Depending on the operator, the left subexpression's continuations are 1652 // Depending on the operator, the left subexpression's continuations are
1604 // either the right subexpression or an invocation of the join-point 1653 // either the right subexpression or an invocation of the join-point
1605 // continuation. 1654 // continuation.
1606 if (op.source == '&&') { 1655 if (op.source == '&&') {
1607 leftTrueContinuation.body = rightBuilder._root; 1656 leftTrueContinuation.body = rightBuilder._root;
1608 leftFalseContinuation.body = emptyBuilder._root; 1657 leftFalseContinuation.body = emptyBuilder._root;
1609 } else { 1658 } else {
1610 leftTrueContinuation.body = emptyBuilder._root; 1659 leftTrueContinuation.body = emptyBuilder._root;
1611 leftFalseContinuation.body = rightBuilder._root; 1660 leftFalseContinuation.body = rightBuilder._root;
1612 } 1661 }
1613 1662
1614 add(new ir.LetCont(joinContinuation, 1663 irBuilder.add(new ir.LetCont(joinContinuation,
1615 new ir.LetCont(leftTrueContinuation, 1664 new ir.LetCont(leftTrueContinuation,
1616 new ir.LetCont(leftFalseContinuation, 1665 new ir.LetCont(leftFalseContinuation,
1617 new ir.Branch(new ir.IsTrue(leftValue), 1666 new ir.Branch(new ir.IsTrue(leftValue),
1618 leftTrueContinuation, 1667 leftTrueContinuation,
1619 leftFalseContinuation))))); 1668 leftFalseContinuation)))));
1620 // There is always a join parameter for the result value, because it 1669 // There is always a join parameter for the result value, because it
1621 // is different on at least two paths. 1670 // is different on at least two paths.
1622 return joinContinuation.parameters.last; 1671 return joinContinuation.parameters.last;
1623 } 1672 }
1624 1673
1625 ir.Primitive visitOperatorSend(ast.Send node) { 1674 ir.Primitive visitOperatorSend(ast.Send node) {
1626 assert(isOpen); 1675 assert(irBuilder.isOpen);
1627 ast.Operator op = node.selector; 1676 ast.Operator op = node.selector;
1628 if (isUserDefinableOperator(op.source)) { 1677 if (isUserDefinableOperator(op.source)) {
1629 return visitDynamicSend(node); 1678 return visitDynamicSend(node);
1630 } 1679 }
1631 if (op.source == '&&' || op.source == '||') { 1680 if (op.source == '&&' || op.source == '||') {
1632 assert(node.receiver != null); 1681 assert(node.receiver != null);
1633 assert(!node.arguments.isEmpty); 1682 assert(!node.arguments.isEmpty);
1634 assert(node.arguments.tail.isEmpty); 1683 assert(node.arguments.tail.isEmpty);
1635 return translateLogicalOperator(op, node.receiver, node.arguments.head); 1684 return translateLogicalOperator(op, node.receiver, node.arguments.head);
1636 } 1685 }
1637 if (op.source == "!") { 1686 if (op.source == "!") {
1638 assert(node.receiver != null); 1687 assert(node.receiver != null);
1639 assert(node.arguments.isEmpty); 1688 assert(node.arguments.isEmpty);
1640 return buildNegation(visit(node.receiver)); 1689 return buildNegation(visit(node.receiver));
1641 } 1690 }
1642 if (op.source == "!=") { 1691 if (op.source == "!=") {
1643 assert(node.receiver != null); 1692 assert(node.receiver != null);
1644 assert(!node.arguments.isEmpty); 1693 assert(!node.arguments.isEmpty);
1645 assert(node.arguments.tail.isEmpty); 1694 assert(node.arguments.tail.isEmpty);
1646 return buildNegation(visitDynamicSend(node)); 1695 return buildNegation(visitDynamicSend(node));
1647 } 1696 }
1648 assert(invariant(node, op.source == "is" || op.source == "as", 1697 assert(invariant(node, op.source == "is" || op.source == "as",
1649 message: "unexpected operator $op")); 1698 message: "unexpected operator $op"));
1650 DartType type = elements.getType(node.typeAnnotationFromIsCheckOrCast); 1699 DartType type = elements.getType(node.typeAnnotationFromIsCheckOrCast);
1651 ir.Primitive receiver = visit(node.receiver); 1700 ir.Primitive receiver = visit(node.receiver);
1652 ir.Primitive check = continueWithExpression( 1701 ir.Primitive check = irBuilder.continueWithExpression(
1653 (k) => new ir.TypeOperator(op.source, receiver, type, k)); 1702 (k) => new ir.TypeOperator(op.source, receiver, type, k));
1654 return node.isIsNotCheck ? buildNegation(check) : check; 1703 return node.isIsNotCheck ? buildNegation(check) : check;
1655 } 1704 }
1656 1705
1657 // Build(StaticSend(f, arguments), C) = C[C'[InvokeStatic(f, xs)]] 1706 // Build(StaticSend(f, arguments), C) = C[C'[InvokeStatic(f, xs)]]
1658 // where (C', xs) = arguments.fold(Build, C) 1707 // where (C', xs) = arguments.fold(Build, C)
1659 ir.Primitive visitStaticSend(ast.Send node) { 1708 ir.Primitive visitStaticSend(ast.Send node) {
1660 assert(isOpen); 1709 assert(irBuilder.isOpen);
1661 Element element = elements[node]; 1710 Element element = elements[node];
1662 assert(!element.isConstructor); 1711 assert(!element.isConstructor);
1663 // TODO(lry): support foreign functions. 1712 // TODO(lry): support foreign functions.
1664 if (element.isForeign(compiler.backend)) { 1713 if (element.isForeign(compiler.backend)) {
1665 return giveup(node, 'StaticSend: foreign'); 1714 return giveup(node, 'StaticSend: foreign');
1666 } 1715 }
1667 1716
1668 Selector selector = elements.getSelector(node); 1717 Selector selector = elements.getSelector(node);
1669 1718
1670 // TODO(lry): support default arguments, need support for locals. 1719 // TODO(lry): support default arguments, need support for locals.
1671 List<ir.Definition> arguments = node.arguments.mapToList(visit, 1720 List<ir.Definition> arguments = node.arguments.mapToList(visit,
1672 growable:false); 1721 growable:false);
1673 return buildStaticInvocation(element, selector, arguments); 1722 return irBuilder.buildStaticInvocation(element, selector, arguments);
1674 } 1723 }
1675 1724
1676 1725
1677 ir.Primitive visitSuperSend(ast.Send node) { 1726 ir.Primitive visitSuperSend(ast.Send node) {
1678 assert(isOpen); 1727 assert(irBuilder.isOpen);
1679 if (node.isPropertyAccess) { 1728 if (node.isPropertyAccess) {
1680 return visitGetterSend(node); 1729 return visitGetterSend(node);
1681 } else { 1730 } else {
1682 return visitDynamicSend(node); 1731 return visitDynamicSend(node);
1683 } 1732 }
1684 } 1733 }
1685 1734
1686 visitTypePrefixSend(ast.Send node) { 1735 visitTypePrefixSend(ast.Send node) {
1687 compiler.internalError(node, "visitTypePrefixSend should not be called."); 1736 compiler.internalError(node, "visitTypePrefixSend should not be called.");
1688 } 1737 }
1689 1738
1690 ir.Primitive visitTypeLiteralSend(ast.Send node) { 1739 ir.Primitive visitTypeLiteralSend(ast.Send node) {
1691 assert(isOpen); 1740 assert(irBuilder.isOpen);
1692 // If the user is trying to invoke the type literal or variable, 1741 // If the user is trying to invoke the type literal or variable,
1693 // it must be treated as a function call. 1742 // it must be treated as a function call.
1694 if (node.argumentsNode != null) { 1743 if (node.argumentsNode != null) {
1695 // TODO(sigurdm): Handle this to match proposed semantics of issue #19725. 1744 // TODO(sigurdm): Handle this to match proposed semantics of issue #19725.
1696 return giveup(node, 'Type literal invoked as function'); 1745 return giveup(node, 'Type literal invoked as function');
1697 } 1746 }
1698 1747
1699 DartType type = elements.getTypeLiteralType(node); 1748 DartType type = elements.getTypeLiteralType(node);
1700 if (type is TypeVariableType) { 1749 if (type is TypeVariableType) {
1701 ir.Primitive prim = new ir.ReifyTypeVar(type.element); 1750 ir.Primitive prim = new ir.ReifyTypeVar(type.element);
1702 add(new ir.LetPrim(prim)); 1751 irBuilder.add(new ir.LetPrim(prim));
1703 return prim; 1752 return prim;
1704 } else { 1753 } else {
1705 return translateConstant(node); 1754 return translateConstant(node);
1706 } 1755 }
1707 } 1756 }
1708 1757
1709 /// True if [element] is a local variable, local function, or parameter that 1758 /// True if [element] is a local variable, local function, or parameter that
1710 /// is accessed from an inner function. Recursive self-references in a local 1759 /// is accessed from an inner function. Recursive self-references in a local
1711 /// function count as closure accesses. 1760 /// function count as closure accesses.
1712 /// 1761 ///
1713 /// If `true`, [element] is a [LocalElement]. 1762 /// If `true`, [element] is a [LocalElement].
1714 bool isClosureVariable(Element element) { 1763 bool isClosureVariable(Element element) {
1715 return closureLocals.isClosureVariable(element); 1764 return irBuilder.state.closureLocals.contains(element);
1716 } 1765 }
1717 1766
1718 void setLocal(Element element, ir.Primitive valueToStore) { 1767 void setLocal(Element element, ir.Primitive valueToStore) {
1719 if (isClosureVariable(element)) { 1768 if (isClosureVariable(element)) {
1720 LocalElement local = element; 1769 LocalElement local = element;
1721 add(new ir.SetClosureVariable(local, valueToStore)); 1770 irBuilder.add(new ir.SetClosureVariable(local, valueToStore));
1722 } else { 1771 } else {
1723 valueToStore.useElementAsHint(element); 1772 valueToStore.useElementAsHint(element);
1724 environment.update(element, valueToStore); 1773 irBuilder.environment.update(element, valueToStore);
1725 } 1774 }
1726 } 1775 }
1727 1776
1728 void setStatic(Element element, 1777 void setStatic(Element element,
1729 Selector selector, 1778 Selector selector,
1730 ir.Primitive valueToStore) { 1779 ir.Primitive valueToStore) {
1731 assert(element.isErroneous || element.isField || element.isSetter); 1780 assert(element.isErroneous || element.isField || element.isSetter);
1732 continueWithExpression( 1781 irBuilder.continueWithExpression(
1733 (k) => new ir.InvokeStatic(element, selector, k, [valueToStore])); 1782 (k) => new ir.InvokeStatic(element, selector, k, [valueToStore]));
1734 } 1783 }
1735 1784
1736 void setDynamic(ast.Node node, 1785 void setDynamic(ast.Node node,
1737 ir.Primitive receiver, Selector selector, 1786 ir.Primitive receiver, Selector selector,
1738 ir.Primitive valueToStore) { 1787 ir.Primitive valueToStore) {
1739 List<ir.Definition> arguments = [valueToStore]; 1788 List<ir.Definition> arguments = [valueToStore];
1740 continueWithExpression( 1789 irBuilder.continueWithExpression(
1741 (k) => createDynamicInvoke(node, selector, receiver, k, arguments)); 1790 (k) => createDynamicInvoke(node, selector, receiver, k, arguments));
1742 } 1791 }
1743 1792
1744 void setIndex(ast.Node node, 1793 void setIndex(ast.Node node,
1745 ir.Primitive receiver, 1794 ir.Primitive receiver,
1746 Selector selector, 1795 Selector selector,
1747 ir.Primitive index, 1796 ir.Primitive index,
1748 ir.Primitive valueToStore) { 1797 ir.Primitive valueToStore) {
1749 List<ir.Definition> arguments = [index, valueToStore]; 1798 List<ir.Definition> arguments = [index, valueToStore];
1750 continueWithExpression( 1799 irBuilder.continueWithExpression(
1751 (k) => createDynamicInvoke(node, selector, receiver, k, arguments)); 1800 (k) => createDynamicInvoke(node, selector, receiver, k, arguments));
1752 } 1801 }
1753 1802
1754 ir.Primitive visitSendSet(ast.SendSet node) { 1803 ir.Primitive visitSendSet(ast.SendSet node) {
1755 assert(isOpen); 1804 assert(irBuilder.isOpen);
1756 Element element = elements[node]; 1805 Element element = elements[node];
1757 ast.Operator op = node.assignmentOperator; 1806 ast.Operator op = node.assignmentOperator;
1758 // For complex operators, this is the result of getting (before assigning) 1807 // For complex operators, this is the result of getting (before assigning)
1759 ir.Primitive originalValue; 1808 ir.Primitive originalValue;
1760 // For []+= style operators, this saves the index. 1809 // For []+= style operators, this saves the index.
1761 ir.Primitive index; 1810 ir.Primitive index;
1762 ir.Primitive receiver; 1811 ir.Primitive receiver;
1763 // This is what gets assigned. 1812 // This is what gets assigned.
1764 ir.Primitive valueToStore; 1813 ir.Primitive valueToStore;
1765 Selector selector = elements.getSelector(node); 1814 Selector selector = elements.getSelector(node);
(...skipping 30 matching lines...) Expand all
1796 assert(ast.Operator.COMPLEX_OPERATORS.contains(op.source)); 1845 assert(ast.Operator.COMPLEX_OPERATORS.contains(op.source));
1797 1846
1798 _GetterElements getterResult = translateGetter(node, getterSelector); 1847 _GetterElements getterResult = translateGetter(node, getterSelector);
1799 index = getterResult.index; 1848 index = getterResult.index;
1800 receiver = getterResult.receiver; 1849 receiver = getterResult.receiver;
1801 originalValue = getterResult.result; 1850 originalValue = getterResult.result;
1802 1851
1803 // Do the modification of the value in getter. 1852 // Do the modification of the value in getter.
1804 ir.Primitive arg; 1853 ir.Primitive arg;
1805 if (ast.Operator.INCREMENT_OPERATORS.contains(op.source)) { 1854 if (ast.Operator.INCREMENT_OPERATORS.contains(op.source)) {
1806 arg = makePrimConst(constantSystem.createInt(1)); 1855 arg = irBuilder.makePrimConst(
1807 add(new ir.LetPrim(arg)); 1856 irBuilder.state.constantSystem.createInt(1));
1857 irBuilder.add(new ir.LetPrim(arg));
1808 } else { 1858 } else {
1809 arg = visit(getAssignArgument()); 1859 arg = visit(getAssignArgument());
1810 } 1860 }
1811 valueToStore = new ir.Parameter(null); 1861 valueToStore = new ir.Parameter(null);
1812 ir.Continuation k = new ir.Continuation([valueToStore]); 1862 ir.Continuation k = new ir.Continuation([valueToStore]);
1813 ir.Expression invoke = 1863 ir.Expression invoke =
1814 new ir.InvokeMethod(originalValue, operatorSelector, k, [arg]); 1864 new ir.InvokeMethod(originalValue, operatorSelector, k, [arg]);
1815 add(new ir.LetCont(k, invoke)); 1865 irBuilder.add(new ir.LetCont(k, invoke));
1816 } 1866 }
1817 1867
1818 if (Elements.isLocal(element)) { 1868 if (Elements.isLocal(element)) {
1819 setLocal(element, valueToStore); 1869 setLocal(element, valueToStore);
1820 } else if ((!node.isSuperCall && Elements.isErroneousElement(element)) || 1870 } else if ((!node.isSuperCall && Elements.isErroneousElement(element)) ||
1821 Elements.isStaticOrTopLevel(element)) { 1871 Elements.isStaticOrTopLevel(element)) {
1822 setStatic(element, elements.getSelector(node), valueToStore); 1872 setStatic(element, elements.getSelector(node), valueToStore);
1823 } else { 1873 } else {
1824 // Setter or index-setter invocation 1874 // Setter or index-setter invocation
1825 Selector selector = elements.getSelector(node); 1875 Selector selector = elements.getSelector(node);
1826 assert(selector.kind == SelectorKind.SETTER || 1876 assert(selector.kind == SelectorKind.SETTER ||
1827 selector.kind == SelectorKind.INDEX); 1877 selector.kind == SelectorKind.INDEX);
1828 if (selector.isIndexSet) { 1878 if (selector.isIndexSet) {
1829 setIndex(node, receiver, selector, index, valueToStore); 1879 setIndex(node, receiver, selector, index, valueToStore);
1830 } else { 1880 } else {
1831 setDynamic(node, receiver, selector, valueToStore); 1881 setDynamic(node, receiver, selector, valueToStore);
1832 } 1882 }
1833 } 1883 }
1834 1884
1835 if (node.isPostfix) { 1885 if (node.isPostfix) {
1836 assert(originalValue != null); 1886 assert(originalValue != null);
1837 return originalValue; 1887 return originalValue;
1838 } else { 1888 } else {
1839 return valueToStore; 1889 return valueToStore;
1840 } 1890 }
1841 } 1891 }
1842 1892
1843 ir.Primitive visitNewExpression(ast.NewExpression node) { 1893 ir.Primitive visitNewExpression(ast.NewExpression node) {
1844 assert(isOpen); 1894 assert(irBuilder.isOpen);
1845 if (node.isConst) { 1895 if (node.isConst) {
1846 return translateConstant(node); 1896 return translateConstant(node);
1847 } 1897 }
1848 FunctionElement element = elements[node.send]; 1898 FunctionElement element = elements[node.send];
1849 Selector selector = elements.getSelector(node.send); 1899 Selector selector = elements.getSelector(node.send);
1850 ast.Node selectorNode = node.send.selector; 1900 ast.Node selectorNode = node.send.selector;
1851 DartType type = elements.getType(node); 1901 DartType type = elements.getType(node);
1852 List<ir.Primitive> args = 1902 List<ir.Primitive> args =
1853 node.send.arguments.mapToList(visit, growable:false); 1903 node.send.arguments.mapToList(visit, growable:false);
1854 return continueWithExpression( 1904 return irBuilder.continueWithExpression(
1855 (k) => new ir.InvokeConstructor(type, element,selector, k, args)); 1905 (k) => new ir.InvokeConstructor(type, element,selector, k, args));
1856 } 1906 }
1857 1907
1858 ir.Primitive visitStringJuxtaposition(ast.StringJuxtaposition node) { 1908 ir.Primitive visitStringJuxtaposition(ast.StringJuxtaposition node) {
1859 assert(isOpen); 1909 assert(irBuilder.isOpen);
1860 ir.Primitive first = visit(node.first); 1910 ir.Primitive first = visit(node.first);
1861 ir.Primitive second = visit(node.second); 1911 ir.Primitive second = visit(node.second);
1862 return continueWithExpression( 1912 return irBuilder.continueWithExpression(
1863 (k) => new ir.ConcatenateStrings(k, [first, second])); 1913 (k) => new ir.ConcatenateStrings(k, [first, second]));
1864 } 1914 }
1865 1915
1866 ir.Primitive visitStringInterpolation(ast.StringInterpolation node) { 1916 ir.Primitive visitStringInterpolation(ast.StringInterpolation node) {
1867 assert(isOpen); 1917 assert(irBuilder.isOpen);
1868 List<ir.Primitive> arguments = []; 1918 List<ir.Primitive> arguments = [];
1869 arguments.add(visitLiteralString(node.string)); 1919 arguments.add(visitLiteralString(node.string));
1870 var it = node.parts.iterator; 1920 var it = node.parts.iterator;
1871 while (it.moveNext()) { 1921 while (it.moveNext()) {
1872 ast.StringInterpolationPart part = it.current; 1922 ast.StringInterpolationPart part = it.current;
1873 arguments.add(visit(part.expression)); 1923 arguments.add(visit(part.expression));
1874 arguments.add(visitLiteralString(part.string)); 1924 arguments.add(visitLiteralString(part.string));
1875 } 1925 }
1876 return continueWithExpression( 1926 return irBuilder.continueWithExpression(
1877 (k) => new ir.ConcatenateStrings(k, arguments)); 1927 (k) => new ir.ConcatenateStrings(k, arguments));
1878 } 1928 }
1879 1929
1880 ir.Primitive translateConstant(ast.Node node, [ConstantExpression constant]) { 1930 ir.Primitive translateConstant(ast.Node node, [ConstantExpression constant]) {
1881 assert(isOpen); 1931 assert(irBuilder.isOpen);
1882 if (constant == null) { 1932 if (constant == null) {
1883 constant = getConstantForNode(node); 1933 constant = getConstantForNode(node);
1884 } 1934 }
1885 ir.Primitive primitive = makeConst(constant); 1935 ir.Primitive primitive = irBuilder.makeConst(constant);
1886 add(new ir.LetPrim(primitive)); 1936 irBuilder.add(new ir.LetPrim(primitive));
1887 return primitive; 1937 return primitive;
1888 } 1938 }
1889 1939
1890 ir.FunctionDefinition makeSubFunction(ast.FunctionExpression node) { 1940 ir.FunctionDefinition makeSubFunction(ast.FunctionExpression node) {
1941 // TODO(johnniwinther): Share the visitor.
1891 return new IrBuilderVisitor(elements, compiler, sourceFile) 1942 return new IrBuilderVisitor(elements, compiler, sourceFile)
1892 .buildFunctionInternal(elements[node]); 1943 .buildFunctionInternal(elements[node]);
1893 } 1944 }
1894 1945
1895 ir.Primitive visitFunctionExpression(ast.FunctionExpression node) { 1946 ir.Primitive visitFunctionExpression(ast.FunctionExpression node) {
1896 FunctionElement element = elements[node]; 1947 FunctionElement element = elements[node];
1897 ir.FunctionDefinition inner = makeSubFunction(node); 1948 ir.FunctionDefinition inner = makeSubFunction(node);
1898 ir.CreateFunction prim = new ir.CreateFunction(inner); 1949 ir.CreateFunction prim = new ir.CreateFunction(inner);
1899 add(new ir.LetPrim(prim)); 1950 irBuilder.add(new ir.LetPrim(prim));
1900 return prim; 1951 return prim;
1901 } 1952 }
1902 1953
1903 ir.Primitive visitFunctionDeclaration(ast.FunctionDeclaration node) { 1954 ir.Primitive visitFunctionDeclaration(ast.FunctionDeclaration node) {
1904 LocalFunctionElement element = elements[node.function]; 1955 LocalFunctionElement element = elements[node.function];
1905 ir.FunctionDefinition inner = makeSubFunction(node.function); 1956 ir.FunctionDefinition inner = makeSubFunction(node.function);
1906 if (isClosureVariable(element)) { 1957 if (isClosureVariable(element)) {
1907 add(new ir.DeclareFunction(element, inner)); 1958 irBuilder.add(new ir.DeclareFunction(element, inner));
1908 } else { 1959 } else {
1909 ir.CreateFunction prim = new ir.CreateFunction(inner); 1960 ir.CreateFunction prim = new ir.CreateFunction(inner);
1910 add(new ir.LetPrim(prim)); 1961 irBuilder.add(new ir.LetPrim(prim));
1911 environment.extend(element, prim); 1962 irBuilder.environment.extend(element, prim);
1912 prim.useElementAsHint(element); 1963 prim.useElementAsHint(element);
1913 } 1964 }
1914 return null; 1965 return null;
1915 } 1966 }
1916 1967
1917 static final String ABORT_IRNODE_BUILDER = "IrNode builder aborted"; 1968 static final String ABORT_IRNODE_BUILDER = "IrNode builder aborted";
1918 1969
1919 dynamic giveup(ast.Node node, [String reason]) { 1970 dynamic giveup(ast.Node node, [String reason]) {
1920 throw ABORT_IRNODE_BUILDER; 1971 throw ABORT_IRNODE_BUILDER;
1921 } 1972 }
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1971 } 2022 }
1972 2023
1973 visitFunctionExpression(ast.FunctionExpression node) { 2024 visitFunctionExpression(ast.FunctionExpression node) {
1974 FunctionElement oldFunction = currentFunction; 2025 FunctionElement oldFunction = currentFunction;
1975 currentFunction = elements[node]; 2026 currentFunction = elements[node];
1976 visit(node.body); 2027 visit(node.body);
1977 currentFunction = oldFunction; 2028 currentFunction = oldFunction;
1978 } 2029 }
1979 2030
1980 } 2031 }
OLDNEW
« no previous file with comments | « pkg/analyzer2dart/lib/src/cps_generator.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698