PageRenderTime 49ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

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

https://bitbucket.org/mdavid/dlr
C# | 1155 lines | 882 code | 188 blank | 85 comment | 154 complexity | ef3f5d0851572002838bfc90605c47ec MD5 | raw file
  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 !CLR2
  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.Reflection;
  29. using System.Runtime.CompilerServices;
  30. using System.Security;
  31. using System.Text;
  32. using System.Text.RegularExpressions;
  33. using System.Threading;
  34. using Microsoft.Scripting;
  35. using Microsoft.Scripting.Actions;
  36. using Microsoft.Scripting.Generation;
  37. using Microsoft.Scripting.Runtime;
  38. using Microsoft.Scripting.Utils;
  39. using IronPython.Compiler;
  40. using IronPython.Hosting;
  41. using IronPython.Modules;
  42. using IronPython.Runtime.Binding;
  43. using IronPython.Runtime.Exceptions;
  44. using IronPython.Runtime.Operations;
  45. using IronPython.Runtime.Types;
  46. using Debugging = Microsoft.Scripting.Debugging;
  47. using PyAst = IronPython.Compiler.Ast;
  48. namespace IronPython.Runtime {
  49. public delegate int HashDelegate(object o, ref HashDelegate dlg);
  50. public sealed partial class PythonContext : LanguageContext {
  51. internal const string/*!*/ IronPythonDisplayName = "IronPython 2.7 Alpha 1";
  52. internal const string/*!*/ IronPythonNames = "IronPython;Python;py";
  53. internal const string/*!*/ IronPythonFileExtensions = ".py";
  54. private static readonly Guid PythonLanguageGuid = new Guid("03ed4b80-d10b-442f-ad9a-47dae85b2051");
  55. private static readonly Guid LanguageVendor_Microsoft = new Guid(-1723120188, -6423, 0x11d2, 0x90, 0x3f, 0, 0xc0, 0x4f, 0xa3, 2, 0xa1);
  56. // fields used during startup
  57. private readonly IDictionary<object, object>/*!*/ _modulesDict = new PythonDictionary();
  58. private readonly Dictionary<string, ModuleGlobalCache>/*!*/ _builtinCache = new Dictionary<string, ModuleGlobalCache>(StringComparer.Ordinal);
  59. private readonly Dictionary<Type, string>/*!*/ _builtinModuleNames = new Dictionary<Type, string>();
  60. private readonly PythonOptions/*!*/ _options;
  61. private readonly PythonModule/*!*/ _systemState;
  62. private readonly Dictionary<string, Type>/*!*/ _builtinModulesDict;
  63. private readonly PythonOverloadResolverFactory _sharedOverloadResolverFactory;
  64. private readonly PythonBinder _binder;
  65. private readonly SysModuleDictionaryStorage _sysDict = new SysModuleDictionaryStorage();
  66. #if !SILVERLIGHT
  67. private readonly AssemblyResolveHolder _resolveHolder;
  68. #if !CLR2
  69. private readonly HashSet<Assembly> _loadedAssemblies = new HashSet<Assembly>();
  70. #endif
  71. #endif
  72. private Encoding _defaultEncoding = PythonAsciiEncoding.Instance;
  73. // conditional variables for silverlight/desktop CLR features
  74. private Hosting.PythonService _pythonService;
  75. private string _initialExecutable, _initialPrefix = GetInitialPrefix();
  76. // other fields which might only be conditionally used
  77. private string _initialVersionString;
  78. private PythonModule _clrModule;
  79. private PythonDictionary _builtinDict;
  80. private PythonModule _builtins;
  81. private PythonFileManager _fileManager;
  82. private Dictionary<string, object> _errorHandlers;
  83. private List<object> _searchFunctions;
  84. private Dictionary<object, object> _moduleState;
  85. /// <summary> stored for copy_reg module, used for reduce protocol </summary>
  86. internal BuiltinFunction NewObject;
  87. /// <summary> stored for copy_reg module, used for reduce protocol </summary>
  88. internal BuiltinFunction PythonReconstructor;
  89. private Dictionary<Type, object> _genericSiteStorage;
  90. private CallSite<Func<CallSite, CodeContext, object, object>>[] _newUnarySites;
  91. private CallSite<Func<CallSite, CodeContext, object, object, object, object>>[] _newTernarySites;
  92. private CallSite<Func<CallSite, object, object, int>> _compareSite;
  93. private Dictionary<AttrKey, CallSite<Func<CallSite, object, object, object>>> _setAttrSites;
  94. private Dictionary<AttrKey, CallSite<Action<CallSite, object>>> _deleteAttrSites;
  95. private CallSite<Func<CallSite, CodeContext, object, string, PythonTuple, PythonDictionary, object>> _metaClassSite;
  96. private CallSite<Func<CallSite, CodeContext, object, string, object>> _writeSite;
  97. private CallSite<Func<CallSite, object, object, object>> _getIndexSite, _equalSite;
  98. private CallSite<Action<CallSite, object, object>> _delIndexSite;
  99. private CallSite<Func<CallSite, CodeContext, object, object>> _finalizerSite;
  100. private CallSite<Func<CallSite, CodeContext, PythonFunction, object>> _functionCallSite;
  101. private CallSite<Func<CallSite, object, object, bool>> _greaterThanSite, _lessThanSite, _greaterThanEqualSite, _lessThanEqualSite, _containsSite;
  102. private CallSite<Func<CallSite, CodeContext, object, object[], object>> _callSplatSite;
  103. private CallSite<Func<CallSite, CodeContext, object, object[], IDictionary<object, object>, object>> _callDictSite;
  104. private CallSite<Func<CallSite, CodeContext, object, object, object, object>> _callDictSiteLooselyTyped;
  105. private CallSite<Func<CallSite, CodeContext, object, string, PythonDictionary, PythonDictionary, PythonTuple, int, object>> _importSite;
  106. private CallSite<Func<CallSite, CodeContext, object, string, PythonDictionary, PythonDictionary, PythonTuple, object>> _oldImportSite;
  107. private CallSite<Func<CallSite, object, bool>> _isCallableSite;
  108. private CallSite<Func<CallSite, object, IList<string>>> _getSignaturesSite;
  109. private CallSite<Func<CallSite, object, object, object>> _addSite, _divModSite, _rdivModSite;
  110. private CallSite<Func<CallSite, object, object, object, object>> _setIndexSite, _delSliceSite;
  111. private CallSite<Func<CallSite, object, object, object, object, object>> _setSliceSite;
  112. private CallSite<Func<CallSite, object, string>> _docSite;
  113. // conversion sites
  114. private CallSite<Func<CallSite, object, int>> _intSite;
  115. private CallSite<Func<CallSite, object, string>> _tryStringSite;
  116. private CallSite<Func<CallSite, object, object>> _tryIntSite;
  117. private CallSite<Func<CallSite, object, IEnumerable>> _tryIEnumerableSite;
  118. private Dictionary<Type, CallSite<Func<CallSite, object, object>>> _implicitConvertSites;
  119. private Dictionary<PythonOperationKind, CallSite<Func<CallSite, object, object, object>>> _binarySites;
  120. private Dictionary<Type, DefaultPythonComparer> _defaultComparer;
  121. private CallSite<Func<CallSite, CodeContext, object, object, object, int>> _sharedFunctionCompareSite;
  122. private CallSite<Func<CallSite, CodeContext, PythonFunction, object, object, int>> _sharedPythonFunctionCompareSite;
  123. private CallSite<Func<CallSite, CodeContext, BuiltinFunction, object, object, int>> _sharedBuiltinFunctionCompareSite;
  124. private CallSite<Func<CallSite, CodeContext, object, int, object>> _getItemCallSite;
  125. private CallSite<Func<CallSite, CodeContext, object, object, object>> _propGetSite, _propDelSite;
  126. private CallSite<Func<CallSite, CodeContext, object, object, object, object>> _propSetSite;
  127. private CompiledLoader _compiledLoader;
  128. internal bool _importWarningThrows;
  129. private bool _importedEncodings;
  130. private Action<Action> _commandDispatcher; // can be null
  131. private ClrModule.ReferencesList _referencesList;
  132. private FloatFormat _floatFormat, _doubleFormat;
  133. private CultureInfo _collateCulture, _ctypeCulture, _timeCulture, _monetaryCulture, _numericCulture;
  134. private CodeContext _defaultContext, _defaultClsContext;
  135. private readonly TopNamespaceTracker _topNamespace;
  136. private readonly IEqualityComparer<object> _equalityComparer;
  137. private readonly IEqualityComparer _equalityComparerNonGeneric;
  138. private Dictionary<Type, CallSite<Func<CallSite, object, object, bool>>> _equalSites;
  139. private Dictionary<Type, PythonSiteCache> _systemSiteCache;
  140. internal static object _syntaxErrorNoCaret = new object();
  141. // atomized binders
  142. private PythonInvokeBinder _invokeNoArgs, _invokeOneArg;
  143. private Dictionary<CallSignature, PythonInvokeBinder/*!*/> _invokeBinders;
  144. private Dictionary<string/*!*/, PythonGetMemberBinder/*!*/> _getMemberBinders;
  145. private Dictionary<string/*!*/, PythonGetMemberBinder/*!*/> _tryGetMemberBinders;
  146. private Dictionary<string/*!*/, PythonSetMemberBinder/*!*/> _setMemberBinders;
  147. private Dictionary<string/*!*/, PythonDeleteMemberBinder/*!*/> _deleteMemberBinders;
  148. private Dictionary<string/*!*/, CompatibilityGetMember/*!*/> _compatGetMember;
  149. private Dictionary<string/*!*/, CompatibilityGetMember/*!*/> _compatGetMemberNoThrow;
  150. private Dictionary<PythonOperationKind, PythonOperationBinder/*!*/> _operationBinders;
  151. private Dictionary<ExpressionType, PythonUnaryOperationBinder/*!*/> _unaryBinders;
  152. private PythonBinaryOperationBinder[] _binaryBinders;
  153. private Dictionary<OperationRetTypeKey<ExpressionType>, BinaryRetTypeBinder/*!*/> _binaryRetTypeBinders;
  154. private Dictionary<OperationRetTypeKey<PythonOperationKind>, BinaryRetTypeBinder/*!*/> _operationRetTypeBinders;
  155. private Dictionary<Type/*!*/, PythonConversionBinder/*!*/>[] _conversionBinders;
  156. private Dictionary<Type/*!*/, DynamicMetaObjectBinder/*!*/>[] _convertRetObjectBinders;
  157. private Dictionary<CallSignature, CreateFallback/*!*/> _createBinders;
  158. private Dictionary<CallSignature, CompatibilityInvokeBinder/*!*/> _compatInvokeBinders;
  159. private PythonGetSliceBinder _getSlice;
  160. private PythonSetSliceBinder _setSlice;
  161. private PythonDeleteSliceBinder _deleteSlice;
  162. private PythonGetIndexBinder[] _getIndexBinders;
  163. private PythonSetIndexBinder[] _setIndexBinders;
  164. private PythonDeleteIndexBinder[] _deleteIndexBinders;
  165. private DynamicMetaObjectBinder _invokeTwoConvertToInt;
  166. private static CultureInfo _CCulture;
  167. private DynamicDelegateCreator _delegateCreator;
  168. // tracing / in-proc debugging support
  169. private Debugging.CompilerServices.DebugContext _debugContext;
  170. private Debugging.ITracePipeline _tracePipeline;
  171. [ThreadStatic]
  172. private static Stack<PythonTracebackListener> _tracebackListeners;
  173. private static int _tracingThreads;
  174. internal FunctionCode.CodeList _allCodes;
  175. internal readonly object _codeCleanupLock = new object(), _codeUpdateLock = new object();
  176. internal int _codeCount, _nextCodeCleanup = 200;
  177. private int _recursionLimit;
  178. [ThreadStatic]
  179. private static bool _enableTracing;
  180. internal readonly List<FunctionStack> _mainThreadFunctionStack;
  181. private CallSite<Func<CallSite, CodeContext, object, object>> _callSite0LightEh;
  182. #region Generated Python Shared Call Sites Storage
  183. // *** BEGIN GENERATED CODE ***
  184. // generated by function: gen_shared_call_sites_storage from: generate_calls.py
  185. private CallSite<Func<CallSite, CodeContext, object, object>> _callSite0;
  186. private CallSite<Func<CallSite, CodeContext, object, object, object>> _callSite1;
  187. private CallSite<Func<CallSite, CodeContext, object, object, object, object>> _callSite2;
  188. private CallSite<Func<CallSite, CodeContext, object, object, object, object, object>> _callSite3;
  189. private CallSite<Func<CallSite, CodeContext, object, object, object, object, object, object>> _callSite4;
  190. private CallSite<Func<CallSite, CodeContext, object, object, object, object, object, object, object>> _callSite5;
  191. private CallSite<Func<CallSite, CodeContext, object, object, object, object, object, object, object, object>> _callSite6;
  192. // *** END GENERATED CODE ***
  193. #endregion
  194. /// <summary>
  195. /// Creates a new PythonContext not bound to Engine.
  196. /// </summary>
  197. public PythonContext(ScriptDomainManager/*!*/ manager, IDictionary<string, object> options)
  198. : base(manager) {
  199. _options = new PythonOptions(options);
  200. _builtinModulesDict = CreateBuiltinTable();
  201. PythonDictionary defaultScope = new PythonDictionary();
  202. ModuleContext modContext = new ModuleContext(defaultScope, this);
  203. _defaultContext = modContext.GlobalContext;
  204. PythonDictionary sysDict = new PythonDictionary(_sysDict);
  205. _systemState = new PythonModule(sysDict);
  206. _systemState.__dict__["__name__"] = "sys";
  207. _systemState.__dict__["__package__"] = null;
  208. PythonBinder binder = new PythonBinder(this, _defaultContext);
  209. _sharedOverloadResolverFactory = new PythonOverloadResolverFactory(binder, Expression.Constant(_defaultContext));
  210. _binder = binder;
  211. CodeContext defaultClsContext = DefaultContext.CreateDefaultCLSContext(this);
  212. _defaultClsContext = defaultClsContext;
  213. if (DefaultContext._default == null) {
  214. DefaultContext.InitializeDefaults(_defaultContext, defaultClsContext);
  215. }
  216. InitializeBuiltins();
  217. InitializeSystemState();
  218. #if SILVERLIGHT
  219. AddToPath("");
  220. #endif
  221. // sys.argv always includes at least one empty string.
  222. SetSystemStateValue("argv", (_options.Arguments.Count == 0) ?
  223. new List(new object[] { String.Empty }) :
  224. new List(_options.Arguments)
  225. );
  226. if (_options.WarningFilters.Count > 0) {
  227. _systemState.__dict__["warnoptions"] = new List(_options.WarningFilters);
  228. }
  229. if (_options.Frames) {
  230. var getFrame = BuiltinFunction.MakeFunction(
  231. "_getframe",
  232. ArrayUtils.ConvertAll(typeof(SysModule).GetMember("_getframeImpl"), (x) => (MethodBase)x),
  233. typeof(SysModule)
  234. );
  235. _systemState.__dict__["_getframe"] = getFrame;
  236. }
  237. if (_options.Tracing) {
  238. EnsureDebugContext();
  239. RegisterTracebackHandler();
  240. }
  241. List path = new List(_options.SearchPaths);
  242. #if !SILVERLIGHT
  243. _resolveHolder = new AssemblyResolveHolder(this);
  244. try {
  245. Assembly entryAssembly = Assembly.GetEntryAssembly();
  246. // Can be null if called from unmanaged code (VS integration scenario)
  247. if (entryAssembly != null) {
  248. string entry = Path.GetDirectoryName(entryAssembly.Location);
  249. string lib = Path.Combine(entry, "Lib");
  250. path.append(lib);
  251. // add DLLs directory for user-defined extention modules
  252. path.append(Path.Combine(entry, "DLLs"));
  253. }
  254. } catch (SecurityException) {
  255. }
  256. #endif
  257. _systemState.__dict__["path"] = path;
  258. RecursionLimit = _options.RecursionLimit;
  259. #if !SILVERLIGHT
  260. object asmResolve;
  261. if (options == null ||
  262. !options.TryGetValue("NoAssemblyResolveHook", out asmResolve) ||
  263. !System.Convert.ToBoolean(asmResolve)) {
  264. try {
  265. HookAssemblyResolve();
  266. } catch (System.Security.SecurityException) {
  267. // We may not have SecurityPermissionFlag.ControlAppDomain.
  268. // If so, we will not look up sys.path for module loads
  269. }
  270. }
  271. #endif
  272. _equalityComparer = new PythonEqualityComparer(this);
  273. _equalityComparerNonGeneric = (IEqualityComparer)_equalityComparer;
  274. InitialHasher = InitialHasherImpl;
  275. IntHasher = IntHasherImpl;
  276. DoubleHasher = DoubleHasherImpl;
  277. StringHasher = StringHasherImpl;
  278. FallbackHasher = FallbackHasherImpl;
  279. _topNamespace = new TopNamespaceTracker(manager);
  280. foreach (Assembly asm in manager.GetLoadedAssemblyList()) {
  281. _topNamespace.LoadAssembly(asm);
  282. }
  283. manager.AssemblyLoaded += new EventHandler<AssemblyLoadedEventArgs>(ManagerAssemblyLoaded);
  284. _mainThreadFunctionStack = Runtime.Operations.PythonOps.GetFunctionStack();
  285. }
  286. void ManagerAssemblyLoaded(object sender, AssemblyLoadedEventArgs e) {
  287. _topNamespace.LoadAssembly(e.Assembly);
  288. }
  289. /// <summary>
  290. /// Gets or sets the maximum depth of function calls. Equivalent to sys.getrecursionlimit
  291. /// and sys.setrecursionlimit.
  292. /// </summary>
  293. public int RecursionLimit {
  294. get {
  295. return _recursionLimit;
  296. }
  297. set {
  298. if (value < 0) {
  299. throw PythonOps.ValueError("recursion limit must be positive");
  300. }
  301. lock (_codeUpdateLock) {
  302. int oldRecLimit = _recursionLimit;
  303. _recursionLimit = value;
  304. if ((_recursionLimit == Int32.MaxValue) != (value == Int32.MaxValue)) {
  305. // recursion setting has changed, we need to update all of our
  306. // function codes to enforce or un-enforce recursion.
  307. FunctionCode.UpdateAllCode(this);
  308. }
  309. }
  310. }
  311. }
  312. internal bool EnableTracing {
  313. get {
  314. return _tracingThreads > 0 || PythonOptions.Tracing;
  315. }
  316. set {
  317. lock (_codeUpdateLock) {
  318. bool oldEnableTracing = _enableTracing;
  319. _enableTracing = value;
  320. bool flip = false;
  321. if (value && !oldEnableTracing) {
  322. flip = _tracingThreads == 0;
  323. _tracingThreads++;
  324. } else if (!value && oldEnableTracing) {
  325. _tracingThreads--;
  326. flip = _tracingThreads == 0;
  327. if (flip) {
  328. _tracePipeline.TraceCallback = null;
  329. }
  330. }
  331. if (flip) {
  332. // recursion setting has changed, we need to update all of our
  333. // function codes to enforce or un-enforce recursion.
  334. FunctionCode.UpdateAllCode(this);
  335. }
  336. }
  337. }
  338. }
  339. internal TopNamespaceTracker TopNamespace {
  340. get {
  341. return _topNamespace;
  342. }
  343. }
  344. public IEqualityComparer<object>/*!*/ EqualityComparer {
  345. get { return _equalityComparer; }
  346. }
  347. public IEqualityComparer/*!*/ EqualityComparerNonGeneric {
  348. get { return _equalityComparerNonGeneric; }
  349. }
  350. internal sealed class PythonEqualityComparer : IEqualityComparer, IEqualityComparer<object> {
  351. public readonly PythonContext/*!*/ Context;
  352. public PythonEqualityComparer(PythonContext/*!*/ context) {
  353. Assert.NotNull(context);
  354. Context = context;
  355. }
  356. bool IEqualityComparer.Equals(object x, object y) {
  357. return PythonOps.EqualRetBool(Context._defaultContext, x, y);
  358. }
  359. bool IEqualityComparer<object>.Equals(object x, object y) {
  360. return PythonOps.EqualRetBool(Context._defaultContext, x, y);
  361. }
  362. int IEqualityComparer.GetHashCode(object obj) {
  363. return PythonContext.Hash(obj);
  364. }
  365. int IEqualityComparer<object>.GetHashCode(object obj) {
  366. return PythonContext.Hash(obj);
  367. }
  368. }
  369. #region Specialized Hashers
  370. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
  371. internal readonly HashDelegate InitialHasher;
  372. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
  373. internal readonly HashDelegate IntHasher;
  374. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
  375. internal readonly HashDelegate DoubleHasher;
  376. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
  377. internal readonly HashDelegate StringHasher;
  378. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
  379. internal readonly HashDelegate FallbackHasher;
  380. private int InitialHasherImpl(object o, ref HashDelegate dlg) {
  381. if (o == null) {
  382. return NoneTypeOps.NoneHashCode;
  383. }
  384. switch (Type.GetTypeCode(o.GetType())) {
  385. case TypeCode.String:
  386. dlg = StringHasher;
  387. return StringHasher(o, ref dlg);
  388. case TypeCode.Int32:
  389. dlg = IntHasher;
  390. return IntHasher(o, ref dlg);
  391. case TypeCode.Double:
  392. dlg = DoubleHasher;
  393. return DoubleHasher(o, ref dlg);
  394. default:
  395. if (o is IPythonObject) {
  396. dlg = new OptimizedUserHasher(this, ((IPythonObject)o).PythonType).Hasher;
  397. } else {
  398. dlg = new OptimizedBuiltinHasher(this, o.GetType()).Hasher;
  399. }
  400. return dlg(o, ref dlg);
  401. }
  402. }
  403. private int IntHasherImpl(object o, ref HashDelegate dlg) {
  404. if (o != null && o.GetType() == typeof(int)) {
  405. return o.GetHashCode();
  406. }
  407. dlg = FallbackHasher;
  408. return FallbackHasher(o, ref dlg);
  409. }
  410. private int DoubleHasherImpl(object o, ref HashDelegate dlg) {
  411. if (o != null && o.GetType() == typeof(double)) {
  412. return DoubleOps.__hash__((double)o);
  413. }
  414. dlg = FallbackHasher;
  415. return FallbackHasher(o, ref dlg);
  416. }
  417. private int StringHasherImpl(object o, ref HashDelegate dlg) {
  418. if (o != null && o.GetType() == typeof(string)) {
  419. return o.GetHashCode();
  420. }
  421. dlg = FallbackHasher;
  422. return FallbackHasher(o, ref dlg);
  423. }
  424. private int FallbackHasherImpl(object o, ref HashDelegate dlg) {
  425. return PythonOps.Hash(this.SharedContext, o);
  426. }
  427. private sealed class OptimizedUserHasher {
  428. private readonly PythonContext _context;
  429. private readonly PythonType _pt;
  430. public OptimizedUserHasher(PythonContext context, PythonType pt) {
  431. _context = context;
  432. _pt = pt;
  433. }
  434. public int Hasher(object o, ref HashDelegate dlg) {
  435. IPythonObject ipo = o as IPythonObject;
  436. if (ipo != null && ipo.PythonType == _pt) {
  437. return _pt.Hash(o);
  438. }
  439. dlg = _context.FallbackHasher;
  440. return _context.FallbackHasher(o, ref dlg);
  441. }
  442. }
  443. private sealed class OptimizedBuiltinHasher {
  444. private readonly PythonContext _context;
  445. private readonly Type _type;
  446. private readonly PythonType _pt;
  447. public OptimizedBuiltinHasher(PythonContext context, Type type) {
  448. _context = context;
  449. _type = type;
  450. _pt = DynamicHelpers.GetPythonTypeFromType(type);
  451. }
  452. public int Hasher(object o, ref HashDelegate dlg) {
  453. if (o != null && o.GetType() == _type) {
  454. return _pt.Hash(o);
  455. }
  456. dlg = _context.FallbackHasher;
  457. return _context.FallbackHasher(o, ref dlg);
  458. }
  459. }
  460. #endregion
  461. public override LanguageOptions/*!*/ Options {
  462. get { return PythonOptions; }
  463. }
  464. /// <summary>
  465. /// Checks to see if module state has the current value stored already.
  466. /// </summary>
  467. public bool HasModuleState(object key) {
  468. EnsureModuleState();
  469. lock (_moduleState) {
  470. return _moduleState.ContainsKey(key);
  471. }
  472. }
  473. private void EnsureModuleState() {
  474. if (_moduleState == null) {
  475. Interlocked.CompareExchange(ref _moduleState, new Dictionary<object, object>(), null);
  476. }
  477. }
  478. /// <summary>
  479. /// Gets per-runtime state used by a module. The module should have a unique key for
  480. /// each piece of state it needs to store.
  481. /// </summary>
  482. public object GetModuleState(object key) {
  483. EnsureModuleState();
  484. lock (_moduleState) {
  485. Debug.Assert(_moduleState.ContainsKey(key));
  486. return _moduleState[key];
  487. }
  488. }
  489. /// <summary>
  490. /// Sets per-runtime state used by a module. The module should have a unique key for
  491. /// each piece of state it needs to store.
  492. /// </summary>
  493. public void SetModuleState(object key, object value) {
  494. EnsureModuleState();
  495. lock (_moduleState) {
  496. _moduleState[key] = value;
  497. }
  498. }
  499. /// <summary>
  500. /// Sets per-runtime state used by a module and returns the previous value. The module
  501. /// should have a unique key for each piece of state it needs to store.
  502. /// </summary>
  503. public object GetSetModuleState(object key, object value) {
  504. EnsureModuleState();
  505. lock (_moduleState) {
  506. object result;
  507. _moduleState.TryGetValue(key, out result);
  508. _moduleState[key] = value;
  509. return result;
  510. }
  511. }
  512. /// <summary>
  513. /// Sets per-runtime state used by a module and returns the previous value. The module
  514. /// should have a unique key for each piece of state it needs to store.
  515. /// </summary>
  516. public T GetOrCreateModuleState<T>(object key, Func<T> value) where T : class {
  517. EnsureModuleState();
  518. lock (_moduleState) {
  519. object result;
  520. if (!_moduleState.TryGetValue(key, out result)) {
  521. _moduleState[key] = result = value();
  522. }
  523. return (result as T);
  524. }
  525. }
  526. public PythonType EnsureModuleException(object key, PythonDictionary dict, string name, string module) {
  527. return (PythonType)(dict[name] = GetOrCreateModuleState(
  528. key,
  529. () => PythonExceptions.CreateSubType(this, PythonExceptions.Exception, name, module, "", PythonType.DefaultMakeException)
  530. ));
  531. }
  532. public PythonType EnsureModuleException(object key, PythonType baseType, PythonDictionary dict, string name, string module) {
  533. return (PythonType)(dict[name] = GetOrCreateModuleState(
  534. key,
  535. () => PythonExceptions.CreateSubType(this, baseType, name, module, "", PythonType.DefaultMakeException)
  536. ));
  537. }
  538. public PythonType EnsureModuleException(object key, PythonType baseType, Type underlyingType, PythonDictionary dict, string name, string module, Func<string, Exception> exceptionMaker) {
  539. return (PythonType)(dict[name] = GetOrCreateModuleState(
  540. key,
  541. () => PythonExceptions.CreateSubType(this, baseType, underlyingType, name, module, "", exceptionMaker)
  542. ));
  543. }
  544. public PythonType EnsureModuleException(object key, PythonType[] baseTypes, Type underlyingType, PythonDictionary dict, string name, string module) {
  545. return (PythonType)(dict[name] = GetOrCreateModuleState(
  546. key,
  547. () => PythonExceptions.CreateSubType(this, baseTypes, underlyingType, name, module, "", PythonType.DefaultMakeException)
  548. ));
  549. }
  550. internal PythonOptions/*!*/ PythonOptions {
  551. get {
  552. return _options;
  553. }
  554. }
  555. public override Guid VendorGuid {
  556. get {
  557. return LanguageVendor_Microsoft;
  558. }
  559. }
  560. public override Guid LanguageGuid {
  561. get {
  562. return PythonLanguageGuid;
  563. }
  564. }
  565. public PythonModule/*!*/ SystemState {
  566. get {
  567. return _systemState;
  568. }
  569. }
  570. public PythonModule/*!*/ ClrModule {
  571. get {
  572. if (_clrModule == null) {
  573. Interlocked.CompareExchange(ref _clrModule, CreateBuiltinModule("clr"), null);
  574. }
  575. return _clrModule;
  576. }
  577. }
  578. internal bool TryGetSystemPath(out List path) {
  579. object val;
  580. if (SystemState.__dict__.TryGetValue("path", out val)) {
  581. path = val as List;
  582. } else {
  583. path = null;
  584. }
  585. return path != null;
  586. }
  587. internal object SystemStandardOut {
  588. get {
  589. return GetSystemStateValue("stdout");
  590. }
  591. }
  592. internal object SystemStandardIn {
  593. get {
  594. return GetSystemStateValue("stdin");
  595. }
  596. }
  597. internal object SystemStandardError {
  598. get {
  599. return GetSystemStateValue("stderr");
  600. }
  601. }
  602. internal IDictionary<object, object> SystemStateModules {
  603. get {
  604. return _modulesDict;
  605. }
  606. }
  607. internal void UpdateExceptionInfo(object type, object value, object traceback) {
  608. _sysDict.UpdateExceptionInfo(type, value, traceback);
  609. }
  610. internal void UpdateExceptionInfo(Exception clrException, object type, object value, List<DynamicStackFrame> traceback) {
  611. _sysDict.UpdateExceptionInfo(clrException, type, value, traceback);
  612. }
  613. internal void ExceptionHandled() {
  614. _sysDict.ExceptionHandled();
  615. }
  616. internal PythonModule GetModuleByName(string/*!*/ name) {
  617. Assert.NotNull(name);
  618. object scopeObj;
  619. PythonModule module;
  620. if (SystemStateModules.TryGetValue(name, out scopeObj) && (module = scopeObj as PythonModule) != null) {
  621. return module;
  622. }
  623. return null;
  624. }
  625. internal PythonModule GetModuleByPath(string/*!*/ path) {
  626. Assert.NotNull(path);
  627. foreach (object moduleObj in SystemStateModules.Values) {
  628. PythonModule module = moduleObj as PythonModule;
  629. if (module != null) {
  630. if (DomainManager.Platform.PathComparer.Compare(module.GetFile(), path) == 0) {
  631. return module;
  632. }
  633. }
  634. }
  635. return null;
  636. }
  637. public override Version LanguageVersion {
  638. get {
  639. // Assembly.GetName() can't be called in Silverlight...
  640. return GetPythonVersion();
  641. }
  642. }
  643. internal static Version GetPythonVersion() {
  644. return new AssemblyName(typeof(PythonContext).Assembly.FullName).Version;
  645. }
  646. internal FloatFormat FloatFormat {
  647. get {
  648. return _floatFormat;
  649. }
  650. set {
  651. _floatFormat = value;
  652. }
  653. }
  654. internal FloatFormat DoubleFormat {
  655. get {
  656. return _doubleFormat;
  657. }
  658. set {
  659. _doubleFormat = value;
  660. }
  661. }
  662. /// <summary>
  663. /// Initializes the sys module on startup. Called both to load and reload sys
  664. /// </summary>
  665. private void InitializeSystemState() {
  666. // These fields do not get reset on "reload(sys)", we populate them once on startup
  667. SetSystemStateValue("argv", List.FromArrayNoCopy(new object[] { String.Empty }));
  668. SetSystemStateValue("modules", _modulesDict);
  669. InitializeSysFlags();
  670. _modulesDict["sys"] = _systemState;
  671. SetSystemStateValue("path", new List(3));
  672. SetStandardIO();
  673. SysModule.PerformModuleReload(this, _systemState.__dict__);
  674. }
  675. internal bool EmitDebugSymbols(SourceUnit sourceUnit) {
  676. return sourceUnit.EmitDebugSymbols && (PythonOptions.NoDebug == null || !PythonOptions.NoDebug.IsMatch(sourceUnit.Path));
  677. }
  678. private void InitializeSysFlags() {
  679. // sys.flags
  680. SysModule.SysFlags flags = new SysModule.SysFlags();
  681. SetSystemStateValue("flags", flags);
  682. flags.debug = _options.Debug ? 1 : 0;
  683. flags.py3k_warning = _options.WarnPython30 ? 1 : 0;
  684. SetSystemStateValue("py3kwarning", _options.WarnPython30);
  685. switch (_options.DivisionOptions) {
  686. case PythonDivisionOptions.Old:
  687. break;
  688. case PythonDivisionOptions.New:
  689. flags.division_new = 1;
  690. break;
  691. case PythonDivisionOptions.Warn:
  692. flags.division_warning = 1;
  693. break;
  694. case PythonDivisionOptions.WarnAll:
  695. flags.division_warning = 2;
  696. break;
  697. }
  698. flags.inspect = flags.interactive = _options.Inspect ? 1 : 0;
  699. if (_options.StripDocStrings) {
  700. flags.optimize = 2;
  701. } else if (_options.Optimize) {
  702. flags.optimize = 1;
  703. }
  704. flags.dont_write_bytecode = 1;
  705. SetSystemStateValue("dont_write_bytecode", true);
  706. flags.no_user_site = _options.NoUserSite ? 1 : 0;
  707. flags.no_site = _options.NoSite ? 1 : 0;
  708. flags.ignore_environment = _options.IgnoreEnvironment ? 1 : 0;
  709. switch (_options.IndentationInconsistencySeverity) {
  710. case Severity.Warning:
  711. flags.tabcheck = 1;
  712. break;
  713. case Severity.Error:
  714. flags.tabcheck = 2;
  715. break;
  716. }
  717. flags.verbose = _options.Verbose ? 1 : 0;
  718. flags.unicode = 1;
  719. flags.bytes_warning = _options.BytesWarning ? 1 : 0;
  720. }
  721. internal bool ShouldInterpret(PythonCompilerOptions options, SourceUnit source) {
  722. // We have to turn off adaptive compilation in debug mode to
  723. // support mangaged debuggers. Also turn off in optimized mode.
  724. bool adaptiveCompilation = !_options.NoAdaptiveCompilation && !EmitDebugSymbols(source);
  725. return options.Interpreted || adaptiveCompilation;
  726. }
  727. private static PyAst.PythonAst ParseAndBindAst(CompilerContext context) {
  728. ScriptCodeParseResult properties = ScriptCodeParseResult.Complete;
  729. bool propertiesSet = false;
  730. int errorCode = 0;
  731. PyAst.PythonAst ast;
  732. using (Parser parser = Parser.CreateParser(context, PythonContext.GetPythonOptions(null))) {
  733. switch (context.SourceUnit.Kind) {
  734. case SourceCodeKind.InteractiveCode:
  735. ast = parser.ParseInteractiveCode(out properties);
  736. propertiesSet = true;
  737. break;
  738. case SourceCodeKind.Expression:
  739. ast = parser.ParseTopExpression();
  740. break;
  741. case SourceCodeKind.SingleStatement:
  742. ast = parser.ParseSingleStatement();
  743. break;
  744. case SourceCodeKind.File:
  745. ast = parser.ParseFile(true, false);
  746. break;
  747. case SourceCodeKind.Statements:
  748. ast = parser.ParseFile(false, false);
  749. break;
  750. default:
  751. case SourceCodeKind.AutoDetect:
  752. ast = parser.ParseFile(true, true);
  753. break;
  754. }
  755. errorCode = parser.ErrorCode;
  756. }
  757. if (!propertiesSet && errorCode != 0) {
  758. properties = ScriptCodeParseResult.Invalid;
  759. }
  760. context.SourceUnit.CodeProperties = properties;
  761. if (errorCode != 0 || properties == ScriptCodeParseResult.Empty) {
  762. return null;
  763. }
  764. ast.Bind();
  765. return ast;
  766. }
  767. internal static ScriptCode CompilePythonCode(SourceUnit/*!*/ sourceUnit, CompilerOptions/*!*/ options, ErrorSink/*!*/ errorSink) {
  768. var pythonOptions = (PythonCompilerOptions)options;
  769. if (sourceUnit.Kind == SourceCodeKind.File) {
  770. pythonOptions.Module |= ModuleOptions.Initialize;
  771. }
  772. CompilerContext context = new CompilerContext(sourceUnit, options, errorSink);
  773. PyAst.PythonAst ast = ParseAndBindAst(context);
  774. if (ast == null) {
  775. return null;
  776. }
  777. return ast.ToScriptCode();
  778. }
  779. public override ScriptCode CompileSourceCode(SourceUnit/*!*/ sourceUnit, CompilerOptions/*!*/ options, ErrorSink/*!*/ errorSink) {
  780. ScriptCode res = CompilePythonCode(sourceUnit, options, errorSink);
  781. if (res != null) {
  782. Scope scope = res.CreateScope();
  783. // if this is an optimized module we need to initialize the optimized scope.
  784. // Optimized scopes come w/ extensions already attached so we use that to know
  785. // if we're optimized or not.
  786. PythonScopeExtension scopeExtension = (PythonScopeExtension)scope.GetExtension(ContextId);
  787. if (scopeExtension != null) {
  788. InitializeModule(sourceUnit.Path, scopeExtension.ModuleContext, res, ModuleOptions.None);
  789. }
  790. }
  791. return res;
  792. }
  793. public override ScriptCode/*!*/ LoadCompiledCode(Delegate/*!*/ method, string path, string customData) {
  794. SourceUnit su = new SourceUnit(this, NullTextContentProvider.Null, path, SourceCodeKind.File);
  795. return new OnDiskScriptCode((LookupCompilationDelegate)method, su, customData);
  796. }
  797. public override SourceCodeReader/*!*/ GetSourceReader(Stream/*!*/ stream, Encoding/*!*/ defaultEncoding, string path) {
  798. ContractUtils.RequiresNotNull(stream, "stream");
  799. ContractUtils.RequiresNotNull(defaultEncoding, "defaultEncoding");
  800. ContractUtils.Requires(stream.CanSeek && stream.CanRead, "stream", "The stream must support seeking and reading");
  801. // we choose ASCII by default, if the file has a Unicode pheader though
  802. // we'll automatically get it as unicode.
  803. Encoding encoding = PythonAsciiEncoding.SourceEncoding;
  804. long startPosition = stream.Position;
  805. StreamReader sr = new StreamReader(stream, PythonAsciiEncoding.SourceEncoding);
  806. byte[] bomBuffer = new byte[3];
  807. int bomRead = stream.Read(bomBuffer, 0, 3);
  808. int bytesRead = 0;
  809. bool isUtf8 = false;
  810. if (bomRead == 3 && (bomBuffer[0] == 0xef && bomBuffer[1] == 0xbb && bomBuffer[2] == 0xbf)) {
  811. isUtf8 = true;
  812. bytesRead = 3;
  813. } else {
  814. stream.Seek(0, SeekOrigin.Begin);
  815. }
  816. string line;
  817. try {
  818. line = ReadOneLine(sr, ref bytesRead);
  819. } catch (BadSourceException) {
  820. throw ReportEncodingError(stream, path);
  821. }
  822. bool gotEncoding = false;
  823. string encodingName = null;
  824. // magic encoding must be on line 1 or 2
  825. if (line != null && !(gotEncoding = Tokenizer.TryGetEncoding(defaultEncoding, line, ref encoding, out encodingName))) {
  826. try {
  827. line = ReadOneLine(sr, ref bytesRead);
  828. } catch (BadSourceException) {
  829. throw ReportEncodingError(stream, path);
  830. }
  831. if (line != null) {
  832. gotEncoding = Tokenizer.TryGetEncoding(defaultEncoding, line, ref encoding, out encodingName);
  833. }
  834. }
  835. if (gotEncoding && isUtf8 && encodingName != "utf-8") {
  836. // we have both a BOM & an encoding type, throw an error
  837. 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.");
  838. } else if (encoding == null) {
  839. throw new IOException("unknown encoding type");
  840. }
  841. // if we didn't get an encoding seek back to the beginning...
  842. if (!gotEncoding || stream.Position != stream.Length) {
  843. stream.Seek(startPosition, SeekOrigin.Begin);
  844. }
  845. // re-read w/ the correct encoding type...
  846. return new SourceCodeReader(new StreamReader(stream, encoding), encoding);
  847. }
  848. internal static Exception ReportEncodingError(Stream stream, string path) {
  849. stream.Seek(0, SeekOrigin.Begin);
  850. byte[] buffer = new byte[1024];
  851. int bytesRead = 0;
  852. int curLine = 1, curOffset = 1, index = 0;
  853. while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) != -1) {
  854. for (int i = 0; i < bytesRead; i++) {
  855. if (buffer[i] > 0x7f) {
  856. return PythonOps.BadSourceError(
  857. buffer[i],
  858. new SourceSpan(
  859. new SourceLocation(index, curLine, curOffset),
  860. new SourceLocation(index, curLine, curOffset)
  861. ),
  862. path
  863. );
  864. } else if (buffer[i] == '\n') {
  865. curLine++;
  866. curOffset = 1;
  867. } else {
  868. curOffset++;
  869. }
  870. index++;
  871. }
  872. }
  873. return new InvalidOperationException();
  874. }
  875. /// <summary>
  876. /// Reads one line keeping track of the # of bytes read
  877. /// </summary>
  878. private static string ReadOneLine(StreamReader reader, ref int totalRead) {
  879. Stream sr = reader.BaseStream;
  880. byte[] buffer = new byte[256];
  881. StringBuilder builder = null;
  882. int bytesRead = sr.Read(buffer, 0, buffer.Length);
  883. while (bytesRead > 0) {
  884. totalRead += bytesRead;
  885. bool foundEnd = false;
  886. for (int i = 0; i < bytesRead; i++) {
  887. if (buffer[i] == '\r') {
  888. if (i + 1 < bytesRead) {
  889. if (buffer[i + 1] == '\n') {
  890. totalRead -= (bytesRead - (i + 2)); // skip cr/lf
  891. sr.Seek(i + 2, SeekOrigin.Begin);
  892. reader.DiscardBufferedData();
  893. foundEnd = true;
  894. }
  895. } else {
  896. totalRead -= (bytesRead - (i + 1)); // skip cr
  897. sr.Seek(i + 1, SeekOrigin.Begin);
  898. reader.DiscardBufferedData();
  899. foundEnd = true;
  900. }
  901. } else if (buffer[i] == '\n') {
  902. totalRead -= (bytesRead - (i + 1)); // skip lf
  903. sr.Seek(i + 1, SeekOrigin.Begin);
  904. reader.DiscardBufferedData();
  905. foundEnd = true;
  906. }
  907. if (foundEnd) {
  908. if (builder != null) {
  909. builder.Append(buffer.MakeString(), 0, i);
  910. return builder.ToString();
  911. }
  912. return buffer.MakeString().Substring(0, i);
  913. }
  914. }
  915. if (builder == null) builder = new StringBuilder();
  916. builder.Append(buffer.MakeString(), 0, bytesRead);
  917. bytesRead = sr.Read(buffer, 0, buffer.Length);
  918. }
  919. // no string
  920. if (builder == null) {
  921. return null;
  922. }
  923. // no new-line
  924. return builder.ToString();
  925. }
  926. #if !SILVERLIGHT
  927. // Convert a CodeDom to source code, and output the generated code and the line number mappings (if any)
  928. public override SourceUnit/*!*/ GenerateSourceCode(System.CodeDom.CodeObject codeDom, string path, SourceCodeKind kind) {
  929. return new IronPython.Hosting.PythonCodeDomCodeGen().GenerateCode((System.CodeDom.CodeMemberMethod)codeDom, this, path, kind);
  930. }
  931. #endif
  932. #region Scopes
  933. public override Scope GetScope(string/*!*/ path) {
  934. PythonModule module = GetModuleByPath(path);
  935. return (module != null) ? module.Scope : null;
  936. }
  937. public PythonModule/*!*/ InitializeModule(string fileName, ModuleContext moduleContext, ScriptCode scriptCode, ModuleOptions options) {
  938. if ((options & ModuleOptions.NoBuiltins) == 0) {
  939. moduleContext.InitializeBuiltins((options & ModuleOptions.ModuleBuiltins) != 0);
  940. }
  941. // If the filename is __init__.py then this is the initialization code
  942. // for a package and we need to set the __path__ variable appropriately
  943. if (fileName != null && Path.GetFileName(fileName) == "__init__.py") {
  944. string dirname = Path.GetDirectoryName(fileName);
  945. string dir_path = DomainManager.Platform.GetFullPath(dirname);
  946. moduleContext.Globals["__path__"] = PythonOps.MakeList(dir_path);
  947. }
  948. moduleContext.ShowCls = (options & ModuleOptions.ShowClsMethods) != 0;
  949. moduleContext.Features = options;
  950. if ((options & ModuleOptions.Initialize) != 0) {
  951. scriptCode.Run(moduleContext.GlobalScope);
  952. if (!moduleContext.Globals.ContainsKey("__package__")) {
  953. moduleContext.Globals["__package__"] = null;
  954. }
  955. }
  956. return moduleContext.Module;
  957. }
  958. public override ScopeExtension CreateScopeExtension(Scope scope) {
  959. var ret = new PythonScopeExtension(this, scope);
  960. ret.ModuleContext.InitializeBuiltins(false);
  961. return ret;
  962. }
  963. internal PythonModule/*!*/ CompileModule(string fileName, string moduleName, SourceUnit sourceCode, ModuleOptions options) {
  964. ScriptCode compiledCode;
  965. return CompileModule(fileName, moduleName, sourceCode, options, out compiledCode);
  966. }
  967. internal PythonModule/*!*/ CompileModule(string fileName, string moduleName, SourceUnit so