defenum.scm 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. ; Part of Scheme 48 1.9. See file COPYING for notices and license.
  2. ; Authors: Richard Kelsey, Jonathan Rees, Mike Sperber
  3. ; define-enumeration macro
  4. (define-syntax define-enumeration
  5. (lambda (form rename compare)
  6. (let ((name (cadr form))
  7. (components (list->vector (caddr form)))
  8. (conc (lambda things
  9. (string->symbol (apply string-append
  10. (map (lambda (thing)
  11. (if (symbol? thing)
  12. (symbol->string thing)
  13. thing))
  14. things)))))
  15. (%define (rename 'define))
  16. (%define-syntax (rename 'define-syntax))
  17. (%begin (rename 'begin))
  18. (%quote (rename 'quote)))
  19. (let ((e-name (conc name '- 'enumeration))
  20. (count (vector-length components)))
  21. `(,%begin (,%define-syntax ,name
  22. (cons (let ((components ',components))
  23. (lambda (e r c)
  24. (let ((key (cadr e)))
  25. (cond ((c key 'components)
  26. (r ',e-name))
  27. ((c key 'enum)
  28. (let ((which (caddr e)))
  29. (let loop ((i 0)) ;vector-posq
  30. (if (< i ,count)
  31. (if (c which (vector-ref components i))
  32. i
  33. (loop (+ i 1)))
  34. ;; (syntax-violation 'enum "unknown enumerand name"
  35. ;; `(,(cadr e) ,(car e) ,(caddr e)))
  36. e))))
  37. (else e)))))
  38. '(,e-name))) ;Auxiliary binding
  39. (,%define ,e-name ',components)
  40. (,%define ,(conc name '- 'count) ,count)))))
  41. (begin define define-syntax quote))
  42. (define-syntax components
  43. (cons (lambda (e r c) `(,(cadr e) components))
  44. '()))
  45. (define-syntax enum
  46. (cons (lambda (e r c)
  47. (if (not (= (length e) 3))
  48. '(syntax-violation 'enum "wrong number of arguments for enum" e)
  49. `(,(cadr e) enum ,(caddr e))))
  50. '()))
  51. (define-syntax enumerand->name
  52. (syntax-rules ()
  53. ((enumerand->name ?enumerand ?type)
  54. (vector-ref (components ?type) ?enumerand))))
  55. (define-syntax name->enumerand
  56. (syntax-rules ()
  57. ((name->enumerand ?name ?type)
  58. (lookup-enumerand (components ?type) ?name))))
  59. (define (lookup-enumerand components name)
  60. (let ((len (vector-length components)))
  61. (let loop ((i 0)) ;vector-posq
  62. (if (>= i len)
  63. #f
  64. (if (eq? name (vector-ref components i))
  65. i
  66. (loop (+ i 1)))))))