Fixes a bug in `where' clause binding.
This commit is contained in:
parent
550a8b3fa4
commit
c6ed9b9a12
|
@ -7,9 +7,11 @@
|
||||||
"loc-wrapper.ss"
|
"loc-wrapper.ss"
|
||||||
"error.ss"
|
"error.ss"
|
||||||
mzlib/trace
|
mzlib/trace
|
||||||
|
racket/set
|
||||||
(lib "list.ss")
|
(lib "list.ss")
|
||||||
(lib "etc.ss")
|
(lib "etc.ss")
|
||||||
(for-syntax syntax/parse))
|
(for-syntax syntax/parse)
|
||||||
|
(for-syntax racket/set))
|
||||||
|
|
||||||
(require (for-syntax (lib "name.ss" "syntax")
|
(require (for-syntax (lib "name.ss" "syntax")
|
||||||
"loc-wrapper-ct.ss"
|
"loc-wrapper-ct.ss"
|
||||||
|
@ -223,19 +225,18 @@
|
||||||
(syntax/loc stx (do-reduction-relation orig-stx extend-reduction-relation orig-reduction-relation #t lang args ...)))]))
|
(syntax/loc stx (do-reduction-relation orig-stx extend-reduction-relation orig-reduction-relation #t lang args ...)))]))
|
||||||
|
|
||||||
;; the withs, freshs, and side-conditions come in backwards order
|
;; the withs, freshs, and side-conditions come in backwards order
|
||||||
(define-for-syntax (bind-withs orig-name main lang lang-nts stx where-mode body)
|
(define-for-syntax bind-withs
|
||||||
(let* ([bindings '()]
|
(λ (orig-name main lang lang-nts stx where-mode body [lhs-bound #'()])
|
||||||
[body
|
|
||||||
(let loop ([stx stx]
|
(let loop ([stx stx]
|
||||||
[to-not-be-in main])
|
[to-not-be-in main]
|
||||||
|
[bound (apply set lhs-bound)])
|
||||||
(syntax-case stx (fresh)
|
(syntax-case stx (fresh)
|
||||||
[() body]
|
[() body]
|
||||||
[((-where x e) y ...)
|
[((-where x e) y ...)
|
||||||
(or (free-identifier=? #'-where #'where)
|
(or (free-identifier=? #'-where #'where)
|
||||||
(free-identifier=? #'-where #'where/hidden))
|
(free-identifier=? #'-where #'where/hidden))
|
||||||
(let-values ([(names names/ellipses) (extract-names lang-nts 'reduction-relation #t #'x)])
|
(let-values ([(names names/ellipses) (extract-names lang-nts 'reduction-relation #t #'x)])
|
||||||
(with-syntax ([(cpat) (generate-temporaries '(compiled-pattern))]
|
(with-syntax ([side-conditions-rewritten (rewrite-side-conditions/check-errs
|
||||||
[side-conditions-rewritten (rewrite-side-conditions/check-errs
|
|
||||||
lang-nts
|
lang-nts
|
||||||
'reduction-relation
|
'reduction-relation
|
||||||
#f
|
#f
|
||||||
|
@ -243,58 +244,49 @@
|
||||||
[(names ...) names]
|
[(names ...) names]
|
||||||
[(names/ellipses ...) names/ellipses])
|
[(names/ellipses ...) names/ellipses])
|
||||||
(with-syntax ([(x ...) (generate-temporaries #'(names ...))])
|
(with-syntax ([(x ...) (generate-temporaries #'(names ...))])
|
||||||
(set! bindings (cons #`[cpat (compile-pattern #,lang `side-conditions-rewritten #t)] bindings))
|
(let ([rest-body (loop #'(y ...) #`(list x ... #,to-not-be-in) bound)])
|
||||||
(let ([rest-body (loop #'(y ...) #`(list x ... #,to-not-be-in))])
|
#`(let* ([mtchs (match-pattern (compile-pattern #,lang `side-conditions-rewritten #t) (term e))]
|
||||||
#`(let ([mtchs (match-pattern cpat (term e))])
|
[result (λ (mtch)
|
||||||
|
(let ([bindings (mtch-bindings mtch)])
|
||||||
|
(let ([x (lookup-binding bindings 'names)] ...)
|
||||||
|
(term-let ([names/ellipses x] ...)
|
||||||
|
#,rest-body))))])
|
||||||
(if mtchs
|
(if mtchs
|
||||||
#,
|
#,
|
||||||
(case where-mode
|
(case where-mode
|
||||||
[(flatten)
|
[(flatten)
|
||||||
#`(apply
|
#`(apply append (map result mtchs))]
|
||||||
append
|
|
||||||
(map (λ (mtch)
|
|
||||||
(let ([bindings (mtch-bindings mtch)])
|
|
||||||
(let ([x (lookup-binding bindings 'names)] ...)
|
|
||||||
(term-let ([names/ellipses x] ...)
|
|
||||||
#,rest-body))))
|
|
||||||
mtchs))]
|
|
||||||
[(predicate)
|
[(predicate)
|
||||||
#`(ormap (λ (mtch)
|
#`(ormap result mtchs)]
|
||||||
(let ([bindings (mtch-bindings mtch)])
|
|
||||||
(let ([x (lookup-binding bindings 'names)] ...)
|
|
||||||
(term-let ([names/ellipses x] ...)
|
|
||||||
#,rest-body))))
|
|
||||||
mtchs)]
|
|
||||||
[else (error 'unknown-where-mode "~s" where-mode)])
|
[else (error 'unknown-where-mode "~s" where-mode)])
|
||||||
#f))))))]
|
#f))))))]
|
||||||
[((-side-condition s ...) y ...)
|
[((-side-condition s ...) y ...)
|
||||||
(or (free-identifier=? #'-side-condition #'side-condition)
|
(or (free-identifier=? #'-side-condition #'side-condition)
|
||||||
(free-identifier=? #'-side-condition #'side-condition/hidden))
|
(free-identifier=? #'-side-condition #'side-condition/hidden))
|
||||||
#`(and s ... #,(loop #'(y ...) to-not-be-in))]
|
#`(and s ... #,(loop #'(y ...) to-not-be-in bound))]
|
||||||
[((fresh x) y ...)
|
[((fresh x) y ...)
|
||||||
(identifier? #'x)
|
(identifier? #'x)
|
||||||
#`(term-let ([x (variable-not-in #,to-not-be-in 'x)])
|
#`(term-let ([x (variable-not-in #,to-not-be-in 'x)])
|
||||||
#,(loop #'(y ...) #`(list (term x) #,to-not-be-in)))]
|
#,(loop #'(y ...) #`(list (term x) #,to-not-be-in) bound))]
|
||||||
[((fresh x name) y ...)
|
[((fresh x name) y ...)
|
||||||
(identifier? #'x)
|
(identifier? #'x)
|
||||||
#`(term-let ([x (let ([the-name (term name)])
|
#`(term-let ([x (let ([the-name (term name)])
|
||||||
(verify-name-ok '#,orig-name the-name)
|
(verify-name-ok '#,orig-name the-name)
|
||||||
(variable-not-in #,to-not-be-in the-name))])
|
(variable-not-in #,to-not-be-in the-name))])
|
||||||
#,(loop #'(y ...) #`(list (term x) #,to-not-be-in)))]
|
#,(loop #'(y ...) #`(list (term x) #,to-not-be-in) bound))]
|
||||||
[((fresh (y) (x ...)) z ...)
|
[((fresh (y) (x ...)) z ...)
|
||||||
#`(term-let ([(y #,'...)
|
#`(term-let ([(y #,'...)
|
||||||
(variables-not-in #,to-not-be-in
|
(variables-not-in #,to-not-be-in
|
||||||
(map (λ (_ignore_) 'y)
|
(map (λ (_ignore_) 'y)
|
||||||
(term (x ...))))])
|
(term (x ...))))])
|
||||||
#,(loop #'(z ...) #`(list (term (y #,'...)) #,to-not-be-in)))]
|
#,(loop #'(z ...) #`(list (term (y #,'...)) #,to-not-be-in) bound))]
|
||||||
[((fresh (y) (x ...) names) z ...)
|
[((fresh (y) (x ...) names) z ...)
|
||||||
#`(term-let ([(y #,'...)
|
#`(term-let ([(y #,'...)
|
||||||
(let ([the-names (term names)]
|
(let ([the-names (term names)]
|
||||||
[len-counter (term (x ...))])
|
[len-counter (term (x ...))])
|
||||||
(verify-names-ok '#,orig-name the-names len-counter)
|
(verify-names-ok '#,orig-name the-names len-counter)
|
||||||
(variables-not-in #,to-not-be-in the-names))])
|
(variables-not-in #,to-not-be-in the-names))])
|
||||||
#,(loop #'(z ...) #`(list (term (y #,'...)) #,to-not-be-in)))]))])
|
#,(loop #'(z ...) #`(list (term (y #,'...)) #,to-not-be-in) bound))]))))
|
||||||
(values body bindings)))
|
|
||||||
|
|
||||||
(define-syntax-set (do-reduction-relation)
|
(define-syntax-set (do-reduction-relation)
|
||||||
(define (do-reduction-relation/proc stx)
|
(define (do-reduction-relation/proc stx)
|
||||||
|
@ -701,25 +693,26 @@
|
||||||
(let* ([lang-nts (language-id-nts lang-id orig-name)]
|
(let* ([lang-nts (language-id-nts lang-id orig-name)]
|
||||||
[rw-sc (λ (pat) (rewrite-side-conditions/check-errs lang-nts orig-name #t pat))])
|
[rw-sc (λ (pat) (rewrite-side-conditions/check-errs lang-nts orig-name #t pat))])
|
||||||
(let-values ([(name sides/withs/freshs) (process-extras stx orig-name name-table extras)])
|
(let-values ([(name sides/withs/freshs) (process-extras stx orig-name name-table extras)])
|
||||||
(let-values ([(names names/ellipses) (extract-names lang-nts orig-name #t from)]
|
(let*-values ([(names names/ellipses) (extract-names lang-nts orig-name #t from)]
|
||||||
[(body-code compile-pattern-bindings)
|
[(body-code)
|
||||||
(bind-withs orig-name
|
(bind-withs orig-name
|
||||||
#'main-exp
|
#'main-exp
|
||||||
lang
|
lang
|
||||||
lang-nts
|
lang-nts
|
||||||
sides/withs/freshs
|
sides/withs/freshs
|
||||||
'flatten
|
'flatten
|
||||||
#`(list (term #,to)))]
|
#`(list (term #,to))
|
||||||
[(test-case-body-code test-case-compile-pattern-bindings)
|
names/ellipses)]
|
||||||
;; this contains some redundant code, eg. the test-case-compile-pattern-bindings
|
[(test-case-body-code)
|
||||||
;; are (morally) the same as the compile-pattern-bindings
|
;; this contains some redundant code
|
||||||
(bind-withs orig-name
|
(bind-withs orig-name
|
||||||
#'#t
|
#'#t
|
||||||
#'lang-id2
|
#'lang-id2
|
||||||
lang-nts
|
lang-nts
|
||||||
sides/withs/freshs
|
sides/withs/freshs
|
||||||
'predicate
|
'predicate
|
||||||
#'#t)])
|
#'#t
|
||||||
|
names/ellipses)])
|
||||||
(with-syntax ([side-conditions-rewritten (rw-sc from)]
|
(with-syntax ([side-conditions-rewritten (rw-sc from)]
|
||||||
[lhs-w/extras (rw-sc #`(side-condition #,from #,test-case-body-code))]
|
[lhs-w/extras (rw-sc #`(side-condition #,from #,test-case-body-code))]
|
||||||
[lhs-source (format "~a:~a:~a"
|
[lhs-source (format "~a:~a:~a"
|
||||||
|
@ -730,15 +723,12 @@
|
||||||
[lang lang]
|
[lang lang]
|
||||||
[(names ...) names]
|
[(names ...) names]
|
||||||
[(names/ellipses ...) names/ellipses]
|
[(names/ellipses ...) names/ellipses]
|
||||||
[body-code body-code]
|
[body-code body-code])
|
||||||
[(test-case-compile-pattern-bindings ...) test-case-compile-pattern-bindings]
|
|
||||||
[(compile-pattern-bindings ...) compile-pattern-bindings])
|
|
||||||
#`
|
#`
|
||||||
(let ([case-id (gensym)])
|
(let ([case-id (gensym)])
|
||||||
(make-rewrite-proc
|
(make-rewrite-proc
|
||||||
(λ (lang-id)
|
(λ (lang-id)
|
||||||
(let ([cp (compile-pattern lang-id `side-conditions-rewritten #t)]
|
(let ([cp (compile-pattern lang-id `side-conditions-rewritten #t)])
|
||||||
compile-pattern-bindings ...)
|
|
||||||
(λ (main-exp exp f other-matches)
|
(λ (main-exp exp f other-matches)
|
||||||
(let ([mtchs (match-pattern cp exp)])
|
(let ([mtchs (match-pattern cp exp)])
|
||||||
(if mtchs
|
(if mtchs
|
||||||
|
@ -768,7 +758,7 @@
|
||||||
(loop (cdr mtchs) acc)]))]))
|
(loop (cdr mtchs) acc)]))]))
|
||||||
other-matches)))))
|
other-matches)))))
|
||||||
name
|
name
|
||||||
(λ (lang-id2) (let (test-case-compile-pattern-bindings ...) `lhs-w/extras))
|
(λ (lang-id2) `lhs-w/extras)
|
||||||
lhs-source
|
lhs-source
|
||||||
case-id)))))))
|
case-id)))))))
|
||||||
|
|
||||||
|
@ -1163,28 +1153,38 @@
|
||||||
(when (and prev-metafunction (eq? (syntax-e #'name) (syntax-e prev-metafunction)))
|
(when (and prev-metafunction (eq? (syntax-e #'name) (syntax-e prev-metafunction)))
|
||||||
(raise-syntax-error syn-error-name "the extended and extending metafunctions cannot share a name" orig-stx prev-metafunction))
|
(raise-syntax-error syn-error-name "the extended and extending metafunctions cannot share a name" orig-stx prev-metafunction))
|
||||||
(parse-extras #'((stuff ...) ...))
|
(parse-extras #'((stuff ...) ...))
|
||||||
(with-syntax ([(((cp-let-bindings ...) rhs/wheres) ...)
|
(let-values ([(lhs-namess lhs-namess/ellipsess)
|
||||||
(map (λ (sc/b rhs)
|
(let loop ([lhss (syntax->list (syntax (lhs ...)))])
|
||||||
(let-values ([(body-code cp-let-bindings)
|
(if (null? lhss)
|
||||||
|
(values null null)
|
||||||
|
(let-values ([(namess namess/ellipsess)
|
||||||
|
(loop (cdr lhss))]
|
||||||
|
[(names names/ellipses)
|
||||||
|
(extract-names lang-nts syn-error-name #t (car lhss))])
|
||||||
|
(values (cons names namess)
|
||||||
|
(cons names/ellipses namess/ellipsess)))))])
|
||||||
|
(with-syntax ([(rhs/wheres ...)
|
||||||
|
(map (λ (sc/b rhs names/ellipses)
|
||||||
(bind-withs
|
(bind-withs
|
||||||
syn-error-name '()
|
syn-error-name '()
|
||||||
#'lang lang-nts
|
#'lang lang-nts
|
||||||
sc/b 'flatten
|
sc/b 'flatten
|
||||||
#`(list (term #,rhs)))])
|
#`(list (term #,rhs))
|
||||||
(list cp-let-bindings body-code)))
|
names/ellipses))
|
||||||
(syntax->list #'((stuff ...) ...))
|
(syntax->list #'((stuff ...) ...))
|
||||||
(syntax->list #'(rhs ...)))]
|
(syntax->list #'(rhs ...))
|
||||||
[(((rg-cp-let-bindings ...) rg-rhs/wheres) ...)
|
lhs-namess/ellipsess)]
|
||||||
(map (λ (sc/b rhs)
|
[(rg-rhs/wheres ...)
|
||||||
(let-values ([(body-code cp-let-bindings)
|
(map (λ (sc/b rhs names/ellipses)
|
||||||
(bind-withs
|
(bind-withs
|
||||||
syn-error-name '()
|
syn-error-name '()
|
||||||
#'lang lang-nts
|
#'lang lang-nts
|
||||||
sc/b 'predicate
|
sc/b 'predicate
|
||||||
#`#t)])
|
#`#t
|
||||||
(list cp-let-bindings body-code)))
|
names/ellipses))
|
||||||
(syntax->list #'((stuff ...) ...))
|
(syntax->list #'((stuff ...) ...))
|
||||||
(syntax->list #'(rhs ...)))])
|
(syntax->list #'(rhs ...))
|
||||||
|
lhs-namess/ellipsess)])
|
||||||
(with-syntax ([(side-conditions-rewritten ...)
|
(with-syntax ([(side-conditions-rewritten ...)
|
||||||
(map (λ (x) (rewrite-side-conditions/check-errs
|
(map (λ (x) (rewrite-side-conditions/check-errs
|
||||||
lang-nts
|
lang-nts
|
||||||
|
@ -1220,9 +1220,7 @@
|
||||||
#f
|
#f
|
||||||
codom-contract)]
|
codom-contract)]
|
||||||
[(rhs-fns ...)
|
[(rhs-fns ...)
|
||||||
(map (λ (lhs rhs/where)
|
(map (λ (names names/ellipses rhs/where)
|
||||||
(let-values ([(names names/ellipses)
|
|
||||||
(extract-names lang-nts syn-error-name #t lhs)])
|
|
||||||
(with-syntax ([(names ...) names]
|
(with-syntax ([(names ...) names]
|
||||||
[(names/ellipses ...) names/ellipses]
|
[(names/ellipses ...) names/ellipses]
|
||||||
[rhs/where rhs/where])
|
[rhs/where rhs/where])
|
||||||
|
@ -1230,8 +1228,8 @@
|
||||||
(λ (name bindings)
|
(λ (name bindings)
|
||||||
(term-let-fn ((name name))
|
(term-let-fn ((name name))
|
||||||
(term-let ([names/ellipses (lookup-binding bindings 'names)] ...)
|
(term-let ([names/ellipses (lookup-binding bindings 'names)] ...)
|
||||||
rhs/where)))))))
|
rhs/where))))))
|
||||||
(syntax->list (syntax (lhs ...)))
|
lhs-namess lhs-namess/ellipsess
|
||||||
(syntax->list (syntax (rhs/wheres ...))))]
|
(syntax->list (syntax (rhs/wheres ...))))]
|
||||||
[(name2 name-predicate) (generate-temporaries (syntax (name name)))]
|
[(name2 name-predicate) (generate-temporaries (syntax (name name)))]
|
||||||
|
|
||||||
|
@ -1243,9 +1241,7 @@
|
||||||
(with-syntax ([defs #`(begin
|
(with-syntax ([defs #`(begin
|
||||||
(define-values (name2 name-predicate)
|
(define-values (name2 name-predicate)
|
||||||
(let ([sc `(side-conditions-rewritten ...)]
|
(let ([sc `(side-conditions-rewritten ...)]
|
||||||
[dsc `dom-side-conditions-rewritten]
|
[dsc `dom-side-conditions-rewritten])
|
||||||
cp-let-bindings ... ...
|
|
||||||
rg-cp-let-bindings ... ...)
|
|
||||||
(let ([cases (map (λ (pat rhs-fn rg-lhs src)
|
(let ([cases (map (λ (pat rhs-fn rg-lhs src)
|
||||||
(make-metafunc-case
|
(make-metafunc-case
|
||||||
(compile-pattern lang pat #t) rhs-fn rg-lhs src (gensym)))
|
(compile-pattern lang pat #t) rhs-fn rg-lhs src (gensym)))
|
||||||
|
@ -1354,7 +1350,7 @@
|
||||||
defs))
|
defs))
|
||||||
(syntax defs))
|
(syntax defs))
|
||||||
'disappeared-use
|
'disappeared-use
|
||||||
(map syntax-local-introduce (syntax->list #'(original-names ...)))))))))))))))]
|
(map syntax-local-introduce (syntax->list #'(original-names ...))))))))))))))))]
|
||||||
[(_ prev-metafunction name lang clauses ...)
|
[(_ prev-metafunction name lang clauses ...)
|
||||||
(begin
|
(begin
|
||||||
(unless (identifier? #'name)
|
(unless (identifier? #'name)
|
||||||
|
@ -2112,7 +2108,9 @@
|
||||||
(print-failed srcinfo)
|
(print-failed srcinfo)
|
||||||
(fprintf (current-error-port) "found a cycle in the reduction graph\n")]
|
(fprintf (current-error-port) "found a cycle in the reduction graph\n")]
|
||||||
[else
|
[else
|
||||||
(unless (set-equal? expected got equiv?)
|
(let* ([⊆ (λ (s1 s2) (andmap (λ (x1) (memf (λ (x) (equiv? x1 x)) s2)) s1))]
|
||||||
|
[set-equal? (λ (s1 s2) (and (⊆ s1 s2) (⊆ s2 s1)))])
|
||||||
|
(unless (set-equal? expected got)
|
||||||
(inc-failures)
|
(inc-failures)
|
||||||
(print-failed srcinfo)
|
(print-failed srcinfo)
|
||||||
(for-each
|
(for-each
|
||||||
|
@ -2120,12 +2118,7 @@
|
||||||
expected)
|
expected)
|
||||||
(for-each
|
(for-each
|
||||||
(λ (v1) (fprintf (current-error-port) " actual: ~v\n" v1))
|
(λ (v1) (fprintf (current-error-port) " actual: ~v\n" v1))
|
||||||
got))])))
|
got)))])))
|
||||||
|
|
||||||
(define (set-equal? s1 s2 equiv?)
|
|
||||||
(define (⊆ s1 s2) (andmap (λ (x1) (memf (λ (x) (equiv? x1 x)) s2)) s1))
|
|
||||||
(and (⊆ s1 s2)
|
|
||||||
(⊆ s2 s1)))
|
|
||||||
|
|
||||||
(define-syntax (test-predicate stx)
|
(define-syntax (test-predicate stx)
|
||||||
(syntax-case stx ()
|
(syntax-case stx ()
|
||||||
|
|
|
@ -844,6 +844,18 @@
|
||||||
(list '((2 3) 20)
|
(list '((2 3) 20)
|
||||||
'(6 (4 5))))
|
'(6 (4 5))))
|
||||||
|
|
||||||
|
; The scope of a `where' clause includes the left-hand sides
|
||||||
|
; of subsequent `where' clauses.
|
||||||
|
(test (apply-reduction-relation
|
||||||
|
(reduction-relation
|
||||||
|
grammar
|
||||||
|
(--> any
|
||||||
|
1
|
||||||
|
(where number_1 2)
|
||||||
|
(where (side-condition any (number? (term number_1))) dontcare)))
|
||||||
|
'dontcare)
|
||||||
|
'(1))
|
||||||
|
|
||||||
; shortcuts like this fail if compilation fails to preserve
|
; shortcuts like this fail if compilation fails to preserve
|
||||||
; lexical context for side-conditions expressions.
|
; lexical context for side-conditions expressions.
|
||||||
(test (let ([x #t])
|
(test (let ([x #t])
|
||||||
|
|
Loading…
Reference in New Issue
Block a user