packages feed

ddc-core-simpl 0.3.1.1 → 0.3.2.1

raw patch · 29 files changed

+1627/−504 lines, 29 filesdep ~ddc-basedep ~ddc-corePVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: ddc-base, ddc-core

API changes (from Hackage documentation)

- DDC.Core.Simplifier: BetaLets :: Transform s a n
- DDC.Core.Simplifier: SnipOver :: Transform s a n
- DDC.Core.Transform.AnonymizeX: instance AnonymizeX LetMode
- DDC.Core.Transform.AnonymizeX: instance AnonymizeX Witness
- DDC.Core.Transform.Beta: BetaReduceInfo :: Int -> Int -> Int -> Int -> Int -> BetaReduceInfo
- DDC.Core.Transform.Beta: data BetaReduceInfo
- DDC.Core.Transform.Beta: instance Monoid BetaReduceInfo
- DDC.Core.Transform.Beta: instance Pretty BetaReduceInfo
- DDC.Core.Transform.Beta: instance Typeable BetaReduceInfo
- DDC.Core.Transform.Namify: instance Namify LetMode
- DDC.Core.Transform.Namify: instance Namify Witness
- DDC.Core.Transform.TransformX: class TransformUpMX m (c :: * -> * -> *)
- DDC.Core.Transform.TransformX: instance Monad m => TransformUpMX m Alt
- DDC.Core.Transform.TransformX: instance Monad m => TransformUpMX m Exp
- DDC.Core.Transform.TransformX: instance Monad m => TransformUpMX m Lets
- DDC.Core.Transform.TransformX: instance Monad m => TransformUpMX m Module
- DDC.Core.Transform.TransformX: transformUpMX :: (TransformUpMX m c, Ord n) => (KindEnv n -> TypeEnv n -> Exp a n -> m (Exp a n)) -> KindEnv n -> TypeEnv n -> c a n -> m (c a n)
- DDC.Core.Transform.TransformX: transformUpX :: (Ord n, TransformUpMX Identity c) => (KindEnv n -> TypeEnv n -> Exp a n -> Exp a n) -> KindEnv n -> TypeEnv n -> c a n -> c a n
- DDC.Core.Transform.TransformX: transformUpX' :: (Ord n, TransformUpMX Identity c) => (Exp a n -> Exp a n) -> c a n -> c a n
+ DDC.Core.Simplifier: Eta :: Config -> Transform s a n
+ DDC.Core.Simplifier.Result: TransformInfo :: i -> TransformInfo
+ DDC.Core.Simplifier.Result: TransformResult :: r -> Bool -> Bool -> TransformInfo -> TransformResult r
+ DDC.Core.Simplifier.Result: data NoInformation
+ DDC.Core.Simplifier.Result: data TransformInfo
+ DDC.Core.Simplifier.Result: data TransformResult r
+ DDC.Core.Simplifier.Result: instance Pretty (TransformResult r)
+ DDC.Core.Simplifier.Result: instance Pretty NoInformation
+ DDC.Core.Simplifier.Result: instance Typeable NoInformation
+ DDC.Core.Simplifier.Result: result :: TransformResult r -> r
+ DDC.Core.Simplifier.Result: resultAgain :: TransformResult r -> Bool
+ DDC.Core.Simplifier.Result: resultDone :: String -> r -> TransformResult r
+ DDC.Core.Simplifier.Result: resultInfo :: TransformResult r -> TransformInfo
+ DDC.Core.Simplifier.Result: resultProgress :: TransformResult r -> Bool
+ DDC.Core.Transform.AnonymizeX: instance AnonymizeX (Witness a)
+ DDC.Core.Transform.Beta: Config :: Bool -> Config
+ DDC.Core.Transform.Beta: Info :: Int -> Int -> Int -> Int -> Int -> Info
+ DDC.Core.Transform.Beta: configBindRedexes :: Config -> Bool
+ DDC.Core.Transform.Beta: configZero :: Config
+ DDC.Core.Transform.Beta: data Config
+ DDC.Core.Transform.Beta: data Info
+ DDC.Core.Transform.Beta: instance Monoid Info
+ DDC.Core.Transform.Beta: instance Pretty Info
+ DDC.Core.Transform.Beta: instance Show Config
+ DDC.Core.Transform.Beta: instance Typeable Info
+ DDC.Core.Transform.Eta: Config :: Bool -> Config
+ DDC.Core.Transform.Eta: Info :: Int -> Int -> Info
+ DDC.Core.Transform.Eta: configExpand :: Config -> Bool
+ DDC.Core.Transform.Eta: configZero :: Config
+ DDC.Core.Transform.Eta: data Config
+ DDC.Core.Transform.Eta: data Info
+ DDC.Core.Transform.Eta: etaModule :: (Ord n, Show n, Pretty n, Show a) => Config -> Profile n -> Module a n -> TransformResult (Module a n)
+ DDC.Core.Transform.Eta: etaX :: (Ord n, Show n, Show a, Pretty n) => Config -> Profile n -> KindEnv n -> TypeEnv n -> Exp a n -> TransformResult (Exp a n)
+ DDC.Core.Transform.Eta: infoExpandedXLAMs :: Info -> Int
+ DDC.Core.Transform.Eta: infoExpandedXLams :: Info -> Int
+ DDC.Core.Transform.Eta: instance Eta Alt
+ DDC.Core.Transform.Eta: instance Eta Exp
+ DDC.Core.Transform.Eta: instance Eta Lets
+ DDC.Core.Transform.Eta: instance Eta Module
+ DDC.Core.Transform.Eta: instance Monoid Info
+ DDC.Core.Transform.Eta: instance Pretty Info
+ DDC.Core.Transform.Eta: instance Show Config
+ DDC.Core.Transform.Eta: instance Typeable Info
+ DDC.Core.Transform.Forward: Config :: (Lets a n -> FloatControl) -> Bool -> Config a n
+ DDC.Core.Transform.Forward: FloatAllow :: FloatControl
+ DDC.Core.Transform.Forward: FloatDeny :: FloatControl
+ DDC.Core.Transform.Forward: FloatForce :: FloatControl
+ DDC.Core.Transform.Forward: configFloatControl :: Config a n -> Lets a n -> FloatControl
+ DDC.Core.Transform.Forward: configFloatLetBody :: Config a n -> Bool
+ DDC.Core.Transform.Forward: data Config a n
+ DDC.Core.Transform.Forward: data FloatControl
+ DDC.Core.Transform.Forward: infoInspected :: ForwardInfo -> !Int
+ DDC.Core.Transform.Forward: instance Eq FloatControl
+ DDC.Core.Transform.Forward: instance Show FloatControl
+ DDC.Core.Transform.Namify: instance Namify (Witness a)
+ DDC.Core.Transform.Snip: Config :: Bool -> Bool -> Config
+ DDC.Core.Transform.Snip: configSnipLetBody :: Config -> Bool
+ DDC.Core.Transform.Snip: configSnipOverApplied :: Config -> Bool
+ DDC.Core.Transform.Snip: configZero :: Config
+ DDC.Core.Transform.Snip: data Config
+ DDC.Core.Transform.Thread: Config :: Config n -> (n -> Type n -> Maybe (Type n)) -> Type n -> Type n -> (Type n -> Type n) -> (Exp (AnTEC a n) n -> Exp (AnTEC a n) n -> Exp a n) -> (n -> Maybe (Bind n -> [Bind n] -> Pat n)) -> Config a n
+ DDC.Core.Transform.Thread: class Thread (c :: * -> * -> *)
+ DDC.Core.Transform.Thread: configCheckConfig :: Config a n -> Config n
+ DDC.Core.Transform.Thread: configThreadMe :: Config a n -> n -> Type n -> Maybe (Type n)
+ DDC.Core.Transform.Thread: configThreadPat :: Config a n -> n -> Maybe (Bind n -> [Bind n] -> Pat n)
+ DDC.Core.Transform.Thread: configTokenType :: Config a n -> Type n
+ DDC.Core.Transform.Thread: configVoidType :: Config a n -> Type n
+ DDC.Core.Transform.Thread: configWrapResultExp :: Config a n -> Exp (AnTEC a n) n -> Exp (AnTEC a n) n -> Exp a n
+ DDC.Core.Transform.Thread: configWrapResultType :: Config a n -> Type n -> Type n
+ DDC.Core.Transform.Thread: data Config a n
+ DDC.Core.Transform.Thread: injectStateType :: Eq n => Config a n -> Type n -> Type n
+ DDC.Core.Transform.Thread: instance Eq n => Eq (Context n)
+ DDC.Core.Transform.Thread: instance Thread Module
+ DDC.Core.Transform.Thread: thread :: (Thread c, Ord n, Show n, Pretty n) => Config a n -> KindEnv n -> TypeEnv n -> c (AnTEC a n) n -> c a n
+ DDC.Core.Transform.TransformDownX: class TransformDownMX m (c :: * -> * -> *)
+ DDC.Core.Transform.TransformDownX: instance Monad m => TransformDownMX m Alt
+ DDC.Core.Transform.TransformDownX: instance Monad m => TransformDownMX m Exp
+ DDC.Core.Transform.TransformDownX: instance Monad m => TransformDownMX m Lets
+ DDC.Core.Transform.TransformDownX: instance Monad m => TransformDownMX m Module
+ DDC.Core.Transform.TransformDownX: transformDownMX :: (TransformDownMX m c, Ord n) => (KindEnv n -> TypeEnv n -> Exp a n -> m (Exp a n)) -> KindEnv n -> TypeEnv n -> c a n -> m (c a n)
+ DDC.Core.Transform.TransformDownX: transformDownX :: (Ord n, TransformDownMX Identity c) => (KindEnv n -> TypeEnv n -> Exp a n -> Exp a n) -> KindEnv n -> TypeEnv n -> c a n -> c a n
+ DDC.Core.Transform.TransformDownX: transformDownX' :: (Ord n, TransformDownMX Identity c) => (Exp a n -> Exp a n) -> c a n -> c a n
+ DDC.Core.Transform.TransformUpX: class TransformUpMX m (c :: * -> * -> *)
+ DDC.Core.Transform.TransformUpX: instance Monad m => TransformUpMX m Alt
+ DDC.Core.Transform.TransformUpX: instance Monad m => TransformUpMX m Exp
+ DDC.Core.Transform.TransformUpX: instance Monad m => TransformUpMX m Lets
+ DDC.Core.Transform.TransformUpX: instance Monad m => TransformUpMX m Module
+ DDC.Core.Transform.TransformUpX: transformSimpleUpMX :: (Ord n, TransformUpMX m c, Monad m) => (KindEnv n -> TypeEnv n -> Exp a n -> m (Maybe (Exp a n))) -> KindEnv n -> TypeEnv n -> c a n -> m (c a n)
+ DDC.Core.Transform.TransformUpX: transformSimpleUpX :: (Ord n, TransformUpMX Identity c) => (KindEnv n -> TypeEnv n -> Exp a n -> Maybe (Exp a n)) -> KindEnv n -> TypeEnv n -> c a n -> c a n
+ DDC.Core.Transform.TransformUpX: transformSimpleUpX' :: (Ord n, TransformUpMX Identity c) => (Exp a n -> Maybe (Exp a n)) -> c a n -> c a n
+ DDC.Core.Transform.TransformUpX: transformUpMX :: (TransformUpMX m c, Ord n) => (KindEnv n -> TypeEnv n -> Exp a n -> m (Exp a n)) -> KindEnv n -> TypeEnv n -> c a n -> m (c a n)
+ DDC.Core.Transform.TransformUpX: transformUpX :: (Ord n, TransformUpMX Identity c) => (KindEnv n -> TypeEnv n -> Exp a n -> Exp a n) -> KindEnv n -> TypeEnv n -> c a n -> c a n
+ DDC.Core.Transform.TransformUpX: transformUpX' :: (Ord n, TransformUpMX Identity c) => (Exp a n -> Exp a n) -> c a n -> c a n
- DDC.Core.Simplifier: Beta :: Transform s a n
+ DDC.Core.Simplifier: Beta :: Config -> Transform s a n
- DDC.Core.Simplifier: Snip :: Transform s a n
+ DDC.Core.Simplifier: Snip :: Config -> Transform s a n
- DDC.Core.Transform.Beta: betaReduce :: (Ord n, TransformUpMX (Writer BetaReduceInfo) c) => Bool -> c a n -> TransformResult (c a n)
+ DDC.Core.Transform.Beta: betaReduce :: (Ord n, TransformUpMX (Writer Info) c) => Config -> c a n -> TransformResult (c a n)
- DDC.Core.Transform.Beta: infoTypes :: BetaReduceInfo -> Int
+ DDC.Core.Transform.Beta: infoTypes :: Info -> Int
- DDC.Core.Transform.Beta: infoValues :: BetaReduceInfo -> Int
+ DDC.Core.Transform.Beta: infoValues :: Info -> Int
- DDC.Core.Transform.Beta: infoValuesLetted :: BetaReduceInfo -> Int
+ DDC.Core.Transform.Beta: infoValuesLetted :: Info -> Int
- DDC.Core.Transform.Beta: infoValuesSkipped :: BetaReduceInfo -> Int
+ DDC.Core.Transform.Beta: infoValuesSkipped :: Info -> Int
- DDC.Core.Transform.Beta: infoWits :: BetaReduceInfo -> Int
+ DDC.Core.Transform.Beta: infoWits :: Info -> Int
- DDC.Core.Transform.Forward: ForwardInfo :: Int -> Int -> ForwardInfo
+ DDC.Core.Transform.Forward: ForwardInfo :: !Int -> !Int -> !Int -> ForwardInfo
- DDC.Core.Transform.Forward: forwardModule :: Ord n => Profile n -> Module a n -> Module a n
+ DDC.Core.Transform.Forward: forwardModule :: Ord n => Profile n -> Config a n -> Module a n -> TransformResult (Module a n)
- DDC.Core.Transform.Forward: forwardX :: Ord n => Profile n -> Exp a n -> TransformResult (Exp a n)
+ DDC.Core.Transform.Forward: forwardX :: Ord n => Profile n -> Config a n -> Exp a n -> TransformResult (Exp a n)
- DDC.Core.Transform.Forward: infoBindings :: ForwardInfo -> Int
+ DDC.Core.Transform.Forward: infoBindings :: ForwardInfo -> !Int
- DDC.Core.Transform.Forward: infoSubsts :: ForwardInfo -> Int
+ DDC.Core.Transform.Forward: infoSubsts :: ForwardInfo -> !Int
- DDC.Core.Transform.Rewrite.Parser: pRule :: Ord n => Parser n (RewriteRule () n)
+ DDC.Core.Transform.Rewrite.Parser: pRule :: Ord n => Context -> Parser n (RewriteRule SourcePos n)
- DDC.Core.Transform.Rewrite.Parser: pRuleMany :: Ord n => Parser n [(n, RewriteRule () n)]
+ DDC.Core.Transform.Rewrite.Parser: pRuleMany :: Ord n => Context -> Parser n [(n, RewriteRule SourcePos n)]
- DDC.Core.Transform.Snip: snip :: (Snip c, Ord n) => Bool -> c n -> c n
+ DDC.Core.Transform.Snip: snip :: (Snip c, Ord n) => Config -> c n -> c n

Files

DDC/Core/Analysis/Arity.hs view
@@ -96,7 +96,7 @@                 Nothing         -> Nothing                 Just a          -> Just (b, a)    in case ll of-        LLet _ b x      -> sequence $ map get [(b, x)]+        LLet b x        -> sequence $ map get [(b, x)]         LRec bxs        -> sequence $ map get bxs         _               -> Just [] 
DDC/Core/Analysis/Usage.hs view
@@ -19,7 +19,7 @@ -- Used ----------------------------------------------------------------------- -- | Tracks how a bound variable is used. data Used-        -- | Bound variable is used as the function of an application.+        -- | Bound variable is used as the function in an application.         = UsedFunction          -- | Bound variable is destructed by a case-expression.@@ -71,7 +71,7 @@         = foldl' plusUsedMap m ms  --- Usage ----------------------------------------------------------------------+-- Module --------------------------------------------------------------------- -- | Annotate all binding occurrences of variables in an expression --   with how they are used. usageModule @@ -96,6 +96,7 @@                 , moduleBody            = usageX body }  +-- Exp ------------------------------------------------------------------------ -- | Annotate all binding occurrences of variables in an expression --   with how they are used. usageX  :: Ord n @@ -182,7 +183,9 @@          -> (empty, XType t)          XWitness w     -         -> (empty, XWitness w)+         | (used', w')    <- usageWitness w+         -> ( used'+            , XWitness w')   -- | Annotate binding occurences of named variables with usage information.@@ -193,9 +196,9 @@  usageLets lts  = case lts of-        LLet mode b x-         |  (used, x')   <- usageX' x-         -> (used, LLet mode b x')+        LLet b x+         |  (used1', x')        <- usageX' x+         -> (used1', LLet b x')          LRec bxs          |  (bs, xs)      <- unzip bxs@@ -228,12 +231,17 @@          -> (UsedMap usedCasts, CastWeakenClosure xs')          CastPurify w-         -> (empty, CastPurify w)+         | (used, w')   <- usageWitness w+         -> (used, CastPurify w')          CastForget w-         -> (empty, CastForget w)+         | (used, w')   <- usageWitness w+         -> (used, CastForget w') +        CastSuspend     -> (empty, CastSuspend)+        CastRun         -> (empty, CastRun) + -- | Annotate binding occurrences of named level-0 variables with --   usage information. usageAlt  @@ -246,3 +254,32 @@    in   (used, AAlt p x')  +-- | Annotate binding occurrences of named level-0 variables with+--   usage information.+usageWitness+        :: Ord n+        => Witness a n+        -> (UsedMap n, Witness (UsedMap n, a) n)++usageWitness ww+ = case ww of+        WVar a u+         -> (empty, WVar (empty, a) u)++        WCon a c+         -> (empty, WCon (empty, a) c)++        WApp a w1 w2+         | (used1, w1') <- usageWitness w1+         , (used2, w2') <- usageWitness w2+         , used'        <- plusUsedMap used1 used2+         -> (empty, WApp (used', a) w1' w2')++        WJoin a w1 w2+         | (used1, w1') <- usageWitness w1+         , (used2, w2') <- usageWitness w2+         , used'        <- plusUsedMap used1 used2+         -> (empty, WJoin (used', a) w1' w2')++        WType a t+         -> (empty, WType (empty, a) t)
DDC/Core/Simplifier/Apply.hs view
@@ -12,11 +12,12 @@ import DDC.Core.Fragment import DDC.Core.Simplifier.Base import DDC.Core.Transform.AnonymizeX-import DDC.Core.Transform.Snip+import DDC.Core.Transform.Snip          as Snip import DDC.Core.Transform.Flatten import DDC.Core.Transform.Beta+import DDC.Core.Transform.Eta           as Eta import DDC.Core.Transform.Prune-import DDC.Core.Transform.Forward+import DDC.Core.Transform.Forward       as Forward import DDC.Core.Transform.Bubble import DDC.Core.Transform.Inline import DDC.Core.Transform.Namify@@ -79,12 +80,15 @@  = case spec of         Id               -> return mm         Anonymize        -> return $ anonymizeX mm-        Snip             -> return $ snip False mm-        SnipOver         -> return $ snip True mm+        Snip config      -> return $ snip config mm         Flatten          -> return $ flatten mm-        Beta             -> return $ result $ betaReduce False mm-        BetaLets         -> return $ result $ betaReduce True  mm-        Forward          -> return $ forwardModule profile mm+        Beta config      -> return $ result $ betaReduce config mm+        Eta  config      -> return $ result $ Eta.etaModule config profile mm++        Forward          +         -> let config  = Forward.Config (const FloatAllow) False+            in  return $ result $ forwardModule profile config mm+         Bubble           -> return $ bubbleModule mm         Namify namK namT -> namifyUnique namK namT mm         Inline getDef    -> return $ inline getDef Set.empty mm@@ -225,14 +229,17 @@    in case spec of         Id                -> res xx         Anonymize         -> res    $ anonymizeX xx-        Snip              -> res    $ snip False xx-        SnipOver          -> res    $ snip True xx+        Snip config       -> res    $ snip config xx         Flatten           -> res    $ flatten xx         Inline  getDef    -> res    $ inline getDef Set.empty xx-        Beta              -> return $ betaReduce False xx-        BetaLets          -> return $ betaReduce True  xx+        Beta config       -> return $ betaReduce config xx+        Eta  config       -> return $ Eta.etaX config profile kenv tenv xx         Prune             -> return $ pruneX   profile kenv tenv xx-        Forward           -> return $ forwardX profile xx++        Forward          +         -> let config  = Forward.Config (const FloatAllow) False+            in  return $ forwardX profile config xx+         Bubble            -> res    $ bubbleX kenv tenv xx         Namify  namK namT -> namifyUnique namK namT xx >>= res         Rewrite rules     -> return $ rewriteX rules xx
DDC/Core/Simplifier/Base.hs view
@@ -11,17 +11,19 @@           -- * Transform Results         , TransformResult(..) 	, TransformInfo(..)-	, NoInformation(..)+	, NoInformation 	, resultDone) where+import DDC.Core.Simplifier.Result import DDC.Core.Transform.Rewrite.Rule import DDC.Core.Transform.Namify import DDC.Core.Exp import DDC.Type.Env import DDC.Base.Pretty-import qualified DDC.Base.Pretty	as P+import qualified DDC.Core.Transform.Snip        as Snip+import qualified DDC.Core.Transform.Eta         as Eta+import qualified DDC.Core.Transform.Beta        as Beta import Data.Monoid-import Data.Typeable (Typeable)   -- Simplifier -----------------------------------------------------------------@@ -67,21 +69,16 @@         | Anonymize          -- | Introduce let-bindings for nested applications.-        | Snip--        -- | Introduce let-bindings for nested applications and over-applied-        --   functions-        | SnipOver+        | Snip  Snip.Config          -- | Flatten nested let and case expressions.         | Flatten          -- | Perform beta reduction when the argument is not a redex.-        | Beta+        | Beta  Beta.Config -        -- | Perform beta reduction, introducing new let-bindings for -        --   arguments that are redexes.-        | BetaLets+        -- | Perform eta expansion and reduction.+        | Eta    Eta.Config          -- | Remove unused, pure let bindings.         | Prune@@ -133,11 +130,10 @@   = case ss of         Id              -> text "Id"         Anonymize       -> text "Anonymize"-        Snip            -> text "Snip"-        SnipOver        -> text "Snip"+        Snip{}          -> text "Snip"         Flatten         -> text "Flatten"-        Beta            -> text "Beta"-        BetaLets        -> text "BetaLets"+        Beta{}          -> text "Beta"+        Eta{}           -> text "Eta"         Prune           -> text "Prune"         Forward         -> text "Forward"         Bubble          -> text "Bubble"@@ -146,62 +142,3 @@         Rewrite{}       -> text "Rewrite"         Elaborate       -> text "Elaborate" ---- TransformResult --------------------------------------------------------------- | Package up the result of applying a single transform.-data TransformResult r-        = TransformResult-        { -- | Transform result proper (eg the new module)-          result         :: r--          -- | Whether this transform made any progess.-          --   -          --   If `False` then the result program must be the same as the-          --   input program, and a simplifer fixpoint won't apply this-          --   transform again to the result program.-        , resultProgress :: Bool--          -- | Whether it might help to run the same transform again.-          -- -          --   If `False` then a simplifier fixpoint won't apply this transform-          --   again to the result program.-        , resultAgain    :: Bool--          -- | Transform specific log. This might contain a count of what rules-          --   fired, or information about what parts of the program couldn't-          --   be processed.-        , resultInfo     :: TransformInfo }----- | Existential package for a typeable thing,---   used in `TransformResult`.-data TransformInfo-	=  forall i-        .  (Typeable i, Pretty i)-	=> TransformInfo i----- | Place-holder type to use when there is no real `TransformResult`.-data NoInformation -        = NoInformation String-        deriving Typeable---instance Pretty NoInformation where-    ppr (NoInformation name) = text name P.<> text ": No information"---instance Pretty (TransformResult r) where- ppr (TransformResult _ _ _ (TransformInfo i))-  = ppr i----- | Create a default result with no transform again.---  ---   We'll say we made progress, but set `resultAgain` to False---   so to stop any simplifier fixpoints.-resultDone :: String -> r -> TransformResult r-resultDone name r -        = TransformResult r True False-        $ TransformInfo -        $ NoInformation name
DDC/Core/Simplifier/Parser.hs view
@@ -11,11 +11,14 @@ import DDC.Core.Simplifier.Lexer import DDC.Data.Token import DDC.Data.SourcePos-import DDC.Base.Parser                  (pTok)-import Data.Set                         (Set)-import qualified DDC.Base.Parser        as P-import qualified Data.Map               as Map-import qualified Data.Set               as Set+import DDC.Base.Parser                          (pTok)+import Data.Set                                 (Set)+import qualified DDC.Core.Transform.Snip        as Snip+import qualified DDC.Core.Transform.Beta        as Beta+import qualified DDC.Core.Transform.Eta         as Eta+import qualified DDC.Base.Parser                as P+import qualified Data.Map                       as Map+import qualified Data.Set                       as Set   -------------------------------------------------------------------------------@@ -189,11 +192,17 @@  = case name of         "Id"            -> Just Id         "Anonymize"     -> Just Anonymize-        "Snip"          -> Just Snip-        "SnipOver"      -> Just SnipOver++        "Snip"          -> Just (Snip Snip.configZero)+        "SnipOver"      -> Just (Snip Snip.configZero { Snip.configSnipOverApplied = True })++        "Eta"           -> Just (Eta  Eta.configZero  { Eta.configExpand = True })+         "Flatten"       -> Just Flatten-        "Beta"          -> Just Beta-        "BetaLets"      -> Just BetaLets++        "Beta"          -> Just (Beta Beta.configZero)+        "BetaLets"      -> Just (Beta Beta.configZero { Beta.configBindRedexes    = True })+         "Prune"         -> Just Prune         "Forward"       -> Just Forward         "Bubble"        -> Just Bubble
DDC/Core/Simplifier/Recipe.hs view
@@ -20,6 +20,8 @@ where import DDC.Core.Simplifier.Base import DDC.Core.Transform.Namify+import qualified DDC.Core.Transform.Snip  as Snip+import qualified DDC.Core.Transform.Beta  as Beta import DDC.Type.Env import Data.Monoid @@ -39,12 +41,12 @@  -- | Introduce let-bindings for nested applications. snip      :: Simplifier s a n-snip      = Trans Snip+snip      = Trans (Snip Snip.configZero)   -- | Introduce let-bindings for nested applications. snipOver  :: Simplifier s a n-snipOver  = Trans SnipOver+snipOver  = Trans (Snip Snip.configZero { Snip.configSnipOverApplied = True })   -- | Flatten nested let and case expressions.@@ -54,12 +56,12 @@  -- | Perform beta reduction beta    :: Simplifier s a n-beta    = Trans Beta+beta    = Trans (Beta Beta.configZero)   -- | Perform beta reduction, introducing let-expressions for compound arguments. betaLets :: Simplifier s a n-betaLets = Trans BetaLets+betaLets = Trans (Beta Beta.configZero { Beta.configBindRedexes = True })   -- | Remove unused, pure let bindings.@@ -93,7 +95,7 @@         -> Simplifier s a n  anormalize namK namT-        =  Trans Snip +        =  snip         <> Trans Flatten          <> Trans (Namify namK namT) 
+ DDC/Core/Simplifier/Result.hs view
@@ -0,0 +1,70 @@++module DDC.Core.Simplifier.Result+        ( TransformResult (..)+        , TransformInfo   (..)+        , NoInformation+        , resultDone)+where+import DDC.Base.Pretty+import Data.Typeable+import qualified DDC.Base.Pretty                as P+++-- TransformResult ------------------------------------------------------------+-- | Package up the result of applying a single transform.+data TransformResult r+        = TransformResult+        { -- | Transform result proper (eg the new module)+          result         :: r++          -- | Whether this transform made any progess.+          --   +          --   If `False` then the result program must be the same as the+          --   input program, and a simplifer fixpoint won't apply this+          --   transform again to the result program.+        , resultProgress :: Bool++          -- | Whether it might help to run the same transform again.+          -- +          --   If `False` then a simplifier fixpoint won't apply this transform+          --   again to the result program.+        , resultAgain    :: Bool++          -- | Transform specific log. This might contain a count of what rules+          --   fired, or information about what parts of the program couldn't+          --   be processed.+        , resultInfo     :: TransformInfo }+++-- | Existential package for a typeable thing,+--   used in `TransformResult`.+data TransformInfo+        =  forall i+        .  (Typeable i, Pretty i)+        => TransformInfo i+++-- | Place-holder type to use when there is no real `TransformResult`.+data NoInformation +        = NoInformation String+        deriving Typeable+++instance Pretty NoInformation where+    ppr (NoInformation name) = text name P.<> text ": No information"+++instance Pretty (TransformResult r) where+ ppr (TransformResult _ _ _ (TransformInfo i))+  = ppr i+++-- | Create a default result with no transform again.+--  +--   We'll say we made progress, but set `resultAgain` to False+--   so to stop any simplifier fixpoints.+resultDone :: String -> r -> TransformResult r+resultDone name r +        = TransformResult r True False+        $ TransformInfo +        $ NoInformation name
DDC/Core/Transform/AnonymizeX.hs view
@@ -9,7 +9,6 @@ import DDC.Core.Exp import DDC.Type.Transform.AnonymizeT import DDC.Type.Compounds-import Control.Monad import Data.List import Data.Set                         (Set) import qualified Data.Set               as Set@@ -89,25 +88,12 @@  anonymizeWithX keep kstack tstack cc   = let down = anonymizeWithX keep kstack tstack     in case cc of-        CastWeakenEffect eff-         -> CastWeakenEffect  (anonymizeWithT kstack eff)--        CastWeakenClosure xs-         -> CastWeakenClosure (map down xs)--        CastPurify w-         -> CastPurify        (down w)--        CastForget w-         -> CastForget        (down w)---instance AnonymizeX LetMode where- anonymizeWithX keep kstack tstack lm-  = let down = anonymizeWithX keep kstack tstack-    in case lm of-        LetStrict       -> lm-        LetLazy mw      -> LetLazy $ liftM down mw+        CastWeakenEffect eff    -> CastWeakenEffect  (anonymizeWithT kstack eff)+        CastWeakenClosure xs    -> CastWeakenClosure (map down xs)+        CastPurify w            -> CastPurify        (down w)+        CastForget w            -> CastForget        (down w)+        CastSuspend             -> CastSuspend+        CastRun                 -> CastRun   instance AnonymizeX (Alt a) where@@ -123,19 +109,19 @@             in  AAlt (PData uCon bs') x'  -instance AnonymizeX Witness where+instance AnonymizeX (Witness a) where  anonymizeWithX keep kstack tstack ww   = let down = anonymizeWithX keep kstack tstack      in case ww of-        WVar u@(UName _)+        WVar a u@(UName _)          |  Just ix      <- findIndex (boundMatchesBind u) tstack-         -> WVar (UIx ix)+         -> WVar a (UIx ix) -        WVar u          -> WVar u-        WCon  c         -> WCon  c-        WApp  w1 w2     -> WApp  (down w1) (down w2)-        WJoin w1 w2     -> WJoin (down w1) (down w2)-        WType t         -> WType (anonymizeWithT kstack t)+        WVar  a u       -> WVar  a u+        WCon  a c       -> WCon  a c+        WApp  a w1 w2   -> WApp  a (down w1) (down w2)+        WJoin a w1 w2   -> WJoin a (down w1) (down w2)+        WType a t       -> WType a (anonymizeWithT kstack t)   instance AnonymizeX Bind where@@ -199,11 +185,10 @@  pushAnonymizeLets keep kstack tstack lts  = case lts of-        LLet mode b x-         -> let mode'           = anonymizeWithX     keep kstack tstack mode-                x'              = anonymizeWithX     keep kstack tstack x+        LLet b x+         -> let x'              = anonymizeWithX     keep kstack tstack x                 (tstack', b')   = pushAnonymizeBindX keep kstack tstack b-            in  (kstack, tstack', LLet mode' b' x')+            in  (kstack, tstack', LLet b' x')          LRec bxs           -> let (bs, xs)        = unzip bxs
DDC/Core/Transform/Beta.hs view
@@ -2,18 +2,20 @@ -- | Beta-reduce applications of a explicit lambda abstractions  --   to variables and values. module DDC.Core.Transform.Beta-        ( BetaReduceInfo(..)+        ( Config        (..)+        , configZero+        , Info          (..)         , betaReduce) where import DDC.Base.Pretty import DDC.Core.Collect import DDC.Core.Exp import DDC.Core.Predicates-import DDC.Core.Simplifier.Base-import DDC.Core.Transform.TransformX+import DDC.Core.Transform.TransformUpX import DDC.Core.Transform.SubstituteTX import DDC.Core.Transform.SubstituteWX import DDC.Core.Transform.SubstituteXX+import DDC.Core.Simplifier.Result import Control.Monad.Writer	        (Writer, runWriter, tell) import Data.Monoid		        (Monoid, mempty, mappend) import Data.Typeable		        (Typeable)@@ -24,9 +26,25 @@   -------------------------------------------------------------------------------+data Config+        = Config+        { -- | If we find a lambda abstraction applied to a redex then let-bind+          --   the redex and substitute the new variable instead.+          configBindRedexes     :: Bool }+        deriving Show+++-- | Empty beta configuration with all flags set to False.+configZero :: Config+configZero+        = Config+        { configBindRedexes     = False }+++------------------------------------------------------------------------------- -- | A summary of what the beta reduction transform did.-data BetaReduceInfo-        = BetaReduceInfo+data Info+        = Info         { -- | Number of type applications reduced.           infoTypes             :: Int @@ -44,8 +62,8 @@         deriving Typeable  -instance Pretty BetaReduceInfo where- ppr (BetaReduceInfo ty wit val lets skip)+instance Pretty Info where+ ppr (Info ty wit val lets skip)   =  text "Beta reduction:"   <$> indent 4 (vcat       [ text "Types:          " <> int ty@@ -55,13 +73,13 @@       , text "Values skipped: " <> int skip ])  -instance Monoid BetaReduceInfo where- mempty = BetaReduceInfo 0 0 0 0 0- mappend (BetaReduceInfo ty1 wit1 val1 lets1 skip1)-         (BetaReduceInfo ty2 wit2 val2 lets2 skip2)-  = (BetaReduceInfo +instance Monoid Info where+ mempty = Info 0 0 0 0 0+ mappend (Info ty1 wit1 val1 lets1 skip1)+         (Info ty2 wit2 val2 lets2 skip2)+  = Info                  (ty1   + ty2)   (wit1  + wit2) (val1 + val2)-                (lets1 + lets2) (skip1 + skip2))+                (lets1 + lets2) (skip1 + skip2)   -------------------------------------------------------------------------------@@ -73,19 +91,20 @@ --   instead. betaReduce           :: forall (c :: * -> * -> *) a n -        .  (Ord n, TransformUpMX (Writer BetaReduceInfo) c)-        => Bool         -- ^ Let-bind redexes.+        .  (Ord n, TransformUpMX (Writer Info) c)+        => Config         -> c a n          -> TransformResult (c a n)-betaReduce lets x++betaReduce config x  = {-# SCC betaReduce #-}    let (x', info) = runWriter-		  $ transformUpMX (betaReduce1 lets) Env.empty Env.empty x+		  $ transformUpMX (betaReduce1 config) Env.empty Env.empty x         -- Check if any actual work was performed        progress          = case info of-                BetaReduceInfo ty wit val lets' _+                Info ty wit val lets' _                  -> (ty + wit + val + lets') > 0     in  TransformResult@@ -105,13 +124,13 @@ --     betaReduce1         :: Ord n-        => Bool	        -- ^ Let-bind redexes.+        => Config         -> Env n         -> Env n         -> Exp a n-        -> Writer BetaReduceInfo (Exp a n)+        -> Writer Info (Exp a n) -betaReduce1 lets _kenv tenv xx+betaReduce1 config _kenv tenv xx  = let  ret info x = tell info >> return x    in case xx of @@ -168,9 +187,9 @@                     else XCast a (CastWeakenClosure [x2])                        $ substituteXX b11 x2 x12 -         | lets+         | configBindRedexes config          -> ret mempty { infoValuesLetted  = 1 }-	      $	XLet a (LLet LetStrict b11 x2) x12+	      $	XLet a (LLet b11 x2) x12           | otherwise          -> ret mempty { infoValuesSkipped = 1 }
DDC/Core/Transform/Bubble.hs view
@@ -122,11 +122,11 @@          -- Drop casts that mention the bound variable here,          -- but we can float the others further outwards.-        LLet m b x+        LLet b x          -> let (cs, x')        = bubble kenv tenv x                 Just a          = takeAnnotOfExp x'                 (cs', xc')      = dropCasts kenv tenv a [] [b] cs x'-            in  (cs', LLet m b xc')+            in  (cs', LLet b xc')          -- ISSUE #299: Bubble casts out of recursive lets.         LRec bxs
DDC/Core/Transform/Elaborate.hs view
@@ -75,7 +75,7 @@ elaborateLets us lts   = let down = elaborate us     in case lts of-        LLet m b x -> (us, LLet m b (down x))+        LLet b x   -> (us, LLet b (down x))         LRec bs    -> (us, LRec $ map (second down) bs)          LLetRegions brs bws
+ DDC/Core/Transform/Eta.hs view
@@ -0,0 +1,301 @@++-- Eta-expand functional values.+---+-- NOTE: This is module currently just does eta-expansion, but in future+--       we should expand the config to also make it do expansion/contraction+--       based on the real arity of bindings.+--+module DDC.Core.Transform.Eta+        ( Config(..)+        , configZero+        , Info  (..)+        , etaModule+        , etaX)+where+import qualified DDC.Core.Check as Check+import DDC.Core.Module+import DDC.Core.Exp+import DDC.Core.Fragment+import DDC.Core.Transform.LiftX+import DDC.Core.Transform.LiftT+import DDC.Core.Simplifier.Result+import DDC.Core.Compounds+import DDC.Core.Pretty+import DDC.Type.Env             (TypeEnv, KindEnv)+import Control.Monad.Writer     (Writer, tell, runWriter)+import Data.Monoid              (Monoid, mempty, mappend)+import qualified DDC.Type.Env   as Env+import Data.Typeable+++-------------------------------------------------------------------------------+data Config+        = Config+        { configExpand  :: Bool }+        deriving Show+++-- | Empty eta configuration with all flags set to False.+configZero :: Config+configZero+        = Config+        { configExpand  = False }+++-------------------------------------------------------------------------------+data Info+        = Info+        { -- | Number of level-1 lambdas added.+          infoExpandedXLAMs     :: Int ++          -- | Number of level-0 lambdas added. +        , infoExpandedXLams     :: Int }+        deriving Typeable+++instance Pretty Info where+ ppr (Info ex1 ex0)+  = text "Eta Transform"+  <$> indent 4 (vcat+      [ text "level-1 lambdas added:     " <> int ex1 +      , text "level-0 lambdas added:     " <> int ex0 ])+++instance Monoid Info where+ mempty  = Info 0 0+ mappend (Info ex1  ex0)+         (Info ex1' ex0')+  = Info (ex1 + ex1') (ex0 + ex0')+++-- Module ---------------------------------------------------------------------+-- | Eta-transform expressions in a module.+etaModule+        :: (Ord n, Show n, Pretty n, Show a)+        => Config+        -> Profile n+        -> Module a n+        -> TransformResult (Module a n)++etaModule config profile mm+ = let  cconfig = Check.configOfProfile profile+        kenv'   = Env.union (profilePrimKinds profile) (moduleKindEnv mm)+        tenv'   = Env.union (profilePrimTypes profile) (moduleTypeEnv mm)+        +        -- Run the eta transform.+        (mm', info) +                = runWriter +                $ etaM config cconfig kenv' tenv' mm+                    +        -- Check if any actual work was performed+        progress+         = case info of+                Info ex1 ex0+                 -> ex1 + ex0 > 0++   in   TransformResult+         { result         = mm'+         , resultAgain    = False+         , resultProgress = progress+         , resultInfo     = TransformInfo info }+++-- | Eta-transform an expression.+etaX    :: (Ord n, Show n, Show a, Pretty n)+        => Config               -- ^ Eta-transform config.+        -> Profile n            -- ^ Language profile.+        -> KindEnv n            -- ^ Kind environment.+        -> TypeEnv n            -- ^ Type environment.+        -> Exp a n              -- ^ Expression to transform.+        -> TransformResult (Exp a n)++etaX config profile kenv tenv xx+ = let  cconfig = Check.configOfProfile profile+        kenv'   = Env.union (profilePrimKinds profile) kenv+        tenv'   = Env.union (profilePrimTypes profile) tenv++        -- Run the eta transform.+        (xx', info)     +                = runWriter+                $ etaM config cconfig kenv' tenv' xx++        -- Check if any actual work was performed+        progress+         = case info of+                Info ex1 ex0+                 -> ex1 + ex0 > 0++   in   TransformResult+         { result         = xx'+         , resultAgain    = False+         , resultProgress = progress+         , resultInfo     = TransformInfo info }+++-------------------------------------------------------------------------------+class Eta (c :: * -> * -> *) where+ etaM   :: (Ord n, Pretty n, Show n)+        => Config               -- ^ Eta-transform config.+        -> Check.Config n       -- ^ Type checker config.+        -> KindEnv n            -- ^ Kind environment.+        -> TypeEnv n            -- ^ Type environment.+        -> c a n                -- ^ Do eta-expansion in this thing.+        -> Writer Info (c a n)+++instance Eta Module where+ etaM config cconfig kenv tenv mm+  = do  let kenv'       = Env.union (moduleKindEnv mm) kenv+        let tenv'       = Env.union (moduleTypeEnv mm) tenv+        xx'             <- etaM config cconfig kenv' tenv' (moduleBody mm)+        return  $ mm { moduleBody = xx' }+++instance Eta Exp where+ etaM config cconfig kenv tenv xx+  = let down = etaM config cconfig kenv tenv+    in case xx of++        XVar a _+         | configExpand config+         , Right tX     <- Check.typeOfExp cconfig kenv tenv xx+         -> do  etaExpand a tX xx++        XApp a _ _+         |  configExpand config+         ,  Right tX    <- Check.typeOfExp cconfig kenv tenv xx+         -> do  +                -- Decend into the arguments first.+                --   We don't need to decend into the function part because+                --   we're eta-expanding that here.+                let (x : xs)    =  takeXAppsAsList xx+                xs_eta          <- mapM down xs++                -- Now eta expand the result.+                etaExpand a tX $ xApps a x xs_eta++        XLAM a b x+         -> do  let kenv'       = Env.extend b kenv+                x'              <- etaM config cconfig kenv' tenv x+                return $ XLAM a b x'++        XLam a b x+         -> do  let tenv'       = Env.extend b tenv+                x'              <- etaM config cconfig kenv tenv' x+                return $ XLam a b x'++        XLet a lts x2+         -> do  lts'            <- down lts+                let (bs1, bs0)  = bindsOfLets lts+                let kenv'       = Env.extends bs1 kenv+                let tenv'       = Env.extends bs0 tenv+                x2'             <- etaM config cconfig kenv' tenv' x2+                return $ XLet a lts' x2'++        XCase a x alts+         -> do  x'              <- down x+                alts'           <- mapM (etaM config cconfig kenv tenv) alts+                return $ XCase a x' alts'++        XCast a cc x+         -> do  x'              <- down x+                return $ XCast a cc x'++        _ -> return xx+++instance Eta Lets where+ etaM config cconfig kenv tenv lts+  = let down    = etaM config cconfig kenv tenv+    in case lts of+        LLet b x+         -> do  x'      <- down x+                return  $ LLet b x'++        LRec bxs+         -> do  let bs    = map fst bxs+                let tenv' = Env.extends bs tenv+                xs'       <- mapM (etaM config cconfig kenv tenv') +                          $  map snd bxs+                return    $ LRec (zip bs xs')++        LLetRegions{}   -> return lts+        LWithRegion{}   -> return lts+++instance Eta Alt where+ etaM config cconfig kenv tenv alt+  = case alt of+        AAlt p x        +         -> do  let bs    = bindsOfPat p+                let tenv' = Env.extends bs tenv+                x'        <- etaM config cconfig kenv tenv' x+                return  $ AAlt p x'+++-- Expand ---------------------------------------------------------------------+-- | Eta expand an expression.+etaExpand +        :: Ord n+        => a                    -- ^ Annotation to use for new AST nodes.+        -> Type n               -- ^ Type of the expression.+        -> Exp a n              -- ^ Inner expression to wrap.+        -> Writer Info (Exp a n)++etaExpand a tX xx+ = do   let btsMore     = expandableArgs tX+        xx'             <- etaExpand' a 0 0 [] btsMore xx+        return xx'+++-- | Decide what type arguments need to be eta-expanded.+expandableArgs :: Type n -> [(Bool, Type n)]+expandableArgs tt+        | TForall b t'          <- tt+        = (True, typeOfBind b)  : expandableArgs t'++        | Just (t1, t2)         <- takeTFun tt+        = (False, t1)           : expandableArgs t2++        | otherwise+        = []+++-- | Eta-expand an expression.+etaExpand'+        :: Ord n +        => a                -- ^ Annotation to use for the new AST nodes.+        -> Int              -- ^ Number of level-1 lambdas we've added so far.+        -> Int              -- ^ Number of level-0 lambdas we've added so far.+        -> [Exp a n]        -- ^ Accumulate arguments we need to add to the+                            --      inner expression.+        -> [(Bool, Type n)] -- ^ Types of bindings we need to add, along with+                            --   a flag to indicate level-1 or level-0 binder+        -> Exp a n          -- ^ Inner expression that is being applied.+        -> Writer Info (Exp a n)++etaExpand' a levels1 levels0 args [] xx+ = do   let xx' = liftT levels1 $ liftX levels0 xx+        return  $ xApps a xx' args++etaExpand' a levels1 levels0 args ((True, t) : ts) xx+ = do   let depth1 = length $ filter ((== True) . fst) ts+        xx'     <- etaExpand' a (levels1 + 1) levels0 +                        (args ++ [XType (TVar (UIx depth1))]) +                        ts+                        xx++        tell mempty { infoExpandedXLAMs = 1 }+        return  $ XLAM a (BAnon t) xx'++etaExpand' a levels1 levels0 args ((False, t) : ts) xx+ = do   let depth0 = length $ filter ((== False) . fst) ts+        xx'     <- etaExpand' a +                        levels1 (levels0 + 1) +                        (args ++ [XVar a (UIx depth0)])+                        ts+                        xx++        tell mempty { infoExpandedXLams = 1 }+        return  $ XLam a (BAnon t) xx'+
DDC/Core/Transform/Flatten.hs view
@@ -4,7 +4,7 @@         (flatten) where import DDC.Core.Transform.LiftT-import DDC.Core.Transform.TransformX+import DDC.Core.Transform.TransformUpX import DDC.Core.Transform.AnonymizeX import DDC.Core.Transform.LiftX import DDC.Core.Exp@@ -43,21 +43,21 @@ --      x1 -- @ -- -flatten1 (XLet a1 (LLet LetStrict b1-            inner@(XLet a2 (LLet LetStrict b2 def2) x2))+flatten1 (XLet a1 (LLet b1+            inner@(XLet a2 (LLet b2 def2) x2))                x1)   | isBName b2  = flatten1-        $ XLet a1 (LLet LetStrict b1 +        $ XLet a1 (LLet b1                 (anonymizeX inner))                x1   | otherwise  = let  x1'       = liftAcrossX [b1] [b2] x1                                 -   in   XLet a2 (LLet LetStrict b2 def2) +   in   XLet a2 (LLet b2 def2)        $ flatten1-      $ XLet a1 (LLet LetStrict b1 x2) +      $ XLet a1 (LLet b1 x2)               x1'  @@ -74,12 +74,12 @@ -- NOTE: For region allocation this increases the lifetime of the region. --       Maybe use a follow on transform to reduce the lifetime again. ---flatten1 (XLet a1 (LLet LetStrict b1+flatten1 (XLet a1 (LLet b1             inner@(XLet a2 (LLetRegions b2 bs2) x2))                x1)  | all isBName b2  = flatten1-        $ XLet a1 (LLet LetStrict b1+        $ XLet a1 (LLet b1                   (anonymizeX inner))                x1 @@ -88,7 +88,7 @@                 $ liftAcrossX [b1] bs2 x1    in   XLet a2 (LLetRegions b2 bs2)        $ flatten1-      $ XLet a1 (LLet LetStrict (zapX b1) x2) +      $ XLet a1 (LLet (zapX b1) x2)               x1'  @@ -105,12 +105,12 @@ -- -- * binding must be strict because we force evaluation of x1. ---flatten1 (XLet  a1 (LLet LetStrict b1 +flatten1 (XLet  a1 (LLet b1               inner@(XCase a2 x1 [AAlt p x2]))                    x3)  | any isBName $ bindsOfPat p  = flatten1-        $ XLet  a1 (LLet LetStrict b1+        $ XLet  a1 (LLet b1                    (anonymizeX inner))                    x3 @@ -118,7 +118,7 @@  = let  x3'     = liftAcrossX [b1] (bindsOfPat p) x3    in   XCase a2 x1             [AAlt p ( flatten1 -                   $ XLet a1 (LLet LetStrict b1 x2)+                   $ XLet a1 (LLet b1 x2)                              (anonymizeX x3'))]  
DDC/Core/Transform/Forward.hs view
@@ -2,6 +2,8 @@ -- | Float let-bindings with a single use forward into their use-sites. module DDC.Core.Transform.Forward         ( ForwardInfo   (..)+        , FloatControl  (..)+        , Config(..)         , forwardModule         , forwardX) where@@ -10,8 +12,10 @@ import DDC.Core.Exp import DDC.Core.Module import DDC.Core.Simplifier.Base+import DDC.Core.Transform.Reannotate import DDC.Core.Fragment import DDC.Core.Predicates+import DDC.Core.Compounds import Data.Map                 (Map) import Control.Monad import Control.Monad.Writer	(Writer, runWriter, tell)@@ -24,52 +28,86 @@ -- | Summary of number of bindings floated. data ForwardInfo         = ForwardInfo-        { -- | Number of trivial @v1 = v2@ bindings inlined.-          infoSubsts   :: Int+        { -- | Number of bindings inspected.+          infoInspected :: !Int +          -- | Number of trivial @v1 = v2@ bindings inlined.+        , infoSubsts    :: !Int+           -- | Number of bindings floated forwards.-        , infoBindings :: Int }+        , infoBindings  :: !Int }         deriving Typeable   instance Pretty ForwardInfo where- ppr (ForwardInfo substs bindings)+ ppr (ForwardInfo inspected substs bindings)   =  text "Forward:"   <$> indent 4 (vcat-      [ text "Substitutions:  " <> int substs-      , text "Bindings:       " <> int bindings ])+      [ text "Total bindings inspected:      " <> int inspected+      , text "  Trivial substitutions made:  " <> int substs+      , text "  Bindings moved forward:      " <> int bindings ])   instance Monoid ForwardInfo where- mempty = ForwardInfo 0 0- mappend (ForwardInfo s1 b1)(ForwardInfo s2 b2)-        = ForwardInfo (s1 + s2) (b1 + b2)+ mempty = ForwardInfo 0 0 0+ mappend (ForwardInfo i1 s1 b1)(ForwardInfo i2 s2 b2)+        = ForwardInfo (i1 + i2) (s1 + s2) (b1 + b2)   -------------------------------------------------------------------------------+-- | Fine control over what should be floated.+data FloatControl+        = FloatAllow    -- ^ Allow binding to be floated, but don't require it.+        | FloatDeny     -- ^ Prevent a binding being floated, at all times.+        | FloatForce    -- ^ Force   a binding to be floated, at all times.+        deriving (Eq, Show)++data Config a n+        = Config+        { configFloatControl    :: Lets a n -> FloatControl+        , configFloatLetBody    :: Bool }++------------------------------------------------------------------------------- -- | Float let-bindings in a module with a single use forward into --   their use sites. forwardModule          :: Ord n-        => Profile n -> Module a n -> Module a n+        => Profile n    -- ^ Language profile+        -> Config a n+        -> Module a n +        -> TransformResult (Module a n) -forwardModule profile mm-        = fst   $ runWriter-                $ forwardWith profile Map.empty +forwardModule profile config mm+ = let  (mm', info)+         = runWriter+                $ forwardWith profile config Map.empty                  $ usageModule mm +        progress (ForwardInfo _ s f)+                = s + f > 0 +   in   TransformResult+         { result         = mm'+         , resultProgress = progress info+         , resultAgain    = False+         , resultInfo     = TransformInfo info }++ -- | Float let-bindings in an expression with a single use forward into --   their use-sites. forwardX :: Ord n-         => Profile n -> Exp a n -> TransformResult (Exp a n)-forwardX profile xx+         => Profile n   -- ^ Language profile.+         -> Config a n +         -> Exp a n                      +         -> TransformResult (Exp a n)++forwardX profile config xx  = let  (x',info) = runWriter-		  $ forwardWith profile Map.empty+		  $ forwardWith profile config Map.empty 		  $ usageX xx -        progress (ForwardInfo s _) -                = s > 0+        progress (ForwardInfo _ s f) +                = s + f > 0     in  TransformResult         { result	 = x'@@ -83,13 +121,14 @@  -- | Carry bindings forward and downward into their use-sites.  forwardWith          :: Ord n-        => Profile n-        -> Map n (Exp a n)+        => Profile n            -- ^ Language profile.+        -> Config a n+        -> Map n (Exp a n)      -- ^ Bindings currently being carried forward.         -> c (UsedMap n, a) n         -> Writer ForwardInfo (c a n)  instance Forward Module where- forwardWith profile bindings + forwardWith profile config bindings          (ModuleCore                 { moduleName            = name                 , moduleExportKinds     = exportKinds@@ -98,7 +137,7 @@                 , moduleImportTypes     = importTypes                 , moduleBody            = body }) -  = do	body' <- forwardWith profile bindings body+  = do	body' <- forwardWith profile config bindings body 	return ModuleCore 		{ moduleName            = name 		, moduleExportKinds     = exportKinds@@ -109,9 +148,9 @@   instance Forward Exp where- forwardWith profile bindings xx+ forwardWith profile config bindings xx   = {-# SCC forwardWith #-}-    let down    = forwardWith profile bindings +    let down    = forwardWith profile config bindings      in case xx of         XVar a u@(UName n)          -> case Map.lookup n bindings of@@ -127,33 +166,64 @@         XLam a b x      -> liftM    (XLam (snd a) b) (down x)         XApp a x1 x2    -> liftM2   (XApp (snd a))   (down x1) (down x2) -        XLet (UsedMap um, _) (LLet _mode (BName n _) x1) x2-         | isXLam x1 || isXLAM x1-         , Just usage     <- Map.lookup n um-         , [UsedFunction] <- filterUsedInCasts usage-	 -> do-                -- Record that we've moved this binding.-                tell mempty { infoBindings = 1 }-                x1'           <- down x1-                forwardWith profile (Map.insert n x1' bindings) x2+        -- Always float last let-binding into its use.+        --   let x = exp in x => exp+        XLet _ (LLet b x1) (XVar _ u)+         |  boundMatchesBind u b+         ,  configFloatLetBody config+         -> down x1 -	-- Always float atomic bindings (variables, constructors)-        XLet _ (LLet _mode b x1) x2-	 | isAtomX x1-	 -> do +        -- Always float atomic bindings (variables, constructors)+        XLet _ (LLet b x1) x2+         | isAtomX x1+         -> do                  -- Record that we've moved this binding.-                tell mempty { infoBindings = 1 }+                tell mempty { infoInspected = 1+                            , infoBindings  = 1 }                  -- Slow, but handles anonymous binders and shadowing                 down $ S.substituteXX b x1 x2 +        XLet (UsedMap um, a') lts@(LLet (BName n _) x1) x2+         -> do  +                let control    = configFloatControl config +                               $ reannotate snd lts++                let isFun      = isXLam x1 || isXLAM x1++                let isApplied+                     | Just usage       <- Map.lookup n um+                     , [UsedFunction]   <- filterUsedInCasts usage+                                        = True+                     | otherwise        = False++                let shouldFloat+                     = case control of+                        FloatDeny       -> False+                        FloatForce      -> True+                        FloatAllow      -> isFun && isApplied++                if shouldFloat +                 then do+                        -- Record that we've moved this binding.+                        tell mempty { infoInspected = 1+                                    , infoBindings  = 1 }++                        x1'             <- down x1+                        let bindings'   = Map.insert n x1' bindings+                        forwardWith profile config bindings' x2++                 else do        +                        tell mempty { infoInspected = 1}+                        liftM2 (XLet a') (down lts) (down x2)+         XLet (_, a') lts x     -         -> liftM2 (XLet a') (down lts) (down x)+         ->     liftM2 (XLet a') (down lts) (down x)          XCase a x alts  -> liftM2   (XCase (snd a)) (down x) (mapM down alts)         XCast a c x     -> liftM2   (XCast (snd a)) (down c) (down x)         XType t         -> return $ XType t-        XWitness w      -> return $ XWitness w+        XWitness w      -> return $ XWitness (reannotate snd w)   filterUsedInCasts :: [Used] -> [Used]@@ -163,20 +233,23 @@   instance Forward Cast where- forwardWith profile bindings xx-  = let down    = forwardWith profile bindings+ forwardWith profile config bindings xx+  = let down    = forwardWith profile config bindings     in case xx of         CastWeakenEffect eff    -> return $ CastWeakenEffect eff         CastWeakenClosure xs    -> liftM    CastWeakenClosure (mapM down xs)-        CastPurify w            -> return $ CastPurify w-        CastForget w            -> return $ CastForget w+        CastPurify w            -> return $ CastPurify (reannotate snd w)+        CastForget w            -> return $ CastForget (reannotate snd w)+        CastSuspend             -> return $ CastSuspend+        CastRun                 -> return $ CastRun   instance Forward Lets where- forwardWith profile bindings lts-  = let down    = forwardWith profile bindings+ forwardWith profile config bindings lts+  = let down    = forwardWith profile config bindings     in case lts of-        LLet mode b x   -> liftM (LLet mode b) (down x)+        LLet b x   +         -> liftM (LLet b) (down x)          LRec bxs                  -> liftM LRec@@ -190,6 +263,6 @@   instance Forward Alt where- forwardWith profile bindings (AAlt p x)-  = liftM (AAlt p) (forwardWith profile bindings x)+ forwardWith profile config bindings (AAlt p x)+  = liftM (AAlt p) (forwardWith profile config bindings x) 
DDC/Core/Transform/Inline.hs view
@@ -62,7 +62,7 @@                 _               -> inline get inside x      in case lts of-        LLet mode b x   -> LLet mode b (enter b x)+        LLet b x        -> LLet b (enter b x)         LRec bxs        -> LRec [(b, enter b x) | (b, x) <- bxs]         LLetRegions{}   -> lts         LWithRegion{}   -> lts
DDC/Core/Transform/Namify.hs view
@@ -98,23 +98,15 @@         return  $ mm { moduleBody = body' }  -instance Namify LetMode where- namify tnam xnam mm-  = case mm of-        LetStrict               -> return mm-        LetLazy Nothing         -> return mm-        LetLazy (Just w)        -> liftM (LetLazy . Just) $ namify tnam xnam w---instance Namify Witness where+instance Namify (Witness a) where  namify tnam xnam ww   = let down = namify tnam xnam     in case ww of-        WVar u          -> liftM  WVar  (rewriteX tnam xnam u)+        WVar  a u       -> liftM  (WVar  a) (rewriteX tnam xnam u)         WCon{}          -> return ww-        WApp  w1 w2     -> liftM2 WApp  (down w1) (down w2)-        WJoin w1 w2     -> liftM2 WJoin (down w1) (down w2)-        WType t         -> liftM  WType (down t)+        WApp  a w1 w2   -> liftM2 (WApp  a) (down w1) (down w2)+        WJoin a w1 w2   -> liftM2 (WJoin a) (down w1) (down w2)+        WType a t       -> liftM  (WType a) (down t)   instance Namify (Exp a) where@@ -138,12 +130,11 @@         XApp  a x1 x2             ->     liftM3 XApp     (return a) (down x1)  (down x2) -        XLet  a (LLet mode b x1) x2-         -> do  mode'           <- down mode-                x1'             <- namify tnam xnam x1+        XLet  a (LLet b x1) x2+         -> do  x1'             <- namify tnam xnam x1                 (xnam', b')     <- pushX  tnam xnam b                 x2'             <- namify tnam xnam' x2-                return $ XLet a (LLet mode' b' x1') x2'+                return $ XLet a (LLet b' x1') x2'          XLet a (LRec bxs) x2          -> do  let (bs, xs)    = unzip bxs@@ -183,18 +174,16 @@  namify tnam xnam cc   = let down = namify tnam xnam     in case cc of-        CastWeakenEffect  eff-         -> liftM CastWeakenEffect  (down eff)+        CastWeakenEffect  eff   -> liftM CastWeakenEffect  (down eff)          CastWeakenClosure xs              -> do  xs' <- mapM down xs                 return $ CastWeakenClosure xs' -        CastPurify w-         -> liftM CastPurify (down w)--        CastForget w-         -> liftM CastForget (down w)+        CastPurify w            -> liftM CastPurify (down w)+        CastForget w            -> liftM CastForget (down w)+        CastSuspend             -> return CastSuspend+        CastRun                 -> return CastRun   -- | Rewrite level-1 anonymous binders.
DDC/Core/Transform/Prune.hs view
@@ -13,7 +13,7 @@ import DDC.Core.Analysis.Usage import DDC.Core.Simplifier.Base import DDC.Core.Transform.Reannotate-import DDC.Core.Transform.TransformX+import DDC.Core.Transform.TransformUpX import DDC.Core.Fragment import DDC.Core.Check import DDC.Core.Module@@ -69,8 +69,8 @@          -- If the language fragment has untracked effects then we can't do          -- the prune transform because we risk dropping statements with global          -- effects.-         | featuresUntrackedEffects -                $ profileFeatures profile+         | not $ featuresTrackedEffects+               $ profileFeatures profile          = mm           | otherwise@@ -144,7 +144,7 @@  pruneTrans _ _ xx  = case xx of-        XLet a@(usedMap, antec) (LLet _mode b x1) x2+        XLet a@(usedMap, antec) (LLet b x1) x2          | isUnusedBind b usedMap          , isContainedEffect $ annotEffect antec          -> do      
DDC/Core/Transform/Rewrite.hs view
@@ -171,9 +171,9 @@          =      rewrites env x args  -        goLets (LLet lm b e) ws +        goLets (LLet b e) ws           = do   e' <- down ws e -                return $ LLet lm b e'+                return $ LLet b e'          goLets (LRec bs) ws           = do   bs'     <- mapM (down ws) $ map snd bs@@ -202,7 +202,7 @@ --       x = box ^0 --   in ... ---goDefHoles rules a l@(LLet LetStrict let_bind def) e env down+goDefHoles rules a l@(LLet let_bind def) e env down  | (((sub, []), name, RewriteRule { ruleBinds = bs, ruleLeft = hole }):_)         <- checkHoles rules def env @@ -233,13 +233,13 @@          -- replace 'def' with LHS-HOLE[sub => ^n]         anons   = zipWith (\(b,_) i -> (b, XVar a (UIx i))) bas' [0..]-        lets    = map (\(b,v) -> LLet LetStrict b v) values+        lets    = map (\(b,v) -> LLet b v) values          def'    = S.substituteXArgs basK                 $ S.substituteXArgs anons hole          let_bind'  = S.substituteTs basK' let_bind-        lets'      = lets ++ [LLet LetStrict let_bind' def']+        lets'      = lets ++ [LLet let_bind' def']          -- lift e by (length bas)         depth   = case let_bind of@@ -402,7 +402,7 @@         anons   = zipWith (\(b,_) i -> (b, XVar a (UIx i))) as' [0..]         values  = map     (\(b,v) ->   (BAnon (substT bs' $ T.typeOfBind b), v))                            (reverse as')-        lets    = map (\(b,v) -> LLet LetStrict b v) values+        lets    = map (\(b,v) -> LLet b v) values     in   (bs' ++ anons, lets) 
DDC/Core/Transform/Rewrite/Env.hs view
@@ -93,7 +93,7 @@         extend' b (r:rs') = (b:r) : rs'         extend' b []	   = [[b]] -extendLets (LLet _ b def) env+extendLets (LLet b def) env  = insertDef b (Just def') (liftValue b env)  where  def' = case b of 	         BAnon{} -> L.liftX 1 def
DDC/Core/Transform/Rewrite/Match.hs view
@@ -80,7 +80,8 @@ 	match m' bs x12 x22  match m bs (XCast _ c1 x1) (XCast _ c2 x2)- | eqCast c1 c2	= match m bs x1 x2+ | eqCast c1 c2	+ = match m bs x1 x2  match (xs, tys) bs (XType t1) (XType t2)  = do	tys' <- matchT t1 t2 bs tys@@ -93,20 +94,25 @@  = Nothing  +eqCast :: Ord n => Cast a n -> Cast a n -> Bool eqCast lc rc   = clean lc == clean rc  where  clean c -         = case c of-                CastWeakenEffect  eff -> CastWeakenEffect  $ T.anonymizeT eff-                CastWeakenClosure clo -> CastWeakenClosure $ map cleanX clo-                CastPurify        wit -> CastPurify wit-                CastForget        wit -> CastForget wit+         = T.reannotate (const ())+         $ case c of+                CastWeakenEffect  eff   -> CastWeakenEffect  $ T.anonymizeT eff+                CastWeakenClosure clo   -> CastWeakenClosure $ map T.anonymizeX clo+                CastPurify        wit   -> CastPurify        wit+                CastForget        wit   -> CastForget wit+                CastSuspend             -> CastSuspend+                CastRun                 -> CastRun -        cleanX -         = T.anonymizeX . T.reannotate (const ()) +eqWit  :: Ord n => Witness a n -> Witness a n -> Bool eqWit lw rw -        = lw == rw+        =  T.reannotate (const ()) lw +        == T.reannotate (const ()) rw+  -- Types ---------------------------------------------------------------------- type VarSet n = Set.Set n
DDC/Core/Transform/Rewrite/Parser.hs view
@@ -19,13 +19,14 @@ 	x -} -- | Parse a rewrite rule.-pRule	:: Ord n => Parser n (R.RewriteRule () n)-pRule- = do	bs	 <- pRuleBinders-	(cs,lhs) <- pRuleCsLhs-	hole	 <- pRuleHole+pRule	:: Ord n +        => Context -> Parser n (R.RewriteRule P.SourcePos n)+pRule c+ = do	bs	 <- pRuleBinders c+	(cs,lhs) <- pRuleCsLhs c+	hole	 <- pRuleHole c 	pTok KEquals-	rhs	 <- pExp+	rhs	 <- pExp c  	return $ R.mkRewriteRule bs cs lhs hole rhs @@ -41,44 +42,53 @@         ; -} -- | Parse many rewrite rules.-pRuleMany	:: Ord n => Parser n [(n,R.RewriteRule () n)]-pRuleMany+pRuleMany	+        :: Ord n +        => Context -> Parser n [(n,R.RewriteRule P.SourcePos n)]+pRuleMany c  = P.many (do         n <- pName-        r <- pRule+        r <- pRule c         pTok KSemiColon         return (n,r))  -pRuleBinders :: Ord n => Parser n [(R.BindMode,Bind n)]-pRuleBinders+pRuleBinders +        :: Ord n +        => Context -> Parser n [(R.BindMode,Bind n)]++pRuleBinders c  = P.choice- [ do	bs <- P.many1 pBinders+ [ do	bs <- P.many1 (pBinders c) 	pTok KDot 	return $ concat bs  , return []  ]  -pRuleCsLhs :: Ord n => Parser n ([Type n], Exp () n)-pRuleCsLhs+pRuleCsLhs +        :: Ord n +        => Context -> Parser n ([Type n], Exp P.SourcePos n)+pRuleCsLhs c  = P.choice  [ do	cs <- P.many1 $ P.try (do-		c <- pTypeApp+		cc <- pTypeApp c 		pTok KArrowEquals-		return c)-	lhs <- pExp+		return cc)+	lhs <- pExp c 	return (cs,lhs)- , do	lhs <- pExp+ , do	lhs <- pExp c 	return ([],lhs)  ]  -pRuleHole :: Ord n => Parser n (Maybe (Exp () n))-pRuleHole+pRuleHole +        :: Ord n +        => Context -> Parser n (Maybe (Exp P.SourcePos n))+pRuleHole c  = P.optionMaybe  $ do	pTok KBraceBra-	e <- pExp+	e <- pExp c 	pTok KBraceKet 	return e @@ -89,26 +99,29 @@ --       [BIND1 BIND2 .. BINDN : TYPE] --   or  (BIND : TYPE) ---pBinders :: Ord n => Parser n [(R.BindMode, Bind n)]-pBinders+pBinders +        :: Ord n +        => Context -> Parser n [(R.BindMode, Bind n)]+pBinders c  = P.choice- [ pBindersBetween R.BMSpec      (pTok KSquareBra) (pTok KSquareKet)- , pBindersBetween (R.BMValue 0) (pTok KRoundBra)  (pTok KRoundKet)+ [ pBindersBetween c R.BMSpec      (pTok KSquareBra) (pTok KSquareKet)+ , pBindersBetween c (R.BMValue 0) (pTok KRoundBra)  (pTok KRoundKet)  ]   pBindersBetween          :: Ord n -        => R.BindMode +        => Context+        -> R.BindMode          -> Parser n ()          -> Parser n ()          -> Parser n [(R.BindMode,Bind n)] -pBindersBetween bm bra ket+pBindersBetween c bm bra ket  = do	bra         bs      <- P.many1 pBinder         pTok KColon-        t       <- pType+        t       <- pType c         ket         return $ map (mk t) bs  where mk t b = (bm,T.makeBindFromBinder b t)
DDC/Core/Transform/Rewrite/Rule.hs view
@@ -16,7 +16,7 @@ where import DDC.Core.Transform.Rewrite.Error import DDC.Core.Transform.Reannotate-import DDC.Core.Transform.TransformX+import DDC.Core.Transform.TransformUpX import DDC.Core.Exp import DDC.Core.Pretty                          () import DDC.Core.Collect@@ -305,8 +305,8 @@         -> Type n       -- ^ The constraint type to check.         -> Either (Error a n) (Kind n) -checkConstraint defs kenv tt- = case T.checkType (C.configPrimDataDefs defs) kenv tt of+checkConstraint config kenv tt+ = case T.checkType config kenv tt of         Left _err               -> Left $ ErrorBadConstraint tt         Right k          | T.isWitnessType tt   -> return k@@ -392,7 +392,7 @@          $  [XVar a u                  | u <- Set.toList $ daLeft `Set.difference` daRight ] -         ++ [XWitness (WVar u)+         ++ [XWitness (WVar a u)                 | u <- Set.toList $ wiLeft `Set.difference` wiRight ]           ++ [XType (TVar u)@@ -414,8 +414,7 @@   remove kenv _tenv x     | XType et   <- x-   , Right k    <- T.checkType (C.configPrimDataDefs config)-                               kenv et+   , Right k    <- T.checkType config kenv et    , T.isEffectKind k    = XType $ T.tBot T.kEffect 
DDC/Core/Transform/Snip.hs view
@@ -1,16 +1,41 @@  -- | Snip out nested applications. module DDC.Core.Transform.Snip-        (Snip(..))+        ( Snip   (..)+        , Config (..)+        , configZero) where import DDC.Core.Analysis.Arity import DDC.Core.Module import DDC.Core.Exp import DDC.Core.Compounds+import DDC.Core.Predicates import qualified DDC.Core.Transform.LiftX       as L import qualified DDC.Type.Compounds             as T  +-------------------------------------------------------------------------------+-- | Snipper configuration.+data Config +        = Config+        { -- | Introduce new bindings for over-applied functions.+          configSnipOverApplied :: Bool+        +          -- | Ensure the body of a let-expression is a variable.+        , configSnipLetBody     :: Bool+        }+++-- | Snipper configuration with all flags set to False.+configZero :: Config+configZero+        = Config+        { configSnipOverApplied = False+        , configSnipLetBody     = False }+++-------------------------------------------------------------------------------+-- | Class of things that can have things snipped out of them. class Snip (c :: * -> *) where   -- | Snip out nested applications as anonymous bindings.@@ -19,54 +44,50 @@  --      f (g x) (h y)  --  ==> let ^ = g x in ^ = h y in f ^1 ^0  -- @- snip   :: Ord n -        => Bool         -- ^ Introduce extra bindings for over-applied functions.-        -> c n -        -> c n+ snip   :: Ord n => Config -> c n -> c n   instance Snip (Module a) where- snip bOver mm-  = {-# SCC "snip[Module]" #-}-    let arities = aritiesOfModule mm-        body'   = snipX bOver arities (moduleBody mm) []+ snip config mm+  = let arities = aritiesOfModule mm+        body'   = snipX config arities (moduleBody mm) []     in  mm { moduleBody = body'  }   instance Snip (Exp a) where- snip bOver x -  = {-# SCC "snip[Exp]" #-}-    snipX bOver emptyArities x []+ snip config x +  = snipX config emptyArities x []   -- | Convert an expression into A-normal form.-snipX -        :: Ord n-        => Bool           -- ^ Introduce extra bindings for over-applied functions.+snipX   :: Ord n+        => Config         -> Arities n      -- ^ Arities of functions in environment.         -> Exp a n        -- ^ Expression to transform.         -> [(Exp a n, a)] -- ^ Arguments being applied to current expression.         -> Exp a n -snipX bOver arities x args+snipX config arities x args         -- For applications, remember the argument that the function is being          --   applied to, and decend into the function part.         --   This unzips application nodes as we decend into the tree.         | XApp a fun arg        <- x-        = snipX bOver arities fun $ (snipX bOver arities arg [], a) : args+        = snipX  config arities fun +                $ (snipX config arities arg [], a) : args          -- Some non-application node with no arguments.         | null args-        = enterX bOver arities x+        = enterX config arities x          -- Some non-application node being applied to arguments.         | otherwise-        = buildNormalisedApp bOver arities (enterX bOver arities x) args+        = let   x'      = enterX config arities x+          in    buildNormalisedApp config arities x' args  -- Enter into a non-application.-enterX bOver arities xx+enterX config arities xx  = let  down ars e -         = snipX bOver (extendsArities arities ars) e []+         = snipX config (extendsArities arities ars) e []     in case xx of         -- The snipX function shouldn't have called us with an XApp.@@ -87,10 +108,11 @@          -> XLam a b (down [(b,0)] e)          -- non-recursive let-        XLet a (LLet m b x1) x2-         -> let x1' = down [] x1-                x2' = down [(b, arityOfExp' x1')] x2-            in  XLet a (LLet m b x1') x2'+        XLet a (LLet b x1) x2+         -> let x1'     = down [] x1+                x2'     = snipLetBody config a+                        $ down [(b, arityOfExp' x1')] x2+            in  XLet a (LLet b x1') x2'          -- recursive let         XLet a (LRec lets) x2@@ -98,17 +120,19 @@                 xs      = map snd lets                  ars     = zip bs (map arityOfExp' xs)                  xs'     = map (down ars) xs-                x2'     = down ars x2+                x2'     = snipLetBody config a $ down ars x2             in  XLet a (LRec $ zip bs xs') x2'           -- letregion, just make sure we record bindings with dummy val.         XLet a (LLetRegions b bs) x2-         -> let ars = zip bs (repeat 0) -            in  XLet a (LLetRegions b bs) (down ars x2)+         -> let ars     = zip bs (repeat 0)+                x2'     = snipLetBody config a $ down ars x2+            in  XLet a (LLetRegions b bs) x2'          -- withregion-        XLet a (LWithRegion b) z2-         -> XLet a (LWithRegion b) (down [] z2)+        XLet a (LWithRegion b) x2+         -> let x2'     = snipLetBody config a $ down [] x2+            in  XLet a (LWithRegion b) x2'          -- case         -- Split out non-atomic discriminants into their own bindings.@@ -121,11 +145,14 @@           | otherwise          -> let e'      = down [] e-                alts'   = [AAlt pat (down (aritiesOfPat pat) ae) | AAlt pat ae <- alts]+                alts'   = [AAlt pat (down (aritiesOfPat pat) ae) +                                | AAlt pat ae <- alts]+                xBody'  = snipLetBody config a+                        $ XCase a (XVar a $ UIx 0)+                                  (map (L.liftX 1) alts') -            in   XLet a (LLet LetStrict (BAnon (T.tBot T.kData)) e')-                        (XCase a (XVar a $ UIx 0) -                                 (map (L.liftX 1) alts'))+            in  XLet a (LLet (BAnon (T.tBot T.kData)) e')+                       xBody'          -- cast         XCast a c e@@ -134,18 +161,18 @@  -- | Build an A-normalised application of some functional expression to  --   its arguments. Atomic arguments are applied directly, while ---   on-atomic arguments are bound via let-expressions, then the+--   non-atomic arguments are bound via let-expressions, then the --   associated let-bound variable is passed to the function. buildNormalisedApp          :: Ord n-        => Bool            -- ^ Introduce extra bindings for over-applied functions.+        => Config          -- ^ Snipper config.         -> Arities n	   -- ^ environment, arities of bound variables         -> Exp a n	   -- ^ function         -> [(Exp a n,a)]   -- ^ arguments being applied to current expression         -> Exp a n -buildNormalisedApp _bOver _  f0 [] = f0-buildNormalisedApp bOver arities f0 args@( (_, annot) : _)+buildNormalisedApp _ _  f0 [] = f0+buildNormalisedApp config arities f0 args@( (_, annot) : _)  = make annot f0 args  where         tBot' = T.tBot T.kData@@ -164,13 +191,14 @@           -- The function part is already atomic.          | isAtom xFun-         = buildNormalisedFunApp bOver a f0Arity xFun xsArgs+         = buildNormalisedFunApp config a f0Arity xFun xsArgs           -- The function part is not atomic,           --  so we need to add an outer-most let-binding for it.          | otherwise-         = XLet a (LLet LetStrict (BAnon tBot') xFun)-                  (buildNormalisedFunApp bOver a f0Arity +         = XLet a (LLet (BAnon tBot') xFun)+                  (snipLetBody config a+                    $ buildNormalisedFunApp config a f0Arity                                 (XVar a (UIx 0))                                 [ (L.liftX 1 x, a') | (x, a') <- xsArgs]) @@ -184,14 +212,14 @@ --   wants the function part to be normalised as well. buildNormalisedFunApp         :: Ord n-        => Bool           -- ^ Introduce extra bindings for over-applied functions.+        => Config         -- ^ Snipper configuration.         -> a              -- ^ Annotation to use.         -> Int            -- ^ Arity of the function part.         -> Exp a n        -- ^ Function part.         -> [(Exp a n, a)] -- ^ Arguments to apply         -> Exp a n -buildNormalisedFunApp bOver an funArity xFun xsArgs+buildNormalisedFunApp config an funArity xFun xsArgs  = let  tBot' = T.tBot T.kData          -- Split arguments into the already atomic ones,@@ -228,12 +256,13 @@          -- If the function is over-applied then create an intermediate          -- binding that saturates it, then apply the extra arguments          -- separately.-         | bOver+         | configSnipOverApplied config          , length xsArgs' > funArity          , (xsSat, xsOver)      <- splitAt funArity xsArgs'-         = XLet an (LLet LetStrict (BAnon tBot') +         = XLet an (LLet (BAnon tBot')                          (makeXAppsWithAnnots xFun' xsSat))-                   (makeXAppsWithAnnots +                   (snipLetBody config an+                    $ makeXAppsWithAnnots                          (XVar an (UIx 0))                          [ (L.liftX 1 x, a) | (x, a) <- xsOver ]) @@ -246,10 +275,12 @@          -- Wrap the function application in the let-bindings         -- for its arguments.-   in   foldr (\(x, a) x' -> XLet a x x')-                xFunApps-                [ (LLet LetStrict (BAnon tBot') x, a) -                        | (x, a) <- xsLets' ]+   in   case xsLets' of+         []     -> xFunApps+         _      -> foldr (\(x, a) x' -> XLet a x x')+                        (snipLetBody config an xFunApps)+                        [ (LLet (BAnon tBot') x, a) +                                | (x, a) <- xsLets' ]   -- | Sort function arguments into either the atomic ones, @@ -274,9 +305,24 @@          = (XVar a (UIx n), a, False, Just xArg)  : go (n + 1) xsArgs  +-- | If `snipLetResults` is set and this is not an atomic expression then+--   introduce a new binding for it.+snipLetBody :: Config -> a -> Exp a n -> Exp a n+snipLetBody config a xx+        | configSnipLetBody config+        , not (isAtom xx)+        , not (isXLet xx)+        = let  tBot'   = T.tBot T.kData+          in   XLet a  (LLet (BAnon tBot') xx)+                       (XVar a (UIx 0))+        +        | otherwise+        = xx++ -- | Check if an expression needs a binding, or if it's simple enough to be --   applied as-is.-isAtom :: Ord n => Exp a n -> Bool+isAtom :: Exp a n -> Bool isAtom xx  = case xx of         XVar{}          -> True
+ DDC/Core/Transform/Thread.hs view
@@ -0,0 +1,412 @@++-- | Thread a state token through calls to given functions.+--+--   ASSUMPTIONS:+--   * Program is a-normalized and fully named.+--+module DDC.Core.Transform.Thread+        ( Thread (..)+        , Config (..)+        , injectStateType)+where+import DDC.Core.Compounds+import DDC.Core.Module+import DDC.Core.Exp+import DDC.Base.Pretty+import DDC.Core.Transform.Reannotate+import DDC.Core.Check           (AnTEC (..))+import DDC.Type.Env             (KindEnv, TypeEnv)+import qualified DDC.Type.Env   as Env+import qualified DDC.Core.Check as Check+++-------------------------------------------------------------------------------+-- | Configuration for the Thread transform.+data Config a n+        = Config+        { -- | Config for the type checker.+          --   We need to reconstruct the type of the result of stateful+          --   functions when bundling them into the tuple that holds the +          --   state token.+          configCheckConfig     :: Check.Config n++          -- | Function to decide which top-level bindings are stateful and+          --   need the state token threaded through them. If the binding with+          --   the given name is stateful then the function should return the+          --   new type for the binding that accepts and returns the state token.+        , configThreadMe        :: n -> Type n -> Maybe (Type n) ++          -- | Type of the state token to use.+        , configTokenType       :: Type n++          -- | Type that represents a missing value.+          --   If a stateful function returns a void then our thread transform+          --   rewrites it to return the state token, instead of a tuple+          --   that contains the token as well as a void value.+        , configVoidType        :: Type n++          -- | Wrap a type with the world token.+          --   eg change Int to (World#, Int)+        , configWrapResultType  :: Type n -> Type n++          -- | Wrap a result expression with the state token.+          --   The function is given the types of the world token and result,+          --   then the expressions for the same.+        , configWrapResultExp   :: Exp (AnTEC a n) n  -> Exp (AnTEC a n) n +                                -> Exp a n++          -- | Make a pattern which binds the world argument+          --   from a threaded primop.+        , configThreadPat       :: n -> Maybe (Bind n -> [Bind n] -> Pat n)+        }+++-- | Class of things that can have a state token threaded through them.+class Thread (c :: * -> * -> *) where+ thread :: (Ord n, Show n, Pretty n)+        => Config a n +        -> KindEnv n -> TypeEnv n +        -> c (AnTEC a n) n     +        -> c a n+++instance Thread Module where+ thread config kenv tenv mm+  = let body'   = threadModuleBody config kenv tenv (moduleBody mm) +    in  mm { moduleBody = body' }+++-- | Keeps track of which recursive functions we're inside.+data Context n+        -- | We're in the body of an effectful recursive function.+        = ContextRec n++        -- | This effectful function in the context had a world token threaded+        --   through it, but we're not in its body.+        | ContextFun n+        deriving Eq+++-- Module ---------------------------------------------------------------------+-- | Thread state token though a module body.+--   We assume every top-level binding is a stateful function+--   that needs to accept and return the state token.+threadModuleBody +        :: (Ord n, Show n, Pretty n)+        => Config a n +        -> KindEnv n -> TypeEnv n+        -> Exp (AnTEC a n) n   +        -> Exp a n++threadModuleBody config kenv tenv xx+ = case xx of+        XLet a lts x+         -> let lts'       = threadTopLets    config kenv tenv lts+                (bks, bts) = bindsOfLets lts+                kenv'      = Env.extends bks kenv+                tenv'      = Env.extends bts tenv+                x'         = threadModuleBody config kenv' tenv' x+            in  XLet (annotTail a) lts' x'++        _ -> reannotate annotTail xx+++-- | Thread state token through some top-level bindings in a module.+threadTopLets    +        :: (Ord n, Show n, Pretty n)+        => Config a n +        -> KindEnv n -> TypeEnv n+        -> Lets (AnTEC a n) n  +        -> Lets a n++threadTopLets config kenv tenv lts+ = case lts of+        LLet b x+         -> let (b', x')  = threadTopBind config [] kenv tenv b x+            in  LLet b' x'++        LRec bxs+         -> let tenv'     =   Env.extends (map fst bxs) tenv+                bxs'      = [ threadTopBind config [ContextRec n] kenv tenv' b x +                                | (b, x) <- bxs+                                , let BName n _ = b ]+            in  LRec bxs'++        _ -> reannotate annotTail lts+++-- TopBind ------------------------------------------------------------------+-- | Thread state token into a top-level binding.+--   We assume every top-level binding is stateful function that needs to+--   accept and return the state token.+--+--   We inject the world type into the type of the function and then call+--   threadBind which will add the actual lambda for the new argument.+--+threadTopBind+        :: (Ord n, Show n, Pretty n)+        => Config a n+        -> [Context n]+        -> KindEnv n -> TypeEnv n+        ->  Bind n   -> Exp (AnTEC a n) n+        -> (Bind n,     Exp a n)++threadTopBind config context kenv tenv b xBody+ = let  tBind   = typeOfBind b+        tBind'  = injectStateType config tBind+        b'      = replaceTypeOfBind tBind' b+        tenv'   = Env.extend b' tenv+        tsArgs  = fst $ takeTFunAllArgResult tBind'+   in   ( b'+        , threadProc config context kenv tenv' xBody tsArgs)+++-- Arg ------------------------------------------------------------------------+-- | Thread state token into an argument expression.+--   If it is a syntactic function then we assume the function is stateful+--   and needs the state token added, otherwise return it unharmed.+threadArg +        :: (Ord n, Show n, Pretty n)+        => Config a n+        -> [Context n]+        -> KindEnv n -> TypeEnv n+        -> Type n    -> Exp (AnTEC a n) n+        -> Exp a n++threadArg config context kenv tenv t xx+ = case xx of+        XLam{}  -> threadProcArg config context kenv tenv t xx+        XLAM{}  -> threadProcArg config context kenv tenv t xx+        _       -> reannotate annotTail xx++threadProcArg config context kenv tenv t xx+ = let  tsArgs  = fst $ takeTFunAllArgResult t+   in   threadProc config context kenv tenv xx tsArgs+++-- Proc -----------------------------------------------------------------------+-- | Thread world token into the body of a stateful function (procedure).+threadProc+        :: (Ord n, Show n, Pretty n)+        => Config a n+        -> [Context n]+        -> KindEnv n -> TypeEnv n+        -> Exp (AnTEC a n) n    -- Whole expression, including lambdas.+        -> [Type n]             -- Types of function parameters.+        -> Exp a n++-- We're out of parameters. +--  Now thread into the statements in the function body.+threadProc config context kenv tenv xx []+ = threadProcBody config context kenv tenv xx++-- We're still decending past all the lambdas.+--  When we get to the inner-most one then add the state parameter.+threadProc config context kenv tenv xx (t : tsArgs)+ = case xx of+        XLAM a b x+          -> let kenv'  = Env.extend b kenv+                 x'     = threadProc config context kenv' tenv x tsArgs+             in  XLAM (annotTail a) b x'++        XLam a b x      +          -> let tenv'  = Env.extend b tenv+                 x'     = threadProc config context kenv tenv' x tsArgs+             in  XLam (annotTail a) b x'++        -- Inject a new lambda to bind the state parameter.+        _ |  Just a     <- takeAnnotOfExp xx+          ,  t == configTokenType config +          -> let b'     = BAnon (configTokenType config)+                 tenv'  = Env.extend b' tenv+                 x'     = threadProc config context kenv tenv' xx tsArgs+             in  XLam (annotTail a) b' x'++        -- We've decended past all the lambdas,+        -- so now thread into the procedure body.+        _ -> threadProcBody config context kenv tenv xx+++-- | Thread world token into the body of a procedure,+--   after we've decended past all the lambdas.+threadProcBody +        :: (Ord n, Show n, Pretty n)+        => Config a n +        -> [Context n]+        -> KindEnv n -> TypeEnv n+        -> Exp (AnTEC a n) n   +        -> Exp a n++threadProcBody config context kenv tenv xx+ = case xx of+ +        -- Recursive let bindings in a procedure body.+        -- These will be local loops.+        XLet a (LRec bxs) x2+         -> let bxs'    = [threadTopBind config +                                (context ++ [ContextRec n]) +                                kenv tenv b x+                                | (b, x)        <- bxs +                                , let BName n _ = b ]++                tenv'   = Env.extends (map fst bxs) tenv+++                x2'     = threadProcBody config +                                (context ++ [ContextFun n +                                                | (b, _x)  <- bxs+                                                , let BName n _ = b ])+                                kenv tenv' x2+            in  XLet (annotTail a) (LRec bxs') x2'++        -- A statement in the procedure body.+        XLet _ (LLet b x) x2+         |  Just (XVar a u, xsArgs) <- takeXApps x+         ,  Just n       <- takeNameOfBound u+         ,  Just tOld    <- Env.lookup u tenv+         ,  Just tNew    <- configThreadMe  config n tOld+         ,  Just mkPat   <- configThreadPat config n+         -> let +                tWorld  = configTokenType config++                -- Add world token as final argument +                xsArgs' = xsArgs ++ [XVar a (UIx 0)]++                -- Thread into possibly higher order arguments.+                tsArgs   = fst $ takeTFunAllArgResult tNew+                xsArgs'' = zipWith (threadArg config context kenv tenv) tsArgs xsArgs'++                -- Build the final expression.+                u'      = replaceTypeOfBound tNew u+                x'      = xApps (annotTail a) (XVar (annotTail a) u') xsArgs''++                -- Thread into let-expression body.+                tenv'   = Env.extend b tenv+                x2'     = threadProcBody config context kenv tenv' x2+                pat'    = mkPat (BAnon tWorld) [b]+            in  XCase (annotTail a) x' [AAlt pat' x2']+++        -- Let bound effectful function.+        -- Needs to be converted to a 'case'.+        XLet a (LLet b x1) x2+         | Just (XVar _ (UName n), _xsArgs) <- takeXApps x1+         , elem (ContextFun n) context+         , Just mkPat   <- configThreadPat config n+         -> let +                tWorld  = configTokenType config+                a'      = annotTail a+                x1'     = XApp a' (reannotate annotTail x1) (XVar a' (UIx 0))+                x2'     = threadProcBody config context kenv tenv x2+                pat'    = mkPat (BAnon tWorld) [b]++            in  XCase (annotTail a) x1' [AAlt pat' x2']+++        -- A pure binding that doesn't need the token.+        XLet a lts x+         -> let (bks, bts) = bindsOfLets lts+                kenv'   = Env.extends bks kenv+                tenv'   = Env.extends bts tenv+                lts'    = reannotate annotTail lts+                x'      = threadProcBody config context kenv' tenv' x+            in  XLet (annotTail a) lts' x'+++        -- Case of an effectful function.+        XCase a xScrut [AAlt (PData _dc bs) xBody]+         | Just ((XVar _ (UName n), _xsArgs)) <- takeXApps xScrut+         , elem (ContextFun n) context+         , Just mkPat   <- configThreadPat config n+         -> let +                a'      = annotTail a+                tWorld  = configTokenType config+                xScrut' = XApp a' (reannotate annotTail xScrut) (XVar a' (UIx 0))+                pat'    = mkPat (BAnon tWorld) bs+                alt'    = threadAlt config context kenv tenv +                                (AAlt pat' xBody)++            in  XCase (annotTail a) xScrut' [alt']+++        -- Pure case. +        XCase a x alts+         -> let alts' = map (threadAlt config context kenv tenv) alts+                x'    = reannotate annotTail x+            in  XCase (annotTail a) x' alts'++        -- We shouldn't see these things in a proc body.+        XLAM{}          -> error "ddc-core-simpl.Thread: unexpected XLAM"+        XLam{}          -> error "ddc-core-simpl.Thread: unexpected XLam"+        XCast{}         -> error "ddc-core-simpl.Thread: unexpected cast."+        XType t         -> XType t+        +        XWitness w      +         -> XWitness (reannotate annotTail w)++        -- Tailcalls+        XApp a _ _+         | Just ((XVar _ (UName n), _xsArgs)) <- takeXApps xx+         , elem (ContextRec n) context+         -> let a'      = annotTail a+            in  XApp a' (reannotate annotTail xx)+                        (XVar a' (UIx 0))+++        -- For XVar, XCon, XApp as result value of function.+        _+         -- Otherwise wrap the returned value with a tuple holding+         -- the world.+         | otherwise+         -> let Just a  = takeAnnotOfExp xx+                a'      = AnTEC (configTokenType config) +                                (tBot kEffect) +                                (tBot kClosure)+                                (annotTail a)++                xWorld  = XVar a' (UIx 0)+                wrap    = configWrapResultExp config+            in  wrap xWorld xx++++-- | Thread world token into a case alternative+threadAlt +        :: (Ord n, Show n, Pretty n)+        => Config a n +        -> [Context n]+        -> KindEnv n -> TypeEnv n+        -> Alt (AnTEC a n) n   +        -> Alt a n++threadAlt config context kenv tenv (AAlt pat xx)+ = case pat of+        PDefault+         ->     AAlt pat (threadProcBody config context kenv tenv xx)++        PData _ bs+         -> let tenv' = Env.extends bs tenv+            in  AAlt pat (threadProcBody config context kenv tenv' xx)+ ++-------------------------------------------------------------------------------+-- | Inject the state token into the type of an effectful function.+--   Eg, change  ([a b : Data]. a -> b -> Int) +--          to   ([a b : Data]. a -> b -> World -> (World, Int)+injectStateType :: Eq n => Config a n -> Type n -> Type n+injectStateType config tt+ = let down = injectStateType config+   in case tt of+        TForall b x     +         -> TForall b (down x)++        TApp{}+         | (tsArg@(_ : _), tResult)     <- takeTFunArgResult tt+         -> let  tsArg'   = tsArg ++ [configTokenType config]+                 tResult' = injectStateType config tResult+            in   foldr tFunPE tResult' tsArg'++        _ | tt == configTokenType config -> tt+          | tt == configVoidType  config -> configTokenType config+          | otherwise                    -> configWrapResultType config tt+
+ DDC/Core/Transform/TransformDownX.hs view
@@ -0,0 +1,139 @@++-- | General purpose tree walking boilerplate.+module DDC.Core.Transform.TransformDownX+        ( TransformDownMX(..)+        , transformDownX+        , transformDownX')+where+import DDC.Core.Module+import DDC.Core.Exp+import DDC.Core.Compounds+import DDC.Type.Env             (KindEnv, TypeEnv)+import Data.Functor.Identity+import Control.Monad+import qualified DDC.Type.Env   as Env+++-- | Top-down rewrite of all core expressions in a thing.+transformDownX+        :: forall (c :: * -> * -> *) a n+        .  (Ord n, TransformDownMX Identity c)+        => (KindEnv n -> TypeEnv n -> Exp a n -> Exp a n)       +                        -- ^ The worker function is given the current kind and type environments.+        -> KindEnv n    -- ^ Initial kind environment.+        -> TypeEnv n    -- ^ Initial type environment.+        -> c a n        -- ^ Transform this thing.+        -> c a n++transformDownX f kenv tenv xx+        = runIdentity +        $ transformDownMX +                (\kenv' tenv' x -> return (f kenv' tenv' x)) +                kenv tenv xx+++-- | Like transformDownX, but without using environments.+transformDownX'+        :: forall (c :: * -> * -> *) a n+        .  (Ord n, TransformDownMX Identity c)+        => (Exp a n -> Exp a n)       +                        -- ^ The worker function is given the current+                        --      kind and type environments.+        -> c a n        -- ^ Transform this thing.+        -> c a n++transformDownX' f xx+        = transformDownX (\_ _ -> f) Env.empty Env.empty xx+++-------------------------------------------------------------------------------+class TransformDownMX m (c :: * -> * -> *) where+ -- | Top-down monadic rewrite of all core expressions in a thing.+ transformDownMX+        :: Ord n+        => (KindEnv n -> TypeEnv n -> Exp a n -> m (Exp a n))+                        -- ^ The worker function is given the current+                        --      kind and type environments.+        -> KindEnv n    -- ^ Initial kind environment.+        -> TypeEnv n    -- ^ Initial type environment.+        -> c a n        -- ^ Transform this thing.+        -> m (c a n)+++instance Monad m => TransformDownMX m Module where+ transformDownMX f kenv tenv !mm+  = do  x'    <- transformDownMX f kenv tenv $ moduleBody mm+        return  $ mm { moduleBody = x' }+++instance Monad m => TransformDownMX m Exp where+ transformDownMX f kenv tenv !xx+  = {-# SCC transformDownMX #-} +    f kenv tenv xx >>= \xx' -> +     case xx' of+        XVar{}          -> return xx'+        XCon{}          -> return xx'++        XLAM a b x1+         -> liftM3 XLAM (return a) (return b)+                        (transformDownMX f (Env.extend b kenv) tenv x1)++        XLam a b  x1    +         -> liftM3 XLam (return a) (return b) +                        (transformDownMX f kenv (Env.extend b tenv) x1)++        XApp a x1 x2    +         -> liftM3 XApp (return a) +                        (transformDownMX f kenv tenv x1) +                        (transformDownMX f kenv tenv x2)++        XLet a lts x+         -> do  lts'      <- transformDownMX f kenv tenv lts+                let kenv' = Env.extends (specBindsOfLets lts')   kenv+                let tenv' = Env.extends (valwitBindsOfLets lts') tenv+                x'        <- transformDownMX f kenv' tenv' x+                return  $ XLet a lts' x'+                +        XCase a x alts+         -> liftM3 XCase (return a)+                         (transformDownMX f kenv tenv x)+                         (mapM (transformDownMX f kenv tenv) alts)++        XCast a c x       +         -> liftM3 XCast+                        (return a) (return c)+                        (transformDownMX f kenv tenv x)++        XType _         -> return xx'+        XWitness _      -> return xx'+++instance Monad m => TransformDownMX m Lets where+ transformDownMX f kenv tenv xx+  = case xx of+        LLet b x+         -> liftM2 LLet (return b)+                        (transformDownMX f kenv tenv x)+        +        LRec bxs+         -> do  let (bs, xs) = unzip bxs+                let tenv'    = Env.extends bs tenv+                xs'          <- mapM (transformDownMX f kenv tenv') xs+                return       $ LRec $ zip bs xs'++        LLetRegions{}    -> return xx+        LWithRegion{}    -> return xx+++instance Monad m => TransformDownMX m Alt where+ transformDownMX f kenv tenv alt+  = case alt of+        AAlt p@(PData _ bsArg) x+         -> let tenv'   = Env.extends bsArg tenv+            in  liftM2  AAlt (return p) +                        (transformDownMX f kenv tenv' x)++        AAlt PDefault x+         ->     liftM2  AAlt (return PDefault)+                        (transformDownMX f kenv tenv x) +
+ DDC/Core/Transform/TransformUpX.hs view
@@ -0,0 +1,215 @@++-- | General purpose tree walking boilerplate.+module DDC.Core.Transform.TransformUpX+        ( TransformUpMX(..)+        , transformUpX+        , transformUpX'++          -- * Via the Simple AST+        , transformSimpleUpMX+        , transformSimpleUpX+        , transformSimpleUpX')+where+import DDC.Core.Module+import DDC.Core.Exp+import DDC.Core.Compounds+import DDC.Core.Transform.Annotate+import DDC.Core.Transform.Deannotate+import DDC.Type.Env             (KindEnv, TypeEnv)+import Data.Functor.Identity+import Control.Monad+import qualified DDC.Type.Env           as Env+import qualified DDC.Core.Exp.Simple    as S+++-- | Bottom up rewrite of all core expressions in a thing.+transformUpX+        :: forall (c :: * -> * -> *) a n+        .  (Ord n, TransformUpMX Identity c)+        => (KindEnv n -> TypeEnv n -> Exp a n -> Exp a n)       +                        -- ^ The worker function is given the current kind and type environments.+        -> KindEnv n    -- ^ Initial kind environment.+        -> TypeEnv n    -- ^ Initial type environment.+        -> c a n        -- ^ Transform this thing.+        -> c a n++transformUpX f kenv tenv xx+        = runIdentity +        $ transformUpMX +                (\kenv' tenv' x -> return (f kenv' tenv' x)) +                kenv tenv xx+++-- | Like transformUpX, but without using environments.+transformUpX'+        :: forall (c :: * -> * -> *) a n+        .  (Ord n, TransformUpMX Identity c)+        => (Exp a n -> Exp a n)       +                        -- ^ The worker function is given the current+                        --      kind and type environments.+        -> c a n        -- ^ Transform this thing.+        -> c a n++transformUpX' f xx+        = transformUpX (\_ _ -> f) Env.empty Env.empty xx+++-------------------------------------------------------------------------------+class TransformUpMX m (c :: * -> * -> *) where+ -- | Bottom-up monadic rewrite of all core expressions in a thing.+ transformUpMX+        :: Ord n+        => (KindEnv n -> TypeEnv n -> Exp a n -> m (Exp a n))+                        -- ^ The worker function is given the current+                        --      kind and type environments.+        -> KindEnv n    -- ^ Initial kind environment.+        -> TypeEnv n    -- ^ Initial type environment.+        -> c a n        -- ^ Transform this thing.+        -> m (c a n)+++instance Monad m => TransformUpMX m Module where+ transformUpMX f kenv tenv !mm+  = do  x'    <- transformUpMX f kenv tenv $ moduleBody mm+        return  $ mm { moduleBody = x' }+++instance Monad m => TransformUpMX m Exp where+ transformUpMX f kenv tenv !xx+  = (f kenv tenv =<<)+  $ case xx of+        XVar{}          -> return xx+        XCon{}          -> return xx++        XLAM a b x1+         -> liftM3 XLAM (return a) (return b)+                        (transformUpMX f (Env.extend b kenv) tenv x1)++        XLam a b  x1    +         -> liftM3 XLam (return a) (return b) +                        (transformUpMX f kenv (Env.extend b tenv) x1)++        XApp a x1 x2    +         -> liftM3 XApp (return a) +                        (transformUpMX f kenv tenv x1) +                        (transformUpMX f kenv tenv x2)++        XLet a lts x+         -> do  lts'      <- transformUpMX f kenv tenv lts+                let kenv' = Env.extends (specBindsOfLets lts')   kenv+                let tenv' = Env.extends (valwitBindsOfLets lts') tenv+                x'        <- transformUpMX f kenv' tenv' x+                return  $ XLet a lts' x'+                +        XCase a x alts+         -> liftM3 XCase (return a)+                         (transformUpMX f kenv tenv x)+                         (mapM (transformUpMX f kenv tenv) alts)++        XCast a c x       +         -> liftM3 XCast+                        (return a) (return c)+                        (transformUpMX f kenv tenv x)++        XType _         -> return xx+        XWitness _      -> return xx+++instance Monad m => TransformUpMX m Lets where+ transformUpMX f kenv tenv xx+  = case xx of+        LLet b x+         -> liftM2 LLet (return b)+                        (transformUpMX f kenv tenv x)+        +        LRec bxs+         -> do  let (bs, xs) = unzip bxs+                let tenv'    = Env.extends bs tenv+                xs'          <- mapM (transformUpMX f kenv tenv') xs+                return       $ LRec $ zip bs xs'++        LLetRegions{}    -> return xx+        LWithRegion{}    -> return xx+++instance Monad m => TransformUpMX m Alt where+ transformUpMX f kenv tenv alt+  = case alt of+        AAlt p@(PData _ bsArg) x+         -> let tenv'   = Env.extends bsArg tenv+            in  liftM2  AAlt (return p) +                        (transformUpMX f kenv tenv' x)++        AAlt PDefault x+         ->     liftM2  AAlt (return PDefault)+                        (transformUpMX f kenv tenv x) +++-- Simple ---------------------------------------------------------------------+-- | Like `transformUpMX`, but the worker takes the Simple version of the AST.+--+--   * To avoid repeated conversions between the different versions of the AST,+--     the worker should return `Nothing` if the provided expression is unchanged.+transformSimpleUpMX +        :: (Ord n, TransformUpMX m c, Monad m)+        => (KindEnv n -> TypeEnv n -> S.Exp a n -> m (Maybe (S.Exp a n)))+                        -- ^ The worker function is given the current+                        --     kind and type environments.+        -> KindEnv n    -- ^ Initial kind environment.+        -> TypeEnv n    -- ^ Initial type environment.+        -> c a n        -- ^ Transform thing thing.+        -> m (c a n)++transformSimpleUpMX f kenv0 tenv0 xx0+ = let  +        f' kenv tenv xx+         = case takeAnnotOfExp xx of+            Nothing -> return xx+            Just a  +             -> do let sxx  = deannotate (const Nothing) xx+                   msxx'    <- f kenv tenv sxx+                   case msxx' of+                        Nothing   -> return $ xx+                        Just sxx' -> return $ annotate a sxx'++   in   transformUpMX f' kenv0 tenv0 xx0+++-- | Like `transformUpX`, but the worker takes the Simple version of the AST.+--+--   * To avoid repeated conversions between the different versions of the AST,+--     the worker should return `Nothing` if the provided expression is unchanged.+transformSimpleUpX+        :: forall (c :: * -> * -> *) a n+        .  (Ord n, TransformUpMX Identity c)+        => (KindEnv n -> TypeEnv n -> S.Exp a n -> Maybe (S.Exp a n))+                      -- ^ The worker function is given the current+                      --     kind and type environments.+        -> KindEnv n  -- ^ Initial kind environment.+        -> TypeEnv n  -- ^ Initial type environment.+        -> c a n      -- ^ Transform this thing.+        -> c a n++transformSimpleUpX f kenv tenv xx+        = runIdentity +        $ transformSimpleUpMX +                (\kenv' tenv' x -> return (f kenv' tenv' x)) +                kenv tenv xx+++-- | Like `transformUpX'`, but the worker takes the Simple version of the AST.+--+--   * To avoid repeated conversions between the different versions of the AST,+--     the worker should return `Nothing` if the provided expression is unchanged.+transformSimpleUpX'+        :: forall (c :: * -> * -> *) a n+        .  (Ord n, TransformUpMX Identity c)+        => (S.Exp a n -> Maybe (S.Exp a n))+                        -- ^ The worker function is given the current+                        --      kind and type environments.+        -> c a n        -- ^ Transform this thing.+        -> c a n++transformSimpleUpX' f xx+        = transformSimpleUpX (\_ _ -> f) Env.empty Env.empty xx+
− DDC/Core/Transform/TransformX.hs
@@ -1,139 +0,0 @@---- | General purpose tree walking boilerplate.-module DDC.Core.Transform.TransformX-        ( TransformUpMX(..)-        , transformUpX-        , transformUpX')-where-import DDC.Core.Module-import DDC.Core.Exp-import DDC.Core.Compounds-import DDC.Type.Env             (KindEnv, TypeEnv)-import Data.Functor.Identity-import Control.Monad-import qualified DDC.Type.Env   as Env----- | Bottom up rewrite of all core expressions in a thing.-transformUpX-        :: forall (c :: * -> * -> *) a n-        .  (Ord n, TransformUpMX Identity c)-        => (KindEnv n -> TypeEnv n -> Exp a n -> Exp a n)       -                        -- ^ The worker function is given the current kind and type environments.-        -> KindEnv n    -- ^ Initial kind environment.-        -> TypeEnv n    -- ^ Initial type environment.-        -> c a n        -- ^ Transform this thing.-        -> c a n--transformUpX f kenv tenv xx-        = runIdentity -        $ transformUpMX -                (\kenv' tenv' x -> return (f kenv' tenv' x)) -                kenv tenv xx----- | Like transformUpX, but without using environments.-transformUpX'-        :: forall (c :: * -> * -> *) a n-        .  (Ord n, TransformUpMX Identity c)-        => (Exp a n -> Exp a n)       -                        -- ^ The worker function is given the current-                        --      kind and type environments.-        -> c a n        -- ^ Transform this thing.-        -> c a n--transformUpX' f xx-        = transformUpX (\_ _ -> f) Env.empty Env.empty xx-----------------------------------------------------------------------------------class TransformUpMX m (c :: * -> * -> *) where- -- | Bottom-up monadic rewrite of all core expressions in a thing.- transformUpMX-        :: Ord n-        => (KindEnv n -> TypeEnv n -> Exp a n -> m (Exp a n))-                        -- ^ The worker function is given the current-                        --      kind and type environments.-        -> KindEnv n    -- ^ Initial kind environment.-        -> TypeEnv n    -- ^ Initial type environment.-        -> c a n        -- ^ Transform this thing.-        -> m (c a n)---instance Monad m => TransformUpMX m Module where- transformUpMX f kenv tenv !mm-  = do  x'    <- transformUpMX f kenv tenv $ moduleBody mm-        return  $ mm { moduleBody = x' }---instance Monad m => TransformUpMX m Exp where- transformUpMX f kenv tenv !xx-  = {-# SCC transformUpMX #-} -    (f kenv tenv =<<)-  $ case xx of-        XVar{}          -> return xx-        XCon{}          -> return xx--        XLAM a b x1-         -> liftM3 XLAM (return a) (return b)-                        (transformUpMX f (Env.extend b kenv) tenv x1)--        XLam a b  x1    -         -> liftM3 XLam (return a) (return b) -                        (transformUpMX f kenv (Env.extend b tenv) x1)--        XApp a x1 x2    -         -> liftM3 XApp (return a) -                        (transformUpMX f kenv tenv x1) -                        (transformUpMX f kenv tenv x2)--        XLet a lts x-         -> do  lts'      <- transformUpMX f kenv tenv lts-                let kenv' = Env.extends (specBindsOfLets lts')   kenv-                let tenv' = Env.extends (valwitBindsOfLets lts') tenv-                x'        <- transformUpMX f kenv' tenv' x-                return  $ XLet a lts' x'-                -        XCase a x alts-         -> liftM3 XCase (return a)-                         (transformUpMX f kenv tenv x)-                         (mapM (transformUpMX f kenv tenv) alts)--        XCast a c x       -         -> liftM3 XCast-                        (return a) (return c)-                        (transformUpMX f kenv tenv x)--        XType _         -> return xx-        XWitness _      -> return xx---instance Monad m => TransformUpMX m Lets where- transformUpMX f kenv tenv xx-  = case xx of-        LLet m b x-         -> liftM3 LLet (return m) (return b)-                        (transformUpMX f kenv tenv x)-        -        LRec bxs-         -> do  let (bs, xs) = unzip bxs-                let tenv'    = Env.extends bs tenv-                xs'          <- mapM (transformUpMX f kenv tenv') xs-                return       $ LRec $ zip bs xs'--        LLetRegions{}    -> return xx-        LWithRegion{}    -> return xx---instance Monad m => TransformUpMX m Alt where- transformUpMX f kenv tenv alt-  = case alt of-        AAlt p@(PData _ bsArg) x-         -> let tenv'   = Env.extends bsArg tenv-            in  liftM2  AAlt (return p) -                        (transformUpMX f kenv tenv' x)--        AAlt PDefault x-         ->     liftM2  AAlt (return PDefault)-                        (transformUpMX f kenv tenv x) -
LICENSE view
@@ -1,7 +1,7 @@ -------------------------------------------------------------------------------- The Disciplined Disciple Compiler License (MIT style) -Copyrite (K) 2007-2012 The Disciplined Disciple Compiler Strike Force+Copyrite (K) 2007-2013 The Disciplined Disciple Compiler Strike Force All rights reversed.  Permission is hereby granted, free of charge, to any person obtaining a copy
ddc-core-simpl.cabal view
@@ -1,5 +1,5 @@ Name:           ddc-core-simpl-Version:        0.3.1.1+Version:        0.3.2.1 License:        MIT License-file:   LICENSE Author:         The Disciplined Disciple Compiler Strike Force@@ -9,7 +9,6 @@ Stability:      experimental Category:       Compilers/Interpreters Homepage:       http://disciple.ouroborus.net-Bug-reports:    disciple@ouroborus.net Synopsis:       Disciplined Disciple Compiler code transformations. Description:    Disciplined Disciple Compiler code transformations. @@ -21,14 +20,15 @@         array           == 0.4.*,         transformers    == 0.3.*,         mtl             == 2.1.*,-        ddc-base        == 0.3.1.*,-        ddc-core        == 0.3.1.*+        ddc-base        == 0.3.2.*,+        ddc-core        == 0.3.2.*    Exposed-modules:         DDC.Core.Analysis.Arity         DDC.Core.Analysis.Usage         DDC.Core.Simplifier.Recipe         DDC.Core.Simplifier.Parser+        DDC.Core.Simplifier.Result         DDC.Core.Transform.Rewrite.Disjoint         DDC.Core.Transform.Rewrite.Env         DDC.Core.Transform.Rewrite.Match@@ -39,13 +39,16 @@         DDC.Core.Transform.Bubble         DDC.Core.Transform.Prune         DDC.Core.Transform.Elaborate+        DDC.Core.Transform.Eta         DDC.Core.Transform.Flatten         DDC.Core.Transform.Forward         DDC.Core.Transform.Inline         DDC.Core.Transform.Namify         DDC.Core.Transform.Rewrite         DDC.Core.Transform.Snip-        DDC.Core.Transform.TransformX+        DDC.Core.Transform.Thread+        DDC.Core.Transform.TransformUpX+        DDC.Core.Transform.TransformDownX         DDC.Core.Simplifier          DDC.Type.Transform.Alpha