Search in sources :

Example 86 with Function

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 =");
        }
    }
}
Also used : AnalyzerUtil.getPackageTypedDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getPackageTypedDeclaration) AnalyzerUtil.getTypedDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTypedDeclaration) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) Function(org.eclipse.ceylon.model.typechecker.model.Function) ModelUtil.intersectionType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.intersectionType) ModelUtil.unionType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.unionType) AnalyzerUtil.spreadType(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.spreadType) AnalyzerUtil.getTupleType(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTupleType) Type(org.eclipse.ceylon.model.typechecker.model.Type) UnknownType(org.eclipse.ceylon.model.typechecker.model.UnknownType) ModelUtil.appliedType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType) ModelUtil.genericFunctionType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.genericFunctionType) Value(org.eclipse.ceylon.model.typechecker.model.Value) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue) CustomTree(org.eclipse.ceylon.compiler.typechecker.tree.CustomTree) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) AnalyzerUtil.getPackageTypedDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getPackageTypedDeclaration) AnalyzerUtil.getTypedDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTypedDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) AnalyzerUtil.getPackageTypeDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getPackageTypeDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) ModelUtil.getNativeDeclaration(org.eclipse.ceylon.model.typechecker.model.ModelUtil.getNativeDeclaration) AnalyzerUtil.getTypeDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTypeDeclaration) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)

Example 87 with Function

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");
        }
    }
}
Also used : Function(org.eclipse.ceylon.model.typechecker.model.Function) CustomTree(org.eclipse.ceylon.compiler.typechecker.tree.CustomTree) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) AnalyzerUtil.getPackageTypedDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getPackageTypedDeclaration) AnalyzerUtil.getTypedDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTypedDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) AnalyzerUtil.getPackageTypeDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getPackageTypeDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) ModelUtil.getNativeDeclaration(org.eclipse.ceylon.model.typechecker.model.ModelUtil.getNativeDeclaration) AnalyzerUtil.getTypeDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTypeDeclaration)

Example 88 with Function

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));
        }
    }
}
Also used : Function(org.eclipse.ceylon.model.typechecker.model.Function) IntersectionType(org.eclipse.ceylon.model.typechecker.model.IntersectionType) ModelUtil.intersectionType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.intersectionType) LazyType(org.eclipse.ceylon.model.typechecker.model.LazyType) Type(org.eclipse.ceylon.model.typechecker.model.Type) ModelUtil.erasedType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.erasedType) Collections.emptyList(java.util.Collections.emptyList) List(java.util.List) ParameterList(org.eclipse.ceylon.model.typechecker.model.ParameterList) ArrayList(java.util.ArrayList) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) AnalyzerUtil.getTypedDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTypedDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) Unit(org.eclipse.ceylon.model.typechecker.model.Unit) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)

Example 89 with Function

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);
}
Also used : ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) Unit(org.eclipse.ceylon.model.typechecker.model.Unit) Function(org.eclipse.ceylon.model.typechecker.model.Function) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) AnalyzerUtil.getTypedDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTypedDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) AnalyzerUtil.getTypedDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTypedDeclaration) ExpressionVisitor.getRefinedMemberReference(org.eclipse.ceylon.compiler.typechecker.analyzer.ExpressionVisitor.getRefinedMemberReference) Reference(org.eclipse.ceylon.model.typechecker.model.Reference) Specification(org.eclipse.ceylon.model.typechecker.model.Specification) Annotation(org.eclipse.ceylon.model.typechecker.model.Annotation) IntersectionType(org.eclipse.ceylon.model.typechecker.model.IntersectionType) ModelUtil.intersectionType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.intersectionType) LazyType(org.eclipse.ceylon.model.typechecker.model.LazyType) Type(org.eclipse.ceylon.model.typechecker.model.Type) ModelUtil.erasedType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.erasedType) Scope(org.eclipse.ceylon.model.typechecker.model.Scope) ModelUtil.getRealScope(org.eclipse.ceylon.model.typechecker.model.ModelUtil.getRealScope) ParameterList(org.eclipse.ceylon.model.typechecker.model.ParameterList)

Example 90 with Function

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;
    }
}
Also used : Function(org.eclipse.ceylon.model.typechecker.model.Function) AnalyzerUtil.getLastConstructor(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getLastConstructor) ModelUtil.isConstructor(org.eclipse.ceylon.model.typechecker.model.ModelUtil.isConstructor) Constructor(org.eclipse.ceylon.model.typechecker.model.Constructor)

Aggregations

Function (org.eclipse.ceylon.model.typechecker.model.Function)167 TypeDeclaration (org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)71 Declaration (org.eclipse.ceylon.model.typechecker.model.Declaration)70 TypedDeclaration (org.eclipse.ceylon.model.typechecker.model.TypedDeclaration)69 Type (org.eclipse.ceylon.model.typechecker.model.Type)68 Tree (org.eclipse.ceylon.compiler.typechecker.tree.Tree)62 TypeParameter (org.eclipse.ceylon.model.typechecker.model.TypeParameter)57 Value (org.eclipse.ceylon.model.typechecker.model.Value)50 FunctionOrValue (org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)46 Parameter (org.eclipse.ceylon.model.typechecker.model.Parameter)43 Class (org.eclipse.ceylon.model.typechecker.model.Class)39 ArrayList (java.util.ArrayList)32 ParameterList (org.eclipse.ceylon.model.typechecker.model.ParameterList)29 JCExpression (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression)26 Constructor (org.eclipse.ceylon.model.typechecker.model.Constructor)23 Scope (org.eclipse.ceylon.model.typechecker.model.Scope)23 TypedReference (org.eclipse.ceylon.model.typechecker.model.TypedReference)23 UnknownType (org.eclipse.ceylon.model.typechecker.model.UnknownType)23 ClassOrInterface (org.eclipse.ceylon.model.typechecker.model.ClassOrInterface)22 ModelUtil.appliedType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType)21