fix: fix dynamic let bindings recursion and binder leaks (#1281)

This commit is contained in:
Veit Heller 2021-07-15 22:45:05 +02:00 committed by GitHub
parent f3944ce73d
commit 760726e001
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 16 additions and 3 deletions

View File

@ -2,6 +2,7 @@ module Context
( ContextError (..),
replaceGlobalEnv,
replaceInternalEnv,
replaceInternalEnvMaybe,
replaceTypeEnv,
replaceHistory,
replaceProject,
@ -118,6 +119,13 @@ replaceInternalEnv :: Context -> Env -> Context
replaceInternalEnv ctx env =
ctx {contextInternalEnv = Just env}
-- | Replace a context's internal environment with a new environment or nothing.
--
-- The previous environment is completely replaced and will not be recoverable.
replaceInternalEnvMaybe :: Context -> Maybe Env -> Context
replaceInternalEnvMaybe ctx env =
ctx {contextInternalEnv = env}
-- | Replace a context's global environment with a new environment.
--
-- The previous environment is completely replaced and will not be recoverable.

View File

@ -277,9 +277,9 @@ eval ctx xobj@(XObj o info ty) preference resolver =
Right newCtx -> do
(finalCtx, evaledBody) <- eval newCtx body (PreferLocal (map (\(name, _) -> (SymPath [] name)) binds)) ResolveLocal
let Just e = contextInternalEnv finalCtx
parentEnv = fromMaybe e (envParent e)
parentEnv = envParent e
pure
( replaceInternalEnv finalCtx parentEnv,
( replaceInternalEnvMaybe finalCtx parentEnv,
do
okBody <- evaledBody
Right okBody
@ -298,7 +298,7 @@ eval ctx xobj@(XObj o info ty) preference resolver =
-- (let [f (fn [x] (if (= x 1) x (f (dec x))))] (f 10))
let origin = (contextInternalEnv ctx')
recFix = (E.recursive origin (Just "let-rec-env") 0)
Right envWithSelf = E.insertX recFix (SymPath [] n) x
Right envWithSelf = if isFn x then E.insertX recFix (SymPath [] n) x else Right recFix
ctx'' = replaceInternalEnv ctx' envWithSelf
(newCtx, res) <- eval ctx'' x preference resolver
case res of

View File

@ -232,6 +232,11 @@ isMod :: XObj -> Bool
isMod (XObj (Mod _ _) _ _) = True
isMod _ = False
isFn :: XObj -> Bool
isFn (XObj (Lst (XObj (Fn _ _) _ _ : _)) _ _) = True
isFn (XObj (Lst (XObj (Sym (SymPath [] "fn") _) _ _ : _)) _ _) = True
isFn _ = False
-- | This instance is needed for the dynamic Dictionary
instance Ord Obj where
compare (Str a) (Str b) = compare a b