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

Side by Side Diff: pkg/compiler/lib/src/cps_ir/cps_ir_builder_visitor.dart

Issue 908863003: dart2js cps: Handle optional parameters in builder. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebase Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
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 part of dart2js.ir_builder; 5 part of dart2js.ir_builder;
6 6
7 /** 7 /**
8 * This task iterates through all resolved elements and builds [ir.Node]s. The 8 * This task iterates through all resolved elements and builds [ir.Node]s. The
9 * nodes are stored in the [nodes] map and accessible through [hasIr] and 9 * nodes are stored in the [nodes] map and accessible through [hasIr] and
10 * [getIr]. 10 * [getIr].
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 /** 142 /**
143 * Builds the [ir.ExecutableDefinition] for an executable element. In case the 143 * Builds the [ir.ExecutableDefinition] for an executable element. In case the
144 * function uses features that cannot be expressed in the IR, this element 144 * function uses features that cannot be expressed in the IR, this element
145 * returns `null`. 145 * returns `null`.
146 */ 146 */
147 ir.ExecutableDefinition buildExecutable(ExecutableElement element); 147 ir.ExecutableDefinition buildExecutable(ExecutableElement element);
148 148
149 ClosureScope getClosureScopeForNode(ast.Node node); 149 ClosureScope getClosureScopeForNode(ast.Node node);
150 ClosureEnvironment getClosureEnvironment(); 150 ClosureEnvironment getClosureEnvironment();
151 151
152 /// Normalizes the argument list to a static invocation (i.e. where the target
153 /// element is known).
154 ///
155 /// For the JS backend, inserts default arguments and normalizes order of
156 /// named arguments.
157 ///
158 /// For the Dart backend, returns [arguments].
159 List<ir.Primitive> normalizeStaticArguments(
160 Selector selector,
161 FunctionElement target,
162 List<ir.Primitive> arguments);
152 163
164 /// Normalizes the argument list of a dynamic invocation (i.e. where the
165 /// target element is unknown).
166 ///
167 /// For the JS backend, normalizes order of named arguments.
168 ///
169 /// For the Dart backend, returns [arguments].
170 List<ir.Primitive> normalizeDynamicArguments(
171 Selector selector,
172 List<ir.Primitive> arguments);
153 173
154 ir.FunctionDefinition _makeFunctionBody(FunctionElement element, 174 ir.FunctionDefinition _makeFunctionBody(FunctionElement element,
155 ast.FunctionExpression node) { 175 ast.FunctionExpression node) {
156 FunctionSignature signature = element.functionSignature; 176 FunctionSignature signature = element.functionSignature;
157 List<ParameterElement> parameters = []; 177 List<ParameterElement> parameters = [];
158 signature.orderedForEachParameter(parameters.add); 178 signature.orderedForEachParameter(parameters.add);
159 179
160 irBuilder.buildFunctionHeader(parameters, 180 irBuilder.buildFunctionHeader(parameters,
161 closureScope: getClosureScopeForNode(node), 181 closureScope: getClosureScopeForNode(node),
162 env: getClosureEnvironment()); 182 env: getClosureEnvironment());
(...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after
547 } 567 }
548 568
549 ir.Primitive visitNamedArgument(ast.NamedArgument node) { 569 ir.Primitive visitNamedArgument(ast.NamedArgument node) {
550 assert(irBuilder.isOpen); 570 assert(irBuilder.isOpen);
551 return visit(node.expression); 571 return visit(node.expression);
552 } 572 }
553 573
554 ir.Primitive visitClosureSend(ast.Send node) { 574 ir.Primitive visitClosureSend(ast.Send node) {
555 assert(irBuilder.isOpen); 575 assert(irBuilder.isOpen);
556 Element element = elements[node]; 576 Element element = elements[node];
557 Selector closureSelector = elements.getSelector(node); 577 Selector selector = elements.getSelector(node);
558 if (element == null) { 578 ir.Primitive receiver = (element == null)
559 ir.Primitive closureTarget = visit(node.selector); 579 ? visit(node.selector)
560 List<ir.Primitive> args = 580 : irBuilder.buildLocalGet(element);
561 node.arguments.mapToList(visit, growable:false); 581 List<ir.Primitive> arguments = node.arguments.mapToList(visit);
562 return irBuilder.buildFunctionExpressionInvocation( 582 arguments = normalizeDynamicArguments(selector, arguments);
563 closureTarget, elements.getSelector(node), args); 583 return irBuilder.buildCallInvocation(receiver, selector, arguments);
564 } else {
565 List<ir.Primitive> args =
566 node.arguments.mapToList(visit, growable:false);
567 return irBuilder.buildLocalInvocation(
568 element, elements.getSelector(node), args);
569 }
570 } 584 }
571 585
572 /// If [node] is null, returns this. 586 /// If [node] is null, returns this.
573 /// If [node] is super, returns null (for special handling) 587 /// If [node] is super, returns null (for special handling)
574 /// Otherwise visits [node] and returns the result. 588 /// Otherwise visits [node] and returns the result.
575 ir.Primitive visitReceiver(ast.Expression node) { 589 ir.Primitive visitReceiver(ast.Expression node) {
576 if (node == null) return irBuilder.buildThis(); 590 if (node == null) return irBuilder.buildThis();
577 if (node.isSuper()) return null; 591 if (node.isSuper()) return null;
578 return visit(node); 592 return visit(node);
579 } 593 }
580 594
581 /// Returns `true` if [node] is a super call. 595 /// Returns `true` if [node] is a super call.
582 // TODO(johnniwinther): Remove the need for this. 596 // TODO(johnniwinther): Remove the need for this.
583 bool isSuperCall(ast.Send node) { 597 bool isSuperCall(ast.Send node) {
584 return node != null && node.receiver != null && node.receiver.isSuper(); 598 return node != null && node.receiver != null && node.receiver.isSuper();
585 } 599 }
586 600
587 ir.Primitive visitDynamicSend(ast.Send node) { 601 ir.Primitive visitDynamicSend(ast.Send node) {
588 assert(irBuilder.isOpen); 602 assert(irBuilder.isOpen);
589 Selector selector = elements.getSelector(node); 603 Selector selector = elements.getSelector(node);
590 ir.Primitive receiver = visitReceiver(node.receiver); 604 ir.Primitive receiver = visitReceiver(node.receiver);
591 List<ir.Primitive> arguments = new List<ir.Primitive>(); 605 List<ir.Primitive> arguments = node.arguments.mapToList(visit);
592 for (ast.Node n in node.arguments) { 606 arguments = normalizeDynamicArguments(selector, arguments);
593 arguments.add(visit(n));
594 }
595 return irBuilder.buildDynamicInvocation(receiver, selector, arguments); 607 return irBuilder.buildDynamicInvocation(receiver, selector, arguments);
596 } 608 }
597 609
598 _GetterElements translateGetter(ast.Send node, Selector selector) { 610 _GetterElements translateGetter(ast.Send node, Selector selector) {
599 Element element = elements[node]; 611 Element element = elements[node];
600 ir.Primitive result; 612 ir.Primitive result;
601 ir.Primitive receiver; 613 ir.Primitive receiver;
602 ir.Primitive index; 614 ir.Primitive index;
603 615
604 if (element != null && element.isConst) { 616 if (element != null && element.isConst) {
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
710 assert(irBuilder.isOpen); 722 assert(irBuilder.isOpen);
711 Element element = elements[node]; 723 Element element = elements[node];
712 assert(!element.isConstructor); 724 assert(!element.isConstructor);
713 // TODO(lry): support foreign functions. 725 // TODO(lry): support foreign functions.
714 if (element.isForeign(compiler.backend)) { 726 if (element.isForeign(compiler.backend)) {
715 return giveup(node, 'StaticSend: foreign'); 727 return giveup(node, 'StaticSend: foreign');
716 } 728 }
717 729
718 Selector selector = elements.getSelector(node); 730 Selector selector = elements.getSelector(node);
719 731
720 // TODO(lry): support default arguments, need support for locals. 732 if (selector.isCall && (element.isGetter || element.isField)) {
721 List<ir.Primitive> arguments = 733 // We are invoking a static field or getter as if it was a method, e.g:
722 node.arguments.mapToList(visit, growable:false); 734 //
723 return irBuilder.buildStaticInvocation(element, selector, arguments); 735 // get foo => {..}
736 // main() { foo(1, 2, 3); }
737 //
738 // We invoke the getter of 'foo' and then invoke the 'call' method
739 // on the result, using the given arguments.
740 Selector getter = new Selector.getterFrom(selector);
741 Selector call = new Selector.callClosureFrom(selector);
742 ir.Primitive receiver = irBuilder.buildStaticGet(element, getter);
743 List<ir.Primitive> arguments = node.arguments.mapToList(visit);
744 arguments = normalizeDynamicArguments(selector, arguments);
745 return irBuilder.buildCallInvocation(receiver, call, arguments);
746 } else if (selector.isGetter) {
747 // We are reading a static field or invoking a static getter.
748 return irBuilder.buildStaticGet(element, selector);
749 } else {
750 // We are invoking a static method.
751 assert(selector.isCall);
752 assert(element is FunctionElement);
753 List<ir.Primitive> arguments = node.arguments.mapToList(visit);
754 arguments = normalizeStaticArguments(selector, element, arguments);
755 return irBuilder.buildStaticInvocation(element, selector, arguments);
756 }
724 } 757 }
725 758
726 ir.Primitive visitSuperSend(ast.Send node) { 759 ir.Primitive visitSuperSend(ast.Send node) {
727 assert(irBuilder.isOpen); 760 assert(irBuilder.isOpen);
728 if (node.isPropertyAccess) { 761 if (node.isPropertyAccess) {
729 return visitGetterSend(node); 762 return visitGetterSend(node);
730 } else { 763 } else {
731 Selector selector = elements.getSelector(node); 764 Selector selector = elements.getSelector(node);
732 Element target = elements[node]; 765 Element target = elements[node];
733 List<ir.Primitive> arguments = new List<ir.Primitive>(); 766 List<ir.Primitive> arguments = node.arguments.mapToList(visit);
734 for (ast.Node n in node.arguments) { 767 if (selector.isCall) {
735 arguments.add(visit(n)); 768 arguments = normalizeStaticArguments(selector, target, arguments);
736 } 769 }
737 return irBuilder.buildSuperInvocation(target, selector, arguments); 770 return irBuilder.buildSuperInvocation(target, selector, arguments);
738 } 771 }
739 } 772 }
740 773
741 visitTypePrefixSend(ast.Send node) { 774 visitTypePrefixSend(ast.Send node) {
742 compiler.internalError(node, "visitTypePrefixSend should not be called."); 775 compiler.internalError(node, "visitTypePrefixSend should not be called.");
743 } 776 }
744 777
745 ir.Primitive visitTypeLiteralSend(ast.Send node) { 778 ir.Primitive visitTypeLiteralSend(ast.Send node) {
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
859 } 892 }
860 893
861 ir.Primitive visitNewExpression(ast.NewExpression node) { 894 ir.Primitive visitNewExpression(ast.NewExpression node) {
862 if (node.isConst) { 895 if (node.isConst) {
863 return translateConstant(node); 896 return translateConstant(node);
864 } 897 }
865 FunctionElement element = elements[node.send]; 898 FunctionElement element = elements[node.send];
866 Selector selector = elements.getSelector(node.send); 899 Selector selector = elements.getSelector(node.send);
867 DartType type = elements.getType(node); 900 DartType type = elements.getType(node);
868 ast.Node selectorNode = node.send.selector; 901 ast.Node selectorNode = node.send.selector;
869 List<ir.Definition> arguments = 902 List<ir.Primitive> arguments =
870 node.send.arguments.mapToList(visit, growable:false); 903 node.send.arguments.mapToList(visit, growable:false);
904 arguments = normalizeStaticArguments(selector, element, arguments);
871 return irBuilder.buildConstructorInvocation( 905 return irBuilder.buildConstructorInvocation(
872 element, selector, type, arguments); 906 element, selector, type, arguments);
873 } 907 }
874 908
875 ir.Primitive visitStringJuxtaposition(ast.StringJuxtaposition node) { 909 ir.Primitive visitStringJuxtaposition(ast.StringJuxtaposition node) {
876 assert(irBuilder.isOpen); 910 assert(irBuilder.isOpen);
877 ir.Primitive first = visit(node.first); 911 ir.Primitive first = visit(node.first);
878 ir.Primitive second = visit(node.second); 912 ir.Primitive second = visit(node.second);
879 return irBuilder.buildStringConcatenation([first, second]); 913 return irBuilder.buildStringConcatenation([first, second]);
880 } 914 }
881 915
882 ir.Primitive visitStringInterpolation(ast.StringInterpolation node) { 916 ir.Primitive visitStringInterpolation(ast.StringInterpolation node) {
883 assert(irBuilder.isOpen); 917 assert(irBuilder.isOpen);
884 List<ir.Primitive> arguments = []; 918 List<ir.Primitive> arguments = [];
885 arguments.add(visitLiteralString(node.string)); 919 arguments.add(visitLiteralString(node.string));
886 var it = node.parts.iterator; 920 var it = node.parts.iterator;
887 while (it.moveNext()) { 921 while (it.moveNext()) {
888 ast.StringInterpolationPart part = it.current; 922 ast.StringInterpolationPart part = it.current;
889 arguments.add(visit(part.expression)); 923 arguments.add(visit(part.expression));
890 arguments.add(visitLiteralString(part.string)); 924 arguments.add(visitLiteralString(part.string));
891 } 925 }
892 return irBuilder.buildStringConcatenation(arguments); 926 return irBuilder.buildStringConcatenation(arguments);
893 } 927 }
894 928
895 ir.Primitive translateConstant(ast.Node node, [ConstantExpression constant]) { 929 ir.Primitive translateConstant(ast.Node node) {
896 assert(irBuilder.isOpen); 930 assert(irBuilder.isOpen);
897 if (constant == null) { 931 return irBuilder.buildConstantLiteral(getConstantForNode(node));
898 constant = getConstantForNode(node);
899 }
900 return irBuilder.buildConstantLiteral(constant);
901 } 932 }
902 933
903 ir.ExecutableDefinition nullIfGiveup(ir.ExecutableDefinition action()) { 934 ir.ExecutableDefinition nullIfGiveup(ir.ExecutableDefinition action()) {
904 try { 935 try {
905 return action(); 936 return action();
906 } catch(e, tr) { 937 } catch(e, tr) {
907 if (e == ABORT_IRNODE_BUILDER) { 938 if (e == ABORT_IRNODE_BUILDER) {
908 return null; 939 return null;
909 } 940 }
910 rethrow; 941 rethrow;
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
1105 SynthesizedConstructorElementX constructor = element; 1136 SynthesizedConstructorElementX constructor = element;
1106 if (!constructor.isDefaultConstructor) { 1137 if (!constructor.isDefaultConstructor) {
1107 giveup(null, 'cannot handle synthetic forwarding constructors'); 1138 giveup(null, 'cannot handle synthetic forwarding constructors');
1108 } 1139 }
1109 } 1140 }
1110 1141
1111 IrBuilder builder = makeIRBuilder(node, element); 1142 IrBuilder builder = makeIRBuilder(node, element);
1112 1143
1113 return withBuilder(builder, () => _makeFunctionBody(element, node)); 1144 return withBuilder(builder, () => _makeFunctionBody(element, node));
1114 } 1145 }
1146
1147 List<ir.Primitive> normalizeStaticArguments(
1148 Selector selector,
1149 FunctionElement target,
1150 List<ir.Primitive> arguments) {
1151 return arguments;
1152 }
1153
1154 List<ir.Primitive> normalizeDynamicArguments(
1155 Selector selector,
1156 List<ir.Primitive> arguments) {
1157 return arguments;
1158 }
1115 } 1159 }
1116 1160
1117 /// IR builder specific to the JavaScript backend, coupled to the [JsIrBuilder]. 1161 /// IR builder specific to the JavaScript backend, coupled to the [JsIrBuilder].
1118 class JsIrBuilderVisitor extends IrBuilderVisitor { 1162 class JsIrBuilderVisitor extends IrBuilderVisitor {
1119 /// Promote the type of [irBuilder] to [JsIrBuilder]. 1163 /// Promote the type of [irBuilder] to [JsIrBuilder].
1120 JsIrBuilder get irBuilder => super.irBuilder; 1164 JsIrBuilder get irBuilder => super.irBuilder;
1121 1165
1122 /// Result of closure conversion for the current body of code. 1166 /// Result of closure conversion for the current body of code.
1123 /// 1167 ///
1124 /// Will be initialized upon entering the body of a function. 1168 /// Will be initialized upon entering the body of a function.
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
1240 /// Such expressions need to be compiled with a different [sourceFile] and 1284 /// Such expressions need to be compiled with a different [sourceFile] and
1241 /// [elements] mapping. 1285 /// [elements] mapping.
1242 ir.Primitive inlineExpression(AstElement context, ast.Expression expression) { 1286 ir.Primitive inlineExpression(AstElement context, ast.Expression expression) {
1243 JsIrBuilderVisitor visitor = new JsIrBuilderVisitor( 1287 JsIrBuilderVisitor visitor = new JsIrBuilderVisitor(
1244 context.resolvedAst.elements, 1288 context.resolvedAst.elements,
1245 compiler, 1289 compiler,
1246 elementSourceFile(context)); 1290 elementSourceFile(context));
1247 return visitor.withBuilder(irBuilder, () => visitor.visit(expression)); 1291 return visitor.withBuilder(irBuilder, () => visitor.visit(expression));
1248 } 1292 }
1249 1293
1294 /// Builds the IR for a constant taken from a different [context].
1295 ///
1296 /// Such constants need to be compiled with a different [sourceFile] and
1297 /// [elements] mapping.
1298 ir.Primitive inlineConstant(AstElement context, ast.Expression exp) {
1299 JsIrBuilderVisitor visitor = new JsIrBuilderVisitor(
1300 context.resolvedAst.elements,
1301 compiler,
1302 elementSourceFile(context));
1303 return visitor.withBuilder(irBuilder, () => visitor.translateConstant(exp));
1304 }
1305
1250 /// Builds the IR for a given constructor. 1306 /// Builds the IR for a given constructor.
1251 /// 1307 ///
1252 /// 1. Evaluates all own or inherited field initializers. 1308 /// 1. Evaluates all own or inherited field initializers.
1253 /// 2. Creates the object and assigns its fields. 1309 /// 2. Creates the object and assigns its fields.
1254 /// 3. Calls constructor body and super constructor bodies. 1310 /// 3. Calls constructor body and super constructor bodies.
1255 /// 4. Returns the created object. 1311 /// 4. Returns the created object.
1256 ir.FunctionDefinition buildConstructor(ConstructorElement constructor) { 1312 ir.FunctionDefinition buildConstructor(ConstructorElement constructor) {
1257 constructor = constructor.implementation; 1313 constructor = constructor.implementation;
1258 ClassElement classElement = constructor.enclosingClass.implementation; 1314 ClassElement classElement = constructor.enclosingClass.implementation;
1259 1315
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
1544 1600
1545 closureMap = compiler.closureToClassMapper.computeClosureToClassMapping( 1601 closureMap = compiler.closureToClassMapper.computeClosureToClassMapping(
1546 element, 1602 element,
1547 node, 1603 node,
1548 elements); 1604 elements);
1549 IrBuilder builder = 1605 IrBuilder builder =
1550 new JsIrBuilder(compiler.backend.constantSystem, element); 1606 new JsIrBuilder(compiler.backend.constantSystem, element);
1551 return withBuilder(builder, () => _makeFunctionBody(element, node)); 1607 return withBuilder(builder, () => _makeFunctionBody(element, node));
1552 } 1608 }
1553 1609
1610 /// Creates a primitive for the default value of [parameter].
1611 ir.Primitive translateDefaultValue(ParameterElement parameter) {
1612 if (parameter.initializer == null) {
1613 return irBuilder.buildNullLiteral();
1614 } else {
1615 return inlineConstant(parameter.executableContext, parameter.initializer);
1616 }
1617 }
1618
1619 /// Inserts default arguments and normalizes order of named arguments.
1620 List<ir.Primitive> normalizeStaticArguments(
1621 Selector selector,
1622 FunctionElement target,
1623 List<ir.Primitive> arguments) {
1624 target = target.implementation;
1625 FunctionSignature signature = target.functionSignature;
1626 if (!signature.optionalParametersAreNamed &&
1627 signature.parameterCount == arguments.length) {
1628 // Optimization: don't copy the argument list for trivial cases.
1629 return arguments;
1630 }
1631
1632 List<ir.Primitive> result = <ir.Primitive>[];
1633 int i = 0;
1634 signature.forEachRequiredParameter((ParameterElement element) {
1635 result.add(arguments[i]);
1636 ++i;
1637 });
1638
1639 if (!signature.optionalParametersAreNamed) {
1640 signature.forEachOptionalParameter((ParameterElement element) {
1641 if (i < arguments.length) {
1642 result.add(arguments[i]);
1643 ++i;
1644 } else {
1645 result.add(translateDefaultValue(element));
1646 }
1647 });
1648 } else {
1649 int offset = i;
1650 // Iterate over the optional parameters of the signature, and try to
1651 // find them in [compiledNamedArguments]. If found, we use the
1652 // value in the temporary list, otherwise the default value.
1653 signature.orderedOptionalParameters.forEach((ParameterElement element) {
1654 int nameIndex = selector.namedArguments.indexOf(element.name);
1655 if (nameIndex != -1) {
1656 int translatedIndex = offset + nameIndex;
1657 result.add(arguments[translatedIndex]);
1658 } else {
1659 result.add(translateDefaultValue(element));
1660 }
1661 });
1662 }
1663 return result;
1664 }
1665
1666 /// Normalizes order of named arguments.
1667 List<ir.Primitive> normalizeDynamicArguments(
1668 Selector selector,
1669 List<ir.Primitive> arguments) {
1670 assert(arguments.length == selector.argumentCount);
1671 // Optimization: don't copy the argument list for trivial cases.
1672 if (selector.namedArguments.isEmpty) return arguments;
1673 List<ir.Primitive> result = <ir.Primitive>[];
1674 for (int i=0; i < selector.positionalArgumentCount; i++) {
1675 result.add(arguments[i]);
1676 }
1677 for (String argName in selector.getOrderedNamedArguments()) {
1678 int nameIndex = selector.namedArguments.indexOf(argName);
1679 int translatedIndex = selector.positionalArgumentCount + nameIndex;
1680 result.add(arguments[translatedIndex]);
1681 }
1682 return result;
1683 }
1684
1554 } 1685 }
1555 1686
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart ('k') | pkg/compiler/lib/src/js_backend/codegen/codegen.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698