Search in sources :

Example 1 with State

use of org.yinwang.pysonar.State 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 State

use of org.yinwang.pysonar.State in project pysonar2 by yinwang0.

the class TypeInferencer method visit.

@NotNull
@Override
public Type visit(While node, State s) {
    visit(node.test, s);
    Type t1 = Types.UNKNOWN;
    Type t2 = Types.UNKNOWN;
    Type t3 = Types.UNKNOWN;
    State s1 = s.copy();
    State s2 = s.copy();
    if (node.body != null) {
        t1 = visit(node.body, s1);
        s.merge(s1);
        t2 = visit(node.body, s1);
        s.merge(s1);
    }
    if (node.orelse != null) {
        t3 = visit(node.orelse, s2);
        s.merge(s2);
    }
    return UnionType.union(UnionType.union(t1, t2), t3);
}
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) NotNull(org.jetbrains.annotations.NotNull)

Example 3 with State

use of org.yinwang.pysonar.State in project pysonar2 by yinwang0.

the class TypeInferencer method visit.

@NotNull
@Override
public Type visit(For node, State s) {
    bindIter(s, node.target, node.iter, SCOPE);
    Type t1 = Types.UNKNOWN;
    Type t2 = Types.UNKNOWN;
    Type t3 = Types.UNKNOWN;
    State s1 = s.copy();
    State s2 = s.copy();
    if (node.body != null) {
        t1 = visit(node.body, s1);
        s.merge(s1);
        t2 = visit(node.body, s1);
        s.merge(s1);
    }
    if (node.orelse != null) {
        t3 = visit(node.orelse, s2);
        s.merge(s2);
    }
    return UnionType.union(UnionType.union(t1, t2), t3);
}
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) NotNull(org.jetbrains.annotations.NotNull)

Example 4 with State

use of org.yinwang.pysonar.State in project pysonar2 by yinwang0.

the class TypeInferencer method visit.

@NotNull
@Override
public Type visit(FunctionDef node, State s) {
    State env = s.getForwarding();
    FunType fun = new FunType(node, env);
    fun.table.setParent(s);
    fun.table.setPath(s.extendPath(node.name.id));
    fun.setDefaultTypes(visit(node.defaults, s));
    Analyzer.self.addUncalled(fun);
    Binding.Kind funkind;
    if (node.isLamba) {
        return fun;
    } else {
        if (s.stateType == State.StateType.CLASS) {
            if ("__init__".equals(node.name.id)) {
                funkind = CONSTRUCTOR;
            } else {
                funkind = METHOD;
            }
        } else {
            funkind = FUNCTION;
        }
        Type outType = s.type;
        if (outType instanceof ClassType) {
            fun.setCls((ClassType) outType);
        }
        bind(s, node.name, fun, funkind);
        return Types.CONT;
    }
}
Also used : Binding(org.yinwang.pysonar.Binding) 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) FunType(org.yinwang.pysonar.types.FunType) ClassType(org.yinwang.pysonar.types.ClassType) NotNull(org.jetbrains.annotations.NotNull)

Example 5 with State

use of org.yinwang.pysonar.State in project pysonar2 by yinwang0.

the class TypeInferencer method visit.

@NotNull
@Override
public Type visit(If node, State s) {
    Type type1, type2;
    State s1 = s.copy();
    State s2 = s.copy();
    // Ignore result because Python can treat anything as bool
    visit(node.test, s);
    inferInstance(node.test, s, s1);
    if (node.body != null) {
        type1 = visit(node.body, s1);
    } else {
        type1 = Types.CONT;
    }
    if (node.orelse != null) {
        type2 = visit(node.orelse, s2);
    } else {
        type2 = Types.CONT;
    }
    boolean cont1 = UnionType.contains(type1, Types.CONT);
    boolean cont2 = UnionType.contains(type2, Types.CONT);
    // decide which branch affects the downstream state
    if (cont1 && cont2) {
        s1.merge(s2);
        s.overwrite(s1);
    } else if (cont1) {
        s.overwrite(s1);
    } else if (cont2) {
        s.overwrite(s2);
    }
    return UnionType.union(type1, type2);
}
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) NotNull(org.jetbrains.annotations.NotNull)

Aggregations

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