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

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

Issue 662593003: Support dynamic get/invocation in analyzer2dart. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebased 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/test/end2end_test.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 327 matching lines...) Expand 10 before | Expand all | Expand 10 after
338 IrBuilder.recursive(IrBuilder parent) 338 IrBuilder.recursive(IrBuilder parent)
339 : this.state = parent.state, 339 : this.state = parent.state,
340 this.environment = new Environment.empty() { 340 this.environment = new Environment.empty() {
341 parent.environment.index2variable.forEach(createParameter); 341 parent.environment.index2variable.forEach(createParameter);
342 } 342 }
343 343
344 344
345 bool get isOpen => _root == null || _current != null; 345 bool get isOpen => _root == null || _current != null;
346 346
347 /// Create a parameter for [parameterElement] and add it to the current 347 /// Create a parameter for [parameterElement] and add it to the current
348 /// environment. If [isClosureVariable] marks whether [parameterElement] is 348 /// environment.
349 /// accessed from an inner function. 349 ///
350 /// [isClosureVariable] marks whether [parameterElement] is accessed from an
351 /// inner function.
350 void createParameter(LocalElement parameterElement, 352 void createParameter(LocalElement parameterElement,
351 {bool isClosureVariable: false}) { 353 {bool isClosureVariable: false}) {
352 ir.Parameter parameter = new ir.Parameter(parameterElement); 354 ir.Parameter parameter = new ir.Parameter(parameterElement);
353 _parameters.add(parameter); 355 _parameters.add(parameter);
354 if (isClosureVariable) { 356 if (isClosureVariable) {
355 add(new ir.SetClosureVariable(parameterElement, parameter)); 357 add(new ir.SetClosureVariable(parameterElement, parameter));
356 } else { 358 } else {
357 environment.extend(parameterElement, parameter); 359 environment.extend(parameterElement, parameter);
358 } 360 }
359 } 361 }
360 362
363 /// Add the constant [variableElement] to the environment with [value] as its
364 /// constant value.
361 void declareLocalConstant(LocalVariableElement variableElement, 365 void declareLocalConstant(LocalVariableElement variableElement,
362 ConstantExpression value) { 366 ConstantExpression value) {
363 state.localConstants.add(new ConstDeclaration(variableElement, value)); 367 state.localConstants.add(new ConstDeclaration(variableElement, value));
364 } 368 }
365 369
370 /// Add [variableElement] to the environment with [initialValue] as its
371 /// initial value.
372 ///
373 /// [isClosureVariable] marks whether [variableElement] is accessed from an
374 /// inner function.
366 void declareLocalVariable(LocalVariableElement variableElement, 375 void declareLocalVariable(LocalVariableElement variableElement,
367 {ir.Primitive initialValue, 376 {ir.Primitive initialValue,
368 bool isClosureVariable: false}) { 377 bool isClosureVariable: false}) {
369 assert(isOpen); 378 assert(isOpen);
370 if (initialValue == null) { 379 if (initialValue == null) {
371 // TODO(kmillikin): Consider pooling constants. 380 // TODO(kmillikin): Consider pooling constants.
372 // The initial value is null. 381 // The initial value is null.
373 initialValue = makePrimConst(state.constantSystem.createNull()); 382 initialValue = makePrimConst(state.constantSystem.createNull());
374 add(new ir.LetPrim(initialValue)); 383 add(new ir.LetPrim(initialValue));
375 } 384 }
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
444 return buildPrimConst(state.constantSystem.createNull()); 453 return buildPrimConst(state.constantSystem.createNull());
445 } 454 }
446 455
447 /// Create a string literal. 456 /// Create a string literal.
448 ir.Constant buildStringLiteral(String value) { 457 ir.Constant buildStringLiteral(String value) {
449 return buildPrimConst( 458 return buildPrimConst(
450 state.constantSystem.createString(new ast.DartString.literal(value))); 459 state.constantSystem.createString(new ast.DartString.literal(value)));
451 } 460 }
452 461
453 /// Create a get access of [local]. 462 /// Create a get access of [local].
454 ir.Primitive buildGetLocal(Element local) { 463 ir.Primitive buildLocalGet(Element local) {
455 assert(isOpen); 464 assert(isOpen);
456 return environment.lookup(local); 465 return environment.lookup(local);
457 } 466 }
458 467
459 /// Create a get access of the static [element]. 468 /// Create a get access of the static [element].
460 ir.Primitive buildGetStatic(Element element, Selector selector) { 469 ir.Primitive buildStaticGet(Element element, Selector selector) {
461 assert(isOpen); 470 assert(isOpen);
462 assert(selector.isGetter); 471 assert(selector.isGetter);
463 return continueWithExpression( 472 return continueWithExpression(
464 (k) => new ir.InvokeStatic(element, selector, k, [])); 473 (k) => new ir.InvokeStatic(
474 element, selector, k, const <ir.Definition>[]));
475 }
476
477 /// Create a dynamic get access on [receiver] where the property is defined
478 /// by the getter [selector].
479 ir.Primitive buildDynamicGet(ir.Primitive receiver, Selector selector) {
480 assert(isOpen);
481 assert(selector.isGetter);
482 return continueWithExpression(
483 (k) => new ir.InvokeMethod(
484 receiver, selector, k, const <ir.Definition>[]));
465 } 485 }
466 486
467 /** 487 /**
468 * Add an explicit `return null` for functions that don't have a return 488 * Add an explicit `return null` for functions that don't have a return
469 * statement on each branch. This includes functions with an empty body, 489 * statement on each branch. This includes functions with an empty body,
470 * such as `foo(){ }`. 490 * such as `foo(){ }`.
471 */ 491 */
472 void ensureReturn() { 492 void ensureReturn() {
473 if (!isOpen) return; 493 if (!isOpen) return;
474 ir.Constant constant = makePrimConst(state.constantSystem.createNull()); 494 ir.Constant constant = makePrimConst(state.constantSystem.createNull());
(...skipping 18 matching lines...) Expand all
493 assert(invariant(element, _root == null, 513 assert(invariant(element, _root == null,
494 message: "Non-empty body for abstract method $element: $_root")); 514 message: "Non-empty body for abstract method $element: $_root"));
495 assert(invariant(element, state.localConstants.isEmpty, 515 assert(invariant(element, state.localConstants.isEmpty,
496 message: "Local constants for abstract method $element: " 516 message: "Local constants for abstract method $element: "
497 "${state.localConstants}")); 517 "${state.localConstants}"));
498 return new ir.FunctionDefinition.abstract( 518 return new ir.FunctionDefinition.abstract(
499 element, _parameters, defaults); 519 element, _parameters, defaults);
500 } 520 }
501 } 521 }
502 522
523
524 /// Create a super invocation with method name and arguments structure defined
525 /// by [selector] and argument values defined by [arguments].
526 ir.Primitive buildSuperInvocation(Selector selector,
527 List<ir.Definition> arguments) {
528 assert(isOpen);
529 return continueWithExpression(
530 (k) => new ir.InvokeSuperMethod(selector, k, arguments));
531
532 }
533
534 /// Create a dynamic invocation on [receiver] with method name and arguments
535 /// structure defined by [selector] and argument values defined by
536 /// [arguments].
537 ir.Primitive buildDynamicInvocation(ir.Definition receiver,
538 Selector selector,
539 List<ir.Definition> arguments) {
540 assert(isOpen);
541 return continueWithExpression(
542 (k) => new ir.InvokeMethod(receiver, selector, k, arguments));
543 }
544
503 /// Create a static invocation of [element] with arguments structure defined 545 /// Create a static invocation of [element] with arguments structure defined
504 /// by [selector] and argument values defined by [arguments]. 546 /// by [selector] and argument values defined by [arguments].
505 ir.Primitive buildStaticInvocation(Element element, 547 ir.Primitive buildStaticInvocation(Element element,
506 Selector selector, 548 Selector selector,
507 List<ir.Definition> arguments) { 549 List<ir.Definition> arguments) {
508 return continueWithExpression( 550 return continueWithExpression(
509 (k) => new ir.InvokeStatic(element, selector, k, arguments)); 551 (k) => new ir.InvokeStatic(element, selector, k, arguments));
510 } 552 }
511 553
512 /// Create a return statement `return value;` or `return;` if [value] is 554 /// Create a return statement `return value;` or `return;` if [value] is
(...skipping 965 matching lines...) Expand 10 before | Expand all | Expand 10 after
1478 } 1520 }
1479 1521
1480 ir.Primitive visitDynamicSend(ast.Send node) { 1522 ir.Primitive visitDynamicSend(ast.Send node) {
1481 assert(irBuilder.isOpen); 1523 assert(irBuilder.isOpen);
1482 Selector selector = elements.getSelector(node); 1524 Selector selector = elements.getSelector(node);
1483 ir.Primitive receiver = visitReceiver(node.receiver); 1525 ir.Primitive receiver = visitReceiver(node.receiver);
1484 List<ir.Primitive> arguments = new List<ir.Primitive>(); 1526 List<ir.Primitive> arguments = new List<ir.Primitive>();
1485 for (ast.Node n in node.arguments) { 1527 for (ast.Node n in node.arguments) {
1486 arguments.add(visit(n)); 1528 arguments.add(visit(n));
1487 } 1529 }
1488 return irBuilder.continueWithExpression( 1530 return irBuilder.buildDynamicInvocation(receiver, selector, arguments);
1489 (k) => createDynamicInvoke(node, selector, receiver, k, arguments));
1490 } 1531 }
1491 1532
1492 _GetterElements translateGetter(ast.Send node, Selector selector) { 1533 _GetterElements translateGetter(ast.Send node, Selector selector) {
1493 Element element = elements[node]; 1534 Element element = elements[node];
1494 ir.Primitive result; 1535 ir.Primitive result;
1495 ir.Primitive receiver; 1536 ir.Primitive receiver;
1496 ir.Primitive index; 1537 ir.Primitive index;
1497 1538
1498 if (element != null && element.isConst) { 1539 if (element != null && element.isConst) {
1499 // Reference to constant local, top-level or static field 1540 // Reference to constant local, top-level or static field
1500 result = translateConstant(node); 1541 result = translateConstant(node);
1501 } else if (isClosureVariable(element)) { 1542 } else if (isClosureVariable(element)) {
1502 LocalElement local = element; 1543 LocalElement local = element;
1503 result = new ir.GetClosureVariable(local); 1544 result = new ir.GetClosureVariable(local);
1504 irBuilder.add(new ir.LetPrim(result)); 1545 irBuilder.add(new ir.LetPrim(result));
1505 } else if (Elements.isLocal(element)) { 1546 } else if (Elements.isLocal(element)) {
1506 // Reference to local variable 1547 // Reference to local variable
1507 result = irBuilder.buildGetLocal(element); 1548 result = irBuilder.buildLocalGet(element);
1508 } else if (element == null || 1549 } else if (element == null ||
1509 Elements.isInstanceField(element) || 1550 Elements.isInstanceField(element) ||
1510 Elements.isInstanceMethod(element) || 1551 Elements.isInstanceMethod(element) ||
1511 selector.isIndex || 1552 selector.isIndex ||
1512 // TODO(johnniwinther): clean up semantics of resolution. 1553 // TODO(johnniwinther): clean up semantics of resolution.
1513 node.isSuperCall) { 1554 node.isSuperCall) {
1514 // Dynamic dispatch to a getter. Sometimes resolution will suggest a 1555 // Dynamic dispatch to a getter. Sometimes resolution will suggest a
1515 // target element, but in these cases we must still emit a dynamic 1556 // target element, but in these cases we must still emit a dynamic
1516 // dispatch. The target element may be an instance method in case we are 1557 // dispatch. The target element may be an instance method in case we are
1517 // converting a method to a function object. 1558 // converting a method to a function object.
(...skipping 10 matching lines...) Expand all
1528 result = irBuilder.continueWithExpression( 1569 result = irBuilder.continueWithExpression(
1529 (k) => createDynamicInvoke(node, selector, receiver, k, arguments)); 1570 (k) => createDynamicInvoke(node, selector, receiver, k, arguments));
1530 } else if (element.isField || element.isGetter || element.isErroneous || 1571 } else if (element.isField || element.isGetter || element.isErroneous ||
1531 element.isSetter) { 1572 element.isSetter) {
1532 // TODO(johnniwinther): Change handling of setter selectors. 1573 // TODO(johnniwinther): Change handling of setter selectors.
1533 // Access to a static field or getter (non-static case handled above). 1574 // Access to a static field or getter (non-static case handled above).
1534 // Even if there is only a setter, we compile as if it was a getter, 1575 // Even if there is only a setter, we compile as if it was a getter,
1535 // so the vm can fail at runtime. 1576 // so the vm can fail at runtime.
1536 assert(selector.kind == SelectorKind.GETTER || 1577 assert(selector.kind == SelectorKind.GETTER ||
1537 selector.kind == SelectorKind.SETTER); 1578 selector.kind == SelectorKind.SETTER);
1538 result = irBuilder.buildGetStatic(element, selector); 1579 result = irBuilder.buildStaticGet(element, selector);
1539 } else if (Elements.isStaticOrTopLevelFunction(element)) { 1580 } else if (Elements.isStaticOrTopLevelFunction(element)) {
1540 // Convert a top-level or static function to a function object. 1581 // Convert a top-level or static function to a function object.
1541 result = translateConstant(node); 1582 result = translateConstant(node);
1542 } else { 1583 } else {
1543 throw "Unexpected SendSet getter: $node, $element"; 1584 throw "Unexpected SendSet getter: $node, $element";
1544 } 1585 }
1545 return new _GetterElements( 1586 return new _GetterElements(
1546 result: result,index: index, receiver: receiver); 1587 result: result,index: index, receiver: receiver);
1547 } 1588 }
1548 1589
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
1721 growable:false); 1762 growable:false);
1722 return irBuilder.buildStaticInvocation(element, selector, arguments); 1763 return irBuilder.buildStaticInvocation(element, selector, arguments);
1723 } 1764 }
1724 1765
1725 1766
1726 ir.Primitive visitSuperSend(ast.Send node) { 1767 ir.Primitive visitSuperSend(ast.Send node) {
1727 assert(irBuilder.isOpen); 1768 assert(irBuilder.isOpen);
1728 if (node.isPropertyAccess) { 1769 if (node.isPropertyAccess) {
1729 return visitGetterSend(node); 1770 return visitGetterSend(node);
1730 } else { 1771 } else {
1731 return visitDynamicSend(node); 1772 Selector selector = elements.getSelector(node);
1773 List<ir.Primitive> arguments = new List<ir.Primitive>();
floitsch 2014/10/17 11:34:48 = node.arguments.mapToList(visit, growable: false)
Johnni Winther 2014/10/17 11:54:30 Done.
1774 for (ast.Node n in node.arguments) {
1775 arguments.add(visit(n));
1776 }
1777 return irBuilder.buildSuperInvocation(selector, arguments);
1732 } 1778 }
1733 } 1779 }
1734 1780
1735 visitTypePrefixSend(ast.Send node) { 1781 visitTypePrefixSend(ast.Send node) {
1736 compiler.internalError(node, "visitTypePrefixSend should not be called."); 1782 compiler.internalError(node, "visitTypePrefixSend should not be called.");
1737 } 1783 }
1738 1784
1739 ir.Primitive visitTypeLiteralSend(ast.Send node) { 1785 ir.Primitive visitTypeLiteralSend(ast.Send node) {
1740 assert(irBuilder.isOpen); 1786 assert(irBuilder.isOpen);
1741 // If the user is trying to invoke the type literal or variable, 1787 // If the user is trying to invoke the type literal or variable,
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after
2022 } 2068 }
2023 2069
2024 visitFunctionExpression(ast.FunctionExpression node) { 2070 visitFunctionExpression(ast.FunctionExpression node) {
2025 FunctionElement oldFunction = currentFunction; 2071 FunctionElement oldFunction = currentFunction;
2026 currentFunction = elements[node]; 2072 currentFunction = elements[node];
2027 visit(node.body); 2073 visit(node.body);
2028 currentFunction = oldFunction; 2074 currentFunction = oldFunction;
2029 } 2075 }
2030 2076
2031 } 2077 }
OLDNEW
« no previous file with comments | « pkg/analyzer2dart/test/end2end_test.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698