{-# OPTIONS_GHC -fno-warn-unused-binds #-} --TODO module Il.Analyzer (analyzeIl) where import Defs.Structures import Defs.Common import Il.AST import Analyzer hiding (getFunName, getFunArgs, getFunType) import Data.Monoid import Control.Monad.State -- | Runs everything that is needed to analyze a program analyzeIl :: [Function] -> [DSInfo] analyzeIl functions = let dsfs = map generateDSF functions in stupidMerge $ analyzeFunctions dsfs -- | Start the state monad to create a 'DSFun' for function generateDSF :: Function -> DSFun Type generateDSF fn = let (dsus, st) = runState (sumTerms step [getFunBody fn]) (AS []) in let fd = FunDecl (getFunName fn) (getFunType fn) (getFunArgs fn) in DSF fd (getStateCalls st) (generateDSI (getFunName fn) dsus) -- | Analyze a block of terms using the state monad stepBlock :: [Term] -> TermAnalyzer Output stepBlock = sumTerms step -- | Sums the 'DSUse's using the 'step' function and concating the results sumTerms :: (Term -> TermAnalyzer Output) -> [Term] -> TermAnalyzer Output sumTerms f ts = fmap concat (mapM f ts) -- | Function putting a function call in the state putCall :: FunctionName -> [Term] -> TermAnalyzer () putCall name args = do let cleanArgs = map justifyVars args let call = (name, cleanArgs) modify $ \s -> s {getStateCalls = call:getStateCalls s} where justifyVars :: Term -> Maybe VariableName justifyVars (Var v) = Just v -- FIXME should work on function calls returning dses, not only vars justifyVars _ = Nothing -- | Generate 'DSUse's for a single 'Term' step :: Term -> TermAnalyzer Output step (Block body) = stepBlock body step (VarInit _ Ds) = return [] step (InitAssign _ _ Ds) = return [] step (While cond body) = stepBlock [cond,body] step (Funcall name args) = do let opname = case name of -- FIXME nicer with usage of dsinfFunctions from Common F "insert" -> Just InsertVal F "find" -> Just FindByVal F "update" -> Just UpdateByRef F "max" -> Just ExtremalVal F "delete_max" -> Just DeleteExtremalVal _ -> Nothing -- FIXME add reading the function calls argDsus <- stepBlock args funcallDsu <- case opname of Nothing -> do putCall name args return [] Just op -> case head args of -- FIXME dsinfFunctions ds argument recognition Var varname -> return [(varname, DSU op False False)] _ -> error "Not implemented yet" return $ argDsus ++ funcallDsu step (If cond t1 t2) = do dsuCond <- step cond oldState <- get dsuT1 <- step t1 stateT1 <- get put oldState dsuT2 <- step t2 stateT2 <- get put (stateT1 `mappend` stateT2) return $ concat [dsuCond, dsuT1, dsuT2] -- Dummy steps step t = case t of Var _ -> return [] VarInit _ _ -> return [] Inc _ -> return [] Dec _ -> return [] Int _ -> return [] Assign _ t -> step t Lt t1 t2 -> stepBlock [t1, t2] Mul t1 t2 -> stepBlock [t1, t2] s -> error $ "No step for " ++ show s