@@ -34,36 +34,119 @@ let flatten_rec def =
3434 | Ast. RecD defs -> defs
3535 | _ -> [ def ]
3636
37- (* List of relation names that appear in the prose of the validation rules *)
38- let validation_helper_relations = [
39- " Expand" ;
40- " Expand_use" ;
41- " ImmutReachable" ;
42- " NotImmutReachable"
43- ]
44- let is_validation_helper_relation def =
45- match def.it with
46- | Ast. RelD (id , _ , _ , _ , _ ) ->
47- List. mem id.it validation_helper_relations
48- | _ -> false
4937(* NOTE: Assume validation relation is `|-` *)
5038let is_validation_relation def =
5139 match def.it with
5240 | Ast. RelD (_ , _ , mixop , _ , _ ) ->
5341 List. exists (List. exists (fun atom -> atom.it = Atom. Turnstile )) (Mixop. flatten mixop)
5442 | _ -> false
5543
56- let extract_validation_il il =
57- il
58- |> List. concat_map flatten_rec
59- |> List. filter
60- (fun rel -> is_validation_relation rel || is_validation_helper_relation rel)
44+ let pairwise_concat xyss =
45+ (* [(xs1, ys1); (xs2, ys2)] ==> (xs1@xs2, ys1@ys2) *)
46+ let xss, yss = List. split xyss in
47+ List. concat xss, List. concat yss
48+
49+ let pairwise_concat_map f xs = List. map f xs |> pairwise_concat
50+
51+ (* dependent_rei_id_of_X: (x:X) -> (rel_id list, func_id list) *)
52+
53+ let dependent_rel_id_of_exp exp =
54+ let func_ids = ref [] in
55+ let collect_func_call e =
56+ (match e.it with
57+ | Ast. CallE (id , _ ) -> func_ids := id :: ! func_ids
58+ | _ -> ()
59+ );
60+ e
61+ in
62+
63+ let open Il2al.Il_walk in
64+ let transformer = { base_transformer with
65+ transform_exp = collect_func_call;
66+ } in
67+ ignore (transform_exp transformer exp);
68+
69+ [] , ! func_ids
70+
71+ let rec dependent_rel_id_of_prem prem =
72+ match prem.it with
73+ | Ast. IfPr exp -> dependent_rel_id_of_exp exp
74+ | Ast. LetPr (exp1 , exp2 , _ ) -> pairwise_concat_map dependent_rel_id_of_exp [exp1; exp2]
75+ | Ast. RulePr (id , _ , _ , exp ) -> pairwise_concat [([id], [] ); dependent_rel_id_of_exp exp]
76+ | Ast. IterPr (prem' , _ ) -> dependent_rel_id_of_prem prem'
77+ | _ -> ([] , [] )
78+
79+ let dependent_ids_of_rule rule =
80+ match rule.it with
81+ | Ast. RuleD (_ , _ , _ , _ , prems ) -> pairwise_concat_map dependent_rel_id_of_prem prems
82+
83+ let dependent_ids_of_clause clause =
84+ match clause.it with
85+ | Ast. DefD (_ , _ , _ , prems ) -> pairwise_concat_map dependent_rel_id_of_prem prems
86+
87+ let dependent_ids_of_def def =
88+ match def.it with
89+ | Ast. RelD (_ , _ , _ , _ , rules ) -> pairwise_concat_map dependent_ids_of_rule rules
90+ | Ast. DecD (_ , _ , _ , clauses ) -> pairwise_concat_map dependent_ids_of_clause clauses
91+ | _ -> ([] , [] )
6192
6293let rel_has_id id rel =
6394 match rel.it with
64- | Ast. RelD (id' , _ , _ , _ , _ ) -> id.it = id'.it
95+ | Ast. RelD (id' , _ , _ , _ , _ ) -> Eq. eq_id id id'
96+ | _ -> false
97+
98+ let func_has_id id func =
99+ match func.it with
100+ | Ast. DecD (id' , _ , _ , _ ) -> Eq. eq_id id id'
65101 | _ -> false
66102
103+ let id_to_rel defs id =
104+ List. find (rel_has_id id) defs
105+
106+ let id_to_func funcs id =
107+ List. find (func_has_id id) funcs
108+
109+ let rec dedup ids =
110+ match ids with
111+ | [] -> []
112+ | hd :: tl ->
113+ let tl' = List. filter (fun id -> not (Eq. eq_id hd id)) tl in
114+ hd :: dedup tl'
115+
116+ let extract_validation_il il =
117+ let all_defs = List. concat_map flatten_rec il in
118+ let validation_rels = List. filter is_validation_relation all_defs in
119+
120+ (* Expand according to the premise dependency *)
121+ let rec expand (prev_rels , prev_funcs ) (new_rels , new_funcs ) =
122+ let rels = new_rels @ prev_rels in
123+ let is_new_rel_id id = List. for_all (Fun. negate (rel_has_id id)) rels in
124+ let funcs = new_funcs @ prev_funcs in
125+ let is_new_func_id id = List. for_all (Fun. negate (func_has_id id)) funcs in
126+
127+ match new_rels @ new_funcs with
128+ | [] -> rels
129+ | defs ->
130+ let (rel_ids, func_ids) = pairwise_concat_map dependent_ids_of_def defs in
131+
132+ let prem_rels =
133+ rel_ids
134+ |> dedup
135+ |> List. filter is_new_rel_id
136+ |> List. map (id_to_rel all_defs)
137+ in
138+ let prem_funcs =
139+ func_ids
140+ |> dedup
141+ |> List. filter is_new_func_id
142+ |> List. map (id_to_func all_defs)
143+ in
144+
145+ expand (rels, funcs) (prem_rels, prem_funcs)
146+ in
147+
148+ expand ([] , [] ) (validation_rels, [] )
149+
67150let extract_prose_hint hintexp =
68151 match hintexp.it with
69152 | El.Ast. TextE hint -> Some hint
@@ -293,7 +376,8 @@ let rec prem_to_instrs prem =
293376 let rel =
294377 match List. find_opt (rel_has_id id) ! Langs. validation_il with
295378 | Some rel -> rel
296- | None -> failwith (" Unknown relation id: " ^ id.it)
379+ | None -> failwith (
380+ Printf. sprintf " The relation %s is supposed to be included in `validation_il`. Hint: Plese fix `extract_validation_il`." id.it)
297381 in
298382 let frees = (Free. free_prem prem).varid in
299383 let args = exp_to_argexpr e in
0 commit comments