author | paulson |
Wed, 02 Mar 2005 10:21:17 +0100 | |
changeset 15559 | 10c5c689aa20 |
parent 15531 | 08c8dad8e399 |
child 15570 | 8d8c70b41bab |
permissions | -rw-r--r-- |
8364 | 1 |
(* Title: Pure/Isar/rule_cases.ML |
2 |
ID: $Id$ |
|
3 |
Author: Markus Wenzel, TU Muenchen |
|
4 |
||
5 |
Manage local contexts of rules. |
|
6 |
*) |
|
7 |
||
8 |
signature RULE_CASES = |
|
9 |
sig |
|
10530 | 10 |
val consumes: int -> 'a attribute |
11 |
val consumes_default: int -> 'a attribute |
|
8364 | 12 |
val name: string list -> thm -> thm |
8427 | 13 |
val case_names: string list -> 'a attribute |
12761 | 14 |
val save: thm -> thm -> thm |
10530 | 15 |
val get: thm -> string list * int |
16 |
val add: thm -> thm * (string list * int) |
|
10811 | 17 |
type T |
12166 | 18 |
val empty: T |
14404
4952c5a92e04
Transitive_Closure: added consumes and case_names attributes
nipkow
parents:
13668
diff
changeset
|
19 |
val make: bool -> term option -> Sign.sg * term -> string list -> (string * T) list |
8427 | 20 |
val rename_params: string list list -> thm -> thm |
8364 | 21 |
val params: string list list -> 'a attribute |
22 |
end; |
|
23 |
||
24 |
structure RuleCases: RULE_CASES = |
|
25 |
struct |
|
26 |
||
10811 | 27 |
(* names *) |
28 |
||
29 |
val consumes_tagN = "consumes"; |
|
30 |
val cases_tagN = "cases"; |
|
31 |
val case_conclN = "case"; |
|
32 |
||
33 |
||
10530 | 34 |
(* number of consumed facts *) |
8364 | 35 |
|
12761 | 36 |
fun lookup_consumes thm = |
10530 | 37 |
let fun err () = raise THM ("Malformed 'consumes' tag of theorem", 0, [thm]) in |
12761 | 38 |
(case Library.assoc (Thm.tags_of_thm thm, consumes_tagN) of |
15531 | 39 |
NONE => NONE |
40 |
| SOME [s] => (case Syntax.read_nat s of SOME n => SOME n | _ => err ()) |
|
10530 | 41 |
| _ => err ()) |
42 |
end; |
|
43 |
||
15531 | 44 |
fun put_consumes NONE th = th |
45 |
| put_consumes (SOME n) th = th |
|
12761 | 46 |
|> Drule.untag_rule consumes_tagN |
47 |
|> Drule.tag_rule (consumes_tagN, [Library.string_of_int n]); |
|
10530 | 48 |
|
12761 | 49 |
val save_consumes = put_consumes o lookup_consumes; |
50 |
||
15531 | 51 |
fun consumes n x = Drule.rule_attribute (K (put_consumes (SOME n))) x; |
10530 | 52 |
fun consumes_default n x = if Library.is_some (lookup_consumes (#2 x)) then x else consumes n x; |
8364 | 53 |
|
54 |
||
55 |
(* case names *) |
|
56 |
||
15531 | 57 |
fun put_case_names NONE thm = thm |
58 |
| put_case_names (SOME names) thm = |
|
12761 | 59 |
thm |
60 |
|> Drule.untag_rule cases_tagN |
|
61 |
|> Drule.tag_rule (cases_tagN, names); |
|
8364 | 62 |
|
12761 | 63 |
fun lookup_case_names thm = Library.assoc (Thm.tags_of_thm thm, cases_tagN); |
10530 | 64 |
|
12761 | 65 |
val save_case_names = put_case_names o lookup_case_names; |
15531 | 66 |
val name = put_case_names o SOME; |
8427 | 67 |
fun case_names ss = Drule.rule_attribute (K (name ss)); |
8364 | 68 |
|
10530 | 69 |
|
70 |
(* access hints *) |
|
71 |
||
12761 | 72 |
fun save thm = save_case_names thm o save_consumes thm; |
73 |
||
74 |
fun get thm = |
|
75 |
let |
|
76 |
val n = if_none (lookup_consumes thm) 0; |
|
77 |
val ss = |
|
78 |
(case lookup_case_names thm of |
|
15531 | 79 |
NONE => map Library.string_of_int (1 upto (Thm.nprems_of thm - n)) |
80 |
| SOME ss => ss); |
|
12761 | 81 |
in (ss, n) end; |
82 |
||
8364 | 83 |
fun add thm = (thm, get thm); |
10530 | 84 |
|
8364 | 85 |
|
86 |
(* prepare cases *) |
|
87 |
||
13425
119ae829ad9b
support for split assumptions in cases (hyps vs. prems);
wenzelm
parents:
12809
diff
changeset
|
88 |
type T = |
119ae829ad9b
support for split assumptions in cases (hyps vs. prems);
wenzelm
parents:
12809
diff
changeset
|
89 |
{fixes: (string * typ) list, |
119ae829ad9b
support for split assumptions in cases (hyps vs. prems);
wenzelm
parents:
12809
diff
changeset
|
90 |
assumes: (string * term list) list, |
119ae829ad9b
support for split assumptions in cases (hyps vs. prems);
wenzelm
parents:
12809
diff
changeset
|
91 |
binds: (indexname * term option) list}; |
119ae829ad9b
support for split assumptions in cases (hyps vs. prems);
wenzelm
parents:
12809
diff
changeset
|
92 |
|
119ae829ad9b
support for split assumptions in cases (hyps vs. prems);
wenzelm
parents:
12809
diff
changeset
|
93 |
val hypsN = "hyps"; |
119ae829ad9b
support for split assumptions in cases (hyps vs. prems);
wenzelm
parents:
12809
diff
changeset
|
94 |
val premsN = "prems"; |
10530 | 95 |
|
12166 | 96 |
val empty = {fixes = [], assumes = [], binds = []}; |
97 |
||
13596 | 98 |
fun nth_subgoal(i,prop) = |
13668 | 99 |
hd (#1 (Logic.strip_prems (i, [], prop))); |
13596 | 100 |
|
14404
4952c5a92e04
Transitive_Closure: added consumes and case_names attributes
nipkow
parents:
13668
diff
changeset
|
101 |
fun prep_case is_open split sg prop name i = |
8364 | 102 |
let |
14404
4952c5a92e04
Transitive_Closure: added consumes and case_names attributes
nipkow
parents:
13668
diff
changeset
|
103 |
val Bi = Drule.norm_hhf sg (nth_subgoal(i,prop)); |
13596 | 104 |
val all_xs = Logic.strip_params Bi |
15531 | 105 |
val n = (case split of NONE => length all_xs |
106 |
| SOME t => length (Logic.strip_params(nth_subgoal(i,t)))) |
|
13629 | 107 |
val (ind_xs, goal_xs) = splitAt(n,all_xs) |
14404
4952c5a92e04
Transitive_Closure: added consumes and case_names attributes
nipkow
parents:
13668
diff
changeset
|
108 |
val rename = if is_open then I else apfst Syntax.internal |
13596 | 109 |
val xs = map rename ind_xs @ goal_xs |
10811 | 110 |
val asms = map (curry Term.list_abs xs) (Logic.strip_assums_hyp Bi); |
13425
119ae829ad9b
support for split assumptions in cases (hyps vs. prems);
wenzelm
parents:
12809
diff
changeset
|
111 |
val named_asms = |
15531 | 112 |
(case split of NONE => [("", asms)] |
113 |
| SOME t => |
|
13596 | 114 |
let val h = length (Logic.strip_assums_hyp(nth_subgoal(i,t))) |
13629 | 115 |
val (ps,qs) = splitAt(h, asms) |
116 |
in [(hypsN, ps), (premsN, qs)] end); |
|
10872 | 117 |
val concl = Term.list_abs (xs, Logic.strip_assums_concl Bi); |
15531 | 118 |
val bind = ((case_conclN, 0), SOME (ObjectLogic.drop_judgment sg concl)); |
13425
119ae829ad9b
support for split assumptions in cases (hyps vs. prems);
wenzelm
parents:
12809
diff
changeset
|
119 |
in (name, {fixes = xs, assumes = named_asms, binds = [bind]}) end; |
8364 | 120 |
|
14404
4952c5a92e04
Transitive_Closure: added consumes and case_names attributes
nipkow
parents:
13668
diff
changeset
|
121 |
fun make is_open split (sg, prop) names = |
13668 | 122 |
let val nprems = Logic.count_prems (prop, 0) in |
14404
4952c5a92e04
Transitive_Closure: added consumes and case_names attributes
nipkow
parents:
13668
diff
changeset
|
123 |
foldr (fn (name, (cases, i)) => (prep_case is_open split sg prop name i :: cases, i - 1)) |
13425
119ae829ad9b
support for split assumptions in cases (hyps vs. prems);
wenzelm
parents:
12809
diff
changeset
|
124 |
(Library.drop (length names - nprems, names), ([], length names)) |> #1 |
10811 | 125 |
end; |
8364 | 126 |
|
127 |
||
8427 | 128 |
(* params *) |
8364 | 129 |
|
11002 | 130 |
fun rename_params xss thm = foldln Thm.rename_params_rule xss thm |
10530 | 131 |
|> save thm; |
8364 | 132 |
|
133 |
fun params xss = Drule.rule_attribute (K (rename_params xss)); |
|
134 |
||
135 |
end; |