defenum.scm 3.0 KB

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