1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
|
(compile-only
(load-for (struct sys:param-parser-base "param")))
(defvar *trace-output* *stdout*)
(defvar sys:*trace-hash* (hash :equal-based))
(defvar sys:*trace-level* -1)
(defvarl sys:tr* (fun *))
(defvarl sys:trfm (fun format))
(defun sys:trace-enter (name args)
[sys:trfm *trace-output* "~*a(~s ~s\n" [sys:tr* sys:*trace-level* 2] "" name args])
(defun sys:trace-leave (val)
[sys:trfm *trace-output* "~*a ~s)\n" [sys:tr* sys:*trace-level* 2] "" val])
(defun sys:trace-canonicalize-name (name)
(if (and (consp name)
(eq (car name) 'meth))
(let* ((req-type-sym (cadr name))
(slot-sym (caddr name))
(req-type (find-struct-type req-type-sym))
(s-s-p (if req-type
(static-slot-p req-type slot-sym)))
(actual-type-sym (if s-s-p
(static-slot-home req-type-sym slot-sym))))
(if (and s-s-p (neq req-type-sym actual-type-sym))
^(meth ,actual-type-sym ,slot-sym)
name))
name))
(defun sys:trace (names)
(cond
((null names) (hash-keys sys:*trace-hash*))
(t
(each ((orig-n names)
(n [mapcar sys:trace-canonicalize-name names]))
(unless [sys:*trace-hash* n]
(when (neq n orig-n)
(usr:catch
(throwf 'warning "~s: ~s is actually ~s: tracing that instead"
'trace orig-n n)
(continue ())))
(let* ((prev (or (symbol-function n)
(throwf 'eval-error
"~s: ~s does not name a function" 'trace n)))
(lex-n n)
(hook (lambda (. args)
(let ((abandoned t)
(sys:*trace-level* (succ sys:*trace-level*)))
(unwind-protect
(progn
(sys:trace-enter lex-n args)
(let ((val (apply prev args)))
(sys:trace-leave val)
(set abandoned nil)
val))
(if abandoned
(sys:trace-leave :abandoned)))))))
(set (symbol-function n) hook
[sys:*trace-hash* n] prev)))))))
(defun sys:untrace (names)
(flet ((disable (name-orig name)
(let ((prev (del [sys:*trace-hash* name])))
(when prev
(when (neq name-orig name)
(usr:catch
(throwf 'warning "~s: ~s is actually ~s: untracing that instead"
'trace name-orig name)
(continue ())))
(set (symbol-function name) prev)))))
(if names
(each ((n-orig names)
(n [mapcar sys:trace-canonicalize-name names]))
(disable n-orig n))
(dohash (n #:v sys:*trace-hash*)
(disable n n)))))
(defun sys:trace-redefine-check (orig-name)
(let ((name (sys:trace-canonicalize-name orig-name)))
(when [sys:*trace-hash* name]
(usr:catch
(cond
((neq name orig-name)
(throwf 'warning "~!~s won't be traced, though it overrides\n\
~s which is currently traced"
name orig-name))
(t (sys:untrace (list name))
(throwf 'warning "previously traced ~s is redefined and no\ \
longer traced"
name)))
(continue ())))))
(defmacro usr:trace (. names)
^(sys:trace ',names))
(defmacro usr:untrace (. names)
^(sys:untrace ',names))
(define-param-expander :trace (param body menv form)
(ignore menv)
(let* ((pp (new (fun-param-parser param form)))
(args (append pp.req pp.(opt-syms) pp.rest))
(name (let* ((anc (dig form))
(sls (source-loc-str anc)))
(match-case anc
((@(member @type '(flet labels macrolet)) @name)
^(,type ,name ,sls))
((@(or defun defmacro) @name . @nil)
^(,name ,sls))
(@nil sls)))))
(with-gensyms (abandoned arglist result)
(list param
^(let ((,abandoned t)
(sys:*trace-level* (succ sys:*trace-level*))
(,arglist (list ,*args))
,result)
(unwind-protect
(progn
(sys:trace-enter ',name ,arglist)
(set ,result (progn ,*body))
(sys:trace-leave ,result)
(set ,abandoned nil)
,result)
(if ,abandoned
(sys:trace-leave :abandoned))))))))
|