HaRe-0.6: StrategyLib-4.0-beta/examples/haskell/HsFreeNames.hs
module HsFreeNames where
-------------------------------------------------------------------------------
-- This module implements free name analysis for Haskell.
-- Under construction!!!
-- We are not yet faithfully dealing with qualified vs. unqualified names.
-- Same holds for module level analysis.
-------------------------------------------------------------------------------
import Language.Haskell.Syntax
import SyntaxTermInstances
import StrategyLib
import Data.List
import Control.Monad
import Data.Monoid
-------------------------------------------------------------------------------
-- The main function of analysis.
-- We use the stop_td scheme.
-- We define ad hoc cases for several syntactical domains.
-- Ad hoc cases are meant to restart recursion.
hsFreeAndDeclared :: (Term t, MonadPlus m) => t -> m ([HsQName],[HsQName])
hsFreeAndDeclared = applyTU (stop_tdTU worker)
where
worker = failTU `adhocTU` exp
`adhocTU` pat
`adhocTU` match
`adhocTU` alt
`adhocTU` decls
`adhocTU` stmts
exp (HsVar qn) = return ([qn],[])
exp (HsCon qn) = return ([qn],[])
exp (HsLambda _ pats body)
= do (pf,pd) <- hsFreeAndDeclared pats
(bf,bd) <- hsFreeAndDeclared body
return ((bf `union` pf) \\ pd,[])
exp (HsLet decls exp)
= do (df,dd) <- hsFreeAndDeclared decls
(ef,ed) <- hsFreeAndDeclared exp
return (df `union` (ef \\ dd),[])
exp (HsListComp exp stmts)
= hsFreeAndDeclared (stmts ++ [HsQualifier exp])
exp (HsRecConstr qn e) = addFree qn (hsFreeAndDeclared e)
exp _ = mzero
pat (HsPVar n) = return ([],[UnQual n])
pat (HsPInfixApp p1 qn p2) = addFree qn (hsFreeAndDeclared [p1,p2])
pat (HsPApp qn pats) = addFree qn (hsFreeAndDeclared pats)
pat (HsPRec qn fields) = addFree qn (hsFreeAndDeclared fields)
pat _ = mzero
match (HsMatch _ fun pats rhs {-where-} decls)
= do (pf,pd) <- hsFreeAndDeclared pats
(rf,rd) <- hsFreeAndDeclared rhs
(df,dd) <- hsFreeAndDeclared decls
let qfun = UnQual fun
return ( pf `union` (((rf \\ (dd `union` [qfun]) `union` df) \\ pd)),
[qfun] )
alt (HsAlt _ pat exp decls)
= do (pf,pd) <- hsFreeAndDeclared pat
(ef,ed) <- hsFreeAndDeclared exp
(df,dd) <- hsFreeAndDeclared decls
return (pf `union` (((ef \\ dd) `union` df) \\ pd),[])
decls (ds::[HsDecl])
= do (f,d) <- hsFreeAndDeclaredList ds
return (f \\ d, d)
stmts (HsGenerator _ pat exp:stmts)
= do (pf,pd) <- hsFreeAndDeclared pat
(ef,ed) <- hsFreeAndDeclared exp
(sf,sd) <- hsFreeAndDeclared stmts
return (pf `union` ef `union` (sf \\ pd),[])
stmts (HsLetStmt decls:stmts)
= do (df,dd) <- hsFreeAndDeclared decls
(sf,sd) <- hsFreeAndDeclared stmts
return (df `union` (sf \\ dd),[])
stmts _ = mzero
addFree free mfd = do (f,d) <- mfd
return ([free] `union` f,d)
hsFreeAndDeclaredList :: (Term t, MonadPlus m) => [t] -> m ([HsQName],[HsQName])
hsFreeAndDeclaredList l
= do fds <- mapM hsFreeAndDeclared l
return ( foldr union [] (map fst fds),
foldr union [] (map snd fds) )
-------------------------------------------------------------------------------
-- This should go somewhere else.
-- instance (Monoid a, Monoid b) => Monoid (a,b) where
-- mappend (a,b) (a',b') = (mappend a a', mappend b b')
-- mempty = (mempty,mempty)
-------------------------------------------------------------------------------