42 |
42 |
43 val mk_cons = map (fn ((s, ts), syn) => |
43 val mk_cons = map (fn ((s, ts), syn) => |
44 pars (commas [s, mk_list ts, syn])); |
44 pars (commas [s, mk_list ts, syn])); |
45 |
45 |
46 (*remove all quotes from a string*) |
46 (*remove all quotes from a string*) |
47 fun rem_quotes s = implode (filter (fn c => c <> "\"") (explode s)); |
47 val rem_quotes = implode o filter (fn c => c <> "\"") o explode; |
48 |
48 |
49 (*generate names of ineq axioms*) |
49 (*generate names of distinct axioms*) |
50 fun rules_ineq cs tname = |
50 fun rules_distinct cs tname = |
51 let (*combine all constructor names with all others w/o duplicates*) |
51 let val uqcs = map (fn ((s,_),_) => rem_quotes s) cs; |
52 fun negOne _ [] = [] |
52 (*combine all constructor names with all others w/o duplicates*) |
53 | negOne (c : (string * 'a) * 'b) ((c2 : (string * 'a) * 'b) |
53 fun negOne c = map (fn c2 => quote (c ^ "_not_" ^ c2)); |
54 :: cs) = |
|
55 quote ("ineq_" ^ rem_quotes (#1 (#1 c)) ^ "_" ^ |
|
56 rem_quotes (#1 (#1 c2))) :: negOne c cs; |
|
57 |
|
58 fun neg1 [] = [] |
54 fun neg1 [] = [] |
59 | neg1 (c1 :: cs) = (negOne c1 cs) @ (neg1 cs) |
55 | neg1 (c1 :: cs) = (negOne c1 cs) @ (neg1 cs) |
60 in if length cs < dtK then neg1 cs |
56 in if length uqcs < dtK then neg1 uqcs |
61 else map (fn n => quote (tname ^ "_ord" ^ string_of_int n)) |
57 else quote (tname ^ "_ord_distinct") :: |
62 (0 upto (length cs)) |
58 map (fn c => quote (tname ^ "_ord_" ^ c)) uqcs |
63 end; |
59 end; |
64 |
|
65 fun arg1 ((_, ts), _) = not (null ts); |
|
66 |
60 |
67 (*generate string for calling 'add_datatype'*) |
61 (*generate string for calling 'add_datatype'*) |
68 fun mk_params ((ts, tname), cons) = |
62 fun mk_params ((ts, tname), cons) = |
69 ("|> add_datatype\n" ^ |
63 ("|> add_datatype\n" ^ |
70 pars (commas [mk_list ts, quote tname, mk_list (mk_cons cons)]), |
64 pars (commas [mk_list ts, quote tname, mk_list (mk_cons cons)]), |
71 "structure " ^ tname ^ " =\n\ |
65 "structure " ^ tname ^ " =\n\ |
72 \struct\n\ |
66 \struct\n\ |
73 \ val inject = map (get_axiom thy) " ^ |
67 \ val inject = map (get_axiom thy) " ^ |
74 mk_list (map (fn ((s,_), _) => quote ("inject_" ^ rem_quotes s)) |
68 mk_list (map (fn ((s,_), _) => quote ("inject_" ^ rem_quotes s)) |
75 (filter arg1 cons)) ^ ";\n\ |
69 (filter_out (null o snd o fst) cons)) ^ ";\n\ |
76 \ val ineq = " ^ (if length cons < dtK then "let val ineq' = " else "") |
70 \ val distinct = " ^ (if length cons < dtK then "let val distinct' = " else "") |
77 ^ "map (get_axiom thy) " ^ mk_list (rules_ineq cons tname) ^ |
71 ^ "map (get_axiom thy) " ^ mk_list (rules_distinct cons tname) ^ |
78 (if length cons < dtK then |
72 (if length cons < dtK then |
79 " in ineq' @ (map (fn t => sym COMP (t RS contrapos)) ineq') end" |
73 " in distinct' @ (map (fn t => sym COMP (t RS contrapos)) distinct') end" |
80 else "") ^ ";\n\ |
74 else "") ^ ";\n\ |
81 \ val induct = get_axiom thy \"" ^ tname ^ "_induct\";\n\ |
75 \ val induct = get_axiom thy \"" ^ tname ^ "_induct\";\n\ |
82 \ val cases = map (get_axiom thy) " ^ |
76 \ val cases = map (get_axiom thy) " ^ |
83 mk_list (map (fn ((s,_),_) => |
77 mk_list (map (fn ((s,_),_) => |
84 quote(tname ^ "_case_" ^ rem_quotes s)) cons) ^ ";\n\ |
78 quote(tname ^ "_case_" ^ rem_quotes s)) cons) ^ ";\n\ |
85 \ val simps = inject @ ineq @ cases;\n\ |
79 \ val simps = inject @ distinct @ cases;\n\ |
86 \ fun induct_tac a = res_inst_tac [(" ^ quote tname ^ ", a)] induct;\n\ |
80 \ fun induct_tac a = res_inst_tac[(" ^ quote tname ^ ", a)]induct;\n\ |
87 \end;\n"); |
81 \end;\n"); |
88 in (type_var_list || empty) -- ident --$$ "=" -- constructs >> mk_params end |
82 in (type_var_list || empty) -- ident --$$ "=" -- constructs >> mk_params end |
89 end; |
83 end; |
90 |
84 |
91 (*used for constructor parameters*) |
85 (*used for constructor parameters*) |
92 datatype dt_type = dtVar of string | |
86 datatype dt_type = dtVar of string | |
93 dtId of string | |
87 dtTyp of dt_type list * string | |
94 dtComp of dt_type list * string | |
|
95 dtRek of dt_type list * string; |
88 dtRek of dt_type list * string; |
96 |
89 |
97 local open Syntax.Mixfix |
90 local open Syntax.Mixfix |
98 exception Impossible |
91 exception Impossible |
99 in |
92 in |
100 fun add_datatype (typevars, tname, cons_list') thy = |
93 fun add_datatype (typevars, tname, cons_list') thy = |
101 let fun cat s1 s2 = s1 ^ " " ^ s2; |
94 let (*check if constructor names are unique*) |
102 |
|
103 val pars = parents "(" ")"; |
|
104 val brackets = parents "[" "]"; |
|
105 |
|
106 val mk_list = brackets o commas; |
|
107 |
|
108 (*check if constructor names are unique*) |
|
109 fun check_cons (cs : (string * 'b * 'c) list) = |
95 fun check_cons (cs : (string * 'b * 'c) list) = |
110 (case findrep (map #1 cs) of |
96 (case findrep (map #1 cs) of |
111 [] => true |
97 [] => true |
112 | c::_ => error("Constructor \"" ^ c ^ "\" occurs twice")); |
98 | c::_ => error("Constructor \"" ^ c ^ "\" occurs twice")); |
113 |
99 |
114 (*search for free type variables and convert recursive *) |
100 (*search for free type variables and convert recursive *) |
115 fun analyse_types (cons, typlist, syn) = |
101 fun analyse_types (cons, typlist, syn) = |
116 let fun analyse ((dtVar v) :: typlist) = |
102 let fun analyse(t as dtVar v) = |
117 if ((dtVar v) mem typevars) then |
103 if t mem typevars then t |
118 (dtVar v) :: analyse typlist |
|
119 else error ("Variable " ^ v ^ " is free.") |
104 else error ("Variable " ^ v ^ " is free.") |
120 | analyse ((dtId s) :: typlist) = |
105 | analyse(dtTyp(typl,s)) = |
121 if tname<>s then (dtId s) :: analyse typlist |
106 if tname <> s then dtTyp(analyses typl, s) |
122 else if null typevars then |
107 else if typevars = typl then dtRek(typl, s) |
123 dtRek ([], tname) :: analyse typlist |
|
124 else error (s ^ " used in different ways") |
108 else error (s ^ " used in different ways") |
125 | analyse (dtComp (typl,s) :: typlist) = |
109 | analyse(dtRek _) = raise Impossible |
126 if tname <> s then dtComp (analyse typl, s) |
110 and analyses ts = map analyse ts; |
127 :: analyse typlist |
111 in (cons, analyses typlist, syn) end; |
128 else if typevars = typl then |
|
129 dtRek (typl, s) :: analyse typlist |
|
130 else |
|
131 error (s ^ " used in different ways") |
|
132 | analyse [] = [] |
|
133 | analyse ((dtRek _) :: _) = raise Impossible; |
|
134 in (cons, analyse typlist, syn) end; |
|
135 |
112 |
136 (*test if there are elements that are not recursive, i.e. if the type is |
113 (*test if there are elements that are not recursive, i.e. if the type is |
137 not empty*) |
114 not empty*) |
138 fun one_not_rek (cs : ('a * dt_type list * 'c) list) = |
115 fun one_not_rek (cs : ('a * dt_type list * 'c) list) = |
139 let val contains_no_rek = forall (fn dtRek _ => false | _ => true); |
116 let val contains_no_rek = forall (fn dtRek _ => false | _ => true); |
183 in [("logic", "case x of " ^ first_part) <-> |
160 in [("logic", "case x of " ^ first_part) <-> |
184 ("logic", tname ^ "_case(x, " ^ scnd_part ^ ")" )] |
161 ("logic", tname ^ "_case(x, " ^ scnd_part ^ ")" )] |
185 end; |
162 end; |
186 |
163 |
187 (*type declarations for constructors*) |
164 (*type declarations for constructors*) |
188 fun const_types ((id, typlist, syn) :: cs) = |
165 fun const_type (id, typlist, syn) = |
189 (id, |
166 (id, |
190 (if null typlist then "" else pp_typlist2 typlist ^ " => ") ^ |
167 (if null typlist then "" else pp_typlist2 typlist ^ " => ") ^ |
191 pp_typlist1 typevars ^ tname, syn) |
168 pp_typlist1 typevars ^ tname, syn); |
192 :: const_types cs |
|
193 | const_types [] = []; |
|
194 |
169 |
195 fun create_typevar (dtVar s) typlist = |
170 fun create_typevar (dtVar s) typlist = |
196 if (dtVar s) mem typlist then |
171 if (dtVar s) mem typlist then |
197 create_typevar (dtVar (s ^ "'")) typlist |
172 create_typevar (dtVar (s ^ "'")) typlist |
198 else s |
173 else s |
199 | create_typevar _ _ = raise Impossible; |
174 | create_typevar _ _ = raise Impossible; |
200 |
175 |
201 fun assumpt (dtRek _ :: ts, v :: vs ,found) = |
176 fun assumpt (dtRek _ :: ts, v :: vs ,found) = |
202 let val h = if found then ";P(" ^ v ^ ")" |
177 let val h = if found then ";P(" ^ v ^ ")" else "[| P(" ^ v ^ ")" |
203 else "[| P(" ^ v ^ ")" |
|
204 in h ^ (assumpt (ts, vs, true)) end |
178 in h ^ (assumpt (ts, vs, true)) end |
205 | assumpt (t :: ts, v :: vs, found) = assumpt (ts, vs, found) |
179 | assumpt (t :: ts, v :: vs, found) = assumpt (ts, vs, found) |
206 | assumpt ([], [], found) = if found then "|] ==>" else "" |
180 | assumpt ([], [], found) = if found then "|] ==>" else "" |
207 | assumpt _ = raise Impossible; |
181 | assumpt _ = raise Impossible; |
208 |
182 |
209 (*insert type with suggested name 'varname' into table*) |
183 (*insert type with suggested name 'varname' into table*) |
210 fun insert typ varname ((t, s, n) :: xs) = |
184 fun insert typ varname ((tri as (t, s, n)) :: xs) = |
211 if typ = t then (t, s, n+1) :: xs |
185 if typ = t then (t, s, n+1) :: xs |
212 else if varname = s then (t,s,n) :: (insert typ (varname ^ "'") xs) |
186 else tri :: (if varname = s then insert typ (varname ^ "'") xs |
213 else (t,s,n) :: (insert typ varname xs) |
187 else insert typ varname xs) |
214 | insert typ varname [] = [(typ, varname, 1)]; |
188 | insert typ varname [] = [(typ, varname, 1)]; |
215 |
189 |
216 fun insert_types (dtRek (l,id) :: ts) tab = |
190 fun typid(dtRek(_,id)) = id |
217 insert_types ts (insert (dtRek(l,id)) id tab) |
191 | typid(dtVar s) = implode (tl (explode s)) |
218 | insert_types ((dtVar s) :: ts) tab = |
192 | typid(dtTyp(_,id)) = id; |
219 insert_types ts (insert (dtVar s) (implode (tl (explode s))) tab) |
193 |
220 | insert_types ((dtId s) :: ts) tab = |
194 val insert_types = foldl (fn (tab,typ) => insert typ (typid typ) tab); |
221 insert_types ts (insert (dtId s) s tab) |
|
222 | insert_types (dtComp (l,id) :: ts) tab = |
|
223 insert_types ts (insert (dtComp(l,id)) id tab) |
|
224 | insert_types [] tab = tab; |
|
225 |
195 |
226 fun update(dtRek _, s, v :: vs, (dtRek _) :: ts) = s :: vs |
196 fun update(dtRek _, s, v :: vs, (dtRek _) :: ts) = s :: vs |
227 | update(t, s, v :: vs, t1 :: ts) = |
197 | update(t, s, v :: vs, t1 :: ts) = |
228 if t=t1 then s :: vs |
198 if t=t1 then s :: vs |
229 else v :: (update (t, s, vs, ts)) |
199 else v :: (update (t, s, vs, ts)) |
239 else v :: (update_n (t, s, vs, ts, n)) |
209 else v :: (update_n (t, s, vs, ts, n)) |
240 | update_n (_,_,[],[],_) = [] |
210 | update_n (_,_,[],[],_) = [] |
241 | update_n _ = raise Impossible; |
211 | update_n _ = raise Impossible; |
242 |
212 |
243 (*insert type variables into table*) |
213 (*insert type variables into table*) |
244 fun convert ((t, s, n) :: ts) var_list typ_list = |
214 fun convert typs = |
245 let val h = if n=1 then update (t, s, var_list, typ_list) |
215 let fun conv(vars, (t, s, n)) = |
246 else update_n (t, s, var_list, typ_list, 1) |
216 if n=1 then update (t, s, vars, typs) |
247 in convert ts h typ_list end |
217 else update_n (t, s, vars, typs, 1) |
248 | convert [] var_list _ = var_list; |
218 in foldl conv end; |
249 |
219 |
250 fun empty_list n = replicate n ""; |
220 fun empty_list n = replicate n ""; |
251 |
221 |
252 fun t_inducting ((id, typl, syn) :: cs) = |
222 fun t_inducting ((id, typl, syn) :: cs) = |
253 let val name = const_name id syn; |
223 let val name = const_name id syn; |
254 val tab = insert_types typl []; |
224 val tab = insert_types([],typl); |
255 val arity = length typl; |
225 val arity = length typl; |
256 val var_list = convert tab (empty_list arity) typl; |
226 val var_list = convert typl (empty_list arity,tab); |
257 val h = if arity = 0 then " P(" ^ name ^ ")" |
227 val h = if arity = 0 then " P(" ^ name ^ ")" |
258 else " !!" ^ (space_implode " " var_list) ^ "." ^ |
228 else " !!" ^ (space_implode " " var_list) ^ "." ^ |
259 (assumpt (typl, var_list, false)) ^ "P(" ^ |
229 (assumpt (typl, var_list, false)) ^ "P(" ^ |
260 name ^ "(" ^ (commas var_list) ^ "))"; |
230 name ^ "(" ^ (commas var_list) ^ "))"; |
261 val rest = t_inducting cs; |
231 val rest = t_inducting cs; |
302 :: nil; |
272 :: nil; |
303 val rules = case_rules t_case arity 1 cons_list; |
273 val rules = case_rules t_case arity 1 cons_list; |
304 in (dekl, rules) end; |
274 in (dekl, rules) end; |
305 |
275 |
306 val consts = |
276 val consts = |
307 const_types cons_list |
277 map const_type cons_list |
308 @ (if length cons_list < dtK then [] |
278 @ (if length cons_list < dtK then [] |
309 else [(tname ^ "_ord", datatype_name ^ "=>nat", NoSyn)]) |
279 else [(tname ^ "_ord", datatype_name ^ "=>nat", NoSyn)]) |
310 @ case_const; |
280 @ case_const; |
311 |
281 |
312 (*generate 'var_n, ..., var_m'*) |
282 (*generate 'var_n, ..., var_m'*) |
313 fun Args(var, delim, n, m) = |
283 fun Args(var, delim, n, m) = |
314 space_implode delim (map (fn n => var^string_of_int(n)) (n upto m)); |
284 space_implode delim (map (fn n => var^string_of_int(n)) (n upto m)); |
315 |
285 |
316 (*generate 'name_1', ..., 'name_n'*) |
286 (*generate 'name_1', ..., 'name_n'*) |
317 fun C_exp(name, n, var) = |
287 fun C_exp(name, n, var) = |
318 if n > 0 then name ^ "(" ^ Args (var, ",", 1, n) ^ ")" |
288 if n > 0 then name ^ pars(Args(var, ",", 1, n)) else name; |
319 else name; |
|
320 |
289 |
321 (*generate 'x_n = y_n, ..., x_m = y_m'*) |
290 (*generate 'x_n = y_n, ..., x_m = y_m'*) |
322 fun Arg_eql(n,m) = |
291 fun Arg_eql(n,m) = |
323 if n=m then "x" ^ string_of_int(n) ^ "=y" ^ string_of_int(n) |
292 if n=m then "x" ^ string_of_int(n) ^ "=y" ^ string_of_int(n) |
324 else "x" ^ string_of_int(n) ^ "=y" ^ string_of_int(n) ^ " & " ^ |
293 else "x" ^ string_of_int(n) ^ "=y" ^ string_of_int(n) ^ " & " ^ |
325 Arg_eql(n+1, m); |
294 Arg_eql(n+1, m); |
326 |
295 |
327 fun Ci_ing ((id, typlist, syn) :: cs) = |
296 fun Ci_ing ((id, typlist, syn) :: cs) = |
328 let val name = const_name id syn; |
297 let val name = const_name id syn; |
329 val arity = length typlist; |
298 val arity = length typlist; |
330 in if arity > 0 |
299 in if arity = 0 then Ci_ing cs |
331 then ("inject_" ^ id, |
300 else ("inject_" ^ id, |
332 "(" ^ C_exp(name,arity,"x") ^ "=" ^ C_exp(name,arity,"y") |
301 "(" ^ C_exp(name,arity,"x") ^ "=" ^ C_exp(name,arity,"y") |
333 ^ ") = (" ^ Arg_eql (1, arity) ^ ")") :: (Ci_ing cs) |
302 ^ ") = (" ^ Arg_eql (1, arity) ^ ")") :: (Ci_ing cs) |
334 else (Ci_ing cs) |
|
335 end |
303 end |
336 | Ci_ing [] = []; |
304 | Ci_ing [] = []; |
337 |
305 |
338 fun Ci_negOne _ [] = [] |
306 fun Ci_negOne (id1, tl1, syn1) (id2, tl2, syn2) = |
339 | Ci_negOne c (c1::cs) = |
307 let val name1 = const_name id1 syn1; |
340 let val (id1, tl1, syn1) = c |
|
341 val (id2, tl2, syn2) = c1 |
|
342 val name1 = const_name id1 syn1; |
|
343 val name2 = const_name id2 syn2; |
308 val name2 = const_name id2 syn2; |
344 val arit1 = length tl1 |
309 val ax = C_exp(name1, length tl1, "x") ^ "~=" ^ |
345 val arit2 = length tl2 |
310 C_exp(name2, length tl2, "y") |
346 val h = "(" ^ C_exp(name1, arit1, "x") ^ "~=" ^ |
311 in (id1 ^ "_not_" ^ id2, ax) end; |
347 C_exp(name2, arit2, "y") ^ ")" |
|
348 in ("ineq_" ^ id1 ^ "_" ^ id2, h):: (Ci_negOne c cs) |
|
349 end; |
|
350 |
312 |
351 fun Ci_neg1 [] = [] |
313 fun Ci_neg1 [] = [] |
352 | Ci_neg1 (c1::cs) = Ci_negOne c1 cs @ Ci_neg1 cs; |
314 | Ci_neg1 (c1::cs) = (map (Ci_negOne c1) cs) @ Ci_neg1 cs; |
353 |
315 |
354 fun suc_expr n = |
316 fun suc_expr n = |
355 if n=0 then "0" else "Suc(" ^ suc_expr(n-1) ^ ")"; |
317 if n=0 then "0" else "Suc(" ^ suc_expr(n-1) ^ ")"; |
356 |
318 |
357 fun Ci_neg2equals (ord_t, ((id, typlist, syn) :: cs), n) = |
319 fun Ci_neg2() = |
358 let val name = const_name id syn; |
|
359 val h = ord_t ^ "(" ^ (C_exp(name, length typlist, "x")) |
|
360 ^ ") = " ^ (suc_expr n) |
|
361 in (ord_t ^ (string_of_int (n+1)), h) |
|
362 :: (Ci_neg2equals (ord_t, cs , n+1)) |
|
363 end |
|
364 | Ci_neg2equals (_, [], _) = []; |
|
365 |
|
366 val Ci_neg2 = |
|
367 let val ord_t = tname ^ "_ord"; |
320 let val ord_t = tname ^ "_ord"; |
368 in (Ci_neg2equals (ord_t, cons_list, 0)) @ |
321 val cis = cons_list ~~ (0 upto (length cons_list - 1)) |
369 [(ord_t ^ "0", |
322 fun Ci_neg2equals ((id, typlist, syn), n) = |
370 "(" ^ ord_t ^ "(x) ~= " ^ ord_t ^ "(y)) ==> (x ~= y)")] |
323 let val name = const_name id syn; |
|
324 val ax = ord_t ^ "(" ^ (C_exp(name, length typlist, "x")) |
|
325 ^ ") = " ^ (suc_expr n) |
|
326 in (ord_t ^ "_" ^ id, ax) end |
|
327 in (ord_t ^ "_distinct", ord_t^"(x) ~= "^ord_t^"(y) ==> x ~= y") :: |
|
328 (map Ci_neg2equals cis) |
371 end; |
329 end; |
372 |
330 |
373 val rules_ineq = if length cons_list < dtK then Ci_neg1 cons_list |
331 val rules_distinct = if length cons_list < dtK then Ci_neg1 cons_list |
374 else Ci_neg2; |
332 else Ci_neg2(); |
375 |
333 |
376 val rules_inject = Ci_ing cons_list; |
334 val rules_inject = Ci_ing cons_list; |
377 |
335 |
378 val rule_induct = (tname ^ "_induct", t_induct cons_list tname); |
336 val rule_induct = (tname ^ "_induct", t_induct cons_list tname); |
379 |
337 |
380 val rules = rule_induct :: (rules_inject @ rules_ineq @ rules_case); |
338 val rules = rule_induct :: (rules_inject @ rules_distinct @ rules_case); |
381 in thy |
339 in thy |
382 |> add_types types |
340 |> add_types types |
383 |> add_arities arities |
341 |> add_arities arities |
384 |> add_consts consts |
342 |> add_consts consts |
385 |> add_trrules xrules |
343 |> add_trrules xrules |