;;; 5-4.ms
;;; Copyright 1984-2017 Cisco Systems, Inc.
;;; 
;;; Licensed under the Apache License, Version 2.0 (the "License");
;;; you may not use this file except in compliance with the License.
;;; You may obtain a copy of the License at
;;; 
;;; http://www.apache.org/licenses/LICENSE-2.0
;;; 
;;; Unless required by applicable law or agreed to in writing, software
;;; distributed under the License is distributed on an "AS IS" BASIS,
;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
;;; See the License for the specific language governing permissions and
;;; limitations under the License.

(mat char=?/char-ci=?
    (error? (char=?))
    (error? (char=? 'a))
    (error? (char=? #\a 'a))
    (error? (char=? #\a 'a #\b))
    (error? (char=? 'a #\b #\a))
    (error? (char=? #\a #\c 'a #\b))
    (error? (char-ci=?))
    (error? (char-ci=? 'a))
    (error? (char-ci=? #\a 'a))
    (error? (char-ci=? #\a 'a #\b))
    (error? (char-ci=? 'a #\b #\a))
    (error? (char-ci=? #\a #\c 'a #\b))
    (char=? #\a #\a)
    (char-ci=? #\a #\a)
    (not (char=? #\a #\b))
    (not (char-ci=? #\a #\b))
    (not (char=? #\b #\a))
    (not (char-ci=? #\b #\a))
    (not (char=? #\a #\A))
    (char-ci=? #\a #\A)
    (char=? #\a)
    (char=? #\a #\a #\a #\a)
    (not (char=? #\a #\b #\c #\d))
    (not (char=? #\z #\t #\m #\d))
    (not (char=? #\a #\t #\m #\d))
    (not (char=? #\a #\A #\a #\A))
    (not (char=? #\a #\B #\C #\d))
    (not (char=? #\Z #\t #\m #\D))
    (char-ci=? #\a)
    (char-ci=? #\a #\a #\a #\a)
    (not (char-ci=? #\a #\b #\c #\d))
    (not (char-ci=? #\z #\t #\m #\d))
    (not (char-ci=? #\a #\t #\m #\d))
    (char-ci=? #\a #\A #\a #\A)
    (not (char-ci=? #\a #\B #\C #\d))
    (not (char-ci=? #\Z #\t #\m #\D))
    (guard (c [#t #t]) (char=? #\3 #\4 (error #f "oops")))
    (guard (c [#t #t]) (char=? #\3 (error #f "oops") #\4))
    (guard (c [#t #t]) (char=? (error #f "oops") #\3 #\4))
    (guard (c [#t #t]) (not (char=? (error #f "oops"))))
    (guard (c [#t #t]) (char-ci=? #\3 #\4 (error #f "oops")))
    (guard (c [#t #t]) (char-ci=? #\3 (error #f "oops") #\4))
    (guard (c [#t #t]) (char-ci=? (error #f "oops") #\3 #\4))
    (guard (c [#t #t]) (not (char-ci=? (error #f "oops"))))
 )

(mat char<?/char-ci<?
    (error? (char<?))
    (error? (char<? 'a))
    (error? (char<? #\a 'a))
    (error? (char<? #\a 'a #\b))
    (error? (char<? 'a #\b #\a))
    (error? (char<? #\a #\c 'a #\b))
    (error? (char-ci<?))
    (error? (char-ci<? 'a))
    (error? (char-ci<? #\a 'a))
    (error? (char-ci<? #\a 'a #\b))
    (error? (char-ci<? 'a #\b #\a))
    (error? (char-ci<? #\a #\c 'a #\b))
    (not (char<? #\a #\a))
    (not (char-ci<? #\a #\a))
    (char<? #\a #\b)
    (char-ci<? #\a #\b)
    (not (char<? #\b #\a))
    (not (char-ci<? #\b #\a))
    (char<? #\A #\a)
    (not (char-ci<? #\A #\a))
    (char<? #\a)
    (not (char<? #\a #\a #\a #\a))
    (char<? #\a #\b #\c #\d)
    (not (char<? #\z #\t #\m #\d))
    (not (char<? #\a #\t #\m #\d))
    (not (char<? #\a #\A #\a #\A))
    (not (char<? #\a #\B #\C #\d))
    (not (char<? #\Z #\t #\m #\D))
    (char-ci<? #\a)
    (not (char-ci<? #\a #\a #\a #\a))
    (char-ci<? #\a #\b #\c #\d)
    (not (char-ci<? #\z #\t #\m #\d))
    (not (char-ci<? #\a #\t #\m #\d))
    (not (char-ci<? #\a #\A #\a #\A))
    (char-ci<? #\a #\B #\C #\d)
    (not (char-ci<? #\Z #\t #\m #\D))
    (guard (c [#t #t]) (char<? #\4 #\3 (error #f "oops")))
    (guard (c [#t #t]) (char<? #\4 (error #f "oops") #\3))
    (guard (c [#t #t]) (char<? (error #f "oops") #\4 #\3))
    (guard (c [#t #t]) (not (char<? (error #f "oops"))))
    (guard (c [#t #t]) (char-ci<? #\4 #\3 (error #f "oops")))
    (guard (c [#t #t]) (char-ci<? #\4 (error #f "oops") #\3))
    (guard (c [#t #t]) (char-ci<? (error #f "oops") #\4 #\3))
    (guard (c [#t #t]) (not (char-ci<? (error #f "oops"))))
 )

(mat char>?/char-ci>?
    (error? (char>?))
    (error? (char>? 'a))
    (error? (char>? #\a 'a))
    (error? (char>? #\a 'a #\b))
    (error? (char>? 'a #\b #\a))
    (error? (char>? #\a #\c 'a #\b))
    (error? (char-ci>?))
    (error? (char-ci>? 'a))
    (error? (char-ci>? #\a 'a))
    (error? (char-ci>? #\a 'a #\b))
    (error? (char-ci>? 'a #\b #\a))
    (error? (char-ci>? #\a #\c 'a #\b))
    (not (char>? #\a #\a))
    (not (char-ci>? #\a #\b))
    (char>? #\b #\a)
    (char-ci>? #\b #\a)
    (char>? #\a #\A)
    (not (char-ci>? #\a #\A))
    (char>? #\a)
    (not (char>? #\a #\a #\a #\a))
    (not (char>? #\a #\b #\c #\d))
    (char>? #\z #\t #\m #\d)
    (not (char>? #\a #\t #\m #\d))
    (not (char>? #\a #\A #\a #\A))
    (not (char>? #\a #\B #\C #\d))
    (not (char>? #\Z #\t #\m #\D))
    (char-ci>? #\a)
    (not (char-ci>? #\a #\a #\a #\a))
    (not (char-ci>? #\a #\b #\c #\d))
    (char-ci>? #\z #\t #\m #\d)
    (not (char-ci>? #\a #\t #\m #\d))
    (not (char-ci>? #\a #\A #\a #\A))
    (not (char-ci>? #\a #\B #\C #\d))
    (char-ci>? #\Z #\t #\m #\D)
    (guard (c [#t #t]) (char>? #\3 #\4 (error #f "oops")))
    (guard (c [#t #t]) (char>? #\3 (error #f "oops") #\4))
    (guard (c [#t #t]) (char>? (error #f "oops") #\3 #\4))
    (guard (c [#t #t]) (not (char>? (error #f "oops"))))
    (guard (c [#t #t]) (char-ci>? #\3 #\4 (error #f "oops")))
    (guard (c [#t #t]) (char-ci>? #\3 (error #f "oops") #\4))
    (guard (c [#t #t]) (char-ci>? (error #f "oops") #\3 #\4))
    (guard (c [#t #t]) (not (char-ci>? (error #f "oops"))))
 )

(mat char<=?/char-ci<=?
    (error? (char<=?))
    (error? (char<=? 'a))
    (error? (char<=? #\a 'a))
    (error? (char<=? #\a 'a #\b))
    (error? (char<=? 'a #\b #\a))
    (error? (char<=? #\a #\c 'a #\b))
    (error? (char-ci<=?))
    (error? (char-ci<=? 'a))
    (error? (char-ci<=? #\a 'a))
    (error? (char-ci<=? #\a 'a #\b))
    (error? (char-ci<=? 'a #\b #\a))
    (error? (char-ci<=? #\a #\c 'a #\b))
    (char<=? #\a #\a)
    (char-ci<=? #\a #\a)
    (char<=? #\a #\b)
    (char-ci<=? #\a #\b)
    (not (char<=? #\b #\a))
    (not (char-ci<=? #\b #\a))
    (not (char<=? #\a #\A))
    (char-ci<=? #\a #\A)
    (char<=? #\a)
    (char<=? #\a #\a #\a #\a)
    (char<=? #\a #\b #\c #\d)
    (not (char<=? #\z #\t #\m #\d))
    (not (char<=? #\a #\t #\m #\d))
    (not (char<=? #\a #\A #\a #\A))
    (not (char<=? #\a #\B #\C #\d))
    (not (char<=? #\Z #\t #\m #\D))
    (char-ci<=? #\a)
    (char-ci<=? #\a #\a #\a #\a)
    (char-ci<=? #\a #\b #\c #\d)
    (not (char-ci<=? #\z #\t #\m #\d))
    (not (char-ci<=? #\a #\t #\m #\d))
    (char-ci<=? #\a #\A #\a #\A)
    (char-ci<=? #\a #\B #\C #\d)
    (not (char-ci<=? #\Z #\t #\m #\D))
    (guard (c [#t #t]) (char<=? #\4 #\3 (error #f "oops")))
    (guard (c [#t #t]) (char<=? #\4 (error #f "oops") #\3))
    (guard (c [#t #t]) (char<=? (error #f "oops") #\4 #\3))
    (guard (c [#t #t]) (not (char<=? (error #f "oops"))))
    (guard (c [#t #t]) (char-ci<=? #\4 #\3 (error #f "oops")))
    (guard (c [#t #t]) (char-ci<=? #\4 (error #f "oops") #\3))
    (guard (c [#t #t]) (char-ci<=? (error #f "oops") #\4 #\3))
    (guard (c [#t #t]) (not (char-ci<=? (error #f "oops"))))
 )

(mat char>=?/char-ci>=?
    (error? (char>=?))
    (error? (char>=? 'a))
    (error? (char>=? #\a 'a))
    (error? (char>=? #\a 'a #\b))
    (error? (char>=? 'a #\b #\a))
    (error? (char>=? #\a #\c 'a #\b))
    (error? (char-ci>=?))
    (error? (char-ci>=? 'a))
    (error? (char-ci>=? #\a 'a))
    (error? (char-ci>=? #\a 'a #\b))
    (error? (char-ci>=? 'a #\b #\a))
    (error? (char-ci>=? #\a #\c 'a #\b))
    (char>=? #\a #\a)
    (char-ci>=? #\a #\a)
    (not (char>=? #\a #\b))
    (not (char-ci>=? #\a #\b))
    (char>=? #\b #\a)
    (char-ci>=? #\b #\a)
    (not (char>=? #\A #\a))
    (char-ci>=? #\A #\a)
    (char>=? #\a)
    (char>=? #\a #\a #\a #\a)
    (not (char>=? #\a #\b #\c #\d))
    (char>=? #\z #\t #\m #\d)
    (not (char>=? #\a #\t #\m #\d))
    (not (char>=? #\a #\A #\a #\A))
    (not (char>=? #\a #\B #\C #\d))
    (not (char>=? #\Z #\t #\m #\D))
    (char-ci>=? #\a)
    (char-ci>=? #\a #\a #\a #\a)
    (not (char-ci>=? #\a #\b #\c #\d))
    (char-ci>=? #\z #\t #\m #\d)
    (not (char-ci>=? #\a #\t #\m #\d))
    (char-ci>=? #\a #\A #\a #\A)
    (not (char-ci>=? #\a #\B #\C #\d))
    (char-ci>=? #\Z #\t #\m #\D)
    (guard (c [#t #t]) (char>=? #\3 #\4 (error #f "oops")))
    (guard (c [#t #t]) (char>=? #\3 (error #f "oops") #\4))
    (guard (c [#t #t]) (char>=? (error #f "oops") #\3 #\4))
    (guard (c [#t #t]) (not (char>=? (error #f "oops"))))
    (guard (c [#t #t]) (char-ci>=? #\3 #\4 (error #f "oops")))
    (guard (c [#t #t]) (char-ci>=? #\3 (error #f "oops") #\4))
    (guard (c [#t #t]) (char-ci>=? (error #f "oops") #\3 #\4))
    (guard (c [#t #t]) (not (char-ci>=? (error #f "oops"))))
 )

(mat r6rs:char=?/r6rs:char-ci=?
    (error? (r6rs:char=?))
    (error? (r6rs:char=? 'a))
    (error? (r6rs:char=? #\a 'a))
    (error? (r6rs:char=? #\a 'a #\b))
    (error? (r6rs:char=? 'a #\b #\a))
    (error? (r6rs:char=? #\a #\c 'a #\b))
    (error? (r6rs:char-ci=?))
    (error? (r6rs:char-ci=? 'a))
    (error? (r6rs:char-ci=? #\a 'a))
    (error? (r6rs:char-ci=? #\a 'a #\b))
    (error? (r6rs:char-ci=? 'a #\b #\a))
    (error? (r6rs:char-ci=? #\a #\c 'a #\b))
    (r6rs:char=? #\a #\a)
    (r6rs:char-ci=? #\a #\a)
    (not (r6rs:char=? #\a #\b))
    (not (r6rs:char-ci=? #\a #\b))
    (not (r6rs:char=? #\b #\a))
    (not (r6rs:char-ci=? #\b #\a))
    (not (r6rs:char=? #\a #\A))
    (r6rs:char-ci=? #\a #\A)
    (r6rs:char=? #\a #\a #\a #\a)
    (not (r6rs:char=? #\a #\b #\c #\d))
    (not (r6rs:char=? #\z #\t #\m #\d))
    (not (r6rs:char=? #\a #\t #\m #\d))
    (not (r6rs:char=? #\a #\A #\a #\A))
    (not (r6rs:char=? #\a #\B #\C #\d))
    (not (r6rs:char=? #\Z #\t #\m #\D))
    (r6rs:char-ci=? #\a #\a #\a #\a)
    (not (r6rs:char-ci=? #\a #\b #\c #\d))
    (not (r6rs:char-ci=? #\z #\t #\m #\d))
    (not (r6rs:char-ci=? #\a #\t #\m #\d))
    (r6rs:char-ci=? #\a #\A #\a #\A)
    (not (r6rs:char-ci=? #\a #\B #\C #\d))
    (not (r6rs:char-ci=? #\Z #\t #\m #\D))
    (guard (c [#t #t]) (r6rs:char=? #\3 #\4 (error #f "oops")))
    (guard (c [#t #t]) (r6rs:char=? #\3 (error #f "oops") #\4))
    (guard (c [#t #t]) (r6rs:char=? (error #f "oops") #\3 #\4))
    (guard (c [#t #t]) (not (r6rs:char=? (error #f "oops"))))
    (guard (c [#t #t]) (r6rs:char-ci=? #\3 #\4 (error #f "oops")))
    (guard (c [#t #t]) (r6rs:char-ci=? #\3 (error #f "oops") #\4))
    (guard (c [#t #t]) (r6rs:char-ci=? (error #f "oops") #\3 #\4))
    (guard (c [#t #t]) (not (r6rs:char-ci=? (error #f "oops"))))
 )

(mat r6rs:char<?/r6rs:char-ci<?
    (error? (r6rs:char<?))
    (error? (r6rs:char<? 'a))
    (error? (r6rs:char<? #\a 'a))
    (error? (r6rs:char<? #\a 'a #\b))
    (error? (r6rs:char<? 'a #\b #\a))
    (error? (r6rs:char<? #\a #\c 'a #\b))
    (error? (r6rs:char-ci<?))
    (error? (r6rs:char-ci<? 'a))
    (error? (r6rs:char-ci<? #\a 'a))
    (error? (r6rs:char-ci<? #\a 'a #\b))
    (error? (r6rs:char-ci<? 'a #\b #\a))
    (error? (r6rs:char-ci<? #\a #\c 'a #\b))
    (not (r6rs:char<? #\a #\a))
    (not (r6rs:char-ci<? #\a #\a))
    (r6rs:char<? #\a #\b)
    (r6rs:char-ci<? #\a #\b)
    (not (r6rs:char<? #\b #\a))
    (not (r6rs:char-ci<? #\b #\a))
    (r6rs:char<? #\A #\a)
    (not (r6rs:char-ci<? #\A #\a))
    (not (r6rs:char<? #\a #\a #\a #\a))
    (r6rs:char<? #\a #\b #\c #\d)
    (not (r6rs:char<? #\z #\t #\m #\d))
    (not (r6rs:char<? #\a #\t #\m #\d))
    (not (r6rs:char<? #\a #\A #\a #\A))
    (not (r6rs:char<? #\a #\B #\C #\d))
    (not (r6rs:char<? #\Z #\t #\m #\D))
    (not (r6rs:char-ci<? #\a #\a #\a #\a))
    (r6rs:char-ci<? #\a #\b #\c #\d)
    (not (r6rs:char-ci<? #\z #\t #\m #\d))
    (not (r6rs:char-ci<? #\a #\t #\m #\d))
    (not (r6rs:char-ci<? #\a #\A #\a #\A))
    (r6rs:char-ci<? #\a #\B #\C #\d)
    (not (r6rs:char-ci<? #\Z #\t #\m #\D))
    (guard (c [#t #t]) (r6rs:char<? #\4 #\3 (error #f "oops")))
    (guard (c [#t #t]) (r6rs:char<? #\4 (error #f "oops") #\3))
    (guard (c [#t #t]) (r6rs:char<? (error #f "oops") #\4 #\3))
    (guard (c [#t #t]) (not (r6rs:char<? (error #f "oops"))))
    (guard (c [#t #t]) (r6rs:char-ci<? #\4 #\3 (error #f "oops")))
    (guard (c [#t #t]) (r6rs:char-ci<? #\4 (error #f "oops") #\3))
    (guard (c [#t #t]) (r6rs:char-ci<? (error #f "oops") #\4 #\3))
    (guard (c [#t #t]) (not (r6rs:char-ci<? (error #f "oops"))))
 )

(mat r6rs:char>?/r6rs:char-ci>?
    (error? (r6rs:char>?))
    (error? (r6rs:char>? 'a))
    (error? (r6rs:char>? #\a 'a))
    (error? (r6rs:char>? #\a 'a #\b))
    (error? (r6rs:char>? 'a #\b #\a))
    (error? (r6rs:char>? #\a #\c 'a #\b))
    (error? (r6rs:char-ci>?))
    (error? (r6rs:char-ci>? 'a))
    (error? (r6rs:char-ci>? #\a 'a))
    (error? (r6rs:char-ci>? #\a 'a #\b))
    (error? (r6rs:char-ci>? 'a #\b #\a))
    (error? (r6rs:char-ci>? #\a #\c 'a #\b))
    (not (r6rs:char>? #\a #\a))
    (not (r6rs:char-ci>? #\a #\b))
    (r6rs:char>? #\b #\a)
    (r6rs:char-ci>? #\b #\a)
    (r6rs:char>? #\a #\A)
    (not (r6rs:char-ci>? #\a #\A))
    (not (r6rs:char>? #\a #\a #\a #\a))
    (not (r6rs:char>? #\a #\b #\c #\d))
    (r6rs:char>? #\z #\t #\m #\d)
    (not (r6rs:char>? #\a #\t #\m #\d))
    (not (r6rs:char>? #\a #\A #\a #\A))
    (not (r6rs:char>? #\a #\B #\C #\d))
    (not (r6rs:char>? #\Z #\t #\m #\D))
    (not (r6rs:char-ci>? #\a #\a #\a #\a))
    (not (r6rs:char-ci>? #\a #\b #\c #\d))
    (r6rs:char-ci>? #\z #\t #\m #\d)
    (not (r6rs:char-ci>? #\a #\t #\m #\d))
    (not (r6rs:char-ci>? #\a #\A #\a #\A))
    (not (r6rs:char-ci>? #\a #\B #\C #\d))
    (r6rs:char-ci>? #\Z #\t #\m #\D)
    (guard (c [#t #t]) (r6rs:char>? #\3 #\4 (error #f "oops")))
    (guard (c [#t #t]) (r6rs:char>? #\3 (error #f "oops") #\4))
    (guard (c [#t #t]) (r6rs:char>? (error #f "oops") #\3 #\4))
    (guard (c [#t #t]) (not (r6rs:char>? (error #f "oops"))))
    (guard (c [#t #t]) (r6rs:char-ci>? #\3 #\4 (error #f "oops")))
    (guard (c [#t #t]) (r6rs:char-ci>? #\3 (error #f "oops") #\4))
    (guard (c [#t #t]) (r6rs:char-ci>? (error #f "oops") #\3 #\4))
    (guard (c [#t #t]) (not (r6rs:char-ci>? (error #f "oops"))))
 )

(mat r6rs:char<=?/r6rs:char-ci<=?
    (error? (r6rs:char<=?))
    (error? (r6rs:char<=? 'a))
    (error? (r6rs:char<=? #\a 'a))
    (error? (r6rs:char<=? #\a 'a #\b))
    (error? (r6rs:char<=? 'a #\b #\a))
    (error? (r6rs:char<=? #\a #\c 'a #\b))
    (error? (r6rs:char-ci<=?))
    (error? (r6rs:char-ci<=? 'a))
    (error? (r6rs:char-ci<=? #\a 'a))
    (error? (r6rs:char-ci<=? #\a 'a #\b))
    (error? (r6rs:char-ci<=? 'a #\b #\a))
    (error? (r6rs:char-ci<=? #\a #\c 'a #\b))
    (r6rs:char<=? #\a #\a)
    (r6rs:char-ci<=? #\a #\a)
    (r6rs:char<=? #\a #\b)
    (r6rs:char-ci<=? #\a #\b)
    (not (r6rs:char<=? #\b #\a))
    (not (r6rs:char-ci<=? #\b #\a))
    (not (r6rs:char<=? #\a #\A))
    (r6rs:char-ci<=? #\a #\A)
    (r6rs:char<=? #\a #\a #\a #\a)
    (r6rs:char<=? #\a #\b #\c #\d)
    (not (r6rs:char<=? #\z #\t #\m #\d))
    (not (r6rs:char<=? #\a #\t #\m #\d))
    (not (r6rs:char<=? #\a #\A #\a #\A))
    (not (r6rs:char<=? #\a #\B #\C #\d))
    (not (r6rs:char<=? #\Z #\t #\m #\D))
    (r6rs:char-ci<=? #\a #\a #\a #\a)
    (r6rs:char-ci<=? #\a #\b #\c #\d)
    (not (r6rs:char-ci<=? #\z #\t #\m #\d))
    (not (r6rs:char-ci<=? #\a #\t #\m #\d))
    (r6rs:char-ci<=? #\a #\A #\a #\A)
    (r6rs:char-ci<=? #\a #\B #\C #\d)
    (not (r6rs:char-ci<=? #\Z #\t #\m #\D))
    (guard (c [#t #t]) (r6rs:char<=? #\4 #\3 (error #f "oops")))
    (guard (c [#t #t]) (r6rs:char<=? #\4 (error #f "oops") #\3))
    (guard (c [#t #t]) (r6rs:char<=? (error #f "oops") #\4 #\3))
    (guard (c [#t #t]) (not (r6rs:char<=? (error #f "oops"))))
    (guard (c [#t #t]) (r6rs:char-ci<=? #\4 #\3 (error #f "oops")))
    (guard (c [#t #t]) (r6rs:char-ci<=? #\4 (error #f "oops") #\3))
    (guard (c [#t #t]) (r6rs:char-ci<=? (error #f "oops") #\4 #\3))
    (guard (c [#t #t]) (not (r6rs:char-ci<=? (error #f "oops"))))
 )

(mat r6rs:char>=?/r6rs:char-ci>=?
    (error? (r6rs:char>=?))
    (error? (r6rs:char>=? 'a))
    (error? (r6rs:char>=? #\a 'a))
    (error? (r6rs:char>=? #\a 'a #\b))
    (error? (r6rs:char>=? 'a #\b #\a))
    (error? (r6rs:char>=? #\a #\c 'a #\b))
    (error? (r6rs:char-ci>=?))
    (error? (r6rs:char-ci>=? 'a))
    (error? (r6rs:char-ci>=? #\a 'a))
    (error? (r6rs:char-ci>=? #\a 'a #\b))
    (error? (r6rs:char-ci>=? 'a #\b #\a))
    (error? (r6rs:char-ci>=? #\a #\c 'a #\b))
    (r6rs:char>=? #\a #\a)
    (r6rs:char-ci>=? #\a #\a)
    (not (r6rs:char>=? #\a #\b))
    (not (r6rs:char-ci>=? #\a #\b))
    (r6rs:char>=? #\b #\a)
    (r6rs:char-ci>=? #\b #\a)
    (not (r6rs:char>=? #\A #\a))
    (r6rs:char-ci>=? #\A #\a)
    (r6rs:char>=? #\a #\a #\a #\a)
    (not (r6rs:char>=? #\a #\b #\c #\d))
    (r6rs:char>=? #\z #\t #\m #\d)
    (not (r6rs:char>=? #\a #\t #\m #\d))
    (not (r6rs:char>=? #\a #\A #\a #\A))
    (not (r6rs:char>=? #\a #\B #\C #\d))
    (not (r6rs:char>=? #\Z #\t #\m #\D))
    (r6rs:char-ci>=? #\a #\a #\a #\a)
    (not (r6rs:char-ci>=? #\a #\b #\c #\d))
    (r6rs:char-ci>=? #\z #\t #\m #\d)
    (not (r6rs:char-ci>=? #\a #\t #\m #\d))
    (r6rs:char-ci>=? #\a #\A #\a #\A)
    (not (r6rs:char-ci>=? #\a #\B #\C #\d))
    (r6rs:char-ci>=? #\Z #\t #\m #\D)
    (guard (c [#t #t]) (r6rs:char>=? #\3 #\4 (error #f "oops")))
    (guard (c [#t #t]) (r6rs:char>=? #\3 (error #f "oops") #\4))
    (guard (c [#t #t]) (r6rs:char>=? (error #f "oops") #\3 #\4))
    (guard (c [#t #t]) (not (r6rs:char>=? (error #f "oops"))))
    (guard (c [#t #t]) (r6rs:char-ci>=? #\3 #\4 (error #f "oops")))
    (guard (c [#t #t]) (r6rs:char-ci>=? #\3 (error #f "oops") #\4))
    (guard (c [#t #t]) (r6rs:char-ci>=? (error #f "oops") #\3 #\4))
    (guard (c [#t #t]) (not (r6rs:char-ci>=? (error #f "oops"))))
 )

(mat char-alphabetic?
    (error? (char-alphabetic?))
    (error? (char-alphabetic? #\a #\b))
    (error? (char-alphabetic? 'a))
    (char-alphabetic? #\z)
    (not (char-alphabetic? #\3))
    (char-alphabetic? #\A)
    (not (char-alphabetic? #\space))
 )

(mat char-numeric?
    (error? (char-numeric?))
    (error? (char-numeric? #\a #\b))
    (error? (char-numeric? 'a))
    (not (char-numeric? #\k))
    (char-numeric? #\0)
    (char-numeric? #\4)
    (char-numeric? #\9)
    (not (char-numeric? #\newline))
 )

(mat char-lower-case?
    (error? (char-lower-case?))
    (error? (char-lower-case? #\a #\b))
    (error? (char-lower-case? 'a))
    (char-lower-case? #\z)
    (not (char-lower-case? #\A))
 )

(mat char-upper-case?
    (error? (char-upper-case?))
    (error? (char-upper-case? #\a #\b))
    (error? (char-upper-case? 'a))
    (char-upper-case? #\A)
    (not (char-upper-case? #\z))
 )

(mat char-title-case?
    (error? (char-title-case?))
    (error? (char-title-case? #\a #\b))
    (error? (char-title-case? 'a))
    (char-title-case? #\x01C5)
    (not (char-title-case? #\z))
 )

(mat char-general-category
    (error? (char-general-category))
    (error? (char-general-category #\a #\b))
    (error? (char-general-category 'a))
    (eq? (char-general-category #\A) 'Lu)
    (eq? (char-general-category #\z) 'Ll)
 )

(mat char-whitespace?
    (error? (char-whitespace?))
    (error? (char-whitespace? #\a #\b))
    (error? (char-whitespace? 'a))
    (char-whitespace? #\space)
    (char-whitespace? #\return)
    (not (char-whitespace? #\F))
    (char-whitespace? #\newline)
    (char-whitespace? #\tab)
    (not (char-whitespace? #\%))
    (char-whitespace? #\page)
    (not (char-whitespace? #\3))
    (char-whitespace? #\linefeed)
 )

(mat char-grapheme-break-property
    (error? (char-grapheme-break-property))
    (error? (char-grapheme-break-property #\a #\b))
    (error? (char-grapheme-break-property 'a))
    (eq? 'Other (char-grapheme-break-property #\space))
    (eq? 'Other (char-grapheme-break-property #\a))
    (eq? 'Extend (char-grapheme-break-property #\x300))
    (eq? 'Extend (char-grapheme-break-property #\x1122F))
    (eq? 'SpacingMark (char-grapheme-break-property #\x1122E))
 )

(mat char-extended-pictographic?
    (error? (char-extended-pictographic?))
    (error? (char-extended-pictographic? #\a #\b))
    (error? (char-extended-pictographic? 'a))
    (not (char-extended-pictographic? #\space))
    (not (char-extended-pictographic? #\a))
    (char-extended-pictographic? #\xA9)
    (char-extended-pictographic? #\x2195)
    (char-extended-pictographic? #\x1F4AD)
    (not (char-extended-pictographic? #\x1F11F))
 )

(mat char-upcase
    (error? (char-upcase))
    (error? (char-upcase #\a #\b))
    (error? (char-upcase 'a))
    (eqv? (char-upcase #\a) #\A)
    (eqv? (char-upcase #\Z) #\Z)
 )

(mat char-titlecase
    (error? (char-titlecase))
    (error? (char-titlecase #\a #\b))
    (error? (char-titlecase 'a))
    (eqv? (char-titlecase #\a) #\A)
    (eqv? (char-titlecase #\Z) #\Z)
 )

(mat char-downcase
    (error? (char-downcase))
    (error? (char-downcase #\a #\b))
    (error? (char-downcase 'a))
    (eqv? (char-downcase #\a) #\a)
    (eqv? (char-downcase #\Z) #\z)
 )

(mat char-foldcase
    (error? (char-foldcase))
    (error? (char-foldcase #\a #\b))
    (error? (char-foldcase 'a))
    (eqv? (char-foldcase #\a) #\a)
    (eqv? (char-foldcase #\Z) #\z)
    (eqv? (char-foldcase #\x1e9e) #\xDF)
    (eqv? (char-foldcase #\x1f8d) #\x1f85)
 )

(mat integer->char
    (error? (integer->char))
    (error? (integer->char 17 3))
    (error? (integer->char 'a))
    (error? (integer->char #f))
    (error? (integer->char #\a))
    (error? (integer->char -1))
    (error? (integer->char (+ (most-positive-fixnum) 1)))
    (error? (integer->char (- (most-negative-fixnum) 1)))
    (error? (integer->char #xD800))
    (error? (integer->char #xD900))
    (error? (integer->char #xDA00))
    (error? (integer->char #xDB00))
    (error? (integer->char #xDC00))
    (error? (integer->char #xDD00))
    (error? (integer->char #xDE00))
    (error? (integer->char #xDF00))
    (error? (integer->char #xDFFF))
    (error? (integer->char #x110000))
    (error? (integer->char #x120000))
    (error? (integer->char #x7fffffff))
    (eqv? (integer->char #x20) #\space)
    (eqv? (integer->char #x41) #\A)
    (eqv? (integer->char #x61) #\a)
    (eqv? (integer->char #x7f) #\rubout)
    (eqv? (integer->char #xD7FF) #\xD7FF)
    (eqv? (integer->char #xE000) #\xE000)
    (eqv? (integer->char #x10FFFF) #\x10FFFF)
 )

(mat char->integer
    (error? (char->integer))
    (error? (char->integer #\a #\b))
    (error? (char->integer 'a))
    (error? (char->integer #x20))
    (eqv? (char->integer #\1) #x31)
    (eqv? (char->integer #\z) #x7a)
    (eqv? (char->integer #\~) #x7e)
    (eqv? (char->integer #\nul) #x00)
    (eqv? (char->integer #\backspace) #x08)
    (eqv? (char->integer #\return) #x0d)
    (eqv? (char->integer #\page) #x0c)
    (eqv? (char->integer #\linefeed) #x0a)
    (eqv? (char->integer #\newline) #x0a)
    (eqv? (char->integer #\rubout) #x7f)
    (eqv? (char->integer #\space) #x20)
    (eqv? (char->integer #\tab) #x09)
    (begin
      (do ([i 0 (fx+ i 1)])
          ((fx>= i #xD800))
        (unless (eqv? (char->integer (integer->char i)) i)
          (errorf #f "failed for ~s" i)))
      (do ([i #xE000 (fx+ i 1)])
          ((fx>= i #x110000))
        (unless (eqv? (char->integer (integer->char i)) i)
          (errorf #f "failed for ~s" i)))
      #t)
 )

(mat char-
  (error? (char-))
  (error? (char- #\a #\b #\c))
  (error? (char- #\a 4))
  (eqv? (char- #\b #\a) 1)
  (eqv? (char- #\a #\b) -1)
  ;; lambda - eta
  (eqv? (char- #\x03BB #\x03B7) 4)
  ;; eta - lambda
  (eqv? (char- #\x03B7 #\x03BB) -4)
)

(mat string-for-each
  (error? ; invalid number of arguments
    (string-for-each))
  (error? ; invalid number of arguments
    (string-for-each '#()))
  (error? ; invalid number of arguments
    (string-for-each +))
  (error? ; non procedure ""
    (string-for-each "" ""))
  (error? ; non procedure ""
    (string-for-each "" "" ""))
  (error? ; non procedure ""
    (string-for-each "" "" "" '()))
  (error? ; non procedure ""
    (string-for-each "" "" "" "" ""))
  (error? ; non string 3
    (string-for-each + 3))
  (error? ; non string (3)
    (string-for-each + "" '(3)))
  (error? ; non string (3)
    (string-for-each + "" "" '(3)))
  (error? ; non string (3)
    (string-for-each + "" "" '(3) ""))
  (error? ; non string 7
    (string-for-each + 7 "" "" "" ""))
  (error? ; lengths differ
    (string-for-each + "" "x"))
  (error? ; lengths differ
    (string-for-each + "" "" "x"))
  (error? ; lengths differ
    (string-for-each + "" "" "x" ""))
  (error? ; lengths differ
    (string-for-each + "y" "" "x" ""))
  (error? ; lengths differ
    (string-for-each + "y" "" "" "" ""))
  (equal? (string-for-each + "") (void))
  (equal? (string-for-each + "" "") (void))
  (equal? (string-for-each + "" "" "") (void))
  (equal? (string-for-each + "" "" "" "" "") (void))
  (equal?
    (let ([ls '()])
      (string-for-each (lambda (x) (set! ls (cons x ls))) "abcdef")
      ls)
    '(#\f #\e #\d #\c #\b #\a))
  (equal?
    (let ([ls '()])
      (string-for-each
        (lambda (x y) (set! ls (cons (cons x y) ls)))
        "abcdef"
        "327654")
      ls)
    '((#\f . #\4) (#\e . #\5) (#\d . #\6) (#\c . #\7) (#\b . #\2) (#\a . #\3)))
  (equal?
    (let ([ls '()])
      (string-for-each
        (lambda r (set! ls (cons r ls)))
        "abcdef"
        "327654"
        "!@#$%^")
      ls)
    '((#\f #\4 #\^) (#\e #\5 #\%) (#\d #\6 #\$) (#\c #\7 #\#) (#\b #\2 #\@) (#\a #\3 #\!)))
  (equal?
    (let ([ls '()])
      (string-for-each
        (lambda r (set! ls (cons r ls)))
        "abcdef"
        "327654"
        "!@#$%^"
        "hello!"
        "hello?"
        "3.1415")
      (map list->string ls))
    '("f4^!?5" "e5%oo1" "d6$ll4" "c7#ll1" "b2@ee." "a3!hh3"))
  (begin
    (define ($string-for-each-f1 p x1 x2 x3 x4 x5)
      (begin
        (string-for-each p "")
        (string-for-each p "" x1)
        (string-for-each p "" x1 x2)
        (string-for-each p "" x1 x2 x3)
        (string-for-each p "" x1 x2 x3 x4)
        (string-for-each p "" x1 x2 x3 x4 x5)
        (string-for-each p x1 "")
        (string-for-each p x1 "" x2)
        (string-for-each p x1 "" x2 x3)
        (string-for-each p x1 "" x2 x3 x4)
        (string-for-each p x1 "" x2 x3 x4 x5)
        (string-for-each p x1 x2 "")
        (string-for-each p x1 x2 "" x3)
        (string-for-each p x1 x2 "" x3 x4)
        (string-for-each p x1 x2 "" x3 x4 x5)
        (string-for-each p x1 x2 x3 "")
        (string-for-each p x1 x2 x3 "" x4)
        (string-for-each p x1 x2 x3 "" x4 x5)
        (string-for-each p x1 x2 x3 x4 "")
        (string-for-each p x1 x2 x3 x4 "" x5)
        (string-for-each p x1 x2 x3 x4 x5 "")))
    (procedure? $string-for-each-f1))
  (equal?
    (let ([ls '()])
      (define q (lambda args (set! ls (cons (reverse args) ls))))
      ($string-for-each-f1 q "" "" "" "" "")
      (reverse ls))
    '())
  (begin
    (define ($string-for-each-f1 p x1 x2 x3 x4 x5)
      (begin
        (string-for-each p "a")
        (string-for-each p "a" x1)
        (string-for-each p "a" x1 x2)
        (string-for-each p "a" x1 x2 x3)
        (string-for-each p "a" x1 x2 x3 x4)
        (string-for-each p "a" x1 x2 x3 x4 x5)
        (string-for-each p x1 "a")
        (string-for-each p x1 "a" x2)
        (string-for-each p x1 "a" x2 x3)
        (string-for-each p x1 "a" x2 x3 x4)
        (string-for-each p x1 "a" x2 x3 x4 x5)
        (string-for-each p x1 x2 "a")
        (string-for-each p x1 x2 "a" x3)
        (string-for-each p x1 x2 "a" x3 x4)
        (string-for-each p x1 x2 "a" x3 x4 x5)
        (string-for-each p x1 x2 x3 "a")
        (string-for-each p x1 x2 x3 "a" x4)
        (string-for-each p x1 x2 x3 "a" x4 x5)
        (string-for-each p x1 x2 x3 x4 "a")
        (string-for-each p x1 x2 x3 x4 "a" x5)
        (string-for-each p x1 x2 x3 x4 x5 "a")))
    (procedure? $string-for-each-f1))
  (equal?
    (let ([ls '()])
      (define q (lambda args (set! ls (cons (reverse args) ls))))
      ($string-for-each-f1 q "1" "f" "k" "p" "u")
      (map list->string (reverse ls)))
    '("a" "1a" "f1a" "kf1a" "pkf1a" "upkf1a" "a1" "fa1"
      "kfa1" "pkfa1" "upkfa1" "af1" "kaf1" "pkaf1" "upkaf1"
      "akf1" "pakf1" "upakf1" "apkf1" "uapkf1" "aupkf1"))
  (begin
    (define ($string-for-each-f1 p x1 x2 x3 x4 x5)
      (begin
        (string-for-each p "ab")
        (string-for-each p "ab" x1)
        (string-for-each p "ab" x1 x2)
        (string-for-each p "ab" x1 x2 x3)
        (string-for-each p "ab" x1 x2 x3 x4)
        (string-for-each p "ab" x1 x2 x3 x4 x5)
        (string-for-each p x1 "ab")
        (string-for-each p x1 "ab" x2)
        (string-for-each p x1 "ab" x2 x3)
        (string-for-each p x1 "ab" x2 x3 x4)
        (string-for-each p x1 "ab" x2 x3 x4 x5)
        (string-for-each p x1 x2 "ab")
        (string-for-each p x1 x2 "ab" x3)
        (string-for-each p x1 x2 "ab" x3 x4)
        (string-for-each p x1 x2 "ab" x3 x4 x5)
        (string-for-each p x1 x2 x3 "ab")
        (string-for-each p x1 x2 x3 "ab" x4)
        (string-for-each p x1 x2 x3 "ab" x4 x5)
        (string-for-each p x1 x2 x3 x4 "ab")
        (string-for-each p x1 x2 x3 x4 "ab" x5)
        (string-for-each p x1 x2 x3 x4 x5 "ab")))
    (procedure? $string-for-each-f1))
  (equal?
    (let ([ls '()])
      (define q (lambda args (set! ls (cons (reverse args) ls))))
      ($string-for-each-f1 q "12" "fg" "kl" "pq" "uv")
      (map list->string (reverse ls)))
    '("a" "b" "1a" "2b" "f1a" "g2b" "kf1a" "lg2b" "pkf1a"
      "qlg2b" "upkf1a" "vqlg2b" "a1" "b2" "fa1" "gb2" "kfa1"
      "lgb2" "pkfa1" "qlgb2" "upkfa1" "vqlgb2" "af1" "bg2"
      "kaf1" "lbg2" "pkaf1" "qlbg2" "upkaf1" "vqlbg2" "akf1"
      "blg2" "pakf1" "qblg2" "upakf1" "vqblg2" "apkf1"
      "bqlg2" "uapkf1" "vbqlg2" "aupkf1" "bvqlg2"))
  (begin
    (define ($string-for-each-f1 p x1 x2 x3 x4 x5)
      (begin
        (string-for-each p "abc")
        (string-for-each p "abc" x1)
        (string-for-each p "abc" x1 x2)
        (string-for-each p "abc" x1 x2 x3)
        (string-for-each p "abc" x1 x2 x3 x4)
        (string-for-each p "abc" x1 x2 x3 x4 x5)
        (string-for-each p x1 "abc")
        (string-for-each p x1 "abc" x2)
        (string-for-each p x1 "abc" x2 x3)
        (string-for-each p x1 "abc" x2 x3 x4)
        (string-for-each p x1 "abc" x2 x3 x4 x5)
        (string-for-each p x1 x2 "abc")
        (string-for-each p x1 x2 "abc" x3)
        (string-for-each p x1 x2 "abc" x3 x4)
        (string-for-each p x1 x2 "abc" x3 x4 x5)
        (string-for-each p x1 x2 x3 "abc")
        (string-for-each p x1 x2 x3 "abc" x4)
        (string-for-each p x1 x2 x3 "abc" x4 x5)
        (string-for-each p x1 x2 x3 x4 "abc")
        (string-for-each p x1 x2 x3 x4 "abc" x5)
        (string-for-each p x1 x2 x3 x4 x5 "abc")))
    (procedure? $string-for-each-f1))
  (equal?
    (let ([ls '()])
      (define q (lambda args (set! ls (cons (reverse args) ls))))
      ($string-for-each-f1 q "123" "fgh" "klm" "pqr" "uvw")
      (map list->string (reverse ls)))
    '("a" "b" "c" "1a" "2b" "3c" "f1a" "g2b" "h3c" "kf1a"
      "lg2b" "mh3c" "pkf1a" "qlg2b" "rmh3c" "upkf1a" "vqlg2b"
      "wrmh3c" "a1" "b2" "c3" "fa1" "gb2" "hc3" "kfa1" "lgb2"
      "mhc3" "pkfa1" "qlgb2" "rmhc3" "upkfa1" "vqlgb2"
      "wrmhc3" "af1" "bg2" "ch3" "kaf1" "lbg2" "mch3" "pkaf1"
      "qlbg2" "rmch3" "upkaf1" "vqlbg2" "wrmch3" "akf1"
      "blg2" "cmh3" "pakf1" "qblg2" "rcmh3" "upakf1" "vqblg2"
      "wrcmh3" "apkf1" "bqlg2" "crmh3" "uapkf1" "vbqlg2"
      "wcrmh3" "aupkf1" "bvqlg2" "cwrmh3"))
  (begin
    (define ($string-for-each-f1 p x1 x2 x3 x4 x5)
      (begin
        (string-for-each p "abcd")
        (string-for-each p "abcd" x1)
        (string-for-each p "abcd" x1 x2)
        (string-for-each p "abcd" x1 x2 x3)
        (string-for-each p "abcd" x1 x2 x3 x4)
        (string-for-each p "abcd" x1 x2 x3 x4 x5)
        (string-for-each p x1 "abcd")
        (string-for-each p x1 "abcd" x2)
        (string-for-each p x1 "abcd" x2 x3)
        (string-for-each p x1 "abcd" x2 x3 x4)
        (string-for-each p x1 "abcd" x2 x3 x4 x5)
        (string-for-each p x1 x2 "abcd")
        (string-for-each p x1 x2 "abcd" x3)
        (string-for-each p x1 x2 "abcd" x3 x4)
        (string-for-each p x1 x2 "abcd" x3 x4 x5)
        (string-for-each p x1 x2 x3 "abcd")
        (string-for-each p x1 x2 x3 "abcd" x4)
        (string-for-each p x1 x2 x3 "abcd" x4 x5)
        (string-for-each p x1 x2 x3 x4 "abcd")
        (string-for-each p x1 x2 x3 x4 "abcd" x5)
        (string-for-each p x1 x2 x3 x4 x5 "abcd")))
    (procedure? $string-for-each-f1))
  (equal?
    (let ([ls '()])
      (define q (lambda args (set! ls (cons (reverse args) ls))))
      ($string-for-each-f1 q "1234" "fghi" "klmn" "pqrs" "uvwx")
      (map list->string (reverse ls)))
    '("a" "b" "c" "d" "1a" "2b" "3c" "4d" "f1a" "g2b" "h3c"
      "i4d" "kf1a" "lg2b" "mh3c" "ni4d" "pkf1a" "qlg2b"
      "rmh3c" "sni4d" "upkf1a" "vqlg2b" "wrmh3c" "xsni4d"
      "a1" "b2" "c3" "d4" "fa1" "gb2" "hc3" "id4" "kfa1"
      "lgb2" "mhc3" "nid4" "pkfa1" "qlgb2" "rmhc3" "snid4"
      "upkfa1" "vqlgb2" "wrmhc3" "xsnid4" "af1" "bg2" "ch3"
      "di4" "kaf1" "lbg2" "mch3" "ndi4" "pkaf1" "qlbg2"
      "rmch3" "sndi4" "upkaf1" "vqlbg2" "wrmch3" "xsndi4"
      "akf1" "blg2" "cmh3" "dni4" "pakf1" "qblg2" "rcmh3"
      "sdni4" "upakf1" "vqblg2" "wrcmh3" "xsdni4" "apkf1"
      "bqlg2" "crmh3" "dsni4" "uapkf1" "vbqlg2" "wcrmh3"
      "xdsni4" "aupkf1" "bvqlg2" "cwrmh3" "dxsni4"))
  (begin
    (define ($string-for-each-f1 p x1 x2 x3 x4 x5)
      (begin
        (string-for-each p "abcde")
        (string-for-each p "abcde" x1)
        (string-for-each p "abcde" x1 x2)
        (string-for-each p "abcde" x1 x2 x3)
        (string-for-each p "abcde" x1 x2 x3 x4)
        (string-for-each p "abcde" x1 x2 x3 x4 x5)
        (string-for-each p x1 "abcde")
        (string-for-each p x1 "abcde" x2)
        (string-for-each p x1 "abcde" x2 x3)
        (string-for-each p x1 "abcde" x2 x3 x4)
        (string-for-each p x1 "abcde" x2 x3 x4 x5)
        (string-for-each p x1 x2 "abcde")
        (string-for-each p x1 x2 "abcde" x3)
        (string-for-each p x1 x2 "abcde" x3 x4)
        (string-for-each p x1 x2 "abcde" x3 x4 x5)
        (string-for-each p x1 x2 x3 "abcde")
        (string-for-each p x1 x2 x3 "abcde" x4)
        (string-for-each p x1 x2 x3 "abcde" x4 x5)
        (string-for-each p x1 x2 x3 x4 "abcde")
        (string-for-each p x1 x2 x3 x4 "abcde" x5)
        (string-for-each p x1 x2 x3 x4 x5 "abcde")))
    (procedure? $string-for-each-f1))
  (equal?
    (let ([ls '()])
      (define q (lambda args (set! ls (cons (reverse args) ls))))
      ($string-for-each-f1 q "12345" "fghij" "klmno" "pqrst" "uvwxy")
      (map list->string (reverse ls)))
    '("a" "b" "c" "d" "e" "1a" "2b" "3c" "4d" "5e" "f1a"
      "g2b" "h3c" "i4d" "j5e" "kf1a" "lg2b" "mh3c" "ni4d"
      "oj5e" "pkf1a" "qlg2b" "rmh3c" "sni4d" "toj5e" "upkf1a"
      "vqlg2b" "wrmh3c" "xsni4d" "ytoj5e" "a1" "b2" "c3" "d4"
      "e5" "fa1" "gb2" "hc3" "id4" "je5" "kfa1" "lgb2" "mhc3"
      "nid4" "oje5" "pkfa1" "qlgb2" "rmhc3" "snid4" "toje5"
      "upkfa1" "vqlgb2" "wrmhc3" "xsnid4" "ytoje5" "af1"
      "bg2" "ch3" "di4" "ej5" "kaf1" "lbg2" "mch3" "ndi4"
      "oej5" "pkaf1" "qlbg2" "rmch3" "sndi4" "toej5" "upkaf1"
      "vqlbg2" "wrmch3" "xsndi4" "ytoej5" "akf1" "blg2"
      "cmh3" "dni4" "eoj5" "pakf1" "qblg2" "rcmh3" "sdni4"
      "teoj5" "upakf1" "vqblg2" "wrcmh3" "xsdni4" "yteoj5"
      "apkf1" "bqlg2" "crmh3" "dsni4" "etoj5" "uapkf1"
      "vbqlg2" "wcrmh3" "xdsni4" "yetoj5" "aupkf1" "bvqlg2"
      "cwrmh3" "dxsni4" "eytoj5"))
 ; check for proper tail recursion
   (equal?
     (list
       (let ([s (statistics)])
         (let ([k 100000] [str "abc"])
           (let ([n k] [m 0])
             (define (f) (unless (fx= n 0) (string-for-each foo str)))
             (define (foo x)
               (set! m (+ m 1))
               (when (char=? x (string-ref str (fx- (string-length str) 1)))
                 (set! n (- n 1))
                 (f)
                 17)) ; blow tail recursion here
             (f)
             (list (> (sstats-bytes (sstats-difference (statistics) s))
                      10000)
                   (eqv? n 0)
                   (eqv? m (* k (string-length str)))))))
       (let ([s (statistics)])
         (let ([k 100000] [str "abc"])
           (let ([n k] [m 0])
             (define (f) (unless (fx= n 0) (string-for-each foo str)))
             (define (foo x)
               (set! m (+ m 1))
               (when (char=? x (string-ref str (fx- (string-length str) 1)))
                 (set! n (- n 1))
                 (f)))
             (f)
             (list (<= 0
                      (sstats-bytes (sstats-difference (statistics) s))
                      1000)
                   (eqv? n 0)
                   (eqv? m (* k (string-length str))))))))
     '((#t #t #t) (#t #t #t)))
 )

(mat string-xcase-errors
  (error? (string-upcase))
  (error? (string-upcase "hello" "goodbye"))
  (error? (string-upcase 'ouch))
  (error? (string-downcase))
  (error? (string-downcase "hello" "goodbye"))
  (error? (string-downcase 'ouch))
  (error? (string-titlecase))
  (error? (string-titlecase "hello" "goodbye"))
  (error? (string-titlecase 'ouch))
  (error? (string-foldcase))
  (error? (string-foldcase "hello" "goodbye"))
  (error? (string-foldcase 'ouch))
)

(mat normalization-tests
  (error? (string-normalize-nfd))
  (error? (string-normalize-nfd "hello" "goodbye"))
  (error? (string-normalize-nfd 'ouch))
  (error? (string-normalize-nfkd))
  (error? (string-normalize-nfkd "hello" "goodbye"))
  (error? (string-normalize-nfkd 'ouch))
  (error? (string-normalize-nfc))
  (error? (string-normalize-nfc "hello" "goodbye"))
  (error? (string-normalize-nfc 'ouch))
  (error? (string-normalize-nfkc))
  (error? (string-normalize-nfkc "hello" "goodbye"))
  (error? (string-normalize-nfkc 'ouch))
  (begin
    (load (find-source "../unicode/unicode-data.ss"))
    #t)
  (let ()
    (import (unicode-data))
    (define (split str)
      (remove ""
        (let f ([i 0] [n (string-length str)])
          (cond
            [(= i n) (list (substring str 0 n))]
            [(char=? (string-ref str i) #\space)
             (cons (substring str 0 i) 
                   (split (substring str (+ i 1) n)))]
            [else (f (add1 i) n)]))))

    (define (conv x)
      (list->string
        (map (lambda (x) (integer->char (string->number x 16)))
             (split x))))

    (let ([data (map (lambda (x) (map conv (list-head x 5)))
                     (filter (lambda (x) (>= (length x) 5))
                       (get-unicode-data
                         (find-source "../unicode/UNIDATA/NormalizationTest.txt"))))])
      (define NFD string-normalize-nfd)
      (define NFKD string-normalize-nfkd)
      (define NFC string-normalize-nfc)
      (define NFKC string-normalize-nfkc)

      (printf "found ~s tests\n" (length data))

     ; test 1
      (for-each
        (lambda (x testno)
          (apply
            (lambda (c1 c2 c3 c4 c5)
              (unless (and (string=? c2 (NFC c1) (NFC c2) (NFC c3))
                           (string=? c4 (NFC c4) (NFC c5)))
                (parameterize ([print-unicode #f])
                  (printf "test 1[~s] failed for ~s\n" testno x)
                  (printf "       c2 = ~s\n" c2)
                  (printf "  NFC(c1) = ~s\n" (NFC c1))
                  (printf "  NFC(c2) = ~s\n" (NFC c2))
                  (printf "  NFC(c3) = ~s\n" (NFC c3))
                  (printf "       c4 = ~s\n" c4)
                  (printf "  NFC(c4) = ~s\n" (NFC c4))
                  (printf "  NFC(c5) = ~s\n" (NFC c5))
                  (errorf #f "test 1 failed: see make output"))))
            x))
        data (enumerate data))

     ; test 2
      (for-each
        (lambda (x testno)
          (apply
            (lambda (c1 c2 c3 c4 c5)
              (unless (and (string=? c3 (NFD c1) (NFD c2) (NFD c3))
                           (string=? c5 (NFD c4) (NFD c5)))
                (parameterize ([print-unicode #f])
                  (printf "test 2[~s] failed for ~s\n" testno x)
                  (printf "       c3 = ~s\n" c3)
                  (printf "  NFD(c1) = ~s\n" (NFD c1))
                  (printf "  NFD(c2) = ~s\n" (NFD c2))
                  (printf "  NFD(c3) = ~s\n" (NFD c3))
                  (printf "       c5 = ~s\n" c5)
                  (printf "  NFD(c4) = ~s\n" (NFD c4))
                  (printf "  NFD(c5) = ~s\n" (NFD c5))
                  (errorf #f "test 2 failed: see make output"))))
            x))
        data (enumerate data))

     ; test 3
      (for-each
        (lambda (x testno)
          (apply
            (lambda (c1 c2 c3 c4 c5)
              (unless (string=? c4 (NFKC c1) (NFKC c2) (NFKC c3) (NFKC c4) (NFKC c5))
                (parameterize ([print-unicode #f])
                  (printf "test 3[~s] failed for ~s\n" testno x)
                  (printf "       c4 = ~s\n" c4)
                  (printf "  NFKC(c1) = ~s\n" (NFKC c1))
                  (printf "  NFKC(c2) = ~s\n" (NFKC c2))
                  (printf "  NFKC(c3) = ~s\n" (NFKC c3))
                  (printf "  NFKC(c4) = ~s\n" (NFKC c4))
                  (printf "  NFKC(c5) = ~s\n" (NFKC c5))
                  (errorf #f "test 3 failed: see make output"))))
            x))
        data (enumerate data))

     ; test 4
      (for-each
        (lambda (x testno)
          (apply
            (lambda (c1 c2 c3 c4 c5)
              (unless (string=? c5 (NFKD c1) (NFKD c2) (NFKD c3) (NFKD c4) (NFKD c5))
                (parameterize ([print-unicode #f])
                  (printf "test 4[~s] failed for ~s\n" testno x)
                  (printf "       c5 = ~s\n" c5)
                  (printf "  NFKD(c1) = ~s\n" (NFKD c1))
                  (printf "  NFKD(c2) = ~s\n" (NFKD c2))
                  (printf "  NFKD(c3) = ~s\n" (NFKD c3))
                  (printf "  NFKD(c4) = ~s\n" (NFKD c4))
                  (printf "  NFKD(c5) = ~s\n" (NFKD c5))
                  (errorf #f "test 4 failed: see make output"))))
            x))
        data (enumerate data)))
    #t)
 )

(mat r6rs-unicode-tests ; from Flatt's R6RS test suite
  (begin
    (define test equal?)
    (test test equal?))

  (test (char-upcase #\i) #\I)
  (test (char-downcase #\i) #\i)
  (test (char-titlecase #\i) #\I)
  (test (char-foldcase #\i) #\i)
  
  (test (char-upcase #\xDF) #\xDF)
  (test (char-downcase #\xDF) #\xDF)
  (test (char-titlecase #\xDF) #\xDF)
  (test (char-foldcase #\xDF) #\xDF)
  
  (test (char-upcase #\x3A3) #\x3A3)
  (test (char-downcase #\x3A3) #\x3C3)
  (test (char-titlecase #\x3A3) #\x3A3)
  (test (char-foldcase #\x3A3) #\x3C3)

  (test (char-upcase #\x3C2) #\x3A3)
  (test (char-downcase #\x3C2) #\x3C2)
  (test (char-titlecase #\x3C2) #\x3A3)
  (test (char-foldcase #\x3C2) #\x3C3)

  (test (char-ci<? #\z #\Z) #f)
  (test (char-ci<? #\Z #\z) #f)
  (test (char-ci<? #\a #\Z) #t)
  (test (char-ci<? #\Z #\a) #f)
  (test (char-ci<=? #\z #\Z) #t)
  (test (char-ci<=? #\Z #\z) #t)
  (test (char-ci<=? #\a #\Z) #t)
  (test (char-ci<=? #\Z #\a) #f)
  (test (char-ci=? #\z #\a) #f)
  (test (char-ci=? #\z #\Z) #t)
  (test (char-ci=? #\x3C2 #\x3C3) #t)
  (test (char-ci>? #\z #\Z) #f)
  (test (char-ci>? #\Z #\z) #f)
  (test (char-ci>? #\a #\Z) #f)
  (test (char-ci>? #\Z #\a) #t)
  (test (char-ci>=? #\Z #\z) #t)
  (test (char-ci>=? #\z #\Z) #t)
  (test (char-ci>=? #\z #\Z) #t)
  (test (char-ci>=? #\a #\z) #f)

  (test (char-alphabetic? #\a) #t)
  (test (char-alphabetic? #\1) #f)
  (test (char-numeric? #\1) #t)
  (test (char-numeric? #\a) #f)
  (test (char-whitespace? #\space) #t)
  (test (char-whitespace? #\x00A0) #t)
  (test (char-whitespace? #\a) #f)
  (test (char-upper-case? #\a) #f)
  (test (char-upper-case? #\A) #t)
  (test (char-upper-case? #\x3A3) #t)
  (test (char-lower-case? #\a) #t)
  (test (char-lower-case? #\A) #f)
  (test (char-lower-case? #\x3C3) #t)
  (test (char-lower-case? #\x00AA) #t)
  (test (char-title-case? #\a) #f)
  (test (char-title-case? #\A) #f)
  (test (char-title-case? #\I) #f)
  (test (char-title-case? #\x01C5) #t)

  (test (char-general-category #\a) 'Ll)
  (test (char-general-category #\space) 'Zs)
  (test (char-general-category #\x10FFFF) 'Cn)

  (test (string-upcase "Hi") "HI")
  (test (string-upcase "HI") "HI")
  (test (string-downcase "Hi") "hi")
  (test (string-downcase "hi") "hi")
  (test (string-foldcase "Hi") "hi")
  (test (string-foldcase "HI") "hi")
  (test (string-foldcase "hi") "hi")

  (test (string-upcase "Stra\xDF;e") "STRASSE")
  (test (string-downcase "Stra\xDF;e") "stra\xDF;e")
  (test (string-foldcase "Stra\xDF;e") "strasse")
  (test (string-downcase "STRASSE")  "strasse")
  
  (test (string-downcase "\x3A3;") "\x3C3;")

  (test (string-upcase "\x39E;\x391;\x39F;\x3A3;") "\x39E;\x391;\x39F;\x3A3;")
  (test (string-downcase "\x39E;\x391;\x39F;\x3A3;") "\x3BE;\x3B1;\x3BF;\x3C2;")
  (test (string-downcase "\x39E;\x391;\x39F;\x3A3;\x3A3;") "\x3BE;\x3B1;\x3BF;\x3C3;\x3C2;")
  (test (string-downcase "\x39E;\x391;\x39F;\x3A3; \x3A3;") "\x3BE;\x3B1;\x3BF;\x3C2; \x3C3;")
  (test (string-foldcase "\x39E;\x391;\x39F;\x3A3;") "\x3BE;\x3B1;\x3BF;\x3C3;")
  (test (string-upcase "\x3BE;\x3B1;\x3BF;\x3C3;") "\x39E;\x391;\x39F;\x3A3;") 
  (test (string-upcase "\x3BE;\x3B1;\x3BF;\x3C2;") "\x39E;\x391;\x39F;\x3A3;") 

  (test (string-titlecase "kNock KNoCK") "Knock Knock")
  (test (string-titlecase "who's there?") "Who's There?")
  (test (string-titlecase "r6rs") "R6rs") ; this example appears to be wrong in R6RS (Sept 2007 version)
  (test (string-titlecase "R6RS") "R6rs") ; this one, too

  (test (string-titlecase "stra \xDF;e") "Stra Sse")
  (test (string-titlecase "one \xFB00;e") "One Ffe")
  (test (string-titlecase "one\xFB00;e") "One\xFB00;e")

  (test (string-downcase "A\x3A3;'x") "a\x3C3;'x") ; ' is a MidLetter

  (test (string-ci<? "a" "Z") #t)
  (test (string-ci<? "A" "z") #t)
  (test (string-ci<? "Z" "a") #f)
  (test (string-ci<? "z" "A") #f)
  (test (string-ci<? "z" "Z") #f)
  (test (string-ci<? "Z" "z") #f)
  (test (string-ci>? "a" "Z") #f)
  (test (string-ci>? "A" "z") #f)
  (test (string-ci>? "Z" "a") #t)
  (test (string-ci>? "z" "A") #t)
  (test (string-ci>? "z" "Z") #f)
  (test (string-ci>? "Z" "z") #f)
  (test (string-ci=? "z" "Z") #t)
  (test (string-ci=? "z" "a") #f)
  (test (string-ci=? "Stra\xDF;e" "Strasse") #t)
  (test (string-ci=? "Stra\xDF;e" "STRASSE") #t)
  (test (string-ci=? "\x39E;\x391;\x39F;\x3A3;" "\x3BE;\x3B1;\x3BF;\x3C2;") #t)
  (test (string-ci=? "\x39E;\x391;\x39F;\x3A3;" "\x3BE;\x3B1;\x3BF;\x3C3;") #t)
  (test (string-ci<=? "a" "Z") #t)
  (test (string-ci<=? "A" "z") #t)
  (test (string-ci<=? "Z" "a") #f)
  (test (string-ci<=? "z" "A") #f)
  (test (string-ci<=? "z" "Z") #t)
  (test (string-ci<=? "Z" "z") #t)
  (test (string-ci>=? "a" "Z") #f)
  (test (string-ci>=? "A" "z") #f)
  (test (string-ci>=? "Z" "a") #t)
  (test (string-ci>=? "z" "A") #t)
  (test (string-ci>=? "z" "Z") #t)
  (test (string-ci>=? "Z" "z") #t)

  (test (string-normalize-nfd "\xE9;") "\x65;\x301;")
  (test (string-normalize-nfc "\xE9;") "\xE9;")
  (test (string-normalize-nfd "\x65;\x301;") "\x65;\x301;")
  (test (string-normalize-nfc "\x65;\x301;") "\xE9;")

  (test (string-normalize-nfkd "\xE9;") "\x65;\x301;")
  (test (string-normalize-nfkc "\xE9;") "\xE9;")
  (test (string-normalize-nfkd "\x65;\x301;") "\x65;\x301;")
  (test (string-normalize-nfkc "\x65;\x301;") "\xE9;")
 )

(mat unicode-tests.sch ; adapted from Clinger's unicode-tests.sch
  ; Copyright 2006 William D Clinger.
  ;
  ; Permission to copy this software, in whole or in part, to use this
  ; software for any lawful purpose, and to redistribute this software
  ; is granted subject to the restriction that all copies made of this
  ; software must include this copyright and permission notice in full.
  ;
  ; I also request that you send me a copy of any improvements that you
  ; make to this software so that they may be incorporated within it to
  ; the benefit of the Scheme community.

  (begin
    (define es-zed (integer->char #x00df))
    (define final-sigma (integer->char #x03c2))
    (define lower-sigma (integer->char #x03c3))
    (define upper-sigma (integer->char #x03a3))
    (define upper-chi (integer->char #x03a7))
    (define upper-alpha (integer->char #x0391))
    (define upper-omicron (integer->char #x039f))
    (define lower-chi (integer->char #x03c7))
    (define lower-alpha (integer->char #x03b1))
    (define lower-omicron (integer->char #x03bf))
    (define strasse (string #\S #\t #\r #\a es-zed #\e))
    (define upper-chaos (string upper-chi upper-alpha upper-omicron upper-sigma))
    (define final-chaos (string lower-chi lower-alpha lower-omicron final-sigma))
    (define lower-chaos (string lower-chi lower-alpha lower-omicron lower-sigma))
   ; Given a unary predicate on characters, returns a sorted
   ; list of all characters that satisfy the predicate.
    (define (filter-all-chars p?)
      (do ((i 0 (+ i 1))
           (chars '()
                  (if (and (not (<= #xd800 i #xdfff))
                           (p? (integer->char i)))
                      (cons (integer->char i) chars)
                      chars)))
          ((= i #x110000)
           (reverse chars))))
   ; Given a list of characters, prints its length and returns 0.
    (define (report chars n)
      (display "  ")
      (display (length chars))
      (display " characters")
      (if (not (= n (length chars)))
          (begin (display " but expected ")
                 (write n)
                 (display " in Unicode 15.1")))
      (newline)
      0)
    (define-syntax test
      (syntax-rules (=> error)
        [(test name exp => result)
         (equal? exp result)]))
   ; According to SRFI 77, this is a complete list of all code points
   ; above 127 in Unicode 4.1 whose Unicode general category is
   ; Ps, Pe, Pi, Pf, Zs, Zp, Zl, Cc, or Cf.
   ;
   ; In Unicode 5.0, the general category of
   ; #\x23B4 (TOP SQUARE BRACKET)
   ; and
   ; #\x23B5 (BOTTOM SQUARE BRACKET)
   ; was changed from Ps and Pe to So.
   ; rkd: Unicode 5.1 adds
   ; #x2064 #x27EC #x27ED #x27EE #x27EF #x2E20 #x2E21 #x2E22
   ; #x2E23 #x2E24 #x2E25 #x2E26 #x2E27 #x2E28 #x2E29
   ; rkd: Unicode 7.0 adds:
   ; #x604 #x605 #x61C #x2066 #x2067 #x2068 #x2069 #x2308 #x2309
   ; #x230A #x230B #x2E42 #x110BD #x1BCA0 #x1BCA1 #x1BCA2 #x1BCA3
   ; rkd: Unicode 7.0 removes:
   ; #x17B4 #x17B5
   ; Unicode 14.0 adds:
   ; #x890 #x891 #x8E2 #x2E55 #x2E56 #x2E57 #x2E58 #x2E59 #x2E5A
   ; #x2E5B #x2E5C #x110CD #x13430 #x13431 #x13432 #x13433 #x13434
   ; #x13435 #x13436 #x13437 #x13438
    (define excluded-code-points-above-127
      '(
    
     #x80 #x81 #x82 #x83 #x84 #x85 #x86 #x87 #x88 #x89
     #x8A #x8B #x8C #x8D #x8E #x8F #x90 #x91 #x92 #x93
     #x94 #x95 #x96 #x97 #x98 #x99 #x9A #x9B #x9C #x9D
     #x9E #x9F #xA0 #xAB #xAD #xBB #x600 #x601 #x602 #x603
     #x604 #x605 #x61C                                       ; Unicode 7.0
     #x6DD #x70F
     #x890 #x891 #x8E2                                       ; Unicode 14.0
     #xF3A #xF3B #xF3C #xF3D #x1680 #x169B #x169C
     #;#x17B4 #;#x17B5                                       ; Unicode 7.0
     #x180E #x2000 #x2001 #x2002 #x2003
     #x2004 #x2005 #x2006 #x2007 #x2008 #x2009 #x200A #x200B
     #x200C #x200D #x200E #x200F #x2018 #x2019 #x201A #x201B
     #x201C #x201D #x201E #x201F #x2028 #x2029 #x202A #x202B
     #x202C #x202D #x202E #x202F #x2039 #x203A #x2045 #x2046
     #x205F #x2060 #x2061 #x2062 #x2063
     #x2064                                                  ; Unicode 5.1
     #x2066 #x2067 #x2068 #x2069                             ; Unicode 7.0
     #x206A #x206B #x206C
     #x206D #x206E #x206F #x207D #x207E #x208D #x208E
     #x2308 #x2309 #x230A #x230B                             ; Unicode 7.0
     #x2329 #x232A 
    ;       #x23B4 #x23B5 ; see note above for Unicode 5.0
                          #x2768 #x2769 #x276A #x276B #x276C
     #x276D #x276E #x276F #x2770 #x2771 #x2772 #x2773 #x2774
     #x2775 #x27C5 #x27C6 #x27E6 #x27E7 #x27E8 #x27E9 #x27EA
     #x27EB 
     #x27EC #x27ED #x27EE #x27EF                             ; Unicode 5.1
     #x2983 #x2984 #x2985 #x2986 #x2987 #x2988 #x2989
     #x298A #x298B #x298C #x298D #x298E #x298F #x2990 #x2991
     #x2992 #x2993 #x2994 #x2995 #x2996 #x2997 #x2998 #x29D8
     #x29D9 #x29DA #x29DB #x29FC #x29FD #x2E02 #x2E03 #x2E04
     #x2E05 #x2E09 #x2E0A #x2E0C #x2E0D #x2E1C #x2E1D
     #x2E20 #x2E21 #x2E22 #x2E23 #x2E24 #x2E25 #x2E26 #x2E27 ; Unicode 5.1
     #x2E28 #x2E29                                           ; Unicode 5.1
     #x2E42                                                  ; Unicode 7.0
     #x2E55 #x2E56 #x2E57 #x2E58 #x2E59 #x2E5A #x2E5B #x2E5C ; Unicode 14.0
     #x3000
     #x3008 #x3009 #x300A #x300B #x300C #x300D #x300E #x300F
     #x3010 #x3011 #x3014 #x3015 #x3016 #x3017 #x3018 #x3019
     #x301A #x301B #x301D #x301E #x301F #xFD3E #xFD3F #xFE17
     #xFE18 #xFE35 #xFE36 #xFE37 #xFE38 #xFE39 #xFE3A #xFE3B
     #xFE3C #xFE3D #xFE3E #xFE3F #xFE40 #xFE41 #xFE42 #xFE43
     #xFE44 #xFE47 #xFE48 #xFE59 #xFE5A #xFE5B #xFE5C #xFE5D
     #xFE5E #xFEFF #xFF08 #xFF09 #xFF3B #xFF3D #xFF5B #xFF5D
     #xFF5F #xFF60 #xFF62 #xFF63 #xFFF9 #xFFFA #xFFFB
     #x110BD                                                 ; Unicode 7.0
     #x110CD #x13430 #x13431 #x13432 #x13433 #x13434 #x13435 ; Unicode 14.0
     #x13436 #x13437 #x13438                                 ; Unicode 14.0
     #x13439 #x1343A #x1343B #x1343C #x1343D #x1343E #x1343F ; Unicode 15.0
     #x1BCA0 #x1BCA1 #x1BCA2 #x1BCA3                         ; Unicode 7.0
     #x1D173
     #x1D174 #x1D175 #x1D176 #x1D177 #x1D178 #x1D179 #x1D17A
     #xE0001 #xE0020 #xE0021 #xE0022 #xE0023 #xE0024 #xE0025
     #xE0026 #xE0027 #xE0028 #xE0029 #xE002A #xE002B #xE002C
     #xE002D #xE002E #xE002F #xE0030 #xE0031 #xE0032 #xE0033
     #xE0034 #xE0035 #xE0036 #xE0037 #xE0038 #xE0039 #xE003A
     #xE003B #xE003C #xE003D #xE003E #xE003F #xE0040 #xE0041
     #xE0042 #xE0043 #xE0044 #xE0045 #xE0046 #xE0047 #xE0048
     #xE0049 #xE004A #xE004B #xE004C #xE004D #xE004E #xE004F
     #xE0050 #xE0051 #xE0052 #xE0053 #xE0054 #xE0055 #xE0056
     #xE0057 #xE0058 #xE0059 #xE005A #xE005B #xE005C #xE005D
     #xE005E #xE005F #xE0060 #xE0061 #xE0062 #xE0063 #xE0064
     #xE0065 #xE0066 #xE0067 #xE0068 #xE0069 #xE006A #xE006B
     #xE006C #xE006D #xE006E #xE006F #xE0070 #xE0071 #xE0072
     #xE0073 #xE0074 #xE0075 #xE0076 #xE0077 #xE0078 #xE0079
     #xE007A #xE007B #xE007C #xE007D #xE007E #xE007F))
   #t)

  (test type1 (integer->char 32) => #\space)
  (test type2 (char->integer (integer->char 5000)) => 5000)
  ;(test type3 (integer->char #xd800) => error)

  (test comp1 (char<? #\z es-zed) => #t)
  (test comp2 (char<? #\z #\Z) => #f)
  (test comp3 (char-ci<? #\z #\Z) => #f)
  (test comp4 (char-ci=? #\z #\Z) => #t)
  (test comp5 (char-ci=? final-sigma lower-sigma) => #t)

  (test case1 (char-upcase #\i) => #\I)
  (test case2 (char-downcase #\i) => #\i)
  (test case3 (char-titlecase #\i) => #\I)
  (test case4 (char-foldcase #\i) => #\i)

  (test case5 (char-upcase es-zed) => es-zed)
  (test case6 (char-downcase es-zed) => es-zed)
  (test case7 (char-titlecase es-zed) => es-zed)
  (test case8 (char-foldcase es-zed) => es-zed)

  (test case9 (char-upcase upper-sigma) => upper-sigma)
  (test case10 (char-downcase upper-sigma) => lower-sigma)
  (test case11 (char-titlecase upper-sigma) => upper-sigma)
  (test case12 (char-foldcase upper-sigma) => lower-sigma)

  (test case13 (char-upcase final-sigma) => upper-sigma)
  (test case14 (char-downcase final-sigma) => final-sigma)
  (test case15 (char-titlecase final-sigma) => upper-sigma)
  (test case16 (char-foldcase final-sigma) => lower-sigma)

  (test cat1 (char-general-category #\a) => 'Ll)
  (test cat2 (char-general-category #\space) => 'Zs)
  (test cat3 (char-general-category (integer->char #x10FFFF)) => 'Cn)
  (test cat4 (char-general-category #\x31EF) => 'So) ; Unicode 15.1

  (test alpha1 (char-alphabetic? #\a) => #t)
  (test numer1 (char-numeric? #\1) => #t)
  (test white1 (char-whitespace? #\space) => #t)
  (test white2 (char-whitespace? (integer->char #x00A0)) => #t)
  (test upper1 (char-upper-case? upper-sigma) => #t)
  (test lower1 (char-lower-case? lower-sigma) => #t)
  (test lower2 (char-lower-case? (integer->char #x00AA)) => #t)
  (test title1 (char-title-case? #\I) => #f)
  (test title2 (char-title-case? (integer->char #x01C5)) => #t)

  ; 01/30/15 rkd: modified to print the exceptions
  (test excluded
        (let f ((i 128) (excluded excluded-code-points-above-127) (okay? #t))
          (if (= i #x110000)
              okay?
              (if (and (not (null? excluded)) (> i (car excluded)))
                  (begin
                    (printf "missed excluded char \\x~x\n" (car excluded))
                    (f i (cdr excluded) #f))
                  (let ([excluded? (and (not (<= #xd800 i #xdfff))
                                        (memq (char-general-category (integer->char i))
                                          '(Ps Pe Pi Pf Zs Zp Zl Cc Cf)))])
                    (if excluded?
                        (if (and (not (null? excluded)) (eqv? i (car excluded)))
                            (f (+ i 1) (cdr excluded) okay?)
                            (begin
                              (printf "excluding non-excluded char \\x~x\n" i)
                              (f (+ i 1) excluded #f)))
                        (f (+ i 1) excluded okay?))))))
        => #t)

  (test upcase
        (filter-all-chars (lambda (c) (char-upcase c) #f))
        => '())

  (test downcase
        (filter-all-chars (lambda (c) (char-downcase c) #f))
        => '())

  (test titlecase
        (filter-all-chars (lambda (c) (char-titlecase c) #f))
        => '())

  (test foldcase
        (filter-all-chars (lambda (c) (char-foldcase c) #f))
        => '())

  (test general-category
        (report (filter-all-chars (lambda (c)
                                    (char-general-category c)))
                1112064)
        => 0)

  (test alphabetic?
        (report (filter-all-chars char-alphabetic?) 137765)
        => 0)

  (test numeric?
        (report (filter-all-chars char-numeric?) 1839)
        => 0)

  (test whitespace?
        (report (filter-all-chars char-whitespace?) 25)
        => 0)

  (test upper-case?
        (report (filter-all-chars char-upper-case?) 1951)
        => 0)

  (test lower-case?
        (report (filter-all-chars char-lower-case?) 2544)
        => 0)

  (test title-case?
        (report (filter-all-chars char-title-case?) 31)
        => 0)

  (test scomp1 (string<? "z" (string es-zed)) => #t)
  (test scomp2 (string<? "z" "zz") => #t)
  (test scomp3 (string<? "z" "Z") => #f)
  (test scomp4 (string=? strasse "Strasse") => #f)

  (test sup1 (string-upcase "Hi") => "HI")
  (test sdown1 (string-downcase "Hi") => "hi")
  (test sfold1 (string-foldcase "Hi") => "hi")

  (test sup2  (string-upcase strasse) => "STRASSE")
  (test sdown2 (string-downcase strasse)
               => (string-append "s" (substring strasse 1 6)))
  (test sfold2 (string-foldcase strasse) => "strasse")
  (test sdown3 (string-downcase "STRASSE")  => "strasse")

  (test chaos1 (string-upcase upper-chaos) => upper-chaos)
  (test chaos2 (string-downcase (string upper-sigma))
               => (string lower-sigma))
  (test chaos3 (string-downcase upper-chaos) => final-chaos)
  (test chaos4 (string-downcase (string-append upper-chaos
                                               (string upper-sigma)))
               => (string-append (substring lower-chaos 0 3)
                                 (string lower-sigma final-sigma)))
  (test chaos5 (string-downcase (string-append upper-chaos
                                               (string #\space
                                                       upper-sigma)))
               => (string-append final-chaos
                                 (string #\space lower-sigma)))
  (test chaos6 (string-foldcase (string-append upper-chaos
                                               (string upper-sigma)))
               => (string-append lower-chaos
                                 (string lower-sigma)))
  (test chaos7 (string-upcase final-chaos) => upper-chaos)
  (test chaos8 (string-upcase lower-chaos) => upper-chaos)

  (test stitle1 (string-titlecase "kNock KNoCK") => "Knock Knock")
  (test stitle2 (string-titlecase "who's there?") => "Who's There?")
  (test stitle3 (string-titlecase "r6rs") => "R6rs")
  (test stitle4 (string-titlecase "R6RS") => "R6rs")

  (test norm1 (string-normalize-nfd (string #\xE9))
              => (string #\x65 #\x301))
  (test norm2 (string-normalize-nfc (string #\xE9))
              => (string #\xE9))
  (test norm3 (string-normalize-nfd (string #\x65 #\x301))
              => (string #\x65 #\x301))
  (test norm4 (string-normalize-nfc (string #\x65 #\x301))
              => (string #\xE9))

  (test sci1 (string-ci<? "z" "Z") => #f)
  (test sci2 (string-ci=? "z" "Z") => #t)
  (test sci3 (string-ci=? strasse "Strasse") => #t)
  (test sci4 (string-ci=? strasse "STRASSE") => #t)
  (test sci5 (string-ci=? upper-chaos lower-chaos) => #t)

 ; eliminate macro binding for test so it doesn't screw up later mats
  (begin (define test) #t)
)

(mat string-titlecase
  (equal? (string-titlecase "ciao12") "Ciao12")
  (equal? (string-titlecase "ciao123") "Ciao123")
  (equal? (string-titlecase "ciao123 futzmo") "Ciao123 Futzmo")
  (equal? (string-titlecase "ciao123 futzmo.  goobar") "Ciao123 Futzmo.  Goobar")
  (equal? (string-titlecase "ciao123 futzmo.  goob33ar") "Ciao123 Futzmo.  Goob33ar")
  (equal? (string-titlecase "ciao123 futzmo.  33ar") "Ciao123 Futzmo.  33Ar")
)

(mat grapheme
  (error? (string-grapheme-count 'a))
  (error? (string-grapheme-count "a" -1))
  (error? (string-grapheme-count "a" 'a))
  (error? (string-grapheme-count "a" 2))
  (error? (string-grapheme-count "a" 1 0))
  (error? (string-grapheme-count "a" 0 'a))
  (error? (string-grapheme-count "a" 1 2))

  (eqv? 0 (string-grapheme-count ""))
  (eqv? 1 (string-grapheme-count "a"))
  (eqv? 0 (string-grapheme-count "a" 1))
  (eqv? 0 (string-grapheme-count "a" 1 1))
  (eqv? 0 (string-grapheme-count "a" 1 1))

  (error? (string-grapheme-span "a"))
  (error? (string-grapheme-span 'a 0))
  (error? (string-grapheme-span "a" -1))
  (error? (string-grapheme-span "a" 'a))
  (error? (string-grapheme-span "a" 2))
  (error? (string-grapheme-span "a" 1 0))
  (error? (string-grapheme-span "a" 0 'a))
  (error? (string-grapheme-span "a" 1 2))

  (eqv? 0 (string-grapheme-span "" 0))
  (eqv? 1 (string-grapheme-span "a" 0))
  (eqv? 0 (string-grapheme-span "a" 1))
  (eqv? 0 (string-grapheme-span "a" 1 1))
  (eqv? 0 (string-grapheme-span "a" 1 1))

  (error? (char-grapheme-step "a" 0))
  (error? (char-grapheme-step 'a 0))
  (error? (char-grapheme-step #\a #\a))
  (error? (char-grapheme-step #\a (expt 2 100)))

  (let-values ([(consume? state) (char-grapheme-step #\a 0)])
    (and (not consume?)
         (not (eqv? 0 state))))

  (let-values ([(consume? state) (char-grapheme-step #\a 0)])
    (let-values ([(consume? state) (char-grapheme-step #\b state)])
      (and consume?
           (not (eqv? 0 state)))))

  (let-values ([(consume? state) (char-grapheme-step #\x1 0)])
    (and consume?
         (eqv? 0 state)))

  (let-values ([(consume? state) (char-grapheme-step #\a 0)])
    (let-values ([(consume? state) (char-grapheme-step #\x300 state)])
      (and (not consume?)
           (not (eqv? 0 state)))))

  (let ()
    ;; These sequences are from https://www.unicode.org/Public/13.0.0/ucd/auxiliary/GraphemeBreakTest.txt,
    ;; but with one extra marked as "added"
    (define seqs
      '((#x0020 then #x0020)
        (#x0020 and #x0308 then #x0020)
        (#x0020 then #x000D)
        (#x0020 and #x0308 then #x000D)
        (#x0020 then #x000A)
        (#x0020 and #x0308 then #x000A)
        (#x0020 then #x0001)
        (#x0020 and #x0308 then #x0001)
        (#x0020 and #x034F)
        (#x0020 and #x0308 and #x034F)
        (#x0020 then #x1F1E6)
        (#x0020 and #x0308 then #x1F1E6)
        (#x0020 then #x0600)
        (#x0020 and #x0308 then #x0600)
        (#x0020 and #x0903)
        (#x0020 and #x0308 and #x0903)
        (#x0020 then #x1100)
        (#x0020 and #x0308 then #x1100)
        (#x0020 then #x1160)
        (#x0020 and #x0308 then #x1160)
        (#x0020 then #x11A8)
        (#x0020 and #x0308 then #x11A8)
        (#x0020 then #xAC00)
        (#x0020 and #x0308 then #xAC00)
        (#x0020 then #xAC01)
        (#x0020 and #x0308 then #xAC01)
        (#x0020 then #x231A)
        (#x0020 and #x0308 then #x231A)
        (#x0020 and #x0300)
        (#x0020 and #x0308 and #x0300)
        (#x0020 and #x200D)
        (#x0020 and #x0308 and #x200D)
        (#x0020 then #x0378)
        (#x0020 and #x0308 then #x0378)
        (#x000D then #x0020)
        (#x000D then #x0308 then #x0020)
        (#x000D then #x000D)
        (#x000D then #x0308 then #x000D)
        (#x000D and #x000A)
        (#x000D then #x0308 then #x000A)
        (#x000D then #x0001)
        (#x000D then #x0308 then #x0001)
        (#x000D then #x034F)
        (#x000D then #x0308 and #x034F)
        (#x000D then #x1F1E6)
        (#x000D then #x0308 then #x1F1E6)
        (#x000D then #x0600)
        (#x000D then #x0308 then #x0600)
        (#x000D then #x0903)
        (#x000D then #x0308 and #x0903)
        (#x000D then #x1100)
        (#x000D then #x0308 then #x1100)
        (#x000D then #x1160)
        (#x000D then #x0308 then #x1160)
        (#x000D then #x11A8)
        (#x000D then #x0308 then #x11A8)
        (#x000D then #xAC00)
        (#x000D then #x0308 then #xAC00)
        (#x000D then #xAC01)
        (#x000D then #x0308 then #xAC01)
        (#x000D then #x231A)
        (#x000D then #x0308 then #x231A)
        (#x000D then #x0300)
        (#x000D then #x0308 and #x0300)
        (#x000D then #x200D)
        (#x000D then #x0308 and #x200D)
        (#x000D then #x0378)
        (#x000D then #x0308 then #x0378)
        (#x000A then #x0020)
        (#x000A then #x0308 then #x0020)
        (#x000A then #x000D)
        (#x000A then #x0308 then #x000D)
        (#x000A then #x000A)
        (#x000A then #x0308 then #x000A)
        (#x000A then #x0001)
        (#x000A then #x0308 then #x0001)
        (#x000A then #x034F)
        (#x000A then #x0308 and #x034F)
        (#x000A then #x1F1E6)
        (#x000A then #x0308 then #x1F1E6)
        (#x000A then #x0600)
        (#x000A then #x0308 then #x0600)
        (#x000A then #x0903)
        (#x000A then #x0308 and #x0903)
        (#x000A then #x1100)
        (#x000A then #x0308 then #x1100)
        (#x000A then #x1160)
        (#x000A then #x0308 then #x1160)
        (#x000A then #x11A8)
        (#x000A then #x0308 then #x11A8)
        (#x000A then #xAC00)
        (#x000A then #x0308 then #xAC00)
        (#x000A then #xAC01)
        (#x000A then #x0308 then #xAC01)
        (#x000A then #x231A)
        (#x231A then #x000A then #x231A) ; added
        (#x000A then #x0308 then #x231A)
        (#x000A then #x0300)
        (#x000A then #x0308 and #x0300)
        (#x000A then #x200D)
        (#x000A then #x0308 and #x200D)
        (#x000A then #x0378)
        (#x000A then #x0308 then #x0378)
        (#x0001 then #x0020)
        (#x0001 then #x0308 then #x0020)
        (#x0001 then #x000D)
        (#x0001 then #x0308 then #x000D)
        (#x0001 then #x000A)
        (#x0001 then #x0308 then #x000A)
        (#x0001 then #x0001)
        (#x0001 then #x0308 then #x0001)
        (#x0001 then #x034F)
        (#x0001 then #x0308 and #x034F)
        (#x0001 then #x1F1E6)
        (#x0001 then #x0308 then #x1F1E6)
        (#x0001 then #x0600)
        (#x0001 then #x0308 then #x0600)
        (#x0001 then #x0903)
        (#x0001 then #x0308 and #x0903)
        (#x0001 then #x1100)
        (#x0001 then #x0308 then #x1100)
        (#x0001 then #x1160)
        (#x0001 then #x0308 then #x1160)
        (#x0001 then #x11A8)
        (#x0001 then #x0308 then #x11A8)
        (#x0001 then #xAC00)
        (#x0001 then #x0308 then #xAC00)
        (#x0001 then #xAC01)
        (#x0001 then #x0308 then #xAC01)
        (#x0001 then #x231A)
        (#x0001 then #x0308 then #x231A)
        (#x0001 then #x0300)
        (#x0001 then #x0308 and #x0300)
        (#x0001 then #x200D)
        (#x0001 then #x0308 and #x200D)
        (#x0001 then #x0378)
        (#x0001 then #x0308 then #x0378)
        (#x034F then #x0020)
        (#x034F and #x0308 then #x0020)
        (#x034F then #x000D)
        (#x034F and #x0308 then #x000D)
        (#x034F then #x000A)
        (#x034F and #x0308 then #x000A)
        (#x034F then #x0001)
        (#x034F and #x0308 then #x0001)
        (#x034F and #x034F)
        (#x034F and #x0308 and #x034F)
        (#x034F then #x1F1E6)
        (#x034F and #x0308 then #x1F1E6)
        (#x034F then #x0600)
        (#x034F and #x0308 then #x0600)
        (#x034F and #x0903)
        (#x034F and #x0308 and #x0903)
        (#x034F then #x1100)
        (#x034F and #x0308 then #x1100)
        (#x034F then #x1160)
        (#x034F and #x0308 then #x1160)
        (#x034F then #x11A8)
        (#x034F and #x0308 then #x11A8)
        (#x034F then #xAC00)
        (#x034F and #x0308 then #xAC00)
        (#x034F then #xAC01)
        (#x034F and #x0308 then #xAC01)
        (#x034F then #x231A)
        (#x034F and #x0308 then #x231A)
        (#x034F and #x0300)
        (#x034F and #x0308 and #x0300)
        (#x034F and #x200D)
        (#x034F and #x0308 and #x200D)
        (#x034F then #x0378)
        (#x034F and #x0308 then #x0378)
        (#x1F1E6 then #x0020)
        (#x1F1E6 and #x0308 then #x0020)
        (#x1F1E6 then #x000D)
        (#x1F1E6 and #x0308 then #x000D)
        (#x1F1E6 then #x000A)
        (#x1F1E6 and #x0308 then #x000A)
        (#x1F1E6 then #x0001)
        (#x1F1E6 and #x0308 then #x0001)
        (#x1F1E6 and #x034F)
        (#x1F1E6 and #x0308 and #x034F)
        (#x1F1E6 and #x1F1E6)
        (#x1F1E6 and #x0308 then #x1F1E6)
        (#x1F1E6 then #x0600)
        (#x1F1E6 and #x0308 then #x0600)
        (#x1F1E6 and #x0903)
        (#x1F1E6 and #x0308 and #x0903)
        (#x1F1E6 then #x1100)
        (#x1F1E6 and #x0308 then #x1100)
        (#x1F1E6 then #x1160)
        (#x1F1E6 and #x0308 then #x1160)
        (#x1F1E6 then #x11A8)
        (#x1F1E6 and #x0308 then #x11A8)
        (#x1F1E6 then #xAC00)
        (#x1F1E6 and #x0308 then #xAC00)
        (#x1F1E6 then #xAC01)
        (#x1F1E6 and #x0308 then #xAC01)
        (#x1F1E6 then #x231A)
        (#x1F1E6 and #x0308 then #x231A)
        (#x1F1E6 and #x0300)
        (#x1F1E6 and #x0308 and #x0300)
        (#x1F1E6 and #x200D)
        (#x1F1E6 and #x0308 and #x200D)
        (#x1F1E6 then #x0378)
        (#x1F1E6 and #x0308 then #x0378)
        (#x0600 and #x0020)
        (#x0600 and #x0308 then #x0020)
        (#x0600 then #x000D)
        (#x0600 and #x0308 then #x000D)
        (#x0600 then #x000A)
        (#x0600 and #x0308 then #x000A)
        (#x0600 then #x0001)
        (#x0600 and #x0308 then #x0001)
        (#x0600 and #x034F)
        (#x0600 and #x0308 and #x034F)
        (#x0600 and #x1F1E6)
        (#x0600 and #x0308 then #x1F1E6)
        (#x0600 and #x0600)
        (#x0600 and #x0308 then #x0600)
        (#x0600 and #x0903)
        (#x0600 and #x0308 and #x0903)
        (#x0600 and #x1100)
        (#x0600 and #x0308 then #x1100)
        (#x0600 and #x1160)
        (#x0600 and #x0308 then #x1160)
        (#x0600 and #x11A8)
        (#x0600 and #x0308 then #x11A8)
        (#x0600 and #xAC00)
        (#x0600 and #x0308 then #xAC00)
        (#x0600 and #xAC01)
        (#x0600 and #x0308 then #xAC01)
        (#x0600 and #x231A)
        (#x0600 and #x0308 then #x231A)
        (#x0600 and #x0300)
        (#x0600 and #x0308 and #x0300)
        (#x0600 and #x200D)
        (#x0600 and #x0308 and #x200D)
        (#x0600 and #x0378)
        (#x0600 and #x0308 then #x0378)
        (#x0903 then #x0020)
        (#x0903 and #x0308 then #x0020)
        (#x0903 then #x000D)
        (#x0903 and #x0308 then #x000D)
        (#x0903 then #x000A)
        (#x0903 and #x0308 then #x000A)
        (#x0903 then #x0001)
        (#x0903 and #x0308 then #x0001)
        (#x0903 and #x034F)
        (#x0903 and #x0308 and #x034F)
        (#x0903 then #x1F1E6)
        (#x0903 and #x0308 then #x1F1E6)
        (#x0903 then #x0600)
        (#x0903 and #x0308 then #x0600)
        (#x0903 and #x0903)
        (#x0903 and #x0308 and #x0903)
        (#x0903 then #x1100)
        (#x0903 and #x0308 then #x1100)
        (#x0903 then #x1160)
        (#x0903 and #x0308 then #x1160)
        (#x0903 then #x11A8)
        (#x0903 and #x0308 then #x11A8)
        (#x0903 then #xAC00)
        (#x0903 and #x0308 then #xAC00)
        (#x0903 then #xAC01)
        (#x0903 and #x0308 then #xAC01)
        (#x0903 then #x231A)
        (#x0903 and #x0308 then #x231A)
        (#x0903 and #x0300)
        (#x0903 and #x0308 and #x0300)
        (#x0903 and #x200D)
        (#x0903 and #x0308 and #x200D)
        (#x0903 then #x0378)
        (#x0903 and #x0308 then #x0378)
        (#x1100 then #x0020)
        (#x1100 and #x0308 then #x0020)
        (#x1100 then #x000D)
        (#x1100 and #x0308 then #x000D)
        (#x1100 then #x000A)
        (#x1100 and #x0308 then #x000A)
        (#x1100 then #x0001)
        (#x1100 and #x0308 then #x0001)
        (#x1100 and #x034F)
        (#x1100 and #x0308 and #x034F)
        (#x1100 then #x1F1E6)
        (#x1100 and #x0308 then #x1F1E6)
        (#x1100 then #x0600)
        (#x1100 and #x0308 then #x0600)
        (#x1100 and #x0903)
        (#x1100 and #x0308 and #x0903)
        (#x1100 and #x1100)
        (#x1100 and #x0308 then #x1100)
        (#x1100 and #x1160)
        (#x1100 and #x0308 then #x1160)
        (#x1100 then #x11A8)
        (#x1100 and #x0308 then #x11A8)
        (#x1100 and #xAC00)
        (#x1100 and #x0308 then #xAC00)
        (#x1100 and #xAC01)
        (#x1100 and #x0308 then #xAC01)
        (#x1100 then #x231A)
        (#x1100 and #x0308 then #x231A)
        (#x1100 and #x0300)
        (#x1100 and #x0308 and #x0300)
        (#x1100 and #x200D)
        (#x1100 and #x0308 and #x200D)
        (#x1100 then #x0378)
        (#x1100 and #x0308 then #x0378)
        (#x1160 then #x0020)
        (#x1160 and #x0308 then #x0020)
        (#x1160 then #x000D)
        (#x1160 and #x0308 then #x000D)
        (#x1160 then #x000A)
        (#x1160 and #x0308 then #x000A)
        (#x1160 then #x0001)
        (#x1160 and #x0308 then #x0001)
        (#x1160 and #x034F)
        (#x1160 and #x0308 and #x034F)
        (#x1160 then #x1F1E6)
        (#x1160 and #x0308 then #x1F1E6)
        (#x1160 then #x0600)
        (#x1160 and #x0308 then #x0600)
        (#x1160 and #x0903)
        (#x1160 and #x0308 and #x0903)
        (#x1160 then #x1100)
        (#x1160 and #x0308 then #x1100)
        (#x1160 and #x1160)
        (#x1160 and #x0308 then #x1160)
        (#x1160 and #x11A8)
        (#x1160 and #x0308 then #x11A8)
        (#x1160 then #xAC00)
        (#x1160 and #x0308 then #xAC00)
        (#x1160 then #xAC01)
        (#x1160 and #x0308 then #xAC01)
        (#x1160 then #x231A)
        (#x1160 and #x0308 then #x231A)
        (#x1160 and #x0300)
        (#x1160 and #x0308 and #x0300)
        (#x1160 and #x200D)
        (#x1160 and #x0308 and #x200D)
        (#x1160 then #x0378)
        (#x1160 and #x0308 then #x0378)
        (#x11A8 then #x0020)
        (#x11A8 and #x0308 then #x0020)
        (#x11A8 then #x000D)
        (#x11A8 and #x0308 then #x000D)
        (#x11A8 then #x000A)
        (#x11A8 and #x0308 then #x000A)
        (#x11A8 then #x0001)
        (#x11A8 and #x0308 then #x0001)
        (#x11A8 and #x034F)
        (#x11A8 and #x0308 and #x034F)
        (#x11A8 then #x1F1E6)
        (#x11A8 and #x0308 then #x1F1E6)
        (#x11A8 then #x0600)
        (#x11A8 and #x0308 then #x0600)
        (#x11A8 and #x0903)
        (#x11A8 and #x0308 and #x0903)
        (#x11A8 then #x1100)
        (#x11A8 and #x0308 then #x1100)
        (#x11A8 then #x1160)
        (#x11A8 and #x0308 then #x1160)
        (#x11A8 and #x11A8)
        (#x11A8 and #x0308 then #x11A8)
        (#x11A8 then #xAC00)
        (#x11A8 and #x0308 then #xAC00)
        (#x11A8 then #xAC01)
        (#x11A8 and #x0308 then #xAC01)
        (#x11A8 then #x231A)
        (#x11A8 and #x0308 then #x231A)
        (#x11A8 and #x0300)
        (#x11A8 and #x0308 and #x0300)
        (#x11A8 and #x200D)
        (#x11A8 and #x0308 and #x200D)
        (#x11A8 then #x0378)
        (#x11A8 and #x0308 then #x0378)
        (#xAC00 then #x0020)
        (#xAC00 and #x0308 then #x0020)
        (#xAC00 then #x000D)
        (#xAC00 and #x0308 then #x000D)
        (#xAC00 then #x000A)
        (#xAC00 and #x0308 then #x000A)
        (#xAC00 then #x0001)
        (#xAC00 and #x0308 then #x0001)
        (#xAC00 and #x034F)
        (#xAC00 and #x0308 and #x034F)
        (#xAC00 then #x1F1E6)
        (#xAC00 and #x0308 then #x1F1E6)
        (#xAC00 then #x0600)
        (#xAC00 and #x0308 then #x0600)
        (#xAC00 and #x0903)
        (#xAC00 and #x0308 and #x0903)
        (#xAC00 then #x1100)
        (#xAC00 and #x0308 then #x1100)
        (#xAC00 and #x1160)
        (#xAC00 and #x0308 then #x1160)
        (#xAC00 and #x11A8)
        (#xAC00 and #x0308 then #x11A8)
        (#xAC00 then #xAC00)
        (#xAC00 and #x0308 then #xAC00)
        (#xAC00 then #xAC01)
        (#xAC00 and #x0308 then #xAC01)
        (#xAC00 then #x231A)
        (#xAC00 and #x0308 then #x231A)
        (#xAC00 and #x0300)
        (#xAC00 and #x0308 and #x0300)
        (#xAC00 and #x200D)
        (#xAC00 and #x0308 and #x200D)
        (#xAC00 then #x0378)
        (#xAC00 and #x0308 then #x0378)
        (#xAC01 then #x0020)
        (#xAC01 and #x0308 then #x0020)
        (#xAC01 then #x000D)
        (#xAC01 and #x0308 then #x000D)
        (#xAC01 then #x000A)
        (#xAC01 and #x0308 then #x000A)
        (#xAC01 then #x0001)
        (#xAC01 and #x0308 then #x0001)
        (#xAC01 and #x034F)
        (#xAC01 and #x0308 and #x034F)
        (#xAC01 then #x1F1E6)
        (#xAC01 and #x0308 then #x1F1E6)
        (#xAC01 then #x0600)
        (#xAC01 and #x0308 then #x0600)
        (#xAC01 and #x0903)
        (#xAC01 and #x0308 and #x0903)
        (#xAC01 then #x1100)
        (#xAC01 and #x0308 then #x1100)
        (#xAC01 then #x1160)
        (#xAC01 and #x0308 then #x1160)
        (#xAC01 and #x11A8)
        (#xAC01 and #x0308 then #x11A8)
        (#xAC01 then #xAC00)
        (#xAC01 and #x0308 then #xAC00)
        (#xAC01 then #xAC01)
        (#xAC01 and #x0308 then #xAC01)
        (#xAC01 then #x231A)
        (#xAC01 and #x0308 then #x231A)
        (#xAC01 and #x0300)
        (#xAC01 and #x0308 and #x0300)
        (#xAC01 and #x200D)
        (#xAC01 and #x0308 and #x200D)
        (#xAC01 then #x0378)
        (#xAC01 and #x0308 then #x0378)
        (#x231A then #x0020)
        (#x231A and #x0308 then #x0020)
        (#x231A then #x000D)
        (#x231A and #x0308 then #x000D)
        (#x231A then #x000A)
        (#x231A and #x0308 then #x000A)
        (#x231A then #x0001)
        (#x231A and #x0308 then #x0001)
        (#x231A and #x034F)
        (#x231A and #x0308 and #x034F)
        (#x231A then #x1F1E6)
        (#x231A and #x0308 then #x1F1E6)
        (#x231A then #x0600)
        (#x231A and #x0308 then #x0600)
        (#x231A and #x0903)
        (#x231A and #x0308 and #x0903)
        (#x231A then #x1100)
        (#x231A and #x0308 then #x1100)
        (#x231A then #x1160)
        (#x231A and #x0308 then #x1160)
        (#x231A then #x11A8)
        (#x231A and #x0308 then #x11A8)
        (#x231A then #xAC00)
        (#x231A and #x0308 then #xAC00)
        (#x231A then #xAC01)
        (#x231A and #x0308 then #xAC01)
        (#x231A then #x231A)
        (#x231A and #x0308 then #x231A)
        (#x231A and #x0300)
        (#x231A and #x0308 and #x0300)
        (#x231A and #x200D)
        (#x231A and #x0308 and #x200D)
        (#x231A then #x0378)
        (#x231A and #x0308 then #x0378)
        (#x0300 then #x0020)
        (#x0300 and #x0308 then #x0020)
        (#x0300 then #x000D)
        (#x0300 and #x0308 then #x000D)
        (#x0300 then #x000A)
        (#x0300 and #x0308 then #x000A)
        (#x0300 then #x0001)
        (#x0300 and #x0308 then #x0001)
        (#x0300 and #x034F)
        (#x0300 and #x0308 and #x034F)
        (#x0300 then #x1F1E6)
        (#x0300 and #x0308 then #x1F1E6)
        (#x0300 then #x0600)
        (#x0300 and #x0308 then #x0600)
        (#x0300 and #x0903)
        (#x0300 and #x0308 and #x0903)
        (#x0300 then #x1100)
        (#x0300 and #x0308 then #x1100)
        (#x0300 then #x1160)
        (#x0300 and #x0308 then #x1160)
        (#x0300 then #x11A8)
        (#x0300 and #x0308 then #x11A8)
        (#x0300 then #xAC00)
        (#x0300 and #x0308 then #xAC00)
        (#x0300 then #xAC01)
        (#x0300 and #x0308 then #xAC01)
        (#x0300 then #x231A)
        (#x0300 and #x0308 then #x231A)
        (#x0300 and #x0300)
        (#x0300 and #x0308 and #x0300)
        (#x0300 and #x200D)
        (#x0300 and #x0308 and #x200D)
        (#x0300 then #x0378)
        (#x0300 and #x0308 then #x0378)
        (#x200D then #x0020)
        (#x200D and #x0308 then #x0020)
        (#x200D then #x000D)
        (#x200D and #x0308 then #x000D)
        (#x200D then #x000A)
        (#x200D and #x0308 then #x000A)
        (#x200D then #x0001)
        (#x200D and #x0308 then #x0001)
        (#x200D and #x034F)
        (#x200D and #x0308 and #x034F)
        (#x200D then #x1F1E6)
        (#x200D and #x0308 then #x1F1E6)
        (#x200D then #x0600)
        (#x200D and #x0308 then #x0600)
        (#x200D and #x0903)
        (#x200D and #x0308 and #x0903)
        (#x200D then #x1100)
        (#x200D and #x0308 then #x1100)
        (#x200D then #x1160)
        (#x200D and #x0308 then #x1160)
        (#x200D then #x11A8)
        (#x200D and #x0308 then #x11A8)
        (#x200D then #xAC00)
        (#x200D and #x0308 then #xAC00)
        (#x200D then #xAC01)
        (#x200D and #x0308 then #xAC01)
        (#x200D then #x231A)
        (#x200D and #x0308 then #x231A)
        (#x200D and #x0300)
        (#x200D and #x0308 and #x0300)
        (#x200D and #x200D)
        (#x200D and #x0308 and #x200D)
        (#x200D then #x0378)
        (#x200D and #x0308 then #x0378)
        (#x0378 then #x0020)
        (#x0378 and #x0308 then #x0020)
        (#x0378 then #x000D)
        (#x0378 and #x0308 then #x000D)
        (#x0378 then #x000A)
        (#x0378 and #x0308 then #x000A)
        (#x0378 then #x0001)
        (#x0378 and #x0308 then #x0001)
        (#x0378 and #x034F)
        (#x0378 and #x0308 and #x034F)
        (#x0378 then #x1F1E6)
        (#x0378 and #x0308 then #x1F1E6)
        (#x0378 then #x0600)
        (#x0378 and #x0308 then #x0600)
        (#x0378 and #x0903)
        (#x0378 and #x0308 and #x0903)
        (#x0378 then #x1100)
        (#x0378 and #x0308 then #x1100)
        (#x0378 then #x1160)
        (#x0378 and #x0308 then #x1160)
        (#x0378 then #x11A8)
        (#x0378 and #x0308 then #x11A8)
        (#x0378 then #xAC00)
        (#x0378 and #x0308 then #xAC00)
        (#x0378 then #xAC01)
        (#x0378 and #x0308 then #xAC01)
        (#x0378 then #x231A)
        (#x0378 and #x0308 then #x231A)
        (#x0378 and #x0300)
        (#x0378 and #x0308 and #x0300)
        (#x0378 and #x200D)
        (#x0378 and #x0308 and #x200D)
        (#x0378 then #x0378)
        (#x0378 and #x0308 then #x0378)
        (#x000D and #x000A then #x0061 then #x000A then #x0308)
        (#x0061 and #x0308)
        (#x0020 and #x200D then #x0646)
        (#x0646 and #x200D then #x0020)
        (#x1100 and #x1100)
        (#xAC00 and #x11A8 then #x1100)
        (#xAC01 and #x11A8 then #x1100)
        (#x1F1E6 and #x1F1E7 then #x1F1E8 then #x0062)
        (#x0061 then #x1F1E6 and #x1F1E7 then #x1F1E8 then #x0062)
        (#x0061 then #x1F1E6 and #x1F1E7 and #x200D then #x1F1E8 then #x0062)
        (#x0061 then #x1F1E6 and #x200D then #x1F1E7 and #x1F1E8 then #x0062)
        (#x0061 then #x1F1E6 and #x1F1E7 then #x1F1E8 and #x1F1E9 then #x0062)
        (#x0061 and #x200D)
        (#x0061 and #x0308 then #x0062)
        (#x0061 and #x0903 then #x0062)
        (#x0061 then #x0600 and #x0062)
        (#x1F476 and #x1F3FF then #x1F476)
        (#x0061 and #x1F3FF then #x1F476)
        (#x0061 and #x1F3FF then #x1F476 and #x200D and #x1F6D1)
        (#x1F476 and #x1F3FF and #x0308 and #x200D and #x1F476 and #x1F3FF)
        (#x1F6D1 and #x200D and #x1F6D1)
        (#x0061 and #x200D then #x1F6D1)
        (#x2701 and #x200D and #x2701)
        (#x0061 and #x200D then #x2701)))

    (for-each (lambda (seq)
                (printf "~s\n" seq)
                (let ([s (list->string
                          (map integer->char
                               (filter integer? seq)))]
                      [pieces (let loop ([seq seq] [start 0] [i 0])
                                (cond
                                  [(null? seq)
                                   (list start)]
                                  [(eq? 'and (car seq))
                                   (loop (cdr seq) start i)]
                                  [(eq? 'then (car seq))
                                   (cons start (loop (cdr seq) i i))]
                                  [else
                                   (loop (cdr seq) start (add1 i))]))])
                  (let ([str-pieces
                         (let loop ([i 0])
                           (cond
                             [(= i (string-length s)) '()]
                             [else
                              (cons i (loop (+ i (string-grapheme-span s i))))]))])
                    (unless (equal? pieces str-pieces)
                      (error 'seq "mismatch ~s ~s ~s ~s" seq s pieces str-pieces)))
                  (let ([stream-str-pieces
                         (let loop ([i 0] [start 0] [state 0])
                           (cond
                             [(= i (string-length s))
                              (if (fx= state 0)
                                  '()
                                  (list start))]
                             [else
                              (let-values ([(consume? state)
                                            (char-grapheme-step (string-ref s i) state)])
                                (if consume?
                                    (cons start (loop (+ i 1)
                                                      (if (fx= state 0) (+ i 1) i)
                                                      state))
                                    (loop (+ i 1) start state)))]))])
                    (unless (equal? pieces stream-str-pieces)
                      (error 'seq "stream mismatch ~s ~s ~s ~s" seq s pieces stream-str-pieces)))
                  (let ([n (string-grapheme-count s)])
                    (unless (= n (length pieces))
                      (error 'seq "count mismatch ~s ~s ~s ~s" seq s n (length pieces))))))
              seqs)
    #t)
)

(mat string->symbol
  (immutable-string? (symbol->string (string->symbol "example")))
  (let* ([str (string-copy "example")]
         [sym (string->symbol str)])
    (string-set! str 0 #\E)
    (and (equal? str "Example")
         (equal? (symbol->string sym) "example")))
  (immutable-string? (symbol->string (string->symbol "")))
  ;; make sure `string->symbol` didn't make the mutable empty string immutable:
  (not (immutable-string? (string)))
)
