1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-01 04:10:18 +02:00
guile/ice-9/debug.scm
Mikael Djurfeldt e6875011f4 * * debug.scm: *Warning* This feature is a bit premature. I add
it anyway because 1. it is very useful, and, 2. you can start
	making it less premature by complaining to me and by modifying
	the source! :-)
	(trace): Given one or more procedure objects, trace each one.
	Given no arguments, show all traced procedures.
	(untrace): Given one or more procedure objects, untrace each one.
	Given no arguments, untrace all traced procedures.  The tracing in
	Guile have an advantage to most other systems: We don't create new
	procedure objects, but mark the procedure objects themselves.
	This means that also anonymous and internal procedures can be
	traced.

	* boot-9.scm (error-catching-loop): Added handling of apply-frame
	and exit-frame exceptions.

*	* boot-9.scm (assert-repl-prompt, the-prompt-string): Removed.
	(set-repl-prompt!): Setter for repl prompt.
	(scm-style-repl): If prompt is #f, don't prompt; if prompt is a
	string, display it; if prompt is a thunk, call it and display its
	result; otherwise display "> ".
	(Change suggested by Roland Orre <orre@nada.kth.se>.)
1997-02-28 23:11:22 +00:00

214 lines
5.7 KiB
Scheme
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;;;; Copyright (C) 1996 Mikael Djurfeldt
;;;;
;;;; This program is free software; you can redistribute it and/or modify
;;;; it under the terms of the GNU General Public License as published by
;;;; the Free Software Foundation; either version 2, or (at your option)
;;;; any later version.
;;;;
;;;; This program is distributed in the hope that it will be useful,
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;;; GNU General Public License for more details.
;;;;
;;;; You should have received a copy of the GNU General Public License
;;;; along with this software; see the file COPYING. If not, write to
;;;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
;;;;
;;;; The author can be reached at djurfeldt@nada.kth.se
;;;; Mikael Djurfeldt, SANS/NADA KTH, 10044 STOCKHOLM, SWEDEN
;;;;
(define-module #/ice-9/debug)
;;; {Run-time options}
(define names '((debug-options-interface
(debug-options debug-enable debug-disable)
(debug-set!))
(evaluator-traps-interface
(traps trap-enable trap-disable)
(trap-set!))
(read-options-interface
(read-options read-enable read-disable)
(read-set!))
(print-options-interface
(print-options print-enable print-disable)
(print-set!))
))
(define option-name car)
(define option-value cadr)
(define option-documentation caddr)
(define (print-option option)
(display (option-name option))
(if (< (string-length (symbol->string (option-name option))) 8)
(display #\tab))
(display #\tab)
(display (option-value option))
(display #\tab)
(display (option-documentation option))
(newline))
;;; Below follows the macros defining the run-time option interfaces.
;;; *fixme* These should not be macros, but need to be until module
;;; system is improved.
;;;
(define (make-options interface)
`(lambda args
(cond ((null? args) (,interface))
((pair? (car args)) (,interface (car args)) (,interface))
(else (for-each print-option (,interface #t))))))
(define (make-enable interface)
`(lambda flags
(,interface (append flags (,interface)))
(,interface)))
(define (make-disable interface)
`(lambda flags
(let ((options (,interface)))
(for-each (lambda (flag)
(set! options (delq! flag options)))
flags)
(,interface options)
(,interface))))
(define (make-set! interface)
`((name exp)
(,'quasiquote
(begin (,interface (append (,interface)
(list '(,'unquote name)
(,'unquote exp))))
(,interface)))))
(defmacro define-all ()
(cons 'begin
(apply append
(map (lambda (group)
(let ((interface (car group)))
(append (map (lambda (name constructor)
`(define-public ,name
,(constructor interface)))
(cadr group)
(list make-options
make-enable
make-disable))
(map (lambda (name constructor)
`(defmacro-public ,name
,@(constructor interface)))
(caddr group)
(list make-set!)))))
names))))
(define-all)
;;; A fix to get the error handling working together with the module system.
;;;
(variable-set! (builtin-variable 'debug-options) debug-options)
;;; {Trace}
;;;
(define traced-procedures '())
(define-public (trace . args)
(if (null? args)
(nameify traced-procedures)
(begin
(for-each (lambda (proc)
(set-procedure-property! proc 'trace #t)
(if (not (memq proc traced-procedures))
(set! traced-procedures
(cons proc traced-procedures))))
args)
(set! apply-frame-handler trace-entry)
(set! exit-frame-handler trace-exit)
(set! trace-level 0)
(debug-enable 'trace)
(nameify args))))
(define-public (untrace . args)
(if (and (null? args)
(not (null? traced-procedures)))
(apply untrace traced-procedures)
(begin
(for-each (lambda (proc)
(set-procedure-property! proc 'trace #f)
(set! traced-procedures (delq! proc traced-procedures)))
args)
(if (null? traced-procedures)
(debug-disable 'trace))
(nameify args))))
(define (nameify ls)
(map (lambda (proc)
(let ((name (procedure-name proc)))
(or name proc)))
ls))
(define trace-level 0)
(define (trace-entry key cont tail)
(dynamic-wind
(lambda ()
;; We have to protect ourselves against the case that the user
;; has chosen to trace a procedure used in the trace handler.
;; Note that debug-disable is a very slow operation.
;; This is not an ideal solution. *fixme*
(debug-disable 'trace))
(lambda ()
(let ((cep (current-error-port))
(frame (last-stack-frame cont)))
(if (not tail)
(set! trace-level (+ trace-level 1)))
(let indent ((n trace-level))
(cond ((> n 1) (display "| " cep) (indent (- n 1)))))
(display-application frame cep)
(newline cep)
;; It's not necessary to call the continuation since
;; execution will continue if the handler returns
;(cont #f)
))
(lambda ()
(debug-enable 'trace))))
(define (trace-exit key cont retval)
(dynamic-wind
(lambda ()
(debug-disable 'trace))
(lambda ()
(let ((cep (current-error-port)))
(set! trace-level (- trace-level 1))
(let indent ((n trace-level))
(cond ((> n 0) (display "| " cep) (indent (- n 1)))))
(write retval cep)
(newline cep)))
(lambda ()
(debug-enable 'trace))))
(define (display-application frame port)
(display #\[ port)
(display (car (unmemoize (frame-source frame))) port)
(let loop ((args (frame-arguments frame)))
(if (not (null? args))
(begin
(display #\space port)
(write (car args) port)
(loop (cdr args)))))
(display #\] port))
(debug-enable 'debug)
(read-enable 'positions)