1#!nobacktrace
2;;; proting Pattern Matching Syntactic Extensiond for Scheme to ypsilon
3;;; -- y.fujita.lwp
4
5(library (ypsilon match)
6  (export match
7          match-lambda
8          match-lambda*
9          match-let
10          match-let*
11          match-letrec
12          match-define)
13  (import (core))
14
15  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
16  ;; Pattern Matching Syntactic Extensions for Scheme
17  ;;
18  (define match:version "Version 1.18, July 17, 1995")
19  ;;
20  ;; Report bugs to wright@research.nj.nec.com.  The most recent version of
21  ;; this software can be obtained by anonymous FTP from ftp.nj.nec.com
22  ;; in file pub/wright/match.tar.Z.  Be sure to set "type binary" when
23  ;; transferring this file.
24  ;;
25  ;; Written by Andrew K. Wright, 1993 (wright@research.nj.nec.com).
26  ;; Adapted from code originally written by Bruce F. Duba, 1991.
27  ;; This package also includes a modified version of Kent Dybvig's
28  ;; define-structure (see Dybvig, R.K., The Scheme Programming Language,
29  ;; Prentice-Hall, NJ, 1987).
30  ;;
31  ;; This software is in the public domain.  Feel free to copy,
32  ;; distribute, and modify this software as desired.  No warranties
33  ;; nor guarantees of any kind apply.  Please return any improvements
34  ;; or bug fixes to wright@research.nj.nec.com so that they may be included
35  ;; in future releases.
36  ;;
37  ;; This macro package extends Scheme with several new expression forms.
38  ;; Following is a brief summary of the new forms.  See the associated
39  ;; LaTeX documentation for a full description of their functionality.
40  ;;
41  ;;
42  ;;         match expressions:
43  ;;
44  ;; exp ::= ...
45  ;;       | (match exp clause ...)
46  ;;       | (match-lambda clause ...)
47  ;;       | (match-lambda* clause ...)
48  ;;       | (match-let ((pat exp) ...) body)
49  ;;       | (match-let* ((pat exp) ...) body)
50  ;;       | (match-letrec ((pat exp) ...) body)
51  ;;       | (match-define pat exp)
52  ;;
53  ;; clause ::= (pat body) | (pat => exp)
54  ;;
55  ;;         patterns:                       matches:
56  ;;
57  ;; pat ::= identifier                      anything, and binds identifier
58  ;;       | _                               anything
59  ;;       | ()                              the empty list
60  ;;       | #t                              #t
61  ;;       | #f                              #f
62  ;;       | string                          a string
63  ;;       | number                          a number
64  ;;       | character                       a character
65  ;;       | 'sexp                           an s-expression
66  ;;       | 'symbol                         a symbol (special case of s-expr)
67  ;;       | (pat_1 ... pat_n)               list of n elements
68  ;;       | (pat_1 ... pat_n . pat_{n+1})   list of n or more
69  ;;       | (pat_1 ... pat_n pat_n+1 ooo)   list of n or more, each element
70  ;;                                           of remainder must match pat_n+1
71  ;;       | #(pat_1 ... pat_n)              vector of n elements
72  ;;       | #(pat_1 ... pat_n pat_n+1 ooo)  vector of n or more, each element
73  ;;                                           of remainder must match pat_n+1
74  ;;       | #&pat                           box
75  ;;       | ($ struct-name pat_1 ... pat_n) a structure
76  ;;       | (= field pat)                   a field of a structure
77  ;;       | (and pat_1 ... pat_n)           if all of pat_1 thru pat_n match
78  ;;       | (or pat_1 ... pat_n)            if any of pat_1 thru pat_n match
79  ;;       | (not pat_1 ... pat_n)           if all pat_1 thru pat_n don't match
80  ;;       | (? predicate pat_1 ... pat_n)   if predicate true and all of
81  ;;                                           pat_1 thru pat_n match
82  ;;       | (set! identifier)               anything, and binds setter
83  ;;       | (get! identifier)               anything, and binds getter
84  ;;       | `qp                             a quasi-pattern
85  ;;
86  ;; ooo ::= ...                             zero or more
87  ;;       | ___                             zero or more
88  ;;       | ..k                             k or more
89  ;;       | __k                             k or more
90  ;;
91  ;;         quasi-patterns:                 matches:
92  ;;
93  ;; qp  ::= ()                              the empty list
94  ;;       | #t                              #t
95  ;;       | #f                              #f
96  ;;       | string                          a string
97  ;;       | number                          a number
98  ;;       | character                       a character
99  ;;       | identifier                      a symbol
100  ;;       | (qp_1 ... qp_n)                 list of n elements
101  ;;       | (qp_1 ... qp_n . qp_{n+1})      list of n or more
102  ;;       | (qp_1 ... qp_n qp_n+1 ooo)      list of n or more, each element
103  ;;                                           of remainder must match qp_n+1
104  ;;       | #(qp_1 ... qp_n)                vector of n elements
105  ;;       | #(qp_1 ... qp_n qp_n+1 ooo)     vector of n or more, each element
106  ;;                                           of remainder must match qp_n+1
107  ;;       | #&qp                            box
108  ;;       | ,pat                            a pattern
109  ;;       | ,@pat                           a pattern
110  ;;
111  ;; The names (quote, quasiquote, unquote, unquote-splicing, ?, _, $,
112  ;; and, or, not, set!, get!, ..., ___) cannot be used as pattern variables.
113  ;;
114  ;;
115  ;;         structure expressions:
116  ;;
117  ;; exp ::= ...
118  ;;       | (define-structure (id_0 id_1 ... id_n))
119  ;;       | (define-structure (id_0 id_1 ... id_n)
120  ;;                           ((id_{n+1} exp_1) ... (id_{n+m} exp_m)))
121  ;;       | (define-const-structure (id_0 arg_1 ... arg_n))
122  ;;       | (define-const-structure (id_0 arg_1 ... arg_n)
123  ;;                                 ((arg_{n+1} exp_1) ... (arg_{n+m} exp_m)))
124  ;;
125  ;; arg ::= id | (! id) | (@ id)
126  ;;
127  ;;
128  ;; match:error-control controls what code is generated for failed matches.
129  ;; Possible values:
130  ;;  'unspecified - do nothing, ie., evaluate (cond [#f #f])
131  ;;  'fail - call match:error, or die at car or cdr
132  ;;  'error - call match:error with the unmatched value
133  ;;  'match - call match:error with the unmatched value _and_
134  ;;             the quoted match expression
135  ;; match:error-control is set by calling match:set-error-control with
136  ;; the new value.
137  ;;
138  ;; match:error is called for a failed match.
139  ;; match:error is set by calling match:set-error with the new value.
140  ;;
141  ;; match:structure-control controls the uniqueness of structures
142  ;; (does not exist for Scheme 48 version).
143  ;; Possible values:
144  ;;  'vector - (default) structures are vectors with a symbol in position 0
145  ;;  'disjoint - structures are fully disjoint from all other values
146  ;; match:structure-control is set by calling match:set-structure-control
147  ;; with the new value.
148  ;;
149  ;; match:runtime-structures controls whether local structure declarations
150  ;; generate new structures each time they are reached
151  ;; (does not exist for Scheme 48 version).
152  ;; Possible values:
153  ;;  #t - (default) each runtime occurrence generates a new structure
154  ;;  #f - each lexical occurrence generates a new structure
155  ;;
156  ;; End of user visible/modifiable stuff.
157  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
158
159  (define gentemp gensym)
160
161  (define match:error
162    (lambda (val . args)
163      (for-each (lambda (expr) (format (current-error-port) "~s" expr)) args)
164      (syntax-violation 'match "no matching clause for ~m" val)))
165
166  (define match:andmap
167    (lambda (f l)
168      (or (null? l)
169          (and (f (car l)) (match:andmap f (cdr l))))))
170
171  (define match:syntax-err
172    (lambda (obj msg) (syntax-violation 'match (format "~a ~s" msg obj))))
173
174  (define match:disjoint-structure-tags '())
175  (define match:make-structure-tag
176    (lambda (name)
177      (if (or (eq? match:structure-control 'disjoint)
178              match:runtime-structures)
179          (let ((tag (gentemp)))
180            (set! match:disjoint-structure-tags
181                  (cons tag match:disjoint-structure-tags))
182            tag)
183          (string->symbol
184           (string-append "<" (symbol->string name) ">")))))
185  (define match:structure?
186    (lambda (tag) (memq tag match:disjoint-structure-tags)))
187
188  (define match:structure-control 'vector)
189
190  (define match:set-structure-control
191    (lambda (v) (set! match:structure-control v)))
192
193  (define match:set-error
194    (lambda (v) (set! match:error v)))
195  (define match:error-control 'error)
196  (define match:set-error-control
197    (lambda (v) (set! match:error-control v)))
198
199  (define match:disjoint-predicates
200    (cons 'null
201          '(pair?
202            symbol?
203            boolean?
204            number?
205            string?
206            char?
207            procedure?
208            vector?)))
209
210  (define match:vector-structures '())
211
212  ;;; beginning of expanders
213
214  (define genmatch
215    (lambda (x clauses match-expr)
216      (let* ((length>= (gentemp))
217             (eb-errf (error-maker match-expr))
218             (blist (car eb-errf))
219             (plist (map (lambda (c)
220                           (let* ((x (bound (validate-pattern (car c))))
221                                  (p (car x))
222                                  (bv (cadr x))
223                                  (bindings (caddr x))
224                                  (code (gentemp))
225                                  (fail (and (pair? (cdr c))
226                                             (pair? (cadr c))
227                                             (eq? (caadr c) '=>)
228                                             (symbol? (cadadr c))
229                                             (pair? (cdadr c))
230                                             (null? (cddadr c))
231                                             (pair? (cddr c))
232                                             (cadadr c)))
233                                  (bv2 (if fail (cons fail bv) bv))
234                                  (body (if fail (cddr c) (cdr c))))
235                             (set! blist
236                                   (cons `(,code (lambda ,bv2 ,@body))
237                                         (append bindings blist)))
238                             (list p code bv (and fail (gentemp)) #f)))
239                         clauses))
240             (code (gen x '() plist (cdr eb-errf) length>= (gentemp))))
241        (unreachable plist match-expr)
242        (inline-let
243         `(let ((,length>= (lambda (n) (lambda (l) (>= (length l) n))))
244                ,@blist)
245            ,code)))))
246  ;;;
247  (define genletrec
248    (lambda (pat exp body match-expr)
249      (let* ((length>= (gentemp))
250             (eb-errf (error-maker match-expr))
251             (x (bound (validate-pattern pat)))
252             (p (car x))
253             (bv (cadr x))
254             (bindings (caddr x))
255             (code (gentemp))
256             (plist (list (list p code bv #f #f)))
257             (x (gentemp))
258             (m (gen x '() plist (cdr eb-errf) length>= (gentemp)))
259             (gs (map (lambda (_) (gentemp)) bv)))
260        (unreachable plist match-expr)
261        `(letrec ((,length>= (lambda (n) (lambda (l) (>= (length l) n))))
262                  ,@(map (lambda (v) `(,v #f)) bv)
263                  (,x ,exp)
264                  (,code (lambda ,gs
265                           ,@(map (lambda (v g) `(set! ,v ,g)) bv gs)
266                           ,@body))
267                  ,@bindings
268                  ,@(car eb-errf))
269           ,m))))
270  ;;;
271  (define gendefine
272    (lambda (pat exp match-expr)
273      (let* ((length>= (gentemp))
274             (eb-errf (error-maker match-expr))
275             (x (bound (validate-pattern pat)))
276             (p (car x))
277             (bv (cadr x))
278             (bindings (caddr x))
279             (code (gentemp))
280             (plist (list (list p code bv #f #f)))
281             (x (gentemp))
282             (m (gen x '() plist (cdr eb-errf) length>= (gentemp)))
283             (gs (map (lambda (_) (gentemp)) bv)))
284        (unreachable plist match-expr)
285        `(begin ,@(map (lambda (v) `(define ,v #f)) bv)
286           ,(inline-let
287             `(let ((,length>= (lambda (n) (lambda (l) (>= (length l) n))))
288                    (,x ,exp)
289                    (,code (lambda ,gs
290                             ,@(map (lambda (v g) `(set! ,v ,g)) bv gs)
291                             (void)))
292                    ,@bindings
293                    ,@(car eb-errf))
294                ,m))))))
295  ;;;
296  (define pattern-var?
297    (lambda (x)
298      (and (symbol? x)
299           (not (dot-dot-k? x))
300           (not (memq x
301                      '(quasiquote
302                        quote
303                        unquote
304                        unquote-splicing
305                        ?
306                        _
307                        $
308                        =
309                        and
310                        or
311                        not
312                        set!
313                        get!
314                        ...
315                        ___))))))
316  ;;;
317  (define dot-dot-k?
318    (lambda (s)
319      (and (symbol? s)
320           (if (memq s '(... ___))
321               0
322               (let* ((s (symbol->string s))
323                      (n (string-length s)))
324                 (and (<= 3 n)
325                      (memq (string-ref s 0) '(#\. #\_))
326                      (memq (string-ref s 1) '(#\. #\_))
327                      (match:andmap char-numeric? (string->list (substring s 2 n)))
328                      (string->number (substring s 2 n))))))))
329  ;;;
330  (define error-maker
331    (lambda (match-expr)
332      (cond ((eq? match:error-control 'unspecified)
333             (cons '() (lambda (x) `(void))))
334            ((memq match:error-control '(error fail))
335             (cons '() (lambda (x) `(match:error ,x))))
336            ((eq? match:error-control 'match)
337             (let ((errf (gentemp)) (arg (gentemp)))
338               (cons `((,errf (lambda (,arg) (match:error ,arg ',match-expr))))
339                     (lambda (x) `(,errf ,x)))))
340            (else (match:syntax-err
341                   '(unspecified error fail match)
342                   "invalid value for match:error-control, legal values are")))))
343  ;;;
344  (define unreachable
345    (lambda (plist match-expr)
346      (for-each (lambda (x)
347                  (if (not (car (cddddr x)))
348                      (begin (display "Warning: unreachable pattern ")
349                        (display (car x))
350                        (display " in ")
351                        (display match-expr)
352                        (newline))))
353                plist)))
354  ;;;
355  (define validate-pattern
356    (lambda (pattern)
357      (define simple?
358        (lambda (x) (or (string? x) (boolean? x) (char? x) (number? x) (null? x))))
359      (define ordinary
360        (lambda (p)
361          (define cons-ordinaries (lambda (x y) (cons (ordinary x) (ordinary y))))
362          (cond ((or (simple? p) (eq? p '_) (pattern-var? p)) p)
363                ((pair? p)
364                 (case (car p)
365                   ((quote) (if (and (pair? (cdr p))
366                                     (null? (cddr p)))
367                                p
368                                (cons-ordinaries (car p) (cdr p))))
369                   ((?)     (if (and (pair? (cdr p))
370                                     (list? (cddr p)))
371                                `(? ,(cadr p) ,@(map ordinary (cddr p)))
372                                (cons-ordinaries (car p) (cdr p))))
373                   ((=)     (if (and (pair? (cdr p))
374                                     (pair? (cddr p))
375                                     (null? (cdddr p)))
376                                `(= ,(cadr p) ,(ordinary (caddr p)))
377                                (cons-ordinaries (car p) (cdr p))))
378                   ((and)   (if (and (list? (cdr p))
379                                     (pair? (cdr p)))
380                                `(and ,@(map ordinary (cdr p)))
381                                (cons-ordinaries (car p) (cdr p))))
382                   ((or)    (if (and (list? (cdr p))
383                                     (pair? (cdr p)))
384                                `(or ,@(map ordinary (cdr p)))
385                                (cons-ordinaries (car p) (cdr p))))
386                   ((not)   (if (and (list? (cdr p))
387                                     (pair? (cdr p)))
388                                `(not ,@(map ordinary (cdr p)))
389                                (cons-ordinaries (car p) (cdr p))))
390                   (($)     (if (and (pair? (cdr p))
391                                     (symbol? (cadr p))
392                                     (list? (cddr p)))
393                                `($ ,(cadr p) ,@(map ordinary (cddr p)))
394                                (cons-ordinaries (car p) (cdr p))))
395                   ((set!)  (if (and (pair? (cdr p))
396                                     (pattern-var? (cadr p))
397                                     (null? (cddr p)))
398                                p
399                                (cons-ordinaries (car p) (cdr p))))
400                   ((get!)  (if (and (pair? (cdr p))
401                                     (pattern-var? (cadr p))
402                                     (null? (cddr p)))
403                                p
404                                (cons-ordinaries (car p) (cdr p))))
405                   ((quasiquote) (if (and (pair? (cdr p))
406                                          (null? (cddr p)))
407                                     (quasi (cadr p))
408                                     (cons-ordinaries (car p) (cdr p))))
409                   ((unquote unquote-splicing) (cons-ordinaries (car p) (cdr p)))
410                   (else
411                    (if (and (pair? (cdr p))
412                             (dot-dot-k? (cadr p))
413                             (null? (cddr p)))
414                        `(,(ordinary (car p)) ,(cadr p))
415                        (cons-ordinaries (car p) (cdr p))))))
416                ((vector? p) (let* ((pl (vector->list p))
417                                    (rpl (reverse pl)))
418                               (apply vector
419                                      (if (and (not (null? rpl))
420                                               (dot-dot-k? (car rpl)))
421                                          (reverse (cons (car rpl) (map ordinary (cdr rpl))))
422                                          (map ordinary pl)))))
423
424                (else
425                 (match:syntax-err pattern "syntax error in pattern")))))
426      (define quasi
427        (lambda (p)
428          (define cons-quasies (lambda (x y) (cons (quasi x) (quasi y))))
429          (cond ((simple? p) p)
430                ((symbol? p) `',p)
431                ((pair? p)
432                 (if (eq? (car p) 'unquote)
433                     (if (and (pair? (cdr p))
434                              (null? (cddr p)))
435                         (ordinary (cadr p))
436                         (cons-quasies (car p) (cdr p)))
437                     (if (and (pair? (car p))
438                              (eq? (caar p) 'unquote-splicing)
439                              (pair? (cdar p))
440                              (null? (cddar p)))
441                         (if (null? (cdr p))
442                             (ordinary (cadar p))
443                             (append (ordlist (cadar p)) (quasi (cdr p))))
444                         (if (and (pair? (cdr p))
445                                  (dot-dot-k? (cadr p))
446                                  (null? (cddr p)))
447                             `(,(quasi (car p)) ,(cadr p))
448                             (cons-quasies (car p) (cdr p))))))
449                ((vector? p)
450                 (let* ((pl (vector->list p)) (rpl (reverse pl)))
451                   (apply vector
452                          (if (dot-dot-k? (car rpl))
453                              (reverse (cons (car rpl)
454                                             (map quasi (cdr rpl))))
455                              (map ordinary pl)))))
456                (else
457                 (match:syntax-err pattern "syntax error in pattern")))))
458      (define ordlist
459        (lambda (p)
460          (cond ((null? p) '())
461                ((pair? p) (cons (ordinary (car p)) (ordlist (cdr p))))
462                (else (match:syntax-err pattern "invalid use of unquote-splicing in pattern")))))
463
464      (ordinary pattern)))
465  ;;;
466  (define bound
467    (lambda (pattern)
468      (define pred-bodies '())
469      (define bound
470        (lambda (p a k)
471          (cond ((eq? '_ p)
472                 (k p a))
473                ((symbol? p)
474                 (if (memq p a) (match:syntax-err pattern "duplicate variable in pattern"))
475                 (k p (cons p a)))
476                ((and (pair? p) (eq? 'quote (car p)))
477                 (k p a))
478                ((and (pair? p) (eq? '? (car p)))
479                 (cond ((not (null? (cddr p)))
480                        (bound `(and (? ,(cadr p)) ,@(cddr p)) a k))
481                       ((or (not (symbol? (cadr p))) (memq (cadr p) a))
482                        (let ((g (gentemp)))
483                          (set! pred-bodies (cons `(,g ,(cadr p)) pred-bodies))
484                          (k `(? ,g) a)))
485                       (else (k p a))))
486                ((and (pair? p) (eq? '= (car p)))
487                 (cond ((or (not (symbol? (cadr p))) (memq (cadr p) a))
488                        (let ((g (gentemp)))
489                          (set! pred-bodies (cons `(,g ,(cadr p)) pred-bodies))
490                          (bound `(= ,g ,(caddr p)) a k)))
491                       (else (bound (caddr p) a (lambda (p2 a) (k `(= ,(cadr p) ,p2) a))))))
492                ((and (pair? p) (eq? 'and (car p)))
493                 (bound* (cdr p) a (lambda (p a) (k `(and ,@p) a))))
494                ((and (pair? p) (eq? 'or (car p)))
495                 (bound (cadr p) a
496                        (lambda (first-p first-a)
497                          (let or* ((plist (cddr p))
498                                    (k (lambda (plist) (k `(or ,first-p ,@plist) first-a))))
499                            (if (null? plist)
500                                (k plist)
501                                (bound (car plist) a
502                                       (lambda (car-p car-a)
503                                         (if (not (permutation car-a first-a))
504                                             (match:syntax-err pattern "variables of or-pattern differ in"))
505                                         (or* (cdr plist) (lambda (cdr-p) (k (cons car-p cdr-p)))))))))))
506                ((and (pair? p) (eq? 'not (car p)))
507                 (cond ((not (null? (cddr p)))
508                        (bound `(not (or ,@(cdr p))) a k))
509                       (else
510                        (bound (cadr p) a
511                               (lambda (p2 a2)
512                                 (if (not (permutation a a2))
513                                     (match:syntax-err p "no variables allowed in"))
514                                 (k `(not ,p2) a))))))
515                ((and (pair? p)
516                      (pair? (cdr p))
517                      (dot-dot-k? (cadr p)))
518                 (bound (car p) a
519                        (lambda (q b)
520                          (let ((bvars (find-prefix b a)))
521                            (k `(,q ,(cadr p)
522                                  ,bvars
523                                  ,(gentemp)
524                                  ,(gentemp)
525                                  ,(map (lambda (_) (gentemp)) bvars))
526                               b)))))
527                ((and (pair? p) (eq? '$ (car p)))
528                 (bound* (cddr p) a (lambda (p1 a) (k `($ ,(cadr p) ,@p1) a))))
529                ((and (pair? p) (eq? 'set! (car p)))
530                 (if (memq (cadr p) a)
531                     (k p a)
532                     (k p (cons (cadr p) a))))
533                ((and (pair? p) (eq? 'get! (car p)))
534                 (if (memq (cadr p) a)
535                     (k p a)
536                     (k p (cons (cadr p) a))))
537                ((pair? p)
538                 (bound (car p) a
539                        (lambda (car-p a) (bound (cdr p) a (lambda (cdr-p a) (k (cons car-p cdr-p) a))))))
540                ((vector? p)
541                 (boundv (vector->list p) a
542                         (lambda (pl a) (k (list->vector pl) a))))
543                (else (k p a)))))
544      (define boundv
545        (lambda (plist a k)
546          (if (pair? plist)
547              (if (and (pair? (cdr plist))
548                       (dot-dot-k? (cadr plist))
549                       (null? (cddr plist)))
550                  (bound plist a k)
551                  (if (null? plist)
552                      (k plist a)
553                      (bound (car plist) a
554                             (lambda (car-p a) (boundv (cdr plist) a (lambda (cdr-p a) (k (cons car-p cdr-p) a)))))))
555              (if (null? plist)
556                  (k plist a)
557                  (match:error plist)))))
558      (define bound*
559        (lambda (plist a k)
560          (if (null? plist)
561              (k plist a)
562              (bound (car plist) a
563                     (lambda (car-p a) (bound* (cdr plist) a (lambda (cdr-p a) (k (cons car-p cdr-p) a))))))))
564      (define find-prefix
565        (lambda (b a)
566          (if (eq? b a)
567              '()
568              (cons (car b) (find-prefix (cdr b) a)))))
569      (define permutation
570        (lambda (p1 p2)
571          (and (= (length p1) (length p2))
572               (match:andmap (lambda (x1) (memq x1 p2)) p1))))
573
574      (bound pattern '() (lambda (p a) (list p (reverse a) pred-bodies)))))
575  ;;;
576  (define inline-let
577    (lambda (let-exp)
578      (define occ
579        (lambda (x e)
580          (let loop ((e e))
581            (cond ((pair? e) (+ (loop (car e)) (loop (cdr e))))
582                  ((eq? x e) 1)
583                  (else 0)))))
584      (define subst
585        (lambda (e old new)
586          (let loop ((e e))
587            (cond ((pair? e) (cons (loop (car e)) (loop (cdr e))))
588                  ((eq? old e) new)
589                  (else e)))))
590      (define const?
591        (lambda (sexp)
592          (or (symbol? sexp)
593              (boolean? sexp)
594              (string? sexp)
595              (char? sexp)
596              (number? sexp)
597              (null? sexp)
598              (and (pair? sexp)
599                   (eq? (car sexp) 'quote)
600                   (pair? (cdr sexp))
601                   (symbol? (cadr sexp))
602                   (null? (cddr sexp))))))
603      (define isval?
604        (lambda (sexp)
605          (or (const? sexp)
606              (and (pair? sexp)
607                   (memq (car sexp) '(lambda quote match-lambda match-lambda*))))))
608      (define small?
609        (lambda (sexp)
610          (or (const? sexp)
611              (and (pair? sexp)
612                   (eq? (car sexp) 'lambda)
613                   (pair? (cdr sexp))
614                   (pair? (cddr sexp))
615                   (const? (caddr sexp))
616                   (null? (cdddr sexp))))))
617
618      (let loop ((b (cadr let-exp)) (new-b '()) (e (caddr let-exp)))
619        (cond ((null? b)
620               (if (null? new-b)
621                   e
622                   `(let ,(reverse new-b) ,e)))
623              ((isval? (cadr (car b)))
624               (let* ((x (caar b)) (n (occ x e)))
625                 (cond ((= 0 n) (loop (cdr b) new-b e))
626                       ((or (= 1 n) (small? (cadr (car b))))
627                        (loop (cdr b) new-b (subst e x (cadr (car b)))))
628                       (else
629                        (loop (cdr b) (cons (car b) new-b) e)))))
630              (else
631               (loop (cdr b) (cons (car b) new-b) e))))))
632  ;;;
633  (define gen
634    (lambda (x sf plist erract length>= eta)
635      (if (null? plist)
636          (erract x)
637          (let* ((v '())
638                 (val (lambda (x) (cdr (assq x v))))
639                 (fail (lambda (sf)
640                         (gen x sf (cdr plist) erract length>= eta)))
641                 (success (lambda (sf)
642                            (set-car! (cddddr (car plist)) #t)
643                            (let* ((code (cadr (car plist)))
644                                   (bv (caddr (car plist)))
645                                   (fail-sym (cadddr (car plist))))
646                              (if fail-sym
647                                  (let ((ap `(,code ,fail-sym ,@(map val bv))))
648                                    `(call-with-current-continuation
649                                      (lambda (,fail-sym)
650                                        (let ((,fail-sym (lambda () (,fail-sym ,(fail sf)))))
651                                          ,ap))))
652                                  `(,code ,@(map val bv)))))))
653            (let next ((p (caar plist))
654                       (e x)
655                       (sf sf)
656                       (kf fail)
657                       (ks success))
658              (cond ((eq? '_ p) (ks sf))
659                    ((symbol? p)
660                     (set! v (cons (cons p e) v)) (ks sf))
661                    ((null? p)
662                     (emit `(null? ,e) sf kf ks))
663                    ((equal? p ''())
664                     (emit `(null? ,e) sf kf ks))
665                    ((string? p)
666                     (emit `(equal? ,e ,p) sf kf ks))
667                    ((boolean? p)
668                     (emit `(equal? ,e ,p) sf kf ks))
669                    ((char? p)
670                     (emit `(equal? ,e ,p) sf kf ks))
671                    ((number? p)
672                     (emit `(equal? ,e ,p) sf kf ks))
673                    ((and (pair? p) (eq? 'quote (car p)))
674                     (emit `(equal? ,e ,p) sf kf ks))
675                    ((and (pair? p) (eq? '? (car p)))
676                     (let ((tst `(,(cadr p) ,e)))
677                       (emit tst sf kf ks)))
678                    ((and (pair? p) (eq? '= (car p)))
679                     (next (caddr p) `(,(cadr p) ,e) sf kf ks))
680                    ((and (pair? p) (eq? 'and (car p)))
681                     (let loop ((p (cdr p)) (sf sf))
682                       (if (null? p)
683                           (ks sf)
684                           (next (car p) e sf kf (lambda (sf) (loop (cdr p) sf))))))
685                    ((and (pair? p) (eq? 'or (car p)))
686                     (let ((or-v v))
687                       (let loop ((p (cdr p)) (sf sf))
688                         (if (null? p)
689                             (kf sf)
690                             (begin (set! v or-v)
691                               (next (car p) e sf (lambda (sf) (loop (cdr p) sf)) ks))))))
692                    ((and (pair? p) (eq? 'not (car p)))
693                     (next (cadr p) e sf ks kf))
694                    ((and (pair? p) (eq? '$ (car p)))
695                     (let* ((tag (cadr p))
696                            (fields (cdr p))
697                            (rlen (length fields))
698                            (tst `(,(symbol-append tag '?) ,e)))
699                       (emit tst sf kf
700                             (let rloop ((n 1))
701                               (lambda (sf)
702                                 (if (= n rlen)
703                                     (ks sf)
704                                     (next (list-ref fields n)
705                                           `(,(symbol-append tag '- n) ,e)
706                                           sf
707                                           kf
708                                           (rloop (+ 1 n)))))))))
709                    ((and (pair? p) (eq? 'set! (car p)))
710                     (set! v (cons (cons (cadr p) (setter e p)) v))
711                     (ks sf))
712                    ((and (pair? p) (eq? 'get! (car p)))
713                     (set! v (cons (cons (cadr p) (getter e p)) v))
714                     (ks sf))
715                    ((and (pair? p)
716                          (pair? (cdr p))
717                          (dot-dot-k? (cadr p)))
718                     (emit `(list? ,e) sf kf
719                           (lambda (sf)
720                             (let* ((k (dot-dot-k? (cadr p)))
721                                    (ks (lambda (sf)
722                                          (let ((bound (list-ref p  2)))
723                                            (cond ((eq? (car p) '_)
724                                                   (ks sf))
725                                                  ((null? bound)
726                                                   (let* ((ptst (next (car p) eta sf (lambda (sf) #f) (lambda (sf) #t)))
727                                                          (tst (if (and (pair? ptst)
728                                                                        (symbol? (car ptst))
729                                                                        (pair? (cdr ptst))
730                                                                        (eq? eta (cadr ptst))
731                                                                        (null? (cddr ptst)))
732                                                                   (car ptst)
733                                                                   `(lambda (,eta) ,ptst))))
734                                                     (assm `(match:andmap ,tst ,e) (kf sf) (ks sf))))
735                                                  ((and (symbol? (car p))
736                                                        (equal? (list (car p)) bound))
737                                                   (next (car p) e sf kf ks))
738                                                  (else (let* ((gloop (list-ref p 3))
739                                                               (ge (list-ref p 4))
740                                                               (fresh (list-ref p 5))
741                                                               (p1 (next (car p) `(car ,ge) sf kf
742                                                                         (lambda (sf)
743                                                                           `(,gloop
744                                                                              (cdr ,ge)
745                                                                              ,@(map (lambda (b f) `(cons ,(val b) ,f)) bound fresh))))))
746                                                          (set! v (append (map cons bound (map (lambda (x) `(reverse ,x)) fresh)) v))
747                                                          `(let ,gloop ((,ge ,e)
748                                                                        ,@(map (lambda (x) `(,x '())) fresh))
749                                                             (if (null? ,ge)
750                                                                 ,(ks sf)
751                                                                 ,p1)))))))))
752                               (case k
753                                 ((0) (ks sf))
754                                 ((1) (emit `(pair? ,e) sf kf ks))
755                                 (else (emit `((,length>= ,k) ,e) sf kf ks)))))))
756                    ((pair? p) (emit `(pair? ,e) sf kf
757                                     (lambda (sf)
758                                       (next (car p) (add-a e) sf kf
759                                             (lambda (sf) (next (cdr p) (add-d e) sf kf ks))))))
760                    ((and (vector? p)
761                          (>= (vector-length p) 6)
762                          (dot-dot-k? (vector-ref p (- (vector-length p) 5))))
763                     (let* ((vlen (- (vector-length p) 6))
764                            (k (dot-dot-k? (vector-ref p (+ vlen 1))))
765                            (minlen (+ vlen k))
766                            (bound (vector-ref p (+ vlen 2))))
767                       (emit `(vector? ,e) sf kf
768                             (lambda (sf)
769                               (assm `(>= (vector-length ,e) ,minlen)
770                                     (kf sf)
771                                     ((let vloop ((n 0))
772                                        (lambda (sf)
773                                          (cond ((not (= n vlen))
774                                                 (next (vector-ref p n) `(vector-ref ,e ,n) sf kf
775                                                       (vloop (+ 1 n))))
776                                                ((eq? (vector-ref p vlen) '_)
777                                                 (ks sf))
778                                                (else
779                                                 (let* ((gloop (vector-ref p (+ vlen 3)))
780                                                        (ind (vector-ref p (+ vlen 4)))
781                                                        (fresh (vector-ref p (+ vlen 5)))
782                                                        (p1 (next (vector-ref p vlen) `(vector-ref ,e ,ind) sf kf
783                                                                  (lambda (sf)
784                                                                    `(,gloop (- ,ind 1) ,@(map (lambda (b f) `(cons ,(val b) ,f)) bound fresh))))))
785                                                   (set! v (append (map cons bound fresh) v))
786                                                   `(let ,gloop
787                                                      ((,ind (- (vector-length ,e) 1)) ,@(map (lambda (x) `(,x '())) fresh))
788                                                      (if (> ,minlen ,ind)
789                                                          ,(ks sf)
790                                                          ,p1)))))))
791                                      sf))))))
792                    ((vector? p)
793                     (let ((vlen (vector-length p)))
794                       (emit `(vector? ,e) sf kf
795                             (lambda (sf)
796                               (emit `(equal? (vector-length ,e) ,vlen) sf kf
797                                     (let vloop ((n 0))
798                                       (lambda (sf)
799                                         (if (= n vlen)
800                                             (ks sf)
801                                             (next (vector-ref p n) `(vector-ref ,e ,n) sf kf
802                                                   (vloop (+ 1 n)))))))))))
803                    (else
804                     (display "FATAL ERROR IN PATTERN MATCHER")
805                     (newline)
806                     (error #f "THIS NEVER HAPPENS"))))))))
807  ;;;
808  (define emit
809    (lambda (tst sf kf ks)
810      (cond ((in tst sf) (ks sf))
811            ((in `(not ,tst) sf) (kf sf))
812            (else (let* ((e (cadr tst))
813                         (implied (cond ((eq? (car tst) 'equal?)
814                                         (let ((p (caddr tst)))
815                                           (cond ((string? p) `((string? ,e)))
816                                                 ((boolean? p) `((boolean? ,e)))
817                                                 ((char? p) `((char? ,e)))
818                                                 ((number? p) `((number? ,e)))
819                                                 ((and (pair? p) (eq? 'quote (car p))) `((symbol? ,e)))
820                                                 (else '()))))
821                                        ((eq? (car tst) 'null?) `((list? ,e)))
822                                        ((vec-structure? tst) `((vector? ,e)))
823                                        (else '())))
824                         (not-imp (case (car tst)
825                                    ((list?) `((not (null? ,e))))
826                                    (else '())))
827                         (s (ks (cons tst (append implied sf))))
828                         (k (kf (cons `(not ,tst) (append not-imp sf)))))
829                    (assm tst k s))))))
830  ;;;
831  (define assm
832    (lambda (tst f s)
833      (cond ((equal? s f) s)
834            ((and (eq? s #t) (eq? f #f)) tst)
835            ((and (eq? (car tst) 'pair?)
836                  (memq match:error-control '(unspecified fail))
837                  (memq (car f) '(cond match:error))
838                  (guarantees s (cadr tst))) s)
839            ((and (pair? s)
840                  (eq? (car s) 'if)
841                  (equal? (cadddr s) f))
842             (if (eq? (car (cadr s)) 'and)
843                 `(if (and ,tst ,@(cdr (cadr s)))
844                      ,(caddr s)
845                      ,f)
846                 `(if (and ,tst ,(cadr s))
847                      ,(caddr s)
848                      ,f)))
849            ((and (pair? s)
850                  (eq? (car s) 'call-with-current-continuation)
851                  (pair? (cdr s))
852                  (pair? (cadr s))
853                  (eq? (caadr s) 'lambda)
854                  (pair? (cdadr s))
855                  (pair? (cadadr s))
856                  (null? (cdr (cadadr s)))
857                  (pair? (cddadr s))
858                  (pair? (car (cddadr s)))
859                  (eq? (caar (cddadr s)) 'let)
860                  (pair? (cdar (cddadr s)))
861                  (pair? (cadar (cddadr s)))
862                  (pair? (caadar (cddadr s)))
863                  (pair? (cdr (caadar (cddadr s))))
864                  (pair? (cadr (caadar (cddadr s))))
865                  (eq? (caadr (caadar (cddadr s))) 'lambda)
866                  (pair? (cdadr (caadar (cddadr s))))
867                  (null? (cadadr (caadar (cddadr s))))
868                  (pair? (cddadr (caadar (cddadr s))))
869                  (pair? (car (cddadr (caadar (cddadr s)))))
870                  (pair? (cdar (cddadr (caadar (cddadr s)))))
871                  (null? (cddar (cddadr (caadar (cddadr s)))))
872                  (null? (cdr (cddadr (caadar (cddadr s)))))
873                  (null? (cddr (caadar (cddadr s))))
874                  (null? (cdadar (cddadr s)))
875                  (pair? (cddar (cddadr s)))
876                  (null? (cdddar (cddadr s)))
877                  (null? (cdr (cddadr s)))
878                  (null? (cddr s))
879                  (equal? f (cadar (cddadr (caadar (cddadr s))))))
880             (let ((k (car (cadadr s)))
881                   (fail (car (caadar (cddadr s))))
882                   (s2 (caddar (cddadr s))))
883               `(call-with-current-continuation
884                 (lambda (,k)
885                   (let ((,fail (lambda () (,k ,f))))
886                     ,(assm tst `(,fail) s2))))))
887            ((and #f
888                  (pair? s)
889                  (eq? (car s) 'let)
890                  (pair? (cdr s))
891                  (pair? (cadr s))
892                  (pair? (caadr s))
893                  (pair? (cdaadr s))
894                  (pair? (car (cdaadr s)))
895                  (eq? (caar (cdaadr s)) 'lambda)
896                  (pair? (cdar (cdaadr s)))
897                  (null? (cadar (cdaadr s)))
898                  (pair? (cddar (cdaadr s)))
899                  (null? (cdddar (cdaadr s)))
900                  (null? (cdr (cdaadr s)))
901                  (null? (cdadr s))
902                  (pair? (cddr s))
903                  (null? (cdddr s))
904                  (equal? (caddar (cdaadr s)) f))
905             (let ((fail (caaadr s))
906                   (s2 (caddr s)))
907               `(let ((,fail (lambda () ,f)))
908                  ,(assm tst `(,fail) s2))))
909            (else `(if ,tst ,s ,f)))))
910  ;;;
911  (define guarantees
912    (lambda (code x)
913      (let ((a (add-a x)) (d (add-d x)))
914        (let loop ((code code))
915          (cond ((not (pair? code)) #f)
916                ((memq (car code) '(cond match:error)) #t)
917                ((or (equal? code a) (equal? code d)) #t)
918                ((eq? (car code) 'if) (or (loop (cadr code))
919                                          (and (loop (caddr code))
920                                               (loop (cadddr code)))))
921                ((eq? (car code) 'lambda) #f)
922                ((and (eq? (car code) 'let) (symbol? (cadr code))) #f)
923                (else
924                 (or (loop (car code))
925                     (loop (cdr code)))))))))
926  ;;;
927  (define in
928    (lambda (e l)
929      (or (member e l)
930          (and (eq? (car e) 'list?)
931               (or (member `(null? ,(cadr e)) l)
932                   (member `(pair? ,(cadr e)) l)))
933          (and (eq? (car e) 'not)
934               (let* ((srch (cadr e))
935                      (const-class (equal-test? srch)))
936                 (cond (const-class (let mem ((l l))
937                                      (if (null? l)
938                                          #f
939                                          (let ((x (car l)))
940                                            (or (and (equal? (cadr x) (cadr srch))
941                                                     (disjoint? x)
942                                                     (not (equal? const-class (car x))))
943                                                (equal? x `(not (,const-class ,(cadr srch))))
944                                                (and (equal? (cadr x) (cadr srch))
945                                                     (equal-test? x)
946                                                     (not (equal? (caddr srch) (caddr x))))
947                                                (mem (cdr l)))))))
948                       ((disjoint? srch) (let mem ((l l))
949                                           (if (null? l)
950                                               #f
951                                               (let ((x (car l)))
952                                                 (or (and (equal? (cadr x) (cadr srch))
953                                                          (disjoint? x)
954                                                          (not (equal? (car x) (car srch))))
955                                                     (mem (cdr l)))))))
956                       ((eq? (car srch) 'list?) (let mem ((l l))
957                                                  (if (null? l)
958                                                      #f
959                                                      (let ((x (car l)))
960                                                        (or (and (equal? (cadr x) (cadr srch))
961                                                                 (disjoint? x)
962                                                                 (not (memq (car x) '(list? pair? null?))))
963                                                            (mem (cdr l)))))))
964                       ((vec-structure? srch) (let mem ((l l))
965                                                (if (null? l)
966                                                    #f
967                                                    (let ((x (car l)))
968                                                      (or (and (equal? (cadr x) (cadr srch))
969                                                               (or (disjoint? x)
970                                                                   (vec-structure? x))
971                                                               (not (eq? (car x) 'vector?))
972                                                               (not (equal? (car x) (car srch))))
973                                                          (equal? x `(not (vector? ,(cadr srch))))
974                                                          (mem (cdr l)))))))
975                       (else #f)))))))
976  ;;;
977  (define equal-test?
978    (lambda (tst)
979      (and (eq? (car tst) 'equal?)
980           (let ((p (caddr tst)))
981             (cond ((string? p) 'string?)
982                   ((boolean? p) 'boolean?)
983                   ((char? p) 'char?)
984                   ((number? p) 'number?)
985                   ((and (pair? p)
986                         (pair? (cdr p))
987                         (null? (cddr p))
988                         (eq? 'quote (car p))
989                         (symbol? (cadr p))) 'symbol?)
990                   (else #f))))))
991  ;;;
992  (define disjoint?
993    (lambda (tst)
994      (memq (car tst) match:disjoint-predicates)))
995  ;;;
996  (define vec-structure?
997    (lambda (tst)
998      (memq (car tst) match:vector-structures)))
999  ;;;
1000  (define add-a
1001    (lambda (a)
1002      (let ((new (and (pair? a) (assq (car a) c---rs))))
1003        (if new
1004            (cons (cadr new) (cdr a))
1005            `(car ,a)))))
1006  ;;;
1007  (define add-d
1008    (lambda (a)
1009      (let ((new (and (pair? a) (assq (car a) c---rs))))
1010        (if new
1011            (cons (cddr new) (cdr a))
1012            `(cdr ,a)))))
1013  ;;;
1014  (define c---rs
1015    '((car caar . cdar)
1016      (cdr cadr . cddr)
1017      (caar caaar . cdaar)
1018      (cadr caadr . cdadr)
1019      (cdar cadar . cddar)
1020      (cddr caddr . cdddr)
1021      (caaar caaaar . cdaaar)
1022      (caadr caaadr . cdaadr)
1023      (cadar caadar . cdadar)
1024      (caddr caaddr . cdaddr)
1025      (cdaar cadaar . cddaar)
1026      (cdadr cadadr . cddadr)
1027      (cddar caddar . cdddar)
1028      (cdddr cadddr . cddddr)))
1029  ;;;
1030  (define setter
1031    (lambda (e p)
1032      (let ((mk-setter (lambda (s) (symbol-append 'set- s '!))))
1033        (cond ((not (pair? e)) (match:syntax-err p "unnested set! pattern"))
1034              ((eq? (car e) 'vector-ref) `(let ((x ,(cadr e))) (lambda (y) (vector-set! x ,(caddr e) y))))
1035              ((eq? (car e) 'unbox) `(let ((x ,(cadr e))) (lambda (y) (set-box! x y))))
1036              ((eq? (car e) 'car) `(let ((x ,(cadr e))) (lambda (y) (set-car! x y))))
1037              ((eq? (car e) 'cdr) `(let ((x ,(cadr e))) (lambda (y) (set-cdr! x y))))
1038              ((let ((a (assq (car e) get-c---rs)))
1039                 (and a `(let ((x (,(cadr a) ,(cadr e)))) (lambda (y) (,(mk-setter (cddr a)) x y))))))
1040              (else
1041               `(let ((x ,(cadr e))) (lambda (y) (,(mk-setter (car e)) x y))))))))
1042  ;;;
1043  (define getter
1044    (lambda (e p)
1045      (cond ((not (pair? e)) (match:syntax-err p "unnested get! pattern"))
1046            ((eq? (car e) 'vector-ref) `(let ((x ,(cadr e))) (lambda () (vector-ref x ,(caddr e)))))
1047            ((eq? (car e) 'unbox) `(let ((x ,(cadr e))) (lambda () (unbox x))))
1048            ((eq? (car e) 'car) `(let ((x ,(cadr e))) (lambda () (car x))))
1049            ((eq? (car e) 'cdr) `(let ((x ,(cadr e))) (lambda () (cdr x))))
1050            ((let ((a (assq (car e) get-c---rs)))
1051               (and a `(let ((x (,(cadr a) ,(cadr e)))) (lambda () (,(cddr a) x))))))
1052            (else
1053             `(let ((x ,(cadr e))) (lambda () (,(car e) x)))))))
1054  ;;;
1055  (define get-c---rs '((caar car . car)
1056                       (cadr cdr . car)
1057                       (cdar car . cdr)
1058                       (cddr cdr . cdr)
1059                       (caaar caar . car)
1060                       (caadr cadr . car)
1061                       (cadar cdar . car)
1062                       (caddr cddr . car)
1063                       (cdaar caar . cdr)
1064                       (cdadr cadr . cdr)
1065                       (cddar cdar . cdr)
1066                       (cdddr cddr . cdr)
1067                       (caaaar caaar . car)
1068                       (caaadr caadr . car)
1069                       (caadar cadar . car)
1070                       (caaddr caddr . car)
1071                       (cadaar cdaar . car)
1072                       (cadadr cdadr . car)
1073                       (caddar cddar . car)
1074                       (cadddr cdddr . car)
1075                       (cdaaar caaar . cdr)
1076                       (cdaadr caadr . cdr)
1077                       (cdadar cadar . cdr)
1078                       (cdaddr caddr . cdr)
1079                       (cddaar cdaar . cdr)
1080                       (cddadr cdadr . cdr)
1081                       (cdddar cddar . cdr)
1082                       (cddddr cdddr . cdr)))
1083  ;;;
1084  (define symbol-append
1085    (lambda l
1086      (string->symbol (apply string-append (map (lambda (x)
1087                                                  (cond ((symbol? x) (symbol->string x))
1088                                                        ((number? x) (number->string x))
1089                                                        (else x)))
1090                                                l)))))
1091  ;;;
1092  (define rac (lambda (l) (if (null? (cdr l)) (car l) (rac (cdr l)))))
1093  ;;;
1094  (define rdc (lambda (l) (if (null? (cdr l)) '() (cons (car l) (rdc (cdr l))))))
1095  ;;;
1096  (define match:expanders (list genmatch genletrec gendefine pattern-var?))
1097
1098  ;;; end of expanders
1099
1100  (define-macro (match . args)
1101    (cond
1102     ((and (list? args)
1103           (<= 1 (length args))
1104           (match:andmap (lambda (y) (and (list? y) (<= 2 (length y))))
1105                         (cdr args)))
1106      (let* ((exp (car args))
1107             (clauses (cdr args))
1108             (e (if (symbol? exp) exp (gentemp))))
1109        (if (symbol? exp)
1110            (genmatch e clauses `(match ,@args))
1111            `(let ((,e ,exp))
1112               ,(genmatch e clauses `(match ,@args))))))
1113     (else (match:syntax-err `(match ,@args) "syntax error in"))))
1114
1115  (define-macro (match-lambda . args)
1116    (if (and (list? args)
1117             (match:andmap (lambda (arg) (and (pair? arg) (list? (cdr arg)) (pair? (cdr arg))))
1118                           args))
1119        (let ((e (gentemp))) `(lambda (,e) (match ,e ,@args)))
1120        (match:syntax-err `(match-lambda ,@args) "syntax error in")))
1121
1122  (define-macro (match-lambda* . args)
1123    (if (and (list? args)
1124             (match:andmap (lambda (arg) (and (pair? arg) (list? (cdr arg)) (pair? (cdr arg))))
1125                           args))
1126        (let ((e (gentemp))) `(lambda ,e (match ,e ,@args)))
1127        (match:syntax-err `(match-lambda* ,@args)  "syntax error in")))
1128
1129  (define-macro (match-let . args)
1130    (let ((g158 (lambda (pat exp body)
1131                  `(match ,exp (,pat ,@body))))
1132          (g154 (lambda (pat exp body)
1133                  (let ((g (map (lambda (x) (gentemp)) pat))
1134                        (vpattern (list->vector pat)))
1135                    `(let ,(map list g exp)
1136                       (match (vector ,@g) (,vpattern ,@body))))))
1137          (g146 (lambda ()
1138                  (match:syntax-err `(match-let ,@args) "syntax error in")))
1139          (g145 (lambda (p1 e1 p2 e2 body)
1140                  (let ((g1 (gentemp)) (g2 (gentemp)))
1141                    `(let ((,g1 ,e1) (,g2 ,e2))
1142                       (match (cons ,g1 ,g2) ((,p1 . ,p2) ,@body))))))
1143          (g136 (cadddr match:expanders)))
1144      (if (pair? args)
1145          (if (symbol? (car args))
1146              (if (and (pair? (cdr args)) (list? (cadr args)))
1147                  (let g161 ((g162 (cadr args)) (g160 '()) (g159 '()))
1148                    (if (null? g162)
1149                        (if (and (list? (cddr args)) (pair? (cddr args)))
1150                            ((lambda (name pat exp body)
1151                               (if (match:andmap
1152                                    (cadddr match:expanders)
1153                                    pat)
1154                                   `(let ,@args)
1155                                   `(letrec ((,name (match-lambda*
1156                                                     (,pat ,@body))))
1157                                      (,name ,@exp))))
1158                             (car args)
1159                             (reverse g159)
1160                             (reverse g160)
1161                             (cddr args))
1162                            (g146))
1163                        (if (and (pair? (car g162))
1164                                 (pair? (cdar g162))
1165                                 (null? (cddar g162)))
1166                            (g161 (cdr g162)
1167                                  (cons (cadar g162) g160)
1168                                  (cons (caar g162) g159))
1169                            (g146))))
1170                  (g146))
1171              (if (list? (car args))
1172                  (if (match:andmap
1173                       (lambda (g167)
1174                         (if (and (pair? g167)
1175                                  (g136 (car g167))
1176                                  (pair? (cdr g167)))
1177                             (null? (cddr g167))
1178                             #f))
1179                       (car args))
1180                      (if (and (list? (cdr args)) (pair? (cdr args)))
1181                          ((lambda () `(let ,@args)))
1182                          (let g149 ((g150 (car args)) (g148 '()) (g147 '()))
1183                            (if (null? g150)
1184                                (g146)
1185                                (if (and (pair? (car g150))
1186                                         (pair? (cdar g150))
1187                                         (null? (cddar g150)))
1188                                    (g149 (cdr g150)
1189                                          (cons (cadar g150) g148)
1190                                          (cons (caar g150) g147))
1191                                    (g146)))))
1192                      (if (and (pair? (car args))
1193                               (pair? (caar args))
1194                               (pair? (cdaar args))
1195                               (null? (cddaar args)))
1196                          (if (null? (cdar args))
1197                              (if (and (list? (cdr args)) (pair? (cdr args)))
1198                                  (g158 (caaar args)
1199                                        (cadaar args)
1200                                        (cdr args))
1201                                  (let g149 ((g150 (car args))
1202                                             (g148 '())
1203                                             (g147 '()))
1204                                    (if (null? g150)
1205                                        (g146)
1206                                        (if (and (pair? (car g150))
1207                                                 (pair? (cdar g150))
1208                                                 (null? (cddar g150)))
1209                                            (g149 (cdr g150)
1210                                                  (cons (cadar g150) g148)
1211                                                  (cons (caar g150) g147))
1212                                            (g146)))))
1213                              (if (and (pair? (cdar args))
1214                                       (pair? (cadar args))
1215                                       (pair? (cdadar args))
1216                                       (null? (cdr (cdadar args)))
1217                                       (null? (cddar args)))
1218                                  (if (and (list? (cdr args))
1219                                           (pair? (cdr args)))
1220                                      (g145 (caaar args)
1221                                            (cadaar args)
1222                                            (caadar args)
1223                                            (car (cdadar args))
1224                                            (cdr args))
1225                                      (let g149 ((g150 (car args))
1226                                                 (g148 '())
1227                                                 (g147 '()))
1228                                        (if (null? g150)
1229                                            (g146)
1230                                            (if (and (pair? (car g150))
1231                                                     (pair? (cdar g150))
1232                                                     (null? (cddar g150)))
1233                                                (g149 (cdr g150)
1234                                                      (cons (cadar g150)
1235                                                            g148)
1236                                                      (cons (caar g150)
1237                                                            g147))
1238                                                (g146)))))
1239                                  (let g149 ((g150 (car args))
1240                                             (g148 '())
1241                                             (g147 '()))
1242                                    (if (null? g150)
1243                                        (if (and (list? (cdr args))
1244                                                 (pair? (cdr args)))
1245                                            (g154 (reverse g147)
1246                                                  (reverse g148)
1247                                                  (cdr args))
1248                                            (g146))
1249                                        (if (and (pair? (car g150))
1250                                                 (pair? (cdar g150))
1251                                                 (null? (cddar g150)))
1252                                            (g149 (cdr g150)
1253                                                  (cons (cadar g150) g148)
1254                                                  (cons (caar g150) g147))
1255                                            (g146))))))
1256                          (let g149 ((g150 (car args)) (g148 '()) (g147 '()))
1257                            (if (null? g150)
1258                                (if (and (list? (cdr args))
1259                                         (pair? (cdr args)))
1260                                    (g154 (reverse g147)
1261                                          (reverse g148)
1262                                          (cdr args))
1263                                    (g146))
1264                                (if (and (pair? (car g150))
1265                                         (pair? (cdar g150))
1266                                         (null? (cddar g150)))
1267                                    (g149 (cdr g150)
1268                                          (cons (cadar g150) g148)
1269                                          (cons (caar g150) g147))
1270                                    (g146))))))
1271                  (if (pair? (car args))
1272                      (if (and (pair? (caar args))
1273                               (pair? (cdaar args))
1274                               (null? (cddaar args)))
1275                          (if (null? (cdar args))
1276                              (if (and (list? (cdr args)) (pair? (cdr args)))
1277                                  (g158 (caaar args)
1278                                        (cadaar args)
1279                                        (cdr args))
1280                                  (let g149 ((g150 (car args))
1281                                             (g148 '())
1282                                             (g147 '()))
1283                                    (if (null? g150)
1284                                        (g146)
1285                                        (if (and (pair? (car g150))
1286                                                 (pair? (cdar g150))
1287                                                 (null? (cddar g150)))
1288                                            (g149 (cdr g150)
1289                                                  (cons (cadar g150) g148)
1290                                                  (cons (caar g150) g147))
1291                                            (g146)))))
1292                              (if (and (pair? (cdar args))
1293                                       (pair? (cadar args))
1294                                       (pair? (cdadar args))
1295                                       (null? (cdr (cdadar args)))
1296                                       (null? (cddar args)))
1297                                  (if (and (list? (cdr args))
1298                                           (pair? (cdr args)))
1299                                      (g145 (caaar args)
1300                                            (cadaar args)
1301                                            (caadar args)
1302                                            (car (cdadar args))
1303                                            (cdr args))
1304                                      (let g149 ((g150 (car args))
1305                                                 (g148 '())
1306                                                 (g147 '()))
1307                                        (if (null? g150)
1308                                            (g146)
1309                                            (if (and (pair? (car g150))
1310                                                     (pair? (cdar g150))
1311                                                     (null? (cddar g150)))
1312                                                (g149 (cdr g150)
1313                                                      (cons (cadar g150)
1314                                                            g148)
1315                                                      (cons (caar g150)
1316                                                            g147))
1317                                                (g146)))))
1318                                  (let g149 ((g150 (car args))
1319                                             (g148 '())
1320                                             (g147 '()))
1321                                    (if (null? g150)
1322                                        (if (and (list? (cdr args))
1323                                                 (pair? (cdr args)))
1324                                            (g154 (reverse g147)
1325                                                  (reverse g148)
1326                                                  (cdr args))
1327                                            (g146))
1328                                        (if (and (pair? (car g150))
1329                                                 (pair? (cdar g150))
1330                                                 (null? (cddar g150)))
1331                                            (g149 (cdr g150)
1332                                                  (cons (cadar g150) g148)
1333                                                  (cons (caar g150) g147))
1334                                            (g146))))))
1335                          (let g149 ((g150 (car args)) (g148 '()) (g147 '()))
1336                            (if (null? g150)
1337                                (if (and (list? (cdr args))
1338                                         (pair? (cdr args)))
1339                                    (g154 (reverse g147)
1340                                          (reverse g148)
1341                                          (cdr args))
1342                                    (g146))
1343                                (if (and (pair? (car g150))
1344                                         (pair? (cdar g150))
1345                                         (null? (cddar g150)))
1346                                    (g149 (cdr g150)
1347                                          (cons (cadar g150) g148)
1348                                          (cons (caar g150) g147))
1349                                    (g146)))))
1350                      (g146))))
1351          (g146))))
1352  (define-macro (match-let* . args)
1353    (let ((g176 (lambda ()
1354                  (match:syntax-err `(match-let* ,@args) "syntax error in"))))
1355      (if (pair? args)
1356          (if (null? (car args))
1357              (if (and (list? (cdr args)) (pair? (cdr args)))
1358                  ((lambda (body) `(let* ,@args)) (cdr args))
1359                  (g176))
1360              (if (and (pair? (car args))
1361                       (pair? (caar args))
1362                       (pair? (cdaar args))
1363                       (null? (cddaar args))
1364                       (list? (cdar args))
1365                       (list? (cdr args))
1366                       (pair? (cdr args)))
1367                  ((lambda (pat exp rest body)
1368                     (if ((cadddr match:expanders) pat)
1369                         `(let ((,pat ,exp)) (match-let* ,rest ,@body))
1370                         `(match ,exp (,pat (match-let* ,rest ,@body)))))
1371                   (caaar args)
1372                   (cadaar args)
1373                   (cdar args)
1374                   (cdr args))
1375                  (g176)))
1376          (g176))))
1377  (define-macro (match-letrec . args)
1378    (let ((g200 (cadddr match:expanders))
1379          (g199 (lambda (p1 e1 p2 e2 body)
1380                  `(match-letrec (((,p1 . ,p2) (cons ,e1 ,e2))) ,@body)))
1381          (g195 (lambda ()
1382                  (match:syntax-err
1383                   `(match-letrec ,@args)
1384                   "syntax error in")))
1385          (g194 (lambda (pat exp body)
1386                  `(match-letrec
1387                    ((,(list->vector pat) (vector ,@exp)))
1388                    ,@body)))
1389          (g186 (lambda (pat exp body)
1390                  ((cadr match:expanders)
1391                   pat
1392                   exp
1393                   body
1394                   `(match-letrec ((,pat ,exp)) ,@body)))))
1395      (if (pair? args)
1396          (if (list? (car args))
1397              (if (match:andmap
1398                   (lambda (g206)
1399                     (if (and (pair? g206)
1400                              (g200 (car g206))
1401                              (pair? (cdr g206)))
1402                         (null? (cddr g206))
1403                         #f))
1404                   (car args))
1405                  (if (and (list? (cdr args)) (pair? (cdr args)))
1406                      ((lambda () `(letrec ,@args)))
1407                      (let g189 ((g190 (car args)) (g188 '()) (g187 '()))
1408                        (if (null? g190)
1409                            (g195)
1410                            (if (and (pair? (car g190))
1411                                     (pair? (cdar g190))
1412                                     (null? (cddar g190)))
1413                                (g189 (cdr g190)
1414                                      (cons (cadar g190) g188)
1415                                      (cons (caar g190) g187))
1416                                (g195)))))
1417                  (if (and (pair? (car args))
1418                           (pair? (caar args))
1419                           (pair? (cdaar args))
1420                           (null? (cddaar args)))
1421                      (if (null? (cdar args))
1422                          (if (and (list? (cdr args)) (pair? (cdr args)))
1423                              (g186 (caaar args) (cadaar args) (cdr args))
1424                              (let g189 ((g190 (car args))
1425                                         (g188 '())
1426                                         (g187 '()))
1427                                (if (null? g190)
1428                                    (g195)
1429                                    (if (and (pair? (car g190))
1430                                             (pair? (cdar g190))
1431                                             (null? (cddar g190)))
1432                                        (g189 (cdr g190)
1433                                              (cons (cadar g190) g188)
1434                                              (cons (caar g190) g187))
1435                                        (g195)))))
1436                          (if (and (pair? (cdar args))
1437                                   (pair? (cadar args))
1438                                   (pair? (cdadar args))
1439                                   (null? (cdr (cdadar args)))
1440                                   (null? (cddar args)))
1441                              (if (and (list? (cdr args)) (pair? (cdr args)))
1442                                  (g199 (caaar args)
1443                                        (cadaar args)
1444                                        (caadar args)
1445                                        (car (cdadar args))
1446                                        (cdr args))
1447                                  (let g189 ((g190 (car args))
1448                                             (g188 '())
1449                                             (g187 '()))
1450                                    (if (null? g190)
1451                                        (g195)
1452                                        (if (and (pair? (car g190))
1453                                                 (pair? (cdar g190))
1454                                                 (null? (cddar g190)))
1455                                            (g189 (cdr g190)
1456                                                  (cons (cadar g190) g188)
1457                                                  (cons (caar g190) g187))
1458                                            (g195)))))
1459                              (let g189 ((g190 (car args))
1460                                         (g188 '())
1461                                         (g187 '()))
1462                                (if (null? g190)
1463                                    (if (and (list? (cdr args))
1464                                             (pair? (cdr args)))
1465                                        (g194 (reverse g187)
1466                                              (reverse g188)
1467                                              (cdr args))
1468                                        (g195))
1469                                    (if (and (pair? (car g190))
1470                                             (pair? (cdar g190))
1471                                             (null? (cddar g190)))
1472                                        (g189 (cdr g190)
1473                                              (cons (cadar g190) g188)
1474                                              (cons (caar g190) g187))
1475                                        (g195))))))
1476                      (let g189 ((g190 (car args)) (g188 '()) (g187 '()))
1477                        (if (null? g190)
1478                            (if (and (list? (cdr args)) (pair? (cdr args)))
1479                                (g194 (reverse g187)
1480                                      (reverse g188)
1481                                      (cdr args))
1482                                (g195))
1483                            (if (and (pair? (car g190))
1484                                     (pair? (cdar g190))
1485                                     (null? (cddar g190)))
1486                                (g189 (cdr g190)
1487                                      (cons (cadar g190) g188)
1488                                      (cons (caar g190) g187))
1489                                (g195))))))
1490              (if (pair? (car args))
1491                  (if (and (pair? (caar args))
1492                           (pair? (cdaar args))
1493                           (null? (cddaar args)))
1494                      (if (null? (cdar args))
1495                          (if (and (list? (cdr args)) (pair? (cdr args)))
1496                              (g186 (caaar args) (cadaar args) (cdr args))
1497                              (let g189 ((g190 (car args))
1498                                         (g188 '())
1499                                         (g187 '()))
1500                                (if (null? g190)
1501                                    (g195)
1502                                    (if (and (pair? (car g190))
1503                                             (pair? (cdar g190))
1504                                             (null? (cddar g190)))
1505                                        (g189 (cdr g190)
1506                                              (cons (cadar g190) g188)
1507                                              (cons (caar g190) g187))
1508                                        (g195)))))
1509                          (if (and (pair? (cdar args))
1510                                   (pair? (cadar args))
1511                                   (pair? (cdadar args))
1512                                   (null? (cdr (cdadar args)))
1513                                   (null? (cddar args)))
1514                              (if (and (list? (cdr args)) (pair? (cdr args)))
1515                                  (g199 (caaar args)
1516                                        (cadaar args)
1517                                        (caadar args)
1518                                        (car (cdadar args))
1519                                        (cdr args))
1520                                  (let g189 ((g190 (car args))
1521                                             (g188 '())
1522                                             (g187 '()))
1523                                    (if (null? g190)
1524                                        (g195)
1525                                        (if (and (pair? (car g190))
1526                                                 (pair? (cdar g190))
1527                                                 (null? (cddar g190)))
1528                                            (g189 (cdr g190)
1529                                                  (cons (cadar g190) g188)
1530                                                  (cons (caar g190) g187))
1531                                            (g195)))))
1532                              (let g189 ((g190 (car args))
1533                                         (g188 '())
1534                                         (g187 '()))
1535                                (if (null? g190)
1536                                    (if (and (list? (cdr args))
1537                                             (pair? (cdr args)))
1538                                        (g194 (reverse g187)
1539                                              (reverse g188)
1540                                              (cdr args))
1541                                        (g195))
1542                                    (if (and (pair? (car g190))
1543                                             (pair? (cdar g190))
1544                                             (null? (cddar g190)))
1545                                        (g189 (cdr g190)
1546                                              (cons (cadar g190) g188)
1547                                              (cons (caar g190) g187))
1548                                        (g195))))))
1549                      (let g189 ((g190 (car args)) (g188 '()) (g187 '()))
1550                        (if (null? g190)
1551                            (if (and (list? (cdr args)) (pair? (cdr args)))
1552                                (g194 (reverse g187)
1553                                      (reverse g188)
1554                                      (cdr args))
1555                                (g195))
1556                            (if (and (pair? (car g190))
1557                                     (pair? (cdar g190))
1558                                     (null? (cddar g190)))
1559                                (g189 (cdr g190)
1560                                      (cons (cadar g190) g188)
1561                                      (cons (caar g190) g187))
1562                                (g195)))))
1563                  (g195)))
1564          (g195))))
1565  (define-macro (match-define . args)
1566    (let ((g210 (cadddr match:expanders))
1567          (g209 (lambda ()
1568                  (match:syntax-err
1569                   `(match-define ,@args)
1570                   "syntax error in"))))
1571      (if (pair? args)
1572          (if (g210 (car args))
1573              (if (and (pair? (cdr args)) (null? (cddr args)))
1574                  ((lambda () `(begin (define ,@args))))
1575                  (g209))
1576              (if (and (pair? (cdr args)) (null? (cddr args)))
1577                  ((lambda (pat exp)
1578                     ((caddr match:expanders)
1579                      pat
1580                      exp
1581                      `(match-define ,@args)))
1582                   (car args)
1583                   (cadr args))
1584                  (g209)))
1585          (g209))))
1586
1587  (define match:runtime-structures #f)
1588
1589  #|
1590  (define match:set-runtime-structures
1591    (lambda (v) (set! match:runtime-structures v)))
1592  (define match:primitive-vector? vector?)
1593  (define-macro (defstruct . args)
1594    (let ((field? (lambda (x)
1595                    (if (symbol? x)
1596                        ((lambda () #t))
1597                        (if (and (pair? x)
1598                                 (symbol? (car x))
1599                                 (pair? (cdr x))
1600                                 (symbol? (cadr x))
1601                                 (null? (cddr x)))
1602                            ((lambda () #t))
1603                            ((lambda () #f))))))
1604          (selector-name (lambda (x)
1605                           (if (symbol? x)
1606                               ((lambda () x))
1607                               (if (and (pair? x)
1608                                        (symbol? (car x))
1609                                        (pair? (cdr x))
1610                                        (null? (cddr x)))
1611                                   ((lambda (s) s) (car x))
1612                                   (match:error x)))))
1613          (mutator-name (lambda (x)
1614                          (if (symbol? x)
1615                              ((lambda () #f))
1616                              (if (and (pair? x)
1617                                       (pair? (cdr x))
1618                                       (symbol? (cadr x))
1619                                       (null? (cddr x)))
1620                                  ((lambda (s) s) (cadr x))
1621                                  (match:error x)))))
1622          (filter-map-with-index (lambda (f l)
1623                                   (letrec ((mapi (lambda (l i)
1624                                                    (cond
1625                                                     ((null? l) '())
1626                                                     ((f (car l) i) =>
1627                                                      (lambda (x)
1628                                                        (cons x
1629                                                              (mapi (cdr l)
1630                                                                    (+ 1
1631                                                                       i)))))
1632                                                     (else (mapi (cdr l)
1633                                                                 (+ 1 i)))))))
1634                                     (mapi l 1)))))
1635      (let ((g227 (lambda ()
1636                    (match:syntax-err `(defstruct ,@args) "syntax error in"))))
1637        (if (and (pair? args)
1638                 (symbol? (car args))
1639                 (pair? (cdr args))
1640                 (symbol? (cadr args))
1641                 (pair? (cddr args))
1642                 (symbol? (caddr args))
1643                 (list? (cdddr args)))
1644            (let g229 ((g230 (cdddr args)) (g228 '()))
1645              (if (null? g230)
1646                  ((lambda (name constructor predicate fields)
1647                     (let* ((selectors (map selector-name fields))
1648                            (mutators (map mutator-name fields))
1649                            (tag (if match:runtime-structures
1650                                     (gentemp)
1651                                     `',(match:make-structure-tag name)))
1652                            (vectorP (cond
1653                                      ((eq? match:structure-control
1654                                            'disjoint) 'match:primitive-vector?)
1655                                      ((eq? match:structure-control 'vector) 'vector?))))
1656                       (cond
1657                        ((eq? match:structure-control 'disjoint) (if (eq? vector?
1658                                                                          match:primitive-vector?)
1659                                                                     (set! vector?
1660                                                                           (lambda (v)
1661                                                                             (and (match:primitive-vector?
1662                                                                                   v)
1663                                                                                  (or (zero?
1664                                                                                       (vector-length
1665                                                                                        v))
1666                                                                                      (not (symbol?
1667                                                                                            (vector-ref
1668                                                                                             v
1669                                                                                             0)))
1670                                                                                      (not (match:structure?
1671                                                                                            (vector-ref
1672                                                                                             v
1673                                                                                             0))))))))
1674                         (if (not (memq predicate
1675                                        match:disjoint-predicates))
1676                             (set! match:disjoint-predicates
1677                                   (cons predicate match:disjoint-predicates))))
1678                        ((eq? match:structure-control 'vector) (if (not (memq predicate
1679                                                                              match:vector-structures))
1680                                                                   (set! match:vector-structures
1681                                                                         (cons predicate
1682                                                                               match:vector-structures))))
1683                        (else (match:syntax-err
1684                               '(vector disjoint)
1685                               "invalid value for match:structure-control, legal values are")))
1686                       `(begin ,@(if match:runtime-structures
1687                                     `((define ,tag
1688                                         (match:make-structure-tag ',name)))
1689                                     '())
1690                          (define ,constructor
1691                            (lambda ,selectors
1692                              (vector ,tag ,@selectors)))
1693                          (define ,predicate
1694                            (lambda (obj)
1695                              (and (,vectorP obj)
1696                                   (= (vector-length obj)
1697                                      ,(+ 1 (length selectors)))
1698                                   (eq? (vector-ref obj 0) ,tag))))
1699                          ,@(filter-map-with-index
1700                             (lambda (n i)
1701                               `(define ,n
1702                                  (lambda (obj) (vector-ref obj ,i))))
1703                             selectors)
1704                          ,@(filter-map-with-index
1705                             (lambda (n i)
1706                               (and n
1707                                    `(define ,n
1708                                       (lambda (obj newval)
1709                                         (vector-set!
1710                                          obj
1711                                          ,i
1712                                          newval)))))
1713                             mutators))))
1714                   (car args)
1715                   (cadr args)
1716                   (caddr args)
1717                   (reverse g228))
1718                  (if (field? (car g230))
1719                      (g229 (cdr g230) (cons (car g230) g228))
1720                      (g227))))
1721            (g227)))))
1722  (define-macro (define-structure . args)
1723    (let ((g242 (lambda ()
1724                  (match:syntax-err
1725                   `(define-structure ,@args)
1726                   "syntax error in"))))
1727      (if (and (pair? args)
1728               (pair? (car args))
1729               (list? (cdar args)))
1730          (if (null? (cdr args))
1731              ((lambda (name id1) `(define-structure (,name ,@id1) ()))
1732               (caar args)
1733               (cdar args))
1734              (if (and (pair? (cdr args)) (list? (cadr args)))
1735                  (let g239 ((g240 (cadr args)) (g238 '()) (g237 '()))
1736                    (if (null? g240)
1737                        (if (null? (cddr args))
1738                            ((lambda (name id1 id2 val)
1739                               (let ((mk-id (lambda (id)
1740                                              (if (and (pair? id)
1741                                                       (equal? (car id) '@)
1742                                                       (pair? (cdr id))
1743                                                       (symbol? (cadr id))
1744                                                       (null? (cddr id)))
1745                                                  ((lambda (x) x) (cadr id))
1746                                                  ((lambda () `(! ,id)))))))
1747                                 `(define-const-structure
1748                                   (,name ,@(map mk-id id1))
1749                                   ,(map (lambda (id v) `(,(mk-id id) ,v))
1750                                         id2
1751                                         val))))
1752                             (caar args)
1753                             (cdar args)
1754                             (reverse g237)
1755                             (reverse g238))
1756                            (g242))
1757                        (if (and (pair? (car g240))
1758                                 (pair? (cdar g240))
1759                                 (null? (cddar g240)))
1760                            (g239 (cdr g240)
1761                                  (cons (cadar g240) g238)
1762                                  (cons (caar g240) g237))
1763                            (g242))))
1764                  (g242)))
1765          (g242))))
1766  (define-macro (define-const-structure . args)
1767    (let ((field? (lambda (id)
1768                    (if (symbol? id)
1769                        ((lambda () #t))
1770                        (if (and (pair? id)
1771                                 (equal? (car id) '!)
1772                                 (pair? (cdr id))
1773                                 (symbol? (cadr id))
1774                                 (null? (cddr id)))
1775                            ((lambda () #t))
1776                            ((lambda () #f))))))
1777          (field-name (lambda (x) (if (symbol? x) x (cadr x))))
1778          (has-mutator? (lambda (x) (not (symbol? x))))
1779          (filter-map-with-index (lambda (f l)
1780                                   (letrec ((mapi (lambda (l i)
1781                                                    (cond
1782                                                     ((null? l) '())
1783                                                     ((f (car l) i) =>
1784                                                      (lambda (x)
1785                                                        (cons x
1786                                                              (mapi (cdr l)
1787                                                                    (+ 1
1788                                                                       i)))))
1789                                                     (else (mapi (cdr l)
1790                                                                 (+ 1 i)))))))
1791                                     (mapi l 1))))
1792          (symbol-append (lambda l
1793                           (string->symbol
1794                            (apply
1795                             string-append
1796                             (map (lambda (x)
1797                                    (cond
1798                                     ((symbol? x) (symbol->string x))
1799                                     ((number? x) (number->string x))
1800                                     (else x)))
1801                                  l))))))
1802      (let ((g266 (lambda ()
1803                    (match:syntax-err
1804                     `(define-const-structure ,@args)
1805                     "syntax error in"))))
1806        (if (and (pair? args)
1807                 (pair? (car args))
1808                 (list? (cdar args)))
1809            (if (null? (cdr args))
1810                ((lambda (name id1)
1811                   `(define-const-structure (,name ,@id1) ()))
1812                 (caar args)
1813                 (cdar args))
1814                (if (symbol? (caar args))
1815                    (let g259 ((g260 (cdar args)) (g258 '()))
1816                      (if (null? g260)
1817                          (if (and (pair? (cdr args)) (list? (cadr args)))
1818                              (let g263 ((g264 (cadr args))
1819                                         (g262 '())
1820                                         (g261 '()))
1821                                (if (null? g264)
1822                                    (if (null? (cddr args))
1823                                        ((lambda (name id1 id2 val)
1824                                           (let* ((id1id2 (append id1 id2))
1825                                                  (raw-constructor (symbol-append
1826                                                                    'make-raw-
1827                                                                    name))
1828                                                  (constructor (symbol-append
1829                                                                'make-
1830                                                                name))
1831                                                  (predicate (symbol-append
1832                                                              name
1833                                                              '?)))
1834                                             `(begin (defstruct
1835                                                      ,name
1836                                                      ,raw-constructor
1837                                                      ,predicate
1838                                                      ,@(filter-map-with-index
1839                                                         (lambda (arg i)
1840                                                           (if (has-mutator?
1841                                                                arg)
1842                                                               `(,(symbol-append
1843                                                                   name
1844                                                                   '-
1845                                                                   i)
1846                                                                  ,(symbol-append
1847                                                                    'set-
1848                                                                    name
1849                                                                    '-
1850                                                                    i
1851                                                                    '!))
1852                                                               (symbol-append
1853                                                                name
1854                                                                '-
1855                                                                i)))
1856                                                         id1id2))
1857                                                ,(let* ((make-fresh (lambda (x)
1858                                                                      (if (eq? '_
1859                                                                               x)
1860                                                                          (gentemp)
1861                                                                          x)))
1862                                                        (names1 (map make-fresh
1863                                                                     (map field-name
1864                                                                          id1)))
1865                                                        (names2 (map make-fresh
1866                                                                     (map field-name
1867                                                                          id2))))
1868                                                   `(define ,constructor
1869                                                      (lambda ,names1
1870                                                        (let* ,(map list
1871                                                                    names2
1872                                                                    val)
1873                                                          (,raw-constructor
1874                                                            ,@names1
1875                                                            ,@names2)))))
1876                                                ,@(filter-map-with-index
1877                                                   (lambda (field i)
1878                                                     (if (eq? (field-name
1879                                                               field)
1880                                                              '_)
1881                                                         #f
1882                                                         `(define ,(symbol-append
1883                                                                    name
1884                                                                    '-
1885                                                                    (field-name
1886                                                                     field))
1887                                                            ,(symbol-append
1888                                                              name
1889                                                              '-
1890                                                              i))))
1891                                                   id1id2)
1892                                                ,@(filter-map-with-index
1893                                                   (lambda (field i)
1894                                                     (if (or (eq? (field-name
1895                                                                   field)
1896                                                                  '_)
1897                                                             (not (has-mutator?
1898                                                                   field)))
1899                                                         #f
1900                                                         `(define ,(symbol-append
1901                                                                    'set-
1902                                                                    name
1903                                                                    '-
1904                                                                    (field-name
1905                                                                     field)
1906                                                                    '!)
1907                                                            ,(symbol-append
1908                                                              'set-
1909                                                              name
1910                                                              '-
1911                                                              i
1912                                                              '!))))
1913                                                   id1id2))))
1914                                         (caar args)
1915                                         (reverse g258)
1916                                         (reverse g261)
1917                                         (reverse g262))
1918                                        (g266))
1919                                    (if (and (pair? (car g264))
1920                                             (field? (caar g264))
1921                                             (pair? (cdar g264))
1922                                             (null? (cddar g264)))
1923                                        (g263 (cdr g264)
1924                                              (cons (cadar g264) g262)
1925                                              (cons (caar g264) g261))
1926                                        (g266))))
1927                              (g266))
1928                          (if (field? (car g260))
1929                              (g259 (cdr g260) (cons (car g260) g258))
1930                              (g266))))
1931                    (g266)))
1932            (g266)))))
1933  |#
1934
1935
1936  ) ; [end]
1937