on master help sign in
Fix memory leak

It turns out that having H.catch around too large a block means that state is retained. In particular, having the catch around a recursive application of the REPL means that all previous states get retained! So, be careful to scope catch blocks around the smallest possible block.

commita611deb1ae8ce7c65fad1cd9c7198b63761251ef authorEdwin Brady <ecb10@st-andrews.ac.uk> dateThu 16 Jan 2014, 18:49 (13 years ago) parentfac49fc
7 files changed+52−40
src/Idris/AbsSyntax.hs+12−7 src/Idris/AbsSyntaxTree.hs+1−1 src/Idris/Core/Elaborate.hs+6 src/Idris/Core/ProofState.hs+1−1 src/Idris/ElabTerm.hs−1 src/Idris/IBC.hs+1−1 src/Idris/REPL.hs+31−29
src/Idris/AbsSyntax.hs+12−7
@@ -238,14 +238,19 @@ resetNameIdx :: Idris ()
238238resetNameIdx = do i <- getIState
239239 put (i { idris_nameIdx = (0, emptyContext) })
240240
241−addNameIdx :: Name -> Idris Int
241+-- Used to preserve sharing of names
242+addNameIdx :: Name -> Idris (Int, Name)
242243addNameIdx n = do i <- getIState
243− let idxs = snd (idris_nameIdx i)
244− case lookupCtxt n idxs of
245− [x] -> return x
246− _ -> do let i' = fst (idris_nameIdx i) + 1
247− put (i { idris_nameIdx = (i', addDef n i' idxs) })
248− return i'
244+ let (i', x) = addNameIdx' i n
245+ return x
246+
247+addNameIdx' :: IState -> Name -> (IState, (Int, Name))
248+addNameIdx' i n
249+ = let idxs = snd (idris_nameIdx i) in
250+ case lookupCtxt n idxs of
251+ [x] -> (i, x)
252+ _ -> let i' = fst (idris_nameIdx i) + 1 in
253+ (i { idris_nameIdx = (i', addDef n (i', n) idxs) }, (i', n))
249254
250255getHdrs :: Codegen -> Idris [String]
251256getHdrs tgt = do i <- getIState; return (forCodegen tgt $ idris_hdrs i)
src/Idris/AbsSyntaxTree.hs+1−1
@@ -133,7 +133,7 @@ data IState = IState {
133133 idris_colourTheme :: ColourTheme,
134134 idris_outh :: Handle,
135135 idris_errorhandlers :: [Name],
136− idris_nameIdx :: (Int, Ctxt Int)
136+ idris_nameIdx :: (Int, Ctxt (Int, Name))
137137 }
138138
139139data SizeChange = Smaller | Same | Bigger | Unknown
src/Idris/Core/Elaborate.hs+6
@@ -16,7 +16,9 @@ import Idris.Core.TT
1616import Idris.Core.Evaluate
1717import Idris.Core.Typecheck
1818import Idris.Core.Unify
19+import Idris.Core.DeepSeq
1920
21+import Control.DeepSeq
2022import Control.Monad.State
2123import Data.Char
2224import Data.List
@@ -125,6 +127,10 @@ elaborate ctxt n ty d elab = do let ps = initElaborator n ctxt ty
125127 (a, ES ps' str _) <- runElab d elab ps
126128 return (a, str)
127129
130+force_term :: Elab' aux ()
131+force_term = do ES (ps, a) l p <- get
132+ put (ES (ps { pterm = force (pterm ps) }, a) l p)
133+
128134updateAux :: (aux -> aux) -> Elab' aux ()
129135updateAux f = do ES (ps, a) l p <- get
130136 put (ES (ps, f a) l p)
src/Idris/Core/ProofState.hs+1−1
@@ -740,7 +740,7 @@ keepGiven du (u@(n, _) : us) hs
740740keepGiven du (u : us) hs = keepGiven du us hs
741741
742742updateSolved xs x = -- trace ("Updating " ++ show xs ++ " in " ++ show x) $
743− updateSolved' xs x
743+ updateSolved' xs x
744744updateSolved' [] x = x
745745updateSolved' xs (Bind n (Hole ty) t)
746746 | Just v <- lookup n xs = case xs of
src/Idris/ElabTerm.hs−1
@@ -110,7 +110,6 @@ elab ist info pattern opts fn tm
110110 end_unify
111111 when pattern -- convert remaining holes to pattern vars
112112 (do update_term orderPats
113− tm <- get_term
114113 mkPat)
115114 where
116115 tcgen = Dictionary `elem` opts
src/Idris/IBC.hs+1−1
@@ -177,7 +177,7 @@ ibc i (IBCDef n) f = case lookupDef n (tt_ctxt i) of
177177 update (P t n@(MN _ _) ty) = return (P t n ty)
178178 update (P t n@(UN _) ty) = return (P t n ty)
179179 update (P t n ty) = do (f, len) <- ST.get
180− i <- lift (addNameIdx n)
180+ (i, _) <- lift (addNameIdx n)
181181 when (i >= len) $
182182 ST.put (f { symbols = symbols f ++ [n] }, len+1)
183183 return (P t (SymRef i) ty)
src/Idris/REPL.hs+31−29
@@ -80,31 +80,33 @@ repl :: IState -- ^ The initial state
8080 -> [FilePath] -- ^ The loaded modules
8181 -> InputT Idris ()
8282repl orig mods
83− = H.catch
84− (do let quiet = opt_quiet (idris_options orig)
85− i <- lift getIState
86− let colour = idris_colourRepl i
87− let theme = idris_colourTheme i
88− let mvs = idris_metavars i
89− let prompt = if quiet
90− then ""
91− else showMVs colour theme mvs ++
92− let str = mkPrompt mods ++ ">" in
93− (if colour then colourisePrompt theme str else str) ++ " "
94− x <- getInputLine prompt
95− case x of
96− Nothing -> do lift $ when (not quiet) (iputStrLn "Bye bye")
97− return ()
98− Just input -> H.catch
99− (do ms <- lift $ processInput input orig mods
100− case ms of
101− Just mods -> repl orig mods
102− Nothing -> return ())
103− ctrlC)
104− ctrlC
105− where ctrlC :: SomeException -> InputT Idris ()
106− ctrlC e = do lift $ iputStrLn (show e)
107− repl orig mods
83+ = -- H.catch
84+ do let quiet = opt_quiet (idris_options orig)
85+ i <- lift getIState
86+ let colour = idris_colourRepl i
87+ let theme = idris_colourTheme i
88+ let mvs = idris_metavars i
89+ let prompt = if quiet
90+ then ""
91+ else showMVs colour theme mvs ++
92+ let str = mkPrompt mods ++ ">" in
93+ (if colour then colourisePrompt theme str else str) ++ " "
94+ x <- H.catch (getInputLine prompt)
95+ (ctrlC (return Nothing))
96+ case x of
97+ Nothing -> do lift $ when (not quiet) (iputStrLn "Bye bye")
98+ return ()
99+ Just input -> -- H.catch
100+ do ms <- H.catch (lift $ processInput input orig mods)
101+ (ctrlC (return (Just mods)))
102+ case ms of
103+ Just mods -> repl orig mods
104+ Nothing -> return ()
105+-- ctrlC)
106+-- ctrlC
107+ where ctrlC :: InputT Idris a -> SomeException -> InputT Idris a
108+ ctrlC act e = do lift $ iputStrLn (show e)
109+ act -- repl orig mods
108110
109111 showMVs c thm [] = ""
110112 showMVs c thm ms = "Metavariables: " ++
@@ -1193,8 +1195,8 @@ idrisMain opts =
11931195 when (not (NoPrelude `elem` opts)) $ do x <- loadModule stdout "Prelude"
11941196 return ()
11951197 when (runrepl && not quiet && not idesl && not (isJust script) && not nobanner) $ iputStrLn banner
1196− ist <- getIState
11971198
1199+ orig <- getIState
11981200 loadInputs stdout inputs
11991201
12001202 runIO $ hSetBuffering stdout LineBuffering
@@ -1219,9 +1221,9 @@ idrisMain opts =
12191221
12201222 when (runrepl && not idesl) $ do
12211223 initScript
1222− startServer ist inputs
1223− runInputT (replSettings (Just historyFile)) $ repl ist inputs
1224− when (idesl) $ ideslaveStart ist inputs
1224+ startServer orig inputs
1225+ runInputT (replSettings (Just historyFile)) $ repl orig inputs
1226+ when (idesl) $ ideslaveStart orig inputs
12251227 ok <- noErrors
12261228 when (not ok) $ runIO (exitWith (ExitFailure 1))
12271229 where