Skip to content

Commit f20d85d

Browse files
committed
wip: traceback types from Nim's
1 parent b1ada6c commit f20d85d

File tree

2 files changed

+138
-0
lines changed

2 files changed

+138
-0
lines changed

src/pylib/Lib/types.nim

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
2+
3+
import ../version
4+
import ../noneType
5+
6+
const PyVer = (PyMajor, PyMinor)
7+
when PyVer > (3, 10):
8+
export NoneType
9+
10+

src/pylib/Lib/types_impl/debugs.nim

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
2+
##[
3+
.. note:: almost all functionalities here is only available in debug mode,
4+
e.g. not when `-d:release`
5+
]##
6+
7+
8+
#[
9+
# dev-manual
10+
11+
## types
12+
StackTraceEntry = object
13+
procname*: cstring ## Name of the proc that is currently executing.
14+
line*: int ## Line number of the proc that is currently executing.
15+
filename*: cstring ## Filename of the proc that is currently executing.
16+
...
17+
18+
PFrame = ptr TFrame
19+
TFrame {.importc, nodecl, final.} = object
20+
prev*: PFrame ## Previous frame; used for chaining the call stack.
21+
procname*: cstring ## Name of the proc that is currently executing.
22+
line*: int ## Line number of the proc that is currently executing.
23+
filename*: cstring ## Filename of the proc that is currently executing.
24+
len*: int16 ## Length of the inspectable slots.
25+
calldepth*: int16 ## Used for max call depth checking.
26+
27+
## procs
28+
29+
proc getStackTraceEntries([e: ref Exception]): seq[StackTraceEntry]
30+
proc getFrame(): PFrame
31+
32+
]#
33+
34+
type
35+
FrameType*{.acyclic.} = ref object
36+
# RO
37+
f_back: FrameType
38+
#[f_code*:
39+
f_locals*:
40+
f_globals*:
41+
f_builtins*: ]#
42+
f_lasti*: int ## Always 0 here, see `TracebackType`_ for details
43+
44+
# RW
45+
f_lineno*: int
46+
47+
TracebackType*{.acyclic.} = ref object
48+
# RO
49+
tb_frame: FrameType
50+
tb_lineno: int
51+
tb_lasti*: int ## .. note:: as Nim is a compile-language,
52+
## no opcode here, so this attr is always 0
53+
54+
# RW
55+
tb_next*: TracebackType
56+
57+
func f_back*(f: FrameType): FrameType = self.f_back
58+
59+
60+
func tb_frame*(tb: TracebackType): FrameType = self.tb_frame
61+
func tb_lineno*(tb: TracebackType): FrameType = self.tb_lineno
62+
63+
64+
proc newPyFrame*(f: PFrame = getFrame()): FrameType =
65+
FrameType(
66+
f_back: f.prev,
67+
f_lineno: f.line
68+
)
69+
proc newPyFrame*(f: StackTraceEntry, f_back: FrameType = nil, f_lasti=0): FrameType =
70+
FrameType(
71+
f_back: f_back,
72+
f_lineno: f.line,
73+
f_lasti: f_lasti,
74+
)
75+
76+
proc newPyTraceback*(st: StackTraceEntry, f: PFrame, tb_next: TracebackType = nil): TracebackType =
77+
let pyf = newPyFrame f
78+
TracebackType(
79+
tb_frame: pyf,
80+
tb_lineno: f.line,
81+
tb_lasti: pyf.f_lasti,
82+
tb_next: tb_next
83+
)
84+
85+
proc newPyTraceback*(st: seq[StackTraceEntry] = getStackTraceEntries()
86+
): TracebackType =
87+
## may used to implement traceback.print_*
88+
for i in countdown(st.high, 0):
89+
result = newPyTraceback(st[i], newPyFrame(st),
90+
tb_next=result)
91+
92+
proc `traceback.print_stack`*(f: FrameType = newPyFrame()
93+
file=stderr) =
94+
let st = getStackTraceEntries()
95+
for i in countdown(st.high, max(0, st.high-limit)):
96+
let s = st[i]
97+
file.write "File $#, line $#, in $#\n".format(
98+
s.filename, f.line, f.procname)
99+
100+
101+
func newPyTraceback*(tb_next: TracebackType,
102+
tb_frame: FrameType, tb_lasti, tb_lineno: int): TracebackType =
103+
TracebackType(
104+
tb_frame: tb_frame,
105+
tb_lineno: tb_lineno,
106+
tb_lasti: tb_lasti,
107+
tb_next: tb_next,
108+
)
109+
110+
#[
111+
# Graph
112+
113+
## Python
114+
f1 f2
115+
<- .f_back
116+
^
117+
|
118+
.tb_frame
119+
tb1 tb2
120+
.tb_next ->
121+
122+
## Nim
123+
124+
getStackTraceEntries([e: ref Exception]) -> [GlobalScope, ..., PreviousStack, CurrentStack]
125+
126+
]#
127+
128+
proc getLastTraceback*()

0 commit comments

Comments
 (0)