// Constructor call
        public override IMember CreateInstance(string typeName, LocationInfo location, IArgumentSet args)
        {
            // Specializations
            switch (typeName)
            {
            case "list":
                return(PythonCollectionType.CreateList(DeclaringModule.Interpreter, location, args));

            case "dict": {
                // self, then contents
                var contents = args.Values <IMember>().Skip(1).FirstOrDefault();
                return(new PythonDictionary(DeclaringModule.Interpreter, location, contents));
            }

            case "tuple": {
                var contents = args.Values <IMember>();
                return(PythonCollectionType.CreateTuple(DeclaringModule.Interpreter, location, contents));
            }
            }
            return(new PythonInstance(this, location));
        }
예제 #2
0
        public IMember Call(IArgumentSet args, IPythonType self, LocationInfo callLocation = null)
        {
            callLocation = callLocation ?? LocationInfo.Empty;
            if (!_fromAnnotation)
            {
                // First try supplied specialization callback.
                var rt = _returnValueProvider?.Invoke(_declaringModule, this, callLocation, args);
                if (!rt.IsUnknown())
                {
                    return(rt);
                }
            }

            // If function returns generic, determine actual type based on the passed in specific type (self).
            // If there is no self and no declaring type, the function is standalone.
            if (self == null && StaticReturnValue.IsGeneric() && Parameters.Any(p => p.IsGeneric))
            {
                return(null); // Evaluate standalone generic with arguments instead.
            }
            if (!(self is IPythonClassType selfClassType))
            {
                return(StaticReturnValue);
            }

            var returnType = StaticReturnValue.GetPythonType();

            switch (returnType)
            {
            case PythonClassType cls when cls.IsGeneric():
                // -> A[_T1, _T2, ...]
                // Match arguments
                IReadOnlyList <IPythonType> typeArgs = null;

                var classGenericParameters = selfClassType.GenericParameters.Keys.ToArray();
                if (classGenericParameters.Length > 0)
                {
                    // Declaring class is specific and provides definitions of generic parameters
                    typeArgs = classGenericParameters
                               .Select(n => selfClassType.GenericParameters.TryGetValue(n, out var t) ? t : null)
                               .ExcludeDefault()
                               .ToArray();
                }
                else
                {
                    typeArgs = ExpressionEval.GetTypeArgumentsFromParameters(this, args);
                }

                if (typeArgs != null)
                {
                    var specificReturnValue = cls.CreateSpecificType(new ArgumentSet(typeArgs), _declaringModule, callLocation);
                    return(new PythonInstance(specificReturnValue, callLocation));
                }
                break;

            case IGenericTypeDefinition gtp1: {
                // -> _T
                if (selfClassType.GenericParameters.TryGetValue(gtp1.Name, out var specificType))
                {
                    return(new PythonInstance(specificType, callLocation));
                }
                // Try returning the constraint
                // TODO: improve this, the heuristic is pretty basic and tailored to simple func(_T) -> _T
                var name       = StaticReturnValue.GetPythonType()?.Name;
                var typeDefVar = _declaringModule.Analysis.GlobalScope.Variables[name];
                if (typeDefVar?.Value is IGenericTypeDefinition gtp2)
                {
                    return(gtp2.Constraints.FirstOrDefault());
                }

                break;
            }
            }
            return(StaticReturnValue);
        }
 public PythonFunctionOverload(FunctionDefinition fd, IPythonModule declaringModule, LocationInfo location, string returnDocumentation = null)
     : this(fd.Name, declaringModule, _ => location, returnDocumentation)
 {
     FunctionDefinition = fd;
 }
 public PythonFunctionOverload(string name, IPythonModule declaringModule, LocationInfo location, string returnDocumentation = null)
     : this(name, declaringModule, _ => location ?? LocationInfo.Empty, returnDocumentation)
 {
     _declaringModule = declaringModule;
 }
예제 #5
0
 public PythonPropertyType(string name, IPythonModule declaringModule, IPythonType declaringType, bool isAbstract, LocationInfo location)
     : base(name, declaringModule, null, location)
 {
     DeclaringType = declaringType;
     IsAbstract    = isAbstract;
 }
예제 #6
0
 public PythonPropertyType(FunctionDefinition fd, IPythonModule declaringModule, IPythonType declaringType, bool isAbstract, LocationInfo location)
     : this(fd.Name, declaringModule, declaringType, isAbstract, location)
 {
     FunctionDefinition = fd;
 }
 public Argument(string name, ParameterKind kind, Expression valueValueExpression, Expression typeExpression, LocationInfo location)
 {
     Name            = name;
     Kind            = kind;
     ValueExpression = valueValueExpression;
     TypeExpression  = typeExpression;
     Location        = location;
 }
        public IPythonType CreateSpecificType(IArgumentSet args, IPythonModule declaringModule, LocationInfo location = null)
        {
            location = location ?? LocationInfo.Empty;
            // Get declared generic parameters of the class, i.e. list of Ts in Generic[T1, T2, ...]
            var genericClassParameters = Bases.OfType <IGenericClassParameter>().ToArray();
            // Optimistically use the first one
            // TODO: handle optional generics as class A(Generic[_T1], Optional[Generic[_T2]])
            var genericClassParameter = genericClassParameters.FirstOrDefault();

            // Create map of names listed in Generic[...] in the class definition.
            // We will be filling the map with specific types, if any provided.
            var genericTypeDefinitions     = genericClassParameter?.TypeDefinitions ?? Array.Empty <IGenericTypeDefinition>();
            var genericClassTypeParameters = genericTypeDefinitions.ToDictionary(td => td.Name, td => td);

            var specificClassTypeParameters = new Dictionary <string, IPythonType>();
            var newBases = new List <IPythonType>();

            // Arguments passed are those of __init__ or it is a copy constructor.
            // They do not necessarily match all of the declared generic parameters.
            // Some generic parameters may be used to specify method return types or
            // method arguments and do not appear in the constructor argument list.
            // Figure out whatever specific types we can from the arguments.
            foreach (var arg in args.Arguments)
            {
                // The argument may either match generic type definition of be a specific type
                // created off generic type. Consider '__init__(self, v: _T)' and
                // 'class A(Generic[K, V], Mapping[K, V])'.
                if (arg.Type is IGenericTypeDefinition argTypeDefinition)
                {
                    // Parameter is annotated as generic type definition. Check if its generic type
                    // name matches any of the generic class parameters. I.e. if there is
                    // an argument like 'v: _T' we need to check if class has matching Generic[_T].
                    if (genericClassTypeParameters.ContainsKey(argTypeDefinition.Name))
                    {
                        // TODO: Check if specific type matches generic type definition constraints and report mismatches.
                        // Assign specific type.
                        if (arg.Value is IMember m && m.GetPythonType() is IPythonType pt)
                        {
                            specificClassTypeParameters[argTypeDefinition.Name] = pt;
                        }
                        else
                        {
                            // TODO: report supplied parameter is not a type.
                        }
                    }
                    else
                    {
                        // TODO: report generic parameter name mismatch.
                    }
                    continue;
                }

                if (arg.Value is IMember member && !member.GetPythonType().IsUnknown())
                {
                    var type = member.GetPythonType();
                    // Type may be a specific type created off generic or just a type
                    // for the copy constructor. Consider 'class A(Generic[K, V], Mapping[K, V])'
                    // constructed as 'd = {1:'a', 2:'b'}; A(d)'. Here we look through bases
                    // and see if any matches the builtin type id. For example, Mapping or Dict
                    // will have BultinTypeId.Dict and we can figure out specific types from
                    // the content of the collection.
                    var b = _bases.OfType <IGenericType>().FirstOrDefault(x => x.TypeId == type.TypeId);
                    if (b != null && b.Parameters.Count > 0)
                    {
                        newBases.Add(type);
                        // Optimistically assign argument types if they match.
                        // Handle common cases directly.
                        GetSpecificTypeFromArgumentValue(b, arg.Value, specificClassTypeParameters);
                        continue;
                    }

                    // Any regular base match?
                    if (_bases.Any(x => x.TypeId == type.TypeId) && !type.Equals(this))
                    {
                        newBases.Add(type);
                    }
                }
            }
 public virtual IMember CreateInstance(string typeName, LocationInfo location, IArgumentSet args)
 => IsAbstract ? null : InnerType.CreateInstance(typeName, location, args);
        public IPythonType CreateSpecificType(IArgumentSet args, IPythonModule declaringModule, LocationInfo location = null)
        {
            location = location ?? LocationInfo.Empty;
            // Get declared generic parameters of the class, i.e. list of Ts in Generic[T1, T2, ...]
            var genericClassParameters = Bases.OfType <IGenericClassParameter>().ToArray();
            // Optimistically use the first one
            // TODO: handle optional generics as class A(Generic[_T1], Optional[Generic[_T2]])
            var genericClassParameter = genericClassParameters.FirstOrDefault();

            // Create map of names listed in Generic[...] in the class definition.
            // We will be filling the map with specific types, if any provided.
            var genericTypeDefinitions     = genericClassParameter?.TypeDefinitions ?? Array.Empty <IGenericTypeDefinition>();
            var genericClassTypeParameters = genericTypeDefinitions.ToDictionary(td => td.Name, td => td);

            var specificClassTypeParameters = new Dictionary <string, IPythonType>();
            var newBases = new List <IPythonType>();

            // Arguments passed are those of __init__ or it is a copy constructor.
            // They do not necessarily match all of the declared generic parameters.
            // Some generic parameters may be used to specify method return types or
            // method arguments and do not appear in the constructor argument list.
            // Figure out whatever specific types we can from the arguments.
            foreach (var a in args.Arguments)
            {
                // The argument may either match generic type definition of be a specific type
                // created off generic type. Consider '__init__(self, v: _T)' and
                // 'class A(Generic[K, V], Mapping[K, V])'.
                if (a.Type is IGenericTypeDefinition argTypeDefinition)
                {
                    // Parameter is annotated as generic type definition. Check if its generic type
                    // name matches any of the generic class parameters. I.e. if there is
                    // an argument like 'v: _T' we need to check if class has matching Generic[_T].
                    if (genericClassTypeParameters.ContainsKey(argTypeDefinition.Name))
                    {
                        // TODO: Check if specific type matches generic type definition constraints and report mismatches.
                        // Assign specific type.
                        if (a.Value is IMember m && m.GetPythonType() is IPythonType pt)
                        {
                            specificClassTypeParameters[argTypeDefinition.Name] = pt;
                        }
                        else
                        {
                            // TODO: report supplied parameter is not a type.
                        }
                    }
                    else
                    {
                        // TODO: report generic parameter name mismatch.
                    }
                }
 public DictArg(string name, Expression expression, LocationInfo location)
 {
     Name       = name;
     Expression = expression;
     Location   = location;
 }
 private Argument(string name, object value, LocationInfo location)
 {
     Name     = name;
     Value    = value;
     Location = location;
 }
 public Argument(IMember member, LocationInfo location) : this(string.Empty, member, location)
 {
 }
 public Argument(IPythonType type, LocationInfo location) : this(type.Name, type, location)
 {
 }
예제 #15
0
        public PythonFunctionOverload(FunctionDefinition fd, IPythonClassMember classMember, IPythonModule declaringModule, LocationInfo location)
            : this(fd.Name, declaringModule, _ => location)
        {
            FunctionDefinition = fd;
            ClassMember        = classMember;
            var ast = (declaringModule as IDocument)?.Analysis.Ast;

            _returnDocumentation = ast != null?fd.ReturnAnnotation?.ToCodeString(ast) : null;
        }
 internal virtual void SetLocation(LocationInfo location) => _location          = location;
 /// <summary>
 /// Create instance of the type, if any.
 /// </summary>
 /// <param name="typeName">Name of the type. Used in specialization scenarios
 /// where constructor may want to create specialized type.</param>
 /// <param name="location">Instance location</param>
 /// <param name="args">Any custom arguments required to create the instance.</param>
 public virtual IMember CreateInstance(string typeName, LocationInfo location, IArgumentSet args)
 => new PythonInstance(this, location);
 // For tests
 internal PythonClassType(string name, IPythonModule declaringModule, LocationInfo location = null)
     : base(name, declaringModule, string.Empty, location ?? LocationInfo.Empty, BuiltinTypeId.Type)
 {
 }
 public Argument(Parameter p, LocationInfo location) :
     this(p.Name, p.Kind, null, p.Annotation, location)
 {
 }