[plt-scheme] Dalek vs. FrTime

From: Guillaume Marceau (gmarceau at cs.brown.edu)
Date: Fri Aug 20 16:10:53 EDT 2004

On Sun, 2004-08-15 at 20:47, Vadim Nasardinov wrote:

> Even though your FrTime-based solution
> is arguably more elegant, do you think there is any middle ground
> between Dalek and FrTime?  In other words, can I do slightly better
> than Dalek, even though I'm not going to go as far as FrTime?

MzTake extends Dalek in the following ways:

      * MzTake events are first-class. With these, we can define
        reusable debugging constructs, such as the function not-in-order
        that we define in the paper.

      * MzTake has time-varying values, called behaviours, which are
        also first class. You can pass these behaviours as an argument
        to set-running! to install a rule that will decide whether the
        target program should be running.

With the two extension put together, we can define reusable start-stop
rules. In particular, these rules can arbitrate the corner cases
identified in the "semantic issues" paper in purpose-dependent ways.

In our paper, we claim we can define Dalek's start-resume policy in
MzTake. Let's do so now:

        (define tracepoints (make-hash))
        
        (define (break location callback)
          (hash-put!
           tracepoints
           location
           (map-e
            (lambda (i) (and i (callback i)))
            (hash-get tracepoints location
                      (lambda () (trace location (bind () true)))))))
        
        (define (resume)
          (set-running! 
           (hold (apply merge-e
                        (hash-values tracepoints))
                 true)))

For each location with one (or many) breakpoints, the "break" function
above accumulates a cascade of events, where each event is dependent on
the event that was in that location previously. When the execution of
the target program reaches one of the locations, the cascade evaluates
each decision function in order, until the first one that returns false.
The guard "(and i ...)" ensures that the other callbacks are not called
afterwards.

This is Dalek's arbitration rule when there is multiple breakpoints
at the same location.


One might wonder, is this the right rule for all applications? In
particular, the guard that prevents the execution of subsequent
breakpoint's callback creates a dependency between the breakpoints (if
the first breakpoint decides to suspend the execution, the second
doesn't get to run at all). These dependencies are problematic if (as
discussed in the paper) these breakpoints each monitor different
aspects of the target program.

Let's define a different rule. This time, all breakpoints at a
location get to execute when we hit that location, and we resume only
when none of them requested a pause:

        (define stop-requested? false)
        
        (define (break location callback)
          (set! stop-requested?
                (or (hold (trace location (bind () (callback))) false)
                    stop-requested?)))
        
        (define (resume) (set-running! (not stop-requested?)))

[You can imagine another rule where "and" is used instead of "or"]

Our claims is that the combination of first-class events, behaviours
and set-running! makes it easy to define both reusable and
custom-purpose start-stop policies. Furthermore, MzTake turns the
installation of such a decision rules into a simple library call.

In contrast, in Dalek, installing custom decision rules can only be
accomplished through a coding convention, where (as you were pointing
out) all main events converge into a single "leaf" event that is
responsible for the resume decision.

Since we do not have single-stepping, we can only really claim to help
the multiple-breakpoint case, as we did above. However, we hope the
idea extends to single-stepping loops just as well.


Posted on the users mailing list.