Skip to content

Commit b8dd1ab

Browse files
committed
inline equalities
1 parent fa553ad commit b8dd1ab

2 files changed

Lines changed: 95 additions & 19 deletions

File tree

shell.nix

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66
let
77
smtml = pkgs.ocamlPackages.smtml.overrideAttrs (old: {
88
src = pkgs.fetchFromGitHub {
9-
owner = "formalsec";
9+
owner = "redianthus";
1010
repo = "smtml";
11-
rev = "e259d5b7d108cb2d1102c188132a6c86bbf7705e";
12-
hash = "sha256-8OzNJIyJhfqgDw3ioINN0D0WVTSliG9TP4cUNlrm4s8=";
11+
rev = "84f727e98ceb793043a6e5984a2ce38dd64286a6";
12+
hash = "sha256-0m4fDKYYKmC3UqHIc4ZQW1Fl06seDX5mAKLr4MTYsM4=";
1313
};
1414
doCheck = false;
1515
});

src/symbolic/symbolic_path_condition.ml

Lines changed: 92 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,48 +4,124 @@
44

55
module Union_find = Union_find.Make (Smtml.Symbol)
66

7-
type t = Smtml.Expr.Set.t Union_find.t
7+
type union_find = Smtml.Expr.Set.t Union_find.t
88

9-
let empty : t = Union_find.empty
9+
type equalities = Smtml.Expr.t Smtml.Symbol.Map.t
1010

11-
let add_one (condition : Smtml.Expr.t) pc : t =
11+
type t =
12+
{ union_find : union_find
13+
(** the union find contains many partitions of the whole path condition,
14+
each partition is a set of expressions representing a conjunctions of
15+
transitively related formula, that is, if we have a formula xRy and
16+
yRz, then x, y and z end-up in the same partition. We can quickly
17+
merge two partition and find the partition to which a symbol belongs.
18+
*)
19+
; equalities : equalities
20+
(** the equalities is a map of symbol to known constant values *)
21+
}
22+
23+
let empty : t =
24+
let union_find = Union_find.empty in
25+
let equalities = Smtml.Symbol.Map.empty in
26+
{ union_find; equalities }
27+
28+
let add_one (condition : Smtml.Expr.t) (union_find : union_find) : union_find =
1229
match Smtml.Expr.get_symbols [ condition ] with
1330
| hd :: tl ->
14-
(* We add the first symbol to the UF *)
15-
let pc =
31+
(* We add the first symbol to the union-find *)
32+
let union_find =
1633
let c = Smtml.Expr.Set.singleton condition in
17-
Union_find.add ~merge:Smtml.Expr.Set.union hd c pc
34+
Union_find.add ~merge:Smtml.Expr.Set.union hd c union_find
1835
in
1936
(* We union-ize all symbols together, starting with the first one that has already been added *)
20-
let pc, _last_sym =
37+
let union_find, _last_sym =
2138
List.fold_left
2239
(fun (pc, last_sym) sym ->
2340
(Union_find.union ~merge:Smtml.Expr.Set.union last_sym sym pc, sym) )
24-
(pc, hd) tl
41+
(union_find, hd) tl
2542
in
26-
pc
43+
union_find
2744
| [] ->
2845
(* It means smtml did not properly simplified an expression! *)
2946
assert false
3047

3148
let add (condition : Symbolic_boolean.t) (pc : t) : t =
32-
(* we start by splitting the condition ((P & Q) & R) into a set {P; Q; R} before adding each of P, Q and R into the UF data structure, this way we maximize the independence of the PC *)
49+
(* we start by splitting the condition ((P & Q) & R) into a set {P; Q; R} before adding each of P, Q and R into the union_find data structure, this way we maximize the independence of the PC *)
3350
let splitted_condition = Smtml.Typed.Bool.split_conjunctions condition in
34-
Smtml.Expr.Set.fold add_one splitted_condition pc
51+
let splitted_condition =
52+
Smtml.Expr.Set.map Smtml.Expr.simplify splitted_condition
53+
in
54+
let equalities =
55+
Smtml.Expr.Set.fold
56+
(fun (condition : Smtml.Expr.t) equalities ->
57+
match Smtml.Expr.view condition with
58+
| Relop (_, Smtml.Ty.Relop.Eq, e1, e2) -> begin
59+
match (Smtml.Expr.view e1, Smtml.Expr.view e2) with
60+
| Smtml.Expr.Symbol s, _ ->
61+
if Smtml.Expr.is_symbolic e2 then equalities
62+
else Smtml.Symbol.Map.add s e2 equalities
63+
| _, Symbol s ->
64+
if Smtml.Expr.is_symbolic e1 then equalities
65+
else Smtml.Symbol.Map.add s e1 equalities
66+
| _ -> equalities
67+
end
68+
| _ -> equalities )
69+
splitted_condition pc.equalities
70+
in
71+
let union_find =
72+
Smtml.Expr.Set.fold add_one splitted_condition pc.union_find
73+
in
74+
{ union_find; equalities }
75+
76+
let equality_to_expr sym expr =
77+
Smtml.Expr.Bool.equal (Smtml.Expr.symbol sym) expr
78+
79+
let equalities_to_expr_list (equalities : equalities) : Smtml.Expr.t list =
80+
Smtml.Symbol.Map.bindings equalities
81+
|> List.map (fun (sym, expr) -> equality_to_expr sym expr)
82+
83+
let equalities_to_set (equalities : equalities) : Smtml.Expr.Set.t =
84+
Smtml.Symbol.Map.fold
85+
(fun sym expr set ->
86+
let e = equality_to_expr sym expr in
87+
Smtml.Expr.Set.add e set )
88+
equalities Smtml.Expr.Set.empty
89+
90+
let filter_set (set : Smtml.Expr.Set.t) : Smtml.Expr.Set.t =
91+
Smtml.Expr.Set.fold
92+
(fun expr set ->
93+
match Smtml.Expr.view expr with
94+
| Val True -> set
95+
| _ -> Smtml.Expr.Set.add expr set )
96+
set Smtml.Expr.Set.empty
3597

3698
(* Get all sub conditions of the path condition as a list of independent sets of constraints. *)
37-
let slice pc = Union_find.explode pc
99+
let slice (pc : t) =
100+
let slice =
101+
Union_find.explode pc.union_find
102+
|> List.map (Smtml.Expr.Set.inline_symbol_values pc.equalities)
103+
|> List.map filter_set
104+
in
105+
let equalities =
106+
equalities_to_expr_list pc.equalities |> List.map Smtml.Expr.Set.singleton
107+
in
108+
slice @ equalities
38109

39110
(* Return the set of constraints from [pc] that are relevant for [sym]. *)
40-
let slice_on_symbol (sym : Smtml.Symbol.t) pc : Smtml.Expr.Set.t =
41-
match Union_find.find_opt sym pc with
42-
| Some s -> s
111+
let slice_on_symbol (sym : Smtml.Symbol.t) (pc : t) : Smtml.Expr.Set.t =
112+
match Union_find.find_opt sym pc.union_find with
113+
| Some s ->
114+
let set =
115+
Smtml.Expr.Set.inline_symbol_values pc.equalities s |> filter_set
116+
in
117+
let equalities = equalities_to_set pc.equalities in
118+
Smtml.Expr.Set.union set equalities
43119
| None ->
44120
(* if there is a symbol, it should have been added to the union-find structure before, otherwise it means `add` has not been called properly before *)
45121
assert false
46122

47123
(* Return the set of constraints from [pc] that are relevant for [c]. *)
48-
let slice_on_condition (c : Symbolic_boolean.t) pc : Smtml.Expr.Set.t =
124+
let slice_on_condition (c : Symbolic_boolean.t) (pc : t) : Smtml.Expr.Set.t =
49125
match Smtml.Typed.get_symbols [ c ] with
50126
| sym0 :: _tl ->
51127
(* we need only the first symbol as all the others should have been merged with it *)

0 commit comments

Comments
 (0)