make macro stepper recover from jumps within expansion
original commit: 678fc4d6f894df87c79a4277eb41c46ace1ea9b3
This commit is contained in:
parent
b3dd6bfbae
commit
d0712ceee2
|
@ -47,6 +47,7 @@
|
||||||
(define-struct track-origin (before after) #:transparent)
|
(define-struct track-origin (before after) #:transparent)
|
||||||
(define-struct local-remark (contents) #:transparent)
|
(define-struct local-remark (contents) #:transparent)
|
||||||
;; contents : (listof (U string syntax))
|
;; contents : (listof (U string syntax))
|
||||||
|
(define-struct local-mess (events) #:transparent)
|
||||||
|
|
||||||
;; A PrimDeriv is one of
|
;; A PrimDeriv is one of
|
||||||
(define-struct (prule base) () #:transparent)
|
(define-struct (prule base) () #:transparent)
|
||||||
|
|
|
@ -42,7 +42,7 @@
|
||||||
enter-list exit-list
|
enter-list exit-list
|
||||||
enter-check exit-check
|
enter-check exit-check
|
||||||
local-post exit-local exit-local/expr
|
local-post exit-local exit-local/expr
|
||||||
local-bind enter-bind exit-bind
|
local-bind enter-bind exit-bind exit-local-bind
|
||||||
local-value-result local-value-binding
|
local-value-result local-value-binding
|
||||||
phase-up module-body
|
phase-up module-body
|
||||||
renames-lambda
|
renames-lambda
|
||||||
|
@ -173,8 +173,9 @@
|
||||||
(#:args e1 rs next)
|
(#:args e1 rs next)
|
||||||
[(enter-macro ! macro-pre-transform (? LocalActions)
|
[(enter-macro ! macro-pre-transform (? LocalActions)
|
||||||
macro-post-transform ! exit-macro)
|
macro-post-transform ! exit-macro)
|
||||||
(make mrule e1 (and next (wderiv-e2 next)) rs $2
|
(let ([e2 (and next (wderiv-e2 next))])
|
||||||
$3 $4 $5 $6 $7 next)])
|
(make mrule e1 e2 rs $2
|
||||||
|
$3 $4 (and $5 (car $5)) $6 $7 next))])
|
||||||
|
|
||||||
;; Keyword resolution
|
;; Keyword resolution
|
||||||
(Resolves
|
(Resolves
|
||||||
|
@ -202,9 +203,9 @@
|
||||||
(make local-lift-require (car $1) (cadr $1) (cddr $1))]
|
(make local-lift-require (car $1) (cadr $1) (cddr $1))]
|
||||||
[(lift-provide)
|
[(lift-provide)
|
||||||
(make local-lift-provide $1)]
|
(make local-lift-provide $1)]
|
||||||
[(local-bind ! rename-list next)
|
[(local-bind ! rename-list exit-local-bind)
|
||||||
(make local-bind $1 $2 $3 #f)]
|
(make local-bind $1 $2 $3 #f)]
|
||||||
[(local-bind rename-list (? BindSyntaxes) next)
|
[(local-bind rename-list (? BindSyntaxes) exit-local-bind)
|
||||||
(make local-bind $1 #f $2 $3)]
|
(make local-bind $1 #f $2 $3)]
|
||||||
[(track-origin)
|
[(track-origin)
|
||||||
(make track-origin (car $1) (cdr $1))]
|
(make track-origin (car $1) (cdr $1))]
|
||||||
|
@ -224,6 +225,10 @@
|
||||||
before null after #f mafter
|
before null after #f mafter
|
||||||
(make p:stop mafter mafter null #f))
|
(make p:stop mafter mafter null #f))
|
||||||
#f after #f))]
|
#f after #f))]
|
||||||
|
[(local-mess)
|
||||||
|
;; Represents subsequence of event stream incoherent due to
|
||||||
|
;; jump (eg, macro catches exn raised from within local-expand).
|
||||||
|
(make local-mess $1)]
|
||||||
;; -- Not really local actions, but can occur during evaluation
|
;; -- Not really local actions, but can occur during evaluation
|
||||||
;; called 'expand' (not 'local-expand') within transformer
|
;; called 'expand' (not 'local-expand') within transformer
|
||||||
[(start (? EE)) #f]
|
[(start (? EE)) #f]
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
EOF ; .
|
EOF ; .
|
||||||
enter-bind ; .
|
enter-bind ; .
|
||||||
exit-bind ; .
|
exit-bind ; .
|
||||||
|
exit-local-bind ; .
|
||||||
IMPOSSIBLE ; useful for error-handling clauses that have no
|
IMPOSSIBLE ; useful for error-handling clauses that have no
|
||||||
; NoError counterpart
|
; NoError counterpart
|
||||||
top-non-begin ; .
|
top-non-begin ; .
|
||||||
|
@ -26,7 +27,7 @@
|
||||||
resolve ; identifier
|
resolve ; identifier
|
||||||
enter-macro ; syntax
|
enter-macro ; syntax
|
||||||
macro-pre-transform ; syntax
|
macro-pre-transform ; syntax
|
||||||
macro-post-transform ; syntax
|
macro-post-transform ; (cons syntax syntax)
|
||||||
exit-macro ; syntax
|
exit-macro ; syntax
|
||||||
enter-prim ; syntax
|
enter-prim ; syntax
|
||||||
exit-prim ; syntax
|
exit-prim ; syntax
|
||||||
|
@ -73,6 +74,7 @@
|
||||||
local-value ; identifier
|
local-value ; identifier
|
||||||
local-value-result ; boolean
|
local-value-result ; boolean
|
||||||
local-value-binding ; result of identifier-binding; added by trace.rkt, not expander
|
local-value-binding ; result of identifier-binding; added by trace.rkt, not expander
|
||||||
|
local-mess ; (listof event)
|
||||||
))
|
))
|
||||||
|
|
||||||
(define-tokens renames-tokens
|
(define-tokens renames-tokens
|
||||||
|
@ -113,6 +115,7 @@
|
||||||
(#f local-remark ,token-local-remark)
|
(#f local-remark ,token-local-remark)
|
||||||
(#f local-artificial-step ,token-local-artificial-step)
|
(#f local-artificial-step ,token-local-artificial-step)
|
||||||
(#f local-value-binding ,token-local-value-binding)
|
(#f local-value-binding ,token-local-value-binding)
|
||||||
|
(#f local-mess ,token-local-mess)
|
||||||
|
|
||||||
;; Standard signals
|
;; Standard signals
|
||||||
(0 visit ,token-visit)
|
(0 visit ,token-visit)
|
||||||
|
@ -198,6 +201,7 @@
|
||||||
(157 prepare-env)
|
(157 prepare-env)
|
||||||
(158 prim-submodule)
|
(158 prim-submodule)
|
||||||
(159 prim-submodule*)
|
(159 prim-submodule*)
|
||||||
|
(160 exit-local-bind)
|
||||||
))
|
))
|
||||||
|
|
||||||
(define (signal->symbol sig)
|
(define (signal->symbol sig)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#lang racket/base
|
#lang racket/base
|
||||||
(require (for-syntax racket/base)
|
(require (for-syntax racket/base)
|
||||||
racket/match
|
racket/match
|
||||||
|
racket/format
|
||||||
syntax/stx
|
syntax/stx
|
||||||
"../util/eomap.rkt"
|
"../util/eomap.rkt"
|
||||||
"deriv-util.rkt"
|
"deriv-util.rkt"
|
||||||
|
@ -505,7 +506,17 @@
|
||||||
]]
|
]]
|
||||||
[(struct local-remark (contents))
|
[(struct local-remark (contents))
|
||||||
(R [#:reductions (list (walk/talk 'remark contents))])]
|
(R [#:reductions (list (walk/talk 'remark contents))])]
|
||||||
|
[(struct local-mess (events))
|
||||||
|
;; FIXME: While it is not generally possible to parse tokens as one or more
|
||||||
|
;; interrupted derivations (possibly interleaved with successful derivs),
|
||||||
|
;; it should be possible to recover *some* information and display it.
|
||||||
|
(R [#:reductions
|
||||||
|
(let ([texts
|
||||||
|
(list (~a "Some expansion history has been lost due to a jump "
|
||||||
|
"within expansion.")
|
||||||
|
(~a "For example, a macro may have caught an "
|
||||||
|
"exception coming from within a call to `local-expand'."))])
|
||||||
|
(list (walk/talk 'remark texts)))])]
|
||||||
[#f
|
[#f
|
||||||
(R)]))
|
(R)]))
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#lang racket/base
|
#lang racket/base
|
||||||
(require racket/promise
|
(require racket/promise
|
||||||
|
racket/list
|
||||||
syntax/modcode
|
syntax/modcode
|
||||||
syntax/modresolve
|
syntax/modresolve
|
||||||
parser-tools/lex
|
parser-tools/lex
|
||||||
|
@ -76,20 +77,58 @@
|
||||||
;; expand/events : stx (stx -> stx) -> stx/exn (list-of event)
|
;; expand/events : stx (stx -> stx) -> stx/exn (list-of event)
|
||||||
(define (expand/events sexpr expander)
|
(define (expand/events sexpr expander)
|
||||||
(define events null)
|
(define events null)
|
||||||
|
;; Problem: jumps within expansion (eg, macro catches error thrown from within
|
||||||
|
;; call to 'local-expand') can result in ill-formed event stream.
|
||||||
|
;; In general, not possible to detect jump endpoints, but we can at least isolate
|
||||||
|
;; the bad parts by watching for mismatched bracketing events
|
||||||
|
;; (eg, macro-{pre,post}-transform).
|
||||||
|
(define counter 0) ;; = (length events)
|
||||||
|
(define macro-stack null) ;; (listof (cons (U stx 'local-bind) nat))
|
||||||
(define (add! x y)
|
(define (add! x y)
|
||||||
|
(set! counter (add1 counter))
|
||||||
(set! events (cons (cons (signal->symbol x) y) events)))
|
(set! events (cons (cons (signal->symbol x) y) events)))
|
||||||
(define add!/check
|
(define add!/check
|
||||||
(let ([limit (trace-macro-limit)]
|
(let ([limit (trace-macro-limit)]
|
||||||
[handler (trace-limit-handler)]
|
[handler (trace-limit-handler)]
|
||||||
[counter 0]
|
[limit-counter 0]
|
||||||
[last-local-value-id #f])
|
[last-local-value-id #f])
|
||||||
(lambda (x y)
|
(lambda (x y)
|
||||||
(add! x y)
|
(add! x y)
|
||||||
(case x
|
(case x
|
||||||
((8) ;; enter-macro
|
((8) ;; enter-macro
|
||||||
(set! counter (add1 counter))
|
(set! limit-counter (add1 limit-counter))
|
||||||
(when (>= counter limit)
|
(when (>= limit-counter limit)
|
||||||
(set! limit (handler counter))))
|
(set! limit (handler limit-counter))))
|
||||||
|
((21) ;; macro-pre-transform
|
||||||
|
(let ([rec (cons y counter)])
|
||||||
|
(set! macro-stack (cons rec macro-stack))))
|
||||||
|
((22) ;; macro-post-transform
|
||||||
|
(cond [(and (pair? macro-stack)
|
||||||
|
(eq? (car (car macro-stack)) (cdr y)))
|
||||||
|
(set! macro-stack (cdr macro-stack))]
|
||||||
|
[else ;; Jumped!
|
||||||
|
(let loop ([ms macro-stack])
|
||||||
|
(let ([top (car ms)])
|
||||||
|
(cond [(eq? (car top) (cdr y))
|
||||||
|
(let* ([reset-to (cdr top)]
|
||||||
|
[len (- counter reset-to 1)]
|
||||||
|
[pfx (take (cdr events) len)]
|
||||||
|
[sfx (drop (cdr events) len)])
|
||||||
|
(set! macro-stack (cdr ms))
|
||||||
|
(set! events sfx)
|
||||||
|
(set! counter (cdr top))
|
||||||
|
(add! 'local-mess (reverse pfx))
|
||||||
|
(add! 'macro-post-transform y))]
|
||||||
|
[else (loop (cdr ms))])))]))
|
||||||
|
((143) ;; local-bind
|
||||||
|
(let ([rec (cons 'local-bind counter)])
|
||||||
|
(set! macro-stack (cons rec macro-stack))))
|
||||||
|
((160) ;; exit-local-bind
|
||||||
|
(let ([top (car macro-stack)])
|
||||||
|
(cond [(eq? (car top) 'local-bind)
|
||||||
|
(set! macro-stack (cdr macro-stack))]
|
||||||
|
[else ;; Jumped!
|
||||||
|
(error 'trace "internal error: cannot handle catch within bind")])))
|
||||||
((153) ;; local-value
|
((153) ;; local-value
|
||||||
(set! last-local-value-id y))
|
(set! last-local-value-id y))
|
||||||
((154) ;; local-value-result
|
((154) ;; local-value-result
|
||||||
|
@ -107,7 +146,6 @@
|
||||||
(values result
|
(values result
|
||||||
(reverse events)))))
|
(reverse events)))))
|
||||||
|
|
||||||
|
|
||||||
(require syntax/stx
|
(require syntax/stx
|
||||||
syntax/kerncase)
|
syntax/kerncase)
|
||||||
|
|
||||||
|
|
|
@ -223,4 +223,17 @@
|
||||||
(define-values (y) 2))))])
|
(define-values (y) 2))))])
|
||||||
(check-pred deriv? d)
|
(check-pred deriv? d)
|
||||||
(check-pred ok-node? d)))
|
(check-pred ok-node? d)))
|
||||||
|
|
||||||
|
;; Added 10/11/2012 based on bug from mflatt,shriram
|
||||||
|
(test-case "recover from jump"
|
||||||
|
(let ([d (trace '(module m racket/base
|
||||||
|
(require (for-syntax racket/base))
|
||||||
|
(define-syntax (convert-error stx)
|
||||||
|
(syntax-case stx ()
|
||||||
|
[(convert-error expr)
|
||||||
|
(with-handlers ([exn? (lambda (e) #'(quote error))])
|
||||||
|
(local-expand #'expr 'expression null))]))
|
||||||
|
(convert-error (lambda))))])
|
||||||
|
(check-pred deriv? d)
|
||||||
|
(check-pred ok-node? d)))
|
||||||
))
|
))
|
||||||
|
|
Loading…
Reference in New Issue
Block a user