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 |