playground/coq/unfinished/semantic-style.v

399 lines
9.5 KiB
Coq
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

(*
https://github.com/coq-community/semantics/blob/master/little.v
*)
Require Import List String.
Import ListNotations.
(*
ρ: env
e: expr
b: bool
i: instr
ρ := (var, val)::ρ | ∅
e := var | val | e+e (only addition possible)
b := e < e (only < possible. But what about true,false??
i := skip (empty program. Does nothing. noop)
| x:=e (assignment to var)
| i;i
| while b do i done (loop)
All values are nat
*)
Require Import String.
Inductive aexpr : Type :=
| Anum : nat -> aexpr
| Avar : string -> aexpr
| Aplus : aexpr -> aexpr -> aexpr.
Inductive bexpr : Type :=
| Lt : aexpr -> aexpr -> bexpr.
Inductive instr : Type :=
| Skip : instr
| Let : string -> aexpr -> instr
| Seq : instr -> instr -> instr
| While : bexpr -> instr -> instr.
Definition env : Type := list (string * nat).
Inductive aeval : env -> aexpr -> nat -> Prop :=
(* ρ ⊢ n → n *)
| AEnum : forall (en:env) (n:nat),
aeval en (Anum n) n
(* ((var, val)::ρ)(var → val) *)
| AEvar : forall (en:env) (val:nat) (var:string),
aeval ((var,val)::en)%list (Avar var) val (* Found! *)
(* var1 ≠ var2
(ρ(var1 → val1))
(((var2,val2)::ρ)(var2 → val2))
*)
| AEvarOther : forall (en:env) (val1 val2:nat) (var1 var2:string),
var1 <> var2
-> aeval en (Avar var1) val1
-> aeval ((var2,val2)::en)%list (Avar var1) val1 (* Even if we had another variable added to the env. *)
(*
(ρ(e1 → val1))
(ρ(e2 → val2))
(ρ(e1 + e2)(val1 + val2))
*)
| AEplus : forall (en:env) (e1 e2 : aexpr) (val1 val2 : nat),
aeval en e1 val1
-> aeval en e2 val2
-> aeval en (Aplus e1 e2) (val1 + val2).
Inductive beval : env -> bexpr -> bool -> Prop :=
(*
val1 < val2
(ρ(e1 → val1))
(ρ(e2 → val2))
(ρ((e1 < e2) → true))
*)
| BEltLeft : forall (en:env) (val1 val2 : nat) (e1 e2 : aexpr),
(val1 < val2)
-> aeval en e1 val1
-> aeval en e2 val2
-> beval en (Lt e1 e2) true
(*
¬(val1 < val2)
(ρ(e1 → val1))
(ρ(e2 → val2))
(ρ((e1 < e2) → false))
*)
| BEltRight : forall (en:env) (val1 val2 : nat) (e1 e2 : aexpr),
(val2 >= val2)
-> aeval en e1 val1
-> aeval en e2 val2
-> beval en (Lt e1 e2) false.
Inductive envupdate : env -> string -> nat -> env -> Prop :=
(* Update a variable *)
| EnvUpdNew : forall (en:env) (var:string) (val:nat),
envupdate en var val ((var,val)::en)
(* New variable *)
| EnvUpdOld : forall (en1 en2:env) (var1 var2:string) (val1 val2:nat),
envupdate en1 var1 val1 en2
-> var1 <> var2
(* en2 already has var1 *)
-> envupdate ((var2,val2)::en1) var1 val1 ((var2,val2)::en2).
Inductive instrevalBS : env -> instr -> env -> Prop :=
| IEBSSkip : forall (en:env), instrevalBS en Skip en
| IEBSLet : forall (en en':env) (var:string) (val:nat) (ae:aexpr),
aeval en ae val
-> envupdate en var val en'
-> instrevalBS en (Let var ae) en'
(*
-> envupdate en var val en'
-> instrevalBS en (Let var ae) en'
*)
| IEBSSeq : forall (en en1 en2:env) (i1 i2:instr),
(instrevalBS en i1 en1)
-> (instrevalBS en1 i2 en2)
-> instrevalBS en (Seq i1 i2) en2
| IEBSWhileT : forall (en eni enw:env) (i:instr) (be:bexpr),
beval en be true
-> instrevalBS en i eni
-> instrevalBS eni (While be i) enw
-> instrevalBS en (While be i) enw
| IEBSWhileF : forall (en eni enw:env) (i:instr) (be:bexpr),
beval en be false
-> instrevalBS en (While be i) en.
Inductive instrevalSS : env -> instr -> instr -> env -> Prop :=
| IESSLet : forall (en en':env) (var:string) (val:nat) (ae:aexpr),
aeval en ae val
-> envupdate en var val en'
-> instrevalSS en (Let var ae) Skip en'
| IESSSeqOne : forall (en:env) (i:instr),
instrevalSS en (Seq Skip i) i en
(* i1 reduces to i1' and i1' to i2. Then i1 reduces to i2 *)
(* both i1 and i1' result it en'
then both i1;i2 and i1';i2 result in en'
*)
| IESSSeqMany : forall (en en':env) (i1 i1' i2:instr),
instrevalSS en i1 i1' en'
-> instrevalSS en (Seq i1 i2) (Seq i1' i2) en'
(* XXX: Only aexpr can be bound to vars, okay. But how can we say that env doesn't change after a while loop??? *)
| IESSWhileT : forall (en:env) (i:instr) (be:bexpr),
beval en be true
-> instrevalSS en (While be i) (Seq i (While be i)) en
| IESSWhileF : forall (en:env) (i:instr) (be:bexpr),
beval en be false
(* Says that 'give me (While be i), I'll give you skip' *)
-> instrevalSS en (While be i) Skip en.
Fixpoint lookup (en:env) (var:string) : option nat :=
match en with
| []%list => None
| (x::xs)%list =>
let '(var', val') := x in
if (String.eqb var' var) then
Some val'
else
lookup xs var
end.
Definition bind (A B:Type) (x:option A) (f:A->option B) : option B :=
match x with
| None => None
| Some x' => f x'
end.
Arguments bind {A B}.
(* XXX: Evaluate aexpr ?? *)
Fixpoint af (en:env) (ae:aexpr) : option nat :=
match ae with
| Avar var => lookup en var
| Anum n => Some n
| Aplus e1 e2 =>
bind (af en e1)
(fun x =>
bind (af en e2) (fun y => Some(x+y)))
end.
Example en1 : env := [("x"%string, 2)]%list.
Example en2 : env := [("x"%string, 2); ("y"%string, 3)]%list.
Example ae1 : aexpr := (Aplus (Avar "x"%string) (Avar "y"%string)).
Compute (lookup en1 "x"%string). (* Some 2 *)
Compute (lookup en1 "a"%string). (* None *)
Compute (af en1 (Anum 3)).
Compute (af en2 ae1).
Definition bf (en:env) (b:bexpr) : option bool :=
match b with
| Lt e1 e2 =>
bind (af en e1) (fun x =>
bind (af en e2) (fun y => Some (Nat.ltb x y)))
end.
(* Only update existing vars. Won't add new vars to env *)
Fixpoint updatefn (en:env) (var:string) (val:nat) : option env :=
match en with
| []%list => None
| ((var',val')::ens)%list =>
if (string_dec var var') then
Some ((var, val)::ens)%list
else
bind (updatefn ens var val)
(fun x => Some ((var',val')::x)%list)
(*
match (String.eqb var var') with
| true => Some ((var, val)::ens)%list
| false =>
bind (updatefn ens var val)
(fun x => Some ((var',val')::x)%list)
end
*)
end.
Compute en2.
Compute updatefn en2 "y"%string 5.
Check list nat -> Prop.
Check (list nat) -> Prop.
Check list (nat -> Prop).
Inductive assert : Type :=
| AssertBool (b:bexpr)
| AssertNot (a:assert)
| AssertConj (a1 a2:assert)
| AssertPred (s:string) (n:nat).
Inductive condition : Type :=
| Condition (a1 a2 : assert).
Definition eq_O (n:nat) : {n=O}+{n<>O}.
Proof.
case n.
- left.
reflexivity.
- right.
discriminate.
Restart.
case n.
auto.
right.
discriminate.
Qed.
Definition eq_skip (i:instr) : {i=Skip}+{i<>Skip}.
Proof.
case i.
- left.
reflexivity.
- intros.
right.
discriminate.
- intros.
right.
discriminate.
- intros.
right.
discriminate.
Restart.
(* [auto] takes care of the simple goal which needed [left] tactic *)
case i; auto; right; discriminate.
Qed.
Inductive integer : Set :=
| Int (n:nat) : integer.
(*
Goal
forall (var varname:nat),
Int var = Int varname.
Proof.
intros.
discriminate.
*)
Goal
forall (n1 n2:nat),
Int n1 = Int n2 -> n1 = n2.
Proof.
intros.
induction n1.
- .
discriminate.
Lemma aeval_lookup :
forall (en:env) (e:aexpr) (n:nat) (var:string),
aeval en e n
-> e = (Avar var)
-> lookup en var = Some n.
Proof.
intros en e n varname H.
induction H.
- intro H1.
induction en.
+ discriminate.
+ rewrite <- IHen.
discriminate.
- intro H1.
induction en.
+
(*
Fixpoint aeval (en:env) (e:aexpr) : option nat :=
match e with
| Avar var => lookup en var
| Anum n => Some n
| Aplus e1 e2 =>
match (aeval en e1) with
| None => None
| Some val1 =>
match (aeval en e2) with
| None => None
| Some val2 => Some (val1 + val2)
end
end
end.
Definition beval (en:env) (e:bexpr) : option bool :=
match e with
| Lt ae1 ae2 =>
match (aeval en ae1) with
| None => None
| Some val1 =>
match (aeval en ae2) with
| None => None
| Some val2 => Some (Nat.ltb val1 val2)
end
end
end.
Check (lookup []%list "a"%string = Some 3).
Print eq.
Check eq_refl.
Lemma lookup_aeval : forall (en:env) (var:string) (val:nat),
(lookup en var = Some val) -> aeval en (Avar var) val.
Proof.
intros.
apply (AEvar en H).
(match H with
| eqrefl val' => val'
| None => None
end)
).
Qed.
Fixpoint instreval (en:env) (i:instr) : env :=
match i with
| Let var ae =>
let res := (aeval en ae) in
match res with
| None => en
| Some val => ((var,val)::en)%list
end
| Seq i1 i2 =>
let en' := (instreval en i1) in
(instreval en' i2)
| While be i' =>
match (beval en be) with
| None => en
| Some true => instreval en (Seq i' (While be i'))
| Some false => en
end
end.
*)
(*
Inductive var : Set := string.
Inductive val : Set := nat.
Inductive expr : Set :=
| Var : var -> expr
| Val : val -> expr
| Add : expr -> expr -> expr.
Inductive boolean : Set :=
| Lt : expr -> expr -> boolean.
Inductive instr : Set :=
| Skip : instr
| Let : var -> expr -> instr
| Seq : instr -> instr -> instr
| While : bool -> instr -> instr.
Inductive env : Set :=
| Empty : env
| NewVar : var * val -> env.
(*
ρ ⊢ n → n
(var, val)::ρ ⊢ var → val
*)
Inductive eval : env -> expr -> val -> Prop :=
| ValEval : forall (en:env) (n:expr),
*)