/
alternative.rkt
68 lines (54 loc) · 1.99 KB
/
alternative.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
#lang racket
(require "programs.rkt")
(require "points.rkt")
(require "core/matcher.rkt")
(require "common.rkt")
(provide alt-delta alt-delta? (struct-out alt)
make-alt alt? alt-program alt-change
alt-cost alt-add-event
alt-apply alt-rewrite-expression alt-rewrite-rm)
;; Alts are a lightweight audit trail.
;; An alt records a low-level view of how Herbie got
;; from one program to another.
;; They are a labeled linked list of changes.
(struct alt (program event prevs)
#:transparent
#:methods gen:custom-write
[(define (write-proc alt port mode)
(display "#<alt " port)
(write (alt-program alt) port)
(display ">" port))])
(define (alt-delta program change prev)
(alt program (list 'change change) (list prev)))
(define (make-alt prog)
(alt prog 'start '()))
(define (alt-delta? altn)
(match (alt-event altn)
[(list 'change _) true]
[_ false]))
(define (alt-change altn)
(match altn
[(alt _ (list 'change cng) _) cng]
[(alt _ _ prevs) (ormap alt-change prevs)]))
(define (alt-prev altn)
(match altn
[(alt _ (list 'change cng) (list prev)) prev]
[(alt _ _ '()) #f]
[(alt _ _ `(,prev ,_ ...)) (alt-prev prev)]))
(define (alt-cost altn)
(program-cost (alt-program altn)))
(define (alt-apply altn . changes)
(foldl (λ (cng altn)
(alt-delta (change-apply cng (alt-program altn)) cng altn))
altn changes))
(define (alt-rewrite-expression alt #:destruct [destruct? #f] #:root [root-loc '()])
(let ([subtree (location-get root-loc (alt-program alt))])
(map (curry alt-apply alt)
(rewrite-expression subtree #:destruct destruct? #:root root-loc))))
(define (alt-rewrite-rm alt #:root [root-loc '()])
(let ([subtree (location-get root-loc (alt-program alt))])
(map (curry apply alt-apply alt)
(map reverse
(rewrite-expression-head subtree #:root root-loc)))))
(define (alt-add-event altn event)
(alt (alt-program altn) event (list altn)))