| author | wenzelm |
| Tue, 24 Sep 2024 21:31:20 +0200 | |
| changeset 80946 | b76f64d7d493 |
| parent 80734 | 7054a1bc8347 |
| child 81147 | 503e5280ba72 |
| permissions | -rw-r--r-- |
| 79490 | 1 |
|
2 |
signature TIMING_FUNCTIONS = |
|
3 |
sig |
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
4 |
type 'a wctxt = {
|
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
5 |
ctxt: local_theory, |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
6 |
origins: term list, |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
7 |
f: term -> 'a |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
8 |
} |
| 79490 | 9 |
type 'a converter = {
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
10 |
constc : 'a wctxt -> term -> 'a, |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
11 |
funcc : 'a wctxt -> term -> term list -> 'a, |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
12 |
ifc : 'a wctxt -> typ -> term -> term -> term -> 'a, |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
13 |
casec : 'a wctxt -> term -> term list -> 'a, |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
14 |
letc : 'a wctxt -> typ -> term -> string list -> typ list -> term -> 'a |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
15 |
} |
|
79494
c7536609bb9b
translation to time functions now with canonical let.
nipkow
parents:
79490
diff
changeset
|
16 |
val walk : local_theory -> term list -> 'a converter -> term -> 'a |
| 79490 | 17 |
|
|
79494
c7536609bb9b
translation to time functions now with canonical let.
nipkow
parents:
79490
diff
changeset
|
18 |
type pfunc = { names : string list, terms : term list, typs : typ list }
|
| 79490 | 19 |
val fun_pretty': Proof.context -> pfunc -> Pretty.T |
20 |
val fun_pretty: Proof.context -> Function.info -> Pretty.T |
|
21 |
val print_timing': Proof.context -> pfunc -> pfunc -> unit |
|
22 |
val print_timing: Proof.context -> Function.info -> Function.info -> unit |
|
23 |
||
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
24 |
val reg_and_proove_time_func: local_theory -> term list -> term list |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
25 |
-> bool -> Function.info * local_theory |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
26 |
val reg_time_func: local_theory -> term list -> term list |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
27 |
-> bool -> Function.info * local_theory |
| 79490 | 28 |
|
29 |
val time_dom_tac: Proof.context -> thm -> thm list -> int -> tactic |
|
30 |
||
31 |
end |
|
32 |
||
33 |
structure Timing_Functions : TIMING_FUNCTIONS = |
|
34 |
struct |
|
35 |
(* Configure config variable to adjust the prefix *) |
|
36 |
val bprefix = Attrib.setup_config_string @{binding "time_prefix"} (K "T_")
|
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
37 |
(* Configure config variable to adjust the suffix *) |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
38 |
val bsuffix = Attrib.setup_config_string @{binding "time_suffix"} (K "")
|
| 79490 | 39 |
|
40 |
(* some default values to build terms easier *) |
|
41 |
val zero = Const (@{const_name "Groups.zero"}, HOLogic.natT)
|
|
42 |
val one = Const (@{const_name "Groups.one"}, HOLogic.natT)
|
|
43 |
(* Extracts terms from function info *) |
|
44 |
fun terms_of_info (info: Function.info) = |
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
45 |
map Thm.prop_of (case #simps info of SOME s => s |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
46 |
| NONE => error "No terms of function found in info") |
| 79490 | 47 |
|
48 |
type pfunc = {
|
|
|
79494
c7536609bb9b
translation to time functions now with canonical let.
nipkow
parents:
79490
diff
changeset
|
49 |
names : string list, |
| 79490 | 50 |
terms : term list, |
|
79494
c7536609bb9b
translation to time functions now with canonical let.
nipkow
parents:
79490
diff
changeset
|
51 |
typs : typ list |
| 79490 | 52 |
} |
53 |
fun info_pfunc (info: Function.info): pfunc = |
|
54 |
let |
|
55 |
val {defname, fs, ...} = info;
|
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
56 |
val T = case hd fs of (Const (_,T)) => T |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
57 |
| (Free (_,T)) => T |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
58 |
| _ => error "Internal error: Invalid info to print" |
| 79490 | 59 |
in |
|
79494
c7536609bb9b
translation to time functions now with canonical let.
nipkow
parents:
79490
diff
changeset
|
60 |
{ names=[Binding.name_of defname], terms=terms_of_info info, typs=[T] }
|
| 79490 | 61 |
end |
62 |
||
63 |
(* Auxiliary functions for printing functions *) |
|
64 |
fun fun_pretty' ctxt (pfunc: pfunc) = |
|
65 |
let |
|
|
79494
c7536609bb9b
translation to time functions now with canonical let.
nipkow
parents:
79490
diff
changeset
|
66 |
val {names, terms, typs} = pfunc;
|
|
c7536609bb9b
translation to time functions now with canonical let.
nipkow
parents:
79490
diff
changeset
|
67 |
val header_beg = Pretty.str "fun "; |
|
c7536609bb9b
translation to time functions now with canonical let.
nipkow
parents:
79490
diff
changeset
|
68 |
fun prepHeadCont (nm,T) = [Pretty.str (nm ^ " :: "), (Pretty.quote (Syntax.pretty_typ ctxt T))] |
|
c7536609bb9b
translation to time functions now with canonical let.
nipkow
parents:
79490
diff
changeset
|
69 |
val header_content = |
|
c7536609bb9b
translation to time functions now with canonical let.
nipkow
parents:
79490
diff
changeset
|
70 |
List.concat (prepHeadCont (hd names,hd typs) :: map ((fn l => Pretty.str "\nand " :: l) o prepHeadCont) (ListPair.zip (tl names, tl typs))); |
|
c7536609bb9b
translation to time functions now with canonical let.
nipkow
parents:
79490
diff
changeset
|
71 |
val header_end = Pretty.str " where\n "; |
|
c7536609bb9b
translation to time functions now with canonical let.
nipkow
parents:
79490
diff
changeset
|
72 |
val header = [header_beg] @ header_content @ [header_end]; |
| 79490 | 73 |
fun separate sep prts = |
74 |
flat (Library.separate [Pretty.str sep] (map single prts)); |
|
75 |
val ptrms = (separate "\n| " (map (Syntax.pretty_term ctxt) terms)); |
|
76 |
in |
|
77 |
Pretty.text_fold (header @ ptrms) |
|
78 |
end |
|
79 |
fun fun_pretty ctxt = fun_pretty' ctxt o info_pfunc |
|
80 |
fun print_timing' ctxt (opfunc: pfunc) (tpfunc: pfunc) = |
|
81 |
let |
|
|
79494
c7536609bb9b
translation to time functions now with canonical let.
nipkow
parents:
79490
diff
changeset
|
82 |
val {names, ...} = opfunc;
|
| 79490 | 83 |
val poriginal = Pretty.item [Pretty.str "Original function:\n", fun_pretty' ctxt opfunc] |
84 |
val ptiming = Pretty.item [Pretty.str ("Running time function:\n"), fun_pretty' ctxt tpfunc]
|
|
85 |
in |
|
|
79494
c7536609bb9b
translation to time functions now with canonical let.
nipkow
parents:
79490
diff
changeset
|
86 |
Pretty.writeln (Pretty.text_fold [Pretty.str ("Converting " ^ (hd names) ^ (String.concat (map (fn nm => ", " ^ nm) (tl names))) ^ "\n"), poriginal, Pretty.str "\n", ptiming])
|
| 79490 | 87 |
end |
88 |
fun print_timing ctxt (oinfo: Function.info) (tinfo: Function.info) = |
|
89 |
print_timing' ctxt (info_pfunc oinfo) (info_pfunc tinfo) |
|
90 |
||
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
91 |
fun contains l e = exists (fn e' => e' = e) l |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
92 |
fun contains' comp l e = exists (comp e) l |
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
93 |
fun index [] _ = 0 |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
94 |
| index (x::xs) el = (if x = el then 0 else 1 + index xs el) |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
95 |
fun used_for_const orig_used t i = orig_used (t,i) |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
96 |
(* Split name by . *) |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
97 |
val split_name = String.fields (fn s => s = #".") |
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
98 |
|
| 79490 | 99 |
(* returns true if it's an if term *) |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
100 |
fun is_if (Const (@{const_name "HOL.If"},_)) = true
|
| 79490 | 101 |
| is_if _ = false |
102 |
(* returns true if it's a case term *) |
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
103 |
fun is_case (Const (n,_)) = n |> split_name |> List.last |> String.isPrefix "case_" |
| 79490 | 104 |
| is_case _ = false |
105 |
(* returns true if it's a let term *) |
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
106 |
fun is_let (Const (@{const_name "HOL.Let"},_)) = true
|
| 79490 | 107 |
| is_let _ = false |
108 |
(* change type of original function to new type (_ \<Rightarrow> ... \<Rightarrow> _ to _ \<Rightarrow> ... \<Rightarrow> nat) |
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
109 |
and replace all function arguments f with (t*T_f) if used *) |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
110 |
fun change_typ' used (Type ("fun", [T1, T2])) =
|
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
111 |
Type ("fun", [check_for_fun' (used 0) T1, change_typ' (fn i => used (i+1)) T2])
|
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
112 |
| change_typ' _ _ = HOLogic.natT |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
113 |
and check_for_fun' true (f as Type ("fun", [_,_])) = HOLogic.mk_prodT (f, change_typ' (K false) f)
|
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
114 |
| check_for_fun' false (f as Type ("fun", [_,_])) = change_typ' (K false) f
|
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
115 |
| check_for_fun' _ t = t |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
116 |
val change_typ = change_typ' (K false) |
| 79490 | 117 |
(* Convert string name of function to its timing equivalent *) |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
118 |
fun fun_name_to_time ctxt s name = |
| 79490 | 119 |
let |
120 |
val prefix = Config.get ctxt bprefix |
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
121 |
val suffix = (if s then Config.get ctxt bsuffix else "") |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
122 |
fun replace_last_name [n] = [prefix ^ n ^ suffix] |
| 79490 | 123 |
| replace_last_name (n::ns) = n :: (replace_last_name ns) |
124 |
| replace_last_name _ = error "Internal error: Invalid function name to convert" |
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
125 |
val parts = split_name name |
| 79490 | 126 |
in |
127 |
String.concatWith "." (replace_last_name parts) |
|
128 |
end |
|
129 |
(* Count number of arguments of a function *) |
|
130 |
fun count_args (Type (n, [_,res])) = (if n = "fun" then 1 + count_args res else 0) |
|
131 |
| count_args _ = 0 |
|
132 |
(* Check if number of arguments matches function *) |
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
133 |
val _ = dest_Const |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
134 |
fun check_args s (t, args) = |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
135 |
(if length args = count_args (type_of t) then () |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
136 |
else error ("Partial applications/Lambdas not allowed (" ^ s ^ ")"))
|
| 79490 | 137 |
(* Removes Abs *) |
138 |
fun rem_abs f (Abs (_,_,t)) = rem_abs f t |
|
139 |
| rem_abs f t = f t |
|
140 |
(* Map right side of equation *) |
|
141 |
fun map_r f (pT $ (eq $ l $ r)) = (pT $ (eq $ l $ f r)) |
|
142 |
| map_r _ _ = error "Internal error: No right side of equation found" |
|
143 |
(* Get left side of equation *) |
|
144 |
fun get_l (_ $ (_ $ l $ _)) = l |
|
145 |
| get_l _ = error "Internal error: No left side of equation found" |
|
146 |
(* Get right side of equation *) |
|
147 |
fun get_r (_ $ (_ $ _ $ r)) = r |
|
148 |
| get_r _ = error "Internal error: No right side of equation found" |
|
149 |
(* Return name of Const *) |
|
150 |
fun Const_name (Const (nm,_)) = SOME nm |
|
151 |
| Const_name _ = NONE |
|
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
152 |
fun is_Used (Type ("Product_Type.prod", _)) = true
|
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
153 |
| is_Used _ = false |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
154 |
(* Custom compare function for types ignoring variable names *) |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
155 |
fun typ_comp (Type (A,a)) (Type (B,b)) = (A = B) andalso List.foldl (fn ((c,i),s) => typ_comp c i andalso s) true (ListPair.zip (a, b)) |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
156 |
| typ_comp (Type _) _ = false |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
157 |
| typ_comp _ (Type _) = false |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
158 |
| typ_comp _ _ = true |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
159 |
fun const_comp (Const (nm,T)) (Const (nm',T')) = nm = nm' andalso typ_comp T T' |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
160 |
| const_comp _ _ = false |
| 79490 | 161 |
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
162 |
fun time_term ctxt s (Const (nm,T)) = |
| 79490 | 163 |
let |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
164 |
val T_nm = fun_name_to_time ctxt s nm |
| 79490 | 165 |
val T_T = change_typ T |
166 |
in |
|
167 |
(SOME (Syntax.check_term ctxt (Const (T_nm,T_T)))) |
|
168 |
handle (ERROR _) => |
|
169 |
case Syntax.read_term ctxt (Long_Name.base_name T_nm) |
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
170 |
of (Const (T_nm,T_T)) => |
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
171 |
let |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
172 |
fun col_Used i (Type ("fun", [Type ("fun", _), Ts])) (Type ("fun", [T', Ts'])) =
|
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
173 |
(if is_Used T' then [i] else []) @ col_Used (i+1) Ts Ts' |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
174 |
| col_Used i (Type ("fun", [_, Ts])) (Type ("fun", [_, Ts'])) = col_Used (i+1) Ts Ts'
|
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
175 |
| col_Used _ _ _ = [] |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
176 |
in |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
177 |
SOME (Const (T_nm,change_typ' (contains (col_Used 0 T T_T)) T)) |
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
178 |
end |
| 79490 | 179 |
| _ => error ("Timing function of " ^ nm ^ " is not defined")
|
180 |
end |
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
181 |
| time_term _ _ _ = error "Internal error: No valid function given" |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
182 |
|
| 79490 | 183 |
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
184 |
type 'a wctxt = {
|
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
185 |
ctxt: local_theory, |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
186 |
origins: term list, |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
187 |
f: term -> 'a |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
188 |
} |
| 79490 | 189 |
type 'a converter = {
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
190 |
constc : 'a wctxt -> term -> 'a, |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
191 |
funcc : 'a wctxt -> term -> term list -> 'a, |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
192 |
ifc : 'a wctxt -> typ -> term -> term -> term -> 'a, |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
193 |
casec : 'a wctxt -> term -> term list -> 'a, |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
194 |
letc : 'a wctxt -> typ -> term -> string list -> typ list -> term -> 'a |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
195 |
} |
| 79490 | 196 |
|
197 |
(* Walks over term and calls given converter *) |
|
198 |
fun walk_func (t1 $ t2) ts = walk_func t1 (t2::ts) |
|
199 |
| walk_func t ts = (t, ts) |
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
200 |
fun walk_func' t = walk_func t [] |
| 79490 | 201 |
fun build_func (f, []) = f |
202 |
| build_func (f, (t::ts)) = build_func (f$t, ts) |
|
203 |
fun walk_abs (Abs (nm,T,t)) nms Ts = walk_abs t (nm::nms) (T::Ts) |
|
204 |
| walk_abs t nms Ts = (t, nms, Ts) |
|
205 |
fun build_abs t (nm::nms) (T::Ts) = build_abs (Abs (nm,T,t)) nms Ts |
|
206 |
| build_abs t [] [] = t |
|
207 |
| build_abs _ _ _ = error "Internal error: Invalid terms to build abs" |
|
|
79494
c7536609bb9b
translation to time functions now with canonical let.
nipkow
parents:
79490
diff
changeset
|
208 |
fun walk ctxt (origin: term list) (conv as {ifc, casec, funcc, letc, ...} : 'a converter) (t as _ $ _) =
|
| 79490 | 209 |
let |
210 |
val (f, args) = walk_func t [] |
|
211 |
val this = (walk ctxt origin conv) |
|
212 |
val _ = (case f of Abs _ => error "Lambdas not supported" | _ => ()) |
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
213 |
val wctxt = {ctxt = ctxt, origins = origin, f = this}
|
| 79490 | 214 |
in |
215 |
(if is_if f then |
|
216 |
(case f of (Const (_,T)) => |
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
217 |
(case args of [cond, t, f] => ifc wctxt T cond t f |
| 79490 | 218 |
| _ => error "Partial applications not supported (if)") |
219 |
| _ => error "Internal error: invalid if term") |
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
220 |
else if is_case f then casec wctxt f args |
| 79490 | 221 |
else if is_let f then |
222 |
(case f of (Const (_,lT)) => |
|
223 |
(case args of [exp, t] => |
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
224 |
let val (t,nms,Ts) = walk_abs t [] [] in letc wctxt lT exp nms Ts t end |
| 79490 | 225 |
| _ => error "Partial applications not allowed (let)") |
226 |
| _ => error "Internal error: invalid let term") |
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
227 |
else funcc wctxt f args) |
| 79490 | 228 |
end |
229 |
| walk ctxt origin (conv as {constc, ...}) c =
|
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
230 |
constc {ctxt = ctxt, origins = origin, f = walk ctxt origin conv} c
|
| 79490 | 231 |
|
232 |
(* 1. Fix all terms *) |
|
233 |
(* Exchange Var in types and terms to Free *) |
|
234 |
fun fixTerms (Var(ixn,T)) = Free (fst ixn, T) |
|
235 |
| fixTerms t = t |
|
236 |
fun fixTypes (TVar ((t, _), T)) = TFree (t, T) |
|
237 |
| fixTypes t = t |
|
| 79542 | 238 |
|
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
239 |
fun noFun (Type ("fun", _)) = error "Functions in datatypes are not allowed in case constructions"
|
|
80643
11b8f2e4c3d2
branches of case expressions may need to be eta-expanded
nipkow
parents:
80636
diff
changeset
|
240 |
| noFun T = T |
| 79490 | 241 |
fun casecBuildBounds n t = if n > 0 then casecBuildBounds (n-1) (t $ (Bound (n-1))) else t |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
242 |
fun casecAbs wctxt n (Type ("fun",[T,Tr])) (Abs (v,Ta,t)) = (map_atyps noFun T; Abs (v,Ta,casecAbs wctxt n Tr t))
|
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
243 |
| casecAbs wctxt n (Type ("fun",[T,Tr])) t =
|
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
244 |
(map_atyps noFun T; Abs ("uu",T,casecAbs wctxt (n + 1) Tr t))
|
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
245 |
| casecAbs wctxt n _ t = (#f wctxt) (casecBuildBounds n (Term.incr_bv n 0 t)) |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
246 |
fun fixCasecCases _ _ [t] = [t] |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
247 |
| fixCasecCases wctxt (Type (_,[T,Tr])) (t::ts) = casecAbs wctxt 0 T t :: fixCasecCases wctxt Tr ts |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
248 |
| fixCasecCases _ _ _ = error "Internal error: invalid case types/terms" |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
249 |
fun fixCasec wctxt (t as Const (_,T)) args = |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
250 |
(check_args "cases" (t,args); build_func (t,fixCasecCases wctxt T args)) |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
251 |
| fixCasec _ _ _ = error "Internal error: invalid case term" |
| 79490 | 252 |
|
|
79494
c7536609bb9b
translation to time functions now with canonical let.
nipkow
parents:
79490
diff
changeset
|
253 |
fun fixPartTerms ctxt (term: term list) t = |
| 79490 | 254 |
let |
255 |
val _ = check_args "args" (walk_func (get_l t) []) |
|
256 |
in |
|
257 |
map_r (walk ctxt term {
|
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
258 |
funcc = (fn wctxt => fn t => fn args => |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
259 |
(check_args "func" (t,args); build_func (t, map (#f wctxt) args))), |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
260 |
constc = (fn _ => fn c => (case c of Abs _ => error "Lambdas not supported" | _ => c)), |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
261 |
ifc = (fn wctxt => fn T => fn cond => fn tt => fn tf => |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
262 |
((Const (@{const_name "HOL.If"}, T)) $ (#f wctxt) cond $ ((#f wctxt) tt) $ ((#f wctxt) tf))),
|
| 79490 | 263 |
casec = fixCasec, |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
264 |
letc = (fn wctxt => fn expT => fn exp => fn nms => fn Ts => fn t => |
| 79490 | 265 |
let |
266 |
val f' = if length nms = 0 then |
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
267 |
(case (#f wctxt) (t$exp) of t$_ => t | _ => error "Internal error: case could not be fixed (let)") |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
268 |
else (#f wctxt) t |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
269 |
in (Const (@{const_name "HOL.Let"},expT) $ ((#f wctxt) exp) $ build_abs f' nms Ts) end)
|
| 79490 | 270 |
}) t |
271 |
end |
|
272 |
||
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
273 |
(* 2. Check for properties about the function *) |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
274 |
(* 2.1 Check if function is recursive *) |
| 79490 | 275 |
fun or f (a,b) = f a orelse b |
276 |
fun find_rec ctxt term = (walk ctxt term {
|
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
277 |
funcc = (fn wctxt => fn t => fn args => |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
278 |
List.exists (fn term => (Const_name t) = (Const_name term)) term |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
279 |
orelse List.foldr (or (#f wctxt)) false args), |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
280 |
constc = (K o K) false, |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
281 |
ifc = (fn wctxt => fn _ => fn cond => fn tt => fn tf => |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
282 |
(#f wctxt) cond orelse (#f wctxt) tt orelse (#f wctxt) tf), |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
283 |
casec = (fn wctxt => fn t => fn cs => |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
284 |
(#f wctxt) t orelse List.foldr (or (rem_abs (#f wctxt))) false cs), |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
285 |
letc = (fn wctxt => fn _ => fn exp => fn _ => fn _ => fn t => |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
286 |
(#f wctxt) exp orelse (#f wctxt) t) |
| 79490 | 287 |
}) o get_r |
|
79494
c7536609bb9b
translation to time functions now with canonical let.
nipkow
parents:
79490
diff
changeset
|
288 |
fun is_rec ctxt (term: term list) = List.foldr (or (find_rec ctxt term)) false |
| 79490 | 289 |
|
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
290 |
(* 2.2 Check for higher-order function if original function is used *) |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
291 |
fun find_used' ctxt term t T_t = |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
292 |
let |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
293 |
val (ident, _) = walk_func (get_l t) [] |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
294 |
val (T_ident, T_args) = walk_func (get_l T_t) [] |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
295 |
|
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
296 |
fun filter_passed [] = [] |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
297 |
| filter_passed ((f as Free (_, Type ("Product_Type.prod",[Type ("fun",_), Type ("fun", _)])))::args) =
|
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
298 |
f :: filter_passed args |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
299 |
| filter_passed (_::args) = filter_passed args |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
300 |
val frees' = (walk ctxt term {
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
301 |
funcc = (fn wctxt => fn t => fn args => |
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
302 |
(case t of (Const ("Product_Type.prod.snd", _)) => []
|
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
303 |
| _ => (if t = T_ident then [] else filter_passed args) |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
304 |
@ List.foldr (fn (l,r) => (#f wctxt) l @ r) [] args)), |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
305 |
constc = (K o K) [], |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
306 |
ifc = (fn wctxt => fn _ => fn cond => fn tt => fn tf => (#f wctxt) cond @ (#f wctxt) tt @ (#f wctxt) tf), |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
307 |
casec = (fn wctxt => fn _ => fn cs => List.foldr (fn (l,r) => (#f wctxt) l @ r) [] cs), |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
308 |
letc = (fn wctxt => fn _ => fn exp => fn _ => fn _ => fn t => (#f wctxt) exp @ (#f wctxt) t) |
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
309 |
}) (get_r T_t) |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
310 |
fun build _ [] _ = false |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
311 |
| build i (a::args) item = |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
312 |
(if item = (ident,i) then contains frees' a else build (i+1) args item) |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
313 |
in |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
314 |
build 0 T_args |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
315 |
end |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
316 |
fun find_used ctxt term terms T_terms = |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
317 |
ListPair.zip (terms, T_terms) |
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
318 |
|> List.map (fn (t, T_t) => find_used' ctxt term t T_t) |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
319 |
|> List.foldr (fn (f,g) => fn item => f item orelse g item) (K false) |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
320 |
|
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
321 |
|
| 79490 | 322 |
(* 3. Convert equations *) |
323 |
(* Some Helper *) |
|
324 |
val plusTyp = @{typ "nat => nat => nat"}
|
|
325 |
fun plus (SOME a) (SOME b) = SOME (Const (@{const_name "Groups.plus"}, plusTyp) $ a $ b)
|
|
326 |
| plus (SOME a) NONE = SOME a |
|
327 |
| plus NONE (SOME b) = SOME b |
|
328 |
| plus NONE NONE = NONE |
|
329 |
fun opt_term NONE = HOLogic.zero |
|
330 |
| opt_term (SOME t) = t |
|
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
331 |
fun use_origin (Free (nm, T as Type ("fun",_))) = HOLogic.mk_fst (Free (nm,HOLogic.mk_prodT (T, change_typ T)))
|
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
332 |
| use_origin t = t |
| 79490 | 333 |
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
334 |
(* Conversion of function term *) |
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
335 |
fun fun_to_time ctxt orig_used _ (origin: term list) (func as Const (nm,T)) = |
| 79490 | 336 |
let |
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
337 |
val used' = used_for_const orig_used func |
| 79490 | 338 |
in |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
339 |
if contains' const_comp origin func then SOME (Free (func |> Term.term_name |> fun_name_to_time ctxt true, change_typ' used' T)) else |
| 79490 | 340 |
if Zero_Funcs.is_zero (Proof_Context.theory_of ctxt) (nm,T) then NONE else |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
341 |
time_term ctxt false func |
| 79490 | 342 |
end |
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
343 |
| fun_to_time ctxt _ used _ (f as Free (nm,T)) = SOME ( |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
344 |
if used f then HOLogic.mk_snd (Free (nm,HOLogic.mk_prodT (T,change_typ T))) |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
345 |
else Free (fun_name_to_time ctxt false nm, change_typ T) |
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
346 |
) |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
347 |
| fun_to_time _ _ _ _ _ = error "Internal error: invalid function to convert" |
| 79490 | 348 |
|
349 |
(* Convert arguments of left side of a term *) |
|
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
350 |
fun conv_arg ctxt used _ (f as Free (nm,T as Type("fun",_))) =
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
351 |
if used f then Free (nm, HOLogic.mk_prodT (T, change_typ' (K false) T)) |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
352 |
else Free (fun_name_to_time ctxt false nm, change_typ' (K false) T) |
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
353 |
| conv_arg _ _ _ x = x |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
354 |
fun conv_args ctxt used origin = map (conv_arg ctxt used origin) |
| 79490 | 355 |
|
356 |
(* Handle function calls *) |
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
357 |
fun build_zero (Type ("fun", [T, R])) = Abs ("uu", T, build_zero R)
|
| 79490 | 358 |
| build_zero _ = zero |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
359 |
fun funcc_use_origin used (f as Free (nm, T as Type ("fun",_))) =
|
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
360 |
if used f then HOLogic.mk_fst (Free (nm,HOLogic.mk_prodT (T, change_typ T))) |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
361 |
else error "Internal error: Error in used detection" |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
362 |
| funcc_use_origin _ t = t |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
363 |
fun funcc_conv_arg _ used _ (t as (_ $ _)) = map_aterms (funcc_use_origin used) t |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
364 |
| funcc_conv_arg wctxt used u (f as Free (nm, T as Type ("fun",_))) =
|
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
365 |
if used f then |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
366 |
if u then Free (nm, HOLogic.mk_prodT (T, change_typ T)) |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
367 |
else HOLogic.mk_snd (Free (nm,HOLogic.mk_prodT (T,change_typ T))) |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
368 |
else Free (fun_name_to_time (#ctxt wctxt) false nm, change_typ T) |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
369 |
| funcc_conv_arg wctxt _ true (f as Const (_,T as Type ("fun",_))) =
|
| 79490 | 370 |
(Const (@{const_name "Product_Type.Pair"},
|
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
371 |
Type ("fun", [T,Type ("fun", [change_typ T, HOLogic.mk_prodT (T,change_typ T)])]))
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
372 |
$ f $ (Option.getOpt (fun_to_time (#ctxt wctxt) (K false) (K false) (#origins wctxt) f, build_zero T))) |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
373 |
| funcc_conv_arg wctxt _ false (f as Const (_,T as Type ("fun",_))) =
|
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
374 |
Option.getOpt (fun_to_time (#ctxt wctxt) (K false) (K false) (#origins wctxt) f, build_zero T) |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
375 |
| funcc_conv_arg _ _ _ t = t |
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
376 |
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
377 |
fun funcc_conv_args _ _ _ [] = [] |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
378 |
| funcc_conv_args wctxt used (Type ("fun", [t, ts])) (a::args) =
|
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
379 |
funcc_conv_arg wctxt used (is_Used t) a :: funcc_conv_args wctxt used ts args |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
380 |
| funcc_conv_args _ _ _ _ = error "Internal error: Non matching type" |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
381 |
fun funcc orig_used used wctxt func args = |
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
382 |
let |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
383 |
fun get_T (Free (_,T)) = T |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
384 |
| get_T (Const (_,T)) = T |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
385 |
| get_T (_ $ (Free (_,Type (_, [_, T])))) = T (* Case of snd was constructed *) |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
386 |
| get_T _ = error "Internal error: Forgotten type" |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
387 |
in |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
388 |
List.foldr (I #-> plus) |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
389 |
(case fun_to_time (#ctxt wctxt) orig_used used (#origins wctxt) func |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
390 |
of SOME t => SOME (build_func (t,funcc_conv_args wctxt used (get_T t) args)) |
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
391 |
| NONE => NONE) |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
392 |
(map (#f wctxt) args) |
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
393 |
end |
| 79490 | 394 |
|
395 |
(* Handle case terms *) |
|
396 |
fun casecIsCase (Type (n1, [_,Type (n2, _)])) = (n1 = "fun" andalso n2 = "fun") |
|
397 |
| casecIsCase _ = false |
|
398 |
fun casecLastTyp (Type (n, [T1,T2])) = Type (n, [T1, change_typ T2]) |
|
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
399 |
| casecLastTyp _ = error "Internal error: Invalid case type" |
| 79490 | 400 |
fun casecTyp (Type (n, [T1, T2])) = |
401 |
Type (n, [change_typ T1, (if casecIsCase T2 then casecTyp else casecLastTyp) T2]) |
|
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
402 |
| casecTyp _ = error "Internal error: Invalid case type" |
| 79490 | 403 |
fun casecAbs f (Abs (v,Ta,t)) = (case casecAbs f t of (nconst,t) => (nconst,Abs (v,Ta,t))) |
404 |
| casecAbs f t = (case f t of NONE => (false,HOLogic.zero) | SOME t => (true,t)) |
|
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
405 |
fun casecArgs _ [t] = (false, [map_aterms use_origin t]) |
| 79490 | 406 |
| casecArgs f (t::ar) = |
407 |
(case casecAbs f t of (nconst, tt) => |
|
408 |
casecArgs f ar ||> (fn ar => tt :: ar) |>> (if nconst then K true else I)) |
|
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
409 |
| casecArgs _ _ = error "Internal error: Invalid case term" |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
410 |
fun casec wctxt (Const (t,T)) args = |
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
411 |
if not (casecIsCase T) then error "Internal error: Invalid case type" else |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
412 |
let val (nconst, args') = casecArgs (#f wctxt) args in |
| 79490 | 413 |
plus |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
414 |
((#f wctxt) (List.last args)) |
| 79490 | 415 |
(if nconst then |
416 |
SOME (build_func (Const (t,casecTyp T), args')) |
|
417 |
else NONE) |
|
418 |
end |
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
419 |
| casec _ _ _ = error "Internal error: Invalid case term" |
| 79490 | 420 |
|
421 |
(* Handle if terms -> drop the term if true and false terms are zero *) |
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
422 |
fun ifc wctxt _ cond tt ft = |
| 79490 | 423 |
let |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
424 |
val f = #f wctxt |
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
425 |
val rcond = map_aterms use_origin cond |
| 79490 | 426 |
val tt = f tt |
427 |
val ft = f ft |
|
428 |
in |
|
| 79969 | 429 |
plus (f cond) (case (tt,ft) of (NONE, NONE) => NONE | _ => |
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
430 |
if tt = ft then tt else |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
431 |
(SOME ((Const (@{const_name "HOL.If"}, @{typ "bool \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> nat"})) $ rcond $ (opt_term tt) $ (opt_term ft))))
|
| 79490 | 432 |
end |
433 |
||
|
79494
c7536609bb9b
translation to time functions now with canonical let.
nipkow
parents:
79490
diff
changeset
|
434 |
fun letc_change_typ (Type ("fun", [T1, Type ("fun", [T2, _])])) = (Type ("fun", [T1, Type ("fun", [change_typ T2, HOLogic.natT])]))
|
|
c7536609bb9b
translation to time functions now with canonical let.
nipkow
parents:
79490
diff
changeset
|
435 |
| letc_change_typ _ = error "Internal error: invalid let type" |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
436 |
fun letc wctxt expT exp nms Ts t = |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
437 |
plus (#f wctxt exp) |
| 79542 | 438 |
(if length nms = 0 (* In case of "length nms = 0" the expression got reducted |
439 |
Here we need Bound 0 to gain non-partial application *) |
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
440 |
then (case #f wctxt (t $ Bound 0) of SOME (t' $ Bound 0) => |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
441 |
(SOME (Const (@{const_name "HOL.Let"}, letc_change_typ expT) $ (map_aterms use_origin exp) $ t'))
|
| 79542 | 442 |
(* Expression is not used and can therefore let be dropped *) |
443 |
| SOME t' => SOME t' |
|
444 |
| NONE => NONE) |
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
445 |
else (case #f wctxt t of SOME t' => |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
446 |
SOME (if Term.is_dependent t' then Const (@{const_name "HOL.Let"}, letc_change_typ expT) $ (map_aterms use_origin exp) $ build_abs t' nms Ts
|
| 79542 | 447 |
else Term.subst_bounds([exp],t')) |
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
448 |
| NONE => NONE)) |
| 79490 | 449 |
|
450 |
(* The converter for timing functions given to the walker *) |
|
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
451 |
fun converter orig_used used : term option converter = {
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
452 |
constc = fn _ => fn t => |
| 80036 | 453 |
(case t of Const ("HOL.undefined", _) => SOME (Const ("HOL.undefined", @{typ "nat"}))
|
454 |
| _ => NONE), |
|
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
455 |
funcc = (funcc orig_used used), |
| 79490 | 456 |
ifc = ifc, |
457 |
casec = casec, |
|
458 |
letc = letc |
|
459 |
} |
|
| 79665 | 460 |
fun top_converter is_rec _ _ = opt_term o (fn exp => plus exp (if is_rec then SOME one else NONE)) |
| 79490 | 461 |
|
462 |
(* Use converter to convert right side of a term *) |
|
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
463 |
fun to_time ctxt origin is_rec orig_used used term = |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
464 |
top_converter is_rec ctxt origin (walk ctxt origin (converter orig_used used) term) |
| 79490 | 465 |
|
466 |
(* Converts a term to its running time version *) |
|
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
467 |
fun convert_term ctxt (origin: term list) is_rec orig_used (pT $ (Const (eqN, _) $ l $ r)) = |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
468 |
let |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
469 |
val (l' as (l_const, l_params)) = walk_func l [] |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
470 |
val used = |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
471 |
l_const |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
472 |
|> used_for_const orig_used |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
473 |
|> (fn f => fn n => f (index l_params n)) |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
474 |
in |
| 79490 | 475 |
pT |
476 |
$ (Const (eqN, @{typ "nat \<Rightarrow> nat \<Rightarrow> bool"})
|
|
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
477 |
$ (build_func (l' |>> (fun_to_time ctxt orig_used used origin) |>> Option.valOf ||> conv_args ctxt used origin)) |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
478 |
$ (to_time ctxt origin is_rec orig_used used r)) |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
479 |
end |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
480 |
| convert_term _ _ _ _ _ = error "Internal error: invalid term to convert" |
| 79490 | 481 |
|
482 |
(* 4. Tactic to prove "f_dom n" *) |
|
483 |
fun time_dom_tac ctxt induct_rule domintros = |
|
484 |
(Induction.induction_tac ctxt true [] [[]] [] (SOME [induct_rule]) [] |
|
485 |
THEN_ALL_NEW ((K (auto_tac ctxt)) THEN' (fn i => FIRST' ( |
|
486 |
(if i <= length domintros then [Metis_Tactic.metis_tac [] ATP_Problem_Generate.combsN ctxt [List.nth (domintros, i-1)]] else []) @ |
|
487 |
[Metis_Tactic.metis_tac [] ATP_Problem_Generate.combsN ctxt domintros]) i))) |
|
488 |
||
489 |
||
490 |
fun get_terms theory (term: term) = |
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
491 |
let |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
492 |
val equations = Spec_Rules.retrieve theory term |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
493 |
|> map #rules |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
494 |
|> map (map Thm.prop_of) |
| 79490 | 495 |
handle Empty => error "Function or terms of function not found" |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
496 |
in |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
497 |
equations |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
498 |
|> filter (fn ts => typ_comp (ts |> hd |> get_l |> walk_func' |> fst |> dest_Const |> snd) (term |> dest_Const |> snd)) |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
499 |
|> hd |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
500 |
end |
| 79490 | 501 |
|
502 |
(* Register timing function of a given function *) |
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
503 |
fun reg_time_func (lthy: local_theory) (term: term list) (terms: term list) print = |
| 79490 | 504 |
let |
505 |
val _ = |
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
506 |
case time_term lthy true (hd term) |
| 79490 | 507 |
handle (ERROR _) => NONE |
|
79494
c7536609bb9b
translation to time functions now with canonical let.
nipkow
parents:
79490
diff
changeset
|
508 |
of SOME _ => error ("Timing function already declared: " ^ (Term.term_name (hd term)))
|
| 79490 | 509 |
| NONE => () |
510 |
||
511 |
(* 1. Fix all terms *) |
|
512 |
(* Exchange Var in types and terms to Free and check constraints *) |
|
| 79969 | 513 |
val terms = map |
| 79542 | 514 |
(map_aterms fixTerms |
515 |
#> map_types (map_atyps fixTypes) |
|
516 |
#> fixPartTerms lthy term) |
|
517 |
terms |
|
| 79490 | 518 |
|
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
519 |
(* 2. Find properties about the function *) |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
520 |
(* 2.1 Check if function is recursive *) |
| 79490 | 521 |
val is_rec = is_rec lthy term terms |
522 |
||
523 |
(* 3. Convert every equation |
|
524 |
- Change type of toplevel equation from _ \<Rightarrow> _ \<Rightarrow> bool to nat \<Rightarrow> nat \<Rightarrow> bool |
|
525 |
- On left side change name of function to timing function |
|
526 |
- Convert right side of equation with conversion schema |
|
527 |
*) |
|
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
528 |
fun convert used = map (convert_term lthy term is_rec used) |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
529 |
fun repeat T_terms = |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
530 |
let |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
531 |
val orig_used = find_used lthy term terms T_terms |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
532 |
val T_terms' = convert orig_used terms |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
533 |
in |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
534 |
if T_terms' <> T_terms then repeat T_terms' else T_terms' |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
535 |
end |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
536 |
val T_terms = repeat (convert (K true) terms) |
|
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
537 |
val orig_used = find_used lthy term terms T_terms |
| 79490 | 538 |
|
539 |
(* 4. Register function and prove termination *) |
|
|
79494
c7536609bb9b
translation to time functions now with canonical let.
nipkow
parents:
79490
diff
changeset
|
540 |
val names = map Term.term_name term |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
541 |
val timing_names = map (fun_name_to_time lthy true) names |
|
79494
c7536609bb9b
translation to time functions now with canonical let.
nipkow
parents:
79490
diff
changeset
|
542 |
val bindings = map (fn nm => (Binding.name nm, NONE, NoSyn)) timing_names |
| 79490 | 543 |
fun pat_completeness_auto ctxt = |
544 |
Pat_Completeness.pat_completeness_tac ctxt 1 THEN auto_tac ctxt |
|
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
545 |
val specs = map (fn eq => (((Binding.empty, []), eq), [], [])) T_terms |
| 79490 | 546 |
|
547 |
(* For partial functions sequential=true is needed in order to support them |
|
548 |
We need sequential=false to support the automatic proof of termination over dom |
|
549 |
*) |
|
550 |
fun register seq = |
|
551 |
let |
|
552 |
val _ = (if seq then warning "Falling back on sequential function..." else ()) |
|
553 |
val fun_config = Function_Common.FunctionConfig |
|
|
79494
c7536609bb9b
translation to time functions now with canonical let.
nipkow
parents:
79490
diff
changeset
|
554 |
{sequential=seq, default=NONE, domintros=true, partials=false}
|
| 79490 | 555 |
in |
556 |
Function.add_function bindings specs fun_config pat_completeness_auto lthy |
|
557 |
end |
|
558 |
||
559 |
(* Context for printing without showing question marks *) |
|
560 |
val print_ctxt = lthy |
|
561 |
|> Config.put show_question_marks false |
|
562 |
|> Config.put show_sorts false (* Change it for debugging *) |
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
563 |
val print_ctxt = List.foldl (fn (term, ctxt) => Variable.add_fixes_implicit term ctxt) print_ctxt (term @ T_terms) |
| 79490 | 564 |
(* Print result if print *) |
565 |
val _ = if not print then () else |
|
566 |
let |
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
567 |
val nms = map (fst o dest_Const) term |
|
80624
9f8034d29365
time_function T_map can now be generated automatically.
nipkow
parents:
80036
diff
changeset
|
568 |
val used = map (used_for_const orig_used) term |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
569 |
val typs = map (snd o dest_Const) term |
| 79490 | 570 |
in |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
571 |
print_timing' print_ctxt { names=nms, terms=terms, typs=typs }
|
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
572 |
{ names=timing_names, terms=T_terms, typs=map (fn (used, typ) => change_typ' used typ) (ListPair.zip (used, typs)) }
|
| 79490 | 573 |
end |
574 |
||
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
575 |
in |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
576 |
register false |
| 79490 | 577 |
handle (ERROR _) => |
578 |
register true |
|
579 |
| Match => |
|
580 |
register true |
|
581 |
end |
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
582 |
fun proove_termination (term: term list) terms print (T_info: Function.info, lthy: local_theory) = |
| 79490 | 583 |
let |
584 |
(* Start proving the termination *) |
|
|
79494
c7536609bb9b
translation to time functions now with canonical let.
nipkow
parents:
79490
diff
changeset
|
585 |
val infos = SOME (map (Function.get_info lthy) term) handle Empty => NONE |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
586 |
val timing_names = map (fun_name_to_time lthy true o Term.term_name) term |
| 79490 | 587 |
|
588 |
(* Proof by lexicographic_order_tac *) |
|
589 |
val (time_info, lthy') = |
|
590 |
(Function.prove_termination NONE |
|
591 |
(Lexicographic_Order.lexicographic_order_tac false lthy) lthy) |
|
592 |
handle (ERROR _) => |
|
593 |
let |
|
594 |
val _ = warning "Falling back on proof over dom..." |
|
|
79494
c7536609bb9b
translation to time functions now with canonical let.
nipkow
parents:
79490
diff
changeset
|
595 |
val _ = (if length term > 1 then error "Proof over dom not supported for mutual recursive functions" else ()) |
|
c7536609bb9b
translation to time functions now with canonical let.
nipkow
parents:
79490
diff
changeset
|
596 |
|
| 79490 | 597 |
fun args (a$(Var ((nm,_),T))) = args a |> (fn ar => (nm,T)::ar) |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
598 |
| args (a$(Const (_,T))) = args a |> (fn ar => ("uu",T)::ar)
|
| 79490 | 599 |
| args _ = [] |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
600 |
val dom_vars = |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
601 |
terms |> hd |> get_l |> map_types (map_atyps fixTypes) |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
602 |
|> args |> Variable.variant_frees lthy [] |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
603 |
val dom_args = |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
604 |
List.foldl (fn (t,p) => HOLogic.mk_prod ((Free t),p)) (Free (hd dom_vars)) (tl dom_vars) |
| 79490 | 605 |
|
|
79494
c7536609bb9b
translation to time functions now with canonical let.
nipkow
parents:
79490
diff
changeset
|
606 |
val {inducts, ...} = case infos of SOME [i] => i | _ => error "Proof over dom failed as no induct rule was found"
|
| 79490 | 607 |
val induct = (Option.valOf inducts |> hd) |
608 |
||
|
79494
c7536609bb9b
translation to time functions now with canonical let.
nipkow
parents:
79490
diff
changeset
|
609 |
val domintros = Proof_Context.get_fact lthy (Facts.named (hd timing_names ^ ".domintros")) |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
610 |
val prop = HOLogic.mk_Trueprop (#dom T_info $ dom_args) |
| 79490 | 611 |
|
612 |
(* Prove a helper lemma *) |
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
613 |
val dom_lemma = Goal.prove lthy (map fst dom_vars) [] prop |
| 79490 | 614 |
(fn {context, ...} => HEADGOAL (time_dom_tac context induct domintros))
|
615 |
(* Add dom_lemma to simplification set *) |
|
616 |
val simp_lthy = Simplifier.add_simp dom_lemma lthy |
|
617 |
in |
|
618 |
(* Use lemma to prove termination *) |
|
619 |
Function.prove_termination NONE |
|
620 |
(auto_tac simp_lthy) lthy |
|
621 |
end |
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
622 |
|
| 79490 | 623 |
(* Context for printing without showing question marks *) |
624 |
val print_ctxt = lthy' |
|
625 |
|> Config.put show_question_marks false |
|
626 |
|> Config.put show_sorts false (* Change it for debugging *) |
|
627 |
(* Print result if print *) |
|
628 |
val _ = if not print then () else |
|
629 |
let |
|
|
80643
11b8f2e4c3d2
branches of case expressions may need to be eta-expanded
nipkow
parents:
80636
diff
changeset
|
630 |
val nms = map (fst o dest_Const) term |
|
11b8f2e4c3d2
branches of case expressions may need to be eta-expanded
nipkow
parents:
80636
diff
changeset
|
631 |
val typs = map (snd o dest_Const) term |
| 79490 | 632 |
in |
|
79494
c7536609bb9b
translation to time functions now with canonical let.
nipkow
parents:
79490
diff
changeset
|
633 |
print_timing' print_ctxt { names=nms, terms=terms, typs=typs } (info_pfunc time_info)
|
| 79490 | 634 |
end |
635 |
in |
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
636 |
(time_info, lthy') |
| 79490 | 637 |
end |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
638 |
fun reg_and_proove_time_func (lthy: local_theory) (term: term list) (terms: term list) print = |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
639 |
reg_time_func lthy term terms false |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
640 |
|> proove_termination term terms print |
| 79490 | 641 |
|
| 79969 | 642 |
fun fix_definition (Const ("Pure.eq", _) $ l $ r) = Const ("HOL.Trueprop", @{typ "bool \<Rightarrow> prop"})
|
643 |
$ (Const ("HOL.eq", @{typ "bool \<Rightarrow> bool \<Rightarrow> bool"}) $ l $ r)
|
|
644 |
| fix_definition t = t |
|
645 |
fun check_definition [t] = [t] |
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
646 |
| check_definition _ = error "Only a single definition is allowed" |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
647 |
|
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
648 |
fun isTypeClass' (Const (nm,_)) = |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
649 |
(case split_name nm |> rev |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
650 |
of (_::nm::_) => String.isSuffix "_class" nm |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
651 |
| _ => false) |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
652 |
| isTypeClass' _ = false |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
653 |
val isTypeClass = |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
654 |
(List.foldr (fn (a,b) => a orelse b) false) o (map isTypeClass') |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
655 |
|
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
656 |
fun detect_typ (ctxt: local_theory) (term: term) = |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
657 |
let |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
658 |
val class_term = (case term of Const (nm,_) => Syntax.read_term ctxt nm |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
659 |
| _ => error "Could not find term of class") |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
660 |
fun find_free (Type (_,class)) (Type (_,inst)) = |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
661 |
List.foldl (fn ((c,i),s) => (case s of NONE => find_free c i | t => t)) (NONE) (ListPair.zip (class, inst)) |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
662 |
| find_free (TFree _) (TFree _) = NONE |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
663 |
| find_free (TFree _) (Type (nm,_)) = SOME nm |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
664 |
| find_free _ _ = error "Unhandled case in detecting type" |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
665 |
in |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
666 |
find_free (type_of class_term) (type_of term) |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
667 |
|> Option.map (hd o rev o split_name) |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
668 |
end |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
669 |
|
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
670 |
fun set_suffix (fterms: term list) ctxt = |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
671 |
let |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
672 |
val isTypeClass = isTypeClass fterms |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
673 |
val _ = (if length fterms > 1 andalso isTypeClass then error "No mutual recursion inside instantiation allowed" else ()) |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
674 |
val suffix = (if isTypeClass then detect_typ ctxt (hd fterms) else NONE) |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
675 |
in |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
676 |
(case suffix of NONE => I | SOME s => Config.put bsuffix ("_" ^ s)) ctxt
|
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
677 |
end |
| 79969 | 678 |
|
| 79490 | 679 |
(* Convert function into its timing function (called by command) *) |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
680 |
fun reg_time_fun_cmd (funcs, thms) (ctxt: local_theory) = |
| 79490 | 681 |
let |
|
79494
c7536609bb9b
translation to time functions now with canonical let.
nipkow
parents:
79490
diff
changeset
|
682 |
val fterms = map (Syntax.read_term ctxt) funcs |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
683 |
val ctxt = set_suffix fterms ctxt |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
684 |
val (_, ctxt') = reg_and_proove_time_func ctxt fterms |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
685 |
(case thms of NONE => get_terms ctxt (hd fterms) |
| 79490 | 686 |
| SOME thms => thms |> Attrib.eval_thms ctxt |> List.map Thm.prop_of) |
| 79969 | 687 |
true |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
688 |
in ctxt' |
| 79490 | 689 |
end |
690 |
||
691 |
(* Convert function into its timing function (called by command) with termination proof provided by user*) |
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
692 |
fun reg_time_function_cmd (funcs, thms) (ctxt: local_theory) = |
| 79490 | 693 |
let |
|
79494
c7536609bb9b
translation to time functions now with canonical let.
nipkow
parents:
79490
diff
changeset
|
694 |
val fterms = map (Syntax.read_term ctxt) funcs |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
695 |
val ctxt = set_suffix fterms ctxt |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
696 |
val ctxt' = reg_time_func ctxt fterms |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
697 |
(case thms of NONE => get_terms ctxt (hd fterms) |
| 79490 | 698 |
| SOME thms => thms |> Attrib.eval_thms ctxt |> List.map Thm.prop_of) |
| 79969 | 699 |
true |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
700 |
|> snd |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
701 |
in ctxt' |
| 79490 | 702 |
end |
703 |
||
| 79969 | 704 |
(* Convert function into its timing function (called by command) *) |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
705 |
fun reg_time_definition_cmd (funcs, thms) (ctxt: local_theory) = |
| 79969 | 706 |
let |
707 |
val fterms = map (Syntax.read_term ctxt) funcs |
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
708 |
val ctxt = set_suffix fterms ctxt |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
709 |
val (_, ctxt') = reg_and_proove_time_func ctxt fterms |
|
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
710 |
(case thms of NONE => get_terms ctxt (hd fterms) |> check_definition |> map fix_definition |
| 79969 | 711 |
| SOME thms => thms |> Attrib.eval_thms ctxt |> List.map Thm.prop_of) |
712 |
true |
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
713 |
in ctxt' |
| 79969 | 714 |
end |
715 |
||
|
79494
c7536609bb9b
translation to time functions now with canonical let.
nipkow
parents:
79490
diff
changeset
|
716 |
val parser = (Scan.repeat1 Parse.prop) -- (Scan.option (Parse.keyword_improper "equations" -- Parse.thms1 >> snd)) |
| 79490 | 717 |
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
718 |
val _ = Outer_Syntax.local_theory @{command_keyword "time_fun"}
|
| 79490 | 719 |
"Defines runtime function of a function" |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
720 |
(parser >> reg_time_fun_cmd) |
| 79490 | 721 |
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
722 |
val _ = Outer_Syntax.local_theory @{command_keyword "time_function"}
|
| 79490 | 723 |
"Defines runtime function of a function" |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
724 |
(parser >> reg_time_function_cmd) |
| 79969 | 725 |
|
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
726 |
val _ = Outer_Syntax.local_theory @{command_keyword "time_definition"}
|
| 79969 | 727 |
"Defines runtime function of a definition" |
|
80734
7054a1bc8347
new version of time_fun that works for classes; define T_length automatically now
nipkow
parents:
80657
diff
changeset
|
728 |
(parser >> reg_time_definition_cmd) |
| 79490 | 729 |
|
730 |
end |