use of org.eclipse.ceylon.model.typechecker.model.FunctionOrValue 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.FunctionOrValue in project ceylon by eclipse.
the class CallableBuilder method getParameterTypesFromParameterModels.
private java.util.List<Type> getParameterTypesFromParameterModels() {
java.util.List<Type> parameterTypes = new ArrayList<Type>(numParams);
// get them from our declaration
for (Parameter p : paramLists.getParameters()) {
Type pt;
FunctionOrValue pm = p.getModel();
if (pm instanceof Function && ((Function) pm).isParameter())
pt = gen.getTypeForFunctionalParameter((Function) pm);
else
pt = p.getType();
parameterTypes.add(pt);
}
return parameterTypes;
}
use of org.eclipse.ceylon.model.typechecker.model.FunctionOrValue in project ceylon by eclipse.
the class ExpressionVisitor method accountForIntermediateRefinements.
private Reference accountForIntermediateRefinements(Tree.SpecifierStatement that, FunctionOrValue refinedMethodOrValue, FunctionOrValue methodOrValue, ClassOrInterface refiningType, List<Declaration> interveningRefinements) {
// accumulate an intersection of the types of
// everything it refines
List<Type> refinedTypes = new ArrayList<Type>();
// don't check this one here because it is
// separately checked in visit(SpecifierStatement)
Reference refinedProducedReference = getRefinedMemberReference(refinedMethodOrValue, refiningType);
Map<TypeParameter, Type> substs = substitutions(refinedMethodOrValue, methodOrValue);
Type refinedType = refinedProducedReference.getType().substitute(substs, null);
boolean allHaveNulls = hasNullReturnValues(refinedType, refinedMethodOrValue);
intersectReturnType(refinedTypes, refinedType);
for (Declaration intervening : interveningRefinements) {
if (intervening instanceof FunctionOrValue && // factors here as well?
!refinedMethodOrValue.equals(intervening)) {
FunctionOrValue refinement = (FunctionOrValue) intervening;
Reference refinedMember = getRefinedMemberReference(refinement, refiningType);
Map<TypeParameter, Type> subs = substitutions(refinement, methodOrValue);
Type type = refinedMember.getType().substitute(subs, null);
allHaveNulls = allHaveNulls && hasNullReturnValues(type, refinement);
intersectReturnType(refinedTypes, type);
checkIntermediateRefinement(that, refinement, refinedMember);
}
}
Type it = canonicalIntersection(refinedTypes, unit);
if (allHaveNulls && !unit.isOptionalType(it)) {
methodOrValue.setUncheckedNullType(true);
Tree.Term lhs = that.getBaseMemberExpression();
// TODO: this is pretty ugly, think of something better!
lhs.setTypeModel(unit.getOptionalType(lhs.getTypeModel()));
}
methodOrValue.setType(it);
return refinedProducedReference;
}
use of org.eclipse.ceylon.model.typechecker.model.FunctionOrValue in project ceylon by eclipse.
the class ExpressionVisitor method checkNamedArgument.
private void checkNamedArgument(Tree.NamedArgument arg, Reference reference, Parameter param) {
arg.setParameter(param);
Type argType = null;
if (arg instanceof Tree.SpecifiedArgument) {
Tree.SpecifiedArgument sa = (Tree.SpecifiedArgument) arg;
Tree.Expression e = sa.getSpecifierExpression().getExpression();
if (e != null) {
argType = e.getTypeModel();
}
} else if (arg instanceof Tree.TypedArgument) {
Tree.TypedArgument typedArg = (Tree.TypedArgument) arg;
TypedDeclaration argDec = typedArg.getDeclarationModel();
argType = argumentType(arg.getScope(), argDec);
checkArgumentToVoidParameter(param, typedArg);
if (!dynamic && isTypeUnknown(argType) && !hasError(arg)) {
arg.addError("could not determine type of named argument: the type of '" + param.getName() + "' is not known");
}
}
FunctionOrValue paramModel = param.getModel();
if (paramModel != null) {
TypedReference paramRef = reference.getTypedParameter(param);
Type paramType = paramType(arg.getScope(), paramRef, paramModel);
if (!isTypeUnknown(argType) && !isTypeUnknown(paramType)) {
Node node;
if (arg instanceof Tree.SpecifiedArgument) {
Tree.SpecifiedArgument specifiedArg = (Tree.SpecifiedArgument) arg;
node = specifiedArg.getSpecifierExpression();
} else {
node = arg;
}
checkAssignable(argType, paramType, node, "named argument must be assignable to parameter " + argdesc(param, reference), 2100);
}
}
}
use of org.eclipse.ceylon.model.typechecker.model.FunctionOrValue in project ceylon by eclipse.
the class ExpressionVisitor method createInferredDynamicParameter.
private void createInferredDynamicParameter(Function m, Parameter pm) {
FunctionOrValue model = pm.getModel();
if (model == null) {
Value value = (Value) model;
value = new Value();
value.setUnit(unit);
value.setName(pm.getName());
pm.setModel(value);
value.setContainer(m);
value.setScope(m);
m.addMember(value);
value.setType(unit.getUnknownType());
// value.setDynamic(true);
value.setDynamicallyTyped(true);
value.setInferred(true);
value.setInitializerParameter(pm);
}
}
Aggregations