1 module Eval exposing (..)
3 import Types exposing (..)
4 import IO exposing (IO)
8 apply : Eval a -> Env -> EvalContext a
13 run : Env -> Eval a -> EvalContext a
18 withEnv : (Env -> Eval a) -> Eval a
23 setEnv : Env -> Eval ()
25 apply (succeed ()) env
28 modifyEnv : (Env -> Env) -> Eval ()
30 apply (succeed ()) (f env)
38 io : Cmd Msg -> (IO -> Eval a) -> Eval a
40 ( env, EvalIO cmd cont )
43 map : (a -> b) -> Eval a -> Eval b
46 ( env, EvalOk res ) ->
47 ( env, EvalOk (f res) )
49 ( env, EvalErr msg ) ->
52 ( env, EvalIO cmd cont ) ->
53 ( env, EvalIO cmd (cont >> map f) )
56 {-| Chain two Eval's together. The function f takes the result from
57 the left eval and generates a new Eval.
59 andThen : (a -> Eval b) -> Eval a -> Eval b
62 ( env, EvalOk res ) ->
65 ( env, EvalErr msg ) ->
68 ( env, EvalIO cmd cont ) ->
69 ( env, EvalIO cmd (cont >> andThen f) )
72 {-| Apply a transformation to the Env, for a Ok and a Err.
74 finally : (Env -> Env) -> Eval a -> Eval a
77 ( env, EvalOk res ) ->
80 ( env, EvalErr msg ) ->
81 ( f env, EvalErr msg )
83 ( env, EvalIO cmd cont ) ->
84 ( env, EvalIO cmd (cont >> finally f) )
87 gcPass : Eval MalExpr -> Eval MalExpr
91 if env.gcCounter >= env.gcInterval then
97 -- |> always ( Env.gc env, t expr )
98 ( Env.gc expr env, t expr )
103 ( env, EvalOk res ) ->
106 ( env, EvalErr msg ) ->
109 ( env, EvalIO cmd cont ) ->
110 ( env, EvalIO cmd (cont >> gcPass) )
113 catchError : (MalExpr -> Eval a) -> Eval a -> Eval a
116 ( env, EvalOk res ) ->
119 ( env, EvalErr msg ) ->
122 ( env, EvalIO cmd cont ) ->
123 ( env, EvalIO cmd (cont >> catchError f) )
126 fail : String -> Eval a
128 ( env, EvalErr <| MalString msg )
131 throw : MalExpr -> Eval a
136 {-| Apply f to expr repeatedly.
137 Continues iterating if f returns (Left eval).
138 Stops if f returns (Right expr).
143 runLoop : (MalExpr -> Env -> Either (Eval MalExpr) MalExpr) -> MalExpr -> Eval MalExpr
148 ( env, EvalOk expr ) ->
151 ( env, EvalErr msg ) ->
154 ( env, EvalIO cmd cont ) ->
155 ( env, EvalIO cmd (cont >> andThen (runLoop f)) )
161 fromResult : Result String a -> Eval a
171 {-| Chain the left and right Eval but ignore the right's result.
173 ignore : Eval b -> Eval a -> Eval a
179 |> andThen (\_ -> succeed res)
183 withStack : Eval a -> Eval a
190 (Env.restoreRefs env.stack)
195 pushRef : MalExpr -> Eval a -> Eval a
197 modifyEnv (Env.pushRef ref)
198 |> andThen (always e)
201 inGlobal : Eval a -> Eval a
207 | keepFrames = env.currentFrameId :: env.keepFrames
208 , currentFrameId = Env.globalFrameId
211 leave oldEnv newEnv =
213 | keepFrames = oldEnv.keepFrames
214 , currentFrameId = oldEnv.currentFrameId
219 if env.currentFrameId /= Env.globalFrameId then
221 |> andThen (always body)
222 |> finally (leave env)
228 runSimple : Eval a -> Result MalExpr a
230 case run Env.global e of
234 ( _, EvalErr msg ) ->
238 Debug.crash "can't happen"