src/Pure/meta_simplifier.ML
changeset 22902 ac833b4bb7ee
parent 22892 c77a1e1c7323
child 23178 07ba6b58b3d2
equal deleted inserted replaced
22901:481cd919c47f 22902:ac833b4bb7ee
   458 fun decomp_simp thm =
   458 fun decomp_simp thm =
   459   let
   459   let
   460     val {thy, prop, ...} = Thm.rep_thm thm;
   460     val {thy, prop, ...} = Thm.rep_thm thm;
   461     val prems = Logic.strip_imp_prems prop;
   461     val prems = Logic.strip_imp_prems prop;
   462     val concl = Drule.strip_imp_concl (Thm.cprop_of thm);
   462     val concl = Drule.strip_imp_concl (Thm.cprop_of thm);
   463     val (lhs, rhs) = Drule.dest_equals concl handle TERM _ =>
   463     val (lhs, rhs) = Thm.dest_equals concl handle TERM _ =>
   464       raise SIMPLIFIER ("Rewrite rule not a meta-equality", thm);
   464       raise SIMPLIFIER ("Rewrite rule not a meta-equality", thm);
   465     val elhs = Thm.dest_arg (Thm.cprop_of (Thm.eta_conversion lhs));
   465     val elhs = Thm.dest_arg (Thm.cprop_of (Thm.eta_conversion lhs));
   466     val elhs = if term_of elhs aconv term_of lhs then lhs else elhs;  (*share identical copies*)
   466     val elhs = if term_of elhs aconv term_of lhs then lhs else elhs;  (*share identical copies*)
   467     val erhs = Envir.eta_contract (term_of rhs);
   467     val erhs = Envir.eta_contract (term_of rhs);
   468     val perm =
   468     val perm =
   576   end;
   576   end;
   577 
   577 
   578 fun add_cong (ss, thm) = ss |>
   578 fun add_cong (ss, thm) = ss |>
   579   map_simpset2 (fn (congs, procs, mk_rews, termless, subgoal_tac, loop_tacs, solvers) =>
   579   map_simpset2 (fn (congs, procs, mk_rews, termless, subgoal_tac, loop_tacs, solvers) =>
   580     let
   580     let
   581       val (lhs, _) = Drule.dest_equals (Drule.strip_imp_concl (Thm.cprop_of thm))
   581       val (lhs, _) = Thm.dest_equals (Drule.strip_imp_concl (Thm.cprop_of thm))
   582         handle TERM _ => raise SIMPLIFIER ("Congruence not a meta-equality", thm);
   582         handle TERM _ => raise SIMPLIFIER ("Congruence not a meta-equality", thm);
   583     (*val lhs = Envir.eta_contract lhs;*)
   583     (*val lhs = Envir.eta_contract lhs;*)
   584       val a = the (cong_name (head_of (term_of lhs))) handle Option.Option =>
   584       val a = the (cong_name (head_of (term_of lhs))) handle Option.Option =>
   585         raise SIMPLIFIER ("Congruence must start with a constant or free variable", thm);
   585         raise SIMPLIFIER ("Congruence must start with a constant or free variable", thm);
   586       val (xs, weak) = congs;
   586       val (xs, weak) = congs;
   826 *)
   826 *)
   827 
   827 
   828 fun check_conv msg ss thm thm' =
   828 fun check_conv msg ss thm thm' =
   829   let
   829   let
   830     val thm'' = transitive thm (transitive
   830     val thm'' = transitive thm (transitive
   831       (symmetric (Drule.beta_eta_conversion (Drule.lhs_of thm'))) thm')
   831       (symmetric (Drule.beta_eta_conversion (Thm.lhs_of thm'))) thm')
   832   in if msg then trace_thm (fn () => "SUCCEEDED") ss thm' else (); SOME thm'' end
   832   in if msg then trace_thm (fn () => "SUCCEEDED") ss thm' else (); SOME thm'' end
   833   handle THM _ =>
   833   handle THM _ =>
   834     let val {thy, prop = _ $ _ $ prop0, ...} = Thm.rep_thm thm in
   834     let val {thy, prop = _ $ _ $ prop0, ...} = Thm.rep_thm thm in
   835       trace_thm (fn () => "Proved wrong thm (Check subgoaler?)") ss thm';
   835       trace_thm (fn () => "Proved wrong thm (Check subgoaler?)") ss thm';
   836       trace_term false (fn () => "Should have proved:") ss thy prop0;
   836       trace_term false (fn () => "Should have proved:") ss thy prop0;
   888 
   888 
   889 fun rewritec (prover, thyt, maxt) ss t =
   889 fun rewritec (prover, thyt, maxt) ss t =
   890   let
   890   let
   891     val Simpset ({rules, ...}, {congs, procs, termless, ...}) = ss;
   891     val Simpset ({rules, ...}, {congs, procs, termless, ...}) = ss;
   892     val eta_thm = Thm.eta_conversion t;
   892     val eta_thm = Thm.eta_conversion t;
   893     val eta_t' = Drule.rhs_of eta_thm;
   893     val eta_t' = Thm.rhs_of eta_thm;
   894     val eta_t = term_of eta_t';
   894     val eta_t = term_of eta_t';
   895     fun rew {thm, name, lhs, elhs, extra, fo, perm} =
   895     fun rew {thm, name, lhs, elhs, extra, fo, perm} =
   896       let
   896       let
   897         val {thy, prop, maxidx, ...} = rep_thm thm;
   897         val {thy, prop, maxidx, ...} = rep_thm thm;
   898         val (rthm, elhs') =
   898         val (rthm, elhs') =
   899           if maxt = ~1 orelse not extra then (thm, elhs)
   899           if maxt = ~1 orelse not extra then (thm, elhs)
   900           else (Thm.incr_indexes (maxt+1) thm, Thm.cterm_incr_indexes (maxt+1) elhs);
   900           else (Thm.incr_indexes (maxt + 1) thm, Thm.incr_indexes_cterm (maxt + 1) elhs);
   901         val insts = if fo then Thm.cterm_first_order_match (elhs', eta_t')
   901         val insts =
   902                           else Thm.cterm_match (elhs', eta_t');
   902           if fo then Thm.first_order_match (elhs', eta_t')
       
   903           else Thm.match (elhs', eta_t');
   903         val thm' = Thm.instantiate insts (Thm.rename_boundvars lhs eta_t rthm);
   904         val thm' = Thm.instantiate insts (Thm.rename_boundvars lhs eta_t rthm);
   904         val prop' = Thm.prop_of thm';
   905         val prop' = Thm.prop_of thm';
   905         val unconditional = (Logic.count_prems prop' = 0);
   906         val unconditional = (Logic.count_prems prop' = 0);
   906         val (lhs', rhs') = Logic.dest_equals (Logic.strip_imp_concl prop')
   907         val (lhs', rhs') = Logic.dest_equals (Logic.strip_imp_concl prop')
   907       in
   908       in
   972 
   973 
   973 
   974 
   974 (* conversion to apply a congruence rule to a term *)
   975 (* conversion to apply a congruence rule to a term *)
   975 
   976 
   976 fun congc prover ss maxt {thm=cong,lhs=lhs} t =
   977 fun congc prover ss maxt {thm=cong,lhs=lhs} t =
   977   let val rthm = Thm.incr_indexes (maxt+1) cong;
   978   let val rthm = Thm.incr_indexes (maxt + 1) cong;
   978       val rlhs = fst (Drule.dest_equals (Drule.strip_imp_concl (cprop_of rthm)));
   979       val rlhs = fst (Thm.dest_equals (Drule.strip_imp_concl (cprop_of rthm)));
   979       val insts = Thm.cterm_match (rlhs, t)
   980       val insts = Thm.match (rlhs, t)
   980       (* Pattern.match can raise Pattern.MATCH;
   981       (* Thm.match can raise Pattern.MATCH;
   981          is handled when congc is called *)
   982          is handled when congc is called *)
   982       val thm' = Thm.instantiate insts (Thm.rename_boundvars (term_of rlhs) (term_of t) rthm);
   983       val thm' = Thm.instantiate insts (Thm.rename_boundvars (term_of rlhs) (term_of t) rthm);
   983       val unit = trace_thm (fn () => "Applying congruence rule:") ss thm';
   984       val unit = trace_thm (fn () => "Applying congruence rule:") ss thm';
   984       fun err (msg, thm) = (trace_thm (fn () => msg) ss thm; NONE)
   985       fun err (msg, thm) = (trace_thm (fn () => msg) ss thm; NONE)
   985   in case prover thm' of
   986   in case prover thm' of
   986        NONE => err ("Congruence proof failed.  Could not prove", thm')
   987        NONE => err ("Congruence proof failed.  Could not prove", thm')
   987      | SOME thm2 => (case check_conv true ss (Drule.beta_eta_conversion t) thm2 of
   988      | SOME thm2 => (case check_conv true ss (Drule.beta_eta_conversion t) thm2 of
   988           NONE => err ("Congruence proof failed.  Should not have proved", thm2)
   989           NONE => err ("Congruence proof failed.  Should not have proved", thm2)
   989         | SOME thm2' =>
   990         | SOME thm2' =>
   990             if op aconv (pairself term_of (dest_equals (cprop_of thm2')))
   991             if op aconv (pairself term_of (Thm.dest_equals (cprop_of thm2')))
   991             then NONE else SOME thm2')
   992             then NONE else SOME thm2')
   992   end;
   993   end;
   993 
   994 
   994 val (cA, (cB, cC)) =
   995 val (cA, (cB, cC)) =
   995   apsnd dest_equals (dest_implies (hd (cprems_of Drule.imp_cong)));
   996   apsnd Thm.dest_equals (Thm.dest_implies (hd (cprems_of Drule.imp_cong)));
   996 
   997 
   997 fun transitive1 NONE NONE = NONE
   998 fun transitive1 NONE NONE = NONE
   998   | transitive1 (SOME thm1) NONE = SOME thm1
   999   | transitive1 (SOME thm1) NONE = SOME thm1
   999   | transitive1 NONE (SOME thm2) = SOME thm2
  1000   | transitive1 NONE (SOME thm2) = SOME thm2
  1000   | transitive1 (SOME thm1) (SOME thm2) = SOME (transitive thm1 thm2)
  1001   | transitive1 (SOME thm1) (SOME thm2) = SOME (transitive thm1 thm2)
  1007     fun botc skel ss t =
  1008     fun botc skel ss t =
  1008           if is_Var skel then NONE
  1009           if is_Var skel then NONE
  1009           else
  1010           else
  1010           (case subc skel ss t of
  1011           (case subc skel ss t of
  1011              some as SOME thm1 =>
  1012              some as SOME thm1 =>
  1012                (case rewritec (prover, thy, maxidx) ss (Drule.rhs_of thm1) of
  1013                (case rewritec (prover, thy, maxidx) ss (Thm.rhs_of thm1) of
  1013                   SOME (thm2, skel2) =>
  1014                   SOME (thm2, skel2) =>
  1014                     transitive2 (transitive thm1 thm2)
  1015                     transitive2 (transitive thm1 thm2)
  1015                       (botc skel2 ss (Drule.rhs_of thm2))
  1016                       (botc skel2 ss (Thm.rhs_of thm2))
  1016                 | NONE => some)
  1017                 | NONE => some)
  1017            | NONE =>
  1018            | NONE =>
  1018                (case rewritec (prover, thy, maxidx) ss t of
  1019                (case rewritec (prover, thy, maxidx) ss t of
  1019                   SOME (thm2, skel2) => transitive2 thm2
  1020                   SOME (thm2, skel2) => transitive2 thm2
  1020                     (botc skel2 ss (Drule.rhs_of thm2))
  1021                     (botc skel2 ss (Thm.rhs_of thm2))
  1021                 | NONE => NONE))
  1022                 | NONE => NONE))
  1022 
  1023 
  1023     and try_botc ss t =
  1024     and try_botc ss t =
  1024           (case botc skel0 ss t of
  1025           (case botc skel0 ss t of
  1025              SOME trec1 => trec1 | NONE => (reflexive t))
  1026              SOME trec1 => trec1 | NONE => (reflexive t))
  1043              end
  1044              end
  1044          | t $ _ => (case t of
  1045          | t $ _ => (case t of
  1045              Const ("==>", _) $ _  => impc t0 ss
  1046              Const ("==>", _) $ _  => impc t0 ss
  1046            | Abs _ =>
  1047            | Abs _ =>
  1047                let val thm = beta_conversion false t0
  1048                let val thm = beta_conversion false t0
  1048                in case subc skel0 ss (Drule.rhs_of thm) of
  1049                in case subc skel0 ss (Thm.rhs_of thm) of
  1049                     NONE => SOME thm
  1050                     NONE => SOME thm
  1050                   | SOME thm' => SOME (transitive thm thm')
  1051                   | SOME thm' => SOME (transitive thm thm')
  1051                end
  1052                end
  1052            | _  =>
  1053            | _  =>
  1053                let fun appc () =
  1054                let fun appc () =
  1075                        | SOME cong =>
  1076                        | SOME cong =>
  1076   (*post processing: some partial applications h t1 ... tj, j <= length ts,
  1077   (*post processing: some partial applications h t1 ... tj, j <= length ts,
  1077     may be a redex. Example: map (%x. x) = (%xs. xs) wrt map_cong*)
  1078     may be a redex. Example: map (%x. x) = (%xs. xs) wrt map_cong*)
  1078                           (let
  1079                           (let
  1079                              val thm = congc (prover ss) ss maxidx cong t0;
  1080                              val thm = congc (prover ss) ss maxidx cong t0;
  1080                              val t = the_default t0 (Option.map Drule.rhs_of thm);
  1081                              val t = the_default t0 (Option.map Thm.rhs_of thm);
  1081                              val (cl, cr) = Thm.dest_comb t
  1082                              val (cl, cr) = Thm.dest_comb t
  1082                              val dVar = Var(("", 0), dummyT)
  1083                              val dVar = Var(("", 0), dummyT)
  1083                              val skel =
  1084                              val skel =
  1084                                list_comb (h, replicate (length ts) dVar)
  1085                                list_comb (h, replicate (length ts) dVar)
  1085                            in case botc skel ss cl of
  1086                            in case botc skel ss cl of
  1106     and add_rrules (rrss, asms) ss =
  1107     and add_rrules (rrss, asms) ss =
  1107       (fold o fold) insert_rrule rrss ss |> add_prems (map_filter I asms)
  1108       (fold o fold) insert_rrule rrss ss |> add_prems (map_filter I asms)
  1108 
  1109 
  1109     and disch r (prem, eq) =
  1110     and disch r (prem, eq) =
  1110       let
  1111       let
  1111         val (lhs, rhs) = Drule.dest_equals (Thm.cprop_of eq);
  1112         val (lhs, rhs) = Thm.dest_equals (Thm.cprop_of eq);
  1112         val eq' = implies_elim (Thm.instantiate
  1113         val eq' = implies_elim (Thm.instantiate
  1113           ([], [(cA, prem), (cB, lhs), (cC, rhs)]) Drule.imp_cong)
  1114           ([], [(cA, prem), (cB, lhs), (cC, rhs)]) Drule.imp_cong)
  1114           (implies_intr prem eq)
  1115           (implies_intr prem eq)
  1115       in if not r then eq' else
  1116       in if not r then eq' else
  1116         let
  1117         let
  1117           val (prem', concl) = dest_implies lhs;
  1118           val (prem', concl) = Thm.dest_implies lhs;
  1118           val (prem'', _) = dest_implies rhs
  1119           val (prem'', _) = Thm.dest_implies rhs
  1119         in transitive (transitive
  1120         in transitive (transitive
  1120           (Thm.instantiate ([], [(cA, prem'), (cB, prem), (cC, concl)])
  1121           (Thm.instantiate ([], [(cA, prem'), (cB, prem), (cC, concl)])
  1121              Drule.swap_prems_eq) eq')
  1122              Drule.swap_prems_eq) eq')
  1122           (Thm.instantiate ([], [(cA, prem), (cB, prem''), (cC, concl)])
  1123           (Thm.instantiate ([], [(cA, prem), (cB, prem''), (cC, concl)])
  1123              Drule.swap_prems_eq)
  1124              Drule.swap_prems_eq)
  1127     and rebuild [] _ _ _ _ eq = eq
  1128     and rebuild [] _ _ _ _ eq = eq
  1128       | rebuild (prem :: prems) concl (rrs :: rrss) (asm :: asms) ss eq =
  1129       | rebuild (prem :: prems) concl (rrs :: rrss) (asm :: asms) ss eq =
  1129           let
  1130           let
  1130             val ss' = add_rrules (rev rrss, rev asms) ss;
  1131             val ss' = add_rrules (rev rrss, rev asms) ss;
  1131             val concl' =
  1132             val concl' =
  1132               Drule.mk_implies (prem, the_default concl (Option.map Drule.rhs_of eq));
  1133               Drule.mk_implies (prem, the_default concl (Option.map Thm.rhs_of eq));
  1133             val dprem = Option.map (curry (disch false) prem)
  1134             val dprem = Option.map (curry (disch false) prem)
  1134           in case rewritec (prover, thy, maxidx) ss' concl' of
  1135           in case rewritec (prover, thy, maxidx) ss' concl' of
  1135               NONE => rebuild prems concl' rrss asms ss (dprem eq)
  1136               NONE => rebuild prems concl' rrss asms ss (dprem eq)
  1136             | SOME (eq', _) => transitive2 (Library.foldl (disch false o swap)
  1137             | SOME (eq', _) => transitive2 (Library.foldl (disch false o swap)
  1137                   (the (transitive3 (dprem eq) eq'), prems))
  1138                   (the (transitive3 (dprem eq) eq'), prems))
  1138                 (mut_impc0 (rev prems) (Drule.rhs_of eq') (rev rrss) (rev asms) ss)
  1139                 (mut_impc0 (rev prems) (Thm.rhs_of eq') (rev rrss) (rev asms) ss)
  1139           end
  1140           end
  1140 
  1141 
  1141     and mut_impc0 prems concl rrss asms ss =
  1142     and mut_impc0 prems concl rrss asms ss =
  1142       let
  1143       let
  1143         val prems' = strip_imp_prems concl;
  1144         val prems' = strip_imp_prems concl;
  1162             NONE => mut_impc prems concl rrss asms (prem :: prems')
  1163             NONE => mut_impc prems concl rrss asms (prem :: prems')
  1163               (rrs :: rrss') (asm :: asms') (NONE :: eqns) ss changed
  1164               (rrs :: rrss') (asm :: asms') (NONE :: eqns) ss changed
  1164               (if k = 0 then 0 else k - 1)
  1165               (if k = 0 then 0 else k - 1)
  1165           | SOME eqn =>
  1166           | SOME eqn =>
  1166             let
  1167             let
  1167               val prem' = Drule.rhs_of eqn;
  1168               val prem' = Thm.rhs_of eqn;
  1168               val tprems = map term_of prems;
  1169               val tprems = map term_of prems;
  1169               val i = 1 + Library.foldl Int.max (~1, map (fn p =>
  1170               val i = 1 + Library.foldl Int.max (~1, map (fn p =>
  1170                 find_index (fn q => q aconv p) tprems) (#hyps (rep_thm eqn)));
  1171                 find_index (fn q => q aconv p) tprems) (#hyps (rep_thm eqn)));
  1171               val (rrs', asm') = rules_of_prem ss prem'
  1172               val (rrs', asm') = rules_of_prem ss prem'
  1172             in mut_impc prems concl rrss asms (prem' :: prems')
  1173             in mut_impc prems concl rrss asms (prem' :: prems')
  1176                   ss (length prems') ~1
  1177                   ss (length prems') ~1
  1177             end
  1178             end
  1178 
  1179 
  1179      (*legacy code - only for backwards compatibility*)
  1180      (*legacy code - only for backwards compatibility*)
  1180      and nonmut_impc ct ss =
  1181      and nonmut_impc ct ss =
  1181        let val (prem, conc) = dest_implies ct;
  1182        let val (prem, conc) = Thm.dest_implies ct;
  1182            val thm1 = if simprem then botc skel0 ss prem else NONE;
  1183            val thm1 = if simprem then botc skel0 ss prem else NONE;
  1183            val prem1 = the_default prem (Option.map Drule.rhs_of thm1);
  1184            val prem1 = the_default prem (Option.map Thm.rhs_of thm1);
  1184            val ss1 = if not useprem then ss else add_rrules
  1185            val ss1 = if not useprem then ss else add_rrules
  1185              (apsnd single (apfst single (rules_of_prem ss prem1))) ss
  1186              (apsnd single (apfst single (rules_of_prem ss prem1))) ss
  1186        in (case botc skel0 ss1 conc of
  1187        in (case botc skel0 ss1 conc of
  1187            NONE => (case thm1 of
  1188            NONE => (case thm1 of
  1188                NONE => NONE
  1189                NONE => NONE
  1251         (theory_context (Thm.theory_of_cterm ct) empty_ss addsimps thms) ct;
  1252         (theory_context (Thm.theory_of_cterm ct) empty_ss addsimps thms) ct;
  1252 
  1253 
  1253 (*Rewrite a theorem*)
  1254 (*Rewrite a theorem*)
  1254 fun simplify _ [] th = th
  1255 fun simplify _ [] th = th
  1255   | simplify full thms th =
  1256   | simplify full thms th =
  1256       Drule.fconv_rule (rewrite_cterm (full, false, false) simple_prover
  1257       Conv.fconv_rule (rewrite_cterm (full, false, false) simple_prover
  1257         (theory_context (Thm.theory_of_thm th) empty_ss addsimps thms)) th;
  1258         (theory_context (Thm.theory_of_thm th) empty_ss addsimps thms)) th;
  1258 
  1259 
  1259 val rewrite_rule = simplify true;
  1260 val rewrite_rule = simplify true;
  1260 
  1261 
  1261 (*simple term rewriting -- no proof*)
  1262 (*simple term rewriting -- no proof*)
  1262 fun rewrite_term thy rules procs =
  1263 fun rewrite_term thy rules procs =
  1263   Pattern.rewrite_term thy (map decomp_simp' rules) procs;
  1264   Pattern.rewrite_term thy (map decomp_simp' rules) procs;
  1264 
  1265 
  1265 fun rewrite_thm mode prover ss = Drule.fconv_rule (rewrite_cterm mode prover ss);
  1266 fun rewrite_thm mode prover ss = Conv.fconv_rule (rewrite_cterm mode prover ss);
  1266 
  1267 
  1267 (*Rewrite the subgoals of a proof state (represented by a theorem) *)
  1268 (*Rewrite the subgoals of a proof state (represented by a theorem) *)
  1268 fun rewrite_goals_rule thms th =
  1269 fun rewrite_goals_rule thms th =
  1269   Drule.fconv_rule (Drule.goals_conv (K true) (rewrite_cterm (true, true, true) simple_prover
  1270   Conv.fconv_rule (Conv.goals_conv (K true) (rewrite_cterm (true, true, true) simple_prover
  1270     (theory_context (Thm.theory_of_thm th) empty_ss addsimps thms))) th;
  1271     (theory_context (Thm.theory_of_thm th) empty_ss addsimps thms))) th;
  1271 
  1272 
  1272 (*Rewrite the subgoal of a proof state (represented by a theorem)*)
  1273 (*Rewrite the subgoal of a proof state (represented by a theorem)*)
  1273 fun rewrite_goal_rule mode prover ss i thm =
  1274 fun rewrite_goal_rule mode prover ss i thm =
  1274   if 0 < i  andalso  i <= nprems_of thm
  1275   if 0 < i  andalso  i <= nprems_of thm
  1275   then Drule.fconv_rule (Drule.goals_conv (fn j => j=i) (rewrite_cterm mode prover ss)) thm
  1276   then Conv.fconv_rule (Conv.goals_conv (fn j => j=i) (rewrite_cterm mode prover ss)) thm
  1276   else raise THM("rewrite_goal_rule", i, [thm]);
  1277   else raise THM("rewrite_goal_rule", i, [thm]);
  1277 
  1278 
  1278 
  1279 
  1279 (** meta-rewriting tactics **)
  1280 (** meta-rewriting tactics **)
  1280 
  1281 
  1318 
  1319 
  1319 local
  1320 local
  1320 
  1321 
  1321 fun gen_norm_hhf ss th =
  1322 fun gen_norm_hhf ss th =
  1322   (if Drule.is_norm_hhf (Thm.prop_of th) then th
  1323   (if Drule.is_norm_hhf (Thm.prop_of th) then th
  1323    else Drule.fconv_rule (rewrite_cterm (true, false, false) (K (K NONE)) ss) th)
  1324    else Conv.fconv_rule (rewrite_cterm (true, false, false) (K (K NONE)) ss) th)
  1324   |> Thm.adjust_maxidx_thm ~1
  1325   |> Thm.adjust_maxidx_thm ~1
  1325   |> Drule.gen_all;
  1326   |> Drule.gen_all;
  1326 
  1327 
  1327 val ss = theory_context ProtoPure.thy empty_ss addsimps [Drule.norm_hhf_eq];
  1328 val ss = theory_context ProtoPure.thy empty_ss addsimps [Drule.norm_hhf_eq];
  1328 
  1329