packages feed

ddc-core-simpl 0.2.1.2 → 0.3.1.1

raw patch · 32 files changed

+5413/−417 lines, 32 filesdep +deepseqdep ~arraydep ~ddc-basedep ~ddc-corePVP ok

version bump matches the API change (PVP)

Dependencies added: deepseq

Dependency ranges changed: array, ddc-base, ddc-core

API changes (from Hackage documentation)

- DDC.Core.Transform.ANormal: anormalise :: Ord n => Exp a n -> Exp a n
- DDC.Core.Transform.AnonymizeX: instance AnonymizeX Bound
- DDC.Core.Transform.AnonymizeX: instance AnonymizeX Cast
- DDC.Type.Transform.Rename: class Rename (c :: * -> *)
- DDC.Type.Transform.Rename: instance Rename Bind
- DDC.Type.Transform.Rename: instance Rename Bound
- DDC.Type.Transform.Rename: instance Rename TyCon
- DDC.Type.Transform.Rename: instance Rename Type
- DDC.Type.Transform.Rename: instance Rename TypeSum
- DDC.Type.Transform.Rename: rename :: (Rename c, Ord n2) => (n1 -> n2) -> c n1 -> c n2
+ DDC.Core.Analysis.Arity: aritiesOfLets :: Ord n => Lets a n -> Maybe [(Bind n, Int)]
+ DDC.Core.Analysis.Arity: aritiesOfModule :: Ord n => Module a n -> Arities n
+ DDC.Core.Analysis.Arity: aritiesOfPat :: Ord n => Pat n -> [(Bind n, Int)]
+ DDC.Core.Analysis.Arity: arityFromType :: Ord n => Type n -> Maybe Int
+ DDC.Core.Analysis.Arity: arityOfExp :: Ord n => Exp a n -> Maybe Int
+ DDC.Core.Analysis.Arity: emptyArities :: Ord n => Arities n
+ DDC.Core.Analysis.Arity: extendsArities :: Ord n => Arities n -> [(Bind n, Int)] -> Arities n
+ DDC.Core.Analysis.Arity: getArity :: Ord n => Arities n -> Bound n -> Maybe Int
+ DDC.Core.Analysis.Arity: type Arities n = (Map n Int, [Int])
+ DDC.Core.Analysis.Usage: UsedDestruct :: Used
+ DDC.Core.Analysis.Usage: UsedFunction :: Used
+ DDC.Core.Analysis.Usage: UsedInAlt :: Used -> Used
+ DDC.Core.Analysis.Usage: UsedInCast :: Used
+ DDC.Core.Analysis.Usage: UsedInLambda :: Used -> Used
+ DDC.Core.Analysis.Usage: UsedMap :: (Map n [Used]) -> UsedMap n
+ DDC.Core.Analysis.Usage: UsedOcc :: Used
+ DDC.Core.Analysis.Usage: data Used
+ DDC.Core.Analysis.Usage: data UsedMap n
+ DDC.Core.Analysis.Usage: instance Eq Used
+ DDC.Core.Analysis.Usage: instance Show Used
+ DDC.Core.Analysis.Usage: instance Show n => Show (UsedMap n)
+ DDC.Core.Analysis.Usage: usageModule :: Ord n => Module a n -> Module (UsedMap n, a) n
+ DDC.Core.Analysis.Usage: usageX :: Ord n => Exp a n -> Exp (UsedMap n, a) n
+ DDC.Core.Simplifier: Anonymize :: Transform s a n
+ DDC.Core.Simplifier: Beta :: Transform s a n
+ DDC.Core.Simplifier: BetaLets :: Transform s a n
+ DDC.Core.Simplifier: Bubble :: Transform s a n
+ DDC.Core.Simplifier: Elaborate :: Transform s a n
+ DDC.Core.Simplifier: Fix :: Int -> (Simplifier s a n) -> Simplifier s a n
+ DDC.Core.Simplifier: Flatten :: Transform s a n
+ DDC.Core.Simplifier: Forward :: Transform s a n
+ DDC.Core.Simplifier: Id :: Transform s a n
+ DDC.Core.Simplifier: Inline :: InlinerTemplates a n -> Transform s a n
+ DDC.Core.Simplifier: Namify :: (Env n -> Namifier s n) -> (Env n -> Namifier s n) -> Transform s a n
+ DDC.Core.Simplifier: Prune :: Transform s a n
+ DDC.Core.Simplifier: Rewrite :: NamedRewriteRules a n -> Transform s a n
+ DDC.Core.Simplifier: Seq :: (Simplifier s a n) -> (Simplifier s a n) -> Simplifier s a n
+ DDC.Core.Simplifier: Snip :: Transform s a n
+ DDC.Core.Simplifier: SnipOver :: Transform s a n
+ DDC.Core.Simplifier: Trans :: (Transform s a n) -> Simplifier s a n
+ DDC.Core.Simplifier: TransformInfo :: i -> TransformInfo
+ DDC.Core.Simplifier: TransformResult :: r -> Bool -> Bool -> TransformInfo -> TransformResult r
+ DDC.Core.Simplifier: applySimplifier :: (Show a, Ord n, Show n, Pretty n, NFData a, NFData n) => Profile n -> KindEnv n -> TypeEnv n -> Simplifier s a n -> Module a n -> State s (Module a n)
+ DDC.Core.Simplifier: applySimplifierX :: (Show a, Show n, Ord n, Pretty n) => Profile n -> KindEnv n -> TypeEnv n -> Simplifier s a n -> Exp a n -> State s (TransformResult (Exp a n))
+ DDC.Core.Simplifier: data Simplifier s a n
+ DDC.Core.Simplifier: data Transform s a n
+ DDC.Core.Simplifier: data TransformInfo
+ DDC.Core.Simplifier: data TransformResult r
+ DDC.Core.Simplifier: result :: TransformResult r -> r
+ DDC.Core.Simplifier: resultAgain :: TransformResult r -> Bool
+ DDC.Core.Simplifier: resultDone :: String -> r -> TransformResult r
+ DDC.Core.Simplifier: resultInfo :: TransformResult r -> TransformInfo
+ DDC.Core.Simplifier: resultProgress :: TransformResult r -> Bool
+ DDC.Core.Simplifier: transInlineDef :: Transform s a n -> InlinerTemplates a n
+ DDC.Core.Simplifier: transMkNamifierT :: Transform s a n -> Env n -> Namifier s n
+ DDC.Core.Simplifier: transMkNamifierX :: Transform s a n -> Env n -> Namifier s n
+ DDC.Core.Simplifier: transRules :: Transform s a n -> NamedRewriteRules a n
+ DDC.Core.Simplifier: type InlinerTemplates a n = n -> Maybe (Exp a n)
+ DDC.Core.Simplifier: type NamedRewriteRules a n = [(String, RewriteRule a n)]
+ DDC.Core.Simplifier.Parser: SimplifierDetails :: (Env n -> Namifier s n) -> (Env n -> Namifier s n) -> NamedRewriteRules a n -> [Module a n] -> SimplifierDetails s a n
+ DDC.Core.Simplifier.Parser: data SimplifierDetails s a n
+ DDC.Core.Simplifier.Parser: parseSimplifier :: (Ord n, Show n) => (String -> Maybe n) -> SimplifierDetails s a n -> String -> Either ParseError (Simplifier s a n)
+ DDC.Core.Simplifier.Parser: simplifierMkNamifierT :: SimplifierDetails s a n -> Env n -> Namifier s n
+ DDC.Core.Simplifier.Parser: simplifierMkNamifierX :: SimplifierDetails s a n -> Env n -> Namifier s n
+ DDC.Core.Simplifier.Parser: simplifierRules :: SimplifierDetails s a n -> NamedRewriteRules a n
+ DDC.Core.Simplifier.Parser: simplifierTemplates :: SimplifierDetails s a n -> [Module a n]
+ DDC.Core.Simplifier.Recipe: anonymize :: Simplifier s a n
+ DDC.Core.Simplifier.Recipe: anormalize :: (KindEnv n -> Namifier s n) -> (TypeEnv n -> Namifier s n) -> Simplifier s a n
+ DDC.Core.Simplifier.Recipe: beta :: Simplifier s a n
+ DDC.Core.Simplifier.Recipe: betaLets :: Simplifier s a n
+ DDC.Core.Simplifier.Recipe: bubble :: Simplifier s a n
+ DDC.Core.Simplifier.Recipe: elaborate :: Simplifier s a n
+ DDC.Core.Simplifier.Recipe: flatten :: Simplifier s a n
+ DDC.Core.Simplifier.Recipe: forward :: Simplifier s a n
+ DDC.Core.Simplifier.Recipe: idsimp :: Simplifier s a n
+ DDC.Core.Simplifier.Recipe: prune :: Simplifier s a n
+ DDC.Core.Simplifier.Recipe: rewriteSimp :: Int -> NamedRewriteRules a n -> Simplifier s a n
+ DDC.Core.Simplifier.Recipe: snip :: Simplifier s a n
+ DDC.Core.Simplifier.Recipe: snipOver :: Simplifier s a n
+ DDC.Core.Transform.AnonymizeX: instance AnonymizeX (Cast a)
+ DDC.Core.Transform.AnonymizeX: instance AnonymizeX (Module a)
+ DDC.Core.Transform.AnonymizeX: pushAnonymizeBindX :: Ord n => Set n -> [Bind n] -> [Bind n] -> Bind n -> ([Bind n], Bind n)
+ DDC.Core.Transform.Beta: BetaReduceInfo :: Int -> Int -> Int -> Int -> Int -> BetaReduceInfo
+ DDC.Core.Transform.Beta: data BetaReduceInfo
+ DDC.Core.Transform.Beta: infoTypes :: BetaReduceInfo -> Int
+ DDC.Core.Transform.Beta: infoValues :: BetaReduceInfo -> Int
+ DDC.Core.Transform.Beta: infoValuesLetted :: BetaReduceInfo -> Int
+ DDC.Core.Transform.Beta: infoValuesSkipped :: BetaReduceInfo -> Int
+ DDC.Core.Transform.Beta: infoWits :: BetaReduceInfo -> Int
+ DDC.Core.Transform.Beta: instance Monoid BetaReduceInfo
+ DDC.Core.Transform.Beta: instance Pretty BetaReduceInfo
+ DDC.Core.Transform.Beta: instance Typeable BetaReduceInfo
+ DDC.Core.Transform.Bubble: bubbleModule :: Ord n => Module a n -> Module a n
+ DDC.Core.Transform.Bubble: bubbleX :: Ord n => KindEnv n -> TypeEnv n -> Exp a n -> Exp a n
+ DDC.Core.Transform.Bubble: instance Bubble Alt
+ DDC.Core.Transform.Bubble: instance Bubble Exp
+ DDC.Core.Transform.Bubble: instance Bubble Lets
+ DDC.Core.Transform.Bubble: instance Ord n => MapBoundX (FvsCast a) n
+ DDC.Core.Transform.Elaborate: elaborateModule :: Eq n => Module a n -> Module a n
+ DDC.Core.Transform.Elaborate: elaborateX :: Eq n => Exp a n -> Exp a n
+ DDC.Core.Transform.Elaborate: instance Elaborate (Alt a)
+ DDC.Core.Transform.Elaborate: instance Elaborate (Cast a)
+ DDC.Core.Transform.Elaborate: instance Elaborate (Exp a)
+ DDC.Core.Transform.Flatten: flatten :: Ord n => TransformUpMX Identity c => c a n -> c a n
+ DDC.Core.Transform.Forward: ForwardInfo :: Int -> Int -> ForwardInfo
+ DDC.Core.Transform.Forward: data ForwardInfo
+ DDC.Core.Transform.Forward: forwardModule :: Ord n => Profile n -> Module a n -> Module a n
+ DDC.Core.Transform.Forward: forwardX :: Ord n => Profile n -> Exp a n -> TransformResult (Exp a n)
+ DDC.Core.Transform.Forward: infoBindings :: ForwardInfo -> Int
+ DDC.Core.Transform.Forward: infoSubsts :: ForwardInfo -> Int
+ DDC.Core.Transform.Forward: instance Forward Alt
+ DDC.Core.Transform.Forward: instance Forward Cast
+ DDC.Core.Transform.Forward: instance Forward Exp
+ DDC.Core.Transform.Forward: instance Forward Lets
+ DDC.Core.Transform.Forward: instance Forward Module
+ DDC.Core.Transform.Forward: instance Monoid ForwardInfo
+ DDC.Core.Transform.Forward: instance Pretty ForwardInfo
+ DDC.Core.Transform.Forward: instance Typeable ForwardInfo
+ DDC.Core.Transform.Inline: InlineSpecAll :: ModuleName -> Set n -> InlineSpec n
+ DDC.Core.Transform.Inline: InlineSpecNone :: ModuleName -> Set n -> InlineSpec n
+ DDC.Core.Transform.Inline: data InlineSpec n
+ DDC.Core.Transform.Inline: inline :: (Inline c, Ord n) => (n -> Maybe (Exp a n)) -> Set n -> c a n -> c a n
+ DDC.Core.Transform.Inline: inlineSpecExclude :: InlineSpec n -> Set n
+ DDC.Core.Transform.Inline: inlineSpecInclude :: InlineSpec n -> Set n
+ DDC.Core.Transform.Inline: inlineSpecModuleName :: InlineSpec n -> ModuleName
+ DDC.Core.Transform.Inline: instance Inline Alt
+ DDC.Core.Transform.Inline: instance Inline Exp
+ DDC.Core.Transform.Inline: instance Inline Lets
+ DDC.Core.Transform.Inline: instance Inline Module
+ DDC.Core.Transform.Inline: lookupTemplateFromModules :: (Eq n, Ord n, Show n) => Map ModuleName (InlineSpec n) -> [Module a n] -> n -> Maybe (Exp a n)
+ DDC.Core.Transform.Namify: Namifier :: (Env n -> Bind n -> State s n) -> Env n -> [Bind n] -> Namifier s n
+ DDC.Core.Transform.Namify: class Namify (c :: * -> *)
+ DDC.Core.Transform.Namify: data Namifier s n
+ DDC.Core.Transform.Namify: instance Namify (Alt a)
+ DDC.Core.Transform.Namify: instance Namify (Cast a)
+ DDC.Core.Transform.Namify: instance Namify (Exp a)
+ DDC.Core.Transform.Namify: instance Namify (Module a)
+ DDC.Core.Transform.Namify: instance Namify LetMode
+ DDC.Core.Transform.Namify: instance Namify Type
+ DDC.Core.Transform.Namify: instance Namify Witness
+ DDC.Core.Transform.Namify: makeNamifier :: (Env n -> Bind n -> State s n) -> Env n -> Namifier s n
+ DDC.Core.Transform.Namify: namifierEnv :: Namifier s n -> Env n
+ DDC.Core.Transform.Namify: namifierNew :: Namifier s n -> Env n -> Bind n -> State s n
+ DDC.Core.Transform.Namify: namifierStack :: Namifier s n -> [Bind n]
+ DDC.Core.Transform.Namify: namify :: (Namify c, Ord n) => Namifier s n -> Namifier s n -> c n -> State s (c n)
+ DDC.Core.Transform.Namify: namifyUnique :: (Ord n, Namify c, BindStruct c) => (KindEnv n -> Namifier s n) -> (TypeEnv n -> Namifier s n) -> c n -> State s (c n)
+ DDC.Core.Transform.Prune: PruneInfo :: Int -> PruneInfo
+ DDC.Core.Transform.Prune: data PruneInfo
+ DDC.Core.Transform.Prune: infoBindingsErased :: PruneInfo -> Int
+ DDC.Core.Transform.Prune: instance Monoid PruneInfo
+ DDC.Core.Transform.Prune: instance Pretty PruneInfo
+ DDC.Core.Transform.Prune: instance Typeable PruneInfo
+ DDC.Core.Transform.Prune: pruneModule :: (Show a, Show n, Ord n, Pretty n) => Profile n -> Module a n -> Module a n
+ DDC.Core.Transform.Prune: pruneX :: (Show a, Show n, Ord n, Pretty n) => Profile n -> KindEnv n -> TypeEnv n -> Exp a n -> TransformResult (Exp a n)
+ DDC.Core.Transform.Rewrite: RewriteRule :: [(BindMode, Bind n)] -> [Type n] -> Exp a n -> Maybe (Exp a n) -> Exp a n -> Maybe (Effect n) -> [Exp a n] -> [Bound n] -> RewriteRule a n
+ DDC.Core.Transform.Rewrite: data RewriteRule a n
+ DDC.Core.Transform.Rewrite: instance Pretty RewriteInfo
+ DDC.Core.Transform.Rewrite: instance Pretty RewriteLog
+ DDC.Core.Transform.Rewrite: instance Typeable RewriteInfo
+ DDC.Core.Transform.Rewrite: instance Typeable RewriteLog
+ DDC.Core.Transform.Rewrite: rewriteModule :: (Show a, Show n, Ord n, Pretty n) => [NamedRewriteRule a n] -> Module a n -> Module a n
+ DDC.Core.Transform.Rewrite: rewriteX :: (Show a, Show n, Ord n, Pretty n) => [NamedRewriteRule a n] -> Exp a n -> TransformResult (Exp a n)
+ DDC.Core.Transform.Rewrite: ruleBinds :: RewriteRule a n -> [(BindMode, Bind n)]
+ DDC.Core.Transform.Rewrite: ruleConstraints :: RewriteRule a n -> [Type n]
+ DDC.Core.Transform.Rewrite: ruleFreeVars :: RewriteRule a n -> [Bound n]
+ DDC.Core.Transform.Rewrite: ruleLeft :: RewriteRule a n -> Exp a n
+ DDC.Core.Transform.Rewrite: ruleLeftHole :: RewriteRule a n -> Maybe (Exp a n)
+ DDC.Core.Transform.Rewrite: ruleRight :: RewriteRule a n -> Exp a n
+ DDC.Core.Transform.Rewrite: ruleWeakClo :: RewriteRule a n -> [Exp a n]
+ DDC.Core.Transform.Rewrite: ruleWeakEff :: RewriteRule a n -> Maybe (Effect n)
+ DDC.Core.Transform.Rewrite.Disjoint: checkDisjoint :: (Ord n, Show n) => Type n -> RewriteEnv a n -> Bool
+ DDC.Core.Transform.Rewrite.Disjoint: checkDistinct :: Ord n => Type n -> RewriteEnv a n -> Bool
+ DDC.Core.Transform.Rewrite.Env: containsRegion :: Ord n => Bound n -> RewriteEnv a n -> Bool
+ DDC.Core.Transform.Rewrite.Env: containsWitness :: Ord n => Type n -> RewriteEnv a n -> Bool
+ DDC.Core.Transform.Rewrite.Env: data RewriteEnv a n
+ DDC.Core.Transform.Rewrite.Env: empty :: Ord n => RewriteEnv a n
+ DDC.Core.Transform.Rewrite.Env: extend :: Ord n => Bind n -> RewriteEnv a n -> RewriteEnv a n
+ DDC.Core.Transform.Rewrite.Env: extendLets :: Ord n => Lets a n -> RewriteEnv a n -> RewriteEnv a n
+ DDC.Core.Transform.Rewrite.Env: getDef :: (Ord n, MapBoundX (Exp a) n) => Bound n -> RewriteEnv a n -> Maybe (Exp a n)
+ DDC.Core.Transform.Rewrite.Env: getWitnesses :: Ord n => RewriteEnv a n -> [Type n]
+ DDC.Core.Transform.Rewrite.Env: hasDef :: (Ord n, MapBoundX (Exp a) n) => Bound n -> RewriteEnv a n -> Bool
+ DDC.Core.Transform.Rewrite.Env: insertDef :: Bind n -> Maybe (Exp a n) -> RewriteEnv a n -> RewriteEnv a n
+ DDC.Core.Transform.Rewrite.Env: instance (Eq a, Eq n) => Eq (RewriteEnv a n)
+ DDC.Core.Transform.Rewrite.Env: instance (Show a, Show n) => Show (RewriteEnv a n)
+ DDC.Core.Transform.Rewrite.Env: lift :: Bind n -> RewriteEnv a n -> RewriteEnv a n
+ DDC.Core.Transform.Rewrite.Env: liftValue :: Bind n -> RewriteEnv a n -> RewriteEnv a n
+ DDC.Core.Transform.Rewrite.Match: emptySubstInfo :: SubstInfo a n
+ DDC.Core.Transform.Rewrite.Match: match :: (Show a, Show n, Ord n) => SubstInfo a n -> Set n -> Exp a n -> Exp a n -> Maybe (SubstInfo a n)
+ DDC.Core.Transform.Rewrite.Match: type SubstInfo a n = (Map n (Exp a n), Map n (Type n))
+ DDC.Core.Transform.Rewrite.Parser: pRule :: Ord n => Parser n (RewriteRule () n)
+ DDC.Core.Transform.Rewrite.Parser: pRuleMany :: Ord n => Parser n [(n, RewriteRule () n)]
+ DDC.Core.Transform.Rewrite.Rule: BMSpec :: BindMode
+ DDC.Core.Transform.Rewrite.Rule: BMValue :: Int -> BindMode
+ DDC.Core.Transform.Rewrite.Rule: ErrorAnonymousBinder :: Bind n -> Error a n
+ DDC.Core.Transform.Rewrite.Rule: ErrorBadConstraint :: Type n -> Error a n
+ DDC.Core.Transform.Rewrite.Rule: ErrorNotFirstOrder :: Exp a n -> Error a n
+ DDC.Core.Transform.Rewrite.Rule: ErrorTypeCheck :: Side -> Exp a n -> Error a n -> Error a n
+ DDC.Core.Transform.Rewrite.Rule: ErrorTypeConflict :: (Type n, Effect n, Closure n) -> (Type n, Effect n, Closure n) -> Error a n
+ DDC.Core.Transform.Rewrite.Rule: ErrorVarUnmentioned :: Error a n
+ DDC.Core.Transform.Rewrite.Rule: Lhs :: Side
+ DDC.Core.Transform.Rewrite.Rule: RewriteRule :: [(BindMode, Bind n)] -> [Type n] -> Exp a n -> Maybe (Exp a n) -> Exp a n -> Maybe (Effect n) -> [Exp a n] -> [Bound n] -> RewriteRule a n
+ DDC.Core.Transform.Rewrite.Rule: Rhs :: Side
+ DDC.Core.Transform.Rewrite.Rule: checkRewriteRule :: (Ord n, Show n, Pretty n) => Config n -> Env n -> Env n -> RewriteRule a n -> Either (Error a n) (RewriteRule (AnTEC a n) n)
+ DDC.Core.Transform.Rewrite.Rule: data BindMode
+ DDC.Core.Transform.Rewrite.Rule: data Error a n
+ DDC.Core.Transform.Rewrite.Rule: data RewriteRule a n
+ DDC.Core.Transform.Rewrite.Rule: data Side
+ DDC.Core.Transform.Rewrite.Rule: errorBinder :: Error a n -> Bind n
+ DDC.Core.Transform.Rewrite.Rule: errorCheckError :: Error a n -> Error a n
+ DDC.Core.Transform.Rewrite.Rule: errorConstraint :: Error a n -> Type n
+ DDC.Core.Transform.Rewrite.Rule: errorExp :: Error a n -> Exp a n
+ DDC.Core.Transform.Rewrite.Rule: errorSide :: Error a n -> Side
+ DDC.Core.Transform.Rewrite.Rule: errorTypeLhs :: Error a n -> (Type n, Effect n, Closure n)
+ DDC.Core.Transform.Rewrite.Rule: errorTypeRhs :: Error a n -> (Type n, Effect n, Closure n)
+ DDC.Core.Transform.Rewrite.Rule: instance (Eq a, Eq n) => Eq (RewriteRule a n)
+ DDC.Core.Transform.Rewrite.Rule: instance (Pretty n, Eq n) => Pretty (RewriteRule a n)
+ DDC.Core.Transform.Rewrite.Rule: instance (Show a, Show n) => Show (RewriteRule a n)
+ DDC.Core.Transform.Rewrite.Rule: instance Eq BindMode
+ DDC.Core.Transform.Rewrite.Rule: instance Reannotate RewriteRule
+ DDC.Core.Transform.Rewrite.Rule: instance Show BindMode
+ DDC.Core.Transform.Rewrite.Rule: isBMSpec :: BindMode -> Bool
+ DDC.Core.Transform.Rewrite.Rule: isBMValue :: BindMode -> Bool
+ DDC.Core.Transform.Rewrite.Rule: mkRewriteRule :: Ord n => [(BindMode, Bind n)] -> [Type n] -> Exp a n -> Maybe (Exp a n) -> Exp a n -> RewriteRule a n
+ DDC.Core.Transform.Rewrite.Rule: ruleBinds :: RewriteRule a n -> [(BindMode, Bind n)]
+ DDC.Core.Transform.Rewrite.Rule: ruleConstraints :: RewriteRule a n -> [Type n]
+ DDC.Core.Transform.Rewrite.Rule: ruleFreeVars :: RewriteRule a n -> [Bound n]
+ DDC.Core.Transform.Rewrite.Rule: ruleLeft :: RewriteRule a n -> Exp a n
+ DDC.Core.Transform.Rewrite.Rule: ruleLeftHole :: RewriteRule a n -> Maybe (Exp a n)
+ DDC.Core.Transform.Rewrite.Rule: ruleRight :: RewriteRule a n -> Exp a n
+ DDC.Core.Transform.Rewrite.Rule: ruleWeakClo :: RewriteRule a n -> [Exp a n]
+ DDC.Core.Transform.Rewrite.Rule: ruleWeakEff :: RewriteRule a n -> Maybe (Effect n)
+ DDC.Core.Transform.Rewrite.Rule: type NamedRewriteRule a n = (String, RewriteRule a n)
+ DDC.Core.Transform.Snip: class Snip (c :: * -> *)
+ DDC.Core.Transform.Snip: instance Snip (Exp a)
+ DDC.Core.Transform.Snip: instance Snip (Module a)
+ DDC.Core.Transform.Snip: snip :: (Snip c, Ord n) => Bool -> c n -> c n
+ DDC.Core.Transform.TransformX: instance Monad m => TransformUpMX m Module
+ DDC.Core.Transform.TransformX: transformUpX' :: (Ord n, TransformUpMX Identity c) => (Exp a n -> Exp a n) -> c a n -> c a n
+ DDC.Type.Transform.Alpha: alpha :: (Alpha c, Ord n2) => (n1 -> n2) -> c n1 -> c n2
+ DDC.Type.Transform.Alpha: class Alpha (c :: * -> *)
+ DDC.Type.Transform.Alpha: instance Alpha Bind
+ DDC.Type.Transform.Alpha: instance Alpha Bound
+ DDC.Type.Transform.Alpha: instance Alpha TyCon
+ DDC.Type.Transform.Alpha: instance Alpha Type
+ DDC.Type.Transform.Alpha: instance Alpha TypeSum
- DDC.Core.Transform.AnonymizeX: anonymizeWithX :: (AnonymizeX c, Ord n) => [Bind n] -> [Bind n] -> c n -> c n
+ DDC.Core.Transform.AnonymizeX: anonymizeWithX :: (AnonymizeX c, Ord n) => Set n -> [Bind n] -> [Bind n] -> c n -> c n
- DDC.Core.Transform.Beta: betaReduce :: Ord n => Exp a n -> Exp a n
+ DDC.Core.Transform.Beta: betaReduce :: (Ord n, TransformUpMX (Writer BetaReduceInfo) c) => Bool -> c a n -> TransformResult (c a n)
- DDC.Core.Transform.TransformX: transformUpMX :: (TransformUpMX m c, Ord n) => (Env n -> Env n -> Exp a n -> m (Exp a n)) -> Env n -> Env n -> c a n -> m (c a n)
+ 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) => (Env n -> Env n -> Exp a n -> Exp a n) -> Env n -> Env n -> c a n -> 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

Files

+ DDC/Core/Analysis/Arity.hs view
@@ -0,0 +1,142 @@++-- | Slurp out arities of function bindings.+--   and infer arities for primitives based on their types.+--+--   For function bindings the arity is the number of outer-most lambdas+--   in the definition. +--+--   For primitives, the arity is the number of function+--   constructors in its type. +--+module DDC.Core.Analysis.Arity+        ( -- * Arities map+          Arities+        , emptyArities+        , extendsArities+        , getArity++          -- * Arity analysis+        , aritiesOfModule+        , aritiesOfLets+        , aritiesOfPat+        , arityFromType+        , arityOfExp)+where+import DDC.Core.Predicates+import DDC.Core.Compounds+import DDC.Core.Module+import DDC.Core.Exp+import DDC.Data.ListUtils+import Control.Monad+import Data.Maybe+import qualified Data.Map       as Map+++-- | Arities of named and anonymous bindings.+type Arities n = (Map.Map n Int, [Int])+++-- | Empty arities context.+emptyArities :: Ord n => Arities n+emptyArities = (Map.empty, [])+++-- | Extend map with some binders and their arities.+extendsArities :: Ord n => Arities n -> [(Bind n, Int)] -> Arities n+extendsArities arity exts = foldl go arity exts+ where  go (named, anon) (BNone _t,   _) = (named,anon)+        go (named, anon) (BAnon _t,   a) = (named, a:anon)+        go (named, anon) (BName n _t, a) = (Map.insert n a named, anon)+++-- | Look up a binder's arity from the arity map+--   or determine it from its type in the case of primops.+getArity :: Ord n => Arities n -> Bound n -> Maybe Int+getArity (named, anon) u+ = case u of+        -- Get arities of anonymous things from the stack.+        UIx ix +         -> let Just x  = index anon ix+            in  Just x++        -- Lookup arities of named things from the stack.+        UName n         -> Map.lookup n named++        -- Get a primitive's arity from its type.+        -- The arities of primitives always match their types, so this is ok.+        UPrim _ t       -> arityFromType t+++-- Slurp ----------------------------------------------------------------------+-- | Slurp out arities of imports and top-level bindings from a module.+aritiesOfModule :: Ord n => Module a n -> Arities n+aritiesOfModule mm+  = let (lts, _)        = splitXLets $ moduleBody mm++        aritiesLets     +         = concat $ catMaybes $ map aritiesOfLets  lts++        aritiesImports  +         = catMaybes+         $ [ case arityFromType t of+                Just a  -> Just (BName n t, a)+                Nothing -> Nothing+           | (n, (_, t)) <- Map.toList $ moduleImportTypes mm ]++    in  emptyArities+        `extendsArities` aritiesImports+        `extendsArities` aritiesLets+++-- | Get the arities of a `Lets`+aritiesOfLets :: Ord n => Lets a n -> Maybe [(Bind n, Int)]+aritiesOfLets ll+ = let get (b, x)+        = case arityOfExp x of+                Nothing         -> Nothing+                Just a          -> Just (b, a)+   in case ll of+        LLet _ b x      -> sequence $ map get [(b, x)]+        LRec bxs        -> sequence $ map get bxs+        _               -> Just []+++-- | Retrieve binders from case pattern, so we can extend the arity context.+--   We don't know anything about their values, so record as 0.+aritiesOfPat :: Ord n => Pat n -> [(Bind n, Int)]+aritiesOfPat p+ = case p of+        PDefault        -> []+        (PData _b bs)   -> zip bs (repeat 0)+++-- | Get the arity of an expression. +arityOfExp :: Ord n => Exp a n -> Maybe Int+arityOfExp xx+ = case xx of+        -- Counting all binders, because they all correspond to XApps.+        XLam _ _ e      -> liftM (+ 1) $ arityOfExp e+        XLAM _ _ e      -> liftM (+ 1) $ arityOfExp e++        -- Determine a data constructor's arity from its type.+        XCon _ dc       -> arityFromType (typeOfDaCon dc)++        -- Anything else we'll need to apply one at a time+        _               -> Just 0+++-- | Determine the arity of an expression by looking at its type.+--   Count all the function arrows, and foralls.+arityFromType :: Ord n => Type n -> Maybe Int+arityFromType tt+        | TForall _ t   <- tt+        = case arityFromType t of+                Nothing -> Nothing+                Just a  -> Just (1 + a)++        | isBot tt+        = Nothing++        | (args, _)     <- takeTFunArgResult tt+        = Just (length args)+
+ DDC/Core/Analysis/Usage.hs view
@@ -0,0 +1,248 @@++-- | Annotate let bindings with how their bound variables are used.+module DDC.Core.Analysis.Usage+        ( -- * Usage map+          Used    (..)+        , UsedMap (..)++          -- * Usage analysis+        , usageModule+        , usageX)+where+import DDC.Core.Module+import DDC.Core.Exp+import Data.List+import Data.Map                 (Map)+import qualified Data.Map       as Map+++-- Used -----------------------------------------------------------------------+-- | Tracks how a bound variable is used.+data Used+        -- | Bound variable is used as the function of an application.+        = UsedFunction++        -- | Bound variable is destructed by a case-expression.+        | UsedDestruct++	-- | Bound variable is used inside a @weakclo@ cast.+	| UsedInCast++        -- | Bound variable has an occurrence that is not one of the above.+        | UsedOcc++        -- | Usage is inside a Lambda abstraction (either type or value)+        | UsedInLambda Used++        -- | Usage is inside a case alternative.+        | UsedInAlt    Used+        deriving (Eq, Show)+++-- UsedMap --------------------------------------------------------------------+-- | Map of bound name to how the variable is used.+data UsedMap n+        = UsedMap (Map n [Used])+        deriving Show+++-- | An empty usage map.+empty :: UsedMap n+empty   = UsedMap (Map.empty)+++-- | Add a single usage to a usage map.+accUsed :: Ord n => Bound n -> Used -> UsedMap n -> UsedMap n+accUsed u used um@(UsedMap m)+ = case u of+        UName n         -> UsedMap $ Map.insertWith (++) n [used] m +        _               -> um++-- | Combine two usage maps.+plusUsedMap :: Ord n => UsedMap n -> UsedMap n -> UsedMap n+plusUsedMap (UsedMap map1) (UsedMap map2)+        = UsedMap $ Map.unionWith (++) map1 map2+++-- | Combine a list of usage maps into a single one.+sumUsedMap :: Ord n => [UsedMap n] -> UsedMap n+sumUsedMap []   = UsedMap Map.empty+sumUsedMap (m:ms)+        = foldl' plusUsedMap m ms+++-- Usage ----------------------------------------------------------------------+-- | Annotate all binding occurrences of variables in an expression+--   with how they are used.+usageModule +        :: Ord n+        => Module a n+        -> Module (UsedMap n, a) n+usageModule +        (ModuleCore+                { moduleName            = name+                , moduleExportKinds     = exportKinds+                , moduleExportTypes     = exportTypes+                , moduleImportKinds     = importKinds+                , moduleImportTypes     = importTypes+                , moduleBody            = body })++ =       ModuleCore+                { moduleName            = name+                , moduleExportKinds     = exportKinds+                , moduleExportTypes     = exportTypes+                , moduleImportKinds     = importKinds+                , moduleImportTypes     = importTypes+                , moduleBody            = usageX body }+++-- | Annotate all binding occurrences of variables in an expression+--   with how they are used.+usageX  :: Ord n +        => Exp a n +        -> Exp (UsedMap n, a) n+usageX xx = snd $ usageX' xx+++usageX' :: Ord n +        => Exp a n +        -> (UsedMap n, Exp (UsedMap n, a) n)++usageX' xx+ = case xx of+        XVar a u+         | used         <- accUsed u UsedOcc empty+         -> ( used+            , XVar (used, a) u)++        XCon a u+         -> ( empty+            , XCon (empty, a) u)++        -- Wrap usages from the body in UsedInLambda to singla that if we move+        -- the definition here then it might not be demanded at runtime.+        XLAM a b1 x2+         |  ( used2, x2')  <- usageX' x2+         ,  UsedMap us2    <- used2+         ,  used2'         <- UsedMap (Map.map (map UsedInLambda) us2)+         -> ( used2'+            , XLAM (used2', a) b1 x2')++        -- Wrap usages from the body in UsedInLambda to signal that if we move+        -- the definition here then it might not be demanded at runtime.+        XLam a b1 x2+         |  ( used2, x2')  <- usageX' x2+         ,  UsedMap us2    <- used2+         ,  used2'         <- UsedMap (Map.map (map UsedInLambda) us2)+         -> ( used2'+            , XLam (used2', a) b1 x2')++        XApp a x1 x2+         -- application of a function variable.+         |  XVar a1 u      <- x1+         ,  used1          <- accUsed u UsedFunction empty+         ,  (used2, x2')   <- usageX' x2+         ,  used'          <- used1 `plusUsedMap` used2+         -> ( used'+            , XApp (used', a) (XVar (used1, a1) u) x2')++         -- General application.+         |  ( used1, x1')  <- usageX' x1+         ,  ( used2, x2')  <- usageX' x2+         ,  used'          <- used1 `plusUsedMap` used2+         -> ( used'+            , XApp (used', a) x1' x2')++        XLet a lts x2+         |  ( used1, lts')  <- usageLets lts+         ,  ( used2, x2')   <- usageX' x2+         ,  used'           <- used1 `plusUsedMap` used2+         -> ( used'+            , XLet (used', a) lts' x2')++        -- Wrap usages in the Alts in UsedInAlt to signal that if we move+        -- the definition here then it might not be demanded at runtime.+        XCase a x1 alts+         |  ( used1, x1')   <- usageX' x1+         ,  ( usedA, alts') <- unzip $ map usageAlt alts+         ,  UsedMap usA     <- sumUsedMap usedA+         ,  usedA'          <- UsedMap (Map.map (map UsedInAlt) usA)+         ,  used'           <- plusUsedMap used1 usedA'+         -> ( used'+            , XCase (used', a) x1' alts' )++        XCast a c x1+         |  (used1, x1')   <- usageX' x1+         ,  (used2, c')    <- usageCast c+         ,  used'          <- plusUsedMap used1 used2+         -> ( used'+            , XCast (used', a) c' x1')++        XType t        +         -> (empty, XType t)++        XWitness w     +         -> (empty, XWitness w)+++-- | Annotate binding occurences of named variables with usage information.+usageLets +        :: Ord n+        => Lets a n +        -> (UsedMap n, Lets (UsedMap n, a) n)++usageLets lts+ = case lts of+        LLet mode b x+         |  (used, x')   <- usageX' x+         -> (used, LLet mode b x')++        LRec bxs+         |  (bs, xs)      <- unzip bxs+         ,  (useds', xs') <- unzip $ map usageX' xs+         ,  used'         <- sumUsedMap useds'+         -> (used', LRec $ zip bs xs')++        LLetRegions b bs +         -> (empty, LLetRegions b bs)++        LWithRegion b+         -> (empty, LWithRegion b)+++-- | Annotate binding occurrences of named value variables with +--  usage information.+usageCast  +        :: Ord n+        => Cast a n+        -> (UsedMap n, Cast (UsedMap n, a) n)+usageCast cc+ = case cc of+        CastWeakenEffect eff    +         -> (empty, CastWeakenEffect eff)++        CastWeakenClosure xs+         | (useds, xs')         <- unzip $ map usageX' xs+         , UsedMap used'        <- sumUsedMap useds+	 , usedCasts		<- Map.map (map $ const UsedInCast) used'+         -> (UsedMap usedCasts, CastWeakenClosure xs')++        CastPurify w+         -> (empty, CastPurify w)++        CastForget w+         -> (empty, CastForget w)+++-- | Annotate binding occurrences of named level-0 variables with+--   usage information.+usageAlt  +        :: Ord n +        => Alt a n  +        -> (UsedMap n, Alt (UsedMap n, a) n)++usageAlt (AAlt p x)+ = let  (used, x')      = usageX' x+   in   (used, AAlt p x')++
+ DDC/Core/Simplifier.hs view
@@ -0,0 +1,21 @@++module DDC.Core.Simplifier+        ( -- * Simplifier Specifications+          Simplifier(..)++          -- * Transform Specifications+        , Transform(..)+        , InlinerTemplates+        , NamedRewriteRules++          -- * Transform Results+        , TransformResult(..)+        , TransformInfo(..)+        , resultDone++          -- * Application+        , applySimplifier+        , applySimplifierX)+where+import DDC.Core.Simplifier.Apply+import DDC.Core.Simplifier.Base
+ DDC/Core/Simplifier/Apply.hs view
@@ -0,0 +1,240 @@++-- | Application of simplifiers to modules and expressions.+module DDC.Core.Simplifier.Apply+        ( applySimplifier+        , applyTransform+        , applySimplifierX+        , applyTransformX)+where+import DDC.Base.Pretty+import DDC.Core.Module+import DDC.Core.Exp+import DDC.Core.Fragment+import DDC.Core.Simplifier.Base+import DDC.Core.Transform.AnonymizeX+import DDC.Core.Transform.Snip+import DDC.Core.Transform.Flatten+import DDC.Core.Transform.Beta+import DDC.Core.Transform.Prune+import DDC.Core.Transform.Forward+import DDC.Core.Transform.Bubble+import DDC.Core.Transform.Inline+import DDC.Core.Transform.Namify+import DDC.Core.Transform.Rewrite+import DDC.Core.Transform.Elaborate+import DDC.Type.Env                     (KindEnv, TypeEnv)+import Data.Typeable                    (Typeable)+import Control.Monad.State.Strict+import Control.DeepSeq+import qualified DDC.Base.Pretty	as P+import qualified Data.Set               as Set+++-- Modules --------------------------------------------------------------------+-- | Apply a simplifier to a module.+--+--   The state monad can be used by `Namifier` functions to generate fresh names.+---+--   ISSUE #277: Make 'applySimplifier' return a TransformResult+--      Applying a simplifier to an expression yields a TransformResult+--      with the transform log, and we should get one for a module as well.+--+applySimplifier +        :: (Show a, Ord n, Show n, Pretty n, NFData a, NFData n) +	=> Profile n		-- ^ Profile of language we're working in+	-> KindEnv n		-- ^ Kind environment+	-> TypeEnv n		-- ^ Type environment+        -> Simplifier s a n     -- ^ Simplifier to apply+        -> Module a n           -- ^ Module to simplify+        -> State s (Module a n)++applySimplifier !profile !kenv !tenv !spec !mm+ = case spec of+        Seq t1 t2+         -> do  !mm'     <- applySimplifier profile kenv tenv t1 mm+                applySimplifier profile kenv tenv t2 mm'++        Trans t1+         -> applyTransform profile kenv tenv t1 mm+	+	Fix 0 _+	 -> return mm++	Fix !n !s+	 -> do	!mm' <- applySimplifier profile kenv tenv s mm+                applySimplifier profile kenv tenv (Fix (n - 1) s) mm'+++-- | Apply a transform to a module.+applyTransform+        :: (Show a, Ord n, Show n, Pretty n)+	=> Profile n		-- ^ Profile of language we're working in+	-> KindEnv n		-- ^ Kind environment+	-> TypeEnv n		-- ^ Type environment+        -> Transform s a n      -- ^ Transform to apply.+        -> Module a n           -- ^ Module to simplify.+        -> State s (Module a n)++applyTransform !profile !_kenv !_tenv !spec !mm+ = case spec of+        Id               -> return mm+        Anonymize        -> return $ anonymizeX mm+        Snip             -> return $ snip False mm+        SnipOver         -> return $ snip True mm+        Flatten          -> return $ flatten mm+        Beta             -> return $ result $ betaReduce False mm+        BetaLets         -> return $ result $ betaReduce True  mm+        Forward          -> return $ forwardModule profile mm+        Bubble           -> return $ bubbleModule mm+        Namify namK namT -> namifyUnique namK namT mm+        Inline getDef    -> return $ inline getDef Set.empty mm+        Rewrite rules    -> return $ rewriteModule rules mm+        Prune            -> return $ pruneModule profile mm+        Elaborate        -> return $ elaborateModule mm+++-- Expressions ----------------------------------------------------------------+-- | Apply a simplifier to an expression.+--+--   The state monad can be used by `Namifier` functions to generate fresh names.+--+applySimplifierX +        :: (Show a, Show n, Ord n, Pretty n)+	=> Profile n		-- ^ Profile of language we're working in+	-> KindEnv n		-- ^ Kind environment+	-> TypeEnv n		-- ^ Type environment+        -> Simplifier s a n     -- ^ Simplifier to apply+        -> Exp a n              -- ^ Expression to simplify+        -> State s (TransformResult (Exp a n))++applySimplifierX !profile !kenv !tenv !spec !xx+ = let down = applySimplifierX profile kenv tenv+   in  case spec of+        Seq t1 t2+         -> do  tx  <- down t1 xx+                tx' <- down t2 (result tx)++		let info =+			case (resultInfo tx, resultInfo tx') of+			(TransformInfo i1, TransformInfo i2) -> SeqInfo i1 i2+		+                let again    = resultAgain    tx || resultAgain    tx'+                let progress = resultProgress tx || resultProgress tx'++		return TransformResult+                        { result         = result tx'+                        , resultAgain    = again+                        , resultProgress = progress+                        , resultInfo     = TransformInfo info }++	Fix i s+	 -> do	tx      <- applyFixpointX profile kenv tenv i s xx+		let info =+			case resultInfo tx of+			TransformInfo info1 -> FixInfo i info1+		+		return TransformResult+                        { result         = result tx+                        , resultAgain    = resultAgain    tx+                        , resultProgress = resultProgress tx+                        , resultInfo     = TransformInfo info }+		+        Trans t1+         -> applyTransformX profile kenv tenv t1 xx+++-- | Apply a simplifier until it stops progressing, or a maximum number of times+applyFixpointX+        :: (Show a, Show n, Ord n, Pretty n)+	=> Profile n		-- ^ Profile of language we're working in+	-> KindEnv n		-- ^ Kind environment+	-> TypeEnv n		-- ^ Type environment+        -> Int			-- ^ Maximum number of times to apply+	-> Simplifier s a n     -- ^ Simplifier to apply.+        -> Exp a n              -- ^ Exp to simplify.+        -> State s (TransformResult (Exp a n))++applyFixpointX !profile !kenv !tenv !i' !s !xx'+ = go i' xx' False+ where+  simp = applySimplifierX profile kenv tenv s++  go 0 xx progress +   = do tx <- simp xx+        return tx { resultProgress = progress }++  go i xx progress +   = do tx      <- simp xx+        case resultAgain tx of+	 False +          ->    return tx { resultProgress = progress }++	 True  +          -> do tx'        <- go (i-1) (result tx) True++	        let info +                     = case (resultInfo tx, resultInfo tx') of+	                (TransformInfo i1, TransformInfo i2) +                          -> SeqInfo i1 i2++	        return TransformResult+                        { result   	 = result tx'+                        , resultAgain    = resultProgress tx'+                        , resultProgress = resultProgress tx'+                        , resultInfo     = TransformInfo info }+++-- | Result of applying two simplifiers in sequence.+data SeqInfo+        = forall i1 i2+        . (Typeable i1, Typeable i2, Pretty i1, Pretty i2)+        => SeqInfo i1 i2+        deriving Typeable+++instance Pretty SeqInfo where+ ppr (SeqInfo i1 i2) = ppr i1 P.<> text ";" <$> ppr i2+++-- | Result of applying a simplifier until we reach a fixpoint.+data FixInfo+        = forall i1+        . (Typeable i1, Pretty i1)+        => FixInfo Int i1+        deriving Typeable+++instance Pretty FixInfo where+ ppr (FixInfo num i1) +  =  text "fix" <+> int num P.<> text ":"+  <$> indent 4 (ppr i1)+++-- | Apply a single transform to an expression.+applyTransformX +        :: (Show a, Show n, Ord n, Pretty n)+	=> Profile n		-- ^ Profile of language we're working in+	-> KindEnv n		-- ^ Kind environment+	-> TypeEnv n		-- ^ Type environment+        -> Transform s a n      -- ^ Transform to apply.+        -> Exp a n              -- ^ Exp  to transform.+        -> State s (TransformResult (Exp a n))++applyTransformX !profile !kenv !tenv !spec !xx+ = let  res x = return $ resultDone (show $ ppr spec) x+   in case spec of+        Id                -> res xx+        Anonymize         -> res    $ anonymizeX xx+        Snip              -> res    $ snip False xx+        SnipOver          -> res    $ snip True xx+        Flatten           -> res    $ flatten xx+        Inline  getDef    -> res    $ inline getDef Set.empty xx+        Beta              -> return $ betaReduce False xx+        BetaLets          -> return $ betaReduce True  xx+        Prune             -> return $ pruneX   profile kenv tenv xx+        Forward           -> return $ forwardX profile xx+        Bubble            -> res    $ bubbleX kenv tenv xx+        Namify  namK namT -> namifyUnique namK namT xx >>= res+        Rewrite rules     -> return $ rewriteX rules xx+        Elaborate{}       -> res    $ elaborateX xx+    
+ DDC/Core/Simplifier/Base.hs view
@@ -0,0 +1,207 @@++module DDC.Core.Simplifier.Base+        ( -- * Simplifier Specifications+          Simplifier(..)++          -- * Transform Specifications+        , Transform(..)+        , InlinerTemplates+        , NamedRewriteRules++          -- * Transform Results+        , TransformResult(..)+	, TransformInfo(..)+	, NoInformation(..)+	, resultDone)+where+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 Data.Monoid+import Data.Typeable (Typeable)+++-- Simplifier -----------------------------------------------------------------+-- | Specification of how to simplify a core program.+data Simplifier s a n+        -- | Apply a single transform.+        = Trans (Transform s a n)++        -- | Apply two simplifiers in sequence.+        | Seq   (Simplifier s a n) (Simplifier s a n)++        -- | Keep applying a transform until it reports that further+        --   applications won't be helpful, bailing out after a maximum number+        --   of applications.+	| Fix	Int		   (Simplifier s a n)+++instance Monoid (Simplifier s a n) where+ mempty  = Trans Id+ mappend = Seq+++instance Pretty (Simplifier s a n) where+ ppr ss+  = case ss of+        Seq s1 s2+         -> ppr s1 <+> text ";" <+> ppr s2++        Fix i s+         -> text "fix" <+> int i <+> ppr s++        Trans t1+         -> ppr t1+++-- Transform ------------------------------------------------------------------+-- | Individual transforms to apply during simplification.+data Transform s a n+        -- | The Identity transform returns the original program unharmed.+        = Id++        -- | Rewrite named binders to anonymous deBruijn binders.+        | Anonymize++        -- | Introduce let-bindings for nested applications.+        | Snip++        -- | Introduce let-bindings for nested applications and over-applied+        --   functions+        | SnipOver++        -- | Flatten nested let and case expressions.+        | Flatten++        -- | Perform beta reduction when the argument is not a redex.+        | Beta++        -- | Perform beta reduction, introducing new let-bindings for +        --   arguments that are redexes.+        | BetaLets++        -- | Remove unused, pure let bindings.+        | Prune++        -- | Float single-use bindings forward into their use sites.+        | Forward++        -- | Float casts outwards.+        | Bubble++        -- | Elaborate possible Const and Distinct witnesses that aren't+        --   otherwise in the program.+        | Elaborate++        -- | Inline definitions into their use sites.+        | Inline+                { -- | Get the unfolding for a named variable.+                  transInlineDef   :: InlinerTemplates a n }++        -- | Apply general rule-based rewrites.+        | Rewrite+                { -- | List of rewrite rules along with their names.+                  transRules       :: NamedRewriteRules a n }++        -- | Rewrite anonymous binders to fresh named binders.+        | Namify+                { -- | Create a namifier to make fresh type (level-1) +                  --   names that don't conflict with any already in this+                  --   environment.+                  transMkNamifierT :: Env n -> Namifier s n++                  -- | Create a namifier to make fresh value or witness (level-0) +                  --   names that don't conflict with any already in this+                  --   environment.+                , transMkNamifierX :: Env n -> Namifier s n }+++-- | Function to get the inliner template (unfolding) for the given name.+type InlinerTemplates a n +        = (n -> Maybe (Exp a n))++-- | Rewrite rules along with their names.+type NamedRewriteRules a n+        = [(String, RewriteRule a n)]+++instance Pretty (Transform s a n) where+ ppr ss+  = case ss of+        Id              -> text "Id"+        Anonymize       -> text "Anonymize"+        Snip            -> text "Snip"+        SnipOver        -> text "Snip"+        Flatten         -> text "Flatten"+        Beta            -> text "Beta"+        BetaLets        -> text "BetaLets"+        Prune           -> text "Prune"+        Forward         -> text "Forward"+        Bubble          -> text "Bubble"+        Inline{}        -> text "Inline"+        Namify{}        -> text "Namify"+        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/Lexer.hs view
@@ -0,0 +1,85 @@++module DDC.Core.Simplifier.Lexer+        ( Tok(..)+        , lexSimplifier)+where+import DDC.Data.Token+import DDC.Data.SourcePos+import Data.Char+++lexSimplifier +        :: (String -> Maybe n)  -- ^ Function to read a name.+        -> String               -- ^ String to parse.+        -> [Token (Tok n)]++lexSimplifier readName str+ = map (\t -> Token t (SourcePos "<simplifier spec>" 0 0)) + $ lexer readName str+++-- Lexer ----------------------------------------------------------------------+-- | Lex a transform specification.+lexer   :: (String -> Maybe n)  -- ^ Function to read a name.+        -> String               -- ^ String to parse.+        -> [Tok n]++lexer readName ss+ = let down = lexer readName+   in case ss of+        []              -> []++        (';' : cs)      -> KSemiColon   : down cs+        (',' : cs)      -> KComma       : down cs+        ('-' : cs)      -> KMinus       : down cs+        ('+' : cs)      -> KPlus        : down cs+        ('{' : cs)      -> KBraceBra    : down cs+        ('}' : cs)      -> KBraceKet    : down cs+        ('[' : cs)      -> KSquareBra   : down cs+        (']' : cs)      -> KSquareKet   : down cs++        'f' : 'i' : 'x' : s : cs  +         | isSpace s    -> KFix         : down cs++        (c : cs)+         |  isSpace c+         -> down cs++        (c : cs)+         | isUpper c+         , (body, rest) <- span isAlpha cs+         -> KCon    (c : body) : down rest++        (c : cs)+         | isLower c+         , (body, rest) <- span isAlpha cs+         , Just n       <- readName (c : body)+         -> KVar  n : down rest++        (c : cs)+         | isDigit c+         , (digits, rest) <- span isDigit cs+         -> KInt (read (c:digits)) : down rest++        _ -> [KJunk ss]+++-- | Tokens for transform specification.+data Tok n+        = KEnd+        | KJunk  String+        | KCon   String+        | KVar   n+        | KInt   Int++        | KFix++        | KSemiColon+        | KComma+        | KMinus+        | KPlus+        | KBraceBra+        | KBraceKet+        | KSquareBra+        | KSquareKet+        deriving (Eq, Show)
+ DDC/Core/Simplifier/Parser.hs view
@@ -0,0 +1,227 @@++module DDC.Core.Simplifier.Parser+        ( SimplifierDetails     (..)+        , parseSimplifier)+where+import DDC.Core.Transform.Namify+import DDC.Core.Transform.Inline+import DDC.Core.Simplifier.Base+import DDC.Core.Module+import DDC.Type.Env+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+++-------------------------------------------------------------------------------+-- | Auxilliary information that may be used by a simplifier.+data SimplifierDetails s a n+        = SimplifierDetails+        { -- | Create a namifier to make fresh type (level-1) +          --   names that don't conflict with any already in this environment.+          simplifierMkNamifierT         :: Env n -> Namifier s n++          -- | Create a namifier to make fresh value or witness (level-0) +          --   names that don't conflict with any already in this environment.+        , simplifierMkNamifierX         :: Env n -> Namifier s n++          -- | Rewrite rules along with their names.+        , simplifierRules               :: NamedRewriteRules a n++          -- | Modules available for inlining.+        , simplifierTemplates           :: [Module a n] }+++-------------------------------------------------------------------------------+-- | A parser of simplifier specifications.+type Parser n a+        = P.Parser (Tok n) a++-- | Parse a simplifier from a string.+parseSimplifier+        :: (Ord n, Show n)+        => (String -> Maybe n)               -- Function to read a name.+        -> SimplifierDetails s a n+        -> String+        -> Either P.ParseError (Simplifier s a n)++parseSimplifier readName details str+ = let  kend    = Token KEnd (SourcePos "<simplifier spec>" 0 0)+        toks    = lexSimplifier readName str ++ [kend]+   in   P.runTokenParser show "<simplifier spec>" +                (pSimplifier details)+                toks+++-- | Parse a simplifier.+pSimplifier +        :: (Ord n, Show n)+        => SimplifierDetails s a n+        -> Parser n (Simplifier s a n)++pSimplifier details+ = do   simpl   <- pSimplifierSeq details+        pTok KEnd+        return simpl+++-- | Parse a simplifier sequence.+pSimplifierSeq +        :: (Ord n, Show n)+        => SimplifierDetails s a n+        -> Parser n (Simplifier s a n)++pSimplifierSeq details+ = P.choice+ [ do   -- Single Transform or Sequence.+        simpl0  <- pSimplifier0 details++        P.choice+         [ do   pTok KSemiColon+                simpl1  <- pSimplifierSeq details+                return  $ Seq simpl0 simpl1++         , do   return simpl0 ]+ ]+++pSimplifier0+        :: (Ord n, Show n)+        => SimplifierDetails s a n+        -> Parser n (Simplifier s a n)++pSimplifier0 details+ = P.choice+ [      -- Fixpoint transform.+        --  fix INT SIMP+   do   pTok KFix+        maxIters <- pInt+        simp     <- pSimplifier0 details+        return  $ Fix maxIters simp++ , do   -- Atomic transform.+        trans   <- pTransform details+        return  $ Trans trans++ , do   -- Simplifier in braces+        --  { SIMP }+        pTok KBraceBra+        simpl   <- pSimplifierSeq details+        pTok KBraceKet+        return simpl+ ]+++-- | Parse a single transform.+pTransform +        :: (Ord n, Show n)+        => SimplifierDetails s a n+        -> Parser n (Transform s a n)++pTransform details+ = P.choice+ [      -- Single transforms with no parameters.+   do   trans   <- P.pTokMaybe readTransformAtomic+        return trans++        -- Namifier+ , do   pTok (KCon "Namify")+        return  $ Namify (simplifierMkNamifierT details)+                         (simplifierMkNamifierX details)++        -- Rewrite+ , do   pTok (KCon "Rewrite")+        return  $ Rewrite (simplifierRules details) ++        -- Inline+ , do   pTok (KCon "Inline")+        let modules     = simplifierTemplates details+        specs           <- P.many pInlinerSpec+        let specsMap    = Map.fromList specs+        return  $ Inline (lookupTemplateFromModules specsMap modules) ]+++-- | Parse an inlining specification.+pInlinerSpec +        :: (Ord n, Show n)+        => Parser n (ModuleName, InlineSpec n)++pInlinerSpec + = P.choice + [ do   modname  <- pModuleName+        P.choice+         [ pInlinerSpecIncludeList modname+         , pInlinerSpecExcludeList modname+         , return (modname, InlineSpecAll modname (Set.empty :: Set n)) ]+ ]++-- Inline all bindings in a module, except particulars.+--   Inline MODULENAME +[VAR1, VAR2, ... VARn]+--   Inline MODULENAME  [VAR1, VAR2, ... VARn]+pInlinerSpecIncludeList modname+ = do   P.choice [ pTok KPlus, return () ]+        pTok KSquareBra+        ns      <- P.sepEndBy pVar (pTok KComma)+        pTok KSquareKet+        return  $ (modname, InlineSpecNone modname (Set.fromList ns))+++-- Inline no bindings in a module by default,+--   but include some particulars.+--   Inline MODULENAME -[VAR1, VAR2, ... VARn]+pInlinerSpecExcludeList modname+ = do   pTok KMinus+        pTok KSquareBra+        ns      <- P.sepEndBy pVar (pTok KComma)+        pTok KSquareKet+        return  $ (modname, InlineSpecAll modname (Set.fromList ns))+++-- | Read an atomic transform name.+readTransformAtomic :: Tok n -> Maybe (Transform s a n)+readTransformAtomic kk+ | KCon name  <- kk+ = case name of+        "Id"            -> Just Id+        "Anonymize"     -> Just Anonymize+        "Snip"          -> Just Snip+        "SnipOver"      -> Just SnipOver+        "Flatten"       -> Just Flatten+        "Beta"          -> Just Beta+        "BetaLets"      -> Just BetaLets+        "Prune"         -> Just Prune+        "Forward"       -> Just Forward+        "Bubble"        -> Just Bubble+        "Elaborate"     -> Just Elaborate+        _               -> Nothing++ | otherwise+ = Nothing+++-- | Parse a variable name+pVar :: Parser n n+pVar = P.pTokMaybe f+ where  f (KVar n) = Just n+        f _        = Nothing+++-- | Parse an integer.+pInt :: Parser n Int+pInt = P.pTokMaybe f+ where  f (KInt i) = Just i+        f _        = Nothing+++-- | Parse a module name.+pModuleName :: Parser n ModuleName+pModuleName = P.pTokMaybe f+ where  f (KCon n) = Just $ ModuleName [n]+        f _        = Nothing++
+ DDC/Core/Simplifier/Recipe.hs view
@@ -0,0 +1,110 @@++-- | Common simplifier recipes that combine multiple transforms.+module DDC.Core.Simplifier.Recipe+        ( -- * Atomic recipies+          idsimp+        , anonymize+        , snip+        , snipOver+        , flatten+        , beta+        , betaLets+        , prune+        , forward+        , bubble+        , elaborate++          -- * Compound recipies+        , anormalize+	, rewriteSimp)+where+import DDC.Core.Simplifier.Base+import DDC.Core.Transform.Namify+import DDC.Type.Env+import Data.Monoid+++-- Atomic ---------------------------------------------------------------------+-- These are short names for single transforms.++-- | The identity simplifier returns the code unharmed.+idsimp    :: Simplifier s a n+idsimp    = Trans Id+++-- | Rewrite named binders to anonymous debruijn binders.+anonymize :: Simplifier s a n+anonymize = Trans Anonymize+++-- | Introduce let-bindings for nested applications.+snip      :: Simplifier s a n+snip      = Trans Snip+++-- | Introduce let-bindings for nested applications.+snipOver  :: Simplifier s a n+snipOver  = Trans SnipOver+++-- | Flatten nested let and case expressions.+flatten   :: Simplifier s a n+flatten   = Trans Flatten+++-- | Perform beta reduction+beta    :: Simplifier s a n+beta    = Trans Beta+++-- | Perform beta reduction, introducing let-expressions for compound arguments.+betaLets :: Simplifier s a n+betaLets = Trans BetaLets+++-- | Remove unused, pure let bindings.+prune  :: Simplifier s a n+prune   = Trans Prune+++-- | Float single-use bindings forward into their use sites.+forward  :: Simplifier s a n+forward  = Trans Forward+++-- | Float casts outwards.+bubble   :: Simplifier s a n+bubble   = Trans Bubble+++-- | Elaborate possible Const and Distinct witnesses that aren't+--   otherwise in the program.+elaborate :: Simplifier s a n+elaborate = Trans Elaborate+++-- Compound -------------------------------------------------------------------+-- | Conversion to administrative normal-form.+anormalize +        :: (KindEnv n -> Namifier s n) +                -- ^ Make a namifier to create fresh level-1 names.+        -> (TypeEnv n -> Namifier s n) +                -- ^ Make a namifier to create fresh level-0 names.+        -> Simplifier s a n++anormalize namK namT+        =  Trans Snip +        <> Trans Flatten +        <> Trans (Namify namK namT)+++-- | Intersperse rewrites and beta reduction+rewriteSimp+        :: Int                          -- ^ Maximum number of iterations.+        -> NamedRewriteRules a n        -- ^ Rewrite rules to apply.+	-> Simplifier s a n++rewriteSimp maxIters rules+ = let  rewrite = Trans $ Rewrite rules+   in   Fix maxIters (rewrite <> bubble <> betaLets)+
− DDC/Core/Transform/ANormal.hs
@@ -1,253 +0,0 @@--module DDC.Core.Transform.ANormal-    (anormalise)-where-import DDC.Core.Exp-import qualified DDC.Type.Exp as T-import qualified DDC.Type.Compounds as T-import qualified DDC.Core.Transform.AnonymizeX as A-import qualified DDC.Core.Transform.LiftX as L--import qualified Data.Map as Map---- **** Recording arities of known values--- So we can try to create apps to fully apply ---- | Arities of known bound variables.--- We need to track everything even if it's not a function to keep indices correct.--- Just use zero for unknown/irrelevant-type Arities n = (Map.Map n Int, [Int])---- | Empty arities context-arEmpty :: Ord n => Arities n-arEmpty = (Map.empty, [])---- | Extend map with multiple bindings and their arities-arExtends :: Ord n => Arities n -> [(Bind n, Int)] -> Arities n-arExtends arity exts = foldl go arity exts- where	go (named,anon) (BNone _t,   _)    = (named,anon)-	go (named,anon) (BAnon _t,   a)    = (named, a:anon)-	go (named,anon) (BName n _t, a) = (Map.insert n a named, anon)---- | Look up a binder's arity-arGet :: Ord n => Arities n -> Bound n -> Int-arGet (_named, anon) (UIx ix _)	  = anon !! ix-arGet (named, _anon) (UName n _)  = named Map.! n--- Get a primitive's arity from its type-arGet (_named,_anon) (UPrim _ t)  = arityOfType t---- **** Finding arities of expressions etc---- | Count all the arrows and foralls, ignoring any effects--- We can be sure that primitives don't effect until they're fully applied-arityOfType :: Ord n => Type n -> Int-arityOfType (T.TForall _ t)- =  1 + arityOfType t-arityOfType t- =  let (args, _) = T.takeTFunArgResult t in-    length args---- | Find arity of an expression. Count lambdas, use type for primitives-arityOfExp :: Ord n => Exp a n -> Int--- Counting all binders, because they all correspond to XApps.-arityOfExp (XLam _ _ e)-    = 1 + arityOfExp e-arityOfExp (XLAM _ _ e)-    = 1 + arityOfExp e--- Find primitive's constructor's arities from type,--- we might need to do this for user defined constructors too.-arityOfExp (XCon _ (UPrim _ t))-    = arityOfType t--- Anything else we'll need to apply one at a time-arityOfExp _-    = 0---- | Retrieve binders from case pattern, so we can extend the arity context.--- We don't know anything about their values, so record as 0.-aritiesOfPat :: Ord n => Pat n -> [(Bind n, Int)]-aritiesOfPat PDefault = []-aritiesOfPat (PData _b bs) = zip bs (repeat 0)----- **** Actually converting to a-normal form---- | Recursively transform expression into a-normal-anormal :: Ord n-	=> Arities n	-- ^ environment, arities of bound variables-	-> Exp a n	-- ^ expression to transform-	-> [(Exp a n,a)]-- ^ arguments being applied to current expression-	-> Exp a n---- Application: just record argument and descend into function-anormal ar (XApp a lhs rhs) args- =  -- normalise rhs and add to arguments-    let args' = (anormal ar rhs [], a) : args in-    -- descend into lhs, remembering all args-    anormal ar lhs args'---- Anything other than application: if we're applied to arguments add bindings,--- otherwise just recurse.-anormal ar x args- =  let x' = go x in-    case args of-	-- if there are no args, we're done-	[] -> x'-	-- there are arguments. we must apply them.-	_  -> flattenLets $ makeLets ar x' args- where-    -- helper for descent-    down ars e = anormal (arExtends ar ars) e []--    -- we know x isn't an app.-    go (XApp{}) = error "DDC.Core.Transform.ANormal.anormal: impossible XApp!"--    -- leafy ones-    go (XVar{}) = x-    go (XCon{}) = x-    go (XType{}) = x-    go (XWitness{}) = x--    -- lambdas-    go (XLAM a b e) =-	XLAM a b (down [(b,0)] e)-    go (XLam a b e) =-	XLam a b (down [(b,0)] e)--    -- non-recursive let-    go (XLet a (LLet m b le) re) =-	let le' = down [] le in-	let re' = down [(b, arityOfExp le')] re in-	XLet a (LLet m b le') re'--    -- recursive let-    go (XLet a (LRec lets) re) =-	let bs = map fst lets in-	let es = map snd lets in-	let ars= zip bs (map arityOfExp es) in-	let es'= map (down ars) es in-	let re'= down ars re in-	XLet a (LRec $ zip bs es') re' --    -- letregion, just make sure we record bindings with dummy val-    go (XLet a (LLetRegion b bs) re) =-	let ars = zip bs (repeat 0) in-	XLet a (LLetRegion b bs) (down ars re)--    -- withregion: I don't think this should ever show up.-    go (XLet a (LWithRegion b) re) =-	XLet a (LWithRegion b) (down [] re)--    -- case-    go (XCase a e alts) =-	let e' = down [] e in-	let alts' = map (\(AAlt pat ae) -> AAlt pat (down (aritiesOfPat pat) ae)) alts in-	XCase a e' alts'--    -- cast-    go (XCast a c e) =-	XCast a c (down [] e)----- | Convert an expression into a-normal form-anormalise :: Ord n => Exp a n -> Exp a n-anormalise x = anormal arEmpty x []---- | Check if an expression needs a binding, or if it's simple enough to be applied as-is-isNormal :: Ord n => Exp a n -> Bool--- Trivial expressions-isNormal (XVar{}) = True-isNormal (XCon{}) = True-isNormal (XType{}) = True-isNormal (XWitness{}) = True--- Casts are ignored by code generator, so we can leave them in if their subexpression is normal-isNormal (XCast _ _ x) = isNormal x-isNormal _ = False-	--- | Create lets for any non-trivial arguments-makeLets :: Ord n-	=> Arities n	-- ^ environment, arities of bound variables-	-> Exp a n	-- ^ function-	-> [(Exp a n,a)]-- ^ arguments being applied to current expression-	-> Exp a n-makeLets _  f0 [] = f0-makeLets ar f0 args@((_,annot):_) = go 0 (findArity f0) ((f0,annot):args) []- where-    tBot = T.tBot T.kData--    -- out of arguments, create XApps out of leftovers-    go i _arf [] acc = mkApps i 0 acc-    -- f is fully applied and we have arguments left to add:-    --	create let for intermediate result-    go i arf ((x,a):xs) acc | length acc > arf-     =  XLet a (LLet LetStrict (BAnon tBot) (mkApps i 0 acc))-            (go i 1 ((x,a):xs) [(XVar a $ UIx 0 tBot,a)])-    -- application to variable, don't bother binding-    go i arf ((x,a):xs) acc | isNormal x-     =  go i arf xs ((x,a):acc)-    -- non-trivial argument, create binding-    go i arf ((x,a):xs) acc-     =  XLet a (LLet LetStrict (BAnon tBot) (L.liftX i x))-	    (go (i+1) arf xs ((x,a):acc))-    -    -- fold list into applications-    -- can't create empty app-    mkApps _ _ []-     = error "DDC.Core.Transform.ANormal.makeLets.mkApps: impossible empty list"--    -- single element - this is the function-    mkApps l _ [(x,_)] | isNormal x-     = L.liftX l x-    mkApps _ i [(_,a)]-     = XVar a $ UIx i tBot--    -- apply this argument and recurse-    mkApps l i ((x,a):xs) | isNormal x-     = XApp a (mkApps l i xs) (L.liftX l x)-    mkApps l i ((_,a):xs)-     = XApp a (mkApps l (i+1) xs) (XVar a $ UIx i tBot)--    findArity (XVar _ b) = max (arGet ar b) 1-    findArity x          = max (arityOfExp x) 1---- | Perform let-floating on strict non-recursive lets--- Only does the top level, to clean up the ones directly produced by makeLets.--- let b1 = (let b2 = def2 in x2)--- in x1--- ==>--- let b2 = def2--- in let b1 = x2--- in x1-flattenLets :: Ord n-	=> Exp a n-	-> Exp a n---- We only do this if b2 is anonymous (ones generated by makeLets are).--- If we tried to wrap x1 in b2 when b2's name is already used,--- we'd be in trouble.-flattenLets-    (XLet a1-	(LLet LetStrict b1-	    (XLet a2 (LLet LetStrict b2@(BAnon _) def2) x2))-	x1)- =  -- If b1 is anon, we don't want to lift references to it-    let liftDepth = case b1 of { BAnon _ -> 1; _ -> 0 } in-    let x1'	  = L.liftAtDepthX 1 liftDepth x1 in-    XLet a2 (LLet LetStrict b2 def2) $-	flattenLets $ XLet a1 (LLet LetStrict b1 x2) x1'---- Same as above but b2 isn't anonymous - anonymize inner let & re-flatten.-flattenLets-    (XLet a1-	(LLet LetStrict b1 inner@(XLet _ (LLet LetStrict _ _) _))-	x1)- =  flattenLets $-	XLet a1-	    (LLet LetStrict b1 (A.anonymizeX inner))-	    x1---- Any let, its bound expression doesn't contain a strict non-recursive let so just flatten the body-flattenLets (XLet a1 llet1 x1)- =  XLet a1 llet1 (flattenLets x1)---- Anything else we can ignore. We don't need to recurse, because this is always called immediately after makeLets.-flattenLets x = x
DDC/Core/Transform/AnonymizeX.hs view
@@ -1,19 +1,24 @@ +-- | Rewrite all binders to anonymous deBruijn form. module DDC.Core.Transform.AnonymizeX         ( anonymizeX-        , AnonymizeX(..))+        , AnonymizeX(..)+        , pushAnonymizeBindX) where+import DDC.Core.Module 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+import qualified Data.Map               as Map --- | Rewrite all binders in a thing to be of anonymous form.+-- | Rewrite all binders in a thing to anonymous form. anonymizeX :: (Ord n, AnonymizeX c) => c n -> c n anonymizeX xx-        = anonymizeWithX [] [] xx+        = anonymizeWithX Set.empty [] [] xx   -------------------------------------------------------------------------------@@ -25,31 +30,54 @@  --   will be replaced by references into these stacks.  anonymizeWithX          :: forall n. Ord n -        => [Bind n]     -- ^ Stack for Spec binders (level-1).+        => Set n        -- ^ Don't anonymize level-0 binders with these names.+        -> [Bind n]     -- ^ Stack for Spec binders (level-1).         -> [Bind n]     -- ^ Stack for Data and Witness binders (level-0).         -> c n -> c n +instance AnonymizeX (Module a) where+ anonymizeWithX keep kstack tstack mm@ModuleCore{}+  = let +        -- We need to keep exported names, +        -- because the export list can't deal with anonymous binders.+        keep'   = Set.union keep +                        $ Set.fromList +                        $ Map.keys $ moduleExportTypes mm +        x'      = anonymizeWithX keep' kstack tstack (moduleBody mm)++    in  mm { moduleBody = x' }++ instance AnonymizeX (Exp a) where- anonymizeWithX kstack tstack xx-  = let down = anonymizeWithX kstack tstack+ anonymizeWithX keep kstack tstack xx+  = {-# SCC anonymizeWithX #-}+    let down = anonymizeWithX keep kstack tstack     in case xx of-        XVar a u        -> XVar a (down u)-        XCon a u        -> XCon a (down u)+        XVar _ UPrim{}  -> xx+        XCon{}          -> xx      ++        XVar a u@(UName{})       +         |  Just ix      <- findIndex (boundMatchesBind u) tstack+         -> XVar a (UIx ix)++        XVar a u+         -> XVar a u+         XApp a x1 x2    -> XApp a (down x1) (down x2)          XLAM a b x          -> let (kstack', b')   = pushAnonymizeBindT kstack b-            in  XLAM a b'   (anonymizeWithX kstack' tstack x)+            in  XLAM a b'   (anonymizeWithX keep kstack' tstack x)          XLam a b x-         -> let (tstack', b')   = pushAnonymizeBindX kstack tstack b-            in  XLam a b'   (anonymizeWithX kstack tstack' x)+         -> let (tstack', b')   = pushAnonymizeBindX keep kstack tstack b+            in  XLam a b'   (anonymizeWithX keep kstack tstack' x)          XLet a lts x          -> let (kstack', tstack', lts')  -                 = pushAnonymizeLets kstack tstack lts-            in  XLet a lts' (anonymizeWithX kstack' tstack' x)+                 = pushAnonymizeLets keep kstack tstack lts+            in  XLet a lts' (anonymizeWithX keep kstack' tstack' x)          XCase a x alts  -> XCase a  (down x) (map down alts)         XCast a c x     -> XCast a  (down c) (down x)@@ -57,39 +85,53 @@         XWitness w      -> XWitness (down w)  -instance AnonymizeX Cast where- anonymizeWithX kstack tstack cc-  = case cc of-        CastWeakenEffect eff    -> CastWeakenEffect  (anonymizeWithT kstack eff)-        CastWeakenClosure clo   -> CastWeakenClosure (anonymizeWithT kstack clo)-        CastPurify w            -> CastPurify   (anonymizeWithX kstack tstack w)-        CastForget w            -> CastForget   (anonymizeWithX kstack tstack w)+instance AnonymizeX (Cast a) where+ 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 kstack tstack lm-  = case lm of+ anonymizeWithX keep kstack tstack lm+  = let down = anonymizeWithX keep kstack tstack+    in case lm of         LetStrict       -> lm-        LetLazy mw      -> LetLazy $ liftM (anonymizeWithX kstack tstack) mw+        LetLazy mw      -> LetLazy $ liftM down mw   instance AnonymizeX (Alt a) where- anonymizeWithX kstack tstack alt-  = case alt of+ anonymizeWithX keep kstack tstack alt+  = let down = anonymizeWithX keep kstack tstack+    in case alt of         AAlt PDefault x-         -> AAlt PDefault (anonymizeWithX kstack tstack x)+         -> AAlt PDefault (down x)          AAlt (PData uCon bs) x-         -> let (tstack', bs')  = pushAnonymizeBindXs kstack tstack bs-                x'              = anonymizeWithX kstack tstack' x+         -> let (tstack', bs')  = pushAnonymizeBindXs keep kstack tstack bs+                x'              = anonymizeWithX keep kstack tstack' x             in  AAlt (PData uCon bs') x'   instance AnonymizeX Witness where- anonymizeWithX kstack tstack ww-  = let down = anonymizeWithX kstack tstack + anonymizeWithX keep kstack tstack ww+  = let down = anonymizeWithX keep kstack tstack      in case ww of-        WVar  u         -> WVar  (down u)+        WVar u@(UName _)+         |  Just ix      <- findIndex (boundMatchesBind u) tstack+         -> WVar (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)@@ -97,78 +139,83 @@   instance AnonymizeX Bind where- anonymizeWithX kstack _tstack bb+ anonymizeWithX _keep kstack _tstack bb   = let t'      = anonymizeWithT kstack $ typeOfBind bb     in  replaceTypeOfBind t' bb   -instance AnonymizeX Bound where - anonymizeWithX kstack tstack bb-  = case bb of-        UName _ t-         | Just ix      <- findIndex (boundMatchesBind bb) tstack-         -> UIx ix (anonymizeWithT kstack t)-         -        _ -> bb-- -- Push ------------------------------------------------------------------------- Push a binding occurrence of a type variable on the stack, ---  returning the anonyized binding occurrence and the new stack.+-- | Push a binding occurrence of a level-0 on the stack, +--   returning the anonyized binding occurrence and the new stack. pushAnonymizeBindX          :: Ord n -        => [Bind n]     -- ^ Stack for Spec binders (kind environment)-        -> [Bind n]     -- ^ Stack for Value and Witness binders (type environment)+        => Set n        -- ^ Don't anonymize binders with these names.+        -> [Bind n]     -- ^ Stack for Spec binders (level-1)+        -> [Bind n]     -- ^ Stack for Value and Witness binders (level-0)         -> Bind n          -> ([Bind n], Bind n) -pushAnonymizeBindX kstack tstack b- = let  b'      = anonymizeWithX kstack tstack b+pushAnonymizeBindX keep kstack tstack b@(BName n _)+ | Set.member n keep+ = let  b'      = anonymizeWithX keep kstack tstack b+   in  (tstack, b')++pushAnonymizeBindX keep kstack tstack b@BNone{}+ = let  b'      = anonymizeWithX keep kstack tstack b         t'      = typeOfBind b'+   in   (tstack,  BNone t')++pushAnonymizeBindX keep kstack tstack b+ = let  b'      = anonymizeWithX keep kstack tstack b+        t'      = typeOfBind b'         tstack' = b' : tstack    in   (tstack', BAnon t')  --- Push a binding occurrence on the stack, ---  returning the anonyized binding occurrence and the new stack.--- Used in the definition of `anonymize`.+-- | Push a binding occurrence on the stack, +--   returning the anonyized binding occurrence and the new stack.+--  Used in the definition of `anonymize`. pushAnonymizeBindXs          :: Ord n -        => [Bind n]     -- ^ Stack for Spec binders (kind environment)-        -> [Bind n]     -- ^ Stack for Value and Witness binders (type environment)+        => Set n        -- ^ Don't anonymize binders with these names.+        -> [Bind n]     -- ^ Stack for Spec binders (level-1)+        -> [Bind n]     -- ^ Stack for Value and Witness binders (level-0)         -> [Bind n]          -> ([Bind n], [Bind n]) -pushAnonymizeBindXs kstack tstack bs-  = mapAccumL   (\tstack' b -> pushAnonymizeBindX kstack tstack' b)-                tstack bs+pushAnonymizeBindXs keep kstack tstack bs+  = mapAccumL+        (\tstack' b -> pushAnonymizeBindX keep kstack tstack' b)+        tstack bs   pushAnonymizeLets          :: Ord n -        => [Bind n] -> [Bind n] +        => Set n+        -> [Bind n] +        -> [Bind n]          -> Lets a n          -> ([Bind n], [Bind n], Lets a n) -pushAnonymizeLets kstack tstack lts+pushAnonymizeLets keep kstack tstack lts  = case lts of         LLet mode b x-         -> let mode'           = anonymizeWithX     kstack tstack mode-                x'              = anonymizeWithX     kstack tstack x-                (tstack', b')   = pushAnonymizeBindX kstack tstack b+         -> let mode'           = anonymizeWithX     keep kstack tstack mode+                x'              = anonymizeWithX     keep kstack tstack x+                (tstack', b')   = pushAnonymizeBindX keep kstack tstack b             in  (kstack, tstack', LLet mode' b' x')          LRec bxs           -> let (bs, xs)        = unzip bxs-                (tstack', bs')  = pushAnonymizeBindXs kstack tstack   bs-                xs'             = map (anonymizeWithX kstack tstack') xs+                (tstack', bs')  = pushAnonymizeBindXs keep kstack tstack   bs+                xs'             = map (anonymizeWithX keep kstack tstack') xs                 bxs'            = zip bs' xs'             in  (kstack, tstack', LRec bxs') -        LLetRegion b bs-         -> let (kstack', b')   = pushAnonymizeBindT  kstack b-                (tstack', bs')  = pushAnonymizeBindXs kstack' tstack bs-            in  (kstack', tstack', LLetRegion b' bs')+        LLetRegions b bs+         -> let (kstack', b')   = mapAccumL pushAnonymizeBindT kstack b+                (tstack', bs')  = pushAnonymizeBindXs keep kstack' tstack bs+            in  (kstack', tstack', LLetRegions b' bs')          LWithRegion{}          -> (kstack, tstack, lts)
DDC/Core/Transform/Beta.hs view
@@ -1,40 +1,182 @@ +-- | Beta-reduce applications of a explicit lambda abstractions +--   to variables and values. module DDC.Core.Transform.Beta-        (betaReduce)+        ( BetaReduceInfo(..)+        , 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.SubstituteTX import DDC.Core.Transform.SubstituteWX import DDC.Core.Transform.SubstituteXX-import DDC.Type.Env             (Env)-import qualified DDC.Type.Env   as Env+import Control.Monad.Writer	        (Writer, runWriter, tell)+import Data.Monoid		        (Monoid, mempty, mappend)+import Data.Typeable		        (Typeable)+import DDC.Type.Env                     (Env)+import DDC.Type.Compounds+import qualified DDC.Type.Env           as Env+import qualified Data.Set               as Set  +-------------------------------------------------------------------------------+-- | A summary of what the beta reduction transform did.+data BetaReduceInfo+        = BetaReduceInfo+        { -- | Number of type applications reduced.+          infoTypes             :: Int++          -- | Number of witness applications reduced.+        , infoWits              :: Int++          -- | Number of value applications reduced.+        , infoValues            :: Int++          -- | Number of redexes let-bound.+        , infoValuesLetted      :: Int++          -- | Number of applications that we couldn't reduce.+        , infoValuesSkipped     :: Int }+        deriving Typeable+++instance Pretty BetaReduceInfo where+ ppr (BetaReduceInfo ty wit val lets skip)+  =  text "Beta reduction:"+  <$> indent 4 (vcat+      [ text "Types:          " <> int ty+      , text "Witnesses:      " <> int wit+      , text "Values:         " <> int val+      , text "Values letted:  " <> int lets+      , 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 +                (ty1   + ty2)   (wit1  + wit2) (val1 + val2)+                (lets1 + lets2) (skip1 + skip2))+++------------------------------------------------------------------------------- -- | Beta-reduce applications of a explicit lambda abstractions  --   to variables and values.-betaReduce  :: Ord n => Exp a n -> Exp a n-betaReduce -        = transformUpX betaReduce1 Env.empty Env.empty+--+--   If the flag is set then if we find a lambda abstraction that is applied+--   to a redex then let-bind the redex and substitute the new variable+--   instead.+betaReduce  +        :: forall (c :: * -> * -> *) a n +        .  (Ord n, TransformUpMX (Writer BetaReduceInfo) c)+        => Bool         -- ^ Let-bind redexes.+        -> c a n +        -> TransformResult (c a n)+betaReduce lets x+ = {-# SCC betaReduce #-}+   let (x', info) = runWriter+		  $ transformUpMX (betaReduce1 lets) Env.empty Env.empty x +       -- Check if any actual work was performed+       progress +        = case info of+                BetaReduceInfo ty wit val lets' _+                 -> (ty + wit + val + lets') > 0 -betaReduce1 :: Ord n => Env n -> Env n -> Exp a n -> Exp a n-betaReduce1 _ _ xx- = case xx of+   in  TransformResult+	{ result   	 = x'+        , resultAgain    = progress+	, resultProgress = progress+	, resultInfo	 = TransformInfo info }+++-- | Do a single beta reduction for this application.+--+--    To avoid duplicating work, we only reduce value applications when the+--    the argument is not a redex.+--+--    If needed, we also insert 'weakclo' to ensure the result has the same+--    closure as the original expression.+--    +betaReduce1+        :: Ord n+        => Bool	        -- ^ Let-bind redexes.+        -> Env n+        -> Env n+        -> Exp a n+        -> Writer BetaReduceInfo (Exp a n)++betaReduce1 lets _kenv tenv xx+ = let  ret info x = tell info >> return x+   in case xx of++        -- Substitute type arguments into type abstractions.+        --  If the type argument of the redex does not appear as an +        --  argument of the result then we need to add a closure weakening+        --  for the case where t2 was a region variable or handle.+        XApp a (XLAM _ b11 x12) (XType t2)+         | isRegionKind $ typeOfBind b11+         -> let sup             = support Env.empty Env.empty x12++                usUsed          = Set.unions+                                        [ supportTyConXArg sup+                                        , supportSpVarXArg sup ]++                usesBind        = any (flip boundMatchesBind b11)+                                $ Set.toList usUsed++                fvs2            = freeT Env.empty t2++            in  ret mempty { infoTypes = 1}+                 $ if usesBind || Set.null fvs2+                    then substituteTX b11 t2 x12+                    else XCast a (CastWeakenClosure [XType t2])+                        $ substituteTX b11 t2 x12++        -- Substitute type arguments into type abstractions,+        --  Where the argument is not a region type.         XApp _ (XLAM _ b11 x12) (XType t2)-         -> substituteTX b11 t2 x12+         -> ret mempty { infoTypes = 1 }+                 $ substituteTX b11 t2 x12 -        XApp _ (XLam _ b11 x12) (XWitness w2)-         -> substituteWX b11 w2 x12+        -- Substitute witness arguments into witness abstractions.+        XApp a (XLam _ b11 x12) (XWitness w2)+         -> let usesBind        = any (flip boundMatchesBind b11)+                                $ Set.toList $ freeX tenv x12+                fvs2            = freeX Env.empty w2+            in  ret mempty { infoWits = 1 }+                 $ if usesBind || Set.null fvs2+                    then substituteWX b11 w2 x12+                    else XCast a (CastWeakenClosure [XWitness w2])+                       $ substituteWX b11 w2 x12 -        XApp _ (XLam _ b11 x12) x2-         |  canBetaSubstX x2     -         -> substituteXX b11 x2 x12 +        -- Substitute value arguments into value abstractions.+        XApp a (XLam _ b11 x12) x2+         |  canBetaSubstX x2+         -> let usesBind        = any (flip boundMatchesBind b11) +                                $ Set.toList $ freeX tenv x12+                fvs2            = freeX Env.empty x2+            in  ret mempty { infoValues = 1 }+                 $ if usesBind || Set.null fvs2+                    then substituteXX b11 x2 x12+                    else XCast a (CastWeakenClosure [x2])+                       $ substituteXX b11 x2 x12++         | lets+         -> ret mempty { infoValuesLetted  = 1 }+	      $	XLet a (LLet LetStrict b11 x2) x12+          | otherwise-         -> xx+         -> ret mempty { infoValuesSkipped = 1 }+              $ xx -        _ -> xx+        _ -> return xx   -- | Check whether we can safely substitute this expression during beta@@ -43,6 +185,7 @@ --   We allow variables, abstractions, type and witness applications. --   Duplicating these expressions is guaranteed not to duplicate work --   at runtime,+-- canBetaSubstX :: Exp a n -> Bool canBetaSubstX xx  = case xx of
+ DDC/Core/Transform/Bubble.hs view
@@ -0,0 +1,346 @@++-- | Bubble casts outwards.+--   We float casts up and outwards so they are just inside the inner-most+--   enclosing let. This way the functions still have the same effect and+--   closure, but the casts don't get in the way of subsequent transforms.+--+module DDC.Core.Transform.Bubble+        ( bubbleModule+        , bubbleX)+where+import DDC.Core.Collect+import DDC.Core.Transform.LiftX+import DDC.Core.Predicates+import DDC.Core.Compounds+import DDC.Core.Module+import DDC.Core.Exp+import DDC.Type.Env                             (KindEnv, TypeEnv)+import qualified DDC.Type.Env                   as Env+import qualified DDC.Type.Sum                   as Sum+import qualified Data.Set                       as Set+import Data.Set                                 (Set)+import Data.List+++-- | Bubble casts outwards in a `Module`.+bubbleModule +        :: Ord n+        => Module a n -> Module a n++bubbleModule mm@ModuleCore{}+ = let  kenv    = moduleKindEnv mm+        tenv    = moduleTypeEnv mm+   in   mm { moduleBody = bubbleX kenv tenv (moduleBody mm) }+++-- | Bubble casts outwards in an `Exp`.+bubbleX :: Ord n+        => KindEnv n -> TypeEnv n -> Exp a n -> Exp a n+bubbleX kenv tenv x+ = let  +        -- Bubble the expression, yielding any casts that floated out+        -- to top-level.+        (cs, x')        = bubble kenv tenv x+        Just a          = takeAnnotOfExp x'++        -- Reattach top-level casts.+   in   dropAllCasts kenv tenv a cs x'+++-------------------------------------------------------------------------------+-- | Bubble casts outwards in some thing.+class Bubble (c :: * -> * -> *) where+ bubble :: Ord n+        => KindEnv n+        -> TypeEnv n+        -> c a n +        -> ([FvsCast a n], c a n)+++instance Bubble Exp where+ bubble kenv tenv xx+  = {-# SCC bubble #-}+    case xx of+        XVar{}  -> ([], xx)+        XCon{}  -> ([], xx)++        -- Drop casts before we leave lambda abstractions, because the+        -- function type depends on the effect and closure of the body.+        -- The cast could also reference the bound variable.+        XLAM a b x+         -> let kenv'           = Env.extend b kenv+                (cs, x')        = bubble kenv' tenv x+            in  ([], XLAM a b (dropAllCasts kenv' tenv a cs x'))++        XLam a b x+         -> let tenv'           = Env.extend b tenv+                (cs, x')        = bubble kenv tenv' x+            in  ([], XLam a b (dropAllCasts kenv tenv' a cs x'))++        -- Decend into applications.+        XApp a x1 x2+         -> let (cs1, x1')      = bubble kenv tenv x1+                (cs2, x2')      = bubble kenv tenv x2+            in  (cs1 ++ cs2, XApp a x1' x2')++        -- After decending into let-expressions, make sure to drop+        -- any casts that mention variables bound here.+        XLet a lts x2+         -> let (cs1, lts')     = bubble kenv tenv lts+                (bs1, bs0)      = bindsOfLets lts+                kenv'           = Env.extends bs1 kenv+                tenv'           = Env.extends bs0 tenv+                (cs2, x2')      = bubble kenv' tenv' x2+                (cs2', x2'')    = dropCasts kenv' tenv' a bs1 bs0 cs2 x2'+            in  ( cs1 ++ cs2'+                , XLet a lts' x2'')++        -- Decent into case-expressions.+        --  Casts that depend on bound variables are dropped +        --  in the corresponding alternatives.+        XCase a x alts+         -> let (cs, x')        = bubble kenv tenv x+                (css, alts')    = unzip $ map (bubble kenv tenv) alts+            in  ( cs ++ concat css+                , XCase a x' alts')++        -- Strip of cast and pass it up.+        XCast _ c x+         -> let (cs, x')        = bubble kenv tenv x+                fvsT            = freeT Env.empty c+                fvsX            = freeX Env.empty c+                fc              = FvsCast c fvsT fvsX+            in  (fc : cs, x')++        XType{}         -> ([], xx)+        XWitness{}      -> ([], xx)+++instance Bubble Lets where+ bubble kenv tenv lts+  = case lts of++        -- Drop casts that mention the bound variable here, +        -- but we can float the others further outwards.+        LLet m 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')++        -- ISSUE #299: Bubble casts out of recursive lets.+        LRec bxs+         -> let bs              = map fst bxs+                tenv'           = Env.extends bs tenv++                bubbleRec (b, x)+                 = let  (cs, x') = bubble kenv tenv' x+                        Just a   = takeAnnotOfExp x'+                   in   (b, dropAllCasts kenv tenv' a cs x')++                bxs'            = map bubbleRec bxs++            in  ([], LRec bxs')++        LLetRegions{}           -> ([], lts)+        LWithRegion{}           -> ([], lts)+++instance Bubble Alt where++ -- Default patterns don't bind variables, + -- so there is no problem floating casts outwards.+ bubble kenv tenv (AAlt PDefault x)+  = let (cs, x') = bubble kenv tenv x+    in  (cs, AAlt PDefault x')++ -- Drop casts before we leave the alt because they could contain+ -- variables bound by the pattern.+ bubble kenv tenv (AAlt p x)+  = let bs              = bindsOfPat p+        Just a          = takeAnnotOfExp x'+        tenv'           = Env.extends bs tenv+        (cs, x')        = bubble kenv tenv' x+        (csUp, xcHere)  = dropCasts kenv tenv' a [] bs cs x'+    in  (csUp, AAlt p xcHere)+++-- FvsCast --------------------------------------------------------------------+-- | A Cast along with its free level-1 and level-0 vars.+--   When we first build a `FvsCast` we record its free variables, +--   so that we don't have to keep recomputing them.+data FvsCast a n+        = FvsCast (Cast a n)+                  (Set (Bound n))       -- Free level-1 variables.+                  (Set (Bound n))       -- Free level-0 variables.++instance Ord n => MapBoundX (FvsCast a) n where+ mapBoundAtDepthX f d (FvsCast c fvs1 fvs0)+  = FvsCast (mapBoundAtDepthX f d c)+            fvs1+            (Set.fromList+                $ map (mapBoundAtDepthX f d)+                $ Set.toList fvs0)+++packFvsCasts +        :: Ord n+        => KindEnv n -> TypeEnv n+        -> a -> [FvsCast a n] -> [Cast a n]++packFvsCasts kenv tenv a fvsCasts+        = packCasts kenv tenv a [ c | FvsCast c _ _ <- fvsCasts ]+++-- | Pack down casts by combining multiple 'weakclo' and 'weakeff' casts+--   together. We pack casts just before we drop them, so that the resulting+--   code is easier to read.+packCasts :: Ord n+          => KindEnv n -> TypeEnv n -> a -> [Cast a n] -> [Cast a n]+packCasts kenv tenv a vs+ = let  +        -- Sort casts into weakeff, weakclo and any others.+        -- We'll collect the weakeff and weakclo casts together.+        collect weakEffs weakClos others cc+         = case cc of+            []                        +             -> (reverse weakEffs, reverse weakClos, reverse others)++            CastWeakenEffect eff : cs +             -> collect (eff : weakEffs) weakClos others cs++            CastWeakenClosure xs : cs +             -> collect weakEffs        (xs ++ weakClos) others cs++            c : cs+             -> collect weakEffs        weakClos (c : others) cs+++        (effs, xsClos, csOthers) +                = collect [] [] [] vs++        xsClos_packed+                = packWeakenClosureXs kenv tenv a xsClos++   in   (if null effs +                then []+                else [CastWeakenEffect  (TSum $ Sum.fromList kEffect effs)])+     ++ (if null xsClos_packed+                then []+                else [CastWeakenClosure xsClos_packed])+     ++ csOthers+++-- | Pack the expressions given to a `WeakenClosure` to just the ones that we+--   care about. We only need region variables, and value variables with +--   open types.+packWeakenClosureXs +        :: Ord n+        => KindEnv n -> TypeEnv n +        -> a -> [Exp a n] -> [Exp a n]++packWeakenClosureXs kenv tenv a xx+ = let  +        eat fvsSp fvsDa []+         = (fvsSp, fvsDa)++        eat fvsSp fvsDa (x : xs)+         = let  sup      = support Env.empty Env.empty x+                fvsSp'   = supportSpVar sup+                fvsDa'   = supportDaVar sup+           in   eat (Set.union fvsSp fvsSp') (Set.union fvsDa fvsDa') xs++        (vsSp, vsDa)      = eat Set.empty Set.empty xx++   in   [XType (TVar u) | u <- Set.toList vsSp]+     ++ [XVar a u       | u <- Set.toList vsDa, keepBound kenv tenv u]+++-- | When packing vars given to a closure weakening, we only need to keep+--   vars that have open types or contain region handles.+keepBound :: Ord n => KindEnv n -> TypeEnv n -> Bound n -> Bool+keepBound _kenv tenv u+        | Just t        <- Env.lookup u tenv+        , sup           <- support Env.empty Env.empty t+        , Set.null (supportSpVar sup)+        , all (not . isRegionHandle) $ Set.toList $ supportTyCon sup+        = False++        | otherwise+        = True +++-- | Treat primitive constructors with region kind as region handles.+--   Region handles are only really a part of the 'Disciple Core Eval' +--   language, but they're easy to check for even if the name type 'n'+--   hasn't been revealed.+isRegionHandle :: Bound n -> Bool+isRegionHandle u+ = case u of+        UPrim _ k       -> isRegionKind k+        _               -> False+++-- Dropping -------------------------------------------------------------------+-- | Wrap the provided expression with these casts.+dropAllCasts +        :: Ord n+        => KindEnv n+        -> TypeEnv n+        -> a +        -> [FvsCast a n] -> Exp a n +        -> Exp a n++dropAllCasts kenv tenv a cs x+ = let  cs'     = packFvsCasts kenv tenv a cs+   in   foldr (XCast a) x cs'+++-- | Split the provided casts into ones that contain variables+--   bound by these binders. The casts that do are used to wrap+--   the provided expression, and the casts that don't are returned+--   seprately so we can keep bubbling them up the tree.+dropCasts +        :: Ord n+        => KindEnv n -> TypeEnv n+        -> a +        -> [Bind n]             -- ^ Level-1 binders.+        -> [Bind n]             -- ^ Level-0 binders.+        -> [FvsCast a n] +        -> Exp a n +        -> ([FvsCast a n], Exp a n)++dropCasts kenv tenv a bs1 bs0 cs x+ = let  (csHere1, cs1)    = partition (fvsCastUsesBinds1 bs1) cs+        (csHere0, csUp)   = partition (fvsCastUsesBinds0 bs0) cs1+        csHere            = packFvsCasts kenv tenv a $ csHere1 ++ csHere0+   in   ( map (lowerX 1) csUp+        , foldr (XCast a) x csHere)+++-- | Check if a `FvsCast` mentions any of these level-0 variables.+fvsCastUsesBinds0 :: Ord n => [Bind n] -> FvsCast a n -> Bool+fvsCastUsesBinds0 bb (FvsCast _ _ fvs0)+        = bindsMatchBoundSet bb fvs0+++-- | Check if a `FvsCast` mentions any of these level-1 variables.+fvsCastUsesBinds1 :: Ord n => [Bind n] -> FvsCast a n -> Bool+fvsCastUsesBinds1 bb (FvsCast _ fvs1 _)+        = bindsMatchBoundSet bb fvs1+++-- | Check if a set of bound variables matches any of the given binders.+bindsMatchBoundSet :: Ord n => [Bind n] -> Set (Bound n) -> Bool+bindsMatchBoundSet bb fvs+ = go bb+ where  go []           = False+        go (b : bs)+         | Just u       <- takeSubstBoundOfBind b+         = if Set.member u fvs+                then True+                else go bs++         | otherwise+         = go bs+
+ DDC/Core/Transform/Elaborate.hs view
@@ -0,0 +1,114 @@++-- | Add possible Const and Distinct witnesses that aren't+--   otherwise in the program.+module DDC.Core.Transform.Elaborate+       ( elaborateModule+       , elaborateX )+where+import DDC.Core.Exp+import DDC.Core.Module+import DDC.Type.Compounds+import DDC.Data.ListUtils+import Control.Monad+import Control.Arrow+import Data.Maybe+import Data.List+++-- | Elaborate witnesses in a module.+elaborateModule :: Eq n => Module a n -> Module a n+elaborateModule mm +        = mm { moduleBody = elaborate [] $ moduleBody mm }+++-- | Elaborate witnesses in an expression.+elaborateX :: Eq n => Exp a n -> Exp a n+elaborateX xx+        = elaborate [] xx+++-------------------------------------------------------------------------------+class Elaborate (c :: * -> *) where+  elaborate :: Eq n => [Bound n] -> c n -> c n+++instance Elaborate (Exp a) where+ elaborate us xx+  = {-# SCC elaborate #-}+    let down = elaborate us +    in case xx of+        XVar{}            -> xx+        XCon{}            -> xx    +        XLAM  a b    x    -> XLAM a b (down x)+        XLam  a b    x    -> XLam a b (down x)+        XApp  a x1   x2   -> XApp a (down x1) (down x2)++        XLet  a lts  x2 +         -> let (us', lts') = elaborateLets us lts+            in  XLet a lts' (elaborate us' x2)+            +        XCase a x    alts -> XCase a (down x) (map down alts)+        XCast a cst  x2   -> XCast a (down cst) (down x2)+        XType{}           -> xx+        XWitness{}        -> xx+++instance Elaborate (Cast a) where+ elaborate us cst +  = case cst of+        CastWeakenClosure es+          -> CastWeakenClosure $ map (elaborate us) es +        _ -> cst+++instance Elaborate (Alt a) where+  elaborate us (AAlt p x) = AAlt p (elaborate us x) +++-- | Elaborate witnesses in some let-bindings.+elaborateLets+        :: Eq n +        => [Bound n]            -- ^ Witness bindings in the environment.+        -> Lets a n             -- ^ Elaborate these let bindings.+        -> ([Bound n], Lets a n)++elaborateLets us lts + = let down = elaborate us +   in case lts of+        LLet m b x -> (us, LLet m b (down x))+        LRec bs    -> (us, LRec $ map (second down) bs)++        LLetRegions brs bws+         |  urs@(_:_) <- takeSubstBoundsOfBinds brs+         -> let +                -- Mutable regions bound here.+                rsMutable       = catMaybes +                                $ map (takeMutableRegion . typeOfBind) bws++                -- Make a new const witness for all non-mutable regions.+                constWits       = map makeConstWit +                                $ urs \\ rsMutable++                -- Make a new distinct witness against all regions+                -- in the environment.+                Just ursTail    = takeTail urs+                distinctWits    = map makeDistinctWit +                                $  liftM2 (,) us   urs+                                ++ zip        urs  ursTail++            in  ( us ++ urs+                , LLetRegions brs $ bws ++ distinctWits ++ constWits )++        _          -> (us, lts)++makeConstWit u+        = BNone $ tConst (TVar u)        ++makeDistinctWit (u1,u2)+        = BNone $ tDistinct 2 [TVar u1, TVar u2]++takeMutableRegion tt+ = case takeTyConApps tt of+        Just (TyConWitness TwConMutable, [TVar u]) -> Just u+        _                                          -> Nothing+
+ DDC/Core/Transform/Flatten.hs view
@@ -0,0 +1,156 @@++-- | Flattening nested let and case expressions.+module DDC.Core.Transform.Flatten+        (flatten)+where+import DDC.Core.Transform.LiftT+import DDC.Core.Transform.TransformX+import DDC.Core.Transform.AnonymizeX+import DDC.Core.Transform.LiftX+import DDC.Core.Exp+import DDC.Core.Compounds+import DDC.Type.Predicates+import Data.Functor.Identity+++-- | Flatten binding structure in a thing.+--+--   Flattens nested let-expressions, +--   and single alternative let-case expressions. +--+flatten :: Ord n +        => (TransformUpMX Identity c)+        => c a n -> c a n+flatten + = {-# SCC flatten #-}+   transformUpX' flatten1+++-- | Flatten a single nested let-expression.+flatten1+        :: Ord n+        => Exp a n+        -> Exp a n++-- Let ----------------------------------------------------+-- Flatten Nested Lets.+-- @+--      let b1 = (let b2 = def2 in x2) in+--      x1+--+--  ==> let b2 = def2 in +--      let b1 = x2   in+--      x1+-- @+-- +flatten1 (XLet a1 (LLet LetStrict b1+            inner@(XLet a2 (LLet LetStrict b2 def2) x2))+               x1)++ | isBName b2+ = flatten1+        $ XLet a1 (LLet LetStrict b1 +               (anonymizeX inner))+               x1++ | otherwise+ = let  x1'       = liftAcrossX [b1] [b2] x1                                 +   in   XLet a2 (LLet LetStrict b2 def2) +      $ flatten1+      $ XLet a1 (LLet LetStrict b1 x2) +             x1'+++-- Drag 'letregion' out of the top-level of a binding.+-- @+--    let b1 = letregion b2 in x2 in+--    x1+--+-- => letregion b2 in +--    let b1 = x2 in+--    x1+-- @+--+-- 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+            inner@(XLet a2 (LLetRegions b2 bs2) x2))+               x1)+ | all isBName b2+ = flatten1+        $ XLet a1 (LLet LetStrict b1+                  (anonymizeX inner))+               x1++ | otherwise+ = let  x1'     = liftAcrossT []   b2+                $ liftAcrossX [b1] bs2 x1+   in   XLet a2 (LLetRegions b2 bs2) +      $ flatten1+      $ XLet a1 (LLet LetStrict (zapX b1) x2) +             x1'+++-- Flatten single-alt case expressions.+-- @+--     let b1 = case x1 of +--                P -> x2 +--     in x3+--+--  => case x1 of +--       P -> let b1 = x2 +--            in x3+-- @+--+-- * binding must be strict because we force evaluation of x1.+--+flatten1 (XLet  a1 (LLet LetStrict b1 +             inner@(XCase a2 x1 [AAlt p x2]))+                   x3)+ | any isBName $ bindsOfPat p+ = flatten1+        $ XLet  a1 (LLet LetStrict b1+                   (anonymizeX inner))+                   x3++ | otherwise+ = let  x3'     = liftAcrossX [b1] (bindsOfPat p) x3+   in   XCase a2 x1 +           [AAlt p ( flatten1 +                   $ XLet a1 (LLet LetStrict b1 x2)+                             (anonymizeX x3'))]+++-- Any let, its bound expression doesn't contain a strict non-recursive+-- let so just flatten the body+flatten1 (XLet a1 llet1 x1)+ = XLet a1 llet1 (flatten1 x1)+++-- Case ---------------------------------------------------+-- Flatten all the alternatives in a case-expression.+flatten1 (XCase a x1 alts)+ = XCase a (flatten1 x1) +           [AAlt p (flatten1 x) | AAlt p x <- alts ]++flatten1 x = x+++liftAcrossX :: Ord n => [Bind n] -> [Bind n] -> Exp a n -> Exp a n+liftAcrossX bsDepth bsLevels x+ = let  depth   = length [b | b@(BAnon _) <- bsDepth]+        levels  = length [b | b@(BAnon _) <- bsLevels]+   in   liftAtDepthX levels depth x+++liftAcrossT :: Ord n => [Bind n] -> [Bind n] -> Exp a n -> Exp a n+liftAcrossT bsDepth bsLevels x+ = let  depth   = length [b | b@(BAnon _) <- bsDepth]+        levels  = length [b | b@(BAnon _) <- bsLevels]+   in   liftAtDepthT levels depth x+++-- | Erase the type of a data binder.+zapX :: Bind n -> Bind n+zapX b = replaceTypeOfBind (tBot kData) b
+ DDC/Core/Transform/Forward.hs view
@@ -0,0 +1,195 @@++-- | Float let-bindings with a single use forward into their use-sites.+module DDC.Core.Transform.Forward+        ( ForwardInfo   (..)+        , forwardModule+        , forwardX)+where+import DDC.Base.Pretty+import DDC.Core.Analysis.Usage+import DDC.Core.Exp+import DDC.Core.Module+import DDC.Core.Simplifier.Base+import DDC.Core.Fragment+import DDC.Core.Predicates+import Data.Map                 (Map)+import Control.Monad+import Control.Monad.Writer	(Writer, runWriter, tell)+import Data.Monoid		(Monoid, mempty, mappend)+import Data.Typeable+import qualified Data.Map                               as Map+import qualified DDC.Core.Transform.SubstituteXX	as S++-------------------------------------------------------------------------------+-- | Summary of number of bindings floated.+data ForwardInfo+        = ForwardInfo+        { -- | Number of trivial @v1 = v2@ bindings inlined.+          infoSubsts   :: Int++          -- | Number of bindings floated forwards.+        , infoBindings :: Int }+        deriving Typeable+++instance Pretty ForwardInfo where+ ppr (ForwardInfo substs bindings)+  =  text "Forward:"+  <$> indent 4 (vcat+      [ text "Substitutions:  " <> int substs+      , text "Bindings:       " <> int bindings ])+++instance Monoid ForwardInfo where+ mempty = ForwardInfo 0 0+ mappend (ForwardInfo s1 b1)(ForwardInfo s2 b2)+        = ForwardInfo (s1 + s2) (b1 + b2)+++-------------------------------------------------------------------------------+-- | 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++forwardModule profile mm+        = fst   $ runWriter+                $ forwardWith profile Map.empty +                $ usageModule mm+++-- | 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+ = let  (x',info) = runWriter+		  $ forwardWith profile Map.empty+		  $ usageX xx++        progress (ForwardInfo s _) +                = s > 0++   in  TransformResult+        { result	 = x'+        , resultProgress = progress info+        , resultAgain    = False+        , resultInfo	 = TransformInfo info }+++-------------------------------------------------------------------------------+class Forward (c :: * -> * -> *) where+ -- | Carry bindings forward and downward into their use-sites.+ forwardWith +        :: Ord n+        => Profile n+        -> Map n (Exp a n)+        -> c (UsedMap n, a) n+        -> Writer ForwardInfo (c a n)++instance Forward Module where+ forwardWith profile bindings +        (ModuleCore+                { moduleName            = name+                , moduleExportKinds     = exportKinds+                , moduleExportTypes     = exportTypes+                , moduleImportKinds     = importKinds+                , moduleImportTypes     = importTypes+                , moduleBody            = body })++  = do	body' <- forwardWith profile bindings body+	return ModuleCore+		{ moduleName            = name+		, moduleExportKinds     = exportKinds+		, moduleExportTypes     = exportTypes+		, moduleImportKinds     = importKinds+		, moduleImportTypes     = importTypes+		, moduleBody            = body' }+++instance Forward Exp where+ forwardWith profile bindings xx+  = {-# SCC forwardWith #-}+    let down    = forwardWith profile bindings +    in case xx of+        XVar a u@(UName n)+         -> case Map.lookup n bindings of+                Just xx'        -> do+		    tell mempty { infoSubsts = 1 }+		    return xx'+                Nothing         ->+		    return $ XVar (snd a) u++        XVar a u        -> return $ XVar (snd a) u+        XCon a u        -> return $ XCon (snd a) u+        XLAM a b x      -> liftM    (XLAM (snd a) b) (down x)+        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 atomic bindings (variables, constructors)+        XLet _ (LLet _mode b x1) x2+	 | isAtomX x1+	 -> do +                -- Record that we've moved this binding.+                tell mempty { infoBindings = 1 }++                -- Slow, but handles anonymous binders and shadowing+                down $ S.substituteXX b x1 x2++        XLet (_, a') lts 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+++filterUsedInCasts :: [Used] -> [Used]+filterUsedInCasts = filter notCast+ where  notCast UsedInCast      = False+        notCast _               = True+++instance Forward Cast where+ forwardWith profile bindings xx+  = let down    = forwardWith profile 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+++instance Forward Lets where+ forwardWith profile bindings lts+  = let down    = forwardWith profile bindings+    in case lts of+        LLet mode b x   -> liftM (LLet mode b) (down x)++        LRec bxs        +         -> liftM LRec+         $  mapM (\(b,x) +                    -> do x' <- down x+			  return (b, x')) +            bxs++        LLetRegions b bs -> return $ LLetRegions b bs+        LWithRegion b    -> return $ LWithRegion b+++instance Forward Alt where+ forwardWith profile bindings (AAlt p x)+  = liftM (AAlt p) (forwardWith profile bindings x)+
+ DDC/Core/Transform/Inline.hs view
@@ -0,0 +1,76 @@++-- | Inlining definitions into their use sites.+module DDC.Core.Transform.Inline+        ( inline+        , InlineSpec   (..)+        , lookupTemplateFromModules)+where+import DDC.Core.Exp+import DDC.Core.Module+import DDC.Core.Transform.Inline.Templates+import qualified Data.Set               as Set+import Data.Set                         (Set)+++class Inline (c :: * -> * -> *) where+ inline :: Ord n+        => (n -> Maybe (Exp a n))+                        -- ^ Get the template for a named variable.+        -> Set n        -- ^ Don't inline definitions for these names.+        -> c a n+        -> c a n+++instance Inline Module where+ inline get inside mm+  = mm  { moduleBody = inline get inside (moduleBody mm) }+++instance Inline Exp where+ inline get inside xx+  = let down x = inline get inside x+    in case xx of+        XVar _ (UName n)+         -- Don't inline a recursive definition into itself.+         | Set.member n inside+         -> xx++         -- If there is a template for this variable then inline it, +         -- but remember that we're now inside the body so we don't inline+         -- recursive functions forever.+         | Just xx'     <- get n+         -> let !inside' = Set.insert n inside+            in  inline get inside' xx'++        XVar{}          -> xx+        XCon{}          -> xx+        XLAM  a b x     -> XLAM  a b (down x)+        XLam  a b x     -> XLam  a b (down x)+        XApp  a x1 x2   -> XApp  a (down x1)  (down x2)+        XLet  a lts x2  -> XLet  a (down lts) (down x2)+        XCase a x alts  -> XCase a (down x)   (map down alts)+        XCast a c x     -> XCast a c          (down x)+        XType{}         -> xx+        XWitness{}      -> xx+++instance Inline Lets where+ inline get inside lts+  = let enter b x+         = case b of+                BName n _       -> inline get (Set.insert n inside) x+                _               -> inline get inside x++    in case lts of+        LLet mode b x   -> LLet mode b (enter b x)+        LRec bxs        -> LRec [(b, enter b x) | (b, x) <- bxs]+        LLetRegions{}   -> lts+        LWithRegion{}   -> lts+++instance Inline Alt where+ inline get inside alt+  = case alt of+        AAlt p x        -> AAlt p (inline get inside x)++
+ DDC/Core/Transform/Inline/Templates.hs view
@@ -0,0 +1,96 @@++-- | Retrieving inliner templates from a list of modules.+module DDC.Core.Transform.Inline.Templates+	( InlineSpec(..)+        , lookupTemplateFromModules+	, lookupTemplateFromModule )+where+import DDC.Core.Exp+import DDC.Core.Module+import DDC.Core.Transform.AnonymizeX+import Data.List+import Data.Set                 (Set)+import Data.Map                 (Map)+import qualified Data.Map       as Map+import qualified Data.Set       as Set+++-- | Inlining specification says what bindings we should inline+--   from a particular module.+data InlineSpec n+        -- | Inline all bindings from a module,+        --   but exclude some particulars.+        = InlineSpecAll+        { inlineSpecModuleName  :: ModuleName+        , inlineSpecExclude     :: Set n }++        -- | Inline no bindings from a module,+        --   but include some particulars.+        | InlineSpecNone+        { inlineSpecModuleName  :: ModuleName+        , inlineSpecInclude     :: Set n }+        deriving Show+++-- | Lookup an inliner template from a list of modules.+---+--   This just does a linear search through all the modules.+--   As we only inline functions defined at top level, we don't need to worry+--   about lifting indices in templates when we go under binders.+--+lookupTemplateFromModules +        :: (Eq n, Ord n, Show n)+        => Map ModuleName (InlineSpec n)+                                -- ^ Inliner specifications for the modules.+        -> [Module a n]         -- ^ Modules to use for inliner templates.+        -> n +        -> Maybe (Exp a n)++lookupTemplateFromModules specs mm n+ | m : ms <- mm+ = let  -- If there is no inliner spec then don't inline anything.+        spec    = case Map.lookup (moduleName m) specs of+                        Just s  -> s+                        Nothing -> InlineSpecNone (moduleName m) Set.empty++   in   case lookupTemplateFromModule spec m n of+                Nothing -> lookupTemplateFromModules specs ms n+                Just x  -> Just x++ | otherwise+ = Nothing+++lookupTemplateFromModule +        :: (Eq n, Ord n, Show n)+        => InlineSpec n         -- ^ Inliner specification for this module.+        -> Module a n           -- ^ Module to use for inliner templates.+        -> n    +        -> Maybe (Exp a n)++lookupTemplateFromModule spec mm n+        | shouldInline spec n+        , XLet _ (LRec bxs) _  <- moduleBody mm+        , Just (_,x)	       <- find (\(BName n' _, _) -> n == n') bxs+        = Just $ anonymizeX x++        | otherwise+        = Nothing+++-- | Decide whether we should inline the binding with this name based on the +--   provided inliner specification.+shouldInline+        :: (Ord n, Show n)+        => InlineSpec n -> n -> Bool++shouldInline spec n+ = case spec of+        InlineSpecAll _ except+         | Set.member n except  -> False+         | otherwise            -> True++        InlineSpecNone _ include+         | Set.member n include -> True+         | otherwise            -> False+
+ DDC/Core/Transform/Namify.hs view
@@ -0,0 +1,301 @@++-- | Rewriting of anonymous binders to named binders.+module DDC.Core.Transform.Namify+        ( Namify        (..)+        , Namifier      (..)+        , makeNamifier+        , namifyUnique)+where+import DDC.Core.Module+import DDC.Core.Exp+import DDC.Type.Collect+import DDC.Type.Compounds+import Control.Monad+import DDC.Type.Env             (Env, KindEnv, TypeEnv)+import qualified DDC.Type.Sum   as Sum+import qualified DDC.Type.Env   as Env+import Control.Monad.State.Strict+++-- | Holds a function to rename binders, +--   and the state of the renamer as we decend into the tree.+data Namifier s n+        = Namifier+        { -- | Create a new name for this bind that is not in the given+          --   environment.+          namifierNew   :: Env n -> Bind n -> State s n++          -- | Holds the current environment during namification.+        , namifierEnv   :: Env n++          -- | Stack of debruijn binders that have been rewritten during+          --   namification.+        , namifierStack :: [Bind n] }+++-- | Construct a new namifier.+makeNamifier +        :: (Env n -> Bind n -> State s n)       +                        -- ^ Function to rename binders.+                        --   The name chosen cannot be a member of the given+                        ---  environment.+        -> Env n        -- ^ Starting environment of names we cannot use.+        -> Namifier s n++makeNamifier new env+        = Namifier new env []+++-- | Namify a thing, +--   not reusing names already in the program.+namifyUnique+        :: (Ord n, Namify c, BindStruct c)+        => (KindEnv n -> Namifier s n)  -- ^ Make a namifier for level-1 names.+        -> (TypeEnv n -> Namifier s n)  -- ^ Make a namifier for level-0 names.+        -> c n+        -> State s (c n)++namifyUnique mkNamK mkNamT xx+ = let  (tbinds, xbinds) = collectBinds xx+        namK    = mkNamK (Env.fromList tbinds)+        namT    = mkNamT (Env.fromList xbinds)+   in   namify namK namT xx+++-- Namify ---------------------------------------------------------------------+class Namify (c :: * -> *) where+ -- | Rewrite anonymous binders to named binders in a thing.+ namify :: Ord n+        => Namifier s n         -- ^ Namifier for type names (level-1)+        -> Namifier s n         -- ^ Namifier for exp names (level-0)+        -> c n                  -- ^ Rewrite binders in this thing.+        -> State s (c n)+++instance Namify Type where+ namify tnam xnam tt+  = let down = namify tnam xnam+    in case tt of+        TVar u          -> liftM TVar (rewriteT tnam u)     ++        TCon{}          +         ->     return tt++        TForall b t+         -> do  (tnam', b')     <- pushT tnam b+                t'              <- namify tnam' xnam t+                return  $ TForall b' t'++        TApp t1 t2      -> liftM2 TApp (down t1) (down t2)+        TSum ts         +         -> do  ts'     <- mapM down $ Sum.toList ts+                return  $ TSum $ Sum.fromList (Sum.kindOfSum ts) ts'+++instance Namify (Module a) where+ namify tnam xnam mm +  = do  body'    <- namify tnam xnam $ moduleBody mm+        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+ namify tnam xnam ww+  = let down = namify tnam xnam+    in case ww of+        WVar u          -> liftM  WVar  (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)+++instance Namify (Exp a) where+ namify tnam xnam xx+  = {-# SCC namify #-}+    let down = namify tnam xnam+    in case xx of+        XVar a u        -> liftM2 XVar (return a) (rewriteX tnam xnam u)+        XCon{}          -> return xx++        XLAM a b x+         -> do  (tnam', b')     <- pushT  tnam b+                x'              <- namify tnam' xnam x+                return $ XLAM a b' x'++        XLam a b x+         -> do  (xnam', b')     <- pushX  tnam xnam b+                x'              <- namify tnam xnam' x+                return $ XLam a b' x'++        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+                (xnam', b')     <- pushX  tnam xnam b+                x2'             <- namify tnam xnam' x2+                return $ XLet a (LLet mode' b' x1') x2'++        XLet a (LRec bxs) x2+         -> do  let (bs, xs)    = unzip bxs+                (xnam', bs')    <- pushXs tnam xnam bs+                xs'             <- mapM (namify tnam xnam') xs+                x2'             <- namify tnam xnam' x2+                return $ XLet a (LRec (zip bs' xs')) x2'++        XLet a (LLetRegions b bs) x2+         -> do  (tnam', b')     <- pushTs tnam b+                (xnam', bs')    <- pushXs tnam' xnam bs+                x2'             <- namify tnam' xnam' x2+                return $ XLet a (LLetRegions b' bs') x2'++        XLet a (LWithRegion u) x2+         -> do  u'              <- rewriteX tnam xnam u+                x2'             <- down x2+                return  $ XLet a (LWithRegion u') x2'++        XCase a x1 alts -> liftM3 XCase    (return a) (down x1)  (mapM down alts)+        XCast a c  x    -> liftM3 XCast    (return a) (down c)   (down x)+        XType t         -> liftM  XType    (down t)+        XWitness w      -> liftM  XWitness (down w)+++instance Namify (Alt a) where+ namify tnam xnam (AAlt PDefault x)+  = liftM (AAlt PDefault) (namify tnam xnam x)++ namify tnam xnam (AAlt (PData u bs) x)+  = do  (xnam', bs')    <- pushXs tnam xnam bs+        x'              <- namify tnam xnam' x+        return  $ AAlt (PData u bs') x'+++instance Namify (Cast a) where+ namify tnam xnam cc+  = let down = namify tnam xnam+    in case cc of+        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)+++-- | Rewrite level-1 anonymous binders.+rewriteT :: Namifier s n+         -> Bound n+         -> State s (Bound n)++rewriteT tnam u+ = case u of+        UIx i+         -> case lookup i (zip [0..] (namifierStack tnam)) of+                Just (BName n _) -> return $ UName n+                _                -> return u++        _       -> return u+++-- | Rewrite level-0 anonymous binders.+rewriteX :: Ord n+         => Namifier s n+         -> Namifier s n+         -> Bound n+         -> State s (Bound n)++rewriteX _tnam xnam u+ = case u of+        UIx i+         -> case lookup i (zip [0..] (namifierStack xnam)) of+                Just (BName n _) +                 -> do  return  $ UName n+                _                -> return u++        _       -> return u+++-- Push -----------------------------------------------------------------------+-- Chosing new names for anonymous binders and pushing them on the stack.++-- | Push a level-0 binder on the stack.+--   When we do this we also rewrite any indices in its type annotation.+pushX   :: Ord n+        => Namifier s n+        -> Namifier s n+        -> Bind n+        -> State s (Namifier s n, Bind n) ++pushX tnam xnam b+ = do   t'      <- namify tnam xnam (typeOfBind b)+        let b'  = replaceTypeOfBind t' b+        push xnam b'+++-- | Push some level-0 binders on the stack.+--   When we do this we also rewrite their type annotations.+pushXs  :: Ord n+        => Namifier s n+        -> Namifier s n+        -> [Bind n]+        -> State s (Namifier s n, [Bind n])++pushXs _tnam xnam []    +        = return (xnam, [])++pushXs tnam xnam (b:bs)+ = do   (xnam1, b')      <- pushX  tnam xnam  b+        (xnam2, bs')     <- pushXs tnam xnam1 bs+        return (xnam2, b' : bs')+++-- | Push a level-1 binder on the stack.+pushT   :: Ord n+        => Namifier s n+        -> Bind n+        -> State s (Namifier s n, Bind n)+pushT   = push+++pushTs  :: Ord n+        => Namifier s n+        -> [Bind n]+        -> State s (Namifier s n, [Bind n])+pushTs  tnam [] = return (tnam, [])+pushTs  tnam (b:bs)+ = do   (tnam1, b')  <- pushT  tnam  b+        (tnam2, bs') <- pushTs tnam1 bs+        return (tnam2, b' : bs')+        ++-- | Rewrite an anonymous binder and push it on the stack.+push    :: Ord n +        => Namifier s n +        -> Bind n +        -> State s (Namifier s n, Bind n)++push nam b+ = case b of+        BAnon t+         -> do  n       <- namifierNew nam (namifierEnv nam) b+                let b'  = BName n t+                return  ( nam { namifierStack = b' : namifierStack nam +                              , namifierEnv   = Env.extend b (namifierEnv nam) }+                        , b' )+        _ ->    return  ( nam { namifierEnv   = Env.extend b (namifierEnv nam) }+                        , b)
+ DDC/Core/Transform/Prune.hs view
@@ -0,0 +1,225 @@++-- | Erase contained let-bindings that have no uses.+--+--   Contained bindings are ones that do not perform effects that are+--   visible to anything in the calling context. This includes allocation+--   and read effects, but not writes or any globally visible effects.+--+module DDC.Core.Transform.Prune+        ( PruneInfo  (..)+        , pruneModule+        , pruneX)+where+import DDC.Core.Analysis.Usage+import DDC.Core.Simplifier.Base+import DDC.Core.Transform.Reannotate+import DDC.Core.Transform.TransformX+import DDC.Core.Fragment+import DDC.Core.Check+import DDC.Core.Module+import DDC.Core.Exp+import DDC.Type.Env+import DDC.Base.Pretty+import Data.Typeable+import Control.Monad.Writer                     (Writer, runWriter, tell)+import Data.Monoid                              (Monoid, mempty, mappend)+import qualified Data.Map                               as Map+import qualified Data.Set                               as Set+import qualified DDC.Type.Env                           as Env+import qualified DDC.Core.Collect                       as C+import qualified DDC.Core.Transform.SubstituteXX	as S+import qualified DDC.Core.Transform.Trim               	as Trim+import qualified DDC.Type.Compounds			as T+import qualified DDC.Type.Sum				as TS+import qualified DDC.Type.Transform.Crush		as T+++-------------------------------------------------------------------------------+-- | A summary of what the prune transform did.+data PruneInfo+    = PruneInfo+    { -- | How many let-bindings we erased.+      infoBindingsErased  :: Int }+    deriving Typeable+++instance Pretty PruneInfo where+ ppr (PruneInfo remo)+  =  text "Prune:"+  <$> indent 4 (vcat+      [ text "Removed:        " <> int remo])+++instance Monoid PruneInfo where+ mempty = PruneInfo 0++ mappend (PruneInfo r1) (PruneInfo r2)+        = PruneInfo (r1 + r2)+++-------------------------------------------------------------------------------+-- | Erase pure let-bindings in a module that have no uses.+pruneModule+	:: (Show a, Show n, Ord n, Pretty n)+	=> Profile n           -- ^ Profile of the language we're in+	-> Module a n+	-> Module a n++pruneModule profile mm+         -- 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+         = mm++         | otherwise+         = mm { moduleBody      +                = result +                $ pruneX profile (moduleKindEnv mm) (moduleTypeEnv mm)+                $ moduleBody mm }+++-- | Erase pure let-bindings in an expression that have no uses.+pruneX+	:: (Show a, Show n, Ord n, Pretty n)+	=> Profile n           -- ^ Profile of the language we're in+	-> KindEnv n           -- ^ Kind environment+	-> TypeEnv n           -- ^ Type environment+	-> Exp a n+	-> TransformResult (Exp a n)++pruneX profile kenv tenv xx+ = {-# SCC pruneX #-}+   let  +        (xx', info)+                = transformTypeUsage profile kenv tenv+	               (transformUpMX pruneTrans kenv tenv)+                       xx++        progress (PruneInfo r) +                = r > 0++   in TransformResult+        { result	 = xx'+        , resultAgain    = progress info+        , resultProgress = progress info+        , resultInfo     = TransformInfo info }+++-- The prune transform proper needs to have every expression annotated+-- with its type an effect, as well the variable usage map.+--+-- We generate these annotations here then pass the result off to+-- deadCodeTrans to actually erase dead bindings.+--+transformTypeUsage profile kenv tenv trans xx+ = case checkExp (configOfProfile profile) kenv tenv xx of+        Right (xx1, _, _,_) +         -> let xx2        = usageX xx1+                (x', info) = runWriter (trans xx2)+                x''        = reannotate (\(_, AnTEC { annotTail = a }) -> a) x'+            in  (x'', info)++        Left err +         -> error $  renderIndent+         $  vcat [ text "DDC.Core.Transform.Prune: core type error"+                 , ppr err ]+++-------------------------------------------------------------------------------+-- | Annotations used by the dead-code trasnform.+type Annot a n +        = (UsedMap n, AnTEC a n)+++-- | Apply the dead-code transform to an annotated expression.+pruneTrans+	:: (Show a, Show n, Ord n, Pretty n)+	=> KindEnv n+	-> TypeEnv n+	-> Exp (Annot a n) n+	-> Writer PruneInfo +                 (Exp (Annot a n) n)++pruneTrans _ _ xx+ = case xx of+        XLet a@(usedMap, antec) (LLet _mode b x1) x2+         | isUnusedBind b usedMap+         , isContainedEffect $ annotEffect antec+         -> do      +                -- We still need to substitute value into casts+                let x2' = transformUpX' Trim.trimX $ S.substituteXX b x1 x2++                -- Record that we've erased a binding.+                tell mempty {infoBindingsErased = 1}++                -- +                return $ XCast a (weakEff antec)+                       $ XCast a (weakClo a x1)+                       $ x2'++        _ -> return xx++ where+        weakEff antec+         = CastWeakenEffect+         $ T.crushEffect+         $ annotEffect antec++        weakClo a x1 +         = CastWeakenClosure+         $ Trim.trimClosures a+                (  (map (XType . TVar)+                        $ Set.toList+                        $ C.freeT Env.empty x1)+                ++ (map (XVar a)+                        $ Set.toList+                          $ C.freeX Env.empty x1))+++-- | Check whether this binder has no uses, +--   not including weakclo casts, beause we'll substitute the bound+--   expression directly into those.+isUnusedBind :: Ord n => Bind n -> UsedMap n -> Bool+isUnusedBind bb (UsedMap um)+ = case bb of+        BName n _+         -> case Map.lookup n um of+                Just useds -> filterUsedInCasts useds == []+        	Nothing	   -> True++        BNone _ -> True+        _       -> False+++filterUsedInCasts :: [Used] -> [Used]+filterUsedInCasts = filter notCast+ where  notCast UsedInCast      = False+        notCast _               = True+++-- | A contained effect is one that is not visible to anything else+--   in the context. This is allocation and read effects, which are+--   not visible from outside the computation performing the effect. +isContainedEffect :: Ord n => Effect n -> Bool+isContainedEffect eff + = all contained+        $ map T.takeTApps +        $ sumList +        $ T.crushEffect eff+ where+        contained (c : _args)+         = case c of+                TCon (TyConSpec TcConAlloc)	-> True+        	TCon (TyConSpec TcConDeepAlloc) -> True+        	TCon (TyConSpec TcConRead)      -> True+                TCon (TyConSpec TcConHeadRead)  -> True+                TCon (TyConSpec TcConDeepRead)  -> True+        	_				-> False++        contained [] = False++        sumList (TSum ts) = TS.toList ts+        sumList tt            = [tt]+
+ DDC/Core/Transform/Rewrite.hs view
@@ -0,0 +1,562 @@++-- | Apply rewrite rules.+module DDC.Core.Transform.Rewrite+        ( RewriteRule(..)+        , rewriteModule+        , rewriteX)+where+import DDC.Base.Pretty+import DDC.Core.Exp+import DDC.Core.Module+import Data.Map                                         (Map)+import DDC.Core.Simplifier.Base (TransformResult(..), TransformInfo(..))+import qualified DDC.Core.Compounds                     as X+import qualified DDC.Core.Transform.AnonymizeX          as A+import qualified DDC.Core.Transform.Rewrite.Disjoint    as RD+import qualified DDC.Core.Transform.Rewrite.Env         as RE+import qualified DDC.Core.Transform.Rewrite.Match       as RM+import           DDC.Core.Transform.Rewrite.Rule+import qualified DDC.Core.Transform.SubstituteXX        as S+import qualified DDC.Type.Transform.SubstituteT         as S+import qualified DDC.Core.Transform.Trim                as Trim+import qualified DDC.Core.Transform.LiftX               as L+import qualified DDC.Type.Compounds                     as T+import qualified Data.Map                               as Map+import qualified Data.Set                               as Set+import Data.Maybe+import Control.Monad+import Control.Monad.Writer (tell, runWriter)+import Data.List+import Data.Typeable+++-- Log ------------------------------------------------------------------------+-- | Tracks which rewrite rules fired.+data RewriteInfo +        = RewriteInfo [RewriteLog]+        deriving Typeable++data RewriteLog+        = LogRewrite String+        | LogUnfold  String+        deriving Typeable+++instance Pretty RewriteInfo where+ ppr (RewriteInfo rules) +        =   text "Rules fired:"+        <$> indent 4 (vcat $ map ppr rules)+++instance Pretty RewriteLog where+ ppr (LogRewrite name) = text "Rewrite: " <> text name+ ppr (LogUnfold  name) = text "Unfold:  " <> text name++isProgress = not . null+++-- Rewrite --------------------------------------------------------------------+-- | Apply rewrite rules to a module.+rewriteModule+        :: (Show a, Show n, Ord n, Pretty n)+        => [NamedRewriteRule a n]       -- ^ Rewrite rule database.+        -> Module a n                   -- ^ Rewrite in this module.+        -> Module a n++rewriteModule rules mm+ = mm { moduleBody = result $ rewriteX' True rules $ moduleBody mm }+++-- | Perform rewrites top-down, repeatedly.+rewriteX +        :: (Show a, Show n, Ord n, Pretty n) +        => [NamedRewriteRule a n]       -- ^ Rewrite rules database.+        -> Exp a n                      -- ^ Rewrite in this expression.+        -> TransformResult (Exp a n)+rewriteX = rewriteX' False+++-- | Repeatedly perform rewrites top-down.+--   Usually any names bound in @letrec@s disable rules, because the+--   new binding makes the old rule meaningless.+--   For modules we do not want to do this, since the rules for that module+--   are probably about the functions exported from the module.+--   In this case, we ignore the top-level bindings when checking for rule shadowing.+rewriteX'+        :: (Show a, Show n, Ord n, Pretty n) +        => Bool                         -- ^ Ignore top-level bindings when checking for shadowing?+        -> [NamedRewriteRule a n]       -- ^ Rewrite rules database.+        -> Exp a n                      -- ^ Rewrite in this expression.+        -> TransformResult (Exp a n)++rewriteX' ignore_toplevel rules x0+ = {-# SCC rewriteX #-}+   let  (x,info) = runWriter $ go RE.empty x0 [] ignore_toplevel+   in   TransformResult+         { result               = x+         , resultAgain          = isProgress info+         , resultProgress       = isProgress info+         , resultInfo           = TransformInfo (RewriteInfo info) }+ where+        -- ISSUE #280:  Rewrites should be done with the most specific rule.+        --   The rewrite engine should apply the most specific rule, instead+        --   of the first one that it finds that matches. If not, then we+        --   should give some warning about overlapping rules.+        -- +        -- Look for rules in the list that match the given expression,+        -- and apply the first one that matches.+        rewrites env f args+         = rewrites' rules env f args++        rewrites' [] _ f args+         = return $ X.makeXAppsWithAnnots f args++        rewrites' ((n, rule) : rs) env f args+         = case rewriteWithX rule env f args of+                Nothing -> rewrites' rs env f args+                Just x  -> tell [LogRewrite n] >> go env x [] False+++        down env x  +         = go env x [] False+++        -- Decend into the expression, looking for applications that we +        -- might be able to apply rewrites to.+        go env (XApp a f arg) args _toplevel+         = do   arg' <- down env arg+                go env f ((arg',a):args) False++        go env x@XVar{}   args  _toplevel+         =      rewrites env x args++        go env x@XCon{}   args  _toplevel+         =      rewrites env x args++        go env (XLAM a b e) args _toplevel+         = do   e' <- down (RE.lift b env) e +                rewrites env (XLAM a b e') args++        go env (XLam a b e) args _toplevel+         = do   e' <- down (RE.extend b env) e+                rewrites env (XLam a b e') args++        go env (XLet a l@(LRec _) e) args toplevel+         = do   -- Don't add the @letrec@'s bindings to the rule shadow list if we're at the top-level+                let env' = if   toplevel+                           then env+                           else RE.extendLets l env+                l'      <- goLets l env'+                e'      <- down env' e +                rewrites env' (XLet a l' e') args++        go env (XLet a l e)     args _toplevel+         = do   l'      <- goLets l env+                dh      <- goDefHoles rules a l' e env down+                rewrites env dh args ++        go env (XCase a e alts) args _toplevel+         = do   e'      <- down env e+                alts'   <- mapM (goAlts env) alts+                rewrites env (XCase a e' alts') args++        go env (XCast a c e)    args _toplevel+         = do   e'      <- down env e+                rewrites env (XCast a c e') args++        go env x@(XType{})      args _toplevel+         =      rewrites env x args++        go env x@(XWitness{})   args _toplevel+         =      rewrites env x args+++        goLets (LLet lm b e) ws +         = do   e' <- down ws e +                return $ LLet lm b e'++        goLets (LRec bs) ws +         = do   bs'     <- mapM (down ws) $ map snd bs+                return $ LRec $ zip (map fst bs) bs'+++        goLets l _ +         = return $ l++        goAlts ws (AAlt p e) +         = do   e' <- down ws e +                return $ AAlt p e'+++-- If definitions match the holes of any rules,+-- clean it up and record it for later.+-- Eg with this rule,+--   RULE unbox {box s} = s+--+-- this expression:+--   let x = box (some expensive op)+--   in  ...+--+-- will be transformed to+--   let ^ = some expensive op+--       x = box ^0+--   in ...+--+goDefHoles rules a l@(LLet LetStrict let_bind def) e env down+ | (((sub, []), name, RewriteRule { ruleBinds = bs, ruleLeft = hole }):_)+        <- checkHoles rules def env++ = let  -- only get value-level bindings+        bs'     = filter (isBMValue . fst) bs+        bas'    = lookupFromSubst bs' sub++        -- check if it looks like something has already been unfolded+        isUIx x = case x of +                      XVar _ (UIx _)     -> True+                      XVar _ (UPrim _ _) -> True+                      _                  -> False++        already_done+                = all isUIx $ map snd bas'++        -- find kind-values and sub those in as well+        bsK'    = filter ((== BMSpec) . fst) bs+        basK    = lookupFromSubst bsK' sub++        basK'   = concatMap (\(b,x) -> case X.takeXType x of+                                             Just t -> [(b,t)]+                                             Nothing-> []) basK++        -- surround whole expression with anon lets from sub+        values  = map   (\(b,v) ->   (BAnon (S.substituteTs basK' $ T.typeOfBind b), v))+                        (reverse bas')++        -- 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++        def'    = S.substituteXArgs basK+                $ S.substituteXArgs anons hole++        let_bind'  = S.substituteTs basK' let_bind+        lets'      = lets ++ [LLet LetStrict let_bind' def']++        -- lift e by (length bas)+        depth   = case let_bind of+                     BAnon _ -> 1 +                     _       -> 0++        e'      = L.liftAtDepthX (length bas') depth e++        -- SAVE in wit env+        env'     = foldl (flip RE.extendLets) env lets'++   in  if already_done+            then do+                e'' <- down (RE.extendLets l env) e+                return $ XLet a l e''++            else do+                tell [LogUnfold name]+                e'' <- down env' e'+                return $ X.xLets a lets' e''++ | otherwise+ = do   e' <- down (RE.extendLets l env) e+        return $ XLet a l e'++goDefHoles _rules a l e env down+ = do   e' <- down (RE.extendLets l env) e+        return $ XLet a l e'+++-- Match a let-definition against the holes in all the rules+checkHoles +        :: (Show n, Show a, Ord n, Pretty n)+        => [NamedRewriteRule a n]+        -> Exp a n+        -> RE.RewriteEnv a n+        -> [ ( (RM.SubstInfo a n, [(Exp a n, a)])+               , String+               , RewriteRule a n) ]++checkHoles rules def ws+ = let  rules'   = catMaybes $ map holeRule rules+        (f,args) = X.takeXAppsWithAnnots def++   in   catMaybes+         $ map (\(name,r) -> fmap (\s -> (s,name,r)) +                          $ matchWithRule r ws f args RM.emptySubstInfo)+           rules'+++holeRule (name, rule@RewriteRule { ruleLeftHole     = Just hole })+ = Just ( name+        , rule { ruleLeft     = hole+               , ruleLeftHole = Nothing })++holeRule _ = Nothing+++-------------------------------------------------------------------------------+-- | Perform rewrite rule on expression if a valid substitution exists,+--   and constraints are satisfied.+rewriteWithX+        :: (Show n, Show a, Ord n, Pretty n)+        => RewriteRule a n+        -> RE.RewriteEnv a n+        -> Exp a n+        -> [(Exp a n, a)]+        -> Maybe (Exp a n)++rewriteWithX rule env f args + = do   +        let RewriteRule+             { ruleBinds         = binds+             , ruleConstraints   = constrs+             , ruleRight         = rhs+             , ruleWeakEff       = eff+             , ruleWeakClo       = clo } +             = rule+   +        -- Try to find a substitution for the left of the rule.+        (m, rest)       <- matchWithRule rule env f args RM.emptySubstInfo++        -- Check constraints, perform substitution and add weakens if necessary.+        let Just a      = X.takeAnnotOfExp f++        let bas2        = lookupFromSubst binds m+        let rhs2        = A.anonymizeX rhs+        let (bas3,lets) = wrapLets a binds bas2+        let rhs3        = L.liftX (length lets) rhs2++        -- Substitute bindings into the effect of the right of the rule.+        let eff'        = liftM (substT bas3) eff++        -- Substitute bindings into the closure of the right of the rule.+        let clo'        = Trim.trimClosures a+                        $ map (S.substituteXArgs bas3) clo++        -- Substitute bindings into rule constraints and+        -- check that they are all satisfied by the environment.+        let constrs'    = map (substT bas3) constrs+        when (not $ all (satisfiedContraint env) constrs')+                $ Nothing++        -- Build the rewritten expression.+        let x'  =  X.xLets a lets+                $  weakeff a eff'+                $  weakclo a clo'+                $  S.substituteXArgs bas3 rhs3++        -- Add the remaining arguments from the original expression+        -- that weren't matched by rule+        return   $  X.makeXAppsWithAnnots x' rest+++-- | Check whether we can satisfy this constraint using witnesses+--   in the rewrite nevironment.+satisfiedContraint :: (Ord n, Show n) => RE.RewriteEnv a n -> Type n -> Bool+satisfiedContraint env c+        =  RE.containsWitness c env+        || RD.checkDisjoint   c env+        || RD.checkDistinct   c env+++-- | Wrap an expression in an effect weakning.+weakeff :: Ord n +        => a -> Maybe (Effect n) +        -> Exp a n -> Exp a n++weakeff a meff x+ = maybe x (\e -> XCast a (CastWeakenEffect e) x) meff+++-- | Wrap an expression in a closure weakening.+weakclo :: Ord n +        => a -> [Exp a n] +        -> Exp a n -> Exp a n++weakclo a clos x+ = case clos of+        []      -> x+        _       -> XCast a (CastWeakenClosure clos) x+++wrapLets+        :: Ord n +        => a +        -> [(BindMode, Bind n)]         -- ^ Variables bound by the rule.+        -> [(Bind n,   Exp a n)]        -- ^ Substitution for the left of the rule.+        -> ( [(Bind n, Exp a n)]+           , [Lets a n])++wrapLets a binds bas + = let  isMkLet (_, (BMValue i, _)) = i /= 1+        isMkLet _                   = False++        (as, bs'') = partition isMkLet (bas `zip` binds)+        as'     = map fst as+        bs'     = map fst bs''++        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++   in   (bs' ++ anons, lets)+++-- | Substitute type bindings into a type.+substT :: Ord n => [(Bind n, Exp a n)] -> Type n -> Type n+substT bas x + = let  sub     = [(b, t) | (b, XType t) <- bas ] +   in   S.substituteTs sub x+++-------------------------------------------------------------------------------+-- | Attempt to find a rewrite substitution to match expression against rule.+--   Returns substitution and the left-over arguments that weren't matched+--   against.+--+--   matchWithRule+--      (RULE mapMapId [a b : *] (f : a -> b) (xs : List a).+--            map [:a b:] f (map [:a a:] id xs)+--          = map [:a b:] f xs)+--      map+--      [ [Int], [Int], (\x -> f), (map [:Int Int:] id [1,2,3]) ]+--+--      env+--+--      emptySubstInfo+--   ==>+--     Just ({a |-> Int, b |-> Int, f |-> (\x -> f), xs |-> [1,2,3] }, [])+--+--   However if we had passed a substitution such as {a |-> Float} instead of+--   emptySubstInfo, it would not have matched.+--+--   The environment is used for 'hole' rules, that can look up bound definitions+--   and match if inlining would let them, even when inlining won't occur.+--+matchWithRule+        :: (Show n, Show a, Ord n, Pretty n)+        => RewriteRule a n   -- ^ Rule to unify with.+        -> RE.RewriteEnv a n -- ^ Environment to rewrite in, contains witnesses+                             --   for the constraints on rules.+        -> Exp a n           -- ^ Function-part of the expression to rewrite.+        -> [(Exp a n, a)]    -- ^ Arguments of expression to rewrite, with the +                             --   annotations we took from the XApp nodes.+        -> RM.SubstInfo  a n -- ^ Existing substitution to match with++        -> Maybe ( RM.SubstInfo a n+                 , [(Exp a n, a)])+                             -- ^ Substitution map and remaining (unmatched) args++-- Handle a rule without a hole.+matchWithRule+        RewriteRule+         { ruleBinds     = binds+         , ruleLeft      = lhs+         , ruleLeftHole  = Nothing+         , ruleFreeVars  = free }+         env f args sub+ = do   +        -- Check that none of the free variables have been rebound.+        when (any (flip RE.hasDef env) free)+         $ Nothing++        -- Get names of all the variables bound by the rule.+        --  This should always match because checked rules are guaranteed not to+        --  have `BAnon` or `BNone` binders.+        let Just vs +                = liftM Set.fromList+                $ sequence +                $ map T.takeNameOfBind+                $ map snd binds++        -- Split the left part of the rule in to the function part and its+        -- arguments.+        l:ls    <- return $ X.takeXAppsAsList lhs++        -- Match the function part of the expression against+        -- the function part of the rule.+        sub'    <- RM.match sub vs l f++        -- Match each of the expression arguments against +        -- the arguments of the rule.+        let go m [] rest+             = do return $ (m, rest)++            go m (l':ls') ((r,_):rs)+             = do m' <- RM.match m vs l' r+                  go m' ls' rs++            go _ _ _ +             = Nothing++        go sub' ls args+++-- Handle a rule with a hole. +-- An example rule with a holes is:+--      RULE (i : Int). unbox {box i} = i+matchWithRule+        rule@(RewriteRule { ruleLeftHole = Just hole })+        env f args sub++        -- Try to match against entire rule with no inlining.+        -- Eg (unbox (box 5))+        | Just a        <- X.takeAnnotOfExp f+        , lhs_full      <- XApp a (ruleLeft rule) hole +        , rule_full     <- rule { ruleLeft = lhs_full, ruleLeftHole = Nothing}+        , Just subst    <- matchWithRule rule_full env f args sub+        = Just subst++        -- Try to match against the part without the hole.+        --  eg unifyWithRule (RULE (i : Int). unbox) (unbox x)+        -- which will return a substitution (empty here),+        -- and the leftover argument 'x'.+        | rule_some     <- rule { ruleLeftHole = Nothing }+        , Just (sub', (XVar _ b, _) : as)+                        <- matchWithRule rule_some env f args sub++        -- See if the 'x' variable is let-bound in an outer scope+        , Just d'       <- RE.getDef b env +        , (fd, ad)      <- X.takeXAppsWithAnnots d' ++        -- Match the hole part with the right of the 'x' binding.+        -- This completes the match, so we merge this new substitution+        -- with the one for the outer part of the rule.+        , rule_hole        <- rule { ruleLeft = hole, ruleLeftHole = Nothing }+        , Just (subd, asd) <- matchWithRule rule_hole env fd ad sub'+        = Just (subd, asd ++ as)++        -- rule_some didn't match properly: failure+        | otherwise+        = Nothing+++-------------------------------------------------------------------------------+-- | Lookup a binding from a rewrite rule substitution.+--+--    Eg: RULE [x : %] (x : Int x). ...+-- +lookupFromSubst :: Ord n+        => [(BindMode,Bind n)]+        -> (Map n (Exp a n), Map n (Type n))+        -> [(Bind n, Exp a n)]++lookupFromSubst bs m+ = let  bas  = catMaybes $ map (lookupX m) bs+   in   map (\(b, a) -> (A.anonymizeX b, A.anonymizeX a)) bas+   + where  lookupX (xs,_) (BMValue _, b@(BName n _))+         | Just x <- Map.lookup n xs+         = Just (b, x)++        lookupX (_,tys) (BMSpec, b@(BName n _))+         | Just t <- Map.lookup n tys+         = Just (b, XType t)++        lookupX _ _ = Nothing+
+ DDC/Core/Transform/Rewrite/Disjoint.hs view
@@ -0,0 +1,203 @@+-- | Check whether two effects are non-interfering+module DDC.Core.Transform.Rewrite.Disjoint+        ( checkDisjoint+        , checkDistinct )+where+import DDC.Core.Exp+import DDC.Type.Predicates+import DDC.Type.Compounds+import qualified DDC.Core.Transform.Rewrite.Env	as RE+import qualified DDC.Type.Sum			as Sum+import qualified DDC.Type.Transform.Crush	as TC+++-- | Check whether a disjointness property is true in the given+--   rewrite environment.+--+--   Disjointness means that two effects do not interfere.+--+--   Context is important because if two regions are known to be+--   distinct, reading from one and writing to another is valid.+--   If they have different names they may not be distinct.+--+--   All read effects are disjoint with other reads.+--+-- > Disjoint (Read r1) (Read r2)+-- > Disjoint (Read r1) (DeepRead a)+--+--   Allocation effects are disjoint with everything.+--+-- > Disjoint (Alloc r) (_)+--+--   Atomic reads and write effects are disjoint if they are to distinct regions.+--+-- >         Distinct r1 r2+-- > -----------------------------+-- > Disjoint (Read r1) (Write r2)+-- +--   @DeepWrite@ effects are only disjoint with allocation effects, because+--   we don't know what regions it will write to.+--+--   An effect sum is disjoint from some other effect if all its components are.+--+-- > Disjoint f1 g /\ Disjoint f2 g+-- > -----------------------------+-- >      Disjoint (f1 + f2) g+--+--   Disjointness is commutative.+--+-- > Disjoint f g+-- > ------------+-- > Disjoint g f+--  +--   Example:+--   +-- >  checkDisjoint+-- >	(Disjoint (Read r1 + Read r2) (Write r3))+-- >	[Distinct r1 r3, Distinct r2 r3]+-- >  = True+--+checkDisjoint+        :: (Ord n, Show n)+        => Type n               -- ^ Type of property we want+                                --   eg @Disjoint e1 e2@+        -> RE.RewriteEnv a n	-- ^ Environment we're rewriting in.+        -> Bool++checkDisjoint c env+        -- The type must have the form "Disjoint e1 e2"+        | [TCon (TyConWitness TwConDisjoint), fs, gs] <- takeTApps c+        = and [ areDisjoint env g f +                | f <- sumList $ TC.crushEffect fs+                , g <- sumList $ TC.crushEffect gs ]++        | otherwise+        = False+        where   sumList (TSum ts) = Sum.toList ts+                sumList tt        = [tt]+++-- | Check whether two atomic effects are disjoint.+areDisjoint +        :: (Ord n, Show n)+        => RE.RewriteEnv a n+        -> Effect n+        -> Effect n+        -> Bool++areDisjoint env t1 t2+        -- Allocations are disjoint with everything.+        |   isSomeAllocEffect t1+         || isSomeAllocEffect t2+        = True ++        -- All the read effects are disjoint with each other.+        | isSomeReadEffect t1+        , isSomeReadEffect t2+        = True++        -- Combinations of reads and writes are disjoint+        -- if the regions are distinct.+        | TApp _ tR1            <- t1+        , TApp _ tR2            <- t2+        ,   (isReadEffect  t1 && isWriteEffect t2)+         || (isWriteEffect t1 && isReadEffect  t2)+         || (isWriteEffect t1 && isWriteEffect t2)+        = areDistinct env tR1 tR2++        -- All other effects are assumed to be interfering.+        | otherwise                     = False+++-- Distinct -------------------------------------------------------------------+-- | Check whether a distintness property is true in the given +--   rewrite environment.+--+--   Distinctness means that two regions do not alias.+--+checkDistinct+    :: Ord n+    => Type n			-- ^ Type of the property we want,+                                --   eg @Distinct r1 r2@+    -> RE.RewriteEnv a n	-- ^ Environment we're rewriting in.+    -> Bool++checkDistinct c env+        -- It's of the form "Distinct r q"+        | (TCon (TyConWitness (TwConDistinct _)) : args)+        	<- takeTApps c+        = all (uncurry $ areDistinct env) (combinations args)++        | otherwise+        = False++        where   combinations [] = []+                combinations (x:xs) = repeat x `zip` xs ++ combinations xs+++-- | Check if two regions are distinct.+areDistinct+        :: Ord n+        => RE.RewriteEnv a n+        -> Type n -> Type n -> Bool++areDistinct env t1 t2+        | Just u1   <- takeBound t1+        , Just u2   <- takeBound t2+        = areDistinctBound env u1 u2++        | otherwise+        = False+        where   takeBound (TVar u)                = Just u+                takeBound (TCon (TyConBound u _)) = Just u+                takeBound _                       = Nothing+++-- | Check whether two regions are distinct.+--   This version takes `Bounds` so we don't need to worry about+--   region constructors like R0# directly.+areDistinctBound +        :: Ord n+        => RE.RewriteEnv a n+        -> Bound n -> Bound n -> Bool++areDistinctBound env p q+        -- If they are the same, they can't possibly be different+        | p == q+        = False++        -- If they're both named primitives (eg R0#, R1#)+        -- we can just check name-equality, since can't be bound in lambdas+        -- Or if they're both bound in letregions, we can check by name+        -- (and we know names are different because that's an insta-fail)+        | concrete p && concrete q+        = True++        -- Check witness map for "Distinct p q" and vice versa+        | any check $ RE.getWitnesses env+        = True++        -- Otherwise not.+        | otherwise+        = False++        where   -- Check if region is 'concrete' either a region handle (R0#) +                -- or bound by a letregion in a higher scope.+                concrete r+                 = case r of+                        UPrim _ _ -> True+                        _	  -> RE.containsRegion r env++                check w+                 | (TCon (TyConWitness (TwConDistinct _)) : args)+                        <- takeTApps w+                 = rgn p `elem` args && rgn q `elem` args++                 | otherwise+                 = False++                rgn b+                 = case b of+                    UPrim _ t   -> TCon (TyConBound b t)+                    _	        -> TVar b+
+ DDC/Core/Transform/Rewrite/Env.hs view
@@ -0,0 +1,219 @@+module DDC.Core.Transform.Rewrite.Env+        ( RewriteEnv+        , empty+        , extend+        , extendLets+        , containsRegion+        , containsWitness+        , getWitnesses+        , insertDef+        , getDef+        , hasDef+        , lift+        , liftValue)+where+import DDC.Core.Exp+import qualified DDC.Type.Exp			as T+import qualified DDC.Type.Compounds		as T+import qualified DDC.Type.Predicates		as T+import qualified DDC.Type.Transform.LiftT	as L+import qualified DDC.Core.Transform.LiftX	as L+import Data.Maybe (fromMaybe, listToMaybe, isJust)+++-- | A summary of the environment that we perform a rewrite in.+--+--   As we decend into the program looking for expressions to rewrite, +--   we keep track of what information as been defined in the environment+--   in a `RewriteEnv`.+--+--   When we go under an anonymous binder then we push a new outermost+--   list instead of lifting every element on the environment eagerly.+--   +data RewriteEnv a n +        = RewriteEnv+        { -- | Types of all witnesses in scope.+          --   We use these to satisfy constraints on rewrite rules like Const r.+          witnesses     :: [[T.Type n]]++          -- | Names of letregion-bound regions:+          --   this is interesting because they must be distinct.+        , letregions    :: [[Bind n]]++          -- | Assoc of known values+          --   If going to inline them, they must only reference de bruijn binds+          --   these are value-level bindings, so be careful lifting.+        , defs	         :: [[RewriteDef a n]] }+        deriving (Show,Eq)+++type RewriteDef a n +        = (Bind n, Maybe (Exp a n))+++-- | An empty environment.+empty   :: Ord n => RewriteEnv a n+empty = RewriteEnv [] [] []+++-- | Extend an environment with some lambda-bound binder (XLam)+--   Might be a witness. Don't count if it's a region.+extend  :: Ord n => Bind n -> RewriteEnv a n -> RewriteEnv a n+extend b env+        | T.isWitnessType (T.typeOfBind b)+        = let   ty      = T.typeOfBind b+                extend' (w:ws') = (ty:w) : ws'+                extend' []              = [[ty]]+          in    liftValue b $ env { witnesses = extend' (witnesses env) }++        | otherwise+        = insertDef b Nothing (liftValue b env)+++-- | Extend an environment with the variables bount by these let-bindings.+--+--   If it's a letregion, remember the region's name and any witnesses.+--+extendLets :: Ord n => Lets a n -> RewriteEnv a n -> RewriteEnv a n+extendLets (LLetRegions bs cs) renv+ = foldl (flip extend) (foldl extendB renv bs) cs+ where  +        extendB (env@RewriteEnv{witnesses = ws, letregions = rs}) b+         = case b of+                BAnon{}+                 -> env { witnesses  = []  : ws+                        , letregions = [b] : rs }+      +                BName{}+                 -> env { letregions = extend' b rs }++                BNone{}+                 -> env++        extend' b (r:rs') = (b:r) : rs'+        extend' b []	   = [[b]]++extendLets (LLet _ b def) env+ = insertDef b (Just def') (liftValue b env)+ where  def' = case b of+	         BAnon{} -> L.liftX 1 def+        	 _	 -> def++extendLets (LRec bs) env+ = foldl lift' env (map fst bs)+ where  lift' e b = insertDef b Nothing (liftValue b e)+++extendLets _ env  = env+++-- Witnesses ------------------------------------------------------------------+-- | Check if the witness map in the given environment.+---  +--  This tries each set in turn, lowering the indices in c by 1 after each+--  unsuccessful match. If nothing matches then 'c' may end up with negative +--  indices, which will definiately not match anything else.+--+containsWitness :: Ord n => Type n -> RewriteEnv a n -> Bool+containsWitness c env+ = go c (witnesses env)+ where  go _  []        = False+        go c' (w:ws)    = c' `elem` w || go (L.liftT (-1) c') ws+++-- | Get a list of all the witness types in an environment, +--   normalising their indices.+getWitnesses :: Ord n => RewriteEnv a n -> [Type n]+getWitnesses env+ = go (witnesses env) 0+ where  go []     _ = []+        go (w:ws) i = map (L.liftT i) w ++ go ws (i+1)+++-- Regions --------------------------------------------------------------------+-- | Check whether an environment contains the given region, +--   bound by a letregion.+containsRegion :: Ord n => Bound n -> RewriteEnv a n -> Bool+containsRegion r env+ = go r (letregions env)+ where  +        go _  []+         = False++        go (UIx 0) (w:_) +         = any (T.boundMatchesBind (UIx 0)) w++        go (UIx n) (_:ws) +         = go (UIx (n-1)) ws++        go (UName n) (w:ws) +         = any (T.boundMatchesBind (UName n)) w || go r ws++        go (UPrim _ _) _+         = False+++-- Defs -----------------------------------------------------------------------+-- | Insert a rewrite definition into the environment.+insertDef :: Bind n -> Maybe (Exp a n) -> RewriteEnv a n -> RewriteEnv a n+insertDef b def env+ = env { defs = extend' $ defs env }+ where  +        extend' (r:rs') = ((b,def):r) : rs'+        extend' []	= [[(b,def)]]+++hasDef  :: (Ord n, L.MapBoundX (Exp a) n)+        => Bound n -> RewriteEnv a n -> Bool++hasDef b env+ = isJust $ getDef' b env+++-- | Lookup the definition of some let-bound variable from the environment.+getDef  :: (Ord n, L.MapBoundX (Exp a) n)+        => Bound n+        -> RewriteEnv a n+        -> Maybe (Exp a n)+getDef b env+ = fromMaybe Nothing $ getDef' b env+++getDef' :: (Ord n, L.MapBoundX (Exp a) n)+        => Bound n+        -> RewriteEnv a n+        -> Maybe (Maybe (Exp a n))++getDef' b env+ = go b 0 (defs env)+ where  +        go _ _  []      = Nothing+        go b' i (w:ws)  = match b' i w `orM` go (L.liftX (-1) b') (i+1) ws++        match b' i ds+                = fmap (fmap $ L.liftX i)+		$ listToMaybe+		$ map snd+		$ filter (T.boundMatchesBind b' . fst) ds++        orM (Just x) _  = Just x+        orM Nothing  y  = y+++-- | Raise all elements in witness map if binder is anonymous.+--   Only call with type binders: ie XLAM, not XLam+lift :: Bind n -> RewriteEnv a n -> RewriteEnv a n+lift b env@(RewriteEnv ws rs is)+ = case b of+        BAnon{} -> RewriteEnv ([]:ws) ([]:rs) is+        _       -> env+++-- | Raise all elements in definitions map if binder is anonymous+--   Use for *value* binders, not type binders.+liftValue :: Bind n -> RewriteEnv a n -> RewriteEnv a n+liftValue b env@(RewriteEnv ws rs is)+ = case b of+        BAnon{} -> RewriteEnv ws rs ([]:is)+        _       -> env+
+ DDC/Core/Transform/Rewrite/Error.hs view
@@ -0,0 +1,80 @@+module DDC.Core.Transform.Rewrite.Error+        ( Error (..)+        , Side  (..))+where+import DDC.Core.Exp+import DDC.Core.Check                   ()+import DDC.Type.Pretty+import qualified DDC.Core.Check         as C+++-- | What can go wrong when checking a rewrite rule.+data Error a n+        -- | Error typechecking one of the expressions+        = ErrorTypeCheck+        { -- | What side of the rule the error was on.+          errorSide         :: Side+        , errorExp          :: Exp a n+        , errorCheckError   :: C.Error a n }++        -- | Error typechecking one of the expressions+        | ErrorBadConstraint+        { errorConstraint   :: Type n }++        -- | Types don't match...+        | ErrorTypeConflict+        { errorTypeLhs      :: (Type n, Effect n, Closure n)+        , errorTypeRhs      :: (Type n, Effect n, Closure n) }++        -- | No binders allowed in left-hand side (right is fine, eg @let@s)+        | ErrorNotFirstOrder+        { errorExp          :: Exp a n }++        -- | All variables must be mentioned in left-hand side,+        --   otherwise they won't get bound.+        | ErrorVarUnmentioned++        -- | I don't want to deal with anonymous variables.+        | ErrorAnonymousBinder+        { errorBinder       :: Bind n }+++-- | What side of a rewrite rule we're talking about.+data Side +        = Lhs | Rhs+++instance Pretty Side where+ ppr Lhs = text "lhs"+ ppr Rhs = text "rhs"+++instance (Show a, Pretty n, Show n, Eq n) => Pretty (Error a n) where+ ppr err+  = case err of+        ErrorTypeCheck s x e+         -> vcat [ text "Can't typecheck " <> ppr s <> text ":  " <> ppr e+                 , text "While checking "  <> ppr x ]++        ErrorBadConstraint c+         ->        text "Bad constraint: " <> ppr c++        ErrorTypeConflict (tl,el,cl) (tr,er,cr)+         -> vcat [ text "LHS and RHS have different types:"+                 , text "Type L: "      <> ppr tl +                 , text "Type R: "      <> ppr tr+                 , text "Eff L:  "      <> ppr el+                 , text "Eff R:  "      <> ppr er+                 , text "Clo L:  "      <> ppr cl+                 , text "Clo R:  "      <> ppr cr ]++        ErrorNotFirstOrder x+         -> vcat [ text "No binders allowed in left-hand side."+                 , text "While checking " <> ppr x ]++        ErrorVarUnmentioned +         ->        text "All variables in rule should be mentioned in left-hand side."++        ErrorAnonymousBinder b+         ->        text "Anonymous binders, just give it a name: " <> ppr b+
+ DDC/Core/Transform/Rewrite/Match.hs view
@@ -0,0 +1,209 @@+-- | Create substitution to make (subst template) == target+module DDC.Core.Transform.Rewrite.Match+        ( -- * Substitutions+          SubstInfo+        , emptySubstInfo ++          -- * Matching+        , match)+where+import DDC.Core.Exp+import DDC.Type.Transform.Crush+import Data.Set                                 (Set)+import Data.Map                                 (Map)+import qualified DDC.Type.Sum                   as Sum+import qualified DDC.Type.Transform.AnonymizeT	as T+import qualified DDC.Core.Transform.AnonymizeX	as T+import qualified DDC.Core.Transform.Reannotate	as T+import qualified DDC.Type.Equiv			as TE+import qualified Data.Map			as Map+import qualified Data.Set			as Set+++-------------------------------------------------------------------------------+-- | Value and type substition.+type SubstInfo a n +        = (Map n (Exp a n), Map n (Type n))++-- | An empty substition info.+emptySubstInfo :: SubstInfo a n+emptySubstInfo +        = (Map.empty, Map.empty)++lookupx n (xs,_) +        = Map.lookup n xs++insertx n x (xs,tys) +        = (Map.insert n x xs, tys)+++-- Match Exp ------------------------------------------------------------------+-- | Create substitution to make (subst template) == target+--   Does not handle higher-order templates (ie ones with binders)+--+--  @ match emptySubstInfo (Set.fromList [r1, r2, s])+--   (stream [r1]  (unstream [r2]  s))+--   (stream [R0#] (unstream [R1#] (someStream 23))+--+--   => { r1 |-> R0#, r2 |-> R1, s |-> someStream 23 }+--  @+match   :: (Show a, Show n, Ord n)+        => SubstInfo a n        -- ^ Current substitution+        -> Set n                -- ^ Variables we're interested in+        -> Exp a n              -- ^ Template expression.+        -> Exp a n              -- ^ Target expression.+        -> Maybe (SubstInfo a n)++-- Variables bound by the rule: restricted to just UName earlier.+match m bs (XVar _ (UName n)) r+ | n `Set.member` bs+ -- Check if it's already been matched+ = case lookupx n m of+   Nothing -> return $ insertx n r m+   Just x  +    ->  -- Check if they're equal. Anonymize so names don't matter.+	-- Reannotate so annotations are ignored.+	let  x' = T.anonymizeX $ T.reannotate (const ()) x+	     r' = T.anonymizeX $ T.reannotate (const ()) r+	in if   x' == r'+	   then Just m+	   else Nothing++match m _ (XVar _ v1) (XVar _ v2)+ | v1 == v2      = Just m++match m _ (XCon _ c1) (XCon _ c2)+ | c1 == c2      = Just m++match m bs (XApp _ x11 x12) (XApp _ x21 x22)+ = do	m' <- match m bs x11 x21+	match m' bs x12 x22++match m bs (XCast _ c1 x1) (XCast _ c2 x2)+ | eqCast c1 c2	= match m bs x1 x2++match (xs, tys) bs (XType t1) (XType t2)+ = do	tys' <- matchT t1 t2 bs tys+	return (xs, tys')++match m _ (XWitness w1) (XWitness w2)+ | eqWit w1 w2	= return m++match _ _ _ _ + = Nothing+++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++        cleanX +         = T.anonymizeX . T.reannotate (const ())++eqWit lw rw +        = lw == rw++-- Types ----------------------------------------------------------------------+type VarSet n = Set.Set n+type Subst n  = Map.Map n (Type n)+++-- | Try to find a simple substitution between two types.+--   Ignoring complicated effect sums.+--   Also ignoring TForall - checkRewriteRule outlaws foralls in the template, so it's safe.+--   Eg given template @a -> b@ and target @Int -> Float@,+--   returns substitution:+--      @{ a |-> Int, b |-> Float }@+--+matchT  :: Ord n+        => Type n       -- ^ Template type.+        -> Type n       -- ^ Target type.+        -> VarSet n     -- ^ Only attempt to match these names.+        -> Subst n      -- ^ Already matched (or @Map.empty@)+        -> Maybe (Subst n)++matchT t1 t2 vs subst+ = let  t1'     = unpackSumT $ crushSomeT t1+        t2'     = unpackSumT $ crushSomeT t2+   in case (t1', t2') of+        -- Constructor names must be equal.+        --+        -- Will this still work when it's a TyConBound - basically same as TVar?+        (TCon tc1,        TCon tc2)+         | tc1 == tc2+         -> Just subst++        -- Decend into applications.+        (TApp t11 t12,    TApp t21 t22)+         -> matchT t11 t21 vs subst >>= matchT t12 t22 vs++        -- Sums are equivalent if all of their components are.+        --   Very simple matching, only consider equivalent if both have same+        --   length and in the same order.+        --+        -- > (Read + Write + a) `matchT` (Read + Write + Alloc)+        -- > =+        -- > Just { a |-> Alloc }+        -- but+        -- > (Read + a + Write) `matchT` (Read + Write + Alloc)+        -- > =+        -- > Nothing+        -- and+        -- > (Read + Write + Alloc + a) `matchT` (Read + Write + Alloc)+        -- > =+        -- > Nothing+        -- despite a valid substitution existing as+        -- > { a |-> !0 }+        --+        (TSum ts1,        TSum ts2)+         -> let ts1'      = Sum.toList ts1+                ts2'      = Sum.toList ts2++                go (l:ls) (r:rs) s = matchT l r vs s >>= go ls rs+                go _      _      s = Just s+            in  if   length ts1' /= length ts2'+                then Nothing+                else go ts1' ts2' subst+++        -- If template is in variable set, push the target into substitution+        (TVar (UName n), _)+         | Set.member n vs+         , Nothing <- Map.lookup n subst+         -> Just $ Map.insert n t2' subst++         | Set.member n vs+         , Just t1'' <- Map.lookup n subst+         , TE.equivT t1'' t2'+         -> Just subst++        -- Both are variables but it's not a template variable,+        -- so it's only valid if they're equal.+        (TVar (UName n), TVar v2)+         | not $ Set.member n vs+         , UName n == v2+         -> Just subst++        (TVar (UIx i), TVar v2)+         | UIx i == v2+         -> Just subst++        (TVar (UPrim n t), TVar v2)+         | UPrim n t == v2+         -> Just subst++        -- Otherwise the two are different+        (_, _)  -> Nothing+++-- | Unpack single element sums into plain types.+unpackSumT :: Type n -> Type n+unpackSumT (TSum ts)+        | [t]   <- Sum.toList ts = t+unpackSumT tt                    = tt+
+ DDC/Core/Transform/Rewrite/Parser.hs view
@@ -0,0 +1,115 @@++-- | Core language parser.+module DDC.Core.Transform.Rewrite.Parser+        (pRule, pRuleMany)+where+import DDC.Core.Exp+import DDC.Core.Parser+import DDC.Core.Lexer.Tokens+import qualified DDC.Base.Parser                 as P+import qualified DDC.Type.Compounds              as T+import qualified DDC.Core.Transform.Rewrite.Rule as R+++-- Rewrite Rules ----------------------------------------------------------------+{-+    [r1 r2 : %] (x : Int r1).+	Const r1 =>+	addInt [:r1 r2 r1:] x (0 [r2] ()) =+	x+-}+-- | Parse a rewrite rule.+pRule	:: Ord n => Parser n (R.RewriteRule () n)+pRule+ = do	bs	 <- pRuleBinders+	(cs,lhs) <- pRuleCsLhs+	hole	 <- pRuleHole+	pTok KEquals+	rhs	 <- pExp++	return $ R.mkRewriteRule bs cs lhs hole rhs+++{-+add_zero_r+    [r1 r2 : %] (x : Int r1).+	Const r1 =>+	addInt [:r1 r2 r1:] x (0 [r2] ()) =+	x;+add_zero_l+    [r1 r2 : %] ...+        ;+-}+-- | Parse many rewrite rules.+pRuleMany	:: Ord n => Parser n [(n,R.RewriteRule () n)]+pRuleMany+ = P.many (do+        n <- pName+        r <- pRule+        pTok KSemiColon+        return (n,r))+++pRuleBinders :: Ord n => Parser n [(R.BindMode,Bind n)]+pRuleBinders+ = P.choice+ [ do	bs <- P.many1 pBinders+	pTok KDot+	return $ concat bs+ , return []+ ]+++pRuleCsLhs :: Ord n => Parser n ([Type n], Exp () n)+pRuleCsLhs+ = P.choice+ [ do	cs <- P.many1 $ P.try (do+		c <- pTypeApp+		pTok KArrowEquals+		return c)+	lhs <- pExp+	return (cs,lhs)+ , do	lhs <- pExp+	return ([],lhs)+ ]+++pRuleHole :: Ord n => Parser n (Maybe (Exp () n))+pRuleHole+ = P.optionMaybe+ $ do	pTok KBraceBra+	e <- pExp+	pTok KBraceKet+	return e+++-- | Parse rewrite binders+--+-- Many of:+--       [BIND1 BIND2 .. BINDN : TYPE]+--   or  (BIND : TYPE)+--+pBinders :: Ord n => Parser n [(R.BindMode, Bind n)]+pBinders+ = P.choice+ [ pBindersBetween R.BMSpec      (pTok KSquareBra) (pTok KSquareKet)+ , pBindersBetween (R.BMValue 0) (pTok KRoundBra)  (pTok KRoundKet)+ ]+++pBindersBetween +        :: Ord n +        => R.BindMode +        -> Parser n () +        -> Parser n () +        -> Parser n [(R.BindMode,Bind n)]++pBindersBetween bm bra ket+ = do	bra+        bs      <- P.many1 pBinder+        pTok KColon+        t       <- pType+        ket+        return $ map (mk t) bs+ where mk t b = (bm,T.makeBindFromBinder b t)+
+ DDC/Core/Transform/Rewrite/Rule.hs view
@@ -0,0 +1,513 @@+-- | Constructing and checking whether rewrite rules are valid+module DDC.Core.Transform.Rewrite.Rule +        ( -- * Binding modes+          BindMode      (..)+        , isBMSpec+        , isBMValue++        , RewriteRule   (..)+        , NamedRewriteRule++          -- * Construction+        , mkRewriteRule+        , checkRewriteRule+        , Error (..)+        , Side  (..))+where+import DDC.Core.Transform.Rewrite.Error+import DDC.Core.Transform.Reannotate+import DDC.Core.Transform.TransformX+import DDC.Core.Exp+import DDC.Core.Pretty                          ()+import DDC.Core.Collect+import DDC.Core.Compounds+import DDC.Type.Pretty                          ()+import DDC.Type.Env                             (KindEnv, TypeEnv)+import DDC.Base.Pretty+import Control.Monad+import qualified DDC.Core.Analysis.Usage        as U+import qualified DDC.Core.Check                 as C+import qualified DDC.Core.Collect               as C+import qualified DDC.Core.Transform.SpreadX     as S+import qualified DDC.Type.Check                 as T+import qualified DDC.Type.Compounds             as T+import qualified DDC.Type.Env                   as T+import qualified DDC.Type.Equiv                 as T+import qualified DDC.Type.Predicates            as T+import qualified DDC.Type.Subsumes              as T+import qualified DDC.Type.Transform.SpreadT     as S+import qualified Data.Map                       as Map+import qualified Data.Maybe                     as Maybe+import qualified Data.Set                       as Set+import qualified DDC.Type.Env                   as Env+++-- | A rewrite rule. For example:+--+--   @ RULE [r1 r2 r3 : %] (x : Int r1)+--      . addInt  [:r1 r2 r3:] x (0 [r2] ()+--      = copyInt [:r1 r3:]    x+--   @+data RewriteRule a n+        = RewriteRule+        { -- | Variables bound by the rule.+          ruleBinds       :: [(BindMode, Bind n)]++          -- | Extra constraints on the rule.+          --   These must all be satisfied for the rule to fire.+        , ruleConstraints :: [Type n]           ++          -- | Left-hand side of the rule.+          --   We match on this part.+        , ruleLeft        :: Exp a n            ++          -- | Extra part of left-hand side,+          --   but allow this bit to be out-of-context.+        , ruleLeftHole    :: Maybe (Exp a n)    ++          -- | Right-hand side of the rule.+          --   We replace the matched expression with this part.+        , ruleRight       :: Exp a n            ++          -- | Effects that are caused by the left but not the right.+          --   When applying the rule we add an effect weakning to ensure+          --   the rewritten expression has the same effects.+        , ruleWeakEff     :: Maybe (Effect n)   ++          -- | Closure that the left has that is not present in the right.+          --   When applying the rule we add a closure weakening to ensure+          --   the rewritten expression has the same closure.+        , ruleWeakClo     :: [Exp a n]          ++          -- | References to environment. +          --   Used to check whether the rule is shadowed.+        , ruleFreeVars    :: [Bound n]          +        } deriving (Eq, Show)+++type NamedRewriteRule a n+        = (String, RewriteRule a n)+++instance (Pretty n, Eq n) => Pretty (RewriteRule a n) where+ ppr (RewriteRule bs cs lhs hole rhs _ _ _)+  = pprBinders bs <> pprConstrs cs <> ppr lhs <> pprHole <> text " = " <> ppr rhs+  where pprBinders []            = text ""+        pprBinders bs'           = foldl1 (<>) (map pprBinder bs') <> text ". "++        pprBinder (BMSpec, b)    = text "[" <> ppr b <> text "] "+        pprBinder (BMValue _, b) = text "(" <> ppr b <> text ") "+      +        pprConstrs []            = text ""+        pprConstrs (c:cs')       = ppr c <> text " => " <> pprConstrs cs'++        pprHole+         | Just h <- hole+         = text " {" <> ppr h <> text "}"++         | otherwise+         = text ""+++-- BindMode -------------------------------------------------------------------+-- | Binding level for the binders in a rewrite rule.+data BindMode +        -- | Level-1 binder (specs)+        = BMSpec ++        -- | Level-0 binder (data values and witnesses)+        | BMValue Int -- ^ number of usages+        deriving (Eq, Show)+++-- | Check if a `BindMode` is a `BMSpec`.+isBMSpec :: BindMode -> Bool+isBMSpec BMSpec         = True+isBMSpec _              = False+++-- | Check if a `BindMode` is a `BMValue`.+isBMValue :: BindMode -> Bool+isBMValue (BMValue _)   = True+isBMValue _             = False+++-- Make -----------------------------------------------------------------------+-- | Construct a rewrite rule, but do not check if it's valid.+--+--   You then need to apply 'checkRewriteRule' to check it.+--+mkRewriteRule+        :: Ord n+        => [(BindMode,Bind n)]  -- ^ Variables bound by the rule.+        -> [Type n]             -- ^ Extra constraints on the rule.+        -> Exp a n              -- ^ Left-hand side of the rule.+        -> Maybe (Exp a n)      -- ^ Extra part of left, can be out of context.+        -> Exp a n              -- ^ Right-hand side (replacement)+        -> RewriteRule a n++mkRewriteRule  bs cs lhs hole rhs+ = RewriteRule bs cs lhs hole rhs Nothing [] []+++-- Check ----------------------------------------------------------------------+-- | Take a rule, make sure it's valid and fill in type, closure and effect+--   information.+--+--   The left-hand side of rule can't have any binders (lambdas, lets etc).+--+--   All binders must appear in the left-hand side, otherwise they would match+--   with no value.+--+--   Both sides must have the same types, but the right can have fewer effects+--   and smaller closure.+--+--   We don't handle anonymous binders on either the left or right.+--+checkRewriteRule+    :: (Ord n, Show n, Pretty n)        +    => C.Config n               -- ^ Type checker config.+    -> T.Env n                  -- ^ Kind environment.+    -> T.Env n                  -- ^ Type environment.+    -> RewriteRule a n          -- ^ Rule to check+    -> Either (Error a n)+              (RewriteRule (C.AnTEC a n) n)++checkRewriteRule config kenv tenv+        (RewriteRule bs cs lhs hole rhs _ _ _)+ = do   +        -- Extend the environments with variables bound by the rule.+        let (kenv', tenv', bs')  = extendBinds bs kenv tenv+        let csSpread             = map (S.spreadT kenv') cs++        -- Check that all constraints are valid types.+        mapM_ (checkConstraint config kenv') csSpread++        -- Typecheck, spread and annotate with type information+        (lhs', _, _, _)+                <- checkExp config kenv' tenv' Lhs lhs ++        -- If the extra left part is there, typecheck and annotate it.+        hole' <- case hole of+                  Just h  +                   -> do  (h',_,_,_)  <- checkExp config kenv' tenv' Lhs h +                          return $ Just h'++                  Nothing -> return Nothing++        -- Build application from lhs and the hole so we can check its+        -- type against rhs+        let Just a      = takeAnnotOfExp lhs+        let lhs_full    = maybe lhs (XApp a lhs) hole++        -- Check the full left hand side.+        (lhs_full', tLeft, effLeft, cloLeft)+                <- checkExp config kenv' tenv' Lhs lhs_full++        -- Check the full right hand side.+        (rhs', tRight, effRight, cloRight)+                <- checkExp config kenv' tenv' Rhs rhs ++        -- Check that types of both sides are equivalent.+        let err = ErrorTypeConflict +                        (tLeft,  effLeft,  cloLeft) +                        (tRight, effRight, cloRight)++        checkEquiv tLeft tRight err++        -- Check the effect of the right is smaller than that +        -- of the left, and add a weakeff cast if nessesary+        effWeak        <- makeEffectWeakening  T.kEffect effLeft effRight err++        -- Check that the closure of the right is smaller than that+        -- of the left, and add a weakclo cast if nessesary.+        cloWeak        <- makeClosureWeakening config kenv' tenv' lhs_full' rhs'++        -- Check that all the bound variables are mentioned+        -- in the left-hand side.+        checkUnmentionedBinders bs' lhs_full'++        -- No BAnons allowed.+        --  We don't handle deBruijn binders.+        checkAnonymousBinders bs'++        -- No lets or lambdas in left-hand side.+        --  We can't match against these.+        checkValidPattern lhs_full++        -- Count how many times each binder is used in the right-hand side.+        bs''    <- countBinderUsage bs' rhs++        -- Get the free variables of the rule.+        let binds     = Set.fromList+                      $ Maybe.catMaybes+                      $ map (T.takeSubstBoundOfBind . snd) bs++        let freeVars  = Set.toList+                      $ (C.freeX T.empty lhs_full' +                         `Set.union` C.freeX T.empty rhs)+                      `Set.difference` binds++        return  $ RewriteRule +                        bs'' csSpread+                        lhs' hole' rhs'+                        effWeak cloWeak+                        freeVars+++-- | Extend kind and type environments with a rule's binders.+--   Which environment a binder goes into depends on its BindMode.+--   Also return list of binders which have been spread.+extendBinds +        :: Ord n +        => [(BindMode, Bind n)] +        -> KindEnv n -> TypeEnv n +        -> (T.KindEnv n, T.TypeEnv n, [(BindMode, Bind n)])++extendBinds binds kenv tenv+ = go binds kenv tenv []+ where+        go []          k t acc+         = (k,t,acc)++        go ((bm,b):bs) k t acc+         = let  b'      = S.spreadX k t b+                (k',t') = case bm of+                             BMSpec    -> (T.extend b' k, t)+                             BMValue _ -> (k, T.extend b' t)++           in  go bs k' t' (acc ++ [(bm,b')])+++-- | Type check the expression on one side of the rule.+checkExp +        :: (Ord n, Show n, Pretty n)+        => C.Config n +        -> KindEnv n    -- ^ Kind environment of expression.+        -> TypeEnv n    -- ^ Type environment of expression.+        -> Side         -- ^ Side that the expression appears on for errors.+        -> Exp a n      -- ^ Expression to check.+        -> Either (Error a n) +                  (Exp (C.AnTEC a n) n, Type n, Effect n, Closure n)++checkExp defs kenv tenv side xx+ = let xx' = S.spreadX kenv tenv xx +   in  case C.checkExp defs kenv tenv xx' of+        Left err  -> Left $ ErrorTypeCheck side xx' err+        Right rhs -> return rhs+++-- | Type check a constraint on the rule.+checkConstraint+        :: (Ord n, Show n, Pretty n)+        => C.Config n+        -> KindEnv n    -- ^ Kind environment of the constraint.+        -> 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+        Left _err               -> Left $ ErrorBadConstraint tt+        Right k+         | T.isWitnessType tt   -> return k+         | otherwise            -> Left $ ErrorBadConstraint tt+++-- | Check equivalence of types or error+checkEquiv+        :: Ord n+        => Type n       -- ^ Type of left of rule.+        -> Type n       -- ^ Type of right of rule.+        -> Error a n    -- ^ Error to report if the types don't match.+        -> Either (Error a n) ()++checkEquiv tLeft tRight err+        | T.equivT tLeft tRight  = return ()+        | otherwise              = Left err+++-- Weaken ---------------------------------------------------------------------+-- | Make the effect weakening for a rule.+--   This contains the effects that are caused by the left of the rule+--   but not the right. +--   If the right has more effects than the left then return an error.+--+makeEffectWeakening+        :: (Ord n, Show n)+        => Kind n       -- ^ Should be the effect kind.+        -> Effect n     -- ^ Effect of the left of the rule.+        -> Effect n     -- ^ Effect of the right of the rule.+        -> Error a n    -- ^ Error to report if the right is bigger.+        -> Either (Error a n) (Maybe (Type n))++makeEffectWeakening k effLeft effRight onError+        -- When the effect of the left matches that of the right+        -- then we don't have to do anything else.+        | T.equivT effLeft effRight+        = return Nothing++        -- When the effect of the right is smaller than that of+        -- the left then we need to wrap it in an effect weaking+        -- so the rewritten expression retains its original effect.+        | T.subsumesT k effLeft effRight+        = return $ Just effLeft++        -- When the effect of the right is more than that of the left+        -- then this is an error. The rewritten expression can't have+        -- can't have more effects than the source.+        | otherwise+        = Left onError+++-- | Make the closure weakening for a rule.+--   This contains a closure term for all variables that are present+--   in the left of a rule but not in the right.+--+makeClosureWeakening +        :: (Ord n, Pretty n, Show n)+        => C.Config n               -- ^ Type-checker config+        -> T.Env n                  -- ^ Kind environment.+        -> T.Env n                  -- ^ Type environment.+        -> Exp (C.AnTEC a n) n      -- ^ Expression on the left of the rule.+        -> Exp (C.AnTEC a n) n      -- ^ Expression on the right of the rule.+        -> Either (Error a n) +                  [Exp (C.AnTEC a n) n]++makeClosureWeakening config kenv tenv lhs rhs+ = let  lhs'         = removeEffects config kenv tenv lhs+        supportLeft  = support Env.empty Env.empty lhs'+        daLeft  = supportDaVar supportLeft+        wiLeft  = supportWiVar supportLeft+        spLeft  = supportSpVar supportLeft++        rhs'         = removeEffects config kenv tenv rhs+        supportRight = support Env.empty Env.empty rhs'+        daRight = supportDaVar supportRight+        wiRight = supportWiVar supportRight+        spRight = supportSpVar supportRight++        Just a  = takeAnnotOfExp lhs++   in   Right +         $  [XVar a u +                | u <- Set.toList $ daLeft `Set.difference` daRight ]++         ++ [XWitness (WVar u)+                | u <- Set.toList $ wiLeft `Set.difference` wiRight ]++         ++ [XType (TVar u)+                | u <- Set.toList $ spLeft `Set.difference` spRight ]+++-- | Replace all effects with !0.+--   This is done so that when @makeClosureWeakening@ finds free variables,+--   it ignores those only mentioned in effects.+removeEffects+        :: (Ord n, Pretty n, Show n)+        => C.Config n   -- ^ Type-checker config+        -> T.Env n      -- ^ Kind environment+        -> T.Env n      -- ^ Type environment+        -> Exp a n      -- ^ Target expression - has all effects replaced with bottom.+        -> Exp a n+removeEffects config = transformUpX remove+ where+  remove kenv _tenv x++   | XType et   <- x+   , Right k    <- T.checkType (C.configPrimDataDefs config)+                               kenv et+   , T.isEffectKind k+   = XType $ T.tBot T.kEffect++   | otherwise+   = x+++-- Structural Checks ----------------------------------------------------------+-- | Check for rule variables that have no uses.+checkUnmentionedBinders+        :: (Ord n, Show n)+        => [(BindMode, Bind n)]+        -> Exp (C.AnTEC a n) n+        -> Either (Error a n) ()++checkUnmentionedBinders bs expr+ = let  used  = C.freeX T.empty expr `Set.union` C.freeT T.empty expr++        binds = Set.fromList+              $ Maybe.catMaybes+              $ map (T.takeSubstBoundOfBind . snd) bs++   in   if binds `Set.isSubsetOf` used+         then return ()+         else Left ErrorVarUnmentioned+++-- | Check for anonymous binders in the rule. We don't handle these.+checkAnonymousBinders +        :: [(BindMode, Bind n)] +        -> Either (Error a n) ()++checkAnonymousBinders bs+        | (b:_) <- filter T.isBAnon $ map snd bs+        = Left $ ErrorAnonymousBinder b++        | otherwise+        = return ()+++-- | Check whether the form of the left-hand side of the rule is valid+--   we can only match against nested applications, and not general+--   expressions containing let-bindings and the like.+checkValidPattern :: Exp a n -> Either (Error a n) ()+checkValidPattern expr+ = go expr+ where  go (XVar _ _)           = return ()+        go (XCon _ _)           = return ()+        go x@(XLAM _ _ _)       = Left $ ErrorNotFirstOrder x+        go x@(XLam _ _ _)       = Left $ ErrorNotFirstOrder x+        go (XApp _ l r)         = go l >> go r+        go x@(XLet _ _ _)       = Left $ ErrorNotFirstOrder x+        go x@(XCase _ _ _)      = Left $ ErrorNotFirstOrder x+        go (XCast _ _ x)        = go x+        go (XType t)            = go_t t+        go (XWitness _)         = return ()++        go_t (TVar _)           = return ()+        go_t (TCon _)           = return ()+        go_t t@(TForall _ _)    = Left $ ErrorNotFirstOrder (XType t)+        go_t (TApp l r)         = go_t l >> go_t r+        go_t (TSum _)           = return ()+++-- | Count how many times each binder is used in right-hand side.+countBinderUsage +        :: Ord n +        => [(BindMode, Bind n)] +        -> Exp a n +        -> Either (Error a n) [(BindMode, Bind n)]++countBinderUsage bs x+ = let  Just (U.UsedMap um)+                = liftM fst $ takeAnnotOfExp $ U.usageX x++        get (BMValue _, BName n t)+         = (BMValue+                $ length+                $ Maybe.fromMaybe []+                $ Map.lookup n um+           , BName n t)++        get b+         = b++   in   return $ map get bs+++-- | Allow the expressions and anything else with annotations to be reannotated+instance Reannotate RewriteRule where+ reannotate f (RewriteRule bs cs lhs hole rhs eff clo fv)+   = RewriteRule bs cs (re lhs) (fmap re hole) (re rhs) eff (map re clo) fv+    where+     re = reannotate f+
+ DDC/Core/Transform/Snip.hs view
@@ -0,0 +1,300 @@++-- | Snip out nested applications.+module DDC.Core.Transform.Snip+        (Snip(..))+where+import DDC.Core.Analysis.Arity+import DDC.Core.Module+import DDC.Core.Exp+import DDC.Core.Compounds+import qualified DDC.Core.Transform.LiftX       as L+import qualified DDC.Type.Compounds             as T+++class Snip (c :: * -> *) where++ -- | Snip out nested applications as anonymous bindings.+ -- + -- @+ --      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+++instance Snip (Module a) where+ snip bOver mm+  = {-# SCC "snip[Module]" #-}+    let arities = aritiesOfModule mm+        body'   = snipX bOver arities (moduleBody mm) []+    in  mm { moduleBody = body'  }+++instance Snip (Exp a) where+ snip bOver x +  = {-# SCC "snip[Exp]" #-}+    snipX bOver emptyArities x []+++-- | Convert an expression into A-normal form.+snipX +        :: Ord n+        => Bool           -- ^ Introduce extra bindings for over-applied functions.+        -> 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+        -- 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++        -- Some non-application node with no arguments.+        | null args+        = enterX bOver arities x++        -- Some non-application node being applied to arguments.+        | otherwise+        = buildNormalisedApp bOver arities (enterX bOver arities x) args++-- Enter into a non-application.+enterX bOver arities xx+ = let  down ars e +         = snipX bOver (extendsArities arities ars) e []++   in case xx of+        -- The snipX function shouldn't have called us with an XApp.+        XApp{}           +         -> error "DDC.Core.Transform.Snip: snipX shouldn't give us an XApp"++        -- leafy constructors+        XVar{}           -> xx+        XCon{}           -> xx+        XType{}          -> xx+        XWitness{}       -> xx++        -- lambdas+        XLAM a b e+         -> XLAM a b (down [(b,0)] e)++        XLam a b e+         -> 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'++        -- recursive let+        XLet a (LRec lets) x2+         -> let bs      = map fst lets +                xs      = map snd lets +                ars     = zip bs (map arityOfExp' xs) +                xs'     = map (down ars) xs+                x2'     = 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)++        -- withregion+        XLet a (LWithRegion b) z2+         -> XLet a (LWithRegion b) (down [] z2)++        -- case+        -- Split out non-atomic discriminants into their own bindings.+        XCase a e alts+         | isAtom e+         -> let  e'      = down [] e +                 alts'   = map (\(AAlt pat ae) +                               -> AAlt pat (down (aritiesOfPat pat) ae)) alts +            in   XCase a e' alts'++         | otherwise+         -> let e'      = down [] e+                alts'   = [AAlt pat (down (aritiesOfPat pat) ae) | AAlt pat ae <- alts]++            in   XLet a (LLet LetStrict (BAnon (T.tBot T.kData)) e')+                        (XCase a (XVar a $ UIx 0) +                                 (map (L.liftX 1) alts'))++        -- cast+        XCast a c e+         -> XCast a c (down [] e)+++-- | 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+--   associated let-bound variable is passed to the function.+buildNormalisedApp +        :: Ord n+        => Bool            -- ^ Introduce extra bindings for over-applied functions.+        -> 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) : _)+ = make annot f0 args+ where+        tBot' = T.tBot T.kData++        -- Lookup the arity of the function.+        f0Arity    +         = case f0 of+                XVar _ b+                 | Just arity <- getArity arities b+                 -> max arity 1++                _ -> max (arityOfExp' f0) 1++        -- Make a normalised function application.+        make a xFun xsArgs++         -- The function part is already atomic.+         | isAtom xFun+         = buildNormalisedFunApp bOver 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 +                               (XVar a (UIx 0)) +                               [ (L.liftX 1 x, a') | (x, a') <- xsArgs])+++-- | 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+--   associated let-bound variable is passed to the function.+--+--   Unlike the `buildNormalisedFunApp` function above, this one+--   wants the function part to be normalised as well.+buildNormalisedFunApp+        :: Ord n+        => Bool           -- ^ Introduce extra bindings for over-applied functions.+        -> 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+ = let  tBot' = T.tBot T.kData++        -- Split arguments into the already atomic ones,+        --  and the ones we need to introduce let-expressions for.+        argss    = splitArgs xsArgs++        -- Collect up the new let-bindings.+        xsLets   = [ (x, a)  +                        | (_,    a, _, Just x) <- argss]++        -- The total number of new let-bindings.+        nLets    = length xsLets++        -- Lift indices in each binding over the bindings before it.+        xsLets'  = [ (L.liftX n x, a)+                        | (x, a)        <- xsLets+                        | (n :: Int)    <- [0..] ]++        -- Lift indices in the function over the bindings before it.+        xFun'    = L.liftX nLets xFun++        -- Collect up the new function arguments.+        --  If the argument was already atomic then we have to lift+        --  its indices past the new let bindings we're about to add.+        --  Otherwise it's a reference to one of the bindings directly.+        xsArgs'  = [if liftMe +                        then (L.liftX nLets xArg, a)+                        else (xArg, a)+                        | (xArg, a, liftMe, _)      <- argss]++        -- Construct the new function application.+        xFunApps ++         -- If the function is over-applied then create an intermediate+         -- binding that saturates it, then apply the extra arguments+         -- separately.+         | bOver+         , length xsArgs' > funArity+         , (xsSat, xsOver)      <- splitAt funArity xsArgs'+         = XLet an (LLet LetStrict (BAnon tBot') +                        (makeXAppsWithAnnots xFun' xsSat))+                   (makeXAppsWithAnnots +                        (XVar an (UIx 0)) +                        [ (L.liftX 1 x, a) | (x, a) <- xsOver ])++         -- Function has the correct number of arguments,+         -- or is partially applied.+         | otherwise+         = makeXAppsWithAnnots +                xFun'+                xsArgs'              ++        -- 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' ]+++-- | Sort function arguments into either the atomic ones, +--   or compound ones.+splitArgs +        :: Ord n+        => [(Exp a n, a)] +        -> [( Exp a n            -- Expression to use as the new argument.+            , a                  -- Annoation for the argument application.+            , Bool               -- Whether this argument was already atomic.+            , Maybe (Exp a n))]  -- New expression to let-bind.++splitArgs args+ = reverse $ go 0 $ reverse args+ where  +        go _n [] = []+        go n ((xArg, a) : xsArgs)+         | isAtom xArg+         = (xArg,           a, True,  Nothing)    : go n       xsArgs++         | otherwise+         = (XVar a (UIx n), a, False, Just xArg)  : go (n + 1) xsArgs+++-- | 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 xx+ = case xx of+        XVar{}          -> True+        XCon{}          -> True+        XType{}         -> True+        XWitness{}      -> True++        -- Casts are ignored by code generator, so we can leave them in if+        -- their subexpression is normal+        XCast _ _ x     -> isAtom x+        _               -> False+++-- | Take the arity of an expression, +--   returning 0 for XType and XWitness.+arityOfExp' :: Ord n => Exp a n -> Int+arityOfExp' xx+ = case arityOfExp xx of+        Nothing -> 0+        Just a  -> a+
DDC/Core/Transform/TransformX.hs view
@@ -2,11 +2,13 @@ -- | General purpose tree walking boilerplate. module DDC.Core.Transform.TransformX         ( TransformUpMX(..)-        , transformUpX)+        , transformUpX+        , transformUpX') where+import DDC.Core.Module import DDC.Core.Exp import DDC.Core.Compounds-import DDC.Type.Env             (Env)+import DDC.Type.Env             (KindEnv, TypeEnv) import Data.Functor.Identity import Control.Monad import qualified DDC.Type.Env   as Env@@ -16,10 +18,10 @@ transformUpX         :: forall (c :: * -> * -> *) a n         .  (Ord n, TransformUpMX Identity c)-        => (Env n -> Env n -> Exp a n -> Exp a n)       +        => (KindEnv n -> TypeEnv n -> Exp a n -> Exp a n)                                -- ^ The worker function is given the current kind and type environments.-        -> Env n        -- ^ Initial kind environment.-        -> Env n        -- ^ Initial type environment.+        -> KindEnv n    -- ^ Initial kind environment.+        -> TypeEnv n    -- ^ Initial type environment.         -> c a n        -- ^ Transform this thing.         -> c a n @@ -30,20 +32,44 @@                 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-        => (Env n -> Env n -> Exp a n -> m (Exp a n))-                        -- ^ The worker function is given the current kind and type environments.-        -> Env n        -- ^ Initial kind environment.-        -> Env n        -- ^ Initial type environment.+        => (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 =<<)+ transformUpMX f kenv tenv !xx+  = {-# SCC transformUpMX #-} +    (f kenv tenv =<<)   $ case xx of         XVar{}          -> return xx         XCon{}          -> return xx@@ -95,7 +121,7 @@                 xs'          <- mapM (transformUpMX f kenv tenv') xs                 return       $ LRec $ zip bs xs' -        LLetRegion{}    -> return xx+        LLetRegions{}    -> return xx         LWithRegion{}    -> return xx  @@ -110,3 +136,4 @@         AAlt PDefault x          ->     liftM2  AAlt (return PDefault)                         (transformUpMX f kenv tenv x) +
+ DDC/Type/Transform/Alpha.hs view
@@ -0,0 +1,53 @@++module DDC.Type.Transform.Alpha+        (Alpha(..))+where+import DDC.Type.Exp+import DDC.Type.Sum+++class Alpha (c :: * -> *) where+ -- | Apply a function to all the names in a thing.+ alpha :: forall n1 n2. Ord n2 => (n1 -> n2) -> c n1 -> c n2+ ++instance Alpha Type where+ alpha f tt+  = case tt of+        TVar    u       -> TVar    (alpha f u)+        TCon    c       -> TCon    (alpha f c)+        TForall b t     -> TForall (alpha f b)  (alpha f t)+        TApp    t1 t2   -> TApp    (alpha f t1) (alpha f t2)+        TSum    ts      -> TSum    (alpha f ts)+++instance Alpha TypeSum where+ alpha f ts+  = fromList (alpha f $ kindOfSum ts) $ map (alpha f) $ toList ts+++instance Alpha Bind where+ alpha f bb+  = case bb of+        BName n t       -> BName (f n) (alpha f t)+        BAnon   t       -> BAnon (alpha f t)+        BNone   t       -> BNone (alpha f t)+        ++instance Alpha Bound where+ alpha f uu+  = case uu of+        UIx i           -> UIx i+        UName n         -> UName (f n)+        UPrim n t       -> UPrim (f n) (alpha f t)+++instance Alpha TyCon where+ alpha f cc+  = case cc of+        TyConSort sc    -> TyConSort    sc+        TyConKind kc    -> TyConKind    kc+        TyConWitness tc -> TyConWitness tc+        TyConSpec tc    -> TyConSpec    tc+        TyConBound u t  -> TyConBound (alpha f u) (alpha f t)+
DDC/Type/Transform/AnonymizeT.hs view
@@ -57,17 +57,22 @@ instance AnonymizeT Bound where   anonymizeWithT kstack bb   = case bb of-        UName _ t+        UName _          | Just ix      <- findIndex (boundMatchesBind bb) kstack-         -> UIx ix (anonymizeWithT kstack t)+         -> UIx ix                   _ -> bb   -- Push ------------------------------------------------------------------------- Push a binding occurrence of a type variable on the stack, ---  returning the anonyized binding occurrence and the new stack.-pushAnonymizeBindT :: Ord n => [Bind n] -> Bind n -> ([Bind n], Bind n)+-- | Push a binding occurrence of a level-1 variable on the stack, +--   returning the anonyized binding occurrence and the new stack.+pushAnonymizeBindT +        :: Ord n +        => [Bind n]             -- ^ Stack for Spec binders (level-1)+        -> Bind n +        -> ([Bind n], Bind n)+ pushAnonymizeBindT kstack b  = let  t'      = typeOfBind b         kstack' = b : kstack
− DDC/Type/Transform/Rename.hs
@@ -1,53 +0,0 @@--module DDC.Type.Transform.Rename-        (Rename(..))-where-import DDC.Type.Exp-import DDC.Type.Sum---class Rename (c :: * -> *) where- -- | Apply a function to all the names in a thing.- rename :: forall n1 n2. Ord n2 => (n1 -> n2) -> c n1 -> c n2- --instance Rename Type where- rename f tt-  = case tt of-        TVar    u       -> TVar    (rename f u)-        TCon    c       -> TCon    (rename f c)-        TForall b t     -> TForall (rename f b)  (rename f t)-        TApp    t1 t2   -> TApp    (rename f t1) (rename f t2)-        TSum    ts      -> TSum    (rename f ts)---instance Rename TypeSum where- rename f ts-  = fromList (rename f $ kindOfSum ts) $ map (rename f) $ toList ts---instance Rename Bind where- rename f bb-  = case bb of-        BName n t       -> BName (f n) (rename f t)-        BAnon   t       -> BAnon (rename f t)-        BNone   t       -> BNone (rename f t)-        --instance Rename Bound where- rename f uu-  = case uu of-        UIx   i k       -> UIx   i     (rename f k)-        UName n k       -> UName (f n) (rename f k)-        UPrim n k       -> UName (f n) (rename f k)---instance Rename TyCon where- rename f cc-  = case cc of-        TyConSort sc    -> TyConSort    sc-        TyConKind kc    -> TyConKind    kc-        TyConWitness tc -> TyConWitness tc-        TyConSpec tc    -> TyConSpec    tc-        TyConBound u    -> TyConBound $ rename f u-
ddc-core-simpl.cabal view
@@ -1,5 +1,5 @@ Name:           ddc-core-simpl-Version:        0.2.1.2+Version:        0.3.1.1 License:        MIT License-file:   LICENSE Author:         The Disciplined Disciple Compiler Strike Force@@ -10,27 +10,56 @@ Category:       Compilers/Interpreters Homepage:       http://disciple.ouroborus.net Bug-reports:    disciple@ouroborus.net-Synopsis:       Disciple Core language simplifying code transformations.-Description:    Disciple Core language simplifying code transformations.+Synopsis:       Disciplined Disciple Compiler code transformations.+Description:    Disciplined Disciple Compiler code transformations.  Library   Build-Depends:          base            == 4.6.*,+        deepseq         == 1.3.*,         containers      == 0.5.*,-        array           >= 0.3   && < 0.5,+        array           == 0.4.*,         transformers    == 0.3.*,         mtl             == 2.1.*,-        ddc-base        == 0.2.1.*,-        ddc-core        == 0.2.1.*+        ddc-base        == 0.3.1.*,+        ddc-core        == 0.3.1.*    Exposed-modules:+        DDC.Core.Analysis.Arity+        DDC.Core.Analysis.Usage+        DDC.Core.Simplifier.Recipe+        DDC.Core.Simplifier.Parser+        DDC.Core.Transform.Rewrite.Disjoint+        DDC.Core.Transform.Rewrite.Env+        DDC.Core.Transform.Rewrite.Match+        DDC.Core.Transform.Rewrite.Parser+        DDC.Core.Transform.Rewrite.Rule         DDC.Core.Transform.AnonymizeX-        DDC.Core.Transform.ANormal         DDC.Core.Transform.Beta+        DDC.Core.Transform.Bubble+        DDC.Core.Transform.Prune+        DDC.Core.Transform.Elaborate+        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.Simplifier++        DDC.Type.Transform.Alpha         DDC.Type.Transform.AnonymizeT-        DDC.Type.Transform.Rename-        ++  Other-modules:+        DDC.Core.Simplifier.Apply+        DDC.Core.Simplifier.Lexer+        DDC.Core.Simplifier.Base++        DDC.Core.Transform.Inline.Templates+        DDC.Core.Transform.Rewrite.Error++   GHC-options:         -Wall         -fno-warn-orphans@@ -38,10 +67,18 @@         -fno-warn-unused-do-bind    Extensions:+        BangPatterns         NoMonomorphismRestriction+        ParallelListComp         ExplicitForAll         KindSignatures         PatternGuards         MultiParamTypeClasses         FlexibleContexts         FlexibleInstances+        RankNTypes+        ExistentialQuantification+        DeriveDataTypeable+        ScopedTypeVariables++