ps-defenum.scm 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  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 hacked to use external (C enumeration) names
  4. ; instead of integers.
  5. ;(define-external-enumeration bing
  6. ; ((foo "BAR")
  7. ; baz))
  8. ; =>
  9. ;(define-syntax bing ...)
  10. ;(define bing/foo (make-external-constant 'bing 'foo "BAR"))
  11. ;(define bing/baz (make-external-constant 'bing 'baz "BAZ"))
  12. ;
  13. ;(enum bing foo) => bing/foo
  14. (define-record-type external-constant :external-constant
  15. (make-external-constant enum-name name c-string)
  16. external-constant?
  17. (enum-name external-constant-enum-name)
  18. (name external-constant-name)
  19. (c-string external-constant-c-string))
  20. (define-record-discloser :external-constant
  21. (lambda (external-const)
  22. (list 'enum
  23. (external-constant-enum-name external-const)
  24. (external-constant-name external-const))))
  25. (define-syntax define-external-enumeration
  26. (lambda (form rename compare)
  27. (let* ((name (cadr form))
  28. (symbol->upcase-string
  29. (lambda (s)
  30. (list->string (map (lambda (c)
  31. (if (char=? c #\-)
  32. #\_
  33. (char-upcase c)))
  34. (string->list (symbol->string s))))))
  35. (constant
  36. (lambda (sym string)
  37. `(,(rename 'make-external-constant) ',name ',sym ,string)))
  38. (conc (lambda things
  39. (string->symbol (apply string-append
  40. (map (lambda (thing)
  41. (if (symbol? thing)
  42. (symbol->string thing)
  43. thing))
  44. things)))))
  45. (var-name
  46. (lambda (sym)
  47. (conc name "/" sym)))
  48. (components
  49. (list->vector
  50. (map (lambda (stuff)
  51. (if (pair? stuff)
  52. (cons (car stuff)
  53. (var-name (car stuff)))
  54. (cons stuff
  55. (var-name stuff))))
  56. (caddr form))))
  57. (%define (rename 'define))
  58. (%define-syntax (rename 'define-syntax))
  59. (%begin (rename 'begin))
  60. (%quote (rename 'quote))
  61. (%make-external-constant (rename 'make-external-constant))
  62. (e-name (conc name '- 'enumeration))
  63. (count (vector-length components)))
  64. `(,%begin
  65. (,%define-syntax ,name
  66. (let ((components ',components))
  67. (lambda (e r c)
  68. (let ((key (cadr e)))
  69. (cond ((c key 'enum)
  70. (let ((which (caddr e)))
  71. (let loop ((i 0)) ;vector-posq
  72. (if (< i ,count)
  73. (if (c which (car (vector-ref components i)))
  74. (r (cdr (vector-ref components i)))
  75. (loop (+ i 1)))
  76. ;; (syntax-violation 'enum "unknown enumerand name"
  77. ;; `(,(cadr e) ,(car e) ,(caddr e)))
  78. e))))
  79. (else e))))))
  80. (,%define ,(conc name '- 'count) ,count)
  81. . ,(map (lambda (stuff)
  82. (if (pair? stuff)
  83. `(,%define ,(var-name (car stuff))
  84. (,%make-external-constant ',name
  85. ',(car stuff)
  86. ,(cadr stuff)))
  87. `(,%define ,(var-name stuff)
  88. (,%make-external-constant ',name
  89. ',stuff
  90. ,(symbol->upcase-string stuff)))))
  91. (caddr form)))))
  92. (begin define define-syntax quote external make-external-constant))