packages feed

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)
 
-------------------------------------------------------------------------------