View patterns, record wildcards, and record puns
[ghc-hetmet.git] / compiler / basicTypes / SrcLoc.lhs
index 51d4318..fda74e0 100644 (file)
@@ -1,11 +1,6 @@
 %
-% (c) The University of Glasgow, 1992-2003
+% (c) The University of Glasgow, 1992-2006
 %
-%************************************************************************
-%*                                                                     *
-\section[SrcLoc]{The @SrcLoc@ type}
-%*                                                                     *
-%************************************************************************
 
 \begin{code}
 module SrcLoc (
@@ -15,8 +10,6 @@ module SrcLoc (
        noSrcLoc,               -- "I'm sorry, I haven't a clue"
        advanceSrcLoc,
 
-       importedSrcLoc,         -- Unknown place in an interface
-       wiredInSrcLoc,          -- Something wired into the compiler
        generatedSrcLoc,        -- Code generated within the compiler
        interactiveSrcLoc,      -- Code from an interactive session
 
@@ -26,22 +19,28 @@ module SrcLoc (
        pprDefnLoc,
 
        SrcSpan,                -- Abstract
-       noSrcSpan,
+       noSrcSpan, 
+       wiredInSrcSpan,         -- Something wired into the compiler
        mkGeneralSrcSpan, 
-       isGoodSrcSpan,
+       isGoodSrcSpan, isOneLineSpan,
        mkSrcSpan, srcLocSpan,
        combineSrcSpans,
-       srcSpanFile,
-       srcSpanStartLine, srcSpanEndLine,
-       srcSpanStartCol, srcSpanEndCol,
        srcSpanStart, srcSpanEnd,
+       optSrcSpanFileName,
 
-       Located(..), getLoc, unLoc, noLoc, eqLocated, cmpLocated, combineLocs, addCLoc
+       -- These are dubious exports, because they crash on some inputs,
+       -- used only in Lexer.x where we are sure what the Span looks like
+       srcSpanFile, 
+        srcSpanStartLine, srcSpanEndLine, 
+        srcSpanStartCol, srcSpanEndCol,
+
+       Located(..), getLoc, unLoc, noLoc, eqLocated, cmpLocated, combineLocs, addCLoc,
+        leftmost_smallest, leftmost_largest, rightmost, spans, isSubspanOf
     ) where
 
 #include "HsVersions.h"
 
-import Util            ( thenCmp )
+import Util
 import Outputable
 import FastString
 \end{code}
@@ -62,16 +61,9 @@ data SrcLoc
                -- Don't ask me why lines start at 1 and columns start at
                -- zero.  That's just the way it is, so there.  --SDM
 
-  | ImportedLoc        String          -- Module name
-
   | UnhelpfulLoc FastString    -- Just a general indication
 \end{code}
 
-Note that an entity might be imported via more than one route, and
-there could be more than one ``definition point'' --- in two or more
-\tr{.hi} files.         We deemed it probably-unworthwhile to cater for this
-rare case.
-
 %************************************************************************
 %*                                                                     *
 \subsection[SrcLoc-access-fns]{Access functions for names}
@@ -80,35 +72,35 @@ rare case.
 
 Things to make 'em:
 \begin{code}
+mkSrcLoc :: FastString -> Int -> Int -> SrcLoc
 mkSrcLoc x line col = SrcLoc x line col
+
+noSrcLoc, generatedSrcLoc, interactiveSrcLoc :: SrcLoc
 noSrcLoc         = UnhelpfulLoc FSLIT("<no location info>")
 generatedSrcLoc   = UnhelpfulLoc FSLIT("<compiler-generated code>")
-wiredInSrcLoc     = UnhelpfulLoc FSLIT("<wired into compiler>")
 interactiveSrcLoc = UnhelpfulLoc FSLIT("<interactive session>")
 
 mkGeneralSrcLoc :: FastString -> SrcLoc
 mkGeneralSrcLoc = UnhelpfulLoc 
 
-importedSrcLoc :: String -> SrcLoc
-importedSrcLoc mod_name = ImportedLoc mod_name
-
+isGoodSrcLoc :: SrcLoc -> Bool
 isGoodSrcLoc (SrcLoc _ _ _) = True
-isGoodSrcLoc other          = False
+isGoodSrcLoc _other         = False
 
 srcLocFile :: SrcLoc -> FastString
 srcLocFile (SrcLoc fname _ _) = fname
-srcLocFile other             = FSLIT("<unknown file")
+srcLocFile _other            = FSLIT("<unknown file")
 
 srcLocLine :: SrcLoc -> Int
-srcLocLine (SrcLoc _ l c) = l
-srcLocLine other         = panic "srcLocLine: unknown line"
+srcLocLine (SrcLoc _ l _) = l
+srcLocLine _other        = panic "srcLocLine: unknown line"
 
 srcLocCol :: SrcLoc -> Int
-srcLocCol (SrcLoc _ l c) = c
-srcLocCol other          = panic "srcLocCol: unknown col"
+srcLocCol (SrcLoc _ _ c) = c
+srcLocCol _other         = panic "srcLocCol: unknown col"
 
 advanceSrcLoc :: SrcLoc -> Char -> SrcLoc
-advanceSrcLoc (SrcLoc f l c) '\n' = SrcLoc f  (l + 1) 0
+advanceSrcLoc (SrcLoc f l _) '\n' = SrcLoc f  (l + 1) 0
 advanceSrcLoc (SrcLoc f l c) _    = SrcLoc f  l (c + 1)
 advanceSrcLoc loc           _    = loc -- Better than nothing
 \end{code}
@@ -123,26 +115,19 @@ advanceSrcLoc loc      _    = loc -- Better than nothing
 -- SrcLoc is an instance of Ord so that we can sort error messages easily
 instance Eq SrcLoc where
   loc1 == loc2 = case loc1 `cmpSrcLoc` loc2 of
-                  EQ    -> True
-                  other -> False
+                  EQ     -> True
+                  _other -> False
 
 instance Ord SrcLoc where
   compare = cmpSrcLoc
-
+   
+cmpSrcLoc :: SrcLoc -> SrcLoc -> Ordering
 cmpSrcLoc (UnhelpfulLoc s1) (UnhelpfulLoc s2) = s1 `compare` s2
-cmpSrcLoc (UnhelpfulLoc _)  other                    = LT
-
-cmpSrcLoc (ImportedLoc _)  (UnhelpfulLoc _)  = GT
-cmpSrcLoc (ImportedLoc m1) (ImportedLoc m2)  = m1 `compare` m2
-cmpSrcLoc (ImportedLoc _)  other            = LT
+cmpSrcLoc (UnhelpfulLoc _)  _other            = LT
 
 cmpSrcLoc (SrcLoc s1 l1 c1) (SrcLoc s2 l2 c2)      
-  = (s1 `compare` s2) `thenCmp` (l1 `cmpline` l2) `thenCmp` (c1 `cmpline` c2)
-  where
-       l1 `cmpline` l2 | l1 <  l2 = LT
-                       | l1 == l2 = EQ
-                       | otherwise = GT 
-cmpSrcLoc (SrcLoc _ _ _) other = GT
+  = (s1 `compare` s2) `thenCmp` (l1 `compare` l2) `thenCmp` (c1 `compare` c2)
+cmpSrcLoc (SrcLoc _ _ _) _other = GT
 
 instance Outputable SrcLoc where
     ppr (SrcLoc src_path src_line src_col)
@@ -156,7 +141,6 @@ instance Outputable SrcLoc where
           hcat [text "{-# LINE ", int src_line, space,
                 char '\"', ftext src_path, text " #-}"]
 
-    ppr (ImportedLoc mod) = ptext SLIT("Imported from") <+> text mod
     ppr (UnhelpfulLoc s)  = ftext s
 \end{code}
 
@@ -199,8 +183,6 @@ data SrcSpan
          srcSpanCol      :: !Int
        }
 
-  | ImportedSpan String                -- Module name
-
   | UnhelpfulSpan FastString   -- Just a general indication
                                -- also used to indicate an empty span
 
@@ -212,16 +194,41 @@ instance Ord SrcSpan where
      (srcSpanStart a `compare` srcSpanStart b) `thenCmp` 
      (srcSpanEnd   a `compare` srcSpanEnd   b)
 
-noSrcSpan  = UnhelpfulSpan FSLIT("<no location info>")
+noSrcSpan, wiredInSrcSpan :: SrcSpan
+noSrcSpan      = UnhelpfulSpan FSLIT("<no location info>")
+wiredInSrcSpan = UnhelpfulSpan FSLIT("<wired into compiler>")
 
 mkGeneralSrcSpan :: FastString -> SrcSpan
 mkGeneralSrcSpan = UnhelpfulSpan
 
+isGoodSrcSpan :: SrcSpan -> Bool
 isGoodSrcSpan SrcSpanOneLine{} = True
 isGoodSrcSpan SrcSpanMultiLine{} = True
 isGoodSrcSpan SrcSpanPoint{} = True
 isGoodSrcSpan _ = False
 
+optSrcSpanFileName :: SrcSpan -> Maybe FastString
+optSrcSpanFileName (SrcSpanOneLine { srcSpanFile = nm })   = Just nm
+optSrcSpanFileName (SrcSpanMultiLine { srcSpanFile = nm }) = Just nm
+optSrcSpanFileName (SrcSpanPoint { srcSpanFile = nm})      = Just nm
+optSrcSpanFileName _                                       = Nothing
+
+isOneLineSpan :: SrcSpan -> Bool
+-- True if the span is known to straddle more than one line
+-- By default, it returns False
+isOneLineSpan s
+  | isGoodSrcSpan s = srcSpanStartLine s == srcSpanEndLine s
+  | otherwise      = False             
+
+--------------------------------------------------------
+-- Don't export these four;
+-- they panic on Unhelpful.
+-- They are for internal use only
+-- Urk!  Some are needed for Lexer.x; see comment in export list
+
+srcSpanStartLine, srcSpanEndLine, srcSpanStartCol, srcSpanEndCol
+  :: SrcSpan -> Int
+
 srcSpanStartLine SrcSpanOneLine{ srcSpanLine=l } = l
 srcSpanStartLine SrcSpanMultiLine{ srcSpanSLine=l } = l
 srcSpanStartLine SrcSpanPoint{ srcSpanLine=l } = l
@@ -241,15 +248,15 @@ srcSpanEndCol SrcSpanOneLine{ srcSpanECol=c } = c
 srcSpanEndCol SrcSpanMultiLine{ srcSpanECol=c } = c
 srcSpanEndCol SrcSpanPoint{ srcSpanCol=c } = c
 srcSpanEndCol _ = panic "SrcLoc.srcSpanEndCol"
+--------------------------------------------------------
+
+srcSpanStart, srcSpanEnd :: SrcSpan -> SrcLoc
 
-srcSpanStart (ImportedSpan str) = ImportedLoc str
 srcSpanStart (UnhelpfulSpan str) = UnhelpfulLoc str
-srcSpanStart s = 
-  mkSrcLoc (srcSpanFile s) 
-          (srcSpanStartLine s)
-          (srcSpanStartCol s)
+srcSpanStart s = mkSrcLoc (srcSpanFile s) 
+                         (srcSpanStartLine s)
+                         (srcSpanStartCol s)
 
-srcSpanEnd (ImportedSpan str) = ImportedLoc str
 srcSpanEnd (UnhelpfulSpan str) = UnhelpfulLoc str
 srcSpanEnd s = 
   mkSrcLoc (srcSpanFile s) 
@@ -257,14 +264,11 @@ srcSpanEnd s =
           (srcSpanEndCol s)
 
 srcLocSpan :: SrcLoc -> SrcSpan
-srcLocSpan (ImportedLoc str)  = ImportedSpan str
 srcLocSpan (UnhelpfulLoc str) = UnhelpfulSpan str
 srcLocSpan (SrcLoc file line col) = SrcSpanPoint file line col
 
 mkSrcSpan :: SrcLoc -> SrcLoc -> SrcSpan
-mkSrcSpan (ImportedLoc str) _  = ImportedSpan str
 mkSrcSpan (UnhelpfulLoc str) _ = UnhelpfulSpan str
-mkSrcSpan _ (ImportedLoc str)  = ImportedSpan str
 mkSrcSpan _ (UnhelpfulLoc str) = UnhelpfulSpan str
 mkSrcSpan loc1 loc2
   | line1 == line2 = if col1 == col2
@@ -280,10 +284,8 @@ mkSrcSpan loc1 loc2
 
 combineSrcSpans        :: SrcSpan -> SrcSpan -> SrcSpan
 -- Assumes the 'file' part is the same in both
-combineSrcSpans        (ImportedSpan str) _  = ImportedSpan str
-combineSrcSpans        (UnhelpfulSpan str) r = r -- this seems more useful
-combineSrcSpans        _ (ImportedSpan str)  = ImportedSpan str
-combineSrcSpans        l (UnhelpfulSpan str) = l
+combineSrcSpans        (UnhelpfulSpan _) r = r -- this seems more useful
+combineSrcSpans        l (UnhelpfulSpan _) = l
 combineSrcSpans        start end 
  = case line1 `compare` line2 of
      EQ -> case col1 `compare` col2 of
@@ -299,11 +301,11 @@ combineSrcSpans   start end
        col2  = srcSpanEndCol end
        file  = srcSpanFile start
 
-pprDefnLoc :: SrcLoc -> SDoc
--- "defined at ..." or "imported from ..."
+pprDefnLoc :: SrcSpan -> SDoc
+-- "defined at ..."
 pprDefnLoc loc
-  | isGoodSrcLoc loc = ptext SLIT("Defined at") <+> ppr loc
-  | otherwise       = ppr loc
+  | isGoodSrcSpan loc = ptext SLIT("Defined at") <+> ppr loc
+  | otherwise        = ppr loc
 
 instance Outputable SrcSpan where
     ppr span
@@ -315,6 +317,7 @@ instance Outputable SrcSpan where
                 char '\"', ftext (srcSpanFile span), text " #-}"]
 
 
+pprUserSpan :: SrcSpan -> SDoc
 pprUserSpan (SrcSpanOneLine src_path line start_col end_col)
   = hcat [ ftext src_path, char ':', 
           int line,
@@ -340,7 +343,6 @@ pprUserSpan (SrcSpanPoint src_path line col)
           char ':', int col
         ]
 
-pprUserSpan (ImportedSpan mod) = ptext SLIT("Imported from") <+> quotes (text mod)
 pprUserSpan (UnhelpfulSpan s)  = ftext s
 \end{code}
 
@@ -381,6 +383,34 @@ instance Functor Located where
   fmap f (L l e) = L l (f e)
 
 instance Outputable e => Outputable (Located e) where
-  ppr (L span e) =  ppr e
+  ppr (L _ e) =  ppr e
        -- do we want to dump the span in debugSty mode?    
 \end{code}
+
+
+%************************************************************************
+%*                                                                     *
+\subsection{Manipulating SrcSpans}
+%*                                                                     *
+%************************************************************************
+
+\begin{code}
+leftmost_smallest, leftmost_largest, rightmost :: SrcSpan -> SrcSpan -> Ordering
+rightmost            = flip compare
+leftmost_smallest    = compare 
+leftmost_largest a b = (srcSpanStart a `compare` srcSpanStart b)
+                                `thenCmp`
+                       (srcSpanEnd b `compare` srcSpanEnd a)
+
+
+spans :: SrcSpan -> (Int,Int) -> Bool
+spans span (l,c) = srcSpanStart span <= loc && loc <= srcSpanEnd span
+   where loc = mkSrcLoc (srcSpanFile span) l c
+
+isSubspanOf :: SrcSpan -> SrcSpan -> Bool
+isSubspanOf src parent 
+    | optSrcSpanFileName parent /= optSrcSpanFileName src = False
+    | otherwise = srcSpanStart parent <= srcSpanStart src &&
+                  srcSpanEnd parent   >= srcSpanEnd src
+
+\end{code}