Skip to content

Commit

Permalink
Add decorations to ir nodes in Painless (#63894)
Browse files Browse the repository at this point in the history
This change starts to switch all ir nodes to use decorations instead of specific member data. For this 
specific change, we add only an expression type decoration to begin with to keep the change smaller. 
Other members of the ir nodes will be converted to decorations in future changes.

The decoration system has two important advantages:
- The first is it's consistent with the user nodes as generated data is attached to them as a decoration, 
so we have a clear, consistent model for how to use both trees.
- This allows additionally generated data to be attached as necessary for optimization phases making 
the ir tree extendable which is one of our primary, long-term goals.
  • Loading branch information
jdconrad committed Oct 22, 2020
1 parent 3bc250c commit 31e9792
Show file tree
Hide file tree
Showing 7 changed files with 363 additions and 212 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,28 +20,9 @@
package org.elasticsearch.painless.ir;

import org.elasticsearch.painless.Location;
import org.elasticsearch.painless.lookup.PainlessLookupUtility;

public abstract class ExpressionNode extends IRNode {

/* ---- begin node data ---- */

private Class<?> expressionType;

public void setExpressionType(Class<?> expressionType) {
this.expressionType = expressionType;
}

public Class<?> getExpressionType() {
return expressionType;
}

public String getExpressionCanonicalTypeName() {
return PainlessLookupUtility.typeToCanonicalTypeName(expressionType);
}

/* ---- end node data ---- */

public ExpressionNode(Location location) {
super(location);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,82 @@
import org.elasticsearch.painless.Location;
import org.elasticsearch.painless.phase.IRTreeVisitor;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public abstract class IRNode {

/* ---- begin node data ---- */
/* ---- begin decorations ---- */

public interface IRDecoration {

}

private final Map<Class<? extends IRDecoration>, IRDecoration> decorations = new HashMap<>();

@SuppressWarnings("unchecked")
public <T extends IRDecoration> T attachDecoration(T decoration) {
return (T)decorations.put(decoration.getClass(), decoration);
}

public <T extends IRDecoration> T removeDecoration(Class<T> type) {
return type.cast(decorations.remove(type));
}

public <T extends IRDecoration> T getDecoration(Class<T> type) {
return type.cast(decorations.get(type));
}

public boolean hasDecoration(Class<? extends IRDecoration> type) {
return decorations.containsKey(type);
}

public <T extends IRDecoration> boolean copyDecorationFrom(IRNode copyFromIRNode, Class<T> type) {
T decoration = copyFromIRNode.getDecoration(type);


if (decoration != null) {
attachDecoration(decoration);

return true;
}

return false;
}

/* ---- end decorations, begin conditions ---- */

public interface IRCondition {

}

private final Set<Class<? extends IRCondition>> conditions = new HashSet<>();

public boolean attachCondition(Class<? extends IRCondition> type) {
return conditions.add(type);
}

public boolean removeCondition(Class<? extends IRCondition> type) {
return conditions.remove(type);
}

public boolean hasCondition(Class<? extends IRCondition> type) {
return conditions.contains(type);
}

public boolean copyConditionFrom(IRNode copyFromIRNode, Class<? extends IRCondition> type) {
if (copyFromIRNode.hasCondition(type)) {
attachCondition(type);

return true;
}

return false;
}

/* ---- end conditions, begin node data ---- */

private final Location location;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
import org.elasticsearch.painless.ir.UnaryMathNode;
import org.elasticsearch.painless.ir.WhileLoopNode;
import org.elasticsearch.painless.lookup.PainlessLookupUtility;
import org.elasticsearch.painless.symbol.IRDecorations.IRDExpressionType;

import java.util.function.Consumer;

Expand Down Expand Up @@ -180,7 +181,7 @@ public void visitUnaryMath(UnaryMathNode irUnaryMathNode, Consumer<ExpressionNod
if (irUnaryMathNode.getChildNode() instanceof ConstantNode) {
ConstantNode irConstantNode = (ConstantNode)irUnaryMathNode.getChildNode();
Operation operation = irUnaryMathNode.getOperation();
Class<?> type = irUnaryMathNode.getExpressionType();
Class<?> type = irUnaryMathNode.getDecoration(IRDExpressionType.class).getType();

if (operation == Operation.SUB) {
if (type == int.class) {
Expand Down Expand Up @@ -238,7 +239,7 @@ public void visitBinaryMath(BinaryMathNode irBinaryMathNode, Consumer<Expression
ConstantNode irLeftConstantNode = (ConstantNode)irBinaryMathNode.getLeftNode();
ConstantNode irRightConstantNode = (ConstantNode)irBinaryMathNode.getRightNode();
Operation operation = irBinaryMathNode.getOperation();
Class<?> type = irBinaryMathNode.getExpressionType();
Class<?> type = irBinaryMathNode.getDecoration(IRDExpressionType.class).getType();

if (operation == Operation.MUL) {
if (type == int.class) {
Expand Down Expand Up @@ -435,22 +436,22 @@ public void visitStringConcatenation(StringConcatenationNode irStringConcatenati
if (irLeftNode instanceof ConstantNode && irRightNode instanceof ConstantNode) {
ConstantNode irConstantNode = (ConstantNode)irLeftNode;
irConstantNode.setConstant("" + irConstantNode.getConstant() + ((ConstantNode)irRightNode).getConstant());
irConstantNode.setExpressionType(String.class);
irConstantNode.attachDecoration(new IRDExpressionType(String.class));
irStringConcatenationNode.getArgumentNodes().remove(i + 1);
} else if (irLeftNode instanceof NullNode && irRightNode instanceof ConstantNode) {
ConstantNode irConstantNode = (ConstantNode)irRightNode;
irConstantNode.setConstant("" + null + ((ConstantNode)irRightNode).getConstant());
irConstantNode.setExpressionType(String.class);
irConstantNode.attachDecoration(new IRDExpressionType(String.class));
irStringConcatenationNode.getArgumentNodes().remove(i);
} else if (irLeftNode instanceof ConstantNode && irRightNode instanceof NullNode) {
ConstantNode irConstantNode = (ConstantNode)irLeftNode;
irConstantNode.setConstant("" + ((ConstantNode)irLeftNode).getConstant() + null);
irConstantNode.setExpressionType(String.class);
irConstantNode.attachDecoration(new IRDExpressionType(String.class));
irStringConcatenationNode.getArgumentNodes().remove(i + 1);
} else if (irLeftNode instanceof NullNode && irRightNode instanceof NullNode) {
ConstantNode irConstantNode = new ConstantNode(irLeftNode.getLocation());
irConstantNode.setConstant("" + null + null);
irConstantNode.setExpressionType(String.class);
irConstantNode.attachDecoration(new IRDExpressionType(String.class));
irStringConcatenationNode.getArgumentNodes().set(i, irConstantNode);
irStringConcatenationNode.getArgumentNodes().remove(i + 1);
} else {
Expand All @@ -476,7 +477,7 @@ public void visitBoolean(BooleanNode irBooleanNode, Consumer<ExpressionNode> sco
ConstantNode irLeftConstantNode = (ConstantNode)irBooleanNode.getLeftNode();
ConstantNode irRightConstantNode = (ConstantNode)irBooleanNode.getRightNode();
Operation operation = irBooleanNode.getOperation();
Class<?> type = irBooleanNode.getExpressionType();
Class<?> type = irBooleanNode.getDecoration(IRDExpressionType.class).getType();

if (operation == Operation.AND) {
if (type == boolean.class) {
Expand Down Expand Up @@ -544,7 +545,7 @@ public void visitComparison(ComparisonNode irComparisonNode, Consumer<Expression
}
}

irLeftConstantNode.setExpressionType(boolean.class);
irLeftConstantNode.attachDecoration(new IRDExpressionType(boolean.class));
scope.accept(irLeftConstantNode);
} else if (operation == Operation.NE || operation == Operation.NER) {
if (type == boolean.class) {
Expand All @@ -571,7 +572,7 @@ public void visitComparison(ComparisonNode irComparisonNode, Consumer<Expression
}
}

irLeftConstantNode.setExpressionType(boolean.class);
irLeftConstantNode.attachDecoration(new IRDExpressionType(boolean.class));
scope.accept(irLeftConstantNode);
} else if (irLeftConstantNode != null && irRightConstantNode != null) {
if (operation == Operation.GT) {
Expand All @@ -591,7 +592,7 @@ public void visitComparison(ComparisonNode irComparisonNode, Consumer<Expression
"constants [" + irLeftConstantNode.getConstant() + "] and [" + irRightConstantNode.getConstant() + "]"));
}

irLeftConstantNode.setExpressionType(boolean.class);
irLeftConstantNode.attachDecoration(new IRDExpressionType(boolean.class));
scope.accept(irLeftConstantNode);
} else if (operation == Operation.GTE) {
if (type == int.class) {
Expand All @@ -610,7 +611,7 @@ public void visitComparison(ComparisonNode irComparisonNode, Consumer<Expression
"constants [" + irLeftConstantNode.getConstant() + "] and [" + irRightConstantNode.getConstant() + "]"));
}

irLeftConstantNode.setExpressionType(boolean.class);
irLeftConstantNode.attachDecoration(new IRDExpressionType(boolean.class));
scope.accept(irLeftConstantNode);
} else if (operation == Operation.LT) {
if (type == int.class) {
Expand All @@ -629,7 +630,7 @@ public void visitComparison(ComparisonNode irComparisonNode, Consumer<Expression
"constants [" + irLeftConstantNode.getConstant() + "] and [" + irRightConstantNode.getConstant() + "]"));
}

irLeftConstantNode.setExpressionType(boolean.class);
irLeftConstantNode.attachDecoration(new IRDExpressionType(boolean.class));
scope.accept(irLeftConstantNode);
} else if (operation == Operation.LTE) {
if (type == int.class) {
Expand All @@ -648,7 +649,7 @@ public void visitComparison(ComparisonNode irComparisonNode, Consumer<Expression
"constants [" + irLeftConstantNode.getConstant() + "] and [" + irRightConstantNode.getConstant() + "]"));
}

irLeftConstantNode.setExpressionType(boolean.class);
irLeftConstantNode.attachDecoration(new IRDExpressionType(boolean.class));
scope.accept(irLeftConstantNode);
}
}
Expand All @@ -659,11 +660,12 @@ public void visitComparison(ComparisonNode irComparisonNode, Consumer<Expression
public void visitCast(CastNode irCastNode, Consumer<ExpressionNode> scope) {
irCastNode.getChildNode().visit(this, irCastNode::setChildNode);

if (irCastNode.getChildNode() instanceof ConstantNode && PainlessLookupUtility.isConstantType(irCastNode.getExpressionType())) {
if (irCastNode.getChildNode() instanceof ConstantNode &&
PainlessLookupUtility.isConstantType(irCastNode.getDecoration(IRDExpressionType.class).getType())) {
ConstantNode irConstantNode = (ConstantNode)irCastNode.getChildNode();
irConstantNode.setConstant(
AnalyzerCaster.constCast(irCastNode.getLocation(), irConstantNode.getConstant(), irCastNode.getCast()));
irConstantNode.setExpressionType(irCastNode.getExpressionType());
irConstantNode.copyDecorationFrom(irCastNode, IRDExpressionType.class);
scope.accept(irConstantNode);
}
}
Expand Down

0 comments on commit 31e9792

Please sign in to comment.