public override void Evaluate()
        {
            var stub = SymbolTable.ReplacedByStubs.Contains(Target) ||
                       _function.DeclaringModule.ModuleType == ModuleType.Stub ||
                       Module.ModuleType == ModuleType.Specialized;

            using (Eval.OpenScope(_function.DeclaringModule, FunctionDefinition, out _)) {
                var returnType = TryDetermineReturnValue();

                var parameters = Eval.CreateFunctionParameters(_self, _function, FunctionDefinition, !stub);
                _overload.SetParameters(parameters);

                // Do process body of constructors since they may be declaring
                // variables that are later used to determine return type of other
                // methods and properties.
                var ctor = _function.IsDunderInit() || _function.IsDunderNew();
                if (ctor || returnType.IsUnknown() || Module.ModuleType == ModuleType.User)
                {
                    // Return type from the annotation is sufficient for libraries and stubs, no need to walk the body.
                    FunctionDefinition.Body?.Walk(this);
                    // For libraries remove declared local function variables to free up some memory.
                    var optionsProvider = Eval.Services.GetService <IAnalysisOptionsProvider>();
                    if (Module.ModuleType != ModuleType.User && optionsProvider?.Options.KeepLibraryLocalVariables != true)
                    {
                        ((VariableCollection)Eval.CurrentScope.Variables).Clear();
                    }
                }
            }
            Result = _function;
        }
Example #2
0
        private void SpecializeFuture(FromImportStatement node)
        {
            if (Interpreter.LanguageVersion.Is3x())
            {
                return;
            }

            var printNameExpression = node.Names.FirstOrDefault(n => n?.Name == "print_function");

            if (printNameExpression != null)
            {
                var fn         = new PythonFunctionType("print", new Location(Module), null, string.Empty);
                var o          = new PythonFunctionOverload(fn.Name, new Location(Module));
                var parameters = new List <ParameterInfo> {
                    new ParameterInfo("*values", Interpreter.GetBuiltinType(BuiltinTypeId.Object), ParameterKind.List, null),
                    new ParameterInfo("sep", Interpreter.GetBuiltinType(BuiltinTypeId.Str), ParameterKind.KeywordOnly, null),
                    new ParameterInfo("end", Interpreter.GetBuiltinType(BuiltinTypeId.Str), ParameterKind.KeywordOnly, null),
                    new ParameterInfo("file", Interpreter.GetBuiltinType(BuiltinTypeId.Str), ParameterKind.KeywordOnly, null)
                };
                o.SetParameters(parameters);
                o.SetReturnValue(Interpreter.GetBuiltinType(BuiltinTypeId.NoneType), true);
                fn.AddOverload(o);
                Eval.DeclareVariable("print", fn, VariableSource.Import, printNameExpression);
            }
        }
Example #3
0
 private void EnsureContent()
 {
     lock (_contentLock) {
         if (_model != null)
         {
             _overload.SetParameters(_model.Parameters.Select(p => ConstructParameter(_mf, p)).ToArray());
             _overload.SetReturnValue(_mf.ConstructMember(_model.ReturnType), true);
             _model = null;
             _mf    = null;
         }
     }
 }
        private IPythonType SpecializeNewType(Location location)
        {
            var fn = PythonFunctionType.Specialize("NewType", this, GetMemberDocumentation("NewType"));
            var o  = new PythonFunctionOverload(fn, location);

            // When called, create generic parameter type. For documentation
            // use original TypeVar declaration so it appear as a tooltip.
            o.SetReturnValueProvider((interpreter, overload, args, indexSpan) => CreateTypeAlias(args));
            o.SetParameters(new[] {
                new ParameterInfo("name", Interpreter.GetBuiltinType(BuiltinTypeId.Str), ParameterKind.Normal, null),
                new ParameterInfo("tp", Interpreter.GetBuiltinType(BuiltinTypeId.Type), ParameterKind.Normal, null),
            });
            fn.AddOverload(o);
            return(fn);
        }
Example #5
0
        public NamedTuple(IPythonModule declaringModule) : base(BuiltinTypeId.Tuple, declaringModule)
        {
            var interpreter = DeclaringModule.Interpreter;

            var fn = new PythonFunctionType("__init__", new Location(declaringModule), this, "NamedTuple");
            var o  = new PythonFunctionOverload(fn, new Location(DeclaringModule));

            o.SetParameters(new List <ParameterInfo> {
                new ParameterInfo("self", this, ParameterKind.Normal, this),
                new ParameterInfo("name", interpreter.GetBuiltinType(BuiltinTypeId.Str), ParameterKind.Normal, null),
                new ParameterInfo("members", interpreter.GetBuiltinType(BuiltinTypeId.List), ParameterKind.Normal, null)
            });
            fn.AddOverload(o);
            _constructor = fn;
        }
        public IMember GetValueFromLambda(LambdaExpression expr)
        {
            if (expr == null)
            {
                return(null);
            }

            var fd       = expr.Function;
            var location = GetLocationOfName(fd);
            var ft       = new PythonFunctionType(fd, null, location);
            var overload = new PythonFunctionOverload(ft, fd, location, expr.Function.ReturnAnnotation?.ToCodeString(Ast));

            overload.SetParameters(CreateFunctionParameters(null, ft, fd, false));
            ft.AddOverload(overload);
            return(ft);
        }
        public TypeVar(IPythonModule declaringModule) : base(BuiltinTypeId.Type, declaringModule)
        {
            var interpreter = DeclaringModule.Interpreter;

            var fn = new PythonFunctionType("__init__", new Location(declaringModule), this, "TypeVar");
            var o  = new PythonFunctionOverload(fn, new Location(DeclaringModule));

            var boolType = interpreter.GetBuiltinType(BuiltinTypeId.Bool);

            o.SetParameters(new List <ParameterInfo> {
                new ParameterInfo("self", this, ParameterKind.Normal, this),
                new ParameterInfo("name", interpreter.GetBuiltinType(BuiltinTypeId.Str), ParameterKind.Normal, null),
                new ParameterInfo("constraints", interpreter.GetBuiltinType(BuiltinTypeId.Str), ParameterKind.List, null),
                new ParameterInfo("bound", interpreter.GetBuiltinType(BuiltinTypeId.Type), ParameterKind.KeywordOnly, new PythonConstant(null, interpreter.GetBuiltinType(BuiltinTypeId.None))),
                new ParameterInfo("covariant", boolType, ParameterKind.KeywordOnly, new PythonConstant(false, boolType)),
                new ParameterInfo("contravariant", boolType, ParameterKind.KeywordOnly, new PythonConstant(false, boolType))
            });
            fn.AddOverload(o);
            _constructor = fn;
        }
Example #8
0
        public override void Populate(ModuleFactory mf, IPythonType declaringType, IGlobalScope gs)
        {
            // Create inner functions and classes first since function may be returning one of them.
            var all = Classes.Concat <MemberModel>(Functions).ToArray();

            foreach (var model in all)
            {
                _function.AddMember(Name, model.Create(mf, _function, gs), overwrite: true);
            }
            foreach (var model in all)
            {
                model.Populate(mf, _function, gs);
            }

            foreach (var om in Overloads)
            {
                var o = new PythonFunctionOverload(_function, new Location(mf.Module, IndexSpan.ToSpan()));
                o.SetDocumentation(Documentation);
                o.SetReturnValue(mf.ConstructMember(om.ReturnType), true);
                o.SetParameters(om.Parameters.Select(p => ConstructParameter(mf, p)).ToArray());
                _function.AddOverload(o);
            }
        }
Example #9
0
        private void DeclareParameters(bool declareVariables)
        {
            // For class method no need to add extra parameters, but first parameter type should be the class.
            // For static and unbound methods do not add or set anything.
            // For regular bound methods add first parameter and set it to the class.

            var parameters = new List <ParameterInfo>();
            var skip       = 0;

            if (_self != null && _function.HasClassFirstArgument())
            {
                var p0 = FunctionDefinition.Parameters.FirstOrDefault();
                if (p0 != null && !string.IsNullOrEmpty(p0.Name))
                {
                    // Actual parameter type will be determined when method is invoked.
                    // The reason is that if method might be called on a derived class.
                    // Declare self or cls in this scope.
                    if (declareVariables)
                    {
                        Eval.DeclareVariable(p0.Name, new PythonInstance(_self), VariableSource.Declaration, p0.NameExpression);
                    }
                    // Set parameter info.
                    var pi = new ParameterInfo(Ast, p0, _self, null, false);
                    parameters.Add(pi);
                    skip++;
                }
            }

            // Declare parameters in scope
            IMember defaultValue = null;

            for (var i = skip; i < FunctionDefinition.Parameters.Length; i++)
            {
                var isGeneric = false;
                var p         = FunctionDefinition.Parameters[i];
                if (!string.IsNullOrEmpty(p.Name))
                {
                    IPythonType paramType = null;
                    if (p.DefaultValue != null)
                    {
                        defaultValue = Eval.GetValueFromExpression(p.DefaultValue);
                        // If parameter has default value, look for the annotation locally first
                        // since outer type may be getting redefined. Consider 's = None; def f(s: s = 123): ...
                        paramType = Eval.GetTypeFromAnnotation(p.Annotation, out isGeneric, LookupOptions.Local | LookupOptions.Builtins);
                        // Default value of None does not mean the parameter is None, just says it can be missing.
                        defaultValue = defaultValue.IsUnknown() || defaultValue.IsOfType(BuiltinTypeId.NoneType) ? null : defaultValue;
                        if (paramType == null && defaultValue != null)
                        {
                            paramType = defaultValue.GetPythonType();
                        }
                    }
                    // If all else fails, look up globally.
                    paramType = paramType ?? Eval.GetTypeFromAnnotation(p.Annotation, out isGeneric) ?? Eval.UnknownType;
                    var pi = new ParameterInfo(Ast, p, paramType, defaultValue, isGeneric);
                    if (declareVariables)
                    {
                        DeclareParameter(p, pi);
                    }
                    parameters.Add(pi);
                }
            }
            _overload.SetParameters(parameters);
        }
        private void SpecializeMembers()
        {
            var location = new Location(this);

            // TypeVar
            var fn = PythonFunctionType.Specialize("TypeVar", this, GetMemberDocumentation("TypeVar"));
            var o  = new PythonFunctionOverload(fn, location);

            o.SetParameters(new List <ParameterInfo> {
                new ParameterInfo("name", Interpreter.GetBuiltinType(BuiltinTypeId.Str), ParameterKind.Normal, null),
                new ParameterInfo("constraints", Interpreter.GetBuiltinType(BuiltinTypeId.Str), ParameterKind.List, null),
                new ParameterInfo("bound", Interpreter.GetBuiltinType(BuiltinTypeId.Str), ParameterKind.KeywordOnly, new PythonConstant(null, Interpreter.GetBuiltinType(BuiltinTypeId.NoneType))),
                new ParameterInfo("covariant", Interpreter.GetBuiltinType(BuiltinTypeId.Bool), ParameterKind.KeywordOnly, new PythonConstant(false, Interpreter.GetBuiltinType(BuiltinTypeId.Bool))),
                new ParameterInfo("contravariant", Interpreter.GetBuiltinType(BuiltinTypeId.Bool), ParameterKind.KeywordOnly, new PythonConstant(false, Interpreter.GetBuiltinType(BuiltinTypeId.Bool)))
            });

            // When called, create generic parameter type. For documentation
            // use original TypeVar declaration so it appear as a tooltip.
            o.SetReturnValueProvider((declaringModule, overload, args, indexSpan)
                                     => GenericTypeParameter.FromTypeVar(args, declaringModule, indexSpan));

            fn.AddOverload(o);
            _members["TypeVar"] = fn;

            // NewType
            _members["NewType"] = SpecializeNewType(location);

            // Type
            fn = PythonFunctionType.Specialize("Type", this, GetMemberDocumentation("Type"));
            o  = new PythonFunctionOverload(fn, location);
            // When called, create generic parameter type. For documentation
            // use original TypeVar declaration so it appear as a tooltip.
            o.SetReturnValueProvider((declaringModule, overload, args, indexSpan) => {
                var a = args.Values <IMember>();
                return(a.Count == 1 ? a[0] : Interpreter.UnknownType);
            });
            fn.AddOverload(o);
            _members["Type"] = fn;

            _members["Iterator"] = new SpecializedGenericType("Iterator", CreateIteratorType, this);

            _members["Iterable"]        = new SpecializedGenericType("Iterable", typeArgs => CreateListType("Iterable", BuiltinTypeId.List, typeArgs, false), this);
            _members["Sequence"]        = new SpecializedGenericType("Sequence", typeArgs => CreateListType("Sequence", BuiltinTypeId.List, typeArgs, false), this);
            _members["MutableSequence"] = new SpecializedGenericType("MutableSequence",
                                                                     typeArgs => CreateListType("MutableSequence", BuiltinTypeId.List, typeArgs, true), this);
            _members["List"] = new SpecializedGenericType("List",
                                                          typeArgs => CreateListType("List", BuiltinTypeId.List, typeArgs, true), this);

            _members["MappingView"] = new SpecializedGenericType("MappingView",
                                                                 typeArgs => CreateDictionary("MappingView", typeArgs, false), this);

            _members["KeysView"]   = new SpecializedGenericType("KeysView", CreateKeysViewType, this);
            _members["ValuesView"] = new SpecializedGenericType("ValuesView", CreateValuesViewType, this);
            _members["ItemsView"]  = new SpecializedGenericType("ItemsView", CreateItemsViewType, this);

            _members["AbstractSet"] = new SpecializedGenericType("AbstractSet",
                                                                 typeArgs => CreateListType("AbstractSet", BuiltinTypeId.Set, typeArgs, true), this);
            _members["Set"] = new SpecializedGenericType("Set",
                                                         typeArgs => CreateListType("Set", BuiltinTypeId.Set, typeArgs, true), this);
            _members["MutableSet"] = new SpecializedGenericType("MutableSet",
                                                                typeArgs => CreateListType("MutableSet", BuiltinTypeId.Set, typeArgs, true), this);
            _members["FrozenSet"] = new SpecializedGenericType("FrozenSet",
                                                               typeArgs => CreateListType("FrozenSet", BuiltinTypeId.Set, typeArgs, false), this);

            _members["Tuple"] = new SpecializedGenericType("Tuple", CreateTupleType, this);

            _members["Mapping"] = new SpecializedGenericType("Mapping",
                                                             typeArgs => CreateDictionary("Mapping", typeArgs, false), this);
            _members["MutableMapping"] = new SpecializedGenericType("MutableMapping",
                                                                    typeArgs => CreateDictionary("MutableMapping", typeArgs, true), this);
            _members["Dict"] = new SpecializedGenericType("Dict",
                                                          typeArgs => CreateDictionary("Dict", typeArgs, true), this);
            _members["OrderedDict"] = new SpecializedGenericType("OrderedDict",
                                                                 typeArgs => CreateDictionary("OrderedDict", typeArgs, true), this);
            _members["DefaultDict"] = new SpecializedGenericType("DefaultDict",
                                                                 typeArgs => CreateDictionary("DefaultDict", typeArgs, true), this);

            _members["Union"] = new SpecializedGenericType("Union", CreateUnion, this);

            _members["Counter"] = Specialized.Function("Counter", this, GetMemberDocumentation("Counter"),
                                                       Interpreter.GetBuiltinType(BuiltinTypeId.Int)).CreateInstance(ArgumentSet.WithoutContext);

            // TODO: make these classes that support __float__, etc per spec.
            //_members["SupportsInt"] = Interpreter.GetBuiltinType(BuiltinTypeId.Int);
            //_members["SupportsFloat"] = Interpreter.GetBuiltinType(BuiltinTypeId.Float);
            //_members["SupportsComplex"] = Interpreter.GetBuiltinType(BuiltinTypeId.Complex);
            //_members["SupportsBytes"] = Interpreter.GetBuiltinType(BuiltinTypeId.Bytes);
            _members["ByteString"] = Interpreter.GetBuiltinType(BuiltinTypeId.Bytes);

            fn = PythonFunctionType.Specialize("NamedTuple", this, GetMemberDocumentation("NamedTuple"));
            o  = new PythonFunctionOverload(fn, location);
            o.SetReturnValueProvider((declaringModule, overload, args, indexSpan)
                                     => CreateNamedTuple(args.Values <IMember>(), declaringModule, indexSpan));
            fn.AddOverload(o);
            _members["NamedTuple"] = fn;

            _members["Any"]    = new AnyType(this);
            _members["AnyStr"] = CreateAnyStr();

            _members["Optional"] = new SpecializedGenericType("Optional", CreateOptional, this);
            _members["Type"]     = new SpecializedGenericType("Type", CreateType, this);

            _members["Generic"] = new SpecializedGenericType("Generic", CreateGenericClassBase, this);
        }
Example #11
0
        private async Task DeclareParametersAsync(CancellationToken cancellationToken = default)
        {
            // For class method no need to add extra parameters, but first parameter type should be the class.
            // For static and unbound methods do not add or set anything.
            // For regular bound methods add first parameter and set it to the class.

            var parameters = new List <ParameterInfo>();
            var skip       = 0;

            if (_self != null && _function.HasClassFirstArgument())
            {
                var p0 = FunctionDefinition.Parameters.FirstOrDefault();
                if (p0 != null && !string.IsNullOrEmpty(p0.Name))
                {
                    // Actual parameter type will be determined when method is invoked.
                    // The reason is that if method might be called on a derived class.
                    // Declare self or cls in this scope.
                    Eval.DeclareVariable(p0.Name, _self, p0.NameExpression);
                    // Set parameter info.
                    var pi = new ParameterInfo(Ast, p0, _self);
                    pi.SetType(_self);
                    parameters.Add(pi);
                    skip++;
                }
            }

            // Declare parameters in scope
            for (var i = skip; i < FunctionDefinition.Parameters.Length; i++)
            {
                cancellationToken.ThrowIfCancellationRequested();

                var p = FunctionDefinition.Parameters[i];
                if (!string.IsNullOrEmpty(p.Name))
                {
                    // If parameter has default value, look for the annotation locally first
                    // since outer type may be getting redefined. Consider 's = None; def f(s: s = 123): ...
                    IPythonType paramType = null;
                    if (p.DefaultValue != null)
                    {
                        paramType = await Eval.GetTypeFromAnnotationAsync(p.Annotation, cancellationToken, LookupOptions.Local | LookupOptions.Builtins);

                        if (paramType == null)
                        {
                            var defaultValue = await Eval.GetValueFromExpressionAsync(p.DefaultValue, cancellationToken);

                            if (!defaultValue.IsUnknown())
                            {
                                paramType = defaultValue.GetPythonType();
                            }
                        }
                    }
                    // If all else fails, look up globally.
                    paramType = paramType ?? await Eval.GetTypeFromAnnotationAsync(p.Annotation, cancellationToken);

                    var pi = new ParameterInfo(Ast, p, paramType);
                    await DeclareParameterAsync(p, i, pi, cancellationToken);

                    parameters.Add(pi);
                }
            }
            _overload.SetParameters(parameters);
        }