dynamic import added by konlovett on Sun Feb 13 02:42:28 2022

;;;; dynamic-import.scm  -*- Scheme -*-
;;;; Kon Lovett, Feb '22

;inspired by Feb 12 '22 #chicken irc - http-client & openssl eggs

(module dynamic-import

(;export
  (dynamic-import dynamic-import-body))

(import scheme)
(import (chicken base))
(import (chicken syntax))
(import (chicken condition))
(import (only (srfi 1) make-list))

;FIXME more elegant defaults specification/handling

(define-syntax dynamic-import
  (syntax-rules ()
    ;multiple identifier
    ;w/o default
    ((dynamic-import (?id0 ...) (?md0 ...))
      (define-values (?id0 ...)
                     (dynamic-import-body '(?id0 ...) '(?md0 ...))) )
    ;w/ default
    ((dynamic-import (?id0 ...) (?md0 ...) ?df)
      (define-values (?id0 ...)
                     (dynamic-import-body '(?id0 ...) '(?md0 ...) ?df)) )
    ;single identifier
    ;w/o default
    ((dynamic-import ?id (?md0 ...))
      (dynamic-import (?id) (?md0 ...)) )
    ;w/o default
    ((dynamic-import ?id ?md)
      (dynamic-import (?id) (?md)) )
    ;w/ default
    ((dynamic-import ?id (?md0 ...) ?df)
      (dynamic-import (?id) (?md0 ...) ?df) )
    ;w/ default
    ((dynamic-import ?id ?md ?df)
      (dynamic-import (?id) (?md) ?df) ) ) )

(define (dynamic-import-body ids mds #!optional (df (void)))
  (define (dfs)
    (cond ((list? df) df)
          ((procedure? df) (df ids))
          (else (make-list (length ids) df))))
  (let ((idvals `(values ,@ids)))
    (let loop ((mds mds))
      (if (null? mds)
          (error 'dynamic-import-body "empty module list" ids mds df)
          (let ((expr `(let () (import ,(car mds)) ,idvals)))
            (if (null? (cdr mds))
                ;then last module, any default?
                (if (eq? df (void))
                    ;then system-error on failure
                    (eval expr)
                    ;else defaults on failure
                    (handle-exceptions
                     exn (apply values (dfs))
                     (eval expr)) )
                ;else try next module on failure
                (handle-exceptions
                 exn (loop (cdr mds))
                 (eval expr)) ) ) ) ) ) )

) ;module dynamic-import