iface (make-custom-interface mod)))
       (for-each (lambda (sym)
                   (module-add! iface sym
                                (or (module-variable mod sym)
                                    (error (format
                                             #f
                                             "no binding `~A' in module ~A"
                                             sym mod))))
                   (when (hashq-ref (module-replacements mod) sym)
                     (hashq-set! (module-replacements iface) sym #t)))
                 (syntax->datum #'(identifier ...)))
       iface))
    
    ((except import-set identifier ...)
     (and-map sym? #'(identifier ...))
     (let* ((mod (resolve-r6rs-interface #'import-set))
            (iface (make-custom-interface mod)))
       (module-for-each/nonlocal (lambda (sym var)
                                   (module-add! iface sym var))
                                 mod)
       (for-each (lambda (sym)
                   (unless (module-local-variable iface sym)
                     (error (format #f "no binding `~A' in module ~A" sym mod)))
                   (module-remove! iface sym))
                 (syntax->datum #'(identifier ...)))
       iface))

    ((prefix import-set identifier)
     (sym? #'identifier)
     (let* ((mod (resolve-r6rs-interface #'import-set))
            (iface (make-custom-interface mod))
            (pre (syntax->datum #'identifier)))
       (module-for-each/nonlocal
        (lambda (sym var)
          (let ((sym* (symbol-append pre sym)))
            (module-add! iface sym* var)
            (when (hashq-ref (module-replacements mod) sym)
              (hashq-set! (module-replacements iface) sym* #t))))
        mod)
       iface))

    ((rename import-set (from to) ...)
     (and (and-map sym? #'(from ...)) (and-map sym? #'(to ...)))
     (let* ((mod (resolve-r6rs-interface #'import-set))
            (replacements (module-replacements mod))
            (iface (make-custom-interface mod)))
       (module-for-each/nonlocal
        (lambda (sym var) (module-add! iface sym var))
        mod)
       (let lp ((in (syntax->datum #'((from . to) ...))) (out '()))
         (cond
          ((null? in)
           (for-each
            (lambda (v)
              (let ((to (vector-ref v 0))
                    (replace? (vector-ref v 1))
                    (var (vector-ref v 2)))
                (when (module-local-variable iface to)
                  (error (format
                           #f
                           "duplicate binding for `~A' in module ~A"
                           to
                           mod)))
                (module-add! iface to var)
                (when replace?
                  (hashq-set! replacements to #t))))
            out)
           iface)
          (else
           (let* ((from (caar in))
                  (to (cdar in))
                  (var (module-variable mod from))
                  (replace? (hashq-ref replacements from)))
             (unless var (error
                           (format #f "no binding `~A' in module ~A" from mod)))
             (module-remove! iface from)
             (hashq-remove! replacements from)
             (lp (cdr in) (cons (vector to replace? var) out))))))))
    
    ((name name* ... (version ...))
     (module-name? #'(name name* ...))
     (resolve-r6rs-interface #'(library (name name* ... (version ...)))))

    ((name name* ...)
     (module-name? #'(name name* ...))
     (resolve-r6rs-interface #'(library (name name* ... ()))))))

(define-syntax library
  (lambda (stx)
    (define (sym? stx)
      (symbol? (syntax->datum stx)))

    (define (n? stx)
      (let ((n (syntax->datum stx)))
        (and (exact-integer? n)
             (not (negative? n)))))

    (define (colon-n? x)
      (let ((sym (syntax->datum x)))
        (and (symbol? sym)
             (let ((str (symbol->string sym)))
               (and (string-prefix? ":" str)
                    (let ((num (string->number (substring str 1))))
                      (and (exact-integer? num)
                           (not (negative? num)))))))))

    (define (srfi-name? stx)
      (syntax-case stx (srfi)
        ((srfi n rest ...)
         (and (and-map sym? #'(rest ...))
              (or (n? #'n)
                  (colon-n? #'n))))
        (_ #f)))

    (define (module-name? stx)
      (or (srfi-name? stx)
          (syntax-case stx ()
            ((name name* ...)
             (and-map sym? #'(name name* ...)))
            (_ #f))))

    (define (make-srfi-n context n)
      (datum->syntax
       context
       (string->symbol
        (string-append
         "srfi-"
         (let ((n (syntax->datum n)))
           (if (symbol? n)
               (substring (symbol->string n) 1)
               (number->string n)))))))

    (define (compute-exports ifaces specs)
      (define (re-export? sym)
        (or-map (lambda (iface) (module-variable iface sym)) ifaces))
      (define (replace? sym)
        (module-variable the-scm-module sym))
      
      (let lp ((specs specs) (e '()) (r '()) (x '()))
        (syntax-case specs (rename)
          (() (values e r x))
          (((rename (from to) ...) . rest)
           (and (and-map identifier? #'(from ...))
                (and-map identifier? #'(to ...)))
           (let lp2 ((in #'((from . to) ...)) (e e) (r r) (x x))
             (syntax-case in ()
               (() (lp #'rest e r x))
               (((from . to) . in)
                (cond
                 ((re-export? (syntax->datum #'from))
                  (lp2 #'in e (cons #'(from . to) r) x))
                 ((replace? (syntax->datum #'from))
                  (lp2 #'in e r (cons #'(from . to) x)))
                 (else
                  (lp2 #'in (cons #'(from . to) e) r x)))))))
          ((id . rest)
           (identifier? #'id)
           (let ((sym (syntax->datum #'id)))
             (cond
              ((re-export? sym)
               (lp #'rest e (cons #'id r) x))
              ((replace? sym)
               (lp #'rest e r (cons #'id x)))
              (else
               (lp #'rest (cons #'id e) r x))))))))

    (syntax-case stx (export import srfi)
      ((_ (name name* ...)
          (export espec ...)
          (import ispec ...)
          body ...)
       (module-name? #'(name name* ...))
       ;; Add () as the version.
       #'(library (name name* ... ())
           (export espec ...)
           (import ispec ...)
           body ...))

      ((_ (srfi n rest ... (version ...))
          (export espec ...)
          (import ispec ...)
          body ...)
       (srfi-name? #'(srfi n rest ...))
       (let ((srfi-n (make-srfi-n #'srfi #'n)))
         #`(library (srfi #,srfi-n rest ... (version ...))
             (export espec ...)
             (import ispec ...)
             body ...)))

      ((_ (name name* ... (version ...))
          (export espec ...)
          (import ispec ...)
	  body ...)
       (module-name? #'(name name* ...))
       (call-with-values
           (lambda ()
             (compute-exports 
              (map (lambda (im)
                     (syntax-case im (for)
                       ((for import-set import-level ...)
                        (resolve-r6rs-interface #'import-set))
                       (import-set (resolve-r6rs-interface #'import-set))))
                   #'(ispec ...))
              #'(espec ...)))
         (lambda (exports re-exports replacements)
           (with-syntax (((e ...) exports)
                         ((r ...) re-exports)
                         ((x ...) replacements))
             ;; It would be nice to push the module that was current before the
             ;; definition, and pop it after the library definition, but I
             ;; actually can't see a way to do that. Helper procedures perhaps,
             ;; around a fluid that is rebound in save-module-excursion? Patches
             ;; welcome!
             #'(begin
                 (define-module (name name* ...)
                   #:pure
                   #:version (version ...))
                 (import ispec)
                 ...
                 (export e ...)
                 (re-export r ...)
                 (export! x ...)
                 (@@ @@ (name name* ...) body)
                 ...))))))))
    
(define-syntax import
  (lambda (stx)
    (define (strip-for import-set)
      (syntax-case import-set (for)
        ((for import-set import-level ...)
         #'import-set)
        (import-set
         #'import-set)))
    (syntax-case stx ()
      ((_ import-set ...)
       (with-syntax (((library-reference ...) (map strip-for #'(import-set ...))))
         #'(eval-when (expand load eval)
             (let ((iface (resolve-r6rs-interface 'library-reference)))
               (call-with-deferred-observers
                 (lambda ()
                   (module-use-interfaces! (current-module) (list iface)))))
             ...
             (if #f #f)))))))
