lean4-htt/tests/elab/meta.lean
Kim Morrison 66bc9ae177
chore: deprecate levelZero and levelOne (#12720)
This PR deprecates `levelZero` in favor of `Level.zero` and `levelOne`
in favor of the new `Level.one`, and updates all usages throughout the
codebase. The `levelZero` alias was previously required for computed
field `data` to work, but this is no longer needed.

🤖 Prepared with Claude Code
2026-03-04 01:03:08 +00:00

112 lines
3.2 KiB
Text

import Lean
open Lean
open Meta
def execShow (x : MetaM Expr) : MetaM Unit := do
let e ← x
IO.println (← ppExpr e)
/-
The `MetaM` has an ambient local context.
The local context contains the types of the free variables.
-/
def mkLam1 : MetaM Expr :=
/- The following `withLocalDecl` extends the local context with `(x : Nat)`, and executes the lambda
with an expression `x`. -/
withLocalDecl `x BinderInfo.default (mkConst `Nat) fun x =>
/- Similar to the method above, but sets `BinderInfo.default`. -/
withLocalDeclD `y (mkConst `Nat) fun y => do
-- Double backticks instruct Lean to resolve the names at compilation time
let b ← mkAppM ``HAdd.hAdd #[x, y] -- `x + y`
let b ← mkAppM ``HAdd.hAdd #[b, x] -- `x + y + x`
/- `mkLambdaFVars` converts the free variables into de-Bruijn bound variables, and construct the lambda for us. -/
mkLambdaFVars #[x, y] b
/-- info: fun x y => x + y + x -/
#guard_msgs in
#eval execShow mkLam1
/-- info: Nat → Nat → Nat -/
#guard_msgs in
#eval execShow do let e ← mkLam1; inferType e
def mkForall1 : MetaM Expr :=
withLocalDeclD `x (mkConst `Nat) fun x =>
withLocalDeclD `y (mkConst `Nat) fun y => do
let b ← mkEq x y
mkForallFVars #[x, y] b
/-- info: ∀ (x y : Nat), x = y -/
#guard_msgs in
#eval execShow mkForall1
def mkForall2Lambda : MetaM Expr := do
let e ← mkForall1
/- The following method `opens` a `forall` term, and expands the local context with
new free variables corresponding to the forall binders.
We also have a telescope function for `lambda` terms. -/
forallTelescopeReducing e fun xs b => do
IO.println s!">> {← xs.mapM Meta.ppExpr}"
IO.println s!">> {← ppExpr b}"
-- xs is an array of `Expr`
let b ← mkAppM ``HMul.hMul xs
mkLambdaFVars xs b
/--
info: >> #[x, y]
>> x = y
fun x y => x * y
-/
#guard_msgs in
#eval execShow mkForall2Lambda
def mkGoal : MetaM Expr :=
withLocalDeclD `x (mkConst `Nat) fun x =>
withLocalDeclD `y (mkConst `Nat) fun y => do
withLocalDeclD `h (← mkEq x y) fun h => do
let b ← mkEq y x
mkForallFVars #[x, y, h] b
/-- info: ∀ (x y : Nat), x = y → y = x -/
#guard_msgs in
#eval execShow mkGoal
def proveGoal : MetaM Unit := do
let g ← mkGoal
-- `main` is a metavariable representing the term we want to construct
let main ← mkFreshExprSyntheticOpaqueMVar g
let m := main.mvarId!
IO.println (← ppGoal m)
IO.println "-----"
let (xs, m) ← m.introNP 3 -- `intro` 3 variables using the binder names to name the new locals
IO.println (← ppGoal m)
IO.println "-----"
-- The `apply` tactic generates 0 or more subgoals
let [m] ← m.apply (mkConst ``Eq.symm [Level.one]) | throwError "unexpected number of subgoals"
IO.println (← ppGoal m)
IO.println "-----"
m.assumption
-- `main` contains the whole proof now
IO.println (← ppExpr main)
check main -- type check the proof. This is not the kernel type checker.
IO.println (← ppExpr (← inferType main))
/--
info: ⊢ ∀ (x y : Nat), x = y → y = x
-----
x y : Nat
h : x = y
⊢ y = x
-----
case h
x y : Nat
h : x = y
⊢ x = y
-----
fun x y h => Eq.symm h
∀ (x y : Nat), x = y → y = x
-/
#guard_msgs in
#eval proveGoal