Moved the annotator from stepper to mztake, and removed some printfs it was using. We no longer use any code from stepper except for what the annotator uses, and marks.ss.
Updated the doc. svn: r133
This commit is contained in:
parent
65d16858c8
commit
bbfd480ea5
181
collects/mztake/debugger-annotate.ss
Normal file
181
collects/mztake/debugger-annotate.ss
Normal file
|
@ -0,0 +1,181 @@
|
|||
(module debugger-annotate mzscheme
|
||||
|
||||
(require (prefix kernel: (lib "kerncase.ss" "syntax"))
|
||||
(lib "shared.ss" "stepper" "private")
|
||||
(lib "marks.ss" "stepper" "private")
|
||||
(lib "contract.ss"))
|
||||
|
||||
;; (define count 0)
|
||||
|
||||
(provide annotate)
|
||||
|
||||
(define (arglist-bindings arglist-stx)
|
||||
(syntax-case arglist-stx ()
|
||||
[var
|
||||
(identifier? arglist-stx)
|
||||
(list arglist-stx)]
|
||||
[(var ...)
|
||||
(syntax->list arglist-stx)]
|
||||
[(var . others)
|
||||
(cons #'var (arglist-bindings #'others))]))
|
||||
|
||||
(define (annotate stx breakpoints breakpoint-origin break)
|
||||
|
||||
(define (top-level-annotate stx)
|
||||
(kernel:kernel-syntax-case stx #f
|
||||
[(module identifier name (#%plain-module-begin . module-level-exprs))
|
||||
(quasisyntax/loc stx (module identifier name
|
||||
(#%plain-module-begin
|
||||
#,@(map module-level-expr-iterator
|
||||
(syntax->list #'module-level-exprs)))))]
|
||||
[else-stx
|
||||
(general-top-level-expr-iterator stx)]))
|
||||
|
||||
(define (module-level-expr-iterator stx)
|
||||
(kernel:kernel-syntax-case stx #f
|
||||
[(provide . provide-specs)
|
||||
stx]
|
||||
[else-stx
|
||||
(general-top-level-expr-iterator stx)]))
|
||||
|
||||
(define (general-top-level-expr-iterator stx)
|
||||
(kernel:kernel-syntax-case stx #f
|
||||
[(define-values (var ...) expr)
|
||||
#`(define-values (var ...)
|
||||
#,(annotate #`expr (syntax->list #`(var ...)) #t))]
|
||||
[(define-syntaxes (var ...) expr)
|
||||
stx]
|
||||
[(begin . top-level-exprs)
|
||||
(quasisyntax/loc stx (begin #,@(map (lambda (expr)
|
||||
(module-level-expr-iterator expr))
|
||||
(syntax->list #'top-level-exprs))))]
|
||||
[(require . require-specs)
|
||||
stx]
|
||||
[(require-for-syntax . require-specs)
|
||||
stx]
|
||||
[else
|
||||
(annotate stx '() #f)]))
|
||||
|
||||
(define (annotate expr bound-vars is-tail?)
|
||||
|
||||
(define (let/rec-values-annotator letrec?)
|
||||
(kernel:kernel-syntax-case expr #f
|
||||
[(label (((var ...) rhs) ...) . bodies)
|
||||
(let* ([new-bindings (apply append (map syntax->list (syntax->list #`((var ...) ...))))]
|
||||
[new-rhs (if letrec?
|
||||
(map (lambda (expr) (annotate expr (append new-bindings bound-vars) #f))
|
||||
(syntax->list #`(rhs ...)))
|
||||
(map (lambda (expr) (annotate expr bound-vars #f))
|
||||
(syntax->list #`(rhs ...))))]
|
||||
[last-body (car (reverse (syntax->list #`bodies)))]
|
||||
[all-but-last-body (reverse (cdr (reverse (syntax->list #`bodies))))]
|
||||
[bodies (append (map (lambda (expr) (annotate expr (append new-bindings bound-vars) #f))
|
||||
all-but-last-body)
|
||||
(list (annotate last-body (append new-bindings bound-vars) is-tail?)))])
|
||||
(with-syntax ([(new-rhs/trans ...) new-rhs])
|
||||
(quasisyntax/loc expr
|
||||
(label (((var ...) new-rhs/trans) ...)
|
||||
#,@bodies))))]))
|
||||
|
||||
(define (lambda-clause-annotator clause)
|
||||
(kernel:kernel-syntax-case clause #f
|
||||
[(arg-list . bodies)
|
||||
(let* ([new-bound-vars (append (arglist-bindings #`arg-list) bound-vars)]
|
||||
[new-bodies (let loop ([bodies (syntax->list #`bodies)])
|
||||
(if (equal? '() (cdr bodies))
|
||||
(list (annotate (car bodies) new-bound-vars #t))
|
||||
(cons (annotate (car bodies) new-bound-vars #f)
|
||||
(loop (cdr bodies)))))])
|
||||
(quasisyntax/loc clause
|
||||
(arg-list #,@new-bodies)))]))
|
||||
|
||||
(define (break-wrap debug-info annotated)
|
||||
#`(begin
|
||||
(#,break (current-continuation-marks) 'debugger-break #,debug-info)
|
||||
#,annotated))
|
||||
|
||||
(define annotated
|
||||
(kernel:kernel-syntax-case expr #f
|
||||
[var-stx (identifier? (syntax var-stx)) expr]
|
||||
|
||||
[(lambda . clause)
|
||||
(quasisyntax/loc expr
|
||||
(lambda #,@(lambda-clause-annotator #`clause)))]
|
||||
|
||||
[(case-lambda . clauses)
|
||||
(quasisyntax/loc expr
|
||||
(case-lambda #,@(map lambda-clause-annotator (syntax->list #`clauses))))]
|
||||
|
||||
[(if test then)
|
||||
(quasisyntax/loc expr (if #,(annotate #`test bound-vars #f)
|
||||
#,(annotate #`then bound-vars is-tail?)))]
|
||||
|
||||
[(if test then else)
|
||||
(quasisyntax/loc expr (if #,(annotate #`test bound-vars #f)
|
||||
#,(annotate #`then bound-vars is-tail?)
|
||||
#,(annotate #`else bound-vars is-tail?)))]
|
||||
|
||||
[(begin . bodies)
|
||||
(letrec ([traverse
|
||||
(lambda (lst)
|
||||
(if (and (pair? lst) (equal? '() (cdr lst)))
|
||||
`(,(annotate (car lst) bound-vars is-tail?))
|
||||
(cons (annotate (car lst) bound-vars #f)
|
||||
(traverse (cdr lst)))))])
|
||||
(quasisyntax/loc expr (begin #,@(traverse (syntax->list #`bodies)))))]
|
||||
|
||||
[(begin0 . bodies)
|
||||
(quasisyntax/loc expr (begin0 #,@(map (lambda (expr)
|
||||
(annotate expr bound-vars #f))
|
||||
(syntax->list #`bodies))))]
|
||||
|
||||
[(let-values . clause)
|
||||
(let/rec-values-annotator #f)]
|
||||
|
||||
[(letrec-values . clause)
|
||||
(let/rec-values-annotator #t)]
|
||||
|
||||
[(set! var val)
|
||||
(quasisyntax/loc expr (set! var #,(annotate #`val bound-vars #f)))]
|
||||
|
||||
[(quote _) expr]
|
||||
|
||||
[(quote-syntax _) expr]
|
||||
|
||||
;; FIXME: we have to think harder about this
|
||||
[(with-continuation-mark key mark body)
|
||||
(quasisyntax/loc expr (with-continuation-mark key
|
||||
#,(annotate #`mark bound-vars #f)
|
||||
#,(annotate #`body bound-vars is-tail?)))]
|
||||
|
||||
[(#%app . exprs)
|
||||
(let ([subexprs (map (lambda (expr)
|
||||
(annotate expr bound-vars #f))
|
||||
(syntax->list #`exprs))])
|
||||
(if is-tail?
|
||||
(quasisyntax/loc expr #,subexprs)
|
||||
(wcm-wrap (make-debug-info expr bound-vars bound-vars 'normal #f)
|
||||
(quasisyntax/loc expr #,subexprs))))]
|
||||
|
||||
[(#%datum . _) expr]
|
||||
|
||||
[(#%top . var) expr]
|
||||
|
||||
[else (error 'expr-syntax-object-iterator "unknown expr: ~a"
|
||||
(syntax-object->datum expr))]))
|
||||
|
||||
;; (set! count (+ count 1))
|
||||
;; (if (= (modulo count 100) 0)
|
||||
;; (fprintf (current-error-port) "syntax-source: ~v\nsyntax-position: ~v\n" (syntax-source expr) (syntax-position expr)))
|
||||
|
||||
|
||||
(if (and (eq? (syntax-source expr) breakpoint-origin)
|
||||
(memq (- (syntax-position expr) 1) ; syntax positions start at one.
|
||||
breakpoints))
|
||||
(break-wrap (make-debug-info expr bound-vars bound-vars 'at-break #f)
|
||||
annotated)
|
||||
annotated))
|
||||
|
||||
(top-level-annotate stx)))
|
||||
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
(module debugger-model mzscheme
|
||||
(require (lib "unit.ss")
|
||||
(lib "mred.ss" "mred")
|
||||
(lib "debugger-annotate.ss" "stepper/private")
|
||||
(lib "marks.ss" "stepper/private")
|
||||
"../debugger-annotate.ss"
|
||||
"mztake-structs.ss"
|
||||
"private/load-annotator.ss"
|
||||
"private/more-useful-code.ss")
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
About MzTake
|
||||
|
||||
_MzTake_ is a scripted debugger for Plt Scheme. It
|
||||
_MzTake_ is a scripted debugger for PLT Scheme. It
|
||||
provides facilities for monitoring the execution of a
|
||||
target program as it unfolds. In the future, MzTake
|
||||
will also let you interact with a paused program and
|
||||
|
@ -19,15 +19,16 @@ events, concisely without using callbacks, for example:
|
|||
(debug-process p ("highway.ss" [values-of-speed 3 5 bind 'speed]))
|
||||
(history-b 10 values-of-speed)
|
||||
|
||||
This MzTake script executes the file first-demo.ss in the
|
||||
"module" language, and installs a watch point for the
|
||||
variable "x" on line 5 (at column 8). This watch point
|
||||
is named "values-of-speed", which is in turn used in the
|
||||
This MzTake script executes the file highway.ss in the
|
||||
"module" language, and installs a watch point (also used
|
||||
interchangeably as 'trace point') for the variable "speed"
|
||||
on line 5 (at column 8). This watch point is named
|
||||
"values-of-speed", which is in turn used in the
|
||||
call to "history-b". Here, "history-b" returns a list
|
||||
of the last ten values of the variable x seen on line
|
||||
5, over time. DrScheme displays this list in the
|
||||
interaction pane, where you can use it to confirm (or
|
||||
refute!) that your program is working correctly.
|
||||
of the last ten values of the variable "speed"
|
||||
seen on line 5, over time. DrScheme displays this list
|
||||
in the interaction pane, where you can use it to confirm
|
||||
(or refute!) that your program is working correctly.
|
||||
|
||||
MzTake scripts are powerful tool for building test
|
||||
suites. Whereas typical test cases can only assert that
|
||||
|
@ -35,10 +36,10 @@ the result of a computation is correct, MzTake scripts
|
|||
can break open an execution and record its inner state
|
||||
and compute with it, allowing you to confirm that the
|
||||
intermediate steps that lead to a correct answer were
|
||||
also correct. In the example below, we test that x
|
||||
always is less than 5:
|
||||
also correct. In the example below, we test that the
|
||||
lsat 10 speeds are all less than 55:
|
||||
|
||||
(map (lambda (an-x) (if (< an-x 55) 'ok 'too-fast!!))
|
||||
(map (lambda (a-speed) (if (< a-speed 55) 'ok 'too-fast!!))
|
||||
(history-b 10 values-of-speed))
|
||||
|
||||
Finally, FrTime provides a rich animation
|
||||
|
@ -59,11 +60,12 @@ automatically, if found. Make sure you select the
|
|||
"MzTake" language from DrScheme's language dialog, in
|
||||
the "Experimental Languages" section. If your language
|
||||
dialog does not contain "MzTake", you can install it by
|
||||
downloading the ".plt" distribution file, then
|
||||
selecting "Install .plt File..." from the "File" menu
|
||||
downloading the ".PLT" distribution file, then
|
||||
selecting "Install .PLT File..." from the "File" menu
|
||||
in DrScheme.
|
||||
|
||||
http://www.cs.brown.edu/~gmarceau/files/mztake.plt
|
||||
http://www.cs.brown.edu/~gmarceau/files/mztake.PLT
|
||||
|
||||
|
||||
|
||||
============================================================
|
||||
|
@ -80,12 +82,11 @@ and clicking the "Run" button.
|
|||
demos/sine/sine-test.ss - plots values extracted from the
|
||||
running program
|
||||
|
||||
demos/montecarlo/montecarlo-test.ss - visualizes montecarlo integration used
|
||||
to evaluate the value of pi
|
||||
demos/montecarlo/montecarlo-test.ss - visualizes Monte Carlo integration
|
||||
used to derive the value of pi
|
||||
|
||||
demos/random/random-Xs-test.ss - tests the quality of Scheme's random
|
||||
number generator
|
||||
|
||||
number generator with a histogram
|
||||
|
||||
|
||||
|
||||
|
@ -95,7 +96,7 @@ and clicking the "Run" button.
|
|||
|
||||
In order to use MzTake, you will first have to learn
|
||||
the FrTime language. FrTime's own "doc.txt" explains
|
||||
how to use time varying values and event streams, and
|
||||
how to use time-varying values and event streams, and
|
||||
also describes the many functions that operate on them.
|
||||
|
||||
MzTake itself defines the following functions:
|
||||
|
@ -109,7 +110,7 @@ _Installing Watch Points_
|
|||
where trace-clause is either
|
||||
|
||||
<1> [trace-name line-number column-number break]
|
||||
<2> [trace-name line-number column-number bind variable-name]
|
||||
<2> [trace-name line-number column-number bind 'variable-name]
|
||||
|
||||
or
|
||||
|
||||
|
@ -118,12 +119,17 @@ _Installing Watch Points_
|
|||
mztake-process installs watch points in one or many
|
||||
files, as indicated by the trace-clauses. The
|
||||
target-filename can be any file specification
|
||||
accepted the standard "require" syntax for
|
||||
modules. For instance, to specify a target file
|
||||
using an absolute path, use requires's "file"
|
||||
specifier:
|
||||
accepted by the standard "require" syntax for
|
||||
modules:
|
||||
|
||||
(mztake-process p [(file "/home/me/test.ss") [brk 10 7 break]])
|
||||
* Absolute path:
|
||||
(mztake-process p [(file "/home/me/test.ss") [brk 10 7 break]])
|
||||
|
||||
* Relative path:
|
||||
(mztake-process p ["../test.ss" [brk 10 7 break]])
|
||||
|
||||
* Library path:
|
||||
(mztake-process p [(lib “test.ss” “file-lib”) [brk 10 7 break]])
|
||||
|
||||
Each target-filename should define a module (MzTake
|
||||
does not support debugging top-level
|
||||
|
@ -132,10 +138,17 @@ _Installing Watch Points_
|
|||
object. That object can be passed to the process
|
||||
functions documented in the next section. In
|
||||
particular, start/resume is a function that consumes
|
||||
a MzTake process and actually lunches its
|
||||
execution. That is, start/resume calls "require" on
|
||||
the first of the target-files given in the call to
|
||||
mztake-process.
|
||||
a MzTake process and starts its execution and debugging.
|
||||
That is, start/resume calls a "require" on the *first* of
|
||||
the target-files (the main-module) given in the call
|
||||
to mztake-process, assuming there will be side-effects
|
||||
that run the program in the main-module.
|
||||
|
||||
The rest of the files for a mztake-process are typically
|
||||
modules used *by* the main-module, allowing you to see
|
||||
what is going on deeper than the main module. For instance,
|
||||
you want to debug my-vector.ss in the context of
|
||||
my-vector-test-cases.ss using functions from my-vector.ss.
|
||||
|
||||
For each trace-clause in the call to mztake-process,
|
||||
the trace-name is a variable name bound at the
|
||||
|
@ -146,11 +159,11 @@ _Installing Watch Points_
|
|||
that event depends on which of the three kinds of
|
||||
trace-clause was used, as follow:
|
||||
|
||||
<1> the value of the event is #t
|
||||
<1> the value of the event is #t (a "break" trace)
|
||||
|
||||
<2> the value of the event is the value of variable-name,
|
||||
in the target program, at the location of the
|
||||
watch point.
|
||||
watch point (a "bind" trace).
|
||||
|
||||
<3> the value of the event is a list containing one
|
||||
element for each variable name given. The value
|
||||
|
@ -177,59 +190,65 @@ _Installing Watch Points_
|
|||
|
||||
_Operations on MzTake Processes_
|
||||
|
||||
The following functions operate on MzTake processes:
|
||||
The following functions operate on MzTake processes, and
|
||||
can be used interactively in the interactions pane.
|
||||
|
||||
> (start/resume process)
|
||||
> (start/resume process-name)
|
||||
|
||||
Initiate the execution of the process, under the
|
||||
monitoring by MzTake. In general, you should install
|
||||
your monitoring before calling start/resume,
|
||||
otherwise you script may miss events from the
|
||||
beginning of the evaluation.
|
||||
Start the execution and monitoring of the mztake-process,
|
||||
process-name. If the process given to start/resume is already
|
||||
running, and was paused with the function "pause" (below),
|
||||
start/resume resumes its execution.
|
||||
|
||||
If the process given to start/resume is already
|
||||
running was paused with the function "pause", below,
|
||||
start/resume resume its execution.
|
||||
Script statements are executed top-down, sequentially.
|
||||
In general, you want to call start/resume at the end of
|
||||
the script, or in the interactions pane after you
|
||||
started the script -- in either case, after you have done
|
||||
all processing. Otherwise your script may miss events
|
||||
from the beginning of the evaluation.
|
||||
|
||||
> (pause process)
|
||||
|
||||
Suspends the execution of the given mztake
|
||||
process. Use start/resume to resume execution.
|
||||
|
||||
> (kill process)
|
||||
|
||||
Kills the target process and releases all ressources
|
||||
it used.
|
||||
Kills the target process and releases all resources
|
||||
it used -- you cannot start/resume after a kill.
|
||||
|
||||
> (kill-all)
|
||||
|
||||
kill-all kills all the processes currently running
|
||||
under MzTake.
|
||||
|
||||
> (pause process)
|
||||
|
||||
Suspends the execution of the given debugger
|
||||
process. Use start/resume to resume execution.
|
||||
under MzTake - use this when it seems a process is
|
||||
out of control and needs to be stopped immediately.
|
||||
Has the same effect of calling kill on each process
|
||||
you defined and start/resume'd in the script.
|
||||
|
||||
> (process:exceptions process)
|
||||
|
||||
Returns an event stream. If the target process
|
||||
throws an uncaught exception, the exception will
|
||||
appear of this stream.
|
||||
appear on this stream.
|
||||
|
||||
> (process:runtime/seconds process)
|
||||
|
||||
Returns a FrTime time-varying value which count the
|
||||
Returns a FrTime time-varying value which counts the
|
||||
number of seconds elapsed in the execution of the
|
||||
given process (not counting time spent suspended by
|
||||
"pause")
|
||||
"pause"). Includes garbage-collection time.
|
||||
|
||||
> (process:runtime/milliseconds process)
|
||||
|
||||
Returns a FrTime time-varying value which count the
|
||||
number of milliseconds elapsed in the execution of the
|
||||
given process (not counting time spent suspended by
|
||||
"pause")
|
||||
"pause"). Includes garbage-collection time.
|
||||
|
||||
> (process:exited? process)
|
||||
|
||||
Return a time-varying boolean value which becomes
|
||||
true after the given MzTake process exited.
|
||||
Return a time-varying Boolean value which becomes
|
||||
true after the given MzTake process exited/killed.
|
||||
|
||||
|
||||
_Useful Functions for Time-Varying Values_
|
||||
|
@ -247,20 +266,24 @@ that are particularly useful when debugging.
|
|||
|
||||
> (count-e stream)
|
||||
|
||||
Counts number of event pings on an eventstream.
|
||||
Counts number of event pings on an eventstream,
|
||||
regardless of whether the value changes or not
|
||||
(used often with "break" traces).
|
||||
|
||||
> (count-b b)
|
||||
|
||||
Counts number of times a behavior updates/changes
|
||||
Counts number of times a behavior's value
|
||||
updates/changes (used often with "bind" traces).
|
||||
|
||||
> (sequence-match? seq evs)
|
||||
|
||||
Matches a sequence of items in a list to the history
|
||||
of event pings, on the event stream evs.
|
||||
|
||||
> (printf-b format arg ...)
|
||||
> (printf-b format-string arg ...)
|
||||
|
||||
Display the value of the behaviors with the given format
|
||||
Displays the value of the behaviors with the given format,
|
||||
using "~a" just like in Scheme's "format" function.
|
||||
|
||||
|
||||
============================================================
|
||||
|
@ -274,7 +297,7 @@ Known Issues
|
|||
(define x 12)
|
||||
(->let ->(->[>x (add1 x)]) x)
|
||||
do *not* produce any values for the bindings, just an empty
|
||||
eventstream -- particularily in "let"s.
|
||||
eventstream -- particularly in "let"s.
|
||||
|
||||
Legal (recommended) bind points ("->"):
|
||||
(define x 12)
|
||||
|
@ -293,8 +316,8 @@ Known Issues
|
|||
and a breakpoint, you may want the breakpoint to happen
|
||||
before the bind happens.
|
||||
|
||||
- For now, the hack is to bind one at ->(code...)
|
||||
and the other (code...->(more-code...))
|
||||
- For now, the hack is to bind one at (“->”) ->(code...)
|
||||
and the other at (code...->(more-code...))
|
||||
immediately following at the next open parentheses.
|
||||
Often, not much happens on the same line between two
|
||||
valid trace points, so this gives you a definite order.
|
||||
|
@ -304,18 +327,27 @@ Known Issues
|
|||
*with* traces on them -- other 'require'd modules will work
|
||||
as expected.
|
||||
|
||||
* Error handling is not perfect -- e.g., the little "bug"
|
||||
buttons on syntax errors don't reference the correct code.
|
||||
However, the messages that are printed are as accurate as
|
||||
possible.
|
||||
|
||||
* process:running? tells you if the process is currently,
|
||||
actively, running. It might be useful to you, and will
|
||||
be in the next release.
|
||||
|
||||
|
||||
============================================================
|
||||
|
||||
Misc. Tips
|
||||
Tips and Tricks
|
||||
|
||||
* You may want to bind more than one variable at a certain point
|
||||
so that you only get one change event -- otherwise, you will
|
||||
get multiple change events even if at the same tracepoint
|
||||
get multiple change events even if at the same trace point
|
||||
(see Known Issues).
|
||||
|
||||
For instance, if you trace 'x and 'y seperately:
|
||||
'x 'y are up to date, then 'x updates, 'y is out of date,
|
||||
For instance, if you trace 'x and 'y separately:
|
||||
'x and 'y are up to date, then 'x updates, 'y is out of date,
|
||||
then 'y updates, and both are up to date.
|
||||
|
||||
But code that draws x and y locations will draw in two places,
|
||||
|
@ -363,11 +395,11 @@ should enable new debugging approaches that were not
|
|||
possible (easily) before. We are eager to hear about
|
||||
how you are using MzTake.
|
||||
|
||||
Guillaume Marceau: gmarceau@cs.brown.edu
|
||||
Jonathan Spiro: jspiro@cs.brown.edu
|
||||
Shriram Khrisnamurthy: sk@cs.brown.edu
|
||||
Guillaume Marceau: gmarceau@cs.brown.edu
|
||||
Shriram Krishnamurthi: sk@cs.brown.edu
|
||||
|
||||
|
||||
Icons for MzTake come from the Gnome Project: Nautilus
|
||||
Emblems, used under the GPL lisence.
|
||||
Emblems, used under the GPL license.
|
||||
http://jimmac.musichall.cz/ikony.php3
|
||||
|
|
|
@ -336,7 +336,7 @@ TESTING/CAPABILITIES------------------------------------------------------------
|
|||
; run the process
|
||||
(thread-wait (thread (lambda () (run))))
|
||||
; program terminates
|
||||
(kill process)
|
||||
(stop process)
|
||||
(print-info (format "process terminated: ~a" (main-client-name process))))))
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user