diff --git a/collects/mztake/annotator.ss b/collects/mztake/annotator.ss index 8fe0fb5104..efcc9986ae 100644 --- a/collects/mztake/annotator.ss +++ b/collects/mztake/annotator.ss @@ -384,15 +384,4 @@ is-tail?) annotated)) - (values (top-level-annotate stx) (hash-table-map breakpoints (lambda (k v) k))))) - - #; - (define (tests) - (run/single-stepping-annotation - (current-custodian) "a.ss" - (map string->path '("/home/gmarceau/projects/mztake/collects/mztake/a.ss" - "/home/gmarceau/projects/mztake/collects/mztake/b.ss")) - (lambda (fn pos) - (printf "break?: ~a ~a~n" fn pos) #t) - (lambda (bp-info) (printf "break: ~a~n" bp-info) #f))) -) \ No newline at end of file + (values (top-level-annotate stx) (hash-table-map breakpoints (lambda (k v) k)))))) diff --git a/collects/mztake/debug-tool.ss b/collects/mztake/debug-tool.ss index fb88ef26a2..eda7b6584e 100644 --- a/collects/mztake/debug-tool.ss +++ b/collects/mztake/debug-tool.ss @@ -116,7 +116,7 @@ (if (is-a? source editor<%>) source (cond - [(send (group:get-the-frame-group) locate-file source) + [(and source (send (group:get-the-frame-group) locate-file source)) => (lambda (frame) (let ([defss (map (lambda (t) (send t get-defs)) (send frame get-tabs))]) @@ -587,7 +587,7 @@ (lambda (defs) (send (send defs get-tab) add-top-level-binding var val))] - [else (printf "record-top-level failed~n")]) + [else (void) #;(printf "record-top-level failed~n")]) #; (printf "top-level binding: ~a ~a ~a~n" mod var val)) source)]) diff --git a/collects/mztake/demos/dijkstra/dijkstra-mztake.ss b/collects/mztake/demos/dijkstra/dijkstra-mztake.ss deleted file mode 100644 index c26fb55945..0000000000 --- a/collects/mztake/demos/dijkstra/dijkstra-mztake.ss +++ /dev/null @@ -1,85 +0,0 @@ -#| This script tests a priority queue (heap) that is correctly implemented, but incorrectly used. - It is not commented because it uses a some advanced FrTime concepts that can easily be looked - up in the help desk, and both the description and motivation of the example can be found in - "A Dataflow Language for Scriptable Debugging" (Marceau, Cooper, Krishnamurthi, Reiss), - available at: - - http://www.cs.brown.edu/~sk/Publications/Papers/Published/mckr-dataflow-lang-script-debug/ - - This script uses the concept of maintaining a local model of the heap being debugged, as a simple, - and very slow, list. The difference is that a fancy heap used can be naively implemented as a list, - simply removing only the smallest element each time. Models are external to your program, you don't - have to add any test code to your program to use them. By adding and removing the items to our local - "model" (the values come from the heap code we used), we can compare the results and assert whether - it is working correctly or not. Our model shows the values we should be getting from the program, - but clearly are not. - - To provide some context for this demo, and what debugging problem MzTake helps us explore, I offer - the following, out of context, taken directly from the paper: - We find that the queue's elements are not in sorted order while those in the model - are. More revealingly, the queue's elements are not the same as those in the model. - A little further study shows that the bug is in our usage of the priority queue: - we have failed to account for the fact that the assignment to dest.weight - in relax (figure 1) updates the weights of nodes already in the queue. Because - the queue is not sensitive to these updates, what it returns is no longer the - smallest element in the queue. - - On further reading, we trace the error to a subtle detail in the description of - Dijkstra's algorithm in Cormen, et al.'s book [9, page 530]. The book permits - the use of a binary heap (which is how we implemented the priority queue) for - sparse graphs, but subsequently amends the pseudocode to say that the assignment - to dest.weight must explicitly invoke a key-decrement operation. Our error, - therefore, was not in the implementation of the heap, but in using the (faster) - binary heap implementation without satisfying its (stronger) contract. |# - -(require (lib "mztake.ss" "mztake") - (lib "useful-code.ss" "mztake") - "dijkstra-solver.ss" - (lib "match.ss")) - -(define inserts (trace (loc '(lib "heap.ss" "frtime") '(let* ((sorter _) _) _)) - item)) -(define removes (trace (loc/r '(dv:ref (t-data _) _)))) - -#| The following code -merely observes the insertions and removals - from the heap. We notice whether any of the removals are out - of order based on the last item removed, as long as there are - no insertions between the two events. We can keep track of the - last 2 using history-e. |# - -(define (not-in-order e) - (filter-e - (match-lambda - [('reset _) false] - [(_ 'reset) false] - [(previous current) (> previous current)] - [else false]) - (history-e e 2))) - - -(define inserts-and-removes-e (merge-e (removes . ==> . node-weight) - (inserts . -=> . 'reset))) -(define violations (not-in-order inserts-and-removes-e)) - -(printf-b "all inserts and removes: ~a" (history-b inserts-and-removes-e)) -(printf-b "all violations: ~a" (history-b violations)) -(printf-b "latest-violation: ~a" (hold violations)) -#| This output indicates that the queue has yielded nodes whose weights are out of order. - This confirms our suspicion that the problem somehow involves the priority queue. |# - -#| Implementation of the local model follows... |# -(define ((insert-in-model item) model) - (printf "~nInserting ~a into model containing:~n~a~n" item (value-now model)) - (cons item model)) - -(define ((remove-from-model item) model) - (printf "~nRemoving ~a from model containing:~n~a~n" item (value-now model)) - (filter (lambda (i) (not (equal? i item))) model)) - -(define inserters (accum-b (inserts . ==> . insert-in-model) empty)) -(define removers (accum-b (removes . ==> . remove-from-model) inserters)) - -(set-main! "dijkstra.ss") - -(set-running-e! (violations . -=> . false)) \ No newline at end of file diff --git a/collects/mztake/demos/dijkstra/dijkstra-solver.ss b/collects/mztake/demos/dijkstra/dijkstra-solver.ss deleted file mode 100644 index 636198033d..0000000000 --- a/collects/mztake/demos/dijkstra/dijkstra-solver.ss +++ /dev/null @@ -1,49 +0,0 @@ -(module dijkstra-solver mzscheme - (require (lib "heap.ss" "frtime") - (lib "list.ss") - "graph.ss") - - (provide (all-defined)) - - (define (make-node label x y weight) (vector label x y weight)) - (define (node-label n) (vector-ref n 0)) - (define (node-x n) (vector-ref n 1)) - (define (node-y n) (vector-ref n 2)) - (define (node-weight n) (vector-ref n 3)) - (define (set-node-weight! n v) (vector-set! n 3 v)) - - (define (node< a b) (< (node-weight a) (node-weight b))) - (define (sqr x) (* x x)) - (define (distance-to a b) - (sqrt (+ (sqr (- (node-x a) (node-x b))) - (sqr (- (node-y a) (node-y b)))))) - - (define (hash-table-pairs hash) - (hash-table-map hash (lambda (key val) (list key val)))) - - (define (relax backtrace heap origin dest) - (let ([candidate-weight - (+ (node-weight origin) - (distance-to origin dest))]) - (when (candidate-weight . < . (node-weight dest)) - (set-node-weight! dest candidate-weight) - ;;(heap-resort heap dest) - (hash-table-put! backtrace dest origin)))) - - (define (solve graph nodes source) - (let ([backtrace (make-hash-table)] - [heap (make-heap node< eq?)]) - (set-node-weight! source 0) - (for-each (lambda (node) (heap-insert heap node)) - nodes) - - (let loop () - (unless (heap-empty? heap) - (let* ([node (heap-pop heap)] - [successors (graph-succs graph node)]) - (for-each - (lambda (succ) (relax backtrace heap node succ)) - successors)) - (loop))) - - (hash-table-pairs backtrace)))) diff --git a/collects/mztake/demos/dijkstra/dijkstra.ss b/collects/mztake/demos/dijkstra/dijkstra.ss deleted file mode 100644 index acf3d29b02..0000000000 --- a/collects/mztake/demos/dijkstra/dijkstra.ss +++ /dev/null @@ -1,32 +0,0 @@ -(module dijkstra mzscheme - (require "dijkstra-solver.ss" - "graph.ss" - (lib "list.ss")) - - (define g (make-graph 'directed)) - (define (m-node label x y) (make-node label x y +inf.0)) - (define nodes - (list - (m-node 'J 200 100) - (m-node 's 100 125) - (m-node '1 150 100) - (m-node '2 150 150) - (m-node '4 250 100) - (m-node '5 300 100) - (m-node '6 300 150))) - (for-each (lambda (n) (graph-node-add! g n)) nodes) - (define (n-ref label) - (first (filter (lambda (n) (eq? label (node-label n))) nodes))) - - (define edges - (list (list (n-ref 's) (n-ref '1)) - (list (n-ref 's) (n-ref '2)) - (list (n-ref '1) (n-ref 'J)) - (list (n-ref '4) (n-ref '5)) - (list (n-ref 'J) (n-ref '4)) - (list (n-ref 'J) (n-ref '6)))) - (for-each (lambda (e) (graph-edge-add! g (first e) (second e))) - edges) - - (printf "~n~n---output from dijkstra.ss:~n~a~n---~n" - (solve g (reverse nodes) (n-ref 's)))) \ No newline at end of file diff --git a/collects/mztake/demos/dijkstra/dv.ss b/collects/mztake/demos/dijkstra/dv.ss deleted file mode 100644 index 043cdc7ea8..0000000000 --- a/collects/mztake/demos/dijkstra/dv.ss +++ /dev/null @@ -1,100 +0,0 @@ -; -*- Scheme -*- - -; Shriram Krishnamurthi (shriram@cs.rice.edu) -; Tue Jul 25 23:20:45 EDT 1995 - -; (define-structure (dv:vector length size contents)) - -(module dv mzscheme - - (provide dv:make dv:make-w/-init dv:length dv:contents dv:append - dv:remove-last dv:legitimate-index dv:ref dv:set!) - - (define dv:vector? - (lambda (obj) - (if (vector? obj) - (if (= (vector-length obj) 4) - (eq? (vector-ref obj 0) 'dv:vector) - #f) - #f))) - (define dv:vector-length - (lambda (obj) (vector-ref obj 1))) - (define dv:vector-size - (lambda (obj) (vector-ref obj 2))) - (define dv:vector-contents - (lambda (obj) (vector-ref obj 3))) - (define dv:set-vector-length! - (lambda (obj newval) (vector-set! obj 1 newval))) - (define dv:set-vector-size! - (lambda (obj newval) (vector-set! obj 2 newval))) - (define dv:set-vector-contents! - (lambda (obj newval) (vector-set! obj 3 newval))) - (define dv:make-vector - (lambda (length size contents) - ((lambda () (vector 'dv:vector length size contents))))) - - (define dv:make - (let* ((default-initial-size 8) - (default-initial-vector (make-vector default-initial-size))) - (lambda arg - (cond - ((null? arg) - (dv:make-vector 0 default-initial-size default-initial-vector)) - ((= 1 (length arg)) - (let ((l (car arg))) - (dv:make-vector 0 l (make-vector l)))) - (else - (error 'dv:make "wrong number of arguments")))))) - - (define dv:make-w/-init - (lambda values - (let ((l (length values))) - (dv:make-vector l l (list->vector values))))) - - (define dv:append - (lambda (dv item) - (let ((length (dv:vector-length dv)) - (size (dv:vector-size dv)) - (contents (dv:vector-contents dv))) - (if (< length size) - (begin - (vector-set! contents length item) - (dv:set-vector-length! dv (+ length 1))) - (begin - (let ((new-vector (make-vector (* size 2)))) - (let loop - ((i 0)) - (when (< i size) - (vector-set! new-vector i (vector-ref contents i)) - (loop (+ i 1)))) - (dv:set-vector-contents! dv new-vector) - (dv:set-vector-size! dv (* size 2)) - (dv:append dv item))))))) - - (define dv:remove-last - (lambda (dv) - (dv:set-vector-length! dv (- (dv:vector-length dv) 1)) - (vector-set! (dv:vector-contents dv) (dv:vector-length dv) 0))) - - - (define dv:legitimate-index - (lambda (dv index) - (< index (dv:vector-length dv)))) - - (define dv:ref - (lambda (dv index) - (if (dv:legitimate-index dv index) - (vector-ref (dv:vector-contents dv) index) - (error 'dv:ref "index too large")))) - - (define dv:set! - (lambda (dv index value) - (if (dv:legitimate-index dv index) - (vector-set! (dv:vector-contents dv) index value) - (error 'dv:set! "index too large")))) - - (define dv:contents dv:vector-contents) - - (define dv:length dv:vector-length) - ) - diff --git a/collects/mztake/demos/dijkstra/graph.ss b/collects/mztake/demos/dijkstra/graph.ss deleted file mode 100644 index 6802352db1..0000000000 --- a/collects/mztake/demos/dijkstra/graph.ss +++ /dev/null @@ -1,542 +0,0 @@ -;; -*- compile-command: "mzscheme -M errortrace -u graph.ss" -*- -(module graph mzscheme - (require (lib "base-gm.ss" "frtime") - (lib "etc.ss") - (lib "list.ss")) - - (provide make-graph - ;; --- Constructors : - graph? - graph-directed? - graph-make-similar - graph-copy - graph-add-all! - ;; --- Functions on nodes: - graph-nodes - graph-nodes-size - graph-make-node! - graph-node-add! - graph-node-mem? - graph-node-set! - graph-node-remove! - graph-node-collapse! - graph-node-has-label? - graph-node-label - graph-for-each-node - graph-fold-nodes - ;; --- Functions on neighbors: - graph-succs - graph-preds - graph-adjs - graph-for-each-adjs - ;; --- Functions on edges: - graph-edges - graph-edges-size - graph-edge-add! - graph-edge-mem? - graph-edge-set! - graph-edge-remove! - graph-edge-has-label? - graph-edge-label - graph-for-each-edge - graph-fold-edges - ;; --- Simple graph algorithms: - graph-dfs-from-node - graph-dfs-all - graph-components - graph-strongly-connected-components - graph-topological-sort - ;; --- Debugging: - graph-to-list - graph-to-string - graph-test - ) - - (define-struct t (flags nNodes nEdges nodes successors predessessors)) - - ;; Flags can be: 'equal 'directed 'unique-node 'unique-edge 'nodes-must-exists 'safe - ;; 'safe is a short for '(unique-node unique-edge nodes-must-exists) - (define (make-graph . flags) - (let ((flag-hash (make-hash))) - (set! flags (expands-safe-flag flags)) - (for-each (lambda (flag) (hash-put! flag-hash flag true)) flags) - (if (member 'equal flags) - (make-t flag-hash 0 0 (make-hash 'equal) (make-hash 'equal) (make-hash 'equal)) - (make-t flag-hash 0 0 (make-hash) (make-hash) (make-hash))))) - - (define (graph? graph) (t? graph)) - - (define no-value (box empty)) - - ;; Makes a hash with the same 'equal as the graph - (define (graph-make-hash graph) - (if (graph-has-flag? graph 'equal) - (make-hash 'equal) - (make-hash))) - - - (define (expands-safe-flag flags) - (let loop ((cur flags) (acc empty)) - (cond [(empty? cur) acc] - [(eq? (first cur) 'safe) (loop (rest cur) (append '(unique-node unique-edge nodes-must-exists) flags))] - [true (loop (rest cur) (cons (first cur) acc))]))) - - ;; Make a graph with mostly the same flags as another graph - (define (graph-make-similar graph plus-flags minus-flags) - (set! plus-flags (expands-safe-flag plus-flags)) - (set! minus-flags (expands-safe-flag minus-flags)) - (apply make-graph - (append plus-flags - (filter (lambda (i) (not (member i minus-flags))) - (hash-keys (t-flags graph)))))) - - (define (graph-copy graph) - (let* ((rtn-nodes (graph-make-hash graph)) - (rtn-successors (graph-make-hash graph)) - (rtn-predessessors (graph-make-hash graph)) - (rtn (make-t (t-flags graph) (t-nNodes graph) (t-nEdges graph) rtn-nodes rtn-successors rtn-predessessors))) - - (hash-add-all! rtn-nodes (t-nodes graph)) - (hash-add-all! rtn-successors (t-successors graph)) - (hash-add-all! rtn-predessessors (t-predessessors graph)) - rtn)) - - (define (graph-add-all! dest-graph src-graph) - (graph-for-each-node - src-graph - (lambda (node) - (if (graph-node-has-label? src-graph node) - (graph-node-add! dest-graph node (graph-node-label src-graph node)) - (graph-node-add! dest-graph node)))) - (graph-for-each-edge - src-graph - (lambda (from to) - (if (graph-edge-has-label? src-graph from to) - (graph-edge-add! dest-graph from to (graph-edge-label src-graph from to)) - (graph-edge-add! dest-graph from to))))) - - (define (graph-has-flag? graph flag) - (hash-mem? (t-flags graph) flag)) - - (define (graph-directed? graph) - (hash-mem? (t-flags graph) 'directed)) - - ;;; ===================================================================== - ;;; Nodes - - (define (graph-nodes graph) (hash-keys (t-nodes graph))) - - (define (graph-nodes-size graph) (t-nNodes graph)) - - (define graph-make-node! - (case-lambda - [(graph) (graph-make-node! graph no-value)] - [(graph val) - (let ((sym (string->symbol (string-append "node" (number->string (t-nNodes graph)))))) - (graph-node-add! graph sym val) - sym)])) - - ;; Add a node to the graph. If the node already exists, - ;; sets its label, unless the graph has the 'unique-node property, - ;; in which case this will assert. - (define graph-node-add! - (case-lambda - [(graph node) (graph-node-add! graph node no-value)] - [(graph node val) - (if (hash-mem? (t-nodes graph) node) - (assert (not (graph-has-flag? graph 'unique-node))) - (begin - (set-t-nNodes! graph (+ 1 (t-nNodes graph))) - (hash-put! (t-successors graph) node (graph-make-hash graph)) - (if (graph-directed? graph) - (hash-put! (t-predessessors graph) node (graph-make-hash graph))))) - (hash-put! (t-nodes graph) node val)])) - - (define (graph-node-mem? graph node) - (hash-mem? (t-nodes graph) node)) - - (define (graph-node-set! graph node val) - (assert (hash-mem? (t-nodes graph) node)) - (hash-put! (t-nodes graph) node val)) - - (define (graph-node-remove! graph node) - (assert (graph-node-mem? graph node)) - (for-each (lambda (i) (graph-edge-remove! graph node i)) - (hash-keys (hash-get (t-successors graph) node))) - - (if (graph-directed? graph) - (for-each (lambda (i) (graph-edge-remove! graph i node)) - (hash-keys (hash-get (t-predessessors graph) node)))) - - (hash-remove! (t-nodes graph) node) - (hash-remove! (t-successors graph) node) - (if (graph-directed? graph) - (hash-remove! (t-predessessors graph) node)) - (set-t-nNodes! graph (- (t-nNodes graph) 1))) - - (define graph-node-collapse! - (case-lambda - [(graph node with-self-loop) (graph-node-collapse! graph node with-self-loop (lambda (pred-label succ-label) no-value))] - [(graph node with-self-loop label-fn) - (let ((is-directed (graph-directed? graph))) - (for-each - - (lambda (pred) - (for-each - (lambda (succ) - (unless (or (and (not is-directed) (eq? pred succ)) - (graph-edge-mem? graph pred succ)) - (let* ((label-pred (hash-get (hash-get (t-successors graph) pred) node)) - (label-succ (hash-get (hash-get (t-successors graph) node) succ)) - (new-label (label-fn (if (eq? label-pred no-value) false label-pred) - (if (eq? label-succ no-value) false label-succ)))) - (when (or with-self-loop (not (eq? pred succ))) - (hash-put! (hash-get (t-successors graph) pred) succ new-label) - (if is-directed - (hash-put! (hash-get (t-predessessors graph) succ) pred new-label) - (hash-put! (hash-get (t-successors graph) succ) pred new-label)))))) - (hash-keys (hash-get (t-successors graph) node)))) - - (hash-keys (hash-get - (if is-directed (t-predessessors graph) (t-successors graph)) - node)))) - (graph-node-remove! graph node)])) - - (define (graph-node-has-label? graph node) - (not (eq? (hash-get (t-nodes graph) node) no-value))) - - (define (graph-node-label graph node) - (let ((r (hash-get (t-nodes graph) node))) - (if (eq? r no-value) (error "graph-node-label: no value for node" node) - r))) - - (define (graph-succs graph node) - (assert (graph-directed? graph)) - (hash-keys (hash-get (t-successors graph) node))) - - (define (graph-preds graph node) - (assert (graph-directed? graph)) - (hash-keys (hash-get (t-predessessors graph) node))) - - (define (graph-adjs graph node) - (if (graph-directed? graph) - (append (hash-keys (hash-get (t-successors graph) node)) - (hash-keys (hash-get (t-predessessors graph) node))) - (hash-keys (hash-get (t-successors graph) node)))) - - (define (graph-for-each-adjs graph node fn) - (for-each (hash-keys (hash-get (t-successors graph) node)) - (lambda (succ) (fn node succ))) - (when (graph-directed? graph) - (for-each (hash-keys (hash-get (t-predessessors graph) node)) - (lambda (pred) (fn pred node))))) - - (define (graph-for-each-node graph fn) - (for-each fn (hash-keys (t-nodes graph)))) - - (define (graph-fold-nodes graph init fn) - (let ((acc init)) - (graph-for-each-node - graph - (lambda (node) (set! acc (fn node acc)))) - acc)) - - ;;; ===================================================================== - ;;; Edges - - (define (graph-edges graph) - (let ((rtn empty)) - (graph-for-each-edge graph (lambda (from to) (set! rtn (cons from to)))) - rtn)) - - (define (graph-edges-size graph) (t-nEdges graph)) - - ;; Add an edge to the graph. If the edge already exists, - ;; sets its label, unless the graph has the 'unique-edge property, - ;; in which case this will assert. - (define graph-edge-add! - (case-lambda - [(graph from to) (graph-edge-add! graph from to no-value)] - [(graph from to val) - - (if (graph-edge-mem? graph from to) - (assert (not (graph-has-flag? graph 'unique-edge))) - (set-t-nEdges! graph (+ (t-nEdges graph) 1))) - - (if (graph-has-flag? graph 'nodes-must-exists) - (assert (and (graph-node-mem? graph from) (graph-node-mem? graph to))) - (begin (if (not (graph-node-mem? graph from)) (graph-node-add! graph from)) - (if (not (graph-node-mem? graph to)) (graph-node-add! graph to)))) - - (hash-put! (hash-get (t-successors graph) from) to val) - - (if (graph-directed? graph) - (hash-put! (hash-get (t-predessessors graph) to) from val) - (hash-put! (hash-get (t-successors graph) to) from val))])) - - (define (graph-edge-mem? graph from to) - (if (graph-has-flag? graph 'nodes-must-exists) - (assert (and (graph-node-mem? graph from) - (graph-node-mem? graph to)))) - - (and (hash-mem? (t-successors graph) from) - (hash-mem? (hash-get (t-successors graph) from) to))) - - (define (graph-edge-set! graph from to val) - (assert (graph-edge-mem? graph from to)) - (hash-put! (hash-get (t-successors graph) from) to val) - - (if (graph-directed? graph) - (hash-put! (hash-get (t-predessessors graph) to) from val) - (hash-put! (hash-get (t-successors graph) to) from val))) - - (define (graph-edge-remove! graph from to) - (assert (graph-edge-mem? graph from to)) - (hash-remove! (hash-get (t-successors graph) from) to) - - (if (graph-directed? graph) - (hash-remove! (hash-get (t-predessessors graph) to) from) - (hash-remove! (hash-get (t-successors graph) to) from))) - - (define (graph-edge-has-label? graph from to) - (not (eq? (hash-get (hash-get (t-successors graph) from) to) no-value))) - - (define (graph-edge-label graph from to) - (let ((r (hash-get (hash-get (t-successors graph) from) to))) - (if (eq? r no-value) (error "graph-edge-label: no value for edge" (cons from to))) - r)) - - (define (graph-for-each-edge graph fn) - (graph-for-each-node - graph - (lambda (from) - (for-each (lambda (to) (fn from to)) - (hash-keys (hash-get (t-successors graph) from)))))) - - (define (graph-fold-edges graph init fn) - (let ((acc init)) - (graph-for-each-edge - graph - (lambda (from to) (set! acc (fn from to acc)))) - acc)) - - ;;; ===================================================================== - ;;; Algos - - (define (graph-dfs-from-node-with-log graph node dealt-with pre-fn post-fn backward) - (assert (or (not backward) (graph-directed? graph))) - (if (not (hash-mem? dealt-with node)) - (begin (hash-put! dealt-with node true) - (pre-fn node) - (for-each (lambda (n) (graph-dfs-from-node-with-log graph n dealt-with pre-fn post-fn backward)) - (if backward - (hash-keys (hash-get (t-predessessors graph) node)) - (hash-keys (hash-get (t-successors graph) node)))) - (post-fn node)))) - - - (define graph-dfs-from-node - (case-lambda - [(graph node pre-fn) (graph-dfs-from-node graph node pre-fn (lambda (i) i))] - [(graph node pre-fn post-fn) - (graph-dfs-from-node-with-log graph node (graph-make-hash graph) pre-fn post-fn false)])) - - (define graph-dfs-all - (case-lambda - [(graph pre-fn) (graph-dfs-all graph pre-fn (lambda (i) i))] - [(graph pre-fn post-fn) - (let ((dealt-with (graph-make-hash graph))) - (graph-for-each-node graph (lambda (n) (if (not (hash-mem? dealt-with n)) - (graph-dfs-from-node-with-log graph n dealt-with pre-fn post-fn false)))))])) - - - (define (graph-components graph) - (let ((dealt-with (graph-make-hash graph))) - (graph-fold-nodes - graph - empty - (lambda (node acc) - (if (hash-mem? dealt-with node) acc - (let ((cur-component - (let loop ((cur node) (acc empty)) - (if (hash-mem? dealt-with cur) acc - (begin (hash-put! dealt-with cur true) - (foldl (lambda (adj acc) (loop adj acc)) (cons cur acc) - (graph-adjs graph cur))))))) - (cons cur-component acc))))))) - - (define (graph-strongly-connected-components graph) - (assert (graph-directed? graph)) - (let ((finish-times empty) - (dealt-with (graph-make-hash graph))) - - (graph-for-each-node - graph - (lambda (n) (graph-dfs-from-node-with-log - graph n dealt-with - (lambda (i) i) - (lambda (i) (set! finish-times (cons i finish-times))) - false))) - - (set! dealt-with (graph-make-hash graph)) - - (let ((component-graph (graph-make-similar graph empty '(safe equal))) - (node2supernode (make-hash))) - - (for-each - (lambda (n) - (if (not (hash-mem? dealt-with n)) - (let ((super-node (graph-make-node! component-graph empty))) - (graph-dfs-from-node-with-log - graph n dealt-with - (lambda (i) - (graph-node-set! component-graph super-node (cons i (graph-node-label component-graph super-node))) - (hash-put! node2supernode i super-node)) - (lambda (i) i) - true)))) - finish-times) - (graph-for-each-edge graph - (lambda (from to) - (graph-edge-add! component-graph - (hash-get node2supernode from) - (hash-get node2supernode to)))) - (cons component-graph node2supernode)))) - - (define (graph-topological-sort graph) - (assert (graph-directed? graph)) - (let ((rtn empty)) - (graph-dfs-all graph (lambda (i) i) (lambda (node) (set! rtn (cons node rtn)))) - rtn)) - - - ;;; ===================================================================== - ;;; Utils - - (define graph-to-list - (case-lambda - [(graph) (graph-to-list graph false)] - [(graph with-labels) - (hash-map (t-nodes graph) - (lambda (node node-val) - (let ((node-rep (if (and with-labels (graph-node-has-label? graph node)) - (cons node (graph-node-label graph node)) - node))) - (cons node-rep - (hash-fold (hash-get (t-successors graph) node) empty - (lambda (succ edge-val acc) - (if (and with-labels (graph-edge-has-label? graph node succ)) - (cons (cons succ (graph-edge-label graph node succ)) acc) - (cons succ acc))))))))])) - - (define (graph-to-string-prv graph with-labels to-string) - (let ([the-to-string (or to-string - (lambda (item) (format "~a" item)))]) - (string-append (if (graph-directed? graph) "[di-graph: " "[undirected-graph:") - (the-to-string (map (lambda (n) - (cons (first n) (cons '--> (rest n)))) - (graph-to-list graph with-labels))) - "]"))) - - (define (graph-to-string graph . to-string) - (graph-to-string-prv graph false (if (empty? to-string) false (first to-string)))) - - (define (graph-to-string-with-labels graph . to-string) - (graph-to-string-prv graph true (if (empty? to-string) true (first to-string)))) - - - ;;; ===================================================================== - ;;; Tests - - (define (graph-test) - (define graph (make-graph 'safe 'directed)) - - (graph-node-add! graph 'a) - (graph-node-add! graph 'b 2) - (graph-node-add! graph 'c 3) - (graph-node-add! graph 'd) - - (graph-edge-add! graph 'a 'c) - (graph-edge-add! graph 'a 'd "asd") - (graph-edge-add! graph 'b 'c "dfg") - (graph-edge-add! graph 'b 'd) - (graph-edge-add! graph 'd 'a) - - (display (graph-node-mem? graph 'a)) - (display (graph-edge-mem? graph 'a 'c)) - (newline) - (display (graph-node-mem? graph 'v)) - (display (graph-edge-mem? graph 'c 'a)) - (display (graph-edge-mem? graph 'a 'b)) - (newline) - - (print-each (graph-to-list graph true)) - (graph-for-each-edge graph (lambda (a b) (print-each "A " a b))) - - (graph-dfs-from-node graph 'a (lambda (i) (display i))) - (newline) - (graph-dfs-from-node graph 'b (lambda (i) (display i))) - (newline) - (graph-dfs-from-node graph 'c (lambda (i) (display i))) - (newline) - (graph-dfs-from-node graph 'd (lambda (i) (display i))) - (newline) - - (let ((star (make-graph 'directed))) - (graph-edge-add! star 1 'x) - (graph-edge-add! star 'x 1) - (graph-edge-add! star 2 'x) - (graph-edge-add! star 'x 3) - (graph-edge-add! star 'x 4) - (graph-edge-add! star 'x 5) - (graph-node-collapse! star 'x false) - (print-each "collapsed:" (graph-to-list star))) - - (let ((strong-graph (make-graph 'directed))) - - (graph-edge-add! strong-graph 'e 'a) - (graph-edge-add! strong-graph 'a 'b) - (graph-edge-add! strong-graph 'b 'e) - (graph-edge-add! strong-graph 'e 'f) - (graph-edge-add! strong-graph 'b 'f) - (graph-edge-add! strong-graph 'b 'c) - (graph-edge-add! strong-graph 'f 'g) - (graph-edge-add! strong-graph 'g 'f) - (graph-edge-add! strong-graph 'c 'g) - (graph-edge-add! strong-graph 'c 'd) - (graph-edge-add! strong-graph 'd 'c) - (graph-edge-add! strong-graph 'g 'h) - (graph-edge-add! strong-graph 'd 'h) - (graph-edge-add! strong-graph 'h 'h) - - (graph-edge-add! strong-graph 'xa 'xb) - (graph-edge-add! strong-graph 'xb 'xc) - (graph-edge-add! strong-graph 'xc 'xa) - - (print-each "strong-graph" strong-graph) - (print-each "component" (graph-components strong-graph)) - (let ((components (graph-strongly-connected-components strong-graph))) - (print-each "strong-components" components) - (print-each "toposort" (graph-topological-sort (first components))))) - - (let ((u-graph (make-graph))) - (graph-edge-add! u-graph 'a 'b) - (graph-edge-add! u-graph 'b 'c) - (graph-edge-add! u-graph 'c 'd) - (graph-edge-add! u-graph 'd 'a) - (graph-edge-add! u-graph 'd 'e) - (graph-edge-add! u-graph 'e 'c) - - (graph-edge-add! u-graph 'xa 'xb) - (graph-edge-add! u-graph 'xa 'xc) - (graph-edge-add! u-graph 'xb 'xd) - (newline) - (print-each "u-graph" u-graph) - (graph-edge-remove! u-graph 'b 'a) - (graph-node-remove! u-graph 'd) - (print-each "u-graph" u-graph) - (print-each "component" (graph-components u-graph))) - - ) - ;(graph-test) - ) - diff --git a/collects/mztake/demos/dijkstra/heap-speed-mztake.ss b/collects/mztake/demos/dijkstra/heap-speed-mztake.ss deleted file mode 100644 index 9284ed10df..0000000000 --- a/collects/mztake/demos/dijkstra/heap-speed-mztake.ss +++ /dev/null @@ -1,9 +0,0 @@ -(require (lib "mztake.ss" "mztake")) -(set-main! '(lib "heap.ss" "frtime")) - -(define start (current-milliseconds)) -(set-running! #t) -(exited?) -(- (hold (map-e (lambda (e) (current-milliseconds)) - (changes (exited?)))) start) - diff --git a/collects/mztake/demos/exception/exception-mztake.ss b/collects/mztake/demos/exception/exception-mztake.ss deleted file mode 100644 index 952e4349af..0000000000 --- a/collects/mztake/demos/exception/exception-mztake.ss +++ /dev/null @@ -1,10 +0,0 @@ -(require (lib "mztake.ss" "mztake") - (lib "useful-code.ss" "mztake")) - -(set-main! "exception.ss") - -(printf-b "exception.ss exited? ~a" (exited?)) - -(printf-b "last exception seen: ~a" (exceptions)) - -(set-running! true) \ No newline at end of file diff --git a/collects/mztake/demos/exception/exception.ss b/collects/mztake/demos/exception/exception.ss deleted file mode 100644 index 8a42fe40a4..0000000000 --- a/collects/mztake/demos/exception/exception.ss +++ /dev/null @@ -1,2 +0,0 @@ -(module exception mzscheme - (thread (lambda () (raise 'exn:oops-made-a-mztake!)))) \ No newline at end of file diff --git a/collects/mztake/demos/highway/highway-mztake.ss b/collects/mztake/demos/highway/highway-mztake.ss deleted file mode 100644 index 67e8e9bd96..0000000000 --- a/collects/mztake/demos/highway/highway-mztake.ss +++ /dev/null @@ -1,23 +0,0 @@ -(require (lib "mztake.ss" "mztake") - (lib "animation.ss" "frtime") - (lib "useful-code.ss" "mztake")) - -(define/bind (loc "highway.ss" 4) speed) - -(printf-b "current speed: ~a" speed) - -(define (make-speed-gauge speed) - (let ([center (make-posn 200 200)]) - (list (make-circle center 170 "black") - (make-circle center 160 "white") - (make-rect (make-posn 0 202) 1000 1000 "white") - (make-line (make-posn 30 201) (make-posn 370 201) "black") - (make-line center - (posn+ center (make-posn (- (* 150 (cos (/ speed 30)))) - (- (* 150 (sin (/ speed 30)))))) - "red")))) - - -(display-shapes (make-speed-gauge speed)) - -(set-running! (< speed 55)) \ No newline at end of file diff --git a/collects/mztake/demos/highway/highway.ss b/collects/mztake/demos/highway/highway.ss deleted file mode 100644 index f6d15110a2..0000000000 --- a/collects/mztake/demos/highway/highway.ss +++ /dev/null @@ -1,6 +0,0 @@ -(module highway mzscheme - (let ([nap-time 0.8]) - (let loop ([speed 0]) - (sleep nap-time) - ;; Generate some fake speeds readings: - (loop (+ speed 4))))) \ No newline at end of file diff --git a/collects/mztake/demos/sprofiler/picture.ss b/collects/mztake/demos/sprofiler/picture.ss deleted file mode 100644 index aa55ab7dd7..0000000000 --- a/collects/mztake/demos/sprofiler/picture.ss +++ /dev/null @@ -1,29 +0,0 @@ -(module picture mzscheme - - (require (lib "graphics.ss" "graphics") - (lib "math.ss")) - - (open-graphics) - - (define d 400) - - (define viewport (open-viewport "Blah" (* 2 d) (* 2 d))) - - (values 1 2 3) - - (define-syntax for - (syntax-rules (=) - [(_ (var = init) condn delta proc ...) - (let loop ([var init]) - (when condn - proc ... - (loop (delta var))))])) - - (for (i = (- d)) (< i d) add1 - (for (j = (- d)) (< j d) add1 - (when (<= (+ (sqr i) (sqr j)) (sqr d)) - ((draw-pixel viewport) (make-posn (+ d i) (+ d j)) - (if (or (zero? i) (zero? j)) - (make-rgb 0 0 1) - (let ([i (- 1 (/ (abs (gcd i j)) (+ (abs i) (abs j))))]) - (make-rgb i i 1)))))))) diff --git a/collects/mztake/demos/sprofiler/sprofiler-mztake.ss b/collects/mztake/demos/sprofiler/sprofiler-mztake.ss deleted file mode 100644 index 0a14922592..0000000000 --- a/collects/mztake/demos/sprofiler/sprofiler-mztake.ss +++ /dev/null @@ -1,28 +0,0 @@ -(require (lib "mztake.ss" "mztake" ) - (lib "match.ss") - (lib "base-gm.ss" "frtime") - (only mzscheme hash-table-map)) - -(set-main! "picture.ss") - -(define (hash-table-increment! h k) - (let ([old (hash-get h k (lambda () 0))]) - (hash-put! h k (add1 old)))) - -(define pings (make-hash 'equal)) - -(for-each-e! (where) - (match-lambda [(line function context rest ...) - (hash-table-increment! pings (list function context))] - [_ (void)])) - -(define clicks (changes (quotient milliseconds 50))) - -(set-running-e! (merge-e (clicks . -=> . false) - (clicks . -=> . true))) - -(define (hash-pairs ht) - (hash-table-map ht (lambda (k v) (list k v)))) - -(define (show-profile) - (sort (hash-pairs pings) (lambda (a b) (> (second a) (second b))))) diff --git a/collects/mztake/doc.txt b/collects/mztake/doc.txt deleted file mode 100644 index 09b0a70301..0000000000 --- a/collects/mztake/doc.txt +++ /dev/null @@ -1,519 +0,0 @@ - - -============================================================ - - 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. In -order to use MzTake, you will need to familiarize yourself with the -FrTime language by reading its own documentation. - -With signals it is possible to respond to outside events concisely, -without using callbacks. Consider a MzTake script to monitor the -behavior of the program "highway-mztake.ss", in the demos directory of -the MzTake collection: - - (require (lib "mztake.ss" "mztake")) - (define/bind (loc "highway.ss" 4) speed) - (printf-b "current speed: ~a" speed) - ;; more code - (set-running! true) - -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 line -of "highway.ss". SPEED is a FrTime behavior that always -contains the *current* value of the variable named SPEED in -the target program. - -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". The last line invokes SET-RUNNING!, -which lunches 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 highway example, perhaps knowing the last ten speeds -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 (changes speed) 10)) - -HISTORY-B consumes an event stream (CHANGES SPEED) and an -optional number n, returning a FrTime behavior containing a -FIFO ordered list of the n values emitted on that event -stream. In this case, HISTORY-B maintains a list of the ten -most recent SPEEDS seen on SPEED. - -We might want to pause the program when something goes awry. We do -this by exploiting the fact that the SET-RUNNING! function consumes a -FrTime behavior. The value of a behavior can change over time, and -SET-RUNNING! monitors these changes. Whenever the behavior is true, -the target program runs, and whenever it is false, the target program -pauses. We can indicate to MzTake to pause when the speed exceeds 55 -as follow: - - (printf-b "last ten speeds: ~a" (history-b (changes speed) 10)) - (set-running! (< speed 55)) - -Once paused, it is possible to interactively explore the state of the -paused process. You may enter names of variables bound in the target -program, and MzTake will look up and return their values. For -example, typing 'nap-time' in the REPL while the program is paused -yields the value 0.8. - -You can resume execution with "(set-running #t)", or -some other behavior, or end the execution altogether with "(kill)". - -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. - - (require (lib "animation.ss" "frtime")) - (display-shapes (make-speed-gauge (hold speed))) - - -============================================================ - - Demos - -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 "FrTime" 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 (starting with the simplest one): - - ./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. - - ./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. - - ./djikstra/dijkstra-mztake.ss - Debugs a buggy implementation of - Dijkstra's algorithm - - -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_ - -MzTake is a library for the FrTime languages which provides 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. - -MzTake defines the following functions and macros: - -_Installing Trace Points_ - -> (loc require-spec line-number) -> (loc require-spec line-number column-number) - - Creates a LOC structure containing the target file, the target line - number, and (optionally) the target column number. LOC structures - are consumed by TRACE and by DEFINE/BIND. The first argument to LOC - is a file specification suitable for require, provided as a - datum. For instance, to install a trace point on the tenth line of - the MzLib's list library, use: - - (trace (loc '(lib "list.ss") 10) ) - -> (loc require-spec pattern) - - The LOC function can also accept a pattern. MzTake will scan the - text of the target source file and install a breakpoint at every - location where the text matches the pattern. The pattern language - is very simple. Every symbol in the pattern is taken literally, - with the exception of the underscore. In a pattern, and underscore - stand for zero, one, or many items. Unlike the patterns used by - match.ss, MzTake does not make use of an ellipsis to indicate - repetition. The repetition is always implicit. The following - expression inserts a tracepoint on every lambda expression that has - exactly one argument, called "l" : - - (trace (loc '(lib "list.ss") '(lambda (l) _)) ) - -> (trace loc body ...) - - Install a trace point at the location indicated by the LOC value. - The result is a FrTime event stream containing one value each time - the target reaches the location specified. To get the value event, - TRACE evaluates its body (once per event. During the evaluation of - the body, the target process is paused, and the body can inspect - the state of the paused program. - - The body is optional. If no body is provided, the value #t is used - by default. - - Unless SET-MAIN! is used, the first call to trace sets the file - name that will be run when SET-RUNNING! is invoked the first time. - -> (trace* process loc thunk) - - Like TRACE, but takes an explicit process argument, and a thunk - rather than a body. - -> (bind (name ...) body ...) - - When the target process is paused (or during the execution of a - trace body), BIND reaches in the lexical context at the point of - the pause (or of the trace point) and finds the values for the - variables whose names are given. These values are then bound in the - body (in the MzTake script) to the variables of the same name. - - It is an error to call BIND while the target process is running. - - You can use BIND to look up values of identifiers in the target - program that are shadowed by identifiers in the script. - -> (bind* process symbol) - - In the given process, find the variable whose name has the given - symbol, and returns its value. - - -> (define/bind loc name ...) - - Define the NAMEs to behaviors reflecting the values of the - given names in the target program, at the given - location. DEFINE/BIND is short for: - - (define name (hold (trace loc (bind (name) name)))) - - -> (define/bind-e loc name ...) - - Same as DEFINE/BIND, but binds event streams to the names instead - of behaviors. - - -> (exceptions) -> (exceptions process) - - Returns an event stream containing one EXN structure for each - exception raised in the target process and not caught. - - -> (exited?) -> (exited? process) - - Returns a behavior which starts as #f and take on the value #t when - the target process exits. - - -> (set-running! val) -> (set-running! val process) -> (set-running! event) -> (set-running! event process) - - Launches the execution of the target process. Execution continues - as long as the given behavior is true (aka, any value beside #f), - or until an event comes on the given event stream with the value - #f. When execution pauses, the target remains on the line where - the pause occured. You can then inspect the state of the program, - or resume execution with another call to SET-RUNNING!. - - -> (set-main! require-spec) -> (set-main! require-spec process) - - Sets the file where execution begins when SET-RUNNING! is called - for the first time. When SET-MAIN! is not used explicitly, - execution begins with the file specified in the first call to - TRACE. It is an error to call SET-RUNNING! without first calling - either TRACE or SET-MAIN!. - - -> (where) -> (where process) - - Returns an event stream that contains one event for each expression - evaluated in the target process. Combined with HISTORY-B, this makes - it possible to record entire execution traces for the target program. - - -> (kill) - - Kills the target process and releases all resources - it used -- you cannot resume after a KILL. - - This will not stop evaluation of the MzTake script, however. In - particular, if the script depends on input the varies independently - of the target process, FrTime will continue to update them. You can - use "Kill" command from DrScheme's "Scheme" menu to stop both the - MzTake script and its target process at once. - - Also, note that closing a FrTime animation/graphics window does *not* - kill a running MzTake process. - -> (kill-all) - - When using more than one target process at a time, KILL-ALL invokes - KILL on all of them at once. - - -> (current-process) -> (current-process process) - - The CURRENT-PROCESS parameter gets or sets the process manipulated - by the MzTake function when they are not provided with a process - argument. The CURRENT-PROCESS parameter is initialized with a blank - process, and you can create additional processes using the - CREATE-DEBUG-PROCESS function. Using more than one process at a - time lets your MzTake run multiple programs different at once and - compare their output using a single script. - - -> (create-debug-process) - - Creates a fresh blank debug process. Each debug process has its own - set of trace points, its own run trigger (set via SET-RUNNING!), - its own exceptions stream, etc. Each debug process run - independently from the others, and they can be paused and killed - individually. All debug processes in a single MzTake script share - the same FrTime event space, and so it is possible to compare - output and traces between each of them. - -> (current-policy) -> (current-policy policy) - - Every file executed under MzTake can run either in fast mode or in - debuggable mode. The CURRENT-POLICY decides which. - - - debuggable mode: the file is instrumented with MzTake debugging - information. It can be the target of tracepoint and it generate - events on the WHERE stream. Execution can also be paused in the middle - of code running in debuggable mode. The instrumentation overhead - is considerable, however, of the order of 10x-20x slowdown. - - - fast mode: the file is not instrumented, and runs at its normal - speed, but cannot be debugged. Inserting trace points into fast - mode files after the beginning of the execution has no - effect. Also, pausing while executing a fast mode file will be - delayed until execution reaches a debuggable mode file. - - Files that are the target of a trace point when first lunching the - process run in debuggable mode, so is the main file set by - SET-MAIN!. Otherwise, the current policy is consulted to decide - between fast and debuggable mode. In this case, if the policy does - not decide, MzTake raises an error. - - Policies have the following contract: - - (listof (list/c (symbols 'fast 'debuggable) - (union (symbols 'everything-else) - path? - string? - (listof (union path? string?))))) - - A policy consist of a list of entries. Each entry is a pair - specifying either fast mode or debuggable mode, then a directory, - or a list of directories. Files in these directories, or their - subdirectories will run under the given mode. The special symbol - 'everything-else can be used instead of a directory, and this will - match any file. The policy is checked in order, and the first entry - that applies to the given filename assign a mode the file. - - The default policy run files of the directories specified by - CURRENT-LIBRARY-COLLECTIONS-PATHS in fast mode, and runs everything - else in debuggable mode. This poloicy is set as follow: - - (current-policy `((fast ,(current-library-collection-paths)) - (debuggable everything-else))) - - You can change this policy by calling the - CURRENT-POLICY function with a new policy as an argument. The - policy is assigned to a process when the process lunches. - - -_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. You can require these -functions with (require (lib "useful-code.ss" "mztake")) - -> (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 stream n) -> (history-b stream n) - - 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 in your MzTake script any - functions that act on the structures of your target program. - - ORIGINAL FILE: - (define-struct foo (a b)) - (let ([x (make-foo 1 2)]) - x) - - MZTAKE SCRIPT: - (require "original-file.ss") - (define/bind (loc "original-file.ss" 3) x) - (foo-a x) ;; this will fail! - - The target program and the MzTake will have different - instances of the struct, and the call to FOO-A will fail. - Instead, use BIND to bring the function from the target program to - the script: - - (define/bind (loc "original-file.ss" 3) x foo-a) - (foo-a x) ;; this succeeds - -* The break button will *not* kill runaway client processes. - You must type (kill) 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). For instance, - the name clause of a LET is never the current point of execution: - - (define x 12) - (let ([x (add1 x)]) x) - ^ - Recommended syntax locations to use for trace points: - - (define x 12) - (let ([x (add1 x)]) x) - ^ ^^ ^ ^ - -* Watch out: when you change target code, your line/col locations in - the script will drift out of align. - -* 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. - -* You can add trace points to the body first-class functions, and they - will send trace update from anywhere they are passed to and invoked. - -============================================================ - -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 diff --git a/collects/mztake/engine.ss b/collects/mztake/engine.ss deleted file mode 100644 index 5f92b712dd..0000000000 --- a/collects/mztake/engine.ss +++ /dev/null @@ -1,445 +0,0 @@ -(module engine mzscheme - (require "marks.ss" - (lib "etc.ss") - (lib "list.ss") - (lib "match.ss") - (prefix frp: (lib "lang-ext.ss" "frtime")) - (rename (lib "frp-core.ss" "frtime") - frp:signal-thunk signal-thunk) - "useful-code.ss" - (lib "base-gm.ss" "frtime") - "mztake-structs.ss" - "load-sandbox.ss" - "annotator.ss" - (lib "match.ss")) - - (provide process:set-main! - current-policy - all-debug-processes - create-debug-process - process:->dead - process:new->running - process:running->finished - process:running->paused - process:paused->running - pause - resume - trace* - - read-all-syntax - pattern->pos) - - ;Keeps track of all debugging processes - (define all-debug-processes null) - - ; produces a nested list of (line column offset span) for all addressable syntax - (define (unwrap-syntax stx) - (let ([elt (list (syntax-line stx) - (syntax-column stx) - (sub1 (syntax-position stx)) - (syntax-span stx))]) - (syntax-case stx () - [(item ...) (cons elt (map unwrap-syntax (syntax->list stx)))] - [x elt]))) - - (define (read-all-syntax filename) - (parameterize ([port-count-lines-enabled #t]) - (let ([port (open-input-file filename)]) - (begin0 - (let loop ([stx (read-syntax filename port)]) - (if (eof-object? stx) '() - (cons stx - (loop (read-syntax filename port))))) - (close-input-port port))))) - - ;; returns a memoized function that takes (line column) -> (list/c position span) - ;; line-col->pos : (debug-file? . -> . (number? number? . -> . (union void? number?))) - (define (line-col->pos stx) - (let ([pos-list (flatten (map unwrap-syntax stx))]) - (lambda (line maybe-col) - (let loop ([lst pos-list]) - (cond - [(empty? lst) - (error 'loc - "No syntax found for trace at line/column ~a:~a in `~a'" - line maybe-col (syntax-source stx))] - [(and (<= line (first (first lst))) - (or (not maybe-col) - (<= maybe-col (second (first lst))))) - (list (third (first lst)) (fourth (first lst)))] - - [else (loop (rest lst))]))))) - - (define (pattern->pos stx-lst) - (define (quote-symbols lst) - (match lst - [(? symbol? s) `(quote ,s)] - [() empty] - [('_ tl ...) `(_ ... ,@(quote-symbols tl))] - [(hd tl ...) (cons (quote-symbols hd) - (quote-symbols tl))] - [item item])) - - (define (collect-locations h stx lst) - (let loop ([stx stx] [lst lst]) - (cond - [(empty? stx) (void)] - [(pair? stx) - (loop (first stx) (first lst)) - (loop (rest stx) (rest lst))] - [else - (when (syntax-line stx) - (hash-put! h lst (list (sub1 (syntax-position stx)) (syntax-span stx)))) - (when (pair? (syntax-e stx)) - (loop (first (syntax-e stx)) (first lst)) - (loop (rest (syntax-e stx)) (rest lst)))]))) - - (define stx2line-col (make-hash)) - (define lst (map syntax-object->datum stx-lst)) - - (for-each (lambda (s l) (collect-locations stx2line-col s l)) - stx-lst lst) - - (lambda (pattern) - (let ([pred (eval `(begin (require (lib "match.ss")) - (lambda (v) - (match v - [,(quote-symbols pattern) #t] - [_ #f]))))]) - (let loop ([lst lst]) - (let ([sub (if (pair? lst) - (append (loop (first lst)) - (loop (rest lst))) - empty)]) - (if (and (hash-mem? stx2line-col lst) (pred lst)) - (cons (hash-get stx2line-col lst) sub) - sub)))))) - - - (define (find-client process modpath) - (cond - [(memf (lambda (c) (equal? (debug-client-modpath c) modpath)) - (debug-process-clients process)) => first] - [else false])) - - (define (find-client/create process modpath) - (or (find-client process modpath) - (create-debug-client process modpath))) - - (define (process:set-main! p reqspec) - (let* ([modpath (reqspec->modpath reqspec)] - [client (find-client/create p modpath)]) - (set-debug-process-main-client! p client))) - - - (define (break? process client) - (let ([tracepoints (and client (debug-client-tracepoints client))]) - (lambda (pos) - (or (debug-process-pause-requested? process) - (and tracepoints - (hash-get tracepoints (sub1 pos) (lambda () false))))))) - - (define (traces->events traces vals) - (map (lambda (t) - (list (trace-struct-evnt-rcvr t) - (apply (trace-struct-thunk t) vals))) - traces)) - - (define (receive-result process client byte-offset top-mark rest-marks vals) - (let* ([traces (hash-get (debug-client-tracepoints client) byte-offset (lambda () empty))] - [no-traces? (empty? traces)] - [has-single-trace? (and (not no-traces?) (empty? (rest traces)))] - [no-where? (not (debug-process-where process))] - [no-events? (and no-traces? no-where? - (not (debug-process-pause-requested? process)))]) - - - (unless no-events? - (let* ([marks (cons top-mark (continuation-mark-set->list rest-marks debug-key))]) - (set-debug-process-marks! process marks) - - (if no-where? - ;; No where event to generate - (cond [has-single-trace? - ;; fast-path - (let* ([t (first traces)] - [e (apply (trace-struct-thunk t) vals)]) - (frp:send-synchronous-event (trace-struct-evnt-rcvr t) e))] - [no-traces? (void)] - [else (frp:send-synchronous-events (traces->events traces vals))]) - - ;; With a where event to generate - (let ([where-event (debug-process-where process)] - [w (map (compose syntax-local-infer-name mark-source) marks)]) - (if no-traces? - (frp:send-synchronous-event where-event w) - - (let* ([where-event (list where-event w)] - [trace-events (traces->events traces vals)]) - (frp:send-synchronous-events (cons where-event trace-events)))))) - - ;; Now that we processed the trace, do we want to pause or continue - (when (debug-process-pause-requested? process) - (let loop () - (unless (debug-process-resume-requested? process) - (semaphore-wait (debug-process-run-semaphore process)) - (loop))) - (set-debug-process-pause-requested?! process false) - (set-debug-process-resume-requested?! process false)) - - (set-debug-process-marks! process false))))) - - - - - (define ((break-after process client) top-mark marks . vals) - (let* ([stx (mark-source top-mark)] - [byte-offset (+ (syntax-position stx) (syntax-span stx) -2)]) - (receive-result process client byte-offset top-mark marks vals) - (apply values vals))) ; TODO: allow modification of the return value - - (define ((break-before process client) top-mark marks) - (let ([byte-offset (sub1 (syntax-position (mark-source top-mark)))]) - (receive-result process client byte-offset top-mark marks empty) ; TODO: allow substitute value - false)) - - (define (unbuild-path path) - (let-values ([(base name _) (split-path path)]) - (if base - (append (unbuild-path base) (list name)) - empty))) - - (define (head lst n) - (if (= n 0) - empty - (cons (first lst) (head (rest lst) (sub1 n))))) - - (define (dir-contains? dir filename) - (let ([dir-lst (unbuild-path dir)] - [file-lst (unbuild-path filename)]) - (and (< (length dir-lst) (length file-lst)) - (equal? dir-lst (head file-lst (length dir-lst)))))) - - (define (map-policy-tag tag) - (cond [(eq? tag 'fast) false] - [(eq? tag 'debuggable) true] - [else (error 'map-policy-tag "unknown policy tag ~a" tag)])) - - (define (policy-requests-annotatation? policy filename) - (if (empty? policy) - true - (let ([tag (first (first policy))] - [collect-paths (second (first policy))]) - (map-policy-tag tag) ;; complains if the tag doesn't exists - (if (or (eq? collect-paths 'everything-else) - (ormap (lambda (dir) (dir-contains? dir filename)) - (if (list? collect-paths) - collect-paths - (list collect-paths)))) - (map-policy-tag tag) - (policy-requests-annotatation? (rest policy) filename))))) - - (define (process-has-file? process filename) - (and - (memf (lambda (c) (equal? (debug-client-modpath c) - (path->string filename)));; TODO: harmonize path & string - (debug-process-clients process)) - true)) - - (define ((record-top-level-id process) module-name var-name val) - (let* ([modules (debug-process-top-level process)] - [bindings (hash-get modules module-name (lambda () (make-hash)))]) - (unless (hash-mem? modules module-name) - (hash-put! modules module-name bindings)) - (hash-put! bindings var-name val))) - - (define (launch-sandbox process) - (unless (debug-process-main-client process) - (error 'launch-sandbox - "No main file specified. Use TRACE or SET-MAIN! to indicate where to start execution")) - - (parameterize ([current-inspector (make-inspector)]) - (require/sandbox+annotations - (debug-process-custodian process) - ;; error-display-handler : - (let ([orig-err-disp (error-display-handler)]) - (lambda (msg exn) - (frp:send-event (debug-process-exceptions process) exn) - (orig-err-disp msg exn))) - - ;; target file - `(file ,(debug-client-modpath (debug-process-main-client process))) - - ;; annotate-module? - (lambda (filename module-name) - #;(print-each "annotate-module?" - filename - (process-has-file? process filename) - (policy-requests-annotatation? (debug-process-policy process) filename)) - - (or (process-has-file? process filename) - (policy-requests-annotatation? (debug-process-policy process) filename))) - - ;; annotator - (lambda (stx) - (if (not (syntax-source stx)) - stx - (let*-values ([(client) - (find-client/create - process - (path->string (syntax-source stx)))] - [(annotated-stx pos-list) - (annotate-for-single-stepping - stx - (lambda (_) (break? process client)) - (break-before process client) - (break-after process client) - (lambda (kind bound binding) (void)) - (record-top-level-id process))]) - annotated-stx)))))) - - (define (process:new->running process) - (printf "mztake: starting ~a~n" (debug-client-modpath (debug-process-main-client process))) - (set-debug-process-run-semaphore! process (make-semaphore)) - (set-debug-process-policy! process (current-policy)) - - (thread (lambda () - (launch-sandbox process) - (process:running->finished process)))) - - (define (process:running->finished process) - (process:->dead process)) - - (define (process:->dead process) - (printf "mztake: finished ~a~n" (debug-client-modpath (debug-process-main-client process))) - (set! all-debug-processes (remq process all-debug-processes)) - (custodian-shutdown-all (debug-process-custodian process)) - (frp:set-cell! (debug-process-exited? process) true)) - - (define (process:running->paused process) - (set-debug-process-pause-requested?! process true)) - - (define (process:paused->running process) - (set-debug-process-resume-requested?! process true) - (semaphore-post (debug-process-run-semaphore process))) - - (define (pause process) - (when (and (debug-process-run-semaphore process) - (not (frp:value-now (debug-process-exited? process))) - (not (debug-process-pause-requested? process))) - (process:running->paused process))) - - (define (resume process) - (cond - [(not (debug-process-run-semaphore process)) (process:new->running process)] - [(and (not (frp:value-now (debug-process-exited? process))) - (debug-process-pause-requested? process) - (not (debug-process-resume-requested? process))) - (process:paused->running process)])) - - (define current-policy (make-parameter `((fast ,(current-library-collection-paths)) - (debuggable everything-else)))) - - (define (create-debug-process) - - (letrec ([running-e (frp:new-cell frp:never-e)] - [run-manager (running-e . frp:==> . - (lambda (r) - (if r (resume process) (pause process))))] - [process (make-debug-process (make-custodian) - false ; run-semaphore - false so we know it has never started - running-e ; running-e - run-manager ; run-manager - false ; pause-requested? - false ; resume-requested? - false ; policy - - (frp:new-cell false) ; exited? - (frp:event-receiver) ; exceptions - false ; main-client - empty ; clients - (make-hash 'equal ) ; top-level - - false ; where - false)]) ; marks - (set! all-debug-processes (cons process all-debug-processes)) - process)) - - ; Creates a debugger client - ; (debug-process? require-path. -> . debug-file?) - (define (create-debug-client process modpath) - ; throwaway namespace so the module-name-resolver doesn't load an unannotated module - (parameterize ([current-namespace (make-namespace)]) - (let ([client (create-empty-debug-client)] - [stx (read-all-syntax modpath)]) - (for-each (lambda (c) - (when (equal? modpath (debug-client-modpath c)) - (raise-syntax-error 'mztake:script-error:create-debug-client - (format "A client for `~a' is already defined for this process." modpath)))) - (debug-process-clients process)) - - (set-debug-client-modpath! client modpath) - (set-debug-client-process! client process) - (set-debug-client-line-col->pos! client (line-col->pos stx)) - (set-debug-client-pattern->pos! client (pattern->pos stx)) - (set-debug-process-clients! process - (append (list client) (debug-process-clients process))) - - ; set the main module if it has not been set - ; this implies that the first client created is always the main module - (unless (debug-process-main-client process) - (set-debug-process-main-client! process client)) - - client))) - - (define (reqspec->modpath filename) - (define (build-module-filename str) ; taken from module-overview.ss - (let ([try (lambda (ext) - (let ([tst (string-append str ext)]) - (and (file-exists? tst) tst)))]) - (or (try ".ss") (try ".scm") (try "") str))) - (let ([modpath (symbol->string ((current-module-name-resolver) filename #f #f))]) - (build-module-filename - (if (regexp-match #rx"^," modpath) - (substring modpath 1 (string-length modpath)) - modpath)))) - - (define (loc->positions client loc) - (let ([pos&spans - (if (loc/lc? loc) - (list ((debug-client-line-col->pos client) (loc/lc-line loc) (loc/lc-col loc))) - ((debug-client-pattern->pos client) (loc/p-pattern loc)))]) - (if (loc-after? loc) - (map (lambda (p&s) (+ (first p&s) (second p&s) -1)) pos&spans) - (map first pos&spans)))) - - (define (trace* p loc thunk) - (let* ([modpath (reqspec->modpath (loc-reqspec loc))] - [client (find-client/create p modpath)] - [trace-hash (debug-client-tracepoints client)] - [trace (make-trace-struct (frp:event-receiver) thunk)] - [positions (loc->positions client loc)]) - ; add the trace to the list of traces for these byte-offsets - (for-each (lambda (pos) - (hash-put! trace-hash pos - (append (hash-get trace-hash pos (lambda () '())) - (list trace)))) - positions) - (trace-struct-evnt-rcvr trace))) - - (define (syntax-local-infer-name stx) - (or (syntax-property stx 'inferred-name) - (let ([s (syntax-source stx)]) - (and s - (let ([s (cond - [(path? s) (path->string s)] - [else s])] - [l (syntax-line stx)] - [c (syntax-column stx)]) - (if l - (string->symbol (format "~a:~a:~a" s l c)) - (let ([p (syntax-position stx)]) - (string->symbol (format "~a::~a" s p))))))))) - - - ) \ No newline at end of file diff --git a/collects/mztake/mztake-structs.ss b/collects/mztake/mztake-structs.ss deleted file mode 100644 index 413e6111b0..0000000000 --- a/collects/mztake/mztake-structs.ss +++ /dev/null @@ -1,84 +0,0 @@ -(module mztake-structs mzscheme - (require (lib "match.ss") - (lib "etc.ss") - (lib "base-gm.ss" "frtime")) - - (provide (all-defined)) - - (define require-spec? - (match-lambda - [(? string?) true] - [('file (? string?)) true] - [('lib (? string?) (? string?) ...) true] - [('planet . arg) true] - [else false])) - - ; ;;;;; ; ; - ; ; ; ; ; - ; ; ; ; - ; ; ;;;;;; ;;; ; ; ;;; ;;;;; ;;;; - ; ; ; ;; ; ; ; ; ; ; ; - ; ;;; ; ; ; ; ; ; ; - ; ;;; ; ; ; ; ; ; ; - ; ; ; ; ; ; ; ; ;;;; - ; ; ; ; ; ; ; ; ; - ; ; ; ; ; ; ; ; ; - ; ; ; ; ; ; ;; ; ; ; ; ; - ; ;;;;; ;;;; ;;;; ; ;;; ;;; ;;;; - - (define-struct trace-struct (evnt-rcvr thunk)) ; frp:event-receiver - - (define-struct debug-client (modpath ; complete-path of the module - tracepoints ; hash-table of traces - line-col->pos ; memoized O(n) function to map line/col -> byte offset - pattern->pos - process)) ; parent debug-process - - (define-struct debug-process (custodian ; If you shutdown-all it will kill the debugger process - run-semaphore ; When you post to this the debuggee will continue executing - running-e ; #t on this event resumes, #f pauses - run-manager ; saves behavior that actually pauses/resumes from GC - pause-requested? - resume-requested? - policy - - exited? ; FrTime cell receives #t when the target exits - exceptions ; (an event stream) Exceptions thrown during the evaluation of the target - main-client ; the main client module that will be run - clients ; list of all the clients attached to this process - top-level - - where ; a behavior signaling each position where we pause - marks)) ; while paused, the marks at the point of the pause (else false) - - (define-struct loc (reqspec after?)) - (define-struct (loc/lc loc) (line col)) - (define-struct (loc/p loc) (pattern)) - - ;########################################################################################################### - - - - - ; ;;;;; ; ; ;;;;; ; - ; ; ; ; ; ;; ; ; - ; ; ; ; ; ; - ; ; ;;;;;; ;;; ; ; ;;; ;;;;; ; ; ;;; ;;; ;;;; ;;;;; ;;;; ; ;;; ;;;; - ; ; ; ;; ; ; ; ; ; ; ;; ; ; ; ; ; ; ; ;; ; ; - ; ;;; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; - ; ;;; ; ; ; ; ; ; ; ; ; ; ;;;;; ; ; ; ; ; - ; ; ; ; ; ; ; ; ; ; ;;;;;;; ; ; ; ; ; ; ;;;; - ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; - ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; - ; ; ; ; ; ; ;; ; ; ; ;; ; ; ; ; ; ;; ; ; ; ; ; ; - ; ;;;;; ;;;; ;;;; ; ;;; ;;; ;;;;; ; ;;;; ;;;; ; ;;; ;;;; ; ;;;; - - (define (create-empty-debug-client) - (make-debug-client null ; modpath - (make-hash) ; tracepoints - null ; line-col->pos function - null - null)) ; process - - ;########################################################################################################### - ) \ No newline at end of file diff --git a/collects/mztake/mztake.ss b/collects/mztake/mztake.ss deleted file mode 100644 index 68d26560cb..0000000000 --- a/collects/mztake/mztake.ss +++ /dev/null @@ -1,176 +0,0 @@ -(module mztake mzscheme - (require (lib "contract.ss") - (lib "match.ss") - (prefix frp: (lib "lang-ext.ss" "frtime")) - (rename (lib "frtime.ss" "frtime") frp:list list) - (rename (lib "frtime.ss" "frtime") frp:value-nowable? value-nowable?) - (rename (lib "frtime.ss" "frtime") frp:behaviorof behaviorof) - "mztake-structs.ss" - (lib "base-gm.ss" "frtime") - (lib "etc.ss") - (lib "list.ss") - "marks.ss" - "engine.ss") - - ;; Turn struct printing on for MzTake users. - (print-struct true) - - (provide (rename loc loc$) - debug-process-running-e - loc/r - trace - bind - define/bind - define/bind-e - [rename loc/opt-col loc] - [rename mztake-top #%top]) - - (provide/contract [exceptions (() (debug-process?) . opt-> . frp:event?)] - [exited? (() (debug-process?) . opt-> . frp:behavior?)] - [kill (() (debug-process?) . opt-> . void?)] - [kill-all (-> void?)] - [set-running-e! ((frp:event?) (debug-process?) . opt-> . any)] - [set-running! ((frp:value-nowable?) (debug-process?) . opt-> . any)] - [where (() (debug-process?) . opt-> . frp:event?)] - - [current-policy (case-> (-> any) - (any/c . -> . void?))] - [current-process (case-> (-> debug-process?) - (debug-process? . -> . void?))] - [current-reqspec (case-> (-> string?) - (string? . -> . void?))] - [create-debug-process (-> debug-process?)] - [set-main! ((require-spec?) (debug-process?) . opt-> . void?)] - [trace* (debug-process? loc? (-> any) . -> . frp:event?)] - [bind* (debug-process? symbol? . -> . any)]) - - (define (loc* after?) - (define (set-r r) (current-reqspec r)) - (match-lambda* - [(arg) ((loc* after?) (current-reqspec) arg)] - [((and (not (? require-spec?)) arg) args ...) (apply (loc* after?) (current-reqspec) arg args)] - [((? require-spec? r) (? number? line)) (set-r r) (make-loc/lc r after? line false)] - [((? require-spec? r) (? number? line) (? number? col)) (set-r r) (make-loc/lc r after? line col)] - [((? require-spec? r) pattern) (set-r r) (make-loc/p r after? pattern)])) - - (define loc/r (loc* true)) - - (define loc/opt-col (loc* false)) - - (define exceptions - (opt-lambda ([p (current-process)]) - (debug-process-exceptions p))) - - (define exited? - (opt-lambda ([p (current-process)]) - (debug-process-exited? p))) - - (define kill - (opt-lambda ([p (current-process)]) - (unless (debug-process-exited? p) - (process:->dead p)))) - - (define (kill-all) - (unless (empty? all-debug-processes) - (for-each (lambda (p) (kill p)) all-debug-processes) - (display "All debug processes have been killed."))) - - (define set-running-e! - (opt-lambda (e [process (current-process)]) - (resume process) - (frp:set-cell! (debug-process-running-e process) e))) - - (define set-running! - (opt-lambda (b [process (current-process)]) - (if (frp:value-now b) (resume process) (pause process)) - (frp:set-cell! (debug-process-running-e process) (frp:changes b)))) - - (define where - (opt-lambda ([p (current-process)]) - (unless (debug-process-where p) - (set-debug-process-where! p (frp:event-receiver))) - (debug-process-where p))) - - (define current-process (make-parameter (create-debug-process))) - (define current-reqspec (make-parameter false)) - - (define set-main! - (opt-lambda (reqspec [p (current-process)]) - (current-reqspec reqspec ) - (process:set-main! p reqspec))) - - (define-syntax trace - (syntax-rules (=>) - [(_ loc) - (let ([loc* loc]) - (if (loc-after? loc*) - (trace* (current-process) loc* identity) - (trace* (current-process) loc* (lambda () true))))] - [(_ loc => proc) - (trace* (current-process) loc proc)] - [(_ loc body ...) - (trace* (current-process) loc (lambda () body ...))])) - - (define (mztake-top* name thunk) - (if (debug-process-marks (current-process)) - (with-handlers - ([exn:fail? - (lambda (exn) - (with-handlers - ([exn:fail? (lambda (exn2) (raise exn2))]) - (bind* (current-process) name)))]) - (thunk)) - (thunk))) - - (define-syntax (mztake-top stx) - (syntax-case stx () - [(_ . name) - #'(mztake-top* 'name (lambda () (#%top . name)))])) - - (define (lookup-in-top-level p name) - (let/ec success - (define (try m) - (let/ec fail - (define (fail*) (fail false)) - (success (hash-get (hash-get (debug-process-top-level p) m fail*) name fail*)))) - (for-each try (map mark-module-name (debug-process-marks p))) - (hash-for-each (debug-process-top-level p) (lambda (m ns) (try m))) - (error 'bind "variable `~a' not found in target at the current location" name))) - - (define (bind* p name) - (unless (debug-process-marks p) - (error "Bind called but the target process is not paused.")) - - (let ([bs (lookup-all-bindings - (lambda (id) (eq? (syntax-e id) name)) - (debug-process-marks p))]) - (if (empty? bs) - (lookup-in-top-level p name) - (mark-binding-value (first bs))))) - - (define-syntax bind - (syntax-rules () - [(_ (name ...) body0 body ...) - (let* ([p (current-process)] - [name (bind* p 'name)] - ...) - body0 body ...)])) - - (define-syntax define/bind-e - (syntax-rules () - [(_ loc name ...) - (begin - (define here loc) - (define name (trace here (bind (name) name))) - ...)])) - - (define-syntax define/bind - (syntax-rules () - [(_ loc name ...) - (begin - (define here loc) - (define name (frp:hold (trace here (bind (name) name)))) - ...)])) - - - ) \ No newline at end of file diff --git a/collects/mztake/useful-code.ss b/collects/mztake/useful-code.ss deleted file mode 100644 index 0b45c0b3fe..0000000000 --- a/collects/mztake/useful-code.ss +++ /dev/null @@ -1,64 +0,0 @@ -(module useful-code frtime - - (require (lib "string.ss") - (lib "contract.ss") - (lib "list.ss")) - - (provide (all-defined)) - - ; Keeps a list of the last n values of a behavior - (define/contract history-e (case-> (event? . -> . any) - (event? number? . -> . any)) - (case-lambda [(stream) - (define ((add-to-complete-hist x) hist) (append hist (list x))) - (accum-e (stream . ==> . add-to-complete-hist) empty)] - - [(stream n) - (define ((add-to-short-hist x) hist) (append (if (< (length hist) n) hist (rest hist)) (list x))) - (accum-e (stream . ==> . add-to-short-hist) empty)])) - - (define/contract history-b (case-> (event? . -> . any) - (event? number? . -> . any)) - (case-lambda [(stream) (hold (history-e stream) empty)] - [(stream n) (hold (history-e stream n) empty)])) - - ; Counts number of events on an event stream - (define/contract count-b (event? . -> . any) - (lambda (stream) - (hold (accum-e (stream . -=> . add1) 0) 0))) - - ; Keeps track of the largest value seen on a stream - (define/contract largest-val-b (event? . -> . any) - (lambda (stream) - (hold (accum-e (stream - . ==> . - (lambda (last) - (lambda (x) - (if (> x last) x last)))) - -inf.0)))) - - ; Keeps track of the smallest value seen on a stream - (define/contract smallest-val-b (event? . -> . any) - (lambda (stream) - (hold (accum-e (stream - . ==> . - (lambda (last) - (lambda (x) - (if (< x last) x last)))) - +inf.0)))) - - ; Matches a sequence of items in a list to event pings - (define/contract sequence-match? ((listof any/c) . -> . any) - (lambda (seq evs) - (equal? seq (history-b evs (length seq))))) - - ; Cheap printf for behaviors - (define printf-b format) - - ; Flattens a list - (define (flatten x) - (cond ((empty? x) '()) - ((and (list? x) - (list? (first x))) - (append (flatten (car x)) (flatten (cdr x)))) - (else (list x))))) \ No newline at end of file diff --git a/collects/tests/mztake/engine-test.ss b/collects/tests/mztake/engine-test.ss deleted file mode 100644 index 4789d6ad78..0000000000 --- a/collects/tests/mztake/engine-test.ss +++ /dev/null @@ -1,12 +0,0 @@ -(module engine-test mzscheme - - (require "../engine.ss") - - (define stx (read-all-syntax "../demos/dijkstra/dijkstra.ss")) - - (define fn (pattern->pos stx)) - (define result (fn '(define (_ ...) _ ...))) - - (define expected '((7 2 147) (18 2 463))) - (printf "~a~n" (list (equal? result expected) result expected)) - ) \ No newline at end of file diff --git a/collects/tests/mztake/mztake-test.ss b/collects/tests/mztake/mztake-test.ss deleted file mode 100644 index edf9800be5..0000000000 --- a/collects/tests/mztake/mztake-test.ss +++ /dev/null @@ -1,7 +0,0 @@ -(require (as-is mzscheme load) - (as-is "test-harness.ss" test)) -(load "../demos/dijkstra/dijkstra-mztake.ss") -(map-e (lambda (e) - (unless e - (test (dv:vector-length (t-data heap)) 5))) - (debug-process-running-e (current-process))) diff --git a/collects/tests/mztake/test-harness.ss b/collects/tests/mztake/test-harness.ss deleted file mode 100644 index bafc2a43a5..0000000000 --- a/collects/tests/mztake/test-harness.ss +++ /dev/null @@ -1,75 +0,0 @@ -(module test-harness mzscheme - (provide (all-defined)) - (require (lib "list.ss") - (lib "etc.ss") - (lib "pretty.ss")) - - (define print-tests (make-parameter #f)) - (define test-inspector (make-parameter (current-inspector))) - (define test-inexact-epsilon (make-parameter 0.01)) - - (define-struct (exn:test exn) ()) - - (define (install-test-inspector) - (test-inspector (current-inspector)) - (current-inspector (make-inspector)) - (print-struct #t)) - - (define (may-print-result result) - (parameterize ([current-inspector (test-inspector)] - [print-struct #t]) - (when (or (eq? (print-tests) (first result)) - (eq? (print-tests) #t)) - (pretty-print result)) - (when (and (eq? (print-tests) 'stop) - (eq? (first result) 'bad)) - (raise (make-exn:test (format "test failed: ~a" result) - (current-continuation-marks)))))) - - - (define test - (opt-lambda (result expected [compare equal?]) - (let* ([test-result - (cond [(or (and (number? result) (not (exact? result))) - (and (number? expected) (not (exact? expected)))) - (< (abs (- result expected)) (test-inexact-epsilon))] - [else - (parameterize ([current-inspector (test-inspector)]) - (compare result expected))])] - [to-print (if test-result - (list 'good result expected) - (list 'bad result expected))]) - - (may-print-result to-print) - to-print))) - - (define (test/pred result pred) - (let* ([test-result (pred result)] - [to-print (if test-result - (list 'good result test-result) - (list 'bad result test-result))]) - (may-print-result to-print) - to-print)) - - (define (test/exn thunk expected-exception-msg) - (unless (and (procedure? thunk) - (procedure-arity-includes? thunk 0)) - (error (format - "the first argument to test/exn should be a function of no arguments (a \"thunk\"), got ~a" - thunk))) - (let* ([result - (with-handlers - ([void (lambda (exn) exn)]) - (thunk))] - [test-result - (if (and (exn? result) - (regexp-match expected-exception-msg (exn-message result))) - (list 'good result expected-exception-msg) - (list 'bad result expected-exception-msg))]) - (may-print-result test-result) - test-result)) - - (install-test-inspector) - ) - -