7733aee3e15b7c651cf47a9a33addf0a29b3bcd8
[ghc.git] / compiler / basicTypes / SrcLoc.hs
1 -- (c) The University of Glasgow, 1992-2006
2
3 {-# LANGUAGE CPP #-}
4 {-# LANGUAGE DeriveDataTypeable #-}
5 {-# LANGUAGE StandaloneDeriving #-}
6 {-# LANGUAGE DeriveFunctor #-}
7 {-# LANGUAGE DeriveFoldable #-}
8 {-# LANGUAGE DeriveTraversable #-}
9 {-# LANGUAGE FlexibleInstances #-}
10 {-# OPTIONS_GHC -fno-omit-interface-pragmas #-}
11 -- Workaround for Trac #5252 crashes the bootstrap compiler without -O
12 -- When the earliest compiler we want to boostrap with is
13 -- GHC 7.2, we can make RealSrcLoc properly abstract
14
15 -- | This module contains types that relate to the positions of things
16 -- in source files, and allow tagging of those things with locations
17 module SrcLoc (
18 -- * SrcLoc
19 RealSrcLoc, -- Abstract
20 SrcLoc(..),
21
22 -- ** Constructing SrcLoc
23 mkSrcLoc, mkRealSrcLoc, mkGeneralSrcLoc,
24
25 noSrcLoc, -- "I'm sorry, I haven't a clue"
26 generatedSrcLoc, -- Code generated within the compiler
27 interactiveSrcLoc, -- Code from an interactive session
28
29 advanceSrcLoc,
30
31 -- ** Unsafely deconstructing SrcLoc
32 -- These are dubious exports, because they crash on some inputs
33 srcLocFile, -- return the file name part
34 srcLocLine, -- return the line part
35 srcLocCol, -- return the column part
36
37 -- * SrcSpan
38 RealSrcSpan, -- Abstract
39 SrcSpan(..),
40
41 -- ** Constructing SrcSpan
42 mkGeneralSrcSpan, mkSrcSpan, mkRealSrcSpan,
43 noSrcSpan,
44 wiredInSrcSpan, -- Something wired into the compiler
45 interactiveSrcSpan,
46 srcLocSpan, realSrcLocSpan,
47 combineSrcSpans,
48
49 -- ** Deconstructing SrcSpan
50 srcSpanStart, srcSpanEnd,
51 realSrcSpanStart, realSrcSpanEnd,
52 srcSpanFileName_maybe,
53 pprUserRealSpan,
54
55 -- ** Unsafely deconstructing SrcSpan
56 -- These are dubious exports, because they crash on some inputs
57 srcSpanFile,
58 srcSpanStartLine, srcSpanEndLine,
59 srcSpanStartCol, srcSpanEndCol,
60
61 -- ** Predicates on SrcSpan
62 isGoodSrcSpan, isOneLineSpan,
63 containsSpan,
64
65 -- * Located
66 Located,
67 RealLocated,
68 GenLocated(..),
69
70 -- ** Constructing Located
71 noLoc,
72 mkGeneralLocated,
73
74 -- ** Deconstructing Located
75 getLoc, unLoc,
76
77 -- ** Combining and comparing Located values
78 eqLocated, cmpLocated, combineLocs, addCLoc,
79 leftmost_smallest, leftmost_largest, rightmost,
80 spans, isSubspanOf, sortLocated
81 ) where
82
83 import Util
84 import Outputable
85 import FastString
86
87 #if __GLASGOW_HASKELL__ < 709
88 import Data.Foldable ( Foldable )
89 import Data.Traversable ( Traversable )
90 #endif
91 import Data.Bits
92 import Data.Data
93 import Data.List
94 import Data.Ord
95
96 {-
97 ************************************************************************
98 * *
99 \subsection[SrcLoc-SrcLocations]{Source-location information}
100 * *
101 ************************************************************************
102
103 We keep information about the {\em definition} point for each entity;
104 this is the obvious stuff:
105 -}
106
107 -- | Represents a single point within a file
108 data RealSrcLoc
109 = SrcLoc FastString -- A precise location (file name)
110 {-# UNPACK #-} !Int -- line number, begins at 1
111 {-# UNPACK #-} !Int -- column number, begins at 1
112
113 data SrcLoc
114 = RealSrcLoc {-# UNPACK #-}!RealSrcLoc
115 | UnhelpfulLoc FastString -- Just a general indication
116 deriving Show
117
118 {-
119 ************************************************************************
120 * *
121 \subsection[SrcLoc-access-fns]{Access functions}
122 * *
123 ************************************************************************
124 -}
125
126 mkSrcLoc :: FastString -> Int -> Int -> SrcLoc
127 mkSrcLoc x line col = RealSrcLoc (mkRealSrcLoc x line col)
128
129 mkRealSrcLoc :: FastString -> Int -> Int -> RealSrcLoc
130 mkRealSrcLoc x line col = SrcLoc x line col
131
132 -- | Built-in "bad" 'SrcLoc' values for particular locations
133 noSrcLoc, generatedSrcLoc, interactiveSrcLoc :: SrcLoc
134 noSrcLoc = UnhelpfulLoc (fsLit "<no location info>")
135 generatedSrcLoc = UnhelpfulLoc (fsLit "<compiler-generated code>")
136 interactiveSrcLoc = UnhelpfulLoc (fsLit "<interactive>")
137
138 -- | Creates a "bad" 'SrcLoc' that has no detailed information about its location
139 mkGeneralSrcLoc :: FastString -> SrcLoc
140 mkGeneralSrcLoc = UnhelpfulLoc
141
142 -- | Gives the filename of the 'RealSrcLoc'
143 srcLocFile :: RealSrcLoc -> FastString
144 srcLocFile (SrcLoc fname _ _) = fname
145
146 -- | Raises an error when used on a "bad" 'SrcLoc'
147 srcLocLine :: RealSrcLoc -> Int
148 srcLocLine (SrcLoc _ l _) = l
149
150 -- | Raises an error when used on a "bad" 'SrcLoc'
151 srcLocCol :: RealSrcLoc -> Int
152 srcLocCol (SrcLoc _ _ c) = c
153
154 -- | Move the 'SrcLoc' down by one line if the character is a newline,
155 -- to the next 8-char tabstop if it is a tab, and across by one
156 -- character in any other case
157 advanceSrcLoc :: RealSrcLoc -> Char -> RealSrcLoc
158 advanceSrcLoc (SrcLoc f l _) '\n' = SrcLoc f (l + 1) 1
159 advanceSrcLoc (SrcLoc f l c) '\t' = SrcLoc f l (((((c - 1) `shiftR` 3) + 1)
160 `shiftL` 3) + 1)
161 advanceSrcLoc (SrcLoc f l c) _ = SrcLoc f l (c + 1)
162
163 {-
164 ************************************************************************
165 * *
166 \subsection[SrcLoc-instances]{Instance declarations for various names}
167 * *
168 ************************************************************************
169 -}
170
171 -- SrcLoc is an instance of Ord so that we can sort error messages easily
172 instance Eq SrcLoc where
173 loc1 == loc2 = case loc1 `cmpSrcLoc` loc2 of
174 EQ -> True
175 _other -> False
176
177 instance Eq RealSrcLoc where
178 loc1 == loc2 = case loc1 `cmpRealSrcLoc` loc2 of
179 EQ -> True
180 _other -> False
181
182 instance Ord SrcLoc where
183 compare = cmpSrcLoc
184
185 instance Ord RealSrcLoc where
186 compare = cmpRealSrcLoc
187
188 sortLocated :: [Located a] -> [Located a]
189 sortLocated things = sortBy (comparing getLoc) things
190
191 cmpSrcLoc :: SrcLoc -> SrcLoc -> Ordering
192 cmpSrcLoc (UnhelpfulLoc s1) (UnhelpfulLoc s2) = s1 `compare` s2
193 cmpSrcLoc (UnhelpfulLoc _) (RealSrcLoc _) = GT
194 cmpSrcLoc (RealSrcLoc _) (UnhelpfulLoc _) = LT
195 cmpSrcLoc (RealSrcLoc l1) (RealSrcLoc l2) = (l1 `compare` l2)
196
197 cmpRealSrcLoc :: RealSrcLoc -> RealSrcLoc -> Ordering
198 cmpRealSrcLoc (SrcLoc s1 l1 c1) (SrcLoc s2 l2 c2)
199 = (s1 `compare` s2) `thenCmp` (l1 `compare` l2) `thenCmp` (c1 `compare` c2)
200
201 instance Outputable RealSrcLoc where
202 ppr (SrcLoc src_path src_line src_col)
203 = hcat [ pprFastFilePath src_path <> colon
204 , int src_line <> colon
205 , int src_col ]
206
207 -- I don't know why there is this style-based difference
208 -- if userStyle sty || debugStyle sty then
209 -- hcat [ pprFastFilePath src_path, char ':',
210 -- int src_line,
211 -- char ':', int src_col
212 -- ]
213 -- else
214 -- hcat [text "{-# LINE ", int src_line, space,
215 -- char '\"', pprFastFilePath src_path, text " #-}"]
216
217 instance Outputable SrcLoc where
218 ppr (RealSrcLoc l) = ppr l
219 ppr (UnhelpfulLoc s) = ftext s
220
221 instance Data RealSrcSpan where
222 -- don't traverse?
223 toConstr _ = abstractConstr "RealSrcSpan"
224 gunfold _ _ = error "gunfold"
225 dataTypeOf _ = mkNoRepType "RealSrcSpan"
226
227 instance Data SrcSpan where
228 -- don't traverse?
229 toConstr _ = abstractConstr "SrcSpan"
230 gunfold _ _ = error "gunfold"
231 dataTypeOf _ = mkNoRepType "SrcSpan"
232
233 {-
234 ************************************************************************
235 * *
236 \subsection[SrcSpan]{Source Spans}
237 * *
238 ************************************************************************
239 -}
240
241 {- |
242 A SrcSpan delimits a portion of a text file. It could be represented
243 by a pair of (line,column) coordinates, but in fact we optimise
244 slightly by using more compact representations for single-line and
245 zero-length spans, both of which are quite common.
246
247 The end position is defined to be the column /after/ the end of the
248 span. That is, a span of (1,1)-(1,2) is one character long, and a
249 span of (1,1)-(1,1) is zero characters long.
250 -}
251 data RealSrcSpan
252 = SrcSpanOneLine -- a common case: a single line
253 { srcSpanFile :: !FastString,
254 srcSpanLine :: {-# UNPACK #-} !Int,
255 srcSpanSCol :: {-# UNPACK #-} !Int,
256 srcSpanECol :: {-# UNPACK #-} !Int
257 }
258
259 | SrcSpanMultiLine
260 { srcSpanFile :: !FastString,
261 srcSpanSLine :: {-# UNPACK #-} !Int,
262 srcSpanSCol :: {-# UNPACK #-} !Int,
263 srcSpanELine :: {-# UNPACK #-} !Int,
264 srcSpanECol :: {-# UNPACK #-} !Int
265 }
266
267 | SrcSpanPoint
268 { srcSpanFile :: !FastString,
269 srcSpanLine :: {-# UNPACK #-} !Int,
270 srcSpanCol :: {-# UNPACK #-} !Int
271 }
272 deriving (Eq, Typeable)
273
274 data SrcSpan =
275 RealSrcSpan !RealSrcSpan
276 | UnhelpfulSpan !FastString -- Just a general indication
277 -- also used to indicate an empty span
278
279 deriving (Eq, Ord, Typeable, Show) -- Show is used by Lexer.x, because we
280 -- derive Show for Token
281
282 -- | Built-in "bad" 'SrcSpan's for common sources of location uncertainty
283 noSrcSpan, wiredInSrcSpan, interactiveSrcSpan :: SrcSpan
284 noSrcSpan = UnhelpfulSpan (fsLit "<no location info>")
285 wiredInSrcSpan = UnhelpfulSpan (fsLit "<wired into compiler>")
286 interactiveSrcSpan = UnhelpfulSpan (fsLit "<interactive>")
287
288 -- | Create a "bad" 'SrcSpan' that has not location information
289 mkGeneralSrcSpan :: FastString -> SrcSpan
290 mkGeneralSrcSpan = UnhelpfulSpan
291
292 -- | Create a 'SrcSpan' corresponding to a single point
293 srcLocSpan :: SrcLoc -> SrcSpan
294 srcLocSpan (UnhelpfulLoc str) = UnhelpfulSpan str
295 srcLocSpan (RealSrcLoc l) = RealSrcSpan (realSrcLocSpan l)
296
297 realSrcLocSpan :: RealSrcLoc -> RealSrcSpan
298 realSrcLocSpan (SrcLoc file line col) = SrcSpanPoint file line col
299
300 -- | Create a 'SrcSpan' between two points in a file
301 mkRealSrcSpan :: RealSrcLoc -> RealSrcLoc -> RealSrcSpan
302 mkRealSrcSpan loc1 loc2
303 | line1 == line2 = if col1 == col2
304 then SrcSpanPoint file line1 col1
305 else SrcSpanOneLine file line1 col1 col2
306 | otherwise = SrcSpanMultiLine file line1 col1 line2 col2
307 where
308 line1 = srcLocLine loc1
309 line2 = srcLocLine loc2
310 col1 = srcLocCol loc1
311 col2 = srcLocCol loc2
312 file = srcLocFile loc1
313
314 -- | Create a 'SrcSpan' between two points in a file
315 mkSrcSpan :: SrcLoc -> SrcLoc -> SrcSpan
316 mkSrcSpan (UnhelpfulLoc str) _ = UnhelpfulSpan str
317 mkSrcSpan _ (UnhelpfulLoc str) = UnhelpfulSpan str
318 mkSrcSpan (RealSrcLoc loc1) (RealSrcLoc loc2)
319 = RealSrcSpan (mkRealSrcSpan loc1 loc2)
320
321 -- | Combines two 'SrcSpan' into one that spans at least all the characters
322 -- within both spans. Assumes the "file" part is the same in both inputs
323 combineSrcSpans :: SrcSpan -> SrcSpan -> SrcSpan
324 combineSrcSpans (UnhelpfulSpan _) r = r -- this seems more useful
325 combineSrcSpans l (UnhelpfulSpan _) = l
326 combineSrcSpans (RealSrcSpan span1) (RealSrcSpan span2)
327 = RealSrcSpan (combineRealSrcSpans span1 span2)
328
329 -- | Combines two 'SrcSpan' into one that spans at least all the characters
330 -- within both spans. Assumes the "file" part is the same in both inputs
331 combineRealSrcSpans :: RealSrcSpan -> RealSrcSpan -> RealSrcSpan
332 combineRealSrcSpans span1 span2
333 = if line_start == line_end
334 then if col_start == col_end
335 then SrcSpanPoint file line_start col_start
336 else SrcSpanOneLine file line_start col_start col_end
337 else SrcSpanMultiLine file line_start col_start line_end col_end
338 where
339 (line_start, col_start) = min (srcSpanStartLine span1, srcSpanStartCol span1)
340 (srcSpanStartLine span2, srcSpanStartCol span2)
341 (line_end, col_end) = max (srcSpanEndLine span1, srcSpanEndCol span1)
342 (srcSpanEndLine span2, srcSpanEndCol span2)
343 file = srcSpanFile span1
344
345 {-
346 ************************************************************************
347 * *
348 \subsection[SrcSpan-predicates]{Predicates}
349 * *
350 ************************************************************************
351 -}
352
353 -- | Test if a 'SrcSpan' is "good", i.e. has precise location information
354 isGoodSrcSpan :: SrcSpan -> Bool
355 isGoodSrcSpan (RealSrcSpan _) = True
356 isGoodSrcSpan (UnhelpfulSpan _) = False
357
358 isOneLineSpan :: SrcSpan -> Bool
359 -- ^ True if the span is known to straddle only one line.
360 -- For "bad" 'SrcSpan', it returns False
361 isOneLineSpan (RealSrcSpan s) = srcSpanStartLine s == srcSpanEndLine s
362 isOneLineSpan (UnhelpfulSpan _) = False
363
364 -- | Tests whether the first span "contains" the other span, meaning
365 -- that it covers at least as much source code. True where spans are equal.
366 containsSpan :: RealSrcSpan -> RealSrcSpan -> Bool
367 containsSpan s1 s2
368 = srcSpanFile s1 == srcSpanFile s2
369 && (srcSpanStartLine s1, srcSpanStartCol s1)
370 <= (srcSpanStartLine s2, srcSpanStartCol s2)
371 && (srcSpanEndLine s1, srcSpanEndCol s1)
372 >= (srcSpanEndLine s2, srcSpanEndCol s2)
373
374 {-
375 %************************************************************************
376 %* *
377 \subsection[SrcSpan-unsafe-access-fns]{Unsafe access functions}
378 * *
379 ************************************************************************
380 -}
381
382 srcSpanStartLine :: RealSrcSpan -> Int
383 srcSpanEndLine :: RealSrcSpan -> Int
384 srcSpanStartCol :: RealSrcSpan -> Int
385 srcSpanEndCol :: RealSrcSpan -> Int
386
387 srcSpanStartLine SrcSpanOneLine{ srcSpanLine=l } = l
388 srcSpanStartLine SrcSpanMultiLine{ srcSpanSLine=l } = l
389 srcSpanStartLine SrcSpanPoint{ srcSpanLine=l } = l
390
391 srcSpanEndLine SrcSpanOneLine{ srcSpanLine=l } = l
392 srcSpanEndLine SrcSpanMultiLine{ srcSpanELine=l } = l
393 srcSpanEndLine SrcSpanPoint{ srcSpanLine=l } = l
394
395 srcSpanStartCol SrcSpanOneLine{ srcSpanSCol=l } = l
396 srcSpanStartCol SrcSpanMultiLine{ srcSpanSCol=l } = l
397 srcSpanStartCol SrcSpanPoint{ srcSpanCol=l } = l
398
399 srcSpanEndCol SrcSpanOneLine{ srcSpanECol=c } = c
400 srcSpanEndCol SrcSpanMultiLine{ srcSpanECol=c } = c
401 srcSpanEndCol SrcSpanPoint{ srcSpanCol=c } = c
402
403 {-
404 ************************************************************************
405 * *
406 \subsection[SrcSpan-access-fns]{Access functions}
407 * *
408 ************************************************************************
409 -}
410
411 -- | Returns the location at the start of the 'SrcSpan' or a "bad" 'SrcSpan' if that is unavailable
412 srcSpanStart :: SrcSpan -> SrcLoc
413 srcSpanStart (UnhelpfulSpan str) = UnhelpfulLoc str
414 srcSpanStart (RealSrcSpan s) = RealSrcLoc (realSrcSpanStart s)
415
416 -- | Returns the location at the end of the 'SrcSpan' or a "bad" 'SrcSpan' if that is unavailable
417 srcSpanEnd :: SrcSpan -> SrcLoc
418 srcSpanEnd (UnhelpfulSpan str) = UnhelpfulLoc str
419 srcSpanEnd (RealSrcSpan s) = RealSrcLoc (realSrcSpanEnd s)
420
421 realSrcSpanStart :: RealSrcSpan -> RealSrcLoc
422 realSrcSpanStart s = mkRealSrcLoc (srcSpanFile s)
423 (srcSpanStartLine s)
424 (srcSpanStartCol s)
425
426 realSrcSpanEnd :: RealSrcSpan -> RealSrcLoc
427 realSrcSpanEnd s = mkRealSrcLoc (srcSpanFile s)
428 (srcSpanEndLine s)
429 (srcSpanEndCol s)
430
431 -- | Obtains the filename for a 'SrcSpan' if it is "good"
432 srcSpanFileName_maybe :: SrcSpan -> Maybe FastString
433 srcSpanFileName_maybe (RealSrcSpan s) = Just (srcSpanFile s)
434 srcSpanFileName_maybe (UnhelpfulSpan _) = Nothing
435
436 {-
437 ************************************************************************
438 * *
439 \subsection[SrcSpan-instances]{Instances}
440 * *
441 ************************************************************************
442 -}
443
444 -- We want to order RealSrcSpans first by the start point, then by the
445 -- end point.
446 instance Ord RealSrcSpan where
447 a `compare` b =
448 (realSrcSpanStart a `compare` realSrcSpanStart b) `thenCmp`
449 (realSrcSpanEnd a `compare` realSrcSpanEnd b)
450
451 instance Show RealSrcLoc where
452 show (SrcLoc filename row col)
453 = "SrcLoc " ++ show filename ++ " " ++ show row ++ " " ++ show col
454
455 -- Show is used by Lexer.x, because we derive Show for Token
456 instance Show RealSrcSpan where
457 show (SrcSpanOneLine file l sc ec)
458 = "SrcSpanOneLine " ++ show file ++ " "
459 ++ intercalate " " (map show [l,sc,ec])
460 show (SrcSpanMultiLine file sl sc el ec)
461 = "SrcSpanMultiLine " ++ show file ++ " "
462 ++ intercalate " " (map show [sl,sc,el,ec])
463 show (SrcSpanPoint file l c)
464 = "SrcSpanPoint " ++ show file ++ " " ++ intercalate " " (map show [l,c])
465
466
467 instance Outputable RealSrcSpan where
468 ppr span = pprUserRealSpan True span
469
470 -- I don't know why there is this style-based difference
471 -- = getPprStyle $ \ sty ->
472 -- if userStyle sty || debugStyle sty then
473 -- text (showUserRealSpan True span)
474 -- else
475 -- hcat [text "{-# LINE ", int (srcSpanStartLine span), space,
476 -- char '\"', pprFastFilePath $ srcSpanFile span, text " #-}"]
477
478 instance Outputable SrcSpan where
479 ppr span = pprUserSpan True span
480
481 -- I don't know why there is this style-based difference
482 -- = getPprStyle $ \ sty ->
483 -- if userStyle sty || debugStyle sty then
484 -- pprUserSpan True span
485 -- else
486 -- case span of
487 -- UnhelpfulSpan _ -> panic "Outputable UnhelpfulSpan"
488 -- RealSrcSpan s -> ppr s
489
490 pprUserSpan :: Bool -> SrcSpan -> SDoc
491 pprUserSpan _ (UnhelpfulSpan s) = ftext s
492 pprUserSpan show_path (RealSrcSpan s) = pprUserRealSpan show_path s
493
494 pprUserRealSpan :: Bool -> RealSrcSpan -> SDoc
495 pprUserRealSpan show_path (SrcSpanOneLine src_path line start_col end_col)
496 = hcat [ ppWhen show_path (pprFastFilePath src_path <> colon)
497 , int line <> colon
498 , int start_col
499 , ppUnless (end_col - start_col <= 1) (char '-' <> int (end_col - 1)) ]
500 -- For single-character or point spans, we just
501 -- output the starting column number
502
503 pprUserRealSpan show_path (SrcSpanMultiLine src_path sline scol eline ecol)
504 = hcat [ ppWhen show_path (pprFastFilePath src_path <> colon)
505 , parens (int sline <> comma <> int scol)
506 , char '-'
507 , parens (int eline <> comma <> int ecol') ]
508 where
509 ecol' = if ecol == 0 then ecol else ecol - 1
510
511 pprUserRealSpan show_path (SrcSpanPoint src_path line col)
512 = hcat [ ppWhen show_path (pprFastFilePath src_path <> colon)
513 , int line <> colon
514 , int col ]
515
516 {-
517 ************************************************************************
518 * *
519 \subsection[Located]{Attaching SrcSpans to things}
520 * *
521 ************************************************************************
522 -}
523
524 -- | We attach SrcSpans to lots of things, so let's have a datatype for it.
525 data GenLocated l e = L l e
526 deriving (Eq, Ord, Typeable, Data, Functor, Foldable, Traversable)
527
528 type Located e = GenLocated SrcSpan e
529 type RealLocated e = GenLocated RealSrcSpan e
530
531 unLoc :: GenLocated l e -> e
532 unLoc (L _ e) = e
533
534 getLoc :: GenLocated l e -> l
535 getLoc (L l _) = l
536
537 noLoc :: e -> Located e
538 noLoc e = L noSrcSpan e
539
540 mkGeneralLocated :: String -> e -> Located e
541 mkGeneralLocated s e = L (mkGeneralSrcSpan (fsLit s)) e
542
543 combineLocs :: Located a -> Located b -> SrcSpan
544 combineLocs a b = combineSrcSpans (getLoc a) (getLoc b)
545
546 -- | Combine locations from two 'Located' things and add them to a third thing
547 addCLoc :: Located a -> Located b -> c -> Located c
548 addCLoc a b c = L (combineSrcSpans (getLoc a) (getLoc b)) c
549
550 -- not clear whether to add a general Eq instance, but this is useful sometimes:
551
552 -- | Tests whether the two located things are equal
553 eqLocated :: Eq a => Located a -> Located a -> Bool
554 eqLocated a b = unLoc a == unLoc b
555
556 -- not clear whether to add a general Ord instance, but this is useful sometimes:
557
558 -- | Tests the ordering of the two located things
559 cmpLocated :: Ord a => Located a -> Located a -> Ordering
560 cmpLocated a b = unLoc a `compare` unLoc b
561
562 instance (Outputable l, Outputable e) => Outputable (GenLocated l e) where
563 ppr (L l e) = -- TODO: We can't do this since Located was refactored into
564 -- GenLocated:
565 -- Print spans without the file name etc
566 -- ifPprDebug (braces (pprUserSpan False l))
567 ifPprDebug (braces (ppr l))
568 $$ ppr e
569
570 {-
571 ************************************************************************
572 * *
573 \subsection{Ordering SrcSpans for InteractiveUI}
574 * *
575 ************************************************************************
576 -}
577
578 -- | Alternative strategies for ordering 'SrcSpan's
579 leftmost_smallest, leftmost_largest, rightmost :: SrcSpan -> SrcSpan -> Ordering
580 rightmost = flip compare
581 leftmost_smallest = compare
582 leftmost_largest a b = (srcSpanStart a `compare` srcSpanStart b)
583 `thenCmp`
584 (srcSpanEnd b `compare` srcSpanEnd a)
585
586 -- | Determines whether a span encloses a given line and column index
587 spans :: SrcSpan -> (Int, Int) -> Bool
588 spans (UnhelpfulSpan _) _ = panic "spans UnhelpfulSpan"
589 spans (RealSrcSpan span) (l,c) = realSrcSpanStart span <= loc && loc <= realSrcSpanEnd span
590 where loc = mkRealSrcLoc (srcSpanFile span) l c
591
592 -- | Determines whether a span is enclosed by another one
593 isSubspanOf :: SrcSpan -- ^ The span that may be enclosed by the other
594 -> SrcSpan -- ^ The span it may be enclosed by
595 -> Bool
596 isSubspanOf src parent
597 | srcSpanFileName_maybe parent /= srcSpanFileName_maybe src = False
598 | otherwise = srcSpanStart parent <= srcSpanStart src &&
599 srcSpanEnd parent >= srcSpanEnd src