use of org.eclipse.ceylon.model.typechecker.model.TypedDeclaration 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.TypedDeclaration in project ceylon by eclipse.
the class RefinementVisitor method checkRefinedMemberTypeExactly.
private void checkRefinedMemberTypeExactly(Reference refiningMember, Reference refinedMember, Node that, Declaration refined, Declaration refining) {
Unit unit = that.getUnit();
Type refiningType = refiningMember.getType();
Type refinedType = refinedMember.getType();
if (!isTypeUnknown(refinedType)) {
if (that instanceof Tree.LocalModifier) {
TypedDeclaration td = (TypedDeclaration) refining;
Tree.LocalModifier mod = (Tree.LocalModifier) that;
Type t;
if (isTypeUnknown(refiningType)) {
t = refinedType;
td.setType(t);
mod.setTypeModel(t);
} else {
checkIsExactly(refiningType, refinedType, that, "inferred type of member must be exactly the same as type of variable refined member: " + message(refined), 9000);
}
return;
}
checkIsExactlyIgnoringNull(refined, refiningType, refinedType, that, "type of member must be exactly the same as type of variable refined member: " + message(refined), 9000);
}
}
use of org.eclipse.ceylon.model.typechecker.model.TypedDeclaration in project ceylon by eclipse.
the class RefinementVisitor method refineAttribute.
private void refineAttribute(Value assignedAttribute, Tree.BaseMemberExpression bme, Tree.SpecifierStatement that, ClassOrInterface c) {
if (!assignedAttribute.isFormal() && !assignedAttribute.isDefault() && !assignedAttribute.isShortcutRefinement()) {
// this condition is here to squash a dupe message
that.addError("inherited attribute may not be assigned in initializer and may not be refined: " + message(assignedAttribute) + " is declared neither 'formal' nor 'default'", 510);
// return;
} else if (assignedAttribute.isVariable()) {
that.addError("inherited attribute may not be assigned in initializer and may not be refined by non-variable: " + message(assignedAttribute) + " is declared 'variable'");
// return;
}
ClassOrInterface ci = (ClassOrInterface) assignedAttribute.getContainer();
String name = assignedAttribute.getName();
Declaration refined = ci.getRefinedMember(name, null, false);
Value root = refined instanceof Value ? (Value) refined : assignedAttribute;
Reference rv = getRefinedMemberReference(assignedAttribute, c);
boolean lazy = that.getSpecifierExpression() instanceof Tree.LazySpecifierExpression;
Value attribute = new Value();
attribute.setName(name);
attribute.setShared(true);
attribute.setActual(true);
attribute.getAnnotations().add(new Annotation("shared"));
attribute.getAnnotations().add(new Annotation("actual"));
attribute.setRefinedDeclaration(root);
Unit unit = that.getUnit();
attribute.setUnit(unit);
attribute.setContainer(c);
attribute.setScope(c);
attribute.setShortcutRefinement(true);
attribute.setTransient(lazy);
Declaration rvd = rv.getDeclaration();
if (rvd instanceof TypedDeclaration) {
TypedDeclaration rvtd = (TypedDeclaration) rvd;
attribute.setUncheckedNullType(rvtd.hasUncheckedNullType());
}
ModelUtil.setVisibleScope(attribute);
c.addMember(attribute);
that.setRefinement(true);
that.setDeclaration(attribute);
that.setRefined(assignedAttribute);
unit.addDeclaration(attribute);
setRefiningType(c, ci, name, null, false, root, attribute, unit, NO_SUBSTITUTIONS);
}
use of org.eclipse.ceylon.model.typechecker.model.TypedDeclaration in project ceylon by eclipse.
the class RefinementVisitor method checkRefinedMemberTypeAssignable.
private void checkRefinedMemberTypeAssignable(Reference refiningMember, Reference refinedMember, Node that, Declaration refined, Declaration refining) {
Unit unit = that.getUnit();
Type refiningType = refiningMember.getType();
Type refinedType = refinedMember.getType();
if (!isTypeUnknown(refinedType)) {
if (that instanceof Tree.LocalModifier) {
// infer the type of an actual member
// by taking the intersection of all
// members it refines
// NOTE: feature not blessed by the spec!
TypedDeclaration td = (TypedDeclaration) refining;
Tree.LocalModifier mod = (Tree.LocalModifier) that;
Type t;
t = isTypeUnknown(refiningType) ? refinedType : intersectionType(refinedType, refiningType, unit);
td.setType(t);
mod.setTypeModel(t);
return;
}
checkAssignableIgnoringNull(refiningType, refinedType, that, refined, "type of member must be assignable to type of refined member " + message(refined), 9000);
checkSmallRefinement(that, refiningMember.getDeclaration(), refinedMember.getDeclaration());
}
}
use of org.eclipse.ceylon.model.typechecker.model.TypedDeclaration 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);
}
Aggregations