source: src/RTLabs/Traces.ma @ 1719

Last change on this file since 1719 was 1719, checked in by campbell, 8 years ago

Show that non-termination survives a terminating function call.

File size: 64.8 KB
Line 
1
2include "RTLabs/semantics.ma".
3include "common/StructuredTraces.ma".
4
5discriminator status_class.
6
7(* NB: For RTLabs we only classify branching behaviour as jumps.  Other jumps
8       will be added later (LTL → LIN). *)
9
10definition RTLabs_classify : state → status_class ≝
11λs. match s with
12[ State f _ _ ⇒
13    match lookup_present ?? (f_graph (func f)) (next f) (next_ok f) with
14    [ St_cond _ _ _ ⇒ cl_jump
15    | St_jumptable _ _ ⇒ cl_jump
16    | _ ⇒ cl_other
17    ]
18| Callstate _ _ _ _ _ ⇒ cl_call
19| Returnstate _ _ _ _ ⇒ cl_return
20| Finalstate _ ⇒ cl_other
21].
22
23definition is_cost_label : statement → bool ≝
24λs. match s with [ St_cost _ _ ⇒ true | _ ⇒ false ].
25
26definition RTLabs_cost : state → bool ≝
27λs. match s with
28[ State f fs m ⇒
29    is_cost_label (lookup_present ?? (f_graph (func f)) (next f) (next_ok f))
30| _ ⇒ false
31].
32
33definition RTLabs_status : genv → abstract_status ≝
34λge.
35  mk_abstract_status
36    state
37    (λs,s'. ∃t. eval_statement ge s = Value ??? 〈t,s'〉)
38    (λs,c. RTLabs_classify s = c)
39    (λs. RTLabs_cost s = true)
40    (λs,s'. match s with
41      [ mk_Sig s p ⇒
42        match s return λs. RTLabs_classify s = cl_call → ? with
43        [ Callstate fd args dst stk m ⇒
44          λ_. match s' with
45          [ State f fs m ⇒ match stk with [ nil ⇒ False | cons h t ⇒ next h = next f ]
46          | Finalstate r ⇒ True
47          | _ ⇒ False
48          ]
49        | State f fs m ⇒ λH.⊥
50        | _ ⇒ λH.⊥
51        ] p
52      ]).
53[ normalize in H; destruct
54| normalize in H; destruct
55| whd in H:(??%?);
56  cases (lookup_present LabelTag statement (f_graph (func f)) (next f) (next_ok f)) in H;
57  normalize try #a try #b try #c try #d try #e try #g try #h destruct
58] qed.
59
60lemma RTLabs_not_cost : ∀ge,s.
61  RTLabs_cost s = false →
62  ¬ as_costed (RTLabs_status ge) s.
63#ge #s #E % whd in ⊢ (% → ?); >E #E' destruct
64qed.
65
66(* Before attempting to construct a structured trace, let's show that we can
67   form flat traces with evidence that they were constructed from an execution.
68   
69   For now we don't consider I/O. *)
70
71
72coinductive exec_no_io (o:Type[0]) (i:o → Type[0]) : execution state o i → Prop ≝
73| noio_stop : ∀a,b,c. exec_no_io o i (e_stop … a b c)
74| noio_step : ∀a,b,e. exec_no_io o i e → exec_no_io o i (e_step … a b e)
75| noio_wrong : ∀m. exec_no_io o i (e_wrong … m).
76
77(* add I/O? *)
78coinductive flat_trace (o:Type[0]) (i:o → Type[0]) (ge:genv) : state → Type[0] ≝
79| ft_stop : ∀s. RTLabs_is_final s ≠ None ? → flat_trace o i ge s
80| ft_step : ∀s,tr,s'. eval_statement ge s = Value ??? 〈tr,s'〉 → flat_trace o i ge s' → flat_trace o i ge s
81| ft_wrong : ∀s,m. eval_statement ge s = Wrong ??? m → flat_trace o i ge s.
82
83coinductive not_wrong (o:Type[0]) (i:o → Type[0]) (ge:genv) : ∀s. flat_trace o i ge s → Type[0] ≝
84| nw_stop : ∀s,H. not_wrong o i ge s (ft_stop o i ge s H)
85| nw_step : ∀s,tr,s',H,tr'. not_wrong o i ge s' tr' → not_wrong o i ge s (ft_step o i ge s tr s' H tr').
86
87lemma still_not_wrong : ∀o,i,ge,s,tr,s',H,tr'.
88  not_wrong o i ge s (ft_step o i ge s tr s' H tr') →
89  not_wrong o i ge s' tr'.
90#o #i #ge #s #tr #s' #H #tr' #NW inversion NW
91[ #H105 #H106 #H107 #H108 #H109 destruct
92| #H111 #H112 #H113 #H114 #H115 #H116 #H117 #H118 #H119 destruct //
93] qed.
94
95let corec make_flat_trace ge s
96  (H:exec_no_io … (exec_inf_aux … RTLabs_fullexec ge (eval_statement ge s))) :
97  flat_trace io_out io_in ge s ≝
98let e ≝ exec_inf_aux … RTLabs_fullexec ge (eval_statement ge s) in
99match e return λx. e = x → ? with
100[ e_stop tr i s' ⇒ λE. ft_step … s tr s' ? (ft_stop … s' ?)
101| e_step tr s' e' ⇒ λE. ft_step … s tr s' ? (make_flat_trace ge s' ?)
102| e_wrong m ⇒ λE. ft_wrong … s m ?
103| e_interact o f ⇒ λE. ⊥
104] (refl ? e).
105[ 1,2: whd in E:(??%?); >exec_inf_aux_unfold in E;
106  cases (eval_statement ge s)
107  [ 1,4: #O #K whd in ⊢ (??%? → ?); #E destruct
108  | 2,5: * #tr #s1 whd in ⊢ (??%? → ?);
109    >(?:is_final ????? = RTLabs_is_final s1) //
110    lapply (refl ? (RTLabs_is_final s1))
111    cases (RTLabs_is_final s1) in ⊢ (???% → %);
112    [ 1,3: #_ whd in ⊢ (??%? → ?); #E destruct
113    | #i #_ whd in ⊢ (??%? → ?); #E destruct /2/ @refl
114    | #i #E whd in ⊢ (??%? → ?); #E2 destruct >E % #E' destruct
115    ]
116  | *: #m whd in ⊢ (??%? → ?); #E destruct
117  ]
118| whd in E:(??%?); >exec_inf_aux_unfold in E;
119  cases (eval_statement ge s)
120  [ #O #K whd in ⊢ (??%? → ?); #E destruct
121  | * #tr #s1 whd in ⊢ (??%? → ?);
122    cases (is_final ?????)
123    [ whd in ⊢ (??%? → ?); #E destruct @refl
124    | #i whd in ⊢ (??%? → ?); #E destruct
125    ]
126  | #m whd in ⊢ (??%? → ?); #E destruct
127  ]
128| whd in E:(??%?); >E in H; #H >exec_inf_aux_unfold in E;
129  cases (eval_statement ge s)
130  [ #O #K whd in ⊢ (??%? → ?); #E destruct
131  | * #tr #s1 whd in ⊢ (??%? → ?);
132    cases (is_final ?????)
133    [ whd in ⊢ (??%? → ?); #E
134      change with (eval_statement ge s1) in E:(??(??????(?????%))?);
135      destruct
136      inversion H
137      [ #a #b #c #E1 destruct
138      | #trx #sx #ex #H1 #E2 #E3 destruct @H1
139      | #m #E1 destruct
140      ]
141    | #i whd in ⊢ (??%? → ?); #E destruct
142    ]
143  | #m whd in ⊢ (??%? → ?); #E destruct
144  ]
145| whd in E:(??%?); >exec_inf_aux_unfold in E;
146  cases (eval_statement ge s)
147  [ #O #K whd in ⊢ (??%? → ?); #E destruct
148  | * #tr1 #s1 whd in ⊢ (??%? → ?);
149    cases (is_final ?????)
150    [ whd in ⊢ (??%? → ?); #E destruct
151    | #i whd in ⊢ (??%? → ?); #E destruct
152    ]
153  | #m whd in ⊢ (??%? → ?); #E destruct @refl
154  ]
155| whd in E:(??%?); >E in H; #H
156  inversion H
157  [ #a #b #c #E destruct
158  | #a #b #c #d #E1 destruct
159  | #m #E1 destruct
160  ]
161] qed.
162
163let corec make_whole_flat_trace p s
164  (H:exec_no_io … (exec_inf … RTLabs_fullexec p))
165  (I:make_initial_state ??? p = OK ? s) :
166  flat_trace io_out io_in (make_global … RTLabs_fullexec p) s ≝
167let ge ≝ make_global … p in
168let e ≝ exec_inf_aux ?? RTLabs_fullexec ge (Value … 〈E0, s〉) in
169match e return λx. e = x → ? with
170[ e_stop tr i s' ⇒ λE. ft_stop ?? ge s ?
171| e_step _ _ e' ⇒ λE. make_flat_trace ge s ?
172| e_wrong m ⇒ λE. ⊥
173| e_interact o f ⇒ λE. ⊥
174] (refl ? e).
175[ whd in E:(??%?); >exec_inf_aux_unfold in E;
176  whd in ⊢ (??%? → ?);
177  >(?:is_final ????? = RTLabs_is_final s) //
178  lapply (refl ? (RTLabs_is_final s))
179  cases (RTLabs_is_final s) in ⊢ (???% → %);
180  [ #_ whd in ⊢ (??%? → ?); #E destruct
181  | #i #E whd in ⊢ (??%? → ?); #E2 % #E3 destruct
182  ]
183| whd in H:(???%); >I in H; whd in ⊢ (???% → ?); whd in E:(??%?);
184  >exec_inf_aux_unfold in E ⊢ %; whd in ⊢ (??%? → ???% → ?); cases (is_final ?????)
185  [ whd in ⊢ (??%? → ???% → ?); #E #H inversion H
186    [ #a #b #c #E1 destruct
187    | #tr1 #s1 #e1 #H1 #E1 #E2 -E2 -I destruct (E1)
188      @H1
189    | #m #E1 destruct
190    ]
191  | #i whd in ⊢ (??%? → ???% → ?); #E destruct
192  ]
193| whd in E:(??%?); >exec_inf_aux_unfold in E; whd in ⊢ (??%? → ?);
194  cases (is_final ?????) [2:#i] whd in ⊢ (??%? → ?); #E destruct
195| whd in E:(??%?); >exec_inf_aux_unfold in E; whd in ⊢ (??%? → ?);
196  cases (is_final ?????) [2:#i] whd in ⊢ (??%? → ?); #E destruct
197] qed.
198
199(* Need a way to choose whether a called function terminates.  Then,
200     if the initial function terminates we generate a purely inductive structured trace,
201     otherwise we start generating the coinductive one, and on every function call
202       use the choice method again to decide whether to step over or keep going.
203
204Not quite what we need - have to decide on seeing each label whether we will see
205another or hit a non-terminating call?
206
207Also - need the notion of well-labelled in order to break loops.
208
209
210
211outline:
212
213 does function terminate?
214 - yes, get (bound on the number of steps until return), generate finite
215        structure using bound as termination witness
216 - no,  get (¬ bound on steps to return), start building infinite trace out of
217        finite steps.  At calls, check for termination, generate appr. form.
218
219generating the finite parts:
220
221We start with the status after the call has been executed; well-labelling tells
222us that this is a labelled state.  Now we want to generate a trace_label_return
223and also return the remainder of the flat trace.
224
225*)
226
227(* [will_return ge depth s trace] says that after a finite number of steps of
228   [trace] from [s] we reach the return state for the current function.  [depth]
229   performs the call/return counting necessary for handling deeper function
230   calls.  It should be zero at the top level. *)
231inductive will_return (ge:genv) : nat → ∀s. flat_trace io_out io_in ge s → Type[0] ≝
232| wr_step : ∀s,tr,s',depth,EX,trace.
233    RTLabs_classify s = cl_other ∨ RTLabs_classify s = cl_jump →
234    will_return ge depth s' trace →
235    will_return ge depth s (ft_step ?? ge s tr s' EX trace)
236| wr_call : ∀s,tr,s',depth,EX,trace.
237    RTLabs_classify s = cl_call →
238    will_return ge (S depth) s' trace →
239    will_return ge depth s (ft_step ?? ge s tr s' EX trace)
240| wr_ret : ∀s,tr,s',depth,EX,trace.
241    RTLabs_classify s = cl_return →
242    will_return ge depth s' trace →
243    will_return ge (S depth) s (ft_step ?? ge s tr s' EX trace)
244    (* Note that we require the ability to make a step after the return (this
245       corresponds to somewhere that will be guaranteed to be a label at the
246       end of the compilation chain). *)
247| wr_base : ∀s,tr,s',EX,trace.
248    RTLabs_classify s = cl_return →
249    will_return ge O s (ft_step ?? ge s tr s' EX trace)
250.
251
252(* The way we will use [will_return] won't satisfy Matita's guardedness check,
253   so we will measure the length of these termination proofs and use an upper
254   bound to show termination of the finite structured trace construction
255   functions. *)
256
257let rec will_return_length ge d s tr (T:will_return ge d s tr) on T : nat ≝
258match T with
259[ wr_step _ _ _ _ _ _ _ T' ⇒ S (will_return_length … T')
260| wr_call _ _ _ _ _ _ _ T' ⇒ S (will_return_length … T')
261| wr_ret _ _ _ _ _ _ _ T' ⇒ S (will_return_length … T')
262| wr_base _ _ _ _ _ _ ⇒ S O
263].
264
265include alias "arithmetics/nat.ma".
266
267(* Specialised to the particular situation it is used in. *)
268lemma wrl_nonzero : ∀ge,d,s,tr,T. O ≥ 3 * (will_return_length ge d s tr T) → False.
269#ge #d #s #tr * #s1 #tr1 #s2 [ 1,2,3: #d ] #EX #tr' #CL [1,2,3:#IH]
270whd in ⊢ (??(??%) → ?);
271>commutative_times
272#H lapply (le_plus_b … H)
273#H lapply (le_to_leb_true … H)
274normalize #E destruct
275qed.
276   
277let rec will_return_end ge d s tr (T:will_return ge d s tr) on T : 𝚺s'.flat_trace io_out io_in ge s' ≝
278match T with
279[ wr_step _ _ _ _ _ _ _ T' ⇒ will_return_end … T'
280| wr_call _ _ _ _ _ _ _ T' ⇒ will_return_end … T'
281| wr_ret _ _ _ _ _ _ _ T' ⇒ will_return_end … T'
282| wr_base _ _ _ _ tr' _ ⇒ mk_DPair ? (λs.flat_trace io_out io_in ge s) ? tr'
283].
284
285(* Inversion lemmas on [will_return] that also note the effect on the length
286   of the proof. *)
287lemma will_return_call : ∀ge,d,s,tr,s',EX,trace.
288  RTLabs_classify s = cl_call →
289  ∀TM:will_return ge d s (ft_step ?? ge s tr s' EX trace).
290  ΣTM':will_return ge (S d) s' trace. will_return_length … TM > will_return_length … TM' ∧ will_return_end … TM = will_return_end … TM'.
291#ge #d #s #tr #s' #EX #trace #CL #TERM inversion TERM
292[ #H19 #H20 #H21 #H22 #H23 #H24 #H25 #H26 #H27 #H28 #H29 #H30 #H31 @⊥ destruct >CL in H25; * #E destruct
293| #H33 #H34 #H35 #H36 #H37 #H38 #H39 #H40 #H41 #H42 #H43 #H44 #H45 destruct % /2/
294| #H47 #H48 #H49 #H50 #H51 #H52 #H53 #H54 #H55 #H56 #H57 #H58 #H59 @⊥ destruct >CL in H53; #E destruct
295| #H61 #H62 #H63 #H64 #H65 #H66 #H67 #H68 #H69 #H70 @⊥ destruct >CL in H66; #E destruct
296] qed.
297
298lemma will_return_return : ∀ge,d,s,tr,s',EX,trace.
299  RTLabs_classify s = cl_return →
300  ∀TM:will_return ge d s (ft_step ?? ge s tr s' EX trace).
301  match d with
302  [ O ⇒ will_return_end … TM = ❬s', trace❭
303  | S d' ⇒
304      ΣTM':will_return ge d' s' trace. will_return_length … TM > will_return_length … TM' ∧ will_return_end … TM = will_return_end … TM'
305  ].
306#ge #d #s #tr #s' #EX #trace #CL #TERM inversion TERM
307[ #H19 #H20 #H21 #H22 #H23 #H24 #H25 #H26 #H27 #H28 #H29 #H30 #H31 @⊥ destruct >CL in H25; * #E destruct
308| #H33 #H34 #H35 #H36 #H37 #H38 #H39 #H40 #H41 #H42 #H43 #H44 #H45 @⊥  destruct >CL in H39; #E destruct
309| #H47 #H48 #H49 #H50 #H51 #H52 #H53 #H54 #H55 #H56 #H57 #H58 #H59 destruct % /2/
310| #H61 #H62 #H63 #H64 #H65 #H66 #H67 #H68 #H69 #H70 destruct @refl
311] qed.
312
313lemma will_return_notfn : ∀ge,d,s,tr,s',EX,trace.
314  (RTLabs_classify s = cl_other) ⊎ (RTLabs_classify s = cl_jump) →
315  ∀TM:will_return ge d s (ft_step ?? ge s tr s' EX trace).
316  ΣTM':will_return ge d s' trace. will_return_length … TM > will_return_length … TM' ∧ will_return_end … TM = will_return_end … TM'.
317#ge #d #s #tr #s' #EX #trace * #CL #TERM inversion TERM
318[ #H290 #H291 #H292 #H293 #H294 #H295 #H296 #H297 #H298 #H299 #H300 #H301 #H302 destruct % /2/
319| #H304 #H305 #H306 #H307 #H308 #H309 #H310 #H311 #H312 #H313 #H314 #H315 #H316 @⊥ destruct >CL in H310; #E destruct
320| #H318 #H319 #H320 #H321 #H322 #H323 #H324 #H325 #H326 #H327 #H328 #H329 #H330 @⊥ destruct >CL in H324; #E destruct
321| #H332 #H333 #H334 #H335 #H336 #H337 #H338 #H339 #H340 #H341 @⊥ destruct >CL in H337; #E destruct
322| #H343 #H344 #H345 #H346 #H347 #H348 #H349 #H350 #H351 #H352 #H353 #H354 #H355 destruct % /2/
323| #H357 #H358 #H359 #H360 #H361 #H362 #H363 #H364 #H365 #H366 #H367 #H368 #H369 @⊥ destruct >CL in H363; #E destruct
324| #H371 #H372 #H373 #H374 #H375 #H376 #H377 #H378 #H379 #H380 #H381 #H382 #H383 @⊥ destruct >CL in H377; #E destruct
325| #H385 #H386 #H387 #H388 #H389 #H390 #H391 #H392 #H393 #H394 @⊥ destruct >CL in H390; #E destruct
326] qed.
327
328(* When it comes to building bits of nonterminating executions we'll need to be
329   able to glue termination proofs together. *)
330
331lemma will_return_prepend : ∀ge,d1,s1,t1.
332  ∀T1:will_return ge d1 s1 t1.
333  ∀d2,s2,t2.
334  will_return ge d2 s2 t2 →
335  will_return_end … T1 = ❬s2, t2❭ →
336  will_return ge (d1 + S d2) s1 t1.
337#ge #d1 #s1 #tr1 #T1 elim T1
338[ #s #tr #s' #depth #EX #t #CL #T #IH #d2 #s2 #t2 #T2 #E
339  %1 // @(IH … T2) @E
340| #s #tr #s' #depth #EX #t #CL #T #IH #d2 #s2 #t2 #T2 #E %2 // @(IH … T2) @E
341| #s #tr #s' #depth #EX #t #CL #T #IH #s2 #s2 #t2 #T2 #E %3 // @(IH … T2) @E
342| #s #tr #s' #EX #t #CL #d2 #s2 #t2 #T2 #E normalize in E; destruct %3 //
343] qed.
344
345discriminator nat.
346
347lemma will_return_remove_call : ∀ge,d1,s1,t1.
348  ∀T1:will_return ge d1 s1 t1.
349  ∀d2.
350  will_return ge (d1 + S d2) s1 t1 →
351  ∀s2,t2.
352  will_return_end … T1 = ❬s2, t2❭ →
353  will_return ge d2 s2 t2.
354(* The key part of the proof is to show that the two termination proofs follow
355   the same pattern. *)
356#ge #d1x #s1x #t1x #T1 elim T1
357[ #s #tr #s' #d1 #EX #t #CL #T #IH #d2 #T2 #s2 #t2 #E @IH
358  [ inversion T2 [ #H1 #H2 #H3 #H4 #H5 #H6 #H7 #H8 #H9 #H10 #H11 #H12 #H13 destruct //
359                 | #H15 #H16 #H17 #H18 #H19 #H20 #H21 #H22 #H23 #H24 #H25 #H26 #H27 @⊥ destruct
360                   >H21 in CL; * #E destruct
361                 | #H29 #H30 #H31 #H32 #H33 #H34 #H35 #H36 #H37 #H38 #H39 #H40 #H41 @⊥ destruct
362                   >H35 in CL; * #E destruct
363                 | #H43 #H44 #H45 #H46 #H47 #H48 #H49 #H50 #H51 #H52 @⊥ destruct
364                   >H48 in CL; * #E destruct
365                 ]
366  | @E
367  ]
368| #s #tr #s' #d1 #EX #t #CL #T #IH #d2 #T2 #s2 #t2 #E @IH
369  [ inversion T2 [ #H1 #H2 #H3 #H4 #H5 #H6 #H7 #H8 #H9 #H10 #H11 #H12 #H13 @⊥ destruct
370                   >CL in H7; * #E destruct
371                 | #H15 #H16 #H17 #H18 #H19 #H20 #H21 #H22 #H23 #H24 #H25 #H26 #H27 destruct //
372                 | #H29 #H30 #H31 #H32 #H33 #H34 #H35 #H36 #H37 #H38 #H39 #H40 #H41 @⊥ destruct
373                   >H35 in CL; #E destruct
374                 | #H43 #H44 #H45 #H46 #H47 #H48 #H49 #H50 #H51 #H52 @⊥ destruct
375                   >H48 in CL; #E destruct
376                 ]
377  | @E
378  ]
379| #s #tr #s' #d1 #EX #t #CL #T #IH #d2 #T2 #s2 #t2 #E @IH
380  [ inversion T2 [ #H1 #H2 #H3 #H4 #H5 #H6 #H7 #H8 #H9 #H10 #H11 #H12 #H13 @⊥ destruct
381                   >CL in H7; * #E destruct
382                 | #H15 #H16 #H17 #H18 #H19 #H20 #H21 #H22 #H23 #H24 #H25 #H26 #H27 @⊥ destruct
383                   >H21 in CL; #E destruct
384                 | #H29 #H30 #H31 #H32 #H33 #H34 #H35 #H36 #H37 #H38 #H39 #H40 #H41
385                   whd in H38:(??%??); destruct //
386                 | #H43 #H44 #H45 #H46 #H47 #H48 #H49 #H50 #H51 #H52
387                   whd in H49:(??%??); @⊥ destruct
388                 ]
389  | @E
390  ]
391| #s #tr #s' #EX #t #CL #d2 #T2 #s2 #t2 #E whd in E:(??%?); destruct
392  inversion T2 [ #H1 #H2 #H3 #H4 #H5 #H6 #H7 #H8 #H9 #H10 #H11 #H12 #H13 @⊥ destruct
393                 >CL in H7; * #E destruct
394               | #H15 #H16 #H17 #H18 #H19 #H20 #H21 #H22 #H23 #H24 #H25 #H26 #H27 @⊥ destruct
395                 >H21 in CL; #E destruct
396               | #H29 #H30 #H31 #H32 #H33 #H34 #H35 #H36 #H37 #H38 #H39 #H40 #H41
397                 whd in H38:(??%??); destruct //
398               | #H43 #H44 #H45 #H46 #H47 #H48 #H49 #H50 #H51 #H52
399                 whd in H49:(??%??); @⊥ destruct
400               ]
401] qed.
402
403(* We require that labels appear after branch instructions and at the start of
404   functions.  The first is required for preciseness, the latter for soundness.
405   We will make a separate requirement for there to be a finite number of steps
406   between labels to catch loops for soundness (is this sufficient?). *)
407
408definition well_cost_labelled_statement : ∀f:internal_function. ∀s. labels_present (f_graph f) s → Prop ≝
409λf,s. match s return λs. labels_present ? s → Prop with
410[ St_cond _ l1 l2 ⇒ λH.
411    is_cost_label (lookup_present … (f_graph f) l1 ?) = true ∧
412    is_cost_label (lookup_present … (f_graph f) l2 ?) = true
413| St_jumptable _ ls ⇒ λH.
414    (* I did have a dependent version of All here, but it's a pain. *)
415    All … (λl. ∃H. is_cost_label (lookup_present … (f_graph f) l H) = true) ls
416| _ ⇒ λ_. True
417]. whd in H;
418[ @(proj1 … H)
419| @(proj2 … H)
420] qed.
421
422definition well_cost_labelled_fn : internal_function → Prop ≝
423λf. (∀l. ∀H:present … (f_graph f) l.
424         well_cost_labelled_statement f (lookup_present … (f_graph f) l H) (f_closed f l …)) ∧
425    is_cost_label (lookup_present … (f_graph f) (f_entry f) ?) = true.
426[ @lookup_lookup_present | cases (f_entry f) // ] qed.
427
428(* We need to ensure that any code we come across is well-cost-labelled.  We may
429   get function code from either the global environment or the state. *)
430
431definition well_cost_labelled_ge : genv → Prop ≝
432λge. ∀b,f. find_funct_ptr ?? ge b = Some ? (Internal ? f) → well_cost_labelled_fn f.
433
434definition well_cost_labelled_state : state → Prop ≝
435λs. match s with
436[ State f fs m ⇒ well_cost_labelled_fn (func f) ∧ All ? (λf. well_cost_labelled_fn (func f)) fs
437| Callstate fd _ _ fs _ ⇒ match fd with [ Internal fn ⇒ well_cost_labelled_fn fn | External _ ⇒ True ] ∧
438                          All ? (λf. well_cost_labelled_fn (func f)) fs
439| Returnstate _ _ fs _ ⇒ All ? (λf. well_cost_labelled_fn (func f)) fs
440| Finalstate _ ⇒ True
441].
442
443lemma well_cost_labelled_state_step : ∀ge,s,tr,s'.
444  eval_statement ge s = Value ??? 〈tr,s'〉 →
445  well_cost_labelled_ge ge →
446  well_cost_labelled_state s →
447  well_cost_labelled_state s'.
448#ge #s #tr' #s' #EV cases (eval_perserves … EV)
449[ #ge #f #f' #fs #m #m' * #func #locals #next #next_ok #sp #retdst #locals' #next' #next_ok' #Hge * #H1 #H2 % //
450| #ge #f #fs #m * #fn #args #f' #dst * #func #locals #next #next_ok #sp #retdst #locals' #next' #next_ok' #b #Hfn #Hge * #H1 #H2 % /2/
451(*
452| #ge #f #fs #m * #fn #args #f' #dst #m' #b #Hge * #H1 #H2 % /2/
453*)
454| #ge #fn #locals #next #nok #sp #fs #m #args #dst #m' #Hge * #H1 #H2 % /2/
455| #ge #f #fs #m #rtv #dst #m' #Hge * #H1 #H2 @H2
456| #ge #f #fs #rtv #dst #f' #m * #func #locals #next #nok #sp #retdst #locals' #next' #nok' #Hge * #H1 #H2 % //
457| //
458] qed.
459
460lemma rtlabs_jump_inv : ∀s.
461  RTLabs_classify s = cl_jump →
462  ∃f,fs,m. s = State f fs m ∧
463  let stmt ≝ lookup_present ?? (f_graph (func f)) (next f) (next_ok f) in
464  (∃r,l1,l2. stmt = St_cond r l1 l2) ∨ (∃r,ls. stmt = St_jumptable r ls).
465*
466[ #f #fs #m #E
467  %{f} %{fs} %{m} %
468  [ @refl
469  | whd in E:(??%?); cases (lookup_present ? statement ???) in E ⊢ %;
470    try (normalize try #A try #B try #C try #D try #F try #G try #H destruct)
471    [ %1 %{A} %{B} %{C} @refl
472    | %2 %{A} %{B} @refl
473    ]
474  ]
475| normalize #H1 #H2 #H3 #H4 #H5 #H6 destruct
476| normalize #H8 #H9 #H10 #H11 #H12 destruct
477| #r #E normalize in E; destruct
478] qed.
479
480lemma well_cost_labelled_jump : ∀ge,s,tr,s'.
481  eval_statement ge s = Value ??? 〈tr,s'〉 →
482  well_cost_labelled_state s →
483  RTLabs_classify s = cl_jump →
484  RTLabs_cost s' = true.
485#ge #s #tr #s' #EV #H #CL
486cases (rtlabs_jump_inv s CL)
487#fr * #fs * #m * #Es *
488[ * #r * #l1 * #l2 #Estmt
489  >Es in H; whd in ⊢ (% → ?); * * #Hbody #_ #Hfs
490  >Es in EV; whd in ⊢ (??%? → ?); generalize in ⊢ (??(?%)? → ?);
491  >Estmt #LP whd in ⊢ (??%? → ?);
492  (* replace with lemma on successors? *)
493  @bind_value #v #Ev @bind_ok * #Eb whd in ⊢ (??%? → ?); #E destruct
494  lapply (Hbody (next fr) (next_ok fr))
495  generalize in ⊢ (???% → ?);
496  >Estmt #LP'
497  whd in ⊢ (% → ?);
498  * #H1 #H2 [ @H1 | @H2 ]
499| * #r * #ls #Estmt
500  >Es in H; whd in ⊢ (% → ?); * * #Hbody #_ #Hfs
501  >Es in EV; whd in ⊢ (??%? → ?); generalize in ⊢ (??(?%)? → ?);
502  >Estmt #LP whd in ⊢ (??%? → ?);
503  (* replace with lemma on successors? *)
504  @bind_value #a cases a [ | #sz #i | #f | #r | #ptr ]  #Ea whd in ⊢ (??%? → ?);
505  [ 2: (* later *)
506  | *: #E destruct
507  ]
508  lapply (Hbody (next fr) (next_ok fr))
509  generalize in ⊢ (???% → ?); >Estmt #LP' whd in ⊢ (% → ?); #CP
510  generalize in ⊢ (??(?%)? → ?);
511  cases (nth_opt label (nat_of_bitvector (bitsize_of_intsize sz) i) ls) in ⊢ (???% → ??(match % with [_⇒?|_⇒?]?)? → ?);
512  [ #E1 #E2 whd in E2:(??%?); destruct
513  | #l' #E1 #E2 whd in E2:(??%?); destruct
514    cases (All_nth ???? CP ? E1)
515    #H1 #H2 @H2
516  ]
517] qed.
518
519lemma rtlabs_call_inv : ∀s.
520  RTLabs_classify s = cl_call →
521  ∃fd,args,dst,stk,m. s = Callstate fd args dst stk m.
522* [ #f #fs #m whd in ⊢ (??%? → ?);
523    cases (lookup_present … (next f) (next_ok f)) normalize
524    try #A try #B try #C try #D try #E try #F try #G destruct
525  | #fd #args #dst #stk #m #E %{fd} %{args} %{dst} %{stk} %{m} @refl
526  | normalize #H411 #H412 #H413 #H414 #H415 destruct
527  | normalize #H1 #H2 destruct
528  ] qed.
529
530lemma well_cost_labelled_call : ∀ge,s,tr,s'.
531  eval_statement ge s = Value ??? 〈tr,s'〉 →
532  well_cost_labelled_state s →
533  RTLabs_classify s = cl_call →
534  RTLabs_cost s' = true.
535#ge #s #tr #s' #EV #WCL #CL
536cases (rtlabs_call_inv s CL)
537#fd * #args * #dst * #stk * #m #E >E in EV WCL;
538whd in ⊢ (??%? → % → ?);
539cases fd
540[ #fn whd in ⊢ (??%? → % → ?);
541  @bind_value #lcl #Elcl cases (alloc m O (f_stacksize fn) Any)
542  #m' #b whd in ⊢ (??%? → ?); #E' destruct
543  * whd in ⊢ (% → ?); * #WCL1 #WCL2 #WCL3
544  @WCL2
545| #fn whd in ⊢ (??%? → % → ?);
546  @bindIO_value #evargs #Eargs
547  whd in ⊢ (??%? → ?);
548  #E' destruct
549] qed.
550
551
552(* The preservation of (most of) the stack is useful to show as_after_return.
553   We do this by showing that during the execution of a function the lower stack
554   frames never change, and that after returning from the function we preserve
555   the identity of the next instruction to execute.
556 *)
557
558inductive stack_of_state : list frame → state → Prop ≝
559| sos_State : ∀f,fs,m. stack_of_state fs (State f fs m)
560| sos_Callstate : ∀fd,args,dst,f,fs,m. stack_of_state fs (Callstate fd args dst (f::fs) m)
561| sos_Returnstate : ∀rtv,dst,fs,m. stack_of_state fs (Returnstate rtv dst fs m)
562.
563
564inductive stack_preserved : trace_ends_with_ret → state → state → Prop ≝
565| sp_normal : ∀fs,s1,s2.
566    stack_of_state fs s1 →
567    stack_of_state fs s2 →
568    stack_preserved doesnt_end_with_ret s1 s2
569| sp_finished : ∀s1,f,f',fs,m.
570    next f = next f' →
571    stack_of_state (f::fs) s1 →
572    stack_preserved ends_with_ret s1 (State f' fs m)
573| sp_stop : ∀e,s1,r.
574    stack_preserved e s1 (Finalstate r)
575.
576
577discriminator list.
578
579lemma stack_of_state_eq : ∀fs,fs',s.
580  stack_of_state fs s →
581  stack_of_state fs' s →
582  fs = fs'.
583#fs0 #fs0' #s0 *
584[ #f #fs #m #H inversion H
585  #a #b #c #d try #e try #g try #h try #i try #j destruct @refl
586| #fd #args #dst #f #fs #m #H inversion H
587  #a #b #c #d try #e try #g try #h try #i try #j destruct @refl
588| #rtv #dst #fs #m #H inversion H
589  #a #b #c #d try #e try #g try #h try #i try #j destruct @refl
590] qed.
591
592lemma stack_preserved_final : ∀e,r,s.
593  stack_preserved e (Finalstate r) s → ∃r'. s = Finalstate r'.
594#e #r #s #H inversion H
595[ #H184 #H185 #H186 #SOS #H188 #H189 #H190 #H191 #H192 destruct
596  inversion SOS #a #b #c #d #e #f try #g try #h destruct
597| #H194 #H195 #H196 #H197 #H198 #H199 #SOS #H201 #H202 #H203 #H204 destruct
598  inversion SOS #a #b #c #d #e #f try #g try #h destruct
599| #e' #s' #r' #E1 #E2 #E3 #E4 destruct %{r'} @refl
600] qed.
601
602lemma stack_preserved_join : ∀e,s1,s2,s3.
603  stack_preserved doesnt_end_with_ret s1 s2 →
604  stack_preserved e s2 s3 →
605  stack_preserved e s1 s3.
606#e1 #s1 #s2 #s3 #H1 inversion H1
607[ #fs #s1' #s2' #S1 #S2 #E1 #E2 #E3 #E4 destruct
608  #H2 inversion H2
609  [ #fs' #s1'' #s2'' #S1' #S2' #E1 #E2 #E3 #E4 destruct
610    @(sp_normal fs) // <(stack_of_state_eq … S1' S2) //
611  | #s1'' #f #f' #fs' #m #N #S1' #E1 #E2 #E3 #E4 destruct
612    @(sp_finished … N) >(stack_of_state_eq … S1' S2) //
613  | #s1'' #r #E1 #E2 #E3 #E4 destruct //
614  ]
615| #H25 #H26 #H27 #H28 #H29 #H30 #H31 #H32 #H33 #H34 #H35 #H36 destruct
616| #H19 #H20 #H21 #H22 #H23 #H24 #H25 destruct #H
617  cases (stack_preserved_final … H) #r #E destruct //
618] qed.
619
620lemma stack_preserved_return : ∀ge,s1,s2,tr.
621  RTLabs_classify s1 = cl_return →
622  eval_statement ge s1 = Value ??? 〈tr,s2〉 →
623  stack_preserved ends_with_ret s1 s2.
624#ge *
625[ #f #fs #m #s2 #tr #E @⊥ whd in E:(??%?);
626  cases (lookup_present ??? (next f) (next_ok f)) in E;
627  normalize #a try #b try #c try #d try #e try #f try #g destruct
628| #fd #args #dst #fs #m #s2 #tr #E normalize in E; destruct
629| #res #dst *
630  [ #m #s2 #tr #_ #EV whd in EV:(??%?); cases res in EV; [ normalize #EV destruct | * [ 2: * #r normalize #EV destruct // | *: normalize #a try #b destruct ] ]
631  | #f #fs #m #s2 #tr #_ whd in ⊢ (??%? → ?); @bind_value #locals #El #EV
632    whd in EV:(??%?); destruct @(sp_finished ? f) //
633  ]
634| #r #s2 #tr #E normalize in E; destruct
635] qed.
636
637lemma stack_preserved_step : ∀ge,s1,s2,tr.
638  RTLabs_classify s1 = cl_other ∨ RTLabs_classify s1 = cl_jump →
639  eval_statement ge s1 = Value ??? 〈tr,s2〉 →
640  stack_preserved doesnt_end_with_ret s1 s2.
641#ge0 #s1 #s2 #tr #CL #EV inversion (eval_perserves … EV)
642[ #ge #f #f' #fs #m #m' #F #E1 #E2 #E3 #E4 destruct /2/
643| #ge #f #fs #m #fd #args #f' #dst #F #b #FFP #E1 #E2 #E3 #E4 /2/
644| #ge #fn #locals #next #nok #sp #fs #m #args #dst #m' #E1 #E2 #E3 #E4 destruct
645  normalize in CL; cases CL #E destruct
646| #ge #f #fs #m #rtv #dst #m' #E1 #E2 #E3 #E4 destruct /2/
647| #ge #f #fs #rtv #dst #f' #m #F #E1 #E2 #E3 #E4 destruct cases CL
648  #E normalize in E; destruct
649| #ge #r #dst #m #E1 #E2 destruct @⊥ cases CL normalize #E destruct
650] qed.
651
652lemma stack_preserved_call : ∀ge,s1,s2,s3,tr.
653  RTLabs_classify s1 = cl_call →
654  eval_statement ge s1 = Value ??? 〈tr,s2〉 →
655  stack_preserved ends_with_ret s2 s3 →
656  stack_preserved doesnt_end_with_ret s1 s3.
657#ge #s1 #s2 #s3 #tr #CL #EV #SP
658cases (rtlabs_call_inv … CL)
659#fd * #args * #dst * #stk * #m #E destruct
660inversion SP
661[ #H38 #H39 #H40 #H41 #H42 #H43 #H44 #H45 #H46 destruct
662| #s2' #f #f' #fs #m' #N #S #E1 #E2 #E3 #E4 destruct
663  inversion (eval_perserves … EV)
664  [ #H48 #H49 #H50 #H51 #H52 #H53 #H54 #H55 #H56 #H57 #H58 destruct
665  | #H60 #H61 #H62 #H63 #H64 #H65 #H66 #H67 #H68 #H69 #H70 #H71 #H72 #H73 #H74 destruct
666  | #ge' #fn #locals #next #nok #sp #fs1 #m1 #args1 #dst1 #m2 #E1 #E2 #E3 #E4 destruct
667    inversion S
668    [ #fx #fsx #mx #E1 #E2 #E3 destruct /2/
669    | #H76 #H77 #H78 #H79 #H80 #H81 #H82 #H83 #H84 destruct
670    | #H86 #H87 #H88 #H89 #H90 #H91 #H92 destruct
671    ]
672  | #H94 #H95 #H96 #H97 #H98 #H99 #H100 #H101 #H102 #H103 #H104 destruct
673  | #H106 #H107 #H108 #H109 #H110 #H111 #H112 #H113 #H114 #H115 #H116 #H117 destruct
674  | #H1 #H2 #H3 #H4 #H5 #H6 #H7 #H8 destruct
675  ]
676| #e #s1 #r #E1 #E2 #E3 #_ destruct //
677] qed.
678 
679lemma RTLabs_after_call : ∀ge,s1,s2,s3,tr.
680  ∀CL : RTLabs_classify s1 = cl_call.
681  eval_statement ge s1 = Value ??? 〈tr,s2〉 →
682  stack_preserved ends_with_ret s2 s3 →
683  as_after_return (RTLabs_status ge) «s1,CL» s3.
684#ge #s1 #s2 #s3 #tr #CL #EV #S23
685cases (rtlabs_call_inv … CL) #fn * #args * #dst * #stk * #m #E destruct
686inversion S23
687[ #H129 #H130 #H131 #H132 #H133 #H134 #H135 #H136 #H137 destruct
688| #s2' #f #f' #fs #m' #N #S #E1 #E2 #E3 #E4 destruct
689  inversion (eval_perserves … EV)
690  [ #H139 #H140 #H141 #H142 #H143 #H144 #H145 #H146 #H147 #H148 #H149 destruct
691  | #H151 #H152 #H153 #H154 #H155 #H156 #H157 #H158 #H159 #H160 #H161 #H162 #H163 #H164 #H165 destruct
692  | #gex #fnx #locals #next #nok #sp #fsx #mx #argsx #dstx #mx' #E1 #E2 #E3 #E4 destruct
693    inversion S
694    [ #fy #fsy #my #E1 #E2 #E3 destruct @N
695    | #H167 #H168 #H169 #H170 #H171 #H172 #H173 #H174 #H175 destruct
696    | #H177 #H178 #H179 #H180 #H181 #H182 #H183 destruct
697    ]
698  | #H185 #H186 #H187 #H188 #H189 #H190 #H191 #H192 #H193 #H194 #H195 destruct
699  | #H197 #H198 #H199 #H200 #H201 #H202 #H203 #H204 #H205 #H206 #H207 #H208 destruct
700  | #H10 #H11 #H12 #H13 #H14 #H15 #H16 #H17 destruct
701  ]
702| #e #s1 #r #E1 #E2 #E3 #E4 destruct //
703] qed.
704
705(* Don't need to know that labels break loops because we have termination. *)
706
707(* A bit of mucking around with the depth to avoid proving termination after
708   termination.  Note that we keep a proof that our upper bound on the length
709   of the termination proof is respected. *)
710record trace_result (ge:genv) (depth:nat) (ends:trace_ends_with_ret)
711  (start:state) (full:flat_trace io_out io_in ge start)
712  (original_terminates: will_return ge depth start full)
713  (T:state → Type[0]) (limit:nat) : Type[0] ≝
714{
715  new_state : state;
716  remainder : flat_trace io_out io_in ge new_state;
717  cost_labelled : well_cost_labelled_state new_state;
718  new_trace : T new_state;
719  stack_ok : stack_preserved ends start new_state;
720  terminates : match (match ends with [ doesnt_end_with_ret ⇒ S depth | _ ⇒ depth ]) with
721               [ O ⇒ will_return_end … original_terminates = ❬new_state, remainder❭
722               | S d ⇒ ΣTM:will_return ge d new_state remainder.
723                         limit > will_return_length … TM ∧
724                         will_return_end … original_terminates = will_return_end … TM
725               ]
726}.
727
728(* The same with a flag indicating whether the function returned, as opposed to
729   encountering a label. *)
730record sub_trace_result (ge:genv) (depth:nat)
731  (start:state) (full:flat_trace io_out io_in ge start)
732  (original_terminates: will_return ge depth start full)
733  (T:trace_ends_with_ret → state → Type[0]) (limit:nat) : Type[0] ≝
734{
735  ends : trace_ends_with_ret;
736  trace_res :> trace_result ge depth ends start full original_terminates (T ends) limit
737}.
738
739(* We often return the result from a recursive call with an addition to the
740   structured trace, so we define a couple of functions to help.  The bound on
741   the size of the termination proof might need to be relaxed, too. *)
742
743definition replace_trace : ∀ge,d,e,s1,s2,t1,t2,TM1,TM2,T1,T2,l1,l2. l2 ≥ l1 →
744  ∀r:trace_result ge d e s1 t1 TM1 T1 l1.
745    will_return_end … TM1 = will_return_end … TM2 →
746    T2 (new_state … r) →
747    stack_preserved e s2 (new_state … r) →
748    trace_result ge d e s2 t2 TM2 T2 l2 ≝
749λge,d,e,s1,s2,t1,t2,TM1,TM2,T1,T2,l1,l2,lGE,r,TME,trace,SP.
750  mk_trace_result ge d e s2 t2 TM2 T2 l2
751    (new_state … r)
752    (remainder … r)
753    (cost_labelled … r)
754    trace
755    SP
756    ?
757    (*(match d return λd'.match d' with [ O ⇒ True | S d'' ⇒ ΣTM.l1 > will_return_length ge d'' (new_state … r) (remainder … r) TM] →
758                        match d' with [ O ⇒ True | S d'' ⇒ ΣTM.l2 > will_return_length ge d'' (new_state … r) (remainder … r) TM] with
759     [O ⇒ λ_. I | _ ⇒ λTM. «pi1 … TM, ?» ] (terminates ???????? r))*)
760.
761cases e in r ⊢ %;
762[ <TME -TME * cases d in TM1 TM2 ⊢ %;
763  [ #TM1 #TM2 #ns #rem #WCLS #T1NS #SP whd in ⊢ (% → %); #TMS @TMS
764  | #d' #TM1 #TM2 #ns #rem #WCLS #T1NS #SP whd in ⊢ (% → %); * #TMa * #L1 #TME
765    %{TMa} % // @(transitive_le … lGE) @L1
766  ]
767| <TME -TME * #ns #rem #WCLS #T1NS #SP whd in ⊢ (% → %);
768   * #TMa * #L1 #TME
769    %{TMa} % // @(transitive_le … lGE) @L1
770] qed.
771
772definition replace_sub_trace : ∀ge,d,s1,s2,t1,t2,TM1,TM2,T1,T2,l1,l2. l2 ≥ l1 →
773  ∀r:sub_trace_result ge d s1 t1 TM1 T1 l1.
774    will_return_end … TM1 = will_return_end … TM2 →
775    T2 (ends … r) (new_state … r) →
776    stack_preserved (ends … r) s2 (new_state … r) →
777    sub_trace_result ge d s2 t2 TM2 T2 l2 ≝
778λge,d,s1,s2,t1,t2,TM1,TM2,T1,T2,l1,l2,lGE,r,TME,trace,SP.
779  mk_sub_trace_result ge d s2 t2 TM2 T2 l2
780    (ends … r)
781    (replace_trace … lGE … r TME trace SP).
782
783(* Small syntax hack to avoid ambiguous input problems. *)
784definition myge : nat → nat → Prop ≝ ge.
785
786let rec make_label_return ge depth s
787  (trace: flat_trace io_out io_in ge s)
788  (ENV_COSTLABELLED: well_cost_labelled_ge ge)
789  (STATE_COSTLABELLED: well_cost_labelled_state s)  (* functions in the state *)
790  (STATEMENT_COSTLABEL: RTLabs_cost s = true)       (* current statement is a cost label *)
791  (TERMINATES: will_return ge depth s trace)
792  (TIME: nat)
793  (TERMINATES_IN_TIME: myge TIME (plus 2 (times 3 (will_return_length … TERMINATES))))
794  on TIME : trace_result ge depth ends_with_ret s trace TERMINATES
795              (trace_label_return (RTLabs_status ge) s)
796              (will_return_length … TERMINATES) ≝
797             
798match TIME return λTIME. TIME ≥ ? → ? with
799[ O ⇒ λTERMINATES_IN_TIME. ⊥
800| S TIME ⇒ λTERMINATES_IN_TIME.
801
802  let r ≝ make_label_label ge depth s
803            trace
804            ENV_COSTLABELLED
805            STATE_COSTLABELLED
806            STATEMENT_COSTLABEL
807            TERMINATES
808            TIME ? in
809  match ends … r return λx. trace_result ge depth x s trace TERMINATES (trace_label_label (RTLabs_status ge) x s) ? →
810                            trace_result ge depth ends_with_ret s trace TERMINATES (trace_label_return (RTLabs_status ge) s) (will_return_length … TERMINATES) with
811  [ ends_with_ret ⇒ λr.
812      replace_trace … r ? (tlr_base (RTLabs_status ge) s (new_state … r) (new_trace … r)) (stack_ok … r)
813  | doesnt_end_with_ret ⇒ λr.
814      let r' ≝ make_label_return ge depth (new_state … r)
815                 (remainder … r)
816                 ENV_COSTLABELLED
817                 (cost_labelled … r) ?
818                 (pi1 … (terminates … r)) TIME ? in
819        replace_trace … r' ?
820          (tlr_step (RTLabs_status ge) s (new_state … r)
821            (new_state … r') (new_trace … r) (new_trace … r')) ?
822  ] (trace_res … r)
823
824] TERMINATES_IN_TIME
825
826
827and make_label_label ge depth s
828  (trace: flat_trace io_out io_in ge s)
829  (ENV_COSTLABELLED: well_cost_labelled_ge ge)
830  (STATE_COSTLABELLED: well_cost_labelled_state s)  (* functions in the state *)
831  (STATEMENT_COSTLABEL: RTLabs_cost s = true)       (* current statement is a cost label *)
832  (TERMINATES: will_return ge depth s trace)
833  (TIME: nat)
834  (TERMINATES_IN_TIME:  myge TIME (plus 1 (times 3 (will_return_length … TERMINATES))))
835  on TIME : sub_trace_result ge depth s trace TERMINATES
836              (λends. trace_label_label (RTLabs_status ge) ends s)
837              (will_return_length … TERMINATES) ≝
838             
839match TIME return λTIME. TIME ≥ ? → ? with
840[ O ⇒ λTERMINATES_IN_TIME. ⊥
841| S TIME ⇒ λTERMINATES_IN_TIME.
842
843let r ≝ make_any_label ge depth s trace ENV_COSTLABELLED STATE_COSTLABELLED TERMINATES TIME ? in
844  replace_sub_trace … r ?
845    (tll_base (RTLabs_status ge) (ends … r) s (new_state … r) (new_trace … r) STATEMENT_COSTLABEL) (stack_ok … r)
846
847] TERMINATES_IN_TIME
848
849
850and make_any_label ge depth s
851  (trace: flat_trace io_out io_in ge s)
852  (ENV_COSTLABELLED: well_cost_labelled_ge ge)
853  (STATE_COSTLABELLED: well_cost_labelled_state s)  (* functions in the state *)
854  (TERMINATES: will_return ge depth s trace)
855  (TIME: nat)
856  (TERMINATES_IN_TIME: myge TIME (times 3 (will_return_length … TERMINATES)))
857  on TIME : sub_trace_result ge depth s trace TERMINATES
858              (λends. trace_any_label (RTLabs_status ge) ends s)
859              (will_return_length … TERMINATES) ≝
860
861match TIME return λTIME. TIME ≥ ? → ? with
862[ O ⇒ λTERMINATES_IN_TIME. ⊥
863| S TIME ⇒ λTERMINATES_IN_TIME.
864
865  match trace return λs,trace. well_cost_labelled_state s →
866                               ∀TM:will_return ??? trace.
867                               myge ? (times 3 (will_return_length ??? trace TM)) →
868                               sub_trace_result ge depth s trace TM (λends. trace_any_label (RTLabs_status ge) ends s) (will_return_length … TM) with
869  [ ft_stop st FINAL ⇒
870      λSTATE_COSTLABELLED,TERMINATES,TERMINATES_IN_TIME. ⊥
871
872  | ft_step start tr next EV trace' ⇒ λSTATE_COSTLABELLED,TERMINATES,TERMINATES_IN_TIME.
873    match RTLabs_classify start return λx. RTLabs_classify start = x → sub_trace_result ge depth start ?? (λends. trace_any_label (RTLabs_status ge) ends ?) (will_return_length … TERMINATES) with
874    [ cl_other ⇒ λCL.
875        match RTLabs_cost next return λx. RTLabs_cost next = x → sub_trace_result ge depth start ?? (λends. trace_any_label (RTLabs_status ge) ends ?) (will_return_length … TERMINATES) with
876        (* We're about to run into a label. *)
877        [ true ⇒ λCS.
878            mk_sub_trace_result ge depth start ? TERMINATES (λends. trace_any_label (RTLabs_status ge) ends start) ?
879              doesnt_end_with_ret
880              (mk_trace_result ge … next trace' ?
881                (tal_base_not_return (RTLabs_status ge) start next ?? CS) ??)
882        (* An ordinary step, keep going. *)
883        | false ⇒ λCS.
884            let r ≝ make_any_label ge depth next trace' ENV_COSTLABELLED ? (will_return_notfn … TERMINATES) TIME ? in
885                replace_sub_trace … r ?
886                  (tal_step_default (RTLabs_status ge) (ends … r)
887                     start next (new_state … r) ? (new_trace … r) ? (RTLabs_not_cost … CS)) ?
888        ] (refl ??)
889       
890    | cl_jump ⇒ λCL.
891        mk_sub_trace_result ge depth start ? TERMINATES (λends. trace_any_label (RTLabs_status ge) ends start) ?
892          doesnt_end_with_ret
893          (mk_trace_result ge … next trace' ?
894            (tal_base_not_return (RTLabs_status ge) start next ???) ??)
895           
896    | cl_call ⇒ λCL.
897        let r ≝ make_label_return ge (S depth) next trace' ENV_COSTLABELLED ?? (will_return_call … CL TERMINATES) TIME ? in
898        match RTLabs_cost (new_state … r) return λx. RTLabs_cost (new_state … r) = x → sub_trace_result ge depth start ?? (λends. trace_any_label (RTLabs_status ge) ends ?) (will_return_length … TERMINATES) with
899        (* We're about to run into a label, use base case for call *)
900        [ true ⇒ λCS.
901            mk_sub_trace_result ge depth start ? TERMINATES (λends. trace_any_label (RTLabs_status ge) ends start) ?
902            doesnt_end_with_ret
903            (mk_trace_result ge …
904              (tal_base_call (RTLabs_status ge) start next (new_state … r)
905                ? CL ? (new_trace … r) CS) ??)
906        (* otherwise use step case *)
907        | false ⇒ λCS.
908            let r' ≝ make_any_label ge depth
909                       (new_state … r) (remainder … r) ENV_COSTLABELLED ?
910                       (pi1 … (terminates … r)) TIME ? in
911            replace_sub_trace … r' ?
912              (tal_step_call (RTLabs_status ge) (ends … r')
913                start next (new_state … r) (new_state … r') ? CL ?
914                (new_trace … r) (RTLabs_not_cost … CS) (new_trace … r')) ?
915        ] (refl ??)
916
917    | cl_return ⇒ λCL.
918        mk_sub_trace_result ge depth start ? TERMINATES (λends. trace_any_label (RTLabs_status ge) ends start) ?
919          ends_with_ret
920          (mk_trace_result ge …
921            next
922            trace'
923            ?
924            (tal_base_return (RTLabs_status ge) start next ? CL)
925            ?
926            ?)
927    ] (refl ? (RTLabs_classify start))
928   
929  | ft_wrong start m EV ⇒ λSTATE_COSTLABELLED,TERMINATES. ⊥
930 
931  ] STATE_COSTLABELLED TERMINATES TERMINATES_IN_TIME
932] TERMINATES_IN_TIME.
933
934[ cases (not_le_Sn_O ?) [ #H @H @TERMINATES_IN_TIME ]
935| //
936| //
937| cases r #H1 #H2 #H3 #H4 #H5 * #H7 * #GT #_ @(le_S_to_le … GT)
938| cases r #H1 #H2 #H3 #H4 #H5 * #H7 * #_ #EEQ //
939| @(stack_preserved_join … (stack_ok … r)) //
940| @(trace_label_label_label … (new_trace … r))
941| cases r #H1 #H2 #H3 #H4 #H5 * #H7 * #LT #_
942  @(le_plus_to_le … 1) @(transitive_le … TERMINATES_IN_TIME)
943  @(transitive_le …  (3*(will_return_length … TERMINATES)))
944  [ >commutative_times change with ((S ?) * 3 ≤ ?) >commutative_times
945    @(monotonic_le_times_r 3 … LT)
946  | @le_S @le_S @le_n
947  ]
948| @le_S_S_to_le @TERMINATES_IN_TIME
949| cases (not_le_Sn_O ?) [ #H @H @TERMINATES_IN_TIME ]
950| @le_n
951| //
952| @le_S_S_to_le @TERMINATES_IN_TIME
953| @(wrl_nonzero … TERMINATES_IN_TIME)
954| (* We can't reach the final state because the function terminates with a
955     return *)
956  inversion TERMINATES
957  [ #H214 #H215 #H216 #H217 #H218 #H219 #H220 #H221 #H222 #H223 #H224 #H225 #_ -TERMINATES -TERMINATES destruct
958  | #H228 #H229 #H230 #H231 #H232 #H233 #H234 #H235 #H236 #H237 #H238 #H239 #H240 -TERMINATES -TERMINATES destruct
959  | #H242 #H243 #H244 #H245 #H246 #H247 #H248 #H249 #H250 #H251 #H252 #H253 #H254 -TERMINATES -TERMINATES destruct
960  | #H256 #H257 #H258 #H259 #H260 #H261 #H262 #H263 #H264 #H265 -TERMINATES -TERMINATES destruct
961  ]
962| @(will_return_return … CL TERMINATES)
963| /2 by stack_preserved_return/
964| %{tr} @EV
965| @(well_cost_labelled_state_step  … EV) //
966| whd @(will_return_notfn … TERMINATES) %2 @CL
967| @stack_preserved_step /2/
968| %{tr} @EV
969| %1 whd @CL
970| @(well_cost_labelled_jump … EV) //
971| @(well_cost_labelled_state_step  … EV) //
972| whd cases (terminates ???????? r) #TMr * #LTr #EQr %{TMr} %
973  [ @(transitive_lt … LTr) cases (will_return_call … CL TERMINATES)
974    #TMx * #LT' #_ @LT'
975  | <EQr cases (will_return_call … CL TERMINATES)
976    #TM' * #_ #EQ' @EQ'
977  ]
978| @(stack_preserved_call … EV (stack_ok … r)) //
979| %{tr} @EV
980| @RTLabs_after_call //
981| @(cost_labelled … r)
982| skip
983| cases r #ns #rm #WS #TLR #SP * #TM * #LT #_ @le_S_to_le
984  @(transitive_lt … LT)
985  cases (will_return_call … CL TERMINATES) #TM' * #LT' #_ @LT'
986| cases r #ns #rm #WS #TLR #SP * #TM * #_ #EQ <EQ
987  cases (will_return_call … CL TERMINATES) #TM' * #_ #EQ' //
988| @RTLabs_after_call //
989| %{tr} @EV
990| @(stack_preserved_join … (stack_ok … r')) @(stack_preserved_call … EV (stack_ok … r)) //
991| @(cost_labelled … r)
992| cases r #H72 #H73 #H74 #H75 #HX * #HY * #GT #H78
993  @(le_plus_to_le … 1) @(transitive_le … TERMINATES_IN_TIME)
994  cases (will_return_call … TERMINATES) in GT;
995  #X * #Y #_ #Z
996  @(transitive_le … (monotonic_lt_times_r 3 … Y))
997  [ @(transitive_le … (monotonic_lt_times_r 3 … Z)) //
998  | //
999  ]
1000| @(well_cost_labelled_state_step  … EV) //
1001| @(well_cost_labelled_call … EV) //
1002| cases (will_return_call … TERMINATES)
1003  #TM * #GT #_ @le_S_S_to_le
1004  >commutative_times change with ((S ?) * 3 ≤ ?) >commutative_times
1005  @(transitive_le … TERMINATES_IN_TIME)
1006  @(monotonic_le_times_r 3 … GT)
1007| whd @(will_return_notfn … TERMINATES) %1 @CL
1008| @(stack_preserved_step … EV) /2/
1009| %{tr} @EV
1010| %2 whd @CL
1011| @(well_cost_labelled_state_step  … EV) //
1012| cases (will_return_notfn … TERMINATES) #TM * #GT #_ @(le_S_to_le … GT)
1013| cases (will_return_notfn … TERMINATES) #TM * #_ #EQ //
1014| @CL
1015| %{tr} @EV
1016| @(stack_preserved_join … (stack_ok … r)) @(stack_preserved_step … EV) /2/
1017| @(well_cost_labelled_state_step  … EV) //
1018| %1 @CL
1019| cases (will_return_notfn … TERMINATES) #TM * #GT #_
1020  @le_S_S_to_le
1021  @(transitive_le … (monotonic_lt_times_r … GT) TERMINATES_IN_TIME)
1022  //
1023| inversion TERMINATES
1024  [ #H1 #H2 #H3 #H4 #H5 #H6 #H7 #H8 #H9 #H10 #H11 #H12 #H13 -TERMINATES -TERMINATES destruct
1025  | #H17 #H18 #H19 #H20 #H21 #H22 #H23 #H24 #H25 #H26 #H27 #H28 #H29 -TERMINATES -TERMINATES destruct
1026  | #H33 #H34 #H35 #H36 #H37 #H38 #H39 #H40 #H41 #H42 #H43 #H44 #H45 -TERMINATES -TERMINATES destruct
1027  | #H1 #H2 #H3 #H4 #H5 #H6 #H7 #H8 #H9 #H10 -TERMINATES -TERMINATES destruct
1028  ]
1029] qed.
1030
1031(* We can initialise TIME with a suitably large value based on the length of the
1032   termination proof. *)
1033let rec make_label_return' ge depth s
1034  (trace: flat_trace io_out io_in ge s)
1035  (ENV_COSTLABELLED: well_cost_labelled_ge ge)
1036  (STATE_COSTLABELLED: well_cost_labelled_state s)  (* functions in the state *)
1037  (STATEMENT_COSTLABEL: RTLabs_cost s = true)       (* current statement is a cost label *)
1038  (TERMINATES: will_return ge depth s trace)
1039  : trace_result ge depth ends_with_ret s trace TERMINATES (trace_label_return (RTLabs_status ge) s) (will_return_length … TERMINATES) ≝
1040make_label_return ge depth s trace ENV_COSTLABELLED STATE_COSTLABELLED STATEMENT_COSTLABEL TERMINATES
1041  (2 + 3 * will_return_length … TERMINATES) ?.
1042@le_n
1043qed.
1044 
1045(* Tail-calls would not be handled properly (which means that if we try to show the
1046   full version with non-termination we'll fail because calls and returns aren't
1047   balanced.
1048 *)
1049
1050inductive inhabited (T:Type[0]) : Prop ≝
1051| witness : T → inhabited T.
1052
1053(* We also require that program's traces are soundly labelled: for any state
1054   in the execution, we can give a distance to a labelled state or termination.
1055   
1056   Note that this differs from the syntactic notions in earlier languages
1057   because it is a global property.  In principle, we would have a loop broken
1058   only by a call to a function (which necessarily has a label) and no local
1059   cost label.
1060 *)
1061
1062let rec nth_state ge s
1063  (trace: flat_trace io_out io_in ge s)
1064  n
1065  on n : option state ≝
1066match n with
1067[ O ⇒ Some ? s
1068| S n' ⇒
1069  match trace with
1070  [ ft_step _ _ s' _ trace' ⇒ nth_state ge s' trace' n'
1071  | _ ⇒ None ?
1072  ]
1073].
1074
1075definition soundly_labelled_trace : ∀ge,s. flat_trace io_out io_in ge s → Prop ≝
1076λge,s,trace. ∀n.∃m. ∀s'. nth_state ge s trace (n+m) = Some ? s' → RTLabs_cost s' = true.
1077
1078lemma soundly_labelled_step : ∀ge,s,tr,s',EV,trace'.
1079  soundly_labelled_trace ge s (ft_step … ge s tr s' EV trace') →
1080  soundly_labelled_trace ge s' trace'.
1081#ge #s #tr #s' #EV #trace' #H
1082#n cases (H (S n)) #m #H' %{m} @H'
1083qed.
1084
1085(* Define a notion of sound labellings of RTLabs programs. *)
1086
1087let rec successors (s : statement) : list label ≝
1088match s with
1089[ St_skip l ⇒ [l]
1090| St_cost _ l ⇒ [l]
1091| St_const _ _ l ⇒ [l]
1092| St_op1 _ _ _ _ _ l ⇒ [l]
1093| St_op2 _ _ _ _ l ⇒ [l]
1094| St_load _ _ _ l ⇒ [l]
1095| St_store _ _ _ l ⇒ [l]
1096| St_call_id _ _ _ l ⇒ [l]
1097| St_call_ptr _ _ _ l ⇒ [l]
1098(*
1099| St_tailcall_id _ _ ⇒ [ ]
1100| St_tailcall_ptr _ _ ⇒ [ ]
1101*)
1102| St_cond _ l1 l2 ⇒ [l1; l2]
1103| St_jumptable _ ls ⇒ ls
1104| St_return ⇒ [ ]
1105].
1106
1107definition actual_successor : state → option label ≝
1108λs. match s with
1109[ State f fs m ⇒ Some ? (next f)
1110| Callstate _ _ _ fs _ ⇒ match fs with [ cons f _ ⇒ Some ? (next f) | _ ⇒ None ? ]
1111| Returnstate _ _ _ _ ⇒ None ?
1112| Finalstate _ ⇒ None ?
1113].
1114
1115lemma nth_opt_Exists : ∀A,n,l,a.
1116  nth_opt A n l = Some A a →
1117  Exists A (λa'. a' = a) l.
1118#A #n elim n
1119[ * [ #a #E normalize in E; destruct | #a #l #a' #E normalize in E; destruct % // ]
1120| #m #IH *
1121  [ #a #E normalize in E; destruct
1122  | #a #l #a' #E %2 @IH @E
1123  ]
1124] qed.
1125
1126lemma eval_successor : ∀ge,f,fs,m,tr,s'.
1127  eval_statement ge (State f fs m) = Value ??? 〈tr,s'〉 →
1128  RTLabs_classify s' = cl_return ∨
1129  ∃l. actual_successor s' = Some ? l ∧ Exists ? (λl0. l0 = l) (successors (lookup_present … (f_graph (func f)) (next f) (next_ok f))).
1130#ge * #func #locals #next #next_ok #sp #dst #fs #m #tr #s'
1131whd in ⊢ (??%? → ?);
1132generalize in ⊢ (??(?%)? → ?); cases (lookup_present ??? next next_ok)
1133[ #l #LP whd in ⊢ (??%? → ?); #E destruct %2 %{l} % // % //
1134| #cl #l #LP whd in ⊢ (??%? → ?); #E destruct %2 %{l} % // % //
1135| #r #c #l #LP whd in ⊢ (??%? → ?); @bind_value #v #Ev @bind_ok #locals' #El whd in ⊢ (??%? → ?); #E destruct %2 %{l} % // % //
1136| #ty #ty' #op #r1 #r2 #l #LP whd in ⊢ (??%? → ?); @bind_value #v #Ev @bind_ok #v' #Ev' @bind_ok #locals' #El whd in ⊢ (??%? → ?); #E destruct %2 %{l} % // % //
1137| #op #r1 #r2 #r3 #l #LP whd in ⊢ (??%? → ?); @bind_value #v1 #Ev1 @bind_ok #v2 #Ev2 @bind_ok #v' #Ev' @bind_ok #locals' #El whd in ⊢ (??%? → ?); #E destruct %2 %{l} % // % //
1138| #ch #r1 #r2 #l  #LP whd in ⊢ (??%? → ?); @bind_value #v1 #Ev1 @bind_ok #v2 #Ev2 @bind_ok #locals' #El whd in ⊢ (??%? → ?); #E destruct %2 %{l} % // % //
1139| #ch #r1 #r2 #l  #LP whd in ⊢ (??%? → ?); @bind_value #v1 #Ev1 @bind_ok #v2 #Ev2 @bind_ok #m' #Em whd in ⊢ (??%? → ?); #E destruct %2 %{l} % // % //
1140| #id #rs #r #l #LP whd in ⊢ (??%? → ?); @bind_value #b #Eb @bind_ok #fd #Efd @bind_ok #vs #Evs whd in ⊢ (??%? → ?); #E destruct %2 %{l} % // % //
1141| #r #rs #r' #l #LP whd in ⊢ (??%? → ?); @bind_value #fv #Efv @bind_ok #fd #Efd @bind_ok #vs #Evs whd in ⊢ (??%? → ?); #E destruct %2 %{l} % // % //
1142| #r #l1 #l2 #LP whd in ⊢ (??%? → ?); @bind_value #v #Ev @bind_ok #b #Eb whd in ⊢ (??%? → ?); #E destruct %2 cases b [ %{l1} | %{l2} ] % // [ % | %2 %] //
1143| #r #ls #LP whd in ⊢ (??%? → ?); @bind_value #v #Ev
1144  cases v [ #E normalize in E; destruct | #sz #i | #f #E normalize in E; destruct | #r #E normalize in E; destruct | #p #E normalize in E; destruct ]
1145  whd in ⊢ (??%? → ?);
1146  generalize in ⊢ (??(?%)? → ?);
1147  cases (nth_opt label (nat_of_bitvector (bitsize_of_intsize sz) i) ls) in ⊢ (???% → ??(match % with [ _ ⇒ ? | _ ⇒ ? ] ?)? → ?);
1148  [ #e #E normalize in E; destruct
1149  | #l #El whd in ⊢ (??%? → ?); #E destruct %2 %{l} % // @(nth_opt_Exists … El)
1150  ]
1151| #LP whd in ⊢ (??%? → ?); @bind_value #v #Ev whd in ⊢ (??%? → ?); #E destruct %1 @refl
1152] qed.
1153
1154definition steps_for_statement : statement → nat ≝
1155λs. S (match s with [ St_call_id _ _ _ _ ⇒ 1 | St_call_ptr _ _ _ _ ⇒ 1 | St_return ⇒ 1 | _ ⇒ 0 ]).
1156
1157inductive bound_on_steps_to_cost (g:graph statement) : label → nat → Prop ≝
1158| bostc_here : ∀l,n,H. is_cost_label (lookup_present … g l H) → bound_on_steps_to_cost g l n
1159| bostc_later : ∀l,n. bound_on_steps_to_cost1 g l n → bound_on_steps_to_cost g l n
1160with bound_on_steps_to_cost1 : label → nat → Prop ≝
1161| bostc_step : ∀l,n,H.
1162    let stmt ≝ lookup_present … g l H in
1163    (∀l'. Exists label (λl0. l0 = l') (successors stmt) →
1164          bound_on_steps_to_cost g l' n) →
1165    bound_on_steps_to_cost1 g l (steps_for_statement stmt + n).
1166
1167(*
1168lemma steps_to_label_bound_inv : ∀g,l,n.
1169  steps_to_label_bound g l n →
1170  ∀H. let stmt ≝ lookup_present … g l H in
1171  ∃n'. n = steps_for_statement stmt + n' ∧
1172  (∀l'. Exists label (λl0. l0 = l') (successors stmt) →
1173        (∃H'. bool_to_Prop (is_cost_label (lookup_present … g l' H'))) ∨
1174        steps_to_label_bound g l' n').
1175#g #l0 #n0 #S inversion S #l #n #H #IH #E1 #E2 #_ destruct #H'
1176% [2: % [ @refl | #l' #EX cases (IH l' EX) /2/ ] | skip ]
1177qed.
1178  *) 
1179
1180(*
1181definition soundly_labelled_pc ≝ λg,l. ∃n. steps_to_label_bound g l n.
1182
1183let rec soundly_labelled_fn (fn : internal_function) : Prop ≝
1184  soundly_labelled_pc (f_graph fn) (f_entry fn).
1185
1186
1187definition soundly_labelled_frame : frame → Prop ≝
1188λf. soundly_labelled_pc (f_graph (func f)) (next f).
1189
1190definition soundly_labelled_state : state → Prop ≝
1191λs. match s with
1192[ State f _ _ ⇒ soundly_labelled_frame f
1193| Callstate _ _ _ stk _ ⇒ match stk with [ nil ⇒ False | cons f _ ⇒ soundly_labelled_frame f ]
1194| Returnstate _ _ stk _ ⇒ match stk with [ nil ⇒ False | cons f _ ⇒ soundly_labelled_frame f ]
1195].
1196*)
1197definition frame_bound_on_steps_to_cost : frame → nat → Prop ≝
1198λf. bound_on_steps_to_cost (f_graph (func f)) (next f).
1199definition frame_bound_on_steps_to_cost1 : frame → nat → Prop ≝
1200λf. bound_on_steps_to_cost1 (f_graph (func f)) (next f).
1201
1202inductive state_bound_on_steps_to_cost : state → nat → Prop ≝
1203| sbostc_state : ∀f,fs,m,n. frame_bound_on_steps_to_cost1 f n → state_bound_on_steps_to_cost (State f fs m) n
1204| sbostc_call : ∀fd,args,dst,f,fs,m,n. frame_bound_on_steps_to_cost f n → state_bound_on_steps_to_cost (Callstate fd args dst (f::fs) m) (S n)
1205| sbostc_ret : ∀rtv,dst,f,fs,m,n. frame_bound_on_steps_to_cost f n → state_bound_on_steps_to_cost (Returnstate rtv dst (f::fs) m) (S n)
1206.
1207
1208lemma state_bound_on_steps_to_cost_zero : ∀s.
1209  ¬ state_bound_on_steps_to_cost s O.
1210#s % #H inversion H
1211[ #H46 #H47 #H48 #H49 #H50 #H51 #H52 #H53 destruct
1212  whd in H50; @(bound_on_steps_to_cost1_inv_ind … H50) (* XXX inversion H50*)
1213  #H55 #H56 #H57 #H58 #H59 #H60 #H61 normalize in H60; destruct
1214| #H1 #H2 #H3 #H4 #H5 #H6 #H7 #H8 #H9 #H10 #H11 destruct
1215| #H13 #H14 #H15 #H16 #H17 #H18 #H19 #H20 #H21 #H22 destruct
1216] qed.
1217
1218lemma eval_steps : ∀ge,f,fs,m,tr,s'.
1219  eval_statement ge (State f fs m) = Value ??? 〈tr,s'〉 →
1220  steps_for_statement (lookup_present ?? (f_graph (func f)) (next f) (next_ok f)) =
1221  match s' with [ State _ _ _ ⇒ 1 | Callstate _ _ _ _ _ ⇒ 2 | Returnstate _ _ _ _ ⇒ 2 | Finalstate _ ⇒ 1 ].
1222#ge * #func #locals #next #next_ok #sp #dst #fs #m #tr #s'
1223whd in ⊢ (??%? → ?);
1224generalize in ⊢ (??(?%)? → ?); cases (lookup_present ??? next next_ok)
1225[ #l #LP whd in ⊢ (??%? → ?); #E destruct @refl
1226| #cl #l #LP whd in ⊢ (??%? → ?); #E destruct @refl
1227| #r #c #l #LP whd in ⊢ (??%? → ?); @bind_value #v #Ev @bind_ok #locals' #El whd in ⊢ (??%? → ?); #E destruct @refl
1228| #ty #ty' #op #r1 #r2 #l #LP whd in ⊢ (??%? → ?); @bind_value #v #Ev @bind_ok #v' #Ev' @bind_ok #locals' #El whd in ⊢ (??%? → ?); #E destruct @refl
1229| #op #r1 #r2 #r3 #l #LP whd in ⊢ (??%? → ?); @bind_value #v1 #Ev1 @bind_ok #v2 #Ev2 @bind_ok #v' #Ev' @bind_ok #locals' #El whd in ⊢ (??%? → ?); #E destruct @refl
1230| #ch #r1 #r2 #l  #LP whd in ⊢ (??%? → ?); @bind_value #v1 #Ev1 @bind_ok #v2 #Ev2 @bind_ok #locals' #El whd in ⊢ (??%? → ?); #E destruct @refl
1231| #ch #r1 #r2 #l  #LP whd in ⊢ (??%? → ?); @bind_value #v1 #Ev1 @bind_ok #v2 #Ev2 @bind_ok #m' #Em whd in ⊢ (??%? → ?); #E destruct @refl
1232| #id #rs #r #l #LP whd in ⊢ (??%? → ?); @bind_value #b #Eb @bind_ok #fd #Efd @bind_ok #vs #Evs whd in ⊢ (??%? → ?); #E destruct @refl
1233| #r #rs #r' #l #LP whd in ⊢ (??%? → ?); @bind_value #fv #Efv @bind_ok #fd #Efd @bind_ok #vs #Evs whd in ⊢ (??%? → ?); #E destruct @refl
1234| #r #l1 #l2 #LP whd in ⊢ (??%? → ?); @bind_value #v #Ev @bind_ok #b #Eb whd in ⊢ (??%? → ?); #E destruct @refl
1235| #r #ls #LP whd in ⊢ (??%? → ?); @bind_value #v #Ev
1236  cases v [ #E normalize in E; destruct | #sz #i | #f #E normalize in E; destruct | #r #E normalize in E; destruct | #p #E normalize in E; destruct ]
1237  whd in ⊢ (??%? → ?);
1238  generalize in ⊢ (??(?%)? → ?);
1239  cases (nth_opt label (nat_of_bitvector (bitsize_of_intsize sz) i) ls) in ⊢ (???% → ??(match % with [ _ ⇒ ? | _ ⇒ ? ] ?)? → ?);
1240  [ #e #E normalize in E; destruct
1241  | #l #El whd in ⊢ (??%? → ?); #E destruct @refl
1242  ]
1243| #LP whd in ⊢ (??%? → ?); @bind_value #v #Ev whd in ⊢ (??%? → ?); #E destruct @refl
1244] qed.
1245
1246lemma bound_after_step : ∀ge,s,tr,s',n.
1247  state_bound_on_steps_to_cost s (S n) →
1248  eval_statement ge s = Value ??? 〈tr, s'〉 →
1249  RTLabs_cost s' = false →
1250  (RTLabs_classify s' = cl_return ∨ RTLabs_classify s = cl_call) ∨
1251   state_bound_on_steps_to_cost s' n.
1252#ge #s #tr #s' #n #BOUND1 inversion BOUND1
1253[ #f #fs #m #m #FS #E1 #E2 #_ destruct
1254  #EVAL cases (eval_successor … EVAL)
1255  [ /3/
1256  | * #l * #S1 #S2 #NC %2
1257  (*
1258    cases (bound_on_steps_to_cost1_inv … FS ?) [2: @(next_ok f) ]
1259    *)
1260    @(bound_on_steps_to_cost1_inv_ind … FS) #next #n' #next_ok #IH #E1 #E2 #E3 destruct
1261    inversion (eval_perserves … EVAL)
1262    [ #ge0 #f0 #f' #fs' #m0 #m' #F #E4 #E5 #E6 #_ destruct
1263      >(eval_steps … EVAL) in E2; #En normalize in En;
1264      inversion F #H1 #H2 #H3 #H4 #H5 #H6 #H7 #H8 #H9 #H10 #H11 #H12 destruct
1265      %1 inversion (IH … S2)
1266      [ #lx #nx #LPx #CSx #E1x #E2x @⊥ destruct
1267        change with (RTLabs_cost (State (mk_frame H1 H7 lx LPx H5 H6) fs' m')) in CSx:(?%);
1268        whd in S1:(??%?); destruct >NC in CSx; *
1269      | whd in S1:(??%?); destruct #H71 #H72 #H73 #H74 #H75 #H76 destruct @H73
1270      ]
1271    | #ge0 #f0 #fs' #m0 #fd #args #f' #dst #F #b #FFP #E4 #E5 #E6 #_ destruct
1272      >(eval_steps … EVAL) in E2; #En normalize in En;
1273      inversion F #H1 #H2 #H3 #H4 #H5 #H6 #H7 #H8 #H9 #H10 #H11 #H12 destruct
1274      %2 @IH normalize in S1; destruct @S2
1275    | #H14 #H15 #H16 #H17 #H18 #H19 #H20 #H21 #H22 #H23 #H24 #H25 #H26 #H27 #H28
1276      destruct
1277    | #H31 #H32 #H33 #H34 #H35 #H36 #H37 #H38 #H39 #H40 #H41 destruct
1278      normalize in S1; destruct
1279    | #H44 #H45 #H46 #H47 #H48 #H49 #H50 #H51 #H52 #H53 #H54 #H55 destruct
1280    | #H267 #H268 #H269 #H270 #H271 #H272 #H273 #H274 destruct
1281    ]
1282  ]
1283| #H58 #H59 #H60 #H61 #H62 #H63 #H64 #H65 #H66 #H67 #H68 #H69 #H70 destruct
1284  /3/
1285| #rtv #dst #f #fs #m #n' #FS #E1 #E2 #_ destruct
1286  #EVAL #NC %2 inversion (eval_perserves … EVAL)
1287  [ #H72 #H73 #H74 #H75 #H76 #H77 #H78 #H79 #H80 #H81 #H82 destruct
1288  | #H84 #H85 #H86 #H87 #H88 #H89 #H90 #H91 #H92 #H93 #H94 #H95 #H96 #H97 #H98 destruct
1289  | #H100 #H101 #H102 #H103 #H104 #H105 #H106 #H107 #H108 #H109 #H110 #H111 #H112 #H113 #H114 destruct
1290  | #H116 #H117 #H118 #H119 #H120 #H121 #H122 #H123 #H124 #H125 #H126 destruct
1291  | #ge' #f' #fs' #rtv' #dst' #f'' #m' #F #E1 #E2 #E3 #_ destruct
1292    %1 whd in FS ⊢ %;
1293    inversion (stack_preserved_return … EVAL) [ @refl | #H141 #H142 #H143 #H144 #H145 #H146 #H147 #H148 #H149 destruct | 4: #H276 #H277 #H278 #H279 #H280 #H281 #H282 destruct ]
1294    #s1 #f1 #f2 #fs #m #FE #SS1 #_ #E1 #E2 #_ destruct <FE
1295    inversion SS1 [ #H163 #H164 #H165 #H166 #H167 #H168 destruct | #H170 #H171 #H172 #H173 #H174 #H175 #H176 #H177 #H178 destruct | #rtv #dst #fs0 #m0 #E1 #E2 #_ destruct ]
1296    inversion F #func #locals #next #next_ok #sp #retdst #locals' #next' #next_ok' #E1 #E2 #_ destruct
1297    inversion FS
1298    [ #lx #nx #LPx #CSx #E1x #E2x @⊥ destruct
1299        change with (RTLabs_cost (State (mk_frame func locals' lx ? sp retdst) fs m0)) in CSx:(?%);
1300        >NC in CSx; *
1301    | #lx #nx #H #E1x #E2x #_ destruct @H
1302    ]
1303  | #H284 #H285 #H286 #H287 #H288 #H289 #H290 #H291 destruct
1304  ]
1305] qed.
1306 
1307(* When constructing an infinite trace, we need to be able to grab the finite
1308   portion of the trace for the next [trace_label_diverges] constructor.  We
1309   use the fact that the trace is soundly labelled to achieve this. *)
1310
1311inductive finite_prefix (ge:genv) : state → Prop ≝
1312| fp_tal : ∀s,s'.
1313           trace_any_label (RTLabs_status ge) doesnt_end_with_ret s s' →
1314           flat_trace io_out io_in ge s' →
1315           finite_prefix ge s
1316| fp_tac : ∀s,s'.
1317           trace_any_call (RTLabs_status ge) s s' →
1318           flat_trace io_out io_in ge s' →
1319           finite_prefix ge s
1320.
1321
1322definition fp_add_default : ∀ge,s,s'.
1323  RTLabs_classify s = cl_other →
1324  finite_prefix ge s' →
1325  (∃t. eval_statement ge s = Value ??? 〈t,s'〉) →
1326  RTLabs_cost s' = false →
1327  finite_prefix ge s ≝
1328λge,s,s',OTHER,fp.
1329match fp return λs'.λ_. (∃t. eval_statement ge ? = Value ??? 〈t,s'〉) → RTLabs_cost s' = false → finite_prefix ge s with
1330[ fp_tal s' sf TAL rem ⇒ λEVAL, NOT_COST. fp_tal ge s sf
1331    (tal_step_default (RTLabs_status ge) doesnt_end_with_ret s s' sf EVAL TAL OTHER (RTLabs_not_cost … NOT_COST))
1332    rem
1333| fp_tac s' sf TAC rem ⇒ λEVAL, NOT_COST. fp_tac ge s sf
1334    (tac_step_default (RTLabs_status ge) s sf s' EVAL TAC OTHER (RTLabs_not_cost … NOT_COST)) rem
1335].
1336
1337definition fp_add_terminating_call : ∀ge,s,s1,s'.
1338  (∃t. eval_statement ge s = Value ??? 〈t,s1〉) →
1339  ∀CALL:RTLabs_classify s = cl_call.
1340  finite_prefix ge s' →
1341  trace_label_return (RTLabs_status ge) s1 s' →
1342  as_after_return (RTLabs_status ge) (mk_Sig ?? s CALL) s' →
1343  RTLabs_cost s' = false →
1344  finite_prefix ge s ≝
1345λge,s,s1,s',EVAL,CALL,fp.
1346match fp return λs'.λ_. trace_label_return (RTLabs_status ge) ? s' → as_after_return (RTLabs_status ge) ? s' → RTLabs_cost s' = false → finite_prefix ge s with
1347[ fp_tal s' sf TAL rem ⇒ λTLR,RET,NOT_COST. fp_tal ge s sf
1348    (tal_step_call (RTLabs_status ge) doesnt_end_with_ret s s1 s' sf EVAL CALL RET TLR (RTLabs_not_cost … NOT_COST) TAL)
1349    rem
1350| fp_tac s' sf TAC rem ⇒ λTLR,RET,NOT_COST. fp_tac ge s sf
1351    (tac_step_call (RTLabs_status ge) s s' sf s1 EVAL CALL RET TLR (RTLabs_not_cost … NOT_COST) TAC)
1352    rem
1353].
1354
1355definition termination_oracle ≝ ∀ge,depth,s,trace.
1356  inhabited (will_return ge depth s trace) ∨ ¬ inhabited (will_return ge depth s trace).
1357
1358let rec finite_segment ge s n trace
1359  (ORACLE: termination_oracle)
1360  (ENV_COSTLABELLED: well_cost_labelled_ge ge)
1361  (STATE_COSTLABELLED: well_cost_labelled_state s)  (* functions in the state *)
1362  (NO_TERMINATION: Not (∃depth. inhabited (will_return ge depth s trace)))
1363  (NOT_UNDEFINED: not_wrong … trace)
1364  (LABEL_LIMIT: state_bound_on_steps_to_cost s n)
1365  on n : finite_prefix ge s ≝
1366match n return λn. state_bound_on_steps_to_cost s n → finite_prefix ge s with
1367[ O ⇒ λLABEL_LIMIT. ⊥
1368| S n' ⇒
1369    match trace return λs,trace. not_wrong ??? s trace → well_cost_labelled_state s → (Not (∃depth. inhabited (will_return ge depth s trace))) → state_bound_on_steps_to_cost s (S n') → finite_prefix ge s with
1370    [ ft_stop st FINAL ⇒ λNOT_UNDEFINED,STATE_COSTLABELLED,NO_TERMINATION,LABEL_LIMIT. ⊥
1371    | ft_step start tr next EV trace' ⇒ λNOT_UNDEFINED,STATE_COSTLABELLED,NO_TERMINATION,LABEL_LIMIT.
1372        match RTLabs_classify start return λx. RTLabs_classify start = x → ? with
1373        [ cl_other ⇒ λCL.
1374            match RTLabs_cost next return λx. RTLabs_cost next = x → ? with
1375            [ true ⇒ λCS.
1376                fp_tal ge start next (tal_base_not_return (RTLabs_status ge) start next ?? CS) trace'
1377            | false ⇒ λCS.
1378                let fs ≝ finite_segment ge next n' trace' ORACLE ENV_COSTLABELLED ???? in
1379                fp_add_default ge ?? CL fs ? CS
1380            ] (refl ??)
1381        | cl_jump ⇒ λCL.
1382            fp_tal ge start next (tal_base_not_return (RTLabs_status ge) start next ?? ?) trace'
1383        | cl_call ⇒ λCL.
1384            match ORACLE ge O next trace' return λ_. finite_prefix ge start with
1385            [ or_introl TERMINATES ⇒
1386              match TERMINATES with [ witness TERMINATES ⇒
1387                let tlr ≝ make_label_return' ge O next trace' ENV_COSTLABELLED ?? TERMINATES in
1388                match RTLabs_cost (new_state … tlr) return λx. RTLabs_cost (new_state … tlr) = x → finite_prefix ge start with
1389                [ true ⇒ λCS. fp_tal ge start (new_state … tlr) (tal_base_call (RTLabs_status ge) start next (new_state … tlr) ? CL ? (new_trace … tlr) CS) (remainder … tlr)
1390                | false ⇒ λCS.
1391                    let fs ≝ finite_segment ge (new_state … tlr) n' (remainder … tlr) ORACLE ENV_COSTLABELLED ???? in
1392                    fp_add_terminating_call … fs (new_trace … tlr) ? CS
1393                ] (refl ??)
1394              ]
1395            | or_intror NO_TERMINATION ⇒
1396                fp_tac ??? (tac_base (RTLabs_status ge) start CL) (ft_step io_out io_in ge start tr next EV trace')
1397            ]
1398        | cl_return ⇒ λCL. ⊥
1399        ] (refl ??)
1400    | ft_wrong start m EV ⇒ λNOT_UNDEFINED,STATE_COSTLABELLED,NO_TERMINATION,LABEL_LIMIT. ⊥
1401    ] NOT_UNDEFINED STATE_COSTLABELLED NO_TERMINATION
1402] LABEL_LIMIT.
1403[ cases (state_bound_on_steps_to_cost_zero s) /2/
1404| (* TODO: how do we know that we're not at the final state? *)
1405| @(absurd ?? NO_TERMINATION)
1406     %{0} % @wr_base //
1407| @(well_cost_labelled_jump … EV) //
1408| 5,6,7,8,9,10: /2/
1409| /2/
1410| //
1411| @(not_to_not … NO_TERMINATION) * #depth * #TM1 %{depth} %
1412  @wr_call //
1413  @(will_return_prepend … TERMINATES … TM1)
1414  cases (terminates … tlr) //
1415| (* FIXME: post-call not-wrong *)
1416| (* FIXME: bound on steps after call *)
1417| @(well_cost_labelled_state_step … EV) //
1418| @(well_cost_labelled_call … EV) //
1419| 18,19,20: /2/
1420| @(well_cost_labelled_state_step … EV) //
1421| @(not_to_not … NO_TERMINATION)
1422  * #depth * #TERM %{depth} % @wr_step /2/
1423| @(still_not_wrong … NOT_UNDEFINED)
1424| cases (bound_after_step … LABEL_LIMIT EV ?)
1425  [ * [ #TERMINATES @⊥ @(absurd ?? NO_TERMINATION) %{0} % @wr_step [ %1 // |
1426    inversion trace'
1427    [ cases daemon (* TODO again *) | #s1 #tr1 #s2 #EVAL' #trace'' #E1 #E2 destruct
1428    @wr_base //
1429    | #H99 #H100 #H101 #H102 #H103 destruct
1430      inversion NOT_UNDEFINED
1431      [ #H137 #H138 #H139 #H140 #H141 destruct
1432      | #H143 #H144 #H145 #H146 #H147 #H148 #H149 #H150 #H151 destruct
1433        inversion H148
1434        [ #H153 #H154 #H155 #H156 #H157 destruct
1435        | #H159 #H160 #H161 #H162 #H163 #H164 #H165 #H166 #H167 destruct
1436        ]
1437      ]
1438    ]
1439    ]
1440    | >CL #E destruct
1441    ]
1442  | //
1443  | //
1444  ]
1445| inversion NOT_UNDEFINED
1446  [ #H169 #H170 #H171 #H172 #H173 destruct
1447  | #H175 #H176 #H177 #H178 #H179 #H180 #H181 #H182 #H183 destruct
1448  ]
1449] cases daemon qed.
1450
1451(*
1452let corec make_label_diverges ge s
1453  (trace: flat_trace io_out io_in ge s)
1454  (ENV_COSTLABELLED: well_cost_labelled_ge ge)
1455  (STATE_COSTLABELLED: well_cost_labelled_state s)  (* functions in the state *)
1456  (STATEMENT_COSTLABEL: RTLabs_cost s = true)       (* current statement is a cost label *)
1457  (SOUNDLY_COSTLABELLED: soundly_labelled_trace … trace)
1458  (NO_TERMINATION: Not (∃depth. inhabited (will_return ge depth s trace)))
1459  : trace_label_diverges (RTLabs_status ge) s ≝ ?
1460.
1461*)
Note: See TracBrowser for help on using the repository browser.