eliminate use of Thy_Info 10: arg. ctxt for Rule.to_string finished
1 (* Title: ProgLang/Auto_Prog
2 Author: Walther Neuper, Aug.2019
3 (c) due to copyright terms
6 theory Auto_Prog imports Prog_Tac Tactical begin
9 The tactics Rewrite_Set* create ONE step in a calculation by application of usually
10 MORE than one theorem (here called "rule").
11 However, students can request details of rewriting down to single applications of theorems.
12 For accomplishing such requests, a program is auto-generated from the items of a rule-set.
15 subsection \<open>consts for programs automatically built from rules\<close>
17 partial_function (tailrec) auto_generated :: "'z \<Rightarrow> 'z"
18 where "auto_generated t_t = t_t"
19 partial_function (tailrec) auto_generated_inst :: "'z \<Rightarrow> real \<Rightarrow> 'z"
20 where "auto_generated_inst t_t v = t_t"
23 subsection \<open>TODO: code for above\<close>
26 signature AUTO_GERNERATE_PROGRAM =
28 val contain_bdv: Rule.rule list -> bool
29 val contains_bdv: thm -> bool
30 val subst_typs: term -> typ -> typ -> term
31 val pblterm: ThyC.id -> Probl_Def.id -> term
32 val subpbl: string -> string list -> term
33 val stacpbls: term -> term list
34 val op_of_calc: term -> string
35 val get_calcs: theory -> term -> Eval_Def.ml_from_prog list
36 val prep_rls: theory -> Rule_Set.T -> Rule_Set.T (*ren insert*)
37 val gen: theory -> term -> Rule_Set.T -> term
39 val subst_typ: string -> typ -> term list -> (typ * typ) list
40 val is_calc: term -> bool
41 val rule2stac: theory -> Rule.rule -> term
42 val rule2stac_inst: theory -> Rule.rule -> term
43 val #> : term list -> term
44 val rules2scr_Rls : theory -> Rule.rule list -> term
45 val rules2scr_Seq : theory -> Rule.rule list -> term
49 structure Auto_Prog(**): AUTO_GERNERATE_PROGRAM(**) =
53 (** build up a program from rules **)
55 (* make the term 'Subproblem (domID, pblID)' to a formula for frontend;
56 needs to be here after def. Subproblem in Prog_Tac.thy *)
57 val subpbl_t $ (pair_t $ _ $ _) = (TermC.parseNEW'' @{theory Prog_Tac})
58 "Subproblem (''Isac_Knowledge'',[''equation'',''univar''])"
60 fun subpbl domID pblID =
61 subpbl_t $ (pair_t $ HOLogic.mk_string domID $
62 list_comb (Syntax.const @{const_syntax Char}, map HOLogic.mk_string pblID));
63 fun pblterm domID pblID =
64 pair_t $ HOLogic.mk_string domID $
65 list_comb (Syntax.const @{const_syntax Char}, map HOLogic.mk_string pblID);
67 (* fetch tactics from a program omitting tacticals like While, Repeat,.. *)
68 fun stacpbls (_ $ body) =
70 fun scan (Const (\<^const_name>\<open>Let\<close>, _) $ e $ (Abs (_, _, b))) = (scan e) @ (scan b)
71 | scan (Const (\<^const_name>\<open>Tactical.If\<close>, _) $ _ $ e1 $ e2) = (scan e1) @ (scan e2)
72 | scan (Const (\<^const_name>\<open>Tactical.While\<close>, _) $ _ $ e $ _) = scan e
73 | scan (Const (\<^const_name>\<open>Tactical.While\<close>, _) $ _ $ e) = scan e
74 | scan (Const (\<^const_name>\<open>Tactical.Repeat\<close>, _) $ e $ _) = scan e
75 | scan (Const (\<^const_name>\<open>Tactical.Repeat\<close>, _) $ e) = scan e
76 | scan (Const (\<^const_name>\<open>Tactical.Try\<close>, _) $ e $ _) = scan e
77 | scan (Const (\<^const_name>\<open>Tactical.Try\<close>, _) $ e) = scan e
78 | scan (Const (\<^const_name>\<open>Tactical.Or\<close>, _) $ e1 $ e2 $ _) = (scan e1) @ (scan e2)
79 | scan (Const (\<^const_name>\<open>Tactical.Or\<close>, _) $ e1 $ e2) = (scan e1) @ (scan e2)
80 | scan (Const (\<^const_name>\<open>Tactical.Chain\<close>, _) $ e1 $ e2 $ _) = (scan e1) @ (scan e2)
81 | scan (Const (\<^const_name>\<open>Tactical.Chain\<close>, _) $ e1 $ e2) = (scan e1) @ (scan e2)
82 | scan t = case Prog_Tac.eval_leaf [] NONE TermC.empty t of
83 (Program.Tac _, _) => [t] | (Program.Expr _, _) => []
84 in ((distinct op =) o scan) body end
85 | stacpbls t = raise ERROR ("fun stacpbls not applicable to '" ^ UnparseC.term t ^ "'")
87 (* get operators out of a program *)
88 fun is_calc (Const (\<^const_name>\<open>Prog_Tac.Calculate\<close>,_) $ _) = true
89 | is_calc (Const (\<^const_name>\<open>Prog_Tac.Calculate\<close>,_) $ _ $ _) = true
91 fun op_of_calc (Const (\<^const_name>\<open>Prog_Tac.Calculate\<close>,_) $ op_) = HOLogic.dest_string op_
92 | op_of_calc (Const (\<^const_name>\<open>Prog_Tac.Calculate\<close>,_) $ op_ $ _) = HOLogic.dest_string op_
93 | op_of_calc t = raise ERROR ("op_of_calc called with " ^ UnparseC.term t);
94 fun get_calcs thy sc =
99 |> (get_calc (Proof_Context.init_global thy) |> map);
101 (** build up a program from rules **)
103 (* transform type rule to a term *)
104 (*WN060605 script-arg (t_::'z) and "Free (t_, 'a)" at end of body are inconsistent !!!*)
105 val (FunID_Term $ _) = Program.prep_program @{thm auto_generated.simps}
106 val (FunID_Term_Bdv $ _) = Program.prep_program @{thm auto_generated_inst.simps}
107 val Repeat $ _ = (TermC.inst_abs o (TermC.parseNEW'' @{theory}))
108 "Repeat (Rewrite ''real_diff_minus'' t)";
109 val Try $ _ = (TermC.inst_abs o (TermC.parseNEW'' @{theory}))
110 "Try (Rewrite ''real_diff_minus'' t)";
111 val Cal $ _ = (TermC.inst_abs o (TermC.parseNEW'' @{theory}))
112 "Calculate ''PLUS''";
113 val Ca1 $ _ = (TermC.inst_abs o (TermC.parseNEW'' @{theory}))
114 "Calculate1 ''PLUS''";
115 val Rew $ _ $ _ = (TermC.inst_abs o (TermC.parseNEW'' @{theory}))
116 "Rewrite ''real_diff_minus'' t";
117 (*this is specific to FunHead_inst ...*)
118 val Rew_Inst $ Subs $ _ = (TermC.inst_abs o (TermC.parseNEW'' @{theory}))
119 "Rewrite_Inst [(''bdv'',v)] ''real_diff_minus''";
120 val Rew_Set $ _ = (TermC.inst_abs o (TermC.parseNEW'' @{theory}))
121 "Rewrite_Set ''real_diff_minus''";
122 val Rew_Set_Inst $ _ $ _ = (TermC.inst_abs o (TermC.parseNEW'' @{theory}))
123 "Rewrite_Set_Inst [(''bdv'',v)] ''real_diff_minus''";
124 val SEq $ _ $ _ $ _ = (TermC.inst_abs o (TermC.parseNEW'' @{theory}))
125 " ((Try (Repeat (Rewrite ''real_diff_minus''))) #> \
126 \ (Try (Repeat (Rewrite ''add.commute''))) #> \
127 \ (Try (Repeat (Rewrite ''mult_commute'')))) t"; (*has not yet been needed*)
129 fun rule2stac _ (Rule.Thm (thmID, _)) = Try $ (Repeat $ (Rew $ HOLogic.mk_string thmID))
130 | rule2stac thy (Rule.Eval (c, _)) = Try $ (Repeat $ (Cal $ HOLogic.mk_string
131 (get_calc_prog_id (Proof_Context.init_global thy) c)))
132 | rule2stac thy (Rule.Cal1 (c, _)) = Try $ (Repeat $ (Ca1 $ HOLogic.mk_string
133 (get_calc_prog_id (Proof_Context.init_global thy) c)))
134 | rule2stac _ (Rule.Rls_ rls) = Try $ (Rew_Set $ HOLogic.mk_string (Rule_Set.id rls))
135 | rule2stac thy r = raise ERROR ("rule2stac: not applicable to \"" ^
136 Rule.to_string (Proof_Context.init_global thy) r ^ "\"");
137 fun rule2stac_inst _ (Rule.Thm (thmID, _)) =
138 Try $ (Repeat $ (Rew_Inst $ Subs $ HOLogic.mk_string thmID))
139 | rule2stac_inst thy (Rule.Eval (c, _)) =
140 Try $ (Repeat $ (Cal $ HOLogic.mk_string (get_calc_prog_id (Proof_Context.init_global thy) c)))
141 | rule2stac_inst thy (Rule.Cal1 (c, _)) =
142 Try $ (Repeat $ (Cal $ HOLogic.mk_string (get_calc_prog_id (Proof_Context.init_global thy) c)))
143 | rule2stac_inst _ (Rule.Rls_ rls) =
144 Try $ (Rew_Set_Inst $ Subs $ HOLogic.mk_string (Rule_Set.id rls))
145 | rule2stac_inst thy r = raise ERROR ("rule2stac_inst: not applicable to \"" ^
146 Rule.to_string (Proof_Context.init_global thy) r ^ "\"");
148 (*for appropriate nesting take stacs in _reverse_ order*)
149 fun op #>@ sts [s] = SEq $ s $ sts
150 | op #>@ sts (s::ss) = op #>@ (SEq $ s $ sts) ss
152 raise ERROR ("fun #>@ not applicable to \"" ^ UnparseC.term t ^ "\" \"" ^ UnparseC.terms ts ^ "\"");
154 fun op #> [stac] = stac
155 | op #> [s1, s2] = SEq $ s1 $ s2
156 | op #> stacs = case rev stacs of
157 s3 :: s2 :: ss => op #>@ (SEq $ s2 $ s3) ss
158 | ts => raise ERROR ("fun #> not applicable to \"" ^ UnparseC.terms ts ^ "\"")
160 val contains_bdv = not o null o filter TermC.is_bdv o TermC.ids2str o Thm.prop_of;
162 (* does a rule contain a 'bdv'; descend recursively into Rls_ *)
163 fun contain_bdv [] = false
164 | contain_bdv (Rule.Thm (_, thm) :: rs) =
165 if (not o contains_bdv) thm
168 | contain_bdv (Rule.Eval _ :: rs) = contain_bdv rs
169 | contain_bdv (Rule.Cal1 _ :: rs) = contain_bdv rs
170 | contain_bdv (Rule.Rls_ rls :: rs) =
171 contain_bdv (Rule_Set.get_rules rls) orelse contain_bdv rs
172 | contain_bdv (r :: _) =
173 raise ERROR ("contain_bdv called with [" ^ Rule.id r ^ ",...]");
175 (* filter Frees for free_str and pair their respective types with typ *)
176 fun subst_typ free_str typ frees =
178 val vars_v = filter (fn t => curry op = (t |> dest_Free |> fst) free_str) frees
179 val typs_v = map (fn t => (t |> dest_Free |> snd)) vars_v
181 map (fn T => (T, typ)) typs_v
183 (* instantiate typs in Prog auto_generated or auto_generated_ins for args "t_t", "v" *)
184 fun subst_typs prog typ_t typ_bdv =
186 val args = Program.formal_args prog
187 val frees = TermC.vars prog
188 val prog' = subst_atomic_types (subst_typ "t_t" typ_t frees) prog
193 else (* auto_generated_inst has second argument "v" *)
194 subst_atomic_types (subst_typ "v" typ_bdv frees) prog'
197 fun rules2scr_Rls thy rules =
199 then FunID_Term_Bdv $ (Repeat $ (((op #> o (map (rule2stac_inst thy))) rules) $ TermC.empty))
200 else FunID_Term $ (Repeat $ (((op #> o (map (rule2stac thy))) rules) $ TermC.empty));
201 fun rules2scr_Seq thy rules =
203 then FunID_Term_Bdv $ (((op #> o (map (rule2stac_inst thy))) rules) $ TermC.empty)
204 else FunID_Term $ (((op #> o (map (rule2stac thy))) rules) $ TermC.empty);
206 (* REPLACED BY Auto_Prog.gen:
207 prepare the input for an rls for use:
208 # generate a program for stepwise execution of the rls
209 # filter the operators for Eval out of the script ?WN111014?
210 use this function while storing (TODO integrate..) into Know_Store.add_rlss
212 fun prep_rls _ Rule_Set.Empty = raise ERROR "prep_rls: not required for Erls"
213 | prep_rls thy (Rule_Def.Repeat {id, preconds, rew_ord, asm_rls, prog_rls, rules, errpatts, ...}) =
215 val sc = rules2scr_Rls thy rules
217 Rule_Def.Repeat {id = id, preconds = preconds, rew_ord = rew_ord, asm_rls = asm_rls, prog_rls = prog_rls,
218 calc = get_calcs thy sc,
219 rules = rules, errpatts = errpatts,
220 program = Rule.Empty_Prog (*Rule.Prog sc AD-HOC REPLACED BY Auto_Prog.gen*)} end
221 | prep_rls thy (Rule_Set.Sequence {id, preconds, rew_ord, asm_rls, prog_rls, rules, errpatts, ...}) =
223 val sc = (rules2scr_Seq thy rules)
225 Rule_Set.Sequence {id = id, preconds = preconds, rew_ord = rew_ord, asm_rls = asm_rls, prog_rls = prog_rls,
226 calc = get_calcs thy sc,
227 rules = rules, errpatts = errpatts,
228 program = Rule.Empty_Prog (*Rule.Prog sc AD-HOC REPLACED BY Auto_Prog.gen*)} end
229 | prep_rls _ (Rule_Set.Rrls {id, ...}) =
230 raise ERROR ("prep_rls: not required for Rrls \"" ^ id ^ "\"");
232 (* on the fly generate a Prog from an rls for Detail_Step.go.
233 Types are not precise, but these are not required by LI.
234 Argument "thy" is only required for lookup in Know_Store.
238 val prog = case rls of
239 Rule_Def.Repeat {rules, ...} => rules2scr_Rls thy rules
240 | Rule_Set.Sequence {rules, ...} => rules2scr_Seq thy rules
241 | _ => raise ERROR ("Auto_Prog.gen: not for rule-set \"" ^ Rule_Set.id rls ^ "\"")
243 subst_typs prog (type_of t) (TermC.guess_bdv_typ t)