DynEditorExample.icl 12.1 KB
Newer Older
1 2
module DynEditorExample

Steffen Michels's avatar
Steffen Michels committed
3
import StdEnv
Tim Steenvoorden's avatar
Tim Steenvoorden committed
4 5
import Data.Func
import Data.Functor
6
import Text
Tim Steenvoorden's avatar
Tim Steenvoorden committed
7 8
import iTasks
import iTasks.Extensions.Editors.DynamicEditor
9

Tim Steenvoorden's avatar
Tim Steenvoorden committed
10 11 12

// Synonyms ////////////////////////////////////////////////////////////////////

Tim Steenvoorden's avatar
Tim Steenvoorden committed
13
:: List a :== [a]
Tim Steenvoorden's avatar
Tim Steenvoorden committed
14

Tim Steenvoorden's avatar
Tim Steenvoorden committed
15 16 17

// Main ////////////////////////////////////////////////////////////////////////

18 19
Start world = doTasks editTask world

Tim Steenvoorden's avatar
Tim Steenvoorden committed
20 21 22 23 24 25 26 27
editTask :: Task Value
editTask = forever $
  enterInformation ("Contruct a task", info1) [EnterUsing id $ dynamicEditor taskEditor]
    >>= \v ->
        viewInformation ("Evaluate the task", info2) [] ()
          ||- (evalTaskExpr (toValue taskEditor v) <<@ ApplyLayout frameCompact)
          >>= viewInformation ("Done!", info3) []
          >>= return  // Extra return to disable `Continue` button
Tim Steenvoorden's avatar
Tim Steenvoorden committed
28
where
Tim Steenvoorden's avatar
Tim Steenvoorden committed
29
  info1 :: String
Tim Steenvoorden's avatar
Tim Steenvoorden committed
30
  info1 = "Select the editors and combinators you'd like to use. When you're ready, push the 'Continue' button below to run your program."
Tim Steenvoorden's avatar
Tim Steenvoorden committed
31
  info2 :: String
Tim Steenvoorden's avatar
Tim Steenvoorden committed
32
  info2 = "Now step through the task you just created to test it."
Tim Steenvoorden's avatar
Tim Steenvoorden committed
33
  info3 :: String
Tim Steenvoorden's avatar
Tim Steenvoorden committed
34
  info3 = "The program is done, the result is given below."
35 36


Tim Steenvoorden's avatar
Tim Steenvoorden committed
37 38
// Data ////////////////////////////////////////////////////////////////////////

Tim Steenvoorden's avatar
Tim Steenvoorden committed
39
:: TaskExpr
Tim Steenvoorden's avatar
Tim Steenvoorden committed
40 41
  = Done Expr
  // | Apply TaskFuncExpr Expr
Tim Steenvoorden's avatar
Tim Steenvoorden committed
42
  | EnterInfo String Ty
Tim Steenvoorden's avatar
Tim Steenvoorden committed
43 44 45 46
  | Then TaskExpr TaskFuncExpr
  | Or TaskExpr TaskExpr
  | And TaskExpr TaskExpr
  | When TaskExpr (List TaskContExpr)
47

Tim Steenvoorden's avatar
Tim Steenvoorden committed
48
:: TaskFuncExpr
Tim Steenvoorden's avatar
Tim Steenvoorden committed
49 50
  = ViewInfo String
  | UpdateInfo String
51

Tim Steenvoorden's avatar
Tim Steenvoorden committed
52 53 54
:: TaskContExpr
  = { name :: String, pred :: FuncExpr, cont :: TaskFuncExpr}

Tim Steenvoorden's avatar
Tim Steenvoorden committed
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
:: Expr
  = Int Int
  | Bool Bool
  | String String
  | Tuple Expr Expr
  | Fst Expr
  | Snd Expr
  | Eq Expr Expr

:: Value
  = VInt Int
  | VBool Bool
  | VString String
  | VTuple Value Value

Tim Steenvoorden's avatar
Tim Steenvoorden committed
70
:: FuncExpr
Tim Steenvoorden's avatar
Tim Steenvoorden committed
71 72 73 74 75 76 77 78 79
  = EqV Value
  | GrtV Value
  | LessV Value

:: Ty
  = E.a: Ty (a -> Value) & iTask a

:: Typed a b
  =: Typed a
80

Tim Steenvoorden's avatar
Tim Steenvoorden committed
81
derive class iTask TaskExpr, TaskFuncExpr, TaskContExpr, Expr, FuncExpr, Value, Typed
82

Tim Steenvoorden's avatar
Tim Steenvoorden committed
83 84
// These instances cannot be auto derived because of the existential quantifier.
// However, they will be never used, so we make them undefined.
Tim Steenvoorden's avatar
Tim Steenvoorden committed
85 86 87 88 89 90 91
gDefault{|Ty|} = undef
gEq{|Ty|} _ _ = undef
JSONEncode{|Ty|} _ _ = undef
JSONDecode{|Ty|} _ _ = undef
gText{|Ty|} _ _ = undef
gEditor{|Ty|} = undef

92

Tim Steenvoorden's avatar
Tim Steenvoorden committed
93 94
// Editor //////////////////////////////////////////////////////////////////////

Tim Steenvoorden's avatar
Tim Steenvoorden committed
95
taskEditor :: DynamicEditor TaskExpr
96 97
taskEditor = DynamicEditor conses
where
Tim Steenvoorden's avatar
Tim Steenvoorden committed
98
  conses =
Tim Steenvoorden's avatar
Tim Steenvoorden committed
99
    [ // This cons is used to provide untyped `TaskExpr` values.
Tim Steenvoorden's avatar
Tim Steenvoorden committed
100
      DynamicCons
Tim Steenvoorden's avatar
Tim Steenvoorden committed
101
        $ functionConsDyn "TaskExpr" "(enter task)" (dynamic \(Typed taskExpr) -> taskExpr ::  A.a: (Typed TaskExpr a) -> TaskExpr)
Tim Steenvoorden's avatar
Tim Steenvoorden committed
102
        <<@@@ HideIfOnlyChoice
Tim Steenvoorden's avatar
Tim Steenvoorden committed
103
    , DynamicConsGroup "Combinators"
Tim Steenvoorden's avatar
Tim Steenvoorden committed
104 105 106 107 108 109 110 111
        [ functionConsDyn "Done" "done"
            ( dynamic \(Typed expr) -> Typed (Done expr) ::
                A.a:
                (Typed Expr a)
                -> Typed TaskExpr (Task a)
            )
        , functionConsDyn "Then" "sequence"
            ( dynamic \(Typed task) (Typed taskFunc) -> Typed (Then task taskFunc) ::
Tim Steenvoorden's avatar
Tim Steenvoorden committed
112
                A.a b:
Tim Steenvoorden's avatar
Tim Steenvoorden committed
113 114
                (Typed TaskExpr (Task a)) (Typed TaskFuncExpr (a -> Task b))
                -> Typed TaskExpr (Task b)
Tim Steenvoorden's avatar
Tim Steenvoorden committed
115
            )
Tim Steenvoorden's avatar
Tim Steenvoorden committed
116
        , functionConsDyn "When" "guarded sequence"
Tim Steenvoorden's avatar
Tim Steenvoorden committed
117
            ( dynamic \(Typed task1) (Typed steps) -> Typed (When task1 steps) ::
118
              // Typed (When task1 [(expr, pred, tfExpr) \\ (Typed expr, pred, Typed tfExpr) <- steps]) ::
Tim Steenvoorden's avatar
Tim Steenvoorden committed
119
                A.a b:
Tim Steenvoorden's avatar
Tim Steenvoorden committed
120 121 122 123
                (Typed TaskExpr (Task a))
                (Typed (List TaskContExpr) (a -> Task b))
                // (Typed (List (Typed FuncExpr (a -> Bool), String, Typed TaskFuncExpr (a -> Task a))) (a -> Task b))
                -> Typed TaskExpr (Task b)
Tim Steenvoorden's avatar
Tim Steenvoorden committed
124
            )
Tim Steenvoorden's avatar
Tim Steenvoorden committed
125 126
            <<@@@ applyHorizontalClasses
        , functionConsDyn "Or" "or"
Tim Steenvoorden's avatar
Tim Steenvoorden committed
127
            ( dynamic \(Typed task1) (Typed task2) -> Typed (Or task1 task2) ::
Tim Steenvoorden's avatar
Tim Steenvoorden committed
128
                A.a b:
129 130
                (Typed TaskExpr (Task a))
                (Typed TaskExpr (Task a))
Tim Steenvoorden's avatar
Tim Steenvoorden committed
131
                -> Typed TaskExpr (Task a)
Tim Steenvoorden's avatar
Tim Steenvoorden committed
132
            )
133
            <<@@@ applyHorizontalClasses
Tim Steenvoorden's avatar
Tim Steenvoorden committed
134
        , functionConsDyn "And" "and"
Tim Steenvoorden's avatar
Tim Steenvoorden committed
135
            ( dynamic \(Typed task1) (Typed task2) -> Typed (And task1 task2) ::
Tim Steenvoorden's avatar
Tim Steenvoorden committed
136
                A.a b:
137 138
                (Typed TaskExpr (Task a))
                (Typed TaskExpr (Task b))
Tim Steenvoorden's avatar
Tim Steenvoorden committed
139
                -> Typed TaskExpr (Task (a, b))
Tim Steenvoorden's avatar
Tim Steenvoorden committed
140
            )
141
            <<@@@ applyHorizontalClasses
Tim Steenvoorden's avatar
Tim Steenvoorden committed
142
        , listConsDyn "List TaskContExpr" "continuations"
Tim Steenvoorden's avatar
Tim Steenvoorden committed
143
            ( dynamic \typedSteps -> Typed ((\(Typed expr) -> expr) <$> typedSteps) ::
Tim Steenvoorden's avatar
Tim Steenvoorden committed
144
                A.a b:
145
                (List (Typed TaskContExpr (a -> Task b)))
Tim Steenvoorden's avatar
Tim Steenvoorden committed
146
                -> Typed (List TaskContExpr) (a -> Task b)
Tim Steenvoorden's avatar
Tim Steenvoorden committed
147 148
            )
            <<@@@ HideIfOnlyChoice
Tim Steenvoorden's avatar
Tim Steenvoorden committed
149
        , functionConsDyn "TaskContExpr" "continuation"
Tim Steenvoorden's avatar
Tim Steenvoorden committed
150
            ( dynamic \s (Typed func) (Typed taskFunc) -> Typed {name = s, pred = func, cont = taskFunc} ::
Tim Steenvoorden's avatar
Tim Steenvoorden committed
151
                A.a b:
Tim Steenvoorden's avatar
Tim Steenvoorden committed
152
                String
Tim Steenvoorden's avatar
Tim Steenvoorden committed
153
                (Typed FuncExpr a)
Tim Steenvoorden's avatar
Tim Steenvoorden committed
154
                (Typed TaskFuncExpr (a -> Task b))
Tim Steenvoorden's avatar
Tim Steenvoorden committed
155
                -> Typed TaskContExpr (a -> Task b)
Tim Steenvoorden's avatar
Tim Steenvoorden committed
156 157
            )
            <<@@@ HideIfOnlyChoice
Tim Steenvoorden's avatar
Tim Steenvoorden committed
158
            <<@@@ AddLabels [Just "name", Just "predicate", Just "continuation"]
Tim Steenvoorden's avatar
Tim Steenvoorden committed
159
        ]
Tim Steenvoorden's avatar
Tim Steenvoorden committed
160
    , DynamicConsGroup "Editors"
Tim Steenvoorden's avatar
Tim Steenvoorden committed
161 162 163 164 165 166 167 168 169 170
        // [ functionConsDyn "Apply" "apply"
        //     ( dynamic \(Typed taskFunc) (Typed expr) ->
        //       Typed (Apply taskFunc expr) ::
        //         A.a b:
        //         (Typed TaskFuncExpr (a -> Task b))
        //         (Typed Expr a)
        //         -> Typed TaskExpr (Task b)
        //     )
        [ functionConsDyn "EnterInfo" "enter information"
            ( dynamic \s (Typed ty) -> Typed (EnterInfo s ty) ::
Tim Steenvoorden's avatar
Tim Steenvoorden committed
171
                A.a:
Tim Steenvoorden's avatar
Tim Steenvoorden committed
172
                String (Typed Ty a)
Tim Steenvoorden's avatar
Tim Steenvoorden committed
173
                -> Typed TaskExpr (Task a)
Tim Steenvoorden's avatar
Tim Steenvoorden committed
174 175
            )
            <<@@@ applyHorizontalClasses
Tim Steenvoorden's avatar
Tim Steenvoorden committed
176
        , functionConsDyn "ViewInfo" "view information"
Tim Steenvoorden's avatar
Tim Steenvoorden committed
177
            ( dynamic \s -> Typed (ViewInfo s) ::
Tim Steenvoorden's avatar
Tim Steenvoorden committed
178
                A.a:
Tim Steenvoorden's avatar
Tim Steenvoorden committed
179 180
                String
                -> Typed TaskFuncExpr (a -> Task a)
Tim Steenvoorden's avatar
Tim Steenvoorden committed
181 182
            )
            <<@@@ applyHorizontalClasses
Tim Steenvoorden's avatar
Tim Steenvoorden committed
183
        , functionConsDyn "UpdateInfo" "update information"
Tim Steenvoorden's avatar
Tim Steenvoorden committed
184
            ( dynamic \s -> Typed (UpdateInfo s) ::
Tim Steenvoorden's avatar
Tim Steenvoorden committed
185
                A.a:
Tim Steenvoorden's avatar
Tim Steenvoorden committed
186 187
                String
                -> Typed TaskFuncExpr (a -> Task a)
Tim Steenvoorden's avatar
Tim Steenvoorden committed
188 189 190
            )
            <<@@@ applyHorizontalClasses
        ]
Tim Steenvoorden's avatar
Tim Steenvoorden committed
191
    // ordinary (non-task) expressions
Tim Steenvoorden's avatar
Tim Steenvoorden committed
192
    , DynamicCons
Tim Steenvoorden's avatar
Tim Steenvoorden committed
193
        $ functionConsDyn "EqV" "equal" (dynamic \i -> Typed (EqV (VInt i)) :: Int -> Typed FuncExpr Int)
Tim Steenvoorden's avatar
Tim Steenvoorden committed
194 195
        <<@@@ applyHorizontalClasses
    , DynamicCons
Tim Steenvoorden's avatar
Tim Steenvoorden committed
196
        $ functionConsDyn "GrtV" "greater" (dynamic \i -> Typed (GrtV (VInt i)) :: Int -> Typed FuncExpr Int)
Tim Steenvoorden's avatar
Tim Steenvoorden committed
197 198
        <<@@@ applyHorizontalClasses
    , DynamicCons
Tim Steenvoorden's avatar
Tim Steenvoorden committed
199
        $ functionConsDyn "LessV" "less" (dynamic \i -> Typed (LessV (VInt i)) :: Int -> Typed FuncExpr Int)
Tim Steenvoorden's avatar
Tim Steenvoorden committed
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
        <<@@@ applyHorizontalClasses
    , DynamicCons
        $ functionConsDyn "int" "enter an integer:" (dynamic \i -> Typed (Int i) :: Int -> Typed Expr Int)
    , DynamicCons
        $ functionConsDyn "bool" "enter a boolean:" (dynamic \b -> Typed (Bool b) :: Bool -> Typed Expr Bool)
    , DynamicCons
        $ functionConsDyn "string" "enter a string:" (dynamic \s -> Typed (String s) :: String -> Typed Expr String)
    , DynamicCons
        $ functionConsDyn "tuple" "enter tuple:"
            ( dynamic \(Typed a) (Typed b) ->
              Typed (Tuple a b) ::
                A.a b:
                  (Typed Expr a) (Typed Expr b) -> Typed Expr (a, b)
            )
    , DynamicCons
        $ functionConsDyn "fst" "fst" (dynamic \(Typed (Tuple a _)) -> Typed a ::  A.a b: (Typed Expr (a, b)) -> Typed Expr a)
        <<@@@ applyHorizontalClasses
    , DynamicCons
        $ functionConsDyn "snd" "snd" (dynamic \(Typed (Tuple _ b)) -> Typed b ::  A.a b: (Typed Expr (a, b)) -> Typed Expr b)
        <<@@@ applyHorizontalClasses
    , DynamicCons
        $ functionConsDyn "==" "=="
            ( dynamic \(Typed a) (Typed b) ->
              Typed (Eq a b) ::
                A.a:
                  (Typed Expr a) (Typed Expr a) -> Typed Expr Bool
            )
        <<@@@ applyHorizontalClasses
    , DynamicCons $ customEditorCons "Int" "(enter integer)" intEditor <<@@@ HideIfOnlyChoice
    , DynamicCons $ customEditorCons "Bool" "(enter boolean)" boolEditor <<@@@ HideIfOnlyChoice
    , DynamicCons $ customEditorCons "String" "(enter string )" stringEditor <<@@@ HideIfOnlyChoice
Tim Steenvoorden's avatar
Tim Steenvoorden committed
231
    // type specifications for enterInformation
Tim Steenvoorden's avatar
Tim Steenvoorden committed
232 233 234 235 236 237 238 239 240 241 242
    , DynamicCons $ functionConsDyn "Ty.Int" "Int" (dynamic Typed (Ty VInt) :: Typed Ty Int)
    , DynamicCons $ functionConsDyn "Ty.Bool" "Bool" (dynamic Typed (Ty VBool) :: Typed Ty Bool)
    , DynamicCons $ functionConsDyn "Ty.String" "String" (dynamic Typed (Ty VString) :: Typed Ty String)
    , DynamicCons
        $ functionConsDyn "Ty.Tuple" "Tuple"
            ( dynamic \(Typed (Ty toValue1)) (Typed (Ty toValue2)) ->
              Typed (Ty \(x, y) -> VTuple (toValue1 x) (toValue2 y)) ::
                A.a b:
                  (Typed Ty a) (Typed Ty b) -> Typed Ty (a, b)
            )
        <<@@@ applyHorizontalClasses
Tim Steenvoorden's avatar
Tim Steenvoorden committed
243 244 245
    ]


Tim Steenvoorden's avatar
Tim Steenvoorden committed
246 247
// Helpers //

Tim Steenvoorden's avatar
Tim Steenvoorden committed
248 249 250 251 252 253
derivedType :: Typed Ty a | iTask a
derivedType = case dynToValue of
  (toValue :: a^ -> Value | iTask a^) = Typed (Ty toValue)
where
  dynToValue = dynamic ()

Tim Steenvoorden's avatar
Tim Steenvoorden committed
254

Tim Steenvoorden's avatar
Tim Steenvoorden committed
255 256
intEditor :: Editor Int
intEditor = gEditor{|*|}
Tim Steenvoorden's avatar
Tim Steenvoorden committed
257

Tim Steenvoorden's avatar
Tim Steenvoorden committed
258 259
boolEditor :: Editor Bool
boolEditor = gEditor{|*|}
260

Tim Steenvoorden's avatar
Tim Steenvoorden committed
261 262
stringEditor :: Editor String
stringEditor = gEditor{|*|}
263

264 265
applyHorizontalClasses = ApplyCssClasses ["itasks-horizontal", "itasks-wrap-width", "itasks-panel"]

Tim Steenvoorden's avatar
Tim Steenvoorden committed
266

Tim Steenvoorden's avatar
Tim Steenvoorden committed
267 268
// Evaluation //////////////////////////////////////////////////////////////////

Tim Steenvoorden's avatar
Tim Steenvoorden committed
269
evalTaskConstExpr :: TaskExpr -> Task Value
Tim Steenvoorden's avatar
Tim Steenvoorden committed
270
evalTaskConstExpr (Done expr) = return $ evalExpr expr
Tim Steenvoorden's avatar
Tim Steenvoorden committed
271
evalTaskConstExpr (EnterInfo msg (Ty toValue)) = enterInformation msg [] @ toValue
Tim Steenvoorden's avatar
Tim Steenvoorden committed
272
// evalTaskConstExpr (Apply taskFunc expr) = evalTaskFuncExpr taskFunc $ evalExpr expr
Tim Steenvoorden's avatar
Tim Steenvoorden committed
273
evalTaskConstExpr (Then task taskFunc) = evalTaskConstExpr task >>= evalTaskFuncExpr taskFunc
274 275
evalTaskConstExpr (Or task1 task2) = (evalTaskConstExpr task1 -||- evalTaskConstExpr task2 <<@ ApplyLayout arrangeHorizontal)
evalTaskConstExpr (And task1 task2) = (evalTaskConstExpr task1 -&&- evalTaskConstExpr task2 <<@ ApplyLayout arrangeHorizontal) @ \(a, b) -> VTuple a b
Tim Steenvoorden's avatar
Tim Steenvoorden committed
276
evalTaskConstExpr (When task1 options) = evalTaskConstExpr task1
Tim Steenvoorden's avatar
Tim Steenvoorden committed
277 278 279
  >>* [ OnAction (Action name) (ifValue (test pred) (evalTaskFuncExpr cont))
      \\ {name, pred, cont} <- options
      ]
Steffen Michels's avatar
Steffen Michels committed
280
where
Tim Steenvoorden's avatar
Tim Steenvoorden committed
281
  test pred (VInt i) = case pred of
Tim Steenvoorden's avatar
Tim Steenvoorden committed
282 283 284 285
    LessV (VInt j) -> i < j
    GrtV (VInt j) -> i > j
    EqV (VInt j) -> i == j

Tim Steenvoorden's avatar
Tim Steenvoorden committed
286
  test pred (VBool i) = case pred of
Tim Steenvoorden's avatar
Tim Steenvoorden committed
287 288 289 290
    EqV (VBool j) -> i == j
    LessV (VBool j) -> False
    GrtV (VBool j) -> False

291 292

evalTaskFuncExpr :: TaskFuncExpr Value -> Task Value
Tim Steenvoorden's avatar
Tim Steenvoorden committed
293 294 295 296
evalTaskFuncExpr (ViewInfo p) (VInt i) = (viewInformation p [] i @ VInt) <<@ ApplyLayout arrangeHorizontal
evalTaskFuncExpr (ViewInfo p) (VBool b) = (viewInformation p [] b @ VBool) <<@ ApplyLayout arrangeHorizontal
evalTaskFuncExpr (ViewInfo p) (VString s) = (viewInformation p [] s @ VString) <<@ ApplyLayout arrangeHorizontal
evalTaskFuncExpr (ViewInfo p) (VTuple a b) =
Tim Steenvoorden's avatar
Tim Steenvoorden committed
297
  ( viewInformation p [] ()
Tim Steenvoorden's avatar
Tim Steenvoorden committed
298 299
    ||- evalTaskFuncExpr (ViewInfo "") a
    -&&- evalTaskFuncExpr (ViewInfo "") b
Tim Steenvoorden's avatar
Tim Steenvoorden committed
300 301 302
    @ \(a, b) -> VTuple a b
  )
    <<@ ApplyLayout arrangeHorizontal
Tim Steenvoorden's avatar
Tim Steenvoorden committed
303 304 305 306
evalTaskFuncExpr (UpdateInfo p) (VInt i) = (updateInformation p [] i @ VInt) <<@ ApplyLayout arrangeHorizontal
evalTaskFuncExpr (UpdateInfo p) (VBool b) = (updateInformation p [] b @ VBool) <<@ ApplyLayout arrangeHorizontal
evalTaskFuncExpr (UpdateInfo p) (VString s) = (updateInformation p [] s @ VString) <<@ ApplyLayout arrangeHorizontal
evalTaskFuncExpr (UpdateInfo p) (VTuple a b) =
Tim Steenvoorden's avatar
Tim Steenvoorden committed
307
  ( viewInformation p [] ()
Tim Steenvoorden's avatar
Tim Steenvoorden committed
308 309
    ||- evalTaskFuncExpr (UpdateInfo "") a
    -&&- evalTaskFuncExpr (UpdateInfo "") b
Tim Steenvoorden's avatar
Tim Steenvoorden committed
310 311 312 313
    @ \(a, b) -> VTuple a b
  )
    <<@ ApplyLayout arrangeHorizontal

314
evalExpr :: Expr -> Value
Tim Steenvoorden's avatar
Tim Steenvoorden committed
315 316 317
evalExpr (Int i) = VInt i
evalExpr (Bool b) = VBool b
evalExpr (String s) = VString s
318
evalExpr (Tuple fstExpr sndExpr) = VTuple (evalExpr fstExpr) (evalExpr sndExpr)
Tim Steenvoorden's avatar
Tim Steenvoorden committed
319
evalExpr (Fst expr) = fst
320
where
Tim Steenvoorden's avatar
Tim Steenvoorden committed
321
  (VTuple fst _) = evalExpr expr
Tim Steenvoorden's avatar
Tim Steenvoorden committed
322
evalExpr (Snd expr) = snd
323
where
Tim Steenvoorden's avatar
Tim Steenvoorden committed
324
  (VTuple _ snd) = evalExpr expr
Tim Steenvoorden's avatar
Tim Steenvoorden committed
325
evalExpr (Eq expr1 expr2) = VBool $ evalExpr expr1 === evalExpr expr2