{- ---------------------------------------------------------------------------
Basic data type and functions for "need" analysis
-}
module NeedLib(initNeed,needit,NeedLib,pushNeed,popNeed,bindTid,needTid
,NeedTable,needQualify) where
-- ,TokenId,IdKind,Memo(..),Tree) where
import TokenId(TokenId(..))
import TokenInt(tokenAllways,tokenMain)
import IdKind
import qualified Data.Map as Map
import qualified Data.Set as Set
import Overlap (Overlap,addOverlap)
import Syntax hiding (TokenId)
-- Added in H98: the overlap table, which allows for later resolution of
-- shared module aliases.
type NeedTable = Map.Map (TokenId,IdKind) [Pos]
data NeedLib = NeedLib (TokenId -> [TokenId]) -- qualified renaming
(Set.Set (TokenId,IdKind)) -- tids already seen
[Set.Set (TokenId,IdKind)] -- stack of memos
-- (Map.Map (TokenId,IdKind) (Bool,TokenId,[TokenId]))
-- overlap table
Overlap -- overlaps for later resolution
NeedTable -- final need-table
initNeed :: Bool -> NeedTable
initNeed b = foldr (\(k,t) a -> Map.insert (t,k) [] a) Map.empty initNeed'
where initNeed' = tokenAllways ++ (if b then tokenMain else [])
needit :: (NeedLib -> NeedLib)
-> (TokenId -> [TokenId])
-> NeedTable
-> (NeedTable,Overlap)
needit n r iNeed =
case n (NeedLib r Set.empty [] Map.empty iNeed) of
(NeedLib r m [] o n) -> (n,o)
pushNeed :: NeedLib -> NeedLib
pushNeed (NeedLib r m ms o n) = NeedLib r m (m:ms) o n
popNeed :: NeedLib -> NeedLib
popNeed (NeedLib r _ (m:ms) o n) = NeedLib r m ms o n
-- This version of bindTid was for Haskell 1.3, before the introduction
-- of overlapping import renamings.
--
--bindTid idKind tid (NeedLib r m ms o n) = NeedLib r (addM m (r tid,idKind)) ms o n
{-
memoise identifier together with its kind
-}
bindTid :: IdKind -> TokenId -> NeedLib -> NeedLib
bindTid idKind tid (NeedLib r m ms o n) =
NeedLib r (foldr memoise m (r tid)) ms o n
where
memoise :: TokenId -> Set.Set (TokenId,IdKind) -> Set.Set (TokenId,IdKind)
memoise tid m = Set.insert (tid,idKind) m
-- This version of needTid was for Haskell 1.3, before the introduction
-- of overlapping import renamings.
--
--needTid pos idKind tid needlib@(NeedLib r m ms o n) =
-- case r tid of
-- [tid] ->
-- case lookupM m (tid,idKind) of
-- Just _ -> needlib
-- Nothing ->
-- case lookupAT n (tid,idKind) of -- mostly to evaluate n now and then :-)
-- Just _ -> NeedLib r (addM m (tid,idKind)) ms o (updateAT n (tid,idKind) (pos:))
-- Nothing -> NeedLib r (addM m (tid,idKind)) ms o (addAT n undefined (tid,idKind) [pos])
---- tids ->
---- case lookupM m (tids,idKind) of
---- Just _ -> needlib
---- Nothing ->
---- case lookupAT n (tids,idKind) of -- mostly to evaluate n now and then :-)
---- Just _ -> NeedLib r (addM m (tids,idKind)) ms (updateAT n (tids,idKind) (pos:))
---- Nothing -> NeedLib r (addM m (tids,idKind)) ms (addAT n undefined (tids,idKind) [pos])
needTid :: Pos -> IdKind -> TokenId -> NeedLib -> NeedLib
needTid pos idKind tid needlib@(NeedLib r m ms o n) =
case r tid of
[] -> error ("qualified renaming of "++show tid++" produced no results!")
[tid] -> record tid needlib
tids -> foldr record (NeedLib r m ms (addOverlap tid idKind o tids) n) tids
where
record tid needlib@(NeedLib r m ms o n) =
case (tid,idKind) `Set.member` m of
True -> needlib
False ->
case Map.lookup (tid,idKind) n of -- mostly to evaluate n now and then :-)
Just _ -> NeedLib r (Set.insert (tid,idKind) m) ms o
(Map.update (Just . (pos:)) (tid,idKind) n)
Nothing -> NeedLib r (Set.insert (tid,idKind) m) ms o
(Map.insertWith undefined (tid,idKind) [pos] n)
-- push qualification of identifiers from instance head into method decls
needQualify :: TokenId -> Decl TokenId -> Decl TokenId
needQualify (Visible _) decl = decl
needQualify (Qualified mod _) decl = q decl
where
q (DeclFun pos (Visible fun) funs) =
DeclFun pos (Qualified mod fun) funs
q (DeclPat (Alt (ExpVar pos (Visible fun)) rhs decls)) =
DeclPat (Alt (ExpVar pos (Qualified mod fun)) rhs decls)
q decl = decl