playground/coq/unfinished/semantic-style.v

399 lines
9.5 KiB
Coq
Raw Normal View History

2023-05-23 17:08:33 +00:00
(*
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),
*)