Another idea occured to me: What if the implementation of (srfi 155) attaches the dynamic extent prior to the evaluation of "with-continuation-mark" ....
That would be (promise-extent promise), right?
...
(call/cc
(lambda (c)
(make-promise
(with-dynamic-extent
(promise-extent promise) <----!!!
(lambda ()
;; the dynamic extent here is the one we just
;; installed above.
(with-continuation-mark key
(vector c forcing-extent (promise-extent promise))
((promise-value promise))))))))))
...
to the continuation mark added by this evaluation. Then the code called by with-continuation-mark can retrieve the dynamic extent and resurrect it, thus effectively deleting the just added continuation mark.
So, then delay gets re-written:
(define-syntax delay
(syntax-rules ()
((_ expr)
(call-with-current-dynamic-extent
(lambda (extent)
(%make-promise
#f
(lambda ()
(call-with-immediate-continuation-mark
key
(lambda (m)
(with-dynamic-extent
(vector-ref m 2)
(lambda () expr)))))
extent))))))
Perhaps I misunderstand your suggestion -- but doesn't this just kill the whole tail-call-detection-mark feature? If "expr" either immediately or eventually leads to a call to force in tail context, we can't detect it and unwind back to the encompassing force call.
Also, this approach does nothing about parameterizations in client code that get captured by delay.
I implemented this faithfully, and as I expected, all the bounded-space tests fail - and to be certain, I logged the maximum "stack depth" (length of my continuation-chains), and confirmed size of the continuations was growing unbounded.
but perhaps I misinterpreted your idea...