finite-type.scm 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. ; Copyright (c) 1993-2008 by Richard Kelsey and Jonathan Rees. See file COPYING.
  2. ; Finite types (i.e. record types with a fixed set of elements).
  3. ;
  4. ; An enumeration is really a special case of a finite type.
  5. ;
  6. ; (define-finite-type <id and dispatch-macro>
  7. ; <type name>
  8. ; (<constructor field name> ...)
  9. ; <predicate>
  10. ; <vector of elements>
  11. ; <name accessor>
  12. ; <index accessor>
  13. ; (<field name> <field accessor> [<field setter>])
  14. ; ...
  15. ; ((<element name> <constructor field value> ...)
  16. ; ...))
  17. ;
  18. ; This is equivalent to
  19. ;
  20. ; (define-record-type <id and dispatch-macro>
  21. ; <type name>
  22. ; (maker name index <constructor field name> ...)
  23. ; <predicate>
  24. ; (name <name accessor>)
  25. ; (index <index accessor>)
  26. ; (<field name> <field accessor> [<field setter>])
  27. ; ...)
  28. ;
  29. ; (define <vector of elements>
  30. ; (vector (maker <element name> 0 <constructor field value>)
  31. ; (maker <element name> 1 <constructor field value>)
  32. ; ...))
  33. ;
  34. ; (define-dispatch-macro <id and dispatch-macro>
  35. ; (<element name> ...)
  36. ; <vector-of-elements>)
  37. ;
  38. ; where DEFINE-DISPATCH-MACRO defines an ENUM-like dispatcher.
  39. ;
  40. ;(define-finite-type foo :foo ; id and type
  41. ; foo? ; predicate
  42. ; foo-elements ; vector containing all elements
  43. ; foo-name ; name accessor
  44. ; foo-index ; index accessor
  45. ; (color foo-color set-foo-color!) ; any additional fields
  46. ; ((name color) ; element pattern
  47. ; (a 'red) ; the elements themselves
  48. ; (b 'green)
  49. ; (c 'puce)
  50. ; (d 'taupe)))
  51. ;
  52. ; (foo a) -> #{foo a}
  53. (define-syntax define-finite-type
  54. (lambda (form rename compare)
  55. (let ((destruct (lambda (proc)
  56. (apply proc (cdr form))))
  57. (%define-record-type (rename 'define-record-type))
  58. (%define-record-discloser (rename 'define-record-discloser))
  59. (%define (rename 'define))
  60. (%begin (rename 'begin))
  61. (%lambda (rename 'lambda))
  62. (%vector (rename 'vector))
  63. (%list (rename 'list))
  64. (%define-dispatch (rename 'define-dispatch))
  65. (%make-immutable! (rename 'make-immutable!))
  66. (%maker (rename 'maker))
  67. (%name (rename 'name))
  68. (%index (rename 'index))
  69. (%blah (rename 'blah)))
  70. (destruct (lambda (foo :foo pattern foo? foo-elements foo-name foo-index
  71. . more)
  72. (let* ((fields (do ((more more (cdr more))
  73. (fields '() (cons (car more) fields)))
  74. ((or (null? more)
  75. (pair? (caar more)))
  76. (reverse fields))))
  77. (elts (car (reverse more)))
  78. (names (map car elts)))
  79. `(,%begin
  80. (,%define-record-type ,foo ,:foo
  81. (,%maker ,%name ,%index . ,pattern)
  82. ,foo?
  83. (,%name ,foo-name)
  84. (,%index ,foo-index)
  85. . ,fields)
  86. (,%define-record-discloser ,:foo
  87. (,%lambda (,%blah)
  88. (,%list ',foo (,foo-name ,%blah))))
  89. (,%define ,foo-elements
  90. (,%make-immutable!
  91. (,%vector . ,(do ((elts elts (cdr elts))
  92. (i 0 (+ i 1))
  93. (res '() `((,%maker ',(caar elts)
  94. ,i
  95. . ,(cdar elts))
  96. . ,res)))
  97. ((null? elts)
  98. (reverse res))))))
  99. (,%define-dispatch ,foo ,names ,foo-elements)))))))
  100. (define-record-type define-record-discloser define-dispatch
  101. define begin lambda vector list))
  102. ; (define-dispatch <name> (<member name> ...) <vector of members>)
  103. ;
  104. ; This defines <name> to be a macro (<name> X) that looks X up in
  105. ; the list of member names and returns the corresponding element of
  106. ; <vector of members>.
  107. ;
  108. ; (define-dispatch foo (a b c) members)
  109. ; (foo b) -expands-into-> (vector-ref members 1)
  110. (define-syntax define-dispatch
  111. (lambda (form0 rename0 compare0)
  112. (let ((name (cadr form0))
  113. (names (caddr form0))
  114. (elts (cadddr form0))
  115. (%vector-ref (rename0 'vector-ref))
  116. (%code-quote (rename0 'code-quote)))
  117. `(define-syntax ,name
  118. (lambda (form1 rename1 compare1)
  119. (let ((elt (cadr form1)))
  120. (let loop ((names ',names) (i 0))
  121. (cond ((null? names)
  122. form1)
  123. ((compare1 elt (car names))
  124. (list (,%code-quote ,%vector-ref) (rename1 ',elts) i))
  125. (else
  126. (loop (cdr names) (+ i 1))))))))))
  127. (vector-ref code-quote))
  128. ; (define-enumerated-type <id and dispatch-macro>
  129. ; <type name>
  130. ; <predicate>
  131. ; <vector of elements>
  132. ; <name accessor>
  133. ; <index accessor>
  134. ; (<element name> ...))
  135. ;
  136. ; This is a simplified version that has no additional fields. It avoids
  137. ; a lot of unnecessary parens around the element names.
  138. ;
  139. ; The above expands into:
  140. ;
  141. ; (define-finite-type <id and dispatch-macro>
  142. ; <type name>
  143. ; <predicate>
  144. ; <vector of elements>
  145. ; <name accessor>
  146. ; <index accessor>
  147. ; ((name)
  148. ; (<element name>)
  149. ; ...))
  150. (define-syntax define-enumerated-type
  151. (syntax-rules ()
  152. ((define-enumerated-type id type-name predicate elements
  153. name-accessor index-accessor
  154. (element ...))
  155. (define-finite-type id type-name () predicate elements
  156. name-accessor index-accessor
  157. ((element) ...)))))