public override IMember GetMember(string name) { lock (MembersLock) { if (Members.TryGetValue(name, out var member)) { return(member); } } // Special case names that we want to add to our own Members dict var is3x = DeclaringModule.Interpreter.LanguageVersion.Is3x(); switch (name) { case "__mro__": case "mro": return(is3x ? PythonCollectionType.CreateList(DeclaringModule, Mro) : UnknownType as IMember); case "__dict__": return(is3x ? DeclaringModule.Interpreter.GetBuiltinType(BuiltinTypeId.Dict) : UnknownType); case @"__weakref__": return(is3x ? DeclaringModule.Interpreter.GetBuiltinType(BuiltinTypeId.Object) : UnknownType); } using (_memberGuard.Push(this, out var reentered)) { if (!reentered) { return(Mro.Skip(1).Select(c => c.GetMember(name)).ExcludeDefault().FirstOrDefault()); } return(null); } }
public override IMember GetMember(string name) { IMember member; lock (_lock) { if (Members.TryGetValue(name, out member)) { return(member); } // Special case names that we want to add to our own Members dict switch (name) { case "__mro__": member = AddMember(name, PythonCollectionType.CreateList(DeclaringModule.Interpreter, LocationInfo.Empty, Mro), true); return(member); } } if (Push()) { try { foreach (var m in Mro.Reverse()) { if (m == this) { return(member); } member = member ?? m.GetMember(name); } } finally { Pop(); } } return(null); }
// Constructor call public override IMember CreateInstance(IArgumentSet args) { var builtins = DeclaringModule.Interpreter.ModuleResolution.BuiltinsModule; // Specializations switch (Name) { case "list": return(PythonCollectionType.CreateList(builtins, args)); case "dict": { // self, then contents var contents = args.Values <IMember>().Skip(1).FirstOrDefault(); return(new PythonDictionary(builtins, contents)); } case "tuple": { var contents = args.Values <IMember>(); return(PythonCollectionType.CreateTuple(builtins, contents)); } } // Metaclasses return type, not instance. if (Bases.MaybeEnumerate().Any(b => b.Name == "type" && b.DeclaringModule.ModuleType == ModuleType.Builtins)) { return(this); } return(new PythonInstance(this)); }
internal static void DeclareParametersInScope(this IArgumentSet args, ExpressionEval eval) { if (eval == null) { return; } // 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. foreach (var a in args.Arguments) { if (a.Value is IMember m && !string.IsNullOrEmpty(a.Name)) { eval.DeclareVariable(a.Name, m, VariableSource.Declaration, a.Location); } } if (args.ListArgument != null && !string.IsNullOrEmpty(args.ListArgument.Name)) { var type = new PythonCollectionType(null, BuiltinTypeId.List, eval.Interpreter, false); var list = new PythonCollection(type, args.ListArgument.Values); eval.DeclareVariable(args.ListArgument.Name, list, VariableSource.Declaration, args.ListArgument.Location); } if (args.DictionaryArgument != null) { foreach (var kvp in args.DictionaryArgument.Arguments) { eval.DeclareVariable(kvp.Key, kvp.Value, VariableSource.Declaration, args.DictionaryArgument.Location); } } }
private IMember GetValueFromTuple(TupleExpression expression) { var contents = new List <IMember>(); foreach (var item in expression.Items) { var value = GetValueFromExpression(item) ?? UnknownType; contents.Add(value); } return(PythonCollectionType.CreateTuple(Module.Interpreter, GetLoc(expression), contents)); }
public IMember GetValueFromSet(SetExpression expression) { var contents = new List <IMember>(); foreach (var item in expression.Items) { var value = GetValueFromExpression(item) ?? UnknownType; contents.Add(value); } return(PythonCollectionType.CreateSet(Interpreter, GetLoc(expression), contents)); }
public IMember GetValueFromSet(SetExpression expression) { var contents = new List <IMember>(); foreach (var item in expression.Items.Take(MaxCollectionSize)) { var value = GetValueFromExpression(item) ?? UnknownType; contents.Add(value); } return(PythonCollectionType.CreateSet(Interpreter, contents, exact: expression.Items.Count <= MaxCollectionSize)); }
public static IMember Range(IPythonModule module, IPythonFunctionOverload overload, LocationInfo location, IArgumentSet argSet) { var args = argSet.Values <IMember>(); if (args.Count > 0) { var type = new PythonCollectionType(null, BuiltinTypeId.List, module.Interpreter, false); return(new PythonCollection(type, location, new[] { args[0] })); } return(null); }
public static IMember Range(IPythonModule module, IPythonFunctionOverload overload, IArgumentSet argSet, IndexSpan indexSpan) { var args = argSet.Values <IMember>(); if (args.Count > 0) { var type = new PythonCollectionType(BuiltinTypeId.List, module.Interpreter.ModuleResolution.BuiltinsModule, false); return(new PythonCollection(type, new[] { args[0] })); } return(null); }
public IMember GetValueFromList(ListExpression expression, LookupOptions lookupOptions = LookupOptions.Normal) { var contents = new List <IMember>(); foreach (var item in expression.Items.Take(MaxCollectionSize)) { var value = GetValueFromExpression(item, lookupOptions) ?? UnknownType; contents.Add(value); } return(PythonCollectionType.CreateList(Module, contents, exact: expression.Items.Count <= MaxCollectionSize)); }
private IMember GetValueFromTuple(TupleExpression expression) { var contents = new List <IMember>(); foreach (var item in expression.Items.Take(MaxCollectionSize)) { var value = GetValueFromExpression(item) ?? UnknownType; contents.Add(value); } return(PythonCollectionType.CreateTuple(Module, contents, exact: expression.Items.Count <= MaxCollectionSize)); }
private async Task <IMember> GetValueFromTupleAsync(TupleExpression expression, CancellationToken cancellationToken = default) { var contents = new List <IMember>(); foreach (var item in expression.Items) { var value = await GetValueFromExpressionAsync(item, cancellationToken) ?? UnknownType; contents.Add(value); } return(PythonCollectionType.CreateTuple(Module.Interpreter, GetLoc(expression), contents)); }
private void HandleAllAppendExtend(CallExpression node) { if (!(node.Target is MemberExpression me)) { return; } if (!IsHandleableAll(me.Target)) { return; } if (node.Args.Count == 0) { return; } var arg = node.Args[0].Expression; var v = Eval.GetValueFromExpression(arg); if (v == null) { _allIsUsable = false; return; } IPythonCollection values = null; switch (me.Name) { case "append": values = PythonCollectionType.CreateList(Module.Interpreter, Eval.GetLoc(arg), new List <IMember>() { v }, exact: true); break; case "extend": values = v as IPythonCollection; break; } if (values == null) { _allIsUsable = false; return; } ExtendAll(node, values); }
private void ExtendAll(Node location, IPythonCollection values) { Eval.LookupNameInScopes(AllVariableName, out var scope, LookupOptions.Global); if (scope == null) { return; } var all = scope.Variables[AllVariableName]?.Value as IPythonCollection; var list = PythonCollectionType.CreateConcatenatedList(Module.Interpreter, all, values); var source = list.IsGeneric() ? VariableSource.Generic : VariableSource.Declaration; Eval.DeclareVariable(AllVariableName, list, source, location); }
private IEnumerable <IPythonType> CreateBases(ClassModel cm, ModuleFactory mf, IGlobalScope gs) { var ntBases = cm.NamedTupleBases .Select(ntb => MemberFactory.CreateMember(ntb, ModuleFactory, GlobalScope, _cls)) .OfType <IPythonType>() .ToArray(); var is3x = mf.Module.Interpreter.LanguageVersion.Is3x(); var basesNames = cm.Bases.Select(b => is3x && b == "object" ? null : b).ExcludeDefault().ToArray(); var bases = basesNames.Select(mf.ConstructType).ExcludeDefault().Concat(ntBases).ToArray(); // Make sure base types are realized foreach (var b in bases.OfType <PythonLazyClassType>()) { b.EnsureContent(); } if (cm.GenericBaseParameters.Length > 0) { // Generic class. Need to reconstruct generic base so code can then // create specific types off the generic class. var genericBase = bases.OfType <IGenericType>().FirstOrDefault(b => b.Name == "Generic"); if (genericBase != null) { var typeVars = cm.GenericBaseParameters.Select(n => gs.Variables[n]?.Value).OfType <IGenericTypeParameter>().ToArray(); //Debug.Assert(typeVars.Length > 0, "Class generic type parameters were not defined in the module during restore"); if (typeVars.Length > 0) { var genericWithParameters = genericBase.CreateSpecificType(new ArgumentSet(typeVars, null, null)); if (genericWithParameters != null) { bases = bases.Except(Enumerable.Repeat(genericBase, 1)).Concat(Enumerable.Repeat(genericWithParameters, 1)).ToArray(); } } } else { Debug.Fail("Generic class does not have generic base."); } } if (bases.Length > 0) { _cls.AddMember("__base__", bases[0], true); } _cls.AddMember("__bases__", PythonCollectionType.CreateList(DeclaringModule.Interpreter.ModuleResolution.BuiltinsModule, bases), true); return(bases); }
private void ExtendAll(Node declNode, IReadOnlyList <IMember> values) { Eval.LookupNameInScopes(AllVariableName, out var scope, LookupOptions.Normal); if (scope == null) { return; } var loc = Eval.GetLoc(declNode); var allContents = (scope.Variables[AllVariableName].Value as IPythonCollection)?.Contents; var list = PythonCollectionType.CreateConcatenatedList(Module.Interpreter, loc, allContents, values); var source = list.IsGeneric() ? VariableSource.Generic : VariableSource.Declaration; Eval.DeclareVariable(AllVariableName, list, source, loc); }
public override IMember GetMember(string name) { IMember member; lock (_lock) { if (Members.TryGetValue(name, out member)) { return(member); } // Special case names that we want to add to our own Members dict var is3x = DeclaringModule.Interpreter.LanguageVersion.Is3x(); switch (name) { case "__mro__": case "mro": return(is3x ? PythonCollectionType.CreateList(DeclaringModule.Interpreter, LocationInfo.Empty, Mro) : UnknownType); case "__dict__": return(is3x ? DeclaringModule.Interpreter.GetBuiltinType(BuiltinTypeId.Dict) : UnknownType); case @"__weakref__": return(is3x ? DeclaringModule.Interpreter.GetBuiltinType(BuiltinTypeId.Object) : UnknownType); } } if (Push(this)) { try { foreach (var m in Mro.Reverse()) { if (m == this) { return(member); } member = member ?? m.GetMember(name); } } finally { Pop(); } } return(null); }
/// <summary> /// Sets class bases. If scope is provided, detects loops in base classes and removes them. /// </summary> /// <param name="bases">List of base types.</param> /// <param name="currentScope">Current scope to look up base types. /// Can be null if class is restored from database, in which case /// there is no need to try and disambiguate bases.</param> internal void SetBases(IEnumerable <IPythonType> bases, IScope currentScope = null) { if (_bases != null) { return; // Already set } // Consider // from X import A // class A(A): ... bases = DisambiguateBases(bases, currentScope).ToArray(); // For Python 3+ attach object as a base class by default except for the object class itself. if (DeclaringModule.Interpreter.LanguageVersion.Is3x() && DeclaringModule.ModuleType != ModuleType.Builtins) { var objectType = DeclaringModule.Interpreter.GetBuiltinType(BuiltinTypeId.Object); // During processing of builtins module some types may not be available yet. // Specialization will attach proper base at the end. Debug.Assert(!objectType.IsUnknown()); if (!bases.Any(b => objectType.Equals(b))) { bases = bases.Concat(Enumerable.Repeat(objectType, 1)); } } _bases = bases.ToList(); if (_bases.Count > 0) { AddMember("__base__", _bases[0], true); } // Invalidate MRO _mro = null; DecideGeneric(); if (DeclaringModule is BuiltinsPythonModule) { // TODO: If necessary, we can set __bases__ on builtins when the module is fully analyzed. return; } AddMember("__bases__", PythonCollectionType.CreateList(DeclaringModule.Interpreter.ModuleResolution.BuiltinsModule, _bases), true); }
public IMember GetValueFromComprehension(Comprehension node) { var oldVariables = CurrentScope.Variables.OfType <Variable>().ToDictionary(k => k.Name, v => v); try { ProcessComprehension(node); // TODO: Evaluate comprehensions to produce exact contents, if possible. switch (node) { case ListComprehension lc: var v1 = GetValueFromExpression(lc.Item) ?? UnknownType; return(PythonCollectionType.CreateList(Module, new[] { v1 })); case SetComprehension sc: var v2 = GetValueFromExpression(sc.Item) ?? UnknownType; return(PythonCollectionType.CreateSet(Module, new[] { v2 })); case DictionaryComprehension dc: var k = GetValueFromExpression(dc.Key) ?? UnknownType; var v = GetValueFromExpression(dc.Value) ?? UnknownType; return(new PythonDictionary(new PythonDictionaryType(Interpreter.ModuleResolution.BuiltinsModule), new Dictionary <IMember, IMember> { { k, v } })); } return(UnknownType); } finally { // Remove temporary variables since this is assignment and the right hand // side comprehension does not leak internal variables into the scope. var newVariables = CurrentScope.Variables.ToDictionary(k => k.Name, v => v); var variables = (VariableCollection)CurrentScope.Variables; foreach (var kvp in newVariables) { if (!oldVariables.ContainsKey(kvp.Key)) { variables.RemoveVariable(kvp.Key); } } } }
internal void SetBases(IPythonInterpreter interpreter, IEnumerable <IPythonType> bases) { lock (_lock) { if (Bases != null) { return; // Already set } Bases = bases.MaybeEnumerate().ToArray(); if (Bases.Count > 0) { AddMember("__base__", Bases[0], true); } if (!(DeclaringModule is BuiltinsPythonModule)) { // TODO: If necessary, we can set __bases__ on builtins when the module is fully analyzed. AddMember("__bases__", PythonCollectionType.CreateList(DeclaringModule.Interpreter, LocationInfo.Empty, Bases), true); } } }
// Constructor call public override IMember CreateInstance(string typeName, IArgumentSet args) { // Specializations switch (typeName) { case "list": return(PythonCollectionType.CreateList(DeclaringModule.Interpreter, args)); case "dict": { // self, then contents var contents = args.Values <IMember>().Skip(1).FirstOrDefault(); return(new PythonDictionary(DeclaringModule.Interpreter, contents)); } case "tuple": { var contents = args.Values <IMember>(); return(PythonCollectionType.CreateTuple(DeclaringModule.Interpreter, contents)); } } return(new PythonInstance(this)); }
internal void SetBases(IEnumerable <IPythonType> bases) { lock (_lock) { if (_bases != null) { return; // Already set } bases = bases != null?bases.Where(b => !b.GetPythonType().IsUnknown()).ToArray() : Array.Empty <IPythonType>(); // For Python 3+ attach object as a base class by default except for the object class itself. if (DeclaringModule.Interpreter.LanguageVersion.Is3x() && DeclaringModule.ModuleType != ModuleType.Builtins) { var objectType = DeclaringModule.Interpreter.GetBuiltinType(BuiltinTypeId.Object); // During processing of builtins module some types may not be available yet. // Specialization will attach proper base at the end. Debug.Assert(!objectType.IsUnknown()); if (!bases.Any(b => objectType.Equals(b))) { bases = bases.Concat(Enumerable.Repeat(objectType, 1)); } } _bases = bases.ToList(); if (_bases.Count > 0) { AddMember("__base__", _bases[0], true); } // Invalidate MRO _mro = null; if (DeclaringModule is BuiltinsPythonModule) { // TODO: If necessary, we can set __bases__ on builtins when the module is fully analyzed. return; } AddMember("__bases__", PythonCollectionType.CreateList(DeclaringModule.Interpreter, LocationInfo.Empty, _bases), true); } }
public override IMember GetMember(string name) { // Push/Pop should be lock protected. if (Members.TryGetValue(name, out var member)) { return(member); } // Special case names that we want to add to our own Members dict var is3x = DeclaringModule.Interpreter.LanguageVersion.Is3x(); switch (name) { case "__mro__": case "mro": return(is3x ? PythonCollectionType.CreateList(DeclaringModule.Interpreter, Mro) : UnknownType as IMember); case "__dict__": return(is3x ? DeclaringModule.Interpreter.GetBuiltinType(BuiltinTypeId.Dict) : UnknownType); case @"__weakref__": return(is3x ? DeclaringModule.Interpreter.GetBuiltinType(BuiltinTypeId.Object) : UnknownType); } using (_memberGuard.Push(this, out var reentered)) { if (!reentered) { foreach (var m in Mro.Reverse()) { if (m == this) { return(member); } member = member ?? m.GetMember(name); } } return(null); } }
// Constructor call public override IPythonInstance CreateInstance(IArgumentSet args) { var builtins = DeclaringModule.Interpreter.ModuleResolution.BuiltinsModule; // Specializations switch (Name) { case "list": return(PythonCollectionType.CreateList(builtins, args)); case "dict": { // self, then contents var contents = args.Values <IMember>().Skip(1).FirstOrDefault(); return(new PythonDictionary(builtins, contents)); } case "tuple": { var contents = args.Values <IMember>(); return(PythonCollectionType.CreateTuple(builtins, contents)); } } return(new PythonInstance(this)); }
public static IMember List(IPythonInterpreter interpreter, IPythonFunctionOverload overload, LocationInfo location, IReadOnlyList <IMember> args) => PythonCollectionType.CreateList(interpreter, location, args);
private IMember GetValueFromBinaryOp(Expression expr) { if (expr is AndExpression) { return(Interpreter.GetBuiltinType(BuiltinTypeId.Bool)); } if (expr is OrExpression orexp) { // Consider 'self.__params = types.MappingProxyType(params or {})' var leftSide = GetValueFromExpression(orexp.Left); if (!leftSide.IsUnknown()) { return(leftSide); } var rightSide = GetValueFromExpression(orexp.Right); return(rightSide.IsUnknown() ? Interpreter.GetBuiltinType(BuiltinTypeId.Bool) : rightSide); } if (!(expr is BinaryExpression binop) || binop.Left == null) { return(null); } // TODO: Specific parsing // TODO: warn about incompatible types like 'str' + 1 switch (binop.Operator) { case PythonOperator.Equal: case PythonOperator.GreaterThan: case PythonOperator.GreaterThanOrEqual: case PythonOperator.In: case PythonOperator.Is: case PythonOperator.IsNot: case PythonOperator.LessThan: case PythonOperator.LessThanOrEqual: case PythonOperator.Not: case PythonOperator.NotEqual: case PythonOperator.NotIn: // Assume all of these return True/False return(Interpreter.GetBuiltinType(BuiltinTypeId.Bool)); case PythonOperator.Divide: case PythonOperator.TrueDivide: if (Interpreter.LanguageVersion.Is3x()) { return(Interpreter.GetBuiltinType(BuiltinTypeId.Float)); } break; } var left = GetValueFromExpression(binop.Left) ?? UnknownType; var right = GetValueFromExpression(binop.Right) ?? UnknownType; var rightType = right.GetPythonType(); if (rightType?.TypeId == BuiltinTypeId.Float) { return(right); } var leftType = left.GetPythonType(); if (leftType?.TypeId == BuiltinTypeId.Float) { return(left); } if (rightType?.TypeId == BuiltinTypeId.Long) { return(right); } if (leftType?.TypeId == BuiltinTypeId.Long) { return(left); } if (binop.Operator == PythonOperator.Add && leftType?.TypeId == BuiltinTypeId.List && rightType?.TypeId == BuiltinTypeId.List && left is IPythonCollection lc && right is IPythonCollection rc) { return(PythonCollectionType.CreateConcatenatedList(Module.Interpreter, GetLoc(expr), lc, rc)); } return(left.IsUnknown() ? right : left); }
public static IMember List(IPythonInterpreter interpreter, IPythonFunctionOverload overload, LocationInfo location, IArgumentSet argSet) => PythonCollectionType.CreateList(interpreter, location, argSet);
public static IMember List(IPythonInterpreter interpreter, IPythonFunctionOverload overload, IArgumentSet argSet, IndexSpan indexSpan) => PythonCollectionType.CreateList(interpreter.ModuleResolution.BuiltinsModule, argSet);
private IMember GetValueFromBinaryOp(Expression expr, LookupOptions lookupOptions) { if (expr is AndExpression a) { GetValueFromExpression(a.Left, lookupOptions); GetValueFromExpression(a.Right, lookupOptions); return(Interpreter.GetBuiltinType(BuiltinTypeId.Bool)); } if (expr is OrExpression orexp) { // Consider 'self.__params = types.MappingProxyType(params or {})' var leftSide = GetValueFromExpression(orexp.Left, lookupOptions); if (!leftSide.IsUnknown()) { return(leftSide); } var rightSide = GetValueFromExpression(orexp.Right, lookupOptions); return(rightSide.IsUnknown() ? Interpreter.GetBuiltinType(BuiltinTypeId.Bool) : rightSide); } if (!(expr is BinaryExpression binop) || binop.Left == null) { return(null); } var op = binop.Operator; var left = GetValueFromExpression(binop.Left, lookupOptions) ?? UnknownType; var right = GetValueFromExpression(binop.Right, lookupOptions) ?? UnknownType; if (left.IsUnknown() && right.IsUnknown()) { // Fast path for when nothing below will give any results. if (op.IsComparison()) { return(Interpreter.GetBuiltinType(BuiltinTypeId.Bool)); } return(UnknownType); } var leftType = left.GetPythonType(); var rightType = right.GetPythonType(); var leftTypeId = leftType.TypeId; var rightTypeId = rightType.TypeId; if (op == PythonOperator.Add && leftTypeId == rightTypeId && left is IPythonCollection lc && right is IPythonCollection rc) { switch (leftTypeId) { case BuiltinTypeId.List: return(PythonCollectionType.CreateConcatenatedList(Module, lc, rc)); case BuiltinTypeId.Tuple: return(PythonCollectionType.CreateConcatenatedTuple(Module, lc, rc)); } } // Mod-style string formatting; don't bother looking at the right side. if (op == PythonOperator.Mod && (leftTypeId == BuiltinTypeId.Str || leftTypeId == BuiltinTypeId.Unicode)) { return(Interpreter.GetBuiltinType(leftTypeId)); } var leftIsSupported = IsSupportedBinopBuiltin(leftTypeId); var rightIsSupported = IsSupportedBinopBuiltin(rightTypeId); if (leftIsSupported && rightIsSupported) { if (TryGetValueFromBuiltinBinaryOp(op, leftTypeId, rightTypeId, Interpreter.LanguageVersion.Is3x(), out var member)) { return(member); } } if (leftIsSupported) { IMember ret; if (op.IsComparison()) { // If the op is a comparison, and the thing on the left is the builtin, // flip the operation and call it instead. ret = CallOperator(op.InvertComparison(), right, rightType, left, leftType, expr, tryRight: false); } else { ret = CallOperator(op, left, leftType, right, rightType, expr, tryLeft: false); } if (!ret.IsUnknown()) { return(ret); } return(op.IsComparison() ? Interpreter.GetBuiltinType(BuiltinTypeId.Bool) : left); } if (rightIsSupported) { // Try calling the function on the left side, otherwise just return right. var ret = CallOperator(op, left, leftType, right, rightType, expr, tryRight: false); if (!ret.IsUnknown()) { return(ret); } return(op.IsComparison() ? Interpreter.GetBuiltinType(BuiltinTypeId.Bool) : right); } var callRet = CallOperator(op, left, leftType, right, rightType, expr); if (!callRet.IsUnknown()) { return(callRet); } if (op.IsComparison()) { callRet = CallOperator(op.InvertComparison(), right, rightType, left, leftType, expr); if (!callRet.IsUnknown()) { return(callRet); } } // TODO: Specific parsing // TODO: warn about incompatible types like 'str' + 1 switch (op) { case PythonOperator.Equal: case PythonOperator.GreaterThan: case PythonOperator.GreaterThanOrEqual: case PythonOperator.In: case PythonOperator.Is: case PythonOperator.IsNot: case PythonOperator.LessThan: case PythonOperator.LessThanOrEqual: case PythonOperator.Not: case PythonOperator.NotEqual: case PythonOperator.NotIn: // Assume all of these return True/False return(Interpreter.GetBuiltinType(BuiltinTypeId.Bool)); case PythonOperator.Divide: case PythonOperator.TrueDivide: if (Interpreter.LanguageVersion.Is3x()) { return(Interpreter.GetBuiltinType(BuiltinTypeId.Float)); } break; } return(left.IsUnknown() ? right : left); }
private IPythonCollection CreateList(IReadOnlyList <IMember> items) => PythonCollectionType.CreateList(Type.DeclaringModule.Interpreter, items, false);