Fixes bug 181105: syntax pattern variable list length mismatch error
is obscure
This commit is contained in:
parent
62765c2885
commit
4444496609
Binary file not shown.
|
@ -1 +1 @@
|
|||
1334
|
||||
1335
|
||||
|
|
|
@ -1382,6 +1382,7 @@
|
|||
[make-i/o-would-block-condition i]
|
||||
[i/o-would-block-condition? i]
|
||||
[i/o-would-block-port i]
|
||||
[ellipsis-map ]
|
||||
))
|
||||
|
||||
(define (macro-identifier? x)
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
syntax-violation
|
||||
syntax->datum make-variable-transformer
|
||||
eval-r6rs-top-level boot-library-expand eval-top-level
|
||||
null-environment scheme-report-environment)
|
||||
null-environment scheme-report-environment ellipsis-map)
|
||||
(import
|
||||
(except (rnrs)
|
||||
environment environment? identifier?
|
||||
|
@ -2226,149 +2226,164 @@
|
|||
(build-lambda no-source (list x) body)
|
||||
(list (chi-expr expr r mr)))))))))))
|
||||
|
||||
(define syntax-transformer
|
||||
(let ()
|
||||
(define gen-syntax
|
||||
(lambda (src e r maps ellipsis? vec?)
|
||||
(syntax-match e ()
|
||||
(dots (ellipsis? dots)
|
||||
(stx-error src "misplaced ellipsis in syntax form"))
|
||||
(id (id? id)
|
||||
(let* ((label (id->label e))
|
||||
(b (label->binding label r)))
|
||||
(if (eq? (binding-type b) 'syntax)
|
||||
(let-values (((var maps)
|
||||
(let ((var.lev (binding-value b)))
|
||||
(gen-ref src (car var.lev) (cdr var.lev) maps))))
|
||||
(values (list 'ref var) maps))
|
||||
(values (list 'quote e) maps))))
|
||||
((dots e) (ellipsis? dots)
|
||||
(if vec?
|
||||
(stx-error src "misplaced ellipsis in syntax form")
|
||||
(gen-syntax src e r maps (lambda (x) #f) #f)))
|
||||
((x dots . y) (ellipsis? dots)
|
||||
(let f ((y y)
|
||||
(k (lambda (maps)
|
||||
(let-values (((x maps)
|
||||
(gen-syntax src x r
|
||||
(cons '() maps) ellipsis? #f)))
|
||||
(if (null? (car maps))
|
||||
(stx-error src
|
||||
"extra ellipsis in syntax form")
|
||||
(values (gen-map x (car maps)) (cdr maps)))))))
|
||||
(syntax-match y ()
|
||||
(() (k maps))
|
||||
((dots . y) (ellipsis? dots)
|
||||
(f y
|
||||
(lambda (maps)
|
||||
(let-values (((x maps) (k (cons '() maps))))
|
||||
(if (null? (car maps))
|
||||
(stx-error src "extra ellipsis in syntax form")
|
||||
(values (gen-mappend x (car maps)) (cdr maps)))))))
|
||||
(_
|
||||
(let-values (((y maps)
|
||||
(gen-syntax src y r maps ellipsis? vec?)))
|
||||
(let-values (((x maps) (k maps)))
|
||||
(values (gen-append x y) maps)))))))
|
||||
((x . y)
|
||||
(let-values (((xnew maps)
|
||||
(gen-syntax src x r maps ellipsis? #f)))
|
||||
(let-values (((ynew maps)
|
||||
(gen-syntax src y r maps ellipsis? vec?)))
|
||||
(values (gen-cons e x y xnew ynew) maps))))
|
||||
(#(ls ...)
|
||||
(let-values (((lsnew maps)
|
||||
(gen-syntax src ls r maps ellipsis? #t)))
|
||||
(values (gen-vector e ls lsnew) maps)))
|
||||
(_ (values `(quote ,e) maps)))))
|
||||
(define gen-ref
|
||||
(lambda (src var level maps)
|
||||
(if (= level 0)
|
||||
(values var maps)
|
||||
(if (null? maps)
|
||||
(stx-error src "missing ellipsis in syntax form")
|
||||
(let-values (((outer-var outer-maps)
|
||||
(gen-ref src var (- level 1) (cdr maps))))
|
||||
(cond
|
||||
((assq outer-var (car maps)) =>
|
||||
(lambda (b) (values (cdr b) maps)))
|
||||
(else
|
||||
(let ((inner-var (gen-lexical 'tmp)))
|
||||
(values
|
||||
inner-var
|
||||
(cons
|
||||
(cons (cons outer-var inner-var) (car maps))
|
||||
outer-maps))))))))))
|
||||
(define gen-append
|
||||
(lambda (x y)
|
||||
(if (equal? y '(quote ())) x `(append ,x ,y))))
|
||||
(define gen-mappend
|
||||
(lambda (e map-env)
|
||||
`(apply (primitive append) ,(gen-map e map-env))))
|
||||
(define gen-map
|
||||
(lambda (e map-env)
|
||||
(let ((formals (map cdr map-env))
|
||||
(actuals (map (lambda (x) `(ref ,(car x))) map-env)))
|
||||
(cond
|
||||
; identity map equivalence:
|
||||
; (map (lambda (x) x) y) == y
|
||||
((eq? (car e) 'ref)
|
||||
(car actuals))
|
||||
; eta map equivalence:
|
||||
; (map (lambda (x ...) (f x ...)) y ...) == (map f y ...)
|
||||
((for-all
|
||||
(lambda (x) (and (eq? (car x) 'ref) (memq (cadr x) formals)))
|
||||
(cdr e))
|
||||
(let ((args (map (let ((r (map cons formals actuals)))
|
||||
(lambda (x) (cdr (assq (cadr x) r))))
|
||||
(cdr e))))
|
||||
`(map (primitive ,(car e)) . ,args)))
|
||||
(else (cons* 'map (list 'lambda formals e) actuals))))))
|
||||
(define gen-cons
|
||||
(lambda (e x y xnew ynew)
|
||||
(case (car ynew)
|
||||
((quote)
|
||||
(if (eq? (car xnew) 'quote)
|
||||
(let ((xnew (cadr xnew)) (ynew (cadr ynew)))
|
||||
(if (and (eq? xnew x) (eq? ynew y))
|
||||
`(quote ,e)
|
||||
`(quote ,(cons xnew ynew))))
|
||||
(if (null? (cadr ynew))
|
||||
`(list ,xnew)
|
||||
`(cons ,xnew ,ynew))))
|
||||
((list) `(list ,xnew . ,(cdr ynew)))
|
||||
(else `(cons ,xnew ,ynew)))))
|
||||
(define gen-vector
|
||||
(lambda (e ls lsnew)
|
||||
(cond
|
||||
((eq? (car lsnew) 'quote)
|
||||
(if (eq? (cadr lsnew) ls)
|
||||
`(quote ,e)
|
||||
`(quote #(,@(cadr lsnew)))))
|
||||
((eq? (car lsnew) 'list)
|
||||
`(vector . ,(cdr lsnew)))
|
||||
(else `(list->vector ,lsnew)))))
|
||||
(define regen
|
||||
(lambda (x)
|
||||
(case (car x)
|
||||
((ref) (build-lexical-reference no-source (cadr x)))
|
||||
((primitive) (build-primref no-source (cadr x)))
|
||||
((quote) (build-data no-source (cadr x)))
|
||||
((lambda) (build-lambda no-source (cadr x) (regen (caddr x))))
|
||||
((map)
|
||||
(let ((ls (map regen (cdr x))))
|
||||
(build-application no-source
|
||||
(build-primref no-source 'map)
|
||||
ls)))
|
||||
(else
|
||||
(build-application no-source
|
||||
(build-primref no-source (car x))
|
||||
(map regen (cdr x)))))))
|
||||
(lambda (e r mr)
|
||||
(define (ellipsis-map proc ls . ls*)
|
||||
(define who '...)
|
||||
(unless (list? ls)
|
||||
(assertion-violation who "not a list" ls))
|
||||
(unless (null? ls*)
|
||||
(let ([n (length ls)])
|
||||
(for-each
|
||||
(lambda (x)
|
||||
(unless (list? x)
|
||||
(assertion-violation who "not a list" x))
|
||||
(unless (= (length x) n)
|
||||
(assertion-violation who "length mismatch" ls x)))
|
||||
ls*)))
|
||||
(apply map proc ls ls*))
|
||||
|
||||
(define syntax-transformer
|
||||
(let ()
|
||||
(define gen-syntax
|
||||
(lambda (src e r maps ellipsis? vec?)
|
||||
(syntax-match e ()
|
||||
((_ x)
|
||||
(let-values (((e maps) (gen-syntax e x r '() ellipsis? #f)))
|
||||
(regen e)))))))
|
||||
(dots (ellipsis? dots)
|
||||
(stx-error src "misplaced ellipsis in syntax form"))
|
||||
(id (id? id)
|
||||
(let* ((label (id->label e))
|
||||
(b (label->binding label r)))
|
||||
(if (eq? (binding-type b) 'syntax)
|
||||
(let-values (((var maps)
|
||||
(let ((var.lev (binding-value b)))
|
||||
(gen-ref src (car var.lev) (cdr var.lev) maps))))
|
||||
(values (list 'ref var) maps))
|
||||
(values (list 'quote e) maps))))
|
||||
((dots e) (ellipsis? dots)
|
||||
(if vec?
|
||||
(stx-error src "misplaced ellipsis in syntax form")
|
||||
(gen-syntax src e r maps (lambda (x) #f) #f)))
|
||||
((x dots . y) (ellipsis? dots)
|
||||
(let f ((y y)
|
||||
(k (lambda (maps)
|
||||
(let-values (((x maps)
|
||||
(gen-syntax src x r
|
||||
(cons '() maps) ellipsis? #f)))
|
||||
(if (null? (car maps))
|
||||
(stx-error src
|
||||
"extra ellipsis in syntax form")
|
||||
(values (gen-map x (car maps)) (cdr maps)))))))
|
||||
(syntax-match y ()
|
||||
(() (k maps))
|
||||
((dots . y) (ellipsis? dots)
|
||||
(f y
|
||||
(lambda (maps)
|
||||
(let-values (((x maps) (k (cons '() maps))))
|
||||
(if (null? (car maps))
|
||||
(stx-error src "extra ellipsis in syntax form")
|
||||
(values (gen-mappend x (car maps)) (cdr maps)))))))
|
||||
(_
|
||||
(let-values (((y maps)
|
||||
(gen-syntax src y r maps ellipsis? vec?)))
|
||||
(let-values (((x maps) (k maps)))
|
||||
(values (gen-append x y) maps)))))))
|
||||
((x . y)
|
||||
(let-values (((xnew maps)
|
||||
(gen-syntax src x r maps ellipsis? #f)))
|
||||
(let-values (((ynew maps)
|
||||
(gen-syntax src y r maps ellipsis? vec?)))
|
||||
(values (gen-cons e x y xnew ynew) maps))))
|
||||
(#(ls ...)
|
||||
(let-values (((lsnew maps)
|
||||
(gen-syntax src ls r maps ellipsis? #t)))
|
||||
(values (gen-vector e ls lsnew) maps)))
|
||||
(_ (values `(quote ,e) maps)))))
|
||||
(define gen-ref
|
||||
(lambda (src var level maps)
|
||||
(if (= level 0)
|
||||
(values var maps)
|
||||
(if (null? maps)
|
||||
(stx-error src "missing ellipsis in syntax form")
|
||||
(let-values (((outer-var outer-maps)
|
||||
(gen-ref src var (- level 1) (cdr maps))))
|
||||
(cond
|
||||
((assq outer-var (car maps)) =>
|
||||
(lambda (b) (values (cdr b) maps)))
|
||||
(else
|
||||
(let ((inner-var (gen-lexical 'tmp)))
|
||||
(values
|
||||
inner-var
|
||||
(cons
|
||||
(cons (cons outer-var inner-var) (car maps))
|
||||
outer-maps))))))))))
|
||||
(define gen-append
|
||||
(lambda (x y)
|
||||
(if (equal? y '(quote ())) x `(append ,x ,y))))
|
||||
(define gen-mappend
|
||||
(lambda (e map-env)
|
||||
`(apply (primitive append) ,(gen-map e map-env))))
|
||||
(define gen-map
|
||||
(lambda (e map-env)
|
||||
(let ((formals (map cdr map-env))
|
||||
(actuals (map (lambda (x) `(ref ,(car x))) map-env)))
|
||||
(cond
|
||||
; identity map equivalence:
|
||||
; (map (lambda (x) x) y) == y
|
||||
((eq? (car e) 'ref)
|
||||
(car actuals))
|
||||
; eta map equivalence:
|
||||
; (map (lambda (x ...) (f x ...)) y ...) == (map f y ...)
|
||||
((for-all
|
||||
(lambda (x) (and (eq? (car x) 'ref) (memq (cadr x) formals)))
|
||||
(cdr e))
|
||||
(let ((args (map (let ((r (map cons formals actuals)))
|
||||
(lambda (x) (cdr (assq (cadr x) r))))
|
||||
(cdr e))))
|
||||
`(map (primitive ,(car e)) . ,args)))
|
||||
(else (cons* 'map (list 'lambda formals e) actuals))))))
|
||||
(define gen-cons
|
||||
(lambda (e x y xnew ynew)
|
||||
(case (car ynew)
|
||||
((quote)
|
||||
(if (eq? (car xnew) 'quote)
|
||||
(let ((xnew (cadr xnew)) (ynew (cadr ynew)))
|
||||
(if (and (eq? xnew x) (eq? ynew y))
|
||||
`(quote ,e)
|
||||
`(quote ,(cons xnew ynew))))
|
||||
(if (null? (cadr ynew))
|
||||
`(list ,xnew)
|
||||
`(cons ,xnew ,ynew))))
|
||||
((list) `(list ,xnew . ,(cdr ynew)))
|
||||
(else `(cons ,xnew ,ynew)))))
|
||||
(define gen-vector
|
||||
(lambda (e ls lsnew)
|
||||
(cond
|
||||
((eq? (car lsnew) 'quote)
|
||||
(if (eq? (cadr lsnew) ls)
|
||||
`(quote ,e)
|
||||
`(quote #(,@(cadr lsnew)))))
|
||||
((eq? (car lsnew) 'list)
|
||||
`(vector . ,(cdr lsnew)))
|
||||
(else `(list->vector ,lsnew)))))
|
||||
(define regen
|
||||
(lambda (x)
|
||||
(case (car x)
|
||||
((ref) (build-lexical-reference no-source (cadr x)))
|
||||
((primitive) (build-primref no-source (cadr x)))
|
||||
((quote) (build-data no-source (cadr x)))
|
||||
((lambda) (build-lambda no-source (cadr x) (regen (caddr x))))
|
||||
((map)
|
||||
(let ((ls (map regen (cdr x))))
|
||||
(build-application no-source
|
||||
(build-primref no-source 'ellipsis-map)
|
||||
ls)))
|
||||
(else
|
||||
(build-application no-source
|
||||
(build-primref no-source (car x))
|
||||
(map regen (cdr x)))))))
|
||||
(lambda (e r mr)
|
||||
(syntax-match e ()
|
||||
((_ x)
|
||||
(let-values (((e maps) (gen-syntax e x r '() ellipsis? #f)))
|
||||
(regen e)))))))
|
||||
|
||||
(define core-macro-transformer
|
||||
(lambda (name)
|
||||
|
|
Loading…
Reference in New Issue