1structure decidable_separationLogicLib :> decidable_separationLogicLib =
2struct
3
4open HolKernel Parse boolLib bossLib;
5
6(*
7quietdec := true;
8loadPath :=
9            (concat Globals.HOLDIR "/examples/decidable_separationLogic/src") ::
10            !loadPath;
11
12map load ["finite_mapTheory", "relationTheory", "congLib", "sortingTheory",
13   "rich_listTheory", "decidable_separationLogicTheory", "listLib",
14   "decidable_separationLogicLibTheory", "optionLib", "stringLib"];
15show_assums := true;
16*)
17
18open finite_mapTheory relationTheory pred_setTheory congLib sortingTheory
19   listTheory rich_listTheory decidable_separationLogicTheory listLib
20   decidable_separationLogicLibTheory listSyntax;
21
22
23(*
24quietdec := false;
25*)
26
27
28val INFINITE_UNIV___THMs = ref ([]:thm list);
29
30
31fun DUMMY_CONV t =
32   let
33      val v = mk_var("XXXX", type_of t);
34      val thm = mk_thm ([], mk_eq (t, v))
35   in
36      thm
37   end;
38
39
40
41val swap_cs = reduceLib.num_compset ();
42val _ = computeLib.add_thms [SWAP_REWRITES, APPEND]
43   swap_cs;
44
45val ds_direct_cs = reduceLib.num_compset ();
46val _ = computeLib.add_thms [MAP, PF_TURN_EQ_def, SAFE_MAP_THM]
47   ds_direct_cs;
48
49
50(*
51val sf_points_to_list_cs = reduceLib.num_compset ();
52val _ = computeLib.add_thms [SF_POINTS_TO_LIST_def, SAFE_FILTER_THM, MAP, APPEND,
53   DISJOINT_LIST_PRODUCT_def, pairTheory.UNCURRY, pairTheory.FST, pairTheory.SND]
54   sf_points_to_list_cs;
55*)
56
57fun SMALLFOOT_ERR s =
58   raise HOL_ERR {message = s, origin_function = "", origin_structure = "decidable_separationLogicLib"}
59
60
61
62(************************************************************
63 Term consts
64*************************************************************)
65
66val LIST_DS_ENTAILS_term = ``LIST_DS_ENTAILS``;
67val pf_true_term = ``pf_true``;
68val pf_equal_term = ``pf_equal``;
69val pf_unequal_term = ``pf_unequal``;
70
71val sf_star_term = ``sf_star``;
72val sf_emp_term = ``sf_emp``;;
73val sf_ls_term = ``sf_ls``;
74val sf_points_to_term = ``sf_points_to``;
75val sf_tree_term = ``sf_tree``;
76val sf_bin_tree_term = ``sf_bin_tree``;
77
78val dse_var_term = ``dse_var``;
79val dse_const_term = ``dse_const``;
80val dsv_nil_term = ``dsv_nil``;
81val dse_nil_term = ``dse_nil``;
82
83
84(************************************************************
85 destructors
86************************************************************)
87local
88   fun strip_cons_int l t =
89      if not (listSyntax.is_cons t) then (l, t) else
90      let
91         val (e, t') = listSyntax.dest_cons t
92      in
93         strip_cons_int (l@[e]) t'
94      end
95in
96   val strip_cons = strip_cons_int []
97end;
98
99fun list_mk_cons [] b  = b |
100      list_mk_cons (t::tL) b  =
101      listSyntax.mk_cons (t, list_mk_cons tL b);
102
103
104fun dest_LIST_DS_ENTAILS t =
105   let
106      val (f, args) = strip_comb t;
107      val _ = if same_const f LIST_DS_ENTAILS_term then () else
108                  (SMALLFOOT_ERR "NO DEST_LIST_ENTAILS!");
109      val _ = if (length args = 3) then () else
110                  (SMALLFOOT_ERR "Wrong No. of ARGS!");
111      val (pre, ante, cons) = (el 1 args, el 2 args, el 3 args);
112      val (c1, c2) = pairLib.dest_pair pre;
113      val (ante_pf, ante_sf) = pairLib.dest_pair ante;
114      val (cons_pf, cons_sf) = pairLib.dest_pair cons;
115   in
116      (c1, c2, ante_pf, ante_sf, cons_pf, cons_sf)
117   end;
118
119
120
121fun dest_pf_equal pf =
122   let
123      val (f, args) = strip_comb pf;
124      val _ = if same_const f pf_equal_term then () else
125                  (SMALLFOOT_ERR "NO PF_EQUAL!");
126      val _ = if (length args = 2) then () else
127                  (SMALLFOOT_ERR "Wrong No. of ARGS!");
128   in
129      (hd args, hd (tl args))
130   end;
131
132
133fun dest_pf_unequal pf =
134   let
135      val (f, args) = strip_comb pf;
136      val _ = if same_const f pf_unequal_term then () else
137                  (SMALLFOOT_ERR "NO PF_UNEQUAL!");
138      val _ = if (length args = 2) then () else
139                  (SMALLFOOT_ERR "Wrong No. of ARGS!");
140   in
141      (hd args, hd (tl args))
142   end;
143
144
145(*
146   val sf = ``sf_ls f e1 e2``
147*)
148fun dest_sf_ls sf =
149   let
150      val (f, args) = strip_comb sf;
151      val _ = if same_const f sf_ls_term then () else
152                  (SMALLFOOT_ERR "NO SF_LIST!");
153      val _ = if (length args = 3) then () else
154                  (SMALLFOOT_ERR "Wrong No. of ARGS!");
155   in
156      (el 1 args, el 2 args, el 3 args)
157   end
158
159
160(*
161   val sf = ``sf_bin_tree (f1,f2) e``
162   val sf = ``sf_bin_tree fL e``
163*)
164fun dest_sf_bin_tree sf =
165   let
166      val (f, args) = strip_comb sf;
167      val _ = if same_const f sf_bin_tree_term then () else
168                  (SMALLFOOT_ERR "NO SF_BIN_TREE!");
169      val _ = if (length args = 2) then () else
170                  (SMALLFOOT_ERR "Wrong No. of ARGS!");
171      val (f1,f2) = pairLib.dest_pair (el 1 args)
172      val _ = if f1 = f2 then (SMALLFOOT_ERR "NO SF_BIN_TREE!") else ();
173   in
174      (f1,f2, el 2 args, el 1 args)
175   end
176
177
178(*
179   val sf = ``sf_tree (f1::f2::l) e1 e2``
180   val sf = ``sf_ls f e1 e2``
181   val sf = ``sf_bin_tree (f1,f2) e``
182   val sf = ``sf_bin_tree fL e``
183*)
184fun dest_sf_tree sf =
185   let
186      val (f, args) = strip_comb sf;
187      val _ = if same_const f sf_tree_term then () else
188                  (SMALLFOOT_ERR "NO SF_TREE!");
189      val _ = if (length args = 3) then () else
190                  (SMALLFOOT_ERR "Wrong No. of ARGS!");
191      val p = strip_cons (el 1 args)
192
193   in
194      (p, el 2 args, el 3 args)
195   end
196
197
198fun dest_sf_tree_ext sf =
199   let
200      val (p, es, e) = dest_sf_tree sf;
201   in
202      (sf, p, es, e)
203   end handle _ =>
204   let
205      val (f1, f2, e, _) = dest_sf_bin_tree sf;
206      val (_, typeL) = (dest_type (type_of e));
207      val es = inst [alpha |-> el 1 typeL, beta |-> el 2 typeL] ``dse_nil:('a, 'b) ds_expression``;
208   in
209      (sf, ([f1,f2], mk_list ([], type_of f1)), es, e)
210   end handle _ =>
211   let
212      val (f, e, es) = dest_sf_ls sf;
213   in
214      (sf, ([f], mk_list ([], type_of f)), es, e)
215   end;
216
217
218(*
219   val sf = ``sf_points_to e ((f1, e1)::(f2,e2)::l)``
220*)
221fun dest_sf_points_to sf =
222   let
223      val (f, args) = strip_comb sf;
224      val _ = if same_const f sf_points_to_term then () else
225                  (SMALLFOOT_ERR "NO POINTS_TO!");
226      val _ = if (length args = 2) then () else
227                  (SMALLFOOT_ERR "Wrong No. of ARGS!");
228      val (l1, l2) = strip_cons (el 2 args);
229      val l1' = map pairLib.dest_pair l1;
230   in
231      (el 1 args, el 2 args, l1', l2)
232   end
233
234
235fun dest_dse_var t =
236   let
237      val (f, args) = strip_comb t;
238      val _ = if same_const f dse_var_term then () else
239                  (SMALLFOOT_ERR "NO VAR!");
240      val _ = if (length args = 1) then () else
241                  (SMALLFOOT_ERR "Wrong No. of ARGS!");
242   in
243      (hd args)
244   end;
245
246fun dest_dse_const t =
247   let
248      val (f, args) = strip_comb t;
249      val _ = if same_const f dse_const_term then () else
250                  (SMALLFOOT_ERR "NO CONST!");
251      val _ = if (length args = 1) then () else
252                  (SMALLFOOT_ERR "Wrong No. of ARGS!");
253   in
254      (hd args)
255   end;
256
257val is_pf_true = same_const pf_true_term;
258val is_sf_emp = same_const sf_emp_term;
259val is_pf_equal = can dest_pf_equal;
260val is_pf_unequal = can dest_pf_unequal;
261val is_sf_ls = can dest_sf_ls;
262val is_sf_points_to = can dest_sf_points_to;
263val is_sf_tree = can dest_sf_tree;
264val is_sf_bin_tree = can dest_sf_bin_tree;
265val is_sf_tree_ext = can dest_sf_tree_ext;
266
267val is_dse_var = can dest_dse_var;
268val is_dse_const = can dest_dse_const;
269fun is_dse_nil ex = same_const ex dse_nil_term;
270
271
272fun is_uneq_2 e1 e2 pf =
273   let
274      val (e1', e2') = dest_pf_unequal pf;
275   in
276      ((e1 = e1') andalso (e2 = e2')) orelse
277      ((e2 = e1') andalso (e1 = e2'))
278   end handle _ => false;
279
280fun is_eq_2 e1 e2 pf =
281   let
282      val (e1', e2') = dest_pf_equal pf;
283   in
284      ((e1 = e1') andalso (e2 = e2')) orelse
285      ((e2 = e1') andalso (e1 = e2'))
286   end handle _ => false;
287
288fun is_uneq_nil ex pf =
289   let
290      val (e1, e2) = dest_pf_unequal pf;
291   in
292      ((e1 = ex) andalso (is_dse_nil e2)) orelse
293      ((e2 = ex) andalso (is_dse_nil e1))
294   end;
295
296
297fun is_pf_equal_refl pf =
298   (let
299      val (e1, e2) = dest_pf_equal pf;
300   in
301      e1 = e2
302   end) handle _ => false
303
304
305fun is_pf_unequal_refl pf =
306   (let
307      val (e1, e2) = dest_pf_unequal pf;
308   in
309      e1 = e2
310   end) handle _ => false
311
312
313fun is_sf_ls_eq sf =
314   (let
315      val (f, e1, e2) = dest_sf_ls sf;
316   in
317      e1 = e2
318   end) handle _ => false
319
320
321fun is_sf_trivial_list sf =
322   let
323      val (f, e1, e2) = dest_sf_ls sf
324   in
325      (e1 = e2)
326   end handle _ => false;
327
328
329fun is_sf_trivial_bin_tree sf =
330   let
331      val (_, _, e, _) = dest_sf_bin_tree sf
332   in
333      is_dse_nil e
334   end handle _ => false;
335
336
337fun is_sf_trivial_tree sf =
338   let
339      val (_, e1, e2) = dest_sf_tree sf
340   in
341      (e1 = e2)
342   end handle _ => false;
343
344
345
346fun is_sf_trivial sf =
347   is_sf_trivial_list sf orelse
348   is_sf_trivial_bin_tree sf orelse
349   is_sf_trivial_tree sf orelse
350   is_sf_emp sf;
351
352
353fun is_pf_trivial pf =
354   is_pf_equal_refl pf orelse
355   is_pf_true pf;
356
357
358fun is_points_to_nil t =
359   let
360      val (e, _, _, _) = dest_sf_points_to t;
361   in
362      is_dse_nil e
363   end handle _ => false;
364
365
366fun pf_eq pf1 pf2 =
367   (if (pf1 = pf2) then (true, false) else
368   if (is_pf_equal pf1) then (
369      let
370         val (e1, e2) = dest_pf_equal pf1;
371         val (e1', e2') = dest_pf_equal pf2;
372      in
373         ((e1 = e2') andalso (e2 = e1'), true) (*e1 = e1' ... => pf1 = pf2*)
374      end
375   ) else
376   if (is_pf_unequal pf1) then (
377      let
378         val (e1, e2) = dest_pf_unequal pf1;
379         val (e1', e2') = dest_pf_unequal pf2;
380      in
381         ((e1 = e2') andalso (e2 = e1'), true) (*e1 = e1' ... => pf1 = pf2*)
382      end
383   ) else (false, false))
384   handle _ => (false, false)
385
386
387
388fun is_dse_nil_list t =
389   let
390      val (_, e1, _) = dest_sf_ls t;
391   in
392      is_dse_nil e1
393   end;
394
395fun is_sf_points_to_ex ex h =
396   let
397      val (ex', _, _, _) = dest_sf_points_to h;
398   in
399      ex' = ex
400   end;
401
402
403(* too strong
404fun is_dse_nil ex = (
405   (same_const ex dse_nil_term) orelse
406   let
407      val n = dest_dse_const ex;
408   in
409      (same_const n dsv_nil_term)
410   end) handle _ => false;
411*)
412
413
414
415
416
417
418
419(* general helper functions *)
420local
421   fun fun_in_list_help n P [] = NONE
422   |   fun_in_list_help n P (e::l) =
423         let
424            val c = (P e) handle _ => false;
425         in
426            if c then (SOME (n, e)) else fun_in_list_help (n+1) P l
427         end
428in
429   fun find_in_list P l = fun_in_list_help 0 P l;
430end
431
432
433local
434   fun fun_in_list_help n P [] = NONE
435   |   fun_in_list_help n P (e::l) =
436         let
437            val c = (P e) handle _ => NONE;
438         in
439            if isSome c then (SOME (n, e, valOf c)) else fun_in_list_help (n+1) P l
440         end
441in
442   fun find_in_list_val P l = fun_in_list_help 0 P l;
443end
444
445
446
447
448
449
450
451
452(********************************************
453 swapping
454*********************************************)
455fun GEN_SWAP_CONV n1 m1 n2 m2 n3 m3 n4 m4 n5 m5 n6 m6 =
456   let
457      val argsL = [n1, m1, n2, m2, n3, m3, n4, m4, n5, m5, n6, m6];
458      val argTL = map (numSyntax.term_of_int) argsL;
459(*    slightly more efficient, but reordering may be confusing when used manually
460
461      val rewrite_thm = ISPECL argTL LIST_DS_ENTAILS___PERM_SWAP_ELEMENTS
462*)
463      val rewrite_thm = ISPECL argTL LIST_DS_ENTAILS___PERM_SWAP_TO_POS
464   in
465      (ONCE_REWRITE_CONV [rewrite_thm] THENC
466               computeLib.CBV_CONV swap_cs)
467   end
468
469
470fun SWAP_CONV p n m =
471   if (p = 0) then GEN_SWAP_CONV n m 0 0 0 0 0 0 0 0 0 0 else
472   if (p = 1) then GEN_SWAP_CONV 0 0 n m 0 0 0 0 0 0 0 0 else
473   if (p = 2) then GEN_SWAP_CONV 0 0 0 0 n m 0 0 0 0 0 0 else
474   if (p = 3) then GEN_SWAP_CONV 0 0 0 0 0 0 n m 0 0 0 0 else
475   if (p = 4) then GEN_SWAP_CONV 0 0 0 0 0 0 0 0 n m 0 0 else
476   if (p = 5) then GEN_SWAP_CONV 0 0 0 0 0 0 0 0 0 0 n m else
477   SMALLFOOT_ERR "Wrong Parameter"
478
479
480
481
482(* EXAMPLE
483
484val t = ``LIST_DS_ENTAILS ([e3;e4], [(e5,e6);(e8,e8)]) ((pf_equal e1 e2::pf_unequal dse_nil e2::pf_equal e1 e2::l),[]) ((pf_equal e1 e2::pf_unequal e1 e2::pf_equal e1 e2::l),[])``
485
486SWAP_CONV 4 0 1 t
487
488val l1 = [true, false, false];
489val l2 = [false, true];
490*)
491
492fun should_turn (pf1, pf2) =
493   if pf1 = pf2 then false else
494   if (is_dse_nil pf1) then (not (is_dse_nil pf2)) else
495   if (is_dse_var pf2) then (not (is_dse_var pf1)) else
496   if (is_dse_const pf1) then (not (is_dse_const pf2)) else
497   (term_to_string pf1 > term_to_string pf2);
498
499
500fun bool_list2term l =
501   let
502      val l' = map (fn b => if b then T else F) l;
503   in
504      mk_list (l', bool)
505   end
506
507
508fun ds_TURN_EQUATIONS_CONV l1 l2 t =
509   let
510      val thm1 = SPECL [bool_list2term l1, bool_list2term l2] LIST_DS_ENTAILS___PF_TURN_EQ
511      val thm2 = PART_MATCH (fst o dest_eq) thm1 t;
512      val thm3 = CONV_RULE (RHS_CONV (computeLib.CBV_CONV ds_direct_cs)) thm2
513   in
514      thm3
515   end
516
517fun ds_TURN_EQUATIONS_TAC l1 l2 =
518   CONV_TAC (ds_TURN_EQUATIONS_CONV l1 l2);
519
520fun ds_AUTO_DIRECT_EQUATIONS_CONV t =
521   let
522      val (_, _, pf, _,pf', _) = dest_LIST_DS_ENTAILS t;
523      val (pfL, _) = strip_cons pf;
524      val (pfL', _) = strip_cons pf';
525
526      fun dest_eq_uneq sf = dest_pf_unequal sf handle _ => dest_pf_equal sf;
527
528      val l1 = map (fn sf => (should_turn (dest_eq_uneq sf) handle _ => false)) pfL;
529      val l2 = map (fn sf => (should_turn (dest_eq_uneq sf) handle _ => false)) pfL';
530   in
531      ds_TURN_EQUATIONS_CONV l1 l2 t
532   end;
533
534
535
536
537
538(* Example
539
540
541val t = ``LIST_DS_ENTAILS ([], [(e1,e2);(e9,e9)]) ((pf1::pf_equal e e::pf_true::pf2::pf_equal e' e'::pf3::l),(sf1::sf2::(sf_ls f e e) ::sf3::(sf_points_to e [(f, e)])::(sf_bin_tree (f1, f2) dse_nil)::(sf_tree fL e2 e2)::(sf_ls f e1 e2)::l2)) ((pf1::pfx::pf_equal e e::pf2::pf_equal e' e'::pf3::l),(sf1::sf2::(sf_ls f e2 e2) ::sf3::sf_emp::(sf_points_to e [(f, e)])::(sf_bin_tree (f1, f2) e)::(sf_tree fL e1 e2)::(sf_ls f e e)::l3))``
542
543
544val t = ``LIST_DS_ENTAILS ([], [])  ([], []) ([], [sf_ls f e e])``;
545
546val t3 =
547    ``LIST_DS_ENTAILS ([dse_var 0; dse_var 2],[(dse_var 3,dse_nil)])
548        ([pf_unequal (dse_var 0) (dse_var 3);
549          pf_unequal (dse_var 4) (dse_var 5);
550          pf_unequal (dse_var 3) (dse_var 2)],[])
551        ([],[sf_ls "f" (dse_var 2) (dse_var 2)])``
552*)
553
554fun bool_list2term_list___filter [] (l1, l2) = (l1, l2) |
555    bool_list2term_list___filter (true::l) (l1, l2) =
556      bool_list2term_list___filter l (T::(append l2 l1), []) |
557    bool_list2term_list___filter (false::l) (l1, l2) =
558      bool_list2term_list___filter l (l1, F::l2);
559
560
561fun bool_list2term___filter l =
562   let
563      val (l1, _) = bool_list2term_list___filter l ([], []);
564      val l2 = rev l1;
565   in
566      (mk_list (l2, bool), l2 = [])
567   end;
568
569
570
571
572
573
574fun is_pre_trivial t =
575   let
576      val (e1, e2) = pairLib.dest_pair t;
577   in
578      (e1 = e2)
579   end handle _ => false;
580
581
582fun get_pf_trival_filter pf =
583let
584   val (pfL, _) = strip_cons pf;
585   val fL = map is_pf_trivial pfL;
586in
587   bool_list2term___filter fL
588end;
589
590fun get_sf_trival_filter sf =
591let
592   val (sfL, _) = strip_cons sf;
593   val fL = map is_sf_trivial sfL;
594in
595   bool_list2term___filter fL
596end;
597
598fun get_pre_trival_filter c2 =
599let
600   val (pre, _) = strip_cons c2;
601   val fL = map is_pre_trivial pre;
602in
603   bool_list2term___filter fL
604end;
605
606
607
608val reflexive_cs = computeLib.bool_compset();
609val _ = computeLib.add_thms [POS_FILTER_THM, PF_TRIVIAL_FILTER_PRED_def,
610   SF_TRIVIAL_FILTER_PRED_THM, pairTheory.FST, pairTheory.SND] reflexive_cs;
611
612
613fun ds_inference_REMOVE_TRIVIAL___CONV t =
614   let
615      val (c1, c2, pf, sf, pf', sf') = dest_LIST_DS_ENTAILS t;
616
617      val (f1, p1) = get_pre_trival_filter c2;
618      val (f2, p2) = get_pf_trival_filter pf;
619      val (f3, p3) = get_sf_trival_filter sf;
620      val (f4, p4) = get_pf_trival_filter pf';
621      val (f5, p5) = get_sf_trival_filter sf';
622
623      val _ = if p1 andalso p2 andalso p3 andalso p4 andalso p5 then SMALLFOOT_ERR "Nothing trivial found!" else ();
624
625      val thm = ISPECL [f1, f2,f3,f4, f5, c1, c2, pf, sf, pf', sf'] INFERENCE_TRIVIAL_FILTER;
626      val thm2 = CONV_RULE (RHS_CONV (computeLib.CBV_CONV reflexive_cs)) thm;
627   in
628      thm2
629   end
630
631
632
633
634
635(* Example
636val t = ``LIST_DS_ENTAILS (e1::c1,c2) ([pf1;pf_unequal e3 e;pf2],[sf_points_to e1 []; sf_points_to dse_nil []]) ([],[])``
637val t = ``LIST_DS_ENTAILS (e1::e45::e6::e45::dse_nil::c1,c2) ([pf1;pf_unequal e e;pf2],[sf_points_to e3 []; sf_points_to dse_nil [];sf_bin_tree (f1, f2) e1]) ([],[])``
638*)
639
640val inconsistent_cs = reduceLib.num_compset ();
641val _ = computeLib.add_thms [SWAP_REWRITES] inconsistent_cs;
642
643fun ds_inference_INCONSISTENT___CONV___UNEQUAL t =
644   let
645      val (c1, c2, pf, sf, pf', sf') = dest_LIST_DS_ENTAILS t;
646      val (pfL, _) = strip_cons pf;
647      val pfOption = find_in_list is_pf_unequal_refl pfL
648      val _ = if isSome pfOption then () else SMALLFOOT_ERR "No disequation (e = e) found!";
649      val (n, uneq) = valOf pfOption;
650      val (e, _) = dest_pf_unequal uneq;
651
652      val thm = ISPECL [numLib.term_of_int n, e, c1, c2, pf, sf, pf', sf'] INFERENCE_INCONSISTENT_UNEQUAL___EVAL;
653      val thm2 = CONV_RULE (computeLib.CBV_CONV inconsistent_cs) thm;
654      val _ = if ((concl thm2) = t) then () else SMALLFOOT_ERR "No CONVERSION";
655   in
656      EQT_INTRO thm2
657   end
658
659
660fun ds_inference_INCONSISTENT___CONV___NIL_POINTS_TO t =
661   let
662      val (c1, c2, pf, sf, pf', sf') = dest_LIST_DS_ENTAILS t;
663      val (sfL, _) = strip_cons sf;
664      val pfOption = find_in_list is_points_to_nil sfL
665      val _ = if isSome pfOption then () else SMALLFOOT_ERR "Nothing found!";
666      val (n, uneq) = valOf pfOption;
667      val (_, a, _, _) = dest_sf_points_to uneq;
668
669      val thm = ISPECL [numLib.term_of_int n, a, c1, c2, pf, sf, pf', sf'] INFERENCE_INCONSISTENT___NIL_POINTS_TO___EVAL;
670      val thm2 = CONV_RULE (computeLib.CBV_CONV inconsistent_cs) thm;
671      val _ = if ((concl thm2) = t) then () else SMALLFOOT_ERR "No CONVERSION";
672   in
673      EQT_INTRO thm2
674   end
675
676
677fun find_entry n e [] = NONE |
678    find_entry n e (h::l) = if (e = h) then (SOME n) else
679                            find_entry (n+1) e l;
680
681fun find_double_entry n [] = NONE |
682    find_double_entry n (h::l) =
683      let
684         val mOpt = (find_entry (n+1) h l);
685      in
686         if (isSome mOpt) then (SOME (n, valOf mOpt, h)) else find_double_entry (n+1) l
687      end;
688
689fun find_match n cL [] = NONE |
690    find_match n cL (h::l) =
691      let
692         val (i, ex, d) =
693            let
694               val (ex, a, _, _) = dest_sf_points_to h;
695            in
696               (0, ex, a)
697            end handle _ =>
698            let
699               val (_, _, ex, fL) = dest_sf_bin_tree h;
700            in
701               (1, ex, fL)
702            end;
703         val cOpt = find_entry 0 ex cL;
704      in
705         if (isSome cOpt) then SOME (n, valOf cOpt, i, ex, d) else
706         find_match (n+1) cL l
707      end handle _ => find_match (n+1) cL l;
708
709
710
711fun ds_inference_INCONSISTENT___CONV___precondition_POINTS_TO_BIN_TREE t =
712   let
713      val (c1, c2, pf, sf, pf', sf') = dest_LIST_DS_ENTAILS t;
714      val (sfL, _) = strip_cons sf;
715      val (c1L, _) = strip_cons c1;
716      val _ = if ((c1L = []) orelse (sfL = [])) then SMALLFOOT_ERR "Nothing found!" else ();
717
718
719      val resOption = find_match 0 c1L sfL;
720      val _ = if isSome resOption then () else SMALLFOOT_ERR "Nothing found!";
721      val (n, m, i, e, d) = valOf resOption;
722
723      val inf = if i = 0 then
724                  INFERENCE_INCONSISTENT___precondition_POINTS_TO___EVAL
725                else
726                  INFERENCE_INCONSISTENT___precondition_BIN_TREE___EVAL;
727
728      val thm = ISPECL [numLib.term_of_int m, numLib.term_of_int n, e, d, c1, c2, pf, sf, pf', sf'] inf;
729      val thm2 = CONV_RULE (computeLib.CBV_CONV inconsistent_cs) thm;
730      val _ = if ((concl thm2) = t) then () else SMALLFOOT_ERR "No CONVERSION";
731   in
732      EQT_INTRO thm2
733   end;
734
735
736fun ds_inference_INCONSISTENT___CONV___precondition_dse_nil t =
737   let
738      val (c1, c2, pf, sf, pf', sf') = dest_LIST_DS_ENTAILS t;
739      val (c1L, _) = strip_cons c1;
740
741
742      val cOption = find_in_list is_dse_nil c1L;
743      val _ = if isSome cOption then () else SMALLFOOT_ERR "Nothing found!";
744      val (n, _) = valOf cOption;
745
746      val thm = ISPECL [numLib.term_of_int n, c1, c2, pf, sf, pf', sf']
747         INFERENCE_INCONSISTENT___precondition_dse_nil;
748      val thm2 = CONV_RULE (computeLib.CBV_CONV inconsistent_cs) thm;
749      val _ = if ((concl thm2) = t) then () else SMALLFOOT_ERR "No CONVERSION";
750   in
751      EQT_INTRO thm2
752   end;
753
754
755fun ds_inference_INCONSISTENT___CONV___precondition_not_all_distinct t =
756   let
757      val (c1, c2, pf, sf, pf', sf') = dest_LIST_DS_ENTAILS t;
758      val (c1L, _) = strip_cons c1;
759
760
761      val cOption = find_double_entry 0 c1L;
762      val _ = if isSome cOption then () else SMALLFOOT_ERR "Nothing found!";
763      val (n, m, x) = valOf cOption;
764
765      val thm = ISPECL [numLib.term_of_int n, numLib.term_of_int m, x, c1, c2, pf, sf, pf', sf']
766         INFERENCE_INCONSISTENT___precondition_distinct;
767      val thm2 = CONV_RULE (computeLib.CBV_CONV inconsistent_cs) thm;
768      val _ = if ((concl thm2) = t) then () else SMALLFOOT_ERR "No CONVERSION";
769   in
770      EQT_INTRO thm2
771   end;
772
773
774val ds_inference_INCONSISTENT___CONV =
775   ds_inference_INCONSISTENT___CONV___UNEQUAL ORELSEC
776   ds_inference_INCONSISTENT___CONV___NIL_POINTS_TO ORELSEC
777   ds_inference_INCONSISTENT___CONV___precondition_dse_nil ORELSEC
778   ds_inference_INCONSISTENT___CONV___precondition_POINTS_TO_BIN_TREE ORELSEC
779   ds_inference_INCONSISTENT___CONV___precondition_not_all_distinct;
780
781
782
783(* Example
784val t = ``LIST_DS_ENTAILS ([pf1;pf_unequal e e;pf2],[]) ([],[])``
785set_goal ([], t)
786*)
787
788fun ds_inference_AXIOM___CONV t = EQT_INTRO (PART_MATCH (I) INFERENCE_AXIOM t);
789
790
791
792
793(* Example
794val t = ``LIST_DS_ENTAILS ([dse_var 4], [(dse_var 1, dse_var 4)]) ([pf_unequal (dse_var 4) dse_nil;pf_equal x1 (dse_var 1); pf_equal (dse_var 1) (dse_var 2)],sfL) ([pf_equal (dse_var 4) (dse_var 2)],[sf_points_to (dse_var 5) [(f, (dse_var 1))]])``
795
796*)
797
798
799
800
801val subst_cs = reduceLib.num_compset ();
802val _ = computeLib.add_thms [PF_SUBST_def, MAP, SF_SUBST_THM, DS_VAR_SUBST_def, DS_VAR_SUBST_NIL,
803   SWAP_REWRITES, pairTheory.FST, pairTheory.SND]
804   subst_cs;
805
806
807fun is_pf_equal_subst pf =
808   (let
809      val (e1, e2) = dest_pf_equal pf;
810   in
811      (not (e1 = e2)) andalso ((is_dse_var e1) orelse (is_dse_var e2))
812   end) handle _ => false
813
814fun ds_inference_SUBSTITUTION___CONV t =
815   let
816      val (c1, c2, pf, sf, pf', sf') = dest_LIST_DS_ENTAILS t;
817      val (pfL, _) = strip_cons pf;
818      val pfOption = find_in_list is_pf_equal_subst pfL
819      val _ = if isSome pfOption then () else SMALLFOOT_ERR "No equation (var s = e) found!";
820      val (n, uneq) = valOf pfOption;
821      val (e1, e2) = dest_pf_equal uneq;
822      val (inf, e1, e2) = if (is_dse_var e1) then (INFERENCE_SUBSTITUTION___EVAL1, e1, e2) else
823                              (INFERENCE_SUBSTITUTION___EVAL2, e2, e1);
824
825      val thm = ISPECL [numLib.term_of_int n, e2, dest_dse_var e1, c1, c2, pf, sf, pf', sf'] inf;
826      val thm2 = CONV_RULE (computeLib.CBV_CONV subst_cs) thm;
827      val _ = if (lhs (concl thm2) = t) then () else SMALLFOOT_ERR "No CONVERSION";
828   in
829      thm2
830   end;
831
832
833
834
835
836
837(*example
838val t = ``LIST_DS_ENTAILS ([e7;e5;e4;e6], []) ([pf_unequal e1 e2;pf1;pf_unequal dse_nil e5;pf2;pf_unequal e1 e2],sfL) ([pf5;pf_unequal e6 e7;pf4;pf1;pf_equal e2 e1;pf_unequal dse_nil e4;pf_unequal e2 e1],pfL')``
839*)
840
841
842fun find_sf_eq_in_list n ex [] = NONE |
843    find_sf_eq_in_list n ex (h::l) =
844      let
845         val (p1, p2) = pf_eq ex h;
846      in
847         if p1 then (SOME (n, p2)) else
848         find_sf_eq_in_list (n+1) ex l
849      end
850
851
852local
853
854   fun check_in_pre_pf l1 h =
855      let
856         val cOpt = find_sf_eq_in_list 0 h l1;
857         val (n, turn) = valOf cOpt;
858         val cond = (list_mk_comb (``hyp_in_precond``, [if turn then T else F, numLib.term_of_int n]));
859      in
860         SOME cond
861      end handle _ => NONE;
862
863
864   fun check_in_self_pf n l2 h =
865      let
866         val cOpt = find_sf_eq_in_list 0 h l2;
867         val (m, turn) = valOf cOpt;
868         val _ = if (m < n) then () else SMALLFOOT_ERR "To late";
869         val cond = (list_mk_comb (``hyp_in_self``, [if turn then T else F, numLib.term_of_int m]));
870      in
871         SOME cond
872      end handle _ => NONE;
873
874
875   fun check_c_dse_nil cL h =
876      let
877         val (e1, e2) = dest_pf_unequal h;
878         val (e1, turn) = if is_dse_nil e2 then (e1, true) else
879                          if is_dse_nil e1 then (e2, false) else
880                          SMALLFOOT_ERR "no dse_nil found";
881
882         val cOpt = find_entry 0 e1 cL;
883         val n = valOf cOpt;
884      in
885         SOME (list_mk_comb (``hyp_c_dse_nil``, [if turn then T else F, numLib.term_of_int n]))
886      end  handle _ => NONE;
887
888
889   fun check_c_unequal cL h =
890      let
891         val (e1, e2) = dest_pf_unequal h;
892         val _ = if (e1 = e2) then SMALLFOOT_ERR "preserve for inconsistence" else ();
893
894         val n1 = valOf (find_entry 0 e1 cL);
895         val n2 = valOf (find_entry 0 e2 cL);
896      in
897         SOME (list_mk_comb (``hyp_c_unequal``, [numLib.term_of_int n1, numLib.term_of_int n2]))
898      end  handle _ => NONE;
899
900
901
902   fun get_hypothesis_filter_helper c1 l1 l2 n [] = [] |
903      get_hypothesis_filter_helper c1 l1 l2 n (h::l) =
904         let
905            val condOpt = check_in_pre_pf l1 h;
906            val condOpt = if isSome (condOpt) then condOpt else
907                          check_in_self_pf n l2 h;
908            val condOpt = if isSome (condOpt) then condOpt else
909                          check_c_dse_nil c1 h;
910            val condOpt = if isSome (condOpt) then condOpt else
911                          check_c_unequal c1 h;
912            val cond = if isSome condOpt then valOf condOpt else ``hyp_keep``;
913         in
914            cond::(get_hypothesis_filter_helper c1 l1 l2 (n+1) l)
915         end;
916
917   fun remove_keep l1 l2 [] = l1 |
918       remove_keep l1 l2 (h::l) =
919         if (same_const ``hyp_keep`` h) then
920            remove_keep l1 (h::l2) l
921         else
922            remove_keep (h::(append l2 l1)) [] l
923
924
925in
926   fun get_hypothesis_filter c1 l1 l2 =
927      let
928         val f = get_hypothesis_filter_helper c1 l1 l2 0 l2;
929         val rf = remove_keep [] [] f;
930         val fL = rev rf;
931         val p = (fL = []);
932         val ft = mk_list (fL, ``:hypothesis_rule_cases``);
933      in
934         (ft, p)
935      end
936end;
937
938
939
940val hypothesis_cs = reduceLib.num_compset ();
941val _ = computeLib.add_thms [HYPOTHESIS_RULE_MAP_def, SWAP_REWRITES, PF_TURN_EQ_def, HYPOTHESIS_RULE_COND_THM]
942   hypothesis_cs;
943
944fun ds_inference_HYPOTHESIS___CONV t =
945   let
946      val (c1, c2, pf, sf, pf', sf') = dest_LIST_DS_ENTAILS t;
947      val (cL, _) = strip_cons c1;
948      val (pfL, _) = strip_cons pf;
949      val (pfL', _) = strip_cons pf';
950      val (f1, p1) = get_hypothesis_filter cL [] pfL;
951      val (f2, p2) = get_hypothesis_filter cL pfL pfL';
952
953      val _ = if (p1 andalso p2) then SMALLFOOT_ERR "No common formulas found!" else ();
954
955      val thm = ISPECL [f1, f2, c1, c2, pf, sf, pf', sf']
956         INFERENCE_HYPOTHESIS___EVAL;
957      val thm2 = CONV_RULE (RHS_CONV (computeLib.CBV_CONV hypothesis_cs)) thm;
958   in
959      thm2
960   end;
961
962
963
964
965
966
967
968
969(*example
970val t = ``LIST_DS_ENTAILS ([], []) (pfL,[sf1;sf2;sf_points_to e1 [("f", b);("g", c)];sf_points_to e2 [("f", b)];sf_bin_tree ("f", "g") e3; sf_bin_tree ("g", "f") e4;sf_points_to e3 [("f", b);("g", c)];sf5;sf_ls "f" e1 e3]++sfL) (pfL',[sf5;sf_points_to e1 [("g", c);("f", b)];sf_points_to e1 [("f", b);("h", c)];sf_points_to e2 [("f", b)];sf_ls "f" e1 e3;sf_points_to e3 [("f", b);("g", c)];sf4;sf_bin_tree ("f", "g") e3; sf_bin_tree ("f", "g") e4;sf1]++sfL)``
971
972val t = rhs (concl (SIMP_CONV list_ss [] t))
973*)
974
975local
976   fun find_pairs_helper P n1 n2 l [] l2 r = r
977   | find_pairs_helper P n1 n2 l (e::l1) [] r =
978      find_pairs_helper P (n1+1) 0 l l1 l r
979   | find_pairs_helper P n1 n2 l (e1::l1) (e2::l2) r =
980         if ((P e1 e2) handle _ => false) then
981            find_pairs_helper P n1 (n2+1) l (e1::l1) l2 ((n1, e1, n2, e2)::r)
982         else
983            find_pairs_helper P n1 (n2+1) l (e1::l1) l2 r
984in
985   fun find_pairs P l1 l2 =
986       find_pairs_helper P 0 0 l2 l1 l2 [];
987end
988
989
990local
991   fun adapt_pair_list_to_deletes___map n1 n2 [] = [] |
992       adapt_pair_list_to_deletes___map n1 n2 ((n1', e1, n2', e2)::l) =
993         let val l' = adapt_pair_list_to_deletes___map n1 n2 l in
994         if (n1 = n1') orelse (n2 = n2') then
995            l'
996         else
997            (if n1' > n1 then (n1'-1) else n1', e1,
998             if n2' > n2 then (n2'-1) else n2', e2)::l'
999         end;
1000
1001   fun adapt_pair_list_to_deletes___helper l1 [] = l1 |
1002       adapt_pair_list_to_deletes___helper l1 ((n1, e1, n2, e2)::l) =
1003       adapt_pair_list_to_deletes___helper ((n1, e1, n2, e2)::l1) (adapt_pair_list_to_deletes___map n1 n2 l);
1004in
1005
1006fun adapt_pair_list_to_deletes l = rev (adapt_pair_list_to_deletes___helper [] l);
1007
1008end;
1009
1010
1011fun pred_frame___points_to sf1 sf2 =
1012   let
1013      val (e1, _, a1, aL1) = dest_sf_points_to sf1;
1014      val (e2, _, a2, aL2) = dest_sf_points_to sf2;
1015   in
1016      (e1 = e2) andalso (aL1 = aL2) andalso
1017      (all (fn x => mem x a1) a2)
1018   end;
1019
1020
1021val frame_cs = reduceLib.num_compset ();
1022val _ = listSimps.list_rws frame_cs;
1023val _ = computeLib.add_thms [SWAP_REWRITES, pairTheory.FST, listTheory.ALL_DISTINCT] frame_cs;
1024val _ = computeLib.add_conv (``$=``, 2, stringLib.string_EQ_CONV) frame_cs;
1025val _ = computeLib.add_conv (``$=``, 2, stringLib.char_EQ_CONV) frame_cs;
1026
1027
1028
1029fun ds_inference_FRAME___SINGLE_CONV___sf_points_to (n1, sf1, n2, sf2) t =
1030   let
1031      val (e1, a1, _, _) = dest_sf_points_to sf1;
1032      val (_, a2, _, _) = dest_sf_points_to sf2;
1033      val (c1, c2, pf, sf, pf', sf') = dest_LIST_DS_ENTAILS t;
1034
1035      val thm = ISPECL [e1, numLib.term_of_int n1, a1, numLib.term_of_int n2, a2, c1, c2, pf, sf, pf', sf']
1036         INFERENCE_STAR_INTRODUCTION___points_to___EVAL
1037      val thm2 = CONV_RULE (computeLib.CBV_CONV frame_cs) thm;
1038      val _ = if (lhs (concl thm2) = t) then () else SMALLFOOT_ERR "No conversion";
1039   in
1040      thm2
1041   end;
1042
1043
1044fun ds_inference_FRAME___CONV___sf_points_to t =
1045   let
1046      val (c1, c2, pf, sf, pf', sf') = dest_LIST_DS_ENTAILS t;
1047      val (sfL, _) = strip_cons sf;
1048      val (sfL', _) = strip_cons sf';
1049
1050      val pairList = find_pairs pred_frame___points_to sfL sfL';
1051      val _ = if (pairList = []) then SMALLFOOT_ERR "Nothing found" else ();
1052
1053      val adapt_pairList = adapt_pair_list_to_deletes (rev pairList)
1054   in
1055      EVERY_CONV (map ds_inference_FRAME___SINGLE_CONV___sf_points_to adapt_pairList) t
1056   end;
1057
1058
1059fun pred_frame___list sf1 sf2 =
1060   (sf1 = sf2) andalso (is_sf_ls sf1);
1061
1062
1063fun ds_inference_FRAME___SINGLE_CONV___sf_ls (n1, sf1, n2, sf2) t =
1064   let
1065      val (f, e1, e2) = dest_sf_ls sf1;
1066      val (c1, c2, pf, sf, pf', sf') = dest_LIST_DS_ENTAILS t;
1067
1068      val thm = ISPECL [f, e1, e2, numLib.term_of_int n1, numLib.term_of_int n2, c1, c2, pf, sf, pf', sf']
1069         INFERENCE_STAR_INTRODUCTION___list___EVAL
1070      val thm2 = CONV_RULE (computeLib.CBV_CONV frame_cs) thm;
1071      val _ = if (lhs (concl thm2) = t) then () else SMALLFOOT_ERR "No conversion";
1072   in
1073      thm2
1074   end;
1075
1076
1077fun ds_inference_FRAME___CONV___sf_ls t =
1078   let
1079      val (c1, c2, pf, sf, pf', sf') = dest_LIST_DS_ENTAILS t;
1080      val (sfL, _) = strip_cons sf;
1081      val (sfL', _) = strip_cons sf';
1082
1083      val pairList = find_pairs pred_frame___list sfL sfL';
1084      val _ = if (pairList = []) then SMALLFOOT_ERR "Nothing found" else ();
1085
1086      val adapt_pairList = adapt_pair_list_to_deletes (rev pairList);
1087   in
1088      EVERY_CONV (map ds_inference_FRAME___SINGLE_CONV___sf_ls adapt_pairList) t
1089   end;
1090
1091
1092
1093fun pred_frame___bin_tree sf1 sf2 =
1094   let
1095      val (f11, f12, e1, _) = dest_sf_bin_tree sf1;
1096      val (f21, f22, e2, _) = dest_sf_bin_tree sf2;
1097   in
1098      (e1 = e2) andalso
1099      (((f11 = f21) andalso (f12 = f22)) orelse
1100       ((f12 = f21) andalso (f11 = f22)))
1101   end;
1102
1103
1104
1105fun ds_inference_FRAME___SINGLE_CONV___sf_bin_tree (n1, sf1, n2, sf2) t =
1106   let
1107      val (f11, f12, e1, _) = dest_sf_bin_tree sf1;
1108      val (f21, f22, _, _) = dest_sf_bin_tree sf2;
1109      val (c1, c2, pf, sf, pf', sf') = dest_LIST_DS_ENTAILS t;
1110
1111      val thm = ISPECL [e1, f11, f12, f21, f22, numLib.term_of_int n1, numLib.term_of_int n2, c1, c2, pf, sf, pf', sf']
1112         INFERENCE_STAR_INTRODUCTION___bin_tree___EVAL
1113      val thm2 = CONV_RULE (computeLib.CBV_CONV frame_cs) thm;
1114      val _ = if (lhs (concl thm2) = t) then () else SMALLFOOT_ERR "No conversion";
1115   in
1116      thm2
1117   end;
1118
1119fun ds_inference_FRAME___CONV___sf_bin_tree t =
1120   let
1121      val (c1, c2, pf, sf, pf', sf') = dest_LIST_DS_ENTAILS t;
1122      val (sfL, _) = strip_cons sf;
1123      val (sfL', _) = strip_cons sf';
1124
1125      val pairList = find_pairs pred_frame___bin_tree sfL sfL';
1126      val _ = if (pairList = []) then SMALLFOOT_ERR "Nothing found" else ();
1127
1128      val adapt_pairList = adapt_pair_list_to_deletes (rev pairList);
1129   in
1130      EVERY_CONV (map ds_inference_FRAME___SINGLE_CONV___sf_bin_tree adapt_pairList) t
1131   end;
1132
1133
1134val ds_inference_FRAME___CONV =
1135   (TRY_CONV ds_inference_FRAME___CONV___sf_points_to) THENC
1136   (TRY_CONV ds_inference_FRAME___CONV___sf_ls) THENC
1137   (TRY_CONV ds_inference_FRAME___CONV___sf_bin_tree)
1138
1139
1140
1141
1142fun ds_inference_FRAME___IMPL_CONV___tail t =
1143   let
1144      val (c1, c2, pf, sf, pf', sf') = dest_LIST_DS_ENTAILS t;
1145      val (sfL, sfLr) = strip_cons sf;
1146      val (sfL', sfLr') = strip_cons sf';
1147
1148      val _ = if (is_nil sfLr orelse not (sfLr = sfLr')) then SMALLFOOT_ERR "Nothing found" else ();
1149
1150      val list_type = dest_list_type (type_of sfLr)
1151      val sfLt = mk_list (sfL, list_type);
1152      val sfLt' = mk_list (sfL', list_type);
1153
1154      val thm = ISPECL [sfLr, c1,c2, pf, sfLt, pf', sfLt'] INFERENCE_STAR_INTRODUCTION___EVAL1
1155      val thm2 = CONV_RULE (computeLib.CBV_CONV frame_cs) thm;
1156      val _ = if (snd (dest_imp (concl thm2)) = t) then () else SMALLFOOT_ERR "No imp-conversion";
1157   in
1158      thm2
1159   end;
1160
1161
1162fun ds_inference_FRAME___IMPL_CONV___single_step ((n1, x, n2, _),in_thm) =
1163let
1164   val (t1, t2) = dest_imp (concl in_thm);
1165
1166   val (c1, c2, pf, sf, pf', sf') = dest_LIST_DS_ENTAILS t1;
1167
1168   val thm = ISPECL [x, numLib.term_of_int n1, numLib.term_of_int n2, c1, c2, pf, sf, pf', sf'] INFERENCE_STAR_INTRODUCTION___EVAL2;
1169   val thm2 = CONV_RULE (computeLib.CBV_CONV frame_cs) thm;
1170   val thm3 = IMP_TRANS thm2 in_thm
1171in
1172   thm3
1173end;
1174
1175val imp_thm = prove (``!a. a ==> a``, SIMP_TAC std_ss []);
1176
1177fun ds_inference_FRAME___IMPL_CONV___pair t =
1178   let
1179      val (c1, c2, pf, sf, pf', sf') = dest_LIST_DS_ENTAILS t;
1180      val (sfL, _) = strip_cons sf;
1181      val (sfL', _) = strip_cons sf';
1182
1183      val pairList = find_pairs (fn x => fn y => x = y) sfL sfL';
1184      val _ = if (pairList = []) then SMALLFOOT_ERR "Nothing found" else ();
1185      val adapt_pairList = adapt_pair_list_to_deletes (rev pairList);
1186
1187      val in_thm = ISPEC t imp_thm;
1188      val thm = foldl ds_inference_FRAME___IMPL_CONV___single_step in_thm adapt_pairList;
1189   in
1190      thm
1191   end;
1192
1193
1194fun ds_inference_FRAME___IMPL_CONV t =
1195   let
1196      val eq_thm = (SOME (ds_inference_FRAME___CONV t)) handle _ => NONE
1197      val t2 = if isSome eq_thm then (rhs (concl (valOf eq_thm))) else t;
1198      val imp1_thm = (SOME (ds_inference_FRAME___IMPL_CONV___tail t2)) handle _ => NONE;
1199      val t3 = if isSome imp1_thm then (fst (dest_imp (concl (valOf imp1_thm)))) else t2;
1200      val imp2_thm = (SOME (ds_inference_FRAME___IMPL_CONV___pair t3)) handle _ => NONE;
1201
1202      val imp_thm = if not (isSome imp2_thm) then imp1_thm else
1203                    if not (isSome imp1_thm) then imp2_thm else
1204                    SOME (IMP_TRANS (valOf imp2_thm) (valOf imp1_thm));
1205
1206      val thm = if not (isSome imp_thm) then eq_thm else
1207               if not (isSome eq_thm) then imp_thm else
1208               SOME (CONV_RULE (REWRITE_CONV [GSYM (valOf eq_thm)]) (valOf imp_thm))
1209   in
1210      valOf thm
1211   end;
1212
1213
1214(*example
1215val t = ``LIST_DS_ENTAILS ([e6], []) ([pf_unequal e1 dse_nil; pf_unequal dse_nil e3;pf_unequal e3 e2],[sf_points_to e1 [("g", e5)];sf_points_to e3 [];sf_ls f e1 e2;sf_ls f e2 e3;sf_points_to e4 []]) ([],[])``
1216*)
1217
1218
1219val pointsto_skip_term = ``pointsto_skip``;
1220val pointsto_pointsto_term = ``pointsto_pointsto``;
1221val pointsto_tree_term = ``pointsto_tree``;
1222
1223
1224fun get_points_to_list_cond_filter pfL sf =
1225   if is_sf_points_to sf then pointsto_pointsto_term else
1226   let
1227      val (_, _, es, e) = dest_sf_tree_ext sf;
1228      val (n, uneqt) = valOf (find_in_list (is_uneq_2 es e) pfL)
1229      val (e', es') = dest_pf_unequal uneqt
1230      val turn = not (es' = es);
1231   in
1232      list_mk_comb (pointsto_tree_term, [if turn then T else F, numLib.term_of_int n])
1233   end handle _ => pointsto_skip_term;
1234
1235
1236fun check_unequal_dse_nil_is_necessary cL pfL ex =
1237   not (isSome (find_in_list (is_uneq_nil ex) pfL)) andalso
1238   not (isSome (find_entry 0 ex cL));
1239
1240fun get_points_to_list_cond_exp sf =
1241   let
1242      val (e1, _, _, _) = dest_sf_points_to sf;
1243   in
1244   e1
1245   end handle _ =>
1246   let
1247      val (_, _, _, e1) = dest_sf_tree_ext sf;
1248   in
1249      e1
1250   end;
1251
1252
1253fun map_restrict_points_to_list_cond_filter pfL cL [] _ = [] |
1254    map_restrict_points_to_list_cond_filter pfL cL (f::fL) [] = [] |
1255    map_restrict_points_to_list_cond_filter pfL cL (f::fL) (sf::sfL) =
1256   let
1257      val ex = get_points_to_list_cond_exp sf;
1258      val f' = if check_unequal_dse_nil_is_necessary cL pfL ex then f else pointsto_skip_term;
1259   in
1260      (f' :: (map_restrict_points_to_list_cond_filter pfL (ex::cL) fL sfL))
1261   end;
1262
1263
1264
1265
1266val sf_points_to_list_cs = reduceLib.num_compset ();
1267val _ = computeLib.add_thms
1268[SF_POINTS_TO_LIST_def,
1269   SAFE_FILTER_THM, SF_POINTS_TO_LIST_COND_FILTER_def, SF_POINTS_TO_LIST_COND_THM,
1270   SWAP_REWRITES] sf_points_to_list_cs;
1271val _ = listSimps.list_rws sf_points_to_list_cs;
1272
1273
1274fun ds_inference_NIL_NOT_LVAL___CONV___overeager over t =
1275   let
1276      val (c1, c2, pf, sf, pf', sf') = dest_LIST_DS_ENTAILS t;
1277      val (cL, _) = strip_cons c1;
1278      val (pfL, _) = strip_cons pf;
1279      val (sfL, _) = strip_cons sf;
1280
1281      val f = map (get_points_to_list_cond_filter pfL) sfL;
1282      val f = if over then f else
1283              map_restrict_points_to_list_cond_filter pfL cL f sfL;
1284
1285      val p = exists (fn x => not (x = pointsto_skip_term)) f;
1286      val _ = if not p then SMALLFOOT_ERR "No new facts!" else ()
1287
1288      val ft = mk_list (f, type_of (hd f));
1289
1290      val thm = ISPECL [ft, c1, c2, pf, sf, pf', sf'] INFERENCE_NIL_NOT_LVAL___EVAL
1291      val thm2 = CONV_RULE (RHS_CONV (computeLib.CBV_CONV sf_points_to_list_cs)) thm;
1292   in
1293      thm2
1294   end;
1295
1296
1297val ds_inference_NIL_NOT_LVAL___CONV =
1298   ds_inference_NIL_NOT_LVAL___CONV___overeager false;
1299
1300
1301
1302
1303
1304
1305(*example
1306val t = ``LIST_DS_ENTAILS ([e2;e1;e4;e6;e5], []) ([pf_unequal e3 e2],[sf_points_to e1 x;sf_points_to e2 x;sf_points_to e3 x;sf_points_to e4 x;sf_ls f e3 e2]) ([],[])``
1307*)
1308
1309
1310val product_term = ``
1311                 (LIST_PRODUCT (SF_POINTS_TO_LIST_COND_FILTER pfL f2 sfL)
1312                    c1) ++
1313                  DISJOINT_LIST_PRODUCT
1314                    (SF_POINTS_TO_LIST_COND_FILTER pfL f2 (sfL:('c, 'b, 'a) ds_spatial_formula list))``;
1315
1316val partial_cs = reduceLib.num_compset ();
1317val _ = computeLib.add_thms [SF_POINTS_TO_LIST_def,
1318   SAFE_FILTER_THM, LIST_PRODUCT_def, DISJOINT_LIST_PRODUCT_def, pairTheory.UNCURRY_DEF,
1319   SF_POINTS_TO_LIST_COND_FILTER_def, SF_POINTS_TO_LIST_COND_THM, SWAP_REWRITES] partial_cs
1320val _ = listSimps.list_rws partial_cs;
1321
1322
1323
1324fun EVAL___DISJOINT_LIST_PRODUCT c1 pf sf f2 =
1325   let
1326      val (_, typeL) = dest_type (dest_list_type (type_of sf))
1327      val product_term = inst [alpha |-> el 3 typeL,
1328                               beta |-> el 2 typeL,
1329                               gamma |-> el 1 typeL] product_term;
1330      val t = subst [mk_var("pfL",type_of pf) |-> pf,
1331             mk_var("c1",type_of c1) |-> c1,
1332             mk_var("f2",type_of f2) |-> f2,
1333             mk_var("sfL",type_of sf) |-> sf] product_term;
1334   in
1335      computeLib.CBV_CONV partial_cs t
1336   end;
1337
1338
1339fun check_unequal_is_necessary cL pfL (e1, e2) =
1340   not (isSome (find_in_list (is_uneq_2 e1 e2) pfL)) andalso
1341   ((e1 = e2) orelse
1342      not (isSome (find_entry 0 e1 cL)) orelse
1343      not (isSome (find_entry 0 e2 cL)));
1344
1345
1346
1347fun get_uneq_filter overeager cL pfL r l' [] = r |
1348    get_uneq_filter overeager cL pfL r l' ((e1,e2)::l) =
1349    let
1350      val necessary =
1351         overeager orelse (
1352         (not (mem (e1,e2) l')) andalso
1353         (not (mem (e2,e1) l')) andalso
1354         check_unequal_is_necessary cL pfL (e1,e2));
1355    in
1356      (get_uneq_filter overeager cL pfL (necessary::r) (if necessary then (e1,e2)::l' else l') l)
1357    end;
1358
1359
1360
1361fun ds_inference_PARTIAL___CONV___overeager over t =
1362   let
1363      val (c1, c2, pf, sf, pf', sf') = dest_LIST_DS_ENTAILS t;
1364      val (cL, _) = strip_cons c1;
1365      val (pfL, _) = strip_cons pf;
1366      val (sfL, _) = strip_cons sf;
1367
1368      val f2L = map (get_points_to_list_cond_filter pfL) sfL;
1369      val f2 = mk_list (f2L, Type `:pointsto_cases`);
1370
1371
1372      val SF_POINTS_TO_LIST___THM = EVAL___DISJOINT_LIST_PRODUCT c1 pf sf f2;
1373      val (points_list, _) = dest_list (rhs (concl SF_POINTS_TO_LIST___THM));
1374      val points_list = map pairLib.dest_pair points_list;
1375
1376      val pre_f = get_uneq_filter over cL pfL [] [] points_list;
1377      val (f, p) = bool_list2term___filter (rev pre_f);
1378      val _ = if p then SMALLFOOT_ERR "No new facts!" else ()
1379
1380      val thm = ISPECL [f, f2, c1, c2, pf, sf, pf', sf'] INFERENCE_PARTIAL___EVAL
1381      val thm2 = CONV_RULE (RHS_CONV (REWRITE_CONV [SF_POINTS_TO_LIST___THM])) thm;
1382      val thm3 = CONV_RULE (RHS_CONV (computeLib.CBV_CONV partial_cs)) thm2;
1383   in
1384      thm3
1385   end;
1386
1387
1388val ds_inference_PARTIAL___CONV = ds_inference_PARTIAL___CONV___overeager false;
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398(*example
1399val t = ``LIST_DS_ENTAILS ([e1;e2],[(e2,e3);(e3,e4);(e4,e2);(e9,e10);(e4,e2);(e9,e10)]) ([pf_unequal e3 e4;pf1;pf_unequal e2 e4; pf3],[sf1;sf_ls "f" e1 e2;sf2]) ([],[])``
1400*)
1401
1402fun find_strengthen_uneq_pairs___helper accu n1 n2 pfLorg [] pfL = accu
1403  | find_strengthen_uneq_pairs___helper accu n1 n2 pfLorg ((e1,e2)::cL) [] =
1404    find_strengthen_uneq_pairs___helper accu (n1+1) 0 pfLorg cL pfLorg
1405  | find_strengthen_uneq_pairs___helper accu n1 n2 pfLorg ((e1,e2)::cL) (pf::pfL) =
1406    let val accu' = (let
1407      val (e1', e2') = dest_pf_unequal pf;
1408    in
1409      if ((e1 = e1') andalso (e2 = e2')) then (n1,n2,false,e1,e2)::accu else
1410      if ((e2 = e1') andalso (e1 = e2')) then (n1,n2,true,e1,e2)::accu else
1411      accu
1412    end handle _ => accu) in
1413      find_strengthen_uneq_pairs___helper accu' n1 (n2+1) pfLorg ((e1,e2)::cL) pfL
1414    end;
1415
1416fun find_strengthen_uneq_pairs cL pfL =
1417   find_strengthen_uneq_pairs___helper [] 0 0 pfL cL pfL;
1418
1419val strengthen_cs = reduceLib.num_compset ();
1420val _ = computeLib.add_thms [SWAP_REWRITES] strengthen_cs;
1421
1422
1423fun ds_inference_PRECONDITION_STRENGTHEN___SINGLE_CONV (n1,n2,turn,e1,e2) t =
1424   let
1425      val (c1, c2, pf, sf, pf', sf') = dest_LIST_DS_ENTAILS t;
1426
1427      val inf = if turn then INFERENCE___precondition_STRENGTHEN_2 else
1428                  INFERENCE___precondition_STRENGTHEN_1;
1429
1430      val thm = ISPECL [numLib.term_of_int n2, numLib.term_of_int n1, e1, e2, c1, c2, pf, sf, pf', sf'] inf;
1431      val thm2 = CONV_RULE (computeLib.CBV_CONV strengthen_cs) thm;
1432      val _ = if (lhs (concl thm2) = t) then () else SMALLFOOT_ERR "No conversion";
1433   in
1434      thm2
1435   end;
1436
1437
1438fun ds_inference_PRECONDITION_STRENGTHEN___CONV___unequal t =
1439   let
1440      val (_, c2, pf, _, _, _) = dest_LIST_DS_ENTAILS t;
1441      val (cL, _) = strip_cons c2;
1442      val cL = map pairLib.dest_pair cL;
1443      val (pfL, _) = strip_cons pf;
1444
1445      (*notice the reverse order*)
1446      val pairs_list = find_strengthen_uneq_pairs cL pfL;
1447   in
1448      EVERY_CONV (map ds_inference_PRECONDITION_STRENGTHEN___SINGLE_CONV pairs_list) t
1449   end;
1450
1451
1452
1453
1454
1455fun find_strengthen_eq_pair___helper n1 n2 pfL [] cfL = NONE
1456  | find_strengthen_eq_pair___helper n1 n2 pfL ((e1,e2)::cL) [] =
1457    find_strengthen_eq_pair___helper (n1+1) (n1+2) pfL cL (tl cL)
1458  | find_strengthen_eq_pair___helper n1 n2 pfL ((e1,e2)::cL) ((e1',e2')::cL') =
1459    let
1460      val cond = (e1 = e1') andalso (e2 = e2') andalso
1461                 not (isSome (find_in_list (is_eq_2 e1 e2) pfL)) handle _ => false;
1462    in
1463      if cond then SOME (n1, n2, e1, e2) else
1464         find_strengthen_eq_pair___helper n1 (n2+1) pfL ((e1,e2)::cL) cL'
1465    end;
1466
1467fun find_strengthen_eq_pair cL pfL =
1468   valOf (find_strengthen_eq_pair___helper 0 1 pfL cL (tl cL));
1469
1470fun ds_inference_PRECONDITION_STRENGTHEN___CONV___equal t =
1471   let
1472      val (c1, c2, pf, sf, pf', sf') = dest_LIST_DS_ENTAILS t;
1473      val (cL, _) = strip_cons c2;
1474      val cL = map pairLib.dest_pair cL;
1475      val (pfL, _) = strip_cons pf;
1476
1477
1478      val (n1,n2,e1,e2) = find_strengthen_eq_pair cL pfL handle _ =>
1479         SMALLFOOT_ERR "Not applicable";
1480
1481      val thm = ISPECL [numLib.term_of_int n1, numLib.term_of_int n2, e1, e2, c1, c2, pf, sf, pf', sf']
1482         INFERENCE___precondition_NOT_DISTINCT_EQ___EVAL;
1483      val thm2 = CONV_RULE (computeLib.CBV_CONV strengthen_cs) thm;
1484      val _ = if (lhs (concl thm2) = t) then () else SMALLFOOT_ERR "No CONVERSION";
1485   in
1486      thm2
1487   end
1488
1489
1490fun find_strengthen_eq_precondition___helper n cL1 [] = NONE
1491  | find_strengthen_eq_precondition___helper n cL1 ((e1,e2)::cL2) =
1492    let
1493      val n1 = valOf (find_entry 0 e1 cL1);
1494    in
1495      SOME (n1, n, e1, e2)
1496    end handle _ =>
1497      find_strengthen_eq_precondition___helper (n+1) cL1 (cL2);
1498
1499fun find_strengthen_eq_precondition cL1 cL2 =
1500   valOf (find_strengthen_eq_precondition___helper 0 cL1 cL2);
1501
1502
1503fun ds_inference_PRECONDITION_STRENGTHEN___CONV___precondition t =
1504   let
1505      val (c1, c2, pf, sf, pf', sf') = dest_LIST_DS_ENTAILS t;
1506      val (cL1, _) = strip_cons c1;
1507      val (cL2, _) = strip_cons c2;
1508      val cL2 = map pairLib.dest_pair cL2;
1509
1510
1511      val (n1,n2,e1,e2) = find_strengthen_eq_precondition cL1 cL2 handle _ =>
1512         SMALLFOOT_ERR "Not applicable";
1513
1514
1515      val thm = ISPECL [numLib.term_of_int n1, numLib.term_of_int n2, e1, e2, c1, c2, pf, sf, pf', sf']
1516         INFERENCE___precondition_precondition_EQ___EVAL;
1517      val thm2 = CONV_RULE (computeLib.CBV_CONV strengthen_cs) thm;
1518      val _ = if (lhs (concl thm2) = t) then () else SMALLFOOT_ERR "No CONVERSION";
1519   in
1520      thm2
1521   end
1522
1523val ds_inference_PRECONDITION_STRENGTHEN___CONV =
1524    ds_inference_PRECONDITION_STRENGTHEN___CONV___unequal THENC
1525    (REPEATC ds_inference_PRECONDITION_STRENGTHEN___CONV___equal) THENC
1526    (REPEATC ds_inference_PRECONDITION_STRENGTHEN___CONV___precondition);
1527
1528
1529
1530(*example
1531val t = ``LIST_DS_ENTAILS ([e1],[(e2,e3);(e3,e4);(e4,e2);(e9,e10);(e4,e2);(e9,e10)]) ([pf_unequal e3 e4;pf1;pf_unequal e2 e4; pf3],[sf_ls "g" e5 e7; sf_ls "f" dse_nil e3;sf1;sf_ls "f" e1 e2;sf2]) ([],[])``
1532*)
1533
1534val unroll_cs = reduceLib.num_compset ();
1535val _ = listSimps.list_rws unroll_cs;
1536val _ = computeLib.add_thms [SWAP_REWRITES, pairTheory.FST, listTheory.ALL_DISTINCT] unroll_cs;
1537val _ = computeLib.add_conv (``$=``, 2, stringLib.string_EQ_CONV) unroll_cs;
1538val _ = computeLib.add_conv (``$=``, 2, stringLib.char_EQ_CONV) unroll_cs;
1539
1540
1541
1542
1543
1544fun ds_inference_SIMPLE_UNROLL___CONV___list_dse_nil t =
1545   let
1546      val (c1, c2, pf, sf, pf', sf') = dest_LIST_DS_ENTAILS t;
1547      val (sfL, _) = strip_cons sf;
1548
1549
1550      val sfOpt = find_in_list is_dse_nil_list sfL;
1551      val _ = if (isSome sfOpt) then () else SMALLFOOT_ERR "Not dse_nil list found!";
1552      val (n, lsf) = valOf sfOpt;
1553      val (f, e1, e2) = dest_sf_ls lsf;
1554
1555
1556      val thm = ISPECL [numLib.term_of_int n, f, e2, c1, c2, pf, sf, pf', sf']
1557         INFERENCE___NIL_LIST_EVAL
1558      val thm2 = CONV_RULE (computeLib.CBV_CONV unroll_cs) thm;
1559      val _ = if (lhs (concl thm2) = t) then () else SMALLFOOT_ERR "No CONVERSION";
1560   in
1561      thm2
1562   end;
1563
1564
1565
1566
1567fun find_list_precond n cL [] = NONE |
1568    find_list_precond n cL (h::l) =
1569      let
1570         val (f, e1, e2) = dest_sf_ls h;
1571         val cOpt = find_entry 0 e1 cL;
1572      in
1573         if (isSome cOpt) then SOME (n, valOf cOpt, f, e1, e2) else
1574         find_list_precond (n+1) cL l
1575      end handle _ => find_list_precond (n+1) cL l;
1576
1577
1578fun ds_inference_SIMPLE_UNROLL___CONV___precondition_list t =
1579   let
1580      val (c1, c2, pf, sf, pf', sf') = dest_LIST_DS_ENTAILS t;
1581      val (cL, _) = strip_cons c1;
1582      val (sfL, _) = strip_cons sf;
1583
1584
1585      val sfOpt = find_list_precond 0 cL sfL
1586      val _ = if (isSome sfOpt) then () else SMALLFOOT_ERR "Not suitable list found!";
1587      val (n, m, f, e1, e2) = valOf sfOpt;
1588
1589      val thm = ISPECL [numLib.term_of_int m, numLib.term_of_int n, f, e1, e2, c1, c2, pf, sf, pf', sf']
1590         INFERENCE___precondition_LIST_EVAL
1591      val thm2 = CONV_RULE (computeLib.CBV_CONV unroll_cs) thm;
1592      val _ = if (lhs (concl thm2) = t) then () else SMALLFOOT_ERR "No CONVERSION";
1593   in
1594      thm2
1595   end
1596
1597
1598(*
1599val t = ``LIST_DS_ENTAILS ([e1],[(e2,e3)]) ([pf_unequal e1 e3;pf1;pf_unequal e2 e4; pf3],[sf_ls "g" e5 e7; sf_ls "f" dse_nil e3;sf_points_to e1 [("g", x); ("f", y)]; sf1;sf2]) ([],[sf432;sf_ls "f" e1 e3;sf4])``
1600
1601val t = ``LIST_DS_ENTAILS ([e1],[(e2,e3)]) ([pf_unequal e3 e1;pf1;pf_unequal e2 e4; pf3],[sf_ls "g" e5 e7; sf_ls "f" dse_nil e3;sf_points_to e1 [("g", x); ("f", y)]; sf1;sf2]) ([],[sf_ls "f" e1 e3])``
1602
1603val t = ``LIST_DS_ENTAILS ([e1],[(e2,e3)]) ([pf_unequal e3 e1;pf1;pf_unequal e2 e4; pf3],[sf_ls "g" e5 e7; sf_ls "f" dse_nil e3;sf_points_to e1 [("g", x); ("f", y)]; sf1;sf2]) ([],[sf_bin_tree ("f1","f2") e1])``
1604
1605val t = ``LIST_DS_ENTAILS ([e1],[(e2,e3)]) ([pf_unequal e3 e1;pf1;pf_unequal e2 e4; pf3],[sf_ls "g" e5 e7;sf_points_to e1 [("g", x); ("f", y)]; sf1;sf2]) ([],[sf_bin_tree ("g","fa") e1])``
1606
1607*)
1608
1609
1610fun find_list_unroll_right n sfL pfL [] = NONE |
1611    find_list_unroll_right n sfL pfL (h::l) =
1612      let
1613         val (f, e1, e3) = dest_sf_ls h;
1614         val (n3, pointer) = valOf (find_in_list (is_sf_points_to_ex e1) sfL);
1615         val (_, a, pointer_list, _) = dest_sf_points_to pointer;
1616         val e2 = snd (first (fn (x,y) => x = f) pointer_list);
1617         val (n2, uneq) = valOf (find_in_list (is_uneq_2 e1 e3) pfL);
1618         val (e1',e2') = dest_pf_unequal uneq;
1619         val turn = (e1 = e2');
1620      in
1621         SOME (n, n2, n3, turn, e1, e2,e3, f, a)
1622      end handle _ => find_list_unroll_right (n+1) sfL pfL l;
1623
1624fun find_bin_tree_unroll_right n sfL [] = NONE |
1625    find_bin_tree_unroll_right n sfL (h::l) =
1626      let
1627         val (f1,f2, ex, _) = dest_sf_bin_tree h;
1628         val (n2, pointer) = valOf (find_in_list (is_sf_points_to_ex ex) sfL);
1629         val (_, a, pointer_list, _) = dest_sf_points_to pointer;
1630         val e1 = snd (first (fn (x,y) => x = f1) pointer_list);
1631         val e2 = snd (first (fn (x,y) => x = f2) pointer_list);
1632      in
1633         SOME (n, n2, ex, e1, e2, f1, f2, a)
1634      end handle _ => find_bin_tree_unroll_right (n+1) sfL l;
1635
1636
1637fun ds_inference_SIMPLE_UNROLL___CONV___points_to_list t =
1638   let
1639      val (c1, c2, pf, sf, pf', sf') = dest_LIST_DS_ENTAILS t;
1640      val (pfL, _) = strip_cons pf;
1641      val (sfL, _) = strip_cons sf;
1642      val (sfL', _) = strip_cons sf';
1643
1644
1645      val searchOpt = find_list_unroll_right 0 sfL pfL sfL';
1646      val _ = if (isSome searchOpt) then () else SMALLFOOT_ERR "Not suitable list found!";
1647      val (n1, n2, n3, turn, e1, e2,e3, f, a) = valOf searchOpt;
1648
1649      val thm = ISPECL [numLib.term_of_int n1, numLib.term_of_int n2, numLib.term_of_int n3,
1650            if turn then F else T, e1, e2, e3, f, a, c1, c2, pf, sf, pf', sf']
1651         INFERENCE___NON_EMPTY_LS___EVAL
1652      val thm2 = CONV_RULE (computeLib.CBV_CONV unroll_cs) thm;
1653      val _ = if (lhs (concl thm2) = t) then () else SMALLFOOT_ERR "No CONVERSION";
1654   in
1655      thm2
1656   end
1657
1658
1659
1660fun ds_inference_SIMPLE_UNROLL___CONV___points_to_bin_tree t =
1661   let
1662      val (c1, c2, pf, sf, pf', sf') = dest_LIST_DS_ENTAILS t;
1663      val (sfL, _) = strip_cons sf;
1664      val (sfL', _) = strip_cons sf';
1665
1666
1667      val searchOpt = find_bin_tree_unroll_right 0 sfL sfL';
1668      val _ = if (isSome searchOpt) then () else SMALLFOOT_ERR "Not suitable tree found!";
1669      val (n, n2, ex, e1, e2, f1, f2, a) = valOf searchOpt;
1670      val thm = ISPECL [numLib.term_of_int n, numLib.term_of_int n2,
1671            ex, e1, e2, f1, f2, a, c1, c2, pf, sf, pf', sf']
1672         INFERENCE___NON_EMPTY_BIN_TREE___EVAL
1673      val thm2 = CONV_RULE (computeLib.CBV_CONV unroll_cs) thm;
1674      val _ = if (lhs (concl thm2) = t) then () else SMALLFOOT_ERR "No CONVERSION";
1675   in
1676      thm2
1677   end
1678
1679
1680val ds_inference_SIMPLE_UNROLL___CONV =
1681   (REPEATC ds_inference_SIMPLE_UNROLL___CONV___list_dse_nil) THENC
1682   (REPEATC ds_inference_SIMPLE_UNROLL___CONV___precondition_list) THENC
1683   (REPEATC ds_inference_SIMPLE_UNROLL___CONV___points_to_list) THENC
1684   (REPEATC ds_inference_SIMPLE_UNROLL___CONV___points_to_bin_tree);
1685
1686
1687
1688
1689
1690(*example
1691val t = ``LIST_DS_ENTAILS (c1,c2) ([],[sf1;sf3;sf_bin_tree ("f1","f2") e;sf2]) ([],[])``
1692val t = ``LIST_DS_ENTAILS (c1,c2) ([pf_unequal e1 e2],[sf1;sf3;sf_ls "f" e1 e2;sf2]) ([],[])``
1693val t = ``LIST_DS_ENTAILS (c1,c2) ([pf2;pf_unequal e2 e1],[sf1;sf3;sf_ls "f" e1 e2;sf2]) ([],[])``
1694
1695*)
1696
1697
1698fun prove_infinite_univ_ante thm =
1699   let
1700      val (inf_univ_t, _)  = dest_imp (concl thm);
1701      val inf_univ_thm = (prove (inf_univ_t, SIMP_TAC std_ss (append (!INFINITE_UNIV___THMs) [INFINITE_UNIV___NUM,INFINITE_UNIV___STRING]))) handle _ =>
1702         (let
1703            val _ = print "Could not deduce \"INFINITE UNIV\"!. It is added as an assumption.\nPlease add this theorem to INFINITE_UNIV___THMs.\n\n";
1704         in
1705            ASSUME inf_univ_t
1706         end);
1707   in
1708      MP thm inf_univ_thm
1709   end;
1710
1711
1712fun find_list_uneq_unroll_left n pfL [] = NONE |
1713    find_list_uneq_unroll_left n pfL (h::l) =
1714      let
1715         val (f, e1, e2) = dest_sf_ls h;
1716         val (n2, uneq) = valOf (find_in_list (is_uneq_2 e1 e2) pfL);
1717         val (e1',e2') = dest_pf_unequal uneq;
1718         val turn = (e1 = e2');
1719      in
1720         SOME (n, n2, turn, e1, e2, f)
1721      end handle _ => find_list_uneq_unroll_left (n+1) pfL l;
1722
1723
1724fun ds_inference_UNROLL_LIST___NON_EMPTY___CONV t =
1725   let
1726      val (c1, c2, pf, sf, pf', sf') = dest_LIST_DS_ENTAILS t;
1727      val (pfL, _) = strip_cons pf;
1728      val (sfL, _) = strip_cons sf;
1729
1730
1731      val searchOpt = find_list_uneq_unroll_left 0 pfL sfL;
1732      val _ = if (isSome searchOpt) then () else SMALLFOOT_ERR "Not suitable list found!";
1733      val (n, n2, turn, e1, e2, f) = valOf searchOpt;
1734
1735      val thm = ISPECL [numLib.term_of_int n, numLib.term_of_int n2,
1736            if turn then T else F, e1, e2, f, c1, c2, pf, sf, pf', sf']
1737         INFERENCE_UNROLL_COLLAPSE_LS___NON_EMPTY___EVAL
1738      val thm2 = CONV_RULE (computeLib.CBV_CONV unroll_cs) thm;
1739      val thm3 = prove_infinite_univ_ante thm2;
1740      val _ = if (lhs (concl thm3) = t) then () else SMALLFOOT_ERR "No CONVERSION";
1741   in
1742      thm3
1743   end
1744
1745val ds_inference_PRECONDITION_CASES___CONV =
1746   REWR_CONV INFERENCE_UNROLL_COLLAPSE_PRECONDITION___EVAL;
1747
1748
1749
1750fun ds_inference_UNROLL_LIST___CONV t =
1751   let
1752      val (c1, c2, pf, sf, pf', sf') = dest_LIST_DS_ENTAILS t;
1753      val (sfL, _) = strip_cons sf;
1754
1755
1756      val searchOpt = find_in_list is_sf_ls sfL;
1757      val _ = if (isSome searchOpt) then () else SMALLFOOT_ERR "Not suitable list found!";
1758      val (n, list_term) = valOf searchOpt;
1759      val (f, e1, e2) = dest_sf_ls list_term;
1760
1761      val thm = ISPECL [numLib.term_of_int n,
1762            e1, e2, f, c1, c2, pf, sf, pf', sf']
1763         INFERENCE_UNROLL_COLLAPSE_LS___EVAL
1764      val thm2 = CONV_RULE (computeLib.CBV_CONV unroll_cs) thm;
1765      val thm3 = prove_infinite_univ_ante thm2;
1766      val _ = if (lhs (concl thm3) = t) then () else SMALLFOOT_ERR "No CONVERSION";
1767   in
1768      thm3
1769   end
1770
1771
1772fun ds_inference_UNROLL_BIN_TREE___CONV t =
1773   let
1774      val (c1, c2, pf, sf, pf', sf') = dest_LIST_DS_ENTAILS t;
1775      val (sfL, _) = strip_cons sf;
1776
1777
1778      val searchOpt = find_in_list is_sf_bin_tree sfL;
1779      val _ = if (isSome searchOpt) then () else SMALLFOOT_ERR "Not suitable binary tree found!";
1780      val (n, tree_term) = valOf searchOpt;
1781      val (f1,f2, e1, _) = dest_sf_bin_tree tree_term;
1782
1783      val thm = ISPECL [numLib.term_of_int n,
1784            e1, f1, f2, c1, c2, pf, sf, pf', sf']
1785         INFERENCE_UNROLL_COLLAPSE_BIN_TREE___EVAL;
1786      val thm2 = CONV_RULE (computeLib.CBV_CONV unroll_cs) thm;
1787      val thm3 = prove_infinite_univ_ante thm2;
1788      val _ = if (lhs (concl thm3) = t) then () else SMALLFOOT_ERR "No CONVERSION";
1789   in
1790      thm3
1791   end
1792
1793
1794
1795
1796(*
1797val t = ``LIST_DS_ENTAILS (c1,c2) ([pf_equal e2 e1],[sf1;sf3;sf2]) ([],[sf_ls f e1 e2;sf_tree fL es e])``
1798*)
1799fun is_tree_case_candidate pfL t =
1800   let
1801      val (_, e2, e1) = dest_sf_tree t;
1802   in
1803      not (isSome (find_in_list (is_uneq_2 e1 e2) pfL)) andalso
1804      not (isSome (find_in_list (is_eq_2 e1 e2) pfL))
1805   end;
1806
1807fun ds_inference_UNROLL_RIGHT_CASES___CONV t =
1808   let
1809      val (c1, c2, pf, sf, pf', sf') = dest_LIST_DS_ENTAILS t;
1810      val sf'' = rhs (concl (((REWRITE_CONV [sf_ls_def, sf_bin_tree_def] sf') handle _ => REFL sf')));
1811      val (pfL, _) = strip_cons pf;
1812      val (sfL', _) = strip_cons sf'';
1813
1814      val searchOpt = find_in_list (is_tree_case_candidate pfL) sfL';
1815      val _ = if (isSome searchOpt) then () else SMALLFOOT_ERR "Not suitable tree found!";
1816
1817      val (n, tree_term) = valOf searchOpt;
1818      val (_, e1, e2) = dest_sf_tree tree_term;
1819
1820      val thm = ISPECL [e1, e2, c1, c2, pf, sf, pf', sf']
1821         (GSYM INFERENCE_EXCLUDED_MIDDLE);
1822      val _ = if (lhs (concl thm) = t) then () else SMALLFOOT_ERR "No CONVERSION";
1823   in
1824      thm
1825   end;
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836(*
1837val t = ``LIST_DS_ENTAILS ([],[]) ([pf1;pf2],[sf4;sf_ls f e1 e2; sf5;sf6]) ([],[sf2;sf_ls f e1 dse_nil;sf1])``
1838
1839val t = ``LIST_DS_ENTAILS ([e3],[]) ([pf1;pf2;pf_unequal e3 e1],[sf4;sf_ls f e1 e2; sf5;sf6]) ([],[sf2;sf_ls f e1 e3;sf1])``
1840
1841
1842val t = ``LIST_DS_ENTAILS ([],[]) ([pf1;pf2;pf_unequal e3 e1],[sf_points_to e3 [(f,e2)];sf4;sf_ls f e1 e2; sf5;sf6]) ([],[sf2;sf_ls f e1 e3;sf1])``
1843
1844
1845val t = ``LIST_DS_ENTAILS ([],[]) ([pf1;pf_unequal e2 e3;pf2;pf_unequal e3 e1],[sf_points_to e3 [(f,e2)];sf4;sf_ls f e1 e2; sf5;sf_ls g e3 e2;sf6]) ([],[sf2;sf_ls f e1 e3;sf1])``
1846
1847*)
1848
1849
1850
1851fun get_uneq_index_turn pfL e1 e3 = let
1852      val (n, pf) = valOf (find_in_list (is_uneq_2 e1 e3) pfL);
1853      val (e1', e3') = dest_pf_unequal pf;
1854      val turn = not (e1' = e1);
1855   in
1856      (n, turn)
1857   end;
1858
1859fun find_list_append_instance_nil n1 n2 e1 e2 e3 f =
1860   let
1861      val _ = if (is_dse_nil e3) then () else SMALLFOOT_ERR "Not applicable!";
1862      val thm = ISPECL [numLib.term_of_int n1, numLib.term_of_int n2, e1, e2, f] INFERENCE_APPEND_LIST___nil___EVAL
1863   in
1864      thm
1865   end;
1866
1867fun find_list_append_instance_precond n1 n2 e1 e2 e3 f n3 b1 c1L =
1868   let
1869      val n4 = valOf (find_entry 0 e3 c1L)
1870      val thm = ISPECL [numLib.term_of_int n1, numLib.term_of_int n2, e1, e2, f, e3, numLib.term_of_int n4, numLib.term_of_int n3, if b1 then T else F] INFERENCE_APPEND_LIST___precond___EVAL
1871   in
1872      thm
1873   end;
1874
1875
1876fun find_list_append_instance_points_to n1 n2 e1 e2 e3 f n3 b1 sfL =
1877   let
1878      val (n4, pt) = valOf (find_in_list (is_sf_points_to_ex e3) sfL);
1879      val (_, a, _, _) = dest_sf_points_to pt;
1880
1881      val thm = ISPECL [numLib.term_of_int n1, numLib.term_of_int n2, e1, e2, f, e3, numLib.term_of_int n4, a, numLib.term_of_int n3, if b1 then T else F] INFERENCE_APPEND_LIST___points_to___EVAL
1882   in
1883      thm
1884   end;
1885
1886
1887fun del_el l n =
1888   List.take(l, n) @ List.drop(l, n+1)
1889
1890
1891fun find_list_append_instance_tree n1 n2 e1 e2 e3 f n3 b1 pfL sfL =
1892   let
1893      fun pred sf =
1894         let
1895            val (_, (fL, l), es, e3') = dest_sf_tree_ext sf;
1896            val _ = if (e3 = e3') then () else raise SMALLFOOT_ERR "Not suitable!";
1897            val fLt = list_mk_cons fL l;
1898            val (n5, b2) = get_uneq_index_turn pfL es e3';
1899         in
1900            SOME (fLt, n5, b2, es)
1901         end;
1902      val (n4, pt, (fLt, n5, b2,es)) = valOf (find_in_list_val pred (del_el sfL n1));
1903      val n4 = if (n4 < n1) then n4 else (n4 + 1);
1904
1905      val thm = ISPECL [numLib.term_of_int n1, numLib.term_of_int n2, e1, e2,
1906         numLib.term_of_int n4, e3, fLt, es,
1907         numLib.term_of_int n3, if b1 then T else F,
1908         numLib.term_of_int n5, if b2 then T else F, f] INFERENCE_APPEND_LIST___tree___EVAL
1909   in
1910      thm
1911   end;
1912
1913
1914fun find_list_append_instance n2 c1L pfL sfL [] = NONE |
1915    find_list_append_instance n2 c1L pfL sfL (sf'::sfL') =
1916    let
1917      val (f, e1, e3) = dest_sf_ls sf';
1918      val (n1, sf) = valOf (find_in_list (fn sf => (let val (f', e1', e2') = dest_sf_ls sf in (f = f') andalso (e1' = e1) end)) sfL);
1919      val (_, _, e2) = dest_sf_ls sf;
1920      val thm = find_list_append_instance_nil n1 n2 e1 e2 e3 f handle _ =>
1921                let
1922                   val (n3,b1) = get_uneq_index_turn pfL e1 e3;
1923                in
1924                   find_list_append_instance_precond n1 n2 e1 e2 e3 f n3 b1 c1L handle _ =>
1925                   find_list_append_instance_points_to n1 n2 e1 e2 e3 f n3 b1 sfL handle _ =>
1926                   find_list_append_instance_tree n1 n2 e1 e2 e3 f n3 b1 pfL sfL
1927                end;
1928    in
1929      SOME thm
1930    end handle _ => find_list_append_instance (n2+1) c1L pfL sfL sfL';
1931
1932
1933
1934fun ds_inference_APPEND_LIST___CONV t =
1935   let
1936      val (c1, c2, pf, sf, pf', sf') = dest_LIST_DS_ENTAILS t;
1937      val (c1L, _) = strip_cons c1;
1938      val (pfL, _) = strip_cons pf;
1939      val (sfL, _) = strip_cons sf;
1940      val (sfL', _) = strip_cons sf';
1941
1942      val inferenceOpt = find_list_append_instance 0 c1L pfL sfL sfL';
1943      val _ = if (isSome inferenceOpt) then () else SMALLFOOT_ERR "No suitable lists found!";
1944
1945      val thm = ISPECL [c1, c2, pf, sf, pf', sf'] (valOf inferenceOpt);
1946      val thm2 = CONV_RULE (computeLib.CBV_CONV unroll_cs) thm;
1947      val thm3 = prove_infinite_univ_ante thm2;
1948      val _ = if (lhs (concl thm3) = t) then () else SMALLFOOT_ERR "No CONVERSION";
1949   in
1950      thm3
1951   end
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963val ds_inference_NO_SPLIT_CONV =
1964   TRY_CONV ds_inference_SUBSTITUTION___CONV THENC
1965   TRY_CONV ds_inference_REMOVE_TRIVIAL___CONV THENC
1966   TRY_CONV ds_inference_HYPOTHESIS___CONV THENC
1967   TRY_CONV ds_inference_FRAME___CONV THENC
1968   TRY_CONV ds_inference_NIL_NOT_LVAL___CONV THENC
1969   TRY_CONV ds_inference_PARTIAL___CONV THENC
1970   (REPEATC ds_inference_APPEND_LIST___CONV) THENC
1971   TRY_CONV ds_inference_PRECONDITION_STRENGTHEN___CONV THENC
1972   (REPEATC ds_inference_SIMPLE_UNROLL___CONV) THENC
1973   TRY_CONV ds_inference_INCONSISTENT___CONV THENC
1974   TRY_CONV ds_inference_AXIOM___CONV;
1975
1976
1977val ds_inference_SPLIT_CONV =
1978   ds_inference_UNROLL_RIGHT_CASES___CONV ORELSEC
1979   ds_inference_PRECONDITION_CASES___CONV ORELSEC
1980   (CHANGED_CONV (REPEATC ds_inference_UNROLL_LIST___NON_EMPTY___CONV)) ORELSEC
1981   ds_inference_UNROLL_LIST___CONV ORELSEC
1982   ds_inference_UNROLL_BIN_TREE___CONV;
1983
1984
1985fun ds_inference_CHECK_LIST_DS_ENTAILS_CONV t =
1986    let
1987      val _ = dest_LIST_DS_ENTAILS t;
1988    in
1989      raise UNCHANGED
1990    end
1991
1992val ds_DECIDE_CONV =
1993   (REDEPTH_CONV (CHANGED_CONV (
1994      ds_inference_CHECK_LIST_DS_ENTAILS_CONV THENC
1995      (REPEATC ds_inference_NO_SPLIT_CONV) THENC
1996      TRY_CONV ds_inference_SPLIT_CONV)
1997   )) THENC REWRITE_CONV[];
1998
1999
2000fun ds_DECIDE t = EQT_ELIM (ds_DECIDE_CONV t);
2001
2002
2003
2004end;
2005