@@ -38,7 +38,6 @@ module Language.PureScript.Make.ExternsDiff
3838import Protolude hiding (check , moduleName , trace )
3939
4040import Data.Graph as G (graphFromEdges , reachable )
41- import Data.List qualified as L
4241import Data.Map qualified as M
4342import Data.Set qualified as S
4443
@@ -94,13 +93,13 @@ isRefRemoved _ = False
9493-- present in new extern's exports) or changed in dependencies.
9594getReExported :: P. ExternsFile -> P. ExternsFile -> ModuleRefsMap -> RefsWithStatus
9695getReExported newExts oldExts depsDiffsMap =
97- M. fromList $ mapMaybe checkRe oldExports
96+ M. fromList $ mapMaybe checkRe $ S. toList oldExports
9897 where
99- goRe (P. ReExportRef _ es ref) = (P. exportSourceDefinedIn es,) <$> toRefs ref
100- goRe _ = []
98+ goRe (P. ReExportRef _ es ref) = S. mapMonotonic (P. exportSourceDefinedIn es,) ( toRefs ref)
99+ goRe _ = S. empty
101100
102- oldExports = concatMap goRe (P. efExports oldExts)
103- newReExports = concatMap goRe (P. efExports newExts)
101+ oldExports = foldMap goRe (P. efExports oldExts)
102+ newReExports = foldMap goRe (P. efExports newExts)
104103 checkRe (mn, ref)
105104 | (mn, ref) `notElem` newReExports = Just (ref, Removed )
106105 | Just True <- elem ref <$> M. lookup mn depsDiffsMap = Just (ref, Updated )
@@ -109,7 +108,7 @@ getReExported newExts oldExts depsDiffsMap =
109108-- Extracts declarations from old and new externs and compares them. Returns a
110109-- tuple of changed refs (a form of which have changed) and unchanged refs with
111110-- dependencies (refs they depend upon).
112- getChanged :: P. ExternsFile -> P. ExternsFile -> ModuleRefsMap -> (RefsWithStatus , [ RefWithDeps ] )
111+ getChanged :: P. ExternsFile -> P. ExternsFile -> ModuleRefsMap -> (RefsWithStatus , Set RefWithDeps )
113112getChanged newExts oldExts depsDiffsMap =
114113 (changedRefs, unchangedRefs)
115114 where
@@ -125,30 +124,31 @@ getChanged newExts oldExts depsDiffsMap =
125124 -- class or (if the type class defined in another module) we have to
126125 -- recompile modules that use types defined in this module affected by the
127126 -- instance.
127+ applyInstances :: Tuple4 Set RefWithDeps -> Tuple4 Set RefWithDeps
128128 applyInstances (a, r, c, u) =
129129 let checkType t (TypeRef t') = t' == t
130130 checkType _ _ = False
131- uRefs = map fst u -- Unchanged refs.
131+ uRefs = mapFst u -- Unchanged refs.
132132 go (TypeInstanceRef _ (clsMod, cls) types)
133133 | clsRef <- TypeClassRef cls =
134134 if clsMod == modName
135135 then -- If the class is defined in this module we ensure that is marked as changed.
136- maybe [] pure $ find ( (==) clsRef) uRefs
136+ if S. member clsRef uRefs then S. singleton clsRef else S. empty
137137 else case S. member clsRef <$> M. lookup clsMod depsDiffsMap of
138138 Just True ->
139139 -- If the type class is in another module and it has
140140 -- changed we don't need to care about instance types
141141 -- (because the instance change affects modules that use
142142 -- the type class/its methods).
143- []
143+ S. empty
144144 _ ->
145145 -- Otherwise mark instance types as changed.
146- foldMap (\ t -> filter (checkType t) uRefs) types
147- go _ = mempty
146+ foldMap (\ t -> S. filter (checkType t) uRefs) types
147+ go _ = S. empty
148148
149149 -- Check class instances in added, removed and changed.
150- affected = foldMap (S. fromList . go . fst ) (a <> r <> c)
151- (uc, uu) = L . partition (flip S. member affected . fst ) u
150+ affected = foldMap (go . fst ) (a <> r <> c)
151+ (uc, uu) = S . partition (flip S. member affected . fst ) u
152152 in (a, r, c <> uc, uu)
153153
154154 -- Group/split exported refs of the module into (added, removed, changed,
@@ -159,7 +159,7 @@ getChanged newExts oldExts depsDiffsMap =
159159
160160 -- Make the context for fixity's data constructor search: place all
161161 -- known refs in the map.
162- getRefsSet (a, r, c, u) = S. fromList $ map fst (a <> r <> c <> u)
162+ getRefsSet (a, r, c, u) = mapFst (a <> r <> c <> u)
163163 fixityCtx = M. insert modName (getRefsSet declsSplit) depsDiffsMap
164164
165165 -- Determine which declarations where directly changed or removed by
@@ -172,10 +172,9 @@ getChanged newExts oldExts depsDiffsMap =
172172 , splitRefs (getTypeFixities newExts) (getTypeFixities oldExts) (pure . externsTypeFixityToRef)
173173 ]
174174
175- withStatus status refs = map ((, status) . fst ) refs
175+ withStatus status refs = M. fromSet ( const status) $ mapFst refs
176176 changedRefs =
177- M. fromList $
178- withStatus Added added <> withStatus Removed removed <> withStatus Updated changed
177+ withStatus Added added <> withStatus Removed removed <> withStatus Updated changed
179178
180179-- Gets set of type constructors from new externs that have changed.
181180getCtorsSets :: P. ExternsFile -> P. ExternsFile -> Set Ref
@@ -194,25 +193,26 @@ getCtorsSets newExts oldExts =
194193-- Takes a list unchanged local refs with dependencies and finds that are affected by
195194-- changed refs. Cyclic dependencies between local refs are searched using
196195-- directed graph.
197- getAffectedLocal :: ModuleName -> ModuleRefsMap -> [ RefWithDeps ] -> Set Ref
196+ getAffectedLocal :: ModuleName -> ModuleRefsMap -> Set RefWithDeps -> Set Ref
198197getAffectedLocal modName diffsMap unchangedRefs =
199198 affectedLocalRefs
200199 where
201200 hasChangedDeps (mn, ref) =
202201 Just True == (S. member ref <$> M. lookup mn diffsMap)
203202 (affectedByChanged, restLocalRefs) =
204- L . partition (any hasChangedDeps . snd ) unchangedRefs
203+ S . partition (any hasChangedDeps . snd ) unchangedRefs
205204
206205 -- Use graph to go though local refs and their cyclic dependencies on each other.
207206 -- The graph includes only local refs that depend on other local refs.
208207 toNode (ref, deps) = (ref, ref, map snd $ filter ((== modName) . fst ) (S. toList deps))
209208
210209 -- Make graph vertexes from the rest local refs with deps and affected refs
211210 -- with no deps.
212- vtxs = toNode <$> restLocalRefs <> (map (const mempty ) <$> affectedByChanged)
211+ vtxs = toNode <$> S. toList restLocalRefs <> (map (const S. empty ) <$> S. toList affectedByChanged)
213212 (graph, fromVtx, toVtx) = G. graphFromEdges vtxs
214213
215214 -- Graph is a list of refs with (refs) dependencies.
215+ refsGraph :: [(Ref , [Ref ])]
216216 refsGraph = do
217217 (_, t, _) <- vtxs
218218 let v = fromMaybe (internalError " diffExterns: vertex not found" ) $ toVtx t
@@ -226,7 +226,7 @@ getAffectedLocal modName diffsMap unchangedRefs =
226226 affectedLocalRefs =
227227 S. fromList $
228228 map fst $
229- filter (any (flip elem ( fst <$> affectedByChanged)) . snd ) refsGraph
229+ filter (any (flip S. member (mapFst affectedByChanged)) . snd ) refsGraph
230230
231231-- Compares two externs file versions using list with diffs of dependencies.
232232diffExterns :: [ExternsDiff ] -> P. ExternsFile -> P. ExternsFile -> ExternsDiff
@@ -358,42 +358,45 @@ makeSearches decls depsDiffs =
358358 -- Add data constructors to refs if all are implicitly imported using (..).
359359 getCtor n (ConstructorRef tn _) = tn == n
360360 getCtor _ _ = False
361- getCtors n = M. keys . M. filterWithKey (const . getCtor n)
362- addCtors mn (P. TypeRef _ n Nothing ) = maybe [] (getCtors n) (M. lookup mn diffsMap)
363- addCtors _ _ = []
361+ getCtors n = M. keysSet . M. filterWithKey (const . getCtor n)
362+ addCtors mn (P. TypeRef _ n Nothing ) = foldMap (getCtors n) (M. lookup mn diffsMap)
363+ addCtors _ _ = S. empty
364364 getRefs = (toRefs <> ) . addCtors
365365
366366 go s (P. ImportDeclaration _ mn dt qual)
367367 -- We return Nothing if we encounter removed refs in imports.
368368 | Just diffs <- M. lookup mn diffsMap
369369 , removed <- M. keysSet $ M. filter isRefRemoved diffs =
370- fmap ((s <> ) . S. map (mn, qual,) . M. keysSet) $ case dt of
370+ let
371+ addIn updated = s <>
372+ S. mapMonotonic (mn, qual,) (M. keysSet updated)
373+ in case dt of
371374 P. Explicit dRefs
372375 | Just ref <- searchRef removed refs -> Left (mn, ref)
373376 | otherwise ->
374377 -- Search only refs encountered in the import.
375- Right $ M. filterWithKey (const . flip elem refs) diffs
378+ Right $ addIn $ M. filterWithKey (const . flip elem refs) diffs
376379 where
377380 refs = foldMap (getRefs mn) dRefs
378381 P. Hiding dRefs
379382 | Just ref <- searchRef removed refs -> Left (mn, ref)
380383 | otherwise ->
381384 -- Search only refs not encountered in the import.
382- Right $ M. filterWithKey (const . not . flip elem refs) diffs
385+ Right $ addIn $ M. filterWithKey (const . not . flip elem refs) diffs
383386 where
384387 refs = foldMap (getRefs mn) dRefs
385388 -- Search all changed refs.
386- P. Implicit -> Right diffs
389+ P. Implicit -> Right $ addIn diffs
387390 go s _ = Right s
388391
389- toRefs :: P. DeclarationRef -> [ Ref ]
392+ toRefs :: P. DeclarationRef -> Set Ref
390393toRefs = \ case
391- P. TypeClassRef _ n -> [ TypeClassRef n]
392- P. TypeOpRef _ n -> [ TypeOpRef n]
393- P. TypeRef _ n c -> [ TypeRef n] <> ( ConstructorRef n <$> fromMaybe [] c)
394- P. ValueRef _ i -> [ ValueRef i]
395- P. ValueOpRef _ n -> [ ValueOpRef n]
396- _ -> []
394+ P. TypeClassRef _ n -> S. singleton ( TypeClassRef n)
395+ P. TypeOpRef _ n -> S. singleton ( TypeOpRef n)
396+ P. TypeRef _ n c -> S. singleton ( TypeRef n) <> foldMap ( S. fromList . fmap ( ConstructorRef n)) c
397+ P. ValueRef _ i -> S. singleton ( ValueRef i)
398+ P. ValueOpRef _ n -> S. singleton ( ValueOpRef n)
399+ _ -> S. empty
397400
398401isEmpty :: ExternsDiff -> Bool
399402isEmpty (ExternsDiff _ refs)
@@ -403,19 +406,19 @@ isEmpty (ExternsDiff _ refs)
403406type Tuple4 m a = (m a , m a , m a , m a )
404407
405408-- | Returns refs as a tuple of four (added, removed, changed, unchanged).
406- splitRefs :: Ord r => Eq a => [a ] -> [a ] -> (a -> Maybe r ) -> Tuple4 [] r
409+ splitRefs :: Ord r => Eq a => [a ] -> [a ] -> (a -> Maybe r ) -> Tuple4 Set r
407410splitRefs new old toRef =
408- M. foldrWithKey go (added, [] , [] , [] ) oldMap
411+ M. foldrWithKey go (added, S. empty, S. empty, S. empty ) oldMap
409412 where
410413 toMap = M. fromList . mapMaybe (((<$>) . flip (,)) <*> toRef)
411414 newMap = toMap new
412415 oldMap = toMap old
413- added = M. keys $ M. difference newMap oldMap
416+ added = M. keysSet $ M. difference newMap oldMap
414417 go ref decl (a, r, c, u) = case M. lookup ref newMap of
415- Nothing -> (a, r <> [ ref] , c, u)
418+ Nothing -> (a, S. insert ref r , c, u)
416419 Just newDecl
417- | decl /= newDecl -> (a, r, ref : c, u)
418- | otherwise -> (a, r, c, ref : u)
420+ | decl /= newDecl -> (a, r, S. insert ref c, u)
421+ | otherwise -> (a, r, c, S. insert ref u)
419422
420423-- | Traverses the type and finds all the refs within.
421424typeDeps :: P. Type a -> S. Set (ModuleName , Ref )
@@ -574,3 +577,7 @@ refineDeclaration = \case
574577
575578isPrimModule :: ModuleName -> Bool
576579isPrimModule = flip S. member (S. fromList primModules)
580+
581+ -- @fst@ is monotonic, so it is safe to use @S.mapMonotonic@
582+ mapFst :: forall a b . Set (a , b ) -> Set a
583+ mapFst = S. mapMonotonic fst
0 commit comments