cleanup
[minfp.git] / int.icl
1 implementation module int
2
3 import StdEnv
4 import Data.Either
5 import Data.Functor
6 import Data.Maybe
7 import Data.List
8 import Control.Applicative
9 import Control.Monad
10 import Control.Monad.State
11 import Control.Monad.Trans
12
13 import ast
14
15 :: Eval a :== StateT EvalState (Either [String]) a
16 :: EvalState :== [([Char], Value)]
17
18 int :: Expression -> Either [String] Value
19 int e = evalStateT (eval e) preamble
20
21 preamble =
22 [(['_if'], Func \i->pure (Func \t->pure (Func \e->eval i >>= \(Bool b)->if b (eval t) (eval e))))
23 ,(['_eq'], binop \(Int i) (Int j)->Bool (i==j))
24 ,(['_sub'], binop \(Int i) (Int j)->Int (i-j))
25 ,(['_add'], binop \(Int i) (Int j)->Int (i+j))
26 ,(['_mul'], binop \(Int i) (Int j)->Int (i*j))
27 ,(['_div'], binop \(Int i) (Int j)->Int (i/j))
28 ]
29 where
30 binop op = Func \l->pure (Func \r->op <$> eval l <*> eval r)
31
32 sub :: [Char] Expression Expression -> Expression
33 sub ident subst (Let v b rest) = Let v (sub ident subst b) (if (v == ident) rest (sub ident subst rest))
34 sub ident subst (Var v)
35 | ident == v = subst
36 sub ident subst (App e1 e2) = App (sub ident subst e1) (sub ident subst e2)
37 sub ident subst (Lambda v b)
38 | ident <> v = Lambda v (sub ident b subst)
39 sub _ _ x = x
40
41 eval :: Expression -> Eval Value
42 eval (Let ident body rest) = eval body >>= \v->modify (\vs->[(ident, v):vs]) >>| eval rest
43 eval (Lit v) = pure v
44 eval (Var v) = gets (lookup v) >>= maybe (liftT (Left [toString v +++ " not found"])) pure
45 eval (App e1 e2) = eval e1 >>= \(Func v)->v e2
46 eval (Lambda a b) = pure (Func \arg->eval (sub a arg b))