use of com.sun.tools.javac.tree.JCTree.JCStatement in project ceylon-compiler by ceylon.
the class ClassTransformer method makeReassignFinalField.
private JCStatement makeReassignFinalField(JCExpression fieldType, String fieldName, JCExpression newValue) {
final JCStatement assignment;
JCExpression mhExpr = utilInvocation().setter(naming.makeUnquotedIdent("lookup"), // TODO field name should encapsulated
make().Literal(fieldName));
JCExpression expr = make().Apply(null, naming.makeQualIdent(mhExpr, "invokeExact"), List.of(naming.makeThis(), // We always typecast here, due to method handle
make().TypeCast(fieldType, newValue)));
assignment = make().Exec(expr);
return assignment;
}
use of com.sun.tools.javac.tree.JCTree.JCStatement in project ceylon-compiler by ceylon.
the class StatementTransformer method transformIterableIteration.
/**
* The transformation of a ceylon {@code for} loop:
*
* <pre>
* java.lang.Object ITERATION_VAR_NAME;
* Iterator<ITERATOR_ELEMENT_TYPE> ITERATOR_VAR_NAME = ITERABLE.getIterator();
* while (
* !((ITERATION_VAR_NAME = ITERATOR_VAR_NAME.getNext()) instanceof ceylon.language.Finished;
* ) {
* ITEM_DECLS;
* BODY_STMTS;
* }
* </pre>
* @param label
*
* @param iterationVarName The iteration variable (which recieves the value of {@code Iterator.next()})
* @param iteratorVarName The name of the {@code Iterator} variable
* @param iteratorElementType The type argument of the {@code Iterator}
* @param iterableExpr The {@code Iterable} expression
* @param itemDecls variable declarations for the iteration variables which
* begin the loop body (these depend on {@code iterationVarName} and may
* typecast or destructure it). May be null.
* @param bodyStmts Other statements in the loop body
* @return
*/
List<JCStatement> transformIterableIteration(Node node, Name label, Naming.SyntheticName iterationVarName, Naming.SyntheticName iteratorVarName, Type iterableType, Type iteratedType, JCExpression iterableExpr, List<JCStatement> itemDecls, List<JCStatement> bodyStmts, boolean allowArrayOpt, boolean allowArraySeqOpt) {
Type iteratorElementType = iteratedType;
ListBuffer<JCStatement> result = ListBuffer.<JCStatement>lb();
// TODO Only when the iterable *could be* an array (e.g. if static type is Iterable, but not if static type is Sequence)
// TODO Need to use naming.Infix for the hidden members of Array
boolean optForArray = allowArrayOpt && typeFact().getArrayType(iteratedType).isSubtypeOf(iterableType);
boolean optForTuple = allowArraySeqOpt && typeFact().getTupleType(Collections.singletonList(iteratedType), true, false, -1).isSubtypeOf(iterableType);
SyntheticName iterableName = optForArray || optForTuple ? naming.alias("iterable") : null;
SyntheticName isArrayName = optForArray ? naming.alias("isArray") : null;
SyntheticName isTupleName = optForTuple ? naming.alias("isTuple") : null;
SyntheticName arrayName = optForArray || optForTuple ? naming.alias("array") : null;
SyntheticName arrayIndex = optForArray || optForTuple ? naming.alias("i") : null;
SyntheticName arrayLength = optForArray || optForTuple ? naming.alias("length") : null;
if (optForArray || optForTuple) {
result.append(makeVar(FINAL, iterableName, makeJavaType(typeFact().getIterableType(iteratorElementType)), iterableExpr));
}
if (optForArray) {
result.append(makeVar(FINAL, isArrayName, make().Type(syms().booleanType), make().TypeTest(iterableName.makeIdent(), makeJavaType(typeFact().getArrayType(iteratorElementType), JT_RAW))));
}
if (optForTuple) {
result.append(makeVar(FINAL, isTupleName, make().Type(syms().booleanType), make().Binary(JCTree.AND, make().TypeTest(iterableName.makeIdent(), make().QualIdent(syms().ceylonTupleType.tsym)), make().Binary(JCTree.NE, make().Apply(null, naming.makeQualIdent(make().TypeCast(make().QualIdent(syms().ceylonTupleType.tsym), iterableName.makeIdent()), Unfix.$getArray$.toString()), List.<JCExpression>nil()), makeNull()))));
}
// java.lang.Object ELEM_NAME;
JCVariableDecl elemDecl = makeVar(iterationVarName, make().Type(syms().objectType), optForArray || optForTuple ? makeNull() : null);
result.append(elemDecl);
SyntheticName iterName = iteratorVarName;
Type iteratorType = typeFact().getIteratorType(iteratorElementType);
JCExpression iteratorTypeExpr = makeJavaType(iteratorType, CeylonTransformer.JT_TYPE_ARGUMENT);
// ceylon.language.Iterator<T> LOOP_VAR_NAME$iter$X = ITERABLE.getIterator();
// We don't need to unerase here as anything remotely a sequence will be erased to Iterable, which has getIterator()
JCExpression getIter;
if (optForArray || optForTuple) {
at(node);
result.append(makeVar(FINAL, arrayName, make().Type(syms().objectType), null));
result.append(makeVar(arrayIndex, make().Type(syms().intType), make().Literal(0)));
result.append(makeVar(FINAL, arrayLength, make().Type(syms().intType), null));
ListBuffer<JCStatement> whenTuple = ListBuffer.<JCTree.JCStatement>lb();
whenTuple.append(make().Exec(make().Assign(arrayName.makeIdent(), make().Apply(null, naming.makeQualIdent(make().TypeCast(make().QualIdent(syms().ceylonTupleType.tsym), iterableName.makeIdent()), Unfix.$getArray$.toString()), List.<JCExpression>nil()))));
whenTuple.append(make().Exec(make().Assign(arrayIndex.makeIdent(), make().Apply(null, naming.makeQualIdent(make().TypeCast(make().QualIdent(syms().ceylonTupleType.tsym), iterableName.makeIdent()), Unfix.$getFirst$.toString()), List.<JCExpression>nil()))));
whenTuple.append(make().Exec(make().Assign(arrayLength.makeIdent(), make().Binary(JCTree.PLUS, arrayIndex.makeIdent(), make().Apply(null, naming.makeQualIdent(make().TypeCast(make().QualIdent(syms().ceylonTupleType.tsym), iterableName.makeIdent()), Unfix.$getLength$.toString()), List.<JCExpression>nil())))));
ListBuffer<JCStatement> whenArray = ListBuffer.<JCTree.JCStatement>lb();
whenArray.append(make().Exec(make().Assign(arrayName.makeIdent(), make().Apply(null, naming.makeQualIdent(make().TypeCast(makeJavaType(typeFact().getArrayType(typeFact().getAnythingType()), JT_RAW), iterableName.makeIdent()), "toArray"), List.<JCExpression>nil()))));
whenArray.append(make().Exec(make().Assign(arrayLength.makeIdent(), make().Apply(null, naming.makeQuotedFQIdent("com.redhat.ceylon.compiler.java.Util.arrayLength"), List.<JCExpression>of(arrayName.makeIdent())))));
ListBuffer<JCStatement> whenIterable = ListBuffer.<JCTree.JCStatement>lb();
whenIterable.append(make().Exec(make().Assign(arrayName.makeIdent(), makeNull())));
whenIterable.append(make().Exec(make().Assign(arrayLength.makeIdent(), make().Literal(0))));
if (optForArray && optForTuple) {
result.append(make().If(isTupleName.makeIdent(), make().Block(0, whenTuple.toList()), make().If(isArrayName.makeIdent(), make().Block(0, whenArray.toList()), make().Block(0, whenIterable.toList()))));
} else {
result.append(make().If((optForArray ? isArrayName : isTupleName).makeIdent(), make().Block(0, (optForArray ? whenArray : whenTuple).toList()), make().Block(0, whenIterable.toList())));
}
getIter = make().Conditional(optForArray && optForTuple ? make().Binary(JCTree.OR, isTupleName.makeIdent(), isArrayName.makeIdent()) : optForArray ? isArrayName.makeIdent() : isTupleName.makeIdent(), makeNull(), make().Apply(null, makeSelect(iterableName.makeIdent(), "iterator"), List.<JCExpression>nil()));
} else {
getIter = at(node).Apply(null, makeSelect(iterableExpr, "iterator"), List.<JCExpression>nil());
}
getIter = gen().expressionGen().applyErasureAndBoxing(getIter, iteratorType, true, BoxingStrategy.BOXED, iteratorType);
JCVariableDecl iteratorDecl = at(node).VarDef(make().Modifiers(0), iterName.asName(), iteratorTypeExpr, getIter);
// .ceylon.language.Iterator<T> LOOP_VAR_NAME$iter$X = ITERABLE.getIterator();
result.append(iteratorDecl);
ListBuffer<JCStatement> loopBody = ListBuffer.<JCStatement>lb();
if (optForArray || optForTuple) {
JCExpression cond;
if (optForArray && optForTuple) {
cond = make().Binary(JCTree.OR, isTupleName.makeIdent(), isArrayName.makeIdent());
} else if (optForArray) {
cond = isArrayName.makeIdent();
} else {
cond = isTupleName.makeIdent();
}
loopBody.append(make().If(cond, make().Exec(make().Assign(iterationVarName.makeIdent(), make().Apply(null, naming.makeQuotedFQIdent("com.redhat.ceylon.compiler.java.Util.getObjectArray"), List.<JCExpression>of(arrayName.makeIdent(), make().Unary(JCTree.POSTINC, arrayIndex.makeIdent()))))), null));
}
if (itemDecls != null) {
loopBody.appendList(itemDecls);
}
// The user-supplied contents of the loop
loopBody.appendList(bodyStmts);
// ELEM_NAME = LOOP_VAR_NAME$iter$X.next()
JCExpression iter_elem = make().Apply(null, makeSelect(iterName.makeIdent(), "next"), List.<JCExpression>nil());
JCExpression elem_assign = make().Assign(iterationVarName.makeIdent(), iter_elem);
// !((ELEM_NAME = LOOP_VAR_NAME$iter$X.next()) instanceof Finished)
JCExpression instof = make().TypeTest(elem_assign, makeIdent(syms().ceylonFinishedType));
JCExpression loopCond = make().Unary(JCTree.NOT, instof);
if (optForArray || optForTuple) {
JCExpression cond;
if (optForArray && optForTuple) {
cond = make().Binary(JCTree.OR, isTupleName.makeIdent(), isArrayName.makeIdent());
} else if (optForArray) {
cond = isArrayName.makeIdent();
} else {
cond = isTupleName.makeIdent();
}
loopCond = make().Conditional(cond, make().Binary(JCTree.LT, arrayIndex.makeIdent(), arrayLength.makeIdent()), make().Unary(JCTree.NOT, instof));
}
// while (!(($elem$X = $V$iter$X.next()) instanceof Finished); ) {
JCStatement whileLoop = at(node).WhileLoop(loopCond, at(node).Block(0, loopBody.toList()));
if (label != null) {
whileLoop = make().Labelled(label, whileLoop);
}
return result.append(whileLoop).toList();
}
use of com.sun.tools.javac.tree.JCTree.JCStatement in project ceylon-compiler by ceylon.
the class StatementTransformer method transform.
public JCStatement transform(Tree.TryCatchStatement t) {
Tree.TryClause tryClause = t.getTryClause();
at(tryClause);
JCBlock tryBlock = transform(tryClause.getBlock());
Tree.ResourceList resList = tryClause.getResourceList();
if (resList != null) {
ArrayList<Tree.Resource> resources = new ArrayList<Tree.Resource>(resList.getResources());
Collections.reverse(resources);
for (Tree.Resource res : resources) {
List<JCStatement> stats = List.nil();
Tree.Expression resExpr;
String resVarName;
if (res.getExpression() != null) {
resExpr = res.getExpression();
resVarName = naming.newTemp("try");
} else if (res.getVariable() != null) {
Tree.Variable var = res.getVariable();
resExpr = var.getSpecifierExpression().getExpression();
resVarName = var.getIdentifier().getText();
} else {
throw new BugException(res, "missing resource expression");
}
boolean isDestroyable = typeFact().getDestroyableType().isSupertypeOf(resExpr.getTypeModel());
Type resVarType = resExpr.getTypeModel();
Type resVarExpectedType = isDestroyable ? typeFact().getDestroyableType() : typeFact().getObtainableType();
// CloseableType $var = resource-expression
JCExpression expr = expressionGen().transformExpression(resExpr);
JCExpression javaType = makeJavaType(resVarType);
JCVariableDecl var = makeVar(FINAL, resVarName, javaType, expr);
stats = stats.append(var);
if (!isDestroyable) {
JCExpression resVar0 = expressionGen().applyErasureAndBoxing(makeUnquotedIdent(resVarName), resVarType, true, BoxingStrategy.BOXED, resVarExpectedType);
JCMethodInvocation openCall = make().Apply(null, makeQualIdent(resVar0, "obtain"), List.<JCExpression>nil());
stats = stats.append(make().Exec(openCall));
}
// Exception $tpmex = null;
String innerExTmpVarName = naming.newTemp("ex");
JCExpression innerExType = makeJavaType(typeFact().getThrowableType(), JT_CATCH);
JCVariableDecl innerExTmpVar = makeVar(innerExTmpVarName, innerExType, makeNull());
stats = stats.append(innerExTmpVar);
// $tmpex = ex;
List<JCStatement> innerCatchStats = List.nil();
Name innerCatchVarName = naming.tempName("ex");
JCAssign exTmpAssign = make().Assign(makeUnquotedIdent(innerExTmpVarName), make().Ident(innerCatchVarName));
innerCatchStats = innerCatchStats.append(make().Exec(exTmpAssign));
// throw ex;
JCThrow innerCatchThrow = make().Throw(make().Ident(innerCatchVarName));
innerCatchStats = innerCatchStats.append(innerCatchThrow);
JCBlock innerCatchBlock = make().Block(0, innerCatchStats);
// $var.close() /// ((Closeable)$var).close()
JCExpression exarg = makeUnquotedIdent(innerExTmpVarName);
JCExpression resVar1 = expressionGen().applyErasureAndBoxing(makeUnquotedIdent(resVarName), resVarType, true, BoxingStrategy.BOXED, resVarExpectedType);
JCMethodInvocation closeCall = make().Apply(null, makeQualIdent(resVar1, isDestroyable ? "destroy" : "release"), List.<JCExpression>of(exarg));
JCBlock closeTryBlock = make().Block(0, List.<JCStatement>of(make().Exec(closeCall)));
// try { $var.close() } catch (Exception closex) { $tmpex.addSuppressed(closex); }
Name closeCatchVarName = naming.tempName("closex");
JCExpression closeCatchExType = makeJavaType(typeFact().getThrowableType(), JT_CATCH);
JCVariableDecl closeCatchVar = make().VarDef(make().Modifiers(Flags.FINAL), closeCatchVarName, closeCatchExType, null);
JCExpression addarg = make().Ident(closeCatchVarName);
JCMethodInvocation addSuppressedCall = make().Apply(null, makeQualIdent(makeUnquotedIdent(innerExTmpVarName), "addSuppressed"), List.<JCExpression>of(addarg));
JCCatch closeCatch = make().Catch(closeCatchVar, make().Block(0, List.<JCStatement>of(make().Exec(addSuppressedCall))));
JCTry closeTry = at(res).Try(closeTryBlock, List.<JCCatch>of(closeCatch), null);
// $var.close() /// ((Closeable)$var).close()
JCExpression exarg2 = makeUnquotedIdent(innerExTmpVarName);
JCExpression resVar2 = expressionGen().applyErasureAndBoxing(makeUnquotedIdent(resVarName), resVarType, true, BoxingStrategy.BOXED, resVarExpectedType);
JCMethodInvocation closeCall2 = make().Apply(null, makeQualIdent(resVar2, isDestroyable ? "destroy" : "release"), List.<JCExpression>of(exarg2));
// if ($tmpex != null) { ... } else { ... }
JCBinary closeCatchCond = make().Binary(JCTree.NE, makeUnquotedIdent(innerExTmpVarName), makeNull());
JCIf closeCatchIf = make().If(closeCatchCond, closeTry, make().Exec(closeCall2));
// try { .... } catch (Exception ex) { $tmpex=ex; throw ex; }
// finally { try { $var.close() } catch (Exception closex) { } }
JCExpression innerCatchExType = makeJavaType(typeFact().getThrowableType(), JT_CATCH);
JCVariableDecl innerCatchVar = make().VarDef(make().Modifiers(Flags.FINAL), innerCatchVarName, innerCatchExType, null);
JCCatch innerCatch = make().Catch(innerCatchVar, innerCatchBlock);
JCBlock innerFinallyBlock = make().Block(0, List.<JCStatement>of(closeCatchIf));
JCTry innerTry = at(res).Try(tryBlock, List.<JCCatch>of(innerCatch), innerFinallyBlock);
stats = stats.append(innerTry);
tryBlock = at(res).Block(0, stats);
}
}
final List<JCCatch> catches;
if (usePolymorphicCatches(t.getCatchClauses())) {
catches = transformCatchesPolymorphic(t.getCatchClauses());
} else {
catches = transformCatchesIfElseIf(t.getCatchClauses());
}
final JCBlock finallyBlock;
Tree.FinallyClause finallyClause = t.getFinallyClause();
if (finallyClause != null) {
at(finallyClause);
finallyBlock = transform(finallyClause.getBlock());
} else {
finallyBlock = null;
}
if (!catches.isEmpty() || finallyBlock != null) {
return at(t).Try(tryBlock, catches, finallyBlock);
} else {
return tryBlock;
}
}
use of com.sun.tools.javac.tree.JCTree.JCStatement in project ceylon-compiler by ceylon.
the class StatementTransformer method makeThenBlock.
private JCBlock makeThenBlock(Cond cond, Node thenPart, Substitution subs, String tmpVar, Tree.Term outerExpression, Type expectedType) {
List<JCStatement> blockStmts;
if (thenPart instanceof Tree.Block)
blockStmts = statementGen().transformBlock((Tree.Block) thenPart);
else if (thenPart instanceof Tree.Expression) {
blockStmts = evaluateAndAssign(tmpVar, (Tree.Expression) thenPart, outerExpression, expectedType);
} else if (thenPart == null) {
blockStmts = List.<JCStatement>nil();
} else {
blockStmts = List.<JCStatement>of(make().Exec(makeErroneous(thenPart, "Only block or expression allowed")));
}
if (subs != null) {
// The variable holding the result for the code inside the code block
blockStmts = blockStmts.prepend(at(cond.getCondition()).VarDef(make().Modifiers(FINAL), names().fromString(subs.substituted), cond.getVarTrans().makeTypeExpr(), cond.getVarTrans().makeResultExpr()));
}
JCBlock thenBlock = at(cond.getCondition()).Block(0, blockStmts);
return thenBlock;
}
use of com.sun.tools.javac.tree.JCTree.JCStatement in project ceylon-compiler by ceylon.
the class NamedArgumentInvocation method bindObjectArgument.
private void bindObjectArgument(Tree.ObjectArgument objectArg, Parameter declaredParam, Naming.SyntheticName argName) {
ListBuffer<JCStatement> statements;
List<JCTree> object = gen.classGen().transformObjectArgument(objectArg);
// No need to worry about boxing (it cannot be a boxed type)
JCVariableDecl varDecl = gen.makeLocalIdentityInstance(argName.getName(), Naming.quoteClassName(objectArg.getIdentifier().getText()), false);
statements = toStmts(objectArg, object).append(varDecl);
bind(declaredParam, argName, gen.makeJavaType(objectArg.getType().getTypeModel()), statements.toList());
}
Aggregations