]> git.donarmstrong.com Git - lilypond.git/blobdiff - guile18/ice-9/debugger/utils.scm
Import guile-1.8 as multiple upstream tarball component
[lilypond.git] / guile18 / ice-9 / debugger / utils.scm
diff --git a/guile18/ice-9/debugger/utils.scm b/guile18/ice-9/debugger/utils.scm
new file mode 100644 (file)
index 0000000..dfef25b
--- /dev/null
@@ -0,0 +1,203 @@
+
+(define-module (ice-9 debugger utils)
+  #:use-module (ice-9 debugger state)
+  #:export (display-position
+           source-position
+           write-frame-args-long
+           write-frame-index-long
+           write-frame-short/expression
+           write-frame-short/application
+           write-frame-long
+           write-state-long
+           write-state-short))
+
+;;; Procedures in this module print information about a stack frame.
+;;; The available information is as follows.
+;;;
+;;; * Source code location.
+;;;
+;;; For an evaluation frame, this is the location recorded at the time
+;;; that the expression being evaluated was read, if the 'positions
+;;; read option was enabled at that time.
+;;;
+;;; For an application frame, I'm not yet sure.  Some applications
+;;; seem to have associated source expressions.
+;;;
+;;; * Whether frame is still evaluating its arguments.
+;;;
+;;; Only applies to an application frame.  For example, an expression
+;;; like `(+ (* 2 3) 4)' goes through the following stages of
+;;; evaluation.
+;;;
+;;; (+ (* 2 3) 4)       -- evaluation
+;;; [+ ...              -- application; the car of the evaluation
+;;;                        has been evaluated and found to be a
+;;;                        procedure; before this procedure can
+;;;                        be applied, its arguments must be evaluated
+;;; [+ 6 ...            -- same application after evaluating the
+;;;                        first argument
+;;; [+ 6 4]             -- same application after evaluating all
+;;;                        arguments
+;;; 10                  -- result
+;;;
+;;; * Whether frame is real or tail-recursive.
+;;;
+;;; If a frame is tail-recursive, its containing frame as shown by the
+;;; debugger backtrace doesn't really exist as far as the Guile
+;;; evaluator is concerned.  The effect of this is that when a
+;;; tail-recursive frame returns, it looks as though its containing
+;;; frame returns at the same time.  (And if the containing frame is
+;;; also tail-recursive, _its_ containing frame returns at that time
+;;; also, and so on ...)
+;;;
+;;; A `real' frame is one that is not tail-recursive.
+
+
+(define (write-state-short state)
+  (let* ((frame (stack-ref (state-stack state) (state-index state)))
+        (source (frame-source frame))
+        (position (and source (source-position source))))
+    (format #t "Frame ~A at " (frame-number frame))
+    (if position
+       (display-position position)
+       (display "unknown source location"))
+    (newline)
+    (write-char #\tab)
+    (write-frame-short frame)
+    (newline)))
+
+(define (write-state-short* stack index)
+  (write-frame-index-short stack index)
+  (write-char #\space)
+  (write-frame-short (stack-ref stack index))
+  (newline))
+
+(define (write-frame-index-short stack index)
+  (let ((s (number->string (frame-number (stack-ref stack index)))))
+    (display s)
+    (write-char #\:)
+    (write-chars #\space (- 4 (string-length s)))))
+
+(define (write-frame-short frame)
+  (if (frame-procedure? frame)
+      (write-frame-short/application frame)
+      (write-frame-short/expression frame)))
+
+(define (write-frame-short/application frame)
+  (write-char #\[)
+  (write (let ((procedure (frame-procedure frame)))
+          (or (and (procedure? procedure)
+                   (procedure-name procedure))
+              procedure)))
+  (if (frame-evaluating-args? frame)
+      (display " ...")
+      (begin
+       (for-each (lambda (argument)
+                   (write-char #\space)
+                   (write argument))
+                 (frame-arguments frame))
+       (write-char #\]))))
+
+;;; Use builtin function instead:
+(set! write-frame-short/application
+      (lambda (frame)
+       (display-application frame (current-output-port) 12)))
+
+(define (write-frame-short/expression frame)
+  (write (let* ((source (frame-source frame))
+               (copy (source-property source 'copy)))
+          (if (pair? copy)
+              copy
+              (unmemoize-expr source)))))
+\f
+(define (write-state-long state)
+  (let ((index (state-index state)))
+    (let ((frame (stack-ref (state-stack state) index)))
+      (write-frame-index-long frame)
+      (write-frame-long frame))))
+
+(define (write-frame-index-long frame)
+  (display "Stack frame: ")
+  (write (frame-number frame))
+  (if (frame-real? frame)
+      (display " (real)"))
+  (newline))
+
+(define (write-frame-long frame)
+  (if (frame-procedure? frame)
+      (write-frame-long/application frame)
+      (write-frame-long/expression frame)))
+
+(define (write-frame-long/application frame)
+  (display "This frame is an application.")
+  (newline)
+  (if (frame-source frame)
+      (begin
+       (display "The corresponding expression is:")
+       (newline)
+       (display-source frame)
+       (newline)))
+  (display "The procedure being applied is: ")
+  (write (let ((procedure (frame-procedure frame)))
+          (or (and (procedure? procedure)
+                   (procedure-name procedure))
+              procedure)))
+  (newline)
+  (display "The procedure's arguments are")
+  (if (frame-evaluating-args? frame)
+      (display " being evaluated.")
+      (begin
+       (display ": ")
+       (write (frame-arguments frame))))
+  (newline))
+
+(define (display-source frame)
+  (let* ((source (frame-source frame))
+        (copy (source-property source 'copy)))
+    (cond ((source-position source)
+          => (lambda (p) (display-position p) (display ":\n"))))
+    (display "  ")
+    (write (or copy (unmemoize-expr source)))))
+
+(define (source-position source)
+  (let ((fname (source-property source 'filename))
+       (line (source-property source 'line))
+       (column (source-property source 'column)))
+    (and fname
+        (list fname line column))))
+
+(define (display-position pos)
+  (format #t "~A:~D:~D" (car pos) (+ 1 (cadr pos)) (+ 1 (caddr pos))))
+
+(define (write-frame-long/expression frame)
+  (display "This frame is an evaluation.")
+  (newline)
+  (display "The expression being evaluated is:")
+  (newline)
+  (display-source frame)
+  (newline))
+
+(define (write-frame-args-long frame)
+  (if (frame-procedure? frame)
+      (let ((arguments (frame-arguments frame)))
+       (let ((n (length arguments)))
+         (display "This frame has ")
+         (write n)
+         (display " argument")
+         (if (not (= n 1))
+             (display "s"))
+         (write-char (if (null? arguments) #\. #\:))
+         (newline))
+       (for-each (lambda (argument)
+                   (display "  ")
+                   (write argument)
+                   (newline))
+                 arguments))
+      (begin
+       (display "This frame is an evaluation frame; it has no arguments.")
+       (newline))))
+
+(define (write-chars char n)
+  (do ((i 0 (+ i 1)))
+      ((>= i n))
+    (write-char char)))