use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression in project ceylon by eclipse.
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 org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression in project ceylon by eclipse.
the class StatementTransformer method transformVariableOrDestructure.
public List<JCStatement> transformVariableOrDestructure(Tree.Statement varOrDes) {
List<JCStatement> vars = List.<JCStatement>nil();
if (varOrDes instanceof Tree.Variable) {
Tree.Variable var = (Tree.Variable) varOrDes;
Expression expr = var.getSpecifierExpression().getExpression();
BoxingStrategy boxingStrategy = CodegenUtil.getBoxingStrategy(var.getDeclarationModel());
JCExpression init = expressionGen().transformExpression(expr, boxingStrategy, var.getType().getTypeModel());
vars = vars.append(transformVariable(var, init, expr.getTypeModel(), boxingStrategy == BoxingStrategy.BOXED).build());
} else if (varOrDes instanceof Tree.Destructure) {
Tree.Destructure des = (Tree.Destructure) varOrDes;
vars = vars.appendList(transform(des));
} else {
throw BugException.unhandledNodeCase(varOrDes);
}
return vars;
}
use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression in project ceylon by eclipse.
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");
}
final TryResourceTransformation resourceTx;
if (typeFact().getDestroyableType().isSupertypeOf(resExpr.getTypeModel())) {
resourceTx = destroyableResource;
} else if (typeFact().getObtainableType().isSupertypeOf(resExpr.getTypeModel())) {
resourceTx = obtainableResource;
} else if (javacJavaTypeToProducedType(syms().autoCloseableType).isSupertypeOf(resExpr.getTypeModel())) {
resourceTx = javaAutoCloseableResource;
} else {
throw BugException.unhandledTypeCase(resExpr.getTypeModel());
}
Type resVarType = resExpr.getTypeModel();
Type resVarExpectedType = resourceTx.getType();
// 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 (resourceTx.getInitMethodName() != null) {
JCExpression resVar0 = expressionGen().applyErasureAndBoxing(makeUnquotedIdent(resVarName), resVarType, true, BoxingStrategy.BOXED, resVarExpectedType);
JCMethodInvocation openCall = make().Apply(null, makeQualIdent(resVar0, resourceTx.getInitMethodName()), 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);
JCExpression closeCall = resourceTx.makeRecover(resVar1, 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));
JCStatement catchForClose;
if (resourceTx != javaAutoCloseableResource) {
// Obtainable.release() and Destroyable.close() could
// rethrow the originating exception, so guard against
// self-supression (which causes addSuppressed() to throw
catchForClose = make().If(make().Binary(JCTree.Tag.NE, makeUnquotedIdent(innerExTmpVarName), make().Ident(closeCatchVarName)), make().Block(0, List.<JCStatement>of(make().Exec(addSuppressedCall))), null);
} else {
// AutoClosable can't rethrow the originating exception,
// so no need to worry about self suppression
catchForClose = make().Exec(addSuppressedCall);
}
JCCatch closeCatch = make().Catch(closeCatchVar, make().Block(0, List.<JCStatement>of(catchForClose)));
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);
JCExpression closeCall2 = resourceTx.makeRecover(resVar1, exarg);
// if ($tmpex != null) { ... } else { ... }
JCBinary closeCatchCond = make().Binary(JCTree.Tag.NE, makeUnquotedIdent(innerExTmpVarName), makeNull());
JCIf closeCatchIf = make().If(closeCatchCond, make().Block(0, List.<JCStatement>of(closeTry)), make().Block(0, List.<JCStatement>of(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 org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression in project ceylon by eclipse.
the class ExpressionTransformer method transformSpreadArgument.
private ExpressionAndType transformSpreadArgument(SimpleInvocation invocation, int numArguments, int argIndex, BoxingStrategy boxingStrategy, Type parameterType) {
ExpressionAndType exprAndType;
final Type iteratedType = typeFact().getIteratedType(parameterType);
final JCExpression expr;
final JCExpression type;
// optimise "*javaArray.iterable" into "javaArray" for java variadic parameters, since we can pass them just along
if (invocation.isJavaVariadicMethod() && numArguments == argIndex + 1 && !invocation.isArgumentComprehension(argIndex)) {
Expression argumentExpression = invocation.getArgumentExpression(argIndex);
Term argument = Decl.unwrapExpressionsUntilTerm(argumentExpression);
if (argument instanceof Tree.QualifiedMemberExpression) {
Tree.QualifiedMemberExpression qualifiedMemberArgument = (Tree.QualifiedMemberExpression) argument;
if ("iterable".equals(qualifiedMemberArgument.getIdentifier().getText()) && isJavaArray(qualifiedMemberArgument.getPrimary().getTypeModel())) {
// just pass the array as-is
// we don't care at all about unboxing or casting since we can't be dealing with boxing
// and we generate our own cast, at least for non-primitive arrays where it may be ambiguous,
// we could avoid the cast for non-type-parameter and non-Object arrays, but that's more expensive
// to check for
JCExpression primary = transformExpression(qualifiedMemberArgument.getPrimary());
type = makeJavaType(typeFact().getSequenceType(iteratedType).getType());
if (isJavaObjectArray(qualifiedMemberArgument.getPrimary().getTypeModel())) {
expr = make().TypeCast(makeJavaType(qualifiedMemberArgument.getPrimary().getTypeModel()), primary);
} else {
expr = primary;
}
return new ExpressionAndType(expr, type);
}
}
}
// invoking f(a, *b), where declared f(A a, B* b)
// we can have several remaining arguments and the last one is spread
List<JCExpression> x = List.<JCExpression>nil();
for (int ii = argIndex; ii < numArguments; ii++) {
JCExpression argExpr = invocation.getTransformedArgumentExpression(ii);
// the last parameter is spread and must be put first
if (ii < numArguments - 1) {
x = x.append(argExpr);
} else {
// convert to a Sequential if required
Type argType = invocation.getArgumentType(ii);
if (typeFact().isJavaArrayType(argType)) {
String methodName;
if (typeFact().getJavaIntArrayDeclaration().equals(argType.getDeclaration())) {
methodName = "org.eclipse.ceylon.compiler.java.language.IntArray.getIterable";
} else if (typeFact().getJavaShortArrayDeclaration().equals(argType.getDeclaration())) {
methodName = "org.eclipse.ceylon.compiler.java.language.ShortArray.getIterable";
} else if (typeFact().getJavaLongArrayDeclaration().equals(argType.getDeclaration())) {
methodName = "org.eclipse.ceylon.compiler.java.language.LongArray.getIterable";
} else if (typeFact().getJavaByteArrayDeclaration().equals(argType.getDeclaration())) {
methodName = "org.eclipse.ceylon.compiler.java.language.ByteArray.getIterable";
} else if (typeFact().getJavaBooleanArrayDeclaration().equals(argType.getDeclaration())) {
methodName = "org.eclipse.ceylon.compiler.java.language.BooleanArray.getIterable";
} else if (typeFact().getJavaCharArrayDeclaration().equals(argType.getDeclaration())) {
methodName = "org.eclipse.ceylon.compiler.java.language.CharArray.getIterable";
} else if (typeFact().getJavaFloatArrayDeclaration().equals(argType.getDeclaration())) {
methodName = "org.eclipse.ceylon.compiler.java.language.FloatArray.getIterable";
} else if (typeFact().getJavaDoubleArrayDeclaration().equals(argType.getDeclaration())) {
methodName = "org.eclipse.ceylon.compiler.java.language.DoubleArray.getIterable";
} else {
methodName = "org.eclipse.ceylon.compiler.java.language.ObjectArray.getIterable";
}
argExpr = make().Apply(null, naming.makeQuotedQualIdentFromString(methodName), List.<JCExpression>of(argExpr));
argExpr = iterableToSequential(argExpr);
} else if (typeFact().isSequentialType(argType)) {
// we're good
} else if (typeFact().isIterableType(argType)) {
argExpr = iterableToSequential(argExpr);
} else if (typeFact().isJavaIterableType(argType)) {
argExpr = utilInvocation().toIterable(makeJavaType(iteratedType, JT_TYPE_ARGUMENT), makeReifiedTypeArgument(iteratedType), argExpr);
argExpr = iterableToSequential(argExpr);
}
x = x.prepend(argExpr);
}
}
if (invocation.isJavaVariadicMethod()) {
// collect all the initial arguments and wrap into a Java array
// first arg is the spread part
JCExpression last = x.head;
// remove it from x
x = x.tail;
Type lastType = invocation.getArgumentType(numArguments - 1);
// must translate it into a Util call
expr = sequenceToJavaArray(invocation, last, parameterType, boxingStrategy, lastType, x);
} else {
JCExpression typeExpr = makeJavaType(iteratedType, JT_TYPE_ARGUMENT);
JCExpression sequentialExpr = utilInvocation().sequentialInstance(typeExpr, makeReifiedTypeArgument(iteratedType), x.head, x.tail);
if (invocation.isParameterVariadicPlus(argIndex)) {
expr = utilInvocation().castSequentialToSequence(sequentialExpr, iteratedType);
} else {
expr = sequentialExpr;
}
}
type = makeJavaType(typeFact().getSequenceType(iteratedType).getType());
exprAndType = new ExpressionAndType(expr, type);
return exprAndType;
}
use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression in project ceylon by eclipse.
the class BoxingVisitor method visit.
@Override
public void visit(Tree.SwitchExpression that) {
super.visit(that);
SwitchCaseList caseList = that.getSwitchCaseList();
if (caseList == null || caseList.getCaseClauses() == null)
return;
boolean unboxed = true;
for (Tree.CaseClause caseClause : caseList.getCaseClauses()) {
Expression expr = caseClause.getExpression();
if (expr == null)
return;
// a single boxed one makes the whole switch boxed
if (!CodegenUtil.isUnBoxed(expr))
unboxed = false;
// A Switch expression can never be raw, type erased or untrusted because
// it uses a Let with a new variable declaration, so the rawness,
// erasedness and untrustedness of its branches cannot propagate further
// up the tree.
}
if (caseList.getElseClause() != null) {
Expression expr = caseList.getElseClause().getExpression();
if (expr == null)
return;
// a single boxed one makes the whole switch boxed
if (!CodegenUtil.isUnBoxed(expr))
unboxed = false;
// see comment about about why we don't propagate rawness etc here.
}
if (unboxed && !willEraseToObject(that.getUnit().denotableType(that.getTypeModel())))
CodegenUtil.markUnBoxed(that);
if (that.getTypeModel().isExactly(that.getUnit().getNullValueType())) {
CodegenUtil.markTypeErased(that);
}
}
Aggregations