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.IfExpression that) {
super.visit(that);
if (that.getIfClause() == null || that.getElseClause() == null)
return;
Tree.Expression ifExpr = that.getIfClause().getExpression();
Tree.Expression elseExpr = that.getElseClause().getExpression();
if (ifExpr == null || elseExpr == null)
return;
if (CodegenUtil.isUnBoxed(ifExpr) && CodegenUtil.isUnBoxed(elseExpr) && !willEraseToObject(that.getUnit().denotableType(that.getTypeModel())))
CodegenUtil.markUnBoxed(that);
if (that.getTypeModel().isExactly(that.getUnit().getNullValueType())) {
CodegenUtil.markTypeErased(that);
}
// An If 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.
}
use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression in project ceylon by eclipse.
the class StatementTransformer method spanOpIteration.
/**
* Returns a {@link SpanOpIterationOptimization} if that optimization applies
* to the given {@code for} statement, otherwise null.
* @param stmt The for statement
* @return a {@link SpanOpIterationOptimization} or null.
*/
private ForStatementTransformation spanOpIteration(Tree.ForStatement stmt) {
if (isOptimizationDisabled(stmt, Optimization.SpanOpIteration)) {
return optimizationFailed(stmt, Optimization.SpanOpIteration, "optimization explicitly disabled by @disableOptimization");
}
Tree.ForIterator iterator = stmt.getForClause().getForIterator();
if (!(iterator instanceof Tree.ValueIterator)) {
return optimizationFailed(stmt, Optimization.SpanOpIteration, "optimization applies only to ValueIterators");
}
Tree.ValueIterator vi = (Tree.ValueIterator) iterator;
Tree.SpecifierExpression specifier = vi.getSpecifierExpression();
Tree.Term term = specifier.getExpression().getTerm();
final Tree.Term increment;
final Tree.RangeOp range;
if (term instanceof Tree.RangeOp) {
// So it's a for (i in (lhs..rhs)) { ... }
increment = null;
range = (Tree.RangeOp) term;
} else if (term instanceof Tree.InvocationExpression) {
Tree.InvocationExpression inv = (Tree.InvocationExpression) term;
if (inv.getPrimary() instanceof Tree.QualifiedMemberExpression) {
Tree.QualifiedMemberExpression prim = (Tree.QualifiedMemberExpression) inv.getPrimary();
if ("by".equals(prim.getIdentifier().getText()) && prim.getPrimary() instanceof Tree.Expression && (((Tree.Expression) (prim.getPrimary())).getTerm() instanceof Tree.RangeOp)) {
// So it's a for (i in (lhs..rhs).by(increment)) { ... }
range = (Tree.RangeOp) ((Tree.Expression) (prim.getPrimary())).getTerm();
if (inv.getPositionalArgumentList() != null) {
Tree.PositionalArgument a = inv.getPositionalArgumentList().getPositionalArguments().get(0);
if (a instanceof Tree.ListedArgument)
increment = ((Tree.ListedArgument) a).getExpression().getTerm();
else
return optimizationFailed(stmt, Optimization.SpanOpIteration, "Unable to determine expression for argument to by(): appears spread or comprehension");
} else if (inv.getNamedArgumentList() != null) {
Tree.SpecifiedArgument sarg = null;
for (Tree.NamedArgument arg : inv.getNamedArgumentList().getNamedArguments()) {
if ("step".equals(arg.getIdentifier().getText())) {
if (arg instanceof Tree.SpecifiedArgument) {
sarg = ((Tree.SpecifiedArgument) arg);
break;
}
// TODO In theory we could support Tree.AttributeArgument too
}
}
if (sarg != null) {
increment = sarg.getSpecifierExpression().getExpression().getTerm();
} else {
return optimizationFailed(stmt, Optimization.SpanOpIteration, "Unable to determine expression for argument to by{}");
}
} else {
return optimizationFailed(stmt, Optimization.SpanOpIteration, "Unable to get arguments to by()");
}
} else {
return optimizationFailed(stmt, Optimization.SpanOpIteration, "Only applies to Iterables of the form 'lhs..rhs' or '(lhs..rhs).by(step)'");
}
} else {
return optimizationFailed(stmt, Optimization.SpanOpIteration, "Only applies to Iterables of the form 'lhs..rhs' or '(lhs..rhs).by(step)'");
}
} else {
return optimizationFailed(stmt, Optimization.SpanOpIteration, "Only applies to Iterables of the form 'lhs..rhs' or '(lhs..rhs).by(step)'");
}
if (!isSpanOf(range, typeFact().getCharacterType()) && !isSpanOf(range, typeFact().getIntegerType())) {
return optimizationFailed(stmt, Optimization.SpanOpIteration, "The RangeOp doesn't produce a Range<Integer>/Range<Character>");
}
return increment == null ? new SpanOpIterationOptimization(stmt, range, increment) : new SpanOpWithStepIterationOptimization(stmt, range, increment);
}
use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression in project ceylon by eclipse.
the class StatementTransformer method transform.
/**
* Transforms a Ceylon destructuring assignment to Java code.
* @param stmt The Ceylon destructure
* @return The Java tree
*/
List<JCStatement> transform(Tree.Destructure stmt) {
List<JCStatement> result = List.nil();
// Create temp var to hold result of expression
Tree.Pattern pat = stmt.getPattern();
Naming.SyntheticName tmpVarName = naming.synthetic(pat);
Expression destExpr = stmt.getSpecifierExpression().getExpression();
JCExpression typeExpr = makeJavaType(destExpr.getTypeModel());
JCExpression expr = expressionGen().transformExpression(destExpr);
at(stmt);
JCVariableDecl tmpVar = makeVar(Flags.FINAL, tmpVarName, typeExpr, expr);
result = result.append(tmpVar);
// Now add the destructured variables
List<VarDefBuilder> destructured = transformPattern(pat, tmpVarName.makeIdent());
for (VarDefBuilder vdb : destructured) {
Value v = vdb.var.getDeclarationModel();
at(vdb.var);
if (v.isClassMember() && v.isCaptured()) {
AttributeDefinitionBuilder adb = AttributeDefinitionBuilder.getter(this, v.getName(), v);
adb.immutable();
classGen().current().attribute(adb);
classGen().current().defs(vdb.buildDefOnly());
result = result.append(make().Exec(make().Assign(vdb.name().makeIdentWithThis(), vdb.expr())));
} else {
result = result.append(vdb.build());
}
}
return result;
}
use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression in project ceylon by eclipse.
the class StatementTransformer method transform.
JCStatement transform(Node node, Tree.SwitchClause switchClause, Tree.SwitchCaseList caseList, String tmpVar, Tree.Term outerExpression, Type expectedType) {
at(switchClause);
block();
SwitchTransformation transformation = null;
Type exprType = switchExpressionType(switchClause);
Boolean switchUnboxed = switchExpressionUnboxed(switchClause);
// Are we switching with just String literal or Character literal match cases?
if (isJavaSwitchableType(exprType, switchUnboxed)) {
boolean canUseSwitch = true;
caseStmts: for (Tree.CaseClause clause : caseList.getCaseClauses()) {
if (clause.getCaseItem() instanceof Tree.MatchCase) {
Tree.MatchList matchList = ((Tree.MatchCase) clause.getCaseItem()).getExpressionList();
if (!matchList.getTypes().isEmpty()) {
canUseSwitch = false;
break caseStmts;
}
java.util.List<Expression> caseExprs = matchList.getExpressions();
caseExpr: for (Tree.Expression expr : caseExprs) {
Tree.Term e = ExpressionTransformer.eliminateParens(expr);
if (e instanceof Tree.StringLiteral || e instanceof Tree.CharLiteral) {
continue caseExpr;
} else if (e instanceof Tree.BaseMemberExpression && ((Tree.BaseMemberExpression) e).getDeclaration() instanceof Value && ((Value) ((Tree.BaseMemberExpression) e).getDeclaration()).isEnumValue()) {
continue caseExpr;
} else {
canUseSwitch = false;
break caseStmts;
}
}
} else {
canUseSwitch = false;
break caseStmts;
}
}
if (canUseSwitch) {
// yes, so use a Java Switch
transformation = new Switch();
}
}
if (transformation == null && isOptional(exprType)) {
// Are we switching with just String literal or Character literal plus null
// match cases?
Type definiteType = typeFact().getDefiniteType(exprType);
if (isJavaSwitchableType(definiteType, switchUnboxed)) {
boolean canUseIfElseSwitch = true;
boolean hasSingletonNullCase = false;
caseStmts: for (Tree.CaseClause clause : caseList.getCaseClauses()) {
if (clause.getCaseItem() instanceof Tree.MatchCase) {
if (getSingletonNullCase(clause) != null) {
hasSingletonNullCase = true;
}
Tree.MatchList matchList = ((Tree.MatchCase) clause.getCaseItem()).getExpressionList();
if (!matchList.getTypes().isEmpty()) {
canUseIfElseSwitch = false;
break caseStmts;
}
java.util.List<Expression> caseExprs = matchList.getExpressions();
caseExpr: for (Tree.Expression expr : caseExprs) {
Tree.Term e = ExpressionTransformer.eliminateParens(expr);
if (e instanceof Tree.StringLiteral || e instanceof Tree.CharLiteral) {
continue caseExpr;
} else if (e instanceof Tree.BaseMemberExpression && isNullValue(((Tree.BaseMemberExpression) e).getDeclaration()) && caseExprs.size() == 1) {
continue caseExpr;
} else if (e instanceof Tree.BaseMemberExpression && ((Tree.BaseMemberExpression) e).getDeclaration() instanceof Value && ((Value) ((Tree.BaseMemberExpression) e).getDeclaration()).isEnumValue()) {
continue caseExpr;
} else {
canUseIfElseSwitch = false;
break caseStmts;
}
}
} else {
canUseIfElseSwitch = false;
break caseStmts;
}
}
canUseIfElseSwitch &= hasSingletonNullCase;
if (canUseIfElseSwitch) {
// yes, so use a If
transformation = new IfNullElseSwitch();
}
}
}
// The default transformation
if (transformation == null) {
transformation = new IfElseChain();
}
JCStatement result = transformation.transformSwitch(node, switchClause, caseList, tmpVar, outerExpression, expectedType);
unblock();
return result;
}
use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression in project ceylon by eclipse.
the class NamedArgumentInvocation method bindMethodArgument.
private void bindMethodArgument(Tree.MethodArgument methodArg, Parameter declaredParam, Naming.SyntheticName argName) {
ListBuffer<JCStatement> statements;
Function model = methodArg.getDeclarationModel();
List<JCStatement> body;
boolean prevNoExpressionlessReturn = gen.statementGen().noExpressionlessReturn;
boolean prevSyntheticClassBody = gen.expressionGen().withinSyntheticClassBody(Decl.isMpl(model) || gen.expressionGen().isWithinSyntheticClassBody());
try {
gen.expressionGen().withinSyntheticClassBody(true);
gen.statementGen().noExpressionlessReturn = AbstractTransformer.isAnything(model.getType());
if (methodArg.getBlock() != null) {
body = gen.statementGen().transformBlock(methodArg.getBlock());
if (!methodArg.getBlock().getDefinitelyReturns()) {
if (AbstractTransformer.isAnything(model.getType())) {
body = body.append(gen.make().Return(gen.makeNull()));
} else {
body = body.append(gen.make().Return(gen.makeErroneous(methodArg.getBlock(), "compiler bug: non-void method does not definitely return")));
}
}
} else {
Expression expr = methodArg.getSpecifierExpression().getExpression();
BoxingStrategy boxing = CodegenUtil.getBoxingStrategy(model);
Type type = model.getType();
JCExpression transExpr = gen.expressionGen().transformExpression(expr, boxing, type);
JCReturn returnStat = gen.make().Return(transExpr);
body = List.<JCStatement>of(returnStat);
}
} finally {
gen.expressionGen().withinSyntheticClassBody(prevSyntheticClassBody);
gen.statementGen().noExpressionlessReturn = prevNoExpressionlessReturn;
}
Type callableType = model.appliedReference(null, Collections.<Type>emptyList()).getFullType();
CallableBuilder callableBuilder = CallableBuilder.methodArgument(gen.gen(), methodArg, model, callableType, Collections.singletonList(methodArg.getParameterLists().get(0)), gen.classGen().transformMplBody(methodArg.getParameterLists(), model, body));
JCExpression callable = callableBuilder.build();
gen.at(methodArg);
JCExpression typeExpr = gen.makeJavaType(callableType, JT_RAW);
JCVariableDecl varDecl = gen.makeVar(argName, typeExpr, callable);
statements = ListBuffer.<JCStatement>of(varDecl);
bind(declaredParam, argName, gen.makeJavaType(callableType), statements.toList());
}
Aggregations