#lang racket/base
(require syntax/module-reader)
(provide (rename-out [UPPERCASE-read read]
[UPPERCASE-read-syntax read-syntax]
[UPPERCASE-get-info get-info]))
(define (wrap-read p)
(lambda args
(define datum (apply p args))
(syntax->datum (walk (datum->syntax #f datum)))))
(define (wrap-read-syntax p)
(lambda args
(define stx (apply p args))
(walk stx)))
(define (walk stx)
(syntax-case stx ()
[_
(identifier? stx)
stx]
[(pattern ...)
(with-syntax ([(transformed-pattern ...)
(map walk (syntax->list #'(pattern ...)))])
(syntax/loc stx
(transformed-pattern ...)))]
[(p-head pattern ... . tail)
(with-syntax ([transformed-p-head (walk #'p-head)]
[(transformed-pattern ...)
(map walk (syntax->list #'(pattern ...)))]
[transformed-tail (walk #'tail)])
(syntax/loc stx
(transformed-p-head transformed-pattern ... . transformed-tail)))]
[#(pattern ...)
(with-syntax ([(transformed-pattern ...)
(map walk (syntax->list #'(pattern ...)))])
(syntax/loc stx
#(transformed-pattern ...)))]
[#s(key-datum pattern ...)
(with-syntax ([transformed-pattern
(map walk (syntax->list #'(pattern ...)))])
(syntax/loc stx
#s(key-datum transformed-pattern)))]
[const
(cond
[(string? (syntax-e #'const))
(datum->syntax #'const (string-upcase (syntax-e #'const)) #'const)]
[else
#'const])]))
(define-values (UPPERCASE-read UPPERCASE-read-syntax UPPERCASE-get-info)
(make-meta-reader
'UPPERCASE
"language path"
(lambda (bstr)
(let* ([str (bytes->string/latin-1 bstr)]
[sym (string->symbol str)])
(and (module-path? sym)
(vector
`(submod ,sym reader)
(string->symbol (string-append str "/lang/reader"))))))
wrap-read
wrap-read-syntax
(lambda (proc)
(lambda (key defval)
(if proc (proc key defval) defval)))))