176 lines
6.2 KiB
Scheme
176 lines
6.2 KiB
Scheme
(module mztake mzscheme
|
|
(require (lib "contract.ss")
|
|
(lib "match.ss")
|
|
(prefix frp: (lib "lang-ext.ss" "frtime"))
|
|
(rename (lib "frtime.ss" "frtime") frp:list list)
|
|
(rename (lib "frtime.ss" "frtime") frp:value-nowable? value-nowable?)
|
|
(rename (lib "frtime.ss" "frtime") frp:behaviorof behaviorof)
|
|
"mztake-structs.ss"
|
|
(lib "base-gm.ss" "frtime")
|
|
(lib "etc.ss")
|
|
(lib "list.ss")
|
|
"marks.ss"
|
|
"engine.ss")
|
|
|
|
;; Turn struct printing on for MzTake users.
|
|
(print-struct true)
|
|
|
|
(provide (rename loc loc$)
|
|
debug-process-running-e
|
|
loc/r
|
|
trace
|
|
bind
|
|
define/bind
|
|
define/bind-e
|
|
[rename loc/opt-col loc]
|
|
[rename mztake-top #%top])
|
|
|
|
(provide/contract [exceptions (() (debug-process?) . opt-> . frp:event?)]
|
|
[exited? (() (debug-process?) . opt-> . frp:behavior?)]
|
|
[kill (() (debug-process?) . opt-> . void?)]
|
|
[kill-all (-> void?)]
|
|
[set-running-e! ((frp:event?) (debug-process?) . opt-> . any)]
|
|
[set-running! ((frp:value-nowable?) (debug-process?) . opt-> . any)]
|
|
[where (() (debug-process?) . opt-> . frp:event?)]
|
|
|
|
[current-policy (case-> (-> any)
|
|
(any/c . -> . void?))]
|
|
[current-process (case-> (-> debug-process?)
|
|
(debug-process? . -> . void?))]
|
|
[current-reqspec (case-> (-> string?)
|
|
(string? . -> . void?))]
|
|
[create-debug-process (-> debug-process?)]
|
|
[set-main! ((require-spec?) (debug-process?) . opt-> . void?)]
|
|
[trace* (debug-process? loc? (-> any) . -> . frp:event?)]
|
|
[bind* (debug-process? symbol? . -> . any)])
|
|
|
|
(define (loc* after?)
|
|
(define (set-r r) (current-reqspec r))
|
|
(match-lambda*
|
|
[(arg) ((loc* after?) (current-reqspec) arg)]
|
|
[((and (not (? require-spec?)) arg) args ...) (apply (loc* after?) (current-reqspec) arg args)]
|
|
[((? require-spec? r) (? number? line)) (set-r r) (make-loc/lc r after? line false)]
|
|
[((? require-spec? r) (? number? line) (? number? col)) (set-r r) (make-loc/lc r after? line col)]
|
|
[((? require-spec? r) pattern) (set-r r) (make-loc/p r after? pattern)]))
|
|
|
|
(define loc/r (loc* true))
|
|
|
|
(define loc/opt-col (loc* false))
|
|
|
|
(define exceptions
|
|
(opt-lambda ([p (current-process)])
|
|
(debug-process-exceptions p)))
|
|
|
|
(define exited?
|
|
(opt-lambda ([p (current-process)])
|
|
(debug-process-exited? p)))
|
|
|
|
(define kill
|
|
(opt-lambda ([p (current-process)])
|
|
(unless (debug-process-exited? p)
|
|
(process:->dead p))))
|
|
|
|
(define (kill-all)
|
|
(unless (empty? all-debug-processes)
|
|
(for-each (lambda (p) (kill p)) all-debug-processes)
|
|
(display "All debug processes have been killed.")))
|
|
|
|
(define set-running-e!
|
|
(opt-lambda (e [process (current-process)])
|
|
(resume process)
|
|
(frp:set-cell! (debug-process-running-e process) e)))
|
|
|
|
(define set-running!
|
|
(opt-lambda (b [process (current-process)])
|
|
(if (frp:value-now b) (resume process) (pause process))
|
|
(frp:set-cell! (debug-process-running-e process) (frp:changes b))))
|
|
|
|
(define where
|
|
(opt-lambda ([p (current-process)])
|
|
(unless (debug-process-where p)
|
|
(set-debug-process-where! p (frp:event-receiver)))
|
|
(debug-process-where p)))
|
|
|
|
(define current-process (make-parameter (create-debug-process)))
|
|
(define current-reqspec (make-parameter false))
|
|
|
|
(define set-main!
|
|
(opt-lambda (reqspec [p (current-process)])
|
|
(current-reqspec reqspec )
|
|
(process:set-main! p reqspec)))
|
|
|
|
(define-syntax trace
|
|
(syntax-rules (=>)
|
|
[(_ loc)
|
|
(let ([loc* loc])
|
|
(if (loc-after? loc*)
|
|
(trace* (current-process) loc* identity)
|
|
(trace* (current-process) loc* (lambda () true))))]
|
|
[(_ loc => proc)
|
|
(trace* (current-process) loc proc)]
|
|
[(_ loc body ...)
|
|
(trace* (current-process) loc (lambda () body ...))]))
|
|
|
|
(define (mztake-top* name thunk)
|
|
(if (debug-process-marks (current-process))
|
|
(with-handlers
|
|
([exn:fail?
|
|
(lambda (exn)
|
|
(with-handlers
|
|
([exn:fail? (lambda (exn2) (raise exn2))])
|
|
(bind* (current-process) name)))])
|
|
(thunk))
|
|
(thunk)))
|
|
|
|
(define-syntax (mztake-top stx)
|
|
(syntax-case stx ()
|
|
[(_ . name)
|
|
#'(mztake-top* 'name (lambda () (#%top . name)))]))
|
|
|
|
(define (lookup-in-top-level p name)
|
|
(let/ec success
|
|
(define (try m)
|
|
(let/ec fail
|
|
(define (fail*) (fail false))
|
|
(success (hash-get (hash-get (debug-process-top-level p) m fail*) name fail*))))
|
|
(for-each try (map mark-module-name (debug-process-marks p)))
|
|
(hash-for-each (debug-process-top-level p) (lambda (m ns) (try m)))
|
|
(error 'bind "variable `~a' not found in target at the current location" name)))
|
|
|
|
(define (bind* p name)
|
|
(unless (debug-process-marks p)
|
|
(error "Bind called but the target process is not paused."))
|
|
|
|
(let ([bs (lookup-all-bindings
|
|
(lambda (id) (eq? (syntax-e id) name))
|
|
(debug-process-marks p))])
|
|
(if (empty? bs)
|
|
(lookup-in-top-level p name)
|
|
(mark-binding-value (first bs)))))
|
|
|
|
(define-syntax bind
|
|
(syntax-rules ()
|
|
[(_ (name ...) body0 body ...)
|
|
(let* ([p (current-process)]
|
|
[name (bind* p 'name)]
|
|
...)
|
|
body0 body ...)]))
|
|
|
|
(define-syntax define/bind-e
|
|
(syntax-rules ()
|
|
[(_ loc name ...)
|
|
(begin
|
|
(define here loc)
|
|
(define name (trace here (bind (name) name)))
|
|
...)]))
|
|
|
|
(define-syntax define/bind
|
|
(syntax-rules ()
|
|
[(_ loc name ...)
|
|
(begin
|
|
(define here loc)
|
|
(define name (frp:hold (trace here (bind (name) name))))
|
|
...)]))
|
|
|
|
|
|
) |