lean4-htt/tests/lean/474.lean
Kyle Miller fdd5aec172
feat: better #eval command (#5627)
This refactors and improves the `#eval` command, introducing some new
features.
* Now evaluated results can be represented using `ToExpr` and pretty
printing. This means **hoverable output**. If `ToExpr` fails, it then
tries `Repr` and then `ToString`. The `eval.pp` option controls whether
or not to try `ToExpr`.
* There is now **auto-derivation** of `Repr` instances, enabled with the
`pp.derive.repr` option (default to **true**). For example:
  ```lean
  inductive Baz
    | a | b

  #eval Baz.a
  -- Baz.a
  ```
It simply does `deriving instance Repr for Baz` when there's no way to
represent `Baz`. If core Lean gets `ToExpr` derive handlers, they could
be used here as well.
* The option `eval.type` controls whether or not to include the type in
the output. For now the default is false.
* Now things like `#eval do return 2` work. It tries using
`CommandElabM`, `TermElabM`, or `IO` when the monad is unknown.
* Now there is no longer `Lean.Eval` or `Lean.MetaEval`. These each used
to be responsible for both adapting monads and printing results. The
concerns have been split into two. (1) The `MonadEval` class is
responsible for adapting monads for evaluation (it is similar to
`MonadLift`, but instances are allowed to use default data when
initializing state) and (2) finding a way to represent results is
handled separately.
* Error messages about failed instance synthesis are now more precise.
Once it detects that a `MonadEval` class applies, then the error message
will be specific about missing `ToExpr`/`Repr`/`ToString` instances.
* Fixes a bug where `Repr`/`ToString` instances can't be found by
unfolding types "under the monad". For example, this works now:
  ```lean
  def Foo := List Nat
  def Foo.mk (l : List Nat) : Foo := l
  #eval show Lean.CoreM Foo from do return Foo.mk [1,2,3]
  ```
* Elaboration errors now abort evaluation. This eliminates some
not-so-relevant error messages.
* Now evaluating a value of type `m Unit` never prints a blank message.
* Fixes bugs where evaluating `MetaM` and `CoreM` wouldn't collect log
messages.

The `run_cmd`, `run_elab`, and `run_meta` commands are now frontends for
`#eval`.
2024-10-08 20:51:46 +00:00

43 lines
1.8 KiB
Text

import Lean
open Lean Meta
open PrettyPrinter Delaborator SubExpr in
@[delab fvar]
def delabFVar : Delab := do
let Expr.fvar fvarId ← getExpr | unreachable!
let none := (← getLCtx).find? fvarId | failure
return mkIdent `FREE
#eval do
let e ← withLetDecl `y (mkConst ``Nat) (mkConst ``Nat.zero) fun y => do
let m ← mkFreshExprMVar (mkConst ``Nat)
m.mvarId!.assign y
let e := mkApp2 (mkConst ``Nat.add) m y
-- goal: construct λ y, e
dbg_trace (← ppExpr (← mkLambdaFVars #[y] e)) -- doesn't work: creates let
dbg_trace (← ppExpr (← instantiateMVars <| -- doesn't work: contains free variable
mkLambda `y BinderInfo.default (mkConst ``Nat) (e.abstract #[y])))
instantiateMVars <| -- doesn't work: contains free variable
mkLambda `y BinderInfo.default (mkConst ``Nat) (e.abstract #[y])
dbg_trace (← ppExpr e)
#eval
withLetDecl `y (mkConst ``Nat) (mkConst ``Nat.zero) fun y => do
let m ← mkFreshExprMVar (mkConst ``Nat)
m.mvarId!.assign y
let e := mkApp2 (mkConst ``Nat.add) m y
-- goal: construct λ y, e
dbg_trace (← instantiateMVars <| -- doesn't work: contains free variable
mkLambda `y BinderInfo.default (mkConst ``Nat) (← e.abstractM #[y]))
#eval do
let (e, _) ← withLetDecl `y (mkConst ``Nat) (mkConst ``Nat.zero) fun y => do
let m ← mkFreshExprMVar (mkConst ``Nat) (kind := MetavarKind.syntheticOpaque)
let e := mkApp2 (mkConst ``Nat.add) m y
dbg_trace (← ppExpr e)
dbg_trace (← ppExpr (← e.abstractM #[y]))
let e ← instantiateMVars <| -- doesn't work: contains free variable
mkLambda `y BinderInfo.default (mkConst ``Nat) (← e.abstractM #[y])
m.mvarId!.assign (mkApp2 (mkConst ``Nat.add) y y)
return (e, m)
dbg_trace (← ppExpr (← instantiateMVars e))