ps-defenum.scm 3.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. ;;; Ported from Scheme 48 1.9. See file COPYING for notices and license.
  2. ;;;
  3. ;;; Port Author: Andrew Whatson
  4. ;;;
  5. ;;; Original Authors: Richard Kelsey, Jonathan Rees, Mike Sperber
  6. ;;;
  7. ;;; scheme48-1.9.2/scheme/prescheme/ps-defenum.scm
  8. ;;;
  9. ;;; DEFINE-ENUMERATION macro hacked to use external (C enumeration) names
  10. ;;; instead of integers.
  11. ;;;
  12. ;;; (define-external-enumeration bing
  13. ;;; ((foo "BAR")
  14. ;;; baz))
  15. ;;; =>
  16. ;;; (define-syntax bing ...)
  17. ;;; (define bing/foo (make-external-constant 'bing 'foo "BAR"))
  18. ;;; (define bing/baz (make-external-constant 'bing 'baz "BAZ"))
  19. ;;;
  20. ;;; (enum bing foo) => bing/foo
  21. ;;;
  22. (define-module (prescheme ps-defenum)
  23. #:use-module (srfi srfi-9)
  24. #:use-module (prescheme s48-defenum)
  25. #:use-module (prescheme record-discloser)
  26. #:use-module (prescheme syntax-utils)
  27. #:re-export (enum)
  28. #:export (make-external-constant
  29. external-constant?
  30. external-constant-enum-name
  31. external-constant-name
  32. external-constant-c-string
  33. define-external-enumeration))
  34. (define-record-type :external-constant
  35. (make-external-constant enum-name name c-string)
  36. external-constant?
  37. (enum-name external-constant-enum-name)
  38. (name external-constant-name)
  39. (c-string external-constant-c-string))
  40. (define-record-discloser :external-constant
  41. (lambda (external-const)
  42. (list 'enum
  43. (external-constant-enum-name external-const)
  44. (external-constant-name external-const))))
  45. (define (symbol->upcase-string s)
  46. (list->string (map (lambda (c)
  47. (if (char=? c #\-)
  48. #\_
  49. (char-upcase c)))
  50. (string->list (symbol->string s)))))
  51. (define (syntax->upcase-string s)
  52. (datum->syntax s (symbol->upcase-string (syntax->datum s))))
  53. (define-syntax define-external-enumeration
  54. (lambda (x)
  55. (syntax-case x ()
  56. ((_ e-name (elem-defs ...))
  57. (with-syntax (((elems ...) (map (lambda (def)
  58. (syntax-case def ()
  59. ((elem c-name) #'elem)
  60. (elem #'elem)))
  61. #'(elem-defs ...)))
  62. ((c-names ...) (map (lambda (def)
  63. (syntax-case def ()
  64. ((elem c-name) #'c-name)
  65. (elem (syntax->upcase-string #'elem))))
  66. #'(elem-defs ...)))
  67. (e-count (syntax-conc #'e-name '-count)))
  68. (let* ((elements #'(elems ...))
  69. (c-names #'(c-names ...))
  70. (e-symbol (syntax->datum #'e-name))
  71. (var-names (map (lambda (elem)
  72. (syntax-conc e-symbol '/ elem))
  73. elements)))
  74. #`(begin
  75. (define-syntax e-name
  76. (syntax-rules (get elems ...)
  77. #,@(map (lambda (elem var-name)
  78. #`((_ get #,elem) #,var-name))
  79. elements var-names)))
  80. (define e-count #,(length elements))
  81. #,@(map (lambda (elem c-name var-name)
  82. #`(define #,var-name
  83. (make-external-constant 'e-name '#,elem #,c-name)))
  84. elements c-names var-names)
  85. )))))))