racket/collects/redex/tests/gen-test.rkt
Burke Fetscher 2a9d42216e redex-generator: determine bound order automatically
also, fix a bug where continuations in thunks returned
by redex-generator weren't being shuffled
2013-01-23 13:03:07 -06:00

570 lines
15 KiB
Racket

#lang racket
(require "../reduction-semantics.rkt"
"../private/jdg-gen.rkt"
"../private/generate-term.rkt"
"test-util.rkt"
(only-in "../private/pat-unify.rkt"
bound
lvar))
(let ()
(define-language L0)
(test-equal (check-dq `a `a (make-hash) L0 (hash))
#f)
(test-equal (check-dq `a `b (make-hash) L0 (hash))
#t)
(test-equal (check-dq `(list a) `(list a) (make-hash) L0 (hash))
#f)
(test-equal (check-dq `(list a) `(list b) (make-hash) L0 (hash))
#t)
(test-equal (check-dq `(list number) `(list variable) (make-hash) L0 (hash))
#t)
(test-equal (check-dq `(list a) `(list number) (make-hash) L0 (hash))
#t)
(test-equal (check-dq `(list 2) `(list variable-not-otherwise-mentioned) (make-hash) L0 (hash))
#t)
(test-equal (check-dq `(list a b) `(list a number) (make-hash) L0 (hash))
#t)
(test-equal (check-dq `(list a b) `(list a b) (make-hash) L0 (hash))
#f)
(test-equal (check-dq `(list (name a ,(bound)))
`(list (name a ,(bound)))
(make-hash)
L0
(hash (lvar 'a) 'number))
#f)
(test-equal (check-dq `(name a ,(bound))
`(name b ,(bound))
(make-hash (list (cons (lvar 'a) '(1 2 3))
(cons (lvar 'b) '(1 2 3))))
L0
(hash (lvar 'a) 'any (lvar 'b) 'any))
#f)
)
(let ()
(define-language nats
(n z (s n)))
(define-judgment-form nats
#:mode (sum I I O)
#:contract (sum n n n)
[(sum z n n)]
[(sum (s n_1) n_2 (s n_3))
(sum n_1 n_2 n_3)])
(define-relation nats
[(r-sum z n n)]
[(r-sum (s n_1) n_2 (s n_3))
(r-sum n_1 n_2 n_3)])
(test-equal (judgment-holds (sum z (s z) (s z)))
#t)
(test-equal (judgment-holds (sum (s z) (s z) (s (s z))))
#t)
(test-equal (generate-term nats #:satisfying (sum z (s z) n) +inf.0)
'(sum z (s z) (s z)))
(test-equal (generate-term nats #:satisfying (sum (s z) (s z) n) +inf.0)
'(sum (s z) (s z) (s (s z))))
(test-equal (generate-term nats #:satisfying (sum z z (s z)) 5)
#f)
(for ([_ 100])
(match (generate-term nats #:satisfying (sum n_1 n_2 n_3) 5)
[`(sum ,l ,r ,res)
(test-equal (judgment-holds (sum ,l ,r n) n)
`(,res))])
(match (generate-term nats #:satisfying (r-sum n_1 n_2 n_3) 5)
[`(r-sum ,l ,r ,res)
(test-equal (term (r-sum ,l ,r ,res))
#t)])))
(let ()
(define-language lists
(l (x l)
())
(x variable-not-otherwise-mentioned))
(define-judgment-form lists
#:mode (not-in I I)
[(not-in x_0 ())]
[(not-in x_0 (x_1 l_0))
(different x_0 x_1) ;; this line has to go first or this won't terminate
(not-in x_0 l_0)])
(define-judgment-form lists
#:mode (different I I)
[(different x_!_1 x_!_1)])
(test
(judgment-holds (not-in a (b (c (d (e (f ())))))))
#t)
(test
(judgment-holds (not-in a (b (c (d (a (f ())))))))
#f)
(test
(generate-term lists #:satisfying (not-in a (b (a (c l)))) 5)
#f)
(test
(not (generate-term lists #:satisfying (not-in a (b (c (d (e (f ())))))) +inf.0))
#f)
(for/and ([_ 100])
(match (generate-term lists #:satisfying (not-in a l) 5)
[`(not-in a ,l)
(unless (judgment-holds (not-in a ,l)) (printf "l: ~s\n" l))
(test-equal (judgment-holds (not-in a ,l))
#t)]
[#f
(void)])))
(let ()
(define-language TL
(T (N T T)
(L number)))
(define-relation TL
[(tree (N T_1 T_2))
(tree T_1)
(tree T_2)]
[(tree (L number))])
(test-equal
(not
(empty?
(filter
values
(for/list ([_ 100])
(generate-term TL #:satisfying (tree T) 2)))))
#t)
)
(let ()
(define-language STLC
(τ int
(τ τ))
(Γ ([x τ] Γ)
)
(x variable-not-otherwise-mentioned))
(define-metafunction STLC
[(lookup x ([x τ] Γ))
τ]
[(lookup x ([x_1 τ] Γ))
(lookup x Γ)])
(test-equal (generate-term STLC
#:satisfying
(lookup x ([x int] ([x (int int)] ))) = (int int)
6)
#f))
(let ()
(define-language simple
(e (+ e e)
(+ e e e)
number))
(define-judgment-form simple
#:mode (double I I)
[(double (+ e_1 e_2) e_3)
(where e_3 (+ (+ e_1 e_1) (+ e_2 e_2)))])
(for ([_ 100])
(define t (generate-term simple #:satisfying (double e_1 e_2) +inf.0))
(match t
[`(double ,e1 ,e2)
(test-equal (judgment-holds (double ,e1 ,e2))
#t)]
[#f
(void)]))
(define-metafunction simple
[(duplicate e_1 e_1)
(+ e_1 e_1 e_1)]
[(duplicate e_1 e_2)
(+ e_3 e_4)
(where e_31 e_1)
(where e_3 (+ e_31 e_31))
(where e_42 e_2)
(where e_4 (+ e_42 e_42))]
[(duplicate e_1)
(duplicate e_1 e_1)])
(define-judgment-form simple
#:mode (double2 I I)
[(double2 (+ e_1 e_2) e_3)
(where e_3 (duplicate e_1 e_2))]
[(double2 e_1 e_2)
(where e_2 (duplicate e_1))])
(test-equal (term (duplicate 1 2))
'(+ (+ 1 1) (+ 2 2)))
(test-equal (term (duplicate 1))
'(+ 1 1 1))
(test-equal (term (duplicate 2 2))
'(+ 2 2 2))
(test-equal (judgment-holds (double2 (+ 1 2) (+ (+ 1 1) (+ 2 2))))
#t)
(test-equal (judgment-holds (double2 1 (+ 1 1 1)))
#t)
(test-equal (judgment-holds (double2 (+ 2 2) (+ 2 2 2)))
#t)
(for ([_ 100])
(define t (generate-term simple #:satisfying (double2 e_1 e_2) +inf.0))
(match t
[`(double2 ,e1 ,e2)
(test-equal (judgment-holds (double2 ,e1 ,e2))
#t)]
[#f
(void)])))
(let ()
(define-language STLC
(e (λ (x τ) e)
(e e)
x
i
add1)
(τ int
(τ τ))
(Γ ([x τ] Γ)
)
(i integer)
(x variable-not-otherwise-mentioned))
(define-judgment-form STLC
#:mode (typeof I I O)
#:contract (typeof Γ e τ)
[(typeof Γ i int)]
[(typeof Γ x (lookup x Γ))]
[(typeof Γ add1 (int int))]
[(typeof Γ (λ (x τ_1) e) (τ_1 τ_2))
(typeof ([x τ_1] Γ) e τ_2)]
[(typeof Γ (e_1 e_2) τ)
(typeof Γ e_1 (τ_2 τ))
(typeof Γ e_2 τ_2)])
(define-metafunction STLC
[(lookup x ([x τ] Γ))
τ]
[(lookup x ([x_1 τ] Γ))
(lookup x Γ)])
(define-extended-language if-l STLC
(e (if0 e e e)
....))
(define-extended-judgment-form if-l typeof
#:mode (typ-if I I O)
[(typ-if Γ (if0 e_1 e_2 e_3) τ)
(typ-if Γ e_1 int)
(typ-if Γ e_2 τ)
(typ-if Γ e_3 τ)])
(test-equal (judgment-holds (typeof ([x_1 int] ([x_1 (int int)] )) (x_1 5) int))
#f)
(test-equal (judgment-holds (typeof ([x_2 int] ([x_1 (int int)] )) (x_1 5) int))
#t)
(for ([_ 100])
(define term (generate-term STLC #:satisfying (typeof Γ e τ) 6))
(match term
[`(typeof ,g ,e ,t)
(define tp (judgment-holds (typeof ,g ,e τ) τ))
(test-equal tp `(,t))]
[#f
(void)]))
(for ([_ 100])
(define term (generate-term if-l #:satisfying (typ-if Γ e τ) 5))
(match term
[`(typ-if ,g ,e ,t)
(define tp (judgment-holds (typ-if ,g ,e τ) τ))
(test-equal tp `(,t))]
[#f
(void)]))
(define g (redex-generator STLC (typeof e τ) 5))
(define terms (filter values (for/list ([_ 400]) (g))))
(test-equal (length terms)
(length (remove-duplicates terms)))
(map (match-lambda
[`(typeof ,g ,e ,t)
(define tp (judgment-holds (typeof ,g ,e τ) τ))
(test-equal tp `(,t))])
terms)
(void)
)
(let ()
(define-language l
(e (n e)
)
(n number))
(define-metafunction l
fltr : n e -> e
[(fltr n )
]
[(fltr n (n e))
(fltr n e)]
[(fltr n (n_0 e))
(n_0 (fltr n e))])
(define-judgment-form l
#:mode (filtered I I O)
[(filtered e n (fltr n e))])
(test-equal (generate-term l #:satisfying (filtered (1 (2 (3 (4 )))) 3 (1 (2 (4 )))) +inf.0)
'(filtered (1 (2 (3 (4 )))) 3 (1 (2 (4 )))))
(test-equal (generate-term l #:satisfying (filtered (1 (2 (3 (4 )))) 5 (1 (2 (4 )))) +inf.0)
#f)
(for ([_ 50])
(define term (generate-term l #:satisfying (filtered e_1 n e_2) 5))
(match term
[`(filtered ,e1 ,n ,e2)
(define tp (judgment-holds (filtered ,e1 ,n e_2) e_2))
(test-equal tp `(,e2))]
[#f
(void)]))
(for ([_ 50])
(define t (generate-term l #:satisfying (fltr n e) = e_1 5))
(match t
[`((fltr ,n ,e) = ,e1)
(test-equal (term (fltr ,n ,e)) e1)]
[#f
(void)]))
(define g (redex-generator l (fltr n e_1) = e_2 5))
(define terms (filter values (for/list ([_ 50]) (g))))
(test-equal (length terms)
(length (remove-duplicates terms)))
(map (match-lambda
[`((fltr ,n ,e) = ,e1)
(test-equal (term (fltr ,n ,e)) e1)])
terms)
(void))
(let ()
(define-language L
(v a
b
c
d
e
f)
(bool T F))
(define-metafunction L
[(is-a? a) T]
[(is-a? v) F])
(define-metafunction/extension is-a? L
[(is-a/b? b) T])
(define-metafunction/extension is-a/b? L
[(is-a/b/c/d/e? c) T]
[(is-a/b/c/d/e? d) T]
[(is-a/b/c/d/e? e) T])
(test-equal (generate-term L #:satisfying (is-a? a) = any +inf.0)
'((is-a? a) = T))
(test-equal (generate-term L #:satisfying (is-a? b) = any +inf.0)
'((is-a? b) = F))
(test-equal (generate-term L #:satisfying (is-a? c) = any +inf.0)
'((is-a? c) = F))
(test-equal (generate-term L #:satisfying (is-a/b? a) = any +inf.0)
'((is-a/b? a) = T))
(test-equal (generate-term L #:satisfying (is-a/b? b) = any +inf.0)
'((is-a/b? b) = T))
(test-equal (generate-term L #:satisfying (is-a/b? c) = any +inf.0)
'((is-a/b? c) = F))
(test-equal (generate-term L #:satisfying (is-a/b/c/d/e? a) = any +inf.0)
'((is-a/b/c/d/e? a) = T))
(test-equal (generate-term L #:satisfying (is-a/b/c/d/e? b) = any +inf.0)
'((is-a/b/c/d/e? b) = T))
(test-equal (generate-term L #:satisfying (is-a/b/c/d/e? c) = any +inf.0)
'((is-a/b/c/d/e? c) = T))
(test-equal (generate-term L #:satisfying (is-a/b/c/d/e? d) = any +inf.0)
'((is-a/b/c/d/e? d) = T))
(test-equal (generate-term L #:satisfying (is-a/b/c/d/e? e) = any +inf.0)
'((is-a/b/c/d/e? e) = T))
(test-equal (generate-term L #:satisfying (is-a/b/c/d/e? f) = any +inf.0)
'((is-a/b/c/d/e? f) = F)))
;; errors for unsupprted pats
(let ()
(define-language L (n any))
(define-metafunction L
[(g (side-condition any #f)) any])
(define-metafunction L
[(f n) (g n)])
(test (with-handlers ((exn:fail? exn-message))
(generate-term L #:satisfying (f any) = any +inf.0)
"didn't raise an exception")
#rx".*generate-term:.*side-condition.*"))
(let ()
(define-language L (n any))
(define-metafunction L
[(g any_1 ...) (any_1 ...)])
(define-metafunction L
[(f n) (g n)])
(test (with-handlers ((exn:fail? exn-message))
(generate-term L #:satisfying (f any) = any +inf.0)
"didn't raise an exception")
#rx".*generate-term:.*repeat.*"))
(let ()
(define-language L
(n 1))
(define-judgment-form L
#:mode (jf I)
[(jf (n_0 n_1 ...))
(jf n_0)
(where (n_2 ...) (n_1 ...))
(jf (n_1 ...))]
[(jf 1)]
[(jf 2)]
[(jf 3)])
(test (with-handlers ([exn:fail? exn-message])
(generate-term L #:satisfying (jf n_1 n_2 n_3) +inf.0))
#rx".*generate-term:.*repeat.*"))
(let ()
(define-language L
(q any)
(r number))
(define-metafunction L
[(f r_1)
r_2
(where r_2 ,(+ (term r) (term r)))]
[(f (q_1 q_2))
q_3
(where q_3 (f q_1))
(where q_3 (f q_2))])
(test (with-handlers ([exn:fail? exn-message])
(generate-term L #:satisfying (f r_1) = r_2 +inf.0))
#rx".*generate-term:.*undatum.*"))
(let ()
(define-language L (n 2))
(define-metafunction L
[(n any) any])
(define-metafunction L
[(f n) (n 1)])
(test-equal (generate-term L #:satisfying (f any_1) = any_2 +inf.0)
'((f 2) = (2 1))))
(let ()
(define-language L (n 2))
(define-metafunction L
[(n any) any])
(define-metafunction L
[(f n) n])
(test-equal (generate-term L #:satisfying (f any_1) = any_2 +inf.0)
'((f 2) = 2)))
(let ()
(define-language l (n number))
(define-metafunction l
[(t n n)
1]
[(t n 2)
2]
[(t 1 n)
3]
[(t n_1 n_2)
4])
(test-equal (generate-term l #:satisfying (t 1 1) = 1 +inf.0)
'((t 1 1) = 1))
(test-equal (generate-term l #:satisfying (t 1 1) = 2 +inf.0)
#f)
(test-equal (generate-term l #:satisfying (t 1 2) = 2 +inf.0)
'((t 1 2) = 2))
(test-equal (generate-term l #:satisfying (t 1 2) = 3 +inf.0)
#f)
(test-equal (generate-term l #:satisfying (t 1 3) = 3 +inf.0)
'((t 1 3) = 3))
(test-equal (generate-term l #:satisfying (t 1 3) = 4 +inf.0)
#f)
(test-equal (generate-term l #:satisfying (t 6 7) = 4 +inf.0)
'((t 6 7) = 4))
(test-equal (generate-term l #:satisfying (t 6 7) = 3 +inf.0)
#f)
(test-equal (generate-term l #:satisfying (t 6 7) = 2 +inf.0)
#f)
(test-equal (generate-term l #:satisfying (t 6 7) = 1 +inf.0)
#f))
(let ()
(define-language L
(e (or e e) b)
(b T F))
(define-relation L
[(or-eval T)]
[(or-eval (or T e_2))]
[(or-eval (or (or e_1 e_2) e_3)) (or-eval (or e_1 (or e_2 e_3)))]
[(or-eval (or F e)) (or-eval e)])
(test-equal (generate-term L #:satisfying (or-eval F) +inf.0)
#f)
(test-equal (generate-term L #:satisfying (or-eval T) +inf.0)
'(or-eval T))
(test-equal (generate-term L #:satisfying (or-eval (or (or F F) T)) +inf.0)
'(or-eval (or (or F F) T))))
(let ()
(define-language wrong-nums
(n z (s z)))
(define-relation wrong-nums
[(sum z n n)]
[(sum (s n_1) n_2 (s n_3))
(sum n_1 n_2 n_3)])
(for ([n 10])
(define r (random 100000))
(random-seed r)
(define g (redex-generator wrong-nums (sum n_1 n_2 n_3) 1))
(with-handlers
([exn? (λ (e)
(printf "random seed: ~s\n" r)
(raise e))])
(for ([n 10])
(g)))))