src/Pure/Isar/class.ML
changeset 32206 b2e93cda0be8
parent 32113 bafffa63ebfd
child 32713 b8381161adb1
equal deleted inserted replaced
32205:49db434c157f 32206:b2e93cda0be8
    99   in (base_morph, eqs, export_morph, axiom, assm_intro, of_class) end;
    99   in (base_morph, eqs, export_morph, axiom, assm_intro, of_class) end;
   100 
   100 
   101 
   101 
   102 (* reading and processing class specifications *)
   102 (* reading and processing class specifications *)
   103 
   103 
   104 fun prep_class_elems prep_decl thy supexpr sups proto_base_sort raw_elems =
   104 fun prep_class_elems prep_decl thy sups proto_base_sort raw_elems =
   105   let
   105   let
   106 
   106 
   107     (* user space type system: only permits 'a type variable, improves towards 'a *)
   107     (* user space type system: only permits 'a type variable, improves towards 'a *)
   108     val base_constraints = (map o apsnd)
   108     val base_constraints = (map o apsnd)
   109       (map_type_tfree (K (TVar ((Name.aT, 0), proto_base_sort))) o fst o snd)
   109       (map_type_tfree (K (TVar ((Name.aT, 0), proto_base_sort))) o fst o snd)
   127                   ^ Syntax.string_of_sort_global thy inferred_sort
   127                   ^ Syntax.string_of_sort_global thy inferred_sort
   128                   ^ " of type parameter " ^ Name.aT ^ " of sort "
   128                   ^ " of type parameter " ^ Name.aT ^ " of sort "
   129                   ^ Syntax.string_of_sort_global thy a_sort ^ ".")
   129                   ^ Syntax.string_of_sort_global thy a_sort ^ ".")
   130             | _ => error "Multiple type variables in class specification.";
   130             | _ => error "Multiple type variables in class specification.";
   131       in (map o map_atyps) (K (TFree (Name.aT, fixate_sort))) Ts end;
   131       in (map o map_atyps) (K (TFree (Name.aT, fixate_sort))) Ts end;
   132     fun add_typ_check level name f = Context.proof_map (Syntax.add_typ_check level name (fn xs => fn ctxt =>
   132     fun add_typ_check level name f = Context.proof_map
   133       let val xs' = f xs in if eq_list (op =) (xs, xs') then NONE else SOME (xs', ctxt) end));
   133       (Syntax.add_typ_check level name (fn xs => fn ctxt =>
   134 
   134         let val xs' = f xs in if eq_list (op =) (xs, xs') then NONE else SOME (xs', ctxt) end));
   135     (* preprocessing elements, retrieving base sort from type-checked elements *)
   135 
       
   136     (* preprocessing elements, retrieving base sort from typechecked elements *)
   136     val init_class_body = fold (ProofContext.add_const_constraint o apsnd SOME) base_constraints
   137     val init_class_body = fold (ProofContext.add_const_constraint o apsnd SOME) base_constraints
   137       #> redeclare_operations thy sups
   138       #> redeclare_operations thy sups
   138       #> add_typ_check 10 "reject_bcd_etc" reject_bcd_etc
   139       #> add_typ_check 10 "reject_bcd_etc" reject_bcd_etc
   139       #> add_typ_check ~10 "singleton_fixate" (singleton_fixate thy (Sign.classes_of thy));
   140       #> add_typ_check ~10 "singleton_fixate" (singleton_fixate thy (Sign.classes_of thy));
   140     val ((_, _, inferred_elems), _) = ProofContext.init thy
   141     val raw_supexpr = (map (fn sup => (sup, (("", false),
   141       |> prep_decl supexpr init_class_body raw_elems;
   142       Expression.Positional []))) sups, []);
       
   143     val ((raw_supparams, _, inferred_elems), _) = ProofContext.init thy
       
   144       |> prep_decl raw_supexpr init_class_body raw_elems;
   142     fun fold_element_types f (Element.Fixes fxs) = fold (fn (_, SOME T, _) => f T) fxs
   145     fun fold_element_types f (Element.Fixes fxs) = fold (fn (_, SOME T, _) => f T) fxs
   143       | fold_element_types f (Element.Constrains cnstrs) = fold (f o snd) cnstrs
   146       | fold_element_types f (Element.Constrains cnstrs) = fold (f o snd) cnstrs
   144       | fold_element_types f (Element.Assumes assms) = fold (fold (fn (t, ts) =>
   147       | fold_element_types f (Element.Assumes assms) = fold (fold (fn (t, ts) =>
   145           fold_types f t #> (fold o fold_types) f ts) o snd) assms
   148           fold_types f t #> (fold o fold_types) f ts) o snd) assms
   146       | fold_element_types f (Element.Defines _) =
   149       | fold_element_types f (Element.Defines _) =
   149           error ("\"notes\" element not allowed in class specification.");
   152           error ("\"notes\" element not allowed in class specification.");
   150     val base_sort = if null inferred_elems then proto_base_sort else
   153     val base_sort = if null inferred_elems then proto_base_sort else
   151       case (fold o fold_element_types) Term.add_tfreesT inferred_elems []
   154       case (fold o fold_element_types) Term.add_tfreesT inferred_elems []
   152        of [] => error "No type variable in class specification"
   155        of [] => error "No type variable in class specification"
   153         | [(_, sort)] => sort
   156         | [(_, sort)] => sort
   154         | _ => error "Multiple type variables in class specification"
   157         | _ => error "Multiple type variables in class specification";
   155 
   158     val supparams = map (fn ((c, T), _) =>
   156   in (base_sort, inferred_elems) end;
   159       (c, map_atyps (K (TFree (Name.aT, base_sort))) T)) raw_supparams;
       
   160     val supparam_names = map fst supparams;
       
   161     fun mk_param ((c, _), _) = Free (c, (the o AList.lookup (op =) supparams) c);
       
   162     val supexpr = (map (fn sup => (sup, (("", false),
       
   163       Expression.Positional (map (SOME o mk_param) (Locale.params_of thy sup))))) sups,
       
   164         map (fn (c, T) => (Binding.name c, SOME T, NoSyn)) supparams);
       
   165 
       
   166   in (base_sort, supparam_names, supexpr, inferred_elems) end;
   157 
   167 
   158 val cert_class_elems = prep_class_elems Expression.cert_declaration;
   168 val cert_class_elems = prep_class_elems Expression.cert_declaration;
   159 val read_class_elems = prep_class_elems Expression.cert_read_declaration;
   169 val read_class_elems = prep_class_elems Expression.cert_read_declaration;
   160 
   170 
   161 fun prep_class_spec prep_class prep_class_elems thy raw_supclasses raw_elems =
   171 fun prep_class_spec prep_class prep_class_elems thy raw_supclasses raw_elems =
   166     val sups = map (prep_class thy) raw_supclasses
   176     val sups = map (prep_class thy) raw_supclasses
   167       |> Sign.minimize_sort thy;
   177       |> Sign.minimize_sort thy;
   168     val _ = case filter_out (is_class thy) sups
   178     val _ = case filter_out (is_class thy) sups
   169      of [] => ()
   179      of [] => ()
   170       | no_classes => error ("No (proper) classes: " ^ commas (map quote no_classes));
   180       | no_classes => error ("No (proper) classes: " ^ commas (map quote no_classes));
   171     val supparams = (map o apsnd) (snd o snd) (these_params thy sups);
   181     val raw_supparams = (map o apsnd) (snd o snd) (these_params thy sups);
   172     val supparam_names = map fst supparams;
   182     val raw_supparam_names = map fst raw_supparams;
   173     val _ = if has_duplicates (op =) supparam_names
   183     val _ = if has_duplicates (op =) raw_supparam_names
   174       then error ("Duplicate parameter(s) in superclasses: "
   184       then error ("Duplicate parameter(s) in superclasses: "
   175         ^ (commas o map quote o duplicates (op =)) supparam_names)
   185         ^ (commas o map quote o duplicates (op =)) raw_supparam_names)
   176       else ();
   186       else ();
   177     val supexpr = (map (fn sup => (sup, (("", false), Expression.Positional [])))
       
   178       sups, []);
       
   179     val given_basesort = fold inter_sort (map (base_sort thy) sups) [];
   187     val given_basesort = fold inter_sort (map (base_sort thy) sups) [];
   180 
   188 
   181     (* infer types and base sort *)
   189     (* infer types and base sort *)
   182     val (base_sort, inferred_elems) = prep_class_elems thy supexpr sups
   190     val (base_sort, supparam_names, supexpr, inferred_elems) =
   183       given_basesort raw_elems;
   191       prep_class_elems thy sups given_basesort raw_elems;
   184     val sup_sort = inter_sort base_sort sups
   192     val sup_sort = inter_sort base_sort sups;
   185 
   193 
   186     (* process elements as class specification *)
   194     (* process elements as class specification *)
   187     val class_ctxt = begin sups base_sort (ProofContext.init thy)
   195     val class_ctxt = begin sups base_sort (ProofContext.init thy);
   188     val ((_, _, syntax_elems), _) = class_ctxt
   196     val ((_, _, syntax_elems), _) = class_ctxt
   189       |> Expression.cert_declaration supexpr I inferred_elems;
   197       |> Expression.cert_declaration supexpr I inferred_elems;
   190     fun check_vars e vs = if null vs
   198     fun check_vars e vs = if null vs
   191       then error ("No type variable in part of specification element "
   199       then error ("No type variable in part of specification element "
   192         ^ (Pretty.output o Pretty.chunks) (Element.pretty_ctxt class_ctxt e))
   200         ^ (Pretty.output o Pretty.chunks) (Element.pretty_ctxt class_ctxt e))
   202           fold_map (fn (c, ty, syn) => cons (c, syn) #> pair (c, ty, NoSyn)) xs
   210           fold_map (fn (c, ty, syn) => cons (c, syn) #> pair (c, ty, NoSyn)) xs
   203           #>> Element.Fixes
   211           #>> Element.Fixes
   204       | fork_syn x = pair x;
   212       | fork_syn x = pair x;
   205     val (elems, global_syntax) = fold_map fork_syn syntax_elems [];
   213     val (elems, global_syntax) = fold_map fork_syn syntax_elems [];
   206     val constrain = Element.Constrains ((map o apsnd o map_atyps)
   214     val constrain = Element.Constrains ((map o apsnd o map_atyps)
   207       (K (TFree (Name.aT, base_sort))) supparams);
   215       (K (TFree (Name.aT, base_sort))) raw_supparams);
   208       (*FIXME perhaps better: control type variable by explicit
   216       (*FIXME perhaps better: control type variable by explicit
   209       parameter instantiation of import expression*)
   217       parameter instantiation of import expression*)
   210 
   218 
   211   in (((sups, supparam_names), (sup_sort, base_sort, supexpr)), (constrain :: elems, global_syntax)) end;
   219   in (((sups, supparam_names), (sup_sort, base_sort, supexpr)), ((*constrain :: *)elems, global_syntax)) end;
   212 
   220 
   213 val cert_class_spec = prep_class_spec (K I) cert_class_elems;
   221 val cert_class_spec = prep_class_spec (K I) cert_class_elems;
   214 val read_class_spec = prep_class_spec Sign.intern_class read_class_elems;
   222 val read_class_spec = prep_class_spec Sign.intern_class read_class_elems;
   215 
   223 
   216 
   224 
   217 (* class establishment *)
   225 (* class establishment *)
   218 
   226 
   219 fun add_consts class base_sort sups supparams global_syntax thy =
   227 fun add_consts class base_sort sups supparam_names global_syntax thy =
   220   let
   228   let
   221     (*FIXME simplify*)
   229     (*FIXME simplify*)
   222     val supconsts = supparams
   230     val supconsts = supparam_names
   223       |> AList.make (snd o the o AList.lookup (op =) (these_params thy sups))
   231       |> AList.make (snd o the o AList.lookup (op =) (these_params thy sups))
   224       |> (map o apsnd o apsnd o map_atyps o K o TFree) (Name.aT, [class]);
   232       |> (map o apsnd o apsnd o map_atyps o K o TFree) (Name.aT, [class]);
   225     val all_params = Locale.params_of thy class;
   233     val all_params = Locale.params_of thy class;
   226     val raw_params = (snd o chop (length supparams)) all_params;
   234     val raw_params = (snd o chop (length supparam_names)) all_params;
   227     fun add_const ((raw_c, raw_ty), _) thy =
   235     fun add_const ((raw_c, raw_ty), _) thy =
   228       let
   236       let
   229         val b = Binding.name raw_c;
   237         val b = Binding.name raw_c;
   230         val c = Sign.full_name thy b;
   238         val c = Sign.full_name thy b;
   231         val ty = map_atyps (K (TFree (Name.aT, base_sort))) raw_ty;
   239         val ty = map_atyps (K (TFree (Name.aT, base_sort))) raw_ty;
   244     |> fold_map add_const raw_params
   252     |> fold_map add_const raw_params
   245     ||> Sign.restore_naming thy
   253     ||> Sign.restore_naming thy
   246     |-> (fn params => pair (supconsts @ (map o apfst) fst params, params))
   254     |-> (fn params => pair (supconsts @ (map o apfst) fst params, params))
   247   end;
   255   end;
   248 
   256 
   249 fun adjungate_axclass bname class base_sort sups supsort supparams global_syntax thy =
   257 fun adjungate_axclass bname class base_sort sups supsort supparam_names global_syntax thy =
   250   let
   258   let
   251     (*FIXME simplify*)
   259     (*FIXME simplify*)
   252     fun globalize param_map = map_aterms
   260     fun globalize param_map = map_aterms
   253       (fn Free (v, ty) => Const ((fst o the o AList.lookup (op =) param_map) v, ty)
   261       (fn Free (v, ty) => Const ((fst o the o AList.lookup (op =) param_map) v, ty)
   254         | t => t);
   262         | t => t);
   258     fun get_axiom thy = case (#axioms o AxClass.get_info thy) class
   266     fun get_axiom thy = case (#axioms o AxClass.get_info thy) class
   259      of [] => NONE
   267      of [] => NONE
   260       | [thm] => SOME thm;
   268       | [thm] => SOME thm;
   261   in
   269   in
   262     thy
   270     thy
   263     |> add_consts class base_sort sups supparams global_syntax
   271     |> add_consts class base_sort sups supparam_names global_syntax
   264     |-> (fn (param_map, params) => AxClass.define_class (bname, supsort)
   272     |-> (fn (param_map, params) => AxClass.define_class (bname, supsort)
   265           (map (fst o snd) params)
   273           (map (fst o snd) params)
   266           [(Thm.empty_binding, Option.map (globalize param_map) raw_pred |> the_list)]
   274           [(Thm.empty_binding, Option.map (globalize param_map) raw_pred |> the_list)]
   267     #> snd
   275     #> snd
   268     #> `get_axiom
   276     #> `get_axiom
   269     #-> (fn assm_axiom => fold (Sign.add_const_constraint o apsnd SOME o snd) params
   277     #-> (fn assm_axiom => fold (Sign.add_const_constraint o apsnd SOME o snd) params
   270     #> pair (param_map, params, assm_axiom)))
   278     #> pair (param_map, params, assm_axiom)))
   271   end;
   279   end;
   272 
   280 
   273 fun gen_class prep_spec bname raw_supclasses raw_elems thy =
   281 fun gen_class prep_class_spec bname raw_supclasses raw_elems thy =
   274   let
   282   let
   275     val class = Sign.full_name thy bname;
   283     val class = Sign.full_name thy bname;
   276     val (((sups, supparams), (supsort, base_sort, supexpr)), (elems, global_syntax)) =
   284     val (((sups, supparam_names), (supsort, base_sort, supexpr)), (elems, global_syntax)) =
   277       prep_spec thy raw_supclasses raw_elems;
   285       prep_class_spec thy raw_supclasses raw_elems;
   278   in
   286   in
   279     thy
   287     thy
   280     |> Expression.add_locale bname Binding.empty supexpr elems
   288     |> Expression.add_locale bname Binding.empty supexpr elems
   281     |> snd |> LocalTheory.exit_global
   289     |> snd |> LocalTheory.exit_global
   282     |> adjungate_axclass bname class base_sort sups supsort supparams global_syntax
   290     |> adjungate_axclass bname class base_sort sups supsort supparam_names global_syntax
   283     ||> Theory.checkpoint
   291     ||> Theory.checkpoint
   284     |-> (fn (param_map, params, assm_axiom) =>
   292     |-> (fn (param_map, params, assm_axiom) =>
   285        `(fn thy => calculate thy class sups base_sort param_map assm_axiom)
   293        `(fn thy => calculate thy class sups base_sort param_map assm_axiom)
   286     #-> (fn (base_morph, eqs, export_morph, axiom, assm_intro, of_class) =>
   294     #-> (fn (base_morph, eqs, export_morph, axiom, assm_intro, of_class) =>
   287        Locale.add_registration_eqs (class, base_morph) eqs export_morph
   295        Locale.add_registration_eqs (class, base_morph) eqs export_morph