added with-eval-preserve-source-locations to scribble/eval
Makes it possible to show examples of redex term->pict, etc. original commit: 516f56fc83653558d3b3bfea8cb471a213dcbe25
This commit is contained in:
parent
af5721a887
commit
d16c59f097
|
@ -7,7 +7,9 @@
|
||||||
racket/pretty ;; attached into new namespace via anchor
|
racket/pretty ;; attached into new namespace via anchor
|
||||||
racket/sandbox racket/promise racket/port
|
racket/sandbox racket/promise racket/port
|
||||||
racket/gui/dynamic
|
racket/gui/dynamic
|
||||||
(for-syntax racket/base)
|
(for-syntax racket/base syntax/srcloc unstable/struct)
|
||||||
|
racket/stxparam
|
||||||
|
racket/splicing
|
||||||
scribble/text/wrap)
|
scribble/text/wrap)
|
||||||
|
|
||||||
(provide interaction
|
(provide interaction
|
||||||
|
@ -32,7 +34,8 @@
|
||||||
close-eval
|
close-eval
|
||||||
|
|
||||||
scribble-exn->string
|
scribble-exn->string
|
||||||
scribble-eval-handler)
|
scribble-eval-handler
|
||||||
|
with-eval-preserve-source-locations)
|
||||||
|
|
||||||
(define scribble-eval-handler
|
(define scribble-eval-handler
|
||||||
(make-parameter (lambda (ev c? x) (ev x))))
|
(make-parameter (lambda (ev c? x) (ev x))))
|
||||||
|
@ -412,6 +415,15 @@
|
||||||
[else s]))))
|
[else s]))))
|
||||||
list)))
|
list)))
|
||||||
|
|
||||||
|
(define-syntax-parameter quote-expr-preserve-source? #f)
|
||||||
|
|
||||||
|
(define-syntax (with-eval-preserve-source-locations stx)
|
||||||
|
(syntax-case stx ()
|
||||||
|
[(with-eval-preserve-source-locations e ...)
|
||||||
|
(syntax/loc stx
|
||||||
|
(splicing-syntax-parameterize ([quote-expr-preserve-source? #t])
|
||||||
|
e ...))]))
|
||||||
|
|
||||||
;; Quote an expression to be evaluated or wrap as escaped:
|
;; Quote an expression to be evaluated or wrap as escaped:
|
||||||
(define-syntax quote-expr
|
(define-syntax quote-expr
|
||||||
(syntax-rules (eval:alts eval:result eval:results)
|
(syntax-rules (eval:alts eval:result eval:results)
|
||||||
|
@ -422,13 +434,63 @@
|
||||||
[(_ (eval:results es)) (make-eval-results es "" "")]
|
[(_ (eval:results es)) (make-eval-results es "" "")]
|
||||||
[(_ (eval:results es out)) (make-eval-results es out "")]
|
[(_ (eval:results es out)) (make-eval-results es out "")]
|
||||||
[(_ (eval:results es out err)) (make-eval-results es out err)]
|
[(_ (eval:results es out err)) (make-eval-results es out err)]
|
||||||
|
[(_ e) (base-quote-expr e)]))
|
||||||
|
|
||||||
|
(define orig-stx (read-syntax 'orig (open-input-string "()")))
|
||||||
|
|
||||||
|
(define-syntax (base-quote-expr stx)
|
||||||
|
(syntax-case stx ()
|
||||||
[(_ e)
|
[(_ e)
|
||||||
;; Using quote means that sandbox evaluation works on
|
(cond [(syntax-parameter-value #'quote-expr-preserve-source?)
|
||||||
;; sexprs; to get it to work on syntaxes, use
|
;; Preserve source; produce an expression resulting in a
|
||||||
;; (strip-context (quote-syntax e)))
|
;; syntax object with no lexical context (like strip-context)
|
||||||
;; while importing
|
;; but with (quotable) source locations.
|
||||||
;; (require syntax/strip-context)
|
;; Also preserve syntax-original?, since that seems important
|
||||||
'e]))
|
;; to some syntax-based code (eg redex term->pict).
|
||||||
|
(define (get-source-location e)
|
||||||
|
(let* ([src (build-source-location-list e)]
|
||||||
|
[old-source (source-location-source src)]
|
||||||
|
[new-source
|
||||||
|
(cond [(path? old-source) ;; not quotable/writable
|
||||||
|
;;(path->string old-source) ;; don't leak build paths
|
||||||
|
'eval]
|
||||||
|
[(or (string? old-source)
|
||||||
|
(symbol? old-source))
|
||||||
|
;; Okay? Or should this be replaced also?
|
||||||
|
old-source]
|
||||||
|
[else #f])])
|
||||||
|
(update-source-location src #:source new-source)))
|
||||||
|
(let loop ([e #'e])
|
||||||
|
(cond [(syntax? e)
|
||||||
|
(let ([src (get-source-location e)]
|
||||||
|
[original? (syntax-original? (syntax-local-introduce e))])
|
||||||
|
#`(syntax-property
|
||||||
|
(datum->syntax #f
|
||||||
|
#,(loop (syntax-e e))
|
||||||
|
(quote #,src)
|
||||||
|
#,(if original? #'orig-stx #'#f))
|
||||||
|
'paren-shape
|
||||||
|
(quote #,(syntax-property e 'paren-shape))))]
|
||||||
|
[(pair? e)
|
||||||
|
#`(cons #,(loop (car e)) #,(loop (cdr e)))]
|
||||||
|
[(vector? e)
|
||||||
|
#`(list->vector #,(loop (vector->list e)))]
|
||||||
|
[(box? e)
|
||||||
|
#`(box #,(loop (unbox e)))]
|
||||||
|
[(prefab-struct-key e)
|
||||||
|
=> (lambda (key)
|
||||||
|
#`(apply make-prefab-struct
|
||||||
|
(quote #,key)
|
||||||
|
#,(loop (struct->list e))))]
|
||||||
|
[else
|
||||||
|
#`(quote #,e)]))]
|
||||||
|
[else
|
||||||
|
;; Using quote means that sandbox evaluation works on
|
||||||
|
;; sexprs; to get it to work on syntaxes, use
|
||||||
|
;; (strip-context (quote-syntax e)))
|
||||||
|
;; while importing
|
||||||
|
;; (require syntax/strip-context)
|
||||||
|
#'(quote e)])]))
|
||||||
|
|
||||||
(define (do-interaction-eval ev e)
|
(define (do-interaction-eval ev e)
|
||||||
(let-values ([(e expect) (extract-to-evaluate e)])
|
(let-values ([(e expect) (extract-to-evaluate e)])
|
||||||
|
|
|
@ -209,3 +209,13 @@ results), @racket[#f] otherwise.}
|
||||||
(exn-message e)
|
(exn-message e)
|
||||||
(format "uncaught exception: ~s" e)))]
|
(format "uncaught exception: ~s" e)))]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@defform[(with-eval-preserve-source-locations expr ...)]{
|
||||||
|
|
||||||
|
By default, the evaluation forms provided by this module, such as
|
||||||
|
@racket[interaction] and @racket[examples], discard the source
|
||||||
|
locations from the expressions they evaluate. Within a
|
||||||
|
@racket[with-eval-preserve-source-locations] form, the source
|
||||||
|
locations are preserved. This can be useful for documenting forms that
|
||||||
|
depend on source locations, such as Redex's typesetting macros.
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user