105 | trans_recs thy cs' (eq1::eqs) = |
107 | trans_recs thy cs' (eq1::eqs) = |
106 let val (name1,rpos1,ls1,_,_,_,_) = dest_rec eq1 |
108 let val (name1,rpos1,ls1,_,_,_,_) = dest_rec eq1 |
107 handle RecError s => |
109 handle RecError s => |
108 error("Primrec definition error: " ^ s ^ ":\n" |
110 error("Primrec definition error: " ^ s ^ ":\n" |
109 ^ " " ^ Sign.string_of_term (sign_of thy) eq1); |
111 ^ " " ^ Sign.string_of_term (sign_of thy) eq1); |
110 val tcs = map (fn (_,c,T,_) => (c,T)) cs'; |
112 val tcs = map (fn (_,c,T,_,_) => (c,T)) cs'; |
111 val cs = map fst tcs; |
113 val cs = map fst tcs; |
112 fun trans_recs' _ [] = [] |
114 fun trans_recs' _ [] = [] |
113 | trans_recs' cis (eq::eqs) = |
115 | trans_recs' cis (eq::eqs) = |
114 let val (name,rpos,ls,c,cargs,rs,rhs) = dest_rec eq; |
116 let val (name,rpos,ls,c,cargs,rs,rhs) = dest_rec eq; |
115 val tc = assoc(tcs,c); |
117 val tc = assoc(tcs,c); |
133 , check_and_sort (length cs, trans_recs' [] (eq1::eqs))) |
135 , check_and_sort (length cs, trans_recs' [] (eq1::eqs))) |
134 end ; |
136 end ; |
135 |
137 |
136 in |
138 in |
137 fun add_datatype (typevars, tname, cons_list') thy = |
139 fun add_datatype (typevars, tname, cons_list') thy = |
138 let (*search for free type variables and convert recursive *) |
140 let |
139 fun analyse_types (cons, typlist, syn) = |
141 fun typid(dtRek(_,id)) = id |
|
142 | typid(dtVar s) = implode (tl (explode s)) |
|
143 | typid(dtTyp(_,id)) = id; |
|
144 |
|
145 fun index_vnames(vn::vns,tab) = |
|
146 (case assoc(tab,vn) of |
|
147 None => if vn mem vns |
|
148 then (vn^"1") :: index_vnames(vns,(vn,2)::tab) |
|
149 else vn :: index_vnames(vns,tab) |
|
150 | Some(i) => (vn^(string_of_int i)) :: |
|
151 index_vnames(vns,(vn,i+1)::tab)) |
|
152 | index_vnames([],tab) = []; |
|
153 |
|
154 fun mk_var_names types = index_vnames(map typid types,[]); |
|
155 |
|
156 (*search for free type variables and convert recursive *) |
|
157 fun analyse_types (cons, types, syn) = |
140 let fun analyse(t as dtVar v) = |
158 let fun analyse(t as dtVar v) = |
141 if t mem typevars then t |
159 if t mem typevars then t |
142 else error ("Free type variable " ^ v ^ " on rhs.") |
160 else error ("Free type variable " ^ v ^ " on rhs.") |
143 | analyse(dtTyp(typl,s)) = |
161 | analyse(dtTyp(typl,s)) = |
144 if tname <> s then dtTyp(analyses typl, s) |
162 if tname <> s then dtTyp(analyses typl, s) |
145 else if typevars = typl then dtRek(typl, s) |
163 else if typevars = typl then dtRek(typl, s) |
146 else error (s ^ " used in different ways") |
164 else error (s ^ " used in different ways") |
147 | analyse(dtRek _) = raise Impossible |
165 | analyse(dtRek _) = raise Impossible |
148 and analyses ts = map analyse ts; |
166 and analyses ts = map analyse ts; |
149 in (cons, Syntax.const_name cons syn, analyses typlist, syn) |
167 in (cons, Syntax.const_name cons syn, analyses types, |
150 end; |
168 mk_var_names types, syn) |
|
169 end; |
151 |
170 |
152 (*test if all elements are recursive, i.e. if the type is empty*) |
171 (*test if all elements are recursive, i.e. if the type is empty*) |
153 |
172 |
154 fun non_empty (cs : ('a * 'b * dt_type list * 'c) list) = |
173 fun non_empty (cs : ('a * 'b * dt_type list * 'c *'d) list) = |
155 not(forall (exists is_dtRek o #3) cs) orelse |
174 not(forall (exists is_dtRek o #3) cs) orelse |
156 error("Empty datatype not allowed!"); |
175 error("Empty datatype not allowed!"); |
157 |
176 |
158 val cons_list = map analyse_types cons_list'; |
177 val cons_list = map analyse_types cons_list'; |
159 val dummy = non_empty cons_list; |
178 val dummy = non_empty cons_list; |
163 |
182 |
164 (*generate 'var_n, ..., var_m'*) |
183 (*generate 'var_n, ..., var_m'*) |
165 fun Args(var, delim, n, m) = |
184 fun Args(var, delim, n, m) = |
166 space_implode delim (map (fn n => var^string_of_int(n)) (n upto m)); |
185 space_implode delim (map (fn n => var^string_of_int(n)) (n upto m)); |
167 |
186 |
168 (*generate 'name_1', ..., 'name_n'*) |
187 fun C_exp name vns = name ^ opt_parens(commas vns); |
169 fun C_exp(name, n, var) = |
188 |
170 if n > 0 then name ^ parens(Args(var, ",", 1, n)) else name; |
189 (*Arg_eqs([x1,...,xn],[y1,...,yn]) = "x1 = y1 & ... & xn = yn" *) |
171 |
190 fun arg_eqs vns vns' = |
172 (*generate 'x_n = y_n, ..., x_m = y_m'*) |
191 let fun mkeq(x,x') = x ^ "=" ^ x' |
173 fun Arg_eql(n,m) = |
192 in space_implode " & " (map mkeq (vns~~vns')) end |
174 if n=m then "x" ^ string_of_int(n) ^ "=y" ^ string_of_int(n) |
|
175 else "x" ^ string_of_int(n) ^ "=y" ^ string_of_int(n) ^ " & " ^ |
|
176 Arg_eql(n+1, m); |
|
177 |
193 |
178 (*Pretty printers for type lists; |
194 (*Pretty printers for type lists; |
179 pp_typlist1: parentheses, pp_typlist2: brackets*) |
195 pp_typlist1: parentheses, pp_typlist2: brackets*) |
180 fun pp_typ (dtVar s) = s |
196 fun pp_typ (dtVar s) = s |
181 | pp_typ (dtTyp (typvars, id)) = |
197 | pp_typ (dtTyp (typvars, id)) = |
187 pp_typlist1 ts = if null ts then "" else parens (pp_typlist' ts); |
203 pp_typlist1 ts = if null ts then "" else parens (pp_typlist' ts); |
188 |
204 |
189 fun pp_typlist2 ts = if null ts then "" else brackets (pp_typlist' ts); |
205 fun pp_typlist2 ts = if null ts then "" else brackets (pp_typlist' ts); |
190 |
206 |
191 (* Generate syntax translation for case rules *) |
207 (* Generate syntax translation for case rules *) |
192 fun calc_xrules c_nr y_nr ((_, name, typlist, _) :: cs) = |
208 fun calc_xrules c_nr y_nr ((_, name, _, vns, _) :: cs) = |
193 let val arity = length typlist; |
209 let val arity = length vns; |
194 val body = "z" ^ string_of_int(c_nr); |
210 val body = "z" ^ string_of_int(c_nr); |
195 val args1 = if arity=0 then "" |
211 val args1 = if arity=0 then "" |
196 else parens (Args ("y", ",", y_nr, y_nr+arity-1)); |
212 else parens (Args ("y", ",", y_nr, y_nr+arity-1)); |
197 val args2 = if arity=0 then "" |
213 val args2 = if arity=0 then "" |
198 else "% " ^ Args ("y", " ", y_nr, y_nr+arity-1) |
214 else "% " ^ Args ("y", " ", y_nr, y_nr+arity-1) |
222 in h ^ (assumpt (ts, vs, true)) end |
238 in h ^ (assumpt (ts, vs, true)) end |
223 | assumpt (t :: ts, v :: vs, found) = assumpt (ts, vs, found) |
239 | assumpt (t :: ts, v :: vs, found) = assumpt (ts, vs, found) |
224 | assumpt ([], [], found) = if found then "|] ==>" else "" |
240 | assumpt ([], [], found) = if found then "|] ==>" else "" |
225 | assumpt _ = raise Impossible; |
241 | assumpt _ = raise Impossible; |
226 |
242 |
227 (*insert type with suggested name 'varname' into table*) |
243 fun t_inducting ((_, name, types, vns, _) :: cs) = |
228 fun insert typ varname ((tri as (t, s, n)) :: xs) = |
244 let |
229 if typ = t then (t, s, n+1) :: xs |
245 val h = if null types then " P(" ^ name ^ ")" |
230 else tri :: (if varname = s then insert typ (varname ^ "'") xs |
246 else " !!" ^ (space_implode " " vns) ^ "." ^ |
231 else insert typ varname xs) |
247 (assumpt (types, vns, false)) ^ |
232 | insert typ varname [] = [(typ, varname, 1)]; |
248 "P(" ^ C_exp name vns ^ ")"; |
233 |
|
234 fun typid(dtRek(_,id)) = id |
|
235 | typid(dtVar s) = implode (tl (explode s)) |
|
236 | typid(dtTyp(_,id)) = id; |
|
237 |
|
238 val insert_types = foldl (fn (tab,typ) => insert typ (typid typ) tab); |
|
239 |
|
240 fun update(dtRek _, s, v :: vs, (dtRek _) :: ts) = s :: vs |
|
241 | update(t, s, v :: vs, t1 :: ts) = |
|
242 if t=t1 then s :: vs else v :: (update (t, s, vs, ts)) |
|
243 | update _ = raise Impossible; |
|
244 |
|
245 fun update_n (dtRek r1, s, v :: vs, (dtRek r2) :: ts, n) = |
|
246 if r1 = r2 then (s ^ string_of_int n) :: |
|
247 (update_n (dtRek r1, s, vs, ts, n+1)) |
|
248 else v :: (update_n (dtRek r1, s, vs, ts, n)) |
|
249 | update_n (t, s, v :: vs, t1 :: ts, n) = |
|
250 if t = t1 then (s ^ string_of_int n) :: |
|
251 (update_n (t, s, vs, ts, n+1)) |
|
252 else v :: (update_n (t, s, vs, ts, n)) |
|
253 | update_n (_,_,[],[],_) = [] |
|
254 | update_n _ = raise Impossible; |
|
255 |
|
256 (*insert type variables into table*) |
|
257 fun convert typs = |
|
258 let fun conv(vars, (t, s, n)) = |
|
259 if n=1 then update (t, s, vars, typs) |
|
260 else update_n (t, s, vars, typs, 1) |
|
261 in foldl conv |
|
262 end; |
|
263 |
|
264 fun empty_list n = replicate n ""; |
|
265 |
|
266 fun t_inducting ((_, name, typl, _) :: cs) = |
|
267 let val tab = insert_types([],typl); |
|
268 val arity = length typl; |
|
269 val var_list = convert typl (empty_list arity,tab); |
|
270 val h = if arity = 0 then " P(" ^ name ^ ")" |
|
271 else " !!" ^ (space_implode " " var_list) ^ "." ^ |
|
272 (assumpt (typl, var_list, false)) ^ "P(" ^ |
|
273 name ^ "(" ^ (commas var_list) ^ "))"; |
|
274 val rest = t_inducting cs; |
249 val rest = t_inducting cs; |
275 in if rest = "" then h else h ^ "; " ^ rest end |
250 in if rest = "" then h else h ^ "; " ^ rest end |
276 | t_inducting [] = ""; |
251 | t_inducting [] = ""; |
277 |
252 |
278 fun t_induct cl typ_name = |
253 fun t_induct cl typ_name = |
279 "[|" ^ t_inducting cl ^ "|] ==> P(" ^ typ_name ^ ")"; |
254 "[|" ^ t_inducting cl ^ "|] ==> P(" ^ typ_name ^ ")"; |
280 |
255 |
281 fun gen_typlist typevar f ((_, _, ts, _) :: cs) = |
256 fun gen_typlist typevar f ((_, _, ts, _, _) :: cs) = |
282 let val h = if (length ts) > 0 |
257 let val h = if (length ts) > 0 |
283 then pp_typlist2(f ts) ^ "=>" |
258 then pp_typlist2(f ts) ^ "=>" |
284 else "" |
259 else "" |
285 in h ^ typevar ^ "," ^ (gen_typlist typevar f cs) end |
260 in h ^ typevar ^ "," ^ (gen_typlist typevar f cs) end |
286 | gen_typlist _ _ [] = ""; |
261 | gen_typlist _ _ [] = ""; |
289 (* -------------------------------------------------------------------- *) |
264 (* -------------------------------------------------------------------- *) |
290 (* The case constant and rules *) |
265 (* The case constant and rules *) |
291 |
266 |
292 val t_case = tname ^ "_case"; |
267 val t_case = tname ^ "_case"; |
293 |
268 |
294 fun case_rule n (id, name, ts, _) = |
269 fun case_rule n (id, name, _, vns, _) = |
295 let val args = opt_parens(Args("x", ",", 1, length ts)) |
270 let val args = opt_parens(commas vns) |
296 in (t_case ^ "_" ^ id, |
271 in (t_case ^ "_" ^ id, |
297 t_case ^ "(" ^ Args("f", ",", 1, num_of_cons) |
272 t_case ^ "(" ^ Args("f", ",", 1, num_of_cons) |
298 ^ "," ^ name ^ args |
273 ^ "," ^ name ^ args ^ ") = f"^string_of_int(n) ^ args) |
299 ^ ") = f" ^ string_of_int(n) ^ args) |
|
300 end |
274 end |
301 |
275 |
302 fun case_rules n (c :: cs) = case_rule n c :: case_rules(n+1) cs |
276 fun case_rules n (c :: cs) = case_rule n c :: case_rules(n+1) cs |
303 | case_rules _ [] = []; |
277 | case_rules _ [] = []; |
304 |
278 |
332 |
306 |
333 fun add_reks ts = |
307 fun add_reks ts = |
334 ts @ map (fn _ => dtVar new_tvar_name) (filter is_dtRek ts); |
308 ts @ map (fn _ => dtVar new_tvar_name) (filter is_dtRek ts); |
335 |
309 |
336 (* positions of the dtRek types in a list of dt_types, starting from 1 *) |
310 (* positions of the dtRek types in a list of dt_types, starting from 1 *) |
337 |
311 fun rek_vars ts vns = map snd (filter (is_dtRek o fst) (ts ~~ vns)) |
338 fun rek_pos ts = |
312 |
339 map snd (filter (is_dtRek o fst) (ts ~~ (1 upto length ts))) |
313 fun rec_rule n (id,name,ts,vns,_) = |
340 |
314 let val args = commas vns |
341 fun rec_rule n (id,name,ts,_) = |
|
342 let val args = Args("x",",",1,length ts) |
|
343 val fargs = Args("f",",",1,num_of_cons) |
315 val fargs = Args("f",",",1,num_of_cons) |
344 fun rarg i = "," ^ t_rec ^ parens(fargs ^ "," ^ "x" ^ |
316 fun rarg vn = "," ^ t_rec ^ parens(fargs ^ "," ^ vn) |
345 string_of_int(i)) |
317 val rargs = implode (map rarg (rek_vars ts vns)) |
346 val rargs = implode (map rarg (rek_pos ts)) |
318 in |
347 in |
|
348 ( t_rec ^ "_" ^ id |
319 ( t_rec ^ "_" ^ id |
349 , t_rec ^ parens(fargs ^ "," ^ name ^ (opt_parens args)) ^ " = f" |
320 , t_rec ^ parens(fargs ^ "," ^ name ^ (opt_parens args)) ^ " = f" |
350 ^ string_of_int(n) ^ opt_parens (args ^ rargs)) |
321 ^ string_of_int(n) ^ opt_parens (args ^ rargs)) |
351 end |
322 end |
352 |
323 |
367 @ (if num_of_cons < dtK then [] |
338 @ (if num_of_cons < dtK then [] |
368 else [(tname ^ "_ord", datatype_name ^ "=>nat", NoSyn)]) |
339 else [(tname ^ "_ord", datatype_name ^ "=>nat", NoSyn)]) |
369 @ [case_const,rec_const]; |
340 @ [case_const,rec_const]; |
370 |
341 |
371 |
342 |
372 fun Ci_ing ((id, name, typlist, _) :: cs) = |
343 fun Ci_ing ((id, name, _, vns, _) :: cs) = |
373 let val arity = length typlist; |
344 if null vns then Ci_ing cs |
374 in if arity = 0 then Ci_ing cs |
345 else let val vns' = variantlist(vns,vns) |
375 else ("inject_" ^ id, |
346 in ("inject_" ^ id, |
376 "(" ^ C_exp(name,arity,"x") ^ "=" ^ C_exp(name,arity,"y") |
347 "(" ^ (C_exp name vns) ^ "=" ^ (C_exp name vns') |
377 ^ ") = (" ^ Arg_eql (1, arity) ^ ")") :: (Ci_ing cs) |
348 ^ ") = (" ^ (arg_eqs vns vns') ^ ")") :: (Ci_ing cs) |
378 end |
349 end |
379 | Ci_ing [] = []; |
350 | Ci_ing [] = []; |
380 |
351 |
381 fun Ci_negOne (id1, name1, tl1, _) (id2, name2, tl2, _) = |
352 fun Ci_negOne (id1,name1,_,vns1,_) (id2,name2,_,vns2,_) = |
382 let val ax = C_exp(name1, length tl1, "x") ^ "~=" ^ |
353 let val vns2' = variantlist(vns2,vns1) |
383 C_exp(name2, length tl2, "y") |
354 val ax = C_exp name1 vns1 ^ "~=" ^ C_exp name2 vns2' |
384 in (id1 ^ "_not_" ^ id2, ax) |
355 in (id1 ^ "_not_" ^ id2, ax) end; |
385 end; |
|
386 |
356 |
387 fun Ci_neg1 [] = [] |
357 fun Ci_neg1 [] = [] |
388 | Ci_neg1 (c1::cs) = (map (Ci_negOne c1) cs) @ Ci_neg1 cs; |
358 | Ci_neg1 (c1::cs) = (map (Ci_negOne c1) cs) @ Ci_neg1 cs; |
389 |
359 |
390 fun suc_expr n = |
360 fun suc_expr n = |
391 if n=0 then "0" else "Suc(" ^ suc_expr(n-1) ^ ")"; |
361 if n=0 then "0" else "Suc(" ^ suc_expr(n-1) ^ ")"; |
392 |
362 |
393 fun Ci_neg2() = |
363 fun Ci_neg2() = |
394 let val ord_t = tname ^ "_ord"; |
364 let val ord_t = tname ^ "_ord"; |
395 val cis = cons_list ~~ (0 upto (num_of_cons - 1)) |
365 val cis = cons_list ~~ (0 upto (num_of_cons - 1)) |
396 fun Ci_neg2equals ((id, name, typlist, _), n) = |
366 fun Ci_neg2equals ((id, name, _, vns, _), n) = |
397 let val ax = ord_t ^ "(" ^ (C_exp(name, length typlist, "x")) |
367 let val ax = ord_t ^ "(" ^ (C_exp name vns) ^ ") = " ^ (suc_expr n) |
398 ^ ") = " ^ (suc_expr n) |
|
399 in (ord_t ^ "_" ^ id, ax) end |
368 in (ord_t ^ "_" ^ id, ax) end |
400 in (ord_t ^ "_distinct", ord_t^"(x) ~= "^ord_t^"(y) ==> x ~= y") :: |
369 in (ord_t ^ "_distinct", ord_t^"(x) ~= "^ord_t^"(y) ==> x ~= y") :: |
401 (map Ci_neg2equals cis) |
370 (map Ci_neg2equals cis) |
402 end; |
371 end; |
403 |
372 |