diff options
Diffstat (limited to 'interpreter.v')
-rw-r--r-- | interpreter.v | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/interpreter.v b/interpreter.v new file mode 100644 index 0000000..c701b42 --- /dev/null +++ b/interpreter.v | |||
@@ -0,0 +1,103 @@ | |||
1 | Require Import Coq.Strings.String. | ||
2 | From stdpp Require Import fin_maps. | ||
3 | From mininix Require Import binop expr maptools matching. | ||
4 | |||
5 | Open Scope string_scope. | ||
6 | |||
7 | Definition eval1 (go : bool → expr → option value) | ||
8 | (uf : bool) (d : expr) : option value := | ||
9 | match d with | ||
10 | | X_Id _ => None | ||
11 | | X_Force e => go true e | ||
12 | | X_Closed e => go uf e | ||
13 | | X_Placeholder x e => go uf e | ||
14 | | X_V (V_Attrset bs) => | ||
15 | if uf | ||
16 | then vs' ← map_mapM (go true) bs; | ||
17 | Some (V_Attrset (X_V <$> vs')) | ||
18 | else Some (V_Attrset bs) | ||
19 | | X_V v => Some v | ||
20 | | X_Attrset bs => go uf (V_Attrset (rec_subst bs)) | ||
21 | | X_LetBinding bs e => | ||
22 | let e' := subst (closed (rec_subst bs)) e | ||
23 | in go uf e' | ||
24 | | X_Select e (Ne_Cons x ys) => | ||
25 | v' ← go false e; | ||
26 | bs ← maybe V_Attrset v'; | ||
27 | e'' ← bs !! x; | ||
28 | match ys with | ||
29 | | [] => go uf e'' | ||
30 | | y :: ys => go uf (X_Select e'' (Ne_Cons y ys)) | ||
31 | end | ||
32 | | X_SelectOr e (Ne_Cons x ys) or => | ||
33 | v' ← go false e; | ||
34 | bs ← maybe V_Attrset v'; | ||
35 | match bs !! x with | ||
36 | | Some e'' => | ||
37 | match ys with | ||
38 | | [] => go uf e'' | ||
39 | | y :: ys => go uf (X_SelectOr e'' (Ne_Cons y ys) or) | ||
40 | end | ||
41 | | None => go uf or | ||
42 | end | ||
43 | | X_Apply e1 e2 => | ||
44 | v1' ← go false e1; | ||
45 | match v1' with | ||
46 | | V_Fn x e => | ||
47 | let e' := subst {[x := X_Closed e2]} e | ||
48 | in go uf e' | ||
49 | | V_AttrsetFn m e => | ||
50 | v2' ← go false e2; | ||
51 | bs ← maybe V_Attrset v2'; | ||
52 | bs' ← matches m bs; | ||
53 | go uf (X_LetBinding bs' e) | ||
54 | | V_Attrset bs => | ||
55 | f ← bs !! "__functor"; | ||
56 | go uf (X_Apply (X_Apply f (V_Attrset bs)) e2) | ||
57 | | _ => None | ||
58 | end | ||
59 | | X_Cond e1 e2 e3 => | ||
60 | v1' ← go false e1; | ||
61 | b ← maybe V_Bool v1'; | ||
62 | go uf (if b : bool then e2 else e3) | ||
63 | | X_Incl e1 e2 => | ||
64 | v1' ← go false e1; | ||
65 | match v1' with | ||
66 | | V_Attrset bs => go uf (subst (placeholders bs) e2) | ||
67 | | _ => go uf e2 | ||
68 | end | ||
69 | | X_Op op e1 e2 => | ||
70 | e1' ← go false e1; | ||
71 | e2' ← go false e2; | ||
72 | v' ← binop_eval op e1' e2'; | ||
73 | go uf (X_V v') | ||
74 | | X_HasAttr e x => | ||
75 | v' ← go false e; | ||
76 | Some $ V_Bool $ | ||
77 | match v' with | ||
78 | | V_Attrset bs => | ||
79 | bool_decide (is_Some (bs !! x)) | ||
80 | | _ => false | ||
81 | end | ||
82 | | X_Assert e1 e2 => | ||
83 | v1' ← go false e1; | ||
84 | match v1' with | ||
85 | | V_Bool true => go uf e2 | ||
86 | | _ => None | ||
87 | end | ||
88 | end. | ||
89 | |||
90 | Fixpoint eval (n : nat) (uf : bool) (e : expr) : option value := | ||
91 | match n with | ||
92 | | O => None | ||
93 | | S n => eval1 (eval n) uf e | ||
94 | end. | ||
95 | |||
96 | (* Don't automatically 'simplify' eval: this can lead to very complicated | ||
97 | assumptions and goals. Instead, we define our own lemma which can be used | ||
98 | to unfold eval once. This allows us to write proofs in a much more | ||
99 | controlled manner, and we can still leverage tactics like simplify_option_eq | ||
100 | without everything blowing up uncontrollably *) | ||
101 | Global Opaque eval. | ||
102 | Lemma eval_S n : eval (S n) = eval1 (eval n). | ||
103 | Proof. done. Qed. | ||