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

Unified Diff: pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart

Issue 1130813002: dart2js cps: Handle error cases. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Whitelist unused API due to semantic visitor being WIP Created 5 years, 7 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart ('k') | pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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.
« no previous file with comments | « pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart ('k') | pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698