record.scm 5.1 KB

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