;; reader macro (rune)#.(begin (def $10 'nothing) (assert (not (get-reader-macro #\$))) (assert (not (get-reader-macro #\€))) (assert (not (get-reader-macro #\!))) (def (capital s m) (when (equal? m "!") (return (void (read s)))) `(cons ',(case m ("$" 'usd) ("€" 'eur)) ,(read s))) (assert (void? (set-reader-macro! #\$ capital))) (assert (void? (set-reader-macro! #\€ capital))) (assert (void? (set-reader-macro! #\! capital))) (assert (eq? (get-reader-macro #\$) capital)) (assert (eq? (get-reader-macro #\€) capital)) (assert (eq? (get-reader-macro #\!) capital)))#.(begin (assert (equal? $10 '(usd . 10))) (assert (equal? €20 '(eur . 20))) (assert (equal? (list $10 !10) '((usd . 10)))) (assert (not (list !10))) (assert (void? (set-reader-macro! "$" NIL)))) ; the fall of the US empire#.(begin (assert (equal? $10 'nothing))) ;; reader macro (string)#.(begin (def (to-path s m) (let* {[next (io-peek s 'rune)] [path (if (or (rune-whitespace? next) (eq? next #\))) (subseq m 1) (str (subseq m 1) (read s)))]} `(cons 'path ,path))) (assert (void? (set-reader-macro! "@." to-path))) (assert (void? (set-reader-macro! "@/" to-path))) (assert (eq? (get-reader-macro "@.") to-path)) (assert (eq? (get-reader-macro "@/") to-path)))#.(begin (assert (equal? '(path . ".") @.)) (assert (equal? '(path . "../a") @../a)) (assert (equal? '(path . "./test/blah.txt") @./test/blah.txt)) (assert (equal? '(path . "/absolute/path.txt") @/absolute/path.txt))) ;; read-list-until#.(begin (def s (buffer ">11 >22 >33>>44 55>>66")) (assert (equal? (read-list-until ">>" s) '(>11 >22 >33))) (assert (equal? (read s) 44))) ;; read-list-until and reader macros#.(begin (assert (void? (set-reader-macro! "<<" (λ (s m) `(list ,@(read-list-until ">>" s)))))) (def s (buffer "<<€1 €2 €3>>1 2")) (assert (equal? (eval (read s)) '((eur . 1) (eur . 2) (eur . 3)))) (assert (equal? (read s) 1))) ;; two reader macros with read-list-until within each other#.(begin (assert (void? (set-reader-macro! "%%" (λ (s r) `(list ,@(read-list-until "$$" s)))))) (def s (buffer "<<%%1$$>>")) (assert (equal? (eval (read s)) '((1)))) (def s (buffer "<<%% 1 >> $$")) (assert-fail (read s) parse-error))
;; reader macro (rune)
#.(begin
(def $10 'nothing)
(assert (not (get-reader-macro #\$)))
(assert (not (get-reader-macro #\€)))
(assert (not (get-reader-macro #\!)))
(def (capital s m)
(when (equal? m "!")
(return (void (read s))))
`(cons ',(case m ("$" 'usd) ("€" 'eur)) ,(read s)))
(assert (void? (set-reader-macro! #\$ capital)))
(assert (void? (set-reader-macro! #\€ capital)))
(assert (void? (set-reader-macro! #\! capital)))
(assert (eq? (get-reader-macro #\$) capital))
(assert (eq? (get-reader-macro #\€) capital))
(assert (eq? (get-reader-macro #\!) capital)))
#.(begin
(assert (equal? $10 '(usd . 10)))
(assert (equal? €20 '(eur . 20)))
(assert (equal? (list $10 !10) '((usd . 10))))
(assert (not (list !10)))
(assert (void? (set-reader-macro! "$" NIL)))) ; the fall of the US empire
#.(begin
(assert (equal? $10 'nothing)))
;; reader macro (string)
#.(begin
(def (to-path s m)
(let* {[next (io-peek s 'rune)]
[path (if (or (rune-whitespace? next) (eq? next #\)))
(subseq m 1)
(str (subseq m 1) (read s)))]}
`(cons 'path ,path)))
(assert (void? (set-reader-macro! "@." to-path)))
(assert (void? (set-reader-macro! "@/" to-path)))
(assert (eq? (get-reader-macro "@.") to-path))
(assert (eq? (get-reader-macro "@/") to-path)))
#.(begin
(assert (equal? '(path . ".") @.))
(assert (equal? '(path . "../a") @../a))
(assert (equal? '(path . "./test/blah.txt") @./test/blah.txt))
(assert (equal? '(path . "/absolute/path.txt") @/absolute/path.txt)))
;; read-list-until
#.(begin
(def s (buffer ">11 >22 >33>>44 55>>66"))
(assert (equal? (read-list-until ">>" s) '(>11 >22 >33)))
(assert (equal? (read s) 44)))
;; read-list-until and reader macros
#.(begin
(assert (void? (set-reader-macro! "<<"
(λ (s m) `(list ,@(read-list-until ">>" s))))))
(def s (buffer "<<€1 €2 €3>>1 2"))
(assert (equal? (eval (read s)) '((eur . 1) (eur . 2) (eur . 3))))
(assert (equal? (read s) 1)))
;; two reader macros with read-list-until within each other
#.(begin
(assert (void? (set-reader-macro! "%%"
(λ (s r) `(list ,@(read-list-until "$$" s))))))
(def s (buffer "<<%%1$$>>"))
(assert (equal? (eval (read s)) '((1))))
(def s (buffer "<<%% 1 >> $$"))
(assert-fail (read s) parse-error))