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

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: Fix static invoke 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)) {
karlklose 2015/02/11 14:54:43 Could you add a few comments for the different cas
asgerf 2015/02/11 15:04:31 Done.
721 List<ir.Primitive> arguments = 733 Selector getter = new Selector.getterFrom(selector);
722 node.arguments.mapToList(visit, growable:false); 734 Selector call = new Selector.callClosureFrom(selector);
723 return irBuilder.buildStaticInvocation(element, selector, arguments); 735 ir.Primitive receiver = irBuilder.buildStaticGet(element, getter);
736 List<ir.Primitive> arguments = node.arguments.mapToList(visit);
737 arguments = normalizeDynamicArguments(selector, arguments);
738 return irBuilder.buildCallInvocation(receiver, call, arguments);
739 } else if (selector.isGetter) {
740 return irBuilder.buildStaticGet(element, selector);
741 } else {
742 assert(selector.isCall);
743 assert(element is FunctionElement);
744 List<ir.Primitive> arguments = node.arguments.mapToList(visit);
745 arguments = normalizeStaticArguments(selector, element, arguments);
746 return irBuilder.buildStaticInvocation(element, selector, arguments);
747 }
724 } 748 }
725 749
726 ir.Primitive visitSuperSend(ast.Send node) { 750 ir.Primitive visitSuperSend(ast.Send node) {
727 assert(irBuilder.isOpen); 751 assert(irBuilder.isOpen);
728 if (node.isPropertyAccess) { 752 if (node.isPropertyAccess) {
729 return visitGetterSend(node); 753 return visitGetterSend(node);
730 } else { 754 } else {
731 Selector selector = elements.getSelector(node); 755 Selector selector = elements.getSelector(node);
732 Element target = elements[node]; 756 Element target = elements[node];
733 List<ir.Primitive> arguments = new List<ir.Primitive>(); 757 List<ir.Primitive> arguments = node.arguments.mapToList(visit);
734 for (ast.Node n in node.arguments) { 758 if (selector.isCall) {
735 arguments.add(visit(n)); 759 arguments = normalizeStaticArguments(selector, target, arguments);
736 } 760 }
737 return irBuilder.buildSuperInvocation(target, selector, arguments); 761 return irBuilder.buildSuperInvocation(target, selector, arguments);
738 } 762 }
739 } 763 }
740 764
741 visitTypePrefixSend(ast.Send node) { 765 visitTypePrefixSend(ast.Send node) {
742 compiler.internalError(node, "visitTypePrefixSend should not be called."); 766 compiler.internalError(node, "visitTypePrefixSend should not be called.");
743 } 767 }
744 768
745 ir.Primitive visitTypeLiteralSend(ast.Send node) { 769 ir.Primitive visitTypeLiteralSend(ast.Send node) {
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
859 } 883 }
860 884
861 ir.Primitive visitNewExpression(ast.NewExpression node) { 885 ir.Primitive visitNewExpression(ast.NewExpression node) {
862 if (node.isConst) { 886 if (node.isConst) {
863 return translateConstant(node); 887 return translateConstant(node);
864 } 888 }
865 FunctionElement element = elements[node.send]; 889 FunctionElement element = elements[node.send];
866 Selector selector = elements.getSelector(node.send); 890 Selector selector = elements.getSelector(node.send);
867 DartType type = elements.getType(node); 891 DartType type = elements.getType(node);
868 ast.Node selectorNode = node.send.selector; 892 ast.Node selectorNode = node.send.selector;
869 List<ir.Definition> arguments = 893 List<ir.Primitive> arguments =
870 node.send.arguments.mapToList(visit, growable:false); 894 node.send.arguments.mapToList(visit, growable:false);
895 arguments = normalizeStaticArguments(selector, element, arguments);
871 return irBuilder.buildConstructorInvocation( 896 return irBuilder.buildConstructorInvocation(
872 element, selector, type, arguments); 897 element, selector, type, arguments);
873 } 898 }
874 899
875 ir.Primitive visitStringJuxtaposition(ast.StringJuxtaposition node) { 900 ir.Primitive visitStringJuxtaposition(ast.StringJuxtaposition node) {
876 assert(irBuilder.isOpen); 901 assert(irBuilder.isOpen);
877 ir.Primitive first = visit(node.first); 902 ir.Primitive first = visit(node.first);
878 ir.Primitive second = visit(node.second); 903 ir.Primitive second = visit(node.second);
879 return irBuilder.buildStringConcatenation([first, second]); 904 return irBuilder.buildStringConcatenation([first, second]);
880 } 905 }
881 906
882 ir.Primitive visitStringInterpolation(ast.StringInterpolation node) { 907 ir.Primitive visitStringInterpolation(ast.StringInterpolation node) {
883 assert(irBuilder.isOpen); 908 assert(irBuilder.isOpen);
884 List<ir.Primitive> arguments = []; 909 List<ir.Primitive> arguments = [];
885 arguments.add(visitLiteralString(node.string)); 910 arguments.add(visitLiteralString(node.string));
886 var it = node.parts.iterator; 911 var it = node.parts.iterator;
887 while (it.moveNext()) { 912 while (it.moveNext()) {
888 ast.StringInterpolationPart part = it.current; 913 ast.StringInterpolationPart part = it.current;
889 arguments.add(visit(part.expression)); 914 arguments.add(visit(part.expression));
890 arguments.add(visitLiteralString(part.string)); 915 arguments.add(visitLiteralString(part.string));
891 } 916 }
892 return irBuilder.buildStringConcatenation(arguments); 917 return irBuilder.buildStringConcatenation(arguments);
893 } 918 }
894 919
895 ir.Primitive translateConstant(ast.Node node, [ConstantExpression constant]) { 920 ir.Primitive translateConstant(ast.Node node) {
896 assert(irBuilder.isOpen); 921 assert(irBuilder.isOpen);
897 if (constant == null) { 922 return irBuilder.buildConstantLiteral(getConstantForNode(node));
898 constant = getConstantForNode(node);
899 }
900 return irBuilder.buildConstantLiteral(constant);
901 } 923 }
902 924
903 ir.ExecutableDefinition nullIfGiveup(ir.ExecutableDefinition action()) { 925 ir.ExecutableDefinition nullIfGiveup(ir.ExecutableDefinition action()) {
904 try { 926 try {
905 return action(); 927 return action();
906 } catch(e, tr) { 928 } catch(e, tr) {
907 if (e == ABORT_IRNODE_BUILDER) { 929 if (e == ABORT_IRNODE_BUILDER) {
908 return null; 930 return null;
909 } 931 }
910 rethrow; 932 rethrow;
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
1105 SynthesizedConstructorElementX constructor = element; 1127 SynthesizedConstructorElementX constructor = element;
1106 if (!constructor.isDefaultConstructor) { 1128 if (!constructor.isDefaultConstructor) {
1107 giveup(null, 'cannot handle synthetic forwarding constructors'); 1129 giveup(null, 'cannot handle synthetic forwarding constructors');
1108 } 1130 }
1109 } 1131 }
1110 1132
1111 IrBuilder builder = makeIRBuilder(node, element); 1133 IrBuilder builder = makeIRBuilder(node, element);
1112 1134
1113 return withBuilder(builder, () => _makeFunctionBody(element, node)); 1135 return withBuilder(builder, () => _makeFunctionBody(element, node));
1114 } 1136 }
1137
1138 List<ir.Primitive> normalizeStaticArguments(
1139 Selector selector,
1140 FunctionElement target,
1141 List<ir.Primitive> arguments) {
1142 return arguments;
1143 }
1144
1145 List<ir.Primitive> normalizeDynamicArguments(
1146 Selector selector,
1147 List<ir.Primitive> arguments) {
1148 return arguments;
1149 }
1115 } 1150 }
1116 1151
1117 /// IR builder specific to the JavaScript backend, coupled to the [JsIrBuilder]. 1152 /// IR builder specific to the JavaScript backend, coupled to the [JsIrBuilder].
1118 class JsIrBuilderVisitor extends IrBuilderVisitor { 1153 class JsIrBuilderVisitor extends IrBuilderVisitor {
1119 /// Promote the type of [irBuilder] to [JsIrBuilder]. 1154 /// Promote the type of [irBuilder] to [JsIrBuilder].
1120 JsIrBuilder get irBuilder => super.irBuilder; 1155 JsIrBuilder get irBuilder => super.irBuilder;
1121 1156
1122 /// Result of closure conversion for the current body of code. 1157 /// Result of closure conversion for the current body of code.
1123 /// 1158 ///
1124 /// Will be initialized upon entering the body of a function. 1159 /// 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 1275 /// Such expressions need to be compiled with a different [sourceFile] and
1241 /// [elements] mapping. 1276 /// [elements] mapping.
1242 ir.Primitive inlineExpression(AstElement context, ast.Expression expression) { 1277 ir.Primitive inlineExpression(AstElement context, ast.Expression expression) {
1243 JsIrBuilderVisitor visitor = new JsIrBuilderVisitor( 1278 JsIrBuilderVisitor visitor = new JsIrBuilderVisitor(
1244 context.resolvedAst.elements, 1279 context.resolvedAst.elements,
1245 compiler, 1280 compiler,
1246 elementSourceFile(context)); 1281 elementSourceFile(context));
1247 return visitor.withBuilder(irBuilder, () => visitor.visit(expression)); 1282 return visitor.withBuilder(irBuilder, () => visitor.visit(expression));
1248 } 1283 }
1249 1284
1285 /// Builds the IR for a constant taken from a different [context].
1286 ///
1287 /// Such constants need to be compiled with a different [sourceFile] and
1288 /// [elements] mapping.
1289 ir.Primitive inlineConstant(AstElement context, ast.Expression exp) {
1290 JsIrBuilderVisitor visitor = new JsIrBuilderVisitor(
1291 context.resolvedAst.elements,
1292 compiler,
1293 elementSourceFile(context));
1294 return visitor.withBuilder(irBuilder, () => visitor.translateConstant(exp));
1295 }
1296
1250 /// Builds the IR for a given constructor. 1297 /// Builds the IR for a given constructor.
1251 /// 1298 ///
1252 /// 1. Evaluates all own or inherited field initializers. 1299 /// 1. Evaluates all own or inherited field initializers.
1253 /// 2. Creates the object and assigns its fields. 1300 /// 2. Creates the object and assigns its fields.
1254 /// 3. Calls constructor body and super constructor bodies. 1301 /// 3. Calls constructor body and super constructor bodies.
1255 /// 4. Returns the created object. 1302 /// 4. Returns the created object.
1256 ir.FunctionDefinition buildConstructor(ConstructorElement constructor) { 1303 ir.FunctionDefinition buildConstructor(ConstructorElement constructor) {
1257 constructor = constructor.implementation; 1304 constructor = constructor.implementation;
1258 ClassElement classElement = constructor.enclosingClass.implementation; 1305 ClassElement classElement = constructor.enclosingClass.implementation;
1259 1306
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
1544 1591
1545 closureMap = compiler.closureToClassMapper.computeClosureToClassMapping( 1592 closureMap = compiler.closureToClassMapper.computeClosureToClassMapping(
1546 element, 1593 element,
1547 node, 1594 node,
1548 elements); 1595 elements);
1549 IrBuilder builder = 1596 IrBuilder builder =
1550 new JsIrBuilder(compiler.backend.constantSystem, element); 1597 new JsIrBuilder(compiler.backend.constantSystem, element);
1551 return withBuilder(builder, () => _makeFunctionBody(element, node)); 1598 return withBuilder(builder, () => _makeFunctionBody(element, node));
1552 } 1599 }
1553 1600
1601 /// Creates a primitive for the default value of [parameter].
1602 ir.Primitive translateDefaultValue(ParameterElement parameter) {
1603 if (parameter.initializer == null) {
1604 return irBuilder.buildNullLiteral();
1605 } else {
1606 return inlineConstant(parameter.executableContext, parameter.initializer);
1607 }
1608 }
1609
1610 /// Inserts default arguments and normalizes order of named arguments.
1611 List<ir.Primitive> normalizeStaticArguments(
1612 Selector selector,
1613 FunctionElement target,
1614 List<ir.Primitive> arguments) {
1615 target = target.implementation;
1616 FunctionSignature signature = target.functionSignature;
1617 if (!signature.optionalParametersAreNamed &&
1618 signature.parameterCount == arguments.length) {
1619 // Optimization: don't copy the argument list for trivial cases.
1620 return arguments;
1621 }
1622
1623 List<ir.Primitive> result = <ir.Primitive>[];
1624 int i = 0;
1625 signature.forEachRequiredParameter((ParameterElement element) {
1626 result.add(arguments[i]);
1627 ++i;
1628 });
1629
1630 if (!signature.optionalParametersAreNamed) {
1631 signature.forEachOptionalParameter((ParameterElement element) {
1632 if (i < arguments.length) {
1633 result.add(arguments[i]);
1634 ++i;
1635 } else {
1636 result.add(translateDefaultValue(element));
1637 }
1638 });
1639 } else {
1640 int offset = i;
1641 // Iterate over the optional parameters of the signature, and try to
1642 // find them in [compiledNamedArguments]. If found, we use the
1643 // value in the temporary list, otherwise the default value.
1644 signature.orderedOptionalParameters.forEach((ParameterElement element) {
1645 int nameIndex = selector.namedArguments.indexOf(element.name);
1646 if (nameIndex != -1) {
1647 int translatedIndex = offset + nameIndex;
1648 result.add(arguments[translatedIndex]);
1649 } else {
1650 result.add(translateDefaultValue(element));
1651 }
1652 });
1653 }
1654 return result;
1655 }
1656
1657 /// Normalizes order of named arguments.
1658 List<ir.Primitive> normalizeDynamicArguments(
1659 Selector selector,
1660 List<ir.Primitive> arguments) {
1661 assert(arguments.length == selector.argumentCount);
1662 // Optimization: don't copy the argument list for trivial cases.
1663 if (selector.namedArguments.isEmpty) return arguments;
1664 List<ir.Primitive> result = <ir.Primitive>[];
1665 for (int i=0; i < selector.positionalArgumentCount; i++) {
1666 result.add(arguments[i]);
1667 }
1668 for (String argName in selector.getOrderedNamedArguments()) {
1669 int nameIndex = selector.namedArguments.indexOf(argName);
1670 int translatedIndex = selector.positionalArgumentCount + nameIndex;
1671 result.add(arguments[translatedIndex]);
1672 }
1673 return result;
1674 }
1675
1554 } 1676 }
1555 1677
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