Module CImp.
Inductive com : Type :=
| CSkip : com
| CAss : id -> aexp -> com
| CSeq : com -> com -> com
| CIf : bexp -> com -> com -> com
| CWhile : bexp -> com -> com
(* New: *)
| CPar : com -> com -> com.
Notation "'SKIP'" :=
CSkip.
Notation "x '::=' a" :=
(CAss x a) (at level 60).
Notation "c1 ;; c2" :=
(CSeq c1 c2) (at level 80, right associativity).
Notation "'WHILE' b 'DO' c 'END'" :=
(CWhile b c) (at level 80, right associativity).
Notation "'IFB' b 'THEN' c1 'ELSE' c2 'FI'" :=
(CIf b c1 c2) (at level 80, right associativity).
Notation "'PAR' c1 'WITH' c2 'END'" :=
(CPar c1 c2) (at level 80, right associativity).
Inductive cstep : (com * state)  -> (com * state) -> Prop :=
(* Old part *)
| CS_AssStep : forall st i a a',
a / st ===>a a' ->
(i ::= a) / st ===> (i ::= a') / st
| CS_Ass : forall st i n,
(i ::= (ANum n)) / st ===> SKIP / (t_update st i n)
| CS_SeqStep : forall st c1 c1' st' c2,
c1 / st ===> c1' / st' ->
(c1 ;; c2) / st ===> (c1' ;; c2) / st'
| CS_SeqFinish : forall st c2,
(SKIP ;; c2) / st ===> c2 / st
| CS_IfTrue : forall st c1 c2,
(IFB BTrue THEN c1 ELSE c2 FI) / st ===> c1 / st
| CS_IfFalse : forall st c1 c2,
(IFB BFalse THEN c1 ELSE c2 FI) / st ===> c2 / st
| CS_IfStep : forall st b b' c1 c2,
b /st ===>b b' ->
(IFB b THEN c1 ELSE c2 FI) / st
===> (IFB b' THEN c1 ELSE c2 FI) / st
| CS_While : forall st b c1,
(WHILE b DO c1 END) / st
===> (IFB b THEN (c1;; (WHILE b DO c1 END)) ELSE SKIP FI) / st
(* New part: *)
| CS_Par1 : forall st c1 c1' c2 st',
c1 / st ===> c1' / st' ->
(PAR c1 WITH c2 END) / st ===> (PAR c1' WITH c2 END) / st'
| CS_Par2 : forall st c1 c2 c2' st',
c2 / st ===> c2' / st' ->
(PAR c1 WITH c2 END) / st ===> (PAR c1 WITH c2' END) / st'
| CS_ParDone : forall st,
(PAR SKIP WITH SKIP END) / st ===> SKIP / st
where " t '/' st '===>' t' '/' st' " := (cstep (t,st) (t',st')).
Definition cmultistep := multi cstep.
Notation " t '/' st '===>*' t' '/' st' " :=
(multi cstep  (t,st) (t',st'))
(at level 40, st at level 39, t' at level 39).
(** Among the many interesting properties of this language is the fact that the following program can terminate with the variable [X] set to any value. *)
Definition par_loop : com :=
PAR
Y ::= ANum 1
WITH
WHILE BEq (AId Y) (ANum 0) DO
X ::= APlus (AId X) (ANum 1)
END
END.
(** In particular, it can terminate with [X] set to [0]: *)
Example par_loop_example_0:
exists st',
par_loop / empty_state  ===>* SKIP / st'
/\ st' X = 0.
End CImp.
(* ################################################################# *)
(** * A Small-Step Stack Machine *)
(** Our last example is a small-step semantics for the stack machine example from the [Imp] chapter. *)
Definition stack := list nat.
Definition prog  := list sinstr.
Inductive stack_step : state -> prog * stack -> prog * stack -> Prop :=
| SS_Push : forall st stk n p',
stack_step st (SPush n :: p', stk)      (p', n :: stk)
| SS_Load : forall st stk i p',
stack_step st (SLoad i :: p', stk)      (p', st i :: stk)
| SS_Plus : forall st stk n m p',
stack_step st (SPlus :: p', n::m::stk)  (p', (m+n)::stk)
| SS_Minus : forall st stk n m p',
stack_step st (SMinus :: p', n::m::stk) (p', (m-n)::stk)
| SS_Mult : forall st stk n m p',
stack_step st (SMult :: p', n::m::stk)  (p', (m*n)::stk).

Theorem stack_step_deterministic : forall st,
deterministic (stack_step st).