(** * Satisfaction of specifications *)

(** The second additional results shows that if all executions
  of the source C program satisfies a given specification,
  then all executions of the produced Asm program satisfy
  this specification as well.  *)

(** The specifications we consider here are sets of observable
  behaviors, representing the good behaviors a program is expected
  to have.  A specification can be as simple as
  ``the program does not go wrong'' or as precise as
  ``the program prints a prime number then terminates with code 0''.
  As usual in Coq, sets of behaviors are represented as predicates
  [program_behavior -> Prop]. *)

Definition specification := program_behavior -> Prop.(** A program satisfies a specification if all its observable behaviors
  are in the specification. *)

Definition c_program_satisfies_spec (p: Csyntax.program) (spec: specification): Prop :=
  forall beh,  program_behaves (Csem.semantics p) beh -> spec beh.Definition asm_program_satisfies_spec (p: Asm.program) (spec: specification): Prop :=
  forall beh,  program_behaves (Asm.semantics p) beh -> spec beh.(** It is not always the case that if the source program satisfies a
  specification, then the generated assembly code satisfies it as
  well.  For example, if the specification is ``the program goes wrong
  on an undefined behavior'', a C source that goes wrong satisfies
  this specification but can be compiled into Asm code that does not
  go wrong and therefore does not satisfy the specification.

  For this reason, we restrict ourselves to safety-enforcing specifications:
  specifications that exclude ``going wrong'' behaviors and are satisfied
  only by programs that execute safely. *)

Definition safety_enforcing_specification (spec: specification): Prop :=
  forall beh, spec beh -> not_wrong beh.

Theorem transf_c_program_preserves_spec: forall p tp spec, transf_c_program p = OK tp -> safety_enforcing_specification spec -> c_program_satisfies_spec p spec -> asm_program_satisfies_spec tp spec.