replace Celem. with new struct.s in BaseDefinitions/
Note: the remaining code in calcelems.sml shall be destributed to respective struct.s
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 -> Spec.pblID -> 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 -> (Exec_Def.prog_calcID * (Exec_Def.calID * Exec_Def.eval_fn)) list
36 val prep_rls: theory -> Rule_Set.T -> Rule_Set.T (*ren insert*)
37 val gen: theory -> term -> Rule_Set.T -> term
38 (* ---- for tests only: shifted from below to remove the Warning "unused" at fun.def. --------- *)
40 (*/-------------------------------------------------------- ! aktivate for Test_Isac BEGIN ---\* )
41 val subst_typ: string -> typ -> term list -> (typ * typ) list
42 val is_calc: term -> bool
43 val rule2stac: theory -> Rule.rule -> term
44 val rule2stac_inst: theory -> Rule.rule -> term
45 val #> : term list -> term
46 val rules2scr_Rls : theory -> Rule.rule list -> term
47 val rules2scr_Seq : theory -> Rule.rule list -> term
48 ( *\--- ! aktivate for Test_Isac END ----------------------------------------------------------/*)
51 structure Auto_Prog(**): AUTO_GERNERATE_PROGRAM(**) =
55 (** build up a program from rules **)
57 (* make the term 'Subproblem (domID, pblID)' to a formula for frontend;
58 needs to be here after def. Subproblem in Prog_Tac.thy *)
59 val subpbl_t $ (pair_t $ _ $ _) = (Thm.term_of o the o (TermC.parse @{theory Prog_Tac}))
60 "Subproblem (''Isac_Knowledge'',[''equation'',''univar''])"
62 (Thm.term_of o the o (TermC.parse @{theory Prog_Tac})) "Problem (''Isac_Knowledge'',[''equation'',''univar''])"
64 fun subpbl domID pblID =
65 subpbl_t $ (pair_t $ HOLogic.mk_string domID $
66 list_comb (Syntax.const @{const_syntax Char}, map HOLogic.mk_string pblID));
67 fun pblterm domID pblID =
68 pbl_t $ (pair_t $ HOLogic.mk_string domID $
69 list_comb (Syntax.const @{const_syntax Char}, map HOLogic.mk_string pblID));
71 (* fetch tactics from a program omitting tacticals like While, Repeat,.. *)
72 fun stacpbls (_ $ body) =
74 fun scan (Const ("HOL.Let", _) $ e $ (Abs (_, _, b))) = (scan e) @ (scan b)
75 | scan (Const ("Tactical.If", _) $ _ $ e1 $ e2) = (scan e1) @ (scan e2)
76 | scan (Const ("Tactical.While", _) $ _ $ e $ _) = scan e
77 | scan (Const ("Tactical.While", _) $ _ $ e) = scan e
78 | scan (Const ("Tactical.Repeat", _) $ e $ _) = scan e
79 | scan (Const ("Tactical.Repeat", _) $ e) = scan e
80 | scan (Const ("Tactical.Try", _) $ e $ _) = scan e
81 | scan (Const ("Tactical.Try", _) $ e) = scan e
82 | scan (Const ("Tactical.Or", _) $ e1 $ e2 $ _) = (scan e1) @ (scan e2)
83 | scan (Const ("Tactical.Or", _) $ e1 $ e2) = (scan e1) @ (scan e2)
84 | scan (Const ("Tactical.Chain", _) $ e1 $ e2 $ _) = (scan e1) @ (scan e2)
85 | scan (Const ("Tactical.Chain", _) $ e1 $ e2) = (scan e1) @ (scan e2)
86 | scan t = case Prog_Tac.eval_leaf [] NONE TermC.empty t of
87 (Program.Tac _, _) => [t] | (Program.Expr _, _) => []
88 in (distinct o scan) body end
89 | stacpbls t = raise ERROR ("fun stacpbls not applicable to '" ^ UnparseC.term t ^ "'")
91 (* get operators out of a program *)
92 fun is_calc (Const ("Prog_Tac.Calculate",_) $ _) = true
93 | is_calc (Const ("Prog_Tac.Calculate",_) $ _ $ _) = true
95 fun op_of_calc (Const ("Prog_Tac.Calculate",_) $ op_) = HOLogic.dest_string op_
96 | op_of_calc (Const ("Prog_Tac.Calculate",_) $ op_ $ _) = HOLogic.dest_string op_
97 | op_of_calc t = error ("op_of_calc called with " ^ UnparseC.term t);
98 fun get_calcs thy sc =
103 |> (assoc_calc' thy |> map);
105 (** build up a program from rules **)
107 (* transform type rule to a term *)
108 (*WN060605 script-arg (t_::'z) and "Free (t_, 'a)" at end of body are inconsistent !!!*)
109 val (FunID_Term $ _) = Program.prep_program @{thm auto_generated.simps}
110 val (FunID_Term_Bdv $ _) = Program.prep_program @{thm auto_generated_inst.simps}
111 val Repeat $ _ = (TermC.inst_abs o Thm.term_of o the o (TermC.parseN @{theory}))
112 "Repeat (Rewrite ''real_diff_minus'' t)";
113 val Try $ _ = (TermC.inst_abs o Thm.term_of o the o (TermC.parseN @{theory}))
114 "Try (Rewrite ''real_diff_minus'' t)";
115 val Cal $ _ = (TermC.inst_abs o Thm.term_of o the o (TermC.parseN @{theory}))
116 "Calculate ''PLUS''";
117 val Ca1 $ _ = (TermC.inst_abs o Thm.term_of o the o (TermC.parseN @{theory}))
118 "Calculate1 ''PLUS''";
119 val Rew $ _ $ _ = (TermC.inst_abs o Thm.term_of o the o (TermC.parseN @{theory}))
120 "Rewrite ''real_diff_minus'' t";
121 (*this is specific to FunHead_inst ...*)
122 val Rew_Inst $ Subs $ _ = (TermC.inst_abs o Thm.term_of o the o (TermC.parseN @{theory}))
123 "Rewrite_Inst [(''bdv'',v)] ''real_diff_minus''";
124 val Rew_Set $ _ = (TermC.inst_abs o Thm.term_of o the o (TermC.parseN @{theory}))
125 "Rewrite_Set ''real_diff_minus''";
126 val Rew_Set_Inst $ _ $ _ = (TermC.inst_abs o Thm.term_of o the o (TermC.parseN @{theory}))
127 "Rewrite_Set_Inst [(''bdv'',v)] ''real_diff_minus''";
128 val SEq $ _ $ _ $ _ = (TermC.inst_abs o Thm.term_of o the o (TermC.parseN @{theory}))
129 " ((Try (Repeat (Rewrite ''real_diff_minus''))) #> \
130 \ (Try (Repeat (Rewrite ''add.commute''))) #> \
131 \ (Try (Repeat (Rewrite ''mult_commute'')))) t";
133 fun rule2stac _ (Rule.Thm (thmID, _)) = Try $ (Repeat $ (Rew $ HOLogic.mk_string thmID))
134 | rule2stac thy (Rule.Eval (c, _)) = Try $ (Repeat $ (Cal $ HOLogic.mk_string (assoc_calc thy c)))
135 | rule2stac thy (Rule.Cal1 (c, _)) = Try $ (Repeat $ (Ca1 $ HOLogic.mk_string (assoc_calc thy c)))
136 | rule2stac _ (Rule.Rls_ rls) = Try $ (Rew_Set $ HOLogic.mk_string (Rule_Set.id rls))
137 | rule2stac _ r = raise ERROR ("rule2stac: not applicable to \"" ^ Rule.to_string r ^ "\"");
138 fun rule2stac_inst _ (Rule.Thm (thmID, _)) =
139 Try $ (Repeat $ (Rew_Inst $ Subs $ HOLogic.mk_string thmID))
140 | rule2stac_inst thy (Rule.Eval (c, _)) =
141 Try $ (Repeat $ (Cal $ HOLogic.mk_string (assoc_calc thy c)))
142 | rule2stac_inst thy (Rule.Cal1 (c, _)) =
143 Try $ (Repeat $ (Cal $ HOLogic.mk_string (assoc_calc thy c)))
144 | rule2stac_inst _ (Rule.Rls_ rls) =
145 Try $ (Rew_Set_Inst $ Subs $ HOLogic.mk_string (Rule_Set.id rls))
146 | rule2stac_inst _ r = raise ERROR ("rule2stac_inst: not applicable to \"" ^ Rule.to_string 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 | #> [s1, s2] = SEq $ s1 $ s2
155 | #> stacs = case rev stacs of
156 s3 :: s2 :: ss => op #>@ (SEq $ s2 $ s3) ss
157 | ts => raise ERROR ("fun #> not applicable to \"" ^ UnparseC.terms ts ^ "\"")
159 val contains_bdv = (not o null o (filter TermC.is_bdv) o TermC.ids2str o #prop o Thm.rep_thm);
161 (* does a rule contain a 'bdv'; descend recursively into Rls_ *)
162 fun contain_bdv [] = false
163 | contain_bdv (Rule.Thm (_, thm) :: rs) =
164 if (not o contains_bdv) thm
167 | contain_bdv (Rule.Eval _ :: rs) = contain_bdv rs
168 | contain_bdv (Rule.Cal1 _ :: rs) = contain_bdv rs
169 | contain_bdv (Rule.Rls_ rls :: rs) =
170 contain_bdv (Rule_Set.get_rules rls) orelse contain_bdv rs
171 | contain_bdv (r :: _) =
172 error ("contain_bdv called with [" ^ Rule.id r ^ ",...]");
174 (* filter Frees for free_str and pair their respective types with typ *)
175 fun subst_typ free_str typ frees =
177 val vars_v = filter (fn t => curry op = (t |> dest_Free |> fst) free_str) frees
178 val typs_v = map (fn t => (t |> dest_Free |> snd)) vars_v
180 map (fn T => (T, typ)) typs_v
182 (* instantiate typs in Prog auto_generated or auto_generated_ins for args "t_t", "v" *)
183 fun subst_typs prog typ_t typ_bdv =
185 val args = Program.formal_args prog
186 val frees = TermC.vars prog
187 val prog' = subst_atomic_types (subst_typ "t_t" typ_t frees) prog
192 else (* auto_generated_inst has second argument "v" *)
193 subst_atomic_types (subst_typ "v" typ_bdv frees) prog'
196 fun rules2scr_Rls thy rules =
198 then FunID_Term_Bdv $ (Repeat $ (((op #> o (map (rule2stac_inst thy))) rules) $ TermC.empty))
199 else FunID_Term $ (Repeat $ (((op #> o (map (rule2stac thy))) rules) $ TermC.empty));
200 fun rules2scr_Seq thy rules =
202 then FunID_Term_Bdv $ (((op #> o (map (rule2stac_inst thy))) rules) $ TermC.empty)
203 else FunID_Term $ (((op #> o (map (rule2stac thy))) rules) $ TermC.empty);
205 (* REPLACED BY Auto_Prog.gen:
206 prepare the input for an rls for use:
207 # generate a program for stepwise execution of the rls
208 # filter the operators for Eval out of the script ?WN111014?
209 use this function while storing (TODO integrate..) into KEStore_Elems.add_rlss
211 fun prep_rls _ Rule_Set.Empty = error "prep_rls: not required for Erls"
212 | prep_rls thy (Rule_Def.Repeat {id, preconds, rew_ord, erls, srls, rules, errpatts, ...}) =
214 val sc = (rules2scr_Rls thy rules)
216 Rule_Def.Repeat {id = id, preconds = preconds, rew_ord = rew_ord, erls = erls, srls = srls,
217 calc = get_calcs thy sc,
218 rules = rules, errpatts = errpatts,
219 scr = Rule.Empty_Prog (*Rule.Prog sc AD-HOC REPLACED BY Auto_Prog.gen*)} end
220 | prep_rls thy (Rule_Set.Sequence {id, preconds, rew_ord, erls, srls, rules, errpatts, ...}) =
222 val sc = (rules2scr_Seq thy rules)
224 Rule_Set.Sequence {id = id, preconds = preconds, rew_ord = rew_ord, erls = erls, srls = srls,
225 calc = get_calcs thy sc,
226 rules = rules, errpatts = errpatts,
227 scr = Rule.Empty_Prog (*Rule.Prog sc AD-HOC REPLACED BY Auto_Prog.gen*)} end
228 | prep_rls _ (Rule_Set.Rrls {id, ...}) =
229 error ("prep_rls: not required for Rrls \"" ^ id ^ "\"");
231 (* on the fly generate a Prog from an rls for Detail_Step.go.
232 Types are not precise, but these are not required by LI.
233 Argument "thy" is only required for lookup in Know_Store.
237 val prog = case rls of
238 Rule_Def.Repeat {rules, ...} => rules2scr_Rls thy rules
239 | Rule_Set.Sequence {rules, ...} => rules2scr_Seq thy rules
240 | _ => raise ERROR ("Auto_Prog.gen: not for rule-set \"" ^ Rule_Set.id rls ^ "\"")
242 subst_typs prog (type_of t) (TermC.guess_bdv_typ t)