/
actions.ml
293 lines (230 loc) · 10.7 KB
/
actions.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
(* ========================================================================= *)
(* Composition actions. *)
(* *)
(* Petros Papapanagiotou *)
(* Center of Intelligent Systems and their Applications *)
(* University of Edinburgh *)
(* 2011 - 2019 *)
(* ========================================================================= *)
(* Dependencies *)
needs ("embed/sequent.ml");;
needs (!serv_dir ^ "support/support.ml");;
needs (!serv_dir ^ "processes/provenance.ml");;
(* ========================================================================= *)
(* Composition actions. *)
(* ------------------------------------------------------------------------- *)
(* These are standardized as named actions that correspond to a HOL Light *)
(* tactic. *)
(* Composition actions are binary. They involve two named components which *)
(* can be either existing atomic or composite processes or intermediate *)
(* compositions (see below). *)
(* The component names are given as arguments larg (left argument) and rarg *)
(* (right argument). Two selector strings lsel and rsel are also given. *)
(* These define a selection for a part of the corresponding component. *)
(* e.g. if the user selected a particular input or output that the *)
(* composition action must be applied on. *)
(* The res argument corresponds to the name of the resulting intermediate *)
(* composition. *)
(* ------------------------------------------------------------------------- *)
(* Note that not all current composition tactics make use of the selector *)
(* arguments. *)
(* TENSOR does not need to. *)
(* WITH needs the selection of the particular input types that will be *)
(* involved in the conditional. *)
(* JOIN does not use selectors but will be updated to do so. *)
(* ========================================================================= *)
module Actionmap = Map.Make(String);;
module Actionstate = struct
type t = {
label : string;
ctr : int;
metas : term list;
merged : (term * string * string) list;
iprov : (term * provtree) list;
prov : (string * provtree) list;
}
let create lbl = ({ label = lbl ; ctr = 0 ; metas = [] ; merged = [] ; iprov = [] ; prov = [] }:t)
let reset s = ({ s with merged = [] }:t)
let label s = s.label
let set_label l s =
({ s with label = l }:t)
let ctr s = s.ctr
let set_ctr c s =
({ s with ctr = c }:t)
let inc i s = set_ctr (s.ctr + i) s
let set_metas l s =
({ s with metas = l }:t)
let add_merged tm (cl,cr) s =
({ s with merged = (tm,string_of_term cl,string_of_term cr) :: s.merged }:t)
let get_lmerge chan s =
let str = string_of_term chan in
let search (tm,l,_) = l = str in
find search s.merged
let get_rmerge chan s =
let str = string_of_term chan in
let search (tm,_,r) = r = str in
find search s.merged
let inst_merge i s =
let imerge (tm,l,r) = instantiate i tm,l,r in
({ s with merged = map imerge s.merged } :t)
let add_prov n p s =
({ s with prov = assoc_add n p s.prov }:t)
let set_prov pm s =
({ s with prov = pm }:t)
let add_iprov n p s =
({ s with iprov = (n,p) :: s.iprov }:t)
let set_iprov pm s =
({ s with iprov = pm }:t)
let from_seqstate (l,i,m) s =
({ s with label = l ; ctr = i ; metas = m }:t)
let to_seqstate s = (s.label,s.ctr,s.metas)
let (print:t -> unit) =
fun st ->
let stml tml = String.concat ", " (map string_of_term tml)
and prmerged (tm,l,r) = ( print_string (" " ^ l ^ " = "^ r ^ " (" ^ (string_of_term tm) ^ ")") ; print_newline() )
and prprov (n,p) = ( print_string (" " ^ n ^ " -> " ^ (string_of_prov p)) ; print_newline() )
and priprov (n,p) = ( print_string (" " ^ (string_of_term n) ^ " -> " ^ (string_of_prov p)) ; print_newline() )
in
print_string "-----";
print_newline ();
print_string ("Label = " ^ st.label);
print_newline ();
print_string ("Ctr = " ^ (string_of_int st.ctr));
print_newline ();
print_string ("Metas = " ^ (stml st.metas));
print_newline ();
print_string ("Merged = ");
ignore(map prmerged st.merged);
print_newline ();
print_string ("IProv = ") ;
ignore(map priprov st.iprov) ;
print_newline ();
print_string ("Prov = ") ;
ignore(map prprov st.prov) ;
print_newline ();
print_newline ();
print_string "-----";
print_newline()
let (TAC:t etactic -> tactic) =
fun atac -> ETAC_TAC' print (create "") atac
let (CLL_TAC:seqtactic -> t etactic) =
fun tac -> LIFT_ETAC to_seqstate from_seqstate tac
let (ASTAC:tactic -> t etactic) = CLL_TAC o SEQTAC
let (ADD_PROV_TAC:string -> provtree -> t etactic) =
fun n p -> ALL_ETAC' (fun s -> add_prov n p s)
let (UPDATE_PROV_TAC:((string * provtree) list -> (string * provtree) list) -> t etactic) =
fun f -> ALL_ETAC' (fun s -> set_prov (f s.prov) s)
let (ADD_IPROV_TAC:term -> provtree -> t etactic) =
fun n p -> ALL_ETAC' (fun s -> add_iprov n p s)
let (TIMES_IPROV_TAC:term -> term -> t etactic) =
fun l r ->
let update s = try (
let (_,lp),rest = remove (fun (i,p) -> i = l) s.iprov in
let (_,rp),rest = remove (fun (i,p) -> i = r) rest in
set_iprov ((list_mk_comb(`LinTimes`,[l;r]),provtimes lp rp) :: rest) s
) with Failure _ -> (
warn true ("Failed to tensor iprov: " ^ (string_of_term l) ^ " - " ^ (string_of_term r)) ;
s) in
ALL_ETAC' update
let (PLUS_IPROV_TAC:term -> term -> t etactic) =
fun l r ->
let update s = try (
let (_,lp),rest = remove (fun (i,p) -> i = l) s.iprov in
let (_,rp),rest = remove (fun (i,p) -> i = r) rest in
set_iprov ((list_mk_comb(`LinPlus`,[l;r]),provplus lp rp) :: rest) s
) with Failure _ -> (
warn true ("Failed to add iprov: " ^ (string_of_term l) ^ " - " ^ (string_of_term r)) ;
s) in
ALL_ETAC' update
let (SET_CTR_TAC: int -> t etactic) =
fun c -> ALL_ETAC' (fun s -> set_ctr c s)
let (SET_LABEL_TAC: string -> t etactic) =
fun l -> ALL_ETAC' (fun s -> set_label l s)
let (UPDATE_LABEL_TAC: (string -> string) -> t etactic) =
fun f s -> SET_LABEL_TAC (f s.label) s
let (TEMP_LABEL_THEN: (string -> string) -> t etactic -> t etactic) =
fun f tac s -> EEVERY [
SET_CTR_TAC 0 ;
UPDATE_LABEL_TAC f ;
tac ;
SET_LABEL_TAC s.label ;
SET_CTR_TAC s.ctr
] s
end;;
type astactic = Actionstate.t etactic;;
(* ------------------------------------------------------------------------- *)
(* REFRESH_CHANS_TAC renames all the channels in a process to keep them fresh*)
(* ------------------------------------------------------------------------- *)
(* The use of INSTANTIATE below will fail for composite processes as their *)
(* channels are not universally quantified. REFRESH_CHANS_TAC will only *)
(* succeed for atomic processes. *)
(* ------------------------------------------------------------------------- *)
(*
let REFRESH_CHANS_TAC:string -> astactic =
fun lbl st (asl,_ as gl) ->
let thm = try ( assoc lbl asl ) with Failure _ -> failwith ("REFRESH_CHANS_TAC") in
let chans = get_ll_channels (concl thm) in
let new_chan c = number_var st.Actionstate.ctr (mk_undered_var [c] c) in
let nchans = map new_chan chans in
let pairs = List.combine chans nchans in
let mk_inst = fun t1,t2 -> term_match [] t1 t2 in
let inst = itlist compose_insts (map mk_inst pairs) null_inst in
let tac = REMOVE_THEN lbl (fun x -> LABEL_TAC lbl (INSTANTIATE inst x)) in
let ((metas,insts),goals,just),st' = ETAC tac (Actionstate.inc 1 st) gl in
((nchans @ metas,insts),goals,just),Actionstate.add_chanmap pairs st';;
*)
module Action = struct
type t = {
act : string;
larg : string;
lsel : string;
rarg : string;
rsel : string;
res : string ;
}
type tac = t -> thm -> thm -> astactic
let actions = ref Actionmap.empty;;
let get_all () = Actionmap.fold (fun k v l -> (v::l)) (!actions) []
let names () = Actionmap.fold (fun k v l -> (k::l)) (!actions) []
let get name = try ( Actionmap.find name (!actions) )
with Not_found -> failwith ("No such action '" ^ name ^ "'")
let delete name = actions := Actionmap.remove name (!actions)
let string_of_act (a:t) =
a.act ^ ": " ^
a.larg ^ " (" ^ a.lsel ^ ") " ^
a.rarg ^ " (" ^ a.rsel ^ ") -> " ^ a.res
let (add:Actionmap.key->tac->unit) =
fun name act ->
warn (try (let _ = get name in true) with Failure _ -> false)
("add_action: Overwriting action '" ^ name ^ "'.") ;
actions := Actionmap.add name act (!actions)
let (create:string -> string -> string -> string -> string -> string -> t) =
fun act larg lsel rarg rsel res ->
({ act = act; larg = larg; lsel = lsel; rarg = rarg; rsel = rsel; res = res }:t)
let apply: t -> astactic =
fun act s gl ->
let tac s (asl,w as gl) =
let name = String.uppercase act.act in
let atac = get name
and thml = try ( assoc act.larg asl )
with Failure _ -> failwith ("APPLY ACTION '"^name^"': No such process '"^act.larg^"'")
and thmr = try ( assoc act.rarg asl )
with Failure _ -> failwith ("APPLY ACTION '"^name^"': No such process '"^act.rarg^"'") in
atac act thml thmr s gl in
let temp_label l =
if (l = "") then ("c"^act.res) else String.concat "__" ["c"^l;act.res;""] in
EEVERY [
(* ETRY (REFRESH_CHANS_TAC act.rarg);
ETRY (REFRESH_CHANS_TAC act.larg); *)
Actionstate.TEMP_LABEL_THEN temp_label tac
] s gl
(* let (TAC:t -> tactic) =
fun act -> Actionstate.TAC (apply act)
*)
let root_deps (l:t list) =
let split_act a = [a.larg; a.rarg], a.res in
let splits = map split_act l in
let deps,results = unzip splits in
subtract (setify (flat deps)) results
end;;
type actiontactic = Action.tac;;