datatype.ML
changeset 211 9b403e123c1b
parent 186 6be2f3e03786
child 215 5f9d7ed4ea0c
equal deleted inserted replaced
210:1a3d3b5b5d15 211:9b403e123c1b
     1 (* Title:       HOL/datatype.ML
     1 (* Title:       HOL/datatype.ML
     2    ID:          $Id$
     2    ID:          $Id$
     3    Author:      Max Breitling, Carsten Clasohm, Tobias Nipkow, Norbert Voelker
     3    Author:      Max Breitling, Carsten Clasohm, Tobias Nipkow, Norbert Voelker
     4    Copyright 1994 TU Muenchen
     4    Copyright 1995 TU Muenchen
     5 *)
     5 *)
     6 
     6 
     7 
     7 
     8 (*used for constructor parameters*)
     8 (*used for constructor parameters*)
     9 datatype dt_type = dtVar of string |
     9 datatype dt_type = dtVar of string |
    21 fun opt_parens s = if s = "" then "" else enclose "(" ")" s; 
    21 fun opt_parens s = if s = "" then "" else enclose "(" ")" s; 
    22 
    22 
    23 (* ----------------------------------------------------------------------- *)
    23 (* ----------------------------------------------------------------------- *)
    24 (* Derivation of the primrec combinator application from the equations     *)
    24 (* Derivation of the primrec combinator application from the equations     *)
    25 
    25 
    26 (* subst. applications fname(ls,xk,rs) by yk(ls,rs) for xk in rargs *)
    26 (* substitute fname(ls,xk,rs) by yk(ls,rs) in t for (xk,yk) in pairs  *) 
    27 
    27 
    28 fun subst_apps (_,_) [] t = t
    28 fun subst_apps (_,_) [] t = t
    29   | subst_apps (fname,cpos) pairs t =
    29   | subst_apps (fname,rpos) pairs t =
    30     let 
    30     let 
    31     fun subst (Abs(a,T,t)) = Abs(a,T,subst t)
    31     fun subst (Abs(a,T,t)) = Abs(a,T,subst t)
    32       | subst (funct $ body) = 
    32       | subst (funct $ body) = 
    33 	let val (f,b) = strip_comb (funct$body)
    33 	let val (f,b) = strip_comb (funct$body)
    34 	in 
    34 	in 
    35 	  if is_Const f andalso fst(dest_Const f) = fname 
    35 	  if is_Const f andalso fst(dest_Const f) = fname 
    36 	    then 
    36 	    then 
    37 	      let val (ls,rest) = (take(cpos,b), drop (cpos,b));
    37 	      let val (ls,rest) = (take(rpos,b), drop(rpos,b));
    38 		val (xk,rs) = (hd rest,tl rest)
    38 		val (xk,rs) = (hd rest,tl rest)
    39 		  handle LIST _ => raise RecError "not enough arguments \
    39 		  handle LIST _ => raise RecError "not enough arguments \
    40 		   \ in recursive application on rhs"
    40 		   \ in recursive application on rhs"
    41               in 
    41               in 
    42 		(case assoc (pairs,xk) of 
    42 		(case assoc (pairs,xk) of 
    43 		   None => raise RecError 
    43 		   None => raise RecError 
    44 		     ("illegal occurence of " ^ fname ^ " on rhs")
    44 		     ("illegal occurence of " ^ fname ^ " on rhs")
    45 		 | Some(U) => list_comb(U,ls @ rs))
    45 		 | Some(U) => list_comb(U,map subst (ls @ rs)))
    46 	      end
    46 	      end
    47 	  else list_comb(f, map subst b)
    47 	  else list_comb(f, map subst b)
    48 	end
    48 	end
    49       | subst(t) = t
    49       | subst(t) = t
    50     in subst t end;
    50     in subst t end;
    51   
    51   
    52 (* abstract rhs *)
    52 (* abstract rhs *)
    53 
    53 
    54 fun abst_rec (fname,cpos,tc,ls,cargs,rs,rhs) =       
    54 fun abst_rec (fname,rpos,tc,ls,cargs,rs,rhs) =       
    55   let val rargs = (map fst o 
    55   let val rargs = (map fst o 
    56 		   (filter (fn (a,T) => is_dtRek T))) (cargs ~~ tc);
    56 		   (filter (fn (a,T) => is_dtRek T))) (cargs ~~ tc);
    57       val subs = map (fn (s,T) => (s,dummyT))
    57       val subs = map (fn (s,T) => (s,dummyT))
    58 	           (rev(rename_wrt_term rhs rargs));
    58 	           (rev(rename_wrt_term rhs rargs));
    59       val subst_rhs = subst_apps (fname,cpos)
    59       val subst_rhs = subst_apps (fname,rpos)
    60 	                (map Free rargs ~~ map Free subs) rhs;
    60 	                (map Free rargs ~~ map Free subs) rhs;
    61       val res = list_abs_free (cargs @ subs @ ls @ rs, subst_rhs);
    61   in 
    62   in
    62       list_abs_free (cargs @ subs @ ls @ rs, subst_rhs) 
    63     if fname mem add_term_names (res,[]) 
       
    64       then raise RecError ("illegal occurence of " ^ fname ^ " on rhs")
       
    65     else res
       
    66   end;
    63   end;
    67 
    64 
    68 (* parsing the prim rec equations *)
    65 (* parsing the prim rec equations *)
    69 
    66 
    70 fun dest_eq ( Const("Trueprop",_) $ (Const ("op =",_) $ lhs $ rhs))
    67 fun dest_eq ( Const("Trueprop",_) $ (Const ("op =",_) $ lhs $ rhs))
    74 fun dest_rec eq = 
    71 fun dest_rec eq = 
    75   let val (lhs,rhs) = dest_eq eq; 
    72   let val (lhs,rhs) = dest_eq eq; 
    76     val (name,args) = strip_comb lhs; 
    73     val (name,args) = strip_comb lhs; 
    77     val (ls',rest)  = take_prefix is_Free args; 
    74     val (ls',rest)  = take_prefix is_Free args; 
    78     val (middle,rs') = take_suffix is_Free rest;
    75     val (middle,rs') = take_suffix is_Free rest;
    79     val cpos = length ls';
    76     val rpos = length ls';
    80     val (c,cargs') = strip_comb (hd middle)
    77     val (c,cargs') = strip_comb (hd middle)
    81       handle LIST "hd" => raise RecError "constructor missing";
    78       handle LIST "hd" => raise RecError "constructor missing";
    82     val (ls,cargs,rs) = (map dest_Free ls', map dest_Free cargs'
    79     val (ls,cargs,rs) = (map dest_Free ls', map dest_Free cargs'
    83 			 , map dest_Free rs')
    80 			 , map dest_Free rs')
    84       handle TERM ("dest_Free",_) => 
    81       handle TERM ("dest_Free",_) => 
    88       raise RecError "more than one non-variable in pattern"
    85       raise RecError "more than one non-variable in pattern"
    89     else if not(null(findrep (map fst (ls @ rs @ cargs)))) then 
    86     else if not(null(findrep (map fst (ls @ rs @ cargs)))) then 
    90       raise RecError "repeated variable name in pattern" 
    87       raise RecError "repeated variable name in pattern" 
    91 	 else (fst(dest_Const name) handle TERM _ => 
    88 	 else (fst(dest_Const name) handle TERM _ => 
    92 	       raise RecError "function is not declared as constant in theory"
    89 	       raise RecError "function is not declared as constant in theory"
    93 		 ,cpos,ls,fst( dest_Const c),cargs,rs,rhs)
    90 		 ,rpos,ls,fst( dest_Const c),cargs,rs,rhs)
    94   end; 
    91   end; 
    95 
    92 
    96 (* check function specified for all constructors and sort function terms *)
    93 (* check function specified for all constructors and sort function terms *)
    97 
    94 
    98 fun check_and_sort (n,its) = 
    95 fun check_and_sort (n,its) = 
   104 (* translate rec equations into function arguments suitable for rec comb *)
   101 (* translate rec equations into function arguments suitable for rec comb *)
   105 (* theory parameter needed for printing error messages                   *) 
   102 (* theory parameter needed for printing error messages                   *) 
   106 
   103 
   107 fun trans_recs _ _ [] = error("No primrec equations.")
   104 fun trans_recs _ _ [] = error("No primrec equations.")
   108   | trans_recs thy cs' (eq1::eqs) = 
   105   | trans_recs thy cs' (eq1::eqs) = 
   109     let val (name1,cpos1,ls1,_,_,_,_) = dest_rec eq1
   106     let val (name1,rpos1,ls1,_,_,_,_) = dest_rec eq1
   110       handle RecError s =>
   107       handle RecError s =>
   111 	error("Primrec definition error: " ^ s ^ ":\n" 
   108 	error("Primrec definition error: " ^ s ^ ":\n" 
   112 	      ^ "   " ^ Sign.string_of_term (sign_of thy) eq1);
   109 	      ^ "   " ^ Sign.string_of_term (sign_of thy) eq1);
   113       val tcs = map (fn (_,c,T,_) => (c,T)) cs';  
   110       val tcs = map (fn (_,c,T,_) => (c,T)) cs';  
   114       val cs = map fst tcs;
   111       val cs = map fst tcs;
   115       fun trans_recs' _ [] = []
   112       fun trans_recs' _ [] = []
   116         | trans_recs' cis (eq::eqs) = 
   113         | trans_recs' cis (eq::eqs) = 
   117 	  let val (name,cpos,ls,c,cargs,rs,rhs) = dest_rec eq; 
   114 	  let val (name,rpos,ls,c,cargs,rs,rhs) = dest_rec eq; 
   118 	    val tc = assoc(tcs,c);
   115 	    val tc = assoc(tcs,c);
   119 	    val i = (1 + find (c,cs))  handle LIST "find" => 0; 
   116 	    val i = (1 + find (c,cs))  handle LIST "find" => 0; 
   120 	  in
   117 	  in
   121 	  if name <> name1 then 
   118 	  if name <> name1 then 
   122 	    raise RecError "function names inconsistent"
   119 	    raise RecError "function names inconsistent"
   123 	  else if cpos <> cpos1 then 
   120 	  else if rpos <> rpos1 then 
   124 	    raise RecError "position of rec. argument inconsistent"
   121 	    raise RecError "position of rec. argument inconsistent"
   125 	  else if i = 0 then 
   122 	  else if i = 0 then 
   126 	    raise RecError "illegal argument in pattern" 
   123 	    raise RecError "illegal argument in pattern" 
   127 	  else if i mem cis then
   124 	  else if i mem cis then
   128 	    raise RecError "constructor already occured as pattern "
   125 	    raise RecError "constructor already occured as pattern "
   129 	       else (i,abst_rec (name,cpos,the tc,ls,cargs,rs,rhs))
   126 	       else (i,abst_rec (name,rpos,the tc,ls,cargs,rs,rhs))
   130 		     :: trans_recs' (i::cis) eqs 
   127 		     :: trans_recs' (i::cis) eqs 
   131 	  end
   128 	  end
   132 	  handle RecError s =>
   129 	  handle RecError s =>
   133 	        error("Primrec definition error\n" ^ s ^ "\n" 
   130 	        error("Primrec definition error\n" ^ s ^ "\n" 
   134 		      ^ "   " ^ Sign.string_of_term (sign_of thy) eq);
   131 		      ^ "   " ^ Sign.string_of_term (sign_of thy) eq);
   442       |> add_consts consts
   439       |> add_consts consts
   443       |> add_trrules xrules
   440       |> add_trrules xrules
   444       |> add_axioms rules,add_primrec)
   441       |> add_axioms rules,add_primrec)
   445     end
   442     end
   446 end
   443 end
       
   444 
       
   445 (*
       
   446 Informal description of functions used in datatype.ML for the Isabelle/HOL
       
   447 implementation of prim. rec. function definitions. (N. Voelker, Feb. 1995) 
       
   448 
       
   449 * subst_apps (fname,rpos) pairs t:
       
   450    substitute the term 
       
   451        fname(ls,xk,rs) 
       
   452    by 
       
   453       yk(ls,rs) 
       
   454    in t for (xk,yk) in pairs, where rpos = length ls. 
       
   455    Applied with : 
       
   456      fname = function name 
       
   457      rpos = position of recursive argument 
       
   458      pairs = list of pairs (xk,yk), where 
       
   459           xk are the rec. arguments of the constructor in the pattern,
       
   460           yk is a variable with name derived from xk 
       
   461      t = rhs of equation 
       
   462 
       
   463 * abst_rec (fname,rpos,tc,ls,cargs,rs,rhs)
       
   464   - filter recursive arguments from constructor arguments cargs,
       
   465   - perform substitutions on rhs, 
       
   466   - derive list subs of new variable names yk for use in subst_apps, 
       
   467   - abstract rhs with respect to cargs, subs, ls and rs. 
       
   468 
       
   469 * dest_eq t 
       
   470   destruct a term denoting an equation into lhs and rhs. 
       
   471 
       
   472 * dest_req eq 
       
   473   destruct an equation of the form 
       
   474       name (vl1..vlrpos, Ci(vi1..vin), vr1..vrn) = rhs
       
   475   into 
       
   476   - function name  (name) 
       
   477   - position of the first non-variable parameter  (rpos)
       
   478   - the list of first rpos parameters (ls = [vl1..vlrpos]) 
       
   479   - the constructor (fst( dest_Const c) = Ci)
       
   480   - the arguments of the constructor (cargs = [vi1..vin])
       
   481   - the rest of the variables in the pattern (rs = [vr1..vrn])
       
   482   - the right hand side of the equation (rhs).  
       
   483  
       
   484 * check_and_sort (n,its)
       
   485   check that  n = length its holds, and sort elements of its by 
       
   486   first component. 
       
   487 
       
   488 * trans_recs thy cs' (eq1::eqs)
       
   489   destruct eq1 into name1, rpos1, ls1, etc.. 
       
   490   get constructor list with and without type (tcs resp. cs) from cs',  
       
   491   for every equation:  
       
   492     destruct it into (name,rpos,ls,c,cargs,rs,rhs)
       
   493     get typed constructor tc from c and tcs 
       
   494     determine the index i of the constructor 
       
   495     check function name and position of rec. argument by comparison
       
   496     with first equation 
       
   497     check for repeated variable names in pattern
       
   498     derive function term f_i which is used as argument of the rec. combinator
       
   499     sort the terms f_i according to i and return them together
       
   500       with the function name and the parameter of the definition (ls). 
       
   501 
       
   502 * Application:
       
   503 
       
   504   The rec. combinator is applied to the function terms resulting from
       
   505   trans_rec. This results in a function which takes the recursive arg. 
       
   506   as first parameter and then the arguments corresponding to ls. The
       
   507   order of parameters is corrected by setting the rhs equal to 
       
   508 
       
   509   list_abs_free
       
   510 	    (ls @ [(tname,dummyT)]
       
   511 	     ,list_comb(rec_comb
       
   512 			, fns @ map Bound (0 ::(length ls downto 1))));
       
   513 
       
   514   Note the de-Bruijn indices counting the number of lambdas between the
       
   515   variable and its binding. 
       
   516 *)