Compare commits
No commits in common. "doc-change" and "master" have entirely different histories.
doc-change
...
master
|
@ -6,7 +6,8 @@ env:
|
|||
global:
|
||||
- RACKET_DIR=~/racket
|
||||
matrix:
|
||||
- RACKET_VERSION=6.7
|
||||
- RACKET_VERSION=6.2
|
||||
- RACKET_VERSION=6.2.1
|
||||
- RACKET_VERSION=HEAD
|
||||
|
||||
matrix:
|
||||
|
@ -26,6 +27,6 @@ before_script:
|
|||
|
||||
script:
|
||||
- raco pkg install --deps search-auto --link debug
|
||||
- raco test -p debug
|
||||
- raco test -x -p debug
|
||||
|
||||
after_script:
|
||||
|
|
34
README.md
34
README.md
|
@ -1,11 +1,9 @@
|
|||
debug [](https://travis-ci.org/AlexKnauth/debug)
|
||||
==
|
||||
A lang-extension for debugging, based on sugar/debug from [mbutterick/sugar](https://github.com/mbutterick/sugar)
|
||||
A meta-language for debugging, based on sugar/debug from [mbutterick/sugar](https://github.com/mbutterick/sugar)
|
||||
|
||||
documentation: http://pkg-build.racket-lang.org/doc/debug/index.html
|
||||
|
||||
### `#lang debug`
|
||||
|
||||
To debug the value of an expression, simply put `debug` in front of the language at the top of
|
||||
the file (for instance `#lang debug racket`), and put `#R`, `#RR` or `#RRR` in front of the
|
||||
expression.
|
||||
|
@ -33,33 +31,3 @@ Shows the output:
|
|||
(* 3 4) = 12
|
||||
15
|
||||
```
|
||||
|
||||
### `debug-repl`
|
||||
|
||||
```racket
|
||||
> (require debug/repl)
|
||||
> (define (f x y)
|
||||
(debug-repl))
|
||||
> (f 1 2)
|
||||
-> ; in the debug-repl now
|
||||
x
|
||||
1
|
||||
-> y
|
||||
2
|
||||
-> (+ x y)
|
||||
3
|
||||
-> ; exit the debug-repl by pressing ctrl-D
|
||||
> ; back in the normal repl
|
||||
(f (λ (g a) (g a)) (list add1 4))
|
||||
-> ; a new debug-repl
|
||||
x
|
||||
#<procedure>
|
||||
-> y
|
||||
(list #<procedure:add1> 4)
|
||||
-> (x string->number "3")
|
||||
3
|
||||
-> (x (first y) (second y))
|
||||
5
|
||||
-> ; exit this debug-repl by pressing ctrl-D
|
||||
```
|
||||
|
||||
|
|
|
@ -2,6 +2,3 @@
|
|||
|
||||
(define scribblings '(["scribblings/debug.scrbl" ()]))
|
||||
|
||||
(define compile-omit-paths
|
||||
'("test/debug-repl-macros.rkt"
|
||||
))
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
#lang racket/base
|
||||
|
||||
(provide make-variable-like-transformer)
|
||||
|
||||
(define make-variable-like-transformer
|
||||
(with-handlers
|
||||
([exn:fail:filesystem:missing-module?
|
||||
(λ (e)
|
||||
(dynamic-require 'unstable/syntax
|
||||
'make-variable-like-transformer))])
|
||||
(dynamic-require 'syntax/transformer
|
||||
'make-variable-like-transformer)))
|
||||
|
103
debug/repl.rkt
103
debug/repl.rkt
|
@ -1,103 +0,0 @@
|
|||
#lang racket/base
|
||||
|
||||
(provide debug-repl resume)
|
||||
|
||||
(require "private/make-variable-like-transformer.rkt"
|
||||
racket/list
|
||||
racket/splicing
|
||||
(for-syntax racket/base
|
||||
racket/list
|
||||
syntax/parse
|
||||
))
|
||||
|
||||
(define debug-repl-prompt-tag (make-continuation-prompt-tag 'debug-repl))
|
||||
(define debug-repl-abort-handler values)
|
||||
|
||||
;; ----------------------------------------------------------------------------
|
||||
|
||||
(begin-for-syntax
|
||||
;; syntax-find-local-variables : Syntax -> (Listof Id)
|
||||
(define (syntax-find-local-variables stx)
|
||||
(define debug-info (syntax-debug-info stx (syntax-local-phase-level) #t))
|
||||
(define context (hash-ref debug-info 'context))
|
||||
(define bindings (hash-ref debug-info 'bindings))
|
||||
(remove-duplicates
|
||||
(for/list ([binding (in-list bindings)]
|
||||
#:when (hash-has-key? binding 'local)
|
||||
#:when (context-subset? (hash-ref binding 'context) context))
|
||||
(datum->syntax stx (hash-ref binding 'name) stx))
|
||||
bound-identifier=?))
|
||||
|
||||
;; context-subset? : Context Context -> Boolean
|
||||
(define (context-subset? a b)
|
||||
;; TODO: use an actual set-of-scopes subset function
|
||||
(list-prefix? a b))
|
||||
|
||||
;; non-macro-id? : Id -> Boolean
|
||||
(define NON-MACRO (gensym 'NON-MACRO))
|
||||
(define (non-macro-id? id)
|
||||
(eq? NON-MACRO (syntax-local-value id (λ () NON-MACRO))))
|
||||
)
|
||||
|
||||
(define-syntax debug-repl
|
||||
(lambda (stx)
|
||||
(syntax-parse stx
|
||||
[(debug-repl)
|
||||
#:do [(define all-vars (syntax-find-local-variables stx))
|
||||
(define-values [xs ms]
|
||||
(partition non-macro-id? all-vars))]
|
||||
#:with [x ...] xs
|
||||
#:with [m ...] ms
|
||||
#:with [mv ...] (map (λ (m)
|
||||
(datum->syntax
|
||||
stx
|
||||
`(quote ,(syntax-local-value m))))
|
||||
ms)
|
||||
#:with varref (syntax-local-introduce #'(#%variable-reference))
|
||||
#'(debug-repl/varref+hash
|
||||
varref
|
||||
(list (list (quote-syntax x) (λ () x)) ...)
|
||||
(list (list (quote-syntax m) mv) ...))])))
|
||||
|
||||
;; debug-repl/varref+hash :
|
||||
;; Variable-Ref
|
||||
;; (Listof (List Id (-> Any)))
|
||||
;; (Listof (List Id Any))
|
||||
;; ->
|
||||
;; Any
|
||||
(define (debug-repl/varref+hash varref var-list macro-list)
|
||||
(define ns (variable-reference->namespace varref))
|
||||
(define intro (make-syntax-introducer #true))
|
||||
(for ([pair (in-list var-list)])
|
||||
(namespace-define-transformer-binding!
|
||||
ns
|
||||
(intro (first pair))
|
||||
(make-variable-like-transformer #`(#,(second pair)))))
|
||||
(for ([pair (in-list macro-list)])
|
||||
(namespace-define-transformer-binding!
|
||||
ns
|
||||
(intro (first pair))
|
||||
(second pair)))
|
||||
(define old-prompt-read (current-prompt-read))
|
||||
(define old-eval (current-eval))
|
||||
(define (new-prompt-read)
|
||||
(write-char #\-)
|
||||
(old-prompt-read))
|
||||
(define (new-eval stx)
|
||||
(old-eval (intro stx)))
|
||||
(parameterize ([current-namespace ns]
|
||||
[current-prompt-read new-prompt-read]
|
||||
[current-eval new-eval])
|
||||
(call-with-continuation-prompt
|
||||
read-eval-print-loop
|
||||
debug-repl-prompt-tag
|
||||
debug-repl-abort-handler)))
|
||||
|
||||
;; namespace-define-transformer-binding! : Namespace Symbol Any -> Void
|
||||
(define (namespace-define-transformer-binding! ns sym val)
|
||||
(eval #`(define-syntax #,(datum->syntax #f sym) #,val) ns))
|
||||
|
||||
;; resume : Any ... -> Nothing
|
||||
(define (resume . vs)
|
||||
(apply abort-current-continuation debug-repl-prompt-tag vs))
|
||||
|
|
@ -1,19 +1,15 @@
|
|||
#lang scribble/manual
|
||||
|
||||
@(require (for-label racket/base
|
||||
debug/repl
|
||||
))
|
||||
|
||||
@title{debug}
|
||||
|
||||
source code: @url{https://github.com/AlexKnauth/debug}
|
||||
|
||||
A racket lang-extension for debugging, based on sugar/debug.
|
||||
A racket meta-language for debugging, based on sugar/debug.
|
||||
|
||||
@section{#lang debug}
|
||||
|
||||
@defmodule[debug #:lang]{
|
||||
A lang-extension (like @racketmodname[at-exp]) that allows for quick debugging
|
||||
A meta-language (like @racketmodname[at-exp]) that allows for quick debugging
|
||||
shorthands to a program written in any racket-based language that looks at the
|
||||
readtable.
|
||||
}
|
||||
|
@ -43,42 +39,3 @@ Examples:
|
|||
;(* 3 4) = 12
|
||||
;15
|
||||
}
|
||||
|
||||
@section{debug-repl}
|
||||
|
||||
@defmodule[debug/repl]
|
||||
|
||||
@defform[(debug-repl)]{
|
||||
Creates a repl for debugging, which can access local variables in the context
|
||||
where it is used.
|
||||
|
||||
For example a @racket[(debug-repl)] in a @racket[let] form
|
||||
@codeblock[#:keep-lang-line? #f]{
|
||||
#lang racket
|
||||
(let ([x 1] [y 2])
|
||||
(debug-repl))
|
||||
}
|
||||
Will be able to access the @racket[x] and @racket[y] local variables (if
|
||||
debugging information is enabled in DrRacket's
|
||||
@seclink["Language" #:doc '(lib "scribblings/drracket/drracket.scrbl")]{
|
||||
@onscreen{Choose Language}} window, or if the program was executed using
|
||||
@exec{racket -l errortrace -t myprogram.rkt}).
|
||||
|
||||
It becomes much more useful in a function definition:
|
||||
@codeblock[#:keep-lang-line? #f]{
|
||||
#lang racket
|
||||
(define (f x y)
|
||||
(debug-repl))
|
||||
}
|
||||
Then if you call @racket[(f 1 2)], it will create a repl where @racket[x] is
|
||||
@racket[1] and @racket[y] is @racket[2].
|
||||
|
||||
In one of these repls, you can try evaluating different expressions. If you're
|
||||
debugging a higher-order function for example, you can try out the functions
|
||||
it accepts or creates with multiple sets of arguments to see how they react.
|
||||
|
||||
@defproc[(resume [v any/c] ...) any]{
|
||||
When called inside of a @racket[debug-repl], exits the repl. The call to
|
||||
@racket[debug-repl] returns the arguments to @racket[resume].
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,92 +0,0 @@
|
|||
#lang racket/base
|
||||
|
||||
(require "../repl.rkt"
|
||||
"test-util.rkt"
|
||||
rackunit
|
||||
(for-syntax racket/base syntax/parse))
|
||||
|
||||
(define a 3)
|
||||
(define b 4)
|
||||
|
||||
(test-case "local macros that don't refer to other macros"
|
||||
(define (f tmp)
|
||||
(define-syntax ?list
|
||||
(syntax-parser
|
||||
[(?list x:expr ...)
|
||||
(define (?list-helper acc xs)
|
||||
(syntax-parse (list acc xs)
|
||||
[([acc:id ...] []) #'(list acc ...)]
|
||||
[([acc:id ...] [x:expr y:expr ...])
|
||||
#:with [tmp] (generate-temporaries #'[x])
|
||||
#`(let ([tmp x])
|
||||
(if tmp
|
||||
#,(?list-helper #'[acc ... tmp] #'[y ...])
|
||||
#false))]))
|
||||
(?list-helper #'[] #'[x ...])]
|
||||
[stx
|
||||
;; TODO: figure out how to make syntax-parse's own errors
|
||||
;; not cause infinite loops
|
||||
(raise-syntax-error #f "bad syntax" #'stx)]))
|
||||
(debug-repl)
|
||||
tmp)
|
||||
|
||||
(test-with-io
|
||||
#:i [i (open-input-string "a b tmp (?list a b tmp)")]
|
||||
#:o [o (open-output-string)]
|
||||
(check-equal? (f 1) 1)
|
||||
(check-equal? (get-output-string o)
|
||||
(string-append
|
||||
"-> " #;a "3\n"
|
||||
"-> " #;b "4\n"
|
||||
"-> " #;tmp "1\n"
|
||||
"-> " #;(?list a b tmp) "'(3 4 1)\n"
|
||||
"-> ")))
|
||||
|
||||
(test-with-io
|
||||
#:i [i (open-input-string "(?list . bluh)")]
|
||||
#:o [o (open-output-string)]
|
||||
(check-exn #rx"\\?list: bad syntax"
|
||||
(λ () (f 1)))
|
||||
(check-equal? (get-output-string o)
|
||||
(string-append
|
||||
"-> " #;(?list . bluh)))))
|
||||
|
||||
;; TODO: !!! identifier used out of context !!!
|
||||
#;
|
||||
(test-case "local macros that refer to other macros"
|
||||
(define (f tmp)
|
||||
(define-syntax ?list-helper
|
||||
(syntax-parser
|
||||
[(?list-helper [acc:id ...] []) #'(list acc ...)]
|
||||
[(?list-helper [acc:id ...] [x:expr y:expr ...])
|
||||
#'(let ([tmp x])
|
||||
(if tmp
|
||||
(?list-helper [acc ... tmp] [y ...])
|
||||
#false))]))
|
||||
(define-syntax-rule (?list x ...)
|
||||
(?list-helper [] [x ...]))
|
||||
(debug-repl)
|
||||
tmp)
|
||||
|
||||
(test-with-io
|
||||
#:i [i (open-input-string "a b tmp (?list a b tmp)")]
|
||||
#:o [o (open-output-string)]
|
||||
(check-equal? (f 1) 1)
|
||||
(check-equal? (get-output-string o)
|
||||
(string-append
|
||||
"-> " #;a "3\n"
|
||||
"-> " #;b "4\n"
|
||||
"-> " #;tmp "1\n"
|
||||
"-> " #;(?list a b tmp) "'(3 4 1)\n"
|
||||
"-> ")))
|
||||
|
||||
(test-with-io
|
||||
#:i [i (open-input-string "a b tmp (+ a b tmp)")]
|
||||
#:o [o (open-output-string)]
|
||||
(check-exn #rx"a: undefined;\n cannot use before initialization"
|
||||
(λ () (f 1)))
|
||||
(check-equal? (get-output-string o)
|
||||
(string-append
|
||||
"-> " #;b "4\n"
|
||||
"-> " #;(+ b 13) "17\n"
|
||||
"-> " #;(+ a b 13)))))
|
|
@ -1,103 +0,0 @@
|
|||
#lang racket/base
|
||||
|
||||
(require "../repl.rkt"
|
||||
"test-util.rkt"
|
||||
rackunit)
|
||||
|
||||
(define a 3)
|
||||
(define b 4)
|
||||
|
||||
(define-syntax-rule (with-other-vars body)
|
||||
(let ([x 5] [z 6])
|
||||
;; x and z are not available outside this scope
|
||||
body))
|
||||
|
||||
(define (f x y)
|
||||
;; x and y are local variables
|
||||
(with-other-vars
|
||||
(let ([y 7] [b 8] [c 9])
|
||||
;; y, b, and c are local variables
|
||||
(debug-repl)
|
||||
x)))
|
||||
|
||||
(test-with-io
|
||||
#:i [i (open-input-string "x y a b c (+ x y a b c) (with-other-vars x)")]
|
||||
#:o [o (open-output-string)]
|
||||
(check-equal? (f 1 2) 1)
|
||||
(check-equal? (get-output-string o)
|
||||
(string-append
|
||||
"-> " #;x "1\n"
|
||||
"-> " #;y "7\n"
|
||||
"-> " #;a "3\n"
|
||||
"-> " #;b "8\n"
|
||||
"-> " #;c "9\n"
|
||||
"-> " #;(+ x y a b c) "28\n"
|
||||
"-> " #;(with-other-vars x) "1\n"
|
||||
"-> "))
|
||||
)
|
||||
|
||||
;; test for issue #9
|
||||
(test-case "issue #9"
|
||||
(define (f)
|
||||
(when #true
|
||||
(debug-repl))
|
||||
(define a 1)
|
||||
a)
|
||||
|
||||
(test-with-io
|
||||
#:i [i (open-input-string "b (+ b 13)")]
|
||||
#:o [o (open-output-string)]
|
||||
(check-equal? (f) 1)
|
||||
(check-equal? (get-output-string o)
|
||||
(string-append
|
||||
"-> " #;b "4\n"
|
||||
"-> " #;(+ b 13) "17\n"
|
||||
"-> ")))
|
||||
|
||||
(test-with-io
|
||||
#:i [i (open-input-string "b (+ b 13) (+ a b 13)")]
|
||||
#:o [o (open-output-string)]
|
||||
(check-exn #rx"a: undefined;\n cannot use before initialization"
|
||||
(λ () (f)))
|
||||
(check-equal? (get-output-string o)
|
||||
(string-append
|
||||
"-> " #;b "4\n"
|
||||
"-> " #;(+ b 13) "17\n"
|
||||
"-> " #;(+ a b 13)))))
|
||||
|
||||
;; test for mutation
|
||||
(define x-for-mutation 1)
|
||||
|
||||
(test-case "test for mutation"
|
||||
|
||||
(define (f1 x-for-mutation)
|
||||
(debug-repl)
|
||||
x-for-mutation)
|
||||
|
||||
(define (f2)
|
||||
(debug-repl)
|
||||
x-for-mutation)
|
||||
|
||||
(test-with-io
|
||||
#:i [i (open-input-string "x-for-mutation")]
|
||||
#:o [o (open-output-string)]
|
||||
(check-equal? x-for-mutation 1)
|
||||
(check-equal? (f1 2) 2)
|
||||
(check-equal? (get-output-string o)
|
||||
(string-append
|
||||
"-> " #;x-for-mutation "2\n"
|
||||
"-> "))
|
||||
(check-equal? x-for-mutation 1))
|
||||
|
||||
(test-with-io
|
||||
#:i [i (open-input-string "x-for-mutation")]
|
||||
#:o [o (open-output-string)]
|
||||
(check-equal? x-for-mutation 1)
|
||||
(check-equal? (f2) 1)
|
||||
(check-equal? (get-output-string o)
|
||||
(string-append
|
||||
"-> " #;x-for-mutation "1\n"
|
||||
"-> "))
|
||||
(check-equal? x-for-mutation 1)))
|
||||
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
#lang racket/base
|
||||
|
||||
(provide test-with-io)
|
||||
|
||||
(define-syntax-rule (test-with-io
|
||||
#:i [i input-port]
|
||||
#:o [o output-port]
|
||||
body ...)
|
||||
(let ([i input-port]
|
||||
[o output-port])
|
||||
(parameterize ([current-input-port i]
|
||||
[current-output-port o])
|
||||
body ...)))
|
||||
|
8
info.rkt
8
info.rkt
|
@ -2,13 +2,9 @@
|
|||
|
||||
(define collection 'multi)
|
||||
|
||||
;; Require a version of racket after this commit:
|
||||
;; make `variable-reference->namespace` enable top-level mode
|
||||
;; d1c2daf15b8be048b5cea63d5a1d7206bfc8d43f
|
||||
|
||||
(define deps
|
||||
'(["base" #:version "6.6.0.3"]
|
||||
"rackunit-lib"
|
||||
'("rackunit-lib"
|
||||
"base"
|
||||
))
|
||||
|
||||
(define build-deps
|
||||
|
|
Loading…
Reference in New Issue
Block a user