Elm: step5 - TCO the theory
[jackhill/mal.git] / elm / Eval.elm
CommitLineData
c792f15e
JB
1module Eval exposing (..)
2
3import Types exposing (..)
4import IO exposing (IO)
0bac0757
JB
5import Env
6import Printer
c792f15e
JB
7
8
86fcd61d 9apply : Eval a -> Env -> EvalContext a
c792f15e
JB
10apply (Eval f) state =
11 f state
12
13
86fcd61d 14run : Env -> Eval a -> EvalContext a
c792f15e
JB
15run state e =
16 apply e state
17
18
86fcd61d
JB
19withEnv : (Env -> Eval a) -> Eval a
20withEnv f =
c792f15e
JB
21 Eval <|
22 \state ->
23 apply (f state) state
24
25
86fcd61d
JB
26setEnv : Env -> Eval ()
27setEnv state =
c792f15e
JB
28 Eval <|
29 \_ ->
30 apply (succeed ()) state
31
32
86fcd61d
JB
33modifyEnv : (Env -> Env) -> Eval ()
34modifyEnv f =
c792f15e
JB
35 Eval <|
36 \state ->
37 apply (succeed ()) (f state)
38
39
40succeed : a -> Eval a
41succeed res =
42 Eval <|
43 \state ->
44 ( state, EvalOk res )
45
46
47io : Cmd Msg -> (IO -> Eval a) -> Eval a
48io cmd cont =
49 Eval <|
50 \state ->
51 ( state, EvalIO cmd cont )
52
53
54map : (a -> b) -> Eval a -> Eval b
55map f e =
56 Eval <|
57 \state ->
58 case apply e state of
59 ( state, EvalOk res ) ->
60 ( state, EvalOk (f res) )
61
62 ( state, EvalErr msg ) ->
63 ( state, EvalErr msg )
64
65 ( state, EvalIO cmd cont ) ->
66 ( state, EvalIO cmd (cont >> map f) )
67
68
69andThen : (a -> Eval b) -> Eval a -> Eval b
70andThen f e =
71 Eval <|
72 \state ->
73 case apply e state of
74 ( state, EvalOk res ) ->
75 apply (f res) state
76
77 ( state, EvalErr msg ) ->
78 ( state, EvalErr msg )
79
80 ( state, EvalIO cmd cont ) ->
81 ( state, EvalIO cmd (cont >> andThen f) )
82
83
c792f15e
JB
84fail : String -> Eval a
85fail msg =
86 Eval <|
87 \state ->
88 ( state, EvalErr msg )
0bac0757
JB
89
90
91enter : Int -> List ( String, MalExpr ) -> Eval a -> Eval a
92enter frameId bound body =
93 withEnv
94 (\env ->
95 modifyEnv (Env.enter frameId bound)
96 |> andThen (\_ -> body)
97 |> andThen
98 (\res ->
99 modifyEnv (Env.leave env.currentFrameId)
100 |> map (\_ -> res)
101 )
102 )