(require (lib "list.ss")
(lib "67.ss" "srfi"))
(define types
'(
(union : set set -> set)
(intersection : set set -> set)
(difference : set set -> set)
(insert : elm set -> set)
(delete : elm set -> set)
))
(define (build-base-level-expr type)
(case type
[(set) `(insert* '(,(random 10) ,(random 10) ,(random 10)) (empty))]
[(elm) (random 10)]
[else (error 'build-base-level-expr "no base level exprs known for ~a" type)]))
(define (build-expr type level)
(define (build-sub-expr type) (build-expr type (- level 1)))
(cond
[(or (= level 0)
(empty? (operations/result-type type)))
(build-base-level-expr type)]
[else
(let* ((operation (random-element-of (operations/result-type type)))
(arg-exprs (map build-sub-expr (operation-argument-types operation))))
`(,operation ,@arg-exprs))]))
(define (operations)
(map car types))
(define (operation-member operation)
(ormap (lambda (type)
(if (eq? (first type) operation)
type
#f))
types))
(define (operation-type operation)
(let ((type (operation-member operation)))
(when (not type) (error 'operation-type "no type associated with ~a" operation))
(rest (rest type))))
(define (before-arrow type)
(when (not (member '-> type)) (error 'before-arrow "no arrow in type: ~a" type))
(do ((type type (cdr type))
(before '() (cons (car type) before)))
((eq? (first type) '->)
(reverse! before))))
(define (after-arrow type)
(when (not (member '-> type)) (error 'after-arrow "no arrow in type: ~a" type))
(first (rest (member '-> type))))
(define (operation-result-type operation)
(let ((type (operation-member operation)))
(when (not type) (error 'operation-result-type "unknown operation: ~a" operation))
(after-arrow type)))
(define (operation-argument-types operation)
(let ((type (operation-member operation)))
(when (not type) (error 'operation-argument-types "unknown operation: ~a" operation))
(rest (rest (before-arrow type)))))
(define (operations/result-type type)
(filter (lambda (op)
(equal? (operation-result-type op) type))
(operations)))
(define (random-element-of l)
(list-ref l (random (length l))))
(define (test-expr expr namespaces compare)
(define (test-module namespace)
(parameterize ([current-namespace namespace])
(eval expr)))
(printf "~a~n" expr)
(let ((results (map test-module namespaces)))
(cond
[(not (andmap (lambda (r) (equal? (first results) r))
(rest results)))
(error "FAILED:\n"
expr "\n" results)]
[else (printf "~a~n" results)])))
(define (test cnt modules compare)
(define (module->namespace module)
(let ((n (make-namespace)))
(parameterize ([current-namespace n])
(namespace-require '(lib "list.ss"))
(namespace-require module)
(current-namespace))))
(do ((i 0 (+ i 1)))
((= i cnt) (void))
(let ([namespaces (map module->namespace modules)])
(test-expr `(mergesort (elements ,(build-expr 'set (random 5))) <)
namespaces compare))))
(test 1000 '("../list-set.scm" "../red-black-tree-set.scm") default-compare)