Section Monoid.
Variable M : Set.
Variable MO : monoid M.
Let uM := u _ MO.
Let oM := o _ MO.
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}.
(****************************************************************************)
Hint Resolve Config_inv: arith.
(* Operational semantics of the elementary instructions *)
Definition Exec1 (c : Instr) (v : Config) : Config :=
let (m, s) := v in
match c with
| MUL => config (oM m (top s)) (pop s)
| SQR => config (oM m m) s
| PUSH => config m (push m s)
| SWAP => config m (push (top (pop s)) (push (top s) (pop (pop s))))
end.
(****************************************************************)
(* Execution of a compound instruction *)
Fixpoint Exec (c : Code) : Config -> Config :=
fun v : Config =>
match c with
| End => v
| seq i c => Exec c (Exec1 i v)
end.
(****************************************)
(* Semantics of code   appending *)
(*********************************)

Lemma Exec_app :
forall (c c' : Code) (v : Config), Exec (app c c') v = Exec c' (Exec c v).