|     75     cases : thm list, |     96     cases : thm list, | 
|     76     pelims : thm list list, |     97     pelims : thm list list, | 
|     77     termination : thm, |     98     termination : thm, | 
|     78     domintros : thm list option} |     99     domintros : thm list option} | 
|     79   val transform_function_data : info -> morphism -> info |    100   val transform_function_data : info -> morphism -> info | 
|     80   val get_function : Proof.context -> (term * info) Item_Net.T |         | 
|     81   val import_function_data : term -> Proof.context -> info option |    101   val import_function_data : term -> Proof.context -> info option | 
|     82   val import_last_function : Proof.context -> info option |    102   val import_last_function : Proof.context -> info option | 
|     83   val add_function_data : info -> Context.generic -> Context.generic |         | 
|     84   val set_termination_prover : (Proof.context -> tactic) -> Context.generic -> Context.generic |         | 
|     85   val get_termination_prover : Proof.context -> tactic |         | 
|     86   val store_termination_rule : thm -> Context.generic -> Context.generic |         | 
|     87   datatype function_config = FunctionConfig of |         | 
|     88    {sequential: bool, |         | 
|     89     default: string option, |         | 
|     90     domintros: bool, |         | 
|     91     partials: bool} |         | 
|     92   val default_config : function_config |    103   val default_config : function_config | 
|     93   val split_def : Proof.context -> (string -> 'a) -> term -> |         | 
|     94     string * (string * typ) list * term list * term list * term |         | 
|     95   val check_defs : Proof.context -> ((string * typ) * 'a) list -> term list -> unit |         | 
|     96   type fixes = ((string * typ) * mixfix) list |         | 
|     97   type 'a spec = (Attrib.binding * 'a list) list |         | 
|     98   type preproc = function_config -> Proof.context -> fixes -> term spec -> |         | 
|     99     (term list * (thm list -> thm spec) * (thm list -> thm list list) * string list) |         | 
|    100   val fname_of : term -> string |         | 
|    101   val mk_case_names : int -> string -> int -> string list |         | 
|    102   val empty_preproc : (Proof.context -> ((string * typ) * mixfix) list -> term list -> 'c) -> preproc |         | 
|    103   val get_preproc: Proof.context -> preproc |         | 
|    104   val set_preproc: preproc -> Context.generic -> Context.generic |         | 
|    105   val function_parser : function_config -> |    104   val function_parser : function_config -> | 
|    106     ((function_config * (binding * string option * mixfix) list) * (Attrib.binding * string) list) parser |    105     ((function_config * (binding * string option * mixfix) list) * | 
|         |    106       (Attrib.binding * string) list) parser | 
|    107 end |    107 end | 
|    108  |    108  | 
|    109 structure Function_Common : FUNCTION_COMMON = |    109 structure Function_Common : FUNCTION_COMMON = | 
|    110 struct |    110 struct | 
|    111  |    111  | 
|    112 open Function_Data |    112 open Function_Data | 
|    113  |    113  | 
|    114 local open Function_Lib in |    114 local open Function_Lib in | 
|    115  |    115  | 
|    116 (* Profiling *) |    116  | 
|    117 val profile = Unsynchronized.ref false; |    117 (* profiling *) | 
|         |    118  | 
|         |    119 val profile = Unsynchronized.ref false | 
|    118  |    120  | 
|    119 fun PROFILE msg = if !profile then timeap_msg msg else I |    121 fun PROFILE msg = if !profile then timeap_msg msg else I | 
|    120  |    122  | 
|    121 val acc_const_name = @{const_name Wellfounded.accp} |    123 val acc_const_name = @{const_name Wellfounded.accp} | 
|    122 fun mk_acc domT R = |    124 fun mk_acc domT R = | 
|    123   Const (acc_const_name, (domT --> domT --> HOLogic.boolT) --> domT --> HOLogic.boolT) $ R  |    125   Const (acc_const_name, (domT --> domT --> HOLogic.boolT) --> domT --> HOLogic.boolT) $ R | 
|    124  |    126  | 
|    125 val function_name = suffix "C" |    127 val function_name = suffix "C" | 
|    126 val graph_name = suffix "_graph" |    128 val graph_name = suffix "_graph" | 
|    127 val rel_name = suffix "_rel" |    129 val rel_name = suffix "_rel" | 
|    128 val dom_name = suffix "_dom" |    130 val dom_name = suffix "_dom" | 
|    129  |    131  | 
|    130 (* Termination rules *) |    132  | 
|    131  |    133 (* analyzing function equations *) | 
|    132 (* FIXME just one data slot (record) per program unit *) |    134  | 
|    133 structure TerminationRule = Generic_Data |    135 fun split_def ctxt check_head geq = | 
|         |    136   let | 
|         |    137     fun input_error msg = cat_lines [msg, Syntax.string_of_term ctxt geq] | 
|         |    138     val qs = Term.strip_qnt_vars @{const_name Pure.all} geq | 
|         |    139     val imp = Term.strip_qnt_body @{const_name Pure.all} geq | 
|         |    140     val (gs, eq) = Logic.strip_horn imp | 
|         |    141  | 
|         |    142     val (f_args, rhs) = HOLogic.dest_eq (HOLogic.dest_Trueprop eq) | 
|         |    143       handle TERM _ => error (input_error "Not an equation") | 
|         |    144  | 
|         |    145     val (head, args) = strip_comb f_args | 
|         |    146  | 
|         |    147     val fname = fst (dest_Free head) handle TERM _ => "" | 
|         |    148     val _ = check_head fname | 
|         |    149   in | 
|         |    150     (fname, qs, gs, args, rhs) | 
|         |    151   end | 
|         |    152  | 
|         |    153 (*check for all sorts of errors in the input*) | 
|         |    154 fun check_defs ctxt fixes eqs = | 
|         |    155   let | 
|         |    156     val fnames = map (fst o fst) fixes | 
|         |    157  | 
|         |    158     fun check geq = | 
|         |    159       let | 
|         |    160         fun input_error msg = error (cat_lines [msg, Syntax.string_of_term ctxt geq]) | 
|         |    161  | 
|         |    162         fun check_head fname = | 
|         |    163           member (op =) fnames fname orelse | 
|         |    164           input_error ("Illegal equation head. Expected " ^ commas_quote fnames) | 
|         |    165  | 
|         |    166         val (fname, qs, gs, args, rhs) = split_def ctxt check_head geq | 
|         |    167  | 
|         |    168         val _ = length args > 0 orelse input_error "Function has no arguments:" | 
|         |    169  | 
|         |    170         fun add_bvs t is = add_loose_bnos (t, 0, is) | 
|         |    171         val rvs = (subtract (op =) (fold add_bvs args []) (add_bvs rhs [])) | 
|         |    172                     |> map (fst o nth (rev qs)) | 
|         |    173  | 
|         |    174         val _ = null rvs orelse input_error | 
|         |    175           ("Variable" ^ plural " " "s " rvs ^ commas_quote rvs ^ | 
|         |    176            " occur" ^ plural "s" "" rvs ^ " on right hand side only:") | 
|         |    177  | 
|         |    178         val _ = forall (not o Term.exists_subterm | 
|         |    179           (fn Free (n, _) => member (op =) fnames n | _ => false)) (gs @ args) | 
|         |    180           orelse input_error "Defined function may not occur in premises or arguments" | 
|         |    181  | 
|         |    182         val freeargs = map (fn t => subst_bounds (rev (map Free qs), t)) args | 
|         |    183         val funvars = | 
|         |    184           filter | 
|         |    185             (fn q => exists (exists_subterm (fn (Free q') $ _ => q = q' | _ => false)) freeargs) qs | 
|         |    186         val _ = null funvars orelse (warning (cat_lines | 
|         |    187           ["Bound variable" ^ plural " " "s " funvars ^ | 
|         |    188           commas_quote (map fst funvars) ^ " occur" ^ plural "s" "" funvars ^ | 
|         |    189           " in function position.", "Misspelled constructor???"]); true) | 
|         |    190       in | 
|         |    191         (fname, length args) | 
|         |    192       end | 
|         |    193  | 
|         |    194     val grouped_args = AList.group (op =) (map check eqs) | 
|         |    195     val _ = grouped_args | 
|         |    196       |> map (fn (fname, ars) => | 
|         |    197         length (distinct (op =) ars) = 1 orelse | 
|         |    198           error ("Function " ^ quote fname ^ | 
|         |    199             " has different numbers of arguments in different equations")) | 
|         |    200  | 
|         |    201     val not_defined = subtract (op =) (map fst grouped_args) fnames | 
|         |    202     val _ = null not_defined | 
|         |    203       orelse error ("No defining equations for function" ^ | 
|         |    204         plural " " "s " not_defined ^ commas_quote not_defined) | 
|         |    205  | 
|         |    206     fun check_sorts ((fname, fT), _) = | 
|         |    207       Sorts.of_sort (Sign.classes_of (Proof_Context.theory_of ctxt)) (fT, @{sort type}) | 
|         |    208       orelse error (cat_lines | 
|         |    209       ["Type of " ^ quote fname ^ " is not of sort " ^ quote "type" ^ ":", | 
|         |    210        Syntax.string_of_typ (Config.put show_sorts true ctxt) fT]) | 
|         |    211  | 
|         |    212     val _ = map check_sorts fixes | 
|         |    213   in | 
|         |    214     () | 
|         |    215   end | 
|         |    216  | 
|         |    217  | 
|         |    218 (* preprocessors *) | 
|         |    219  | 
|         |    220 type fixes = ((string * typ) * mixfix) list | 
|         |    221 type 'a spec = (Attrib.binding * 'a list) list | 
|         |    222  | 
|         |    223 datatype function_config = FunctionConfig of | 
|         |    224  {sequential: bool, | 
|         |    225   default: string option, | 
|         |    226   domintros: bool, | 
|         |    227   partials: bool} | 
|         |    228  | 
|         |    229 type preproc = function_config -> Proof.context -> fixes -> term spec -> | 
|         |    230   (term list * (thm list -> thm spec) * (thm list -> thm list list) * string list) | 
|         |    231  | 
|         |    232 val fname_of = fst o dest_Free o fst o strip_comb o fst o HOLogic.dest_eq o | 
|         |    233   HOLogic.dest_Trueprop o Logic.strip_imp_concl o snd o dest_all_all | 
|         |    234  | 
|         |    235 fun mk_case_names i "" k = mk_case_names i (string_of_int (i + 1)) k | 
|         |    236   | mk_case_names _ _ 0 = [] | 
|         |    237   | mk_case_names _ n 1 = [n] | 
|         |    238   | mk_case_names _ n k = map (fn i => n ^ "_" ^ string_of_int i) (1 upto k) | 
|         |    239  | 
|         |    240 fun empty_preproc check (_: function_config) (ctxt: Proof.context) (fixes: fixes) spec = | 
|         |    241   let | 
|         |    242     val (bnds, tss) = split_list spec | 
|         |    243     val ts = flat tss | 
|         |    244     val _ = check ctxt fixes ts | 
|         |    245     val fnames = map (fst o fst) fixes | 
|         |    246     val indices = map (fn eq => find_index (curry op = (fname_of eq)) fnames) ts | 
|         |    247  | 
|         |    248     fun sort xs = partition_list (fn i => fn (j,_) => i = j) 0 (length fnames - 1) | 
|         |    249       (indices ~~ xs) |> map (map snd) | 
|         |    250  | 
|         |    251     (* using theorem names for case name currently disabled *) | 
|         |    252     val cnames = map_index (fn (i, _) => mk_case_names i "" 1) bnds |> flat | 
|         |    253   in | 
|         |    254     (ts, curry op ~~ bnds o Library.unflat tss, sort, cnames) | 
|         |    255   end | 
|         |    256  | 
|         |    257  | 
|         |    258 (* context data *) | 
|         |    259  | 
|         |    260 structure Data = Generic_Data | 
|    134 ( |    261 ( | 
|    135   type T = thm list |    262   type T = | 
|    136   val empty = [] |    263     thm list * | 
|         |    264     (term * info) Item_Net.T * | 
|         |    265     (Proof.context -> tactic) * | 
|         |    266     preproc | 
|         |    267   val empty: T = | 
|         |    268    ([], | 
|         |    269     Item_Net.init (op aconv o apply2 fst) (single o fst), | 
|         |    270     fn _ => error "Termination prover not configured", | 
|         |    271     empty_preproc check_defs) | 
|    137   val extend = I |    272   val extend = I | 
|    138   val merge = Thm.merge_thms |    273   fun merge | 
|    139 ); |    274    ((termination_rules1, functions1, termination_prover1, preproc1), | 
|    140  |    275     (termination_rules2, functions2, _, _)) : T = | 
|    141 val get_termination_rules = TerminationRule.get |    276    (Thm.merge_thms (termination_rules1, termination_rules2), | 
|    142 val store_termination_rule = TerminationRule.map o cons |    277     Item_Net.merge (functions1, functions2), | 
|    143 val apply_termination_rule = resolve_tac o get_termination_rules o Context.Proof |    278     termination_prover1, | 
|    144  |    279     preproc1) | 
|    145  |    280 ) | 
|    146 (* Function definition result data *) |    281  | 
|         |    282 val termination_rule_tac = resolve_tac o #1 o Data.get o Context.Proof | 
|         |    283 val store_termination_rule = Data.map o @{apply 4(1)} o cons | 
|         |    284  | 
|         |    285 val get_functions = #2 o Data.get o Context.Proof | 
|         |    286 fun add_function_data (info : info as {fs, termination, ...}) = | 
|         |    287   (Data.map o @{apply 4(2)}) (fold (fn f => Item_Net.update (f, info)) fs) | 
|         |    288   #> store_termination_rule termination | 
|         |    289  | 
|         |    290 fun termination_prover_tac ctxt = #3 (Data.get (Context.Proof ctxt)) ctxt | 
|         |    291 val set_termination_prover = Data.map o @{apply 4(3)} o K | 
|         |    292  | 
|         |    293 val get_preproc = #4 o Data.get o Context.Proof | 
|         |    294 val set_preproc = Data.map o @{apply 4(4)} o K | 
|         |    295  | 
|         |    296  | 
|         |    297 (* function definition result data *) | 
|    147  |    298  | 
|    148 datatype function_result = FunctionResult of |    299 datatype function_result = FunctionResult of | 
|    149  {fs: term list, |    300  {fs: term list, | 
|    150   G: term, |    301   G: term, | 
|    151   R: term, |    302   R: term, | 
|    203  |    343  | 
|    204     fun match (trm, data) = |    344     fun match (trm, data) = | 
|    205       SOME (transform_function_data data (inst_morph (Thm.match (cterm_of thy trm, ct)))) |    345       SOME (transform_function_data data (inst_morph (Thm.match (cterm_of thy trm, ct)))) | 
|    206       handle Pattern.MATCH => NONE |    346       handle Pattern.MATCH => NONE | 
|    207   in |    347   in | 
|    208     get_first match (Item_Net.retrieve (get_function ctxt) t) |    348     get_first match (Item_Net.retrieve (get_functions ctxt) t) | 
|    209   end |    349   end | 
|    210  |    350  | 
|    211 fun import_last_function ctxt = |    351 fun import_last_function ctxt = | 
|    212   case Item_Net.content (get_function ctxt) of |    352   (case Item_Net.content (get_functions ctxt) of | 
|    213     [] => NONE |    353     [] => NONE | 
|    214   | (t, _) :: _ => |    354   | (t, _) :: _ => | 
|    215     let |    355       let val ([t'], ctxt') = Variable.import_terms true [t] ctxt | 
|    216       val ([t'], ctxt') = Variable.import_terms true [t] ctxt |    356       in import_function_data t' ctxt' end) | 
|    217     in |    357  | 
|    218       import_function_data t' ctxt' |    358  | 
|    219     end |    359 (* configuration management *) | 
|    220  |    360  | 
|    221 fun add_function_data (data : info as {fs, termination, ...}) = |    361 datatype function_opt = | 
|    222   FunctionData.map (fold (fn f => Item_Net.update (f, data)) fs) |    362     Sequential | 
|    223   #> store_termination_rule termination |         | 
|    224  |         | 
|    225  |         | 
|    226 (* Default Termination Prover *) |         | 
|    227  |         | 
|    228 (* FIXME just one data slot (record) per program unit *) |         | 
|    229 structure TerminationProver = Generic_Data |         | 
|    230 ( |         | 
|    231   type T = Proof.context -> tactic |         | 
|    232   val empty = (fn _ => error "Termination prover not configured") |         | 
|    233   val extend = I |         | 
|    234   fun merge (a, _) = a |         | 
|    235 ) |         | 
|    236  |         | 
|    237 val set_termination_prover = TerminationProver.put |         | 
|    238 fun get_termination_prover ctxt = TerminationProver.get (Context.Proof ctxt) ctxt |         | 
|    239  |         | 
|    240  |         | 
|    241 (* Configuration management *) |         | 
|    242 datatype function_opt |         | 
|    243   = Sequential |         | 
|    244   | Default of string |    363   | Default of string | 
|    245   | DomIntros |    364   | DomIntros | 
|    246   | No_Partials |    365   | No_Partials | 
|    247  |    366  | 
|    248 datatype function_config = FunctionConfig of |    367 fun apply_opt Sequential (FunctionConfig {sequential = _, default, domintros, partials}) = | 
|    249  {sequential: bool, |    368       FunctionConfig | 
|    250   default: string option, |    369         {sequential = true, default = default, domintros = domintros, partials = partials} | 
|    251   domintros: bool, |    370   | apply_opt (Default d) (FunctionConfig {sequential, default = _, domintros, partials}) = | 
|    252   partials: bool} |    371       FunctionConfig | 
|    253  |    372         {sequential = sequential, default = SOME d, domintros = domintros, partials = partials} | 
|    254 fun apply_opt Sequential (FunctionConfig {sequential, default, domintros, partials}) = |    373   | apply_opt DomIntros (FunctionConfig {sequential, default, domintros = _, partials}) = | 
|    255     FunctionConfig {sequential=true, default=default, domintros=domintros, partials=partials} |    374       FunctionConfig | 
|    256   | apply_opt (Default d) (FunctionConfig {sequential, default, domintros, partials}) = |    375         {sequential = sequential, default = default, domintros = true, partials = partials} | 
|    257     FunctionConfig {sequential=sequential, default=SOME d, domintros=domintros, partials=partials} |    376   | apply_opt No_Partials (FunctionConfig {sequential, default, domintros, partials = _}) = | 
|    258   | apply_opt DomIntros (FunctionConfig {sequential, default, domintros, partials}) = |    377       FunctionConfig | 
|    259     FunctionConfig {sequential=sequential, default=default, domintros=true, partials=partials} |    378         {sequential = sequential, default = default, domintros = domintros, partials = false} | 
|    260   | apply_opt No_Partials (FunctionConfig {sequential, default, domintros, partials}) = |         | 
|    261     FunctionConfig {sequential=sequential, default=default, domintros=domintros, partials=false} |         | 
|    262  |    379  | 
|    263 val default_config = |    380 val default_config = | 
|    264   FunctionConfig { sequential=false, default=NONE, |    381   FunctionConfig { sequential=false, default=NONE, | 
|    265     domintros=false, partials=true} |    382     domintros=false, partials=true} | 
|    266  |         | 
|    267  |         | 
|    268 (* Analyzing function equations *) |         | 
|    269  |         | 
|    270 fun split_def ctxt check_head geq = |         | 
|    271   let |         | 
|    272     fun input_error msg = cat_lines [msg, Syntax.string_of_term ctxt geq] |         | 
|    273     val qs = Term.strip_qnt_vars @{const_name Pure.all} geq |         | 
|    274     val imp = Term.strip_qnt_body @{const_name Pure.all} geq |         | 
|    275     val (gs, eq) = Logic.strip_horn imp |         | 
|    276  |         | 
|    277     val (f_args, rhs) = HOLogic.dest_eq (HOLogic.dest_Trueprop eq) |         | 
|    278       handle TERM _ => error (input_error "Not an equation") |         | 
|    279  |         | 
|    280     val (head, args) = strip_comb f_args |         | 
|    281  |         | 
|    282     val fname = fst (dest_Free head) handle TERM _ => "" |         | 
|    283     val _ = check_head fname |         | 
|    284   in |         | 
|    285     (fname, qs, gs, args, rhs) |         | 
|    286   end |         | 
|    287  |         | 
|    288 (* Check for all sorts of errors in the input *) |         | 
|    289 fun check_defs ctxt fixes eqs = |         | 
|    290   let |         | 
|    291     val fnames = map (fst o fst) fixes |         | 
|    292  |         | 
|    293     fun check geq = |         | 
|    294       let |         | 
|    295         fun input_error msg = error (cat_lines [msg, Syntax.string_of_term ctxt geq]) |         | 
|    296  |         | 
|    297         fun check_head fname = |         | 
|    298           member (op =) fnames fname orelse |         | 
|    299           input_error ("Illegal equation head. Expected " ^ commas_quote fnames) |         | 
|    300  |         | 
|    301         val (fname, qs, gs, args, rhs) = split_def ctxt check_head geq |         | 
|    302  |         | 
|    303         val _ = length args > 0 orelse input_error "Function has no arguments:" |         | 
|    304  |         | 
|    305         fun add_bvs t is = add_loose_bnos (t, 0, is) |         | 
|    306         val rvs = (subtract (op =) (fold add_bvs args []) (add_bvs rhs [])) |         | 
|    307                     |> map (fst o nth (rev qs)) |         | 
|    308  |         | 
|    309         val _ = null rvs orelse input_error |         | 
|    310           ("Variable" ^ plural " " "s " rvs ^ commas_quote rvs ^ |         | 
|    311            " occur" ^ plural "s" "" rvs ^ " on right hand side only:") |         | 
|    312  |         | 
|    313         val _ = forall (not o Term.exists_subterm |         | 
|    314           (fn Free (n, _) => member (op =) fnames n | _ => false)) (gs @ args) |         | 
|    315           orelse input_error "Defined function may not occur in premises or arguments" |         | 
|    316  |         | 
|    317         val freeargs = map (fn t => subst_bounds (rev (map Free qs), t)) args |         | 
|    318         val funvars = filter (fn q => exists (exists_subterm (fn (Free q') $ _ => q = q' | _ => false)) freeargs) qs |         | 
|    319         val _ = null funvars orelse (warning (cat_lines |         | 
|    320           ["Bound variable" ^ plural " " "s " funvars ^ |         | 
|    321           commas_quote (map fst funvars) ^ " occur" ^ plural "s" "" funvars ^ |         | 
|    322           " in function position.", "Misspelled constructor???"]); true) |         | 
|    323       in |         | 
|    324         (fname, length args) |         | 
|    325       end |         | 
|    326  |         | 
|    327     val grouped_args = AList.group (op =) (map check eqs) |         | 
|    328     val _ = grouped_args |         | 
|    329       |> map (fn (fname, ars) => |         | 
|    330         length (distinct (op =) ars) = 1 |         | 
|    331         orelse error ("Function " ^ quote fname ^ |         | 
|    332           " has different numbers of arguments in different equations")) |         | 
|    333  |         | 
|    334     val not_defined = subtract (op =) (map fst grouped_args) fnames |         | 
|    335     val _ = null not_defined |         | 
|    336       orelse error ("No defining equations for function" ^ |         | 
|    337         plural " " "s " not_defined ^ commas_quote not_defined) |         | 
|    338  |         | 
|    339     fun check_sorts ((fname, fT), _) = |         | 
|    340       Sorts.of_sort (Sign.classes_of (Proof_Context.theory_of ctxt)) (fT, @{sort type}) |         | 
|    341       orelse error (cat_lines |         | 
|    342       ["Type of " ^ quote fname ^ " is not of sort " ^ quote "type" ^ ":", |         | 
|    343        Syntax.string_of_typ (Config.put show_sorts true ctxt) fT]) |         | 
|    344  |         | 
|    345     val _ = map check_sorts fixes |         | 
|    346   in |         | 
|    347     () |         | 
|    348   end |         | 
|    349  |         | 
|    350 (* Preprocessors *) |         | 
|    351  |         | 
|    352 type fixes = ((string * typ) * mixfix) list |         | 
|    353 type 'a spec = (Attrib.binding * 'a list) list |         | 
|    354 type preproc = function_config -> Proof.context -> fixes -> term spec -> |         | 
|    355   (term list * (thm list -> thm spec) * (thm list -> thm list list) * string list) |         | 
|    356  |         | 
|    357 val fname_of = fst o dest_Free o fst o strip_comb o fst o HOLogic.dest_eq o |         | 
|    358   HOLogic.dest_Trueprop o Logic.strip_imp_concl o snd o dest_all_all |         | 
|    359  |         | 
|    360 fun mk_case_names i "" k = mk_case_names i (string_of_int (i + 1)) k |         | 
|    361   | mk_case_names _ n 0 = [] |         | 
|    362   | mk_case_names _ n 1 = [n] |         | 
|    363   | mk_case_names _ n k = map (fn i => n ^ "_" ^ string_of_int i) (1 upto k) |         | 
|    364  |         | 
|    365 fun empty_preproc check (_: function_config) (ctxt: Proof.context) (fixes: fixes) spec = |         | 
|    366   let |         | 
|    367     val (bnds, tss) = split_list spec |         | 
|    368     val ts = flat tss |         | 
|    369     val _ = check ctxt fixes ts |         | 
|    370     val fnames = map (fst o fst) fixes |         | 
|    371     val indices = map (fn eq => find_index (curry op = (fname_of eq)) fnames) ts |         | 
|    372  |         | 
|    373     fun sort xs = partition_list (fn i => fn (j,_) => i = j) 0 (length fnames - 1)  |         | 
|    374       (indices ~~ xs) |> map (map snd) |         | 
|    375  |         | 
|    376     (* using theorem names for case name currently disabled *) |         | 
|    377     val cnames = map_index (fn (i, _) => mk_case_names i "" 1) bnds |> flat |         | 
|    378   in |         | 
|    379     (ts, curry op ~~ bnds o Library.unflat tss, sort, cnames) |         | 
|    380   end |         | 
|    381  |         | 
|    382 (* FIXME just one data slot (record) per program unit *) |         | 
|    383 structure Preprocessor = Generic_Data |         | 
|    384 ( |         | 
|    385   type T = preproc |         | 
|    386   val empty : T = empty_preproc check_defs |         | 
|    387   val extend = I |         | 
|    388   fun merge (a, _) = a |         | 
|    389 ) |         | 
|    390  |         | 
|    391 val get_preproc = Preprocessor.get o Context.Proof |         | 
|    392 val set_preproc = Preprocessor.map o K |         | 
|    393  |         | 
|    394  |         | 
|    395  |    383  | 
|    396 local |    384 local | 
|    397   val option_parser = Parse.group (fn () => "option") |    385   val option_parser = Parse.group (fn () => "option") | 
|    398     ((Parse.reserved "sequential" >> K Sequential) |    386     ((Parse.reserved "sequential" >> K Sequential) | 
|    399      || ((Parse.reserved "default" |-- Parse.term) >> Default) |    387      || ((Parse.reserved "default" |-- Parse.term) >> Default) |