/Retrie/PatternMap/Bag.hs

https://github.com/facebookincubator/retrie · Haskell · 164 lines · 104 code · 39 blank · 21 comment · 0 complexity · 563f640092df69b12bbfce9f5c5037ba MD5 · raw file

  1. -- Copyright (c) Facebook, Inc. and its affiliates.
  2. --
  3. -- This source code is licensed under the MIT license found in the
  4. -- LICENSE file in the root directory of this source tree.
  5. --
  6. {-# LANGUAGE InstanceSigs #-}
  7. {-# LANGUAGE TupleSections #-}
  8. {-# LANGUAGE TypeFamilies #-}
  9. {-# LANGUAGE DeriveFunctor #-}
  10. module Retrie.PatternMap.Bag where
  11. import qualified Data.Map as M
  12. import qualified Data.IntMap as I
  13. import Retrie.AlphaEnv
  14. import qualified Retrie.GHC as GHC
  15. import Retrie.PatternMap.Class
  16. import Retrie.Quantifiers
  17. import Retrie.Substitution
  18. data BoolMap a
  19. = EmptyBoolMap
  20. | BoolMap
  21. { bmTrue :: MaybeMap a
  22. , bmFalse :: MaybeMap a
  23. }
  24. deriving (Functor)
  25. instance PatternMap BoolMap where
  26. type Key BoolMap = Bool
  27. mEmpty :: BoolMap a
  28. mEmpty = EmptyBoolMap
  29. mUnion :: BoolMap a -> BoolMap a -> BoolMap a
  30. mUnion EmptyBoolMap m = m
  31. mUnion m EmptyBoolMap = m
  32. mUnion m1 m2 = BoolMap
  33. { bmTrue = unionOn bmTrue m1 m2
  34. , bmFalse = unionOn bmFalse m1 m2
  35. }
  36. mAlter
  37. :: AlphaEnv -> Quantifiers -> Key BoolMap -> A a -> BoolMap a -> BoolMap a
  38. mAlter env qs b f EmptyBoolMap = mAlter env qs b f (BoolMap mEmpty mEmpty)
  39. mAlter env qs b f m@BoolMap{}
  40. | b = m { bmTrue = mAlter env qs () f (bmTrue m) }
  41. | otherwise = m { bmFalse = mAlter env qs () f (bmFalse m) }
  42. mMatch
  43. :: MatchEnv
  44. -> Key BoolMap
  45. -> (Substitution, BoolMap a)
  46. -> [(Substitution, a)]
  47. mMatch _ _ (_, EmptyBoolMap) = []
  48. mMatch env b hs@(_, BoolMap{})
  49. | b = mapFor bmTrue hs >>= mMatch env ()
  50. | otherwise = mapFor bmFalse hs >>= mMatch env ()
  51. ------------------------------------------------------------------------
  52. newtype IntMap a = IntMap { unIntMap :: I.IntMap [a] }
  53. deriving (Functor)
  54. instance PatternMap IntMap where
  55. type Key IntMap = I.Key
  56. mEmpty :: IntMap a
  57. mEmpty = IntMap I.empty
  58. mUnion :: IntMap a -> IntMap a -> IntMap a
  59. mUnion (IntMap m1) (IntMap m2) = IntMap $ I.unionWith (++) m1 m2
  60. mAlter :: AlphaEnv -> Quantifiers -> Key IntMap -> A a -> IntMap a -> IntMap a
  61. mAlter _ _ i f (IntMap m) = IntMap $ I.alter (toAList f) i m
  62. mMatch
  63. :: MatchEnv
  64. -> Key IntMap
  65. -> (Substitution, IntMap a)
  66. -> [(Substitution, a)]
  67. mMatch _ i = maybeListMap (I.lookup i . unIntMap)
  68. ------------------------------------------------------------------------
  69. newtype Map k a = Map { unMap :: M.Map k [a] }
  70. deriving (Functor)
  71. mapAssocs :: Map k v -> [(k,v)]
  72. mapAssocs (Map m) = [ (k,v) | (k,vs) <- M.assocs m, v <- vs ]
  73. instance Ord k => PatternMap (Map k) where
  74. type Key (Map k) = k
  75. mEmpty :: Map k a
  76. mEmpty = Map M.empty
  77. mUnion :: Map k a -> Map k a -> Map k a
  78. mUnion (Map m1) (Map m2) = Map $ M.unionWith (++) m1 m2
  79. mAlter :: AlphaEnv -> Quantifiers -> Key (Map k) -> A a -> Map k a -> Map k a
  80. mAlter _ _ k f (Map m) = Map $ M.alter (toAList f) k m
  81. mMatch
  82. :: MatchEnv
  83. -> Key (Map k)
  84. -> (Substitution, Map k a)
  85. -> [(Substitution, a)]
  86. mMatch _ k = maybeListMap (M.lookup k . unMap)
  87. ------------------------------------------------------------------------
  88. -- Note [OccEnv]
  89. --
  90. -- We avoid using OccEnv because the Uniquable instance for OccName
  91. -- takes the NameSpace of the OccName into account, which we rarely actually
  92. -- want. (Doing so requires creating new RdrNames with the proper namespace,
  93. -- which is a bunch of fiddling for no obvious gain for our uses.) Instead
  94. -- we just use a map based on the FastString name.
  95. newtype FSEnv a =
  96. FSEnv { _unFSEnv :: UniqFM a } -- this is the UniqFM below, NOT GHC's UniqFM
  97. deriving (Functor)
  98. instance PatternMap FSEnv where
  99. type Key FSEnv = GHC.FastString
  100. mEmpty :: FSEnv a
  101. mEmpty = FSEnv mEmpty
  102. mUnion :: FSEnv a -> FSEnv a -> FSEnv a
  103. mUnion (FSEnv m1) (FSEnv m2) = FSEnv (mUnion m1 m2)
  104. mAlter :: AlphaEnv -> Quantifiers -> Key FSEnv -> A a -> FSEnv a -> FSEnv a
  105. mAlter env qs fs f (FSEnv m) = FSEnv (mAlter env qs (GHC.getUnique fs) f m)
  106. mMatch :: MatchEnv -> Key FSEnv -> (Substitution, FSEnv a) -> [(Substitution, a)]
  107. mMatch env fs (hs, FSEnv m) = mMatch env (GHC.getUnique fs) (hs, m)
  108. ------------------------------------------------------------------------
  109. newtype UniqFM a = UniqFM { unUniqFM :: GHC.UniqFM [a] }
  110. deriving (Functor)
  111. instance PatternMap UniqFM where
  112. type Key UniqFM = GHC.Unique
  113. mEmpty :: UniqFM a
  114. mEmpty = UniqFM GHC.emptyUFM
  115. mUnion :: UniqFM a -> UniqFM a -> UniqFM a
  116. mUnion (UniqFM m1) (UniqFM m2) = UniqFM $ GHC.plusUFM_C (++) m1 m2
  117. mAlter :: AlphaEnv -> Quantifiers -> Key UniqFM -> A a -> UniqFM a -> UniqFM a
  118. mAlter _ _ k f (UniqFM m) = UniqFM $ GHC.alterUFM (toAList f) m k
  119. mMatch
  120. :: MatchEnv
  121. -> Key UniqFM
  122. -> (Substitution, UniqFM a)
  123. -> [(Substitution, a)]
  124. mMatch _ k = maybeListMap (flip GHC.lookupUFM_Directly k . unUniqFM)
  125. ------------------------------------------------------------------------