Source file path_condition.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
module Union_find = struct
include Union_find.Make (Smtml.Symbol)
type nonrec t = Smtml.Expr.Set.t t
let pp : t Fmt.t = fun ppf union_find -> pp Smtml.Expr.Set.pp ppf union_find
end
module Equalities : sig
type t = Smtml.Value.t Smtml.Symbol.Map.t
val pp : t Fmt.t
end = struct
type t = Smtml.Value.t Smtml.Symbol.Map.t
let pp ppf v =
Fmt.pf ppf "@[<hov 1>{%a}@]"
(Fmt.iter_bindings
~sep:(fun ppf () -> Fmt.pf ppf ",@ ")
Smtml.Symbol.Map.iter
(fun ppf (k, v) ->
Fmt.pf ppf "%a = %a" Smtml.Symbol.pp k Smtml.Value.pp v ) )
v
end
type t =
{ union_find : Union_find.t
; equalities : Equalities.t
}
let pp : t Fmt.t =
fun ppf { union_find; equalities } ->
Fmt.pf ppf "union find:@\n @[<v>%a@]@\nequalities:@\n @[<v>%a@]@\n"
Union_find.pp union_find Equalities.pp equalities
let empty : t =
let union_find = Union_find.empty in
let equalities = Smtml.Symbol.Map.empty in
{ union_find; equalities }
let rec add_one_equality symbol value (pc : t) : t =
let equalities = Smtml.Symbol.Map.add symbol value pc.equalities in
match Union_find.find_and_remove_opt symbol pc.union_find with
| Some (set, union_find) ->
let pc = { union_find; equalities } in
Smtml.Expr.Set.fold add_one_constraint set pc
| None -> { pc with equalities }
and add_one_constraint (condition : Smtml.Expr.t) (pc : t) : t =
let condition = Smtml.Expr.inline_symbol_values pc.equalities condition in
let condition = Smtml.Expr.simplify condition in
let pc, shortcut =
match Smtml.Expr.view condition with
| Relop (_, Smtml.Ty.Relop.Eq, e1, e2) -> begin
match (Smtml.Expr.view e1, Smtml.Expr.view e2) with
| Smtml.Expr.Symbol symbol, Val value | Val value, Symbol symbol -> begin
match Smtml.Symbol.Map.find_opt symbol pc.equalities with
| None ->
(add_one_equality symbol value pc, true)
| Some value' ->
assert (Smtml.Eval.relop symbol.ty Eq value value');
(pc, true)
end
| _ -> (pc, false)
end
| _ -> (pc, false)
in
if shortcut then pc
else
match Smtml.Expr.view condition with
| Val True ->
pc
| Val False ->
assert false
| _ -> begin
match Smtml.Expr.get_symbols [ condition ] with
| hd :: tl ->
let union_find =
let c = Smtml.Expr.Set.singleton condition in
Union_find.add ~merge:Smtml.Expr.Set.union hd c pc.union_find
in
let union_find, _last_sym =
List.fold_left
(fun (union_find, last_sym) sym ->
( Union_find.union ~merge:Smtml.Expr.Set.union last_sym sym
union_find
, sym ) )
(union_find, hd) tl
in
{ pc with union_find }
| [] ->
assert false
end
let add_checked_sat_condition (condition : Smtml.Typed.Bool.t) (pc : t) : t =
let splitted_condition = Smtml.Typed.Bool.split_conjunctions condition in
Smtml.Expr.Set.fold add_one_constraint splitted_condition pc
let to_list (pc : t) =
let uf = Union_find.explode pc.union_find in
Smtml.Symbol.Map.fold
(fun symbol value acc ->
let eq =
Smtml.Expr.Bool.equal (Smtml.Expr.symbol symbol)
(Smtml.Expr.value value)
|> Smtml.Expr.Set.singleton
in
eq :: acc )
pc.equalities uf
let slice_on_symbol (sym : Smtml.Symbol.t) (pc : t) : Smtml.Expr.Set.t =
match Union_find.find_opt sym pc.union_find with
| Some s -> s
| None -> (
match Smtml.Symbol.Map.find_opt sym pc.equalities with
| Some value ->
let eq =
Smtml.Expr.Bool.equal (Smtml.Expr.symbol sym) (Smtml.Expr.value value)
in
Smtml.Expr.Set.singleton eq
| None -> Smtml.Expr.Set.empty )
let slice_on_new_condition (c : Smtml.Typed.Bool.t) (pc : t) : Smtml.Expr.Set.t
=
let symbols = Smtml.Typed.get_symbols [ c ] in
List.fold_left
(fun set symbol ->
let slice = slice_on_symbol symbol pc in
Smtml.Expr.Set.union set slice )
Smtml.Expr.Set.empty symbols
let get_known_equalities (pc : t) : Smtml.Value.t Smtml.Symbol.Map.t =
pc.equalities