use of org.eclipse.ceylon.model.typechecker.model.Declaration in project ceylon by eclipse.
the class BoxingDeclarationVisitor method setBoxingState.
private void setBoxingState(TypedDeclaration declaration, TypedDeclaration refinedDeclaration, Node that) {
Type type = declaration.getType();
if (type == null) {
// an error must have already been reported
return;
}
// fetch the real refined declaration if required
if (Decl.equal(declaration, refinedDeclaration) && declaration instanceof FunctionOrValue && ((FunctionOrValue) declaration).isParameter() && declaration.getContainer() instanceof Class) {
// maybe it is really inherited from a field?
FunctionOrValue methodOrValueForParam = (FunctionOrValue) declaration;
if (methodOrValueForParam != null) {
// make sure we get the refined version of that member
refinedDeclaration = (TypedDeclaration) methodOrValueForParam.getRefinedDeclaration();
}
}
// inherit underlying type constraints
if (!Decl.equal(refinedDeclaration, declaration)) {
// simple case
if (type.getUnderlyingType() == null && refinedDeclaration.getType() != null) {
if (type.isCached()) {
type = type.clone();
}
type.setUnderlyingType(refinedDeclaration.getType().getUnderlyingType());
declaration.setType(type);
}
// special case for variadics
if (Decl.isValueParameter(refinedDeclaration)) {
Parameter parameter = ((FunctionOrValue) refinedDeclaration).getInitializerParameter();
if (parameter.isSequenced()) {
// inherit the underlying type of the iterated type
Type refinedIteratedType = refinedDeclaration.getType().getTypeArgumentList().get(0);
if (refinedIteratedType.getUnderlyingType() != null) {
Type ourIteratedType = type.getTypeArgumentList().get(0);
if (ourIteratedType.getUnderlyingType() == null) {
if (ourIteratedType.isCached()) {
ourIteratedType = ourIteratedType.clone();
}
ourIteratedType.setUnderlyingType(refinedIteratedType.getUnderlyingType());
type.getTypeArgumentList().set(0, ourIteratedType);
// make sure we remove those types from the cache otherwise UGLY things happen
TypeCache cache = type.getDeclaration().getUnit().getCache();
if (cache != null) {
cache.remove(ourIteratedType);
cache.remove(type);
}
}
}
}
}
}
// abort if our boxing state has already been set
if (declaration.getUnboxed() != null)
return;
// functional parameter return values are always boxed if we're not creating a method for them
if (declaration instanceof Function && ((Function) declaration).isParameter() && !JvmBackendUtil.createMethod((Function) declaration)) {
declaration.setUnboxed(false);
return;
}
if (!Decl.equal(refinedDeclaration, declaration)) {
// make sure refined declarations have already been set
if (refinedDeclaration.getUnboxed() == null)
setBoxingState(refinedDeclaration, refinedDeclaration, that);
// inherit
declaration.setUnboxed(refinedDeclaration.getUnboxed());
} else if (declaration instanceof Function && Strategy.useBoxedVoid((Function) declaration) && !(refinedDeclaration.getTypeDeclaration() instanceof TypeParameter) && !CodegenUtil.isContainerFunctionalParameter(refinedDeclaration) && !(refinedDeclaration instanceof Functional && Decl.isMpl((Functional) refinedDeclaration))) {
declaration.setUnboxed(false);
} else if ((isCeylonBasicType(type) || Decl.isUnboxedVoid(declaration)) && !(refinedDeclaration.getTypeDeclaration() instanceof TypeParameter) && (refinedDeclaration.getContainer() instanceof Declaration == false || !CodegenUtil.isContainerFunctionalParameter(refinedDeclaration)) && !(refinedDeclaration instanceof Functional && Decl.isMpl((Functional) refinedDeclaration))) {
boolean unbox = !forceBoxedLocals || !(declaration instanceof Value) || !Decl.isLocal(declaration) || Decl.isParameter(declaration) || Decl.isTransient(declaration);
// until it's used later by user code
if (declaration.getOriginalDeclaration() != null && declaration.hasUncheckedNullType())
unbox = false;
declaration.setUnboxed(unbox);
} else if (Decl.isValueParameter(declaration) && CodegenUtil.isContainerFunctionalParameter(declaration) && JvmBackendUtil.createMethod((FunctionOrValue) declaration.getContainer())) {
Function functionalParameter = (Function) declaration.getContainer();
TypedDeclaration refinedFrom = (TypedDeclaration) CodegenUtil.getTopmostRefinedDeclaration(functionalParameter, optimisedMethodSpecifiersToMethods);
if (Decl.equal(refinedFrom, functionalParameter)) {
// not a method return type (where void would be considered unboxed).
if (declaration.getUnit().getAnythingType().isExactly(declaration.getType()) || declaration.getUnit().isOptionalType(declaration.getType())) {
declaration.setUnboxed(false);
} else {
declaration.setUnboxed(true);
}
} else {
// make sure refined declarations have already been set
if (refinedFrom.getUnboxed() == null)
setBoxingState(refinedFrom, refinedFrom, that);
// inherit
declaration.setUnboxed(refinedFrom.getUnboxed());
}
} else {
declaration.setUnboxed(false);
}
// Any "@boxed" or "@unboxed" compiler annotation overrides
boxFromAnnotation(declaration, that);
}
use of org.eclipse.ceylon.model.typechecker.model.Declaration in project ceylon by eclipse.
the class CallBuilder method build.
public JCExpression build() {
if (built) {
throw new BugException("already built");
}
built = true;
JCExpression result;
List<JCExpression> arguments;
final JCExpression newEncl;
if ((cbOpts & CB_ALIAS_ARGS) != 0) {
if (instantiateQualfier != null && instantiateQualfier.expression != null) {
if (instantiateQualfier.type == null) {
throw new BugException(MISSING_TYPE);
}
SyntheticName qualName = getQualifierName(basename);
appendStatement(gen.makeVar(Flags.FINAL, qualName, instantiateQualfier.type, instantiateQualfier.expression));
newEncl = qualName.makeIdent();
} else {
newEncl = null;
}
arguments = List.<JCExpression>nil();
int argumentNum = 0;
for (ExpressionAndType argumentAndType : argumentsAndTypes) {
SyntheticName name = getArgumentName(basename, argumentNum);
if (argumentAndType.type == null) {
throw new BugException(MISSING_TYPE);
}
if ((cbOpts & CB_ALIAS_ARGS) != 0) {
appendStatement(gen.makeVar(Flags.FINAL, name, argumentAndType.type, argumentAndType.expression));
}
arguments = arguments.append(name.makeIdent());
argumentNum++;
}
} else {
newEncl = this.instantiateQualfier != null ? this.instantiateQualfier.expression : null;
arguments = ExpressionAndType.toExpressionList(this.argumentsAndTypes);
}
if (haveLocation) {
gen.at(this.location);
}
switch(kind) {
case APPLY:
result = gen.make().Apply(this.typeargs.toList(), this.methodOrClass, arguments);
break;
case NEW:
result = gen.make().NewClass(newEncl, null, this.methodOrClass, arguments, classDefs);
break;
case ARRAY_READ:
result = gen.make().Indexed(this.methodOrClass, arguments.head);
break;
case ARRAY_WRITE:
{
JCExpression array;
if (arrayWriteNeedsCast)
array = gen.make().TypeCast(gen.make().TypeArray(gen.make().Type(gen.syms().objectType)), this.methodOrClass);
else
array = this.methodOrClass;
result = gen.make().Assign(gen.make().Indexed(array, arguments.head), arguments.tail.head);
}
break;
case NEW_ARRAY:
// methodOrClass must be a ArrayType, so we get the element type out
JCExpression elementTypeExpr = ((JCTree.JCArrayTypeTree) this.methodOrClass).elemtype;
if (arrayInstanceReifiedType == null) {
result = gen.make().NewArray(elementTypeExpr, List.of(arguments.head), null);
if (arrayInstanceCast != null) {
result = gen.make().TypeCast(arrayInstanceCast, result);
}
} else {
List<JCExpression> dimensions = List.nil();
if (arrayInstanceDimensions > 1) {
for (int i = 1; i < arrayInstanceDimensions; i++) {
dimensions = dimensions.prepend(gen.makeInteger(0));
}
}
dimensions = dimensions.prepend(arguments.head);
dimensions = dimensions.prepend(arrayInstanceReifiedType);
result = gen.utilInvocation().makeArray(dimensions);
}
if (arguments.tail.nonEmpty()) {
// must fill it
result = gen.utilInvocation().fillArray(List.of(result, arguments.tail.head));
}
break;
case NEW_ARRAY_WITH:
Declaration d = arrayType.getDeclaration();
if (d.equals(gen.typeFact().getJavaLongArrayDeclaration())) {
result = gen.utilInvocation().toLongArray(arguments.head, arguments.tail);
} else if (d.equals(gen.typeFact().getJavaIntArrayDeclaration())) {
result = gen.utilInvocation().toIntArray(arguments.head, arguments.tail);
} else if (d.equals(gen.typeFact().getJavaShortArrayDeclaration())) {
result = gen.utilInvocation().toShortArray(arguments.head, arguments.tail);
} else if (d.equals(gen.typeFact().getJavaCharArrayDeclaration())) {
result = gen.utilInvocation().toCharArray(arguments.head, arguments.tail);
} else if (d.equals(gen.typeFact().getJavaByteArrayDeclaration())) {
result = gen.utilInvocation().toByteArray(arguments.head, arguments.tail);
} else if (d.equals(gen.typeFact().getJavaBooleanArrayDeclaration())) {
result = gen.utilInvocation().toBooleanArray(arguments.head, arguments.tail);
} else if (d.equals(gen.typeFact().getJavaFloatArrayDeclaration())) {
result = gen.utilInvocation().toFloatArray(arguments.head, arguments.tail);
} else if (d.equals(gen.typeFact().getJavaDoubleArrayDeclaration())) {
result = gen.utilInvocation().toDoubleArray(arguments.head, arguments.tail);
} else {
// it must be an ObjectArray
result = gen.utilInvocation().toArray(arguments.tail.head, // don't use makeClassLiteral, because it doesn't c.l.Object -> j.l.Object
gen.makeSelect(gen.makeJavaType(arrayType.getTypeArgumentList().get(0), AbstractTransformer.JT_NO_PRIMITIVES), "class"), arguments.tail.tail);
}
break;
case FIELD_READ:
result = this.methodOrClass;
break;
default:
throw BugException.unhandledEnumCase(kind);
}
if ((cbOpts & CB_LET) != 0) {
if (voidMethod) {
result = gen.make().LetExpr(statements.toList().append(gen.make().Exec(result)), gen.makeNull());
} else if (!statements.isEmpty()) {
result = gen.make().LetExpr(statements.toList(), result);
}
}
return result;
}
use of org.eclipse.ceylon.model.typechecker.model.Declaration in project ceylon by eclipse.
the class CallableBuilder method methodReference.
/**
* Constructs an {@code AbstractCallable} suitable for wrapping a
* method reference. For example:
* <pre>
* void someMethod() { ... }
* Anything() ref = someMethod;
* </pre>
*/
public static JCExpression methodReference(CeylonTransformer gen, final Tree.StaticMemberOrTypeExpression forwardCallTo, ParameterList parameterList, Type expectedType, Type callableType, boolean useParameterTypesFromCallableModel) {
ListBuffer<JCStatement> letStmts = new ListBuffer<JCStatement>();
CallableBuilder cb = new CallableBuilder(gen, forwardCallTo, callableType, parameterList);
cb.parameterTypes = useParameterTypesFromCallableModel ? cb.getParameterTypesFromCallableModel() : cb.getParameterTypesFromParameterModels();
Naming.SyntheticName instanceFieldName;
boolean instanceFieldIsBoxed = false;
if (forwardCallTo instanceof Tree.QualifiedMemberOrTypeExpression && !ExpressionTransformer.isSuperOrSuperOf(((Tree.QualifiedMemberOrTypeExpression) forwardCallTo).getPrimary()) && !ExpressionTransformer.isPackageQualified((Tree.QualifiedMemberOrTypeExpression) forwardCallTo)) {
if ((((Tree.QualifiedMemberOrTypeExpression) forwardCallTo).getMemberOperator() instanceof Tree.SpreadOp)) {
instanceFieldIsBoxed = true;
instanceFieldName = null;
} else {
Tree.QualifiedMemberOrTypeExpression qmte = (Tree.QualifiedMemberOrTypeExpression) forwardCallTo;
boolean prevCallableInv = gen.expressionGen().withinSyntheticClassBody(true);
try {
instanceFieldName = gen.naming.synthetic(Unfix.$instance$);
int varTypeFlags = Decl.isPrivateAccessRequiringCompanion(qmte) ? JT_COMPANION : 0;
Type primaryType;
if (Decl.isValueTypeDecl(qmte.getPrimary().getTypeModel())) {
primaryType = qmte.getPrimary().getTypeModel();
} else {
primaryType = qmte.getTarget().getQualifyingType();
}
if (((Tree.QualifiedMemberOrTypeExpression) forwardCallTo).getMemberOperator() instanceof Tree.SafeMemberOp) {
primaryType = gen.typeFact().getOptionalType(primaryType);
}
JCExpression primaryExpr = gen.expressionGen().transformQualifiedMemberPrimary(qmte);
Declaration dec = qmte.getDeclaration();
if (Decl.isPrivateAccessRequiringCompanion(qmte)) {
primaryExpr = gen.naming.makeCompanionAccessorCall(primaryExpr, (Interface) dec.getContainer());
}
Type varType = dec.isShared() ? primaryType : Decl.getPrivateAccessType(qmte);
if (qmte.getPrimary().getUnboxed() == false) {
varTypeFlags |= JT_NO_PRIMITIVES;
instanceFieldIsBoxed = true;
}
letStmts.add(gen.makeVar(Flags.FINAL, instanceFieldName, gen.makeJavaType(varType, varTypeFlags), primaryExpr));
if (qmte.getPrimary() instanceof Tree.MemberOrTypeExpression && ((Tree.MemberOrTypeExpression) qmte.getPrimary()).getDeclaration() instanceof TypedDeclaration) {
cb.instanceSubstitution = gen.naming.addVariableSubst((TypedDeclaration) ((Tree.MemberOrTypeExpression) qmte.getPrimary()).getDeclaration(), instanceFieldName.getName());
}
} finally {
gen.expressionGen().withinSyntheticClassBody(prevCallableInv);
}
}
} else {
instanceFieldName = null;
}
CallableTransformation tx;
cb.defaultValueCall = new DefaultValueMethodTransformation() {
@Override
public JCExpression makeDefaultValueMethod(AbstractTransformer gen, Parameter defaultedParam, List<JCExpression> defaultMethodArgs) {
JCExpression fn = null;
if (forwardCallTo instanceof Tree.BaseMemberOrTypeExpression) {
fn = gen.naming.makeDefaultedParamMethod(null, defaultedParam);
} else if (forwardCallTo instanceof Tree.QualifiedMemberOrTypeExpression) {
JCExpression qualifier = gen.expressionGen().transformTermForInvocation(((Tree.QualifiedMemberOrTypeExpression) forwardCallTo).getPrimary(), null);
fn = gen.naming.makeDefaultedParamMethod(qualifier, defaultedParam);
}
return gen.make().Apply(null, fn, defaultMethodArgs);
}
};
if (cb.isVariadic) {
tx = cb.new VariadicCallableTransformation(cb.new CallMethodWithForwardedBody(instanceFieldName, instanceFieldIsBoxed, forwardCallTo, false, callableType));
} else {
tx = cb.new FixedArityCallableTransformation(cb.new CallMethodWithForwardedBody(instanceFieldName, instanceFieldIsBoxed, forwardCallTo, true, callableType), null);
}
cb.useTransformation(tx);
cb.checkForFunctionalInterface(expectedType);
return letStmts.isEmpty() ? cb.build() : gen.make().LetExpr(letStmts.toList(), cb.build());
}
use of org.eclipse.ceylon.model.typechecker.model.Declaration in project ceylon by eclipse.
the class CeylonDoc method getIcons.
protected final List<String> getIcons(Object obj) {
List<String> icons = new ArrayList<String>();
if (obj instanceof Declaration) {
Declaration decl = (Declaration) obj;
Annotation deprecated = Util.findAnnotation(decl, "deprecated");
if (deprecated != null) {
icons.add("icon-decoration-deprecated");
}
if (decl instanceof ClassOrInterface || decl instanceof Constructor) {
if (decl instanceof Interface) {
icons.add("icon-interface");
if (Util.isEnumerated((ClassOrInterface) decl)) {
icons.add("icon-decoration-enumerated");
}
}
if (decl instanceof Class) {
Class klass = (Class) decl;
if (klass.isAnonymous()) {
icons.add("icon-object");
} else {
icons.add("icon-class");
}
if (klass.isAbstract()) {
icons.add("icon-decoration-abstract");
}
if (klass.isFinal() && !klass.isAnonymous() && !klass.isAnnotation()) {
icons.add("icon-decoration-final");
}
if (Util.isEnumerated(klass)) {
icons.add("icon-decoration-enumerated");
}
}
if (decl instanceof Constructor) {
icons.add("icon-class");
}
if (!decl.isShared()) {
icons.add("icon-decoration-local");
}
}
if (decl instanceof TypedDeclaration) {
if (decl.isShared()) {
icons.add("icon-shared-member");
} else {
icons.add("icon-local-member");
}
if (decl.isFormal()) {
icons.add("icon-decoration-formal");
}
if (decl.isActual()) {
Declaration refinedDeclaration = decl.getRefinedDeclaration();
if (refinedDeclaration != null) {
if (refinedDeclaration.isFormal()) {
icons.add("icon-decoration-impl");
}
if (refinedDeclaration.isDefault()) {
icons.add("icon-decoration-over");
}
}
}
if (((TypedDeclaration) decl).isVariable()) {
icons.add("icon-decoration-variable");
}
}
if (decl instanceof TypeAlias || decl instanceof NothingType) {
icons.add("icon-type-alias");
}
if (decl.isAnnotation()) {
icons.add("icon-decoration-annotation");
}
}
if (obj instanceof Package) {
Package pkg = (Package) obj;
icons.add("icon-package");
if (!pkg.isShared()) {
icons.add("icon-decoration-local");
}
}
if (obj instanceof ModuleImport) {
ModuleImport moduleImport = (ModuleImport) obj;
icons.add("icon-module");
if (moduleImport.isExport()) {
icons.add("icon-module-exported-decoration");
}
if (moduleImport.isOptional()) {
icons.add("icon-module-optional-decoration");
}
}
if (obj instanceof Module) {
icons.add("icon-module");
}
return icons;
}
use of org.eclipse.ceylon.model.typechecker.model.Declaration in project ceylon by eclipse.
the class CeylonDocTool method doc.
private void doc(Module module) throws IOException {
Writer rootWriter = openWriter(getObjectFile(module));
try {
ModuleDoc moduleDoc = new ModuleDoc(this, rootWriter, module);
moduleDoc.generate();
for (Package pkg : getPackages(module)) {
if (pkg.getMembers().isEmpty()) {
continue;
}
// document the package
if (!isRootPackage(module, pkg)) {
Writer packageWriter = openWriter(getObjectFile(pkg));
try {
new PackageDoc(this, packageWriter, pkg).generate();
} finally {
packageWriter.close();
}
}
// document its members
for (Declaration decl : pkg.getMembers()) {
doc(decl);
}
if (pkg.getNameAsString().equals(AbstractModelLoader.CEYLON_LANGUAGE)) {
docNothingType(pkg);
}
}
} finally {
rootWriter.close();
}
}
Aggregations