use of com.google.devtools.j2objc.ast.Assignment in project j2objc by google.
the class Autoboxer method endVisit.
@Override
public void endVisit(Assignment node) {
TypeMirror lhType = node.getLeftHandSide().getTypeMirror();
boolean lhPrimitive = lhType.getKind().isPrimitive();
Expression rhs = node.getRightHandSide();
TypeMirror rhType = rhs.getTypeMirror();
boolean rhPrimitive = rhType.getKind().isPrimitive();
Assignment.Operator op = node.getOperator();
if (op != Assignment.Operator.ASSIGN && !lhPrimitive) {
rewriteBoxedAssignment(node);
} else if (lhPrimitive && !rhPrimitive) {
unbox(rhs);
} else if (!lhPrimitive && rhPrimitive) {
box(rhs, lhType);
}
}
use of com.google.devtools.j2objc.ast.Assignment in project j2objc by google.
the class Rewriter method visit.
@Override
public boolean visit(TryStatement node) {
// This visit rewrites try-with-resources constructs into regular try statements according to
// JLS 14.20.3. The rewriting is done in a visit instead of endVisit because the mutations may
// result in more try-with-resources constructs that need to be rewritten recursively.
List<TreeNode> resources = node.getResources();
if (resources.isEmpty()) {
return true;
}
if (!node.getCatchClauses().isEmpty() || node.getFinally() != null) {
// Extended try-with-resources. (JLS 14.20.3.2)
// The new innerTry statement will be a "Basic try-with-resources" and will be rewritten by
// the code below when it is visited.
TryStatement innerTry = new TryStatement().setBody(TreeUtil.remove(node.getBody()));
;
TreeUtil.moveList(resources, innerTry.getResources());
node.setBody(new Block().addStatement(innerTry));
return true;
}
// Basic try-with-resources. (JLS 14.20.3.1)
DeclaredType throwableType = (DeclaredType) typeUtil.getJavaThrowable().asType();
VariableElement primaryException = GeneratedVariableElement.newLocalVar("__primaryException" + resources.size(), throwableType, null);
TreeNode resource = resources.remove(0);
VariableElement resourceVar = null;
VariableDeclarationFragment resourceFrag = null;
if (resource.getKind() == Kind.VARIABLE_DECLARATION_EXPRESSION) {
List<VariableDeclarationFragment> resourceFrags = ((VariableDeclarationExpression) resource).getFragments();
assert resourceFrags.size() == 1;
resourceFrag = resourceFrags.get(0);
resourceVar = resourceFrag.getVariableElement();
} else {
resourceVar = TreeUtil.getVariableElement((Expression) resource);
}
assert resourceVar != null;
DeclaredType closeableType = typeUtil.findSupertype(resourceVar.asType(), "java.lang.AutoCloseable");
ExecutablePair closeMethod = typeUtil.findMethod(closeableType, "close");
ExecutablePair addSuppressedMethod = typeUtil.findMethod(throwableType, "addSuppressed", "java.lang.Throwable");
Block block = new Block();
if (resourceFrag != null) {
block.addStatement(new VariableDeclarationStatement(resourceVar, TreeUtil.remove(resourceFrag.getInitializer())));
}
block.addStatement(new VariableDeclarationStatement(primaryException, new NullLiteral(typeUtil.getNull())));
// If the current try node is the only statement in its parent block then replace the parent
// block instead of the try node to avoid extra nesting of braces.
TreeNode parent = node.getParent();
if (parent instanceof Block && ((Block) parent).getStatements().size() == 1) {
parent.replaceWith(block);
} else {
node.replaceWith(block);
}
block.addStatement(TreeUtil.remove(node));
VariableElement caughtException = GeneratedVariableElement.newLocalVar("e", throwableType, null);
Block catchBlock = new Block().addStatement(new ExpressionStatement(new Assignment(new SimpleName(primaryException), new SimpleName(caughtException)))).addStatement(new ThrowStatement(new SimpleName(caughtException)));
node.addCatchClause(new CatchClause().setException(new SingleVariableDeclaration(caughtException)).setBody(catchBlock));
Statement closeResource = new ExpressionStatement(new MethodInvocation(closeMethod, typeUtil.getVoid(), new SimpleName(resourceVar)));
VariableElement suppressedException = GeneratedVariableElement.newLocalVar("e", throwableType, null);
node.setFinally(new Block().addStatement(new IfStatement().setExpression(new InfixExpression(typeUtil.getBoolean(), InfixExpression.Operator.NOT_EQUALS, new SimpleName(resourceVar), new NullLiteral(typeUtil.getNull()))).setThenStatement(new Block().addStatement(new IfStatement().setExpression(new InfixExpression(typeUtil.getBoolean(), InfixExpression.Operator.NOT_EQUALS, new SimpleName(primaryException), new NullLiteral(typeUtil.getNull()))).setThenStatement(new Block().addStatement(new TryStatement().setBody(new Block().addStatement(closeResource)).addCatchClause(new CatchClause().setException(new SingleVariableDeclaration(suppressedException)).setBody(new Block().addStatement(new ExpressionStatement(new MethodInvocation(addSuppressedMethod, typeUtil.getVoid(), new SimpleName(primaryException)).addArgument(new SimpleName(suppressedException)))))))).setElseStatement(new Block().addStatement(closeResource.copy()))))));
// Visit the new block instead of the current node because some of content of the node (eg. the
// resource initializer) has been moved outside of the try node.
block.accept(this);
return false;
}
use of com.google.devtools.j2objc.ast.Assignment in project j2objc by google.
the class EnumRewriter method addArcInitialization.
// ARC does not allow using "objc_constructInstance" so ARC code doesn't get
// the shared allocation optimization.
private void addArcInitialization(EnumDeclaration node) {
List<Statement> stmts = node.getClassInitStatements().subList(0, 0);
int i = 0;
for (EnumConstantDeclaration constant : node.getEnumConstants()) {
VariableElement varElement = constant.getVariableElement();
ClassInstanceCreation creation = new ClassInstanceCreation(constant.getExecutablePair());
TreeUtil.copyList(constant.getArguments(), creation.getArguments());
String stringLiteralName = options.stripEnumConstants() ? ENUM_NAME_STRIPPED : ElementUtil.getName(varElement);
creation.addArgument(new StringLiteral(stringLiteralName, typeUtil));
creation.addArgument(new NumberLiteral(i++, typeUtil));
creation.setHasRetainedResult(true);
stmts.add(new ExpressionStatement(new Assignment(new SimpleName(varElement), creation)));
}
}
use of com.google.devtools.j2objc.ast.Assignment in project j2objc by google.
the class UnsequencedExpressionRewriter method extractConditionalExpression.
private void extractConditionalExpression(List<Statement> stmtList, ConditionalExpression conditional, List<VariableAccess> toExtract) {
Expression condition = conditional.getExpression();
Expression thenExpr = conditional.getThenExpression();
Expression elseExpr = conditional.getElseExpression();
List<VariableAccess> conditionAccesses = Lists.newArrayList();
List<VariableAccess> thenAccesses = Lists.newArrayList();
List<VariableAccess> elseAccesses = Lists.newArrayList();
boolean needsExtraction = false;
for (VariableAccess access : toExtract) {
TreeNode node = access.expression;
while (node.getParent() != conditional) {
node = node.getParent();
}
if (node == condition) {
conditionAccesses.add(access);
} else if (node == thenExpr) {
thenAccesses.add(access);
} else if (node == elseExpr) {
elseAccesses.add(access);
} else {
throw new AssertionError();
}
if (node != condition) {
// We need to extract an if-statement if there is an access that
// executes conditionally.
needsExtraction = true;
}
}
extractOrderedAccesses(stmtList, condition, conditionAccesses);
// The recursive call might replace the condition child.
condition = conditional.getExpression();
if (needsExtraction) {
VariableElement resultVar = GeneratedVariableElement.newLocalVar("unseq$" + count++, conditional.getTypeMirror(), currentMethod);
conditional.replaceWith(new SimpleName(resultVar));
stmtList.add(new VariableDeclarationStatement(resultVar, null));
IfStatement newIf = new IfStatement();
newIf.setExpression(condition.copy());
stmtList.add(newIf);
Block thenBlock = new Block();
newIf.setThenStatement(thenBlock);
List<Statement> thenStmts = thenBlock.getStatements();
extractOrderedAccesses(thenStmts, thenExpr, thenAccesses);
// The recursive call might replace the then expression child.
thenExpr = conditional.getThenExpression();
thenStmts.add(new ExpressionStatement(new Assignment(new SimpleName(resultVar), thenExpr.copy())));
Block elseBlock = new Block();
newIf.setElseStatement(elseBlock);
List<Statement> elseStmts = elseBlock.getStatements();
extractOrderedAccesses(elseStmts, elseExpr, elseAccesses);
// The recursive call might replace the else expression child.
elseExpr = conditional.getElseExpression();
elseStmts.add(new ExpressionStatement(new Assignment(new SimpleName(resultVar), elseExpr.copy())));
} else {
extractOrderedAccesses(stmtList, thenExpr, thenAccesses);
extractOrderedAccesses(stmtList, elseExpr, elseAccesses);
}
}
use of com.google.devtools.j2objc.ast.Assignment in project j2objc by google.
the class UnsequencedExpressionRewriter method isUnsequenced.
private boolean isUnsequenced(VariableAccess modification, Set<TreeNode> modificationAncestors, VariableAccess access) {
TreeNode commonAncestor = currentTopNode;
TreeNode node = access.expression;
while (node != currentTopNode) {
if (modificationAncestors.contains(node)) {
commonAncestor = node;
break;
}
node = node.getParent();
}
// contain the other access, then they are not unsequenced.
if (isConditional(commonAncestor) && (isWithinConditionalBranch(modification.expression, commonAncestor) || isWithinConditionalBranch(access.expression, commonAncestor))) {
return false;
} else if (commonAncestor instanceof CommaExpression) {
return false;
} else if (commonAncestor instanceof Assignment && modification.expression == commonAncestor) {
// "i = 1 + i++;" is unsequenced (according to clang).
return access.expression instanceof PrefixExpression || access.expression instanceof PostfixExpression;
}
return true;
}
Aggregations