use of com.redhat.ceylon.compiler.java.codegen.Naming.SyntheticName in project ceylon-compiler by ceylon.
the class ClassTransformer method serializationReferences.
/**
* <p>Generates the {@code $deserialize$()} method to deserialize
* the classes state, which:</p>
* <ul>
* <li>invokes {@code super.$deserialize$()}, if the super class is also
* serializable,</li>
* <li>assigns each reified type argument in the
* class by invoking {@code dted.getTypeArgument()},</li>
* <li>assigns each field in the
* class by invoking {@code dted.getValue()}.</li>
* </ul>
*/
private void serializationReferences(Class model, ClassDefinitionBuilder classBuilder) {
MethodDefinitionBuilder mdb = MethodDefinitionBuilder.systemMethod(this, Unfix.$references$.toString());
mdb.isOverride(true);
mdb.ignoreModelAnnotations();
mdb.modifiers(PUBLIC);
mdb.resultType(null, make().TypeApply(naming.makeQuotedFQIdent("java.util.Collection"), List.<JCExpression>of(make().Type(syms().ceylonReachableReferenceType))));
ListBuffer<JCStatement> stmts = ListBuffer.lb();
// TODO this is all static information, but the method itself needs to be
// callable virtually, so we should cache it somehow.
SyntheticName r = naming.synthetic(Unfix.reference);
if (extendsSerializable(model)) {
// prepend the invocation of super.$serialize$()
stmts.add(makeVar(r, make().TypeApply(naming.makeQuotedFQIdent("java.util.Collection"), List.<JCExpression>of(make().Type(syms().ceylonReachableReferenceType))), make().Apply(null, naming.makeQualIdent(naming.makeSuper(), Unfix.$references$.toString()), List.<JCExpression>nil())));
} else {
stmts.add(makeVar(r, make().TypeApply(naming.makeQuotedFQIdent("java.util.Collection"), List.<JCExpression>of(make().Type(syms().ceylonReachableReferenceType))), make().NewClass(null, null, make().TypeApply(naming.makeQuotedFQIdent("java.util.ArrayList"), List.<JCExpression>of(make().Type(syms().ceylonReachableReferenceType))), List.<JCExpression>nil(), null)));
}
if (model.isMember()) {
JCExpressionStatement outer = make().Exec(make().Apply(null, naming.makeQualIdent(r.makeIdent(), "add"), List.<JCExpression>of(make().Apply(null, naming.makeQualIdent(make().Type(syms().ceylonOuterImplType), "get_"), List.<JCExpression>nil()))));
stmts.add(outer);
}
for (Declaration member : model.getMembers()) {
if (hasField(member)) {
// Obtain a ValueDeclaration
JCExpression valueDeclaration = expressionGen().makeMemberValueOrFunctionDeclarationLiteral(null, member, false);
// Create a MemberImpl
JCExpression mi = make().NewClass(null, null, make().QualIdent(syms().ceylonMemberImplType.tsym), List.of(valueDeclaration), null);
JCExpressionStatement attribute = make().Exec(make().Apply(null, naming.makeQualIdent(r.makeIdent(), "add"), List.of(mi)));
stmts.add(attribute);
}
}
stmts.add(make().Return(r.makeIdent()));
mdb.body(stmts.toList());
classBuilder.method(mdb);
}
use of com.redhat.ceylon.compiler.java.codegen.Naming.SyntheticName in project ceylon-compiler by ceylon.
the class ExpressionTransformer method makeOptimizedInCharacterRange.
protected JCTree makeOptimizedInCharacterRange(Tree.InOp op) {
com.sun.tools.javac.code.Type type = syms().intType;
com.sun.tools.javac.code.Type ceylonType = syms().ceylonCharacterType;
// x in y..z with x, y, z all Character
Tree.RangeOp rangeOp = (Tree.RangeOp) op.getRightTerm();
JCExpression x = transformExpression(op.getLeftTerm(), BoxingStrategy.UNBOXED, typeFact().getObjectType());
JCExpression first = transformExpression(rangeOp.getLeftTerm(), BoxingStrategy.UNBOXED, rangeOp.getLeftTerm().getTypeModel());
JCExpression last = transformExpression(rangeOp.getRightTerm(), BoxingStrategy.UNBOXED, rangeOp.getRightTerm().getTypeModel());
SyntheticName xName = naming.temp("x");
SyntheticName firstName = naming.temp("first");
SyntheticName lastName = naming.temp("last");
SyntheticName recursiveName = naming.temp("recursive");
return make().LetExpr(List.<JCStatement>of(makeVar(xName, make().Type(type), x), makeVar(firstName, make().Type(type), first), makeVar(lastName, make().Type(type), last), // so we have to replicate that **short-circuit** logic here
makeVar(recursiveName, make().Type(syms().booleanType), make().Binary(JCTree.AND, make().Binary(JCTree.GT, firstName.makeIdent(), make().Apply(null, naming.makeSelect(make().QualIdent(ceylonType.tsym), "getSuccessor"), List.<JCExpression>of(firstName.makeIdent()))), make().Binary(JCTree.GT, make().Apply(null, naming.makeSelect(make().QualIdent(ceylonType.tsym), "getPredecessor"), List.<JCExpression>of(lastName.makeIdent())), lastName.makeIdent())))), make().Conditional(make().Binary(JCTree.LT, firstName.makeIdent(), lastName.makeIdent()), make().Binary(JCTree.AND, make().Binary(JCTree.LE, xName.makeIdent(), lastName.makeIdent()), make().Binary(JCTree.GE, xName.makeIdent(), firstName.makeIdent())), make().Binary(JCTree.AND, make().Binary(JCTree.GE, xName.makeIdent(), lastName.makeIdent()), make().Binary(JCTree.LE, xName.makeIdent(), firstName.makeIdent()))));
}
use of com.redhat.ceylon.compiler.java.codegen.Naming.SyntheticName in project ceylon-compiler by ceylon.
the class ExpressionTransformer method transform.
public JCExpression transform(Tree.WithinOp op) {
Tree.Term middleTerm = op.getTerm();
Tree.Bound lowerBound = op.getLowerBound();
OperatorTranslation lowerOp = Operators.getOperator(lowerBound instanceof Tree.OpenBound ? Tree.SmallerOp.class : Tree.SmallAsOp.class);
Tree.Term lowerTerm = lowerBound.getTerm();
Tree.Bound upperBound = op.getUpperBound();
OperatorTranslation upperOp = Operators.getOperator(upperBound instanceof Tree.OpenBound ? Tree.SmallerOp.class : Tree.SmallAsOp.class);
Tree.Term upperTerm = upperBound.getTerm();
Type middleType = getComparableType(middleTerm);
Type lowerType = getComparableType(lowerTerm);
Type upperType = getComparableType(upperTerm);
// If any of the terms is optimizable, then use optimized
OptimisationStrategy opt;
boolean optimizeLower = lowerOp.isTermOptimisable(lowerTerm, lowerType, this) == OptimisationStrategy.OPTIMISE || lowerOp.isTermOptimisable(middleTerm, middleType, this) == OptimisationStrategy.OPTIMISE;
boolean optimizeUpper = upperOp.isTermOptimisable(middleTerm, middleType, this) == OptimisationStrategy.OPTIMISE || upperOp.isTermOptimisable(upperTerm, upperType, this) == OptimisationStrategy.OPTIMISE;
if ((lowerType.isExactly(middleType) && middleType.isExactly(upperType) && (optimizeLower || // if all same type and any optimizable
optimizeUpper)) || (// otherwise onle if all optimizable
optimizeLower && optimizeUpper)) {
opt = OptimisationStrategy.OPTIMISE;
} else {
opt = OptimisationStrategy.NONE;
}
SyntheticName middleName = naming.alias("middle");
List<JCStatement> vars = List.<JCStatement>of(makeVar(middleName, makeJavaType(middleType, opt.getBoxingStrategy() == BoxingStrategy.UNBOXED ? 0 : JT_NO_PRIMITIVES), transformExpression(middleTerm, opt.getBoxingStrategy(), middleType)));
JCExpression lower = transformBound(middleName, middleType, lowerType, lowerOp, opt, middleTerm, lowerBound, false);
JCExpression upper = transformBound(middleName, middleType, upperType, upperOp, opt, middleTerm, upperBound, true);
at(op);
OperatorTranslation andOp = Operators.getOperator(Tree.AndOp.class);
OptimisationStrategy optimisationStrategy = OptimisationStrategy.OPTIMISE;
return make().LetExpr(vars, transformOverridableBinaryOperator(andOp, optimisationStrategy, lower, upper, null, null, op.getTypeModel()));
}
use of com.redhat.ceylon.compiler.java.codegen.Naming.SyntheticName 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.redhat.ceylon.compiler.java.codegen.Naming.SyntheticName in project ceylon-compiler by ceylon.
the class StatementTransformer method transform.
public JCTree transform(CustomTree.GuardedVariable that) {
BoxingStrategy boxingStrategy = CodegenUtil.getBoxingStrategy(that.getDeclarationModel());
Tree.Expression expr = that.getSpecifierExpression().getExpression();
Type fromType = expr.getTypeModel();
Value newValue = that.getDeclarationModel();
Type toType = newValue.getType();
Tree.ConditionList conditionList = that.getConditionList();
Tree.Condition condition = conditionList.getConditions().get(0);
JCExpression val = expressionGen().transformExpression(expr);
at(that);
if (condition instanceof Tree.IsCondition) {
if (!willEraseToObject(toType)) {
// Want raw type for instanceof since it can't be used with generic types
JCExpression rawToTypeExpr = makeJavaType(toType, JT_NO_PRIMITIVES | JT_RAW);
// Substitute variable with the correct type to use in the rest of the code block
val = make().TypeCast(rawToTypeExpr, val);
if (CodegenUtil.isUnBoxed(newValue) && canUnbox(toType)) {
val = unboxType(val, toType);
}
}
} else if (condition instanceof Tree.ExistsCondition) {
Type exprType = fromType;
if (isOptional(exprType)) {
exprType = typeFact().getDefiniteType(exprType);
}
val = expressionGen().applyErasureAndBoxing(val, exprType, CodegenUtil.hasTypeErased(expr), true, CodegenUtil.hasUntrustedType(expr), boxingStrategy, toType, 0);
} else if (condition instanceof Tree.NonemptyCondition) {
Type exprType = fromType;
if (isOptional(exprType)) {
exprType = typeFact().getDefiniteType(exprType);
}
val = expressionGen().applyErasureAndBoxing(val, exprType, false, true, BoxingStrategy.BOXED, toType, ExpressionTransformer.EXPR_DOWN_CAST);
}
SyntheticName alias = naming.alias(that.getIdentifier().getText());
Substitution subst = naming.addVariableSubst(newValue, alias.getName());
// FIXME: this is rubbish, but the same rubbish from assert. it's most likely wrong there too
Scope scope = that.getScope().getScope();
while (scope instanceof ConditionScope) {
scope = scope.getScope();
}
subst.scopeClose(scope);
JCExpression varType = makeJavaType(toType);
return make().VarDef(make().Modifiers(FINAL), alias.asName(), varType, val);
}
Aggregations