lean4-htt/src/Lean/Exception.lean
Leonardo de Moura cf3b8d4eb4 chore: cleanup
Make the code style more uniform.
We still have a lot of leftovers from the old frontend.
2022-01-26 09:18:17 -08:00

122 lines
4.3 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/-
Copyright (c) 2020 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
import Lean.Message
import Lean.InternalExceptionId
import Lean.Data.Options
import Lean.Util.MonadCache
namespace Lean
/- Exception type used in most Lean monads -/
inductive Exception where
| error (ref : Syntax) (msg : MessageData)
| internal (id : InternalExceptionId) (extra : KVMap := {})
def Exception.toMessageData : Exception → MessageData
| Exception.error _ msg => msg
| Exception.internal id _ => id.toString
def Exception.getRef : Exception → Syntax
| Exception.error ref _ => ref
| Exception.internal _ _ => Syntax.missing
instance : Inhabited Exception := ⟨Exception.error default default⟩
/- Similar to `AddMessageContext`, but for error messages.
The default instance just uses `AddMessageContext`.
In error messages, we may want to provide additional information (e.g., macro expansion stack),
and refine the `(ref : Syntax)`. -/
class AddErrorMessageContext (m : Type → Type) where
add : Syntax → MessageData → m (Syntax × MessageData)
instance (m : Type → Type) [AddMessageContext m] [Monad m] : AddErrorMessageContext m where
add ref msg := do
let msg ← addMessageContext msg
pure (ref, msg)
class abbrev MonadError (m : Type → Type) :=
MonadExceptOf Exception m
MonadRef m
AddErrorMessageContext m
section Methods
protected def throwError [Monad m] [MonadError m] (msg : MessageData) : m α := do
let ref ← getRef
let (ref, msg) ← AddErrorMessageContext.add ref msg
throw <| Exception.error ref msg
def throwUnknownConstant [Monad m] [MonadError m] (constName : Name) : m α :=
Lean.throwError m!"unknown constant '{mkConst constName}'"
protected def throwErrorAt [Monad m] [MonadError m] (ref : Syntax) (msg : MessageData) : m α := do
withRef ref <| Lean.throwError msg
def ofExcept [Monad m] [MonadError m] [ToString ε] (x : Except ε α) : m α :=
match x with
| Except.ok a => pure a
| Except.error e => Lean.throwError <| toString e
def throwKernelException [Monad m] [MonadError m] [MonadOptions m] (ex : KernelException) : m α := do
Lean.throwError <| ex.toMessageData (← getOptions)
end Methods
class MonadRecDepth (m : Type → Type) where
withRecDepth {α} : Nat → m α → m α
getRecDepth : m Nat
getMaxRecDepth : m Nat
instance [Monad m] [MonadRecDepth m] : MonadRecDepth (ReaderT ρ m) where
withRecDepth d x := fun ctx => MonadRecDepth.withRecDepth d (x ctx)
getRecDepth := fun _ => MonadRecDepth.getRecDepth
getMaxRecDepth := fun _ => MonadRecDepth.getMaxRecDepth
instance [Monad m] [MonadRecDepth m] : MonadRecDepth (StateRefT' ω σ m) :=
inferInstanceAs (MonadRecDepth (ReaderT _ _))
instance [BEq α] [Hashable α] [Monad m] [STWorld ω m] [MonadRecDepth m] : MonadRecDepth (MonadCacheT α β m) :=
inferInstanceAs (MonadRecDepth (StateRefT' _ _ _))
def throwMaxRecDepthAt [MonadError m] (ref : Syntax) : m α :=
throw <| Exception.error ref (MessageData.ofFormat (Std.Format.text maxRecDepthErrorMessage))
/--
Return true if `ex` was generated by `throwMaxRecDepthAt`.
This function is a bit hackish. The max rec depth exception should probably be an internal exception,
but it is also produced by `MacroM` which implemented in the prelude, and internal exceptions have not
been defined yet. -/
def Exception.isMaxRecDepth (ex : Exception) : Bool :=
match ex with
| error _ (MessageData.ofFormat (Std.Format.text msg)) => msg == maxRecDepthErrorMessage
| _ => false
@[inline] def withIncRecDepth [Monad m] [MonadError m] [MonadRecDepth m] (x : m α) : m α := do
let curr ← MonadRecDepth.getRecDepth
let max ← MonadRecDepth.getMaxRecDepth
if curr == max then
throwMaxRecDepthAt (← getRef)
else
MonadRecDepth.withRecDepth (curr+1) x
syntax "throwError " (interpolatedStr(term) <|> term) : term
syntax "throwErrorAt " term:max (interpolatedStr(term) <|> term) : term
macro_rules
| `(throwError $msg) =>
if msg.getKind == interpolatedStrKind then
`(Lean.throwError (m! $msg))
else
`(Lean.throwError $msg)
macro_rules
| `(throwErrorAt $ref $msg) =>
if msg.getKind == interpolatedStrKind then
`(Lean.throwErrorAt $ref (m! $msg))
else
`(Lean.throwErrorAt $ref $msg)
end Lean