eliminate use of Thy_Info 21: replace Unparse.term, TermC.unparse_ERROR for far off ctxt
1 (* calculate values for function constants
2 (c) Walther Neuper 000106
4 Some formula transformations cannot be done by rewriting;
5 these are done by structure Eval, which works tightly intertwined with structure Rewrite.
12 val ml_fun_empty: ml_fun
15 val is_num: term -> bool
16 val calc_equ: string -> int * int -> bool
17 val power: int -> int -> int
18 val sign_mult: int -> int -> int
19 val squfact: int -> int
20 val gcd: int -> int -> int
22 val cancel_int: int * int -> int * (int * int)
23 val adhoc_thm: Proof.context -> Eval_Def.ml -> term -> (string * thm) option
24 val adhoc_thm1_: Proof.context -> Eval_Def.ml -> term -> (string * thm) option
25 val norm: term -> term
26 val popt2str: Proof.context -> ('a * term) option -> string
27 val int_of_numeral: term -> int
29 val get_pair: Proof.context -> string -> Eval_Def.ml_fun -> term -> (string * term) option
30 val mk_rule: term list * term * term -> term
31 val divisors: int -> int list
32 val doubles: int list -> int list
37 structure Eval(**): EVALUATE(**) =
42 type ml_fun = Eval_Def.ml_fun
43 val ml_fun_empty = Eval_Def.ml_fun_empty
44 type ml_from_prog = Eval_Def.ml_from_prog
46 val is_num = can HOLogic.dest_number;
48 (* trace internal steps of isac's numeral calculations *)
49 val eval_trace = Attrib.setup_config_bool \<^binding>\<open>eval_trace\<close> (K false);
51 (** calculate integers **)
53 fun calc_equ "less" (n1, n2) = n1 < n2
54 | calc_equ "less_eq" (n1, n2) = n1 <= n2
55 | calc_equ op_ _ = raise ERROR ("calc_equ: operator = " ^ op_ ^ " not defined");
56 fun sqrt (n:int) = if n < 0 then 0 else (trunc o Math.sqrt o Real.fromInt (*FIXME*)) n;
59 if n > 0 then b* (power b (n - 1))
60 else raise ERROR ("power " ^ TermC.str_of_int b ^ " " ^ TermC.str_of_int n);
62 | gcd a b = if a < b then gcd (b mod a) a else gcd (a mod b) b;
65 else if n = 0 then 0 else 1;
66 fun sign_mult n1 n2 = (sign n1) * (sign n2);
68 fun cancel_int (i1, i2) =
70 val sg = sign_mult i1 i2;
71 val gcd' = gcd (abs i1) (abs i2);
73 (sg, ((abs i1) div gcd', (abs i2) div gcd'))
77 fun d dvd n = n mod d = 0;
81 else if d dvd n then pdiv (d :: ds) d (n div d)
82 else pdiv ds (d + 1) n
85 fun doubles ds = (* ds is ordered *)
86 let fun dbls ds [] = ds
88 | dbls ds (i :: i' :: is) = if i = i' then dbls (i :: ds) is
93 | squfact n = foldl op* (1, (doubles o divisors) n);
96 (** calculate numerals **)
98 fun popt2str ctxt (SOME (_, term)) = "SOME " ^ UnparseC.term_in_ctxt ctxt term (*TODO \<longrightarrow> str_of_termopt*)
99 | popt2str _ NONE = "NONE";
101 (* scan a term for applying eval_fn ef
104 op_: operator (as string) selecting the root of the pair
105 ef : fn : (string -> term -> theory -> (string * term) option)
106 ^^^^^^... for creating the string for the resulting theorem
107 t : term to be scanned
109 (string * term) option: found by the eval_* -function of type
110 fn : string -> string -> term -> theory -> (string * term) option
111 ^^^^^^... the selecting operator op_ (variable for eval_binop)
113 fun trace_calc0 ctxt str =
114 if Config.get ctxt eval_trace then writeln ("### " ^ str) else ()
115 fun trace_calc1 ctxt str1 str2 =
116 if Config.get ctxt eval_trace then writeln (str1 ^ str2) else ()
117 fun trace_calc2 ctxt str term popt =
118 if Config.get ctxt eval_trace
119 then writeln (str ^ UnparseC.term_in_ctxt ctxt term ^ " , " ^ popt2str ctxt popt) else ()
120 fun trace_calc3 ctxt str term =
121 if Config.get ctxt eval_trace then writeln ("### " ^ str ^ UnparseC.term_in_ctxt ctxt term) else ()
122 fun trace_calc4 ctxt str t1 t2 =
123 if Config.get ctxt eval_trace
124 then writeln ("### " ^ str ^ UnparseC.term_in_ctxt ctxt t1 ^ " $ " ^ UnparseC.term_in_ctxt ctxt t2) else ()
126 fun get_pair (*1*)ctxt op_ (ef: ml_fun) (t as (Const (op0, _) $ arg)) = (* unary fns *)
128 let val popt = ef op_ t ctxt
129 in case popt of SOME _ => popt | NONE => get_pair ctxt op_ ef arg end
130 else get_pair ctxt op_ ef arg
131 | get_pair (*2*)ctxt "Prog_Expr.ident" ef (t as (Const ("Prog_Expr.ident", _) $ _ $ _ )) =
132 ef "Prog_Expr.ident" t ctxt (* not nested *)
133 | get_pair (*3*)ctxt op_ ef (t as (Const (op0, _) $ t1 $ t2)) = (* binary funs *)
134 (trace_calc1 ctxt "1.. get_pair: binop = " op_;
137 val popt = ef op_ t ctxt
138 val _ = trace_calc2 ctxt "2.. get_pair: " t popt
139 in case popt of SOME _ => popt | NONE =>
141 val popt = get_pair ctxt op_ ef t1
142 val _ = trace_calc2 ctxt "3.. get_pair: " t1 popt
143 in case popt of SOME _ => popt | NONE => get_pair ctxt op_ ef t2 end (* search subterms *)
145 else (* search subterms *)
147 val popt = get_pair ctxt op_ ef t1
148 val _ = trace_calc2 ctxt "4.. get_pair: " t popt
149 in case popt of SOME _ => popt | NONE => get_pair ctxt op_ ef t2 end)
150 | get_pair (*4*)ctxt op_ ef (t as (Const (op0, _) $ t1 $ t2 $ t3)) = (* ternary funs *)
151 (trace_calc3 ctxt "get_pair 4a: t= "t;
152 trace_calc1 ctxt "get_pair 4a: op_= " op_;
153 trace_calc1 ctxt "get_pair 4a: op0= " op0;
155 case ef op_ t ctxt of st as SOME _ => st | NONE =>
156 (case get_pair ctxt op_ ef t2 of st as SOME _ => st | NONE => get_pair ctxt op_ ef t3)
158 (case get_pair ctxt op_ ef t1 of st as SOME _ => st | NONE =>
159 (case get_pair ctxt op_ ef t2 of st as SOME _ => st | NONE => get_pair ctxt op_ ef t3)))
160 | get_pair (*5*)ctxt op_ ef (Abs (_, _, body)) = get_pair ctxt op_ ef body
161 | get_pair (*6*)ctxt op_ ef (t1 $ t2) =
163 val _ = trace_calc4 ctxt "5.. get_pair t1 $ t2: " t1 t2;
164 val popt = get_pair ctxt op_ ef t1
165 in case popt of SOME _ => popt
166 | NONE => (trace_calc0 ctxt "### get_pair: t1 $ t2 -> NONE"; get_pair ctxt op_ ef t2)
168 | get_pair (*7*)_ _ _ _ = NONE
170 (* get a thm from an op_ somewhere in a term by use of get_pair *)
171 fun adhoc_thm ctxt (op_, eval_fn) t =
172 ((*@{print\<open>tracing\<close>}{a = "adhoc_thm", op_ = op_, t = t, get_p = get_pair thy op_ eval_fn t};*)
173 case get_pair ctxt op_ eval_fn t of
175 | SOME (thmid, t') => SOME (thmid, Skip_Proof.make_thm (Proof_Context.theory_of ctxt) t'));
177 (* get a thm applying an op_ to a term by direct use of eval_fn *)
178 fun adhoc_thm1_ ctxt (op_, eval_fn) ct =
179 case eval_fn op_ ct ctxt of
181 | SOME (thmid, t') => SOME (thmid, Skip_Proof.make_thm (Proof_Context.theory_of ctxt) t');
183 (** for ordered and conditional rewriting **)
185 fun mk_rule (prems, l, r) =
186 HOLogic.Trueprop $ (Logic.list_implies (prems, TermC.mk_equality (l, r)));
188 (* 'norms' a rule, e.g.
189 (*1*) from a = 1 ==> a*(b+c) = b+c
190 to a = 1 ==> a*(b+c) = b+c no change
193 (*3*) from [| k < l; m + l = k + n |] ==> m < n
194 to [| k < l; m + l = k + n |] ==> m < n = True !! *)
198 (map TermC.strip_trueprop (Logic.strip_imp_prems rule),
199 (TermC.strip_trueprop o Logic.strip_imp_concl) rule)
201 if TermC.is_equality concl
203 let val (l, r) = TermC.dest_equals concl
205 if l = r then (*2*) mk_rule (prems, concl, @{term True}) else (*1*) rule
207 else (*3*) mk_rule (prems, concl, @{term True})
210 (* preliminary HACK *)
211 fun int_of_numeral (Const (\<^const_name>\<open>zero_class.zero\<close>, _)) = 0
212 | int_of_numeral (Const (\<^const_name>\<open>one_class.one\<close>, _)) = 1
213 | int_of_numeral (Const (\<^const_name>\<open>uminus\<close>, _) $ t) = ~1 * int_of_numeral t
214 | int_of_numeral (Const (\<^const_name>\<open>numeral\<close>, _) $ n) = HOLogic.dest_numeral n
215 | int_of_numeral t = raise TERM ("int_of_numeral", [t]);