PageRenderTime 74ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/Languages/IronPython/IronPython/Runtime/PythonContext.cs

http://github.com/IronLanguages/main
C# | 4294 lines | 3348 code | 714 blank | 232 comment | 643 complexity | 6d50450b5a5d9ba0929681877a40b566 MD5 | raw file
Possible License(s): CPL-1.0, BSD-3-Clause, ISC, GPL-2.0, MPL-2.0-no-copyleft-exception
  1. /* ****************************************************************************
  2. *
  3. * Copyright (c) Microsoft Corporation.
  4. *
  5. * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
  6. * copy of the license can be found in the License.html file at the root of this distribution. If
  7. * you cannot locate the Apache License, Version 2.0, please send an email to
  8. * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
  9. * by the terms of the Apache License, Version 2.0.
  10. *
  11. * You must not remove this notice, or any other, from this software.
  12. *
  13. *
  14. * ***************************************************************************/
  15. #if FEATURE_CORE_DLR
  16. using System.Linq.Expressions;
  17. #else
  18. using dynamic = System.Object;
  19. using Microsoft.Scripting.Ast;
  20. #endif
  21. using System;
  22. using System.Collections;
  23. using System.Collections.Generic;
  24. using System.Diagnostics;
  25. using System.Dynamic;
  26. using System.Globalization;
  27. using System.IO;
  28. using System.Linq;
  29. using System.Reflection;
  30. using System.Runtime.CompilerServices;
  31. using System.Security;
  32. using System.Text;
  33. using System.Threading;
  34. using Microsoft.Scripting;
  35. using Microsoft.Scripting.Actions;
  36. using Microsoft.Scripting.Debugging.CompilerServices;
  37. using Microsoft.Scripting.Generation;
  38. using Microsoft.Scripting.Runtime;
  39. using Microsoft.Scripting.Utils;
  40. using IronPython.Compiler;
  41. using IronPython.Hosting;
  42. using IronPython.Modules;
  43. using IronPython.Runtime.Binding;
  44. using IronPython.Runtime.Exceptions;
  45. using IronPython.Runtime.Operations;
  46. using IronPython.Runtime.Types;
  47. using Debugging = Microsoft.Scripting.Debugging;
  48. using PyAst = IronPython.Compiler.Ast;
  49. #if NETCOREAPP1_0
  50. using Environment = System.FakeEnvironment;
  51. #endif
  52. namespace IronPython.Runtime
  53. {
  54. public delegate int HashDelegate(object o, ref HashDelegate dlg);
  55. public sealed partial class PythonContext : LanguageContext {
  56. internal const string/*!*/ IronPythonDisplayName = CurrentVersion.DisplayName;
  57. internal const string/*!*/ IronPythonNames = "IronPython;Python;py";
  58. internal const string/*!*/ IronPythonFileExtensions = ".py";
  59. private static readonly Guid PythonLanguageGuid = new Guid("03ed4b80-d10b-442f-ad9a-47dae85b2051");
  60. private static readonly Guid LanguageVendor_Microsoft = new Guid(-1723120188, -6423, 0x11d2, 0x90, 0x3f, 0, 0xc0, 0x4f, 0xa3, 2, 0xa1);
  61. // fields used during startup
  62. private readonly IDictionary<object, object>/*!*/ _modulesDict = new PythonDictionary();
  63. private readonly Dictionary<string, ModuleGlobalCache>/*!*/ _builtinCache = new Dictionary<string, ModuleGlobalCache>(StringComparer.Ordinal);
  64. private readonly Dictionary<Type, string>/*!*/ _builtinModuleNames = new Dictionary<Type, string>();
  65. private readonly PythonOptions/*!*/ _options;
  66. private readonly PythonModule/*!*/ _systemState;
  67. private readonly Dictionary<string, Type>/*!*/ _builtinModulesDict;
  68. private readonly PythonOverloadResolverFactory _sharedOverloadResolverFactory;
  69. private readonly PythonBinder _binder;
  70. private readonly SysModuleDictionaryStorage _sysDict = new SysModuleDictionaryStorage();
  71. #if FEATURE_FILESYSTEM
  72. #if FEATURE_ASSEMBLY_RESOLVE
  73. private readonly AssemblyResolveHolder _resolveHolder;
  74. #endif
  75. #if !CLR2
  76. private readonly HashSet<Assembly> _loadedAssemblies = new HashSet<Assembly>();
  77. #endif
  78. #endif
  79. private Encoding _defaultEncoding = PythonAsciiEncoding.Instance;
  80. // conditional variables for silverlight/desktop CLR features
  81. private Hosting.PythonService _pythonService;
  82. private string _initialExecutable, _initialPrefix = GetInitialPrefix();
  83. // other fields which might only be conditionally used
  84. private string _initialVersionString;
  85. private PythonModule _clrModule;
  86. private PythonDictionary _builtinDict;
  87. private PythonModule _builtins;
  88. private PythonFileManager _fileManager;
  89. private Dictionary<string, object> _errorHandlers;
  90. private List<object> _searchFunctions;
  91. private Dictionary<object, object> _moduleState;
  92. /// <summary> stored for copy_reg module, used for reduce protocol </summary>
  93. internal BuiltinFunction NewObject;
  94. /// <summary> stored for copy_reg module, used for reduce protocol </summary>
  95. internal BuiltinFunction PythonReconstructor;
  96. private Dictionary<Type, object> _genericSiteStorage;
  97. private CallSite<Func<CallSite, CodeContext, object, object>>[] _newUnarySites;
  98. private CallSite<Func<CallSite, CodeContext, object, object, object, object>>[] _newTernarySites;
  99. private CallSite<Func<CallSite, object, object, int>> _compareSite;
  100. private Dictionary<AttrKey, CallSite<Func<CallSite, object, object, object>>> _setAttrSites;
  101. private Dictionary<AttrKey, CallSite<Action<CallSite, object>>> _deleteAttrSites;
  102. private CallSite<Func<CallSite, CodeContext, object, string, PythonTuple, PythonDictionary, object>> _metaClassSite;
  103. private CallSite<Func<CallSite, CodeContext, object, string, object>> _writeSite;
  104. private CallSite<Func<CallSite, object, object, object>> _getIndexSite, _equalSite;
  105. private CallSite<Action<CallSite, object, object>> _delIndexSite;
  106. private CallSite<Func<CallSite, CodeContext, object, object>> _finalizerSite;
  107. private CallSite<Func<CallSite, CodeContext, PythonFunction, object>> _functionCallSite;
  108. private CallSite<Func<CallSite, object, object, bool>> _greaterThanSite, _lessThanSite, _greaterThanEqualSite, _lessThanEqualSite, _containsSite;
  109. private CallSite<Func<CallSite, CodeContext, object, object[], object>> _callSplatSite;
  110. private CallSite<Func<CallSite, CodeContext, object, object[], IDictionary<object, object>, object>> _callDictSite;
  111. private CallSite<Func<CallSite, CodeContext, object, object, object, object>> _callDictSiteLooselyTyped;
  112. private CallSite<Func<CallSite, CodeContext, object, string, PythonDictionary, PythonDictionary, PythonTuple, int, object>> _importSite;
  113. private CallSite<Func<CallSite, CodeContext, object, string, PythonDictionary, PythonDictionary, PythonTuple, object>> _oldImportSite;
  114. private CallSite<Func<CallSite, object, bool>> _isCallableSite;
  115. private CallSite<Func<CallSite, object, IList<string>>> _getSignaturesSite;
  116. private CallSite<Func<CallSite, object, object, object>> _addSite, _divModSite, _rdivModSite;
  117. private CallSite<Func<CallSite, object, object, object, object>> _setIndexSite, _delSliceSite;
  118. private CallSite<Func<CallSite, object, object, object, object, object>> _setSliceSite;
  119. private CallSite<Func<CallSite, object, string>> _docSite;
  120. // conversion sites
  121. private CallSite<Func<CallSite, object, int>> _intSite;
  122. private CallSite<Func<CallSite, object, string>> _tryStringSite;
  123. private CallSite<Func<CallSite, object, object>> _tryIntSite;
  124. private CallSite<Func<CallSite, object, IEnumerable>> _tryIEnumerableSite;
  125. private Dictionary<Type, CallSite<Func<CallSite, object, object>>> _implicitConvertSites;
  126. private Dictionary<PythonOperationKind, CallSite<Func<CallSite, object, object, object>>> _binarySites;
  127. private Dictionary<Type, DefaultPythonComparer> _defaultComparer;
  128. private CallSite<Func<CallSite, CodeContext, object, object, object, int>> _sharedFunctionCompareSite;
  129. private CallSite<Func<CallSite, CodeContext, PythonFunction, object, object, int>> _sharedPythonFunctionCompareSite;
  130. private CallSite<Func<CallSite, CodeContext, BuiltinFunction, object, object, int>> _sharedBuiltinFunctionCompareSite;
  131. private CallSite<Func<CallSite, CodeContext, object, int, object>> _getItemCallSite;
  132. private CallSite<Func<CallSite, CodeContext, object, object, object>> _propGetSite, _propDelSite;
  133. private CallSite<Func<CallSite, CodeContext, object, object, object, object>> _propSetSite;
  134. private CompiledLoader _compiledLoader;
  135. internal bool _importWarningThrows;
  136. private bool _importedEncodings;
  137. private Action<Action> _commandDispatcher; // can be null
  138. private ClrModule.ReferencesList _referencesList;
  139. private FloatFormat _floatFormat, _doubleFormat;
  140. private CultureInfo _collateCulture, _ctypeCulture, _timeCulture, _monetaryCulture, _numericCulture;
  141. private CodeContext _defaultContext, _defaultClsContext;
  142. private readonly TopNamespaceTracker _topNamespace;
  143. private readonly IEqualityComparer<object> _equalityComparer;
  144. private readonly IEqualityComparer _equalityComparerNonGeneric;
  145. private Dictionary<Type, CallSite<Func<CallSite, object, object, bool>>> _equalSites;
  146. private Dictionary<Type, PythonSiteCache> _systemSiteCache;
  147. internal static object _syntaxErrorNoCaret = new object();
  148. // atomized binders
  149. private PythonInvokeBinder _invokeNoArgs, _invokeOneArg;
  150. private Dictionary<CallSignature, PythonInvokeBinder/*!*/> _invokeBinders;
  151. private Dictionary<string/*!*/, PythonGetMemberBinder/*!*/> _getMemberBinders;
  152. private Dictionary<string/*!*/, PythonGetMemberBinder/*!*/> _tryGetMemberBinders;
  153. private Dictionary<string/*!*/, PythonSetMemberBinder/*!*/> _setMemberBinders;
  154. private Dictionary<string/*!*/, PythonDeleteMemberBinder/*!*/> _deleteMemberBinders;
  155. private Dictionary<string/*!*/, CompatibilityGetMember/*!*/> _compatGetMember;
  156. private Dictionary<string/*!*/, CompatibilityGetMember/*!*/> _compatGetMemberNoThrow;
  157. private Dictionary<PythonOperationKind, PythonOperationBinder/*!*/> _operationBinders;
  158. private Dictionary<ExpressionType, PythonUnaryOperationBinder/*!*/> _unaryBinders;
  159. private PythonBinaryOperationBinder[] _binaryBinders;
  160. private Dictionary<OperationRetTypeKey<ExpressionType>, BinaryRetTypeBinder/*!*/> _binaryRetTypeBinders;
  161. private Dictionary<OperationRetTypeKey<PythonOperationKind>, BinaryRetTypeBinder/*!*/> _operationRetTypeBinders;
  162. private Dictionary<Type/*!*/, PythonConversionBinder/*!*/>[] _conversionBinders;
  163. private Dictionary<Type/*!*/, DynamicMetaObjectBinder/*!*/>[] _convertRetObjectBinders;
  164. private Dictionary<CallSignature, CreateFallback/*!*/> _createBinders;
  165. private Dictionary<CallSignature, CompatibilityInvokeBinder/*!*/> _compatInvokeBinders;
  166. private PythonGetSliceBinder _getSlice;
  167. private PythonSetSliceBinder _setSlice;
  168. private PythonDeleteSliceBinder _deleteSlice;
  169. private PythonGetIndexBinder[] _getIndexBinders;
  170. private PythonSetIndexBinder[] _setIndexBinders;
  171. private PythonDeleteIndexBinder[] _deleteIndexBinders;
  172. private DynamicMetaObjectBinder _invokeTwoConvertToInt;
  173. private static CultureInfo _CCulture;
  174. private DynamicDelegateCreator _delegateCreator;
  175. // tracing / in-proc debugging support
  176. private DebugContext _debugContext;
  177. private Debugging.TracePipeline _tracePipeline;
  178. private readonly Microsoft.Scripting.Utils.ThreadLocal<PythonTracebackListener> _tracebackListeners = new Microsoft.Scripting.Utils.ThreadLocal<PythonTracebackListener>();
  179. private int _tracebackListenersCount;
  180. internal FunctionCode.CodeList _allCodes;
  181. internal readonly object _codeCleanupLock = new object(), _codeUpdateLock = new object();
  182. internal int _codeCount, _nextCodeCleanup = 200;
  183. private int _recursionLimit;
  184. internal readonly List<FunctionStack> _mainThreadFunctionStack;
  185. private CallSite<Func<CallSite, CodeContext, object, object>> _callSite0LightEh;
  186. private List<WeakReference> _weakExtensionMethodSets;
  187. // store the Python types mapping to each .NET type
  188. private CommonDictionaryStorage _systemPythonTypesWeakRefs = new CommonDictionaryStorage();
  189. #region Generated Python Shared Call Sites Storage
  190. // *** BEGIN GENERATED CODE ***
  191. // generated by function: gen_shared_call_sites_storage from: generate_calls.py
  192. private CallSite<Func<CallSite, CodeContext, object, object>> _callSite0;
  193. private CallSite<Func<CallSite, CodeContext, object, object, object>> _callSite1;
  194. private CallSite<Func<CallSite, CodeContext, object, object, object, object>> _callSite2;
  195. private CallSite<Func<CallSite, CodeContext, object, object, object, object, object>> _callSite3;
  196. private CallSite<Func<CallSite, CodeContext, object, object, object, object, object, object>> _callSite4;
  197. private CallSite<Func<CallSite, CodeContext, object, object, object, object, object, object, object>> _callSite5;
  198. private CallSite<Func<CallSite, CodeContext, object, object, object, object, object, object, object, object>> _callSite6;
  199. // *** END GENERATED CODE ***
  200. #endregion
  201. /// <summary>
  202. /// Creates a new PythonContext not bound to Engine.
  203. /// </summary>
  204. public PythonContext(ScriptDomainManager/*!*/ manager, IDictionary<string, object> options)
  205. : base(manager) {
  206. _options = new PythonOptions(options);
  207. _builtinModulesDict = CreateBuiltinTable();
  208. PythonDictionary defaultScope = new PythonDictionary();
  209. ModuleContext modContext = new ModuleContext(defaultScope, this);
  210. _defaultContext = modContext.GlobalContext;
  211. PythonDictionary sysDict = new PythonDictionary(_sysDict);
  212. _systemState = new PythonModule(sysDict);
  213. _systemState.__dict__["__name__"] = "sys";
  214. _systemState.__dict__["__package__"] = null;
  215. PythonBinder binder = new PythonBinder(this, _defaultContext);
  216. _sharedOverloadResolverFactory = new PythonOverloadResolverFactory(binder, Expression.Constant(_defaultContext));
  217. _binder = binder;
  218. CodeContext defaultClsContext = DefaultContext.CreateDefaultCLSContext(this);
  219. _defaultClsContext = defaultClsContext;
  220. if (DefaultContext._default == null) {
  221. DefaultContext.InitializeDefaults(_defaultContext, defaultClsContext);
  222. }
  223. InitializeBuiltins();
  224. InitializeSystemState();
  225. #if SILVERLIGHT
  226. AddToPath("");
  227. #endif
  228. // sys.argv always includes at least one empty string.
  229. SetSystemStateValue("argv", (_options.Arguments.Count == 0) ?
  230. new List(new object[] { String.Empty }) :
  231. new List(_options.Arguments)
  232. );
  233. if (_options.WarningFilters.Count > 0) {
  234. _systemState.__dict__["warnoptions"] = new List(_options.WarningFilters);
  235. }
  236. if (_options.Frames) {
  237. var getFrame = BuiltinFunction.MakeFunction(
  238. "_getframe",
  239. ArrayUtils.ConvertAll(typeof(SysModule).GetMember("_getframeImpl"), (x) => (MethodBase)x),
  240. typeof(SysModule)
  241. );
  242. _systemState.__dict__["_getframe"] = getFrame;
  243. }
  244. if (_options.Tracing) {
  245. EnsureDebugContext();
  246. }
  247. List path = new List(_options.SearchPaths);
  248. #if FEATURE_ASSEMBLY_RESOLVE && FEATURE_FILESYSTEM
  249. _resolveHolder = new AssemblyResolveHolder(this);
  250. try {
  251. Assembly entryAssembly = Assembly.GetEntryAssembly();
  252. // Can be null if called from unmanaged code (VS integration scenario)
  253. if (entryAssembly != null) {
  254. string entry = Path.GetDirectoryName(entryAssembly.Location);
  255. string lib = Path.Combine(entry, "Lib");
  256. path.append(lib);
  257. // add DLLs directory for user-defined extention modules
  258. path.append(Path.Combine(entry, "DLLs"));
  259. #if DEBUG
  260. // For developer use, add External.LCA_RESTRICTED/Languages/IronPython/27/Lib
  261. string devStdLib = Path.GetFullPath(Path.Combine(entry, @"../../External.LCA_RESTRICTED/Languages/IronPython/27/Lib"));
  262. if (Directory.Exists(devStdLib))
  263. path.append(devStdLib);
  264. #endif
  265. }
  266. } catch (SecurityException) {
  267. }
  268. #endif
  269. _systemState.__dict__["path"] = path;
  270. RecursionLimit = _options.RecursionLimit;
  271. #if FEATURE_ASSEMBLY_RESOLVE && FEATURE_FILESYSTEM
  272. object asmResolve;
  273. if (options == null ||
  274. !options.TryGetValue("NoAssemblyResolveHook", out asmResolve) ||
  275. !System.Convert.ToBoolean(asmResolve)) {
  276. try {
  277. HookAssemblyResolve();
  278. } catch (System.Security.SecurityException) {
  279. // We may not have SecurityPermissionFlag.ControlAppDomain.
  280. // If so, we will not look up sys.path for module loads
  281. }
  282. }
  283. #endif
  284. _equalityComparer = new PythonEqualityComparer(this);
  285. _equalityComparerNonGeneric = (IEqualityComparer)_equalityComparer;
  286. InitialHasher = InitialHasherImpl;
  287. IntHasher = IntHasherImpl;
  288. DoubleHasher = DoubleHasherImpl;
  289. StringHasher = StringHasherImpl;
  290. FallbackHasher = FallbackHasherImpl;
  291. _topNamespace = new TopNamespaceTracker(manager);
  292. foreach (Assembly asm in manager.GetLoadedAssemblyList()) {
  293. _topNamespace.LoadAssembly(asm);
  294. }
  295. manager.AssemblyLoaded += new EventHandler<AssemblyLoadedEventArgs>(ManagerAssemblyLoaded);
  296. _mainThreadFunctionStack = PythonOps.GetFunctionStack();
  297. }
  298. void ManagerAssemblyLoaded(object sender, AssemblyLoadedEventArgs e) {
  299. _topNamespace.LoadAssembly(e.Assembly);
  300. }
  301. /// <summary>
  302. /// Gets or sets the maximum depth of function calls. Equivalent to sys.getrecursionlimit
  303. /// and sys.setrecursionlimit.
  304. /// </summary>
  305. public int RecursionLimit {
  306. get {
  307. return _recursionLimit;
  308. }
  309. set {
  310. if (value < 0) {
  311. throw PythonOps.ValueError("recursion limit must be positive");
  312. }
  313. lock (_codeUpdateLock) {
  314. _recursionLimit = value;
  315. if ((_recursionLimit == Int32.MaxValue) != (value == Int32.MaxValue)) {
  316. // recursion setting has changed, we need to update all of our
  317. // function codes to enforce or un-enforce recursion.
  318. FunctionCode.UpdateAllCode(this);
  319. }
  320. }
  321. }
  322. }
  323. internal bool EnableTracing {
  324. get {
  325. return PythonOptions.Tracing || _tracebackListenersCount > 0;
  326. }
  327. }
  328. internal TopNamespaceTracker TopNamespace {
  329. get {
  330. return _topNamespace;
  331. }
  332. }
  333. #if FEATURE_THREAD
  334. /// <summary>
  335. /// Gets or sets the main thread which should be interupted by thread.interrupt_main
  336. /// </summary>
  337. public Thread MainThread {
  338. get {
  339. return _mainThread;
  340. }
  341. set {
  342. _mainThread = value;
  343. }
  344. }
  345. private Thread _mainThread;
  346. #endif
  347. public IEqualityComparer<object>/*!*/ EqualityComparer {
  348. get { return _equalityComparer; }
  349. }
  350. public IEqualityComparer/*!*/ EqualityComparerNonGeneric {
  351. get { return _equalityComparerNonGeneric; }
  352. }
  353. internal sealed class PythonEqualityComparer : IEqualityComparer, IEqualityComparer<object> {
  354. public readonly PythonContext/*!*/ Context;
  355. public PythonEqualityComparer(PythonContext/*!*/ context) {
  356. Assert.NotNull(context);
  357. Context = context;
  358. }
  359. bool IEqualityComparer.Equals(object x, object y) {
  360. return PythonOps.EqualRetBool(Context._defaultContext, x, y);
  361. }
  362. bool IEqualityComparer<object>.Equals(object x, object y) {
  363. return PythonOps.EqualRetBool(Context._defaultContext, x, y);
  364. }
  365. int IEqualityComparer.GetHashCode(object obj) {
  366. return PythonContext.Hash(obj);
  367. }
  368. int IEqualityComparer<object>.GetHashCode(object obj) {
  369. return PythonContext.Hash(obj);
  370. }
  371. }
  372. #region Specialized Hashers
  373. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
  374. internal readonly HashDelegate InitialHasher;
  375. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
  376. internal readonly HashDelegate IntHasher;
  377. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
  378. internal readonly HashDelegate DoubleHasher;
  379. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
  380. internal readonly HashDelegate StringHasher;
  381. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
  382. internal readonly HashDelegate FallbackHasher;
  383. private int InitialHasherImpl(object o, ref HashDelegate dlg) {
  384. if (o == null) {
  385. return NoneTypeOps.NoneHashCode;
  386. }
  387. switch (o.GetType().GetTypeCode()) {
  388. case TypeCode.String:
  389. dlg = StringHasher;
  390. return StringHasher(o, ref dlg);
  391. case TypeCode.Int32:
  392. dlg = IntHasher;
  393. return IntHasher(o, ref dlg);
  394. case TypeCode.Double:
  395. dlg = DoubleHasher;
  396. return DoubleHasher(o, ref dlg);
  397. default:
  398. if (o is IPythonObject) {
  399. dlg = new OptimizedUserHasher(this, ((IPythonObject)o).PythonType).Hasher;
  400. } else {
  401. dlg = new OptimizedBuiltinHasher(this, o.GetType()).Hasher;
  402. }
  403. return dlg(o, ref dlg);
  404. }
  405. }
  406. private int IntHasherImpl(object o, ref HashDelegate dlg) {
  407. if (o != null && o.GetType() == typeof(int)) {
  408. return o.GetHashCode();
  409. }
  410. dlg = FallbackHasher;
  411. return FallbackHasher(o, ref dlg);
  412. }
  413. private int DoubleHasherImpl(object o, ref HashDelegate dlg) {
  414. if (o != null && o.GetType() == typeof(double)) {
  415. return DoubleOps.__hash__((double)o);
  416. }
  417. dlg = FallbackHasher;
  418. return FallbackHasher(o, ref dlg);
  419. }
  420. private int StringHasherImpl(object o, ref HashDelegate dlg) {
  421. if (o != null && o.GetType() == typeof(string)) {
  422. return o.GetHashCode();
  423. }
  424. dlg = FallbackHasher;
  425. return FallbackHasher(o, ref dlg);
  426. }
  427. private int FallbackHasherImpl(object o, ref HashDelegate dlg) {
  428. return PythonOps.Hash(this.SharedContext, o);
  429. }
  430. private sealed class OptimizedUserHasher {
  431. private readonly PythonContext _context;
  432. private readonly PythonType _pt;
  433. public OptimizedUserHasher(PythonContext context, PythonType pt) {
  434. _context = context;
  435. _pt = pt;
  436. }
  437. public int Hasher(object o, ref HashDelegate dlg) {
  438. IPythonObject ipo = o as IPythonObject;
  439. if (ipo != null && ipo.PythonType == _pt) {
  440. return _pt.Hash(o);
  441. }
  442. dlg = _context.FallbackHasher;
  443. return _context.FallbackHasher(o, ref dlg);
  444. }
  445. }
  446. private sealed class OptimizedBuiltinHasher {
  447. private readonly PythonContext _context;
  448. private readonly Type _type;
  449. private readonly PythonType _pt;
  450. public OptimizedBuiltinHasher(PythonContext context, Type type) {
  451. _context = context;
  452. _type = type;
  453. _pt = DynamicHelpers.GetPythonTypeFromType(type);
  454. }
  455. public int Hasher(object o, ref HashDelegate dlg) {
  456. if (o != null && o.GetType() == _type) {
  457. return _pt.Hash(o);
  458. }
  459. dlg = _context.FallbackHasher;
  460. return _context.FallbackHasher(o, ref dlg);
  461. }
  462. }
  463. #endregion
  464. public override LanguageOptions/*!*/ Options {
  465. get { return PythonOptions; }
  466. }
  467. /// <summary>
  468. /// Checks to see if module state has the current value stored already.
  469. /// </summary>
  470. public bool HasModuleState(object key) {
  471. EnsureModuleState();
  472. lock (_moduleState) {
  473. return _moduleState.ContainsKey(key);
  474. }
  475. }
  476. private void EnsureModuleState() {
  477. if (_moduleState == null) {
  478. Interlocked.CompareExchange(ref _moduleState, new Dictionary<object, object>(), null);
  479. }
  480. }
  481. /// <summary>
  482. /// Gets per-runtime state used by a module. The module should have a unique key for
  483. /// each piece of state it needs to store.
  484. /// </summary>
  485. public object GetModuleState(object key) {
  486. EnsureModuleState();
  487. lock (_moduleState) {
  488. Debug.Assert(_moduleState.ContainsKey(key));
  489. return _moduleState[key];
  490. }
  491. }
  492. /// <summary>
  493. /// Sets per-runtime state used by a module. The module should have a unique key for
  494. /// each piece of state it needs to store.
  495. /// </summary>
  496. public void SetModuleState(object key, object value) {
  497. EnsureModuleState();
  498. lock (_moduleState) {
  499. _moduleState[key] = value;
  500. }
  501. }
  502. /// <summary>
  503. /// Sets per-runtime state used by a module and returns the previous value. The module
  504. /// should have a unique key for each piece of state it needs to store.
  505. /// </summary>
  506. public object GetSetModuleState(object key, object value) {
  507. EnsureModuleState();
  508. lock (_moduleState) {
  509. object result;
  510. _moduleState.TryGetValue(key, out result);
  511. _moduleState[key] = value;
  512. return result;
  513. }
  514. }
  515. /// <summary>
  516. /// Sets per-runtime state used by a module and returns the previous value. The module
  517. /// should have a unique key for each piece of state it needs to store.
  518. /// </summary>
  519. public T GetOrCreateModuleState<T>(object key, Func<T> value) where T : class {
  520. EnsureModuleState();
  521. lock (_moduleState) {
  522. object result;
  523. if (!_moduleState.TryGetValue(key, out result)) {
  524. _moduleState[key] = result = value();
  525. }
  526. return (result as T);
  527. }
  528. }
  529. public PythonType EnsureModuleException(object key, PythonDictionary dict, string name, string module) {
  530. return (PythonType)(dict[name] = GetOrCreateModuleState(
  531. key,
  532. () => PythonExceptions.CreateSubType(this, PythonExceptions.Exception, name, module, null, PythonType.DefaultMakeException)
  533. ));
  534. }
  535. public PythonType EnsureModuleException(object key, PythonType baseType, PythonDictionary dict, string name, string module) {
  536. return (PythonType)(dict[name] = GetOrCreateModuleState(
  537. key,
  538. () => PythonExceptions.CreateSubType(this, baseType, name, module, null, PythonType.DefaultMakeException)
  539. ));
  540. }
  541. public PythonType EnsureModuleException(object key, PythonType baseType, Type underlyingType, PythonDictionary dict, string name, string module, Func<string, Exception> exceptionMaker) {
  542. return (PythonType)(dict[name] = GetOrCreateModuleState(
  543. key,
  544. () => PythonExceptions.CreateSubType(this, baseType, underlyingType, name, module, null, exceptionMaker)
  545. ));
  546. }
  547. public PythonType EnsureModuleException(object key, PythonType[] baseTypes, Type underlyingType, PythonDictionary dict, string name, string module) {
  548. return (PythonType)(dict[name] = GetOrCreateModuleState(
  549. key,
  550. () => PythonExceptions.CreateSubType(this, baseTypes, underlyingType, name, module, null, PythonType.DefaultMakeException)
  551. ));
  552. }
  553. internal PythonOptions/*!*/ PythonOptions {
  554. get {
  555. return _options;
  556. }
  557. }
  558. public override Guid VendorGuid {
  559. get {
  560. return LanguageVendor_Microsoft;
  561. }
  562. }
  563. public override Guid LanguageGuid {
  564. get {
  565. return PythonLanguageGuid;
  566. }
  567. }
  568. public PythonModule/*!*/ SystemState {
  569. get {
  570. return _systemState;
  571. }
  572. }
  573. public PythonModule/*!*/ ClrModule {
  574. get {
  575. if (_clrModule == null) {
  576. Interlocked.CompareExchange(ref _clrModule, CreateBuiltinModule("clr"), null);
  577. }
  578. return _clrModule;
  579. }
  580. }
  581. internal bool TryGetSystemPath(out List path) {
  582. object val;
  583. if (SystemState.__dict__.TryGetValue("path", out val)) {
  584. path = val as List;
  585. } else {
  586. path = null;
  587. }
  588. return path != null;
  589. }
  590. internal object SystemStandardOut {
  591. get {
  592. return GetSystemStateValue("stdout");
  593. }
  594. }
  595. internal object SystemStandardIn {
  596. get {
  597. return GetSystemStateValue("stdin");
  598. }
  599. }
  600. internal object SystemStandardError {
  601. get {
  602. return GetSystemStateValue("stderr");
  603. }
  604. }
  605. internal IDictionary<object, object> SystemStateModules {
  606. get {
  607. return _modulesDict;
  608. }
  609. }
  610. internal void UpdateExceptionInfo(object type, object value, object traceback) {
  611. _sysDict.UpdateExceptionInfo(type, value, traceback);
  612. }
  613. internal void UpdateExceptionInfo(Exception clrException, object type, object value, List<DynamicStackFrame> traceback) {
  614. _sysDict.UpdateExceptionInfo(clrException, type, value, traceback);
  615. }
  616. internal void ExceptionHandled() {
  617. _sysDict.ExceptionHandled();
  618. }
  619. internal PythonModule GetModuleByName(string/*!*/ name) {
  620. Assert.NotNull(name);
  621. object scopeObj;
  622. PythonModule module;
  623. if (SystemStateModules.TryGetValue(name, out scopeObj) && (module = scopeObj as PythonModule) != null) {
  624. return module;
  625. }
  626. return null;
  627. }
  628. internal PythonModule GetModuleByPath(string/*!*/ path) {
  629. Assert.NotNull(path);
  630. foreach (object moduleObj in SystemStateModules.Values) {
  631. PythonModule module = moduleObj as PythonModule;
  632. if (module != null) {
  633. if (DomainManager.Platform.PathComparer.Compare(module.GetFile(), path) == 0) {
  634. return module;
  635. }
  636. }
  637. }
  638. return null;
  639. }
  640. public override Version LanguageVersion {
  641. get {
  642. // Assembly.GetName() can't be called in Silverlight...
  643. return GetPythonVersion();
  644. }
  645. }
  646. internal static Version GetPythonVersion() {
  647. return new AssemblyName(typeof(PythonContext).GetTypeInfo().Assembly.FullName).Version;
  648. }
  649. internal FloatFormat FloatFormat {
  650. get {
  651. return _floatFormat;
  652. }
  653. set {
  654. _floatFormat = value;
  655. }
  656. }
  657. internal FloatFormat DoubleFormat {
  658. get {
  659. return _doubleFormat;
  660. }
  661. set {
  662. _doubleFormat = value;
  663. }
  664. }
  665. /// <summary>
  666. /// Initializes the sys module on startup. Called both to load and reload sys
  667. /// </summary>
  668. private void InitializeSystemState() {
  669. // These fields do not get reset on "reload(sys)", we populate them once on startup
  670. SetSystemStateValue("argv", List.FromArrayNoCopy(new object[] { String.Empty }));
  671. SetSystemStateValue("modules", _modulesDict);
  672. InitializeSysFlags();
  673. _modulesDict["sys"] = _systemState;
  674. SetSystemStateValue("path", new List(3));
  675. SetStandardIO();
  676. SysModule.PerformModuleReload(this, _systemState.__dict__);
  677. }
  678. internal bool EmitDebugSymbols(SourceUnit sourceUnit) {
  679. return sourceUnit.EmitDebugSymbols && (PythonOptions.NoDebug == null || !PythonOptions.NoDebug.IsMatch(sourceUnit.Path));
  680. }
  681. private void InitializeSysFlags() {
  682. // sys.flags
  683. SysModule.SysFlags flags = new SysModule.SysFlags();
  684. SetSystemStateValue("flags", flags);
  685. flags.debug = _options.Debug ? 1 : 0;
  686. flags.py3k_warning = _options.WarnPython30 ? 1 : 0;
  687. SetSystemStateValue("py3kwarning", _options.WarnPython30);
  688. switch (_options.DivisionOptions) {
  689. case PythonDivisionOptions.Old:
  690. break;
  691. case PythonDivisionOptions.New:
  692. flags.division_new = 1;
  693. break;
  694. case PythonDivisionOptions.Warn:
  695. flags.division_warning = 1;
  696. break;
  697. case PythonDivisionOptions.WarnAll:
  698. flags.division_warning = 2;
  699. break;
  700. }
  701. flags.inspect = flags.interactive = _options.Inspect ? 1 : 0;
  702. if (_options.StripDocStrings) {
  703. flags.optimize = 2;
  704. } else if (_options.Optimize) {
  705. flags.optimize = 1;
  706. }
  707. flags.dont_write_bytecode = 1;
  708. SetSystemStateValue("dont_write_bytecode", true);
  709. flags.no_user_site = _options.NoUserSite ? 1 : 0;
  710. flags.no_site = _options.NoSite ? 1 : 0;
  711. flags.ignore_environment = _options.IgnoreEnvironment ? 1 : 0;
  712. switch (_options.IndentationInconsistencySeverity) {
  713. case Severity.Warning:
  714. flags.tabcheck = 1;
  715. break;
  716. case Severity.Error:
  717. flags.tabcheck = 2;
  718. break;
  719. }
  720. flags.verbose = _options.Verbose ? 1 : 0;
  721. flags.unicode = 1;
  722. flags.bytes_warning = _options.BytesWarning ? 1 : 0;
  723. }
  724. internal bool ShouldInterpret(PythonCompilerOptions options, SourceUnit source) {
  725. // We have to turn off adaptive compilation in debug mode to
  726. // support mangaged debuggers. Also turn off in optimized mode.
  727. bool adaptiveCompilation = !_options.NoAdaptiveCompilation && !EmitDebugSymbols(source);
  728. return options.Interpreted || adaptiveCompilation;
  729. }
  730. private static PyAst.PythonAst ParseAndBindAst(CompilerContext context) {
  731. ScriptCodeParseResult properties = ScriptCodeParseResult.Complete;
  732. bool propertiesSet = false;
  733. int errorCode = 0;
  734. PyAst.PythonAst ast;
  735. using (Parser parser = Parser.CreateParser(context, PythonContext.GetPythonOptions(null))) {
  736. switch (context.SourceUnit.Kind) {
  737. case SourceCodeKind.InteractiveCode:
  738. ast = parser.ParseInteractiveCode(out properties);
  739. propertiesSet = true;
  740. break;
  741. case SourceCodeKind.Expression:
  742. ast = parser.ParseTopExpression();
  743. break;
  744. case SourceCodeKind.SingleStatement:
  745. ast = parser.ParseSingleStatement();
  746. break;
  747. case SourceCodeKind.File:
  748. ast = parser.ParseFile(true, false);
  749. break;
  750. case SourceCodeKind.Statements:
  751. ast = parser.ParseFile(false, false);
  752. break;
  753. default:
  754. case SourceCodeKind.AutoDetect:
  755. ast = parser.ParseFile(true, true);
  756. break;
  757. }
  758. errorCode = parser.ErrorCode;
  759. }
  760. if (!propertiesSet && errorCode != 0) {
  761. properties = ScriptCodeParseResult.Invalid;
  762. }
  763. context.SourceUnit.CodeProperties = properties;
  764. if (errorCode != 0 || properties == ScriptCodeParseResult.Empty) {
  765. return null;
  766. }
  767. ast.Bind();
  768. return ast;
  769. }
  770. internal static ScriptCode CompilePythonCode(SourceUnit/*!*/ sourceUnit, CompilerOptions/*!*/ options, ErrorSink/*!*/ errorSink) {
  771. var pythonOptions = (PythonCompilerOptions)options;
  772. if (sourceUnit.Kind == SourceCodeKind.File) {
  773. pythonOptions.Module |= ModuleOptions.Initialize;
  774. }
  775. CompilerContext context = new CompilerContext(sourceUnit, options, errorSink);
  776. PyAst.PythonAst ast = ParseAndBindAst(context);
  777. if (ast == null) {
  778. return null;
  779. }
  780. return ast.ToScriptCode();
  781. }
  782. public override ScriptCode CompileSourceCode(SourceUnit/*!*/ sourceUnit, CompilerOptions/*!*/ options, ErrorSink/*!*/ errorSink) {
  783. ScriptCode res = CompilePythonCode(sourceUnit, options, errorSink);
  784. if (res != null) {
  785. Scope scope = res.CreateScope();
  786. // if this is an optimized module we need to initialize the optimized scope.
  787. // Optimized scopes come w/ extensions already attached so we use that to know
  788. // if we're optimized or not.
  789. PythonScopeExtension scopeExtension = (PythonScopeExtension)scope.GetExtension(ContextId);
  790. if (scopeExtension != null) {
  791. InitializeModule(sourceUnit.Path, scopeExtension.ModuleContext, res, ModuleOptions.None);
  792. }
  793. }
  794. return res;
  795. }
  796. public override ScriptCode/*!*/ LoadCompiledCode(Delegate/*!*/ method, string path, string customData) {
  797. SourceUnit su = new SourceUnit(this, NullTextContentProvider.Null, path, SourceCodeKind.File);
  798. return new OnDiskScriptCode((LookupCompilationDelegate)method, su, customData);
  799. }
  800. public override SourceCodeReader/*!*/ GetSourceReader(Stream/*!*/ stream, Encoding/*!*/ defaultEncoding, string path) {
  801. ContractUtils.RequiresNotNull(stream, "stream");
  802. ContractUtils.RequiresNotNull(defaultEncoding, "defaultEncoding");
  803. ContractUtils.Requires(stream.CanSeek && stream.CanRead, "stream", "The stream must support seeking and reading");
  804. // we choose ASCII by default, if the file has a Unicode header though
  805. // we'll automatically get it as unicode.
  806. Encoding encoding = PythonAsciiEncoding.SourceEncoding;
  807. long startPosition = stream.Position;
  808. StreamReader sr = new StreamReader(stream, PythonAsciiEncoding.SourceEncoding);
  809. byte[] bomBuffer = new byte[3];
  810. int bomRead = stream.Read(bomBuffer, 0, 3);
  811. int bytesRead = 0;
  812. bool isUtf8 = false;
  813. if (bomRead == 3 && (bomBuffer[0] == 0xef && bomBuffer[1] == 0xbb && bomBuffer[2] == 0xbf)) {
  814. isUtf8 = true;
  815. bytesRead = 3;
  816. } else {
  817. stream.Seek(0, SeekOrigin.Begin);
  818. }
  819. string line;
  820. try {
  821. line = ReadOneLine(sr, ref bytesRead);
  822. } catch (BadSourceException) {
  823. throw ReportEncodingError(stream, path);
  824. }
  825. bool gotEncoding = false;
  826. string encodingName = null;
  827. // magic encoding must be on line 1 or 2
  828. if (line != null && !(gotEncoding = Tokenizer.TryGetEncoding(defaultEncoding, line, ref encoding, out encodingName))) {
  829. try {
  830. line = ReadOneLine(sr, ref bytesRead);
  831. } catch (BadSourceException) {
  832. throw ReportEncodingError(stream, path);
  833. }
  834. if (line != null) {
  835. gotEncoding = Tokenizer.TryGetEncoding(defaultEncoding, line, ref encoding, out encodingName);
  836. }
  837. }
  838. if (gotEncoding && isUtf8 && encodingName != "utf-8") {
  839. // we have both a BOM & an encoding type, throw an error
  840. throw new IOException("file has both Unicode marker and PEP-263 file encoding. You can only use \"utf-8\" as the encoding name when a BOM is present.");
  841. } else if (encoding == null) {
  842. throw new IOException("unknown encoding type");
  843. }
  844. // if we didn't get an encoding seek back to the beginning...
  845. if (!gotEncoding || stream.Position != stream.Length) {
  846. stream.Seek(startPosition, SeekOrigin.Begin);
  847. }
  848. // re-read w/ the correct encoding type...
  849. return new SourceCodeReader(new StreamReader(stream, encoding), encoding);
  850. }
  851. internal static Exception ReportEncodingError(Stream stream, string path) {
  852. stream.Seek(0, SeekOrigin.Begin);
  853. byte[] buffer = new byte[1024];
  854. int bytesRead = 0;
  855. int curLine = 1, curOffset = 1, index = 0;
  856. while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) != -1) {
  857. for (int i = 0; i < bytesRead; i++) {
  858. if (buffer[i] > 0x7f) {
  859. return PythonOps.BadSourceError(
  860. buffer[i],
  861. new SourceSpan(
  862. new SourceLocation(index, curLine, curOffset),
  863. new SourceLocation(index, curLine, curOffset)
  864. ),
  865. path
  866. );
  867. } else if (buffer[i] == '\n') {
  868. curLine++;
  869. curOffset = 1;
  870. } else {
  871. curOffset++;
  872. }
  873. index++;
  874. }
  875. }
  876. return new InvalidOperationException();
  877. }
  878. /// <summary>
  879. /// Reads one line keeping track of the # of bytes read
  880. /// </summary>
  881. private static string ReadOneLine(StreamReader reader, ref int totalRead) {
  882. Stream sr = reader.BaseStream;
  883. byte[] buffer = new byte[256];
  884. StringBuilder builder = null;
  885. int bytesRead = sr.Read(buffer, 0, buffer.Length);
  886. while (bytesRead > 0) {
  887. totalRead += bytesRead;
  888. bool foundEnd = false;
  889. for (int i = 0; i < bytesRead; i++) {
  890. if (buffer[i] == '\r') {
  891. if (i + 1 < bytesRead) {
  892. if (buffer[i + 1] == '\n') {
  893. totalRead -= (bytesRead - (i + 2)); // skip cr/lf
  894. sr.Seek(i + 2, SeekOrigin.Begin);
  895. reader.DiscardBufferedData();
  896. foundEnd = true;
  897. }
  898. } else {
  899. totalRead -= (bytesRead - (i + 1)); // skip cr
  900. sr.Seek(i + 1, SeekOrigin.Begin);
  901. reader.DiscardBufferedData();
  902. foundEnd = true;
  903. }
  904. } else if (buffer[i] == '\n') {
  905. totalRead -= (bytesRead - (i + 1)); // skip lf
  906. sr.Seek(i + 1, SeekOrigin.Begin);
  907. reader.DiscardBufferedData();
  908. foundEnd = true;
  909. }
  910. if (foundEnd) {
  911. if (builder != null) {
  912. builder.Append(buffer.MakeString(), 0, i);
  913. return builder.ToString();
  914. }
  915. return buffer.MakeString().Substring(0, i);
  916. }
  917. }
  918. if (builder == null) builder = new StringBuilder();
  919. builder.Append(buffer.MakeString(), 0, bytesRead);
  920. bytesRead = sr.Read(buffer, 0, buffer.Length);
  921. }
  922. // no string
  923. if (builder == null) {
  924. return null;
  925. }
  926. // no new-line
  927. return builder.ToString();
  928. }
  929. #if FEATURE_CODEDOM
  930. // Convert a CodeDom to source code, and output the generated code and the line number mappings (if any)
  931. public override SourceUnit/*!*/ GenerateSourceCode(System.CodeDom.CodeObject codeDom, string path, SourceCodeKind kind) {
  932. return new IronPython.Hosting.PythonCodeDomCodeGen().GenerateCode((System.CodeDom.CodeMemberMethod)codeDom, this, path, kind);
  933. }
  934. #endif
  935. #region Scopes
  936. public override Scope GetScope(string/*!*/ path) {
  937. PythonModule module = GetModuleByPath(path);
  938. return (module != null) ? module.Scope : null;
  939. }
  940. public PythonModule/*!*/ InitializeModule(string fileName, ModuleContext moduleContext, ScriptCode scriptCode, ModuleOptions options) {
  941. if ((options & ModuleOptions.NoBuiltins) == 0) {
  942. moduleContext.InitializeBuiltins((options & ModuleOptions.ModuleBuiltins) != 0);
  943. }
  944. // If the filename is __init__.py then this is the initialization code
  945. // for a package and we need to set the __path__ variable appropriately
  946. if (fileName != null && Path.GetFileName(fileName) == "__init__.py") {
  947. string dirname = Path.GetDirectoryName(fileName);
  948. string dir_path = DomainManager.Platform.GetFullPath(dirname);
  949. moduleContext.Globals["__path__"] = PythonOps.MakeList(dir_path);
  950. }
  951. moduleContext.ShowCls = (options & ModuleOptions.ShowClsMethods) != 0;
  952. moduleContext.Features = options;
  953. if ((options & ModuleOptions.Initialize) != 0) {
  954. scriptCode.Run(moduleContext.GlobalScope);
  955. if (!moduleContext.Globals.ContainsKey("__package__")) {
  956. moduleContext.Globals["__package__"] = null;
  957. }
  958. }
  959. return moduleContext.Module;
  960. }
  961. public override ScopeExtension CreateScopeExtension(Scope scope) {
  962. var ret = new PythonScopeExtension(this, scope);
  963. ret.ModuleContext.InitializeBuiltins(false);
  964. return ret;
  965. }
  966. public PythonModule/*!*/ CompileModule(string fileName, string moduleName, SourceUnit sourceCode, ModuleOptions options) {
  967. ScriptCode compiledCode;
  968. return CompileModule(fileName, moduleName, sourceCode, options, out compiledCode);
  969. }
  970. public PythonModule/*!*/ CompileModule(string fileName, string moduleName, SourceUnit sourceCode, ModuleOptions options, out ScriptCode scriptCode) {
  971. ContractUtils.RequiresNotNull(fileName, "fileName");
  972. ContractUtils.RequiresNotNull(moduleName, "moduleName");
  973. ContractUtils.RequiresNotNull(sourceCode, "sourceCode");
  974. scriptCode = GetScriptCode(sourceCode, moduleName, options);
  975. Scope scope = scriptCode.CreateScope();
  976. return InitializeModule(fileName, ((PythonScopeExtension)scope.GetExtension(ContextId)).ModuleContext, scriptCode, options);
  977. }
  978. internal ScriptCode GetScriptCode(SourceUnit sourceCode, string moduleName, ModuleOptions options) {
  979. return GetScriptCode(sourceCode, moduleName, options, null);
  980. }
  981. internal ScriptCode GetScriptCode(SourceUnit sourceCode, string moduleName, ModuleOptions options, Compiler.CompilationMode mode) {
  982. PythonCompilerOptions compilerOptions = GetPythonCompilerOptions();
  983. compilerOptions.SkipFirstLine = (options & ModuleOptions.SkipFirstLine) != 0;
  984. compilerOptions.ModuleName = moduleName;
  985. compilerOptions.Module = options;
  986. compilerOptions.CompilationMode = mode;
  987. return CompilePythonCode(sourceCode, compilerOptions, ThrowingErrorSink.Default);
  988. }
  989. internal PythonModule GetBuiltinModule(string name) {
  990. lock (this) {
  991. PythonModule mod = CreateBuiltinModule(name);
  992. if (mod != null) {
  993. PublishModule(name, mod);
  994. return mod;
  995. }
  996. return null;
  997. }
  998. }
  999. internal PythonModule CreateBuiltinModule(string name) {
  1000. Type type;
  1001. if (BuiltinModules.TryGetValue(name, out type)) {
  1002. // RuntimeHelpers.RunClassConstructor
  1003. // run the type's .cctor before doing any custom reflection on the type.
  1004. // This allows modules to lazily initialize PythonType's to custom values
  1005. // rather than having them get populated w/ the ReflectedType. W/o this the
  1006. // cctor runs after we've done a bunch of reflection over the type that doesn't
  1007. // force the cctor to run.
  1008. RuntimeHelpers.RunClassConstructor(type.TypeHandle);
  1009. return CreateBuiltinModule(name, type);
  1010. }
  1011. return null;
  1012. }
  1013. internal PythonModule/*!*/ CreateBuiltinModule(string moduleName, Type type) {
  1014. PythonDictionary dict;
  1015. if (type.IsSubclassOf(typeof(BuiltinPythonModule))) {
  1016. // an optimized Python module.
  1017. var builtinModule = (BuiltinPythonModule)Activator.CreateInstance(type, this);
  1018. var globals = new Dictionary<string, PythonGlobal>();
  1019. var globalStorage = new InstancedModuleDictionaryStorage(builtinModule, globals);
  1020. dict = new PythonDictionary(globalStorage);
  1021. var names = builtinModule.GetGlobalVariableNames();
  1022. var codeContext = new ModuleContext(dict, this).GlobalContext;
  1023. foreach (var name in names) {
  1024. globals[name] = new PythonGlobal(codeContext, name);
  1025. }
  1026. builtinModule.Initialize(codeContext, globals);
  1027. } else {
  1028. dict = new PythonDictionary(new ModuleDictionaryStorage(type));
  1029. if (type == typeof(Builtin)) {
  1030. Builtin.PerformModuleReload(this, dict);
  1031. } else if (type != typeof(SysModule)) { // will be performed by hand later, see InitializeSystemState
  1032. MethodInfo reload = type.GetMethod("PerformModuleReload");
  1033. if (reload != null) {
  1034. Debug.Assert(reload.IsStatic);
  1035. reload.Invoke(null, new object[] { this, dict });
  1036. }
  1037. }
  1038. }
  1039. PythonModule mod = new PythonModule(dict);
  1040. mod.__dict__["__name__"] = moduleName;
  1041. mod.__dict__["__package__"] = null;
  1042. return mod;
  1043. }
  1044. public void PublishModule(string/*!*/ name, PythonModule/*!*/ module) {
  1045. ContractUtils.RequiresNotNull(name, "name");
  1046. ContractUtils.RequiresNotNull(module, "module");
  1047. SystemStateModules[name] = module;
  1048. }
  1049. internal PythonModule GetReloadableModule(PythonModule/*!*/ module) {
  1050. Assert.NotNull(module);
  1051. object name;
  1052. if (!module.__dict__._storage.TryGetName(out name) || !(name is string)) {
  1053. throw PythonOps.SystemError("nameless module");
  1054. }
  1055. if (!SystemStateModules.ContainsKey(name)) {
  1056. throw PythonOps.ImportError("module {0} not in sys.modules", name);
  1057. }
  1058. return module;
  1059. }
  1060. #endregion
  1061. public object GetWarningsModule() {
  1062. object warnings = null;
  1063. try {
  1064. if (!_importWarningThrows) {
  1065. warnings = Importer.ImportModule(SharedContext, new PythonDictionary(), "warnings", false, -1);
  1066. }
  1067. } catch {
  1068. // don't repeatedly import after it fails
  1069. _importWarningThrows = true;
  1070. }
  1071. return warnings;
  1072. }
  1073. public void EnsureEncodings() {
  1074. if (!_importedEncodings) {
  1075. try {
  1076. Importer.ImportModule(SharedContext, new PythonDictionary(), "encodings", false, -1);
  1077. } catch (ImportException) {
  1078. }
  1079. _importedEncodings = true;
  1080. }
  1081. }
  1082. internal ModuleGlobalCache GetModuleGlobalCache(string name) {
  1083. ModuleGlobalCache res;
  1084. if (!TryGetModuleGlobalCache(name, out res)) {
  1085. res = ModuleGlobalCache.NoCache;
  1086. }
  1087. return res;
  1088. }
  1089. #region Assembly Loading
  1090. #if FEATURE_FILESYSTEM
  1091. internal Assembly LoadAssemblyFromFile(string file) {
  1092. // check all files in the path...
  1093. List path;
  1094. if (TryGetSystemPath(out path)) {
  1095. IEnumerator ie = PythonOps.GetEnumerator(path);
  1096. while (ie.MoveNext()) {
  1097. string str;
  1098. if (TryConvertToString(ie.Current, out str)) {
  1099. string fullName = Path.Combine(str, file);
  1100. Assembly res;
  1101. if (TryLoadAssemblyFromFileWithPath(fullName, out res)) return res;
  1102. if (TryLoadAssemblyFromFileWithPath(fullName + ".exe", out res)) return res;
  1103. if (TryLoadAssemblyFromFileWithPath(fullName + ".dll", out res)) return res;
  1104. }
  1105. }
  1106. }
  1107. return null;
  1108. }
  1109. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", MessageId = "System.Reflection.Assembly.LoadFile")]
  1110. internal bool TryLoadAssemblyFromFileWithPath(string path, out Assembly res) {
  1111. if (File.Exists(path) && Path.IsPathRooted(path)) {
  1112. #if NETSTANDARD
  1113. res = System.Runtime.Loader.AssemblyLoadContext.Default.LoadFromAssemblyPath(path);
  1114. #else
  1115. res = Assembly.LoadFile(path);
  1116. #endif
  1117. if (res != null) {
  1118. #if !CLR2
  1119. _loadedAssemblies.Add(res);
  1120. #endif
  1121. return true;
  1122. }
  1123. }
  1124. res = null;
  1125. return false;
  1126. }
  1127. #if FEATURE_ASSEMBLY_RESOLVE
  1128. internal Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) {
  1129. #if !CLR2 && !ANDROID
  1130. if (args.RequestingAssembly != null && !_loadedAssemblies.Contains(args.RequestingAssembly)) {
  1131. return null;
  1132. }
  1133. #endif
  1134. AssemblyName an = new AssemblyName(args.Name);
  1135. try {
  1136. return LoadAssemblyFromFile(an.Name);
  1137. } catch {
  1138. return null;
  1139. }
  1140. }
  1141. /// <summary>
  1142. /// We use Assembly.LoadFile to load assemblies from a path specified by the script (in LoadAssemblyFromFileWithPath).
  1143. /// However, when the CLR loader tries to resolve any of assembly references, it will not be able to
  1144. /// find the dependencies, unless we can hook into the CLR loader.
  1145. /// </summary>
  1146. [MethodImpl(MethodImplOptions.NoInlining)] // avoid inlining due to LinkDemand from assembly resolve.
  1147. private void HookAssemblyResolve() {
  1148. AppDomain.CurrentDomain.AssemblyResolve += _resolveHolder.AssemblyResolveEvent;
  1149. }
  1150. class AssemblyResolveHolder {
  1151. private readonly WeakReference _context;
  1152. public AssemblyResolveHolder(PythonContext context) {
  1153. _context = new WeakReference(context);
  1154. }
  1155. internal Assembly AssemblyResolveEvent(object sender, ResolveEventArgs args) {
  1156. PythonContext context = (PythonContext)_context.Target;
  1157. if (context != null) {
  1158. return context.CurrentDomain_AssemblyResolve(sender, args);
  1159. } else {
  1160. AppDomain.CurrentDomain.AssemblyResolve -= AssemblyResolveEvent;
  1161. return null;
  1162. }
  1163. }
  1164. }
  1165. private void UnhookAssemblyResolve() {
  1166. try {
  1167. AppDomain.CurrentDomain.AssemblyResolve -= _resolveHolder.AssemblyResolveEvent;
  1168. } catch (System.Security.SecurityException) {
  1169. // We may not have SecurityPermissionFlag.ControlAppDomain.
  1170. // If so, we will not look up sys.path for module loads
  1171. }
  1172. }
  1173. #endif
  1174. #endif
  1175. #endregion
  1176. public override ICollection<string> GetSearchPaths() {
  1177. List<string> result = new List<string>();
  1178. List paths;
  1179. if (TryGetSystemPath(out paths)) {
  1180. IEnumerator ie = PythonOps.GetEnumerator(paths);
  1181. while (ie.MoveNext()) {
  1182. string str;
  1183. if (TryConvertToString(ie.Current, out str)) {
  1184. result.Add(str);
  1185. }
  1186. }
  1187. }
  1188. return result;
  1189. }
  1190. public override void SetSearchPaths(ICollection<string> paths) {
  1191. SetSystemStateValue("path", new List(paths));
  1192. }
  1193. public override void Shutdown() {
  1194. object callable;
  1195. #if FEATURE_ASSEMBLY_RESOLVE && FEATURE_FILESYSTEM
  1196. UnhookAssemblyResolve();
  1197. #endif
  1198. object threadingMod;
  1199. if (SystemStateModules.TryGetValue("threading", out threadingMod) &&
  1200. (threadingMod is PythonModule) &&
  1201. ((PythonModule)threadingMod).__dict__.TryGetValue("_shutdown", out callable)) {
  1202. try {
  1203. PythonCalls.Call(SharedContext, callable);
  1204. } catch (Exception e) {
  1205. PythonOps.PrintWithDest(
  1206. SharedContext,
  1207. SystemStandardError,
  1208. String.Format("Exception {0} ignored", FormatException(e))
  1209. );
  1210. }
  1211. }
  1212. try {
  1213. if (_systemState.__dict__.TryGetValue("exitfunc", out callable)) {
  1214. PythonCalls.Call(SharedContext, callable);
  1215. }
  1216. } finally {
  1217. #if FEATURE_BASIC_CONSOLE
  1218. if (PythonOptions.PerfStats) {
  1219. PerfTrack.DumpStats();
  1220. }
  1221. #endif
  1222. }
  1223. }
  1224. // TODO: ExceptionFormatter service
  1225. #region Stack Traces and Exceptions
  1226. public override string FormatException(Exception exception) {
  1227. ContractUtils.RequiresNotNull(exception, "exception");
  1228. SyntaxErrorException syntax_error = exception as SyntaxErrorException;
  1229. if (syntax_error != null) {
  1230. return FormatPythonSyntaxError(syntax_error);
  1231. }
  1232. object pythonEx = PythonExceptions.ToPython(exception);
  1233. string result = FormatStackTraces(exception) + FormatPythonException(pythonEx) + Environment.NewLine;
  1234. if (Options.ShowClrExceptions) {
  1235. result += FormatCLSException(exception);
  1236. }
  1237. return result;
  1238. }
  1239. internal static string FormatPythonSyntaxError(SyntaxErrorException e) {
  1240. string sourceLine = GetSourceLine(e);
  1241. if (e.GetData(_syntaxErrorNoCaret) == null) {
  1242. return String.Format(
  1243. " File \"{1}\", line {2}{0}" +
  1244. " {3}{0}" +
  1245. " {4}^{0}" +
  1246. "{5}: {6}{0}",
  1247. Environment.NewLine,
  1248. e.GetSymbolDocumentName(),
  1249. e.Line > 0 ? e.Line.ToString() : "?",
  1250. (sourceLine != null) ? sourceLine.Replace('\t', ' ') : null,
  1251. new String(' ', e.Column != 0 ? e.Column - 1 : 0),
  1252. GetPythonExceptionClassName(PythonExceptions.ToPython(e)), e.Message);
  1253. }
  1254. return String.Format(
  1255. " File \"{1}\", line {2}{0}" +
  1256. "{3}: {4}{0}",
  1257. Environment.NewLine,
  1258. e.GetSymbolDocumentName(),
  1259. new String(' ', e.Column != 0 ? e.Column - 1 : 0),
  1260. GetPythonExceptionClassName(PythonExceptions.ToPython(e)), e.Message);
  1261. }
  1262. internal static string GetSourceLine(SyntaxErrorException e) {
  1263. if (e.SourceCode == null) {
  1264. return null;
  1265. }
  1266. try {
  1267. using (StringReader reader = new StringReader(e.SourceCode)) {
  1268. char[] buffer = new char[80];
  1269. int curLine = 1;
  1270. StringBuilder line = new StringBuilder();
  1271. int bytesRead;
  1272. // we can't use SourceUnit.GetCodeLines because Python includes the new lines
  1273. // in the syntax error and the codeop standard library depends upon this
  1274. // being correct
  1275. while ((bytesRead = reader.Read(buffer, 0, buffer.Length)) > 0 && curLine <= e.Line) {
  1276. for (int i = 0; i < bytesRead; i++) {
  1277. if (curLine == e.Line) {
  1278. line.Append(buffer[i]);
  1279. }
  1280. if (buffer[i] == '\n') {
  1281. curLine++;
  1282. }
  1283. if (curLine > e.Line) {
  1284. break;
  1285. }
  1286. }
  1287. }
  1288. return line.ToString();
  1289. }
  1290. } catch (IOException) {
  1291. return null;
  1292. }
  1293. }
  1294. private static string FormatCLSException(Exception e) {
  1295. StringBuilder result = new StringBuilder();
  1296. result.AppendLine("CLR Exception: ");
  1297. while (e != null) {
  1298. result.Append(" ");
  1299. result.AppendLine(e.GetType().Name);
  1300. if (!String.IsNullOrEmpty(e.Message)) {
  1301. result.AppendLine(": ");
  1302. result.AppendLine(e.Message);
  1303. } else {
  1304. result.AppendLine();
  1305. }
  1306. e = e.InnerException;
  1307. }
  1308. return result.ToString();
  1309. }
  1310. internal static string FormatPythonException(object pythonException) {
  1311. string result = "";
  1312. // dump the python exception.
  1313. if (pythonException != null) {
  1314. string str = pythonException as string;
  1315. if (str != null) {
  1316. result += str;
  1317. } else {
  1318. result += GetPythonExceptionClassName(pythonException);
  1319. string excepStr = PythonOps.ToString(pythonException);
  1320. if (!String.IsNullOrEmpty(excepStr)) {
  1321. result += ": " + excepStr;
  1322. }
  1323. }
  1324. }
  1325. return result;
  1326. }
  1327. private static string GetPythonExceptionClassName(object pythonException) {
  1328. string className = "";
  1329. object val;
  1330. if (PythonOps.TryGetBoundAttr(pythonException, "__class__", out val)) {
  1331. if (PythonOps.TryGetBoundAttr(val, "__name__", out val)) {
  1332. className = val.ToString();
  1333. if (PythonOps.TryGetBoundAttr(pythonException, "__module__", out val)) {
  1334. string moduleName = val.ToString();
  1335. if (moduleName != PythonExceptions.DefaultExceptionModule) {
  1336. className = moduleName + "." + className;
  1337. }
  1338. }
  1339. }
  1340. }
  1341. return className;
  1342. }
  1343. public override IList<DynamicStackFrame> GetStackFrames(Exception exception) {
  1344. return PythonOps.GetDynamicStackFrames(exception);
  1345. }
  1346. #if !FEATURE_STACK_TRACE
  1347. private string FormatStackTraces(Exception e) {
  1348. StringBuilder result = new StringBuilder();
  1349. result.AppendLine("Traceback (most recent call last):");
  1350. DynamicStackFrame[] dfs = PythonExceptions.GetDynamicStackFrames(e);
  1351. for (int i = 0; i < dfs.Length; ++i) {
  1352. DynamicStackFrame frame = dfs[i];
  1353. result.AppendFormat(" at {0} in {1}, line {2}\n", frame.GetMethodName(), frame.GetFileName(), frame.GetFileLineNumber());
  1354. }
  1355. if (Options.ExceptionDetail) {
  1356. result.AppendLine(e.Message);
  1357. }
  1358. return result.ToString();
  1359. }
  1360. #else
  1361. private string FormatStackTraces(Exception e) {
  1362. bool printedHeader = false;
  1363. return FormatStackTraces(e, ref printedHeader);
  1364. }
  1365. private string FormatStackTraces(Exception e, ref bool printedHeader) {
  1366. string result = "";
  1367. if (Options.ExceptionDetail) {
  1368. if (!printedHeader) {
  1369. result = e.Message + Environment.NewLine;
  1370. printedHeader = true;
  1371. }
  1372. IList<System.Diagnostics.StackTrace> traces = ExceptionHelpers.GetExceptionStackTraces(e);
  1373. if (traces != null) {
  1374. foreach (StackTrace trace in traces) {
  1375. foreach (StackFrame curFrame in trace.GetFrames()) {
  1376. result += curFrame.ToString() + Environment.NewLine;
  1377. }
  1378. }
  1379. }
  1380. if (e.StackTrace != null) result += e.StackTrace.ToString() + Environment.NewLine;
  1381. if (e.InnerException != null) result += FormatStackTraces(e.InnerException, ref printedHeader);
  1382. } else {
  1383. result = FormatStackTraceNoDetail(e, ref printedHeader);
  1384. }
  1385. return result;
  1386. }
  1387. internal string FormatStackTraceNoDetail(Exception e, ref bool printedHeader) {
  1388. string result = String.Empty;
  1389. // dump inner most exception first, followed by outer most.
  1390. if (e.InnerException != null) result += FormatStackTraceNoDetail(e.InnerException, ref printedHeader);
  1391. if (!printedHeader) {
  1392. result += "Traceback (most recent call last):" + Environment.NewLine;
  1393. printedHeader = true;
  1394. }
  1395. var traceback = e.GetTraceBack();
  1396. if (traceback != null) {
  1397. return result + traceback.Extract();
  1398. }
  1399. var frames = PythonExceptions.GetDynamicStackFrames(e);
  1400. for (int i = frames.Length - 1; i >= 0; i--) {
  1401. var frame = frames[i];
  1402. MethodBase method = frame.GetMethod();
  1403. if (CallSiteHelpers.IsInternalFrame(method) ||
  1404. (method.DeclaringType != null && method.DeclaringType.FullName.StartsWith("IronPython."))) {
  1405. continue;
  1406. }
  1407. result += FrameToString(frame) + Environment.NewLine;
  1408. }
  1409. return result;
  1410. }
  1411. private static string FrameToString(DynamicStackFrame frame) {
  1412. string methodName = frame.GetMethodName();
  1413. int lineNumber = frame.GetFileLineNumber();
  1414. return String.Format(" File \"{0}\", line {1}, in {2}",
  1415. frame.GetFileName(),
  1416. lineNumber == 0 ? "unknown" : lineNumber.ToString(),
  1417. methodName);
  1418. }
  1419. #endif
  1420. #endregion
  1421. // TODO: Replace all usages with direct access
  1422. internal static PythonContext/*!*/ GetContext(CodeContext/*!*/ context) {
  1423. return context.LanguageContext;
  1424. }
  1425. public override TService GetService<TService>(params object[] args) {
  1426. if (typeof(TService) == typeof(TokenizerService)) {
  1427. return (TService)(object)new Tokenizer(ErrorSink.Null, GetPythonCompilerOptions(), true);
  1428. } else if (typeof(TService) == typeof(PythonService)) {
  1429. return (TService)(object)GetPythonService((Microsoft.Scripting.Hosting.ScriptEngine)args[0]);
  1430. } else if (typeof(TService) == typeof(DocumentationProvider)) {
  1431. return (TService)(object)new PythonDocumentationProvider(this);
  1432. }
  1433. return base.GetService<TService>(args);
  1434. }
  1435. /// <summary>
  1436. /// Returns (and creates if necessary) the PythonService that is associated with this PythonContext.
  1437. ///
  1438. /// The PythonService is used for providing remoted convenience helpers for the DLR hosting APIs.
  1439. /// </summary>
  1440. internal Hosting.PythonService GetPythonService(Microsoft.Scripting.Hosting.ScriptEngine engine) {
  1441. if (_pythonService == null) {
  1442. Interlocked.CompareExchange(ref _pythonService, new Hosting.PythonService(this, engine), null);
  1443. }
  1444. return _pythonService;
  1445. }
  1446. internal static PythonOptions GetPythonOptions(CodeContext context) {
  1447. return DefaultContext.DefaultPythonContext._options;
  1448. }
  1449. internal void InsertIntoPath(int index, string directory) {
  1450. List path;
  1451. if (TryGetSystemPath(out path)) {
  1452. path.insert(index, directory);
  1453. }
  1454. }
  1455. internal void AddToPath(string directory) {
  1456. List path;
  1457. if (TryGetSystemPath(out path)) {
  1458. path.append(directory);
  1459. }
  1460. }
  1461. internal void AddToPath(string directory, int index) {
  1462. List path;
  1463. if (TryGetSystemPath(out path)) {
  1464. path.insert(index, directory);
  1465. }
  1466. }
  1467. internal PythonCompilerOptions GetPythonCompilerOptions() {
  1468. ModuleOptions features = ModuleOptions.None;
  1469. if (PythonOptions.DivisionOptions == PythonDivisionOptions.New) {
  1470. features |= ModuleOptions.TrueDivision;
  1471. }
  1472. return new PythonCompilerOptions(features);
  1473. }
  1474. public override CompilerOptions GetCompilerOptions() {
  1475. return GetPythonCompilerOptions();
  1476. }
  1477. public override CompilerOptions/*!*/ GetCompilerOptions(Scope/*!*/ scope) {
  1478. Assert.NotNull(scope);
  1479. PythonCompilerOptions res = GetPythonCompilerOptions();
  1480. PythonScopeExtension module = (PythonScopeExtension)scope.GetExtension(ContextId);
  1481. if (module != null) {
  1482. res.Module |= module.ModuleContext.Features;
  1483. }
  1484. return res;
  1485. }
  1486. public override void GetExceptionMessage(Exception exception, out string message, out string typeName) {
  1487. object pythonEx = PythonExceptions.ToPython(exception);
  1488. message = FormatPythonException(PythonExceptions.ToPython(exception));
  1489. typeName = GetPythonExceptionClassName(pythonEx);
  1490. }
  1491. /// <summary>
  1492. /// Gets or sets the default encoding for this system state / engine.
  1493. /// </summary>
  1494. public Encoding DefaultEncoding {
  1495. get { return _defaultEncoding; }
  1496. set { _defaultEncoding = value; }
  1497. }
  1498. public string GetDefaultEncodingName() {
  1499. return DefaultEncoding.WebName.ToLower().Replace('-', '_');
  1500. }
  1501. /// <summary>
  1502. /// Dictionary from name to type of all known built-in module names.
  1503. /// </summary>
  1504. internal Dictionary<string, Type> BuiltinModules {
  1505. get {
  1506. return _builtinModulesDict;
  1507. }
  1508. }
  1509. /// <summary>
  1510. /// Dictionary from type to name of all built-in modules.
  1511. /// </summary>
  1512. internal Dictionary<Type, string> BuiltinModuleNames {
  1513. get {
  1514. return _builtinModuleNames;
  1515. }
  1516. }
  1517. private void InitializeBuiltins() {
  1518. // create the __builtin__ module
  1519. BuiltinsDictionaryStorage storage = new BuiltinsDictionaryStorage(BuiltinsChanged);
  1520. PythonDictionary dict = new PythonDictionary(storage);
  1521. Builtin.PerformModuleReload(this, dict);
  1522. _builtinDict = dict;
  1523. _builtins = new PythonModule(dict);
  1524. _modulesDict["__builtin__"] = _builtins;
  1525. }
  1526. private Dictionary<string, Type> CreateBuiltinTable() {
  1527. Dictionary<string, Type> builtinTable = new Dictionary<string, Type>();
  1528. // We should register builtins, if any, from IronPython.dll
  1529. LoadBuiltins(builtinTable, typeof(PythonContext).GetTypeInfo().Assembly, false);
  1530. // Load builtins from IronPython.Modules
  1531. Assembly ironPythonModules = null;
  1532. try {
  1533. ironPythonModules = DomainManager.Platform.LoadAssembly(GetIronPythonAssembly("IronPython.Modules"));
  1534. } catch (FileNotFoundException) {
  1535. // IronPython.Modules is not available, continue without it...
  1536. }
  1537. if (ironPythonModules != null) {
  1538. LoadBuiltins(builtinTable, ironPythonModules, false);
  1539. #if !WIN8
  1540. if (Environment.OSVersion.Platform == PlatformID.Unix) {
  1541. // we make our nt package show up as a posix package
  1542. // on unix platforms. Because we build on top of the
  1543. // CLI for all file operations we should be good from
  1544. // there, but modules that check for the presence of
  1545. // names (e.g. os) will do the right thing.
  1546. Debug.Assert(builtinTable.ContainsKey("nt"));
  1547. builtinTable["posix"] = builtinTable["nt"];
  1548. builtinTable.Remove("nt");
  1549. }
  1550. #endif
  1551. }
  1552. return builtinTable;
  1553. }
  1554. internal void LoadBuiltins(Dictionary<string, Type> builtinTable, Assembly assem, bool updateSys) {
  1555. #if NETSTANDARD
  1556. var attrs = assem.GetCustomAttributes(typeof(PythonModuleAttribute));
  1557. #else
  1558. var attrs = assem.GetCustomAttributes(typeof(PythonModuleAttribute), false);
  1559. #endif
  1560. if (attrs.Any()) {
  1561. foreach (PythonModuleAttribute pma in attrs) {
  1562. if (pma.InvalidPlatforms != null && Array.IndexOf(pma.InvalidPlatforms, Environment.OSVersion.Platform) < 0) {
  1563. builtinTable[pma.Name] = pma.Type;
  1564. BuiltinModuleNames[pma.Type] = pma.Name;
  1565. }
  1566. }
  1567. if (updateSys) {
  1568. SysModule.PublishBuiltinModuleNames(this, _systemState.__dict__);
  1569. }
  1570. }
  1571. }
  1572. public static string GetIronPythonAssembly(string/*!*/ baseName) {
  1573. ContractUtils.RequiresNotNull(baseName, "baseName");
  1574. string fullName = typeof(PythonContext).GetTypeInfo().Assembly.FullName;
  1575. int firstComma = fullName.IndexOf(',');
  1576. return firstComma > 0 ? baseName + fullName.Substring(firstComma) : baseName;
  1577. }
  1578. /// <summary>
  1579. /// TODO: Remove me, or stop caching built-ins. This is broken if the user changes __builtin__
  1580. /// </summary>
  1581. public PythonModule BuiltinModuleInstance {
  1582. get {
  1583. return _builtins;
  1584. }
  1585. }
  1586. public PythonDictionary BuiltinModuleDict {
  1587. get {
  1588. return _builtinDict;
  1589. }
  1590. }
  1591. private void BuiltinsChanged(object sender, ModuleChangeEventArgs e) {
  1592. ModuleGlobalCache mgc;
  1593. lock (_builtinCache) {
  1594. if (_builtinCache.TryGetValue(e.Name, out mgc)) {
  1595. switch (e.ChangeType) {
  1596. case ModuleChangeType.Delete: mgc.Value = Uninitialized.Instance; break;
  1597. case ModuleChangeType.Set: mgc.Value = e.Value; break;
  1598. }
  1599. } else {
  1600. // shouldn't be able to delete before it was set
  1601. object value = e.ChangeType == ModuleChangeType.Set ? e.Value : Uninitialized.Instance;
  1602. _builtinCache[e.Name] = new ModuleGlobalCache(value);
  1603. }
  1604. }
  1605. }
  1606. internal bool TryGetModuleGlobalCache(string name, out ModuleGlobalCache cache) {
  1607. lock (_builtinCache) {
  1608. if (!_builtinCache.TryGetValue(name, out cache)) {
  1609. // only cache values currently in built-ins, everything else will have
  1610. // no caching policy and will fall back to the LanguageContext.
  1611. object value;
  1612. if (BuiltinModuleInstance.__dict__.TryGetValue(name, out value)) {
  1613. _builtinCache[name] = cache = new ModuleGlobalCache(value);
  1614. }
  1615. }
  1616. }
  1617. return cache != null;
  1618. }
  1619. internal void SetHostVariables(string prefix, string executable, string versionString) {
  1620. _initialVersionString = !string.IsNullOrEmpty(versionString) ? versionString : GetVersionString();
  1621. _initialExecutable = executable ?? "";
  1622. _initialPrefix = prefix;
  1623. #if !SILVERLIGHT
  1624. AddToPath(Path.Combine(prefix, "Lib"), 0);
  1625. #endif
  1626. SetHostVariables(SystemState.__dict__);
  1627. }
  1628. internal string InitialPrefix {
  1629. get {
  1630. return _initialPrefix;
  1631. }
  1632. }
  1633. internal void SetHostVariables(PythonDictionary dict) {
  1634. dict["executable"] = _initialExecutable;
  1635. dict["prefix"] = _initialPrefix;
  1636. dict["exec_prefix"] = _initialPrefix;
  1637. SetVersionVariables(dict);
  1638. }
  1639. private void SetVersionVariables(PythonDictionary dict) {
  1640. var implementation = new Implementation();
  1641. dict["implementation"] = implementation;
  1642. dict["version_info"] = implementation.version;
  1643. dict["hexversion"] = implementation.hexversion;
  1644. dict["version"] = implementation.version.GetVersionString(
  1645. _initialVersionString ?? GetVersionString());
  1646. }
  1647. internal static string GetVersionString() {
  1648. string configuration = BuildInfo.IsDebug ? " DEBUG" : "";
  1649. string platform = Type.GetType("Mono.Runtime") == null ? ".NET" : "Mono";
  1650. string bitness = (IntPtr.Size * 8).ToString();
  1651. return String.Format("{0}{3} ({1}) on {4} {2} ({5}-bit)",
  1652. PythonContext.IronPythonDisplayName,
  1653. PythonContext.GetPythonVersion().ToString(),
  1654. Environment.Version,
  1655. configuration,
  1656. platform,
  1657. bitness
  1658. );
  1659. }
  1660. private static string GetInitialPrefix() {
  1661. #if FEATURE_ASSEMBLY_CODEBASE
  1662. try {
  1663. return typeof(PythonContext).GetTypeInfo().Assembly.CodeBase;
  1664. } catch (SecurityException) {
  1665. // we don't have permissions to get paths...
  1666. return String.Empty;
  1667. } catch (MethodAccessException) {
  1668. return String.Empty;
  1669. }
  1670. #else
  1671. return String.Empty;
  1672. #endif
  1673. }
  1674. /// <summary>
  1675. /// Gets the member names associated with the object
  1676. /// TODO: Move "GetMemberNames" functionality into MetaObject implementations
  1677. /// </summary>
  1678. public override IList<string> GetMemberNames(object obj) {
  1679. List<string> res = new List<string>();
  1680. foreach (object o in PythonOps.GetAttrNames(SharedContext, obj)) {
  1681. if (o is string) {
  1682. res.Add((string)o);
  1683. }
  1684. }
  1685. return res;
  1686. }
  1687. public override string/*!*/ FormatObject(DynamicOperations/*!*/ operations, object obj) {
  1688. return PythonOps.Repr(_defaultContext, obj) ?? "None";
  1689. }
  1690. internal object GetSystemStateValue(string name) {
  1691. object val;
  1692. if (SystemState.__dict__.TryGetValue(name, out val)) {
  1693. return val;
  1694. }
  1695. return null;
  1696. }
  1697. internal void SetSystemStateValue(string name, object value) {
  1698. SystemState.__dict__[name] = value;
  1699. }
  1700. internal void DelSystemStateValue(string name) {
  1701. SystemState.__dict__.Remove(name);
  1702. }
  1703. private void SetStandardIO() {
  1704. SharedIO io = DomainManager.SharedIO;
  1705. PythonFile stdin = PythonFile.CreateConsole(this, io, ConsoleStreamType.Input, "<stdin>");
  1706. PythonFile stdout = PythonFile.CreateConsole(this, io, ConsoleStreamType.Output, "<stdout>");
  1707. PythonFile stderr = PythonFile.CreateConsole(this, io, ConsoleStreamType.ErrorOutput, "<stderr>");
  1708. SetSystemStateValue("__stdin__", stdin);
  1709. SetSystemStateValue("stdin", stdin);
  1710. SetSystemStateValue("__stdout__", stdout);
  1711. SetSystemStateValue("stdout", stdout);
  1712. SetSystemStateValue("__stderr__", stderr);
  1713. SetSystemStateValue("stderr", stderr);
  1714. }
  1715. internal PythonFileManager RawFileManager {
  1716. get {
  1717. return _fileManager;
  1718. }
  1719. }
  1720. internal PythonFileManager/*!*/ FileManager {
  1721. get {
  1722. if (_fileManager == null) {
  1723. Interlocked.CompareExchange(ref _fileManager, new PythonFileManager(), null);
  1724. }
  1725. return _fileManager;
  1726. }
  1727. }
  1728. public override int ExecuteProgram(SourceUnit/*!*/ program) {
  1729. try {
  1730. PythonCompilerOptions pco = (PythonCompilerOptions)GetCompilerOptions();
  1731. pco.ModuleName = "__main__";
  1732. pco.Module |= ModuleOptions.Initialize;
  1733. program.Execute(pco, ErrorSink.Default);
  1734. } catch (SystemExitException e) {
  1735. object obj;
  1736. return e.GetExitCode(out obj);
  1737. }
  1738. return 0;
  1739. }
  1740. /// <summary> Dictionary of error handlers for string codecs. </summary>
  1741. internal Dictionary<string, object> ErrorHandlers {
  1742. get {
  1743. if (_errorHandlers == null) {
  1744. Interlocked.CompareExchange(ref _errorHandlers, new Dictionary<string, object>(), null);
  1745. }
  1746. return _errorHandlers;
  1747. }
  1748. }
  1749. /// <summary> Table of functions used for looking for additional codecs. </summary>
  1750. internal List<object> SearchFunctions {
  1751. get {
  1752. if (_searchFunctions == null) {
  1753. Interlocked.CompareExchange(ref _searchFunctions, new List<object>(), null);
  1754. }
  1755. return _searchFunctions;
  1756. }
  1757. }
  1758. /// <summary>
  1759. /// Gets a SiteLocalStorage when no call site is available.
  1760. /// </summary>
  1761. internal SiteLocalStorage<T> GetGenericSiteStorage<T>() {
  1762. if (_genericSiteStorage == null) {
  1763. Interlocked.CompareExchange(ref _genericSiteStorage, new Dictionary<Type, object>(), null);
  1764. }
  1765. lock (_genericSiteStorage) {
  1766. object res;
  1767. if (!_genericSiteStorage.TryGetValue(typeof(T), out res)) {
  1768. _genericSiteStorage[typeof(T)] = res = new SiteLocalStorage<T>();
  1769. }
  1770. return (SiteLocalStorage<T>)res;
  1771. }
  1772. }
  1773. internal SiteLocalStorage<CallSite<Func<CallSite, CodeContext, object, object[], object>>> GetGenericCallSiteStorage() {
  1774. return GetGenericSiteStorage<CallSite<Func<CallSite, CodeContext, object, object[], object>>>();
  1775. }
  1776. internal SiteLocalStorage<CallSite<Func<CallSite, CodeContext, object, object>>> GetGenericCallSiteStorage0() {
  1777. return GetGenericSiteStorage<CallSite<Func<CallSite, CodeContext, object, object>>>();
  1778. }
  1779. internal SiteLocalStorage<CallSite<Func<CallSite, CodeContext, object, object[], IDictionary<object, object>, object>>> GetGenericKeywordCallSiteStorage() {
  1780. return GetGenericSiteStorage<CallSite<Func<CallSite, CodeContext, object, object[], IDictionary<object, object>, object>>>();
  1781. }
  1782. #region Object Operations
  1783. public override ConvertBinder/*!*/ CreateConvertBinder(Type/*!*/ toType, bool? explicitCast) {
  1784. if (explicitCast != null) {
  1785. return Convert(toType, (bool)explicitCast ? ConversionResultKind.ExplicitCast : ConversionResultKind.ImplicitCast).CompatBinder;
  1786. } else {
  1787. return Convert(toType, ConversionResultKind.ImplicitCast).CompatBinder;
  1788. }
  1789. }
  1790. public override DeleteMemberBinder/*!*/ CreateDeleteMemberBinder(string/*!*/ name, bool ignoreCase) {
  1791. if (ignoreCase) {
  1792. return new PythonDeleteMemberBinder(this, name, ignoreCase);
  1793. }
  1794. return DeleteMember(name);
  1795. }
  1796. public override GetMemberBinder/*!*/ CreateGetMemberBinder(string/*!*/ name, bool ignoreCase) {
  1797. if (ignoreCase) {
  1798. return new CompatibilityGetMember(this, name, false);
  1799. }
  1800. return CompatGetMember(name, false);
  1801. }
  1802. public override InvokeBinder/*!*/ CreateInvokeBinder(CallInfo /*!*/ callInfo) {
  1803. return CompatInvoke(callInfo);
  1804. }
  1805. public override BinaryOperationBinder CreateBinaryOperationBinder(ExpressionType operation) {
  1806. return BinaryOperation(operation);
  1807. }
  1808. public override UnaryOperationBinder CreateUnaryOperationBinder(ExpressionType operation) {
  1809. return UnaryOperation(operation);
  1810. }
  1811. public override SetMemberBinder/*!*/ CreateSetMemberBinder(string/*!*/ name, bool ignoreCase) {
  1812. if (ignoreCase) {
  1813. return new PythonSetMemberBinder(this, name, ignoreCase);
  1814. }
  1815. return SetMember(name);
  1816. }
  1817. public override CreateInstanceBinder/*!*/ CreateCreateBinder(CallInfo /*!*/ callInfo) {
  1818. return Create(
  1819. CompatInvoke(callInfo),
  1820. callInfo
  1821. );
  1822. }
  1823. #endregion
  1824. internal WeakRefTracker GetSystemPythonTypeWeakRef(PythonType type) {
  1825. object wrt;
  1826. return _systemPythonTypesWeakRefs.TryGetValue(type, out wrt) ?
  1827. (WeakRefTracker)wrt :
  1828. null;
  1829. }
  1830. internal bool SetSystemPythonTypeWeakRef(PythonType type, WeakRefTracker value) {
  1831. lock(_systemPythonTypesWeakRefs) {
  1832. _systemPythonTypesWeakRefs.AddNoLock(type, value);
  1833. }
  1834. return true;
  1835. }
  1836. internal void SetSystemPythonTypeFinalizer(PythonType type, WeakRefTracker value) {
  1837. lock(_systemPythonTypesWeakRefs) {
  1838. _systemPythonTypesWeakRefs.AddNoLock(type, value);
  1839. }
  1840. }
  1841. internal bool TryConvertToWeakReferenceable(object obj, out IWeakReferenceable weakref) {
  1842. IWeakReferenceableByProxy iwrp = obj as IWeakReferenceableByProxy;
  1843. if (iwrp != null) {
  1844. weakref = iwrp.GetWeakRefProxy(this);
  1845. return true;
  1846. }
  1847. IWeakReferenceable iwr = obj as IWeakReferenceable;
  1848. if (iwr != null) {
  1849. weakref = iwr;
  1850. return true;
  1851. }
  1852. weakref = null;
  1853. return false;
  1854. }
  1855. internal IWeakReferenceable ConvertToWeakReferenceable(object obj) {
  1856. IWeakReferenceable iwr;
  1857. if (TryConvertToWeakReferenceable(obj, out iwr)) {
  1858. return iwr;
  1859. } else {
  1860. throw PythonOps.TypeError("cannot create weak reference to '{0}' object", PythonOps.GetPythonTypeName(obj));
  1861. }
  1862. }
  1863. #region Per-Runtime Call Sites
  1864. private bool InvokeOperatorWorker(CodeContext/*!*/ context, UnaryOperators oper, object target, out object result) {
  1865. if (_newUnarySites == null) {
  1866. Interlocked.CompareExchange(
  1867. ref _newUnarySites,
  1868. new CallSite<Func<CallSite, CodeContext, object, object>>[(int)UnaryOperators.Maximum],
  1869. null
  1870. );
  1871. }
  1872. if (_newUnarySites[(int)oper] == null) {
  1873. Interlocked.CompareExchange(
  1874. ref _newUnarySites[(int)oper],
  1875. CallSite<Func<CallSite, CodeContext, object, object>>.Create(
  1876. InvokeNone
  1877. ),
  1878. null
  1879. );
  1880. }
  1881. CallSite<Func<CallSite, CodeContext, object, object>> site = _newUnarySites[(int)oper];
  1882. var symbol = GetUnarySymbol(oper);
  1883. PythonType pt = DynamicHelpers.GetPythonType(target);
  1884. PythonTypeSlot pts;
  1885. object callable;
  1886. if (pt.TryResolveMixedSlot(context, symbol, out pts) &&
  1887. pts.TryGetValue(context, target, pt, out callable)) {
  1888. result = site.Target(site, context, callable);
  1889. return true;
  1890. }
  1891. result = null;
  1892. return false;
  1893. }
  1894. private static string GetUnarySymbol(UnaryOperators oper) {
  1895. string symbol;
  1896. switch (oper) {
  1897. case UnaryOperators.Repr: symbol = "__repr__"; break;
  1898. case UnaryOperators.Length: symbol = "__len__"; break;
  1899. case UnaryOperators.Hash: symbol = "__hash__"; break;
  1900. case UnaryOperators.String: symbol = "__str__"; break;
  1901. default: throw new ValueErrorException("unknown unary symbol");
  1902. }
  1903. return symbol;
  1904. }
  1905. private bool InvokeOperatorWorker(CodeContext/*!*/ context, TernaryOperators oper, object target, object value1, object value2, out object result) {
  1906. if (_newTernarySites == null) {
  1907. Interlocked.CompareExchange(
  1908. ref _newTernarySites,
  1909. new CallSite<Func<CallSite, CodeContext, object, object, object, object>>[(int)TernaryOperators.Maximum],
  1910. null
  1911. );
  1912. }
  1913. if (_newTernarySites[(int)oper] == null) {
  1914. Interlocked.CompareExchange(
  1915. ref _newTernarySites[(int)oper],
  1916. CallSite<Func<CallSite, CodeContext, object, object, object, object>>.Create(
  1917. Invoke(
  1918. new CallSignature(2)
  1919. )
  1920. ),
  1921. null
  1922. );
  1923. }
  1924. CallSite<Func<CallSite, CodeContext, object, object, object, object>> site = _newTernarySites[(int)oper];
  1925. string symbol = GetTernarySymbol(oper);
  1926. PythonType pt = DynamicHelpers.GetPythonType(target);
  1927. PythonTypeSlot pts;
  1928. object callable;
  1929. if (pt.TryResolveMixedSlot(context, symbol, out pts) &&
  1930. pts.TryGetValue(context, target, pt, out callable)) {
  1931. result = site.Target(site, context, callable, value1, value2);
  1932. return true;
  1933. }
  1934. result = null;
  1935. return false;
  1936. }
  1937. private static string GetTernarySymbol(TernaryOperators oper) {
  1938. string symbol;
  1939. switch (oper) {
  1940. case TernaryOperators.SetDescriptor: symbol = "__set__"; break;
  1941. case TernaryOperators.GetDescriptor: symbol = "__get__"; break;
  1942. default: throw new ValueErrorException("unknown ternary operator");
  1943. }
  1944. return symbol;
  1945. }
  1946. internal static object InvokeUnaryOperator(CodeContext/*!*/ context, UnaryOperators oper, object target, string errorMsg) {
  1947. object res;
  1948. if (PythonContext.GetContext(context).InvokeOperatorWorker(context, oper, target, out res)) {
  1949. return res;
  1950. }
  1951. throw PythonOps.TypeError(errorMsg);
  1952. }
  1953. internal static object InvokeUnaryOperator(CodeContext/*!*/ context, UnaryOperators oper, object target) {
  1954. object res;
  1955. if (PythonContext.GetContext(context).InvokeOperatorWorker(context, oper, target, out res)) {
  1956. return res;
  1957. }
  1958. throw PythonOps.TypeError(String.Empty);
  1959. }
  1960. internal static bool TryInvokeTernaryOperator(CodeContext/*!*/ context, TernaryOperators oper, object target, object value1, object value2, out object res) {
  1961. return PythonContext.GetContext(context).InvokeOperatorWorker(context, oper, target, value1, value2, out res);
  1962. }
  1963. internal CallSite<Func<CallSite, object, object, int>> CompareSite {
  1964. get {
  1965. if (_compareSite == null) {
  1966. Interlocked.CompareExchange(ref _compareSite,
  1967. MakeSortCompareSite(),
  1968. null
  1969. );
  1970. }
  1971. return _compareSite;
  1972. }
  1973. }
  1974. internal CallSite<Func<CallSite, object, object, int>> MakeSortCompareSite() {
  1975. return CallSite<Func<CallSite, object, object, int>>.Create(
  1976. Operation(
  1977. PythonOperationKind.Compare
  1978. )
  1979. );
  1980. }
  1981. internal void SetAttr(CodeContext/*!*/ context, object o, string name, object value) {
  1982. CallSite<Func<CallSite, object, object, object>> site;
  1983. if (_setAttrSites == null) {
  1984. Interlocked.CompareExchange(ref _setAttrSites, new Dictionary<AttrKey, CallSite<Func<CallSite, object, object, object>>>(), null);
  1985. }
  1986. lock (_setAttrSites) {
  1987. AttrKey key = new AttrKey(CompilerHelpers.GetType(o), name);
  1988. if (!_setAttrSites.TryGetValue(key, out site)) {
  1989. _setAttrSites[key] = site = CallSite<Func<CallSite, object, object, object>>.Create(
  1990. SetMember(
  1991. name
  1992. )
  1993. );
  1994. }
  1995. }
  1996. site.Target.Invoke(site, o, value);
  1997. }
  1998. internal void DeleteAttr(CodeContext/*!*/ context, object o, string name) {
  1999. AttrKey key = new AttrKey(CompilerHelpers.GetType(o), name);
  2000. if (_deleteAttrSites == null) {
  2001. Interlocked.CompareExchange(ref _deleteAttrSites, new Dictionary<AttrKey, CallSite<Action<CallSite, object>>>(), null);
  2002. }
  2003. CallSite<Action<CallSite, object>> site;
  2004. lock (_deleteAttrSites) {
  2005. if (!_deleteAttrSites.TryGetValue(key, out site)) {
  2006. _deleteAttrSites[key] = site = CallSite<Action<CallSite, object>>.Create(
  2007. DeleteMember(name)
  2008. );
  2009. }
  2010. }
  2011. site.Target(site, o);
  2012. }
  2013. internal CallSite<Func<CallSite, CodeContext, object, string, PythonTuple, PythonDictionary, object>> MetaClassCallSite {
  2014. get {
  2015. if (_metaClassSite == null) {
  2016. Interlocked.CompareExchange(
  2017. ref _metaClassSite,
  2018. CallSite<Func<CallSite, CodeContext, object, string, PythonTuple, PythonDictionary, object>>.Create(
  2019. Invoke(
  2020. new CallSignature(3)
  2021. )
  2022. ),
  2023. null
  2024. );
  2025. }
  2026. return _metaClassSite;
  2027. }
  2028. }
  2029. internal CallSite<Func<CallSite, CodeContext, object, string, object>> WriteCallSite {
  2030. get {
  2031. if (_writeSite == null) {
  2032. Interlocked.CompareExchange(
  2033. ref _writeSite,
  2034. CallSite<Func<CallSite, CodeContext, object, string, object>>.Create(
  2035. InvokeOne
  2036. ),
  2037. null
  2038. );
  2039. }
  2040. return _writeSite;
  2041. }
  2042. }
  2043. internal CallSite<Func<CallSite, object, object, object>> GetIndexSite {
  2044. get {
  2045. if (_getIndexSite == null) {
  2046. Interlocked.CompareExchange(
  2047. ref _getIndexSite,
  2048. CallSite<Func<CallSite, object, object, object>>.Create(
  2049. GetIndex(
  2050. 1
  2051. )
  2052. ),
  2053. null
  2054. );
  2055. }
  2056. return _getIndexSite;
  2057. }
  2058. }
  2059. internal void DelIndex(object target, object index) {
  2060. if (_delIndexSite == null) {
  2061. Interlocked.CompareExchange(
  2062. ref _delIndexSite,
  2063. CallSite<Action<CallSite, object, object>>.Create(
  2064. DeleteIndex(
  2065. 1
  2066. )
  2067. ),
  2068. null
  2069. );
  2070. }
  2071. _delIndexSite.Target(_delIndexSite, target, index);
  2072. }
  2073. internal void DelSlice(object target, object start, object end) {
  2074. if (_delSliceSite == null) {
  2075. Interlocked.CompareExchange(
  2076. ref _delSliceSite,
  2077. CallSite<Func<CallSite, object, object, object, object>>.Create(
  2078. DeleteSlice
  2079. ),
  2080. null
  2081. );
  2082. }
  2083. _delSliceSite.Target(_delSliceSite, target, start, end);
  2084. }
  2085. internal void SetIndex(object a, object b, object c) {
  2086. if (_setIndexSite == null) {
  2087. Interlocked.CompareExchange(
  2088. ref _setIndexSite,
  2089. CallSite<Func<CallSite, object, object, object, object>>.Create(
  2090. SetIndex(1)
  2091. ),
  2092. null
  2093. );
  2094. }
  2095. _setIndexSite.Target(_setIndexSite, a, b, c);
  2096. }
  2097. internal void SetSlice(object a, object start, object end, object value) {
  2098. if (_setSliceSite == null) {
  2099. Interlocked.CompareExchange(
  2100. ref _setSliceSite,
  2101. CallSite<Func<CallSite, object, object, object, object, object>>.Create(
  2102. SetSliceBinder
  2103. ),
  2104. null
  2105. );
  2106. }
  2107. _setSliceSite.Target(_setSliceSite, a, start, end, value);
  2108. }
  2109. internal CallSite<Func<CallSite, object, object, object>> EqualSite {
  2110. get {
  2111. if (_equalSite == null) {
  2112. Interlocked.CompareExchange(
  2113. ref _equalSite,
  2114. CallSite<Func<CallSite, object, object, object>>.Create(
  2115. BinaryOperation(
  2116. ExpressionType.Equal
  2117. )
  2118. ),
  2119. null
  2120. );
  2121. }
  2122. return _equalSite;
  2123. }
  2124. }
  2125. internal CallSite<Func<CallSite, CodeContext, object, object>> FinalizerSite {
  2126. get {
  2127. if (_finalizerSite == null) {
  2128. Interlocked.CompareExchange(
  2129. ref _finalizerSite,
  2130. CallSite<Func<CallSite, CodeContext, object, object>>.Create(
  2131. InvokeNone
  2132. ),
  2133. null
  2134. );
  2135. }
  2136. return _finalizerSite;
  2137. }
  2138. }
  2139. internal CallSite<Func<CallSite, CodeContext, PythonFunction, object>> FunctionCallSite {
  2140. get {
  2141. if (_functionCallSite == null) {
  2142. Interlocked.CompareExchange(
  2143. ref _functionCallSite,
  2144. CallSite<Func<CallSite, CodeContext, PythonFunction, object>>.Create(
  2145. InvokeNone
  2146. ),
  2147. null
  2148. );
  2149. }
  2150. return _functionCallSite;
  2151. }
  2152. }
  2153. class AttrKey : IEquatable<AttrKey> {
  2154. private Type _type;
  2155. private string _name;
  2156. public AttrKey(Type type, string name) {
  2157. _type = type;
  2158. _name = name;
  2159. }
  2160. #region IEquatable<AttrKey> Members
  2161. public bool Equals(AttrKey other) {
  2162. if (other == null) return false;
  2163. return _type == other._type && _name == other._name;
  2164. }
  2165. #endregion
  2166. public override bool Equals(object obj) {
  2167. return Equals(obj as AttrKey);
  2168. }
  2169. public override int GetHashCode() {
  2170. return _type.GetHashCode() ^ _name.GetHashCode();
  2171. }
  2172. }
  2173. public override string GetDocumentation(object obj) {
  2174. if (_docSite == null) {
  2175. _docSite = CallSite<Func<CallSite, object, string>>.Create(
  2176. Operation(
  2177. PythonOperationKind.Documentation
  2178. )
  2179. );
  2180. }
  2181. return _docSite.Target(_docSite, obj);
  2182. }
  2183. internal PythonSiteCache GetSiteCacheForSystemType(Type type) {
  2184. if (_systemSiteCache == null) {
  2185. Interlocked.CompareExchange(ref _systemSiteCache, new Dictionary<Type, PythonSiteCache>(), null);
  2186. }
  2187. lock (_systemSiteCache) {
  2188. PythonSiteCache result;
  2189. if (!_systemSiteCache.TryGetValue(type, out result)) {
  2190. _systemSiteCache[type] = result = new PythonSiteCache();
  2191. }
  2192. return result;
  2193. }
  2194. }
  2195. #endregion
  2196. #region Conversions
  2197. internal Int32 ConvertToInt32(object value) {
  2198. if (_intSite == null) {
  2199. Interlocked.CompareExchange(ref _intSite, MakeExplicitConvertSite<int>(), null);
  2200. }
  2201. return _intSite.Target.Invoke(_intSite, value);
  2202. }
  2203. internal bool TryConvertToString(object str, out string res) {
  2204. if (_tryStringSite == null) {
  2205. Interlocked.CompareExchange(ref _tryStringSite, MakeExplicitTrySite<string>(), null);
  2206. }
  2207. res = _tryStringSite.Target(_tryStringSite, str);
  2208. return res != null;
  2209. }
  2210. internal bool TryConvertToInt32(object val, out int res) {
  2211. if (_tryIntSite == null) {
  2212. Interlocked.CompareExchange(ref _tryIntSite, MakeExplicitStructTrySite<int>(), null);
  2213. }
  2214. object objRes = _tryIntSite.Target(_tryIntSite, val);
  2215. if (objRes != null) {
  2216. res = (int)objRes;
  2217. return true;
  2218. }
  2219. res = 0;
  2220. return false;
  2221. }
  2222. internal bool TryConvertToIEnumerable(object enumerable, out IEnumerable res) {
  2223. if (_tryIEnumerableSite == null) {
  2224. Interlocked.CompareExchange(ref _tryIEnumerableSite, MakeExplicitTrySite<IEnumerable>(), null);
  2225. }
  2226. res = _tryIEnumerableSite.Target(_tryIEnumerableSite, enumerable);
  2227. return res != null;
  2228. }
  2229. private CallSite<Func<CallSite, object, T>> MakeExplicitTrySite<T>() where T : class {
  2230. return MakeTrySite<T, T>(ConversionResultKind.ExplicitTry);
  2231. }
  2232. private CallSite<Func<CallSite, object, object>> MakeExplicitStructTrySite<T>() where T : struct {
  2233. return MakeTrySite<T, object>(ConversionResultKind.ExplicitTry);
  2234. }
  2235. private CallSite<Func<CallSite, object, TRet>> MakeTrySite<T, TRet>(ConversionResultKind kind) {
  2236. return CallSite<Func<CallSite, object, TRet>>.Create(
  2237. Convert(
  2238. typeof(T),
  2239. kind
  2240. )
  2241. );
  2242. }
  2243. internal object ImplicitConvertTo<T>(object value) {
  2244. if (_implicitConvertSites == null) {
  2245. Interlocked.CompareExchange(ref _implicitConvertSites, new Dictionary<Type, CallSite<Func<CallSite, object, object>>>(), null);
  2246. }
  2247. CallSite<Func<CallSite, object, object>> site;
  2248. lock (_implicitConvertSites) {
  2249. if (!_implicitConvertSites.TryGetValue(typeof(T), out site)) {
  2250. _implicitConvertSites[typeof(T)] = site = MakeImplicitConvertSite<T>();
  2251. }
  2252. }
  2253. return site.Target(site, value);
  2254. }
  2255. /*
  2256. public static String ConvertToString(object value) { return _stringSite.Invoke(DefaultContext.Default, value); }
  2257. public static BigInteger ConvertToBigInteger(object value) { return _bigIntSite.Invoke(DefaultContext.Default, value); }
  2258. public static Double ConvertToDouble(object value) { return _doubleSite.Invoke(DefaultContext.Default, value); }
  2259. public static Complex64 ConvertToComplex(object value) { return _complexSite.Invoke(DefaultContext.Default, value); }
  2260. public static Boolean ConvertToBoolean(object value) { return _boolSite.Invoke(DefaultContext.Default, value); }
  2261. public static Int64 ConvertToInt64(object value) { return _int64Site.Invoke(DefaultContext.Default, value); }
  2262. */
  2263. private CallSite<Func<CallSite, object, T>> MakeExplicitConvertSite<T>() {
  2264. return MakeConvertSite<T>(ConversionResultKind.ExplicitCast);
  2265. }
  2266. private CallSite<Func<CallSite, object, object>> MakeImplicitConvertSite<T>() {
  2267. return CallSite<Func<CallSite, object, object>>.Create(
  2268. ConvertRetObject(
  2269. typeof(T),
  2270. ConversionResultKind.ImplicitCast
  2271. )
  2272. );
  2273. }
  2274. private CallSite<Func<CallSite, object, T>> MakeConvertSite<T>(ConversionResultKind kind) {
  2275. return CallSite<Func<CallSite, object, T>>.Create(
  2276. Convert(
  2277. typeof(T),
  2278. kind
  2279. )
  2280. );
  2281. }
  2282. /// <summary>
  2283. /// Invokes the specified operation on the provided arguments and returns the new resulting value.
  2284. ///
  2285. /// operation is usually a value from StandardOperators (standard CLR/DLR operator) or
  2286. /// OperatorStrings (a Python specific operator)
  2287. /// </summary>
  2288. internal object Operation(PythonOperationKind operation, object self, object other) {
  2289. if (_binarySites == null) {
  2290. Interlocked.CompareExchange(
  2291. ref _binarySites,
  2292. new Dictionary<PythonOperationKind, CallSite<Func<CallSite, object, object, object>>>(),
  2293. null
  2294. );
  2295. }
  2296. CallSite<Func<CallSite, object, object, object>> site;
  2297. lock (_binarySites) {
  2298. if (!_binarySites.TryGetValue(operation, out site)) {
  2299. _binarySites[operation] = site = CallSite<Func<CallSite, object, object, object>>.Create(
  2300. Binders.BinaryOperationBinder(this, operation)
  2301. );
  2302. }
  2303. }
  2304. return site.Target(site, self, other);
  2305. }
  2306. internal bool GreaterThan(object self, object other) {
  2307. return Comparison(self, other, ExpressionType.GreaterThan, ref _greaterThanSite);
  2308. }
  2309. internal bool LessThan(object self, object other) {
  2310. return Comparison(self, other, ExpressionType.LessThan, ref _lessThanSite);
  2311. }
  2312. internal bool GreaterThanOrEqual(object self, object other) {
  2313. return Comparison(self, other, ExpressionType.GreaterThanOrEqual, ref _greaterThanEqualSite);
  2314. }
  2315. internal bool LessThanOrEqual(object self, object other) {
  2316. return Comparison(self, other, ExpressionType.LessThanOrEqual, ref _lessThanEqualSite);
  2317. }
  2318. internal bool Contains(object self, object other) {
  2319. return Comparison(self, other, PythonOperationKind.Contains, ref _containsSite);
  2320. }
  2321. internal static bool Equal(object self, object other) {
  2322. return DynamicHelpers.GetPythonType(self).EqualRetBool(self, other);
  2323. }
  2324. internal static bool NotEqual(object self, object other) {
  2325. return !Equal(self, other);
  2326. }
  2327. private bool Comparison(object self, object other, ExpressionType operation, ref CallSite<Func<CallSite, object, object, bool>> comparisonSite) {
  2328. if (comparisonSite == null) {
  2329. Interlocked.CompareExchange(
  2330. ref comparisonSite,
  2331. CreateComparisonSite(operation),
  2332. null
  2333. );
  2334. }
  2335. return comparisonSite.Target(comparisonSite, self, other);
  2336. }
  2337. internal CallSite<Func<CallSite, object, object, bool>> CreateComparisonSite(ExpressionType op) {
  2338. return CallSite<Func<CallSite, object, object, bool>>.Create(
  2339. BinaryOperationRetType(
  2340. BinaryOperation(op),
  2341. Convert(typeof(bool), ConversionResultKind.ExplicitCast)
  2342. )
  2343. );
  2344. }
  2345. private bool Comparison(object self, object other, PythonOperationKind operation, ref CallSite<Func<CallSite, object, object, bool>> comparisonSite) {
  2346. if (comparisonSite == null) {
  2347. Interlocked.CompareExchange(
  2348. ref comparisonSite,
  2349. CreateComparisonSite(operation),
  2350. null
  2351. );
  2352. }
  2353. return comparisonSite.Target(comparisonSite, self, other);
  2354. }
  2355. internal CallSite<Func<CallSite, object, object, bool>> CreateComparisonSite(PythonOperationKind op) {
  2356. return CallSite<Func<CallSite, object, object, bool>>.Create(
  2357. OperationRetType(
  2358. Operation(op),
  2359. Convert(typeof(bool), ConversionResultKind.ExplicitCast)
  2360. )
  2361. );
  2362. }
  2363. internal object CallSplat(object func, params object[] args) {
  2364. EnsureCallSplatSite();
  2365. return _callSplatSite.Target(_callSplatSite, SharedContext, func, args);
  2366. }
  2367. internal object CallWithContext(CodeContext/*!*/ context, object func, params object[] args) {
  2368. EnsureCallSplatSite();
  2369. return _callSplatSite.Target(_callSplatSite, context, func, args);
  2370. }
  2371. internal object Call(CodeContext/*!*/ context, object func) {
  2372. EnsureCall0Site();
  2373. return _callSite0.Target(_callSite0, context, func);
  2374. }
  2375. private void EnsureCall0SiteLightEh() {
  2376. if (_callSite0LightEh == null) {
  2377. Interlocked.CompareExchange(
  2378. ref _callSite0LightEh,
  2379. CallSite<Func<CallSite, CodeContext, object, object>>.Create(Invoke(new CallSignature(0)).GetLightExceptionBinder()),
  2380. null
  2381. );
  2382. }
  2383. }
  2384. internal object CallLightEh(CodeContext/*!*/ context, object func) {
  2385. EnsureCall0SiteLightEh();
  2386. return _callSite0LightEh.Target(_callSite0LightEh, context, func);
  2387. }
  2388. internal object Call(CodeContext/*!*/ context, object func, object arg0) {
  2389. EnsureCall1Site();
  2390. return _callSite1.Target(_callSite1, context, func, arg0);
  2391. }
  2392. internal object Call(CodeContext/*!*/ context, object func, object arg0, object arg1) {
  2393. EnsureCall2Site();
  2394. return _callSite2.Target(_callSite2, context, func, arg0, arg1);
  2395. }
  2396. private void EnsureCallSplatSite() {
  2397. if (_callSplatSite == null) {
  2398. Interlocked.CompareExchange(
  2399. ref _callSplatSite,
  2400. MakeSplatSite(),
  2401. null
  2402. );
  2403. }
  2404. }
  2405. internal CallSite<Func<CallSite, CodeContext, object, object[], object>> MakeSplatSite() {
  2406. return CallSite<Func<CallSite, CodeContext, object, object[], object>>.Create(Binders.InvokeSplat(this));
  2407. }
  2408. internal object CallWithKeywords(object func, object[] args, IDictionary<object, object> dict) {
  2409. if (_callDictSite == null) {
  2410. Interlocked.CompareExchange(
  2411. ref _callDictSite,
  2412. MakeKeywordSplatSite(),
  2413. null
  2414. );
  2415. }
  2416. return _callDictSite.Target(_callDictSite, SharedContext, func, args, dict);
  2417. }
  2418. internal CallSite<Func<CallSite, CodeContext, object, object[], IDictionary<object, object>, object>> MakeKeywordSplatSite() {
  2419. return CallSite<Func<CallSite, CodeContext, object, object[], IDictionary<object, object>, object>>.Create(Binders.InvokeKeywords(this));
  2420. }
  2421. internal object CallWithKeywords(object func, object args, object dict) {
  2422. if (_callDictSiteLooselyTyped == null) {
  2423. Interlocked.CompareExchange(
  2424. ref _callDictSiteLooselyTyped,
  2425. MakeKeywordSplatSiteLooselyTyped(),
  2426. null
  2427. );
  2428. }
  2429. return _callDictSiteLooselyTyped.Target(_callDictSiteLooselyTyped, SharedContext, func, args, dict);
  2430. }
  2431. internal CallSite<Func<CallSite, CodeContext, object, object, object, object>> MakeKeywordSplatSiteLooselyTyped() {
  2432. return CallSite<Func<CallSite, CodeContext, object, object, object, object>>.Create(Binders.InvokeKeywords(this));
  2433. }
  2434. internal CallSite<Func<CallSite, CodeContext, object, string, PythonDictionary, PythonDictionary, PythonTuple, int, object>> ImportSite {
  2435. get {
  2436. if (_importSite == null) {
  2437. Interlocked.CompareExchange(
  2438. ref _importSite,
  2439. CallSite<Func<CallSite, CodeContext, object, string, PythonDictionary, PythonDictionary, PythonTuple, int, object>>.Create(
  2440. Invoke(
  2441. new CallSignature(5)
  2442. ).GetLightExceptionBinder()
  2443. ),
  2444. null
  2445. );
  2446. }
  2447. return _importSite;
  2448. }
  2449. }
  2450. internal CallSite<Func<CallSite, CodeContext, object, string, PythonDictionary, PythonDictionary, PythonTuple, object>> OldImportSite {
  2451. get {
  2452. if (_oldImportSite == null) {
  2453. Interlocked.CompareExchange(
  2454. ref _oldImportSite,
  2455. CallSite<Func<CallSite, CodeContext, object, string, PythonDictionary, PythonDictionary, PythonTuple, object>>.Create(
  2456. Invoke(
  2457. new CallSignature(4)
  2458. ).GetLightExceptionBinder()
  2459. ),
  2460. null
  2461. );
  2462. }
  2463. return _oldImportSite;
  2464. }
  2465. }
  2466. public override bool IsCallable(object obj) {
  2467. if (_isCallableSite == null) {
  2468. Interlocked.CompareExchange(
  2469. ref _isCallableSite,
  2470. CallSite<Func<CallSite, object, bool>>.Create(
  2471. Operation(
  2472. PythonOperationKind.IsCallable
  2473. )
  2474. ),
  2475. null
  2476. );
  2477. }
  2478. return _isCallableSite.Target(_isCallableSite, obj);
  2479. }
  2480. internal static int Hash(object o) {
  2481. if (o != null) {
  2482. switch (o.GetType().GetTypeCode()) {
  2483. case TypeCode.Int32: return Int32Ops.__hash__((int)o);
  2484. case TypeCode.String: return ((string)o).GetHashCode();
  2485. case TypeCode.Double: return DoubleOps.__hash__((double)o);
  2486. case TypeCode.Int16: return Int16Ops.__hash__((short)o);
  2487. case TypeCode.Int64: return Int64Ops.__hash__((long)o);
  2488. case TypeCode.SByte: return SByteOps.__hash__((sbyte)o);
  2489. case TypeCode.Single: return SingleOps.__hash__((float)o);
  2490. case TypeCode.UInt16: return UInt16Ops.__hash__((ushort)o);
  2491. case TypeCode.UInt32: return UInt32Ops.__hash__((uint)o);
  2492. case TypeCode.UInt64: return UInt64Ops.__hash__((ulong)o);
  2493. case TypeCode.Decimal: return DecimalOps.__hash__((decimal)o);
  2494. case TypeCode.DateTime: return ((DateTime)o).GetHashCode();
  2495. case TypeCode.Boolean: return ((bool)o).GetHashCode();
  2496. case TypeCode.Byte: return ByteOps.__hash__((byte)o);
  2497. }
  2498. }
  2499. return DynamicHelpers.GetPythonType(o).Hash(o);
  2500. }
  2501. internal static bool IsHashable(object o) {
  2502. if (o == null) {
  2503. return true;
  2504. }
  2505. switch (o.GetType().GetTypeCode()) {
  2506. case TypeCode.Int32:
  2507. case TypeCode.String:
  2508. case TypeCode.Double:
  2509. case TypeCode.Int16:
  2510. case TypeCode.Int64:
  2511. case TypeCode.SByte:
  2512. case TypeCode.Single:
  2513. case TypeCode.UInt16:
  2514. case TypeCode.UInt32:
  2515. case TypeCode.UInt64:
  2516. case TypeCode.Decimal:
  2517. case TypeCode.DateTime:
  2518. case TypeCode.Boolean:
  2519. case TypeCode.Byte:
  2520. return true;
  2521. }
  2522. object hashFunction;
  2523. if (PythonOps.TryGetBoundAttr(o, "__hash__", out hashFunction) && hashFunction != null) {
  2524. return true;
  2525. }
  2526. var instance = o as OldInstance;
  2527. if (instance != null) {
  2528. if (instance.TryGetBoundCustomMember(DefaultContext.Default, "__hash__", out hashFunction) ||
  2529. ( ! instance.TryGetBoundCustomMember(DefaultContext.Default, "__cmp__", out hashFunction) &&
  2530. ! instance.TryGetBoundCustomMember(DefaultContext.Default, "__eq__", out hashFunction))) {
  2531. return true;
  2532. }
  2533. }
  2534. if (o is PythonType) {
  2535. return true;
  2536. }
  2537. return false;
  2538. }
  2539. internal object Add(object x, object y) {
  2540. var addSite = EnsureAddSite();
  2541. return addSite.Target(addSite, x, y);
  2542. }
  2543. internal CallSite<Func<CallSite, object, object, object>> EnsureAddSite() {
  2544. if (_addSite == null) {
  2545. Interlocked.CompareExchange(
  2546. ref _addSite,
  2547. CallSite<Func<CallSite, object, object, object>>.Create(
  2548. BinaryOperation(ExpressionType.Add)
  2549. ),
  2550. null
  2551. );
  2552. }
  2553. return _addSite;
  2554. }
  2555. internal object DivMod(object x, object y) {
  2556. if (_divModSite == null) {
  2557. Interlocked.CompareExchange(
  2558. ref _divModSite,
  2559. CallSite<Func<CallSite, object, object, object>>.Create(
  2560. Operation(PythonOperationKind.DivMod)
  2561. ),
  2562. null
  2563. );
  2564. }
  2565. object ret = _divModSite.Target(_divModSite, x, y);
  2566. if (ret != NotImplementedType.Value) {
  2567. return ret;
  2568. }
  2569. if (_rdivModSite == null) {
  2570. Interlocked.CompareExchange(
  2571. ref _rdivModSite,
  2572. CallSite<Func<CallSite, object, object, object>>.Create(
  2573. Operation(PythonOperationKind.ReverseDivMod)
  2574. ),
  2575. null
  2576. );
  2577. }
  2578. ret = _rdivModSite.Target(_rdivModSite, x, y);
  2579. if (ret != NotImplementedType.Value) {
  2580. return ret;
  2581. }
  2582. throw PythonOps.TypeErrorForBinaryOp("divmod", x, y);
  2583. }
  2584. #endregion
  2585. #region Compiled Code Support
  2586. internal CompiledLoader GetCompiledLoader() {
  2587. if (_compiledLoader == null) {
  2588. if (Interlocked.CompareExchange(ref _compiledLoader, new CompiledLoader(), null) == null) {
  2589. object path;
  2590. List lstPath;
  2591. if (!SystemState.__dict__.TryGetValue("meta_path", out path) || ((lstPath = path as List) == null)) {
  2592. SystemState.__dict__["meta_path"] = lstPath = new List();
  2593. }
  2594. lstPath.append(_compiledLoader);
  2595. }
  2596. }
  2597. return _compiledLoader;
  2598. }
  2599. #endregion
  2600. /// <summary>
  2601. /// Returns a shared code context for the current PythonContext. This shared
  2602. /// context can be used for performing general operations which usually
  2603. /// require a CodeContext.
  2604. /// </summary>
  2605. internal CodeContext SharedContext {
  2606. get {
  2607. return _defaultContext;
  2608. }
  2609. }
  2610. /// <summary>
  2611. /// Returns an overload resolver for the current PythonContext. The overload
  2612. /// resolver will flow the shared context through as it's CodeContext.
  2613. /// </summary>
  2614. internal PythonOverloadResolverFactory SharedOverloadResolverFactory {
  2615. get {
  2616. return _sharedOverloadResolverFactory;
  2617. }
  2618. }
  2619. /// <summary>
  2620. /// Returns a shared code context for the current PythonContext. This shared
  2621. /// context can be used for doing lookups which need to occur as if they
  2622. /// happened in a module which has done "import clr".
  2623. /// </summary>
  2624. internal CodeContext SharedClsContext {
  2625. get {
  2626. return _defaultClsContext;
  2627. }
  2628. }
  2629. internal ClrModule.ReferencesList ReferencedAssemblies {
  2630. get {
  2631. if (_referencesList == null) {
  2632. Interlocked.CompareExchange(ref _referencesList, new ClrModule.ReferencesList(), null);
  2633. }
  2634. return _referencesList;
  2635. }
  2636. }
  2637. internal static CultureInfo CCulture {
  2638. get {
  2639. if (_CCulture == null) {
  2640. Interlocked.CompareExchange(ref _CCulture, MakeCCulture(), null);
  2641. }
  2642. return _CCulture;
  2643. }
  2644. }
  2645. private static CultureInfo MakeCCulture() {
  2646. CultureInfo res = (CultureInfo)CultureInfo.InvariantCulture.Clone();
  2647. res.NumberFormat.NumberGroupSizes = new int[] { 0 };
  2648. res.NumberFormat.CurrencyGroupSizes = new int[] { 0 };
  2649. return res;
  2650. }
  2651. internal CultureInfo CollateCulture {
  2652. get {
  2653. if (_collateCulture == null) {
  2654. _collateCulture = CCulture;
  2655. }
  2656. return _collateCulture;
  2657. }
  2658. set { _collateCulture = value; }
  2659. }
  2660. internal CultureInfo CTypeCulture {
  2661. get {
  2662. if (_ctypeCulture == null) {
  2663. _ctypeCulture = CCulture;
  2664. }
  2665. return _ctypeCulture;
  2666. }
  2667. set { _ctypeCulture = value; }
  2668. }
  2669. internal CultureInfo TimeCulture {
  2670. get {
  2671. if (_timeCulture == null) {
  2672. _timeCulture = CCulture;
  2673. }
  2674. return _timeCulture;
  2675. }
  2676. set { _timeCulture = value; }
  2677. }
  2678. internal CultureInfo MonetaryCulture {
  2679. get {
  2680. if (_monetaryCulture == null) {
  2681. _monetaryCulture = CCulture;
  2682. }
  2683. return _monetaryCulture;
  2684. }
  2685. set { _monetaryCulture = value; }
  2686. }
  2687. internal CultureInfo NumericCulture {
  2688. get {
  2689. if (_numericCulture == null) {
  2690. _numericCulture = CCulture;
  2691. }
  2692. return _numericCulture;
  2693. }
  2694. set { _numericCulture = value; }
  2695. }
  2696. #region Command Dispatching
  2697. /// <summary>
  2698. /// Sets the current command dispatcher for the Python command line. The previous dispatcher
  2699. /// is returned. Null can be passed to remove the current command dispatcher.
  2700. ///
  2701. /// The command dispatcher will be called with a delegate to be executed. The command dispatcher
  2702. /// should invoke the target delegate in the desired context.
  2703. ///
  2704. /// A common use for this is to enable running all REPL commands on the UI thread while the REPL
  2705. /// continues to run on a non-UI thread.
  2706. ///
  2707. /// The ipy.exe REPL will call into PythonContext.DispatchCommand to dispatch each execution to
  2708. /// the correct thread. Other REPLs can do the same to support this functionality as well.
  2709. /// </summary>
  2710. public Action<Action> GetSetCommandDispatcher(Action<Action> newDispatcher) {
  2711. return Interlocked.Exchange(ref _commandDispatcher, newDispatcher);
  2712. }
  2713. public Action<Action> GetCommandDispatcher() {
  2714. return _commandDispatcher;
  2715. }
  2716. /// <summary>
  2717. /// Dispatches the command to the current command dispatcher. If there is no current command
  2718. /// dispatcher the command is executed immediately on the current thread.
  2719. /// </summary>
  2720. public void DispatchCommand(Action command) {
  2721. Action<Action> dispatcher = _commandDispatcher;
  2722. if (dispatcher != null) {
  2723. dispatcher(command);
  2724. } else if (command != null) {
  2725. command();
  2726. }
  2727. }
  2728. #endregion
  2729. internal CallSite<Func<CallSite, CodeContext, object, object, object>> PropertyGetSite {
  2730. get {
  2731. if (_propGetSite == null) {
  2732. Interlocked.CompareExchange(ref _propGetSite,
  2733. CallSite<Func<CallSite, CodeContext, object, object, object>>.Create(
  2734. InvokeOne
  2735. ),
  2736. null
  2737. );
  2738. }
  2739. return _propGetSite;
  2740. }
  2741. }
  2742. internal CallSite<Func<CallSite, CodeContext, object, object, object>> PropertyDeleteSite {
  2743. get {
  2744. if (_propDelSite == null) {
  2745. Interlocked.CompareExchange(ref _propDelSite,
  2746. CallSite<Func<CallSite, CodeContext, object, object, object>>.Create(
  2747. InvokeOne
  2748. ),
  2749. null
  2750. );
  2751. }
  2752. return _propDelSite;
  2753. }
  2754. }
  2755. internal CallSite<Func<CallSite, CodeContext, object, object, object, object>> PropertySetSite {
  2756. get {
  2757. if (_propSetSite == null) {
  2758. Interlocked.CompareExchange(ref _propSetSite,
  2759. CallSite<Func<CallSite, CodeContext, object, object, object, object>>.Create(
  2760. Invoke(
  2761. new CallSignature(2)
  2762. )
  2763. ),
  2764. null
  2765. );
  2766. }
  2767. return _propSetSite;
  2768. }
  2769. }
  2770. internal PythonBinder Binder {
  2771. get {
  2772. return _binder;
  2773. }
  2774. }
  2775. private class DefaultPythonComparer : IComparer {
  2776. private CallSite<Func<CallSite, object, object, int>> _site;
  2777. public DefaultPythonComparer(PythonContext context) {
  2778. _site = CallSite<Func<CallSite, object, object, int>>.Create(
  2779. context.Operation(PythonOperationKind.Compare)
  2780. );
  2781. }
  2782. public int Compare(object x, object y) {
  2783. return _site.Target(_site, x, y);
  2784. }
  2785. }
  2786. private class FunctionComparer<T> : IComparer {
  2787. private T _cmpfunc;
  2788. private CallSite<Func<CallSite, CodeContext, T, object, object, int>> _funcSite;
  2789. private CodeContext/*!*/ _context;
  2790. public FunctionComparer(PythonContext/*!*/ context, T cmpfunc)
  2791. : this(context, cmpfunc, MakeCompareSite<T>(context)) {
  2792. }
  2793. public FunctionComparer(PythonContext/*!*/ context, T cmpfunc, CallSite<Func<CallSite, CodeContext, T, object, object, int>> site) {
  2794. _cmpfunc = cmpfunc;
  2795. _context = context.SharedContext;
  2796. _funcSite = site;
  2797. }
  2798. public int Compare(object o1, object o2) {
  2799. return _funcSite.Target(_funcSite, _context, _cmpfunc, o1, o2);
  2800. }
  2801. }
  2802. private static CallSite<Func<CallSite, CodeContext, T, object, object, int>> MakeCompareSite<T>(PythonContext context) {
  2803. return CallSite<Func<CallSite, CodeContext, T, object, object, int>>.Create(
  2804. context.InvokeTwoConvertToInt
  2805. );
  2806. }
  2807. /// <summary>
  2808. /// Gets a function which can be used for comparing two values. If cmp is not null
  2809. /// then the comparison will use the provided comparison function. Otherwise
  2810. /// it will use the normal Python semantics.
  2811. ///
  2812. /// If type is null then a generic comparison function is returned. If type is
  2813. /// not null a comparison function is returned that's used for just that type.
  2814. /// </summary>
  2815. internal IComparer GetComparer(object cmp, Type type) {
  2816. if (type == null) {
  2817. // no type information, return the generic version...
  2818. if (cmp == null) {
  2819. return new DefaultPythonComparer(this);
  2820. } else if (cmp is PythonFunction) {
  2821. return new FunctionComparer<PythonFunction>(this, (PythonFunction)cmp);
  2822. } else if (cmp is BuiltinFunction) {
  2823. return new FunctionComparer<BuiltinFunction>(this, (BuiltinFunction)cmp);
  2824. }
  2825. return new FunctionComparer<object>(this, cmp);
  2826. }
  2827. if (cmp == null) {
  2828. if (_defaultComparer == null) {
  2829. Interlocked.CompareExchange(
  2830. ref _defaultComparer,
  2831. new Dictionary<Type, DefaultPythonComparer>(),
  2832. null
  2833. );
  2834. }
  2835. lock (_defaultComparer) {
  2836. DefaultPythonComparer comparer;
  2837. if (!_defaultComparer.TryGetValue(type, out comparer)) {
  2838. _defaultComparer[type] = comparer = new DefaultPythonComparer(this);
  2839. }
  2840. return comparer;
  2841. }
  2842. } else if (cmp is PythonFunction) {
  2843. if (_sharedPythonFunctionCompareSite == null) {
  2844. _sharedPythonFunctionCompareSite = MakeCompareSite<PythonFunction>(this);
  2845. }
  2846. return new FunctionComparer<PythonFunction>(this, (PythonFunction)cmp, _sharedPythonFunctionCompareSite);
  2847. } else if (cmp is BuiltinFunction) {
  2848. if (_sharedBuiltinFunctionCompareSite == null) {
  2849. _sharedBuiltinFunctionCompareSite = MakeCompareSite<BuiltinFunction>(this);
  2850. }
  2851. return new FunctionComparer<BuiltinFunction>(this, (BuiltinFunction)cmp, _sharedBuiltinFunctionCompareSite);
  2852. }
  2853. if (_sharedFunctionCompareSite == null) {
  2854. _sharedFunctionCompareSite = MakeCompareSite<object>(this);
  2855. }
  2856. return new FunctionComparer<object>(this, cmp, _sharedFunctionCompareSite);
  2857. }
  2858. internal CallSite<Func<CallSite, CodeContext, object, int, object>> GetItemCallSite {
  2859. get {
  2860. if (_getItemCallSite == null) {
  2861. Interlocked.CompareExchange(
  2862. ref _getItemCallSite,
  2863. CallSite<Func<CallSite, CodeContext, object, int, object>>.Create(
  2864. new PythonInvokeBinder(
  2865. this,
  2866. new CallSignature(1)
  2867. )
  2868. ),
  2869. null
  2870. );
  2871. }
  2872. return _getItemCallSite;
  2873. }
  2874. }
  2875. internal CallSite<Func<CallSite, object, object, bool>> GetEqualSite(Type/*!*/ type) {
  2876. if (_equalSites == null) {
  2877. Interlocked.CompareExchange(ref _equalSites, new Dictionary<Type, CallSite<Func<CallSite, object, object, bool>>>(), null);
  2878. }
  2879. CallSite<Func<CallSite, object, object, bool>> res;
  2880. lock (_equalSites) {
  2881. if (!_equalSites.TryGetValue(type, out res)) {
  2882. _equalSites[type] = res = MakeEqualSite();
  2883. }
  2884. }
  2885. return res;
  2886. }
  2887. internal CallSite<Func<CallSite, object, object, bool>> MakeEqualSite() {
  2888. return CreateComparisonSite(ExpressionType.Equal);
  2889. }
  2890. internal static CallSite<Func<CallSite, object, int>> GetHashSite(PythonType/*!*/ type) {
  2891. return type.HashSite;
  2892. }
  2893. internal CallSite<Func<CallSite, object, int>> MakeHashSite() {
  2894. return CallSite<Func<CallSite, object, int>>.Create(
  2895. Operation(
  2896. PythonOperationKind.Hash
  2897. )
  2898. );
  2899. }
  2900. public override IList<string> GetCallSignatures(object obj) {
  2901. if (_getSignaturesSite == null) {
  2902. Interlocked.CompareExchange(
  2903. ref _getSignaturesSite,
  2904. CallSite<Func<CallSite, object, IList<string>>>.Create(
  2905. Operation(PythonOperationKind.CallSignatures)
  2906. ),
  2907. null
  2908. );
  2909. }
  2910. return _getSignaturesSite.Target(_getSignaturesSite, obj);
  2911. }
  2912. /// <summary>
  2913. /// Performs a GC collection including the possibility of freeing weak data structures held onto by the Python runtime.
  2914. /// </summary>
  2915. /// <param name="generation"></param>
  2916. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", MessageId = "System.GC.Collect")]
  2917. internal int Collect(int generation) {
  2918. if (generation > GC.MaxGeneration || generation < 0) {
  2919. throw PythonOps.ValueError("invalid generation {0}", generation);
  2920. }
  2921. // now let the CLR do it's normal collection
  2922. long start = GC.GetTotalMemory(false);
  2923. for (int i = 0; i < 2; i++) {
  2924. #if !SILVERLIGHT // GC.Collect
  2925. GC.Collect(generation);
  2926. #else
  2927. GC.Collect();
  2928. #endif
  2929. GC.WaitForPendingFinalizers();
  2930. if (generation == GC.MaxGeneration) {
  2931. // cleanup any weak data structures which we maintain when
  2932. // we force a collection
  2933. FunctionCode.CleanFunctionCodes(this, true);
  2934. }
  2935. }
  2936. return (int)Math.Max(start - GC.GetTotalMemory(false), 0);
  2937. }
  2938. public DynamicDelegateCreator DelegateCreator {
  2939. get {
  2940. if (_delegateCreator == null) {
  2941. Interlocked.CompareExchange(ref _delegateCreator, new DynamicDelegateCreator(this), null);
  2942. }
  2943. return _delegateCreator;
  2944. }
  2945. }
  2946. #region Binder Factories
  2947. internal CompatibilityInvokeBinder/*!*/ CompatInvoke(CallInfo /*!*/ callInfo) {
  2948. if (_compatInvokeBinders == null) {
  2949. Interlocked.CompareExchange(
  2950. ref _compatInvokeBinders,
  2951. new Dictionary<CallSignature, CompatibilityInvokeBinder>(),
  2952. null
  2953. );
  2954. }
  2955. lock (_compatInvokeBinders) {
  2956. CallSignature sig = BindingHelpers.CallInfoToSignature(callInfo);
  2957. CompatibilityInvokeBinder res;
  2958. if (!_compatInvokeBinders.TryGetValue(sig, out res)) {
  2959. _compatInvokeBinders[sig] = res = new CompatibilityInvokeBinder(this, callInfo);
  2960. }
  2961. return res;
  2962. }
  2963. }
  2964. internal PythonConversionBinder/*!*/ Convert(Type/*!*/ type, ConversionResultKind resultKind) {
  2965. if (_conversionBinders == null) {
  2966. Interlocked.CompareExchange(
  2967. ref _conversionBinders,
  2968. new Dictionary<Type, PythonConversionBinder>[(int)ConversionResultKind.ExplicitTry + 1], // max conversion result kind
  2969. null
  2970. );
  2971. }
  2972. if (_conversionBinders[(int)resultKind] == null) {
  2973. Interlocked.CompareExchange(
  2974. ref _conversionBinders[(int)resultKind],
  2975. new Dictionary<Type, PythonConversionBinder>(),
  2976. null
  2977. );
  2978. }
  2979. Dictionary<Type, PythonConversionBinder> dict = _conversionBinders[(int)resultKind];
  2980. lock (dict) {
  2981. PythonConversionBinder res;
  2982. if (!dict.TryGetValue(type, out res)) {
  2983. dict[type] = res = new PythonConversionBinder(this, type, resultKind);
  2984. }
  2985. return res;
  2986. }
  2987. }
  2988. internal DynamicMetaObjectBinder/*!*/ ConvertRetObject(Type/*!*/ type, ConversionResultKind resultKind) {
  2989. if (_convertRetObjectBinders == null) {
  2990. Interlocked.CompareExchange(
  2991. ref _convertRetObjectBinders,
  2992. new Dictionary<Type, DynamicMetaObjectBinder>[(int)ConversionResultKind.ExplicitTry + 1], // max conversion result kind
  2993. null
  2994. );
  2995. }
  2996. if (_convertRetObjectBinders[(int)resultKind] == null) {
  2997. Interlocked.CompareExchange(
  2998. ref _convertRetObjectBinders[(int)resultKind],
  2999. new Dictionary<Type, DynamicMetaObjectBinder>(),
  3000. null
  3001. );
  3002. }
  3003. Dictionary<Type, DynamicMetaObjectBinder> dict = _convertRetObjectBinders[(int)resultKind];
  3004. lock (dict) {
  3005. DynamicMetaObjectBinder res;
  3006. if (!dict.TryGetValue(type, out res)) {
  3007. dict[type] = res = new PythonConversionBinder(this, type, resultKind, true);
  3008. }
  3009. return res;
  3010. }
  3011. }
  3012. internal CreateFallback/*!*/ Create(CompatibilityInvokeBinder/*!*/ realFallback, CallInfo /*!*/ callInfo) {
  3013. if (_createBinders == null) {
  3014. Interlocked.CompareExchange(
  3015. ref _createBinders,
  3016. new Dictionary<CallSignature, CreateFallback>(),
  3017. null
  3018. );
  3019. }
  3020. lock (_createBinders) {
  3021. CallSignature sig = BindingHelpers.CallInfoToSignature(callInfo);
  3022. CreateFallback res;
  3023. if (!_createBinders.TryGetValue(sig, out res)) {
  3024. _createBinders[sig] = res = new CreateFallback(realFallback, callInfo);
  3025. }
  3026. return res;
  3027. }
  3028. }
  3029. internal PythonGetMemberBinder/*!*/ GetMember(string/*!*/ name) {
  3030. return GetMember(name, false);
  3031. }
  3032. internal PythonGetMemberBinder/*!*/ GetMember(string/*!*/ name, bool isNoThrow) {
  3033. Dictionary<string, PythonGetMemberBinder> dict;
  3034. if (isNoThrow) {
  3035. if (_tryGetMemberBinders == null) {
  3036. Interlocked.CompareExchange(
  3037. ref _tryGetMemberBinders,
  3038. new Dictionary<string, PythonGetMemberBinder>(),
  3039. null
  3040. );
  3041. }
  3042. dict = _tryGetMemberBinders;
  3043. } else {
  3044. if (_getMemberBinders == null) {
  3045. Interlocked.CompareExchange(
  3046. ref _getMemberBinders,
  3047. new Dictionary<string, PythonGetMemberBinder>(),
  3048. null
  3049. );
  3050. }
  3051. dict = _getMemberBinders;
  3052. }
  3053. lock (dict) {
  3054. PythonGetMemberBinder res;
  3055. if (!dict.TryGetValue(name, out res)) {
  3056. dict[name] = res = new PythonGetMemberBinder(this, name, isNoThrow);
  3057. }
  3058. return res;
  3059. }
  3060. }
  3061. internal CompatibilityGetMember/*!*/ CompatGetMember(string/*!*/ name, bool isNoThrow) {
  3062. Dictionary<string, CompatibilityGetMember> dict;
  3063. if (isNoThrow) {
  3064. if (_compatGetMemberNoThrow == null) {
  3065. Interlocked.CompareExchange(
  3066. ref _compatGetMemberNoThrow,
  3067. new Dictionary<string, CompatibilityGetMember>(),
  3068. null
  3069. );
  3070. }
  3071. dict = _compatGetMemberNoThrow;
  3072. } else {
  3073. if (_compatGetMember == null) {
  3074. Interlocked.CompareExchange(
  3075. ref _compatGetMember,
  3076. new Dictionary<string, CompatibilityGetMember>(),
  3077. null
  3078. );
  3079. }
  3080. dict = _compatGetMember;
  3081. }
  3082. lock (dict) {
  3083. CompatibilityGetMember res;
  3084. if (!dict.TryGetValue(name, out res)) {
  3085. dict[name] = res = new CompatibilityGetMember(this, name, isNoThrow);
  3086. }
  3087. return res;
  3088. }
  3089. }
  3090. internal PythonSetMemberBinder/*!*/ SetMember(string/*!*/ name) {
  3091. if (_setMemberBinders == null) {
  3092. Interlocked.CompareExchange(
  3093. ref _setMemberBinders,
  3094. new Dictionary<string, PythonSetMemberBinder>(),
  3095. null
  3096. );
  3097. }
  3098. lock (_setMemberBinders) {
  3099. PythonSetMemberBinder res;
  3100. if (!_setMemberBinders.TryGetValue(name, out res)) {
  3101. _setMemberBinders[name] = res = new PythonSetMemberBinder(this, name);
  3102. }
  3103. return res;
  3104. }
  3105. }
  3106. internal PythonDeleteMemberBinder/*!*/ DeleteMember(string/*!*/ name) {
  3107. if (_deleteMemberBinders == null) {
  3108. Interlocked.CompareExchange(
  3109. ref _deleteMemberBinders,
  3110. new Dictionary<string, PythonDeleteMemberBinder>(),
  3111. null
  3112. );
  3113. }
  3114. lock (_deleteMemberBinders) {
  3115. PythonDeleteMemberBinder res;
  3116. if (!_deleteMemberBinders.TryGetValue(name, out res)) {
  3117. _deleteMemberBinders[name] = res = new PythonDeleteMemberBinder(this, name);
  3118. }
  3119. return res;
  3120. }
  3121. }
  3122. internal PythonInvokeBinder/*!*/ Invoke(CallSignature signature) {
  3123. if (_invokeBinders == null) {
  3124. Interlocked.CompareExchange(
  3125. ref _invokeBinders,
  3126. new Dictionary<CallSignature, PythonInvokeBinder>(),
  3127. null
  3128. );
  3129. }
  3130. lock (_invokeBinders) {
  3131. PythonInvokeBinder res;
  3132. if (!_invokeBinders.TryGetValue(signature, out res)) {
  3133. _invokeBinders[signature] = res = new PythonInvokeBinder(this, signature);
  3134. }
  3135. return res;
  3136. }
  3137. }
  3138. internal PythonInvokeBinder/*!*/ InvokeNone {
  3139. get {
  3140. if (_invokeNoArgs == null) {
  3141. _invokeNoArgs = Invoke(new CallSignature(0));
  3142. }
  3143. return _invokeNoArgs;
  3144. }
  3145. }
  3146. internal PythonInvokeBinder/*!*/ InvokeOne {
  3147. get {
  3148. if (_invokeOneArg == null) {
  3149. _invokeOneArg = Invoke(new CallSignature(1));
  3150. }
  3151. return _invokeOneArg;
  3152. }
  3153. }
  3154. internal DynamicMetaObjectBinder/*!*/ InvokeTwoConvertToInt {
  3155. get {
  3156. if (_invokeTwoConvertToInt == null) {
  3157. // +2 for the target object and CodeContext which InvokeBinder recevies
  3158. const int argCount = 2;
  3159. ParameterMappingInfo[] args = new ParameterMappingInfo[argCount + 2];
  3160. for (int i = 0; i < argCount + 2; i++) {
  3161. args[i] = ParameterMappingInfo.Parameter(i);
  3162. }
  3163. _invokeTwoConvertToInt = new ComboBinder(
  3164. new BinderMappingInfo(
  3165. Invoke(new CallSignature(2)),
  3166. args
  3167. ),
  3168. new BinderMappingInfo(
  3169. Convert(typeof(int), ConversionResultKind.ExplicitCast),
  3170. ParameterMappingInfo.Action(0)
  3171. )
  3172. );
  3173. }
  3174. return _invokeTwoConvertToInt;
  3175. }
  3176. }
  3177. internal PythonOperationBinder/*!*/ Operation(PythonOperationKind operation) {
  3178. if (_operationBinders == null) {
  3179. Interlocked.CompareExchange(
  3180. ref _operationBinders,
  3181. new Dictionary<PythonOperationKind, PythonOperationBinder>(),
  3182. null
  3183. );
  3184. }
  3185. lock (_operationBinders) {
  3186. PythonOperationBinder res;
  3187. if (!_operationBinders.TryGetValue(operation, out res)) {
  3188. _operationBinders[operation] = res = new PythonOperationBinder(this, operation);
  3189. }
  3190. return res;
  3191. }
  3192. }
  3193. internal PythonUnaryOperationBinder/*!*/ UnaryOperation(ExpressionType operation) {
  3194. if (_unaryBinders == null) {
  3195. Interlocked.CompareExchange(
  3196. ref _unaryBinders,
  3197. new Dictionary<ExpressionType, PythonUnaryOperationBinder>(),
  3198. null
  3199. );
  3200. }
  3201. lock (_unaryBinders) {
  3202. PythonUnaryOperationBinder res;
  3203. if (!_unaryBinders.TryGetValue(operation, out res)) {
  3204. _unaryBinders[operation] = res = new PythonUnaryOperationBinder(this, operation);
  3205. }
  3206. return res;
  3207. }
  3208. }
  3209. internal PythonBinaryOperationBinder/*!*/ BinaryOperation(ExpressionType operation) {
  3210. if (_binaryBinders == null) {
  3211. Interlocked.CompareExchange(
  3212. ref _binaryBinders,
  3213. new PythonBinaryOperationBinder[(int)ExpressionType.IsFalse + 1],
  3214. null
  3215. );
  3216. }
  3217. var ret = _binaryBinders[(int)operation];
  3218. if (ret != null) {
  3219. return ret;
  3220. }
  3221. var oldValue = Interlocked.CompareExchange(
  3222. ref _binaryBinders[(int)operation],
  3223. ret = new PythonBinaryOperationBinder(this, operation),
  3224. null
  3225. );
  3226. return oldValue ?? ret;
  3227. }
  3228. internal BinaryRetTypeBinder/*!*/ BinaryOperationRetType(PythonBinaryOperationBinder opBinder, PythonConversionBinder convBinder) {
  3229. if (_binaryRetTypeBinders == null) {
  3230. Interlocked.CompareExchange(
  3231. ref _binaryRetTypeBinders,
  3232. new Dictionary<OperationRetTypeKey<ExpressionType>, BinaryRetTypeBinder>(),
  3233. null
  3234. );
  3235. }
  3236. lock (_binaryRetTypeBinders) {
  3237. BinaryRetTypeBinder res;
  3238. OperationRetTypeKey<ExpressionType> key = new OperationRetTypeKey<ExpressionType>(convBinder.Type, opBinder.Operation);
  3239. if (!_binaryRetTypeBinders.TryGetValue(key, out res)) {
  3240. _binaryRetTypeBinders[key] = res = new BinaryRetTypeBinder(opBinder, convBinder);
  3241. }
  3242. return res;
  3243. }
  3244. }
  3245. internal BinaryRetTypeBinder/*!*/ OperationRetType(PythonOperationBinder opBinder, PythonConversionBinder convBinder) {
  3246. if (_operationRetTypeBinders == null) {
  3247. Interlocked.CompareExchange(
  3248. ref _operationRetTypeBinders,
  3249. new Dictionary<OperationRetTypeKey<PythonOperationKind>, BinaryRetTypeBinder>(),
  3250. null
  3251. );
  3252. }
  3253. lock (_operationRetTypeBinders) {
  3254. BinaryRetTypeBinder res;
  3255. OperationRetTypeKey<PythonOperationKind> key = new OperationRetTypeKey<PythonOperationKind>(convBinder.Type, opBinder.Operation);
  3256. if (!_operationRetTypeBinders.TryGetValue(key, out res)) {
  3257. _operationRetTypeBinders[key] = res = new BinaryRetTypeBinder(opBinder, convBinder);
  3258. }
  3259. return res;
  3260. }
  3261. }
  3262. internal PythonGetIndexBinder/*!*/ GetIndex(int argCount) {
  3263. if (_getIndexBinders == null) {
  3264. Interlocked.CompareExchange(ref _getIndexBinders, new PythonGetIndexBinder[argCount + 1], null);
  3265. }
  3266. lock (this) {
  3267. if (_getIndexBinders.Length <= argCount) {
  3268. Array.Resize(ref _getIndexBinders, argCount + 1);
  3269. }
  3270. if (_getIndexBinders[argCount] == null) {
  3271. _getIndexBinders[argCount] = new PythonGetIndexBinder(this, argCount);
  3272. }
  3273. return _getIndexBinders[argCount];
  3274. }
  3275. }
  3276. internal PythonSetIndexBinder/*!*/ SetIndex(int argCount) {
  3277. if (_setIndexBinders == null) {
  3278. Interlocked.CompareExchange(ref _setIndexBinders, new PythonSetIndexBinder[argCount + 1], null);
  3279. }
  3280. lock (this) {
  3281. if (_setIndexBinders.Length <= argCount) {
  3282. Array.Resize(ref _setIndexBinders, argCount + 1);
  3283. }
  3284. if (_setIndexBinders[argCount] == null) {
  3285. _setIndexBinders[argCount] = new PythonSetIndexBinder(this, argCount);
  3286. }
  3287. return _setIndexBinders[argCount];
  3288. }
  3289. }
  3290. internal PythonDeleteIndexBinder/*!*/ DeleteIndex(int argCount) {
  3291. if (_deleteIndexBinders == null) {
  3292. Interlocked.CompareExchange(ref _deleteIndexBinders, new PythonDeleteIndexBinder[argCount + 1], null);
  3293. }
  3294. lock (this) {
  3295. if (_deleteIndexBinders.Length <= argCount) {
  3296. Array.Resize(ref _deleteIndexBinders, argCount + 1);
  3297. }
  3298. if (_deleteIndexBinders[argCount] == null) {
  3299. _deleteIndexBinders[argCount] = new PythonDeleteIndexBinder(this, argCount);
  3300. }
  3301. return _deleteIndexBinders[argCount];
  3302. }
  3303. }
  3304. internal PythonGetSliceBinder/*!*/ GetSlice {
  3305. get {
  3306. if (_getSlice == null) {
  3307. Interlocked.CompareExchange(ref _getSlice, new PythonGetSliceBinder(this), null);
  3308. }
  3309. return _getSlice;
  3310. }
  3311. }
  3312. internal PythonSetSliceBinder/*!*/ SetSliceBinder {
  3313. get {
  3314. if (_setSlice == null) {
  3315. Interlocked.CompareExchange(ref _setSlice, new PythonSetSliceBinder(this), null);
  3316. }
  3317. return _setSlice;
  3318. }
  3319. }
  3320. internal PythonDeleteSliceBinder/*!*/ DeleteSlice {
  3321. get {
  3322. if (_deleteSlice == null) {
  3323. Interlocked.CompareExchange(ref _deleteSlice, new PythonDeleteSliceBinder(this), null);
  3324. }
  3325. return _deleteSlice;
  3326. }
  3327. }
  3328. class OperationRetTypeKey<T> : IEquatable<OperationRetTypeKey<T>> {
  3329. public readonly Type ReturnType;
  3330. public readonly T Operation;
  3331. public OperationRetTypeKey(Type retType, T operation) {
  3332. ReturnType = retType;
  3333. Operation = operation;
  3334. }
  3335. #region IEquatable<BinaryOperationRetTypeKey> Members
  3336. public bool Equals(OperationRetTypeKey<T> other) {
  3337. return other.ReturnType == ReturnType && other.Operation.Equals(Operation);
  3338. }
  3339. #endregion
  3340. public override int GetHashCode() {
  3341. return ReturnType.GetHashCode() ^ Operation.GetHashCode();
  3342. }
  3343. public override bool Equals(object obj) {
  3344. OperationRetTypeKey<T> other = obj as OperationRetTypeKey<T>;
  3345. if (other != null) {
  3346. return Equals(other);
  3347. }
  3348. return false;
  3349. }
  3350. }
  3351. /// <summary>
  3352. /// Gets a PythonContext given a DynamicMetaObjectBinder.
  3353. /// </summary>
  3354. public static PythonContext/*!*/ GetPythonContext(DynamicMetaObjectBinder/*!*/ action) {
  3355. IPythonSite pySite = action as IPythonSite;
  3356. if (pySite != null) {
  3357. return pySite.Context;
  3358. }
  3359. return DefaultContext.DefaultPythonContext;
  3360. }
  3361. public static Expression/*!*/ GetCodeContext(DynamicMetaObjectBinder/*!*/ action) {
  3362. return Microsoft.Scripting.Ast.Utils.Constant(PythonContext.GetPythonContext(action)._defaultContext);
  3363. }
  3364. public static DynamicMetaObject/*!*/ GetCodeContextMO(DynamicMetaObjectBinder/*!*/ action) {
  3365. return new DynamicMetaObject(
  3366. Microsoft.Scripting.Ast.Utils.Constant(PythonContext.GetPythonContext(action)._defaultContext),
  3367. BindingRestrictions.Empty,
  3368. PythonContext.GetPythonContext(action)._defaultContext
  3369. );
  3370. }
  3371. public static DynamicMetaObject/*!*/ GetCodeContextMOCls(DynamicMetaObjectBinder/*!*/ action) {
  3372. return new DynamicMetaObject(
  3373. Microsoft.Scripting.Ast.Utils.Constant(PythonContext.GetPythonContext(action).SharedClsContext),
  3374. BindingRestrictions.Empty,
  3375. PythonContext.GetPythonContext(action).SharedClsContext
  3376. );
  3377. }
  3378. #endregion
  3379. #region Scope Access
  3380. public override T ScopeGetVariable<T>(Scope scope, string name) {
  3381. var storage = scope.Storage as ScopeStorage;
  3382. object res;
  3383. if (storage != null && storage.TryGetValue(name, false, out res)) {
  3384. return Operations.ConvertTo<T>(res);
  3385. }
  3386. StringDictionaryExpando dictStorage = scope.Storage as StringDictionaryExpando;
  3387. if (dictStorage != null && dictStorage.Dictionary.TryGetValue(name, out res)) {
  3388. return Operations.ConvertTo<T>(res);
  3389. }
  3390. return base.ScopeGetVariable<T>(scope, name);
  3391. }
  3392. public override dynamic ScopeGetVariable(Scope scope, string name) {
  3393. var storage = scope.Storage as ScopeStorage;
  3394. object res;
  3395. if (storage != null && storage.TryGetValue(name, false, out res)) {
  3396. return res;
  3397. }
  3398. StringDictionaryExpando dictStorage = scope.Storage as StringDictionaryExpando;
  3399. if (dictStorage != null && dictStorage.Dictionary.TryGetValue(name, out res)) {
  3400. return res;
  3401. }
  3402. return base.ScopeGetVariable(scope, name);
  3403. }
  3404. public override void ScopeSetVariable(Scope scope, string name, object value) {
  3405. var storage = scope.Storage as ScopeStorage;
  3406. if (storage != null) {
  3407. storage.SetValue(name, false, value);
  3408. return;
  3409. }
  3410. StringDictionaryExpando dictStorage = scope.Storage as StringDictionaryExpando;
  3411. if (dictStorage != null) {
  3412. dictStorage.Dictionary[name] = value;
  3413. return;
  3414. }
  3415. base.ScopeSetVariable(scope, name, value);
  3416. }
  3417. public override bool ScopeTryGetVariable(Scope scope, string name, out dynamic value) {
  3418. var storage = scope.Storage as ScopeStorage;
  3419. if (storage != null && storage.TryGetValue(name, false, out value)) {
  3420. return true;
  3421. }
  3422. StringDictionaryExpando dictStorage = scope.Storage as StringDictionaryExpando;
  3423. if (dictStorage != null && dictStorage.Dictionary.TryGetValue(name, out value)) {
  3424. return true;
  3425. }
  3426. return base.ScopeTryGetVariable(scope, name, out value);
  3427. }
  3428. #endregion
  3429. #region Tracing
  3430. internal DebugContext DebugContext {
  3431. get {
  3432. EnsureDebugContext();
  3433. return _debugContext;
  3434. }
  3435. }
  3436. private void EnsureDebugContext() {
  3437. if (_debugContext == null) {
  3438. lock(this) {
  3439. if (_debugContext == null) {
  3440. try {
  3441. _debugContext = DebugContext.CreateInstance();
  3442. _tracePipeline = Debugging.TracePipeline.CreateInstance(_debugContext);
  3443. _tracePipeline.TraceCallback = new PythonTracebackListenersDispatcher(this);
  3444. } catch {
  3445. _debugContext = null;
  3446. _tracePipeline = null;
  3447. throw;
  3448. }
  3449. }
  3450. }
  3451. }
  3452. }
  3453. private class PythonTracebackListenersDispatcher : Debugging.ITraceCallback {
  3454. private readonly PythonContext _parent;
  3455. public PythonTracebackListenersDispatcher(PythonContext parent) {
  3456. _parent = parent;
  3457. }
  3458. void Debugging.ITraceCallback.OnTraceEvent(Debugging.TraceEventKind kind, string name, string sourceFileName, SourceSpan sourceSpan, Func<IDictionary<object, object>> scopeCallback, object payload, object customPayload)
  3459. {
  3460. var listener = _parent._tracebackListeners.Value;
  3461. if (listener == null && _parent.PythonOptions.Tracing) {
  3462. // If tracing without sys.set_trace() is enabled, we need to register a dummy traceback listener,
  3463. // because of the FunctionStack handling done there.
  3464. _parent._tracebackListeners.Value = listener = new PythonTracebackListener(_parent, null);
  3465. }
  3466. if (listener != null)
  3467. listener.OnTraceEvent(kind, name, sourceFileName, sourceSpan, scopeCallback, payload, customPayload);
  3468. }
  3469. }
  3470. internal Debugging.ITracePipeline TracePipeline {
  3471. get {
  3472. return _tracePipeline;
  3473. }
  3474. }
  3475. internal void SetTrace(object o) {
  3476. if (o == null && _debugContext == null)
  3477. return;
  3478. EnsureDebugContext();
  3479. // thread-local
  3480. var oldTraceListener = _tracebackListeners.Value;
  3481. var newTraceListener = oldTraceListener;
  3482. if (o == null) {
  3483. _tracebackListeners.Value = newTraceListener = null;
  3484. } else {
  3485. // We're following CPython behavior here.
  3486. // If CurrentPythonFrame is not null then we're currently inside a traceback, and
  3487. // enabling trace while inside a traceback is only allowed through sys.call_tracing()
  3488. var pyThread = PythonOps.GetFunctionStackNoCreate();
  3489. if (pyThread == null || (oldTraceListener == null || !oldTraceListener.InTraceBack)) {
  3490. _tracebackListeners.Value = newTraceListener = new PythonTracebackListener(this, o);
  3491. }
  3492. }
  3493. // global
  3494. lock (_codeUpdateLock)
  3495. {
  3496. var oldEnableTracing = EnableTracing;
  3497. if ((oldTraceListener != null) != (newTraceListener != null)) {
  3498. _tracebackListenersCount += (newTraceListener != null) ? 1 : -1;
  3499. }
  3500. if (EnableTracing != oldEnableTracing) {
  3501. // DebugContext invocation has changed, we need to update all of our
  3502. // function codes.
  3503. FunctionCode.UpdateAllCode(this);
  3504. }
  3505. }
  3506. }
  3507. internal object CallTracing(object func, PythonTuple args) {
  3508. // The CPython implementation basically only stores/restores the
  3509. // nesting level and the recursion control (e.g. that the trace handler
  3510. // is not called from inside of the trace handler)
  3511. var tblistener = (_debugContext != null) ? _tracebackListeners.Value : null;
  3512. var backupInTraceBack = (tblistener != null) ? tblistener.InTraceBack : false;
  3513. if (tblistener != null && backupInTraceBack)
  3514. tblistener.InTraceBack = false;
  3515. try {
  3516. return PythonCalls.Call(func, args.ToArray());
  3517. } finally {
  3518. if (tblistener != null)
  3519. tblistener.InTraceBack = backupInTraceBack;
  3520. }
  3521. }
  3522. internal object GetTrace()
  3523. {
  3524. if (_debugContext == null)
  3525. return null;
  3526. var listener = _tracebackListeners.Value;
  3527. if (listener == null)
  3528. return null;
  3529. return listener.TraceObject;
  3530. }
  3531. #endregion
  3532. internal ExtensionMethodSet UniqifyExtensions(ExtensionMethodSet newSet) {
  3533. int deadIndex = -1;
  3534. // we shouldn't have tons of different sets so we just run through the list of possible sets...
  3535. if (_weakExtensionMethodSets == null) {
  3536. Interlocked.CompareExchange(ref _weakExtensionMethodSets, new List<WeakReference>(), null);
  3537. }
  3538. lock (_weakExtensionMethodSets) {
  3539. for (int i = 0; i < _weakExtensionMethodSets.Count; i++) {
  3540. var weakSet = _weakExtensionMethodSets[i];
  3541. var set = (ExtensionMethodSet)weakSet.Target;
  3542. if (set != null) {
  3543. if (set == newSet) {
  3544. return set;
  3545. }
  3546. } else {
  3547. deadIndex = i;
  3548. }
  3549. }
  3550. if (deadIndex == -1) {
  3551. _weakExtensionMethodSets.Add(new WeakReference(newSet));
  3552. } else {
  3553. _weakExtensionMethodSets[deadIndex].Target = newSet;
  3554. }
  3555. return newSet;
  3556. }
  3557. }
  3558. }
  3559. public static class PythonContextHelpers {
  3560. public static PythonContext GetPythonContext(this CodeContext context) {
  3561. return PythonContext.GetContext(context);
  3562. }
  3563. }
  3564. /// <summary>
  3565. /// List of unary operators which we have sites for to enable fast dispatch that
  3566. /// doesn't collide with other operators.
  3567. /// </summary>
  3568. enum UnaryOperators {
  3569. Repr,
  3570. Length,
  3571. Hash,
  3572. String,
  3573. Maximum
  3574. }
  3575. enum TernaryOperators {
  3576. SetDescriptor,
  3577. GetDescriptor,
  3578. Maximum
  3579. }
  3580. }