mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 00:58:29 +00:00
dart2js-kernel: Implement Let and PropertySet.
The Accessor builders capture some subexpressions to help map kernel Nodes to Ast Nodes. R=asgerf@google.com Review URL: https://codereview.chromium.org/2526123002 .
This commit is contained in:
parent
d92107e01d
commit
b20b10a0af
|
@ -73,6 +73,7 @@ class Kernel {
|
|||
|
||||
final Map<ir.Node, Element> nodeToElement = <ir.Node, Element>{};
|
||||
final Map<ir.Node, Node> nodeToAst = <ir.Node, Node>{};
|
||||
final Map<ir.Node, Node> nodeToAstOperator = <ir.Node, Node>{};
|
||||
|
||||
/// FIFO queue of work that needs to be completed before the returned AST
|
||||
/// nodes are correct.
|
||||
|
|
|
@ -1230,6 +1230,7 @@ class KernelVisitor extends Object
|
|||
@override
|
||||
ir.Expression visitCompoundIndexSet(SendSet node, Node receiver, Node index,
|
||||
AssignmentOperator operator, Node rhs, _) {
|
||||
// TODO(sra): Find binary operator.
|
||||
return buildIndexAccessor(receiver, index).buildCompoundAssignment(
|
||||
kernel.irName(operator.selectorName, currentElement),
|
||||
visitForValue(rhs),
|
||||
|
@ -1289,7 +1290,8 @@ class KernelVisitor extends Object
|
|||
receiver == null ? new ir.ThisExpression() : visitForValue(receiver);
|
||||
ir.Expression compound = buildCompound(
|
||||
PropertyAccessor.make(receiverNode, nameToIrName(name), null, null),
|
||||
rhs);
|
||||
rhs,
|
||||
node);
|
||||
if (compound is ir.VariableSet) {
|
||||
associateNode(compound.value, node);
|
||||
} else {
|
||||
|
@ -1720,19 +1722,32 @@ class KernelVisitor extends Object
|
|||
return buildLocalGet(element);
|
||||
}
|
||||
|
||||
ir.Expression buildCompound(Accessor accessor, CompoundRhs rhs) {
|
||||
ir.Expression buildCompound(
|
||||
Accessor accessor, CompoundRhs rhs, SendSet node) {
|
||||
ir.Name name = kernel.irName(rhs.operator.selectorName, currentElement);
|
||||
ir.Expression result;
|
||||
switch (rhs.kind) {
|
||||
case CompoundKind.POSTFIX:
|
||||
return accessor.buildPostfixIncrement(name, voidContext: isVoidContext);
|
||||
result =
|
||||
accessor.buildPostfixIncrement(name, voidContext: isVoidContext);
|
||||
break;
|
||||
|
||||
case CompoundKind.PREFIX:
|
||||
return accessor.buildPrefixIncrement(name, voidContext: isVoidContext);
|
||||
result =
|
||||
accessor.buildPrefixIncrement(name, voidContext: isVoidContext);
|
||||
break;
|
||||
|
||||
case CompoundKind.ASSIGNMENT:
|
||||
return accessor.buildCompoundAssignment(name, visitForValue(rhs.rhs),
|
||||
result = accessor.buildCompoundAssignment(name, visitForValue(rhs.rhs),
|
||||
voidContext: isVoidContext);
|
||||
break;
|
||||
}
|
||||
assert(accessor.builtBinary != null);
|
||||
kernel.nodeToAstOperator[accessor.builtBinary] = node;
|
||||
if (accessor.builtGetter != null) {
|
||||
kernel.nodeToAst[accessor.builtGetter] = node;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -1740,7 +1755,7 @@ class KernelVisitor extends Object
|
|||
SendSet node, LocalElement local, CompoundRhs rhs, _,
|
||||
{bool isSetterValid}) {
|
||||
ir.Expression compound =
|
||||
buildCompound(new VariableAccessor(getLocal(local)), rhs);
|
||||
buildCompound(new VariableAccessor(getLocal(local)), rhs, node);
|
||||
if (compound is ir.VariableSet) {
|
||||
associateNode(compound.value, node);
|
||||
} else {
|
||||
|
@ -2235,6 +2250,7 @@ class KernelVisitor extends Object
|
|||
AssignmentOperator operator,
|
||||
Node rhs,
|
||||
_) {
|
||||
// TODO(sra): Find binary operator.
|
||||
return buildSuperIndexAccessor(index, getter, setter)
|
||||
.buildCompoundAssignment(
|
||||
kernel.irName(operator.selectorName, currentElement),
|
||||
|
@ -2286,7 +2302,7 @@ class KernelVisitor extends Object
|
|||
if (setterKind == CompoundSetter.INVALID) {
|
||||
setter = null;
|
||||
}
|
||||
return buildCompound(buildSuperPropertyAccessor(getter, setter), rhs);
|
||||
return buildCompound(buildSuperPropertyAccessor(getter, setter), rhs, node);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -2301,13 +2317,14 @@ class KernelVisitor extends Object
|
|||
if (setterKind == CompoundSetter.INVALID) {
|
||||
setter = null;
|
||||
}
|
||||
return buildCompound(buildStaticAccessor(getter, setter), rhs);
|
||||
return buildCompound(buildStaticAccessor(getter, setter), rhs, node);
|
||||
}
|
||||
|
||||
@override
|
||||
ir.Expression handleTypeLiteralConstantCompounds(
|
||||
SendSet node, ConstantExpression constant, CompoundRhs rhs, _) {
|
||||
return buildCompound(new ReadOnlyAccessor(buildTypeLiteral(constant)), rhs);
|
||||
return buildCompound(
|
||||
new ReadOnlyAccessor(buildTypeLiteral(constant)), rhs, node);
|
||||
}
|
||||
|
||||
ir.TypeLiteral buildTypeVariable(TypeVariableElement element) {
|
||||
|
@ -2317,7 +2334,8 @@ class KernelVisitor extends Object
|
|||
@override
|
||||
ir.Expression handleTypeVariableTypeLiteralCompounds(
|
||||
SendSet node, TypeVariableElement element, CompoundRhs rhs, _) {
|
||||
return buildCompound(new ReadOnlyAccessor(buildTypeVariable(element)), rhs);
|
||||
return buildCompound(
|
||||
new ReadOnlyAccessor(buildTypeVariable(element)), rhs, node);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -86,6 +86,9 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder {
|
|||
LoopHandler<ir.Node> loopHandler;
|
||||
TypeBuilder typeBuilder;
|
||||
|
||||
final Map<ir.VariableDeclaration, HInstruction> letBindings =
|
||||
<ir.VariableDeclaration, HInstruction>{};
|
||||
|
||||
KernelSsaBuilder(
|
||||
this.targetElement,
|
||||
this.resolvedAst,
|
||||
|
@ -939,10 +942,31 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder {
|
|||
|
||||
@override
|
||||
void visitVariableGet(ir.VariableGet variableGet) {
|
||||
ir.VariableDeclaration variable = variableGet.variable;
|
||||
HInstruction letBinding = letBindings[variable];
|
||||
if (letBinding != null) {
|
||||
stack.add(letBinding);
|
||||
return;
|
||||
}
|
||||
|
||||
Local local = astAdapter.getLocal(variableGet.variable);
|
||||
stack.add(localsHandler.readLocal(local));
|
||||
}
|
||||
|
||||
@override
|
||||
void visitPropertySet(ir.PropertySet propertySet) {
|
||||
propertySet.receiver.accept(this);
|
||||
HInstruction receiver = pop();
|
||||
propertySet.value.accept(this);
|
||||
HInstruction value = pop();
|
||||
|
||||
_pushDynamicInvocation(propertySet, astAdapter.typeOfSet(propertySet),
|
||||
<HInstruction>[receiver, value]);
|
||||
|
||||
pop();
|
||||
stack.add(value);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitVariableSet(ir.VariableSet variableSet) {
|
||||
variableSet.value.accept(this);
|
||||
|
@ -984,6 +1008,16 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder {
|
|||
value, astAdapter.getDartType(variable.type)));
|
||||
}
|
||||
|
||||
@override
|
||||
void visitLet(ir.Let let) {
|
||||
ir.VariableDeclaration variable = let.variable;
|
||||
variable.initializer.accept(this);
|
||||
HInstruction initializedValue = pop();
|
||||
// TODO(sra): Apply inferred type information.
|
||||
letBindings[variable] = initializedValue;
|
||||
let.body.accept(this);
|
||||
}
|
||||
|
||||
// TODO(het): Also extract type arguments
|
||||
/// Extracts the list of instructions for the expressions in the arguments.
|
||||
List<HInstruction> _visitArguments(ir.Arguments arguments) {
|
||||
|
|
|
@ -96,7 +96,8 @@ class KernelAstAdapter {
|
|||
|
||||
ast.Node getNode(ir.Node node) {
|
||||
ast.Node result = _nodeToAst[node];
|
||||
assert(result != null);
|
||||
assert(invariant(CURRENT_ELEMENT_SPANNABLE, result != null,
|
||||
message: "No node found for $node"));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -144,6 +145,7 @@ class KernelAstAdapter {
|
|||
|
||||
Selector getSelector(ir.Expression node) {
|
||||
if (node is ir.PropertyGet) return getGetterSelector(node);
|
||||
if (node is ir.PropertySet) return getSetterSelector(node);
|
||||
if (node is ir.InvocationExpression) return getInvocationSelector(node);
|
||||
_compiler.reporter.internalError(getNode(node),
|
||||
"Can only get the selector for a property get or an invocation.");
|
||||
|
@ -174,7 +176,18 @@ class KernelAstAdapter {
|
|||
return new Selector.getter(name);
|
||||
}
|
||||
|
||||
Selector getSetterSelector(ir.PropertySet setter) {
|
||||
ir.Name irName = setter.name;
|
||||
Name name = new Name(
|
||||
irName.name, irName.isPrivate ? getElement(irName.library) : null);
|
||||
return new Selector.setter(name);
|
||||
}
|
||||
|
||||
TypeMask typeOfInvocation(ir.Expression send) {
|
||||
ast.Node operatorNode = kernel.nodeToAstOperator[send];
|
||||
if (operatorNode != null) {
|
||||
return _resultOf(_target).typeOfOperator(operatorNode);
|
||||
}
|
||||
return _resultOf(_target).typeOfSend(getNode(send));
|
||||
}
|
||||
|
||||
|
@ -182,6 +195,10 @@ class KernelAstAdapter {
|
|||
return _resultOf(_target).typeOfSend(getNode(getter));
|
||||
}
|
||||
|
||||
TypeMask typeOfSet(ir.PropertySet setter) {
|
||||
return _compiler.closedWorld.commonMasks.dynamicType;
|
||||
}
|
||||
|
||||
TypeMask typeOfSend(ir.Expression send) {
|
||||
assert(send is ir.InvocationExpression || send is ir.PropertyGet);
|
||||
return _resultOf(_target).typeOfSend(getNode(send));
|
||||
|
|
|
@ -9,6 +9,13 @@ library kernel.frontend.accessors;
|
|||
import '../ast.dart';
|
||||
|
||||
abstract class Accessor {
|
||||
// [builtBinary] and [builtGetter] capture the inner nodes. Used by
|
||||
// dart2js+rasta for determining how subexpressions map to legacy dart2js Ast
|
||||
// nodes. This will be removed once dart2js type analysis (aka inference) is
|
||||
// reimplemented on kernel.
|
||||
Expression builtBinary;
|
||||
Expression builtGetter;
|
||||
|
||||
Expression buildSimpleRead() {
|
||||
return _finish(_makeSimpleRead());
|
||||
}
|
||||
|
@ -37,7 +44,8 @@ abstract class Accessor {
|
|||
Expression buildCompoundAssignment(Name binaryOperator, Expression value,
|
||||
{bool voidContext: false, Procedure interfaceTarget}) {
|
||||
return _finish(_makeWrite(
|
||||
makeBinary(_makeRead(), binaryOperator, interfaceTarget, value),
|
||||
builtBinary =
|
||||
makeBinary(_makeRead(), binaryOperator, interfaceTarget, value),
|
||||
voidContext));
|
||||
}
|
||||
|
||||
|
@ -56,7 +64,7 @@ abstract class Accessor {
|
|||
var value = new VariableDeclaration.forValue(_makeRead());
|
||||
valueAccess() => new VariableGet(value);
|
||||
var dummy = new VariableDeclaration.forValue(_makeWrite(
|
||||
makeBinary(
|
||||
builtBinary = makeBinary(
|
||||
valueAccess(), binaryOperator, interfaceTarget, new IntLiteral(1)),
|
||||
true));
|
||||
return _finish(makeLet(value, makeLet(dummy, valueAccess())));
|
||||
|
@ -122,7 +130,7 @@ class PropertyAccessor extends Accessor {
|
|||
return new VariableGet(_receiverVariable);
|
||||
}
|
||||
|
||||
_makeRead() => new PropertyGet(receiverAccess(), name, getter);
|
||||
_makeRead() => builtGetter = new PropertyGet(receiverAccess(), name, getter);
|
||||
|
||||
_makeWrite(Expression value, bool voidContext) {
|
||||
return new PropertySet(receiverAccess(), name, value, setter);
|
||||
|
@ -139,7 +147,8 @@ class ThisPropertyAccessor extends Accessor {
|
|||
|
||||
ThisPropertyAccessor(this.name, this.getter, this.setter);
|
||||
|
||||
_makeRead() => new PropertyGet(new ThisExpression(), name, getter);
|
||||
_makeRead() =>
|
||||
builtGetter = new PropertyGet(new ThisExpression(), name, getter);
|
||||
|
||||
_makeWrite(Expression value, bool voidContext) {
|
||||
return new PropertySet(new ThisExpression(), name, value, setter);
|
||||
|
@ -158,7 +167,7 @@ class NullAwarePropertyAccessor extends Accessor {
|
|||
|
||||
receiverAccess() => new VariableGet(receiver);
|
||||
|
||||
_makeRead() => new PropertyGet(receiverAccess(), name, getter);
|
||||
_makeRead() => builtGetter = new PropertyGet(receiverAccess(), name, getter);
|
||||
|
||||
_makeWrite(Expression value, bool voidContext) {
|
||||
return new PropertySet(receiverAccess(), name, value, setter);
|
||||
|
|
Loading…
Reference in a new issue