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.List as List
14 import qualified Data.Ord as Ord
15 import qualified Data.Map.Strict as Map
16 import Prelude hiding (and, not, or, compare)
18 import Language.Symantic.Lib.Control.Monad
19 import Language.Symantic.Expr
23 -- | Interpreter's data.
25 -- NOTE: the host-type @h@ is wrapped inside @lam@ to let 'Sym_Lambda'
26 -- control its callings (see 'inline', 'val', and 'lazy').
27 newtype Repr_Host lam h
29 { unRepr_Host :: lam h }
30 deriving (Applicative, Functor, Monad, MonadIO)
33 host_from_expr :: Repr_Host lam h -> lam h
34 host_from_expr = unRepr_Host
36 instance MonadIO lam => Sym_Lambda lam (Repr_Host lam) where
37 type Lambda_from_Repr (Repr_Host lam) = lam
38 app = liftM2Join $ \f a -> Repr_Host $ f $ return a
39 inline f = return $ unRepr_Host . f . Repr_Host
40 val f = return $ (>>= unRepr_Host . f . Repr_Host . return)
41 lazy f = return $ ((>>= unRepr_Host . f . Repr_Host) . expr_lambda_lazy_share)
42 instance Monad lam => Sym_Bool (Repr_Host lam) where
47 instance Monad lam => Sym_Int (Repr_Host lam) where
51 instance Monad lam => Sym_Maybe (Repr_Host lam) where
52 nothing = return Nothing
53 just = liftMJoin $ return . Just
54 instance MonadIO lam => Sym_Maybe_Lam lam (Repr_Host lam) where
57 Maybe.maybe n (\a -> j `app` return a) mm
58 instance Monad lam => Sym_If (Repr_Host lam) where
62 instance Monad lam => Sym_When (Repr_Host lam) where
66 instance Monad lam => Sym_Eq (Repr_Host lam) where
68 instance Monad lam => Sym_Ord (Repr_Host lam) where
69 compare = liftM2 Ord.compare
70 instance Monad lam => Sym_List (Repr_Host lam) where
71 list_empty = return []
72 list_cons = liftM2 (:)
73 instance MonadIO lam => Sym_List_Lam lam (Repr_Host lam) where
74 list_filter f = liftMJoin go
79 (if b then ((x :) <$>) else id)
81 instance Monad lam => Sym_Tuple2 (Repr_Host lam) where
83 instance Monad lam => Sym_Map (Repr_Host lam) where
84 map_from_list = fmap Map.fromList
85 instance MonadIO lam => Sym_Map_Lam lam (Repr_Host lam) where
86 map_map f = liftMJoin $ sequence . ((\a -> f `app` return a) <$>)
88 -- | Helper to store arguments of 'lazy' into an 'IORef'.
89 expr_lambda_lazy_share :: MonadIO m => m a -> m (m a)
90 expr_lambda_lazy_share m = do
91 r <- liftIO $ newIORef (False, m)
93 (already_evaluated, m') <- liftIO $ readIORef r
98 liftIO $ writeIORef r (True, return v)