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))