AbstractSyntax.hs revision 98890889ffb2e8f6f722b00e265a211f13b5a861
{-# LANGUAGE MagicHash #-}
{- |
Module : $Header$
Description : the abstract syntax of shared ATerms and their lookup table
Copyright : (c) Klaus Luettich, C. Maeder, Uni Bremen 2002-2006
License : GPLv2 or higher, see LICENSE.txt
Maintainer : Christian.Maeder@dfki.de
Stability : provisional
Portability : non-portable(imports System.Mem.StableName and GHC.Prim)
the data types 'ShATerm' and 'ATermTable' plus some utilities
-}
module ATerm.AbstractSyntax
(ShATerm(..),
ATermTable,
emptyATermTable,
addATerm,
getATerm, toReadonlyATT,
getTopIndex,
getATerm', setATerm', getShATerm,
Key, getKey, setKey, mkKey,
getATermByIndex1, str2Char, integer2Int
) where
import qualified Data.Map as Map
import qualified Data.Map as IntMap
import Data.Dynamic
import Data.Array
import System.Mem.StableName
import GHC.Prim
import qualified Data.List as List
import Data.Maybe
data ShATerm =
ShAAppl String [Int] [Int]
| ShAList [Int] [Int]
| ShAInt Integer [Int]
deriving (Show, Eq, Ord)
data IntMap =
Updateable !(IntMap.Map Int ShATerm)
| Readonly !(Array Int ShATerm)
empty :: IntMap
empty = Updateable IntMap.empty
insert :: Int -> ShATerm -> IntMap -> IntMap
insert i s t = case t of
Updateable m -> Updateable $ IntMap.insert i s m
_ -> error "ATerm.insert"
find :: Int -> IntMap -> ShATerm
find i t = case t of
Updateable m -> IntMap.findWithDefault (ShAInt (-1) []) i m
Readonly a -> a ! i
data EqKey = EqKey (StableName ()) TypeRep deriving Eq
data Key = Key Int EqKey
mkKey :: Typeable a => a -> IO Key
mkKey t = do
s <- makeStableName t
return $ Key (hashStableName s) $ EqKey (unsafeCoerce# s) $ typeOf t
data ATermTable = ATT
(IntMap.Map Int [(EqKey, Int)])
!(Map.Map ShATerm Int) !IntMap Int
!(IntMap.Map Int [Dynamic])
toReadonlyATT :: ATermTable -> ATermTable
toReadonlyATT (ATT h s t i dM) = ATT h s
(case t of
Updateable m -> Readonly $ listArray (0, i) $ IntMap.elems m
_ -> t ) i dM
emptyATermTable :: ATermTable
addATermNoFullSharing :: ShATerm -> ATermTable -> (ATermTable, Int)
addATermNoFullSharing t (ATT h a_iDFM i_aDFM i1 dM) = let j = i1 + 1 in
(ATT h (Map.insert t j a_iDFM) (insert j t i_aDFM) j dM, j)
addATerm :: ShATerm -> ATermTable -> (ATermTable, Int)
addATerm t at@(ATT _ a_iDFM _ _ _) =
case Map.lookup t a_iDFM of
Nothing -> addATermNoFullSharing t at
Just i -> (at, i)
setKey :: Key -> Int -> ATermTable -> IO (ATermTable, Int)
setKey (Key h e) i (ATT t s l m d) =
return (ATT (IntMap.insertWith (++) h [(e, i)] t) s l m d, i)
getKey :: Key -> ATermTable -> IO (Maybe Int)
getKey (Key h k) (ATT t _ _ _ _) =
return $ List.lookup k $ IntMap.findWithDefault [] h t
getATerm :: ATermTable -> ShATerm
getATerm (ATT _ _ i_aFM i _) = find i i_aFM
getShATerm :: Int -> ATermTable -> ShATerm
getShATerm i (ATT _ _ i_aFM _ _) = find i i_aFM
getTopIndex :: ATermTable -> Int
getTopIndex (ATT _ _ _ i _) = i
getATermByIndex1 :: Int -> ATermTable -> ATermTable
getATermByIndex1 i (ATT h a_iDFM i_aDFM _ dM) = ATT h a_iDFM i_aDFM i dM
getATerm' :: Typeable t => Int -> ATermTable -> Maybe t
getATerm' i (ATT _ _ _ _ dM) =
listToMaybe $ mapMaybe fromDynamic $ IntMap.findWithDefault [] i dM
setATerm' :: Typeable t => Int -> t -> ATermTable -> ATermTable
setATerm' i t (ATT h a_iDFM i_aDFM m dM) =
ATT h a_iDFM i_aDFM m $ IntMap.insertWith (++) i [toDyn t] dM
-- | conversion of a string in double quotes to a character
str2Char :: String -> Char
str2Char str = case str of
'\"' : sr@(_ : _) -> conv' (init sr) where
conv' r = case r of
[x] -> x
['\\', x] -> case x of
'n' -> '\n'
't' -> '\t'
'r' -> '\r'
'\"' -> '\"'
_ -> error "ATerm.AbstractSyntax: unexpected escape sequence"
_ -> error "ATerm.AbstractSyntax: String not convertible to Char"
_ -> error "ATerm.AbstractSyntax: String doesn't begin with '\"'"
-- | conversion of an unlimited integer to a machine int
integer2Int :: Integer -> Int
integer2Int x = if toInteger ((fromInteger :: Integer -> Int) x) == x
then fromInteger x else
error $ "ATerm.AbstractSyntax: Integer to big for Int: " ++ show x