src/HOL/Eisbach/eisbach_rule_insts.ML
changeset 60285 b4f1a0a701ae
parent 60248 f7e4294216d2
child 60379 51d9dcd71ad7
equal deleted inserted replaced
60284:014b86186c49 60285:b4f1a0a701ae
    70     COMP_INCR asm_rl)
    70     COMP_INCR asm_rl)
    71     |> Thm.adjust_maxidx_thm ~1
    71     |> Thm.adjust_maxidx_thm ~1
    72     |> restore_tags thm
    72     |> restore_tags thm
    73   end;
    73   end;
    74 
    74 
       
    75 (* FIXME unused *)
       
    76 fun read_instantiate_no_thm ctxt insts fixes =
       
    77   let
       
    78     val (type_insts, term_insts) =
       
    79       List.partition (fn (((x, _) : indexname), _) => String.isPrefix "'" x) insts;
       
    80 
       
    81     val ctxt1 =
       
    82       ctxt
       
    83       |> Context_Position.not_really
       
    84       |> Proof_Context.read_vars fixes |-> Proof_Context.add_fixes |> #2;
       
    85 
       
    86     val typs =
       
    87       map snd type_insts
       
    88       |> Syntax.read_typs ctxt1
       
    89       |> Syntax.check_typs ctxt1;
       
    90 
       
    91     val typ_insts' = map2 (fn (xi, _) => fn T => (xi,T)) type_insts typs;
       
    92 
       
    93     val terms =
       
    94       map snd term_insts
       
    95       |> Syntax.read_terms ctxt1
       
    96       |> Syntax.check_terms ctxt1;
       
    97 
       
    98     val term_insts' = map2 (fn (xi, _) => fn t => (xi, t)) term_insts terms;
       
    99 
       
   100   in (typ_insts',term_insts') end;
       
   101 
    75 
   102 
    76 datatype rule_inst =
   103 datatype rule_inst =
    77   Named_Insts of ((indexname * string) * (term -> unit)) list
   104   Named_Insts of ((indexname * string) * (term -> unit)) list * (binding * string option * mixfix) list
    78 | Term_Insts of (indexname * term) list;
   105 (*| Unchecked_Of_Insts of (string option list * string option list) * (binding * string option * mixfix) list*)
       
   106 | Term_Insts of (indexname * term) list
       
   107 | Unchecked_Term_Insts of term option list * term option list;
       
   108 
       
   109 fun mk_pair (t, t') = Logic.mk_conjunction (Logic.mk_term t, Logic.mk_term t');
       
   110 
       
   111 fun dest_pair t = apply2 Logic.dest_term (Logic.dest_conjunction t);
    79 
   112 
    80 fun embed_indexname ((xi, s), f) =
   113 fun embed_indexname ((xi, s), f) =
    81   let
   114   let fun wrap_xi xi t = mk_pair (Var (xi, fastype_of t), t);
    82     fun wrap_xi xi t =
       
    83       Logic.mk_conjunction (Logic.mk_term (Var (xi, fastype_of t)), Logic.mk_term t);
       
    84   in ((xi, s), f o wrap_xi xi) end;
   115   in ((xi, s), f o wrap_xi xi) end;
    85 
   116 
    86 fun unembed_indexname t =
   117 fun unembed_indexname t = dest_pair t |> apfst (Term.dest_Var #> fst);
    87   let
   118 
    88     val (t, t') = apply2 Logic.dest_term (Logic.dest_conjunction t);
   119 fun read_where_insts (insts, fixes) =
    89     val (xi, _) = Term.dest_Var t;
   120   let
    90   in (xi, t') end;
       
    91 
       
    92 fun read_where_insts toks =
       
    93   let
       
    94     val parser =
       
    95       Parse.!!!
       
    96         (Parse.and_list1 (Args.var -- (Args.$$$ "=" |-- Parse_Tools.name_term)) -- Parse.for_fixes)
       
    97           --| Scan.ahead Parse.eof;
       
    98     val (insts, fixes) = the (Scan.read Token.stopper parser toks);
       
    99 
       
   100     val insts' =
   121     val insts' =
   101       if forall (fn (_, v) => Parse_Tools.is_real_val v) insts
   122       if forall (fn (_, v) => Parse_Tools.is_real_val v) insts
   102       then Term_Insts (map (fn (_, t) => unembed_indexname (Parse_Tools.the_real_val t)) insts)
   123       then Term_Insts (map (unembed_indexname o Parse_Tools.the_real_val o snd) insts)
   103       else Named_Insts (map (fn (xi, p) => embed_indexname
   124       else
   104             ((xi, Parse_Tools.the_parse_val p), Parse_Tools.the_parse_fun p)) insts);
   125         Named_Insts (map (fn (xi, p) => embed_indexname
   105   in
   126           ((xi, Parse_Tools.the_parse_val p), Parse_Tools.the_parse_fun p)) insts, fixes);
   106     (insts', fixes)
   127   in insts' end;
   107   end;
       
   108 
   128 
   109 fun of_rule thm  (args, concl_args) =
   129 fun of_rule thm  (args, concl_args) =
   110   let
   130   let
   111     fun zip_vars _ [] = []
   131     fun zip_vars _ [] = []
   112       | zip_vars (_ :: xs) (NONE :: rest) = zip_vars xs rest
   132       | zip_vars (_ :: xs) (NONE :: rest) = zip_vars xs rest
   118   in insts end;
   138   in insts end;
   119 
   139 
   120 val inst =  Args.maybe Parse_Tools.name_term;
   140 val inst =  Args.maybe Parse_Tools.name_term;
   121 val concl = Args.$$$ "concl" -- Args.colon;
   141 val concl = Args.$$$ "concl" -- Args.colon;
   122 
   142 
   123 fun read_of_insts toks thm =
   143 fun close_unchecked_insts context ((insts,concl_inst), fixes) =
   124   let
   144   let
   125     val parser =
   145     val ctxt = Context.proof_of context;
   126       Parse.!!!
   146     val ctxt1 = ctxt
   127         ((Scan.repeat (Scan.unless concl inst) -- Scan.optional (concl |-- Scan.repeat inst) [])
   147       |> Proof_Context.read_vars fixes |-> Proof_Context.add_fixes |> #2;
   128           -- Parse.for_fixes) --| Scan.ahead Parse.eof;
   148 
   129     val ((insts, concl_insts), fixes) =
   149     val insts' = insts @ concl_inst;
   130       the (Scan.read Token.stopper parser toks);
   150 
   131 
   151     val term_insts =
   132     val insts' =
   152       map (the_list o (Option.map Parse_Tools.the_parse_val)) insts'
   133       if forall (fn SOME t => Parse_Tools.is_real_val t | NONE => true) (insts @ concl_insts)
   153       |> burrow (Syntax.read_terms ctxt1
   134       then
   154         #> Syntax.check_terms ctxt1
   135         Term_Insts
   155         #> Variable.export_terms ctxt1 ctxt)
   136           (map_filter
   156       |> map (try the_single);
   137             (Option.map (Parse_Tools.the_real_val #> unembed_indexname)) (insts @ concl_insts))
   157 
   138       else
   158     val _ =
       
   159       (insts', term_insts)
       
   160       |> ListPair.app (fn (SOME p, SOME t) => Parse_Tools.the_parse_fun p t | _ => ());
       
   161     val (insts'',concl_insts'') = chop (length insts) term_insts;
       
   162    in Unchecked_Term_Insts (insts'', concl_insts'') end;
       
   163 
       
   164 fun read_of_insts checked context ((insts, concl_insts), fixes) =
       
   165   if forall (fn SOME t => Parse_Tools.is_real_val t | NONE => true) (insts @ concl_insts)
       
   166   then
       
   167     if checked
       
   168     then
       
   169       (fn _ =>
       
   170        Term_Insts
       
   171         (map (unembed_indexname o Parse_Tools.the_real_val) (map_filter I (insts @ concl_insts))))
       
   172     else
       
   173       (fn _ =>
       
   174         Unchecked_Term_Insts
       
   175           (map (Option.map Parse_Tools.the_real_val) insts,
       
   176             map (Option.map Parse_Tools.the_real_val) concl_insts))
       
   177   else
       
   178     if checked
       
   179     then
       
   180       (fn thm =>
   139         Named_Insts
   181         Named_Insts
   140           (apply2
   182           (apply2
   141             (map (Option.map (fn p => (Parse_Tools.the_parse_val p, Parse_Tools.the_parse_fun p))))
   183             (map (Option.map (fn p => (Parse_Tools.the_parse_val p, Parse_Tools.the_parse_fun p))))
   142             (insts, concl_insts)
   184             (insts, concl_insts)
   143           |> of_rule thm |> map ((fn (xi, (nm, tok)) => embed_indexname ((xi, nm), tok))));
   185           |> of_rule thm |> map ((fn (xi, (nm, f)) => embed_indexname ((xi, nm), f))), fixes))
   144   in
   186     else
   145     (insts', fixes)
   187       let val result = close_unchecked_insts context ((insts, concl_insts), fixes);
   146   end;
   188       in fn _ => result end;
   147 
   189 
   148 fun read_instantiate_closed ctxt ((Named_Insts insts), fixes) thm  =
   190 
       
   191 fun read_instantiate_closed ctxt (Named_Insts (insts, fixes)) thm  =
   149       let
   192       let
   150         val insts' = map (fn ((v, t), _) => ((v, Position.none), t)) insts;
   193         val insts' = map (fn ((v, t), _) => ((v, Position.none), t)) insts;
   151 
   194 
   152         val (thm_insts, thm') = add_thm_insts thm
   195         val (thm_insts, thm') = add_thm_insts thm
   153         val (thm'', thm_insts') =
   196         val (thm'', thm_insts') =
   168                   SOME t => f t
   211                   SOME t => f t
   169                 | NONE => error "Lost indexname in instantiated theorem"))) insts;
   212                 | NONE => error "Lost indexname in instantiated theorem"))) insts;
   170       in
   213       in
   171         (thm'' |> restore_tags thm)
   214         (thm'' |> restore_tags thm)
   172       end
   215       end
   173   | read_instantiate_closed _ ((Term_Insts insts), _) thm = instantiate_xis insts thm;
   216   | read_instantiate_closed ctxt (Unchecked_Term_Insts insts) thm =
   174 
   217       let
   175 val parse_all : Token.T list context_parser = Scan.lift (Scan.many Token.not_eof);
   218         val (xis, ts) = ListPair.unzip (of_rule thm insts);
       
   219         val ctxt' = Variable.declare_maxidx (Thm.maxidx_of thm) ctxt;
       
   220         val (ts', ctxt'') = Variable.import_terms false ts ctxt';
       
   221         val ts'' = Variable.export_terms ctxt'' ctxt ts';
       
   222         val insts' = ListPair.zip (xis, ts'');
       
   223       in instantiate_xis insts' thm end
       
   224   | read_instantiate_closed _ (Term_Insts insts) thm = instantiate_xis insts thm;
   176 
   225 
   177 val _ =
   226 val _ =
   178   Theory.setup
   227   Theory.setup
   179     (Attrib.setup @{binding "where"} (parse_all >>
   228     (Attrib.setup @{binding "where"}
   180       (fn toks => Thm.rule_attribute (fn context =>
   229       (Scan.lift
   181         read_instantiate_closed (Context.proof_of context) (read_where_insts toks))))
   230         (Parse.and_list1 (Args.var -- (Args.$$$ "=" |-- Parse_Tools.name_term)) -- Parse.for_fixes)
       
   231         >> (fn args => let val args' = read_where_insts args in Thm.rule_attribute (fn context =>
       
   232             read_instantiate_closed (Context.proof_of context) args') end))
   182       "named instantiation of theorem");
   233       "named instantiation of theorem");
   183 
   234 
   184 val _ =
   235 val _ =
   185   Theory.setup
   236   Theory.setup
   186     (Attrib.setup @{binding "of"} (parse_all >>
   237     (Attrib.setup @{binding "of"}
   187       (fn toks => Thm.rule_attribute (fn context => fn thm =>
   238       (Scan.lift
   188         read_instantiate_closed (Context.proof_of context) (read_of_insts toks thm) thm)))
   239         (Args.mode "unchecked" --
       
   240           (Scan.repeat (Scan.unless concl inst) --
       
   241             Scan.optional (concl |-- Scan.repeat inst) [] --
       
   242             Parse.for_fixes)) -- Scan.state >>
       
   243       (fn ((unchecked, args), context) =>
       
   244         let
       
   245           val read_insts = read_of_insts (not unchecked) context args;
       
   246         in
       
   247           Thm.rule_attribute (fn context => fn thm =>
       
   248             if Method_Closure.is_free_thm thm andalso unchecked
       
   249             then Method_Closure.dummy_free_thm
       
   250             else read_instantiate_closed (Context.proof_of context) (read_insts thm) thm)
       
   251         end))
   189       "positional instantiation of theorem");
   252       "positional instantiation of theorem");
   190 
   253 
   191 end;
   254 end;