aboutsummaryrefslogtreecommitdiffstats
path: root/theories/DecreaseChecker.v
blob: d24887a422fe66f4f0744d2afb1af0f16ecfb980 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
(* The executable admission checker, proven and extracted.

   Decrease.v states the abstract argument: strict containment
   decreases a well founded measure. This file carries the argument
   over to an executable checker faithful to lib/pattern.ml: terms
   keep their labels and leaf identities, the checker is a boolean
   function, and its soundness is proven, so extraction can replace
   the hand written OCaml. The equality functions supplied by the
   host and the conversion from Pattern.t are the remaining trusted
   seam. *)

From Stdlib Require Import Arith Lia Bool Wf_nat.

Section Checker.
  Variables (L A : Type).
  Variables (eqL : L -> L -> bool) (eqA : A -> A -> bool).

  (* Terms as the checker sees them: leaves carry their identity
     (variable name, scalar value), nodes carry labeled fields in
     canonical order. Mirrors Pattern.t through an injective
     conversion. *)
  Inductive term : Type :=
  | Leaf : A -> term
  | Node : fields -> term
  with fields : Type :=
  | FNil : fields
  | FCons : L -> term -> fields -> fields.

  Scheme term_mut := Induction for term Sort Prop
    with fields_mut := Induction for fields Sort Prop.
  Combined Scheme term_fields_mut from term_mut, fields_mut.

  Fixpoint term_eqb (x y : term) : bool :=
    match x, y with
    | Leaf a, Leaf b => eqA a b
    | Node f, Node g => fields_eqb f g
    | _, _ => false
    end
  with fields_eqb (f g : fields) : bool :=
    match f, g with
    | FNil, FNil => true
    | FCons l t r, FCons l' t' r' =>
        eqL l l' && term_eqb t t' && fields_eqb r r'
    | _, _ => false
    end.

  (* Strict containment: [sub] occurs somewhere inside the fields of
     [t], at depth one or more. *)
  Fixpoint contains (sub t : term) : bool :=
    match t with
    | Leaf _ => false
    | Node f => fields_contain sub f
    end
  with fields_contain (sub : term) (f : fields) : bool :=
    match f with
    | FNil => false
    | FCons _ t r => term_eqb t sub || contains sub t || fields_contain sub r
    end.

  Fixpoint size (t : term) : nat :=
    match t with
    | Leaf _ => 1
    | Node f => S (fields_size f)
    end
  with fields_size (f : fields) : nat :=
    match f with
    | FNil => 0
    | FCons _ t r => size t + fields_size r
    end.

  Hypothesis eqL_sound : forall x y, eqL x y = true -> x = y.
  Hypothesis eqA_sound : forall x y, eqA x y = true -> x = y.

  Lemma eqb_sound_all :
    (forall x, forall y, term_eqb x y = true -> x = y)
    /\ (forall f, forall g, fields_eqb f g = true -> f = g).
  Proof.
    apply term_fields_mut.
    - intros a y H; destruct y; simpl in H; [ f_equal; auto | discriminate ].
    - intros f IH y H; destruct y; simpl in H; [ discriminate | f_equal; auto ].
    - intros g H; destruct g; [ reflexivity | discriminate ].
    - intros l t IHt r IHr g H; destruct g; simpl in H; [ discriminate | ].
      rewrite !andb_true_iff in H; destruct H as [[Hl Ht] Hr].
      f_equal; auto.
  Qed.

  Definition term_eqb_sound := proj1 eqb_sound_all.

  Lemma contains_size_all :
    (forall t, forall sub, contains sub t = true -> size sub < size t)
    /\ (forall f, forall sub, fields_contain sub f = true -> size sub <= fields_size f).
  Proof.
    apply term_fields_mut.
    - intros a sub H; simpl in H; discriminate.
    - intros f IH sub H; simpl in H; simpl.
      specialize (IH _ H); lia.
    - intros sub H; simpl in H; discriminate.
    - intros l t IHt r IHr sub H; simpl in H; simpl.
      rewrite !orb_true_iff in H; destruct H as [[He | Hc] | Hr].
      + apply term_eqb_sound in He; subst; lia.
      + specialize (IHt _ Hc); lia.
      + specialize (IHr _ Hr); lia.
  Qed.

  Definition contains_decreases := proj1 contains_size_all.

  (* The checker's acceptance order is well founded: any chain of
     recursive unfoldings whose argument the checker accepts is
     finite. This is what admission buys at runtime. *)
  Definition decrease (b a : term) : Prop := contains b a = true.

  Theorem decrease_well_founded : well_founded decrease.
  Proof.
    apply well_founded_lt_compat with (f := size).
    intros x y H; apply contains_decreases; exact H.
  Qed.

End Checker.