Admitted. (* OUT-OF-SCOPE *)
(* TODO: Map rewrite Inductive aval : aexp -> Prop := | av_num : forall n, aval (ANum n).  Reserved Notation " t '/' st '===>a' t' " (at level 40, st at level 39).  Inductive astep : state -> aexp -> aexp -> Prop := | AS_Id : forall st i, AId i / st ===>a ANum (st i) | AS_Plus : forall st n1 n2, APlus (ANum n1) (ANum n2) / st ===>a ANum (n1 + n2) | AS_Plus1 : forall st a1 a1' a2, a1 / st ===>a a1' -> (APlus a1 a2) / st ===>a (APlus a1' a2) | AS_Plus2 : forall st v1 a2 a2', aval v1 -> a2 / st ===>a a2' -> (APlus v1 a2) / st ===>a (APlus v1 a2') | AS_Minus : forall st n1 n2, (AMinus (ANum n1) (ANum n2)) / st ===>a (ANum (minus n1 n2)) | AS_Minus1 : forall st a1 a1' a2, a1 / st ===>a a1' -> (AMinus a1 a2) / st ===>a (AMinus a1' a2) | AS_Minus2 : forall st v1 a2 a2', aval v1 -> a2 / st ===>a a2' -> (AMinus v1 a2) / st ===>a (AMinus v1 a2') | AS_Mult : forall st n1 n2, (AMult (ANum n1) (ANum n2)) / st ===>a (ANum (mult n1 n2)) | AS_Mult1 : forall st a1 a1' a2, a1 / st ===>a a1' -> (AMult a1 a2) / st ===>a (AMult a1' a2) | AS_Mult2 : forall st v1 a2 a2', aval v1 -> a2 / st ===>a a2' -> (AMult v1 a2) / st ===>a (AMult v1 a2')  where " t '/' st '===>a' t' " := (astep st t t').  Reserved Notation " t '/' st '===>b' t' " (at level 40, st at level 39).  Inductive bstep : state -> bexp -> bexp -> Prop := | BS_Eq : forall st n1 n2, (BEq (ANum n1) (ANum n2)) / st ===>b (if (beq_nat n1 n2) then BTrue else BFalse) | BS_Eq1 : forall st a1 a1' a2, a1 / st ===>a a1' -> (BEq a1 a2) / st ===>b (BEq a1' a2) | BS_Eq2 : forall st v1 a2 a2', aval v1 -> a2 / st ===>a a2' -> (BEq v1 a2) / st ===>b (BEq v1 a2') | BS_LtEq : forall st n1 n2, (BLe (ANum n1) (ANum n2)) / st ===>b (if (leb n1 n2) then BTrue else BFalse) | BS_LtEq1 : forall st a1 a1' a2, a1 / st ===>a a1' -> (BLe a1 a2) / st ===>b (BLe a1' a2) | BS_LtEq2 : forall st v1 a2 a2', aval v1 -> a2 / st ===>a a2' -> (BLe v1 a2) / st ===>b (BLe v1 a2') | BS_NotTrue : forall st, (BNot BTrue) / st ===>b BFalse | BS_NotFalse : forall st, (BNot BFalse) / st ===>b BTrue | BS_NotStep : forall st b1 b1', b1 / st ===>b b1' -> (BNot b1) / st ===>b (BNot b1') | BS_AndTrueTrue : forall st, (BAnd BTrue BTrue) / st ===>b BTrue | BS_AndTrueFalse : forall st, (BAnd BTrue BFalse) / st ===>b BFalse | BS_AndFalse : forall st b2, (BAnd BFalse b2) / st ===>b BFalse | BS_AndTrueStep : forall st b2 b2', b2 / st ===>b b2' -> (BAnd BTrue b2) / st ===>b (BAnd BTrue b2') | BS_AndStep : forall st b1 b1' b2, b1 / st ===>b b1' -> (BAnd b1 b2) / st ===>b (BAnd b1' b2)  where " t '/' st '===>b' t' " := (bstep st t t').  (** The semantics of commands is the interesting part.  We need two small tricks to make it work:  - We use [SKIP] as a "command value" -- i.e., a command that has reached a normal form.  - An assignment command reduces to [SKIP] (and an updated state).  - The sequencing command waits until its left-hand subcommand has reduced to [SKIP], then throws it away so that reduction can continue with the right-hand subcommand.  - We reduce a [WHILE] command by transforming it into a conditional followed by the same [WHILE]. *)
(** (There are other ways of achieving the effect of the latter trick, but they all share the feature that the original [WHILE] command needs to be saved somewhere while a single copy of the loop body is being reduced.) *)
Reserved Notation " t '/' st '===>' t' '/' st' "
(at level 40, st at level 39, t' at level 39).
Inductive cstep : (com * state) -> (com * state) -> Prop :=
| 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
where " t '/' st '===>' t' '/' st' " := (cstep (t,st) (t',st')).
(* ################################################################# *)
(** * Concurrent Imp *)
(** Finally, to show the power of this definitional style, let's enrich Imp with a new form of command that runs two subcommands in parallel and terminates when both have terminated.  To reflect the unpredictability of scheduling, the actions of the subcommands may be interleaved in any order, but they share the same memory and can communicate by reading and writing the same variables. *)
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).

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