5 *) |
5 *) |
6 |
6 |
7 signature DOMAIN_EXTENDER = |
7 signature DOMAIN_EXTENDER = |
8 sig |
8 sig |
9 val add_domain_cmd: string -> |
9 val add_domain_cmd: string -> |
10 ((string * string option) list * binding * mixfix * |
10 ((string * string option) list * binding * mixfix * |
11 (binding * (bool * binding option * string) list * mixfix) list) list |
11 (binding * (bool * binding option * string) list * mixfix) list) list |
12 -> theory -> theory |
12 -> theory -> theory |
13 val add_domain: string -> |
13 val add_domain: string -> |
14 ((string * string option) list * binding * mixfix * |
14 ((string * string option) list * binding * mixfix * |
15 (binding * (bool * binding option * typ) list * mixfix) list) list |
15 (binding * (bool * binding option * typ) list * mixfix) list) list |
16 -> theory -> theory |
16 -> theory -> theory |
17 end; |
17 end; |
18 |
18 |
19 structure Domain_Extender :> DOMAIN_EXTENDER = |
19 structure Domain_Extender :> DOMAIN_EXTENDER = |
20 struct |
20 struct |
21 |
21 |
22 open Domain_Library; |
22 open Domain_Library; |
23 |
23 |
24 (* ----- general testing and preprocessing of constructor list -------------- *) |
24 (* ----- general testing and preprocessing of constructor list -------------- *) |
25 fun check_and_sort_domain |
25 fun check_and_sort_domain |
26 (dtnvs : (string * typ list) list) |
26 (dtnvs : (string * typ list) list) |
27 (cons'' : (binding * (bool * binding option * typ) list * mixfix) list list) |
27 (cons'' : (binding * (bool * binding option * typ) list * mixfix) list list) |
28 (sg : theory) |
28 (sg : theory) |
29 : ((string * typ list) * |
29 : ((string * typ list) * |
30 (binding * (bool * binding option * typ) list * mixfix) list) list = |
30 (binding * (bool * binding option * typ) list * mixfix) list) list = |
31 let |
31 let |
32 val defaultS = Sign.defaultS sg; |
32 val defaultS = Sign.defaultS sg; |
33 val test_dupl_typs = (case duplicates (op =) (map fst dtnvs) of |
33 val test_dupl_typs = (case duplicates (op =) (map fst dtnvs) of |
34 [] => false | dups => error ("Duplicate types: " ^ commas_quote dups)); |
34 [] => false | dups => error ("Duplicate types: " ^ commas_quote dups)); |
35 val test_dupl_cons = (case duplicates (op =) (map (Binding.name_of o first) (List.concat cons'')) of |
35 val test_dupl_cons = |
36 [] => false | dups => error ("Duplicate constructors: " |
36 (case duplicates (op =) (map (Binding.name_of o first) (List.concat cons'')) of |
37 ^ commas_quote dups)); |
37 [] => false | dups => error ("Duplicate constructors: " |
38 val test_dupl_sels = (case duplicates (op =) (map Binding.name_of (List.mapPartial second |
38 ^ commas_quote dups)); |
39 (List.concat (map second (List.concat cons''))))) of |
39 val test_dupl_sels = |
40 [] => false | dups => error("Duplicate selectors: "^commas_quote dups)); |
40 (case duplicates (op =) (map Binding.name_of (List.mapPartial second |
41 val test_dupl_tvars = exists(fn s=>case duplicates (op =) (map(fst o dest_TFree)s)of |
41 (List.concat (map second (List.concat cons''))))) of |
42 [] => false | dups => error("Duplicate type arguments: " |
42 [] => false | dups => error("Duplicate selectors: "^commas_quote dups)); |
43 ^commas_quote dups)) (map snd dtnvs); |
43 val test_dupl_tvars = |
44 (* test for free type variables, illegal sort constraints on rhs, |
44 exists(fn s=>case duplicates (op =) (map(fst o dest_TFree)s)of |
45 non-pcpo-types and invalid use of recursive type; |
45 [] => false | dups => error("Duplicate type arguments: " |
46 replace sorts in type variables on rhs *) |
46 ^commas_quote dups)) (map snd dtnvs); |
47 fun analyse_equation ((dname,typevars),cons') = |
47 (* test for free type variables, illegal sort constraints on rhs, |
48 let |
48 non-pcpo-types and invalid use of recursive type; |
49 val tvars = map dest_TFree typevars; |
49 replace sorts in type variables on rhs *) |
50 val distinct_typevars = map TFree tvars; |
50 fun analyse_equation ((dname,typevars),cons') = |
51 fun rm_sorts (TFree(s,_)) = TFree(s,[]) |
51 let |
52 | rm_sorts (Type(s,ts)) = Type(s,remove_sorts ts) |
52 val tvars = map dest_TFree typevars; |
53 | rm_sorts (TVar(s,_)) = TVar(s,[]) |
53 val distinct_typevars = map TFree tvars; |
54 and remove_sorts l = map rm_sorts l; |
54 fun rm_sorts (TFree(s,_)) = TFree(s,[]) |
55 val indirect_ok = ["*","Cfun.->","Ssum.++","Sprod.**","Up.u"] |
55 | rm_sorts (Type(s,ts)) = Type(s,remove_sorts ts) |
56 fun analyse indirect (TFree(v,s)) = (case AList.lookup (op =) tvars v of |
56 | rm_sorts (TVar(s,_)) = TVar(s,[]) |
57 NONE => error ("Free type variable " ^ quote v ^ " on rhs.") |
57 and remove_sorts l = map rm_sorts l; |
58 | SOME sort => if eq_set_string (s,defaultS) orelse |
58 val indirect_ok = ["*","Cfun.->","Ssum.++","Sprod.**","Up.u"] |
59 eq_set_string (s,sort ) |
59 fun analyse indirect (TFree(v,s)) = |
60 then TFree(v,sort) |
60 (case AList.lookup (op =) tvars v of |
61 else error ("Inconsistent sort constraint" ^ |
61 NONE => error ("Free type variable " ^ quote v ^ " on rhs.") |
62 " for type variable " ^ quote v)) |
62 | SOME sort => if eq_set_string (s,defaultS) orelse |
63 | analyse indirect (t as Type(s,typl)) = (case AList.lookup (op =) dtnvs s of |
63 eq_set_string (s,sort ) |
64 NONE => if s mem indirect_ok |
64 then TFree(v,sort) |
65 then Type(s,map (analyse false) typl) |
65 else error ("Inconsistent sort constraint" ^ |
66 else Type(s,map (analyse true) typl) |
66 " for type variable " ^ quote v)) |
67 | SOME typevars => if indirect |
67 | analyse indirect (t as Type(s,typl)) = |
68 then error ("Indirect recursion of type " ^ |
68 (case AList.lookup (op =) dtnvs s of |
69 quote (string_of_typ sg t)) |
69 NONE => if s mem indirect_ok |
70 else if dname <> s orelse (** BUG OR FEATURE?: |
70 then Type(s,map (analyse false) typl) |
71 mutual recursion may use different arguments **) |
71 else Type(s,map (analyse true) typl) |
72 remove_sorts typevars = remove_sorts typl |
72 | SOME typevars => if indirect |
73 then Type(s,map (analyse true) typl) |
73 then error ("Indirect recursion of type " ^ |
74 else error ("Direct recursion of type " ^ |
74 quote (string_of_typ sg t)) |
75 quote (string_of_typ sg t) ^ |
75 else if dname <> s orelse |
76 " with different arguments")) |
76 (** BUG OR FEATURE?: |
77 | analyse indirect (TVar _) = Imposs "extender:analyse"; |
77 mutual recursion may use different arguments **) |
78 fun check_pcpo lazy T = |
78 remove_sorts typevars = remove_sorts typl |
79 let val ok = if lazy then cpo_type else pcpo_type |
79 then Type(s,map (analyse true) typl) |
80 in if ok sg T then T else error |
80 else error ("Direct recursion of type " ^ |
81 ("Constructor argument type is not of sort pcpo: " ^ |
81 quote (string_of_typ sg t) ^ |
82 string_of_typ sg T) |
82 " with different arguments")) |
83 end; |
83 | analyse indirect (TVar _) = Imposs "extender:analyse"; |
84 fun analyse_arg (lazy, sel, T) = |
84 fun check_pcpo lazy T = |
85 (lazy, sel, check_pcpo lazy (analyse false T)); |
85 let val ok = if lazy then cpo_type else pcpo_type |
86 fun analyse_con (b, args, mx) = (b, map analyse_arg args, mx); |
86 in if ok sg T then T else error |
87 in ((dname,distinct_typevars), map analyse_con cons') end; |
87 ("Constructor argument type is not of sort pcpo: " ^ |
88 in ListPair.map analyse_equation (dtnvs,cons'') |
88 string_of_typ sg T) |
89 end; (* let *) |
89 end; |
|
90 fun analyse_arg (lazy, sel, T) = |
|
91 (lazy, sel, check_pcpo lazy (analyse false T)); |
|
92 fun analyse_con (b, args, mx) = (b, map analyse_arg args, mx); |
|
93 in ((dname,distinct_typevars), map analyse_con cons') end; |
|
94 in ListPair.map analyse_equation (dtnvs,cons'') |
|
95 end; (* let *) |
90 |
96 |
91 (* ----- calls for building new thy and thms -------------------------------- *) |
97 (* ----- calls for building new thy and thms -------------------------------- *) |
92 |
98 |
93 fun gen_add_domain |
99 fun gen_add_domain |
94 (prep_typ : theory -> 'a -> typ) |
100 (prep_typ : theory -> 'a -> typ) |
95 (comp_dnam : string) |
101 (comp_dnam : string) |
96 (eqs''' : ((string * string option) list * binding * mixfix * |
102 (eqs''' : ((string * string option) list * binding * mixfix * |
97 (binding * (bool * binding option * 'a) list * mixfix) list) list) |
103 (binding * (bool * binding option * 'a) list * mixfix) list) list) |
98 (thy''' : theory) = |
104 (thy''' : theory) = |
99 let |
105 let |
100 fun readS (SOME s) = Syntax.read_sort_global thy''' s |
106 fun readS (SOME s) = Syntax.read_sort_global thy''' s |
101 | readS NONE = Sign.defaultS thy'''; |
107 | readS NONE = Sign.defaultS thy'''; |
102 fun readTFree (a, s) = TFree (a, readS s); |
108 fun readTFree (a, s) = TFree (a, readS s); |
103 |
109 |
104 val dtnvs = map (fn (vs,dname:binding,mx,_) => |
110 val dtnvs = map (fn (vs,dname:binding,mx,_) => |
105 (dname, map readTFree vs, mx)) eqs'''; |
111 (dname, map readTFree vs, mx)) eqs'''; |
106 val cons''' = map (fn (_,_,_,cons) => cons) eqs'''; |
112 val cons''' = map (fn (_,_,_,cons) => cons) eqs'''; |
107 fun thy_type (dname,tvars,mx) = (dname, length tvars, mx); |
113 fun thy_type (dname,tvars,mx) = (dname, length tvars, mx); |
108 fun thy_arity (dname,tvars,mx) = (Sign.full_name thy''' dname, map (snd o dest_TFree) tvars, pcpoS); |
114 fun thy_arity (dname,tvars,mx) = (Sign.full_name thy''' dname, map (snd o dest_TFree) tvars, pcpoS); |
109 val thy'' = thy''' |> Sign.add_types (map thy_type dtnvs) |
115 val thy'' = thy''' |> Sign.add_types (map thy_type dtnvs) |
110 |> fold (AxClass.axiomatize_arity o thy_arity) dtnvs; |
116 |> fold (AxClass.axiomatize_arity o thy_arity) dtnvs; |
111 val cons'' = map (map (upd_second (map (upd_third (prep_typ thy''))))) cons'''; |
117 val cons'' = map (map (upd_second (map (upd_third (prep_typ thy''))))) cons'''; |
112 val dtnvs' = map (fn (dname,vs,mx) => (Sign.full_name thy''' dname,vs)) dtnvs; |
118 val dtnvs' = map (fn (dname,vs,mx) => (Sign.full_name thy''' dname,vs)) dtnvs; |
113 val eqs' : ((string * typ list) * (binding * (bool * binding option * typ) list * mixfix) list) list = check_and_sort_domain dtnvs' cons'' thy''; |
119 val eqs' : ((string * typ list) * (binding * (bool * binding option * typ) list * mixfix) list) list = |
114 val thy' = thy'' |> Domain_Syntax.add_syntax comp_dnam eqs'; |
120 check_and_sort_domain dtnvs' cons'' thy''; |
115 val dts = map (Type o fst) eqs'; |
121 val thy' = thy'' |> Domain_Syntax.add_syntax comp_dnam eqs'; |
116 val new_dts = map (fn ((s,Ts),_) => (s, map (fst o dest_TFree) Ts)) eqs'; |
122 val dts = map (Type o fst) eqs'; |
117 fun strip ss = Library.drop (find_index_eq "'" ss +1, ss); |
123 val new_dts = map (fn ((s,Ts),_) => (s, map (fst o dest_TFree) Ts)) eqs'; |
118 fun typid (Type (id,_)) = |
124 fun strip ss = Library.drop (find_index_eq "'" ss +1, ss); |
|
125 fun typid (Type (id,_)) = |
119 let val c = hd (Symbol.explode (Long_Name.base_name id)) |
126 let val c = hd (Symbol.explode (Long_Name.base_name id)) |
120 in if Symbol.is_letter c then c else "t" end |
127 in if Symbol.is_letter c then c else "t" end |
121 | typid (TFree (id,_) ) = hd (strip (tl (Symbol.explode id))) |
128 | typid (TFree (id,_) ) = hd (strip (tl (Symbol.explode id))) |
122 | typid (TVar ((id,_),_)) = hd (tl (Symbol.explode id)); |
129 | typid (TVar ((id,_),_)) = hd (tl (Symbol.explode id)); |
123 fun one_con (con,args,mx) = |
130 fun one_con (con,args,mx) = |
124 ((Syntax.const_name mx (Binding.name_of con)), |
131 ((Syntax.const_name mx (Binding.name_of con)), |
125 ListPair.map (fn ((lazy,sel,tp),vn) => mk_arg ((lazy, |
132 ListPair.map (fn ((lazy,sel,tp),vn) => mk_arg ((lazy, |
126 DatatypeAux.dtyp_of_typ new_dts tp), |
133 DatatypeAux.dtyp_of_typ new_dts tp), |
127 Option.map Binding.name_of sel,vn)) |
134 Option.map Binding.name_of sel,vn)) |
128 (args,(mk_var_names(map (typid o third) args))) |
135 (args,(mk_var_names(map (typid o third) args))) |
129 ) : cons; |
136 ) : cons; |
130 val eqs = map (fn (dtnvs,cons') => (dtnvs, map one_con cons')) eqs' : eq list; |
137 val eqs = map (fn (dtnvs,cons') => (dtnvs, map one_con cons')) eqs' : eq list; |
131 val thy = thy' |> Domain_Axioms.add_axioms comp_dnam eqs; |
138 val thy = thy' |> Domain_Axioms.add_axioms comp_dnam eqs; |
132 val ((rewss, take_rews), theorems_thy) = thy |> fold_map (fn eq => |
139 val ((rewss, take_rews), theorems_thy) = |
133 Domain_Theorems.theorems (eq, eqs)) eqs |
140 thy |> fold_map (fn eq => Domain_Theorems.theorems (eq, eqs)) eqs |
134 ||>> Domain_Theorems.comp_theorems (comp_dnam, eqs); |
141 ||>> Domain_Theorems.comp_theorems (comp_dnam, eqs); |
135 in |
142 in |
136 theorems_thy |
143 theorems_thy |
137 |> Sign.add_path (Long_Name.base_name comp_dnam) |
144 |> Sign.add_path (Long_Name.base_name comp_dnam) |
138 |> (snd o (PureThy.add_thmss [((Binding.name "rews", List.concat rewss @ take_rews), [])])) |
145 |> (snd o (PureThy.add_thmss [((Binding.name "rews", List.concat rewss @ take_rews), [])])) |
139 |> Sign.parent_path |
146 |> Sign.parent_path |
140 end; |
147 end; |
141 |
148 |
142 val add_domain = gen_add_domain Sign.certify_typ; |
149 val add_domain = gen_add_domain Sign.certify_typ; |
143 val add_domain_cmd = gen_add_domain Syntax.read_typ_global; |
150 val add_domain_cmd = gen_add_domain Syntax.read_typ_global; |
144 |
151 |
145 |
152 |
148 local structure P = OuterParse and K = OuterKeyword in |
155 local structure P = OuterParse and K = OuterKeyword in |
149 |
156 |
150 val _ = OuterKeyword.keyword "lazy"; |
157 val _ = OuterKeyword.keyword "lazy"; |
151 |
158 |
152 val dest_decl : (bool * binding option * string) parser = |
159 val dest_decl : (bool * binding option * string) parser = |
153 P.$$$ "(" |-- Scan.optional (P.$$$ "lazy" >> K true) false -- |
160 P.$$$ "(" |-- Scan.optional (P.$$$ "lazy" >> K true) false -- |
154 (P.binding >> SOME) -- (P.$$$ "::" |-- P.typ) --| P.$$$ ")" >> P.triple1 |
161 (P.binding >> SOME) -- (P.$$$ "::" |-- P.typ) --| P.$$$ ")" >> P.triple1 |
155 || P.$$$ "(" |-- P.$$$ "lazy" |-- P.typ --| P.$$$ ")" |
162 || P.$$$ "(" |-- P.$$$ "lazy" |-- P.typ --| P.$$$ ")" |
156 >> (fn t => (true,NONE,t)) |
163 >> (fn t => (true,NONE,t)) |
157 || P.typ >> (fn t => (false,NONE,t)); |
164 || P.typ >> (fn t => (false,NONE,t)); |
158 |
165 |
159 val cons_decl = |
166 val cons_decl = |
160 P.binding -- Scan.repeat dest_decl -- P.opt_mixfix; |
167 P.binding -- Scan.repeat dest_decl -- P.opt_mixfix; |
161 |
168 |
162 val type_var' : (string * string option) parser = |
169 val type_var' : (string * string option) parser = |
163 (P.type_ident -- Scan.option (P.$$$ "::" |-- P.!!! P.sort)); |
170 (P.type_ident -- Scan.option (P.$$$ "::" |-- P.!!! P.sort)); |
164 |
171 |
165 val type_args' : (string * string option) list parser = |
172 val type_args' : (string * string option) list parser = |
166 type_var' >> single || |
173 type_var' >> single || |
167 P.$$$ "(" |-- P.!!! (P.list1 type_var' --| P.$$$ ")") || |
174 P.$$$ "(" |-- P.!!! (P.list1 type_var' --| P.$$$ ")") || |
168 Scan.succeed []; |
175 Scan.succeed []; |
169 |
176 |
170 val domain_decl = |
177 val domain_decl = |
171 (type_args' -- P.binding -- P.opt_infix) -- |
178 (type_args' -- P.binding -- P.opt_infix) -- |
172 (P.$$$ "=" |-- P.enum1 "|" cons_decl); |
179 (P.$$$ "=" |-- P.enum1 "|" cons_decl); |
173 |
180 |
174 val domains_decl = |
181 val domains_decl = |
175 Scan.option (P.$$$ "(" |-- P.name --| P.$$$ ")") -- |
182 Scan.option (P.$$$ "(" |-- P.name --| P.$$$ ")") -- |
176 P.and_list1 domain_decl; |
183 P.and_list1 domain_decl; |
177 |
184 |
178 fun mk_domain (opt_name : string option, |
185 fun mk_domain (opt_name : string option, |
179 doms : ((((string * string option) list * binding) * mixfix) * |
186 doms : ((((string * string option) list * binding) * mixfix) * |
180 ((binding * (bool * binding option * string) list) * mixfix) list) list ) = |
187 ((binding * (bool * binding option * string) list) * mixfix) list) list ) = |
181 let |
188 let |
182 val names = map (fn (((_, t), _), _) => Binding.name_of t) doms; |
189 val names = map (fn (((_, t), _), _) => Binding.name_of t) doms; |
183 val specs : ((string * string option) list * binding * mixfix * |
190 val specs : ((string * string option) list * binding * mixfix * |
184 (binding * (bool * binding option * string) list * mixfix) list) list = |
191 (binding * (bool * binding option * string) list * mixfix) list) list = |
185 map (fn (((vs, t), mx), cons) => |
192 map (fn (((vs, t), mx), cons) => |
186 (vs, t, mx, map (fn ((c, ds), mx) => (c, ds, mx)) cons)) doms; |
193 (vs, t, mx, map (fn ((c, ds), mx) => (c, ds, mx)) cons)) doms; |
187 val comp_dnam = |
194 val comp_dnam = |
188 case opt_name of NONE => space_implode "_" names | SOME s => s; |
195 case opt_name of NONE => space_implode "_" names | SOME s => s; |
189 in add_domain_cmd comp_dnam specs end; |
196 in add_domain_cmd comp_dnam specs end; |
190 |
197 |
191 val _ = |
198 val _ = |
192 OuterSyntax.command "domain" "define recursive domains (HOLCF)" K.thy_decl |
199 OuterSyntax.command "domain" "define recursive domains (HOLCF)" K.thy_decl |
193 (domains_decl >> (Toplevel.theory o mk_domain)); |
200 (domains_decl >> (Toplevel.theory o mk_domain)); |
194 |
201 |
195 end; |
202 end; |
196 |
203 |
197 end; |
204 end; |