git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
Ensure no duplicates appear in the PSCiState

- Use a Set for imported filenames, to ensure there are no duplicates - Use a Map for loaded modules, keyed by module name, to ensure that there are no duplicates - Provide new accessors using the old types Maybe if a duplicate module is loaded, silently forgetting the old module isn't the right approach, though. Especially if the filenames were different.

commite66c773c5b71bc49d4835474c1ab4ea5eb882a74 authorHarry Garrood <harry@garrood.me> dateWed 16 Dec 2015, 15:07 (11 years ago) parent0c87efe
2 files changed+60−19
psci/PSCi.hs+11−10 psci/Types.hs+49−9
psci/PSCi.hs+11−10
@@ -129,7 +129,7 @@ loadAllImportedModules = do
129129 modulesOrFirstError <- psciIO $ loadAllModules files
130130 case modulesOrFirstError of
131131 Left errs -> printErrors errs
132− Right modules -> PSCI . lift . modify $ \st -> st { psciLoadedModules = modules }
132+ Right modules -> PSCI . lift . modify $ updateModules modules
133133
134134-- |
135135-- Expands tilde in path.
@@ -249,11 +249,12 @@ makeIO f io = do
249249 either (throwError . P.singleError . f) return e
250250
251251make :: PSCiState -> [(Either P.RebuildPolicy FilePath, P.Module)] -> P.Make P.Environment
252−make PSCiState{..} ms = P.make actions' (map snd (psciLoadedModules ++ ms))
252+make st@PSCiState{..} ms = P.make actions' (map snd (loadedModules ++ ms))
253253 where
254− filePathMap = M.fromList $ (first P.getModuleName . swap) `map` (psciLoadedModules ++ ms)
254+ filePathMap = M.fromList $ (first P.getModuleName . swap) `map` (loadedModules ++ ms)
255255 actions = P.buildMakeActions modulesDir filePathMap psciForeignFiles False
256256 actions' = actions { P.progress = const (return ()) }
257+ loadedModules = psciLoadedModules st
257258
258259-- |
259260-- Takes a value declaration and evaluates it with the current state.
@@ -294,7 +295,7 @@ handleDecls ds = do
294295--
295296handleShowLoadedModules :: PSCI ()
296297handleShowLoadedModules = do
297− PSCiState { psciLoadedModules = loadedModules } <- PSCI $ lift get
298+ loadedModules <- PSCI $ lift $ gets psciLoadedModules
298299 psciIO $ readModules loadedModules >>= putStrLn
299300 return ()
300301 where readModules = return . unlines . sort . nub . map toModuleName
@@ -547,11 +548,11 @@ handleCommand (LoadForeign filePath) = whenFileExists filePath $ \absPath -> do
547548 Right foreigns -> PSCI . lift $ modify (updateForeignFiles foreigns)
548549handleCommand ResetState = do
549550 files <- psciImportedFilenames <$> PSCI (lift get)
550− PSCI . lift . modify $ \st -> st
551− { psciImportedFilenames = files
552− , psciImportedModules = []
553− , psciLetBindings = []
554− }
551+ PSCI . lift . modify $ \st ->
552+ (foldl (flip updateImportedFiles) st files)
553+ { psciImportedModules = []
554+ , psciLetBindings = []
555+ }
555556 loadAllImportedModules
556557handleCommand (TypeOf val) = handleTypeOf val
557558handleCommand (KindOf typ) = handleKindOf typ
@@ -614,7 +615,7 @@ loop PSCiOptions{..} = do
614615 case foreignsOrError of
615616 Left errs -> putStrLn (P.prettyPrintMultipleErrors False errs) >> exitFailure
616617 Right foreigns ->
617− flip evalStateT (PSCiState inputFiles [] modules foreigns [] psciInputNodeFlags) . runInputT (setComplete completion settings) $ do
618+ flip evalStateT (mkPSCiState inputFiles [] modules foreigns [] psciInputNodeFlags) . runInputT (setComplete completion settings) $ do
618619 outputStrLn prologueMessage
619620 traverse_ (traverse_ (runPSCI . handleCommand)) config
620621 modules' <- lift $ gets psciLoadedModules
psci/Types.hs+49−9
@@ -15,7 +15,10 @@
1515
1616module Types where
1717
18−import qualified Data.Map as M
18+import Data.Set (Set)
19+import qualified Data.Set as Set
20+import Data.Map (Map)
21+import qualified Data.Map as Map
1922import qualified Language.PureScript as P
2023
2124data PSCiOptions = PSCiOptions
@@ -32,14 +35,48 @@ data PSCiOptions = PSCiOptions
3235-- because it makes more sense to apply the binding to the final evaluated expression.
3336--
3437data PSCiState = PSCiState
35− { psciImportedFilenames :: [FilePath]
38+ { _psciImportedFilenames :: Set FilePath
3639 , psciImportedModules :: [ImportedModule]
37− , psciLoadedModules :: [(Either P.RebuildPolicy FilePath, P.Module)]
38− , psciForeignFiles :: M.Map P.ModuleName FilePath
40+ , _psciLoadedModules :: Map P.ModuleName (Either P.RebuildPolicy FilePath, P.Module)
41+ , psciForeignFiles :: Map P.ModuleName FilePath
3942 , psciLetBindings :: [P.Declaration]
4043 , psciNodeFlags :: [String]
4144 }
4245
46+-- Public psci state accessors
47+
48+-- | Get the imported filenames as a list.
49+psciImportedFilenames :: PSCiState -> [FilePath]
50+psciImportedFilenames = Set.toList . _psciImportedFilenames
51+
52+-- | Get the loaded modules as a list.
53+psciLoadedModules :: PSCiState -> [(Either P.RebuildPolicy FilePath, P.Module)]
54+psciLoadedModules = Map.elems . _psciLoadedModules
55+
56+mkPSCiState :: [FilePath]
57+ -> [ImportedModule]
58+ -> [(Either P.RebuildPolicy FilePath, P.Module)]
59+ -> Map P.ModuleName FilePath
60+ -> [P.Declaration]
61+ -> [String]
62+ -> PSCiState
63+mkPSCiState files imported loaded foreign lets nodeFlags =
64+ (initialPSCiState
65+ |> each files updateImportedFiles
66+ |> each imported updateImportedModules
67+ |> updateModules loaded)
68+ { psciForeignFiles = foreign
69+ , psciLetBindings = lets
70+ , psciNodeFlags = nodeFlags
71+ }
72+ where
73+ x |> f = f x
74+ each xs f st = foldl (flip f) st xs
75+
76+initialPSCiState :: PSCiState
77+initialPSCiState =
78+ PSCiState Set.empty [] Map.empty Map.empty [] []
79+
4380-- | All of the data that is contained by an ImportDeclaration in the AST.
4481-- That is:
4582--
@@ -65,10 +102,10 @@ allImportsOf m (PSCiState{psciImportedModules = is}) =
65102-- State helpers
66103
67104-- |
68−-- Updates the state to have more imported modules.
105+-- Updates the state to have more imported files.
69106--
70107updateImportedFiles :: FilePath -> PSCiState -> PSCiState
71−updateImportedFiles filename st = st { psciImportedFilenames = filename : psciImportedFilenames st }
108+updateImportedFiles filename st = st { _psciImportedFilenames = Set.insert filename (_psciImportedFilenames st) }
72109
73110-- |
74111-- Updates the state to have more imported modules.
@@ -80,7 +117,10 @@ updateImportedModules im st = st { psciImportedModules = im : psciImportedModule
80117-- Updates the state to have more loaded files.
81118--
82119updateModules :: [(Either P.RebuildPolicy FilePath, P.Module)] -> PSCiState -> PSCiState
83−updateModules modules st = st { psciLoadedModules = psciLoadedModules st ++ modules }
120+updateModules modules st =
121+ st { _psciLoadedModules = foldl (\m mdl -> Map.insert (keyFor mdl) mdl m) (_psciLoadedModules st) modules }
122+ where
123+ keyFor = P.getModuleName . snd
84124
85125-- |
86126-- Updates the state to have more let bindings.
@@ -91,8 +131,8 @@ updateLets ds st = st { psciLetBindings = psciLetBindings st ++ ds }
91131-- |
92132-- Updates the state to have more let bindings.
93133--
94−updateForeignFiles :: M.Map P.ModuleName FilePath -> PSCiState -> PSCiState
95−updateForeignFiles fs st = st { psciForeignFiles = psciForeignFiles st `M.union` fs }
134+updateForeignFiles :: Map P.ModuleName FilePath -> PSCiState -> PSCiState
135+updateForeignFiles fs st = st { psciForeignFiles = psciForeignFiles st `Map.union` fs }
96136
97137-- |
98138-- Valid Meta-commands for PSCI