use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement in project ceylon by eclipse.
the class StatementTransformer method transformCaseMatch.
private JCStatement transformCaseMatch(Naming.SyntheticName selectorAlias, Tree.SwitchClause switchClause, Tree.CaseClause caseClause, String tmpVar, Tree.Term outerExpression, Type expectedType, Tree.MatchCase matchCase, JCStatement last, Type switchType, boolean primitiveSelector) {
at(matchCase);
JCVariableDecl decl2 = null;
Substitution prevSubst2 = null;
if (matchCase.getVariable() != null) {
// Use the type of the variable, which is more precise than the type we test for.
Type varType = matchCase.getVariable().getDeclarationModel().getType();
String name = matchCase.getVariable().getIdentifier().getText();
TypedDeclaration varDecl = matchCase.getVariable().getDeclarationModel();
Naming.SyntheticName tmpVarName = selectorAlias;
Name substVarName = naming.aliasName(name);
// Want raw type for instanceof since it can't be used with generic types
JCExpression rawToTypeExpr = makeJavaType(varType, JT_NO_PRIMITIVES | JT_RAW);
// Substitute variable with the correct type to use in the rest of the code block
JCExpression tmpVarExpr = at(matchCase).TypeCast(rawToTypeExpr, tmpVarName.makeIdent());
JCExpression toTypeExpr;
if (isCeylonBasicType(varType) && varDecl.getUnboxed() == true) {
toTypeExpr = makeJavaType(varType);
tmpVarExpr = unboxType(tmpVarExpr, varType);
} else {
toTypeExpr = makeJavaType(varType, JT_NO_PRIMITIVES);
}
// The variable holding the result for the code inside the code block
decl2 = at(matchCase).VarDef(make().Modifiers(FINAL), substVarName, toTypeExpr, tmpVarExpr);
// Prepare for variable substitution in the following code block
prevSubst2 = naming.addVariableSubst(varDecl, substVarName.toString());
}
JCExpression tests = null;
java.util.List<Tree.Expression> expressions = matchCase.getExpressionList().getExpressions();
for (Tree.Expression expr : expressions) {
Tree.Term term = ExpressionTransformer.eliminateParens(expr.getTerm());
boolean unboxedEquality = primitiveSelector || isCeylonBasicType(typeFact().getDefiniteType(switchType));
Type type = term.getTypeModel();
JCExpression transformedExpression = expressionGen().transformExpression(term, unboxedEquality ? BoxingStrategy.UNBOXED : BoxingStrategy.BOXED, type);
JCExpression test;
if (term instanceof Tree.Literal || term instanceof Tree.NegativeOp) {
if (unboxedEquality) {
if (term instanceof Tree.StringLiteral) {
test = make().Apply(null, makeSelect(unboxType(selectorAlias.makeIdent(), type), "equals"), List.<JCExpression>of(transformedExpression));
} else {
test = make().Binary(JCTree.Tag.EQ, primitiveSelector ? selectorAlias.makeIdent() : unboxType(selectorAlias.makeIdent(), type), transformedExpression);
}
} else {
test = make().Apply(null, makeSelect(selectorAlias.makeIdent(), "equals"), List.<JCExpression>of(transformedExpression));
}
if (isOptional(switchType)) {
test = make().Binary(JCTree.Tag.AND, make().Binary(JCTree.Tag.NE, selectorAlias.makeIdent(), makeNull()), test);
}
} else {
JCExpression selectorExpr;
if (!primitiveSelector && isCeylonBasicType(typeFact().getDefiniteType(switchType))) {
selectorExpr = unboxType(selectorAlias.makeIdent(), type);
} else {
selectorExpr = selectorAlias.makeIdent();
}
if (term instanceof Tree.Tuple) {
if (type.isEmpty()) {
test = make().TypeTest(selectorAlias.makeIdent(), makeJavaType(typeFact().getEmptyType(), JT_RAW));
} else {
test = make().Apply(null, makeSelect(selectorExpr, "equals"), List.<JCExpression>of(transformedExpression));
test = make().Binary(Tag.AND, make().TypeTest(selectorAlias.makeIdent(), make().QualIdent(syms().ceylonTupleType.tsym)), test);
}
} else if (type.isString()) {
test = make().Apply(null, makeSelect(selectorExpr, "equals"), List.<JCExpression>of(transformedExpression));
} else {
test = make().Binary(JCTree.Tag.EQ, selectorExpr, transformedExpression);
}
}
if (tests == null) {
tests = test;
} else if (isNull(type)) {
// ensure we do any null check as the first operation in the ||-ed expression
tests = make().Binary(JCTree.Tag.OR, test, tests);
} else {
tests = make().Binary(JCTree.Tag.OR, tests, test);
}
}
java.util.List<Tree.Type> types = matchCase.getExpressionList().getTypes();
for (Tree.Type caseType : types) {
// note: There's no point using makeOptimizedTypeTest() because cases are disjoint
// anyway and the cheap cases get evaluated first.
Type type = caseType.getTypeModel();
JCExpression cond = makeTypeTest(null, selectorAlias, type, type);
if (tests == null) {
tests = cond;
} else if (isNull(type)) {
// ensure we do any null check as the first operation in the ||-ed expression
tests = make().Binary(JCTree.Tag.OR, cond, tests);
} else {
tests = make().Binary(JCTree.Tag.OR, tests, cond);
}
}
Substitution prevSubst = null;
if (switchClause.getSwitched().getVariable() != null) {
// Prepare for variable substitution in the following code block
prevSubst = naming.addVariableSubst(switchClause.getSwitched().getVariable().getDeclarationModel(), selectorAlias.toString());
}
JCBlock block;
if (decl2 != null) {
List<JCStatement> stats = List.<JCStatement>of(decl2);
stats = stats.appendList(transformCaseClause(caseClause, tmpVar, outerExpression, expectedType));
block = at(matchCase).Block(0, stats);
} else {
block = transformCaseClauseBlock(caseClause, tmpVar, outerExpression, expectedType);
}
if (prevSubst2 != null) {
// Deactivate the above variable substitution
prevSubst2.close();
}
if (prevSubst != null) {
// Deactivate the above variable substitution
prevSubst.close();
}
return at(caseClause).If(tests, block, last);
}
use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement in project ceylon by eclipse.
the class StatementTransformer method transformPattern.
List<VarDefBuilder> transformPattern(Tree.Pattern pat, JCExpression varAccessExpr) {
List<VarDefBuilder> result = List.nil();
if (pat instanceof Tree.TuplePattern) {
// For a Tuple we get the value of each of its items and assign it to a local value
int idx = 0;
Tree.TuplePattern tuple = (Tree.TuplePattern) pat;
for (Tree.Pattern p : tuple.getPatterns()) {
JCExpression idxExpr = makeInteger(idx++);
Type ot = typeFact().getObjectType();
JCExpression fullGetExpr;
if (varAccessExpr != null) {
JCExpression seqVarAccessExpr = make().TypeCast(makeJavaType(typeFact().getSequenceType(ot), JT_RAW), varAccessExpr);
JCExpression tupleAccessExpr;
if (isVariadicVariable(p)) {
tupleAccessExpr = makeQualIdent(seqVarAccessExpr, "skip");
} else {
tupleAccessExpr = makeQualIdent(seqVarAccessExpr, "getFromFirst");
}
fullGetExpr = make().Apply(null, tupleAccessExpr, List.of(idxExpr));
if (isVariadicVariable(p)) {
Tree.Variable vp = ((Tree.VariablePattern) p).getVariable();
Type vt = vp.getDeclarationModel().getType();
Naming.SyntheticName tail = naming.alias("tail");
int minLength = p.getUnit().getTupleMinimumLength(vt);
if (minLength > 0) {
// defend against tuples containing finished
JCStatement v = makeVar(tail, makeJavaType(typeFact().getSequentialType(ot), JT_RAW), make().Apply(null, makeQualIdent(fullGetExpr, "sequence"), List.<JCExpression>nil()));
JCStatement c = make().If(make().Apply(null, naming.makeSelect(tail.makeIdent(), "shorterThan"), List.<JCExpression>of(make().Literal(minLength))), makeThrowAssertionException(make().Literal("length of " + vp.getDeclarationModel().getName() + " is less than minimum length of its static type " + vt.asString())), null);
fullGetExpr = make().LetExpr(List.<JCStatement>of(v, c), make().TypeCast(makeJavaType(vt), tail.makeIdent()));
} else {
fullGetExpr = make().Apply(null, makeQualIdent(fullGetExpr, "sequence"), List.<JCExpression>nil());
}
// make sure to put the thing into a tuple if that's what we asked for
if (vt.getDeclaration().inherits(typeFact().getTupleDeclaration())) {
Type iteratedType = typeFact().getIteratedType(vt);
JCExpression typeArg = makeJavaType(iteratedType, JT_NO_PRIMITIVES);
JCExpression reifiedTypeArg = makeReifiedTypeArgument(iteratedType);
fullGetExpr = utilInvocation().sequentialToTuple(typeArg, reifiedTypeArg, fullGetExpr);
}
}
} else {
fullGetExpr = null;
}
result = result.appendList(transformPattern(p, fullGetExpr));
}
} else if (pat instanceof Tree.KeyValuePattern) {
// For an Entry we create two local values, one for the key and one for the value
Tree.KeyValuePattern entry = (Tree.KeyValuePattern) pat;
Type ot = typeFact().getObjectType();
JCExpression getItemExpr;
if (varAccessExpr != null) {
JCExpression entryVarAccessExpr = make().TypeCast(makeJavaType(typeFact().getEntryType(ot, ot), JT_RAW), varAccessExpr);
JCExpression getKeyExpr = make().Apply(null, makeQualIdent(entryVarAccessExpr, "getKey"), List.<JCExpression>nil());
result = result.appendList(transformPattern(entry.getKey(), getKeyExpr));
getItemExpr = make().Apply(null, makeQualIdent(entryVarAccessExpr, "getItem"), List.<JCExpression>nil());
} else {
getItemExpr = null;
}
result = result.appendList(transformPattern(entry.getValue(), getItemExpr));
} else if (pat instanceof Tree.VariablePattern) {
Tree.VariablePattern var = (Tree.VariablePattern) pat;
result = result.append(transformVariable(var.getVariable(), varAccessExpr));
} else {
throw BugException.unhandledNodeCase(pat);
}
return result;
}
use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement in project ceylon by eclipse.
the class StatementTransformer method transformBlock.
public List<JCStatement> transformBlock(Tree.Block block, boolean revertRet) {
if (block == null) {
return List.<JCStatement>nil();
}
at(block);
CeylonVisitor v = gen().visitor;
final ListBuffer<JCTree> prevDefs = v.defs;
final boolean prevInInitializer = v.inInitializer;
final ClassDefinitionBuilder prevClassBuilder = v.classBuilder;
Tree.Block oldBlock = block;
currentBlock = block;
List<JCStatement> result;
try {
v.defs = new ListBuffer<JCTree>();
v.inInitializer = false;
v.classBuilder = current();
pushBlockImports(block);
java.util.Iterator<Statement> statements = block.getStatements().iterator();
while (statements.hasNext()) {
Tree.Statement stmt = statements.next();
Transformer<JCStatement, Return> returnTransformer;
if (revertRet && stmt instanceof Tree.Declaration) {
returnTransformer = returnTransformer(defaultReturnTransformer);
} else {
returnTransformer = this.returnTransformer;
}
try {
HasErrorException error = errors().getFirstErrorBlock(stmt);
if (error == null) {
stmt.visit(v);
} else {
v.append(this.makeThrowUnresolvedCompilationError(error));
break;
}
} finally {
returnTransformer(returnTransformer);
}
}
popBlockImports(block);
result = (List<JCStatement>) v.getResult().toList();
Runnable r = onEndBlock.get(block);
if (r != null) {
r.run();
}
} finally {
v.classBuilder = prevClassBuilder;
v.inInitializer = prevInInitializer;
v.defs = prevDefs;
// Close Substitutions which were scoped to this block
Scope scope = block.getScope();
while (scope instanceof ConditionScope) {
scope = scope.getScope();
}
naming.closeScopedSubstitutions(scope);
currentBlock = oldBlock;
}
return result;
}
use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement in project ceylon by eclipse.
the class StatementTransformer method transformCaseIs.
/**
* Transform a "case(is ...)"
* @param selectorAlias
* @param caseClause
* @param isCase
* @param last
* @return
*/
private JCStatement transformCaseIs(Naming.SyntheticName selectorAlias, Tree.CaseClause caseClause, String tmpVar, Tree.Term outerExpression, Type expectedType, Tree.IsCase isCase, JCStatement last, Type expressionType) {
at(isCase);
// Use the type of the variable, which is more precise than the type we test for.
Type varType = isCase.getVariable().getDeclarationModel().getType();
Type caseType = getIsCaseType(isCase);
// note: There's no point using makeOptimizedTypeTest() because cases are disjoint
// anyway and the cheap cases get evaluated first.
JCExpression cond = makeTypeTest(null, selectorAlias, caseType, expressionType);
String name = isCase.getVariable().getIdentifier().getText();
TypedDeclaration varDecl = isCase.getVariable().getDeclarationModel();
Naming.SyntheticName tmpVarName = selectorAlias;
Name substVarName = naming.aliasName(name);
// Want raw type for instanceof since it can't be used with generic types
JCExpression rawToTypeExpr = makeJavaType(varType, JT_NO_PRIMITIVES | JT_RAW);
// Substitute variable with the correct type to use in the rest of the code block
JCExpression tmpVarExpr = at(isCase).TypeCast(rawToTypeExpr, tmpVarName.makeIdent());
JCExpression toTypeExpr;
if (isCeylonBasicType(varType) && varDecl.getUnboxed() == true) {
toTypeExpr = makeJavaType(varType);
tmpVarExpr = unboxType(tmpVarExpr, varType);
} else {
toTypeExpr = makeJavaType(varType, JT_NO_PRIMITIVES);
}
// The variable holding the result for the code inside the code block
JCVariableDecl decl2 = at(isCase).VarDef(make().Modifiers(FINAL), substVarName, toTypeExpr, tmpVarExpr);
// Prepare for variable substitution in the following code block
Substitution prevSubst = naming.addVariableSubst(varDecl, substVarName.toString());
List<JCStatement> stats = List.<JCStatement>of(decl2);
stats = stats.appendList(transformCaseClause(caseClause, tmpVar, outerExpression, expectedType));
JCBlock block = at(isCase).Block(0, stats);
// Deactivate the above variable substitution
prevSubst.close();
last = make().If(cond, block, last);
return last;
}
use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement in project ceylon by eclipse.
the class StatementTransformer method transformCatchesIfElseIf.
/**
* Transforms a list of {@code CatchClause}s to a single {@code JCCatch}
* containing and if/else if chain for finding the appropriate catch block.
* @see #transformCatchesPolymorphic(java.util.List)
*/
private List<JCCatch> transformCatchesIfElseIf(java.util.List<Tree.CatchClause> catchClauses) {
Type supertype = intersectionOfCatchClauseTypes(catchClauses);
JCExpression exceptionType = makeJavaType(supertype, JT_CATCH | JT_RAW);
SyntheticName exceptionVar = naming.alias("exception");
JCVariableDecl param = make().VarDef(make().Modifiers(Flags.FINAL), exceptionVar.asName(), exceptionType, null);
ArrayList<Tree.CatchClause> reversed = new ArrayList<Tree.CatchClause>(catchClauses);
Collections.reverse(reversed);
JCStatement elsePart = make().Throw(exceptionVar.makeIdent());
for (Tree.CatchClause catchClause : reversed) {
Tree.Variable caughtVar = catchClause.getCatchVariable().getVariable();
Type caughtType = caughtVar.getType().getTypeModel();
List<JCStatement> catchBlock = transformBlock(catchClause.getBlock());
catchBlock = catchBlock.prepend(makeVar(FINAL, caughtVar.getIdentifier().getText(), makeJavaType(caughtType), expressionGen().applyErasureAndBoxing(exceptionVar.makeIdent(), supertype, true, true, BoxingStrategy.BOXED, caughtType, 0)));
elsePart = make().If(makeOptimizedTypeTest(null, exceptionVar, caughtType, supertype), make().Block(0, catchBlock), elsePart);
}
return List.of(make().Catch(param, make().Block(0, List.<JCStatement>of(elsePart))));
}
Aggregations