source: LTS/Vm.ma @ 3496

Last change on this file since 3496 was 3496, checked in by sacerdot, 5 years ago

Termination hypothesis greatly simplified.

File size: 53.7 KB
Line 
1 include "costs.ma".
2include "basics/lists/list.ma".
3include "../src/utilities/option.ma".
4include "basics/jmeq.ma".
5
6lemma bind_inversion : ∀A,B : Type[0].∀m : option A.
7∀f : A → option B.∀y : B.
8! x ← m; f x = return y →
9∃ x.(m = return x) ∧ (f x = return y).
10#A #B * [| #a] #f #y normalize #EQ [destruct]
11%{a} %{(refl …)} //
12qed.
13
14record assembler_params : Type[1] ≝
15{ seq_instr : Type[0]
16; jump_condition : Type[0]
17; io_instr : Type[0] }.
18
19inductive AssemblerInstr (p : assembler_params) : Type[0] ≝
20| Seq : seq_instr p → option (NonFunctionalLabel) →  AssemblerInstr p
21| Ijmp: ℕ → AssemblerInstr p
22| CJump : jump_condition p → ℕ → NonFunctionalLabel → NonFunctionalLabel → AssemblerInstr p
23| Iio : NonFunctionalLabel → io_instr p → NonFunctionalLabel → AssemblerInstr p
24| Icall: FunctionName → AssemblerInstr p
25| Iret: AssemblerInstr p.
26
27definition labels_pc_of_instr : ∀p.AssemblerInstr p → ℕ → list (CostLabel × ℕ) ≝
28λp,i,program_counter.
29match i with
30  [ Seq _ opt_l ⇒ match opt_l with
31                  [ Some lbl ⇒ [〈(a_non_functional_label lbl),S program_counter〉]
32                  | None ⇒ [ ]
33                  ]
34  | Ijmp _ ⇒ [ ]
35  | CJump _ newpc ltrue lfalse ⇒ [〈(a_non_functional_label ltrue),newpc〉;
36                                  〈(a_non_functional_label lfalse),S program_counter〉]
37  | Iio lin _ lout ⇒ [〈(a_non_functional_label lin),program_counter〉;
38                      〈(a_non_functional_label lout),S program_counter〉]
39  | Icall f ⇒ [ ]
40  | Iret ⇒ [ ]
41  ].
42
43let rec labels_pc (p : assembler_params)
44(prog : list (AssemblerInstr p)) (call_label_fun : list (ℕ × CallCostLabel))
45              (return_label_fun : list (ℕ × ReturnPostCostLabel)) (i_act : NonFunctionalLabel)
46              (program_counter : ℕ) on prog : list (CostLabel × ℕ) ≝
47match prog with
48[ nil ⇒ [〈a_non_functional_label (i_act),O〉] @
49        map … (λx.let〈y,z〉 ≝ x in 〈(a_call z),y〉) (call_label_fun) @
50        map … (λx.let〈y,z〉 ≝ x in 〈(a_return_post z),y〉) (return_label_fun)
51| cons i is ⇒ (labels_pc_of_instr … i program_counter)@labels_pc p is call_label_fun return_label_fun i_act (S program_counter)
52].
53
54include "basics/lists/listb.ma".
55
56(*doppione da mettere a posto*)
57let rec no_duplicates (A : DeqSet) (l : list A) on l : Prop ≝
58match l with
59[ nil ⇒ True
60| cons x xs ⇒ ¬ (bool_to_Prop (x ∈ xs)) ∧ no_duplicates … xs
61].
62
63
64record AssemblerProgram (p : assembler_params) : Type[0] ≝
65{ instructions : list (AssemblerInstr p)
66; endmain : ℕ
67; endmain_ok : endmain < |instructions|
68; entry_of_function : FunctionName → ℕ
69; call_label_fun : list (ℕ × CallCostLabel)
70; return_label_fun : list (ℕ × ReturnPostCostLabel)
71; in_act : NonFunctionalLabel
72; asm_no_duplicates : no_duplicates … (map ?? \fst … (labels_pc … instructions call_label_fun return_label_fun in_act O))
73}.
74
75
76definition fetch: ∀p.AssemblerProgram p → ℕ → option (AssemblerInstr p) ≝
77 λp,l,n. nth_opt ? n (instructions … l).
78
79definition stackT: Type[0] ≝ list (nat).
80
81record sem_params (p : assembler_params) : Type[1] ≝
82{ m : monoid
83; asm_store_type : Type[0]
84; eval_asm_seq : seq_instr p → asm_store_type → option asm_store_type
85; eval_asm_cond : jump_condition p → asm_store_type → option bool
86; eval_asm_io : io_instr p → asm_store_type → option asm_store_type
87; cost_of_io : io_instr p → asm_store_type → m
88; cost_of : AssemblerInstr p → asm_store_type →  m
89}.
90
91record vm_state (p : assembler_params) (p' : sem_params p) : Type[0] ≝
92{ pc : ℕ
93; asm_stack : stackT
94; asm_store : asm_store_type … p'
95; asm_is_io : bool
96; cost : m … p'
97}.
98
99definition label_of_pc ≝ λL.λl.λpc.find …
100   (λp.let 〈x,y〉 ≝ p in if eqb x pc then Some L y else None ? ) l.
101   
102definition option_pop ≝
103  λA.λl:list A. match l with
104  [ nil ⇒ None ?
105  | cons a tl ⇒ Some ? (〈a,tl〉) ].
106
107
108inductive vmstep (p : assembler_params) (p' : sem_params p)
109   (prog : AssemblerProgram p)  :
110      ActionLabel → relation (vm_state p p') ≝
111| vm_seq : ∀st1,st2 : vm_state p p'.∀i,l.
112           fetch … prog (pc … st1) = return (Seq p i l) →
113           asm_is_io … st1 = false →
114           eval_asm_seq p p' i (asm_store … st1) = return asm_store … st2 → 
115           asm_stack … st1 = asm_stack … st2 →
116           asm_is_io … st1 = asm_is_io … st2 →
117           S (pc … st1) = pc … st2 →
118           op … (cost … st1) (cost_of p p' (Seq p i l) (asm_store … st1)) = cost … st2 →
119           vmstep … (cost_act l) st1 st2
120| vm_ijump : ∀st1,st2 : vm_state p p'.∀new_pc : ℕ.
121           fetch … prog (pc … st1) = return (Ijmp p new_pc) →
122           asm_is_io … st1 = false →
123           asm_store … st1 = asm_store … st2 →
124           asm_stack … st1 = asm_stack … st2 →
125           asm_is_io … st1 = asm_is_io … st2 →
126           new_pc = pc … st2 →
127           op … (cost … st1) (cost_of p p' (Ijmp … new_pc) (asm_store … st1)) = cost … st2 →
128           vmstep … (cost_act (None ?)) st1 st2
129| vm_cjump_true :
130           ∀st1,st2 : vm_state p p'.∀cond,new_pc,ltrue,lfalse.
131           eval_asm_cond p p' cond (asm_store … st1) = return true→
132           fetch … prog (pc … st1) = return (CJump p cond new_pc ltrue lfalse) →
133           asm_is_io … st1 = false →
134           asm_store … st1 = asm_store … st2 →
135           asm_stack … st1 = asm_stack … st2 →
136           asm_is_io … st1 = asm_is_io … st2 →
137           pc … st2 = new_pc →
138           op … (cost … st1) (cost_of p p' (CJump p cond new_pc ltrue lfalse) (asm_store … st1)) = cost … st2 →
139           vmstep … (cost_act (Some ? ltrue)) st1 st2
140| vm_cjump_false :
141           ∀st1,st2 : vm_state p p'.∀cond,new_pc,ltrue,lfalse.
142           eval_asm_cond p p' cond (asm_store … st1) = return false→
143           fetch … prog (pc … st1) = return (CJump p cond new_pc ltrue lfalse) →
144           asm_is_io … st1 = false →
145           asm_store … st1 = asm_store … st2 →
146           asm_stack … st1 = asm_stack … st2 →
147           asm_is_io … st1 = asm_is_io … st2 →
148           S (pc … st1) = pc … st2 →
149           op … (cost … st1) (cost_of p p' (CJump … cond new_pc ltrue lfalse) (asm_store … st1)) = cost … st2 →
150           vmstep … (cost_act (Some ? lfalse)) st1 st2
151| vm_io_in : 
152           ∀st1,st2 : vm_state p p'.∀lin,io,lout.
153           fetch … prog (pc … st1) = return (Iio p lin io lout) →
154           asm_is_io … st1 = false →
155           asm_store … st1 = asm_store … st2 →
156           asm_stack … st1 = asm_stack … st2 →
157           true = asm_is_io … st2 →
158           pc … st1 = pc … st2 →
159           cost … st1 = cost … st2 →
160           vmstep … (cost_act (Some ? lin)) st1 st2
161| vm_io_out :
162           ∀st1,st2 : vm_state p p'.∀lin,io,lout.
163           fetch … prog (pc … st1) = return (Iio p lin io lout) →
164           asm_is_io … st1 = true →
165           eval_asm_io … io (asm_store … st1) = return asm_store … st2 →
166           asm_stack … st1 = asm_stack … st2 →
167           false = asm_is_io … st2 →
168           S (pc … st1) = pc … st2 →
169           op … (cost … st1) (cost_of_io p p' io (asm_store … st1)) = cost … st2 →
170           vmstep … (cost_act (Some ? lout)) st1 st2
171| vm_call :
172           ∀st1,st2 : vm_state p p'.∀f,lbl.
173           fetch … prog (pc … st1) = return (Icall p f) →
174           asm_is_io … st1 = false →
175           asm_store … st1 = asm_store … st2 →
176           S (pc … st1) ::  asm_stack … st1 = asm_stack … st2 →
177           asm_is_io … st1 = asm_is_io … st2 →
178           entry_of_function … prog f = pc … st2 →
179           op … (cost … st1) (cost_of p p' (Icall p f) (asm_store … st1)) = cost … st2 →
180           label_of_pc ? (call_label_fun … prog) (entry_of_function … prog f) = return lbl →
181           vmstep … (call_act f lbl) st1 st2
182| vm_ret :
183          ∀st1,st2 : vm_state p p'.∀newpc,lbl.
184           fetch … prog (pc … st1) = return (Iret p) →
185           asm_is_io … st1 = false →
186           asm_store … st1 = asm_store … st2 →
187           asm_stack … st1 = newpc ::  asm_stack … st2  →
188           asm_is_io … st1 = asm_is_io … st2 →
189           newpc = pc … st2 →
190           label_of_pc ? (return_label_fun … prog) newpc = return lbl →
191           op … (cost … st1) (cost_of p p' (Iret p) (asm_store … st1)) = cost … st2 →
192           vmstep … (ret_act (Some ? lbl)) st1 st2.
193
194definition eval_vmstate : ∀p : assembler_params.∀p' : sem_params p.
195AssemblerProgram p → vm_state p p' → option (ActionLabel × (vm_state p p')) ≝
196λp,p',prog,st.
197! i ← fetch … prog (pc … st);
198match i with
199[ Seq x opt_l ⇒
200   if asm_is_io … st then
201     None ?
202   else
203     ! new_store ← eval_asm_seq p p' x (asm_store … st);
204     return 〈cost_act opt_l,
205             mk_vm_state ?? (S (pc … st)) (asm_stack … st) new_store false
206                (op … (cost … st) (cost_of p p' (Seq p x opt_l) (asm_store … st)))〉
207| Ijmp newpc ⇒
208   if asm_is_io … st then
209     None ?
210   else
211     return 〈cost_act (None ?),
212             mk_vm_state ?? newpc (asm_stack … st) (asm_store … st) false
213                (op … (cost … st) (cost_of p p' (Ijmp … newpc) (asm_store … st)))〉
214| CJump cond newpc ltrue lfalse ⇒
215   if asm_is_io … st then
216     None ?
217   else
218     ! b ← eval_asm_cond p p' cond (asm_store … st);
219     if b then
220       return 〈cost_act (Some ? ltrue),
221               mk_vm_state ?? newpc (asm_stack … st) (asm_store … st) false
222                (op … (cost … st) (cost_of p p' (CJump … cond newpc ltrue lfalse) (asm_store … st)))〉
223     else
224       return 〈cost_act (Some ? lfalse),
225               mk_vm_state ?? (S (pc … st)) (asm_stack … st) (asm_store … st) false
226                (op … (cost … st) (cost_of p p' (CJump … cond newpc ltrue lfalse) (asm_store … st)))〉
227| Iio lin io lout ⇒
228              if asm_is_io … st then
229                 ! new_store ← eval_asm_io … io (asm_store … st);
230                 return 〈cost_act (Some ? lout),
231                         mk_vm_state ?? (S (pc … st)) (asm_stack … st)
232                         new_store false
233                         (op … (cost … st)
234                               (cost_of_io p p' io (asm_store … st)))〉   
235              else
236                return 〈cost_act (Some ? lin),
237                        mk_vm_state ?? (pc … st) (asm_stack … st) (asm_store … st)
238                                    true (cost … st)〉
239| Icall f ⇒
240    if asm_is_io … st then
241      None ?
242    else
243      ! lbl ← label_of_pc ? (call_label_fun … prog) (entry_of_function … prog f);
244      return 〈call_act f lbl,
245              mk_vm_state ?? (entry_of_function … prog f)
246                             ((S (pc … st)) :: (asm_stack … st))
247                             (asm_store … st) false
248                             (op … (cost … st) (cost_of p p' (Icall p f) (asm_store … st)))〉
249| Iret ⇒ if asm_is_io … st then
250            None ?
251         else
252            ! 〈newpc,tl〉 ← option_pop … (asm_stack … st);
253            ! lbl ← label_of_pc ? (return_label_fun … prog) newpc;
254            return 〈ret_act (Some ? lbl),
255                    mk_vm_state ?? newpc tl (asm_store … st) false   
256                     (op … (cost … st) (cost_of p p' (Iret p) (asm_store … st)))〉
257].
258
259lemma eval_vmstate_to_Prop : ∀p,p',prog,st1,st2,l.
260eval_vmstate p p' prog st1 = return 〈l,st2〉 → vmstep … prog l st1 st2.
261#p #p' #prog #st1 #st2 #l whd in match eval_vmstate; normalize nodelta
262#H cases(bind_inversion ????? H) -H * normalize nodelta
263[ #seq #opt_l * #EQfetch inversion(asm_is_io ???) normalize nodelta
264  [ #_ whd in ⊢ (??%% → ?); #EQ destruct] #EQio #H cases(bind_inversion ????? H)
265  #newstore * #EQnewstore whd in ⊢ (??%% → ?); #EQ destruct
266  @vm_seq //
267| #newpc * #EQfetch inversion(asm_is_io ???) normalize nodelta #EQio
268  [ whd in ⊢ (??%% → ?); #EQ destruct] whd in ⊢ (??%% → ?); #EQ destruct
269  @vm_ijump //
270| #cond #new_pc #ltrue #lfase * #EQfetch inversion(asm_is_io ???) normalize nodelta
271  [ #_ whd in ⊢ (??%% → ?); #EQ destruct] #EQio #H cases(bind_inversion ????? H) -H
272  * normalize nodelta * #EQcond whd in ⊢ (??%% → ?); #EQ destruct
273  [ @(vm_cjump_true … EQfetch) // | @(vm_cjump_false … EQfetch) //]
274| #lin #io #lout * #EQfetch inversion(asm_is_io ???) normalize nodelta #EQio
275  [ #H cases(bind_inversion ????? H) -H #newstore * #EQnewstore ]
276  whd in ⊢ (??%% → ?); #EQ destruct
277  [ @(vm_io_out … EQfetch) // | @(vm_io_in … EQfetch) // ]
278| #f * #EQfetch inversion(asm_is_io ???) #EQio normalize nodelta
279  [ whd in ⊢ (??%% → ?); #EQ destruct ] #H cases (bind_inversion ????? H) -H
280  #lbl * #EQlb whd in ⊢ (??%% → ?); #EQ destruct @(vm_call … EQfetch) //
281| * #EQfetch inversion(asm_is_io ???) normalize nodelta #EQio
282  [ whd in ⊢ (??%% → ?); #EQ destruct] #H cases(bind_inversion ????? H) -H
283  * #newpc #tl * whd in match option_pop; normalize nodelta inversion(asm_stack ???)
284  normalize nodelta [#_ whd in ⊢ (??%% → ?); #EQ destruct] #newpc1 #tl1 #_
285  #EQstack whd in ⊢ (??%% → ?); #EQ destruct #H cases(bind_inversion ????? H) #lbl
286  * #EQlbl whd in ⊢ (??%% → ?); #EQ destruct @vm_ret //
287]
288qed.
289
290 
291lemma vm_step_to_eval : ∀p,p',prog,st1,st2,l.vmstep … prog l st1 st2 →
292eval_vmstate p p' prog st1 = return 〈l,st2〉.
293#p #p' #prog * #pc1 #stack1 #store1 #io1 #cost1
294* #pc2 #stack2 #store2 #io2 #cost2 #l #H inversion H
295[ #s1 #s2 #i #opt_l #EQfetch #EQio #EQstore #EQstack #EQio1 #EQpc #EQcost
296  #EQ1 #EQ2 #EQ3 #EQ4 destruct whd in match eval_vmstate; normalize nodelta   
297  >EQfetch >m_return_bind normalize nodelta >EQio normalize nodelta >EQstore
298  >m_return_bind <EQio1 >EQio <EQpc >EQstack >EQcost %
299| #s1 #s2 #newpc #EQfetch #EQio1 #EQstore #EQstack #EQio2 #EQnewpc #EQcost
300  #EQ1 #EQ2 #EQ3 #EQ4 destruct whd in match eval_vmstate; normalize nodelta
301  >EQfetch >m_return_bind normalize nodelta >EQio1 normalize nodelta <EQio2 >EQio1
302  >EQstore >EQstack <EQcost >EQstore %
303|3,4: #s1 #s2 #cond #newoc #ltrue #lfalse #EQev_cond #EQfetch #EQio1 #EQstore
304  #EQstack #EQio2 #EQnewoc #EQcost #EQ1 #EQ2 #EQ3 #EQ4 destruct
305  whd in match eval_vmstate; normalize nodelta >EQfetch >m_return_bind
306  normalize nodelta >EQio1 normalize nodelta >EQev_cond >m_return_bind
307  normalize nodelta <EQio1 >EQio2 >EQstore >EQstack <EQcost >EQstore [%] >EQnewoc %
308|5,6: #s1 #s2 #lin #io #lout #EQfetch #EQio1 #EQstore #EQstack #EQio2 #EQpc
309   #EQcost #EQ1 #EQ2 #EQ3 #EQ4 destruct whd in match eval_vmstate;
310   normalize nodelta >EQfetch >m_return_bind normalize nodelta >EQio1
311   normalize nodelta >EQstack <EQpc >EQcost [ >EQstore <EQio2 %]
312   >EQstore >m_return_bind <EQpc <EQio2 %
313| #s1 #s2 #f #lbl #EQfetch #EQio1 #EQstore #EQstack #EQio2 #EQentry
314  #EQcost #EQlab_pc #EQ1 #EQ2 #EQ3 #EQ4 destruct whd in match eval_vmstate;
315  normalize nodelta >EQfetch >m_return_bind normalize nodelta >EQio1
316  normalize nodelta >EQlab_pc >m_return_bind >EQentry >EQcost <EQio2 >EQio1
317  <EQstack >EQstore %
318| #s1 #s2 #newpc #lbl #EQfetch #EQio1 #EQstore #EQstack #EQio2 #EQnewpc
319  #EQlab_pc #EQcosts #EQ1 #EQ2 #EQ3 #EQ4 destruct whd in match eval_vmstate;
320  normalize nodelta >EQfetch >m_return_bind normalize nodelta >EQio1 normalize nodelta
321  >EQstack whd in match option_pop; normalize nodelta >m_return_bind
322  >EQlab_pc >m_return_bind >EQcosts >EQstore  <EQio2 >EQio1 %
323]
324qed.
325
326coercion vm_step_to_eval.
327
328include "../src/utilities/hide.ma".
329
330discriminator option.
331
332inductive vm_ass_state  (p : assembler_params) (p' : sem_params p) : Type[0] ≝
333| INITIAL : vm_ass_state p p'
334| FINAL : vm_ass_state p p'
335| STATE : vm_state p p' → vm_ass_state p p'.
336
337definition asm_operational_semantics : ∀p.sem_params p → AssemblerProgram p →  abstract_status ≝
338λp,p',prog.let init_act ≝ cost_act (Some ? (in_act … prog)) in
339           let end_act ≝ cost_act (Some ? (in_act … prog)) in
340    mk_abstract_status
341                (vm_ass_state p p')
342                (λl.λs1,s2 : vm_ass_state p p'.
343                    match s1 with
344                    [ STATE st1 ⇒
345                        match s2 with
346                        [ STATE st2 ⇒ 
347                            (eqb (pc ?? st1) (endmain … prog)) = false ∧ vmstep p p' prog l st1 st2
348                        | INITIAL ⇒ False
349                        | FINAL ⇒ eqb (pc … st1) (endmain … prog) = true ∧ l = end_act
350                        ]
351                    | INITIAL ⇒ match s2 with
352                                [ STATE st2 ⇒ eqb (pc … st2) O = true ∧ l = init_act
353                                | _ ⇒ False
354                                ]
355                    | FINAL ⇒ False
356                    ])
357                (λ_.λ_.True)
358                (λst.match st with
359                    [ INITIAL ⇒ cl_other | FINAL ⇒ cl_other |
360                     STATE s ⇒
361                      match fetch … prog (pc … s) with
362                      [ Some i ⇒ match i with
363                               [ Seq _ _ ⇒ cl_other
364                               | Ijmp _ ⇒ cl_other
365                               | CJump _ _ _ _ ⇒ cl_jump
366                               | Iio _ _ _ ⇒ if asm_is_io … s then cl_io else cl_other
367                               | Icall _ ⇒ cl_other
368                               | Iret ⇒ cl_other
369                               ]
370                     | None ⇒ cl_other
371                     ]
372                    ]
373                )
374                (λ_.true)
375                (λs.match s with [ INITIAL ⇒ true | _ ⇒ false])
376                (λs.match s with [ FINAL ⇒ true | _ ⇒ false])
377                ???.
378@hide_prf
379[ #s1 #s2 #l
380 cases s1 normalize nodelta [1,2: #abs destruct] -s1 #s1
381 cases s2 normalize nodelta [1: #_ * |2: #_ * #_ #EQ >EQ normalize /2/ ] #s2 
382 inversion(fetch ???) normalize nodelta
383  [ #_ #EQ destruct] * normalize nodelta
384  [ #seq #lbl #_
385  | #n #_
386  | #cond #newpc #ltrue #lfalse #EQfetch
387  | #lin #io #lout #_ cases (asm_is_io ??) normalize nodelta
388  | #f #_
389  | #_
390  ]
391  #EQ destruct * #_ #H lapply(vm_step_to_eval … H) whd in match eval_vmstate;
392  normalize nodelta >EQfetch >m_return_bind normalize nodelta cases(asm_is_io ??)
393  normalize nodelta [ whd in ⊢ (??%% → ?); #EQ destruct] #H cases(bind_inversion ????? H) -H
394  * * #_ normalize nodelta whd in ⊢ (??%% → ?); #EQ destruct % //
395| #s1 #s2 #l
396  cases s1 normalize nodelta [2: #_ * |3: #s1 ]
397  cases s2 normalize nodelta [1,2,4,5: #abs destruct ] #s2 [2: #_ * #_ /2/ ]
398  inversion(fetch ???) normalize nodelta
399  [ #_ #EQ destruct] * normalize nodelta
400  [ #seq #lbl #_
401  | #n #_
402  | #cond #newpc #ltrue #lfalse #_
403  | #lin #io #lout #EQfetch inversion (asm_is_io ??) #EQio normalize nodelta
404  | #f #_
405  | #_
406  ]
407  #EQ destruct * #_ #H lapply(vm_step_to_eval … H) whd in match eval_vmstate;
408  normalize nodelta #H cases(bind_inversion ????? H) -H *
409  [ #seq1 #lbl1
410  | #n1
411  | #cond1 #newpc1 #ltrue1 #lfalse1
412  | #lin1 #io1 #lout1
413  | #f
414  |
415  ]
416  normalize nodelta * #_ cases(asm_is_io ??) normalize nodelta
417  [1,3,5,9,11: whd in ⊢ (??%% → ?); #EQ destruct
418  |2,6,7,10,12: #H cases(bind_inversion ????? H) -H #x * #_
419    [2: cases x normalize nodelta
420    |5: #H cases(bind_inversion ????? H) -H #y * #_
421    ]
422  ]
423  whd in ⊢ (??%% → ?); #EQ destruct destruct % //
424| #s1 #s2 #l
425  cases s1 normalize nodelta [1,2: #abs destruct ] #s1
426  cases s2 normalize nodelta [ #_ * | #_ * /2/ ] #s2
427  inversion(fetch ???) normalize nodelta
428  [ #_ #EQ destruct] * normalize nodelta
429  [ #seq #lbl #_
430  | #n #_
431  | #cond #newpc #ltrue #lfalse #_
432  | #lin #io #lout #EQfetch inversion(asm_is_io ??) normalize nodelta #EQio
433  | #f #_
434  | #_
435  ]
436  #EQ destruct * #_ #H lapply(vm_step_to_eval … H) whd in match eval_vmstate;
437  normalize nodelta  >EQfetch >m_return_bind normalize nodelta >EQio
438  normalize nodelta #H cases(bind_inversion ????? H) -H #x * #_
439  whd in ⊢ (??%% → ?); #EQ destruct % //
440qed.
441
442definition asm_concrete_trans_sys ≝
443λp,p',prog.mk_concrete_transition_sys …
444             (asm_operational_semantics p p' prog) (m … p')
445             (λs.match s with [STATE st ⇒ cost … st | _ ⇒ e …] ).
446
447definition emits_labels ≝
448λp.λinstr : AssemblerInstr p.match instr with
449        [ Seq _ opt_l ⇒ match opt_l with
450                        [ None ⇒ Some ? (λpc.S pc)
451                        | Some _ ⇒ None ?
452                        ]
453        | Ijmp newpc ⇒ Some ? (λ_.newpc)
454        | _ ⇒ None ?
455        ].
456
457definition fetch_state : ∀p,p'.AssemblerProgram p → vm_state p p' → option (AssemblerInstr p) ≝
458λp,p',prog,st.fetch … prog (pc … st).
459
460definition asm_static_analisys_data ≝ λp,p',prog,abs_t,instr_m.
461mk_static_analysis_data (asm_concrete_trans_sys p p' prog) abs_t (option (AssemblerInstr p))
462 (λs.match s with [ STATE st ⇒ if eqb (pc … st) (endmain … prog) then
463                                   Some ? (None ?)
464                               else ! x ← fetch_state p p' prog st; Some ? (Some ? x)
465                  | INITIAL ⇒ Some ? (None ?)
466                  | FINAL  ⇒ None ? ]) instr_m.
467
468definition non_empty_list : ∀A.list A → bool ≝
469λA,l.match l with [ nil ⇒ false | _ ⇒  true ].
470
471let rec block_cost (p : assembler_params)
472 (prog: AssemblerProgram p) (abs_t : monoid)
473 (instr_m : AssemblerInstr p → abs_t)
474 (prog_c: option ℕ)
475    (program_size: ℕ)
476        on program_size: option abs_t ≝
477match prog_c with
478[ None ⇒ return e … abs_t
479| Some program_counter ⇒
480  match program_size with
481    [ O ⇒ None ?
482    | S program_size' ⇒
483       if eqb program_counter (endmain … prog) then
484        return e … abs_t
485      else
486      ! instr ← fetch … prog program_counter;
487      ! n ← (match emits_labels … instr with
488            [ Some f ⇒ block_cost … prog abs_t instr_m (Some ? (f program_counter)) program_size'
489            | None ⇒ return e …
490            ]);
491      return (op … abs_t (instr_m … instr) n)
492    ]
493].
494
495
496record cost_map_T (dom : DeqSet) (codom : Type[0]) : Type[1] ≝
497{ map_type :> Type[0]
498; empty_map : map_type
499; get_map : map_type → dom → option codom
500; set_map : map_type → dom → codom → map_type
501; get_set_hit : ∀k,v,m.get_map (set_map m k v) k = return v
502; get_set_miss : ∀k1,k2,v,m.(k1 == k2) = false → get_map (set_map m k1 v) k2 = get_map m k2
503}.
504
505
506
507lemma labels_pc_ok : ∀p,prog,l1,l2,i_act,i,lbl,pc,m.
508nth_opt ? pc prog = return i →
509mem ? lbl (labels_pc_of_instr … i (m+pc)) →
510mem ? lbl (labels_pc p prog l1 l2 i_act m).
511#p #instrs #l1 #l2 #iact #i #lbl #pc
512whd in match fetch; normalize nodelta lapply pc -pc
513elim instrs
514[ #pc #m whd in ⊢ (??%% → ?); #EQ destruct]
515#x #xs #IH * [|#pc'] #m  whd in ⊢ (??%% → ?);
516[ #EQ destruct #lbl_addr whd in match (labels_pc ???);
517  /2 by mem_append_l1/
518| #EQ #H2 whd in match (labels_pc ???); @mem_append_l2 @(IH … EQ) //
519]
520qed.
521
522lemma labels_pf_in_act: ∀p,prog,pc.
523  mem CostLabel (in_act p prog)
524  (map (CostLabel×ℕ) CostLabel \fst
525   (labels_pc p (instructions p prog) (call_label_fun p prog)
526    (return_label_fun p prog) (in_act p prog) pc)).
527 #p #prog elim (instructions p prog) normalize /2/
528qed.
529
530lemma labels_pc_return: ∀p,prog,l1,l2,iact,x1,x2.
531 label_of_pc ReturnPostCostLabel l2 x1=return x2 →
532 ∀m.
533   mem … 〈(a_return_post x2),x1〉 (labels_pc p prog l1 l2 iact m).
534 #p #l #l1 #l2 #iact whd in match (labels_pc ???); #x1 #x2 #H elim l
535[ #m @mem_append_l2 @mem_append_l2 whd in H:(??%?);
536  elim l2 in H; [ whd in ⊢ (??%% → ?); #EQ destruct]
537  * #x #y #tl #IH whd in ⊢ (??%? → %); normalize nodelta @eqb_elim
538  normalize nodelta
539  [ #EQ whd in ⊢ (??%% → ?); #EQ2 destruct /2/
540  | #NEQ #H2 %2 @IH // ]
541| #hd #tl #IH #m @mem_append_l2 @IH ]
542qed.
543
544lemma labels_pc_call: ∀p,prog,l1,l2,iact,x1,x2.
545 label_of_pc CallCostLabel l1 x1=return x2 →
546 ∀m.
547   mem … 〈(a_call x2),x1〉 (labels_pc p prog l1 l2 iact m).
548 #p #l #l1 #l2 #iact whd in match (labels_pc ???); #x1 #x2 #H elim l
549[ #m @mem_append_l2 @mem_append_l1 whd in H:(??%?);
550  elim l1 in H; [ whd in ⊢ (??%% → ?); #EQ destruct]
551  * #x #y #tl #IH whd in ⊢ (??%? → %); normalize nodelta @eqb_elim
552  normalize nodelta
553  [ #EQ whd in ⊢ (??%% → ?); #EQ2 destruct /2/
554  | #NEQ #H2 %2 @IH // ]
555| #hd #tl #IH #m @mem_append_l2 @IH ]
556qed.
557
558(*
559lemma labels_pc_bounded : ∀p.∀prog : AssemblerProgram p.∀lbl,pc.∀m.
560mem ? 〈lbl,pc〉 (labels_pc p (instructions … prog) m) →
561(m + pc) < (|(instructions … prog)|).
562#p * #instr #endmain #_  #H1 #H2 elim instr
563[ #H3 @⊥ /2/ ] #x #xs #IH #_ #lbl #pc #m whd in match (labels_pc ???);
564#H cases(mem_append ???? H) -H
565[ whd in match labels_pc_of_instr; normalize nodelta
566  cases x normalize nodelta
567  [ #seq * [|#lab]
568  | #newpc
569  | #cond #newpc #ltrue #lfalse
570  | #lin #io #lout
571  | #f
572  |
573  ]
574  normalize [1,3,6,7: *] * [2,4,6: * [2,4:*] ]
575  #EQ destruct
576*) 
577
578let rec m_foldr (M : Monad) (X,Y : Type[0]) (f : X→Y→M Y) (l : list X) (y : Y) on l : M Y ≝
579match l with
580[ nil ⇒ return y
581| cons x xs ⇒ ! z ← m_foldr M X Y f xs y; f x z
582].
583
584definition static_analisys : ∀p : assembler_params.∀abs_t : monoid.(AssemblerInstr p → abs_t) →
585∀mT : cost_map_T DEQCostLabel abs_t.AssemblerProgram p → option mT ≝
586λp,abs_t,instr_m,mT,prog.
587let prog_size ≝ S (|instructions … prog|) in
588m_foldr Option ?? (λx,m.let 〈z,w〉≝ x in ! k ← block_cost p prog abs_t instr_m (Some ? w) prog_size; 
589                               return set_map … m z k) (labels_pc … (instructions … prog)
590                                         (call_label_fun … prog) (return_label_fun … prog) (in_act … prog) O)
591      (empty_map ?? mT).
592     
593
594(*falso: necessita di no_duplicates*)
595
596definition eq_deq_prod : ∀D1,D2 : DeqSet.D1 × D2 → D1 × D2 → bool ≝
597λD1,D2,x,y.\fst x == \fst y ∧ \snd x == \snd y.
598
599definition DeqProd ≝ λD1 : DeqSet.λD2 : DeqSet.
600mk_DeqSet (D1 × D2) (eq_deq_prod D1 D2) ?.
601@hide_prf
602* #x1 #x2 * #y1 #y2 whd in match eq_deq_prod; normalize nodelta
603% [2: #EQ destruct @andb_Prop >(\b (refl …)) %]
604inversion (? ==?) #EQ1 whd in match (andb ??); #EQ2 destruct
605>(\P EQ1) >(\P EQ2) %
606qed.
607(*
608unification hint  0 ≔ D1,D2 ;
609    X ≟ DeqProd D1 D2
610(* ---------------------------------------- *) ⊢
611    D1 × D2 ≡ carr X.
612
613
614unification hint  0 ≔ D1,D2,p1,p2;
615    X ≟ DeqProd D1 D2
616(* ---------------------------------------- *) ⊢
617    eq_deq_prod D1 D2 p1 p2 ≡ eqb X p1 p2.
618   
619definition deq_prod_to_prod : ∀D1,D2 : DeqSet.DeqProd D1 D2 → D1 × D2 ≝
620λD1,D2,x.x.
621
622coercion deq_prod_to_prod.
623*)
624
625lemma map_mem : ∀A,B,f,l,a.mem A a l → ∃b : B.mem B b (map A B f l)
626∧ b = f a.
627#A #B #f #l elim l [ #a *] #x #xs #IH #a *
628[ #EQ destruct %{(f x)} % // % // | #H cases(IH … H)
629  #b * #H1 #EQ destruct %{(f a)} % // %2 //
630]
631qed.
632
633lemma static_analisys_ok : ∀p,abs_t,instr_m,mT,prog,lbl,pc,map.
634static_analisys p abs_t instr_m mT prog = return map →
635mem … 〈lbl,pc〉 (labels_pc … (instructions … prog) (call_label_fun … prog)
636                   (return_label_fun … prog) (in_act … prog) O) →
637get_map … map lbl =
638block_cost … prog abs_t instr_m (Some ? pc) (S (|(instructions … prog)|)) ∧
639block_cost … prog abs_t instr_m (Some ? pc) (S (|(instructions … prog)|)) ≠ None ?.
640#p #abs_t #instr_m #mT * #prog whd in match static_analisys; normalize nodelta
641#endmain #Hendmain #entry_fun #call_label_fun #return_label_fun #inact
642#nodup generalize in match nodup in ⊢ (∀_.∀_.∀_. (??(????%??)?) → %); #Hnodup lapply nodup -nodup
643lapply (labels_pc ??????) #l elim l [ #x #y #z #w #h * ]
644* #hd1 #hd2 #tl #IH * #H1 #H2 #lbl #pc #map #H
645cases(bind_inversion ????? H) -H #map1 * #EQmap1 normalize nodelta #H
646cases(bind_inversion ????? H) -H #elem * #EQelem whd in ⊢ (??%% → ?); #EQ
647destruct *
648[ #EQ destruct % [ >get_set_hit >EQelem % | >EQelem % whd in ⊢ (??%% → ?); #EQ destruct]
649| #H %
650  [ >get_set_miss [ @(proj1 … (IH …)) //] inversion (? == ?) [2: #_ %]
651    #ABS cases H1 -H1 #H1 @⊥ @H1 >(\P ABS) >mem_to_memb //
652    cases(map_mem … \fst … H) #z1 * #Hz1 #EQ destruct @Hz1
653  | @(proj2 … (IH …)) //
654  ]
655]
656qed.
657
658include "Simulation.ma".
659
660definition terminated_trace : ∀S : abstract_status.∀s1,s3 : S.raw_trace … s1 s3 → Prop ≝
661λS,s1,s3,t.∃s2: S.∃t1 : raw_trace … s1 s2.∃ l,prf.t = t1 @ (t_ind ? s2 s3 s3 l prf … (t_base … s3))
662∧ is_costlabelled_act l.
663
664definition big_op: ∀M: monoid. list M → M ≝
665 λM. foldl … (op … M) (e … M).
666
667lemma big_op_associative:
668 ∀M:monoid. ∀l1,l2.
669  big_op M (l1@l2) = op M (big_op … l1) (big_op … l2).
670 #M #l1 whd in match big_op; normalize nodelta
671 generalize in match (e M) in ⊢ (? → (??%(??%?))); elim l1
672 [ #c #l2 whd in match (append ???); normalize lapply(neutral_r … c)
673   generalize in match c in ⊢ (??%? → ???%); lapply c -c lapply(e M)
674   elim l2 normalize
675   [ #c #c1 #c2 #EQ @sym_eq //
676   | #x #xs #IH #c1 #c2 #c3 #EQ <EQ <IH [% | <is_associative % |]
677   ]
678 | #x #xs #IH #c #l2 @IH
679 ]
680qed.
681
682lemma act_big_op : ∀M,B. ∀act : monoid_action M B.
683 ∀l1,l2,x.
684   act (big_op M (l1@l2)) x = act (big_op … l2) (act (big_op … l1) x).
685 #M #B #act #l1 elim l1
686 [ #l2 #x >act_neutral //
687 | #hd #tl #IH #l2 #x change with ([?]@(tl@l2)) in match ([?]@(tl@l2));
688   >big_op_associative >act_op >IH change with ([hd]@tl) in match ([hd]@tl);
689   >big_op_associative >act_op in ⊢ (???%); %
690 ]
691qed.
692
693lemma monotonicity_of_block_cost : ∀p,prog,abs_t,instr_m,pc,size,k.
694block_cost p prog abs_t instr_m (Some ? pc) size = return k →
695∀size'.size ≤ size' →
696block_cost p prog abs_t instr_m (Some ? pc) size' = return k.
697#p #prog #abs_t #instr_m #pc #size lapply pc elim size
698[ #pc #k whd in ⊢ (??%% → ?); #EQ destruct]
699#n #IH #pc #k whd in ⊢ (??%% → ?); @eqb_elim
700[ #EQ destruct normalize nodelta whd in ⊢ (??%% → ?); #EQ destruct
701  #size' * [2: #m #_] whd in ⊢ (??%%); @eqb_elim try( #_ %) * #H @⊥ @H %
702| #Hpc normalize nodelta #H cases(bind_inversion ????? H) -H #i
703  * #EQi #H cases(bind_inversion ????? H) -H #elem * #EQelem whd in ⊢ (??%% → ?);
704  #EQ destruct #size' *
705  [ whd in ⊢ (??%?); @eqb_elim
706    [ #EQ @⊥ @(absurd ?? Hpc) assumption ]
707    #_ normalize nodelta >EQi >m_return_bind >EQelem %
708  | #m #Hm whd in ⊢ (??%?); @eqb_elim
709    [ #EQ @⊥ @(absurd ?? Hpc) assumption ]
710    #_ normalize nodelta >EQi >m_return_bind
711    cases (emits_labels ??) in EQelem; normalize nodelta
712    [ whd in ⊢ (??%%→ ??%%); #EQ destruct %]
713    #f #EQelem >(IH … EQelem) [2: /2/ ] %
714  ]
715]
716qed.
717
718lemma step_emit : ∀p,p',prog,st1,st2,l,i.
719fetch p prog (pc … st1) = return i →
720eval_vmstate p p' … prog st1 = return 〈l,st2〉 → 
721emits_labels … i = None ? → ∃x.
722match l in ActionLabel return λ_:ActionLabel.(list CostLabel) with 
723[call_act f c ⇒ [a_call c]
724|ret_act x ⇒
725   match x with [None⇒[]|Some c⇒[a_return_post c]]
726|cost_act x ⇒
727   match x with [None⇒[]|Some c⇒[a_non_functional_label c]]
728] = [x] ∧
729 (mem … 〈x,pc … st2〉 (labels_pc p (instructions … prog) (call_label_fun … prog) (return_label_fun … prog) (in_act … prog) O)).
730#p #p' #prog #st1 #st2 #l #i #EQi whd in match eval_vmstate; normalize nodelta
731>EQi >m_return_bind normalize nodelta cases i in EQi; -i normalize nodelta
732[ #seq * [|#lab]
733| #newpc
734| #cond #newpc #ltrue #lfalse
735| #lin #io #lout
736| #f
737|
738]
739#EQi cases(asm_is_io ???) normalize nodelta
740[1,3,5,7,11,13: whd in ⊢ (??%% → ?); #EQ destruct
741|2,4,8,9,12,14: #H cases(bind_inversion ????? H) -H #x1 * #EQx1
742  [3: cases x1 in EQx1; -x1 #EQx1 normalize nodelta
743  |6: #H cases(bind_inversion ????? H) -H #x2 * #EQx2
744  ]
745]
746whd in ⊢ (??%% → ?); #EQ destruct whd in match emits_labels;
747normalize nodelta #EQ destruct % [2,4,6,8,10,12,14: % try % |*:]
748[1,2,4,5,7: @(labels_pc_ok … EQi) normalize /3 by or_introl,or_intror/ ]
749/2 by labels_pc_return, labels_pc_call/
750qed.
751
752lemma step_non_emit : ∀p,p',prog,st1,st2,l,i,f.
753fetch p prog (pc … st1) = return i →
754eval_vmstate p p' … prog st1 = return 〈l,st2〉 → 
755emits_labels … i = Some ? f →
756match l in ActionLabel return λ_:ActionLabel.(list CostLabel) with 
757[call_act f c ⇒ [a_call c]
758|ret_act x ⇒
759   match x with [None⇒[]|Some c⇒[a_return_post c]]
760|cost_act x ⇒
761   match x with [None⇒[]|Some c⇒[a_non_functional_label c]]
762] = [ ] ∧ pc … st2 = f (pc … st1).
763#p #p' #prog #st1 #st2 #l #i #f #EQi whd in match eval_vmstate; normalize nodelta
764>EQi >m_return_bind normalize nodelta cases i in EQi; -i normalize nodelta
765[ #seq * [|#lab]
766| #newpc
767| #cond #newpc #ltrue #lfalse
768| #lin #io #lout
769| #f
770|
771]
772#EQi cases(asm_is_io ???) normalize nodelta
773[1,3,5,7,11,13: whd in ⊢ (??%% → ?); #EQ destruct
774|2,4,8,9,12,14: #H cases(bind_inversion ????? H) -H #x1 * #EQx1
775  [3: cases x1 in EQx1; -x1 #EQx1 normalize nodelta
776  |6: #H cases(bind_inversion ????? H) -H #x2 * #EQx2
777  ]
778]
779whd in ⊢ (??%% → ?); #EQ destruct whd in match emits_labels;
780normalize nodelta #EQ destruct /2 by refl, conj/
781qed.
782
783lemma labels_of_trace_are_in_code :
784∀p,p',prog.∀st1,st2 : vm_ass_state p p'.∀t : raw_trace (asm_operational_semantics p p' prog) … st1 st2.
785∀lbl.
786mem … lbl (get_costlabels_of_trace … t) →
787mem … lbl (map … \fst … (labels_pc … (instructions p prog) (call_label_fun … prog) (return_label_fun … prog) (in_act … prog) O)).
788#p #p' #prog #st1 #st2 #t elim t
789[ #st #lbl *
790| #st1 #st2 #st3 #l whd in ⊢ (% → ?);
791  cases st1 -st1 normalize nodelta [2: * |3: #st1]
792  cases st2 -st2 normalize nodelta [1,4,5: * |2: * #HN1 #HN2 >HN2 -HN2 |6: #st2 * #HN1 #HN2 >HN2 -HN2 |3: #st2 ]
793  [3: * #H1 #H2 #tl #IH #lbl whd in match (get_costlabels_of_trace ????);
794      #H cases(mem_append ???? H) -H [2: #H @IH //]
795      lapply(vm_step_to_eval … H2) whd in match eval_vmstate;
796      normalize nodelta #H cases(bind_inversion ????? H) -H #i * #EQi #_
797      inversion(emits_labels … i)
798      [ #EQemit cases(step_emit … (vm_step_to_eval … H2)) // #x * #EQ1 #EQ2 >EQ1 *
799        [2: *] #EQ destruct cases(map_mem … \fst … EQ2) #y * #H3 #EQ destruct //
800      | #f #EQemit >(proj1 … (step_non_emit … EQi (vm_step_to_eval … H2) … EQemit))
801        *
802      ]
803  |*: #tl #IH #lbl whd in match (get_costlabels_of_trace ????); * // @IH
804]
805qed.
806
807let rec dependent_map (A,B : Type[0]) (l : list A) (f : ∀a : A.mem … a l → B) on l : list B ≝
808(match l return λx.l=x → ? with
809[ nil ⇒ λ_.nil ?
810| cons x xs ⇒ λprf.(f x ?) :: dependent_map A B xs (λx,prf1.f x ?)
811])(refl …).
812[ >prf %% | >prf %2 assumption]
813qed.
814
815lemma dependent_map_append : ∀A,B,l1,l2,f.
816dependent_map A B (l1 @ l2) (λa,prf.f a prf) =
817(dependent_map A B l1 (λa,prf.f a ?)) @ (dependent_map A B l2 (λa,prf.f a ?)).
818[2: @hide_prf /2/ | 3: @hide_prf /2/]
819#A #B #l1 elim l1 normalize /2/
820qed.
821
822lemma rewrite_in_dependent_map : ∀A,B,l1,l2,f.
823        ∀EQ:l1 = l2.
824         dependent_map A B l1 (λa,prf.f a prf) =
825         dependent_map A B l2 (λa,prf.f a ?).
826[2: >EQ // | #A #B #l1 #l2 #f #EQ >EQ in f; #f % ]
827qed.
828
829definition get_pc : ∀p,p'.vm_ass_state p p' → ℕ → option ℕ ≝
830λp,p',st,endmain.match st with
831[ STATE s ⇒ Some ? (pc … s)
832| INITIAL ⇒ None ?
833| FINAL ⇒ Some ? endmain
834].
835
836
837lemma tbase_tind_append : ∀S : abstract_status.∀st1,st2,st3.∀t : raw_trace … st1 st2.
838∀l,prf.∀t'.
839t_base … st1 = t @ t_ind S st2 st3 st1 l prf t' → False.
840#S #st1 #st2 #st3 *
841[ #st #l #prf  #t' normalize #EQ lapply(eq_to_jmeq ??? EQ) -EQ #EQ destruct ]
842#s1 #s2 #s3 #l1 #prf1 #t2 #l2 #prf2 #t3 normalize #EQ lapply(eq_to_jmeq ??? EQ) -EQ #EQ destruct
843qed.
844
845let rec chop (A : Type[0]) (l : list A) on l : list A ≝
846match l with
847[ nil ⇒ nil ?
848| cons x xs ⇒ match xs with [ nil ⇒ nil ? | cons _ _ ⇒ x :: chop … xs]
849].
850
851lemma chop_append_singleton : ∀A : Type[0].∀x : A.∀l : list A.chop ? (l@ [x]) = l.
852#A #x #l elim l normalize // #y * normalize //
853qed.
854
855lemma chop_mem : ∀A : Type[0].∀x : A.∀l : list A. mem … x (chop ? l) → mem … x l.
856#A #x #l elim l [*] #y * [ normalize /2/] #z #zs #IH * [/2/] /3/
857qed.
858
859definition actionlabel_to_costlabel : ActionLabel → list CostLabel ≝
860λa.match a with
861[ call_act f l ⇒ [a_call l]
862| ret_act opt_l ⇒ match opt_l with [None ⇒ [ ] | Some l ⇒ [a_return_post l]]
863| cost_act opt_l ⇒ match opt_l with [None ⇒ [ ] | Some l ⇒ [a_non_functional_label l]]
864].
865
866lemma get_cost_label_of_trace_tind : ∀S : abstract_status.
867∀st1,st2,st3 : S.∀l,prf,t.
868get_costlabels_of_trace … (t_ind … st1 st2 st3 l prf t) =
869actionlabel_to_costlabel l @ get_costlabels_of_trace … t.
870#S #st1 #st2 #st3 * // qed.
871
872lemma actionlabel_ok :
873 ∀l : ActionLabel.
874  is_costlabelled_act l → ∃c.actionlabel_to_costlabel l = [c].
875* /2/ * /2/ *
876qed.
877
878lemma static_dynamic : ∀p,p',prog.
879∀abs_t : abstract_transition_sys (m … p').∀instr_m : (AssemblerInstr p) → abs_instr … abs_t.
880∀good : static_galois … (asm_static_analisys_data p p' prog abs_t
881 (λi.match i with [None ⇒ e …
882                  |Some x ⇒ instr_m x
883                  ])) .∀mT,map1.
884∀EQmap : static_analisys p ? instr_m mT prog = return map1.
885∀st1,st2 : vm_ass_state p p'.
886∀t : raw_trace (asm_operational_semantics p p' prog) … st1 st2.
887terminated_trace … t →
888∀k.
889pre_measurable_trace … t →
890block_cost p prog … instr_m (get_pc … st1 (endmain … prog)) (S (|(instructions … prog)|)) = return k →
891∀a1.rel_galois … good st1 a1 →
892∀labels.
893labels = dependent_map CostLabel ? (chop … (get_costlabels_of_trace …  t)) (λlbl,prf.(opt_safe … (get_map … map1 lbl) ?)) →
894rel_galois … good st2 (act_abs … abs_t (big_op … labels) (act_abs … abs_t k a1)).
895[2: @hide_prf
896    cases(mem_map ????? (labels_of_trace_are_in_code … (chop_mem … prf))) *
897    #lbl' #pc * #Hmem #EQ destruct   
898    >(proj1 … (static_analisys_ok … EQmap … Hmem))
899    @(proj2 … (static_analisys_ok … EQmap … Hmem))
900]
901#p #p' #prog #abs_t #instr_m #good #mT #map1 #EQmap #st1 #st2 #t * #st3 * #t1 * #l1 * #prf1 * #EQ destruct
902#Hlabelled >(rewrite_in_dependent_map ??? (get_costlabels_of_trace … t1))
903[2: >get_cost_label_append  >get_cost_label_of_trace_tind >append_nil cases(actionlabel_ok … Hlabelled)
904   #c #EQc >EQc //
905]   
906lapply Hlabelled lapply prf1 -prf1 lapply l1 -l1 elim t1 -st3
907[ * [3: #st] #l #prf #H1 #H2 #k whd in ⊢ (??%? → ?);
908  [3: cases prf
909  |2: whd in ⊢ (??%% → ?); #EQ destruct #a1 #rel_fin #labels whd in ⊢ (??%% → ?);
910      lapply(instr_map_ok … good … prf … rel_fin) [ %|] cases st2 in prf; -st2 [3: #st2] *
911      #EQpc #EQ destruct #H #EQ destruct >act_neutral >act_neutral normalize in H;
912      <(act_neutral ?? (act_abs ? abs_t) a1) @H
913  | @eqb_elim normalize nodelta
914    [ #EQpc whd in ⊢(??%% → ?); #EQ destruct #a1 #good_st_a1 #labels whd in ⊢ (??%% → ?);
915      #EQ destruct >act_neutral >act_neutral whd in prf; cases st2 in prf; -st2 [3: #st2]
916      normalize nodelta * >EQpc @eqb_elim [2,4: * #ABS @⊥ @ABS %] #_ #EQ destruct
917      #EQ destruct whd in EQc : (??%%); destruct
918      lapply(instr_map_ok …  good … good_st_a1)
919      [5: @(FINAL …)
920      |2: whd % [ >EQpc @eqb_elim // * #ABS @⊥ @ABS %] %
921      | whd in ⊢ (??%%); @eqb_elim [2: * #ABS @⊥ @ABS assumption
922      ]
923      #_ normalize nodelta % | | | whd in ⊢ (% → ?); >act_neutral //
924      ]
925  | #Hpc lapply prf whd in ⊢ (% → ?); cases st2 in prf; -st2 [3: #st2] #prf
926    normalize nodelta [2:* |3: * #ABS @⊥ lapply ABS -ABS @eqb_elim
927    [#EQ #_ @(absurd ? EQ Hpc) | #_ #EQ destruct ] ] * #INUTILE #H4
928    #H cases(bind_inversion ????? H) -H *
929    [ #seq * [|#lbl1]
930    | #newpc
931    | #cond #newpc #ltrue #lfalse
932    | #lin #io #lout
933    | #f
934    |
935    ]
936    * #EQfetch  lapply(vm_step_to_eval … H4) whd in match eval_vmstate;
937    normalize nodelta >EQfetch >m_return_bind normalize nodelta
938    cases(asm_is_io ??) normalize nodelta
939    [1,3,5,7,11,13: whd in ⊢ (??%% → ?); #EQ destruct
940    |2,4,8,9,12,14: #H cases(bind_inversion ????? H) -H #x * #_
941      [3: cases x normalize nodelta
942      |6: #H cases(bind_inversion ????? H) -H #y * #_
943      ]
944    ]
945    whd in ⊢ (??%% → ?); #EQ destruct [4,8: cases H1 ]
946    >m_return_bind whd in ⊢ (??%% → ?); #EQ destruct
947    #a1 #good_st_a1 whd in match (dependent_map ????); #costs #EQ destruct >neutral_r
948    >act_neutral
949    lapply(instr_map_ok … good … good_st_a1)
950    [1,7,13,19,25,31,37: whd in ⊢ (??%%); @eqb_elim normalize nodelta
951      [1,3,5,7,9,11,13: #EQ cases(absurd ? EQ Hpc) ] #_ whd in match fetch_state;
952        normalize nodelta
953        [ >EQfetch in ⊢ (??%?); | >EQfetch in ⊢ (??%?); | >EQfetch in ⊢ (??%?);
954        | >EQfetch in ⊢ (??%?); | >EQfetch in ⊢ (??%?); | >EQfetch in ⊢ (??%?);
955        | >EQfetch in ⊢ (??%?); ] %
956      |3,9,15,21,27,33,39: skip |*: try assumption // ]
957      ]
958    ]
959| -st1 * [3: #st1] #st3 #st4 #l [3: *] cases st3 -st3
960  [1,2,4,5: * #H1 #H2 #tl #_ #l1 #exe @⊥ lapply tl -tl lapply(refl ? (FINAL p p'))
961    generalize in match (FINAL ??) in ⊢ (??%? → %); #st5 #EQst5 #tl lapply EQst5
962    lapply exe lapply st2 -st2 -EQst5 elim tl
963    [ #st #st5 #ABS #EQ destruct cases ABS
964    | #s1 #s2 #s3 #l2 #H3 #tl1 #IH #s4 #_ #EQ destruct cases H3
965    ]
966  ]
967  #st3 #exe_st1_st3 #tl #IH #l1 #exe_st4_st2 #l1_lab #k #pre_meas whd in ⊢ (??%? → ?);
968  >rewrite_in_dependent_map [2,5: @get_cost_label_of_trace_tind |3,6: ]
969  >dependent_map_append
970  [ @eqb_elim [ #ABS @⊥ cases exe_st1_st3 >ABS @eqb_elim [ #_ #EQ destruct | * #ABS1 @⊥ @ABS1 %] ]
971    #Hpc normalize nodelta #H cases(bind_inversion ????? H) -H #i * #EQi
972    inversion(emits_labels ??)
973    [ #EQemits whd in ⊢ (??%% → ?); #EQ destruct #a1 #good_a1 #labels
974      cases(step_emit … EQi … EQemits)
975      [4: cases exe_st1_st3  #EQ #H @(vm_step_to_eval … H) |2,3:] #c * #EQc #Hc
976      whd in match actionlabel_to_costlabel; normalize nodelta
977      >rewrite_in_dependent_map [2: @EQc |3:] whd in match (dependent_map ????);
978      @opt_safe_elim #k_c #EQk_c whd in match (dependent_map ????); letin ih_labels ≝ (dependent_map ????)
979      #EQ destruct >big_op_associative >act_op @IH
980    | #f #EQemits normalize nodelta #H cases(bind_inversion ????? H) -H #k' * #EQk' whd in ⊢ (??%% → ?);
981      #EQ destruct(EQ) #a1 #good_a1 #labels cases(step_non_emit … EQi… EQemits)
982      [4: cases exe_st1_st3  #EQ #H @(vm_step_to_eval … H) |2,3:] #EQl #EQpc
983      >(rewrite_in_dependent_map ??? []) [2: assumption] whd in match (dependent_map ????);
984      #EQlabels >act_op @IH
985  ]
986  try //
987  [2: cases(static_analisys_ok … c … (pc … st3) … EQmap) // #EQ #_ <EQ whd in match (big_op ??);
988      >neutral_l assumption
989   |3: >neutral_r lapply(instr_map_ok … good … good_a1)
990       [ whd in ⊢ (??%?); @eqb_elim
991         [ #ABS cases(absurd ? ABS Hpc) ] #_ normalize nodelta whd in match fetch_state;
992         normalize nodelta >EQi in ⊢ (??%?); %
993       | assumption
994       |*:
995       ]
996       normalize in ⊢ (% → ?); #H @H
997   
998 
999   [2: assumption | | assumption | assumption | cases daemon (*TODO*)|
1000      whd in ⊢ (??%%);
1001  [1,5: inversion H in ⊢ ?;
1002    [1,6: #st #c #EQ1 #EQ2 #EQ3 #EQ4 destruct
1003    |2,7: #s1 #s2 #s3 #lbl #exe #tl1 #s1_noio * #opt_l #EQ destruct #pre_tl1 #_
1004      #EQ1 #EQ2 #EQ3 #EQ4 destruct
1005    |3,8: #s1 #s2 #s3 #lbl #s1_noio #exe #tl1 * #lbl1 #EQ destruct #pre_tl1 #_
1006      #EQ1 #EQ2 #EQ3 #EQ4 destruct
1007    |4,9: #s1 #s2 #s3 #lbl #exe #tl1 #s1_noio * #f * #lbl1 #EQ destruct
1008      * #pre_tl1 #_ #EQ1 #EQ2 #EQ3 #EQ4 destruct
1009    |5,10: #s1 #s2 #s3 #s4 #s5 #l1 #l2 #exe1 #t1 #t2 #exe2 #noio1 #noio2 #H *
1010    ] //
1011  | cases(step_emit … EQi (vm_step_to_eval … H4) … EQemits) #x * #EQx #Hx
1012    >(rewrite_in_dependent_map … EQx)
1013 
1014    whd in match (dependent_map ????); whd in match (dependent_map ????); whd in match (big_op ??);
1015    >neutral_l @opt_safe_elim #elem #EQget
1016    cases (static_analisys_ok  … x … (pc … st2) … no_dup … EQmap) //
1017    #EQ #_ <EQ assumption
1018  | >neutral_r  @(instr_map_ok … good … EQi … good_a1) /2/
1019  | %
1020  | >(proj2 … (step_non_emit … EQi (vm_step_to_eval … H4) … EQemits))
1021    >(monotonicity_of_block_cost … EQk') //
1022  | @(instr_map_ok … good … EQi … good_a1) /2/
1023  | lapply (proj1 … (step_non_emit … EQi (vm_step_to_eval … H4) … EQemits))
1024    #EQ >(rewrite_in_dependent_map … EQ) %
1025  ]
1026   
1027    >rewrite_in_dependent_map [2: @eq_f [2: @eq_f2 [3: % |4: @get_cost_label_append |*:] |*:] |3:]
1028    xxxxxx
1029   
1030    >dependent_map_append
1031  inversion(emits_labels ??)
1032  [ #EQemits whd in ⊢ (??%% → ?); #EQ destruct #a1 #good_a1 #labels
1033    >rewrite_in_dependent_map #EQlabels
1034    >neutral_r check big_op_associative @IH
1035    >big_op_associative >act_op @IH
1036  | #f #EQemits normalize nodelta #H
1037    cases(bind_inversion ????? H) -H #k' * #EQk' whd in ⊢ (??%% → ?);
1038    #EQ destruct(EQ) >act_op whd in match (append ???); @IH
1039  ]
1040  [1,5: inversion H in ⊢ ?;
1041    [1,6: #st #c #EQ1 #EQ2 #EQ3 #EQ4 destruct
1042    |2,7: #s1 #s2 #s3 #lbl #exe #tl1 #s1_noio * #opt_l #EQ destruct #pre_tl1 #_
1043      #EQ1 #EQ2 #EQ3 #EQ4 destruct
1044    |3,8: #s1 #s2 #s3 #lbl #s1_noio #exe #tl1 * #lbl1 #EQ destruct #pre_tl1 #_
1045      #EQ1 #EQ2 #EQ3 #EQ4 destruct
1046    |4,9: #s1 #s2 #s3 #lbl #exe #tl1 #s1_noio * #f * #lbl1 #EQ destruct
1047      * #pre_tl1 #_ #EQ1 #EQ2 #EQ3 #EQ4 destruct
1048    |5,10: #s1 #s2 #s3 #s4 #s5 #l1 #l2 #exe1 #t1 #t2 #exe2 #noio1 #noio2 #H *
1049    ] //
1050  | cases(step_emit … EQi (vm_step_to_eval … H4) … EQemits) #x * #EQx #Hx
1051    >(rewrite_in_dependent_map … EQx)
1052 
1053    whd in match (dependent_map ????); whd in match (dependent_map ????); whd in match (big_op ??);
1054    >neutral_l @opt_safe_elim #elem #EQget
1055    cases (static_analisys_ok  … x … (pc … st2) … no_dup … EQmap) //
1056    #EQ #_ <EQ assumption
1057  | >neutral_r  @(instr_map_ok … good … EQi … good_a1) /2/
1058  | %
1059  | >(proj2 … (step_non_emit … EQi (vm_step_to_eval … H4) … EQemits))
1060    >(monotonicity_of_block_cost … EQk') //
1061  | @(instr_map_ok … good … EQi … good_a1) /2/
1062  | lapply (proj1 … (step_non_emit … EQi (vm_step_to_eval … H4) … EQemits))
1063    #EQ >(rewrite_in_dependent_map … EQ) %
1064  ]
1065]
1066       
1067  ]
1068 
1069 
1070 
1071  * #i * #EQi inversion(emits_labels …) normalize nodelta
1072       
1073     
1074       >(act_neutral … a1) in H;
1075     
1076     
1077       #H #H1
1078      cases st2 in prf; -st2 [3: #st2] #prf
1079      lapply(instr_map_ok … good … prf … rel_fin)
1080     
1081       lapply prf *
1082      #EQpc_st2 #EQ destruct normalize nodelta whd in ⊢ (??%% → ?); #EQ destruct
1083      >act_neutral >act_neutral @(instr_map_ok … good … rel_fin)
1084     
1085     
1086       @opt_safe_elim #k_init
1087      #EQk_init whd in ⊢ (??%% → ?); whd in match (dependent_map ????); #EQ destruct
1088      >act_neutral whd in match (big_op ??); >act_op >act_neutral
1089     
1090     
1091       #H >act_neutral whd in prf;
1092       
1093        cases l in prf H1 H2;
1094        [1,4: #f #lbl |2,5: * [2,4: #lbl] |*: * [2,4: #lbl] ] #prf
1095        ** [normalize in ⊢ (% → ?);
1096         ⊢ (??%% → ?);
1097
1098 #st * #st3 * #t1 * #l * #prf * #ABS cases(tbase_tind_append … ABS) ]
1099  cases st -st [3: #x] * #H #_ whd in ⊢ (??%% → ?); @eqb_elim [2: * #ABS @⊥ @ABS %]
1100   #_ normalize nodelta whd in ⊢ (??%% → ?); #EQ destruct #a1 #rel_fin_a1
1101   #labels whd in ⊢ (???% → ?); #EQ destruct >act_neutral >act_neutral assumption
1102| -st1 -st2 * [3: #st1] * [3,6,9: #st2] #st3 #l whd in ⊢ (% → ?); *
1103  [ #no_final #Hstep #tl #IH whd in ⊢ (% → ?);
1104   (*
1105    #EQlabels
1106  #EQr_post #k #_ lapply(R_fin_ok … ter) >EQr_post normalize nodelta
1107  [ whd in ⊢ (?% → ?); #final_st whd in ⊢ (??%? → ?); >final_st
1108    normalize nodelta whd in ⊢ (??%% → ?); #EQ destruct(EQ)
1109    #a1 #rel_st_a1 whd in match (map ????); #costs #EQ >EQ >act_neutral >act_neutral assumption
1110  | ** #H1 #H2 * #H3 #H4 whd in ⊢ (??%% → ?); >H3 normalize nodelta
1111    #H cases(bind_inversion ????? H) -H *
1112    [ #seq * [|#lbl1]
1113    | #newpc
1114    | #cond #newpc #ltrue #lfalse
1115    | #lin #io #lout
1116    | #f
1117    |
1118    ]
1119    * #EQfetch lapply(vm_step_to_eval … H4) whd in match eval_vmstate;
1120    normalize nodelta >EQfetch >m_return_bind normalize nodelta
1121    cases(asm_is_io ??) normalize nodelta
1122    [1,3,5,7,11,13: whd in ⊢ (??%% → ?); #EQ destruct
1123    |2,4,8,9,12,14: #H cases(bind_inversion ????? H) -H #x * #_
1124      [3: cases x normalize nodelta
1125      |6: #H cases(bind_inversion ????? H) -H #y * #_
1126      ]
1127    ]
1128    whd in ⊢ (??%% → ?); #EQ destruct
1129    [4,8: cases H1 [1,3: * |*: * #y #EQ destruct]]
1130    >m_return_bind whd in ⊢ (??%% → ?); #EQ destruct
1131    #a1 #good_st_a1 whd in match (dependent_map ????); #costs #EQ >EQ >neutral_r
1132    >act_neutral
1133    @(instr_map_ok … good … EQfetch … good_st_a1) /2/
1134  ]*)
1135| -st1 -st2 #st1 #st2 #st3 #l * #H3 #H4 #tl #IH #ter #k #H
1136  #H2 #a1 #good_a1 whd in match (get_costlabels_of_trace ????);
1137  whd #costs >dependent_map_append
1138  (*change with (list_cost_to_list_initcost ?) in match (list_cost_to_list_initcost ?);*) 
1139  #EQ destruct whd in H2 : (??%?); lapply H2 >H3 in ⊢ (% → ?); -H2
1140  normalize nodelta #H cases(bind_inversion ????? H) -H #i * #EQi
1141  inversion(emits_labels ??)
1142  [ #EQemits whd in ⊢ (??%% → ?); #EQ destruct  >big_op_associative >act_op @IH
1143  | #f #EQemits normalize nodelta #H
1144    cases(bind_inversion ????? H) -H #k' * #EQk' whd in ⊢ (??%% → ?);
1145    #EQ destruct(EQ) >act_op whd in match (append ???); @IH
1146  ]
1147  [1,5: inversion H in ⊢ ?;
1148    [1,6: #st #c #EQ1 #EQ2 #EQ3 #EQ4 destruct
1149    |2,7: #s1 #s2 #s3 #lbl #exe #tl1 #s1_noio * #opt_l #EQ destruct #pre_tl1 #_
1150      #EQ1 #EQ2 #EQ3 #EQ4 destruct
1151    |3,8: #s1 #s2 #s3 #lbl #s1_noio #exe #tl1 * #lbl1 #EQ destruct #pre_tl1 #_
1152      #EQ1 #EQ2 #EQ3 #EQ4 destruct
1153    |4,9: #s1 #s2 #s3 #lbl #exe #tl1 #s1_noio * #f * #lbl1 #EQ destruct
1154      * #pre_tl1 #_ #EQ1 #EQ2 #EQ3 #EQ4 destruct
1155    |5,10: #s1 #s2 #s3 #s4 #s5 #l1 #l2 #exe1 #t1 #t2 #exe2 #noio1 #noio2 #H *
1156    ] //
1157  | cases(step_emit … EQi (vm_step_to_eval … H4) … EQemits) #x * #EQx #Hx
1158    >(rewrite_in_dependent_map … EQx)
1159 
1160    whd in match (dependent_map ????); whd in match (dependent_map ????); whd in match (big_op ??);
1161    >neutral_l @opt_safe_elim #elem #EQget
1162    cases (static_analisys_ok  … x … (pc … st2) … no_dup … EQmap) //
1163    #EQ #_ <EQ assumption
1164  | >neutral_r  @(instr_map_ok … good … EQi … good_a1) /2/
1165  | %
1166  | >(proj2 … (step_non_emit … EQi (vm_step_to_eval … H4) … EQemits))
1167    >(monotonicity_of_block_cost … EQk') //
1168  | @(instr_map_ok … good … EQi … good_a1) /2/
1169  | lapply (proj1 … (step_non_emit … EQi (vm_step_to_eval … H4) … EQemits))
1170    #EQ >(rewrite_in_dependent_map … EQ) %
1171  ]
1172]
1173qed.
1174
1175definition actionlabel_to_costlabel : ActionLabel → list CostLabel ≝
1176λa.match a with
1177[ call_act f l ⇒ [a_call l]
1178| ret_act opt_l ⇒ match opt_l with [None ⇒ [ ] | Some l ⇒ [a_return_post l]]
1179| cost_act opt_l ⇒ match opt_l with [None ⇒ [ ] | Some l ⇒ [a_non_functional_label l]]
1180].
1181
1182definition get_costlabels_of_measurable_trace : ∀S : abstract_status.measurable_trace S → list CostLabel ≝
1183λS,t.
1184 match L_label … t with
1185 [ None ⇒ [i_act]
1186 | Some l ⇒ actionlabel_to_costlabel l
1187 ] @
1188 get_costlabels_of_trace … (trace … t).
1189
1190lemma i_act_in_map :  ∀p,prog.
1191mem … 〈i_act,O〉 (labels_pc … (instructions p prog) O).
1192#p *#instr #n #_ generalize in match O in ⊢ (???%); elim instr
1193[ normalize /2/] #i #xs #IH #m whd in match (labels_pc ???);
1194@mem_append_l2 @IH
1195qed.
1196
1197
1198lemma as_execute_labelled_ok : ∀p,p',prog,c,l,st1,st2.
1199eval_vmstate p p' prog st1 = return 〈l,st2〉 → actionlabel_to_costlabel l = [c] →
1200∃n.
1201mem … 〈c,n〉 (labels_pc … (instructions p prog) O).
1202#p #p' * #instr #endmain #Hendmain #c #l #st1 #st2 #H2 lapply H2 whd in match eval_vmstate; normalize nodelta
1203#H cases(bind_inversion ????? H) -H #i * #EQfetch #_
1204 inversion(emits_labels … i)
1205 [ #EQemit cases(step_emit … H2) // #x * #EQ1 #EQ2 whd in match actionlabel_to_costlabel;
1206   normalize nodelta >EQ1 #EQ destruct /2 by ex_intro/
1207  | #f #EQemit whd in match actionlabel_to_costlabel; normalize nodelta  >(proj1 … (step_non_emit … EQfetch H2 … EQemit))
1208    #EQ destruct
1209 ]
1210qed.
1211 
1212
1213(*get_costlabels_of_measurable_trace deve aggiungere la label iniziale.*)
1214theorem static_dynamic_meas : ∀p,p',prog.∀no_dup : asm_no_duplicates p prog.
1215∀abs_t : abstract_transition_sys (m … p').∀instr_m.
1216∀good : static_galois … (asm_static_analisys_data p p' prog abs_t instr_m).∀mT,map1.
1217∀EQmap : static_analisys p ? instr_m mT prog = return map1.
1218∀t : measurable_trace (asm_operational_semantics p p' prog).
1219let start_state ≝ match L_pre_state … t with [None ⇒ L_s1 … t | Some x ⇒ x ] in
1220∀a1.rel_galois … good start_state a1 →
1221∀abs_trace.
1222abs_trace = dependent_map CostLabel ? (get_costlabels_of_measurable_trace …  t) (λlbl,prf.(opt_safe … (get_map … map1 lbl) ?)) →
1223rel_galois … good (R_s2 … t) (act_abs … abs_t (big_op … abs_trace) a1).
1224[2: @hide_prf
1225    whd in match get_costlabels_of_measurable_trace in prf; normalize nodelta in prf;
1226    cases(mem_append ???? prf) -prf
1227    [2: #prf cases(mem_map ????? (labels_of_trace_are_in_code … prf)) *
1228        #lbl' #pc * #Hmem #EQ destruct   
1229        >(proj1 … (static_analisys_ok … no_dup … EQmap … Hmem))
1230        @(proj2 … (static_analisys_ok … no_dup … EQmap … Hmem))
1231    | inversion(L_label … t) normalize nodelta [| #lbl'] #EQleft
1232      [ * [2: *] #EQ destruct >(proj1 … (static_analisys_ok … no_dup … EQmap … (i_act_in_map …)))
1233        @(proj2 … (static_analisys_ok … no_dup … EQmap … (i_act_in_map …)))
1234      | #H lapply(L_init_ok … t) inversion(L_pre_state … t) [ #_ normalize nodelta * #_ >EQleft #EQ destruct]
1235        #st_pre #EQst_pre normalize nodelta * #l' ** >EQleft #EQ destruct cases l' in H;
1236        [ #x1 #x2 | * [|#x1] | * [|#x1]] whd in ⊢ (% → %→ ?); * [2,4,6: *] #EQ destruct * * #_
1237        #H cases(as_execute_labelled_ok … H) [3,6,9:% |*:] #w #EQw
1238        >(proj1 … (static_analisys_ok … no_dup … EQmap … EQw))
1239       @(proj2 … (static_analisys_ok … no_dup … EQmap … EQw))
1240      ]
1241    ]
1242]
1243#p #p' #prog #no_dup #abs_t #instr_m #good #mT #map1 #EQmap1 #t #a1 #rel_galois #abs_trace #EQabs_trace
1244@(static_dynamic …)
1245
1246xxxxxx
1247lapply(static_dynamic … (trace …t) … abs_trace) try //
1248
1249
Note: See TracBrowser for help on using the repository browser.