732 lines
28 KiB
Plaintext
732 lines
28 KiB
Plaintext
|
|
|
|
============================================================
|
|
|
|
About MzTake
|
|
|
|
_MzTake_ is a _scripted debugger_ for PLT Scheme. It helps
|
|
programmers monitor the execution of a target program as it
|
|
unfolds (and optionally pause or resume its execution!). MzTake
|
|
gives you the power to easily write real programs that debug real
|
|
programs. You are no longer limited to a tool chest of buttons
|
|
like "add breakpoint", "step-next", "step-into", and "step-over".
|
|
|
|
MzTake scripts are written in the FrTime programming
|
|
language, which is bundled with DrScheme. FrTime supports the
|
|
implementation of reactive systems in a functional style.
|
|
The key abstraction it adds is a type of value called a 'signal',
|
|
which can change over time. FrTime infers dataflow dependencies
|
|
between signals and automatically recomputes them when necessary.
|
|
|
|
With signals (implemented as "event streams" and "behaviors"),
|
|
it is possible to respond to outside events concisely (without
|
|
using callbacks). Consider a MzTake script to monitor the
|
|
behavior of the program "highway.ss", in the demos directory
|
|
of the MzTake collection:
|
|
|
|
(define-mztake-process radar-program
|
|
("highway.ss" [values-of-speed 3 4 bind 'speed]))
|
|
(printf-b "current speed: ~a" (hold values-of-speed))
|
|
(start/resume radar-program)
|
|
|
|
This code executes a target module in the file "highway.ss"
|
|
after installing a _trace point_ (also known as a
|
|
_watch point_) just before the Scheme expression on the fourth
|
|
column of the third line of "highway.ss". VALUES-OF-SPEED
|
|
is a FrTime event stream that always contains the *current*
|
|
value (and potentially every past value) of the variable named
|
|
SPEED, as it is bound to the values corresponding to that
|
|
syntactic location.
|
|
|
|
PRINTF-B works like Scheme's PRINTF function, consuming a
|
|
format-string and fill-values, printing the result in
|
|
DrScheme's interaction pane. Whereas PRINTF accumulates
|
|
outdated text on the screen, PRINTF-B will replace old text
|
|
with updated text if any of the fill-values change. In this
|
|
invocation, it prints the current speed to screen, throughout
|
|
the execution of "highway.ss".
|
|
|
|
MzTake scripts are also powerful tools for building external
|
|
test suites. Whereas typical test cases may only assert that
|
|
the result of a computation is correct, MzTake scripts
|
|
can dynamically break open an execution, record inner state,
|
|
and *compute* with it. This allows you to confirm that the
|
|
intermediate steps which lead to a correct answer were
|
|
also correct. In the example below, we use a version of map
|
|
that operates over events in an event stream, instead of
|
|
elements in a list. We assert that all recorded speeds are
|
|
less than 55, otherwise we raise an exception:
|
|
|
|
(map-e (lambda (a-speed)
|
|
(when (>= a-speed 55) (raise 'too-fast!!)))
|
|
values-of-speed)
|
|
|
|
Of course, like most test suites, this only tells you
|
|
something went wrong. Perhaps knowing the last ten speeds that
|
|
led to this would prove useful. You could PRINTF the value
|
|
onto a new line each time, but after ten updates the screen
|
|
is already starting to fill up with information -- we are
|
|
only interested in the last ten speeds, after all.
|
|
One possible solution:
|
|
|
|
(printf-b "last ten speeds: ~a" (history-b 10 values-of-speed))
|
|
(map-e (lambda (a-speed)
|
|
(when (>= a-speed 55) (raise 'too-fast!!)))
|
|
values-of-speed)
|
|
|
|
HISTORY-B consumes a number and an event stream (VALUES-OF-SPEED),
|
|
returning a FrTime behavior containing a FIFO ordered list of
|
|
the last ten values emitted on that event stream. In this case,
|
|
HISTORY-B maintains a list of the ten most recent SPEEDS seen
|
|
on VALUES-OF-SPEED (up until the exception is raised). Though
|
|
this is is an improvement, we still can't *use* that list as
|
|
data to see what led to the exception. One possible solution:
|
|
|
|
(define last-ten (history-b 10 values-of-speed))
|
|
(printf-b "last ten speeds: ~a" last-ten)
|
|
(map-e (lambda (a-speed)
|
|
(when (>= a-speed 55) (pause radar-program)))
|
|
values-of-speed)
|
|
|
|
MzTake allows you to "pause" a target program anytime during
|
|
execution. Once paused, it becomes trivial to interactively
|
|
explore and compute with script variables (such as LAST-TEN)
|
|
in the interaction pane. Once satisfied, you can easily resume
|
|
execution by typing "(start/resume radar-program)", or end it
|
|
with "(kill radar-program)", where RADAR-PROGRAM is any MzTake
|
|
process.
|
|
|
|
Finally, FrTime provides a rich animation library. Combined
|
|
with the MzTake debugger, it takes only a few lines to animate
|
|
your algorithms and see them in action, easily letting you
|
|
confirm (or refute!) that they are working correctly.
|
|
|
|
(display-shapes (make-speed-gauge (hold values-of-speed)))
|
|
|
|
|
|
============================================================
|
|
|
|
Installing MzTake
|
|
|
|
MzTake is a DrScheme tool distributed as a self-installing
|
|
".PLT" file from the following web site:
|
|
|
|
http://www.cs.brown.edu/research/plt/software/mztake/
|
|
|
|
MzTake requires PLT Scheme v208 and higher.
|
|
|
|
|
|
============================================================
|
|
|
|
Demos
|
|
|
|
If you installed MzTake using the .PLT distribution, you can
|
|
find the demos in the following directories:
|
|
|
|
On Linux:
|
|
~/.plt-scheme/208/collects/mztake/demos
|
|
|
|
On Windows (typically):
|
|
C:\Documents and Settings\Jono\Application Data\PLT Scheme\208\collects\mztake\demos
|
|
|
|
where "Jono" is your username, and "208" is the version of
|
|
DrScheme you are running.
|
|
|
|
The demos directory contains a sub-directory for each of the demos.
|
|
For instance, the highway directory contains "highway.ss" and
|
|
"highway-mztake.ss". To run this demo, switch to the "MzTake" language
|
|
level from the "Experimental Languages" section of DrScheme's language
|
|
dialog, load "highway-mztake.ss", and click "Run". What you see is
|
|
generated by the debugging script. Each demo directory contains
|
|
the following two files: one is the program being debugged
|
|
(named after the directory), and the other is a file ending
|
|
in "...-mztake.ss" (the MzTake script).
|
|
|
|
The demos are in order of increasing complexity. When you open
|
|
them in DrScheme, don't let the amount of text overwhelm you --
|
|
the scripts themselves are only a few lines of code. However, the
|
|
commenting is *extensive* to aid even a FrTime novice who has never
|
|
written a FrTime script before!
|
|
|
|
./highway/highway-mztake.ss - The program simulates a very simple
|
|
speedometer, and the MzTake script
|
|
monitors it.
|
|
|
|
./sine/sine-mztake.ss - Plots values extracted from a program
|
|
which generates coordinates for a
|
|
single sine wave.
|
|
|
|
./montecarlo/montecarlo-mztake.ss - Visualizes the Monte Carlo integration
|
|
("throwing darts at a dartboard") used
|
|
to derive the value of pi.
|
|
|
|
./random/random-mztake.ss - Tests the quality of Scheme's random
|
|
number generator with a histogram.
|
|
|
|
./exception/exception-mztake.ss - Demonstrates how MzTake catches exceptions.
|
|
|
|
./first-class/first-class-mztake.ss - Demonstrates how you can add multiple traces
|
|
to the same variable in a file to `record'
|
|
its evolution, and how you can trace first-class
|
|
functions, such as those passed to map.
|
|
|
|
./djikstra/dijkstra-mztake.ss - Debugs a buggy implementation of
|
|
Dijkstra's algorithm
|
|
|
|
If you have just downloaded MzTake and are coming directly
|
|
to the demos, know that once started, you can easily end
|
|
execution of a debugger scipt by typing "(kill p)" into the
|
|
Interactions window (freeing up resources). You can also pause
|
|
a script with "(pause p)", and resume it with with "(start/resume p)",
|
|
where P is any MzTake process. In the "highway" demo, P is
|
|
"radar-program", and P is "p" (meaning "process") for the others.
|
|
|
|
|
|
============================================================
|
|
|
|
Functions
|
|
|
|
The demos demonstrate many ways to debug with MzTake using
|
|
FrTime, even if you are not very familiar with the language.
|
|
That said, in order to become more proficient in using MzTake,
|
|
you will want to learn more about the FrTime language.
|
|
|
|
You can refer to FrTime's own documentation by searching for
|
|
"frtime" in DrScheme's Help window. It explains how to use
|
|
time-varying behaviors and event streams in greater depth, and
|
|
also describes the many useful functions FrTime provides to work
|
|
with them.
|
|
|
|
|
|
|
|
============================================================
|
|
|
|
_Debugging with MzTake_
|
|
|
|
Conceptually, MzTake is an extension of FrTime, providing
|
|
functions that execute a target program (or many!), and
|
|
"connect" to points in its code. MzTake then provides the
|
|
running FrTime script with interesting information (such as
|
|
a variable's current value) which it derives from these
|
|
"connections". FrTime then handles the rest.
|
|
|
|
FrTime takes that information and lets the script author
|
|
compute with it, verify it, print it, make visualizations
|
|
with it, anything you would like to do.
|
|
|
|
Currently, other than the powerful monitoring facilities that
|
|
MzTake provides (see BIND and ENTRY in the next section), user
|
|
interaction is limited to pausing/resuming the running program,
|
|
and operating on a few properties and predicates over general
|
|
program state (see PROCESS:EXITED?, PROCESS:RUNTIME/SECONDS,
|
|
and PROCESS:EXCEPTIONS). In the future, MzTake will offer other
|
|
types of interaction and information, such as inspecting
|
|
(and stepping through!) the call stack.
|
|
|
|
In more depth, the debugger works on a model roughly as follows:
|
|
|
|
* A single debugging script file contains all the MzTake
|
|
processes, traces, bindings, animations, and other FrTime
|
|
code fragments that do the debugging and program monitoring.
|
|
|
|
* This script file is loaded into the Definitions window in
|
|
DrScheme, and run using the MzTake language. User interaction
|
|
with the debugger is provided through the Interactions window.
|
|
|
|
* A MzTake *process* is like an operating system that runs a group of
|
|
programs, installs hooks into them to monitor their execution,
|
|
and provides FrTime with these hooks to do computations.
|
|
|
|
* Also like an operating system, each MzTake process runs
|
|
independently of all other MzTake processes; one will not affect
|
|
another. They can "interact" in the script by adding traces and
|
|
computing with those traces.
|
|
|
|
* A MzTake process accepts a number of target-files as "clients" to
|
|
debug and monitor. Each client should contain a module program,
|
|
of the form:
|
|
|
|
(module mod-name mzscheme
|
|
... program-body ... )
|
|
|
|
MzTake does not support debugging anything other than modules.
|
|
|
|
* The first client defined for each MzTake process is *always* the
|
|
main ("top level") module. That is, START/RESUME runs the main
|
|
client module, in much the same way that you would run it in
|
|
DrScheme (in the "module ..." language). It is assumed the module
|
|
has "side-effects" which start the target program.
|
|
|
|
The rest of the files traced in a DEFINE-MZTAKE-PROCESS are modules
|
|
used *by* the main module, allowing you to see what is going
|
|
on deeper than in the main-module. For example:
|
|
|
|
(define-mztake-process p1
|
|
("my-stack-tests.ss")
|
|
((lib "my-stack.ss" "my-stack") [s-push-p1 3 29 bind 'insert-value]
|
|
[s-pop-p1 10 16 bind 'return-value]))
|
|
|
|
"my-stack-tests.ss" is the main module. Suppose it is a test-suite
|
|
for "my-stack.ss"; the test suite asserts that the stacks are not
|
|
working as expected. You may want to use these traces to test how
|
|
"my-stack.ss" is operating "inside" during the test-suite.
|
|
Watch the pushes and pops and see how they correlate to what you expect.
|
|
|
|
* The same module can be traced differently for each MzTake processe.
|
|
Lets say that in the same script you want to see why the stack is using
|
|
a lot more memory than expected. You can set traces to count how many times
|
|
spaces is allocated and cleared and see if they are equal.
|
|
|
|
(define-mztake-process p2
|
|
("my-stack-tests.ss")
|
|
((lib "my-stack.ss" "my-stack") [s-allocates-p2 22 2 entry]
|
|
[s-clears-p2 28 2 entry]))
|
|
|
|
This installs an ENTRY trace at the function entry point for
|
|
ALLOCATE-STACK and CLEAR-STACK in "my-stack.ss". Every time
|
|
those functions get called, these traces will send a "#t" event,
|
|
and could be counted using COUNT-B.
|
|
|
|
* Once a MzTake processe is defined, and all the script code operating
|
|
on traces is defined, START/RESUME can be called on the process
|
|
to begin its execution.
|
|
|
|
* All of the variables defined by traces (BINDs and ENTRYs on the active
|
|
MzTake processes) are available simulatenously in the script.
|
|
|
|
* Lastly, proceses can be started, paused, resumed, and terminated.
|
|
See START/RESUME, PAUSE, KILL, KILL-ALL.
|
|
|
|
|
|
|
|
============================================================
|
|
|
|
MzTake itself defines the following functions:
|
|
|
|
_Installing Trace Points_
|
|
|
|
Currently, MzTake offers two types of traces: ENTRY and BIND.
|
|
ENTRYs are event streams that get a "#t" event every time the
|
|
target program reaches the trace point. Binds are event streams that
|
|
ping the value of one or more variables when the trace point is reached.
|
|
|
|
> (define-mztake-process process-name
|
|
[target-filename trace-clause ...] ...)
|
|
|
|
Where trace-clause is one of the following:
|
|
|
|
<1> [trace-name line-number column-number ENTRY]
|
|
<2> [trace-name line-number column-number bind 'variable-name]
|
|
<3> [trace-name line-number column-number bind '(variable-name ...)]
|
|
|
|
DEFINE-MZTAKE-PROCESS defines the variable process-name,
|
|
whose value is a MzTake process object. That object
|
|
can be passed to functions such as START/RESUME, KILL,
|
|
and "process:runtime/milliseconds", documented in the next
|
|
section.
|
|
|
|
DEFINE-MZTAKE-PROCESS installs trace points in one or many files,
|
|
as indicated by the trace-clauses. The target-filename can
|
|
be any file specification accepted by the standard REQUIRE
|
|
syntax for modules:
|
|
|
|
* Absolute path:
|
|
(define-mztake-process p [(file "/home/me/test.ss") [brk 10 7 ENTRY]])
|
|
|
|
* Relative path:
|
|
(define-mztake-process p ["../test.ss" [brk 10 7 ENTRY]])
|
|
|
|
* Library path:
|
|
(define-mztake-process p [(lib "test.ss" "collect-dir") [brk 10 7 ENTRY]])
|
|
|
|
For each trace-clause in the call to DEFINE-MZTAKE-PROCESS,
|
|
the trace-name is a variable name bound at the
|
|
top-level, whose value is a FrTime event
|
|
stream. Each time the execution of the target
|
|
reaches the given line-number and column[*], the
|
|
debugger emits an event on that stream. The value of
|
|
that event depends on which of the three kinds of
|
|
trace-clause was used, as follows:
|
|
|
|
<1> The value of the event is #t (an ENTRY trace).
|
|
|
|
<2> The value of the event is the value of variable-name,
|
|
in the target program, at the location of the
|
|
trace point (a BIND trace).
|
|
|
|
<3> The value of the event is a list containing one
|
|
element for each variable name given. The value
|
|
of each element is taken from the variable of
|
|
that name in the target (as in <2>).
|
|
|
|
Trace points do not themselves pause the
|
|
program. Unless a MzTake process is suspended using
|
|
the PAUSE function (below), execution resumes after
|
|
the MzTake script processed the event.
|
|
|
|
[*] Valid locations to add traces to are almost
|
|
always one character to the left of open-parentheses, "(",
|
|
open-square-braces, "[", or to the left of the first
|
|
character of a symbol/name (LET is a special exception,
|
|
see Known Problems for more information on tracing LET):
|
|
|
|
(code [more-code ...] ...)
|
|
^^ ^^ ^
|
|
|
|
[*] To obtain accurate line/column information when
|
|
setting up trace points, make sure you turn off
|
|
DrScheme's "Wrap Text" feature under the "Edit"
|
|
menu. Alternatively, you can position your cursor
|
|
at the location where you want to add a trace,
|
|
and click MzTake's "Syntax Location" button on the
|
|
main DrScheme toolbar. A message-box will tell
|
|
the correct line and column numbers to use.
|
|
|
|
|
|
_Operations on MzTake Processes_
|
|
|
|
The following functions operate on MzTake processes,
|
|
and can be used in the Interactions window.
|
|
|
|
> (start/resume process-name)
|
|
|
|
Start the execution and monitoring of the DEFINE-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.
|
|
|
|
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
|
|
start running the script. Otherwise, a race condition may
|
|
develop, where your script may miss events from the
|
|
beginning of the execution.
|
|
|
|
> (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 resources
|
|
it used -- you cannot START/RESUME after a KILL.
|
|
|
|
Closing a FrTime animation/graphics window will *not*
|
|
kill a running MzTake process. If it does not terminate
|
|
on its own, you may kill it with "(kill p-name)" or
|
|
"(kill-all)" in the Interactions window.
|
|
|
|
> (kill-all)
|
|
|
|
kill-all kills all the processes currently running
|
|
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 on this stream.
|
|
|
|
> (process:runtime/seconds process)
|
|
|
|
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). Includes garbage-collection time.
|
|
|
|
> (process:runtime/milliseconds process)
|
|
|
|
Returns a FrTime time-varying value which counts the
|
|
number of milliseconds elapsed in the execution of the
|
|
given process (not counting time spent suspended by
|
|
PAUSE). Includes garbage-collection time.
|
|
|
|
> (process:exited? process)
|
|
|
|
Return a time-varying Boolean value which becomes
|
|
true after the given MzTake process exited/killed.
|
|
|
|
|
|
_Useful Functions for Time-Varying Values_
|
|
|
|
Note: FrTime uses a naming convention where functions which
|
|
return behaviors have names that end in "-b", and
|
|
functions that return event streams end in "-e".
|
|
|
|
Tips: When you have a behavior that you want to turn into
|
|
an event, use (changes behavior).
|
|
|
|
When you have an event that you want to be a
|
|
behavior, use (hold event)
|
|
|
|
|
|
MzTake defines a few functions on time-varying values
|
|
that are particularly useful when debugging:
|
|
|
|
> (history-e stream)
|
|
> (history-b stream)
|
|
|
|
Keeps a complete history of all the values seen
|
|
on an event stream as a list, oldest events last.
|
|
|
|
Use with BINDs: (history-b x-trace)
|
|
|
|
> (history-e n stream)
|
|
> (history-b n stream)
|
|
|
|
Keeps a list of the last n values of a behavior
|
|
Returns a list of at most n elements, where the
|
|
elements are the n last values seem on the stream,
|
|
in order, oldest first.
|
|
|
|
> (count-b stream)
|
|
|
|
Counts number of events seen on an eventstream.
|
|
|
|
Often used directly on ENTRY traces, counting how many
|
|
times ENTRY occured: (count-b entry-trace)
|
|
|
|
Also useful to count how many times a BIND changed
|
|
by calling: (count-b (changes bind-trace))
|
|
|
|
> (largest-val-b stream)
|
|
> (smallest-val-b stream)
|
|
|
|
Keeps track of the largest/smallest values seen on a stream.
|
|
Use with BINDs: (largest-val-b (changes bind-trace)).
|
|
|
|
> (sequence-match? seq stream)
|
|
|
|
Matches a sequence of items in a list to the history
|
|
of event pings, on the event stream evs. Returns #t
|
|
when it matches, and #f otherwise. Use when you expect
|
|
a certain pattern to show up, and want to know when:
|
|
(sequence-match? '(0 1 2 1 0) (changes bind-trace))
|
|
|
|
> (printf-b format-string arg ...)
|
|
|
|
Displays the value of the behaviors with the given format,
|
|
using "~a" just like in Scheme's FORMAT function.
|
|
|
|
|
|
============================================================
|
|
|
|
Known Problems
|
|
|
|
* In general, you should not REQUIRE or use any methods
|
|
in your MzTake script that were defined in any of the files
|
|
you are putting bind-traces on:
|
|
|
|
ORIGINAL FILE:
|
|
(define (my-fun some-struct) ...)
|
|
|
|
MZTAKE SCRIPT:
|
|
(require "original-file.ss")
|
|
(define-mztake-process p ("original-file.ss" [val 10 12 bind 'my-struct]))
|
|
(my-fun (hold val))
|
|
|
|
Sometimes this causes unusual errors. These problems usually only
|
|
show up if you are binding to structs (defined in the same file) and
|
|
passing those bindings to functions (defined in the same file).
|
|
|
|
You have been warned.
|
|
|
|
* The break button will *not* kill runaway client processes.
|
|
You must type (kill process-name) or (kill-all).
|
|
|
|
* Some legal syntax locations (used in setting trace points)
|
|
are unreachable during program execution (they do not get
|
|
triggered and produce empty eventstreams). So far, this only
|
|
shows up in LETs (the trace point being one line above,
|
|
and one character to the left of the carrot):
|
|
|
|
(define x 12)
|
|
(let ([x (add1 x)]) x)
|
|
^ ^^^
|
|
Recommended syntax locations to use for trace points:
|
|
(define x 12)
|
|
(let ([x (add1 x)]) x)
|
|
^ ^^ ^ ^
|
|
|
|
* Don't rely entirely on MzTake to complain when you change
|
|
target code and your line/col locations in the script are out
|
|
of date. It can only raise an error if the locations are invalid.
|
|
|
|
* MzTake has not been tested for stability if the target is using
|
|
multiple threads. This only applies to threaded modules
|
|
*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.
|
|
|
|
* On particularly fast computers, when running scripts with a
|
|
very high trace point density (traces are hit constantly,
|
|
potentially hundreds in a second, like in the Monte Carlo,
|
|
random-xs, and sine demos), the FrTime animation window may
|
|
appear unresponsive because of how fast it is redrawing.
|
|
|
|
* Currently, if you are running traces on two modules with the
|
|
same name, IN the same process, though in different directories,
|
|
there will probably be some sort of name-clash and strange error.
|
|
This will be fixed.
|
|
|
|
* If you find that sometimes it seems one of the breakpoints you
|
|
set in a file REQUIRE'd by the main client module, your problem
|
|
may be that the file-specification you used is different in the
|
|
script than it is in the main client module (occuring in REQUIREs
|
|
that use sub-directories):
|
|
|
|
MAIN CLIENT:
|
|
(require (lib "my-lib.ss" "mycollect" "private"))
|
|
|
|
MZTAKE SCRIPT:
|
|
(define-mztake-process p ("main.ss")
|
|
((lib "my-lib.ss" "mycollect/private") [traces...])
|
|
|
|
This seems to be an issue with DrScheme rather than MzTake.
|
|
For instance, you get an error if you make a module like this
|
|
on Windows:
|
|
|
|
(module m mzscheme
|
|
(require (lib "my-lib.ss" "mycollect" "private"))
|
|
(provide (lib "my-lib.ss" "mycollect/private")))
|
|
|
|
This will be looked into, but keep your eyes open for it.
|
|
|
|
|
|
============================================================
|
|
|
|
Tips and Tricks
|
|
|
|
* If output seems difficult to read in the script, e.g. you ever
|
|
see "struct:signal" and a lot of garbage, try (print-struct #f)
|
|
before you do any printing, or use (value-now behavior-name) to
|
|
get a more usable/printable version of a FrTime behavior (the
|
|
caveat is that it is no longer 'reactive' and it may be out of
|
|
date after the moment it is processed).
|
|
|
|
* 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 trace point
|
|
(see Known Problems).
|
|
|
|
For instance, if you trace 'x and 'y separately:
|
|
* First 'x and 'y are up-to-date.
|
|
* Then 'x updates and 'y is out-of-date.
|
|
* Then 'y updates, and both are up-to-date.
|
|
|
|
But code that draws using a position derived from X and Y
|
|
will draw twice, in two locations, one for each update,
|
|
the second one being correct.
|
|
|
|
* Order matters -- if you have more than one trace at an identical
|
|
syntax location (in the same file), the order that trace events
|
|
get updated is identical to the order they exist in the script.
|
|
For example:
|
|
|
|
(define-mztake-process p ("file.ss" [a-bind 5 55 bind 'x]
|
|
[some-bind 2 22 bind 'irrelevent]
|
|
[a-entry 5 55 entry]
|
|
[another-bind 5 55 bind 'y]))
|
|
|
|
When that trace gets evaluated, A-BIND will get the new value
|
|
of X, and relevant FrTime code will get re-evaluated. *Then*
|
|
A-ENTRY will be notified about the trace and a #t will be emitted,
|
|
(at this point in time, Y is out-of-date, but X is up-to-date). Lastly,
|
|
ANOTHER-BIND will get the new value of Y, and the trace is complete.
|
|
|
|
Of course, you will typically want ENTRY as the first trace,
|
|
and all other BINDs to be in a list, so that you get two updates,
|
|
as explained in the previous tip:
|
|
|
|
(define-mztake-process p ("file.ss" [a-entry 5 55 entry]
|
|
[x/y-bind 5 55 bind '(x y)]
|
|
[some-bind 2 22 bind 'irrelevent]))
|
|
|
|
* You can trace the *same* file in different ways by using
|
|
multiple processes on the same file, under different
|
|
contexts, and compare results. For example, in
|
|
"demos/misc/first-class-mztake.ss":
|
|
|
|
(define-mztake-process p ("first-class.ss" [x-before-let 3 29 bind 'x]
|
|
[x-in-let 4 25 bind 'x]
|
|
[x-after-let 5 11 bind 'x]))
|
|
(... code omitted ...)
|
|
(start/resume p)
|
|
|
|
is functionally equivalent to:
|
|
|
|
(define-mztake-process p1 ("first-class.ss" [x-before-let 3 29 bind 'x]))
|
|
(define-mztake-process p2 ("first-class.ss" [x-in-let 4 25 bind 'x]))
|
|
(define-mztake-process p3 ("first-class.ss" [x-after-let 5 11 bind 'x]))
|
|
(... code omitted ...)
|
|
(start/resume p1) (start/resume p2) (start/resume p3)
|
|
|
|
All the variable bindings can still be used as they were before.
|
|
|
|
* Code such as (when (= num 100) (pause p)) pauses *after*
|
|
num reaches 100, the next time a trace point is hit.
|
|
However, the next point is not processed until you
|
|
START/RESUME. See the random-xs demo.
|
|
|
|
* When you pause a MzTake process, you can play with
|
|
current bindings and explore script code interactively.
|
|
You *may* dynamically evaluate/add FrTime code to do
|
|
things like pause or kill a MzTake process based on runtime,
|
|
etc. You can even define new MzTake processes dynamically
|
|
and start/resume them, integrating and exploring the traces.
|
|
You cannot add or change existing traces dynamically.
|
|
|
|
* You can add trace points to first-class functions, and they
|
|
will send trace update from anywhere they are passed to and
|
|
evaluated.
|
|
|
|
* FrTime has two methods for drawing graphics. One runs in
|
|
constant time, and is fast, because it simply accumulates
|
|
pixels on the screen and doesn't redraw a list of objects.
|
|
See the "Monte Carlo" or "random-xs" demos for this in action.
|
|
|
|
The other method is primarily for animations which need
|
|
redrawing because things move. It slows down pretty quickly
|
|
after you have more than 1000 objects to the shape list.
|
|
See the "sine" or "highway" demos for this in action.
|
|
|
|
For more information, refer to the FrTime documentation.
|
|
|
|
|
|
============================================================
|
|
|
|
Authors and Thanks
|
|
|
|
MzTake is an experimental debugger. It should enable new
|
|
debugging approaches that were not possible (easily) before.
|
|
Please send feedback to the PLT-Scheme mailing list:
|
|
http://www.plt-scheme.org/maillist/
|
|
|
|
We are eager to hear about how you are using MzTake!
|
|
|
|
Jonathan Spiro
|
|
Guillaume Marceau
|
|
Gregory Cooper
|
|
John Clements
|
|
Shriram Krishnamurthi
|
|
|
|
|
|
Please send bug reports to: jspiro@cs.brown.edu
|
|
|
|
---
|
|
Icons for MzTake come from the Gnome Project: Nautilus Emblems.
|
|
These are provided under the GPL license.
|
|
http://jimmac.musichall.cz/ikony.php3
|