Permalink
Browse files

write up docs for delimcc

  • Loading branch information...
1 parent f8f6c52 commit f97857db8740898a74e681e9739cd44f66bf193f @dubiousjim committed Jul 11, 2012
Showing with 91 additions and 22 deletions.
  1. +91 −22 experiments/delimcc.pure
View
@@ -1,28 +1,97 @@
/* delimcc macros
Copyright (c) 2012 by Dubiousjim <dubiousjim@gmail.com>.
- [Add explanation about licensing, or link to
- https://github.com/dubiousjim/unspoiled/blob/master/LICENSE].
-
-
-These macros use a similar rewriting technique to the one used in gfold.pure.
-Ideally we should abstract away the differences and use a single rewriting macro
-backend.
-
-reset/shift:
-
- reset (middle (shift (\k -> inside) moreshift...) moremiddle...)
-
-(where reset doesn't occur in middle, inside, moreshift or moremiddle) is transformed to:
-
- catch handle (shifted captured_middle moreshift...) with
- shifted k = inside2; // just like `inside` except head occurrences of k are replaced by (abort.k)
- captured_middle v = middle v moremiddle...;
- handle v = if v===cell then get v else throw v;
- abort v = put cell v $$ throw cell;
- end with
- cell = ref ();
- end;
+ BSD License at https://github.com/dubiousjim/unspoiled/blob/master/LICENSE
+
+
+This is an experiment at using the __macro__::walker code rewriter to implement
+delimited continuations (shift/reset and friends).
+
+It succeeds only in limited cases, for example:
+
+ Welcome to Racket v5.2.
+ > (require racket/control)
+ > (define (f choice val)
+ > (cons 'outside
+ > (reset (cons 'middle
+ > (shift k
+ > (case choice
+ > ((1) (k val))
+ > ((2) (cons 'inner (k val)))
+ > ((3) val)
+ > ((4) k)))))))
+ > (values (f 1 (list 1)) (f 2 (list 1)) (f 3 (list 1)) ((cdr (f 4 #f)) 'something))
+ '(outside middle 1)
+ '(outside inner middle 1)
+ '(outside 1)
+ '(middle . something)
+
+Compare:
+
+ Pure 0.53 (x86_64-portbld-freebsd) Copyright (c) 2008-2012 by Albert Graef
+ (Type 'help' for help, 'help copying' for license information.)
+ Loaded prelude from /usr/local/lib/pure/prelude.pure.
+
+ > using delimcc;
+ > using namespace delimcc;
+ > f choice val = outside:reset (middle:shift (\k ->
+ > case choice of 1 = k val; 2 = inner:k val; 3 = val; 4 = k; end));
+
+ > show f
+ f choice val = outside:((\k -> case choice of 1 = k val; 2 = inner:k
+ val; 3 = val; 4 = k end) k with k v = middle:v end);
+
+ > [f 1 [1], f 2 [1], f 3 [1], tail (f 4 0) something];
+ [[outside,middle,1],[outside,inner,middle,1],[outside,1],middle:something]
+
+Looks good so far. But---short of a complete CPS transform of the Pure program, which I'm
+not doing---this only works up to a point.
+
+ Welcome to Racket v5.2.
+ > (require racket/control)
+ > (reset (foldl (lambda (x a) (shift k (if (= x 6) a (begin (displayln
+ > x) (k (+ a x)))))) 0 '(1 2 3 4 5 6 7 8 9 10)))
+ 1
+ 2
+ 3
+ 4
+ 5
+ 15
+
+ Pure 0.53 (x86_64-portbld-freebsd) Copyright (c) 2008-2012 by Albert Graef
+ (Type 'help' for help, 'help copying' for license information.)
+ Loaded prelude from /usr/local/lib/pure/prelude.pure.
+
+ > using namespace delimcc;
+ > using system;
+ > foo = reset (foldl (\a x -> shift (\k ->
+ > if x==6 then a else printf "%d\n" x $$ k (a+x))) 0 (1..10));
+
+ > show foo
+ foo = (\k -> if x==6 then a else printf "%d\n" x$$k (a+x)) k with k v =
+ foldl (\a x -> v) 0 (1..10) end;
+
+You can see that won't work, because x and a are no longer bound by the
+(\a v -> ...).
+
+ > foo;
+ <stdin>, line 6: unhandled exception 'failed_cond' while evaluating
+ 'foo'
+
+We need to leave the shift-body in place so that its variables still get
+bound properly. Yet we want sometimes to escape from the shift-body to the
+reset boundary, skipping over the "captured" part unless the user specifically
+invokes it. This is easy enough to do with Pure exceptions if it's
+all we want. But then if we do that, Pure throws away our stack. And
+the specifications for delimited continuations include that k should be bound
+to the computations that are no longer recoverable once that stack has
+been discarded. If we handed k to external code that wanted to invoke it later,
+we couldn't make it work.
+
+So delimited continuations in full generality look not yet to be possible in
+Pure, without additional compiler suppprt, or doing a full CPS transform of the
+program. (Or minimally, that segment of the program that might invoke a
+captured continuation.)
*/

0 comments on commit f97857d

Please sign in to comment.