Syntax highlighter

2026-03-06

Composable continuation (3)

Dynamic winder is always a headache. It doesn't matter in which situation. For the composable continuation, it's not an exception at all.

For example the below script

(define saved #f)
(define count 0)
(call/prompt
 (lambda ()
   (dynamic-wind
       (lambda () (display "pre1\n"))
       (lambda ()
         (call/prompt
          (lambda ()
            (dynamic-wind
                (lambda () (display "pre2\n"))
                (lambda () #t)
                (lambda ()
                  (call/comp (lambda (k) (set! saved k) ))
                  (display "post2\n"))))))
       (lambda () (display "post1\n")))
   (unless (= count 1)
     (set! count (+ count 1))
     (saved 'again))))

This results like this

pre1
pre2
post2
post1
post2

And if I swap call/comp with call/cc then it'd print this

pre1
pre2
post2
post1
pre1
post2
post1

The second post2 is wrapped with pre1 and post1 which are the winders of the outer dynamic-wind.

If I see how it's written, it makes sense. The captured continuation is in the second prompt, so it shouldn't invoke the outer prompt winders. It makes sense, that doesn't mean it's easy to achieve.

Prompt as winder boundary

The winders are basically chains managed on VM. At the deepest location of the above example, the winder looks like this

[pre2 . post2] - [pre1 . post1] - [... system winders]
              ^^^
             prompt

The prompt is in between the first and the second winders. So, when the composable continuation is captured, then it only considers the first winder.

Though, if I replace only the first winder but without the rest of the [... system winders], then it'd cause a problem. So, it has to have some sort of filtering.

Filtering winders

One of the easiest filtering is that if the captured continuation is partial a.k.a composable, then no before thunk is needed. I'm not entirely sure if this assumption is actually correct, but it seems working. So, keep it like that...

Then the next one is that comparing the current winders and capture winders.

Captured:
[pre2 . post2] - [pre1 . post1] - [... system winders]
              ^^^
             prompt

Current:
[... system winders]

After exiting from the both dynamic-winds, then the current winders contains only the [... system winders] for the above example. So, it should take up until the prompt, then append the current winder.

Again, I'm not sure if the current implementation is correct, but it's working. So, I'm fine for now until I find a bug...