(**************************************************************)
(*   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).
Local Notation "P // s -[ k ]-> t" := (sss_steps (@mm_sss _) P k s t).
Local Notation "P // s -+> t" := (sss_progress (@mm_sss _) P s t).
Local Notation "P // s ->> t" := (sss_compute (@mm_sss _) P s t).
(** ** Simulating Binary Stacks with numbers *)
Section Minsky_Machine_utils.
Variable (n : nat).
Ltac dest x y := destruct (pos_eq_dec x y) as [ | ]; [ subst x | ]; rew vec.
Section mm_null.
Variable (src zero : pos n) (Hsz : src <> zero).
Definition mm_null i := DEC src (2+i) :: DEC zero i :: nil.
Fact mm_null_length i : length (mm_null i) = 2.
Fact mm_null_progress i v st :
v#>zero = 0
-> st = (2+i,v[0/src])
-> (i,mm_null i) // (i,v) -+> st.
End mm_null.
Hint Rewrite mm_null_length : length_db.
Section mm_nullify.
(* Make every register in the list lr become 0 *)
Variable (zero : pos n).
Fixpoint mm_nullify i lr :=
match lr with
| nil   => nil
| x::lr => mm_null x zero i ++ mm_nullify (2+i) lr
end.
Fact mm_nullify_length i lr : length (mm_nullify i lr) = 2*length lr.
Fact mm_nullify_compute i lr v w :
v#>zero = 0
-> (forall p, In p lr -> p <> zero)
-> (forall p, In p lr -> w#>p = 0)
-> (forall p, ~ In p lr -> w#>p = v#>p)
-> (i,mm_nullify i lr) // (i,v) ->> (length (mm_nullify i lr)+i,w).
End mm_nullify.
Section transfert.
Variables (src dst zero : pos n).
Hypothesis (Hsd : src <> dst) (Hsz : src <> zero) (Hdz : dst <> zero).
Definition mm_transfert i := DEC src (3+i) :: INC dst :: DEC zero i :: nil.
Fact mm_transfert_length i : length (mm_transfert i) = 3.
Fact mm_transfert_progress i v st :
v#>dst = 0
-> v#>zero = 0
-> st = (3+i,v[0/src][(v#>src)/dst])
-> (i,mm_transfert i) // (i,v) -+> st.
End transfert.
Hint Rewrite mm_transfert_length : length_db.
Section div2.
Variables (src quo rem : pos n)
(Hsq : src <> quo) (Hsr : src <> rem) (Hqr : quo <> rem)
(i : nat).
Definition mm_div2 :=
DEC src (6+i) ::
INC rem ::
DEC src (i+6) ::
DEC rem (4+i) ::
INC quo ::
DEC rem i ::
nil.
Fact mm_div2_length : length mm_div2 = 6.
Let mm_div2_spec_1 k v w :
v#>src = 1+2*k -> v#>rem = 0 -> w = v[0/src][(k+(v#>quo))/quo][1/rem] -> (i,mm_div2) // (i,v) -+> (6+i,w).
Fact mm_div2_progress v :
v#>quo = 0
-> v#>rem = 0
-> let (k,b) := div2 (v#>src)
in  (i,mm_div2) // (i,v) -+> (6+i,v[0/src][k/quo][(if b then 1 else 0)/rem]).

(* Specifications: *)
Corollary mm_div2_progress_1 v k st :
v#>quo = 0
-> v#>rem = 0
-> div2 (v#>src) = (k,true)
-> st = (6+i,v[0/src][k/quo][1/rem])
-> (i,mm_div2) // (i,v) -+> st.
Corollary mm_div2_progress_0 v k st :
v#>quo = 0
-> v#>rem = 0
-> div2 (v#>src) = (k,false)
-> st = (6+i,v[0/src][k/quo][0/rem])
-> (i,mm_div2) // (i,v) -+> st.