| Index: pkg/compiler/lib/src/cps_ir/cps_ir_builder_visitor.dart
|
| diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_visitor.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_visitor.dart
|
| index 9eafea621fd7bd0b0c18106d0f53e1747687240e..363f81ea00d4d4f0dcd231847553a104e537ea6d 100644
|
| --- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_visitor.dart
|
| +++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_visitor.dart
|
| @@ -144,7 +144,27 @@ abstract class IrBuilderVisitor extends ResolvedVisitor<ir.Primitive>
|
| ClosureScope getClosureScopeForNode(ast.Node node);
|
| ClosureEnvironment getClosureEnvironment();
|
|
|
| -
|
| + /// Normalizes the argument list to a static invocation (i.e. where the target
|
| + /// element is known).
|
| + ///
|
| + /// For the JS backend, inserts default arguments and normalizes order of
|
| + /// named arguments.
|
| + ///
|
| + /// For the Dart backend, returns [arguments].
|
| + List<ir.Primitive> normalizeStaticArguments(
|
| + Selector selector,
|
| + FunctionElement target,
|
| + List<ir.Primitive> arguments);
|
| +
|
| + /// Normalizes the argument list of a dynamic invocation (i.e. where the
|
| + /// target element is unknown).
|
| + ///
|
| + /// For the JS backend, normalizes order of named arguments.
|
| + ///
|
| + /// For the Dart backend, returns [arguments].
|
| + List<ir.Primitive> normalizeDynamicArguments(
|
| + Selector selector,
|
| + List<ir.Primitive> arguments);
|
|
|
| ir.FunctionDefinition _makeFunctionBody(FunctionElement element,
|
| ast.FunctionExpression node) {
|
| @@ -549,19 +569,14 @@ abstract class IrBuilderVisitor extends ResolvedVisitor<ir.Primitive>
|
| ir.Primitive visitClosureSend(ast.Send node) {
|
| assert(irBuilder.isOpen);
|
| Element element = elements[node];
|
| - Selector closureSelector = elements.getSelector(node);
|
| - if (element == null) {
|
| - ir.Primitive closureTarget = visit(node.selector);
|
| - List<ir.Primitive> args =
|
| - node.arguments.mapToList(visit, growable:false);
|
| - return irBuilder.buildFunctionExpressionInvocation(
|
| - closureTarget, elements.getSelector(node), args);
|
| - } else {
|
| - List<ir.Primitive> args =
|
| - node.arguments.mapToList(visit, growable:false);
|
| - return irBuilder.buildLocalInvocation(
|
| - element, elements.getSelector(node), args);
|
| - }
|
| + Selector selector = elements.getSelector(node);
|
| + ir.Primitive receiver = (element == null)
|
| + ? visit(node.selector)
|
| + : irBuilder.buildLocalGet(element);
|
| + List<ir.Primitive> arguments = node.arguments.mapToList(visit);
|
| + arguments = normalizeDynamicArguments(selector, arguments);
|
| + return irBuilder.buildFunctionExpressionInvocation(
|
| + receiver, selector, arguments);
|
| }
|
|
|
| /// If [node] is null, returns this.
|
| @@ -583,10 +598,8 @@ abstract class IrBuilderVisitor extends ResolvedVisitor<ir.Primitive>
|
| assert(irBuilder.isOpen);
|
| Selector selector = elements.getSelector(node);
|
| ir.Primitive receiver = visitReceiver(node.receiver);
|
| - List<ir.Primitive> arguments = new List<ir.Primitive>();
|
| - for (ast.Node n in node.arguments) {
|
| - arguments.add(visit(n));
|
| - }
|
| + List<ir.Primitive> arguments = node.arguments.mapToList(visit);
|
| + arguments = normalizeDynamicArguments(selector, arguments);
|
| return irBuilder.buildDynamicInvocation(receiver, selector, arguments);
|
| }
|
|
|
| @@ -712,9 +725,9 @@ abstract class IrBuilderVisitor extends ResolvedVisitor<ir.Primitive>
|
|
|
| Selector selector = elements.getSelector(node);
|
|
|
| - // TODO(lry): support default arguments, need support for locals.
|
| List<ir.Primitive> arguments =
|
| node.arguments.mapToList(visit, growable:false);
|
| + arguments = normalizeStaticArguments(selector, element, arguments);
|
| return irBuilder.buildStaticInvocation(element, selector, arguments);
|
| }
|
|
|
| @@ -725,10 +738,8 @@ abstract class IrBuilderVisitor extends ResolvedVisitor<ir.Primitive>
|
| } else {
|
| Selector selector = elements.getSelector(node);
|
| Element target = elements[node];
|
| - List<ir.Primitive> arguments = new List<ir.Primitive>();
|
| - for (ast.Node n in node.arguments) {
|
| - arguments.add(visit(n));
|
| - }
|
| + List<ir.Primitive> arguments = node.arguments.mapToList(visit);
|
| + arguments = normalizeStaticArguments(selector, target, arguments);
|
| return irBuilder.buildSuperInvocation(target, selector, arguments);
|
| }
|
| }
|
| @@ -861,8 +872,9 @@ abstract class IrBuilderVisitor extends ResolvedVisitor<ir.Primitive>
|
| Selector selector = elements.getSelector(node.send);
|
| DartType type = elements.getType(node);
|
| ast.Node selectorNode = node.send.selector;
|
| - List<ir.Definition> arguments =
|
| + List<ir.Primitive> arguments =
|
| node.send.arguments.mapToList(visit, growable:false);
|
| + arguments = normalizeStaticArguments(selector, element, arguments);
|
| return irBuilder.buildConstructorInvocation(
|
| element, selector, type, arguments);
|
| }
|
| @@ -887,12 +899,9 @@ abstract class IrBuilderVisitor extends ResolvedVisitor<ir.Primitive>
|
| return irBuilder.buildStringConcatenation(arguments);
|
| }
|
|
|
| - ir.Primitive translateConstant(ast.Node node, [ConstantExpression constant]) {
|
| + ir.Primitive translateConstant(ast.Node node) {
|
| assert(irBuilder.isOpen);
|
| - if (constant == null) {
|
| - constant = getConstantForNode(node);
|
| - }
|
| - return irBuilder.buildConstantLiteral(constant);
|
| + return irBuilder.buildConstantLiteral(getConstantForNode(node));
|
| }
|
|
|
| ir.ExecutableDefinition nullIfGiveup(ir.ExecutableDefinition action()) {
|
| @@ -1107,6 +1116,19 @@ class DartIrBuilderVisitor extends IrBuilderVisitor {
|
|
|
| return withBuilder(builder, () => _makeFunctionBody(element, node));
|
| }
|
| +
|
| + List<ir.Primitive> normalizeStaticArguments(
|
| + Selector selector,
|
| + FunctionElement target,
|
| + List<ir.Primitive> arguments) {
|
| + return arguments;
|
| + }
|
| +
|
| + List<ir.Primitive> normalizeDynamicArguments(
|
| + Selector selector,
|
| + List<ir.Primitive> arguments) {
|
| + return arguments;
|
| + }
|
| }
|
|
|
| /// IR builder specific to the JavaScript backend, coupled to the [JsIrBuilder].
|
| @@ -1242,6 +1264,18 @@ class JsIrBuilderVisitor extends IrBuilderVisitor {
|
| return visitor.withBuilder(irBuilder, () => visitor.visit(expression));
|
| }
|
|
|
| + /// Builds the IR for a constant taken from a different [context].
|
| + ///
|
| + /// Such constants need to be compiled with a different [sourceFile] and
|
| + /// [elements] mapping.
|
| + ir.Primitive inlineConstant(AstElement context, ast.Expression exp) {
|
| + JsIrBuilderVisitor visitor = new JsIrBuilderVisitor(
|
| + context.resolvedAst.elements,
|
| + compiler,
|
| + elementSourceFile(context));
|
| + return visitor.withBuilder(irBuilder, () => visitor.translateConstant(exp));
|
| + }
|
| +
|
| /// Builds the IR for a given constructor.
|
| ///
|
| /// 1. Evaluates all own or inherited field initializers.
|
| @@ -1545,5 +1579,40 @@ class JsIrBuilderVisitor extends IrBuilderVisitor {
|
| return withBuilder(builder, () => _makeFunctionBody(element, node));
|
| }
|
|
|
| + /// Creates a primitive for the default value of [parameter].
|
| + ir.Primitive translateDefaultValue(ParameterElement parameter) {
|
| + if (parameter.initializer == null) {
|
| + return irBuilder.buildNullLiteral();
|
| + } else {
|
| + return inlineConstant(parameter.executableContext, parameter.initializer);
|
| + }
|
| + }
|
| +
|
| + /// Inserts default arguments and normalizes order of named arguments.
|
| + List<ir.Primitive> normalizeStaticArguments(
|
| + Selector selector,
|
| + FunctionElement target,
|
| + List<ir.Primitive> arguments) {
|
| + target = target.implementation;
|
| + if (!target.functionSignature.optionalParametersAreNamed &&
|
| + target.functionSignature.parameterCount == arguments.length) {
|
| + // Optimization: don't copy the argument list for trivial cases.
|
| + return arguments;
|
| + }
|
| + return selector.makeArgumentsList(
|
| + target,
|
| + arguments,
|
| + translateDefaultValue);
|
| + }
|
| +
|
| + /// Normalizes order of named arguments.
|
| + List<ir.Primitive> normalizeDynamicArguments(
|
| + Selector selector,
|
| + List<ir.Primitive> arguments) {
|
| + // Optimization: don't copy the argument list for trivial cases.
|
| + if (selector.namedArguments.isEmpty) return arguments;
|
| + return selector.makeDynamicArgumentsList(arguments);
|
| + }
|
| +
|
| }
|
|
|
|
|