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