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

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

Issue 1004683002: Refactor IrBuilder to use SemanticVisitor. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 9 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
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 3006d3b08480d6a28a07a5f55d113b96a82472e8..b9d916d84d4b8b42637cb05fbe306cc3b27ba01a 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
@@ -15,6 +15,8 @@ import '../elements/modelx.dart' show SynthesizedConstructorElementX,
import '../io/source_file.dart';
import '../io/source_information.dart';
import '../js_backend/js_backend.dart' show JavaScriptBackend;
+import '../resolution/semantic_visitor.dart';
+import '../resolution/operators.dart' as op;
import '../scanner/scannerlib.dart' show Token, isUserDefinableOperator;
import '../tree/tree.dart' as ast;
import '../universe/universe.dart' show SelectorKind;
@@ -116,21 +118,20 @@ class IrBuilderTask extends CompilerTask {
}
-class _GetterElements {
- ir.Primitive result;
- ir.Primitive index;
- ir.Primitive receiver;
-
- _GetterElements({this.result, this.index, this.receiver}) ;
-}
-
/**
* A tree visitor that builds [IrNodes]. The visit methods add statements using
* to the [builder] and return the last added statement for trees that represent
* an expression.
*/
-abstract class IrBuilderVisitor extends ResolvedVisitor<ir.Primitive>
- with IrBuilderMixin<ast.Node> {
+abstract class IrBuilderVisitor extends SemanticVisitor<ir.Primitive, dynamic>
+ with IrBuilderMixin<ast.Node>,
+ GroupStaticMixin<ir.Primitive, dynamic>,
floitsch 2015/03/12 18:04:02 Just looking at this, I have no idea what this (an
Johnni Winther 2015/03/16 13:28:13 Is 'GroupStaticSemantics' better ?
floitsch 2015/03/16 13:38:41 Maybe BaseImplementationOfStaticsMixin?
Johnni Winther 2015/03/20 13:40:59 Done.
+ GroupLocalMixin<ir.Primitive, dynamic>,
+ GroupDynamicMixin<ir.Primitive, dynamic>,
+ GroupConstantMixin<ir.Primitive, dynamic>,
+ GroupSuperMixin<ir.Primitive, dynamic>,
+ ErrorBulkMixin<ir.Primitive, dynamic>
+ implements SemanticSendVisitor<ir.Primitive, dynamic> {
final Compiler compiler;
final SourceInformationBuilder sourceInformationBuilder;
@@ -158,6 +159,15 @@ abstract class IrBuilderVisitor extends ResolvedVisitor<ir.Primitive>
this.sourceInformationBuilder)
: super(elements);
+ @override
+ bulkHandleNode(ast.Node node, String message) => giveup(node, message);
+
+ @override
+ ir.Primitive apply(ast.Node node, _) => node.accept(this);
+
+ @override
+ SemanticSendVisitor get sendVisitor => this;
+
/**
* Builds the [ir.ExecutableDefinition] for an executable element. In case the
* function uses features that cannot be expressed in the IR, this element
@@ -591,7 +601,11 @@ abstract class IrBuilderVisitor extends ResolvedVisitor<ir.Primitive>
}
// ==== Sends ====
floitsch 2015/03/12 18:04:02 nit (and not your code): if we have sections in th
Johnni Winther 2015/03/16 13:28:13 Converted into 2nd level headers.
- ir.Primitive visitAssert(ast.Send node) {
+ @override
+ ir.Primitive visitAssert(
+ ast.Send node,
+ ast.Node condition,
+ _) {
assert(irBuilder.isOpen);
return giveup(node, 'Assert');
}
@@ -601,109 +615,136 @@ abstract class IrBuilderVisitor extends ResolvedVisitor<ir.Primitive>
return visit(node.expression);
}
- ir.Primitive visitClosureSend(ast.Send node) {
- assert(irBuilder.isOpen);
- Element element = elements[node];
- Selector selector = elements.getSelector(node);
- ir.Primitive receiver = (element == null)
- ? visit(node.selector)
- : irBuilder.buildLocalGet(element);
+ @override
+ ir.Primitive visitExpressionInvoke(ast.Send node,
+ ast.Node expression,
+ ast.NodeList arguments,
+ Selector selector, _) {
+ ir.Primitive receiver = visit(expression);
List<ir.Primitive> arguments = node.arguments.mapToList(visit);
arguments = normalizeDynamicArguments(selector, arguments);
return irBuilder.buildCallInvocation(receiver, selector, arguments);
}
- /// If [node] is null, returns this.
- /// If [node] is super, returns null (for special handling)
- /// Otherwise visits [node] and returns the result.
- ir.Primitive visitReceiver(ast.Expression node) {
- if (node == null) return irBuilder.buildThis();
- if (node.isSuper()) return null;
- return visit(node);
- }
-
/// Returns `true` if [node] is a super call.
// TODO(johnniwinther): Remove the need for this.
bool isSuperCall(ast.Send node) {
return node != null && node.receiver != null && node.receiver.isSuper();
}
- ir.Primitive visitDynamicSend(ast.Send node) {
- assert(irBuilder.isOpen);
- Selector selector = elements.getSelector(node);
- ir.Primitive receiver = visitReceiver(node.receiver);
- List<ir.Primitive> arguments = node.arguments.mapToList(visit);
- arguments = normalizeDynamicArguments(selector, arguments);
- return irBuilder.buildDynamicInvocation(receiver, selector, arguments);
+ @override
+ ir.Primitive handleConstantGet(ast.Send node,
+ ConstantExpression constant, _) {
+ return irBuilder.buildConstantLiteral(constant);
}
- _GetterElements translateGetter(ast.Send node, Selector selector) {
- Element element = elements[node];
- ir.Primitive result;
- ir.Primitive receiver;
- ir.Primitive index;
-
- if (element != null && element.isConst) {
- // Reference to constant local, top-level or static field
- result = translateConstant(node);
- } else if (Elements.isLocal(element)) {
- // Reference to local variable
- result = irBuilder.buildLocalGet(element);
- } else if (element == null ||
- Elements.isInstanceField(element) ||
- Elements.isInstanceMethod(element) ||
- selector.isIndex ||
- // TODO(johnniwinther): clean up semantics of resolution.
- node.isSuperCall) {
- // Dynamic dispatch to a getter. Sometimes resolution will suggest a
- // target element, but in these cases we must still emit a dynamic
- // dispatch. The target element may be an instance method in case we are
- // converting a method to a function object.
-
- receiver = visitReceiver(node.receiver);
- List<ir.Primitive> arguments = new List<ir.Primitive>();
- if (selector.isIndex) {
- index = visit(node.arguments.head);
- arguments.add(index);
- }
+ /// If [node] is null, returns this.
+ /// Otherwise visits [node] and returns the result.
+ ir.Primitive translateReceiver(ast.Expression node) {
+ return node != null ? visit(node) : irBuilder.buildThis();
+ }
- assert(selector.kind == SelectorKind.GETTER ||
- selector.kind == SelectorKind.INDEX);
- if (isSuperCall(node)) {
- result = irBuilder.buildSuperInvocation(element, selector, arguments);
- } else {
- result =
- irBuilder.buildDynamicInvocation(receiver, selector, arguments);
- }
- } else if (element.isField || element.isGetter || element.isErroneous ||
- element.isSetter) {
- // TODO(johnniwinther): Change handling of setter selectors.
- // Access to a static field or getter (non-static case handled above).
- // Even if there is only a setter, we compile as if it was a getter,
- // so the vm can fail at runtime.
- assert(selector.kind == SelectorKind.GETTER ||
- selector.kind == SelectorKind.SETTER);
- result = irBuilder.buildStaticGet(element, selector,
- sourceInformation: sourceInformationBuilder.buildGet(node));
- } else if (Elements.isStaticOrTopLevelFunction(element)) {
- // Convert a top-level or static function to a function object.
- result = translateConstant(node);
- } else {
- throw "Unexpected SendSet getter: $node, $element";
+ @override
+ ir.Primitive handleDynamicGet(
+ ast.Send node,
+ ast.Node receiver,
+ Selector selector,
+ _) {
+ return irBuilder.buildDynamicGet(
+ translateReceiver(receiver),
+ selector);
+ }
+
+ @override
+ ir.Primitive visitDynamicTypeLiteralGet(
+ ast.Send node,
+ ConstantExpression constant,
+ _) {
+ return irBuilder.buildConstantLiteral(constant);
+ }
+
+ @override
+ ir.Primitive handleLocalGet(
+ ast.Send node,
+ LocalElement element,
+ _) {
+ return irBuilder.buildLocalGet(element);
+ }
+
+ @override
+ ir.Primitive handleStaticFieldGet(
+ ast.Send node,
+ FieldElement field,
+ _) {
+ return irBuilder.buildStaticGet(field);
+ }
+
+ @override
+ ir.Primitive handleStaticFunctionGet(
+ ast.Send node,
+ MethodElement function,
+ _) {
+ // TODO(karlklose): support foreign functions.
+ if (function.isForeign(compiler.backend)) {
+ return giveup(node, 'handleStaticFunctionGet: foreign: $function');
}
- return new _GetterElements(
- result: result,index: index, receiver: receiver);
+ return irBuilder.buildStaticGet(function);
}
- ir.Primitive visitGetterSend(ast.Send node) {
- assert(irBuilder.isOpen);
- return translateGetter(node, elements.getSelector(node)).result;
+ @override
+ ir.Primitive handleStaticGetterGet(
+ ast.Send node,
+ FunctionElement getter,
+ _) {
+ return irBuilder.buildStaticInvocation(getter,
+ new Selector.getter(getter.name, getter.library), const []);
+ }
+
+ @override
+ ir.Primitive visitSuperFieldGet(
+ ast.Send node,
+ FieldElement field,
+ _) {
+ return irBuilder.buildSuperGet(field);
+ }
+ @override
+ ir.Primitive visitSuperGetterGet(
+ ast.Send node,
+ FunctionElement getter,
+ _) {
+ return irBuilder.buildSuperGet(getter);
+ }
+
+ @override
+ ir.Primitive visitSuperMethodGet(
+ ast.Send node,
+ MethodElement method,
+ _) {
+ return irBuilder.buildSuperGet(method);
+ }
+
+ @override
+ ir.Primitive visitThisGet(ast.Identifier node, _) {
+ return irBuilder.buildThis();
}
- ir.Primitive translateLogicalOperator(ast.Operator op,
- ast.Expression left,
- ast.Expression right) {
+ ir.Primitive translateTypeVariableTypeLiteral(TypeVariableElement element) {
+ // TODO(johnniwinther): This should be a method on [IrBuilder].
+ ir.Primitive prim = new ir.ReifyTypeVar(element);
+ irBuilder.add(new ir.LetPrim(prim));
+ return prim;
+ }
+
+ @override
+ ir.Primitive visitTypeVariableTypeLiteralGet(ast.Send node,
+ TypeVariableElement element, _) {
+ return translateTypeVariableTypeLiteral(element);
+ }
+
+ ir.Primitive translateLogicalOperator(ast.Expression left,
+ ast.Expression right,
+ {bool isLazyOr}) {
ir.Primitive leftValue = visit(left);
ir.Primitive buildRightValue(IrBuilder rightBuilder) {
@@ -711,241 +752,886 @@ abstract class IrBuilderVisitor extends ResolvedVisitor<ir.Primitive>
}
return irBuilder.buildLogicalOperator(
- leftValue, buildRightValue, isLazyOr: op.source == '||');
+ leftValue, buildRightValue, isLazyOr: isLazyOr);
}
- ir.Primitive visitOperatorSend(ast.Send node) {
- assert(irBuilder.isOpen);
- ast.Operator op = node.selector;
- if (isUserDefinableOperator(op.source)) {
- return visitDynamicSend(node);
- }
- if (op.source == '&&' || op.source == '||') {
- assert(node.receiver != null);
- assert(!node.arguments.isEmpty);
- assert(node.arguments.tail.isEmpty);
- return translateLogicalOperator(op, node.receiver, node.arguments.head);
- }
- if (op.source == "!") {
- assert(node.receiver != null);
- assert(node.arguments.isEmpty);
- return irBuilder.buildNegation(visit(node.receiver));
- }
- if (op.source == "!=") {
- assert(node.receiver != null);
- assert(!node.arguments.isEmpty);
- assert(node.arguments.tail.isEmpty);
- return irBuilder.buildNegation(visitDynamicSend(node));
- }
- assert(invariant(node, op.source == "is" || op.source == "as",
- message: "unexpected operator $op"));
- DartType type = elements.getType(node.typeAnnotationFromIsCheckOrCast);
- ir.Primitive receiver = visit(node.receiver);
+ @override
+ ir.Primitive visitLogicalAnd(
+ ast.Send node, ast.Node left, ast.Node right, _) {
+ return translateLogicalOperator(left, right, isLazyOr: false);
+ }
+
+ @override
+ ir.Primitive visitLogicalOr(
+ ast.Send node, ast.Node left, ast.Node right, _) {
+ return translateLogicalOperator(left, right, isLazyOr: true);
+ }
+
+ @override
+ ir.Primitive visitAs(
+ ast.Send node,
+ ast.Node expression,
+ DartType type,
+ _) {
+ ir.Primitive receiver = visit(expression);
+ return irBuilder.buildTypeOperator(receiver, type, isTypeTest: false);
+ }
+
+ @override
+ ir.Primitive visitIs(
+ ast.Send node,
+ ast.Node expression,
+ DartType type,
+ _) {
+ ir.Primitive receiver = visit(expression);
return irBuilder.buildTypeOperator(
receiver, type,
- isTypeTest: op.source == "is",
- isNotCheck: node.isIsNotCheck);
+ isTypeTest: true,
+ isNotCheck: false);
}
- // Build(StaticSend(f, arguments), C) = C[C'[InvokeStatic(f, xs)]]
- // where (C', xs) = arguments.fold(Build, C)
- ir.Primitive visitStaticSend(ast.Send node) {
- assert(irBuilder.isOpen);
- Element element = elements[node];
- assert(!element.isConstructor);
- // TODO(lry): support foreign functions.
- if (element.isForeign(compiler.backend)) {
- return giveup(node, 'StaticSend: foreign');
- }
+ @override
+ ir.Primitive visitIsNot(ast.Send node,
+ ast.Node expression, DartType type, _) {
+ ir.Primitive receiver = visit(expression);
+ return irBuilder.buildTypeOperator(
+ receiver, type,
+ isTypeTest: true,
+ isNotCheck: true);
+ }
- Selector selector = elements.getSelector(node);
-
- if (selector.isCall && (element.isGetter || element.isField)) {
- // We are invoking a static field or getter as if it was a method, e.g:
- //
- // get foo => {..}
- // main() { foo(1, 2, 3); }
- //
- // We invoke the getter of 'foo' and then invoke the 'call' method
- // on the result, using the given arguments.
- Selector getter = new Selector.getterFrom(selector);
- Selector call = new Selector.callClosureFrom(selector);
- ir.Primitive receiver = irBuilder.buildStaticGet(element, getter);
- List<ir.Primitive> arguments = node.arguments.mapToList(visit);
- arguments = normalizeDynamicArguments(selector, arguments);
- return irBuilder.buildCallInvocation(receiver, call, arguments);
- } else if (selector.isGetter) {
- // We are reading a static field or invoking a static getter.
- return irBuilder.buildStaticGet(element, selector);
- } else {
- // We are invoking a static method.
- assert(selector.isCall);
- assert(element is FunctionElement);
- List<ir.Primitive> arguments = node.arguments.mapToList(visit);
- arguments = normalizeStaticArguments(selector, element, arguments);
- return irBuilder.buildStaticInvocation(element, selector, arguments,
- sourceInformation: sourceInformationBuilder.buildCall(node));
- }
+ ir.Primitive translateBinary(ast.Node left,
+ op.BinaryOperator operator,
+ ast.Node right) {
+ Selector selector = new Selector.binaryOperator(operator.selectorName);
+ ir.Primitive receiver = visit(left);
+ List<ir.Primitive> arguments = [visit(right)];
+ arguments = normalizeDynamicArguments(selector, arguments);
+ return irBuilder.buildDynamicInvocation(receiver, selector, arguments);
}
- ir.Primitive visitSuperSend(ast.Send node) {
- assert(irBuilder.isOpen);
- Selector selector = elements.getSelector(node);
- Element target = elements[node];
-
- if (selector.isCall && (target.isGetter || target.isField)) {
- // We are invoking a field or getter as if it was a method, e.g:
- //
- // class A { get foo => {..} }
- // class B extends A {
- // m() {
- // super.foo(1, 2, 3); }
- // }
- // }
- //
- // We invoke the getter of 'foo' and then invoke the 'call' method on
- // the result, using the given arguments.
- Selector getter = new Selector.getterFrom(selector);
- Selector call = new Selector.callClosureFrom(selector);
- ir.Primitive receiver =
- irBuilder.buildSuperInvocation(target, getter, []);
- List<ir.Primitive> arguments = node.arguments.mapToList(visit);
- arguments = normalizeDynamicArguments(selector, arguments);
- return irBuilder.buildCallInvocation(receiver, call, arguments);
- } else if (selector.isCall) {
- // We are invoking a method.
- assert(target is FunctionElement);
- List<ir.Primitive> arguments = node.arguments.mapToList(visit);
- arguments = normalizeStaticArguments(selector, target, arguments);
- return irBuilder.buildSuperInvocation(target, selector, arguments);
- } else {
- // We are invoking a getter, operator, indexer, etc.
- List<ir.Primitive> arguments = node.argumentsNode == null
- ? <ir.Primitive>[]
- : node.arguments.mapToList(visit);
- return irBuilder.buildSuperInvocation(target, selector, arguments);
- }
+ @override
+ ir.Primitive visitBinary(ast.Send node,
+ ast.Node left,
+ op.BinaryOperator operator,
+ ast.Node right, _) {
+ return translateBinary(left, operator, right);
}
- visitTypePrefixSend(ast.Send node) {
- compiler.internalError(node, "visitTypePrefixSend should not be called.");
+ @override
+ ir.Primitive visitIndex(ast.Send node,
+ ast.Node receiver,
+ ast.Node index, _) {
+ Selector selector = new Selector.index();
+ ir.Primitive target = visit(receiver);
+ List<ir.Primitive> arguments = [visit(index)];
+ arguments = normalizeDynamicArguments(selector, arguments);
+ return irBuilder.buildDynamicInvocation(target, selector, arguments);
}
- ir.Primitive visitTypeLiteralSend(ast.Send node) {
- assert(irBuilder.isOpen);
- // If the user is trying to invoke the type literal or variable,
- // it must be treated as a function call.
- if (node.argumentsNode != null) {
- // TODO(sigurdm): Handle this to match proposed semantics of issue #19725.
- return giveup(node, 'Type literal invoked as function');
- }
+ ir.Primitive translateSuperBinary(FunctionElement function,
+ op.BinaryOperator operator,
+ ast.Node argument) {
+ Selector selector = new Selector.binaryOperator(operator.selectorName);
+ List<ir.Primitive> arguments = [visit(argument)];
+ arguments = normalizeDynamicArguments(selector, arguments);
+ return irBuilder.buildSuperInvocation(function, selector, arguments);
+ }
- DartType type = elements.getTypeLiteralType(node);
- if (type is TypeVariableType) {
- return buildReifyTypeVariable(irBuilder.buildThis(), type);
- } else {
- return translateConstant(node);
+ @override
+ ir.Primitive visitSuperBinary(
+ ast.Send node,
+ FunctionElement function,
+ op.BinaryOperator operator,
+ ast.Node argument,
+ _) {
+ return translateSuperBinary(function, operator, argument);
+ }
+
+ @override
+ ir.Primitive visitSuperIndex(
+ ast.Send node,
+ FunctionElement function,
+ ast.Node index,
+ _) {
+ Selector selector = new Selector.index();
+ List<ir.Primitive> arguments = [visit(index)];
+ arguments = normalizeDynamicArguments(selector, arguments);
+ return irBuilder.buildSuperInvocation(function, selector, arguments);
+ }
+
+ @override
+ ir.Primitive visitEquals(
+ ast.Send node,
+ ast.Node left,
+ ast.Node right,
+ _) {
+ return translateBinary(left, op.BinaryOperator.EQ, right);
+ }
+
+ @override
+ ir.Primitive visitSuperEquals(
+ ast.Send node,
+ FunctionElement function,
+ ast.Node argument,
+ _) {
+ return translateSuperBinary(function, op.BinaryOperator.EQ, argument);
+ }
+
+ @override
+ ir.Primitive visitNot(
+ ast.Send node,
+ ast.Node expression,
+ _) {
+ return irBuilder.buildNegation(visit(expression));
+ }
+
+ @override
+ ir.Primitive visitNotEquals(
+ ast.Send node,
+ ast.Node left,
+ ast.Node right,
+ _) {
+ return irBuilder.buildNegation(
+ translateBinary(left, op.BinaryOperator.NOT_EQ, right));
+ }
+
+ @override
+ ir.Primitive visitSuperNotEquals(
+ ast.Send node,
+ FunctionElement function,
+ ast.Node argument,
+ _) {
+ return irBuilder.buildNegation(
+ translateSuperBinary(function, op.BinaryOperator.NOT_EQ, argument));
+ }
+
+ @override
+ ir.Primitive visitUnary(ast.Send node,
+ op.UnaryOperator operator, ast.Node expression, _) {
+ // TODO(johnniwinther): Clean up the creation of selectors.
+ Selector selector =
+ new Selector(SelectorKind.OPERATOR, operator.selectorName, null, 0);
+ ir.Primitive receiver = translateReceiver(expression);
+ return irBuilder.buildDynamicInvocation(receiver, selector, const []);
+ }
+
+ @override
+ ir.Primitive visitSuperUnary(
+ ast.Send node,
+ op.UnaryOperator operator,
+ FunctionElement function,
+ _) {
+ // TODO(johnniwinther): Clean up the creation of selectors.
+ Selector selector =
+ new Selector(SelectorKind.OPERATOR, operator.selectorName, null, 0);
+ return irBuilder.buildSuperInvocation(function, selector, const []);
+ }
+
+ // TODO(johnniwinther): Handle this in the [IrBuilder] to ensure the correct
+ // semantic correlation between arguments and invocation.
+ List<ir.Primitive> translateDynamicArguments(ast.NodeList nodeList,
+ Selector selector) {
+ List<ir.Primitive> arguments = nodeList.nodes.mapToList(visit);
+ return normalizeDynamicArguments(selector, arguments);
+ }
+
+ // TODO(johnniwinther): Handle this in the [IrBuilder] to ensure the correct
+ // semantic correlation between arguments and invocation.
+ List<ir.Primitive> translateStaticArguments(ast.NodeList nodeList,
+ Element element,
+ Selector selector) {
+ List<ir.Primitive> arguments = nodeList.nodes.mapToList(visit);
+ return normalizeStaticArguments(selector, element, arguments);
+ }
+
+ ir.Primitive translateCallInvoke(ir.Primitive target,
+ ast.NodeList arguments,
+ Selector selector) {
+
+ return irBuilder.buildCallInvocation(target, selector,
+ translateDynamicArguments(arguments, selector));
+ }
+
+ ir.Primitive translateConstantInvoke(ConstantExpression constant,
+ ast.NodeList arguments,
+ Selector selector) {
+ return translateCallInvoke(
+ irBuilder.buildConstantLiteral(constant),
+ arguments,
+ selector);
+ }
+
+ @override
+ ir.Primitive handleConstantInvoke(
+ ast.Send node,
+ ConstantExpression constant,
+ ast.NodeList arguments,
+ Selector selector,
+ _) {
+ return translateConstantInvoke(constant, arguments, selector);
+ }
+
+ @override
+ ir.Primitive handleDynamicInvoke(
+ ast.Send node,
+ ast.Node receiver,
+ ast.NodeList arguments,
+ Selector selector,
+ _) {
+ return irBuilder.buildDynamicInvocation(
+ translateReceiver(receiver), selector,
+ translateDynamicArguments(arguments, selector));
+ }
+
+ ir.Primitive handleLocalInvoke(
+ ast.Send node,
+ LocalElement element,
+ ast.NodeList arguments,
+ Selector selector,
+ _) {
+ return irBuilder.buildLocalInvocation(element, selector,
+ translateDynamicArguments(arguments, selector));
+ }
+
+ @override
+ ir.Primitive handleStaticFieldInvoke(
+ ast.Send node,
+ FieldElement field,
+ ast.NodeList arguments,
+ Selector selector,
+ _) {
+ return translateCallInvoke(
+ irBuilder.buildStaticGet(field),
+ arguments, selector);
+ }
+
+ @override
+ ir.Primitive handleStaticFunctionInvoke(
+ ast.Send node,
+ MethodElement function,
+ ast.NodeList arguments,
+ Selector selector,
+ _) {
+ // TODO(karlklose): support foreign functions.
+ if (function.isForeign(compiler.backend)) {
+ return giveup(node, 'handleStaticFunctionInvoke: foreign: $function');
}
+ return irBuilder.buildStaticInvocation(function, selector,
+ translateStaticArguments(arguments, function, selector));
+ }
+
+ @override
+ ir.Primitive handleStaticGetterInvoke(
+ ast.Send node,
+ FunctionElement getter,
+ ast.NodeList arguments,
+ Selector selector,
+ _) {
+ return translateCallInvoke(
+ irBuilder.buildStaticGet(getter),
+ arguments, selector);
+ }
+
+ @override
+ ir.Primitive visitSuperFieldInvoke(
+ ast.Send node,
+ FieldElement field,
+ ast.NodeList arguments,
+ Selector selector,
+ _) {
+ return translateCallInvoke(
+ irBuilder.buildSuperGet(field),
+ arguments, selector);
+ }
+
+ @override
+ ir.Primitive visitSuperGetterInvoke(
+ ast.Send node,
+ FunctionElement getter,
+ ast.NodeList arguments,
+ Selector selector,
+ _) {
+ return translateCallInvoke(
+ irBuilder.buildStaticGet(getter),
+ arguments, selector);
+ }
+
+ @override
+ ir.Primitive visitSuperMethodInvoke(
+ ast.Send node,
+ MethodElement method,
+ ast.NodeList arguments,
+ Selector selector,
+ _) {
+ return irBuilder.buildStaticInvocation(method, selector,
+ translateDynamicArguments(arguments, selector));
+ }
+
+ @override
+ ir.Primitive visitThisInvoke(
+ ast.Send node,
+ ast.NodeList arguments,
+ Selector selector,
+ _) {
+ return translateCallInvoke(irBuilder.buildThis(), arguments, selector);
+ }
+
+ @override
+ ir.Primitive visitTypeVariableTypeLiteralInvoke(
+ ast.Send node,
+ TypeVariableElement element,
+ ast.NodeList arguments,
+ Selector selector,
+ _) {
+ return translateCallInvoke(
+ translateTypeVariableTypeLiteral(element),
+ arguments,
+ selector);
+ }
+
+ @override
+ ir.Primitive visitTypedefTypeLiteralInvoke(
+ ast.Send node,
+ TypeConstantExpression constant,
+ ast.NodeList arguments,
+ Selector selector, _) {
+ return translateConstantInvoke(constant, arguments, selector);
}
ir.Primitive buildReifyTypeVariable(ir.Primitive target,
TypeVariableType variable);
- ir.Primitive visitSendSet(ast.SendSet node) {
- assert(irBuilder.isOpen);
- Element element = elements[node];
- ast.Operator op = node.assignmentOperator;
- // For complex operators, this is the result of getting (before assigning)
- ir.Primitive originalValue;
- // For []+= style operators, this saves the index.
- ir.Primitive index;
- ir.Primitive receiver;
- // This is what gets assigned.
- ir.Primitive valueToStore;
- Selector selector = elements.getSelector(node);
+ @override
+ ir.Primitive visitIndexSet(
+ ast.SendSet node,
+ ast.Node receiver,
+ ast.Node index,
+ ast.Node rhs,
+ _) {
+ return irBuilder.buildDynamicIndexSet(
+ visit(receiver), visit(index), visit(rhs));
+ }
+
+ @override
+ ir.Primitive visitSuperIndexSet(
+ ast.SendSet node,
+ FunctionElement function,
+ ast.Node index,
+ ast.Node rhs,
+ _) {
+ return irBuilder.buildSuperIndexSet(function, visit(index), visit(rhs));
+ }
+
+ @override
+ ir.Primitive visitCompoundIndexSet(
+ ast.SendSet node,
+ ast.Node receiver,
+ ast.Node index,
+ op.AssignmentOperator operator,
+ ast.Node rhs,
+ _) {
+ ir.Primitive target = visit(receiver);
+ ir.Primitive indexValue = visit(index);
+ return translateCompound(
+ getValue: () {
+ Selector selector =
+ new Selector.binaryOperator(operator.selectorName);
+ List<ir.Primitive> arguments = [indexValue];
+ arguments = normalizeDynamicArguments(selector, arguments);
+ return irBuilder.buildDynamicInvocation(target, selector, arguments);
+ },
+ operator: operator,
+ rhs: rhs,
+ setValue: (ir.Primitive result) {
+ irBuilder.buildDynamicIndexSet(target, indexValue, result);
+ });
+ }
+
+ @override
+ ir.Primitive visitSuperCompoundIndexSet(
+ ast.SendSet node,
+ FunctionElement getter,
+ FunctionElement setter,
+ ast.Node index,
+ op.AssignmentOperator operator,
+ ast.Node rhs,
+ _) {
+ ir.Primitive indexValue = visit(index);
+ return translateCompound(
+ getValue: () {
+ Selector selector =
+ new Selector.binaryOperator(operator.selectorName);
+ List<ir.Primitive> arguments = [indexValue];
+ arguments = normalizeDynamicArguments(selector, arguments);
+ return irBuilder.buildSuperInvocation(getter, selector, arguments);
+ },
+ operator: operator,
+ rhs: rhs,
+ setValue: (ir.Primitive result) {
+ irBuilder.buildSuperIndexSet(setter, indexValue, result);
+ });
+ }
+
+ ir.Primitive translatePrefixPostfix(
+ {ir.Primitive getValue(),
+ op.IncDecOperator operator,
+ void setValue(ir.Primitive value),
+ bool isPrefix}) {
+ ir.Primitive value = getValue();
Selector operatorSelector =
- elements.getOperatorSelectorInComplexSendSet(node);
- Selector getterSelector =
- elements.getGetterSelectorInComplexSendSet(node);
- assert(
- // Indexing send-sets have an argument for the index.
- (selector.isIndexSet ? 1 : 0) +
- // Non-increment send-sets have one more argument.
- (ast.Operator.INCREMENT_OPERATORS.contains(op.source) ? 0 : 1)
- == node.argumentCount());
-
- ast.Node getAssignArgument() {
- assert(invariant(node, !node.arguments.isEmpty,
- message: "argument expected"));
- return selector.isIndexSet
- ? node.arguments.tail.head
- : node.arguments.head;
- }
+ new Selector.binaryOperator(operator.selectorName);
+ List<ir.Primitive> arguments = [irBuilder.buildIntegerLiteral(1)];
+ arguments = normalizeDynamicArguments(operatorSelector, arguments);
+ ir.Primitive result =
+ irBuilder.buildDynamicInvocation(value, operatorSelector, arguments);
+ setValue(result);
+ return isPrefix ? result : value;
+ }
+
+ ir.Primitive translateCompound(
+ {ir.Primitive getValue(),
+ op.AssignmentOperator operator,
+ ast.Node rhs,
+ void setValue(ir.Primitive value)}) {
+ ir.Primitive value = getValue();
+ Selector operatorSelector =
+ new Selector.binaryOperator(operator.selectorName);
+ List<ir.Primitive> arguments = [visit(rhs)];
+ arguments = normalizeDynamicArguments(operatorSelector, arguments);
+ ir.Primitive result =
+ irBuilder.buildDynamicInvocation(value, operatorSelector, arguments);
+ setValue(result);
+ return result;
+ }
- // Get the value into valueToStore
- if (op.source == "=") {
- if (selector.isIndexSet) {
- receiver = visitReceiver(node.receiver);
- index = visit(node.arguments.head);
- } else if (element == null || Elements.isInstanceField(element)) {
- receiver = visitReceiver(node.receiver);
- }
- valueToStore = visit(getAssignArgument());
- } else {
- // Get the original value into getter
- assert(ast.Operator.COMPLEX_OPERATORS.contains(op.source));
-
- _GetterElements getterResult = translateGetter(node, getterSelector);
- index = getterResult.index;
- receiver = getterResult.receiver;
- originalValue = getterResult.result;
-
- // Do the modification of the value in getter.
- ir.Primitive arg;
- if (ast.Operator.INCREMENT_OPERATORS.contains(op.source)) {
- arg = irBuilder.buildIntegerLiteral(1);
- } else {
- arg = visit(getAssignArgument());
- }
- valueToStore = new ir.Parameter(null);
- ir.Continuation k = new ir.Continuation([valueToStore]);
- ir.Expression invoke =
- new ir.InvokeMethod(originalValue, operatorSelector, k, [arg]);
- irBuilder.add(new ir.LetCont(k, invoke));
- }
+ @override
+ ir.Primitive handleDynamicCompound(
+ ast.Send node,
+ ast.Node receiver,
+ op.AssignmentOperator operator,
+ ast.Node rhs,
+ Selector getterSelector,
+ Selector setterSelector,
+ _) {
+ ir.Primitive target = translateReceiver(receiver);
+ return translateCompound(
+ getValue: () => irBuilder.buildDynamicGet(target, getterSelector),
+ operator: operator,
+ rhs: rhs,
+ setValue: (ir.Primitive result) {
+ irBuilder.buildDynamicSet(target, setterSelector, result);
+ });
+ }
- if (Elements.isLocal(element)) {
- irBuilder.buildLocalSet(element, valueToStore);
- } else if ((!node.isSuperCall && Elements.isErroneous(element)) ||
- Elements.isStaticOrTopLevel(element)) {
- irBuilder.buildStaticSet(
- element, elements.getSelector(node), valueToStore);
- } else {
- // Setter or index-setter invocation
- Selector selector = elements.getSelector(node);
- assert(selector.kind == SelectorKind.SETTER ||
- selector.kind == SelectorKind.INDEX);
- if (selector.isIndexSet) {
- if (isSuperCall(node)) {
- irBuilder.buildSuperIndexSet(element, index, valueToStore);
- } else {
- irBuilder.buildDynamicIndexSet(receiver, index, valueToStore);
- }
- } else {
- if (isSuperCall(node)) {
- irBuilder.buildSuperSet(element, selector, valueToStore);
- } else {
- irBuilder.buildDynamicSet(receiver, selector, valueToStore);
- }
- }
- }
+ @override
+ ir.Primitive handleDynamicPostfixPrefix(
+ ast.Send node,
+ ast.Node receiver,
+ op.IncDecOperator operator,
+ Selector getterSelector,
+ Selector setterSelector,
+ arg,
+ {bool isPrefix}) {
+ ir.Primitive target = translateReceiver(receiver);
+ return translatePrefixPostfix(
+ getValue: () => irBuilder.buildDynamicGet(target, getterSelector),
+ operator: operator,
+ setValue: (ir.Primitive result) {
+ irBuilder.buildDynamicSet(target, setterSelector, result);
+ },
+ isPrefix: isPrefix);
+ }
- if (node.isPostfix) {
- assert(originalValue != null);
- return originalValue;
- } else {
- return valueToStore;
- }
+ @override
+ ir.Primitive handleDynamicSet(
+ ast.SendSet node,
+ ast.Node receiver,
+ Selector selector,
+ ast.Node rhs,
+ _) {
+ return irBuilder.buildDynamicSet(
+ translateReceiver(receiver),
+ selector,
+ visit(rhs));
+ }
+
+ @override
+ ir.Primitive handleLocalCompound(
+ ast.Send node,
+ LocalElement element,
+ op.AssignmentOperator operator,
+ ast.Node rhs,
+ _) {
+ return translateCompound(
+ getValue: () => irBuilder.buildLocalGet(element),
+ operator: operator,
+ rhs: rhs,
+ setValue: (ir.Primitive result) {
+ irBuilder.buildLocalSet(element, result);
+ });
+ }
+
+ @override
+ ir.Primitive handleLocalPostfixPrefix(
+ ast.Send node,
+ LocalElement element,
+ op.IncDecOperator operator,
+ arg,
+ {bool isPrefix}) {
+ return translatePrefixPostfix(
+ getValue: () => irBuilder.buildLocalGet(element),
+ operator: operator,
+ setValue: (ir.Primitive result) {
+ irBuilder.buildLocalSet(element, result);
+ },
+ isPrefix: isPrefix);
+ }
+
+ @override
+ ir.Primitive handleLocalSet(
+ ast.SendSet node,
+ LocalElement element,
+ ast.Node rhs,
+ _) {
+ return irBuilder.buildLocalSet(element, visit(rhs));
+ }
+
+ @override
+ ir.Primitive handleStaticFieldCompound(
+ ast.Send node,
+ FieldElement field,
+ op.AssignmentOperator operator,
+ ast.Node rhs,
+ _) {
+ return translateCompound(
+ getValue: () => irBuilder.buildStaticGet(field),
+ operator: operator,
+ rhs: rhs,
+ setValue: (ir.Primitive result) {
+ irBuilder.buildStaticSet(field, result);
+ });
+ }
+
+ @override
+ ir.Primitive handleStaticFieldPostfixPrefix(
+ ast.Send node,
+ FieldElement field,
+ op.IncDecOperator operator,
+ arg,
+ {bool isPrefix}) {
+ return translatePrefixPostfix(
+ getValue: () => irBuilder.buildStaticGet(field),
+ operator: operator,
+ setValue: (ir.Primitive result) {
+ irBuilder.buildStaticSet(field, result);
+ },
+ isPrefix: isPrefix);
+ }
+
+ @override
+ ir.Primitive handleStaticFieldSet(
+ ast.SendSet node,
+ FieldElement field,
+ ast.Node rhs,
+ _) {
+ return irBuilder.buildStaticSet(field, visit(rhs));
+ }
+
+ @override
+ ir.Primitive visitSuperFieldSet(
+ ast.SendSet node,
+ FieldElement field,
+ ast.Node rhs,
+ _) {
+ return irBuilder.buildSuperSet(field, visit(rhs));
+ }
+
+ @override
+ ir.Primitive visitSuperSetterSet(
+ ast.SendSet node,
+ FunctionElement setter,
+ ast.Node rhs,
+ _) {
+ return irBuilder.buildSuperSet(setter, visit(rhs));
+ }
+
+ @override
+ ir.Primitive handleStaticGetterSetterCompound(
+ ast.Send node,
+ FunctionElement getter,
+ FunctionElement setter,
+ op.AssignmentOperator operator,
+ ast.Node rhs,
+ _) {
+ return translateCompound(
+ getValue: () => irBuilder.buildStaticGet(getter),
+ operator: operator,
+ rhs: rhs,
+ setValue: (ir.Primitive result) {
+ irBuilder.buildStaticSet(setter, result);
+ });
+ }
+
+ @override
+ ir.Primitive handleSuperFieldFieldPostfixPrefix(
+ ast.Send node,
+ FieldElement readField,
+ FieldElement writtenField,
+ op.IncDecOperator operator,
+ arg,
+ {bool isPrefix}) {
+ return translatePrefixPostfix(
+ getValue: () => irBuilder.buildSuperGet(readField),
+ operator: operator,
+ setValue: (ir.Primitive result) {
+ irBuilder.buildSuperSet(writtenField, result);
+ },
+ isPrefix: isPrefix);
+ }
+
+ @override
+ ir.Primitive handleSuperFieldSetterPostfixPrefix(
+ ast.Send node,
+ FieldElement field,
+ FunctionElement setter,
+ op.IncDecOperator operator,
+ arg,
+ {bool isPrefix}) {
+ return translatePrefixPostfix(
+ getValue: () => irBuilder.buildSuperGet(field),
+ operator: operator,
+ setValue: (ir.Primitive result) {
+ irBuilder.buildSuperSet(setter, result);
+ },
+ isPrefix: isPrefix);
+ }
+
+ @override
+ ir.Primitive handleSuperGetterFieldPostfixPrefix(
+ ast.Send node,
+ FunctionElement getter,
+ FieldElement field,
+ op.IncDecOperator operator,
+ arg,
+ {bool isPrefix}) {
+ return translatePrefixPostfix(
+ getValue: () => irBuilder.buildSuperGet(getter),
+ operator: operator,
+ setValue: (ir.Primitive result) {
+ irBuilder.buildSuperSet(field, result);
+ },
+ isPrefix: isPrefix);
+ }
+
+ @override
+ ir.Primitive handleSuperGetterSetterPostfixPrefix(
+ ast.Send node,
+ FunctionElement getter,
+ FunctionElement setter,
+ op.IncDecOperator operator,
+ arg,
+ {bool isPrefix}) {
+ return translatePrefixPostfix(
+ getValue: () => irBuilder.buildSuperGet(getter),
+ operator: operator,
+ setValue: (ir.Primitive result) {
+ irBuilder.buildSuperSet(setter, result);
+ },
+ isPrefix: isPrefix);
+ }
+
+ @override
+ ir.Primitive handleSuperMethodSetterPostfixPrefix(
+ ast.Send node,
+ FunctionElement method,
+ FunctionElement setter,
+ op.IncDecOperator operator,
+ arg,
+ {bool isPrefix}) {
+ return translatePrefixPostfix(
+ getValue: () => irBuilder.buildSuperGet(method),
+ operator: operator,
+ setValue: (ir.Primitive result) {
+ irBuilder.buildSuperSet(setter, result);
+ },
+ isPrefix: isPrefix);
+ }
+
+ @override
+ ir.Primitive handleStaticGetterSetterPostfixPrefix(
+ ast.Send node,
+ FunctionElement getter,
+ FunctionElement setter,
+ op.IncDecOperator operator,
+ arg,
+ {bool isPrefix}) {
+ return translatePrefixPostfix(
+ getValue: () => irBuilder.buildStaticGet(getter),
+ operator: operator,
+ setValue: (ir.Primitive result) {
+ irBuilder.buildStaticSet(setter, result);
+ },
+ isPrefix: isPrefix);
+ }
+
+ @override
+ ir.Primitive handleStaticMethodSetterCompound(
+ ast.Send node,
+ FunctionElement method,
+ FunctionElement setter,
+ op.AssignmentOperator operator,
+ ast.Node rhs,
+ _) {
+ return translateCompound(
+ getValue: () => irBuilder.buildStaticGet(method),
+ operator: operator,
+ rhs: rhs,
+ setValue: (ir.Primitive result) {
+ irBuilder.buildStaticSet(setter, result);
+ });
+ }
+
+ @override
+ ir.Primitive handleStaticMethodSetterPostfixPrefix(
+ ast.Send node,
+ FunctionElement getter,
+ FunctionElement setter,
+ op.IncDecOperator operator,
+ arg,
+ {bool isPrefix}) {
+ return translatePrefixPostfix(
+ getValue: () => irBuilder.buildStaticGet(getter),
+ operator: operator,
+ setValue: (ir.Primitive result) {
+ irBuilder.buildStaticSet(setter, result);
+ },
+ isPrefix: isPrefix);
+ }
+
+ @override
+ ir.Primitive handleStaticSetterSet(
+ ast.SendSet node,
+ FunctionElement setter,
+ ast.Node rhs,
+ _) {
+ return irBuilder.buildStaticSet(setter, visit(rhs));
+ }
+
+ @override
+ ir.Primitive visitSuperFieldCompound(
+ ast.Send node,
+ FieldElement field,
+ op.AssignmentOperator operator,
+ ast.Node rhs,
+ _) {
+ return translateCompound(
+ getValue: () => irBuilder.buildSuperGet(field),
+ operator: operator,
+ rhs: rhs,
+ setValue: (ir.Primitive result) {
+ irBuilder.buildSuperSet(field, result);
+ });
+ }
+
+ @override
+ ir.Primitive visitSuperFieldFieldPostfix(
+ ast.Send node,
+ FieldElement readField,
+ FieldElement writtenField,
+ op.IncDecOperator operator,
+ _) {
+ return translatePrefixPostfix(
+ getValue: () => irBuilder.buildStaticGet(readField),
+ operator: operator,
+ setValue: (ir.Primitive result) {
+ irBuilder.buildStaticSet(writtenField, result);
+ },
+ isPrefix: false);
+ }
+
+ @override
+ ir.Primitive visitSuperFieldFieldPrefix(
+ ast.Send node,
+ FieldElement readField,
+ FieldElement writtenField,
+ op.IncDecOperator operator,
+ _) {
+ return translatePrefixPostfix(
+ getValue: () => irBuilder.buildStaticGet(readField),
+ operator: operator,
+ setValue: (ir.Primitive result) {
+ irBuilder.buildStaticSet(writtenField, result);
+ },
+ isPrefix: true);
+ }
+
+ @override
+ ir.Primitive visitSuperFieldSetterCompound(
+ ast.Send node,
+ FieldElement field,
+ FunctionElement setter,
+ op.AssignmentOperator operator,
+ ast.Node rhs,
+ _) {
+ return translateCompound(
+ getValue: () => irBuilder.buildSuperGet(field),
+ operator: operator,
+ rhs: rhs,
+ setValue: (ir.Primitive result) {
+ irBuilder.buildSuperSet(setter, result);
+ });
+ }
+
+ @override
+ ir.Primitive visitSuperGetterFieldCompound(
+ ast.Send node,
+ FunctionElement getter,
+ FieldElement field,
+ op.AssignmentOperator operator,
+ ast.Node rhs,
+ _) {
+ return translateCompound(
+ getValue: () => irBuilder.buildSuperGet(getter),
+ operator: operator,
+ rhs: rhs,
+ setValue: (ir.Primitive result) {
+ irBuilder.buildSuperSet(field, result);
+ });
+ }
+
+ @override
+ ir.Primitive visitSuperGetterSetterCompound(
+ ast.Send node,
+ FunctionElement getter,
+ FunctionElement setter,
+ op.AssignmentOperator operator,
+ ast.Node rhs,
+ _) {
+ return translateCompound(
+ getValue: () => irBuilder.buildSuperGet(getter),
+ operator: operator,
+ rhs: rhs,
+ setValue: (ir.Primitive result) {
+ irBuilder.buildSuperSet(setter, result);
+ });
+ }
+
+ @override
+ ir.Primitive visitSuperMethodSetterCompound(
+ ast.Send node,
+ FunctionElement method,
+ FunctionElement setter,
+ op.AssignmentOperator operator,
+ ast.Node rhs,
+ _) {
+ return translateCompound(
+ getValue: () => irBuilder.buildSuperGet(method),
+ operator: operator,
+ rhs: rhs,
+ setValue: (ir.Primitive result) {
+ irBuilder.buildSuperSet(setter, result);
+ });
}
ir.Primitive visitNewExpression(ast.NewExpression node) {
@@ -999,9 +1685,14 @@ abstract class IrBuilderVisitor extends ResolvedVisitor<ir.Primitive>
}
}
- void internalError(String reason, {ast.Node node}) {
+ void internalError(ast.Node node, String message) {
giveup(node);
}
+
+ @override
+ visitNode(ast.Node node) {
+ internalError(node, "Unhandled node");
+ }
}
final String ABORT_IRNODE_BUILDER = "IrNode builder aborted";

Powered by Google App Engine
This is Rietveld 408576698