-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy patheq.llrl
68 lines (60 loc) · 2.02 KB
/
eq.llrl
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
(no-implicit-std)
(import "std/prelude/stage-0" _)
(import "std/s" s/_)
(import "std/never" Never never)
(import "std/control" _)
(import "std/derive" derive/_)
(import "std/bool" Bool not and)
(export Eq eq? ne? = Eq._ derive/Eq)
(class (Eq A)
(function (eq? a b) {(-> A A Bool)})
(transparent-function (ne? a b) {(-> A A Bool)}
(not (eq? a b))))
(macro (= s)
(s/match s
[(_)
(ok '#t)]
[(_ _)
(ok '#t)]
[(_ ,a ,b)
(ok `(,\eq? ,a ,b))]
[(_ ,a ,@bs)
@let ([tmp-a (gensym)])
(ok
`(let ([,tmp-a ,a])
(,\and ,@(s/map (lambda (b) `(,\eq? ,tmp-a ,b)) bs)!)))]
[_
(err "Expected (= expr ...)")]))
(instance Eq.Never (Eq Never)
(transparent-function (eq? a b) (never a) (never b)))
(instance Eq.Bool (Eq Bool)
(transparent-function (eq? a b) (<bool/eq?> a b)))
(builtin-op <bool/eq?> {(-> Bool Bool Bool)} "integer.eq")
(macro (derive/Eq s)
(s/match s
[(_ _ ,type-con ,@value-cons)
@let (
[inst-name (derive/symbol/concat 'Eq. (derive/data/type-con/name type-con))!]
[inst-signature (derive/data/type-con/instance-signature \Eq type-con)!]
[match-body
(match value-cons
[(s:list (let value-con)) `(,(equality-clause value-con)!)]
[_ `(,@(s/traverse equality-clause value-cons)! [_ #f])])])
(ok
`(instance ,inst-name ,@inst-signature
(function (eq? a b)
(match (: a b)
,@match-body))))]
[_
(err "Unsupported derivation")]))
(function (equality-clause value-con)
@let (
[con-name (derive/data/value-con/name value-con)]
[con-fields (derive/data/value-con/fields value-con)])
(ok (if-match1 (some (let fields)) con-fields
(let ([l-names (s/map [^1 (gensym)] fields)!]
[r-names (s/map [^1 (gensym)] fields)!])
`[(: (,con-name ,@(s/map [^1 `(let ,%1)] l-names)!)
(,con-name ,@(s/map [^1 `(let ,%1)] r-names)!))
(,\and ,@(s/zip [^2 `(,\eq? ,%1 ,%2)] l-names r-names)!)])
`[(: ,con-name ,con-name) #t])))