[project @ 2002-10-15 11:01:29 by simonmar]
[ghc-hetmet.git] / ghc / compiler / utils / Panic.lhs
1 %
2 % (c) The GRASP Project, Glasgow University, 1992-2000
3 %
4 \section{Panic error messages}
5
6 Defines basic funtions for printing error messages.
7
8 It's hard to put these functions anywhere else without causing
9 some unnecessary loops in the module dependency graph.
10
11 \begin{code}
12 module Panic  
13    ( 
14      GhcException(..), ghcError, progName, 
15      panic, panic#, assertPanic, trace,
16      showException, showGhcException, tryMost,
17
18 #if __GLASGOW_HASKELL__ <= 408
19      catchJust, ioErrors, throwTo,
20 #endif
21    ) where
22
23 #include "HsVersions.h"
24
25 import Config
26 import FastTypes
27
28 import DYNAMIC
29 import qualified EXCEPTION as Exception
30 import TRACE            ( trace )
31 import UNSAFE_IO        ( unsafePerformIO )
32
33 import System
34 \end{code}
35
36 GHC's own exception type.
37
38 \begin{code}
39 ghcError :: GhcException -> a
40 ghcError e = Exception.throwDyn e
41
42 -- error messages all take the form
43 --
44 --      <location>: <error>
45 --
46 -- If the location is on the command line, or in GHC itself, then 
47 -- <location>="ghc".  All of the error types below correspond to 
48 -- a <location> of "ghc", except for ProgramError (where the string is
49 -- assumed to contain a location already, so we don't print one).
50
51 data GhcException
52   = PhaseFailed String          -- name of phase 
53                 ExitCode        -- an external phase (eg. cpp) failed
54   | Interrupted                 -- someone pressed ^C
55   | UsageError String           -- prints the short usage msg after the error
56   | CmdLineError String         -- cmdline prob, but doesn't print usage
57   | Panic String                -- the `impossible' happened
58   | InstallationError String    -- an installation problem
59   | ProgramError String         -- error in the user's code, probably
60   deriving Eq
61
62 progName = unsafePerformIO (getProgName)
63 {-# NOINLINE progName #-}
64
65 short_usage = "Usage: For basic information, try the `--help' option."
66    
67 showException :: Exception.Exception -> String
68 -- Show expected dynamic exceptions specially
69 showException (Exception.DynException d) | Just e <- fromDynamic d 
70                                          = show (e::GhcException)
71 showException other_exn                  = show other_exn
72
73 instance Show GhcException where
74   showsPrec _ e@(ProgramError _) = showGhcException e
75   showsPrec _ e = showString progName . showString ": " . showGhcException e
76
77 showGhcException (UsageError str)
78    = showString str . showChar '\n' . showString short_usage
79 showGhcException (PhaseFailed phase code)
80    = showString "phase `" . showString phase . 
81      showString "' failed (exitcode = " . shows int_code . 
82      showString ")"
83   where
84     int_code = 
85       case code of
86         ExitSuccess   -> (0::Int)
87         ExitFailure x -> x
88 showGhcException (CmdLineError str)
89    = showString str
90 showGhcException (ProgramError str)
91    = showString str
92 showGhcException (InstallationError str)
93    = showString str
94 showGhcException (Interrupted)
95    = showString "interrupted"
96 showGhcException (Panic s)
97    = showString ("panic! (the `impossible' happened, GHC version "
98                  ++ cProjectVersion ++ "):\n\t"
99                  ++ s ++ "\n\n"
100                  ++ "Please report it as a compiler bug "
101                  ++ "to glasgow-haskell-bugs@haskell.org,\n"
102                  ++ "or http://sourceforge.net/projects/ghc/.\n\n")
103
104 ghcExceptionTc = mkTyCon "GhcException"
105 {-# NOINLINE ghcExceptionTc #-}
106 instance Typeable GhcException where
107   typeOf _ = mkAppTy ghcExceptionTc []
108 \end{code}
109
110 Panics and asserts.
111
112 \begin{code}
113 panic :: String -> a
114 panic x = Exception.throwDyn (Panic x)
115
116 -- #-versions because panic can't return an unboxed int, and that's
117 -- what TAG_ is with GHC at the moment.  Ugh. (Simon)
118 -- No, man -- Too Beautiful! (Will)
119
120 panic# :: String -> FastInt
121 panic# s = case (panic s) of () -> _ILIT 0
122
123 assertPanic :: String -> Int -> a
124 assertPanic file line = 
125   Exception.throw (Exception.AssertionFailed 
126            ("ASSERT failed! file " ++ file ++ ", line " ++ show line))
127 \end{code}
128
129 \begin{code}
130 -- | tryMost is like try, but passes through Interrupted and Panic
131 -- exceptions.  Used when we want soft failures when reading interface
132 -- files, for example.
133
134 tryMost :: IO a -> IO (Either Exception.Exception a)
135 tryMost action = do r <- myTry action; filter r
136   where
137    filter (Left e@(Exception.DynException d))
138             | Just ghc_ex <- fromDynamic d
139                 = case ghc_ex of
140                     Interrupted -> Exception.throw e
141                     Panic _     -> Exception.throw e
142                     _other      -> return (Left e)
143    filter other 
144      = return other
145
146 #if __GLASGOW_HASKELL__ <= 408
147 myTry = Exception.tryAllIO
148 #else
149 myTry = Exception.try
150 #endif
151 \end{code}      
152
153 Compatibility stuff:
154
155 \begin{code}
156 #if __GLASGOW_HASKELL__ <= 408
157 catchJust = Exception.catchIO
158 ioErrors  = Exception.justIoErrors
159 throwTo   = Exception.raiseInThread
160 #endif
161 \end{code}