-
Notifications
You must be signed in to change notification settings - Fork 0
Prove Expr.typeCheck_complete for full language with Var, Lam, App #8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
8e1ddf2
30cd630
acd4f98
85630ab
3ed9b48
e8938c0
aba9c0c
329808f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,11 +5,26 @@ import Tibi.Util | |
|
|
||
| namespace Tibi | ||
|
|
||
| def Expr.eval : (e : Expr) → {{ r | Eval e r }} | ||
| | .Const n => | ||
| def Expr.eval (env : Env ctx) : {ty : Ty} → (e : Expr ctx ty) → ty.dom → {{ r | Eval e r }} | ||
| | _, .Const n, _ => | ||
| if h : (-Int64.size : Int) ≤ n ∧ n < Int64.size then | ||
| .found (.ok <| Int64.mk ⟨n, h.right, h.left⟩) <| Eval.Const h.right h.left | ||
| else | ||
| Decidable.not_and_iff_or_not_not.mp h |>.by_cases | ||
| (fun h => .found (.error <| .OutOfBounds_Int64 n) <| Eval.ConstErr_ge h) | ||
| (fun h => .found (.error <| .OutOfBounds_Int64 n) <| Eval.ConstErr_lt h) | ||
| | _, .Var x, _ => | ||
| .found (.ok <| env.lookup x) <| .Var x env | ||
| | _, .Lam e', x => | ||
| match e'.eval (x :: env) x with | ||
| | .found (.ok v) h => .found (.ok <| fun _ => v) <| .Lam h | ||
| | .unknown => .unknown | ||
| | .int, .App (dom := .int) (.Lam e₁) e₂, _ => | ||
| match e₂.eval env () with | ||
| | .found (.ok v) h₂ => | ||
| match e₁.eval (v :: env) v with | ||
| | .found (.ok v) h₁ => | ||
| .found (.ok <| v) <| .App h₁ h₂ | ||
| | _ => .unknown | ||
| | _ => .unknown | ||
| | _, _, _ => .unknown | ||
|
Comment on lines
+22
to
+30
|
||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -5,14 +5,14 @@ import Tibi.Wasm.Semantics | |||||||||
| namespace Tibi | ||||||||||
|
|
||||||||||
| theorem Wasm.Reduction.of_has_type_of_eval_ok_of_compile_ok -- Expr.compile_ok_of_has_type_of_eval | ||||||||||
| : {e : Expr} → HasType e _ty → Eval e (.ok v) → {_ : e.compile = .ok instrs} | ||||||||||
| : {e : Expr ctx .int} → HasType e _ty → Eval e (.ok v) → e.compile = .ok instrs | ||||||||||
| → Wasm.Reduction | ||||||||||
| { instrs := instrs ++ K, stack, store, framestate } | ||||||||||
| { instrs := K, stack := .Value (.Num (.Int64 v)) :: stack, store, framestate } | ||||||||||
| | .Const n, .Int64 hLt hGe, .Const _ _, hc => by | ||||||||||
| have : (Expr.Const n).compile = .ok [.i64__const (Int64.mk ⟨n, hLt, hGe⟩)] := by | ||||||||||
| -- dsimp [Expr.compile] | ||||||||||
| | .Const n, .Int64 _ _, .Const hLt hGe, hc => by | ||||||||||
| have : (Expr.Const n : Expr ctx .int).compile = .ok [.i64__const (Int64.mk ⟨n, hLt, hGe⟩)] := by | ||||||||||
| apply dite_cond_eq_true <| eq_true <| And.intro hGe hLt | ||||||||||
| have : instrs = [.i64__const ⟨n, hLt, hGe⟩ ] := Except.ok.inj <| Eq.trans hc.symm this | ||||||||||
| rw [this] | ||||||||||
| exact .i64__const | ||||||||||
| | .App _ _, _, _, hc => by simp [Expr.compile] at hc | ||||||||||
|
||||||||||
| | .App _ _, _, _, hc => by simp [Expr.compile] at hc | |
| | .App _ _, _, _, hc => by | |
| simp [Expr.compile] at hc | |
| cases hc |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -4,26 +4,38 @@ import Tibi.Typing | |||||||||||||||||||||
| namespace Tibi | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| theorem HasType.det (h₁ : HasType e t₁) (h₂ : HasType e t₂) : t₁ = t₂ := by | ||||||||||||||||||||||
| cases h₁ <;> cases h₂ <;> rfl | ||||||||||||||||||||||
| induction h₁ generalizing t₂ with | ||||||||||||||||||||||
| | Int64 => cases h₂; rfl | ||||||||||||||||||||||
| | Var => cases h₂; rfl | ||||||||||||||||||||||
| | Lam _ ih => cases h₂ with | Lam h' => exact congrArg (Typ.Fn (.Var 0)) (ih h') | ||||||||||||||||||||||
| | App _ _ ihf _ => | ||||||||||||||||||||||
| cases h₂ with | ||||||||||||||||||||||
| | App hf' _ => | ||||||||||||||||||||||
| have h := ihf hf' | ||||||||||||||||||||||
| simp only [Typ.Fn.injEq] at h | ||||||||||||||||||||||
| exact h.2 | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| theorem Expr.typeCheck_correct {e : Expr} | ||||||||||||||||||||||
| : (ht : HasType e ty) → e.typeCheck = .found ty ht | ||||||||||||||||||||||
| theorem Expr.typeCheck_correct : (ht : HasType e t) → e.typeCheck = .found t ht | ||||||||||||||||||||||
| | .Int64 (n := n) hLt hGe => | ||||||||||||||||||||||
| have := eq_true <| And.intro (ge_iff_le.mp hGe) hLt | ||||||||||||||||||||||
| dite_cond_eq_true this | ||||||||||||||||||||||
| | .Var => rfl | ||||||||||||||||||||||
| | .Lam h => by | ||||||||||||||||||||||
| have ih := typeCheck_correct h | ||||||||||||||||||||||
| simp only [Expr.typeCheck, ih] | ||||||||||||||||||||||
| | .App hf hv => by | ||||||||||||||||||||||
| have ihf := typeCheck_correct hf | ||||||||||||||||||||||
| have ihv := typeCheck_correct hv | ||||||||||||||||||||||
| simp [Expr.typeCheck, ihf, ihv] | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| theorem Expr.typeCheck_complete {e : Expr} | ||||||||||||||||||||||
| : e.typeCheck = .unknown → ¬ HasType e ty | ||||||||||||||||||||||
| := by | ||||||||||||||||||||||
| dsimp [Expr.typeCheck] | ||||||||||||||||||||||
| intro h (ht : HasType e ty) | ||||||||||||||||||||||
| match ht with | ||||||||||||||||||||||
| | .Int64 hLt hGe => | ||||||||||||||||||||||
| have := eq_true <| And.intro (ge_iff_le.mp hGe) hLt | ||||||||||||||||||||||
| have := h ▸ dite_cond_eq_true this | ||||||||||||||||||||||
| exact Maybe.noConfusion this | ||||||||||||||||||||||
| theorem Expr.typeCheck_complete {e : Expr ctx ty} | ||||||||||||||||||||||
| : e.typeCheck = .unknown → ¬ HasType e t | ||||||||||||||||||||||
| := fun h ht => by | ||||||||||||||||||||||
| have := typeCheck_correct ht | ||||||||||||||||||||||
| rw [h] at this | ||||||||||||||||||||||
| exact Maybe.noConfusion this | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| instance (e : Expr) (t : Typ) : Decidable (HasType e t) := | ||||||||||||||||||||||
| instance (e : Expr ctx ty) (t : Typ) : Decidable (HasType e t) := | ||||||||||||||||||||||
| match h : e.typeCheck with | ||||||||||||||||||||||
| | .found t' ht' => | ||||||||||||||||||||||
| if heq : t = t' then | ||||||||||||||||||||||
|
|
@@ -32,8 +44,11 @@ instance (e : Expr) (t : Typ) : Decidable (HasType e t) := | |||||||||||||||||||||
| isFalse fun ht => heq (HasType.det ht ht') | ||||||||||||||||||||||
| | .unknown => isFalse (Expr.typeCheck_complete h) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| theorem type_safe {e : Expr} | ||||||||||||||||||||||
| theorem type_safe {e : Expr ctx ty} | ||||||||||||||||||||||
| : HasType e t → Eval e r → ∃ v, r = .ok v | ||||||||||||||||||||||
| | .Int64 hLt hGe, .Const .. => ⟨Int64.mk ⟨_, hLt, hGe⟩, rfl⟩ | ||||||||||||||||||||||
| | .Int64 hLt hGe, .Const .. => ⟨_, rfl⟩ | ||||||||||||||||||||||
| | .Int64 hLt _, .ConstErr_lt h => absurd hLt h | ||||||||||||||||||||||
| | .Int64 _ hGe, .ConstErr_ge h => absurd hGe h | ||||||||||||||||||||||
| | .Var, .Var .. => ⟨_, rfl⟩ | ||||||||||||||||||||||
| | .Lam _, .Lam .. => ⟨_, rfl⟩ | ||||||||||||||||||||||
| | .App _ _, .App .. => ⟨_, rfl⟩ | ||||||||||||||||||||||
|
Comment on lines
+53
to
+54
|
||||||||||||||||||||||
| | .Lam _, .Lam .. => ⟨_, rfl⟩ | |
| | .App _ _, .App .. => ⟨_, rfl⟩ | |
| | .Lam _, hEval => | |
| -- Use the structure of the evaluation derivation for lambdas | |
| cases hEval with | |
| | Lam .. => exact ⟨_, rfl⟩ | |
| | .App _ _, hEval => | |
| -- Use the structure of the evaluation derivation for applications | |
| cases hEval with | |
| | App .. => exact ⟨_, rfl⟩ |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,15 +1,25 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import Tibi.FinInt | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import Tibi.Semantics.Env | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import Tibi.Syntax | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| namespace Tibi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| inductive EvalError | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | OutOfBounds_Int64 (n : Int) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| inductive Eval : Expr → Except EvalError Int64 → Prop | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | Const {n : Int} (hLt : n < Int64.size) (hGe : n >= -Int64.size) : Eval (.Const n) (.ok <| Int64.mk ⟨n, hLt, hGe⟩) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | ConstErr_lt {n : Int} (h : ¬ n < Int64.size) : Eval (.Const n) (.error <| .OutOfBounds_Int64 n) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | ConstErr_ge {n : Int} (h : ¬ n >= -Int64.size) : Eval (.Const n) (.error <| .OutOfBounds_Int64 n) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| inductive Eval : (Expr ctx ty) → Except EvalError ty.interp → Prop | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | Const {n : Int} (hLt : n < Int64.size) (hGe : n >= -Int64.size) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| : Eval (.Const n) (.ok <| Int64.mk ⟨n, hLt, hGe⟩) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | ConstErr_lt {n : Int} (h : ¬ n < Int64.size) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| : Eval (.Const n) (.error <| .OutOfBounds_Int64 n) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | ConstErr_ge {n : Int} (h : ¬ n >= -Int64.size) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| : Eval (.Const n) (.error <| .OutOfBounds_Int64 n) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | Var (x : Locals k ctx ty) (env : Env ctx) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| : Eval (.Var x) (.ok <| env.lookup x) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | Lam (d : Eval e (.ok v)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| : Eval (.Lam e) (.ok <| fun _ => v) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | App (d₁ : Eval e₁ (.ok v₁)) (d₂ : Eval e₂ (.ok v₂)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| : Eval (.App (.Lam e₁) e₂) (.ok <| v₁) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+10
to
+22
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| inductive Eval : (Expr ctx ty) → Except EvalError ty.interp → Prop | |
| | Const {n : Int} (hLt : n < Int64.size) (hGe : n >= -Int64.size) | |
| : Eval (.Const n) (.ok <| Int64.mk ⟨n, hLt, hGe⟩) | |
| | ConstErr_lt {n : Int} (h : ¬ n < Int64.size) | |
| : Eval (.Const n) (.error <| .OutOfBounds_Int64 n) | |
| | ConstErr_ge {n : Int} (h : ¬ n >= -Int64.size) | |
| : Eval (.Const n) (.error <| .OutOfBounds_Int64 n) | |
| | Var (x : Locals k ctx ty) (env : Env ctx) | |
| : Eval (.Var x) (.ok <| env.lookup x) | |
| | Lam (d : Eval e (.ok v)) | |
| : Eval (.Lam e) (.ok <| fun _ => v) | |
| | App (d₁ : Eval e₁ (.ok v₁)) (d₂ : Eval e₂ (.ok v₂)) | |
| : Eval (.App (.Lam e₁) e₂) (.ok <| v₁) | |
| inductive Eval (env : Env ctx) : (Expr ctx ty) → Except EvalError ty.interp → Prop | |
| | Const {n : Int} (hLt : n < Int64.size) (hGe : n >= -Int64.size) | |
| : Eval env (.Const n) (.ok <| Int64.mk ⟨n, hLt, hGe⟩) | |
| | ConstErr_lt {n : Int} (h : ¬ n < Int64.size) | |
| : Eval env (.Const n) (.error <| .OutOfBounds_Int64 n) | |
| | ConstErr_ge {n : Int} (h : ¬ n >= -Int64.size) | |
| : Eval env (.Const n) (.error <| .OutOfBounds_Int64 n) | |
| | Var (x : Locals k ctx ty) | |
| : Eval env (.Var x) (.ok <| env.lookup x) | |
| | Lam (d : Eval env e (.ok v)) | |
| : Eval env (.Lam e) (.ok <| fun _ => v) | |
| | App (d₁ : Eval env e₁ (.ok v₁)) (d₂ : Eval env e₂ (.ok v₂)) | |
| : Eval env (.App (.Lam e₁) e₂) (.ok <| v₁) |
Copilot
AI
Mar 4, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Lam/App rules currently ignore the argument: Lam returns fun _ => v after evaluating the body once, and App returns v₁ without relating it to the argument value (it even requires d₂ but never uses v₂). This makes function semantics incorrect (every lambda becomes a constant function) and makes App unrelated to substitution/application. Rework these constructors to model closures/application (likely using an explicit Env parameter and evaluating the body under an extended environment for the given argument).
| | Lam (d : Eval e (.ok v)) | |
| : Eval (.Lam e) (.ok <| fun _ => v) | |
| | App (d₁ : Eval e₁ (.ok v₁)) (d₂ : Eval e₂ (.ok v₂)) | |
| : Eval (.App (.Lam e₁) e₂) (.ok <| v₁) | |
| | Lam {e v} (d : ∀ a, Eval e (.ok (v a))) | |
| : Eval (.Lam e) (.ok v) | |
| | App (d₁ : Eval e₁ (.ok v₁)) (d₂ : Eval e₂ (.ok v₂)) | |
| : Eval (.App (.Lam e₁) e₂) (.ok <| v₁ v₂) |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,14 @@ | ||||||
| import Tibi.Syntax | ||||||
| import Tibi.Util | ||||||
|
|
||||||
| namespace Tibi | ||||||
|
|
||||||
| inductive Env : Vec Ty n → Type where | ||||||
| | nil : Env Vec.nil | ||||||
| | cons : Ty.interp a → Env ctx → Env (a :: ctx) | ||||||
|
|
||||||
| infix:67 " :: " => Env.cons | ||||||
|
||||||
| infix:67 " :: " => Env.cons | |
| scoped infixr:67 " :: " => Env.cons |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,10 +1,55 @@ | ||
| import Tibi.FinInt | ||
| import Tibi.Util | ||
|
|
||
| namespace Tibi | ||
|
|
||
| inductive Expr | ||
| | Const : Int → Expr | ||
| inductive Ty where | ||
| | int | ||
| | fn (a b : Ty) | ||
| | cls (a b : Ty) | ||
|
|
||
| instance : ToString Expr where | ||
| toString | ||
| | .Const n => s!"<Const {n}>" | ||
| @[reducible] | ||
| def Ty.interp : Ty → Type | ||
| | int => Int64 | ||
| | fn a b => a.interp → b.interp | ||
| | cls _ b => b.interp | ||
|
|
||
| @[reducible] | ||
| def Ty.dom : Ty → Type | ||
| | int => Unit | ||
| | fn a _ => a.interp | ||
| | cls a _ => a.interp | ||
|
|
||
| def Ty.toString : Ty → String | ||
| | int => "Int" | ||
| | fn a b => s!"{a.toString} -> {b.toString}" | ||
| | cls _ b => s!"{b.toString}" | ||
|
|
||
| instance : ToString Ty where | ||
| toString := Ty.toString | ||
|
|
||
| inductive Locals : Fin n → Tibi.Vec Ty n → Ty → Type where | ||
| | stop : Locals 0 (ty :: ctx) ty | ||
| | pop : Locals k ctx ty → Locals k.succ (u :: ctx) ty | ||
|
|
||
| def Locals.idx : Locals n ctx ty → Fin n.succ | ||
| | stop => Fin.mk 0 (Fin.succ_pos _) | ||
| | pop k => k.idx.succ | ||
|
|
||
| instance : ToString (Locals n ctx ty) where | ||
| toString x := s!"${x.idx}" | ||
|
|
||
| inductive Expr : Vec Ty n → Ty → Type where | ||
| | Const : Int → Expr ctx .int | ||
| | Var : Locals i ctx ty → Expr ctx (.cls ty ty) | ||
| | Lam : Expr (dom :: ctx) (.cls dom ran) → Expr ctx (.fn dom ran) | ||
| | App : Expr ctx (.fn dom ran) → Expr ctx dom → Expr ctx ran | ||
|
|
||
| def Expr.toString : Expr ctx ty → String | ||
| | Const n => s!"<Const {n}>" | ||
| | Var x => s!"<Var {x} @{ty}>" | ||
| | Lam e => s!"<Lam {e.toString}>" | ||
| | App e₁ e₂ => s!"<App {e₁.toString} {e₂.toString}>" | ||
|
|
||
| instance : ToString (Expr ctx ty) where | ||
| toString := Expr.toString |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,25 +1,52 @@ | ||
| import Tibi.FinInt | ||
| import Tibi.Semantics | ||
| import Tibi.Syntax | ||
| import Tibi.Util | ||
|
|
||
| namespace Tibi | ||
|
|
||
| inductive Typ | ||
| | Var (idx : Nat) | ||
| | Int64 | ||
| | Fn (a : Typ) (b : Typ) | ||
| deriving DecidableEq | ||
|
|
||
| def Typ.toString : Typ → String | ||
| | Int64 => "Int" | ||
| | Var idx => s!"α{idx}" | ||
| | Int64 => "Int" | ||
| | Fn a b => s!"{a.toString} -> {b.toString}" | ||
|
|
||
| instance : ToString Typ where | ||
| toString := Typ.toString | ||
|
|
||
| inductive HasType : Expr → Typ → Prop | ||
| def Ty.toTyp : Ty → Typ | ||
| | int => .Int64 | ||
| | fn a b => .Fn a.toTyp b.toTyp | ||
| | cls _ b => b.toTyp | ||
|
|
||
| inductive HasType : Expr ctx ty → Typ → Prop | ||
| | Int64 {n : Int} (hLt : n < Int64.size) (hGe : n ≥ -Int64.size) : HasType (.Const n) .Int64 | ||
| | Var {x : Locals i ctx ty} : HasType (.Var x) (Ty.cls ty ty).toTyp | ||
| | Lam (h : HasType e t) : HasType (.Lam e) (.Fn (.Var 0) t) | ||
| | App (hf : HasType f (.Fn dom ran)) (hv : HasType v dom) : HasType (.App f v) ran | ||
|
Comment on lines
+27
to
+31
|
||
|
|
||
| def Expr.typeCheck : (e : Expr) → {{ t | HasType e t }} | ||
| def Expr.typeCheck : (e : Expr ctx ty) → {{ t | HasType e t }} | ||
| | .Const n => | ||
| if h : -Int64.size ≤ n ∧ n < Int64.size then | ||
| .found .Int64 <| .Int64 h.right h.left | ||
| else | ||
| .unknown | ||
| | .Var _ => | ||
| .found _ .Var | ||
| | .Lam e => | ||
| match e.typeCheck with | ||
| | .found t h => .found (.Fn (.Var 0) t) <| .Lam h | ||
| | .unknown => .unknown | ||
|
Comment on lines
+41
to
+44
|
||
| | .App f v => | ||
| match f.typeCheck, v.typeCheck with | ||
| | .found (.Fn a b) hf, .found a' hv => | ||
| if h : a = a' then | ||
| .found b <| .App hf (h ▸ hv) | ||
| else | ||
| .unknown | ||
| | _, _ => .unknown | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
Lamevaluation path computesvby evaluating the body once with the specific inputx, then returns the constant functionfun _ => v. That makes lambda values independent of the argument (i.e., not a real closure). IfTy.interp (fn a b)isa → b,Lamshould return a function that (for each argument) evaluates the body under the extended environment for that argument.