ddc-core-0.4.2.1: DDC/Core/Exp/Generic/Compounds.hs
{-# LANGUAGE TypeFamilies #-}
-- | Utilities for constructing and destructing compound expressions.
--
-- For the generic version of the AST.
--
module DDC.Core.Exp.Generic.Compounds
( module DDC.Type.Compounds
-- * Abstractions
, makeXAbs, takeXAbs
, makeXLAMs, takeXLAMs
, makeXLams, takeXLams
-- * Applications
, makeXApps, takeXApps, splitXApps
, takeXConApps
, takeXPrimApps
-- * Data Constructors
, dcUnit
, takeNameOfDaCon
, takeTypeOfDaCon)
where
import DDC.Core.Exp.Generic.Exp
import DDC.Core.Exp.DaCon
import DDC.Type.Compounds
import Data.Maybe
-- Abstractions ---------------------------------------------------------------
-- | Make some nested abstractions.
makeXAbs :: [GAbs l] -> GExp l -> GExp l
makeXAbs as xx
= foldr XAbs xx as
-- | Split type and value/witness abstractions from the front of an expression,
-- or `Nothing` if there aren't any.
takeXAbs :: GExp l -> Maybe ([GAbs l], GExp l)
takeXAbs xx
= let go as (XAbs a x) = go (a : as) x
go as x = (reverse as, x)
in case go [] xx of
([], _) -> Nothing
(as, body) -> Just (as, body)
-- | Make some nested type lambdas.
makeXLAMs :: [GBind l] -> GExp l -> GExp l
makeXLAMs bs x
= foldr XLAM x bs
-- | Split type lambdas from the front of an expression,
-- or `Nothing` if there aren't any.
takeXLAMs :: GExp l -> Maybe ([GBind l], GExp l)
takeXLAMs xx
= let go bs (XLAM b x) = go (b : bs) x
go bs x = (reverse bs, x)
in case go [] xx of
([], _) -> Nothing
(bs, body) -> Just (bs, body)
-- | Make some nested value or witness lambdas.
makeXLams :: [GBind l] -> GExp l -> GExp l
makeXLams bs x
= foldr XLam x bs
-- | Split nested value or witness lambdas from the front of an expression,
-- or `Nothing` if there aren't any.
takeXLams :: GExp l -> Maybe ([GBind l], GExp l)
takeXLams xx
= let go bs (XLam b x) = go (b : bs) x
go bs x = (reverse bs, x)
in case go [] xx of
([], _) -> Nothing
(bs, body) -> Just (bs, body)
-- Applications ---------------------------------------------------------------
-- | Build sequence of applications.
makeXApps :: GExp l -> [GArg l] -> GExp l
makeXApps t1 ts
= foldl XApp t1 ts
-- | Flatten an application into the functional expression and its arguments,
-- or `Nothing if this is not an application.
takeXApps :: GExp l -> Maybe (GExp l, [GArg l])
takeXApps xx
= case xx of
XApp x1@XApp{} a2
-> case takeXApps x1 of
Just (f1, as1) -> Just (f1, as1 ++ [a2])
Nothing -> Nothing
XApp x1 a2
-> Just (x1, [a2])
_ -> Nothing
-- | Flatten an application into a functional expression and its arguments,
-- or just return the expression with no arguments if this is not
-- an application.
splitXApps :: GExp l -> (GExp l, [GArg l])
splitXApps xx
= fromMaybe (xx, []) $ takeXApps xx
-- | Flatten an application of a primitive operators into the operator itself
-- and its arguments, or `Nothing` if this is not an application of a
-- primitive.
takeXPrimApps :: GExp l -> Maybe (GPrim l, [GArg l])
takeXPrimApps xx
= case xx of
XApp (XPrim p) a2
-> Just (p, [a2])
XApp x1@XApp{} a2
-> case takeXPrimApps x1 of
Just (p, as1) -> Just (p, as1 ++ [a2])
_ -> Nothing
_ -> Nothing
-- | Flatten an application of a data constructor into the constructor itself
-- and its arguments, or `Nothing` if this is not an application of a
-- data constructor.
takeXConApps :: GExp l -> Maybe (DaCon l, [GArg l])
takeXConApps xx
= case xx of
XApp (XCon c) a2
-> Just (c, [a2])
XApp x1@XApp{} a2
-> case takeXConApps x1 of
Just (c, as1) -> Just (c, as1 ++ [a2])
_ -> Nothing
_ -> Nothing