35 |
42 |
36 |
43 |
37 (* data kind 'Pure/classes' *) |
44 (* data kind 'Pure/classes' *) |
38 |
45 |
39 type class_data = { |
46 type class_data = { |
40 locale_name: string, |
47 superclasses: class list, |
41 axclass_name: string, |
48 name_locale: string, |
42 consts: string list, |
49 name_axclass: string, |
43 tycos: (string * string) list |
50 var: string, |
|
51 consts: (string * typ) list, |
|
52 insts: (string * string) list |
44 }; |
53 }; |
45 |
54 |
46 structure ClassesData = TheoryDataFun ( |
55 structure ClassData = TheoryDataFun ( |
47 struct |
56 struct |
48 val name = "Pure/classes"; |
57 val name = "Pure/classes"; |
49 type T = class_data Symtab.table * class Symtab.table; |
58 type T = class_data Symtab.table * class Symtab.table; |
50 val empty = (Symtab.empty, Symtab.empty); |
59 val empty = (Symtab.empty, Symtab.empty); |
51 val copy = I; |
60 val copy = I; |
52 val extend = I; |
61 val extend = I; |
53 fun merge _ ((t1, r1), (t2, r2))= |
62 fun merge _ ((t1, r1), (t2, r2))= |
54 (Symtab.merge (op =) (t1, t2), |
63 (Symtab.merge (op =) (t1, t2), |
55 Symtab.merge (op =) (r1, r2)); |
64 Symtab.merge (op =) (r1, r2)); |
56 fun print _ (tab, _) = (Pretty.writeln o Pretty.chunks) (map Pretty.str (Symtab.keys tab)); |
65 fun print thy (tab, _) = |
|
66 let |
|
67 fun pretty_class (name, {superclasses, name_locale, name_axclass, var, consts, insts}) = |
|
68 (Pretty.block o Pretty.fbreaks) [ |
|
69 Pretty.str ("class " ^ name ^ ":"), |
|
70 (Pretty.block o Pretty.fbreaks) ( |
|
71 Pretty.str "superclasses: " |
|
72 :: map Pretty.str superclasses |
|
73 ), |
|
74 Pretty.str ("locale: " ^ name_locale), |
|
75 Pretty.str ("axclass: " ^ name_axclass), |
|
76 Pretty.str ("class variable: " ^ var), |
|
77 (Pretty.block o Pretty.fbreaks) ( |
|
78 Pretty.str "constants: " |
|
79 :: map (fn (c, ty) => Pretty.str (c ^ " :: " ^ Sign.string_of_typ thy ty)) consts |
|
80 ), |
|
81 (Pretty.block o Pretty.fbreaks) ( |
|
82 Pretty.str "instances: " |
|
83 :: map (fn (tyco, thyname) => Pretty.str (tyco ^ ", in theory " ^ thyname)) insts |
|
84 ) |
|
85 ] |
|
86 in |
|
87 (Pretty.writeln o Pretty.chunks o map pretty_class o Symtab.dest) tab |
|
88 end; |
57 end |
89 end |
58 ); |
90 ); |
59 |
91 |
60 val lookup_class_data = Symtab.lookup o fst o ClassesData.get; |
92 val print_classes = ClassData.print; |
61 val lookup_const_class = Symtab.lookup o snd o ClassesData.get; |
93 |
|
94 val lookup_class_data = Symtab.lookup o fst o ClassData.get; |
|
95 val lookup_const_class = Symtab.lookup o snd o ClassData.get; |
62 |
96 |
63 fun get_class_data thy class = |
97 fun get_class_data thy class = |
64 case lookup_class_data thy class |
98 case lookup_class_data thy class |
65 of NONE => error ("undeclared class " ^ quote class) |
99 of NONE => error ("undeclared class " ^ quote class) |
66 | SOME data => data; |
100 | SOME data => data; |
67 |
101 |
68 fun put_class_data class data = |
102 fun add_class_data (class, (superclasses, name_locale, name_axclass, classvar, consts)) = |
69 ClassesData.map (apfst (Symtab.update (class, data))); |
103 ClassData.map (fn (classtab, consttab) => ( |
70 fun add_const class const = |
104 classtab |
71 ClassesData.map (apsnd (Symtab.update (const, class))); |
105 |> Symtab.update (class, { |
72 val the_consts = #consts oo get_class_data; |
106 superclasses = superclasses, |
73 val the_tycos = #tycos oo get_class_data; |
107 name_locale = name_locale, |
74 |
108 name_axclass = name_axclass, |
75 |
109 var = classvar, |
76 (* name mangling *) |
110 consts = consts, |
77 |
111 insts = [] |
78 fun get_locale_for_class thy class = |
112 }), |
79 #locale_name (get_class_data thy class); |
113 consttab |
80 |
114 |> fold (fn (c, _) => Symtab.update (c, class)) consts |
81 fun get_axclass_for_class thy class = |
115 )); |
82 #axclass_name (get_class_data thy class); |
116 |
83 |
117 fun add_inst_data (class, inst) = |
84 |
118 (ClassData.map o apfst o Symtab.map_entry class) |
85 (* classes *) |
119 (fn {superclasses, name_locale, name_axclass, var, consts, insts} |
|
120 => { |
|
121 superclasses = superclasses, |
|
122 name_locale = name_locale, |
|
123 name_axclass = name_axclass, |
|
124 var = var, |
|
125 consts = consts, |
|
126 insts = insts @ [inst] |
|
127 }); |
|
128 |
|
129 val the_consts = map fst o #consts oo get_class_data; |
|
130 val the_tycos = #insts oo get_class_data; |
|
131 |
|
132 |
|
133 (* classes and instances *) |
86 |
134 |
87 local |
135 local |
88 |
136 |
89 open Element |
137 open Element |
90 |
138 |
91 fun gen_add_class add_locale bname raw_import raw_body thy = |
139 fun gen_add_class add_locale bname raw_import raw_body thy = |
92 let |
140 let |
93 fun extract_notes_consts thy elems = |
141 fun subst_clsvar v ty_subst = |
94 elems |
142 map_type_tfree (fn u as (w, _) => |
95 |> Library.flat |
143 if w = v then ty_subst else TFree u); |
96 |> List.mapPartial |
144 fun extract_assumes c_adds elems = |
97 (fn (Notes notes) => SOME notes |
145 let |
98 | _ => NONE) |
146 fun subst_free ts = |
99 |> Library.flat |
147 let |
100 |> map (fn (_, facts) => map fst facts) |
148 val get_ty = the o AList.lookup (op =) (fold Term.add_frees ts []); |
101 |> Library.flat o Library.flat |
149 val subst_map = map (fn (c, (c', _)) => |
102 |> map prop_of |
150 (Free (c, get_ty c), Const (c', get_ty c))) c_adds; |
103 |> (fn ts => fold (curry add_term_consts) ts []) |
151 in map (subst_atomic subst_map) ts end; |
104 |> tap (writeln o commas); |
152 in |
|
153 elems |
|
154 |> (map o List.mapPartial) |
|
155 (fn (Assumes asms) => (SOME o map (map fst o snd)) asms |
|
156 | _ => NONE) |
|
157 |> Library.flat o Library.flat o Library.flat |
|
158 |> subst_free |
|
159 end; |
105 fun extract_tyvar_name thy tys = |
160 fun extract_tyvar_name thy tys = |
106 fold (curry add_typ_tfrees) tys [] |
161 fold (curry add_typ_tfrees) tys [] |
107 |> (fn [(v, [])] => v |
162 |> (fn [(v, sort)] => |
108 | [(v, sort)] => |
|
109 if Sorts.sort_eq (Sign.classes_of thy) (Sign.defaultS thy, sort) |
163 if Sorts.sort_eq (Sign.classes_of thy) (Sign.defaultS thy, sort) |
110 then v |
164 then v |
111 else error ("sort constraint on class type variable: " ^ Sign.string_of_sort thy sort) |
165 else error ("illegal sort constraint on class type variable: " ^ Sign.string_of_sort thy sort) |
112 | [] => error ("no class type variable") |
166 | [] => error ("no class type variable") |
113 | vs => error ("more than one type variable: " ^ (commas o map (Sign.string_of_typ thy o TFree)) vs)) |
167 | vs => error ("more than one type variable: " ^ (commas o map (Sign.string_of_typ thy o TFree)) vs)) |
114 fun extract_tyvar_consts thy elems = |
168 fun extract_tyvar_consts thy elems = |
115 elems |
169 elems |
116 |> Library.flat |
170 |> Library.flat |
117 |> List.mapPartial |
171 |> List.mapPartial |
118 (fn (Fixes consts) => SOME consts |
172 (fn (Fixes consts) => SOME consts |
119 | _ => NONE) |
173 | _ => NONE) |
120 |> Library.flat |
174 |> Library.flat |
121 |> map (fn (c, ty, syn) => ((c, the ty), the syn)) |
175 |> map (fn (c, ty, syn) => |
122 |> `(fn consts => extract_tyvar_name thy (map (snd o fst) consts)); |
176 ((c, the ty), (Syntax.unlocalize_mixfix o Syntax.fix_mixfix c o the) syn)) |
123 (* fun remove_local_syntax ((c, ty), _) thy = |
177 |> `(fn consts => extract_tyvar_name thy (map (snd o fst) consts)) |
|
178 |-> (fn v => map ((apfst o apsnd) (subst_clsvar v (TFree (v, [])))) |
|
179 #> pair v); |
|
180 fun add_global_const v ((c, ty), syn) thy = |
124 thy |
181 thy |
125 |> Sign.add_syntax_i [(c, ty, Syntax.NoSyn)]; *) |
182 |> Sign.add_consts_i [(c, ty |> subst_clsvar v (TFree (v, Sign.defaultS thy)), syn)] |
126 fun add_global_const ((c, ty), syn) thy = |
183 |> `(fn thy => (c, (Sign.intern_const thy c, ty))) |
|
184 fun add_global_constraint v class (_, (c, ty)) thy = |
127 thy |
185 thy |
128 |> Sign.add_consts_i [(c, ty, syn)] |
186 |> Sign.add_const_constraint_i (c, subst_clsvar v (TVar ((v, 0), [class])) ty); |
129 |> `(fn thy => Sign.intern_const thy c) |
|
130 fun add_axclass bname_axiom locale_pred cs thy = |
|
131 thy |
|
132 |> AxClass.add_axclass_i (bname, Sign.defaultS thy) |
|
133 [Thm.no_attributes (bname_axiom, |
|
134 Const (ObjectLogic.judgment_name thy, dummyT) $ |
|
135 list_comb (Const (locale_pred, dummyT), map (fn c => Const (c, dummyT)) cs) |
|
136 |> curry (inferT_axm thy) "locale_pred" |> snd)] |
|
137 |-> (fn _ => `(fn thy => Sign.intern_class thy bname)) |
|
138 fun print_ctxt ctxt elem = |
187 fun print_ctxt ctxt elem = |
139 map Pretty.writeln (Element.pretty_ctxt ctxt elem) |
188 map Pretty.writeln (Element.pretty_ctxt ctxt elem) |
140 in |
189 in |
141 thy |
190 thy |
142 |> add_locale bname raw_import raw_body |
191 |> add_locale bname raw_import raw_body |
143 |-> (fn ((_, elems : context_i list list), ctxt) => |
192 |-> (fn ((import_elems, body_elems), ctxt) => |
144 tap (fn _ => (map o map) (print_ctxt ctxt) elems) |
193 `(fn thy => Locale.intern thy bname) |
145 #> tap (fn thy => extract_notes_consts thy elems) |
|
146 #> `(fn thy => Locale.intern thy bname) |
|
147 #-> (fn name_locale => |
194 #-> (fn name_locale => |
148 `(fn thy => extract_tyvar_consts thy elems) |
195 `(fn thy => extract_tyvar_consts thy body_elems) |
149 #-> (fn (v, consts) => |
196 #-> (fn (v, c_defs) => |
150 fold_map add_global_const consts |
197 fold_map (add_global_const v) c_defs |
151 #-> (fn cs => |
198 #-> (fn c_adds => |
152 add_axclass (bname ^ "_intro") name_locale cs |
199 AxClass.add_axclass_i (bname, Sign.defaultS thy) |
|
200 (map (Thm.no_attributes o pair "") (extract_assumes c_adds (import_elems @ body_elems))) |
|
201 #-> (fn _ => |
|
202 `(fn thy => Sign.intern_class thy bname) |
153 #-> (fn name_axclass => |
203 #-> (fn name_axclass => |
154 put_class_data name_locale { |
204 fold (add_global_constraint v name_axclass) c_adds |
155 locale_name = name_locale, |
205 #> add_class_data (name_locale, ([], name_locale, name_axclass, v, map snd c_adds)) |
156 axclass_name = name_axclass, |
206 #> tap (fn _ => (map o map) (print_ctxt ctxt) import_elems) |
157 consts = cs, |
207 #> tap (fn _ => (map o map) (print_ctxt ctxt) body_elems) |
158 tycos = [] |
|
159 }) |
|
160 #> fold (add_const name_locale) cs |
|
161 #> pair ctxt |
208 #> pair ctxt |
162 )))) |
209 )))))) |
163 end; |
210 end; |
164 |
211 |
165 in |
212 in |
166 |
213 |
167 val add_class = gen_add_class (Locale.add_locale_context true); |
214 val add_class = gen_add_class (Locale.add_locale_context true); |
168 val add_class_i = gen_add_class (Locale.add_locale_context_i true); |
215 val add_class_i = gen_add_class (Locale.add_locale_context_i true); |
169 |
216 |
170 end; (* local *) |
217 end; (* local *) |
|
218 |
|
219 fun gen_instance_arity prep_arity add_defs tap_def raw_arity raw_defs thy = |
|
220 let |
|
221 val dest_def = Theory.dest_def (Sign.pp thy) handle TERM (msg, _) => error msg; |
|
222 val arity as (tyco, asorts, sort) = prep_arity thy ((fn ((x, y), z) => (x, y, z)) raw_arity); |
|
223 val ty_inst = Type (tyco, map2 (curry TVar o rpair 0) (Term.invent_names [] "'a" (length asorts)) asorts) |
|
224 fun get_c_req class = |
|
225 let |
|
226 val data = get_class_data thy class; |
|
227 val subst_ty = map_type_tfree (fn (var as (v, _)) => |
|
228 if #var data = v then ty_inst else TFree var) |
|
229 in (map (apsnd subst_ty) o #consts) data end; |
|
230 val c_req = (Library.flat o map get_c_req) sort; |
|
231 fun get_remove_contraint c thy = |
|
232 let |
|
233 val ty1 = Sign.the_const_constraint thy c; |
|
234 val ty2 = Sign.the_const_type thy c; |
|
235 in |
|
236 thy |
|
237 |> Sign.add_const_constraint_i (c, ty2) |
|
238 |> pair (c, ty1) |
|
239 end; |
|
240 fun get_c_given thy = map (fst o dest_def o snd o tap_def thy o fst) raw_defs; |
|
241 fun check_defs c_given c_req thy = |
|
242 let |
|
243 fun eq_c ((c1, ty1), (c2, ty2)) = c1 = c2 andalso Sign.typ_instance thy (ty1, ty2) |
|
244 val _ = case fold (remove eq_c) c_given c_req |
|
245 of [] => () |
|
246 | cs => error ("no definition(s) given for" |
|
247 ^ (commas o map (fn (c, ty) => quote (c ^ "::" ^ Sign.string_of_typ thy ty))) cs); |
|
248 val _ = case fold (remove eq_c) c_req c_given |
|
249 of [] => () |
|
250 | cs => error ("superfluous definition(s) given for" |
|
251 ^ (commas o map (fn (c, ty) => quote (c ^ "::" ^ Sign.string_of_typ thy ty))) cs); |
|
252 in thy end; |
|
253 in |
|
254 thy |
|
255 |> fold_map get_remove_contraint (map fst c_req) |
|
256 ||> tap (fn thy => check_defs (get_c_given thy) c_req) |
|
257 ||> add_defs (true, raw_defs) |
|
258 |-> (fn cs => fold Sign.add_const_constraint_i cs) |
|
259 |> AxClass.instance_arity_i arity |
|
260 end; |
|
261 |
|
262 val add_instance_arity = fn x => gen_instance_arity (AxClass.read_arity) IsarThy.add_defs read_axm x; |
|
263 val add_instance_arity_i = fn x => gen_instance_arity (AxClass.cert_arity) IsarThy.add_defs_i (K I) x; |
171 |
264 |
172 |
265 |
173 (* class queries *) |
266 (* class queries *) |
174 |
267 |
175 fun is_class thy cls = lookup_class_data thy cls |> Option.map (not o null o #consts) |> the_default false; |
268 fun is_class thy cls = lookup_class_data thy cls |> Option.map (not o null o #consts) |> the_default false; |