(*  Let us imagine an abstract machine for computing on the monoid (M,o,u)
  (see "monoid.v").
    This machine has a register X and a stack S.
*)


Inductive Instr : Set :=
  | MUL : Instr
  | SQR : Instr
  | PUSH : Instr
  | SWAP : Instr.(*  Let us imagine an abstract machine for computing on the monoid (M,o,u)
  (see "monoid.v").
    This machine has a register X and a stack S.
*)


Inductive Instr : Set :=
  | MUL : Instr
  | SQR : Instr
  | PUSH : Instr
  | SWAP : Instr.(*  Let us imagine an abstract machine for computing on the monoid (M,o,u)
  (see "monoid.v").
    This machine has a register X and a stack S.
*)


Inductive Instr : Set :=
  | MUL : Instr
  | SQR : Instr
  | PUSH : Instr
  | SWAP : Instr.(*  Let us imagine an abstract machine for computing on the monoid (M,o,u)
  (see "monoid.v").
    This machine has a register X and a stack S.
*)


Inductive Instr : Set :=
  | MUL : Instr
  | SQR : Instr
  | PUSH : Instr
  | SWAP : Instr.(*  Let us imagine an abstract machine for computing on the monoid (M,o,u)
  (see "monoid.v").
    This machine has a register X and a stack S.
*)


Inductive Instr : Set :=
  | MUL : Instr
  | SQR : Instr
  | PUSH : Instr
  | SWAP : Instr.(* sequences of instructions *)

Inductive Code : Set :=
  | End : Code
  | seq : Instr -> Code -> Code.(* sequences of instructions *)

Inductive Code : Set :=
  | End : Code
  | seq : Instr -> Code -> Code.(* sequences of instructions *)

Inductive Code : Set :=
  | End : Code
  | seq : Instr -> Code -> Code.(* code appending *)

(*Recursive Definition app:Code->Code->Code:=
    End c' => c'
  | (seq i  c) c' => (seq i ( app c  c')).
*)

Fixpoint app (c : Code) : Code -> Code :=
  fun c' : Code => match c with
                   | End => c'
                   | seq i c => seq i (app c c')
                   end.Inductive Stack : Set :=
   | emptystack : Stack
   | push : M -> Stack -> Stack.Inductive Stack : Set :=
   | emptystack : Stack
   | push : M -> Stack -> Stack.Inductive Stack : Set :=
   | emptystack : Stack
   | push : M -> Stack -> Stack.Definition top (s : Stack) :=
   match s return M with
   | emptystack => uM
   | push m _ => m
   end.Definition pop (s : Stack) :=
   match s return Stack with
   | emptystack => emptystack
   | push _ r => r
   end.(* configurations of the abstract machine *)
(******************************************)


 Record Config : Set := config {config_X : M; config_S : Stack}.(* configurations of the abstract machine *)
(******************************************)


 Record Config : Set := config {config_X : M; config_S : Stack}.(* configurations of the abstract machine *)
(******************************************)


 Record Config : Set := config {config_X : M; config_S : Stack}.(* configurations of the abstract machine *)
(******************************************)


 Record Config : Set := config {config_X : M; config_S : Stack}.

(* Specifications: *)
Lemma Config_inv : forall (a a' : M) (s s' : Stack), a = a' -> s = s' -> config a s = config a' s'.