-
Notifications
You must be signed in to change notification settings - Fork 0
/
Interpreter.elm
118 lines (95 loc) · 2.78 KB
/
Interpreter.elm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
module Ch1.L_Int.Interpreter exposing
( Error(..)
, Input
, RuntimeError(..)
, run
, runProgram
)
import Ch1.L_Int.AST as AST exposing (..)
import Ch1.L_Int.Parser as P
type alias Input =
List Int
type Error
= SyntaxError P.Error
| RuntimeError RuntimeError
type RuntimeError
= MissingInput
run : String -> Input -> Result Error Int
run source input =
case P.parse source of
Ok program ->
runProgram program input
|> Result.mapError RuntimeError
Err err ->
Err <| SyntaxError err
runProgram : AST.Program -> Input -> Result RuntimeError Int
runProgram (Program expr) =
interpretExpr expr >> Tuple.first
interpretExpr : Expr -> Input -> ( Result RuntimeError Int, Input )
interpretExpr expr input =
case expr of
Int n ->
( Ok n
, input
)
Prim Read ->
case input of
[] ->
( Err MissingInput
, input
)
n :: restInput ->
( Ok n
, restInput
)
Prim (Negate aExpr) ->
interpretExpr aExpr input
|> Tuple.mapFirst (Result.map negate)
Prim (Add aExpr bExpr) ->
let
( aResult, input1 ) =
interpretExpr aExpr input
in
case aResult of
Ok a ->
let
( bResult, input2 ) =
interpretExpr bExpr input1
in
case bResult of
Ok b ->
( Ok <| a + b
, input2
)
Err _ ->
( bResult
, input2
)
Err _ ->
( aResult
, input1
)
Prim (Sub aExpr bExpr) ->
let
( aResult, input1 ) =
interpretExpr aExpr input
in
case aResult of
Ok a ->
let
( bResult, input2 ) =
interpretExpr bExpr input1
in
case bResult of
Ok b ->
( Ok <| a - b
, input2
)
Err _ ->
( bResult
, input2
)
Err _ ->
( aResult
, input1
)