> {-# OPTIONS_GHC -XFlexibleInstances #-} > module Epic.Evaluator(eval) where > import Epic.Language > import Debug.Trace Assume all expressions are in HOAS form - if we see any Vs, or any Updates then we have an error. Returns expression in standard form. > eval :: [EvalDecl] -> Expr -> Expr > eval ctx e = case ev e of > Nothing -> quote 0 e > Just e' -> quote 0 e' > where > ev (R n) = case lookupD n ctx of > Just e' -> ev e' > Nothing -> return $ R n > ev (V i) = return $ V i > ev (App f xs) = do f' <- ev f > xs' <- mapM ev xs > evFn f' xs' > ev (Lazy e) = ev e > ev (Par e) = ev e > ev (Effect e) = ev e > ev (Con t es) = do es' <- mapM ev es > return $ Con t es' > ev (Proj e i) = do e' <- ev e > return $ project e' i > ev (Case e alts) = do e' <- ev e > docase e' alts > ev (If x t e) = do x' <- ev x > case x of > Const (MkInt 0) -> ev e > _ -> ev t > ev (While _ _) = fail "Can't evaluate while" > ev (WhileAcc _ _ _) = fail "Can't evaluate while" > ev (Op op x y) = do x' <- ev x > y' <- ev y > case (x', y') of > (Const xv, Const yv) -> return $ doOp op xv yv > _ -> return $ Op op x' y' > ev (Let _ _ _ _) = fail "Not in HOAS form (let)" > ev (LetM _ _ _) = fail "Can't do updates" > ev (HLet n ty val sc) = do val' <- ev val > ev (sc val') > ev (HLam n ty sc) = do let sc' = \x -> case ev (sc x) of > Nothing -> sc x > Just v -> v > return $ HLam n ty sc' > ev (WithMem a t e) = ev e > ev (ForeignCall t str args) > = do args' <- mapM ev (map fst args) > return $ ForeignCall t str (zip args' (map snd args)) > ev (LazyForeignCall t str args) > = do args' <- mapM ev (map fst args) > return $ LazyForeignCall t str (zip args' (map snd args)) > ev x = return x > evFn (HLam n t sc) (a:as) = do a' <- ev (sc a) > evFn a' as > evFn f [] = ev f > evFn f as = return $ App f as > docase c@(Con t as) alts = case fConAlt t as alts of > Just rhs -> ev rhs > Nothing -> return $ Case c alts > docase c@(Const (MkInt i)) alts > = case fConstAlt i alts of > Just rhs -> ev rhs > Nothing -> return $ Case c alts > docase c alts = return $ Case c alts > fConAlt :: Int -> [Expr] -> [CaseAlt] -> Maybe Expr > fConAlt t args (HAlt t' n rhs : _) > | t == t' && n == length args = > substRHS args rhs > where > substRHS [] (HExp rhs) = return rhs > substRHS (x:xs) (HBind n ty rhsf) = substRHS xs (rhsf x) > fConAlt t args (DefaultCase e : _) = return e > fConAlt t args (_:xs) = fConAlt t args xs > fConAlt t args _ = Nothing > fConstAlt :: Int -> [CaseAlt] -> Maybe Expr > fConstAlt t (ConstAlt t' rhs:_) > | t == t' = return rhs > fConstAlt t (DefaultCase e : _) = return e > fConstAlt t (_:xs) = fConstAlt t xs > fConstAlt t _ = Nothing > doOp Plus (MkInt x) (MkInt y) = Const $ MkInt (x+y) > doOp Minus (MkInt x) (MkInt y) = Const $ MkInt (x-y) > doOp Times (MkInt x) (MkInt y) = Const $ MkInt (x*y) > doOp Divide (MkInt x) (MkInt y) = Const $ MkInt (x `div` y) > doOp Modulo (MkInt x) (MkInt y) = Const $ MkInt (x `mod` y) > doOp OpEQ (MkInt x) (MkInt y) = bint (x==y) > doOp OpLT (MkInt x) (MkInt y) = bint (x doOp OpLE (MkInt x) (MkInt y) = bint (x<=y) > doOp OpGT (MkInt x) (MkInt y) = bint (x>y) > doOp OpGE (MkInt x) (MkInt y) = bint (x>=y) > doOp FPlus (MkFloat x) (MkFloat y) = Const $ MkFloat (x+y) > doOp FMinus (MkFloat x) (MkFloat y) = Const $ MkFloat (x-y) > doOp FTimes (MkFloat x) (MkFloat y) = Const $ MkFloat (x*y) > doOp FDivide (MkFloat x) (MkFloat y) = Const $ MkFloat (x/y) > doOp OpFEQ (MkFloat x) (MkFloat y) = bint (x==y) > doOp OpFLT (MkFloat x) (MkFloat y) = bint (x doOp OpFLE (MkFloat x) (MkFloat y) = bint (x<=y) > doOp OpFGT (MkFloat x) (MkFloat y) = bint (x>y) > doOp OpFGE (MkFloat x) (MkFloat y) = bint (x>=y) > doOp op x y = Op op (Const x) (Const y) > bint True = Const $ MkInt 1 > bint False = Const $ MkInt 0 > project :: Expr -> Int -> Expr > project (Con t as) i | i < length as = as!!i > project e i = Proj e i > lookupD n [] = Nothing > lookupD n (EDecl en def:xs) | n == en = Just def > lookupD n (_:xs) = lookupD n xs > class Quote a where > quote :: Int -> a -> a > instance Quote a => Quote [a] where > quote l = map (quote l) > instance Quote a => Quote (a, Type) where > quote l (x,t) = (quote l x, t) > instance Quote Expr where > quote v (App x xs) = App (quote v x) (quote v xs) > quote v (Lazy x) = Lazy (quote v x) > quote v (Par x) = Par (quote v x) > quote v (Effect x) = Effect (quote v x) > quote v (Con t xs) = Con t (quote v xs) > quote v (Proj x i) = Proj (quote v x) i > quote v (Case e as) = Case (quote v e) (quote v as) > quote v (If x y z) = If (quote v x) (quote v y) (quote v z) > quote v (While x y) = While (quote v x) (quote v y) > quote v (WhileAcc x y z) = WhileAcc (quote v x) (quote v y) (quote v z) > quote v (Op o x y) = Op o (quote v x) (quote v y) > quote v (HLam n ty fn) = Lam n ty (quote (v+1) (fn (V v))) > quote v (WithMem a x y) = WithMem a (quote v x) (quote v y) > quote v (ForeignCall t s xs) = ForeignCall t s (quote v xs) > quote v (LazyForeignCall t s xs) = LazyForeignCall t s (quote v xs) > quote v x = x > instance Quote CaseAlt where > quote v (HAlt t n rhs) = buildRHS v t [] rhs where > buildRHS v t acc (HExp e) = Alt t (reverse acc) (quote v e) > buildRHS v t acc (HBind n ty rhs) > = buildRHS (v+1) t ((n,ty):acc) (rhs (V v)) > quote v (ConstAlt c e) = ConstAlt c (quote v e) > quote v (DefaultCase e) = DefaultCase (quote v e)