{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TupleSections #-}
module Text.EDE.Internal.AST where
import qualified Control.Comonad as Comonad
import Control.Comonad.Cofree (Cofree ((:<)))
import Data.Aeson.Types (Value (..))
import qualified Data.Foldable as Foldable
import Data.List.NonEmpty (NonEmpty (..))
import qualified Data.Maybe as Maybe
import Text.EDE.Internal.Types
newtype Fix f = Fix (f (Fix f))
cofreeFix :: Functor f => a -> Fix f -> Cofree f a
cofreeFix :: forall (f :: * -> *) a. Functor f => a -> Fix f -> Cofree f a
cofreeFix a
x = Fix f -> Cofree f a
forall {f :: * -> *}. Functor f => Fix f -> Cofree f a
go
where
go :: Fix f -> Cofree f a
go (Fix f (Fix f)
f) = a
x a -> f (Cofree f a) -> Cofree f a
forall (f :: * -> *) a. a -> f (Cofree f a) -> Cofree f a
:< (Fix f -> Cofree f a) -> f (Fix f) -> f (Cofree f a)
forall a b. (a -> b) -> f a -> f b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Fix f -> Cofree f a
go f (Fix f)
f
{-# INLINEABLE cofreeFix #-}
var :: Id -> Var
var :: Text -> Var
var = NonEmpty Text -> Var
Var (NonEmpty Text -> Var) -> (Text -> NonEmpty Text) -> Text -> Var
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text -> [Text] -> NonEmpty Text
forall a. a -> [a] -> NonEmpty a
:| [])
{-# INLINEABLE var #-}
eapp :: a -> [Exp a] -> Exp a
eapp :: forall a. a -> [Exp a] -> Exp a
eapp a
x [] = a -> Fix ExpF -> Exp a
forall (f :: * -> *) a. Functor f => a -> Fix f -> Cofree f a
cofreeFix a
x Fix ExpF
blank
eapp a
_ [Exp a
e] = Exp a
e
eapp a
_ (Exp a
e : [Exp a]
es) = (Exp a -> Exp a -> Exp a) -> Exp a -> [Exp a] -> Exp a
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
Foldable.foldl' (\Exp a
x Exp a
y -> Exp a -> a
forall a. Cofree ExpF a -> a
forall (w :: * -> *) a. Comonad w => w a -> a
Comonad.extract Exp a
x a -> ExpF (Exp a) -> Exp a
forall (f :: * -> *) a. a -> f (Cofree f a) -> Cofree f a
:< Exp a -> Exp a -> ExpF (Exp a)
forall a. a -> a -> ExpF a
EApp Exp a
x Exp a
y) Exp a
e [Exp a]
es
{-# INLINEABLE eapp #-}
efun :: Id -> Exp a -> Exp a
efun :: forall a. Text -> Exp a -> Exp a
efun Text
i Exp a
e = let x :: a
x = Exp a -> a
forall a. Cofree ExpF a -> a
forall (w :: * -> *) a. Comonad w => w a -> a
Comonad.extract Exp a
e in a
x a -> ExpF (Exp a) -> Exp a
forall (f :: * -> *) a. a -> f (Cofree f a) -> Cofree f a
:< Exp a -> Exp a -> ExpF (Exp a)
forall a. a -> a -> ExpF a
EApp (a
x a -> ExpF (Exp a) -> Exp a
forall (f :: * -> *) a. a -> f (Cofree f a) -> Cofree f a
:< Text -> ExpF (Exp a)
forall a. Text -> ExpF a
EFun Text
i) Exp a
e
{-# INLINEABLE efun #-}
efilter :: Exp a -> (Id, [Exp a]) -> Exp a
efilter :: forall a. Exp a -> (Text, [Exp a]) -> Exp a
efilter Exp a
e (Text
i, [Exp a]
ps) = let x :: a
x = Exp a -> a
forall a. Cofree ExpF a -> a
forall (w :: * -> *) a. Comonad w => w a -> a
Comonad.extract Exp a
e in a -> [Exp a] -> Exp a
forall a. a -> [Exp a] -> Exp a
eapp a
x ((a
x a -> ExpF (Exp a) -> Exp a
forall (f :: * -> *) a. a -> f (Cofree f a) -> Cofree f a
:< Text -> ExpF (Exp a)
forall a. Text -> ExpF a
EFun Text
i) Exp a -> [Exp a] -> [Exp a]
forall a. a -> [a] -> [a]
: Exp a
e Exp a -> [Exp a] -> [Exp a]
forall a. a -> [a] -> [a]
: [Exp a]
ps)
{-# INLINEABLE efilter #-}
elet :: Maybe (Id, Exp a) -> Exp a -> Exp a
elet :: forall a. Maybe (Text, Exp a) -> Exp a -> Exp a
elet Maybe (Text, Exp a)
m Exp a
e = Exp a -> ((Text, Exp a) -> Exp a) -> Maybe (Text, Exp a) -> Exp a
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Exp a
e (\(Text
i, Exp a
b) -> Exp a -> a
forall a. Cofree ExpF a -> a
forall (w :: * -> *) a. Comonad w => w a -> a
Comonad.extract Exp a
b a -> ExpF (Exp a) -> Exp a
forall (f :: * -> *) a. a -> f (Cofree f a) -> Cofree f a
:< Text -> Exp a -> Exp a -> ExpF (Exp a)
forall a. Text -> a -> a -> ExpF a
ELet Text
i Exp a
b Exp a
e) Maybe (Text, Exp a)
m
{-# INLINEABLE elet #-}
eset :: Id -> Exp a -> Exp a -> Exp a
eset :: forall a. Text -> Exp a -> Exp a -> Exp a
eset Text
i Exp a
e Exp a
k =
Maybe (Text, Exp a) -> Exp a -> Exp a
forall a. Maybe (Text, Exp a) -> Exp a -> Exp a
elet ((Text, Exp a) -> Maybe (Text, Exp a)
forall a. a -> Maybe a
Just (Text
i, Exp a
e)) Exp a
k
{-# INLINEABLE eset #-}
eblock :: Id -> Exp a -> Exp a
eblock :: forall a. Text -> Exp a -> Exp a
eblock Text
i Exp a
e =
Exp a -> a
forall a. Cofree ExpF a -> a
forall (w :: * -> *) a. Comonad w => w a -> a
Comonad.extract Exp a
e a -> ExpF (Exp a) -> Exp a
forall (f :: * -> *) a. a -> f (Cofree f a) -> Cofree f a
:< Text -> Exp a -> ExpF (Exp a)
forall a. Text -> a -> ExpF a
EBlock Text
i Exp a
e
{-# INLINEABLE eblock #-}
eOverrideBlock :: Id -> Exp a -> Exp a -> Exp a
eOverrideBlock :: forall a. Text -> Exp a -> Exp a -> Exp a
eOverrideBlock Text
i Exp a
b Exp a
e =
Exp a -> a
forall a. Cofree ExpF a -> a
forall (w :: * -> *) a. Comonad w => w a -> a
Comonad.extract Exp a
b a -> ExpF (Exp a) -> Exp a
forall (f :: * -> *) a. a -> f (Cofree f a) -> Cofree f a
:< Text -> Exp a -> Exp a -> ExpF (Exp a)
forall a. Text -> a -> a -> ExpF a
EOverrideBlock Text
i Exp a
b Exp a
e
{-# INLINEABLE eOverrideBlock #-}
ecase ::
Exp a ->
[Alt (Exp a)] ->
Maybe (Exp a) ->
Exp a
ecase :: forall a. Exp a -> [Alt (Exp a)] -> Maybe (Exp a) -> Exp a
ecase Exp a
p [Alt (Exp a)]
ws Maybe (Exp a)
f = Exp a -> a
forall a. Cofree ExpF a -> a
forall (w :: * -> *) a. Comonad w => w a -> a
Comonad.extract Exp a
p a -> ExpF (Exp a) -> Exp a
forall (f :: * -> *) a. a -> f (Cofree f a) -> Cofree f a
:< Exp a -> [Alt (Exp a)] -> ExpF (Exp a)
forall a. a -> [Alt a] -> ExpF a
ECase Exp a
p ([Alt (Exp a)]
ws [Alt (Exp a)] -> [Alt (Exp a)] -> [Alt (Exp a)]
forall a. [a] -> [a] -> [a]
++ [Alt (Exp a)]
-> (Exp a -> [Alt (Exp a)]) -> Maybe (Exp a) -> [Alt (Exp a)]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] ((Alt (Exp a) -> [Alt (Exp a)] -> [Alt (Exp a)]
forall a. a -> [a] -> [a]
: []) (Alt (Exp a) -> [Alt (Exp a)])
-> (Exp a -> Alt (Exp a)) -> Exp a -> [Alt (Exp a)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Exp a -> Alt (Exp a)
forall a. Exp a -> Alt (Exp a)
wild) Maybe (Exp a)
f)
{-# INLINEABLE ecase #-}
eif ::
(Exp a, Exp a) ->
[(Exp a, Exp a)] ->
Maybe (Exp a) ->
Exp a
eif :: forall a.
(Exp a, Exp a) -> [(Exp a, Exp a)] -> Maybe (Exp a) -> Exp a
eif (Exp a, Exp a)
t [(Exp a, Exp a)]
ts Maybe (Exp a)
f =
((Exp a, Exp a) -> Exp a -> Exp a)
-> Exp a -> [(Exp a, Exp a)] -> Exp a
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
Foldable.foldr'
(Exp a, Exp a) -> Exp a -> Exp a
forall {a}.
(Cofree ExpF a, Cofree ExpF a) -> Cofree ExpF a -> Cofree ExpF a
c
(Exp a -> Maybe (Exp a) -> Exp a
forall a. a -> Maybe a -> a
Maybe.fromMaybe (Exp a -> a
forall a. Cofree ExpF a -> a
forall (w :: * -> *) a. Comonad w => w a -> a
Comonad.extract ((Exp a, Exp a) -> Exp a
forall a b. (a, b) -> a
fst (Exp a, Exp a)
t) a -> Fix ExpF -> Exp a
forall (f :: * -> *) a. Functor f => a -> Fix f -> Cofree f a
`cofreeFix` Fix ExpF
blank) Maybe (Exp a)
f)
((Exp a, Exp a)
t (Exp a, Exp a) -> [(Exp a, Exp a)] -> [(Exp a, Exp a)]
forall a. a -> [a] -> [a]
: [(Exp a, Exp a)]
ts)
where
c :: (Cofree ExpF a, Cofree ExpF a) -> Cofree ExpF a -> Cofree ExpF a
c (Cofree ExpF a
p, Cofree ExpF a
w) Cofree ExpF a
e = Cofree ExpF a -> a
forall a. Cofree ExpF a -> a
forall (w :: * -> *) a. Comonad w => w a -> a
Comonad.extract Cofree ExpF a
p a -> ExpF (Cofree ExpF a) -> Cofree ExpF a
forall (f :: * -> *) a. a -> f (Cofree f a) -> Cofree f a
:< Cofree ExpF a -> [Alt (Cofree ExpF a)] -> ExpF (Cofree ExpF a)
forall a. a -> [Alt a] -> ExpF a
ECase Cofree ExpF a
p [Cofree ExpF a -> Alt (Cofree ExpF a)
forall a. Exp a -> Alt (Exp a)
true Cofree ExpF a
w, Cofree ExpF a -> Alt (Cofree ExpF a)
forall a. Exp a -> Alt (Exp a)
false Cofree ExpF a
e]
{-# INLINEABLE eif #-}
eempty :: Exp a -> Exp a -> Maybe (Exp a) -> Exp a
eempty :: forall a. Exp a -> Exp a -> Maybe (Exp a) -> Exp a
eempty Exp a
v Exp a
e = Exp a -> (Exp a -> Exp a) -> Maybe (Exp a) -> Exp a
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Exp a
e ((Exp a, Exp a) -> [(Exp a, Exp a)] -> Maybe (Exp a) -> Exp a
forall a.
(Exp a, Exp a) -> [(Exp a, Exp a)] -> Maybe (Exp a) -> Exp a
eif (Text -> Exp a -> Exp a
forall a. Text -> Exp a -> Exp a
efun Text
"!" (Text -> Exp a -> Exp a
forall a. Text -> Exp a -> Exp a
efun Text
"empty" Exp a
v), Exp a
e) [] (Maybe (Exp a) -> Exp a)
-> (Exp a -> Maybe (Exp a)) -> Exp a -> Exp a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Exp a -> Maybe (Exp a)
forall a. a -> Maybe a
Just)
{-# INLINEABLE eempty #-}
true, false, wild :: Exp a -> Alt (Exp a)
true :: forall a. Exp a -> Alt (Exp a)
true = (Value -> Pat
PLit (Bool -> Value
Bool Bool
True),)
false :: forall a. Exp a -> Alt (Exp a)
false = (Value -> Pat
PLit (Bool -> Value
Bool Bool
False),)
wild :: forall a. Exp a -> Alt (Exp a)
wild = (Pat
PWild,)
{-# INLINEABLE true #-}
{-# INLINEABLE false #-}
{-# INLINEABLE wild #-}
blank :: Fix ExpF
blank :: Fix ExpF
blank = ExpF (Fix ExpF) -> Fix ExpF
forall (f :: * -> *). f (Fix f) -> Fix f
Fix (Value -> ExpF (Fix ExpF)
forall a. Value -> ExpF a
ELit (Text -> Value
String Text
forall a. Monoid a => a
mempty))
{-# INLINEABLE blank #-}