forked from jeapostrophe/exp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
fp-rules.rkt
101 lines (95 loc) · 2.45 KB
/
fp-rules.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
99
100
101
#lang racket
;; fp rules
(define fprops (make-weak-hash))
(define (fprop-set stx k v)
(printf "~v: ~v = ~v!\n" stx k v)
(hash-update! fprops stx
(λ (ht) (hash-set ht k v))
(λ () (hasheq)))
stx)
(define (fprop-get stx k)
(define ans
(hash-ref (hash-ref fprops stx (λ () (hasheq)))
k
#f))
(printf "~v: ~v = ~v\n" stx k ans)
ans)
(define (safe+ x y)
(and x y (+ x y)))
(define (safe-zero? x)
(and (number? x) (zero? x)))
(define (fexpand stx)
(define my-+
(match-lambda
[`(+ ,lhs ,rhs)
(cond
[(safe-zero? (fprop-get lhs 'num))
rhs]
[(safe-zero? (fprop-get rhs 'num))
lhs]
[else
(define ans (safe+ (fprop-get lhs 'num)
(fprop-get rhs 'num)))
(fprop-set stx 'num ans)
(if ans
ans
`(real+ ,lhs ,rhs))])]))
(define my-datum
(match-lambda
[(? number? n)
(fprop-set n
'num
n)]))
(define changed? #f)
(define fix (make-hash))
(define (consult-fix stx)
(cond
[(hash-has-key? fix stx)
(hash-ref fix stx)]
[(list? stx)
(map consult-fix stx)]
[else
stx]))
(define (fexpand/inner stx)
(printf "~v\n" `(fexpand/inner ,stx))
(match stx
[(list-rest '+ inner)
(my-+ stx #;(cons '+ (consult-fix inner)))]
[(? number?)
(my-datum stx #;(consult-fix stx))]
[(? symbol?)
stx]
[(list-rest 'real+ es)
(cons 'real+ (map fexpand/outer es))]))
(define (fexpand/outer stx)
(printf "~v\n" `(fexpand/outer ,stx))
(define last (hash-ref fix stx #f))
(define after (fexpand/inner stx))
(printf "~v ==> ~v [~v]\n" stx after last)
(unless (equal? last after)
(hash-set! fix stx after)
(set! changed? #t))
(if (equal? stx after)
after
(fexpand/outer after)))
(define (fexpand/fix stx)
(printf "~v\n" `(fexpand/fix ,stx))
(set! changed? #f)
(define after (fexpand/outer stx))
(if changed?
(fexpand/fix stx)
after))
(fexpand/fix stx))
;; tests
(require tests/eli-tester)
(test
(fexpand `(+ 0 1)) => `1
(fexpand `(+ 1 0)) => `1
(fexpand `(+ x 0)) => `x
(fexpand `(+ 0 x)) => `x
(fexpand `(+ 1 3)) => `4
(fexpand `(+ -1 1)) => `0
(fexpand `(+ 1 x)) => `(real+ 1 x)
(printf "\n\nBing\n\n")
(fexpand `(+ 3 (+ -1 1))) => `3
)