use of org.eclipse.ceylon.model.typechecker.model.Value 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.model.typechecker.model.Value in project ceylon by eclipse.
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, newValue.hasUncheckedNullType() ? ExpressionTransformer.EXPR_TARGET_ACCEPTS_NULL : 0);
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);
}
use of org.eclipse.ceylon.model.typechecker.model.Value in project ceylon by eclipse.
the class CeylonVisitor method transformSingletonConstructor.
protected void transformSingletonConstructor(HashMap<Constructor, CtorDelegation> delegates, Tree.Enumerated ctor) {
// generate a constructor
transformConstructor(ctor, // ctor.getParameterList(),
null, ctor.getDelegatedConstructor(), ctor.getBlock(), ctor.getEnumerated(), delegates);
Class clz = ModelUtil.getConstructedClass(ctor.getEnumerated());
Value singletonModel = ctor.getDeclarationModel();
// generate a field
AttributeDefinitionBuilder adb = AttributeDefinitionBuilder.singleton(gen, singletonModel.getName(), singletonModel, false);
adb.modelAnnotations(gen.makeAtEnumerated());
adb.modelAnnotations(gen.makeAtIgnore());
adb.userAnnotations(gen.expressionGen().transformAnnotations(OutputElement.GETTER, ctor));
adb.fieldAnnotations(gen.expressionGen().transformAnnotations(OutputElement.FIELD, ctor));
// not setter
adb.immutable();
SyntheticName field = gen.naming.getValueConstructorFieldName(singletonModel);
if (clz.isToplevel()) {
adb.modifiers((singletonModel.isShared() ? PUBLIC : PRIVATE) | STATIC | FINAL);
adb.initialValue(gen.make().NewClass(null, null, gen.naming.makeTypeDeclarationExpression(null, ModelUtil.getConstructedClass(ctor.getEnumerated())), List.<JCExpression>of(gen.make().TypeCast(gen.naming.makeNamedConstructorType(ctor.getEnumerated(), false), gen.makeNull())), null), BoxingStrategy.BOXED);
classBuilder.defs(adb.build());
} else if (clz.isClassMember()) {
int mods = 0;
if (!singletonModel.isShared()) {
mods |= PRIVATE;
}
if (clz.isClassOrInterfaceMember() && clz.isStatic()) {
mods |= STATIC;
}
adb.modifiers(mods);
// lazy
adb.initialValue(gen.makeNull(), BoxingStrategy.BOXED);
List<JCStatement> l = List.<JCStatement>of(gen.make().If(gen.make().Binary(JCTree.Tag.EQ, field.makeIdent(), gen.makeNull()), gen.make().Exec(gen.make().Assign(field.makeIdent(), gen.make().NewClass(null, null, gen.naming.makeTypeDeclarationExpression(null, ModelUtil.getConstructedClass(ctor.getEnumerated())), List.<JCExpression>of(gen.make().TypeCast(gen.naming.makeNamedConstructorType(ctor.getEnumerated(), false), gen.makeNull())), null))), null), gen.make().Return(field.makeIdent()));
adb.getterBlock(gen.make().Block(0, l));
long mods2 = PRIVATE | TRANSIENT;
if (clz.isStatic()) {
mods2 |= STATIC;
}
classBuilder.getContainingClassBuilder().defs(gen.makeVar(mods2, field, gen.naming.makeTypeDeclarationExpression(null, ModelUtil.getConstructedClass(ctor.getEnumerated())), gen.makeNull()));
classBuilder.getContainingClassBuilder().defs(adb.build());
} else {
// LOCAL
// we have to first make an empty box
JCNewClass initialValue = gen.make().NewClass(null, null, gen.naming.makeTypeDeclarationExpression(null, ModelUtil.getConstructedClass(ctor.getEnumerated())), List.<JCExpression>of(gen.make().TypeCast(gen.naming.makeNamedConstructorType(ctor.getEnumerated(), false), gen.makeNull())), null);
JCVariableDecl box = gen.makeVariableBoxDecl(gen.makeNull(), singletonModel);
classBuilder.before(box);
// then do the class, and after that, assign our instance to the box
JCAssign assign = gen.make().Assign(gen.makeSelect(field.getName(), NamingBase.getGetterName(singletonModel)), initialValue);
classBuilder.after(gen.make().Exec(assign));
}
}
use of org.eclipse.ceylon.model.typechecker.model.Value in project ceylon by eclipse.
the class MethodDefinitionBuilder method getNonWideningParam.
public NonWideningParam getNonWideningParam(TypedReference typedRef, WideningRules wideningRules) {
TypedDeclaration nonWideningDecl = null;
int flags = 0;
long modifiers = 0;
Type nonWideningType;
FunctionOrValue mov = (FunctionOrValue) typedRef.getDeclaration();
if (Decl.isValue(mov)) {
TypedReference nonWideningTypedRef = gen.nonWideningTypeDecl(typedRef);
nonWideningType = gen.nonWideningType(typedRef, nonWideningTypedRef).resolveAliases();
nonWideningDecl = nonWideningTypedRef.getDeclaration();
} else {
// Stef: So here's the thing. I know this is wrong for Function where we should do getFullType(), BUT
// lots of methods call this and then feed the output into AT.makeJavaType(TypedDeclaration typeDecl, Type type, int flags)
// which adds the Callable type, so if we fix it here we have to remove it from there and there's lots of callers of that
// function which rely on its behaviour and frankly I've had enough of this refactoring, so a few callers of this function
// have to add the Callable back. It sucks, yeah, but so far it works, which is amazing enough that I don't want to touch it
// any more. More ambitious/courageous people are welcome to fix this properly.
nonWideningType = typedRef.getType().resolveAliases();
nonWideningDecl = mov;
}
if (!CodegenUtil.isUnBoxed(nonWideningDecl))
flags |= AbstractTransformer.JT_NO_PRIMITIVES;
// make sure we don't accidentally narrow value parameters that would be erased in the topmost declaration
if (wideningRules != WideningRules.NONE && mov instanceof Value) {
TypedDeclaration refinedParameter = (TypedDeclaration) CodegenUtil.getTopmostRefinedDeclaration(mov);
if (refinedParameter != null && refinedParameter instanceof Value && ((Value) refinedParameter).getInitializerParameter() != null && gen.isJavaVariadic(((Value) refinedParameter).getInitializerParameter())) {
modifiers |= Flags.VARARGS;
}
// mixin bridge methods have the same rules as when refining stuff except they are their own refined decl
if (wideningRules == WideningRules.FOR_MIXIN || !Decl.equal(refinedParameter, mov)) {
Type refinedParameterType;
// in the refined parameter type
if (refinedParameter instanceof Function)
refinedParameterType = refinedParameter.appliedTypedReference(null, Collections.<Type>emptyList()).getFullType();
else
refinedParameterType = refinedParameter.getType();
// if the supertype method itself got erased to Object, we can't do better than this
if (gen.willEraseToObject(refinedParameterType) && !gen.willEraseToBestBounds(mov))
nonWideningType = gen.typeFact().getObjectType();
else if (CodegenUtil.isRaw(refinedParameter)) {
flags |= AbstractTransformer.JT_RAW;
} else {
flags |= AbstractTransformer.JT_NARROWED;
}
if ((flags & AbstractTransformer.JT_RAW) == 0 && !Decl.equal(refinedParameter, mov) && implementsRawParameter(mov)) {
flags |= AbstractTransformer.JT_RAW;
}
}
}
// keep in sync with gen.willEraseToBestBounds()
if (wideningRules != WideningRules.NONE && (gen.typeFact().isUnion(nonWideningType) || gen.typeFact().isIntersection(nonWideningType))) {
final Type refinedType = ((TypedDeclaration) CodegenUtil.getTopmostRefinedDeclaration(nonWideningDecl)).getType();
if (refinedType.isTypeParameter() && !refinedType.getSatisfiedTypes().isEmpty()) {
nonWideningType = refinedType.getSatisfiedTypes().get(0);
// Could be parameterized, and type param won't be in scope, so have to go raw
flags |= AbstractTransformer.JT_RAW;
}
}
// this is to be done on the parameter's containing method, to see if that method must have raw parameters
if (mov.isParameter() && mov.getContainer() instanceof Declaration && gen.rawParameters((Declaration) mov.getContainer())) {
flags |= AbstractTransformer.JT_RAW;
}
return new NonWideningParam(flags, modifiers, nonWideningType, nonWideningDecl);
}
use of org.eclipse.ceylon.model.typechecker.model.Value in project ceylon by eclipse.
the class InterfaceVisitor method visit.
@Override
public void visit(Tree.AttributeGetterDefinition that) {
Value model = that.getDeclarationModel();
// locals and toplevels get a type generated for them
if (!model.isMember() && !model.isToplevel()) {
Set<String> old = localCompanionClasses;
localCompanionClasses = new HashSet<String>();
super.visit(that);
localCompanionClasses = old;
} else {
super.visit(that);
}
}
Aggregations