1
1
mirror of https://github.com/kanaka/mal.git synced 2024-11-13 01:43:50 +03:00

Elm step A: GC working

This commit is contained in:
Jos van Bakel 2017-07-22 21:44:25 +02:00
parent 4c696bfb54
commit 50ed0aa9a1
4 changed files with 34 additions and 40 deletions

View File

@ -11,7 +11,6 @@ module Env
, push
, pop
, enter
, jump
, leave
, ref
, pushRef
@ -54,6 +53,7 @@ global =
, gcInterval = defaultGcInterval
, gcCounter = 0
, stack = []
, keepFrames = []
}
@ -220,29 +220,6 @@ enter outerId binds env =
}
{-| Jump into a frame
-}
jump : Int -> Env -> Env
jump frameId env =
let
setExitId =
Maybe.map
(\frame ->
{ frame
| exitId = Just env.currentFrameId
, refCnt = frame.refCnt + 1
}
)
bogus =
debug env "jump #" frameId
in
{ env
| currentFrameId = frameId
, frames = Dict.update frameId setExitId env.frames
}
leave : Env -> Env
leave env =
let
@ -332,8 +309,6 @@ Return a new Env with the unreachable frames removed.
gc : MalExpr -> Env -> Env
gc expr env =
let
-- bogus =
-- Debug.log "GC stack = " env.stack
countList acc =
List.foldl countExpr acc
@ -387,7 +362,10 @@ gc expr env =
acc
initSet =
Set.fromList [ globalFrameId, env.currentFrameId ]
Set.fromList
([ globalFrameId, env.currentFrameId ]
++ env.keepFrames
)
countFrames frames acc =
Set.toList frames
@ -437,16 +415,10 @@ gc expr env =
filterFrames frames keep =
Dict.filter (keepFilter keep) frames
reportUnused frames keep =
Set.diff (Set.fromList (Dict.keys frames)) keep
|> Debug.log "\n\nUNUSED FRAMES\n\n"
|> always keep
in
countFrames initSet initSet
|> countExpr expr
|> (flip countList) env.stack
|> loop
-- |> reportUnused env.frames
|> filterFrames env.frames
|> makeNewEnv

View File

@ -3,7 +3,6 @@ module Eval exposing (..)
import Types exposing (..)
import IO exposing (IO)
import Env
import Printer exposing (printEnv)
apply : Eval a -> Env -> EvalContext a
@ -197,3 +196,30 @@ pushRef : MalExpr -> Eval a -> Eval a
pushRef ref e =
modifyEnv (Env.pushRef ref)
|> andThen (always e)
inGlobal : Eval a -> Eval a
inGlobal body =
let
enter env =
setEnv
{ env
| keepFrames = env.currentFrameId :: env.keepFrames
, currentFrameId = Env.globalFrameId
}
leave oldEnv newEnv =
{ newEnv
| keepFrames = oldEnv.keepFrames
, currentFrameId = oldEnv.currentFrameId
}
in
withEnv
(\env ->
if env.currentFrameId /= Env.globalFrameId then
enter env
|> andThen (always body)
|> finally (leave env)
else
body
)

View File

@ -32,6 +32,7 @@ type alias Env =
, gcInterval : Int
, gcCounter : Int
, stack : List MalExpr
, keepFrames : List Int
}

View File

@ -273,12 +273,7 @@ malEval : List MalExpr -> Eval MalExpr
malEval args =
case args of
[ expr ] ->
Eval.withEnv
(\env ->
Eval.modifyEnv (Env.jump Env.globalFrameId)
|> Eval.andThen (\_ -> eval expr)
|> Eval.finally Env.leave
)
Eval.inGlobal (eval expr)
_ ->
Eval.fail "unsupported arguments"