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:
parent
4c696bfb54
commit
50ed0aa9a1
38
elm/Env.elm
38
elm/Env.elm
@ -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
|
||||
|
28
elm/Eval.elm
28
elm/Eval.elm
@ -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
|
||||
)
|
||||
|
@ -32,6 +32,7 @@ type alias Env =
|
||||
, gcInterval : Int
|
||||
, gcCounter : Int
|
||||
, stack : List MalExpr
|
||||
, keepFrames : List Int
|
||||
}
|
||||
|
||||
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user