// 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)); }
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; }
public PythonPropertyType(string name, IPythonModule declaringModule, IPythonType declaringType, bool isAbstract, LocationInfo location) : base(name, declaringModule, null, location) { DeclaringType = declaringType; IsAbstract = isAbstract; }
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) { }
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) { }