Source file Optimize.ml
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
open Core
open Syntax
let mk_and pr1 pr2 =
match pr1, pr2 with
| True, _ ->
pr2
| _, True ->
pr1
| False, _ ->
False
| _, False ->
False
| _ ->
And(pr1, pr2)
let mk_or pr1 pr2 =
match pr1, pr2 with
| True, _ ->
True
| _, True ->
True
| False, _ ->
pr2
| _, False ->
pr1
| _ ->
Or(pr1, pr2)
let mk_not pat =
match pat with
| False -> True
| True -> False
| _ -> Neg(pat)
let mk_filter pr =
Filter (pr)
let mk_union pol1 pol2 =
match pol1, pol2 with
| Filter False, _ ->
pol2
| _, Filter False ->
pol1
| _ ->
Union(pol1,pol2)
let mk_seq pol1 pol2 =
match pol1, pol2 with
| Filter True, _ ->
pol2
| _, Filter True ->
pol1
| Filter False, _ ->
pol1
| _, Filter False ->
pol2
| _ ->
Seq(pol1,pol2)
let mk_star pol =
match pol with
| Filter True ->
pol
| Filter False ->
Filter True
| Star(pol1) -> pol
| _ -> Star(pol)
let specialize_pred sw pr =
let rec loop pr k =
match pr with
| True ->
k pr
| False ->
k pr
| Neg pr1 ->
loop pr1 (fun pr -> k (mk_not pr))
| Test (Switch v) ->
if Poly.(v = sw) then
k True
else
k False
| Test _ ->
k pr
| And (pr1, pr2) ->
loop pr1 (fun p1 -> loop pr2 (fun p2 -> k (mk_and p1 p2)))
| Or (pr1, pr2) ->
loop pr1 (fun p1 -> loop pr2 (fun p2 -> k (mk_or p1 p2))) in
loop pr (fun x -> x)
let specialize_policy sw pol =
let rec loop pol k =
match pol with
| Filter pr ->
k (Filter (specialize_pred sw pr))
| Mod hv ->
k pol
| Union (pol1, pol2) ->
loop pol1 (fun p1 -> loop pol2 (fun p2 -> k (mk_union p1 p2)))
| Seq (pol1, pol2) ->
loop pol1 (fun p1 -> loop pol2 (fun p2 -> k (mk_seq p1 p2)))
| Star pol ->
loop pol (fun p -> k (mk_star p))
| Let {id; init; mut; body} ->
loop body (fun body -> k (Let {id; init; mut; body}))
| Link _ | VLink _ | Dup ->
failwith "cannot specialize global policy" in
loop pol (fun x -> x)
let mk_big_and = List.fold_left ~f:mk_and ~init:True
let mk_big_or = List.fold_left ~f:mk_or ~init:False
let mk_big_union = List.fold_left ~f:mk_union ~init:drop
let mk_big_seq = List.fold_left ~f:mk_seq ~init:id
let rec list_of_and (pred : pred) : pred list = match pred with
| And (a, b) -> list_of_and a @ list_of_and b
| _ -> [pred]
let rec list_of_or (pred : pred) : pred list = match pred with
| Or (a, b) -> list_of_or a @ list_of_or b
| _ -> [pred]
let rec list_of_seq (pol : policy) : policy list = match pol with
| Seq (p, q) -> list_of_seq p @ list_of_seq q
| _ -> [pol]
let rec list_of_union (pol : policy) : policy list = match pol with
| Union (p, q) -> list_of_union p @ list_of_union q
| _ -> [pol]
let rec norm_pred (pred : pred) : pred = match pred with
| True | False | Test _ -> pred
| Neg a -> Neg (norm_pred a)
| And (a, b) ->
let pred' = And (norm_pred a, norm_pred b) in
mk_big_and (list_of_and pred')
| Or (a, b) ->
let pred' = Or (norm_pred a, norm_pred b) in
mk_big_or (list_of_or pred')
let rec norm_policy (pol : policy) : policy = match pol with
| Mod _ | Link _ | VLink _ -> pol
| Filter a -> Filter (norm_pred a)
| Star p -> Star (norm_policy p)
| Union (p, q) ->
let pol' = Union (norm_policy p, norm_policy q) in
mk_big_union (list_of_union pol')
| Seq (p, q) ->
let pol' = Seq (norm_policy p, norm_policy q) in
mk_big_seq (list_of_seq pol')
| Let {id; init; mut; body} ->
Let {id; init; mut; body = norm_policy body}
| Dup -> Dup
let rec flatten_union_k (pol : policy)
(acc : policy list)
(k : policy list -> 'a) : 'a = match pol with
| Union (p, q) -> flatten_union_k p acc (fun acc ->
flatten_union_k q acc k)
| _ -> k (pol :: acc)
let flatten_union (pol : policy) : policy list = flatten_union_k pol [] ident