1structure separationLogicLib :> separationLogicLib =
2struct
3
4(*
5quietdec := true;
6loadPath :=
7            (Globals.HOLDIR ^ "/examples/separationLogic/src") ::
8            (Globals.HOLDIR ^ "/examples/separationLogic/src/holfoot") ::
9            !loadPath;
10show_assums := true;
11*)
12
13open HolKernel Parse boolLib bossLib;
14open listTheory rich_listTheory
15open separationLogicTheory;
16open separationLogicSyntax
17open vars_as_resourceTheory
18open quantHeuristicsLib
19open quantHeuristicsLibBase
20open ConseqConv
21open Profile
22
23(*
24quietdec := false;
25*)
26
27
28(*Aplies functional equality (FUN_EQ_THM
29 |- (f = g) <=> !x. f x = g x) to
30 replace allquantified variables in
31 equations with lambda abstractions.
32 For example
33
34val t = ``!a b c. f a b c = g a b c``
35
36 is converted to
37
38``f = (\a b c. g a b c)``
39
40 This conversion can be used to preprocess
41 rewrite rules, allowing the rewriter to
42 use these rules, even if not all parameters are
43 present, yet.*)
44
45fun GSYM_FUN_EQ_CONV t =
46let
47   val (vars, b_term) = strip_forall t;
48   val (l_term,r_term) = dest_eq b_term;
49   val (l_f, l_args) = strip_comb l_term;
50   fun split_vars [] acc = ([], acc)
51     | split_vars (t::ts) acc =
52       if mem t vars then
53           split_vars ts (t::acc)
54       else
55           (rev (t::ts), acc)
56   val (rest_args, elim_args) = split_vars (rev l_args) [];
57   val _ = if (elim_args = []) then raise UNCHANGED else ();
58   val rest_vars = filter (fn v => not (mem v elim_args)) vars;
59
60   val l_term' = list_mk_comb (l_f, rest_args);
61   val r_term' = list_mk_abs (elim_args, r_term);
62   val b_term' = mk_eq (l_term', r_term');
63   val t' = list_mk_forall (rest_vars, b_term');
64
65   val thm_term = mk_eq (t,t');
66   val thm = prove (thm_term, SIMP_TAC std_ss [FUN_EQ_THM] THEN
67                              EQ_TAC THEN SIMP_TAC std_ss [])
68in
69   thm
70end
71
72
73
74(*Given a theorem of the form |- l = r it returns a theorem
75  r |- l. If r is T, then |- l is returned *)
76fun EQ_ELIM thm =
77   let
78      val (l,r) = dest_eq (concl thm);
79   in
80      if (same_const r T) then EQT_ELIM thm else
81         EQ_MP (GSYM thm) (ASSUME r)
82   end
83
84(*Applies a conversion to the rhs of an equational theorem*)
85fun RHS_CONV_RULE conv thm =
86((CONV_RULE (RHS_CONV conv)) thm) handle UNCHANGED => thm;
87
88(*Applies a conversion to the antecedent of an implication*)
89val ANTE_CONV = (RATOR_CONV o RAND_CONV);
90fun ANTE_CONV_RULE conv thm = ((CONV_RULE o ANTE_CONV) conv) thm
91 handle UNCHANGED => thm;
92
93
94
95(***************************************************************
96 * PROGRAM ABSTRACTION
97 *
98 * The following functions are intended to abstract programs.
99 * A typical one of these functions has the following signature
100 *
101 * abst_function sys xenv penv prog
102 *
103 * given a program prog, this functions tries to find an abstration
104 * prog' and return a theorem of the form
105 *
106 * |- ASL_PROGRAM_IS_ABSTRACTION xenv penv prog prog'
107 *
108 * The parameter sys is a call to the system to ask it to abstract
109 * subprograms. It has the signature sys xenv penv prog.
110 * Calls to system never may fail, i.e. no useful abstraction can be found.
111 * In this case NONE is returned. Notice that
112 * prove_ASL_PROGRAM_ABSTRACTION_REFL may be used to produce
113 * |- ASL_PROGRAM_IS_ABSTRACTION xenv penv prog prog.
114 *
115 * If abst_function can not find an abstraction it should return NONE,
116 * throw an UNCHANGED exception or an HOL_ERR exception.
117 *
118 * There are abst_functions for the most common program constructs.
119 * Instantions of the framework might need to provide additional ones.
120 * These abstraction functions are combined by
121 * search_ASL_PROGRAM_ABSTRACTION fL abstL xenv penv prog
122 *
123 * - fL
124 *     a list of abst_functions
125 * - abstL
126 *     a list of already know abstraction, i.e. theorems of the form
127 *     something? |- ASL_PROGRAM_IS_ABSTRACTION xnev penv prog1 prog2
128 ****************************************************************)
129
130
131fun prove_ASL_PROGRAM_ABSTRACTION_REFL xenv penv p =
132    (ISPECL [xenv,penv,p] ASL_PROGRAM_IS_ABSTRACTION___REFL);
133
134
135type simple_asl_program_abstraction =  term -> term -> term -> thm option;
136type asl_program_abstraction =  (term -> term) -> thm list -> simple_asl_program_abstraction -> simple_asl_program_abstraction;
137
138
139local
140(*
141  fun check_thm_opt xenv penv p NONE = NONE
142    | check_thm_opt xenv penv p (SOME thm) =
143      let
144          val (xenv', penv', p', _) = dest_ASL_PROGRAM_IS_ABSTRACTION (concl thm);
145      in
146          if (xenv = xenv') andalso
147             (penv = penv') andalso (p = p') then SOME thm else
148          let
149             val ps = (term_to_string p);
150             val xenvs = term_to_string xenv;
151             val penvs = term_to_string penv;
152             val thms = thm_to_string thm;
153             val s = "Abstraction of "^ps^
154                     " in ("^xenvs^","^penvs^") resulted in "^
155                     thms^"!";
156             val _ = print s;
157          in
158             NONE
159          end
160      end;
161*)
162  fun check_thm_opt xenv penv p thm_opt = thm_opt
163
164  fun search_ASL_PROGRAM_ABSTRACTION_int (pf:term->term) true fL orgfL cref abstL xenv penv p =
165       let
166          val p_thm_opt_opt = Redblackmap.peek (!cref, p);
167          val thm_opt =
168             if (isSome p_thm_opt_opt) then (
169               (valOf p_thm_opt_opt)
170             ) else (
171               let
172                  val thm1_opt = search_ASL_PROGRAM_ABSTRACTION_int pf false fL orgfL cref abstL xenv penv p;
173                  val nc = Redblackmap.insert (!cref, p, thm1_opt)
174                  val _ = cref := nc
175               in
176                  thm1_opt
177               end
178             )
179       in
180           check_thm_opt xenv penv p thm_opt
181       end
182     | search_ASL_PROGRAM_ABSTRACTION_int pf false [] orgfL cref abstL xenv penv p = NONE
183     | search_ASL_PROGRAM_ABSTRACTION_int pf false (f1::fL) orgfL cref abstL xenv penv p =
184       let
185          val sys = search_ASL_PROGRAM_ABSTRACTION_int pf true orgfL orgfL cref abstL;
186          val thm1_opt = ((f1 pf abstL sys xenv penv p)
187                            handle HOL_ERR _ => NONE)
188                            handle UNCHANGED => NONE;
189       in
190          if not (isSome thm1_opt) then
191             search_ASL_PROGRAM_ABSTRACTION_int pf false fL orgfL cref abstL xenv penv p
192          else
193             check_thm_opt xenv penv p thm1_opt
194       end;
195in
196  fun search_ASL_PROGRAM_ABSTRACTION pf (fL:asl_program_abstraction list) abstL (xenv:term) (penv:term) =
197    let
198       val cref = ref (Redblackmap.mkDict (Term.compare))
199       val abstL' = (flatten (map BODY_CONJUNCTS abstL));
200       val sys = search_ASL_PROGRAM_ABSTRACTION_int pf true fL fL cref abstL' xenv penv;
201
202       fun search p =
203          let
204             val thm_opt = sys p;
205          in
206             if not (isSome thm_opt) then NONE else
207             let
208                val thm1 = valOf thm_opt;
209                val (_,_,_,p') = dest_ASL_PROGRAM_IS_ABSTRACTION (concl thm1);
210                val thm2_opt = search p';
211             in
212                if not(isSome thm2_opt) then thm_opt else
213                SOME (MATCH_MP (MATCH_MP
214                       ASL_PROGRAM_IS_ABSTRACTION___TRANSITIVE thm1)
215                       (valOf thm2_opt))
216             end
217          end
218    in
219       search
220    end
221end;
222
223
224
225(*
226val thmL = BODY_CONJUNCTS (ASSUME proc_abst_t)
227val t = ``asl_prog_procedure_call "merge" ([],[]):holfoot_program``
228*)
229
230fun ASL_PROGRAM_ABSTRACTION___match thmL sys xenv penv t =
231  let
232     val part = list_mk_icomb (ASL_PROGRAM_IS_ABSTRACTION_term, [xenv, penv, t]);
233  in
234     (tryfind (fn thm => SOME (PART_MATCH rator thm part)) thmL)
235        handle HOL_ERR _ => raise UNCHANGED
236  end;
237
238(*
239fun ASL_PROGRAM_ABSTRACTION___match thmL sys xenv penv t =
240  let
241     fun check_thm thm =
242         let
243            val (xenv', penv', p, p') = dest_ASL_PROGRAM_IS_ABSTRACTION t;
244            val m = match_term p t;
245            val _ = if (aconv xenv xenv') then () else fail();
246            val _ = if (aconv penv penv') then () else fail();
247         in
248            INST_TY_TERM m thm
249         end;
250  in
251     (tryfind check_thm thmL)
252        handle HOL_ERR _ => raise UNCHANGED
253  end;
254*)
255
256
257(*
258fun sys xenv penv t = NONE:thm option;
259val xenv = ``xenv :'a bin_option_function # ('b -> 'a -> bool)``
260val penv = ``penv :'c |-> ('d -> ('d, 'b, 'c, 'a) asl_program)``
261val p = ``(asl_prog_block (p1::pL)):('d, 'b, 'c, 'a) asl_program``
262*)
263
264fun ASL_PROGRAM_ABSTRACTION___block pf abstL sys xenv penv p =
265   let
266      (*destruct block*)
267      val bodyL = dest_asl_prog_block p;
268      val (h,restBodyL) = listSyntax.dest_cons bodyL handle HOL_ERR _ => raise UNCHANGED;
269
270      (*Abstract parts*)
271      val thm_h_opt = sys xenv penv h;
272      val rest = mk_asl_prog_block restBodyL;
273      val thm_rest_opt = sys xenv penv rest;
274
275      (*Has something been achived? If not abort*)
276      val _ = if (not (isSome thm_h_opt) andalso not (isSome thm_rest_opt)) then raise UNCHANGED else ();
277
278      (*create dummy abstractions if needed*)
279      val thm_h = if (isSome thm_h_opt) then valOf thm_h_opt else
280          prove_ASL_PROGRAM_ABSTRACTION_REFL xenv penv h;
281      val thm_rest = if (isSome thm_rest_opt) then valOf thm_rest_opt else
282          prove_ASL_PROGRAM_ABSTRACTION_REFL xenv penv rest;
283
284      (*make sure the second abstraction is again a block,
285        if necessary create one*)
286      val (_, _, _, p1) = dest_ASL_PROGRAM_IS_ABSTRACTION (concl thm_h);
287      val (_, _, _, p2) = dest_ASL_PROGRAM_IS_ABSTRACTION (concl thm_rest);
288
289      val (thm_rest', pL) = if (is_asl_prog_block p2) then (thm_rest, dest_asl_prog_block p2) else
290                            let
291                               val pL = listSyntax.mk_list ([p2], type_of p2);
292                               val thm_rest' = ONCE_REWRITE_RULE [GSYM ASL_PROGRAM_IS_ABSTRACTION___block_intro] thm_rest;
293                            in
294                               (thm_rest', pL)
295                            end;
296
297      (* instantiate everything*)
298      val thm = ISPECL [xenv, penv, h, restBodyL,p1,pL] ASL_PROGRAM_IS_ABSTRACTION___block;
299      val thm1 = MP thm thm_h
300      val thm2 = MP thm1 thm_rest'
301   in
302      SOME thm2
303   end;
304
305
306(*
307fun sys xenv penv t = NONE:thm option;
308val xenv = ``xenv :'a bin_option_function # ('b -> 'a -> bool)``
309val penv = ``penv :'c |-> ('d -> ('d, 'b, 'c, 'a) asl_program)``
310val p = ``(asl_prog_block (p1::(asl_prog_block L)::p3::L')):('d, 'b, 'c, 'a) asl_program``
311*)
312
313val append_thm_comment_nil1 = prove (``
314   (asl_comment_location c []) ++ h::hs =
315   (asl_comment_location c (h:'a))::hs``, REWRITE_TAC[asl_comment_location_def, APPEND])
316fun is_comment_nil t =
317   listSyntax.is_nil (#3 (dest_asl_comment t)) handle HOL_ERR _ => false
318
319val append_thm_nil1 = CONJUNCT1 APPEND
320val append_thm_nil2 = CONJUNCT1 APPEND_NIL
321val append_thm_cons = CONJUNCT2 APPEND
322
323fun list_append_norm_CONV tt =
324let
325   val (l1,l2) = listSyntax.dest_append tt;
326in
327   if ((listSyntax.is_append l1) orelse (listSyntax.is_append l2)) then
328      (((RATOR_CONV o RAND_CONV) list_append_norm_CONV)  THENC
329       ((RAND_CONV) list_append_norm_CONV) THENC
330       list_append_norm_CONV) tt
331   else if (listSyntax.is_nil l1) then
332      ISPEC l2 append_thm_nil1
333   else if (listSyntax.is_nil l2) then
334      ISPEC l1 append_thm_nil2
335   else if (is_comment_nil l1) then
336      REWR_CONV append_thm_comment_nil1 tt
337   else let
338        val (h, l1') = listSyntax.dest_cons l1;
339        val thm0 = ISPECL [l1', l2, h] append_thm_cons
340        val thm1 = CONV_RULE (RHS_CONV (RAND_CONV list_append_norm_CONV)) thm0
341     in
342        thm1
343     end
344end handle HOL_ERR _ => raise UNCHANGED;
345
346
347
348fun ASL_PROGRAM_ABSTRACTION___block_flatten pf abstL sys xenv penv p =
349   let
350      (* destruct input *)
351      val bodyL = dest_asl_prog_block p;
352      val (body_termL,body_term_rest) = listSyntax.strip_cons bodyL handle HOL_ERR _ => raise UNCHANGED;
353      val body_term_type = listSyntax.dest_list_type (type_of body_term_rest)
354
355      (* find another block *)
356      val pos = index is_asl_prog_block body_termL
357                   handle HOL_ERR _ => raise UNCHANGED;
358
359      (* split into the list before and after the found block *)
360      val L1_termL = List.take (body_termL,pos)
361      val L1_term = listSyntax.mk_list (L1_termL, body_term_type);
362
363      val L23_termL = List.drop (body_termL,pos);
364      val L2_term = dest_asl_prog_block (hd L23_termL);
365
366      val L3_termL = tl L23_termL;
367      val L3_term = itlist (curry listSyntax.mk_cons) L3_termL body_term_rest;
368
369      (*instantiate the corresponding theorem *)
370      val thm0 = ISPECL [xenv, penv, L1_term, L2_term, L3_term] ASL_PROGRAM_IS_ABSTRACTION___block_flatten;
371
372      (*However, this theorem contains append, it needs to be normalised*)
373      val (_,_,orgL, newL) = dest_ASL_PROGRAM_IS_ABSTRACTION (concl thm0);
374
375      val orgL_thm =  (RAND_CONV list_append_norm_CONV) orgL;
376      val newL_thm =  (RAND_CONV list_append_norm_CONV) newL;
377
378      val thm1 = CONV_RULE
379                   (((RATOR_CONV o RAND_CONV) (K orgL_thm)) THENC
380                    (RAND_CONV (K newL_thm))) thm0
381   in
382      SOME thm1
383   end;
384
385
386val ASL_PROGRAM_ABSTRACTION___block_flatten___no_rec =
387   ASL_PROGRAM_ABSTRACTION___block_flatten I [] (fn x => NONE)
388
389(*
390fun sys xenv penv t = NONE:thm option;
391val xenv = ``xenv :'a bin_option_function # ('b -> 'a -> bool)``
392val penv = ``penv :'c |-> ('d -> ('d, 'b, 'c, 'a) asl_program)``
393val p = ``(asl_prog_cond c p1 p2):('d, 'b, 'c, 'a) asl_program``
394*)
395fun ASL_PROGRAM_ABSTRACTION___cond pf abstL sys xenv penv p =
396   let
397      (*destruct*)
398      val (c,p1,p2) = dest_asl_prog_cond p;
399
400      (*search abstractions*)
401      val p1_thm_opt = sys xenv penv p1;
402      val p2_thm_opt = sys xenv penv p2;
403
404      (*found something?*)
405      val _ = if (not (isSome p1_thm_opt) andalso not (isSome p2_thm_opt)) then raise UNCHANGED else ();
406      val p1_thm = if (isSome p1_thm_opt) then valOf p1_thm_opt else
407          prove_ASL_PROGRAM_ABSTRACTION_REFL xenv penv p1;
408      val p2_thm = if (isSome p2_thm_opt) then valOf p2_thm_opt else
409          prove_ASL_PROGRAM_ABSTRACTION_REFL xenv penv p2;
410
411
412      (*prove the final theorem*)
413      val (_,_,_,p1') = dest_ASL_PROGRAM_IS_ABSTRACTION (concl p1_thm);
414      val (_,_,_,p2') = dest_ASL_PROGRAM_IS_ABSTRACTION (concl p2_thm);
415
416      val thm = ISPECL [xenv, penv, c, p1,p1',p2,p2'] ASL_PROGRAM_IS_ABSTRACTION___cond;
417      val thm1 = MP thm p1_thm
418      val thm2 = MP thm1 p2_thm
419   in
420      SOME thm2
421   end;
422
423
424(*
425fun sys xenv penv t = SOME (prove_ASL_PROGRAM_ABSTRACTION_REFL xenv penv t)
426fun sys xenv penv t = NONE:thm option;
427val xenv = ``xenv :'a bin_option_function # ('b -> 'a -> bool)``
428val penv = ``penv :'c |-> ('d -> ('d, 'b, 'c, 'a) asl_program)``
429val p = ``(asl_prog_while c p):('d, 'b, 'c, 'a) asl_program``
430*)
431fun ASL_PROGRAM_ABSTRACTION___while pf abstL sys xenv penv p =
432   let
433      val (c,p) = dest_asl_prog_while p;
434
435      (*search abstraction*)
436      val p_thm_opt = sys xenv penv p;
437      val p_thm = if (isSome p_thm_opt) then valOf p_thm_opt else raise UNCHANGED;
438      val (_,_,_,p') = dest_ASL_PROGRAM_IS_ABSTRACTION (concl p_thm);
439
440      val thm = ISPECL [xenv, penv, c, p,p'] ASL_PROGRAM_IS_ABSTRACTION___while;
441      val thm1 = MP thm p_thm;
442   in
443      SOME thm1
444   end;
445
446fun ASL_PROGRAM_ABSTRACTION___comment pf abstL sys xenv penv p =
447   let
448      val (_, c, p', def_thm) = dest_asl_comment p;
449
450      (*search abstraction*)
451      val p_thm_opt = sys xenv penv p';
452      val p_thm = if (isSome p_thm_opt) then valOf p_thm_opt else raise UNCHANGED;
453
454      val (_,_,_,p'') = dest_ASL_PROGRAM_IS_ABSTRACTION (concl p_thm);
455      val thm_p' = ISPECL [c, p'] def_thm
456      val thm_p'' = ISPECL [c, p''] def_thm
457
458      val thm0 = CONV_RULE ((RAND_CONV) (K (GSYM thm_p''))) p_thm
459      val thm1 = CONV_RULE ((RATOR_CONV o RAND_CONV) (K (GSYM thm_p'))) thm0
460   in
461      SOME thm1
462   end;
463
464
465val basic_asl_program_abstractions = [
466    ASL_PROGRAM_ABSTRACTION___block_flatten,
467    ASL_PROGRAM_ABSTRACTION___block,
468    ASL_PROGRAM_ABSTRACTION___cond,
469    ASL_PROGRAM_ABSTRACTION___comment,
470    ASL_PROGRAM_ABSTRACTION___while]:asl_program_abstraction list;
471
472
473(*
474
475val fL = append basic_asl_program_abstractions [
476   ASL_PROGRAM_ABSTRACTION___local_var,
477   ASL_PROGRAM_ABSTRACTION___call_by_value_arg,
478   ASL_PROGRAM_ABSTRACTION___eval_expressions]
479
480val t = rand (snd (strip_forall (el 1 (strip_conj specs_t))))
481val abstL = [ASSUME proc_abst_t]
482
483*)
484
485fun ASL_PROGRAM_HOARE_TRIPLE___ABSTRACTION___CONSEQ_CONV fL abstL t =
486   let
487     val _ = if (is_ASL_PROGRAM_HOARE_TRIPLE t) then () else raise UNCHANGED;
488     val (xenv, penv, pre, body, post) = dest_ASL_PROGRAM_HOARE_TRIPLE t;
489
490     val thm_opt =  search_ASL_PROGRAM_ABSTRACTION I fL abstL xenv penv body;
491     val thm = if (isSome thm_opt) then valOf thm_opt else raise UNCHANGED;
492
493     val thm2 = ISPECL [xenv, penv, pre, body, post] ASL_PROGRAM_HOARE_TRIPLE_ABSTRACTION___INTRO;
494     val thm3 = MATCH_MP thm2 thm;
495   in
496     thm3
497   end;
498
499
500(*
501   val t = ``ASL_PROGRAM_IS_ABSTRACTION xenv penv p1 p2``
502
503   val SOME (fL, abstL, t) = !t_opt
504
505*)
506
507fun ASL_PROGRAM_IS_ABSTRACTION___ABSTRACTION___CONSEQ_CONV fL abstL t =
508   let
509     val (xenv, penv, p1, p3) = dest_ASL_PROGRAM_IS_ABSTRACTION t handle HOL_ERR _ => raise UNCHANGED
510
511     val print_fun =
512     let
513         val (a1, a2, _, x) = dest_asl_procedure_call_preserve_names_wrapper
514              (find_term is_asl_procedure_call_preserve_names_wrapper p3)
515         val (x1,x2) = pairSyntax.dest_pair x;
516         fun mk_list_term x a =
517           let
518               val ty = listSyntax.dest_list_type (type_of x)
519               val sL = map (fst o dest_var) (fst (listSyntax.dest_list a))
520               val vL = map (fn s => mk_var (s, ty)) sL;
521           in
522               listSyntax.mk_list (vL, ty)
523           end;
524         val l1 = mk_list_term x1 a1;
525         val l2 = mk_list_term x2 a2
526         val su = subst [x1 |-> l1, x2 |-> l2]
527     in
528         fn p1 => (rhs (concl (SIMP_CONV list_ss [] (su p1)))) handle UNCHANGED => su p1
529     end handle UNCHANGED => I
530              | HOL_ERR _ => I
531
532     val thm_opt =  search_ASL_PROGRAM_ABSTRACTION print_fun fL abstL xenv penv p1;
533     val thm = if (isSome thm_opt) then valOf thm_opt else raise UNCHANGED;
534
535     val (_, _, _, p2) = dest_ASL_PROGRAM_IS_ABSTRACTION (concl thm);
536
537     val thm2 = ISPECL [xenv, penv, p1, p2, p3] ASL_PROGRAM_IS_ABSTRACTION___TRANSITIVE;
538     val thm3 = MP thm2 thm;
539   in
540     thm3
541   end;
542
543
544
545
546
547(***************************************************************
548 * HANDLE SPECIFICATIONS
549 *
550 * Elininate function calls
551 ****************************************************************)
552
553
554val names_all_distinct_cs = computeLib.bool_compset ();
555val _ = computeLib.add_thms [listTheory.MAP, pairTheory.FST, pairTheory.SND,
556                             listTheory.ALL_DISTINCT,
557                             listTheory.MEM] names_all_distinct_cs;
558val _ = computeLib.add_conv (``($=):'a -> 'a -> bool``, 2, stringLib.string_EQ_CONV) names_all_distinct_cs;
559
560
561
562val proc_free_specs_cs = computeLib.bool_compset ();
563val _ = computeLib.add_thms [listTheory.EVERY_DEF, pairTheory.SND, pairTheory.FST,
564    REWRITE_RULE [asl_prog_IS_RESOURCE_AND_PROCCALL_FREE___ALTERNATIVE_DEF] asl_prog_IS_RESOURCE_AND_PROCCALL_FREE___prim_command,
565    REWRITE_RULE [asl_prog_IS_RESOURCE_AND_PROCCALL_FREE___ALTERNATIVE_DEF] asl_prog_IS_RESOURCE_AND_PROCCALL_FREE___SIMPLE_REWRITES] proc_free_specs_cs;
566val _ = computeLib.add_conv (pairSyntax.uncurry_tm, 2, pairLib.GEN_BETA_CONV) proc_free_specs_cs;
567
568
569
570(*
571fun proc_call_free_CONV t = REWRITE_CONV [
572   REWRITE_RULE [asl_prog_IS_RESOURCE_AND_PROCCALL_FREE___ALTERNATIVE_DEF]
573      asl_prog_IS_RESOURCE_AND_PROCCALL_FREE___var_res_bla] t;
574
575val prog_rewrites = [var_res_prog_procedure_call_THM]
576
577val abstrL = append basic_asl_program_abstractions [
578   ASL_PROGRAM_ABSTRACTION___local_var,
579   ASL_PROGRAM_ABSTRACTION___call_by_value_arg,
580   ASL_PROGRAM_ABSTRACTION___eval_expressions]
581
582   val thm_strengthen_specs =
583      DEPTH_CONSEQ_CONV (ASL_PROGRAM_IS_ABSTRACTION___ABSTRACTION___CONSEQ_CONV abstrL [ASSUME proc_abst_t])
584                        specs_t
585
586val t = ``asl_comment_location_string "XXX" YYY``
587*)
588fun asl_comment_location_string_ELIM_CONV t =
589let
590   val (c, p) = dest_asl_comment_location_string t
591   val c_label = mk_var(stringLib.fromHOLstring c, markerSyntax.label_ty)
592   val c_list = listSyntax.mk_list ([c_label], markerSyntax.label_ty)
593
594   val thm1 = ISPECL [c,p] asl_comment_location_string_def
595   val thm2 = GSYM (ISPECL [c_list, p] asl_comment_location_def)
596in
597   TRANS thm1 thm2
598end;
599
600
601val precond1_cs = computeLib.bool_compset ();
602val _ = computeLib.add_thms [listTheory.EVERY_DEF,
603    pairTheory.FST, pairTheory.SND] precond1_cs;
604val _ = computeLib.add_conv (pairSyntax.uncurry_tm, 2, pairLib.GEN_BETA_CONV) precond1_cs;
605val _ = computeLib.add_conv (asl_comment_location_string_term, 2, asl_comment_location_string_ELIM_CONV) precond1_cs;
606
607
608val precond1_conv =
609   (QUANT_INSTANTIATE_CONV [pair_default_qp]) THENC
610   DEPTH_CONV (pairLib.GEN_BETA_CONV)
611
612
613
614fun ASL_SPECIFICATION___CONSEQ_CONV (proc_call_free_CONV, abstrL) t =
615let
616   (* apply SPECIFICATION INFERENCE *)
617   fun apply_inference_rule t =
618      let
619         val (f_term, res_decls_term, p_specs_term) = dest_ASL_SPECIFICATION t;
620         val thm1 = ISPECL [f_term, res_decls_term, p_specs_term] ASL_INFERENCE___SPECIFICATION;
621
622         val side_conds_term = fst (dest_imp (concl thm1));
623         val (proc_free_specs_term, distinct_proc_names_term) = dest_conj side_conds_term;
624
625
626         val proc_free_specs_thm = EQ_ELIM ((computeLib.CBV_CONV proc_free_specs_cs THENC
627                                            proc_call_free_CONV) proc_free_specs_term) handle HOL_ERR _ =>
628               failwith ("Could not prove that specifications are well formed!");
629
630         val distinct_proc_names_thm = EQ_ELIM (computeLib.CBV_CONV names_all_distinct_cs distinct_proc_names_term) handle HOL_ERR _ =>
631               failwith ("Could not prove that all procedure names are distinct!");
632
633         val thm2 = MP thm1 (CONJ proc_free_specs_thm distinct_proc_names_thm);
634      in
635         thm2
636      end;
637
638
639
640   (*Simplify*)
641   fun simplify_precond thm =
642      let
643         val thm1 = CONV_RULE (RATOR_CONV (RAND_CONV (computeLib.CBV_CONV precond1_cs))) thm;
644         val thm2 = CONV_RULE (RATOR_CONV (RAND_CONV (Conv.QUANT_CONV (RAND_CONV precond1_conv)))) thm1;
645      in
646         thm2
647      end;
648
649
650
651
652   (* Eliminate procedure calls, locks, etc. *)
653   fun eliminate_environment thm =
654   let
655      val precond = fst (dest_imp (concl thm));
656      val (penv_var, body) = dest_forall precond;
657      val (proc_abst_t, specs_t) = dest_imp body;
658
659      val thm_strengthen_specs =
660         DEPTH_STRENGTHEN_CONSEQ_CONV (ASL_PROGRAM_IS_ABSTRACTION___ABSTRACTION___CONSEQ_CONV abstrL [ASSUME proc_abst_t])
661                           specs_t handle UNCHANGED => REFL_CONSEQ_CONV specs_t;
662
663
664      val thm2 = let
665         val precond' = fst (dest_imp (concl thm_strengthen_specs));
666         val x_thm0 = ADD_ASSUM  proc_abst_t (UNDISCH thm_strengthen_specs)
667         val x_thm1 = DISCH proc_abst_t x_thm0
668         val x_thm2 = DISCH precond' x_thm1
669         val x_thm3 = GEN_IMP penv_var x_thm2
670         val precond'' = fst (dest_imp (concl x_thm3));
671         val x_thm4 = UNDISCH x_thm3
672         val x_thm5 = MP thm x_thm4
673         val x_thm6 = DISCH precond'' x_thm5
674         in x_thm6 end;
675   in
676     thm2
677   end;
678
679
680
681   val current_thm = apply_inference_rule t;
682   val current_thm2 = simplify_precond current_thm;
683   val current_thm3 = eliminate_environment current_thm2;
684in
685   current_thm3
686end;
687
688
689
690(******************************************************************************)
691(* Remove procedure_call_preserve_names_wrapper                               *)
692(******************************************************************************)
693
694(*
695val tt = ``asl_procedure_call_preserve_names_wrapper ["r"]
696                         ["p_const"] c ([q],[x])``
697*)
698
699fun asl_procedure_call_preserve_names_wrapper_ELIM_CONV tt =
700let
701   val thm0 = PART_MATCH (lhs o snd o dest_imp_only)
702      asl_procedure_call_preserve_names_wrapper_ELIM tt;
703   val precond = (fst o dest_imp o concl) thm0
704   val precond_thm = EQT_ELIM (REWRITE_CONV [LENGTH,
705       pairTheory.SND, pairTheory.FST] precond)
706in
707   MP thm0 precond_thm
708end;
709
710(******************************************************************************)
711(* HANDLE location comments                                                   *)
712(******************************************************************************)
713(*
714   val c = asl_comment_modify_INC c
715*)
716
717fun get_last_num_token c =
718let
719   val (la, cL) = listSyntax.dest_cons c
720   val s = fst (dest_var la)
721
722   val sL = String.tokens (fn c => c = #" ") s;
723   val ls = last sL;
724
725   val n_opt = Int.fromString ls
726   val (n, s') = if isSome n_opt then (valOf n_opt, String.concatWith " " (butlast sL))
727                    else (0, s)
728in
729   (n, s', cL, isSome n_opt)
730end handle HOL_ERR _ => (0, "", c, false)
731
732
733fun asl_comment_modify_NUM_OP f c =
734let
735
736   val (n, s', c', num_found) = get_last_num_token c
737
738   val ns = Int.toString (f n)
739   val s'' = s' ^ " " ^ ns;
740   val l = mk_var (s'', markerSyntax.label_ty)
741   val c'' = listSyntax.mk_cons (l, c')
742in
743   c''
744end;
745
746fun asl_comment_modify_NUM_COPY_INIT i c =
747let
748   val (n, s', c', num_found) = get_last_num_token c
749in
750   if num_found then c else
751   let
752      val s'' = s' ^ " " ^ (Int.toString i);
753      val l = mk_var (s'', markerSyntax.label_ty)
754      val c'' = listSyntax.mk_cons (l, c')
755   in
756      c''
757   end
758end;
759
760
761val asl_comment_modify_INC =
762  asl_comment_modify_NUM_OP (fn n => n+1);
763
764val asl_comment_modify_COPY_INIT =
765  asl_comment_modify_NUM_COPY_INIT 1;
766
767fun asl_comment_modify_APPEND s c =
768let
769   val l = mk_var (s, markerSyntax.label_ty)
770   val c' = listSyntax.mk_cons (l, c)
771in
772   c'
773end;
774
775
776fun asl_comment_modify_APPEND_INC s c =
777let
778   val (n, s', c',_) = get_last_num_token c
779
780   val c'' = listSyntax.mk_cons (mk_var
781                (s', markerSyntax.label_ty), c')
782
783   val ns = Int.toString (n + 1)
784   val s'' = s ^ " " ^ ns;
785   val c''' = listSyntax.mk_cons (mk_var
786                (s'', markerSyntax.label_ty), c'')
787in
788   c'''
789end;
790
791
792fun asl_comment_modify_APPEND_DEC s c =
793let
794   val (n, s', c',_) = get_last_num_token c
795
796   val c'' = listSyntax.mk_cons (mk_var
797                (s', markerSyntax.label_ty), c')
798
799   val ns = Int.toString (n - 1)
800   val s'' = s ^ " " ^ ns;
801   val c''' = listSyntax.mk_cons (mk_var
802                (s'', markerSyntax.label_ty), c'')
803in
804   c'''
805end;
806
807
808fun asl_comment_block_CONV conv t =
809   if (not (is_asl_prog_block t)) then conv t else
810   let
811      val pL = dest_asl_prog_block t;
812      val rec_call = asl_comment_block_CONV conv
813   in
814      if listSyntax.is_cons pL then
815         ((RAND_CONV o RATOR_CONV o RAND_CONV) rec_call) t
816      else if listSyntax.is_nil pL then
817         (RAND_CONV rec_call) t
818      else conv t
819   end;
820
821fun asl_comment_location_INTRO_CONV c t =
822   ISPECL [c, t] (GSYM asl_comment_location_def)
823
824fun asl_comment_location_BLOCK_INTRO_CONV c =
825   asl_comment_block_CONV (asl_comment_location_INTRO_CONV c)
826
827fun asl_comment_location2_INTRO_CONV c t =
828   ISPECL [c, t] (GSYM asl_comment_location2_def)
829
830fun asl_comment_abstraction_INTRO_CONV s t =
831   let
832      val l = mk_var (s, markerSyntax.label_ty);
833   in
834      ISPECL [l, t] (GSYM asl_comment_abstraction_def)
835   end;
836
837
838fun asl_comment_location_CONSEQ_RULE c thm =
839let
840   val _ = if is_eq (concl thm) orelse
841              is_imp_only (concl thm) then () else Feedback.fail ();
842in
843   CONV_RULE (BINOP_CONV (asl_comment_location_INTRO_CONV c)) thm
844end;
845
846
847fun asl_comment_location_CONSEQ_CONV conv t =
848let
849   val (c, t') = dest_asl_comment_location t;
850   val thm0 = conv t';
851in
852   asl_comment_location_CONSEQ_RULE c thm0
853end;
854
855
856fun asl_comment_location___TF_ELIM___CONV t =
857let
858   val (c, t') = dest_asl_comment_location t;
859   val _ = if (aconv t' T) orelse (aconv t' F) then () else raise UNCHANGED;
860in
861   ISPECL [c, t'] asl_comment_location_def
862end;
863
864
865fun CONSEQ_CONV_CONGRUENCE___location_comment context sys dir t =
866  let
867     val (c, body) = dest_asl_comment_location t
868     val (n1, thm0_opt) = sys [] context 0  dir body;
869     val _ = if (isSome thm0_opt) then () else raise UNCHANGED;
870
871     val thm1 = asl_comment_location_CONSEQ_RULE c (valOf thm0_opt)
872  in
873     (n1, thm1)
874  end
875
876
877(******************************************************************************)
878(* Remove asl_exists_list                                                     *)
879(******************************************************************************)
880
881(*
882val tt = ``asl_exists_list [aa; bb; cc] (\x s. (sdds x /\ D /\ (LENGTH x = 3)))``
883val tt = ttt
884val base_name = "name"
885val t2s = term_to_string
886val t2s = holfoot_term_to_string
887*)
888
889local
890   val conv_nil = REWR_CONV (CONJUNCT1 asl_exists_list___REWRITE)
891   val conv_cons = REWR_CONV (CONJUNCT2 asl_exists_list___REWRITE)
892   fun asl_exists_list_CONV_int [] =
893       conv_nil THENC (TRY_CONV BETA_CONV)
894     | asl_exists_list_CONV_int (n::ns) =
895       conv_cons THENC (RAND_CONV (RENAME_VARS_CONV [n])) THENC
896       RAND_CONV (ABS_CONV (
897           (RAND_CONV (ABS_CONV (TRY_CONV BETA_CONV))) THENC
898           asl_exists_list_CONV_int ns))
899in
900
901fun asl_exists_list_CONV base_name t2s tt =
902let
903   val (argL, P) = dest_asl_exists_list tt;
904   fun t2s' t = concat [base_name, "_", t2s t]
905   val namesL = map t2s' (fst (listSyntax.dest_list argL))
906   val P_v = genvar (type_of P)
907
908   val new_t = list_mk_icomb (asl_exists_list_term, [argL, P_v])
909   val thm0 = asl_exists_list_CONV_int namesL new_t;
910   val thm1 = INST [P_v |-> P] thm0
911   val thm2 = CONV_RULE (RHS_CONV (DEPTH_CONV BETA_CONV)) thm1
912in
913   thm2
914end;
915
916end;
917
918(*
919fun VAR_RES_LOCATION_COMMENT_step___CONV tt =
920let
921   val (c, body) = dest_asl_comment_location tt;
922in
923end
924*)
925
926
927
928
929(*
930open holfootParser
931open holfoot_pp_print
932val examplesDir = concat [Globals.HOLDIR, "/examples/separationLogic/src/holfoot/EXAMPLES/"]
933val file = concat [examplesDir, "mergesort.sf"];
934val file = concat [examplesDir, "mergesort.dsf"];
935val t = parse_holfoot_file file
936val t = parse_holfoot_file_restrict ["mergesort"] file
937
938temp_remove_holfoot_pp ();temp_add_holfoot_pp ();t
939temp_remove_holfoot_pp ();t
940
941
942
943open Profile
944add_holfoot_pp()
945reset_all ();
946val thm = time (ASL_SPECIFICATION___CONSEQ_CONV (proc_call_free_CONV, abstrL)) t;
947print_profile_results (results());
948
949
950open Profile
951reset_all ()
952print_profile_results (results())
953val cref = 0
954
955*)
956
957
958
959end
960