| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |