module Language.Clafer.Intermediate.StringAnalyzer where
import Control.Applicative
import Control.Monad.State
import Data.Tuple
import qualified Data.Map as Map
import Prelude
import Language.Clafer.Intermediate.Intclafer
astrModule :: IModule -> (IModule, Map.Map Int String)
astrModule imodule = (imodule{_mDecls = decls''}, flipMap strMap')
where
decls' = _mDecls imodule
(decls'', strMap') = runState (mapM astrElement decls') Map.empty
flipMap :: Map.Map String Int -> Map.Map Int String
flipMap = Map.fromList . map swap . Map.toList
astrClafer :: Functor m => MonadState (Map.Map String Int) m => IClafer -> m IClafer
astrClafer (IClafer s isAbstract' gcrd' ident' uid' puid' super' reference' crd' gCard elements') = do
reference'' <- astrReference reference'
elements'' <- astrElement `mapM` elements'
return $ IClafer s isAbstract' gcrd' ident' uid' puid' super' reference'' crd' gCard elements''
astrReference :: Functor m => MonadState (Map.Map String Int) m => Maybe IReference -> m (Maybe IReference)
astrReference Nothing = return Nothing
astrReference (Just (IReference isSet' ref')) = Just <$> IReference isSet' `liftM` astrPExp ref'
astrElement :: Functor m => MonadState (Map.Map String Int) m => IElement -> m IElement
astrElement x = case x of
IEClafer clafer -> IEClafer `liftM` astrClafer clafer
IEConstraint isHard' pexp -> IEConstraint isHard' `liftM` astrPExp pexp
IEGoal isMaximize' pexp -> IEGoal isMaximize' `liftM` astrPExp pexp
astrPExp :: Functor m => MonadState (Map.Map String Int) m => PExp -> m PExp
astrPExp (PExp (Just TString) pid' pos' exp') =
PExp (Just TInteger) pid' pos' `liftM` astrIExp exp'
astrPExp (PExp t pid' pos' (IFunExp op' exps')) = PExp t pid' pos' `liftM`
(IFunExp op' `liftM` mapM astrPExp exps')
astrPExp (PExp t pid' pos' (IDeclPExp quant' oDecls' bpexp')) = PExp t pid' pos' `liftM`
(IDeclPExp quant' oDecls' `liftM` (astrPExp bpexp'))
astrPExp x = return x
astrIExp :: Functor m => MonadState (Map.Map String Int) m => IExp -> m IExp
astrIExp x = case x of
IFunExp op' exps' -> IFunExp op' `liftM` mapM astrPExp exps'
IStr str -> do
modify (\e -> Map.insertWith (flip const) str (Map.size e) e)
st <- get
return $ (IInt $ toInteger $ (Map.!) st str)
_ -> return x