use of com.redhat.ceylon.model.typechecker.model.Function in project ceylon-compiler by ceylon.
the class NamedArgumentInvocation method transformPrimary.
protected TransformedInvocationPrimary transformPrimary(JCExpression primaryExpr, String selector) {
if (Decl.isJavaStaticOrInterfacePrimary(getPrimary())) {
Declaration methodOrClass = ((Tree.QualifiedMemberOrTypeExpression) getPrimary()).getDeclaration();
if (methodOrClass instanceof Function) {
return new TransformedInvocationPrimary(gen.naming.makeName((Function) methodOrClass, Naming.NA_FQ | Naming.NA_WRAPPER_UNQUOTED), null);
} else if (methodOrClass instanceof Class) {
return new TransformedInvocationPrimary(gen.makeJavaType(((Class) methodOrClass).getType(), JT_RAW | JT_NO_PRIMITIVES), null);
}
}
if (isMemberRefInvocation()) {
JCExpression callable = gen.expressionGen().transformMemberReference((Tree.QualifiedMemberOrTypeExpression) getPrimary(), (Tree.MemberOrTypeExpression) getQmePrimary());
// The callable is a Callable we generate ourselves, it can never be erased to Object so there's no need to unerase
selector = Naming.getCallableMethodName();
return new TransformedInvocationPrimary(callable, selector);
}
JCExpression actualPrimExpr;
if (getPrimary() instanceof Tree.QualifiedTypeExpression && ((Tree.QualifiedTypeExpression) getPrimary()).getPrimary() instanceof Tree.BaseTypeExpression && !Decl.isConstructor(getPrimaryDeclaration())) {
actualPrimExpr = gen.naming.makeQualifiedThis(primaryExpr);
} else {
actualPrimExpr = primaryExpr;
}
if (getPrimary() instanceof Tree.BaseTypeExpression) {
Tree.BaseTypeExpression type = (Tree.BaseTypeExpression) getPrimary();
Declaration declaration = type.getDeclaration();
if (Strategy.generateInstantiator(declaration)) {
if (Decl.withinInterface(declaration)) {
if (primaryExpr != null) {
// if we have some other primary then respect that
actualPrimExpr = primaryExpr;
} else {
// if the class being instantiated is
// within a class we expect the instantiation to be
// accessible from `this`, so use null
// otherwise we must be in an companion class, so we
// need to qualify the instantiator invocation with $this
actualPrimExpr = type.getScope().getInheritingDeclaration(declaration) instanceof Class ? null : gen.naming.makeQuotedThis();
}
} else if (declaration.isToplevel()) {
actualPrimExpr = null;
}
// if the decl is not toplevel (but the primary is a base type
// we must be invoking a member imported from an object
// in which case the qualifer is needed.
}
if (Decl.isConstructor(declaration)) {
selector = null;
}
} else {
if (getPrimary() instanceof Tree.QualifiedMemberOrTypeExpression) {
Tree.QualifiedMemberOrTypeExpression type = (Tree.QualifiedMemberOrTypeExpression) getPrimary();
Declaration declaration = type.getDeclaration();
if (Decl.isConstructor(declaration)) {
if (Decl.withinInterface(Decl.getConstructedClass(declaration))) {
if (Strategy.generateInstantiator(declaration)) {
actualPrimExpr = primaryExpr != null ? primaryExpr : gen.naming.makeQuotedThis();
} else {
actualPrimExpr = null;
}
}
}
} else if (getPrimary() instanceof Tree.BaseMemberOrTypeExpression) {
Tree.BaseMemberOrTypeExpression type = (Tree.BaseMemberOrTypeExpression) getPrimary();
Declaration declaration = type.getDeclaration();
if (Decl.isConstructor(declaration)) {
selector = null;
}
}
if (isIndirect()) {
if (getPrimaryDeclaration() != null && (Decl.isGetter(getPrimaryDeclaration()) || Decl.isToplevel(getPrimaryDeclaration()) || (Decl.isValueOrSharedOrCapturedParam(getPrimaryDeclaration()) && Decl.isCaptured(getPrimaryDeclaration()) && !Decl.isLocalNotInitializer(getPrimaryDeclaration())))) {
// We need to invoke the getter to obtain the Callable
actualPrimExpr = gen.make().Apply(null, gen.naming.makeQualIdent(primaryExpr, selector), List.<JCExpression>nil());
} else if (selector != null) {
actualPrimExpr = gen.naming.makeQualIdent(primaryExpr, selector);
} else if (getPrimaryDeclaration() == null || !((TypedDeclaration) getPrimaryDeclaration()).getType().isTypeConstructor()) {
actualPrimExpr = gen.naming.makeQualifiedName(primaryExpr, (TypedDeclaration) getPrimaryDeclaration(), Naming.NA_MEMBER);
}
actualPrimExpr = unboxCallableIfNecessary(actualPrimExpr, getPrimary());
if (gen.isVariadicCallable(getPrimary().getTypeModel())) {
selector = Naming.getCallableVariadicMethodName();
this.callable = true;
} else {
selector = Naming.getCallableMethodName();
this.callable = true;
}
// If it's indirect the primary might be erased
actualPrimExpr = gen.expressionGen().applyErasureAndBoxing(actualPrimExpr, getPrimary().getTypeModel(), getPrimary().getTypeErased(), // boxed
true, BoxingStrategy.BOXED, getPrimary().getTypeModel(), 0);
} else if ((getPrimaryDeclaration() instanceof Function && // i.e. functional parameter
((Function) getPrimaryDeclaration()).isParameter() && // not class member, or not shared/captured
(!JvmBackendUtil.createMethod((Function) getPrimaryDeclaration())) || // we need to access the Callable parameter, no the member method
gen.expressionGen().isWithinDefaultParameterExpression(getPrimaryDeclaration().getContainer()))) {
if (selector != null) {
actualPrimExpr = gen.naming.makeQualIdent(primaryExpr, selector);
} else {
actualPrimExpr = gen.naming.makeQualifiedName(primaryExpr, (TypedDeclaration) getPrimaryDeclaration(), Naming.NA_MEMBER);
}
actualPrimExpr = unboxCallableIfNecessary(actualPrimExpr, getPrimary());
if (gen.isVariadicCallable(getPrimary().getTypeModel())) {
selector = Naming.getCallableVariadicMethodName();
this.callable = true;
} else {
selector = Naming.getCallableMethodName();
this.callable = true;
}
}
}
return new TransformedInvocationPrimary(actualPrimExpr, selector);
}
use of com.redhat.ceylon.model.typechecker.model.Function in project ceylon-compiler by ceylon.
the class NamedArgumentInvocation method appendVarsForDefaulted.
private boolean appendVarsForDefaulted(java.util.List<Parameter> declaredParams) {
boolean hasDefaulted = false;
if (!Decl.isOverloaded(getPrimaryDeclaration())) {
// append any arguments for defaulted parameters
for (Parameter param : declaredParams) {
if (bound.contains(param)) {
continue;
}
final JCExpression argExpr;
if (Strategy.hasDefaultParameterValueMethod(param)) {
// special handling for "element" optional param of java array constructors
if (getPrimaryDeclaration() instanceof Class && gen.isJavaArray(((Class) getPrimaryDeclaration()).getType())) {
// default values are hard-coded to Java default values, and are actually ignored
continue;
} else if (getQmePrimary() != null && gen.isJavaArray(getQmePrimary().getTypeModel())) {
// we support array methods with optional parameters
if (getPrimaryDeclaration() instanceof Function && getPrimaryDeclaration().getName().equals("copyTo")) {
if (param.getName().equals("sourcePosition") || param.getName().equals("destinationPosition")) {
argExpr = gen.makeInteger(0);
hasDefaulted |= true;
} else if (param.getName().equals("length")) {
argExpr = gen.makeSelect(varBaseName.suffixedBy(Suffix.$argthis$).makeIdent(), "length");
hasDefaulted |= true;
} else {
argExpr = gen.makeErroneous(this.getNode(), "compiler bug: argument to copyTo method of java array type not supported: " + param.getName());
}
} else {
argExpr = gen.makeErroneous(this.getNode(), "compiler bug: virtual method of java array type not supported: " + getPrimaryDeclaration());
}
} else {
argExpr = makeDefaultedArgumentMethodCall(param);
hasDefaulted |= true;
}
} else if (Strategy.hasEmptyDefaultArgument(param)) {
argExpr = gen.makeEmptyAsSequential(true);
} else if (gen.typeFact().isIterableType(param.getType())) {
// must be an iterable we need to fill with empty
// FIXME: deal with this erasure bug later
argExpr = gen.make().TypeCast(gen.makeJavaType(gen.typeFact().getIterableDeclaration().getType(), AbstractTransformer.JT_RAW), gen.makeEmpty());
} else {
// more expensive but worth a try
Type appliedType = gen.getTypeForParameter(param, producedReference, AbstractTransformer.TP_TO_BOUND);
if (gen.typeFact().isIterableType(appliedType)) {
argExpr = gen.make().TypeCast(gen.makeJavaType(gen.typeFact().getIterableDeclaration().getType(), AbstractTransformer.JT_RAW), gen.makeEmpty());
} else {
argExpr = gen.makeErroneous(this.getNode(), "compiler bug: missing argument, and parameter is not defaulted");
}
}
appendDefaulted(param, argExpr);
}
}
return hasDefaulted;
}
use of com.redhat.ceylon.model.typechecker.model.Function in project ceylon-compiler by ceylon.
the class AbstractTransformer method getTypeForParameter.
Type getTypeForParameter(Parameter parameter, Reference producedReference, int flags) {
/* this method is bogus: It's really trying to answer
* "what's the type of the java declaration of the given parameter",
* but using the ceylon type system to do so.
*/
boolean functional = parameter.getModel() instanceof Function;
if (producedReference == null) {
return parameter.getType();
}
final TypedReference producedTypedReference = producedReference.getTypedParameter(parameter);
final Type type = functional ? producedTypedReference.getFullType() : producedTypedReference.getType();
final TypedDeclaration producedParameterDecl = producedTypedReference.getDeclaration();
final Type declType = producedParameterDecl.getType();
// be more resilient to upstream errors
if (declType == null)
return typeFact.getUnknownType();
if (isJavaVariadic(parameter) && (flags & TP_SEQUENCED_TYPE) == 0) {
// type of param must be Iterable<T>
Type elementType = typeFact.getIteratedType(type);
if (elementType == null) {
log.error("ceylon", "Invalid type for Java variadic parameter: " + type.asQualifiedString());
return type;
}
return elementType;
}
if (declType.isClassOrInterface()) {
return type;
} else if ((declType.isTypeParameter()) && (flags & TP_TO_BOUND) != 0) {
if (!declType.getSatisfiedTypes().isEmpty()) {
// use upper bound
Type upperBound = declType.getSatisfiedTypes().get(0);
// make sure we apply the type arguments
upperBound = substituteTypeArgumentsForTypeParameterBound(producedReference, upperBound);
Type self = upperBound.getDeclaration().getSelfType();
if (self != null) {
// make sure we apply the type arguments
Type selfUpperBound = self.substitute(upperBound);
if (!willEraseToObject(selfUpperBound) && (willEraseToObject(type) || expressionGen().needsCast(type, selfUpperBound, false, false, false))) {
return selfUpperBound;
}
}
if (!willEraseToObject(upperBound) && (willEraseToObject(type) || expressionGen().needsCast(type, upperBound, false, false, false))) {
return upperBound;
}
}
}
return type;
}
use of com.redhat.ceylon.model.typechecker.model.Function in project ceylon-compiler by ceylon.
the class AbstractTransformer method makeReifiedTypeArgumentResolved.
private JCExpression makeReifiedTypeArgumentResolved(Type pt, boolean qualified) {
if (pt.isUnion()) {
// FIXME: refactor this shite
List<JCExpression> typeTestArguments = List.nil();
java.util.List<Type> typeParameters = pt.getCaseTypes();
if (typeParameters.size() == 2) {
Type alternative = null;
if (typeParameters.get(0).isEmpty())
alternative = typeParameters.get(1);
else if (typeParameters.get(1).isEmpty())
alternative = typeParameters.get(0);
if (alternative != null && alternative.isTuple()) {
JCExpression tupleType = makeTupleTypeDescriptor(alternative, true);
if (tupleType != null)
return tupleType;
}
}
for (int i = typeParameters.size() - 1; i >= 0; i--) {
typeTestArguments = typeTestArguments.prepend(makeReifiedTypeArgument(typeParameters.get(i)));
}
return make().Apply(null, makeSelect(makeTypeDescriptorType(), "union"), typeTestArguments);
} else if (pt.isIntersection()) {
List<JCExpression> typeTestArguments = List.nil();
java.util.List<Type> typeParameters = pt.getSatisfiedTypes();
for (int i = typeParameters.size() - 1; i >= 0; i--) {
typeTestArguments = typeTestArguments.prepend(makeReifiedTypeArgument(typeParameters.get(i)));
}
return make().Apply(null, makeSelect(makeTypeDescriptorType(), "intersection"), typeTestArguments);
} else if (pt.isNothing()) {
return makeNothingTypeDescriptor();
}
TypeDeclaration declaration = pt.getDeclaration();
if (declaration instanceof Constructor) {
pt = pt.getExtendedType();
declaration = pt.getDeclaration();
}
if (pt.isClassOrInterface()) {
if (declaration.isJavaEnum()) {
pt = pt.getExtendedType();
declaration = pt.getDeclaration();
}
// see if we have an alias for it
if (supportsReifiedAlias((ClassOrInterface) declaration)) {
JCExpression qualifier = naming.makeDeclarationName(declaration, DeclNameFlag.QUALIFIED);
return makeSelect(qualifier, naming.getTypeDescriptorAliasName());
}
if (pt.isTuple()) {
JCExpression tupleType = makeTupleTypeDescriptor(pt, false);
if (tupleType != null)
return tupleType;
}
// no alias, must build it
List<JCExpression> typeTestArguments = makeReifiedTypeArgumentsResolved(pt.getTypeArgumentList(), qualified);
JCExpression thisType = makeUnerasedClassLiteral(declaration);
// do we have variance overrides?
Map<TypeParameter, SiteVariance> varianceOverrides = pt.getVarianceOverrides();
if (!varianceOverrides.isEmpty()) {
// we need to pass them as second argument then, in an array
ListBuffer<JCExpression> varianceElements = new ListBuffer<JCExpression>();
for (TypeParameter typeParameter : declaration.getTypeParameters()) {
SiteVariance useSiteVariance = varianceOverrides.get(typeParameter);
String selector;
if (useSiteVariance != null) {
switch(useSiteVariance) {
case IN:
selector = "IN";
break;
case OUT:
selector = "OUT";
break;
default:
selector = "NONE";
break;
}
} else {
selector = "NONE";
}
JCExpression varianceElement = make().Select(makeIdent(syms().ceylonVarianceType), names().fromString(selector));
varianceElements.append(varianceElement);
}
JCNewArray varianceArray = make().NewArray(makeIdent(syms().ceylonVarianceType), List.<JCExpression>nil(), varianceElements.toList());
typeTestArguments = typeTestArguments.prepend(varianceArray);
}
typeTestArguments = typeTestArguments.prepend(thisType);
JCExpression classDescriptor = make().Apply(null, makeSelect(makeTypeDescriptorType(), "klass"), typeTestArguments);
Type qualifyingType = pt.getQualifyingType();
JCExpression containerType = null;
if (qualifyingType == null && // ignore qualifying types of static java declarations
(Decl.isCeylon(declaration) || !declaration.isStaticallyImportable())) {
// it may be contained in a function or value, and we want its type
Declaration enclosingDeclaration = getDeclarationContainer(declaration);
if (enclosingDeclaration instanceof TypedDeclaration)
containerType = makeTypedDeclarationTypeDescriptorResolved((TypedDeclaration) enclosingDeclaration);
else if (enclosingDeclaration instanceof TypeDeclaration) {
qualifyingType = ((TypeDeclaration) enclosingDeclaration).getType();
}
}
if (qualifyingType != null && qualifyingType.getDeclaration() instanceof Constructor) {
qualifyingType = qualifyingType.getQualifyingType();
}
if (qualifyingType != null) {
containerType = makeReifiedTypeArgumentResolved(qualifyingType, true);
}
if (containerType == null) {
return classDescriptor;
} else {
return make().Apply(null, makeSelect(makeTypeDescriptorType(), "member"), List.of(containerType, classDescriptor));
}
} else if (pt.isTypeParameter()) {
TypeParameter tp = (TypeParameter) declaration;
String name = naming.getTypeArgumentDescriptorName(tp);
if (!qualified || isTypeParameterSubstituted(tp))
return makeUnquotedIdent(name);
Scope container = tp.getContainer();
JCExpression qualifier = null;
if (container instanceof Class) {
qualifier = naming.makeQualifiedThis(makeJavaType(((Class) container).getType(), JT_RAW));
} else if (container instanceof Interface) {
qualifier = naming.makeQualifiedThis(makeJavaType(((Interface) container).getType(), JT_COMPANION | JT_RAW));
} else if (container instanceof Function) {
// name must be a unique name, as returned by getTypeArgumentDescriptorName
return makeUnquotedIdent(name);
} else {
throw BugException.unhandledCase(container);
}
return makeSelect(qualifier, name);
} else {
throw BugException.unhandledDeclarationCase(declaration);
}
}
use of com.redhat.ceylon.model.typechecker.model.Function in project ceylon-compiler by ceylon.
the class LinkRenderer method getUrl.
private String getUrl(Object to, Declaration anchor) {
String url;
List<Function> methods = new ArrayList<Function>();
while (to instanceof Function) {
Function method = (Function) to;
methods.add(method);
to = method.getContainer();
}
if (isInCurrentModule(to)) {
url = getLocalUrl(to);
} else {
url = getExternalUrl(to);
}
if (url != null && anchor != null) {
String sectionPackageAnchor = "#section-package";
if (url.endsWith(sectionPackageAnchor)) {
url = url.substring(0, url.length() - sectionPackageAnchor.length());
}
StringBuilder fragment = new StringBuilder();
if (!methods.isEmpty()) {
Collections.reverse(methods);
for (Function method : methods) {
fragment.append(method.getName());
fragment.append("-");
}
}
fragment.append(anchor.getName());
url = url + "#" + fragment;
}
return url;
}
Aggregations