Import GC benchmarks from Larceny, by Hansen, Clinger, et al.
[bpt/guile.git] / gc-benchmarks / larceny / softscheme.sch
diff --git a/gc-benchmarks/larceny/softscheme.sch b/gc-benchmarks/larceny/softscheme.sch
new file mode 100644 (file)
index 0000000..8db2e48
--- /dev/null
@@ -0,0 +1,9319 @@
+; Soft Scheme -- Copyright (C) 1993, 1994 Andrew K. Wright
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, write to the Free Software
+; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+;
+; Packaged as a single file for Larceny by Lars T Hansen.
+; Modified 2000-02-15 by lth.
+;
+; Compilation notes.
+; 
+; The macro definitions for MATCH in this file depend on the presence of 
+; certain helper functions in the compilation environment, eg. match:andmap.
+; (That is not a problem when loading this file, but it is an issue when
+; compiling it.)  The easiest way to provide the helper functions during
+; compilation is to load match.sch into the compilation environment before
+; compiling.
+;
+; Once compiled, this program is self-contained.
+
+; The SoftScheme benchmark performs soft typing on a program and prints
+; a diagnostic report.  All screen output is captured in an output
+; string port, which is subsequently discarded.  (There is a moderate
+; amount of output).  No file I/O occurs while the program is running.
+
+(define (softscheme-benchmark)
+  (let ((expr `(begin ,@(readfile "ss-input.scm")))
+        (out  (open-output-string)))
+    (run-benchmark "softscheme"
+                   (lambda () 
+                     (with-output-to-port out
+                       (lambda ()
+                         (soft-def expr #f)))))
+    (newline)
+    (display (string-length (get-output-string out)))
+    (display " characters of output written.")
+    (newline)))
+
+;;; Define defmacro, macro?, and macroexpand-1.
+
+(define *macros* '())
+
+(define-syntax
+  defmacro
+  (transformer
+    (lambda (exp rename compare)
+      (define (arglist? x)
+        (or (symbol? x)
+            (null? x)
+            (and (pair? x)
+                 (symbol? (car x))
+                 (arglist? (cdr x)))))
+      (if (not (and (list? exp)
+                    (>= (length exp) 4)
+                    (symbol? (cadr exp))
+                    (arglist? (caddr exp))))
+        (error "Bad macro definition: " exp))
+      (let ((name (cadr exp))
+            (args (caddr exp))
+            (body (cdddr exp)))
+        `(begin
+           (define-syntax
+             ,name
+             (transformer
+              (lambda (_defmacro_exp
+                       _defmacro_rename
+                       _defmacro_compare)
+                (apply (lambda ,args ,@body) (cdr _defmacro_exp)))))
+           (set! *macros*
+                 (cons (cons ',name
+                             (lambda (_exp)
+                               (apply (lambda ,args ,@body) (cdr _exp))))
+                       *macros*))
+           )))))
+
+(define (macroexpand-1 exp)
+  (cond ((pair? exp)
+         (let ((probe (assq (car exp) *macros*)))
+           (if probe ((cdr probe) exp) exp)))
+        (else exp)))
+
+(define (macro? keyword)
+  (and (symbol? keyword) (assq keyword *macros*)))
+
+;;; Other compatibility hacks
+
+(define slib:error error)
+
+(define force-output flush-output-port)
+
+(define format
+  (let ((format format))
+    (lambda (port . rest)
+      (if (not port)
+        (let ((s (open-output-string)))
+          (apply format s rest)
+          (get-output-string s))
+        (apply format port rest)))))
+
+(define gentemp
+  (let ((gensym gensym)) (lambda () (gensym "G"))))
+
+(define getenv
+  (let ((getenv getenv))
+    (lambda (x)
+      (or (getenv x)
+          (if (string=? x "HOME")
+            "Ertevann:Desktop folder:"
+            #f)))))
+
+;;; The rest of the file should be more or less portable.
+
+(define match-file #f)
+(define installation-directory #f)
+(define customization-file #f)
+(define fastlibrary-file #f)
+(define st:version
+  "Larceny Version 0.18, April 21, 1995")
+(define match:version
+  "Version 1.18, July 17, 1995")
+(define match:error
+  (lambda (val . args)
+    (for-each pretty-print args)
+    (slib:error "no matching clause for " val)))
+(define match:andmap
+  (lambda (f l)
+    (if (null? l)
+      (and)
+      (and (f (car l)) (match:andmap f (cdr l))))))
+(define match:syntax-err
+  (lambda (obj msg) (slib:error msg obj)))
+(define match:disjoint-structure-tags '())
+(define match:make-structure-tag
+  (lambda (name)
+    (if (or (eq? match:structure-control 'disjoint)
+            match:runtime-structures)
+      (let ((tag (gentemp)))
+        (set! match:disjoint-structure-tags
+          (cons tag match:disjoint-structure-tags))
+        tag)
+      (string->symbol
+        (string-append "<" (symbol->string name) ">")))))
+(define match:structure?
+  (lambda (tag)
+    (memq tag match:disjoint-structure-tags)))
+(define match:structure-control 'vector)
+(define match:set-structure-control
+  (lambda (v) (set! match:structure-control v)))
+(define match:set-error
+  (lambda (v) (set! match:error v)))
+(define match:error-control 'error)
+(define match:set-error-control
+  (lambda (v) (set! match:error-control v)))
+(define match:disjoint-predicates
+  (cons 'null
+        '(pair? symbol?
+                boolean?
+                number?
+                string?
+                char?
+                procedure?
+                vector?)))
+(define match:vector-structures '())
+(define match:expanders
+  (letrec ((genmatch
+             (lambda (x clauses match-expr)
+               (let* ((length>= (gentemp))
+                      (eb-errf (error-maker match-expr))
+                      (blist (car eb-errf))
+                      (plist (map (lambda (c)
+                                    (let* ((x (bound (validate-pattern
+                                                       (car c))))
+                                           (p (car x))
+                                           (bv (cadr x))
+                                           (bindings (caddr x))
+                                           (code (gentemp))
+                                           (fail (and (pair? (cdr c))
+                                                      (pair? (cadr c))
+                                                      (eq? (caadr c) '=>)
+                                                      (symbol? (cadadr c))
+                                                      (pair? (cdadr c))
+                                                      (null? (cddadr c))
+                                                      (pair? (cddr c))
+                                                      (cadadr c)))
+                                           (bv2 (if fail (cons fail bv) bv))
+                                           (body (if fail (cddr c) (cdr c))))
+                                      (set! blist
+                                        (cons `(,code (lambda ,bv2 ,@body))
+                                              (append bindings blist)))
+                                      (list p
+                                            code
+                                            bv
+                                            (and fail (gentemp))
+                                            #f)))
+                                  clauses))
+                      (code (gen x
+                                 '()
+                                 plist
+                                 (cdr eb-errf)
+                                 length>=
+                                 (gentemp))))
+                 (unreachable plist match-expr)
+                 (inline-let
+                   `(let ((,length>=
+                           (lambda (n) (lambda (l) (>= (length l) n))))
+                          ,@blist)
+                      ,code)))))
+           (genletrec
+             (lambda (pat exp body match-expr)
+               (let* ((length>= (gentemp))
+                      (eb-errf (error-maker match-expr))
+                      (x (bound (validate-pattern pat)))
+                      (p (car x))
+                      (bv (cadr x))
+                      (bindings (caddr x))
+                      (code (gentemp))
+                      (plist (list (list p code bv #f #f)))
+                      (x (gentemp))
+                      (m (gen x
+                              '()
+                              plist
+                              (cdr eb-errf)
+                              length>=
+                              (gentemp)))
+                      (gs (map (lambda (_) (gentemp)) bv)))
+                 (unreachable plist match-expr)
+                 `(letrec ((,length>=
+                            (lambda (n) (lambda (l) (>= (length l) n))))
+                           ,@(map (lambda (v) `(,v #f)) bv)
+                           (,x ,exp)
+                           (,code
+                            (lambda ,gs
+                              ,@(map (lambda (v g) `(set! ,v ,g)) bv gs)
+                              ,@body))
+                           ,@bindings
+                           ,@(car eb-errf))
+                    ,m))))
+           (gendefine
+             (lambda (pat exp match-expr)
+               (let* ((length>= (gentemp))
+                      (eb-errf (error-maker match-expr))
+                      (x (bound (validate-pattern pat)))
+                      (p (car x))
+                      (bv (cadr x))
+                      (bindings (caddr x))
+                      (code (gentemp))
+                      (plist (list (list p code bv #f #f)))
+                      (x (gentemp))
+                      (m (gen x
+                              '()
+                              plist
+                              (cdr eb-errf)
+                              length>=
+                              (gentemp)))
+                      (gs (map (lambda (_) (gentemp)) bv)))
+                 (unreachable plist match-expr)
+                 `(begin
+                    ,@(map (lambda (v) `(define ,v #f)) bv)
+                    ,(inline-let
+                       `(let ((,length>=
+                               (lambda (n) (lambda (l) (>= (length l) n))))
+                              (,x ,exp)
+                              (,code
+                               (lambda ,gs
+                                 ,@(map (lambda (v g) `(set! ,v ,g)) bv gs)
+                                 (cond (#f #f))))
+                              ,@bindings
+                              ,@(car eb-errf))
+                          ,m))))))
+           (pattern-var?
+             (lambda (x)
+               (and (symbol? x)
+                    (not (dot-dot-k? x))
+                    (not (memq x
+                               '(quasiquote
+                                  quote
+                                  unquote
+                                  unquote-splicing
+                                  ?
+                                  _
+                                  $
+                                  =
+                                  and
+                                  or
+                                  not
+                                  set!
+                                  get!
+                                  ...
+                                  ___))))))
+           (dot-dot-k?
+             (lambda (s)
+               (and (symbol? s)
+                    (if (memq s '(... ___))
+                      0
+                      (let* ((s (symbol->string s)) (n (string-length s)))
+                        (and (<= 3 n)
+                             (memq (string-ref s 0) '(#\. #\_))
+                             (memq (string-ref s 1) '(#\. #\_))
+                             (match:andmap
+                               char-numeric?
+                               (string->list (substring s 2 n)))
+                             (string->number (substring s 2 n))))))))
+           (error-maker
+             (lambda (match-expr)
+               (cond ((eq? match:error-control 'unspecified)
+                      (cons '() (lambda (x) `(cond (#f #f)))))
+                     ((memq match:error-control '(error fail))
+                      (cons '() (lambda (x) `(match:error ,x))))
+                     ((eq? match:error-control 'match)
+                      (let ((errf (gentemp)) (arg (gentemp)))
+                        (cons `((,errf
+                                 (lambda (,arg)
+                                   (match:error ,arg ',match-expr))))
+                              (lambda (x) `(,errf ,x)))))
+                     (else
+                      (match:syntax-err
+                        '(unspecified error fail match)
+                        "invalid value for match:error-control, legal values are")))))
+           (unreachable
+             (lambda (plist match-expr)
+               (for-each
+                 (lambda (x)
+                   (if (not (car (cddddr x)))
+                     (begin
+                       (display "Warning: unreachable pattern ")
+                       (display (car x))
+                       (display " in ")
+                       (display match-expr)
+                       (newline))))
+                 plist)))
+           (validate-pattern
+             (lambda (pattern)
+               (letrec ((simple?
+                          (lambda (x)
+                            (or (string? x)
+                                (boolean? x)
+                                (char? x)
+                                (number? x)
+                                (null? x))))
+                        (ordinary
+                          (lambda (p)
+                            (let ((g88 (lambda (x y)
+                                         (cons (ordinary x) (ordinary y)))))
+                              (if (simple? p)
+                                ((lambda (p) p) p)
+                                (if (equal? p '_)
+                                  ((lambda () '_))
+                                  (if (pattern-var? p)
+                                    ((lambda (p) p) p)
+                                    (if (pair? p)
+                                      (if (equal? (car p) 'quasiquote)
+                                        (if (and (pair? (cdr p))
+                                                 (null? (cddr p)))
+                                          ((lambda (p) (quasi p)) (cadr p))
+                                          (g88 (car p) (cdr p)))
+                                        (if (equal? (car p) 'quote)
+                                          (if (and (pair? (cdr p))
+                                                   (null? (cddr p)))
+                                            ((lambda (p) p) p)
+                                            (g88 (car p) (cdr p)))
+                                          (if (equal? (car p) '?)
+                                            (if (and (pair? (cdr p))
+                                                     (list? (cddr p)))
+                                              ((lambda (pred ps)
+                                                 `(? ,pred
+                                                     ,@(map ordinary ps)))
+                                               (cadr p)
+                                               (cddr p))
+                                              (g88 (car p) (cdr p)))
+                                            (if (equal? (car p) '=)
+                                              (if (and (pair? (cdr p))
+                                                       (pair? (cddr p))
+                                                       (null? (cdddr p)))
+                                                ((lambda (sel p)
+                                                   `(= ,sel ,(ordinary p)))
+                                                 (cadr p)
+                                                 (caddr p))
+                                                (g88 (car p) (cdr p)))
+                                              (if (equal? (car p) 'and)
+                                                (if (and (list? (cdr p))
+                                                         (pair? (cdr p)))
+                                                  ((lambda (ps)
+                                                     `(and ,@(map ordinary
+                                                                  ps)))
+                                                   (cdr p))
+                                                  (g88 (car p) (cdr p)))
+                                                (if (equal? (car p) 'or)
+                                                  (if (and (list? (cdr p))
+                                                           (pair? (cdr p)))
+                                                    ((lambda (ps)
+                                                       `(or ,@(map ordinary
+                                                                   ps)))
+                                                     (cdr p))
+                                                    (g88 (car p) (cdr p)))
+                                                  (if (equal? (car p) 'not)
+                                                    (if (and (list? (cdr p))
+                                                             (pair? (cdr p)))
+                                                      ((lambda (ps)
+                                                         `(not ,@(map ordinary
+                                                                      ps)))
+                                                       (cdr p))
+                                                      (g88 (car p) (cdr p)))
+                                                    (if (equal? (car p) '$)
+                                                      (if (and (pair? (cdr p))
+                                                               (symbol?
+                                                                 (cadr p))
+                                                               (list? (cddr p)))
+                                                        ((lambda (r ps)
+                                                           `($ ,r
+                                                               ,@(map ordinary
+                                                                      ps)))
+                                                         (cadr p)
+                                                         (cddr p))
+                                                        (g88 (car p) (cdr p)))
+                                                      (if (equal?
+                                                            (car p)
+                                                            'set!)
+                                                        (if (and (pair? (cdr p))
+                                                                 (pattern-var?
+                                                                   (cadr p))
+                                                                 (null? (cddr p)))
+                                                          ((lambda (p) p) p)
+                                                          (g88 (car p)
+                                                               (cdr p)))
+                                                        (if (equal?
+                                                              (car p)
+                                                              'get!)
+                                                          (if (and (pair? (cdr p))
+                                                                   (pattern-var?
+                                                                     (cadr p))
+                                                                   (null? (cddr p)))
+                                                            ((lambda (p) p) p)
+                                                            (g88 (car p)
+                                                                 (cdr p)))
+                                                          (if (equal?
+                                                                (car p)
+                                                                'unquote)
+                                                            (g88 (car p)
+                                                                 (cdr p))
+                                                            (if (equal?
+                                                                  (car p)
+                                                                  'unquote-splicing)
+                                                              (g88 (car p)
+                                                                   (cdr p))
+                                                              (if (and (pair? (cdr p))
+                                                                       (dot-dot-k?
+                                                                         (cadr p))
+                                                                       (null? (cddr p)))
+                                                                ((lambda (p
+                                                                          ddk)
+                                                                   `(,(ordinary
+                                                                        p)
+                                                                     ,ddk))
+                                                                 (car p)
+                                                                 (cadr p))
+                                                                (g88 (car p)
+                                                                     (cdr p)))))))))))))))
+                                      (if (vector? p)
+                                        ((lambda (p)
+                                           (let* ((pl (vector->list p))
+                                                  (rpl (reverse pl)))
+                                             (apply vector
+                                                    (if (and (not (null? rpl))
+                                                             (dot-dot-k?
+                                                               (car rpl)))
+                                                      (reverse
+                                                        (cons (car rpl)
+                                                              (map ordinary
+                                                                   (cdr rpl))))
+                                                      (map ordinary pl)))))
+                                         p)
+                                        ((lambda ()
+                                           (match:syntax-err
+                                             pattern
+                                             "syntax error in pattern")))))))))))
+                        (quasi (lambda (p)
+                                 (let ((g109 (lambda (x y)
+                                               (cons (quasi x) (quasi y)))))
+                                   (if (simple? p)
+                                     ((lambda (p) p) p)
+                                     (if (symbol? p)
+                                       ((lambda (p) `',p) p)
+                                       (if (pair? p)
+                                         (if (equal? (car p) 'unquote)
+                                           (if (and (pair? (cdr p))
+                                                    (null? (cddr p)))
+                                             ((lambda (p) (ordinary p))
+                                              (cadr p))
+                                             (g109 (car p) (cdr p)))
+                                           (if (and (pair? (car p))
+                                                    (equal?
+                                                      (caar p)
+                                                      'unquote-splicing)
+                                                    (pair? (cdar p))
+                                                    (null? (cddar p)))
+                                             (if (null? (cdr p))
+                                               ((lambda (p) (ordinary p))
+                                                (cadar p))
+                                               ((lambda (p y)
+                                                  (append
+                                                    (ordlist p)
+                                                    (quasi y)))
+                                                (cadar p)
+                                                (cdr p)))
+                                             (if (and (pair? (cdr p))
+                                                      (dot-dot-k? (cadr p))
+                                                      (null? (cddr p)))
+                                               ((lambda (p ddk)
+                                                  `(,(quasi p) ,ddk))
+                                                (car p)
+                                                (cadr p))
+                                               (g109 (car p) (cdr p)))))
+                                         (if (vector? p)
+                                           ((lambda (p)
+                                              (let* ((pl (vector->list p))
+                                                     (rpl (reverse pl)))
+                                                (apply vector
+                                                       (if (dot-dot-k?
+                                                             (car rpl))
+                                                         (reverse
+                                                           (cons (car rpl)
+                                                                 (map quasi
+                                                                      (cdr rpl))))
+                                                         (map ordinary pl)))))
+                                            p)
+                                           ((lambda ()
+                                              (match:syntax-err
+                                                pattern
+                                                "syntax error in pattern"))))))))))
+                        (ordlist
+                          (lambda (p)
+                            (cond ((null? p) '())
+                                  ((pair? p)
+                                   (cons (ordinary (car p)) (ordlist (cdr p))))
+                                  (else
+                                   (match:syntax-err
+                                     pattern
+                                     "invalid use of unquote-splicing in pattern"))))))
+                 (ordinary pattern))))
+           (bound (lambda (pattern)
+                    (letrec ((pred-bodies '())
+                             (bound (lambda (p a k)
+                                      (cond ((eq? '_ p) (k p a))
+                                            ((symbol? p)
+                                             (if (memq p a)
+                                               (match:syntax-err
+                                                 pattern
+                                                 "duplicate variable in pattern"))
+                                             (k p (cons p a)))
+                                            ((and (pair? p)
+                                                  (eq? 'quote (car p)))
+                                             (k p a))
+                                            ((and (pair? p) (eq? '? (car p)))
+                                             (cond ((not (null? (cddr p)))
+                                                    (bound `(and (? ,(cadr p))
+                                                                 ,@(cddr p))
+                                                           a
+                                                           k))
+                                                   ((or (not (symbol?
+                                                               (cadr p)))
+                                                        (memq (cadr p) a))
+                                                    (let ((g (gentemp)))
+                                                      (set! pred-bodies
+                                                        (cons `(,g ,(cadr p))
+                                                              pred-bodies))
+                                                      (k `(? ,g) a)))
+                                                   (else (k p a))))
+                                            ((and (pair? p) (eq? '= (car p)))
+                                             (cond ((or (not (symbol?
+                                                               (cadr p)))
+                                                        (memq (cadr p) a))
+                                                    (let ((g (gentemp)))
+                                                      (set! pred-bodies
+                                                        (cons `(,g ,(cadr p))
+                                                              pred-bodies))
+                                                      (bound `(= ,g ,(caddr p))
+                                                             a
+                                                             k)))
+                                                   (else
+                                                    (bound (caddr p)
+                                                           a
+                                                           (lambda (p2 a)
+                                                             (k `(= ,(cadr p)
+                                                                    ,p2)
+                                                                a))))))
+                                            ((and (pair? p) (eq? 'and (car p)))
+                                             (bound*
+                                               (cdr p)
+                                               a
+                                               (lambda (p a)
+                                                 (k `(and ,@p) a))))
+                                            ((and (pair? p) (eq? 'or (car p)))
+                                             (bound (cadr p)
+                                                    a
+                                                    (lambda (first-p first-a)
+                                                      (let or* ((plist (cddr p))
+                                                                (k (lambda (plist)
+                                                                     (k `(or ,first-p
+                                                                             ,@plist)
+                                                                        first-a))))
+                                                        (if (null? plist)
+                                                          (k plist)
+                                                          (bound (car plist)
+                                                                 a
+                                                                 (lambda (car-p
+                                                                          car-a)
+                                                                   (if (not (permutation
+                                                                              car-a
+                                                                              first-a))
+                                                                     (match:syntax-err
+                                                                       pattern
+                                                                       "variables of or-pattern differ in"))
+                                                                   (or* (cdr plist)
+                                                                        (lambda (cdr-p)
+                                                                          (k (cons car-p
+                                                                                   cdr-p)))))))))))
+                                            ((and (pair? p) (eq? 'not (car p)))
+                                             (cond ((not (null? (cddr p)))
+                                                    (bound `(not (or ,@(cdr p)))
+                                                           a
+                                                           k))
+                                                   (else
+                                                    (bound (cadr p)
+                                                           a
+                                                           (lambda (p2 a2)
+                                                             (if (not (permutation
+                                                                        a
+                                                                        a2))
+                                                               (match:syntax-err
+                                                                 p
+                                                                 "no variables allowed in"))
+                                                             (k `(not ,p2)
+                                                                a))))))
+                                            ((and (pair? p)
+                                                  (pair? (cdr p))
+                                                  (dot-dot-k? (cadr p)))
+                                             (bound (car p)
+                                                    a
+                                                    (lambda (q b)
+                                                      (let ((bvars (find-prefix
+                                                                     b
+                                                                     a)))
+                                                        (k `(,q
+                                                             ,(cadr p)
+                                                             ,bvars
+                                                             ,(gentemp)
+                                                             ,(gentemp)
+                                                             ,(map (lambda (_)
+                                                                     (gentemp))
+                                                                   bvars))
+                                                           b)))))
+                                            ((and (pair? p) (eq? '$ (car p)))
+                                             (bound*
+                                               (cddr p)
+                                               a
+                                               (lambda (p1 a)
+                                                 (k `($ ,(cadr p) ,@p1) a))))
+                                            ((and (pair? p)
+                                                  (eq? 'set! (car p)))
+                                             (if (memq (cadr p) a)
+                                               (k p a)
+                                               (k p (cons (cadr p) a))))
+                                            ((and (pair? p)
+                                                  (eq? 'get! (car p)))
+                                             (if (memq (cadr p) a)
+                                               (k p a)
+                                               (k p (cons (cadr p) a))))
+                                            ((pair? p)
+                                             (bound (car p)
+                                                    a
+                                                    (lambda (car-p a)
+                                                      (bound (cdr p)
+                                                             a
+                                                             (lambda (cdr-p a)
+                                                               (k (cons car-p
+                                                                        cdr-p)
+                                                                  a))))))
+                                            ((vector? p)
+                                             (boundv
+                                               (vector->list p)
+                                               a
+                                               (lambda (pl a)
+                                                 (k (list->vector pl) a))))
+                                            (else (k p a)))))
+                             (boundv
+                               (lambda (plist a k)
+                                 (let ((g115 (lambda () (k plist a))))
+                                   (if (pair? plist)
+                                     (if (and (pair? (cdr plist))
+                                              (dot-dot-k? (cadr plist))
+                                              (null? (cddr plist)))
+                                       ((lambda () (bound plist a k)))
+                                       (if (null? plist)
+                                         (g115)
+                                         ((lambda (x y)
+                                            (bound x
+                                                   a
+                                                   (lambda (car-p a)
+                                                     (boundv
+                                                       y
+                                                       a
+                                                       (lambda (cdr-p a)
+                                                         (k (cons car-p cdr-p)
+                                                            a))))))
+                                          (car plist)
+                                          (cdr plist))))
+                                     (if (null? plist)
+                                       (g115)
+                                       (match:error plist))))))
+                             (bound*
+                               (lambda (plist a k)
+                                 (if (null? plist)
+                                   (k plist a)
+                                   (bound (car plist)
+                                          a
+                                          (lambda (car-p a)
+                                            (bound*
+                                              (cdr plist)
+                                              a
+                                              (lambda (cdr-p a)
+                                                (k (cons car-p cdr-p) a))))))))
+                             (find-prefix
+                               (lambda (b a)
+                                 (if (eq? b a)
+                                   '()
+                                   (cons (car b) (find-prefix (cdr b) a)))))
+                             (permutation
+                               (lambda (p1 p2)
+                                 (and (= (length p1) (length p2))
+                                      (match:andmap
+                                        (lambda (x1) (memq x1 p2))
+                                        p1)))))
+                      (bound pattern
+                             '()
+                             (lambda (p a)
+                               (list p (reverse a) pred-bodies))))))
+           (inline-let
+             (lambda (let-exp)
+               (letrec ((occ (lambda (x e)
+                               (let loop ((e e))
+                                 (cond ((pair? e)
+                                        (+ (loop (car e)) (loop (cdr e))))
+                                       ((eq? x e) 1)
+                                       (else 0)))))
+                        (subst (lambda (e old new)
+                                 (let loop ((e e))
+                                   (cond ((pair? e)
+                                          (cons (loop (car e)) (loop (cdr e))))
+                                         ((eq? old e) new)
+                                         (else e)))))
+                        (const?
+                          (lambda (sexp)
+                            (or (symbol? sexp)
+                                (boolean? sexp)
+                                (string? sexp)
+                                (char? sexp)
+                                (number? sexp)
+                                (null? sexp)
+                                (and (pair? sexp)
+                                     (eq? (car sexp) 'quote)
+                                     (pair? (cdr sexp))
+                                     (symbol? (cadr sexp))
+                                     (null? (cddr sexp))))))
+                        (isval?
+                          (lambda (sexp)
+                            (or (const? sexp)
+                                (and (pair? sexp)
+                                     (memq (car sexp)
+                                           '(lambda quote
+                                              match-lambda
+                                              match-lambda*))))))
+                        (small?
+                          (lambda (sexp)
+                            (or (const? sexp)
+                                (and (pair? sexp)
+                                     (eq? (car sexp) 'lambda)
+                                     (pair? (cdr sexp))
+                                     (pair? (cddr sexp))
+                                     (const? (caddr sexp))
+                                     (null? (cdddr sexp)))))))
+                 (let loop ((b (cadr let-exp))
+                            (new-b '())
+                            (e (caddr let-exp)))
+                   (cond ((null? b)
+                          (if (null? new-b) e `(let ,(reverse new-b) ,e)))
+                         ((isval? (cadr (car b)))
+                          (let* ((x (caar b)) (n (occ x e)))
+                            (cond ((= 0 n) (loop (cdr b) new-b e))
+                                  ((or (= 1 n) (small? (cadr (car b))))
+                                   (loop (cdr b)
+                                         new-b
+                                         (subst e x (cadr (car b)))))
+                                  (else
+                                   (loop (cdr b) (cons (car b) new-b) e)))))
+                         (else (loop (cdr b) (cons (car b) new-b) e)))))))
+           (gen (lambda (x sf plist erract length>= eta)
+                  (if (null? plist)
+                    (erract x)
+                    (let* ((v '())
+                           (val (lambda (x) (cdr (assq x v))))
+                           (fail (lambda (sf)
+                                   (gen x sf (cdr plist) erract length>= eta)))
+                           (success
+                             (lambda (sf)
+                               (set-car! (cddddr (car plist)) #t)
+                               (let* ((code (cadr (car plist)))
+                                      (bv (caddr (car plist)))
+                                      (fail-sym (cadddr (car plist))))
+                                 (if fail-sym
+                                   (let ((ap `(,code
+                                               ,fail-sym
+                                               ,@(map val bv))))
+                                     `(call-with-current-continuation
+                                        (lambda (,fail-sym)
+                                          (let ((,fail-sym
+                                                 (lambda ()
+                                                   (,fail-sym ,(fail sf)))))
+                                            ,ap))))
+                                   `(,code ,@(map val bv)))))))
+                      (let next ((p (caar plist))
+                                 (e x)
+                                 (sf sf)
+                                 (kf fail)
+                                 (ks success))
+                        (cond ((eq? '_ p) (ks sf))
+                              ((symbol? p)
+                               (set! v (cons (cons p e) v))
+                               (ks sf))
+                              ((null? p) (emit `(null? ,e) sf kf ks))
+                              ((equal? p ''()) (emit `(null? ,e) sf kf ks))
+                              ((string? p) (emit `(equal? ,e ,p) sf kf ks))
+                              ((boolean? p) (emit `(equal? ,e ,p) sf kf ks))
+                              ((char? p) (emit `(equal? ,e ,p) sf kf ks))
+                              ((number? p) (emit `(equal? ,e ,p) sf kf ks))
+                              ((and (pair? p) (eq? 'quote (car p)))
+                               (emit `(equal? ,e ,p) sf kf ks))
+                              ((and (pair? p) (eq? '? (car p)))
+                               (let ((tst `(,(cadr p) ,e)))
+                                 (emit tst sf kf ks)))
+                              ((and (pair? p) (eq? '= (car p)))
+                               (next (caddr p) `(,(cadr p) ,e) sf kf ks))
+                              ((and (pair? p) (eq? 'and (car p)))
+                               (let loop ((p (cdr p)) (sf sf))
+                                 (if (null? p)
+                                   (ks sf)
+                                   (next (car p)
+                                         e
+                                         sf
+                                         kf
+                                         (lambda (sf) (loop (cdr p) sf))))))
+                              ((and (pair? p) (eq? 'or (car p)))
+                               (let ((or-v v))
+                                 (let loop ((p (cdr p)) (sf sf))
+                                   (if (null? p)
+                                     (kf sf)
+                                     (begin
+                                       (set! v or-v)
+                                       (next (car p)
+                                             e
+                                             sf
+                                             (lambda (sf) (loop (cdr p) sf))
+                                             ks))))))
+                              ((and (pair? p) (eq? 'not (car p)))
+                               (next (cadr p) e sf ks kf))
+                              ((and (pair? p) (eq? '$ (car p)))
+                               (let* ((tag (cadr p))
+                                      (fields (cdr p))
+                                      (rlen (length fields))
+                                      (tst `(,(symbol-append tag '?) ,e)))
+                                 (emit tst
+                                       sf
+                                       kf
+                                       (let rloop ((n 1))
+                                         (lambda (sf)
+                                           (if (= n rlen)
+                                             (ks sf)
+                                             (next (list-ref fields n)
+                                                   `(,(symbol-append tag '- n)
+                                                     ,e)
+                                                   sf
+                                                   kf
+                                                   (rloop (+ 1 n)))))))))
+                              ((and (pair? p) (eq? 'set! (car p)))
+                               (set! v (cons (cons (cadr p) (setter e p)) v))
+                               (ks sf))
+                              ((and (pair? p) (eq? 'get! (car p)))
+                               (set! v (cons (cons (cadr p) (getter e p)) v))
+                               (ks sf))
+                              ((and (pair? p)
+                                    (pair? (cdr p))
+                                    (dot-dot-k? (cadr p)))
+                               (emit `(list? ,e)
+                                     sf
+                                     kf
+                                     (lambda (sf)
+                                       (let* ((k (dot-dot-k? (cadr p)))
+                                              (ks (lambda (sf)
+                                                    (let ((bound (list-ref
+                                                                   p
+                                                                   2)))
+                                                      (cond ((eq? (car p) '_)
+                                                             (ks sf))
+                                                            ((null? bound)
+                                                             (let* ((ptst (next (car p)
+                                                                                eta
+                                                                                sf
+                                                                                (lambda (sf)
+                                                                                  #f)
+                                                                                (lambda (sf)
+                                                                                  #t)))
+                                                                    (tst (if (and (pair? ptst)
+                                                                                  (symbol?
+                                                                                    (car ptst))
+                                                                                  (pair? (cdr ptst))
+                                                                                  (eq? eta
+                                                                                       (cadr ptst))
+                                                                                  (null? (cddr ptst)))
+                                                                           (car ptst)
+                                                                           `(lambda (,eta)
+                                                                              ,ptst))))
+                                                               (assm `(match:andmap
+                                                                        ,tst
+                                                                        ,e)
+                                                                     (kf sf)
+                                                                     (ks sf))))
+                                                            ((and (symbol?
+                                                                    (car p))
+                                                                  (equal?
+                                                                    (list (car p))
+                                                                    bound))
+                                                             (next (car p)
+                                                                   e
+                                                                   sf
+                                                                   kf
+                                                                   ks))
+                                                            (else
+                                                             (let* ((gloop (list-ref
+                                                                             p
+                                                                             3))
+                                                                    (ge (list-ref
+                                                                          p
+                                                                          4))
+                                                                    (fresh (list-ref
+                                                                             p
+                                                                             5))
+                                                                    (p1 (next (car p)
+                                                                              `(car ,ge)
+                                                                              sf
+                                                                              kf
+                                                                              (lambda (sf)
+                                                                                `(,gloop
+                                                                                  (cdr ,ge)
+                                                                                  ,@(map (lambda (b
+                                                                                                  f)
+                                                                                           `(cons ,(val b)
+                                                                                                  ,f))
+                                                                                         bound
+                                                                                         fresh))))))
+                                                               (set! v
+                                                                 (append
+                                                                   (map cons
+                                                                        bound
+                                                                        (map (lambda (x)
+                                                                               `(reverse
+                                                                                  ,x))
+                                                                             fresh))
+                                                                   v))
+                                                               `(let ,gloop
+                                                                  ((,ge ,e)
+                                                                   ,@(map (lambda (x)
+                                                                            `(,x
+                                                                              '()))
+                                                                          fresh))
+                                                                  (if (null? ,ge)
+                                                                    ,(ks sf)
+                                                                    ,p1)))))))))
+                                         (case k
+                                           ((0) (ks sf))
+                                           ((1) (emit `(pair? ,e) sf kf ks))
+                                           (else
+                                            (emit `((,length>= ,k) ,e)
+                                                  sf
+                                                  kf
+                                                  ks)))))))
+                              ((pair? p)
+                               (emit `(pair? ,e)
+                                     sf
+                                     kf
+                                     (lambda (sf)
+                                       (next (car p)
+                                             (add-a e)
+                                             sf
+                                             kf
+                                             (lambda (sf)
+                                               (next (cdr p)
+                                                     (add-d e)
+                                                     sf
+                                                     kf
+                                                     ks))))))
+                              ((and (vector? p)
+                                    (>= (vector-length p) 6)
+                                    (dot-dot-k?
+                                      (vector-ref p (- (vector-length p) 5))))
+                               (let* ((vlen (- (vector-length p) 6))
+                                      (k (dot-dot-k?
+                                           (vector-ref p (+ vlen 1))))
+                                      (minlen (+ vlen k))
+                                      (bound (vector-ref p (+ vlen 2))))
+                                 (emit `(vector? ,e)
+                                       sf
+                                       kf
+                                       (lambda (sf)
+                                         (assm `(>= (vector-length ,e) ,minlen)
+                                               (kf sf)
+                                               ((let vloop ((n 0))
+                                                  (lambda (sf)
+                                                    (cond ((not (= n vlen))
+                                                           (next (vector-ref
+                                                                   p
+                                                                   n)
+                                                                 `(vector-ref
+                                                                    ,e
+                                                                    ,n)
+                                                                 sf
+                                                                 kf
+                                                                 (vloop (+ 1
+                                                                           n))))
+                                                          ((eq? (vector-ref
+                                                                  p
+                                                                  vlen)
+                                                                '_)
+                                                           (ks sf))
+                                                          (else
+                                                           (let* ((gloop (vector-ref
+                                                                           p
+                                                                           (+ vlen
+                                                                              3)))
+                                                                  (ind (vector-ref
+                                                                         p
+                                                                         (+ vlen
+                                                                            4)))
+                                                                  (fresh (vector-ref
+                                                                           p
+                                                                           (+ vlen
+                                                                              5)))
+                                                                  (p1 (next (vector-ref
+                                                                              p
+                                                                              vlen)
+                                                                            `(vector-ref
+                                                                               ,e
+                                                                               ,ind)
+                                                                            sf
+                                                                            kf
+                                                                            (lambda (sf)
+                                                                              `(,gloop
+                                                                                (- ,ind
+                                                                                   1)
+                                                                                ,@(map (lambda (b
+                                                                                                f)
+                                                                                         `(cons ,(val b)
+                                                                                                ,f))
+                                                                                       bound
+                                                                                       fresh))))))
+                                                             (set! v
+                                                               (append
+                                                                 (map cons
+                                                                      bound
+                                                                      fresh)
+                                                                 v))
+                                                             `(let ,gloop
+                                                                ((,ind
+                                                                  (- (vector-length
+                                                                       ,e)
+                                                                     1))
+                                                                 ,@(map (lambda (x)
+                                                                          `(,x
+                                                                            '()))
+                                                                        fresh))
+                                                                (if (> ,minlen
+                                                                       ,ind)
+                                                                  ,(ks sf)
+                                                                  ,p1)))))))
+                                                sf))))))
+                              ((vector? p)
+                               (let ((vlen (vector-length p)))
+                                 (emit `(vector? ,e)
+                                       sf
+                                       kf
+                                       (lambda (sf)
+                                         (emit `(equal?
+                                                  (vector-length ,e)
+                                                  ,vlen)
+                                               sf
+                                               kf
+                                               (let vloop ((n 0))
+                                                 (lambda (sf)
+                                                   (if (= n vlen)
+                                                     (ks sf)
+                                                     (next (vector-ref p n)
+                                                           `(vector-ref ,e ,n)
+                                                           sf
+                                                           kf
+                                                           (vloop (+ 1
+                                                                     n)))))))))))
+                              (else
+                               (display "FATAL ERROR IN PATTERN MATCHER")
+                               (newline)
+                               (error #f "THIS NEVER HAPPENS"))))))))
+           (emit (lambda (tst sf kf ks)
+                   (cond ((in tst sf) (ks sf))
+                         ((in `(not ,tst) sf) (kf sf))
+                         (else
+                          (let* ((e (cadr tst))
+                                 (implied
+                                   (cond ((eq? (car tst) 'equal?)
+                                          (let ((p (caddr tst)))
+                                            (cond ((string? p) `((string? ,e)))
+                                                  ((boolean? p)
+                                                   `((boolean? ,e)))
+                                                  ((char? p) `((char? ,e)))
+                                                  ((number? p) `((number? ,e)))
+                                                  ((and (pair? p)
+                                                        (eq? 'quote (car p)))
+                                                   `((symbol? ,e)))
+                                                  (else '()))))
+                                         ((eq? (car tst) 'null?) `((list? ,e)))
+                                         ((vec-structure? tst) `((vector? ,e)))
+                                         (else '())))
+                                 (not-imp
+                                   (case (car tst)
+                                     ((list?) `((not (null? ,e))))
+                                     (else '())))
+                                 (s (ks (cons tst (append implied sf))))
+                                 (k (kf (cons `(not ,tst)
+                                              (append not-imp sf)))))
+                            (assm tst k s))))))
+           (assm (lambda (tst f s)
+                   (cond ((equal? s f) s)
+                         ((and (eq? s #t) (eq? f #f)) tst)
+                         ((and (eq? (car tst) 'pair?)
+                               (memq match:error-control '(unspecified fail))
+                               (memq (car f) '(cond match:error))
+                               (guarantees s (cadr tst)))
+                          s)
+                         ((and (pair? s)
+                               (eq? (car s) 'if)
+                               (equal? (cadddr s) f))
+                          (if (eq? (car (cadr s)) 'and)
+                            `(if (and ,tst ,@(cdr (cadr s))) ,(caddr s) ,f)
+                            `(if (and ,tst ,(cadr s)) ,(caddr s) ,f)))
+                         ((and (pair? s)
+                               (equal? (car s) 'call-with-current-continuation)
+                               (pair? (cdr s))
+                               (pair? (cadr s))
+                               (equal? (caadr s) 'lambda)
+                               (pair? (cdadr s))
+                               (pair? (cadadr s))
+                               (null? (cdr (cadadr s)))
+                               (pair? (cddadr s))
+                               (pair? (car (cddadr s)))
+                               (equal? (caar (cddadr s)) 'let)
+                               (pair? (cdar (cddadr s)))
+                               (pair? (cadar (cddadr s)))
+                               (pair? (caadar (cddadr s)))
+                               (pair? (cdr (caadar (cddadr s))))
+                               (pair? (cadr (caadar (cddadr s))))
+                               (equal? (caadr (caadar (cddadr s))) 'lambda)
+                               (pair? (cdadr (caadar (cddadr s))))
+                               (null? (cadadr (caadar (cddadr s))))
+                               (pair? (cddadr (caadar (cddadr s))))
+                               (pair? (car (cddadr (caadar (cddadr s)))))
+                               (pair? (cdar (cddadr (caadar (cddadr s)))))
+                               (null? (cddar (cddadr (caadar (cddadr s)))))
+                               (null? (cdr (cddadr (caadar (cddadr s)))))
+                               (null? (cddr (caadar (cddadr s))))
+                               (null? (cdadar (cddadr s)))
+                               (pair? (cddar (cddadr s)))
+                               (null? (cdddar (cddadr s)))
+                               (null? (cdr (cddadr s)))
+                               (null? (cddr s))
+                               (equal? f (cadar (cddadr (caadar (cddadr s))))))
+                          (let ((k (car (cadadr s)))
+                                (fail (car (caadar (cddadr s))))
+                                (s2 (caddar (cddadr s))))
+                            `(call-with-current-continuation
+                               (lambda (,k)
+                                 (let ((,fail (lambda () (,k ,f))))
+                                   ,(assm tst `(,fail) s2))))))
+                         ((and #f
+                               (pair? s)
+                               (equal? (car s) 'let)
+                               (pair? (cdr s))
+                               (pair? (cadr s))
+                               (pair? (caadr s))
+                               (pair? (cdaadr s))
+                               (pair? (car (cdaadr s)))
+                               (equal? (caar (cdaadr s)) 'lambda)
+                               (pair? (cdar (cdaadr s)))
+                               (null? (cadar (cdaadr s)))
+                               (pair? (cddar (cdaadr s)))
+                               (null? (cdddar (cdaadr s)))
+                               (null? (cdr (cdaadr s)))
+                               (null? (cdadr s))
+                               (pair? (cddr s))
+                               (null? (cdddr s))
+                               (equal? (caddar (cdaadr s)) f))
+                          (let ((fail (caaadr s)) (s2 (caddr s)))
+                            `(let ((,fail (lambda () ,f)))
+                               ,(assm tst `(,fail) s2))))
+                         (else `(if ,tst ,s ,f)))))
+           (guarantees
+             (lambda (code x)
+               (let ((a (add-a x)) (d (add-d x)))
+                 (let loop ((code code))
+                   (cond ((not (pair? code)) #f)
+                         ((memq (car code) '(cond match:error)) #t)
+                         ((or (equal? code a) (equal? code d)) #t)
+                         ((eq? (car code) 'if)
+                          (or (loop (cadr code))
+                              (and (loop (caddr code)) (loop (cadddr code)))))
+                         ((eq? (car code) 'lambda) #f)
+                         ((and (eq? (car code) 'let) (symbol? (cadr code)))
+                          #f)
+                         (else (or (loop (car code)) (loop (cdr code)))))))))
+           (in (lambda (e l)
+                 (or (member e l)
+                     (and (eq? (car e) 'list?)
+                          (or (member `(null? ,(cadr e)) l)
+                              (member `(pair? ,(cadr e)) l)))
+                     (and (eq? (car e) 'not)
+                          (let* ((srch (cadr e))
+                                 (const-class (equal-test? srch)))
+                            (cond (const-class
+                                   (let mem ((l l))
+                                     (if (null? l)
+                                       #f
+                                       (let ((x (car l)))
+                                         (or (and (equal? (cadr x) (cadr srch))
+                                                  (disjoint? x)
+                                                  (not (equal?
+                                                         const-class
+                                                         (car x))))
+                                             (equal?
+                                               x
+                                               `(not (,const-class
+                                                      ,(cadr srch))))
+                                             (and (equal? (cadr x) (cadr srch))
+                                                  (equal-test? x)
+                                                  (not (equal?
+                                                         (caddr srch)
+                                                         (caddr x))))
+                                             (mem (cdr l)))))))
+                                  ((disjoint? srch)
+                                   (let mem ((l l))
+                                     (if (null? l)
+                                       #f
+                                       (let ((x (car l)))
+                                         (or (and (equal? (cadr x) (cadr srch))
+                                                  (disjoint? x)
+                                                  (not (equal?
+                                                         (car x)
+                                                         (car srch))))
+                                             (mem (cdr l)))))))
+                                  ((eq? (car srch) 'list?)
+                                   (let mem ((l l))
+                                     (if (null? l)
+                                       #f
+                                       (let ((x (car l)))
+                                         (or (and (equal? (cadr x) (cadr srch))
+                                                  (disjoint? x)
+                                                  (not (memq (car x)
+                                                             '(list? pair?
+                                                                     null?))))
+                                             (mem (cdr l)))))))
+                                  ((vec-structure? srch)
+                                   (let mem ((l l))
+                                     (if (null? l)
+                                       #f
+                                       (let ((x (car l)))
+                                         (or (and (equal? (cadr x) (cadr srch))
+                                                  (or (disjoint? x)
+                                                      (vec-structure? x))
+                                                  (not (equal?
+                                                         (car x)
+                                                         'vector?))
+                                                  (not (equal?
+                                                         (car x)
+                                                         (car srch))))
+                                             (equal?
+                                               x
+                                               `(not (vector? ,(cadr srch))))
+                                             (mem (cdr l)))))))
+                                  (else #f)))))))
+           (equal-test?
+             (lambda (tst)
+               (and (eq? (car tst) 'equal?)
+                    (let ((p (caddr tst)))
+                      (cond ((string? p) 'string?)
+                            ((boolean? p) 'boolean?)
+                            ((char? p) 'char?)
+                            ((number? p) 'number?)
+                            ((and (pair? p)
+                                  (pair? (cdr p))
+                                  (null? (cddr p))
+                                  (eq? 'quote (car p))
+                                  (symbol? (cadr p)))
+                             'symbol?)
+                            (else #f))))))
+           (disjoint?
+             (lambda (tst)
+               (memq (car tst) match:disjoint-predicates)))
+           (vec-structure?
+             (lambda (tst)
+               (memq (car tst) match:vector-structures)))
+           (add-a (lambda (a)
+                    (let ((new (and (pair? a) (assq (car a) c---rs))))
+                      (if new (cons (cadr new) (cdr a)) `(car ,a)))))
+           (add-d (lambda (a)
+                    (let ((new (and (pair? a) (assq (car a) c---rs))))
+                      (if new (cons (cddr new) (cdr a)) `(cdr ,a)))))
+           (c---rs
+             '((car caar . cdar)
+               (cdr cadr . cddr)
+               (caar caaar . cdaar)
+               (cadr caadr . cdadr)
+               (cdar cadar . cddar)
+               (cddr caddr . cdddr)
+               (caaar caaaar . cdaaar)
+               (caadr caaadr . cdaadr)
+               (cadar caadar . cdadar)
+               (caddr caaddr . cdaddr)
+               (cdaar cadaar . cddaar)
+               (cdadr cadadr . cddadr)
+               (cddar caddar . cdddar)
+               (cdddr cadddr . cddddr)))
+           (setter
+             (lambda (e p)
+               (let ((mk-setter
+                       (lambda (s) (symbol-append 'set- s '!))))
+                 (cond ((not (pair? e))
+                        (match:syntax-err p "unnested set! pattern"))
+                       ((eq? (car e) 'vector-ref)
+                        `(let ((x ,(cadr e)))
+                           (lambda (y) (vector-set! x ,(caddr e) y))))
+                       ((eq? (car e) 'unbox)
+                        `(let ((x ,(cadr e))) (lambda (y) (set-box! x y))))
+                       ((eq? (car e) 'car)
+                        `(let ((x ,(cadr e))) (lambda (y) (set-car! x y))))
+                       ((eq? (car e) 'cdr)
+                        `(let ((x ,(cadr e))) (lambda (y) (set-cdr! x y))))
+                       ((let ((a (assq (car e) get-c---rs)))
+                          (and a
+                               `(let ((x (,(cadr a) ,(cadr e))))
+                                  (lambda (y) (,(mk-setter (cddr a)) x y))))))
+                       (else
+                        `(let ((x ,(cadr e)))
+                           (lambda (y) (,(mk-setter (car e)) x y))))))))
+           (getter
+             (lambda (e p)
+               (cond ((not (pair? e))
+                      (match:syntax-err p "unnested get! pattern"))
+                     ((eq? (car e) 'vector-ref)
+                      `(let ((x ,(cadr e)))
+                         (lambda () (vector-ref x ,(caddr e)))))
+                     ((eq? (car e) 'unbox)
+                      `(let ((x ,(cadr e))) (lambda () (unbox x))))
+                     ((eq? (car e) 'car)
+                      `(let ((x ,(cadr e))) (lambda () (car x))))
+                     ((eq? (car e) 'cdr)
+                      `(let ((x ,(cadr e))) (lambda () (cdr x))))
+                     ((let ((a (assq (car e) get-c---rs)))
+                        (and a
+                             `(let ((x (,(cadr a) ,(cadr e))))
+                                (lambda () (,(cddr a) x))))))
+                     (else
+                      `(let ((x ,(cadr e))) (lambda () (,(car e) x)))))))
+           (get-c---rs
+             '((caar car . car)
+               (cadr cdr . car)
+               (cdar car . cdr)
+               (cddr cdr . cdr)
+               (caaar caar . car)
+               (caadr cadr . car)
+               (cadar cdar . car)
+               (caddr cddr . car)
+               (cdaar caar . cdr)
+               (cdadr cadr . cdr)
+               (cddar cdar . cdr)
+               (cdddr cddr . cdr)
+               (caaaar caaar . car)
+               (caaadr caadr . car)
+               (caadar cadar . car)
+               (caaddr caddr . car)
+               (cadaar cdaar . car)
+               (cadadr cdadr . car)
+               (caddar cddar . car)
+               (cadddr cdddr . car)
+               (cdaaar caaar . cdr)
+               (cdaadr caadr . cdr)
+               (cdadar cadar . cdr)
+               (cdaddr caddr . cdr)
+               (cddaar cdaar . cdr)
+               (cddadr cdadr . cdr)
+               (cdddar cddar . cdr)
+               (cddddr cdddr . cdr)))
+           (symbol-append
+             (lambda l
+               (string->symbol
+                 (apply string-append
+                        (map (lambda (x)
+                               (cond ((symbol? x) (symbol->string x))
+                                     ((number? x) (number->string x))
+                                     (else x)))
+                             l)))))
+           (rac (lambda (l)
+                  (if (null? (cdr l)) (car l) (rac (cdr l)))))
+           (rdc (lambda (l)
+                  (if (null? (cdr l))
+                    '()
+                    (cons (car l) (rdc (cdr l)))))))
+    (list genmatch genletrec gendefine pattern-var?)))
+(defmacro
+  match
+  args
+  (cond ((and (list? args)
+              (<= 1 (length args))
+              (match:andmap
+                (lambda (y) (and (list? y) (<= 2 (length y))))
+                (cdr args)))
+         (let* ((exp (car args))
+                (clauses (cdr args))
+                (e (if (symbol? exp) exp (gentemp))))
+           (if (symbol? exp)
+             ((car match:expanders) e clauses `(match ,@args))
+             `(let ((,e ,exp))
+                ,((car match:expanders) e clauses `(match ,@args))))))
+        (else
+         (match:syntax-err
+           `(match ,@args)
+           "syntax error in"))))
+(defmacro
+  match-lambda
+  args
+  (if (and (list? args)
+           (match:andmap
+             (lambda (g126)
+               (if (and (pair? g126) (list? (cdr g126)))
+                 (pair? (cdr g126))
+                 #f))
+             args))
+    ((lambda ()
+       (let ((e (gentemp)))
+         `(lambda (,e) (match ,e ,@args)))))
+    ((lambda ()
+       (match:syntax-err
+         `(match-lambda ,@args)
+         "syntax error in")))))
+(defmacro
+  match-lambda*
+  args
+  (if (and (list? args)
+           (match:andmap
+             (lambda (g134)
+               (if (and (pair? g134) (list? (cdr g134)))
+                 (pair? (cdr g134))
+                 #f))
+             args))
+    ((lambda ()
+       (let ((e (gentemp)))
+         `(lambda ,e (match ,e ,@args)))))
+    ((lambda ()
+       (match:syntax-err
+         `(match-lambda* ,@args)
+         "syntax error in")))))
+(defmacro
+  match-let
+  args
+  (let ((g158 (lambda (pat exp body)
+                `(match ,exp (,pat ,@body))))
+        (g154 (lambda (pat exp body)
+                (let ((g (map (lambda (x) (gentemp)) pat))
+                      (vpattern (list->vector pat)))
+                  `(let ,(map list g exp)
+                     (match (vector ,@g) (,vpattern ,@body))))))
+        (g146 (lambda ()
+                (match:syntax-err
+                  `(match-let ,@args)
+                  "syntax error in")))
+        (g145 (lambda (p1 e1 p2 e2 body)
+                (let ((g1 (gentemp)) (g2 (gentemp)))
+                  `(let ((,g1 ,e1) (,g2 ,e2))
+                     (match (cons ,g1 ,g2) ((,p1 unquote p2) ,@body))))))
+        (g136 (cadddr match:expanders)))
+    (if (pair? args)
+      (if (symbol? (car args))
+        (if (and (pair? (cdr args)) (list? (cadr args)))
+          (let g161 ((g162 (cadr args)) (g160 '()) (g159 '()))
+            (if (null? g162)
+              (if (and (list? (cddr args)) (pair? (cddr args)))
+                ((lambda (name pat exp body)
+                   (if (match:andmap (cadddr match:expanders) pat)
+                     `(let ,@args)
+                     `(letrec ((,name (match-lambda* (,pat ,@body))))
+                        (,name ,@exp))))
+                 (car args)
+                 (reverse g159)
+                 (reverse g160)
+                 (cddr args))
+                (g146))
+              (if (and (pair? (car g162))
+                       (pair? (cdar g162))
+                       (null? (cddar g162)))
+                (g161 (cdr g162)
+                      (cons (cadar g162) g160)
+                      (cons (caar g162) g159))
+                (g146))))
+          (g146))
+        (if (list? (car args))
+          (if (match:andmap
+                (lambda (g167)
+                  (if (and (pair? g167)
+                           (g136 (car g167))
+                           (pair? (cdr g167)))
+                    (null? (cddr g167))
+                    #f))
+                (car args))
+            (if (and (list? (cdr args)) (pair? (cdr args)))
+              ((lambda () `(let ,@args)))
+              (let g149 ((g150 (car args)) (g148 '()) (g147 '()))
+                (if (null? g150)
+                  (g146)
+                  (if (and (pair? (car g150))
+                           (pair? (cdar g150))
+                           (null? (cddar g150)))
+                    (g149 (cdr g150)
+                          (cons (cadar g150) g148)
+                          (cons (caar g150) g147))
+                    (g146)))))
+            (if (and (pair? (car args))
+                     (pair? (caar args))
+                     (pair? (cdaar args))
+                     (null? (cddaar args)))
+              (if (null? (cdar args))
+                (if (and (list? (cdr args)) (pair? (cdr args)))
+                  (g158 (caaar args) (cadaar args) (cdr args))
+                  (let g149 ((g150 (car args)) (g148 '()) (g147 '()))
+                    (if (null? g150)
+                      (g146)
+                      (if (and (pair? (car g150))
+                               (pair? (cdar g150))
+                               (null? (cddar g150)))
+                        (g149 (cdr g150)
+                              (cons (cadar g150) g148)
+                              (cons (caar g150) g147))
+                        (g146)))))
+                (if (and (pair? (cdar args))
+                         (pair? (cadar args))
+                         (pair? (cdadar args))
+                         (null? (cdr (cdadar args)))
+                         (null? (cddar args)))
+                  (if (and (list? (cdr args)) (pair? (cdr args)))
+                    (g145 (caaar args)
+                          (cadaar args)
+                          (caadar args)
+                          (car (cdadar args))
+                          (cdr args))
+                    (let g149 ((g150 (car args)) (g148 '()) (g147 '()))
+                      (if (null? g150)
+                        (g146)
+                        (if (and (pair? (car g150))
+                                 (pair? (cdar g150))
+                                 (null? (cddar g150)))
+                          (g149 (cdr g150)
+                                (cons (cadar g150) g148)
+                                (cons (caar g150) g147))
+                          (g146)))))
+                  (let g149 ((g150 (car args)) (g148 '()) (g147 '()))
+                    (if (null? g150)
+                      (if (and (list? (cdr args)) (pair? (cdr args)))
+                        (g154 (reverse g147) (reverse g148) (cdr args))
+                        (g146))
+                      (if (and (pair? (car g150))
+                               (pair? (cdar g150))
+                               (null? (cddar g150)))
+                        (g149 (cdr g150)
+                              (cons (cadar g150) g148)
+                              (cons (caar g150) g147))
+                        (g146))))))
+              (let g149 ((g150 (car args)) (g148 '()) (g147 '()))
+                (if (null? g150)
+                  (if (and (list? (cdr args)) (pair? (cdr args)))
+                    (g154 (reverse g147) (reverse g148) (cdr args))
+                    (g146))
+                  (if (and (pair? (car g150))
+                           (pair? (cdar g150))
+                           (null? (cddar g150)))
+                    (g149 (cdr g150)
+                          (cons (cadar g150) g148)
+                          (cons (caar g150) g147))
+                    (g146))))))
+          (if (pair? (car args))
+            (if (and (pair? (caar args))
+                     (pair? (cdaar args))
+                     (null? (cddaar args)))
+              (if (null? (cdar args))
+                (if (and (list? (cdr args)) (pair? (cdr args)))
+                  (g158 (caaar args) (cadaar args) (cdr args))
+                  (let g149 ((g150 (car args)) (g148 '()) (g147 '()))
+                    (if (null? g150)
+                      (g146)
+                      (if (and (pair? (car g150))
+                               (pair? (cdar g150))
+                               (null? (cddar g150)))
+                        (g149 (cdr g150)
+                              (cons (cadar g150) g148)
+                              (cons (caar g150) g147))
+                        (g146)))))
+                (if (and (pair? (cdar args))
+                         (pair? (cadar args))
+                         (pair? (cdadar args))
+                         (null? (cdr (cdadar args)))
+                         (null? (cddar args)))
+                  (if (and (list? (cdr args)) (pair? (cdr args)))
+                    (g145 (caaar args)
+                          (cadaar args)
+                          (caadar args)
+                          (car (cdadar args))
+                          (cdr args))
+                    (let g149 ((g150 (car args)) (g148 '()) (g147 '()))
+                      (if (null? g150)
+                        (g146)
+                        (if (and (pair? (car g150))
+                                 (pair? (cdar g150))
+                                 (null? (cddar g150)))
+                          (g149 (cdr g150)
+                                (cons (cadar g150) g148)
+                                (cons (caar g150) g147))
+                          (g146)))))
+                  (let g149 ((g150 (car args)) (g148 '()) (g147 '()))
+                    (if (null? g150)
+                      (if (and (list? (cdr args)) (pair? (cdr args)))
+                        (g154 (reverse g147) (reverse g148) (cdr args))
+                        (g146))
+                      (if (and (pair? (car g150))
+                               (pair? (cdar g150))
+                               (null? (cddar g150)))
+                        (g149 (cdr g150)
+                              (cons (cadar g150) g148)
+                              (cons (caar g150) g147))
+                        (g146))))))
+              (let g149 ((g150 (car args)) (g148 '()) (g147 '()))
+                (if (null? g150)
+                  (if (and (list? (cdr args)) (pair? (cdr args)))
+                    (g154 (reverse g147) (reverse g148) (cdr args))
+                    (g146))
+                  (if (and (pair? (car g150))
+                           (pair? (cdar g150))
+                           (null? (cddar g150)))
+                    (g149 (cdr g150)
+                          (cons (cadar g150) g148)
+                          (cons (caar g150) g147))
+                    (g146)))))
+            (g146))))
+      (g146))))
+(defmacro
+  match-let*
+  args
+  (let ((g176 (lambda ()
+                (match:syntax-err
+                  `(match-let* ,@args)
+                  "syntax error in"))))
+    (if (pair? args)
+      (if (null? (car args))
+        (if (and (list? (cdr args)) (pair? (cdr args)))
+          ((lambda (body) `(let* ,@args)) (cdr args))
+          (g176))
+        (if (and (pair? (car args))
+                 (pair? (caar args))
+                 (pair? (cdaar args))
+                 (null? (cddaar args))
+                 (list? (cdar args))
+                 (list? (cdr args))
+                 (pair? (cdr args)))
+          ((lambda (pat exp rest body)
+             (if ((cadddr match:expanders) pat)
+               `(let ((,pat ,exp)) (match-let* ,rest ,@body))
+               `(match ,exp (,pat (match-let* ,rest ,@body)))))
+           (caaar args)
+           (cadaar args)
+           (cdar args)
+           (cdr args))
+          (g176)))
+      (g176))))
+(defmacro
+  match-letrec
+  args
+  (let ((g200 (cadddr match:expanders))
+        (g199 (lambda (p1 e1 p2 e2 body)
+                `(match-letrec
+                   (((,p1 unquote p2) (cons ,e1 ,e2)))
+                   ,@body)))
+        (g195 (lambda ()
+                (match:syntax-err
+                  `(match-letrec ,@args)
+                  "syntax error in")))
+        (g194 (lambda (pat exp body)
+                `(match-letrec
+                   ((,(list->vector pat) (vector ,@exp)))
+                   ,@body)))
+        (g186 (lambda (pat exp body)
+                ((cadr match:expanders)
+                 pat
+                 exp
+                 body
+                 `(match-letrec ((,pat ,exp)) ,@body)))))
+    (if (pair? args)
+      (if (list? (car args))
+        (if (match:andmap
+              (lambda (g206)
+                (if (and (pair? g206)
+                         (g200 (car g206))
+                         (pair? (cdr g206)))
+                  (null? (cddr g206))
+                  #f))
+              (car args))
+          (if (and (list? (cdr args)) (pair? (cdr args)))
+            ((lambda () `(letrec ,@args)))
+            (let g189 ((g190 (car args)) (g188 '()) (g187 '()))
+              (if (null? g190)
+                (g195)
+                (if (and (pair? (car g190))
+                         (pair? (cdar g190))
+                         (null? (cddar g190)))
+                  (g189 (cdr g190)
+                        (cons (cadar g190) g188)
+                        (cons (caar g190) g187))
+                  (g195)))))
+          (if (and (pair? (car args))
+                   (pair? (caar args))
+                   (pair? (cdaar args))
+                   (null? (cddaar args)))
+            (if (null? (cdar args))
+              (if (and (list? (cdr args)) (pair? (cdr args)))
+                (g186 (caaar args) (cadaar args) (cdr args))
+                (let g189 ((g190 (car args)) (g188 '()) (g187 '()))
+                  (if (null? g190)
+                    (g195)
+                    (if (and (pair? (car g190))
+                             (pair? (cdar g190))
+                             (null? (cddar g190)))
+                      (g189 (cdr g190)
+                            (cons (cadar g190) g188)
+                            (cons (caar g190) g187))
+                      (g195)))))
+              (if (and (pair? (cdar args))
+                       (pair? (cadar args))
+                       (pair? (cdadar args))
+                       (null? (cdr (cdadar args)))
+                       (null? (cddar args)))
+                (if (and (list? (cdr args)) (pair? (cdr args)))
+                  (g199 (caaar args)
+                        (cadaar args)
+                        (caadar args)
+                        (car (cdadar args))
+                        (cdr args))
+                  (let g189 ((g190 (car args)) (g188 '()) (g187 '()))
+                    (if (null? g190)
+                      (g195)
+                      (if (and (pair? (car g190))
+                               (pair? (cdar g190))
+                               (null? (cddar g190)))
+                        (g189 (cdr g190)
+                              (cons (cadar g190) g188)
+                              (cons (caar g190) g187))
+                        (g195)))))
+                (let g189 ((g190 (car args)) (g188 '()) (g187 '()))
+                  (if (null? g190)
+                    (if (and (list? (cdr args)) (pair? (cdr args)))
+                      (g194 (reverse g187) (reverse g188) (cdr args))
+                      (g195))
+                    (if (and (pair? (car g190))
+                             (pair? (cdar g190))
+                             (null? (cddar g190)))
+                      (g189 (cdr g190)
+                            (cons (cadar g190) g188)
+                            (cons (caar g190) g187))
+                      (g195))))))
+            (let g189 ((g190 (car args)) (g188 '()) (g187 '()))
+              (if (null? g190)
+                (if (and (list? (cdr args)) (pair? (cdr args)))
+                  (g194 (reverse g187) (reverse g188) (cdr args))
+                  (g195))
+                (if (and (pair? (car g190))
+                         (pair? (cdar g190))
+                         (null? (cddar g190)))
+                  (g189 (cdr g190)
+                        (cons (cadar g190) g188)
+                        (cons (caar g190) g187))
+                  (g195))))))
+        (if (pair? (car args))
+          (if (and (pair? (caar args))
+                   (pair? (cdaar args))
+                   (null? (cddaar args)))
+            (if (null? (cdar args))
+              (if (and (list? (cdr args)) (pair? (cdr args)))
+                (g186 (caaar args) (cadaar args) (cdr args))
+                (let g189 ((g190 (car args)) (g188 '()) (g187 '()))
+                  (if (null? g190)
+                    (g195)
+                    (if (and (pair? (car g190))
+                             (pair? (cdar g190))
+                             (null? (cddar g190)))
+                      (g189 (cdr g190)
+                            (cons (cadar g190) g188)
+                            (cons (caar g190) g187))
+                      (g195)))))
+              (if (and (pair? (cdar args))
+                       (pair? (cadar args))
+                       (pair? (cdadar args))
+                       (null? (cdr (cdadar args)))
+                       (null? (cddar args)))
+                (if (and (list? (cdr args)) (pair? (cdr args)))
+                  (g199 (caaar args)
+                        (cadaar args)
+                        (caadar args)
+                        (car (cdadar args))
+                        (cdr args))
+                  (let g189 ((g190 (car args)) (g188 '()) (g187 '()))
+                    (if (null? g190)
+                      (g195)
+                      (if (and (pair? (car g190))
+                               (pair? (cdar g190))
+                               (null? (cddar g190)))
+                        (g189 (cdr g190)
+                              (cons (cadar g190) g188)
+                              (cons (caar g190) g187))
+                        (g195)))))
+                (let g189 ((g190 (car args)) (g188 '()) (g187 '()))
+                  (if (null? g190)
+                    (if (and (list? (cdr args)) (pair? (cdr args)))
+                      (g194 (reverse g187) (reverse g188) (cdr args))
+                      (g195))
+                    (if (and (pair? (car g190))
+                             (pair? (cdar g190))
+                             (null? (cddar g190)))
+                      (g189 (cdr g190)
+                            (cons (cadar g190) g188)
+                            (cons (caar g190) g187))
+                      (g195))))))
+            (let g189 ((g190 (car args)) (g188 '()) (g187 '()))
+              (if (null? g190)
+                (if (and (list? (cdr args)) (pair? (cdr args)))
+                  (g194 (reverse g187) (reverse g188) (cdr args))
+                  (g195))
+                (if (and (pair? (car g190))
+                         (pair? (cdar g190))
+                         (null? (cddar g190)))
+                  (g189 (cdr g190)
+                        (cons (cadar g190) g188)
+                        (cons (caar g190) g187))
+                  (g195)))))
+          (g195)))
+      (g195))))
+(defmacro
+  match-define
+  args
+  (let ((g210 (cadddr match:expanders))
+        (g209 (lambda ()
+                (match:syntax-err
+                  `(match-define ,@args)
+                  "syntax error in"))))
+    (if (pair? args)
+      (if (g210 (car args))
+        (if (and (pair? (cdr args)) (null? (cddr args)))
+          ((lambda () `(begin (define ,@args))))
+          (g209))
+        (if (and (pair? (cdr args)) (null? (cddr args)))
+          ((lambda (pat exp)
+             ((caddr match:expanders)
+              pat
+              exp
+              `(match-define ,@args)))
+           (car args)
+           (cadr args))
+          (g209)))
+      (g209))))
+(define match:runtime-structures #f)
+(define match:set-runtime-structures
+  (lambda (v) (set! match:runtime-structures v)))
+(define match:primitive-vector? vector?)
+(defmacro
+  defstruct
+  args
+  (let ((field?
+          (lambda (x)
+            (if (symbol? x)
+              ((lambda () #t))
+              (if (and (pair? x)
+                       (symbol? (car x))
+                       (pair? (cdr x))
+                       (symbol? (cadr x))
+                       (null? (cddr x)))
+                ((lambda () #t))
+                ((lambda () #f))))))
+        (selector-name
+          (lambda (x)
+            (if (symbol? x)
+              ((lambda () x))
+              (if (and (pair? x)
+                       (symbol? (car x))
+                       (pair? (cdr x))
+                       (null? (cddr x)))
+                ((lambda (s) s) (car x))
+                (match:error x)))))
+        (mutator-name
+          (lambda (x)
+            (if (symbol? x)
+              ((lambda () #f))
+              (if (and (pair? x)
+                       (pair? (cdr x))
+                       (symbol? (cadr x))
+                       (null? (cddr x)))
+                ((lambda (s) s) (cadr x))
+                (match:error x)))))
+        (filter-map-with-index
+          (lambda (f l)
+            (letrec ((mapi (lambda (l i)
+                             (cond ((null? l) '())
+                                   ((f (car l) i)
+                                    =>
+                                    (lambda (x)
+                                      (cons x (mapi (cdr l) (+ 1 i)))))
+                                   (else (mapi (cdr l) (+ 1 i)))))))
+              (mapi l 1)))))
+    (let ((g227 (lambda ()
+                  (match:syntax-err
+                    `(defstruct ,@args)
+                    "syntax error in"))))
+      (if (and (pair? args)
+               (symbol? (car args))
+               (pair? (cdr args))
+               (symbol? (cadr args))
+               (pair? (cddr args))
+               (symbol? (caddr args))
+               (list? (cdddr args)))
+        (let g229 ((g230 (cdddr args)) (g228 '()))
+          (if (null? g230)
+            ((lambda (name constructor predicate fields)
+               (let* ((selectors (map selector-name fields))
+                      (mutators (map mutator-name fields))
+                      (tag (if match:runtime-structures
+                             (gentemp)
+                             `',(match:make-structure-tag name)))
+                      (vectorp
+                        (cond ((eq? match:structure-control 'disjoint)
+                               'match:primitive-vector?)
+                              ((eq? match:structure-control 'vector)
+                               'vector?))))
+                 (cond ((eq? match:structure-control 'disjoint)
+                        (if (eq? vector? match:primitive-vector?)
+                          (set! vector?
+                            (lambda (v)
+                              (and (match:primitive-vector? v)
+                                   (or (zero? (vector-length v))
+                                       (not (symbol? (vector-ref v 0)))
+                                       (not (match:structure?
+                                              (vector-ref v 0))))))))
+                        (if (not (memq predicate match:disjoint-predicates))
+                          (set! match:disjoint-predicates
+                            (cons predicate match:disjoint-predicates))))
+                       ((eq? match:structure-control 'vector)
+                        (if (not (memq predicate match:vector-structures))
+                          (set! match:vector-structures
+                            (cons predicate match:vector-structures))))
+                       (else
+                        (match:syntax-err
+                          '(vector disjoint)
+                          "invalid value for match:structure-control, legal values are")))
+                 `(begin
+                    ,@(if match:runtime-structures
+                        `((define ,tag (match:make-structure-tag ',name)))
+                        '())
+                    (define ,constructor
+                      (lambda ,selectors (vector ,tag ,@selectors)))
+                    (define ,predicate
+                      (lambda (obj)
+                        (and (,vectorp obj)
+                             (= (vector-length obj) ,(+ 1 (length selectors)))
+                             (eq? (vector-ref obj 0) ,tag))))
+                    ,@(filter-map-with-index
+                        (lambda (n i)
+                          `(define ,n (lambda (obj) (vector-ref obj ,i))))
+                        selectors)
+                    ,@(filter-map-with-index
+                        (lambda (n i)
+                          (and n
+                               `(define ,n
+                                  (lambda (obj newval)
+                                    (vector-set! obj ,i newval)))))
+                        mutators))))
+             (car args)
+             (cadr args)
+             (caddr args)
+             (reverse g228))
+            (if (field? (car g230))
+              (g229 (cdr g230) (cons (car g230) g228))
+              (g227))))
+        (g227)))))
+(defmacro
+  define-structure
+  args
+  (let ((g242 (lambda ()
+                (match:syntax-err
+                  `(define-structure ,@args)
+                  "syntax error in"))))
+    (if (and (pair? args)
+             (pair? (car args))
+             (list? (cdar args)))
+      (if (null? (cdr args))
+        ((lambda (name id1)
+           `(define-structure (,name ,@id1) ()))
+         (caar args)
+         (cdar args))
+        (if (and (pair? (cdr args)) (list? (cadr args)))
+          (let g239 ((g240 (cadr args)) (g238 '()) (g237 '()))
+            (if (null? g240)
+              (if (null? (cddr args))
+                ((lambda (name id1 id2 val)
+                   (let ((mk-id (lambda (id)
+                                  (if (and (pair? id)
+                                           (equal? (car id) '@)
+                                           (pair? (cdr id))
+                                           (symbol? (cadr id))
+                                           (null? (cddr id)))
+                                    ((lambda (x) x) (cadr id))
+                                    ((lambda () `(! ,id)))))))
+                     `(define-const-structure
+                        (,name ,@(map mk-id id1))
+                        ,(map (lambda (id v) `(,(mk-id id) ,v)) id2 val))))
+                 (caar args)
+                 (cdar args)
+                 (reverse g237)
+                 (reverse g238))
+                (g242))
+              (if (and (pair? (car g240))
+                       (pair? (cdar g240))
+                       (null? (cddar g240)))
+                (g239 (cdr g240)
+                      (cons (cadar g240) g238)
+                      (cons (caar g240) g237))
+                (g242))))
+          (g242)))
+      (g242))))
+(defmacro
+  define-const-structure
+  args
+  (let ((field?
+          (lambda (id)
+            (if (symbol? id)
+              ((lambda () #t))
+              (if (and (pair? id)
+                       (equal? (car id) '!)
+                       (pair? (cdr id))
+                       (symbol? (cadr id))
+                       (null? (cddr id)))
+                ((lambda () #t))
+                ((lambda () #f))))))
+        (field-name
+          (lambda (x) (if (symbol? x) x (cadr x))))
+        (has-mutator? (lambda (x) (not (symbol? x))))
+        (filter-map-with-index
+          (lambda (f l)
+            (letrec ((mapi (lambda (l i)
+                             (cond ((null? l) '())
+                                   ((f (car l) i)
+                                    =>
+                                    (lambda (x)
+                                      (cons x (mapi (cdr l) (+ 1 i)))))
+                                   (else (mapi (cdr l) (+ 1 i)))))))
+              (mapi l 1))))
+        (symbol-append
+          (lambda l
+            (string->symbol
+              (apply string-append
+                     (map (lambda (x)
+                            (cond ((symbol? x) (symbol->string x))
+                                  ((number? x) (number->string x))
+                                  (else x)))
+                          l))))))
+    (let ((g266 (lambda ()
+                  (match:syntax-err
+                    `(define-const-structure ,@args)
+                    "syntax error in"))))
+      (if (and (pair? args)
+               (pair? (car args))
+               (list? (cdar args)))
+        (if (null? (cdr args))
+          ((lambda (name id1)
+             `(define-const-structure (,name ,@id1) ()))
+           (caar args)
+           (cdar args))
+          (if (symbol? (caar args))
+            (let g259 ((g260 (cdar args)) (g258 '()))
+              (if (null? g260)
+                (if (and (pair? (cdr args)) (list? (cadr args)))
+                  (let g263 ((g264 (cadr args)) (g262 '()) (g261 '()))
+                    (if (null? g264)
+                      (if (null? (cddr args))
+                        ((lambda (name id1 id2 val)
+                           (let* ((id1id2 (append id1 id2))
+                                  (raw-constructor
+                                    (symbol-append 'make-raw- name))
+                                  (constructor (symbol-append 'make- name))
+                                  (predicate (symbol-append name '?)))
+                             `(begin
+                                (defstruct
+                                  ,name
+                                  ,raw-constructor
+                                  ,predicate
+                                  ,@(filter-map-with-index
+                                      (lambda (arg i)
+                                        (if (has-mutator? arg)
+                                          `(,(symbol-append name '- i)
+                                            ,(symbol-append
+                                               'set-
+                                               name
+                                               '-
+                                               i
+                                               '!))
+                                          (symbol-append name '- i)))
+                                      id1id2))
+                                ,(let* ((make-fresh
+                                          (lambda (x)
+                                            (if (eq? '_ x) (gentemp) x)))
+                                        (names1
+                                          (map make-fresh
+                                               (map field-name id1)))
+                                        (names2
+                                          (map make-fresh
+                                               (map field-name id2))))
+                                   `(define ,constructor
+                                      (lambda ,names1
+                                        (let* ,(map list names2 val)
+                                          (,raw-constructor
+                                           ,@names1
+                                           ,@names2)))))
+                                ,@(filter-map-with-index
+                                    (lambda (field i)
+                                      (if (eq? (field-name field) '_)
+                                        #f
+                                        `(define (unquote
+                                                  (symbol-append
+                                                    name
+                                                    '-
+                                                    (field-name field)))
+                                           ,(symbol-append name '- i))))
+                                    id1id2)
+                                ,@(filter-map-with-index
+                                    (lambda (field i)
+                                      (if (or (eq? (field-name field) '_)
+                                              (not (has-mutator? field)))
+                                        #f
+                                        `(define (unquote
+                                                  (symbol-append
+                                                    'set-
+                                                    name
+                                                    '-
+                                                    (field-name field)
+                                                    '!))
+                                           ,(symbol-append
+                                              'set-
+                                              name
+                                              '-
+                                              i
+                                              '!))))
+                                    id1id2))))
+                         (caar args)
+                         (reverse g258)
+                         (reverse g261)
+                         (reverse g262))
+                        (g266))
+                      (if (and (pair? (car g264))
+                               (field? (caar g264))
+                               (pair? (cdar g264))
+                               (null? (cddar g264)))
+                        (g263 (cdr g264)
+                              (cons (cadar g264) g262)
+                              (cons (caar g264) g261))
+                        (g266))))
+                  (g266))
+                (if (field? (car g260))
+                  (g259 (cdr g260) (cons (car g260) g258))
+                  (g266))))
+            (g266)))
+        (g266)))))
+(define home-directory
+  (or (getenv "HOME")
+      (error "environment variable HOME is not defined")))
+(defmacro recur args `(let ,@args))
+(defmacro
+  rec
+  args
+  (match args
+         (((? symbol? x) v) `(letrec ((,x ,v)) ,x))))
+(defmacro
+  parameterize
+  args
+  (match args ((bindings exp ...) `(begin ,@exp))))
+(define gensym gentemp)
+(define expand-once macroexpand-1)
+(defmacro check-increment-counter args #f)
+(define symbol-append
+  (lambda l
+    (string->symbol
+      (apply string-append
+             (map (lambda (x) (format #f "~a" x)) l)))))
+(define gensym gentemp)
+(define andmap
+  (lambda (f . lists)
+    (cond ((null? (car lists)) (and))
+          ((null? (cdr (car lists)))
+           (apply f (map car lists)))
+          (else
+           (and (apply f (map car lists))
+                (apply andmap f (map cdr lists)))))))
+(define true-object? (lambda (x) (eq? #t x)))
+(define false-object? (lambda (x) (eq? #f x)))
+(define void (lambda () (cond (#f #f))))
+(defmacro
+  when
+  args
+  (match args
+         ((tst body __1)
+          `(if ,tst (begin ,@body (void)) (void)))))
+(defmacro
+  unless
+  args
+  (match args
+         ((tst body __1)
+          `(if ,tst (void) (begin ,@body (void))))))
+(define should-never-reach
+  (lambda (form)
+    (slib:error "fell off end of " form)))
+(define make-cvector make-vector)
+(define cvector vector)
+(define cvector-length vector-length)
+(define cvector-ref vector-ref)
+(define cvector->list vector->list)
+(define list->cvector list->vector)
+(define-const-structure (record _))
+(defmacro
+  record
+  args
+  (match args
+         ((((? symbol? id) exp) ...)
+          `(make-record
+             (list ,@(map (lambda (i x) `(cons ',i ,x)) id exp))))
+         (_ (slib:error "syntax error at " `(record ,@args)))))
+(defmacro
+  field
+  args
+  (match args
+         (((? symbol? id) exp)
+          `(match ,exp
+                  (($ record x)
+                   (match (assq ',id x)
+                          (#f
+                           (slib:error
+                             "no field "
+                             ,id
+                             'in
+                             (cons 'record (map car x))))
+                          ((_ . x) x)))
+                  (_ (slib:error "not a record: " '(field ,id _)))))
+         (_ (slib:error "syntax error at " `(field ,@args)))))
+(define-const-structure (module _))
+(defmacro
+  module
+  args
+  (match args
+         (((i ...) defs ...)
+          `(let ()
+             ,@defs
+             (make-module
+               (record ,@(map (lambda (x) (list x x)) i)))))
+         (_ (slib:error "syntax error at " `(module ,@args)))))
+(defmacro
+  import
+  args
+  (match args
+         ((((mod defs ...) ...) body __1)
+          (let* ((m (map (lambda (_) (gentemp)) mod))
+                 (newdefs
+                   (let loop ((mod-names m) (l-defs defs))
+                     (if (null? mod-names)
+                       '()
+                       (append
+                         (let ((m (car mod-names)))
+                           (map (match-lambda
+                                  ((? symbol? x) `(,x (field ,x ,m)))
+                                  (((? symbol? i) (? symbol? e))
+                                   `(,i (field ,e ,m)))
+                                  (x (slib:error "ill-formed definition: " x)))
+                                (car l-defs)))
+                         (loop (cdr mod-names) (cdr l-defs)))))))
+            `(let (unquote
+                   (map (lambda (m mod)
+                          `(,m (match ,mod (($ module x) x))))
+                        m
+                        mod))
+               (let ,newdefs body ...))))))
+(define raise
+  (lambda vals
+    (slib:error "Unhandled exception " vals)))
+(defmacro
+  fluid-let
+  args
+  (match args
+         ((((x val) ...) body __1)
+          (let ((old-x (map (lambda (_) (gentemp)) x))
+                (swap-x (map (lambda (_) (gentemp)) x))
+                (swap (gentemp)))
+            `(let ,(map list old-x val)
+               (let ((,swap
+                      (lambda ()
+                        (let ,(map list swap-x old-x)
+                          ,@(map (lambda (old x) `(set! ,old ,x)) old-x x)
+                          ,@(map (lambda (x swap) `(set! ,x ,swap))
+                                 x
+                                 swap-x)))))
+                 (dynamic-wind ,swap (lambda () ,@body) ,swap)))))
+         (_ (slib:error
+              "syntax error at "
+              `(fluid-let ,@args)))))
+(defmacro
+  handle
+  args
+  (match args
+         ((e h)
+          (let ((k (gentemp)) (exn (gentemp)))
+            `((call-with-current-continuation
+                (lambda (k)
+                  (fluid-let
+                    ((raise (lambda ,exn (k (lambda () (apply ,h ,exn))))))
+                    (let ((v ,e)) (lambda () v))))))))
+         (_ (slib:error "syntax error in " `(handle ,@args)))))
+(defmacro
+  :
+  args
+  (match args ((typeexp exp) exp)))
+(defmacro
+  module:
+  args
+  (match args
+         ((((i type) ...) defs ...)
+          `(let ()
+             ,@defs
+             (make-module
+               (record
+                 ,@(map (lambda (i type) `(,i (: ,type ,i))) i type)))))))
+(defmacro
+  define:
+  args
+  (match args
+         ((name type exp) `(define ,name (: ,type ,exp)))))
+(define st:failure
+  (lambda (chk fmt . args)
+    (slib:error
+      (apply format
+             #f
+             (string-append "~a : " fmt)
+             chk
+             args))))
+(defmacro
+  check-bound
+  args
+  (match args
+         ((var) var)
+         (x (st:failure `(check-bound ,@x) "syntax-error"))))
+(defmacro
+  clash
+  args
+  (match args
+         ((name info ...) name)
+         (x (st:failure `(clash ,@x) "syntax error"))))
+(defmacro
+  check-lambda
+  args
+  (match args
+         (((id info ...) (? symbol? args) body __1)
+          `(lambda ,args
+             (check-increment-counter ,id)
+             ,@body))
+         (((id info ...) args body __1)
+          (let* ((n 0)
+                 (chk (let loop ((a args) (nargs 0))
+                        (cond ((pair? a) (loop (cdr a) (+ 1 nargs)))
+                              ((null? a)
+                               (set! n nargs)
+                               `(= ,nargs (length args)))
+                              (else
+                               (set! n nargs)
+                               `(<= ,nargs (length args))))))
+                 (incr (if (number? id)
+                         `(check-increment-counter ,id)
+                         #f)))
+            `(let ((lam (lambda ,args ,@body)))
+               (lambda args
+                 ,incr
+                 (if ,chk
+                   (apply lam args)
+                   ,(if (eq? '= (car chk))
+                      `(st:failure
+                         '(check-lambda ,id ,@info)
+                         "requires ~a arguments, passed: ~a"
+                         ,n
+                         args)
+                      `(st:failure
+                         '(check-lambda ,id ,@info)
+                         "requires >= ~a arguments, passed: ~a"
+                         ,n
+                         args)))))))
+         (x (st:failure `(check-lambda ,@x) "syntax error"))))
+(defmacro
+  check-ap
+  args
+  (match args
+         (((id info ...) (? symbol? f) args ...)
+          `(begin
+             (check-increment-counter ,id)
+             (if (procedure? ,f)
+               (,f ,@args)
+               (st:failure
+                 '(check-ap ,id ,@info)
+                 "not a procedure: ~a"
+                 ,f))))
+         (((id info ...) f args ...)
+          `((lambda (proc . args)
+              (check-increment-counter ,id)
+              (if (procedure? proc)
+                (apply proc args)
+                (st:failure
+                  '(check-ap ,id ,@info)
+                  "not a procedure: ~a"
+                  proc)))
+            ,f
+            ,@args))
+         (x (st:failure `(check-ap ,@x) "syntax error"))))
+(defmacro
+  check-field
+  args
+  (match args
+         (((id info ...) (? symbol? f) exp)
+          `(match ,exp
+                  (($ record x)
+                   (match (assq ',f x)
+                          (#f
+                           (st:failure
+                             '(check-field ,id ,@info)
+                             "no ~a field in (record ~a)"
+                             ',f
+                             (map car x)))
+                          ((_ . x) x)))
+                  (v (st:failure
+                       '(check-field ,id ,@info)
+                       "not a record: ~a"
+                       v))))
+         (x (st:failure `(check-field ,@x) "syntax error"))))
+(defmacro
+  check-match
+  args
+  (match args
+         (((id info ...) exp (and clause (pat _ __1)) ...)
+          (letrec ((last (lambda (pl)
+                           (if (null? (cdr pl)) (car pl) (last (cdr pl))))))
+            (if (match (last pat)
+                       ((? symbol?) #t)
+                       (('and subp ...) (andmap symbol? subp))
+                       (_ #f))
+              `(begin
+                 (check-increment-counter ,id)
+                 (match ,exp ,@clause))
+              `(begin
+                 (check-increment-counter ,id)
+                 (match ,exp
+                        ,@clause
+                        (x (st:failure
+                             '(check-match ,id ,@info)
+                             "no matching clause for ~a"
+                             x)))))))
+         (x (st:failure `(check-match ,@x) "syntax error"))))
+(defmacro
+  check-:
+  args
+  (match args
+         (((id info ...) typeexp exp)
+          `(st:failure
+             '(check-: ,id ,@info)
+             "static type annotation reached"))
+         (x (st:failure `(check-: ,@x) "syntax error"))))
+(defmacro
+  make-check-typed
+  args
+  (match args
+         ((prim)
+          (let ((chkprim (symbol-append 'check- prim)))
+            (list 'defmacro
+                  chkprim
+                  'id
+                  (list 'quasiquote
+                        `(lambda a
+                           (check-increment-counter (,'unquote (car id)))
+                           (if (null? a)
+                             (,prim)
+                             (st:failure
+                               (cons ',chkprim '(,'unquote id))
+                               "invalid arguments: ~a"
+                               a)))))))
+         ((prim '_)
+          (let ((chkprim (symbol-append 'check- prim)))
+            (list 'defmacro
+                  chkprim
+                  'id
+                  (list 'quasiquote
+                        `(lambda a
+                           (check-increment-counter (,'unquote (car id)))
+                           (if (= 1 (length a))
+                             (,prim (car a))
+                             (st:failure
+                               (cons ',chkprim '(,'unquote id))
+                               "invalid arguments: ~a"
+                               a)))))))
+         ((prim type1)
+          (let ((chkprim (symbol-append 'check- prim)))
+            (list 'defmacro
+                  chkprim
+                  'id
+                  (list 'quasiquote
+                        `(lambda a
+                           (check-increment-counter (,'unquote (car id)))
+                           (if (and (= 1 (length a)) (,type1 (car a)))
+                             (,prim (car a))
+                             (st:failure
+                               (cons ',chkprim '(,'unquote id))
+                               "invalid arguments: ~a"
+                               a)))))))
+         ((prim '_ '_)
+          (let ((chkprim (symbol-append 'check- prim)))
+            (list 'defmacro
+                  chkprim
+                  'id
+                  (list 'quasiquote
+                        `(lambda a
+                           (check-increment-counter (,'unquote (car id)))
+                           (if (= 2 (length a))
+                             (,prim (car a) (cadr a))
+                             (st:failure
+                               (cons ',chkprim '(,'unquote id))
+                               "invalid arguments: ~a"
+                               a)))))))
+         ((prim '_ type2)
+          (let ((chkprim (symbol-append 'check- prim)))
+            (list 'defmacro
+                  chkprim
+                  'id
+                  (list 'quasiquote
+                        `(lambda a
+                           (check-increment-counter (,'unquote (car id)))
+                           (if (and (= 2 (length a)) (,type2 (cadr a)))
+                             (,prim (car a) (cadr a))
+                             (st:failure
+                               (cons ',chkprim '(,'unquote id))
+                               "invalid arguments: ~a"
+                               a)))))))
+         ((prim type1 '_)
+          (let ((chkprim (symbol-append 'check- prim)))
+            (list 'defmacro
+                  chkprim
+                  'id
+                  (list 'quasiquote
+                        `(lambda a
+                           (check-increment-counter (,'unquote (car id)))
+                           (if (and (= 2 (length a)) (,type1 (car a)))
+                             (,prim (car a) (cadr a))
+                             (st:failure
+                               (cons ',chkprim '(,'unquote id))
+                               "invalid arguments: ~a"
+                               a)))))))
+         ((prim type1 type2)
+          (let ((chkprim (symbol-append 'check- prim)))
+            (list 'defmacro
+                  chkprim
+                  'id
+                  (list 'quasiquote
+                        `(lambda a
+                           (check-increment-counter (,'unquote (car id)))
+                           (if (and (= 2 (length a))
+                                    (,type1 (car a))
+                                    (,type2 (cadr a)))
+                             (,prim (car a) (cadr a))
+                             (st:failure
+                               (cons ',chkprim '(,'unquote id))
+                               "invalid arguments: ~a"
+                               a)))))))
+         ((prim types ...)
+          (let ((nargs (length types))
+                (chkprim (symbol-append 'check- prim))
+                (types (map (match-lambda ('_ '(lambda (_) #t)) (x x))
+                            types)))
+            (list 'defmacro
+                  chkprim
+                  'id
+                  (list 'quasiquote
+                        `(lambda a
+                           (check-increment-counter (,'unquote (car id)))
+                           (if (and (= ,nargs (length a))
+                                    (andmap
+                                      (lambda (f a) (f a))
+                                      (list ,@types)
+                                      a))
+                             (apply ,prim a)
+                             (st:failure
+                               (cons ',chkprim '(,'unquote id))
+                               "invalid arguments: ~a"
+                               a)))))))))
+(defmacro
+  make-check-selector
+  args
+  (match args
+         ((prim pat)
+          (let ((chkprim (symbol-append 'check- prim)))
+            (list 'defmacro
+                  chkprim
+                  'id
+                  (list 'quasiquote
+                        `(lambda a
+                           (check-increment-counter (,'unquote (car id)))
+                           (match a
+                                  ((,pat) x)
+                                  (_ (st:failure
+                                       (cons ',chkprim '(,'unquote id))
+                                       "invalid arguments: ~a"
+                                       a))))))))))
+(make-check-typed number? _)
+(make-check-typed null? _)
+(make-check-typed char? _)
+(make-check-typed symbol? _)
+(make-check-typed string? _)
+(make-check-typed vector? _)
+(make-check-typed box? _)
+(make-check-typed pair? _)
+(make-check-typed procedure? _)
+(make-check-typed eof-object? _)
+(make-check-typed input-port? _)
+(make-check-typed output-port? _)
+(make-check-typed true-object? _)
+(make-check-typed false-object? _)
+(make-check-typed boolean? _)
+(make-check-typed list? _)
+(make-check-typed not _)
+(make-check-typed eqv? _ _)
+(make-check-typed eq? _ _)
+(make-check-typed equal? _ _)
+(make-check-typed cons _ _)
+(make-check-selector car (x . _))
+(make-check-selector cdr (_ . x))
+(make-check-selector caar ((x . _) . _))
+(make-check-selector cadr (_ x . _))
+(make-check-selector cdar ((_ . x) . _))
+(make-check-selector cddr (_ _ . x))
+(make-check-selector caaar (((x . _) . _) . _))
+(make-check-selector caadr (_ (x . _) . _))
+(make-check-selector cadar ((_ x . _) . _))
+(make-check-selector caddr (_ _ x . _))
+(make-check-selector cdaar (((_ . x) . _) . _))
+(make-check-selector cdadr (_ (_ . x) . _))
+(make-check-selector cddar ((_ _ . x) . _))
+(make-check-selector cdddr (_ _ _ . x))
+(make-check-selector
+  caaaar
+  ((((x . _) . _) . _) . _))
+(make-check-selector
+  caaadr
+  (_ ((x . _) . _) . _))
+(make-check-selector
+  caadar
+  ((_ (x . _) . _) . _))
+(make-check-selector caaddr (_ _ (x . _) . _))
+(make-check-selector
+  cadaar
+  (((_ x . _) . _) . _))
+(make-check-selector cadadr (_ (_ x . _) . _))
+(make-check-selector caddar ((_ _ x . _) . _))
+(make-check-selector cadddr (_ _ _ x . _))
+(make-check-selector
+  cdaaar
+  ((((_ . x) . _) . _) . _))
+(make-check-selector
+  cdaadr
+  (_ ((_ . x) . _) . _))
+(make-check-selector
+  cdadar
+  ((_ (_ . x) . _) . _))
+(make-check-selector cdaddr (_ _ (_ . x) . _))
+(make-check-selector
+  cddaar
+  (((_ _ . x) . _) . _))
+(make-check-selector cddadr (_ (_ _ . x) . _))
+(make-check-selector cdddar ((_ _ _ . x) . _))
+(make-check-selector cddddr (_ _ _ _ . x))
+(make-check-typed set-car! pair? _)
+(make-check-typed set-cdr! pair? _)
+(defmacro
+  check-list
+  id
+  `(lambda a
+     (check-increment-counter ,(car id))
+     (apply list a)))
+(make-check-typed length list?)
+(defmacro
+  check-append
+  id
+  `(lambda a
+     (check-increment-counter ,(car id))
+     (let loop ((b a))
+       (match b
+              (() #t)
+              ((l) #t)
+              (((? list?) . y) (loop y))
+              (_ (st:failure
+                   (cons 'check-append ',id)
+                   "invalid arguments: ~a"
+                   a))))
+     (apply append a)))
+(make-check-typed reverse list?)
+(make-check-typed list-tail list? number?)
+(make-check-typed list-ref list? number?)
+(make-check-typed memq _ list?)
+(make-check-typed memv _ list?)
+(make-check-typed member _ list?)
+(defmacro
+  check-assq
+  id
+  `(lambda a
+     (check-increment-counter ,(car id))
+     (if (and (= 2 (length a))
+              (list? (cadr a))
+              (andmap pair? (cadr a)))
+       (assq (car a) (cadr a))
+       (st:failure
+         (cons 'check-assq ',id)
+         "invalid arguments: ~a"
+         a))))
+(defmacro
+  check-assv
+  id
+  `(lambda a
+     (check-increment-counter ,(car id))
+     (if (and (= 2 (length a))
+              (list? (cadr a))
+              (andmap pair? (cadr a)))
+       (assv (car a) (cadr a))
+       (st:failure
+         (cons 'check-assv ',id)
+         "invalid arguments: ~a"
+         a))))
+(defmacro
+  check-assoc
+  id
+  `(lambda a
+     (check-increment-counter ,(car id))
+     (if (and (= 2 (length a))
+              (list? (cadr a))
+              (andmap pair? (cadr a)))
+       (assoc (car a) (cadr a))
+       (st:failure
+         (cons 'check-assoc ',id)
+         "invalid arguments: ~a"
+         a))))
+(make-check-typed symbol->string symbol?)
+(make-check-typed string->symbol string?)
+(make-check-typed complex? _)
+(make-check-typed real? _)
+(make-check-typed rational? _)
+(make-check-typed integer? _)
+(make-check-typed exact? number?)
+(make-check-typed inexact? number?)
+(defmacro
+  check-=
+  id
+  `(lambda a
+     (check-increment-counter ,(car id))
+     (if (and (<= 2 (length a)) (andmap number? a))
+       (apply = a)
+       (st:failure
+         (cons 'check-= ',id)
+         "invalid arguments: ~a"
+         a))))
+(defmacro
+  check-<
+  id
+  `(lambda a
+     (check-increment-counter ,(car id))
+     (if (and (<= 2 (length a)) (andmap number? a))
+       (apply < a)
+       (st:failure
+         (cons 'check-< ',id)
+         "invalid arguments: ~a"
+         a))))
+(defmacro
+  check->
+  id
+  `(lambda a
+     (check-increment-counter ,(car id))
+     (if (and (<= 2 (length a)) (andmap number? a))
+       (apply > a)
+       (st:failure
+         (cons 'check-> ',id)
+         "invalid arguments: ~a"
+         a))))
+(defmacro
+  check-<=
+  id
+  `(lambda a
+     (check-increment-counter ,(car id))
+     (if (and (<= 2 (length a)) (andmap number? a))
+       (apply <= a)
+       (st:failure
+         (cons 'check-<= ',id)
+         "invalid arguments: ~a"
+         a))))
+(defmacro
+  check->=
+  id
+  `(lambda a
+     (check-increment-counter ,(car id))
+     (if (and (<= 2 (length a)) (andmap number? a))
+       (apply >= a)
+       (st:failure
+         (cons 'check->= ',id)
+         "invalid arguments: ~a"
+         a))))
+(make-check-typed zero? number?)
+(make-check-typed positive? number?)
+(make-check-typed negative? number?)
+(make-check-typed odd? number?)
+(make-check-typed even? number?)
+(defmacro
+  check-max
+  id
+  `(lambda a
+     (check-increment-counter ,(car id))
+     (if (and (<= 1 (length a)) (andmap number? a))
+       (apply max a)
+       (st:failure
+         (cons 'check-max ',id)
+         "invalid arguments: ~a"
+         a))))
+(defmacro
+  check-min
+  id
+  `(lambda a
+     (check-increment-counter ,(car id))
+     (if (and (<= 1 (length a)) (andmap number? a))
+       (apply min a)
+       (st:failure
+         (cons 'check-min ',id)
+         "invalid arguments: ~a"
+         a))))
+(defmacro
+  check-+
+  id
+  `(lambda a
+     (check-increment-counter ,(car id))
+     (if (andmap number? a)
+       (apply + a)
+       (st:failure
+         (cons 'check-+ ',id)
+         "invalid arguments: ~a"
+         a))))
+(defmacro
+  check-*
+  id
+  `(lambda a
+     (check-increment-counter ,(car id))
+     (if (andmap number? a)
+       (apply * a)
+       (st:failure
+         (cons 'check-* ',id)
+         "invalid arguments: ~a"
+         a))))
+(defmacro
+  check--
+  id
+  `(lambda a
+     (check-increment-counter ,(car id))
+     (if (and (<= 1 (length a)) (andmap number? a))
+       (apply - a)
+       (st:failure
+         (cons 'check-- ',id)
+         "invalid arguments: ~a"
+         a))))
+(defmacro
+  check-/
+  id
+  `(lambda a
+     (check-increment-counter ,(car id))
+     (if (and (<= 1 (length a)) (andmap number? a))
+       (apply / a)
+       (st:failure
+         (cons 'check-/ ',id)
+         "invalid arguments: ~a"
+         a))))
+(make-check-typed abs number?)
+(make-check-typed quotient number? number?)
+(make-check-typed remainder number? number?)
+(make-check-typed modulo number? number?)
+(defmacro
+  check-gcd
+  id
+  `(lambda a
+     (check-increment-counter ,(car id))
+     (if (andmap number? a)
+       (apply gcd a)
+       (st:failure
+         (cons 'check-gcd ',id)
+         "invalid arguments: ~a"
+         a))))
+(defmacro
+  check-lcm
+  id
+  `(lambda a
+     (check-increment-counter ,(car id))
+     (if (andmap number? a)
+       (apply lcm a)
+       (st:failure
+         (cons 'check-lcm ',id)
+         "invalid arguments: ~a"
+         a))))
+(make-check-typed numerator number?)
+(make-check-typed denominator number?)
+(make-check-typed floor number?)
+(make-check-typed ceiling number?)
+(make-check-typed truncate number?)
+(make-check-typed round number?)
+(make-check-typed rationalize number? number?)
+(make-check-typed exp number?)
+(make-check-typed log number?)
+(make-check-typed sin number?)
+(make-check-typed cos number?)
+(make-check-typed tan number?)
+(make-check-typed asin number?)
+(make-check-typed acos number?)
+(defmacro
+  check-atan
+  id
+  `(lambda a
+     (check-increment-counter ,(car id))
+     (if (and (andmap number? a)
+              (pair? a)
+              (>= 2 (length a)))
+       (apply atan a)
+       (st:failure
+         (cons 'check-atan ',id)
+         "invalid arguments: ~a"
+         a))))
+(make-check-typed sqrt number?)
+(make-check-typed expt number? number?)
+(make-check-typed
+  make-rectangular
+  number?
+  number?)
+(make-check-typed make-polar number? number?)
+(make-check-typed real-part number?)
+(make-check-typed imag-part number?)
+(make-check-typed magnitude number?)
+(make-check-typed angle number?)
+(make-check-typed exact->inexact number?)
+(make-check-typed inexact->exact number?)
+(defmacro
+  check-number->string
+  id
+  `(lambda a
+     (check-increment-counter ,(car id))
+     (if (and (andmap number? a)
+              (pair? a)
+              (>= 2 (length a)))
+       (apply number->string a)
+       (st:failure
+         (cons 'check-number->string ',id)
+         "invalid arguments: ~a"
+         a))))
+(defmacro
+  check-string->number
+  id
+  `(lambda a
+     (check-increment-counter ,(car id))
+     (if (and (pair? a)
+              (string? (car a))
+              (>= 2 (length a))
+              (or (null? (cdr a)) (number? (cadr a))))
+       (apply string->number a)
+       (st:failure
+         (cons 'check-string->number ',id)
+         "invalid arguments: ~a"
+         a))))
+(make-check-typed char=? char? char?)
+(make-check-typed char<? char? char?)
+(make-check-typed char>? char? char?)
+(make-check-typed char<=? char? char?)
+(make-check-typed char>=? char? char?)
+(make-check-typed char-ci=? char? char?)
+(make-check-typed char-ci<? char? char?)
+(make-check-typed char-ci>? char? char?)
+(make-check-typed char-ci<=? char? char?)
+(make-check-typed char-ci>=? char? char?)
+(make-check-typed char-alphabetic? char?)
+(make-check-typed char-numeric? char?)
+(make-check-typed char-whitespace? char?)
+(make-check-typed char-upper-case? char?)
+(make-check-typed char-lower-case? char?)
+(make-check-typed char->integer char?)
+(make-check-typed integer->char number?)
+(make-check-typed char-upcase char?)
+(make-check-typed char-downcase char?)
+(defmacro
+  check-make-string
+  id
+  `(lambda a
+     (check-increment-counter ,(car id))
+     (if (and (pair? a)
+              (number? (car a))
+              (>= 2 (length a))
+              (or (null? (cdr a)) (char? (cadr a))))
+       (apply make-string a)
+       (st:failure
+         (cons 'check-make-string ',id)
+         "invalid arguments: ~a"
+         a))))
+(defmacro
+  check-string
+  id
+  `(lambda a
+     (check-increment-counter ,(car id))
+     (if (andmap char? a)
+       (apply string a)
+       (st:failure
+         (cons 'check-string ',id)
+         "invalid arguments: ~a"
+         a))))
+(make-check-typed string-length string?)
+(make-check-typed string-ref string? number?)
+(make-check-typed
+  string-set!
+  string?
+  number?
+  char?)
+(make-check-typed string=? string? string?)
+(make-check-typed string<? string? string?)
+(make-check-typed string>? string? string?)
+(make-check-typed string<=? string? string?)
+(make-check-typed string>=? string? string?)
+(make-check-typed string-ci=? string? string?)
+(make-check-typed string-ci<? string? string?)
+(make-check-typed string-ci>? string? string?)
+(make-check-typed string-ci<=? string? string?)
+(make-check-typed string-ci>=? string? string?)
+(make-check-typed
+  substring
+  string?
+  number?
+  number?)
+(defmacro
+  check-string-append
+  id
+  `(lambda a
+     (check-increment-counter ,(car id))
+     (if (andmap string? a)
+       (apply string-append a)
+       (st:failure
+         (cons 'check-string-append ',id)
+         "invalid arguments: ~a"
+         a))))
+(make-check-typed string->list string?)
+(defmacro
+  check-list->string
+  id
+  `(lambda a
+     (check-increment-counter ,(car id))
+     (if (and (= 1 (length a))
+              (list? (car a))
+              (andmap char? (car a)))
+       (list->string (car a))
+       (st:failure
+         (cons 'check-list->string ',id)
+         "invalid arguments: ~a"
+         a))))
+(make-check-typed string-copy string?)
+(make-check-typed string-fill! string? char?)
+(make-check-typed make-vector number? _)
+(defmacro
+  check-vector
+  id
+  `(lambda a
+     (check-increment-counter ,(car id))
+     (apply vector a)))
+(make-check-typed vector-length vector?)
+(make-check-typed vector-ref vector? number?)
+(make-check-typed vector-set! vector? number? _)
+(make-check-typed vector->list vector?)
+(make-check-typed list->vector list?)
+(make-check-typed vector-fill! vector? _)
+(defmacro
+  check-apply
+  id
+  `(lambda a
+     (check-increment-counter ,(car id))
+     (if (pair? a)
+       (let loop ((arg (cdr a)))
+         (match arg
+                (((? list?)) (apply apply a))
+                ((_ . y) (loop y))
+                (_ (st:failure
+                     (cons 'check-apply ',id)
+                     "invalid arguments: ~a"
+                     a))))
+       (st:failure
+         `(check-apply ,@id)
+         "invalid arguments: ~a"
+         a))))
+(defmacro
+  check-map
+  id
+  `(lambda a
+     (check-increment-counter ,(car id))
+     (if (and (<= 2 (length a))
+              (procedure? (car a))
+              (andmap list? (cdr a)))
+       (apply map a)
+       (st:failure
+         (cons 'check-map ',id)
+         "invalid arguments: ~a"
+         a))))
+(defmacro
+  check-for-each
+  id
+  `(lambda a
+     (check-increment-counter ,(car id))
+     (if (and (<= 2 (length a))
+              (procedure? (car a))
+              (andmap list? (cdr a)))
+       (apply for-each a)
+       (st:failure
+         (cons 'check-for-each ',id)
+         "invalid arguments: ~a"
+         a))))
+(make-check-typed force procedure?)
+(defmacro
+  check-call-with-current-continuation
+  id
+  `(lambda a
+     (check-increment-counter ,(car id))
+     (if (and (= 1 (length a)) (procedure? (car a)))
+       (call-with-current-continuation
+         (lambda (k)
+           ((car a) (check-lambda (continuation) (x) (k x)))))
+       (st:failure
+         (cons 'check-call-with-current-continuation ',id)
+         "invalid arguments: ~a"
+         a))))
+(make-check-typed
+  call-with-input-file
+  string?
+  procedure?)
+(make-check-typed
+  call-with-output-file
+  string?
+  procedure?)
+(make-check-typed input-port? _)
+(make-check-typed output-port? _)
+(make-check-typed current-input-port)
+(make-check-typed current-output-port)
+(make-check-typed
+  with-input-from-file
+  string?
+  procedure?)
+(make-check-typed
+  with-output-to-file
+  string?
+  procedure?)
+(make-check-typed open-input-file string?)
+(make-check-typed open-output-file string?)
+(make-check-typed close-input-port input-port?)
+(make-check-typed close-output-port output-port?)
+(defmacro
+  check-read
+  id
+  `(lambda a
+     (check-increment-counter ,(car id))
+     (if (or (null? a)
+             (and (= 1 (length a)) (input-port? (car a))))
+       (apply read a)
+       (st:failure
+         (cons 'check-read ',id)
+         "invalid arguments: ~a"
+         a))))
+(defmacro
+  check-read-char
+  id
+  `(lambda a
+     (check-increment-counter ,(car id))
+     (if (or (null? a)
+             (and (= 1 (length a)) (input-port? (car a))))
+       (apply read-char a)
+       (st:failure
+         (cons 'check-read-char ',id)
+         "invalid arguments: ~a"
+         a))))
+(defmacro
+  check-peek-char
+  id
+  `(lambda a
+     (check-increment-counter ,(car id))
+     (if (or (null? a)
+             (and (= 1 (length a)) (input-port? (car a))))
+       (apply peek-char a)
+       (st:failure
+         (cons 'check-peek-char ',id)
+         "invalid arguments: ~a"
+         a))))
+(defmacro
+  check-char-ready?
+  id
+  `(lambda a
+     (check-increment-counter ,(car id))
+     (if (or (null? a)
+             (and (= 1 (length a)) (input-port? (car a))))
+       (apply char-ready? a)
+       (st:failure
+         (cons 'check-char-ready? ',id)
+         "invalid arguments: ~a"
+         a))))
+(defmacro
+  check-write
+  id
+  `(lambda a
+     (check-increment-counter ,(car id))
+     (if (and (pair? a)
+              (or (null? (cdr a)) (output-port? (cadr a))))
+       (apply write a)
+       (st:failure
+         (cons 'check-write ',id)
+         "invalid arguments: ~a"
+         a))))
+(defmacro
+  check-display
+  id
+  `(lambda a
+     (check-increment-counter ,(car id))
+     (if (and (pair? a)
+              (or (null? (cdr a)) (output-port? (cadr a))))
+       (apply display a)
+       (st:failure
+         (cons 'check-display ',id)
+         "invalid arguments: ~a"
+         a))))
+(defmacro
+  check-newline
+  id
+  `(lambda a
+     (check-increment-counter ,(car id))
+     (if (or (null? a) (output-port? (car a)))
+       (apply newline a)
+       (st:failure
+         (cons 'check-newline ',id)
+         "invalid arguments: ~a"
+         a))))
+(defmacro
+  check-write-char
+  id
+  `(lambda a
+     (check-increment-counter ,(car id))
+     (if (and (pair? a)
+              (char? (car a))
+              (or (null? (cdr a)) (output-port? (cadr a))))
+       (apply write-char a)
+       (st:failure
+         (cons 'check-write-char ',id)
+         "invalid arguments: ~a"
+         a))))
+(make-check-typed load string?)
+(make-check-typed transcript-on string?)
+(make-check-typed transcript-off)
+(defmacro
+  check-symbol-append
+  id
+  `(lambda a
+     (check-increment-counter ,(car id))
+     (apply symbol-append a)))
+(make-check-typed box _)
+(make-check-typed unbox box?)
+(make-check-typed set-box! box? _)
+(make-check-typed void)
+(make-check-typed make-module _)
+(defmacro
+  check-match:error
+  id
+  `(lambda a
+     (check-increment-counter ,(car id))
+     (if (pair? a)
+       (apply match:error a)
+       (st:failure
+         (cons 'check-match:error ',id)
+         "invalid arguments: ~a"
+         a))))
+(make-check-typed should-never-reach symbol?)
+(defmacro
+  check-make-cvector
+  id
+  `(lambda a
+     (check-increment-counter ,(car id))
+     (if (and (pair? a)
+              (number? (car a))
+              (= 2 (length a)))
+       (apply make-cvector a)
+       (st:failure
+         (cons 'check-make-cvector ',id)
+         "invalid arguments: ~a"
+         a))))
+(defmacro
+  check-cvector
+  id
+  `(lambda a
+     (check-increment-counter ,(car id))
+     (apply cvector a)))
+(make-check-typed cvector-length cvector?)
+(make-check-typed cvector-ref cvector? number?)
+(make-check-typed cvector->list cvector?)
+(make-check-typed list->cvector list?)
+(defmacro
+  check-define-const-structure
+  args
+  (let ((field?
+          (lambda (x)
+            (or (symbol? x)
+                (and (pair? x)
+                     (equal? (car x) '!)
+                     (pair? (cdr x))
+                     (symbol? (cadr x))
+                     (null? (cddr x))))))
+        (arg-name
+          (lambda (x) (if (symbol? x) x (cadr x))))
+        (with-mutator? (lambda (x) (not (symbol? x)))))
+    (match args
+           ((((? symbol? name) (? field? id1) ...))
+            (let ((constructor (symbol-append 'make- name))
+                  (check-constructor
+                    (symbol-append 'check-make- name))
+                  (predicate (symbol-append name '?))
+                  (access
+                    (let loop ((l id1))
+                      (cond ((null? l) '())
+                            ((eq? '_ (arg-name (car l))) (loop (cdr l)))
+                            (else
+                             (cons (symbol-append name '- (arg-name (car l)))
+                                   (loop (cdr l)))))))
+                  (assign
+                    (let loop ((l id1))
+                      (cond ((null? l) '())
+                            ((eq? '_ (arg-name (car l))) (loop (cdr l)))
+                            ((not (with-mutator? (car l))) (loop (cdr l)))
+                            (else
+                             (cons (symbol-append
+                                     'set-
+                                     name
+                                     '-
+                                     (arg-name (car l))
+                                     '!)
+                                   (loop (cdr l)))))))
+                  (nargs (length id1)))
+              `(begin
+                 (define-const-structure (,name ,@id1) ())
+                 (defmacro
+                   ,check-constructor
+                   id
+                   (lambda a
+                     (check-increment-counter (,'unquote (car id)))
+                     (if (= ,nargs (length a))
+                       (apply ,constructor a)
+                       (st:failure
+                         (cons ',check-constructor '(,'unquote id))
+                         "invalid arguments: ~a"
+                         a))))
+                 (make-check-typed ,predicate _)
+                 ,@(map (lambda (a) `(make-check-typed ,a ,predicate))
+                        access)
+                 ,@(map (lambda (a) `(make-check-typed ,a ,predicate _))
+                        assign))))
+           (x (st:failure
+                `(check-define-const-structure ,@x)
+                "syntax error")))))
+(if (equal? '(match 1) (macroexpand-1 '(match 1)))
+  (load "/home/wright/scheme/match/match-slib.scm"))
+(define sprintf
+  (lambda args (apply format #f args)))
+(define printf
+  (lambda args (apply format #t args)))
+(define disaster
+  (lambda (context fmt . args)
+    (slib:error
+      (apply sprintf
+             (string-append "in ~a: " fmt)
+             context
+             args))))
+(define use-error
+  (lambda (fmt . args)
+    (slib:error (apply sprintf fmt args))))
+(define syntax-err
+  (lambda (context fmt . args)
+    (newline)
+    (if context (pretty-print context))
+    (slib:error
+      (apply sprintf
+             (string-append "in syntax: " fmt)
+             args))))
+(define flush-output force-output)
+(define print-context
+  (lambda (obj depth)
+    (pretty-print
+      (recur loop
+             ((obj obj) (n 0))
+             (if (pair? obj)
+               (if (< n depth)
+                 (cons (loop (car obj) (+ 1 n))
+                       (loop (cdr obj) n))
+                 '(...))
+               obj)))))
+(define *box-tag* (gensym))
+(define box (lambda (a) (cons *box-tag* a)))
+(define box?
+  (lambda (b)
+    (and (pair? b) (eq? (car b) *box-tag*))))
+(define unbox cdr)
+(define box-1 cdr)
+(define set-box! set-cdr!)
+(define sort-list sort)
+(define expand-once-if-macro
+  (lambda (e)
+    (and (macro? (car e)) (macroexpand-1 e))))
+(define ormap
+  (lambda (f . lists)
+    (if (null? (car lists))
+      (or)
+      (or (apply f (map car lists))
+          (apply ormap f (map cdr lists))))))
+(define call/cc call-with-current-continuation)
+(define (cpu-time) 0)
+(define (pretty-print x) (display x) (newline))
+(define clock-granularity 1.0e-3)
+(define set-vector! vector-set!)
+(define set-string! string-set!)
+(define maplr
+  (lambda (f l)
+    (match l
+           (() '())
+           ((x . y) (let ((v (f x))) (cons v (maplr f y)))))))
+(define maprl
+  (lambda (f l)
+    (match l
+           (() '())
+           ((x . y) (let ((v (maprl f y))) (cons (f x) v))))))
+(define foldl
+  (lambda (f i l)
+    (recur loop
+           ((l l) (acc i))
+           (match l (() acc) ((x . y) (loop y (f x acc)))))))
+(define foldr
+  (lambda (f i l)
+    (recur loop
+           ((l l))
+           (match l (() i) ((x . y) (f x (loop y)))))))
+(define filter
+  (lambda (p l)
+    (match l
+           (() '())
+           ((x . y)
+            (if (p x) (cons x (filter p y)) (filter p y))))))
+(define filter-map
+  (lambda (p l)
+    (match l
+           (() '())
+           ((x . y)
+            (match (p x)
+                   (#f (filter-map p y))
+                   (x (cons x (filter-map p y))))))))
+(define rac
+  (lambda (l)
+    (match l ((last) last) ((_ . rest) (rac rest)))))
+(define rdc
+  (lambda (l)
+    (match l
+           ((_) '())
+           ((x . rest) (cons x (rdc rest))))))
+(define map-with-n
+  (lambda (f l)
+    (recur loop
+           ((l l) (n 0))
+           (match l
+                  (() '())
+                  ((x . y)
+                   (let ((v (f x n))) (cons v (loop y (+ 1 n)))))))))
+(define readfile
+  (lambda (f)
+    (with-input-from-file
+      f
+      (letrec ((rf (lambda ()
+                     (match (read)
+                            ((? eof-object?) '())
+                            (sexp (cons sexp (rf)))))))
+        rf))))
+(define map2
+  (lambda (f a b)
+    (match (cons a b)
+           ((()) '())
+           (((ax . ay) bx . by)
+            (let ((v (f ax bx))) (cons v (map2 f ay by))))
+           (else (error 'map2 "lists differ in length")))))
+(define for-each2
+  (lambda (f a b)
+    (match (cons a b)
+           ((()) (void))
+           (((ax . ay) bx . by)
+            (f ax bx)
+            (for-each2 f ay by))
+           (else (error 'for-each2 "lists differ in length")))))
+(define andmap2
+  (lambda (f a b)
+    (match (cons a b)
+           ((()) (and))
+           (((ax) bx) (f ax bx))
+           (((ax . ay) bx . by)
+            (and (f ax bx) (andmap2 f ay by)))
+           (else (error 'andmap2 "lists differ in length")))))
+(define ormap2
+  (lambda (f a b)
+    (match (cons a b)
+           ((()) (or))
+           (((ax) bx) (f ax bx))
+           (((ax . ay) bx . by)
+            (or (f ax bx) (ormap2 f ay by)))
+           (else (error 'ormap2 "lists differ in length")))))
+(define empty-set '())
+(define empty-set? null?)
+(define set (lambda l (list->set l)))
+(define list->set
+  (match-lambda
+    (() '())
+    ((x . y)
+     (if (memq x y)
+       (list->set y)
+       (cons x (list->set y))))))
+(define element-of?
+  (lambda (x set) (and (memq x set) #t)))
+(define cardinality length)
+(define set<=
+  (lambda (a b)
+    (foldr (lambda (a-elt acc) (and acc (memq a-elt b) #t))
+           (and)
+           a)))
+(define set-eq?
+  (lambda (a b)
+    (and (= (cardinality a) (cardinality b))
+         (set<= a b))))
+(define union2
+  (lambda (a b)
+    (if (null? b)
+      a
+      (foldr (lambda (x b) (if (memq x b) b (cons x b)))
+             b
+             a))))
+(define union (lambda l (foldr union2 '() l)))
+(define setdiff2
+  (lambda (a b)
+    (if (null? b)
+      a
+      (foldr (lambda (x c) (if (memq x b) c (cons x c)))
+             '()
+             a))))
+(define setdiff
+  (lambda l
+    (if (null? l)
+      '()
+      (setdiff2 (car l) (foldr union2 '() (cdr l))))))
+(define intersect2
+  (lambda (a b)
+    (if (null? b)
+      a
+      (foldr (lambda (x c) (if (memq x b) (cons x c) c))
+             '()
+             a))))
+(define intersect
+  (lambda l
+    (if (null? l) '() (foldl intersect2 (car l) l))))
+(define-const-structure (some _))
+(define-const-structure (none))
+(define none (make-none))
+(define some make-some)
+(define-const-structure (and exps))
+(define-const-structure (app exp exps))
+(define-const-structure (begin exps))
+(define-const-structure (const val pred))
+(define-const-structure (if exp1 exp2 exp3))
+(define-const-structure (lam names body))
+(define-const-structure (let binds body))
+(define-const-structure (let* binds body))
+(define-const-structure (letr binds body))
+(define-const-structure (or exps))
+(define-const-structure (prim name))
+(define-const-structure (delay exp))
+(define-const-structure (set! (! name) exp))
+(define-const-structure (var (! name)))
+(define-const-structure (vlam names name body))
+(define-const-structure (match exp mclauses))
+(define-const-structure (record binds))
+(define-const-structure (field name exp))
+(define-const-structure (cast type exp))
+(define-const-structure (body defs exps))
+(define-const-structure (bind name exp))
+(define-const-structure (mclause pat body fail))
+(define-const-structure (pvar name))
+(define-const-structure (pany))
+(define-const-structure (pelse))
+(define-const-structure (pconst name pred))
+(define-const-structure (pobj name pats))
+(define-const-structure (ppred name))
+(define-const-structure (pand pats))
+(define-const-structure (pnot pat))
+(define-const-structure (define name (! exp)))
+(define-const-structure
+  (defstruct
+    tag
+    args
+    make
+    pred
+    get
+    set
+    getn
+    setn
+    mutable))
+(define-const-structure (datatype _))
+(define-const-structure
+  (variant con pred arg-types))
+(define-structure
+  (name name
+        ty
+        timestamp
+        occ
+        mutated
+        gdef
+        primitive
+        struct
+        pure
+        predicate
+        variant
+        selector))
+(define-structure (type ty exp))
+(define-const-structure (shape _ _))
+(define-const-structure (check _ _))
+(define parse-def
+  (lambda (def)
+    (let ((parse-name
+            (match-lambda
+              ((? symbol? s)
+               (if (keyword? s)
+                 (syntax-err def "invalid use of keyword ~a" s)
+                 s))
+              (n (syntax-err def "invalid variable at ~a" n)))))
+      (match def
+             (('extend-syntax ((? symbol? name) . _) . _)
+              (printf
+                "Note: installing but _not_ checking (extend-syntax (~a) ...)~%"
+                name)
+              (eval def)
+              '())
+             (('extend-syntax . _)
+              (syntax-err def "invalid syntax"))
+             (('defmacro (? symbol? name) . _)
+              (printf
+                "Note: installing but _not_ checking (defmacro ~a ...)~%"
+                name)
+              (eval def)
+              '())
+             (('defmacro . _)
+              (syntax-err def "invalid syntax"))
+             (('define (? symbol? n) e)
+              (list (make-define (parse-name n) (parse-exp e))))
+             (('define (n . args) . body)
+              (list (make-define
+                      (parse-name n)
+                      (parse-exp `(lambda ,args ,@body)))))
+             (('define . _) (syntax-err def "at define"))
+             (('begin . defs)
+              (foldr append '() (smap parse-def defs)))
+             (('define-structure (n . args))
+              (parse-def `(define-structure (,n ,@args) ())))
+             (('define-structure (n . args) inits)
+              (let ((m-args (smap (lambda (x) `(! ,x)) args))
+                    (m-inits
+                      (smap (match-lambda
+                              ((x e) `((! ,x) ,e))
+                              (_ (syntax-err
+                                   def
+                                   "invalid structure initializer")))
+                            inits)))
+                (parse-def
+                  `(define-const-structure (,n ,@m-args) ,m-inits))))
+             (('define-const-structure ((? symbol? n) . args))
+              (parse-def
+                `(define-const-structure (,n ,@args) ())))
+             (('define-const-structure
+               ((? symbol? n) . args)
+               ())
+              (letrec ((smap-with-n
+                         (lambda (f l)
+                           (recur loop
+                                  ((l l) (n 0))
+                                  (match l
+                                         (() '())
+                                         ((x . y)
+                                          (let ((v (f x n)))
+                                            (cons v (loop y (+ 1 n)))))
+                                         (_ (syntax-err l "invalid list"))))))
+                       (parse-arg
+                         (lambda (a index)
+                           (match a
+                                  (('! '_)
+                                   (list none
+                                         none
+                                         (some (symbol-append
+                                                 n
+                                                 '-
+                                                 (+ index 1)))
+                                         (some (symbol-append
+                                                 'set-
+                                                 n
+                                                 '-
+                                                 (+ index 1)
+                                                 '!))
+                                         #t))
+                                  (('! a)
+                                   (let ((a (parse-name a)))
+                                     (list (some (symbol-append n '- a))
+                                           (some (symbol-append
+                                                   'set-
+                                                   n
+                                                   '-
+                                                   a
+                                                   '!))
+                                           (some (symbol-append
+                                                   n
+                                                   '-
+                                                   (+ index 1)))
+                                           (some (symbol-append
+                                                   'set-
+                                                   n
+                                                   '-
+                                                   (+ index 1)
+                                                   '!))
+                                           #t)))
+                                  ('_
+                                   (list none
+                                         none
+                                         (some (symbol-append
+                                                 n
+                                                 '-
+                                                 (+ index 1)))
+                                         none
+                                         #f))
+                                  (a (let ((a (parse-name a)))
+                                       (list (some (symbol-append n '- a))
+                                             none
+                                             (some (symbol-append
+                                                     n
+                                                     '-
+                                                     (+ index 1)))
+                                             none
+                                             #f)))))))
+                (let* ((arg-info (smap-with-n parse-arg args))
+                       (get (map car arg-info))
+                       (set (map cadr arg-info))
+                       (getn (map caddr arg-info))
+                       (setn (map cadddr arg-info))
+                       (mutable
+                         (map (lambda (x) (car (cddddr x))) arg-info)))
+                  (list (make-defstruct
+                          n
+                          (cons n args)
+                          (symbol-append 'make- n)
+                          (symbol-append n '?)
+                          get
+                          set
+                          getn
+                          setn
+                          mutable)))))
+             (('define-const-structure
+               ((? symbol? n) . args)
+               inits)
+              (syntax-err
+                def
+                "sorry, structure initializers are not supported"))
+             (('datatype . d)
+              (let* ((parse-variant
+                       (match-lambda
+                         (((? symbol? con) ? list? args)
+                          (let ((n (parse-name con)))
+                            (make-variant
+                              (symbol-append 'make- n)
+                              (symbol-append n '?)
+                              (cons con args))))
+                         (_ (syntax-err def "invalid datatype syntax"))))
+                     (parse-dt
+                       (match-lambda
+                         (((? symbol? type) . variants)
+                          (cons (list (parse-name type))
+                                (smap parse-variant variants)))
+                         ((((? symbol? type) ? list? targs) . variants)
+                          (cons (cons (parse-name type)
+                                      (smap parse-name targs))
+                                (smap parse-variant variants)))
+                         (_ (syntax-err def "invalid datatype syntax")))))
+                (list (make-datatype (smap parse-dt d)))))
+             (((? symbol? k) . _)
+              (cond ((and (not (keyword? k))
+                          (expand-once-if-macro def))
+                     =>
+                     parse-def)
+                    (else (list (make-define #f (parse-exp def))))))
+             (_ (list (make-define #f (parse-exp def))))))))
+(define keep-match #t)
+(define parse-exp
+  (lambda (expression)
+    (letrec ((n-primitive (string->symbol "#primitive"))
+             (parse-exp
+               (match-lambda
+                 (('quote (? symbol? s)) (make-const s 'symbol?))
+                 ((and m ('quote _)) (parse-exp (quote-tf m)))
+                 ((and m ('quasiquote _))
+                  (parse-exp (quasiquote-tf m)))
+                 ((and m (? box?)) (parse-exp (quote-tf m)))
+                 ((and m (? vector?)) (parse-exp (quote-tf m)))
+                 ((and m ('cond . _)) (parse-exp (cond-tf m)))
+                 ((and m ('case . _)) (parse-exp (case-tf m)))
+                 ((and m ('do . _)) (parse-exp (do-tf m)))
+                 ((? symbol? s) (make-var (parse-name s)))
+                 (#t (make-const #t 'true-object?))
+                 (#f (make-const #f 'false-object?))
+                 ((? null? c) (make-const c 'null?))
+                 ((? number? c) (make-const c 'number?))
+                 ((? char? c) (make-const c 'char?))
+                 ((? string? c) (make-const c 'string?))
+                 ((': ty e1) (make-cast ty (parse-exp e1)))
+                 ((and exp ('record . bind))
+                  (let ((bindings (smap parse-bind bind)))
+                    (no-repeats (map bind-name bindings) exp)
+                    (make-record bindings)))
+                 ((and exp ('field name e1))
+                  (make-field (parse-name name) (parse-exp e1)))
+                 ((and exp ('match e clause0 . clauses))
+                  (=> fail)
+                  (if keep-match
+                    (let* ((e2 (parse-exp e))
+                           (parse-clause
+                             (match-lambda
+                               ((p ('=> (? symbol? failsym)) . body)
+                                (make-mclause
+                                  (parse-pat p expression)
+                                  (parse-body
+                                    `((let ((,failsym (lambda () (,failsym))))
+                                        ,@body)))
+                                  failsym))
+                               ((p . body)
+                                (make-mclause
+                                  (parse-pat p expression)
+                                  (parse-body body)
+                                  #f))
+                               (_ (syntax-err exp "invalid match clause")))))
+                      (make-match
+                        e2
+                        (smap parse-clause (cons clause0 clauses))))
+                    (fail)))
+                 ((and exp ('lambda bind . body))
+                  (recur loop
+                         ((b bind) (names '()))
+                         (match b
+                                ((? symbol? n)
+                                 (let ((rest (parse-name n)))
+                                   (no-repeats (cons rest names) exp)
+                                   (make-vlam
+                                     (reverse names)
+                                     rest
+                                     (parse-body body))))
+                                (()
+                                 (no-repeats names exp)
+                                 (make-lam (reverse names) (parse-body body)))
+                                ((n . x) (loop x (cons (parse-name n) names)))
+                                (_ (syntax-err
+                                     exp
+                                     "invalid lambda expression")))))
+                 (('if e1 e2 e3)
+                  (make-if
+                    (parse-exp e1)
+                    (parse-exp e2)
+                    (parse-exp e3)))
+                 ((and if-expr ('if e1 e2))
+                  (printf "Note: one-armed if: ")
+                  (print-context if-expr 2)
+                  (make-if
+                    (parse-exp e1)
+                    (parse-exp e2)
+                    (parse-exp '(void))))
+                 (('delay e) (make-delay (parse-exp e)))
+                 (('set! n e)
+                  (make-set! (parse-name n) (parse-exp e)))
+                 (('and . args) (make-and (smap parse-exp args)))
+                 (('or . args) (make-or (smap parse-exp args)))
+                 ((and exp ('let (? symbol? n) bind . body))
+                  (let* ((nb (parse-name n))
+                         (bindings (smap parse-bind bind)))
+                    (no-repeats (map bind-name bindings) exp)
+                    (make-app
+                      (make-letr
+                        (list (make-bind
+                                nb
+                                (make-lam
+                                  (map bind-name bindings)
+                                  (parse-body body))))
+                        (make-body '() (list (make-var nb))))
+                      (map bind-exp bindings))))
+                 ((and exp ('let bind . body))
+                  (let ((bindings (smap parse-bind bind)))
+                    (no-repeats (map bind-name bindings) exp)
+                    (make-let bindings (parse-body body))))
+                 (('let* bind . body)
+                  (make-let*
+                    (smap parse-bind bind)
+                    (parse-body body)))
+                 ((and exp ('letrec bind . body))
+                  (let ((bindings (smap parse-bind bind)))
+                    (no-repeats (map bind-name bindings) exp)
+                    (make-letr bindings (parse-body body))))
+                 (('begin e1 . rest)
+                  (make-begin (smap parse-exp (cons e1 rest))))
+                 (('define . _)
+                  (syntax-err
+                    expression
+                    "invalid context for internal define"))
+                 (('define-structure . _)
+                  (syntax-err
+                    expression
+                    "invalid context for internal define-structure"))
+                 (('define-const-structure . _)
+                  (syntax-err
+                    expression
+                    "invalid context for internal define-const-structure"))
+                 ((and m (f . args))
+                  (cond ((and (eq? f n-primitive)
+                              (match args
+                                     (((? symbol? p)) (make-prim p))
+                                     (_ #f))))
+                        ((and (symbol? f)
+                              (not (keyword? f))
+                              (expand-once-if-macro m))
+                         =>
+                         parse-exp)
+                        (else
+                         (make-app (parse-exp f) (smap parse-exp args)))))
+                 (x (syntax-err
+                      expression
+                      "invalid expression at ~a"
+                      x))))
+             (parse-name
+               (match-lambda
+                 ((? symbol? s)
+                  (when (keyword? s)
+                        (syntax-err
+                          expression
+                          "invalid use of keyword ~a"
+                          s))
+                  s)
+                 (n (syntax-err
+                      expression
+                      "invalid variable at ~a"
+                      n))))
+             (parse-bind
+               (match-lambda
+                 ((x e) (make-bind (parse-name x) (parse-exp e)))
+                 (b (syntax-err expression "invalid binding at ~a" b))))
+             (parse-body
+               (lambda (body)
+                 (recur loop
+                        ((b body) (defs '()))
+                        (match b
+                               (((and d ('define . _)) . rest)
+                                (loop rest (append defs (parse-def d))))
+                               (((and d ('define-structure . _)) . rest)
+                                (loop rest (append defs (parse-def d))))
+                               (((and d ('define-const-structure . _)) . rest)
+                                (loop rest (append defs (parse-def d))))
+                               ((('begin) . rest) (loop rest defs))
+                               (((and beg ('begin ('define . _) . _)) . rest)
+                                (loop rest (append defs (parse-def beg))))
+                               (((and beg ('begin ('define-structure . _) . _))
+                                 .
+                                 rest)
+                                (loop rest (append defs (parse-def beg))))
+                               (((and beg
+                                      ('begin
+                                       ('define-const-structure . _)
+                                       .
+                                       _))
+                                 .
+                                 rest)
+                                (loop rest (append defs (parse-def beg))))
+                               ((_ . _) (make-body defs (smap parse-exp b)))
+                               (_ (syntax-err
+                                    expression
+                                    "invalid body at ~a"
+                                    b))))))
+             (no-repeats
+               (lambda (l exp)
+                 (match l
+                        (() #f)
+                        ((_) #f)
+                        ((x . l)
+                         (if (memq x l)
+                           (syntax-err exp "name ~a repeated" x)
+                           (no-repeats l exp)))))))
+      (parse-exp expression))))
+(define parse-pat
+  (lambda (pat expression)
+    (letrec ((parse-pat
+               (match-lambda
+                 (#f (make-ppred 'false-object?))
+                 (#t (make-ppred 'true-object?))
+                 (() (make-ppred 'null?))
+                 ((? number? c) (make-pconst c 'number?))
+                 ((? char? c) (make-pconst c 'char?))
+                 ((? string? c) (make-pconst c 'string?))
+                 (('quote x) (parse-quote x))
+                 ('_ (make-pany))
+                 ('else (make-pelse))
+                 ((? symbol? n) (make-pvar (parse-pname n)))
+                 (('not . pats)
+                  (syntax-err
+                    expression
+                    "not patterns are not supported"))
+                 (('or . pats)
+                  (syntax-err
+                    expression
+                    "or patterns are not supported"))
+                 (('get! . pats)
+                  (syntax-err
+                    expression
+                    "get! patterns are not supported"))
+                 (('set! . pats)
+                  (syntax-err
+                    expression
+                    "set! patterns are not supported"))
+                 (('and . pats)
+                  (let* ((pats (smap parse-pat pats))
+                         (p (make-flat-pand pats))
+                         (non-var?
+                           (match-lambda
+                             ((? pvar?) #f)
+                             ((? pany?) #f)
+                             (_ #t))))
+                    (match p
+                           (($ pand pats)
+                            (when (< 1 (length (filter non-var? pats)))
+                                  (syntax-err
+                                    expression
+                                    "~a has conflicting subpatterns"
+                                    (ppat p))))
+                           (_ #f))
+                    p))
+                 (('? (? symbol? pred) p)
+                  (parse-pat `(and (? ,pred) ,p)))
+                 (('? (? symbol? pred))
+                  (if (keyword? pred)
+                    (syntax-err
+                      expression
+                      "invalid use of keyword ~a"
+                      pred)
+                    (make-ppred pred)))
+                 (('$ (? symbol? c) . args)
+                  (if (memq c '(? _ $))
+                    (syntax-err
+                      expression
+                      "invalid use of pattern keyword ~a"
+                      c)
+                    (make-pobj
+                      (symbol-append c '?)
+                      (smap parse-pat args))))
+                 ((? box? cb)
+                  (make-pobj 'box? (list (parse-pat (unbox cb)))))
+                 ((x . y)
+                  (make-pobj
+                    'pair?
+                    (list (parse-pat x) (parse-pat y))))
+                 ((? vector? v)
+                  (make-pobj
+                    'vector?
+                    (map parse-pat (vector->list v))))
+                 (m (syntax-err expression "invalid pattern at ~a" m))))
+             (parse-quote
+               (match-lambda
+                 (#f (make-pobj 'false-object? '()))
+                 (#t (make-pobj 'true-object? '()))
+                 (() (make-pobj 'null? '()))
+                 ((? number? c) (make-pconst c 'number?))
+                 ((? char? c) (make-pconst c 'char?))
+                 ((? string? c) (make-pconst c 'string?))
+                 ((? symbol? s) (make-pconst s 'symbol?))
+                 ((? box? cb)
+                  (make-pobj 'box? (list (parse-quote (unbox cb)))))
+                 ((x . y)
+                  (make-pobj
+                    'pair?
+                    (list (parse-quote x) (parse-quote y))))
+                 ((? vector? v)
+                  (make-pobj
+                    'vector?
+                    (map parse-quote (vector->list v))))
+                 (m (syntax-err expression "invalid pattern at ~a" m))))
+             (parse-pname
+               (match-lambda
+                 ((? symbol? s)
+                  (cond ((keyword? s)
+                         (syntax-err
+                           expression
+                           "invalid use of keyword ~a"
+                           s))
+                        ((memq s '(? _ else $ and or not set! get! ...))
+                         (syntax-err
+                           expression
+                           "invalid use of pattern keyword ~a"
+                           s))
+                        (else s)))
+                 (n (syntax-err
+                      expression
+                      "invalid pattern variable at ~a"
+                      n)))))
+      (parse-pat pat))))
+(define smap
+  (lambda (f l)
+    (match l
+           (() '())
+           ((x . r) (let ((v (f x))) (cons v (smap f r))))
+           (_ (syntax-err l "invalid list")))))
+(define primitive
+  (lambda (p)
+    (list (string->symbol "#primitive") p)))
+(define keyword?
+  (lambda (s)
+    (or (memq s
+              '(=> and
+                   begin
+                   case
+                   cond
+                   do
+                   define
+                   delay
+                   if
+                   lambda
+                   let
+                   let*
+                   letrec
+                   or
+                   quasiquote
+                   quote
+                   set!
+                   unquote
+                   unquote-splicing
+                   define-structure
+                   define-const-structure
+                   record
+                   field
+                   :
+                   datatype))
+        (and keep-match (eq? s 'match)))))
+(define make-flat-pand
+  (lambda (pats)
+    (let* ((l (foldr (lambda (p plist)
+                       (match p
+                              (($ pand pats) (append pats plist))
+                              (_ (cons p plist))))
+                     '()
+                     pats))
+           (concrete?
+             (match-lambda
+               ((? pconst?) #t)
+               ((? pobj?) #t)
+               ((? ppred?) #t)
+               (_ #f)))
+           (sorted
+             (append
+               (filter concrete? l)
+               (filter (lambda (x) (not (concrete? x))) l))))
+      (match sorted ((p) p) (_ (make-pand sorted))))))
+(define never-counter 0)
+(define reinit-macros!
+  (lambda () (set! never-counter 0)))
+(define cond-tf
+  (lambda (cond-expr)
+    (recur loop
+           ((e (cdr cond-expr)))
+           (match e
+                  (()
+                   (begin
+                     (set! never-counter (+ 1 never-counter))
+                     `(,(primitive 'should-never-reach)
+                       '(cond ,never-counter))))
+                  ((('else b1 . body)) `(begin ,b1 ,@body))
+                  ((('else . _) . _)
+                   (syntax-err cond-expr "invalid cond expression"))
+                  (((test '=> proc) . rest)
+                   (let ((g (gensym)))
+                     `(let ((,g ,test))
+                        (if ,g (,proc ,g) ,(loop rest)))))
+                  (((#t b1 . body)) `(begin ,b1 ,@body))
+                  (((test) . rest) `(or ,test ,(loop rest)))
+                  (((test . body) . rest)
+                   `(if ,test (begin ,@body) ,(loop rest)))
+                  (_ (syntax-err cond-expr "invalid cond expression"))))))
+(define scheme-cond-tf
+  (lambda (cond-expr)
+    (recur loop
+           ((e (cdr cond-expr)))
+           (match e
+                  (() `(,(primitive 'void)))
+                  ((('else b1 . body)) `(begin ,b1 ,@body))
+                  ((('else . _) . _)
+                   (syntax-err cond-expr "invalid cond expression"))
+                  (((test '=> proc) . rest)
+                   (let ((g (gensym)))
+                     `(let ((,g ,test))
+                        (if ,g (,proc ,g) ,(loop rest)))))
+                  (((#t b1 . body)) `(begin ,b1 ,@body))
+                  (((test) . rest) `(or ,test ,(loop rest)))
+                  (((test . body) . rest)
+                   `(if ,test (begin ,@body) ,(loop rest)))
+                  (_ (syntax-err cond-expr "invalid cond expression"))))))
+(define case-tf
+  (lambda (case-expr)
+    (recur loop
+           ((e (cdr case-expr)))
+           (match e
+                  ((exp) `(begin ,exp (,(primitive 'void))))
+                  ((exp ('else b1 . body)) `(begin ,b1 ,@body))
+                  ((exp ('else . _) . _)
+                   (syntax-err case-expr "invalid case expression"))
+                  (((? symbol? exp)
+                    ((? list? test) b1 . body)
+                    .
+                    rest)
+                   `(if (,(primitive 'memv) ,exp ',test)
+                      (begin ,b1 ,@body)
+                      ,(loop (cons exp rest))))
+                  (((? symbol? exp) (test b1 . body) . rest)
+                   `(if (,(primitive 'memv) ,exp '(,test))
+                      (begin ,b1 ,@body)
+                      ,(loop (cons exp rest))))
+                  ((exp . rest)
+                   (if (not (symbol? exp))
+                     (let ((g (gensym)))
+                       `(let ((,g ,exp)) ,(loop (cons g rest))))
+                     (syntax-err case-expr "invalid case expression")))
+                  (_ (syntax-err case-expr "invalid case expression"))))))
+(define conslimit 8)
+(define quote-tf
+  (lambda (exp)
+    (letrec ((qloop (match-lambda
+                      ((? box? q)
+                       `(,(primitive qbox) ,(qloop (unbox q))))
+                      ((? symbol? q) `',q)
+                      ((? null? q) q)
+                      ((? list? q)
+                       (if (< (length q) conslimit)
+                         `(,(primitive qcons)
+                           ,(qloop (car q))
+                           ,(qloop (cdr q)))
+                         `(,(primitive qlist) ,@(map qloop q))))
+                      ((x . y)
+                       `(,(primitive qcons) ,(qloop x) ,(qloop y)))
+                      ((? vector? q)
+                       `(,(primitive qvector)
+                         ,@(map qloop (vector->list q))))
+                      ((? boolean? q) q)
+                      ((? number? q) q)
+                      ((? char? q) q)
+                      ((? string? q) q)
+                      (q (syntax-err
+                           exp
+                           "invalid quote expression at ~a"
+                           q)))))
+      (match exp
+             (('quote q) (qloop q))
+             ((? vector? q) (qloop q))
+             ((? box? q) (qloop q))))))
+(define quasiquote-tf
+  (lambda (exp)
+    (letrec ((make-cons
+               (lambda (x y)
+                 (cond ((null? y) `(,(primitive 'list) ,x))
+                       ((and (pair? y)
+                             (equal? (car y) (primitive 'list)))
+                        (cons (car y) (cons x (cdr y))))
+                       (else `(,(primitive 'cons) ,x ,y)))))
+             (qloop (lambda (e n)
+                      (match e
+                             (('quasiquote e)
+                              (make-cons 'quasiquote (qloop `(,e) (+ 1 n))))
+                             (('unquote e)
+                              (if (zero? n)
+                                e
+                                (make-cons 'unquote (qloop `(,e) (- n 1)))))
+                             (('unquote-splicing e)
+                              (if (zero? n)
+                                e
+                                (make-cons
+                                  'unquote-splicing
+                                  (qloop `(,e) (- n 1)))))
+                             ((('unquote-splicing e) . y)
+                              (=> fail)
+                              (if (zero? n)
+                                (if (null? y)
+                                  e
+                                  `(,(primitive 'append) ,e ,(qloop y n)))
+                                (fail)))
+                             ((? box? q)
+                              `(,(primitive 'box) ,(qloop (unbox q) n)))
+                             ((? symbol? q)
+                              (if (memq q
+                                        '(quasiquote unquote unquote-splicing))
+                                (syntax-err
+                                  exp
+                                  "invalid use of ~a inside quasiquote"
+                                  q)
+                                `',q))
+                             ((? null? q) q)
+                             ((x . y) (make-cons (qloop x n) (qloop y n)))
+                             ((? vector? q)
+                              `(,(primitive 'vector)
+                                ,@(map (lambda (z) (qloop z n))
+                                       (vector->list q))))
+                             ((? boolean? q) q)
+                             ((? number? q) q)
+                             ((? char? q) q)
+                             ((? string? q) q)
+                             (q (syntax-err
+                                  exp
+                                  "invalid quasiquote expression at ~a"
+                                  q))))))
+      (match exp (('quasiquote q) (qloop q 0))))))
+(define do-tf
+  (lambda (do-expr)
+    (recur loop
+           ((e (cdr do-expr)))
+           (match e
+                  (((? list? vis) (e0 ? list? e1) ? list? c)
+                   (if (andmap (match-lambda ((_ _ . _) #t) (_ #f)) vis)
+                     (let* ((var (map car vis))
+                            (init (map cadr vis))
+                            (step (map cddr vis))
+                            (step (map (lambda (v s)
+                                         (match s
+                                                (() v)
+                                                ((e) e)
+                                                (_ (syntax-err
+                                                     do-expr
+                                                     "invalid do expression"))))
+                                       var
+                                       step)))
+                       (let ((doloop (gensym)))
+                         (match e1
+                                (()
+                                 `(let ,doloop
+                                    ,(map list var init)
+                                    (if (not ,e0)
+                                      (begin ,@c (,doloop ,@step) (void))
+                                      (void))))
+                                ((body0 ? list? body)
+                                 `(let ,doloop
+                                    ,(map list var init)
+                                    (if ,e0
+                                      (begin ,body0 ,@body)
+                                      (begin ,@c (,doloop ,@step)))))
+                                (_ (syntax-err
+                                     do-expr
+                                     "invalid do expression")))))
+                     (syntax-err do-expr "invalid do expression")))
+                  (_ (syntax-err do-expr "invalid do expression"))))))
+(define empty-env '())
+(define lookup
+  (lambda (env x)
+    (match (assq x env)
+           (#f (disaster 'lookup "no binding for ~a" x))
+           ((_ . b) b))))
+(define lookup?
+  (lambda (env x)
+    (match (assq x env) (#f #f) ((_ . b) b))))
+(define bound?
+  (lambda (env x)
+    (match (assq x env) (#f #f) (_ #t))))
+(define extend-env
+  (lambda (env x v) (cons (cons x v) env)))
+(define extend-env*
+  (lambda (env xs vs)
+    (append (map2 cons xs vs) env)))
+(define join-env
+  (lambda (env newenv) (append newenv env)))
+(define populated #t)
+(define pseudo #f)
+(define global-error #f)
+(define share #f)
+(define matchst #f)
+(define fullsharing #t)
+(define dump-depths #f)
+(define flags #t)
+(define-structure
+  (c depth kind fsym pres args next))
+(define-structure
+  (v depth kind name vis split inst))
+(define-structure (ts type n-gen))
+(define-structure (k name order args))
+(define top (box 'top))
+(define bot (box 'bot))
+(define generic? (lambda (d) (< d 0)))
+(define new-type
+  (lambda (s d)
+    (let ((t (box s)))
+      (vector-set!
+        types
+        d
+        (cons t (vector-ref types d)))
+      t)))
+(define generate-counter
+  (lambda ()
+    (let ((n 0)) (lambda () (set! n (+ 1 n)) n))))
+(define var-counter (generate-counter))
+(define make-raw-tvar
+  (lambda (d k) (make-v d k var-counter #t #f #f)))
+(define make-tvar
+  (lambda (d k) (new-type (make-raw-tvar d k) d)))
+(define ord? (lambda (k) (eq? 'ord k)))
+(define abs? (lambda (k) (eq? 'abs k)))
+(define pre? (lambda (k) (eq? 'pre k)))
+(define ord-depth 2)
+(define depth ord-depth)
+(define types (make-vector 16 '()))
+(define reset-types!
+  (lambda ()
+    (set! depth ord-depth)
+    (set! types (make-vector 16 '()))))
+(define push-level
+  (lambda ()
+    (set! depth (+ depth 1))
+    (when (< (vector-length types) (+ 1 depth))
+          (set! types
+            (let ((l (vector->list types)))
+              (list->vector
+                (append l (map (lambda (_) '()) l))))))))
+(define pop-level
+  (lambda ()
+    (vector-set! types depth '())
+    (set! depth (- depth 1))))
+(define v-ord (lambda () (make-tvar depth 'ord)))
+(define v-abs (lambda () (make-tvar depth 'abs)))
+(define v-pre (lambda () (make-tvar depth 'pre)))
+(define tvar v-ord)
+(define out1tvar
+  (lambda () (make-tvar (- depth 1) 'ord)))
+(define monotvar
+  (lambda () (make-tvar ord-depth 'ord)))
+(define pvar
+  (match-lambda
+    (($ box (and x ($ v d k _ vis _ _)))
+     (unless
+       (number? (v-name x))
+       (set-v-name! x ((v-name x))))
+     (string->symbol
+       (sprintf
+         "~a~a~a"
+         (match k
+                ('ord
+                 (if (generic? d)
+                   (if vis "X" "x")
+                   (if vis "Z" "z")))
+                ('abs (if vis "A" "a"))
+                ('pre (if vis "P" "p")))
+         (v-name x)
+         (if dump-depths (sprintf ".~a" d) ""))))))
+(define make-tvar-like
+  (match-lambda
+    (($ box ($ v d k _ _ _ _)) (make-tvar d k))))
+(define ind*
+  (lambda (t)
+    (match (unbox t)
+           ((? box? u)
+            (let ((v (ind* u))) (set-box! t v) v))
+           (_ t))))
+(define type-check?
+  (match-lambda
+    ((abs def inexhaust once _)
+     (cond (((if once check-abs1? check-abs?) abs)
+            (if (and def (definite? def)) 'def #t))
+           (inexhaust 'inexhaust)
+           (else #f)))))
+(define type-check1?
+  (match-lambda
+    ((abs def inexhaust _ _)
+     (cond ((check-abs1? abs)
+            (if (and def (definite? def)) 'def #t))
+           (inexhaust 'inexhaust)
+           (else #f)))))
+(define check-abs?
+  (lambda (vlist)
+    (letrec ((seen '())
+             (labs? (lambda (t)
+                      (match t
+                             (($ box ($ v _ _ _ _ _ inst))
+                              (and inst
+                                   (not (memq t seen))
+                                   (begin
+                                     (set! seen (cons t seen))
+                                     (ormap (match-lambda ((t . _) (labs? t)))
+                                            inst))))
+                             (($ box ($ c _ _ _ p _ n))
+                              (or (labs? p) (labs? n)))
+                             (($ box (? symbol?)) #t)
+                             (($ box i) (labs? i))))))
+      (ormap labs? vlist))))
+(define check-abs1?
+  (lambda (vlist)
+    (letrec ((labs1?
+               (lambda (t)
+                 (match t
+                        (($ box (? v?)) #f)
+                        (($ box ($ c _ _ _ p _ n))
+                         (or (labs1? p) (labs1? n)))
+                        (($ box (? symbol?)) #t)
+                        (($ box i) (labs1? i))))))
+      (ormap labs1? vlist))))
+(define check-sources
+  (lambda (info)
+    (letrec ((seen '())
+             (lsrcs (lambda (t source)
+                      (match t
+                             (($ box ($ v _ k _ _ _ inst))
+                              (union (if (and inst (not (memq t seen)))
+                                       (begin
+                                         (set! seen (cons t seen))
+                                         (foldr union
+                                                empty-set
+                                                (map (match-lambda
+                                                       ((t . s) (lsrcs t s)))
+                                                     inst)))
+                                       empty-set)))
+                             (($ box ($ c _ _ _ p _ n))
+                              (union (lsrcs p source) (lsrcs n source)))
+                             (($ box (? symbol?))
+                              (if source (set source) empty-set))
+                             (($ box i) (lsrcs i source))))))
+      (match-let
+        (((abs _ _ _ _) info))
+        (if (eq? #t abs)
+          empty-set
+          (foldr union
+                 empty-set
+                 (map (lambda (t) (lsrcs t #f)) abs)))))))
+(define check-local-sources
+  (match-lambda ((_ _ _ _ component) component)))
+(define mk-definite-prim
+  (match-lambda
+    (($ box ($ c _ _ x p a n))
+     (if (eq? (k-name x) '?->)
+       (let ((seen '()))
+         (recur lprim
+                ((t (car a)))
+                (match t
+                       (($ box ($ c _ _ x p a n))
+                        (if (memq t seen)
+                          '()
+                          (begin
+                            (set! seen (cons t seen))
+                            (match (k-name x)
+                                   ('noarg (cons p (lprim n)))
+                                   ('arg
+                                    (let ((args (recur argloop
+                                                       ((a (car a)))
+                                                       (match a
+                                                              (($ box
+                                                                  ($ c
+                                                                     _
+                                                                     _
+                                                                     _
+                                                                     p
+                                                                     _
+                                                                     n))
+                                                               (cons p
+                                                                     (argloop
+                                                                       n)))
+                                                              (($ box
+                                                                  ($ v
+                                                                     _
+                                                                     k
+                                                                     _
+                                                                     _
+                                                                     _
+                                                                     _))
+                                                               (if (ord? k)
+                                                                 (list a)
+                                                                 '()))
+                                                              (($ box
+                                                                  (? symbol?))
+                                                               '())
+                                                              (($ box i)
+                                                               (argloop i))))))
+                                      (cons (list p args (lprim (cadr a)))
+                                            (lprim n))))))))
+                       (($ box ($ v _ k _ _ _ _))
+                        (if (ord? k) (list t) '()))
+                       (($ box (? symbol?)) '())
+                       (($ box i) (lprim i)))))
+       (mk-definite-prim n)))
+    (($ box (? v?)) '())
+    (($ box (? symbol?)) '())
+    (($ box i) (mk-definite-prim i))))
+(define mk-definite-app
+  (match-lambda
+    (($ box ($ c _ _ _ p _ _)) (list p))))
+(define mk-definite-lam
+  (match-lambda
+    (($ box ($ c _ _ x p a n))
+     (if (eq? (k-name x) '?->)
+       (let ((seen '()))
+         (recur llam
+                ((t (car a)))
+                (match t
+                       (($ box ($ c _ _ x p a n))
+                        (if (memq t seen)
+                          '()
+                          (begin
+                            (set! seen (cons t seen))
+                            (match (k-name x)
+                                   ('noarg (cons p (llam n)))
+                                   ('arg
+                                    (let ((args (list top)))
+                                      (cons (list p args (llam (cadr a)))
+                                            (llam n))))))))
+                       (($ box ($ v _ k _ _ _ _))
+                        (if (ord? k) (list t) '()))
+                       (($ box (? symbol?)) '())
+                       (($ box i) (llam i)))))
+       (mk-definite-lam n)))
+    (($ box (? v?)) '())
+    (($ box (? symbol?)) '())
+    (($ box i) (mk-definite-lam i))))
+(define definite?
+  (lambda (def-info)
+    (letrec ((non-empty?
+               (lambda (t)
+                 (let ((seen '()))
+                   (recur ldef
+                          ((t t))
+                          (match t
+                                 (($ box ($ c _ _ _ p _ n))
+                                  (or (ldef p) (ldef n)))
+                                 (($ box ($ v d k _ _ _ inst))
+                                  (if (or global-error (abs? k))
+                                    (and inst
+                                         (generic? d)
+                                         (not (memq t seen))
+                                         (begin
+                                           (set! seen (cons t seen))
+                                           (ormap (match-lambda
+                                                    ((t . _) (ldef t)))
+                                                  inst)))
+                                    (generic? d)))
+                                 (($ box 'top) #t)
+                                 (($ box 'bot) #f)
+                                 (($ box i) (ldef i)))))))
+             (ok (lambda (l)
+                   (ormap (match-lambda
+                            ((? box? t) (non-empty? t))
+                            ((p arg rest)
+                             (and (non-empty? p)
+                                  (ormap non-empty? arg)
+                                  (ok rest))))
+                          l))))
+      (not (ok def-info)))))
+(define close
+  (lambda (t-list) (close-type t-list #f)))
+(define closeall
+  (lambda (t) (car (close-type (list t) #t))))
+(define for
+  (lambda (from to f)
+    (cond ((= from to) (f from))
+          ((< from to)
+           (begin (f from) (for (+ from 1) to f)))
+          (else #f))))
+(define close-type
+  (lambda (t-list all?)
+    (let* ((sorted (make-vector (+ depth 1) '()))
+           (sort (lambda (t)
+                   (match t
+                          (($ box ($ c d _ _ _ _ _))
+                           (vector-set!
+                             sorted
+                             d
+                             (cons t (vector-ref sorted d))))
+                          (($ box ($ v d _ _ _ _ _))
+                           (vector-set!
+                             sorted
+                             d
+                             (cons t (vector-ref sorted d))))
+                          (_ #f))))
+           (prop-d
+             (lambda (down)
+               (letrec ((pr (match-lambda
+                              (($ box (and x ($ v d _ _ _ _ _)))
+                               (when (< down d) (set-v-depth! x down)))
+                              (($ box (and x ($ c d _ _ p a n)))
+                               (when (< down d)
+                                     (set-c-depth! x down)
+                                     (pr p)
+                                     (for-each pr a)
+                                     (pr n)))
+                              (($ box (? symbol?)) #f)
+                              (z (pr (ind* z))))))
+                 (match-lambda
+                   (($ box (and x ($ c d _ _ p a n)))
+                    (when (<= down d) (pr p) (for-each pr a) (pr n)))
+                   (_ #f)))))
+           (prop-k
+             (lambda (t)
+               (let ((pk (lambda (kind)
+                           (rec pr
+                                (match-lambda
+                                  (($ box (and x ($ v _ k _ _ _ _)))
+                                   (when (kind< kind k) (set-v-kind! x kind)))
+                                  (($ box (and x ($ c _ k _ p a n)))
+                                   (when (kind< kind k)
+                                         (set-c-kind! x kind)
+                                         (pr p)
+                                         (unless populated (for-each pr a))
+                                         (pr n)))
+                                  (($ box (? symbol?)) #f)
+                                  (z (pr (ind* z))))))))
+                 (match t
+                        (($ box (and x ($ c _ k _ p a n)))
+                         (when (not (ord? k))
+                               (let ((prop (pk k)))
+                                 (prop p)
+                                 (unless populated (for-each prop a))
+                                 (prop n))))
+                        (_ #f)))))
+           (might-be-generalized?
+             (match-lambda
+               (($ box ($ v d k _ _ _ _))
+                (and (<= depth d) (or populated (ord? k) all?)))
+               (($ box ($ c d k _ _ _ _))
+                (and (<= depth d) (or populated (ord? k) all?)))
+               (($ box (? symbol?)) #f)))
+           (leaves '())
+           (depth-of
+             (match-lambda
+               (($ box ($ v d _ _ _ _ _)) d)
+               (($ box ($ c d _ _ _ _ _)) d)))
+           (vector-grow
+             (lambda (v)
+               (let* ((n (vector-length v))
+                      (v2 (make-vector (* n 2) '())))
+                 (recur loop
+                        ((i 0))
+                        (when (< i n)
+                              (vector-set! v2 i (vector-ref v i))
+                              (loop (+ 1 i))))
+                 v2)))
+           (parents (make-vector 64 '()))
+           (parent-index 0)
+           (parents-of
+             (lambda (t)
+               (let ((d (depth-of t)))
+                 (if (< depth d)
+                   (vector-ref parents (- (- d depth) 1))
+                   '()))))
+           (xtnd-parents!
+             (lambda (t parent)
+               (match t
+                      (($ box (and x ($ v d _ _ _ _ _)))
+                       (when (= d depth)
+                             (set! parent-index (+ 1 parent-index))
+                             (set-v-depth! x (+ depth parent-index))
+                             (when (< (vector-length parents) parent-index)
+                                   (set! parents (vector-grow parents)))
+                             (set! d (+ depth parent-index)))
+                       (vector-set!
+                         parents
+                         (- (- d depth) 1)
+                         (cons parent
+                               (vector-ref parents (- (- d depth) 1)))))
+                      (($ box (and x ($ c d _ _ _ _ _)))
+                       (when (= d depth)
+                             (set! parent-index (+ 1 parent-index))
+                             (set-c-depth! x (+ depth parent-index))
+                             (when (< (vector-length parents) parent-index)
+                                   (set! parents (vector-grow parents)))
+                             (set! d (+ depth parent-index)))
+                       (vector-set!
+                         parents
+                         (- (- d depth) 1)
+                         (cons parent
+                               (vector-ref parents (- (- d depth) 1))))))))
+           (needs-cleanup '())
+           (revtype
+             (rec revtype
+                  (lambda (parent t)
+                    (let ((t (ind* t)))
+                      (cond ((not (might-be-generalized? t)) #f)
+                            ((null? (parents-of t))
+                             (xtnd-parents! t parent)
+                             (set! needs-cleanup (cons t needs-cleanup))
+                             (match t
+                                    (($ box (? v?))
+                                     (set! leaves (cons t leaves)))
+                                    (($ box ($ c _ _ _ p a n))
+                                     (let ((rev (lambda (q) (revtype t q))))
+                                       (rev p)
+                                       (for-each rev a)
+                                       (rev n)))))
+                            ((not (memq parent (parents-of t)))
+                             (xtnd-parents! t parent))
+                            (else #f))))))
+           (generic-index 0)
+           (gen (rec gen
+                     (lambda (t)
+                       (let ((t (ind* t)))
+                         (when (might-be-generalized? t)
+                               (set! generic-index (- generic-index 1))
+                               (let ((parents (parents-of t)))
+                                 (match t
+                                        (($ box (and x ($ v _ k _ _ _ _)))
+                                         (set-v-depth! x generic-index)
+                                         (when (and populated
+                                                    (or global-error
+                                                        (abs? k)
+                                                        (pre? k))
+                                                    (not all?))
+                                               (set-v-inst! x '())))
+                                        (($ box (? c? x))
+                                         (set-c-depth! x generic-index)))
+                                 (for-each gen parents)))))))
+           (cleanup
+             (match-lambda
+               (($ box (and x ($ v d _ _ _ _ _)))
+                (unless (< d 0) (set-v-depth! x (- depth 1))))
+               (($ box (and x ($ c d _ _ _ _ _)))
+                (unless (< d 0) (set-c-depth! x (- depth 1))))))
+           (gen2 (rec gen
+                      (lambda (t)
+                        (let ((t (ind* t)))
+                          (when (might-be-generalized? t)
+                                (set! generic-index (- generic-index 1))
+                                (match t
+                                       (($ box (and x ($ v _ k _ _ _ _)))
+                                        (set-v-depth! x generic-index)
+                                        (when (and populated
+                                                   (or global-error
+                                                       (abs? k)
+                                                       (pre? k))
+                                                   (not all?))
+                                              (set-v-inst! x '())))
+                                       (($ box (and x ($ c _ _ _ p a n)))
+                                        (set-c-depth! x generic-index)
+                                        (gen p)
+                                        (for-each gen a)
+                                        (gen n))))))))
+           (upd (lambda (t)
+                  (let ((d (depth-of t)))
+                    (when (< 0 d)
+                          (vector-set!
+                            types
+                            d
+                            (cons t (vector-ref types d))))))))
+      (for-each sort (vector-ref types depth))
+      (for 0
+           (- depth 1)
+           (lambda (i)
+             (for-each (prop-d i) (vector-ref sorted i))))
+      (for-each prop-k (vector-ref types depth))
+      (vector-set! types depth '())
+      (if fullsharing
+        (begin
+          (for-each (lambda (t) (revtype t t)) t-list)
+          (for-each gen leaves)
+          (for-each cleanup needs-cleanup))
+        (for-each gen2 t-list))
+      (for 0
+           depth
+           (lambda (i) (for-each upd (vector-ref sorted i))))
+      (if (null? t-list)
+        '()
+        (match-let*
+          ((n-gen (- generic-index))
+           ((t-list n-gen)
+            (if (and pseudo flags (not all?))
+              (pseudo t-list n-gen)
+              (list t-list n-gen))))
+          (visible t-list n-gen)
+          (map (lambda (t) (make-ts t n-gen)) t-list))))))
+(define visible-time 0)
+(define visible
+  (lambda (t-list n-gen)
+    (let* ((before (cpu-time))
+           (valences (make-vector n-gen '()))
+           (namer (generate-counter))
+           (lvis (rec lvis
+                      (lambda (t pos rcd)
+                        (match t
+                               (($ box ($ c d _ x p a n))
+                                (when (and (generic? d)
+                                           (not (element-of?
+                                                  pos
+                                                  (vector-ref
+                                                    valences
+                                                    (- (- d) 1)))))
+                                      (let ((u (union (vector-ref
+                                                        valences
+                                                        (- (- d) 1))
+                                                      (set pos))))
+                                        (vector-set! valences (- (- d) 1) u))
+                                      (lvis p pos rcd)
+                                      (match (k-name x)
+                                             ('?->
+                                              (lvis (car a) (not pos) #f)
+                                              (lvis (cadr a) pos #f))
+                                             ('record (lvis (car a) pos #t))
+                                             (_ (for-each
+                                                  (lambda (x) (lvis x pos #f))
+                                                  a)))
+                                      (lvis n pos rcd)))
+                               (($ box (and x ($ v d k _ _ _ _)))
+                                (when (and (generic? d)
+                                           (not (element-of?
+                                                  pos
+                                                  (vector-ref
+                                                    valences
+                                                    (- (- d) 1)))))
+                                      (let ((u (union (vector-ref
+                                                        valences
+                                                        (- (- d) 1))
+                                                      (set pos))))
+                                        (vector-set! valences (- (- d) 1) u)
+                                        (set-v-name! x namer)
+                                        (cond ((abs? k) #f)
+                                              ((= 2 (cardinality u))
+                                               (set-v-split! x #t)
+                                               (set-v-vis! x #t))
+                                              ((eq? pos rcd) (set-v-vis! x #t))
+                                              (else (set-v-vis! x #f))))))
+                               (($ box (? symbol?)) #f)
+                               (($ box i) (lvis i pos rcd)))))))
+      (for-each (lambda (t) (lvis t #t #f)) t-list)
+      (set! visible-time
+        (+ visible-time (- (cpu-time) before))))))
+(define visible?
+  (match-lambda
+    (($ box ($ v _ k _ vis _ _))
+     (or (pre? k) (and vis (not (abs? k)))))
+    (($ box 'top) #t)
+    (($ box 'bot) #f)
+    (($ box i) (visible? i))))
+(define instantiate
+  (lambda (ts syntax)
+    (match ts
+           (($ ts t n-gen)
+            (let* ((absv '())
+                   (seen (make-vector n-gen #f))
+                   (t2 (recur linst
+                              ((t t))
+                              (match t
+                                     (($ box (and y ($ v d k _ _ _ inst)))
+                                      (cond ((not (generic? d)) t)
+                                            ((vector-ref seen (- (- d) 1)))
+                                            (else
+                                             (let ((u (make-tvar depth k)))
+                                               (vector-set! seen (- (- d) 1) u)
+                                               (when inst
+                                                     (set-v-inst!
+                                                       y
+                                                       (cons (cons u syntax)
+                                                             inst)))
+                                               (when (or (abs? k) (pre? k))
+                                                     (set! absv (cons u absv)))
+                                               u))))
+                                     (($ box ($ c d _ x p a n))
+                                      (cond ((not (generic? d)) t)
+                                            ((vector-ref seen (- (- d) 1)))
+                                            (else
+                                             (let ((u (new-type
+                                                        '**fix**
+                                                        depth)))
+                                               (vector-set! seen (- (- d) 1) u)
+                                               (set-box!
+                                                 u
+                                                 (make-c
+                                                   depth
+                                                   'ord
+                                                   x
+                                                   (if flags (linst p) top)
+                                                   (map linst a)
+                                                   (linst n)))
+                                               u))))
+                                     (($ box (? symbol?)) t)
+                                     (($ box i) (linst i))))))
+              (list t2 absv))))))
+(define pseudo-subtype
+  (lambda (t-list n-gen)
+    (let* ((valences (make-vector n-gen '()))
+           (valence-of
+             (lambda (d) (vector-ref valences (- (- d) 1))))
+           (set-valence
+             (lambda (d v)
+               (vector-set! valences (- (- d) 1) v)))
+           (find (rec find
+                      (lambda (t pos mutable)
+                        (match t
+                               (($ box ($ v d _ _ _ _ _))
+                                (when (generic? d)
+                                      (cond (mutable
+                                             (set-valence d (set #t #f)))
+                                            ((not (element-of?
+                                                    pos
+                                                    (valence-of d)))
+                                             (set-valence
+                                               d
+                                               (union (valence-of d)
+                                                      (set pos))))
+                                            (else #f))))
+                               (($ box ($ c d _ x p a n))
+                                (when (generic? d)
+                                      (cond ((= 2 (cardinality (valence-of d)))
+                                             #f)
+                                            (mutable
+                                             (set-valence d (set #t #f))
+                                             (for-each2
+                                               (lambda (t m)
+                                                 (find t pos mutable))
+                                               a
+                                               (k-args x))
+                                             (find n pos mutable))
+                                            ((not (element-of?
+                                                    pos
+                                                    (valence-of d)))
+                                             (set-valence
+                                               d
+                                               (union (valence-of d)
+                                                      (set pos)))
+                                             (if (eq? '?-> (k-name x))
+                                               (begin
+                                                 (find (car a)
+                                                       (not pos)
+                                                       mutable)
+                                                 (find (cadr a) pos mutable))
+                                               (for-each2
+                                                 (lambda (t m)
+                                                   (find t pos (or m mutable)))
+                                                 a
+                                                 (k-args x)))
+                                             (find n pos mutable))
+                                            (else #f))))
+                               (($ box (? symbol?)) #f)
+                               (($ box i) (find i pos mutable))))))
+           (seen (make-vector n-gen #f))
+           (new-generic-var
+             (lambda ()
+               (set! n-gen (+ 1 n-gen))
+               (box (make-raw-tvar (- n-gen) 'ord))))
+           (copy (rec copy
+                      (lambda (t)
+                        (match t
+                               (($ box ($ v d k _ _ _ _))
+                                (if (generic? d)
+                                  (or (vector-ref seen (- (- d) 1))
+                                      (let ((u (if (and (abs? k)
+                                                        (equal?
+                                                          (valence-of d)
+                                                          '(#t)))
+                                                 (new-generic-var)
+                                                 t)))
+                                        (vector-set! seen (- (- d) 1) u)
+                                        u))
+                                  t))
+                               (($ box ($ c d k x p a n))
+                                (if (generic? d)
+                                  (or (vector-ref seen (- (- d) 1))
+                                      (let* ((u (box '**fix**))
+                                             (_ (vector-set!
+                                                  seen
+                                                  (- (- d) 1)
+                                                  u))
+                                             (new-p (if (and (eq? (ind* p) top)
+                                                             (equal?
+                                                               (valence-of d)
+                                                               '(#f)))
+                                                      (new-generic-var)
+                                                      (copy p)))
+                                             (new-a (map copy a))
+                                             (new-n (copy n)))
+                                        (set-box!
+                                          u
+                                          (make-c d 'ord x new-p new-a new-n))
+                                        u))
+                                  t))
+                               (($ box (? symbol?)) t)
+                               (($ box i) (copy i))))))
+           (t-list
+             (map (lambda (t) (find t #t #f) (copy t)) t-list)))
+      (list t-list n-gen))))
+(set! pseudo pseudo-subtype)
+(define unify
+  (letrec ((uni (lambda (u v)
+                  (unless
+                    (eq? u v)
+                    (match (cons u v)
+                           ((($ box (and us ($ c ud uk ux up ua un)))
+                             $
+                             box
+                             (and vs ($ c vd vk vx vp va vn)))
+                            (if (eq? ux vx)
+                              (begin
+                                (if (< ud vd)
+                                  (begin
+                                    (set-box! v u)
+                                    (when (kind< vk uk) (set-c-kind! us vk)))
+                                  (begin
+                                    (set-box! u v)
+                                    (when (kind< uk vk) (set-c-kind! vs uk))))
+                                (uni un vn)
+                                (for-each2 uni ua va)
+                                (uni up vp))
+                              (let* ((next (tvar))
+                                     (k (if (kind< uk vk) uk vk)))
+                                (if (< ud vd)
+                                  (begin
+                                    (when (< vd ud) (set-c-depth! us vd))
+                                    (when (kind< vk uk) (set-c-kind! us vk))
+                                    (set-box! v u))
+                                  (begin
+                                    (when (< ud vd) (set-c-depth! vs ud))
+                                    (when (kind< uk vk) (set-c-kind! vs uk))
+                                    (set-box! u v)))
+                                (uni (new-type
+                                       (make-c depth k ux up ua next)
+                                       depth)
+                                     vn)
+                                (uni un
+                                     (new-type
+                                       (make-c depth k vx vp va next)
+                                       depth)))))
+                           ((($ box (and x ($ v ud uk _ _ _ _)))
+                             $
+                             box
+                             ($ v vd vk _ _ _ _))
+                            (set-v-depth! x (min ud vd))
+                            (set-v-kind! x (if (kind< uk vk) uk vk))
+                            (set-box! v u))
+                           ((($ box ($ v ud uk _ _ _ _))
+                             $
+                             box
+                             (and x ($ c vd vk _ _ _ _)))
+                            (when (< ud vd) (set-c-depth! x ud))
+                            (when (kind< uk vk) (set-c-kind! x uk))
+                            (set-box! u v))
+                           ((($ box (and x ($ c ud uk _ _ _ _)))
+                             $
+                             box
+                             ($ v vd vk _ _ _ _))
+                            (when (< vd ud) (set-c-depth! x vd))
+                            (when (kind< vk uk) (set-c-kind! x vk))
+                            (set-box! v u))
+                           ((($ box ($ v _ _ _ _ _ _)) $ box (? symbol?))
+                            (set-box! u v))
+                           ((($ box (? symbol?)) $ box ($ v _ _ _ _ _ _))
+                            (set-box! v u))
+                           ((($ box 'bot) $ box ($ c _ _ _ p _ n))
+                            (set-box! v u)
+                            (uni u p)
+                            (uni u n))
+                           ((($ box ($ c _ _ _ p _ n)) $ box 'bot)
+                            (set-box! u v)
+                            (uni v p)
+                            (uni v n))
+                           (_ (uni (ind* u) (ind* v))))))))
+    uni))
+(define kind<
+  (lambda (k1 k2) (and (ord? k2) (not (ord? k1)))))
+(define r+-
+  (lambda (flag+ flag- tail+- absent- pos env type)
+    (letrec ((absent+ v-ord)
+             (tvars '())
+             (fvars '())
+             (absv '())
+             (make-flag
+               (lambda (pos)
+                 (cond ((not flags) top)
+                       (pos (flag+))
+                       (else (flag-)))))
+             (typevar?
+               (lambda (v)
+                 (and (symbol? v)
+                      (not (bound? env v))
+                      (not (memq v
+                                 '(_ bool
+                                     mu
+                                     list
+                                     &list
+                                     &optional
+                                     &rest
+                                     arglist
+                                     +
+                                     not
+                                     rec
+                                     *tidy))))))
+             (parse-type
+               (lambda (t pos)
+                 (match t
+                        (('mu a t)
+                         (unless
+                           (typevar? a)
+                           (raise 'type "invalid type syntax at ~a" t))
+                         (when (assq a tvars)
+                               (raise 'type "~a is defined more than once" a))
+                         (let* ((fix (new-type '**fix** depth))
+                                (_ (set! tvars (cons (list a fix '()) tvars)))
+                                (t (parse-type t pos)))
+                           (when (eq? t fix)
+                                 (raise 'type
+                                        "recursive type is not contractive"))
+                           (set-box! fix t)
+                           (ind* t)))
+                        (('rec (? list? bind) t2)
+                         (for-each
+                           (match-lambda
+                             ((a _)
+                              (unless
+                                (typevar? a)
+                                (raise 'type "invalid type syntax at ~a" t))
+                              (when (assq a tvars)
+                                    (raise 'type
+                                           "~a is defined more than once"
+                                           a))
+                              (set! tvars
+                                (cons (list a (new-type '**fix** depth) '())
+                                      tvars)))
+                             (_ (raise 'type "invalid type syntax at ~a" t)))
+                           bind)
+                         (for-each
+                           (match-lambda
+                             ((a t)
+                              (match (assq a tvars)
+                                     ((_ fix _)
+                                      (let ((t (parse-type t '?)))
+                                        (when (eq? t fix)
+                                              (raise 'type
+                                                     "type is not contractive"))
+                                        (set-box! fix t))))))
+                           bind)
+                         (parse-type t2 pos))
+                        ('bool (parse-type '(+ false true) pos))
+                        ('s-exp
+                         (let ((v (gensym)))
+                           (parse-type
+                             `(mu ,v
+                                  (+ num
+                                     nil
+                                     false
+                                     true
+                                     char
+                                     sym
+                                     str
+                                     (vec ,v)
+                                     (box ,v)
+                                     (cons ,v ,v)))
+                             pos)))
+                        (('list t)
+                         (let ((u (gensym)))
+                           (parse-type `(mu ,u (+ nil (cons ,t ,u))) pos)))
+                        (('arglist t)
+                         (let ((u (gensym)))
+                           (parse-type `(mu ,u (+ noarg (arg ,t ,u))) pos)))
+                        (('+ ? list? union) (parse-union union pos))
+                        (t (parse-union (list t) pos)))))
+             (parse-union
+               (lambda (t pos)
+                 (letrec ((sort-cs
+                            (lambda (cs)
+                              (sort-list
+                                cs
+                                (lambda (x y) (k< (c-fsym x) (c-fsym y))))))
+                          (link (lambda (c t)
+                                  (set-c-next! c t)
+                                  (new-type c depth))))
+                   (recur loop
+                          ((t t) (cs '()))
+                          (match t
+                                 (()
+                                  (foldr link
+                                         (if pos
+                                           (absent+)
+                                           (let ((v (absent-)))
+                                             (set! absv (cons v absv))
+                                             v))
+                                         (sort-cs cs)))
+                                 (((? box? t)) (foldr link t (sort-cs cs)))
+                                 (('_) (foldr link (tail+-) (sort-cs cs)))
+                                 (((? symbol? a))
+                                  (=> fail)
+                                  (unless (typevar? a) (fail))
+                                  (let* ((cs (sort-cs cs))
+                                         (ks (map c-fsym cs)))
+                                    (foldr link
+                                           (match (assq a tvars)
+                                                  ((_ f aks)
+                                                   (unless
+                                                     (equal? ks aks)
+                                                     (raise 'type
+                                                            "variable ~a is not tidy"
+                                                            a))
+                                                   f)
+                                                  (#f
+                                                   (let ((v (tail+-)))
+                                                     (set! tvars
+                                                       (cons (list a v ks)
+                                                             tvars))
+                                                     v)))
+                                           cs)))
+                                 ((k . rest)
+                                  (loop rest (cons (parse-k k pos) cs))))))))
+             (parse-k
+               (lambda (k pos)
+                 (cond ((and (list? k)
+                             (let ((n (length k)))
+                               (and (<= 2 n) (eq? '-> (list-ref k (- n 2))))))
+                        (let* ((rk (reverse k))
+                               (arg (reverse (cddr rk)))
+                               (res (car rk)))
+                          (letrec ((mkargs
+                                     (match-lambda
+                                       (() 'noarg)
+                                       ((('&rest x)) x)
+                                       ((('&list x))
+                                        (let ((u (gensym)))
+                                          `(mu ,u (+ noarg (arg ,x ,u)))))
+                                       ((('&optional x))
+                                        `(+ noarg (arg ,x noarg)))
+                                       ((x . y) `(arg ,x ,(mkargs y)))
+                                       (_ (raise 'type
+                                                 "invalid type syntax")))))
+                            (make-c
+                              depth
+                              'ord
+                              (lookup env '?->)
+                              (make-flag pos)
+                              (let ((a (parse-type (mkargs arg) (flip pos)))
+                                    (r (parse-type res pos)))
+                                (list a r))
+                              '**fix**))))
+                       (else
+                        (match k
+                               ((arg '?-> res)
+                                (make-c
+                                  depth
+                                  'ord
+                                  (lookup env '?->)
+                                  (make-flag pos)
+                                  (let ((a (parse-type arg (flip pos)))
+                                        (r (parse-type res pos)))
+                                    (list a r))
+                                  '**fix**))
+                               (('record ? list? fields)
+                                (make-c
+                                  depth
+                                  'ord
+                                  (lookup env 'record)
+                                  (make-flag pos)
+                                  (list (recur loop
+                                               ((fields fields))
+                                               (match fields
+                                                      (() (if pos bot (v-ord)))
+                                                      ((((? symbol? f) ftype)
+                                                        .
+                                                        rest)
+                                                       (new-type
+                                                         (make-c
+                                                           depth
+                                                           'ord
+                                                           (new-field! f)
+                                                           (if pos
+                                                             (v-ord)
+                                                             (let ((v (v-pre)))
+                                                               (set! absv
+                                                                 (cons v absv))
+                                                               v))
+                                                           (list (parse-type
+                                                                   ftype
+                                                                   pos))
+                                                           (loop rest))
+                                                         depth)))))
+                                  '**fix**))
+                               (('not (? k? k))
+                                (make-c
+                                  depth
+                                  'ord
+                                  k
+                                  (if pos
+                                    (absent+)
+                                    (let ((v (absent-)))
+                                      (set! absv (cons v absv))
+                                      v))
+                                  (map (lambda (x) (tail+-)) (k-args k))
+                                  '**fix**))
+                               (('not c)
+                                (unless
+                                  (bound? env c)
+                                  (raise 'type "invalid type syntax at ~a" k))
+                                (let ((k (lookup env c)))
+                                  (make-c
+                                    depth
+                                    'ord
+                                    k
+                                    (if pos
+                                      (absent+)
+                                      (let ((v (absent-)))
+                                        (set! absv (cons v absv))
+                                        v))
+                                    (map (lambda (x) (tail+-)) (k-args k))
+                                    '**fix**)))
+                               (('*tidy c (? symbol? f))
+                                (unless
+                                  (bound? env c)
+                                  (raise 'type "invalid type syntax at ~a" k))
+                                (let ((k (lookup env c)))
+                                  (make-c
+                                    depth
+                                    'ord
+                                    k
+                                    (match (assq f fvars)
+                                           ((_ . f) f)
+                                           (#f
+                                            (let ((v (tail+-)))
+                                              (set! fvars
+                                                (cons (cons f v) fvars))
+                                              v)))
+                                    (map (lambda (x) (parse-type '(+) pos))
+                                         (k-args k))
+                                    '**fix**)))
+                               (((? k? k) ? list? arg)
+                                (unless
+                                  (= (length arg) (length (k-args k)))
+                                  (raise 'type
+                                         "~a requires ~a arguments"
+                                         (k-name k)
+                                         (length (k-args k))))
+                                (make-c
+                                  depth
+                                  'ord
+                                  k
+                                  (make-flag pos)
+                                  (smap (lambda (x) (parse-type x pos)) arg)
+                                  '**fix**))
+                               ((c ? list? arg)
+                                (unless
+                                  (bound? env c)
+                                  (raise 'type "invalid type syntax at ~a" k))
+                                (let ((k (lookup env c)))
+                                  (unless
+                                    (= (length arg) (length (k-args k)))
+                                    (raise 'type
+                                           "~a requires ~a arguments"
+                                           c
+                                           (length (k-args k))))
+                                  (make-c
+                                    depth
+                                    'ord
+                                    k
+                                    (make-flag pos)
+                                    (smap (lambda (x) (parse-type x pos)) arg)
+                                    '**fix**)))
+                               (c (unless
+                                    (bound? env c)
+                                    (raise 'type
+                                           "invalid type syntax at ~a"
+                                           k))
+                                  (let ((k (lookup env c)))
+                                    (unless
+                                      (= 0 (length (k-args k)))
+                                      (raise 'type
+                                             "~a requires ~a arguments"
+                                             c
+                                             (length (k-args k))))
+                                    (make-c
+                                      depth
+                                      'ord
+                                      k
+                                      (make-flag pos)
+                                      '()
+                                      '**fix**))))))))
+             (flip (match-lambda ('? '?) (#t #f) (#f #t))))
+      (let ((t (parse-type type pos))) (list t absv)))))
+(define v-top (lambda () top))
+(define r+
+  (lambda (env t)
+    (car (r+- v-top v-ord v-ord v-abs #t env t))))
+(define r-
+  (lambda (env t)
+    (car (r+- v-top v-ord v-ord v-abs #f env t))))
+(define r++
+  (lambda (env t)
+    (car (r+- v-top v-ord v-ord v-ord #t env t))))
+(define r+collect
+  (lambda (env t)
+    (r+- v-top v-ord v-ord v-abs #t env t)))
+(define r-collect
+  (lambda (env t)
+    (r+- v-top v-ord v-ord v-abs #f env t)))
+(define r (lambda (t) (r+ initial-type-env t)))
+(define r-match
+  (lambda (t)
+    (close '())
+    '(pretty-print `(fixing ,(ptype t)))
+    (fix-pat-abs! t)
+    (list t (collect-abs t))))
+(define collect-abs
+  (lambda (t)
+    (let ((seen '()))
+      (recur loop
+             ((t t))
+             (match t
+                    (($ box ($ v _ k _ _ _ _))
+                     (if (abs? k) (set t) empty-set))
+                    (($ box ($ c _ _ _ p a n))
+                     (if (memq t seen)
+                       empty-set
+                       (begin
+                         (set! seen (cons t seen))
+                         (foldr union
+                                (union (loop p) (loop n))
+                                (map loop a)))))
+                    (($ box (? symbol?)) empty-set)
+                    (($ box i) (loop i)))))))
+(define fix-pat-abs!
+  (lambda (t)
+    (let ((seen '()))
+      (recur loop
+             ((t t))
+             (match t
+                    (($ box (and x ($ v d _ _ _ _ _)))
+                     (when (= d depth) (set-v-kind! x 'abs)))
+                    (($ box (and c ($ c _ _ _ p a n)))
+                     (unless
+                       (memq t seen)
+                       (set! seen (cons t seen))
+                       (loop p)
+                       (when (and matchst flags (eq? (ind* p) top))
+                             (set-c-pres! c (v-ord)))
+                       (for-each loop a)
+                       (loop n)))
+                    (($ box (? symbol?)) t)
+                    (($ box i) (loop i)))))))
+(define pat-var-bind
+  (lambda (t)
+    (let ((seen '()))
+      (recur loop
+             ((t t))
+             (match t
+                    (($ box ($ v d _ _ _ _ _))
+                     (if (< d depth)
+                       t
+                       (match (assq t seen)
+                              ((_ . new) new)
+                              (#f
+                               (let* ((new (v-ord)))
+                                 (set! seen (cons (cons t new) seen))
+                                 new)))))
+                    (($ box ($ c d k x p a n))
+                     (match (assq t seen)
+                            ((_ . new) new)
+                            (#f
+                             (let* ((fix (new-type '**fix** depth))
+                                    (fixbox (box fix))
+                                    (_ (set! seen (cons (cons t fixbox) seen)))
+                                    (new-p (if flags (loop p) top))
+                                    (new-a (map2 (lambda (mutable a)
+                                                   (if mutable a (loop a)))
+                                                 (k-args x)
+                                                 a))
+                                    (new-n (loop n)))
+                               (if (and (eq? new-p p)
+                                        (eq? new-n n)
+                                        (andmap eq? new-a a))
+                                 (begin (set-box! fixbox t) t)
+                                 (begin
+                                   (set-box!
+                                     fix
+                                     (make-c d k x new-p new-a new-n))
+                                   fix))))))
+                    (($ box (? symbol?)) t)
+                    (($ box i) (loop i)))))))
+(define fields '())
+(define new-field!
+  (lambda (x)
+    (match (assq x fields)
+           (#f
+            (let ((k (make-k x (+ 1 (length fields)) '(#f))))
+              (set! fields (cons (cons x k) fields))
+              k))
+           ((_ . k) k))))
+(define k<
+  (lambda (x y) (< (k-order x) (k-order y))))
+(define k-counter 0)
+(define bind-tycon
+  (lambda (x args covers fail-thunk)
+    (when (memq x
+                '(_ bool
+                    mu
+                    list
+                    &list
+                    &optional
+                    &rest
+                    arglist
+                    +
+                    not
+                    rec
+                    *tidy))
+          (fail-thunk "invalid type constructor ~a" x))
+    (set! k-counter (+ 1 k-counter))
+    (make-k
+      (if covers
+        (symbol-append x "." (- k-counter 100))
+        x)
+      k-counter
+      args)))
+(define initial-type-env '())
+(define init-types!
+  (lambda ()
+    (set! k-counter 0)
+    (set! var-counter (generate-counter))
+    (set! initial-type-env
+      (foldl (lambda (l env)
+               (extend-env
+                 env
+                 (car l)
+                 (bind-tycon
+                   (car l)
+                   (cdr l)
+                   #f
+                   (lambda x (apply disaster 'init x)))))
+             empty-env
+             initial-type-info))
+    (set! k-counter 100)
+    (reset-types!)))
+(define reinit-types!
+  (lambda ()
+    (set! var-counter (generate-counter))
+    (set! k-counter 100)
+    (set! fields '())
+    (set-cons-mutability! #t)
+    (reset-types!)))
+(define deftype
+  (lambda (tag mutability)
+    (set! initial-type-env
+      (extend-env
+        initial-type-env
+        tag
+        (make-k
+          tag
+          (+ 1 (length initial-type-env))
+          mutability)))))
+(define initial-type-info
+  '((?-> #f #f)
+    (arg #f #f)
+    (noarg)
+    (num)
+    (nil)
+    (false)
+    (true)
+    (char)
+    (sym)
+    (str)
+    (void)
+    (iport)
+    (oport)
+    (eof)
+    (vec #t)
+    (box #t)
+    (cons #t #t)
+    (cvec #f)
+    (promise #t)
+    (record #f)
+    (module #f)))
+(define cons-is-mutable #f)
+(define set-cons-mutability!
+  (lambda (m)
+    (set! cons-is-mutable m)
+    (set-k-args!
+      (lookup initial-type-env 'cons)
+      (list m m))))
+(define tidy?
+  (lambda (t)
+    (let ((seen '()))
+      (recur loop
+             ((t t) (label '()))
+             (match t
+                    (($ box (? v?))
+                     (match (assq t seen)
+                            (#f (set! seen (cons (cons t label) seen)) #t)
+                            ((_ . l2) (equal? label l2))))
+                    (($ box ($ c _ _ x _ a n))
+                     (match (assq t seen)
+                            ((_ . l2) (equal? label l2))
+                            (#f
+                             (set! seen (cons (cons t label) seen))
+                             (and (loop n (sort-list (cons x label) k<))
+                                  (andmap (lambda (t) (loop t '())) a)))))
+                    (($ box (? symbol?)) #t)
+                    (($ box i) (loop i label)))))))
+(define tidy
+  (match-lambda
+    (($ ts t _)
+     (tidy-print t print-union assemble-union #f))
+    (t (tidy-print t print-union assemble-union #f))))
+(define ptype
+  (match-lambda
+    (($ ts t _)
+     (tidy-print
+       t
+       print-raw-union
+       assemble-raw-union
+       #t))
+    (t (tidy-print
+         t
+         print-raw-union
+         assemble-raw-union
+         #t))))
+(define tidy-print
+  (lambda (t print assemble top)
+    (let* ((share (shared-unions t top))
+           (bindings
+             (map-with-n
+               (lambda (t n)
+                 (list t
+                       (box #f)
+                       (box #f)
+                       (symbol-append "Y" (+ 1 n))))
+               share))
+           (body (print t (print-binding bindings)))
+           (let-bindings
+             (filter-map
+               (match-lambda
+                 ((_ _ ($ box #f) _) #f)
+                 ((_ ($ box t) ($ box x) _) (list x t)))
+               bindings)))
+      (assemble let-bindings body))))
+(define print-binding
+  (lambda (bindings)
+    (lambda (ty share-wrapper var-wrapper render)
+      (match (assq ty bindings)
+             (#f (render))
+             ((_ box-tprint box-name nprint)
+              (var-wrapper
+                (or (unbox box-name)
+                    (begin
+                      (set-box! box-name nprint)
+                      (set-box! box-tprint (share-wrapper (render)))
+                      nprint))))))))
+(define shared-unions
+  (lambda (t all)
+    (let ((seen '()))
+      (recur loop
+             ((t t) (top #t))
+             (match t
+                    (($ box (? v?)) #f)
+                    (($ box ($ c _ _ _ _ a n))
+                     (match (and top (assq t seen))
+                            (#f
+                             (set! seen (cons (cons t (box 1)) seen))
+                             (for-each (lambda (x) (loop x #t)) a)
+                             (loop n all))
+                            ((_ . b) (set-box! b (+ 1 (unbox b))))))
+                    (($ box (? symbol?)) #f)
+                    (($ box i) (loop i top))))
+      (reverse
+        (filter-map
+          (match-lambda ((_ $ box 1) #f) ((t . _) t))
+          seen)))))
+(define print-raw-union
+  (lambda (t print-share)
+    (recur loop
+           ((t t))
+           (match t
+                  (($ box ($ v _ _ _ _ split _))
+                   (if (and share split)
+                     (string->symbol (sprintf "~a#" (pvar t)))
+                     (pvar t)))
+                  (($ box ($ c d k x p a n))
+                   (print-share
+                     t
+                     (lambda (x) x)
+                     (lambda (x) x)
+                     (lambda ()
+                       (let* ((name (if (abs? k)
+                                      (symbol-append '~ (k-name x))
+                                      (k-name x)))
+                              (name (if dump-depths
+                                      (symbol-append d '! name)
+                                      name))
+                              (pr-x `(,name ,@(maplr loop (cons p a)))))
+                         (cons pr-x (loop n))))))
+                  (($ box 'top) '+)
+                  (($ box 'bot) '-)
+                  (($ box i) (loop i))))))
+(define assemble-raw-union
+  (lambda (bindings body)
+    (if (null? bindings) body `(rec ,bindings ,body))))
+(define print-union
+  (lambda (t print-share)
+    (add-+ (recur loop
+                  ((t t) (tailvis (visible? (tailvar t))))
+                  (match t
+                         (($ box (? v?))
+                          (if (visible? t) (list (pvar t)) '()))
+                         (($ box ($ c _ _ x p a n))
+                          (print-share
+                            t
+                            add-+
+                            list
+                            (lambda ()
+                              (cond ((visible? p)
+                                     (let* ((split-flag
+                                              (and share
+                                                   (match (ind* p)
+                                                          (($ box
+                                                              ($ v
+                                                                 _
+                                                                 _
+                                                                 _
+                                                                 _
+                                                                 split
+                                                                 _))
+                                                           split)
+                                                          (_ #f))))
+                                            (kname (if split-flag
+                                                     (string->symbol
+                                                       (sprintf
+                                                         "~a#~a"
+                                                         (k-name x)
+                                                         (pvar p)))
+                                                     (k-name x))))
+                                       (cons (cond ((null? a) kname)
+                                                   ((eq? '?-> (k-name x))
+                                                    (let ((arg (add-+ (loop (car a)
+                                                                            (visible?
+                                                                              (tailvar
+                                                                                (car a))))))
+                                                          (res (add-+ (loop (cadr a)
+                                                                            (visible?
+                                                                              (tailvar
+                                                                                (cadr a)))))))
+                                                      (decode-arrow
+                                                        kname
+                                                        (lambda ()
+                                                          (if split-flag
+                                                            (string->symbol
+                                                              (sprintf
+                                                                "->#~a"
+                                                                (pvar p)))
+                                                            '->))
+                                                        arg
+                                                        res)))
+                                                   ((eq? 'record (k-name x))
+                                                    `(,kname
+                                                      ,@(loop (car a) #f)))
+                                                   (else
+                                                    `(,kname
+                                                      ,@(maplr (lambda (x)
+                                                                 (add-+ (loop x
+                                                                              (visible?
+                                                                                (tailvar
+                                                                                  x)))))
+                                                               a))))
+                                             (loop n tailvis))))
+                                    ((not tailvis) (loop n tailvis))
+                                    (else
+                                     (cons `(not ,(k-name x))
+                                           (loop n tailvis)))))))
+                         (($ box 'bot) '())
+                         (($ box i) (loop i tailvis)))))))
+(define assemble-union
+  (lambda (bindings body)
+    (subst-small-type
+      (map clean-binding bindings)
+      body)))
+(define add-+
+  (match-lambda
+    (() 'empty)
+    ((t) t)
+    (x (cons '+ x))))
+(define tailvar
+  (lambda (t)
+    (match t
+           (($ box (? v?)) t)
+           (($ box ($ c _ _ _ _ _ n)) (tailvar n))
+           (($ box 'bot) t)
+           (($ box i) (tailvar i)))))
+(define decode-arrow
+  (lambda (kname thunk-> arg res)
+    (let ((args (recur loop
+                       ((l arg))
+                       (match l
+                              ('noarg '())
+                              (('arg a b) `(,a ,@(loop b)))
+                              (('+ ('arg a b) 'noarg . _)
+                               `((&optional ,a) ,@(loop b)))
+                              (('+ 'noarg ('arg a b) . _)
+                               `((&optional ,a) ,@(loop b)))
+                              ((? symbol? z)
+                               (if (rectypevar? z) `(,z) `((&rest ,z))))
+                              (('+ 'noarg z) (loop z))
+                              (('+ ('arg a b) z)
+                               (loop `(+ (arg ,a ,b) noarg ,z)))))))
+      `(,@args ,(thunk->) ,res))))
+(define rectypevar?
+  (lambda (s)
+    (memq (string-ref (symbol->string s) 0) '(#\Y))))
+(define typevar?
+  (lambda (s)
+    (memq (string-ref (symbol->string s) 0)
+          '(#\X #\Z))))
+(define clean-binding
+  (lambda (binding)
+    (match binding
+           ((u ('+ 'nil ('cons a v)))
+            (if (and (equal? u v) (not (memq* u a)))
+              (list u `(list ,a))
+              binding))
+           ((u ('+ ('cons a v) 'nil))
+            (if (and (equal? u v) (not (memq* u a)))
+              (list u `(list ,a))
+              binding))
+           ((u ('+ 'nil ('cons a v) (? symbol? z)))
+            (if (and (equal? u v) (not (memq* u a)) (typevar? z))
+              (list u `(list* ,a ,z))
+              binding))
+           ((u ('+ ('cons a v) 'nil (? symbol? z)))
+            (if (and (equal? u v) (not (memq* u a)) (typevar? z))
+              (list u `(list* ,a ,z))
+              binding))
+           ((u ('+ 'noarg ('arg a v)))
+            (if (and (equal? u v) (not (memq* u a)))
+              (list u `(&list ,a))
+              binding))
+           ((u ('+ ('arg a v) 'noarg))
+            (if (and (equal? u v) (not (memq* u a)))
+              (list u `(&list ,a))
+              binding))
+           (x x))))
+(define memq*
+  (lambda (v t)
+    (recur loop
+           ((t t))
+           (match t
+                  ((x . y) (or (loop x) (loop y)))
+                  (_ (eq? v t))))))
+(define subst-type
+  (lambda (new old t)
+    (match new
+           (('list elem) (subst-list elem old t))
+           (_ (subst* new old t)))))
+(define subst-list
+  (lambda (elem old t)
+    (match t
+           ((? symbol?) (if (eq? old t) `(list ,elem) t))
+           (('+ 'nil ('cons a (? symbol? b)))
+            (if (and (eq? b old) (equal? elem a))
+              `(list ,elem)
+              `(+ nil (cons ,(subst-list elem old a) ,b))))
+           (('+ ('cons a (? symbol? b)) 'nil)
+            (if (and (eq? b old) (equal? elem a))
+              `(list ,elem)
+              `(+ nil (cons ,(subst-list elem old a) ,b))))
+           ((a . b)
+            (cons (subst-list elem old a)
+                  (subst-list elem old b)))
+           (z z))))
+(define subst*
+  (lambda (new old t)
+    (cond ((eq? old t) new)
+          ((pair? t)
+           (cons (subst* new old (car t))
+                 (subst* new old (cdr t))))
+          (else t))))
+(define subst-small-type
+  (lambda (bindings body)
+    (recur loop
+           ((bindings bindings) (newb '()) (body body))
+           (match bindings
+                  (()
+                   (let ((newb (filter
+                                 (match-lambda
+                                   ((name type) (not (equal? name type))))
+                                 newb)))
+                     (if (null? newb)
+                       body
+                       `(rec ,(reverse newb) ,body))))
+                  (((and b (name type)) . rest)
+                   (if (and (not (memq* name type)) (small-type? type))
+                     (loop (subst-type type name rest)
+                           (subst-type type name newb)
+                           (subst-type type name body))
+                     (loop rest (cons b newb) body)))))))
+(define small-type?
+  (lambda (t)
+    (>= 8
+        (recur loop
+               ((t t))
+               (match t
+                      ('+ 0)
+                      ((? symbol? s) 1)
+                      ((? number? n) 0)
+                      ((x . y) (+ (loop x) (loop y)))
+                      (() 0))))))
+(define qop
+  (lambda (s)
+    (string->symbol (string-append "# " s))))
+(define qcons (qop "cons"))
+(define qbox (qop "box"))
+(define qlist (qop "list"))
+(define qvector (qop "vector"))
+(define initial-info
+  `((not (a -> bool))
+    (eqv? (a a -> bool))
+    (eq? (a a -> bool))
+    (equal? (a a -> bool))
+    (cons (a b -> (cons a b)) (ic))
+    (car ((cons a b) -> a) (s (x . _)))
+    (cdr ((cons b a) -> a) (s (_ . x)))
+    (caar ((cons (cons a b) c) -> a)
+          (s ((x . _) . _)))
+    (cadr ((cons c (cons a b)) -> a) (s (_ x . _)))
+    (cdar ((cons (cons b a) c) -> a)
+          (s ((_ . x) . _)))
+    (cddr ((cons c (cons b a)) -> a) (s (_ _ . x)))
+    (caaar ((cons (cons (cons a b) c) d) -> a)
+           (s (((x . _) . _) . _)))
+    (caadr ((cons d (cons (cons a b) c)) -> a)
+           (s (_ (x . _) . _)))
+    (cadar ((cons (cons c (cons a b)) d) -> a)
+           (s ((_ x . _) . _)))
+    (caddr ((cons d (cons c (cons a b))) -> a)
+           (s (_ _ x . _)))
+    (cdaar ((cons (cons (cons b a) c) d) -> a)
+           (s (((_ . x) . _) . _)))
+    (cdadr ((cons d (cons (cons b a) c)) -> a)
+           (s (_ (_ . x) . _)))
+    (cddar ((cons (cons c (cons b a)) d) -> a)
+           (s ((_ _ . x) . _)))
+    (cdddr ((cons d (cons c (cons b a))) -> a)
+           (s (_ _ _ . x)))
+    (caaaar
+      ((cons (cons (cons (cons a b) c) d) e) -> a)
+      (s ((((x . _) . _) . _) . _)))
+    (caaadr
+      ((cons e (cons (cons (cons a b) c) d)) -> a)
+      (s (_ ((x . _) . _) . _)))
+    (caadar
+      ((cons (cons d (cons (cons a b) c)) e) -> a)
+      (s ((_ (x . _) . _) . _)))
+    (caaddr
+      ((cons e (cons d (cons (cons a b) c))) -> a)
+      (s (_ _ (x . _) . _)))
+    (cadaar
+      ((cons (cons (cons c (cons a b)) d) e) -> a)
+      (s (((_ x . _) . _) . _)))
+    (cadadr
+      ((cons e (cons (cons c (cons a b)) d)) -> a)
+      (s (_ (_ x . _) . _)))
+    (caddar
+      ((cons (cons d (cons c (cons a b))) e) -> a)
+      (s ((_ _ x . _) . _)))
+    (cadddr
+      ((cons e (cons d (cons c (cons a b)))) -> a)
+      (s (_ _ _ x . _)))
+    (cdaaar
+      ((cons (cons (cons (cons b a) c) d) e) -> a)
+      (s ((((_ . x) . _) . _) . _)))
+    (cdaadr
+      ((cons e (cons (cons (cons b a) c) d)) -> a)
+      (s (_ ((_ . x) . _) . _)))
+    (cdadar
+      ((cons (cons d (cons (cons b a) c)) e) -> a)
+      (s ((_ (_ . x) . _) . _)))
+    (cdaddr
+      ((cons e (cons d (cons (cons b a) c))) -> a)
+      (s (_ _ (_ . x) . _)))
+    (cddaar
+      ((cons (cons (cons c (cons b a)) d) e) -> a)
+      (s (((_ _ . x) . _) . _)))
+    (cddadr
+      ((cons e (cons (cons c (cons b a)) d)) -> a)
+      (s (_ (_ _ . x) . _)))
+    (cdddar
+      ((cons (cons d (cons c (cons b a))) e) -> a)
+      (s ((_ _ _ . x) . _)))
+    (cddddr
+      ((cons e (cons d (cons c (cons b a)))) -> a)
+      (s (_ _ _ _ . x)))
+    (set-car! ((cons a b) a -> void))
+    (set-cdr! ((cons a b) b -> void))
+    (list ((&list a) -> (list a)) (ic))
+    (length ((list a) -> num))
+    (append ((&list (list a)) -> (list a)) (ic) (d))
+    (reverse ((list a) -> (list a)) (ic))
+    (list-tail ((list a) num -> (list a)) (c))
+    (list-ref ((list a) num -> a) (c))
+    (memq (a (list a) -> (+ false (cons a (list a)))))
+    (memv (a (list a) -> (+ false (cons a (list a)))))
+    (member
+      (a (list a) -> (+ false (cons a (list a)))))
+    (assq (a (list (cons a c)) -> (+ false (cons a c))))
+    (assv (a (list (cons a c)) -> (+ false (cons a c))))
+    (assoc (a (list (cons a c)) -> (+ false (cons a c))))
+    (symbol->string (sym -> str))
+    (string->symbol (str -> sym))
+    (complex? (a -> bool))
+    (real? (a -> bool))
+    (rational? (a -> bool))
+    (integer? (a -> bool))
+    (exact? (num -> bool))
+    (inexact? (num -> bool))
+    (= (num num (&list num) -> bool))
+    (< (num num (&list num) -> bool))
+    (> (num num (&list num) -> bool))
+    (<= (num num (&list num) -> bool))
+    (>= (num num (&list num) -> bool))
+    (zero? (num -> bool))
+    (positive? (num -> bool))
+    (negative? (num -> bool))
+    (odd? (num -> bool))
+    (even? (num -> bool))
+    (max (num (&list num) -> num))
+    (min (num (&list num) -> num))
+    (+ ((&list num) -> num))
+    (* ((&list num) -> num))
+    (- (num (&list num) -> num))
+    (/ (num (&list num) -> num))
+    (abs (num -> num))
+    (quotient (num num -> num))
+    (remainder (num num -> num))
+    (modulo (num num -> num))
+    (gcd ((&list num) -> num))
+    (lcm ((&list num) -> num))
+    (numerator (num -> num))
+    (denominator (num -> num))
+    (floor (num -> num))
+    (ceiling (num -> num))
+    (truncate (num -> num))
+    (round (num -> num))
+    (rationalize (num num -> num))
+    (exp (num -> num))
+    (log (num -> num))
+    (sin (num -> num))
+    (cos (num -> num))
+    (tan (num -> num))
+    (asin (num -> num))
+    (acos (num -> num))
+    (atan (num (&optional num) -> num))
+    (sqrt (num -> num))
+    (expt (num num -> num))
+    (make-rectangular (num num -> num))
+    (make-polar (num num -> num))
+    (real-part (num -> num))
+    (imag-part (num -> num))
+    (magnitude (num -> num))
+    (angle (num -> num))
+    (exact->inexact (num -> num))
+    (inexact->exact (num -> num))
+    (number->string (num (&optional num) -> str))
+    (string->number (str (&optional num) -> num))
+    (char=? (char char -> bool))
+    (char<? (char char -> bool))
+    (char>? (char char -> bool))
+    (char<=? (char char -> bool))
+    (char>=? (char char -> bool))
+    (char-ci=? (char char -> bool))
+    (char-ci<? (char char -> bool))
+    (char-ci>? (char char -> bool))
+    (char-ci<=? (char char -> bool))
+    (char-ci>=? (char char -> bool))
+    (char-alphabetic? (char -> bool))
+    (char-numeric? (char -> bool))
+    (char-whitespace? (char -> bool))
+    (char-upper-case? (char -> bool))
+    (char-lower-case? (char -> bool))
+    (char->integer (char -> num))
+    (integer->char (num -> char))
+    (char-upcase (char -> char))
+    (char-downcase (char -> char))
+    (make-string (num (&optional char) -> str))
+    (string ((&list char) -> str))
+    (string-length (str -> num))
+    (string-ref (str num -> char))
+    (string-set! (str num char -> void))
+    (string=? (str str -> bool))
+    (string<? (str str -> bool))
+    (string>? (str str -> bool))
+    (string<=? (str str -> bool))
+    (string>=? (str str -> bool))
+    (string-ci=? (str str -> bool))
+    (string-ci<? (str str -> bool))
+    (string-ci>? (str str -> bool))
+    (string-ci<=? (str str -> bool))
+    (string-ci>=? (str str -> bool))
+    (substring (str num num -> str))
+    (string-append ((&list str) -> str))
+    (string->list (str -> (list char)) (ic))
+    (list->string ((list char) -> str))
+    (string-copy (str -> str))
+    (string-fill! (str char -> void))
+    (make-vector (num a -> (vec a)) (i))
+    (vector ((&list a) -> (vec a)) (i))
+    (vector-length ((vec a) -> num))
+    (vector-ref ((vec a) num -> a))
+    (vector-set! ((vec a) num a -> void))
+    (vector->list ((vec a) -> (list a)) (ic))
+    (list->vector ((list a) -> (vec a)) (i))
+    (vector-fill! ((vec a) a -> void))
+    (apply (((&list a) -> b) (list a) -> b) (i) (d))
+    (map ((a -> b) (list a) -> (list b)) (i) (d))
+    (for-each ((a -> b) (list a) -> void) (i) (d))
+    (force ((promise a) -> a) (i))
+    (call-with-current-continuation
+      (((a -> b) -> a) -> a)
+      (i))
+    (call-with-input-file
+      (str (iport -> a) -> a)
+      (i))
+    (call-with-output-file
+      (str (oport -> a) -> a)
+      (i))
+    (input-port? (a -> bool))
+    (output-port? (a -> bool))
+    (current-input-port (-> iport))
+    (current-output-port (-> oport))
+    (with-input-from-file (str (-> a) -> a) (i))
+    (with-output-to-file (str (-> a) -> a) (i))
+    (open-input-file (str -> iport))
+    (open-output-file (str -> oport))
+    (close-input-port (iport -> void))
+    (close-output-port (oport -> void))
+    (read ((&optional iport)
+           ->
+           (+ eof
+              num
+              nil
+              false
+              true
+              char
+              sym
+              str
+              (box (mu sexp
+                       (+ num
+                          nil
+                          false
+                          true
+                          char
+                          sym
+                          str
+                          (vec sexp)
+                          (cons sexp sexp)
+                          (box sexp))))
+              (cons sexp sexp)
+              (vec sexp)))
+          (i))
+    (read-char
+      ((&optional iport) -> (+ char eof))
+      (i))
+    (peek-char
+      ((&optional iport) -> (+ char eof))
+      (i))
+    (char-ready? ((&optional iport) -> bool) (i))
+    (write (a (&optional oport) -> void) (i))
+    (display (a (&optional oport) -> void) (i))
+    (newline ((&optional oport) -> void) (i))
+    (write-char (char (&optional oport) -> void) (i))
+    (load (str -> void))
+    (transcript-on (str -> void))
+    (transcript-off (-> void))
+    (symbol-append ((&rest a) -> sym))
+    (box (a -> (box a)) (i))
+    (unbox ((box a) -> a) (s boxx))
+    (set-box! ((box a) a -> void))
+    (void (-> void))
+    (make-module (a -> (module a)))
+    (raise ((&rest a) -> b))
+    (match:error (a (&rest b) -> c))
+    (should-never-reach (a -> b))
+    (make-cvector (num a -> (cvec a)))
+    (cvector ((&list a) -> (cvec a)))
+    (cvector-length ((cvec a) -> num))
+    (cvector-ref ((cvec a) num -> a))
+    (cvector->list ((cvec a) -> (list a)) (ic))
+    (list->cvector ((list a) -> (cvec a)))
+    (,qcons (a b -> (cons a b)) (ic) (n))
+    (,qvector ((&list a) -> (vec a)) (i) (n))
+    (,qbox (a -> (box a)) (i) (n))
+    (,qlist ((&list a) -> (list a)) (ic) (n))
+    (number? ((+ num x) -> bool) (p (num)))
+    (null? ((+ nil x) -> bool) (p (nil)))
+    (char? ((+ char x) -> bool) (p (char)))
+    (symbol? ((+ sym x) -> bool) (p (sym)))
+    (string? ((+ str x) -> bool) (p (str)))
+    (vector? ((+ (vec a) x) -> bool) (p (vec a)))
+    (cvector? ((+ (cvec a) x) -> bool) (p (cvec a)))
+    (box? ((+ (box a) x) -> bool) (p (box a)))
+    (pair? ((+ (cons a b) x) -> bool) (p (cons a b)))
+    (procedure?
+      ((+ ((&rest a) -> b) x) -> bool)
+      (p (?-> a b)))
+    (eof-object? ((+ eof x) -> bool) (p (eof)))
+    (input-port? ((+ iport x) -> bool) (p (iport)))
+    (output-port? ((+ oport x) -> bool) (p (oport)))
+    (true-object? ((+ true x) -> bool) (p (true)))
+    (false-object? ((+ false x) -> bool) (p (false)))
+    (module?
+      ((+ (module a) x) -> bool)
+      (p (module a)))
+    (boolean? ((+ true false x) -> bool) (p #t))
+    (list? ((mu u (+ nil (cons y u) x)) -> bool)
+           (p #t))))
+(define initial-env '())
+(define init-env!
+  (lambda ()
+    (set! initial-env
+      (foldr init-prim empty-env initial-info))))
+(define init-prim
+  (lambda (l env)
+    (letrec ((build-selector
+               (match-lambda
+                 ('x (lambda (x) x))
+                 ('_ (lambda (x) (make-pany)))
+                 ('boxx
+                  (let ((c (lookup env 'box?)))
+                    (lambda (x) (make-pobj c (list x)))))
+                 ((x . y)
+                  (let ((c (lookup env 'pair?))
+                        (lx (build-selector x))
+                        (ly (build-selector y)))
+                    (lambda (x) (make-pobj c (list (lx x) (ly x)))))))))
+      (match l
+             ((name type . attr)
+              (let* ((pure (cond ((assq 'i attr) #f)
+                                 ((assq 'ic attr) 'cons)
+                                 (else #t)))
+                     (def (assq 'd attr))
+                     (check (assq 'c attr))
+                     (nocheck (assq 'n attr))
+                     (pred (match (assq 'p attr)
+                                  (#f #f)
+                                  ((_ #t) #t)
+                                  ((_ (tag . args))
+                                   (cons (lookup initial-type-env tag) args))))
+                     (sel (match (assq 's attr)
+                                 (#f #f)
+                                 ((_ s) (build-selector s))))
+                     (env1 (extend-env
+                             env
+                             name
+                             (make-name
+                               name
+                               (closeall (r+ initial-type-env type))
+                               #f
+                               0
+                               #f
+                               #f
+                               (cond (nocheck 'nocheck)
+                                     (check 'check)
+                                     (def 'imprecise)
+                                     (else #t))
+                               #f
+                               pure
+                               pred
+                               #f
+                               sel)))
+                     (env2 (extend-env
+                             env1
+                             (symbol-append 'check- name)
+                             (make-name
+                               (symbol-append 'check- name)
+                               (closeall (r++ initial-type-env type))
+                               #f
+                               0
+                               #f
+                               #f
+                               #t
+                               #f
+                               pure
+                               pred
+                               #f
+                               sel))))
+                env2))))))
+(define defprim
+  (lambda (name type mode)
+    (handle
+      (r+ initial-type-env type)
+      (match-lambda*
+        (('type . args) (apply syntax-err type args))
+        (x (apply raise x))))
+    (let* ((attr (match mode
+                        ('impure '((i)))
+                        ('pure '())
+                        ('pure-if-cons-is '((ic)))
+                        ('mutates-cons
+                         (set! cons-mutators (cons name cons-mutators))
+                         '())
+                        (x (use-error
+                             "invalid attribute ~a for st:defprim"
+                             x))))
+           (info `(,name ,type ,@attr)))
+      (unless
+        (equal? info (assq name initial-info))
+        (set! initial-info (cons info initial-info))
+        (set! initial-env (init-prim info initial-env))))))
+(init-types!)
+(init-env!)
+(define %not (lookup initial-env 'not))
+(define %list (lookup initial-env 'list))
+(define %cons (lookup initial-env 'cons))
+(define %should-never-reach
+  (lookup initial-env 'should-never-reach))
+(define %false-object?
+  (lookup initial-env 'false-object?))
+(define %eq? (lookup initial-env 'eq?))
+(define %eqv? (lookup initial-env 'eqv?))
+(define %equal? (lookup initial-env 'equal?))
+(define %null? (lookup initial-env 'null?))
+(define %vector? (lookup initial-env 'vector?))
+(define %cvector? (lookup initial-env 'cvector?))
+(define %list? (lookup initial-env 'list?))
+(define %boolean? (lookup initial-env 'boolean?))
+(define %procedure?
+  (lookup initial-env 'procedure?))
+(define n-unbound 0)
+(define bind-defs
+  (lambda (defs env0 tenv0 old-unbound timestamp)
+    (letrec ((cons-mutable #f)
+             (unbound '())
+             (use-var
+               (lambda (x env context mk-node)
+                 (match (lookup? env x)
+                        (#f
+                         (let* ((b (bind-var x)) (n (mk-node b)))
+                           (set-name-timestamp! b context)
+                           (set! unbound (cons n unbound))
+                           n))
+                        (b (when (and (name-primitive b)
+                                      (memq x cons-mutators))
+                                 (set! cons-mutable #t))
+                           (set-name-occ! b (+ 1 (name-occ b)))
+                           (mk-node b)))))
+             (bind-var
+               (lambda (x)
+                 (make-name
+                   x
+                   #f
+                   timestamp
+                   0
+                   #f
+                   #f
+                   #f
+                   #f
+                   #f
+                   #f
+                   #f
+                   #f)))
+             (bind (lambda (e env tenv context)
+                     (let ((bind-cur (lambda (x) (bind x env tenv context))))
+                       (match e
+                              (($ var x) (use-var x env context make-var))
+                              (($ prim x)
+                               (use-var x initial-env context make-var))
+                              (($ const c pred)
+                               (use-var
+                                 pred
+                                 initial-env
+                                 context
+                                 (lambda (p) (make-const c p))))
+                              (($ lam args e2)
+                               (let* ((b-args (map bind-var args))
+                                      (newenv (extend-env* env args b-args)))
+                                 (make-lam
+                                   b-args
+                                   (bind e2 newenv tenv context))))
+                              (($ vlam args rest e2)
+                               (let* ((b-args (map bind-var args))
+                                      (b-rest (bind-var rest))
+                                      (newenv
+                                        (extend-env*
+                                          env
+                                          (cons rest args)
+                                          (cons b-rest b-args))))
+                                 (make-vlam
+                                   b-args
+                                   b-rest
+                                   (bind e2 newenv tenv context))))
+                              (($ match e1 clauses)
+                               (make-match
+                                 (bind-cur e1)
+                                 (map (lambda (x)
+                                        (bind-mclause x env tenv context))
+                                      clauses)))
+                              (($ app e1 args)
+                               (make-app (bind-cur e1) (map bind-cur args)))
+                              (($ begin exps) (make-begin (map bind-cur exps)))
+                              (($ and exps) (make-and (map bind-cur exps)))
+                              (($ or exps) (make-or (map bind-cur exps)))
+                              (($ if test then els)
+                               (make-if
+                                 (bind-cur test)
+                                 (bind-cur then)
+                                 (bind-cur els)))
+                              (($ delay e2) (make-delay (bind-cur e2)))
+                              (($ set! x e2)
+                               (use-var
+                                 x
+                                 env
+                                 context
+                                 (lambda (b)
+                                   (when (name-struct b)
+                                         (syntax-err
+                                           (pexpr e)
+                                           "define-structure identifier ~a may not be assigned"
+                                           x))
+                                   (when (name-primitive b)
+                                         (syntax-err
+                                           (pexpr e)
+                                           "(set! ~a ...) requires (define ~a ...)"
+                                           x
+                                           x))
+                                   (when (and (not (name-mutated b))
+                                              (not (= (name-timestamp b)
+                                                      timestamp)))
+                                         (syntax-err
+                                           (pexpr e)
+                                           "(set! ~a ...) missing from compilation unit defining ~a"
+                                           x
+                                           x))
+                                   (set-name-mutated! b #t)
+                                   (make-set! b (bind-cur e2)))))
+                              (($ let args e2)
+                               (let* ((b-args
+                                        (map (match-lambda
+                                               (($ bind x e)
+                                                (make-bind
+                                                  (bind-var x)
+                                                  (bind-cur e))))
+                                             args))
+                                      (newenv
+                                        (extend-env*
+                                          env
+                                          (map bind-name args)
+                                          (map bind-name b-args))))
+                                 (make-let
+                                   b-args
+                                   (bind e2 newenv tenv context))))
+                              (($ let* args e2)
+                               (recur loop
+                                      ((args args) (b-args '()) (env env))
+                                      (match args
+                                             ((($ bind x e) . rest)
+                                              (let ((b (bind-var x)))
+                                                (loop rest
+                                                      (cons (make-bind
+                                                              b
+                                                              (bind e
+                                                                    env
+                                                                    tenv
+                                                                    context))
+                                                            b-args)
+                                                      (extend-env env x b))))
+                                             (()
+                                              (make-let*
+                                                (reverse b-args)
+                                                (bind e2 env tenv context))))))
+                              (($ letr args e2)
+                               (let* ((b-args
+                                        (map (match-lambda
+                                               (($ bind x e)
+                                                (make-bind (bind-var x) e)))
+                                             args))
+                                      (newenv
+                                        (extend-env*
+                                          env
+                                          (map bind-name args)
+                                          (map bind-name b-args)))
+                                      (b-args
+                                        (map (match-lambda
+                                               (($ bind b e)
+                                                (let* ((n (name-occ b))
+                                                       (e2 (bind e
+                                                                 newenv
+                                                                 tenv
+                                                                 context)))
+                                                  (set-name-occ! b n)
+                                                  (make-bind b e2))))
+                                             b-args)))
+                                 (make-letr
+                                   b-args
+                                   (bind e2 newenv tenv context))))
+                              (($ body defs exps)
+                               (match-let*
+                                 (((defs newenv newtenv)
+                                   (bind-defn defs env tenv #f)))
+                                 (make-body
+                                   defs
+                                   (map (lambda (x)
+                                          (bind x newenv newtenv context))
+                                        exps))))
+                              (($ record args)
+                               (make-record
+                                 (map (match-lambda
+                                        (($ bind x e)
+                                         (new-field! x)
+                                         (make-bind x (bind-cur e))))
+                                      args)))
+                              (($ field x e2)
+                               (new-field! x)
+                               (make-field x (bind-cur e2)))
+                              (($ cast ty e2)
+                               (match-let
+                                 (((t absv)
+                                   (handle
+                                     (r+collect
+                                       tenv
+                                       (match ty
+                                              (('rec bind ty2)
+                                               `(rec ,bind (,ty2 -> ,ty2)))
+                                              (_ `(,ty -> ,ty))))
+                                     (match-lambda*
+                                       (('type . args)
+                                        (apply syntax-err ty args))
+                                       (x (apply raise x))))))
+                                 (make-cast
+                                   (list ty t absv)
+                                   (bind-cur e2))))))))
+             (bind-mclause
+               (lambda (clause env tenv context)
+                 (match-let*
+                   ((($ mclause pattern body failsym) clause)
+                    (patenv empty-env)
+                    (bp (recur loop
+                               ((p pattern))
+                               (match p
+                                      (($ pvar x)
+                                       (when (bound? patenv x)
+                                             (syntax-err
+                                               (ppat pattern)
+                                               "pattern variable ~a repeated"
+                                               x))
+                                       (let ((b (bind-var x)))
+                                         (set! patenv (extend-env patenv x b))
+                                         (make-pvar b)))
+                                      (($ pobj c args)
+                                       (use-var
+                                         c
+                                         env
+                                         context
+                                         (lambda (b)
+                                           (cond ((boolean? (name-predicate b))
+                                                  (syntax-err
+                                                    (ppat pattern)
+                                                    "~a is not a predicate"
+                                                    c))
+                                                 ((and (not (eq? b %vector?))
+                                                       (not (eq? b %cvector?))
+                                                       (not (= (length
+                                                                 (cdr (name-predicate
+                                                                        b)))
+                                                               (length args))))
+                                                  (syntax-err
+                                                    (ppat pattern)
+                                                    "~a requires ~a sub-patterns"
+                                                    c
+                                                    (length
+                                                      (cdr (name-predicate
+                                                             b)))))
+                                                 (else
+                                                  (make-pobj
+                                                    b
+                                                    (map loop args)))))))
+                                      (($ pand pats)
+                                       (make-pand (map loop pats)))
+                                      (($ pnot pat) (make-pnot (loop pat)))
+                                      (($ ppred pred)
+                                       (use-var
+                                         pred
+                                         env
+                                         context
+                                         (lambda (b)
+                                           (unless
+                                             (name-predicate b)
+                                             (syntax-err
+                                               (ppat pattern)
+                                               "~a is not a predicate"
+                                               pred))
+                                           (make-ppred b))))
+                                      (($ pany) p)
+                                      (($ pelse) p)
+                                      (($ pconst c pred)
+                                       (use-var
+                                         pred
+                                         initial-env
+                                         context
+                                         (lambda (p) (make-pconst c p))))))))
+                   (if failsym
+                     (let ((b (bind-var failsym)))
+                       (when (bound? patenv failsym)
+                             (syntax-err
+                               (ppat pattern)
+                               "fail symbol ~a repeated"
+                               failsym))
+                       (set! patenv (extend-env patenv failsym b))
+                       (make-mclause
+                         bp
+                         (bind body (join-env env patenv) tenv context)
+                         b))
+                     (make-mclause
+                       bp
+                       (bind body (join-env env patenv) tenv context)
+                       #f)))))
+             (bind-defn
+               (lambda (defs env tenv glob)
+                 (let* ((newenv empty-env)
+                        (newtenv empty-env)
+                        (struct-def
+                          (lambda (x pure)
+                            (when (or (bound? newenv x)
+                                      (and glob (bound? initial-env x)))
+                                  (syntax-err
+                                    #f
+                                    "~a defined more than once"
+                                    x))
+                            (let ((b (bind-var x)))
+                              (set-name-primitive! b #t)
+                              (set-name-struct! b #t)
+                              (set-name-pure! b pure)
+                              (set! newenv (extend-env newenv x b))
+                              b)))
+                        (bind1 (match-lambda
+                                 ((and z ($ define x e))
+                                  (cond ((not x) z)
+                                        ((bound? newenv x)
+                                         (if glob
+                                           (make-define #f (make-set! x e))
+                                           (syntax-err
+                                             #f
+                                             "~a defined more than once"
+                                             x)))
+                                        (else
+                                         (let ((b (bind-var x)))
+                                           (set-name-gdef! b glob)
+                                           (set! newenv
+                                             (extend-env newenv x b))
+                                           (make-define b e)))))
+                                 ((and d
+                                       ($ defstruct
+                                          tag
+                                          args
+                                          make
+                                          pred
+                                          get
+                                          set
+                                          getn
+                                          setn
+                                          mutable))
+                                  (let* ((make (struct-def
+                                                 make
+                                                 (map not mutable)))
+                                         (pred (struct-def pred #t))
+                                         (bind-get
+                                           (lambda (name n)
+                                             (match name
+                                                    (($ some x)
+                                                     (let ((b (struct-def
+                                                                x
+                                                                #t)))
+                                                       (set-name-selector!
+                                                         b
+                                                         (lambda (x)
+                                                           (make-pobj
+                                                             pred
+                                                             (map-with-n
+                                                               (lambda (_ m)
+                                                                 (if (= m n)
+                                                                   x
+                                                                   (make-pany)))
+                                                               get))))
+                                                       (some b)))
+                                                    (none none))))
+                                         (bind-set
+                                           (match-lambda
+                                             (($ some x)
+                                              (some (struct-def x #t)))
+                                             (none none)))
+                                         (get (map-with-n bind-get get))
+                                         (getn (map-with-n bind-get getn))
+                                         (set (map bind-set set))
+                                         (setn (map bind-set setn))
+                                         (_ (when (bound? newtenv tag)
+                                                  (syntax-err
+                                                    (pdef d)
+                                                    "type constructor ~a defined more than once"
+                                                    tag)))
+                                         (tc (bind-tycon
+                                               tag
+                                               mutable
+                                               (bound? tenv tag)
+                                               (lambda args
+                                                 (apply syntax-err
+                                                        (cons (pdef d)
+                                                              args))))))
+                                    (set! newtenv (extend-env newtenv tag tc))
+                                    (set-name-predicate!
+                                      pred
+                                      `(,tc ,@(map (lambda (_) (gensym)) get)))
+                                    (make-defstruct
+                                      tc
+                                      args
+                                      make
+                                      pred
+                                      get
+                                      set
+                                      getn
+                                      setn
+                                      mutable)))
+                                 ((and d ($ datatype dt))
+                                  (make-datatype
+                                    (maplr (match-lambda
+                                             (((tag . args) . bindings)
+                                              (when (bound? newtenv tag)
+                                                    (syntax-err
+                                                      (pdef d)
+                                                      "type constructor ~a defined more than once"
+                                                      tag))
+                                              (let ((tc (bind-tycon
+                                                          tag
+                                                          (map (lambda (_) #f)
+                                                               args)
+                                                          (bound? tenv tag)
+                                                          (lambda args
+                                                            (apply syntax-err
+                                                                   (cons (pdef d)
+                                                                         args))))))
+                                                (set! newtenv
+                                                  (extend-env newtenv tag tc))
+                                                (cons (cons tc args)
+                                                      (maplr (match-lambda
+                                                               (($ variant
+                                                                   con
+                                                                   pred
+                                                                   arg-types)
+                                                                (let ((make (struct-def
+                                                                              con
+                                                                              #t))
+                                                                      (pred (struct-def
+                                                                              pred
+                                                                              #t)))
+                                                                  (set-name-predicate!
+                                                                    pred
+                                                                    (cons tc
+                                                                          args))
+                                                                  (set-name-variant!
+                                                                    pred
+                                                                    arg-types)
+                                                                  (make-variant
+                                                                    make
+                                                                    pred
+                                                                    arg-types))))
+                                                             bindings)))))
+                                           dt)))))
+                        (defs2 (maplr bind1 defs))
+                        (newenv2 (join-env env newenv))
+                        (newtenv2 (join-env tenv newtenv))
+                        (bind2 (match-lambda
+                                 ((and ($ define (? name? x) ($ var y)))
+                                  (=> fail)
+                                  (if (eq? (name-name x) y)
+                                    (if (bound? initial-env y)
+                                      (make-define
+                                        x
+                                        (make-var (lookup initial-env y)))
+                                      (begin
+                                        (printf
+                                          "Warning: (define ~a ~a) but ~a is not a primitive~%"
+                                          y
+                                          y
+                                          y)
+                                        (fail)))
+                                    (fail)))
+                                 ((and ($ define x e2) context)
+                                  (when (and glob
+                                             (name? x)
+                                             (bound?
+                                               initial-env
+                                               (name-name x)))
+                                        (printf
+                                          "Note: (define ~a ...) hides primitive ~a~%"
+                                          (name-name x)
+                                          (name-name x)))
+                                  (make-define
+                                    (or x
+                                        (let ((b (bind-var x)))
+                                          (set-name-gdef! b glob)
+                                          b))
+                                    (bind e2 newenv2 newtenv2 context)))
+                                 (d d))))
+                   (list (maplr bind2 defs2) newenv2 newtenv2))))
+             (bind-old
+               (lambda (e env)
+                 (match e
+                        (($ var x)
+                         (match (lookup? env (name-name x))
+                                (#f (set! unbound (cons e unbound)))
+                                (b (when (and (name-primitive b)
+                                              (memq x cons-mutators))
+                                         (set! cons-mutable #t))
+                                   (set-name-occ! b (+ 1 (name-occ b)))
+                                   (set-var-name! e b))))
+                        (($ set! x _)
+                         (match (lookup? env (name-name x))
+                                (#f (set! unbound (cons e unbound)))
+                                (b (when (name-struct b)
+                                         (syntax-err
+                                           (pexpr e)
+                                           "define-structure identifier ~a may not be assigned"
+                                           x))
+                                   (when (name-primitive b)
+                                         (syntax-err
+                                           (pexpr e)
+                                           "(set! ~a ...) requires (define ~a ...)"
+                                           x
+                                           x))
+                                   (when (and (not (name-mutated b))
+                                              (not (= (name-timestamp b)
+                                                      timestamp)))
+                                         (syntax-err
+                                           (pexpr e)
+                                           "(set! ~a ...) missing from compilation unit defining ~a"
+                                           x
+                                           x))
+                                   (set-name-mutated! b #t)
+                                   (set-name-occ! b (+ 1 (name-occ b)))
+                                   (set-set!-name! e b))))))))
+      (match-let
+        (((defs env tenv) (bind-defn defs env0 tenv0 #t)))
+        (for-each
+          (lambda (x) (bind-old x env))
+          old-unbound)
+        (set-cons-mutability! cons-mutable)
+        (set! n-unbound (length unbound))
+        (list defs env tenv unbound)))))
+(define rebind-var
+  (lambda (b)
+    (make-name
+      (name-name b)
+      (name-ty b)
+      (name-timestamp b)
+      (name-occ b)
+      (name-mutated b)
+      #f
+      #f
+      #f
+      #f
+      #f
+      #f
+      #f)))
+(define warn-unbound
+  (lambda (l)
+    (let* ((names '())
+           (node->name
+             (match-lambda
+               (($ var x) x)
+               (($ set! x _) x)
+               (($ pobj x _) x)
+               (($ ppred x) x)))
+           (warn (lambda (b)
+                   (unless
+                     (memq (name-name b) names)
+                     (set! names (cons (name-name b) names))
+                     (printf
+                       "Warning: ~a is unbound in "
+                       (name-name b))
+                     (print-context (pexpr (name-timestamp b)) 2)))))
+      (for-each (lambda (x) (warn (node->name x))) l))))
+(define name-unbound?
+  (lambda (x) (not (number? (name-timestamp x)))))
+(define improve-defs
+  (lambda (defs)
+    (map (match-lambda
+           (($ define x e2) (make-define x (improve e2)))
+           (x x))
+         defs)))
+(define improve
+  (match-lambda
+    (($ match e clauses) (improve-match e clauses))
+    (($ if tst thn els) (improve-if tst thn els))
+    ((? var? e) e)
+    ((? const? e) e)
+    (($ lam args e2) (make-lam args (improve e2)))
+    (($ vlam args rest e2)
+     (make-vlam args rest (improve e2)))
+    (($ app (and e1 ($ var x)) args)
+     (let ((args (map improve args)))
+       (if (and (eq? x %list) (< (length args) conslimit))
+         (foldr (lambda (a rest)
+                  (make-app (make-var %cons) (list a rest)))
+                (make-const '() %null?)
+                args)
+         (make-app e1 args))))
+    (($ app e1 args)
+     (make-app (improve e1) (map improve args)))
+    (($ begin exps) (make-begin (map improve exps)))
+    (($ and exps) (make-and (map improve exps)))
+    (($ or exps) (make-or (map improve exps)))
+    (($ delay e2) (make-delay (improve e2)))
+    (($ set! x e2) (make-set! x (improve e2)))
+    (($ let args e2)
+     (let ((args (map (match-lambda
+                        (($ bind x e) (make-bind x (improve e))))
+                      args)))
+       (make-let args (improve e2))))
+    (($ let* args e2)
+     (let ((args (map (match-lambda
+                        (($ bind x e) (make-bind x (improve e))))
+                      args)))
+       (make-let* args (improve e2))))
+    (($ letr args e2)
+     (let ((args (map (match-lambda
+                        (($ bind x e) (make-bind x (improve e))))
+                      args)))
+       (make-letr args (improve e2))))
+    (($ body defs exps)
+     (let ((defs (improve-defs defs)))
+       (make-body defs (map improve exps))))
+    (($ record args)
+     (make-record
+       (map (match-lambda
+              (($ bind x e) (make-bind x (improve e))))
+            args)))
+    (($ field x e2) (make-field x (improve e2)))
+    (($ cast ty e2) (make-cast ty (improve e2)))))
+(define improve-if
+  (lambda (tst thn els)
+    (let ((if->match
+            (lambda (x p mk-s thn els)
+              (let ((else-pat
+                      (match els
+                             (($ app ($ var q) _)
+                              (if (eq? q %should-never-reach)
+                                (make-pelse)
+                                (make-pany)))
+                             (_ (make-pany)))))
+                (make-match
+                  (make-var x)
+                  (list (make-mclause
+                          (mk-s (make-ppred p))
+                          (make-body '() (list thn))
+                          #f)
+                        (make-mclause
+                          (mk-s else-pat)
+                          (make-body '() (list els))
+                          #f)))))))
+      (match tst
+             (($ app ($ var v) (e))
+              (=> fail)
+              (if (eq? v %not) (improve-if e els thn) (fail)))
+             (($ app ($ var eq) (($ const #f _) val))
+              (=> fail)
+              (if (or (eq? eq %eq?)
+                      (eq? eq %eqv?)
+                      (eq? eq %equal?))
+                (improve-if val els thn)
+                (fail)))
+             (($ app ($ var eq) (val ($ const #f _)))
+              (=> fail)
+              (if (or (eq? eq %eq?)
+                      (eq? eq %eqv?)
+                      (eq? eq %equal?))
+                (improve-if val els thn)
+                (fail)))
+             (($ app ($ var v) (($ var x)))
+              (=> fail)
+              (if (and (name-predicate v) (not (name-mutated x)))
+                (improve (if->match x v (lambda (x) x) thn els))
+                (fail)))
+             (($ app ($ var v) (($ app ($ var s) (($ var x)))))
+              (=> fail)
+              (if (and (name-predicate v)
+                       (name-selector s)
+                       (not (name-mutated x)))
+                (improve
+                  (if->match x v (name-selector s) thn els))
+                (fail)))
+             (($ app ($ var v) (($ var x)))
+              (=> fail)
+              (if (and (name-selector v) (not (name-mutated x)))
+                (improve
+                  (if->match
+                    x
+                    %false-object?
+                    (name-selector v)
+                    els
+                    thn))
+                (fail)))
+             (($ var v)
+              (=> fail)
+              (if (not (name-mutated v))
+                (improve
+                  (if->match
+                    v
+                    %false-object?
+                    (lambda (x) x)
+                    els
+                    thn))
+                (fail)))
+             (_ (make-if
+                  (improve tst)
+                  (improve thn)
+                  (improve els)))))))
+(define improve-match
+  (lambda (e clauses)
+    (let ((clauses
+            (map (match-lambda
+                   (($ mclause p body fail)
+                    (make-mclause p (improve body) fail)))
+                 clauses)))
+      (match e
+             (($ var x)
+              (if (not (name-mutated x))
+                (let ((fix-clause
+                        (match-lambda
+                          ((and c ($ mclause p e fail))
+                           (if (not (uses-x? e x))
+                             c
+                             (let ((y (rebind-var x)))
+                               (make-mclause
+                                 (make-flat-pand (list p (make-pvar y)))
+                                 (sub e x y)
+                                 fail)))))))
+                  (make-match e (map fix-clause clauses)))
+                (make-match e clauses)))
+             (_ (make-match (improve e) clauses))))))
+(define uses-x?
+  (lambda (e x)
+    (recur loop
+           ((e e))
+           (match e
+                  (($ and exps) (ormap loop exps))
+                  (($ app fun args)
+                   (or (loop fun) (ormap loop args)))
+                  (($ begin exps) (ormap loop exps))
+                  (($ if e1 e2 e3)
+                   (or (loop e1) (loop e2) (loop e3)))
+                  (($ lam names body) (loop body))
+                  (($ let bindings body)
+                   (or (ormap (match-lambda (($ bind _ b) (loop b)))
+                              bindings)
+                       (loop body)))
+                  (($ let* bindings body)
+                   (or (ormap (match-lambda (($ bind _ b) (loop b)))
+                              bindings)
+                       (loop body)))
+                  (($ letr bindings body)
+                   (or (ormap (match-lambda (($ bind _ b) (loop b)))
+                              bindings)
+                       (loop body)))
+                  (($ or exps) (ormap loop exps))
+                  (($ delay e2) (loop e2))
+                  (($ set! name exp) (or (eq? x name) (loop exp)))
+                  (($ var name) (eq? x name))
+                  (($ vlam names name body) (loop body))
+                  (($ match exp clauses)
+                   (or (loop exp)
+                       (ormap (match-lambda
+                                (($ mclause p b _) (or (loop p) (loop b))))
+                              clauses)))
+                  (($ body defs exps)
+                   (or (ormap loop defs) (ormap loop exps)))
+                  (($ record bindings)
+                   (ormap (match-lambda (($ bind _ b) (loop b)))
+                          bindings))
+                  (($ field _ e) (loop e))
+                  (($ cast _ e) (loop e))
+                  (($ define _ e) (loop e))
+                  ((? defstruct?) #f)
+                  ((? datatype?) #f)
+                  (($ pand pats) (ormap loop pats))
+                  (($ pnot pat) (loop pat))
+                  (($ pobj c args) (ormap loop args))
+                  (($ ppred pred) (eq? x pred))
+                  (_ #f)))))
+(define sub
+  (lambda (e x to)
+    (let ((dos (lambda (y) (if (eq? x y) to y))))
+      (recur sub
+             ((e e))
+             (match e
+                    (($ define x e) (make-define x (sub e)))
+                    ((? defstruct?) e)
+                    ((? datatype?) e)
+                    (($ match e clauses)
+                     (let ((clauses
+                             (map (match-lambda
+                                    (($ mclause p e fail)
+                                     (make-mclause p (sub e) fail)))
+                                  clauses)))
+                       (make-match (sub e) clauses)))
+                    (($ if tst thn els)
+                     (make-if (sub tst) (sub thn) (sub els)))
+                    (($ var x) (make-var (dos x)))
+                    ((? const? e) e)
+                    (($ lam args e2) (make-lam args (sub e2)))
+                    (($ vlam args rest e2)
+                     (make-vlam args rest (sub e2)))
+                    (($ app e1 args)
+                     (make-app (sub e1) (map sub args)))
+                    (($ begin exps) (make-begin (map sub exps)))
+                    (($ and exps) (make-and (map sub exps)))
+                    (($ or exps) (make-or (map sub exps)))
+                    (($ delay e2) (make-delay (sub e2)))
+                    (($ set! x e2) (make-set! (dos x) (sub e2)))
+                    (($ let args e2)
+                     (let ((args (map (match-lambda
+                                        (($ bind x e) (make-bind x (sub e))))
+                                      args)))
+                       (make-let args (sub e2))))
+                    (($ let* args e2)
+                     (let ((args (map (match-lambda
+                                        (($ bind x e) (make-bind x (sub e))))
+                                      args)))
+                       (make-let* args (sub e2))))
+                    (($ letr args e2)
+                     (let ((args (map (match-lambda
+                                        (($ bind x e) (make-bind x (sub e))))
+                                      args)))
+                       (make-letr args (sub e2))))
+                    (($ body defs exps)
+                     (make-body (map sub defs) (map sub exps)))
+                    (($ record args)
+                     (make-record
+                       (map (match-lambda
+                              (($ bind x e) (make-bind x (sub e))))
+                            args)))
+                    (($ field x e) (make-field x (sub e)))
+                    (($ cast ty e) (make-cast ty (sub e))))))))
+(define improve-clauses
+  (lambda (clauses)
+    (recur loop
+           ((clauses clauses))
+           (match clauses
+                  (() '())
+                  ((_) clauses)
+                  (((and m1 ($ mclause p _ fail)) . rest)
+                   (cons m1
+                         (if fail
+                           (loop rest)
+                           (recur loop2
+                                  ((clauses (loop rest)))
+                                  (match clauses
+                                         (() '())
+                                         (((and m ($ mclause p2 body2 fail2))
+                                           .
+                                           r)
+                                          (match (improve-by-pattern p2 p)
+                                                 (('stop . p)
+                                                  (cons (make-mclause
+                                                          p
+                                                          body2
+                                                          fail2)
+                                                        r))
+                                                 (('redundant . p)
+                                                  (unless
+                                                    (null? r)
+                                                    (printf
+                                                      "Warning: redundant pattern ~a~%"
+                                                      (ppat p2)))
+                                                  (cons (make-mclause
+                                                          p
+                                                          body2
+                                                          fail2)
+                                                        r))
+                                                 (('continue . p)
+                                                  (cons (make-mclause
+                                                          p
+                                                          body2
+                                                          fail2)
+                                                        (loop2 r))))))))))))))
+(define improve-by-pattern
+  (lambda (p2 p1)
+    (call-with-current-continuation
+      (lambda (k)
+        (let* ((reject (lambda () (k (cons 'continue p2))))
+               (p1covers #t)
+               (p2covers #t)
+               (p3 (recur m
+                          ((p1 p1) (p2 p2))
+                          '(printf "(M ~a ~a)~%" (ppat p1) (ppat p2))
+                          (match (cons p1 p2)
+                                 ((($ pand (a . _)) . p2) (m a p2))
+                                 ((p1 $ pand (a . b))
+                                  (make-flat-pand (cons (m p1 a) b)))
+                                 ((($ pvar _) . _)
+                                  (unless
+                                    (or (pvar? p2) (pany? p2))
+                                    (set! p2covers #f))
+                                  p2)
+                                 ((($ pany) . _)
+                                  (unless
+                                    (or (pvar? p2) (pany? p2))
+                                    (set! p2covers #f))
+                                  p2)
+                                 ((($ pelse) . _)
+                                  '(unless
+                                     (or (pvar? p2) (pany? p2))
+                                     (set! p2covers #f))
+                                  p2)
+                                 ((_ $ pvar _)
+                                  (unless p1covers (reject))
+                                  (set! p1covers #f)
+                                  (make-flat-pand (list p2 (make-pnot p1))))
+                                 ((_ $ pany)
+                                  (unless p1covers (reject))
+                                  (set! p1covers #f)
+                                  (make-flat-pand (list p2 (make-pnot p1))))
+                                 ((_ $ pelse)
+                                  (unless p1covers (reject))
+                                  (set! p1covers #f)
+                                  (make-flat-pand (list p2 (make-pnot p1))))
+                                 ((($ pconst a _) $ pconst b _)
+                                  (unless (equal? a b) (reject))
+                                  p2)
+                                 ((($ pobj tag1 a) $ pobj tag2 b)
+                                  (unless (eq? tag1 tag2) (reject))
+                                  (make-pobj tag1 (map2 m a b)))
+                                 ((($ ppred tag1) $ ppred tag2)
+                                  (unless (eq? tag1 tag2) (reject))
+                                  p2)
+                                 ((($ ppred tag1) $ pobj tag2 _)
+                                  (unless (eq? tag1 tag2) (reject))
+                                  (set! p2covers #f)
+                                  p2)
+                                 ((($ ppred tag1) $ pconst c tag2)
+                                  (unless (eq? tag1 tag2) (reject))
+                                  (set! p2covers #f)
+                                  p2)
+                                 (_ (reject))))))
+          (cond (p1covers (cons 'redundant p2))
+                (p2covers (cons 'stop p3))
+                (else (cons 'continue p3))))))))
+(define improve-by-noisily
+  (lambda (p2 p1)
+    (let ((r (improve-by-pattern p2 p1)))
+      (printf
+        "~a by ~a returns ~a ~a~%"
+        (ppat p2)
+        (ppat p1)
+        (car r)
+        (ppat (cdr r))))))
+(define make-components
+  (lambda (d)
+    (let* ((structs
+             (filter-map
+               (match-lambda ((? define?) #f) (x x))
+               d))
+           (defs (filter-map
+                   (match-lambda ((? define? x) x) (_ #f))
+                   d))
+           (name-of (match-lambda (($ define x _) x)))
+           (ref-of
+             (match-lambda
+               (($ define _ e) (references e name-gdef))))
+           (comp (top-sort defs name-of ref-of)))
+      (when #f
+            (printf "Components:~%")
+            (pretty-print
+              (map (lambda (c)
+                     (map (match-lambda
+                            (($ define x _) (and x (name-name x))))
+                          c))
+                   comp)))
+      (append structs comp))))
+(define make-body-components
+  (lambda (d)
+    (let* ((structs
+             (filter-map
+               (match-lambda ((? define?) #f) (x x))
+               d))
+           (defs (filter-map
+                   (match-lambda ((? define? x) x) (_ #f))
+                   d))
+           (name-of (match-lambda (($ define x _) x)))
+           (bound (map name-of defs))
+           (ref-of
+             (match-lambda
+               (($ define _ e)
+                (references e (lambda (x) (memq x bound))))))
+           (comp (top-sort defs name-of ref-of)))
+      (when #f
+            (printf "Components:~%")
+            (pretty-print
+              (map (lambda (c)
+                     (map (match-lambda
+                            (($ define x _) (and x (name-name x))))
+                          c))
+                   comp)))
+      (append structs comp))))
+(define make-letrec-components
+  (lambda (bindings)
+    (let* ((name-of bind-name)
+           (bound (map name-of bindings))
+           (ref-of
+             (match-lambda
+               (($ bind _ e)
+                (references e (lambda (x) (memq x bound))))))
+           (comp (top-sort bindings name-of ref-of)))
+      (when #f
+            (printf "Letrec Components:~%")
+            (pretty-print
+              (map (lambda (c)
+                     (map (match-lambda (($ bind x _) (pname x))) c))
+                   comp)))
+      comp)))
+(define references
+  (lambda (e ref?)
+    (recur loop
+           ((e e))
+           (match e
+                  (($ define x e)
+                   (if (and x (name-mutated x))
+                     (union (set x) (loop e))
+                     (loop e)))
+                  ((? defstruct?) empty-set)
+                  ((? datatype?) empty-set)
+                  ((? const?) empty-set)
+                  (($ var x) (if (ref? x) (set x) empty-set))
+                  (($ lam _ e1) (loop e1))
+                  (($ vlam _ _ e1) (loop e1))
+                  (($ app e0 args)
+                   (foldr union2 (loop e0) (map loop args)))
+                  (($ let b e2)
+                   (let ((do-bind (match-lambda (($ bind _ e) (loop e)))))
+                     (foldr union2 (loop e2) (map do-bind b))))
+                  (($ let* b e2)
+                   (let ((do-bind (match-lambda (($ bind _ e) (loop e)))))
+                     (foldr union2 (loop e2) (map do-bind b))))
+                  (($ letr b e2)
+                   (let ((do-bind (match-lambda (($ bind _ e) (loop e)))))
+                     (foldr union2 (loop e2) (map do-bind b))))
+                  (($ body defs exps)
+                   (foldr union2
+                          empty-set
+                          (map loop (append defs exps))))
+                  (($ record b)
+                   (let ((do-bind (match-lambda (($ bind _ e) (loop e)))))
+                     (foldr union2 empty-set (map do-bind b))))
+                  (($ field _ e) (loop e))
+                  (($ cast _ e) (loop e))
+                  (($ and exps)
+                   (foldr union2 empty-set (map loop exps)))
+                  (($ or exps)
+                   (foldr union2 empty-set (map loop exps)))
+                  (($ begin exps)
+                   (foldr union2 empty-set (map loop exps)))
+                  (($ if test then els)
+                   (union (loop test) (loop then) (loop els)))
+                  (($ delay e) (loop e))
+                  (($ set! x body)
+                   (union (if (ref? x) (set x) empty-set)
+                          (loop body)))
+                  (($ match exp clauses)
+                   (foldr union2
+                          (loop exp)
+                          (map (match-lambda (($ mclause _ exp _) (loop exp)))
+                               clauses)))))))
+(define top-sort
+  (lambda (graph name-of references-of)
+    (let* ((adj assq)
+           (g (map (lambda (x)
+                     (list (name-of x)
+                           (box (references-of x))
+                           (box #f)
+                           x))
+                   graph))
+           (gt (let ((gt (map (match-lambda
+                                ((n _ _ name)
+                                 (list n (box empty-set) (box #f) n)))
+                              g)))
+                 (for-each
+                   (match-lambda
+                     ((n nay _ _)
+                      (for-each
+                        (lambda (v)
+                          (match (adj v gt)
+                                 (#f #f)
+                                 ((_ b _ _) (set-box! b (cons n (unbox b))))))
+                        (unbox nay))))
+                   g)
+                 gt))
+           (visit (lambda (vg)
+                    (letrec ((visit (lambda (g l)
+                                      (match g
+                                             (#f l)
+                                             ((n nay mark name)
+                                              (if (unbox mark)
+                                                l
+                                                (begin
+                                                  (set-box! mark #t)
+                                                  (cons name
+                                                        (foldr (lambda (v l)
+                                                                 (visit (adj v
+                                                                             vg)
+                                                                        l))
+                                                               l
+                                                               (unbox nay))))))))))
+                      visit)))
+           (visit-gt (visit gt))
+           (visit-g (visit g))
+           (post (foldr visit-gt '() gt))
+           (pre (foldl (lambda (gg l)
+                         (match (visit-g (adj gg g) '())
+                                (() l)
+                                (c (cons c l))))
+                       '()
+                       post)))
+      (reverse pre))))
+(define genlet #t)
+(define genmatch #t)
+(define letonce #f)
+(define type-defs
+  (lambda (d)
+    (for-each
+      (match-lambda
+        ((? defstruct? b) (type-structure b))
+        ((? datatype? b) (type-structure b))
+        (c (type-component c #t)))
+      (make-components d))
+    (close '())))
+(define type-structure
+  (match-lambda
+    (($ defstruct
+        x
+        _
+        make
+        pred
+        get
+        set
+        getn
+        setn
+        mutable)
+     (let* ((vars (map (lambda (_) (gensym)) get))
+            (make-get-type
+              (lambda (getter v)
+                (match getter
+                       (($ some b)
+                        (set-name-ty!
+                          b
+                          (closeall
+                            (r+ initial-type-env `((,x ,@vars) -> ,v)))))
+                       (_ #f))))
+            (make-set-type
+              (lambda (setter v)
+                (match setter
+                       (($ some b)
+                        (set-name-ty!
+                          b
+                          (closeall
+                            (r+ initial-type-env `((,x ,@vars) ,v -> void)))))
+                       (_ #f)))))
+       (set-name-ty!
+         make
+         (closeall
+           (r+ initial-type-env `(,@vars -> (,x ,@vars)))))
+       (set-name-ty!
+         pred
+         (closeall
+           (r+ initial-type-env
+               `((+ (,x ,@vars) y) -> bool))))
+       (for-each2 make-get-type get vars)
+       (for-each2 make-set-type set vars)
+       (for-each2 make-get-type getn vars)
+       (for-each2 make-set-type setn vars)))
+    (($ datatype dt)
+     (for-each
+       (match-lambda
+         ((type . variants)
+          (for-each
+            (match-lambda
+              (($ variant con pred arg-types)
+               (set-name-ty!
+                 con
+                 (closeall
+                   (r+ initial-type-env
+                       `(,@(cdr arg-types) -> ,type))))
+               (set-name-ty!
+                 pred
+                 (closeall
+                   (r+ initial-type-env
+                       `((+ ,(name-predicate pred) x) -> bool))))))
+            variants)))
+       dt))))
+(define type-component
+  (lambda (component top)
+    (when verbose
+          (let ((cnames
+                  (filter-map
+                    (match-lambda (($ define b _) (name-name b)))
+                    component)))
+            (unless
+              (null? cnames)
+              (printf "Typing ~a~%" cnames))))
+    (let* ((f (match-lambda (($ define b e) (make-bind b e))))
+           (bindings (map f component))
+           (names (map (match-lambda (($ define b _) (pname b)))
+                       component))
+           (f1 (match-lambda
+                 (($ define b _) (set-name-ty! b (tvar)))))
+           (f2 (match-lambda
+                 ((and d ($ define b e))
+                  (set-define-exp! d (w e names)))))
+           (f3 (match-lambda
+                 (($ define b e) (unify (name-ty b) (typeof e)))))
+           (f4 (match-lambda (($ define b _) (name-ty b))))
+           (f5 (lambda (d ts)
+                 (match d (($ define b _) (set-name-ty! b ts))))))
+      (push-level)
+      (for-each f1 component)
+      (for-each f2 component)
+      (for-each f3 component)
+      (for-each limit-expansive component)
+      (for-each
+        f5
+        component
+        (close (map f4 component)))
+      (pop-level))))
+(define w
+  (lambda (e component)
+    (match e
+           (($ const _ pred)
+            (make-type
+              (r+ initial-type-env (name-predicate pred))
+              e))
+           (($ var x)
+            (unless
+              (name-ty x)
+              (set-name-ty!
+                x
+                (if (name-mutated x)
+                  (monotvar)
+                  (let* ((_1 (push-level))
+                         (t (closeall (tvar)))
+                         (_2 (pop-level)))
+                    t))))
+            (if (ts? (name-ty x))
+              (match-let*
+                ((tynode (make-type #f #f))
+                 ((t absv) (instantiate (name-ty x) tynode)))
+                (set-type-ty! tynode t)
+                (set-type-exp!
+                  tynode
+                  (match (name-primitive x)
+                         ('imprecise
+                          (make-check (list absv #f #f #f component) e))
+                         ('check
+                          (make-check
+                            (list (cons top absv) #f #f #f component)
+                            e))
+                         ('nocheck e)
+                         (#t
+                          (make-check
+                            (list absv (mk-definite-prim t) #f #f component)
+                            e))
+                         (#f
+                          (make-check (list absv #f #f #t component) e))))
+                tynode)
+              e))
+           (($ lam x e1)
+            (for-each (lambda (b) (set-name-ty! b (tvar))) x)
+            (match-let*
+              ((body (w e1 component))
+               ((t absv)
+                (r+collect
+                  initial-type-env
+                  `(,@(map name-ty x) -> ,(typeof body)))))
+              (make-type
+                t
+                (make-check
+                  (list absv (mk-definite-lam t) #f #f component)
+                  (make-lam x body)))))
+           (($ vlam x rest e1)
+            (for-each (lambda (b) (set-name-ty! b (tvar))) x)
+            (match-let*
+              ((z (tvar))
+               (_ (set-name-ty!
+                    rest
+                    (r+ initial-type-env `(list ,z))))
+               (body (w e1 component))
+               ((t absv)
+                (r+collect
+                  initial-type-env
+                  `(,@(map name-ty x) (&list ,z) -> ,(typeof body)))))
+              (make-type
+                t
+                (make-check
+                  (list absv (mk-definite-lam t) #f #f component)
+                  (make-vlam x rest body)))))
+           (($ app e0 args)
+            (match-let*
+              ((t0 (w e0 component))
+               (targs (maplr (lambda (e) (w e component)) args))
+               (a* (map (lambda (_) (tvar)) args))
+               (b (tvar))
+               ((t absv)
+                (r-collect initial-type-env `(,@a* -> ,b)))
+               (definf (mk-definite-app t)))
+              (unify (typeof t0) t)
+              (for-each2 unify (map typeof targs) a*)
+              (if (syntactically-a-procedure? t0)
+                (make-type b (make-app t0 targs))
+                (make-type
+                  b
+                  (make-check
+                    (list absv definf #f #f component)
+                    (make-app t0 targs))))))
+           (($ let b e2)
+            (let* ((do-bind
+                     (match-lambda
+                       (($ bind b e)
+                        (if genlet
+                          (let* ((_ (push-level))
+                                 (e (w e (list (pname b))))
+                                 (bind (make-bind b e)))
+                            (limit-expansive bind)
+                            (set-name-ty! b (car (close (list (typeof e)))))
+                            (pop-level)
+                            bind)
+                          (let ((e (w e component)))
+                            (set-name-ty! b (typeof e))
+                            (make-bind b e))))))
+                   (tb (map do-bind b))
+                   (body (w e2 component)))
+              (make-let tb body)))
+           (($ let* b e2)
+            (let* ((do-bind
+                     (match-lambda
+                       (($ bind b e)
+                        (if genlet
+                          (let* ((_ (push-level))
+                                 (e (w e (list (pname b))))
+                                 (bind (make-bind b e)))
+                            (limit-expansive bind)
+                            (set-name-ty! b (car (close (list (typeof e)))))
+                            (pop-level)
+                            bind)
+                          (let ((e (w e component)))
+                            (set-name-ty! b (typeof e))
+                            (make-bind b e))))))
+                   (tb (maplr do-bind b))
+                   (body (w e2 component)))
+              (make-let* tb body)))
+           (($ letr b e2)
+            (let* ((do-comp
+                     (lambda (b)
+                       (if genlet
+                         (let* ((f1 (match-lambda
+                                      (($ bind b _) (set-name-ty! b (tvar)))))
+                                (names (map (match-lambda
+                                              (($ bind b _) (pname b)))
+                                            b))
+                                (f2 (match-lambda
+                                      (($ bind b e)
+                                       (make-bind b (w e names)))))
+                                (f3 (match-lambda
+                                      (($ bind b e)
+                                       (unify (name-ty b) (typeof e))
+                                       (name-ty b))))
+                                (f4 (lambda (bind ts)
+                                      (match bind
+                                             (($ bind b _)
+                                              (set-name-ty! b ts)))))
+                                (_1 (push-level))
+                                (_2 (for-each f1 b))
+                                (tb (maplr f2 b))
+                                (_3 (for-each limit-expansive tb))
+                                (ts-list (close (maplr f3 tb))))
+                           (pop-level)
+                           (for-each2 f4 tb ts-list)
+                           tb)
+                         (let* ((f1 (match-lambda
+                                      (($ bind b _) (set-name-ty! b (tvar)))))
+                                (f2 (match-lambda
+                                      (($ bind b e)
+                                       (make-bind b (w e component)))))
+                                (f3 (match-lambda
+                                      (($ bind b e)
+                                       (unify (name-ty b) (typeof e)))))
+                                (_1 (for-each f1 b))
+                                (tb (maplr f2 b)))
+                           (for-each f3 tb)
+                           tb))))
+                   (comps (make-letrec-components b))
+                   (tb (foldr append '() (maplr do-comp comps))))
+              (make-letr tb (w e2 component))))
+           (($ body defs exps)
+            (for-each
+              (match-lambda
+                ((? defstruct? b) (type-structure b))
+                ((? datatype? b) (type-structure b))
+                (c (type-component c #f)))
+              (make-body-components defs))
+            (let ((texps (maplr (lambda (x) (w x component)) exps)))
+              (make-body defs texps)))
+           (($ and exps)
+            (let* ((texps (maplr (lambda (x) (w x component)) exps))
+                   (t (match texps
+                             (() (r+ initial-type-env 'true))
+                             ((e) (typeof e))
+                             (_ (let ((a (r+ initial-type-env 'false)))
+                                  (unify (typeof (rac texps)) a)
+                                  a)))))
+              (make-type t (make-and texps))))
+           (($ or exps)
+            (let* ((texps (maplr (lambda (x) (w x component)) exps))
+                   (t (match texps
+                             (() (r+ initial-type-env 'false))
+                             ((e) (typeof e))
+                             (_ (let* ((t-last (typeof (rac texps)))
+                                       (but-last (rdc texps))
+                                       (a (tvar)))
+                                  (for-each
+                                    (lambda (e)
+                                      (unify (typeof e)
+                                             (r+ initial-type-env
+                                                 `(+ (not false) ,a))))
+                                    but-last)
+                                  (unify t-last
+                                         (r+ initial-type-env
+                                             `(+ (not false) ,a)))
+                                  t-last)))))
+              (make-type t (make-or texps))))
+           (($ begin exps)
+            (let ((texps (maplr (lambda (x) (w x component)) exps)))
+              (make-begin texps)))
+           (($ if test then els)
+            (let ((ttest (w test component))
+                  (tthen (w then component))
+                  (tels (w els component))
+                  (a (tvar)))
+              (unify (typeof tthen) a)
+              (unify (typeof tels) a)
+              (make-type a (make-if ttest tthen tels))))
+           (($ delay e2)
+            (let ((texp (w e2 component)))
+              (make-type
+                (r+ initial-type-env `(promise ,(typeof texp)))
+                (make-delay texp))))
+           (($ set! x body)
+            (unless (name-ty x) (set-name-ty! x (monotvar)))
+            (let* ((body (w body component))
+                   (t (if (ts? (name-ty x))
+                        (car (instantiate (name-ty x) #f))
+                        (name-ty x))))
+              (unify t (typeof body))
+              (make-type
+                (r+ initial-type-env 'void)
+                (make-set! x body))))
+           (($ record bind)
+            (let* ((tbind (map (match-lambda
+                                 (($ bind name exp)
+                                  (make-bind name (w exp component))))
+                               bind))
+                   (t (r+ initial-type-env
+                          `(record
+                             ,@(map (match-lambda
+                                      (($ bind name exp)
+                                       (list name (typeof exp))))
+                                    tbind)))))
+              (make-type t (make-record tbind))))
+           (($ field name exp)
+            (match-let*
+              ((texp (w exp component))
+               (a (tvar))
+               ((t absv)
+                (r-collect initial-type-env `(record (,name ,a)))))
+              (unify (typeof texp) t)
+              (make-type
+                a
+                (make-check
+                  (list absv #f #f #f component)
+                  (make-field name texp)))))
+           (($ cast (ty t absv) exp)
+            (let ((texp (w exp component)) (a (tvar)))
+              (unify (r+ initial-type-env `(,(typeof texp) -> ,a))
+                     t)
+              (make-type
+                a
+                (make-check
+                  (list absv #f #f #f component)
+                  (make-cast (list ty t absv) texp)))))
+           (($ match exp clauses)
+            (for-each
+              (match-lambda
+                (($ mclause p _ (? name? fail))
+                 (set-name-ty!
+                   fail
+                   (r+ initial-type-env '(a ?-> b))))
+                (_ #f))
+              clauses)
+            (match-let*
+              ((iclauses
+                 (improve-clauses
+                   (append
+                     clauses
+                     (list (make-mclause (make-pelse) #f #f)))))
+               ((tmatch absv precise)
+                (w-match (rdc iclauses) (rac iclauses)))
+               (texp (w exp component))
+               (_ (unify (typeof texp) tmatch))
+               (tclauses
+                 (maplr (match-lambda
+                          (($ mclause p e fail)
+                           (make-mclause p (w e component) fail)))
+                        clauses))
+               (a (tvar)))
+              (for-each
+                (match-lambda
+                  (($ mclause _ e _) (unify (typeof e) a)))
+                tclauses)
+              (make-type
+                a
+                (make-check
+                  (list absv #f (not precise) #f component)
+                  (make-match texp tclauses))))))))
+(define w-match
+  (lambda (clauses last)
+    (letrec ((bindings '())
+             (encode
+               (match-lambda
+                 (($ pand pats) (encode* pats))
+                 (x (encode* (list x)))))
+             (encode*
+               (lambda (pats)
+                 (let* ((concrete?
+                          (lambda (p)
+                            (or (pconst? p) (pobj? p) (ppred? p) (pelse? p))))
+                        (var? (lambda (p) (or (pvar? p) (pany? p))))
+                        (not-var?
+                          (lambda (p)
+                            (and (not (pvar? p)) (not (pany? p)))))
+                        (t (match (filter concrete? pats)
+                                  ((p)
+                                   (r+ initial-type-env
+                                       (match (template p)
+                                              ((x) x)
+                                              (x `(+ ,@x)))))
+                                  (()
+                                   (r+ initial-type-env
+                                       `(+ ,@(apply append
+                                                    (map template
+                                                         (filter
+                                                           not-var?
+                                                           pats)))
+                                           ,@(if (null? (filter var? pats))
+                                               '()
+                                               (list (out1tvar)))))))))
+                   (for-each
+                     (match-lambda
+                       (($ pvar b)
+                        (set! bindings (cons b bindings))
+                        (set-name-ty! b (pat-var-bind t))))
+                     (filter pvar? pats))
+                   t)))
+             (template
+               (match-lambda
+                 ((? pelse?) '())
+                 (($ pconst _ pred) (list (name-predicate pred)))
+                 ((and pat ($ pobj c args))
+                  (list (cond ((or (eq? %vector? c) (eq? %cvector? c))
+                               (cons (if (eq? %vector? c) 'vec 'cvec)
+                                     (match (maplr encode args)
+                                            (() (list (out1tvar)))
+                                            ((first . rest)
+                                             (list (foldr (lambda (x y)
+                                                            (unify x y)
+                                                            y)
+                                                          first
+                                                          rest))))))
+                              (else
+                               (cons (car (name-predicate c))
+                                     (maplr encode args))))))
+                 (($ ppred pred)
+                  (cond ((eq? pred %boolean?) (list 'true 'false))
+                        ((eq? pred %list?) (list `(list ,(out1tvar))))
+                        (else
+                         (list (cons (car (name-predicate pred))
+                                     (maplr (lambda (_) (out1tvar))
+                                            (cdr (name-predicate pred))))))))
+                 (($ pnot (? pconst?)) '())
+                 (($ pnot ($ ppred pred))
+                  (cond ((eq? pred %boolean?) '((not true) (not false)))
+                        ((eq? pred %procedure?) '((not ?->)))
+                        ((eq? pred %list?) '())
+                        (else `((not ,(car (name-predicate pred)))))))
+                 (($ pnot ($ pobj pred pats))
+                  (let ((m (foldr + 0 (map non-triv pats))))
+                    (case m
+                      ((0) `((not ,(car (name-predicate pred)))))
+                      ((1)
+                       `((,(car (name-predicate pred))
+                          ,@(map (match-lambda
+                                   (($ pobj pred _)
+                                    `(+ (not ,(car (name-predicate pred)))
+                                        ,(out1tvar)))
+                                   (($ ppred pred)
+                                    `(+ (not ,(car (name-predicate pred)))
+                                        ,(out1tvar)))
+                                   (_ (out1tvar)))
+                                 pats))))
+                      (else '()))))))
+             (non-triv
+               (match-lambda
+                 ((? pvar?) 0)
+                 ((? pany?) 0)
+                 ((? pelse?) 0)
+                 ((? pconst?) 2)
+                 (($ pobj _ pats) (foldr + 1 (map non-triv pats)))
+                 (_ 1)))
+             (precise
+               (match-lambda
+                 ((? pconst?) #f)
+                 (($ pand pats) (andmap precise pats))
+                 (($ pnot pat) (precise pat))
+                 (($ pobj pred pats)
+                  (let ((m (foldr + 0 (map non-triv pats))))
+                    (case m
+                      ((0) #t)
+                      ((1) (andmap precise pats))
+                      (else #f))))
+                 (($ ppred pred) (not (eq? pred %list?)))
+                 (_ #t))))
+      (push-level)
+      (match-let*
+        ((precise-match
+           (and (andmap
+                  (match-lambda (($ mclause _ _ fail) (not fail)))
+                  clauses)
+                (match last (($ mclause p _ _) (precise p)))))
+         (types (maplr (match-lambda (($ mclause p _ _) (encode p)))
+                       clauses))
+         ((t absv)
+          (r-match
+            (foldr (lambda (x y) (unify x y) y) (tvar) types))))
+        (unify (out1tvar) t)
+        (for-each limit-name bindings)
+        (for-each2
+          set-name-ty!
+          bindings
+          (close (map name-ty bindings)))
+        (pop-level)
+        '(pretty-print
+           `(match-input
+              ,@(map (match-lambda (($ mclause p _ _) (ppat p)))
+                     clauses)))
+        '(pretty-print
+           `(match-type
+              ,(ptype t)
+              ,@(map (lambda (b) (list (pname b) (ptype (name-ty b))))
+                     bindings)))
+        (list t absv precise-match)))))
+(define syntactically-a-procedure?
+  (match-lambda
+    (($ type _ e) (syntactically-a-procedure? e))
+    (($ check _ e) (syntactically-a-procedure? e))
+    (($ var x) (name-primitive x))
+    ((? lam?) #t)
+    ((? vlam?) #t)
+    (($ let _ body)
+     (syntactically-a-procedure? body))
+    (($ let* _ body)
+     (syntactically-a-procedure? body))
+    (($ letr _ body)
+     (syntactically-a-procedure? body))
+    (($ if _ e2 e3)
+     (and (syntactically-a-procedure? e2)
+          (syntactically-a-procedure? e3)))
+    (($ begin exps)
+     (syntactically-a-procedure? (rac exps)))
+    (($ body _ exps)
+     (syntactically-a-procedure? (rac exps)))
+    (_ #f)))
+(define typeof
+  (match-lambda
+    (($ type t _) t)
+    (($ check _ e) (typeof e))
+    (($ let _ body) (typeof body))
+    (($ let* _ body) (typeof body))
+    (($ letr _ body) (typeof body))
+    (($ body _ exps) (typeof (rac exps)))
+    (($ begin exps) (typeof (rac exps)))
+    (($ var x) (name-ty x))))
+(define limit-name
+  (lambda (n)
+    (when (name-mutated n)
+          (unify (name-ty n) (out1tvar)))))
+(define limit-expansive
+  (letrec ((limit! (lambda (t) (unify t (out1tvar))))
+           (expansive-pattern?
+             (match-lambda
+               ((? pconst?) #f)
+               (($ pvar x) (name-mutated x))
+               (($ pobj _ pats) (ormap expansive-pattern? pats))
+               ((? pany?) #f)
+               ((? pelse?) #f)
+               (($ pand pats) (ormap expansive-pattern? pats))
+               (($ ppred x) (name-mutated x))
+               (($ pnot pat) (expansive-pattern? pat))))
+           (limit-expr
+             (match-lambda
+               (($ bind b e)
+                (if (name-mutated b)
+                  (limit! (typeof e))
+                  (limit-expr e)))
+               ((? defstruct?) #f)
+               ((? datatype?) #f)
+               (($ define x e)
+                (if (and x (name-mutated x))
+                  (limit! (typeof e))
+                  (limit-expr e)))
+               (($ type
+                   t
+                   ($ app ($ type _ ($ check _ ($ var x))) exps))
+                (cond ((list? (name-pure x))
+                       (if (= (length (name-pure x)) (length exps))
+                         (for-each2
+                           (lambda (pure e)
+                             (if pure (limit-expr e) (limit! (typeof e))))
+                           (name-pure x)
+                           exps)
+                         (limit! t)))
+                      ((or (eq? #t (name-pure x))
+                           (and (eq? 'cons (name-pure x))
+                                (not cons-is-mutable)))
+                       (for-each limit-expr exps))
+                      (else (limit! t))))
+               (($ type t ($ app _ _)) (limit! t))
+               (($ type t ($ check _ ($ app _ _))) (limit! t))
+               (($ delay _) #f)
+               (($ type t ($ set! _ _)) (limit! t))
+               (($ var _) #f)
+               ((? const?) #f)
+               (($ lam _ _) #f)
+               (($ vlam _ _ _) #f)
+               (($ let bind body)
+                (limit-expr body)
+                (for-each limit-expr bind))
+               (($ let* bind body)
+                (limit-expr body)
+                (for-each limit-expr bind))
+               (($ letr bind body)
+                (limit-expr body)
+                (for-each limit-expr bind))
+               (($ body defs exps)
+                (for-each limit-expr defs)
+                (for-each limit-expr exps))
+               (($ and exps) (for-each limit-expr exps))
+               (($ or exps) (for-each limit-expr exps))
+               (($ begin exps) (for-each limit-expr exps))
+               (($ if e1 e2 e3)
+                (limit-expr e1)
+                (limit-expr e2)
+                (limit-expr e3))
+               (($ record bind)
+                (for-each
+                  (match-lambda (($ bind _ e) (limit-expr e)))
+                  bind))
+               (($ field _ exp) (limit-expr exp))
+               (($ cast _ exp) (limit-expr exp))
+               (($ match exp clauses)
+                (limit-expr exp)
+                (for-each
+                  (match-lambda
+                    (($ mclause pat body fail)
+                     (if (or (and fail (name-mutated fail))
+                             (expansive-pattern? pat))
+                       (limit! (typeof body))
+                       (limit-expr body))))
+                  clauses))
+               (($ type _ e1) (limit-expr e1))
+               (($ check _ e1) (limit-expr e1)))))
+    limit-expr))
+(define unparse
+  (lambda (e check-action)
+    (letrec ((pbind (match-lambda
+                      (($ bind n e) (list (pname n) (pexpr e)))))
+             (pexpr (match-lambda
+                      ((and x ($ type _ (? check?)))
+                       (check-action x pexpr))
+                      (($ type _ exp) (pexpr exp))
+                      (($ shape t exp) (pexpr exp))
+                      (($ define x e)
+                       (if (or (not x) (and (name? x) (not (name-name x))))
+                         (pexpr e)
+                         `(define ,(pname x) ,(pexpr e))))
+                      (($ defstruct _ args _ _ _ _ _ _ _)
+                       `(check-define-const-structure ,args))
+                      (($ datatype d)
+                       `(datatype
+                          ,@(map (match-lambda
+                                   (((tag . args) . bindings)
+                                    (cons (cons (ptag tag) args)
+                                          (map (match-lambda
+                                                 (($ variant _ _ types) types))
+                                               bindings))))
+                                 d)))
+                      (($ and exps) `(and ,@(maplr pexpr exps)))
+                      (($ or exps) `(or ,@(maplr pexpr exps)))
+                      (($ begin exps) `(begin ,@(maplr pexpr exps)))
+                      (($ var x) (pname x))
+                      (($ prim x) (pname x))
+                      (($ const x _) (pconst x))
+                      (($ lam x e1)
+                       `(lambda ,(maplr pname x) ,@(pexpr e1)))
+                      (($ vlam x rest e1)
+                       `(lambda ,(append (maplr pname x) (pname rest))
+                          ,@(pexpr e1)))
+                      (($ match e1 clauses)
+                       (let* ((pclause
+                                (match-lambda
+                                  (($ mclause p #f #f)
+                                   `(,(ppat p) <last clause>))
+                                  (($ mclause p exp fail)
+                                   (if fail
+                                     `(,(ppat p)
+                                       (=> ,(pname fail))
+                                       ,@(pexpr exp))
+                                     `(,(ppat p) ,@(pexpr exp))))))
+                              (p1 (pexpr e1)))
+                         `(match ,p1 ,@(maplr pclause clauses))))
+                      (($ app e1 args)
+                       (let* ((p1 (pexpr e1))
+                              (pargs (maplr pexpr args))
+                              (unkwote
+                                (match-lambda
+                                  (('quote x) x)
+                                  ((? boolean? x) x)
+                                  ((? number? x) x)
+                                  ((? char? x) x)
+                                  ((? string? x) x)
+                                  ((? null? x) x)
+                                  ((? box? x) x)
+                                  ((? vector? x) x))))
+                         (cond ((eq? p1 qlist) `',(maplr unkwote pargs))
+                               ((eq? p1 qcons)
+                                (let ((unq (maplr unkwote pargs)))
+                                  `',(cons (car unq) (cadr unq))))
+                               ((eq? p1 qbox) (box (unkwote (car pargs))))
+                               ((eq? p1 qvector)
+                                (list->vector (maplr unkwote pargs)))
+                               (else (cons p1 pargs)))))
+                      (($ let b e2)
+                       (let ((pb (maplr pbind b)))
+                         `(let ,pb ,@(pexpr e2))))
+                      (($ let* b e2)
+                       (let ((pb (maplr pbind b)))
+                         `(let* ,pb ,@(pexpr e2))))
+                      (($ letr b e2)
+                       (let ((pb (maplr pbind b)))
+                         `(letrec ,pb ,@(pexpr e2))))
+                      (($ body defs exps)
+                       (let ((pdefs (maplr pexpr defs)))
+                         (append pdefs (maplr pexpr exps))))
+                      (($ if e1 e2 e3)
+                       (let* ((p1 (pexpr e1)) (p2 (pexpr e2)) (p3 (pexpr e3)))
+                         `(if ,p1 ,p2 ,p3)))
+                      (($ record bindings)
+                       `(record ,@(maplr pbind bindings)))
+                      (($ field x e2) `(field ,x ,(pexpr e2)))
+                      (($ cast (ty . _) e2) `(: ,ty ,(pexpr e2)))
+                      (($ delay e) `(delay ,(pexpr e)))
+                      (($ set! x e) `(set! ,(pname x) ,(pexpr e))))))
+      (pexpr e))))
+(define pexpr
+  (lambda (ex)
+    (unparse
+      ex
+      (lambda (e pexpr)
+        (match e
+               (($ type _ ($ check _ exp)) (pexpr exp)))))))
+(define pdef pexpr)
+(define ppat
+  (match-lambda
+    (($ pconst x _) (pconst x))
+    (($ pvar x) (pname x))
+    (($ pany) '_)
+    (($ pelse) 'else)
+    (($ pnot pat) `(not ,(ppat pat)))
+    (($ pand pats) `(and ,@(maplr ppat pats)))
+    (($ ppred pred)
+     (match (pname pred)
+            ('false-object? #f)
+            ('true-object? #t)
+            ('null? '())
+            (x `(? ,x))))
+    (($ pobj tag args)
+     (match (cons (pname tag) args)
+            (('box? x) (box (ppat x)))
+            (('pair? x y) (cons (ppat x) (ppat y)))
+            (('vector? . x) (list->vector (maplr ppat x)))
+            ((tg . _) `($ ,(strip-? tg) ,@(maplr ppat args)))))))
+(define strip-?
+  (lambda (s)
+    (let* ((str (symbol->string s))
+           (n (string-length str)))
+      (if (or (zero? n)
+              (not (char=? #\? (string-ref str (- n 1)))))
+        s
+        (string->symbol (substring str 0 (- n 1)))))))
+(define pname
+  (match-lambda
+    ((? name? x) (or (name-name x) '<expr>))
+    ((? symbol? x) x)))
+(define ptag
+  (match-lambda
+    ((? k? k) (k-name k))
+    ((? symbol? x) x)))
+(define pconst
+  (match-lambda
+    ((? symbol? x) `',x)
+    ((? boolean? x) x)
+    ((? number? x) x)
+    ((? char? x) x)
+    ((? string? x) x)
+    ((? null? x) `',x)))
+(define check
+  (lambda (file)
+    (output-checked file '() type-check?)))
+(define profcheck
+  (lambda (file)
+    (output-checked #f '() type-check?)
+    (output-checked
+      #f
+      (make-counters total-possible)
+      type-check?)))
+(define fullcheck
+  (lambda (file)
+    (let ((check? (lambda (_) #t)))
+      (output-checked #f '() check?)
+      (output-checked
+        #f
+        (make-counters total-possible)
+        check?))))
+(define make-counters
+  (lambda (n)
+    (let* ((init `(define check-counters (make-vector ,n 0)))
+           (sum '(define check-total
+                   (lambda ()
+                     (let ((foldr (lambda (f i l)
+                                    (recur loop
+                                           ((l l))
+                                           (match l
+                                                  (() i)
+                                                  ((x . y) (f x (loop y))))))))
+                       (foldr + 0 (vector->list check-counters))))))
+           (incr '(extend-syntax
+                    (check-increment-counter)
+                    ((check-increment-counter c)
+                     (vector-set!
+                       check-counters
+                       c
+                       (+ 1 (vector-ref check-counters c)))))))
+      (list init sum incr))))
+(define output-checked
+  (lambda (file header check-test)
+    (set! summary '())
+    (set! total-possible 0)
+    (set! total-cast 0)
+    (set! total-err 0)
+    (set! total-any 0)
+    (let ((doit (lambda ()
+                  (when (string? file)
+                        (printf
+                          ";; Generated by Soft Scheme ~a~%"
+                          st:version)
+                        (printf ";; (st:control")
+                        (for-each
+                          (lambda (x) (printf " '~a" x))
+                          (show-controls))
+                        (printf ")~%")
+                        (unless
+                          (= 0 n-unbound)
+                          (printf
+                            ";; CAUTION: ~a unbound references, this code is not safe~%"
+                            n-unbound))
+                        (printf "~%")
+                        (for-each pretty-print header))
+                  (for-each
+                    (lambda (exp)
+                      (match exp
+                             (($ define x _)
+                              (set! n-possible 0)
+                              (set! n-clash 0)
+                              (set! n-err 0)
+                              (set! n-match 0)
+                              (set! n-inexhaust 0)
+                              (set! n-prim 0)
+                              (set! n-lam 0)
+                              (set! n-app 0)
+                              (set! n-field 0)
+                              (set! n-cast 0)
+                              (if file
+                                (pretty-print (pcheck exp check-test))
+                                (pcheck exp check-test))
+                              (make-summary-line x)
+                              (set! total-possible
+                                (+ total-possible n-possible))
+                              (set! total-cast (+ total-cast n-cast))
+                              (set! total-err (+ total-err n-err))
+                              (set! total-any
+                                (+ total-any
+                                   n-match
+                                   n-inexhaust
+                                   n-prim
+                                   n-lam
+                                   n-app
+                                   n-field
+                                   n-cast)))
+                             (_ (when file
+                                      (pretty-print
+                                        (pcheck exp check-test))))))
+                    tree)
+                  (when (string? file)
+                        (newline)
+                        (newline)
+                        (print-summary "; ")))))
+      (if (string? file)
+        (begin
+          (delete-file file)
+          (with-output-to-file file doit))
+        (doit)))))
+(define total-possible 0)
+(define total-err 0)
+(define total-cast 0)
+(define total-any 0)
+(define n-possible 0)
+(define n-clash 0)
+(define n-err 0)
+(define n-match 0)
+(define n-inexhaust 0)
+(define n-prim 0)
+(define n-lam 0)
+(define n-app 0)
+(define n-field 0)
+(define n-cast 0)
+(define summary '())
+(define make-summary-line
+  (lambda (x)
+    (let ((total (+ n-match
+                    n-inexhaust
+                    n-prim
+                    n-lam
+                    n-app
+                    n-field
+                    n-cast)))
+      (unless
+        (= 0 total)
+        (let* ((s (sprintf
+                    "~a~a "
+                    (padr (pname x) 16)
+                    (padl total 2)))
+               (s (cond ((< 0 n-inexhaust)
+                         (sprintf
+                           "~a (~a match ~a inexhaust)"
+                           s
+                           n-match
+                           n-inexhaust))
+                        ((< 0 n-match)
+                         (sprintf "~a (~a match)" s n-match))
+                        (else s)))
+               (s (if (< 0 n-prim)
+                    (sprintf "~a (~a prim)" s n-prim)
+                    s))
+               (s (if (< 0 n-field)
+                    (sprintf "~a (~a field)" s n-field)
+                    s))
+               (s (if (< 0 n-lam)
+                    (sprintf "~a (~a lambda)" s n-lam)
+                    s))
+               (s (if (< 0 n-app) (sprintf "~a (~a ap)" s n-app) s))
+               (s (if (< 0 n-err)
+                    (sprintf "~a (~a ERROR)" s n-err)
+                    s))
+               (s (if (< 0 n-cast)
+                    (sprintf "~a (~a TYPE)" s n-cast)
+                    s)))
+          (set! summary (cons s summary)))))))
+(define print-summary
+  (lambda (hdr)
+    (for-each
+      (lambda (s) (printf "~a~a~%" hdr s))
+      (reverse summary))
+    (printf
+      "~a~a~a "
+      hdr
+      (padr "TOTAL CHECKS" 16)
+      (padl total-any 2))
+    (printf
+      " (of ~s is ~s%)"
+      total-possible
+      (if (= 0 total-possible)
+        0
+        (string->number
+          (chop-number
+            (exact->inexact
+              (* (/ total-any total-possible) 100))
+            4))))
+    (when (< 0 total-err)
+          (printf " (~s ERROR)" total-err))
+    (when (< 0 total-cast)
+          (printf " (~s TYPE)" total-cast))
+    (printf "~%")))
+(define padl
+  (lambda (arg n)
+    (let ((s (sprintf "~a" arg)))
+      (recur loop
+             ((s s))
+             (if (< (string-length s) n)
+               (loop (string-append " " s))
+               s)))))
+(define padr
+  (lambda (arg n)
+    (let ((s (sprintf "~a" arg)))
+      (recur loop
+             ((s s))
+             (if (< (string-length s) n)
+               (loop (string-append s " "))
+               s)))))
+(define chop-number
+  (lambda (x n)
+    (substring
+      (sprintf "~s00000000000000000000" x)
+      0
+      (- n 1))))
+(define pcheck
+  (lambda (ex check-test)
+    (unparse
+      ex
+      (lambda (e pexpr)
+        (match e
+               ((and z ($ type _ ($ check inf ($ var x))))
+                (cond ((name-primitive x)
+                       (set! n-possible (+ 1 n-possible))
+                       (match (check-test inf)
+                              (#f (pname x))
+                              ('def
+                               (set! n-err (+ 1 n-err))
+                               (set! n-prim (+ 1 n-prim))
+                               `(,(symbol-append "CHECK-" (pname x))
+                                 ,(tree-index z)
+                                 ',(string->symbol "ERROR")))
+                              (_ (set! n-prim (+ 1 n-prim))
+                                 `(,(symbol-append "CHECK-" (pname x))
+                                   ,(tree-index z)))))
+                      ((name-unbound? x) `(check-bound ,(pname x)))
+                      (else
+                       (if (check-test inf)
+                         (begin
+                           (set! n-clash (+ 1 n-clash))
+                           `(,(string->symbol "CLASH")
+                             ,(pname x)
+                             ,(tree-index z)))
+                         (pname x)))))
+               ((and z
+                     ($ type _ ($ check inf (and m ($ lam x e1)))))
+                (set! n-possible (+ 1 n-possible))
+                (match (check-test inf)
+                       (#f (pexpr m))
+                       ('def
+                        (set! n-err (+ 1 n-err))
+                        (set! n-lam (+ 1 n-lam))
+                        `(,(string->symbol "CHECK-lambda")
+                          (,(tree-index z) ',(string->symbol "ERROR"))
+                          ,(map pname x)
+                          ,@(pexpr e1)))
+                       (_ (set! n-lam (+ 1 n-lam))
+                          `(,(string->symbol "CHECK-lambda")
+                            (,(tree-index z))
+                            ,(map pname x)
+                            ,@(pexpr e1)))))
+               ((and z
+                     ($ type
+                        _
+                        ($ check inf (and m ($ vlam x rest e1)))))
+                (set! n-possible (+ 1 n-possible))
+                (match (check-test inf)
+                       (#f (pexpr m))
+                       ('def
+                        (set! n-err (+ 1 n-err))
+                        (set! n-lam (+ 1 n-lam))
+                        `(,(string->symbol "CHECK-lambda")
+                          (,(tree-index z) ',(string->symbol "ERROR"))
+                          ,(append (map pname x) (pname rest))
+                          ,@(pexpr e1)))
+                       (_ (set! n-lam (+ 1 n-lam))
+                          `(,(string->symbol "CHECK-lambda")
+                            (,(tree-index z))
+                            ,(append (map pname x) (pname rest))
+                            ,@(pexpr e1)))))
+               ((and z
+                     ($ type _ ($ check inf (and m ($ app e1 args)))))
+                (set! n-possible (+ 1 n-possible))
+                (match (check-test inf)
+                       (#f (pexpr m))
+                       ('def
+                        (set! n-err (+ 1 n-err))
+                        (set! n-app (+ 1 n-app))
+                        `(,(string->symbol "CHECK-ap")
+                          (,(tree-index z) ',(string->symbol "ERROR"))
+                          ,(pexpr e1)
+                          ,@(map pexpr args)))
+                       (_ (set! n-app (+ 1 n-app))
+                          (let ((p1 (pexpr e1)))
+                            `(,(string->symbol "CHECK-ap")
+                              (,(tree-index z))
+                              ,p1
+                              ,@(map pexpr args))))))
+               ((and z
+                     ($ type _ ($ check inf (and m ($ field x e1)))))
+                (set! n-possible (+ 1 n-possible))
+                (match (check-test inf)
+                       (#f (pexpr m))
+                       ('def
+                        (set! n-err (+ 1 n-err))
+                        (set! n-field (+ 1 n-field))
+                        `(,(string->symbol "CHECK-field")
+                          (,(tree-index z) ',(string->symbol "ERROR"))
+                          ,x
+                          ,(pexpr e1)))
+                       (_ (set! n-field (+ 1 n-field))
+                          `(,(string->symbol "CHECK-field")
+                            (,(tree-index z))
+                            ,x
+                            ,(pexpr e1)))))
+               ((and z
+                     ($ type
+                        _
+                        ($ check inf (and m ($ cast (x . _) e1)))))
+                (set! n-possible (+ 1 n-possible))
+                (match (check-test inf)
+                       (#f (pexpr m))
+                       (_ (set! n-cast (+ 1 n-cast))
+                          `(,(string->symbol "CHECK-:")
+                            (,(tree-index z))
+                            ,x
+                            ,(pexpr e1)))))
+               ((and z
+                     ($ type
+                        _
+                        ($ check inf (and m ($ match e1 clauses)))))
+                (set! n-possible (+ 1 n-possible))
+                (match (check-test inf)
+                       (#f (pexpr m))
+                       (inx (let* ((pclause
+                                     (match-lambda
+                                       (($ mclause p exp fail)
+                                        (if fail
+                                          `(,(ppat p)
+                                            (=> ,(pname fail))
+                                            ,@(pexpr exp))
+                                          `(,(ppat p) ,@(pexpr exp))))))
+                                   (p1 (pexpr e1)))
+                              (if (eq? 'inexhaust inx)
+                                (begin
+                                  (set! n-inexhaust (+ 1 n-inexhaust))
+                                  `(,(string->symbol "CHECK-match")
+                                    (,(tree-index z)
+                                     ,(string->symbol "INEXHAUST"))
+                                    ,p1
+                                    ,@(maplr pclause clauses)))
+                                (begin
+                                  (set! n-match (+ 1 n-match))
+                                  `(,(string->symbol "CHECK-match")
+                                    (,(tree-index z))
+                                    ,p1
+                                    ,@(maplr pclause clauses)))))))))))))
+(define tree-index-list '())
+(define reinit-output!
+  (lambda () (set! tree-index-list '())))
+(define tree-index
+  (lambda (syntax)
+    (match (assq syntax tree-index-list)
+           (#f
+            (let ((n (length tree-index-list)))
+              (set! tree-index-list
+                (cons (cons syntax n) tree-index-list))
+              n))
+           ((_ . n) n))))
+(define tree-unindex
+  (lambda (n)
+    (let ((max (length tree-index-list)))
+      (when (<= max n)
+            (use-error "Invalid CHECK number ~a" n))
+      (car (list-ref tree-index-list (- (- max 1) n))))))
+(define cause
+  (lambda ()
+    (for-each
+      (lambda (def)
+        (for-each pretty-print (exp-cause def)))
+      tree)))
+(define cause*
+  (lambda names
+    (if (null? names)
+      (for-each
+        (lambda (def)
+          (for-each pretty-print (exp-cause def)))
+        tree)
+      (for-each
+        (match-lambda
+          ((? symbol? dname)
+           (for-each
+             pretty-print
+             (exp-cause (find-global dname)))))
+        names))))
+(define exp-cause
+  (let ((sum (lambda (exps)
+               (foldr (lambda (x y) (append (exp-cause x) y))
+                      '()
+                      exps)))
+        (src (lambda (inf)
+               (let ((nonlocal (map tree-index (check-sources inf))))
+                 (if (type-check1? inf)
+                   (cons (check-local-sources inf) nonlocal)
+                   nonlocal)))))
+    (match-lambda
+      ((and z ($ type ty ($ check inf ($ var x))))
+       (if (name-primitive x)
+         (if (type-check? inf)
+           (list `((,(symbol-append 'check- (pname x))
+                    ,(tree-index z))
+                   ,@(src inf)))
+           '())
+         (if (type-check1? inf)
+           (list `((clash ,(pname x) ,(tree-index z)) ,@(src inf)))
+           '())))
+      ((and z ($ type ty ($ check inf ($ lam x e1))))
+       (append
+         (if (type-check? inf)
+           (list `((check-lambda ,(tree-index z) ,(map pname x) ...)
+                   ,@(src inf)))
+           '())
+         (exp-cause e1)))
+      ((and z
+            ($ type ty ($ check inf ($ vlam x rest e1))))
+       (append
+         (if (type-check? inf)
+           (list `((check-lambda
+                     ,(tree-index z)
+                     ,(append (map pname x) (pname rest))
+                     ...)
+                   ,@(src inf)))
+           '())
+         (exp-cause e1)))
+      ((and z ($ type _ ($ check inf ($ app e1 args))))
+       (append
+         (if (type-check? inf)
+           (list `((check-ap ,(tree-index z)) ,@(src inf)))
+           '())
+         (exp-cause e1)
+         (sum args)))
+      ((and z ($ type _ ($ check inf ($ field x e1))))
+       (append
+         (if (type-check? inf)
+           (list `((check-field ,(tree-index z) ,x ...)
+                   ,@(src inf)))
+           '())
+         (exp-cause e1)))
+      ((and z
+            ($ type _ ($ check inf ($ cast (x . _) e1))))
+       (append
+         (if (type-check? inf)
+           (list `((check-: ,(tree-index z) ,x ...) ,@(src inf)))
+           '())
+         (exp-cause e1)))
+      ((and z
+            ($ type
+               _
+               ($ check inf (and m ($ match e1 clauses)))))
+       (append
+         (if (type-check? inf)
+           (list `((check-match ,(tree-index z) ...) ,@(src inf)))
+           '())
+         (exp-cause m)))
+      (($ define _ e) (exp-cause e))
+      ((? defstruct?) '())
+      ((? datatype?) '())
+      (($ app e1 args) (sum (cons e1 args)))
+      (($ match exp clauses)
+       (foldr (lambda (x y)
+                (append
+                  (match x (($ mclause _ e _) (exp-cause e)))
+                  y))
+              (exp-cause exp)
+              clauses))
+      (($ var _) '())
+      (($ and exps) (sum exps))
+      (($ begin exps) (sum exps))
+      ((? const?) '())
+      (($ if test then els)
+       (append
+         (exp-cause test)
+         (exp-cause then)
+         (exp-cause els)))
+      (($ let bindings body)
+       (foldr (lambda (x y)
+                (append (match x (($ bind _ e) (exp-cause e))) y))
+              (exp-cause body)
+              bindings))
+      (($ let* bindings body)
+       (foldr (lambda (x y)
+                (append (match x (($ bind _ e) (exp-cause e))) y))
+              (exp-cause body)
+              bindings))
+      (($ letr bindings body)
+       (foldr (lambda (x y)
+                (append (match x (($ bind _ e) (exp-cause e))) y))
+              (exp-cause body)
+              bindings))
+      (($ body defs exps) (sum (append defs exps)))
+      (($ or exps) (sum exps))
+      (($ delay e) (exp-cause e))
+      (($ set! var body) (exp-cause body))
+      (($ record bindings)
+       (foldr (lambda (x y)
+                (append (match x (($ bind _ e) (exp-cause e))) y))
+              '()
+              bindings))
+      (($ type _ exp) (exp-cause exp)))))
+(define display-type tidy)
+(define type
+  (lambda names
+    (if (null? names)
+      (for-each globaldef tree)
+      (for-each
+        (match-lambda
+          ((? symbol? x)
+           (match (lookup? global-env x)
+                  (#f (use-error "~a is not defined" x))
+                  (ty (pretty-print
+                        `(,x : ,(display-type (name-ty ty)))))))
+          ((? number? n)
+           (let* ((ty (check-type (tree-unindex n)))
+                  (type (display-type ty)))
+             (pretty-print `(,n : ,type))))
+          (_ (use-error
+               "arguments must be identifiers or CHECK numbers")))
+        names))))
+(define localtype
+  (lambda names
+    (if (null? names)
+      (for-each localdef tree)
+      (for-each
+        (lambda (x) (localdef (find-global x)))
+        names))))
+(define find-global
+  (lambda (name)
+    (let ((d (ormap (match-lambda
+                      ((and d ($ define x _))
+                       (and (eq? name (name-name x)) d))
+                      (_ #f))
+                    tree)))
+      (unless d (use-error "~a is not defined" name))
+      d)))
+(define globaldef
+  (lambda (e)
+    (match e
+           (($ define x _)
+            (let ((type (display-type (name-ty x))))
+              (pretty-print `(,(pname x) : ,type))))
+           (_ #f))))
+(define localdef
+  (lambda (e) (pretty-print (expdef e))))
+(define expdef
+  (let* ((show (lambda (x)
+                 `(,(pname x) : ,(display-type (name-ty x)))))
+         (pbind (match-lambda
+                  (($ bind x e) `(,(show x) ,(expdef e))))))
+    (match-lambda
+      (($ define x e)
+       (if (or (not x) (and (name? x) (not (name-name x))))
+         (expdef e)
+         `(define ,(show x) ,(expdef e))))
+      ((? defstruct? d) (pdef d))
+      ((? datatype? d) (pdef d))
+      (($ and exps) `(and ,@(maplr expdef exps)))
+      (($ app fun args)
+       `(,(expdef fun) ,@(maplr expdef args)))
+      (($ begin exps) `(begin ,@(maplr expdef exps)))
+      (($ const c _) (pconst c))
+      (($ if test then els)
+       `(if ,(expdef test) ,(expdef then) ,(expdef els)))
+      (($ lam params body)
+       `(lambda ,(map show params) ,@(expdef body)))
+      (($ vlam params rest body)
+       `(lambda ,(append (map show params) (show rest))
+          ,@(expdef body)))
+      (($ let bindings body)
+       `(let ,(map pbind bindings) ,@(expdef body)))
+      (($ let* bindings body)
+       `(let* ,(map pbind bindings) ,@(expdef body)))
+      (($ letr bindings body)
+       `(letrec ,(map pbind bindings) ,@(expdef body)))
+      (($ body defs exps)
+       (let ((pdefs (maplr expdef defs)))
+         (append pdefs (maplr expdef exps))))
+      (($ record bindings)
+       `(record ,@(maplr pbind bindings)))
+      (($ field x e) `(field ,x ,(expdef e)))
+      (($ cast (ty . _) e) `(: ,ty ,(expdef e)))
+      (($ or exps) `(or ,@(maplr expdef exps)))
+      (($ delay e) `(delay ,(expdef e)))
+      (($ set! x body)
+       `(set! ,(pname x) ,(expdef body)))
+      (($ var x) (pname x))
+      (($ match e1 clauses)
+       (let* ((pclause
+                (match-lambda
+                  (($ mclause p exp fail)
+                   (if fail
+                     `(,(expdef p) (=> ,(pname fail)) ,@(expdef exp))
+                     `(,(expdef p) ,@(expdef exp))))))
+              (p1 (expdef e1)))
+         `(match ,p1 ,@(maplr pclause clauses))))
+      (($ pconst x _) (pconst x))
+      (($ pvar x) (show x))
+      (($ pany) '_)
+      (($ pelse) 'else)
+      (($ pnot pat) `(not ,(expdef pat)))
+      (($ pand pats) `(and ,@(maplr expdef pats)))
+      (($ ppred pred)
+       (match (pname pred)
+              ('false-object? #f)
+              ('true-object? #t)
+              ('null? '())
+              (x `(? ,x))))
+      (($ pobj tag args)
+       (match (cons (pname tag) args)
+              (('pair? x y) (cons (expdef x) (expdef y)))
+              (('box? x) (box (expdef x)))
+              (('vector? . x) (list->vector (maplr expdef x)))
+              ((tg . _)
+               `($ ,(strip-? tg) ,@(maplr expdef args)))))
+      (($ type _ exp) (expdef exp))
+      (($ check _ exp) (expdef exp)))))
+(define check-type
+  (match-lambda
+    (($ type ty ($ check inf ($ var x))) ty)
+    (($ type ty ($ check inf ($ lam x e1))) ty)
+    (($ type ty ($ check inf ($ vlam x rest e1))) ty)
+    (($ type _ ($ check inf ($ app e1 args)))
+     (typeof e1))
+    (($ type _ ($ check inf ($ field x e1)))
+     (typeof e1))
+    (($ type _ ($ check inf ($ cast (x . _) e1)))
+     (typeof e1))
+    (($ type _ ($ check inf ($ match e1 clauses)))
+     (typeof e1))))
+(define tree '())
+(define global-env empty-env)
+(define verbose #f)
+(define times #t)
+(define benchmarking #f)
+(define cons-mutators '(set-car! set-cdr!))
+(define st:check
+  (lambda args
+    (parameterize
+      ((print-level #f)
+       (print-length #f)
+       (pretty-maximum-lines #f))
+      (let ((output (apply do-soft args)))
+        (when output
+              (printf
+                "Typed program written to file ~a~%"
+                output))))))
+(define st:run
+  (lambda (file)
+    (parameterize
+      ((optimize-level 3))
+      (when benchmarking
+            (printf "Reloading slow CHECKs...~%")
+            (load (string-append
+                    installation-directory
+                    "checklib.scm"))
+            (set! benchmarking #f))
+      (load file))))
+(define st:bench
+  (lambda (file)
+    (parameterize
+      ((optimize-level 3))
+      (unless
+        benchmarking
+        (unless
+          fastlibrary-file
+          (use-error
+            "No benchmarking mode in this version"))
+        (printf "Reloading fast CHECKs...~%")
+        (load (string-append
+                installation-directory
+                fastlibrary-file))
+        (set! benchmarking #t))
+      (load file))))
+(define st:
+  (lambda args
+    (parameterize
+      ((print-level #f)
+       (print-length #f)
+       (pretty-maximum-lines #f))
+      (let ((output (apply do-soft args)))
+        (cond ((not output)
+               (use-error "Output file name required to run"))
+              ((= 0 n-unbound)
+               (printf
+                 "Typed program written to file ~a, executing ...~%"
+                 output)
+               (flush-output)
+               (st:run output))
+              (else
+               (printf
+                 "Typed program written to file ~a, not executing (unbound refs)~%"
+                 output)))))))
+(define do-soft
+  (match-lambda*
+    ((input (? string? output))
+     (when (strip-suffix output)
+           (use-error
+             "output file name cannot end in .ss or .scm"))
+     (cond ((string? input)
+            (soft-files (list input) output)
+            output)
+           ((and (list? input) (andmap string? input))
+            (soft-files input output)
+            output)
+           (else (soft-def input output) output)))
+    ((input #f)
+     (cond ((string? input) (soft-files (list input) #f) #f)
+           ((and (list? input) (andmap string? input))
+            (soft-files input #f)
+            #f)
+           (else (soft-def input #f) #f)))
+    ((input)
+     (cond ((string? input)
+            (let ((o (string-append
+                       (or (strip-suffix input) input)
+                       ".soft")))
+              (soft-files (list input) o)
+              o))
+           ((and (list? input) (andmap string? input))
+            (use-error "Output file name required"))
+           (else (soft-def input #t) #f)))
+    (else (use-error
+            "Input must be a file name or list of file names"))))
+(define rawmode #f)
+(define st:control
+  (lambda args
+    (let ((dbg (match-lambda
+                 ('raw
+                  (set! display-type ptype)
+                  (set! rawmode #t))
+                 ('!raw
+                  (set! display-type tidy)
+                  (set! rawmode #f))
+                 ('verbose (set! verbose #t))
+                 ('!verbose (set! verbose #f))
+                 ('times (set! times #t))
+                 ('!times (set! times #f))
+                 ('partial (set! fullsharing #f))
+                 ('!partial (set! fullsharing #t))
+                 ('pseudo (set! pseudo pseudo-subtype))
+                 ('!pseudo (set! pseudo #f))
+                 ('populated (set! populated #t))
+                 ('!populated (set! populated #f))
+                 ('matchst (set! matchst #t))
+                 ('!matchst (set! matchst #f))
+                 ('genmatch (set! genmatch #t))
+                 ('!genmatch (set! genmatch #f))
+                 ('letonce (set! letonce #t))
+                 ('!letonce (set! letonce #f))
+                 ('global-error (set! global-error #t))
+                 ('!global-error (set! global-error #f))
+                 ('share (set! share #t))
+                 ('!share (set! share #f))
+                 ('flags (set! flags #t))
+                 ('!flags (set! flags #f))
+                 ('depths (set! dump-depths #t))
+                 ('!depths (set! dump-depths #f))
+                 ('match (set! keep-match #t))
+                 ('!match (set! keep-match #f))
+                 (x (printf "Error: unknown debug switch ~a~%" x)
+                    (st:control)))))
+      (if (null? args)
+        (begin
+          (printf "Current values:")
+          (for-each
+            (lambda (x) (printf " ~a" x))
+            (show-controls))
+          (printf "~%"))
+        (for-each dbg args)))))
+(define show-controls
+  (lambda ()
+    (list (if rawmode 'raw '!raw)
+          (if verbose 'verbose '!verbose)
+          (if times 'times '!times)
+          (if share 'share '!share)
+          (if flags 'flags '!flags)
+          (if dump-depths 'depths '!depths)
+          (if fullsharing '!partial 'partial)
+          (if pseudo 'pseudo '!pseudo)
+          (if populated 'populated '!populated)
+          (if letonce 'letonce '!letonce)
+          (if matchst 'matchst '!matchst)
+          (if genmatch 'genmatch '!genmatch)
+          (if global-error 'global-error '!global-error)
+          (if keep-match 'match '!match))))
+(define soft-def
+  (lambda (exp output)
+    (reinit-macros!)
+    (reinit-types!)
+    (reinit-output!)
+    (set! visible-time 0)
+    (match-let*
+      ((before-parse (cpu-time))
+       (defs (parse-def exp))
+       (before-bind (cpu-time))
+       ((defs env tenv unbound)
+        (bind-defs
+          defs
+          initial-env
+          initial-type-env
+          '()
+          0))
+       (_ (warn-unbound unbound))
+       (_ (if cons-is-mutable
+            (printf
+              "Note: use of ~a, treating cons as MUTABLE~%"
+              cons-mutators)
+            (printf
+              "Note: no use of ~a, treating cons as immutable~%"
+              cons-mutators)))
+       (before-improve (cpu-time))
+       (defs (improve-defs defs))
+       (before-typecheck (cpu-time))
+       (_ (type-check defs))
+       (_ (set! global-env env))
+       (before-output (cpu-time))
+       (_ (check output))
+       (_ (print-summary ""))
+       (before-end (cpu-time)))
+      (when times
+            (printf
+              "~a seconds parsing,~%"
+              (exact->inexact
+                (* (- before-bind before-parse)
+                   clock-granularity)))
+            (printf
+              "~a seconds binding,~%"
+              (exact->inexact
+                (* (- before-improve before-bind)
+                   clock-granularity)))
+            (printf
+              "~a seconds improving,~%"
+              (exact->inexact
+                (* (- before-typecheck before-improve)
+                   clock-granularity)))
+            (printf
+              "~a seconds type checking,~%"
+              (exact->inexact
+                (* (- (- before-output before-typecheck)
+                      visible-time)
+                   clock-granularity)))
+            (printf
+              "~a seconds setting visibility,~%"
+              (exact->inexact
+                (* visible-time clock-granularity)))
+            (printf
+              "~a seconds writing output,~%"
+              (exact->inexact
+                (* (- before-end before-output)
+                   clock-granularity)))
+            (printf
+              "~a seconds in total.~%"
+              (exact->inexact
+                (* (- before-end before-parse) clock-granularity)))))))
+(define type-check
+  (lambda (defs)
+    (set! tree defs)
+    (type-defs defs)
+    defs))
+(define soft-files
+  (lambda (files output)
+    (let ((contents
+            (map (lambda (f) `(begin ,@(readfile f))) files)))
+      (soft-def `(begin ,@contents) output))))
+(define strip-suffix
+  (lambda (name)
+    (let ((n (string-length name)))
+      (or (and (<= 3 n)
+               (equal? ".ss" (substring name (- n 3) n))
+               (substring name 0 (- n 3)))
+          (and (<= 4 n)
+               (equal? ".scm" (substring name (- n 4) n))
+               (substring name 0 (- n 4)))))))
+(define st:deftype
+  (match-lambda*
+    (((? symbol? x) ? list? mutability)
+     (=> fail)
+     (if (andmap boolean? mutability)
+       (deftype x mutability)
+       (fail)))
+    (args (use-error
+            "Invalid command ~a"
+            `(st:deftype ,@args)))))
+(define st:defprim
+  (match-lambda*
+    (((? symbol? x) type) (defprim x type 'impure))
+    (((? symbol? x) type (? symbol? mode))
+     (defprim x type mode))
+    (args (use-error
+            "Invalid command ~a"
+            `(st:defprim ,@args)))))
+(define st:help
+  (lambda ()
+    (printf
+      "Commands for Soft Scheme (~a)~%"
+      st:version)
+    (printf
+      "  (st:         file (output))    type check file and execute~%")
+    (printf
+      "  (st:type     (name))           print types of global defs~%")
+    (printf
+      "  (st:check    file (output))    type check file~%")
+    (printf
+      "  (st:run      file)             execute type checked file~%")
+    (printf
+      "  (st:bench    file)             execute type checked file fast~%")
+    (printf
+      "  (st:ltype    (name))           print types of local defs~%")
+    (printf
+      "  (st:cause)                     print cause of CHECKs~%")
+    (printf
+      "  (st:summary)                   print summary of CHECKs~%")
+    (printf
+      "  (st:help)                      prints this message~%")
+    (printf
+      "  (st:defprim  name type (mode)) define a new primitive~%")
+    (printf
+      "  (st:deftype  name bool ...)    define a new type constructor~%")
+    (printf
+      "  (st:control  flag ...)         set internal flags~%")
+    (printf
+      "For more info, see ftp://ftp.nj.nec.com/pub/wright/ssmanual/softscheme.html~%")
+    (printf
+      "Copyright (c) 1993, 1994, 1995 by Andrew K. Wright under the~%")
+    (printf
+      "terms of the Gnu Public License. No warranties of any kind apply.~%")))
+(define st:type type)
+(define st:ltype localtype)
+(define st:cause cause)
+(define st:summary
+  (lambda () (print-summary "")))
+(define init!
+  (lambda ()
+    (when customization-file
+          (load (string-append
+                  installation-directory
+                  customization-file)))
+    (let ((softrc
+            (string-append home-directory "/.softschemerc")))
+      (when (file-exists? softrc) (load softrc)))
+    (set! global-env initial-env)
+    (st:help)))
+(init!)