Lecture notes 20190319
First Order Logic 2
Remark. Some material in this lecture is from << Software Foundation >>
volume 1 and volume 2.
Require Import PL.Imp5.
Falsehood and Negation
Module MyNot.
Definition not (P:Prop) := P → False.
Notation "¬x" := (not x) : type_scope.
Check not.
(* ===> Prop -> Prop *)
End MyNot.
Theorem ex_falso_quodlibet : ∀(P:Prop),
False → P.
Proof.
(* WORKED IN CLASS *)
intros P contra.
destruct contra. Qed.
Definition not (P:Prop) := P → False.
Notation "¬x" := (not x) : type_scope.
Check not.
(* ===> Prop -> Prop *)
End MyNot.
Theorem ex_falso_quodlibet : ∀(P:Prop),
False → P.
Proof.
(* WORKED IN CLASS *)
intros P contra.
destruct contra. Qed.
The Latin ex falso quodlibet means, literally, "from falsehood
follows whatever you like"; this is another common name for the
principle of explosion.
It takes a little practice to get used to working with negation in
Coq. Even though you can see perfectly well why a statement
involving negation is true, it can be a little tricky at first to
get things into the right configuration so that Coq can understand
it! Here are proofs of a few familiar facts to get you warmed
up.
Theorem not_False :
¬False.
Proof.
unfold not. intros H. destruct H. Qed.
Theorem contradiction_implies_anything : ∀P Q : Prop,
(P ∧ ¬P) → Q.
Proof.
(* WORKED IN CLASS *)
intros P Q [HP HNA]. unfold not in HNA.
apply HNA in HP. destruct HP. Qed.
Theorem double_neg_intro : ∀P : Prop,
P → ~~P.
Proof.
(* WORKED IN CLASS *)
intros P H. unfold not. intros G. apply G. apply H. Qed.
¬False.
Proof.
unfold not. intros H. destruct H. Qed.
Theorem contradiction_implies_anything : ∀P Q : Prop,
(P ∧ ¬P) → Q.
Proof.
(* WORKED IN CLASS *)
intros P Q [HP HNA]. unfold not in HNA.
apply HNA in HP. destruct HP. Qed.
Theorem double_neg_intro : ∀P : Prop,
P → ~~P.
Proof.
(* WORKED IN CLASS *)
intros P H. unfold not. intros G. apply G. apply H. Qed.
The following theorem is one of four De Morgan laws.
Theorem or_not_and: ∀P Q : Prop, ¬P ∨ ¬Q → ¬(P ∧ Q).
Proof.
(* WORKED IN CLASS *)
intros.
unfold not.
intros.
destruct H0.
destruct H.
+ unfold not in H.
apply H.
exact H0.
+ unfold not in H.
apply H.
exact H1.
Qed.
Proof.
(* WORKED IN CLASS *)
intros.
unfold not.
intros.
destruct H0.
destruct H.
+ unfold not in H.
apply H.
exact H0.
+ unfold not in H.
apply H.
exact H1.
Qed.
Besides the fact that P and ¬P cannot be both true, one of them must be
true. This principle is called law of excluded middle. In logic studies, this
law distinguishes classical logic (经典逻辑) and intuitionistic logic (直觉主义逻辑).
Thus, it is named classic in Coq.
Check classic.
(* : forall P : Prop, P \/ ~ P *)
Theorem double_neg_elim : ∀P : Prop,
~~P → P.
Proof.
intros.
pose proof classic P.
destruct H0.
+ exact H0.
+ unfold not at 1 in H.
pose proof H H0.
destruct H1.
Qed.
Theorem not_and_or: ∀P Q : Prop, ¬(P ∧ Q) → ¬P ∨ ¬Q.
Proof.
intros.
pose proof classic P.
destruct H0.
+ pose proof classic Q.
destruct H1.
- assert (P ∧ Q).
{
split.
+ exact H0.
+ exact H1.
}
unfold not in H.
pose proof H H2.
destruct H3.
- right.
exact H1.
+ left.
exact H0.
Qed.
(* : forall P : Prop, P \/ ~ P *)
Theorem double_neg_elim : ∀P : Prop,
~~P → P.
Proof.
intros.
pose proof classic P.
destruct H0.
+ exact H0.
+ unfold not at 1 in H.
pose proof H H0.
destruct H1.
Qed.
Theorem not_and_or: ∀P Q : Prop, ¬(P ∧ Q) → ¬P ∨ ¬Q.
Proof.
intros.
pose proof classic P.
destruct H0.
+ pose proof classic Q.
destruct H1.
- assert (P ∧ Q).
{
split.
+ exact H0.
+ exact H1.
}
unfold not in H.
pose proof H H2.
destruct H3.
- right.
exact H1.
+ left.
exact H0.
Qed.
Existential Quantification
Lemma four_is_even : ∃n, 4 = n + n.
Proof.
∃2.
omega.
Qed.
Lemma six_is_not_prime: ∃n, 2 ≤ n < 6 ∧ ∃q, n * q = 6.
Proof.
∃2.
split.
+ omega.
+ ∃3.
omega.
Qed.
Proof.
∃2.
omega.
Qed.
Lemma six_is_not_prime: ∃n, 2 ≤ n < 6 ∧ ∃q, n * q = 6.
Proof.
∃2.
split.
+ omega.
+ ∃3.
omega.
Qed.
Conversely, if we have an existential hypothesis ∃ x, P in Coq, we can destruct it
Theorem exists_example : ∀n,
(∃m, n = 4 + m) →
(∃o, n = 2 + o).
Proof.
(* WORKED IN CLASS *)
intros.
destruct H.
∃(2 + x).
omega.
Qed.
Theorem dist_exists_and : ∀(X:Type) (P Q : X → Prop),
(∃x, P x ∧ Q x) → (∃x, P x) ∧ (∃x, Q x).
Proof.
(* WORKED IN CLASS *)
intros.
destruct H as [x [HP HQ]].
split.
+ ∃x.
exact HP.
+ ∃x.
exact HQ.
Qed.
(∃m, n = 4 + m) →
(∃o, n = 2 + o).
Proof.
(* WORKED IN CLASS *)
intros.
destruct H.
∃(2 + x).
omega.
Qed.
Theorem dist_exists_and : ∀(X:Type) (P Q : X → Prop),
(∃x, P x ∧ Q x) → (∃x, P x) ∧ (∃x, Q x).
Proof.
(* WORKED IN CLASS *)
intros.
destruct H as [x [HP HQ]].
split.
+ ∃x.
exact HP.
+ ∃x.
exact HQ.
Qed.
Notice that the reverse direction of this theorem is not true. For example,
there obviously exists at least one even number and one odd number but there is
not number which is both even and odd.
Module sample_derivation.
Local Instance X: var := new_var().
Fact der: ∀(m n: Z),
0 ≤ m AND [[X]] == m ⊢
EXISTS q, n * q + [[X]] == m AND 0 ≤ [[X]].
Proof.
(* WORKED IN CLASS *)
intros.
entailer.
intros.
∃0.
omega.
Qed.
End sample_derivation.
Local Instance X: var := new_var().
Fact der: ∀(m n: Z),
0 ≤ m AND [[X]] == m ⊢
EXISTS q, n * q + [[X]] == m AND 0 ≤ [[X]].
Proof.
(* WORKED IN CLASS *)
intros.
entailer.
intros.
∃0.
omega.
Qed.
End sample_derivation.
Universal Quantification
Lemma forall_comm: ∀(P: Z → Z → Prop),
(∀x y, P x y) →
(∀y x, P x y).
Proof.
intros.
apply H.
Qed.
Lemma forall_example1: ∀(P Q: Z → Z → Prop),
P 0 1 →
(∀x y, P x y → Q x y) →
Q 0 1.
Proof.
intros.
pose proof H0 0 1 H.
exact H1.
Qed.
Lemma forall_example2: ∀(P Q: Z → Z → Prop),
P 0 1 →
(∀x y, P x y → Q x y) →
Q 0 1.
Proof.
intros.
specialize (H0 0 1 H).
exact H0.
Qed.
Lemma forall_example3: ∀(P Q: Z → Z → Prop),
P 0 1 →
(∀x y, P x y → Q x y) →
Q 0 1.
Proof.
intros.
apply H0.
exact H.
Qed.
Lemma forall_example4: ∀(P Q: Z → Z → Prop),
P 0 1 →
(∀x y, P x y → Q x y) →
Q 0 1.
Proof.
intros.
apply H0 in H.
exact H.
Qed.
(∀x y, P x y) →
(∀y x, P x y).
Proof.
intros.
apply H.
Qed.
Lemma forall_example1: ∀(P Q: Z → Z → Prop),
P 0 1 →
(∀x y, P x y → Q x y) →
Q 0 1.
Proof.
intros.
pose proof H0 0 1 H.
exact H1.
Qed.
Lemma forall_example2: ∀(P Q: Z → Z → Prop),
P 0 1 →
(∀x y, P x y → Q x y) →
Q 0 1.
Proof.
intros.
specialize (H0 0 1 H).
exact H0.
Qed.
Lemma forall_example3: ∀(P Q: Z → Z → Prop),
P 0 1 →
(∀x y, P x y → Q x y) →
Q 0 1.
Proof.
intros.
apply H0.
exact H.
Qed.
Lemma forall_example4: ∀(P Q: Z → Z → Prop),
P 0 1 →
(∀x y, P x y → Q x y) →
Q 0 1.
Proof.
intros.
apply H0 in H.
exact H.
Qed.
Exercise: 1 star, standard (dist_not_exists)
Prove that "P holds for all x" implies "there is no x for which P does not hold." (Hint: destruct H as [x E] works on existential assumptions!)
Theorem dist_not_exists : ∀(X:Type) (P : X → Prop),
(∀x, P x) → ¬(∃x, ¬P x).
Proof.
(* FILL IN HERE *) Admitted.
☐
(∀x, P x) → ¬(∃x, ¬P x).
Proof.
(* FILL IN HERE *) Admitted.
First Order Logic for Assertion Derivation
Check AND_left1.
(* : forall P Q R : Assertion,
P ⊢ R -> P AND Q ⊢ R *)
Check AND_left2.
(* : forall P Q R : Assertion,
Q ⊢ R -> P AND Q ⊢ R *)
Check AND_right.
(* : forall P Q R : Assertion,
P ⊢ Q -> P ⊢ R -> P ⊢ Q AND R *)
Check OR_left.
(* : forall P Q R : Assertion,
P ⊢ R -> Q ⊢ R -> P OR Q ⊢ R *)
Check OR_right1.
(* : forall P Q R : Assertion,
P ⊢ Q -> P ⊢ Q OR R *)
Check OR_right2.
(* : forall P Q R : Assertion,
P ⊢ R -> P ⊢ Q OR R *)
Check CONTRA.
(* : forall P Q : Assertion, P AND NOT P ⊢ Q *)
Check LEM.
(* : forall P Q : Assertion, P ⊢ Q OR NOT Q *)
Check True_right.
(* : forall P : Assertion, P ⊢ True *)
Check False_left.
(* : forall P : Assertion, False ⊢ P *)
Check EXISTS_left.
(* : forall P (Q : Assertion),
(forall x : Z, P x ⊢ Q) ->
EXISTS x, P x ⊢ Q *)
Check EXISTS_right.
(* : forall (P : Assertion) Q (x : Z),
P ⊢ Q x -> P ⊢ EXISTS x, Q x *)
Check FORALL_left.
(* : forall P (Q : Assertion) (x : Z),
P x ⊢ Q -> FORALL x0, P x0 ⊢ Q *)
Check FORALL_right.
(* : forall (P : Assertion) Q,
(forall x : Z, P ⊢ Q x) ->
P ⊢ FORALL x, Q x *)
Check derives_refl.
(* : forall P : Assertion, P ⊢ P *)
Check derives_trans.
(* : forall P Q R : Assertion,
P ⊢ Q -> Q ⊢ R -> P ⊢ R *)
Module min_if.
Import Axiomatic_semantics.
Local Instance A: var := new_var().
Local Instance B: var := new_var().
Local Instance C: var := new_var().
(* : forall P Q R : Assertion,
P ⊢ R -> P AND Q ⊢ R *)
Check AND_left2.
(* : forall P Q R : Assertion,
Q ⊢ R -> P AND Q ⊢ R *)
Check AND_right.
(* : forall P Q R : Assertion,
P ⊢ Q -> P ⊢ R -> P ⊢ Q AND R *)
Check OR_left.
(* : forall P Q R : Assertion,
P ⊢ R -> Q ⊢ R -> P OR Q ⊢ R *)
Check OR_right1.
(* : forall P Q R : Assertion,
P ⊢ Q -> P ⊢ Q OR R *)
Check OR_right2.
(* : forall P Q R : Assertion,
P ⊢ R -> P ⊢ Q OR R *)
Check CONTRA.
(* : forall P Q : Assertion, P AND NOT P ⊢ Q *)
Check LEM.
(* : forall P Q : Assertion, P ⊢ Q OR NOT Q *)
Check True_right.
(* : forall P : Assertion, P ⊢ True *)
Check False_left.
(* : forall P : Assertion, False ⊢ P *)
Check EXISTS_left.
(* : forall P (Q : Assertion),
(forall x : Z, P x ⊢ Q) ->
EXISTS x, P x ⊢ Q *)
Check EXISTS_right.
(* : forall (P : Assertion) Q (x : Z),
P ⊢ Q x -> P ⊢ EXISTS x, Q x *)
Check FORALL_left.
(* : forall P (Q : Assertion) (x : Z),
P x ⊢ Q -> FORALL x0, P x0 ⊢ Q *)
Check FORALL_right.
(* : forall (P : Assertion) Q,
(forall x : Z, P ⊢ Q x) ->
P ⊢ FORALL x, Q x *)
Check derives_refl.
(* : forall P : Assertion, P ⊢ P *)
Check derives_trans.
(* : forall P Q R : Assertion,
P ⊢ Q -> Q ⊢ R -> P ⊢ R *)
Module min_if.
Import Axiomatic_semantics.
Local Instance A: var := new_var().
Local Instance B: var := new_var().
Local Instance C: var := new_var().
Here is the decorated program for min_if:
And here is part of derivation needed in proof:
/* [[A]] == a AND [[B]] == b */
If A ≤ B
Then
/* [[A]] == a AND [[B]] == b AND [[A ≤ B]] */
/* [[A]] == a AND a ≤ b */
C ::= A
/* EXISTS c, [[A]] == a AND a ≤ b AND [[C]] == [[A]] */
/* [[A]] == a AND a ≤ b AND [[C]] == [[A]] */
/* [[C]] == a AND a ≤ b OR [[C]] == b AND b < a */
Else
/* [[A]] == a AND [[B]] == b AND NOT [[A ≤ B]] */
/* [[B]] == b AND b < a */
C ::= B
/* EXISTS c, [[B]] == b AND b < a AND [[C]] == [[B]] */
/* [[B]] == b AND b < a AND [[C]] == [[B]] */
/* [[C]] == a AND a ≤ b OR [[C]] == b AND b < a */
EndIf
/* [[C]] == a AND a ≤ b OR [[C]] == b AND b < a */.
If A ≤ B
Then
/* [[A]] == a AND [[B]] == b AND [[A ≤ B]] */
/* [[A]] == a AND a ≤ b */
C ::= A
/* EXISTS c, [[A]] == a AND a ≤ b AND [[C]] == [[A]] */
/* [[A]] == a AND a ≤ b AND [[C]] == [[A]] */
/* [[C]] == a AND a ≤ b OR [[C]] == b AND b < a */
Else
/* [[A]] == a AND [[B]] == b AND NOT [[A ≤ B]] */
/* [[B]] == b AND b < a */
C ::= B
/* EXISTS c, [[B]] == b AND b < a AND [[C]] == [[B]] */
/* [[B]] == b AND b < a AND [[C]] == [[B]] */
/* [[C]] == a AND a ≤ b OR [[C]] == b AND b < a */
EndIf
/* [[C]] == a AND a ≤ b OR [[C]] == b AND b < a */.
Fact der1_2: ∀a b: Z,
[[A]] == a AND a ≤ b AND [[C]] == [[A]] ⊢
[[C]] == a AND a ≤ b OR [[C]] == b AND b < a.
Proof.
intros.
[[A]] == a AND a ≤ b AND [[C]] == [[A]] ⊢
[[C]] == a AND a ≤ b OR [[C]] == b AND b < a.
Proof.
intros.
As mentioned before, we can use entailer to reduce this proof goal.
entailer.
intros.
omega.
Qed.
Fact der1_2': ∀a b: Z,
[[A]] == a AND a ≤ b AND [[C]] == [[A]] ⊢
[[C]] == a AND a ≤ b OR [[C]] == b AND b < a.
Proof.
intros.
intros.
omega.
Qed.
Fact der1_2': ∀a b: Z,
[[A]] == a AND a ≤ b AND [[C]] == [[A]] ⊢
[[C]] == a AND a ≤ b OR [[C]] == b AND b < a.
Proof.
intros.
But we can also choose to apply some first order logic proof before calling
entailer.
apply OR_right1.
entailer.
intros.
omega.
Qed.
Fact der1_2'': ∀a b: Z,
[[A]] == a AND a ≤ b AND [[C]] == [[A]] ⊢
[[C]] == a AND a ≤ b OR [[C]] == b AND b < a.
Proof.
intros.
apply OR_right1.
apply AND_right.
+ entailer.
intros.
omega.
+ apply AND_left1.
apply AND_left2.
apply derives_refl.
Qed.
End min_if.
Module slow_div.
Local Instance X: var := new_var().
Local Instance Y: var := new_var().
Lemma derivation1: ∀m n: Z,
0 ≤ m AND [[X]] == m AND [[Y]] == 0 ⊢
n * [[Y]] + [[X]] == m AND 0 ≤ [[X]].
Proof.
intros.
entailer.
intros.
destruct H.
rewrite H0.
omega.
Qed.
Lemma derivation2: ∀m n: Z,
EXISTS z, n * [[Y]] + z == m AND 0 ≤ z AND n ≤ z AND [[X]] == z - n ⊢
n * [[Y]] + [[X]] + n == m AND 0 ≤ [[X]].
Proof.
intros.
apply EXISTS_left.
intros.
entailer.
intros.
omega.
Qed.
Lemma derivation3: ∀m n: Z,
EXISTS z, n * z + [[X]] + n == m AND 0 ≤ [[X]] AND [[Y]] == z + 1 ⊢
n * [[Y]] + [[X]] == m AND 0 ≤ [[X]].
Proof.
intros.
entailer.
intros.
destruct H as [k [[? ?] ?]].
split.
+ rewrite H1.
Search (_ * (_ + _)).
rewrite Z.mul_add_distr_l.
omega.
+ exact H0.
Qed.
Lemma derivation4: ∀m n: Z,
n * [[Y]] + [[X]] == m AND 0 ≤ [[X]] AND NOT [[n ≤ X]] ⊢
n * [[Y]] + [[X]] == m AND 0 ≤ [[X]] AND [[X]] < n.
Proof.
intros.
apply AND_right.
+ apply AND_left1.
apply derives_refl.
+ apply AND_left2.
entailer.
intros.
omega.
Qed.
End slow_div.
entailer.
intros.
omega.
Qed.
Fact der1_2'': ∀a b: Z,
[[A]] == a AND a ≤ b AND [[C]] == [[A]] ⊢
[[C]] == a AND a ≤ b OR [[C]] == b AND b < a.
Proof.
intros.
apply OR_right1.
apply AND_right.
+ entailer.
intros.
omega.
+ apply AND_left1.
apply AND_left2.
apply derives_refl.
Qed.
End min_if.
Module slow_div.
Local Instance X: var := new_var().
Local Instance Y: var := new_var().
Lemma derivation1: ∀m n: Z,
0 ≤ m AND [[X]] == m AND [[Y]] == 0 ⊢
n * [[Y]] + [[X]] == m AND 0 ≤ [[X]].
Proof.
intros.
entailer.
intros.
destruct H.
rewrite H0.
omega.
Qed.
Lemma derivation2: ∀m n: Z,
EXISTS z, n * [[Y]] + z == m AND 0 ≤ z AND n ≤ z AND [[X]] == z - n ⊢
n * [[Y]] + [[X]] + n == m AND 0 ≤ [[X]].
Proof.
intros.
apply EXISTS_left.
intros.
entailer.
intros.
omega.
Qed.
Lemma derivation3: ∀m n: Z,
EXISTS z, n * z + [[X]] + n == m AND 0 ≤ [[X]] AND [[Y]] == z + 1 ⊢
n * [[Y]] + [[X]] == m AND 0 ≤ [[X]].
Proof.
intros.
entailer.
intros.
destruct H as [k [[? ?] ?]].
split.
+ rewrite H1.
Search (_ * (_ + _)).
rewrite Z.mul_add_distr_l.
omega.
+ exact H0.
Qed.
Lemma derivation4: ∀m n: Z,
n * [[Y]] + [[X]] == m AND 0 ≤ [[X]] AND NOT [[n ≤ X]] ⊢
n * [[Y]] + [[X]] == m AND 0 ≤ [[X]] AND [[X]] < n.
Proof.
intros.
apply AND_right.
+ apply AND_left1.
apply derives_refl.
+ apply AND_left2.
entailer.
intros.
omega.
Qed.
End slow_div.
Derived Proof Rules
Module derived_rules.
Import Axiomatic_semantics.
Corollary hoare_consequence_pre: ∀P P' Q c,
P ⊢ P' →
{{ P' }} c {{ Q }} →
{{ P }} c {{ Q }}.
Import Axiomatic_semantics.
Corollary hoare_consequence_pre: ∀P P' Q c,
P ⊢ P' →
{{ P' }} c {{ Q }} →
{{ P }} c {{ Q }}.
Now, we can derive this rule from hoare_consequence and derives_refl.
Proof.
intros.
eapply hoare_consequence.
+ exact H.
+ exact H0.
+ apply derives_refl.
Qed.
intros.
eapply hoare_consequence.
+ exact H.
+ exact H0.
+ apply derives_refl.
Qed.
Similarly, we have a single-sided consequence rule for postconditions
as well.
Corollary hoare_consequence_post: ∀P Q Q' c,
{{ P }} c {{ Q' }} →
Q' ⊢ Q →
{{ P }} c {{ Q }}.
Proof.
intros.
eapply hoare_consequence.
+ apply derives_refl.
+ exact H.
+ exact H0.
Qed.
{{ P }} c {{ Q' }} →
Q' ⊢ Q →
{{ P }} c {{ Q }}.
Proof.
intros.
eapply hoare_consequence.
+ apply derives_refl.
+ exact H.
+ exact H0.
Qed.
Since we prove these two rules from primary rules, we call them derived
rules (导出规则).
End derived_rules.
Module Denotational_semantics.
We have seen how a Hoare logic (axiomatic semantics) defines the relation
between the possible programs state sets before and after executing a program.
It is convenient for describing useful program specifications and verifying
them. However, it is not obvious how this semantic definition connects with
compiler implementation.
Denotational semantics (指称语义) is another style of semantic definition. It
directly defines program behavior on concrete program state, but as a
trade-off, it does not directly connect with useful program specifications.
Today we will use integer expression evaluation to illustrate the
difference. Remember that the integer expressions of our simple imperative
language have the following grammar:
The following definition says, for a fixed program state st, the value of
expression a is defined recursively on its syntax tree.
a ::= Z
| var
| a + a
| a - a
| a * a
In Hoare logic, we talk about the property that an expressions a's value
should satisfy. In denotational semantics, we directly define expressions'
evaluation result.
| var
| a + a
| a - a
| a * a
Fixpoint aeval (st : state) (a : aexp) : Z :=
match a with
| ANum n ⇒ n
| AId X ⇒ st X
| APlus a1 a2 ⇒ (aeval st a1) + (aeval st a2)
| AMinus a1 a2 ⇒ (aeval st a1) - (aeval st a2)
| AMult a1 a2 ⇒ (aeval st a1) * (aeval st a2)
end.
match a with
| ANum n ⇒ n
| AId X ⇒ st X
| APlus a1 a2 ⇒ (aeval st a1) + (aeval st a2)
| AMinus a1 a2 ⇒ (aeval st a1) - (aeval st a2)
| AMult a1 a2 ⇒ (aeval st a1) * (aeval st a2)
end.
Here
- The keyword Fixpoint means that we defines a recursive function.
- The function aeval defines the evaluation result of integer expressions in our simple imperative programming language.
- The argument announcement st: state says that st is a program state. Here, a program state is defined as a function from program variables to integers.
- The argument announcement a: aexp says that a is an integer expression. We follow <<Software Foundation>>'s tradition to call integer expressions aexp.
- The match expression (Coq expression) defines how this expression (program expression) evaluation is defined for different kind of a.
- ANum n says if a is a constant expression n.
- AId X says if a is a singleton variable X.
- st X says: applying function st on X. Remember, st is a function from program variables to integers.
Fixpoint alength (a : aexp) : Z :=
match a with
| ANum n ⇒ 1
| AId X ⇒ 1
| APlus a1 a2 ⇒ (alength a1) + (alength a2) + 1
| AMinus a1 a2 ⇒ (alength a1) + (alength a2) + 1
| AMult a1 a2 ⇒ (alength a1) + (alength a2) + 1
end.
match a with
| ANum n ⇒ 1
| AId X ⇒ 1
| APlus a1 a2 ⇒ (alength a1) + (alength a2) + 1
| AMinus a1 a2 ⇒ (alength a1) + (alength a2) + 1
| AMult a1 a2 ⇒ (alength a1) + (alength a2) + 1
end.
And the following Coq function defines boolean expressions' evaluation:
Fixpoint beval (st : state) (b : bexp) : Prop :=
match b with
| BTrue ⇒ True
| BFalse ⇒ False
| BEq a1 a2 ⇒ (aeval st a1) = (aeval st a2)
| BLe a1 a2 ⇒ (aeval st a1) ≤ (aeval st a2)
| BNot b1 ⇒ ¬(beval st b1)
| BAnd b1 b2 ⇒ (beval st b1) ∧ (beval st b2)
end.
End Denotational_semantics.
(* Mon Mar 18 16:03:47 UTC 2019 *)
match b with
| BTrue ⇒ True
| BFalse ⇒ False
| BEq a1 a2 ⇒ (aeval st a1) = (aeval st a2)
| BLe a1 a2 ⇒ (aeval st a1) ≤ (aeval st a2)
| BNot b1 ⇒ ¬(beval st b1)
| BAnd b1 b2 ⇒ (beval st b1) ∧ (beval st b2)
end.
End Denotational_semantics.
(* Mon Mar 18 16:03:47 UTC 2019 *)