;;; - $prompt continues to the body of the prompt, having pushed on a
;;; prompt whose handler will continue at its "handler"
;;; continuation. The continuation of the prompt is responsible for
-;;; popping the prompt.
+;;; popping the prompt. A $prompt also records the continuation
+;;; that pops the prompt, to make various static analyses easier.
;;;
;;; In summary:
;;;
(define-cps-type $call proc args)
(define-cps-type $primcall name args)
(define-cps-type $values args)
-(define-cps-type $prompt escape? tag handler)
+(define-cps-type $prompt escape? tag handler pop)
(define-syntax let-gensyms
(syntax-rules ()
((_ ($primcall name args)) (make-$primcall name args))
((_ ($values (arg ...))) (make-$values (list arg ...)))
((_ ($values args)) (make-$values args))
- ((_ ($prompt escape? tag handler)) (make-$prompt escape? tag handler))))
+ ((_ ($prompt escape? tag handler pop))
+ (make-$prompt escape? tag handler pop))))
(define-syntax build-cps-term
(syntax-rules (unquote $letk $letk* $letconst $letrec $continue)
(build-cps-exp ($primcall name arg)))
(('values arg ...)
(build-cps-exp ($values arg)))
- (('prompt escape? tag handler)
- (build-cps-exp ($prompt escape? tag handler)))
+ (('prompt escape? tag handler pop)
+ (build-cps-exp ($prompt escape? tag handler pop)))
(_
(error "unexpected cps" exp))))
`(primcall ,name ,@args))
(($ $values args)
`(values ,@args))
- (($ $prompt escape? tag handler)
- `(prompt ,escape? ,tag ,handler))
+ (($ $prompt escape? tag handler pop)
+ `(prompt ,escape? ,tag ,handler ,pop))
(_
(error "unexpected cps" exp))))
($continue k ($values args)))
'()))))
- (($ $continue k ($ $prompt escape? tag handler))
+ (($ $continue k ($ $prompt escape? tag handler pop))
(convert-free-var
tag self bound
(lambda (tag)
(values (build-cps-term
- ($continue k ($prompt escape? tag handler)))
+ ($continue k ($prompt escape? tag handler pop)))
'()))))
(_ (error "what" exp))))
(($ $primcall name args)
(error "unhandled primcall in seq context" name))
(($ $values ()) #f)
- (($ $prompt escape? tag handler)
+ (($ $prompt escape? tag handler pop)
(match (lookup-cont handler cont-table)
(($ $ktrunc ($ $arity req () rest () #f) khandler-body)
(let ((receive-args (gensym "handler"))
(($ $values args)
(for-each use! args))
- (($ $prompt escape? tag handler)
+ (($ $prompt escape? tag handler pop)
(use! tag)
- (use-k! handler))
+ (use-k! handler)
+ ;; Any continuation in the prompt body could cause an abort to
+ ;; the handler, so in theory we could register the handler as
+ ;; a successor of any block in the prompt body. That would be
+ ;; inefficient, though, besides being a hack. Instead we take
+ ;; advantage of the fact that pop continuation post-dominates
+ ;; the prompt body, so we add a link from there to the
+ ;; handler. This creates a primcall node with multiple
+ ;; successors, which is not quite correct, but it does reflect
+ ;; control flow. It is necessary to ensure that the live
+ ;; variables in the handler are seen as live in the body.
+ (link-blocks! pop handler))
(($ $fun)
(when global?
live-slots live-slots*
(compute-dst-slots))))
- (($ $prompt escape? tag handler)
+ (($ $prompt escape? tag handler pop)
(match (lookup-cont handler (dfg-cont-table dfg))
(($ $ktrunc arity kargs)
(let* ((live-slots (allocate-prompt-handler! label live-slots))
(for-each (cut check-var <> v-env) arg))
(($ $values ((? symbol? arg) ...))
(for-each (cut check-var <> v-env) arg))
- (($ $prompt escape? tag handler)
+ (($ $prompt escape? tag handler pop)
(unless (boolean? escape?) (error "escape? should be boolean" escape?))
(check-var tag v-env)
- (check-var handler k-env))
+ (check-var handler k-env)
+ (check-var pop k-env))
(_
(error "unexpected expression" exp))))
($letk ((kbody (tree-il-src body)
($kargs () ()
,(convert body krest subst))))
- ($continue kbody ($prompt #t tag khargs))))
+ ($continue kbody ($prompt #t tag khargs kpop))))
(convert-arg body
(lambda (thunk)
(build-cps-term
($primcall 'call-thunk/no-inline
(thunk))))))
($continue kbody
- ($prompt #f tag khargs))))))))))))))
+ ($prompt #f tag khargs kpop))))))))))))))
;; Eta-convert prompts without inline handlers.
(($ <prompt> src escape-only? tag body handler)