heap_lang.v 12.8 KB
Newer Older
1
Require Export program_logic.language prelude.strings.
2
Require Import prelude.gmap.
3

4
5
Module heap_lang.
(** Expressions and vals. *)
6
Definition loc := positive. (* Really, any countable type. *)
Ralf Jung's avatar
Ralf Jung committed
7

8
9
Inductive base_lit : Set :=
  | LitNat (n : nat) | LitBool (b : bool) | LitUnit.
10
11
Notation LitTrue := (LitBool true).
Notation LitFalse := (LitBool false).
12
13
14
15
16
Inductive un_op : Set :=
  | NegOp.
Inductive bin_op : Set :=
  | PlusOp | MinusOp | LeOp | LtOp | EqOp.

Ralf Jung's avatar
Ralf Jung committed
17
Inductive expr :=
18
  (* Base lambda calculus *)
19
20
  | Var (x : string)
  | Rec (f x : string) (e : expr)
21
  | App (e1 e2 : expr)
22
23
  (* Let *)
  | Let (x : string) (e1 e2 : expr)
24
25
26
27
28
  (* Base types and their operations *)
  | Lit (l : base_lit)
  | UnOp (op : un_op) (e : expr)
  | BinOp (op : bin_op) (e1 e2 : expr)
  | If (e0 e1 e2 : expr)
29
30
31
32
33
34
35
  (* Products *)
  | Pair (e1 e2 : expr)
  | Fst (e : expr)
  | Snd (e : expr)
  (* Sums *)
  | InjL (e : expr)
  | InjR (e : expr)
36
  | Case (e0 : expr) (x1 : string) (e1 : expr) (x2 : string) (e2 : expr)
37
38
39
40
41
42
43
44
  (* Concurrency *)
  | Fork (e : expr)
  (* Heap *)
  | Loc (l : loc)
  | Alloc (e : expr)
  | Load (e : expr)
  | Store (e1 : expr) (e2 : expr)
  | Cas (e0 : expr) (e1 : expr) (e2 : expr).
Ralf Jung's avatar
Ralf Jung committed
45

46
Inductive val :=
47
  | RecV (f x : string) (e : expr) (* e should be closed *)
48
  | LitV (l : base_lit)
49
50
51
52
  | PairV (v1 v2 : val)
  | InjLV (v : val)
  | InjRV (v : val)
  | LocV (l : loc).
Ralf Jung's avatar
Ralf Jung committed
53

54
Fixpoint of_val (v : val) : expr :=
Ralf Jung's avatar
Ralf Jung committed
55
  match v with
56
  | RecV f x e => Rec f x e
57
  | LitV l => Lit l
58
59
60
  | PairV v1 v2 => Pair (of_val v1) (of_val v2)
  | InjLV v => InjL (of_val v)
  | InjRV v => InjR (of_val v)
61
  | LocV l => Loc l
Ralf Jung's avatar
Ralf Jung committed
62
  end.
63
Fixpoint to_val (e : expr) : option val :=
64
  match e with
65
  | Rec f x e => Some (RecV f x e)
66
  | Lit l => Some (LitV l)
67
68
69
  | Pair e1 e2 => v1  to_val e1; v2  to_val e2; Some (PairV v1 v2)
  | InjL e => InjLV <$> to_val e
  | InjR e => InjRV <$> to_val e
70
  | Loc l => Some (LocV l)
Ralf Jung's avatar
Ralf Jung committed
71
  | _ => None
72
73
  end.

74
75
(** The state: heaps of vals. *)
Definition state := gmap loc val.
Ralf Jung's avatar
Ralf Jung committed
76

77
(** Evaluation contexts *)
78
79
80
Inductive ectx_item :=
  | AppLCtx (e2 : expr)
  | AppRCtx (v1 : val)
81
  | LetCtx (x : string) (e2 : expr)
82
83
84
85
  | UnOpCtx (op : un_op)
  | BinOpLCtx (op : bin_op) (e2 : expr)
  | BinOpRCtx (op : bin_op) (v1 : val)
  | IfCtx (e1 e2 : expr)
86
87
88
89
90
91
  | PairLCtx (e2 : expr)
  | PairRCtx (v1 : val)
  | FstCtx
  | SndCtx
  | InjLCtx
  | InjRCtx
92
  | CaseCtx (x1 : string) (e1 : expr) (x2 : string) (e2 : expr)
93
94
95
96
97
98
99
  | AllocCtx
  | LoadCtx
  | StoreLCtx (e2 : expr)
  | StoreRCtx (v1 : val)
  | CasLCtx (e1 : expr)  (e2 : expr)
  | CasMCtx (v0 : val) (e2 : expr)
  | CasRCtx (v0 : val) (v1 : val).
100

101
Notation ectx := (list ectx_item).
102

103
Definition fill_item (Ki : ectx_item) (e : expr) : expr :=
104
105
106
  match Ki with
  | AppLCtx e2 => App e e2
  | AppRCtx v1 => App (of_val v1) e
107
  | LetCtx x e2 => Let x e e2
108
109
110
111
  | UnOpCtx op => UnOp op e
  | BinOpLCtx op e2 => BinOp op e e2
  | BinOpRCtx op v1 => BinOp op (of_val v1) e
  | IfCtx e1 e2 => If e e1 e2
112
113
114
115
116
117
  | PairLCtx e2 => Pair e e2
  | PairRCtx v1 => Pair (of_val v1) e
  | FstCtx => Fst e
  | SndCtx => Snd e
  | InjLCtx => InjL e
  | InjRCtx => InjR e
118
  | CaseCtx x1 e1 x2 e2 => Case e x1 e1 x2 e2
119
120
121
122
123
124
125
  | AllocCtx => Alloc e
  | LoadCtx => Load e
  | StoreLCtx e2 => Store e e2
  | StoreRCtx v1 => Store (of_val v1) e
  | CasLCtx e1 e2 => Cas e e1 e2
  | CasMCtx v0 e2 => Cas (of_val v0) e e2
  | CasRCtx v0 v1 => Cas (of_val v0) (of_val v1) e
Ralf Jung's avatar
Ralf Jung committed
126
  end.
127
Definition fill (K : ectx) (e : expr) : expr := fold_right fill_item e K.
Ralf Jung's avatar
Ralf Jung committed
128

129
130
131
132
133
134
135
(** Substitution *)
(** We have [subst e "" v = e] to deal with anonymous binders *)
Fixpoint subst (e : expr) (x : string) (v : val) : expr :=
  match e with
  | Var y => if decide (x = y  x  "") then of_val v else Var y
  | Rec f y e => Rec f y (if decide (x  f  x  y) then subst e x v else e)
  | App e1 e2 => App (subst e1 x v) (subst e2 x v)
136
137
  | Let y e1 e2 =>
     Let y (subst e1 x v) (if decide (x  y) then subst e2 x v else e2)
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
  | Lit l => Lit l
  | UnOp op e => UnOp op (subst e x v)
  | BinOp op e1 e2 => BinOp op (subst e1 x v) (subst e2 x v)
  | If e0 e1 e2 => If (subst e0 x v) (subst e1 x v) (subst e2 x v)
  | Pair e1 e2 => Pair (subst e1 x v) (subst e2 x v)
  | Fst e => Fst (subst e x v)
  | Snd e => Snd (subst e x v)
  | InjL e => InjL (subst e x v)
  | InjR e => InjR (subst e x v)
  | Case e0 x1 e1 x2 e2 =>
     Case (subst e0 x v)
       x1 (if decide (x  x1) then subst e1 x v else e1)
       x2 (if decide (x  x2) then subst e2 x v else e2)
  | Fork e => Fork (subst e x v)
  | Loc l => Loc l
  | Alloc e => Alloc (subst e x v)
  | Load e => Load (subst e x v)
  | Store e1 e2 => Store (subst e1 x v) (subst e2 x v)
  | Cas e0 e1 e2 => Cas (subst e0 x v) (subst e1 x v) (subst e2 x v)
  end.

159
(** The stepping relation *)
160
161
Definition un_op_eval (op : un_op) (l : base_lit) : option base_lit :=
  match op, l with
162
  | NegOp, LitBool b => Some (LitBool (negb b))
163
164
165
166
167
  | _, _ => None
  end.

Definition bin_op_eval (op : bin_op) (l1 l2 : base_lit) : option base_lit :=
  match op, l1, l2 with
168
169
170
171
172
  | PlusOp, LitNat n1, LitNat n2 => Some (LitNat (n1 + n2))
  | MinusOp, LitNat n1, LitNat n2 => Some (LitNat (n1 - n2))
  | LeOp, LitNat n1, LitNat n2 => Some (LitBool (bool_decide (n1  n2)))
  | LtOp, LitNat n1, LitNat n2 => Some (LitBool (bool_decide (n1 < n2)))
  | EqOp, LitNat n1, LitNat n2 => Some (LitBool (bool_decide (n1 = n2)))
173
174
175
  | _, _, _ => None
  end.

176
Inductive head_step : expr -> state -> expr -> state -> option expr -> Prop :=
177
  | BetaS f x e1 e2 v2 σ :
178
     to_val e2 = Some v2 
179
180
     head_step (App (Rec f x e1) e2) σ
       (subst (subst e1 f (RecV f x e1)) x v2) σ None
181
182
183
  | DeltaS x e1 e2 v1 σ :
     to_val e1 = Some v1 
     head_step (Let x e1 e2) σ (subst e2 x v1) σ None
184
  | UnOpS op l l' σ :
185
186
     un_op_eval op l = Some l'  
     head_step (UnOp op (Lit l)) σ (Lit l') σ None
187
  | BinOpS op l1 l2 l' σ :
188
189
190
     bin_op_eval op l1 l2 = Some l'  
     head_step (BinOp op (Lit l1) (Lit l2)) σ (Lit l') σ None
  | IfTrueS e1 e2 σ :
191
     head_step (If (Lit LitTrue) e1 e2) σ e1 σ None
192
  | IfFalseS e1 e2 σ :
193
     head_step (If (Lit LitFalse) e1 e2) σ e2 σ None
194
195
196
197
198
199
  | FstS e1 v1 e2 v2 σ :
     to_val e1 = Some v1  to_val e2 = Some v2 
     head_step (Fst (Pair e1 e2)) σ e1 σ None
  | SndS e1 v1 e2 v2 σ :
     to_val e1 = Some v1  to_val e2 = Some v2 
     head_step (Snd (Pair e1 e2)) σ e2 σ None
200
  | CaseLS e0 v0 x1 e1 x2 e2 σ :
201
     to_val e0 = Some v0 
202
203
     head_step (Case (InjL e0) x1 e1 x2 e2) σ (subst e1 x1 v0) σ None
  | CaseRS e0 v0 x1 e1 x2 e2 σ :
204
     to_val e0 = Some v0 
205
     head_step (Case (InjR e0) x1 e1 x2 e2) σ (subst e2 x2 v0) σ None
206
  | ForkS e σ:
207
     head_step (Fork e) σ (Lit LitUnit) σ (Some e)
208
209
210
211
212
213
214
215
  | AllocS e v σ l :
     to_val e = Some v  σ !! l = None 
     head_step (Alloc e) σ (Loc l) (<[l:=v]>σ) None
  | LoadS l v σ :
     σ !! l = Some v 
     head_step (Load (Loc l)) σ (of_val v) σ None
  | StoreS l e v σ :
     to_val e = Some v  is_Some (σ !! l) 
216
     head_step (Store (Loc l) e) σ (Lit LitUnit) (<[l:=v]>σ) None
217
218
219
  | CasFailS l e1 v1 e2 v2 vl σ :
     to_val e1 = Some v1  to_val e2 = Some v2 
     σ !! l = Some vl  vl  v1 
220
     head_step (Cas (Loc l) e1 e2) σ (Lit LitFalse) σ None
221
222
223
  | CasSucS l e1 v1 e2 v2 σ :
     to_val e1 = Some v1  to_val e2 = Some v2 
     σ !! l = Some v1 
224
     head_step (Cas (Loc l) e1 e2) σ (Lit LitTrue) (<[l:=v2]>σ) None.
Ralf Jung's avatar
Ralf Jung committed
225

226
(** Atomic expressions *)
227
Definition atomic (e: expr) : Prop :=
228
229
230
231
232
233
234
  match e with
  | Alloc e => is_Some (to_val e)
  | Load e => is_Some (to_val e)
  | Store e1 e2 => is_Some (to_val e1)  is_Some (to_val e2)
  | Cas e0 e1 e2 => is_Some (to_val e0)  is_Some (to_val e1)  is_Some (to_val e2)
  | _ => False
  end.
235

236
237
238
239
(** Close reduction under evaluation contexts.
We could potentially make this a generic construction. *)
Inductive prim_step
    (e1 : expr) (σ1 : state) (e2 : expr) (σ2: state) (ef: option expr) : Prop :=
240
  Ectx_step K e1' e2' :
241
242
243
244
245
246
    e1 = fill K e1'  e2 = fill K e2' 
    head_step e1' σ1 e2' σ2 ef  prim_step e1 σ1 e2 σ2 ef.

(** Basic properties about the language *)
Lemma to_of_val v : to_val (of_val v) = Some v.
Proof. by induction v; simplify_option_equality. Qed.
247

248
Lemma of_to_val e v : to_val e = Some v  of_val v = e.
249
Proof.
250
  revert v; induction e; intros; simplify_option_equality; auto with f_equal.
251
Qed.
252

253
254
Instance: Injective (=) (=) of_val.
Proof. by intros ?? Hv; apply (injective Some); rewrite -!to_of_val Hv. Qed.
255

256
Instance fill_item_inj Ki : Injective (=) (=) (fill_item Ki).
257
Proof. destruct Ki; intros ???; simplify_equality'; auto with f_equal. Qed.
258

259
260
Instance ectx_fill_inj K : Injective (=) (=) (fill K).
Proof. red; induction K as [|Ki K IH]; naive_solver. Qed.
261

262
263
Lemma fill_app K1 K2 e : fill (K1 ++ K2) e = fill K1 (fill K2 e).
Proof. revert e; induction K1; simpl; auto with f_equal. Qed.
264

265
Lemma fill_val K e : is_Some (to_val (fill K e))  is_Some (to_val e).
266
Proof.
267
268
  intros [v' Hv']; revert v' Hv'.
  induction K as [|[]]; intros; simplify_option_equality; eauto.
269
Qed.
270

271
272
Lemma fill_not_val K e : to_val e = None  to_val (fill K e) = None.
Proof. rewrite !eq_None_not_Some; eauto using fill_val. Qed.
273

274
275
276
Lemma values_head_stuck e1 σ1 e2 σ2 ef :
  head_step e1 σ1 e2 σ2 ef  to_val e1 = None.
Proof. destruct 1; naive_solver. Qed.
277

278
279
Lemma values_stuck e1 σ1 e2 σ2 ef : prim_step e1 σ1 e2 σ2 ef  to_val e1 = None.
Proof. intros [??? -> -> ?]; eauto using fill_not_val, values_head_stuck. Qed.
280

281
282
Lemma atomic_not_val e : atomic e  to_val e = None.
Proof. destruct e; naive_solver. Qed.
283

284
Lemma atomic_fill K e : atomic (fill K e)  to_val e = None  K = [].
285
Proof.
286
287
  rewrite eq_None_not_Some.
  destruct K as [|[]]; naive_solver eauto using fill_val.
288
Qed.
289

290
291
292
Lemma atomic_head_step e1 σ1 e2 σ2 ef :
  atomic e1  head_step e1 σ1 e2 σ2 ef  is_Some (to_val e2).
Proof. destruct 2; simpl; rewrite ?to_of_val; naive_solver. Qed.
293

294
295
Lemma atomic_step e1 σ1 e2 σ2 ef :
  atomic e1  prim_step e1 σ1 e2 σ2 ef  is_Some (to_val e2).
296
Proof.
297
298
299
  intros Hatomic [K e1' e2' -> -> Hstep].
  assert (K = []) as -> by eauto 10 using atomic_fill, values_head_stuck.
  naive_solver eauto using atomic_head_step.
Ralf Jung's avatar
Ralf Jung committed
300
Qed.
301

302
Lemma head_ctx_step_val Ki e σ1 e2 σ2 ef :
303
  head_step (fill_item Ki e) σ1 e2 σ2 ef  is_Some (to_val e).
304
Proof. destruct Ki; inversion_clear 1; simplify_option_equality; eauto. Qed.
305

306
Lemma fill_item_no_val_inj Ki1 Ki2 e1 e2 :
307
  to_val e1 = None  to_val e2 = None 
308
  fill_item Ki1 e1 = fill_item Ki2 e2  Ki1 = Ki2.
309
Proof.
310
  destruct Ki1, Ki2; intros; try discriminate; simplify_equality';
311
    repeat match goal with
312
313
    | H : to_val (of_val _) = None |- _ => by rewrite to_of_val in H
    end; auto.
Ralf Jung's avatar
Ralf Jung committed
314
Qed.
315

316
317
318
319
320
321
(* When something does a step, and another decomposition of the same expression
has a non-val [e] in the hole, then [K] is a left sub-context of [K'] - in
other words, [e] also contains the reducible expression *)
Lemma step_by_val K K' e1 e1' σ1 e2 σ2 ef :
  fill K e1 = fill K' e1'  to_val e1 = None  head_step e1' σ1 e2 σ2 ef 
  K `prefix_of` K'.
322
Proof.
323
324
325
  intros Hfill Hred Hnval; revert K' Hfill.
  induction K as [|Ki K IH]; simpl; intros K' Hfill; auto using prefix_of_nil.
  destruct K' as [|Ki' K']; simplify_equality'.
Ralf Jung's avatar
Ralf Jung committed
326
  { exfalso; apply (eq_None_not_Some (to_val (fill K e1)));
327
328
      eauto using fill_not_val, head_ctx_step_val. }
  cut (Ki = Ki'); [naive_solver eauto using prefix_of_cons|].
329
  eauto using fill_item_no_val_inj, values_head_stuck, fill_not_val.
330
Qed.
331

332
333
334
Lemma alloc_fresh e v σ :
  let l := fresh (dom _ σ) in
  to_val e = Some v  head_step (Alloc e) σ (Loc l) (<[l:=v]>σ) None.
335
Proof. by intros; apply AllocS, (not_elem_of_dom (D:=gset _)), is_fresh. Qed.
336

337
338
Lemma subst_empty e v : subst e "" v = e.
Proof. induction e; simpl; repeat case_decide; intuition auto with f_equal. Qed.
339
340
341
342
343
344
345
346
347
348
End heap_lang.

(** Language *)
Program Canonical Structure heap_lang : language := {|
  expr := heap_lang.expr; val := heap_lang.val; state := heap_lang.state;
  of_val := heap_lang.of_val; to_val := heap_lang.to_val;
  atomic := heap_lang.atomic; prim_step := heap_lang.prim_step;
|}.
Solve Obligations with eauto using heap_lang.to_of_val, heap_lang.of_to_val,
  heap_lang.values_stuck, heap_lang.atomic_not_val, heap_lang.atomic_step.
349

350
Global Instance heap_lang_ctx K : LanguageCtx heap_lang (heap_lang.fill K).
351
Proof.
352
353
  split.
  * eauto using heap_lang.fill_not_val.
354
  * intros ????? [K' e1' e2' Heq1 Heq2 Hstep].
355
    by exists (K ++ K') e1' e2'; rewrite ?heap_lang.fill_app ?Heq1 ?Heq2.
356
  * intros e1 σ1 e2 σ2 ? Hnval [K'' e1'' e2'' Heq1 -> Hstep].
357
358
359
    destruct (heap_lang.step_by_val
      K K'' e1 e1'' σ1 e2'' σ2 ef) as [K' ->]; eauto.
    rewrite heap_lang.fill_app in Heq1; apply (injective _) in Heq1.
Ralf Jung's avatar
Ralf Jung committed
360
    exists (heap_lang.fill K' e2''); rewrite heap_lang.fill_app; split; auto.
361
    econstructor; eauto.
362
Qed.
363
364
365
366
367
368
369

Global Instance heap_lang_ctx_item Ki :
  LanguageCtx heap_lang (heap_lang.fill_item Ki).
Proof.
  change (LanguageCtx heap_lang (heap_lang.fill [Ki])).
  by apply _.
Qed.