|
|
#lang racket/base
|
|
|
(require racket/string
|
|
|
(for-syntax racket/base)
|
|
|
"define.rkt")
|
|
|
|
|
|
(provide+safe report report/time time-name
|
|
|
report/line report/file
|
|
|
report* report*/line report*/file
|
|
|
report-apply repeat time-repeat time-repeat* time-name time-named time-avg compare)
|
|
|
|
|
|
(define (stringify-results expr-results)
|
|
|
(format (if (= 1 (length expr-results))
|
|
|
"~a"
|
|
|
"(values ~a)") (string-join (for/list ([r (in-list expr-results)])
|
|
|
(format "~v" r)) " ")))
|
|
|
|
|
|
(define-syntax (report stx)
|
|
|
(syntax-case stx ()
|
|
|
[(MACRO EXPR) #'(MACRO EXPR EXPR)]
|
|
|
[(_ EXPR NAME)
|
|
|
#'(let ([expr-results (call-with-values (λ () EXPR) list)])
|
|
|
(eprintf "~a = ~a\n" 'NAME (stringify-results expr-results))
|
|
|
(apply values expr-results))]))
|
|
|
|
|
|
(define-syntax (report/time stx)
|
|
|
(syntax-case stx ()
|
|
|
[(MACRO EXPR) #'(MACRO EXPR EXPR)]
|
|
|
[(_ EXPR NAME)
|
|
|
#'(let* ([op (open-output-string)]
|
|
|
[expr-results (parameterize ([current-output-port op])
|
|
|
(time (call-with-values (λ () EXPR) list)))])
|
|
|
(eprintf "~a = ~a [~a]\n" 'NAME (stringify-results expr-results) (string-trim (get-output-string op)))
|
|
|
(apply values expr-results))]))
|
|
|
|
|
|
(define-syntax (report/line stx)
|
|
|
(syntax-case stx ()
|
|
|
[(MACRO EXPR) #'(MACRO EXPR EXPR)]
|
|
|
[(_ EXPR NAME)
|
|
|
#`(let ([expr-results (call-with-values (λ () EXPR) list)])
|
|
|
(eprintf "~a = ~a on line ~a\n" 'NAME (stringify-results expr-results) #,(syntax-line #'EXPR))
|
|
|
(apply values expr-results))]))
|
|
|
|
|
|
(define-syntax (report/file stx)
|
|
|
(syntax-case stx ()
|
|
|
[(MACRO EXPR) #'(MACRO EXPR EXPR)]
|
|
|
[(_ EXPR NAME)
|
|
|
#`(let ([expr-results (call-with-values (λ () EXPR) list)])
|
|
|
(eprintf "~a = ~a on line ~a in \"~a\"\n" 'NAME (stringify-results expr-results)
|
|
|
#,(syntax-line #'EXPR)
|
|
|
'#,(syntax-source #'EXPR))
|
|
|
(apply values expr-results))]))
|
|
|
|
|
|
(define-syntax-rule (define-multi-version MULTI-NAME NAME)
|
|
|
(define-syntax-rule (MULTI-NAME x (... ...))
|
|
|
(begin (NAME x) (... ...))))
|
|
|
|
|
|
(define-multi-version report* report)
|
|
|
(define-multi-version report*/line report/line)
|
|
|
(define-multi-version report*/file report/file)
|
|
|
|
|
|
(define-syntax (report-apply stx)
|
|
|
(syntax-case stx ()
|
|
|
[(_ PROC EXPR)
|
|
|
#'(let ([lst EXPR])
|
|
|
(report (apply PROC lst) (apply PROC EXPR))
|
|
|
lst)]
|
|
|
[(_ PROC EXPR #:line)
|
|
|
#'(let ([lst EXPR])
|
|
|
(report (apply PROC lst) (apply PROC EXPR) #:line)
|
|
|
lst)]))
|
|
|
|
|
|
(define-syntax-rule (repeat NUM EXPR ...)
|
|
|
(for/last ([i (in-range NUM)])
|
|
|
EXPR ...))
|
|
|
|
|
|
(define-syntax-rule (time-repeat NUM EXPR ...)
|
|
|
(time (repeat NUM EXPR ...)))
|
|
|
|
|
|
(define (parse-time-str str)
|
|
|
(for/list ([num (in-port read (open-input-string str))]
|
|
|
#:when (number? num))
|
|
|
num))
|
|
|
|
|
|
(define-syntax-rule (time-avg NUM EXPR ...)
|
|
|
(let ([n NUM])
|
|
|
(define-values (strs results)
|
|
|
(for/lists (strs results)
|
|
|
([i n])
|
|
|
(let* ([op (open-output-string)]
|
|
|
[expr-results (parameterize ([current-output-port op])
|
|
|
(time (call-with-values (λ () EXPR ...) values)))])
|
|
|
(values (get-output-string op) expr-results))))
|
|
|
(displayln (apply format "~a: cpu time: ~a real time: ~a gc time: ~a (avg of ~a)"
|
|
|
(append
|
|
|
(list (car '(EXPR ...)))
|
|
|
(for/list ([vals (apply map list (map parse-time-str strs))])
|
|
|
(floor (/ (apply + vals) n)))
|
|
|
(list n))))
|
|
|
(car (reverse results))))
|
|
|
|
|
|
(define-syntax (time-repeat* stx)
|
|
|
(syntax-case stx ()
|
|
|
[(_ NUM EXPR ...)
|
|
|
#'(let ([n NUM])
|
|
|
(values (time-repeat n EXPR) ...))]))
|
|
|
|
|
|
(define-syntax (time-name stx)
|
|
|
(syntax-case stx ()
|
|
|
[(_ NAME EXPR ...)
|
|
|
#'(let* ([op (open-output-string)]
|
|
|
[expr-results (parameterize ([current-output-port op])
|
|
|
(time (call-with-values (λ () EXPR ...) values)))])
|
|
|
(display (format "~a: ~a" 'NAME (get-output-string op)))
|
|
|
expr-results)]))
|
|
|
|
|
|
(define-syntax (time-named stx)
|
|
|
(syntax-case stx ()
|
|
|
[(_ EXPR ...)
|
|
|
#'(let* ([op (open-output-string)]
|
|
|
[expr-results (parameterize ([current-output-port op])
|
|
|
(time (call-with-values (λ () EXPR ...) values)))])
|
|
|
(display (format "~a: ~a" (car '(EXPR ...)) (get-output-string op)))
|
|
|
expr-results)]))
|
|
|
|
|
|
(define-syntax (compare stx)
|
|
|
(syntax-case stx ()
|
|
|
[(_ EXPR ID ID-ALT ...)
|
|
|
#'(values EXPR (let ([ID ID-ALT]) EXPR) ...)]))
|
|
|
|
|
|
(module reader racket/base
|
|
|
(require syntax/module-reader racket/syntax version/utils)
|
|
|
(provide (rename-out [debug-read read]
|
|
|
[debug-read-syntax read-syntax]
|
|
|
[debug-get-info get-info]))
|
|
|
|
|
|
(define current-metalang-scope-flipper (make-parameter values))
|
|
|
|
|
|
(define (wrap-reader reader)
|
|
|
(λ args
|
|
|
(parameterize ([current-readtable (make-debug-readtable (current-readtable))]
|
|
|
[current-metalang-scope-flipper (make-syntax-introducer)])
|
|
|
(define stx (apply reader args))
|
|
|
(define proc (if (and (syntax? stx) (version<=? "6.2.900.4" (version)))
|
|
|
(current-metalang-scope-flipper)
|
|
|
values))
|
|
|
(proc stx))))
|
|
|
|
|
|
(define-values (debug-read debug-read-syntax debug-get-info)
|
|
|
(make-meta-reader
|
|
|
'sugar/debug
|
|
|
"language path"
|
|
|
(λ (bstr) ; copy of `lang-reader-module-paths`, only available since 6.7
|
|
|
(let* ([str (bytes->string/latin-1 bstr)]
|
|
|
[sym (string->symbol str)])
|
|
|
(and (module-path? sym)
|
|
|
(vector
|
|
|
;; try submod first:
|
|
|
`(submod ,sym reader)
|
|
|
;; fall back to /lang/reader:
|
|
|
(string->symbol (string-append str "/lang/reader"))))))
|
|
|
wrap-reader
|
|
|
wrap-reader
|
|
|
(λ (proc)
|
|
|
(λ (key defval)
|
|
|
(case key
|
|
|
[else (if proc (proc key defval) defval)])))))
|
|
|
|
|
|
(define report-char #\R)
|
|
|
|
|
|
(define (make-debug-readtable [rt (current-readtable)])
|
|
|
(make-readtable rt report-char 'dispatch-macro report-proc))
|
|
|
|
|
|
(define (another-report-char? ip) (and (char=? (peek-char ip) report-char) (read-char ip)))
|
|
|
|
|
|
(define (report-proc trigger-char ip src ln col pos)
|
|
|
(define flip-metalang-scope (current-metalang-scope-flipper))
|
|
|
(flip-metalang-scope (with-syntax ([REPORT-ID (cond
|
|
|
[(not (another-report-char? ip)) 'report] ; #R...
|
|
|
[(not (another-report-char? ip)) 'report/line] ; #RR...
|
|
|
[else 'report/file])] ; #RRR...
|
|
|
[STX (flip-metalang-scope (read-syntax/recursive src ip))])
|
|
|
#'(let ()
|
|
|
(local-require (only-in sugar/debug REPORT-ID))
|
|
|
(REPORT-ID STX))))))
|