Datatype.ML
changeset 96 d94d0b324b4b
parent 92 bcd0ee8d71aa
child 101 5f99df1e26c4
equal deleted inserted replaced
95:3da472b96f25 96:d94d0b324b4b
     4     Copyright    1994 TU Muenchen
     4     Copyright    1994 TU Muenchen
     5 *)
     5 *)
     6 
     6 
     7 
     7 
     8 (*choice between Ci_neg1 and Ci_neg2 axioms depends on number of constructors*)
     8 (*choice between Ci_neg1 and Ci_neg2 axioms depends on number of constructors*)
     9 local val dtK = 5
     9 local
       
    10 
       
    11 val dtK = 5
       
    12 val pars = parents "(" ")";
       
    13 val brackets = parents "[" "]";
       
    14 
    10 in
    15 in
    11 
    16 
    12 local open ThyParse in
    17 local open ThyParse in
    13 val datatype_decls =
    18 val datatype_decls =
    14   let fun cat s1 s2 = s1 ^ " " ^ s2;
    19   let val mk_list = brackets o commas;
    15 
    20 
    16       val pars = parents "(" ")";
    21       val tvar = type_var >> (fn s => "dtVar" ^ s);
    17       val brackets = parents "[" "]";
       
    18 
       
    19       val mk_list = brackets o commas;
       
    20 
       
    21       val tvar = type_var >> cat "dtVar";
       
    22 
    22 
    23       val type_var_list = 
    23       val type_var_list = 
    24         tvar >> (fn s => [s]) || "(" $$-- list1 tvar --$$ ")";
    24         tvar >> (fn s => [s]) || "(" $$-- list1 tvar --$$ ")";
    25     
    25     
    26       val typ =
    26       val typ =
    27          ident                  >> (cat "dtId" o quote)
    27          ident                  >> (fn s => "dtTyp([]," ^ quote s ^")")
    28         ||
    28         ||
    29          type_var_list -- ident >> (fn (ts, id) => "dtComp (" ^ mk_list ts ^
    29          type_var_list -- ident >> (fn (ts, id) => "dtTyp(" ^ mk_list ts ^
    30   				  ", " ^ quote id ^ ")")
    30   				  "," ^ quote id ^ ")")
    31         ||
    31         ||
    32          tvar;
    32          tvar;
    33     
    33     
    34       val typ_list = "(" $$-- list1 typ --$$ ")" || empty;
    34       val typ_list = "(" $$-- list1 typ --$$ ")" || empty;
    35   
    35   
    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);
   145       val dummy = one_not_rek cons_list;
   122       val dummy = one_not_rek cons_list;
   146 
   123 
   147       (*Pretty printers for type lists;
   124       (*Pretty printers for type lists;
   148         pp_typlist1: parentheses, pp_typlist2: brackets*)
   125         pp_typlist1: parentheses, pp_typlist2: brackets*)
   149       fun pp_typ (dtVar s) = s
   126       fun pp_typ (dtVar s) = s
   150         | pp_typ (dtId s) = s
   127         | pp_typ (dtTyp (typvars, id)) =
   151         | pp_typ (dtComp (typvars, id)) = (pp_typlist1 typvars) ^ id
   128             if null typvars then id else (pp_typlist1 typvars) ^ id
   152         | pp_typ (dtRek (typvars, id)) = (pp_typlist1 typvars) ^ id
   129         | pp_typ (dtRek (typvars, id)) = (pp_typlist1 typvars) ^ id
   153       and
   130       and
   154           pp_typlist' ts = commas (map pp_typ ts)
   131           pp_typlist' ts = commas (map pp_typ ts)
   155       and
   132       and
   156           pp_typlist1 ts = if null ts then "" else pars (pp_typlist' ts);
   133           pp_typlist1 ts = if null ts then "" else pars (pp_typlist' ts);
   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;
   273         | case_typlist _ [] = "";
   243         | case_typlist _ [] = "";
   274 
   244 
   275       fun case_rules t_case arity n ((id, typlist, syn) :: cs) =
   245       fun case_rules t_case arity n ((id, typlist, syn) :: cs) =
   276             let val name = const_name id syn;
   246             let val name = const_name id syn;
   277                 val args = if null typlist then ""
   247                 val args = if null typlist then ""
   278   			   else "(" ^ Args ("x", ",", 1, length typlist) ^ ")"
   248   			   else pars(Args("x", ",", 1, length typlist))
   279             in (t_case ^ "_" ^ id,
   249             in (t_case ^ "_" ^ id,
   280                 t_case ^ "(" ^ name ^ args ^ "," ^ Args ("f", ",", 1, arity) 
   250                 t_case ^ "(" ^ name ^ args ^ "," ^ Args ("f", ",", 1, arity) 
   281                 ^ ") = f" ^ string_of_int(n) ^ args)
   251                 ^ ") = f" ^ string_of_int(n) ^ args)
   282                :: (case_rules t_case arity (n+1) cs)
   252                :: (case_rules t_case arity (n+1) cs)
   283             end
   253             end
   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