Chromium Code Reviews| Index: frog/leg/ssa/builder.dart |
| =================================================================== |
| --- frog/leg/ssa/builder.dart (revision 3723) |
| +++ frog/leg/ssa/builder.dart (working copy) |
| @@ -208,7 +208,6 @@ |
| FunctionExpression function = functionElement.parseNode(compiler); |
| NodeList initializers = function.initializers; |
| - NodeList parameters = function.parameters; |
| // Run through the initializers. |
| if (initializers !== null) { |
| for (Link<Node> link = initializers.nodes; |
| @@ -250,15 +249,11 @@ |
| List bodyCallInputs = <HInstruction>[]; |
| bodyCallInputs.add(newObject); |
| - for (Link link = parameters.nodes; !link.isEmpty(); link = link.tail) { |
| - Link<Node> nodeLink = link.head.definitions.nodes; |
| - // We expect exactly one identifier. |
| - assert(!nodeLink.isEmpty() && nodeLink.tail.isEmpty()); |
| - Node current = nodeLink.head; |
| - Element parameterElement = elements[current]; |
| + FunctionParameters parameters = functionElement.computeParameters(compiler); |
| + parameters.forEachParameter((Element parameterElement) { |
| HInstruction currentValue = definitions[parameterElement]; |
| bodyCallInputs.add(currentValue); |
| - } |
| + }); |
| add(new HInvokeDynamicMethod(null, methodName, bodyCallInputs)); |
| close(new HReturn(newObject)).addSuccessor(graph.exit); |
| return closeFunction(); |
| @@ -887,7 +882,84 @@ |
| } |
| } |
| - addVisitedSendArgumentsToList(Link<Node> link, List<HInstruction> list) { |
| + void addDynamicSendArgumentsToList(Send node, List<HInstruction> list) { |
| + Selector selector = elements.getSelector(node); |
| + if (selector.namedArgumentCount == 0) { |
| + addGenericSendArgumentsToList(node.arguments, list); |
| + } else { |
| + compiler.cancel( |
| + 'Unimplemented named argument for dynamic sends', node: node); |
| + } |
| + } |
| + |
| + void addStaticSendArgumentsToList(Send node, |
| + FunctionElement element, |
| + List<HInstruction> list) { |
| + Selector selector = elements.getSelector(node); |
| + if (!selector.applies(compiler, element)) { |
| + // TODO(ngeoffray): Match the VM behavior and throw an |
| + // exception at runtime. |
| + compiler.cancel('Unimplemented non-matching static call', node: node); |
| + } else if (selector.namedArgumentCount == 0) { |
| + addGenericSendArgumentsToList(node.arguments, list); |
| + } else { |
| + // If there are named arguments, provide them in the order |
| + // expected by the called function, which is the source order. |
| + FunctionParameters parameters = element.computeParameters(compiler); |
| + |
| + // Visit positional arguments and add them to the list. |
| + Link<Node> arguments = node.arguments; |
| + int positionalArgumentCount = selector.positionalArgumentCount; |
| + for (int i = 0; |
| + i < positionalArgumentCount; |
| + arguments = arguments.tail, i++) { |
| + visit(arguments.head); |
| + list.add(pop()); |
| + } |
| + |
| + // Visit named arguments and add them into a temporary list. |
| + List<HInstruction> namedArguments = <HInstruction>[]; |
| + for (; !arguments.isEmpty(); arguments = arguments.tail) { |
| + visit(arguments.head); |
| + namedArguments.add(pop()); |
| + } |
| + |
| + Link<Element> remainingNamedParameters = parameters.optionalParameters; |
| + // Skip the optional parameters that have been given in the |
| + // positional arguments. |
| + for (int i = parameters.requiredParameterCount; |
| + i < positionalArgumentCount; |
| + i++) { |
| + remainingNamedParameters = remainingNamedParameters.tail; |
| + } |
| + |
| + // Loop over the remaining named parameters, and try to find |
| + // their values: either in the temporary list or using the |
| + // default value. |
| + for (; |
| + !remainingNamedParameters.isEmpty(); |
| + remainingNamedParameters = remainingNamedParameters.tail) { |
| + Element parameter = remainingNamedParameters.head; |
| + int foundIndex = -1; |
| + for (int i = 0; i < selector.namedArguments.length; i++) { |
| + SourceString name = selector.namedArguments[i]; |
| + if (name == parameter.name) { |
| + foundIndex = i; |
| + break; |
| + } |
| + } |
| + if (foundIndex != -1) { |
| + list.add(namedArguments[foundIndex]); |
| + } else { |
| + // TODO(ngeoffray): Add the default value. |
|
floitsch
2012/01/31 15:52:41
If it is not too difficult I would prefer checking
ngeoffray
2012/01/31 16:46:17
We don't support default values for parameters yet
|
| + push(new HLiteral(null, HType.UNKNOWN)); |
| + list.add(pop()); |
| + } |
| + } |
| + } |
| + } |
| + |
| + void addGenericSendArgumentsToList(Link<Node> link, List<HInstruction> list) { |
| for (; !link.isEmpty(); link = link.tail) { |
| visit(link.head); |
| list.add(pop()); |
| @@ -926,7 +998,7 @@ |
| inputs.add(target); |
| visit(node.receiver); |
| inputs.add(pop()); |
| - addVisitedSendArgumentsToList(node.arguments, inputs); |
| + addGenericSendArgumentsToList(node.arguments, inputs); |
| push(new HInvokeInterceptor(selector, dartMethodName, false, inputs)); |
| return; |
| } |
| @@ -942,7 +1014,7 @@ |
| inputs.add(pop()); |
| } |
| - addVisitedSendArgumentsToList(node.arguments, inputs); |
| + addDynamicSendArgumentsToList(node, inputs); |
| // The first entry in the inputs list is the receiver. |
| push(new HInvokeDynamicMethod(selector, dartMethodName, inputs)); |
| @@ -969,7 +1041,7 @@ |
| } |
| var inputs = <HInstruction>[]; |
| inputs.add(closureTarget); |
| - addVisitedSendArgumentsToList(node.arguments, inputs); |
| + addDynamicSendArgumentsToList(node, inputs); |
| push(new HInvokeClosure(selector, inputs)); |
| } |
| @@ -983,7 +1055,7 @@ |
| // which is the foreign code. |
| link = link.tail.tail; |
| List<HInstruction> inputs = <HInstruction>[]; |
| - addVisitedSendArgumentsToList(link, inputs); |
| + addGenericSendArgumentsToList(link, inputs); |
| LiteralString type = node.arguments.head; |
| LiteralString literal = node.arguments.tail.head; |
| compiler.ensure(literal is LiteralString); |
| @@ -1006,7 +1078,7 @@ |
| if (!node.arguments.tail.isEmpty()) { |
| compiler.cancel('More than one expression in JS_HAS_EQUALS()'); |
| } |
| - addVisitedSendArgumentsToList(node.arguments, inputs); |
| + addGenericSendArgumentsToList(node.arguments, inputs); |
| String name = compiler.namer.instanceMethodName( |
| Namer.OPERATOR_EQUALS, 1); |
| push(new HForeign( |
| @@ -1028,7 +1100,7 @@ |
| } |
| add(target); |
| var inputs = <HInstruction>[target, context]; |
| - addVisitedSendArgumentsToList(node.arguments, inputs); |
| + addStaticSendArgumentsToList(node, element, inputs); |
| push(new HInvokeSuper(selector, inputs)); |
| } |
| @@ -1039,7 +1111,7 @@ |
| add(target); |
| var inputs = <HInstruction>[]; |
| inputs.add(target); |
| - addVisitedSendArgumentsToList(node.arguments, inputs); |
| + addStaticSendArgumentsToList(node, element, inputs); |
| push(new HInvokeStatic(selector, inputs)); |
| } |
| @@ -1058,6 +1130,8 @@ |
| // Example: f() with 'f' unbound. |
| // This can only happen inside an instance method. |
| visitDynamicSend(node); |
| + } else if (element.kind == ElementKind.CLASS) { |
| + compiler.internalError("Cannot generate code for send", node: node); |
| } else if (element.isInstanceMember()) { |
| // Example: f() with 'f' bound to instance method. |
| visitDynamicSend(node); |
| @@ -1412,7 +1486,7 @@ |
| } |
| visitNamedArgument(NamedArgument node) { |
| - compiler.unimplemented('SsaBuilder.visitNamedArgument', node: node); |
| + visit(node.expression); |
| } |
| visitSwitchStatement(SwitchStatement node) { |