R6RS foreign-error sketch Lassi Kortela 14 Aug 2020 12:22 UTC

Here's one using the R6RS condition system. define-condition-type is a
standard part of R6RS; Chez Scheme expands it into define-record-type.

R6RS would also let us do stuff with subtypes (the R6RS libraries spec,
page 28, has a diagram of the standard condition type hierarchy). But
R6RS doesn't have generic functions so we'd have to define
`foreign-status-ref` in a fancy way.

If we add more accessors like `foreign-status-fold` or
`foreign-status-plist`, you'll notice the abstraction business becomes
more complicated. `foreign-status-keys` would be fairly easy to add but
as soon as have an API that returns the value for more than one property
with one call, you run into problems.

(import (rnrs))

(define (plist-ref plist property default)
   (cond ((not (and (pair? plist) (pair? (cdr plist))))
          default)
         ((eq? property (car plist))
          (cadr plist))
         (else
          (plist-ref (cddr plist) property default))))

(define-condition-type &foreign &condition
   %make-foreign-status
   foreign-status?
   (plist %foreign-status-plist))

(define (make-foreign-status . plist)
   (%make-foreign-status plist))

(define (foreign-status-ref st property)
   (plist-ref  (%foreign-status-plist st) property #f))

;;

(define-syntax pp
   (syntax-rules ()
     ((_ x) (begin (write 'x) (display " => ") (write x) (newline)))))

(let ((st (make-foreign-status 'set 'errno 'code 4)))
   (pp (foreign-status-ref st 'set))
   (pp (foreign-status-ref st 'code))
   (guard (err (foreign-status? (pp (foreign-status-ref st 'code))))
     (raise st)))