src/HOL/Eisbach/method_closure.ML
author wenzelm
Tue, 07 Jun 2016 21:13:08 +0200
changeset 63255 3f594efa9504
parent 63186 dc221b8945f2
child 63527 59eff6e56d81
permissions -rw-r--r--
clarified signature;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
60248
f7e4294216d2 updated Eisbach, using version fb741500f533 of its Bitbucket repository;
wenzelm
parents: 60209
diff changeset
     1
(*  Title:      HOL/Eisbach/method_closure.ML
60119
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
     2
    Author:     Daniel Matichuk, NICTA/UNSW
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
     3
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
     4
Facilities for treating method syntax as a closure, with abstraction
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
     5
over terms, facts and other methods.
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
     6
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
     7
The 'method' command allows to define new proof methods by combining
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
     8
existing ones with their usual syntax.
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
     9
*)
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
    10
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
    11
signature METHOD_CLOSURE =
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
    12
sig
61818
6de8e7ad95c3 more direct use of Token.src as token list;
wenzelm
parents: 61816
diff changeset
    13
  val read: Proof.context -> Token.src -> Method.text
6de8e7ad95c3 more direct use of Token.src as token list;
wenzelm
parents: 61816
diff changeset
    14
  val read_closure: Proof.context -> Token.src -> Method.text * Token.src
6de8e7ad95c3 more direct use of Token.src as token list;
wenzelm
parents: 61816
diff changeset
    15
  val read_closure_input: Proof.context -> Input.source -> Method.text * Token.src
6de8e7ad95c3 more direct use of Token.src as token list;
wenzelm
parents: 61816
diff changeset
    16
  val method_text: Method.text context_parser
60119
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
    17
  val method_evaluate: Method.text -> Proof.context -> Method.method
62070
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
    18
  val apply_method: Proof.context -> string -> term list -> thm list list ->
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
    19
    (Proof.context -> Method.method) list -> Proof.context -> thm list -> context_tactic
61910
ae36547d3a30 tuned signature;
wenzelm
parents: 61903
diff changeset
    20
  val method: binding -> (binding * typ option * mixfix) list -> binding list ->
ae36547d3a30 tuned signature;
wenzelm
parents: 61903
diff changeset
    21
    binding list -> binding list -> Token.src -> local_theory -> string * local_theory
ae36547d3a30 tuned signature;
wenzelm
parents: 61903
diff changeset
    22
  val method_cmd: binding -> (binding * string option * mixfix) list -> binding list ->
ae36547d3a30 tuned signature;
wenzelm
parents: 61903
diff changeset
    23
    binding list -> binding list -> Token.src -> local_theory -> string * local_theory
60119
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
    24
end;
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
    25
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
    26
structure Method_Closure: METHOD_CLOSURE =
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
    27
struct
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
    28
62070
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
    29
(* auxiliary data for method definition *)
60119
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
    30
62070
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
    31
structure Method_Definition = Proof_Data
60119
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
    32
(
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
    33
  type T =
60287
adde5ce1e0a7 updated Eisbach, using version 134bc592909c of its Bitbucket repository;
wenzelm
parents: 60285
diff changeset
    34
    (Proof.context -> Method.method) Symtab.table *  (*dynamic methods*)
63186
dc221b8945f2 allow multiple recursive methods to co-exist in order to support mutual recursion;
matichuk <daniel.matichuk@nicta.com.au>
parents: 63185
diff changeset
    35
    (term list -> Proof.context -> Method.method) Symtab.table  (*recursive methods*);
dc221b8945f2 allow multiple recursive methods to co-exist in order to support mutual recursion;
matichuk <daniel.matichuk@nicta.com.au>
parents: 63185
diff changeset
    36
  fun init _ : T = (Symtab.empty, Symtab.empty);
60119
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
    37
);
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
    38
60287
adde5ce1e0a7 updated Eisbach, using version 134bc592909c of its Bitbucket repository;
wenzelm
parents: 60285
diff changeset
    39
fun lookup_dynamic_method ctxt full_name =
62070
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
    40
  (case Symtab.lookup (#1 (Method_Definition.get ctxt)) full_name of
62074
wenzelm
parents: 62073
diff changeset
    41
    SOME m => m ctxt
60119
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
    42
  | NONE => error ("Illegal use of internal Eisbach method: " ^ quote full_name));
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
    43
62070
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
    44
val update_dynamic_method = Method_Definition.map o apfst o Symtab.update;
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
    45
63186
dc221b8945f2 allow multiple recursive methods to co-exist in order to support mutual recursion;
matichuk <daniel.matichuk@nicta.com.au>
parents: 63185
diff changeset
    46
fun get_recursive_method full_name ts ctxt =
dc221b8945f2 allow multiple recursive methods to co-exist in order to support mutual recursion;
matichuk <daniel.matichuk@nicta.com.au>
parents: 63185
diff changeset
    47
  (case Symtab.lookup (#2 (Method_Definition.get ctxt)) full_name of
dc221b8945f2 allow multiple recursive methods to co-exist in order to support mutual recursion;
matichuk <daniel.matichuk@nicta.com.au>
parents: 63185
diff changeset
    48
    SOME m => m ts ctxt
dc221b8945f2 allow multiple recursive methods to co-exist in order to support mutual recursion;
matichuk <daniel.matichuk@nicta.com.au>
parents: 63185
diff changeset
    49
  | NONE => error ("Illegal use of internal Eisbach method: " ^ quote full_name));
dc221b8945f2 allow multiple recursive methods to co-exist in order to support mutual recursion;
matichuk <daniel.matichuk@nicta.com.au>
parents: 63185
diff changeset
    50
dc221b8945f2 allow multiple recursive methods to co-exist in order to support mutual recursion;
matichuk <daniel.matichuk@nicta.com.au>
parents: 63185
diff changeset
    51
val put_recursive_method = Method_Definition.map o apsnd o Symtab.update;
62070
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
    52
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
    53
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
    54
(* stored method closures *)
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
    55
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
    56
type closure = {vars: term list, named_thms: string list, methods: string list, body: Method.text};
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
    57
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
    58
structure Data = Generic_Data
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
    59
(
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
    60
  type T = closure Symtab.table;
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
    61
  val empty: T = Symtab.empty;
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
    62
  val extend = I;
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
    63
  fun merge data : T = Symtab.merge (K true) data;
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
    64
);
60119
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
    65
62070
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
    66
fun get_closure ctxt name =
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
    67
  (case Symtab.lookup (Data.get (Context.Proof ctxt)) name of
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
    68
    SOME closure => closure
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
    69
  | NONE => error ("Unknown Eisbach method: " ^ quote name));
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
    70
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
    71
fun put_closure binding (closure: closure) lthy =
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
    72
  let
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
    73
    val name = Local_Theory.full_name lthy binding;
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
    74
  in
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
    75
    lthy |> Local_Theory.declaration {syntax = false, pervasive = true} (fn phi =>
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
    76
      Data.map
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
    77
        (Symtab.update (name,
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
    78
          {vars = map (Morphism.term phi) (#vars closure),
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
    79
           named_thms = #named_thms closure,
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
    80
           methods = #methods closure,
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
    81
           body = (Method.map_source o map) (Token.transform phi) (#body closure)})))
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
    82
  end;
60119
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
    83
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
    84
61818
6de8e7ad95c3 more direct use of Token.src as token list;
wenzelm
parents: 61816
diff changeset
    85
(* read method text *)
60119
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
    86
61818
6de8e7ad95c3 more direct use of Token.src as token list;
wenzelm
parents: 61816
diff changeset
    87
fun read ctxt src =
61917
35ec3757d3c1 check and report source at most once, notably in body of "match" method;
wenzelm
parents: 61912
diff changeset
    88
  (case Scan.read Token.stopper (Parse.!!! (Method.parser 0 --| Scan.ahead Parse.eof)) src of
35ec3757d3c1 check and report source at most once, notably in body of "match" method;
wenzelm
parents: 61912
diff changeset
    89
    SOME (text, range) =>
35ec3757d3c1 check and report source at most once, notably in body of "match" method;
wenzelm
parents: 61912
diff changeset
    90
      if Method.checked_text text then text
35ec3757d3c1 check and report source at most once, notably in body of "match" method;
wenzelm
parents: 61912
diff changeset
    91
      else (Method.report (text, range); Method.check_text ctxt text)
62795
063d2f23cdf6 removed redundant Position.set_range -- already done in Position.range;
wenzelm
parents: 62135
diff changeset
    92
  | NONE => error ("Failed to parse method" ^ Position.here (#1 (Token.range_of src))));
60119
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
    93
61818
6de8e7ad95c3 more direct use of Token.src as token list;
wenzelm
parents: 61816
diff changeset
    94
fun read_closure ctxt src0 =
60119
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
    95
  let
61814
1ca1142e1711 clarified type Token.src: plain token list, with usual implicit value assignment;
wenzelm
parents: 60553
diff changeset
    96
    val src1 = map Token.init_assignable src0;
61818
6de8e7ad95c3 more direct use of Token.src as token list;
wenzelm
parents: 61816
diff changeset
    97
    val text = read ctxt src1 |> Method.map_source (Method.method_closure ctxt);
61814
1ca1142e1711 clarified type Token.src: plain token list, with usual implicit value assignment;
wenzelm
parents: 60553
diff changeset
    98
    val src2 = map Token.closure src1;
61818
6de8e7ad95c3 more direct use of Token.src as token list;
wenzelm
parents: 61816
diff changeset
    99
  in (text, src2) end;
60209
022ca2799c73 updated Eisbach, using version 5df3d8c72403 of its Bitbucket repository;
wenzelm
parents: 60119
diff changeset
   100
61818
6de8e7ad95c3 more direct use of Token.src as token list;
wenzelm
parents: 61816
diff changeset
   101
fun read_closure_input ctxt =
6de8e7ad95c3 more direct use of Token.src as token list;
wenzelm
parents: 61816
diff changeset
   102
  Input.source_explode #>
6de8e7ad95c3 more direct use of Token.src as token list;
wenzelm
parents: 61816
diff changeset
   103
  Token.read_no_commands (Thy_Header.get_keywords' ctxt) (Scan.one Token.not_eof) #>
6de8e7ad95c3 more direct use of Token.src as token list;
wenzelm
parents: 61816
diff changeset
   104
  read_closure ctxt;
60119
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   105
61818
6de8e7ad95c3 more direct use of Token.src as token list;
wenzelm
parents: 61816
diff changeset
   106
val method_text =
61912
ad710de5c576 more standard nesting of sub-language: Parse.text allows atomic entities without quotes;
wenzelm
parents: 61911
diff changeset
   107
  Args.context -- Scan.lift (Parse.token Parse.text) >> (fn (ctxt, tok) =>
60119
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   108
    (case Token.get_value tok of
61818
6de8e7ad95c3 more direct use of Token.src as token list;
wenzelm
parents: 61816
diff changeset
   109
      SOME (Token.Source src) => read ctxt src
6de8e7ad95c3 more direct use of Token.src as token list;
wenzelm
parents: 61816
diff changeset
   110
    | _ =>
60119
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   111
        let
61818
6de8e7ad95c3 more direct use of Token.src as token list;
wenzelm
parents: 61816
diff changeset
   112
          val (text, src) = read_closure_input ctxt (Token.input_of tok);
61814
1ca1142e1711 clarified type Token.src: plain token list, with usual implicit value assignment;
wenzelm
parents: 60553
diff changeset
   113
          val _ = Token.assign (SOME (Token.Source src)) tok;
61818
6de8e7ad95c3 more direct use of Token.src as token list;
wenzelm
parents: 61816
diff changeset
   114
        in text end));
60119
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   115
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   116
61919
b3d68dff610b tuned module arrangement;
wenzelm
parents: 61918
diff changeset
   117
(* evaluate method text *)
60119
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   118
61903
d5ddd4866b7b tuned -- with subtle change of order of evaluation;
wenzelm
parents: 61902
diff changeset
   119
fun method_evaluate text ctxt =
61902
4d162c237e48 more accurate lookup of dynamic facts;
wenzelm
parents: 61901
diff changeset
   120
  let
61903
d5ddd4866b7b tuned -- with subtle change of order of evaluation;
wenzelm
parents: 61902
diff changeset
   121
    val text' =
d5ddd4866b7b tuned -- with subtle change of order of evaluation;
wenzelm
parents: 61902
diff changeset
   122
      text |> (Method.map_source o map o Token.map_facts)
61902
4d162c237e48 more accurate lookup of dynamic facts;
wenzelm
parents: 61901
diff changeset
   123
        (fn SOME name =>
4d162c237e48 more accurate lookup of dynamic facts;
wenzelm
parents: 61901
diff changeset
   124
              (case Proof_Context.lookup_fact ctxt name of
63255
3f594efa9504 clarified signature;
wenzelm
parents: 63186
diff changeset
   125
                SOME {dynamic = true, thms} => K thms
61902
4d162c237e48 more accurate lookup of dynamic facts;
wenzelm
parents: 61901
diff changeset
   126
              | _ => I)
4d162c237e48 more accurate lookup of dynamic facts;
wenzelm
parents: 61901
diff changeset
   127
          | NONE => I);
4d162c237e48 more accurate lookup of dynamic facts;
wenzelm
parents: 61901
diff changeset
   128
    val ctxt' = Config.put Method.closure false ctxt;
61903
d5ddd4866b7b tuned -- with subtle change of order of evaluation;
wenzelm
parents: 61902
diff changeset
   129
  in fn facts => Method.RUNTIME (fn st => Method.evaluate text' ctxt' facts st) end;
60287
adde5ce1e0a7 updated Eisbach, using version 134bc592909c of its Bitbucket repository;
wenzelm
parents: 60285
diff changeset
   130
62070
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
   131
fun method_instantiate vars body ts ctxt =
60119
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   132
  let
62076
1add21f7cabc proper Pattern.match and corresponding Envir.subst_term, instead of Envir.norm_term of unify-family;
wenzelm
parents: 62074
diff changeset
   133
    val thy = Proof_Context.theory_of ctxt;
1add21f7cabc proper Pattern.match and corresponding Envir.subst_term, instead of Envir.norm_term of unify-family;
wenzelm
parents: 62074
diff changeset
   134
    val subst = fold (Pattern.match thy) (vars ~~ ts) (Vartab.empty, Vartab.empty);
1add21f7cabc proper Pattern.match and corresponding Envir.subst_term, instead of Envir.norm_term of unify-family;
wenzelm
parents: 62074
diff changeset
   135
    val morphism = Morphism.term_morphism "method_instantiate" (Envir.subst_term subst);
62070
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
   136
    val body' = (Method.map_source o map) (Token.transform morphism) body;
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
   137
  in method_evaluate body' ctxt end;
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
   138
62074
wenzelm
parents: 62073
diff changeset
   139
wenzelm
parents: 62073
diff changeset
   140
wenzelm
parents: 62073
diff changeset
   141
(** apply method closure **)
62070
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
   142
63186
dc221b8945f2 allow multiple recursive methods to co-exist in order to support mutual recursion;
matichuk <daniel.matichuk@nicta.com.au>
parents: 63185
diff changeset
   143
fun recursive_method full_name vars body ts =
62070
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
   144
  let val m = method_instantiate vars body
63186
dc221b8945f2 allow multiple recursive methods to co-exist in order to support mutual recursion;
matichuk <daniel.matichuk@nicta.com.au>
parents: 63185
diff changeset
   145
  in put_recursive_method (full_name, m) #> m ts end;
62070
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
   146
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
   147
fun apply_method ctxt method_name terms facts methods =
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
   148
  let
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
   149
    fun declare_facts (name :: names) (fact :: facts) =
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
   150
          fold (Context.proof_map o Named_Theorems.add_thm name) fact
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
   151
          #> declare_facts names facts
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
   152
      | declare_facts _ [] = I
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
   153
      | declare_facts [] (_ :: _) = error ("Excessive facts for method " ^ quote method_name);
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
   154
    val {vars, named_thms, methods = method_args, body} = get_closure ctxt method_name;
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
   155
  in
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
   156
    declare_facts named_thms facts
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
   157
    #> fold update_dynamic_method (method_args ~~ methods)
63186
dc221b8945f2 allow multiple recursive methods to co-exist in order to support mutual recursion;
matichuk <daniel.matichuk@nicta.com.au>
parents: 63185
diff changeset
   158
    #> recursive_method method_name vars body terms
62070
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
   159
  end;
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
   160
61919
b3d68dff610b tuned module arrangement;
wenzelm
parents: 61918
diff changeset
   161
b3d68dff610b tuned module arrangement;
wenzelm
parents: 61918
diff changeset
   162
62070
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
   163
(** define method closure **)
61919
b3d68dff610b tuned module arrangement;
wenzelm
parents: 61918
diff changeset
   164
b3d68dff610b tuned module arrangement;
wenzelm
parents: 61918
diff changeset
   165
local
b3d68dff610b tuned module arrangement;
wenzelm
parents: 61918
diff changeset
   166
60119
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   167
fun setup_local_method binding lthy =
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   168
  let
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   169
    val full_name = Local_Theory.full_name lthy binding;
62074
wenzelm
parents: 62073
diff changeset
   170
    fun dynamic_method ctxt = lookup_dynamic_method ctxt full_name;
60119
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   171
  in
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   172
    lthy
60287
adde5ce1e0a7 updated Eisbach, using version 134bc592909c of its Bitbucket repository;
wenzelm
parents: 60285
diff changeset
   173
    |> update_dynamic_method (full_name, K Method.fail)
62074
wenzelm
parents: 62073
diff changeset
   174
    |> Method.local_setup binding (Scan.succeed dynamic_method) "(internal)"
60119
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   175
  end;
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   176
62070
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
   177
fun check_named_thm ctxt binding =
61919
b3d68dff610b tuned module arrangement;
wenzelm
parents: 61918
diff changeset
   178
  let
62070
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
   179
    val bname = Binding.name_of binding;
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
   180
    val pos = Binding.pos_of binding;
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
   181
    val full_name = Named_Theorems.check ctxt (bname, pos);
61919
b3d68dff610b tuned module arrangement;
wenzelm
parents: 61918
diff changeset
   182
    val parser: Method.modifier parser =
62070
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
   183
      Args.$$$ bname -- Args.colon
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
   184
        >> K {init = I, attribute = Named_Theorems.add full_name, pos = pos};
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
   185
  in (full_name, parser) end;
61919
b3d68dff610b tuned module arrangement;
wenzelm
parents: 61918
diff changeset
   186
61918
0f9e0106c378 tuned module arrangement;
wenzelm
parents: 61917
diff changeset
   187
fun parse_term_args args =
0f9e0106c378 tuned module arrangement;
wenzelm
parents: 61917
diff changeset
   188
  Args.context :|-- (fn ctxt =>
0f9e0106c378 tuned module arrangement;
wenzelm
parents: 61917
diff changeset
   189
    let
0f9e0106c378 tuned module arrangement;
wenzelm
parents: 61917
diff changeset
   190
      val ctxt' = Proof_Context.set_mode (Proof_Context.mode_schematic) ctxt;
0f9e0106c378 tuned module arrangement;
wenzelm
parents: 61917
diff changeset
   191
0f9e0106c378 tuned module arrangement;
wenzelm
parents: 61917
diff changeset
   192
      fun parse T =
0f9e0106c378 tuned module arrangement;
wenzelm
parents: 61917
diff changeset
   193
        (if T = propT then Syntax.parse_prop ctxt' else Syntax.parse_term ctxt')
0f9e0106c378 tuned module arrangement;
wenzelm
parents: 61917
diff changeset
   194
        #> Type.constraint (Type_Infer.paramify_vars T);
0f9e0106c378 tuned module arrangement;
wenzelm
parents: 61917
diff changeset
   195
0f9e0106c378 tuned module arrangement;
wenzelm
parents: 61917
diff changeset
   196
      fun do_parse' T =
0f9e0106c378 tuned module arrangement;
wenzelm
parents: 61917
diff changeset
   197
        Parse_Tools.name_term >> Parse_Tools.parse_val_cases (parse T);
0f9e0106c378 tuned module arrangement;
wenzelm
parents: 61917
diff changeset
   198
0f9e0106c378 tuned module arrangement;
wenzelm
parents: 61917
diff changeset
   199
      fun do_parse (Var (_, T)) = do_parse' T
0f9e0106c378 tuned module arrangement;
wenzelm
parents: 61917
diff changeset
   200
        | do_parse (Free (_, T)) = do_parse' T
0f9e0106c378 tuned module arrangement;
wenzelm
parents: 61917
diff changeset
   201
        | do_parse t = error ("Unexpected method parameter: " ^ Syntax.string_of_term ctxt' t);
0f9e0106c378 tuned module arrangement;
wenzelm
parents: 61917
diff changeset
   202
0f9e0106c378 tuned module arrangement;
wenzelm
parents: 61917
diff changeset
   203
       fun rep [] x = Scan.succeed [] x
0f9e0106c378 tuned module arrangement;
wenzelm
parents: 61917
diff changeset
   204
         | rep (t :: ts) x  = (do_parse t ::: rep ts) x;
0f9e0106c378 tuned module arrangement;
wenzelm
parents: 61917
diff changeset
   205
0f9e0106c378 tuned module arrangement;
wenzelm
parents: 61917
diff changeset
   206
      fun check ts =
0f9e0106c378 tuned module arrangement;
wenzelm
parents: 61917
diff changeset
   207
        let
0f9e0106c378 tuned module arrangement;
wenzelm
parents: 61917
diff changeset
   208
          val (ts, fs) = split_list ts;
0f9e0106c378 tuned module arrangement;
wenzelm
parents: 61917
diff changeset
   209
          val ts' = Syntax.check_terms ctxt' ts |> Variable.polymorphic ctxt';
0f9e0106c378 tuned module arrangement;
wenzelm
parents: 61917
diff changeset
   210
          val _ = ListPair.app (fn (f, t) => f t) (fs, ts');
0f9e0106c378 tuned module arrangement;
wenzelm
parents: 61917
diff changeset
   211
        in ts' end;
0f9e0106c378 tuned module arrangement;
wenzelm
parents: 61917
diff changeset
   212
    in Scan.lift (rep args) >> check end);
0f9e0106c378 tuned module arrangement;
wenzelm
parents: 61917
diff changeset
   213
62070
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
   214
fun parse_method_args method_args =
61919
b3d68dff610b tuned module arrangement;
wenzelm
parents: 61918
diff changeset
   215
  let
b3d68dff610b tuned module arrangement;
wenzelm
parents: 61918
diff changeset
   216
    fun bind_method (name, text) ctxt =
b3d68dff610b tuned module arrangement;
wenzelm
parents: 61918
diff changeset
   217
      let
b3d68dff610b tuned module arrangement;
wenzelm
parents: 61918
diff changeset
   218
        val method = method_evaluate text;
b3d68dff610b tuned module arrangement;
wenzelm
parents: 61918
diff changeset
   219
        val inner_update = method o update_dynamic_method (name, K (method ctxt));
b3d68dff610b tuned module arrangement;
wenzelm
parents: 61918
diff changeset
   220
      in update_dynamic_method (name, inner_update) ctxt end;
b3d68dff610b tuned module arrangement;
wenzelm
parents: 61918
diff changeset
   221
b3d68dff610b tuned module arrangement;
wenzelm
parents: 61918
diff changeset
   222
    fun rep [] x = Scan.succeed [] x
62070
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
   223
      | rep (m :: ms) x = ((method_text >> pair m) ::: rep ms) x;
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
   224
  in rep method_args >> fold bind_method end;
61919
b3d68dff610b tuned module arrangement;
wenzelm
parents: 61918
diff changeset
   225
61899
77fa1ae5fd31 tuned signature;
wenzelm
parents: 61898
diff changeset
   226
fun gen_method add_fixes name vars uses declares methods source lthy =
60119
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   227
  let
61898
wenzelm
parents: 61853
diff changeset
   228
    val (uses_internal, lthy1) = lthy
60119
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   229
      |> Proof_Context.concealed
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   230
      |> Local_Theory.open_target |-> Proof_Context.private_scope
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   231
      |> Local_Theory.map_background_naming (Name_Space.add_path (Binding.name_of name))
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   232
      |> Config.put Method.old_section_parser true
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   233
      |> fold setup_local_method methods
61898
wenzelm
parents: 61853
diff changeset
   234
      |> fold_map (fn b => Named_Theorems.declare b "") uses;
60119
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   235
60407
53ef7b78e78a tuned signature;
wenzelm
parents: 60379
diff changeset
   236
    val (term_args, lthy2) = lthy1
60469
d1ea37df7358 tuned signature;
wenzelm
parents: 60407
diff changeset
   237
      |> add_fixes vars |-> fold_map Proof_Context.inferred_param |>> map Free;
60119
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   238
62070
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
   239
    val (named_thms, modifiers) = map (check_named_thm lthy2) (declares @ uses) |> split_list;
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
   240
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
   241
    val method_args = map (Local_Theory.full_name lthy2) methods;
60119
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   242
62073
wenzelm
parents: 62070
diff changeset
   243
    fun parser args meth =
60119
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   244
      apfst (Config.put_generic Method.old_section_parser true) #>
60287
adde5ce1e0a7 updated Eisbach, using version 134bc592909c of its Bitbucket repository;
wenzelm
parents: 60285
diff changeset
   245
      (parse_term_args args --
62070
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
   246
        parse_method_args method_args --|
60285
b4f1a0a701ae updated Eisbach, using version 4863020a8fe9 of its Bitbucket repository;
wenzelm
parents: 60248
diff changeset
   247
        (Scan.depend (fn context =>
61900
wenzelm
parents: 61899
diff changeset
   248
          Scan.succeed (fold Named_Theorems.clear uses_internal context, ())) --
62073
wenzelm
parents: 62070
diff changeset
   249
         Method.sections modifiers)) >> (fn (ts, decl) => meth ts o decl);
60119
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   250
63186
dc221b8945f2 allow multiple recursive methods to co-exist in order to support mutual recursion;
matichuk <daniel.matichuk@nicta.com.au>
parents: 63185
diff changeset
   251
    val full_name = Local_Theory.full_name lthy name;
dc221b8945f2 allow multiple recursive methods to co-exist in order to support mutual recursion;
matichuk <daniel.matichuk@nicta.com.au>
parents: 63185
diff changeset
   252
60119
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   253
    val lthy3 = lthy2
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   254
      |> Method.local_setup (Binding.make (Binding.name_of name, Position.none))
63186
dc221b8945f2 allow multiple recursive methods to co-exist in order to support mutual recursion;
matichuk <daniel.matichuk@nicta.com.au>
parents: 63185
diff changeset
   255
        (parser term_args (get_recursive_method full_name)) "(internal)"
dc221b8945f2 allow multiple recursive methods to co-exist in order to support mutual recursion;
matichuk <daniel.matichuk@nicta.com.au>
parents: 63185
diff changeset
   256
      |> put_recursive_method (full_name, fn _ => fn _ => Method.fail);
60119
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   257
62078
76399b8fde4d more systematic treatment of dynamic facts, when forming closure;
wenzelm
parents: 62076
diff changeset
   258
    val (text, src) =
76399b8fde4d more systematic treatment of dynamic facts, when forming closure;
wenzelm
parents: 62076
diff changeset
   259
      read_closure (Config.put Proof_Context.dynamic_facts_dummy true lthy3) source;
60119
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   260
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   261
    val morphism =
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   262
      Variable.export_morphism lthy3
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   263
        (lthy
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   264
          |> Proof_Context.transfer (Proof_Context.theory_of lthy3)
61814
1ca1142e1711 clarified type Token.src: plain token list, with usual implicit value assignment;
wenzelm
parents: 60553
diff changeset
   265
          |> fold Token.declare_maxidx src
60119
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   266
          |> Variable.declare_maxidx (Variable.maxidx_of lthy3));
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   267
61814
1ca1142e1711 clarified type Token.src: plain token list, with usual implicit value assignment;
wenzelm
parents: 60553
diff changeset
   268
    val text' = (Method.map_source o map) (Token.transform morphism) text;
60119
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   269
    val term_args' = map (Morphism.term morphism) term_args;
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   270
  in
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   271
    lthy3
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   272
    |> Local_Theory.close_target
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   273
    |> Proof_Context.restore_naming lthy
62070
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
   274
    |> put_closure name
b13b98a4d5f8 more realistic Eisbach method invocation from ML;
wenzelm
parents: 62069
diff changeset
   275
        {vars = term_args', named_thms = named_thms, methods = method_args, body = text'}
63185
08369e33c185 apply current morphism to method text before evaluating;
matichuk <daniel.matichuk@nicta.com.au>
parents: 62795
diff changeset
   276
    |> Method.local_setup name 
08369e33c185 apply current morphism to method text before evaluating;
matichuk <daniel.matichuk@nicta.com.au>
parents: 62795
diff changeset
   277
        (Args.context :|-- (fn ctxt =>
08369e33c185 apply current morphism to method text before evaluating;
matichuk <daniel.matichuk@nicta.com.au>
parents: 62795
diff changeset
   278
          let val {body, vars, ...} = get_closure ctxt full_name in
63186
dc221b8945f2 allow multiple recursive methods to co-exist in order to support mutual recursion;
matichuk <daniel.matichuk@nicta.com.au>
parents: 63185
diff changeset
   279
            parser vars (recursive_method full_name vars body) end)) ""
63185
08369e33c185 apply current morphism to method text before evaluating;
matichuk <daniel.matichuk@nicta.com.au>
parents: 62795
diff changeset
   280
    |> pair full_name
60119
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   281
  end;
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   282
61898
wenzelm
parents: 61853
diff changeset
   283
in
wenzelm
parents: 61853
diff changeset
   284
61899
77fa1ae5fd31 tuned signature;
wenzelm
parents: 61898
diff changeset
   285
val method = gen_method Proof_Context.add_fixes;
77fa1ae5fd31 tuned signature;
wenzelm
parents: 61898
diff changeset
   286
val method_cmd = gen_method Proof_Context.add_fixes_cmd;
60119
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   287
61898
wenzelm
parents: 61853
diff changeset
   288
end;
wenzelm
parents: 61853
diff changeset
   289
60119
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   290
val _ =
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   291
  Outer_Syntax.local_theory @{command_keyword method} "Eisbach method definition"
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   292
    (Parse.binding -- Parse.for_fixes --
60287
adde5ce1e0a7 updated Eisbach, using version 134bc592909c of its Bitbucket repository;
wenzelm
parents: 60285
diff changeset
   293
      ((Scan.optional (@{keyword "methods"} |-- Parse.!!! (Scan.repeat1 Parse.binding)) []) --
adde5ce1e0a7 updated Eisbach, using version 134bc592909c of its Bitbucket repository;
wenzelm
parents: 60285
diff changeset
   294
        (Scan.optional (@{keyword "uses"} |-- Parse.!!! (Scan.repeat1 Parse.binding)) [])) --
adde5ce1e0a7 updated Eisbach, using version 134bc592909c of its Bitbucket repository;
wenzelm
parents: 60285
diff changeset
   295
      (Scan.optional (@{keyword "declares"} |-- Parse.!!! (Scan.repeat1 Parse.binding)) []) --
61898
wenzelm
parents: 61853
diff changeset
   296
      Parse.!!! (@{keyword "="} |-- Parse.args1 (K true)) >>
wenzelm
parents: 61853
diff changeset
   297
      (fn ((((name, vars), (methods, uses)), declares), src) =>
61910
ae36547d3a30 tuned signature;
wenzelm
parents: 61903
diff changeset
   298
        #2 o method_cmd name vars uses declares methods src));
61814
1ca1142e1711 clarified type Token.src: plain token list, with usual implicit value assignment;
wenzelm
parents: 60553
diff changeset
   299
60119
54bea620e54f added Eisbach, using version 3752768caa17 of its Bitbucket repository;
wenzelm
parents:
diff changeset
   300
end;