enum-set.scm 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. ; Part of Scheme 48 1.9. See file COPYING for notices and license.
  2. ; Authors: Richard Kelsey, Jonathan Rees, Mike Sperber
  3. ; Sets over finite types.
  4. ;
  5. ; (define-enum-set-type id type-name predicate constructor
  6. ; element-syntax element-predicate all-elements element-index-ref)
  7. ;
  8. ; Defines ID to be syntax for constructing sets, PREDICATE to be a predicate
  9. ; for those sets, and CONSTRUCTOR an procedure for constructing one
  10. ; from a list.
  11. ;
  12. ; (enum-set->list <enum-set>) -> <list>
  13. ; (enum-set-member? <enum-set> <enumerand>) -> <boolean>
  14. ; (enum-set=? <enum-set> <enum-set>) -> <boolean>
  15. ; (enum-set-union <enum-set> <enum-set>) -> <enum-set>
  16. ; (enum-set-intersection <enum-set> <enum-set>) -> <enum-set>
  17. ; (enum-set-negation <enum-set>) -> <enum-set>
  18. ;
  19. ; Given an enumerated type:
  20. ; (define-enumerated-type color :color
  21. ; color?
  22. ; colors
  23. ; color-name
  24. ; color-index
  25. ; (red blue green))
  26. ; we can define sets of colors:
  27. ; (define-enum-set-type color-set :color-set
  28. ; color-set?
  29. ; make-color-set
  30. ; color color? colors color-index)
  31. ;
  32. ; (enum-set->list (color-set red blue))
  33. ; -> (#{Color red} #{Color blue})
  34. ; (enum-set->list (enum-set-negation (color-set red blue)))
  35. ; -> (#{Color green})
  36. ; (enum-set-member? (color-set red blue) (color blue))
  37. ; -> #t
  38. (define-syntax define-enum-set-type
  39. (syntax-rules ()
  40. ((define-enum-set-type id type predicate constructor
  41. element-syntax element-predicate all-elements element-index-ref)
  42. (begin
  43. (define type
  44. (make-enum-set-type 'id
  45. element-predicate
  46. all-elements
  47. element-index-ref))
  48. (define (predicate x)
  49. (and (enum-set? x)
  50. (enum-set-has-type? x type)))
  51. (define (constructor elements)
  52. (elements->enum-set type elements))
  53. (define-enum-set-maker id constructor element-syntax)))))
  54. ; (define-enum-set-maker id constructor element-syntax)
  55. (define-syntax define-enum-set-maker
  56. (lambda (e r c)
  57. (let ((id (list-ref e 1))
  58. (constructor (list-ref e 2))
  59. (element-syntax (list-ref e 3))
  60. (%define-syntax (r 'define-syntax)))
  61. `(,%define-syntax ,id
  62. (syntax-rules ()
  63. ((,id element ...)
  64. (,constructor (list (,element-syntax element) ...))))))))
  65. (define-record-type enum-set-type :enum-set-type
  66. (make-enum-set-type id predicate values index-ref)
  67. enum-set-type?
  68. (id enum-set-type-id)
  69. (predicate enum-set-type-predicate)
  70. (values enum-set-type-values)
  71. (index-ref enum-set-type-index-ref))
  72. (define (enum-set-type-element-index enum-set-type element)
  73. ((enum-set-type-index-ref enum-set-type) element))
  74. (define-record-discloser :enum-set-type
  75. (lambda (e-s-t)
  76. (list 'enum-set-type (enum-set-type-id e-s-t))))
  77. ; The mask is settable to allow for destructive operations. There aren't
  78. ; any such yet.
  79. ; The C code (in external-lib.c) knows the layout of this record type.
  80. (define-record-type enum-set :enum-set
  81. (make-enum-set type mask)
  82. enum-set?
  83. (type enum-set-type)
  84. (mask enum-set-mask set-enum-set-mask!))
  85. (define-record-discloser :enum-set
  86. (lambda (e-s)
  87. (cons (enum-set-type-id (enum-set-type e-s))
  88. (enum-set->list e-s))))
  89. (define-exported-binding "enum-set-type" :enum-set)
  90. (define (enum-set-has-type? enum-set type)
  91. (eq? (enum-set-type enum-set) type))
  92. (define enum-set->integer enum-set-mask)
  93. (define integer->enum-set make-enum-set)
  94. (define (elements->enum-set enum-set-type elements)
  95. (let ((element-predicate (enum-set-type-predicate enum-set-type)))
  96. (if (every element-predicate elements)
  97. (make-enum-set enum-set-type
  98. (elements->mask elements
  99. (enum-set-type-index-ref enum-set-type)))
  100. (assertion-violation 'elements->enum-set
  101. "invalid set elements"
  102. enum-set-type elements))))
  103. (define (elements->mask elements index-ref)
  104. (do ((elements elements (cdr elements))
  105. (mask 0
  106. (bitwise-ior mask
  107. (arithmetic-shift 1 (index-ref (car elements))))))
  108. ((null? elements)
  109. mask)))
  110. (define (enum-set-member? enum-set element)
  111. (if (enum-set-type-member? (enum-set-type enum-set) element)
  112. (not (= (bitwise-and (enum-set-mask enum-set)
  113. (element-mask element (enum-set-type enum-set)))
  114. 0))
  115. (assertion-violation 'enum-set-member? "invalid arguments"
  116. enum-set element)))
  117. (define (enum-set-type-member? enum-set-type element)
  118. ((enum-set-type-predicate enum-set-type)
  119. element))
  120. (define (enum-set=? enum-set0 enum-set1)
  121. (if (eq? (enum-set-type enum-set0)
  122. (enum-set-type enum-set1))
  123. (= (enum-set-mask enum-set0)
  124. (enum-set-mask enum-set1))
  125. (assertion-violation 'enum-set=? "invalid arguments"
  126. enum-set0 enum-set1)))
  127. (define (enum-set-subset? enum-set0 enum-set1)
  128. (if (eq? (enum-set-type enum-set0)
  129. (enum-set-type enum-set1))
  130. (let ((mask0 (enum-set-mask enum-set0))
  131. (mask1 (enum-set-mask enum-set1)))
  132. (= (bitwise-ior mask0 mask1)
  133. mask1))
  134. (assertion-violation 'enum-set-subset? "invalid arguments"
  135. enum-set0 enum-set1)))
  136. (define (element-mask element enum-set-type)
  137. (arithmetic-shift 1
  138. ((enum-set-type-index-ref enum-set-type) element)))
  139. ; To reduce the number of bitwise operations required we bite off two bytes
  140. ; at a time.
  141. (define (enum-set->list enum-set)
  142. (let ((values (enum-set-type-values (enum-set-type enum-set))))
  143. (do ((i 0 (+ i 16))
  144. (mask (enum-set-mask enum-set) (arithmetic-shift mask -16))
  145. (elts '()
  146. (do ((m (bitwise-and mask #xFFFF) (arithmetic-shift m -1))
  147. (i i (+ i 1))
  148. (elts elts (if (odd? m)
  149. (cons (vector-ref values i)
  150. elts)
  151. elts)))
  152. ((= m 0)
  153. elts))))
  154. ((= mask 0)
  155. (reverse elts)))))
  156. (define (enum-set-union enum-set0 enum-set1)
  157. (if (eq? (enum-set-type enum-set0)
  158. (enum-set-type enum-set1))
  159. (make-enum-set (enum-set-type enum-set0)
  160. (bitwise-ior (enum-set-mask enum-set0)
  161. (enum-set-mask enum-set1)))
  162. (assertion-violation 'enum-set-union "invalid arguments"
  163. enum-set0 enum-set1)))
  164. (define (enum-set-intersection enum-set0 enum-set1)
  165. (if (eq? (enum-set-type enum-set0)
  166. (enum-set-type enum-set1))
  167. (make-enum-set (enum-set-type enum-set0)
  168. (bitwise-and (enum-set-mask enum-set0)
  169. (enum-set-mask enum-set1)))
  170. (assertion-violation 'enum-set-interaction "invalid arguments"
  171. enum-set0 enum-set1)))
  172. (define (enum-set-negation enum-set)
  173. (let* ((type (enum-set-type enum-set))
  174. (mask (- (arithmetic-shift 1
  175. (vector-length (enum-set-type-values type)))
  176. 1)))
  177. (make-enum-set type
  178. (bitwise-and (bitwise-not (enum-set-mask enum-set))
  179. mask))))
  180. (define (enum-set-difference enum-set0 enum-set1)
  181. (enum-set-intersection enum-set0
  182. (enum-set-negation enum-set1)))