cases: more position information and PIDE markup;
authorwenzelm
Tue, 03 Sep 2013 13:09:15 +0200
changeset 5451507990ba8c0ea
parent 54514 21693b7c8fbf
child 54516 74920496ab71
cases: more position information and PIDE markup;
src/HOL/Tools/Nitpick/nitpick.ML
src/HOL/Tools/Predicate_Compile/predicate_compile_core.ML
src/Pure/Isar/isar_syn.ML
src/Pure/Isar/proof.ML
src/Pure/Isar/proof_context.ML
src/Pure/PIDE/markup.ML
src/Pure/PIDE/markup.scala
     1.1 --- a/src/HOL/Tools/Nitpick/nitpick.ML	Tue Sep 03 11:58:34 2013 +0200
     1.2 +++ b/src/HOL/Tools/Nitpick/nitpick.ML	Tue Sep 03 13:09:15 2013 +0200
     1.3 @@ -460,7 +460,7 @@
     1.4        exists (exists (curry (op =) name o shortest_name o fst)
     1.5                o datatype_constrs hol_ctxt) deep_dataTs
     1.6      val likely_in_struct_induct_step =
     1.7 -      exists is_struct_induct_step (Proof_Context.cases_of ctxt)
     1.8 +      exists is_struct_induct_step (Proof_Context.dest_cases ctxt)
     1.9      val _ = if standard andalso likely_in_struct_induct_step then
    1.10                pprint_nt (fn () => Pretty.blk (0,
    1.11                    pstrs "Hint: To check that the induction hypothesis is \
     2.1 --- a/src/HOL/Tools/Predicate_Compile/predicate_compile_core.ML	Tue Sep 03 11:58:34 2013 +0200
     2.2 +++ b/src/HOL/Tools/Predicate_Compile/predicate_compile_core.ML	Tue Sep 03 13:09:15 2013 +0200
     2.3 @@ -1600,7 +1600,7 @@
     2.4      val case_env = map2 (fn p => fn c => (Long_Name.base_name p, SOME c)) preds cases
     2.5      val lthy'' = lthy'
     2.6        |> fold Variable.auto_fixes cases_rules
     2.7 -      |> Proof_Context.add_cases true case_env
     2.8 +      |> Proof_Context.update_cases true case_env
     2.9      fun after_qed thms goal_ctxt =
    2.10        let
    2.11          val global_thms = Proof_Context.export goal_ctxt
     3.1 --- a/src/Pure/Isar/isar_syn.ML	Tue Sep 03 11:58:34 2013 +0200
     3.2 +++ b/src/Pure/Isar/isar_syn.ML	Tue Sep 03 13:09:15 2013 +0200
     3.3 @@ -611,8 +611,9 @@
     3.4  val _ =
     3.5    Outer_Syntax.command @{command_spec "case"} "invoke local context"
     3.6      ((@{keyword "("} |--
     3.7 -      Parse.!!! (Parse.xname -- Scan.repeat (Parse.maybe Parse.binding) --| @{keyword ")"}) ||
     3.8 -      Parse.xname >> rpair []) -- Parse_Spec.opt_attribs >> (fn ((c, xs), atts) =>
     3.9 +      Parse.!!! (Parse.position Parse.xname -- Scan.repeat (Parse.maybe Parse.binding)
    3.10 +        --| @{keyword ")"}) ||
    3.11 +      Parse.position Parse.xname >> rpair []) -- Parse_Spec.opt_attribs >> (fn ((c, xs), atts) =>
    3.12          Toplevel.print o Toplevel.proof (Proof.invoke_case_cmd (c, xs, atts))));
    3.13  
    3.14  
     4.1 --- a/src/Pure/Isar/proof.ML	Tue Sep 03 11:58:34 2013 +0200
     4.2 +++ b/src/Pure/Isar/proof.ML	Tue Sep 03 13:09:15 2013 +0200
     4.3 @@ -70,8 +70,10 @@
     4.4    val using_cmd: ((Facts.ref * Attrib.src list) list) list -> state -> state
     4.5    val unfolding: ((thm list * attribute list) list) list -> state -> state
     4.6    val unfolding_cmd: ((Facts.ref * Attrib.src list) list) list -> state -> state
     4.7 -  val invoke_case: string * binding option list * attribute list -> state -> state
     4.8 -  val invoke_case_cmd: string * binding option list * Attrib.src list -> state -> state
     4.9 +  val invoke_case: (string * Position.T) * binding option list * attribute list ->
    4.10 +    state -> state
    4.11 +  val invoke_case_cmd: (string * Position.T) * binding option list * Attrib.src list ->
    4.12 +    state -> state
    4.13    val begin_block: state -> state
    4.14    val next_block: state -> state
    4.15    val end_block: state -> state
    4.16 @@ -399,8 +401,8 @@
    4.17      Method.apply meth ctxt using goal |> Seq.map (fn (meth_cases, goal') =>
    4.18        state
    4.19        |> map_goal
    4.20 -          (Proof_Context.add_cases false (no_goal_cases goal @ goal_cases goal') #>
    4.21 -           Proof_Context.add_cases true meth_cases)
    4.22 +          (Proof_Context.update_cases false (no_goal_cases goal @ goal_cases goal') #>
    4.23 +           Proof_Context.update_cases true meth_cases)
    4.24            (K (statement, [], using, goal', before_qed, after_qed)) I)
    4.25    end;
    4.26  
    4.27 @@ -744,17 +746,17 @@
    4.28  fun qualified_binding a =
    4.29    Binding.qualify true (Long_Name.qualifier a) (Binding.name (Long_Name.base_name a));
    4.30  
    4.31 -fun gen_invoke_case prep_att (name, xs, raw_atts) state =
    4.32 +fun gen_invoke_case prep_att ((name, pos), xs, raw_atts) state =
    4.33    let
    4.34      val atts = map (prep_att (context_of state)) raw_atts;
    4.35      val (asms, state') = state |> map_context_result (fn ctxt =>
    4.36 -      ctxt |> Proof_Context.apply_case (Proof_Context.get_case ctxt name xs));
    4.37 +      ctxt |> Proof_Context.apply_case (Proof_Context.check_case ctxt (name, pos) xs));
    4.38      val assumptions = asms |> map (fn (a, ts) => ((qualified_binding a, atts), map (rpair []) ts));
    4.39    in
    4.40      state'
    4.41      |> assume assumptions
    4.42      |> bind_terms Auto_Bind.no_facts
    4.43 -    |> `the_facts |-> (fn thms => note_thmss [((Binding.name name, []), [(thms, [])])])
    4.44 +    |> `the_facts |-> (fn thms => note_thmss [((Binding.make (name, pos), []), [(thms, [])])])
    4.45    end;
    4.46  
    4.47  in
     5.1 --- a/src/Pure/Isar/proof_context.ML	Tue Sep 03 11:58:34 2013 +0200
     5.2 +++ b/src/Pure/Isar/proof_context.ML	Tue Sep 03 13:09:15 2013 +0200
     5.3 @@ -31,7 +31,6 @@
     5.4    val set_syntax_mode: Syntax.mode -> Proof.context -> Proof.context
     5.5    val restore_syntax_mode: Proof.context -> Proof.context -> Proof.context
     5.6    val facts_of: Proof.context -> Facts.T
     5.7 -  val cases_of: Proof.context -> (string * (Rule_Cases.T * bool)) list
     5.8    val map_naming: (Name_Space.naming -> Name_Space.naming) -> Proof.context -> Proof.context
     5.9    val naming_of: Proof.context -> Name_Space.naming
    5.10    val restore_naming: Proof.context -> Proof.context -> Proof.context
    5.11 @@ -132,9 +131,10 @@
    5.12    val add_assms_i: Assumption.export ->
    5.13      (Thm.binding * (term * term list) list) list ->
    5.14      Proof.context -> (string * thm list) list * Proof.context
    5.15 -  val add_cases: bool -> (string * Rule_Cases.T option) list -> Proof.context -> Proof.context
    5.16 +  val dest_cases: Proof.context -> (string * (Rule_Cases.T * bool)) list
    5.17 +  val update_cases: bool -> (string * Rule_Cases.T option) list -> Proof.context -> Proof.context
    5.18    val apply_case: Rule_Cases.T -> Proof.context -> (string * term list) list * Proof.context
    5.19 -  val get_case: Proof.context -> string -> binding option list -> Rule_Cases.T
    5.20 +  val check_case: Proof.context -> string * Position.T -> binding option list -> Rule_Cases.T
    5.21    val type_notation: bool -> Syntax.mode -> (typ * mixfix) list -> Proof.context -> Proof.context
    5.22    val notation: bool -> Syntax.mode -> (term * mixfix) list -> Proof.context -> Proof.context
    5.23    val generic_type_notation: bool -> Syntax.mode -> (typ * mixfix) list -> morphism ->
    5.24 @@ -192,6 +192,9 @@
    5.25  
    5.26  (** Isar proof context information **)
    5.27  
    5.28 +type cases = ((Rule_Cases.T * bool) * int) Name_Space.table;
    5.29 +val empty_cases: cases = Name_Space.empty_table Markup.caseN;
    5.30 +
    5.31  datatype data =
    5.32    Data of
    5.33     {mode: mode,                  (*inner syntax mode*)
    5.34 @@ -199,7 +202,7 @@
    5.35      tsig: Type.tsig * Type.tsig, (*local/global type signature -- local name space / defsort only*)
    5.36      consts: Consts.T * Consts.T, (*local/global consts -- local name space / abbrevs only*)
    5.37      facts: Facts.T,              (*local facts*)
    5.38 -    cases: (string * (Rule_Cases.T * bool)) list};    (*named case contexts*)
    5.39 +    cases: cases};               (*named case contexts: case, is_proper, running index*)
    5.40  
    5.41  fun make_data (mode, syntax, tsig, consts, facts, cases) =
    5.42    Data {mode = mode, syntax = syntax, tsig = tsig, consts = consts, facts = facts, cases = cases};
    5.43 @@ -210,7 +213,7 @@
    5.44    fun init thy =
    5.45      make_data (mode_default, Local_Syntax.init thy,
    5.46        (Sign.tsig_of thy, Sign.tsig_of thy),
    5.47 -      (Sign.consts_of thy, Sign.consts_of thy), Facts.empty, []);
    5.48 +      (Sign.consts_of thy, Sign.consts_of thy), Facts.empty, empty_cases);
    5.49  );
    5.50  
    5.51  fun rep_data ctxt = Data.get ctxt |> (fn Data rep => rep);
    5.52 @@ -1132,28 +1135,23 @@
    5.53  
    5.54  (** cases **)
    5.55  
    5.56 +fun dest_cases ctxt =
    5.57 +  Symtab.fold (fn (a, (c, i)) => cons (i, (a, c))) (#2 (cases_of ctxt)) []
    5.58 +  |> sort (int_ord o pairself #1) |> map #2;
    5.59 +
    5.60  local
    5.61  
    5.62 -fun rem_case name = remove (fn (x: string, (y, _)) => x = y) name;
    5.63 -
    5.64 -fun add_case _ ("", _) cases = cases
    5.65 -  | add_case _ (name, NONE) cases = rem_case name cases
    5.66 -  | add_case is_proper (name, SOME c) cases = (name, (c, is_proper)) :: rem_case name cases;
    5.67 -
    5.68 -fun prep_case name fxs c =
    5.69 -  let
    5.70 -    fun replace (opt_x :: xs) ((y, T) :: ys) = (the_default y opt_x, T) :: replace xs ys
    5.71 -      | replace [] ys = ys
    5.72 -      | replace (_ :: _) [] = error ("Too many parameters for case " ^ quote name);
    5.73 -    val Rule_Cases.Case {fixes, assumes, binds, cases} = c;
    5.74 -    val fixes' = replace fxs fixes;
    5.75 -    val binds' = map drop_schematic binds;
    5.76 -  in
    5.77 -    if null (fold (Term.add_tvarsT o snd) fixes []) andalso
    5.78 -      null (fold (fold Term.add_vars o snd) assumes []) then
    5.79 -        Rule_Cases.Case {fixes = fixes', assumes = assumes, binds = binds', cases = cases}
    5.80 -    else error ("Illegal schematic variable(s) in case " ^ quote name)
    5.81 -  end;
    5.82 +fun update_case _ _ ("", _) res = res
    5.83 +  | update_case _ _ (name, NONE) ((space, tab), index) =
    5.84 +      let
    5.85 +        val tab' = Symtab.delete_safe name tab;
    5.86 +      in ((space, tab'), index) end
    5.87 +  | update_case context is_proper (name, SOME c) (cases, index) =
    5.88 +      let
    5.89 +        val (_, cases') = cases |> Name_Space.define context false
    5.90 +          (Binding.make (name, Position.none), ((c, is_proper), index));
    5.91 +        val index' = index + 1;
    5.92 +      in (cases', index') end;
    5.93  
    5.94  fun fix (b, T) ctxt =
    5.95    let val ([x], ctxt') = add_fixes [(b, SOME T, NoSyn)] ctxt
    5.96 @@ -1161,7 +1159,13 @@
    5.97  
    5.98  in
    5.99  
   5.100 -fun add_cases is_proper = map_cases o fold (add_case is_proper);
   5.101 +fun update_cases is_proper args ctxt =
   5.102 +  let
   5.103 +    val context = Context.Proof ctxt |> Name_Space.map_naming (K Name_Space.default_naming);
   5.104 +    val cases = cases_of ctxt;
   5.105 +    val index = Symtab.fold (fn _ => Integer.add 1) (#2 cases) 0;
   5.106 +    val (cases', _) = fold (update_case context is_proper) args (cases, index);
   5.107 +  in map_cases (K cases') ctxt end;
   5.108  
   5.109  fun case_result c ctxt =
   5.110    let
   5.111 @@ -1171,16 +1175,29 @@
   5.112    in
   5.113      ctxt'
   5.114      |> bind_terms (map drop_schematic binds)
   5.115 -    |> add_cases true (map (apsnd SOME) cases)
   5.116 +    |> update_cases true (map (apsnd SOME) cases)
   5.117      |> pair (assumes, (binds, cases))
   5.118    end;
   5.119  
   5.120  val apply_case = apfst fst oo case_result;
   5.121  
   5.122 -fun get_case ctxt name xs =
   5.123 -  (case AList.lookup (op =) (cases_of ctxt) name of
   5.124 -    NONE => error ("Unknown case: " ^ quote name)
   5.125 -  | SOME (c, _) => prep_case name xs c);
   5.126 +fun check_case ctxt (name, pos) fxs =
   5.127 +  let
   5.128 +    val (_, ((Rule_Cases.Case {fixes, assumes, binds, cases}, _), _)) =
   5.129 +      Name_Space.check (Context.Proof ctxt) (cases_of ctxt) (name, pos);
   5.130 +
   5.131 +    fun replace (opt_x :: xs) ((y, T) :: ys) = (the_default y opt_x, T) :: replace xs ys
   5.132 +      | replace [] ys = ys
   5.133 +      | replace (_ :: _) [] =
   5.134 +          error ("Too many parameters for case " ^ quote name ^ Position.here pos);
   5.135 +    val fixes' = replace fxs fixes;
   5.136 +    val binds' = map drop_schematic binds;
   5.137 +  in
   5.138 +    if null (fold (Term.add_tvarsT o snd) fixes []) andalso
   5.139 +      null (fold (fold Term.add_vars o snd) assumes []) then
   5.140 +        Rule_Cases.Case {fixes = fixes', assumes = assumes, binds = binds', cases = cases}
   5.141 +    else error ("Illegal schematic variable(s) in case " ^ quote name ^ Position.here pos)
   5.142 +  end;
   5.143  
   5.144  end;
   5.145  
   5.146 @@ -1278,10 +1295,10 @@
   5.147  
   5.148  fun pretty_cases ctxt =
   5.149    let
   5.150 -    fun add_case (_, (_, false)) = I
   5.151 -      | add_case (name, (c as Rule_Cases.Case {fixes, ...}, true)) =
   5.152 -          cons (name, (fixes, case_result c ctxt));
   5.153 -    val cases = fold add_case (cases_of ctxt) [];
   5.154 +    fun mk_case (_, (_, false)) = NONE
   5.155 +      | mk_case (name, (c as Rule_Cases.Case {fixes, ...}, true)) =
   5.156 +          SOME (name, (fixes, case_result c ctxt));
   5.157 +    val cases = dest_cases ctxt |> map_filter mk_case;
   5.158    in
   5.159      if null cases then []
   5.160      else [Pretty.big_list "cases:" (map pretty_case cases)]
     6.1 --- a/src/Pure/PIDE/markup.ML	Tue Sep 03 11:58:34 2013 +0200
     6.2 +++ b/src/Pure/PIDE/markup.ML	Tue Sep 03 13:09:15 2013 +0200
     6.3 @@ -46,6 +46,7 @@
     6.4    val type_nameN: string
     6.5    val constantN: string
     6.6    val fixedN: string val fixed: string -> T
     6.7 +  val caseN: string val case_: string -> T
     6.8    val dynamic_factN: string val dynamic_fact: string -> T
     6.9    val tfreeN: string val tfree: T
    6.10    val tvarN: string val tvar: T
    6.11 @@ -288,6 +289,7 @@
    6.12  val constantN = "constant";
    6.13  
    6.14  val (fixedN, fixed) = markup_string "fixed" nameN;
    6.15 +val (caseN, case_) = markup_string "case" nameN;
    6.16  val (dynamic_factN, dynamic_fact) = markup_string "dynamic_fact" nameN;
    6.17  
    6.18  
     7.1 --- a/src/Pure/PIDE/markup.scala	Tue Sep 03 11:58:34 2013 +0200
     7.2 +++ b/src/Pure/PIDE/markup.scala	Tue Sep 03 13:09:15 2013 +0200
     7.3 @@ -105,8 +105,8 @@
     7.4    val CLASS = "class"
     7.5    val TYPE_NAME = "type_name"
     7.6    val FIXED = "fixed"
     7.7 +  val CASE = "case"
     7.8    val CONSTANT = "constant"
     7.9 -
    7.10    val DYNAMIC_FACT = "dynamic_fact"
    7.11  
    7.12