Require Import Coq.Lists.List. Require Import Coq.Strings.String. Require Import Coq.Program.Equality. Import ListNotations. Open Scope list_scope. Open Scope string_scope. Inductive label : Type := (* efficiency hack *) | lDiscard : label | lCapture : label | lQuote: label | lStr : string -> label. Inductive value : Type := | vBool : bool -> value | vSymbol : label -> value | vRecord: value -> list value -> value | vSeq : list value -> value. Inductive pat : Type := | pDiscard : pat | pCapture : pat -> pat | pBool : bool -> pat | pSymbol : label -> pat | pRecord: pat -> list pat -> pat | pSeq : list pat -> pat. Definition vQuote v : value := vRecord (vSymbol lQuote) [v]. Fixpoint value_ind' (P : value -> Prop) (PBool : forall b, P (vBool b)) (PSymbol : forall l, P (vSymbol l)) (PRecord : forall v vs, P v -> Forall P vs -> P (vRecord v vs)) (PSeq : forall vs, Forall P vs -> P (vSeq vs)) p : P p. Proof. induction p; auto; [ apply PRecord; [ apply IHp | ] | apply PSeq ]; try solve [ induction l; [ apply Forall_nil | ]; apply Forall_cons; [ apply value_ind'; try assumption | ]; apply IHl ]. Defined. Fixpoint pat_ind' (P : pat -> Prop) (PDiscard : P pDiscard) (PCapture : forall p, P p -> P (pCapture p)) (PBool : forall b, P (pBool b)) (PSymbol : forall l, P (pSymbol l)) (PRecord : forall p ps, P p -> Forall P ps -> P (pRecord p ps)) (PSeq : forall ps, Forall P ps -> P (pSeq ps)) p : P p. Proof. induction p; auto; [ apply PRecord; [ apply IHp | ] | apply PSeq ]; try solve [ induction l; [ apply Forall_nil | ]; apply Forall_cons; [ apply pat_ind'; try assumption | ]; apply IHl ]. Defined. Fixpoint value_dec (x y : value) : { x = y } + { x <> y }. repeat decide equality. Defined. Fixpoint pat_dec (x y : pat) : { x = y } + { x <> y }. repeat decide equality. Defined. Scheme Equality for label. Fixpoint mat p v : bool := let matseq := (fix matseq ps vs : bool := match ps, vs with | [], [] => true | (p :: ps'), (v :: vs') => andb (mat p v) (matseq ps' vs') | _, _ => false end) in match p with | pDiscard => true | pCapture p' => mat p' v | pBool b => match v with vBool b' => bool_beq b b' | _ => false end | pSymbol s => match v with vSymbol s' => label_beq s s' | _ => false end | pRecord p' ps => match v with vRecord v' vs => mat p' v' && matseq ps vs | _ => false end | pSeq ps => match v with vSeq vs => matseq ps vs | _ => false end end. Fixpoint raw_v_to_p v : pat := match v with | vBool b => pBool b | vSymbol s => pSymbol s | vRecord l fs => pRecord (raw_v_to_p l) (map raw_v_to_p fs) | vSeq vs => pSeq (map raw_v_to_p vs) end. Fixpoint v_to_p v : pat := match v with | vRecord (vSymbol lDiscard) [] => pDiscard | vRecord (vSymbol lCapture) [v'] => pCapture (v_to_p v') | vRecord (vSymbol lQuote) [v'] => raw_v_to_p v' | vBool b => pBool b | vSymbol s => pSymbol s | vRecord l fs => pRecord (v_to_p l) (map v_to_p fs) | vSeq vs => pSeq (map v_to_p vs) end. Fixpoint p_to_v p : value := match p with | pDiscard => vRecord (vSymbol lDiscard) [] | pCapture p' => vRecord (vSymbol lCapture) [p_to_v p'] | pBool b => vBool b | pSymbol s => vSymbol s | pRecord (pSymbol lDiscard) [] => vRecord (vQuote (vSymbol lDiscard)) [] | pRecord (pSymbol lCapture) [p'] => vRecord (vQuote (vSymbol lCapture)) [p_to_v p'] | pRecord (pSymbol lQuote) [p'] => vRecord (vQuote (vSymbol lQuote)) [p_to_v p'] | pRecord l ps => vRecord (p_to_v l) (map p_to_v ps) | pSeq ps => vSeq (map p_to_v ps) end. Lemma Forall_map_map_id : forall A X xs (f : X -> A) (g : A -> X), Forall (fun x : X => g (f x) = x) xs -> (map g (map f xs)) = xs. Proof. intros; rewrite map_map; induction H; [ reflexivity | ]. simpl; rewrite IHForall; rewrite H; reflexivity. Qed. Ltac solve_map_map_id := repeat f_equal; apply Forall_map_map_id; assumption. Theorem reflection_after_interpretation_sensible : forall p, v_to_p (p_to_v p) = p. Proof. induction p using pat_ind'; try solve [ reflexivity | rewrite <- IHp at 2; reflexivity | simpl; solve_map_map_id ]. destruct p; simpl; try rewrite <- IHp; try solve [ solve_map_map_id ]. (* label pSymbol *) destruct l; apply Forall_map_map_id in H; destruct ps; simpl in H; inversion H; clear H; auto; destruct ps; simpl; repeat f_equal; try solve [ repeat rewrite H1; reflexivity | inversion H2; repeat rewrite H0; repeat rewrite H3; reflexivity ]. (* label pRecord *) destruct p; try solve_map_map_id; destruct l0; destruct l; try solve_map_map_id; destruct l; solve_map_map_id. Qed. Theorem interpretation_after_reflection_not_sensible : exists v, p_to_v (v_to_p v) <> v. Proof. exists (vQuote (vRecord (vSymbol lDiscard) [])). simpl; intro H; inversion H. Qed. Fixpoint escape v : value := match v with | vBool b => vBool b | vSymbol s => vSymbol s | vRecord (vSymbol lDiscard) [] => vRecord (vQuote (vSymbol lDiscard)) [] | vRecord (vSymbol lCapture) [v'] => vRecord (vQuote (vSymbol lCapture)) [escape v'] | vRecord (vSymbol lQuote) [v'] => vRecord (vQuote (vSymbol lQuote)) [escape v'] | vRecord l vs => vRecord (escape l) (map escape vs) | vSeq vs => vSeq (map escape vs) end. Fixpoint unescape v : value := match v with | vBool b => vBool b | vSymbol s => vSymbol s | vRecord (vSymbol lQuote) [v'] => v' | vRecord l vs => vRecord (unescape l) (map unescape vs) | vSeq vs => vSeq (map unescape vs) end. Theorem unescape_after_escape_id : forall v, unescape (escape v) = v. Proof. induction v using value_ind'; auto. destruct v; simpl; try rewrite <- IHv; try solve [ solve_map_map_id ]. (* vRecord with a vSymbol label *) destruct l; apply Forall_map_map_id in H; destruct vs; simpl in H; inversion H; clear H; auto; destruct vs; simpl; repeat f_equal; try solve [ repeat rewrite H1; reflexivity | inversion H2; repeat rewrite H0; repeat rewrite H3; reflexivity ]. (* vRecord with a vRecord label *) destruct v; try solve_map_map_id; destruct l0; destruct l; try solve_map_map_id; destruct l; solve_map_map_id. (* vSeq *) destruct vs; inversion H; clear H; simpl; repeat rewrite H2; repeat rewrite H3; solve_map_map_id. Qed. Lemma Forall_map_map_assoc_id : forall A X Y ys (h : Y -> X) (f : X -> A) (g : A -> X), Forall (fun y : Y => g (f (h y)) = (h y)) ys -> map g (map f (map h ys)) = (map h ys). Proof. intros; rewrite map_map; induction H; [ reflexivity | ]. simpl; rewrite IHForall; rewrite H; reflexivity. Qed. Ltac solve_map_map_assoc_id := repeat f_equal; apply Forall_map_map_assoc_id; assumption. Lemma escape_record_record_label : forall l inner outer, escape (vRecord (vRecord l inner) outer) = vRecord (escape (vRecord l inner)) (map escape outer). Proof. reflexivity. Qed. Lemma Forall_map_map_raw : forall B A X xs (h : X -> A) (f : X -> B) (g : B -> A), Forall (fun x : X => (g (f x)) = (h x)) xs -> map g (map f xs) = (map h xs). Proof. intros; rewrite map_map; induction H; [ reflexivity | ]. simpl; rewrite IHForall; rewrite H; reflexivity. Qed. Lemma escaped_record_is_record : forall v l, exists l' v', escape (vRecord v l) = vRecord v' l'. Proof. intros. exists (map escape l). remember v as x. induction x using value_ind'; try destruct l0; try destruct l; try destruct l; try solve [ exists v; subst; reflexivity | exists (vQuote (vSymbol lDiscard)); reflexivity | exists (vQuote (vSymbol lCapture)); reflexivity | exists (vQuote (vSymbol lQuote)); reflexivity | exists (escape (vRecord x vs)); reflexivity | exists (escape (vSeq vs)); reflexivity ]. Qed. Lemma v_to_p_escaped_record_is_raw_v_to_p : forall v, v_to_p (escape v) = (raw_v_to_p v). Proof. induction v using value_ind'; try reflexivity. destruct v. simpl; rewrite Forall_map_map_raw with (h := raw_v_to_p); auto. destruct l; destruct vs; simpl; inversion IHv; try reflexivity; (destruct vs; simpl; inversion H; rewrite H2; try reflexivity; inversion H3; rewrite H6; rewrite Forall_map_map_raw with (h := raw_v_to_p); auto). unfold raw_v_to_p; fold raw_v_to_p; (replace (pRecord (raw_v_to_p v) (map raw_v_to_p l)) with (raw_v_to_p (vRecord v l)); [ | reflexivity ]); rewrite <- IHv; rewrite escape_record_record_label; (assert (exists (l' : list value) (v' : value), escape (vRecord v l) = vRecord v' l'); [ apply escaped_record_is_record | ]); inversion_clear H0; inversion_clear H1; rewrite H0; rewrite <- Forall_map_map_raw with (f := escape) (g := v_to_p); auto. simpl; f_equal; [ apply IHv | ]; apply Forall_map_map_raw; assumption. simpl; f_equal; apply Forall_map_map_raw; assumption. Qed. Lemma p_to_v_of_raw_v_to_p_is_escape : forall v, p_to_v (raw_v_to_p v) = escape v. Proof. induction v using value_ind'; try reflexivity. dependent induction v. (* unfold raw_v_to_p; fold raw_v_to_p; *) (* unfold p_to_v; fold p_to_v. *) simpl; f_equal; f_equal; apply Forall_map_map_raw; assumption. destruct l; destruct vs; simpl; inversion IHv; try reflexivity; (destruct vs; simpl; inversion H; rewrite H2; try reflexivity; inversion H3; rewrite H6; rewrite Forall_map_map_raw with (h := escape); [ | assumption ]; reflexivity). destruct v; simpl; inversion IHv0; f_equal; f_equal; try solve [ apply Forall_map_map_raw; assumption ]. simpl; inversion IHv; rewrite <- Forall_map_map_raw with (f := raw_v_to_p) (g := p_to_v); [ | assumption ]; reflexivity. inversion H; try reflexivity; simpl; rewrite H0; rewrite <- Forall_map_map_raw with (f := raw_v_to_p) (g := p_to_v); [ | assumption ]; reflexivity. Qed. Lemma interpretation_after_reflection_after_escape_sensible v : p_to_v (v_to_p (escape v)) = (escape v). Proof. rewrite v_to_p_escaped_record_is_raw_v_to_p. apply p_to_v_of_raw_v_to_p_is_escape. Qed. Theorem unescape_interpretation_reflection_escape_sensible v : unescape (p_to_v (v_to_p (escape v))) = v. Proof. rewrite interpretation_after_reflection_after_escape_sensible. apply unescape_after_escape_id. Qed. Fixpoint quotation_invariant v u : mat (v_to_p (escape v)) u = true <-> u = v. Proof. destruct v; destruct u; rewrite v_to_p_escaped_record_is_raw_v_to_p; (split; intro Hlhs; [ | rewrite Hlhs ]); try solve [ simpl in * |- *; congruence ]. apply internal_bool_dec_bl in Hlhs; congruence. apply internal_bool_dec_lb; reflexivity. apply internal_label_dec_bl in Hlhs; congruence. apply internal_label_dec_lb; reflexivity. simpl in Hlhs; symmetry in Hlhs; apply Bool.andb_true_eq in Hlhs; inversion_clear Hlhs. symmetry in H, H0. rewrite <- v_to_p_escaped_record_is_raw_v_to_p in H. rewrite quotation_invariant in H. subst u; f_equal. dependent induction l; dependent induction l0; try solve [ reflexivity | simpl in H0; congruence ]. simpl in H0. simpl in H0; symmetry in H0; apply Bool.andb_true_eq in H0; inversion_clear H0. symmetry in H, H1. rewrite <- v_to_p_escaped_record_is_raw_v_to_p in H. rewrite quotation_invariant in H. subst a0; f_equal. apply IHl. assumption. simpl; apply andb_true_intro; rewrite <- v_to_p_escaped_record_is_raw_v_to_p; split. rewrite quotation_invariant; reflexivity. clear Hlhs; induction l; [ reflexivity | ]. simpl; apply andb_true_intro; rewrite <- v_to_p_escaped_record_is_raw_v_to_p; split. rewrite quotation_invariant; reflexivity. apply IHl. dependent induction l; dependent induction l0; try solve [ reflexivity | simpl in Hlhs; congruence ]. simpl in Hlhs. simpl in Hlhs; symmetry in Hlhs; apply Bool.andb_true_eq in Hlhs; inversion_clear Hlhs. symmetry in H, H0. rewrite <- v_to_p_escaped_record_is_raw_v_to_p in H. rewrite quotation_invariant in H. subst a0; f_equal. apply IHl in H0. congruence. clear Hlhs; induction l; [ reflexivity | ]. simpl; apply andb_true_intro; rewrite <- v_to_p_escaped_record_is_raw_v_to_p; split. rewrite quotation_invariant; reflexivity. apply IHl. Qed.