commit
3b3c8c67e7
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,97 @@
|
|||||||
|
From semantics.ts.systemf_mu Require Export lang.
|
||||||
|
Set Default Proof Using "Type".
|
||||||
|
|
||||||
|
|
||||||
|
(** Coercions to make programs easier to type. *)
|
||||||
|
Coercion of_val : val >-> expr.
|
||||||
|
Coercion LitInt : Z >-> base_lit.
|
||||||
|
Coercion LitBool : bool >-> base_lit.
|
||||||
|
Coercion App : expr >-> Funclass.
|
||||||
|
Coercion Var : string >-> expr.
|
||||||
|
|
||||||
|
(** Define some derived forms. *)
|
||||||
|
Notation Let x e1 e2 := (App (Lam x e2) e1) (only parsing).
|
||||||
|
Notation Seq e1 e2 := (Let BAnon e1 e2) (only parsing).
|
||||||
|
Notation Match e0 x1 e1 x2 e2 := (Case e0 (Lam x1 e1) (Lam x2 e2)) (only parsing).
|
||||||
|
|
||||||
|
(* No scope for the values, does not conflict and scope is often not inferred
|
||||||
|
properly. *)
|
||||||
|
Notation "# l" := (LitV l%Z%V%stdpp) (at level 8, format "# l").
|
||||||
|
Notation "# l" := (Lit l%Z%E%stdpp) (at level 8, format "# l") : expr_scope.
|
||||||
|
|
||||||
|
(** Syntax inspired by Coq/Ocaml. Constructions with higher precedence come
|
||||||
|
first. *)
|
||||||
|
Notation "( e1 , e2 , .. , en )" := (Pair .. (Pair e1 e2) .. en) : expr_scope.
|
||||||
|
Notation "( e1 , e2 , .. , en )" := (PairV .. (PairV e1 e2) .. en) : val_scope.
|
||||||
|
|
||||||
|
Notation "'match:' e0 'with' 'InjL' x1 => e1 | 'InjR' x2 => e2 'end'" :=
|
||||||
|
(Match e0 x1%binder e1 x2%binder e2)
|
||||||
|
(e0, x1, e1, x2, e2 at level 200,
|
||||||
|
format "'[hv' 'match:' e0 'with' '/ ' '[' 'InjL' x1 => '/ ' e1 ']' '/' '[' | 'InjR' x2 => '/ ' e2 ']' '/' 'end' ']'") : expr_scope.
|
||||||
|
Notation "'match:' e0 'with' 'InjR' x1 => e1 | 'InjL' x2 => e2 'end'" :=
|
||||||
|
(Match e0 x2%binder e2 x1%binder e1)
|
||||||
|
(e0, x1, e1, x2, e2 at level 200, only parsing) : expr_scope.
|
||||||
|
|
||||||
|
Notation "()" := LitUnit : val_scope.
|
||||||
|
|
||||||
|
Notation "e1 + e2" := (BinOp PlusOp e1%E e2%E) : expr_scope.
|
||||||
|
Notation "e1 - e2" := (BinOp MinusOp e1%E e2%E) : expr_scope.
|
||||||
|
Notation "e1 * e2" := (BinOp MultOp e1%E e2%E) : expr_scope.
|
||||||
|
Notation "e1 ≤ e2" := (BinOp LeOp e1%E e2%E) : expr_scope.
|
||||||
|
Notation "e1 = e2" := (BinOp EqOp e1%E e2%E) : expr_scope.
|
||||||
|
Notation "e1 < e2" := (BinOp LtOp e1%E e2%E) : expr_scope.
|
||||||
|
|
||||||
|
(*Notation "~ e" := (UnOp NegOp e%E) (at level 75, right associativity) : expr_scope.*)
|
||||||
|
|
||||||
|
Notation "'if:' e1 'then' e2 'else' e3" := (If e1%E e2%E e3%E)
|
||||||
|
(at level 200, e1, e2, e3 at level 200) : expr_scope.
|
||||||
|
|
||||||
|
Notation "λ: x , e" := (Lam x%binder e%E)
|
||||||
|
(at level 200, x at level 1, e at level 200,
|
||||||
|
format "'[' 'λ:' x , '/ ' e ']'") : expr_scope.
|
||||||
|
Notation "λ: x y .. z , e" := (Lam x%binder (Lam y%binder .. (Lam z%binder e%E) ..))
|
||||||
|
(at level 200, x, y, z at level 1, e at level 200,
|
||||||
|
format "'[' 'λ:' x y .. z , '/ ' e ']'") : expr_scope.
|
||||||
|
|
||||||
|
Notation "λ: x , e" := (LamV x%binder e%E)
|
||||||
|
(at level 200, x at level 1, e at level 200,
|
||||||
|
format "'[' 'λ:' x , '/ ' e ']'") : val_scope.
|
||||||
|
Notation "λ: x y .. z , e" := (LamV x%binder (Lam y%binder .. (Lam z%binder e%E) .. ))
|
||||||
|
(at level 200, x, y, z at level 1, e at level 200,
|
||||||
|
format "'[' 'λ:' x y .. z , '/ ' e ']'") : val_scope.
|
||||||
|
|
||||||
|
Notation "'let:' x := e1 'in' e2" := (Lam x%binder e2%E e1%E)
|
||||||
|
(at level 200, x at level 1, e1, e2 at level 200,
|
||||||
|
format "'[' 'let:' x := '[' e1 ']' 'in' '/' e2 ']'") : expr_scope.
|
||||||
|
Notation "e1 ;; e2" := (Lam BAnon e2%E e1%E)
|
||||||
|
(at level 100, e2 at level 200,
|
||||||
|
format "'[' '[hv' '[' e1 ']' ;; ']' '/' e2 ']'") : expr_scope.
|
||||||
|
|
||||||
|
|
||||||
|
Notation "'Λ' , e" := (TLam e%E)
|
||||||
|
(at level 200, e at level 200,
|
||||||
|
format "'[' 'Λ' , '/ ' e ']'") : expr_scope.
|
||||||
|
Notation "'Λ' , e" := (TLamV e%E)
|
||||||
|
(at level 200, e at level 200,
|
||||||
|
format "'[' 'Λ' , '/ ' e ']'") : val_scope.
|
||||||
|
|
||||||
|
(* the [e] always needs to be paranthesized, due to the level
|
||||||
|
(chosen to make this cooperate with the [App] coercion) *)
|
||||||
|
Notation "e '<>'" := (TApp e%E)
|
||||||
|
(at level 10) : expr_scope.
|
||||||
|
(*Check ((Λ, #4) <>)%E.*)
|
||||||
|
(*Check (((λ: "x", "x") #5) <>)%E.*)
|
||||||
|
|
||||||
|
Notation "'pack' e" := (Pack e%E)
|
||||||
|
(at level 200, e at level 200) : expr_scope.
|
||||||
|
Notation "'pack' v" := (PackV v%V)
|
||||||
|
(at level 200, v at level 200) : val_scope.
|
||||||
|
Notation "'unpack' e1 'as' x 'in' e2" := (Unpack x%binder e1%E e2%E)
|
||||||
|
(at level 200, e1, e2 at level 200, x at level 1) : expr_scope.
|
||||||
|
|
||||||
|
Notation "'roll' e" := (Roll e%E)
|
||||||
|
(at level 200, e at level 200) : expr_scope.
|
||||||
|
Notation "'roll' v" := (RollV v%E)
|
||||||
|
(at level 200, v at level 200) : val_scope.
|
||||||
|
Notation "'unroll' e" := (Unroll e%E)
|
||||||
|
(at level 200, e at level 200) : expr_scope.
|
@ -0,0 +1,275 @@
|
|||||||
|
From stdpp Require Import prelude.
|
||||||
|
From iris Require Import prelude.
|
||||||
|
From semantics.lib Require Import facts maps.
|
||||||
|
From semantics.ts.systemf_mu Require Import lang.
|
||||||
|
|
||||||
|
Fixpoint subst_map (xs : gmap string expr) (e : expr) : expr :=
|
||||||
|
match e with
|
||||||
|
| Lit l => Lit l
|
||||||
|
| Var y => match xs !! y with Some es => es | _ => Var y end
|
||||||
|
| App e1 e2 => App (subst_map xs e1) (subst_map xs e2)
|
||||||
|
| Lam x e => Lam x (subst_map (binder_delete x xs) e)
|
||||||
|
| UnOp op e => UnOp op (subst_map xs e)
|
||||||
|
| BinOp op e1 e2 => BinOp op (subst_map xs e1) (subst_map xs e2)
|
||||||
|
| If e0 e1 e2 => If (subst_map xs e0) (subst_map xs e1) (subst_map xs e2)
|
||||||
|
| TApp e => TApp (subst_map xs e)
|
||||||
|
| TLam e => TLam (subst_map xs e)
|
||||||
|
| Pack e => Pack (subst_map xs e)
|
||||||
|
| Unpack x e1 e2 => Unpack x (subst_map xs e1) (subst_map (binder_delete x xs) e2)
|
||||||
|
| Pair e1 e2 => Pair (subst_map xs e1) (subst_map xs e2)
|
||||||
|
| Fst e => Fst (subst_map xs e)
|
||||||
|
| Snd e => Snd (subst_map xs e)
|
||||||
|
| InjL e => InjL (subst_map xs e)
|
||||||
|
| InjR e => InjR (subst_map xs e)
|
||||||
|
| Case e e1 e2 => Case (subst_map xs e) (subst_map xs e1) (subst_map xs e2)
|
||||||
|
| Roll e => Roll (subst_map xs e)
|
||||||
|
| Unroll e => Unroll (subst_map xs e)
|
||||||
|
end.
|
||||||
|
|
||||||
|
Lemma subst_map_empty e :
|
||||||
|
subst_map ∅ e = e.
|
||||||
|
Proof.
|
||||||
|
induction e; simpl; f_equal; eauto.
|
||||||
|
all: destruct x; simpl; [done | by rewrite !delete_empty..].
|
||||||
|
Qed.
|
||||||
|
|
||||||
|
Lemma subst_map_is_closed X e xs :
|
||||||
|
is_closed X e →
|
||||||
|
(∀ x : string, x ∈ dom xs → x ∉ X) →
|
||||||
|
subst_map xs e = e.
|
||||||
|
Proof.
|
||||||
|
intros Hclosed Hd.
|
||||||
|
induction e in xs, X, Hd, Hclosed |-*; simpl in *;try done.
|
||||||
|
all: repeat match goal with
|
||||||
|
| H : Is_true (_ && _) |- _ => apply andb_True in H as [ ? ? ]
|
||||||
|
end.
|
||||||
|
{ (* Var *)
|
||||||
|
apply bool_decide_spec in Hclosed.
|
||||||
|
assert (xs !! x = None) as ->; last done.
|
||||||
|
destruct (xs !! x) as [s | ] eqn:Helem; last done.
|
||||||
|
exfalso; eapply Hd; last apply Hclosed.
|
||||||
|
apply elem_of_dom; eauto.
|
||||||
|
}
|
||||||
|
{ (* lambdas *)
|
||||||
|
erewrite IHe; [done | done |].
|
||||||
|
intros y. destruct x as [ | x]; first apply Hd.
|
||||||
|
simpl.
|
||||||
|
rewrite dom_delete elem_of_difference not_elem_of_singleton.
|
||||||
|
intros [Hnx%Hd Hneq]. rewrite elem_of_cons. intros [? | ?]; done.
|
||||||
|
}
|
||||||
|
8: { (* Unpack *)
|
||||||
|
erewrite IHe1; [ | done | done].
|
||||||
|
erewrite IHe2; [ done | done | ].
|
||||||
|
intros y. destruct x as [ | x]; first apply Hd.
|
||||||
|
simpl.
|
||||||
|
rewrite dom_delete elem_of_difference not_elem_of_singleton.
|
||||||
|
intros [Hnx%Hd Hneq]. rewrite elem_of_cons. intros [? | ?]; done.
|
||||||
|
}
|
||||||
|
(* all other cases *)
|
||||||
|
all: repeat match goal with
|
||||||
|
| H : ∀ _ _, _ → _ → subst_map _ _ = _ |- _ => erewrite H; clear H
|
||||||
|
end; done.
|
||||||
|
Qed.
|
||||||
|
|
||||||
|
Lemma subst_map_subst map x (e e' : expr) :
|
||||||
|
is_closed [] e' →
|
||||||
|
subst_map map (subst x e' e) = subst_map (<[x:=e']>map) e.
|
||||||
|
Proof.
|
||||||
|
intros He'.
|
||||||
|
revert x map; induction e; intros xx map; simpl;
|
||||||
|
try (f_equal; eauto).
|
||||||
|
- case_decide.
|
||||||
|
+ simplify_eq/=. rewrite lookup_insert.
|
||||||
|
rewrite (subst_map_is_closed []); [done | apply He' | ].
|
||||||
|
intros ? ?. apply not_elem_of_nil.
|
||||||
|
+ rewrite lookup_insert_ne; done.
|
||||||
|
- destruct x; simpl; first done.
|
||||||
|
+ case_decide.
|
||||||
|
* simplify_eq/=. by rewrite delete_insert_delete.
|
||||||
|
* rewrite delete_insert_ne; last by congruence. done.
|
||||||
|
- destruct x; simpl; first done.
|
||||||
|
+ case_decide.
|
||||||
|
* simplify_eq/=. by rewrite delete_insert_delete.
|
||||||
|
* rewrite delete_insert_ne; last by congruence. done.
|
||||||
|
Qed.
|
||||||
|
|
||||||
|
Definition subst_is_closed (X : list string) (map : gmap string expr) :=
|
||||||
|
∀ x e, map !! x = Some e → closed X e.
|
||||||
|
Lemma subst_is_closed_subseteq X map1 map2 :
|
||||||
|
map1 ⊆ map2 → subst_is_closed X map2 → subst_is_closed X map1.
|
||||||
|
Proof.
|
||||||
|
intros Hsub Hclosed2 x e Hl. eapply Hclosed2, map_subseteq_spec; done.
|
||||||
|
Qed.
|
||||||
|
|
||||||
|
Lemma subst_subst_map x es map e :
|
||||||
|
subst_is_closed [] map →
|
||||||
|
subst x es (subst_map (delete x map) e) =
|
||||||
|
subst_map (<[x:=es]>map) e.
|
||||||
|
Proof.
|
||||||
|
revert map es x; induction e; intros map v0 xx Hclosed; simpl;
|
||||||
|
try (f_equal; eauto).
|
||||||
|
- destruct (decide (xx=x)) as [->|Hne].
|
||||||
|
+ rewrite lookup_delete // lookup_insert //. simpl.
|
||||||
|
rewrite decide_True //.
|
||||||
|
+ rewrite lookup_delete_ne // lookup_insert_ne //.
|
||||||
|
destruct (_ !! x) as [rr|] eqn:Helem.
|
||||||
|
* apply Hclosed in Helem.
|
||||||
|
by apply subst_is_closed_nil.
|
||||||
|
* simpl. rewrite decide_False //.
|
||||||
|
- destruct x; simpl; first by auto.
|
||||||
|
case_decide.
|
||||||
|
+ simplify_eq. rewrite delete_idemp delete_insert_delete. done.
|
||||||
|
+ rewrite delete_insert_ne //; last congruence. rewrite delete_commute. apply IHe.
|
||||||
|
eapply subst_is_closed_subseteq; last done.
|
||||||
|
apply map_delete_subseteq.
|
||||||
|
- destruct x; simpl; first by auto.
|
||||||
|
case_decide.
|
||||||
|
+ simplify_eq. rewrite delete_idemp delete_insert_delete. done.
|
||||||
|
+ rewrite delete_insert_ne //; last congruence. rewrite delete_commute. apply IHe2.
|
||||||
|
eapply subst_is_closed_subseteq; last done.
|
||||||
|
apply map_delete_subseteq.
|
||||||
|
Qed.
|
||||||
|
|
||||||
|
Lemma subst'_subst_map b (es : expr) map e :
|
||||||
|
subst_is_closed [] map →
|
||||||
|
subst' b es (subst_map (binder_delete b map) e) =
|
||||||
|
subst_map (binder_insert b es map) e.
|
||||||
|
Proof.
|
||||||
|
destruct b; first done.
|
||||||
|
apply subst_subst_map.
|
||||||
|
Qed.
|
||||||
|
|
||||||
|
Lemma closed_subst_weaken e map X Y :
|
||||||
|
subst_is_closed [] map →
|
||||||
|
(∀ x, x ∈ X → x ∉ dom map → x ∈ Y) →
|
||||||
|
closed X e →
|
||||||
|
closed Y (subst_map map e).
|
||||||
|
Proof.
|
||||||
|
induction e in X, Y, map |-*; rewrite /closed; simpl; intros Hmclosed Hsub Hcl; first done.
|
||||||
|
all: repeat match goal with
|
||||||
|
| H : Is_true (_ && _) |- _ => apply andb_True in H as [ ? ? ]
|
||||||
|
end.
|
||||||
|
{ (* vars *)
|
||||||
|
destruct (map !! x) as [es | ] eqn:Heq.
|
||||||
|
+ apply is_closed_weaken_nil. by eapply Hmclosed.
|
||||||
|
+ apply bool_decide_pack. apply Hsub; first by eapply bool_decide_unpack.
|
||||||
|
by apply not_elem_of_dom.
|
||||||
|
}
|
||||||
|
{ (* lambdas *)
|
||||||
|
eapply IHe; last done.
|
||||||
|
+ eapply subst_is_closed_subseteq; last done.
|
||||||
|
destruct x; first done. apply map_delete_subseteq.
|
||||||
|
+ intros y. destruct x as [ | x]; first by apply Hsub.
|
||||||
|
rewrite !elem_of_cons. intros [-> | Hy] Hn; first by left.
|
||||||
|
destruct (decide (y = x)) as [ -> | Hneq]; first by left.
|
||||||
|
right. eapply Hsub; first done. set_solver.
|
||||||
|
}
|
||||||
|
8: { (* unpack *)
|
||||||
|
apply andb_True; split; first naive_solver.
|
||||||
|
eapply IHe2; last done.
|
||||||
|
+ eapply subst_is_closed_subseteq; last done.
|
||||||
|
destruct x; first done. apply map_delete_subseteq.
|
||||||
|
+ intros y. destruct x as [ | x]; first by apply Hsub.
|
||||||
|
rewrite !elem_of_cons. intros [-> | Hy] Hn; first by left.
|
||||||
|
destruct (decide (y = x)) as [ -> | Hneq]; first by left.
|
||||||
|
right. eapply Hsub; first done. set_solver.
|
||||||
|
}
|
||||||
|
(* all other cases *)
|
||||||
|
all: repeat match goal with
|
||||||
|
| |- Is_true (_ && _) => apply andb_True; split
|
||||||
|
end.
|
||||||
|
all: naive_solver.
|
||||||
|
Qed.
|
||||||
|
|
||||||
|
Lemma subst_is_closed_weaken X1 X2 θ :
|
||||||
|
subst_is_closed X1 θ →
|
||||||
|
X1 ⊆ X2 →
|
||||||
|
subst_is_closed X2 θ.
|
||||||
|
Proof.
|
||||||
|
intros Hcl Hincl x e Hlook.
|
||||||
|
eapply is_closed_weaken; last done.
|
||||||
|
by eapply Hcl.
|
||||||
|
Qed.
|
||||||
|
|
||||||
|
Lemma subst_is_closed_weaken_nil X θ :
|
||||||
|
subst_is_closed [] θ →
|
||||||
|
subst_is_closed X θ.
|
||||||
|
Proof.
|
||||||
|
intros; eapply subst_is_closed_weaken; first done.
|
||||||
|
apply list_subseteq_nil.
|
||||||
|
Qed.
|
||||||
|
|
||||||
|
Lemma subst_is_closed_insert X e f θ :
|
||||||
|
is_closed X e →
|
||||||
|
subst_is_closed X (delete f θ) →
|
||||||
|
subst_is_closed X (<[f := e]> θ).
|
||||||
|
Proof.
|
||||||
|
intros Hcl Hcl' x e'.
|
||||||
|
destruct (decide (x = f)) as [<- | ?].
|
||||||
|
- rewrite lookup_insert. intros [= <-]. done.
|
||||||
|
- rewrite lookup_insert_ne; last done.
|
||||||
|
intros Hlook. eapply Hcl'.
|
||||||
|
rewrite lookup_delete_ne; done.
|
||||||
|
Qed.
|
||||||
|
|
||||||
|
(* NOTE: this is a simplified version of the tactic in tactics.v which
|
||||||
|
suffice for this proof *)
|
||||||
|
Ltac simplify_closed :=
|
||||||
|
repeat match goal with
|
||||||
|
| |- closed _ _ => unfold closed; simpl
|
||||||
|
| |- Is_true (_ && _) => simpl; rewrite !andb_True; split_and!
|
||||||
|
| H : closed _ _ |- _ => unfold closed in H; simpl in H
|
||||||
|
| H: Is_true (_ && _) |- _ => simpl in H; apply andb_True in H
|
||||||
|
| H : _ ∧ _ |- _ => destruct H
|
||||||
|
end.
|
||||||
|
|
||||||
|
Lemma is_closed_subst_map X θ e :
|
||||||
|
subst_is_closed X θ →
|
||||||
|
closed (X ++ elements (dom θ)) e →
|
||||||
|
closed X (subst_map θ e).
|
||||||
|
Proof.
|
||||||
|
induction e in X, θ |-*; eauto.
|
||||||
|
all: try solve [intros; simplify_closed; naive_solver].
|
||||||
|
- unfold subst_map.
|
||||||
|
destruct (θ !! x) eqn:Heq.
|
||||||
|
+ intros Hcl _. eapply Hcl; done.
|
||||||
|
+ intros _ Hcl.
|
||||||
|
apply closed_is_closed in Hcl.
|
||||||
|
apply bool_decide_eq_true in Hcl.
|
||||||
|
apply elem_of_app in Hcl.
|
||||||
|
destruct Hcl as [ | H].
|
||||||
|
* apply closed_is_closed. by apply bool_decide_eq_true.
|
||||||
|
* apply elem_of_elements in H.
|
||||||
|
by apply not_elem_of_dom in Heq.
|
||||||
|
- intros. simplify_closed.
|
||||||
|
eapply IHe.
|
||||||
|
+ destruct x as [ | x]; simpl; first done.
|
||||||
|
intros y e'. rewrite lookup_delete_Some. intros (? & Hlook%H).
|
||||||
|
eapply is_closed_weaken; first done.
|
||||||
|
by apply list_subseteq_cons_r.
|
||||||
|
+ eapply is_closed_weaken; first done.
|
||||||
|
simpl. destruct x as [ | x]; first done; simpl.
|
||||||
|
apply list_subseteq_cons_l.
|
||||||
|
apply stdpp.sets.elem_of_subseteq.
|
||||||
|
intros y; simpl. rewrite elem_of_cons !elem_of_app.
|
||||||
|
intros [ | Helem]; first naive_solver.
|
||||||
|
destruct (decide (x = y)) as [<- | Hneq]; first naive_solver.
|
||||||
|
right. right. apply elem_of_elements. rewrite dom_delete elem_of_difference elem_of_singleton.
|
||||||
|
apply elem_of_elements in Helem; done.
|
||||||
|
- intros. simplify_closed. { naive_solver. }
|
||||||
|
(* same proof as for lambda *)
|
||||||
|
eapply IHe2.
|
||||||
|
+ destruct x as [ | x]; simpl; first done.
|
||||||
|
intros y e'. rewrite lookup_delete_Some. intros (? & Hlook%H).
|
||||||
|
eapply is_closed_weaken; first done.
|
||||||
|
by apply list_subseteq_cons_r.
|
||||||
|
+ eapply is_closed_weaken; first done.
|
||||||
|
simpl. destruct x as [ | x]; first done; simpl.
|
||||||
|
apply list_subseteq_cons_l.
|
||||||
|
apply stdpp.sets.elem_of_subseteq.
|
||||||
|
intros y; simpl. rewrite elem_of_cons !elem_of_app.
|
||||||
|
intros [ | Helem]; first naive_solver.
|
||||||
|
destruct (decide (x = y)) as [<- | Hneq]; first naive_solver.
|
||||||
|
right. right. apply elem_of_elements. rewrite dom_delete elem_of_difference elem_of_singleton.
|
||||||
|
apply elem_of_elements in Helem; done.
|
||||||
|
Qed.
|
@ -0,0 +1,84 @@
|
|||||||
|
From stdpp Require Import gmap base relations.
|
||||||
|
From iris Require Import prelude.
|
||||||
|
From semantics.lib Require Export facts maps sets.
|
||||||
|
From semantics.ts.systemf_mu Require Export lang notation types.
|
||||||
|
|
||||||
|
Ltac map_solver :=
|
||||||
|
repeat match goal with
|
||||||
|
| |- (⤉ _) !! _ = Some _ =>
|
||||||
|
rewrite fmap_insert
|
||||||
|
| |- <[ ?p := _ ]> _ !! ?p = Some _ =>
|
||||||
|
apply lookup_insert
|
||||||
|
| |- <[ _ := _ ]> _ !! _ = Some _ =>
|
||||||
|
rewrite lookup_insert_ne; [ | congruence]
|
||||||
|
end.
|
||||||
|
Ltac solve_typing :=
|
||||||
|
intros;
|
||||||
|
repeat match goal with
|
||||||
|
| |- TY _ ; _ ⊢ ?e : ?A => first [eassumption | econstructor]
|
||||||
|
(* heuristic to solve tapp goals where we need to pick the right type for the substitution *)
|
||||||
|
| |- TY _ ; _ ⊢ ?e <> : ?A => eapply typed_tapp'; [solve_typing | | asimpl; reflexivity]
|
||||||
|
| |- TY _ ; _ ⊢ Unroll ?e : ?A => eapply typed_unroll'; [solve_typing | asimpl; reflexivity]
|
||||||
|
| |- bin_op_typed _ _ _ _ => econstructor
|
||||||
|
| |- un_op_typed _ _ _ _ => econstructor
|
||||||
|
| |- type_wf _ ?e => assert_fails (is_evar e); eassumption
|
||||||
|
| |- type_wf _ ?e => assert_fails (is_evar e); econstructor
|
||||||
|
| |- type_wf _ (subst _ ?A) => eapply type_wf_subst; [ | intros; simpl]
|
||||||
|
| |- type_wf _ ?e => assert_fails (is_evar e); eapply type_wf_mono; [eassumption | lia]
|
||||||
|
(* conditions spawned by the tyvar case of [type_wf] *)
|
||||||
|
| |- _ < _ => lia
|
||||||
|
(* conditions spawned by the variable case *)
|
||||||
|
| |- _ !! _ = Some _ => map_solver
|
||||||
|
end.
|
||||||
|
|
||||||
|
Tactic Notation "unify_type" uconstr(A) :=
|
||||||
|
match goal with
|
||||||
|
| |- TY ?n; ?Γ ⊢ ?e : ?B => unify A B
|
||||||
|
end.
|
||||||
|
Tactic Notation "replace_type" uconstr(A) :=
|
||||||
|
match goal with
|
||||||
|
| |- TY ?n; ?Γ ⊢ ?e : ?B => replace B%ty with A%ty; cycle -1; first try by asimpl
|
||||||
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
Ltac simplify_list_elem :=
|
||||||
|
simpl;
|
||||||
|
repeat match goal with
|
||||||
|
| |- ?x ∈ ?y :: ?l => apply elem_of_cons; first [left; reflexivity | right]
|
||||||
|
| |- _ ∉ [] => apply not_elem_of_nil
|
||||||
|
| |- _ ∉ _ :: _ => apply not_elem_of_cons; split
|
||||||
|
end; try fast_done.
|
||||||
|
Ltac simplify_list_subseteq :=
|
||||||
|
simpl;
|
||||||
|
repeat match goal with
|
||||||
|
| |- ?x :: _ ⊆ ?x :: _ => apply list_subseteq_cons_l
|
||||||
|
| |- ?x :: _ ⊆ _ => apply list_subseteq_cons_elem; first solve [simplify_list_elem]
|
||||||
|
| |- elements _ ⊆ elements _ => apply elements_subseteq; set_solver
|
||||||
|
| |- [] ⊆ _ => apply list_subseteq_nil
|
||||||
|
| |- ?x :b: _ ⊆ ?x :b: _ => apply list_subseteq_cons_binder
|
||||||
|
(* NOTE: this might make the goal unprovable *)
|
||||||
|
(*| |- elements _ ⊆ _ :: _ => apply list_subseteq_cons_r*)
|
||||||
|
end;
|
||||||
|
try fast_done.
|
||||||
|
|
||||||
|
(* Try to solve [is_closed] goals using a number of heuristics (that shouldn't make the goal unprovable) *)
|
||||||
|
Ltac simplify_closed :=
|
||||||
|
simpl; intros;
|
||||||
|
repeat match goal with
|
||||||
|
| |- closed _ _ => unfold closed; simpl
|
||||||
|
| |- Is_true (is_closed [] _) => first [assumption | done]
|
||||||
|
| |- Is_true (is_closed _ (lang.subst _ _ _)) => rewrite subst_is_closed_nil; last solve[simplify_closed]
|
||||||
|
| |- Is_true (is_closed ?X ?v) => assert_fails (is_evar X); eapply is_closed_weaken
|
||||||
|
| |- Is_true (is_closed _ _) => eassumption
|
||||||
|
| |- Is_true (_ && true) => rewrite andb_true_r
|
||||||
|
| |- Is_true (true && _) => rewrite andb_true_l
|
||||||
|
| |- Is_true (?a && ?a) => rewrite andb_diag
|
||||||
|
| |- Is_true (_ && _) => simpl; rewrite !andb_True; split_and!
|
||||||
|
| |- _ ⊆ ?A => match type of A with | list _ => simplify_list_subseteq end
|
||||||
|
| |- _ ∈ ?A => match type of A with | list _ => simplify_list_elem end
|
||||||
|
| |- _ ≠ _ => congruence
|
||||||
|
| H : closed _ _ |- _ => unfold closed in H; simpl in H
|
||||||
|
| H: Is_true (_ && _) |- _ => simpl in H; apply andb_True in H
|
||||||
|
| H : _ ∧ _ |- _ => destruct H
|
||||||
|
| |- Is_true (bool_decide (_ ∈ _)) => apply bool_decide_pack; set_solver
|
||||||
|
end; try fast_done.
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,80 @@
|
|||||||
|
From stdpp Require Import gmap base relations tactics.
|
||||||
|
From iris Require Import prelude.
|
||||||
|
From semantics.ts.systemf_mu Require Import lang notation types pure tactics.
|
||||||
|
From Autosubst Require Import Autosubst.
|
||||||
|
|
||||||
|
(** * Encoding of the untyped lambda calculus *)
|
||||||
|
|
||||||
|
Definition D := (μ: #0 → #0)%ty.
|
||||||
|
|
||||||
|
Definition lame (x : string) (e : expr) : val := RollV (λ: x, e).
|
||||||
|
Definition appe (e1 e2 : expr) : expr := (unroll e1) e2.
|
||||||
|
|
||||||
|
Lemma lame_typed n Γ x e :
|
||||||
|
TY n; (<[x := D]> Γ) ⊢ e : D →
|
||||||
|
TY n; Γ ⊢ lame x e : D.
|
||||||
|
Proof. solve_typing. Qed.
|
||||||
|
|
||||||
|
Lemma app_typed n Γ e1 e2 :
|
||||||
|
TY n; Γ ⊢ e1 : D →
|
||||||
|
TY n; Γ ⊢ e2 : D →
|
||||||
|
TY n; Γ ⊢ appe e1 e2 : D.
|
||||||
|
Proof.
|
||||||
|
solve_typing.
|
||||||
|
Qed.
|
||||||
|
|
||||||
|
Lemma appe_step_l e1 e1' (v : val) :
|
||||||
|
contextual_step e1 e1' →
|
||||||
|
contextual_step (appe e1 v) (appe e1' v).
|
||||||
|
Proof.
|
||||||
|
intros Hstep. unfold appe.
|
||||||
|
by eapply (fill_contextual_step [UnrollCtx; AppLCtx _]).
|
||||||
|
Qed.
|
||||||
|
|
||||||
|
Lemma appe_step_r e1 e2 e2' :
|
||||||
|
contextual_step e2 e2' →
|
||||||
|
contextual_step (appe e1 e2) (appe e1 e2').
|
||||||
|
Proof.
|
||||||
|
intros Hstep. unfold appe.
|
||||||
|
by eapply (fill_contextual_step [AppRCtx _]).
|
||||||
|
Qed.
|
||||||
|
|
||||||
|
Lemma lame_step_beta x e (v : val) :
|
||||||
|
rtc contextual_step (appe (lame x e) v) (lang.subst x v e).
|
||||||
|
Proof.
|
||||||
|
unfold appe, lame.
|
||||||
|
econstructor 2.
|
||||||
|
{ eapply (fill_contextual_step [AppLCtx _]).
|
||||||
|
eapply base_contextual_step. by econstructor.
|
||||||
|
}
|
||||||
|
econstructor 2.
|
||||||
|
{ eapply base_contextual_step. econstructor; eauto. }
|
||||||
|
reflexivity.
|
||||||
|
Qed.
|
||||||
|
|
||||||
|
(* Divergence *)
|
||||||
|
Definition ω : expr :=
|
||||||
|
roll (λ: "x", (unroll "x") "x").
|
||||||
|
|
||||||
|
Definition Ω := ((unroll ω) ω)%E.
|
||||||
|
|
||||||
|
Lemma Ω_loops:
|
||||||
|
tc contextual_step Ω Ω.
|
||||||
|
Proof.
|
||||||
|
econstructor 2; [|econstructor 1].
|
||||||
|
- rewrite /Ω /ω. eauto.
|
||||||
|
- rewrite /Ω. eauto.
|
||||||
|
Qed.
|
||||||
|
|
||||||
|
Lemma ω_typed :
|
||||||
|
TY 0; ∅ ⊢ ω : D.
|
||||||
|
Proof.
|
||||||
|
solve_typing.
|
||||||
|
Qed.
|
||||||
|
|
||||||
|
Lemma Ω_typed : TY 0; ∅ ⊢ Ω : D.
|
||||||
|
Proof.
|
||||||
|
rewrite /Ω. econstructor.
|
||||||
|
- eapply typed_unroll'; eauto using ω_typed.
|
||||||
|
- eapply ω_typed.
|
||||||
|
Qed.
|
Loading…
Reference in new issue