home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-385-Vol-1of3.iso
/
s
/
s48.zip
/
MISC
/
DEBUG.SCM
< prev
next >
Wrap
Text File
|
1992-06-17
|
7KB
|
263 lines
; Copyright (c) 1992 by Richard Kelsey and Jonathan Rees. See file COPYING.
; Commands for debugging.
(export! system-package '(show-undefined-variables)) ;grumble
; Benchmark mode (i.e., inline primitives)
(define (bench-command)
(let ((b (not *benchmark-mode?*)))
(set-benchmark-mode! b)
(set! *benchmark-mode?* b)
(write-line (if b "Benchmark mode enabled" "Benchmark mode disabled")
(fluid $output-port))))
(define *benchmark-mode?* #t)
(define-command 'bench "" "benchmark mode (integrate primitives)"
'() bench-command)
; :flush
(define-command 'flush "" "flush initial debug information database"
'() flush-debug-info)
; :collect
(define (collect-command)
(let ((port (fluid $output-port))
(before (vm 0 #f)))
(collect)
(let ((after (vm 0 #f)))
(display "Before: " port)
(write before port)
(newline)
(display "After: " port)
(write after port)
(newline))))
(define-command 'collect "" "GC" '() collect-command)
; :undefined
(define (show-undefined-variables)
(let ((out (fluid $output-port))
(undef (undefined-variables (fluid $package-for-commands))))
(if (not (null? undef))
(begin (display "Undefined: " out)
(write undef out)
(newline out)))))
(define-command 'undefined "" "list undefined variables"
'() show-undefined-variables)
; :preview -- show continuations
(define (preview)
(continuation-preview (command-loop-continuation)))
(define (continuation-preview c)
(if (continuation? c)
(begin
(let ((name (template-name (continuation-template c))))
(cond ((and name
;; Pretty kludgey, huh?
(not (member name preview-ignored-names)))
(display " ")
(write name)
(newline))))
(continuation-preview (next-ripe-continuation c)))))
(define preview-ignored-names '(with-dynamic-env))
; If (continuation-cont A) = B, then ignore B if
; 1. (continuation-template B) = (continuation-template A)
; 2. (continuation-pc B) > (continuation-pc A)
; 3. (continuation-env B) = (continuation-env A)
; or some parent of (continuation-env A)
(define (next-ripe-continuation a)
(let ((b (continuation-cont a)))
(if (and (continuation? b)
(eq? (continuation-template b) (continuation-template a))
(> (continuation-pc b) (continuation-pc a))
(let loop ((env (continuation-env A)))
(or (eq? env (continuation-env B))
(and (vector? env)
(loop (vector-ref env 0))))))
(next-ripe-continuation b)
b)))
(define-command 'preview "" "show continuations (stack trace)"
'() preview)
; Proceed
(define (proceed . value-option)
(let ((value (if (null? value-option)
(unspecified)
(car value-option)))
(level (car (fluid $command-levels))))
(if (ok-to-proceed? level)
(throw-to-command-level level (lambda () value))
(write-line "No way to proceed from here." (fluid $output-port)))))
(define-command 'proceed "<exp>" "proceed after interrupt or error"
'(&rest value) proceed)
; Scrutinize the condition to ensure that it's safe to return from the
; call to RAISE.
(define (ok-to-proceed? level)
(let ((condition (command-level-condition level)))
(cond ((not condition) #f)
((or (warning? condition)
(interrupt? condition)
(breakpoint? condition))
#t)
((exception? condition)
(let ((opcode (exception-opcode condition)))
(or (= opcode op/global)
(= opcode op/local0)
(= opcode op/set-global!))))
(else #f))))
(define (breakpoint . rest)
(command-loop unspecified (cons 'breakpoint rest)))
(define (breakpoint? condition)
(and (pair? condition) (eq? (car condition) 'breakpoint)))
(define (go-to-level n)
(let ((levels (reverse (fluid $command-levels))))
(if (and (integer? n)
(>= n 0)
(< n (length levels)))
(throw-to-command-level (list-ref levels n)
(lambda ()
(command-loop unspecified #f)))
(write-line "invalid command level" (fluid $output-port)))))
(define-command 'level "<number>" "go to command level"
'(expression) go-to-level)
; Trace and untrace
(define (trace . names)
(if (null? names)
(let ((port (fluid $output-port)))
(write (map car (fluid $traced)) port)
(newline port))
(for-each trace-1 names)))
(define-command 'trace "<name> ..." "trace calls to given procedure(s)"
'(&rest name) trace)
(define (untrace . names)
(if (null? names)
(for-each untrace-1 (map car (fluid $traced)))
(for-each untrace-1 names)))
(define-command 'untrace "<name> ..." "stop tracing calls"
'(&rest name) untrace)
; Trace internals
(define $traced (make-fluid '()))
(define (trace-1 name)
(let* ((env (fluid $package-for-commands))
(proc (environment-ref env name))
(traced (make-traced proc name)))
(set-fluid! $traced
(cons (list name traced proc env)
(fluid $traced)))
(environment-define! env name traced))) ;was environment-set!
; Should be doing clookup's here -- avoid creating new locations
(define (untrace-1 name)
(let ((probe (assq name (fluid $traced))))
(if probe
(let* ((traced (cadr probe))
(proc (caddr probe))
(env (cadddr probe)))
(if (eq? (environment-ref env name) traced)
(environment-set! env name proc)
(write-line "Value changed since :trace; not restoring it."
(fluid $output-port)))
(set-fluid! $traced
(filter (lambda (x)
(not (eq? (car x) name)))
(fluid $traced))))
(write-line "?" (fluid $output-port)))))
(define (make-traced proc name)
(lambda args
(apply-traced proc name args)))
(define (apply-traced proc name args)
(let ((port (fluid $output-port)))
(display "[Enter " port)
(write (cons name (map value->expression args)) port)
(newline port)
(let ((result (apply proc args)))
(display " Leave " port)
(write name port)
(display " " port)
(write (value->expression result) port)
(display "]" port)
(newline port)
result)))
; Timer stuff.
; Assumes that (vm 1 #f) returns process run time in internal timer units
; and (vm-extension 1 #f) returns number of timer units per second.
(define (time-command form)
(let* ((thunk (eval `(lambda () ,form) (fluid $package-for-commands)))
(start-time (vm 1 #f))
(result (thunk))
(stop-time (vm 1 #f))
(dt (- stop-time start-time))
(units-per-second (vm-extension 1 #f))
(delta (quotient (* dt 100) units-per-second))
(port (fluid $output-port)))
(display "Run time: " port)
(write-hundredths delta port)
(display " seconds" port)
(newline port)
(print-command-result result)))
(define (write-hundredths n port)
(write (quotient n 100) port)
(write-char #\. port)
(let ((r (remainder n 100)))
(if (< r 10)
(write-char #\0 port))
(write r port)))
(define-command 'time "<exp>" "measure execution time"
'(expression) time-command)
; User-friendly version (doesn't really belong here)
(define (with-handler h thunk)
(really-with-handler (lambda (condition handlers)
(let-condition-handlers handlers
(lambda ()
(h condition)))
(try-handlers condition handlers))
thunk))