module Language.ImProve.Narrow (narrow) where import Data.List import Data.Maybe import Language.ImProve.Core narrow :: Statement -> Statement narrow stmt = assumes where assumes = foldl Sequence Null [ Label lab $ Assume assume | (lab, opt) <- optimizations, assume <- opt stmt ] optimizations = [ ("constantAssigns", constantAssigns) ] constantAssigns :: Statement -> [E Bool] constantAssigns stmt = mapMaybe f1 $ stmtVars stmt where f1 :: VarInfo -> Maybe (E Bool) f1 info@(input, path, init) | input = Nothing | otherwise = do assigns <- lastConstAssign info stmt case (init, nub $ init : assigns) of (Bool _, [_, _]) -> Nothing (_, a) -> return $ foldl1 Or $ map f2 a where f2 :: Const -> E Bool f2 assign = case (init, assign) of (Bool a, Bool b) -> Eq (Ref (V input path a)) (Const b) (Int a, Int b) -> Eq (Ref (V input path a)) (Const b) (Float a, Float b) -> Eq (Ref (V input path a)) (Const b) _ -> undefined lastConstAssign :: VarInfo -> Statement -> Maybe [Const] lastConstAssign info a = do (_, a) <- lastConstAssign a return $ nub a where lastConstAssign :: Statement -> Maybe (Bool, [Const]) lastConstAssign a = case a of AssignBool v (Const a) | varInfo v == info -> Just (True, [const' a]) AssignInt v (Const a) | varInfo v == info -> Just (True, [const' a]) AssignFloat v (Const a) | varInfo v == info -> Just (True, [const' a]) AssignBool v _ | varInfo v == info -> Nothing AssignInt v _ | varInfo v == info -> Nothing AssignFloat v _ | varInfo v == info -> Nothing Branch _ a b -> do (aDone, a) <- lastConstAssign a (bDone, b) <- lastConstAssign b return (aDone && bDone, a ++ b) Sequence a b -> do (bDone, b) <- lastConstAssign b if bDone then return (True, b) else do (aDone, a) <- lastConstAssign a return (aDone, a ++ b) Label _ a -> lastConstAssign a _ -> Just (False, [])