blob: 91d4211b2163aadff35deb5a13353349686a0e7e [file] [edit]
import Lean
open Lean
open Lean.Elab
open Lean.Elab.Term
open Lean.Elab.Command
open Std.Format open Std
open Lean.PrettyPrinter
open Lean.PrettyPrinter.Delaborator
open Lean.Meta
def checkM (stx : TermElabM Syntax) (optionsPerPos : OptionsPerPos := {}) : TermElabM Unit := do
let opts ← getOptions
let stx ← stx
let e ← elabTermAndSynthesize stx none <* throwErrorIfErrors
let stx' ← delab e optionsPerPos
let f' ← PrettyPrinter.ppTerm stx'
let s := f'.pretty' opts
IO.println s
let env ← getEnv
match Parser.runParserCategory env `term s "<input>" with
| Except.error e => throwErrorAt stx e
| Except.ok stx'' => do
let e' ← elabTermAndSynthesize stx'' none <* throwErrorIfErrors
unless (← isDefEq e e') do
throwErrorAt stx (m!"failed to round-trip" ++ line ++ format e ++ line ++ format e')
-- set_option trace.PrettyPrinter.parenthesize true
set_option format.width 20
-- #eval checkM `(?m) -- fails round-trip
#eval checkM `(Sort)
#eval checkM `(Type)
#eval checkM `(Type 0)
#eval checkM `(Type 1)
-- TODO: we need support for parsing `?u` to roundtrip the terms containing universe metavariables. Just pretty printing them as `_` is bad for error and trace messages
-- #eval checkM `(Type _)
-- #eval checkM `(Type (_ + 2))
#eval checkM `(@max Nat)
#eval checkM `(@HEq Nat 1)
#eval checkM `(@List.nil)
#eval checkM `(Nat)
#eval checkM `(List Nat)
#eval checkM `(id Nat)
#eval checkM `(id (id (id Nat)))
section
set_option pp.explicit true
#eval checkM `(List Nat)
#eval checkM `(id Nat)
end
section
set_option pp.universes true
#eval checkM `(List Nat)
#eval checkM `(id Nat)
#eval checkM `(Sum Nat Nat)
end
#eval checkM `(id (id Nat)) (Lean.RBMap.empty.insert (SubExpr.Pos.ofArray #[1]) $ KVMap.empty.insert `pp.explicit true)
-- specify the expected type of `a` in a way that is not erased by the delaborator
def typeAs.{u} (α : Type u) (a : α) := ()
set_option pp.analyze.knowsType false in
#eval checkM `(fun (a : Nat) => a)
#eval checkM `(fun (a : Nat) => a)
#eval checkM `(fun (a b : Nat) => a)
#eval checkM `(fun (a : Nat) (b : Bool) => a)
#eval checkM `(fun {a b : Nat} => a)
-- implicit lambdas work as long as the expected type is preserved
#eval checkM `(typeAs ({α : Type} → (a : α) → α) fun a => a)
section
set_option pp.explicit true
#eval checkM `(fun {α : Type} [ToString α] (a : α) => toString a)
end
#eval checkM `((α : Type) → α)
#eval checkM `((α β : Type) → α) -- group
#eval checkM `((α β : Type) → Type) -- don't group
#eval checkM `((α : Type) → (a : α) → α)
#eval checkM `({α : Type} → α)
#eval checkM `({α : Type} → [ToString α] → α)
#eval checkM `(∀ x : Nat, x = x)
#eval checkM `(∀ {x : Nat} [ToString Nat], x = x)
set_option pp.piBinderTypes false in
#eval checkM `(∀ x : Nat, x = x)
-- TODO: hide `ofNat`
#eval checkM `(0)
#eval checkM `(1)
#eval checkM `(42)
#eval checkM `("hi")
set_option pp.structureInstanceTypes true in
#eval checkM `((1,2,3))
#eval checkM `((1,2).fst)
#eval checkM `(1 < 2 || true)
#eval checkM `(id (fun a => a) 0)
#eval checkM `(typeAs (Id Nat) (do
let x := 1
discard <| pure 2
let y := 3
return x + y))
#eval checkM `(typeAs (Id Nat) (pure 1 >>= pure))
#eval checkM `((0 ≤ 1) = False)
#eval checkM `((0 = 1) = False)
#eval checkM `(-(-0))