forked from emina/rosette
-
Notifications
You must be signed in to change notification settings - Fork 0
/
exprs.rkt
98 lines (85 loc) · 3.68 KB
/
exprs.rkt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#lang racket
(require rosette/base/core/term)
(provide naive naive* reduce test-exprs)
(define (concrete? x) (not (term? x)))
; Naive implementation of a non-commutative primitive operator.
(define (naive op)
(case (procedure-arity op)
[(1) (lambda (x) (if (concrete? x) (op x) (expression op x)))]
[(2) (lambda (x y)
(cond [(and (concrete? x) (concrete? y)) (op x y)]
[else (expression op x y)]))]
[else (lambda xs
(if (andmap concrete? xs) (apply op xs) (apply expression op xs)))]))
; Naive implementation of a commutative primitive operator.
(define (naive* op)
(case (procedure-arity op)
[(2) (lambda (x y)
(cond [(and (concrete? x) (concrete? y)) (op x y)]
[(concrete? x) (expression op x y)]
[(concrete? y) (expression op y x)]
[(term<? x y) (expression op x y)]
[else (expression op y x)]))]
[else (lambda xs
(if (andmap concrete? xs)
(apply op xs)
(let-values ([(lits terms) (partition concrete? xs)])
(if (null? lits)
(apply expression op (sort terms term<?))
(apply expression op (apply op lits) (sort terms term<?))))))]))
; Turns a naive expression into a partially reduced one.
(define (reduce e)
(match e
[(expression op t ...)
(apply op (map reduce t))]
[_ e]))
; Generates all expression of up to (and including the given depth).
; Depth of more than 2 takes a very long time to generate.
(define (test-exprs depth ops terminals)
(remove-duplicates
(apply append (map cannonicalize (reverse (exprs depth ops terminals))))))
(define (key e [cache (make-hash)])
(match e
[(expression o t ...)
(list* o (map (curryr key cache) t))]
[(? constant?)
(hash-ref! cache e (hash-count cache))]
[_ e]))
(define (cannonicalize es)
(define keys (make-hash))
(define (seen? e)
(let ([k (key e)])
(or (hash-has-key? keys k)
(hash-ref! keys k #f))))
(for/list ([e es] #:unless (seen? e)) e)) ;(or (seen? e) (equal? e (reduce e)))) e))
(define (exprs depth ops terminals)
(if (= depth 0)
(list terminals)
(let* ([subexprs (exprs (- depth 1) ops terminals)]
[subexprs* (for/list ([es subexprs])
(remove-duplicates (map reduce es)))]
[bot (remove-duplicates (apply append (cdr subexprs*)))]
[top (remove* bot (car subexprs*))])
(cons
(apply
append
(for/list ([op ops])
(case (procedure-arity op)
[(1) (remove-duplicates (map op top))]
[(2) (remove-duplicates
(append (for*/list ([x top][y top]) (op x y))
(for*/list ([x top][y bot]) (op x y))
(for*/list ([x bot][y top]) (op x y))))]
[else (remove-duplicates
(append
(for*/list ([x top][y top]) (op x y))
(for*/list ([x top][y bot]) (op x y))
(for*/list ([x bot][y top]) (op x y))
(for*/list ([x top][y top][z top]) (op x y z))
(for*/list ([x top][y top][z top]) (op x y z))
(for*/list ([x top][y bot][z top]) (op x y z))
(for*/list ([x top][y bot][z bot]) (op x y z))
(for*/list ([x bot][y top][z top]) (op x y z))
(for*/list ([x bot][y bot][z top]) (op x y z))
(for*/list ([x bot][y top][z bot]) (op x y z))))])))
subexprs))))