63 lines
2.6 KiB
Text
63 lines
2.6 KiB
Text
inductive Expr where
|
||
| nat : Nat → Expr
|
||
| plus : Expr → Expr → Expr
|
||
| bool : Bool → Expr
|
||
| and : Expr → Expr → Expr
|
||
deriving DecidableEq
|
||
|
||
inductive Ty where
|
||
| nat
|
||
| bool
|
||
deriving DecidableEq
|
||
|
||
inductive HasType : Expr → Ty → Prop
|
||
| nat : HasType (.nat v) .nat
|
||
| plus : HasType a .nat → HasType b .nat → HasType (.plus a b) .nat
|
||
| bool : HasType (.bool v) .bool
|
||
| and : HasType a .bool → HasType b .bool → HasType (.and a b) .bool
|
||
|
||
def Expr.typeCheck (e : Expr) : Option {t : Ty // HasType e t} :=
|
||
match e with
|
||
| nat .. => some ⟨.nat, .nat⟩
|
||
| bool .. => some ⟨.bool, .bool⟩
|
||
| plus a b =>
|
||
match a.typeCheck, b.typeCheck with
|
||
| some ⟨.nat, h₁⟩, some ⟨.nat, h₂⟩ => some ⟨.nat, .plus h₁ h₂⟩
|
||
| _, _ => none
|
||
| and a b =>
|
||
match a.typeCheck, b.typeCheck with
|
||
| some ⟨.bool, h₁⟩, some ⟨.bool, h₂⟩ => some ⟨.bool, .and h₁ h₂⟩
|
||
| _, _ => none
|
||
|
||
theorem HasType.det (h₁ : HasType e t₁) (h₂ : HasType e t₂) : t₁ = t₂ := by
|
||
cases h₁ <;> cases h₂ <;> rfl
|
||
|
||
-- TODO: for simplifying the following proof we need: ematching for forward reasoning, and `match` blast for case analysis
|
||
|
||
theorem Expr.typeCheck_complete {e : Expr} : e.typeCheck = none → ¬ HasType e t := by
|
||
induction e with simp [typeCheck]
|
||
| plus a b iha ihb =>
|
||
revert iha ihb
|
||
cases typeCheck a <;> cases typeCheck b <;> simp <;> intros <;> intro h <;> cases h <;> try contradiction
|
||
rename_i r₁ r₂ h _ _
|
||
cases r₁; rename_i t₁ _; cases r₂; rename_i t₂ _; cases t₁ <;> cases t₂ <;> simp at h
|
||
. have := HasType.det ‹HasType b Ty.bool› ‹HasType b Ty.nat›; contradiction
|
||
. have := HasType.det ‹HasType a Ty.bool› ‹HasType a Ty.nat›; contradiction
|
||
. have := HasType.det ‹HasType a Ty.bool› ‹HasType a Ty.nat›; contradiction
|
||
| and a b iha ihb =>
|
||
revert iha ihb
|
||
cases typeCheck a <;> cases typeCheck b <;> simp <;> intros <;> intro h <;> cases h <;> try contradiction
|
||
rename_i r₁ r₂ h _ _
|
||
cases r₁; rename_i t₁ _; cases r₂; rename_i t₂ _; cases t₁ <;> cases t₂ <;> simp at h
|
||
. have := HasType.det ‹HasType b Ty.bool› ‹HasType b Ty.nat›; contradiction
|
||
. have := HasType.det ‹HasType a Ty.bool› ‹HasType a Ty.nat›; contradiction
|
||
. have := HasType.det ‹HasType b Ty.bool› ‹HasType b Ty.nat›; contradiction
|
||
|
||
instance (e : Expr) (t : Ty) : Decidable (HasType e t) :=
|
||
match h' : e.typeCheck with
|
||
| some ⟨t', ht'⟩ =>
|
||
if heq : t = t' then
|
||
isTrue (heq ▸ ht')
|
||
else
|
||
isFalse fun ht => heq (HasType.det ht ht')
|
||
| none => isFalse (Expr.typeCheck_complete h')
|