Search in sources :

Example 51 with FunctionOrValue

use of org.eclipse.ceylon.model.typechecker.model.FunctionOrValue in project ceylon by eclipse.

the class JsonPackage method parseParameters.

/**
 * Creates a parameter list from a list of maps where each map represents a parameter.
 * @param params The list of maps to create the parameters.
 * @param owner The declaration to assign to each parameter.
 * @param typeParameters The type parameters which can be referenced from the parameters.
 */
private ParameterList parseParameters(List<Map<String, Object>> params, Declaration owner, List<TypeParameter> typeParameters) {
    ParameterList plist = new ParameterList();
    if (params != null) {
        for (Map<String, Object> p : params) {
            Parameter param = new Parameter();
            final String paramtype = (String) p.get("$pt");
            param.setHidden(p.containsKey("$hdn"));
            param.setName((String) p.get(KEY_NAME));
            param.setDeclaration(owner);
            param.setDefaulted(p.containsKey(KEY_DEFAULT));
            param.setSequenced(p.containsKey("seq"));
            param.setAtLeastOne(p.containsKey("$min1"));
            if (paramtype == null || "v".equals(paramtype)) {
                Value _v = new Value();
                param.setModel(_v);
            } else if ("f".equals(paramtype)) {
                @SuppressWarnings("unchecked") List<List<Map<String, Object>>> paramLists = (List<List<Map<String, Object>>>) p.get(KEY_PARAMS);
                Function _m = new Function();
                param.setModel(_m);
                if (paramLists == null) {
                    _m.addParameterList(new ParameterList());
                } else {
                    boolean first = true;
                    for (List<Map<String, Object>> subplist : paramLists) {
                        ParameterList _params = parseParameters(subplist, _m, typeParameters);
                        if (first) {
                            first = false;
                        } else {
                            _params.setNamedParametersSupported(false);
                        }
                        _m.addParameterList(_params);
                    }
                }
            } else {
                throw new IllegalArgumentException("Unknown parameter type " + paramtype);
            }
            FunctionOrValue paramModel = param.getModel();
            if (paramModel != null) {
                paramModel.setInitializerParameter(param);
                paramModel.setName(param.getName());
                paramModel.setUnit(u2);
                if (owner instanceof Scope) {
                    Scope scope = (Scope) owner;
                    paramModel.setContainer(scope);
                    paramModel.setScope(scope);
                }
                if (p.get(KEY_TYPE) instanceof Map) {
                    @SuppressWarnings("unchecked") final Map<String, Object> ktype = (Map<String, Object>) p.get(KEY_TYPE);
                    paramModel.setType(getTypeFromJson(ktype, owner, typeParameters));
                } else {
                    // parameter type
                    for (TypeParameter tp : typeParameters) {
                        if (tp.getName().equals(p.get(KEY_TYPE))) {
                            paramModel.setType(tp.getType());
                        }
                    }
                }
                setAnnotations(paramModel, (Integer) p.remove(KEY_PACKED_ANNS), p.remove(KEY_ANNOTATIONS));
            }
            // owner.getMembers().add(param);
            plist.getParameters().add(param);
        }
    }
    return plist;
}
Also used : TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) Function(org.eclipse.ceylon.model.typechecker.model.Function) Scope(org.eclipse.ceylon.model.typechecker.model.Scope) Value(org.eclipse.ceylon.model.typechecker.model.Value) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue) ParameterList(org.eclipse.ceylon.model.typechecker.model.ParameterList) Parameter(org.eclipse.ceylon.model.typechecker.model.Parameter) TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) List(java.util.List) ParameterList(org.eclipse.ceylon.model.typechecker.model.ParameterList) ArrayList(java.util.ArrayList) Map(java.util.Map) HashMap(java.util.HashMap) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)

Example 52 with FunctionOrValue

use of org.eclipse.ceylon.model.typechecker.model.FunctionOrValue in project ceylon by eclipse.

the class JsonPackage method getTypeFromJson.

/**
 * Looks up a type from model data, creating it if necessary. The returned type will have its
 * type parameters substituted if needed.
 */
private Type getTypeFromJson(Map<String, Object> m, Declaration container, List<TypeParameter> typeParams) {
    TypeDeclaration td = null;
    if (m.get(KEY_METATYPE) instanceof TypeDeclaration) {
        td = (TypeDeclaration) m.get(KEY_METATYPE);
        if (td instanceof ClassOrInterface && td.getUnit().getPackage() instanceof JsonPackage) {
            ((JsonPackage) td.getUnit().getPackage()).load(td.getName(), typeParams);
        }
    }
    final String tname = (String) m.get(KEY_NAME);
    if ("$U".equals(tname)) {
        m.put(KEY_METATYPE, unknown);
        return unknown.getType();
    }
    if (td == null && m.containsKey("comp")) {
        @SuppressWarnings("unchecked") final List<Map<String, Object>> tmaps = (List<Map<String, Object>>) m.get(KEY_TYPES);
        final ArrayList<Type> types = new ArrayList<>(tmaps.size());
        if ("u".equals(m.get("comp"))) {
            UnionType ut = new UnionType(u2);
            for (Map<String, Object> tmap : tmaps) {
                types.add(getTypeFromJson(tmap, container, typeParams));
            }
            ut.setCaseTypes(types);
            td = ut;
        } else if ("i".equals(m.get("comp"))) {
            IntersectionType it = new IntersectionType(u2);
            for (Map<String, Object> tmap : tmaps) {
                types.add(getTypeFromJson(tmap, container, typeParams));
            }
            it.setSatisfiedTypes(types);
            td = it;
        } else {
            throw new IllegalArgumentException("Invalid composite type '" + m.get("comp") + "'");
        }
    } else if (td == null) {
        final String pname = (String) m.get(KEY_PACKAGE);
        if (pname == null) {
            // It's a ref to a type parameter
            final List<TypeParameter> containerTypeParameters;
            if (container instanceof Constructor) {
                containerTypeParameters = ((Generic) container.getContainer()).getTypeParameters();
            } else if (container instanceof Generic) {
                containerTypeParameters = container.getTypeParameters();
            } else {
                containerTypeParameters = null;
            }
            if (containerTypeParameters != null) {
                for (TypeParameter typeParam : containerTypeParameters) {
                    if (typeParam.getName().equals(tname)) {
                        td = typeParam;
                    }
                }
            }
            if (td == null && typeParams != null) {
                for (TypeParameter typeParam : typeParams) {
                    if (typeParam.getName().equals(tname)) {
                        td = typeParam;
                    }
                }
            }
        } else {
            String mname = (String) m.get(KEY_MODULE);
            if ("$".equals(mname)) {
                mname = LANGUAGE_MODULE_NAME;
            }
            org.eclipse.ceylon.model.typechecker.model.Package rp;
            if ("$".equals(pname) || LANGUAGE_MODULE_NAME.equals(pname)) {
                // Language module package
                rp = isLanguagePackage() ? this : getModule().getLanguageModule().getDirectPackage(LANGUAGE_MODULE_NAME);
            } else if (mname == null) {
                // local type
                if (".".equals(pname)) {
                    rp = this;
                    if (container instanceof TypeDeclaration && tname.equals(container.getName())) {
                        td = (TypeDeclaration) container;
                    }
                } else {
                    rp = getModule().getDirectPackage(pname);
                }
            } else {
                rp = getModule().getPackage(pname);
            }
            if (rp == null) {
                throw new CompilerErrorException("Package not found: " + pname);
            }
            if (rp != this && rp instanceof JsonPackage && !((JsonPackage) rp).loaded) {
                ((JsonPackage) rp).loadIfNecessary();
            }
            final boolean nested = tname.indexOf('.') > 0;
            final String level1 = nested ? tname.substring(0, tname.indexOf('.')) : tname;
            if (rp != null && !nested) {
                Declaration d = rp.getDirectMember(tname, null, false);
                if (d instanceof TypeDeclaration) {
                    td = (TypeDeclaration) d;
                    if (td.isTuple()) {
                        if (m.containsKey(KEY_TYPES)) {
                            @SuppressWarnings("unchecked") List<Map<String, Object>> elemaps = (List<Map<String, Object>>) m.get(KEY_TYPES);
                            ArrayList<Type> elems = new ArrayList<>(elemaps.size());
                            for (Map<String, Object> elem : elemaps) {
                                elems.add(getTypeFromJson(elem, container, typeParams));
                            }
                            Type tail = elems.get(elems.size() - 1);
                            if ((tail.isSequence() || tail.isSequential()) && !tail.isTuple() && !tail.isEmpty()) {
                                elems.remove(elems.size() - 1);
                            } else {
                                tail = null;
                            }
                            return u2.getTupleType(elems, tail, -1);
                        } else if (m.containsKey("count")) {
                            @SuppressWarnings("unchecked") Map<String, Object> elem = (Map<String, Object>) m.get(KEY_TYPE);
                            Type[] elems = new Type[(int) m.remove("count")];
                            Arrays.fill(elems, getTypeFromJson(elem, container, typeParams));
                            return u2.getTupleType(Arrays.asList(elems), null, -1);
                        }
                    }
                } else if (d instanceof FunctionOrValue) {
                    td = ((FunctionOrValue) d).getTypeDeclaration();
                }
            }
            if (td == null && rp instanceof JsonPackage) {
                if (nested) {
                    td = ((JsonPackage) rp).loadNestedType(tname, typeParams);
                } else {
                    td = (TypeDeclaration) ((JsonPackage) rp).load(tname, typeParams);
                }
            }
            // Then look in the top-level declarations
            if (nested && td == null) {
                for (Declaration d : rp.getMembers()) {
                    if (d instanceof TypeDeclaration && level1.equals(d.getName())) {
                        td = (TypeDeclaration) d;
                    }
                }
                final String[] path = tname.split("\\.");
                for (int i = 1; i < path.length; i++) {
                    td = (TypeDeclaration) td.getDirectMember(path[i], null, false);
                }
            }
        }
    }
    // From 1.2.3 we stored type arguments in maps
    final Type newType = loadTypeArguments(m, td, container, typeParams);
    if (newType != null) {
        return newType;
    }
    // This is the old pre 1.2.3 stuff
    @SuppressWarnings("unchecked") final List<Map<String, Object>> modelParms = (List<Map<String, Object>>) m.get(KEY_TYPE_PARAMS);
    if (td != null && modelParms != null) {
        // Substitute type parameters
        final HashMap<TypeParameter, Type> concretes = new HashMap<>();
        HashMap<TypeParameter, SiteVariance> variances = null;
        if (td.getTypeParameters().size() < modelParms.size()) {
            if (td.getUnit().getPackage() == this) {
                parseTypeParameters(modelParms, td, null);
            }
        }
        final Iterator<TypeParameter> viter = td.getTypeParameters().iterator();
        for (Map<String, Object> ptparm : modelParms) {
            TypeParameter _cparm = viter.next();
            if (ptparm.containsKey(KEY_PACKAGE) || ptparm.containsKey(KEY_TYPES)) {
                // Substitute for proper type
                final Type _pt = getTypeFromJson(ptparm, container, typeParams);
                concretes.put(_cparm, _pt);
            } else if (ptparm.containsKey(KEY_NAME) && typeParams != null) {
                // Look for type parameter with same name
                for (TypeParameter typeParam : typeParams) {
                    if (typeParam.getName().equals(ptparm.get(KEY_NAME))) {
                        concretes.put(_cparm, typeParam.getType());
                    }
                }
            }
            Integer usv = (Integer) ptparm.get(KEY_US_VARIANCE);
            if (usv != null) {
                if (variances == null) {
                    variances = new HashMap<>();
                }
                variances.put(_cparm, SiteVariance.values()[usv]);
            }
        }
        if (!concretes.isEmpty()) {
            return td.getType().substitute(concretes, variances);
        }
    }
    if (td == null) {
        try {
            throw new IllegalArgumentException(String.format("Couldn't find type %s::%s for %s in %s<%s> (FROM pkg %s)", m.get(KEY_PACKAGE), m.get(KEY_NAME), m.get(KEY_MODULE), m, typeParams, getNameAsString()));
        } catch (IllegalArgumentException ex) {
            ex.printStackTrace();
        }
    }
    return td.getType();
}
Also used : ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) UnionType(org.eclipse.ceylon.model.typechecker.model.UnionType) TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) HashMap(java.util.HashMap) Generic(org.eclipse.ceylon.model.typechecker.model.Generic) ArrayList(java.util.ArrayList) List(java.util.List) ParameterList(org.eclipse.ceylon.model.typechecker.model.ParameterList) ArrayList(java.util.ArrayList) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) CompilerErrorException(org.eclipse.ceylon.compiler.js.CompilerErrorException) Constructor(org.eclipse.ceylon.model.typechecker.model.Constructor) IntersectionType(org.eclipse.ceylon.model.typechecker.model.IntersectionType) NothingType(org.eclipse.ceylon.model.typechecker.model.NothingType) UnionType(org.eclipse.ceylon.model.typechecker.model.UnionType) Type(org.eclipse.ceylon.model.typechecker.model.Type) UnknownType(org.eclipse.ceylon.model.typechecker.model.UnknownType) IntersectionType(org.eclipse.ceylon.model.typechecker.model.IntersectionType) SiteVariance(org.eclipse.ceylon.model.typechecker.model.SiteVariance) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Map(java.util.Map) HashMap(java.util.HashMap) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)

Example 53 with FunctionOrValue

use of org.eclipse.ceylon.model.typechecker.model.FunctionOrValue in project ceylon by eclipse.

the class TestModuleManager method compareMembers.

private void compareMembers(Declaration m1, Declaration m2) {
    if (m1 instanceof FunctionOrValue) {
        return;
    } else if (m1.getMembers() == null) {
        Assert.assertNull(m2.getMembers());
        return;
    }
    if (m1.getMembers().size() != m2.getMembers().size()) {
        System.out.println(m1 + " (src) tiene " + m1.getMembers());
        System.out.println(m2 + " (js)  tiene " + m2.getMembers());
    }
    Assert.assertEquals(m1 + " member count", m1.getMembers().size(), m2.getMembers().size());
    for (Declaration d0 : m1.getMembers()) {
        String n = d0.getQualifiedNameString();
        if (n.indexOf('.') < 0) {
            n += "(" + d0.getContainer().getQualifiedNameString() + ")";
        }
        Declaration d1 = findMatchingDeclaration(d0, m2.getMembers());
        Assert.assertNotNull(n + " not found in " + m2, d1);
        Assert.assertEquals(n + " declaration kinds differ", d0.getDeclarationKind(), d1.getDeclarationKind());
        if (d0.getContainer() == null) {
            Assert.assertNull(d1.getContainer());
        } else {
            Assert.assertEquals(d0.getContainer().getQualifiedNameString(), d1.getContainer().getQualifiedNameString());
        }
        if (d0 instanceof TypeDeclaration) {
            Assert.assertEquals(d0.getClass(), d1.getClass());
            compareTypeDeclarations((TypeDeclaration) d0, (TypeDeclaration) d1);
        }
        compareMembers(d0, d1);
    }
}
Also used : TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)

Example 54 with FunctionOrValue

use of org.eclipse.ceylon.model.typechecker.model.FunctionOrValue in project ceylon by eclipse.

the class MethodOrValueReferenceVisitor method visitConstructorPlan.

/**
 * Marks declarations as captured if they are used in more than one generated constructor, according
 * to the given plan and knowledge on how we split up constructor delegates.
 */
private void visitConstructorPlan(ConstructorPlan constructorPlan) {
    // if there is no delegation all statements are put in the same method so we can't capture
    if (constructorPlan.delegate == null && !constructorPlan.isDelegate)
        return;
    boolean cs = enterCapturingScope();
    int useCount = usedIn(constructorPlan, false);
    FunctionOrValue fov = ((FunctionOrValue) declaration);
    fov.setCaptured(useCount > 1);
    if (fov instanceof Value) {
        Value val = (Value) fov;
        if (val.getSetter() != null)
            val.getSetter().setCaptured(useCount > 1);
    }
    exitCapturingScope(cs);
}
Also used : FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue) Value(org.eclipse.ceylon.model.typechecker.model.Value) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)

Example 55 with FunctionOrValue

use of org.eclipse.ceylon.model.typechecker.model.FunctionOrValue in project ceylon by eclipse.

the class MethodOrValueReferenceVisitor method usedIn.

/**
 * Returns 1 if the declaration is captured in the given statements, 0 otherwise.
 */
private int usedIn(List<Statement> stmts) {
    for (Tree.Statement stmt : stmts) {
        // count declarations as usage
        if (stmt instanceof Tree.TypedDeclaration) {
            Tree.TypedDeclaration td = (Tree.TypedDeclaration) stmt;
            if (td.getDeclarationModel() == declaration)
                return 1;
        }
        stmt.visit(this);
        if (declaration.isCaptured())
            break;
    }
    boolean used = declaration.isCaptured();
    FunctionOrValue fov = (FunctionOrValue) declaration;
    fov.setCaptured(false);
    if (fov instanceof Value) {
        Value val = (Value) fov;
        if (val.getSetter() != null)
            val.getSetter().setCaptured(false);
    }
    return used ? 1 : 0;
}
Also used : TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) Statement(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Statement) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue) Value(org.eclipse.ceylon.model.typechecker.model.Value) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)

Aggregations

FunctionOrValue (org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)65 Declaration (org.eclipse.ceylon.model.typechecker.model.Declaration)28 TypedDeclaration (org.eclipse.ceylon.model.typechecker.model.TypedDeclaration)27 TypeDeclaration (org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)26 Type (org.eclipse.ceylon.model.typechecker.model.Type)25 Value (org.eclipse.ceylon.model.typechecker.model.Value)24 Tree (org.eclipse.ceylon.compiler.typechecker.tree.Tree)22 Function (org.eclipse.ceylon.model.typechecker.model.Function)22 Parameter (org.eclipse.ceylon.model.typechecker.model.Parameter)21 TypeParameter (org.eclipse.ceylon.model.typechecker.model.TypeParameter)19 UnknownType (org.eclipse.ceylon.model.typechecker.model.UnknownType)13 ArrayList (java.util.ArrayList)12 CustomTree (org.eclipse.ceylon.compiler.typechecker.tree.CustomTree)11 TypedReference (org.eclipse.ceylon.model.typechecker.model.TypedReference)10 AnalyzerUtil.getTupleType (org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTupleType)9 AnalyzerUtil.spreadType (org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.spreadType)9 ModelUtil.appliedType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType)9 ModelUtil.genericFunctionType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.genericFunctionType)9 ModelUtil.intersectionType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.intersectionType)9 ModelUtil.unionType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.unionType)9