module Language.C.Data.Node (
NodeInfo(..), undefNode, isUndefNode,
mkNodeInfoOnlyPos,mkNodeInfoPosLen, mkNodeInfo,mkNodeInfo',
internalNode,
CNode(nodeInfo), fileOfNode,
posOfNode, nameOfNode, getLastTokenPos, lengthOfNode,
eqByName,
) where
import Language.C.Data.Position
import Language.C.Data.Name (Name)
import Data.Generics
data NodeInfo = OnlyPos Position !PosLength
| NodeInfo Position !PosLength !Name
deriving (Data,Typeable)
instance Show NodeInfo where
showsPrec d (OnlyPos p l) =
(showString "(OnlyPos ") . (showsPrec d p) . (showString " ") . (showsPrec d l) . (showString ")")
showsPrec d (NodeInfo p l n) =
(showString "(NodeInfo ") . (showsPrec d p) . (showString " ") . (showsPrec d l) . (showString " ") . (showsPrec d n) . (showString ")")
instance Eq NodeInfo where
(NodeInfo _ _ id1) == (NodeInfo _ _ id2) = id1 == id2
_ == _ =
error "Attributes: Attempt to compare `OnlyPos' attributes!"
instance Ord NodeInfo where
(NodeInfo _ _ id1) <= (NodeInfo _ _ id2) = id1 <= id2
_ <= _ =
error "Attributes: Attempt to compare `OnlyPos' attributes!"
instance Pos NodeInfo where
posOf (OnlyPos pos _) = pos
posOf (NodeInfo pos _ _) = pos
lengthOfNode :: NodeInfo -> Maybe Int
lengthOfNode ni = len
where
len = case ni of NodeInfo firstPos lastTok _ -> computeLength firstPos lastTok
OnlyPos firstPos lastTok -> computeLength firstPos lastTok
computeLength pos (lastPos,len) | len < 0 = Nothing
| otherwise = Just (posOffset lastPos + len posOffset pos)
getLastTokenPos :: NodeInfo -> PosLength
getLastTokenPos (NodeInfo _ lastTok _) = lastTok
getLastTokenPos (OnlyPos _ lastTok) = lastTok
class CNode a where
nodeInfo :: a -> NodeInfo
instance CNode NodeInfo where
nodeInfo = id
instance (CNode a, CNode b) => CNode (Either a b) where
nodeInfo = either nodeInfo nodeInfo
nameOfNode :: NodeInfo -> Maybe Name
nameOfNode (OnlyPos _ _) = Nothing
nameOfNode (NodeInfo _ _ name) = Just name
posOfNode :: NodeInfo -> Position
posOfNode ni = case ni of (OnlyPos pos _) -> pos; (NodeInfo pos _ _) -> pos
fileOfNode :: (CNode a) => a -> Maybe FilePath
fileOfNode = fmap posFile . justIf isSourcePos . posOfNode . nodeInfo where
justIf predicate x | predicate x = Just x
| otherwise = Nothing
eqByName :: CNode a => a -> a -> Bool
eqByName obj1 obj2 = (nodeInfo obj1) == (nodeInfo obj2)
internalNode :: NodeInfo
internalNode = undefNode
undefNode :: NodeInfo
undefNode = OnlyPos nopos (nopos,1)
isUndefNode :: NodeInfo -> Bool
isUndefNode (OnlyPos p _) | isNoPos p = True
| otherwise = False
isUndefNode _ = False
mkNodeInfoOnlyPos :: Position -> NodeInfo
mkNodeInfoOnlyPos pos = OnlyPos pos (nopos,1)
mkNodeInfoPosLen :: Position -> PosLength -> NodeInfo
mkNodeInfoPosLen = OnlyPos
mkNodeInfo :: Position -> Name -> NodeInfo
mkNodeInfo pos name = NodeInfo pos (nopos,1) name
mkNodeInfo' :: Position -> PosLength -> Name -> NodeInfo
mkNodeInfo' pos lasttok name = NodeInfo pos lasttok name