record.scm 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. ; Part of Scheme 48 1.9. See file COPYING for notices and license.
  2. ; Authors: Richard Kelsey
  3. ; Records that translate into C structs.
  4. ; Representation of record types.
  5. (define-record-type record-type :record-type
  6. (really-make-record-type name)
  7. record-type?
  8. (name record-type-name)
  9. ; FIELDS and CONSTRUCTOR-ARGS are filled in later because of circularity
  10. (fields record-type-fields set-record-type-fields!)
  11. (constructor-args ; fields passed to the constructor
  12. record-type-constructor-args set-record-type-constructor-args!))
  13. (define-record-discloser :record-type
  14. (lambda (rtype)
  15. (list 'record-type (record-type-name rtype))))
  16. ; Fields of record types.
  17. (define-record-type record-field :record-field
  18. (make-record-field record-type name type)
  19. record-field?
  20. (record-type record-field-record-type)
  21. (name record-field-name)
  22. (type record-field-type))
  23. ; Global table of record types. Since we compile to a single C file the
  24. ; record types used within a single computation must have distinct names.
  25. ; (This should really be a fluid.)
  26. (define *record-type-table* (make-symbol-table))
  27. (define (reset-record-data!)
  28. (set! *record-type-table* (make-symbol-table)))
  29. (define (get-record-type id)
  30. (cond ((table-ref *record-type-table* id)
  31. => identity)
  32. (else
  33. (error "no record type ~S" id))))
  34. (define (lookup-record-type id)
  35. (table-ref *record-type-table* id))
  36. (define (all-record-types)
  37. (table->entry-list *record-type-table*))
  38. ; Construction a record type. This gets the name, the list of fields whose
  39. ; initial values are passed to the constructor, and the field specifications.
  40. ; Each field specification consists of a name and a type.
  41. (define (make-record-type id constructor-args specs)
  42. (let ((rt (really-make-record-type id)))
  43. (if (table-ref *record-type-table* id)
  44. (user-error "multiple definitions of record type ~S" id))
  45. (table-set! *record-type-table* id rt)
  46. (set-record-type-fields! rt (map (lambda (spec)
  47. (make-record-field
  48. rt
  49. (car spec)
  50. (expand-type-spec (cadr spec))))
  51. specs))
  52. (set-record-type-constructor-args! rt
  53. (map (lambda (name)
  54. (get-record-type-field id name))
  55. constructor-args))
  56. rt))
  57. ; Return the field record for FIELD-ID in record-type TYPE-ID.
  58. (define (get-record-type-field type-id field-id)
  59. (let ((rtype (get-record-type type-id)))
  60. (cond ((any (lambda (field)
  61. (eq? field-id (record-field-name field)))
  62. (record-type-fields rtype))
  63. => identity)
  64. (else
  65. (user-error "~S is not a field of ~S" field-id rtype)))))
  66. ; The macro expander for DEFINE-RECORD-TYPE.
  67. ;
  68. ; (define-record-type <id> <type-id>
  69. ; (<constructor> . <field-names>)
  70. ; (<field-name> <type> <accessor-name> [<modifier-name>]) ...)
  71. ;
  72. ; The <type-id> is used only by Pre-Scheme-in-Scheme.
  73. (define (expand-define-record-type exp r c)
  74. (let ((id (cadr exp))
  75. (maker (cadddr exp))
  76. (fields (cddddr exp)))
  77. (let ((rt (make-record-type id (cdr maker) fields)))
  78. `(,(r 'begin)
  79. (,(r 'define) ,maker
  80. (,(r 'let) ((,(r id) (,(r 'make-record) ',id)))
  81. (,(r 'if) (,(r 'not) (,(r 'null-pointer?) ,(r id)))
  82. (,(r 'begin)
  83. . ,(map (lambda (name)
  84. `(,(r 'record-set!) ,(r id) ,name ',id ',name))
  85. (cdr maker))))
  86. ,(r id)))
  87. ,@(map (lambda (field)
  88. `(,(r 'define) (,(caddr field) ,(r id))
  89. (,(r 'record-ref) ,(r id) ',id ',(car field))))
  90. fields)
  91. ,@(map (lambda (field)
  92. `(,(r 'define) (,(cadddr field) ,(r id) ,(r 'x))
  93. (,(r 'record-set!)
  94. ,(r id) ,(r 'x)',id ',(car field))))
  95. (filter (lambda (spec)
  96. (not (null? (cdddr spec))))
  97. fields))))))
  98. ; primitives
  99. ; (make-record 'type . args)
  100. ; (record-ref thing 'type 'field)
  101. ; (record-set! thing value 'type 'field)
  102. ;
  103. ; C record creator
  104. ; global list of these things