| Index: pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
|
| diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
|
| index 5252b0f04a9c175cd6def2a89af33c1f407aa0b4..d71e511366aceab68a89a0445de64abd8defa282 100644
|
| --- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
|
| +++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
|
| @@ -140,8 +140,7 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
|
| BaseImplementationOfDynamicsMixin<ir.Primitive, dynamic>,
|
| BaseImplementationOfConstantsMixin<ir.Primitive, dynamic>,
|
| BaseImplementationOfSuperIncDecsMixin<ir.Primitive, dynamic>,
|
| - BaseImplementationOfNewMixin<ir.Primitive, dynamic>,
|
| - ErrorBulkMixin<ir.Primitive, dynamic>
|
| + BaseImplementationOfNewMixin<ir.Primitive, dynamic>
|
| implements SemanticSendVisitor<ir.Primitive, dynamic> {
|
| final TreeElements elements;
|
| final Compiler compiler;
|
| @@ -178,11 +177,6 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
|
| this.compiler,
|
| this.sourceInformationBuilder);
|
|
|
| - @override
|
| - bulkHandleNode(ast.Node node, String message, _) {
|
| - giveup(node, message.replaceFirst('#', '$node'));
|
| - }
|
| -
|
| String bailoutMessage = null;
|
|
|
| @override
|
| @@ -223,6 +217,28 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
|
| CallStructure callStructure,
|
| List<ir.Primitive> arguments);
|
|
|
| + /// Creates a [TypedSelector] variant of [newSelector] using the type of
|
| + /// [oldSelector], if available.
|
| + ///
|
| + /// This is needed to preserve inferred receiver types when creating new
|
| + /// selectors.
|
| + Selector useSelectorType(Selector newSelector, Selector oldSelector) {
|
| + // TODO(asgerf,johnniwinther): This works but it is brittle.
|
| + // We should decouple selectors from inferred receiver type masks.
|
| + // TODO(asgerf): Use this whenever we create a selector for a dynamic call.
|
| + if (oldSelector is TypedSelector) {
|
| + return new TypedSelector(oldSelector.mask, newSelector, compiler.world);
|
| + } else {
|
| + return newSelector;
|
| + }
|
| + }
|
| +
|
| + /// Like [useSelectorType], except the original typed selector is obtained
|
| + /// from the [node].
|
| + Selector useSelectorTypeOfNode(Selector newSelector, ast.Send node) {
|
| + return useSelectorType(newSelector, elements.getSelector(node));
|
| + }
|
| +
|
| ir.RootNode _makeFunctionBody(FunctionElement element,
|
| ast.FunctionExpression node) {
|
| FunctionSignature signature = element.functionSignature;
|
| @@ -614,12 +630,6 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
|
| return translateConstant(node);
|
| }
|
|
|
| - ir.Primitive visitIdentifier(ast.Identifier node) {
|
| - // "this" is the only identifier that should be met by the visitor.
|
| - assert(node.isThis());
|
| - return irBuilder.buildThis();
|
| - }
|
| -
|
| ir.Primitive visitParenthesizedExpression(
|
| ast.ParenthesizedExpression node) {
|
| assert(irBuilder.isOpen);
|
| @@ -795,28 +805,25 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
|
| }
|
|
|
| @override
|
| - ir.Primitive visitUnresolvedGet(
|
| - ast.Send node,
|
| - Element element,
|
| - _) {
|
| - return giveup(node, 'visitUnresolvedGet');
|
| - }
|
| -
|
| - @override
|
| ir.Primitive visitUnresolvedSuperGet(
|
| ast.Send node,
|
| - Element element,
|
| - _) {
|
| - return giveup(node, 'visitUnresolvedSuperGet');
|
| + Element element, _) {
|
| + return buildInstanceNoSuchMethod(elements.getSelector(node), []);
|
| }
|
|
|
| @override
|
| ir.Primitive visitThisGet(ast.Identifier node, _) {
|
| + if (irBuilder.state.thisParameter == null) {
|
| + // TODO(asgerf,johnniwinther): Should be in a visitInvalidThis method.
|
| + // 'this' in static context. Just translate to null.
|
| + assert(compiler.compilationFailed);
|
| + return irBuilder.buildNullConstant();
|
| + }
|
| return irBuilder.buildThis();
|
| }
|
|
|
| ir.Primitive translateTypeVariableTypeLiteral(TypeVariableElement element) {
|
| - return buildReifyTypeVariable(irBuilder.buildThis(), element.type);
|
| + return irBuilder.buildReifyTypeVariable(element.type);
|
| }
|
|
|
| @override
|
| @@ -933,16 +940,6 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
|
| }
|
|
|
| @override
|
| - ir.Primitive visitUnresolvedSuperBinary(
|
| - ast.Send node,
|
| - Element element,
|
| - op.BinaryOperator operator,
|
| - ast.Node argument,
|
| - _) {
|
| - return giveup(node, 'visitUnresolvedSuperBinary');
|
| - }
|
| -
|
| - @override
|
| ir.Primitive visitSuperIndex(
|
| ast.Send node,
|
| FunctionElement function,
|
| @@ -952,15 +949,6 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
|
| }
|
|
|
| @override
|
| - ir.Primitive visitUnresolvedSuperIndex(
|
| - ast.Send node,
|
| - Element element,
|
| - ast.Node index,
|
| - _) {
|
| - return giveup(node, 'visitUnresolvedSuperIndex');
|
| - }
|
| -
|
| - @override
|
| ir.Primitive visitEquals(
|
| ast.Send node,
|
| ast.Node left,
|
| @@ -1028,15 +1016,6 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
|
| function, CallStructure.NO_ARGS, const []);
|
| }
|
|
|
| - @override
|
| - ir.Primitive visitUnresolvedSuperUnary(
|
| - ast.Send node,
|
| - op.UnaryOperator operator,
|
| - Element element,
|
| - _) {
|
| - return giveup(node, 'visitUnresolvedSuperUnary');
|
| - }
|
| -
|
| // TODO(johnniwinther): Handle this in the [IrBuilder] to ensure the correct
|
| // semantic correlation between arguments and invocation.
|
| List<ir.Primitive> translateDynamicArguments(ast.NodeList nodeList,
|
| @@ -1140,9 +1119,10 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
|
| ast.Send node,
|
| MethodElement function,
|
| ast.NodeList arguments,
|
| - CallStructure callStructure,
|
| - _) {
|
| - return giveup(node, 'handleStaticFunctionIncompatibleInvoke');
|
| + CallStructure callStructure, _) {
|
| + return buildStaticNoSuchMethod(
|
| + elements.getSelector(node),
|
| + arguments.nodes.mapToList(visit));
|
| }
|
|
|
| @override
|
| @@ -1203,19 +1183,10 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
|
| ast.Send node,
|
| MethodElement method,
|
| ast.NodeList arguments,
|
| - CallStructure callStructure,
|
| - _) {
|
| - return giveup(node, 'visitSuperMethodIncompatibleInvoke');
|
| - }
|
| -
|
| - @override
|
| - ir.Primitive visitUnresolvedInvoke(
|
| - ast.Send node,
|
| - Element element,
|
| - ast.NodeList arguments,
|
| - Selector selector,
|
| - _) {
|
| - return giveup(node, 'visitUnresolvedInvoke');
|
| + CallStructure callStructure, _) {
|
| + return buildInstanceNoSuchMethod(
|
| + elements.getSelector(node),
|
| + translateDynamicArguments(arguments, callStructure));
|
| }
|
|
|
| @override
|
| @@ -1223,9 +1194,10 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
|
| ast.Send node,
|
| Element element,
|
| ast.NodeList arguments,
|
| - Selector selector,
|
| - _) {
|
| - return giveup(node, 'visitUnresolvedSuperInvoke');
|
| + Selector selector, _) {
|
| + return buildInstanceNoSuchMethod(
|
| + elements.getSelector(node),
|
| + translateDynamicArguments(arguments, selector.callStructure));
|
| }
|
|
|
| @override
|
| @@ -1250,10 +1222,6 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
|
| callStructure);
|
| }
|
|
|
| - // TODO(johnniwinther): This should be a method on [IrBuilder].
|
| - ir.Primitive buildReifyTypeVariable(ir.Primitive target,
|
| - TypeVariableType variable);
|
| -
|
| @override
|
| ir.Primitive visitIndexSet(
|
| ast.SendSet node,
|
| @@ -1867,129 +1835,850 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
|
| return irBuilder.buildNonTailThrow(visit(node.expression));
|
| }
|
|
|
| - ir.RootNode nullIfGiveup(ir.RootNode action()) {
|
| - try {
|
| - return action();
|
| - } catch(e) {
|
| - if (e == ABORT_IRNODE_BUILDER) {
|
| - return null;
|
| - }
|
| - rethrow;
|
| + ir.Primitive buildStaticNoSuchMethod(
|
| + Selector selector,
|
| + List<ir.Primitive> arguments);
|
| +
|
| + ir.Primitive buildInstanceNoSuchMethod(
|
| + Selector selector,
|
| + List<ir.Primitive> arguments);
|
| +
|
| + ir.Primitive buildRuntimeError(String message);
|
| +
|
| + ir.Primitive buildAbstractClassInstantiationError(ClassElement element);
|
| +
|
| + @override
|
| + ir.Primitive errorInvalidAssert(
|
| + ast.Send node,
|
| + ast.NodeList arguments, _) {
|
| + if (compiler.enableUserAssertions) {
|
| + return giveup(node, 'Assert');
|
| + } else {
|
| + return irBuilder.buildNullConstant();
|
| }
|
| }
|
|
|
| - void internalError(ast.Node node, String message) {
|
| - giveup(node, message);
|
| + @override
|
| + ir.Primitive errorUnresolvedCompound(
|
| + ast.Send node,
|
| + Element element,
|
| + op.AssignmentOperator operator,
|
| + ast.Node rhs, _) {
|
| + // TODO(asgerf): What is unresolved? The getter and/or the setter?
|
| + // If it was the setter, we must evaluate the right-hand side.
|
| + return buildStaticNoSuchMethod(elements.getSelector(node), []);
|
| }
|
|
|
| @override
|
| - visitNode(ast.Node node) {
|
| - internalError(node, "Unhandled node");
|
| + ir.Primitive visitUnresolvedClassConstructorInvoke(
|
| + ast.NewExpression node,
|
| + Element element,
|
| + DartType type,
|
| + ast.NodeList arguments,
|
| + Selector selector, _) {
|
| + // If the class is missing it's a runtime error.
|
| + return buildRuntimeError("Unresolved class: '${element.name}'");
|
| }
|
|
|
| - dynamic giveup(ast.Node node, [String reason]) {
|
| - bailoutMessage = '($node): $reason';
|
| - throw ABORT_IRNODE_BUILDER;
|
| + @override
|
| + ir.Primitive visitUnresolvedConstructorInvoke(
|
| + ast.NewExpression node,
|
| + Element constructor,
|
| + DartType type,
|
| + ast.NodeList arguments,
|
| + Selector selector, _) {
|
| + // If the class is there but the constructor is missing, it's an NSM error.
|
| + return buildStaticNoSuchMethod(selector,
|
| + translateDynamicArguments(arguments, selector.callStructure));
|
| }
|
| -}
|
|
|
| -final String ABORT_IRNODE_BUILDER = "IrNode builder aborted";
|
| + @override
|
| + ir.Primitive errorNonConstantConstructorInvoke(
|
| + ast.NewExpression node,
|
| + Element element,
|
| + InterfaceType type,
|
| + ast.NodeList arguments,
|
| + CallStructure callStructure, _) {
|
| + assert(compiler.compilationFailed);
|
| + return irBuilder.buildNullConstant();
|
| + }
|
|
|
| -/// Classifies local variables and local functions as captured, if they
|
| -/// are accessed from within a nested function.
|
| -///
|
| -/// This class is specific to the [DartIrBuilder], in that it gives up if it
|
| -/// sees a feature that is currently unsupport by that builder. In particular,
|
| -/// loop variables captured in a for-loop initializer, condition, or update
|
| -/// expression are unsupported.
|
| -class DartCapturedVariables extends ast.Visitor {
|
| - final TreeElements elements;
|
| - DartCapturedVariables(this.elements);
|
| + @override
|
| + ir.Primitive visitUnresolvedGet(
|
| + ast.Send node,
|
| + Element element, _) {
|
| + return buildStaticNoSuchMethod(elements.getSelector(node), []);
|
| + }
|
|
|
| - FunctionElement currentFunction;
|
| - bool insideInitializer = false;
|
| - Set<Local> capturedVariables = new Set<Local>();
|
| + @override
|
| + ir.Primitive visitUnresolvedInvoke(
|
| + ast.Send node,
|
| + Element element,
|
| + ast.NodeList arguments,
|
| + Selector selector, _) {
|
| + return buildStaticNoSuchMethod(elements.getSelector(node),
|
| + arguments.nodes.mapToList(visit));
|
| + }
|
|
|
| - Map<ast.TryStatement, TryStatementInfo> tryStatements =
|
| - <ast.TryStatement, TryStatementInfo>{};
|
| + @override
|
| + ir.Primitive errorUnresolvedPostfix(
|
| + ast.Send node,
|
| + Element element,
|
| + op.IncDecOperator operator, _) {
|
| + // TODO(asgerf): Which ones are missing? The getter and/or the setter?
|
| + return buildStaticNoSuchMethod(elements.getSelector(node), []);
|
| + }
|
|
|
| - List<TryStatementInfo> tryNestingStack = <TryStatementInfo>[];
|
| - bool get inTryStatement => tryNestingStack.isNotEmpty;
|
| + @override
|
| + ir.Primitive errorUnresolvedPrefix(
|
| + ast.Send node,
|
| + Element element,
|
| + op.IncDecOperator operator, _) {
|
| + // TODO(asgerf): Which ones are missing? The getter and/or the setter?
|
| + return buildStaticNoSuchMethod(elements.getSelector(node), []);
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive visitUnresolvedRedirectingFactoryConstructorInvoke(
|
| + ast.NewExpression node,
|
| + ConstructorElement constructor,
|
| + InterfaceType type,
|
| + ast.NodeList arguments,
|
| + CallStructure callStructure, _) {
|
| + String nameString = Elements.reconstructConstructorName(constructor);
|
| + Name name = new Name(nameString, constructor.library);
|
| + return buildStaticNoSuchMethod(
|
| + new Selector(SelectorKind.CALL, name, callStructure),
|
| + translateDynamicArguments(arguments, callStructure));
|
| + }
|
|
|
| - String bailoutMessage = null;
|
| + @override
|
| + ir.Primitive errorUnresolvedSet(
|
| + ast.Send node,
|
| + Element element,
|
| + ast.Node rhs, _) {
|
| + return buildStaticNoSuchMethod(elements.getSelector(node), [visit(rhs)]);
|
| + }
|
|
|
| - giveup(ast.Node node, [String reason]) {
|
| - bailoutMessage = '($node): $reason';
|
| - throw ABORT_IRNODE_BUILDER;
|
| + @override
|
| + ir.Primitive errorUnresolvedSuperCompoundIndexSet(
|
| + ast.SendSet node,
|
| + Element element,
|
| + ast.Node index,
|
| + op.AssignmentOperator operator,
|
| + ast.Node rhs, _) {
|
| + // Assume the index getter is missing.
|
| + Selector selector = useSelectorTypeOfNode(new Selector.index(), node);
|
| + return buildInstanceNoSuchMethod(selector, [visit(index)]);
|
| }
|
|
|
| - void markAsCaptured(Local local) {
|
| - capturedVariables.add(local);
|
| + @override
|
| + ir.Primitive visitUnresolvedSuperIndex(
|
| + ast.Send node,
|
| + Element function,
|
| + ast.Node index, _) {
|
| + // Assume the index getter is missing.
|
| + Selector selector = useSelectorTypeOfNode(new Selector.index(), node);
|
| + return buildInstanceNoSuchMethod(selector, [visit(index)]);
|
| }
|
|
|
| - analyze(ast.Node node) {
|
| - visit(node);
|
| - // Variables that are captured by a closure are boxed for their entire
|
| - // lifetime, so they never need to be boxed on entry to a try block.
|
| - // They are not filtered out before this because we cannot identify all
|
| - // of them in the same pass (they may be captured by a closure after the
|
| - // try statement).
|
| - for (TryStatementInfo info in tryStatements.values) {
|
| - info.boxedOnEntry.removeAll(capturedVariables);
|
| - }
|
| + @override
|
| + ir.Primitive errorUnresolvedSuperIndexPostfix(
|
| + ast.Send node,
|
| + Element function,
|
| + ast.Node index,
|
| + op.IncDecOperator operator, _) {
|
| + // Assume the index getter is missing.
|
| + Selector selector = useSelectorTypeOfNode(new Selector.index(), node);
|
| + return buildInstanceNoSuchMethod(selector, [visit(index)]);
|
| }
|
|
|
| - visit(ast.Node node) => node.accept(this);
|
| + @override
|
| + ir.Primitive errorUnresolvedSuperIndexPrefix(
|
| + ast.Send node,
|
| + Element function,
|
| + ast.Node index,
|
| + op.IncDecOperator operator, _) {
|
| + // Assume the index getter is missing.
|
| + Selector selector = useSelectorTypeOfNode(new Selector.index(), node);
|
| + return buildInstanceNoSuchMethod(selector, [visit(index)]);
|
| + }
|
|
|
| - visitNode(ast.Node node) {
|
| - node.visitChildren(this);
|
| + @override
|
| + ir.Primitive errorUnresolvedSuperIndexSet(
|
| + ast.SendSet node,
|
| + Element element,
|
| + ast.Node index,
|
| + ast.Node rhs, _) {
|
| + Selector selector = useSelectorTypeOfNode(new Selector.index(), node);
|
| + return buildInstanceNoSuchMethod(
|
| + selector,
|
| + [visit(index), visit(rhs)]);
|
| }
|
|
|
| - visitFor(ast.For node) {
|
| - if (node.initializer != null) visit(node.initializer);
|
| - if (node.condition != null) visit(node.condition);
|
| - if (node.update != null) visit(node.update);
|
| + @override
|
| + ir.Primitive visitUnresolvedSuperBinary(
|
| + ast.Send node,
|
| + Element element,
|
| + op.BinaryOperator operator,
|
| + ast.Node argument, _) {
|
| + return buildInstanceNoSuchMethod(
|
| + elements.getSelector(node),
|
| + [visit(argument)]);
|
| + }
|
|
|
| - // Give up if a variable was captured outside of the loop body.
|
| - if (node.initializer is ast.VariableDefinitions) {
|
| - ast.VariableDefinitions definitions = node.initializer;
|
| - for (ast.Node node in definitions.definitions.nodes) {
|
| - LocalElement loopVariable = elements[node];
|
| - if (capturedVariables.contains(loopVariable)) {
|
| - return giveup(node, 'For-loop variable captured in loop header');
|
| - }
|
| - }
|
| - }
|
| + @override
|
| + ir.Primitive visitUnresolvedSuperUnary(
|
| + ast.Send node,
|
| + op.UnaryOperator operator,
|
| + Element element, _) {
|
| + return buildInstanceNoSuchMethod(elements.getSelector(node), []);
|
| + }
|
|
|
| - if (node.body != null) visit(node.body);
|
| + @override
|
| + ir.Primitive errorUndefinedBinaryExpression(
|
| + ast.Send node,
|
| + ast.Node left,
|
| + ast.Operator operator,
|
| + ast.Node right, _) {
|
| + assert(compiler.compilationFailed);
|
| + return irBuilder.buildNullConstant();
|
| }
|
|
|
| - void handleSend(ast.Send node) {
|
| - Element element = elements[node];
|
| - if (Elements.isLocal(element) &&
|
| - !element.isConst &&
|
| - element.enclosingElement != currentFunction) {
|
| - LocalElement local = element;
|
| - markAsCaptured(local);
|
| - }
|
| + @override
|
| + ir.Primitive errorUndefinedUnaryExpression(
|
| + ast.Send node,
|
| + ast.Operator operator,
|
| + ast.Node expression, _) {
|
| + assert(compiler.compilationFailed);
|
| + return irBuilder.buildNullConstant();
|
| }
|
|
|
| - visitSend(ast.Send node) {
|
| - handleSend(node);
|
| - node.visitChildren(this);
|
| + @override
|
| + ir.Primitive errorTopLevelFunctionSet(
|
| + ast.Send node,
|
| + MethodElement function,
|
| + ast.Node rhs, _) {
|
| + return buildStaticNoSuchMethod(
|
| + new Selector.setter(function.name, function.library),
|
| + [visit(rhs)]);
|
| }
|
|
|
| - visitSendSet(ast.SendSet node) {
|
| - handleSend(node);
|
| - Element element = elements[node];
|
| - if (Elements.isLocal(element)) {
|
| - LocalElement local = element;
|
| - if (insideInitializer) {
|
| - assert(local.isParameter);
|
| - // Initializers in an initializer-list can communicate via parameters.
|
| - // If a parameter is stored in an initializer list we box it.
|
| - // TODO(sigurdm): Fix this.
|
| - // Though these variables do not outlive the activation of the
|
| + @override
|
| + ir.Primitive errorTopLevelSetterGet(
|
| + ast.Send node,
|
| + FunctionElement setter, _) {
|
| + return buildStaticNoSuchMethod(
|
| + new Selector.getter(setter.name, setter.library), []);
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive errorTopLevelGetterSet(
|
| + ast.SendSet node,
|
| + FunctionElement getter,
|
| + ast.Node rhs, _) {
|
| + return buildStaticNoSuchMethod(
|
| + new Selector.setter(getter.name, getter.library),
|
| + [visit(rhs)]);
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive errorTopLevelSetterInvoke(
|
| + ast.Send node,
|
| + FunctionElement setter,
|
| + ast.NodeList arguments,
|
| + CallStructure callStructure, _) {
|
| + return buildStaticNoSuchMethod(
|
| + new Selector.getter(setter.name, setter.library), []);
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive errorClassTypeLiteralSet(
|
| + ast.SendSet node,
|
| + TypeConstantExpression constant,
|
| + ast.Node rhs, _) {
|
| + InterfaceType type = constant.type;
|
| + ClassElement element = type.element;
|
| + return buildStaticNoSuchMethod(
|
| + new Selector.setter(element.name, element.library), [visit(rhs)]);
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive errorTypedefTypeLiteralSet(
|
| + ast.SendSet node,
|
| + TypeConstantExpression constant,
|
| + ast.Node rhs, _) {
|
| + TypedefType type = constant.type;
|
| + TypedefElement element = type.element;
|
| + return buildStaticNoSuchMethod(
|
| + new Selector.setter(element.name, element.library), [visit(rhs)]);
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive errorTypeVariableTypeLiteralSet(
|
| + ast.SendSet node,
|
| + TypeVariableElement element,
|
| + ast.Node rhs, _) {
|
| + return buildStaticNoSuchMethod(
|
| + new Selector.setter(element.name, element.library), [visit(rhs)]);
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive errorDynamicTypeLiteralSet(
|
| + ast.SendSet node,
|
| + ConstantExpression constant,
|
| + ast.Node rhs, _) {
|
| + return buildStaticNoSuchMethod(
|
| + new Selector.setter('dynamic', null), [visit(rhs)]);
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive visitAbstractClassConstructorInvoke(
|
| + ast.NewExpression node,
|
| + ConstructorElement element,
|
| + InterfaceType type,
|
| + ast.NodeList arguments,
|
| + CallStructure callStructure, _) {
|
| + return buildAbstractClassInstantiationError(element.enclosingClass);
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive errorClassTypeLiteralCompound(
|
| + ast.Send node,
|
| + ConstantExpression constant,
|
| + op.AssignmentOperator operator,
|
| + ast.Node rhs, _) {
|
| + return translateCompound(
|
| + getValue: () => irBuilder.buildConstant(constant),
|
| + operator: operator,
|
| + rhs: rhs,
|
| + setValue: (value) {}); // The binary operator will throw before this.
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive errorClassTypeLiteralPostfix(
|
| + ast.Send node,
|
| + ConstantExpression constant,
|
| + op.IncDecOperator operator, _) {
|
| + return translatePrefixPostfix(
|
| + getValue: () => irBuilder.buildConstant(constant),
|
| + operator: operator,
|
| + setValue: (value) {}, // The binary operator will throw before this.
|
| + isPrefix: false);
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive errorClassTypeLiteralPrefix(
|
| + ast.Send node,
|
| + ConstantExpression constant,
|
| + op.IncDecOperator operator, _) {
|
| + return translatePrefixPostfix(
|
| + getValue: () => irBuilder.buildConstant(constant),
|
| + operator: operator,
|
| + setValue: (value) {}, // The binary operator will throw before this.
|
| + isPrefix: true);
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive errorDynamicTypeLiteralCompound(
|
| + ast.Send node,
|
| + ConstantExpression constant,
|
| + op.AssignmentOperator operator,
|
| + ast.Node rhs, _) {
|
| + return translateCompound(
|
| + getValue: () => irBuilder.buildConstant(constant),
|
| + operator: operator,
|
| + rhs: rhs,
|
| + setValue: (value) {}); // The binary operator will throw before this.
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive errorDynamicTypeLiteralPostfix(
|
| + ast.Send node,
|
| + ConstantExpression constant,
|
| + op.IncDecOperator operator, _) {
|
| + return translatePrefixPostfix(
|
| + getValue: () => irBuilder.buildConstant(constant),
|
| + operator: operator,
|
| + setValue: (value) {}, // The binary operator will throw before this.
|
| + isPrefix: false);
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive errorDynamicTypeLiteralPrefix(
|
| + ast.Send node,
|
| + ConstantExpression constant,
|
| + op.IncDecOperator operator, _) {
|
| + return translatePrefixPostfix(
|
| + getValue: () => irBuilder.buildConstant(constant),
|
| + operator: operator,
|
| + setValue: (value) {}, // The binary operator will throw before this.
|
| + isPrefix: true);
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive errorFinalLocalVariableCompound(
|
| + ast.Send node,
|
| + LocalVariableElement variable,
|
| + op.AssignmentOperator operator,
|
| + ast.Node rhs, _) {
|
| + Selector selector = new Selector.setter(variable.name, null);
|
| + return translateCompound(
|
| + getValue: () => irBuilder.buildLocalVariableGet(variable),
|
| + operator: operator,
|
| + rhs: rhs,
|
| + setValue: (value) => buildStaticNoSuchMethod(selector, [value]));
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive errorFinalLocalVariableSet(
|
| + ast.SendSet node,
|
| + LocalVariableElement variable,
|
| + ast.Node rhs, _) {
|
| + Selector selector = new Selector.setter(variable.name, null);
|
| + return buildStaticNoSuchMethod(selector, [visit(rhs)]);
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive errorFinalParameterCompound(
|
| + ast.Send node,
|
| + ParameterElement parameter,
|
| + op.AssignmentOperator operator,
|
| + ast.Node rhs, _) {
|
| + Selector selector = new Selector.setter(parameter.name, null);
|
| + return translateCompound(
|
| + getValue: () => irBuilder.buildLocalVariableGet(parameter),
|
| + operator: operator,
|
| + rhs: rhs,
|
| + setValue: (value) => buildStaticNoSuchMethod(selector, [value]));
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive errorFinalParameterSet(
|
| + ast.SendSet node,
|
| + ParameterElement parameter,
|
| + ast.Node rhs, _) {
|
| + Selector selector = new Selector.setter(parameter.name, null);
|
| + return buildStaticNoSuchMethod(selector, [visit(rhs)]);
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive errorFinalStaticFieldCompound(
|
| + ast.Send node,
|
| + FieldElement field,
|
| + op.AssignmentOperator operator,
|
| + ast.Node rhs, _) {
|
| + return translateCompound(
|
| + getValue: () => irBuilder.buildStaticFieldGet(field),
|
| + operator: operator,
|
| + rhs: rhs,
|
| + setValue: (value) => buildStaticNoSuchMethod(
|
| + new Selector.setter(field.name, field.library), [value]));
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive errorFinalStaticFieldSet(
|
| + ast.SendSet node,
|
| + FieldElement field,
|
| + ast.Node rhs, _) {
|
| + // TODO(asgerf): Include class name somehow?
|
| + return buildStaticNoSuchMethod(
|
| + new Selector.setter(field.name, field.library),
|
| + [visit(rhs)]);
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive errorFinalSuperFieldCompound(
|
| + ast.Send node,
|
| + FieldElement field,
|
| + op.AssignmentOperator operator,
|
| + ast.Node rhs, _) {
|
| + Selector selector = useSelectorTypeOfNode(
|
| + new Selector.setter(field.name, field.library),
|
| + node);
|
| + return translateCompound(
|
| + getValue: () => irBuilder.buildSuperFieldGet(field),
|
| + operator: operator,
|
| + rhs: rhs,
|
| + setValue: (value) => buildInstanceNoSuchMethod(selector, [value]));
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive errorFinalSuperFieldSet(
|
| + ast.SendSet node,
|
| + FieldElement field,
|
| + ast.Node rhs, _) {
|
| + Selector selector = useSelectorTypeOfNode(
|
| + new Selector.setter(field.name, field.library),
|
| + node);
|
| + return buildInstanceNoSuchMethod(selector, [visit(rhs)]);
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive errorFinalTopLevelFieldCompound(
|
| + ast.Send node,
|
| + FieldElement field,
|
| + op.AssignmentOperator operator,
|
| + ast.Node rhs, _) {
|
| + return translateCompound(
|
| + getValue: () => irBuilder.buildStaticFieldGet(field),
|
| + operator: operator,
|
| + rhs: rhs,
|
| + setValue: (value) => buildStaticNoSuchMethod(
|
| + new Selector.setter(field.name, field.library), [value]));
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive errorFinalTopLevelFieldSet(
|
| + ast.SendSet node,
|
| + FieldElement field,
|
| + ast.Node rhs, _) {
|
| + return buildStaticNoSuchMethod(
|
| + new Selector.setter(field.name, field.library),
|
| + [visit(rhs)]);
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive errorLocalFunctionCompound(
|
| + ast.Send node,
|
| + LocalFunctionElement function,
|
| + op.AssignmentOperator operator,
|
| + ast.Node rhs, _) {
|
| + return translateCompound(
|
| + getValue: () => irBuilder.buildLocalFunctionGet(function),
|
| + operator: operator,
|
| + rhs: rhs,
|
| + setValue: (value) {}); // Binary operator will throw before this.
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive errorLocalFunctionPostfix(
|
| + ast.Send node,
|
| + LocalFunctionElement function,
|
| + op.IncDecOperator operator,
|
| + _) {
|
| + return translatePrefixPostfix(
|
| + getValue: () => irBuilder.buildLocalFunctionGet(function),
|
| + operator: operator,
|
| + setValue: (value) {}, // Binary operator will throw before this.
|
| + isPrefix: false);
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive errorLocalFunctionPrefix(
|
| + ast.Send node,
|
| + LocalFunctionElement function,
|
| + op.IncDecOperator operator,
|
| + _) {
|
| + return translatePrefixPostfix(
|
| + getValue: () => irBuilder.buildLocalFunctionGet(function),
|
| + operator: operator,
|
| + setValue: (value) {}, // Binary operator will throw before this.
|
| + isPrefix: true);
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive errorLocalFunctionSet(
|
| + ast.SendSet node,
|
| + LocalFunctionElement function,
|
| + ast.Node rhs, _) {
|
| + return buildStaticNoSuchMethod(
|
| + new Selector.setter(function.name, null),
|
| + [visit(rhs)]);
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive errorStaticFunctionSet(
|
| + ast.Send node,
|
| + MethodElement function,
|
| + ast.Node rhs,
|
| + _) {
|
| + return buildStaticNoSuchMethod(
|
| + new Selector.setter(function.name, function.library),
|
| + [visit(rhs)]);
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive errorStaticGetterSet(
|
| + ast.SendSet node,
|
| + FunctionElement getter,
|
| + ast.Node rhs,
|
| + _) {
|
| + return buildStaticNoSuchMethod(
|
| + new Selector.setter(getter.name, getter.library),
|
| + [visit(rhs)]);
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive errorStaticSetterGet(
|
| + ast.Send node,
|
| + FunctionElement setter,
|
| + _) {
|
| + return buildStaticNoSuchMethod(
|
| + new Selector.getter(setter.name, setter.library),
|
| + []);
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive errorStaticSetterInvoke(
|
| + ast.Send node,
|
| + FunctionElement setter,
|
| + ast.NodeList arguments,
|
| + CallStructure callStructure, _) {
|
| + // Translate as a method call.
|
| + List<ir.Primitive> args = arguments.nodes.mapToList(visit);
|
| + Name name = new Name(setter.name, setter.library);
|
| + return buildStaticNoSuchMethod(
|
| + new Selector(SelectorKind.CALL, name, callStructure),
|
| + args);
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive errorSuperGetterSet(
|
| + ast.SendSet node,
|
| + FunctionElement getter,
|
| + ast.Node rhs,
|
| + _) {
|
| + Selector selector = useSelectorTypeOfNode(
|
| + new Selector.setter(getter.name, getter.library),
|
| + node);
|
| + return buildInstanceNoSuchMethod(selector, [visit(rhs)]);
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive errorSuperMethodSet(
|
| + ast.Send node,
|
| + MethodElement method,
|
| + ast.Node rhs,
|
| + _) {
|
| + Selector selector = useSelectorTypeOfNode(
|
| + new Selector.setter(method.name, method.library),
|
| + node);
|
| + return buildInstanceNoSuchMethod(selector, [visit(rhs)]);
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive errorSuperSetterGet(
|
| + ast.Send node,
|
| + FunctionElement setter, _) {
|
| + Selector selector = useSelectorTypeOfNode(
|
| + new Selector.setter(setter.name, setter.library),
|
| + node);
|
| + return buildInstanceNoSuchMethod(selector, []);
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive errorSuperSetterInvoke(
|
| + ast.Send node,
|
| + FunctionElement setter,
|
| + ast.NodeList arguments,
|
| + CallStructure callStructure, _) {
|
| + List<ir.Primitive> args =
|
| + translateDynamicArguments(arguments, callStructure);
|
| + Name name = new Name(setter.name, setter.library);
|
| + Selector selector = useSelectorTypeOfNode(
|
| + new Selector(SelectorKind.CALL, name, callStructure),
|
| + node);
|
| + return buildInstanceNoSuchMethod(selector, args);
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive errorTypeVariableTypeLiteralCompound(
|
| + ast.Send node,
|
| + TypeVariableElement element,
|
| + op.AssignmentOperator operator,
|
| + ast.Node rhs, _) {
|
| + return translateCompound(
|
| + getValue: () => irBuilder.buildReifyTypeVariable(element.type),
|
| + operator: operator,
|
| + rhs: rhs,
|
| + setValue: (value) {}); // The binary operator will throw before this.
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive errorTypeVariableTypeLiteralPostfix(
|
| + ast.Send node,
|
| + TypeVariableElement element,
|
| + op.IncDecOperator operator, _) {
|
| + return translatePrefixPostfix(
|
| + getValue: () => irBuilder.buildReifyTypeVariable(element.type),
|
| + operator: operator,
|
| + setValue: (value) {}, // The binary operator will throw before this.
|
| + isPrefix: false);
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive errorTypeVariableTypeLiteralPrefix(
|
| + ast.Send node,
|
| + TypeVariableElement element,
|
| + op.IncDecOperator operator, _) {
|
| + return translatePrefixPostfix(
|
| + getValue: () => irBuilder.buildReifyTypeVariable(element.type),
|
| + operator: operator,
|
| + setValue: (value) {}, // The binary operator will throw before this.
|
| + isPrefix: true);
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive errorTypedefTypeLiteralCompound(
|
| + ast.Send node,
|
| + ConstantExpression constant,
|
| + op.AssignmentOperator operator,
|
| + ast.Node rhs, _) {
|
| + return translateCompound(
|
| + getValue: () => irBuilder.buildConstant(constant),
|
| + operator: operator,
|
| + rhs: rhs,
|
| + setValue: (value) {}); // The binary operator will throw before this.
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive errorTypedefTypeLiteralPostfix(
|
| + ast.Send node,
|
| + ConstantExpression constant,
|
| + op.IncDecOperator operator, _) {
|
| + return translatePrefixPostfix(
|
| + getValue: () => irBuilder.buildConstant(constant),
|
| + operator: operator,
|
| + setValue: (value) {}, // The binary operator will throw before this.
|
| + isPrefix: false);
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive errorTypedefTypeLiteralPrefix(
|
| + ast.Send node,
|
| + TypeConstantExpression constant,
|
| + op.IncDecOperator operator, _) {
|
| + return translatePrefixPostfix(
|
| + getValue: () => irBuilder.buildConstant(constant),
|
| + operator: operator,
|
| + setValue: (value) {}, // The binary operator will throw before this.
|
| + isPrefix: true);
|
| + }
|
| +
|
| + ir.RootNode nullIfGiveup(ir.RootNode action()) {
|
| + try {
|
| + return action();
|
| + } catch(e) {
|
| + if (e == ABORT_IRNODE_BUILDER) {
|
| + return null;
|
| + }
|
| + rethrow;
|
| + }
|
| + }
|
| +
|
| + void internalError(ast.Node node, String message) {
|
| + giveup(node, message);
|
| + }
|
| +
|
| + @override
|
| + visitNode(ast.Node node) {
|
| + internalError(node, "Unhandled node");
|
| + }
|
| +
|
| + dynamic giveup(ast.Node node, [String reason]) {
|
| + bailoutMessage = '($node): $reason';
|
| + throw ABORT_IRNODE_BUILDER;
|
| + }
|
| +}
|
| +
|
| +final String ABORT_IRNODE_BUILDER = "IrNode builder aborted";
|
| +
|
| +/// Classifies local variables and local functions as captured, if they
|
| +/// are accessed from within a nested function.
|
| +///
|
| +/// This class is specific to the [DartIrBuilder], in that it gives up if it
|
| +/// sees a feature that is currently unsupport by that builder. In particular,
|
| +/// loop variables captured in a for-loop initializer, condition, or update
|
| +/// expression are unsupported.
|
| +class DartCapturedVariables extends ast.Visitor {
|
| + final TreeElements elements;
|
| + DartCapturedVariables(this.elements);
|
| +
|
| + FunctionElement currentFunction;
|
| + bool insideInitializer = false;
|
| + Set<Local> capturedVariables = new Set<Local>();
|
| +
|
| + Map<ast.TryStatement, TryStatementInfo> tryStatements =
|
| + <ast.TryStatement, TryStatementInfo>{};
|
| +
|
| + List<TryStatementInfo> tryNestingStack = <TryStatementInfo>[];
|
| + bool get inTryStatement => tryNestingStack.isNotEmpty;
|
| +
|
| + String bailoutMessage = null;
|
| +
|
| + giveup(ast.Node node, [String reason]) {
|
| + bailoutMessage = '($node): $reason';
|
| + throw ABORT_IRNODE_BUILDER;
|
| + }
|
| +
|
| + void markAsCaptured(Local local) {
|
| + capturedVariables.add(local);
|
| + }
|
| +
|
| + analyze(ast.Node node) {
|
| + visit(node);
|
| + // Variables that are captured by a closure are boxed for their entire
|
| + // lifetime, so they never need to be boxed on entry to a try block.
|
| + // They are not filtered out before this because we cannot identify all
|
| + // of them in the same pass (they may be captured by a closure after the
|
| + // try statement).
|
| + for (TryStatementInfo info in tryStatements.values) {
|
| + info.boxedOnEntry.removeAll(capturedVariables);
|
| + }
|
| + }
|
| +
|
| + visit(ast.Node node) => node.accept(this);
|
| +
|
| + visitNode(ast.Node node) {
|
| + node.visitChildren(this);
|
| + }
|
| +
|
| + visitFor(ast.For node) {
|
| + if (node.initializer != null) visit(node.initializer);
|
| + if (node.condition != null) visit(node.condition);
|
| + if (node.update != null) visit(node.update);
|
| +
|
| + // Give up if a variable was captured outside of the loop body.
|
| + if (node.initializer is ast.VariableDefinitions) {
|
| + ast.VariableDefinitions definitions = node.initializer;
|
| + for (ast.Node node in definitions.definitions.nodes) {
|
| + LocalElement loopVariable = elements[node];
|
| + if (capturedVariables.contains(loopVariable)) {
|
| + return giveup(node, 'For-loop variable captured in loop header');
|
| + }
|
| + }
|
| + }
|
| +
|
| + if (node.body != null) visit(node.body);
|
| + }
|
| +
|
| + void handleSend(ast.Send node) {
|
| + Element element = elements[node];
|
| + if (Elements.isLocal(element) &&
|
| + !element.isConst &&
|
| + element.enclosingElement != currentFunction) {
|
| + LocalElement local = element;
|
| + markAsCaptured(local);
|
| + }
|
| + }
|
| +
|
| + visitSend(ast.Send node) {
|
| + handleSend(node);
|
| + node.visitChildren(this);
|
| + }
|
| +
|
| + visitSendSet(ast.SendSet node) {
|
| + handleSend(node);
|
| + Element element = elements[node];
|
| + if (Elements.isLocal(element)) {
|
| + LocalElement local = element;
|
| + if (insideInitializer) {
|
| + assert(local.isParameter);
|
| + // Initializers in an initializer-list can communicate via parameters.
|
| + // If a parameter is stored in an initializer list we box it.
|
| + // TODO(sigurdm): Fix this.
|
| + // Though these variables do not outlive the activation of the
|
| // function, they still need to be boxed. As a simplification, we
|
| // treat them as if they are captured by a closure (i.e., they do
|
| // outlive the activation of the function).
|
| @@ -2190,15 +2879,6 @@ class DartIrBuilderVisitor extends IrBuilderVisitor {
|
| }
|
|
|
| @override
|
| - ir.Primitive buildReifyTypeVariable(ir.Primitive target,
|
| - TypeVariableType variable) {
|
| - assert(target == irBuilder.state.enclosingMethodThisParameter);
|
| - ir.Primitive prim = new ir.ReifyTypeVar(variable.element);
|
| - irBuilder.add(new ir.LetPrim(prim));
|
| - return prim;
|
| - }
|
| -
|
| - @override
|
| ir.Primitive handleConstructorInvoke(
|
| ast.NewExpression node,
|
| ConstructorElement constructor,
|
| @@ -2213,6 +2893,28 @@ class DartIrBuilderVisitor extends IrBuilderVisitor {
|
| type,
|
| arguments);
|
| }
|
| +
|
| + @override
|
| + ir.Primitive buildStaticNoSuchMethod(Selector selector,
|
| + List<ir.Primitive> arguments) {
|
| + return giveup(null, 'Static noSuchMethod');
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive buildInstanceNoSuchMethod(Selector selector,
|
| + List<ir.Primitive> arguments) {
|
| + return giveup(null, 'Instance noSuchMethod');
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive buildRuntimeError(String message) {
|
| + return giveup(null, 'Build runtime error: $message');
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive buildAbstractClassInstantiationError(ClassElement element) {
|
| + return giveup(null, 'Abstract class instantiation: ${element.name}');
|
| + }
|
| }
|
|
|
| /// The [IrBuilder]s view on the information about the program that has been
|
| @@ -2235,6 +2937,8 @@ class JsIrBuilderVisitor extends IrBuilderVisitor {
|
| /// Promote the type of [irBuilder] to [JsIrBuilder].
|
| JsIrBuilder get irBuilder => super.irBuilder;
|
|
|
| + JavaScriptBackend get backend => compiler.backend;
|
| +
|
| /// Result of closure conversion for the current body of code.
|
| ///
|
| /// Will be initialized upon entering the body of a function.
|
| @@ -2815,18 +3519,6 @@ class JsIrBuilderVisitor extends IrBuilderVisitor {
|
| }
|
| return result;
|
| }
|
| -
|
| - @override
|
| - ir.Primitive buildReifyTypeVariable(ir.Primitive target,
|
| - TypeVariableType variable) {
|
| - ir.Primitive typeArgument =
|
| - irBuilder.buildTypeVariableAccess(target, variable);
|
| -
|
| - ir.Primitive type = new ir.ReifyRuntimeType(typeArgument);
|
| - irBuilder.add(new ir.LetPrim(type));
|
| - return type;
|
| - }
|
| -
|
| @override
|
| ir.Primitive handleConstructorInvoke(
|
| ast.NewExpression node,
|
| @@ -2845,6 +3537,45 @@ class JsIrBuilderVisitor extends IrBuilderVisitor {
|
| constructor.computeEffectiveTargetType(type),
|
| arguments);
|
| }
|
| +
|
| + @override
|
| + ir.Primitive buildStaticNoSuchMethod(Selector selector,
|
| + List<ir.Primitive> arguments) {
|
| + Element thrower = backend.getThrowNoSuchMethod();
|
| + ir.Primitive receiver = irBuilder.buildStringConstant('');
|
| + ir.Primitive name = irBuilder.buildStringConstant(selector.name);
|
| + ir.Primitive argumentList = irBuilder.buildListLiteral(null, arguments);
|
| + ir.Primitive expectedArgumentNames = irBuilder.buildNullConstant();
|
| + return irBuilder.buildStaticFunctionInvocation(
|
| + thrower,
|
| + new CallStructure.unnamed(4),
|
| + [receiver, name, argumentList, expectedArgumentNames]);
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive buildInstanceNoSuchMethod(Selector selector,
|
| + List<ir.Primitive> arguments) {
|
| + return irBuilder.buildDynamicInvocation(
|
| + irBuilder.buildThis(),
|
| + useSelectorType(compiler.noSuchMethodSelector, selector),
|
| + [irBuilder.buildInvocationMirror(selector, arguments)]);
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive buildRuntimeError(String message) {
|
| + return irBuilder.buildStaticFunctionInvocation(
|
| + backend.getThrowRuntimeError(),
|
| + new CallStructure.unnamed(1),
|
| + [irBuilder.buildStringConstant(message)]);
|
| + }
|
| +
|
| + @override
|
| + ir.Primitive buildAbstractClassInstantiationError(ClassElement element) {
|
| + return irBuilder.buildStaticFunctionInvocation(
|
| + backend.getThrowAbstractClassInstantiationError(),
|
| + new CallStructure.unnamed(1),
|
| + [irBuilder.buildStringConstant(element.name)]);
|
| + }
|
| }
|
|
|
| /// Perform simple post-processing on the initial CPS-translated root term.
|
|
|