n))))))

         (define (predicate rtd type-name fields exp)
           (accessors
            rtd type-name fields 0
            #`(begin
                #,exp
                (define (#,(make-id rtd type-name '?) obj)
                  (and (struct? obj) (eq? (struct-vtable obj) #,rtd))))))

         (define (field-list fields)
           (syntax-case fields ()
             (() '())
             (((f . opts) . rest) (identifier? #'f)
              (cons #'f (field-list #'rest)))
             ((f . rest) (identifier? #'f)
              (cons #'f (field-list #'rest)))))

         (define (constructor rtd type-name fields exp)
           (let* ((ctor (make-id rtd type-name '-constructor))
                  (args (field-list fields))
                  (n (length fields))
                  (slots (iota n)))
             (predicate rtd type-name fields
                        #`(begin #,exp
                                 (define #,ctor
                                   (let ((rtd #,rtd))
                                     (lambda #,args
                                       (let ((s (allocate-struct rtd #,n)))
                                         #,@(map
                                             (lambda (arg slot)
                                               #`(struct-set! s #,slot #,arg))
                                             args slots)
                                         s))))
                                 (struct-set! #,rtd (+ vtable-offset-user 2)
                                              #,ctor)))))

         (define (type type-name printer fields)
           (define (make-layout)
             (let lp ((fields fields) (slots '()))
               (syntax-case fields ()
                 (() (datum->syntax #'here
                                    (make-struct-layout
                                     (apply string-append slots))))
                 ((_ . rest) (lp #'rest (cons "pw" slots))))))

           (let ((rtd (make-id type-name type-name '-type)))
             (constructor rtd type-name fields
                          #`(begin
                              (define #,rtd
                                (make-struct/no-tail
                                 record-type-vtable
                                 '#,(make-layout)
                                 #,printer
                                 '#,type-name
                                 '#,(field-list fields)))
                              (set-struct-vtable-name! #,rtd '#,type-name)))))

         (syntax-case x ()
           ((_ type-name printer (field ...))
            (type #'type-name #'printer #'(field ...)))))))

  ;; module-type
  ;;
  ;; A module is characterized by an obarray in which local symbols
  ;; are interned, a list of modules, "uses", from which non-local
  ;; bindings can be inherited, and an optional lazy-binder which
  ;; is a (CLOSURE module symbol) which, as a last resort, can provide
  ;; bindings that would otherwise not be found locally in the module.
  ;;
  ;; NOTE: If you change the set of fields or their order, you also need to
  ;; change the constants in libguile/modules.h.
  ;;
  ;; NOTE: The getter `module-transformer' is defined libguile/modules.c.
  ;; NOTE: The getter `module-name' is defined later, due to boot reasons.
  ;; NOTE: The getter `module-public-interface' is used in libguile/modules.c.
  ;;
  (define-record-type module
    (lambda (obj port) (%print-module obj port))
    (obarray
     uses
     binder
     eval-closure
     (transformer #:no-getter)
     (name #:no-getter)
     kind
     duplicates-handlers
     (import-obarray #:no-setter)
     observers
     (weak-observers #:no-setter)
     version
     submodules
     submodule-binder
     public-interface
     filename
     next-unique-id)))


;; make-module &opt size uses binder
;;
(define* (make-module #:optional (size 31) (uses '()) (binder #f))
  "Create a new module, perhaps with a particular size of obarray,
initial uses list, or binding procedure."
  (if (not (integer? size))
      (error "Illegal size to make-module." size))
  (if (not (and (list? uses)
                (and-map module? uses)))
      (error "Incorrect use list." uses))
  (if (and binder (not (procedure? binder)))
      (error
       "Lazy-binder expected to be a procedure or #f." binder))

  (module-constructor (make-hash-table size)
                      uses binder #f macroexpand
                      #f #f #f
                      (make-hash-table)
                      '()
                      (make-weak-key-hash-table 31) #f
                      (make-hash-table 7) #f #f #f 0))


