(**************************************************************)
(*   Copyright Dominique Larchey-Wendling [*]                 *)
(*                                                            *)
(*                             [*] Affiliation LORIA -- CNRS  *)
(**************************************************************)
(*      This file is distributed under the terms of the       *)
(*         CeCILL v2 FREE SOFTWARE LICENSE AGREEMENT          *)
(**************************************************************)
Set Implicit Arguments.
Tactic Notation "rew" "length" := autorewrite with length_db.
Local Notation "e #> x" := (vec_pos e x).
Local Notation "e [ v / x ]" := (vec_change e x v).
(** * Minsky Machines  A Minsky machine has n registers and there are just two instructions  1/ INC x   : increment register x by 1 2/ DEC x k : decrement register x by 1 if x > 0 or jump to k if x = 0  *)
Inductive mm_instr n : Set :=
| mm_inc : pos n -> mm_instr n
| mm_dec : pos n -> nat -> mm_instr n
.
Notation INC := mm_inc.
Notation DEC := mm_dec.
(** ** Semantics for MM *)
Section Minsky_Machine.
Variable (n : nat).
Definition mm_state := (nat*vec nat n)%type.
(* Minsky machine small step semantics *)
Inductive mm_sss : mm_instr n -> mm_state -> mm_state -> Prop :=
| in_mm_sss_inc   : forall i x v,                   INC x   // (i,v) -1> (1+i,v[(S (v#>x))/x])
| in_mm_sss_dec_0 : forall i x k v,   v#>x = O   -> DEC x k // (i,v) -1> (k,v)
| in_mm_sss_dec_1 : forall i x k v u, v#>x = S u -> DEC x k // (i,v) -1> (1+i,v[u/x])
where "i // s -1> t" := (mm_sss i s t).
Fact mm_sss_fun i s t1 t2 : i // s -1> t1 -> i // s -1> t2 -> t1 = t2.
Fact mm_sss_total ii s : { t | ii // s -1> t }.
Fact mm_sss_INC_inv x i v j w : INC x // (i,v) -1> (j,w) -> j=1+i /\ w = v[(S (v#>x))/x].
Fact mm_sss_DEC1_inv x k u i v j w : v#>x = S u -> DEC x k // (i,v) -1> (j,w) -> j=1+i /\ w = v[u/x].
(* Definition mm_step_stall := sss_step_stall mm_sss. Definition mm_program := (nat*list (mm_instr n))%type. Definition mm_steps := sss_steps mm_sss. Definition mm_compute := sss_compute mm_sss. *)
Notation "P // s -[ k ]-> t" := (sss_steps mm_sss P k s t).
Notation "P // s -+> t" := (sss_progress mm_sss P s t).
Notation "P // s ->> t" := (sss_compute mm_sss P s t).
Fact mm_progress_INC P i x v st :
(i,INC x::nil) <sc P
-> P // (1+i,v[(S (v#>x))/x]) ->> st
-> P // (i,v) -+> st.

(* Specifications: *)
Corollary mm_compute_INC P i x v st : (i,INC x::nil) <sc P -> P // (1+i,v[(S (v#>x))/x]) ->> st -> P // (i,v) ->> st.
Corollary mm_compute_DEC_0 P i x k v st : (i,DEC x k::nil) <sc P -> v#>x = O -> P // (k,v) ->> st -> P // (i,v) ->> st.
Corollary mm_compute_DEC_S P i x k v u st : (i,DEC x k::nil) <sc P -> v#>x = S u -> P // (1+i,v[u/x]) ->> st -> P // (i,v) ->> st.
Fact mm_steps_DEC_0_inv k P i x p v st :
(i,DEC x p::nil) <sc P
-> k <> 0
-> v#>x = 0
-> P // (i,v) -[k]-> st
-> exists k', k' < k /\ P // (p,v) -[k']-> st.