use of org.eclipse.ceylon.compiler.java.codegen.Operators.OptimisationStrategy in project ceylon by eclipse.
the class ExpressionTransformer method transform.
// Prefix operator
public JCExpression transform(final Tree.PrefixOperatorExpression expr) {
final OperatorTranslation operator = Operators.getOperator(expr.getClass());
if (operator == null) {
return makeErroneous(expr, "compiler bug: " + expr.getNodeType() + " is not supported yet");
}
OptimisationStrategy optimisationStrategy = operator.getUnOpOptimisationStrategy(expr, expr.getTerm(), this);
final boolean canOptimise = optimisationStrategy.useJavaOperator();
Tree.Term term = expr.getTerm();
// only fully optimise if we don't have to access the getter/setter
if (canOptimise && CodegenUtil.isDirectAccessVariable(term)) {
JCExpression jcTerm = transformExpression(term, BoxingStrategy.UNBOXED, expr.getTypeModel(), EXPR_WIDEN_PRIM);
return at(expr).Unary(operator.javacOperator, jcTerm);
}
// Interface compoundType = expr.getUnit().getOrdinalDeclaration();
// Type valueType = getSupertype(term, compoundType);
// getMostPreciseType(term, getTypeArgument(valueType, 0));
final Type returnType = term.getTypeModel();
// we work on boxed types unless we could have optimised
return transformAssignAndReturnOperation(expr, term, !canOptimise, term.getTypeModel(), returnType, new AssignAndReturnOperationFactory() {
@Override
public JCExpression getNewValue(JCExpression previousValue) {
// use +1/-1 if we can optimise a bit
if (canOptimise) {
JCExpression ret = make().Binary(operator == OperatorTranslation.UNARY_PREFIX_INCREMENT ? JCTree.Tag.PLUS : JCTree.Tag.MINUS, previousValue, makeInteger(1));
ret = unAutoPromote(ret, returnType, expr.getSmall());
return ret;
}
// make this call: previousValue.getSuccessor() or previousValue.getPredecessor()
return make().Apply(null, makeSelect(previousValue, operator.getCeylonMethodName()), List.<JCExpression>nil());
}
});
}
use of org.eclipse.ceylon.compiler.java.codegen.Operators.OptimisationStrategy in project ceylon by eclipse.
the class ExpressionTransformer method checkForBitwiseOperators.
private JCExpression checkForBitwiseOperators(Tree.Term node, Tree.QualifiedMemberExpression qme, Tree.Term right) {
// must be a call on Integer
Tree.Term left = qme.getPrimary();
if (left == null) {
return null;
}
String signature;
Type binaryType;
if (isCeylonInteger(left.getTypeModel())) {
// must be a supported method/attribute
binaryType = typeFact().getIntegerType();
String name = qme.getIdentifier().getText();
signature = "ceylon.language.Integer." + name;
} else if (isCeylonByte(left.getTypeModel())) {
binaryType = typeFact().getByteType();
String name = qme.getIdentifier().getText();
signature = "ceylon.language.Byte." + name;
} else {
return null;
}
// see if we have an operator for it
OperatorTranslation operator = Operators.getOperator(signature);
if (operator != null) {
JCExpression result;
if (operator.getArity() == 2) {
if (right == null)
return null;
OptimisationStrategy optimisationStrategy = operator.getBinOpOptimisationStrategy(node, left, right, this);
// check that we can optimise it
if (!optimisationStrategy.useJavaOperator())
return null;
JCExpression leftExpr = transformExpression(left, optimisationStrategy.getBoxingStrategy(), binaryType, EXPR_WIDEN_PRIM);
JCExpression rightExpr = transformExpression(right, optimisationStrategy.getBoxingStrategy(), binaryType, EXPR_WIDEN_PRIM);
if (operator.leftValueMask != 0) {
leftExpr = make().Binary(JCTree.Tag.BITAND, leftExpr, makeInteger(operator.leftValueMask));
}
if (operator.rightValueMask != 0) {
rightExpr = make().Binary(JCTree.Tag.BITAND, rightExpr, makeInteger(operator.rightValueMask));
}
result = make().Binary(operator.javacOperator, leftExpr, rightExpr);
} else {
// must be unary
if (right != null)
return null;
OptimisationStrategy optimisationStrategy = operator.getUnOpOptimisationStrategy(node, left, this);
// check that we can optimise it
if (!optimisationStrategy.useJavaOperator())
return null;
JCExpression leftExpr = transformExpression(left, optimisationStrategy.getBoxingStrategy(), binaryType, EXPR_WIDEN_PRIM);
if (operator.leftValueMask != 0) {
leftExpr = make().Binary(JCTree.Tag.BITAND, leftExpr, makeInteger(operator.leftValueMask));
}
result = make().Unary(operator.javacOperator, leftExpr);
}
if (isCeylonByte(binaryType)) {
result = make().TypeCast(syms().byteType, result);
}
return result;
}
return null;
}
use of org.eclipse.ceylon.compiler.java.codegen.Operators.OptimisationStrategy in project ceylon by eclipse.
the class ExpressionTransformer method transform.
// Postfix operator
public JCExpression transform(Tree.PostfixOperatorExpression expr) {
OperatorTranslation operator = Operators.getOperator(expr.getClass());
if (operator == null) {
return makeErroneous(expr, "compiler bug " + expr.getNodeType() + " is not yet supported");
}
OptimisationStrategy optimisationStrategy = operator.getUnOpOptimisationStrategy(expr, expr.getTerm(), this);
boolean canOptimise = optimisationStrategy.useJavaOperator();
// only fully optimise if we don't have to access the getter/setter
if (canOptimise && CodegenUtil.isDirectAccessVariable(expr.getTerm())) {
JCExpression term = transformExpression(expr.getTerm(), BoxingStrategy.UNBOXED, expr.getTypeModel(), EXPR_WIDEN_PRIM);
return at(expr).Unary(operator.javacOperator, term);
}
Tree.Term term = unwrapExpressionUntilTerm(expr.getTerm());
Type returnType = term.getTypeModel();
List<JCVariableDecl> decls = List.nil();
List<JCStatement> stats = List.nil();
JCExpression result = null;
// we can optimise that case a bit sometimes
boolean boxResult = !canOptimise;
// (let $tmp = attr; attr = $tmp.getSuccessor(); $tmp;)
if (term instanceof Tree.BaseMemberExpression || // special case for java statics Foo.attr where Foo does not need to be evaluated
(term instanceof Tree.QualifiedMemberExpression && ((Tree.QualifiedMemberExpression) term).getStaticMethodReference())) {
JCExpression getter;
if (term instanceof Tree.BaseMemberExpression)
getter = transform((Tree.BaseMemberExpression) term, null);
else
getter = transformMemberExpression((Tree.QualifiedMemberExpression) term, null, null);
at(expr);
// Type $tmp = attr
JCExpression exprType = makeJavaType(returnType, boxResult ? JT_NO_PRIMITIVES : 0);
Name varName = naming.tempName("op");
// make sure we box the results if necessary
getter = applyErasureAndBoxing(getter, term, boxResult ? BoxingStrategy.BOXED : BoxingStrategy.UNBOXED, returnType);
JCVariableDecl tmpVar = make().VarDef(make().Modifiers(0), varName, exprType, getter);
decls = decls.prepend(tmpVar);
// attr = $tmp.getSuccessor()
JCExpression successor;
if (canOptimise) {
// use +1/-1 if we can optimise a bit
successor = make().Binary(operator == OperatorTranslation.UNARY_POSTFIX_INCREMENT ? JCTree.Tag.PLUS : JCTree.Tag.MINUS, make().Ident(varName), makeInteger(1));
successor = unAutoPromote(successor, returnType, expr.getSmall());
} else {
successor = make().Apply(null, makeSelect(make().Ident(varName), operator.getCeylonMethodName()), List.<JCExpression>nil());
// make sure the result is boxed if necessary, the result of successor/predecessor is always boxed
successor = boxUnboxIfNecessary(successor, true, term.getTypeModel(), CodegenUtil.getBoxingStrategy(term));
}
JCExpression assignment = makeAssignment(expr, term, transformAssignmentLhs(expr, term), successor);
stats = stats.prepend(at(expr).Exec(assignment));
// $tmp
result = make().Ident(varName);
} else if (term instanceof Tree.QualifiedMemberExpression) {
// e.attr++
// (let $tmpE = e, $tmpV = $tmpE.attr; $tmpE.attr = $tmpV.getSuccessor(); $tmpV;)
Tree.QualifiedMemberExpression qualified = (Tree.QualifiedMemberExpression) term;
boolean isSuper = isSuperOrSuperOf(qualified.getPrimary());
boolean isPackage = isPackageQualified(qualified);
// transform the primary, this will get us a boxed primary
JCExpression e = transformQualifiedMemberPrimary(qualified);
at(expr);
// Type $tmpE = e
JCExpression exprType = makeJavaType(qualified.getTarget().getQualifyingType(), JT_NO_PRIMITIVES);
Name varEName = naming.tempName("opE");
JCVariableDecl tmpEVar = make().VarDef(make().Modifiers(0), varEName, exprType, e);
// Type $tmpV = $tmpE.attr
JCExpression attrType = makeJavaType(returnType, boxResult ? JT_NO_PRIMITIVES : 0);
Name varVName = naming.tempName("opV");
JCExpression getter;
if (isSuper) {
getter = transformMemberExpression(qualified, transformSuper(qualified), null);
} else if (isPackage) {
getter = transformMemberExpression(qualified, null, null);
} else {
getter = transformMemberExpression(qualified, make().Ident(varEName), null);
}
// make sure we box the results if necessary
getter = applyErasureAndBoxing(getter, term, boxResult ? BoxingStrategy.BOXED : BoxingStrategy.UNBOXED, returnType);
JCVariableDecl tmpVVar = make().VarDef(make().Modifiers(0), varVName, attrType, getter);
decls = decls.prepend(tmpVVar);
if (!isSuper && !isPackage) {
// define all the variables
decls = decls.prepend(tmpEVar);
}
// $tmpE.attr = $tmpV.getSuccessor()
JCExpression successor;
if (canOptimise) {
// use +1/-1 if we can optimise a bit
successor = make().Binary(operator == OperatorTranslation.UNARY_POSTFIX_INCREMENT ? JCTree.Tag.PLUS : JCTree.Tag.MINUS, make().Ident(varVName), makeInteger(1));
successor = unAutoPromote(successor, returnType, expr.getSmall());
} else {
successor = make().Apply(null, makeSelect(make().Ident(varVName), operator.getCeylonMethodName()), List.<JCExpression>nil());
// make sure the result is boxed if necessary, the result of successor/predecessor is always boxed
successor = boxUnboxIfNecessary(successor, true, term.getTypeModel(), CodegenUtil.getBoxingStrategy(term));
}
JCExpression assignment = makeAssignment(expr, term, qualifyLhs(expr, term, isSuper ? transformSuper(qualified) : make().Ident(varEName)), successor);
stats = stats.prepend(at(expr).Exec(assignment));
// $tmpV
result = make().Ident(varVName);
} else {
return makeErroneous(term, "compiler bug: " + term.getNodeType() + " is not supported yet");
}
return make().LetExpr(decls, stats, result);
}
use of org.eclipse.ceylon.compiler.java.codegen.Operators.OptimisationStrategy in project ceylon by eclipse.
the class ExpressionTransformer method transform.
// Comparison operators
public JCExpression transform(Tree.IdenticalOp op) {
// The only thing which might be unboxed is boolean, and we can follow the rules of == for optimising it,
// which are simple and require that both types be booleans to be unboxed, otherwise they must be boxed
OptimisationStrategy optimisationStrategy = OperatorTranslation.BINARY_EQUAL.getBinOpOptimisationStrategy(op, op.getLeftTerm(), op.getRightTerm(), this);
JCExpression left = transformExpression(op.getLeftTerm(), optimisationStrategy.getBoxingStrategy(), null);
JCExpression right = transformExpression(op.getRightTerm(), optimisationStrategy.getBoxingStrategy(), null);
return at(op).Binary(JCTree.Tag.EQ, left, right);
}
use of org.eclipse.ceylon.compiler.java.codegen.Operators.OptimisationStrategy in project ceylon by eclipse.
the class ExpressionTransformer method transformOverridableBinaryOperator.
protected BinOpTransformation transformOverridableBinaryOperator(Tree.BinaryOperatorExpression op, OperatorTranslation operator, Type leftType, Type rightType) {
OptimisationStrategy optimisationStrategy = operator.getBinOpOptimisationStrategy(op, op.getLeftTerm(), leftType, op.getRightTerm(), rightType, this);
at(op);
JCExpression left = transformExpression(op.getLeftTerm(), optimisationStrategy.getBoxingStrategy(), leftType, EXPR_WIDEN_PRIM);
JCExpression right = transformExpression(op.getRightTerm(), optimisationStrategy.getBoxingStrategy(), rightType, EXPR_WIDEN_PRIM);
return transformOverridableBinaryOperator(op, operator, optimisationStrategy, left, right, op.getLeftTerm(), op.getRightTerm(), op.getTypeModel());
}
Aggregations