datatype.ML
changeset 215 5f9d7ed4ea0c
parent 211 9b403e123c1b
equal deleted inserted replaced
214:8c1afdbea473 215:5f9d7ed4ea0c
     8 (*used for constructor parameters*)
     8 (*used for constructor parameters*)
     9 datatype dt_type = dtVar of string |
     9 datatype dt_type = dtVar of string |
    10   dtTyp of dt_type list * string |
    10   dtTyp of dt_type list * string |
    11   dtRek of dt_type list * string;
    11   dtRek of dt_type list * string;
    12 
    12 
       
    13 structure Datatype =
       
    14 struct
    13 local 
    15 local 
    14 
    16 
    15 val mysort = sort;
    17 val mysort = sort;
    16 open ThyParse HOLogic;
    18 open ThyParse HOLogic;
    17 exception Impossible;
    19 exception Impossible;
   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) 
   209 	in  [("logic", "case x of " ^ first_part) <->
   225 	in  [("logic", "case x of " ^ first_part) <->
   210 	     ("logic", tname ^ "_case(" ^ scnd_part ^ ", x)" )]
   226 	     ("logic", tname ^ "_case(" ^ scnd_part ^ ", x)" )]
   211 	end;
   227 	end;
   212 
   228 
   213      (*type declarations for constructors*)
   229      (*type declarations for constructors*)
   214       fun const_type (id, _, typlist, syn) =
   230       fun const_type (id, _, typlist, _, syn) =
   215 	(id,  
   231 	(id,  
   216 	 (if null typlist then "" else pp_typlist2 typlist ^ " => ") ^
   232 	 (if null typlist then "" else pp_typlist2 typlist ^ " => ") ^
   217 	    pp_typlist1 typevars ^ tname, syn);
   233 	    pp_typlist1 typevars ^ tname, syn);
   218 
   234 
   219 
   235 
   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 
   439       |> add_consts consts
   408       |> add_consts consts
   440       |> add_trrules xrules
   409       |> add_trrules xrules
   441       |> add_axioms rules,add_primrec)
   410       |> add_axioms rules,add_primrec)
   442     end
   411     end
   443 end
   412 end
       
   413 end
   444 
   414 
   445 (*
   415 (*
   446 Informal description of functions used in datatype.ML for the Isabelle/HOL
   416 Informal description of functions used in datatype.ML for the Isabelle/HOL
   447 implementation of prim. rec. function definitions. (N. Voelker, Feb. 1995) 
   417 implementation of prim. rec. function definitions. (N. Voelker, Feb. 1995) 
   448 
   418