module Language.ObjC.Data.Node (
NodeInfo(..), undefNode, isUndefNode,
mkNodeInfoOnlyPos,mkNodeInfoPosLen, mkNodeInfo,mkNodeInfo',
internalNode,
CNode(nodeInfo), fileOfNode,
posOfNode, nameOfNode, getLastTokenPos, lengthOfNode,
eqByName,
) where
import Language.ObjC.Data.Position
import Language.ObjC.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 (PL 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 (PL nopos nO)
isUndefNode :: NodeInfo -> Bool
isUndefNode (OnlyPos p _) | isNoPos p = True
| otherwise = False
isUndefNode _ = False
nO :: Int
nO = (1)
mkNodeInfoOnlyPos :: Position -> NodeInfo
mkNodeInfoOnlyPos pos = OnlyPos pos (PL nopos nO)
mkNodeInfoPosLen :: Position -> (Position,Int) -> NodeInfo
mkNodeInfoPosLen p pl = OnlyPos p (uncurry PL pl)
mkNodeInfo :: Position -> Name -> NodeInfo
mkNodeInfo pos name = NodeInfo pos (PL nopos nO) name
mkNodeInfo' :: Position -> (Position,Int) -> Name -> NodeInfo
mkNodeInfo' pos lasttok name = NodeInfo pos (uncurry PL lasttok) name