; Debug-wrap is one of the most practical functions resulted from ; deliberations on this blog. It is described in this post: ; ; http://kazimirmajorinc.blogspot.com/2008/07/verbose-functions.html ; ; version described in the blog maybe doesn't work any more as it is, ; because Newlisp changed in the meantime. But essence is the same, and ; updated version is in Instprog.default-library.lsp. ; Classical examples are Fibonacci's numbers. (load "http://www.instprog.com/Instprog.default-library.lsp") ; (load "C:\\Newlisp\\Instprog.default-library.lsp") ; (set 'fib (lambda(n)(if (< n 3) 1 (+ (fib (- n 1)) (fib (- n 2)))))) (debug-wrap fib) (fib 5) ; ; Result: ; ; (fib (in 5) ; (fib (in 4) ; (fib (in 3) ; (fib (in 2) ; (out 1)) ; (fib (in 1) ; (out 1)) ; (out 2)); t=22 ; (fib (in 2) ; (out 1)) ; (out 3)); t=43 ; (fib (in 3) ; (fib (in 2) ; (out 1)) ; (fib (in 1) ; (out 1)) ; (out 2)); t=22 ; (out 5)); t=86 ; ; "comments" like t=113 are the time of the evaluation of the function, ; in microseconds .The result is in form of s-expression, because ; that is readable format, and also, because it allows one to inspect ; debugging output in some s-expression aware text editor, that ; can highlight left and right parenths. I had best experiences ; with PLT Scheme editor. Debug-wrap can be applied on macros and ; built in primitives as well. (debug-wrap +) (fib 5) ; (fib (in 5) ; (+ (in (fib (- n 1)) (fib (- n 2))) ; (fib (in 4) ; (+ (in (fib (- n 1)) (fib (- n 2))) ; (fib (in 3) ; (+ (in (fib (- n 1)) (fib (- n 2))) ; (fib (in 2) ; (out 1)) ; (fib (in 1) ; (out 1)) ; (out 2)); t=23 ; (out 2)); t=35 ; (fib (in 2) ; (out 1)) ; (out 3)); t=57 ; (out 3)); t=71 ; (fib (in 3) ; (+ (in (fib (- n 1)) (fib (- n 2))) ; (fib (in 2) ; (out 1)) ; (fib (in 1) ; (out 1)) ; (out 2)); t=21 ; (out 2)); t=34 ; (out 5)); t=131 ; (out 5)); t=141 ; ; OK, it works. But, what will happen if I try something relatively ; naive: ; ; (debug-wrap when) ; ; (fib 5) ; ; ; Why? The function when is used inside the definition of new, ; debug version of when. So, when calls another instance of when, ; which calls another instance of when and so forth. ; ; So, what is the solution for this case? We'll replace all occurences ; of symbol when in the body of debug-wrap with symbol [when.original]. ; There are few trivial details also. (debug-unwrap fib) (debug-unwrap +) (set '[when.original] when) (set 'debug-wrap (expand debug-wrap '((when [when.original])))) (debug-wrap when) (debug-wrap fib) (fib 5) ; it works. Wrapped when is not problem any more. ; Now, I'll debug-wrap all primitives used in fib: +, - and if. ; I'll use few functions that semi-automatize that. Main idea is ; relatively simple, but there are quite a few technical details. ; My suggestion is - don't bother much about details, just get the ; idea. First, I'll clean the tails left from previous debugging ; sessions of fib. (debug-unwrap when) (debug-unwrap fib) ; Function original accepts symbol, say z as argument and returns ; symbol [z.original] (set 'original (lambda([original.x]) (sym (append "[" (string [original.x]) ".original]")))) ; this loop is equivalent to (set '[+.original] +) and same for ; - and if. (dolist(i '(+ - if)) (if (primitive? (eval i)) (set (original i) (eval i)))) ; The function originalize replace all simbols like + with [+.original] ; in the body of the fname. (set 'originalize (lambda(fname symbolist) (eval (list (if (protected? (eval fname)) 'set 'constant) 'fname (expand (eval fname) (map (lambda(s) ;this map will produce (list s ;((+ [+.original])...) (original s))) symbolist)))))) (originalize 'debug-wrap '(+ - if)) (originalize 'println '(+ - if)) ; I must do that because my library ; redefines println on the way that ; contains if, and if I do not use ; original if, infinite loops is ; created. (originalize 'print '(+ - if)) ; The same as println. (debug-wrap fib) (debug-wrap +) (debug-wrap -) (debug-wrap if) (===) (fib 5) (exit) ; RESULT ; (fib (in 5) ; (if (in (< n 3) 1 (+ (fib (- n 1)) (fib (- n 2)))) ; (+ (in (fib (- n 1)) (fib (- n 2))) ; (- (in n 1) ; (out 4)) ; (fib (in 4) ; (if (in (< n 3) 1 (+ (fib (- n 1)) (fib (- n 2)))) ; (+ (in (fib (- n 1)) (fib (- n 2))) ; (- (in n 1) ; (out 3)) ; (fib (in 3) ; (if (in (< n 3) 1 (+ (fib (- n 1)) (fib (- n 2)))) ; (+ (in (fib (- n 1)) (fib (- n 2))) ; (- (in n 1) ; (out 2)) ; (fib (in 2) ; (if (in (< n 3) 1 (+ (fib (- n 1)) (fib (- n 2)))) ; (out 1)) ; (out 1)); t=10 ; (- (in n 2) ; (out 1)) ; (fib (in 1) ; (if (in (< n 3) 1 (+ (fib (- n 1)) (fib (- n 2)))) ; (out 1)) ; (out 1)); t=14 ; (out 2)); t=64 ; (out 2)); t=78 ; (out 2)); t=89 ; (- (in n 2) ; (out 2)) ; (fib (in 2) ; (if (in (< n 3) 1 (+ (fib (- n 1)) (fib (- n 2)))) ; (out 1)) ; (out 1)); t=11 ; (out 3)); t=143 ; (out 3)); t=153 ; (out 3)); t=164 ; (- (in n 2) ; (out 3)) ; (fib (in 3) ; (if (in (< n 3) 1 (+ (fib (- n 1)) (fib (- n 2)))) ; (+ (in (fib (- n 1)) (fib (- n 2))) ; (- (in n 1) ; (out 2)) ; (fib (in 2) ; (if (in (< n 3) 1 (+ (fib (- n 1)) (fib (- n 2)))) ; (out 1)); t=1 ; (out 1)); t=13 ; (- (in n 2) ; (out 1)) ; (fib (in 1) ; (if (in (< n 3) 1 (+ (fib (- n 1)) (fib (- n 2)))) ; (out 1)) ; (out 1)); t=13 ; (out 2)); t=75 ; (out 2)); t=88 ; (out 2)); t=101 ; (out 5)); t=302 ; (out 5)); t=311 ; (out 5)); t=325 ; ; In next few weeks, I'll integrate all that in the library, so use of the ; debug-wrap will be simpler even when built-in primitives are ; debug-wrapped. |
Debug-wrapping Around Built-in Primitives
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment