{-# LANGUAGE DerivingVia #-}
module IR.DConToFunc (
dConToFunc,
) where
import qualified Common.Compiler as Compiler
import Common.Compiler (MonadError)
import Common.Identifiers (
fromId,
fromString,
ident,
)
import Control.Monad.Reader (
MonadReader,
ReaderT (..),
asks,
)
import Data.Bifunctor (Bifunctor (..))
import Data.Generics.Aliases (mkM)
import Data.Generics.Schemes (everywhereM)
import Data.List (inits)
import qualified Data.Map as M
import Data.Maybe (mapMaybe)
import qualified IR.IR as I
import qualified IR.Types as I
type ArityEnv = M.Map I.DConId Int
newtype ArityFn a = ArityFn (ReaderT ArityEnv Compiler.Pass a)
deriving (a -> ArityFn b -> ArityFn a
(a -> b) -> ArityFn a -> ArityFn b
(forall a b. (a -> b) -> ArityFn a -> ArityFn b)
-> (forall a b. a -> ArityFn b -> ArityFn a) -> Functor ArityFn
forall a b. a -> ArityFn b -> ArityFn a
forall a b. (a -> b) -> ArityFn a -> ArityFn b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> ArityFn b -> ArityFn a
$c<$ :: forall a b. a -> ArityFn b -> ArityFn a
fmap :: (a -> b) -> ArityFn a -> ArityFn b
$cfmap :: forall a b. (a -> b) -> ArityFn a -> ArityFn b
Functor) via (ReaderT ArityEnv Compiler.Pass)
deriving (Functor ArityFn
a -> ArityFn a
Functor ArityFn
-> (forall a. a -> ArityFn a)
-> (forall a b. ArityFn (a -> b) -> ArityFn a -> ArityFn b)
-> (forall a b c.
(a -> b -> c) -> ArityFn a -> ArityFn b -> ArityFn c)
-> (forall a b. ArityFn a -> ArityFn b -> ArityFn b)
-> (forall a b. ArityFn a -> ArityFn b -> ArityFn a)
-> Applicative ArityFn
ArityFn a -> ArityFn b -> ArityFn b
ArityFn a -> ArityFn b -> ArityFn a
ArityFn (a -> b) -> ArityFn a -> ArityFn b
(a -> b -> c) -> ArityFn a -> ArityFn b -> ArityFn c
forall a. a -> ArityFn a
forall a b. ArityFn a -> ArityFn b -> ArityFn a
forall a b. ArityFn a -> ArityFn b -> ArityFn b
forall a b. ArityFn (a -> b) -> ArityFn a -> ArityFn b
forall a b c. (a -> b -> c) -> ArityFn a -> ArityFn b -> ArityFn c
forall (f :: * -> *).
Functor f
-> (forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
<* :: ArityFn a -> ArityFn b -> ArityFn a
$c<* :: forall a b. ArityFn a -> ArityFn b -> ArityFn a
*> :: ArityFn a -> ArityFn b -> ArityFn b
$c*> :: forall a b. ArityFn a -> ArityFn b -> ArityFn b
liftA2 :: (a -> b -> c) -> ArityFn a -> ArityFn b -> ArityFn c
$cliftA2 :: forall a b c. (a -> b -> c) -> ArityFn a -> ArityFn b -> ArityFn c
<*> :: ArityFn (a -> b) -> ArityFn a -> ArityFn b
$c<*> :: forall a b. ArityFn (a -> b) -> ArityFn a -> ArityFn b
pure :: a -> ArityFn a
$cpure :: forall a. a -> ArityFn a
$cp1Applicative :: Functor ArityFn
Applicative) via (ReaderT ArityEnv Compiler.Pass)
deriving (Applicative ArityFn
a -> ArityFn a
Applicative ArityFn
-> (forall a b. ArityFn a -> (a -> ArityFn b) -> ArityFn b)
-> (forall a b. ArityFn a -> ArityFn b -> ArityFn b)
-> (forall a. a -> ArityFn a)
-> Monad ArityFn
ArityFn a -> (a -> ArityFn b) -> ArityFn b
ArityFn a -> ArityFn b -> ArityFn b
forall a. a -> ArityFn a
forall a b. ArityFn a -> ArityFn b -> ArityFn b
forall a b. ArityFn a -> (a -> ArityFn b) -> ArityFn b
forall (m :: * -> *).
Applicative m
-> (forall a b. m a -> (a -> m b) -> m b)
-> (forall a b. m a -> m b -> m b)
-> (forall a. a -> m a)
-> Monad m
return :: a -> ArityFn a
$creturn :: forall a. a -> ArityFn a
>> :: ArityFn a -> ArityFn b -> ArityFn b
$c>> :: forall a b. ArityFn a -> ArityFn b -> ArityFn b
>>= :: ArityFn a -> (a -> ArityFn b) -> ArityFn b
$c>>= :: forall a b. ArityFn a -> (a -> ArityFn b) -> ArityFn b
$cp1Monad :: Applicative ArityFn
Monad) via (ReaderT ArityEnv Compiler.Pass)
deriving (Monad ArityFn
Monad ArityFn
-> (forall a. String -> ArityFn a) -> MonadFail ArityFn
String -> ArityFn a
forall a. String -> ArityFn a
forall (m :: * -> *).
Monad m -> (forall a. String -> m a) -> MonadFail m
fail :: String -> ArityFn a
$cfail :: forall a. String -> ArityFn a
$cp1MonadFail :: Monad ArityFn
MonadFail) via (ReaderT ArityEnv Compiler.Pass)
deriving (MonadError Compiler.Error) via (ReaderT ArityEnv Compiler.Pass)
deriving (MonadReader ArityEnv) via (ReaderT ArityEnv Compiler.Pass)
runArityFn :: [(I.TConId, I.TypeDef)] -> ArityFn a -> Compiler.Pass a
runArityFn :: [(TConId, TypeDef)] -> ArityFn a -> Pass a
runArityFn [(TConId, TypeDef)]
tds (ArityFn ReaderT ArityEnv Pass a
m) = ReaderT ArityEnv Pass a -> ArityEnv -> Pass a
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT ReaderT ArityEnv Pass a
m (ArityEnv -> Pass a) -> ArityEnv -> Pass a
forall a b. (a -> b) -> a -> b
$ [(DConId, Int)] -> ArityEnv
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList [(DConId, Int)]
env
where
env :: [(DConId, Int)]
env = ((TConId, TypeDef) -> [(DConId, Int)])
-> [(TConId, TypeDef)] -> [(DConId, Int)]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (((DConId, TypeVariant) -> (DConId, Int))
-> [(DConId, TypeVariant)] -> [(DConId, Int)]
forall a b. (a -> b) -> [a] -> [b]
map ((TypeVariant -> Int) -> (DConId, TypeVariant) -> (DConId, Int)
forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second TypeVariant -> Int
I.variantFields) ([(DConId, TypeVariant)] -> [(DConId, Int)])
-> ((TConId, TypeDef) -> [(DConId, TypeVariant)])
-> (TConId, TypeDef)
-> [(DConId, Int)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TypeDef -> [(DConId, TypeVariant)]
I.variants (TypeDef -> [(DConId, TypeVariant)])
-> ((TConId, TypeDef) -> TypeDef)
-> (TConId, TypeDef)
-> [(DConId, TypeVariant)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (TConId, TypeDef) -> TypeDef
forall a b. (a, b) -> b
snd) [(TConId, TypeDef)]
tds
dConToFunc :: I.Program I.Type -> Compiler.Pass (I.Program I.Type)
dConToFunc :: Program Type -> Pass (Program Type)
dConToFunc p :: Program Type
p@I.Program{programDefs :: forall t. Program t -> [(Binder t, Expr t)]
I.programDefs = [(Binder Type, Expr Type)]
defs, typeDefs :: forall t. Program t -> [(TConId, TypeDef)]
I.typeDefs = [(TConId, TypeDef)]
tDefs} =
[(TConId, TypeDef)]
-> ArityFn (Program Type) -> Pass (Program Type)
forall a. [(TConId, TypeDef)] -> ArityFn a -> Pass a
runArityFn [(TConId, TypeDef)]
tDefs (ArityFn (Program Type) -> Pass (Program Type))
-> ArityFn (Program Type) -> Pass (Program Type)
forall a b. (a -> b) -> a -> b
$ do
[(Binder Type, Expr Type)]
defs'' <- ArityFn [(Binder Type, Expr Type)]
defs'
Program Type -> ArityFn (Program Type)
forall (m :: * -> *) a. Monad m => a -> m a
return Program Type
p{programDefs :: [(Binder Type, Expr Type)]
I.programDefs = [(Binder Type, Expr Type)]
tDefs' [(Binder Type, Expr Type)]
-> [(Binder Type, Expr Type)] -> [(Binder Type, Expr Type)]
forall a. [a] -> [a] -> [a]
++ [(Binder Type, Expr Type)]
defs''}
where
tDefs' :: [(Binder Type, Expr Type)]
tDefs' = [[(Binder Type, Expr Type)]] -> [(Binder Type, Expr Type)]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ((TConId, TypeDef) -> [(Binder Type, Expr Type)]
createFuncs ((TConId, TypeDef) -> [(Binder Type, Expr Type)])
-> [(TConId, TypeDef)] -> [[(Binder Type, Expr Type)]]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [(TConId, TypeDef)]
tDefs)
defs' :: ArityFn [(Binder Type, Expr Type)]
defs' =
((Binder Type, Expr Type) -> Bool)
-> [(Binder Type, Expr Type)] -> [(Binder Type, Expr Type)]
forall a. (a -> Bool) -> [a] -> [a]
filter ((Binder Type -> [Binder Type] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` ((Binder Type, Expr Type) -> Binder Type
forall a b. (a, b) -> a
fst ((Binder Type, Expr Type) -> Binder Type)
-> [(Binder Type, Expr Type)] -> [Binder Type]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [(Binder Type, Expr Type)]
tDefs')) (Binder Type -> Bool)
-> ((Binder Type, Expr Type) -> Binder Type)
-> (Binder Type, Expr Type)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Binder Type, Expr Type) -> Binder Type
forall a b. (a, b) -> a
fst)
([(Binder Type, Expr Type)] -> [(Binder Type, Expr Type)])
-> ArityFn [(Binder Type, Expr Type)]
-> ArityFn [(Binder Type, Expr Type)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> GenericM ArityFn
-> [(Binder Type, Expr Type)] -> ArityFn [(Binder Type, Expr Type)]
forall (m :: * -> *). Monad m => GenericM m -> GenericM m
everywhereM ((Expr Type -> ArityFn (Expr Type)) -> a -> ArityFn a
forall (m :: * -> *) a b.
(Monad m, Typeable a, Typeable b) =>
(b -> m b) -> a -> m a
mkM Expr Type -> ArityFn (Expr Type)
dataToApp) [(Binder Type, Expr Type)]
defs
createFuncs :: (TConId, TypeDef) -> [(Binder Type, Expr Type)]
createFuncs (TConId
tconid, I.TypeDef{variants :: TypeDef -> [(DConId, TypeVariant)]
I.variants = [(DConId, TypeVariant)]
vars}) =
TConId -> (DConId, TypeVariant) -> Maybe (Binder Type, Expr Type)
createFunc TConId
tconid ((DConId, TypeVariant) -> Maybe (Binder Type, Expr Type))
-> [(DConId, TypeVariant)] -> [(Binder Type, Expr Type)]
forall a b. (a -> Maybe b) -> [a] -> [b]
`mapMaybe` [(DConId, TypeVariant)]
vars
dataToApp :: I.Expr I.Type -> ArityFn (I.Expr I.Type)
dataToApp :: Expr Type -> ArityFn (Expr Type)
dataToApp a :: Expr Type
a@(I.Data DConId
dconid Type
t) = do
Just Int
arity <- (ArityEnv -> Maybe Int) -> ArityFn (Maybe Int)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (DConId -> ArityEnv -> Maybe Int
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup DConId
dconid)
case Int
arity of
Int
0 -> Expr Type -> ArityFn (Expr Type)
forall (m :: * -> *) a. Monad m => a -> m a
return Expr Type
a
Int
_ -> Expr Type -> ArityFn (Expr Type)
forall (m :: * -> *) a. Monad m => a -> m a
return (Expr Type -> ArityFn (Expr Type))
-> Expr Type -> ArityFn (Expr Type)
forall a b. (a -> b) -> a -> b
$ VarId -> Type -> Expr Type
forall t. VarId -> t -> Expr t
I.Var (DConId -> VarId
nameFunc DConId
dconid) Type
t
dataToApp Expr Type
a = Expr Type -> ArityFn (Expr Type)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Expr Type
a
createFunc
:: I.TConId -> (I.DConId, I.TypeVariant) -> Maybe (I.Binder I.Type, I.Expr I.Type)
createFunc :: TConId -> (DConId, TypeVariant) -> Maybe (Binder Type, Expr Type)
createFunc TConId
_ (DConId
_, I.VariantNamed []) = Maybe (Binder Type, Expr Type)
forall a. Maybe a
Nothing
createFunc TConId
tcon (DConId
dconid, I.VariantNamed [(VarId, Type)]
params) = (Binder Type, Expr Type) -> Maybe (Binder Type, Expr Type)
forall a. a -> Maybe a
Just (VarId -> Type -> Binder Type
forall t. VarId -> t -> Binder t
I.BindVar VarId
func_name (Type -> Binder Type) -> Type -> Binder Type
forall a b. (a -> b) -> a -> b
$ Expr Type -> Type
forall (c :: * -> *) a. Carrier c => c a -> a
I.extract Expr Type
lambda, Expr Type
lambda)
where
func_name :: VarId
func_name = DConId -> VarId
nameFunc DConId
dconid
lambda :: Expr Type
lambda = [Binder Type] -> Expr Type -> Expr Type
I.foldLambda ((VarId -> Type -> Binder Type) -> (VarId, Type) -> Binder Type
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry VarId -> Type -> Binder Type
forall t. VarId -> t -> Binder t
I.BindVar ((VarId, Type) -> Binder Type) -> [(VarId, Type)] -> [Binder Type]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [(VarId, Type)]
params) Expr Type
body
body :: Expr Type
body = Expr Type -> [(Expr Type, Type)] -> Expr Type
forall t. Expr t -> [(Expr t, t)] -> Expr t
I.foldApp Expr Type
dcon [(Expr Type, Type)]
args
dcon :: Expr Type
dcon = DConId -> Type -> Expr Type
forall t. DConId -> t -> Expr t
I.Data (DConId -> DConId
forall a b. (Identifiable a, Identifiable b) => a -> b
fromId DConId
dconid) Type
t
args :: [(Expr Type, Type)]
args = [Expr Type] -> [Type] -> [(Expr Type, Type)]
forall a b. [a] -> [b] -> [(a, b)]
zip ((VarId -> Type -> Expr Type) -> (VarId, Type) -> Expr Type
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry VarId -> Type -> Expr Type
forall t. VarId -> t -> Expr t
I.Var ((VarId, Type) -> Expr Type) -> [(VarId, Type)] -> [Expr Type]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [(VarId, Type)]
params) [Type]
ts
tconTyp :: Type
tconTyp = TConId -> [Type] -> Type
I.TCon TConId
tcon []
(Type
t : [Type]
ts) =
[Type] -> [Type]
forall a. [a] -> [a]
reverse ([Type] -> [Type]) -> [Type] -> [Type]
forall a b. (a -> b) -> a -> b
$
(Type -> Type -> Type) -> [Type] -> Type
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldr1 Type -> Type -> Type
I.Arrow ([Type] -> Type) -> ([Type] -> [Type]) -> [Type] -> Type
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Type] -> [Type]
forall a. [a] -> [a]
reverse
([Type] -> Type) -> [[Type]] -> [Type]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [[Type]] -> [[Type]]
forall a. [a] -> [a]
tail
([Type] -> [[Type]]
forall a. [a] -> [[a]]
inits ([Type] -> [[Type]]) -> [Type] -> [[Type]]
forall a b. (a -> b) -> a -> b
$ [Type] -> [Type]
forall a. [a] -> [a]
reverse (((VarId, Type) -> Type
forall a b. (a, b) -> b
snd ((VarId, Type) -> Type) -> [(VarId, Type)] -> [Type]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [(VarId, Type)]
params) [Type] -> [Type] -> [Type]
forall a. [a] -> [a] -> [a]
++ [Type
tconTyp]))
createFunc TConId
tcon (DConId
dcon, I.VariantUnnamed [Type]
params) =
TConId -> (DConId, TypeVariant) -> Maybe (Binder Type, Expr Type)
createFunc
TConId
tcon
(DConId
dcon, [(VarId, Type)] -> TypeVariant
I.VariantNamed [(VarId, Type)]
argNames)
where
argNames :: [(VarId, Type)]
argNames = (Type -> Int -> (VarId, Type))
-> [Type] -> [Int] -> [(VarId, Type)]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (\Type
t Int
i -> (Int -> VarId
nameArg Int
i, Type
t)) [Type]
params [Int
0 ..]
nameFunc :: I.DConId -> I.VarId
nameFunc :: DConId -> VarId
nameFunc DConId
dconid = String -> VarId
forall a. IsString a => String -> a
fromString (String -> VarId) -> String -> VarId
forall a b. (a -> b) -> a -> b
$ String
"__" String -> String -> String
forall a. [a] -> [a] -> [a]
++ DConId -> String
forall i. Identifiable i => i -> String
ident DConId
dconid
nameArg :: Int -> I.VarId
nameArg :: Int -> VarId
nameArg Int
i = String -> VarId
forall a. IsString a => String -> a
fromString (String
"__arg" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
i)