Search in sources :

Example 1 with DictType

use of org.yinwang.pysonar.types.DictType in project pysonar2 by yinwang0.

the class TypeInferencer method apply.

@NotNull
public Type apply(@NotNull FunType func, @Nullable Type selfType, @Nullable List<Type> positional, @Nullable Map<String, Type> kwTypes, @Nullable Type kwArg, @Nullable Type starArg, @Nullable Node call) {
    if (call instanceof Call && ((Call) call).func instanceof Attribute && ((Attribute) ((Call) call).func).attr.id.equals("append")) {
        if (selfType instanceof ListType) {
            ListType listType = (ListType) selfType;
            if (positional != null && positional.size() == 1) {
                listType.add(positional.get(0));
            } else {
                Analyzer.self.putProblem(call, "Calling append with wrong argument types");
            }
        }
    }
    if (call instanceof Call && ((Call) call).func instanceof Attribute && ((Attribute) ((Call) call).func).attr.id.equals("update")) {
        if (selfType instanceof DictType) {
            DictType dict = (DictType) selfType;
            if (positional != null && positional.size() == 1) {
                Type argType = positional.get(0);
                if (argType instanceof DictType) {
                    dict.keyType = UnionType.union(dict.keyType, ((DictType) argType).keyType);
                    dict.valueType = UnionType.union(dict.valueType, ((DictType) argType).valueType);
                }
            } else {
                Analyzer.self.putProblem(call, "Calling update with wrong argument types");
            }
        }
    }
    Analyzer.self.removeUncalled(func);
    if (func.func != null && !func.func.called) {
        Analyzer.self.nCalled++;
        func.func.called = true;
    }
    if (func.func == null) {
        // func without definition (possibly builtins)
        return func.getReturnType();
    }
    List<Type> argTypes = new ArrayList<>();
    // Add class or object as first argument if it is not static method
    if (!func.func.isStaticMethod()) {
        if (func.func.isClassMethod()) {
            if (func.cls != null) {
                argTypes.add(func.cls);
            } else if (selfType != null && selfType instanceof InstanceType) {
                argTypes.add(((InstanceType) selfType).classType);
            }
        } else {
            // usual method
            if (selfType != null) {
                argTypes.add(selfType);
            } else {
                if (func.cls != null) {
                    if (!func.func.name.id.equals("__init__")) {
                        argTypes.add(func.cls.getInstance(null, this, call));
                    } else {
                        argTypes.add(func.cls.getInstance());
                    }
                }
            }
        }
    }
    // Put in positional arguments
    if (positional != null) {
        argTypes.addAll(positional);
    }
    bindMethodAttrs(func);
    State callState = new State(func.env, State.StateType.FUNCTION);
    if (func.table.parent != null) {
        callState.setPath(func.table.parent.extendPath(func.func.name.id));
    } else {
        callState.setPath(func.func.name.id);
    }
    Type fromType = bindParams(callState, func.func, argTypes, func.defaultTypes, kwTypes, kwArg, starArg);
    Type cachedTo = func.getMapping(fromType);
    if (cachedTo != null) {
        return cachedTo;
    } else if (func.oversized()) {
        return Types.UNKNOWN;
    } else {
        func.addMapping(fromType, Types.UNKNOWN);
        Analyzer.self.callStack.push(new CallStackEntry(func, fromType));
        Type toType = visit(func.func.body, callState);
        Analyzer.self.callStack.pop();
        if (missingReturn(toType)) {
            addWarningToNode(func.func.name, "Function not always return a value");
            if (call != null) {
                addWarningToNode(call, "Call not always return a value");
            }
        }
        toType = UnionType.remove(toType, Types.CONT);
        if (!func.func.name.id.equals("__init__")) {
            func.addMapping(fromType, toType);
        } else {
            func.removeMapping(fromType);
        }
        return toType;
    }
}
Also used : ClassType(org.yinwang.pysonar.types.ClassType) ListType(org.yinwang.pysonar.types.ListType) DictType(org.yinwang.pysonar.types.DictType) InstanceType(org.yinwang.pysonar.types.InstanceType) Type(org.yinwang.pysonar.types.Type) UnionType(org.yinwang.pysonar.types.UnionType) TupleType(org.yinwang.pysonar.types.TupleType) FunType(org.yinwang.pysonar.types.FunType) ModuleType(org.yinwang.pysonar.types.ModuleType) State(org.yinwang.pysonar.State) ListType(org.yinwang.pysonar.types.ListType) DictType(org.yinwang.pysonar.types.DictType) ArrayList(java.util.ArrayList) CallStackEntry(org.yinwang.pysonar.CallStackEntry) InstanceType(org.yinwang.pysonar.types.InstanceType) NotNull(org.jetbrains.annotations.NotNull)

Example 2 with DictType

use of org.yinwang.pysonar.types.DictType in project pysonar2 by yinwang0.

the class TypeInferencer method visit.

@NotNull
@Override
public Type visit(Dict node, State s) {
    Type keyType = resolveUnion(node.keys, s);
    Type valType = resolveUnion(node.values, s);
    return new DictType(keyType, valType);
}
Also used : ClassType(org.yinwang.pysonar.types.ClassType) ListType(org.yinwang.pysonar.types.ListType) DictType(org.yinwang.pysonar.types.DictType) InstanceType(org.yinwang.pysonar.types.InstanceType) Type(org.yinwang.pysonar.types.Type) UnionType(org.yinwang.pysonar.types.UnionType) TupleType(org.yinwang.pysonar.types.TupleType) FunType(org.yinwang.pysonar.types.FunType) ModuleType(org.yinwang.pysonar.types.ModuleType) DictType(org.yinwang.pysonar.types.DictType) NotNull(org.jetbrains.annotations.NotNull)

Example 3 with DictType

use of org.yinwang.pysonar.types.DictType in project pysonar2 by yinwang0.

the class TypeInferencer method visit.

@NotNull
@Override
public Type visit(DictComp node, State s) {
    visit(node.generators, s);
    Type keyType = visit(node.key, s);
    Type valueType = visit(node.value, s);
    return new DictType(keyType, valueType);
}
Also used : ClassType(org.yinwang.pysonar.types.ClassType) ListType(org.yinwang.pysonar.types.ListType) DictType(org.yinwang.pysonar.types.DictType) InstanceType(org.yinwang.pysonar.types.InstanceType) Type(org.yinwang.pysonar.types.Type) UnionType(org.yinwang.pysonar.types.UnionType) TupleType(org.yinwang.pysonar.types.TupleType) FunType(org.yinwang.pysonar.types.FunType) ModuleType(org.yinwang.pysonar.types.ModuleType) DictType(org.yinwang.pysonar.types.DictType) NotNull(org.jetbrains.annotations.NotNull)

Example 4 with DictType

use of org.yinwang.pysonar.types.DictType in project pysonar2 by yinwang0.

the class TypeInferencer method visit.

@NotNull
@Override
public Type visit(ClassDef node, State s) {
    ClassType classType = new ClassType(node.name.id, s);
    List<Type> baseTypes = new ArrayList<>();
    for (Node base : node.bases) {
        Type baseType = visit(base, s);
        if (baseType instanceof ClassType) {
            classType.addSuper(baseType);
        } else if (baseType instanceof UnionType) {
            for (Type parent : ((UnionType) baseType).types) {
                classType.addSuper(parent);
            }
        } else {
            addWarningToNode(base, base + " is not a class");
        }
        baseTypes.add(baseType);
    }
    // XXX: Not sure if we should add "bases", "name" and "dict" here. They
    // must be added _somewhere_ but I'm just not sure if it should be HERE.
    node.addSpecialAttribute(classType.table, "__bases__", new TupleType(baseTypes));
    node.addSpecialAttribute(classType.table, "__name__", Types.StrInstance);
    node.addSpecialAttribute(classType.table, "__dict__", new DictType(Types.StrInstance, Types.UNKNOWN));
    node.addSpecialAttribute(classType.table, "__module__", Types.StrInstance);
    node.addSpecialAttribute(classType.table, "__doc__", Types.StrInstance);
    // Bind ClassType to name here before resolving the body because the
    // methods need node type as self.
    bind(s, node.name, classType, CLASS);
    if (node.body != null) {
        visit(node.body, classType.table);
    }
    return Types.CONT;
}
Also used : UnionType(org.yinwang.pysonar.types.UnionType) ClassType(org.yinwang.pysonar.types.ClassType) ListType(org.yinwang.pysonar.types.ListType) DictType(org.yinwang.pysonar.types.DictType) InstanceType(org.yinwang.pysonar.types.InstanceType) Type(org.yinwang.pysonar.types.Type) UnionType(org.yinwang.pysonar.types.UnionType) TupleType(org.yinwang.pysonar.types.TupleType) FunType(org.yinwang.pysonar.types.FunType) ModuleType(org.yinwang.pysonar.types.ModuleType) ArrayList(java.util.ArrayList) TupleType(org.yinwang.pysonar.types.TupleType) DictType(org.yinwang.pysonar.types.DictType) ClassType(org.yinwang.pysonar.types.ClassType) NotNull(org.jetbrains.annotations.NotNull)

Example 5 with DictType

use of org.yinwang.pysonar.types.DictType in project pysonar2 by yinwang0.

the class TypeInferencer method bindParams.

@NotNull
private Type bindParams(@NotNull State state, @NotNull FunctionDef func, @Nullable List<Type> pTypes, @Nullable List<Type> dTypes, @Nullable Map<String, Type> hash, @Nullable Type kw, @Nullable Type star) {
    List<Node> args = func.args;
    Name rest = func.vararg;
    Name restKw = func.kwarg;
    TupleType fromType = new TupleType();
    int pSize = args == null ? 0 : args.size();
    int aSize = pTypes == null ? 0 : pTypes.size();
    int dSize = dTypes == null ? 0 : dTypes.size();
    int nPos = pSize - dSize;
    if (star != null && star instanceof ListType) {
        star = ((ListType) star).toTupleType();
    }
    for (int i = 0, j = 0; i < pSize; i++) {
        Node arg = args.get(i);
        Type aType;
        if (i < aSize) {
            aType = pTypes.get(i);
        } else if (i - nPos >= 0 && i - nPos < dSize) {
            aType = dTypes.get(i - nPos);
        } else {
            if (hash != null && args.get(i) instanceof Name && hash.containsKey(((Name) args.get(i)).id)) {
                aType = hash.get(((Name) args.get(i)).id);
                hash.remove(((Name) args.get(i)).id);
            } else {
                if (star != null && star instanceof TupleType && j < ((TupleType) star).eltTypes.size()) {
                    aType = ((TupleType) star).get(j++);
                } else {
                    aType = Types.UNKNOWN;
                    addWarningToNode(args.get(i), "unable to bind argument:" + args.get(i));
                }
            }
        }
        bind(state, arg, aType, PARAMETER);
        fromType.add(aType);
    }
    if (restKw != null) {
        if (hash != null && !hash.isEmpty()) {
            Type hashType = UnionType.newUnion(hash.values());
            bind(state, restKw, new DictType(Types.StrInstance, hashType), PARAMETER);
        } else {
            bind(state, restKw, Types.UNKNOWN, PARAMETER);
        }
    }
    if (rest != null) {
        if (pTypes.size() > pSize) {
            if (func.afterRest != null) {
                int nAfter = func.afterRest.size();
                for (int i = 0; i < nAfter; i++) {
                    bind(state, func.afterRest.get(i), pTypes.get(pTypes.size() - nAfter + i), PARAMETER);
                }
                if (pTypes.size() - nAfter > 0) {
                    Type restType = new TupleType(pTypes.subList(pSize, pTypes.size() - nAfter));
                    bind(state, rest, restType, PARAMETER);
                }
            } else {
                Type restType = new TupleType(pTypes.subList(pSize, pTypes.size()));
                bind(state, rest, restType, PARAMETER);
            }
        } else {
            bind(state, rest, Types.UNKNOWN, PARAMETER);
        }
    }
    return fromType;
}
Also used : ClassType(org.yinwang.pysonar.types.ClassType) ListType(org.yinwang.pysonar.types.ListType) DictType(org.yinwang.pysonar.types.DictType) InstanceType(org.yinwang.pysonar.types.InstanceType) Type(org.yinwang.pysonar.types.Type) UnionType(org.yinwang.pysonar.types.UnionType) TupleType(org.yinwang.pysonar.types.TupleType) FunType(org.yinwang.pysonar.types.FunType) ModuleType(org.yinwang.pysonar.types.ModuleType) ListType(org.yinwang.pysonar.types.ListType) TupleType(org.yinwang.pysonar.types.TupleType) DictType(org.yinwang.pysonar.types.DictType) NotNull(org.jetbrains.annotations.NotNull)

Aggregations

ClassType (org.yinwang.pysonar.types.ClassType)6 DictType (org.yinwang.pysonar.types.DictType)6 FunType (org.yinwang.pysonar.types.FunType)6 InstanceType (org.yinwang.pysonar.types.InstanceType)6 ListType (org.yinwang.pysonar.types.ListType)6 ModuleType (org.yinwang.pysonar.types.ModuleType)6 TupleType (org.yinwang.pysonar.types.TupleType)6 Type (org.yinwang.pysonar.types.Type)6 UnionType (org.yinwang.pysonar.types.UnionType)6 NotNull (org.jetbrains.annotations.NotNull)5 ArrayList (java.util.ArrayList)2 CallStackEntry (org.yinwang.pysonar.CallStackEntry)1 State (org.yinwang.pysonar.State)1