diff --git a/Src/IronPython.Modules/IterTools.cs b/Src/IronPython.Modules/IterTools.cs index f0efd9155..5de12db3d 100644 --- a/Src/IronPython.Modules/IterTools.cs +++ b/Src/IronPython.Modules/IterTools.cs @@ -743,11 +743,11 @@ private static Exception UnexpectedKeywordArgument(IDictionary p [PythonType] public class product : IterBase { - public product(params object[] iterables) { - InnerEnumerator = Yielder(ArrayUtils.ConvertAll(iterables, x => new PythonList(PythonOps.GetEnumerator(x)))); + public product(CodeContext context, params object[] iterables) { + InnerEnumerator = Yielder(ArrayUtils.ConvertAll(iterables, x => new PythonList(context, PythonOps.GetEnumerator(x)))); } - public product([ParamDictionary]IDictionary paramDict, params object[] iterables) { + public product(CodeContext context, [ParamDictionary]IDictionary paramDict, params object[] iterables) { object repeat; int iRepeat = 1; if (paramDict.TryGetValue("repeat", out repeat)) { @@ -768,7 +768,7 @@ public product([ParamDictionary]IDictionary paramDict, params ob PythonList[] finalIterables = new PythonList[iterables.Length * iRepeat]; for (int i = 0; i < iRepeat; i++) { for (int j = 0; j < iterables.Length; j++) { - finalIterables[i * iterables.Length + j] = new PythonList(iterables[j]); + finalIterables[i * iterables.Length + j] = new PythonList(context, iterables[j]); } } InnerEnumerator = Yielder(finalIterables); @@ -823,8 +823,8 @@ private IEnumerator Yielder(PythonList[] iterables) { public class combinations : IterBase { private readonly PythonList _data; - public combinations(object iterable, object r) { - _data = new PythonList(iterable); + public combinations(CodeContext context, object iterable, object r) { + _data = new PythonList(context, iterable); InnerEnumerator = Yielder(GetR(r, _data)); } @@ -893,8 +893,8 @@ private IEnumerator Yielder(int r) { public class combinations_with_replacement : IterBase { private readonly PythonList _data; - public combinations_with_replacement(object iterable, object r) { - _data = new PythonList(iterable); + public combinations_with_replacement(CodeContext context, object iterable, object r) { + _data = new PythonList(context, iterable); InnerEnumerator = Yielder(GetR(r, _data)); } @@ -962,14 +962,14 @@ private IEnumerator Yielder(int r) { public class permutations : IterBase { private readonly PythonList _data; - public permutations(object iterable) { - _data = new PythonList(iterable); + public permutations(CodeContext context, object iterable) { + _data = new PythonList(context, iterable); InnerEnumerator = Yielder(_data.Count); } - public permutations(object iterable, object r) { - _data = new PythonList(iterable); + public permutations(CodeContext context, object iterable, object r) { + _data = new PythonList(context, iterable); InnerEnumerator = Yielder(GetR(r, _data)); } @@ -1160,7 +1160,7 @@ private IEnumerator Yielder(CodeContext context, object function, IEnume objargs[i] = args[i]; } } else { - PythonList argsList = new PythonList(PythonOps.GetEnumerator(iter.Current)); + PythonList argsList = new PythonList(context, PythonOps.GetEnumerator(iter.Current)); objargs = ArrayUtils.ToArray(argsList); } diff --git a/Src/IronPython.Modules/_ssl.cs b/Src/IronPython.Modules/_ssl.cs index 2c202d531..02c871579 100644 --- a/Src/IronPython.Modules/_ssl.cs +++ b/Src/IronPython.Modules/_ssl.cs @@ -208,7 +208,7 @@ public void load_cert_chain(CodeContext context, string certfile, string keyfile public PythonList get_ca_certs(CodeContext context, bool binary_form = false) { if (binary_form) throw new NotImplementedException(nameof(binary_form)); - return new PythonList(_cert_store.Cast().Select(c => CertificateToPython(context, c))); + return PythonList.FromEnumerable(_cert_store.Cast().Select(c => CertificateToPython(context, c))); } public void load_verify_locations(CodeContext context, object cafile = null, string capath = null, object cadata = null) { diff --git a/Src/IronPython.Modules/grp.cs b/Src/IronPython.Modules/grp.cs index 15e233316..80f3a4520 100644 --- a/Src/IronPython.Modules/grp.cs +++ b/Src/IronPython.Modules/grp.cs @@ -76,7 +76,7 @@ internal struct_group(string gr_name, string gr_passwd, int gr_gid, PythonList g private static struct_group Make(IntPtr pwd) { group g = (group)Marshal.PtrToStructure(pwd, typeof(group)); - return new struct_group(g.gr_name, g.gr_passwd, g.gr_gid, new PythonList(MarshalStringArray(g.gr_mem))); + return new struct_group(g.gr_name, g.gr_passwd, g.gr_gid, PythonList.FromEnumerable(MarshalStringArray(g.gr_mem))); } private static IEnumerable MarshalStringArray(IntPtr arrayPtr) diff --git a/Src/IronPython.Modules/xxsubtype.cs b/Src/IronPython.Modules/xxsubtype.cs index 031e092e8..8980fc8c1 100644 --- a/Src/IronPython.Modules/xxsubtype.cs +++ b/Src/IronPython.Modules/xxsubtype.cs @@ -24,8 +24,8 @@ public spamlist() : base() { } - public spamlist(object sequence) - : base(sequence) { + public spamlist(CodeContext context, object sequence) + : base(context, sequence) { } private int _state; diff --git a/Src/IronPython.SQLite/Cursor.cs b/Src/IronPython.SQLite/Cursor.cs index 772429d7c..8570ad7ef 100644 --- a/Src/IronPython.SQLite/Cursor.cs +++ b/Src/IronPython.SQLite/Cursor.cs @@ -121,7 +121,7 @@ private object queryExecute(CodeContext context, bool multiple, object operation if(multiple) { if(args != null) - parameters_iter = PythonOps.CreatePythonEnumerator(args); + parameters_iter = PythonOps.CreatePythonEnumerator(context, args); } else { diff --git a/Src/IronPython/Modules/Builtin.cs b/Src/IronPython/Modules/Builtin.cs index f2895ac8c..3dad01e67 100644 --- a/Src/IronPython/Modules/Builtin.cs +++ b/Src/IronPython/Modules/Builtin.cs @@ -250,7 +250,7 @@ public static void delattr(CodeContext/*!*/ context, object? o, [NotNone] string public static PythonType dict => TypeCache.Dict; public static PythonList dir(CodeContext/*!*/ context) { - PythonList res = new PythonList(context.Dict.Keys); + PythonList res = new PythonList(context, context.Dict.Keys); res.Sort(context); return res; @@ -258,7 +258,7 @@ public static PythonList dir(CodeContext/*!*/ context) { public static PythonList dir(CodeContext/*!*/ context, object? o) { IList ret = PythonOps.GetAttrNames(context, o); - PythonList lret = new PythonList(ret); + PythonList lret = new PythonList(context, ret); lret.Sort(context); return lret; } diff --git a/Src/IronPython/Modules/_ast.cs b/Src/IronPython/Modules/_ast.cs index 679e1e70e..42d5deabc 100755 --- a/Src/IronPython/Modules/_ast.cs +++ b/Src/IronPython/Modules/_ast.cs @@ -1773,7 +1773,7 @@ public Global(PythonList names, [Optional] int? lineno, [Optional] int? col_offs internal Global(GlobalStatement stmt) : this() { - names = new PythonList(stmt.Names); + names = PythonList.FromGenericCollection(stmt.Names); } internal override Statement Revert() { @@ -2345,7 +2345,7 @@ public Nonlocal(PythonList names, [Optional] int? lineno, [Optional] int? col_of internal Nonlocal(NonlocalStatement stmt) : this() { - names = new PythonList(stmt.Names); + names = PythonList.FromGenericCollection(stmt.Names); } internal override Statement Revert() { diff --git a/Src/IronPython/Runtime/Binding/ConversionBinder.cs b/Src/IronPython/Runtime/Binding/ConversionBinder.cs index 507e395a6..61349b7aa 100644 --- a/Src/IronPython/Runtime/Binding/ConversionBinder.cs +++ b/Src/IronPython/Runtime/Binding/ConversionBinder.cs @@ -781,7 +781,7 @@ internal static DynamicMetaObject ConvertToIEnumerable(DynamicMetaObjectBinder/* PythonTypeSlot pts; if (pt.TryResolveSlot(context, "__iter__", out pts)) { - return MakeIterRule(metaUserObject, nameof(PythonOps.CreatePythonEnumerable)); + return MakeIterRule(metaUserObject, pyContext, nameof(PythonOps.CreatePythonEnumerable)); } else if (pt.TryResolveSlot(context, "__getitem__", out pts)) { return MakeGetItemIterable(metaUserObject, pyContext, pts, nameof(PythonOps.CreateItemEnumerable)); } @@ -804,6 +804,7 @@ internal static DynamicMetaObject ConvertToIEnumerator(DynamicMetaObjectBinder/* new[] { tmp }, Expression.Call( typeof(PythonOps).GetMethod(nameof(PythonOps.CreatePythonEnumerator)), + AstUtils.Constant(context), Ast.Block( MetaPythonObject.MakeTryGetTypeMember( state, @@ -839,6 +840,7 @@ private static DynamicMetaObject MakeGetItemIterable(DynamicMetaObject metaUserO new[] { tmp }, Expression.Call( typeof(PythonOps).GetMethod(method), + AstUtils.Constant(state.SharedContext), AstUtils.Convert(metaUserObject.Expression, typeof(object)), Ast.Block( MetaPythonObject.MakeTryGetTypeMember( @@ -867,10 +869,11 @@ private static DynamicMetaObject MakeGetItemIterable(DynamicMetaObject metaUserO ); } - private static DynamicMetaObject/*!*/ MakeIterRule(DynamicMetaObject/*!*/ self, string methodName) { + private static DynamicMetaObject/*!*/ MakeIterRule(DynamicMetaObject/*!*/ self, PythonContext state, string methodName) { return new DynamicMetaObject( Ast.Call( typeof(PythonOps).GetMethod(methodName), + AstUtils.Constant(state.SharedContext), AstUtils.Convert(self.Expression, typeof(object)) ), self.Restrictions diff --git a/Src/IronPython/Runtime/Binding/MetaPythonFunction.cs b/Src/IronPython/Runtime/Binding/MetaPythonFunction.cs index 245afa076..cd492f595 100644 --- a/Src/IronPython/Runtime/Binding/MetaPythonFunction.cs +++ b/Src/IronPython/Runtime/Binding/MetaPythonFunction.cs @@ -955,6 +955,7 @@ private void MakeParamsCopy(Expression/*!*/ userList) { _params, Ast.Call( typeof(PythonOps).GetMethod(nameof(PythonOps.CopyAndVerifyParamsList)), + _codeContext ?? AstUtils.Constant(DefaultContext.Default), AstUtils.Convert(GetFunctionParam(), typeof(PythonFunction)), AstUtils.Convert(userList, typeof(object)) ) diff --git a/Src/IronPython/Runtime/Bytes.cs b/Src/IronPython/Runtime/Bytes.cs index 034290cc3..1bb46f213 100644 --- a/Src/IronPython/Runtime/Bytes.cs +++ b/Src/IronPython/Runtime/Bytes.cs @@ -1165,7 +1165,7 @@ public IEnumerator GetEnumerator() { System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { // workaround for https://github.com/IronLanguages/ironpython3/issues/1519 if (GetType() != typeof(Bytes) && PythonTypeOps.TryInvokeUnaryOperator(DefaultContext.Default, this, "__iter__", out object? iter)) { - return new PythonEnumerator(iter); + return new PythonEnumerator(DefaultContext.Default, iter); } return _bytes.GetEnumerator(); } diff --git a/Src/IronPython/Runtime/ClrModule.cs b/Src/IronPython/Runtime/ClrModule.cs index 0930d6620..7e7b404bc 100644 --- a/Src/IronPython/Runtime/ClrModule.cs +++ b/Src/IronPython/Runtime/ClrModule.cs @@ -837,9 +837,9 @@ private static bool IsInstanceOf(object obj, PythonType pt) { /// /// returns the result of dir(o) as-if "import clr" has not been performed. /// - public static PythonList Dir(object o) { + public static PythonList Dir(CodeContext context, object o) { IList ret = PythonOps.GetAttrNames(DefaultContext.Default, o); - PythonList lret = new PythonList(ret); + PythonList lret = new PythonList(context, ret); lret.Sort(DefaultContext.Default); return lret; } @@ -847,9 +847,9 @@ public static PythonList Dir(object o) { /// /// Returns the result of dir(o) as-if "import clr" has been performed. /// - public static PythonList DirClr(object o) { + public static PythonList DirClr(CodeContext context, object o) { IList ret = PythonOps.GetAttrNames(DefaultContext.DefaultCLS, o); - PythonList lret = new PythonList(ret); + PythonList lret = new PythonList(context, ret); lret.Sort(DefaultContext.DefaultCLS); return lret; } diff --git a/Src/IronPython/Runtime/Enumerate.cs b/Src/IronPython/Runtime/Enumerate.cs index 654402cf9..c8fae3449 100644 --- a/Src/IronPython/Runtime/Enumerate.cs +++ b/Src/IronPython/Runtime/Enumerate.cs @@ -28,14 +28,14 @@ public class Enumerate : IEnumerator, IEnumerator { private readonly IEnumerator _iter; private object _index; - public Enumerate(object iter) { - _iter = PythonOps.GetEnumerator(iter); + public Enumerate(CodeContext context, object iter) { + _iter = PythonOps.GetEnumerator(context, iter); _index = ScriptingRuntimeHelpers.Int32ToObject(-1); } public Enumerate(CodeContext context, object iter, object start) { object index = PythonOps.Index(start); - _iter = PythonOps.GetEnumerator(iter); + _iter = PythonOps.GetEnumerator(context, iter); _index = context.LanguageContext.Operation(Binding.PythonOperationKind.Subtract, index, ScriptingRuntimeHelpers.Int32ToObject(1)); } @@ -176,16 +176,17 @@ void IDisposable.Dispose() { [PythonType("enumerator")] public class PythonEnumerator : IEnumerator { + private readonly CodeContext _context; private readonly object _baseObject; private object _current; public static bool TryCastIEnumer(object baseObject, out IEnumerator enumerator) { - if (baseObject is IEnumerator) { - enumerator = (IEnumerator)baseObject; + if (baseObject is IEnumerator et) { + enumerator = et; return true; } - if (baseObject is IEnumerable) { - enumerator = ((IEnumerable)baseObject).GetEnumerator(); + if (baseObject is IEnumerable en) { + enumerator = en.GetEnumerator(); return true; } @@ -193,18 +194,18 @@ public static bool TryCastIEnumer(object baseObject, out IEnumerator enumerator) return false; } - public static bool TryCreate(object baseObject, out IEnumerator enumerator) { + public static bool TryCreate(CodeContext context, object baseObject, out IEnumerator enumerator) { if (TryCastIEnumer(baseObject, out enumerator)) { return true; } - if (PythonOps.TryGetBoundAttr(baseObject, "__iter__", out object iter)) { + if (PythonOps.TryGetBoundAttr(context, baseObject, "__iter__", out object iter)) { object iterator = PythonCalls.Call(iter); // don't re-wrap if we don't need to (common case is PythonGenerator). if (TryCastIEnumer(iterator, out enumerator)) { return true; } - enumerator = new PythonEnumerator(iterator); + enumerator = new PythonEnumerator(context, iterator); return true; } else { enumerator = null; @@ -212,17 +213,18 @@ public static bool TryCreate(object baseObject, out IEnumerator enumerator) { } } - public static IEnumerator Create(object baseObject) { + public static IEnumerator Create(CodeContext context, object baseObject) { IEnumerator res; - if (!TryCreate(baseObject, out res)) { + if (!TryCreate(context, baseObject, out res)) { throw PythonOps.TypeError("cannot convert {0} to IEnumerator", PythonOps.GetPythonTypeName(baseObject)); } return res; } - internal PythonEnumerator(object iter) { + internal PythonEnumerator(CodeContext context, object iter) { Debug.Assert(!(iter is PythonGenerator)); + _context = context; _baseObject = iter; } @@ -244,14 +246,14 @@ public object Current { /// /// True if moving was successfull public bool MoveNext() { - PythonTypeOps.TryGetOperator(DefaultContext.Default, _baseObject, "__next__", out object nextMethod); + PythonTypeOps.TryGetOperator(_context, _baseObject, "__next__", out object nextMethod); if (nextMethod == null) { throw PythonOps.TypeErrorForNotAnIterator(_baseObject); } try { - _current = DefaultContext.Default.LanguageContext.CallLightEh(DefaultContext.Default, nextMethod); + _current = _context.LanguageContext.CallLightEh(_context, nextMethod); Exception lightEh = LightExceptions.GetLightException(_current); if (lightEh != null) { if (lightEh is StopIterationException) { @@ -275,21 +277,22 @@ public object __iter__() { [PythonType("enumerable")] public class PythonEnumerable : IEnumerable { + private readonly CodeContext _context; private readonly object _iterator; - public static bool TryCreate(object baseEnumerator, out IEnumerable enumerator) { + public static bool TryCreate(CodeContext context, object baseEnumerator, out IEnumerable enumerator) { Debug.Assert(!(baseEnumerator is IEnumerable) || baseEnumerator is IPythonObject); // we shouldn't re-wrap things that don't need it - if (PythonOps.TryGetBoundAttr(baseEnumerator, "__iter__", out object iter)) { - object iterator = PythonCalls.Call(iter); - if (iterator is IEnumerable) { - enumerator = (IEnumerable)iterator; + if (PythonOps.TryGetBoundAttr(context, baseEnumerator, "__iter__", out object iter)) { + object iterator = PythonCalls.Call(context, iter); + if (iterator is IEnumerable en) { + enumerator = en; } else { - if (!PythonOps.TryGetBoundAttr(iterator, "__next__", out _)) { + if (!PythonOps.TryGetBoundAttr(context, iterator, "__next__", out _)) { enumerator = null; return false; } - enumerator = new PythonEnumerable(iterator); + enumerator = new PythonEnumerable(context, iterator); } return true; } else { @@ -298,22 +301,23 @@ public static bool TryCreate(object baseEnumerator, out IEnumerable enumerator) } } - public static IEnumerable Create(object baseObject) { + public static IEnumerable Create(CodeContext context, object baseObject) { IEnumerable res; - if (!TryCreate(baseObject, out res)) { + if (!TryCreate(context, baseObject, out res)) { throw PythonOps.TypeError("cannot convert {0} to IEnumerable", PythonOps.GetPythonTypeName(baseObject)); } return res; } - private PythonEnumerable(object iterator) { - this._iterator = iterator; + private PythonEnumerable(CodeContext context, object iterator) { + _iterator = iterator; + _context = iterator is IEnumerable ? DefaultContext.Default : context; } #region IEnumerable Members IEnumerator IEnumerable.GetEnumerator() { - return _iterator as IEnumerator ?? new PythonEnumerator(_iterator); + return _iterator as IEnumerator ?? new PythonEnumerator(_context, _iterator); } #endregion @@ -321,6 +325,7 @@ IEnumerator IEnumerable.GetEnumerator() { [PythonType("iterator")] public sealed class ItemEnumerator : IEnumerator { + private readonly CodeContext _context; // The actual object on which we are calling __getitem__() private object _source; private object _getItemMethod; @@ -328,7 +333,8 @@ public sealed class ItemEnumerator : IEnumerator { private object _current; private int _index; - internal ItemEnumerator(object source, object getItemMethod, CallSite> site) { + internal ItemEnumerator(CodeContext context, object source, object getItemMethod, CallSite> site) { + _context = context; _source = source; _getItemMethod = getItemMethod; _site = site; @@ -374,7 +380,7 @@ bool IEnumerator.MoveNext() { } try { - _current = _site.Target(_site, DefaultContext.Default, _getItemMethod, _index); + _current = _site.Target(_site, _context, _getItemMethod, _index); _index++; return true; } catch (IndexOutOfRangeException) { @@ -404,11 +410,13 @@ void IEnumerator.Reset() { [PythonType("iterable")] public sealed class ItemEnumerable : IEnumerable { + private readonly CodeContext _context; private readonly object _source; private readonly object _getitem; private readonly CallSite> _site; - internal ItemEnumerable(object source, object getitem, CallSite> site) { + internal ItemEnumerable(CodeContext context, object source, object getitem, CallSite> site) { + _context = context; _source = source; _getitem = getitem; _site = site; @@ -421,7 +429,7 @@ public IEnumerator __iter__() { #region IEnumerable Members IEnumerator IEnumerable.GetEnumerator() { - return new ItemEnumerator(_source, _getitem, _site); + return new ItemEnumerator(_context, _source, _getitem, _site); } #endregion diff --git a/Src/IronPython/Runtime/Operations/InstanceOps.cs b/Src/IronPython/Runtime/Operations/InstanceOps.cs index 52c018892..2b6c6578f 100644 --- a/Src/IronPython/Runtime/Operations/InstanceOps.cs +++ b/Src/IronPython/Runtime/Operations/InstanceOps.cs @@ -212,7 +212,7 @@ public static object NextMethod(object self) { /// __dir__(self) -> Returns the list of members defined on a foreign IDynamicMetaObjectProvider. /// public static PythonList DynamicDir(CodeContext/*!*/ context, IDynamicMetaObjectProvider self) { - PythonList res = new PythonList(self.GetMetaObject(Expression.Parameter(typeof(object))).GetDynamicMemberNames()); + PythonList res = new PythonList(context, self.GetMetaObject(Expression.Parameter(typeof(object))).GetDynamicMemberNames()); // add in the non-dynamic members from the dynamic objects base class. Type t = self.GetType(); diff --git a/Src/IronPython/Runtime/Operations/PythonOps.cs b/Src/IronPython/Runtime/Operations/PythonOps.cs index db4c7c1ef..382221eaf 100644 --- a/Src/IronPython/Runtime/Operations/PythonOps.cs +++ b/Src/IronPython/Runtime/Operations/PythonOps.cs @@ -1063,7 +1063,7 @@ internal static IList GetStringMemberList(IPythonMembersList pyMemList) } if (o is IMembersList memList) { - return new PythonList(memList.GetMemberNames()); + return new PythonList(context, memList.GetMemberNames()); } if (o is IPythonObject po) { @@ -1761,7 +1761,7 @@ public static void DictUpdate(CodeContext context, PythonDictionary dict, object /// LIST_EXTEND /// [EditorBrowsable(EditorBrowsableState.Never)] - public static void ListExtend(PythonList list, object? o) => list.extend(o); + public static void ListExtend(PythonList list, object? o) => list.extend(DefaultContext.Default, o); /// /// LIST_TO_TUPLE @@ -2637,8 +2637,8 @@ public static void VerifyUnduplicatedByName(PythonFunction function, string name } - public static PythonList CopyAndVerifyParamsList(PythonFunction function, object list) { - return new PythonList(list); + public static PythonList CopyAndVerifyParamsList(CodeContext context, PythonFunction function, object list) { + return new PythonList(context, list); } public static PythonTuple UserMappingToPythonTuple(CodeContext/*!*/ context, object list, string funcName) { @@ -3241,24 +3241,24 @@ public static DynamicMetaObjectBinder MakeSimpleCallAction(int count) { return ((PythonGenerator)self).CheckThrowableAndReturnSendValue(); } - public static ItemEnumerable CreateItemEnumerable(object source, object callable, CallSite> site) { - return new ItemEnumerable(source, callable, site); + public static ItemEnumerable CreateItemEnumerable(CodeContext context, object source, object callable, CallSite> site) { + return new ItemEnumerable(context, source, callable, site); } public static DictionaryKeyEnumerator MakeDictionaryKeyEnumerator(PythonDictionary dict) { return new DictionaryKeyEnumerator(dict._storage); } - public static IEnumerable CreatePythonEnumerable(object baseObject) { - return PythonEnumerable.Create(baseObject); + public static IEnumerable CreatePythonEnumerable(CodeContext context, object baseObject) { + return PythonEnumerable.Create(context, baseObject); } - public static IEnumerator CreateItemEnumerator(object source, object callable, CallSite> site) { - return new ItemEnumerator(source, callable, site); + public static IEnumerator CreateItemEnumerator(CodeContext context, object source, object callable, CallSite> site) { + return new ItemEnumerator(context, source, callable, site); } - public static IEnumerator CreatePythonEnumerator(object baseObject) { - return PythonEnumerator.Create(baseObject); + public static IEnumerator CreatePythonEnumerator(CodeContext context, object baseObject) { + return PythonEnumerator.Create(context, baseObject); } public static bool ContainsFromEnumerable(CodeContext/*!*/ context, object enumerable, object value) { diff --git a/Src/IronPython/Runtime/PythonContext.cs b/Src/IronPython/Runtime/PythonContext.cs index 6aaf220b6..1580aeed1 100644 --- a/Src/IronPython/Runtime/PythonContext.cs +++ b/Src/IronPython/Runtime/PythonContext.cs @@ -1260,7 +1260,7 @@ private void UnhookAssemblyResolve() { public override ICollection GetSearchPaths() { List result = new List(); if (TryGetSystemPath(out PythonList paths)) { - IEnumerator ie = PythonOps.GetEnumerator(paths); + IEnumerator ie = PythonOps.GetEnumerator(SharedContext, paths); while (ie.MoveNext()) { if (TryConvertToString(ie.Current, out string str)) { result.Add(str); @@ -1271,7 +1271,7 @@ public override ICollection GetSearchPaths() { } public override void SetSearchPaths(ICollection paths) { - SetSystemStateValue("path", new PythonList(paths)); + SetSystemStateValue("path", new PythonList(SharedContext, paths)); } public override void Shutdown() { diff --git a/Src/IronPython/Runtime/PythonList.cs b/Src/IronPython/Runtime/PythonList.cs index 0b1527803..94c525199 100644 --- a/Src/IronPython/Runtime/PythonList.cs +++ b/Src/IronPython/Runtime/PythonList.cs @@ -33,6 +33,8 @@ public class PythonList : IList, ICodeFormattable, IList, IReversible, internal int _size; internal volatile object?[] _data; + #region Python Constructors and Initializers + public void __init__() { _data = new object[8]; _size = 0; @@ -106,7 +108,7 @@ public void __init__(CodeContext context, object? sequence) { _data = new object[len]; _size = 0; - ExtendNoLengthCheck(sequence); + ExtendNoLengthCheck(context, sequence); } public static object __new__(CodeContext/*!*/ context, [NotNone] PythonType cls) { @@ -126,9 +128,30 @@ public static object __new__(CodeContext/*!*/ context, [NotNone] PythonType cls, public static object __new__(CodeContext/*!*/ context, [NotNone] PythonType cls, [ParamDictionary, NotNone] IDictionary kwArgs\u00F8, [NotNone] params object[] args\u00F8) => __new__(context, cls); - private PythonList(IEnumerator e) - : this(10) { - while (e.MoveNext()) AddNoLock(e.Current); + #endregion + + #region C# Constructors and Factories + + public PythonList() + : this(0) { + } + + public PythonList(CodeContext context, [NotNone] object sequence) { + if (sequence is ICollection items) { + _data = new object[items.Count]; + int i = 0; + foreach (object? item in items) { + _data[i++] = item; + } + _size = i; + } else { + if (!PythonOps.TryInvokeLengthHint(context, sequence, out int len)) { + len = INITIAL_SIZE; + } + + _data = new object[len]; + ExtendNoLengthCheck(context, sequence); + } } internal PythonList(int capacity) { @@ -139,13 +162,24 @@ internal PythonList(int capacity) { } } - private PythonList(params object?[] items) { + internal PythonList(ICollection items) + : this(items.Count) { + + int i = 0; + foreach (object? item in items) { + _data[i++] = item; + } + _size = i; + } + + private PythonList(object?[] items) { _data = items; _size = _data.Length; } - public PythonList() - : this(0) { + private PythonList(IEnumerator e) + : this(10) { + while (e.MoveNext()) AddNoLock(e.Current); } #if ALLOC_DEBUG @@ -160,32 +194,24 @@ public PythonList() } #endif - internal PythonList(object sequence) { - if (sequence is ICollection items) { - _data = new object[items.Count]; - int i = 0; - foreach (object? item in items) { - _data[i++] = item; - } - _size = i; - } else { - if (!PythonOps.TryInvokeLengthHint(DefaultContext.Default, sequence, out int len)) { - len = INITIAL_SIZE; - } + internal static PythonList FromGenericCollection(ICollection items) { + var list = new PythonList(items.Count); - _data = new object[len]; - ExtendNoLengthCheck(sequence); + int i = 0; + foreach (object? item in items) { + list._data[i++] = item; } + list._size = i; + return list; } - internal PythonList(ICollection items) - : this(items.Count) { - - int i = 0; - foreach (object? item in items) { - _data[i++] = item; + internal static PythonList FromEnumerable(IEnumerable items) { + var enumerator = items.GetEnumerator(); + try { + return new PythonList(enumerator); + } finally { + (enumerator as IDisposable)?.Dispose(); } - _size = i; } /// @@ -197,6 +223,8 @@ internal PythonList(ICollection items) internal static PythonList FromArrayNoCopy(params object[] data) => new PythonList(data); + #endregion + internal object?[] GetObjectArray() { lock (this) { return ArrayOps.CopyArray(_data, _size); @@ -445,7 +473,7 @@ public virtual object? this[[NotNone] Slice slice] { set { if (slice.step != null && (!(slice.step is int) || !slice.step.Equals(_boxedOne))) { // try to assign back to self: make a copy first - if (this == value) value = new PythonList(value); + if (this == value) value = new PythonList((ICollection)value); if (ValueRequiresNoLocks(value)) { // we don't need to worry about lock ordering of accesses to the @@ -743,16 +771,24 @@ public void extend([NotNone] PythonTuple/*!*/ seq) { } } - public void extend(object? seq) { - if (PythonOps.TryInvokeLengthHint(DefaultContext.Default, seq, out int len)) { + public void extend(CodeContext context, object? seq) { + if (PythonOps.TryInvokeLengthHint(context, seq, out int len)) { EnsureSize(len); } - ExtendNoLengthCheck(seq); + ExtendNoLengthCheck(context, seq); + } + + internal void ExtendNoLock(ICollection seq) { + EnsureSize(Count + seq.Count); + + foreach (var item in seq) { + AddNoLock(item); + } } - private void ExtendNoLengthCheck(object? seq) { - IEnumerator i = PythonOps.GetEnumerator(seq); + private void ExtendNoLengthCheck(CodeContext context, object? seq) { + IEnumerator i = PythonOps.GetEnumerator(context, seq); if (seq == (object)this) { PythonList other = new PythonList(i); i = ((IEnumerable)other).GetEnumerator(); diff --git a/Src/IronPython/Runtime/Set.cs b/Src/IronPython/Runtime/Set.cs index 487c7ec18..4fee48acd 100644 --- a/Src/IronPython/Runtime/Set.cs +++ b/Src/IronPython/Runtime/Set.cs @@ -1477,7 +1477,7 @@ public PythonTuple __reduce__(CodeContext/*!*/ context) { context.TryLookupBuiltin("iter", out iter); if (_cnt < 0) return PythonTuple.MakeTuple(iter, PythonTuple.MakeTuple(new PythonList())); - return PythonTuple.MakeTuple(iter, PythonTuple.MakeTuple(new PythonList(_items)), _cnt); + return PythonTuple.MakeTuple(iter, PythonTuple.MakeTuple(new PythonList(context, _items)), _cnt); } public int __length_hint__() { diff --git a/Src/IronPython/Runtime/Types/PythonType.cs b/Src/IronPython/Runtime/Types/PythonType.cs index 53688c208..6e774c591 100644 --- a/Src/IronPython/Runtime/Types/PythonType.cs +++ b/Src/IronPython/Runtime/Types/PythonType.cs @@ -1747,7 +1747,7 @@ private PythonList TryGetCustomDir(CodeContext context, object self) { ? context.LanguageContext.GetSiteCacheForSystemType(UnderlyingSystemType).GetDirSite(context) : _siteCache.GetDirSite(context); - return new PythonList(dirSite.Target(dirSite, context, dir)); + return new PythonList(context, dirSite.Target(dirSite, context, dir)); } } @@ -1790,7 +1790,7 @@ private static PythonList AddInstanceMembers(object self, Dictionary strKeys = new List(keys.Keys); strKeys.Sort(); - res.extend(strKeys); + res.ExtendNoLock(strKeys); return res; }