EECS 762

Programming Language Foundation I

Index
Blog
\[\newcommand{\evalR}{\textsf{evalR}} \newcommand{\aeval}{\textsf{aeval}} \newcommand{\beval}{\textsf{beval}} \newcommand{\ceval}{\textsf{ceval}} \newcommand{\aevalR}{\textsf{aevalR}} \newcommand{\bevalR}{\textsf{bevalR}} \newcommand{\cevalR}{\textsf{cevalR}} \newcommand{\derives}{\vdash} \newcommand{\llbracket}{[\![} \newcommand{\rrbracket}{]\!]} \newcommand{\oxford}[1]{\llbracket #1\rrbracket} \newcommand{\denotes}[2]{\oxford{#1}#2} \newcommand{\compile}[1]{\lfloor #1\rfloor} \newcommand{\lift}[1]{\lceil #1\rceil} \newcommand{\coqrel}[3]{\mathtt{#1\!==\![#2]\!==>\!#3}} \newcommand{\coqhoare}[3]{\mathtt{\lbrace\lbrace #1\rbrace\rbrace #2 \lbrace\lbrace #3\rbrace\rbrace}} \newcommand{\hoare}[3]{\lbrace #1\rbrace #2 \lbrace #3\rbrace}\]

An introduction to mechanized language semantics using Rocq and Software Foundations.

https://perry.alexander.name/eecs762

Formatted using Markdown and Marp for VS Code

Date: 2026-01-20


Formal Systems

All formal Systems ultimately define the semantics of a language


Mechanisms for defining semantics


What we will learn this semester


What we will prove


Our Target Language - IMP

The most over-analyzed programming language in existence.


Example: Sequential Factorial

Z := X;
Y := 1;
while Z <> 0 do
  Y := Y * Z;
  Z := Z - 1
end

Un-mechanized Concrete Syntax

a := nat
  | a + a
  | a - a
  | a * a
  | id

b := true
  | false
  | a = a
  | a <> a
  | a <= a
  | a > a
  | ~b
  | b && b

c := skip
  | c ; c
  | v := a
  | if b then c else c end
  | while b do c end

Mechanized in Abstract Syntax in Rocq

Inductive aexp : Type :=
  | ANum (n : nat)
  | AId (x : string)
  | APlus (a1 a2 : aexp)
  | AMinus (a1 a2 : aexp)
  | AMult (a1 a2 : aexp).

Inductive bexp : Type :=
  | BTrue
  | BFalse
  | BEq (a1 a2 : aexp)
  | BNeq (a1 a2 : aexp)
  | BLe (a1 a2 : aexp)
  | BGt (a1 a2 : aexp)
  | BNot (b : bexp)
  | BAnd (b1 b2 : bexp).

Inductive com : Type :=
  | CSkip
  | CAsgn (x : string) (a : aexp)
  | CSeq (c1 c2 : com)
  | CIf (b : bexp) (c1 c2 : com)
  | CWhile (b : bexp) (c : com).

Mechanized Abstract Syntax


Parsing Concrete Syntax

Rocq provides nifty notations for parsing to abstract syntax.

<{ Z := X;
   Y := 1;
   while Z <> 0 do
     Y := Y × Z;
     Z := Z - 1
   end }>
<{ concrete syntax }> -> abstract syntax

Computational Evaluation

Fixpoint aeval (a : aexp) : nat :=
  match a with
  | ANum n => n
  | APlus  a1 a2 => (aeval a1) + (aeval a2)
  | AMinus a1 a2 => (aeval a1) - (aeval a2)
  | AMult  a1 a2 => (aeval a1) * (aeval a2)
  end.

Example Proof

Example test_aeval1:
  aeval (APlus (ANum 2) (ANum 2)) = 4.
Proof. reflexivity. Qed.

Happier Example Proof

Example test_aeval1:
  aeval <{ 2 + 2 }> = 4.
Proof. reflexivity. Qed.

Booleans work the same way

Fixpoint beval (b : bexp) : bool :=
  match b with
  | BTrue       => true
  | BFalse      => false
  | BEq a1 a2   => (aeval a1) =? (aeval a2)
  | BNeq a1 a2  => negb ((aeval a1) =? (aeval a2))
  | BLe a1 a2   => (aeval a1) <=? (aeval a2)
  | BGt a1 a2   => negb ((aeval a1) <=? (aeval a2))
  | BNot b1     => negb (beval b1)
  | BAnd b1 b2  => andb (beval b1) (beval b2)
  end.
Example test_aeval1:
  aeval <{ true && (1 < 3) }> = true.
Proof. reflexivity. Qed.

State

Functional programs transform terms into values

fact n = if n=0 then 1 else n * (fact n-1)

but not much code is written functionally


Imperative programs transform state

<{ Z := X;
   Y := 1;
   while Z <> 0 do
     Y := Y × Z;
     Z := Z - 1
   end }>

The only reason for [state] is so that everything does not happen at once Buckaroo Banzai


Programs as State Transformation Systems

Date: 2026-01-22


Programs as State Transformation Systems (cont)

<{ Z := X; <st = ??>
   Y := 1; <st = ??>
   while Z <> 0 do 
     Y := Y × Z; <st = ??>
     Z := Z - 1  <st = ??>
   end }> <st = ??>

Total Maps - Representing State

Model maps as a function from string to some type A

Definition total_map (A:Type) := string -> A.`

Empty Maps

An empty map returns the same default value for all inputs.

Definition t_empty {A:Type} (v : A) : total_map A := (fun _ => v)

Nonempty Maps

Update a map by updating its function

Definition t_update {A:Type} (m : total_map A) (x : string) (v : A) :=
  fun x' => if String.eqb x x' then v else (m x').

Map Access

Just call the map as a function to access a value

(m x)

Program State as Map

Program state is a total map over nat

Initial state is the empty map over 0

Update state with t_update

Access with function call


Theorems and Notations

Rocq provides some nifty notations:

Mathematically $(x \mapsto v);m$ or $(x,v);m$


States as Maps

Examples Usage


Switch to Rocq and prove some theorems over total maps

Watch for:

2026-01-27


Now ceval for commands

Fixpoint ceval (st : state) (c : com) : state :=
  match c with
    | <{ skip }> =>
        st
    | <{ x := a }> =>
        (x !-> aeval st a ; st)
    | <{ c1 ; c2 }> =>
        let st' := ceval st c1 in
        ceval st' c2
    | <{ if b then c1 else c2 end}> =>
        if (beval st b)
          then ceval st c1
          else ceval st c2
    | <{ while b do cb end }> =>
        if (beval st b)
           then st
           else (ceval (ceval st cb) c)
  end.

Yay

In st we execute c resulting in st'


Not Yay


Calling ceval on this program terminates

<{ Z := X;
   Y := 1;
   while Z <> 0 do
     Y := Y * Z;
     Z := Z - 1
   end }>

But this one does not

<{ Z := X;
   Y := 1;
   while Z <> 0 do
     Y := Y * Z;
     Z := Z + 1
   end }>

Evaluating while Badly

    | <{ while b do cb end }> =>
        if (beval st b)
        then st
        else (ceval (ceval st cb) c)

Make ceval Terminate

Fixpoint ceval (fuel: nat) (st : state) (c : com) : state :=
  match fuel with
  | 0 => empty
  | succ fuel' =>
      match c with
        | <{ skip }> =>
            st
        | <{ x := a }> =>
            (x !-> aeval fuel st a ; st)
        | <{ c1 ; c2 }> =>
            let st' := ceval fuel' st c1 in
              ceval fuel' st' c2
        | <{ if b then c1 else c2 end}> =>
            if (beval st b) then ceval fuel' st c1
              else ceval fuel' st c2
        | <{ while b do cb end }> =>
            if (beval st b) then st
              else (ceval fuel' (ceval fuel' st cb) c)
  end
end.

Fuel


Relations


Relations in Math

\[R\subseteq\{(x,y)\mid x\in X\wedge y\in Y\}\] \[\aevalR\subseteq \{(t,v)\mid t\in terms\wedge v\in values\}\]

Definition Examples

Three ways of saying “given A and B we know C

$\frac{A,B}{C}$ - Tree style

$A,B \vdash C$ - Flat style

A -> B -> C - Rocq style


Properties of Relations

2026-01-27


Evaluation Relation Examples

forall v, aevalR(ANum(v),v)
forall t1 t2 v1 v2, aevalR(t1,v1) -> aevalR(t2,v2) -> aevalR(t1+t2,v1+v2)
forall t1 t2 v1 v2, aevalR(t1,v1) -> aevalR(t2,v2) -> bevalR(t1=t2,v1=?v2)
forall t1 t2 v1 v2,
  bevalR(t1,v1) -> bevalR(t2,v2) -> bevalR(t1 && t2,(andb v1 v2))
forall c1 c2 st st' st'',
  cevalR(st,c1,st') -> cevalR(st',c2,st'') -> cevalR(st,c1;c2,st'')

Inductive Propositions in Rocq

Inductive aevalR: aexp -> nat -> Prop :=
| aevalNum : forall v : nat, (aevalR (ANum v) v) -> True
| aevalPlus : forall t1 t2 v1 v2,
    (aevalR t1 v1) -> (aevalR t2 v2) -> (aevalR (APlus t1 t2) (v1+v2)) -> True
| aevalTimes : forall t1 t2 v1 v2,
    (aevalR t1 v1) -> (aevalR t2 v2) -> (aevalR (AMult t1 t2) (v1*v2)) -> True
| aevalMinus : forall t1 t2 v1 v2,
    (aevalR t1 v1) -> (aevalR t2 v2) -> v1 <= v2 -> (aevalR (AMinus t1 t2) (v1-v2)) -> True.


Inductive Propositions in Rocq (cont)

Inductive aevalR: aexp -> nat -> Prop :=
| aevalNum : forall v : nat, (aevalR (ANum v) v)
| aevalPlus : forall t1 t2 v1 v2,
    (aevalR t1 v1) -> (aevalR t2 v2) -> (aevalR (APlus t1 t2) (v1+v2))
| aevalTimes : forall t1 t2 v1 v2,
    (aevalR t1 v1) -> (aevalR t2 v2) -> (aevalR (AMult t1 t2) (v1*v2))
| aevalMinus : forall t1 t2 v1 v2,
    (aevalR t1 v1) -> (aevalR t2 v2) -> v1 <= v2 -> (aevalR (AMinus t1 t2) (v1-v2)).

Reasoning With Apply


Reasoning with Inversion


Adding State to aeval

Fixpoint aeval (st : state) (* <--- NEW *)
               (a : aexp) : nat :=
  match a with
  | ANum n => n
  | AId x => st x                                (* <--- NEW *)
  | <{a1 + a2}> => (aeval st a1) + (aeval st a2)
  | <{a1 - a2}> => (aeval st a1) - (aeval st a2)
  | <{a1 * a2}> => (aeval st a1) * (aeval st a2)
  end.

Example aeval State

Definition init := (t_empty 0).
Definition st := (t_update init "X" 3).

Example ex4: aeval st (AId X) = 3.
Proof.

Adding State to aevalR

Inductive aevalR: state -> aexp -> nat -> Prop :=
| aevalNum : forall st : state, v : nat, (aevalR st (ANum v) v)
| aevalId : forall st : state, x : string, (aevalR st (AId x) (st x))
| aevalPlus : forall st t1 t2 v1 v2,
    (aevalR st t1 v1) -> (aevalR st t2 v2) -> (aevalR st (APlus t1 t2) (v1+v2))
| aevalTimes : forall st t1 t2 v1 v2,
    (aevalR st t1 v1) -> (aevalR st t2 v2) -> (aevalR st (AMult t1 t2) (v1*v2))
| aevalMinus : forall st t1 t2 v1 v2,
    (aevalR st t1 v1) -> (aevalR st t2 v2) -> v1 <= v2 -> (aevalR (AMinus st t1
    t2) (v1-v2)).

Example aevalR and aeval with State

Switch to Rocq


Let’s Try com

Inductive com : Type :=
  | CSkip
  | CAsgn (x : string) (a : aexp)
  | CSeq (c1 c2 : com)
  | CIf (b : bexp) (c1 c2 : com)
  | CWhile (b : bexp) (c : com).
ceval : s -> com -> s'
st=[c]=>st'

Rocq Notation

ceval st c st'  == st=[c]=>st'

Skip

-----------
st =[SKIP]=> st

Assign

    aevalR st t v
-------------------------
st =[ x:=t ]=> (x|->v);st

Sequence

        st =[c1]=> st'
       st' =[c2]=> st''
--------------------------------
      st =[c1;c2]=> st''

If

        bevalR b true
        st =[c1]=> st'
--------------------------------
st =[if b then c1 else c2]=> st'

        bevalR b false
        st =[c2]=> st'
--------------------------------
st =[if b then c1 else c2]=> st'

While True

         bevalR b true
         st =[c]=> st'
st' =[ while b do c end ]=> st''
--------------------------------
   st =[while b do c end]=> st''

While False

    bevalR b false
-----------------------
st =[while b do c end]=> st

Some Thoughts on ceval


Behavioral Equivalence

“And if she weighs the same as a duck… she’s made of wood… and therefore… A WITCH!”. ~ Sir Bedevere from Monty Python and the Holy Grail


Behavioral Equivalence of Programs

Why?


Some Definitions of Equivalence

Definition aequiv p1 p2 : aexp :=
  forall st : state, aexp st p1 = aexp st p2.
Definition cequiv (c1 c2 : com) : Prop :=
   (st st' : state),
    (st =[ c1 ]=> st') <-> (st =[ c2 ]=> st').

Examples from Pierce

Theorem skip_left :  c,
  cequiv
    <{ skip; c }>
    c.

Examples from Pierce (2)

Theorem skip_left :  c,
  cequiv
    <{ skip; c }>
    c.
Proof.
  (* WORKED IN CLASS *)
  intros c st st'.
  split; intros H.
  - (* -> *)
    inversion H. subst.
    inversion H2. subst.
    assumption.
  - (* <- *)
    apply E_Seq with st.
    + apply E_Skip.
    + assumption.
Qed.

Examples from Pierce (3)

Theorem skip_right : forall c,
  cequiv
    <{ c; skip }>
    c.

Examples from Pierce (4)

Theorem skip_right : forall c,
  cequiv
    <{ c; skip }>
    c.
Proof.
  intros c st st'.
  split; intros H.
  - inversion H. subst.
    inversion H5. subst.
    assumption.
  - apply E_Seq with st'.
    assumption.
    apply E_Skip.
Qed.
Ltac H := inversion H; subst; remove H.

IF Optimization

Theorem if_true_simple : forall c1 c2,
  cequiv
    <{ if true then c1 else c2 end }>
    c1.

A Stronger if Optimization

Theorem if_true:  b c1 c2,
  bequiv b <{true}> 
  cequiv
    <{ if b then c1 else c2 end }>
    c1.

With the Proof

Theorem if_true:  b c1 c2,
  bequiv b <{true}> 
  cequiv
    <{ if b then c1 else c2 end }>
    c1.
Proof.
  intros b c1 c2 Hb.
  split; intros H.
  - (* -> *)
    inversion H; subst.
    + (* b evaluates to true *)
      assumption.
    + (* b evaluates to false (contradiction) *)
      unfold bequiv in Hb. simpl in Hb.
      rewrite Hb in H5.
      discriminate.
  - (* <- *)
    apply E_IfTrue; try assumption.
    unfold bequiv in Hb. simpl in Hb.
    apply Hb. Qed.

And The Other Way

Theorem if_false :  b c1 c2,
  bequiv b <{false}> 
  cequiv
    <{ if b then c1 else c2 end }>
    c2.

With The Proof

Theorem if_false : forall b c1 c2,
  bequiv b <{false}> ->
  cequiv
    <{ if b then c1 else c2 end }>
    c2.
Proof.
  intros b c1 c2. intros Hb.
  split; intros H.
  - inversion H; subst.
  -- unfold bequiv in Hb. simpl in Hb.
     rewrite Hb in H5.
     inversion H5.
  -- assumption.
  - apply E_IfFalse.
  -- unfold bequiv in Hb. simpl in Hb.
     apply Hb.
  -- assumption.
  Qed.

Flip if Cases

Theorem swap_if_branches : forall b c1 c2,

Flip if Cases (theorem)

Theorem swap_if_branches : forall b c1 c2,
  cequiv
    <{ if b   then c1 else c2 end }>
    <{ if ~ b then c2 else c1 end }>.

Flip if Cases (with the proof)

Theorem swap_if_branches : forall b c1 c2,
  cequiv
    <{ if b   then c1 else c2 end }>
    <{ if ~ b then c2 else c1 end }>.

Properties of while


while false

<{while false do c end}>

while and Non-termination

<{while true do c end}>

Unfolding while

Theorem loop_unrolling : forall b c,

Unfolding while Theorem

Theorem loop_unrolling : forall b c,
  cequiv
    <{ while b do c end }>
    <{ if b then c ; while b do c end else skip end }>.

Properties of Program Equivalence


Program Equivalence is Equivalence


Program Equivalence as Congruence

                aequiv a a'
         -------------------------
         cequiv (x := a) (x := a')

              cequiv c1 c1'
              cequiv c2 c2'
         --------------------------
         cequiv (c1;c2) (c1';c2')

Program Assertions

Definition Assertion := state -> Prop.

Examples

Definition assertion1 : Assertion := fun st  st X  st Y.
Definition assertion2 : Assertion :=
  fun st  st X = 3  st X  st Y.
Definition assertion3 : Assertion :=
  fun st  st Z × st Z  st X 
            ¬ (((S (st Z)) × (S (st Z)))  st X).
Definition assertion4 : Assertion :=
  fun st  st Z = max (st X) (st Y).

Notations for Assertions

fun st => st X = m


Example Assertions

Definition assertion1 : Assertion := .
Definition assertion2 : Assertion := .
Definition assertion3 : Assertion := .
Definition assertion4 : Assertion := .
Definition assertion5 : Assertion := .
Definition assertion6 : Assertion := .
Definition assertion7 : Assertion := .
Definition assertion8 : Assertion := .
Definition assertion9 : Assertion := .

Assertion Implication

Definition assert_implies (P Q : Assertion) : Prop := forall st, P st -> Q st.
P ->> Q
P <<->> Q == P ->> Q /\ Q ->> P

Hoare Triples

{P} c {Q}
 c 

m and M

 X := X + 1 
forall m,  X := X + 1 

Hoare Examples

 c 

forall m,  c 

 c 

 c 

forall m,  c 

forall m,  c 

Valid or Not Valid

 X := 5 

 X := X + 1 

 X := 5; Y := 0 

 X := 5 

 skip 

 skip 

 while true do skip end 


  while X = 0 do X := X + 1 end



  while X  0 do X := X + 1 end


Hoare Triples Defined


Hoare Triples Defined (2)

forall st st',
  P st ->
  st =[ c ]=> st' ->
  Q st'

Hoare Triples Defined (3)

Definition valid_hoare_triple
  (P : Assertion) (c : com) (Q : Assertion) : Prop :=
    forall st st',
      st =[ c ]=> st' ->
      P st ->
      Q st'.
 c 

First Hoare Triple Theorems

Theorem hoare_post_true : forall (P Q : Assertion) c,
  (forall st, Q st) ->
   c .
Theorem hoare_post_false : forall (P Q : Assertion) c,
  (forall st, not (P st)) ->
   c .

Hoare Proof Rules


SKIP

-------------------- [hoare_SKIP]
 SKIP 
Theorem hoare_skip : forall P,
      skip .

Sequence Rule

  c2 
  c1 
-----------------
 c1;c2 

Assignment


Assignment (2)

 X := Y 

Assignment (3)

Y = 1
 X:=Y 

Assignment (4)

Y=1


Assignment (5)

 X:=X+Y 
 X:=X+Y 

Assignment General Rule

 X := a 
 X := a 

Seems kind of backwards. We’ll see forwards later, and you won’t like it


Examples from PLF

        (X + 1 <= 5)
  X := X + 1


            (3 = 3)
  X := 3


    (0 <= 3 /\ 3 <= 5)
  X := 3
0

Assertion Substitution


Assertion Substitution as Environment

Definition assertion_sub X (a:aexp) (P:Assertion) : Assertion :=
  fun (st : state) =>
    (P%_assertion) (X !-> ((a:Aexp) st); st).

Checking a Simple Precondition

(X <= 5) [X !-> 3]
==
fun st =>
  (fun st' => st' X <= 5)
  (X !-> aeval st 3 ; st),
==
fun st =>
  (fun st' => st' X <= 5)
  (X !-> 3 ; st)
==
fun st =>
  ((X !-> 3 ; st) X) <= 5
==
fun st =>
  3 <= 5.

Bounce over to Rocq for a couple of examples


Rule of Consequence


Aside About Weaker/Stronger


Example

 X := 3 ,
 X := 3 

Example Equivalence Rule

                 c 
                  P <<->> P'
             ---------------------
                 c 

Rules of Consequence

                 c 
                   P ->> P'
         -----------------------------   (hoare_consequence_pre)
                 c 
                 c 
                  Q' ->> Q
         -----------------------------    (hoare_consequence_post)
                 c 

Formal Rules of Consequence

Theorem hoare_consequence_pre : forall (P P' Q : Assertion) c,
   c  ->
  P ->> P' ->
   c .
Theorem hoare_consequence_post : forall (P Q Q' : Assertion) c,
   c  ->
  Q' ->> Q ->
   c .

Combined Rule of Consequence

                 c 
                   P ->> P'
                   Q' ->> Q
         -----------------------------   (hoare_consequence)
                 c 
Theorem hoare_consequence : forall (P P' Q Q' : Assertion) c,
   c  ->
  P ->> P' ->
  Q' ->> Q ->
   c .

Proof Automation

Proof search attempts to build a proof automatically


auto and lia


Motivating Example


apply and Specific Rules

Example auto_example_1 : forall (P Q R: Prop),
  (P -> Q) -> (Q -> R) -> P -> R.
Proof.
  intros P Q R H1 H2 H3.
  apply H2. apply H1. assumption.
Qed.

auto and Databases

Example auto_example_1' : forall (P Q R: Prop),
  (P -> Q) -> (Q -> R) -> P -> R.
Proof.
  auto.
Qed.

Example auto_example_2 : forall P Q R S T U : Prop,
  (P -> Q) ->
  (P -> R) ->
  (T -> R) ->
  (S -> T -> U) ->
  ((P -> Q) -> (P -> S)) ->
  T ->
  P ->
  U.
Proof. auto. Qed.

Adding Lemmas to auto

auto using lemma_name.

Limiting Depth

Example auto_example_3 : forall (P Q R S T U: Prop),
  (P -> Q) ->
  (Q -> R) ->
  (R -> S) ->
  (S -> T) ->
  (T -> U) ->
  P ->
  U.
Proof.

Examples with auto


Building a Hint Database

Hint Resolve T : core

Hint Database Shorthands

Hint Constructors c : core.
Hint Unfold d : core.
Hint Transparent d: core.

Example ceval_deterministic Again


Ltac


An Ltac Function

Ltac rwd H1 H2 := rewrite H1 in H2; discriminate

Goal Matching

Ltac find_rwd :=
  match goal with
    H1: ?E = true, H2: ?E = false |- _
       =>
    rwd H1 H2
  end.

Ltac find_rwd :=
  match goal with
    H1: ?E = true, H2: ?E = false |- _
       =>
    rwd H1 H2
  end.

find_eqn

Ltac find_eqn :=
  match goal with
    H1: forall x, ?P x -> ?L = ?R,
    H2: ?P ?X
    |- _
    => rewrite (H1 X H2) in *
  end.

Existential or Meta Variables

 X := 1 ; Y := 2 

A Sequence Example

Example ceval_example1:
  empty_st =[
    X := 2;
    if (X <= 1)
      then Y := 3
      else Z := 4
    end
  ]=> (Z !-> 4 ; X !-> 2).
Proof.
  apply E_Seq with (X !-> 2).
  - apply E_Asgn. reflexivity.
  - apply E_IfFalse. reflexivity. apply E_Asgn. reflexivity.
Qed.

Sequence Subgoals

empty_st =[X:=2]=> (X !-> 2)
(X !-> 2) =[if command]=> (Z!->4;X!->2)

A Sequence Example (2)

st =[c1]=> st' ->
st' =[c2]=> st'' ->
st =[c1;c2]=> st'' 

eapply

Example ceval'_example1:
  empty_st =[
    X := 2;
    if (X <= 1)
      then Y := 3
      else Z := 4
    end
  ]=> (Z !-> 4 ; X !-> 2).
Proof.
  (* 1 *) eapply E_Seq.
  - (* 2 *) apply E_Asgn.
    (* 3 *) reflexivity.
  - (* 4 *) apply E_IfFalse. reflexivity. apply E_Asgn. reflexivity.
Qed.

?X

empty_st =[X:=2]=> ?X

?X =[if command]=> (Z!->4;X!->2)
(X!->2) ; empty_st == (X!->2)
empty_st =[X:=2]=> (X!->2)

(X!->2) =[if command]=> (Z!->4;X!->2)

The e Commands

Start with eapply and work from there