Item.hs revision 3d3889e0cefcdce9b3f43c53aaa201943ac2e895
{-# LANGUAGE MultiParamTypeClasses, TypeSynonymInstances, FlexibleInstances #-}
{- |
Module : $Header$
Description : positions, simple and mixfix identifiers
Copyright : (c) Christian Maeder and Ewaryst Schulz and Uni Bremen 2009
License : GPLv2 or higher, see LICENSE.txt
Maintainer : Ewaryst.Schulz@dfki.de
Stability : experimental
Portability : non-portable (MPTC)
This module provides the item datatype for an abstract logic independent
representation of basic specs.
-}
module Common.Item where
import Common.Id
import Common.AS_Annotation
import Common.Doc
import Data.Maybe
import Control.Monad
-- element name, attributes and optional text
data ItemType = IT
{ getName :: String
, attrList :: [(String, String)]
, getText :: Maybe Doc }
{- flat items (isFlat=True) are intended for output as xml-attributes
but this is not yet used -}
data Item = Item { itemType :: ItemType
, isFlat :: Bool
, range :: Range
, items :: [Annoted Item]
}
hasValue :: ItemType -> Bool
hasValue (IT _ attrs md) = isJust md || not (null attrs)
instance GetRange Item where
getRange = range
{-
In the following we use these abbreviations:
I = Item
AI = Annoted Item
IT = ItemType or ItemTypeable
-}
{- often we have the situation where we want to obtain an ItemType
from a certain Type: -}
class ItemTypeable a where
toIT :: a -> ItemType
instance ItemTypeable ItemType where
toIT = id
-- intelligent ItemType generation
instance ItemTypeable String where
toIT s = IT s [] Nothing
instance ItemTypeable (String, Doc) where
toIT (s, s') = IT s [] $ Just s'
instance ItemTypeable (String, String, String) where
toIT (s, s', s'') = IT s [(s', s'')] Nothing
class Monad m => ItemConvertible a m where
toitem :: a -> m Item
-- -------------------------- Sublist creation ----------------------------
listFromAL :: ItemConvertible a m => [Annoted a] -> m [Annoted Item]
listFromAL = mapM annToAItem
listFromLWithA :: ItemConvertible a m =>
(Item -> Annoted Item) -> [a] -> m [Annoted Item]
listFromLWithA f = mapM (toAItemWithA f)
listFromL :: ItemConvertible a m => [a] -> m [Annoted Item]
listFromL = mapM toAItem
annToAItem :: ItemConvertible a m => Annoted a -> m (Annoted Item)
annToAItem v = liftM (`replaceAnnoted` v) (toitem $ item v)
toAItemWithA :: ItemConvertible a m =>
(Item -> Annoted Item) -> a -> m (Annoted Item)
toAItemWithA f = liftM f . toitem
toAItem :: ItemConvertible a m => a -> m (Annoted Item)
toAItem = toAItemWithA emptyAnno
-- -------------------------- ItemType lifting ----------------------------
{- often we have the situation where we want to obtain a whole Item
or even an Annoted Item from an ItemType: -}
liftIT2I :: ItemTypeable a => a -> Item
liftIT2I t = mkItem t nullRange []
liftIT2AI :: ItemTypeable a => a -> Annoted Item
liftIT2AI = emptyAnno . liftIT2I
-- -------------------------- Combinators ----------------------------
fromC :: ItemConvertible a m => a -> m (Annoted Item)
fromC = fromAC . emptyAnno
fromAC :: ItemConvertible a m => Annoted a -> m (Annoted Item)
fromAC = annToAItem
fromL :: (ItemConvertible a m, ItemTypeable b) => b -> [a] -> m (Annoted Item)
fromL it l = do
l' <- listFromL l
let i = liftIT2I it
return $ emptyAnno i { items = l' }
fromAL :: (ItemConvertible a m, ItemTypeable b) => b -> [Annoted a] ->
m (Annoted Item)
fromAL it l = do
l' <- listFromAL l
let i = liftIT2I it
return $ emptyAnno i { items = l' }
-- -------------------------- standard items ----------------------------
rootItem :: Item
rootItem = liftIT2I "Basicspec"
mkItem :: ItemTypeable a => a -> Range -> [Annoted Item] -> Item
mkItem it = Item (toIT it) False
mkFlatItem :: ItemTypeable a => a -> Range -> Item
mkFlatItem it rg = Item (toIT it) True rg []
mkItemM :: (ItemTypeable a, Monad m) => a -> Range -> m [Annoted Item] ->
m Item
mkItemM it = liftM . mkItem it
mkItemMM :: (ItemTypeable a, Monad m) => a -> Range -> [m (Annoted Item)] ->
m Item
mkItemMM it rg = mkItemM it rg . sequence
mkFlatItemM :: (ItemTypeable a, Monad m) => a -> Range -> m Item
mkFlatItemM it rg = return $ mkFlatItem it rg
flattenItem :: Item -> Item
flattenItem x = x { isFlat = True }
addRange :: Range -> Item -> Item
addRange rg x = x { range = rg }