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

/DICK.B1/IronPython/Runtime/Exceptions/TraceBack.cs

https://bitbucket.org/williamybs/uidipythontool
C# | 313 lines | 245 code | 49 blank | 19 comment | 47 complexity | eff9bf4aa3f889a6fb1568a26d5fc199 MD5 | raw file
  1. /* ****************************************************************************
  2. *
  3. * Copyright (c) Microsoft Corporation.
  4. *
  5. * This source code is subject to terms and conditions of the Microsoft Public License. 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 Microsoft Public License, 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 Microsoft Public License.
  10. *
  11. * You must not remove this notice, or any other, from this software.
  12. *
  13. *
  14. * ***************************************************************************/
  15. using System;
  16. using System.Collections.Generic;
  17. using System.Diagnostics;
  18. using System.Runtime.CompilerServices;
  19. using Microsoft.Scripting;
  20. using Microsoft.Scripting.Runtime;
  21. using Microsoft.Scripting.Utils;
  22. using IronPython.Runtime.Operations;
  23. [module: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope = "member", Target = "IronPython.Runtime.Exceptions.TraceBackFrame..ctor(System.Object,System.Object,System.Object)", MessageId = "0#globals")]
  24. [module: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope = "member", Target = "IronPython.Runtime.Exceptions.TraceBackFrame.Globals", MessageId = "Globals")]
  25. namespace IronPython.Runtime.Exceptions {
  26. [PythonType("traceback")]
  27. [Serializable]
  28. public class TraceBack {
  29. private readonly TraceBack _next;
  30. private readonly TraceBackFrame _frame;
  31. private int _line;
  32. public TraceBack(TraceBack nextTraceBack, TraceBackFrame fromFrame) {
  33. _next = nextTraceBack;
  34. _frame = fromFrame;
  35. }
  36. public TraceBack tb_next {
  37. get {
  38. return _next;
  39. }
  40. }
  41. public object tb_frame {
  42. get {
  43. return _frame;
  44. }
  45. }
  46. public int tb_lineno {
  47. get {
  48. return _line;
  49. }
  50. }
  51. public int tb_lasti {
  52. get {
  53. return 0; // not presently tracked
  54. }
  55. }
  56. internal void SetLine(int lineNumber) {
  57. _line = lineNumber;
  58. }
  59. }
  60. [PythonType("frame")]
  61. [Serializable]
  62. public class TraceBackFrame {
  63. private readonly PythonTracebackListener _traceAdapter;
  64. private TracebackDelegate _trace;
  65. private object _traceObject;
  66. internal int _lineNo;
  67. private readonly PythonDebuggingPayload _debugProperties;
  68. private readonly Func<IAttributesCollection> _scopeCallback;
  69. private readonly PythonDictionary _globals;
  70. private readonly object _locals;
  71. private readonly FunctionCode _code;
  72. private readonly CodeContext/*!*/ _context;
  73. private readonly TraceBackFrame _back;
  74. internal TraceBackFrame(CodeContext/*!*/ context, PythonDictionary globals, object locals, FunctionCode code) {
  75. _globals = globals;
  76. _locals = locals;
  77. _code = code;
  78. _context = context;
  79. }
  80. internal TraceBackFrame(CodeContext/*!*/ context, PythonDictionary globals, object locals, FunctionCode code, TraceBackFrame back) {
  81. _globals = globals;
  82. _locals = locals;
  83. _code = code;
  84. _context = context;
  85. _back = back;
  86. }
  87. internal TraceBackFrame(PythonTracebackListener traceAdapter, FunctionCode code, TraceBackFrame back, PythonDebuggingPayload debugProperties, Func<IAttributesCollection> scopeCallback) {
  88. _traceAdapter = traceAdapter;
  89. _code = code;
  90. _back = back;
  91. _debugProperties = debugProperties;
  92. _scopeCallback = scopeCallback;
  93. }
  94. [SpecialName, PropertyMethod]
  95. public object Getf_trace() {
  96. if (_traceAdapter != null) {
  97. return _traceObject;
  98. } else {
  99. return null;
  100. }
  101. }
  102. [SpecialName, PropertyMethod]
  103. public void Setf_trace(object value) {
  104. _traceObject = value;
  105. _trace = (TracebackDelegate)Converter.ConvertToDelegate(value, typeof(TracebackDelegate));
  106. }
  107. [SpecialName, PropertyMethod]
  108. public void Deletef_trace() {
  109. Setf_trace(null);
  110. }
  111. internal CodeContext Context {
  112. get {
  113. return _context;
  114. }
  115. }
  116. internal TracebackDelegate TraceDelegate {
  117. get {
  118. if (_traceAdapter != null) {
  119. return _trace;
  120. } else {
  121. return null;
  122. }
  123. }
  124. }
  125. public PythonDictionary f_globals {
  126. get {
  127. object context;
  128. if (_scopeCallback != null &&
  129. _scopeCallback().TryGetValue(SymbolTable.StringToId(Compiler.Ast.PythonAst.GlobalContextName), out context)) {
  130. return ((CodeContext)context).GlobalDict;
  131. } else {
  132. return _globals;
  133. }
  134. }
  135. }
  136. public object f_locals {
  137. get {
  138. if (_traceAdapter != null && _scopeCallback != null) {
  139. if (_code.IsModule) {
  140. // don't use the scope callback for locals in a module, use our globals dictionary instead
  141. return f_globals;
  142. }
  143. return new PythonDictionary(new AttributesDictionaryStorage(_scopeCallback()));
  144. } else {
  145. return _locals;
  146. }
  147. }
  148. }
  149. public FunctionCode f_code {
  150. get {
  151. return _code;
  152. }
  153. }
  154. public object f_builtins {
  155. get {
  156. return PythonContext.GetContext(_context).BuiltinModuleDict;
  157. }
  158. }
  159. public TraceBackFrame f_back {
  160. get {
  161. return _back;
  162. }
  163. }
  164. public object f_exc_traceback {
  165. get {
  166. return null;
  167. }
  168. }
  169. public object f_exc_type {
  170. get {
  171. return null;
  172. }
  173. }
  174. public bool f_restricted {
  175. get {
  176. return false;
  177. }
  178. }
  179. public object f_lineno {
  180. get {
  181. if (_traceAdapter != null) {
  182. return _lineNo;
  183. } else {
  184. return 1;
  185. }
  186. }
  187. set {
  188. if (!(value is int)) {
  189. throw PythonOps.ValueError("lineno must be an integer");
  190. }
  191. int newLineNum = (int)value;
  192. if (_traceAdapter != null) {
  193. SetLineNumber(newLineNum);
  194. } else {
  195. throw PythonOps.ValueError("f_lineno can only be set by a trace function");
  196. }
  197. }
  198. }
  199. private void SetLineNumber(int newLineNum) {
  200. var pyThread = PythonOps.GetFunctionStackNoCreate();
  201. if (!TracingThisFrame(pyThread)) {
  202. throw PythonOps.ValueError("f_lineno can only be set by a trace function");
  203. }
  204. FunctionCode funcCode = _debugProperties.Code;
  205. Dictionary<int, Dictionary<int, bool>> loopAndFinallyLocations = _debugProperties.LoopAndFinallyLocations;
  206. Dictionary<int, bool> handlerLocations = _debugProperties.HandlerLocations;
  207. Dictionary<int, bool> currentLoopIds = null;
  208. bool inForLoopOrFinally = loopAndFinallyLocations != null && loopAndFinallyLocations.TryGetValue(_lineNo, out currentLoopIds);
  209. int originalNewLine = newLineNum;
  210. if (newLineNum < funcCode.Span.Start.Line) {
  211. throw PythonOps.ValueError("line {0} comes before the current code block", newLineNum);
  212. } else if (newLineNum > funcCode.Span.End.Line) {
  213. throw PythonOps.ValueError("line {0} comes after the current code block", newLineNum);
  214. }
  215. while (newLineNum <= funcCode.Span.End.Line) {
  216. var span = new SourceSpan(new SourceLocation(0, newLineNum, 1), new SourceLocation(0, newLineNum, Int32.MaxValue));
  217. // Check if we're jumping onto a handler
  218. bool handlerIsFinally;
  219. if (handlerLocations != null && handlerLocations.TryGetValue(newLineNum, out handlerIsFinally)) {
  220. throw PythonOps.ValueError("can't jump to 'except' line");
  221. }
  222. // Check if we're jumping into a for-loop
  223. Dictionary<int, bool> jumpIntoLoopIds;
  224. if (loopAndFinallyLocations != null && loopAndFinallyLocations.TryGetValue(newLineNum, out jumpIntoLoopIds)) {
  225. // If we're not in any loop already - then we can't jump into a loop
  226. if (!inForLoopOrFinally) {
  227. throw BadForOrFinallyJump(newLineNum, jumpIntoLoopIds);
  228. }
  229. // If we're in loops - we can only jump if we're not entering a new loop
  230. foreach (int jumpIntoLoopId in jumpIntoLoopIds.Keys) {
  231. if (!currentLoopIds.ContainsKey(jumpIntoLoopId)) {
  232. throw BadForOrFinallyJump(newLineNum, currentLoopIds);
  233. }
  234. }
  235. } else if (currentLoopIds != null) {
  236. foreach (bool isFinally in currentLoopIds.Values) {
  237. if (isFinally) {
  238. throw PythonOps.ValueError("can't jump out of 'finally block'");
  239. }
  240. }
  241. }
  242. if (_traceAdapter.PythonContext.TracePipeline.CanSetNextStatement((string)((FunctionCode)_code).co_filename, span)) {
  243. _traceAdapter.PythonContext.TracePipeline.SetNextStatement((string)((FunctionCode)_code).co_filename, span);
  244. _lineNo = newLineNum;
  245. return;
  246. }
  247. ++newLineNum;
  248. }
  249. throw PythonOps.ValueError("line {0} is invalid jump location ({1} - {2} are valid)", originalNewLine, funcCode.Span.Start.Line, funcCode.Span.End.Line);
  250. }
  251. private bool TracingThisFrame(List<FunctionStack> pyThread) {
  252. return pyThread != null && pyThread.Count != 0 && Type.ReferenceEquals(this, pyThread[pyThread.Count - 1].Frame);
  253. }
  254. private static Exception BadForOrFinallyJump(int newLineNum, Dictionary<int, bool> jumpIntoLoopIds) {
  255. foreach (bool isFinally in jumpIntoLoopIds.Values) {
  256. if (isFinally) {
  257. return PythonOps.ValueError("can't jump into 'finally block'", newLineNum);
  258. }
  259. }
  260. return PythonOps.ValueError("can't jump into 'for loop'", newLineNum);
  261. }
  262. }
  263. public delegate TracebackDelegate TracebackDelegate(TraceBackFrame frame, string result, object payload);
  264. }