record.scm 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  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, Mike Sperber
  4. ; This is file record.scm.
  5. ;;;; Records
  6. ; This is completely vanilla Scheme code. Should work anywhere.
  7. (define (make-record-type type-id field-names)
  8. (define unique (list type-id))
  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. (number-of-inits (length names))
  15. (indexes (map field-index names)))
  16. (lambda field-values
  17. (if (= (length field-values) number-of-inits)
  18. (let ((record (make-vector size 'uninitialized)))
  19. (vector-set! record 0 unique)
  20. (for-each (lambda (index value)
  21. (vector-set! record index value))
  22. indexes
  23. field-values)
  24. record)
  25. (assertion-violation
  26. '<record-constructor> "wrong number of arguments to record constructor"
  27. field-values type-id names)))))
  28. (define (predicate obj)
  29. (and (vector? obj)
  30. (= (vector-length obj) size)
  31. (eq? (vector-ref obj 0) unique)))
  32. (define (accessor name)
  33. (let ((i (field-index name)))
  34. (lambda (record)
  35. (if (predicate record) ;Faster: (eq? (vector-ref record 0) unique)
  36. (vector-ref record i)
  37. (assertion-violation
  38. '<record-accessor>
  39. "invalid argument to record accessor"
  40. record type-id name)))))
  41. (define (modifier name)
  42. (let ((i (field-index name)))
  43. (lambda (record new-value)
  44. (if (predicate record) ;Faster: (eq? (vector-ref record 0) unique)
  45. (vector-set! record i new-value)
  46. (assertion-violation
  47. '<record-modifier>
  48. "invalid argument to record modifier"
  49. record type-id name)))))
  50. (define (field-index name)
  51. (let loop ((l field-names) (i 1))
  52. (if (null? l)
  53. (assertion-violation 'field-index "bad field name" name)
  54. (if (eq? name (car l))
  55. i
  56. (loop (cdr l) (+ i 1))))))
  57. (define the-descriptor
  58. (lambda (request)
  59. (case request
  60. ((constructor) constructor)
  61. ((predicate) predicate)
  62. ((accessor) accessor)
  63. ((modifier) modifier)
  64. ((name) type-id)
  65. ((field-names) field-names))))
  66. the-descriptor)
  67. (define (record-constructor r-t . names-option)
  68. (apply (r-t 'constructor) names-option))
  69. (define (record-predicate r-t)
  70. (r-t 'predicate))
  71. (define (record-accessor r-t field-name)
  72. ((r-t 'accessor) field-name))
  73. (define (record-modifier r-t field-name)
  74. ((r-t 'modifier) field-name))
  75. (define (record-type-name r-t) (r-t 'name))
  76. (define (record-type-field-names r-t) (r-t 'field-names))
  77. (define (record-type? r-t)
  78. (and (procedure? r-t)
  79. (assertion-violation 'record-type? "record-type? not implemented" r-t)))
  80. (define (define-record-discloser r-t proc)
  81. "ignoring define-record-discloser form")