|
@@ -0,0 +1,120 @@
|
|
1
|
+func new_debug_state(res)
|
|
2
|
+ return {
|
|
3
|
+ tb = res[2],
|
|
4
|
+ framenum = (#(res[2])) - 1,
|
|
5
|
+ err = res[1],
|
|
6
|
+ frame = func(self)
|
|
7
|
+ return self.tb[self.framenum]
|
|
8
|
+ end,
|
|
9
|
+ fun = func(self)
|
|
10
|
+ return self:frame()[2]
|
|
11
|
+ end,
|
|
12
|
+ locals = func(self)
|
|
13
|
+ return self:frame()[1]
|
|
14
|
+ end,
|
|
15
|
+ node = func(self)
|
|
16
|
+ return self:frame()[0]
|
|
17
|
+ end,
|
|
18
|
+ goto = func(self, fn)
|
|
19
|
+ if (fn < 0) || (fn >= (#self.tb)) then
|
|
20
|
+ print('Bad frame number')
|
|
21
|
+ else
|
|
22
|
+ self.framenum = fn
|
|
23
|
+ end
|
|
24
|
+ end,
|
|
25
|
+ }
|
|
26
|
+end
|
|
27
|
+
|
|
28
|
+func list_join(l, sep)
|
|
29
|
+ res = l:reduce(lambda(x, y) x + sep + y end, '')
|
|
30
|
+ return res:sub(#sep, #res)
|
|
31
|
+end
|
|
32
|
+
|
|
33
|
+func list_slice(l, frm, to)
|
|
34
|
+ if frm < 0 then frm += (#l) end
|
|
35
|
+ if to < 0 then to += (#l) end
|
|
36
|
+ dist = to - frm
|
|
37
|
+ return for idx in range(dist) do
|
|
38
|
+ continue l[frm + idx]
|
|
39
|
+ end
|
|
40
|
+end
|
|
41
|
+
|
|
42
|
+commands = {
|
|
43
|
+ print = func(ds, line)
|
|
44
|
+ nd = parse(line).stmtlist[0].expr
|
|
45
|
+ print(nd(ds:locals()))
|
|
46
|
+ end,
|
|
47
|
+ error = func(ds, line)
|
|
48
|
+ print(ds.err)
|
|
49
|
+ end,
|
|
50
|
+ fun = func(ds, line)
|
|
51
|
+ print(ds:fun())
|
|
52
|
+ end,
|
|
53
|
+ backtrace = func(ds, line)
|
|
54
|
+ idx = 0
|
|
55
|
+ for frm in ds.tb do
|
|
56
|
+ print(if idx == ds.framenum then '=> ' else ' ' end,'In', frm[2], 'at', frm[0].loc.line, ',', frm[0].loc.col, ':', frm[0])
|
|
57
|
+ idx += 1
|
|
58
|
+ end
|
|
59
|
+ end,
|
|
60
|
+ locals = func(ds, line)
|
|
61
|
+ loc = ds:locals()
|
|
62
|
+ for var in loc do
|
|
63
|
+ print(var, ':', type(loc[var]))
|
|
64
|
+ end
|
|
65
|
+ end,
|
|
66
|
+ up = func(ds, line)
|
|
67
|
+ ds:goto(ds.framenum - 1)
|
|
68
|
+ end,
|
|
69
|
+ down = func(ds, line)
|
|
70
|
+ ds:goto(ds.framenum + 1)
|
|
71
|
+ end,
|
|
72
|
+ to = func(ds, line)
|
|
73
|
+ ds:goto(toint(line))
|
|
74
|
+ end,
|
|
75
|
+ code = func(ds, line)
|
|
76
|
+ ast.print(ds:node())
|
|
77
|
+ end,
|
|
78
|
+ eval = func(ds, line)
|
|
79
|
+ nd = parse(line)
|
|
80
|
+ nd(ds:locals())
|
|
81
|
+ end,
|
|
82
|
+ cont = func(ds, line)
|
|
83
|
+ ds.running = false
|
|
84
|
+ end,
|
|
85
|
+ help = func(ds, line)
|
|
86
|
+ print('Valid commands:')
|
|
87
|
+ for k in commands do
|
|
88
|
+ print(k)
|
|
89
|
+ end
|
|
90
|
+ end,
|
|
91
|
+}
|
|
92
|
+
|
|
93
|
+commands.p = commands.print
|
|
94
|
+commands.u = commands.up
|
|
95
|
+commands.d = commands.down
|
|
96
|
+commands.t = commands.to
|
|
97
|
+commands.c = commands.code
|
|
98
|
+commands['!'] = commands.eval
|
|
99
|
+commands['continue'] = commands.cont
|
|
100
|
+commands['func'] = commands.fun
|
|
101
|
+commands.f = commands.fun
|
|
102
|
+commands.bt = commands.backtrace
|
|
103
|
+
|
|
104
|
+func postmortem(ds)
|
|
105
|
+ ds.running = true
|
|
106
|
+ while ds.running do
|
|
107
|
+ io.stdout:write('==> ')
|
|
108
|
+ ln = io.stdin:read(io.LINE):sub(0, -1)
|
|
109
|
+ parts = ln:split(" ")
|
|
110
|
+ cmd = parts[0]
|
|
111
|
+ arg = list_join(list_slice(parts, 1, #parts), " ")
|
|
112
|
+ cfunc = commands[cmd]
|
|
113
|
+ if None == cfunc then
|
|
114
|
+ try(commands.help, ds, '')
|
|
115
|
+ continue
|
|
116
|
+ end
|
|
117
|
+ res = try(cfunc, ds, arg)
|
|
118
|
+ if !(res[0]) then print("Postmortem Internal Error:", res[1]) end
|
|
119
|
+ end
|
|
120
|
+end
|