diff --git a/collects/honu/lang/reader.ss b/collects/honu/lang/reader.ss index 2eef6f0cd8..9ca46a46a7 100644 --- a/collects/honu/lang/reader.ss +++ b/collects/honu/lang/reader.ss @@ -1,16 +1,6 @@ +#lang s-exp syntax/module-reader -(module reader scheme/base - (require (only-in syntax/module-reader wrap-read-all)) - (provide (rename-out [*read read] - [*read-syntax read-syntax])) - - (define (*read in modpath line col pos) - (wrap in read-honu modpath #f line col pos)) - - (define (*read-syntax src in modpath line col pos) - (wrap in (lambda (in) - (read-honu-syntax src in)) - modpath src line col pos)) +honu - (define (wrap port read modpath src line col pos) - (wrap-read-all 'honu port read modpath src line col pos))) +#:read read-honu +#:read-syntax read-honu-syntax diff --git a/collects/r5rs/init.ss b/collects/r5rs/init.ss index ce14054238..bcd703e849 100644 --- a/collects/r5rs/init.ss +++ b/collects/r5rs/init.ss @@ -1,19 +1,16 @@ +#lang scheme/base -(module init scheme/base +(read-case-sensitive #f) +(read-accept-infix-dot #f) +(read-curly-brace-as-paren #f) +(read-square-bracket-as-paren #f) - (read-case-sensitive #f) - (read-accept-infix-dot #f) - (read-curly-brace-as-paren #f) - (read-square-bracket-as-paren #f) +(print-mpair-curly-braces #f) +;; Printing pairs with curly braces is a bad idea, because +;; syntax errors then use curly braces! - (print-mpair-curly-braces #f) - ;; Printing pairs with curly braces is a bad idea, because - ;; syntax errors then use curly braces! - - (define-syntax out - (syntax-rules () - [(_) (begin - (require "main.ss") - (provide (all-from-out "main.ss")))])) +(let-syntax ([out (syntax-rules () + [(_) (begin + (require "main.ss") + (provide (all-from-out "main.ss")))])]) (out)) - diff --git a/collects/r5rs/lang/reader.ss b/collects/r5rs/lang/reader.ss index 1f9ea9953e..91102a6ff4 100644 --- a/collects/r5rs/lang/reader.ss +++ b/collects/r5rs/lang/reader.ss @@ -1,20 +1,10 @@ +#lang s-exp syntax/module-reader -(module reader scheme/base - (require (only-in syntax/module-reader wrap-read-all)) - (provide (rename-out [*read read] - [*read-syntax read-syntax])) - - (define (*read in modpath line col pos) - (wrap in read modpath #f line col pos)) - - (define (*read-syntax src in modpath line col pos) - (wrap in (lambda (in) - (read-syntax src in)) - modpath src line col pos)) +r5rs - (define (wrap port read modpath src line col pos) - (parameterize ([read-case-sensitive #f] - [read-accept-infix-dot #f] - [read-curly-brace-as-paren #f] - [read-square-bracket-as-paren #f]) - (wrap-read-all 'r5rs port read modpath src line col pos)))) +#:wrapper1 (lambda (t) + (parameterize ([read-case-sensitive #f] + [read-accept-infix-dot #f] + [read-curly-brace-as-paren #f] + [read-square-bracket-as-paren #f]) + (t))) diff --git a/collects/r6rs/lang/reader.ss b/collects/r6rs/lang/reader.ss index a04369ee18..e055f3af5d 100644 --- a/collects/r6rs/lang/reader.ss +++ b/collects/r6rs/lang/reader.ss @@ -1,19 +1,7 @@ -#lang scheme/base +#lang s-exp syntax/module-reader -(require (only-in syntax/module-reader wrap-read-all) - "../private/readtable.ss") -(provide (rename-out [*read read] - [*read-syntax read-syntax])) +r6rs -(define (*read in) - (wrap in read #f #f #f #f #f)) +#:wrapper1 with-r6rs-reader-parameters -(define (*read-syntax src in modpath line col pos) - (wrap in (lambda (in) - (read-syntax src in)) - modpath src line col pos)) - -(define (wrap in read modpath src line col pos) - (with-r6rs-reader-parameters - (lambda () - (wrap-read-all 'r6rs in read modpath src line col pos)))) +(require "../private/readtable.ss") diff --git a/collects/syntax/module-reader.ss b/collects/syntax/module-reader.ss index 065f746c14..ac8cb57a6b 100644 --- a/collects/syntax/module-reader.ss +++ b/collects/syntax/module-reader.ss @@ -1,28 +1,77 @@ (module module-reader scheme/base (provide (rename-out [provide-module-reader #%module-begin] - [wrap wrap-read-all])) + [wrap wrap-read-all]) + (except-out (all-from-out scheme/base) #%module-begin)) -(define-syntax provide-module-reader - (syntax-rules () - [(_ lib) - (#%module-begin - (#%provide (rename *read read) - (rename *read-syntax read-syntax)) +(require (for-syntax scheme/base)) - (define (*read in modpath line col pos) - (wrap 'lib in read modpath #f line col pos)) +(define-syntax (provide-module-reader stx) + (syntax-case stx () + [(_ lib body ...) + (let ([-read #f] + [-read-syntax #f] + [-wrapper1 #f] + [-wrapper2 #f]) + (define -body + (let loop ([body #'(body ...)]) + (define (err str) + (raise-syntax-error 'syntax/module-reader str + (car (syntax->list body)))) + (syntax-case body () + [(#:read r body ...) + (if -read + (err "got two #:read keywords") + (begin (set! -read #'r) (loop #'(body ...))))] + [(#:read-syntax r body ...) + (if -read-syntax + (err "got two #:read-syntax keywords") + (begin (set! -read-syntax #'r) (loop #'(body ...))))] + [(#:wrapper1 w body ...) + (if -wrapper1 + (err "got two #:wrapper1 keywords") + (begin (set! -wrapper1 #'w) (loop #'(body ...))))] + [(#:wrapper2 w body ...) + (if -wrapper2 + (err "got two #:wrapper2 keywords") + (begin (set! -wrapper2 #'w) (loop #'(body ...))))] + [(k . b) (keyword? (syntax-e #'k)) + (err "got an unknown keyword")] + [_ body]))) + (with-syntax ([-read (or -read #'read)] + [-read-syntax (or -read-syntax #'read-syntax)] + [-wrapper1 (or -wrapper1 #'#f)] + [-wrapper2 (or -wrapper2 #'#f)] + [(body ...) -body]) + (syntax/loc stx + (#%module-begin + body ... + (#%provide (rename *read read) (rename *read-syntax read-syntax)) + (define-values (*read *read-syntax) + (let* ([rd -read] + [rds -read-syntax] + [w1 -wrapper1] + [w1-extra? (and w1 (procedure-arity-includes? w1 2))] + [w1r (if w1-extra? (lambda (t) (w1 t #f)) w1)] + [w1s (if w1-extra? (lambda (t) (w1 t #t)) w1)] + [w2 (or -wrapper2 (lambda (in r) (r in)))]) + (values + (lambda (in modpath line col pos) + (w2 in (lambda (in) + (wrap-internal 'lib in rd w1r modpath #f + line col pos)))) + (lambda (src in modpath line col pos) + (w2 in (lambda (in) + (wrap-internal 'lib in (lambda (in) (rds src in)) + w1s modpath src + line col pos)))))))))))])) - (define (*read-syntax src in modpath line col pos) - (wrap 'lib in (lambda (in) (read-syntax src in)) - modpath src line col pos)))])) - -(define (wrap lib port read modpath src line col pos) - (let* ([body (let loop ([a null]) - (let ([v (read port)]) - (if (eof-object? v) - (reverse a) - (loop (cons v a)))))] +(define (wrap-internal lib port read wrapper modpath src line col pos) + (let* ([body (lambda () + (let loop ([a null]) + (let ([v (read port)]) + (if (eof-object? v) (reverse a) (loop (cons v a))))))] + [body (if wrapper (wrapper body) (body))] [p-name (object-name port)] [name (if (path? p-name) (let-values ([(base name dir?) (split-path p-name)]) @@ -41,7 +90,9 @@ (if (syntax? modpath) (datum->syntax #f lib modpath modpath) v))]) - `(,(tag-src 'module) ,(tag-src name) ,(lib-src lib) - . ,body))) + `(,(tag-src 'module) ,(tag-src name) ,(lib-src lib) . ,body))) + +(define (wrap lib port read modpath src line col pos) + (wrap-internal lib port read #f modpath src line col pos)) ) diff --git a/collects/tests/mzscheme/module-reader.ss b/collects/tests/mzscheme/module-reader.ss new file mode 100644 index 0000000000..41570b921d --- /dev/null +++ b/collects/tests/mzscheme/module-reader.ss @@ -0,0 +1,73 @@ + +(load-relative "loadtest.ss") + +(Section 'module-reader) + +;; ---------------------------------------- + +;; plain version +(module r0 syntax/module-reader scheme/base) + +;; using a simple wrapper to get a case-insensitive reader +(module r1 syntax/module-reader scheme/base + #:wrapper1 (lambda (t) (parameterize ([read-case-sensitive #f]) (t)))) + +;; using the more general wrapper to get a case-insensitive reader +(module r2 syntax/module-reader scheme/base + #:wrapper2 (lambda (in r) (parameterize ([read-case-sensitive #f]) (r in)))) + +;; using explicit case-insensitive read/-syntax versions +(module r3 syntax/module-reader scheme/base + #:read (wrap read) #:read-syntax (wrap read-syntax) + (define ((wrap reader) . args) + (parameterize ([read-case-sensitive #f]) (apply reader args)))) + +;; add something to the result +(module r4 syntax/module-reader zzz + #:wrapper1 (lambda (t) (cons 'foo (t)))) + +;; same as above, but do it properly, if a syntax or a datum is needed +(module r5 syntax/module-reader zzz + #:wrapper1 (lambda (t stx?) (cons (if stx? #'foo 'foo) (t)))) + +;; make an empty module, after reading the contents +(module r6 syntax/module-reader zzz + #:wrapper1 (lambda (t) '())) + +;; fake input port to get an empty module +(module r7 syntax/module-reader zzz + #:wrapper2 (lambda (in rd) (rd (open-input-string "")))) + +;; forget about the input -- just return a fixed empty input module +(module r8 syntax/module-reader whatever + #:wrapper2 (lambda (in rd) + (if (syntax? (rd in)) #'(module page zzz) '(module page zzz)))) + +(define (from-string read str) + (parameterize ([read-accept-reader #t]) + (read (open-input-string str)))) + +(define (test-both str result) + (for ([read (list read + ;; same as `read', but using read-syntax + (lambda (in) (syntax->datum (read-syntax #f in))))]) + (test result from-string read str))) + +(test-both "#reader 'r0 (define FoO #:bAr)" + '(module page scheme/base (define FoO #:bAr))) + +(for ([mod '(r1 r2 r3)]) + (test-both (format "#reader '~a (define FoO #:bAr)" mod) + '(module page scheme/base (define foo #:bar)))) + +(test-both "#reader 'r4 (define foo #:bar)" + '(module page zzz foo (define foo #:bar))) +(test-both "#reader 'r5 (define foo #:bar)" + '(module page zzz foo (define foo #:bar))) + +(test-both "#reader 'r6 (define foo #:bar)" + '(module page zzz)) + +;; ---------------------------------------- + +(report-errs) diff --git a/collects/tests/mzscheme/syntax-tests.ss b/collects/tests/mzscheme/syntax-tests.ss index e12d706275..f9c1b7ea6f 100644 --- a/collects/tests/mzscheme/syntax-tests.ss +++ b/collects/tests/mzscheme/syntax-tests.ss @@ -3,5 +3,6 @@ (load-in-sandbox "moddep.ss") (load-in-sandbox "boundmap-test.ss") (load-in-sandbox "cm.ss") +(load-in-sandbox "module-reader.ss.ss") (report-errs)