language-objc-0.4.2.0: src/Language/ObjC/Data/Position.hs
{-# LANGUAGE DeriveDataTypeable, PatternGuards #-}
-----------------------------------------------------------------------------
-- |
-- Module : Language.ObjC.Data.Position
-- Copyright : (c) [1995..2000] Manuel M. T. Chakravarty
-- [2008..2009] Benedikt Huber
-- (c) 2012 John W. Lato
-- License : BSD-style
-- Maintainer : jwlato@gmail.com
-- Stability : experimental
-- Portability : ghc
--
-- Source code position
-----------------------------------------------------------------------------
module Language.ObjC.Data.Position (
--
-- source text positions
--
Position(..),
position,
PosLength(..),
mkPosLength,
unPosLength,
posFile,posRow,posColumn,posOffset,
initPos, isSourcePos,
nopos, isNoPos,
builtinPos, isBuiltinPos,
internalPos, isInternalPos,
incPos, retPos, adjustPos,
incOffset,
Pos(..),
) where
import Data.Generics
-- | uniform representation of source file positions
data Position = Position { posOffset' :: {-# UNPACK #-} !Int -- ^ absolute offset in the preprocessed file
, posFile' :: String -- ^ source file
, posRow' :: {-# UNPACK #-} !Int -- ^ row (line) in the original file. Affected by #LINE pragmas.
, posColumn' :: {-# UNPACK #-} !Int -- ^ column in the preprocessed file. Inaccurate w.r.t. to the original
-- file in the presence of preprocessor macros.
}
| NoPosition
| BuiltinPosition
| InternalPosition
deriving (Eq, Ord, Typeable, Data)
posFile :: Position -> String
posFile (Position{posFile' = ps}) = ps
posFile pos = show pos
posRow :: Position -> Int
posRow (Position{posRow' = pr}) = pr
posRow _ = (-1)
posColumn :: Position -> Int
posColumn (Position{posColumn' = pc}) = pc
posColumn _ = (-1)
posOffset :: Position -> Int
posOffset (Position{posOffset' = po}) = po
posOffset _ = (-1)
-- | Position and length of a token
data PosLength = PL !Position
{-# UNPACK #-} !Int
deriving (Eq, Ord, Data, Typeable, Show)
mkPosLength :: Position -> Int -> PosLength
mkPosLength = PL
unPosLength :: PosLength -> (Position, Int)
unPosLength (PL pos l) = (pos,l)
instance Show Position where
show (Position _ fname row _) = "(" ++ show fname ++ ": line " ++ show row ++ ")"
show NoPosition = "<no file>"
show BuiltinPosition = "<builtin>"
show InternalPosition = "<internal>"
{-# DEPRECATED posColumn "column number information is inaccurate in presence of macros - do not rely on it." #-}
-- | @position absoluteOffset fileName lineNumber columnNumber@ initializes a @Position@ using the given arguments
position :: Int -> String -> Int -> Int -> Position
position = Position
-- | class of type which aggregate a source code location
class Pos a where
posOf :: a -> Position
-- | initialize a Position to the start of the translation unit starting in the given file
initPos :: FilePath -> Position
initPos file = Position 0 file 1 1
-- | returns @True@ if the given position refers to an actual source file
isSourcePos :: Position -> Bool
isSourcePos (Position _ _ _ _) = True
isSourcePos _ = False
-- | no position (for unknown position information)
nopos :: Position
nopos = NoPosition
-- | returns @True@ if the there is no position information available
isNoPos :: Position -> Bool
isNoPos NoPosition = True
isNoPos _ = False
-- | position attached to built-in objects
--
builtinPos :: Position
builtinPos = BuiltinPosition
-- | returns @True@ if the given position refers to a builtin definition
isBuiltinPos :: Position -> Bool
isBuiltinPos BuiltinPosition = True
isBuiltinPos _ = False
-- | position used for internal errors
internalPos :: Position
internalPos = InternalPosition
-- | returns @True@ if the given position is internal
isInternalPos :: Position -> Bool
isInternalPos InternalPosition = True
isInternalPos _ = False
{-# INLINE incPos #-}
-- | advance column
incPos :: Position -> Int -> Position
incPos (Position offs fname row col) n = Position (offs + n) fname row (col + n)
incPos p _ = p
{-# INLINE retPos #-}
-- | advance to next line
retPos :: Position -> Position
retPos (Position offs fname row _) = Position (offs+1) fname (row + 1) 1
retPos p = p
{-# INLINE adjustPos #-}
-- | adjust position: change file and line number, reseting column to 1. This is usually
-- used for #LINE pragmas. The absolute offset is not changed - this can be done
-- by @adjustPos newFile line . incPos (length pragma)@.
adjustPos :: FilePath -> Int -> Position -> Position
adjustPos fname row (Position offs _ _ _) = Position offs fname row 1
adjustPos _ _ p = p
{-# INLINE incOffset #-}
-- | advance just the offset
incOffset :: Position -> Int -> Position
incOffset (Position o f r c) n = Position (o + n) f r c
incOffset p _n = p