enum-set.scm 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. ; Copyright (c) 1993-2007 by Richard Kelsey and Jonathan Rees. See file COPYING.
  2. ; Sets over finite types.
  3. ;
  4. ; (define-enum-set-type id type-name predicate constructor
  5. ; element-syntax element-predicate all-elements element-index-ref)
  6. ;
  7. ; Defines ID to be syntax for constructing sets, PREDICATE to be a predicate
  8. ; for those sets, and CONSTRUCTOR an procedure for constructing one
  9. ; from a list.
  10. ;
  11. ; (enum-set->list <enum-set>) -> <list>
  12. ; (enum-set-member? <enum-set> <enumerand>) -> <boolean>
  13. ; (enum-set=? <enum-set> <enum-set>) -> <boolean>
  14. ; (enum-set-union <enum-set> <enum-set>) -> <enum-set>
  15. ; (enum-set-intersection <enum-set> <enum-set>) -> <enum-set>
  16. ; (enum-set-negation <enum-set>) -> <enum-set>
  17. ;
  18. ; Given an enumerated type:
  19. ; (define-enumerated-type color :color
  20. ; color?
  21. ; colors
  22. ; color-name
  23. ; color-index
  24. ; (red blue green))
  25. ; we can define sets of colors:
  26. ; (define-enum-set-type color-set :color-set
  27. ; color-set?
  28. ; make-color-set
  29. ; color color? colors color-index)
  30. ;
  31. ; (enum-set->list (color-set red blue))
  32. ; -> (#{Color red} #{Color blue})
  33. ; (enum-set->list (enum-set-negation (color-set red blue)))
  34. ; -> (#{Color green})
  35. ; (enum-set-member? (color-set red blue) (color blue))
  36. ; -> #t
  37. (define-syntax define-enum-set-type
  38. (syntax-rules ()
  39. ((define-enum-set-type id type predicate constructor
  40. element-syntax element-predicate all-elements element-index-ref)
  41. (begin
  42. (define type
  43. (make-enum-set-type 'id
  44. element-predicate
  45. all-elements
  46. element-index-ref))
  47. (define (predicate x)
  48. (and (enum-set? x)
  49. (eq? (enum-set-type x)
  50. type)))
  51. (define (constructor elements)
  52. (if (every element-predicate elements)
  53. (make-enum-set type (elements->mask elements element-index-ref))
  54. (error "invalid set elements" element-predicate elements)))
  55. (define-enum-set-maker id constructor element-syntax)))))
  56. ; (define-enum-set-maker id constructor element-syntax)
  57. (define-syntax define-enum-set-maker
  58. (lambda (e r c)
  59. (let ((id (list-ref e 1))
  60. (constructor (list-ref e 2))
  61. (element-syntax (list-ref e 3))
  62. (%define-syntax (r 'define-syntax)))
  63. `(,%define-syntax ,id
  64. (syntax-rules ()
  65. ((,id element ...)
  66. (,constructor (list (,element-syntax element) ...))))))))
  67. (define-record-type enum-set-type :enum-set-type
  68. (make-enum-set-type id predicate values index-ref)
  69. enum-set-type?
  70. (id enum-set-type-id)
  71. (predicate enum-set-type-predicate)
  72. (values enum-set-type-values)
  73. (index-ref enum-set-type-index-ref))
  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 enum-set-type)
  91. (eq? (enum-set-type enum-set) enum-set-type))
  92. (define enum-set->integer enum-set-mask)
  93. (define integer->enum-set make-enum-set)
  94. (define (make-set-constructor id predicate values index-ref)
  95. (let ((type (make-enum-set-type id predicate values index-ref)))
  96. (lambda elements
  97. (if (every predicate elements)
  98. (make-enum-set type (elements->mask elements index-ref))
  99. (error "invalid set elements" predicate elements)))))
  100. (define (elements->mask elements index-ref)
  101. (do ((elements elements (cdr elements))
  102. (mask 0
  103. (bitwise-ior mask
  104. (arithmetic-shift 1 (index-ref (car elements))))))
  105. ((null? elements)
  106. mask)))
  107. (define (enum-set-member? enum-set element)
  108. (if ((enum-set-type-predicate (enum-set-type enum-set))
  109. element)
  110. (not (= (bitwise-and (enum-set-mask enum-set)
  111. (element-mask element (enum-set-type enum-set)))
  112. 0))
  113. (call-error "invalid arguments" enum-set-member? enum-set element)))
  114. (define (enum-set=? enum-set0 enum-set1)
  115. (if (eq? (enum-set-type enum-set0)
  116. (enum-set-type enum-set1))
  117. (= (enum-set-mask enum-set0)
  118. (enum-set-mask enum-set1))
  119. (call-error "invalid arguments" enum-set=? enum-set0 enum-set1)))
  120. (define (element-mask element enum-set-type)
  121. (arithmetic-shift 1
  122. ((enum-set-type-index-ref enum-set-type) element)))
  123. ; To reduce the number of bitwise operations required we bite off two bytes
  124. ; at a time.
  125. (define (enum-set->list enum-set)
  126. (let ((values (enum-set-type-values (enum-set-type enum-set))))
  127. (do ((i 0 (+ i 16))
  128. (mask (enum-set-mask enum-set) (arithmetic-shift mask -16))
  129. (elts '()
  130. (do ((m (bitwise-and mask #xFFFF) (arithmetic-shift m -1))
  131. (i i (+ i 1))
  132. (elts elts (if (odd? m)
  133. (cons (vector-ref values i)
  134. elts)
  135. elts)))
  136. ((= m 0)
  137. elts))))
  138. ((= mask 0)
  139. (reverse elts)))))
  140. (define (enum-set-union enum-set0 enum-set1)
  141. (if (eq? (enum-set-type enum-set0)
  142. (enum-set-type enum-set1))
  143. (make-enum-set (enum-set-type enum-set0)
  144. (bitwise-ior (enum-set-mask enum-set0)
  145. (enum-set-mask enum-set1)))
  146. (call-error "invalid arguments" enum-set-union enum-set0 enum-set1)))
  147. (define (enum-set-intersection enum-set0 enum-set1)
  148. (if (eq? (enum-set-type enum-set0)
  149. (enum-set-type enum-set1))
  150. (make-enum-set (enum-set-type enum-set0)
  151. (bitwise-and (enum-set-mask enum-set0)
  152. (enum-set-mask enum-set1)))
  153. (call-error "invalid arguments" enum-set-union enum-set0 enum-set1)))
  154. (define (enum-set-negation enum-set)
  155. (let* ((type (enum-set-type enum-set))
  156. (mask (- (arithmetic-shift 1
  157. (vector-length (enum-set-type-values type)))
  158. 1)))
  159. (make-enum-set type
  160. (bitwise-and (bitwise-not (enum-set-mask enum-set))
  161. mask))))