module Agda.Utils.Impossible where
import Control.Exception (Exception(..), throw, catchJust)
import GHC.Stack
(CallStack, HasCallStack, callStack, getCallStack, freezeCallStack
, srcLocModule, srcLocFile, srcLocStartLine)
data Impossible
= Impossible String Integer
| Unreachable String Integer
| ImpMissingDefinitions [String] String
instance Show Impossible where
show :: Impossible -> String
show (Impossible String
file Integer
line) = [String] -> String
unlines
[ String
"An internal error has occurred. Please report this as a bug."
, String
"Location of the error: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
file String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
":" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Integer -> String
forall a. Show a => a -> String
show Integer
line
]
show (Unreachable String
file Integer
line) = [String] -> String
unlines
[ String
"We reached a program point we did not want to reach."
, String
"Location of the error: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
file String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
":" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Integer -> String
forall a. Show a => a -> String
show Integer
line
]
show (ImpMissingDefinitions [String]
needed String
forthis) = [String] -> String
unlines
[ String
"The following builtins or primitives need to be bound to use " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
forthis String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
":"]
String -> ShowS
forall a. [a] -> [a] -> [a]
++ [String] -> String
unwords [String]
needed
instance Exception Impossible
throwImpossible :: Impossible -> a
throwImpossible :: Impossible -> a
throwImpossible = Impossible -> a
forall a e. Exception e => e -> a
throw
class CatchImpossible m where
catchImpossible :: m a -> (Impossible -> m a) -> m a
catchImpossible = (Impossible -> Maybe Impossible)
-> m a -> (Impossible -> m a) -> m a
forall (m :: * -> *) b a.
CatchImpossible m =>
(Impossible -> Maybe b) -> m a -> (b -> m a) -> m a
catchImpossibleJust Impossible -> Maybe Impossible
forall a. a -> Maybe a
Just
catchImpossibleJust :: (Impossible -> Maybe b) -> m a -> (b -> m a) -> m a
catchImpossibleJust = ((b -> m a) -> m a -> m a) -> m a -> (b -> m a) -> m a
forall a b c. (a -> b -> c) -> b -> a -> c
flip (((b -> m a) -> m a -> m a) -> m a -> (b -> m a) -> m a)
-> ((Impossible -> Maybe b) -> (b -> m a) -> m a -> m a)
-> (Impossible -> Maybe b)
-> m a
-> (b -> m a)
-> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Impossible -> Maybe b) -> (b -> m a) -> m a -> m a
forall (m :: * -> *) b a.
CatchImpossible m =>
(Impossible -> Maybe b) -> (b -> m a) -> m a -> m a
handleImpossibleJust
handleImpossible :: (Impossible -> m a) -> m a -> m a
handleImpossible = (m a -> (Impossible -> m a) -> m a)
-> (Impossible -> m a) -> m a -> m a
forall a b c. (a -> b -> c) -> b -> a -> c
flip m a -> (Impossible -> m a) -> m a
forall (m :: * -> *) a.
CatchImpossible m =>
m a -> (Impossible -> m a) -> m a
catchImpossible
handleImpossibleJust :: (Impossible -> Maybe b) -> (b -> m a) -> m a -> m a
handleImpossibleJust = (m a -> (b -> m a) -> m a) -> (b -> m a) -> m a -> m a
forall a b c. (a -> b -> c) -> b -> a -> c
flip ((m a -> (b -> m a) -> m a) -> (b -> m a) -> m a -> m a)
-> ((Impossible -> Maybe b) -> m a -> (b -> m a) -> m a)
-> (Impossible -> Maybe b)
-> (b -> m a)
-> m a
-> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Impossible -> Maybe b) -> m a -> (b -> m a) -> m a
forall (m :: * -> *) b a.
CatchImpossible m =>
(Impossible -> Maybe b) -> m a -> (b -> m a) -> m a
catchImpossibleJust
{-# MINIMAL catchImpossibleJust | handleImpossibleJust #-}
instance CatchImpossible IO where
catchImpossibleJust :: (Impossible -> Maybe b) -> IO a -> (b -> IO a) -> IO a
catchImpossibleJust = (Impossible -> Maybe b) -> IO a -> (b -> IO a) -> IO a
forall e b a.
Exception e =>
(e -> Maybe b) -> IO a -> (b -> IO a) -> IO a
catchJust
withFileAndLine' :: Integral a => CallStack -> (String -> a -> b) -> b
withFileAndLine' :: CallStack -> (String -> a -> b) -> b
withFileAndLine' CallStack
cs String -> a -> b
ctor = String -> a -> b
ctor String
file a
line
where
callSiteList :: [(String, SrcLoc)]
callSiteList = CallStack -> [(String, SrcLoc)]
getCallStack CallStack
cs
notHere :: (a, SrcLoc) -> Bool
notHere (a
_, SrcLoc
loc) = SrcLoc -> String
srcLocModule SrcLoc
loc String -> String -> Bool
forall a. Eq a => a -> a -> Bool
/= String
"Agda.Utils.Impossible"
stackLocations :: [(String, SrcLoc)]
stackLocations = ((String, SrcLoc) -> Bool)
-> [(String, SrcLoc)] -> [(String, SrcLoc)]
forall a. (a -> Bool) -> [a] -> [a]
filter (String, SrcLoc) -> Bool
forall a. (a, SrcLoc) -> Bool
notHere [(String, SrcLoc)]
callSiteList
(String
file, a
line) = case [(String, SrcLoc)]
stackLocations of
(String
_, SrcLoc
loc) : [(String, SrcLoc)]
_ -> (SrcLoc -> String
srcLocFile SrcLoc
loc, Int -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (SrcLoc -> Int
srcLocStartLine SrcLoc
loc))
[] -> (String
"?", -a
1)
withFileAndLine :: (HasCallStack, Integral a) => (String -> a -> b) -> b
withFileAndLine :: (String -> a -> b) -> b
withFileAndLine = CallStack -> (String -> a -> b) -> b
forall a b. Integral a => CallStack -> (String -> a -> b) -> b
withFileAndLine' (CallStack -> CallStack
freezeCallStack CallStack
HasCallStack => CallStack
callStack)
__IMPOSSIBLE__ :: HasCallStack => a
__IMPOSSIBLE__ :: a
__IMPOSSIBLE__ = Impossible -> a
forall a. Impossible -> a
throwImpossible ((String -> Integer -> Impossible) -> Impossible
forall a b. (HasCallStack, Integral a) => (String -> a -> b) -> b
withFileAndLine String -> Integer -> Impossible
Impossible)
__UNREACHABLE__ :: HasCallStack => a
__UNREACHABLE__ :: a
__UNREACHABLE__ = Impossible -> a
forall a. Impossible -> a
throwImpossible ((String -> Integer -> Impossible) -> Impossible
forall a b. (HasCallStack, Integral a) => (String -> a -> b) -> b
withFileAndLine String -> Integer -> Impossible
Unreachable)