schemetoc-record.scm 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. ; -*- Mode: Scheme; Syntax: Scheme; Package: Scheme; -*-
  2. ; Part of Scheme 48 1.9. See file COPYING for notices and license.
  3. ; Authors: Richard Kelsey, Jonathan Rees
  4. ; This is file schemetoc-record.scm.
  5. ; Synchronize any changes with the other *record.scm files.
  6. ;;;; Records
  7. (define (make-record-type type-id field-names)
  8. (define unique (lambda () the-descriptor))
  9. (define size (+ (length field-names) 1))
  10. (define (constructor . names-option)
  11. (let* ((names (if (null? names-option)
  12. field-names
  13. (car names-option)))
  14. (foo (cons unique
  15. (map (lambda (name) 'uninitialized) field-names)))
  16. (number-of-inits (length names))
  17. (indexes (map field-index names)))
  18. (lambda field-values
  19. (if (= (length field-values) number-of-inits)
  20. (let ((record (list->%record foo)))
  21. (for-each (lambda (index value)
  22. (%record-set! record index value))
  23. indexes
  24. field-values)
  25. (%record-methods-set! record usual-record-methods)
  26. record)
  27. (error "wrong number of arguments to record constructor"
  28. field-values type-id names)))))
  29. (define (predicate obj)
  30. (and (%record? obj)
  31. (= (%record-length obj) size)
  32. (eq? (%record-ref obj 0) unique)))
  33. (define (accessor name)
  34. (let ((i (field-index name)))
  35. (lambda (record)
  36. (if (predicate record) ;Faster: (eq? (%record-ref record 0) unique)
  37. (%record-ref record i)
  38. (error "invalid argument to record accessor"
  39. record type-id name)))))
  40. (define (modifier name)
  41. (let ((i (field-index name)))
  42. (lambda (record new-value)
  43. (if (predicate record) ;Faster: (eq? (%record-ref record 0) unique)
  44. (%record-set! record i new-value)
  45. (error "invalid argument to record modifier"
  46. record type-id name)))))
  47. (define (field-index name)
  48. (let loop ((l field-names) (i 1))
  49. (if (null? l)
  50. (error "bad field name" name)
  51. (if (eq? name (car l))
  52. i
  53. (loop (cdr l) (+ i 1))))))
  54. (define (discloser r) (list type-id))
  55. (define the-descriptor
  56. (lambda (request)
  57. (case request
  58. ((constructor) constructor)
  59. ((predicate) predicate)
  60. ((accessor) accessor)
  61. ((modifier) modifier)
  62. ((identification) type-id)
  63. ((field-names) field-names)
  64. ((discloser) discloser)
  65. ((set-discloser!) (lambda (d) (set! discloser d))))))
  66. the-descriptor)
  67. (define (record-type x)
  68. (if (%record? x)
  69. (let ((probe (%record-ref x 0)))
  70. (if (procedure? probe)
  71. (probe)
  72. #f))
  73. #f))
  74. (define (record-type-identification r-t)
  75. (r-t 'identification))
  76. (define (record-type-field-names r-t)
  77. (r-t 'field-names))
  78. (define (record-constructor r-t . names-option)
  79. (apply (r-t 'constructor) names-option))
  80. (define (record-predicate r-t)
  81. (r-t 'predicate))
  82. (define (record-accessor r-t field-name)
  83. ((r-t 'accessor) field-name))
  84. (define (record-modifier r-t field-name)
  85. ((r-t 'modifier) field-name))
  86. (define (define-record-discloser r-t proc)
  87. ((r-t 'set-discloser!) proc))
  88. (define (disclose-record r)
  89. (((record-type r) 'discloser) r))
  90. (define usual-record-methods
  91. (list (cons '%to-write
  92. (lambda (r port indent levels length seen)
  93. (write-char #\# port)
  94. (write-char %record-prefix-char port)
  95. (list (disclose-record r))))))
  96. (set! %record-prefix-char #\~)