HCoop
/
jackhill
/
mal.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Elm step A
[jackhill/mal.git]
/
elm
/
Env.elm
diff --git
a/elm/Env.elm
b/elm/Env.elm
index
19158e8
..
658ee1a
100644
(file)
--- a/
elm/Env.elm
+++ b/
elm/Env.elm
@@
-1,8
+1,11
@@
module Env
exposing
module Env
exposing
- ( global
+ ( debug
+ , globalFrameId
+ , global
, push
, pop
, push
, pop
+ , jump
, enter
, leave
, ref
, enter
, leave
, ref
@@
-20,6
+23,14
@@
import Array
import Set
import Set
+debug : Env -> String -> a -> a
+debug env msg value =
+ if env.debug then
+ Debug.log msg value
+ else
+ value
+
+
globalFrameId : Int
globalFrameId =
0
globalFrameId : Int
globalFrameId =
0
@@
-32,9
+43,15
@@
global =
, currentFrameId = globalFrameId
, atoms = Dict.empty
, nextAtomId = 0
, currentFrameId = globalFrameId
, atoms = Dict.empty
, nextAtomId = 0
+ , debug = False
}
}
+jump : Int -> Env -> Env
+jump frameId env =
+ { env | currentFrameId = frameId }
+
+
push : Env -> Env
push env =
let
push : Env -> Env
push env =
let
@@
-91,8
+108,7
@@
enter : Int -> List ( String, MalExpr ) -> Env -> Env
enter parentFrameId binds env =
let
frameId =
enter parentFrameId binds env =
let
frameId =
- Debug.log "enter #"
- env.nextFrameId
+ debug env "enter #" env.nextFrameId
newFrame =
setBinds binds (emptyFrame (Just parentFrameId))
newFrame =
setBinds binds (emptyFrame (Just parentFrameId))
@@
-108,8
+124,7
@@
leave : Int -> Env -> Env
leave orgFrameId env =
let
frameId =
leave orgFrameId env =
let
frameId =
- Debug.log "leave #"
- env.currentFrameId
+ debug env "leave #" env.currentFrameId
in
{ env
| currentFrameId = orgFrameId
in
{ env
| currentFrameId = orgFrameId
@@
-134,12
+149,6
@@
ref env =
{ env | frames = newFrames }
{ env | frames = newFrames }
-
--- TODO: when disposing, deref all function's frames?
--- TODO: is that enough instead of a GC? no: don't know how often the function is referenced.
--- TODO: consideration: keep refCnt for MalFunction, or implement a light GC.
-
-
deref : Maybe Frame -> Maybe Frame
deref =
Maybe.andThen
deref : Maybe Frame -> Maybe Frame
deref =
Maybe.andThen
@@
-151,12
+160,6
@@
deref =
)
)
-
--- TODO need a GC.
--- given a Env, see which frames are not reachable.
--- in MalFunction need to refer to the frameId.
-
-
{-| Given an Env see which frames are not reachable from the
global frame. Return a new Env without the unreachable frames.
-}
{-| Given an Env see which frames are not reachable from the
global frame. Return a new Env without the unreachable frames.
-}
@@
-170,11
+173,11
@@
gc env =
data |> Dict.values |> countList acc
countRefs expr acc =
data |> Dict.values |> countList acc
countRefs expr acc =
-
Debug.log (toString expr
) <|
+
debug env ("gc-visit " ++ (toString expr)
) <|
case expr of
MalFunction (UserFunc { frameId }) ->
if not (Set.member frameId acc) then
case expr of
MalFunction (UserFunc { frameId }) ->
if not (Set.member frameId acc) then
-
Debug.log "
counting" <|
+
debug env "gc-
counting" <|
case Dict.get frameId env.frames of
Just frame ->
countFrame (Set.insert frameId acc) frame
case Dict.get frameId env.frames of
Just frame ->
countFrame (Set.insert frameId acc) frame
@@
-198,6
+201,11
@@
gc env =
initSet =
Set.fromList [ globalFrameId, env.currentFrameId ]
initSet =
Set.fromList [ globalFrameId, env.currentFrameId ]
+
+ reportUnused frames used =
+ Dict.diff frames used
+ |> debug env "unused frames"
+ |> (\_ -> frames)
in
case Dict.get globalFrameId env.frames of
Nothing ->
in
case Dict.get globalFrameId env.frames of
Nothing ->
@@
-206,10
+214,11
@@
gc env =
Just globalFrame ->
countFrame initSet globalFrame
|> Set.toList
Just globalFrame ->
countFrame initSet globalFrame
|> Set.toList
- |>
Debug.log
"used frames"
+ |>
debug env
"used frames"
|> List.map (\frameId -> ( frameId, emptyFrame Nothing ))
|> Dict.fromList
|> List.map (\frameId -> ( frameId, emptyFrame Nothing ))
|> Dict.fromList
- |> Dict.intersect (Debug.log "cur frames" env.frames)
+ |> reportUnused env.frames
+ |> Dict.intersect env.frames
|> (\frames -> { env | frames = frames })
|> (\frames -> { env | frames = frames })
@@
-221,8
+230,8
@@
emptyFrame outerId =
}
}
-set
:
String -> MalExpr -> Env -> Env
-set name expr env =
+set
InFrame : Int ->
String -> MalExpr -> Env -> Env
+set
InFrame frameId
name expr env =
let
updateFrame =
Maybe.map
let
updateFrame =
Maybe.map
@@
-230,15
+239,17
@@
set name expr env =
{ frame | data = Dict.insert name expr frame.data }
)
{ frame | data = Dict.insert name expr frame.data }
)
- frameId =
- env.currentFrameId
-
newFrames =
Dict.update frameId updateFrame env.frames
in
{ env | frames = newFrames }
newFrames =
Dict.update frameId updateFrame env.frames
in
{ env | frames = newFrames }
+set : String -> MalExpr -> Env -> Env
+set name expr env =
+ setInFrame env.currentFrameId name expr env
+
+
get : String -> Env -> Result String MalExpr
get name env =
let
get : String -> Env -> Result String MalExpr
get name env =
let
@@
-255,7
+266,7
@@
get name env =
Nothing ->
frame.outerId
|> Maybe.map go
Nothing ->
frame.outerId
|> Maybe.map go
- |> Maybe.withDefault (Err
"symbol
not found")
+ |> Maybe.withDefault (Err
<| "'" ++ name ++ "'
not found")
in
go env.currentFrameId
in
go env.currentFrameId