props etc

svn: r187
This commit is contained in:
Eli Barzilay 2005-06-16 00:22:41 +00:00
parent d4d279ec7a
commit cfce6631b3
33 changed files with 2828 additions and 2828 deletions

View File

@ -1,40 +1,40 @@
(require (lib "mztake.ss" "mztake") (require (lib "mztake.ss" "mztake")
"dijkstra-solver.ss" "dijkstra-solver.ss"
(lib "match.ss")) (lib "match.ss"))
(define/bind (loc "heap.ss" 49 6) item) (define/bind (loc "heap.ss" 49 6) item)
(define/bind (loc "heap.ss" 67 10) result) (define/bind (loc "heap.ss" 67 10) result)
(define (not-in-order e) (define (not-in-order e)
(filter-e (filter-e
(match-lambda (match-lambda
[('reset _) false] [('reset _) false]
[(_ 'reset) false] [(_ 'reset) false]
[(previous current) (> previous current)] [(previous current) (> previous current)]
[else false]) [else false])
(history-e 2 e))) (history-e 2 e)))
(define inserts-and-removes-e (merge-e (removes . ==> . node-weight) (define inserts-and-removes-e (merge-e (removes . ==> . node-weight)
(inserts . -=> . 'reset))) (inserts . -=> . 'reset)))
(define violations (not-in-order inserts-and-removes-e)) (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 inserts and removes: ~a" (history-b inserts-and-removes-e))
(printf-b "all violations: ~a" (history-b violations)) (printf-b "all violations: ~a" (history-b violations))
(printf-b "latest-violation: ~a" (hold violations)) (printf-b "latest-violation: ~a" (hold violations))
#| Implementation of the local model follows... |# #| Implementation of the local model follows... |#
(define ((insert-in-model item) model) (define ((insert-in-model item) model)
(printf "~nInserting ~a into model containing:~n~a~n" item (value-now model)) (printf "~nInserting ~a into model containing:~n~a~n" item (value-now model))
(cons item model)) (cons item model))
(define ((remove-from-model item) model) (define ((remove-from-model item) model)
(printf "~nRemoving ~a from model containing:~n~a~n" item (value-now model)) (printf "~nRemoving ~a from model containing:~n~a~n" item (value-now model))
(filter (lambda (i) (not (equal? i item))) model)) (filter (lambda (i) (not (equal? i item))) model))
(define inserters (accum-b (inserts . ==> . insert-in-model) empty)) (define inserters (accum-b (inserts . ==> . insert-in-model) empty))
(define removers (accum-b (removes . ==> . remove-from-model) inserters)) (define removers (accum-b (removes . ==> . remove-from-model) inserters))
(set-running-e! (violations . -=> . false)) (set-running-e! (violations . -=> . false))

View File

@ -1,84 +1,84 @@
#| This script tests a priority queue (heap) that is correctly implemented, but incorrectly used. #| 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 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 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), "A Dataflow Language for Scriptable Debugging" (Marceau, Cooper, Krishnamurthi, Reiss),
available at: available at:
http://www.cs.brown.edu/~sk/Publications/Papers/Published/mckr-dataflow-lang-script-debug/ 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, 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, 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 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 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 "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, it is working correctly or not. Our model shows the values we should be getting from the program,
but clearly are not. but clearly are not.
To provide some context for this demo, and what debugging problem MzTake helps us explore, I offer 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: 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 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. 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: 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 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 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 the queue is not sensitive to these updates, what it returns is no longer the
smallest element in the queue. smallest element in the queue.
On further reading, we trace the error to a subtle detail in the description of 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 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 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 sparse graphs, but subsequently amends the pseudocode to say that the assignment
to dest.weight must explicitly invoke a key-decrement operation. Our error, 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) therefore, was not in the implementation of the heap, but in using the (faster)
binary heap implementation without satisfying its (stronger) contract. |# binary heap implementation without satisfying its (stronger) contract. |#
(require "dijkstra-solver.ss" (require "dijkstra-solver.ss"
(lib "match.ss")) (lib "match.ss"))
(define-mztake-process p (define-mztake-process p
("dijkstra.ss") ("dijkstra.ss")
("heap.ss" [inserts 49 6 bind 'item] ("heap.ss" [inserts 49 6 bind 'item]
[removes 67 10 bind 'result])) [removes 67 10 bind 'result]))
#| The following code merely observes the insertions and removals #| The following code merely observes the insertions and removals
from the heap. We notice whether any of the removals are out 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 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 no insertions between the two events. We can keep track of the
last 2 using history-e. |# last 2 using history-e. |#
(define (not-in-order e) (define (not-in-order e)
(filter-e (filter-e
(match-lambda (match-lambda
[('reset _) false] [('reset _) false]
[(_ 'reset) false] [(_ 'reset) false]
[(previous current) (> previous current)] [(previous current) (> previous current)]
[else false]) [else false])
(history-e 2 e))) (history-e 2 e)))
(define inserts-and-removes-e (merge-e (removes . ==> . node-weight) (define inserts-and-removes-e (merge-e (removes . ==> . node-weight)
(inserts . -=> . 'reset))) (inserts . -=> . 'reset)))
(define violations (not-in-order inserts-and-removes-e)) (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 inserts and removes: ~a" (history-b inserts-and-removes-e))
(printf-b "all violations: ~a" (history-b violations)) (printf-b "all violations: ~a" (history-b violations))
(printf-b "latest-violation: ~a" (hold violations)) (printf-b "latest-violation: ~a" (hold violations))
#| This output indicates that the queue has yielded nodes whose weights are out of order. #| 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. |# This confirms our suspicion that the problem somehow involves the priority queue. |#
#| Implementation of the local model follows... |# #| Implementation of the local model follows... |#
(define ((insert-in-model item) model) (define ((insert-in-model item) model)
(printf "~nInserting ~a into model containing:~n~a~n" item (value-now model)) (printf "~nInserting ~a into model containing:~n~a~n" item (value-now model))
(cons item model)) (cons item model))
(define ((remove-from-model item) model) (define ((remove-from-model item) model)
(printf "~nRemoving ~a from model containing:~n~a~n" item (value-now model)) (printf "~nRemoving ~a from model containing:~n~a~n" item (value-now model))
(filter (lambda (i) (not (equal? i item))) model)) (filter (lambda (i) (not (equal? i item))) model))
(define inserters (accum-b (inserts . ==> . insert-in-model) empty)) (define inserters (accum-b (inserts . ==> . insert-in-model) empty))
(define removers (accum-b (removes . ==> . remove-from-model) inserters)) (define removers (accum-b (removes . ==> . remove-from-model) inserters))
(start/resume p) (start/resume p)

View File

@ -1,49 +1,49 @@
(module dijkstra-solver mzscheme (module dijkstra-solver mzscheme
(require "heap.ss" (require "heap.ss"
(lib "list.ss") (lib "list.ss")
"graph.ss") "graph.ss")
(provide (all-defined)) (provide (all-defined))
(define (make-node label x y weight) (vector label x y weight)) (define (make-node label x y weight) (vector label x y weight))
(define (node-label n) (vector-ref n 0)) (define (node-label n) (vector-ref n 0))
(define (node-x n) (vector-ref n 1)) (define (node-x n) (vector-ref n 1))
(define (node-y n) (vector-ref n 2)) (define (node-y n) (vector-ref n 2))
(define (node-weight n) (vector-ref n 3)) (define (node-weight n) (vector-ref n 3))
(define (set-node-weight! n v) (vector-set! n 3 v)) (define (set-node-weight! n v) (vector-set! n 3 v))
(define (node< a b) (< (node-weight a) (node-weight b))) (define (node< a b) (< (node-weight a) (node-weight b)))
(define (sqr x) (* x x)) (define (sqr x) (* x x))
(define (distance-to a b) (define (distance-to a b)
(sqrt (+ (sqr (- (node-x a) (node-x b))) (sqrt (+ (sqr (- (node-x a) (node-x b)))
(sqr (- (node-y a) (node-y b)))))) (sqr (- (node-y a) (node-y b))))))
(define (hash-table-pairs hash) (define (hash-table-pairs hash)
(hash-table-map hash (lambda (key val) (list key val)))) (hash-table-map hash (lambda (key val) (list key val))))
(define (relax backtrace heap origin dest) (define (relax backtrace heap origin dest)
(let ([candidate-weight (let ([candidate-weight
(+ (node-weight origin) (+ (node-weight origin)
(distance-to origin dest))]) (distance-to origin dest))])
(when (candidate-weight . < . (node-weight dest)) (when (candidate-weight . < . (node-weight dest))
(set-node-weight! dest candidate-weight) (set-node-weight! dest candidate-weight)
;;(heap-resort heap dest) ;;(heap-resort heap dest)
(hash-table-put! backtrace dest origin)))) (hash-table-put! backtrace dest origin))))
(define (solve graph nodes source) (define (solve graph nodes source)
(let ([backtrace (make-hash-table)] (let ([backtrace (make-hash-table)]
[heap (make-heap node< eq?)]) [heap (make-heap node< eq?)])
(set-node-weight! source 0) (set-node-weight! source 0)
(for-each (lambda (node) (heap-insert heap node)) (for-each (lambda (node) (heap-insert heap node))
nodes) nodes)
(let loop () (let loop ()
(unless (heap-empty? heap) (unless (heap-empty? heap)
(let* ([node (heap-pop heap)] (let* ([node (heap-pop heap)]
[successors (graph-succs graph node)]) [successors (graph-succs graph node)])
(for-each (for-each
(lambda (succ) (relax backtrace heap node succ)) (lambda (succ) (relax backtrace heap node succ))
successors)) successors))
(loop))) (loop)))
(hash-table-pairs backtrace)))) (hash-table-pairs backtrace))))

View File

@ -1,32 +1,32 @@
(module dijkstra mzscheme (module dijkstra mzscheme
(require "dijkstra-solver.ss" (require "dijkstra-solver.ss"
"graph.ss" "graph.ss"
(lib "list.ss")) (lib "list.ss"))
(print-struct #t) (print-struct #t)
(define g (make-graph 'directed)) (define g (make-graph 'directed))
(define (m-node label x y) (make-node label x y +inf.0)) (define (m-node label x y) (make-node label x y +inf.0))
(define nodes (define nodes
(list (list
(m-node 'J 200 100) (m-node 'J 200 100)
(m-node 's 100 125) (m-node 's 100 125)
(m-node '1 150 100) (m-node '1 150 100)
(m-node '2 150 150) (m-node '2 150 150)
(m-node '4 250 100) (m-node '4 250 100)
(m-node '5 300 100) (m-node '5 300 100)
(m-node '6 300 150))) (m-node '6 300 150)))
(for-each (lambda (n) (graph-node-add! g n)) nodes) (for-each (lambda (n) (graph-node-add! g n)) nodes)
(define (n-ref label) (define (n-ref label)
(first (filter (lambda (n) (eq? label (node-label n))) nodes))) (first (filter (lambda (n) (eq? label (node-label n))) nodes)))
(define edges (define edges
(list (list (n-ref 's) (n-ref '1)) (list (list (n-ref 's) (n-ref '1))
(list (n-ref 's) (n-ref '2)) (list (n-ref 's) (n-ref '2))
(list (n-ref '1) (n-ref 'J)) (list (n-ref '1) (n-ref 'J))
(list (n-ref '4) (n-ref '5)) (list (n-ref '4) (n-ref '5))
(list (n-ref 'J) (n-ref '4)) (list (n-ref 'J) (n-ref '4))
(list (n-ref 'J) (n-ref '6)))) (list (n-ref 'J) (n-ref '6))))
(for-each (lambda (e) (graph-edge-add! g (first e) (second e))) (for-each (lambda (e) (graph-edge-add! g (first e) (second e)))
edges) edges)
(printf "~n~n---output from dijkstra.ss:~n~a~n---~n" (printf "~n~n---output from dijkstra.ss:~n~a~n---~n"
(solve g (reverse nodes) (n-ref 's)))) (solve g (reverse nodes) (n-ref 's))))

File diff suppressed because it is too large Load Diff

View File

@ -1,162 +1,162 @@
(module heap mzscheme (module heap mzscheme
(require (lib "etc.ss") (require (lib "etc.ss")
"base-gm.ss" "base-gm.ss"
"dv.ss") "dv.ss")
(provide make-heap heap-empty? heap-size heap-insert heap-pop (provide make-heap heap-empty? heap-size heap-insert heap-pop
heap-peak heap-remove heap-find heap-peak heap-remove heap-find
heap-contains heap-resort heap-tostring) heap-contains heap-resort heap-tostring)
(define-struct t (sorter equality data)) (define-struct t (sorter equality data))
;; sorter: elements which have the most trueness according to ;; sorter: elements which have the most trueness according to
;; the sorter pop out first ;; the sorter pop out first
(define (make-heap sorter equality) (define (make-heap sorter equality)
(let ((data (dv:make 5))) (let ((data (dv:make 5)))
(dv:append data 0) (dv:append data 0)
(make-t sorter equality data))) (make-t sorter equality data)))
(define (heap-size heap) (define (heap-size heap)
(- (dv:length (t-data heap)) 1)) (- (dv:length (t-data heap)) 1))
(define (heap-empty? heap) (define (heap-empty? heap)
(= (heap-size heap) 0)) (= (heap-size heap) 0))
(define (heap-last heap) (define (heap-last heap)
(- (dv:length (t-data heap)) 1)) (- (dv:length (t-data heap)) 1))
(define (heap-parent i) (define (heap-parent i)
(floor (/ i 2))) (floor (/ i 2)))
(define (heap-left i) (* i 2)) (define (heap-left i) (* i 2))
(define (heap-right i) (+ 1 (* i 2))) (define (heap-right i) (+ 1 (* i 2)))
(define (heap-has-right heap i) (define (heap-has-right heap i)
(<= (heap-right i) (heap-last heap))) (<= (heap-right i) (heap-last heap)))
(define (heap-has-left heap i) (define (heap-has-left heap i)
(<= (heap-left i) (heap-last heap))) (<= (heap-left i) (heap-last heap)))
(define (heap-insert heap item) (define (heap-insert heap item)
(let* ((sorter (t-sorter heap)) (let* ((sorter (t-sorter heap))
(data (t-data heap))) (data (t-data heap)))
(dv:append data item) (dv:append data item)
(let ((d (let loop ((prev (heap-last heap)) (let ((d (let loop ((prev (heap-last heap))
(current (heap-parent (heap-last heap)))) (current (heap-parent (heap-last heap))))
(cond ((= current 0) prev) (cond ((= current 0) prev)
((sorter item (dv:ref data current)) ((sorter item (dv:ref data current))
(dv:set! data prev (dv:ref data current)) (dv:set! data prev (dv:ref data current))
(loop current (heap-parent current))) (loop current (heap-parent current)))
(#t prev))))) (#t prev)))))
(dv:set! data d item)))) (dv:set! data d item))))
(define (heap-peak heap) (define (heap-peak heap)
(if (= (heap-size heap) 0) (error "heap-peak: empty") (if (= (heap-size heap) 0) (error "heap-peak: empty")
(dv:ref (t-data heap) 1))) (dv:ref (t-data heap) 1)))
(define (heap-pop heap) (define (heap-pop heap)
(if (= (heap-size heap) 0) (error "heap-pop: empty") (if (= (heap-size heap) 0) (error "heap-pop: empty")
(let ([result (dv:ref (t-data heap) 1)]) (let ([result (dv:ref (t-data heap) 1)])
(heap-remove-pos heap 1) (heap-remove-pos heap 1)
result))) result)))
(define (heap-remove-pos heap pos) (define (heap-remove-pos heap pos)
(let* ((data (t-data heap)) (let* ((data (t-data heap))
(sorter (t-sorter heap))) (sorter (t-sorter heap)))
(cond ((= 0 (heap-size heap)) (error "heap: removing from empty")) (cond ((= 0 (heap-size heap)) (error "heap: removing from empty"))
((= pos (heap-last heap)) (dv:remove-last data)) ((= pos (heap-last heap)) (dv:remove-last data))
(#t (let ((item (dv:ref data (heap-last heap)))) (#t (let ((item (dv:ref data (heap-last heap))))
(dv:remove-last data) (dv:remove-last data)
(let loop ((current pos)) (let loop ((current pos))
(dv:set! data current item) (dv:set! data current item)
(let* ((left (heap-left current)) (let* ((left (heap-left current))
(right (heap-right current)) (right (heap-right current))
(best-1 (if (and (heap-has-left heap current) (best-1 (if (and (heap-has-left heap current)
(sorter (dv:ref data left) item)) (sorter (dv:ref data left) item))
left current)) left current))
(best-2 (if (and (heap-has-right heap current) (best-2 (if (and (heap-has-right heap current)
(sorter (dv:ref data right) (sorter (dv:ref data right)
(dv:ref data best-1))) (dv:ref data best-1)))
right best-1))) right best-1)))
(if (not (= best-2 current)) (if (not (= best-2 current))
(begin (dv:set! data current (dv:ref data best-2)) (begin (dv:set! data current (dv:ref data best-2))
(loop best-2)))))))))) (loop best-2))))))))))
;; return false if the object is not found ;; return false if the object is not found
(define (heap-remove heap item) (define (heap-remove heap item)
(let ((pos (heap-find heap item))) (let ((pos (heap-find heap item)))
(if (not pos) false (if (not pos) false
(begin (heap-remove-pos heap pos) true)))) (begin (heap-remove-pos heap pos) true))))
(define (heap-contains heap item) (define (heap-contains heap item)
(if (heap-find heap item) true false)) (if (heap-find heap item) true false))
(define (heap-find heap item) (define (heap-find heap item)
(let ((data (t-data heap)) (let ((data (t-data heap))
(equality (t-equality heap)) (equality (t-equality heap))
(sorter (t-sorter heap))) (sorter (t-sorter heap)))
(let loop ((current 1)) (let loop ((current 1))
(let ((current-item (dv:ref data current))) (let ((current-item (dv:ref data current)))
(cond ((equality item current-item) current) (cond ((equality item current-item) current)
((sorter item current-item) #f) ((sorter item current-item) #f)
(#t (or (and (heap-has-left heap current) (#t (or (and (heap-has-left heap current)
(not (sorter item (dv:ref data (heap-left current)))) (not (sorter item (dv:ref data (heap-left current))))
(loop (heap-left current))) (loop (heap-left current)))
(and (heap-has-right heap current) (and (heap-has-right heap current)
(not (sorter item (dv:ref data (heap-right current)))) (not (sorter item (dv:ref data (heap-right current))))
(loop (heap-right current)))))))))) (loop (heap-right current))))))))))
(define (heap-resort heap item) (define (heap-resort heap item)
(heap-remove heap item) (heap-remove heap item)
(heap-insert heap item)) (heap-insert heap item))
(define (heap-tostring heap . fns) (define (heap-tostring heap . fns)
(let* ((data (t-data heap)) (let* ((data (t-data heap))
(data-list (let loop ((i 1)) (data-list (let loop ((i 1))
(if (> i (heap-last heap)) empty (if (> i (heap-last heap)) empty
(cons (dv:ref data i) (loop (+ i 1))))))) (cons (dv:ref data i) (loop (+ i 1)))))))
(string-append "heap: sz " (number->string (heap-size heap)) ", " (string-append "heap: sz " (number->string (heap-size heap)) ", "
(apply to-string (cons data-list fns))))) (apply to-string (cons data-list fns)))))
(define (test) (define (test)
(define f (make-heap > eq?)) (define f (make-heap > eq?))
(define d (t-data f)) (define d (t-data f))
(heap-insert f 99) (heap-insert f 99)
(debug "A " d) (debug "A " d)
(heap-remove-pos f 1) (heap-remove-pos f 1)
(debug "B " d) (debug "B " d)
(for-each (lambda (x) (heap-insert f x)) '(1 2 3 4 5 6 7 8 9 10 11 12 13 14)) (for-each (lambda (x) (heap-insert f x)) '(1 2 3 4 5 6 7 8 9 10 11 12 13 14))
(debug "C " d) (debug "C " d)
(heap-remove f 10) (debug " " d) (heap-remove f 10) (debug " " d)
(heap-remove f 5) (debug " " d) (heap-remove f 5) (debug " " d)
(heap-remove f 8) (debug " " d) (heap-remove f 8) (debug " " d)
(heap-remove f 13) (debug " " d) (heap-remove f 13) (debug " " d)
(debug (heap-contains f 11)) (debug (heap-contains f 11))
(debug (heap-contains f 123)) (debug (heap-contains f 123))
(heap-pop f) (heap-pop f)
(heap-pop f) (heap-pop f)
(heap-pop f) (heap-pop f)
(heap-pop f) (debug " " d) (heap-pop f) (debug " " d)
(debug (heap-contains f 11)) (debug (heap-contains f 11))
(debug (heap-contains f 4)) (debug (heap-contains f 4))
(debug (heap-tostring f)) (debug (heap-tostring f))
(heap-remove f 2) (heap-remove f 2)
(debug (heap-tostring f)) (debug (heap-tostring f))
(heap-remove f 3) (heap-remove f 3)
(debug (heap-tostring f)) (debug (heap-tostring f))
) )
) )

View File

@ -1,7 +1,7 @@
(set-main! "exception.ss") (set-main! "exception.ss")
(printf-b "exception.ss exited? ~a" (process:exited?)) (printf-b "exception.ss exited? ~a" (process:exited?))
(printf-b "last exception seen: ~a" (hold (process:exceptions))) (printf-b "last exception seen: ~a" (hold (process:exceptions)))
(set-running! true) (set-running! true)

View File

@ -1,16 +1,16 @@
#| This program starts a thread, the thread raises an exception, #| This program starts a thread, the thread raises an exception,
this tests how MzTake catches exceptions, even if they come from this tests how MzTake catches exceptions, even if they come from
anonymous locations. anonymous locations.
We don't even need to bind any variables or add any breaks, we just We don't even need to bind any variables or add any breaks, we just
run the program and catch the exception it throws. |# run the program and catch the exception it throws. |#
(define-mztake-process p ("exception.ss")) (define-mztake-process p ("exception.ss"))
(printf-b "exception.ss exited? ~a" (process:exited? p)) (printf-b "exception.ss exited? ~a" (process:exited? p))
#| Prints out a behavior that tells you whether the debug-process is still running... |# #| Prints out a behavior that tells you whether the debug-process is still running... |#
(printf-b "last exception seen: ~a" (hold (process:exceptions p))) (printf-b "last exception seen: ~a" (hold (process:exceptions p)))
#| Prints out the last exception that the program threw |# #| Prints out the last exception that the program threw |#
(start/resume p) (start/resume p)

View File

@ -1,2 +1,2 @@
(module exception mzscheme (module exception mzscheme
(thread (lambda () (raise 'exn:oops-made-a-mztake!)))) (thread (lambda () (raise 'exn:oops-made-a-mztake!))))

View File

@ -1,15 +1,15 @@
(define x-before-let (trace (loc "first-class.ss" 3 29) (bind (x) x))) (define x-before-let (trace (loc "first-class.ss" 3 29) (bind (x) x)))
(define x-in-let (trace (loc "first-class.ss" 4 25) (bind (x) x))) (define x-in-let (trace (loc "first-class.ss" 4 25) (bind (x) x)))
(define x-after-let (trace (loc "first-class.ss" 5 11) (bind (x) x))) (define x-after-let (trace (loc "first-class.ss" 5 11) (bind (x) x)))
(printf-b "Number of times x updates, should be 12: ~a" (printf-b "Number of times x updates, should be 12: ~a"
(count-b (merge-e x-before-let (count-b (merge-e x-before-let
x-in-let x-in-let
x-after-let))) x-after-let)))
(printf-b "x before let, should be (2 4 6 7): ~a" (history-b 4 x-before-let)) (printf-b "x before let, should be (2 4 6 7): ~a" (history-b 4 x-before-let))
(printf-b "x in let, should be (6 10 14 16): ~a" (history-b 4 x-in-let)) (printf-b "x in let, should be (6 10 14 16): ~a" (history-b 4 x-in-let))
(printf-b "x after let, should be (5 9 13 15): ~a" (history-b 4 x-after-let)) (printf-b "x after let, should be (5 9 13 15): ~a" (history-b 4 x-after-let))
(set-running! true) (set-running! true)

View File

@ -1,28 +1,28 @@
#| This program demonstrates how you can add traces to first class, anonymous functions, #| This program demonstrates how you can add traces to first class, anonymous functions,
such as those passed to map, and the traces will still respond from anywhere such as those passed to map, and the traces will still respond from anywhere
the code is executed. the code is executed.
This test also shows how you can bind to the same variable at different locations, This test also shows how you can bind to the same variable at different locations,
and recieve different values, watching how an algorithm unfolds. and recieve different values, watching how an algorithm unfolds.
Be sure you look at first-class.ss to see where the bindings are taken from, to get Be sure you look at first-class.ss to see where the bindings are taken from, to get
and idea of why they recieve different values from the same "x". |# and idea of why they recieve different values from the same "x". |#
(define-mztake-process p ("first-class.ss" [x-before-let 3 29 bind 'x] (define-mztake-process p ("first-class.ss" [x-before-let 3 29 bind 'x]
[x-in-let 4 25 bind 'x] [x-in-let 4 25 bind 'x]
[x-after-let 5 11 bind 'x])) [x-after-let 5 11 bind 'x]))
(printf-b "Number of times x updates, should be 12: ~a" (printf-b "Number of times x updates, should be 12: ~a"
(count-b (merge-e x-before-let (count-b (merge-e x-before-let
x-in-let x-in-let
x-after-let))) x-after-let)))
#| merge-e takes multiple event streams and turns them into one event stream. #| merge-e takes multiple event streams and turns them into one event stream.
count-e then counts how many pings are recieved on all three streams, count-e then counts how many pings are recieved on all three streams,
in other words, how many times "x" updates in all the traces. |# in other words, how many times "x" updates in all the traces. |#
(printf-b "x before let, should be (2 4 6 7): ~a" (history-b 4 x-before-let)) (printf-b "x before let, should be (2 4 6 7): ~a" (history-b 4 x-before-let))
(printf-b "x in let, should be (6 10 14 16): ~a" (history-b 4 x-in-let)) (printf-b "x in let, should be (6 10 14 16): ~a" (history-b 4 x-in-let))
(printf-b "x after let, should be (5 9 13 15): ~a" (history-b 4 x-after-let)) (printf-b "x after let, should be (5 9 13 15): ~a" (history-b 4 x-after-let))
#| Prints out a FIFO list containing the last 4 values seen by each trace. |# #| Prints out a FIFO list containing the last 4 values seen by each trace. |#
(start/resume p) (start/resume p)

View File

@ -1,6 +1,6 @@
(module first-class mzscheme (module first-class mzscheme
(map (lambda (x) (map (lambda (x)
(let* ([x (* 2 (+ 1 x))] (let* ([x (* 2 (+ 1 x))]
[x (sub1 x)]) [x (sub1 x)])
x)) x))
'(2 4 6 7))) '(2 4 6 7)))

View File

@ -1,28 +1,28 @@
(require (lib "mztake.ss" "mztake") (require (lib "mztake.ss" "mztake")
(lib "animation.ss" "frtime")) (lib "animation.ss" "frtime"))
(define/bind (loc "highway.ss" 3 4) speed) (define/bind (loc "highway.ss" 3 4) speed)
(printf-b "current speed: ~a" (hold values-of-speed)) (printf-b "current speed: ~a" (hold values-of-speed))
(printf-b "last ten speeds: ~a" (history-b 10 values-of-speed)) (printf-b "last ten speeds: ~a" (history-b 10 values-of-speed))
(map-e (lambda (a-speed) (when (>= a-speed 55) (pause radar-program))) (map-e (lambda (a-speed) (when (>= a-speed 55) (pause radar-program)))
values-of-speed) values-of-speed)
(define (make-speed-gauge speed) (define (make-speed-gauge speed)
(let ([center (make-posn 200 200)]) (let ([center (make-posn 200 200)])
(list (make-circle center 170 "black") (list (make-circle center 170 "black")
(make-circle center 160 "white") (make-circle center 160 "white")
(make-rect (make-posn 0 202) 1000 1000 "white") (make-rect (make-posn 0 202) 1000 1000 "white")
(make-line (make-posn 30 201) (make-posn 370 201) "black") (make-line (make-posn 30 201) (make-posn 370 201) "black")
(make-line center (make-line center
(posn+ center (make-posn (- (* 150 (cos (/ speed 30)))) (posn+ center (make-posn (- (* 150 (cos (/ speed 30))))
(- (* 150 (sin (/ speed 30)))))) (- (* 150 (sin (/ speed 30))))))
"red")))) "red"))))
(display-shapes (make-speed-gauge (hold values-of-speed))) (display-shapes (make-speed-gauge (hold values-of-speed)))
(set-runnning! true) (set-runnning! true)

View File

@ -1,55 +1,55 @@
#| The program being debugged (a module in "highway.ss") generates fake speed readings over and over. |# #| The program being debugged (a module in "highway.ss") generates fake speed readings over and over. |#
(require (lib "animation.ss" "frtime")) #| needed for display-shapes |# (require (lib "animation.ss" "frtime")) #| needed for display-shapes |#
(define-mztake-process radar-program ("highway.ss" [values-of-speed 3 4 bind 'speed])) (define-mztake-process radar-program ("highway.ss" [values-of-speed 3 4 bind 'speed]))
#| * Create a process to debug highway.ss #| * Create a process to debug highway.ss
* Add a tracepoint at line 3, column 4; in the program, * Add a tracepoint at line 3, column 4; in the program,
this is right before the program sleeps for 1 second. this is right before the program sleeps for 1 second.
* At this tracepoint, define "values-of-speed" to a FrTime eventstream that * At this tracepoint, define "values-of-speed" to a FrTime eventstream that
recieves events containing the current value of the variable `speed', recieves events containing the current value of the variable `speed',
which are sent every time the code at line 3, column 4, is reached. |# which are sent every time the code at line 3, column 4, is reached. |#
(printf-b "current speed: ~a" (hold values-of-speed)) (printf-b "current speed: ~a" (hold values-of-speed))
#| Prints the current speed being recorded |# #| Prints the current speed being recorded |#
(printf-b "last ten speeds: ~a" (history-b 10 values-of-speed)) (printf-b "last ten speeds: ~a" (history-b 10 values-of-speed))
#| prints a FIFO list of the last 10 speeds seen |# #| prints a FIFO list of the last 10 speeds seen |#
(map-e (lambda (a-speed) (when (>= a-speed 55) (pause radar-program))) (map-e (lambda (a-speed) (when (>= a-speed 55) (pause radar-program)))
values-of-speed) values-of-speed)
#| pauses the program for inspection when a speed is too fast |# #| pauses the program for inspection when a speed is too fast |#
#| produces a list of shapes to draw/animate, taking in a number for speed |# #| produces a list of shapes to draw/animate, taking in a number for speed |#
(define (make-speed-gauge speed) (define (make-speed-gauge speed)
(let ([center (make-posn 200 200)]) (let ([center (make-posn 200 200)])
(list (make-circle center 170 "black") (list (make-circle center 170 "black")
(make-circle center 160 "white") (make-circle center 160 "white")
(make-rect (make-posn 0 202) 1000 1000 "white") (make-rect (make-posn 0 202) 1000 1000 "white")
(make-line (make-posn 30 201) (make-posn 370 201) "black") (make-line (make-posn 30 201) (make-posn 370 201) "black")
#| draws the the half-circle guage |# #| draws the the half-circle guage |#
#| draws the red line for the current speed |# #| draws the red line for the current speed |#
(make-line center (make-line center
(posn+ center (make-posn (- (* 150 (cos (/ speed 30)))) (posn+ center (make-posn (- (* 150 (cos (/ speed 30))))
(- (* 150 (sin (/ speed 30)))))) (- (* 150 (sin (/ speed 30))))))
"red")))) "red"))))
(display-shapes (make-speed-gauge (hold values-of-speed))) (display-shapes (make-speed-gauge (hold values-of-speed)))
#| display-shapes takes a list of objects to draw. #| display-shapes takes a list of objects to draw.
(hold values-of-speed) keeps track of the current value of speed, (hold values-of-speed) keeps track of the current value of speed,
as seen on the eventstream, and that is passed to make-speed-guage, as seen on the eventstream, and that is passed to make-speed-guage,
which gets called every time values-of-speed gets a new speed. |# which gets called every time values-of-speed gets a new speed. |#
(start/resume radar-program) #| Start the process for highway.ss |# (start/resume radar-program) #| Start the process for highway.ss |#

View File

@ -1,5 +1,5 @@
(module highway mzscheme (module highway mzscheme
(let loop ([speed 0]) (let loop ([speed 0])
(sleep 1) (sleep 1)
;; Generate some fake speeds readings: ;; Generate some fake speeds readings:
(loop (+ speed 4)))) (loop (+ speed 4))))

View File

@ -1,25 +1,25 @@
(require (lib "graphics.ss" "graphics") (require (lib "graphics.ss" "graphics")
(lib "match.ss")) (lib "match.ss"))
(open-graphics) (open-graphics)
(define window (open-viewport "Debugger" 400 400)) (define window (open-viewport "Debugger" 400 400))
(define/bind (loc "montecarlo.ss" 13 13) x y pi) (define/bind (loc "montecarlo.ss" 13 13) x y pi)
(printf-b "total points chosen: ~a" (count-b (changes x))) (printf-b "total points chosen: ~a" (count-b (changes x)))
(printf-b "current computed value of pi: ~a" current-pi) (printf-b "current computed value of pi: ~a" current-pi)
(printf-b "log error: ~a" (log (abs (- current-pi 3.141592653)))) (printf-b "log error: ~a" (log (abs (- current-pi 3.141592653))))
((draw-viewport window) "wheat") ((draw-viewport window) "wheat")
((draw-solid-ellipse window) (make-posn -4 -4) 408 408 "black") ((draw-solid-ellipse window) (make-posn -4 -4) 408 408 "black")
((draw-solid-ellipse window) (make-posn 0 0) 400 400 "sienna") ((draw-solid-ellipse window) (make-posn 0 0) 400 400 "sienna")
(map-e (match-lambda [(x y) ((draw-solid-ellipse window) (make-posn x y) (map-e (match-lambda [(x y) ((draw-solid-ellipse window) (make-posn x y)
3 3 "black")]) 3 3 "black")])
(changes (list x y))) (changes (list x y)))
(set-running! true) (set-running! true)

View File

@ -1,71 +1,71 @@
#| The program being debugged (a module in the file "montecarlo.ss") runs #| The program being debugged (a module in the file "montecarlo.ss") runs
an infinite loop, binding "x" and "y" to a random number between an infinite loop, binding "x" and "y" to a random number between
[-199,199], each iteration. [-199,199], each iteration.
This is supposed to represent throwing darts at a circular dartboard. This is supposed to represent throwing darts at a circular dartboard.
You keep a count of how many darts you have thrown, and a side count You keep a count of how many darts you have thrown, and a side count
for each time the dart is thrown within the circle. The ratio of for each time the dart is thrown within the circle. The ratio of
hits to total tries, multiplied by 4, approaches "pi" with some error, hits to total tries, multiplied by 4, approaches "pi" with some error,
usually closing in around 3.13. The target program does this computation usually closing in around 3.13. The target program does this computation
and binds it to the variable "pi". and binds it to the variable "pi".
This MzTake script visualizes the process, drawing points (darts) This MzTake script visualizes the process, drawing points (darts)
that "hit" the circle, a radius of 200 pixels from the center of that "hit" the circle, a radius of 200 pixels from the center of
the window. |# the window. |#
(require (lib "graphics.ss" "graphics")) (require (lib "graphics.ss" "graphics"))
#| Needed for open-graphics, open-viewport, and draw-solid-ellipse |# #| Needed for open-graphics, open-viewport, and draw-solid-ellipse |#
(open-graphics) (open-graphics)
(define window (open-viewport "Debugger" 400 400)) (define window (open-viewport "Debugger" 400 400))
#| This file doesn't animate a list of objects since the number of #| This file doesn't animate a list of objects since the number of
objects quickly reaches the thousands (slowing drawing time severly), objects quickly reaches the thousands (slowing drawing time severly),
and the dots are stationary -- so we just keep drawing the circles at and the dots are stationary -- so we just keep drawing the circles at
the random coordinates that we get from the target program. the random coordinates that we get from the target program.
See the doc for more information on this kind of drawing. |# See the doc for more information on this kind of drawing. |#
(define-mztake-process p ("montecarlo.ss" [x/y/pi-trace 13 13 bind '(x y pi)])) (define-mztake-process p ("montecarlo.ss" [x/y/pi-trace 13 13 bind '(x y pi)]))
#| * Create a process to debug montecarlo.ss #| * Create a process to debug montecarlo.ss
* Add a tracepoint at line 13, column 13; in the program, * Add a tracepoint at line 13, column 13; in the program,
this is right after the cond determined that the point *is* within this is right after the cond determined that the point *is* within
the radius of the circle, before starting the next iteration of the loop. the radius of the circle, before starting the next iteration of the loop.
* At this tracepoint, define "x/y/pi-trace" to a FrTime eventstream that * At this tracepoint, define "x/y/pi-trace" to a FrTime eventstream that
recieves events containing a list of the latest values of "x" "y" and "pi" recieves events containing a list of the latest values of "x" "y" and "pi"
in a list, every time the code at line 13, column 18, is reached. |# in a list, every time the code at line 13, column 18, is reached. |#
(define x/y/pi (hold x/y/pi-trace)) (define x/y/pi (hold x/y/pi-trace))
#| The local, time-varying variable "x/y/pi" is now is a FrTime behavior that always #| The local, time-varying variable "x/y/pi" is now is a FrTime behavior that always
holds the current (latest) list of values from x/y/pi-trace. |# holds the current (latest) list of values from x/y/pi-trace. |#
(define x (+ 200 (first x/y/pi))) (define x (+ 200 (first x/y/pi)))
(define y (+ 200 (second x/y/pi))) (define y (+ 200 (second x/y/pi)))
(define current-pi (third x/y/pi)) (define current-pi (third x/y/pi))
#| The local, time-varying variables "x" "y" and "current-pi" are bound to #| The local, time-varying variables "x" "y" and "current-pi" are bound to
their respective values in the list from x/y/pi. |# their respective values in the list from x/y/pi. |#
(printf-b "total points chosen: ~a" (count-b (changes x))) (printf-b "total points chosen: ~a" (count-b (changes x)))
(printf-b "current computed value of pi: ~a" current-pi) (printf-b "current computed value of pi: ~a" current-pi)
(printf-b "log error: ~a" (log (abs (- current-pi 3.141592653)))) ;; the more negative, the better... (printf-b "log error: ~a" (log (abs (- current-pi 3.141592653)))) ;; the more negative, the better...
((draw-viewport window) "wheat") ((draw-viewport window) "wheat")
((draw-solid-ellipse window) (make-posn -4 -4) 408 408 "black") ((draw-solid-ellipse window) (make-posn -4 -4) 408 408 "black")
((draw-solid-ellipse window) (make-posn 0 0) 400 400 "sienna") ((draw-solid-ellipse window) (make-posn 0 0) 400 400 "sienna")
#| Draw the dartboard |# #| Draw the dartboard |#
(map-e (lambda (x/y) ((draw-solid-ellipse window) (make-posn (first x/y) (second x/y)) (map-e (lambda (x/y) ((draw-solid-ellipse window) (make-posn (first x/y) (second x/y))
3 3 "black")) 3 3 "black"))
(changes (list x y))) (changes (list x y)))
#| Every time the list (x y) changes (x and y get a new value), take this latest list value ("==>") #| Every time the list (x y) changes (x and y get a new value), take this latest list value ("==>")
and pass it to a function which draws a circle at the x,y coordinates in the list. |# and pass it to a function which draws a circle at the x,y coordinates in the list. |#
(start/resume p) #| Start the process for montecarlo.ss |# (start/resume p) #| Start the process for montecarlo.ss |#

View File

@ -1,15 +1,15 @@
(module montecarlo mzscheme (module montecarlo mzscheme
;; a seed specially chosen because it isn't terribly erratic when converging on pi ;; a seed specially chosen because it isn't terribly erratic when converging on pi
(random-seed 846259386) (random-seed 846259386)
(define (run) (define (run)
(let loop ([hits 1] (let loop ([hits 1]
[total 1]) [total 1])
(let* ([x (- (random 401) 200)] (let* ([x (- (random 401) 200)]
[y (- (random 401) 200)] [y (- (random 401) 200)]
[length (sqrt (+ (* x x) (* y y)))] [length (sqrt (+ (* x x) (* y y)))]
[pi (* 4. (/ hits total))]) [pi (* 4. (/ hits total))])
(cond [(length . < . 200) (cond [(length . < . 200)
(loop (add1 hits) (add1 total))] (loop (add1 hits) (add1 total))]
[else (loop hits (add1 total))])))) [else (loop hits (add1 total))]))))
(run)) (run))

View File

@ -1,44 +1,44 @@
(require (lib "graphics.ss" "graphics") (require (lib "graphics.ss" "graphics")
(lib "mztake.ss" "mztake") (lib "mztake.ss" "mztake")
(lifted mzscheme (lifted mzscheme
make-hash-table make-hash-table
hash-table-put! hash-table-put!
hash-table-get)) hash-table-get))
(open-graphics) (open-graphics)
(define window (open-viewport "Debugger" 600 500)) (define window (open-viewport "Debugger" 600 500))
((draw-viewport window) (make-rgb 0.95 0.95 0.95)) ((draw-viewport window) (make-rgb 0.95 0.95 0.95))
(define/bind (loc "random.ss" 4 6) x) (define/bind (loc "random.ss" 4 6) x)
(define largest-bin 0) (define largest-bin 0)
(define valcount (make-hash-table)) (define valcount (make-hash-table))
(hold (x-trace . -=> .(printf-b "largest count: ~a" largest-bin))) (hold (x-trace . -=> .(printf-b "largest count: ~a" largest-bin)))
(map-e (lambda (x) (map-e (lambda (x)
(let* ([new-cnt (add1 (hash-table-get valcount x (lambda () 0)))] (let* ([new-cnt (add1 (hash-table-get valcount x (lambda () 0)))]
[color (/ new-cnt (add1 largest-bin))]) [color (/ new-cnt (add1 largest-bin))])
(when (= largest-bin 250) (when (= largest-bin 250)
(kill p)) (kill p))
(when (> new-cnt largest-bin) (set! largest-bin new-cnt)) (when (> new-cnt largest-bin) (set! largest-bin new-cnt))
(hash-table-put! valcount x new-cnt) (hash-table-put! valcount x new-cnt)
((draw-solid-rectangle window) (make-posn (* x 6) (- 500 (* 2 new-cnt))) ((draw-solid-rectangle window) (make-posn (* x 6) (- 500 (* 2 new-cnt)))
6 10 ;; width height 6 10 ;; width height
(make-rgb 0 (* 0.75 color) color)))) (make-rgb 0 (* 0.75 color) color))))
x-trace) x-trace)
(printf-b "count: ~a" (count-b x-trace)) (printf-b "count: ~a" (count-b x-trace))
(set-running! true) (set-running! true)

View File

@ -1,107 +1,107 @@
#| The program being debugged (a module in the file "random.ss") runs an infinite loop, #| The program being debugged (a module in the file "random.ss") runs an infinite loop,
binding "x" to a random number between [0,100) each iteration. binding "x" to a random number between [0,100) each iteration.
This MzTake script draws a histogram of the values of x seen over time, This MzTake script draws a histogram of the values of x seen over time,
in sync with the execution of "random.ss". This will run until one in sync with the execution of "random.ss". This will run until one
bar reaches the top of the screen. bar reaches the top of the screen.
This histogram provides three pieces of information: This histogram provides three pieces of information:
* Each bar represents a bin, the height represents how many times * Each bar represents a bin, the height represents how many times
that "random" number was generated. that "random" number was generated.
* The brighter the blue, the faster that bin is growing compared * The brighter the blue, the faster that bin is growing compared
to the others. The darker, the slower. to the others. The darker, the slower.
* You can see a history of speeds over time based on how the colors * You can see a history of speeds over time based on how the colors
change in each bin. change in each bin.
Try looking for small groupings of bins where all are light, or all Try looking for small groupings of bins where all are light, or all
are dark -- these represent small trends in the numbers. are dark -- these represent small trends in the numbers.
Look for tortoises that stay low and black, and hares which are very Look for tortoises that stay low and black, and hares which are very
active and bright. active and bright.
The bars drag a bit when moving upwards (the height goes up by 2, but The bars drag a bit when moving upwards (the height goes up by 2, but
the redrawing of the latest color goes down 10 pixels) so that you can the redrawing of the latest color goes down 10 pixels) so that you can
spot vertical trends more easily. |# spot vertical trends more easily. |#
(require (lib "graphics.ss" "graphics") (require (lib "graphics.ss" "graphics")
#| Needed for open-graphics, open-viewport, and draw-solid-ellipse |# #| Needed for open-graphics, open-viewport, and draw-solid-ellipse |#
(lifted mzscheme (lifted mzscheme
make-hash-table make-hash-table
hash-table-put! hash-table-put!
hash-table-get)) hash-table-get))
#| "Lifted" is explained in FrTime's own documentation (plt/collects/frtime/doc.txt) #| "Lifted" is explained in FrTime's own documentation (plt/collects/frtime/doc.txt)
Quickly put, lifting extends the functions listed above so they can take FrTime time-varying Quickly put, lifting extends the functions listed above so they can take FrTime time-varying
values (such as MzTake traces) as arguments. |# values (such as MzTake traces) as arguments. |#
(open-graphics) (open-graphics)
(define window (open-viewport "Debugger" 600 500)) (define window (open-viewport "Debugger" 600 500))
((draw-viewport window) (make-rgb 0.95 0.95 0.95)) ((draw-viewport window) (make-rgb 0.95 0.95 0.95))
#| This file doesn't animate a list of objects since the number of #| This file doesn't animate a list of objects since the number of
objects quickly reaches the thousands (slowing drawing time severly), objects quickly reaches the thousands (slowing drawing time severly),
and they are stationary -- so we just keep drawing the circles at and they are stationary -- so we just keep drawing the circles at
their new heights based on the value in the hashtable. their new heights based on the value in the hashtable.
See the doc for more information on this kind of drawing. |# See the doc for more information on this kind of drawing. |#
(define-mztake-process p ("random.ss" [x-trace 4 6 bind 'x])) (define-mztake-process p ("random.ss" [x-trace 4 6 bind 'x]))
#| * Create a process to debug random.ss #| * Create a process to debug random.ss
* Add a tracepoint at line 4, column 6; in the program, * Add a tracepoint at line 4, column 6; in the program,
this is right before the next iteration of the loop is called, this is right before the next iteration of the loop is called,
->(loop (random 200)) ->(loop (random 200))
* At this tracepoint, define "x-trace" to a FrTime eventstream that * At this tracepoint, define "x-trace" to a FrTime eventstream that
recieves events containing the latest value of "x" seen, recieves events containing the latest value of "x" seen,
every time the code at line 4, column 6, is reached. |# every time the code at line 4, column 6, is reached. |#
(define largest-bin 0) (define largest-bin 0)
(define valcount (make-hash-table)) (define valcount (make-hash-table))
#| this will hold the counts for the histogram #| this will hold the counts for the histogram
x is the key, and the number of times x shows up is the value |# x is the key, and the number of times x shows up is the value |#
(hold (x-trace . -=> .(printf-b "largest count: ~a" largest-bin))) (hold (x-trace . -=> .(printf-b "largest count: ~a" largest-bin)))
#| Prints out the largest count every time we get a new x-trace event |# #| Prints out the largest count every time we get a new x-trace event |#
(map-e (lambda (x) (map-e (lambda (x)
(let* ([new-cnt (add1 (hash-table-get valcount x (lambda () 0)))] (let* ([new-cnt (add1 (hash-table-get valcount x (lambda () 0)))]
[color (/ new-cnt (add1 largest-bin))]) [color (/ new-cnt (add1 largest-bin))])
(when (= largest-bin 250) (when (= largest-bin 250)
(kill p)) (kill p))
; when one of the bars reaches the top of the screen, kill the program. ; when one of the bars reaches the top of the screen, kill the program.
(when (> new-cnt largest-bin) (set! largest-bin new-cnt)) (when (> new-cnt largest-bin) (set! largest-bin new-cnt))
; keep track of the largest count ; keep track of the largest count
(hash-table-put! valcount x new-cnt) (hash-table-put! valcount x new-cnt)
;; increment the value in the hashtable, starting from 0 if none exists. ;; increment the value in the hashtable, starting from 0 if none exists.
((draw-solid-rectangle window) (make-posn (* x 6) (- 500 (* 2 new-cnt))) ((draw-solid-rectangle window) (make-posn (* x 6) (- 500 (* 2 new-cnt)))
6 10 ;; width height 6 10 ;; width height
(make-rgb 0 (* 0.75 color) color)))) (make-rgb 0 (* 0.75 color) color))))
x-trace) x-trace)
#| Every time x-trace gets a new value, take this latest value and pass it to a function #| Every time x-trace gets a new value, take this latest value and pass it to a function
which increments the count in the hashtable, and draws a circle in the window at which increments the count in the hashtable, and draws a circle in the window at
(* x 6) pixels from the left, and the height is (2 * the latest count in the hashtable for that x), (* x 6) pixels from the left, and the height is (2 * the latest count in the hashtable for that x),
making a color (MAKE-RGB) that is lighter based on how fast it is growing. making a color (MAKE-RGB) that is lighter based on how fast it is growing.
|# |#
(printf-b "count: ~a" (count-b x-trace)) (printf-b "count: ~a" (count-b x-trace))
#| prints the count of how many events x-trace got, #| prints the count of how many events x-trace got,
aka how many values are in the histogram and on the screen. aka how many values are in the histogram and on the screen.
|# |#
(start/resume p) (start/resume p)
;; Start the process for random.ss ;; Start the process for random.ss

View File

@ -1,5 +1,5 @@
(module random mzscheme (module random mzscheme
(define (run) (define (run)
(let loop ([x (random 100)]) (let loop ([x (random 100)])
(loop (random 100)))) (loop (random 100))))
(run)) (run))

View File

@ -1,63 +1,63 @@
#| The program being debugged (a module in "sine.ss") runs an infinite loop, #| The program being debugged (a module in "sine.ss") runs an infinite loop,
binding "x" to a moment in time [-200,200], and "sin-x" to the sin(x/20) each iteration. binding "x" to a moment in time [-200,200], and "sin-x" to the sin(x/20) each iteration.
This MzTake script plots the value of x over time, in sync with the execution of "sine.ss". |# This MzTake script plots the value of x over time, in sync with the execution of "sine.ss". |#
(require (lib "animation.ss" "frtime")) ;; needed for display-shapes (require (lib "animation.ss" "frtime")) ;; needed for display-shapes
(define-mztake-process p ("sine.ss" [x/sinx-trace 5 8 bind '(x sin-x)])) (define-mztake-process p ("sine.ss" [x/sinx-trace 5 8 bind '(x sin-x)]))
#| * Create a process to debug sine.ss #| * Create a process to debug sine.ss
* Add a tracepoint at line 5, column 8; in the program, * Add a tracepoint at line 5, column 8; in the program,
this is right after the let values are bound, ->(if (x ...) this is right after the let values are bound, ->(if (x ...)
* At this tracepoint, define "x/sinx-trace" to be a FrTime eventstream that * At this tracepoint, define "x/sinx-trace" to be a FrTime eventstream that
recieves events containing a list of two elements -- the current values recieves events containing a list of two elements -- the current values
of the variables `x' and `sin-x', respectively. |# of the variables `x' and `sin-x', respectively. |#
(define x/sinx (hold x/sinx-trace)) (define x/sinx (hold x/sinx-trace))
#| the local variable "sin/x" now is a FrTime behavior that holds the current value of the list (sin-x x) |# #| the local variable "sin/x" now is a FrTime behavior that holds the current value of the list (sin-x x) |#
(define x (first x/sinx)) (define x (first x/sinx))
(define sin-x (second x/sinx)) (define sin-x (second x/sinx))
#| the local variables x, sin-x hold their current values |# #| the local variables x, sin-x hold their current values |#
(printf-b "x: ~a" x) (printf-b "x: ~a" x)
(printf-b "sin(x/20): ~a" sin-x) (printf-b "sin(x/20): ~a" sin-x)
#| Print the current values of x and sin-x |# #| Print the current values of x and sin-x |#
(printf-b "largest x: ~a sin(x/20): ~a" (printf-b "largest x: ~a sin(x/20): ~a"
(largest-val-b (changes (first x/sinx))) (largest-val-b (changes (first x/sinx)))
(largest-val-b (changes (second x/sinx)))) (largest-val-b (changes (second x/sinx))))
(printf-b "smallest x:~a sin(x/20):~a" (printf-b "smallest x:~a sin(x/20):~a"
(smallest-val-b (changes (first x/sinx))) (smallest-val-b (changes (first x/sinx)))
(smallest-val-b (changes (second x/sinx)))) (smallest-val-b (changes (second x/sinx))))
(display-shapes (display-shapes
(list* (make-line (make-posn 0 200) (make-posn 400 200) "gray") (list* (make-line (make-posn 0 200) (make-posn 400 200) "gray")
(make-line (make-posn 200 0) (make-posn 200 400) "gray") (make-line (make-posn 200 0) (make-posn 200 400) "gray")
#| draw horizontal and vertical gray lines |# #| draw horizontal and vertical gray lines |#
(let ([x (+ 200 x)] (let ([x (+ 200 x)]
[sin-x (+ 200 (* 100 sin-x))]) [sin-x (+ 200 (* 100 sin-x))])
(history-b 50 (changes (make-circle (history-b 50 (changes (make-circle
(make-posn x sin-x) (make-posn x sin-x)
5 5
(if (< 200 sin-x) (if (< 200 sin-x)
(if (< 200 x) "blue" "darkblue") #| Quadrants 3 and 4 |# (if (< 200 x) "blue" "darkblue") #| Quadrants 3 and 4 |#
(if (< 200 x) "red" "darkred")))))))) #| 1 and 2 |# (if (< 200 x) "red" "darkred")))))))) #| 1 and 2 |#
#| Make a circle at position x:(x + 200) and y:(100*sin(x/20) + 200) (scaled so we can draw it on screen) #| Make a circle at position x:(x + 200) and y:(100*sin(x/20) + 200) (scaled so we can draw it on screen)
with diameter of 5 pixels, and a color based on which quadrant the coordinate is in. with diameter of 5 pixels, and a color based on which quadrant the coordinate is in.
Every time this value (the circle) changes (when the values of x and sin-x change): Every time this value (the circle) changes (when the values of x and sin-x change):
* Keep a history (as a FIFO list) of (up to) the last 50 circles that were created. * Keep a history (as a FIFO list) of (up to) the last 50 circles that were created.
* Pass this list to the display-shapes function, which will redraw every time this list changes. |# * Pass this list to the display-shapes function, which will redraw every time this list changes. |#
(start/resume p) #| Start the process for sine.ss |# (start/resume p) #| Start the process for sine.ss |#

View File

@ -1,8 +1,8 @@
(module sine mzscheme (module sine mzscheme
(define (run) (define (run)
(let loop ([x -200]) (let loop ([x -200])
(let ([sin-x (sin (/ x 20.0))]) (let ([sin-x (sin (/ x 20.0))])
(if (x . < . 200) (if (x . < . 200)
(loop (add1 x)) (loop (add1 x))
(loop -200))))) (loop -200)))))
(run)) (run))

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
(module info (lib "infotab.ss" "setup") (module info (lib "infotab.ss" "setup")
(define name "Debugger") (define name "Debugger")
(define tools '(("mztake-lang.ss") ("debug-tool.ss"))) (define tools '(("mztake-lang.ss") ("debug-tool.ss")))
(define blurb '("MzTake is a scripted debugger for PLT Scheme." "A debugging tool for DrScheme")) (define blurb '("MzTake is a scripted debugger for PLT Scheme." "A debugging tool for DrScheme"))
(define tool-names '("MzTake Debugger" "Skipper")) (define tool-names '("MzTake Debugger" "Skipper"))
(define tool-icons '(("emblem-ohno.png" "mztake" "icons") ("icon-big.png" "mztake" "icons"))) (define tool-icons '(("emblem-ohno.png" "mztake" "icons") ("icon-big.png" "mztake" "icons")))
) )

2
collects/mztake/make-clean.bat Normal file → Executable file
View File

@ -1,2 +1,2 @@
del compiled del compiled
del private\compiled del private\compiled

View File

@ -1,20 +1,20 @@
(module make-plt mzscheme (module make-plt mzscheme
(require (lib "pack.ss" "setup") (require (lib "pack.ss" "setup")
#;(lib "util.ss" "planet")) #;(lib "util.ss" "planet"))
(define (my-filter path) (define (my-filter path)
(and (std-filter path) (and (std-filter path)
(not (or (regexp-match #rx".svn$" path) (not (or (regexp-match #rx".svn$" path)
(regexp-match #rx".bak$" path) (regexp-match #rx".bak$" path)
(regexp-match #rx".1$" path) (regexp-match #rx".1$" path)
(regexp-match #rx"-uncommented.ss$" path) (regexp-match #rx"-uncommented.ss$" path)
(regexp-match #rx"make" path))))) (regexp-match #rx"make" path)))))
;without frtime bundled: ;without frtime bundled:
(pack-collections "mztake-208.plt" "MzTake Debugger" (pack-collections "mztake-208.plt" "MzTake Debugger"
'(("mztake")) #t '(("frtime")("stepper")) my-filter #f) '(("mztake")) #t '(("frtime")("stepper")) my-filter #f)
(pack-collections "mztake-frtime-pre-208.plt" "MzTake Debugger" (pack-collections "mztake-frtime-pre-208.plt" "MzTake Debugger"
'(("mztake")("frtime")) #t '(("stepper")) my-filter #f)) '(("mztake")("frtime")) #t '(("stepper")) my-filter #f))

0
collects/mztake/make.bat Normal file → Executable file
View File

View File

@ -1,142 +1,142 @@
; ; ; ;
; ;; ;; ;;;;;;;;; ; ; ; ;; ;; ;;;;;;;;; ; ;
; ;; ;; ; ; ; ; ;; ;; ; ; ;
; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
; ; ; ; ; ;;;;;; ; ;;;; ; ; ;;; ; ;;;; ; ;;;; ;;;;;; ; ; ; ; ; ;;;;;; ; ;;;; ; ; ;;; ; ;;;; ; ;;;; ;;;;;;
; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;; ; ; ;
; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
; ; ; ; ; ; ; ;;;;; ; ; ; ; ; ;;;;; ; ; ; ; ; ; ; ; ; ; ; ;;;;; ; ; ; ; ; ;;;;; ; ; ; ;
; ; ; ; ; ; ; ; ; ;;; ;;;;;;; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;;; ;;;;;;; ; ; ; ; ; ; ;
; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
; ; ; ; ; ; ;; ; ; ; ; ; ; ;; ; ; ; ;; ; ; ; ; ; ; ;; ; ; ; ; ; ; ;; ; ; ; ;;
; ; ; ;;;;;; ; ;;;; ; ; ; ;;;; ;;;;;;; ;;;; ; ; ; ;;;; ; ; ; ; ;;;;;; ; ;;;; ; ; ; ;;;; ;;;;;;; ;;;; ; ; ; ;;;; ;
; ; ; ;
; ; ; ; ; ;
; ;;;; ; ;;;;
(module mztake-lang mzscheme (module mztake-lang mzscheme
(require "mztake.ss" (require "mztake.ss"
(lib "etc.ss") (lib "etc.ss")
(lib "list.ss") (lib "list.ss")
(lib "class.ss") (lib "class.ss")
(lib "unitsig.ss") (lib "unitsig.ss")
(lib "bitmap-label.ss" "mrlib") (lib "bitmap-label.ss" "mrlib")
(lib "contract.ss") (lib "contract.ss")
(lib "mred.ss" "mred") (lib "mred.ss" "mred")
(lib "tool.ss" "drscheme") (lib "tool.ss" "drscheme")
(lib "framework.ss" "framework") (lib "framework.ss" "framework")
(lib "string-constant.ss" "string-constants")) (lib "string-constant.ss" "string-constants"))
(provide tool@) (provide tool@)
(define tool@ (define tool@
(unit/sig drscheme:tool-exports^ (unit/sig drscheme:tool-exports^
(import drscheme:tool^) (import drscheme:tool^)
;############################MZTAKE LANGUAGE RELATED FUNCTIONS############################################## ;############################MZTAKE LANGUAGE RELATED FUNCTIONS##############################################
(define (phase1) (void)) (define (phase1) (void))
(define (phase2) (define (phase2)
(drscheme:language-configuration:add-language (drscheme:language-configuration:add-language
(make-object ((drscheme:language:get-default-mixin) (make-mztake-language mztake-language%))))) (make-object ((drscheme:language:get-default-mixin) (make-mztake-language mztake-language%)))))
(define (make-mztake-language base) (define (make-mztake-language base)
(class (drscheme:language:module-based-language->language-mixin (class (drscheme:language:module-based-language->language-mixin
(drscheme:language:simple-module-based-language->module-based-language-mixin (drscheme:language:simple-module-based-language->module-based-language-mixin
base)) base))
(field (watch-list empty)) (field (watch-list empty))
(inherit get-language-position) (inherit get-language-position)
(define/override (on-execute settings run-in-user-thread) (define/override (on-execute settings run-in-user-thread)
(let ([drs-eventspace (current-eventspace)]) (let ([drs-eventspace (current-eventspace)])
(super on-execute settings run-in-user-thread) (super on-execute settings run-in-user-thread)
(run-in-user-thread (run-in-user-thread
(lambda () (lambda ()
(let ([new-watch (namespace-variable-value 'render)] (let ([new-watch (namespace-variable-value 'render)]
[set-evspc (namespace-variable-value 'set-eventspace)]) [set-evspc (namespace-variable-value 'set-eventspace)])
(set-evspc drs-eventspace) (set-evspc drs-eventspace)
(set! watch-list (set! watch-list
((if (weak-member new-watch watch-list) ((if (weak-member new-watch watch-list)
identity identity
(lambda (r) (cons (make-weak-box new-watch) r))) (lambda (r) (cons (make-weak-box new-watch) r)))
(filter weak-box-value watch-list)))))))) (filter weak-box-value watch-list))))))))
(define/override (render-value/format value settings port width) (define/override (render-value/format value settings port width)
(super render-value/format (watch watch-list value) (super render-value/format (watch watch-list value)
settings port width)) settings port width))
(define/override (render-value value settings port) (define/override (render-value value settings port)
(super render-value (watch watch-list value) (super render-value (watch watch-list value)
settings port)) settings port))
(define/override (use-namespace-require/copy?) #t) (define/override (use-namespace-require/copy?) #t)
(super-instantiate ()))) (super-instantiate ())))
(define mztake-language% (define mztake-language%
(class* object% (drscheme:language:simple-module-based-language<%>) (class* object% (drscheme:language:simple-module-based-language<%>)
(define/public (get-language-numbers) (define/public (get-language-numbers)
'(1000 -400)) '(1000 -400))
(define/public (get-language-position) (define/public (get-language-position)
(list (string-constant experimental-languages) "MzTake")) (list (string-constant experimental-languages) "MzTake"))
(define/public (get-module) (define/public (get-module)
'(lib "mztake-syntax.ss" "mztake")) '(lib "mztake-syntax.ss" "mztake"))
(define/public (get-one-line-summary) (define/public (get-one-line-summary)
(format "MzTake Debugger (~a)" mztake-version)) (format "MzTake Debugger (~a)" mztake-version))
(define/public (get-language-url) #f) (define/public (get-language-url) #f)
(define/public (get-reader) (define/public (get-reader)
(lambda (name port offsets) (lambda (name port offsets)
(let ([v (read-syntax name port offsets)]) (let ([v (read-syntax name port offsets)])
(if (eof-object? v) (if (eof-object? v)
v v
(namespace-syntax-introduce v))))) (namespace-syntax-introduce v)))))
(super-instantiate ()))) (super-instantiate ())))
;;;;;;;;;;;;;FRTIME REPL STUFF;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;FRTIME REPL STUFF;;;;;;;;;;;;;;;;;;;;;;
(define (weak-member obj lis) (define (weak-member obj lis)
(let ([cmp (lambda (v) (eq? v obj))]) (let ([cmp (lambda (v) (eq? v obj))])
(let loop ([lis lis]) (let loop ([lis lis])
(and (cons? lis) (and (cons? lis)
(or (or
(cond (cond
[(weak-box-value (first lis)) => cmp] [(weak-box-value (first lis)) => cmp]
[else false]) [else false])
(loop (rest lis))))))) (loop (rest lis)))))))
(define (watch watch-list value) (define (watch watch-list value)
(foldl (foldl
(lambda (wb acc) (lambda (wb acc)
(cond (cond
[(weak-box-value wb) [(weak-box-value wb)
=> (lambda (f) (f acc))] => (lambda (f) (f acc))]
[else acc])) [else acc]))
value value
watch-list)) watch-list))
;########################################################################################################### ;###########################################################################################################
(define debugger-bitmap (define debugger-bitmap
(bitmap-label-maker (bitmap-label-maker
"Syntax Location" "Syntax Location"
(build-path (collection-path "mztake" "icons") "stock_macro-check-brackets-16.png"))) (build-path (collection-path "mztake" "icons") "stock_macro-check-brackets-16.png")))
(define (debugger-unit-frame-mixin super%) (define (debugger-unit-frame-mixin super%)
(class super% (class super%
(inherit get-button-panel get-interactions-text get-definitions-text get-menu-bar) (inherit get-button-panel get-interactions-text get-definitions-text get-menu-bar)
(super-instantiate ()) (super-instantiate ())
(define debugger-button (define debugger-button
(make-object button% (make-object button%
(debugger-bitmap this) (debugger-bitmap this)
(get-button-panel) (get-button-panel)
(lambda (button evt) (lambda (button evt)
(let* ([pos (send (get-definitions-text) get-start-position)] (let* ([pos (send (get-definitions-text) get-start-position)]
[line (send (get-definitions-text) position-paragraph pos)] [line (send (get-definitions-text) position-paragraph pos)]
[column (- pos (send (get-definitions-text) line-start-position [column (- pos (send (get-definitions-text) line-start-position
(send (get-definitions-text) position-line pos)))]) (send (get-definitions-text) position-line pos)))])
(message-box "Syntax Location" (message-box "Syntax Location"
(format "Line: ~a~nColumn: ~a" (add1 line) column)))))) (format "Line: ~a~nColumn: ~a" (add1 line) column))))))
(send (get-button-panel) change-children (send (get-button-panel) change-children
(lambda (_) (cons debugger-button (remq debugger-button _)))))) (lambda (_) (cons debugger-button (remq debugger-button _))))))
(drscheme:get/extend:extend-unit-frame debugger-unit-frame-mixin)))) (drscheme:get/extend:extend-unit-frame debugger-unit-frame-mixin))))

View File

@ -1,71 +1,71 @@
(module mztake-structs mzscheme (module mztake-structs mzscheme
(require (prefix frp: (lib "frp.ss" "frtime")) (require (prefix frp: (lib "frp.ss" "frtime"))
(lib "more-useful-code.ss" "mztake" "private")) (lib "more-useful-code.ss" "mztake" "private"))
(provide (all-defined-except loc make-loc) (provide (all-defined-except loc make-loc)
(rename loc loc$) (rename loc loc$)
(rename make-loc loc)) (rename make-loc loc))
; ;;;;; ; ; ; ;;;;; ; ;
; ; ; ; ; ; ; ; ; ;
; ; ; ; ; ; ; ;
; ; ;;;;;; ;;; ; ; ;;; ;;;;; ;;;; ; ; ;;;;;; ;;; ; ; ;;; ;;;;; ;;;;
; ; ; ;; ; ; ; ; ; ; ; ; ; ; ;; ; ; ; ; ; ; ;
; ;;; ; ; ; ; ; ; ; ; ;;; ; ; ; ; ; ; ;
; ;;; ; ; ; ; ; ; ; ; ;;; ; ; ; ; ; ; ;
; ; ; ; ; ; ; ; ;;;; ; ; ; ; ; ; ; ; ;;;;
; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
; ; ; ; ; ; ;; ; ; ; ; ; ; ; ; ; ; ; ;; ; ; ; ; ;
; ;;;;; ;;;; ;;;; ; ;;; ;;; ;;;; ; ;;;;; ;;;; ;;;; ; ;;; ;;; ;;;;
(define-struct trace-struct (evnt-rcvr thunk)) ; frp:event-receiver (define-struct trace-struct (evnt-rcvr thunk)) ; frp:event-receiver
(define-struct debug-client (modpath ; complete-path of the module (define-struct debug-client (modpath ; complete-path of the module
tracepoints ; hash-table of traces tracepoints ; hash-table of traces
line-col->pos ; memoized O(n) function to map line/col -> byte offset line-col->pos ; memoized O(n) function to map line/col -> byte offset
process)) ; parent debug-process process)) ; parent debug-process
(define-struct debug-process (custodian ; If you shutdown-all it will kill the debugger 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 run-semaphore ; When you post to this the debuggee will continue executing
running-e ; Is the program (supposed-to-be) currently running running-e ; Is the program (supposed-to-be) currently running
run-manager ; saves behavior that actually pauses/resumes from GC run-manager ; saves behavior that actually pauses/resumes from GC
pause-requested? pause-requested?
resume-requested? resume-requested?
exited? ; FrTime cell receives #t when the target exits exited? ; FrTime cell receives #t when the target exits
exceptions ; (an event stream) Exceptions thrown during the evaluation of the target exceptions ; (an event stream) Exceptions thrown during the evaluation of the target
main-client ; the main client module that will be run main-client ; the main client module that will be run
clients ; list of all the clients attached to this process clients ; list of all the clients attached to this process
where ; a behavior signaling each position where we pause where ; a behavior signaling each position where we pause
marks)) ; while paused, the marks at the point of the pause (else false) marks)) ; while paused, the marks at the point of the pause (else false)
(define-struct loc (modpath line col)) (define-struct loc (modpath line col))
;########################################################################################################### ;###########################################################################################################
; ;;;;; ; ; ;;;;; ; ; ;;;;; ; ; ;;;;; ;
; ; ; ; ; ;; ; ; ; ; ; ; ; ;; ; ;
; ; ; ; ; ; ; ; ; ; ; ;
; ; ;;;;;; ;;; ; ; ;;; ;;;;; ; ; ;;; ;;; ;;;; ;;;;; ;;;; ; ;;; ;;;; ; ; ;;;;;; ;;; ; ; ;;; ;;;;; ; ; ;;; ;;; ;;;; ;;;;; ;;;; ; ;;; ;;;;
; ; ; ;; ; ; ; ; ; ; ;; ; ; ; ; ; ; ; ;; ; ; ; ; ; ;; ; ; ; ; ; ; ;; ; ; ; ; ; ; ; ;; ; ;
; ;;; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;;; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
; ;;; ; ; ; ; ; ; ; ; ; ; ;;;;; ; ; ; ; ; ; ;;; ; ; ; ; ; ; ; ; ; ; ;;;;; ; ; ; ; ;
; ; ; ; ; ; ; ; ; ; ;;;;;;; ; ; ; ; ; ; ;;;; ; ; ; ; ; ; ; ; ; ; ;;;;;;; ; ; ; ; ; ; ;;;;
; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
; ; ; ; ; ; ;; ; ; ; ;; ; ; ; ; ; ;; ; ; ; ; ; ; ; ; ; ; ; ; ;; ; ; ; ;; ; ; ; ; ; ;; ; ; ; ; ; ;
; ;;;;; ;;;; ;;;; ; ;;; ;;; ;;;;; ; ;;;; ;;;; ; ;;; ;;;; ; ;;;; ; ;;;;; ;;;; ;;;; ; ;;; ;;; ;;;;; ; ;;;; ;;;; ; ;;; ;;;; ; ;;;;
(define (create-empty-debug-client) (define (create-empty-debug-client)
(make-debug-client null ; modpath (make-debug-client null ; modpath
(make-hash) ; tracepoints (make-hash) ; tracepoints
null ; line-col->pos function null ; line-col->pos function
null)) ; process null)) ; process
;########################################################################################################### ;###########################################################################################################
) )

View File

@ -1,108 +1,108 @@
(module load-annotator mzscheme (module load-annotator mzscheme
(require (lib "moddep.ss" "syntax") (require (lib "moddep.ss" "syntax")
(lib "class.ss" "mzlib") (lib "class.ss" "mzlib")
(lib "mred.ss" "mred")) (lib "mred.ss" "mred"))
(provide eval/annotations (provide eval/annotations
require/annotations require/annotations
require/sandbox+annotations require/sandbox+annotations
load-module/annotate) load-module/annotate)
#|load-with-annotations : #|load-with-annotations :
>initial-module : (union (listof symbol?) string?) >initial-module : (union (listof symbol?) string?)
Takes in a require spec -- "../file.ss", (file "complete-path.ss"), (lib ...), etc Takes in a require spec -- "../file.ss", (file "complete-path.ss"), (lib ...), etc
In other words - In other words -
pass it a relative filename or a quoted lib to require pass it a relative filename or a quoted lib to require
"mztake.ss" or '(lib "mztake.ss" "mztake") "mztake.ss" or '(lib "mztake.ss" "mztake")
>annotate-module? : (string? symbol? . -> . boolean) >annotate-module? : (string? symbol? . -> . boolean)
(filename module-name) (filename module-name)
If true, loads source file and annotates. If true, loads source file and annotates.
Else, tries to load compiled or source, no annotation. Else, tries to load compiled or source, no annotation.
>annotator : (string? symbol? syntax? . -> . syntax?) >annotator : (string? symbol? syntax? . -> . syntax?)
|# |#
(define (require/sandbox+annotations custodian err-display-handler initial-module annotate-module? annotator) (define (require/sandbox+annotations custodian err-display-handler initial-module annotate-module? annotator)
(parameterize ([current-custodian custodian] (parameterize ([current-custodian custodian]
[current-namespace (make-namespace-with-mred)] [current-namespace (make-namespace-with-mred)]
[error-display-handler err-display-handler]) [error-display-handler err-display-handler])
(require/annotations initial-module annotate-module? annotator))) (require/annotations initial-module annotate-module? annotator)))
(define (require/annotations initial-module annotate-module? annotator) (define (require/annotations initial-module annotate-module? annotator)
(eval/annotations #`(require #,initial-module) annotate-module? annotator)) (eval/annotations #`(require #,initial-module) annotate-module? annotator))
(define (eval/annotations stx annotate-module? annotator) (define (eval/annotations stx annotate-module? annotator)
(parameterize (parameterize
([current-load/use-compiled ([current-load/use-compiled
(let ([ocload/use-compiled (current-load/use-compiled)]) (let ([ocload/use-compiled (current-load/use-compiled)])
(lambda (fn m) (lambda (fn m)
(cond [(annotate-module? fn m) (cond [(annotate-module? fn m)
(load-module/annotate annotator fn m)] (load-module/annotate annotator fn m)]
[else [else
(ocload/use-compiled fn m)])))]) (ocload/use-compiled fn m)])))])
(eval-syntax (annotator stx)))) (eval-syntax (annotator stx))))
(define (load-module/annotate annotator fn m) (define (load-module/annotate annotator fn m)
(let-values ([(base _ __) (split-path fn)] (let-values ([(base _ __) (split-path fn)]
[(in-port src) (build-input-port fn)]) [(in-port src) (build-input-port fn)])
(dynamic-wind (dynamic-wind
(lambda () (void)) (lambda () (void))
(lambda () (lambda ()
(parameterize ([read-accept-compiled #f] (parameterize ([read-accept-compiled #f]
[current-load-relative-directory base]) [current-load-relative-directory base])
(unless m (raise 'module-name-not-passed-to-load-module/annotate)) (unless m (raise 'module-name-not-passed-to-load-module/annotate))
(with-module-reading-parameterization (with-module-reading-parameterization
(lambda () (lambda ()
(let* ([first (expand (read-syntax src in-port))] (let* ([first (expand (read-syntax src in-port))]
[module-ized-exp (annotator (check-module-form first m fn))] [module-ized-exp (annotator (check-module-form first m fn))]
[second (read in-port)]) [second (read in-port)])
(unless (eof-object? second) (unless (eof-object? second)
(raise-syntax-error (raise-syntax-error
'load-module/annotate 'load-module/annotate
(format "expected only a `module' declaration for `~s', but found an extra expression" m) (format "expected only a `module' declaration for `~s', but found an extra expression" m)
second)) second))
(eval module-ized-exp)))))) (eval module-ized-exp))))))
(lambda () (close-input-port in-port))))) (lambda () (close-input-port in-port)))))
; taken directly from mred.ss -- it's not exported... ; taken directly from mred.ss -- it's not exported...
(define (build-input-port filename) (define (build-input-port filename)
(let ([p (open-input-file filename)]) (let ([p (open-input-file filename)])
(port-count-lines! p) (port-count-lines! p)
(let ([p (cond [(regexp-match-peek "^WXME01[0-9][0-9] ## " p) (let ([p (cond [(regexp-match-peek "^WXME01[0-9][0-9] ## " p)
(let ([t (make-object text%)]) (let ([t (make-object text%)])
(send t insert-file p 'standard) (send t insert-file p 'standard)
(close-input-port p) (close-input-port p)
(open-input-text-editor t))] (open-input-text-editor t))]
[else p])]) [else p])])
(port-count-lines! p) (port-count-lines! p)
(let loop () (let loop ()
(when (with-handlers ([exn:fail? (lambda (x) #f)]) (when (with-handlers ([exn:fail? (lambda (x) #f)])
(regexp-match-peek "^#!" p)) (regexp-match-peek "^#!" p))
(let lloop ([prev #f]) (let lloop ([prev #f])
(let ([c (read-char-or-special p)]) (let ([c (read-char-or-special p)])
(if (or (eof-object? c) (if (or (eof-object? c)
(eq? c #\return) (eq? c #\return)
(eq? c #\newline)) (eq? c #\newline))
(when (eq? prev #\\) (when (eq? prev #\\)
(loop)) (loop))
(lloop c)))))) (lloop c))))))
(values p filename)))) (values p filename))))
(define (test annotate-all?) (define (test annotate-all?)
(require/annotations '(lib "mztake.ss" "mztake") (require/annotations '(lib "mztake.ss" "mztake")
(lambda (fn m) (lambda (fn m)
(printf "~a ~a~n" fn m) (printf "~a ~a~n" fn m)
annotate-all?) annotate-all?)
(lambda (fn m stx) stx))) (lambda (fn m stx) stx)))
;(test #t) ; slow ;(test #t) ; slow
;(test #f) ; fast ;(test #f) ; fast
) )

View File

@ -1,292 +1,292 @@
(module more-useful-code mzscheme (module more-useful-code mzscheme
(require (lib "list.ss") (require (lib "list.ss")
(lib "pretty.ss") (lib "pretty.ss")
(lib "etc.ss")) (lib "etc.ss"))
(provide assert (provide assert
cons-to-end cons-to-end
assoc-get assoc-get
debug debug
make-to-string make-to-string
make-debug make-debug
to-string to-string
member-eq? member-eq?
string->char string->char
last last
member-str? member-str?
quicksort-vector! quicksort-vector!
struct->list/deep struct->list/deep
make-for-each make-for-each
begin0/rtn begin0/rtn
with-handlers/finally with-handlers/finally
pretty-print-syntax pretty-print-syntax
with-semaphore with-semaphore
make-hash make-hash
hash? hash?
hash-get hash-get
hash-put! hash-put!
hash-remove! hash-remove!
hash-map hash-map
hash-for-each hash-for-each
hash-size/slow hash-size/slow
hash-mem? hash-mem?
hash-fold hash-fold
hash-filter! hash-filter!
hash-keys hash-keys
hash-values hash-values
hash-pairs hash-pairs
hash-add-all! hash-add-all!
hash-get-or-define! hash-get-or-define!
(all-from (lib "list.ss")) (all-from (lib "list.ss"))
(all-from (lib "etc.ss"))) (all-from (lib "etc.ss")))
(define-struct (exn:assert exn) ()) (define-struct (exn:assert exn) ())
(define-syntax (assert stx) (define-syntax (assert stx)
(syntax-case stx () (syntax-case stx ()
[(src-assert bool) #'(src-assert bool "")] [(src-assert bool) #'(src-assert bool "")]
[(src-assert bool msg ...) [(src-assert bool msg ...)
(with-syntax ([src-text (datum->syntax-object (with-syntax ([src-text (datum->syntax-object
(syntax src-assert) (syntax src-assert)
(format "~a:~a:~a: assertion failed: " (format "~a:~a:~a: assertion failed: "
(syntax-source (syntax bool)) (syntax-source (syntax bool))
(syntax-line (syntax bool)) (syntax-line (syntax bool))
(syntax-column (syntax bool))))]) (syntax-column (syntax bool))))])
#'(unless bool #'(unless bool
(raise (make-exn:assert (apply string-append (raise (make-exn:assert (apply string-append
(cons src-text (cons src-text
(map (lambda (item) (map (lambda (item)
(string-append (to-string item) " ")) (string-append (to-string item) " "))
(list msg ...)))) (list msg ...))))
(current-continuation-marks)))))])) (current-continuation-marks)))))]))
(define-syntax (begin0/rtn stx) (define-syntax (begin0/rtn stx)
(syntax-case stx () (syntax-case stx ()
[(begin0/rtn body bodies ...) [(begin0/rtn body bodies ...)
(with-syntax ([rtn (datum->syntax-object (syntax begin0/rtn) 'rtn)]) (with-syntax ([rtn (datum->syntax-object (syntax begin0/rtn) 'rtn)])
(syntax (let ([rtn body]) bodies ... rtn)))])) (syntax (let ([rtn body]) bodies ... rtn)))]))
(define-syntax with-handlers/finally (define-syntax with-handlers/finally
(syntax-rules () (syntax-rules ()
[(_ (handler ...) body finally) [(_ (handler ...) body finally)
(let ([finally-fn (lambda () finally)]) (let ([finally-fn (lambda () finally)])
(begin0 (begin0
(with-handlers (with-handlers
(handler ... (handler ...
[(lambda (exn) #t) [(lambda (exn) #t)
(lambda (exn) (finally-fn) (raise exn))]) (lambda (exn) (finally-fn) (raise exn))])
body) body)
(finally-fn)))])) (finally-fn)))]))
(define (make-for-each . iterator-fns) (define (make-for-each . iterator-fns)
(lambda (obj fn) (lambda (obj fn)
(cond ((list? obj) (for-each fn obj)) (cond ((list? obj) (for-each fn obj))
((vector? obj) (let loop ((x 0)) ((vector? obj) (let loop ((x 0))
(if (< x (vector-length obj)) (if (< x (vector-length obj))
(begin (fn (vector-ref obj x)) (loop (+ x 1)))))) (begin (fn (vector-ref obj x)) (loop (+ x 1))))))
((hash-table? obj) (hash-for-each obj (lambda (key val) (fn key)))) ((hash-table? obj) (hash-for-each obj (lambda (key val) (fn key))))
(true (let loop ((cur iterator-fns)) (true (let loop ((cur iterator-fns))
(if (empty? cur) (if (empty? cur)
(if (struct? obj) (error "for-each: no iterator for struct `" (struct-name obj) "' value:" obj) (if (struct? obj) (error "for-each: no iterator for struct `" (struct-name obj) "' value:" obj)
(error "for-each: no iterator for value:" obj)) (error "for-each: no iterator for value:" obj))
(or ((first cur) obj fn) (or ((first cur) obj fn)
(loop (rest cur))))))))) (loop (rest cur)))))))))
(define (quicksort-vector! v less-than) (define (quicksort-vector! v less-than)
(let ([count (vector-length v)]) (let ([count (vector-length v)])
(let loop ([min 0][max count]) (let loop ([min 0][max count])
(if (< min (sub1 max)) (if (< min (sub1 max))
(let ([pval (vector-ref v min)]) (let ([pval (vector-ref v min)])
(let pivot-loop ([pivot min] (let pivot-loop ([pivot min]
[pos (add1 min)]) [pos (add1 min)])
(if (< pos max) (if (< pos max)
(let ([cval (vector-ref v pos)]) (let ([cval (vector-ref v pos)])
(if (less-than cval pval) (if (less-than cval pval)
(begin (begin
(vector-set! v pos (vector-ref v pivot)) (vector-set! v pos (vector-ref v pivot))
(vector-set! v pivot cval) (vector-set! v pivot cval)
(pivot-loop (add1 pivot) (add1 pos))) (pivot-loop (add1 pivot) (add1 pos)))
(pivot-loop pivot (add1 pos)))) (pivot-loop pivot (add1 pos))))
(if (= min pivot) (if (= min pivot)
(loop (add1 pivot) max) (loop (add1 pivot) max)
(begin (begin
(loop min pivot) (loop min pivot)
(loop pivot max))))))))) (loop pivot max)))))))))
v) v)
(define (member-str? s ls) (define (member-str? s ls)
(cond (cond
((empty? ls) false) ((empty? ls) false)
((string=? s (first ls)) true) ((string=? s (first ls)) true)
(else (member-str? s (rest ls))))) (else (member-str? s (rest ls)))))
(define (last ls) (define (last ls)
(cond (cond
((empty? ls) (error "took a last but it was emptry")) ((empty? ls) (error "took a last but it was emptry"))
((empty? (rest ls)) (first ls)) ((empty? (rest ls)) (first ls))
(else (last (rest ls))))) (else (last (rest ls)))))
(define (string->char s) (define (string->char s)
(first (string->list s))) (first (string->list s)))
(define (member-eq? x ls) (define (member-eq? x ls)
(not (empty? (filter (lambda (y) (eq? x y)) ls)))) (not (empty? (filter (lambda (y) (eq? x y)) ls))))
(define (to-string arg . extra-printers) (define (to-string arg . extra-printers)
(let ([on-stack-ids (make-hash)] (let ([on-stack-ids (make-hash)]
[used-ids (make-hash)] [used-ids (make-hash)]
[free-id 0]) [free-id 0])
(let loop ((arg arg)) (let loop ((arg arg))
(if (hash-mem? on-stack-ids arg) (if (hash-mem? on-stack-ids arg)
(begin (begin
(hash-put! used-ids arg true) (hash-put! used-ids arg true)
(format "#~a#" (hash-get on-stack-ids arg))) (format "#~a#" (hash-get on-stack-ids arg)))
(let ([my-id free-id]) (let ([my-id free-id])
(hash-put! on-stack-ids arg my-id) (hash-put! on-stack-ids arg my-id)
(set! free-id (add1 free-id)) (set! free-id (add1 free-id))
(let ([result (let ([result
(or (or
(let printer-loop ([printers extra-printers]) (let printer-loop ([printers extra-printers])
(if (empty? printers) (if (empty? printers)
false false
(or (if (procedure-arity-includes? (car printers) 2) (or (if (procedure-arity-includes? (car printers) 2)
((car printers) arg (lambda (arg) (apply to-string (cons arg extra-printers)))) ((car printers) arg (lambda (arg) (apply to-string (cons arg extra-printers))))
((car printers) arg)) ((car printers) arg))
(printer-loop (cdr printers))))) (printer-loop (cdr printers)))))
(cond (cond
[(not arg) "#f"] [(not arg) "#f"]
[(void? arg) "#<void>"] [(void? arg) "#<void>"]
[(eq? arg #t) "#t"] [(eq? arg #t) "#t"]
[(char? arg) (list->string (list arg))] [(char? arg) (list->string (list arg))]
[(string? arg) (format "\"~a\"" arg)] [(string? arg) (format "\"~a\"" arg)]
[(symbol? arg) (symbol->string arg)] [(symbol? arg) (symbol->string arg)]
[(number? arg) (number->string arg)] [(number? arg) (number->string arg)]
[(vector? arg) (string-append "#" (loop (vector->list arg)))] [(vector? arg) (string-append "#" (loop (vector->list arg)))]
[(box? arg) (string-append "#&" (loop (unbox arg)))] [(box? arg) (string-append "#&" (loop (unbox arg)))]
[(empty? arg) "empty"] [(empty? arg) "empty"]
[(list? arg) [(list? arg)
(apply (apply
string-append string-append
`("(" ,@(cons (loop (first arg)) `("(" ,@(cons (loop (first arg))
(map (lambda (item) (string-append " " (loop item))) (rest arg))) (map (lambda (item) (string-append " " (loop item))) (rest arg)))
")"))] ")"))]
[(cons? arg) (format "(~a . ~a)" [(cons? arg) (format "(~a . ~a)"
(loop (first arg)) (loop (first arg))
(loop (rest arg)))] (loop (rest arg)))]
[(hash-table? arg) [(hash-table? arg)
(apply (apply
string-append string-append
`("[hash:" `("[hash:"
,@(map (lambda (item) (string-append " " (loop item))) (hash-pairs arg)) ,@(map (lambda (item) (string-append " " (loop item))) (hash-pairs arg))
"]"))] "]"))]
[(syntax? arg) [(syntax? arg)
(format "[syntax: ~a:~a]" (syntax-line arg) (syntax-column arg))] (format "[syntax: ~a:~a]" (syntax-line arg) (syntax-column arg))]
[(struct? arg) [(struct? arg)
(let ([as-list (vector->list (struct->vector arg))]) (let ([as-list (vector->list (struct->vector arg))])
(apply (apply
string-append string-append
`("[" ,@(cons (loop (first as-list)) `("[" ,@(cons (loop (first as-list))
(map (lambda (item) (string-append " " (loop item))) (map (lambda (item) (string-append " " (loop item)))
(rest as-list))) "]")))] (rest as-list))) "]")))]
[else [else
(format "~a" arg)]))]) (format "~a" arg)]))])
(hash-remove! on-stack-ids arg) (hash-remove! on-stack-ids arg)
(if (hash-mem? used-ids arg) (if (hash-mem? used-ids arg)
(format "#~a=~a" my-id result) (format "#~a=~a" my-id result)
result))))))) result)))))))
;; make-debug: usage example: (define debug-f (make-debug (make-to-string `([,is-type? ,type-to-string])))) ;; make-debug: usage example: (define debug-f (make-debug (make-to-string `([,is-type? ,type-to-string]))))
;; The printers have to take two arguments: the item to converts and the to-string function for subitems ;; The printers have to take two arguments: the item to converts and the to-string function for subitems
(define (make-debug to-string-fn) (define (make-debug to-string-fn)
(lambda args (lambda args
(for-each (lambda (x) (for-each (lambda (x)
(display (if (string? x) x (to-string-fn x))) (display (if (string? x) x (to-string-fn x)))
(display " ")) (display " "))
args) args)
(newline))) (newline)))
(define debug (make-debug to-string)) (define debug (make-debug to-string))
(define (make-to-string predicate-printer-pairs) (define (make-to-string predicate-printer-pairs)
(let ([printers (map (lambda (pair) (lambda (arg printer) (let ([printers (map (lambda (pair) (lambda (arg printer)
(cond [(not ((first pair) arg)) false] (cond [(not ((first pair) arg)) false]
[(procedure-arity-includes? (second pair) 2) [(procedure-arity-includes? (second pair) 2)
((second pair) arg printer)] ((second pair) arg printer)]
[else ((second pair) arg)]))) [else ((second pair) arg)])))
predicate-printer-pairs)]) predicate-printer-pairs)])
(case-lambda (case-lambda
[(arg) (apply to-string arg printers)] [(arg) (apply to-string arg printers)]
[(arg extra-printers) (apply to-string (append (list arg) printers extra-printers))]))) [(arg extra-printers) (apply to-string (append (list arg) printers extra-printers))])))
(define (assoc-get label ls) (define (assoc-get label ls)
(cond (cond
((empty? ls) (error (string-append "failed to find " (to-string label)))) ((empty? ls) (error (string-append "failed to find " (to-string label))))
((eq? label (first (first ls))) ((eq? label (first (first ls)))
(first ls)) (first ls))
(else (assoc-get label (rest ls))))) (else (assoc-get label (rest ls)))))
(define (cons-to-end a ls) (define (cons-to-end a ls)
(cond (cond
((empty? ls) (cons a ls)) ((empty? ls) (cons a ls))
(else (cons (first ls) (else (cons (first ls)
(cons-to-end a (rest ls)))))) (cons-to-end a (rest ls))))))
(define (struct->list/deep item) (define (struct->list/deep item)
(cond [(struct? item) (map struct->list/deep (vector->list (struct->vector item)))] (cond [(struct? item) (map struct->list/deep (vector->list (struct->vector item)))]
[(list? item) (map struct->list/deep item)] [(list? item) (map struct->list/deep item)]
[(vector? item) (list->vector (map struct->list/deep (vector->list item)))] [(vector? item) (list->vector (map struct->list/deep (vector->list item)))]
[else item])) [else item]))
(define (struct-name s) (vector-ref (struct->vector s) 0)) (define (struct-name s) (vector-ref (struct->vector s) 0))
(define (pretty-print-syntax width stx) (define (pretty-print-syntax width stx)
(pretty-print-columns width) (pretty-print-columns width)
(pretty-print (syntax-object->datum stx))) (pretty-print (syntax-object->datum stx)))
(define (with-semaphore sem proc) (define (with-semaphore sem proc)
(semaphore-wait sem) (semaphore-wait sem)
(let ([result (proc)]) (let ([result (proc)])
(semaphore-post sem) (semaphore-post sem)
result)) result))
(define make-hash make-hash-table) (define make-hash make-hash-table)
(define hash? hash-table?) (define hash? hash-table?)
(define hash-get hash-table-get) (define hash-get hash-table-get)
(define hash-put! hash-table-put!) (define hash-put! hash-table-put!)
(define hash-remove! hash-table-remove!) (define hash-remove! hash-table-remove!)
(define hash-map hash-table-map) (define hash-map hash-table-map)
(define hash-for-each hash-table-for-each) (define hash-for-each hash-table-for-each)
(define (hash-empty? hash)(let/ec k (hash-for-each hash (lambda (k v) (k false))) true)) (define (hash-empty? hash)(let/ec k (hash-for-each hash (lambda (k v) (k false))) true))
(define (hash-size/slow hash) (hash-fold hash 0 (lambda (key val acc) (+ acc 1)))) (define (hash-size/slow hash) (hash-fold hash 0 (lambda (key val acc) (+ acc 1))))
(define (hash-mem? hash item) (let/ec k (begin (hash-get hash item (lambda () (k false))) true))) (define (hash-mem? hash item) (let/ec k (begin (hash-get hash item (lambda () (k false))) true)))
(define (hash-fold hash init fn) (define (hash-fold hash init fn)
(hash-for-each hash (lambda (key val) (set! init (fn key val init)))) init) (hash-for-each hash (lambda (key val) (set! init (fn key val init)))) init)
(define (hash-filter! hash predicate) (define (hash-filter! hash predicate)
(hash-for-each (hash-for-each
hash (lambda (key val) (if (not (predicate key val)) hash (lambda (key val) (if (not (predicate key val))
(hash-remove! hash key))))) (hash-remove! hash key)))))
(define (hash-keys hash) (define (hash-keys hash)
(hash-fold hash empty (lambda (key val acc) (cons key acc)))) (hash-fold hash empty (lambda (key val acc) (cons key acc))))
(define (hash-values hash) (define (hash-values hash)
(hash-fold hash empty (lambda (key val acc) (cons val acc)))) (hash-fold hash empty (lambda (key val acc) (cons val acc))))
(define (hash-pairs hash) (define (hash-pairs hash)
(hash-fold hash empty (lambda (key val acc) (cons (list key val) acc)))) (hash-fold hash empty (lambda (key val acc) (cons (list key val) acc))))
(define (hash-add-all! to-hash from-hash) ;; // memcpy-style argument order (define (hash-add-all! to-hash from-hash) ;; // memcpy-style argument order
(hash-for-each from-hash (hash-for-each from-hash
(lambda (key val) (hash-put! to-hash key val)))) (lambda (key val) (hash-put! to-hash key val))))
(define (hash-get-or-define! hash key val-fn) (define (hash-get-or-define! hash key val-fn)
(if (not (hash-mem? hash key)) (if (not (hash-mem? hash key))
(begin (let ((v (val-fn))) (begin (let ((v (val-fn)))
(hash-put! hash key v) (hash-put! hash key v)
v)) v))
(hash-get hash key)))) (hash-get hash key))))

View File

@ -1,66 +1,66 @@
(module useful-code (lib "frtime.ss" "frtime") (module useful-code (lib "frtime.ss" "frtime")
(require (lib "string.ss") (require (lib "string.ss")
(lib "contract.ss") (lib "contract.ss")
(lib "list.ss")) (lib "list.ss"))
(provide (all-defined)) (provide (all-defined))
; Everything is contracted to 'any' for speed benefits, though there is already a big performance hit ; Everything is contracted to 'any' for speed benefits, though there is already a big performance hit
; Keeps a list of the last n values of a behavior ; Keeps a list of the last n values of a behavior
(define/contract history-e (case-> (number? event? . -> . any) (define/contract history-e (case-> (number? event? . -> . any)
(event? . -> . any)) (event? . -> . any))
(case-lambda [(stream) (case-lambda [(stream)
(define ((add-to-complete-hist x) hist) (append hist (list x))) (define ((add-to-complete-hist x) hist) (append hist (list x)))
(accum-e (stream . ==> . add-to-complete-hist) empty)] (accum-e (stream . ==> . add-to-complete-hist) empty)]
[(n stream) [(n stream)
(define ((add-to-short-hist x) hist) (append (if (< (length hist) n) hist (rest hist)) (list x))) (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)])) (accum-e (stream . ==> . add-to-short-hist) empty)]))
(define/contract history-b (case-> (number? event? . -> . any) (define/contract history-b (case-> (number? event? . -> . any)
(event? . -> . any)) (event? . -> . any))
(case-lambda [(stream) (hold (history-e stream) empty)] (case-lambda [(stream) (hold (history-e stream) empty)]
[(n stream) (hold (history-e n stream) empty)])) [(n stream) (hold (history-e n stream) empty)]))
; Counts number of events on an event stream ; Counts number of events on an event stream
(define/contract count-b (event? . -> . any) (define/contract count-b (event? . -> . any)
(lambda (stream) (lambda (stream)
(hold (accum-e (stream . -=> . add1) 0) 0))) (hold (accum-e (stream . -=> . add1) 0) 0)))
; Keeps track of the largest value seen on a stream ; Keeps track of the largest value seen on a stream
(define/contract largest-val-b (event? . -> . any) (define/contract largest-val-b (event? . -> . any)
(lambda (stream) (lambda (stream)
(hold (accum-e (stream (hold (accum-e (stream
. ==> . . ==> .
(lambda (last) (lambda (last)
(lambda (x) (lambda (x)
(if (> x last) x last)))) (if (> x last) x last))))
-inf.0)))) -inf.0))))
; Keeps track of the smallest value seen on a stream ; Keeps track of the smallest value seen on a stream
(define/contract smallest-val-b (event? . -> . any) (define/contract smallest-val-b (event? . -> . any)
(lambda (stream) (lambda (stream)
(hold (accum-e (stream (hold (accum-e (stream
. ==> . . ==> .
(lambda (last) (lambda (last)
(lambda (x) (lambda (x)
(if (< x last) x last)))) (if (< x last) x last))))
+inf.0)))) +inf.0))))
; Matches a sequence of items in a list to event pings ; Matches a sequence of items in a list to event pings
(define/contract sequence-match? ((listof any/c) . -> . any) (define/contract sequence-match? ((listof any/c) . -> . any)
(lambda (seq evs) (lambda (seq evs)
(equal? seq (history-b (length seq) evs)))) (equal? seq (history-b (length seq) evs))))
; Cheap printf for behaviors ; Cheap printf for behaviors
(define printf-b format) (define printf-b format)
; Flattens a list ; Flattens a list
(define (flatten x) (define (flatten x)
(cond ((empty? x) '()) (cond ((empty? x) '())
((and (list? x) ((and (list? x)
(list? (first x))) (list? (first x)))
(append (flatten (car x)) (flatten (cdr x)))) (append (flatten (car x)) (flatten (cdr x))))
(else (list x))))) (else (list x)))))