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