public FunctionAnalysisUnit(FunctionAnalysisUnit originalUnit, CallChain callChain, ArgumentSet callArgs)
            : base(originalUnit.Ast, null) {
            _originalUnit = originalUnit;
            _declUnit = originalUnit._declUnit;
            Function = originalUnit.Function;

            CallChain = callChain;

            var scope = new FunctionScope(
                Function,
                Ast,
                originalUnit.Scope.OuterScope,
                originalUnit.DeclaringModule.ProjectEntry
            );
            scope.UpdateParameters(this, callArgs, false, originalUnit.Scope as FunctionScope);
            _scope = scope;

            var walker = new OverviewWalker(_originalUnit.ProjectEntry, this, Tree);
            if (Ast.Body != null) {
                Ast.Body.Walk(walker);
            }

            AnalysisLog.NewUnit(this);
            Enqueue();
        }
Exemple #2
0
        internal bool UpdateParameters(FunctionAnalysisUnit unit, ArgumentSet others, bool enqueue = true, FunctionScope scopeWithDefaultParameters = null) {
            EnsureParameters(unit);

            var astParams = Function.FunctionDefinition.Parameters;
            bool added = false;
            var entry = unit.ProjectEntry;
            var state = unit.ProjectState;
            var limits = state.Limits;

            for (int i = 0; i < others.Args.Length && i < astParams.Count; ++i) {
                VariableDef param;
                if (!TryGetVariable(astParams[i].Name, out param)) {
                    Debug.Assert(false, "Parameter " + astParams[i].Name + " has no variable in this scope");
                    param = AddVariable(astParams[i].Name);
                }
                param.MakeUnionStrongerIfMoreThan(limits.NormalArgumentTypes, others.Args[i]);
                added |= param.AddTypes(entry, others.Args[i], false);
            }
            if (_seqParameters != null) {
                _seqParameters.List.MakeUnionStrongerIfMoreThan(limits.ListArgumentTypes, others.SequenceArgs);
                added |= _seqParameters.List.AddTypes(unit, new[] { others.SequenceArgs });
            }
            if (_dictParameters != null) {
                _dictParameters.Dict.MakeUnionStrongerIfMoreThan(limits.DictArgumentTypes, others.DictArgs);
                added |= _dictParameters.Dict.AddTypes(Function.FunctionDefinition, unit, state.GetConstant(""), others.DictArgs);
            }

            if (scopeWithDefaultParameters != null) {
                for (int i = 0; i < others.Args.Length && i < astParams.Count; ++i) {
                    VariableDef defParam, param;
                    if (TryGetVariable(astParams[i].Name, out param) &&
                        !param.TypesNoCopy.Any() &&
                        scopeWithDefaultParameters.TryGetVariable(astParams[i].Name, out defParam)) {
                        param.MakeUnionStrongerIfMoreThan(limits.NormalArgumentTypes, defParam.TypesNoCopy);
                        added |= param.AddTypes(entry, defParam.TypesNoCopy, false);
                    }
                }
            }

            if (enqueue && added) {
                unit.Enqueue();
            }
            return added;
        }
Exemple #3
0
 private IAnalysisSet DoCall(Node node, AnalysisUnit callingUnit, FunctionAnalysisUnit calledUnit, ArgumentSet callArgs)
 {
     calledUnit.UpdateParameters(callArgs);
     calledUnit.ReturnValue.AddDependency(callingUnit);
     return(calledUnit.ReturnValue.Types);
 }
Exemple #4
0
        public override IAnalysisSet Call(Node node, AnalysisUnit unit, IAnalysisSet[] args, NameExpression[] keywordArgNames)
        {
            var callArgs = ArgumentSet.FromArgs(FunctionDefinition, unit, args, keywordArgNames);

            if (keywordArgNames != null && keywordArgNames.Any())
            {
                _analysisUnit.AddNamedParameterReferences(unit, keywordArgNames);
            }

            var res = DoCall(node, unit, _analysisUnit, callArgs);

            if (_derived != null)
            {
                foreach (FunctionInfo derived in _derived)
                {
                    var derivedResult = derived.DoCall(node, unit, derived._analysisUnit, callArgs);
                    res = res.Union(derivedResult);
                }
            }

            if (_analysisUnit.State.Limits.PropagateParameterTypeToBaseMethods &&
                _analysisUnit.Scope.OuterScope is ClassScope parentClass)
            {
                var baseMethods = DDG.LookupBaseMethods(Name, parentClass.Class.Mro, AnalysisUnit.Ast, AnalysisUnit);
                foreach (FunctionInfo baseMethod in baseMethods.OfType <FunctionInfo>())
                {
                    baseMethod.DoCall(node, unit, baseMethod._analysisUnit, callArgs);
                }
            }

            if (_callsWithClosure != null)
            {
                var chain     = new CallChain(node, unit, _callDepthLimit);
                var aggregate = GetAggregate(unit);

                if (!_callsWithClosure.TryGetValue(aggregate, chain, _callDepthLimit, out var calledUnit) &&
                    !unit.ForEval)
                {
                    _callsSinceLimitChange += 1;
                    if (_callsSinceLimitChange >= ProjectState.Limits.DecreaseCallDepth && _callDepthLimit > 1)
                    {
                        _callDepthLimit       -= 1;
                        _callsSinceLimitChange = 0;
                        AnalysisLog.ReduceCallDepth(this, _callsWithClosure.Count, _callDepthLimit);

                        _callsWithClosure.Clear();
                        chain = chain.Trim(_callDepthLimit);
                    }

                    calledUnit = new FunctionClosureAnalysisUnit(aggregate, (FunctionAnalysisUnit)AnalysisUnit, chain);
                    _callsWithClosure.Add(aggregate, chain, calledUnit);
                    calledUnit.Enqueue();
                }

                Debug.Assert(calledUnit != null || unit.ForEval);

                res.Split(v => v.IsResolvable(), out _, out var nonLazy);
                res = DoCall(node, unit, calledUnit, callArgs);
                res = res.Union(nonLazy);
            }

            var context = unit.ForEval ? ResolutionContext.Complete : new ResolutionContext {
                Caller   = this,
                CallArgs = callArgs,
                CallSite = node
            };

            var r = res.Resolve(unit, context, out _);

            return(r);
        }
 internal bool UpdateParameters(ArgumentSet callArgs, bool enqueue = true) {
     var defScope = _originalUnit != null ? _originalUnit.Scope as FunctionScope : null;
     return ((FunctionScope)Scope).UpdateParameters(this, callArgs, enqueue, defScope);
 }
Exemple #6
0
 internal override bool UpdateParameters(ArgumentSet callArgs, bool enqueue = true)
 {
     var defScope = _originalUnit.Scope;
     return ((FunctionScope)Scope).UpdateParameters(this, callArgs, enqueue, (FunctionScope)defScope);
 }
Exemple #7
0
 internal virtual bool UpdateParameters(ArgumentSet callArgs, bool enqueue = true)
 {
     return ((FunctionScope)Scope).UpdateParameters(this, callArgs, enqueue, null);
 }
Exemple #8
0
 public static bool AreCompatible(ArgumentSet x, ArgumentSet y)
 {
     return(x.Args.Length == y.Args.Length);
 }
Exemple #9
0
        public override IAnalysisSet Call(Node node, AnalysisUnit unit, IAnalysisSet[] args, NameExpression[] keywordArgNames)
        {
            var callArgs = ArgumentSet.FromArgs(FunctionDefinition, unit, args, keywordArgNames);

            FunctionAnalysisUnit calledUnit;
            bool updateArguments = true;

            if (callArgs.Count == 0 ||
                (ProjectState.Limits.UnifyCallsToNew && Name == "__new__") ||
                _callDepthLimit == 0)
            {
                calledUnit = (FunctionAnalysisUnit)AnalysisUnit;
            }
            else
            {
                if (_allCalls == null)
                {
                    _allCalls = new CallChainSet <FunctionAnalysisUnit>();
                }

                var chain = new CallChain(node, unit, _callDepthLimit);
                if (!_allCalls.TryGetValue(unit.ProjectEntry, chain, _callDepthLimit, out calledUnit))
                {
                    if (unit.ForEval)
                    {
                        // Call expressions that weren't analyzed get the union result
                        // of all calls to this function.
                        var res = AnalysisSet.Empty;
                        foreach (var call in _allCalls.Values)
                        {
                            res = res.Union(call.ReturnValue.TypesNoCopy);
                        }
                        return(res);
                    }
                    else
                    {
                        _callsSinceLimitChange += 1;
                        if (_callsSinceLimitChange >= ProjectState.Limits.DecreaseCallDepth && _callDepthLimit > 1)
                        {
                            _callDepthLimit       -= 1;
                            _callsSinceLimitChange = 0;
                            AnalysisLog.ReduceCallDepth(this, _allCalls.Count, _callDepthLimit);

                            _allCalls.Clear();
                            chain = chain.Trim(_callDepthLimit);
                        }
                        calledUnit = new FunctionAnalysisUnit((FunctionAnalysisUnit)AnalysisUnit, chain, callArgs);
                        _allCalls.Add(unit.ProjectEntry, chain, calledUnit);
                        updateArguments = false;
                    }
                }
            }

            if (updateArguments && calledUnit.UpdateParameters(callArgs))
            {
                AnalysisLog.UpdateUnit(calledUnit);
            }
            if (keywordArgNames != null && keywordArgNames.Any())
            {
                calledUnit.AddNamedParameterReferences(unit, keywordArgNames);
            }

            calledUnit.ReturnValue.AddDependency(unit);
            return(calledUnit.ReturnValue.Types);
        }
Exemple #10
0
        public static ArgumentSet FromArgs(FunctionDefinition node, AnalysisUnit unit, IAnalysisSet[] args, NameExpression[] keywordArgs)
        {
            // TODO: Warn when a keyword argument is provided and it maps to
            // something which is also a positional argument:
            // def f(a, b, c):
            //    print a, b, c
            //
            // f(2, 3, a=42)

            int kwArgsOffset = args.Length - keywordArgs.Length;

            var seqArgs       = AnalysisSet.EmptyUnion;
            var dictArgs      = AnalysisSet.EmptyUnion;
            int listArgsIndex = -1;
            int dictArgsIndex = -1;

            int argCount = node.Parameters.Length;
            var newArgs  = new IAnalysisSet[argCount];

            for (int i = 0; i < node.Parameters.Length; ++i)
            {
                if (node.Parameters[i].Kind == ParameterKind.List)
                {
                    listArgsIndex = i;
                }
                else if (node.Parameters[i].Kind == ParameterKind.Dictionary)
                {
                    dictArgsIndex = i;
                }
                newArgs[i] = AnalysisSet.Empty;
            }

            int lastPositionFilled = -1;

            for (int i = 0; i < kwArgsOffset; ++i)
            {
                if (i < argCount && (listArgsIndex < 0 || i < listArgsIndex))
                {
                    newArgs[i]         = newArgs[i].Union(args[i]);
                    lastPositionFilled = i;
                }
                else if (listArgsIndex >= 0)
                {
                    foreach (var ns in args[i])
                    {
                        var sseq = ns as StarArgsSequenceInfo;
                        if (sseq != null && i < node.Parameters.Length && sseq._node == node.Parameters[i])
                        {
                            seqArgs = seqArgs.Add(unit.State.ClassInfos[BuiltinTypeId.Tuple].Instance);
                        }
                        else
                        {
                            seqArgs = seqArgs.Add(ns);
                        }
                    }
                }
                else
                {
                    // TODO: Warn about extra parameters
                }
            }

            for (int i = kwArgsOffset; i < args.Length; ++i)
            {
                if (i - kwArgsOffset >= keywordArgs.Length || keywordArgs[i - kwArgsOffset] == null)
                {
                    continue;
                }

                var name = keywordArgs[i - kwArgsOffset].Name;
                if (name.Equals("*", StringComparison.Ordinal))
                {
                    foreach (var ns in args[i])
                    {
                        SequenceInfo         seq;
                        StarArgsSequenceInfo sseq;
                        if ((sseq = ns as StarArgsSequenceInfo) != null)
                        {
                            seqArgs = seqArgs.Union(sseq.IndexTypes.SelectMany(def => def.Types));
                        }
                        else if ((seq = ns as SequenceInfo) != null)
                        {
                            for (int j = 0; j < seq.IndexTypes.Length; ++j)
                            {
                                int k = lastPositionFilled + j + 1;
                                if (k < node.Parameters.Length && node.Parameters[k].Kind == ParameterKind.Normal)
                                {
                                    newArgs[k] = newArgs[k].Union(seq.IndexTypes[j].Types);
                                }
                                else if (listArgsIndex >= 0)
                                {
                                    seqArgs = seqArgs.Union(seq.IndexTypes[j].Types);
                                }
                                else
                                {
                                    // TODO: Warn about extra parameters
                                }
                            }
                        }
                        else if (listArgsIndex >= 0)
                        {
                            newArgs[listArgsIndex] = newArgs[listArgsIndex].Add(ns);
                        }
                    }
                }
                else if (name.Equals("**", StringComparison.Ordinal))
                {
                    foreach (var dict in args[i].OfType <DictionaryInfo>())
                    {
                        foreach (var kv in dict._keysAndValues.KeyValueTypes)
                        {
                            var paramName = kv.Key.GetConstantValueAsString();
                            if (string.IsNullOrEmpty(paramName))
                            {
                                continue;
                            }

                            for (int j = 0; j < argCount; ++j)
                            {
                                if (node.Parameters[j].Name.Equals(paramName, StringComparison.Ordinal))
                                {
                                    newArgs[j] = newArgs[j].Union(kv.Value);
                                    break;
                                }
                            }
                        }
                    }

                    if (dictArgsIndex >= 0)
                    {
                        foreach (var ns in args[i])
                        {
                            var sdict = ns as StarArgsDictionaryInfo;
                            if (sdict != null)
                            {
                                dictArgs = dictArgs.Union(sdict._keysAndValues.AllValueTypes);
                            }
                            else
                            {
                                newArgs[dictArgsIndex] = newArgs[dictArgsIndex].Add(ns);
                            }
                        }
                    }
                }
                else
                {
                    bool foundParam = false;
                    for (int j = 0; j < argCount; ++j)
                    {
                        if (node.Parameters[j].Name.Equals(name, StringComparison.Ordinal))
                        {
                            newArgs[j] = newArgs[j].Union(args[i]);
                            foundParam = true;
                            break;
                        }
                    }
                    if (!foundParam && dictArgsIndex >= 0)
                    {
                        dictArgs = dictArgs.Union(args[i]);
                    }
                }
            }

            var limits = unit.State.Limits;

            for (int i = 0; i < argCount; ++i)
            {
                newArgs[i] = ReduceArgs(newArgs[i], limits.NormalArgumentTypes);
            }

            var set = new ArgumentSet(
                newArgs,
                ReduceArgs(seqArgs, limits.ListArgumentTypes),
                ReduceArgs(dictArgs, limits.DictArgumentTypes),
                null
                );

            return(set);
        }
Exemple #11
0
 public static bool AreCompatible(ArgumentSet x, ArgumentSet y) {
     return x.Args.Length == y.Args.Length;
 }