1 {-# LANGUAGE FlexibleInstances #-}
2 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
3 {-# LANGUAGE MultiParamTypeClasses #-}
4 {-# LANGUAGE TypeFamilies #-}
5 -- | Interpreter to compute a host-term.
6 module Language.Symantic.Repr.Host where
8 import Control.Monad as Monad
9 import Control.Monad.IO.Class (MonadIO(..))
11 import qualified Data.Bool as Bool
12 import qualified Data.Maybe as Maybe
13 import qualified Data.Map.Strict as Map
15 import Language.Symantic.Lib.Control.Monad
16 import Language.Symantic.Expr
20 -- | Interpreter's data.
22 -- NOTE: the host-type @h@ is wrapped inside @lam@ to let 'Sym_Lambda'
23 -- control its callings (see 'inline', 'val', and 'lazy').
24 newtype Repr_Host lam h
26 { unRepr_Host :: lam h }
27 deriving (Applicative, Functor, Monad, MonadIO)
30 host_from_expr :: Repr_Host lam h -> lam h
31 host_from_expr = unRepr_Host
33 instance MonadIO lam => Sym_Lambda lam (Repr_Host lam) where
34 type Lambda_from_Repr (Repr_Host lam) = lam
35 app = liftM2Join $ \f a -> Repr_Host $ f $ return a
36 inline f = return $ unRepr_Host . f . Repr_Host
37 val f = return $ (>>= unRepr_Host . f . Repr_Host . return)
38 lazy f = return $ ((>>= unRepr_Host . f . Repr_Host) . lazy_share)
39 instance Monad lam => Sym_Bool (Repr_Host lam) where
41 not = Prelude.fmap Bool.not
42 (&&) = liftM2 (Prelude.&&)
43 (||) = liftM2 (Prelude.||)
44 instance Monad lam => Sym_Int (Repr_Host lam) where
46 abs = Prelude.fmap Prelude.abs
47 negate = Prelude.fmap Prelude.negate
48 (+) = liftM2 (Prelude.+)
49 (-) = liftM2 (Prelude.-)
50 (*) = liftM2 (Prelude.*)
51 mod = liftM2 Prelude.mod
52 instance Monad lam => Sym_Maybe (Repr_Host lam) where
53 nothing = return Nothing
54 just = liftMJoin $ return . Just
55 instance MonadIO lam => Sym_Maybe_Lam lam (Repr_Host lam) where
58 Maybe.maybe n (\a -> j `app` return a) mm
59 instance Monad lam => Sym_If (Repr_Host lam) where
63 instance Monad lam => Sym_When (Repr_Host lam) where
67 instance Monad lam => Sym_Eq (Repr_Host lam) where
68 (==) = liftM2 (Prelude.==)
69 instance Monad lam => Sym_Ord (Repr_Host lam) where
70 compare = liftM2 Prelude.compare
71 instance Monad lam => Sym_List (Repr_Host lam) where
72 list_empty = return []
73 list_cons = liftM2 (:)
75 instance MonadIO lam => Sym_List_Lam lam (Repr_Host lam) where
76 list_filter f = liftMJoin go
81 (if b then ((x :) <$>) else id)
83 instance Monad lam => Sym_Tuple2 (Repr_Host lam) where
85 instance Monad lam => Sym_Map (Repr_Host lam) where
86 map_from_list = Prelude.fmap Map.fromList
87 instance MonadIO lam => Sym_Map_Lam lam (Repr_Host lam) where
88 map_map f = liftMJoin $ sequence . ((\a -> f `app` return a) <$>)
89 instance MonadIO lam => Sym_Functor lam (Repr_Host lam) where
90 fmap f = liftMJoin $ sequence . ((\a -> f `app` return a) <$>)
92 -- | Helper to store arguments of 'lazy' into an 'IORef'.
93 lazy_share :: MonadIO m => m a -> m (m a)
95 r <- liftIO $ newIORef (False, m)
97 (already_evaluated, m') <- liftIO $ readIORef r
102 liftIO $ writeIORef r (True, return v)