209.scm 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645
  1. ;;; Copyright (C) 2020 Wolfgang Corcoran-Mathe
  2. ;;;
  3. ;;; Permission is hereby granted, free of charge, to any person obtaining a
  4. ;;; copy of this software and associated documentation files (the
  5. ;;; "Software"), to deal in the Software without restriction, including
  6. ;;; without limitation the rights to use, copy, modify, merge, publish,
  7. ;;; distribute, sublicense, and/or sell copies of the Software, and to
  8. ;;; permit persons to whom the Software is furnished to do so, subject to
  9. ;;; the following conditions:
  10. ;;;
  11. ;;; The above copyright notice and this permission notice shall be included
  12. ;;; in all copies or substantial portions of the Software.
  13. ;;;
  14. ;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  15. ;;; OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  16. ;;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  17. ;;; IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  18. ;;; CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  19. ;;; TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  20. ;;; SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  21. ;;;
  22. ;;;; Utility
  23. (define-syntax assert
  24. (syntax-rules ()
  25. ((assert expr)
  26. (unless expr
  27. (error "assertion failed" 'expr)))
  28. ((assert expr msg)
  29. (unless expr
  30. (error msg 'expr)))))
  31. (define (exact-natural? obj)
  32. (and (exact-integer? obj) (not (negative? obj))))
  33. (define (bitvector-subset? vec1 vec2)
  34. (let loop ((i (- (bitvector-length vec1) 1)))
  35. (cond ((< i 0) #t)
  36. ((and (bitvector-ref/bool vec1 i)
  37. (zero? (bitvector-ref/int vec2 i)))
  38. #f)
  39. (else (loop (- i 1))))))
  40. ;;;; Types
  41. (define-record-type <enum-type>
  42. (make-raw-enum-type enum-vector name-table comparator)
  43. enum-type?
  44. (enum-vector enum-type-enum-vector set-enum-type-enum-vector!)
  45. (name-table enum-type-name-table set-enum-type-name-table!)
  46. (comparator enum-type-comparator set-enum-type-comparator!))
  47. (define-record-type <enum>
  48. (make-enum type name ordinal value)
  49. enum?
  50. (type enum-type)
  51. (name enum-name)
  52. (ordinal enum-ordinal)
  53. (value enum-value))
  54. (define (make-enum-type names+vals)
  55. (assert (or (pair? names+vals) (null? names+vals))
  56. "argument must be a proper list")
  57. (let* ((type (make-raw-enum-type #f #f #f))
  58. (enums (generate-enums type names+vals)))
  59. (set-enum-type-enum-vector! type (list->vector enums))
  60. (set-enum-type-name-table! type (make-name-table enums))
  61. (set-enum-type-comparator! type (make-enum-comparator type))
  62. type))
  63. (define (generate-enums type names+vals)
  64. (map (lambda (elt ord)
  65. (cond ((and (pair? elt) (= 2 (length elt)) (symbol? (car elt)))
  66. (make-enum type (car elt) ord (cadr elt)))
  67. ((symbol? elt) (make-enum type elt ord ord))
  68. (else (error "make-enum-type: invalid argument" elt))))
  69. names+vals
  70. (iota (length names+vals))))
  71. (define symbol-comparator
  72. (make-comparator symbol?
  73. eqv?
  74. (lambda (sym1 sym2)
  75. (string<? (symbol->string sym1)
  76. (symbol->string sym2)))
  77. symbol-hash))
  78. (define (make-name-table enums)
  79. (hash-table-unfold null?
  80. (lambda (enums)
  81. (values (enum-name (car enums)) (car enums)))
  82. cdr
  83. enums
  84. symbol-comparator))
  85. (define (%enum-type=? etype1 etype2)
  86. (eqv? etype1 etype2))
  87. (define (make-enum-comparator type)
  88. (make-comparator
  89. (lambda (obj)
  90. (and (enum? obj) (eq? (enum-type obj) type)))
  91. eq?
  92. (lambda (enum1 enum2)
  93. (< (enum-ordinal enum1) (enum-ordinal enum2)))
  94. (lambda (enum)
  95. (symbol-hash (enum-name enum)))))
  96. ;;;; Predicates
  97. (define (enum-type-contains? type enum)
  98. (assert (enum-type? type))
  99. (assert (enum? enum))
  100. ((comparator-type-test-predicate (enum-type-comparator type)) enum))
  101. (define (%enum-type-contains?/no-assert type enum)
  102. ((comparator-type-test-predicate (enum-type-comparator type)) enum))
  103. (define (%well-typed-enum? type obj)
  104. (and (enum? obj) (%enum-type-contains?/no-assert type obj)))
  105. (define (%compare-enums compare enums)
  106. (assert (and (pair? enums) (pair? (cdr enums)))
  107. "invalid number of arguments")
  108. (assert (enum? (car enums)))
  109. (let ((type (enum-type (car enums))))
  110. (assert (every (lambda (e) (%well-typed-enum? type e)) (cdr enums))
  111. "enums must all belong to the same type")
  112. (apply compare (enum-type-comparator type) enums)))
  113. (define (enum=? enum1 enum2 . enums)
  114. (assert (enum? enum1))
  115. (let* ((type (enum-type enum1))
  116. (comp (enum-type-comparator type)))
  117. (cond ((null? enums) ; fast path
  118. (assert (%well-typed-enum? type enum2)
  119. "enums must all belong to the same type")
  120. ((comparator-equality-predicate comp) enum1 enum2))
  121. (else ; variadic path
  122. (assert (every (lambda (e) (%well-typed-enum? type e)) enums)
  123. "enums must all belong to the same type")
  124. (apply =? comp enum1 enum2 enums)))))
  125. (define (enum<? . enums) (%compare-enums <? enums))
  126. (define (enum>? . enums) (%compare-enums >? enums))
  127. (define (enum<=? . enums) (%compare-enums <=? enums))
  128. (define (enum>=? . enums) (%compare-enums >=? enums))
  129. ;;;; Enum finders
  130. ;;; Core procedures
  131. (define (enum-name->enum type name)
  132. (assert (enum-type? type))
  133. (assert (symbol? name))
  134. (hash-table-ref/default (enum-type-name-table type) name #f))
  135. (define (enum-ordinal->enum enum-type ordinal)
  136. (assert (enum-type? enum-type))
  137. (assert (exact-natural? ordinal))
  138. (and (< ordinal (enum-type-size enum-type))
  139. (vector-ref (enum-type-enum-vector enum-type) ordinal)))
  140. ;; Fast version for internal use.
  141. (define (%enum-ordinal->enum-no-assert enum-type ordinal)
  142. (vector-ref (enum-type-enum-vector enum-type) ordinal))
  143. ;;; Derived procedures
  144. (define (%enum-project type finder key proc)
  145. (assert (enum-type? type))
  146. (cond ((finder type key) => proc)
  147. (else (error "no enum found" type key))))
  148. (define (enum-name->ordinal type name)
  149. (assert (symbol? name))
  150. (%enum-project type enum-name->enum name enum-ordinal))
  151. (define (enum-name->value type name)
  152. (assert (symbol? name))
  153. (%enum-project type enum-name->enum name enum-value))
  154. (define (enum-ordinal->name type ordinal)
  155. (assert (exact-natural? ordinal))
  156. (%enum-project type %enum-ordinal->enum-no-assert ordinal enum-name))
  157. (define (enum-ordinal->value type ordinal)
  158. (assert (exact-natural? ordinal))
  159. (%enum-project type %enum-ordinal->enum-no-assert ordinal enum-value))
  160. ;;;; Enum type accessors
  161. (define (enum-type-size type)
  162. (assert (enum-type? type))
  163. (vector-length (enum-type-enum-vector type)))
  164. (define (enum-min type)
  165. (assert (enum-type? type))
  166. (vector-ref (enum-type-enum-vector type) 0))
  167. (define (enum-max type)
  168. (assert (enum-type? type))
  169. (let ((vec (enum-type-enum-vector type)))
  170. (vector-ref vec (- (vector-length vec) 1))))
  171. (define (enum-type-enums type)
  172. (assert (enum-type? type))
  173. (vector->list (enum-type-enum-vector type)))
  174. (define (enum-type-names type)
  175. (assert (enum-type? type))
  176. (let ((vec (enum-type-enum-vector type)))
  177. (list-tabulate (vector-length vec)
  178. (lambda (n) (enum-name (vector-ref vec n))))))
  179. (define (enum-type-values type)
  180. (assert (enum-type? type))
  181. (let ((vec (enum-type-enum-vector type)))
  182. (list-tabulate (vector-length vec)
  183. (lambda (n) (enum-value (vector-ref vec n))))))
  184. ;;;; Enum object procedures
  185. (define (enum-next enum)
  186. (assert (enum? enum))
  187. (enum-ordinal->enum (enum-type enum) (+ (enum-ordinal enum) 1)))
  188. (define (enum-prev enum)
  189. (assert (enum? enum))
  190. (let ((ord (enum-ordinal enum)))
  191. (and (> ord 0)
  192. (enum-ordinal->enum (enum-type enum) (- ord 1)))))
  193. ;;;; Enum set constructors
  194. (define-record-type <enum-set>
  195. (make-enum-set type bitvector)
  196. enum-set?
  197. (type enum-set-type)
  198. (bitvector enum-set-bitvector set-enum-set-bitvector!))
  199. (define (enum-empty-set type)
  200. (assert (enum-type? type))
  201. (make-enum-set type (make-bitvector (enum-type-size type) #f)))
  202. (define (enum-type->enum-set type)
  203. (assert (enum-type? type))
  204. (make-enum-set type (make-bitvector (enum-type-size type) #t)))
  205. (define (enum-set type . enums) (list->enum-set type enums))
  206. (define (list->enum-set type enums)
  207. (assert (or (pair? enums) (null? enums))
  208. "argument must be a proper list")
  209. (let ((vec (make-bitvector (enum-type-size type) #f)))
  210. (for-each (lambda (e)
  211. (assert (%well-typed-enum? type e) "ill-typed enum")
  212. (bitvector-set! vec (enum-ordinal e) #t))
  213. enums)
  214. (make-enum-set type vec)))
  215. ;; Returns a set of enums drawn from the enum-type/-set src with
  216. ;; the same names as the enums of eset.
  217. (define (enum-set-projection src eset)
  218. (assert (or (enum-type? src) (enum-set? src))
  219. "argument must be an enum type or enum set")
  220. (assert (enum-set? eset))
  221. (let ((type (if (enum-type? src) src (enum-set-type src))))
  222. (list->enum-set
  223. type
  224. (enum-set-map->list
  225. (lambda (enum)
  226. (let ((name (enum-name enum)))
  227. (or (enum-name->enum type name)
  228. (error "enum name not found in type" name type))))
  229. eset))))
  230. (define (enum-set-copy eset)
  231. (make-enum-set (enum-set-type eset)
  232. (bitvector-copy (enum-set-bitvector eset))))
  233. ;; [Deprecated]
  234. (define (make-enumeration names)
  235. (enum-type->enum-set (make-enum-type (zip names names))))
  236. ;; [Deprecated]
  237. (define (enum-set-universe eset)
  238. (assert (enum-set? eset))
  239. (enum-type->enum-set (enum-set-type eset)))
  240. ;; [Deprecated] Returns a procedure which takes a list of symbols
  241. ;; and returns an enum set containing the corresponding enums. This
  242. ;; extracts the type of eset, but otherwise ignores this argument.
  243. (define (enum-set-constructor eset)
  244. (assert (enum-set? eset))
  245. (let ((type (enum-set-type eset)))
  246. (lambda (names)
  247. (list->enum-set type
  248. (map (lambda (sym)
  249. (or (enum-name->enum type sym)
  250. (error "invalid enum name" sym)))
  251. names)))))
  252. ;; [Deprecated] Returns a procedure which takes a symbol and returns
  253. ;; the corresponding enum ordinal or #f. This doesn't make any use
  254. ;; of eset, beyond pulling out its enum type.
  255. (define (enum-set-indexer eset)
  256. (assert (enum-set? eset))
  257. (let ((type (enum-set-type eset)))
  258. (lambda (name)
  259. (cond ((enum-name->enum type name) => enum-ordinal)
  260. (else #f)))))
  261. ;;;; Enum set predicates
  262. (define (enum-set-contains? eset enum)
  263. (assert (enum-set? eset))
  264. (assert (%well-typed-enum? (enum-set-type eset) enum)
  265. "enum types of arguments must match")
  266. (bitvector-ref/bool (enum-set-bitvector eset) (enum-ordinal enum)))
  267. ;; FIXME: Avoid double (type, then set) lookup.
  268. (define (enum-set-member? name eset)
  269. (assert (symbol? name))
  270. (assert (enum-set? eset))
  271. (bitvector-ref/bool (enum-set-bitvector eset)
  272. (enum-name->ordinal (enum-set-type eset) name)))
  273. (define (%enum-set-type=? eset1 eset2)
  274. (%enum-type=? (enum-set-type eset1) (enum-set-type eset2)))
  275. (define (enum-set-empty? eset)
  276. (assert (enum-set? eset))
  277. (zero? (bitvector-count #t (enum-set-bitvector eset))))
  278. (define (bit-nand a b)
  279. (not (and (= 1 a) (= 1 b))))
  280. (define (enum-set-disjoint? eset1 eset2)
  281. (assert (enum-set? eset1))
  282. (assert (enum-set? eset2))
  283. (assert (%enum-type=? (enum-set-type eset1) (enum-set-type eset2))
  284. "arguments must have the same enum type")
  285. (let ((vec1 (enum-set-bitvector eset1))
  286. (vec2 (enum-set-bitvector eset2)))
  287. (let ((len (bitvector-length vec1)))
  288. (let loop ((i 0))
  289. (or (= i len)
  290. (and (bit-nand (bitvector-ref/int vec1 i)
  291. (bitvector-ref/int vec2 i))
  292. (loop (+ i 1))))))))
  293. (define (enum-set=? eset1 eset2)
  294. (assert (%enum-type=? (enum-set-type eset1) (enum-set-type eset2))
  295. "arguments must have the same enum type")
  296. (bitvector=? (enum-set-bitvector eset1) (enum-set-bitvector eset2)))
  297. (define (enum-set<? eset1 eset2)
  298. (assert (enum-set? eset1))
  299. (assert (enum-set? eset2))
  300. (assert (%enum-type=? (enum-set-type eset1) (enum-set-type eset2))
  301. "arguments must have the same enum type")
  302. (let ((vec1 (enum-set-bitvector eset1))
  303. (vec2 (enum-set-bitvector eset2)))
  304. (and (bitvector-subset? vec1 vec2)
  305. (not (bitvector=? vec1 vec2)))))
  306. (define (enum-set>? eset1 eset2)
  307. (assert (enum-set? eset1))
  308. (assert (enum-set? eset2))
  309. (assert (%enum-type=? (enum-set-type eset1) (enum-set-type eset2))
  310. "arguments must have the same enum type")
  311. (let ((vec1 (enum-set-bitvector eset1))
  312. (vec2 (enum-set-bitvector eset2)))
  313. (and (bitvector-subset? vec2 vec1)
  314. (not (bitvector=? vec1 vec2)))))
  315. (define (enum-set<=? eset1 eset2)
  316. (assert (enum-set? eset1))
  317. (assert (enum-set? eset2))
  318. (assert (%enum-type=? (enum-set-type eset1) (enum-set-type eset2))
  319. "arguments must have the same enum type")
  320. (bitvector-subset? (enum-set-bitvector eset1)
  321. (enum-set-bitvector eset2)))
  322. (define (enum-set>=? eset1 eset2)
  323. (assert (enum-set? eset1))
  324. (assert (enum-set? eset2))
  325. (assert (%enum-type=? (enum-set-type eset1) (enum-set-type eset2))
  326. "arguments must have the same enum type")
  327. (bitvector-subset? (enum-set-bitvector eset2)
  328. (enum-set-bitvector eset1)))
  329. ;; This uses lists as sets and is thus not very efficient.
  330. ;; An implementation with SRFI 113 or some other set library
  331. ;; might want to optimize this.
  332. (define (enum-set-subset? eset1 eset2)
  333. (assert (enum-set? eset1))
  334. (assert (enum-set? eset2))
  335. (lset<= eqv?
  336. (enum-set-map->list enum-name eset1)
  337. (enum-set-map->list enum-name eset2)))
  338. (define (enum-set-any? pred eset)
  339. (assert (procedure? pred))
  340. (call-with-current-continuation
  341. (lambda (return)
  342. (enum-set-fold (lambda (e _) (and (pred e) (return #t)))
  343. #f
  344. eset))))
  345. (define (enum-set-every? pred eset)
  346. (assert (procedure? pred))
  347. (call-with-current-continuation
  348. (lambda (return)
  349. (enum-set-fold (lambda (e _) (or (pred e) (return #f)))
  350. #t
  351. eset))))
  352. ;;;; Enum set mutators
  353. (define (enum-set-adjoin eset . enums)
  354. (apply enum-set-adjoin! (enum-set-copy eset) enums))
  355. (define enum-set-adjoin!
  356. (case-lambda
  357. ((eset enum) ; fast path
  358. (assert (enum-set? eset))
  359. (assert (%well-typed-enum? (enum-set-type eset) enum)
  360. "arguments must have the same enum type")
  361. (bitvector-set! (enum-set-bitvector eset) (enum-ordinal enum) #t)
  362. eset)
  363. ((eset . enums) ; variadic path
  364. (assert (enum-set? eset))
  365. (let ((type (enum-set-type eset))
  366. (vec (enum-set-bitvector eset)))
  367. (for-each (lambda (e)
  368. (assert (%well-typed-enum? type e)
  369. "arguments must have the same enum type")
  370. (bitvector-set! vec (enum-ordinal e) #t))
  371. enums)
  372. eset))))
  373. (define (enum-set-delete eset . enums)
  374. (apply enum-set-delete! (enum-set-copy eset) enums))
  375. (define enum-set-delete!
  376. (case-lambda
  377. ((eset enum) ; fast path
  378. (assert (enum-set? eset))
  379. (assert (%well-typed-enum? (enum-set-type eset) enum)
  380. "arguments must have the same enum type")
  381. (bitvector-set! (enum-set-bitvector eset) (enum-ordinal enum) #f)
  382. eset)
  383. ((eset . enums) ; variadic path
  384. (enum-set-delete-all! eset enums))))
  385. (define (enum-set-delete-all eset enums)
  386. (enum-set-delete-all! (enum-set-copy eset) enums))
  387. (define (enum-set-delete-all! eset enums)
  388. (assert (enum-set? eset))
  389. (assert (or (pair? enums) (null? enums))
  390. "argument must be a proper list")
  391. (unless (null? enums)
  392. (let ((type (enum-set-type eset))
  393. (vec (enum-set-bitvector eset)))
  394. (for-each (lambda (e)
  395. (assert (%well-typed-enum? type e)
  396. "arguments must have the same enum type")
  397. (bitvector-set! vec (enum-ordinal e) #f))
  398. enums)))
  399. eset)
  400. ;;;; Enum set operations
  401. (define (enum-set-size eset)
  402. (assert (enum-set? eset))
  403. (bitvector-count #t (enum-set-bitvector eset)))
  404. (define (enum-set->enum-list eset)
  405. (assert (enum-set? eset))
  406. (enum-set-map->list values eset))
  407. (define (enum-set->list eset)
  408. (enum-set-map->list enum-name eset))
  409. ;; Slightly complicated by the order in which proc is applied.
  410. (define (enum-set-map->list proc eset)
  411. (assert (procedure? proc))
  412. (assert (enum-set? eset))
  413. (let* ((vec (enum-set-bitvector eset))
  414. (len (bitvector-length vec))
  415. (type (enum-set-type eset)))
  416. (letrec
  417. ((build
  418. (lambda (i)
  419. (cond ((= i len) '())
  420. ((bitvector-ref/bool vec i)
  421. (cons (proc (%enum-ordinal->enum-no-assert type i))
  422. (build (+ i 1))))
  423. (else (build (+ i 1)))))))
  424. (build 0))))
  425. (define (enum-set-count pred eset)
  426. (assert (procedure? pred))
  427. (enum-set-fold (lambda (e n) (if (pred e) (+ n 1) n)) 0 eset))
  428. (define (enum-set-filter pred eset)
  429. (enum-set-filter! pred (enum-set-copy eset)))
  430. (define (enum-set-filter! pred eset)
  431. (assert (procedure? pred))
  432. (assert (enum-set? eset))
  433. (let* ((type (enum-set-type eset))
  434. (vec (enum-set-bitvector eset)))
  435. (let loop ((i (- (bitvector-length vec) 1)))
  436. (cond ((< i 0) eset)
  437. ((and (bitvector-ref/bool vec i)
  438. (not (pred (%enum-ordinal->enum-no-assert type i))))
  439. (bitvector-set! vec i #f)
  440. (loop (- i 1)))
  441. (else (loop (- i 1)))))))
  442. (define (enum-set-remove pred eset)
  443. (enum-set-remove! pred (enum-set-copy eset)))
  444. (define (enum-set-remove! pred eset)
  445. (assert (procedure? pred))
  446. (assert (enum-set? eset))
  447. (let* ((type (enum-set-type eset))
  448. (vec (enum-set-bitvector eset)))
  449. (let loop ((i (- (bitvector-length vec) 1)))
  450. (cond ((< i 0) eset)
  451. ((and (bitvector-ref/bool vec i)
  452. (pred (%enum-ordinal->enum-no-assert type i)))
  453. (bitvector-set! vec i #f)
  454. (loop (- i 1)))
  455. (else (loop (- i 1)))))))
  456. (define (enum-set-for-each proc eset)
  457. (assert (procedure? proc))
  458. (enum-set-fold (lambda (e _) (proc e)) '() eset))
  459. (define (enum-set-fold proc nil eset)
  460. (assert (procedure? proc))
  461. (assert (enum-set? eset))
  462. (let ((type (enum-set-type eset)))
  463. (let* ((vec (enum-set-bitvector eset))
  464. (len (bitvector-length vec)))
  465. (let loop ((i 0) (state nil))
  466. (cond ((= i len) state)
  467. ((bitvector-ref/bool vec i)
  468. (loop (+ i 1)
  469. (proc (%enum-ordinal->enum-no-assert type i) state)))
  470. (else (loop (+ i 1) state)))))))
  471. ;;;; Enum set logical operations
  472. (define (%enum-set-logical-op! bv-proc eset1 eset2)
  473. (assert (enum-set? eset1))
  474. (assert (enum-set? eset2))
  475. (assert (%enum-set-type=? eset1 eset2)
  476. "arguments must have the same enum type")
  477. (bv-proc (enum-set-bitvector eset1) (enum-set-bitvector eset2))
  478. eset1)
  479. (define (enum-set-union eset1 eset2)
  480. (%enum-set-logical-op! bitvector-ior! (enum-set-copy eset1) eset2))
  481. (define (enum-set-intersection eset1 eset2)
  482. (%enum-set-logical-op! bitvector-and! (enum-set-copy eset1) eset2))
  483. (define (enum-set-difference eset1 eset2)
  484. (%enum-set-logical-op! bitvector-andc2! (enum-set-copy eset1) eset2))
  485. (define (enum-set-xor eset1 eset2)
  486. (%enum-set-logical-op! bitvector-xor! (enum-set-copy eset1) eset2))
  487. (define (enum-set-union! eset1 eset2)
  488. (%enum-set-logical-op! bitvector-ior! eset1 eset2))
  489. (define (enum-set-intersection! eset1 eset2)
  490. (%enum-set-logical-op! bitvector-and! eset1 eset2))
  491. (define (enum-set-difference! eset1 eset2)
  492. (%enum-set-logical-op! bitvector-andc2! eset1 eset2))
  493. (define (enum-set-xor! eset1 eset2)
  494. (%enum-set-logical-op! bitvector-xor! eset1 eset2))
  495. (define (enum-set-complement eset)
  496. (enum-set-complement! (enum-set-copy eset)))
  497. (define (enum-set-complement! eset)
  498. (assert (enum-set? eset))
  499. (bitvector-not! (enum-set-bitvector eset))
  500. eset)
  501. ;;;; Syntax
  502. ;; Defines a new enum-type T, binds type-name to a macro which
  503. ;; takes a symbol to an enum in T, and binds constructor to a
  504. ;; macro taking symbols to an enum set of type T.
  505. (define-syntax define-enum
  506. (syntax-rules ()
  507. ((_ type-name (name-val ...) constructor)
  508. (begin
  509. (define etype (make-enum-type '(name-val ...)))
  510. (define-syntax type-name
  511. (syntax-rules ()
  512. ((_ name)
  513. (enum-name->enum etype 'name))))
  514. (define-syntax constructor
  515. (syntax-rules ()
  516. ((_ . names)
  517. (list->enum-set etype
  518. (map (lambda (s)
  519. (enum-name->enum etype s))
  520. 'names)))))))))
  521. ;; [Deprecated] As define-enum, except that type-name is bound to
  522. ;; a macro that returns its symbol argument if the corresponding
  523. ;; enum is in the new type.
  524. (define-syntax define-enumeration
  525. (syntax-rules ()
  526. ((_ type-name (name-val ...) constructor)
  527. (begin
  528. (define etype (make-enum-type '(name-val ...)))
  529. (define-syntax type-name
  530. (syntax-rules ()
  531. ((_ name)
  532. (and (enum-name->enum etype 'name) 'name))))
  533. (define-syntax constructor
  534. (syntax-rules ()
  535. ((_ . names)
  536. (list->enum-set etype
  537. (map (lambda (s)
  538. (enum-name->enum etype s))
  539. 'names)))))))))