|
1 | 1 |
|
2 | 2 | import Juvix.Core.Main.Language
|
| 3 | +import Mathlib.Tactic.CC |
3 | 4 |
|
4 | 5 | namespace Juvix.Core.Main
|
5 | 6 |
|
6 |
| -def f : Expr -> Expr := λ e => |
7 |
| - match e with |
8 |
| - | Expr.lambda (body := e) => e |
9 |
| - | _ => Expr.lambda (body := e) |
| 7 | +def eval_binop_int (op : BinaryOp) (i₁ i₂ : Int) : Int := |
| 8 | + match op with |
| 9 | + | BinaryOp.add_int => i₁ + i₂ |
| 10 | + | BinaryOp.sub_int => i₁ - i₂ |
| 11 | + | BinaryOp.mul_int => i₁ * i₂ |
| 12 | + | BinaryOp.div_int => i₁ / i₂ |
| 13 | + |
| 14 | +inductive Eval (P : Program) : Context → Expr → Value → Prop where |
| 15 | + | eval_var {ctx idx val} : |
| 16 | + ctx.get? idx = some val → |
| 17 | + Eval P ctx (Expr.var idx) val |
| 18 | + | eval_ident {ctx name expr val} : |
| 19 | + P.defs.find? name = some expr → |
| 20 | + Eval P [] expr val → |
| 21 | + Eval P ctx (Expr.ident name) val |
| 22 | + | eval_const {ctx c} : |
| 23 | + Eval P ctx (Expr.const c) (Value.const c) |
| 24 | + | eval_app {ctx ctx' f body arg val val'} : |
| 25 | + Eval P ctx f (Value.closure ctx' body) → |
| 26 | + Eval P ctx arg val → |
| 27 | + Eval P (val :: ctx') body val' → |
| 28 | + Eval P ctx (Expr.app f arg) val' |
| 29 | + | eval_constr_app {ctx ctr ctr_name ctr_args_rev arg val} : |
| 30 | + Eval P ctx ctr (Value.constr_app ctr_name ctr_args_rev) → |
| 31 | + Eval P ctx arg val → |
| 32 | + Eval P ctx (Expr.constr_app ctr arg) (Value.constr_app ctr_name (val :: ctr_args_rev)) |
| 33 | + | eval_binop {ctx op arg₁ arg₂ val₁ val₂} : |
| 34 | + Eval P ctx arg₁ (Value.const (Constant.int val₁)) → |
| 35 | + Eval P ctx arg₂ (Value.const (Constant.int val₂)) → |
| 36 | + Eval P ctx (Expr.binop op arg₁ arg₂) (Value.const (Constant.int (eval_binop_int op val₁ val₂))) |
| 37 | + | eval_lambda {ctx body} : |
| 38 | + Eval P ctx (Expr.lambda body) (Value.closure ctx body) |
| 39 | + | eval_save {ctx value body val val'} : |
| 40 | + Eval P ctx value val → |
| 41 | + Eval P (val :: ctx) body val' → |
| 42 | + Eval P ctx (Expr.save value body) val' |
| 43 | + | eval_branch_matches {ctx name args_rev body val} : |
| 44 | + Eval P (args_rev ++ ctx) body val → |
| 45 | + Eval P (Value.constr_app name args_rev :: ctx) (Expr.branch name body _) val |
| 46 | + | eval_branch_fails {ctx name name' next val} : |
| 47 | + name ≠ name' → |
| 48 | + Eval P ctx next val → |
| 49 | + Eval P (Value.constr_app name _ :: ctx) (Expr.branch name' _ next) val |
| 50 | + | eval_default {ctx body val} : |
| 51 | + Eval P ctx body val → |
| 52 | + Eval P (_ :: ctx) (Expr.default body) val |
| 53 | + | eval_unit {ctx} : |
| 54 | + Eval P ctx Expr.unit Value.unit |
| 55 | + |
| 56 | +notation "[" P "] " ctx " ⊢ " e " ↦ " v:40 => Eval P ctx e v |
| 57 | + |
| 58 | +-- The evaluation relation is deterministic. |
| 59 | +theorem Eval.deterministic {P ctx e v₁ v₂} (h₁ : [P] ctx ⊢ e ↦ v₁) (h₂ : [P] ctx ⊢ e ↦ v₂) : v₁ = v₂ := by |
| 60 | + induction h₁ generalizing v₂ with |
| 61 | + | eval_var => |
| 62 | + cases h₂ <;> cc |
| 63 | + | eval_ident _ _ ih => |
| 64 | + specialize (@ih v₂) |
| 65 | + cases h₂ <;> cc |
| 66 | + | eval_const => |
| 67 | + cases h₂ <;> cc |
| 68 | + | eval_app _ _ _ ih ih' aih => |
| 69 | + cases h₂ with |
| 70 | + | eval_app hval harg => |
| 71 | + apply aih |
| 72 | + specialize (ih hval) |
| 73 | + specialize (ih' harg) |
| 74 | + simp_all |
| 75 | + | eval_constr_app _ _ ih ih' => |
| 76 | + cases h₂ with |
| 77 | + | eval_constr_app hctr harg => |
| 78 | + specialize (ih hctr) |
| 79 | + specialize (ih' harg) |
| 80 | + simp_all |
| 81 | + | eval_binop _ _ ih₁ ih₂ => |
| 82 | + cases h₂ with |
| 83 | + | eval_binop h₁ h₂ => |
| 84 | + specialize (ih₁ h₁) |
| 85 | + specialize (ih₂ h₂) |
| 86 | + simp_all |
| 87 | + | eval_lambda => |
| 88 | + cases h₂ <;> cc |
| 89 | + | eval_save _ _ ih ih' => |
| 90 | + cases h₂ with |
| 91 | + | eval_save hval hbody => |
| 92 | + specialize (ih hval) |
| 93 | + rw [<- ih] at hbody |
| 94 | + specialize (ih' hbody) |
| 95 | + simp_all |
| 96 | + | eval_branch_matches _ ih => |
| 97 | + specialize (@ih v₂) |
| 98 | + cases h₂ <;> cc |
| 99 | + | eval_branch_fails _ _ ih => |
| 100 | + specialize (@ih v₂) |
| 101 | + cases h₂ <;> cc |
| 102 | + | eval_default _ ih => |
| 103 | + specialize (@ih v₂) |
| 104 | + cases h₂ <;> cc |
| 105 | + | eval_unit => |
| 106 | + cases h₂ <;> cc |
| 107 | + |
| 108 | +-- The termination predicate for values. It is too strong for higher-order |
| 109 | +-- functions -- requires termination for all function arguments, even |
| 110 | +-- non-terminating ones. |
| 111 | +inductive Value.Terminating (P : Program) : Value → Prop where |
| 112 | + | const {c} : Value.Terminating P (Value.const c) |
| 113 | + | constr_app {ctr_name args_rev} : |
| 114 | + Value.Terminating P (Value.constr_app ctr_name args_rev) |
| 115 | + | closure {ctx body} : |
| 116 | + (∀ v v', |
| 117 | + [P] v :: ctx ⊢ body ↦ v' → |
| 118 | + Value.Terminating P v') → |
| 119 | + Value.Terminating P (Value.closure ctx body) |
| 120 | + | unit : Value.Terminating P Value.unit |
| 121 | + |
| 122 | +def Expr.Terminating (P : Program) (ctx : Context) (e : Expr) : Prop := |
| 123 | + (∃ v, [P] ctx ⊢ e ↦ v ∧ Value.Terminating P v) |
| 124 | + |
| 125 | +def Program.Terminating (P : Program) : Prop := |
| 126 | + Expr.Terminating P [] P.main |
| 127 | + |
| 128 | +lemma Eval.Expr.Terminating {P ctx e v} : |
| 129 | + Expr.Terminating P ctx e → [P] ctx ⊢ e ↦ v → Value.Terminating P v := by |
| 130 | + intro h₁ h₂ |
| 131 | + rcases h₁ with ⟨v', hval, hterm⟩ |
| 132 | + rewrite [Eval.deterministic h₂ hval] |
| 133 | + assumption |
10 | 134 |
|
11 | 135 | end Juvix.Core.Main
|
0 commit comments