(library (rnrs records syntactic (6))
(export define-record-type
record-type-descriptor
record-constructor-descriptor
fields mutable immutable parent protocol
sealed opaque nongenerative)
(import (for (rnrs base) run expand)
(for (rnrs syntax-case) run expand)
(rename (rnrs records private explicit)
(define-record-type define-record-type/explicit)))
(define-syntax define-record-type
(syntax-rules ()
((define-record-type (?record-name ?constructor-name ?predicate-name)
?clause ...)
(define-record-type-1 ?record-name (?record-name ?constructor-name ?predicate-name)
()
?clause ...))
((define-record-type ?record-name
?clause ...)
(define-record-type-1 ?record-name ?record-name
()
?clause ...))))
(define-syntax define-record-type-1
(syntax-rules (fields)
((define-record-type-1 ?record-name ?record-name-spec
(?simple-clause ...)
(fields ?field-spec ...)
?clause ...)
(process-fields-clause (fields ?field-spec ...)
?record-name ?record-name-spec
(?simple-clause ...)
?clause ...))
((define-record-type-1 ?record-name ?record-name-spec
(?simple-clause ...)
?clause0
?clause ...)
(define-record-type-1 ?record-name ?record-name-spec
(?simple-clause ... ?clause0)
?clause ...))
((define-record-type-1 ?record-name ?record-name-spec
(?simple-clause ...))
(define-record-type-2 ?record-name ?record-name-spec
(?simple-clause ...)))))
(define-syntax define-record-type-2
(lambda (form)
(syntax-case form ()
((_ ?record-name (?record-name-2 ?constructor-name ?predicate-name)
(?simple-clause ...))
(syntax
(begin
(define-record-type/explicit (?record-name ?constructor-name ?predicate-name)
?simple-clause ...))))
((_ ?record-name ?record-name-2
(?simple-clause ...))
(with-syntax ((?constructor-name
(datum->syntax (syntax ?record-name)
(string->symbol
(string-append "make-"
(symbol->string
(syntax->datum
(syntax ?record-name)))))))
(?predicate-name
(datum->syntax (syntax ?record-name)
(string->symbol
(string-append (symbol->string
(syntax->datum
(syntax ?record-name)))
"?")))))
(syntax
(define-record-type-2 ?record-name (?record-name ?constructor-name ?predicate-name)
(?simple-clause ...))))))))
(define-syntax process-fields-clause
(lambda (form)
(syntax-case form (fields mutable immutable)
((_ (fields ?field-clause ...)
?record-name ?record-name-spec
(?simple-clause ...)
?clause ...)
(let ((record-name (symbol->string (syntax->datum (syntax ?record-name)))))
(with-syntax
(((?simple-field ...)
(map (lambda (clause)
(syntax-case clause (mutable immutable)
((immutable ?field-name)
(with-syntax ((?accessor-name
(datum->syntax
(syntax ?field-name)
(string->symbol
(string-append record-name "-"
(symbol->string
(syntax->datum
(syntax ?field-name))))))))
(syntax
(immutable ?field-name ?accessor-name))))
((mutable ?field-name)
(with-syntax ((?accessor-name
(datum->syntax
(syntax ?field-name)
(string->symbol
(string-append record-name "-"
(symbol->string
(syntax->datum
(syntax ?field-name)))))))
(?mutator-name
(datum->syntax
(syntax ?field-name)
(string->symbol
(string-append record-name "-"
(symbol->string
(syntax->datum
(syntax ?field-name)))
"-set!")))))
(syntax
(mutable ?field-name ?accessor-name ?mutator-name))))
(?clause
clause)))
(syntax (?field-clause ...)))))
(syntax
(define-record-type-1
?record-name ?record-name-spec
(?simple-clause ... (fields ?simple-field ...))
?clause ...)))))))))