------------------------------------------------------------------------------
--- RootReplaced analysis:
--- This analysis returns for each function f all functions to which this can
--- be replaced at the root. For instance, if there are the definitions:
---
--- f x = g x
--- g x = h x
--- h x = k x : []
---
--- then the root replacements of f are [g,h].
---
--- This analysis could be useful to detect simple loops, e.g., if
--- a function is in its root replacement. This is the purpose
--- of the analysis `RootCyclic` which assigns `True` to some
--- operation if this operation might cause a cyclic root replacement.
---
--- @author Michael Hanus
--- @version January 2017
------------------------------------------------------------------------------
module Analysis.RootReplaced
( rootReplAnalysis, showRootRepl
, rootCyclicAnalysis, showRootCyclic
)
where
import Analysis.Types
import Analysis.ProgInfo
import FlatCurry.Types
import List
import Sort(sort)
------------------------------------------------------------------------------
--- Data type to represent root replacement information.
--- Basically, it is the set (represented as a sorted list) of
--- all function names to which a function can be replaced (directly
--- or by several steps) at the root
--- together with a list of arguments (which are numbered from 0)
--- which might be projected into the result.
--- The latter is necessary to compute the root replacement
--- information for definitions like `look = id loop`.
type RootReplaced = ([QName],[Int])
-- Show root-replacement information as a string.
showRootRepl :: AOutFormat -> RootReplaced -> String
showRootRepl AText ([],_) = "no root replacements"
showRootRepl ANote ([],_) = ""
showRootRepl AText (xs@(_:_),_) =
"root replacements: " ++ intercalate "," (map (\ (mn,fn) -> mn++"."++fn) xs)
showRootRepl ANote (xs@(_:_),_) = "[" ++ intercalate "," (map snd xs) ++ "]"
--- Root replacement analysis.
rootReplAnalysis :: Analysis RootReplaced
rootReplAnalysis = dependencyFuncAnalysis "RootReplaced" ([],[]) rrFunc
rrFunc :: FuncDecl -> [(QName,RootReplaced)] -> RootReplaced
rrFunc (Func _ _ _ _ rule) calledFuncs = rrFuncRule calledFuncs rule
rrFuncRule :: [(QName,RootReplaced)] -> Rule -> RootReplaced
rrFuncRule _ (External _) = ([],[]) -- nothing known about external functions
rrFuncRule calledFuncs (Rule args rhs) = rrOfExp rhs
where
rrOfExp exp = case exp of
Var v -> maybe ([],[]) (\i -> ([],[i])) (elemIndex v args)
Lit _ -> ([],[])
Comb ct g gargs ->
if ct == FuncCall
then maybe (error $ "Abstract value of " ++ show g ++ " not found!")
(\ (grrs,gps) ->
foldr lub (if g `elem` grrs
then grrs
else insertBy (<=) g grrs, [])
(map (\pi -> rrOfExp (gargs!!pi)) gps))
(lookup g calledFuncs)
else ([],[])
Typed e _ -> rrOfExp e
Free _ e -> rrOfExp e
Let _ e -> rrOfExp e
Or e1 e2 -> lub (rrOfExp e1) (rrOfExp e2)
Case _ e bs -> foldr lub (rrOfExp e)
(map (\ (Branch _ be) -> rrOfExp be) bs)
lub (rr1,p1) (rr2,p2) = (sort (union rr1 rr2), sort (union p1 p2))
------------------------------------------------------------------------------
-- Show root-cyclic information as a string.
showRootCyclic :: AOutFormat -> Bool -> String
showRootCyclic AText False = "no cycles at the root"
showRootCyclic ANote False = ""
showRootCyclic AText True = "possible cyclic root replacement"
showRootCyclic ANote True = "root-cyclic"
--- Root cyclic analysis.
rootCyclicAnalysis :: Analysis Bool
rootCyclicAnalysis =
combinedSimpleFuncAnalysis "RootCyclic" rootReplAnalysis rcFunc
rcFunc :: ProgInfo RootReplaced -> FuncDecl -> Bool
-- we assume that external functions are not root cyclic:
rcFunc _ (Func _ _ _ _ (External _)) = False
-- otherwise we check whether the operation is in its set of root replacements:
rcFunc rrinfo (Func qf _ _ _ (Rule _ _)) =
maybe True -- no information, but this case should not occur
(\rrfuncs -> qf `elem` (fst rrfuncs) -- direct cycle
-- or cycle in some root-replacement:
|| any (\rrf -> maybe True
(\fs -> rrf `elem` (fst fs))
(lookupProgInfo rrf rrinfo))
(fst rrfuncs))
(lookupProgInfo qf rrinfo)
------------------------------------------------------------------------------