src/Tools/isac/ProgLang/Auto_Prog.thy
author Walther Neuper <walther.neuper@jku.at>
Tue, 21 Apr 2020 15:42:50 +0200
changeset 59898 68883c046963
parent 59887 4616b145b1cd
child 59903 5037ca1b112b
permissions -rw-r--r--
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
     4 *)
     5 
     6 theory Auto_Prog imports Prog_Tac Tactical begin
     7 
     8 text \<open>Abstract:
     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.
    13 \<close>
    14 
    15 subsection \<open>consts for programs automatically built from rules\<close>
    16 
    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"
    21 
    22 
    23 subsection \<open>TODO: code for above\<close>
    24 ML \<open>
    25 \<close> ML \<open>
    26 signature AUTO_GERNERATE_PROGRAM =
    27   sig
    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. --------- *)
    39   (* NONE *)
    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 ----------------------------------------------------------/*)
    49   end
    50 (**)
    51 structure Auto_Prog(**): AUTO_GERNERATE_PROGRAM(**) =
    52 struct
    53 (**)
    54 
    55 (** build up a program from rules **)
    56 
    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''])"
    61 val pbl_t $ _ = 
    62   (Thm.term_of o the o (TermC.parse @{theory Prog_Tac})) "Problem (''Isac_Knowledge'',[''equation'',''univar''])"
    63 
    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));
    70 
    71 (* fetch tactics from a program omitting tacticals like While, Repeat,.. *)
    72 fun stacpbls (_ $ body) =
    73     let
    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 ^ "'")
    90 
    91 (* get operators out of a program *)
    92 fun is_calc (Const ("Prog_Tac.Calculate",_) $ _) = true
    93   | is_calc (Const ("Prog_Tac.Calculate",_) $ _ $ _) = true
    94   | is_calc _ = false;
    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 =
    99     sc
   100     |> stacpbls
   101     |> filter is_calc
   102     |> map op_of_calc
   103     |> (assoc_calc' thy |> map);
   104 
   105 (** build up a program from rules **)
   106 
   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";
   132 
   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 ^ "\"");
   147 
   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
   151   | op #>@ t ts =
   152     raise ERROR ("fun #>@ not applicable to \"" ^ UnparseC.term t ^ "\" \"" ^ UnparseC.terms ts  ^ "\"");
   153 fun #> [stac] = stac
   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 ^ "\"")
   158 
   159 val contains_bdv = (not o null o (filter TermC.is_bdv) o TermC.ids2str o #prop o Thm.rep_thm);
   160 
   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
   165     then contain_bdv rs
   166     else true
   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 ^ ",...]");
   173 
   174 (* filter Frees for free_str and pair their respective types with typ *)
   175 fun subst_typ free_str typ frees =
   176   let
   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
   179   in
   180     map (fn T => (T, typ)) typs_v
   181   end
   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 =
   184   let
   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
   188   in
   189     if length args <= 1
   190     then
   191       prog'
   192     else (* auto_generated_inst has second argument "v" *)
   193       subst_atomic_types (subst_typ "v" typ_bdv frees) prog'
   194   end
   195 
   196 fun rules2scr_Rls thy rules =
   197     if contain_bdv 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 =
   201     if contain_bdv 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);
   204 
   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
   210 *)
   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, ...}) = 
   213       let
   214         val sc = (rules2scr_Rls thy rules)
   215       in
   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, ...}) = 
   221       let
   222         val sc = (rules2scr_Seq thy rules)
   223       in
   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 ^ "\"");
   230 
   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.
   234 *)
   235 fun gen thy t rls =
   236   let
   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 ^ "\"")
   241   in
   242     subst_typs prog (type_of t) (TermC.guess_bdv_typ t)
   243   end
   244 
   245 (**)end(**)
   246 \<close> ML \<open>
   247 \<close> ML \<open>
   248 \<close> 
   249 end