Module AExp.
Inductive aexp' : Type :=
| ANum : nat -> aexp'
| APlus : aexp' -> aexp' -> aexp'
| AMinus : aexp' -> aexp' -> aexp'
| AMult : aexp' -> aexp' -> aexp'.
Derive (Arbitrary, Show) for aexp'.
Derive (Sized, CanonicalSized) for aexp'.
Derive SizeMonotonic for aexp' using genSaexp'.
Derive SizedMonotonic for aexp'.
Derive SizedCorrect for aexp' using genSaexp' and SizeMonotonicaexp'.
Instance dec_eq_aex (x y : aexp') : Dec (x = y).
constructor; unfold decidable; repeat decide equality. Defined.
(* AEC Reviewer example *)
Inductive aexpEq : aexp' -> aexp' -> Prop :=
| ANumEq : forall n1 n2, n1 = n2 -> aexpEq (ANum n1) (ANum n2).
Instance dec_aexpEq (x y : aexp') : Dec (aexpEq x y).
constructor; unfold decidable. destruct x; destruct y;
try solve [right => H; inversion H; eauto].
destruct ((n = n0)?) eqn:Eq; destruct dec; try solve [inversion Eq].
- left; econstructor; eauto.
- right => H; inversion H; eauto.
Defined.
Conjecture aexpEq_refl : forall x, aexpEq x x.
QuickChick aexpEq_refl.
Derive ArbitrarySizedSuchThat for (fun x => aexpEq x x').
Derive SizedProofEqs for (fun x => aexpEq x x').
Derive SizeMonotonicSuchThatOpt for (fun x => aexpEq x x').
Derive GenSizedSuchThatSizeMonotonicOpt for (fun x => aexpEq x x').
Derive GenSizedSuchThatCorrect for (fun x => aexpEq x x').
Conjecture aexpEq_eq : forall x x', aexpEq x x' -> x = x'.
QuickChick aexpEq_eq.
(* End Reviwer example *)
Inductive bexp' : Type :=
| BTrue : bexp'
| BFalse : bexp'
| BEq : aexp' -> aexp' -> bexp'
| BLe : aexp' -> aexp' -> bexp'
| BNot : bexp' -> bexp'
| BAnd : bexp' -> bexp' -> bexp'.
Derive (Arbitrary, Show) for bexp'.
Derive (Sized, CanonicalSized) for bexp'.
Derive SizeMonotonic for bexp' using genSbexp'.
Derive SizedMonotonic for bexp'.
Derive SizedCorrect for bexp' using genSbexp' and SizeMonotonicbexp'.
Instance dec_eq_bexp (x y : bexp') : Dec (x = y).
constructor; unfold decidable; repeat decide equality. Defined.
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.
Fixpoint beval (b : bexp') : bool :=
match b with
| BTrue       => true
| BFalse      => false
| BEq a1 a2   => beq_nat (aeval a1) (aeval a2)
| BLe a1 a2   => leb (aeval a1) (aeval a2)
| BNot b1     => negb (beval b1)
| BAnd b1 b2  => andb (beval b1) (beval b2)
end.
Fixpoint optimize_0plus (a:aexp') : aexp' :=
match a with
| ANum n =>
ANum n
| APlus (ANum 0) e2 =>
optimize_0plus e2
| APlus e1 e2 =>
APlus (optimize_0plus e1) (optimize_0plus e2)
| AMinus e1 e2 =>
AMinus (optimize_0plus e1) (optimize_0plus e2)
| AMult e1 e2 =>
AMult (optimize_0plus e1) (optimize_0plus e2)
end.
End AExp.

Theorem optimize_0plus_sound: forall a,
aeval (optimize_0plus a) = aeval a.