mit-scheme-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [MIT-Scheme-devel] R7RS and values.


From: Taylor R Campbell
Subject: Re: [MIT-Scheme-devel] R7RS and values.
Date: Fri, 14 Oct 2016 20:10:38 +0000

   Date: Fri, 14 Oct 2016 12:25:12 -0700
   From: Matt Birkholz <address@hidden>

   Did I hear that VALUES might not be terribly expensive nor difficult
   to implement?  Taylor suggested a simple trap is all we need(?).
   I have tried to work out the details here.

What I experimented with several years ago was to add not another
trap, but another return code.  (It will require additional work in
the compiler, since the four {interpreter, compiler}^2 paths from
callee to caller are all slightly different.)

Generally you want to make sure that there's no additional cost to
single-value calls or single-value returns, with at most moderate cost
to matched mv calls and mv returns, and possibly high cost to
mismatched ones.  So you want to avoid changing anything about the
single-value call or return paths.

If you add a new return code for MV continuations, say RC_MV which has
an associated consumer procedure on the stack, then:

(a) Single-value returns work normally, and the `case RC_MV' in the
interpreter handles calling the consumer of CALL-WITH-VALUES with the
one return value -- which may signal an arity error.

(b) Multi-value returns check whether the return code is RC_MV or
something else, perhaps with a branch prediction hint.  If RC_MV, they
can explicitly call the CALL-WITH-VALUES consumer on the stack next to
the RC_MV return code.  If not RC_MV, they can signal an error.

This might be crudely approximated like so:

(define (values . args)
  (if (length=? 1 args)
      (car args)
      (call-with-current-continuation
       (lambda (k)
         (if (mv-continuation? k)
             (let ((k* (mv-continuation-parent k))
                   (consumer (mv-continuation-consumer k)))
               (within-continuation k*
                 (lambda ()
                   (apply consumer args))))
             (error "Values mismatch!" args))))))

(define (call-with-values producer consumer)
  (call-with-current-continuation
   (lambda (k*)
     (let ((v
            (with-stack-marker mv-continuation (cons k* consumer)
              producer)))
       (consumer v)))))

Here MV-CONTINUATION? queries for a continuation with an
MV-CONTINUATION stack marker, and MV-CONTINUATION-PARENT and
MV-CONTINUATION-CONSUMER extract the K* and CONSUMER components of it.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]