use of org.eclipse.ceylon.model.typechecker.model.Function in project ceylon by eclipse.
the class ExpressionVisitor method visit.
@Override
public void visit(Tree.SpecifierStatement that) {
super.visit(that);
Tree.SpecifierExpression rhs = that.getSpecifierExpression();
Tree.Term lhs = that.getBaseMemberExpression();
boolean hasParams = false;
Tree.Term me = lhs;
while (me instanceof Tree.ParameterizedExpression) {
hasParams = true;
Tree.ParameterizedExpression pe = (Tree.ParameterizedExpression) me;
me = pe.getPrimary();
}
if (!(me instanceof Tree.StaticMemberOrTypeExpression)) {
me.addError("illegal specification statement: only a function or value may be specified");
return;
}
assign(me);
Declaration d = that.getDeclaration();
if (d == null && me instanceof Tree.MemberOrTypeExpression) {
Tree.MemberOrTypeExpression mte = (Tree.MemberOrTypeExpression) me;
d = mte.getDeclaration();
}
if (d instanceof TypedDeclaration) {
TypedDeclaration td = (TypedDeclaration) d;
if (that.getRefinement()) {
// refinement of an inherited member
if (d instanceof Value) {
refineAttribute(that);
} else if (d instanceof Function) {
refineMethod(that);
}
Tree.StaticMemberOrTypeExpression smte = (Tree.StaticMemberOrTypeExpression) me;
smte.setDeclaration(d);
} else if (d instanceof FunctionOrValue && !lhs.hasErrors()) {
FunctionOrValue mv = (FunctionOrValue) d;
if (mv.isShortcutRefinement()) {
String desc = d instanceof Value ? "value" : "function";
me.addError(desc + " already specified by shortcut refinement: '" + d.getName(unit) + "'");
} else if (d instanceof Value && ((Value) d).isInferred()) {
me.addError("value is not a variable: '" + d.getName() + "'");
} else if (!mv.isVariable() && !mv.isLate()) {
String desc;
desc = d instanceof Value ? "value is neither variable nor late and" : "function";
if (mv.isToplevel()) {
me.addError("toplevel " + desc + " may not be specified: '" + d.getName(unit) + "'", 803);
} else if (!mv.isDefinedInScope(that.getScope())) {
me.addError(desc + " may not be specified here: '" + d.getName(unit) + "'", 803);
}
}
}
if (hasParams && d instanceof Function) {
Function f = (Function) d;
Tree.Expression se = rhs.getExpression();
if (f.isDeclaredVoid() && !isSatementExpression(se)) {
rhs.addError("function is declared void so specified expression must be a statement: '" + d.getName(unit) + "' is declared 'void'");
}
}
if (rhs instanceof Tree.LazySpecifierExpression && d instanceof Value) {
Value v = (Value) d;
v.setTransient(true);
}
Type lhst = lhs.getTypeModel();
if (!isTypeUnknown(lhst)) {
if (lhs == me && d instanceof Function && !lhst.isTypeConstructor()) {
// if the declaration of the method has
// defaulted parameters, we should ignore
// that when determining if the RHS is
// an acceptable implementation of the
// method
// TODO: this is a pretty nasty way to
// handle the problem
lhst = eraseDefaultedParameters(lhst);
}
TypedDeclaration member = that.getRefinement() ? that.getRefined() : td;
checkType(lhst, member, rhs, 2100);
}
}
if (lhs instanceof Tree.ParameterizedExpression) {
if (!(rhs instanceof Tree.LazySpecifierExpression)) {
rhs.addError("functions with parameters must be specified using =>");
}
} else {
if (rhs instanceof Tree.LazySpecifierExpression && d instanceof Function) {
rhs.addError("functions without parameters must be specified using =");
}
}
}
use of org.eclipse.ceylon.model.typechecker.model.Function in project ceylon by eclipse.
the class ExpressionVisitor method visit.
@Override
public void visit(Tree.MethodDefinition that) {
Function fun = that.getDeclarationModel();
Declaration od = beginReturnDeclaration(fun);
Tree.Type type = that.getType();
Tree.Type rt = beginReturnScope(type);
super.visit(that);
endReturnScope(rt, fun);
endReturnDeclaration(od);
if (type instanceof Tree.LocalModifier) {
if (isTypeUnknown(type.getTypeModel())) {
type.addError("function type could not be inferred");
}
}
}
use of org.eclipse.ceylon.model.typechecker.model.Function in project ceylon by eclipse.
the class RefinementVisitor method checkRefinement.
private void checkRefinement(Tree.Declaration that, Declaration member, ClassOrInterface type) {
Unit unit = that.getUnit();
String name = member.getName();
List<Type> signature = getSignature(member);
boolean variadic = isVariadic(member);
Declaration root = type.getRefinedMember(name, signature, variadic);
boolean legallyOverloaded = member.isNative() || !isOverloadedVersion(member) || isOverloadedVersion(root);
if (root == null || root.equals(member) || root.isNative() && member.isNative()) {
member.setRefinedDeclaration(member);
if (member.isActual() && !isNativeForWrongBackend(member)) {
that.addError("actual member does not refine any inherited member: " + message(member) + " is annotated 'actual' but '" + type.getName() + "' does not inherit any member named '" + name + "'", 1300);
} else if (!legallyOverloaded) {
that.addError("duplicate or overloaded member name: " + message(member));
} else {
List<Declaration> inheritedDeclarations = getInheritedDeclarations(name, type);
if (!inheritedDeclarations.isEmpty()) {
that.addError("duplicate or overloaded member name in type hierarchy: " + message(member) + " collides with " + message(inheritedDeclarations.get(0)));
}
}
} else {
member.setRefinedDeclaration(root);
if (!root.withinRestrictions(unit)) {
that.addError("refined declaration is not visible: " + message(member) + " refines " + message(root) + " which is restricted");
} else if (root.isPackageVisibility() && !declaredInPackage(root, unit)) {
that.addError("refined declaration is not visible: " + message(member) + " refines " + message(root) + " which is package private");
}
if (root.isCoercionPoint()) {
// FIXME: add message pointing to the real method?
that.addError("refined declaration is not a real method: " + message(member) + " refines " + message(root));
}
boolean found = false;
TypeDeclaration rootType = (TypeDeclaration) root.getContainer();
List<Declaration> interveningRefinements = getInterveningRefinements(member, root, type, rootType);
for (Declaration refined : interveningRefinements) {
TypeDeclaration interveningType = (TypeDeclaration) refined.getContainer();
if (interveningType.isJava() && atLeastOneJava(getInterveningRefinements(member, root, type, interveningType))) {
// inheritance of raw types)
continue;
}
if (isOverloadedVersion(refined)) {
// if this member is overloaded, the
// inherited member it refines must
// also be overloaded
legallyOverloaded = true;
}
found = true;
checkRefiningMember(that, refined, member, type);
}
if (!found) {
if (member instanceof Function && root instanceof Function) {
// see the condition in DeclarationVisitor.checkForDuplicateDeclaration()
that.addError("overloaded member does not exactly refine an inherited overloaded member: " + message(member, signature, variadic, unit) + " does not match any overloaded version of " + message(root));
}
} else if (!legallyOverloaded) {
that.addError("overloaded member does not exactly refine an inherited overloaded member: " + message(member, signature, variadic, unit) + " does not match any overloaded version of " + message(root));
}
}
}
use of org.eclipse.ceylon.model.typechecker.model.Function in project ceylon by eclipse.
the class RefinementVisitor method refineMethod.
private void refineMethod(Function assignedMethod, Tree.BaseMemberExpression bme, Tree.SpecifierStatement that, ClassOrInterface c) {
if (!assignedMethod.isFormal() && !assignedMethod.isDefault() && !assignedMethod.isShortcutRefinement()) {
// this condition is here to squash a dupe message
bme.addError("inherited method may not be refined: " + message(assignedMethod) + " is declared neither 'formal' nor 'default'", 510);
// return;
}
ClassOrInterface ci = (ClassOrInterface) assignedMethod.getContainer();
String name = assignedMethod.getName();
List<Type> signature = getSignature(assignedMethod);
boolean variadic = isVariadic(assignedMethod);
Declaration refined = ci.getRefinedMember(name, signature, variadic);
Function root = refined instanceof Function ? (Function) refined : assignedMethod;
Reference rm = getRefinedMemberReference(assignedMethod, c);
Function method = new Function();
method.setName(name);
List<Tree.ParameterList> paramLists;
List<TypeParameter> typeParams;
Tree.Term me = that.getBaseMemberExpression();
if (me instanceof Tree.ParameterizedExpression) {
Tree.ParameterizedExpression pe = (Tree.ParameterizedExpression) me;
paramLists = pe.getParameterLists();
Tree.TypeParameterList typeParameterList = pe.getTypeParameterList();
if (typeParameterList != null) {
typeParams = new ArrayList<TypeParameter>();
for (Tree.TypeParameterDeclaration tpd : typeParameterList.getTypeParameterDeclarations()) {
typeParams.add(tpd.getDeclarationModel());
}
} else {
typeParams = null;
}
} else {
paramLists = emptyList();
typeParams = null;
}
Unit unit = that.getUnit();
final Map<TypeParameter, Type> subs;
if (typeParams != null) {
// the type parameters are written
// down in the shortcut refinement
method.setTypeParameters(typeParams);
// TODO: check 'em!!
// no need to check them because
// this case is actually disallowed
// elsewhere (specification statements
// may not have type parameters)
subs = NO_SUBSTITUTIONS;
} else if (assignedMethod.isParameterized()) {
if (me instanceof Tree.ParameterizedExpression) {
// we have parameters, but no type parameters
bme.addError("refined method is generic: '" + assignedMethod.getName(unit) + "' declares type parameters");
subs = NO_SUBSTITUTIONS;
} else {
// we're assigning a method reference
// so we need to magic up some "fake"
// type parameters
subs = copyTypeParametersFromRefined(assignedMethod, method, unit);
}
} else {
subs = NO_SUBSTITUTIONS;
}
int i = 0;
for (ParameterList pl : assignedMethod.getParameterLists()) {
Tree.ParameterList params = paramLists.size() <= i ? null : paramLists.get(i++);
createRefiningParameterList(rm, method, params, unit, subs, pl);
}
method.setShared(true);
method.setActual(true);
method.getAnnotations().add(new Annotation("shared"));
method.getAnnotations().add(new Annotation("actual"));
method.setRefinedDeclaration(root);
method.setUnit(unit);
method.setContainer(c);
method.setScope(c);
method.setShortcutRefinement(true);
method.setDeclaredVoid(assignedMethod.isDeclaredVoid());
Declaration rmd = rm.getDeclaration();
if (rmd instanceof TypedDeclaration) {
TypedDeclaration rmtd = (TypedDeclaration) rmd;
method.setUncheckedNullType(rmtd.hasUncheckedNullType());
}
ModelUtil.setVisibleScope(method);
c.addMember(method);
that.setRefinement(true);
that.setDeclaration(method);
that.setRefined(root);
unit.addDeclaration(method);
Scope scope = that.getScope();
if (scope instanceof Specification) {
Specification spec = (Specification) scope;
spec.setDeclaration(method);
}
setRefiningType(c, ci, name, signature, variadic, root, method, unit, subs);
inheritDefaultedArguments(method);
}
use of org.eclipse.ceylon.model.typechecker.model.Function in project ceylon by eclipse.
the class SpecificationVisitor method visit.
@Override
public void visit(Tree.Constructor that) {
Function f = that.getDeclarationModel();
Constructor c = that.getConstructor();
if (f == declaration || c == declaration) {
declare();
specify();
}
super.visit(that);
if (declaration.getContainer() == c.getContainer() && that == lastConstructor && initedByEveryConstructor) {
definitely = true;
}
}
Aggregations