racket/collects/redex/examples/cont-mark-transform/randomized-tests.rkt
2011-06-28 02:01:41 -04:00

236 lines
7.6 KiB
Racket
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#lang racket
(require "SL-syntax.rkt" "SL-semantics.rkt"
"TL-syntax.rkt" "TL-semantics.rkt"
"CMT.rkt"
"common.rkt"
redex)
(provide main same-result?)
(define (main . args)
(define seed (add1 (random (sub1 (expt 2 31)))))
(define unique-decomp-tests #f)
(define CMT-range-all-tests #f)
(define CMT-range-rules-tests #f)
(define same-result-all-tests #f)
(define same-result-rules-tests #f)
(command-line
#:argv args
#:once-each
["--seed"
n
"Seed PRG with n"
(set! seed (string->number n))]
["--unique-decomposition"
n
"Test unique decomposition of n expressions"
(set! unique-decomp-tests (string->number n))]
["--CMT-range"
n
("Test that CMT produces a TL expression for n expressions,"
"chosen from SL's e non-terminal")
(set! CMT-range-all-tests (string->number n))]
["--CMT-range-rules"
n
("Test that CMT produces a TL expression for n expressions,"
"chosen from the left-hand sides of -->SL")
(set! CMT-range-rules-tests (string->number n))]
["--same-result"
n
("Test that translation preserves meaning for n expression,"
"chosen from SL's e non-terminal")
(set! same-result-all-tests (string->number n))]
["--same-result-rules"
n
("Test that translation preserves meaning for n expression,"
"chosen from SL's e non-terminal")
(set! same-result-rules-tests (string->number n))])
(printf "Random seed: ~s\n" seed)
(when unique-decomp-tests
(test-unique-decomposition unique-decomp-tests))
(when CMT-range-all-tests
(test-CMT-range CMT-range-all-tests))
(when CMT-range-rules-tests
(test-CMT-range/rules CMT-range-rules-tests))
(when same-result-all-tests
(test-same-result same-result-all-tests))
(when same-result-rules-tests
(test-same-result/rules same-result-rules-tests)))
;; Unique decomposition
(define (test-unique-decomposition attempts)
(redex-check SL e (uniquely-decomposes? (term e)) #:attempts attempts))
(define uniquely-decomposes?
(let ([a? (redex-match SL a)]
[decompositions (redex-match SL (in-hole T r))])
(λ (e)
(or (a? e)
(match (decompositions e)
[(list _) #t]
[_ #f])))))
;; CMT produces TL expressions
(define (test-CMT-range attempts)
(test-translation CMT-produces-TL?
#:attempts attempts))
(define (test-CMT-range/rules attempts)
(test-translation CMT-produces-TL?
#:attempts attempts
#:source -->SL/no-side-conds))
(define CMT-produces-TL?
(let ([TL-e? (redex-match TL e)])
(λ (e)
(TL-e? (term (CMT ,e))))))
;; Translated programs have the same result
(define (test-same-result attempts)
(test-translation same-result?
#:attempts attempts))
(define (test-same-result/rules attempts)
(test-translation same-result?
#:attempts attempts
#:source -->SL/no-side-conds))
(define (same-result? expr)
(let/ec return
(define SL-result
(with-handlers ([normalization-timeout? return]
[eval-undefined? return])
(parameterize ([max-normalization-steps 1000])
(SL-eval (term ( / ,expr))))))
(define TL-result
(dynamic-wind
(λ () (set-cache-size! 100))
(λ () (TL-eval (term ( / (translate ,expr)))))
(λ () (set-cache-size! 350))))
(or (equal? SL-result TL-result)
(compares-incomparable-keys? expr))))
(define SL-eval
(make-eval -->SL (redex-match SL v)))
(define TL-eval
(make-eval -->TL (redex-match TL v)))
;; Utilities
(define-syntax-rule (test-translation predicate . kw-args)
(redex-check SL-gen (Σ / e)
(predicate (term e))
#:prepare close-program . kw-args))
(define-extended-language SL-gen SL
(σ (ref (variable-except resume restore-marks c-w-i-c-m map-set kont/ms equal? last)))
(K (side-condition string_1 (not (member (term string_1) '("square" "diamond")))))
(K-tree (K K-tree ...)))
(define -->SL/no-side-conds
; Disables side-conditions on some rules.
(extend-reduction-relation
-->SL SL
(--> (Σ / (in-hole E (match (K v ...) l ...))) any "2")
(--> (Σ / (in-hole E (σ v ...))) any "4")
(--> (Σ / (in-hole E_1 (σ v))) any "4")))
(define close-program
(match-lambda
[`(,Σ / ,e)
`(,Σ / ,(close-expr e))]))
(define close-expr
(let ([var? (redex-match SL x)]
[val? (redex-match SL v)])
(λ (expr)
; 1. Considers refs to be bound only within the binding letrec.
; 2. Avoids adding duplicate mark to an existing frame, since
; doing so (a) can make a continuation value syntactically invalid
; and (b) can change the reduction rule that applies
(let recur ([expr expr] [vars (set)] [refs (set)] [keys (set)])
(match expr
[(? var?)
(if (set-empty? vars)
(if (set-empty? refs)
(random-constant)
`(ref ,(random-element refs)))
(if (set-member? vars expr)
expr
(random-element vars)))]
[`(ref ,σ)
(if (set-empty? refs)
(random-constant)
(if (set-member? refs σ)
expr
`(ref ,(random-element refs))))]
[`(w-c-m ,k ,v ,e)
(define k
(if (val? k)
k
(let retry ([candidate (recur k vars refs keys)]
[retries 0])
(when (> retries 3)
(error 'close "too many"))
(if (set-member? keys candidate)
(retry (list (first (random-constant)) candidate)
(add1 retries))
candidate))))
(define ext-keys
(if (val? k)
(set-add keys k)
keys))
`(w-c-m ,k ,(recur v vars refs (set))
,(recur e vars refs ext-keys))]
[`(letrec ([(ref ,σs) ,es] ...) ,e)
(define ext-refs (extend refs σs))
`(letrec ,(for/list ([e es] [σ σs])
`[(ref ,σ) ,(recur e vars ext-refs (set))])
,(recur e vars ext-refs (set)))]
[`(match ,e [(,ks ,xss ...) ,es] ...)
(define ext-vars (extend vars (apply append xss)))
`(match ,(recur e vars refs (set))
,@(for/list ([xs xss] [e es] [k ks])
`[(,k ,@xs) ,(recur e ext-vars refs (set))]))]
[`(λ ,xs ,e)
(define ext-vars (extend vars xs))
`(λ ,xs ,(recur e ext-vars refs (set)))]
[(? list?)
(map (λ (e) (recur e vars refs (set))) expr)]
[_ expr])))))
(define (extend s xs)
(for/fold ([s s]) ([x xs])
(set-add s x)))
(define random-constant
(let ([generate-K-tree (generate-term SL-gen K-tree)])
(λ () (generate-K-tree (random 3)))))
(define (random-element xs)
(list-ref (set-map xs values) (random (set-count xs))))
(define (compares-incomparable-keys? expr)
(define procedure? (redex-match SL (λ (x ...) e)))
(define continuation? (redex-match SL (κ E)))
(let/ec return
(apply-reduction-relation*
(extend-reduction-relation
-->SL SL
(--> (Σ / (in-hole E (c-c-m [v ...])))
,(if (andmap comparable? (term (v ...)))
(term (Σ / (in-hole E (χ (v ...) E ("nil")))))
(return #t))
"8"))
`( / ,expr))
#f))
(define comparable?
(let ()
(define-extended-language SL SL
(c σ (K c ...)))
(redex-match SL c)))