use of com.sun.source.tree.BinaryTree in project error-prone by google.
the class UUnary method inline.
@Override
public JCExpression inline(Inliner inliner) throws CouldNotResolveImportException {
JCExpression expr = getExpression().inline(inliner);
final TreeMaker maker = inliner.maker();
if (getKind() == Kind.LOGICAL_COMPLEMENT) {
return new TreeCopier<Void>(maker) {
@SuppressWarnings("unchecked")
// essentially depends on T being a superclass of JCExpression
@Override
public <T extends JCTree> T copy(T t, Void v) {
if (t instanceof BinaryTree || t instanceof UnaryTree || t instanceof ConditionalExpressionTree) {
return super.copy(t, v);
} else {
return (T) defaultNegation(t);
}
}
public JCExpression defaultNegation(Tree expr) {
return maker.Unary(JCTree.Tag.NOT, (JCExpression) expr);
}
@Override
public JCExpression visitBinary(BinaryTree tree, Void v) {
if (UBinary.DEMORGAN.containsKey(tree.getKind())) {
JCExpression negLeft = copy((JCExpression) tree.getLeftOperand());
JCExpression negRight = copy((JCExpression) tree.getRightOperand());
return maker.Binary(UBinary.OP_CODES.get(UBinary.DEMORGAN.get(tree.getKind())), negLeft, negRight);
} else if (UBinary.NEGATION.containsKey(tree.getKind())) {
JCExpression left = (JCExpression) tree.getLeftOperand();
JCExpression right = (JCExpression) tree.getRightOperand();
return maker.Binary(UBinary.OP_CODES.get(UBinary.NEGATION.get(tree.getKind())), left, right);
} else {
return defaultNegation(tree);
}
}
@Override
public JCExpression visitUnary(UnaryTree tree, Void v) {
if (tree.getKind() == Kind.LOGICAL_COMPLEMENT) {
return (JCExpression) tree.getExpression();
} else {
return defaultNegation(tree);
}
}
@Override
public JCConditional visitConditionalExpression(ConditionalExpressionTree tree, Void v) {
return maker.Conditional((JCExpression) tree.getCondition(), copy((JCExpression) tree.getTrueExpression()), copy((JCExpression) tree.getFalseExpression()));
}
}.copy(expr);
} else {
return inliner.maker().Unary(UNARY_OP_CODES.get(getKind()), getExpression().inline(inliner));
}
}
use of com.sun.source.tree.BinaryTree in project checker-framework by typetools.
the class SignednessVisitor method isCastedShift.
/**
* Determines if a right shift operation, {@code >>} or {@code >>>}, is type casted such that
* the cast renders the shift signedness ({@code >>} vs {@code >>>}) irrelevent by discarding
* the bits duplicated into the shift result. For example, the following pair of right shifts on
* {@code short s} both produce the same results under any input, because of type casting:
*
* <p>{@code (byte)(s >> 8) == (byte)(b >>> 8);}
*
* @param shiftExpr a right shift expression: {@code expr1 >> expr2} or {@code expr1 >>> expr2}
* @return true iff the right shift is type casted such that a signed or unsigned right shift
* has the same effect
*/
private boolean isCastedShift(BinaryTree shiftExpr) {
// enclosing is the operation or statement that immediately contains shiftExpr
Tree enclosing;
{
TreePath parentPath = visitorState.getPath().getParentPath();
enclosing = parentPath.getLeaf();
// Strip away all parentheses from the shift operation
while (enclosing.getKind() == Kind.PARENTHESIZED) {
parentPath = parentPath.getParentPath();
enclosing = parentPath.getLeaf();
}
}
PrimitiveTypeTree castPrimitiveType = primitiveTypeCast(enclosing);
if (castPrimitiveType == null) {
return false;
}
TypeKind castTypeKind = castPrimitiveType.getPrimitiveTypeKind();
// Determine the type of the shift result
TypeKind shiftTypeKind = atypeFactory.getAnnotatedType(shiftExpr).getUnderlyingType().getKind();
// Determine shift literal
ExpressionTree shiftAmountExpr = shiftExpr.getRightOperand();
if (!isLiteral(shiftAmountExpr)) {
return false;
}
LiteralTree shiftLit = (LiteralTree) shiftAmountExpr;
return castIgnoresMSB(shiftTypeKind, castTypeKind, shiftLit);
}
use of com.sun.source.tree.BinaryTree in project groovy-cps by cloudbees.
the class Translator method translateMethod.
/**
* @param e
* Method in {@code fqcn} to translate.
*/
private void translateMethod(final CompilationUnitTree cut, ExecutableElement e, JDefinedClass $output, String fqcn, String overloadResolved) {
String methodName = n(e);
boolean isPublic = e.getModifiers().contains(Modifier.PUBLIC);
JMethod delegating = $output.method(isPublic ? JMod.PUBLIC | JMod.STATIC : JMod.STATIC, (JType) null, methodName);
JMethod m = $output.method(JMod.PRIVATE | JMod.STATIC, (JType) null, overloadResolved);
Map<String, JTypeVar> typeVars = new HashMap<>();
e.getTypeParameters().forEach(p -> {
String name = n(p);
JTypeVar typeVar = delegating.generify(name);
JTypeVar typeVar2 = m.generify(name);
p.getBounds().forEach(b -> {
JClass binding = (JClass) t(b, typeVars);
typeVar.bound(binding);
typeVar2.bound(binding);
});
typeVars.put(name, typeVar);
});
JType type = t(e.getReturnType(), typeVars);
delegating.type(type);
m.type(type);
List<JVar> delegatingParams = new ArrayList<>();
List<JVar> params = new ArrayList<>();
e.getParameters().forEach(p -> {
JType paramType = t(p.asType(), typeVars);
delegatingParams.add(e.isVarArgs() && p == e.getParameters().get(e.getParameters().size() - 1) ? delegating.varParam(paramType.elementType(), n(p)) : delegating.param(paramType, n(p)));
params.add(m.param(paramType, n(p)));
});
e.getThrownTypes().forEach(ex -> {
delegating._throws((JClass) t(ex));
m._throws((JClass) t(ex));
});
boolean returnsVoid = e.getReturnType().getKind() == TypeKind.VOID;
if (isPublic) {
// preamble
/*
If the call to this method happen outside CPS code, execute normally via DefaultGroovyMethods
*/
delegating.body()._if(JOp.cand(JOp.not($Caller.staticInvoke("isAsynchronous").tap(inv -> {
inv.arg(delegatingParams.get(0));
inv.arg(methodName);
for (int i = 1; i < delegatingParams.size(); i++) inv.arg(delegatingParams.get(i));
})), JOp.not($Caller.staticInvoke("isAsynchronous").arg($output.dotclass()).arg(methodName).args(params))))._then().tap(blk -> {
JClass $WhateverGroovyMethods = codeModel.ref(fqcn);
JInvocation forward = $WhateverGroovyMethods.staticInvoke(methodName).args(delegatingParams);
if (returnsVoid) {
blk.add(forward);
blk._return();
} else {
blk._return(forward);
}
});
}
JInvocation delegateCall = $output.staticInvoke(overloadResolved);
if (returnsVoid) {
delegating.body().add(delegateCall);
} else {
delegating.body()._return(delegateCall);
}
delegatingParams.forEach(p -> delegateCall.arg(p));
JVar $b = m.body().decl($Builder, "b", JExpr._new($Builder).arg(JExpr.invoke("loc").arg(methodName)).invoke("contextualize").arg(codeModel.ref("com.cloudbees.groovy.cps.sandbox.Trusted").staticRef("INSTANCE")));
JInvocation f = JExpr._new($CpsFunction);
// parameter names
f.arg(codeModel.ref(Arrays.class).staticInvoke("asList").tap(inv -> {
e.getParameters().forEach(p -> inv.arg(n(p)));
}));
// translate the method body into an expression that invokes Builder
f.arg(trees.getTree(e).getBody().accept(new SimpleTreeVisitor<JExpression, Void>() {
private JExpression visit(Tree t) {
if (t == null)
return JExpr._null();
return visit(t, null);
}
/**
* Maps a symbol to its source location.
*/
private JExpression loc(Tree t) {
long pos = trees.getSourcePositions().getStartPosition(cut, t);
return JExpr.lit((int) cut.getLineMap().getLineNumber(pos));
}
@Override
public JExpression visitWhileLoop(WhileLoopTree wt, Void __) {
return $b.invoke("while_").arg(// TODO: label
JExpr._null()).arg(visit(wt.getCondition())).arg(visit(wt.getStatement()));
}
@Override
public JExpression visitMethodInvocation(MethodInvocationTree mt, Void __) {
ExpressionTree ms = mt.getMethodSelect();
JInvocation inv;
if (ms instanceof MemberSelectTree) {
MemberSelectTree mst = (MemberSelectTree) ms;
// of the other known translated classes.
if (mst.getExpression() instanceof JCIdent && !((JCIdent) mst.getExpression()).sym.toString().equals(fqcn) && otherTranslated.containsKey(((JCIdent) mst.getExpression()).sym.toString())) {
inv = $b.invoke("functionCall").arg(loc(mt)).arg($b.invoke("constant").arg(otherTranslated.get(((JCIdent) mst.getExpression()).sym.toString()).dotclass())).arg(n(mst.getIdentifier()));
} else {
inv = $b.invoke("functionCall").arg(loc(mt)).arg(visit(mst.getExpression())).arg(n(mst.getIdentifier()));
}
} else if (ms instanceof JCIdent) {
// invocation without object selection, like foo(bar,zot)
JCIdent it = (JCIdent) ms;
if (!it.sym.owner.toString().equals(fqcn)) {
if (otherTranslated.containsKey(it.sym.owner.toString())) {
// static import from transformed class
inv = $b.invoke("functionCall").arg(loc(mt)).arg($b.invoke("constant").arg(otherTranslated.get(it.sym.owner.toString()).dotclass())).arg(n(it));
} else {
// static import from non-transformed class
inv = $b.invoke("functionCall").arg(loc(mt)).arg($b.invoke("constant").arg(t(it.sym.owner.type).dotclass())).arg(n(it));
}
} else {
// invocation on this class
String overloadResolved = mangledName((Symbol.MethodSymbol) it.sym);
Optional<? extends Element> callSite = elements.getTypeElement(fqcn).getEnclosedElements().stream().filter(e -> e.getKind() == ElementKind.METHOD && mangledName((ExecutableElement) e).equals(overloadResolved)).findAny();
if (callSite.isPresent()) {
ExecutableElement e = (ExecutableElement) callSite.get();
if (e.getModifiers().contains(Modifier.PUBLIC) && !e.isVarArgs() && !e.getParameters().stream().anyMatch(p -> types.isAssignable(p.asType(), closureType))) {
// Delegate to the standard version.
inv = $b.invoke("staticCall").arg(loc(mt)).arg(t(it.sym.owner.type).dotclass()).arg(n(e));
} else if (overloadsResolved.containsKey(overloadResolved)) {
// Private, so delegate to our mangled version.
// TODO add a String parameter to each internal helper method for the expected methodName to pass to CpsCallableInvocation.<init>
// (It could be improved to take a parameter for the name under which we expect methodCall to be invoking it.
// Usually just `each`, but might be `$each__java_util_Iterable__groovy_lang_Closure` for the case that one DGM method is delegating to another.
// See comment in ContinuationGroup, where we are unable to enforce continuation name mismatches in this case.)
inv = $b.invoke("staticCall").arg(loc(mt)).arg($output.dotclass()).arg(overloadResolved);
} else {
throw new IllegalStateException("Not yet translating a " + e.getModifiers() + " method; translatable.txt might need to include: " + fqcn + "." + e);
}
} else {
throw new IllegalStateException("Could not find self-call site " + overloadResolved + " for " + mt);
}
}
} else {
// TODO: figure out what can come here
throw new UnsupportedOperationException(ms.toString());
}
mt.getArguments().forEach(a -> inv.arg(visit(a)));
return inv;
}
@Override
public JExpression visitVariable(VariableTree vt, Void __) {
return $b.invoke("declareVariable").arg(loc(vt)).arg(cpsTypeTranslation(erasure(vt))).arg(n(vt)).arg(visit(vt.getInitializer()));
}
@Override
public JExpression visitIdentifier(IdentifierTree it, Void __) {
JCIdent idt = (JCIdent) it;
return idt.sym.accept(new DefaultSymbolVisitor<JExpression, Void>() {
@Override
public JExpression visitClassSymbol(ClassSymbol cs, Void __) {
return $b.invoke("constant").arg(t(cs.asType()).dotclass());
}
@Override
public JExpression visitVarSymbol(VarSymbol s, Void __) {
return $b.invoke("localVariable").arg(n(s.name));
}
@Override
public JExpression visitSymbol(Symbol s, Void __) {
throw new UnsupportedOperationException(s.toString());
}
}, __);
}
@Override
public JExpression visitBlock(BlockTree bt, Void __) {
JInvocation inv = $b.invoke("block");
bt.getStatements().forEach(s -> inv.arg(visit(s)));
return inv;
}
@Override
public JExpression visitReturn(ReturnTree rt, Void __) {
return $b.invoke("return_").arg(visit(rt.getExpression()));
}
/**
* When used outside {@link MethodInvocationTree}, this is property access.
*/
@Override
public JExpression visitMemberSelect(MemberSelectTree mt, Void __) {
return $b.invoke("property").arg(loc(mt)).arg(visit(mt.getExpression())).arg(n(mt.getIdentifier()));
}
@Override
public JExpression visitTypeCast(TypeCastTree tt, Void __) {
return $b.invoke("cast").arg(loc(tt)).arg(visit(tt.getExpression())).arg(erasure(tt.getType()).dotclass()).arg(JExpr.lit(false));
}
@Override
public JExpression visitIf(IfTree it, Void __) {
JInvocation inv = $b.invoke("if_").arg(visit(it.getCondition())).arg(visit(it.getThenStatement()));
if (it.getElseStatement() != null)
inv.arg(visit(it.getElseStatement()));
return inv;
}
@Override
public JExpression visitNewClass(NewClassTree nt, Void __) {
// TODO: outer class
if (nt.getEnclosingExpression() != null)
throw new UnsupportedOperationException();
return $b.invoke("new_").tap(inv -> {
inv.arg(loc(nt));
inv.arg(cpsTypeTranslation(t(((JCTree) nt).type)));
nt.getArguments().forEach(et -> inv.arg(visit(et)));
});
}
@Override
public JExpression visitExpressionStatement(ExpressionStatementTree et, Void __) {
return visit(et.getExpression());
}
@Override
public JExpression visitLiteral(LiteralTree lt, Void __) {
return $b.invoke("constant").arg(JExpr.literal(lt.getValue()));
}
@Override
public JExpression visitParenthesized(ParenthesizedTree pt, Void __) {
return visit(pt.getExpression());
}
@Override
public JExpression visitBinary(BinaryTree bt, Void __) {
return $b.invoke(opName(bt.getKind())).arg(loc(bt)).arg(visit(bt.getLeftOperand())).arg(visit(bt.getRightOperand()));
}
@Override
public JExpression visitUnary(UnaryTree ut, Void __) {
return $b.invoke(opName(ut.getKind())).arg(loc(ut)).arg(visit(ut.getExpression()));
}
@Override
public JExpression visitCompoundAssignment(CompoundAssignmentTree ct, Void __) {
return $b.invoke(opName(ct.getKind())).arg(loc(ct)).arg(visit(ct.getVariable())).arg(visit(ct.getExpression()));
}
private String opName(Kind kind) {
switch(kind) {
case EQUAL_TO:
return "compareEqual";
case NOT_EQUAL_TO:
return "compareNotEqual";
case LESS_THAN_EQUAL:
return "lessThanEqual";
case LESS_THAN:
return "lessThan";
case GREATER_THAN_EQUAL:
return "greaterThanEqual";
case GREATER_THAN:
return "greaterThan";
case PREFIX_INCREMENT:
return "prefixInc";
case POSTFIX_INCREMENT:
return "postfixInc";
case POSTFIX_DECREMENT:
return "postfixDec";
case LOGICAL_COMPLEMENT:
return "not";
case CONDITIONAL_OR:
return "logicalOr";
case CONDITIONAL_AND:
return "logicalAnd";
case PLUS:
return "plus";
case PLUS_ASSIGNMENT:
return "plusEqual";
case MINUS:
return "minus";
case MINUS_ASSIGNMENT:
return "minusEqual";
}
throw new UnsupportedOperationException(kind.toString());
}
@Override
public JExpression visitAssignment(AssignmentTree at, Void __) {
return $b.invoke("assign").arg(loc(at)).arg(visit(at.getVariable())).arg(visit(at.getExpression()));
}
/**
* This is needed to handle cases like {@code Object[].class}.
*/
@Override
public JExpression visitArrayType(ArrayTypeTree at, Void __) {
if (at.getType() instanceof IdentifierTree) {
return visitIdentifier((IdentifierTree) at.getType(), __);
} else {
return defaultAction(at, __);
}
}
@Override
public JExpression visitNewArray(NewArrayTree nt, Void __) {
if (nt.getInitializers() != null) {
return $b.invoke("newArrayFromInitializers").tap(inv -> {
nt.getInitializers().forEach(d -> inv.arg(visit(d)));
});
} else {
return $b.invoke("newArray").tap(inv -> {
inv.arg(loc(nt));
inv.arg(t(nt.getType()).dotclass());
nt.getDimensions().forEach(d -> inv.arg(visit(d)));
});
}
}
@Override
public JExpression visitForLoop(ForLoopTree ft, Void __) {
return $b.invoke("forLoop").arg(JExpr._null()).arg($b.invoke("sequence").tap(inv -> ft.getInitializer().forEach(i -> inv.arg(visit(i))))).arg(visit(ft.getCondition())).arg($b.invoke("sequence").tap(inv -> ft.getUpdate().forEach(i -> inv.arg(visit(i))))).arg(visit(ft.getStatement()));
}
@Override
public JExpression visitEnhancedForLoop(EnhancedForLoopTree et, Void __) {
return $b.invoke("forInLoop").arg(loc(et)).arg(JExpr._null()).arg(erasure(et.getVariable()).dotclass()).arg(n(et.getVariable())).arg(visit(et.getExpression())).arg(visit(et.getStatement()));
}
@Override
public JExpression visitArrayAccess(ArrayAccessTree at, Void __) {
return $b.invoke("array").arg(loc(at)).arg(visit(at.getExpression())).arg(visit(at.getIndex()));
}
@Override
public JExpression visitBreak(BreakTree node, Void __) {
if (node.getLabel() != null)
throw new UnsupportedOperationException();
return $b.invoke("break_").arg(JExpr._null());
}
@Override
public JExpression visitContinue(ContinueTree node, Void aVoid) {
if (node.getLabel() != null)
throw new UnsupportedOperationException();
return $b.invoke("continue_").arg(JExpr._null());
}
@Override
public JExpression visitInstanceOf(InstanceOfTree it, Void __) {
return $b.invoke("instanceOf").arg(loc(it)).arg(visit(it.getExpression())).arg($b.invoke("constant").arg(t(it.getType()).dotclass()));
}
@Override
public JExpression visitThrow(ThrowTree tt, Void __) {
return $b.invoke("throw_").arg(loc(tt)).arg(visit(tt.getExpression()));
}
@Override
public JExpression visitDoWhileLoop(DoWhileLoopTree dt, Void __) {
return $b.invoke("doWhile").arg(JExpr._null()).arg(visit(dt.getStatement())).arg(visit(dt.getCondition()));
}
@Override
public JExpression visitConditionalExpression(ConditionalExpressionTree ct, Void __) {
return $b.invoke("ternaryOp").arg(visit(ct.getCondition())).arg(visit(ct.getTrueExpression())).arg(visit(ct.getFalseExpression()));
}
@Override
public JExpression visitTry(TryTree tt, Void __) {
return $b.invoke("tryCatch").arg(visit(tt.getBlock())).arg(visit(tt.getFinallyBlock())).tap(inv -> tt.getCatches().forEach(ct -> JExpr._new($CatchExpression).arg(t(ct.getParameter()).dotclass()).arg(n(ct.getParameter())).arg(visit(ct.getBlock()))));
}
@Override
protected JExpression defaultAction(Tree node, Void aVoid) {
throw new UnsupportedOperationException(node.toString());
}
}, null));
JVar $f = m.body().decl($CpsFunction, "f", f);
m.body()._throw(JExpr._new($CpsCallableInvocation).arg(JExpr.lit(methodName)).arg($f).arg(JExpr._null()).args(params));
}
use of com.sun.source.tree.BinaryTree in project j2objc by google.
the class TreeConverter method convertBinary.
private TreeNode convertBinary(BinaryTree node, TreePath parent) {
TreePath path = getTreePath(parent, node);
InfixExpression newNode = new InfixExpression();
newNode.setTypeMirror(getTypeMirror(path)).setOperator(InfixExpression.Operator.from(node.getKind()));
// Flatten this tree to avoid stack overflow with very deep trees. This
// code traverses the subtree non-recursively and merges all children
// that have the same operator into this node.
List<StackState> stack = Lists.newArrayList();
stack.add(new StackState(node));
while (!stack.isEmpty()) {
StackState currentState = stack.get(stack.size() - 1);
ExpressionTree child = currentState.nextChild();
if (child == null) {
stack.remove(stack.size() - 1);
continue;
}
if (child instanceof BinaryTree) {
BinaryTree infixChild = (BinaryTree) child;
if (infixChild.getKind() == node.getKind()) {
stack.add(new StackState(infixChild));
continue;
}
}
newNode.addOperand((Expression) convert(child, path));
}
return newNode;
}
use of com.sun.source.tree.BinaryTree in project checker-framework by typetools.
the class CFGTranslationPhaseOne method visitCompoundAssignment.
@Override
public Node visitCompoundAssignment(CompoundAssignmentTree tree, Void p) {
// According the JLS 15.26.2, E1 op= E2 is equivalent to
// E1 = (T) ((E1) op (E2)), where T is the type of E1,
// except that E1 is evaluated only once.
//
Tree.Kind kind = tree.getKind();
switch(kind) {
case DIVIDE_ASSIGNMENT:
case MULTIPLY_ASSIGNMENT:
case REMAINDER_ASSIGNMENT:
{
// see JLS 15.17 and 15.26.2
Node targetLHS = scan(tree.getVariable(), p);
Node value = scan(tree.getExpression(), p);
TypeMirror exprType = TreeUtils.typeOf(tree);
TypeMirror leftType = TreeUtils.typeOf(tree.getVariable());
TypeMirror rightType = TreeUtils.typeOf(tree.getExpression());
TypeMirror promotedType = binaryPromotedType(leftType, rightType);
Node targetRHS = binaryNumericPromotion(targetLHS, promotedType);
value = binaryNumericPromotion(value, promotedType);
BinaryTree operTree = treeBuilder.buildBinary(promotedType, withoutAssignment(kind), tree.getVariable(), tree.getExpression());
handleArtificialTree(operTree);
Node operNode;
if (kind == Tree.Kind.MULTIPLY_ASSIGNMENT) {
operNode = new NumericalMultiplicationNode(operTree, targetRHS, value);
} else if (kind == Tree.Kind.DIVIDE_ASSIGNMENT) {
if (TypesUtils.isIntegralPrimitive(exprType)) {
operNode = new IntegerDivisionNode(operTree, targetRHS, value);
extendWithNodeWithException(operNode, arithmeticExceptionType);
} else {
operNode = new FloatingDivisionNode(operTree, targetRHS, value);
}
} else {
assert kind == Tree.Kind.REMAINDER_ASSIGNMENT;
if (TypesUtils.isIntegralPrimitive(exprType)) {
operNode = new IntegerRemainderNode(operTree, targetRHS, value);
extendWithNodeWithException(operNode, arithmeticExceptionType);
} else {
operNode = new FloatingRemainderNode(operTree, targetRHS, value);
}
}
extendWithNode(operNode);
TypeCastTree castTree = treeBuilder.buildTypeCast(leftType, operTree);
handleArtificialTree(castTree);
TypeCastNode castNode = new TypeCastNode(castTree, operNode, leftType, types);
castNode.setInSource(false);
extendWithNode(castNode);
AssignmentNode assignNode = new AssignmentNode(tree, targetLHS, castNode);
extendWithNode(assignNode);
return assignNode;
}
case MINUS_ASSIGNMENT:
case PLUS_ASSIGNMENT:
{
// see JLS 15.18 and 15.26.2
Node targetLHS = scan(tree.getVariable(), p);
Node value = scan(tree.getExpression(), p);
TypeMirror leftType = TreeUtils.typeOf(tree.getVariable());
TypeMirror rightType = TreeUtils.typeOf(tree.getExpression());
if (TypesUtils.isString(leftType) || TypesUtils.isString(rightType)) {
assert (kind == Tree.Kind.PLUS_ASSIGNMENT);
Node targetRHS = stringConversion(targetLHS);
value = stringConversion(value);
Node r = new StringConcatenateAssignmentNode(tree, targetRHS, value);
extendWithNode(r);
return r;
} else {
TypeMirror promotedType = binaryPromotedType(leftType, rightType);
Node targetRHS = binaryNumericPromotion(targetLHS, promotedType);
value = binaryNumericPromotion(value, promotedType);
BinaryTree operTree = treeBuilder.buildBinary(promotedType, withoutAssignment(kind), tree.getVariable(), tree.getExpression());
handleArtificialTree(operTree);
Node operNode;
if (kind == Tree.Kind.PLUS_ASSIGNMENT) {
operNode = new NumericalAdditionNode(operTree, targetRHS, value);
} else {
assert kind == Tree.Kind.MINUS_ASSIGNMENT;
operNode = new NumericalSubtractionNode(operTree, targetRHS, value);
}
extendWithNode(operNode);
TypeCastTree castTree = treeBuilder.buildTypeCast(leftType, operTree);
handleArtificialTree(castTree);
TypeCastNode castNode = new TypeCastNode(castTree, operNode, leftType, types);
castNode.setInSource(false);
extendWithNode(castNode);
// Map the compound assignment tree to an assignment node, which
// will have the correct type.
AssignmentNode assignNode = new AssignmentNode(tree, targetLHS, castNode);
extendWithNode(assignNode);
return assignNode;
}
}
case LEFT_SHIFT_ASSIGNMENT:
case RIGHT_SHIFT_ASSIGNMENT:
case UNSIGNED_RIGHT_SHIFT_ASSIGNMENT:
{
// see JLS 15.19 and 15.26.2
Node targetLHS = scan(tree.getVariable(), p);
Node value = scan(tree.getExpression(), p);
TypeMirror leftType = TreeUtils.typeOf(tree.getVariable());
Node targetRHS = unaryNumericPromotion(targetLHS);
value = unaryNumericPromotion(value);
BinaryTree operTree = treeBuilder.buildBinary(leftType, withoutAssignment(kind), tree.getVariable(), tree.getExpression());
handleArtificialTree(operTree);
Node operNode;
if (kind == Tree.Kind.LEFT_SHIFT_ASSIGNMENT) {
operNode = new LeftShiftNode(operTree, targetRHS, value);
} else if (kind == Tree.Kind.RIGHT_SHIFT_ASSIGNMENT) {
operNode = new SignedRightShiftNode(operTree, targetRHS, value);
} else {
assert kind == Tree.Kind.UNSIGNED_RIGHT_SHIFT_ASSIGNMENT;
operNode = new UnsignedRightShiftNode(operTree, targetRHS, value);
}
extendWithNode(operNode);
TypeCastTree castTree = treeBuilder.buildTypeCast(leftType, operTree);
handleArtificialTree(castTree);
TypeCastNode castNode = new TypeCastNode(castTree, operNode, leftType, types);
castNode.setInSource(false);
extendWithNode(castNode);
AssignmentNode assignNode = new AssignmentNode(tree, targetLHS, castNode);
extendWithNode(assignNode);
return assignNode;
}
case AND_ASSIGNMENT:
case OR_ASSIGNMENT:
case XOR_ASSIGNMENT:
// see JLS 15.22
Node targetLHS = scan(tree.getVariable(), p);
Node value = scan(tree.getExpression(), p);
TypeMirror leftType = TreeUtils.typeOf(tree.getVariable());
TypeMirror rightType = TreeUtils.typeOf(tree.getExpression());
Node targetRHS = null;
if (isNumericOrBoxed(leftType) && isNumericOrBoxed(rightType)) {
TypeMirror promotedType = binaryPromotedType(leftType, rightType);
targetRHS = binaryNumericPromotion(targetLHS, promotedType);
value = binaryNumericPromotion(value, promotedType);
} else if (TypesUtils.isBooleanType(leftType) && TypesUtils.isBooleanType(rightType)) {
targetRHS = unbox(targetLHS);
value = unbox(value);
} else {
throw new BugInCF("Both arguments to logical operation must be numeric or boolean");
}
BinaryTree operTree = treeBuilder.buildBinary(leftType, withoutAssignment(kind), tree.getVariable(), tree.getExpression());
handleArtificialTree(operTree);
Node operNode;
if (kind == Tree.Kind.AND_ASSIGNMENT) {
operNode = new BitwiseAndNode(operTree, targetRHS, value);
} else if (kind == Tree.Kind.OR_ASSIGNMENT) {
operNode = new BitwiseOrNode(operTree, targetRHS, value);
} else {
assert kind == Tree.Kind.XOR_ASSIGNMENT;
operNode = new BitwiseXorNode(operTree, targetRHS, value);
}
extendWithNode(operNode);
TypeCastTree castTree = treeBuilder.buildTypeCast(leftType, operTree);
handleArtificialTree(castTree);
TypeCastNode castNode = new TypeCastNode(castTree, operNode, leftType, types);
castNode.setInSource(false);
extendWithNode(castNode);
AssignmentNode assignNode = new AssignmentNode(tree, targetLHS, castNode);
extendWithNode(assignNode);
return assignNode;
default:
throw new BugInCF("unexpected compound assignment type");
}
}
Aggregations