Definition var := nat.Definition adr := nat.Definition stack := table var adr.Definition heap := table adr adr.Definition state := (stack * heap)%type.Inductive command :=
| Skip : command
| Assign: var -> var -> command
| Load : var -> var -> command
| Store: var -> var -> command
| Seq: command -> command -> command.Inductive command :=
| Skip : command
| Assign: var -> var -> command
| Load : var -> var -> command
| Store: var -> var -> command
| Seq: command -> command -> command.Inductive command :=
| Skip : command
| Assign: var -> var -> command
| Load : var -> var -> command
| Store: var -> var -> command
| Seq: command -> command -> command.Inductive command :=
| Skip : command
| Assign: var -> var -> command
| Load : var -> var -> command
| Store: var -> var -> command
| Seq: command -> command -> command.Inductive command :=
| Skip : command
| Assign: var -> var -> command
| Load : var -> var -> command
| Store: var -> var -> command
| Seq: command -> command -> command.Inductive command :=
| Skip : command
| Assign: var -> var -> command
| Load : var -> var -> command
| Store: var -> var -> command
| Seq: command -> command -> command.Inductive step: relation (command * state) :=
| stepAssign:
        forall x y v stk hp,
        table_get stk y = Some v ->
        step (Assign x y, (stk,hp)) (Skip, (table_set x v stk, hp))
| stepLoad:
        forall x y v v' stk hp,
         table_get stk y = Some v ->
         table_get hp v = Some v' ->
         step (Load x y, (stk,hp)) (Skip, (table_set x v' stk, hp))
| stepStore:
         forall x y v p stk hp,
          table_get stk y = Some v ->
          table_get stk x = Some p ->
          step (Store x y, (stk,hp)) (Skip, (stk, table_set p v hp))
| stepSeq0:
         forall c2 s,
         step (Seq Skip c2, s) (c2, s)
| stepSeq1:
         forall c1 c1' c2 s s',
         step (c1,s) (c1',s') ->
         step (Seq c1 c2, s) (Seq c1' c2, s').Inductive step: relation (command * state) :=
| stepAssign:
        forall x y v stk hp,
        table_get stk y = Some v ->
        step (Assign x y, (stk,hp)) (Skip, (table_set x v stk, hp))
| stepLoad:
        forall x y v v' stk hp,
         table_get stk y = Some v ->
         table_get hp v = Some v' ->
         step (Load x y, (stk,hp)) (Skip, (table_set x v' stk, hp))
| stepStore:
         forall x y v p stk hp,
          table_get stk y = Some v ->
          table_get stk x = Some p ->
          step (Store x y, (stk,hp)) (Skip, (stk, table_set p v hp))
| stepSeq0:
         forall c2 s,
         step (Seq Skip c2, s) (c2, s)
| stepSeq1:
         forall c1 c1' c2 s s',
         step (c1,s) (c1',s') ->
         step (Seq c1 c2, s) (Seq c1' c2, s').Inductive step: relation (command * state) :=
| stepAssign:
        forall x y v stk hp,
        table_get stk y = Some v ->
        step (Assign x y, (stk,hp)) (Skip, (table_set x v stk, hp))
| stepLoad:
        forall x y v v' stk hp,
         table_get stk y = Some v ->
         table_get hp v = Some v' ->
         step (Load x y, (stk,hp)) (Skip, (table_set x v' stk, hp))
| stepStore:
         forall x y v p stk hp,
          table_get stk y = Some v ->
          table_get stk x = Some p ->
          step (Store x y, (stk,hp)) (Skip, (stk, table_set p v hp))
| stepSeq0:
         forall c2 s,
         step (Seq Skip c2, s) (c2, s)
| stepSeq1:
         forall c1 c1' c2 s s',
         step (c1,s) (c1',s') ->
         step (Seq c1 c2, s) (Seq c1' c2, s').Inductive step: relation (command * state) :=
| stepAssign:
        forall x y v stk hp,
        table_get stk y = Some v ->
        step (Assign x y, (stk,hp)) (Skip, (table_set x v stk, hp))
| stepLoad:
        forall x y v v' stk hp,
         table_get stk y = Some v ->
         table_get hp v = Some v' ->
         step (Load x y, (stk,hp)) (Skip, (table_set x v' stk, hp))
| stepStore:
         forall x y v p stk hp,
          table_get stk y = Some v ->
          table_get stk x = Some p ->
          step (Store x y, (stk,hp)) (Skip, (stk, table_set p v hp))
| stepSeq0:
         forall c2 s,
         step (Seq Skip c2, s) (c2, s)
| stepSeq1:
         forall c1 c1' c2 s s',
         step (c1,s) (c1',s') ->
         step (Seq c1 c2, s) (Seq c1' c2, s').Inductive step: relation (command * state) :=
| stepAssign:
        forall x y v stk hp,
        table_get stk y = Some v ->
        step (Assign x y, (stk,hp)) (Skip, (table_set x v stk, hp))
| stepLoad:
        forall x y v v' stk hp,
         table_get stk y = Some v ->
         table_get hp v = Some v' ->
         step (Load x y, (stk,hp)) (Skip, (table_set x v' stk, hp))
| stepStore:
         forall x y v p stk hp,
          table_get stk y = Some v ->
          table_get stk x = Some p ->
          step (Store x y, (stk,hp)) (Skip, (stk, table_set p v hp))
| stepSeq0:
         forall c2 s,
         step (Seq Skip c2, s) (c2, s)
| stepSeq1:
         forall c1 c1' c2 s s',
         step (c1,s) (c1',s') ->
         step (Seq c1 c2, s) (Seq c1' c2, s').Inductive step: relation (command * state) :=
| stepAssign:
        forall x y v stk hp,
        table_get stk y = Some v ->
        step (Assign x y, (stk,hp)) (Skip, (table_set x v stk, hp))
| stepLoad:
        forall x y v v' stk hp,
         table_get stk y = Some v ->
         table_get hp v = Some v' ->
         step (Load x y, (stk,hp)) (Skip, (table_set x v' stk, hp))
| stepStore:
         forall x y v p stk hp,
          table_get stk y = Some v ->
          table_get stk x = Some p ->
          step (Store x y, (stk,hp)) (Skip, (stk, table_set p v hp))
| stepSeq0:
         forall c2 s,
         step (Seq Skip c2, s) (c2, s)
| stepSeq1:
         forall c1 c1' c2 s s',
         step (c1,s) (c1',s') ->
         step (Seq c1 c2, s) (Seq c1' c2, s').Inductive step': relation (list command * state)  :=
| step'Skip:
         forall k s,
         step' (Skip :: k, s) (k,s)
| step'Assign:
        forall x y v stk hp k,
        table_get stk y = Some v ->
        step' (Assign x y :: k, (stk,hp)) (k, (table_set x v stk, hp))
| step'Load:
        forall x y v v' stk hp k,
         table_get stk y = Some v ->
         table_get hp v = Some v' ->
         step' (Load x y :: k, (stk,hp)) (k, (table_set x v' stk, hp))
| step'Store:
         forall x y v p stk hp k,
          table_get stk y = Some v ->
          table_get stk x = Some p ->
          step' (Store x y :: k, (stk,hp)) (k, (stk, table_set p v hp))
| step'Seq:
         forall c1 c2 k s cs',
         step' (c1 :: c2 ::k, s) cs' ->
         step' (Seq c1 c2 :: k, s) cs'.Inductive step': relation (list command * state)  :=
| step'Skip:
         forall k s,
         step' (Skip :: k, s) (k,s)
| step'Assign:
        forall x y v stk hp k,
        table_get stk y = Some v ->
        step' (Assign x y :: k, (stk,hp)) (k, (table_set x v stk, hp))
| step'Load:
        forall x y v v' stk hp k,
         table_get stk y = Some v ->
         table_get hp v = Some v' ->
         step' (Load x y :: k, (stk,hp)) (k, (table_set x v' stk, hp))
| step'Store:
         forall x y v p stk hp k,
          table_get stk y = Some v ->
          table_get stk x = Some p ->
          step' (Store x y :: k, (stk,hp)) (k, (stk, table_set p v hp))
| step'Seq:
         forall c1 c2 k s cs',
         step' (c1 :: c2 ::k, s) cs' ->
         step' (Seq c1 c2 :: k, s) cs'.Inductive step': relation (list command * state)  :=
| step'Skip:
         forall k s,
         step' (Skip :: k, s) (k,s)
| step'Assign:
        forall x y v stk hp k,
        table_get stk y = Some v ->
        step' (Assign x y :: k, (stk,hp)) (k, (table_set x v stk, hp))
| step'Load:
        forall x y v v' stk hp k,
         table_get stk y = Some v ->
         table_get hp v = Some v' ->
         step' (Load x y :: k, (stk,hp)) (k, (table_set x v' stk, hp))
| step'Store:
         forall x y v p stk hp k,
          table_get stk y = Some v ->
          table_get stk x = Some p ->
          step' (Store x y :: k, (stk,hp)) (k, (stk, table_set p v hp))
| step'Seq:
         forall c1 c2 k s cs',
         step' (c1 :: c2 ::k, s) cs' ->
         step' (Seq c1 c2 :: k, s) cs'.Inductive step': relation (list command * state)  :=
| step'Skip:
         forall k s,
         step' (Skip :: k, s) (k,s)
| step'Assign:
        forall x y v stk hp k,
        table_get stk y = Some v ->
        step' (Assign x y :: k, (stk,hp)) (k, (table_set x v stk, hp))
| step'Load:
        forall x y v v' stk hp k,
         table_get stk y = Some v ->
         table_get hp v = Some v' ->
         step' (Load x y :: k, (stk,hp)) (k, (table_set x v' stk, hp))
| step'Store:
         forall x y v p stk hp k,
          table_get stk y = Some v ->
          table_get stk x = Some p ->
          step' (Store x y :: k, (stk,hp)) (k, (stk, table_set p v hp))
| step'Seq:
         forall c1 c2 k s cs',
         step' (c1 :: c2 ::k, s) cs' ->
         step' (Seq c1 c2 :: k, s) cs'.Inductive step': relation (list command * state)  :=
| step'Skip:
         forall k s,
         step' (Skip :: k, s) (k,s)
| step'Assign:
        forall x y v stk hp k,
        table_get stk y = Some v ->
        step' (Assign x y :: k, (stk,hp)) (k, (table_set x v stk, hp))
| step'Load:
        forall x y v v' stk hp k,
         table_get stk y = Some v ->
         table_get hp v = Some v' ->
         step' (Load x y :: k, (stk,hp)) (k, (table_set x v' stk, hp))
| step'Store:
         forall x y v p stk hp k,
          table_get stk y = Some v ->
          table_get stk x = Some p ->
          step' (Store x y :: k, (stk,hp)) (k, (stk, table_set p v hp))
| step'Seq:
         forall c1 c2 k s cs',
         step' (c1 :: c2 ::k, s) cs' ->
         step' (Seq c1 c2 :: k, s) cs'.Inductive step': relation (list command * state)  :=
| step'Skip:
         forall k s,
         step' (Skip :: k, s) (k,s)
| step'Assign:
        forall x y v stk hp k,
        table_get stk y = Some v ->
        step' (Assign x y :: k, (stk,hp)) (k, (table_set x v stk, hp))
| step'Load:
        forall x y v v' stk hp k,
         table_get stk y = Some v ->
         table_get hp v = Some v' ->
         step' (Load x y :: k, (stk,hp)) (k, (table_set x v' stk, hp))
| step'Store:
         forall x y v p stk hp k,
          table_get stk y = Some v ->
          table_get stk x = Some p ->
          step' (Store x y :: k, (stk,hp)) (k, (stk, table_set p v hp))
| step'Seq:
         forall c1 c2 k s cs',
         step' (c1 :: c2 ::k, s) cs' ->
         step' (Seq c1 c2 :: k, s) cs'.Fixpoint stackit (k: list command) (c: command) : command :=
 match k with
 | nil => c
 | c'::k' => stackit k' (Seq c c')
 end.Definition stackit' (k: list command) : command :=
 match k with nil => Skip | c::k' => stackit k' c end.(* Eval compute in stackit' (Skip :: Assign 0 1 :: Assign 0 2 :: Assign 0 3 :: nil). *)

Ltac inv H := inversion H; clear H; subst.

(* Specifications: *)
Lemma stackit_step: forall s s' k c c', step (c,s) (c',s') -> step (stackit k c, s) (stackit k c', s').
Lemma step'_equiv: forall k s k' s', clos_refl_trans _ step' (k,s) (k', s') -> clos_refl_trans _ step (stackit' k, s) (stackit' k', s').