aboutsummaryrefslogtreecommitdiffstats
path: root/expr.v
diff options
context:
space:
mode:
authorLibravatar Rutger Broekhoff2024-06-26 20:50:18 +0200
committerLibravatar Rutger Broekhoff2024-06-26 20:50:18 +0200
commit73df1945b31c0beee88cf4476df4ccd09d31403b (patch)
treeed00db26b711442e643f38b66888a3df56e33ebd /expr.v
downloadmininix-formalization-73df1945b31c0beee88cf4476df4ccd09d31403b.tar.gz
mininix-formalization-73df1945b31c0beee88cf4476df4ccd09d31403b.zip
Import Coq project
Diffstat (limited to 'expr.v')
-rw-r--r--expr.v250
1 files changed, 250 insertions, 0 deletions
diff --git a/expr.v b/expr.v
new file mode 100644
index 0000000..11c0737
--- /dev/null
+++ b/expr.v
@@ -0,0 +1,250 @@
1Require Import Coq.Strings.String.
2From stdpp Require Import gmap.
3
4(* The Nix Expression Language *)
5
6(** Selected operators from Dolsta and Löh, 2008. Newer definitions at
7 https://nixos.org/manual/nix/stable/language/operators *)
8Variant op : Type :=
9 | O_Eq (* = *)
10 | O_Lt (* < *)
11 | O_Plus (* + *)
12 | O_Min (* - *)
13 | O_Div (* / *)
14 | O_Upd. (* // *)
15
16Hint Constructors op : core.
17
18Variant nonempty A := Ne_Cons (head : A) (tail : list A).
19Arguments Ne_Cons {A} _ _.
20Hint Constructors nonempty : core.
21
22Inductive expr : Type :=
23 | X_V (v : value) (* v *)
24 | X_Id (x : string) (* x *)
25 | X_Attrset (bs : gmap string b_rhs) (* { bᵣ* } *)
26 | X_LetBinding (bs : gmap string b_rhs) (e : expr) (* let bᵣ* in e *)
27 | X_Select (e : expr) (xs : nonempty string) (* e.xs *)
28 | X_SelectOr (e : expr) (xs : nonempty string) (or : expr) (* e.xs or e *)
29 | X_Apply (e1 e2 : expr) (* e1 e2 *)
30 | X_Cond (e1 e2 e3 : expr) (* if e1 then e2 else e3 *)
31 | X_Incl (e1 e2 : expr) (* with e1; e2 *)
32 | X_Assert (e1 e2 : expr) (* assert e1; e2 *)
33 | X_Op (op : op) (e1 e2 : expr) (* e1 <op> e2 *)
34 | X_HasAttr (e1 : expr) (x : string) (* e ? x *)
35 | X_Force (e : expr) (* force e *)
36 | X_Closed (e : expr) (* closed(e) *)
37 | X_Placeholder (x : string) (e : expr) (* placeholderₓ(e) *)
38with b_rhs :=
39 | B_Rec (e : expr) (* := e *)
40 | B_Nonrec (e : expr) (* :=ᵣ e *)
41with matcher :=
42 | M_Matcher (ms : gmap string m_rhs) (strict : bool)
43with m_rhs :=
44 | M_Mandatory
45 | M_Optional (e : expr) (* ? e *)
46with value :=
47 | V_Bool (p : bool) : value (* true | false *)
48 | V_Null : value (* null *)
49 | V_Int (n : Z) : value (* n *)
50 | V_Str (s : string) : value (* s *)
51 | V_Fn (x : string) (e : expr) : value (* x: e *)
52 | V_AttrsetFn (m : matcher) (e : expr) : value (* { m }: e *)
53 | V_Attrset (bs : gmap string expr) : value. (* { b* } *)
54
55Hint Constructors expr : core.
56
57Instance Maybe_X_Attrset : Maybe X_Attrset := λ e,
58 match e with
59 | X_Attrset bs => Some bs
60 | _ => None
61 end.
62
63Instance Maybe_B_Nonrec : Maybe B_Nonrec := λ rhs,
64 match rhs with
65 | B_Nonrec e => Some e
66 | _ => None
67 end.
68
69Instance Maybe_B_Rec : Maybe B_Rec := λ rhs,
70 match rhs with
71 | B_Rec e => Some e
72 | _ => None
73 end.
74
75Lemma maybe_b_rhs_excl b :
76 is_Some (maybe B_Nonrec b) → is_Some (maybe B_Rec b) → False.
77Proof. intros [e2 Hnonrec] [e1 Hrec]. simplify_option_eq. Qed.
78
79Lemma no_b_nonrec__b_rec b :
80 ¬ is_Some (maybe B_Nonrec b) → is_Some (maybe B_Rec b).
81Proof.
82 destruct b; try by eauto.
83 simplify_eq/=. intros contra. apply is_Some_alt. eauto.
84Qed.
85
86Lemma no_b_rec__b_nonrec b :
87 ¬ is_Some (maybe B_Rec b) → is_Some (maybe B_Nonrec b).
88Proof.
89 destruct b; try by eauto.
90 simplify_eq/=. intros contra. apply is_Some_alt. eauto.
91Qed.
92
93Instance Maybe_V_Attrset : Maybe V_Attrset := λ e,
94 match e with
95 | V_Attrset bs => Some bs
96 | _ => None
97 end.
98
99Instance Maybe_V_Bool : Maybe V_Bool := λ e,
100 match e with
101 | V_Bool p => Some p
102 | _ => None
103 end.
104
105Global Instance B_Nonrec_inj : Inj (=) (=) B_Nonrec.
106Proof. intros [] [] ?; by simplify_eq. Qed.
107
108Definition matcher_keys (m : matcher) : gset string :=
109 match m with M_Matcher ms _ => dom ms end.
110
111Definition matcher_map (f : expr → expr) (m : matcher) : matcher :=
112 let map_m_rhs := λ rhs,
113 match rhs with
114 | M_Optional e => M_Optional (f e)
115 | _ => rhs
116 end in
117 match m with
118 | M_Matcher ms strict => M_Matcher (map_m_rhs <$> ms) strict
119 end.
120
121Local Definition map_delete_all {K V} `{Countable K}
122 (ks : gset K) (m : gmap K V) : gmap K V :=
123 set_fold (λ k m', map_delete k m') m ks.
124
125Local Definition b_rhs_map (f g : expr → expr) (rhs : b_rhs) : b_rhs :=
126 match rhs with
127 | B_Rec e => B_Rec (f e)
128 | B_Nonrec e => B_Nonrec (g e)
129 end.
130
131(* See Dolstra (2006), §4.3.3 and fig. 4.6 (p. 75, PDF: p. 83) *)
132Fixpoint subst (subs : gmap string expr) (e : expr) : expr :=
133 let msubst subs' := b_rhs_map (subst subs') (subst subs) in
134 match e with
135 | X_V V_Null | X_V (V_Bool _) | X_V (V_Str _) | X_V (V_Int _) => e
136 | X_Id x | X_Placeholder x _ => default e (subs !! x)
137 | X_Attrset bs =>
138 let subs' := map_delete_all (dom bs) subs in
139 X_Attrset (msubst subs' <$> bs)
140 | X_V (V_Attrset bs) =>
141 X_V (V_Attrset (subst subs <$> bs))
142 | X_LetBinding bs e' =>
143 let subs' := map_delete_all (dom bs) subs in
144 X_LetBinding (msubst subs' <$> bs) (subst subs' e')
145 | X_Select e' x => X_Select (subst subs e') x
146 | X_SelectOr e' x or => X_SelectOr (subst subs e') x (subst subs or)
147 | X_V (V_Fn x e') =>
148 let subs' := map_delete x subs in
149 X_V (V_Fn x (subst subs' e'))
150 | X_V (V_AttrsetFn (M_Matcher ms _ as m) e') =>
151 let subs' := map_delete_all (matcher_keys m) subs in
152 X_V (V_AttrsetFn (matcher_map (subst subs') m) (subst subs' e'))
153 | X_Apply e1 e2 => X_Apply (subst subs e1) (subst subs e2)
154 | X_Cond e1 e2 e3 => X_Cond (subst subs e1) (subst subs e2) (subst subs e3)
155 | X_Incl e1 e2 => X_Incl (subst subs e1) (subst subs e2)
156 | X_Op op e1 e2 => X_Op op (subst subs e1) (subst subs e2)
157 | X_HasAttr e x => X_HasAttr (subst subs e) x
158 | X_Assert e1 e2 => X_Assert (subst subs e1) (subst subs e2)
159 | X_Closed e => X_Closed e
160 | X_Force e => X_Force (subst subs e)
161 end.
162
163Definition closed (bs : gmap string expr) : gmap string expr :=
164 X_Closed <$> bs.
165
166Definition placeholders (bs : gmap string expr) : gmap string expr :=
167 map_imap (λ (x : string) (e : expr), Some (X_Placeholder x e)) bs.
168
169Definition nonempty_singleton {A} (a : A): nonempty A := Ne_Cons a nil.
170
171Definition nonempty_cons {A} (a : A) (l : nonempty A) : nonempty A :=
172 match l with Ne_Cons head tail => Ne_Cons a (head :: tail) end.
173
174Definition indirect (bs : gmap string b_rhs) : gmap string expr :=
175 map_imap (λ (x : string) (rhs : b_rhs),
176 Some (X_Select (X_Attrset bs) (nonempty_singleton x))) bs.
177
178Definition rec_subst (bs : gmap string b_rhs) : gmap string expr :=
179 let subs := indirect bs
180 in (λ b, match b with
181 | B_Rec e => subst (closed subs) e
182 | B_Nonrec e => e
183 end) <$> bs.
184
185Inductive strong_value : Type :=
186 | SV_Bool (b : bool)
187 | SV_Null
188 | SV_Int (n : Z)
189 | SV_Str (s : string)
190 | SV_Fn (x : string) (e : expr)
191 | SV_AttrsetFn (m : matcher) (e : expr)
192 | SV_Attrset (bs : gmap string strong_value).
193
194Fixpoint value_from_strong_value (sv : strong_value) : value :=
195 match sv with
196 | SV_Null => V_Null
197 | SV_Bool b => V_Bool b
198 | SV_Int n => V_Int n
199 | SV_Str s => V_Str s
200 | SV_Fn x e => V_Fn x e
201 | SV_AttrsetFn m e => V_AttrsetFn m e
202 | SV_Attrset bs => V_Attrset (X_V ∘ value_from_strong_value <$> bs)
203 end.
204
205Global Instance X_V_inj : Inj (=) (=) X_V.
206Proof. intros [] [] ?; by simplify_eq. Qed.
207
208Definition expr_from_strong_value : strong_value → expr :=
209 X_V ∘ value_from_strong_value.
210
211(* Based on the fin_maps test from stdpp *)
212Fixpoint sv_size (sv : strong_value) : nat :=
213 match sv with
214 | SV_Null | SV_Bool _ | SV_Int _ | SV_Str _
215 | SV_Fn _ _ | SV_AttrsetFn _ _ => 1
216 | SV_Attrset bs => S (map_fold (λ _ sv', plus (sv_size sv')) 0 bs)
217 end.
218
219(* Based on the fin_maps test from stdpp *)
220Lemma strong_value_ind' :
221 ∀ P : strong_value → Prop,
222 P SV_Null →
223 (∀ b : bool, P (SV_Bool b)) →
224 (∀ n : Z, P (SV_Int n)) →
225 (∀ s : string, P (SV_Str s)) →
226 (∀ (x : string) (e : expr), P (SV_Fn x e)) →
227 (∀ (m : matcher) (e : expr), P (SV_AttrsetFn m e)) →
228 (∀ bs : gmap string strong_value,
229 map_Forall (λ i, P) bs → P (SV_Attrset bs)) →
230 ∀ s : strong_value, P s.
231Proof.
232 intros P PNull PBool PInt PStr PFn PAttrsetFn PAttrset sv.
233 remember (sv_size sv) as n eqn:Hn. revert sv Hn.
234 induction (lt_wf n) as [n _ IH]; intros [| | | | | | bs] ->; simpl in *; try done.
235 apply PAttrset. revert bs IH.
236 apply (map_fold_ind (λ r bs, (∀ n', n' < S r → _) → map_Forall (λ _, P) bs)).
237 - intros IH. apply map_Forall_empty.
238 - intros k sv bs r ? IHbs IHsv. apply map_Forall_insert; [done|]. split.
239 + eapply IHsv; [|done]; lia.
240 + eapply IHbs. intros; eapply IHsv; [|done]; lia.
241Qed.
242
243Coercion X_Id : string >-> expr.
244Coercion V_Int : Z >-> value.
245(* Leaving this out for now: would conflict with X_Id and
246 therefore cause ambiguity *)
247(* Coercion X_StrVal : string >-> expr. *)
248Coercion V_Bool : bool >-> value.
249Coercion X_V : value >-> expr.
250Coercion value_from_strong_value : strong_value >-> value.