summaryrefslogtreecommitdiff
path: root/module/language/tree-il/peval.scm
diff options
context:
space:
mode:
authorAndy Wingo <wingo@pobox.com>2013-07-06 20:06:02 +0900
committerAndy Wingo <wingo@pobox.com>2013-07-06 20:27:21 +0900
commit178a40928ab5221f6ce57c5af1067abe30a342b3 (patch)
tree6d8b62eff02e8e4fc383cb2e76b0a326d88ad44d /module/language/tree-il/peval.scm
parent98eaef1b50db626c672646da58645c62407d0c1a (diff)
downloadguile-178a40928ab5221f6ce57c5af1067abe30a342b3.tar.gz
<prompt> body and handler are lambdas; add escape-only? field
* module/language/tree-il.scm (<prompt>): Change to have the body and handler be lambdas, and add an "escape-only?" field. This will make generic prompts work better in CPS or ANF with the RTL VM, as it doesn't make sense in that context to capture only part of a frame. Escape-only prompts can still be fully inlined. (parse-tree-il, unparse-tree-il): Add escape-only? to the serialization. (make-tree-il-folder, pre-post-order): Deal with escape-only?. * module/language/tree-il/analyze.scm (analyze-lexicals): Handle escape-only?, and the new expectations for the body and handler. * module/language/tree-il/canonicalize.scm (canonicalize): Ensure that the body of an escape-only continuation is a thunk, and that the handler is always a lambda. * module/language/tree-il/debug.scm (verify-tree-il): Assert that escape-only? is a boolean. * module/language/tree-il/cse.scm (cse): * module/language/tree-il/effects.scm (make-effects-analyzer): * module/language/tree-il/peval.scm (peval): * module/language/tree-il/primitives.scm (*primitive-expand-table*): * test-suite/tests/peval.test ("partial evaluation"): * module/language/tree-il/compile-glil.scm (flatten-lambda-case): Adapt to <prompt> change.
Diffstat (limited to 'module/language/tree-il/peval.scm')
-rw-r--r--module/language/tree-il/peval.scm59
1 files changed, 42 insertions, 17 deletions
diff --git a/module/language/tree-il/peval.scm b/module/language/tree-il/peval.scm
index 5b9852b01..af00e9904 100644
--- a/module/language/tree-il/peval.scm
+++ b/module/language/tree-il/peval.scm
@@ -1514,7 +1514,7 @@ top-level bindings from ENV and return the resulting expression."
(seq-head head)
head)
tail))))
- (($ <prompt> src tag body handler)
+ (($ <prompt> src escape-only? tag body handler)
(define (make-prompt-tag? x)
(match x
(($ <primcall> _ 'make-prompt-tag (or () ((? constant-expression?))))
@@ -1522,7 +1522,7 @@ top-level bindings from ENV and return the resulting expression."
(_ #f)))
(let ((tag (for-value tag))
- (body (for-tail body)))
+ (body (for-value body)))
(cond
((find-definition tag 1)
(lambda (val op)
@@ -1532,31 +1532,56 @@ top-level bindings from ENV and return the resulting expression."
;; for this <prompt>, so we can elide the <prompt>
;; entirely.
(unrecord-operand-uses op 1)
- body))
+ (for-tail (make-call src body '()))))
((find-definition tag 2)
(lambda (val op)
(and (make-prompt-tag? val)
- (abort? body)
- (tree-il=? (abort-tag body) tag)))
+ (match body
+ (($ <lambda> _ _
+ ($ <lambda-case> _ () #f #f #f () ()
+ ($ <abort> _ (? (cut tree-il=? <> tag)))))
+ #t)
+ (else #f))))
=> (lambda (val op)
;; (let ((t (make-prompt-tag)))
;; (call-with-prompt t
;; (lambda () (abort-to-prompt t val ...))
;; (lambda (k arg ...) e ...)))
- ;; => (let-values (((k arg ...) (values values val ...)))
- ;; e ...)
+ ;; => (call-with-values (lambda () (values values val ...))
+ ;; (lambda (k arg ...) e ...))
(unrecord-operand-uses op 2)
- (for-tail
- (make-let-values
- src
- (make-primcall #f 'apply
- `(,(make-primitive-ref #f 'values)
- ,(make-primitive-ref #f 'values)
- ,@(abort-args body)
- ,(abort-tail body)))
- (for-value handler)))))
+ (match body
+ (($ <lambda> _ _
+ ($ <lambda-case> _ () #f #f #f () ()
+ ($ <abort> _ _ args tail)))
+ (for-tail
+ (make-primcall
+ src 'call-with-values
+ (list (make-lambda
+ #f '()
+ (make-lambda-case
+ #f '() #f #f #f '() '()
+ (make-primcall #f 'apply
+ `(,(make-primitive-ref #f 'values)
+ ,(make-primitive-ref #f 'values)
+ ,@args
+ ,tail))
+ #f))
+ handler)))))))
(else
- (make-prompt src tag body (for-value handler))))))
+ (let ((handler (for-value handler)))
+ (define (escape-only-handler? handler)
+ (match handler
+ (($ <lambda> _ _
+ ($ <lambda-case> _ (_ . _) _ _ _ _ (k . _) body #f))
+ (not (tree-il-any
+ (match-lambda
+ (($ <lexical-ref> _ _ (? (cut eq? <> k))) #t)
+ (_ #f))
+ body)))
+ (else #f)))
+ (make-prompt src (or escape-only? (escape-only-handler? handler))
+ tag body (for-value handler)))))))
(($ <abort> src tag args tail)
(make-abort src (for-value tag) (map for-value args)
(for-value tail))))))