33 val const_of = dest_Const o head_of o fst o dest_eqn; |
34 val const_of = dest_Const o head_of o fst o dest_eqn; |
34 |
35 |
35 fun warn thm = warning ("RecfunCodegen: Not a proper equation:\n" ^ |
36 fun warn thm = warning ("RecfunCodegen: Not a proper equation:\n" ^ |
36 string_of_thm thm); |
37 string_of_thm thm); |
37 |
38 |
38 fun add (p as (thy, thm)) = |
39 fun add optmod (p as (thy, thm)) = |
39 let |
40 let |
40 val tab = CodegenData.get thy; |
41 val tab = CodegenData.get thy; |
41 val (s, _) = const_of (prop_of thm); |
42 val (s, _) = const_of (prop_of thm); |
42 in |
43 in |
43 if Pattern.pattern (lhs_of thm) then |
44 if Pattern.pattern (lhs_of thm) then |
44 (CodegenData.put (Symtab.update ((s, |
45 (CodegenData.put (Symtab.update ((s, |
45 thm :: getOpt (Symtab.lookup (tab, s), [])), tab)) thy, thm) |
46 (thm, optmod) :: getOpt (Symtab.lookup (tab, s), [])), tab)) thy, thm) |
46 else (warn thm; p) |
47 else (warn thm; p) |
47 end handle TERM _ => (warn thm; p); |
48 end handle TERM _ => (warn thm; p); |
48 |
49 |
49 fun del (p as (thy, thm)) = |
50 fun del (p as (thy, thm)) = |
50 let |
51 let |
51 val tab = CodegenData.get thy; |
52 val tab = CodegenData.get thy; |
52 val (s, _) = const_of (prop_of thm); |
53 val (s, _) = const_of (prop_of thm); |
53 in case Symtab.lookup (tab, s) of |
54 in case Symtab.lookup (tab, s) of |
54 NONE => p |
55 NONE => p |
55 | SOME thms => (CodegenData.put (Symtab.update ((s, |
56 | SOME thms => (CodegenData.put (Symtab.update ((s, |
56 gen_rem eq_thm (thms, thm)), tab)) thy, thm) |
57 gen_rem (eq_thm o apfst fst) (thms, thm)), tab)) thy, thm) |
57 end handle TERM _ => (warn thm; p); |
58 end handle TERM _ => (warn thm; p); |
58 |
59 |
59 fun del_redundant thy eqs [] = eqs |
60 fun del_redundant thy eqs [] = eqs |
60 | del_redundant thy eqs (eq :: eqs') = |
61 | del_redundant thy eqs (eq :: eqs') = |
61 let |
62 let |
62 val tsig = Sign.tsig_of (sign_of thy); |
63 val tsig = Sign.tsig_of (sign_of thy); |
63 val matches = curry |
64 val matches = curry |
64 (Pattern.matches tsig o pairself lhs_of) |
65 (Pattern.matches tsig o pairself (lhs_of o fst)) |
65 in del_redundant thy (eq :: eqs) (filter_out (matches eq) eqs') end; |
66 in del_redundant thy (eq :: eqs) (filter_out (matches eq) eqs') end; |
66 |
67 |
67 fun get_equations thy (s, T) = |
68 fun get_equations thy defs (s, T) = |
68 (case Symtab.lookup (CodegenData.get thy, s) of |
69 (case Symtab.lookup (CodegenData.get thy, s) of |
69 NONE => [] |
70 NONE => ([], "") |
70 | SOME thms => preprocess thy (del_redundant thy [] |
71 | SOME thms => |
71 (List.filter (fn thm => is_instance thy T |
72 let val thms' = del_redundant thy [] |
72 (snd (const_of (prop_of thm)))) thms))); |
73 (List.filter (fn (thm, _) => is_instance thy T |
|
74 (snd (const_of (prop_of thm)))) thms) |
|
75 in if null thms' then ([], "") |
|
76 else (preprocess thy (map fst thms'), |
|
77 case snd (snd (split_last thms')) of |
|
78 NONE => (case get_defn thy defs s T of |
|
79 NONE => thyname_of_const s thy |
|
80 | SOME ((_, (thyname, _)), _) => thyname) |
|
81 | SOME thyname => thyname) |
|
82 end); |
73 |
83 |
74 fun mk_poly_id thy (s, T) = mk_const_id (sign_of thy) s ^ |
84 fun mk_suffix thy defs (s, T) = (case get_defn thy defs s T of |
75 (case get_defn thy s T of |
85 SOME (_, SOME i) => "_def" ^ string_of_int i | _ => ""); |
76 SOME (_, SOME i) => "_def" ^ string_of_int i |
|
77 | _ => ""); |
|
78 |
86 |
79 exception EQN of string * typ * string; |
87 exception EQN of string * typ * string; |
80 |
88 |
81 fun cycle g (xs, x) = |
89 fun cycle g (xs, x) = |
82 if x mem xs then xs |
90 if x mem xs then xs |
83 else Library.foldl (cycle g) (x :: xs, List.concat (Graph.find_paths g (x, x))); |
91 else Library.foldl (cycle g) (x :: xs, List.concat (Graph.find_paths g (x, x))); |
84 |
92 |
85 fun add_rec_funs thy gr dep eqs = |
93 fun add_rec_funs thy defs gr dep eqs thyname = |
86 let |
94 let |
87 fun dest_eq t = |
95 fun dest_eq t = (fst (const_of t) ^ mk_suffix thy defs (const_of t), |
88 (mk_poly_id thy (const_of t), dest_eqn (rename_term t)); |
96 dest_eqn (rename_term t)); |
89 val eqs' = map dest_eq eqs; |
97 val eqs' = map dest_eq eqs; |
90 val (dname, _) :: _ = eqs'; |
98 val (dname, _) :: _ = eqs'; |
91 val (s, T) = const_of (hd eqs); |
99 val (s, T) = const_of (hd eqs); |
92 |
100 |
93 fun mk_fundef fname prfx gr [] = (gr, []) |
101 fun mk_fundef thyname fname prfx gr [] = (gr, []) |
94 | mk_fundef fname prfx gr ((fname', (lhs, rhs)) :: xs) = |
102 | mk_fundef thyname fname prfx gr ((fname', (lhs, rhs)) :: xs) = |
95 let |
103 let |
96 val (gr1, pl) = invoke_codegen thy dname false (gr, lhs); |
104 val (gr1, pl) = invoke_codegen thy defs dname thyname false (gr, lhs); |
97 val (gr2, pr) = invoke_codegen thy dname false (gr1, rhs); |
105 val (gr2, pr) = invoke_codegen thy defs dname thyname false (gr1, rhs); |
98 val (gr3, rest) = mk_fundef fname' "and " gr2 xs |
106 val (gr3, rest) = mk_fundef thyname fname' "and " gr2 xs |
99 in |
107 in |
100 (gr3, Pretty.blk (4, [Pretty.str (if fname = fname' then " | " else prfx), |
108 (gr3, Pretty.blk (4, [Pretty.str (if fname = fname' then " | " else prfx), |
101 pl, Pretty.str " =", Pretty.brk 1, pr]) :: rest) |
109 pl, Pretty.str " =", Pretty.brk 1, pr]) :: rest) |
102 end; |
110 end; |
103 |
111 |
104 fun put_code fundef = Graph.map_node dname |
112 fun put_code thyname fundef = Graph.map_node dname |
105 (K (SOME (EQN ("", dummyT, dname)), Pretty.string_of (Pretty.blk (0, |
113 (K (SOME (EQN ("", dummyT, dname)), thyname, Pretty.string_of (Pretty.blk (0, |
106 separate Pretty.fbrk fundef @ [Pretty.str ";"])) ^ "\n\n")); |
114 separate Pretty.fbrk fundef @ [Pretty.str ";"])) ^ "\n\n")); |
107 |
115 |
108 in |
116 in |
109 (case try (Graph.get_node gr) dname of |
117 (case try (Graph.get_node gr) dname of |
110 NONE => |
118 NONE => |
111 let |
119 let |
112 val gr1 = Graph.add_edge (dname, dep) |
120 val gr1 = Graph.add_edge (dname, dep) |
113 (Graph.new_node (dname, (SOME (EQN (s, T, "")), "")) gr); |
121 (Graph.new_node (dname, (SOME (EQN (s, T, "")), "", "")) gr); |
114 val (gr2, fundef) = mk_fundef "" "fun " gr1 eqs'; |
122 val (gr2, fundef) = mk_fundef thyname "" "fun " gr1 eqs'; |
115 val xs = cycle gr2 ([], dname); |
123 val xs = cycle gr2 ([], dname); |
116 val cs = map (fn x => case Graph.get_node gr2 x of |
124 val cs = map (fn x => case Graph.get_node gr2 x of |
117 (SOME (EQN (s, T, _)), _) => (s, T) |
125 (SOME (EQN (s, T, _)), _, _) => (s, T) |
118 | _ => error ("RecfunCodegen: illegal cyclic dependencies:\n" ^ |
126 | _ => error ("RecfunCodegen: illegal cyclic dependencies:\n" ^ |
119 implode (separate ", " xs))) xs |
127 implode (separate ", " xs))) xs |
120 in (case xs of |
128 in (case xs of |
121 [_] => put_code fundef gr2 |
129 [_] => put_code thyname fundef gr2 |
122 | _ => |
130 | _ => |
123 if not (dep mem xs) then |
131 if not (dep mem xs) then |
124 let |
132 let |
125 val eqs'' = map (dest_eq o prop_of) |
133 val thmss as (_, thyname) :: _ = map (get_equations thy defs) cs; |
126 (List.concat (map (get_equations thy) cs)); |
134 val eqs'' = map (dest_eq o prop_of) (List.concat (map fst thmss)); |
127 val (gr3, fundef') = mk_fundef "" "fun " |
135 val (gr3, fundef') = mk_fundef thyname "" "fun " |
128 (Graph.add_edge (dname, dep) |
136 (Graph.add_edge (dname, dep) |
129 (foldr (uncurry Graph.new_node) (Graph.del_nodes xs gr2) |
137 (foldr (uncurry Graph.new_node) (Graph.del_nodes xs gr2) |
130 (map (fn k => |
138 (map (fn k => |
131 (k, (SOME (EQN ("", dummyT, dname)), ""))) xs))) eqs'' |
139 (k, (SOME (EQN ("", dummyT, dname)), thyname, ""))) xs))) eqs'' |
132 in put_code fundef' gr3 end |
140 in put_code thyname fundef' gr3 end |
133 else gr2) |
141 else gr2) |
134 end |
142 end |
135 | SOME (SOME (EQN (_, _, s)), _) => |
143 | SOME (SOME (EQN (_, _, s)), _, _) => |
136 if s = "" then |
144 if s = "" then |
137 if dname = dep then gr else Graph.add_edge (dname, dep) gr |
145 if dname = dep then gr else Graph.add_edge (dname, dep) gr |
138 else if s = dep then gr else Graph.add_edge (s, dep) gr) |
146 else if s = dep then gr else Graph.add_edge (s, dep) gr) |
139 end; |
147 end; |
140 |
148 |
141 fun recfun_codegen thy gr dep brack t = (case strip_comb t of |
149 fun recfun_codegen thy defs gr dep thyname brack t = (case strip_comb t of |
142 (Const (p as (s, T)), ts) => (case (get_equations thy p, get_assoc_code thy s T) of |
150 (Const (p as (s, T)), ts) => (case (get_equations thy defs p, get_assoc_code thy s T) of |
143 ([], _) => NONE |
151 (([], _), _) => NONE |
144 | (_, SOME _) => NONE |
152 | (_, SOME _) => NONE |
145 | (eqns, NONE) => |
153 | ((eqns, thyname'), NONE) => |
146 let val (gr', ps) = foldl_map (invoke_codegen thy dep true) (gr, ts) |
154 let |
|
155 val (gr', ps) = foldl_map |
|
156 (invoke_codegen thy defs dep thyname true) (gr, ts); |
|
157 val suffix = mk_suffix thy defs p |
147 in |
158 in |
148 SOME (add_rec_funs thy gr' dep (map prop_of eqns), |
159 SOME (add_rec_funs thy defs gr' dep (map prop_of eqns) thyname', |
149 mk_app brack (Pretty.str (mk_poly_id thy p)) ps) |
160 mk_app brack (Pretty.str |
|
161 (mk_const_id (sign_of thy) thyname thyname' s ^ suffix)) ps) |
150 end) |
162 end) |
151 | _ => NONE); |
163 | _ => NONE); |
152 |
164 |
153 |
165 |
154 val setup = |
166 val setup = |
155 [CodegenData.init, |
167 [CodegenData.init, |
156 add_codegen "recfun" recfun_codegen, |
168 add_codegen "recfun" recfun_codegen, |
157 add_attribute "" (Args.del |-- Scan.succeed del || Scan.succeed add)]; |
169 add_attribute "" |
|
170 ( Args.del |-- Scan.succeed del |
|
171 || Scan.option (Args.$$$ "target" |-- Args.colon |-- Args.name) >> add)]; |
158 |
172 |
159 end; |
173 end; |