(* *********************************************************************)
(*                                                                     *)
(*              The Compcert verified compiler                         *)
(*                                                                     *)
(*          Xavier Leroy, INRIA Paris-Rocquencourt                     *)
(*                                                                     *)
(*  Copyright Institut National de Recherche en Informatique et en     *)
(*  Automatique.  All rights reserved.  This file is distributed       *)
(*  under the terms of the GNU General Public License as published by  *)
(*  the Free Software Foundation, either version 2 of the License, or  *)
(*  (at your option) any later version.  This file is also distributed *)
(*  under the terms of the INRIA Non-Commercial License Agreement.     *)
(*                                                                     *)
(* *********************************************************************)
(** Characterization and properties of deterministic external worlds and deterministic semantics *)
(** * Deterministic worlds *)
(** One source of possible nondeterminism is that our semantics leave unspecified the results of system calls. Different results to e.g. a "read" operation can of course lead to different behaviors for the program. We address this issue by modeling a notion of deterministic external world that uniquely determines the results of external calls. *)
(** An external world is a function that, given the name of an external call and its arguments, returns either [None], meaning that this external call gets stuck, or [Some(r,w)], meaning that this external call succeeds, has result [r], and changes the world to [w]. *)
CoInductive world: Type :=
World (io: string -> list eventval -> option (eventval * world))
(vload: memory_chunk -> ident -> ptrofs -> option (eventval * world))
(vstore: memory_chunk -> ident -> ptrofs -> eventval -> option world).
Definition nextworld_io (w: world) (evname: string) (evargs: list eventval) :
option (eventval * world) :=
match w with World io vl vs => io evname evargs end.
Definition nextworld_vload (w: world) (chunk: memory_chunk) (id: ident) (ofs: ptrofs) :
option (eventval * world) :=
match w with World io vl vs => vl chunk id ofs end.
Definition nextworld_vstore (w: world) (chunk: memory_chunk) (id: ident) (ofs: ptrofs) (v: eventval):
option world :=
match w with World io vl vs => vs chunk id ofs v end.
(** A trace is possible in a given world if all events correspond to non-stuck external calls according to the given world. Two predicates are defined, for finite and infinite traces respectively: - [possible_trace w t w'], where [w] is the initial state of the world, [t] the finite trace of interest, and [w'] the state of the world after performing trace [t]. - [possible_traceinf w T], where [w] is the initial state of the world and [T] the infinite trace of interest. *)
Inductive possible_event: world -> event -> world -> Prop :=
| possible_event_syscall: forall w1 evname evargs evres w2,
nextworld_io w1 evname evargs = Some (evres, w2) ->
possible_event w1 (Event_syscall evname evargs evres) w2
| possible_event_vload: forall w1 chunk id ofs evres w2,
nextworld_vload w1 chunk id ofs = Some (evres, w2) ->
possible_event w1 (Event_vload chunk id ofs evres) w2
| possible_event_vstore: forall w1 chunk id ofs evarg w2,
nextworld_vstore w1 chunk id ofs evarg = Some w2 ->
possible_event w1 (Event_vstore chunk id ofs evarg) w2
| possible_event_annot: forall w1 id args,
possible_event w1 (Event_annot id args) w1.
Inductive possible_trace: world -> trace -> world -> Prop :=
| possible_trace_nil: forall w,
possible_trace w E0 w
| possible_trace_cons: forall w1 ev w2 t w3,
possible_event w1 ev w2 -> possible_trace w2 t w3 ->
possible_trace w1 (ev :: t) w3.

(* Specifications: *)
Lemma possible_trace_app:
forall t2 w2 w0 t1 w1,
possible_trace w0 t1 w1 -> possible_trace w1 t2 w2 ->
possible_trace w0 (t1 ** t2) w2.
Lemma possible_trace_app_inv:
forall t2 w2 t1 w0,
possible_trace w0 (t1 ** t2) w2 ->
exists w1, possible_trace w0 t1 w1 /\ possible_trace w1 t2 w2.
Lemma match_possible_traces:
forall ge t1 t2 w0 w1 w2,
match_traces ge t1 t2 -> possible_trace w0 t1 w1 -> possible_trace w0 t2 w2 ->
t1 = t2 /\ w1 = w2.
Lemma possible_trace_app:
forall t2 w2 w0 t1 w1,
possible_trace w0 t1 w1 -> possible_trace w1 t2 w2 ->
possible_trace w0 (t1 ** t2) w2.
Lemma possible_trace_app_inv:
forall t2 w2 t1 w0,
possible_trace w0 (t1 ** t2) w2 ->
exists w1, possible_trace w0 t1 w1 /\ possible_trace w1 t2 w2.
Lemma match_possible_traces:
forall ge t1 t2 w0 w1 w2,
match_traces ge t1 t2 -> possible_trace w0 t1 w1 -> possible_trace w0 t2 w2 ->
t1 = t2 /\ w1 = w2.