enum.scm 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. ; Copyright (c) 1993-2008 by Richard Kelsey and Jonathan Rees. See file COPYING.
  2. ; The (rnrs enums (6)) library.
  3. (define (make-enum-type members)
  4. (let* ((table (make-constant-table
  5. (map cons members (iota (length members)))
  6. symbol-hash))
  7. (find-index
  8. (lambda (symbol)
  9. (constant-table-lookup table symbol))))
  10. (big:make-enum-set-type 'r6rs-enum
  11. (lambda (symbol)
  12. (and (find-index symbol) #t))
  13. (list->vector members)
  14. find-index)))
  15. (define (iota n)
  16. (let loop ((n n) (r '()))
  17. (if (zero? n)
  18. r
  19. (loop (- n 1)
  20. (cons (- n 1) r)))))
  21. (define (make-enum-set type symbols)
  22. (big:elements->enum-set type symbols))
  23. (define (enum-type->enum-set et)
  24. (big:enum-set-negation
  25. (big:elements->enum-set et '())))
  26. (define (make-enumeration symbols)
  27. (enum-type->enum-set (make-enum-type symbols)))
  28. (define (enum-set-universe es)
  29. (enum-type->enum-set (big:enum-set-type es)))
  30. (define (enum-set-indexer es)
  31. (lambda (symbol)
  32. (big:enum-set-type-element-index (big:enum-set-type es) symbol)))
  33. (define (enum-set-constructor es)
  34. (let ((et (big:enum-set-type es)))
  35. (lambda (symbols)
  36. (make-enum-set et symbols))))
  37. (define enum-set->list big:enum-set->list)
  38. (define (enum-set-member? symbol es)
  39. (big:enum-set-member? es symbol))
  40. (define (enum-set-subset? es1 es2)
  41. (if (eq? (big:enum-set-type es1)
  42. (big:enum-set-type es2))
  43. (big:enum-set-subset? es1 es2)
  44. ;; slow case
  45. (every? (lambda (member)
  46. (enum-set-member? member es2))
  47. (enum-set->list es1))))
  48. (define (enum-set=? es1 es2)
  49. (if (eq? (big:enum-set-type es1)
  50. (big:enum-set-type es2))
  51. (big:enum-set=? es1 es2)
  52. ;; slow case
  53. (and (enum-set-subset? es1 es2)
  54. (enum-set-subset? es2 es1))))
  55. (define enum-set-union big:enum-set-union)
  56. (define enum-set-intersection big:enum-set-intersection)
  57. (define enum-set-difference big:enum-set-difference)
  58. (define enum-set-complement big:enum-set-negation)
  59. (define (enum-set-projection es1 es2)
  60. (if (eq? (big:enum-set-type es1)
  61. (big:enum-set-type es2))
  62. es1
  63. (let ((et2 (big:enum-set-type es2)))
  64. (big:elements->enum-set et2
  65. (filter (lambda (element)
  66. (and (big:enum-set-type-member? et2 element)
  67. (enum-set-member? element es2)))
  68. (enum-set->list es1))))))
  69. (define-syntax define-type-name-keyword
  70. (lambda (form0 rename0 compare0)
  71. (let ((%define-syntax (rename0 'define-syntax))
  72. (%lambda (rename0 'lambda))
  73. (%desyntaxify (rename0 'desyntaxify))
  74. (%code-quote (rename0 'code-quote))
  75. (%quote (rename0 'quote)))
  76. `(,%define-syntax ,(cadr form0)
  77. (,%lambda (form rename compare)
  78. (let ((id (,%desyntaxify (cadr form))))
  79. (let loop ((members ',(cddr form0)))
  80. (cond
  81. ((null? members) form)
  82. ((eq? (car members) id) (list (,%code-quote ,%quote) id))
  83. (else (loop (cdr members)))))))))))
  84. (define-syntax define-enumeration
  85. (syntax-rules ()
  86. ((define-enumeration ?type-name
  87. (?member ...)
  88. ?constructor)
  89. (begin
  90. (define-type-name-keyword ?type-name ?member ...)
  91. (define type (make-enum-type '(?member ...)))
  92. (define (make elements)
  93. (big:elements->enum-set type elements))
  94. (big:define-enum-set-maker ?constructor make ?type-name)))))