ps-defenum.scm 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  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 record-discloser)
  25. #:use-module (prescheme syntax-utils)
  26. #:export (make-external-constant
  27. external-constant?
  28. external-constant-enum-name
  29. external-constant-c-string
  30. define-external-enumeration))
  31. (define-record-type :external-constant
  32. (make-external-constant enum-name name c-string)
  33. external-constant?
  34. (enum-name external-constant-enum-name)
  35. (name external-constant-name)
  36. (c-string external-constant-c-string))
  37. (define-record-discloser :external-constant
  38. (lambda (external-const)
  39. (list 'enum
  40. (external-constant-enum-name external-const)
  41. (external-constant-name external-const))))
  42. (define (symbol->upcase-string s)
  43. (list->string (map (lambda (c)
  44. (if (char=? c #\-)
  45. #\_
  46. (char-upcase c)))
  47. (string->list (symbol->string s)))))
  48. (define (syntax->upcase-string s)
  49. (datum->syntax s (symbol->upcase-string (syntax->datum s))))
  50. (define-syntax define-external-enumeration
  51. (lambda (x)
  52. (syntax-case x ()
  53. ((_ e-name (elem-defs ...))
  54. (with-syntax (((elems ...) (map (lambda (def)
  55. (syntax-case def ()
  56. ((elem c-name) #'elem)
  57. (elem #'elem)))
  58. #'(elem-defs ...)))
  59. ((c-names ...) (map (lambda (def)
  60. (syntax-case def ()
  61. ((elem c-name) #'c-name)
  62. (elem (syntax->upcase-string #'elem))))
  63. #'(elem-defs ...)))
  64. (e-count (syntax-conc #'e-name '-count)))
  65. (let* ((elements #'(elems ...))
  66. (c-names #'(c-names ...))
  67. (e-symbol (syntax->datum #'e-name))
  68. (var-names (map (lambda (elem)
  69. (syntax-conc e-symbol '/ elem))
  70. elements)))
  71. #`(begin
  72. (define-syntax e-name
  73. (syntax-rules (get elems ...)
  74. #,@(map (lambda (elem var-name)
  75. #`((_ get #,elem) #,var-name))
  76. elements var-names)))
  77. (define e-count #,(length elements))
  78. #,@(map (lambda (elem c-name var-name)
  79. #`(define #,var-name
  80. (make-external-constant 'e-name '#,elem #,c-name)))
  81. elements c-names var-names)
  82. )))))))