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

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: Unrevert + 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.buildFunctionExpressionInvocation(
564 } else { 584 receiver, selector, arguments);
565 List<ir.Primitive> args =
566 node.arguments.mapToList(visit, growable:false);
567 return irBuilder.buildLocalInvocation(
568 element, elements.getSelector(node), args);
569 }
570 } 585 }
571 586
572 /// If [node] is null, returns this. 587 /// If [node] is null, returns this.
573 /// If [node] is super, returns null (for special handling) 588 /// If [node] is super, returns null (for special handling)
574 /// Otherwise visits [node] and returns the result. 589 /// Otherwise visits [node] and returns the result.
575 ir.Primitive visitReceiver(ast.Expression node) { 590 ir.Primitive visitReceiver(ast.Expression node) {
576 if (node == null) return irBuilder.buildThis(); 591 if (node == null) return irBuilder.buildThis();
577 if (node.isSuper()) return null; 592 if (node.isSuper()) return null;
578 return visit(node); 593 return visit(node);
579 } 594 }
580 595
581 /// Returns `true` if [node] is a super call. 596 /// Returns `true` if [node] is a super call.
582 // TODO(johnniwinther): Remove the need for this. 597 // TODO(johnniwinther): Remove the need for this.
583 bool isSuperCall(ast.Send node) { 598 bool isSuperCall(ast.Send node) {
584 return node != null && node.receiver != null && node.receiver.isSuper(); 599 return node != null && node.receiver != null && node.receiver.isSuper();
585 } 600 }
586 601
587 ir.Primitive visitDynamicSend(ast.Send node) { 602 ir.Primitive visitDynamicSend(ast.Send node) {
588 assert(irBuilder.isOpen); 603 assert(irBuilder.isOpen);
589 Selector selector = elements.getSelector(node); 604 Selector selector = elements.getSelector(node);
590 ir.Primitive receiver = visitReceiver(node.receiver); 605 ir.Primitive receiver = visitReceiver(node.receiver);
591 List<ir.Primitive> arguments = new List<ir.Primitive>(); 606 List<ir.Primitive> arguments = node.arguments.mapToList(visit);
592 for (ast.Node n in node.arguments) { 607 arguments = normalizeDynamicArguments(selector, arguments);
593 arguments.add(visit(n));
594 }
595 return irBuilder.buildDynamicInvocation(receiver, selector, arguments); 608 return irBuilder.buildDynamicInvocation(receiver, selector, arguments);
596 } 609 }
597 610
598 _GetterElements translateGetter(ast.Send node, Selector selector) { 611 _GetterElements translateGetter(ast.Send node, Selector selector) {
599 Element element = elements[node]; 612 Element element = elements[node];
600 ir.Primitive result; 613 ir.Primitive result;
601 ir.Primitive receiver; 614 ir.Primitive receiver;
602 ir.Primitive index; 615 ir.Primitive index;
603 616
604 if (element != null && element.isConst) { 617 if (element != null && element.isConst) {
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
710 assert(irBuilder.isOpen); 723 assert(irBuilder.isOpen);
711 Element element = elements[node]; 724 Element element = elements[node];
712 assert(!element.isConstructor); 725 assert(!element.isConstructor);
713 // TODO(lry): support foreign functions. 726 // TODO(lry): support foreign functions.
714 if (element.isForeign(compiler.backend)) { 727 if (element.isForeign(compiler.backend)) {
715 return giveup(node, 'StaticSend: foreign'); 728 return giveup(node, 'StaticSend: foreign');
716 } 729 }
717 730
718 Selector selector = elements.getSelector(node); 731 Selector selector = elements.getSelector(node);
719 732
720 // TODO(lry): support default arguments, need support for locals.
721 List<ir.Primitive> arguments = 733 List<ir.Primitive> arguments =
722 node.arguments.mapToList(visit, growable:false); 734 node.arguments.mapToList(visit, growable:false);
735 arguments = normalizeStaticArguments(selector, element, arguments);
asgerf 2015/02/11 10:31:32 This would fail in checked-mode when the element w
723 return irBuilder.buildStaticInvocation(element, selector, arguments); 736 return irBuilder.buildStaticInvocation(element, selector, arguments);
724 } 737 }
725 738
726 ir.Primitive visitSuperSend(ast.Send node) { 739 ir.Primitive visitSuperSend(ast.Send node) {
727 assert(irBuilder.isOpen); 740 assert(irBuilder.isOpen);
728 if (node.isPropertyAccess) { 741 if (node.isPropertyAccess) {
729 return visitGetterSend(node); 742 return visitGetterSend(node);
730 } else { 743 } else {
731 Selector selector = elements.getSelector(node); 744 Selector selector = elements.getSelector(node);
732 Element target = elements[node]; 745 Element target = elements[node];
733 List<ir.Primitive> arguments = new List<ir.Primitive>(); 746 List<ir.Primitive> arguments = node.arguments.mapToList(visit);
734 for (ast.Node n in node.arguments) { 747 arguments = normalizeStaticArguments(selector, target, arguments);
735 arguments.add(visit(n));
736 }
737 return irBuilder.buildSuperInvocation(target, selector, arguments); 748 return irBuilder.buildSuperInvocation(target, selector, arguments);
738 } 749 }
739 } 750 }
740 751
741 visitTypePrefixSend(ast.Send node) { 752 visitTypePrefixSend(ast.Send node) {
742 compiler.internalError(node, "visitTypePrefixSend should not be called."); 753 compiler.internalError(node, "visitTypePrefixSend should not be called.");
743 } 754 }
744 755
745 ir.Primitive visitTypeLiteralSend(ast.Send node) { 756 ir.Primitive visitTypeLiteralSend(ast.Send node) {
746 assert(irBuilder.isOpen); 757 assert(irBuilder.isOpen);
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
859 } 870 }
860 871
861 ir.Primitive visitNewExpression(ast.NewExpression node) { 872 ir.Primitive visitNewExpression(ast.NewExpression node) {
862 if (node.isConst) { 873 if (node.isConst) {
863 return translateConstant(node); 874 return translateConstant(node);
864 } 875 }
865 FunctionElement element = elements[node.send]; 876 FunctionElement element = elements[node.send];
866 Selector selector = elements.getSelector(node.send); 877 Selector selector = elements.getSelector(node.send);
867 DartType type = elements.getType(node); 878 DartType type = elements.getType(node);
868 ast.Node selectorNode = node.send.selector; 879 ast.Node selectorNode = node.send.selector;
869 List<ir.Definition> arguments = 880 List<ir.Primitive> arguments =
870 node.send.arguments.mapToList(visit, growable:false); 881 node.send.arguments.mapToList(visit, growable:false);
882 arguments = normalizeStaticArguments(selector, element, arguments);
871 return irBuilder.buildConstructorInvocation( 883 return irBuilder.buildConstructorInvocation(
872 element, selector, type, arguments); 884 element, selector, type, arguments);
873 } 885 }
874 886
875 ir.Primitive visitStringJuxtaposition(ast.StringJuxtaposition node) { 887 ir.Primitive visitStringJuxtaposition(ast.StringJuxtaposition node) {
876 assert(irBuilder.isOpen); 888 assert(irBuilder.isOpen);
877 ir.Primitive first = visit(node.first); 889 ir.Primitive first = visit(node.first);
878 ir.Primitive second = visit(node.second); 890 ir.Primitive second = visit(node.second);
879 return irBuilder.buildStringConcatenation([first, second]); 891 return irBuilder.buildStringConcatenation([first, second]);
880 } 892 }
881 893
882 ir.Primitive visitStringInterpolation(ast.StringInterpolation node) { 894 ir.Primitive visitStringInterpolation(ast.StringInterpolation node) {
883 assert(irBuilder.isOpen); 895 assert(irBuilder.isOpen);
884 List<ir.Primitive> arguments = []; 896 List<ir.Primitive> arguments = [];
885 arguments.add(visitLiteralString(node.string)); 897 arguments.add(visitLiteralString(node.string));
886 var it = node.parts.iterator; 898 var it = node.parts.iterator;
887 while (it.moveNext()) { 899 while (it.moveNext()) {
888 ast.StringInterpolationPart part = it.current; 900 ast.StringInterpolationPart part = it.current;
889 arguments.add(visit(part.expression)); 901 arguments.add(visit(part.expression));
890 arguments.add(visitLiteralString(part.string)); 902 arguments.add(visitLiteralString(part.string));
891 } 903 }
892 return irBuilder.buildStringConcatenation(arguments); 904 return irBuilder.buildStringConcatenation(arguments);
893 } 905 }
894 906
895 ir.Primitive translateConstant(ast.Node node, [ConstantExpression constant]) { 907 ir.Primitive translateConstant(ast.Node node) {
896 assert(irBuilder.isOpen); 908 assert(irBuilder.isOpen);
897 if (constant == null) { 909 return irBuilder.buildConstantLiteral(getConstantForNode(node));
898 constant = getConstantForNode(node);
899 }
900 return irBuilder.buildConstantLiteral(constant);
901 } 910 }
902 911
903 ir.ExecutableDefinition nullIfGiveup(ir.ExecutableDefinition action()) { 912 ir.ExecutableDefinition nullIfGiveup(ir.ExecutableDefinition action()) {
904 try { 913 try {
905 return action(); 914 return action();
906 } catch(e, tr) { 915 } catch(e, tr) {
907 if (e == ABORT_IRNODE_BUILDER) { 916 if (e == ABORT_IRNODE_BUILDER) {
908 return null; 917 return null;
909 } 918 }
910 rethrow; 919 rethrow;
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
1105 SynthesizedConstructorElementX constructor = element; 1114 SynthesizedConstructorElementX constructor = element;
1106 if (!constructor.isDefaultConstructor) { 1115 if (!constructor.isDefaultConstructor) {
1107 giveup(null, 'cannot handle synthetic forwarding constructors'); 1116 giveup(null, 'cannot handle synthetic forwarding constructors');
1108 } 1117 }
1109 } 1118 }
1110 1119
1111 IrBuilder builder = makeIRBuilder(node, element); 1120 IrBuilder builder = makeIRBuilder(node, element);
1112 1121
1113 return withBuilder(builder, () => _makeFunctionBody(element, node)); 1122 return withBuilder(builder, () => _makeFunctionBody(element, node));
1114 } 1123 }
1124
1125 List<ir.Primitive> normalizeStaticArguments(
1126 Selector selector,
1127 FunctionElement target,
1128 List<ir.Primitive> arguments) {
1129 return arguments;
1130 }
1131
1132 List<ir.Primitive> normalizeDynamicArguments(
1133 Selector selector,
1134 List<ir.Primitive> arguments) {
1135 return arguments;
1136 }
1115 } 1137 }
1116 1138
1117 /// IR builder specific to the JavaScript backend, coupled to the [JsIrBuilder]. 1139 /// IR builder specific to the JavaScript backend, coupled to the [JsIrBuilder].
1118 class JsIrBuilderVisitor extends IrBuilderVisitor { 1140 class JsIrBuilderVisitor extends IrBuilderVisitor {
1119 /// Promote the type of [irBuilder] to [JsIrBuilder]. 1141 /// Promote the type of [irBuilder] to [JsIrBuilder].
1120 JsIrBuilder get irBuilder => super.irBuilder; 1142 JsIrBuilder get irBuilder => super.irBuilder;
1121 1143
1122 /// Result of closure conversion for the current body of code. 1144 /// Result of closure conversion for the current body of code.
1123 /// 1145 ///
1124 /// Will be initialized upon entering the body of a function. 1146 /// 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 1262 /// Such expressions need to be compiled with a different [sourceFile] and
1241 /// [elements] mapping. 1263 /// [elements] mapping.
1242 ir.Primitive inlineExpression(AstElement context, ast.Expression expression) { 1264 ir.Primitive inlineExpression(AstElement context, ast.Expression expression) {
1243 JsIrBuilderVisitor visitor = new JsIrBuilderVisitor( 1265 JsIrBuilderVisitor visitor = new JsIrBuilderVisitor(
1244 context.resolvedAst.elements, 1266 context.resolvedAst.elements,
1245 compiler, 1267 compiler,
1246 elementSourceFile(context)); 1268 elementSourceFile(context));
1247 return visitor.withBuilder(irBuilder, () => visitor.visit(expression)); 1269 return visitor.withBuilder(irBuilder, () => visitor.visit(expression));
1248 } 1270 }
1249 1271
1272 /// Builds the IR for a constant taken from a different [context].
1273 ///
1274 /// Such constants need to be compiled with a different [sourceFile] and
1275 /// [elements] mapping.
1276 ir.Primitive inlineConstant(AstElement context, ast.Expression exp) {
1277 JsIrBuilderVisitor visitor = new JsIrBuilderVisitor(
1278 context.resolvedAst.elements,
1279 compiler,
1280 elementSourceFile(context));
1281 return visitor.withBuilder(irBuilder, () => visitor.translateConstant(exp));
1282 }
1283
1250 /// Builds the IR for a given constructor. 1284 /// Builds the IR for a given constructor.
1251 /// 1285 ///
1252 /// 1. Evaluates all own or inherited field initializers. 1286 /// 1. Evaluates all own or inherited field initializers.
1253 /// 2. Creates the object and assigns its fields. 1287 /// 2. Creates the object and assigns its fields.
1254 /// 3. Calls constructor body and super constructor bodies. 1288 /// 3. Calls constructor body and super constructor bodies.
1255 /// 4. Returns the created object. 1289 /// 4. Returns the created object.
1256 ir.FunctionDefinition buildConstructor(ConstructorElement constructor) { 1290 ir.FunctionDefinition buildConstructor(ConstructorElement constructor) {
1257 constructor = constructor.implementation; 1291 constructor = constructor.implementation;
1258 ClassElement classElement = constructor.enclosingClass.implementation; 1292 ClassElement classElement = constructor.enclosingClass.implementation;
1259 1293
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
1544 1578
1545 closureMap = compiler.closureToClassMapper.computeClosureToClassMapping( 1579 closureMap = compiler.closureToClassMapper.computeClosureToClassMapping(
1546 element, 1580 element,
1547 node, 1581 node,
1548 elements); 1582 elements);
1549 IrBuilder builder = 1583 IrBuilder builder =
1550 new JsIrBuilder(compiler.backend.constantSystem, element); 1584 new JsIrBuilder(compiler.backend.constantSystem, element);
1551 return withBuilder(builder, () => _makeFunctionBody(element, node)); 1585 return withBuilder(builder, () => _makeFunctionBody(element, node));
1552 } 1586 }
1553 1587
1588 /// Creates a primitive for the default value of [parameter].
1589 ir.Primitive translateDefaultValue(ParameterElement parameter) {
1590 if (parameter.initializer == null) {
1591 return irBuilder.buildNullLiteral();
1592 } else {
1593 return inlineConstant(parameter.executableContext, parameter.initializer);
1594 }
1595 }
1596
1597 /// Inserts default arguments and normalizes order of named arguments.
1598 List<ir.Primitive> normalizeStaticArguments(
1599 Selector selector,
1600 FunctionElement target,
1601 List<ir.Primitive> arguments) {
1602 target = target.implementation;
1603 FunctionSignature signature = target.functionSignature;
1604 if (!signature.optionalParametersAreNamed &&
1605 signature.parameterCount == arguments.length) {
1606 // Optimization: don't copy the argument list for trivial cases.
1607 return arguments;
1608 }
1609
1610 List<ir.Primitive> result = <ir.Primitive>[];
1611 int i = 0;
1612 signature.forEachRequiredParameter((ParameterElement element) {
1613 result.add(arguments[i]);
1614 ++i;
1615 });
1616
1617 if (!signature.optionalParametersAreNamed) {
1618 signature.forEachOptionalParameter((ParameterElement element) {
1619 if (i < arguments.length) {
1620 result.add(arguments[i]);
1621 ++i;
1622 } else {
1623 result.add(translateDefaultValue(element));
1624 }
1625 });
1626 } else {
1627 int offset = i;
1628 // Iterate over the optional parameters of the signature, and try to
1629 // find them in [compiledNamedArguments]. If found, we use the
1630 // value in the temporary list, otherwise the default value.
1631 signature.orderedOptionalParameters.forEach((ParameterElement element) {
1632 int nameIndex = selector.namedArguments.indexOf(element.name);
1633 if (nameIndex != -1) {
1634 int translatedIndex = offset + nameIndex;
1635 result.add(arguments[translatedIndex]);
1636 } else {
1637 result.add(translateDefaultValue(element));
1638 }
1639 });
1640 }
1641 return result;
1642 }
1643
1644 /// Normalizes order of named arguments.
1645 List<ir.Primitive> normalizeDynamicArguments(
1646 Selector selector,
1647 List<ir.Primitive> arguments) {
1648 assert(arguments.length == selector.argumentCount);
1649 // Optimization: don't copy the argument list for trivial cases.
1650 if (selector.namedArguments.isEmpty) return arguments;
1651 List<ir.Primitive> result = <ir.Primitive>[];
1652 for (int i=0; i < selector.positionalArgumentCount; i++) {
1653 result.add(arguments[i]);
1654 }
1655 for (String argName in selector.getOrderedNamedArguments()) {
1656 int nameIndex = selector.namedArguments.indexOf(argName);
1657 int translatedIndex = selector.positionalArgumentCount + nameIndex;
1658 result.add(arguments[translatedIndex]);
1659 }
1660 return result;
1661 }
1662
1554 } 1663 }
1555 1664
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