#lang scheme/base (require (for-syntax scheme/base scheme/struct-info)) (provide make) ;; (make struct-name field-expr ...) ;; Checks that correct number of fields given. (define-syntax (make stx) (define (bad-struct-name x) (raise-syntax-error #f "expected struct name" stx x)) (define (get-struct-info id) (unless (identifier? id) (bad-struct-name id)) (let ([value (syntax-local-value id (lambda () #f))]) (unless (struct-info? value) (bad-struct-name id)) (extract-struct-info value))) (syntax-case stx () [(make S expr ...) (let () (define info (get-struct-info #'S)) (define constructor (list-ref info 1)) (define accessors (list-ref info 3)) (unless (identifier? #'constructor) (raise-syntax-error #f "constructor not available for struct" stx #'S)) (unless (andmap identifier? accessors) (raise-syntax-error #f "incomplete info for struct type" stx #'S)) (let ([num-slots (length accessors)] [num-provided (length (syntax->list #'(expr ...)))]) (unless (= num-provided num-slots) (raise-syntax-error #f (format "wrong number of arguments for struct ~s (expected ~s)" (syntax-e #'S) num-slots) stx))) (with-syntax ([constructor constructor]) #'(constructor expr ...)))]))