use of org.eclipse.ceylon.model.typechecker.model.Specification in project ceylon by eclipse.
the class CodegenUtil method isContainerFunctionalParameter.
public static boolean isContainerFunctionalParameter(Declaration declaration) {
Scope containerScope = declaration.getContainer();
Declaration containerDeclaration;
if (containerScope instanceof Specification) {
containerDeclaration = ((Specification) containerScope).getDeclaration();
} else if (containerScope instanceof Declaration) {
containerDeclaration = (Declaration) containerScope;
} else {
// probably invalid user code
return false;
}
return containerDeclaration instanceof Function && ((Function) containerDeclaration).isParameter();
}
use of org.eclipse.ceylon.model.typechecker.model.Specification in project ceylon by eclipse.
the class JvmBackendUtil method getTopmostRefinedDeclaration.
public static Declaration getTopmostRefinedDeclaration(Declaration decl, Map<Function, Function> methodOverrides) {
if (decl instanceof FunctionOrValue && ((FunctionOrValue) decl).isParameter() && decl.getContainer() instanceof Class) {
// Parameters in a refined class are not considered refinements themselves
// We have in find the refined attribute
Class c = (Class) decl.getContainer();
boolean isAlias = c.isAlias();
boolean isActual = c.isActual();
// boxing and stuff
if (isAlias || isActual) {
Functional ctor = null;
int index = c.getParameterList().getParameters().indexOf(findParamForDecl(((TypedDeclaration) decl)));
// Note(Stef): not entirely sure about that one, what about aliases of actual classes?
while ((isAlias && c.isAlias()) || (isActual && c.isActual())) {
ctor = (isAlias && c.isAlias()) ? (Functional) ((ClassAlias) c).getConstructor() : c;
Type et = c.getExtendedType();
c = et != null && et.isClass() ? (Class) et.getDeclaration() : null;
// handle compile errors
if (c == null)
return null;
}
if (isActual) {
ctor = c;
}
// be safe
if (ctor == null || ctor.getParameterLists() == null || ctor.getParameterLists().isEmpty() || ctor.getFirstParameterList() == null || ctor.getFirstParameterList().getParameters() == null || ctor.getFirstParameterList().getParameters().size() <= index)
return null;
decl = ctor.getFirstParameterList().getParameters().get(index).getModel();
}
if (decl.isShared()) {
Declaration refinedDecl = c.getRefinedMember(decl.getName(), getSignature(decl), isVariadic(decl));
if (refinedDecl != null && !ModelUtil.equal(refinedDecl, decl)) {
return getTopmostRefinedDeclaration(refinedDecl, methodOverrides);
}
}
return decl;
} else if (decl instanceof FunctionOrValue && // a parameter
((FunctionOrValue) decl).isParameter() && (// that's not parameter of a functional parameter
(decl.getContainer() instanceof Function && !(((Function) decl.getContainer()).isParameter())) || // or is a parameter in a specification
decl.getContainer() instanceof Specification || (decl.getContainer() instanceof Function && ((Function) decl.getContainer()).isParameter() && createMethod((Function) decl.getContainer())))) {
// or is a class functional parameter
// Parameters in a refined method are not considered refinements themselves
// so we have to look up the corresponding parameter in the container's refined declaration
Functional func = (Functional) getParameterized((FunctionOrValue) decl);
if (func == null)
return decl;
Declaration kk = getTopmostRefinedDeclaration((Declaration) func, methodOverrides);
// error recovery
if (kk instanceof Functional == false)
return decl;
Functional refinedFunc = (Functional) kk;
// shortcut if the functional doesn't override anything
if (ModelUtil.equal((Declaration) refinedFunc, (Declaration) func)) {
return decl;
}
if (func.getParameterLists().size() != refinedFunc.getParameterLists().size()) {
// invalid input
return decl;
}
for (int ii = 0; ii < func.getParameterLists().size(); ii++) {
if (func.getParameterLists().get(ii).getParameters().size() != refinedFunc.getParameterLists().get(ii).getParameters().size()) {
// invalid input
return decl;
}
// find the index of the parameter in the declaration
int index = 0;
for (Parameter px : func.getParameterLists().get(ii).getParameters()) {
if (px.getModel() == null || px.getModel().equals(decl)) {
// And return the corresponding parameter from the refined declaration
return refinedFunc.getParameterLists().get(ii).getParameters().get(index).getModel();
}
index++;
}
continue;
}
} else if (methodOverrides != null && decl instanceof Function && ModelUtil.equal(decl.getRefinedDeclaration(), decl) && decl.getContainer() instanceof Specification && ((Specification) decl.getContainer()).getDeclaration() instanceof Function && ((Function) ((Specification) decl.getContainer()).getDeclaration()).isShortcutRefinement() && // hash lookup we do next to make sure it is really one of those cases
methodOverrides.containsKey(decl)) {
// special case for class X() extends T(){ m = function() => e; } which we inline
decl = methodOverrides.get(decl);
}
Declaration refinedDecl = decl.getRefinedDeclaration();
if (refinedDecl != null && !ModelUtil.equal(refinedDecl, decl))
return getTopmostRefinedDeclaration(refinedDecl);
return decl;
}
use of org.eclipse.ceylon.model.typechecker.model.Specification 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.Specification in project ceylon by eclipse.
the class DeclarationVisitor method visit.
@Override
public void visit(Tree.SpecifierStatement that) {
Tree.Term lhs = that.getBaseMemberExpression();
if (lhs instanceof Tree.ParameterizedExpression) {
Tree.ParameterizedExpression pe = (Tree.ParameterizedExpression) lhs;
pe.setLeftTerm(true);
}
Specification s = new Specification();
s.setId(id++);
visitElement(that, s);
Scope o = enterScope(s);
super.visit(that);
exitScope(o);
}
Aggregations