packages feed

hermit 0.1.2.0 → 0.1.4.0

raw patch · 68 files changed

+2241/−1917 lines, 68 filesdep +directorydep ~kurePVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: directory

Dependency ranges changed: kure

API changes (from Hackage documentation)

- Language.HERMIT.Context: data Context
- Language.HERMIT.Context: initContext :: ModGuts -> Context
- Language.HERMIT.Context: instance PathContext Context
- Language.HERMIT.Context: listBindings :: Context -> [Id]
- Language.HERMIT.CoreExtra: AltCore :: CoreAlt -> Core
- Language.HERMIT.CoreExtra: BindCore :: CoreBind -> Core
- Language.HERMIT.CoreExtra: Def :: Id -> CoreExpr -> CoreDef
- Language.HERMIT.CoreExtra: DefCore :: CoreDef -> Core
- Language.HERMIT.CoreExtra: ExprCore :: CoreExpr -> Core
- Language.HERMIT.CoreExtra: ModGutsCore :: ModGuts -> Core
- Language.HERMIT.CoreExtra: ProgramCore :: CoreProgram -> Core
- Language.HERMIT.CoreExtra: data Core
- Language.HERMIT.CoreExtra: data CoreDef
- Language.HERMIT.CoreExtra: defToRecBind :: [CoreDef] -> CoreBind
- Language.HERMIT.CoreExtra: type CoreTickish = Tickish Id
- Language.HERMIT.Kure: AltCore :: CoreAlt -> Core
- Language.HERMIT.Kure: BindCore :: CoreBind -> Core
- Language.HERMIT.Kure: Def :: Id -> CoreExpr -> CoreDef
- Language.HERMIT.Kure: DefCore :: CoreDef -> Core
- Language.HERMIT.Kure: ExprCore :: CoreExpr -> Core
- Language.HERMIT.Kure: ModGutsCore :: ModGuts -> Core
- Language.HERMIT.Kure: ProgramCore :: CoreProgram -> Core
- Language.HERMIT.Kure: consBindAllR :: RewriteH CoreBind -> RewriteH CoreProgram -> RewriteH CoreProgram
- Language.HERMIT.Kure: consBindAnyR :: RewriteH CoreBind -> RewriteH CoreProgram -> RewriteH CoreProgram
- Language.HERMIT.Kure: consBindOneR :: RewriteH CoreBind -> RewriteH CoreProgram -> RewriteH CoreProgram
- Language.HERMIT.Kure: consBindT :: TranslateH CoreBind a1 -> TranslateH CoreProgram a2 -> (a1 -> a2 -> b) -> TranslateH CoreProgram b
- Language.HERMIT.Kure: data Core
- Language.HERMIT.Kure: data CoreDef
- Language.HERMIT.Kure: data KureMonad a :: * -> *
- Language.HERMIT.Kure: fromKureMonad :: (String -> a) -> KureMonad a -> a
- Language.HERMIT.Kure: instance Injection CoreProgram Core
- Language.HERMIT.Kure: instance Node CoreProgram
- Language.HERMIT.Kure: instance Walker Context HermitM Core
- Language.HERMIT.Kure: instance Walker Context HermitM CoreAlt
- Language.HERMIT.Kure: instance Walker Context HermitM CoreBind
- Language.HERMIT.Kure: instance Walker Context HermitM CoreDef
- Language.HERMIT.Kure: instance Walker Context HermitM CoreExpr
- Language.HERMIT.Kure: instance Walker Context HermitM CoreProgram
- Language.HERMIT.Kure: instance Walker Context HermitM ModGuts
- Language.HERMIT.Kure: nilT :: b -> TranslateH [a] b
- Language.HERMIT.Kure: promoteProgramR :: RewriteH CoreProgram -> RewriteH Core
- Language.HERMIT.Kure: promoteProgramT :: TranslateH CoreProgram b -> TranslateH Core b
- Language.HERMIT.Kure: runKureMonad :: (a -> b) -> (String -> b) -> KureMonad a -> b
- Language.HERMIT.Monad: cloneIdH :: (String -> String) -> Id -> HermitM Id
- Language.HERMIT.Monad: newTypeVarH :: String -> Kind -> HermitM TyVar
- Language.HERMIT.Monad: newVarH :: String -> Type -> HermitM Id
- Language.HERMIT.Primitive.AlphaConversion: alphaAltId :: Maybe Name -> Id -> RewriteH CoreAlt
- Language.HERMIT.Primitive.AlphaConversion: alphaConsNonRec :: Maybe Name -> RewriteH CoreProgram
- Language.HERMIT.Primitive.AlphaConversion: alphaConsRec :: RewriteH CoreProgram
- Language.HERMIT.Primitive.AlphaConversion: alphaConsRecId :: Maybe Name -> Id -> RewriteH CoreProgram
- Language.HERMIT.Primitive.AlphaConversion: alphaConsRecOne :: Maybe Name -> RewriteH CoreProgram
- Language.HERMIT.Primitive.AlphaConversion: alphaLetNonRec :: Maybe Name -> RewriteH CoreExpr
- Language.HERMIT.Primitive.AlphaConversion: alphaLetRec :: RewriteH CoreExpr
- Language.HERMIT.Primitive.AlphaConversion: alphaLetRecId :: Maybe Name -> Id -> RewriteH CoreExpr
- Language.HERMIT.Primitive.AlphaConversion: alphaLetRecOne :: Maybe Name -> RewriteH CoreExpr
- Language.HERMIT.Primitive.AlphaConversion: freshNameGen :: (Maybe Name) -> [Id] -> (String -> String)
- Language.HERMIT.Primitive.AlphaConversion: ifShadowingR :: RewriteH CoreExpr
- Language.HERMIT.Primitive.AlphaConversion: inventNames :: [Id] -> String -> String
- Language.HERMIT.Primitive.AlphaConversion: renameIdR :: (Injection a Core, Generic a ~ Core) => Id -> Id -> RewriteH a
- Language.HERMIT.Primitive.AlphaConversion: replaceId :: Id -> Id -> (Id -> Id)
- Language.HERMIT.Primitive.AlphaConversion: shadowedNamesQuery :: TranslateH CoreExpr String
- Language.HERMIT.Primitive.AlphaConversion: shadowedNamesT :: TranslateH CoreExpr [String]
- Language.HERMIT.Primitive.AlphaConversion: visibleIds :: TranslateH CoreExpr [Id]
- Language.HERMIT.Primitive.AlphaConversion: wrongFormForAlpha :: String -> String
- Language.HERMIT.Primitive.GHC: addCoreBindAsRule :: String -> Name -> RewriteH ModGuts
- Language.HERMIT.Primitive.GHC: arityOf :: Context -> Id -> Int
- Language.HERMIT.Primitive.GHC: bindEqual :: CoreBind -> CoreBind -> Maybe Bool
- Language.HERMIT.Primitive.GHC: castElimination :: RewriteH CoreExpr
- Language.HERMIT.Primitive.GHC: compareValues :: Name -> Name -> TranslateH Core ()
- Language.HERMIT.Primitive.GHC: coreEqual :: Core -> Core -> Maybe Bool
- Language.HERMIT.Primitive.GHC: deShadowBindsR :: RewriteH CoreProgram
- Language.HERMIT.Primitive.GHC: flattenModule :: RewriteH ModGuts
- Language.HERMIT.Primitive.GHC: freeIdsQuery :: TranslateH CoreExpr String
- Language.HERMIT.Primitive.GHC: getHermitRules :: Generic a ~ Core => TranslateH a [(String, [CoreRule])]
- Language.HERMIT.Primitive.GHC: letSubstNR :: Int -> RewriteH Core
- Language.HERMIT.Primitive.GHC: makeRule :: String -> Id -> CoreExpr -> CoreRule
- Language.HERMIT.Primitive.GHC: mergeBinds :: RewriteH CoreProgram
- Language.HERMIT.Primitive.GHC: occurAnalyseExpr :: CoreExpr -> CoreExpr
- Language.HERMIT.Primitive.GHC: occurAnalyseExprR :: RewriteH CoreExpr
- Language.HERMIT.Primitive.GHC: rulesToEnv :: [CoreRule] -> Map String (RewriteH CoreExpr)
- Language.HERMIT.Primitive.GHC: rulesToRewriteH :: [CoreRule] -> RewriteH CoreExpr
- Language.HERMIT.Primitive.GHC: rules_help :: TranslateH Core String
- Language.HERMIT.Primitive.GHC: showVar :: DynFlags -> Var -> String
- Language.HERMIT.Primitive.GHC: substExprR :: Id -> CoreExpr -> RewriteH CoreExpr
- Language.HERMIT.Primitive.GHC: substTopBindR :: Id -> CoreExpr -> RewriteH CoreProgram
- Language.HERMIT.Primitive.Inline: configurableInline :: Bool -> Bool -> RewriteH CoreExpr
- Language.HERMIT.Primitive.Inline: ensureDepth :: Int -> TranslateH Core Bool
- Language.HERMIT.Primitive.Local: dce :: RewriteH CoreExpr
- Language.HERMIT.Primitive.Local: multiBetaReduce :: (Int -> Bool) -> RewriteH CoreExpr
- Language.HERMIT.Primitive.Local.Case: externals :: [External]
- Language.HERMIT.Primitive.Local.Case: letFloatCase :: RewriteH CoreExpr
- Language.HERMIT.Primitive.Local.Let: externals :: [External]
- Language.HERMIT.Primitive.New: abstract :: Name -> RewriteH CoreExpr
- Language.HERMIT.Primitive.New: coreConstructor :: Core -> String
- Language.HERMIT.Primitive.New: coreNode :: Core -> String
- Language.HERMIT.Primitive.New: exprTypeT :: TranslateH CoreExpr String
- Language.HERMIT.Primitive.New: findId :: (MonadUnique m, MonadIO m, MonadThings m, HasDynFlags m) => Context -> String -> m Id
- Language.HERMIT.Primitive.New: findIdMG :: (MonadUnique m, MonadIO m, MonadThings m, HasDynFlags m) => ModGuts -> String -> m Id
- Language.HERMIT.Primitive.New: fixIntro :: RewriteH CoreDef
- Language.HERMIT.Primitive.New: fixSpecialization :: RewriteH CoreExpr
- Language.HERMIT.Primitive.New: fixSpecialization' :: RewriteH CoreExpr
- Language.HERMIT.Primitive.New: info :: TranslateH Core String
- Language.HERMIT.Primitive.New: letPairR :: Name -> RewriteH CoreExpr
- Language.HERMIT.Primitive.New: showExprType :: DynFlags -> CoreExpr -> String
- Language.HERMIT.Primitive.New: showIdInfo :: DynFlags -> Id -> String
- Language.HERMIT.Primitive.Utils: appCount :: CoreExpr -> Int
+ Language.HERMIT.Context: boundVars :: HermitC -> [Var]
+ Language.HERMIT.Context: data HermitC
+ Language.HERMIT.Context: findBoundVars :: Name -> HermitC -> [Var]
+ Language.HERMIT.Context: initHermitC :: ModGuts -> HermitC
+ Language.HERMIT.Context: instance PathContext HermitC
+ Language.HERMIT.Core: AltCore :: CoreAlt -> Core
+ Language.HERMIT.Core: BindCore :: CoreBind -> Core
+ Language.HERMIT.Core: Def :: Id -> CoreExpr -> CoreDef
+ Language.HERMIT.Core: DefCore :: CoreDef -> Core
+ Language.HERMIT.Core: ExprCore :: CoreExpr -> Core
+ Language.HERMIT.Core: ModGutsCore :: ModGuts -> Core
+ Language.HERMIT.Core: ProgCons :: CoreBind -> CoreProg -> CoreProg
+ Language.HERMIT.Core: ProgCore :: CoreProg -> Core
+ Language.HERMIT.Core: ProgNil :: CoreProg
+ Language.HERMIT.Core: appCount :: CoreExpr -> Int
+ Language.HERMIT.Core: bindToIdExprs :: CoreBind -> [(Id, CoreExpr)]
+ Language.HERMIT.Core: bindsToProg :: [CoreBind] -> CoreProg
+ Language.HERMIT.Core: data Core
+ Language.HERMIT.Core: data CoreDef
+ Language.HERMIT.Core: data CoreProg
+ Language.HERMIT.Core: defToIdExpr :: CoreDef -> (Id, CoreExpr)
+ Language.HERMIT.Core: defsToRecBind :: [CoreDef] -> CoreBind
+ Language.HERMIT.Core: exprTypeOrKind :: CoreExpr -> Type
+ Language.HERMIT.Core: isType :: CoreExpr -> Bool
+ Language.HERMIT.Core: progToBinds :: CoreProg -> [CoreBind]
+ Language.HERMIT.Core: type CoreTickish = Tickish Id
+ Language.HERMIT.Core: typeExprToType :: CoreExpr -> Maybe Type
+ Language.HERMIT.Dictionary: type Dictionary = Map String [Dynamic]
+ Language.HERMIT.Kure: data KureM a :: * -> *
+ Language.HERMIT.Kure: fromKureM :: (String -> a) -> KureM a -> a
+ Language.HERMIT.Kure: instance Injection CoreProg Core
+ Language.HERMIT.Kure: instance Node CoreProg
+ Language.HERMIT.Kure: instance Walker HermitC HermitM Core
+ Language.HERMIT.Kure: instance Walker HermitC HermitM CoreAlt
+ Language.HERMIT.Kure: instance Walker HermitC HermitM CoreBind
+ Language.HERMIT.Kure: instance Walker HermitC HermitM CoreDef
+ Language.HERMIT.Kure: instance Walker HermitC HermitM CoreExpr
+ Language.HERMIT.Kure: instance Walker HermitC HermitM CoreProg
+ Language.HERMIT.Kure: instance Walker HermitC HermitM ModGuts
+ Language.HERMIT.Kure: progConsAllR :: RewriteH CoreBind -> RewriteH CoreProg -> RewriteH CoreProg
+ Language.HERMIT.Kure: progConsAnyR :: RewriteH CoreBind -> RewriteH CoreProg -> RewriteH CoreProg
+ Language.HERMIT.Kure: progConsOneR :: RewriteH CoreBind -> RewriteH CoreProg -> RewriteH CoreProg
+ Language.HERMIT.Kure: progConsT :: TranslateH CoreBind a1 -> TranslateH CoreProg a2 -> (a1 -> a2 -> b) -> TranslateH CoreProg b
+ Language.HERMIT.Kure: progNilT :: b -> TranslateH CoreProg b
+ Language.HERMIT.Kure: promoteProgR :: RewriteH CoreProg -> RewriteH Core
+ Language.HERMIT.Kure: promoteProgT :: TranslateH CoreProg b -> TranslateH Core b
+ Language.HERMIT.Kure: runKureM :: (a -> b) -> (String -> b) -> KureM a -> b
+ Language.HERMIT.Monad: cloneVarH :: (String -> String) -> Var -> HermitM Var
+ Language.HERMIT.Monad: newIdH :: String -> Type -> HermitM Id
+ Language.HERMIT.Monad: newTyVarH :: String -> Kind -> HermitM TyVar
+ Language.HERMIT.Plugin: instance Default Options
+ Language.HERMIT.Primitive.AlphaConversion: alphaAltIds :: [Id] -> RewriteH CoreAlt
+ Language.HERMIT.Primitive.AlphaConversion: alphaLetRecIds :: [Id] -> RewriteH CoreExpr
+ Language.HERMIT.Primitive.AlphaConversion: alphaLetVars :: [Var] -> RewriteH CoreExpr
+ Language.HERMIT.Primitive.AlphaConversion: freshNameGenAvoiding :: Maybe Name -> [Var] -> (String -> String)
+ Language.HERMIT.Primitive.AlphaConversion: replaceVarR :: (Injection a Core, Generic a ~ Core) => Var -> Var -> RewriteH a
+ Language.HERMIT.Primitive.AlphaConversion: visibleVarsT :: TranslateH CoreExpr [Var]
+ Language.HERMIT.Primitive.FixPoint: externals :: [External]
+ Language.HERMIT.Primitive.FixPoint: findFixId :: TranslateH a Id
+ Language.HERMIT.Primitive.FixPoint: fixIntro :: RewriteH CoreDef
+ Language.HERMIT.Primitive.FixPoint: fixLocation :: String
+ Language.HERMIT.Primitive.FixPoint: fixSpecialization :: RewriteH CoreExpr
+ Language.HERMIT.Primitive.FixPoint: fixSpecialization' :: RewriteH CoreExpr
+ Language.HERMIT.Primitive.FixPoint: guardIsFixId :: Id -> TranslateH a ()
+ Language.HERMIT.Primitive.FixPoint: monomorphicWorkerWrapperFac :: CoreExpr -> CoreExpr -> RewriteH CoreExpr
+ Language.HERMIT.Primitive.FixPoint: monomorphicWorkerWrapperSplit :: CoreExpr -> CoreExpr -> RewriteH CoreDef
+ Language.HERMIT.Primitive.FixPoint: workerWrapperFacTest :: Name -> Name -> RewriteH CoreExpr
+ Language.HERMIT.Primitive.FixPoint: workerWrapperSplitTest :: Name -> Name -> RewriteH CoreDef
+ Language.HERMIT.Primitive.GHC: altFreeVarsExclWildT :: TranslateH CoreAlt (Id -> [Var])
+ Language.HERMIT.Primitive.GHC: altFreeVarsT :: TranslateH CoreAlt [Var]
+ Language.HERMIT.Primitive.Local: abstract :: Name -> RewriteH CoreExpr
+ Language.HERMIT.Primitive.Local: flattenModule :: RewriteH ModGuts
+ Language.HERMIT.Primitive.Local: flattenProgramR :: RewriteH CoreProg
+ Language.HERMIT.Primitive.Local: flattenProgramT :: TranslateH CoreProg CoreBind
+ Language.HERMIT.Primitive.Local: nonrecToRec :: RewriteH CoreBind
+ Language.HERMIT.Primitive.Local.Case: caseExternals :: [External]
+ Language.HERMIT.Primitive.Local.Let: letElim :: RewriteH CoreExpr
+ Language.HERMIT.Primitive.Local.Let: letExternals :: [External]
+ Language.HERMIT.Primitive.Local.Let: letFloatCase :: RewriteH CoreExpr
+ Language.HERMIT.Primitive.Local.Let: letFloatLam :: RewriteH CoreExpr
+ Language.HERMIT.Primitive.New: collectLets :: CoreExpr -> ([(Var, CoreExpr)], CoreExpr)
- Language.HERMIT.Context: (@@) :: Context -> Int -> Context
+ Language.HERMIT.Context: (@@) :: HermitC -> Int -> HermitC
- Language.HERMIT.Context: addAltBindings :: [Id] -> Context -> Context
+ Language.HERMIT.Context: addAltBindings :: [Id] -> HermitC -> HermitC
- Language.HERMIT.Context: addBinding :: CoreBind -> Context -> Context
+ Language.HERMIT.Context: addBinding :: CoreBind -> HermitC -> HermitC
- Language.HERMIT.Context: addCaseBinding :: (Id, CoreExpr, CoreAlt) -> Context -> Context
+ Language.HERMIT.Context: addCaseBinding :: (Id, CoreExpr, CoreAlt) -> HermitC -> HermitC
- Language.HERMIT.Context: addLambdaBinding :: Id -> Context -> Context
+ Language.HERMIT.Context: addLambdaBinding :: Var -> HermitC -> HermitC
- Language.HERMIT.Context: boundIn :: Id -> Context -> Bool
+ Language.HERMIT.Context: boundIn :: Var -> HermitC -> Bool
- Language.HERMIT.Context: hermitBindings :: Context -> Map Id HermitBinding
+ Language.HERMIT.Context: hermitBindings :: HermitC -> Map Var HermitBinding
- Language.HERMIT.Context: hermitDepth :: Context -> Int
+ Language.HERMIT.Context: hermitDepth :: HermitC -> Int
- Language.HERMIT.Context: hermitModGuts :: Context -> ModGuts
+ Language.HERMIT.Context: hermitModGuts :: HermitC -> ModGuts
- Language.HERMIT.Context: hermitPath :: Context -> AbsolutePath
+ Language.HERMIT.Context: hermitPath :: HermitC -> AbsolutePath
- Language.HERMIT.Context: lookupHermitBinding :: Id -> Context -> Maybe HermitBinding
+ Language.HERMIT.Context: lookupHermitBinding :: Var -> HermitC -> Maybe HermitBinding
- Language.HERMIT.Dictionary: dictionary :: [External] -> Map String [Dynamic]
+ Language.HERMIT.Dictionary: dictionary :: [External] -> Dictionary
- Language.HERMIT.Kernel: applyK :: Kernel -> AST -> RewriteH Core -> HermitMEnv -> IO (KureMonad AST)
+ Language.HERMIT.Kernel: applyK :: Kernel -> AST -> RewriteH ModGuts -> HermitMEnv -> IO (KureM AST)
- Language.HERMIT.Kernel: queryK :: Kernel -> forall a. AST -> TranslateH Core a -> HermitMEnv -> IO (KureMonad a)
+ Language.HERMIT.Kernel: queryK :: Kernel -> forall a. AST -> TranslateH ModGuts a -> HermitMEnv -> IO (KureM a)
- Language.HERMIT.Kernel.Scoped: ScopedKernel :: (SAST -> IO ()) -> IO () -> (SAST -> RewriteH Core -> HermitMEnv -> IO (KureMonad SAST)) -> (forall a. SAST -> TranslateH Core a -> HermitMEnv -> IO (KureMonad a)) -> (SAST -> IO ()) -> IO [SAST] -> (SAST -> IO [Path]) -> (SAST -> (LocalPath -> LocalPath) -> HermitMEnv -> IO (KureMonad SAST)) -> (SAST -> IO SAST) -> (SAST -> IO SAST) -> ScopedKernel
+ Language.HERMIT.Kernel.Scoped: ScopedKernel :: (SAST -> IO ()) -> IO () -> (SAST -> RewriteH Core -> HermitMEnv -> IO (KureM SAST)) -> (forall a. SAST -> TranslateH Core a -> HermitMEnv -> IO (KureM a)) -> (SAST -> IO ()) -> IO [SAST] -> (SAST -> IO [Path]) -> (SAST -> (LocalPath -> LocalPath) -> HermitMEnv -> IO (KureM SAST)) -> (SAST -> IO SAST) -> (SAST -> IO SAST) -> ScopedKernel
- Language.HERMIT.Kernel.Scoped: applyS :: ScopedKernel -> SAST -> RewriteH Core -> HermitMEnv -> IO (KureMonad SAST)
+ Language.HERMIT.Kernel.Scoped: applyS :: ScopedKernel -> SAST -> RewriteH Core -> HermitMEnv -> IO (KureM SAST)
- Language.HERMIT.Kernel.Scoped: modPathS :: ScopedKernel -> SAST -> (LocalPath -> LocalPath) -> HermitMEnv -> IO (KureMonad SAST)
+ Language.HERMIT.Kernel.Scoped: modPathS :: ScopedKernel -> SAST -> (LocalPath -> LocalPath) -> HermitMEnv -> IO (KureM SAST)
- Language.HERMIT.Kernel.Scoped: queryS :: ScopedKernel -> forall a. SAST -> TranslateH Core a -> HermitMEnv -> IO (KureMonad a)
+ Language.HERMIT.Kernel.Scoped: queryS :: ScopedKernel -> forall a. SAST -> TranslateH Core a -> HermitMEnv -> IO (KureM a)
- Language.HERMIT.Kure: consNonRecAllR :: RewriteH CoreExpr -> RewriteH CoreProgram -> RewriteH CoreProgram
+ Language.HERMIT.Kure: consNonRecAllR :: RewriteH CoreExpr -> RewriteH CoreProg -> RewriteH CoreProg
- Language.HERMIT.Kure: consNonRecAnyR :: RewriteH CoreExpr -> RewriteH CoreProgram -> RewriteH CoreProgram
+ Language.HERMIT.Kure: consNonRecAnyR :: RewriteH CoreExpr -> RewriteH CoreProg -> RewriteH CoreProg
- Language.HERMIT.Kure: consNonRecOneR :: RewriteH CoreExpr -> RewriteH CoreProgram -> RewriteH CoreProgram
+ Language.HERMIT.Kure: consNonRecOneR :: RewriteH CoreExpr -> RewriteH CoreProg -> RewriteH CoreProg
- Language.HERMIT.Kure: consNonRecT :: TranslateH CoreExpr a1 -> TranslateH CoreProgram a2 -> (Id -> a1 -> a2 -> b) -> TranslateH CoreProgram b
+ Language.HERMIT.Kure: consNonRecT :: TranslateH CoreExpr a1 -> TranslateH CoreProg a2 -> (Var -> a1 -> a2 -> b) -> TranslateH CoreProg b
- Language.HERMIT.Kure: consRecAllR :: (Int -> RewriteH CoreDef) -> RewriteH CoreProgram -> RewriteH CoreProgram
+ Language.HERMIT.Kure: consRecAllR :: (Int -> RewriteH CoreDef) -> RewriteH CoreProg -> RewriteH CoreProg
- Language.HERMIT.Kure: consRecAnyR :: (Int -> RewriteH CoreDef) -> RewriteH CoreProgram -> RewriteH CoreProgram
+ Language.HERMIT.Kure: consRecAnyR :: (Int -> RewriteH CoreDef) -> RewriteH CoreProg -> RewriteH CoreProg
- Language.HERMIT.Kure: consRecDefAllR :: (Int -> RewriteH CoreExpr) -> RewriteH CoreProgram -> RewriteH CoreProgram
+ Language.HERMIT.Kure: consRecDefAllR :: (Int -> RewriteH CoreExpr) -> RewriteH CoreProg -> RewriteH CoreProg
- Language.HERMIT.Kure: consRecDefAnyR :: (Int -> RewriteH CoreExpr) -> RewriteH CoreProgram -> RewriteH CoreProgram
+ Language.HERMIT.Kure: consRecDefAnyR :: (Int -> RewriteH CoreExpr) -> RewriteH CoreProg -> RewriteH CoreProg
- Language.HERMIT.Kure: consRecDefOneR :: (Int -> RewriteH CoreExpr) -> RewriteH CoreProgram -> RewriteH CoreProgram
+ Language.HERMIT.Kure: consRecDefOneR :: (Int -> RewriteH CoreExpr) -> RewriteH CoreProg -> RewriteH CoreProg
- Language.HERMIT.Kure: consRecDefT :: (Int -> TranslateH CoreExpr a1) -> TranslateH CoreProgram a2 -> ([(Id, a1)] -> a2 -> b) -> TranslateH CoreProgram b
+ Language.HERMIT.Kure: consRecDefT :: (Int -> TranslateH CoreExpr a1) -> TranslateH CoreProg a2 -> ([(Id, a1)] -> a2 -> b) -> TranslateH CoreProg b
- Language.HERMIT.Kure: consRecOneR :: (Int -> RewriteH CoreDef) -> RewriteH CoreProgram -> RewriteH CoreProgram
+ Language.HERMIT.Kure: consRecOneR :: (Int -> RewriteH CoreDef) -> RewriteH CoreProg -> RewriteH CoreProg
- Language.HERMIT.Kure: consRecT :: (Int -> TranslateH CoreDef a1) -> TranslateH CoreProgram a2 -> ([a1] -> a2 -> b) -> TranslateH CoreProgram b
+ Language.HERMIT.Kure: consRecT :: (Int -> TranslateH CoreDef a1) -> TranslateH CoreProg a2 -> ([a1] -> a2 -> b) -> TranslateH CoreProg b
- Language.HERMIT.Kure: lamT :: TranslateH CoreExpr a -> (Id -> a -> b) -> TranslateH CoreExpr b
+ Language.HERMIT.Kure: lamT :: TranslateH CoreExpr a -> (Var -> a -> b) -> TranslateH CoreExpr b
- Language.HERMIT.Kure: letNonRecT :: TranslateH CoreExpr a1 -> TranslateH CoreExpr a2 -> (Id -> a1 -> a2 -> b) -> TranslateH CoreExpr b
+ Language.HERMIT.Kure: letNonRecT :: TranslateH CoreExpr a1 -> TranslateH CoreExpr a2 -> (Var -> a1 -> a2 -> b) -> TranslateH CoreExpr b
- Language.HERMIT.Kure: modGutsR :: RewriteH CoreProgram -> RewriteH ModGuts
+ Language.HERMIT.Kure: modGutsR :: RewriteH CoreProg -> RewriteH ModGuts
- Language.HERMIT.Kure: modGutsT :: TranslateH CoreProgram a -> (ModGuts -> a -> b) -> TranslateH ModGuts b
+ Language.HERMIT.Kure: modGutsT :: TranslateH CoreProg a -> (ModGuts -> a -> b) -> TranslateH ModGuts b
- Language.HERMIT.Kure: nonRecT :: TranslateH CoreExpr a -> (Id -> a -> b) -> TranslateH CoreBind b
+ Language.HERMIT.Kure: nonRecT :: TranslateH CoreExpr a -> (Var -> a -> b) -> TranslateH CoreBind b
- Language.HERMIT.Kure: type LensH a b = Lens Context HermitM a b
+ Language.HERMIT.Kure: type LensH a b = Lens HermitC HermitM a b
- Language.HERMIT.Kure: type RewriteH a = Rewrite Context HermitM a
+ Language.HERMIT.Kure: type RewriteH a = Rewrite HermitC HermitM a
- Language.HERMIT.Kure: type TranslateH a b = Translate Context HermitM a b
+ Language.HERMIT.Kure: type TranslateH a b = Translate HermitC HermitM a b
- Language.HERMIT.Kure: varT :: (Id -> b) -> TranslateH CoreExpr b
+ Language.HERMIT.Kure: varT :: (Var -> b) -> TranslateH CoreExpr b
- Language.HERMIT.Monad: DebugCore :: String -> Context -> Core -> DebugMessage
+ Language.HERMIT.Monad: DebugCore :: String -> HermitC -> Core -> DebugMessage
- Language.HERMIT.Primitive.AlphaConversion: alphaCons :: RewriteH CoreProgram
+ Language.HERMIT.Primitive.AlphaConversion: alphaCons :: RewriteH CoreProg
- Language.HERMIT.Primitive.AlphaConversion: alphaConsOne :: Maybe Name -> RewriteH CoreProgram
+ Language.HERMIT.Primitive.AlphaConversion: alphaConsOne :: Maybe Name -> RewriteH CoreProg
- Language.HERMIT.Primitive.AlphaConversion: freshNameGenT :: (Maybe Name) -> TranslateH CoreExpr (String -> String)
+ Language.HERMIT.Primitive.AlphaConversion: freshNameGenT :: Maybe Name -> TranslateH CoreExpr (String -> String)
- Language.HERMIT.Primitive.GHC: inScope :: Context -> Id -> Bool
+ Language.HERMIT.Primitive.GHC: inScope :: HermitC -> Id -> Bool
- Language.HERMIT.Primitive.GHC: showVars :: DynFlags -> [Var] -> String
+ Language.HERMIT.Primitive.GHC: showVars :: [Var] -> String
- Language.HERMIT.Primitive.GHC: substR :: Id -> CoreExpr -> RewriteH Core
+ Language.HERMIT.Primitive.GHC: substR :: Var -> CoreExpr -> RewriteH Core
- Language.HERMIT.Primitive.Local.Let: letFloatLetTop :: RewriteH CoreProgram
+ Language.HERMIT.Primitive.Local.Let: letFloatLetTop :: RewriteH CoreProg
- Language.HERMIT.Primitive.Unfold: getUnfolding :: Monad m => Bool -> Bool -> Id -> Context -> m (CoreExpr, Int)
+ Language.HERMIT.Primitive.Unfold: getUnfolding :: Monad m => Bool -> Bool -> Id -> HermitC -> m (CoreExpr, Int)

Files

driver/Main.hs view
@@ -9,44 +9,81 @@ import Paths_hermit as P import Data.Version +import Data.List (isPrefixOf)+import System.Directory (doesFileExist)+ hermit_version :: String hermit_version = "HERMIT v" ++ showVersion P.version +usage :: IO ()+usage = putStrLn $ unlines+        [hermit_version+        ,""+        ,"usage: hermit File.hs SCRIPTNAME"+        ,"       - OR -"+        ,"       hermit File.hs [HERMIT_ARGS] [+module_name [MOD_ARGS]]* [-- [ghc-args]]"+        ,""+        ,"examples: hermit Foo.hs Foo.hss"+        ,"          hermit Foo.hs -p6 +main:Main Foo.hss"+        ,"          hermit Foo.hs +main:Main Foo.hss resume"+        ,"          hermit Foo.hs +main:Main Foo.hss +other:Other Bar.hss"+        ,"          hermit Foo.hs -- -ddump-simpl -ddump-to-file"+        ,""+        ,"If a module name is not supplied, the module main:Main is assumed."+        ,""+        ,"HERMIT_ARGS"+        ,"  -pN        : where 0 <= N < 18 is the position in the pipeline in which HERMIT should run, 0 being at the beginning"+        ,""+        ,"MOD_ARGS"+        ,"  SCRIPTNAME : name of script file to run for this module"+        ,"  resume     : skip interactive mode and resume compilation after any scripts"+        ]+ main :: IO () main = do    args <- getArgs-   main2 args+   main1 args -main2 :: [String] -> IO ()-main2 [] = putStrLn $ unlines-        [hermit_version-        ,""-        ,"usage: hermit <ModuleName>.hs [args] [-- [ghc-args]]"-        ]-main2 (mod_nm:args) = case span (/= "--") args of-        (hermit_args,"--":ghc_args) -> main3 mod_nm hermit_args ghc_args-        (hermit_args,[])            -> main3 mod_nm hermit_args []+main1 :: [String] -> IO ()+main1 [] = usage+main1 [file_nm,script_nm] = do+    e <- doesFileExist script_nm+    if e then main4 file_nm [] [("main:Main", [script_nm])] [] else usage+main1 other = main2 other++main2 (file_nm:rest) = case span (/= "--") rest of+        (args,"--":ghc_args) -> main3 file_nm args ghc_args+        (args,[])            -> main3 file_nm args []         _ -> error "hermit internal error" -main3 mod_nm hermit_args ghc_args = do-        putStrLn $ "[starting " ++ hermit_version ++ " on " ++ mod_nm ++ "]"+main3 file_nm args ghc_args = main4 file_nm hermit_args (sepMods margs) ghc_args+    where (hermit_args, margs) = span (not . isPrefixOf "+") args++          sepMods :: [String] -> [(String, [String])]+          sepMods [] = []+          sepMods (('+':mod_nm):rest) = (mod_nm, mod_opts) : sepMods next+            where (mod_opts, next) = span (not . isPrefixOf "+") rest++main4 file_nm hermit_args []          ghc_args = main4 file_nm hermit_args [("main:Main", [])] ghc_args+main4 file_nm hermit_args module_args ghc_args = do+        putStrLn $ "[starting " ++ hermit_version ++ " on " ++ file_nm ++ "]"         let cmds =-                 [ mod_nm+                  [ file_nm                   , "-fforce-recomp"                   , "-O2"                   , "-dcore-lint"                   , "-fsimple-list-literals" --                  , "-v0"-	          , "-fplugin=HERMIT"-                  ] ++ [ "-fplugin-opt=HERMIT:main:Main:" ++ opt-                       | opt <- "" : hermit_args-                       ] ++ ghc_args+                  , "-fplugin=HERMIT"+                  ] +++                  [ "-fplugin-opt=HERMIT:" ++ opt+                  | opt <- hermit_args+                  ] +++                  [ "-fplugin-opt=HERMIT:" ++ m_nm ++ ":" ++ opt+                  | (m_nm, m_opts) <- module_args+                  , opt <- "" : m_opts+                  ] ++ ghc_args         putStrLn $ "% ghc " ++ unwords cmds         (_,_,_,r) <- createProcess $ proc "ghc" cmds         ex <- waitForProcess r         exitWith ex-----
+ examples/WWSplitTactic.hss view
@@ -0,0 +1,18 @@+{+fix-intro+consider lam+let-intro 'f+up+let-float-arg+1+apply-rule ww+simplify+{ 1; let-intro 'w }+let-float-arg+{ rhs-of 'w+  unfold 'fix ; alpha-let 'work+  simplify+}+let-subst+let-float-arg+}
examples/concatVanishes/ConcatVanishes.hss view
@@ -1,3 +1,4 @@+flatten-module consider let { consider def ; fix-intro } safe-let-subst@@ -12,4 +13,3 @@ bash any-call (unfold 'absH) try unshadow-
− examples/concatVanishes/Makefile
@@ -1,10 +0,0 @@-HERMIT = hermit--rev:-	$(HERMIT) Rev.hs Rev.hss--flatten:-	$(HERMIT) Flatten.hs Flatten.hss--qsort:-	$(HERMIT) QSort.hs QSort.hss
− examples/contents.txt
@@ -1,181 +0,0 @@-Concatenate Vanishes-====================--* A common script for all our Concatenate Vanishes examples.--* Completed.--* Interesting rewrites: push, innermost, unfold-rule--* It works for all three examples, but I doubt it would work for *any* concat vanishes example.--* Notes: unsafe uses of RULES with pre-conditions.---Evaluation-==========--* Evaluation of Hutton's Razor with exceptions.--* Convert to CPS to avoid repeated pattern matching.--* Completed.--* Interesting rewrites: abstract, fold---Fibonacci (Tupling)-===================--* Example of Tupling transformation.--* Completed and published--* Interesting rewrites: ww-split tactic, case-split(-inline), fold, remember (and fold/unfold remembered defns), let-tuple---Fibonacci (Stream Memoisation)-===================--* Example of Memoisation.--* Completed.--* Interesting rewrites: ww-split tactic---Flatten-=======--* Another concatenate-vanishes example, based on the Reverse example.--* Completed.--* Main rewrites: any-call---Hanoi-=====--* Another tupling transformation--* Completed.--* Interesting rewrites: ww-split tactic, case-split(-inline), fold, remember (and fold/unfold remembered defns), let-tuple--Map-===--* List unrolling.--* Completed.--* Main rewrites: simplify, any-call, unfold, case-split(-inline), remember.---Haskell 2012 Paper-==================--Fibonacci (Unrolling)------------------------* We unfold fib once to show how things operate overall.--* Main rewrites: any-bu, inline---Reverse----------* Our larger, low-level reverse example.--* Main rewrites: any-bu, unfold---Append---------* A demonstration of GHC RULES (no use of HERMIT).---IFL 2012 Paper-==================--Fibonacci (Tupling)----------------------* Example of Tupling transformation.--* Interesting rewrites: ww-split tactic, case-split(-inline), fold, remember (fold/unfold remembered defns), let-tuple---Last-====--* A classic simple example.--* Completed.---Mean-====--* Problem (and pen-and-paper calculation) provided by Jason Reich.--* A non-WW tupling example (maybe it can be cast as WW, I'm not sure).--* Completed.--* Interesting rewrites: abstract, remember, fold, let-intro, let-float, let-tuple----Nub-===--* A new (that is, unpublished) worker/wrapper example.--* There was a bug in Andy's original pen-and-paper derivation.--* A corrected version is in the files named "Revised".--* There has been no attempt to mechanise this revised derivation as yet.----Quicksort-=========--* Another concatenate-vanishes example.--* Completed.--* Main rewrites: any-call---Reverse-=======--* Higher-level script than in the Haskell 2012 paper.--* Completed.  Lower-level version has been published.--* Main rewrites: any-call---Talks-=====--* This directory is for the code that Neil intends to demo at Nottingham, IFL and Haskell.--* Don't mess with it without telling him!---To Do-=====--* Life - Can we translate to a stronger type?--* Kansas Lava example?--
+ examples/evaluation/Eval.hs view
@@ -0,0 +1,33 @@+module Main where++import Data.Function(fix)++data Expr = Val Int | Add Expr Expr | Throw | Catch Expr Expr++type Mint = Maybe Int++eval :: Expr -> Mint+eval (Val n)     = Just n+eval Throw       = Nothing+eval (Catch x y) = case eval x of+                       Nothing -> eval y+                       Just n  -> Just n+eval (Add x y)   = case eval x of+                       Nothing -> Nothing+                       Just m  -> case eval y of+                                    Nothing -> Nothing+                                    Just n  -> Just (m + n)++unwrap :: (Expr -> Mint) -> Expr -> (Int -> Mint) -> Mint -> Mint+unwrap g e s f = case g e of+                   Nothing -> f+                   Just n  -> s n++wrap :: (Expr -> (Int -> Mint) -> Mint -> Mint) -> Expr -> Mint+wrap h e = h e Just Nothing++{-# RULES "ww"     forall f. fix f = wrap (fix (unwrap . f . wrap)) #-}+{-# RULES "fusion" forall w. unwrap (wrap w) = w                    #-} -- has precondition++main :: IO ()+main = print (eval $ Val 5)
+ examples/evaluation/Eval.hss view
@@ -0,0 +1,19 @@+flatten-module+consider 'eval+load "../WWSplitTactic.hss"+{rhs-of 'work+   eta-expand 'e ; 0+   eta-expand 's ; 0+   eta-expand 'f ; 0+   unfold 'unwrap+   one-td (unfold 'f)+   bash+   {+     consider case ; 2 ; 0 ; abstract 'm+     consider case ; 2 ; 0 ; abstract 'n+   }+   any-bu (fold 'unwrap)+   any-bu (unfold-rule "fusion")+}+simplify+any-call (unfold 'wrap)
+ examples/factorial/Fac.hs view
@@ -0,0 +1,28 @@+{-# LANGUAGE MagicHash #-}++import Prelude hiding ((*),(-))+import GHC.Exts+import Data.Function(fix)++fac :: Int -> Int+fac 0 = 1+fac n = n * fac (n -1)++unwrap :: (Int -> Int) -> Int# -> Int#+unwrap h x = case h (I# x) of+               I# y -> y++wrap :: (Int# -> Int#) -> Int -> Int+wrap h (I# x) = I# (h x)++{-# RULES "ww"     forall f. fix f = wrap (fix (unwrap . f . wrap)) #-}++main :: IO ()+main = print (fac 10)+++(*) :: Int -> Int -> Int+(I# x) * (I# y) = I# (x *# y)++(-) :: Int -> Int -> Int+(I# x) - (I# y) = I# (x -# y)
+ examples/factorial/Fac.hss view
@@ -0,0 +1,20 @@+flatten-module+consider 'fac+load "../WWSplitTactic.hss"+{rhs-of 'work+  eta-expand 'x+  one-td (unfold 'unwrap)+  one-td (unfold 'f)+  one-td (unfold 'wrap)+  simplify+  {+    consider alt ; 0 ; case-float-arg+    consider alt ; 0 ; case-float-arg+  }+  one-td (unfold '-)+  one-td (unfold '*)+  simplify+  innermost case-float-case+}+simplify+{ consider let ; 1 ; eta-expand 'n ; any-call (unfold 'wrap) }
examples/fib-stream/Fib.hss view
@@ -1,14 +1,12 @@ flatten-module consider 'fib {-load "WWSplitTactic.hss"-{ 0 ; 1-  { 0-    any-call (unfold 'unwrap)+  load "../WWSplitTactic.hss"+  {rhs-of 'work+    unfold 'unwrap     any-call (unfold 'f)     { consider lam ; alpha-lam 'm }   }-}-innermost dead-code-elimination-any-call (unfold 'wrap)+  simplify+  any-call (unfold 'wrap) }
− examples/fib-stream/Makefile
@@ -1,10 +0,0 @@-HERMIT = perl ../../scripts/hermit.pl--fib:-	- $(HERMIT) Fib.hs Fib.hss resume--interactive:-	- $(HERMIT) Fib.hs Fib.hss--start:-	- $(HERMIT) Fib.hs
− examples/fib-stream/WWSplitTactic.hss
@@ -1,18 +0,0 @@-{-fix-intro-consider lam-let-intro 'f-up-let-float-arg-1-apply-rule ww-simplify-{ 1; let-intro 'w }-let-float-arg-{ rhs-of 'w-  unfold 'fix ; alpha-let 'work-  simplify-}-let-subst-let-float-arg-}
examples/fib-tuple/Fib.hss view
@@ -3,7 +3,7 @@  { -load "WWSplitTactic.hss"+load "../WWSplitTactic.hss" consider 'work ; remember origwork  -- work = unwrap (f (wrap work))@@ -22,13 +22,13 @@ -- work (n+1) = (f (wrap work) (n+1), f (wrap work) (n+2))  { 1 ; any-call (unfold 'f) }-{ 2 ; 0 ; 1 ; any-bu (unfold 'f) }+{ 2 ; 0 ; 1 ; any-call (unfold 'f) } simplify  -- work 0     = (0, 1) -- work (n+1) = (f (wrap work) (n+1), wrap work (n+1) + wrap work n) -2 ; 0 ; { 1 ; any-bu (unfold origwork) }+2 ; 0 ; { 1 ; any-call (unfold origwork) }  -- work 0     = (0, 1) -- work (n+1) = (f (wrap work) (n+1), wrap (unwrap (f (wrap work))) (n+1) + wrap (unwrap (f (wrap work))) n)@@ -59,5 +59,7 @@  } -innermost dead-code-elimination-{ 0 ; 1 ; any-call (unfold 'wrap) ; simplify }+innermost dead-let-elimination+any-call (unfold 'wrap)+simplify+
− examples/fib-tuple/Makefile
@@ -1,19 +0,0 @@-HERMIT = perl ../../scripts/hermit.pl--fib:-	- $(HERMIT) Fib.hs Fib.hss resume--interactive:-	- $(HERMIT) Fib.hs Fib.hss--start:-	- $(HERMIT) Fib.hs--test:-	- rm *.o *.hi Fib-	- ghc --make -O2 -o Fib -fforce-recomp Fib.hs-	- ./Fib > timing.txt-	- echo "===========================================" >> timing.txt-	- $(HERMIT) Fib.hs Fib.hss resume-	- ./Fib >> timing.txt-	- cat timing.txt
− examples/fib-tuple/WWSplitTactic.hss
@@ -1,51 +0,0 @@--- this is a (pretty general) ww tactic--- it transforms:------ rec g = body                                 (where body mentions g)------ into:------ g = let f = \g -> body                       (f is not recursive)---         rec work = unwrap (f (wrap work))---     in wrap work------ Note: inlining f (and bashing) would result in the same code---       achieved in the reverse example by applying the "ww" rule.------ The original function g is now a non-recursive wrapping of the worker.--- The worker makes use of the original body, and is recursive.------ So what have we gained doing it this way? Mainly, the noise of the--- original body is all tidily hidden in f, and we can focus on manipulating--- the wrap and unwrap functions, which is what we want to do.------ I've tested this on reverse, and it also works, so I think the--- next step is to formulate it as an actual rewrite, or otherwise--- bundle it up as a one-liner.------ TODO: this relies on a RULES pragmas:------  {-# RULES "ww" forall work . fix work = wrap (fix (unwrap . work . wrap)) #-}------ We either need to provide this somehow, or implement it as a rewrite.------ BEGIN: ww tactic-{-fix-intro-consider lam-let-intro 'f-up-let-float-arg-1-apply-rule ww-simplify-{ 1; let-intro 'w }-let-float-arg-{ rhs-of 'w-  unfold 'fix ; alpha-let 'work-  simplify-}-let-subst-let-float-arg-}--- END: ww tactic
− examples/fib-tuple/blog.txt
@@ -1,195 +0,0 @@-Using this file to keep track of progress/improvements coming out of this example.-Format: steps from Neil's worker/wrapper derivation with interspersed commentary.-Entire derivation is:---- Normal fib definition-fib :: Nat -> Nat-fib = body---- After WWSplit tactic-fib = wrap work--f :: (Nat -> Nat) -> Nat -> Nat-f = \fib -> body--wrap :: (Nat -> (Nat, Nat)) -> (Nat -> Nat)-unwrap :: (Nat -> Nat) -> (Nat -> (Nat, Nat))-work :: Nat -> (Nat, Nat)---- Derivation-work = unwrap (f (wrap work))- {- extensionality -}-work n = unwrap (f (wrap work)) n- {- unfold 'unwrap -}-work n = (f (wrap work) n, f (wrap work) (n+1))- {- case 'n -}-work 0     = (f (wrap work) 0, f (wrap work) 1)-work (n+1) = (f (wrap work) (n+1), f (wrap work) (n+2))- {- unfold 'f -}-work 0     = (0, 1)-work (n+1) = (f (wrap work) (n+1), wrap work (n+1) + wrap work n)- {- unfold 'work -}-work 0     = (0, 1)-work (n+1) = (f (wrap work) (n+1), wrap (unwrap (f (wrap work))) (n+1) + wrap (unwrap (f (wrap work))) n)- {- wrap . unwrap = id (precondition) -}-work 0     = (0, 1)-work (n+1) = (f (wrap work) (n+1), f (wrap work) (n+1) + f (wrap work) n)- {- let-intro x2, let-float-tuple -}-work 0     = (0, 1)-work (n+1) = let (x,y) = (f (wrap work) n, f (wrap work) (n+1)) in (y,x+y)- {- fold 'unwrap -}-work 0     = (0, 1)-work (n+1) = let (x,y) = unwrap (f (wrap work)) n in (y,x+y)- {- fold 'work -}-work 0     = (0, 1)-work (n+1) = let (x,y) = work n in (y,x+y)- {- QED -}--Discussion:--###############################################################################--work = unwrap (f (wrap work))--To get to this point required creation of the WWSplit tactic. This-is slightly more complicated than how we did the split in the reverse-example in the paper, because we want to keep f abstract for most-of this derivation (we selectively unfold it once). I was able to-create a tactic which I believe is entirely general, allowing one-to rewrite:--  letrec g = body--to:--  let g = (let f = \g -> body-           in (letrec work = unwrap (f (wrap work))-               in wrap work))--There are a couple todo's regarding this split. It relies on-two GHC RULES pragmas (ww, and inline-fix). These should probably-be written as rewrites. Doing so would probably allow the whole-tactic to be expressed as a rewrite, rather than a hermit script.--###############################################################################-- {- extensionality -}-work n = unwrap (f (wrap work)) n--This was done with "eta-expand 'n". Allowing core lint to run revealed-that eta-expand was not handling types correctly. This is fixed in commit-b49fcd2be2ff0592ab51a2e9b8a291dff48bbf4b by using splitFunTy_maybe, which-looks to be a really handy function. Must remember to exit Hermit with-resume, instead of abort, so core-lint runs.--###############################################################################-- {- unfold 'unwrap -}-work n = (f (wrap work) n, f (wrap work) (n+1))--At the moment we have to be careful to call unfold at the right place. Otherwise-we end up with extra redexes that must be dealt with.--###############################################################################-- {- case 'n -}-work 0     = (f (wrap work) 0, f (wrap work) 1)-work (n+1) = (f (wrap work) (n+1), f (wrap work) (n+2))--This step required two new capabilites:--  * A case-split rewrite that accepts the name of a free variable of an-    expression, finds all the data constructors belonging to the type,-    and builds a case statement, cloning the expression for each case alt.-    Getting the correct types of the pattern binders was tricky (or simple-    once I found the correct GHC functions to instantiate the constructor-    argument types).--  * Modify the Hermit context to store two possible values for variables-    that are case wildcard binders. These can refer to either the scrutinee-    (previous behavior), or the constructor application of the pattern. This-    is what allows the 'n above to be replaced by 0 and 1 when case splitting.-    It is important to store the AltCon and binders in the context, and only-    convert to a CoreExpr upon inlining, so that we can apply the constructor-    at the correct types.--There is a case-split-inline rewrite that combines these steps. This step-also required rewriting fib to work over:--  data Nat = Zero | Succ Nat--rather than Int, as the only Int constructor is the one which boxes Int#. We-probably need an case-literal rewrite, which accepts a literal and adds a-LitCon pattern. We could then go back to working on Int, and "case-literal 0"-rather than "case-split-inline 'n".--###############################################################################-- {- unfold 'f -}-work 0     = (0, 1)-work (n+1) = (f (wrap work) (n+1), wrap work (n+1) + wrap work n)--This step is done by calling unfold and repeatedly applying case-reduce on-three of the four tupled expressions. Should we add case-reduce to the-unfold cleanup step? Is there a more general cleanup rewrite we can build-that isn't as invasive as bash, but handles this stuff for us? I can imagine-some rewrites (like case-reduce) that we simply always want to run, as they-are effectively dead code elimination.--###############################################################################-- {- unfold 'work -}-work 0     = (0, 1)-work (n+1) = (f (wrap work) (n+1), wrap (unwrap (f (wrap work))) (n+1) + wrap (unwrap (f (wrap work))) n)--Our first run-in with equational reasoning issues. The problem is that we-want to unfold the definition of work we started with, not the one we currently-have. We are experimenting with two approaches to this:--    1. Create a GHC rule on the fly, stash it in the ModGuts, and then-       use unfold-rule. There are (currently) a few problems with this:--        * Only top-level bindings consistently work as rules. This can probably-          be solved by tracking down the occasional kernel panic. See my email-          on July 12th about the issue.--        * The add-rule rewrite works on ModGuts (by necessity), so you must be-          at the top level to use it. This is problematic when inside scoping-          braces, which prevent you from going up by design.--    2. Stash the definition in the HermitMonad (currently) or alongside the-       AST in the kernel. This is the method I'm currently using in the-       derivation. It appears to work quite well, and gives us control-       over how its unfolded. We can reject unfoldings that would result-       in variables that are not defined (because a binding is no longer-       present), for instance. TODO: prevent unintended capture!--The two rewrites added for #2 are:--  stashDef :: String -> TranslateH CoreDef () -- stashes the RHS of binding, with a name-  -- stash-defn-  stashApply :: String -> RewriteH CoreExpr   -- like inline, but looks up a stashed name-  -- stash-apply--###############################################################################-- {- wrap . unwrap = id (precondition) -}-work 0     = (0, 1)-work (n+1) = (f (wrap work) (n+1), f (wrap work) (n+1) + f (wrap work) n)--I'm currently using a GHC rule for this:--    {-# RULES precondition forall w . wrap (unwrap w) = w #-}--###############################################################################-- {- let-intro x2, let-float -}-work 0     = (0, 1)-work (n+1) = let (x,y) = (f (wrap work) n, f (wrap work) (n+1)) in (y,x+y)- {- fold 'unwrap -}-work 0     = (0, 1)-work (n+1) = let (x,y) = unwrap (f (wrap work)) n in (y,x+y)- {- fold 'work -}-work 0     = (0, 1)-work (n+1) = let (x,y) = work n in (y,x+y)- {- QED -}
+ examples/flatten/Flatten.hs view
@@ -0,0 +1,25 @@+module Main where++import HList+import Data.Function (fix)++data Tree a = Node (Tree a) (Tree a) | Leaf a++{-# INLINE unwrap #-}+unwrap :: (Tree a -> [a]) -> (Tree a -> H a)+unwrap f = repH . f++{-# INLINE wrap #-}+wrap :: (Tree a -> H a) -> (Tree a -> [a])+wrap g = absH . g++{-# RULES "ww" forall f . fix f = wrap (fix (unwrap . f . wrap)) #-}+{-# RULES "inline-fix" forall f . fix f = let w = f w in w #-}++-- flatten :: Tree a -> [a]+flatten (Leaf a)   = [a]+flatten (Node l r) = flatten l ++ flatten r++main :: IO ()+main = print (flatten (Node (Leaf 'h') (Leaf 'i')))+
+ examples/flatten/Flatten.hss view
@@ -0,0 +1,37 @@+flatten-module+consider 'flatten+{+  consider 'flatten+  fix-intro+  0+  unfold-rule "ww"+  any-call (unfold '.)+  any-call (unfold 'wrap)+  any-call (unfold 'unwrap)+  any-call (unfold '.)+  bash+  unshadow+  any-bu case-float-arg+  {+    consider case+    any-bu (apply-rule "repH ++")+    bash+    any-bu (unfold-rule "rep-abs-fusion")+    {+      2+      0+      unfold-rule "repH (:)"+      one-td (unfold-rule "repH []")+      unfold-rule "(.) id"+    }+  }+  {+    consider app+    unfold 'fix+    alpha-let 'work+  }+}+bash+try unshadow+one-td (unfold 'absH)+
+ examples/flatten/HList.hs view
@@ -0,0 +1,39 @@+module HList+       ( H+       , repH+       , absH+       ) where++type H a = [a] -> [a]++{-# INLINE repH #-}+repH :: [a] -> H a+repH xs = (xs ++)++{-# INLINE absH #-}+absH :: H a -> [a]+absH f = f []++-- These two we may get for free via INLINE+{-# RULES "repH" forall xs	 . repH xs = (xs ++) #-}+{-# RULES "absH" forall f 	 . absH f = f []     #-}++-- The "Algebra" for repH+{-# RULES "repH ++" forall xs ys   . repH (xs ++ ys) = repH xs . repH ys #-}+{-# RULES "repH []" 	             repH [] = id  	       	         #-}+{-# RULES "repH (:)" forall x xs   . repH (x:xs) = ((:) x) . repH xs     #-}++-- Should be in the "List" module+{-# RULES "(:) ++" forall x xs ys . (x:xs) ++ ys = x : (xs ++ ys) #-}+{-# RULES "[] ++"  forall xs      . [] ++ xs     = xs #-}++-- Should be somewhere else+{-# RULES "(.) id" forall f .    f . id = f #-}++-- has preconditon+{-# RULES "rep-abs-fusion" forall h . repH (absH h) = h #-}+++++
examples/hanoi/Hanoi.hss view
@@ -2,7 +2,7 @@  -- do the w/w split consider 'hanoi-{ load "../fib-tuple/WWSplitTactic.hss" }+{ load "../WWSplitTactic.hss" }  { consider 'work   remember origwork@@ -56,4 +56,4 @@     }   } }-innermost dead-code-elimination+innermost dead-let-elimination
− examples/hanoi/Makefile
@@ -1,13 +0,0 @@-hanoi:-	- hermit Hanoi.hs Hanoi.hss resume--interactive:-	- hermit Hanoi.hs Hanoi.hss--test:-	- rm Hanoi *.o *.hi-	- ghc --make Hanoi.hs -O2 -o Hanoi-	- ./Hanoi-	- rm Hanoi *.o *.hi-	- hermit Hanoi.hs Hanoi.hss resume-	- ./Hanoi
+ examples/last/Last.hs view
@@ -0,0 +1,21 @@+module Main where++import Data.Function(fix)+import Prelude hiding (last)++unwrap         :: ([a] -> a) -> a -> [a] -> a+unwrap f a as  = f (a:as)++wrap           :: (a -> [a] -> a) -> [a] -> a+wrap f []      = error "wrap _ []"+wrap f (a:as)  = f a as++{-# RULES "ww" forall f . fix f = wrap (fix (unwrap . f . wrap)) #-}++-- last :: [a] -> a+last []        = error "last []"+last [a]       = a+last (_:a:as)  = last (a:as)++main :: IO ()+main = print (last "hello")
+ examples/last/Last.hss view
@@ -0,0 +1,20 @@+flatten-module+consider 'last+{consider 'last+  load "../WWSplitTactic.hss"+  {rhs-of 'work+     eta-expand 'b+     0+     eta-expand 'bs+     0+     unfold 'unwrap+     unfold 'f+     case-reduce+     consider app+     unfold 'wrap+     case-reduce+  }+}+simplify+any-call (unfold 'wrap)+
− examples/map/Makefile
@@ -1,10 +0,0 @@-HERMIT = perl ../../scripts/hermit.pl--last:-	- $(HERMIT) Map.hs Map.hss resume--interactive:-	- $(HERMIT) Map.hs Map.hss--start:-	- $(HERMIT) Map.hs
− examples/map/Map.hs
@@ -1,53 +0,0 @@-module Main where--import Data.Function(fix)-import Prelude hiding (abs, map)--data List2 a = Cons2 a a (List2 a)-             | Singleton a-             | Nil--rep :: [a] -> List2 a-rep []       = Nil-rep [x]      = Singleton x-rep (x:y:xs) = Cons2 x y (rep xs)--abs :: List2 a -> [a]-abs Nil            = []-abs (Singleton x)  = [x]-abs (Cons2 x y xs) = x : y : abs xs--unwrap :: ([a] -> [b]) -> (List2 a -> List2 b)-unwrap f = rep . f . abs--wrap :: (List2 a -> List2 b) -> ([a] -> [b])-wrap f = abs . f . rep---- needed for WWSplitTactic.hss-{-# RULES "ww" forall f . fix f = wrap (fix (unwrap . f . wrap)) #-}-{-# RULES "inline-fix" forall f . fix f = let work = f work in work #-}-{-# RULES "precondition1" forall xs . abs (rep xs) = xs #-}-{-# RULES "precondition2" forall xs . rep (abs xs) = xs #-}---- can apply "ww" rule to this-mapPlus1Int :: [Int] -> [Int]-mapPlus1Int []     = []-mapPlus1Int (x:xs) = (x+1) : mapPlus1Int xs--{- can't apply "ww" rule to either of these... is it because of the forall type?-unwrap :: ((a -> b) -> [a] -> [b]) -> ((a -> b) -> [a] -> List2 b)-unwrap g f = rep . g f--wrap :: ((a -> b) -> [a] -> List2 b) -> ((a -> b) -> [a] -> [b])-wrap g f = abs . g f--}-mapPlus1 :: Num a => [a] -> [a]-mapPlus1 []     = []-mapPlus1 (x:xs) = (x+1) : mapPlus1 xs--map :: (a -> b) -> [a] -> [b]-map _ []     = []-map f (x:xs) = f x : map f xs--main :: IO ()-main = print (map (+1) [1..10::Int])
− examples/map/Map.hss
@@ -1,47 +0,0 @@-flatten-module-consider 'mapPlus1Int-{load "../fib-tuple/WWSplitTactic.hss"-  consider 'work--  remember origwork-  0-  one-td (unfold 'unwrap)-  any-call (unfold '.)-  innermost (beta-reduce <+ safe-let-subst)-  0-  case-split-inline 'x-  { 3 -- Nil case-    any-call (unfold 'abs)-    any-call (unfold 'f)-    any-call (unfold 'rep)-    simplify-  }-  { 2 -- Singleton case-    any-call (unfold 'abs)-    any-call (unfold 'f)-    any-call (unfold 'wrap)-    any-call (unfold 'rep)-    -- here we make use of the already solved Nil case-    any-call (unfold 'work)-    simplify-    any-call (unfold 'abs)-    simplify-  }-  { 1 -- Cons2 case-    any-call (unfold 'abs)-    any-call (unfold 'f)-    any-call (unfold 'wrap)-    simplify-    any-bu (unfold origwork)-    any-call (unfold 'unwrap)-    simplify-    innermost (unfold-rule precondition1)-    any-call (unfold 'f)-    innermost case-reduce-    any-call (unfold 'rep)-    innermost case-reduce-    any-call (unfold 'wrap)-    simplify-    innermost (unfold-rule precondition2)-  }-}
+ examples/mean/Mean.hs view
@@ -0,0 +1,20 @@+import Prelude hiding (sum, length)++-- so we can let-tuple+import Data.Tuple+import GHC.Tuple++{-# NOINLINE mean #-}+mean :: [Int] -> Int+mean xs = sum xs `div` length xs++sum :: [Int] -> Int+sum []     = 0+sum (x:xs) = x + sum xs++length :: [Int] -> Int+length []     = 0+length (x:xs) = 1 + length xs++main :: IO ()+main = print $ mean [1..10]
+ examples/mean/Mean.hss view
@@ -0,0 +1,24 @@+{rhs-of 'mean ; 0+  { 1 ; let-intro 'l }+  { 0 ; 1 ; let-intro 's }+  innermost let-float+  let-tuple 'sl+  { 0 ; abstract 'xs ; 0 ; let-intro 'sumlength }+}+innermost let-float+consider 'sumlength+nonrec-to-rec           -- since we intend sumlength to be a recursive function+0+remember sumlen+{ 0 ; 0+  case-split-inline 'xs+  any-call (unfold 'sum)+  any-call (unfold 'length)+  simplify+  2 ; 0+  { 1 ; 1 ; let-intro 'l }+  { 0 ; 1 ; 1 ; let-intro 's }+  innermost let-float+  let-tuple 'sl+  { 0 ; fold sumlen }+}
+ examples/qsort/HList.hs view
@@ -0,0 +1,39 @@+module HList+       ( H+       , repH+       , absH+       ) where++type H a = [a] -> [a]++{-# INLINE repH #-}+repH :: [a] -> H a+repH xs = (xs ++)++{-# INLINE absH #-}+absH :: H a -> [a]+absH f = f []++-- These two we may get for free via INLINE+{-# RULES "repH" forall xs	 . repH xs = (xs ++) #-}+{-# RULES "absH" forall f 	 . absH f = f []     #-}++-- The "Algebra" for repH+{-# RULES "repH ++" forall xs ys   . repH (xs ++ ys) = repH xs . repH ys #-}+{-# RULES "repH []" 	             repH [] = id  	       	         #-}+{-# RULES "repH (:)" forall x xs   . repH (x:xs) = ((:) x) . repH xs     #-}++-- Should be in the "List" module+{-# RULES "(:) ++" forall x xs ys . (x:xs) ++ ys = x : (xs ++ ys) #-}+{-# RULES "[] ++"  forall xs      . [] ++ xs     = xs #-}++-- Should be somewhere else+{-# RULES "(.) id" forall f .    f . id = f #-}++-- has preconditon+{-# RULES "rep-abs-fusion" forall h . repH (absH h) = h #-}+++++
+ examples/qsort/QSort.hs view
@@ -0,0 +1,28 @@+module Main where++import HList+import Data.Function (fix)+import Data.List++data Tree a = Node (Tree a) (Tree a) | Leaf a++{-# INLINE unwrap #-}+unwrap :: ([a] -> [a]) -> ([a] -> H a)+unwrap f = repH . f++{-# INLINE wrap #-}+wrap :: ([a] -> H a) -> ([a] -> [a])+wrap g = absH . g++{-# RULES "ww" forall f . fix f = wrap (fix (unwrap . f . wrap)) #-}+{-# RULES "inline-fix" forall f . fix f = let w = f w in w #-}++-- qsort :: Ord a => [a] -> [a]+qsort []     = []+qsort (a:as) = qsort bs ++ [a] ++ qsort cs+               where+                  (bs , cs) = partition (< a) as++main :: IO ()+main = print (qsort [8,3,5,7,2,9,4,6,3,2])+
+ examples/qsort/QSort.hss view
@@ -0,0 +1,36 @@+flatten-module+consider 'qsort+{+  consider 'qsort+  fix-intro+  0+  unfold-rule "ww"+  any-call (unfold '.)+  any-call (unfold 'wrap)+  any-call (unfold 'unwrap)+  any-call (unfold '.)+  bash+  any-td case-float-arg+  bash+  {+    consider case+    any-td (unfold-rule "repH ++")+    any-td (unfold-rule "rep-abs-fusion")+    any-td (unfold-rule "repH (:)")+    any-td (unfold-rule "repH []")+    any-call (unfold '.)+    bash+    { consider let+      repeat let-subst -- maybe if we folded the (.) then safe-let-subst would fire and this would be unneccassary+    }+    any-td (unfold-rule "(.) id")+  }+}+{+  consider app+  unfold 'fix+  alpha-let 'work+}+bash+one-td (unfold 'absH)+
− examples/reverse/Makefile
@@ -1,14 +0,0 @@-HERMIT = perl ../../scripts/hermit.pl-MODULE=Reverse--test-example:-	- $(HERMIT) $(MODULE).hs resume-	./$(MODULE)--	- $(HERMIT) $(MODULE).hs $(MODULE).hss resume-	./$(MODULE)--interactive-example:-	- $(HERMIT) Reverse.hs--
+ examples/reverse/ReverseWW.hss view
@@ -0,0 +1,29 @@+flatten-module+consider 'rev+{consider 'rev+  load "../WWSplitTactic.hss"+  {rhs-of 'work+     any-call (unfold 'wrap)+     any-call (unfold 'f)+     any-call (unfold 'unwrap)+     any-call (unfold '.)+     simplify+     alpha-lam 'ys+     {0+       eta-expand 'acc+       innermost case-float+       one-td (unfold-rule "repH []")+       one-td (unfold 'id)+       one-td (unfold-rule "repH ++")+       one-td (unfold-rule "rep-abs-fusion")+       one-td (unfold 'repH)+       any-call (unfold '.)+       any-call (unfold-rule "(:) ++")+       any-call (unfold-rule "[] ++")+     }+  }+}+any-call (unfold 'wrap)+any-call (unfold '.)+any-call (unfold 'absH)+simplify
hermit.cabal view
@@ -1,5 +1,5 @@ Name:                hermit-Version:             0.1.2.0+Version:             0.1.4.0 Synopsis:            Haskell Equational Reasoning Model-to-Implementation Tunnel Description:   HERMIT uses Haskell to express semi-formal models,@@ -17,7 +17,7 @@   .     * log command prints linearly, even if command history is a tree.   .-    * The fold rewrite can only fold syntactically equivalent (up to+    * The fold rewrite can only fold syntactically alpha-equivalent (up to       parameters of the function you are folding) expressions.   .     * RULES have issues with forall types.@@ -38,12 +38,12 @@   .   @    $ hermit Reverse.hs Reverse.hss resume-   [starting HERMIT v0.1.2.0 on Reverse.hs]+   [starting HERMIT v0.1.4.0 on Reverse.hs]    % ghc Reverse.hs -fforce-recomp -O2 -dcore-lint -fsimple-list-literals -fplugin=HERMIT -fplugin-opt=HERMIT:main:Main: -fplugin-opt=HERMIT:main:Main:resume    [1 of 2] Compiling HList            ( HList.hs, HList.o )    Loading package ghc-prim ... linking ... done.    ...-   Loading package hermit-0.1.2.0 ... linking ... done.+   Loading package hermit-0.1.4.0 ... linking ... done.    [2 of 2] Compiling Main             ( Reverse.hs, Reverse.o )    Linking Reverse ...    $ ./Reverse@@ -54,12 +54,12 @@   .   @    $ hermit Reverse.hs-   [starting HERMIT v0.1.2.0 on Reverse.hs]+   [starting HERMIT v0.1.4.0 on Reverse.hs]    % ghc Reverse.hs -fforce-recomp -O2 -dcore-lint -fsimple-list-literals -fplugin=HERMIT -fplugin-opt=HERMIT:main:Main:    [1 of 2] Compiling HList            ( HList.hs, HList.o )    Loading package ghc-prim ... linking ... done.    ...-   Loading package hermit-0.1.2.0 ... linking ... done.+   Loading package hermit-0.1.4.0 ... linking ... done.    [2 of 2] Compiling Main             ( Reverse.hs, Reverse.o )    module main:Main where    \ \ rev ∷ ∀ a . [] a -> [] a@@ -87,40 +87,44 @@ Maintainer:          Andy Gill <andygill@ku.edu> Stability:           pre-alpha build-type:          Simple-Cabal-Version:       >= 1.10+Cabal-Version:       >= 1.14  extra-source-files:+    examples/WWSplitTactic.hss     examples/concatVanishes/ConcatVanishes.hss     examples/concatVanishes/Flatten.hs     examples/concatVanishes/Flatten.hss     examples/concatVanishes/HList.hs-    examples/concatVanishes/Makefile     examples/concatVanishes/QSort.hs     examples/concatVanishes/QSort.hss     examples/concatVanishes/Rev.hs     examples/concatVanishes/Rev.hss-    examples/contents.txt+    examples/evaluation/Eval.hs+    examples/evaluation/Eval.hss+    examples/factorial/Fac.hs+    examples/factorial/Fac.hss     examples/fib-stream/Fib.hs     examples/fib-stream/Fib.hss-    examples/fib-stream/Makefile     examples/fib-stream/Nat.hs     examples/fib-stream/Stream.hs-    examples/fib-stream/WWSplitTactic.hss     examples/fib-tuple/Fib.hs     examples/fib-tuple/Fib.hss-    examples/fib-tuple/Makefile-    examples/fib-tuple/WWSplitTactic.hss-    examples/fib-tuple/blog.txt+    examples/flatten/HList.hs+    examples/flatten/Flatten.hs+    examples/flatten/Flatten.hss     examples/hanoi/Hanoi.hs     examples/hanoi/Hanoi.hss-    examples/hanoi/Makefile-    examples/map/Map.hs-    examples/map/Map.hss-    examples/map/Makefile+    examples/last/Last.hs+    examples/last/Last.hss+    examples/mean/Mean.hs+    examples/mean/Mean.hss+    examples/qsort/HList.hs+    examples/qsort/QSort.hs+    examples/qsort/QSort.hss     examples/reverse/HList.hs-    examples/reverse/Makefile     examples/reverse/Reverse.hs     examples/reverse/Reverse.hss+    examples/reverse/ReverseWW.hss  Library   ghc-options: -Wall -fno-warn-orphans@@ -131,7 +135,7 @@                  data-default >= 0.5.0,                  ghc == 7.6.*,                  haskeline >= 0.7.0.3,-                 kure >= 2.4.2,+                 kure >= 2.4.10,                  marked-pretty >= 0.1,                  mtl >= 2.1.2,                  stm >= 2.4,@@ -144,7 +148,7 @@        HERMIT         Language.HERMIT.Context-       Language.HERMIT.CoreExtra+       Language.HERMIT.Core        Language.HERMIT.Dictionary        Language.HERMIT.Expr        Language.HERMIT.External@@ -156,7 +160,9 @@         Language.HERMIT.Plugin +       Language.HERMIT.Primitive.AlphaConversion        Language.HERMIT.Primitive.Debug+       Language.HERMIT.Primitive.FixPoint        Language.HERMIT.Primitive.Fold        Language.HERMIT.Primitive.GHC        Language.HERMIT.Primitive.Inline@@ -166,9 +172,7 @@        Language.HERMIT.Primitive.Local.Case        Language.HERMIT.Primitive.Navigation        Language.HERMIT.Primitive.New-       Language.HERMIT.Primitive.AlphaConversion        Language.HERMIT.Primitive.Unfold-       Language.HERMIT.Primitive.Utils         Language.HERMIT.PrettyPrinter        Language.HERMIT.PrettyPrinter.AST@@ -187,6 +191,7 @@  Executable hermit     Build-Depends: base >= 4 && < 5,+                   directory >= 1.2.0.0,                    process      default-language: Haskell2010
src/Language/HERMIT/Context.hs view
@@ -1,31 +1,36 @@ {-# LANGUAGE InstanceSigs #-}  module Language.HERMIT.Context-       (-         -- * HERMIT Bindings-         HermitBinding(..)-       , hermitBindingDepth-         -- * The HERMIT Context-       , Context-       , initContext+       ( -- * The HERMIT Context+         HermitC+       , initHermitC+         -- ** Adding to the Context        , (@@)        , addAltBindings        , addBinding        , addCaseBinding        , addLambdaBinding+         -- ** Reading from the Context        , hermitBindings        , hermitDepth        , hermitPath        , hermitModGuts        , lookupHermitBinding-       , listBindings+       , boundVars        , boundIn+       , findBoundVars+         -- ** Bindings+       , HermitBinding(..)+       , hermitBindingDepth ) where  import Prelude hiding (lookup) import GhcPlugins hiding (empty)-import Data.Map hiding (map, foldr)+import Data.Map hiding (map, foldr, filter)+import qualified Language.Haskell.TH as TH +import Language.HERMIT.GHC+ import Language.KURE  ------------------------------------------------------------------------@@ -35,8 +40,8 @@         = BIND Int Bool CoreExpr  -- ^ Binding depth, whether it is recursive, and the bound value                                   --   (which cannot be inlined without checking for scoping issues).         | LAM Int                 -- ^ For a lambda binding you only know the depth.-        | CASE Int CoreExpr (AltCon,[Id]) -- ^ For case wildcard binders. First expr points to scrutinee,-                                          --   second to AltCon (which can be converted to Constructor or Literal).+        | CASE Int CoreExpr (AltCon,[Id]) -- ^ For case wildcard binders. We store both the scrutinised expression,+                                          --   and the case alternative 'AltCon' (which can be converted to Constructor or Literal) and identifiers.  -- | Get the depth of a binding. hermitBindingDepth :: HermitBinding -> Int@@ -49,8 +54,8 @@ -- | The HERMIT context, containing all bindings in scope and the current location in the AST. --   The bindings here are lazy by choice, so that we can avoid the cost --   of building the context if we never use it.-data Context = Context-        { hermitBindings :: Map Id HermitBinding    -- ^ All (important) bindings in scope.+data HermitC = HermitC+        { hermitBindings :: Map Var HermitBinding   -- ^ All (important) bindings in scope.         , hermitDepth    :: Int                     -- ^ The depth of the bindings.         , hermitPath     :: AbsolutePath            -- ^ The 'AbsolutePath' to the current node from the root.         , hermitModGuts  :: ModGuts                 -- ^ The 'ModGuts' of the current module.@@ -59,80 +64,75 @@ ------------------------------------------------------------------------  -- | The HERMIT context stores an 'AbsolutePath' to the current node in the tree.-instance PathContext Context where-  contextPath :: Context -> AbsolutePath+instance PathContext HermitC where+  contextPath :: HermitC -> AbsolutePath   contextPath = hermitPath --- | Create the initial HERMIT 'Context' by providing a 'ModGuts'.-initContext :: ModGuts -> Context-initContext modGuts = Context empty 0 rootAbsPath modGuts+-- | Create the initial HERMIT 'HermitC' by providing a 'ModGuts'.+initHermitC :: ModGuts -> HermitC+initHermitC modGuts = HermitC empty 0 rootAbsPath modGuts  -- | Update the context by extending the stored 'AbsolutePath' to a child.-(@@) :: Context -> Int -> Context-(@@) env n = env { hermitPath = extendAbsPath n (hermitPath env) }+(@@) :: HermitC -> Int -> HermitC+(@@) c v = c { hermitPath = extendAbsPath v (hermitPath c) } --- | Add all bindings in a binding group to the 'Context'.-addBinding :: CoreBind -> Context -> Context-addBinding (NonRec n e) env-        = env { hermitBindings = insert n (BIND next_depth False e) (hermitBindings env)-              , hermitDepth    = next_depth-              }-  where-        next_depth = succ (hermitDepth env)-addBinding (Rec bds) env-        = env { hermitBindings = bds_env `union` hermitBindings env-              , hermitDepth    = next_depth-              }-  where-        next_depth = succ (hermitDepth env)-        -- notice how all recursive binding in a binding group are at the same depth.-        bds_env    = fromList-                   [ (b,BIND next_depth True e)-                   | (b,e) <- bds-                   ]+------------------------------------------------------------------------ +-- | Add all bindings in a binding group to a context.+addBinding :: CoreBind -> HermitC -> HermitC+addBinding corebind c = let nextDepth = succ (hermitDepth c)+                            hbds      = hermitBindings c+                            newBds    = case corebind of+                                          NonRec v e  -> insert v (BIND nextDepth False e) hbds+                                          Rec bds     -> hbds `union` fromList [ (b, BIND nextDepth True e) | (b,e) <- bds ]+                                                         -- Notice how all recursive binding in a binding group are at the same depth.+                        in c { hermitBindings = newBds+                             , hermitDepth    = nextDepth+                             }+ -- | Add the bindings for a specific case alternative.-addCaseBinding :: (Id,CoreExpr,CoreAlt) -> Context -> Context-addCaseBinding (n,e,(ac,is,_)) env-        = env { hermitBindings = insert n (CASE next_depth e (ac,is)) (hermitBindings env)-              , hermitDepth    = next_depth-              }-  where-        next_depth = succ (hermitDepth env)+addCaseBinding :: (Id,CoreExpr,CoreAlt) -> HermitC -> HermitC+addCaseBinding (v,e,(con,vs,_)) c = let nextDepth = succ (hermitDepth c)+                                     in c { hermitBindings = insert v (CASE nextDepth e (con,vs)) (hermitBindings c)+                                          , hermitDepth    = nextDepth+                                          } --- | Add a binding that you know nothing about, except that it may shadow something.--- If so, do not worry about it here, just remember the binding and the depth.--- When we want to inline a value from the environment,--- we then check to see what is free in the inlinee, and see--- if any of the frees will stop the validity of the inlining.-addLambdaBinding :: Id -> Context -> Context-addLambdaBinding n env-        = env { hermitBindings = insert n (LAM next_depth) (hermitBindings env)-              , hermitDepth    = next_depth-              }-  where-        next_depth = succ (hermitDepth env)+-- | Add a lambda bound variable to a context.+--   All that is known is the variable, which may shadow something.+--   If so, we don't worry about that here, it is instead checked during inlining.+addLambdaBinding :: Var -> HermitC -> HermitC+addLambdaBinding v c = let nextDepth = succ (hermitDepth c)+                        in c { hermitBindings = insert v (LAM nextDepth) (hermitBindings c)+                             , hermitDepth    = nextDepth+                             } --- | Add the Ids bound by a DataCon in a case. Like lambda bindings,+-- | Add the identifiers bound by a 'DataCon' in a case. Like lambda bindings, -- in that we know nothing about them, but all bound at the same depth,--- so we cannot just fold addLambdaBinding over the list.-addAltBindings :: [Id] -> Context -> Context-addAltBindings ns env-        = env { hermitBindings = foldr (\n bds -> insert n (LAM next_depth) bds) (hermitBindings env) ns-              , hermitDepth    = next_depth-              }-  where next_depth = succ (hermitDepth env)+-- so we cannot just fold 'addLambdaBinding' over the list.+addAltBindings :: [Id] -> HermitC -> HermitC+addAltBindings vs c = let nextDepth = succ (hermitDepth c)+                       in c { hermitBindings = foldr (\ v bds -> insert v (LAM nextDepth) bds) (hermitBindings c) vs+                            , hermitDepth    = nextDepth+                            } --- | Lookup the binding for an identifier in a 'Context'.-lookupHermitBinding :: Id -> Context -> Maybe HermitBinding+------------------------------------------------------------------------++-- | Lookup the binding for a variable in a context.+lookupHermitBinding :: Var -> HermitC -> Maybe HermitBinding lookupHermitBinding n env = lookup n (hermitBindings env) --- | List all the identifiers bound in the 'Context'.-listBindings :: Context -> [Id]-listBindings = keys . hermitBindings+-- | List all the variables bound in a context.+boundVars :: HermitC -> [Var]+boundVars = keys . hermitBindings --- | Determine if an identifier is bound in the 'Context'.-boundIn :: Id -> Context -> Bool-boundIn i c = i `elem` listBindings c+-- | Determine if a variable is bound in a context.+boundIn :: Var -> HermitC -> Bool+boundIn i c = i `elem` boundVars c++------------------------------------------------------------------------++-- | List all variables bound in the context that match the given name.+findBoundVars :: TH.Name -> HermitC -> [Var]+findBoundVars nm = filter (cmpTHName2Var nm) . boundVars  ------------------------------------------------------------------------
+ src/Language/HERMIT/Core.hs view
@@ -0,0 +1,115 @@+module Language.HERMIT.Core+          (+            -- * Generic Data Type+            -- $typenote+            Core(..)+          , CoreProg(..)+          , CoreDef(..)+          , CoreTickish+            -- * Conversions to/from 'Core'+          , defsToRecBind+          , defToIdExpr+          , progToBinds+          , bindsToProg+          , bindToIdExprs+            -- * Utilities+          , isType+          , typeExprToType+          , exprTypeOrKind+          , appCount+) where++import Data.Maybe(isJust)++import GhcPlugins++---------------------------------------------------------------------++-- $typenote+--   NOTE: 'Type' is not included in the generic datatype.+--   However, we could have included it and provided the facility for descending into types.+--   We have not done so because+--     (a) we do not need that functionality, and+--     (b) the types are complicated and we're not sure that we understand them.++-- | Core is the sum type of all nodes in the AST that we wish to be able to traverse.+--   All 'Node' instances in HERMIT define their 'Generic' type to be 'Core'.+data Core = ModGutsCore  ModGuts            -- ^ The module.+          | ProgCore     CoreProg           -- ^ A program (a telescope of top-level binding groups).+          | BindCore     CoreBind           -- ^ A binding group.+          | DefCore      CoreDef            -- ^ A recursive definition.+          | ExprCore     CoreExpr           -- ^ An expression.+          | AltCore      CoreAlt            -- ^ A case alternative.++---------------------------------------------------------------------++-- | A program is a telescope of nested binding groups.+--   That is, each binding scopes over the remainder of the program.+--   In GHC Core, programs are encoded as ['CoreBind'].+--   This data type is isomorphic.+data CoreProg = ProgNil                     -- ^ An empty program.+              | ProgCons CoreBind CoreProg  -- ^ A binding group and the program it scopes over.++infixr 5 `ProgCons`++-- | Get the list of bindings in a program.+progToBinds :: CoreProg -> [CoreBind]+progToBinds ProgNil         = []+progToBinds (ProgCons bd p) = bd : progToBinds p++-- | Build a program from a list of bindings.+--   Note that bindings earlier in the list are considered scope over bindings later in the list.+bindsToProg :: [CoreBind] -> CoreProg+bindsToProg = foldr ProgCons ProgNil++-- | Extract the list of identifier/expression pairs from a binding group.+bindToIdExprs :: CoreBind -> [(Id,CoreExpr)]+bindToIdExprs (NonRec v e) = [(v,e)]+bindToIdExprs (Rec bds)    = bds++-- | A (potentially recursive) definition is an identifier and an expression.+--   In GHC Core, recursive definitions are encoded as ('Id', 'CoreExpr') pairs.+--   This data type is isomorphic.+data CoreDef = Def Id CoreExpr++-- | Convert a definition to an identifier/expression pair.+defToIdExpr :: CoreDef -> (Id,CoreExpr)+defToIdExpr (Def v e) = (v,e)++-- | Convert a list of recursive definitions into an (isomorphic) recursive binding group.+defsToRecBind :: [CoreDef] -> CoreBind+defsToRecBind = Rec . map defToIdExpr++-----------------------------------------------------------------------++-- | Unlike everything else, there is no synonym for 'Tickish' 'Id' provided by GHC, so we define one.+type CoreTickish = Tickish Id++-----------------------------------------------------------------------++-- TODO: I don't know what to do about Coercions here, because I don't understand them.++-- | Succeeds if the expression is either a 'Type' or type 'Var'.+isType :: CoreExpr -> Bool+isType = isJust . typeExprToType++-- | Convert a 'CoreExpr' expression that \is\ a 'Type' into a 'Type'.+typeExprToType :: CoreExpr -> Maybe Type+typeExprToType (Type t)            = Just t+typeExprToType (Var v) | isTKVar v = Just (mkTyVarTy v)+typeExprToType _                   = Nothing++-- | GHC's 'exprType' function throws an error if applied to a 'Type' (but, inconsistently, return a 'Kind' if applied to a type variable).+--   This function returns the 'Kind' of a 'Type', but otherwise behaves as 'exprType'.+exprTypeOrKind :: CoreExpr -> Type+exprTypeOrKind (Type t) = typeKind t+exprTypeOrKind e        = exprType e++-----------------------------------------------------------------------++-- | Count the number of nested applications.+appCount :: CoreExpr -> Int+appCount (App e1 _) = appCount e1 + 1+appCount _          = 0++-----------------------------------------------------------------------
− src/Language/HERMIT/CoreExtra.hs
@@ -1,48 +0,0 @@-module Language.HERMIT.CoreExtra-          (-            -- * Generic Data Type-            -- $typenote-            Core(..)-          , CoreDef(..)-            -- * GHC Core Extras-          , CoreTickish-          , defToRecBind-) where--import GhcPlugins--------------------------------------------------------------------------- $typenote---   NOTE: 'Type' is not included in the generic datatype.---   However, we could have included it and provided the facility for descending into types.---   We have not done so because---     (a) we do not need that functionality, and---     (b) the types are complicated and we're not sure that we understand them.---- | Core is the sum type of all nodes in the AST that we wish to be able to traverse.---   All 'Node' instances in HERMIT define their 'Generic' type to be 'Core'.-data Core = ModGutsCore  ModGuts            -- ^ The module.-          | ProgramCore  CoreProgram        -- ^ A program (list of top-level bindings).-          | BindCore     CoreBind           -- ^ A binding group.-          | DefCore      CoreDef            -- ^ A recursive definition.-          | ExprCore     CoreExpr           -- ^ An expression.-          | AltCore      CoreAlt            -- ^ A case alternative.--------------------------------------------------------------------------- | A (potentially recursive) definition is an identifier and an expression.---   In GHC Core, recursive definitions are encoded as ('Id', 'CoreExpr') pairs.---   This data type is isomorphic.-data CoreDef = Def Id CoreExpr----------------------------------------------------------------------------- | Unlike everything else, there is no synonym for 'Tickish' 'Id' provided by GHC, so we provide one.-type CoreTickish = Tickish Id---- | Convert a list of recursive definitions into an (isomorphic) recursive binding group.-defToRecBind :: [CoreDef] -> CoreBind-defToRecBind = Rec . map (\ (Def v e) -> (v,e))-------------------------------------------------------------------------
src/Language/HERMIT/Dictionary.hs view
@@ -3,20 +3,21 @@ module Language.HERMIT.Dictionary        ( -- * The HERMIT Dictionary          -- | This is the main namespace. Things tend to be untyped, because the API is accessed via (untyped) names.-         all_externals+         Dictionary+       , all_externals        , dictionary        , pp_dictionary )  where -import Data.Default (def)+-- import Data.Default (def) import Data.Dynamic import Data.List import Data.Map (Map, fromList, toList) +import Language.HERMIT.Core import Language.HERMIT.Kure import Language.HERMIT.External ---import qualified Language.HERMIT.Primitive.Command as Command import qualified Language.HERMIT.Primitive.Kure as Kure import qualified Language.HERMIT.Primitive.Navigation as Navigation import qualified Language.HERMIT.Primitive.Inline as Inline@@ -24,6 +25,7 @@ import qualified Language.HERMIT.Primitive.New as New import qualified Language.HERMIT.Primitive.Debug as Debug import qualified Language.HERMIT.Primitive.GHC as GHC+import qualified Language.HERMIT.Primitive.FixPoint as FixPoint import qualified Language.HERMIT.Primitive.Fold as Fold import qualified Language.HERMIT.Primitive.Unfold as Unfold import qualified Language.HERMIT.Primitive.AlphaConversion as Alpha@@ -36,6 +38,10 @@  -------------------------------------------------------------------------- +-- | A 'Dictionary' is a collection of 'Dynamic's.+--   Looking up a 'Dynamic' (via a 'String' key) returns a list, as there can be multiple 'Dynamic's with the same name.+type Dictionary = Map String [Dynamic]+ prim_externals :: [External] prim_externals                =    Kure.externals@@ -44,6 +50,7 @@                  ++ Local.externals                  ++ Debug.externals                  ++ New.externals+                 ++ FixPoint.externals                  ++ Fold.externals                  ++ Unfold.externals                  ++ Alpha.externals@@ -53,8 +60,8 @@ all_externals :: [External] -> [External] all_externals my_externals = prim_externals ++ my_externals ++ GHC.externals --- | Create the dictionary.-dictionary :: [External] -> Map String [Dynamic]+-- | Create a dictionary from a list of 'External's.+dictionary :: [External] -> Dictionary dictionary externs = toDictionary externs'   where         msg = layoutTxt 60 (map (show . fst) dictionaryOfTags)@@ -88,6 +95,7 @@         , ("ghc",    GHCPP.corePrettyH)         ] +{- -- (This isn't used anywhere currently.) -- | Each pretty printer can suggest some options pp_opt_dictionary :: Map String PrettyOptions@@ -96,7 +104,7 @@         , ("ast",  def)         , ("ghc",  def)         ]-+-}  -------------------------------------------------------------------------- @@ -150,3 +158,5 @@                          , tagMatch p e                          -- necessary so we don't list things that don't type correctly                          , Just (_ :: RewriteH Core) <- [fmap unbox $ fromDynamic $ externFun e] ])++------------------------------------
src/Language/HERMIT/Expr.hs view
@@ -135,7 +135,7 @@ parseExprH0 inp =         [ (Box (CmdName str),inp1)         | (str,inp1) <- parseToken inp-        , isAlphaNum (head str) || head str == ':'    -- commands can start with :+        , isAlphaNum (head str) || head str == ':'    -- commands can start with : -- This can probably be removed now, as we no longer start commands with :         , all isId (tail str)         ] ++         [ (InfixableExpr (CmdName str),inp1)@@ -210,7 +210,7 @@ isId c = isAlphaNum c || c `elem` "_-'"  isInfixId :: Char -> Bool-isInfixId c = c `elem` "+._-:<>"+isInfixId c = c `elem` "+*/._-:<>"   ---------------------------------------------
src/Language/HERMIT/External.hs view
@@ -42,6 +42,7 @@  import qualified Language.Haskell.TH as TH +import Language.HERMIT.Core import Language.HERMIT.Kure  -----------------------------------------------------------------@@ -58,7 +59,6 @@ --   (or the help function will not find it). --   These should be /user facing/, because they give the user --   a way of sub-dividing our confusing array of commands.- data CmdTag = Shell          -- ^ Shell command.             | Eval           -- ^ The arrow of evaluation (reduces a term).             | KURE           -- ^ 'Language.KURE' command.
src/Language/HERMIT/GHC.hs view
@@ -1,14 +1,16 @@ module Language.HERMIT.GHC-        (+        ( -- * GHC Imports         -- | Things that have been copied from GHC, or imported directly, for various reasons.           ppIdInfo         , var2String         , thRdrNameGuesses         , name2THName-        , id2THName+        , var2THName         , cmpTHName2Name-        , cmpTHName2Id-        , unqualifiedIdName+        , cmpString2Name+        , cmpTHName2Var+        , cmpString2Var+        , unqualifiedVarName         , findNameFromTH         , alphaTyVars         , Type(..)@@ -31,7 +33,6 @@  -------------------------------------------------------------------------- --- idName :: Id -> Name -- varName :: Var -> Name -- nameOccName :: Name -> OccName -- occNameString :: OccName -> String@@ -44,27 +45,35 @@  -- | Convert a variable to a neat string for printing. var2String :: Var -> String-var2String = occNameString . nameOccName . varName+var2String = occNameString . nameOccName . varName -- TODO: would getOccString be okay here?  -- | Converts a GHC 'Name' to a Template Haskell 'TH.Name', going via a 'String'. name2THName :: Name -> TH.Name name2THName = TH.mkName . getOccString --- | Converts an 'Id' to a Template Haskell 'TH.Name', going via a 'String'.-id2THName :: Id -> TH.Name-id2THName = name2THName . idName+-- | Converts an 'Var' to a Template Haskell 'TH.Name', going via a 'String'.+var2THName :: Var -> TH.Name+var2THName = name2THName . varName --- | Get the unqualified name from an Id/Var.-unqualifiedIdName :: Id -> String-unqualifiedIdName = TH.nameBase . id2THName+-- | Get the unqualified name from an Var.+unqualifiedVarName :: Var -> String+unqualifiedVarName = TH.nameBase . var2THName  -- | Hacks until we can find the correct way of doing these. cmpTHName2Name :: TH.Name -> Name -> Bool-cmpTHName2Name th_nm ghc_nm = TH.nameBase th_nm == getOccString ghc_nm -- occNameString (nameOccName ghc_nm)+cmpTHName2Name th_nm = cmpString2Name (TH.nameBase th_nm)  -- | Hacks until we can find the correct way of doing these.-cmpTHName2Id :: TH.Name -> Id -> Bool-cmpTHName2Id nm = cmpTHName2Name nm . idName+cmpString2Name :: String -> Name -> Bool+cmpString2Name str nm = str == getOccString nm -- occNameString (nameOccName ghc_nm)++-- | Hacks until we can find the correct way of doing these.+cmpTHName2Var :: TH.Name -> Var -> Bool+cmpTHName2Var nm = cmpTHName2Name nm . varName++-- | Hacks until we can find the correct way of doing these.+cmpString2Var :: String -> Var -> Bool+cmpString2Var str = cmpString2Name str . varName  -- | This is hopeless O(n), because the we could not generate the 'OccName's that match, -- for use of the GHC 'OccEnv'.
src/Language/HERMIT/Interp.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE KindSignatures, GADTs #-}+{-# LANGUAGE KindSignatures, GADTs, InstanceSigs #-}  module Language.HERMIT.Interp         ( -- * The HERMIT Interpreter@@ -40,7 +40,8 @@ interp = Interp  instance Functor Interp where-   fmap f (Interp g) = Interp (f . g)+  fmap :: (a -> b) -> Interp a -> Interp b+  fmap f (Interp g) = Interp (f . g)   interpExpr :: M.Map String [Dynamic] -> ExprH -> Either String [Dynamic]@@ -49,7 +50,11 @@ interpExpr' :: Bool -> M.Map String [Dynamic] -> ExprH -> Either String [Dynamic] interpExpr' _   _   (SrcName str) = return [ toDyn $ NameBox $ TH.mkName str ] interpExpr' rhs env (CmdName str)-  | all isDigit str                     = return [ toDyn $ IntBox $ read str ]+                                        -- An Int is either a Path, or will be interpreted specially later.+  | all isDigit str                     = let i = read str in+                                          return [ toDyn $ IntBox i+                                                 , toDyn $ TranslateCorePathBox (return [i])+                                                 ]   | Just dyn <- M.lookup str env        = return $ if rhs                                                      then toDyn (StringBox str) : dyn                                                      else dyn@@ -64,4 +69,3 @@    where            dynApply' :: [Dynamic] -> [Dynamic] -> [Dynamic]            dynApply' fs xs = [ r | f <- fs, x <- xs, Just r <- return (dynApply f x)]-
src/Language/HERMIT/Kernel.hs view
@@ -25,23 +25,23 @@ import Data.Map import Control.Concurrent --- | A 'Kernel' is a repository for Core syntax trees.+-- | A 'Kernel' is a repository for complete Core syntax trees ('ModGuts'). --   For now, operations on a 'Kernel' are sequential, but later --   it will be possible to have two 'applyK's running in parallel. data Kernel = Kernel-  { resumeK ::            AST                                      -> IO ()                -- ^ Halt the 'Kernel' and return control to GHC, which compiles the specified 'AST'.-  , abortK  ::                                                        IO ()                -- ^ Halt the 'Kernel' and abort GHC without compiling.-  , applyK  ::            AST -> RewriteH Core     -> HermitMEnv   -> IO (KureMonad AST)   -- ^ Apply a 'Rewrite' to the specified 'AST' and return a handle to the resulting 'AST'.-  , queryK  :: forall a . AST -> TranslateH Core a -> HermitMEnv   -> IO (KureMonad a)     -- ^ Apply a 'TranslateH' to the 'AST' and return the resulting value.-  , deleteK ::            AST                                      -> IO ()                -- ^ Delete the internal record of the specified 'AST'.-  , listK   ::                                                        IO [AST]             -- ^ List all the 'AST's tracked by the 'Kernel'.+  { resumeK ::            AST                                        -> IO ()           -- ^ Halt the 'Kernel' and return control to GHC, which compiles the specified 'AST'.+  , abortK  ::                                                          IO ()           -- ^ Halt the 'Kernel' and abort GHC without compiling.+  , applyK  ::            AST -> RewriteH ModGuts     -> HermitMEnv  -> IO (KureM AST)  -- ^ Apply a 'Rewrite' to the specified 'AST' and return a handle to the resulting 'AST'.+  , queryK  :: forall a . AST -> TranslateH ModGuts a -> HermitMEnv  -> IO (KureM a)    -- ^ Apply a 'TranslateH' to the 'AST' and return the resulting value.+  , deleteK ::            AST                                        -> IO ()           -- ^ Delete the internal record of the specified 'AST'.+  , listK   ::                                                          IO [AST]        -- ^ List all the 'AST's tracked by the 'Kernel'.   }  -- | A /handle/ for a specific version of the 'ModGuts'. newtype AST = AST Int -- ^ Currently 'AST's are identified by an 'Int' label.               deriving (Eq, Ord, Show) -data Msg s r = forall a . Req (s -> CoreM (KureMonad (a,s))) (MVar (KureMonad a))+data Msg s r = forall a . Req (s -> CoreM (KureM (a,s))) (MVar (KureM a))              | Done (s -> CoreM r)  type KernelState = Map AST (DefStash, ModGuts)@@ -54,25 +54,25 @@          msgMV :: MVar (Msg KernelState ModGuts) <- liftIO newEmptyMVar -        syntax_names :: MVar AST <- liftIO newEmptyMVar+        nextASTname :: MVar AST <- liftIO newEmptyMVar -        _ <- liftIO $ forkIO $ let loop n = do putMVar syntax_names (AST n)+        _ <- liftIO $ forkIO $ let loop n = do putMVar nextASTname (AST n)                                                loop (succ n)                                 in loop 0          let sendDone :: (KernelState -> CoreM ModGuts) -> IO ()             sendDone = putMVar msgMV . Done -        let sendReq :: (KernelState -> CoreM (KureMonad (a, KernelState))) -> IO (KureMonad a)+        let sendReq :: (KernelState -> CoreM (KureM (a, KernelState))) -> IO (KureM a)             sendReq fn = do rep  <- newEmptyMVar                             putMVar msgMV (Req fn rep)                             takeMVar rep -        let sendReqRead :: (KernelState -> CoreM (KureMonad a)) -> IO (KureMonad a)+        let sendReqRead :: (KernelState -> CoreM (KureM a)) -> IO (KureM a)             sendReqRead fn = sendReq (\ st -> (fmap.fmap) (,st) $ fn st)          let sendReqWrite :: (KernelState -> CoreM KernelState) -> IO ()-            sendReqWrite fn = sendReq (fmap ( return . ((),) ) . fn) >>= runKureMonad return fail+            sendReqWrite fn = sendReq (fmap ( return . ((),) ) . fn) >>= runKureM return fail          let kernel :: Kernel             kernel = Kernel@@ -80,38 +80,38 @@                  , abortK  = sendDone $ \ _ -> throwGhcException (ProgramError "Exiting HERMIT and aborting GHC compilation.") -                , applyK = \ name r hm_env -> sendReq $ \ st -> findWithErrMsg name st fail $ \ (defs, core) -> runHM hm_env+                , applyK = \ name r hm_env -> sendReq $ \ st -> findWithErrMsg name st fail $ \ (defs, guts) -> runHM hm_env                                                                                                                defs-                                                                                                               (\ defs' core' -> do syn' <- liftIO $ takeMVar syntax_names-                                                                                                                                    return $ return (syn', insert syn' (defs',core') st))+                                                                                                               (\ defs' guts' -> do ast <- liftIO $ takeMVar nextASTname+                                                                                                                                    return $ return (ast, insert ast (defs',guts') st))                                                                                                                (return . fail)-                                                                                                               (apply (extractR r) (initContext core) core)+                                                                                                               (apply r (initHermitC guts) guts) -                , queryK = \ name q hm_env -> sendReqRead $ \ st -> findWithErrMsg name st fail $ \ (defs, core) -> runHM hm_env-                                                                                                                   defs-                                                                                                                   (\ _ -> return.return)-                                                                                                                   (return . fail)-                                                                                                                   (apply (extractT q) (initContext core) core)+                , queryK = \ name t hm_env -> sendReqRead $ \ st -> findWithErrMsg name st fail $ \ (defs, core) -> runHM hm_env+                                                                                                                      defs+                                                                                                                      (\ _ -> return.return)+                                                                                                                      (return . fail)+                                                                                                                      (apply t (initHermitC core) core)                  , deleteK = \ name -> sendReqWrite (return . delete name) -                , listK = sendReqRead (return . return . keys) >>= runKureMonad return fail+                , listK = sendReqRead (return . return . keys) >>= runKureM return fail                 } -        -- We always start with syntax blob 0-        syn <- liftIO $ takeMVar syntax_names+        -- We always start with AST 0+        ast0 <- liftIO $ takeMVar nextASTname          let loop :: KernelState -> CoreM ModGuts             loop st = do                 m <- liftIO $ takeMVar msgMV                 case m of-                  Req fn rep -> fn st >>= runKureMonad (\ (a,st') -> liftIO (putMVar rep $ return a) >> loop st')-                                                       (\ msg     -> liftIO (putMVar rep $ fail msg) >> loop st)+                  Req fn rep -> fn st >>= runKureM (\ (a,st') -> liftIO (putMVar rep $ return a) >> loop st')+                                                   (\ msg     -> liftIO (putMVar rep $ fail msg) >> loop st)                   Done fn -> fn st -        _pid <- liftIO $ forkIO $ callback kernel syn+        _pid <- liftIO $ forkIO $ callback kernel ast0 -        loop (singleton syn (empty, modGuts))+        loop (singleton ast0 (empty, modGuts))          -- (Kill the pid'd thread? do we need to?) 
src/Language/HERMIT/Kernel/Scoped.hs view
@@ -10,6 +10,7 @@        , scopedKernel ) where +import Control.Arrow import Control.Concurrent.STM import Control.Exception.Base (bracketOnError) @@ -17,9 +18,10 @@  import GhcPlugins hiding (Direction,L) +import Language.HERMIT.Core import Language.HERMIT.Kure-import Language.HERMIT.Kernel import Language.HERMIT.Monad+import Language.HERMIT.Kernel  ---------------------------------------------------------------------------- @@ -65,8 +67,8 @@ extendLocalPath :: Path -> LocalPath -> LocalPath extendLocalPath p (LocalPath lp) = LocalPath (reverse p ++ lp) -pathStackToLens :: [LocalPath] -> LocalPath -> LensH Core Core-pathStackToLens ps p = pathL $ concat $ localPaths2Paths (p:ps)+pathStackToLens :: [LocalPath] -> LocalPath -> LensH ModGuts Core+pathStackToLens ps p = injectL >>> pathL (concat $ localPaths2Paths (p:ps))  ---------------------------------------------------------------------------- @@ -74,12 +76,12 @@ data ScopedKernel = ScopedKernel         { resumeS     ::            SAST                                              -> IO ()         , abortS      ::                                                                 IO ()-        , applyS      ::            SAST -> RewriteH Core             -> HermitMEnv   -> IO (KureMonad SAST)-        , queryS      :: forall a . SAST -> TranslateH Core a         -> HermitMEnv   -> IO (KureMonad a)+        , applyS      ::            SAST -> RewriteH Core             -> HermitMEnv   -> IO (KureM SAST)+        , queryS      :: forall a . SAST -> TranslateH Core a         -> HermitMEnv   -> IO (KureM a)         , deleteS     ::            SAST                                              -> IO ()         , listS       ::                                                                 IO [SAST]         , pathS       ::            SAST                                              -> IO [Path]-        , modPathS    ::            SAST -> (LocalPath -> LocalPath)  -> HermitMEnv   -> IO (KureMonad SAST)+        , modPathS    ::            SAST -> (LocalPath -> LocalPath)  -> HermitMEnv   -> IO (KureM SAST)         , beginScopeS ::            SAST                                              -> IO SAST         , endScopeS   ::            SAST                                              -> IO SAST         }@@ -103,7 +105,7 @@     store <- newTMVarIO $ I.fromList [(0,(initAST, [], emptyLocalPath))]     key <- newTMVarIO (1::Int) -    let failCleanup :: SASTStore -> String -> IO (KureMonad a)+    let failCleanup :: SASTStore -> String -> IO (KureM a)         failCleanup m msg = atomically $ do putTMVar store m                                             return $ fail msg @@ -121,9 +123,9 @@             , applyS      = \ (SAST sAst) rr env -> safeTakeTMVar store $ \ m -> do                                 (ast, base, rel) <- get sAst m                                 applyK kernel ast (focusR (pathStackToLens base rel) rr) env-                                  >>= runKureMonad (\ ast' -> atomically $ do k <- newKey-                                                                              putTMVar store $ I.insert k (ast', base, rel) m-                                                                              return $ return $ SAST k)+                                  >>= runKureM (\ ast' -> atomically $ do k <- newKey+                                                                          putTMVar store $ I.insert k (ast', base, rel) m+                                                                          return $ return $ SAST k)                                                    (failCleanup m)             , queryS      = \ (SAST sAst) t env -> do                                 m <- atomically $ readTMVar store@@ -142,13 +144,13 @@                                 (ast, base, rel) <- get sAst m                                 let rel' = f rel                                 queryK kernel ast (testLensT (pathStackToLens base rel')) env-                                  >>= runKureMonad (\ b -> if rel == rel'-                                                            then failCleanup m "Path is unchanged, nothing to do."-                                                            else if b-                                                                  then atomically $ do k <- newKey-                                                                                       putTMVar store $ I.insert k (ast, base, rel') m-                                                                                       return (return $ SAST k)-                                                                  else failCleanup m "Invalid path created.")+                                  >>= runKureM (\ b -> if rel == rel'+                                                        then failCleanup m "Path is unchanged, nothing to do."+                                                        else if b+                                                              then atomically $ do k <- newKey+                                                                                   putTMVar store $ I.insert k (ast, base, rel') m+                                                                                   return (return $ SAST k)+                                                              else failCleanup m "Invalid path created.")                                                    (failCleanup m)             , beginScopeS = \ (SAST sAst) -> atomically $ do                                 m <- takeTMVar store
src/Language/HERMIT/Kure.hs view
@@ -1,5 +1,7 @@-{-# LANGUAGE MultiParamTypeClasses, TypeFamilies, FlexibleInstances, FlexibleContexts, TupleSections #-}+{-# LANGUAGE MultiParamTypeClasses, TypeFamilies, FlexibleInstances, FlexibleContexts, TupleSections, LambdaCase, InstanceSigs #-} +-- Note: InstanceSigs don't expand type families (annoyingly), as of GHC 7.6.1.  Check if this has been fixed in the next version.+ module Language.HERMIT.Kure        (        -- * KURE Modules@@ -7,22 +9,19 @@        -- | All the required functionality of KURE is exported here, so other modules do not need to import KURE directly.          module Language.KURE        , module Language.KURE.Injection-       , KureMonad, runKureMonad, fromKureMonad+       , KureM, runKureM, fromKureM        -- * Synonyms        -- | In HERMIT, 'Translate', 'Rewrite' and 'Lens' always operate on the same context and monad.        , TranslateH        , RewriteH        , LensH        , idR-       -- * Generic Data Type-       , Core(..)-       , CoreDef(..)        -- * Congruence combinators        -- ** Modguts        , modGutsT, modGutsR        -- ** Program-       , nilT-       , consBindT, consBindAllR, consBindAnyR, consBindOneR+       , progNilT+       , progConsT, progConsAllR, progConsAnyR, progConsOneR        -- ** Binding Groups        , nonRecT, nonRecR        , recT, recAllR, recAnyR, recOneR@@ -53,14 +52,14 @@        -- * Promotion Combinators        -- ** Rewrite Promotions        , promoteModGutsR-       , promoteProgramR+       , promoteProgR        , promoteBindR        , promoteDefR        , promoteExprR        , promoteAltR        -- ** Translate Promotions        , promoteModGutsT-       , promoteProgramT+       , promoteProgT        , promoteBindT        , promoteDefT        , promoteExprT@@ -74,7 +73,7 @@ import Language.KURE.Injection import Language.KURE.Utilities -import Language.HERMIT.CoreExtra+import Language.HERMIT.Core import Language.HERMIT.Context import Language.HERMIT.Monad @@ -85,9 +84,9 @@  --------------------------------------------------------------------- -type TranslateH a b = Translate Context HermitM a b-type RewriteH a = Rewrite Context HermitM a-type LensH a b = Lens Context HermitM a b+type TranslateH a b = Translate HermitC HermitM a b+type RewriteH a = Rewrite HermitC HermitM a+type LensH a b = Lens HermitC HermitM a b  -- | A synonym for the identity rewrite.  Convienient to avoid importing Control.Category. idR :: RewriteH a@@ -98,8 +97,9 @@ instance Node Core where   type Generic Core = Core +  numChildren :: Core -> Int   numChildren (ModGutsCore x) = numChildren x-  numChildren (ProgramCore x) = numChildren x+  numChildren (ProgCore x)    = numChildren x   numChildren (BindCore x)    = numChildren x   numChildren (DefCore x)     = numChildren x   numChildren (ExprCore x)    = numChildren x@@ -108,50 +108,57 @@ -- Defining Walker instances for the Generic type 'Core' is almost entirely automated by KURE. -- Unfortunately, you still need to pattern match on the 'Core' data type. -instance Walker Context HermitM Core where-  childL n = lens $ translate $ \ c core -> case core of+instance Walker HermitC HermitM Core where++  childL :: Int -> LensH Core (Generic Core)+  childL n = lens $ translate $ \ c -> \case           ModGutsCore x -> childLgeneric n c x-          ProgramCore x -> childLgeneric n c x+          ProgCore x    -> childLgeneric n c x           BindCore x    -> childLgeneric n c x           DefCore x     -> childLgeneric n c x           ExprCore x    -> childLgeneric n c x           AltCore x     -> childLgeneric n c x -  allT t = translate $ \ c core -> case core of+  allT :: Monoid b => TranslateH (Generic Core) b -> TranslateH Core b+  allT t = translate $ \ c -> \case           ModGutsCore x -> allTgeneric t c x-          ProgramCore x -> allTgeneric t c x+          ProgCore x    -> allTgeneric t c x           BindCore x    -> allTgeneric t c x           DefCore x     -> allTgeneric t c x           ExprCore x    -> allTgeneric t c x           AltCore x     -> allTgeneric t c x -  oneT t = translate $ \ c core -> case core of+  oneT :: TranslateH (Generic Core) b -> TranslateH Core b+  oneT t = translate $ \ c -> \case           ModGutsCore x -> oneTgeneric t c x-          ProgramCore x -> oneTgeneric t c x+          ProgCore x    -> oneTgeneric t c x           BindCore x    -> oneTgeneric t c x           DefCore x     -> oneTgeneric t c x           ExprCore x    -> oneTgeneric t c x           AltCore x     -> oneTgeneric t c x -  allR r = rewrite $ \ c core -> case core of+  allR :: RewriteH (Generic Core) -> RewriteH Core+  allR r = rewrite $ \ c -> \case           ModGutsCore x -> allRgeneric r c x-          ProgramCore x -> allRgeneric r c x+          ProgCore x    -> allRgeneric r c x           BindCore x    -> allRgeneric r c x           DefCore x     -> allRgeneric r c x           ExprCore x    -> allRgeneric r c x           AltCore x     -> allRgeneric r c x -  anyR r = rewrite $ \ c core -> case core of+  anyR :: RewriteH (Generic Core) -> RewriteH Core+  anyR r = rewrite $ \ c -> \case           ModGutsCore x -> anyRgeneric r c x-          ProgramCore x -> anyRgeneric r c x+          ProgCore x    -> anyRgeneric r c x           BindCore x    -> anyRgeneric r c x           DefCore x     -> anyRgeneric r c x           ExprCore x    -> anyRgeneric r c x           AltCore x     -> anyRgeneric r c x -  oneR r = rewrite $ \ c core -> case core of+  oneR :: RewriteH (Generic Core) -> RewriteH Core+  oneR r = rewrite $ \ c -> \case           ModGutsCore x -> oneRgeneric r c x-          ProgramCore x -> oneRgeneric r c x+          ProgCore x    -> oneRgeneric r c x           BindCore x    -> oneRgeneric r c x           DefCore x     -> oneRgeneric r c x           ExprCore x    -> oneRgeneric r c x@@ -160,87 +167,109 @@ ---------------------------------------------------------------------  instance Injection ModGuts Core where-  inject                     = ModGutsCore++  inject :: ModGuts -> Core+  inject = ModGutsCore++  retract :: Core -> Maybe ModGuts   retract (ModGutsCore guts) = Just guts   retract _                  = Nothing  instance Node ModGuts where   type Generic ModGuts = Core +  numChildren :: ModGuts -> Int   numChildren _ = 1 -instance Walker Context HermitM ModGuts where-  childL 0 = lens $ modGutsT exposeT (childL1of2 $ \ modguts bds -> modguts {mg_binds = bds})+instance Walker HermitC HermitM ModGuts where++  childL :: Int -> LensH ModGuts (Generic ModGuts)+  childL 0 = lens $ modGutsT exposeT (childL1of2 $ \ modguts p -> modguts {mg_binds = progToBinds p})   childL n = failT (missingChild n)  -- | Translate a module. --   Slightly different to the other congruence combinators: it passes in *all* of the original to the reconstruction function.-modGutsT :: TranslateH CoreProgram a -> (ModGuts -> a -> b) -> TranslateH ModGuts b-modGutsT t f = translate $ \ c modGuts -> f modGuts <$> apply t (c @@ 0) (mg_binds modGuts)+modGutsT :: TranslateH CoreProg a -> (ModGuts -> a -> b) -> TranslateH ModGuts b+modGutsT t f = translate $ \ c modGuts -> f modGuts <$> apply t (c @@ 0) (bindsToProg (mg_binds modGuts)) --- | Rewrite the 'CoreProgram' child of a module.-modGutsR :: RewriteH CoreProgram -> RewriteH ModGuts-modGutsR r = modGutsT r (\ modguts bds -> modguts {mg_binds = bds})+-- | Rewrite the 'CoreProg' child of a module.+modGutsR :: RewriteH CoreProg -> RewriteH ModGuts+modGutsR r = modGutsT r (\ modguts p -> modguts {mg_binds = progToBinds p})  --------------------------------------------------------------------- -instance Injection CoreProgram Core where-  inject                    = ProgramCore-  retract (ProgramCore bds) = Just bds-  retract _                 = Nothing+instance Injection CoreProg Core where -instance Node CoreProgram where-  type Generic CoreProgram = Core+  inject :: CoreProg -> Core+  inject = ProgCore -  -- we consider only the head and tail to be interesting children-  numChildren bds = min 2 (length bds)+  retract :: Core -> Maybe CoreProg+  retract (ProgCore bds) = Just bds+  retract _              = Nothing -instance Walker Context HermitM CoreProgram where-  childL 0 = lens $ consBindT exposeT idR (childL0of2 (:))-  childL 1 = lens $ consBindT idR exposeT (childL1of2 (:))+instance Node CoreProg where+  type Generic CoreProg = Core++  -- A program is either empty (zero children) or a binding group and the remaining program it scopes over (two children).+  numChildren :: CoreProg -> Int+  numChildren ProgNil        = 0+  numChildren (ProgCons _ _) = 2++instance Walker HermitC HermitM CoreProg where++  childL :: Int -> LensH CoreProg (Generic CoreProg)+  childL 0 = lens $ progConsT exposeT idR (childL0of2 ProgCons)+  childL 1 = lens $ progConsT idR exposeT (childL1of2 ProgCons)   childL n = failT (missingChild n)  -- | Translate an empty list.-nilT :: b -> TranslateH [a] b-nilT b = contextfreeT $ \ e -> case e of-                           [] -> pure b-                           _  -> fail "no match for []"+progNilT :: b -> TranslateH CoreProg b+progNilT b = contextfreeT $ \case+                               ProgNil       -> pure b+                               ProgCons _ _  -> fail "not an empty program node." -consBindT' :: TranslateH CoreBind a1 -> TranslateH CoreProgram a2 -> (HermitM a1 -> HermitM a2 -> HermitM b) -> TranslateH CoreProgram b-consBindT' t1 t2 f = translate $ \ c e -> case e of-        bd:bds -> f (apply t1 (c @@ 0) bd) (apply t2 (addBinding bd c @@ 1) bds)-        _      -> fail "no match for consBind"+progConsT' :: TranslateH CoreBind a1 -> TranslateH CoreProg a2 -> (HermitM a1 -> HermitM a2 -> HermitM b) -> TranslateH CoreProg b+progConsT' t1 t2 f = translate $ \ c -> \case+                                           ProgCons bd p -> f (apply t1 (c @@ 0) bd) (apply t2 (addBinding bd c @@ 1) p)+                                           _             -> fail "not a non-empty program node." --- | Translate a program of the form: ('CoreBind' @:@ 'CoreProgram')-consBindT :: TranslateH CoreBind a1 -> TranslateH CoreProgram a2 -> (a1 -> a2 -> b) -> TranslateH CoreProgram b-consBindT t1 t2 f = consBindT' t1 t2 (liftA2 f)+-- | Translate a program of the form: ('CoreBind' @:@ 'CoreProg')+progConsT :: TranslateH CoreBind a1 -> TranslateH CoreProg a2 -> (a1 -> a2 -> b) -> TranslateH CoreProg b+progConsT t1 t2 f = progConsT' t1 t2 (liftA2 f) --- | Rewrite all children of a program of the form: ('CoreBind' @:@ 'CoreProgram')-consBindAllR :: RewriteH CoreBind -> RewriteH CoreProgram -> RewriteH CoreProgram-consBindAllR r1 r2 = consBindT r1 r2 (:)+-- | Rewrite all children of a program of the form: ('CoreBind' @:@ 'CoreProg')+progConsAllR :: RewriteH CoreBind -> RewriteH CoreProg -> RewriteH CoreProg+progConsAllR r1 r2 = progConsT r1 r2 ProgCons --- | Rewrite any children of a program of the form: ('CoreBind' @:@ 'CoreProgram')-consBindAnyR :: RewriteH CoreBind -> RewriteH CoreProgram -> RewriteH CoreProgram-consBindAnyR r1 r2 = consBindT' (attemptR r1) (attemptR r2) (attemptAny2 (:))+-- | Rewrite any children of a program of the form: ('CoreBind' @:@ 'CoreProg')+progConsAnyR :: RewriteH CoreBind -> RewriteH CoreProg -> RewriteH CoreProg+progConsAnyR r1 r2 = progConsT' (attemptR r1) (attemptR r2) (attemptAny2 ProgCons) --- | Rewrite one child of a program of the form: ('CoreBind' @:@ 'CoreProgram')-consBindOneR :: RewriteH CoreBind -> RewriteH CoreProgram -> RewriteH CoreProgram-consBindOneR r1 r2 = consBindT' (withArgumentT r1) (withArgumentT r2) (attemptOne2 (:))+-- | Rewrite one child of a program of the form: ('CoreBind' @:@ 'CoreProg')+progConsOneR :: RewriteH CoreBind -> RewriteH CoreProg -> RewriteH CoreProg+progConsOneR r1 r2 = progConsT' (withArgumentT r1) (withArgumentT r2) (attemptOne2 ProgCons)  ---------------------------------------------------------------------  instance Injection CoreBind Core where-  inject                  = BindCore++  inject :: CoreBind -> Core+  inject = BindCore++  retract :: Core -> Maybe CoreBind   retract (BindCore bnd)  = Just bnd   retract _               = Nothing  instance Node CoreBind where   type Generic CoreBind = Core +  numChildren :: CoreBind -> Int   numChildren (NonRec _ _) = 1   numChildren (Rec defs)   = length defs -instance Walker Context HermitM CoreBind where+instance Walker HermitC HermitM CoreBind where++  childL :: Int -> LensH CoreBind (Generic CoreBind)   childL n = lens $ setFailMsg (missingChild n) $                case n of                  0 -> nonrec <+ rec@@ -249,41 +278,46 @@     where       nonrec = nonRecT exposeT (childL1of2 NonRec)       rec    = whenM (hasChildT n) $-                  recT (const exposeT) (childLMofN n defToRecBind)+                  recT (const exposeT) (childLMofN n defsToRecBind) +  allT :: Monoid b => TranslateH (Generic CoreBind) b -> TranslateH CoreBind b   allT t = nonRecT (extractT t) (\ _ -> id)         <+ recT (\ _ -> extractT t) mconcat +  oneT :: TranslateH (Generic CoreBind) b -> TranslateH CoreBind b   oneT t = nonRecT (extractT t) (\ _ -> id)         <+ recT' (\ _ -> extractT t) catchesM +  allR :: RewriteH (Generic CoreBind) -> RewriteH CoreBind   allR r = nonRecR (extractR r)         <+ recAllR (\ _ -> extractR r) +  anyR :: RewriteH (Generic CoreBind) -> RewriteH CoreBind   anyR r = nonRecR (extractR r)         <+ recAnyR (\ _ -> extractR r) +  oneR :: RewriteH (Generic CoreBind) -> RewriteH CoreBind   oneR r = nonRecR (extractR r)         <+ recOneR (\ _ -> extractR r) --- | Translate a binding group of the form: @NonRec@ 'Id' 'CoreExpr'-nonRecT :: TranslateH CoreExpr a -> (Id -> a -> b) -> TranslateH CoreBind b-nonRecT t f = translate $ \ c e -> case e of-                                     NonRec v e' -> f v <$> apply t (c @@ 0) e'-                                     _           -> fail "not NonRec constructor"+-- | Translate a binding group of the form: @NonRec@ 'Var' 'CoreExpr'+nonRecT :: TranslateH CoreExpr a -> (Var -> a -> b) -> TranslateH CoreBind b+nonRecT t f = translate $ \ c -> \case+                                    NonRec v e -> f v <$> apply t (c @@ 0) e+                                    _          -> fail "not a non-recursive binding-group node." --- | Rewrite the 'CoreExpr' child of a binding group of the form: @NonRec@ 'Id' 'CoreExpr'+-- | Rewrite the 'CoreExpr' child of a binding group of the form: @NonRec@ 'Var' 'CoreExpr' nonRecR :: RewriteH CoreExpr -> RewriteH CoreBind nonRecR r = nonRecT r NonRec  recT' :: (Int -> TranslateH CoreDef a) -> ([HermitM a] -> HermitM b) -> TranslateH CoreBind b-recT' t f = translate $ \ c e -> case e of-         Rec bds -> -- Notice how we add the scoping bindings here *before* decending into each individual definition.+recT' t f = translate $ \ c -> \case+         Rec bds -> -- Notice how we add the scoping bindings here *before* descending into each individual definition.                     let c' = addBinding (Rec bds) c-                     in f [ apply (t n) (c' @@ n) (Def v e') -- here we convert from (Id,CoreExpr) to CoreDef-                          | ((v,e'),n) <- zip bds [0..]+                     in f [ apply (t n) (c' @@ n) (Def v e) -- here we convert from (Id,CoreExpr) to CoreDef+                          | ((v,e),n) <- zip bds [0..]                           ]-         _       -> fail "not Rec constructor"+         _       -> fail "not a recursive binding-group node."  -- | Translate a binding group of the form: @Rec@ ['CoreDef'] recT :: (Int -> TranslateH CoreDef a) -> ([a] -> b) -> TranslateH CoreBind b@@ -291,29 +325,36 @@  -- | Rewrite all children of a binding group of the form: @Rec@ ['CoreDef'] recAllR :: (Int -> RewriteH CoreDef) -> RewriteH CoreBind-recAllR rs = recT rs defToRecBind+recAllR rs = recT rs defsToRecBind  -- | Rewrite any children of a binding group of the form: @Rec@ ['CoreDef'] recAnyR :: (Int -> RewriteH CoreDef) -> RewriteH CoreBind-recAnyR rs = recT' (attemptR . rs) (attemptAnyN defToRecBind)+recAnyR rs = recT' (attemptR . rs) (attemptAnyN defsToRecBind)  -- | Rewrite one child of a binding group of the form: @Rec@ ['CoreDef'] recOneR :: (Int -> RewriteH CoreDef) -> RewriteH CoreBind-recOneR rs = recT' (withArgumentT . rs) (attemptOneN defToRecBind)+recOneR rs = recT' (withArgumentT . rs) (attemptOneN defsToRecBind)  ---------------------------------------------------------------------  instance Injection CoreDef Core where-  inject                = DefCore++  inject :: CoreDef -> Core+  inject = DefCore++  retract :: Core -> Maybe CoreDef   retract (DefCore def) = Just def   retract _             = Nothing  instance Node CoreDef where   type Generic CoreDef = Core +  numChildren :: CoreDef -> Int   numChildren _ = 1 -instance Walker Context HermitM CoreDef where+instance Walker HermitC HermitM CoreDef where++  childL :: Int -> LensH CoreDef (Generic CoreDef)   childL 0 = lens $ defT exposeT (childL1of2 Def)   childL n = failT (missingChild n) @@ -328,16 +369,23 @@ ---------------------------------------------------------------------  instance Injection CoreAlt Core where-  inject                 = AltCore++  inject :: CoreAlt -> Core+  inject = AltCore++  retract :: Core -> Maybe CoreAlt   retract (AltCore expr) = Just expr   retract _              = Nothing  instance Node CoreAlt where   type Generic CoreAlt = Core +  numChildren :: CoreAlt -> Int   numChildren _ = 1 -instance Walker Context HermitM CoreAlt where+instance Walker HermitC HermitM CoreAlt where++  childL :: Int -> LensH CoreAlt (Generic CoreAlt)   childL 0 = lens $ altT exposeT (childL2of3 (,,))   childL n = failT (missingChild n) @@ -352,13 +400,18 @@ ---------------------------------------------------------------------  instance Injection CoreExpr Core where-  inject                  = ExprCore++  inject :: CoreExpr -> Core+  inject = ExprCore++  retract :: Core -> Maybe CoreExpr   retract (ExprCore expr) = Just expr   retract _               = Nothing  instance Node CoreExpr where   type Generic CoreExpr = Core +  numChildren :: CoreExpr -> Int   numChildren (Var _)         = 0   numChildren (Lit _)         = 0   numChildren (App _ _)       = 2@@ -370,8 +423,9 @@   numChildren (Type _)        = 0   numChildren (Coercion _)    = 0 -instance Walker Context HermitM CoreExpr where+instance Walker HermitC HermitM CoreExpr where +  childL :: Int -> LensH CoreExpr (Generic CoreExpr)   childL n = lens $ setFailMsg (missingChild n) $                case n of                  0  ->    appT  exposeT idR         (childL0of2 App)@@ -391,6 +445,7 @@        caseChooseL = whenM (hasChildT n) $                            caseT idR (const exposeT) (\ e v t -> childLMofN (n-1) (Case e v t)) +  allT :: Monoid b => TranslateH (Generic CoreExpr) b -> TranslateH CoreExpr b   allT t = varT (\ _ -> mempty)         <+ litT (\ _ -> mempty)         <+ appT (extractT t) (extractT t) mappend@@ -402,6 +457,7 @@         <+ typeT (\ _ -> mempty)         <+ coercionT (\ _ -> mempty) +  oneT :: TranslateH (Generic CoreExpr) b -> TranslateH CoreExpr b   oneT t = appT' (extractT t) (extractT t) (<<+)         <+ lamT (extractT t) (\ _ -> id)         <+ letT' (extractT t) (extractT t) (<<+)@@ -409,6 +465,7 @@         <+ castT (extractT t) const         <+ tickT (extractT t) (\ _ -> id) +  allR :: RewriteH (Generic CoreExpr) -> RewriteH CoreExpr   allR r = varT Var         <+ litT Lit         <+ appAllR (extractR r) (extractR r)@@ -420,6 +477,7 @@         <+ typeT Type         <+ coercionT Coercion +  anyR :: RewriteH (Generic CoreExpr) -> RewriteH CoreExpr   anyR r = appAnyR (extractR r) (extractR r)         <+ lamR (extractR r)         <+ letAnyR (extractR r) (extractR r)@@ -428,6 +486,7 @@         <+ tickR (extractR r)         <+ fail "anyR failed" +  oneR :: RewriteH (Generic CoreExpr) -> RewriteH CoreExpr   oneR r = appOneR (extractR r) (extractR r)         <+ lamR (extractR r)         <+ letOneR (extractR r) (extractR r)@@ -438,23 +497,23 @@  --------------------------------------------------------------------- --- | Translate an expression of the form: @Var@ 'Id'-varT :: (Id -> b) -> TranslateH CoreExpr b-varT f = contextfreeT $ \ e -> case e of-        Var v -> pure (f v)-        _     -> fail "no match for Var"+-- | Translate an expression of the form: @Var@ 'Var'+varT :: (Var -> b) -> TranslateH CoreExpr b+varT f = contextfreeT $ \case+                           Var v -> pure (f v)+                           _     -> fail "not a variable node."  -- | Translate an expression of the form: @Lit@ 'Literal' litT :: (Literal -> b) -> TranslateH CoreExpr b-litT f = contextfreeT $ \ e -> case e of-        Lit x -> pure (f x)-        _     -> fail "no match for Lit"+litT f = contextfreeT $ \case+                           Lit x -> pure (f x)+                           _     -> fail "not a literal node."   appT' :: TranslateH CoreExpr a1 -> TranslateH CoreExpr a2 -> (HermitM a1 -> HermitM a2 -> HermitM b) -> TranslateH CoreExpr b-appT' t1 t2 f = translate $ \ c e -> case e of-         App e1 e2 -> f (apply t1 (c @@ 0) e1) (apply t2 (c @@ 1) e2)-         _         -> fail "no match for App"+appT' t1 t2 f = translate $ \ c -> \case+                                      App e1 e2 -> f (apply t1 (c @@ 0) e1) (apply t2 (c @@ 1) e2)+                                      _         -> fail "not an application node."  -- | Translate an expression of the form: @App@ 'CoreExpr' 'CoreExpr' appT :: TranslateH CoreExpr a1 -> TranslateH CoreExpr a2 -> (a1 -> a2 -> b) -> TranslateH CoreExpr b@@ -472,23 +531,23 @@ appOneR :: RewriteH CoreExpr -> RewriteH CoreExpr -> RewriteH CoreExpr appOneR r1 r2 = appT' (withArgumentT r1) (withArgumentT r2) (attemptOne2 App) --- | Translate an expression of the form: @Lam@ 'Id' 'CoreExpr'-lamT :: TranslateH CoreExpr a -> (Id -> a -> b) -> TranslateH CoreExpr b-lamT t f = translate $ \ c e -> case e of-        Lam b e1 -> f b <$> apply t (addLambdaBinding b c @@ 0) e1-        _        -> fail "no match for Lam"+-- | Translate an expression of the form: @Lam@ 'Var' 'CoreExpr'+lamT :: TranslateH CoreExpr a -> (Var -> a -> b) -> TranslateH CoreExpr b+lamT t f = translate $ \ c -> \case+                                 Lam b e -> f b <$> apply t (addLambdaBinding b c @@ 0) e+                                 _       -> fail "not a lambda node." --- | Rewrite the 'CoreExpr' child of an expression of the form: @Lam@ 'Id' 'CoreExpr'+-- | Rewrite the 'CoreExpr' child of an expression of the form: @Lam@ 'Var' 'CoreExpr' lamR :: RewriteH CoreExpr -> RewriteH CoreExpr lamR r = lamT r Lam   letT' :: TranslateH CoreBind a1 -> TranslateH CoreExpr a2 -> (HermitM a1 -> HermitM a2 -> HermitM b) -> TranslateH CoreExpr b-letT' t1 t2 f = translate $ \ c e -> case e of-        Let bds e1 -> f (apply t1 (c @@ 0) bds) (apply t2 (addBinding bds c @@ 1) e1)+letT' t1 t2 f = translate $ \ c -> \case+        Let bds e -> f (apply t1 (c @@ 0) bds) (apply t2 (addBinding bds c @@ 1) e)                 -- use *original* env, because the bindings are self-binding,                 -- if they are recursive. See recT'.-        _         -> fail "no match for Let"+        _         -> fail "not a let node."  -- | Translate an expression of the form: @Let@ 'CoreBind' 'CoreExpr' letT :: TranslateH CoreBind a1 -> TranslateH CoreExpr a2 -> (a1 -> a2 -> b) -> TranslateH CoreExpr b@@ -507,21 +566,15 @@ letOneR r1 r2 = letT' (withArgumentT r1) (withArgumentT r2) (attemptOne2 Let)  -caseT' :: TranslateH CoreExpr a1-      -> (Int -> TranslateH CoreAlt a2)-      -> (Id -> Type -> HermitM a1 -> [HermitM a2] -> HermitM b)-      -> TranslateH CoreExpr b-caseT' t ts f = translate $ \ c e -> case e of-         Case e1 b ty alts -> f b ty (apply t (c @@ 0) e1) $ [ apply (ts n) (addCaseBinding (b,e1,alt) c @@ (n+1)) alt-                                                             | (alt,n) <- zip alts [0..]-                                                             ]-         _ -> fail "no match for Case"+caseT' :: TranslateH CoreExpr a1 -> (Int -> TranslateH CoreAlt a2) -> (Id -> Type -> HermitM a1 -> [HermitM a2] -> HermitM b) -> TranslateH CoreExpr b+caseT' t ts f = translate $ \ c -> \case+         Case e b ty alts -> f b ty (apply t (c @@ 0) e) $ [ apply (ts n) (addCaseBinding (b,e,alt) c @@ (n+1)) alt+                                                           | (alt,n) <- zip alts [0..]+                                                           ]+         _                -> fail "not a case node."  -- | Translate an expression of the form: @Case@ 'CoreExpr' 'Id' 'Type' ['CoreAlt']-caseT :: TranslateH CoreExpr a1-      -> (Int -> TranslateH CoreAlt a2)-      -> (a1 -> Id -> Type -> [a2] -> b)-      -> TranslateH CoreExpr b+caseT :: TranslateH CoreExpr a1 -> (Int -> TranslateH CoreAlt a2) -> (a1 -> Id -> Type -> [a2] -> b) -> TranslateH CoreExpr b caseT t ts f = caseT' t ts (\ b ty me malts -> f <$> me <*> pure b <*> pure ty <*> sequence malts)  -- | Rewrite all children of an expression of the form: @Case@ 'CoreExpr' 'Id' 'Type' ['CoreAlt']@@ -538,9 +591,9 @@  -- | Translate an expression of the form: @Cast@ 'CoreExpr' 'Coercion' castT :: TranslateH CoreExpr a -> (a -> Coercion -> b) -> TranslateH CoreExpr b-castT t f = translate $ \ c e -> case e of-                                   Cast e1 cast -> f <$> apply t (c @@ 0) e1 <*> pure cast-                                   _            -> fail "no match for Cast"+castT t f = translate $ \ c -> \case+                                  Cast e cast -> f <$> apply t (c @@ 0) e <*> pure cast+                                  _           -> fail "not a cast node."  -- | Rewrite the 'CoreExpr' child of an expression of the form: @Cast@ 'CoreExpr' 'Coercion' castR :: RewriteH CoreExpr -> RewriteH CoreExpr@@ -548,9 +601,9 @@  -- | Translate an expression of the form: @Tick@ 'CoreTickish' 'CoreExpr' tickT :: TranslateH CoreExpr a -> (CoreTickish -> a -> b) -> TranslateH CoreExpr b-tickT t f = translate $ \ c e -> case e of-        Tick tk e1 -> f tk <$> apply t (c @@ 0) e1-        _          -> fail "no match for Tick"+tickT t f = translate $ \ c -> \case+        Tick tk e -> f tk <$> apply t (c @@ 0) e+        _         -> fail "not a tick node."  -- | Rewrite the 'CoreExpr' child of an expression of the form: @Tick@ 'CoreTickish' 'CoreExpr' tickR :: RewriteH CoreExpr -> RewriteH CoreExpr@@ -558,15 +611,15 @@  -- | Translate an expression of the form: @Type@ 'Type' typeT :: (Type -> b) -> TranslateH CoreExpr b-typeT f = contextfreeT $ \ e -> case e of-                                  Type t -> pure (f t)-                                  _      -> fail "no match for Type"+typeT f = contextfreeT $ \case+                            Type t -> pure (f t)+                            _      -> fail "not a type node."  -- | Translate an expression of the form: @Coercion@ 'Coercion' coercionT :: (Coercion -> b) -> TranslateH CoreExpr b-coercionT f = contextfreeT $ \ e -> case e of-                                      Coercion co -> pure (f co)-                                      _           -> fail "no match for Coercion"+coercionT f = contextfreeT $ \case+                                Coercion co -> pure (f co)+                                _           -> fail "not a coercion node."  --------------------------------------------------------------------- @@ -589,70 +642,70 @@ recDefOneR rs = recOneR (\ n -> defR (rs n))  --- | Translate a program of the form: (@NonRec@ 'Id' 'CoreExpr') @:@ 'CoreProgram'-consNonRecT :: TranslateH CoreExpr a1 -> TranslateH CoreProgram a2 -> (Id -> a1 -> a2 -> b) -> TranslateH CoreProgram b-consNonRecT t1 t2 f = consBindT (nonRecT t1 (,)) t2 (uncurry f)+-- | Translate a program of the form: (@NonRec@ 'Var' 'CoreExpr') @:@ 'CoreProg'+consNonRecT :: TranslateH CoreExpr a1 -> TranslateH CoreProg a2 -> (Var -> a1 -> a2 -> b) -> TranslateH CoreProg b+consNonRecT t1 t2 f = progConsT (nonRecT t1 (,)) t2 (uncurry f) --- | Rewrite all children of an expression of the form: (@NonRec@ 'Id' 'CoreExpr') @:@ 'CoreProgram'-consNonRecAllR :: RewriteH CoreExpr -> RewriteH CoreProgram -> RewriteH CoreProgram-consNonRecAllR r1 r2 = consBindAllR (nonRecR r1) r2+-- | Rewrite all children of an expression of the form: (@NonRec@ 'Var' 'CoreExpr') @:@ 'CoreProg'+consNonRecAllR :: RewriteH CoreExpr -> RewriteH CoreProg -> RewriteH CoreProg+consNonRecAllR r1 r2 = progConsAllR (nonRecR r1) r2 --- | Rewrite any children of an expression of the form: (@NonRec@ 'Id' 'CoreExpr') @:@ 'CoreProgram'-consNonRecAnyR :: RewriteH CoreExpr -> RewriteH CoreProgram -> RewriteH CoreProgram-consNonRecAnyR r1 r2 = consBindAnyR (nonRecR r1) r2+-- | Rewrite any children of an expression of the form: (@NonRec@ 'Var' 'CoreExpr') @:@ 'CoreProg'+consNonRecAnyR :: RewriteH CoreExpr -> RewriteH CoreProg -> RewriteH CoreProg+consNonRecAnyR r1 r2 = progConsAnyR (nonRecR r1) r2 --- | Rewrite one child of an expression of the form: (@NonRec@ 'Id' 'CoreExpr') @:@ 'CoreProgram'-consNonRecOneR :: RewriteH CoreExpr -> RewriteH CoreProgram -> RewriteH CoreProgram-consNonRecOneR r1 r2 = consBindOneR (nonRecR r1) r2+-- | Rewrite one child of an expression of the form: (@NonRec@ 'Var' 'CoreExpr') @:@ 'CoreProg'+consNonRecOneR :: RewriteH CoreExpr -> RewriteH CoreProg -> RewriteH CoreProg+consNonRecOneR r1 r2 = progConsOneR (nonRecR r1) r2  --- | Translate an expression of the form: (@Rec@ ['CoreDef']) @:@ 'CoreProgram'-consRecT :: (Int -> TranslateH CoreDef a1) -> TranslateH CoreProgram a2 -> ([a1] -> a2 -> b) -> TranslateH CoreProgram b-consRecT ts t = consBindT (recT ts id) t+-- | Translate an expression of the form: (@Rec@ ['CoreDef']) @:@ 'CoreProg'+consRecT :: (Int -> TranslateH CoreDef a1) -> TranslateH CoreProg a2 -> ([a1] -> a2 -> b) -> TranslateH CoreProg b+consRecT ts t = progConsT (recT ts id) t --- | Rewrite all children of an expression of the form: (@Rec@ ['CoreDef']) @:@ 'CoreProgram'-consRecAllR :: (Int -> RewriteH CoreDef) -> RewriteH CoreProgram -> RewriteH CoreProgram-consRecAllR rs r = consBindAllR (recAllR rs) r+-- | Rewrite all children of an expression of the form: (@Rec@ ['CoreDef']) @:@ 'CoreProg'+consRecAllR :: (Int -> RewriteH CoreDef) -> RewriteH CoreProg -> RewriteH CoreProg+consRecAllR rs r = progConsAllR (recAllR rs) r --- | Rewrite any children of an expression of the form: (@Rec@ ['CoreDef']) @:@ 'CoreProgram'-consRecAnyR :: (Int -> RewriteH CoreDef) -> RewriteH CoreProgram -> RewriteH CoreProgram-consRecAnyR rs r = consBindAnyR (recAnyR rs) r+-- | Rewrite any children of an expression of the form: (@Rec@ ['CoreDef']) @:@ 'CoreProg'+consRecAnyR :: (Int -> RewriteH CoreDef) -> RewriteH CoreProg -> RewriteH CoreProg+consRecAnyR rs r = progConsAnyR (recAnyR rs) r --- | Rewrite one child of an expression of the form: (@Rec@ ['CoreDef']) @:@ 'CoreProgram'-consRecOneR :: (Int -> RewriteH CoreDef) -> RewriteH CoreProgram -> RewriteH CoreProgram-consRecOneR rs r = consBindOneR (recOneR rs) r+-- | Rewrite one child of an expression of the form: (@Rec@ ['CoreDef']) @:@ 'CoreProg'+consRecOneR :: (Int -> RewriteH CoreDef) -> RewriteH CoreProg -> RewriteH CoreProg+consRecOneR rs r = progConsOneR (recOneR rs) r  --- | Translate an expression of the form: (@Rec@ [('Id', 'CoreExpr')]) @:@ 'CoreProgram'-consRecDefT :: (Int -> TranslateH CoreExpr a1) -> TranslateH CoreProgram a2 -> ([(Id,a1)] -> a2 -> b) -> TranslateH CoreProgram b+-- | Translate an expression of the form: (@Rec@ [('Id', 'CoreExpr')]) @:@ 'CoreProg'+consRecDefT :: (Int -> TranslateH CoreExpr a1) -> TranslateH CoreProg a2 -> ([(Id,a1)] -> a2 -> b) -> TranslateH CoreProg b consRecDefT ts t = consRecT (\ n -> defT (ts n) (,)) t --- | Rewrite all children of an expression of the form: (@Rec@ [('Id', 'CoreExpr')]) @:@ 'CoreProgram'-consRecDefAllR :: (Int -> RewriteH CoreExpr) -> RewriteH CoreProgram -> RewriteH CoreProgram+-- | Rewrite all children of an expression of the form: (@Rec@ [('Id', 'CoreExpr')]) @:@ 'CoreProg'+consRecDefAllR :: (Int -> RewriteH CoreExpr) -> RewriteH CoreProg -> RewriteH CoreProg consRecDefAllR rs r = consRecAllR (\ n -> defR (rs n)) r --- | Rewrite any children of an expression of the form: (@Rec@ [('Id', 'CoreExpr')]) @:@ 'CoreProgram'-consRecDefAnyR :: (Int -> RewriteH CoreExpr) -> RewriteH CoreProgram -> RewriteH CoreProgram+-- | Rewrite any children of an expression of the form: (@Rec@ [('Id', 'CoreExpr')]) @:@ 'CoreProg'+consRecDefAnyR :: (Int -> RewriteH CoreExpr) -> RewriteH CoreProg -> RewriteH CoreProg consRecDefAnyR rs r = consRecAnyR (\ n -> defR (rs n)) r --- | Rewrite one child of an expression of the form: (@Rec@ [('Id', 'CoreExpr')]) @:@ 'CoreProgram'-consRecDefOneR :: (Int -> RewriteH CoreExpr) -> RewriteH CoreProgram -> RewriteH CoreProgram+-- | Rewrite one child of an expression of the form: (@Rec@ [('Id', 'CoreExpr')]) @:@ 'CoreProg'+consRecDefOneR :: (Int -> RewriteH CoreExpr) -> RewriteH CoreProg -> RewriteH CoreProg consRecDefOneR rs r = consRecOneR (\ n -> defR (rs n)) r  --- | Translate an expression of the form: @Let@ (@NonRec@ 'Id' 'CoreExpr') 'CoreExpr'-letNonRecT :: TranslateH CoreExpr a1 -> TranslateH CoreExpr a2 -> (Id -> a1 -> a2 -> b) -> TranslateH CoreExpr b+-- | Translate an expression of the form: @Let@ (@NonRec@ 'Var' 'CoreExpr') 'CoreExpr'+letNonRecT :: TranslateH CoreExpr a1 -> TranslateH CoreExpr a2 -> (Var -> a1 -> a2 -> b) -> TranslateH CoreExpr b letNonRecT t1 t2 f = letT (nonRecT t1 (,)) t2 (uncurry f) --- | Rewrite all children of an expression of the form: @Let@ (@NonRec@ 'Id' 'CoreExpr') 'CoreExpr'+-- | Rewrite all children of an expression of the form: @Let@ (@NonRec@ 'Var' 'CoreExpr') 'CoreExpr' letNonRecAllR :: RewriteH CoreExpr -> RewriteH CoreExpr -> RewriteH CoreExpr letNonRecAllR r1 r2 = letAllR (nonRecR r1) r2 --- | Rewrite any children of an expression of the form: @Let@ (@NonRec@ 'Id' 'CoreExpr') 'CoreExpr'+-- | Rewrite any children of an expression of the form: @Let@ (@NonRec@ 'Var' 'CoreExpr') 'CoreExpr' letNonRecAnyR :: RewriteH CoreExpr -> RewriteH CoreExpr -> RewriteH CoreExpr letNonRecAnyR r1 r2 = letAnyR (nonRecR r1) r2 --- | Rewrite one child of an expression of the form: @Let@ (@NonRec@ 'Id' 'CoreExpr') 'CoreExpr'+-- | Rewrite one child of an expression of the form: @Let@ (@NonRec@ 'Var' 'CoreExpr') 'CoreExpr' letNonRecOneR :: RewriteH CoreExpr -> RewriteH CoreExpr -> RewriteH CoreExpr letNonRecOneR r1 r2 = letOneR (nonRecR r1) r2 @@ -713,9 +766,9 @@ promoteModGutsR :: RewriteH ModGuts -> RewriteH Core promoteModGutsR = promoteWithFailMsgR "This rewrite can only succeed at the module level." --- | Promote a rewrite on 'CoreProgram' to a rewrite on 'Core'.-promoteProgramR :: RewriteH CoreProgram -> RewriteH Core-promoteProgramR = promoteWithFailMsgR "This rewrite can only succeed at program nodes (the top-level)."+-- | Promote a rewrite on 'CoreProg' to a rewrite on 'Core'.+promoteProgR :: RewriteH CoreProg -> RewriteH Core+promoteProgR = promoteWithFailMsgR "This rewrite can only succeed at program nodes (the top-level)."  -- | Promote a rewrite on 'CoreBind' to a rewrite on 'Core'. promoteBindR :: RewriteH CoreBind -> RewriteH Core@@ -739,9 +792,9 @@ promoteModGutsT :: TranslateH ModGuts b -> TranslateH Core b promoteModGutsT = promoteWithFailMsgT "This translate can only succeed at the module level." --- | Promote a translate on 'CoreProgram' to a translate on 'Core'.-promoteProgramT :: TranslateH CoreProgram b -> TranslateH Core b-promoteProgramT = promoteWithFailMsgT "This translate can only succeed at program nodes (the top-level)."+-- | Promote a translate on 'CoreProg' to a translate on 'Core'.+promoteProgT :: TranslateH CoreProg b -> TranslateH Core b+promoteProgT = promoteWithFailMsgT "This translate can only succeed at program nodes (the top-level)."  -- | Promote a translate on 'CoreBind' to a translate on 'Core'. promoteBindT :: TranslateH CoreBind b -> TranslateH Core b
src/Language/HERMIT/Monad.hs view
@@ -6,15 +6,18 @@             HermitM           , runHM           , liftCoreM-          , newVarH-          , newTypeVarH-          , cloneIdH+          , newIdH+          , newTyVarH+    --      , newVarExprH+    --      , newVarH+          , cloneVarH             -- * Saving Definitions           , Label           , DefStash           , saveDef           , lookupDef           , getStash+            -- * Messages           , HermitMEnv(..)           , DebugMessage(..)           , mkHermitMEnv@@ -34,7 +37,7 @@ import Language.KURE.Combinators import Language.KURE.Utilities -import Language.HERMIT.CoreExtra+import Language.HERMIT.Core import Language.HERMIT.Context  ----------------------------------------------------------------------------@@ -49,14 +52,16 @@ newtype HermitMEnv = HermitMEnv { hs_debugChan :: DebugMessage -> HermitM () }  -- | The HERMIT monad is kept abstract.-newtype HermitM a = HermitM (HermitMEnv -> DefStash -> CoreM (KureMonad (DefStash, a)))+newtype HermitM a = HermitM (HermitMEnv -> DefStash -> CoreM (KureM (DefStash, a))) -runHermitM :: HermitM a -> HermitMEnv -> DefStash -> CoreM (KureMonad (DefStash, a))+runHermitM :: HermitM a -> HermitMEnv -> DefStash -> CoreM (KureM (DefStash, a)) runHermitM (HermitM f) = f +-- | Get the stash of saved definitions. getStash :: HermitM DefStash getStash = HermitM (\ _ s -> return $ return (s, s)) +-- | Replace the stash of saved definitions. putStash :: DefStash -> HermitM () putStash s = HermitM (\ _ _ -> return $ return (s, ())) @@ -75,7 +80,7 @@  -- | Eliminator for 'HermitM'. runHM :: HermitMEnv -> DefStash -> (DefStash -> a -> CoreM b) -> (String -> CoreM b) -> HermitM a -> CoreM b-runHM env s success failure ma = runHermitM ma env s >>= runKureMonad (\ (a,b) -> success a b) failure+runHM env s success failure ma = runHermitM ma env s >>= runKureM (\ (a,b) -> success a b) failure  ---------------------------------------------------------------------------- @@ -85,7 +90,7 @@  instance Applicative HermitM where   pure :: a -> HermitM a-  pure  = return+  pure = return    (<*>) :: HermitM (a -> b) -> HermitM a -> HermitM b   (<*>) = ap@@ -95,14 +100,14 @@   return a = HermitM $ \ _ s -> return (return (s,a))    (>>=) :: HermitM a -> (a -> HermitM b) -> HermitM b-  (HermitM gcm) >>= f = HermitM $ \ env -> gcm env >=> runKureMonad (\ (s', a) -> runHermitM (f a) env s') (return . fail)+  (HermitM gcm) >>= f = HermitM $ \ env -> gcm env >=> runKureM (\ (s', a) -> runHermitM (f a) env s') (return . fail)    fail :: String -> HermitM a   fail msg = HermitM $ \ _ _ -> return (fail msg)  instance MonadCatch HermitM where   catchM :: HermitM a -> (String -> HermitM a) -> HermitM a-  (HermitM gcm) `catchM` f = HermitM $ \ env s -> gcm env s >>= runKureMonad (return.return) (\ msg -> runHermitM (f msg) env s)+  (HermitM gcm) `catchM` f = HermitM $ \ env s -> gcm env s >>= runKureM (return.return) (\ msg -> runHermitM (f msg) env s)  ---------------------------------------------------------------------------- @@ -130,39 +135,48 @@ ----------------------------------------------------------------------------  newName :: String -> HermitM Name-newName name = do-        uq <- getUniqueM-        return $ mkSystemVarName uq $ mkFastString $ name+newName name = do uq <- getUniqueM+                  return $ mkSystemVarName uq $ mkFastString name  -- | Make a unique identifier for a specified type based on a provided name.-newVarH :: String -> Type -> HermitM Id-newVarH name ty = do-        name' <- newName name-        return $ mkLocalId name' ty+newIdH :: String -> Type -> HermitM Id+newIdH name ty = do name' <- newName name+                    return $ mkLocalId name' ty  -- | Make a unique type variable for a specified kind based on a provided name.-newTypeVarH :: String -> Kind -> HermitM TyVar-newTypeVarH name kind = do-        name' <- newName name-        return $ mkTyVar name' kind+newTyVarH :: String -> Kind -> HermitM TyVar+newTyVarH name kind = do name' <- newName name+                         return $ mkTyVar name' kind +-- Not sure whether this would be useful or not.+--  Make either a new identifier of a given type, or type variable of a given kind.+--   Note that as 'Id' and 'TyVar' are synonyms of 'Var', and 'Kind' is a synonym of 'Type',+--   the choice is determined entirely by the 'Either' constructor.+-- newVarH :: String -> Either Type Kind -> HermitM Var+-- newVarH name = either (newIdH name) (newTypeVarH name) --- This gives an new version of an Id, with the same info, and a new textual name.-cloneIdH :: (String -> String) -> Id -> HermitM Id-cloneIdH nameMod b =-        let name = nameMod $ getOccString b-            ty   = idType b+--   Make either a new identifier of a given type, or type variable of a given kind,+--   and wrap it in a 'Var' or 'Type' constructor, respectively.+-- newVarExprH :: String -> Either Type Kind -> HermitM CoreExpr+-- newVarExprH str (Left ty) = Var <$> newIdH str ty+-- newVarExprH str (Right k) = (Type . mkTyVarTy) <$> newTypeVarH str k++-- | This gives an new version of a 'Var', with the same info, and a new textual name.+cloneVarH :: (String -> String) -> Var -> HermitM Var+cloneVarH nameMod v =+        let name = nameMod (getOccString v)+            ty   = varType v         in-          if isTyVar b-           then newTypeVarH name ty-           else newVarH name ty+          if isTyVar v+           then newTyVarH name ty+           else newIdH name ty  ----------------------------------------------------------------------------  -- | A message packet. data DebugMessage :: * where         DebugTick    :: String                    -> DebugMessage-        DebugCore    :: String -> Context -> Core -> DebugMessage       -- A postcard+        DebugCore    :: String -> HermitC -> Core -> DebugMessage       -- A postcard  mkHermitMEnv :: (DebugMessage -> HermitM ()) -> HermitMEnv mkHermitMEnv debugger = HermitMEnv
src/Language/HERMIT/Plugin.hs view
@@ -8,9 +8,22 @@ import Data.List import System.IO +import Data.Char (isDigit)+import Data.Default+ -- | Given a list of 'CommandLineOption's, produce the 'ModGuts' to 'ModGuts' function required to build a plugin. type HermitPass = [CommandLineOption] -> ModGuts -> CoreM ModGuts +data Options = Options { pass :: Int }++instance Default Options where+    def = Options { pass = 0 }++parse :: [String] -> Options -> Options+parse (('-':'p':n):rest) o | all isDigit n = parse rest $ o { pass = read n }+parse (_:rest) o = parse rest o -- unknown option+parse [] o       = o+ -- | Build a hermit plugin. This mainly handles the per-module options. hermitPlugin :: HermitPass -> Plugin hermitPlugin hp = defaultPlugin { installCoreToDos = install }@@ -24,17 +37,18 @@              dynFlags <- getDynFlags -            let-                myPass = CoreDoPluginPass "HERMIT" $ modFilter dynFlags hp opts+            let (m_opts, h_opts) = partition (isInfixOf ":") opts+                hermit_opts = parse h_opts def+                myPass = CoreDoPluginPass "HERMIT" $ modFilter dynFlags hp m_opts                 -- at front, for now-                allPasses = myPass : todos+                allPasses = insertAt (pass hermit_opts) myPass todos              return allPasses  -- | Determine whether to act on this module, choose plugin pass. modFilter :: DynFlags -> HermitPass -> HermitPass modFilter dynFlags hp opts guts | null modOpts && not (null opts) = return guts -- don't process this module-                       | otherwise    = hp modOpts guts+                                | otherwise                       = hp modOpts guts     where modOpts = filterOpts dynFlags opts guts  -- | Filter options to those pertaining to this module, stripping module prefix.@@ -42,3 +56,7 @@ filterOpts dynFlags opts guts = [ drop len nm | nm <- opts, modName `isPrefixOf` nm ]     where modName = showPpr dynFlags $ mg_module guts           len = length modName + 1 -- for the colon++insertAt :: Int -> a -> [a] -> [a]+insertAt n x xs = pre ++ (x : suf)+    where (pre,suf) = splitAt n xs
src/Language/HERMIT/PrettyPrinter.hs view
@@ -6,6 +6,7 @@  import Text.PrettyPrint.MarkedHughesPJ as PP import Language.HERMIT.Kure+import Language.HERMIT.Core import Control.Arrow import Data.Monoid hiding ((<>)) import Data.Default@@ -232,7 +233,7 @@ ghcCorePrettyH :: PrettyH Core ghcCorePrettyH =            promoteT (ppModule :: PrettyH ModGuts)-        <+ promoteT (ppH      :: PrettyH CoreProgram)+        <+ promoteT (ppProg   :: PrettyH CoreProg)         <+ promoteT (ppH      :: PrettyH CoreBind)         <+ promoteT (ppDef    :: PrettyH CoreDef)         <+ promoteT (ppH      :: PrettyH CoreExpr)@@ -247,8 +248,11 @@         ppModule :: PrettyH ModGuts         ppModule = mg_module ^>> ppH +        ppProg :: PrettyH CoreProg+        ppProg = progToBinds ^>> ppH+         ppDef :: PrettyH CoreDef-        ppDef = (\ (Def v e) -> (v,e)) ^>> ppH+        ppDef = defToIdExpr ^>> ppH  --        arr (PP.text . ppr . mg_module) 
src/Language/HERMIT/PrettyPrinter/AST.hs view
@@ -8,6 +8,7 @@  import qualified GhcPlugins as GHC import Language.HERMIT.Kure+import Language.HERMIT.Core import Language.HERMIT.PrettyPrinter  import Text.PrettyPrint.MarkedHughesPJ as PP@@ -37,9 +38,10 @@         ppModGuts :: PrettyH GHC.ModGuts         ppModGuts = arr (ppSDoc . GHC.mg_module) -        -- DocH is not a monoid, so we can't use listT here-        ppProgram :: PrettyH GHC.CoreProgram -- CoreProgram = [CoreBind]-        ppProgram = translate $ \ c -> fmap vlist . sequenceA . map (apply ppCoreBind c)+        -- DocH is not a monoid.+        -- GHC uses a list, which we print here. The CoreProg type is our doing.+        ppCoreProg :: PrettyH CoreProg+        ppCoreProg = translate $ \ c -> fmap vlist . sequenceA . map (apply ppCoreBind c) . progToBinds          ppCoreExpr :: PrettyH GHC.CoreExpr         ppCoreExpr = varT (\i -> text "Var" <+> varColor (ppSDoc i))@@ -71,7 +73,7 @@         ppCoreDef = defT ppCoreExpr $ \ i e -> parens $ varColor (ppSDoc i) <> text "," <> e      promoteT (ppCoreExpr :: PrettyH GHC.CoreExpr)-     <+ promoteT (ppProgram  :: PrettyH GHC.CoreProgram)+     <+ promoteT (ppCoreProg :: PrettyH CoreProg)      <+ promoteT (ppCoreBind :: PrettyH GHC.CoreBind)      <+ promoteT (ppCoreDef  :: PrettyH CoreDef)      <+ promoteT (ppModGuts  :: PrettyH GHC.ModGuts)
src/Language/HERMIT/PrettyPrinter/Clean.hs view
@@ -8,9 +8,12 @@  import qualified GhcPlugins as GHC import Language.HERMIT.Kure+import Language.HERMIT.Core import Language.HERMIT.PrettyPrinter import Language.HERMIT.GHC +import TypeRep (TyLit(..))+ import Text.PrettyPrint.MarkedHughesPJ as PP  listify :: (MDoc a -> MDoc a -> MDoc a) -> [MDoc a] -> MDoc a@@ -52,7 +55,7 @@  normalExpr :: RetExpr -> DocH normalExpr (RetLam vs e0) = hang (specialSymbol LambdaSymbol <+> hsep vs <+> specialSymbol RightArrowSymbol) 2 e0-normalExpr (RetLet vs e0) = sep [ keywordColor (text "let") <+> vcat vs, keywordColor (text "in") <+> e0 ]+normalExpr (RetLet vs e0) = sep [ keyword "let" <+> vcat vs, keyword "in" <+> e0 ] normalExpr (RetApp fn xs) = sep [ hsep (fn : map atomExpr (takeWhile isAtom xs))                                 , nest 2 (sep (map atomExpr (dropWhile isAtom xs))) ] normalExpr (RetExpr e0)    = e0@@ -71,26 +74,41 @@      let hideNotes = True +        optional :: Maybe DocH -> (DocH -> DocH) -> DocH+        optional Nothing  _ = empty+        optional (Just d) k = k d+         ppVar :: GHC.Var -> DocH         ppVar = ppName . GHC.varName          ppName :: GHC.Name -> DocH-        ppName nm-                | isInfix name = ppParens $ varColor $ text name-                | otherwise    = varColor $ text name+        ppName = ppName' True++        ppVar' :: Bool -> GHC.Var -> DocH+        ppVar' useVarColor = ppName' useVarColor . GHC.varName++        ppName' :: Bool -> GHC.Name -> DocH+        ppName' useVarColor nm+                | isInfix name = ppParens $ markColor color $ text name+                | otherwise    = markColor color $ text name           where name = GHC.occNameString $ GHC.nameOccName $ nm                 isInfix = all (\ n -> n `elem` "!@#$%^&*-._+=:?/\\<>'")+                color = if useVarColor then VarColor else TypeColor +        ppLitTy :: Bool -> TyLit -> DocH+        ppLitTy useVarColor tylit = markColor color $ text $ case tylit of+                                                                NumTyLit i -> show i+                                                                StrTyLit fs -> show fs+            where color = if useVarColor then VarColor else TypeColor +         -- binders are vars that is bound by lambda or case, etc.         ppBinder :: GHC.Var -> Maybe DocH-        ppBinder var = case po_exprTypes opts of-                        Abstract | GHC.isTyVar var -> Just $ typeBindSymbol-                        Omit     | GHC.isTyVar var -> Nothing-                        _                          -> Just $ ppVar var--        ppIdBinder :: GHC.Id -> DocH-        ppIdBinder var = ppVar var+        ppBinder var | GHC.isTyVar var = case po_exprTypes opts of+                                            Abstract -> Just $ typeBindSymbol+                                            Omit     -> Nothing+                                            _        -> Just $ ppVar' False var+                     | otherwise = Just $ ppVar var          -- Use for any GHC structure, the 'showSDoc' prefix is to remind us         -- that we are eliding infomation here.@@ -101,16 +119,17 @@          ppModGuts :: PrettyH GHC.ModGuts         ppModGuts =   arr $ \ m -> hang (keyword "module" <+> ppSDoc (GHC.mg_module m) <+> keyword "where") 2-                                   (vcat [ (ppIdBinder v <+> specialSymbol TypeOfSymbol <+> ppCoreType (GHC.idType v))+                                   (vcat [ (optional (ppBinder v) (\b -> b <+> specialSymbol TypeOfSymbol <+> ppCoreType True (GHC.idType v)))                                          | bnd <- GHC.mg_binds m                                          , v <- case bnd of                                                   GHC.NonRec f _ -> [f]                                                   GHC.Rec bnds -> map fst bnds                                        ]) -        -- DocH is not a monoid, so we can't use listT here-        ppProgram :: PrettyH GHC.CoreProgram -- CoreProgram = [CoreBind]-        ppProgram = translate $ \ c -> fmap vcat . sequenceA . map (apply ppCoreBind c)+        -- DocH is not a monoid.+        -- GHC uses a list, which we print here. The CoreProg type is our doing.+        ppCoreProg :: PrettyH CoreProg+        ppCoreProg = translate $ \ c -> fmap vcat . sequenceA . map (apply ppCoreBind c) . progToBinds          ppCoreExpr :: PrettyH GHC.CoreExpr         ppCoreExpr = ppCoreExprR >>^ normalExpr@@ -167,27 +186,30 @@                    <+ varT (\ i p -> RetAtom (attrP p $ ppVar i))                    <+ litT (\ i p -> RetAtom (attrP p $ ppSDoc i))                    <+ typeT (\ t p -> case po_exprTypes opts of-                                      Show     -> RetAtom (attrP p $ ppCoreType t)+                                      Show     -> RetAtom (attrP p $ ppCoreType False t)                                       Abstract -> RetAtom (attrP p $ typeSymbol)                                       Omit     -> RetEmpty)                    <+ (ppCoreExpr0 >>^ \ e p -> RetExpr (attrP p e)) -        ppCoreType :: GHC.Type -> DocH-        ppCoreType = normalExpr . go-            where go (TyVarTy v)   = RetAtom $ ppVar v-                  go (AppTy t1 t2) = RetExpr $ ppCoreType t1 <+> ppCoreType t2+        ppCoreType :: Bool -> GHC.Type -> DocH+        ppCoreType isTySig = normalExpr . go+            where go (TyVarTy v)   = RetAtom $ ppVar' isTySig v+                  go (LitTy tylit) = RetAtom $ ppLitTy isTySig tylit+                  go (AppTy t1 t2) = RetExpr $ ppCoreType isTySig t1 <+> ppCoreType isTySig t2                   go (TyConApp tyCon tys)                     | GHC.isFunTyCon tyCon, [ty1,ty2] <- tys = go (FunTy ty1 ty2)-                    | GHC.isTupleTyCon tyCon = case map ppCoreType tys of-                                                [] -> RetAtom $ text "()"-                                                ds -> RetExpr $ text "(" <> (foldr1 (\d r -> d <> text "," <+> r) ds) <> text ")"-                    | otherwise = RetAtom $ ppName (GHC.getName tyCon) <+> sep (map ppCoreType tys) -- has spaces, but we never want parens-                  go (FunTy ty1 ty2) = RetExpr $ atomExpr (go ty1) <+> text "->" <+> ppCoreType ty2-                  go (ForAllTy v ty) = RetExpr $ specialSymbol ForallSymbol <+> ppVar v <+> symbol '.' <+> ppCoreType ty+                    | GHC.isTupleTyCon tyCon = case map (ppCoreType isTySig) tys of+                                                [] -> RetAtom $ tyText "()"+                                                ds -> RetExpr $ tyText "(" <> (foldr1 (\d r -> d <> tyText "," <+> r) ds) <> tyText ")"+                    | otherwise = RetAtom $ ppName' isTySig (GHC.getName tyCon) <+> sep (map (ppCoreType isTySig) tys) -- has spaces, but we never want parens+                  go (FunTy ty1 ty2) = RetExpr $ atomExpr (go ty1) <+> text "->" <+> ppCoreType isTySig ty2+                  go (ForAllTy v ty) = RetExpr $ specialSymbol ForallSymbol <+> ppVar' isTySig v <+> symbol '.' <+> ppCoreType isTySig ty +                  tyText = if isTySig then text else markColor TypeColor . text+         ppCoreExpr0 :: PrettyH GHC.CoreExpr         ppCoreExpr0 = caseT ppCoreExpr (const ppCoreAlt) (\ s b _ty alts ->-                            (keywordColor (text "case") <+> s <+> keywordColor (text "of") <+> ppIdBinder b) $$+                            (keyword "case" <+> s <+> keyword "of" <+> optional (ppBinder b) id) $$                               nest 2 (vcat alts))                   <+ castT ppCoreExpr (\e co -> text "Cast" $$ nest 2 ((parens e) <+> ppSDoc co))                   <+ tickT ppCoreExpr (\i e  -> text "Tick" $$ nest 2 (ppSDoc i <+> parens e))@@ -196,7 +218,7 @@          ppCoreBind :: PrettyH GHC.CoreBind         ppCoreBind = nonRecT ppCoreExprR ppDefFun-                  <+ recT (const ppCoreDef) (\ bnds -> keywordColor (text "rec") <+> vcat bnds)+                  <+ recT (const ppCoreDef) (\ bnds -> keyword "rec" <+> vcat bnds)          ppCoreAlt :: PrettyH GHC.CoreAlt         ppCoreAlt = altT ppCoreExpr $ \ con ids e -> case con of@@ -205,7 +227,7 @@                       GHC.DEFAULT      -> symbol '_' <+> ppIds ids <+> e               where                      ppIds ids | null ids  = specialSymbol RightArrowSymbol-                               | otherwise = hsep (map ppIdBinder ids) <+> specialSymbol RightArrowSymbol+                               | otherwise = hsep (map (flip optional id . ppBinder) ids) <+> specialSymbol RightArrowSymbol          -- GHC uses a tuple, which we print here. The CoreDef type is our doing.         ppCoreDef :: PrettyH CoreDef@@ -216,12 +238,10 @@                         RetLam vs e0 -> hang (pre <+> specialSymbol LambdaSymbol <+> hsep vs <+> specialSymbol RightArrowSymbol) 2 e0                         _ -> hang pre 2 (normalExpr e)             where-                pre = case ppBinder i of-                        Nothing -> empty-                        Just p  -> p <+> symbol '='+                pre = optional (ppBinder i) (<+> symbol '=')      promoteT (ppCoreExpr :: PrettyH GHC.CoreExpr)-     <+ promoteT (ppProgram  :: PrettyH GHC.CoreProgram)+     <+ promoteT (ppCoreProg :: PrettyH CoreProg)      <+ promoteT (ppCoreBind :: PrettyH GHC.CoreBind)      <+ promoteT (ppCoreDef  :: PrettyH CoreDef)      <+ promoteT (ppModGuts  :: PrettyH GHC.ModGuts)
src/Language/HERMIT/PrettyPrinter/GHC.hs view
@@ -7,6 +7,7 @@  import qualified GhcPlugins as GHC import Language.HERMIT.Kure+import Language.HERMIT.Core import Language.HERMIT.PrettyPrinter  import Text.PrettyPrint.MarkedHughesPJ as PP@@ -36,8 +37,8 @@         ppModGuts :: PrettyH GHC.ModGuts         ppModGuts = arr (ppSDoc . GHC.mg_binds) -        ppProgram :: PrettyH GHC.CoreProgram-        ppProgram = arr ppSDoc+        ppCoreProg :: PrettyH CoreProg+        ppCoreProg = arr (ppSDoc . progToBinds)          ppCoreExpr :: PrettyH GHC.CoreExpr         ppCoreExpr = arr ppSDoc@@ -52,7 +53,7 @@         ppCoreDef = defT ppCoreExpr $ \ i e -> ppSDoc i <> text "=" <> e      promoteT (ppCoreExpr :: PrettyH GHC.CoreExpr)-     <+ promoteT (ppProgram  :: PrettyH GHC.CoreProgram)+     <+ promoteT (ppCoreProg :: PrettyH CoreProg)      <+ promoteT (ppCoreBind :: PrettyH GHC.CoreBind)      <+ promoteT (ppCoreDef  :: PrettyH CoreDef)      <+ promoteT (ppModGuts  :: PrettyH GHC.ModGuts)
src/Language/HERMIT/PrettyPrinter/JSON.hs view
@@ -10,6 +10,7 @@  import qualified GhcPlugins as GHC import Language.HERMIT.Kure+import Language.HERMIT.Core import Language.HERMIT.PrettyPrinter  corePrettyH :: PrettyOptions -> TranslateH Core Value@@ -27,9 +28,10 @@         ppModGuts :: TranslateH GHC.ModGuts Value         ppModGuts = arr (ppSDoc . GHC.mg_module) -        -- DocH is not a monoid, so we can't use listT here-        ppProgram :: TranslateH GHC.CoreProgram Value -- CoreProgram = [CoreBind]-        ppProgram = translate $ \ c -> fmap toJSON . mapM (apply ppCoreBind c)+        -- DocH is not a monoid.+        -- GHC uses a list, which we print here. The CoreProg type is our doing.+        ppCoreProg :: TranslateH CoreProg Value+        ppCoreProg = translate $ \ c -> fmap toJSON . mapM (apply ppCoreBind c) . progToBinds          ppCoreExpr :: TranslateH GHC.CoreExpr Value         ppCoreExpr = varT (\i -> object [mkCon "Var", "value" .= ppSDoc i])@@ -62,7 +64,7 @@         ppCoreDef = defT ppCoreExpr $ \ i e -> object [mkCon "CoreDef", "var" .= ppSDoc i, "exp" .= e]      promoteT ppCoreExpr-     <+ promoteT ppProgram+     <+ promoteT ppCoreProg      <+ promoteT ppCoreBind      <+ promoteT ppCoreDef      <+ promoteT ppModGuts
src/Language/HERMIT/Primitive/AlphaConversion.hs view
@@ -1,24 +1,52 @@ {-# LANGUAGE TypeFamilies, FlexibleContexts #-}-module Language.HERMIT.Primitive.AlphaConversion where+module Language.HERMIT.Primitive.AlphaConversion+       ( -- * Alpha-Renaming and Shadowing+         externals+         -- ** Alpha-Renaming+       , alpha+       , alphaLam+       , alphaCaseBinder+       , alphaAltIds+       , alphaAlt+       , alphaCase+       , alphaLetVars+       , alphaLetRecIds+       , alphaLetOne+       , alphaLet+       , alphaConsOne+       , alphaCons+         -- ** Shadow Detection and Unshadowing+       , unshadow+       , visibleVarsT+       , freshNameGenT+       , freshNameGenAvoiding+       , replaceVarR+       )+where  import GhcPlugins hiding (empty) +import Control.Applicative import Control.Arrow import Data.Char (isDigit)-import Data.List (intersect, (\\), nub)+import Data.List (nub)+import Data.Monoid -import Language.HERMIT.Context+import Language.HERMIT.Core import Language.HERMIT.Monad import Language.HERMIT.Kure import Language.HERMIT.External-import Language.HERMIT.Primitive.GHC(freeVarsT, substR) +import Language.HERMIT.Primitive.GHC hiding (externals) import Language.HERMIT.Primitive.Common  import qualified Language.Haskell.TH as TH  import Prelude hiding (exp) +-----------------------------------------------------------------------++-- | Externals for alpha-renaming. externals :: [External] externals = map (.+ Deep)          [  external "alpha" alpha@@ -39,26 +67,19 @@                [ "renames the bound variable in a Let expression with one binder to the given name."]          ,  external "alpha-let" (promoteExprR alphaLet)                [ "renames the bound variables in a Let expression."]-         ,  external "alpha-top" (promoteProgramR . alphaConsOne . Just)+         ,  external "alpha-top" (promoteProgR . alphaConsOne . Just)                [ "renames the bound variable in a top-level binding with one binder to the given name."]-         ,  external "alpha-top" (promoteProgramR alphaCons)+         ,  external "alpha-top" (promoteProgR alphaCons)                [ "renames the bound variables in a top-level binding."]--         , external "shadow-query" (promoteExprT shadowedNamesQuery)-                [ "List variable names shadowed by bindings in this expression." ] .+ Query-         , external "if-shadow" (promoteExprR ifShadowingR)-                [ "succeeds ONLY-IF bindings in this expression shadow free variable name(s)." ]-          , external "unshadow" unshadow-                [ "Rename local variable with manifestly unique names (x, x0, x1, ...)"]-+                [ "Rename local variables with manifestly unique names (x, x0, x1, ...)."]          ]  ----------------------------------------------------------------------- ----- freshNameGen is a function used in conjunction with cloneIdH, which clones an existing Id.+-- freshNameGen is a function used in conjunction with cloneVarH, which clones an existing 'Var'. -- But, what name should the new Id have?--- cloneIdH generates a new Unique -- so we are positive that the new Id will be new,+-- cloneVarH generates a new Unique -- so we are positive that the new Var will be new, -- but freshNameGen tries to assign a Name that will be meaningful to the user, and -- not shadow other names in scope. -- So,  we start with the name of the original Id, and add an integer suffix@@ -67,66 +88,71 @@ -- 1.  Any free variable name in the active Expr; or -- 2.  Any bound variables in context. -visibleIds :: TranslateH CoreExpr [Id]-visibleIds = do ctx <- contextT-                frees <- freeVarsT-                return $ frees ++ (listBindings ctx)+-- | List all visible identifiers (in the expression or the context).+visibleVarsT :: TranslateH CoreExpr [Var]+visibleVarsT = boundVarsT `mappend` freeVarsT -freshNameGen :: (Maybe TH.Name) -> [Id] -> (String -> String)-freshNameGen newName idsToAvoid =-        case newName of-          Just name -> const (show name)-          Nothing   -> inventNames idsToAvoid+-- | If a name is provided replace the string with that,+--   otherwise modify the string making sure to /not/ clash with any visible variables.+freshNameGenT :: Maybe TH.Name -> TranslateH CoreExpr (String -> String)+freshNameGenT mn = freshNameGenAvoiding mn <$> visibleVarsT -freshNameGenT :: (Maybe TH.Name) -> TranslateH CoreExpr (String -> String)-freshNameGenT newName =-        case newName of-          Just name -> return $ const (show name)-          Nothing -> do idsToAvoid <- visibleIds-                        return $ freshNameGen Nothing idsToAvoid+-- | A generalisation of 'freshNameGen' that operates on any node, but only avoids name clashes with the results of the argument translation.+freshNameGenAvoiding :: Maybe TH.Name -> [Var] -> (String -> String)+freshNameGenAvoiding mn vs str = maybe (inventNames vs str) TH.nameBase mn -inventNames :: [Id] -> String -> String+-- | Invent a new String based on the old one, but avoiding clashing with the given list of identifiers.+inventNames :: [Var] -> String -> String inventNames curr old = head                      [ nm                      | nm <- old : [ base ++ show uq | uq <- [start ..] :: [Int] ]                      , nm `notElem` names                      ]    where-           names = map getOccString curr+           names = nub (map getOccString curr)            nums = reverse $ takeWhile isDigit (reverse old)            baseLeng = length $ drop (length nums) old            base = take baseLeng old            start = case reads nums of-                     [(v,_)] -> (v + 1)-                     _ -> 0+                     [(v,_)] -> v + 1+                     _       -> 0 -shadowedNamesT :: TranslateH CoreExpr [String]-shadowedNamesT = do ctx         <- contextT-                    frees       <- freeVarsT-                    bindingIds  <- extractT bindingVarsT-                    let shadows = intersect (map getOccString bindingIds)-                                            (map getOccString (frees ++ (listBindings ctx)))-                    return        shadows --- | Output a list of all variables that shadowed by bindings in the is expression.-shadowedNamesQuery :: TranslateH CoreExpr String-shadowedNamesQuery = shadowedNamesT >>^ (("Names shadowed by bindings in the current expression: " ++) . show)+-- | Remove all variables from the first list that shadow a variable in the second list.+shadowedBy :: [Var] -> [Var] -> [Var]+shadowedBy vs fvs = filter (\ v -> getOccString v `elem` map getOccString fvs) vs -ifShadowingR :: RewriteH CoreExpr-ifShadowingR = do shadows <- shadowedNamesT-                  case shadows of-                    [] -> fail "Bindings at this node do not shadow."-                    _  -> idR+-- | Lifted version of 'shadowedBy'.+--   Additionally, it fails if no shadows are found.+shadowedByT :: TranslateH a [Var] -> TranslateH a [Var] -> TranslateH a [Var]+shadowedByT t1 t2 = (shadowedBy <$> t1 <*> t2) >>> acceptR (not . null) "No shadowing detected." --- | Arguments are the original identifier and the replacement identifier, respectively.-renameIdR :: (Injection a Core, Generic a ~ Core) => Id -> Id -> RewriteH a-renameIdR v v' = extractR $ tryR $ substR v (Var v')+-- | Rename local variables with manifestly unique names (x, x0, x1, ...).+--   Does not rename top-level definitions (though this may change in the future).+unshadow :: RewriteH Core+unshadow = setFailMsg "No shadows to eliminate." $+           anytdR (promoteExprR unshadowExpr <+ promoteAltR unshadowAlt) --- | Given an identifier to replace, and a replacement, produce an 'Id' @->@ 'Id' function that---   acts as in identity for all 'Id's except the one to replace, for which it returns the replacment.+  where+    unshadowExpr :: RewriteH CoreExpr+    unshadowExpr = do vs <- shadowedByT (boundVarsT `mappend` freeVarsT) (letVarsT <+ fmap return (caseWildVarT <+ lamVarT))+                      alphaLam Nothing <+ alphaLetRecIds vs <+ alphaLetNonRec Nothing <+ alphaCaseBinder Nothing++    unshadowAlt :: RewriteH CoreAlt+    unshadowAlt = shadowedByT altVarsT (boundVarsT `mappend` altFreeVarsT) >>= alphaAltIds++-----------------------------------------------------------------------++-- | Replace all occurrences of a specified variable.+--   Arguments are the variable to replace and the replacement variable, respectively.+replaceVarR :: (Injection a Core, Generic a ~ Core) => Var -> Var -> RewriteH a+replaceVarR v v' = extractR $ tryR $ substR v (Var v')++-- | Given a variable to replace, and a replacement, produce a 'Var' @->@ 'Var' function that+--   acts as in identity for all 'Var's except the one to replace, for which it returns the replacment. --   Don't export this, it'll likely just cause confusion.-replaceId :: Id -> Id -> (Id -> Id)-replaceId v v' i = if v == i then v' else i+replaceVar :: Var -> Var -> (Var -> Var)+replaceVar v v' i = if v == i then v' else i  ----------------------------------------------------------------------- @@ -134,8 +160,8 @@ alphaLam :: Maybe TH.Name -> RewriteH CoreExpr alphaLam mn = setFailMsg (wrongFormForAlpha "Lam v e") $               do (v, nameModifier) <- lamT (freshNameGenT mn) (,)-                 v' <- constT (cloneIdH nameModifier v)-                 lamT (renameIdR v v') (\ _ -> Lam v')+                 v' <- constT (cloneVarH nameModifier v)+                 lamT (replaceVarR v v') (\ _ -> Lam v')  ----------------------------------------------------------------------- @@ -144,22 +170,24 @@ alphaCaseBinder mn = setFailMsg (wrongFormForAlpha "Case e v ty alts") $                      do Case _ v _ _ <- idR                         nameModifier <- freshNameGenT mn-                        v' <- constT (cloneIdH nameModifier v)-                        caseT idR (\ _ -> renameIdR v v') (\ e _ t alts -> Case e v' t alts)+                        v' <- constT (cloneVarH nameModifier v)+                        caseT idR (\ _ -> replaceVarR v v') (\ e _ t alts -> Case e v' t alts)  -----------------------------------------------------------------------  -- | Rename the specified identifier in a case alternative.  Optionally takes a suggested new name. alphaAltId :: Maybe TH.Name -> Id -> RewriteH CoreAlt alphaAltId mn v = do nameModifier <- altT (freshNameGenT mn) (\ _ _ nameGen -> nameGen)-                     v' <- constT (cloneIdH nameModifier v)-                     altT (renameIdR v v') (\ con vs e -> (con, map (replaceId v v') vs, e))+                     v' <- constT (cloneVarH nameModifier v)+                     altT (replaceVarR v v') (\ con vs e -> (con, map (replaceVar v v') vs, e)) +-- | Rename the specified identifiers in a case alternative.+alphaAltIds :: [Id] -> RewriteH CoreAlt+alphaAltIds = andR . map (alphaAltId Nothing)+ -- | Rename all identifiers bound in a case alternative. alphaAlt :: RewriteH CoreAlt-alphaAlt = setFailMsg (wrongFormForAlpha "(con,vs,e)") $-           do (_, vs, _) <- idR-              andR $ map (alphaAltId Nothing) vs+alphaAlt = altVarsT >>= alphaAltIds  ----------------------------------------------------------------------- @@ -173,30 +201,36 @@ alphaLetNonRec :: Maybe TH.Name -> RewriteH CoreExpr alphaLetNonRec mn = setFailMsg (wrongFormForAlpha "Let (NonRec v e1) e2") $                     do (v, nameModifier) <- letNonRecT idR (freshNameGenT mn) (\ v _ nameMod -> (v, nameMod))-                       v' <- constT (cloneIdH nameModifier v)-                       letNonRecT idR (renameIdR v v') (\ _ e1 e2 -> Let (NonRec v' e1) e2)+                       v' <- constT (cloneVarH nameModifier v)+                       letNonRecT idR (replaceVarR v v') (\ _ e1 e2 -> Let (NonRec v' e1) e2) +-- | Alpha rename a non-recursive let binder if the variable appears in the argument list.  Optionally takes a suggested new name.+alphaLetNonRecVars :: Maybe TH.Name -> [Var] -> RewriteH CoreExpr+alphaLetNonRecVars mn vs = whenM ((`elem` vs) <$> letNonRecVarT) (alphaLetNonRec mn)+ -- | Rename the specified identifier bound in a recursive let.  Optionally takes a suggested new name. alphaLetRecId :: Maybe TH.Name -> Id -> RewriteH CoreExpr alphaLetRecId mn v = setFailMsg (wrongFormForAlpha "Let (Rec bs) e") $-                     do Let (Rec {}) _ <- idR-                        ctx <- contextT-                         -- Cannot use freshNameGen directly, because we want to include-                         -- free variables from every bound expression, in the name generation function-                         -- as a result we must replicate the essence of freshNameGen in the next few lines-                        frees <- letRecDefT (\ _ -> freeVarsT) freeVarsT (\ bindFrees exprFrees -> (concat (map snd bindFrees)) ++ exprFrees)-                        let nameGen = case mn of-                                        Just name -> const (show name)-                                        Nothing -> inventNames (frees ++ (listBindings ctx))-                        v' <- constT (cloneIdH nameGen v)+                     do usedVars <- boundVarsT `mappend`+                                    letVarsT  `mappend`+                                    letRecDefT (\ _ -> freeVarsT) freeVarsT (\ bndfvs vs -> concatMap snd bndfvs ++ vs)+                        v' <- constT (cloneVarH (freshNameGenAvoiding mn usedVars) v)+                        letRecDefT (\ _ -> replaceVarR v v')+                                   (replaceVarR v v')+                                   (\ bs e -> Let (Rec $ (map.first) (replaceVar v v') bs) e) -                        letRecDefT (\ _ -> renameIdR v v') (renameIdR v v') (\ bs e -> Let (Rec $ (map.first) (replaceId v v') bs) e)+-- | Rename the specified identifiers bound in a recursive let.+alphaLetRecIds :: [Id] -> RewriteH CoreExpr+alphaLetRecIds = andR . map (alphaLetRecId Nothing) +-- | Rename the specified variables bound in a let.+alphaLetVars :: [Var] -> RewriteH CoreExpr+alphaLetVars vs = alphaLetNonRecVars Nothing vs <+ alphaLetRecIds vs+ -- | Rename all identifiers bound in a recursive let. alphaLetRec :: RewriteH CoreExpr alphaLetRec = setFailMsg (wrongFormForAlpha "Let (Rec bs) e") $-              do Let (Rec bs) _ <- idR-                 andR $ map (alphaLetRecId Nothing . fst) bs+              letRecVarsT >>= alphaLetRecIds  -- | Rename the identifier bound in a recursive let with a single recursively bound identifier.  Optionally takes a suggested new name. alphaLetRecOne :: Maybe TH.Name -> RewriteH CoreExpr@@ -215,47 +249,45 @@ -----------------------------------------------------------------------  -- | Alpha rename a non-recursive top-level binder.  Optionally takes a suggested new name.-alphaConsNonRec :: Maybe TH.Name -> RewriteH CoreProgram-alphaConsNonRec mn = setFailMsg (wrongFormForAlpha "NonRec v e : prog") $-                     do NonRec v _ : _ <- idR+alphaConsNonRec :: Maybe TH.Name -> RewriteH CoreProg+alphaConsNonRec mn = setFailMsg (wrongFormForAlpha "ProgCons (NonRec v e) p") $+                     do ProgCons (NonRec v _) _ <- idR                         nameModifier <- consNonRecT (freshNameGenT mn) idR (\ _ nameGen _ -> nameGen)-                        v' <- constT (cloneIdH nameModifier v)-                        consNonRecT idR (renameIdR v v') (\ _ e1 e2 -> NonRec v' e1 : e2)+                        v' <- constT (cloneVarH nameModifier v)+                        consNonRecT idR (replaceVarR v v') (\ _ e1 e2 -> ProgCons (NonRec v' e1) e2)  -- | Rename the specified identifier bound in a recursive top-level binder.  Optionally takes a suggested new name.-alphaConsRecId :: Maybe TH.Name -> Id -> RewriteH CoreProgram-alphaConsRecId mn v = setFailMsg (wrongFormForAlpha "Rec bs : prog") $-                      do rbs@(Rec _) : _ <- idR-                         -- Cannot use freshNameGen directly, because we want to include-                         -- free variables from every bound expression, in the name generation function-                         -- as a result we must replicate the essence of freshNameGen in the next few lines-                         ctx <- contextT-                         frees <- consRecDefT (\ _ -> freeVarsT) idR (\ frees _ -> concat (map snd frees))-                         let idsToAvoid = ((nub frees) \\ (bindings rbs)) ++ (listBindings ctx)-                             nameGen = case mn of-                                         Just name -> const (show name)-                                         Nothing -> inventNames idsToAvoid-                         v' <- constT (cloneIdH nameGen v)-                         consRecDefT (\ _ -> renameIdR v v') (renameIdR v v') (\ bs e -> Rec ((map.first) (replaceId v v') bs) : e)+alphaConsRecId :: Maybe TH.Name -> Id -> RewriteH CoreProg+alphaConsRecId mn v = setFailMsg (wrongFormForAlpha "ProgCons (Rec bs) p") $+                      do usedVars <- boundVarsT `mappend`+                                     progConsT recVarsT (return ()) (\ vs () -> vs) `mappend`+                                     consRecDefT (\ _ -> freeVarsT) idR (\ bndfvs _ -> concatMap snd bndfvs)+                         v' <- constT (cloneVarH (freshNameGenAvoiding mn usedVars) v)+                         consRecDefT (\ _ -> replaceVarR v v')+                                     (replaceVarR v v')+                                     (\ bs e -> ProgCons (Rec $ (map.first) (replaceVar v v') bs) e) +-- | Rename the specified identifiers bound in a program node containing a recursive binding group.+alphaConsRecIds :: [Id] -> RewriteH CoreProg+alphaConsRecIds = andR . map (alphaConsRecId Nothing)+ -- | Rename all identifiers bound in a recursive top-level binder.-alphaConsRec :: RewriteH CoreProgram-alphaConsRec = setFailMsg (wrongFormForAlpha "Rec bs : prog") $-               do Rec bs : _ <- idR-                  andR $ map (alphaConsRecId Nothing . fst) bs+alphaConsRec :: RewriteH CoreProg+alphaConsRec = setFailMsg (wrongFormForAlpha "ProgCons (Rec bs) p") $+               progConsT recVarsT mempty (\ vs () -> vs) >>= alphaConsRecIds  -- | Rename the identifier bound in a recursive top-level binder with a single recursively bound identifier.  Optionally takes a suggested new name.-alphaConsRecOne :: Maybe TH.Name -> RewriteH CoreProgram-alphaConsRecOne mn = setFailMsg (wrongFormForAlpha "Rec [(v,e)] : prog") $-                     do Rec [(v, _)] : _ <- idR+alphaConsRecOne :: Maybe TH.Name -> RewriteH CoreProg+alphaConsRecOne mn = setFailMsg (wrongFormForAlpha "ProgCons (Rec [Def v e]) p") $+                     do ProgCons (Rec [(v, _)]) _ <- idR                         alphaConsRecId mn v  -- | Rename the identifier bound in a top-level binder with a single bound identifier.  Optionally takes a suggested new name.-alphaConsOne :: Maybe TH.Name -> RewriteH CoreProgram+alphaConsOne :: Maybe TH.Name -> RewriteH CoreProg alphaConsOne mn = alphaConsNonRec mn <+ alphaConsRecOne mn  -- | Rename all identifiers bound in a Let.-alphaCons :: RewriteH CoreProgram+alphaCons :: RewriteH CoreProg alphaCons = alphaConsRec <+ alphaConsNonRec Nothing  -----------------------------------------------------------------------@@ -264,13 +296,12 @@ alpha :: RewriteH Core alpha = setFailMsg "Cannot alpha-rename here." $            promoteExprR (alphaLam Nothing <+ alphaCaseBinder Nothing <+ alphaLet)-        <+ promoteProgramR alphaCons--unshadow :: RewriteH Core-unshadow = setFailMsg "No shadows to eliminate." $-           anytdR (promoteExprR (ifShadowingR >>> (alphaLam Nothing <+ alphaCase <+ alphaLet)))+        <+ promoteProgR alphaCons+        <+ promoteAltR alphaAlt  -----------------------------------------------------------------------  wrongFormForAlpha :: String -> String-wrongFormForAlpha s = "Cannot alpha-rename: " ++ wrongExprForm s+wrongFormForAlpha s = "Cannot alpha-rename, " ++ wrongExprForm s++-----------------------------------------------------------------------
src/Language/HERMIT/Primitive/Common.hs view
@@ -1,94 +1,135 @@-{-# LANGUAGE MultiParamTypeClasses, TypeFamilies, FlexibleInstances, FlexibleContexts, TupleSections #-}- -- | Note: this module should NOT export externals. It is for common --   transformations needed by the other primitive modules. module Language.HERMIT.Primitive.Common-    ( altFreeVarsT-    , bindings-    , bindingVarsT-    , caseAltVarsT-    , caseBinderVarT+    ( -- * Utility Transformations+      -- ** Collecting variables bound at a Node+      progVarsT+    , bindVarsT+    , nonRecVarT+    , recVarsT+    , defVarT+    , lamVarT     , letVarsT+    , letRecVarsT+    , letNonRecVarT+    , caseVarsT+    , caseWildVarT+    , caseAltVarsT+    , altVarsT+      -- ** Finding variables bound in the Context+    , boundVarsT+    , findBoundVarT+    , findIdT+      -- ** Error Message Generators     , wrongExprForm-    ) where+    ) -import GhcPlugins+where -import Control.Arrow+import GhcPlugins  import Data.List import Data.Monoid  import Language.HERMIT.Kure--import Language.HERMIT.Primitive.GHC+import Language.HERMIT.Core+import Language.HERMIT.Context+import Language.HERMIT.GHC +import qualified Language.Haskell.TH as TH -class BindEnv a where-    bindings :: a -> [Id]+------------------------------------------------------------------------------ --- | All the identifiers bound in this binding group.-instance BindEnv  CoreBind where-    bindings (NonRec b _) = [b]-    bindings (Rec bs)     = map fst bs+-- | List all identifiers bound at the top-level in a program.+progVarsT :: TranslateH CoreProg [Id]+progVarsT = progNilT [] <+ progConsT bindVarsT progVarsT (++) -instance BindEnv CoreAlt where-    bindings (_,vs,_) = vs+-- | List all identifiers bound in a binding group.+bindVarsT :: TranslateH CoreBind [Var]+bindVarsT = fmap return nonRecVarT <+ recVarsT -instance BindEnv CoreExpr where-    bindings (Lam b _)          = [b]-    bindings (Let bs _)         = bindings bs-    bindings (Case _ sc _ alts) = sc : (nub (concat (map bindings alts)))-    bindings _                  = []+-- | Return the variable bound by a non-recursive let expression.+nonRecVarT :: TranslateH CoreBind Var+nonRecVarT = nonRecT mempty (\ v () -> v) -instance BindEnv CoreProgram where-    bindings prog = nub (concat (map bindings prog))+-- | List all identifiers bound in a recursive binding group.+recVarsT :: TranslateH CoreBind [Id]+recVarsT = recT (\ _ -> defVarT) id -instance BindEnv CoreDef  where-    bindings (Def b _) = [b]+-- | Return the identifier bound by a recursive definition.+defVarT :: TranslateH CoreDef Id+defVarT = defT mempty (\ v () -> v) -bindingVarsT :: TranslateH Core [Var]-bindingVarsT = translate $ \ c core -> case core of-          ModGutsCore _ -> fail "Cannot get binding vars at topmost level"-          ProgramCore x -> apply (promoteT ((arr bindings) :: TranslateH CoreProgram [Var])) c x-          BindCore x    -> apply (promoteT ((arr bindings) :: TranslateH CoreBind [Var])) c x-          DefCore x     -> apply (promoteT ((arr bindings) :: TranslateH CoreDef [Var])) c x-          ExprCore x    -> apply (promoteT ((arr bindings) :: TranslateH CoreExpr [Var])) c x-          AltCore x     -> apply (promoteT ((arr bindings) :: TranslateH CoreAlt [Var])) c x+-- | Return the variable bound by a lambda expression.+lamVarT :: TranslateH CoreExpr Var+lamVarT = lamT mempty (\ v () -> v) --- TODO.  Isn't there a better way to handle this ?--- Although the work of this Translate is handled by bindingVarsT--- This implementation fails for any expression that is not a Let.--- This specific argument matching is required where it is used in Local/Let.hs and Local/Case.hs+-- | List the variables bound by a let expression. letVarsT :: TranslateH CoreExpr [Var]-letVarsT = setFailMsg "Not a Let expression." $-           do Let bs _ <- idR-              return (bindings bs)+letVarsT = letT bindVarsT mempty (\ vs () -> vs) --- | List of the list of Ids bound by each case alternative-caseAltVarsT :: TranslateH CoreExpr [[Id]]-caseAltVarsT = caseT mempty (const (extractT bindingVarsT)) $ \ () _ _ vs -> vs+-- | List the variables bound by a recursive let expression.+letRecVarsT :: TranslateH CoreExpr [Var]+letRecVarsT = letT recVarsT mempty (\ vs () -> vs) --- | List of the list of Ids bound by each case alternative, including the Case binder in each list-caseAltVarsWithBinderT :: TranslateH CoreExpr [[Id]]-caseAltVarsWithBinderT = caseT mempty (const (extractT bindingVarsT)) $ \ () v _ vs -> map (v:) vs+-- | Return the variable bound by a non-recursive let expression.+letNonRecVarT :: TranslateH CoreExpr Var+letNonRecVarT = letT nonRecVarT mempty (\ v () -> v) --- | list containing the single Id of the case binder-caseBinderVarT :: TranslateH CoreExpr [Id]-caseBinderVarT = setFailMsg "Not a Case expression." $-                 do Case _ b _ _ <- idR-                    return [b]+-- | List all variables bound by a case expression (in the alternatives and the wildcard binder).+caseVarsT :: TranslateH CoreExpr [Var]+caseVarsT = caseT mempty (\ _ -> altVarsT) (\ () v _ vss -> v : nub (concat vss)) --- | Free variables for a CoreAlt, returns a function, which accepts---   the coreBndr name, before giving a result.---   This is so we can use this with congruence combinators:------   caseT id (const altFreeVarsT) $ \ _ bndr _ fs -> [ f bndr | f <- fs ]-altFreeVarsT :: TranslateH CoreAlt (Id -> [Var])-altFreeVarsT = altT freeVarsT $ \ _con ids frees coreBndr -> nub frees \\ nub (coreBndr : ids)+-- | Return the case wildcard binder.+caseWildVarT :: TranslateH CoreExpr Var+caseWildVarT = caseT mempty (\ _ -> return ()) (\ () v _ _ -> v) +-- | List the variables bound by all alternatives in a case expression.+caseAltVarsT :: TranslateH CoreExpr [[Var]]+caseAltVarsT = caseT mempty (\ _ -> altVarsT) (\ () _ _ vss -> vss)++-- | List the variables bound by a case alternative.+altVarsT :: TranslateH CoreAlt [Var]+altVarsT = altT mempty (\ _ vs () -> vs)+ ------------------------------------------------------------------------------ +-- Need a better error type so that we can factor out the repetition.++-- | Lifted version of 'boundVars'.+boundVarsT :: TranslateH a [Var]+boundVarsT = contextonlyT (return . boundVars)++-- | Find the unique variable bound in the context that matches the given name, failing if it is not unique.+findBoundVarT :: TH.Name -> TranslateH a Var+findBoundVarT nm = prefixFailMsg ("Cannot resolve name " ++ TH.nameBase nm ++ ", ") $+                        do c <- contextT+                           case findBoundVars nm c of+                             []         -> fail "no matching variables in scope."+                             [v]        -> return v+                             _ : _ : _  -> fail "multiple matching variables in scope."++-- | Lookup the name in the 'HermitC' first, then, failing that, in GHC's global reader environment.+findIdT :: TH.Name -> TranslateH a Id+findIdT nm = prefixFailMsg ("Cannot resolve name " ++ TH.nameBase nm ++ ", ") $+             do c <- contextT+                case findBoundVars nm c of+                  []         -> findIdMG nm+                  [v]        -> return v+                  _ : _ : _  -> fail "multiple matching variables in scope."++findIdMG :: TH.Name -> TranslateH a Id+findIdMG nm = contextonlyT $ \ c ->+    case filter isValName $ findNameFromTH (mg_rdr_env $ hermitModGuts c) nm of+      []  -> fail $ "variable not in scope."+      [n] -> lookupId n+      ns  -> do dynFlags <- getDynFlags+                fail $ "multiple matches found:\n" ++ intercalate ", " (map (showPpr dynFlags) ns)++------------------------------------------------------------------------------++-- | Constructs a common error message.+--   Argument 'String' should be the desired form of the expression. wrongExprForm :: String -> String wrongExprForm form = "Expression does not have the form: " ++ form 
src/Language/HERMIT/Primitive/Debug.hs view
@@ -8,6 +8,7 @@        ) where +import Language.HERMIT.Core import Language.HERMIT.Kure import Language.HERMIT.External import Language.HERMIT.Monad
+ src/Language/HERMIT/Primitive/FixPoint.hs view
@@ -0,0 +1,214 @@+module Language.HERMIT.Primitive.FixPoint where++import GhcPlugins as GHC hiding (varName)++import Control.Arrow++import Language.HERMIT.Core+import Language.HERMIT.Monad+import Language.HERMIT.Kure+import Language.HERMIT.External+import Language.HERMIT.GHC+import Language.HERMIT.Primitive.GHC+import Language.HERMIT.Primitive.Common+import Language.HERMIT.Primitive.Local+import Language.HERMIT.Primitive.AlphaConversion+import Language.HERMIT.Primitive.New -- TODO: Sort out heirarchy++import qualified Language.Haskell.TH as TH+++externals ::  [External]+externals = map ((.+ Experiment) . (.+ TODO))+         [ external "fix-intro" (promoteDefR fixIntro :: RewriteH Core)+                [ "rewrite a recursive binding into a non-recursive binding using fix" ]+         , external "fix-spec" (promoteExprR fixSpecialization :: RewriteH Core)+                [ "specialize a fix with a given argument"] .+ Shallow+         , external "ww-fac-test" ((\ wrap unwrap -> promoteExprR $ workerWrapperFacTest wrap unwrap) :: TH.Name -> TH.Name -> RewriteH Core)+                [ "Under construction "+                ] .+ Introduce .+ Context .+ Experiment .+ PreCondition+         , external "ww-split-test" ((\ wrap unwrap -> promoteDefR $ workerWrapperSplitTest wrap unwrap) :: TH.Name -> TH.Name -> RewriteH Core)+                [ "Under construction "+                ] .+ Introduce .+ Context .+ Experiment .+ PreCondition+         ]++fixLocation :: String+fixLocation = "Data.Function.fix"++findFixId :: TranslateH a Id+findFixId = findIdT (TH.mkName fixLocation)++guardIsFixId :: Id -> TranslateH a ()+guardIsFixId v = do fixId <- findFixId+                    guardMsg (v == fixId) (var2String v ++ " does not match " ++ fixLocation)+++-- |  f = e   ==>   f = fix (\ f -> e)+fixIntro :: RewriteH CoreDef+fixIntro = prefixFailMsg "Fix introduction failed: " $+           do Def f e <- idR+              fixId   <- findFixId+              constT $ do f' <- cloneVarH id f+                          let coreFix  = App (App (Var fixId) (Type (idType f)))+                              emptySub = mkEmptySubst (mkInScopeSet (exprFreeVars e))+                              sub      = extendSubst emptySub f (Var f')+                          return $ Def f (coreFix (Lam f' (substExpr (text "fixIntro") sub e)))++-- ironically, this is an instance of worker/wrapper itself.++fixSpecialization :: RewriteH CoreExpr+fixSpecialization = do++        -- fix (t::*) (f :: t -> t) (a :: t) :: t+        App (App (App (Var fixId) (Type _)) _) _ <- idR -- TODO: couldn't that Type be a Var?  Might be better to use my "isType" fucntion.++        guardIsFixId fixId -- guardMsg (fx == fixId) "fixSpecialization only works on fix"++        let rr :: RewriteH CoreExpr+            rr = multiEtaExpand [TH.mkName "f",TH.mkName "a"]++            sub :: RewriteH Core+            sub = pathR [0,1] (promoteR rr)+        -- be careful this does not loop (it should not)+        extractR sub >>> fixSpecialization'+++fixSpecialization' :: RewriteH CoreExpr+fixSpecialization' =+     do+        -- In normal form now+        App (App (App (Var fx) fixTyE)+                 (Lam _ (Lam v2 (App (App e _) _a2)))+            )+            a <- idR++        t  <- case typeExprToType fixTyE of+                Nothing -> fail "first argument to fix is not a type, this shouldn't have happened."+                Just ty -> return ty++        t' <- case typeExprToType a of+                Just t2           -> return (applyTy t t2)+                Nothing           -> fail "Not a type variable." -- TODO:  I think this entire functions needs revisiting and cleaning up.  What's going on with all the dead-code (which I've commented out now).+--                   Var  a2  -> mkAppTy t (exprType t2)+--                   mkAppTy t t'+++        -- TODO: t2' isn't used anywhere -- which means that a2 is never used ???+--        let t2' = case a2 of+--                   Type t2  -> applyTy t t2+--                   Var  a2  -> mkAppTy t (exprType t2)+--                   mkAppTy t t'+++        v3 <- constT $ newIdH "f" t' -- (funArgTy t')+        v4 <- constT $ newTyVarH "a" (tyVarKind v2)++         -- f' :: \/ a -> T [a] -> (\/ b . T [b])+        let f' = Lam v4  (Cast (Var v3)+                               (mkUnsafeCo t' (applyTy t (mkTyVarTy v4))))+        let e' = Lam v3 (App (App e f') a)++        return $ App (App (Var fx) (Type t')) e'+++-- introSpecialisedPolyFun :: TH.Name -> TH.Name -> RewriteH CoreExpr+-- introSpecialisedPolyFun funNm ty = do funId <- lookupMatchingVarT funNm+--                                       tyVar <- lookupMatchingVarT ty++++workerWrapperFacTest :: TH.Name -> TH.Name -> RewriteH CoreExpr+workerWrapperFacTest wrapNm unwrapNm = do wrapId   <- findBoundVarT wrapNm+                                          unwrapId <- findBoundVarT unwrapNm+                                          monomorphicWorkerWrapperFac (Var wrapId) (Var unwrapId)++workerWrapperSplitTest :: TH.Name -> TH.Name -> RewriteH CoreDef+workerWrapperSplitTest wrapNm unwrapNm = do wrapId   <- findBoundVarT wrapNm+                                            unwrapId <- findBoundVarT unwrapNm+                                            monomorphicWorkerWrapperSplit (Var wrapId) (Var unwrapId)+++-- monomorphicWorkerWrapperFac :: Id -> Id -> RewriteH CoreExpr+-- monomorphicWorkerWrapperFac wrapId unwrapId = -- let wrapTy   = idType wrapId+--                                               --     unwrapTy = idType unwrapId+--                                               --     (wrapForallTyVars, wrapMainTy)     = splitForAllTys wrapTy+--                                               --     (unwrapForallTyVars, unwrapMainTy) = splitForAllTys unwrapTy++--                                               -- in  -- In progress: above are not used yet.+--                                                   workerWrapperFac (Var wrapId) (Var unwrapId)+--                                                 -- workerWrapperFac (mkTyApps (Var wrapId)   wrapForallTys)+--                                                 --                  (mkTyApps (Var unwrapId) unwrapForallTys)++-- workerWrapperFac (Var wrapId) (Var unwrapId)+-- splitForAllTys :: Type -> ([TyVar], Type)++-- monomorphicWorkerWrapperSplit :: Id -> Id -> RewriteH CoreDef+-- monomorphicWorkerWrapperSplit wrapId unwrapId = workerWrapperSplit (Var wrapId) (Var unwrapId)++-- substTyWith :: [TyVar] -> [Type] -> Type -> Type+-- mkTyApps  :: Expr b -> [Type]   -> Expr b++-- I assume there are GHC functions to do this, but I can't find them.+-- in progress+-- unifyTyVars :: [TyVar] -- | forall quantified type variables+--             -> Type    -- | type containing forall quantified type variables+--             -> Type    -- | type to unify with+--             -> Maybe [Type]  -- | types that the variables have been unified with+-- unifyTyVars vs tyGen tySpec = let unifyTyVarsAux tyGen tySpec vs+--                                in undefined+--   unifyTyVarsAux :: Type -> Type -> [(TyVar,[Type])] -> Maybe [(TyVar,[Type])]+--   unifyTyVarsAux (TyVarTy v)   t             = match v t+--   unifyTyVarsAux (AppTy s1 s2) (AppTy t1 t2) = match s1 t1 . match s2 t2+++-- f      :: a -> a+-- wrap   :: forall x,y..z. b -> a+-- unwrap :: forall p,q..r. a -> b+-- fix tyA f ==> wrap (fix tyB (\ x -> unwrap (f (wrap (Var x)))))+-- Assumes the arguments are monomorphic functions (all type variables have alread been applied)+monomorphicWorkerWrapperFac :: CoreExpr -> CoreExpr -> RewriteH CoreExpr+monomorphicWorkerWrapperFac wrapE unwrapE =+  prefixFailMsg "Worker/wrapper Factorisation failed: " $+  withPatFailMsg (wrongExprForm "fix type fun") $+  do App (App (Var fixId) fixTyE) f <- idR  -- fix :: forall a. (a -> a) -> a+     guardIsFixId fixId+     case typeExprToType fixTyE of+       Nothing  -> fail "first argument to fix is not a type, this shouldn't have happened."+       Just tyA -> case splitFunTy_maybe (exprType wrapE) of+           Nothing            -> fail "type of wrapper is not a function."+           Just (tyB,wrapTyA) -> case splitFunTy_maybe (exprType unwrapE) of+             Nothing                    -> fail "type of unwrapper is not a function."+             Just (unwrapTyA,unwrapTyB) -> do guardMsg (eqType wrapTyA unwrapTyA) ("argument type of unwrapper does not match result type of wrapper.")+                                              guardMsg (eqType unwrapTyB tyB) ("argument type of wrapper does not match result type of unwrapper.")+                                              guardMsg (eqType wrapTyA tyA) ("wrapper/unwrapper types do not match expression type.")+                                              x <- constT (newIdH "x" tyB)+                                              return $ App wrapE+                                                           (App (App (Var fixId) (Type tyB))+                                                                (Lam x (App unwrapE+                                                                            (App f+                                                                                 (App wrapE+                                                                                      (Var x)+                                                                                 )+                                                                            )+                                                                       )+                                                                )+                                                           )+++monomorphicWorkerWrapperSplit :: CoreExpr -> CoreExpr -> RewriteH CoreDef+monomorphicWorkerWrapperSplit wrap unwrap =+  let f    = TH.mkName "f"+      w    = TH.mkName "w"+      work = TH.mkName "work"+      fx   = TH.mkName "fix"+   in+      fixIntro >>> defR ( appAllR idR (letIntro f)+                            >>> letFloatArg+                            >>> letAllR idR ( monomorphicWorkerWrapperFac wrap unwrap+                                                >>> appAllR idR (letIntro w)+                                                >>> letFloatArg+                                                >>> letNonRecAllR (unfold fx >>> alphaLetOne (Just work) >>> extractR simplifyR) idR+                                                >>> letSubstR+                                                >>> letFloatArg+                                            )+                        )
src/Language/HERMIT/Primitive/Fold.hs view
@@ -1,9 +1,12 @@ module Language.HERMIT.Primitive.Fold-    ( externals+    ( -- * Fold/Unfold Transformation+      externals     , foldR     , stashFoldR-    ) where+    ) +where+ import GhcPlugins hiding (empty)  import Control.Applicative@@ -12,10 +15,11 @@ import Data.List (intercalate) import qualified Data.Map as Map -import Language.HERMIT.Monad+import Language.HERMIT.Core import Language.HERMIT.Context-import Language.HERMIT.External+import Language.HERMIT.Monad import Language.HERMIT.Kure+import Language.HERMIT.External import Language.HERMIT.GHC  import Language.HERMIT.Primitive.GHC hiding (externals)@@ -60,7 +64,7 @@ foldR :: TH.Name -> RewriteH CoreExpr foldR nm =  prefixFailMsg "Fold failed: " $     translate $ \ c e -> do-        i <- case filter (cmpTHName2Id nm) $ Map.keys (hermitBindings c) of+        i <- case filter (cmpTHName2Var nm) $ Map.keys (hermitBindings c) of                 []  -> fail "cannot find name."                 [i] -> return i                 is  -> fail $ "multiple names match: " ++ intercalate ", " (map var2String is)
src/Language/HERMIT/Primitive/GHC.hs view
@@ -1,128 +1,146 @@-{-# LANGUAGE ScopedTypeVariables, TypeFamilies, FlexibleContexts, TupleSections #-}-module Language.HERMIT.Primitive.GHC where+module Language.HERMIT.Primitive.GHC+       ( -- * GHC-based Transformations+         -- | This module contains transformations that are reflections of GHC functions, or derived from GHC functions.+         externals+         -- ** Free Variables+       , coreExprFreeIds+       , coreExprFreeVars+       , freeIdsT+       , freeVarsT+       , altFreeVarsT+       , altFreeVarsExclWildT+         -- ** Substitution+       , substR+       , letSubstR+       , safeLetSubstR+       , safeLetSubstPlusR+         -- ** Utilities+       , inScope+       , exprEqual+       , showVars+       , rules+       )+where -import GhcPlugins hiding (empty)+import GhcPlugins import qualified OccurAnal+ import Control.Arrow import Control.Monad-import qualified Data.Map as Map-import Data.List (nub, mapAccumL)---- import Language.HERMIT.Primitive.Debug-import Language.HERMIT.Primitive.Navigation+import Data.List (intercalate,mapAccumL,(\\)) -import Language.HERMIT.CoreExtra-import Language.HERMIT.Kure+import Language.HERMIT.Core+import Language.HERMIT.Context import Language.HERMIT.Monad+import Language.HERMIT.Kure import Language.HERMIT.External-import Language.HERMIT.Context-import qualified Language.HERMIT.GHC as GHC+import Language.HERMIT.GHC -import qualified Language.Haskell.TH as TH--- import Debug.Trace+import Language.HERMIT.Primitive.Navigation hiding (externals) -import Prelude hiding (exp)+import qualified Language.Haskell.TH as TH  ------------------------------------------------------------------------ +-- | Externals that reflect GHC functions, or are derived from GHC functions. externals :: [External] externals =-         [ external "let-subst" (promoteExprR letSubstR :: RewriteH Core)-                [ "Let substitution [via GHC]"-                , "let x = E1 in E2 ==> E2[E1/x], fails otherwise"-                , "only matches non-recursive lets" ]                           .+ Deep+         [ external "info" (info :: TranslateH Core String)+                [ "display information about the current node." ]+         , external "let-subst" (promoteExprR letSubstR :: RewriteH Core)+                [ "Let substitution"+                , "(let x = e1 in e2) ==> (e2[e1/x])"+                , "x must not be free in e1." ]                           .+ Deep          , external "safe-let-subst" (promoteExprR safeLetSubstR :: RewriteH Core)-                [ "Safe let substitution [via GHC]"-                , "let x = E1 in E2, safe to inline without duplicating work ==> E2[E1/x],"-                , "fails otherwise"-                , "only matches non-recursive lets" ]                           .+ Deep .+ Eval .+ Bash+                [ "Safe let substitution"+                , "let x = e1 in e2, safe to inline without duplicating work ==> e2[e1/x],"+                , "x must not be free in e1." ]                           .+ Deep .+ Eval .+ Bash          , external "safe-let-subst-plus" (promoteExprR safeLetSubstPlusR :: RewriteH Core)-                [ "Safe let substitution [via GHC]"-                , "let { x = E1, ... } in E2, "-                , "  where safe to inline without duplicating work ==> E2[E1/x,...],"-                , "fails otherwise"+                [ "Safe let substitution"+                , "let { x = e1, ... } in e2, "+                , "  where safe to inline without duplicating work ==> e2[e1/x,...],"                 , "only matches non-recursive lets" ]  .+ Deep .+ Eval          , external "free-ids" (promoteExprT freeIdsQuery :: TranslateH Core String)-                [ "List the free identifiers in this expression [via GHC]" ] .+ Query .+ Deep-         , external "deshadow-binds" (promoteProgramR deShadowBindsR :: RewriteH Core)-                [ "Deshadow a program " ] .+ Deep+                [ "List the free identifiers in this expression." ] .+ Query .+ Deep+         , external "deshadow-prog" (promoteProgR deShadowProgR :: RewriteH Core)+                [ "Deshadow a program." ] .+ Deep          , external "apply-rule" (promoteExprR . rules :: String -> RewriteH Core)                 [ "apply a named GHC rule" ] .+ Shallow          , external "apply-rule" (rules_help :: TranslateH Core String)                 [ "list rules that can be used" ] .+ Query          , external "compare-values" compareValues-                ["compare's the rhs of two values"] .+ Query .+ Predicate+                ["compare the rhs of two values."] .+ Query .+ Predicate          , external "add-rule" (\ rule_name id_name -> promoteModGutsR (addCoreBindAsRule rule_name id_name))                 ["add-rule \"rule-name\" <id> -- adds a new rule that freezes the right hand side of the <id>"]                                         .+ Introduce          , external "cast-elim" (promoteExprR castElimination)                 ["cast-elim removes casts"]-                                        .+ Shallow .+ TODO+                                        .+ Shallow .+ Experiment .+ TODO          , external "add-rule" (\ rule_name id_name -> promoteModGutsR (addCoreBindAsRule rule_name id_name))                 ["add-rule \"rule-name\" <id> -- adds a new rule that freezes the right hand side of the <id>"]-         , external "flatten-module" (promoteModGutsR flattenModule :: RewriteH Core)-                ["Flatten all the top-level binding groups into a single recursive binding group.",-                 "This can be useful if you intend to appply GHC RULES."]-          , external "occur-analysis" (promoteExprR occurAnalyseExprR :: RewriteH Core)                 ["Performs dependency anlaysis on a CoreExpr.",                  "This can be useful to simplify a recursive let to a non-recursive let."] .+ Deep          ]  -------------------------------------------------------------------------substR :: Id -> CoreExpr -> RewriteH Core-substR b e = setFailMsg "Can only perform substitution on Expr or CoreProgram forms." $-             promoteExprR (substExprR b e) <+  promoteProgramR (substTopBindR b e) -substExprR :: Id -> CoreExpr -> RewriteH CoreExpr-substExprR b e =  contextfreeT $ \ exp ->+-- | Substitute all occurrences of a variable with an expression, in either a program or an expression.+substR :: Var -> CoreExpr -> RewriteH Core+substR v e = setFailMsg "Can only perform substitution on expressions or programs." $+             promoteExprR (substExprR v e) <+ promoteProgR (substTopBindR v e)++-- | Substitute all occurrences of a variable with an expression, in an expression.+substExprR :: Var -> CoreExpr -> RewriteH CoreExpr+substExprR v e =  contextfreeT $ \ expr ->           -- The InScopeSet needs to include any free variables appearing in the           -- expression to be substituted.  Constructing a NonRec Let expression           -- to pass on to exprFeeVars takes care of this, but ...           -- TODO Is there a better way to do this ???-          let emptySub = mkEmptySubst (mkInScopeSet (exprFreeVars (Let (NonRec b e) exp)))-              sub = if (isTyVar b)-                    then case e of-                           (Type bty) -> Just $ extendTvSubst emptySub b bty-                           (Var x)    -> Just $ extendTvSubst emptySub b (mkTyVarTy x)-                           _ ->  Nothing-                    else Just $ extendSubst emptySub b e-          in-            case sub of-              Just sub' -> return $ substExpr (text "substR") sub' exp-              Nothing -> fail "substExprR:  Id argument is a TyVar, but the expression is not a Type."+       let emptySub = mkEmptySubst (mkInScopeSet (exprFreeVars (Let (NonRec v e) expr)))+        in do+              sub <- if isTyVar v+                       then case e of+                              Type vty -> return $ extendTvSubst emptySub v vty+                              Var x    -> return $ extendTvSubst emptySub v (mkTyVarTy x)+                              _        -> fail "substExprR:  Var argument is a TyVar, but the expression is not a Type."+                       else return $ extendSubst emptySub v e+              return $ substExpr (text "substR") sub expr +-- | Substitute all occurrences of a variable with an expression, in a program.+substTopBindR :: Var -> CoreExpr -> RewriteH CoreProg+substTopBindR v e =  contextfreeT $ \ p ->+          -- TODO.  Do we need to initialize the emptySubst with bindFreeVars?+       let emptySub =  emptySubst -- mkEmptySubst (mkInScopeSet (exprFreeVars exp))+        in do+              sub <- if isTyVar v+                      then case e of+                             Type vty -> return $ extendTvSubst emptySub v vty+                             Var x    -> return $ extendTvSubst emptySub v (mkTyVarTy x)+                             _        -> fail "substTopBindR:  Var argument is a TyVar, but the expression is not a Type."+                      else return $ extendSubst emptySub v e+              return $ bindsToProg $ snd (mapAccumL substBind sub (progToBinds p)) -substTopBindR :: Id -> CoreExpr -> RewriteH CoreProgram-substTopBindR b e =  contextfreeT $ \  binds  ->-          -- TODO.  Do we ned to initialize the emptySubst with bindFreeVars ?-          let emptySub =  emptySubst -- mkEmptySubst (mkInScopeSet (exprFreeVars exp))-              sub = if (isTyVar b)-                    then case e of-                           (Type bty) -> Just $ extendTvSubst emptySub b bty-                           (Var x)    -> Just $ extendTvSubst emptySub b (mkTyVarTy x)-                           _ ->  Nothing-                    else Just $ extendSubst emptySub b e-          in-            case sub of-              Just sub' -> return $ snd (mapAccumL substBind sub' binds)-              Nothing -> fail "substTopBindR:  Id argument is a TyVar, but the expression is not a Type." +-- | (let x = e1 in e2) ==> (e2[e1/x]),+--   x must not be free in e1. letSubstR :: RewriteH CoreExpr letSubstR =  prefixFailMsg "Let substition failed: " $-             rewrite $ \ ctx exp -> case occurAnalyseExpr exp of-                                     Let (NonRec b be) e -> apply (substExprR b be) ctx e+             rewrite $ \ c expr -> case occurAnalyseExpr expr of+                                     Let (NonRec b be) e -> apply (substExprR b be) c e                                      _ -> fail "expression is not a non-recursive Let." --- remove N lets, please-letSubstNR :: Int -> RewriteH Core-letSubstNR 0 = idR-letSubstNR n = childR 1 (letSubstNR (n - 1)) >>> promoteExprR letSubstR --- This is quite expensive (O(n) for the size of the sub-tree)+-- Neil: Commented this out as it's not (currently) used.+--  Perform let-substitution the specified number of times.+-- letSubstNR :: Int -> RewriteH Core+-- letSubstNR 0 = idR+-- letSubstNR n = childR 1 (letSubstNR (n - 1)) >>> promoteExprR letSubstR++-- | This is quite expensive (O(n) for the size of the sub-tree). safeLetSubstR :: RewriteH CoreExpr safeLetSubstR =  prefixFailMsg "Safe let-substition failed: " $-                 translate $ \ env exp ->+                 translate $ \ env expr ->     let   -- Lit?           safeBind (Var {})   = True           safeBind (Lam {})   = True@@ -137,13 +155,13 @@           safeSubst IAmDead   = True    -- DCE           safeSubst (OneOcc inLam oneBr _) = not inLam && oneBr -- do not inline inside a lambda or if in multiple case branches           safeSubst _ = False   -- strange case, like a loop breaker-   in case occurAnalyseExpr exp of+   in case occurAnalyseExpr expr of       -- By (our) definition, types are a trivial bind       Let (NonRec b _) _-         | isTyVar b -> apply letSubstR env exp+         | isTyVar b -> apply letSubstR env expr       Let (NonRec b be) _          | isId b && (safeBind be || safeSubst (occInfo (idInfo b)))-                     -> apply letSubstR env exp+                     -> apply letSubstR env expr          | otherwise -> fail "safety critera not met."       _ -> fail "expression is not a non-recursive Let." @@ -154,35 +172,98 @@  ------------------------------------------------------------------------ +info :: TranslateH Core String+info = translate $ \ c core -> do+         dynFlags <- getDynFlags+         let pa       = "Path: " ++ show (contextPath c)+             node     = "Node: " ++ coreNode core+             con      = "Constructor: " ++ coreConstructor core+             bds      = "Bindings in Scope: " ++ show (map unqualifiedVarName $ boundVars c)+             expExtra = case core of+                          ExprCore e -> ["Type or Kind: " ++ showExprTypeOrKind dynFlags e] +++                                        ["Free Variables: " ++ showVars (coreExprFreeVars e)]+                                           --  +++                                           -- case e of+                                           --   Var v -> ["Identifier Info: " ++ showIdInfo dynFlags v] -- TODO: what if this is a TyVar?+                                           --   _     -> []+                          _          -> []++         return (intercalate "\n" $ [pa,node,con,bds] ++ expExtra)++showExprTypeOrKind :: DynFlags -> CoreExpr -> String+showExprTypeOrKind dynFlags = showPpr dynFlags . exprTypeOrKind++-- showIdInfo :: DynFlags -> Id -> String+-- showIdInfo dynFlags v = showSDoc dynFlags $ ppIdInfo v $ idInfo v++coreNode :: Core -> String+coreNode (ModGutsCore _) = "Module"+coreNode (ProgCore _)    = "Program"+coreNode (BindCore _)    = "Binding Group"+coreNode (DefCore _)     = "Recursive Definition"+coreNode (ExprCore _)    = "Expression"+coreNode (AltCore _)     = "Case Alternative"++coreConstructor :: Core -> String+coreConstructor (ModGutsCore _)    = "ModGuts"+coreConstructor (ProgCore prog)    = case prog of+                                       ProgNil      -> "ProgNil"+                                       ProgCons _ _ -> "ProgCons"+coreConstructor (BindCore bnd)     = case bnd of+                                       Rec _      -> "Rec"+                                       NonRec _ _ -> "NonRec"+coreConstructor (DefCore _)        = "Def"+coreConstructor (AltCore _)        = "(,,)"+coreConstructor (ExprCore expr)    = case expr of+                                       Var _        -> "Var"+                                       Type _       -> "Type"+                                       Lit _        -> "Lit"+                                       App _ _      -> "App"+                                       Lam _ _      -> "Lam"+                                       Let _ _      -> "Let"+                                       Case _ _ _ _ -> "Case"+                                       Cast _ _     -> "Cast"+                                       Tick _ _     -> "Tick"+                                       Coercion _   -> "Coercion"++------------------------------------------------------------------------+ -- | Output a list of all free variables in an expression. freeIdsQuery :: TranslateH CoreExpr String-freeIdsQuery = do-    dynFlags <- constT getDynFlags-    frees <- freeIdsT-    return $ "Free identifiers are: " ++ showVars dynFlags frees---- | Show a human-readable version of a 'Var'.-showVar :: DynFlags -> Var -> String-showVar dynFlags = show . showPpr dynFlags+freeIdsQuery = do frees <- freeIdsT+                  return $ "Free identifiers are: " ++ showVars frees  -- | Show a human-readable version of a list of 'Var's.-showVars :: DynFlags -> [Var] -> String-showVars dynFlags = show . map (showPpr dynFlags) -- map GHC.var2String+showVars :: [Var] -> String+showVars = show . map var2String +-- | Lifted version of 'coreExprFreeIds'. freeIdsT :: TranslateH CoreExpr [Id] freeIdsT = arr coreExprFreeIds +-- | Lifted version of 'coreExprFreeVars'. freeVarsT :: TranslateH CoreExpr [Var] freeVarsT = arr coreExprFreeVars --- note: coreExprFreeVars get *all* free variables, including types+-- | List all free variables (including types) in the expression. coreExprFreeVars :: CoreExpr -> [Var] coreExprFreeVars  = uniqSetToList . exprFreeVars --- note: coreExprFreeIds is only value-level free variables+-- | List all free identifiers (value-level free variables) in the expression. coreExprFreeIds :: CoreExpr -> [Id] coreExprFreeIds  = uniqSetToList . exprFreeIds +-- | The free variables in a case alternative, which excludes any identifiers bound in the alternative.+altFreeVarsT :: TranslateH CoreAlt [Var]+altFreeVarsT = altT freeVarsT (\ _ vs fvs -> fvs \\ vs)++-- | A variant of 'altFreeVarsT' that returns a function that accepts the case wild-card binder before giving a result.+--   This is so we can use this with congruence combinators, for example:+--+--   caseT id (const altFreeVarsT) $ \ _ wild _ fvs -> [ f wild | f <- fvs ]+altFreeVarsExclWildT :: TranslateH CoreAlt (Id -> [Var])+altFreeVarsExclWildT = altT freeVarsT (\ _ vs fvs wild -> fvs \\ (wild : vs))+ ------------------------------------------------------------------------  -- | [from GHC documentation] De-shadowing the program is sometimes a useful pre-pass.@@ -191,8 +272,8 @@ -- -- (Actually, within a single /type/ there might still be shadowing, because -- 'substTy' is a no-op for the empty substitution, but that's probably OK.)-deShadowBindsR :: RewriteH CoreProgram-deShadowBindsR = arr deShadowBinds+deShadowProgR :: RewriteH CoreProg+deShadowProgR = arr (bindsToProg . deShadowBinds . progToBinds)  ------------------------------------------------------------------------ {-@@ -203,11 +284,12 @@ 	    -> [CoreRule] -> Maybe (CoreRule, CoreExpr) -} -rulesToEnv :: [CoreRule] -> Map.Map String (RewriteH CoreExpr)-rulesToEnv rs = Map.fromList-        [ ( unpackFS (ruleName r), rulesToRewriteH [r] )-        | r <- rs-        ]+-- Neil: Commented this out as its not (currently) used.+-- rulesToEnv :: [CoreRule] -> Map.Map String (RewriteH CoreExpr)+-- rulesToEnv rs = Map.fromList+--         [ ( unpackFS (ruleName r), rulesToRewriteH [r] )+--         | r <- rs+--         ]  rulesToRewriteH :: [CoreRule] -> RewriteH CoreExpr rulesToRewriteH rs = translate $ \ c e -> do@@ -223,21 +305,21 @@     -- trace (showSDoc (ppr fn GhcPlugins.<+> ppr args $$ ppr rs)) $     case lookupRule (const True) (const NoUnfolding) in_scope fn args rs of         Nothing         -> fail "rule not matched"-        Just (rule, exp)  -> do-            let e' = mkApps exp (drop (ruleArity rule) args)+        Just (rule, expr)  -> do+            let e' = mkApps expr (drop (ruleArity rule) args)             ifM (liftM (and . map (inScope c)) $ apply freeVarsT c e')                 (return e')                 (fail $ unlines ["Resulting expression after rule application contains variables that are not in scope."                                 ,"This can probably be solved by running the flatten-module command at the top level."]) --- | See whether an identifier is in scope.-inScope :: Context -> Id -> Bool-inScope c i = maybe (case unfoldingInfo (idInfo i) of-                        CoreUnfolding {} -> True -- defined elsewhere-                        _ -> False)-                    (const True) -- defined in this module-                    (lookupHermitBinding i c)+-- | Determine whether an identifier is in scope.+inScope :: HermitC -> Id -> Bool+inScope c v = (v `boundIn` c) ||                 -- defined in this module+              case unfoldingInfo (idInfo v) of+                CoreUnfolding {} -> True         -- defined elsewhere+                _                -> False +-- | Lookup a rule and attempt to construct a corresponding rewrite. rules ::  String -> RewriteH CoreExpr rules r = do         theRules <- getHermitRules@@ -245,8 +327,8 @@                Nothing -> fail $ "failed to find rule: " ++ show r                Just rr -> rulesToRewriteH rr -getHermitRules :: (Generic a ~ Core) => TranslateH a [(String, [CoreRule])]-getHermitRules = translate $ \ env _e -> do+getHermitRules :: TranslateH a [(String, [CoreRule])]+getHermitRules = translate $ \ env _ -> do     rb <- liftCoreM getRuleBase     let other_rules = [ rule                         | top_bnds <- mg_binds (hermitModGuts env)@@ -283,9 +365,9 @@              , (v,e) <- case top_bnds of                             Rec bnds -> bnds                             NonRec b e -> [(b,e)]-             ,  nm `GHC.cmpTHName2Id` v+             ,  nm `cmpTHName2Var` v              ] of-         [] -> fail $ "can not find binding " ++ show nm+         [] -> fail $ "cannot find binding " ++ show nm          [(v,e)] -> return $ modGuts { mg_rules = mg_rules modGuts                                               ++ [makeRule rule_name v e]                                      }@@ -293,29 +375,14 @@  ---------------------------------------------------------------------- -flattenModule :: RewriteH ModGuts-flattenModule = modGutsR mergeBinds--mergeBinds :: RewriteH CoreProgram-mergeBinds = contextfreeT $ \  binds ->-             let allbinds = foldr listOfBinds [] binds-                 nodups = nub $ map fst allbinds-             in-               if (length allbinds == length nodups)-               then return $ [Rec allbinds]-               else fail "Module top level bindings contain multiple occurances of a name"- where listOfBinds cb others = case cb of-                                 (NonRec b e) -> (b, e) : others-                                 (Rec bds) -> bds ++ others-------------------------------------------------------------------------+-- | Performs dependency anlaysis on an expression.+--   This can be useful to simplify a non-recursive recursive binding group to a non-recursive binding group. occurAnalyseExpr :: CoreExpr -> CoreExpr occurAnalyseExpr = OccurAnal.occurAnalyseExpr -+-- | Lifted version of 'occurAnalyseExpr' occurAnalyseExprR :: RewriteH CoreExpr-occurAnalyseExprR = contextfreeT $ \ exp -> return (occurAnalyseExpr exp)+occurAnalyseExprR = arr occurAnalyseExpr   @@ -330,12 +397,6 @@  -} -{--joinT :: TranslateH a (TranslateH b c) -> (a -> TranslateH b c)-joinT f e0 = translate $ \ c e1 -> do-                t <- apply f c e0-                apply t c e1--}  exprEqual :: CoreExpr -> CoreExpr -> Bool exprEqual e1 e2 = eqExpr (mkInScopeSet $ exprsFreeVars [e1, e2]) e1 e2@@ -361,25 +422,24 @@ coreEqual :: Core -> Core -> Maybe Bool coreEqual (ExprCore e1) (ExprCore e2) = Just $ e1 `exprEqual` e2 coreEqual (BindCore b1) (BindCore b2) = b1 `bindEqual` b2-coreEqual (DefCore dc1) (DefCore dc2) = defToRecBind [dc1] `bindEqual` defToRecBind [dc2]+coreEqual (DefCore dc1) (DefCore dc2) = defsToRecBind [dc1] `bindEqual` defsToRecBind [dc2] coreEqual _             _             = Nothing  compareValues :: TH.Name -> TH.Name -> TranslateH Core () compareValues n1 n2 = do         p1 <- onePathToT (namedBinding n1)         p2 <- onePathToT (namedBinding n2)-        e1 :: Core <- pathT p1 idR-        e2 :: Core <- pathT p2 idR+        e1 <- pathT p1 idR+        e2 <- pathT p2 idR         case e1 `coreEqual` e2 of-          Nothing    -> fail $ show n1 ++ " and " ++ show n2 ++ " are incomparable"-          Just False -> fail $ show n1 ++ " and " ++ show n2 ++ " are not equal"+          Nothing    -> fail $ show n1 ++ " and " ++ show n2 ++ " are incomparable."+          Just False -> fail $ show n1 ++ " and " ++ show n2 ++ " are not equal."           Just True  -> return ()  -------------------------------------------------------- ---- try figure out the arity of an Id-arityOf:: Context -> Id -> Int+-- | Try to figure out the arity of an identifier.+arityOf :: HermitC -> Id -> Int arityOf env nm =      case lookupHermitBinding nm env of         Nothing       -> idArity nm@@ -387,8 +447,8 @@         -- Note: the exprArity will call idArity if         -- it hits an id; perhaps we should do the counting         -- The advantage of idArity is it will terminate, though.-        Just (BIND _ _ e) -> GHC.exprArity e-        Just (CASE _ e _) -> GHC.exprArity e+        Just (BIND _ _ e) -> exprArity e+        Just (CASE _ e _) -> exprArity e  ------------------------------------------- 
src/Language/HERMIT/Primitive/Inline.hs view
@@ -1,20 +1,34 @@-module Language.HERMIT.Primitive.Inline where+module Language.HERMIT.Primitive.Inline+         ( -- * Inlining+           externals+         , inline+         , inlineName+         , inlineScrutinee+         , inlineCaseBinder+         , inlineTargets+         ) +where+ import GhcPlugins  import Control.Arrow -import Language.HERMIT.GHC-import Language.HERMIT.Primitive.Common--- import Language.HERMIT.Primitive.Debug (traceR)-import Language.HERMIT.Primitive.GHC-import Language.HERMIT.Primitive.Unfold+import Language.HERMIT.Core import Language.HERMIT.Kure import Language.HERMIT.Context+import Language.HERMIT.GHC import Language.HERMIT.External +import Language.HERMIT.Primitive.Common+import Language.HERMIT.Primitive.GHC hiding (externals)+import Language.HERMIT.Primitive.Unfold hiding (externals)+ import qualified Language.Haskell.TH as TH +------------------------------------------------------------------------++-- | 'External's for inlining variables. externals :: [External] externals =             [ external "inline" (promoteExprR inline :: RewriteH Core)@@ -29,20 +43,26 @@                 [ "Inline if this variable is a case binder." ].+ Eval .+ Deep .+ Bash .+ TODO             ] +------------------------------------------------------------------------++-- | If the current variable matches the given name, then inline it. inlineName :: TH.Name -> RewriteH CoreExpr inlineName nm = let name = TH.nameBase nm in                 prefixFailMsg ("inline '" ++ name ++ " failed: ") $                 withPatFailMsg (wrongExprForm "Var v") $    do Var v <- idR-      guardMsg (cmpTHName2Id nm v) $ name ++ " does not match " ++ var2String v ++ "."+      guardMsg (cmpTHName2Var nm v) $ " does not match " ++ var2String v ++ "."       inline +-- | Inline the current variable. inline :: RewriteH CoreExpr inline = configurableInline False False +-- | Inline the current variable, using the scrutinee rather than the case alternative if it is a case wild-card binder. inlineScrutinee :: RewriteH CoreExpr inlineScrutinee = configurableInline True False +-- | If the current variable is a case wild-card binder, then inline it. inlineCaseBinder :: RewriteH CoreExpr inlineCaseBinder = configurableInline False True @@ -74,6 +94,6 @@  -- | Get list of possible inline targets. Used by shell for completion. inlineTargets :: TranslateH Core [String]-inlineTargets = collectT $ promoteT $ ifM (testM inline)-                                          (varT unqualifiedIdName)-                                          (fail "cannot be inlined.")+inlineTargets = collectT $ promoteT $ whenM (testM inline) (varT unqualifiedVarName)++------------------------------------------------------------------------
src/Language/HERMIT/Primitive/Kure.hs view
@@ -7,6 +7,7 @@  import Control.Arrow +import Language.HERMIT.Core import Language.HERMIT.Kure import Language.HERMIT.External @@ -65,6 +66,8 @@    , external "not"        (notM :: TranslateH Core () -> TranslateH Core ())        [ "cause a failing check to succeed, a succeeding check to fail" ] .+ Predicate    ]++------------------------------------------------------------------------------------  hfocusR :: TranslateH Core Path -> RewriteH Core -> RewriteH Core hfocusR tp r = do p <- tp
src/Language/HERMIT/Primitive/Local.hs view
@@ -1,56 +1,100 @@--- Andre Santos' Local Transformations (Ch 3 in his dissertation)-module Language.HERMIT.Primitive.Local where+module Language.HERMIT.Primitive.Local+       ( -- * Local Structural Manipulations+         Language.HERMIT.Primitive.Local.externals+         -- ** Let Expressions+       , module Language.HERMIT.Primitive.Local.Let+         -- ** Case Expressions+       , module Language.HERMIT.Primitive.Local.Case+         -- ** Miscellaneous+       , abstract+       , nonrecToRec+       , betaReduce+       , betaReducePlus+       , betaExpand+       , etaReduce+       , etaExpand+       , multiEtaExpand+       , flattenModule+       , flattenProgramR+       , flattenProgramT+       )+where  import GhcPlugins +import Language.HERMIT.Core import Language.HERMIT.Kure import Language.HERMIT.Monad import Language.HERMIT.External import Language.HERMIT.GHC  import Language.HERMIT.Primitive.GHC--- import Language.HERMIT.Primitive.Debug- import Language.HERMIT.Primitive.Common-import qualified Language.HERMIT.Primitive.Local.Case as Case-import qualified Language.HERMIT.Primitive.Local.Let as Let+import Language.HERMIT.Primitive.Local.Case+import Language.HERMIT.Primitive.Local.Let  import qualified Language.Haskell.TH as TH +import Data.List(nub)+ import Control.Arrow  ------------------------------------------------------------------------------ +-- | Externals for local structural manipulations.+--   (Many taken from Chapter 3 of Andre Santos' dissertation.) externals :: [External] externals =-         [ external "beta-reduce" (promoteExprR betaReduce :: RewriteH Core)-                     [ "((\\ v -> E1) E2) ==> let v = E2 in E1, fails otherwise"-                     , "this form of beta reduction is safe if E2 is an arbitrary"+         [ external "nonrec-to-rec" (promoteBindR nonrecToRec :: RewriteH Core)+                     [ "convert a non-recursive binding into a recursive binding group with a single definition."+                     , "NonRec v e ==> Rec [Def v e]" ]+         , external "beta-reduce" (promoteExprR betaReduce :: RewriteH Core)+                     [ "((\\ v -> E1) E2) ==> let v = E2 in E1"+                     , "this form of beta-reduction is safe if E2 is an arbitrary"                      , "expression (won't duplicate work)" ]                                 .+ Eval .+ Shallow          , external "beta-reduce-plus" (promoteExprR betaReducePlus :: RewriteH Core)-                     [ "perform one or more beta-reductions"]                                .+ Eval .+ Shallow .+ Bash+                     [ "perform one or more beta-reductions."]                               .+ Eval .+ Shallow .+ Bash          , external "beta-expand" (promoteExprR betaExpand :: RewriteH Core)-                     [ "(let v = E1 in E2) ==> (\\ v -> E2) E1, fails otherwise" ]           .+ Shallow-         , external "dead-code-elimination" (promoteExprR dce :: RewriteH Core)-                     [ "dead code elimination removes a let."-                     , "(let v = E1 in E2) ==> E2, if v is not free in E2, fails otherwise"-                     , "condition: let is not-recursive" ]                                   .+ Eval .+ Shallow .+ Bash+                     [ "(let v = e1 in e2) ==> (\\ v -> e2) e1" ]                            .+ Shallow          , external "eta-reduce" (promoteExprR etaReduce :: RewriteH Core)-                     [ "(\\ v -> E1 v) ==> E1, fails otherwise" ]                            .+ Eval .+ Shallow .+ Bash+                     [ "(\\ v -> e1 v) ==> e1" ]                                             .+ Eval .+ Shallow .+ Bash          , external "eta-expand" (promoteExprR . etaExpand :: TH.Name -> RewriteH Core)-                     [ "'eta-expand v' performs E1 ==> (\\ v -> E1 v), fails otherwise" ]    .+ Shallow .+ Introduce+                     [ "\"eta-expand 'v\" performs e1 ==> (\\ v -> e1 v)" ]                     .+ Shallow .+ Introduce+         , external "flatten-module" (promoteModGutsR flattenModule :: RewriteH Core)+                ["Flatten all the top-level binding groups in the module to a single recursive binding group.",+                 "This can be useful if you intend to appply GHC RULES."]+         , external "flatten-program" (promoteProgR flattenProgramR :: RewriteH Core)+                ["Flatten all the top-level binding groups in a program (list of binding groups) to a single recursive binding group.",+                 "This can be useful if you intend to appply GHC RULES."]+         , external "abstract" (promoteExprR . abstract :: TH.Name -> RewriteH Core)+                [ "Abstract over a variable using a lambda.",+                  "e  ==>  (\\ x -> e) x"+                ] .+ Shallow .+ Introduce .+ Context          ]-         ++ Let.externals-         ++ Case.externals+         ++ letExternals+         ++ caseExternals  ------------------------------------------------------------------------------ +-- | NonRec v e ==> Rec [Def v e]+nonrecToRec :: RewriteH CoreBind+nonrecToRec = prefixFailMsg "Converting non-recursive binding to recursive binding failed: " $+              setFailMsg (wrongExprForm "NonRec v e") $+  do NonRec v e <- idR+     guardMsg (isId v) "type variables cannot be defined recursively."+     return $ Rec [(v,e)]++------------------------------------------------------------------------------++-- | ((\\ v -> e1) e2) ==> (let v = e2 in e1)+--   This form of beta-reduction is safe if e2 is an arbitrary+--   expression (won't duplicate work). betaReduce :: RewriteH CoreExpr-betaReduce = prefixFailMsg "Beta reduction failed: " $-             setFailMsg (wrongExprForm "App (Lam v e1) e2") $+betaReduce = setFailMsg ("Beta-reduction failed: " ++ wrongExprForm "App (Lam v e1) e2") $     do App (Lam v e1) e2 <- idR        return $ Let (NonRec v e2) e1 + multiBetaReduce :: (Int -> Bool) -> RewriteH CoreExpr multiBetaReduce p = prefixFailMsg "Multi-Beta-Reduce failed: " $     do@@ -69,6 +113,8 @@            $ mkLams vs2 e0  -- TODO: inline this everywhere+-- Neil: Are we sure we want to inline this?+-- | Perform one or more beta-reductions. betaReducePlus :: RewriteH CoreExpr betaReducePlus = multiBetaReduce (> 0) @@ -91,50 +137,73 @@                    ) -} +-- | (let v = e1 in e2) ==> (\\ v -> e2) e1 betaExpand :: RewriteH CoreExpr-betaExpand = setFailMsg ("Beta expansion failed: " ++ wrongExprForm "Let (NonRec v e1) e2") $-    do Let (NonRec v e2) e1 <- idR-       return $ App (Lam v e1) e2+betaExpand = setFailMsg ("Beta-expansion failed: " ++ wrongExprForm "Let (NonRec v e1) e2") $+    do Let (NonRec v e1) e2 <- idR+       return $ App (Lam v e2) e1  ------------------------------------------------------------------------------ +-- | (\\ v -> e1 v) ==> e1 etaReduce :: RewriteH CoreExpr-etaReduce = prefixFailMsg "Eta reduction failed: " $-            withPatFailMsg (wrongExprForm "Lam v1 (App f (Var v2))") $-       (do Lam v1 (App f (Var v2)) <- idR-           guardMsg (v1 == v2) "the expression has the right form, but the variables are not equal."-           guardMsg (v1 `notElem` coreExprFreeIds f) $ var2String v1 ++ " is free in the function being applied."-           return f) <+-       (do Lam v1 (App f (Type ty)) <- idR-           Just v2 <- return (getTyVar_maybe ty)-           guardMsg (v1 == v2) "type variables are not equal."-           guardMsg (v1 `notElem` coreExprFreeVars f) $ var2String v1 ++ " is free in the function being applied."-           return f)+etaReduce = prefixFailMsg "Eta-reduction failed: " $+            withPatFailMsg (wrongExprForm "Lam v1 (App f e)") $+            do Lam v1 (App f e) <- idR+               case e of+                  Var v2  -> guardMsg (v1 == v2) "the expression has the right form, but the variables are not equal."+                  Type ty -> case getTyVar_maybe ty of+                               Nothing -> fail "the argument expression is not a type variable."+                               Just v2 -> guardMsg (v1 == v2) "type variables are not equal."+                  _       -> fail "the argument expression is not a variable."+               guardMsg (v1 `notElem` coreExprFreeIds f) $ var2String v1 ++ " is free in the function being applied."+               return f +-- | e1 ==> (\\ v -> e1 v) etaExpand :: TH.Name -> RewriteH CoreExpr-etaExpand nm = prefixFailMsg "Eta expansion failed: " $-               contextfreeT $ \ e ->-        case splitFunTy_maybe (exprType e) of-          Just (arg_ty, _) -> do v1 <- newVarH (show nm) arg_ty-                                 return $ Lam v1 (App e (Var v1))-          _ -> case splitForAllTy_maybe (exprType e) of-                  Just (v,_) -> do v1 <- newTypeVarH (show nm) (tyVarKind v)-                                   return $ Lam v1 (App e (Type (mkTyVarTy v1)))-                  Nothing -> fail "TODO: Add useful error message here."+etaExpand nm = prefixFailMsg "Eta-expansion failed: " $+               contextfreeT $ \ e -> let ty = exprType e in+        case splitFunTy_maybe ty of+          Just (argTy, _) -> do v <- newIdH (show nm) argTy+                                return $ Lam v (App e (Var v))+          Nothing         -> case splitForAllTy_maybe ty of+                               Just (tv,_) -> do v <- newTyVarH (show nm) (tyVarKind tv)+                                                 return $ Lam v (App e (Type (mkTyVarTy v)))+                               Nothing -> fail "type of expression is not a function or a forall." +-- | Perform multiple eta-expansions. multiEtaExpand :: [TH.Name] -> RewriteH CoreExpr multiEtaExpand []       = idR multiEtaExpand (nm:nms) = etaExpand nm >>> lamR (multiEtaExpand nms)  ------------------------------------------------------------------------------ --- dead code elimination removes a let.--- (let v = E1 in E2) => E2, if v is not free in E2-dce :: RewriteH CoreExpr-dce = prefixFailMsg "Dead code elimination failed: " $-      withPatFailMsg (wrongExprForm "Let (NonRec v e1) e2") $-      do Let (NonRec v _) e <- idR-         guardMsg (v `notElem` coreExprFreeVars e) "Dead code elimination failed.  No dead code to eliminate."-         return e+-- | Flatten all the top-level binding groups in the module to a single recursive binding group.+flattenModule :: RewriteH ModGuts+flattenModule = modGutsR flattenProgramR++-- | Flatten all the top-level binding groups in a program to a program containing a single recursive binding group.+flattenProgramR :: RewriteH CoreProg+flattenProgramR = do bnd <- flattenProgramT+                     return (bindsToProg [bnd])++-- | Flatten all the top-level binding groups in a program to a single recursive binding group.+flattenProgramT :: TranslateH CoreProg CoreBind+flattenProgramT = do bds <- arr (concatMap bindToIdExprs . progToBinds)+                     guardMsg (nodups $ map fst bds) "Top-level bindings contain multiple occurrences of a name."+                     return (Rec bds)++nodups :: Eq a => [a] -> Bool+nodups as = length as == length (nub as)++------------------------------------------------------------------------------++-- | Abstract over a variable using a lambda.+--   e  ==>  (\ x. e) x+abstract :: TH.Name -> RewriteH CoreExpr+abstract nm = prefixFailMsg "abstraction failed: " $+   do e <- idR+      v <- findBoundVarT nm+      return (App (Lam v e) (Var v))  ------------------------------------------------------------------------------
src/Language/HERMIT/Primitive/Local/Case.hs view
@@ -1,8 +1,6 @@--- Andre Santos' Local Transformations (Ch 3 in his dissertation) module Language.HERMIT.Primitive.Local.Case        ( -- * Rewrites on Case Expressions-         externals-       , letFloatCase+         caseExternals        , caseFloatApp        , caseFloatArg        , caseFloatCase@@ -19,17 +17,17 @@  import Data.List import Control.Arrow-import Control.Applicative -import Language.HERMIT.GHC+import Language.HERMIT.Core+import Language.HERMIT.Monad import Language.HERMIT.Kure+import Language.HERMIT.GHC import Language.HERMIT.External-import Language.HERMIT.Monad  import Language.HERMIT.Primitive.Common-import Language.HERMIT.Primitive.GHC hiding (externals)-import Language.HERMIT.Primitive.Inline hiding (externals)-import Language.HERMIT.Primitive.AlphaConversion hiding (externals)+import Language.HERMIT.Primitive.GHC+import Language.HERMIT.Primitive.Inline+import Language.HERMIT.Primitive.AlphaConversion  import qualified Language.Haskell.TH as TH @@ -37,8 +35,8 @@ ------------------------------------------------------------------------------  -- | Externals relating to Case expressions.-externals :: [External]-externals =+caseExternals :: [External]+caseExternals =          [ -- I'm not sure this is possible. In core, v2 can only be a Constructor, Lit, or DEFAULT            -- In the last case, v1 is already inlined in e. So we can't construct v2 as a Var.          --   external "case-elimination" (promoteR $ not_defined "case-elimination" :: RewriteH Core)@@ -49,9 +47,7 @@          --   -- Again, don't think the lhs of this rule is possible to construct in core.          -- , external "case-merging" (promoteR $ not_defined "case-merging" :: RewriteH Core)          --             [ "case v of ...; d -> case v of alt -> e ==> case v of ...; alt -> e[v/d]" ] .+ Unimplemented .+ Eval-           external "let-float-case" (promoteExprR letFloatCase :: RewriteH Core)-                     [ "case (let v = ev in e) of ... ==> let v = ev in case e of ..." ]  .+ Commute .+ Shallow .+ Eval .+ Bash-         , external "case-float-app" (promoteExprR caseFloatApp :: RewriteH Core)+           external "case-float-app" (promoteExprR caseFloatApp :: RewriteH Core)                      [ "(case ec of alt -> e) v ==> case ec of alt -> e v" ]              .+ Commute .+ Shallow .+ Bash          , external "case-float-arg" (promoteExprR caseFloatArg :: RewriteH Core)                      [ "f (case s of alt -> e) ==> case s of alt -> f e" ]                .+ Commute .+ Shallow .+ PreCondition@@ -72,26 +68,15 @@                 , "applications for all occurances of the named variable." ]          ] --- not_defined :: String -> RewriteH CoreExpr--- not_defined nm = fail $ nm ++ " not implemented!"---- | case (let v = e1 in e2) of alts ==> let v = e1 in case e2 of alts-letFloatCase :: RewriteH CoreExpr-letFloatCase = prefixFailMsg "Let floating from Case failed: " $-  do-     captures <- caseT letVarsT (const (pure ())) $ \ vs _ _ _ -> vs-     cFrees   <- freeVarsT -- so we get type variables too-     caseT (if null (cFrees `intersect` captures) then idR else alphaLet)-           (const idR)-           (\ (Let bnds e) b ty alts -> Let bnds (Case e b ty alts))+------------------------------------------------------------------------------  -- | (case s of alt1 -> e1; alt2 -> e2) v ==> case s of alt1 -> e1 v; alt2 -> e2 v caseFloatApp :: RewriteH CoreExpr caseFloatApp = prefixFailMsg "Case floating from App function failed: " $   do-    captures      <- appT caseAltVarsT freeVarsT (flip (map . intersect))-    binderCapture <- appT caseBinderVarT freeVarsT intersect-    appT ((if null binderCapture then idR else alphaCaseBinder Nothing)+    captures    <- appT caseAltVarsT freeVarsT (flip (map . intersect))+    wildCapture <- appT caseWildVarT freeVarsT elem+    appT ((if not wildCapture then idR else alphaCaseBinder Nothing)           >>> caseAllR idR (\i -> if null (captures !! i) then idR else alphaAlt)          )           idR@@ -104,10 +89,10 @@ caseFloatArg :: RewriteH CoreExpr caseFloatArg = prefixFailMsg "Case floating from App argument failed: " $   do-    captures      <- appT freeVarsT caseAltVarsT (map . intersect)-    binderCapture <- appT freeVarsT caseBinderVarT intersect+    captures    <- appT freeVarsT caseAltVarsT (map . intersect)+    wildCapture <- appT freeVarsT caseWildVarT (flip elem)     appT idR-         ((if null binderCapture then idR else alphaCaseBinder Nothing)+         ((if not wildCapture then idR else alphaCaseBinder Nothing)           >>> caseAllR idR (\i -> if null (captures !! i) then idR else alphaAlt)          )          (\f (Case s b _ty alts) -> let newTy = exprType (App f (case head alts of (_,_,e) -> e))@@ -122,15 +107,15 @@ caseFloatCase :: RewriteH CoreExpr caseFloatCase = prefixFailMsg "Case floating from Case failed: " $   do-    captures <- caseT caseAltVarsT (const altFreeVarsT) $ \ vss bndr _ fs -> map (intersect (concatMap ($ bndr) fs)) vss+    captures <- caseT caseAltVarsT (const altFreeVarsExclWildT) (\ vss bndr _ fs -> map (intersect (concatMap ($ bndr) fs)) vss)     -- does the binder of the inner case, shadow a free variable in any of the outer case alts?     -- notice, caseBinderVarT returns a singleton list-    binderCapture <- caseT caseBinderVarT (const altFreeVarsT) $ \ innerBindr bndr _ fs -> intersect (concatMap ($ bndr) fs) innerBindr-    caseT ((if null binderCapture then idR else alphaCaseBinder Nothing)+    wildCapture <- caseT caseWildVarT (const altFreeVarsExclWildT) (\ innerBndr bndr _ fvs -> innerBndr `elem` concatMap ($ bndr) fvs)+    caseT ((if not wildCapture then idR else alphaCaseBinder Nothing)            >>> caseAllR idR (\i -> if null (captures !! i) then idR else alphaAlt)           )           (const idR)-          (\ (Case s1 b1 ty1 alts1) b2 ty2 alts2 -> Case s1 b1 ty1 [ (c1, ids1, Case e1 b2 ty2 alts2) | (c1, ids1, e1) <- alts1 ])+          (\ (Case s1 b1 _ alts1) b2 ty alts2 -> Case s1 b1 ty [ (c1, ids1, Case e1 b2 ty alts2) | (c1, ids1, e1) <- alts1 ])  -- | let v = case ec of alt1 -> e1 in e ==> case ec of alt1 -> let v = e1 in e caseFloatLet :: RewriteH CoreExpr@@ -153,9 +138,13 @@                          do Case s binder _ alts <- idR                             case isDataCon s of                               Nothing -> fail "head of scrutinee is not a data constructor."-                              Just (dc, args) -> case [ (bs, rhs) | (DataAlt dc', bs, rhs) <- alts, dc == dc' ] of-                                    [(bs,e')] -> let valArgs = filter isValArg args -- discard any type arguments-                                                  in return $ nestedLets e' $ (binder, s) : zip bs valArgs+                              Just (dc, args) ->+                                case [ (bs, rhs) | (DataAlt dc', bs, rhs) <- alts, dc == dc' ] of+                                    [(bs,e')] -> let (tyArgs, valArgs) = span isTypeArg args+                                                     tyBndrs = takeWhile isTyVar bs -- it is possible the pattern constructor binds a type+                                                                                    -- if the constructor is existentially quantified+                                                     existentials = reverse $ take (length tyBndrs) $ reverse tyArgs+                                                  in return $ nestedLets e' $ (binder, s) : zip bs (existentials ++ valArgs)                                     []   -> fail "no matching alternative."                                     _    -> fail "more than one matching alternative." @@ -182,14 +171,14 @@ caseSplit nm = do     frees <- freeIdsT     contextfreeT $ \ e ->-        case [ i | i <- frees, cmpTHName2Id nm i ] of+        case [ i | i <- frees, cmpTHName2Var nm i ] of             []    -> fail "caseSplit: provided name is not free"             (i:_) -> do                 let (tycon, tys) = splitTyConApp (idType i)                     dcs = tyConDataCons tycon                     aNms = map (:[]) $ cycle ['a'..'z']                 dcsAndVars <- mapM (\dc -> do-                                        as <- sequence [ newVarH a ty | (a,ty) <- zip aNms $ dataConInstArgTys dc tys ]+                                        as <- sequence [ newIdH a ty | (a,ty) <- zip aNms $ dataConInstArgTys dc tys ]                                         return (dc,as)) dcs                 return $ Case (Var i) i (exprType e) [ (DataAlt dc, as, e) | (dc,as) <- dcsAndVars ] @@ -200,3 +189,4 @@ caseSplitInline :: TH.Name -> RewriteH Core caseSplitInline nm = promoteR (caseSplit nm) >>> anybuR (promoteExprR $ inlineName nm) +------------------------------------------------------------------------------
src/Language/HERMIT/Primitive/Local/Let.hs view
@@ -1,11 +1,13 @@--- Andre Santos' Local Transformations (Ch 3 in his dissertation) module Language.HERMIT.Primitive.Local.Let        ( -- * Rewrites on Let Expressions-         externals+         letExternals        , letIntro+       , letElim        , letFloatApp        , letFloatArg        , letFloatLet+       , letFloatLam+       , letFloatCase        , letFloatExpr        , letFloatLetTop        , letToCase@@ -19,24 +21,31 @@ import Data.List import Data.Monoid -import Language.HERMIT.Kure+import Language.HERMIT.Core import Language.HERMIT.Monad+import Language.HERMIT.Kure import Language.HERMIT.External import Language.HERMIT.GHC  import Language.HERMIT.Primitive.Common-import Language.HERMIT.Primitive.GHC hiding (externals)-import Language.HERMIT.Primitive.AlphaConversion hiding (externals)+import Language.HERMIT.Primitive.GHC+import Language.HERMIT.Primitive.AlphaConversion  import qualified Language.Haskell.TH as TH  ------------------------------------------------------------------------------  -- | Externals relating to Let expressions.-externals :: [External]-externals =+letExternals :: [External]+letExternals =          [ external "let-intro" (promoteExprR . letIntro :: TH.Name -> RewriteH Core)                 [ "e => (let v = e in v), name of v is provided" ]                      .+ Shallow .+ Introduce+         , external "dead-let-elimination" (promoteExprR letElim :: RewriteH Core)+                     [ "dead-let-elimination removes an unused let binding."+                     , "(let v = e1 in e2) ==> e2, if v is not free in e2."+                     , "condition: let is not-recursive" ]                                   .+ Eval .+ Shallow .+ Bash+         , external "dead-code-elimination" (promoteExprR letElim :: RewriteH Core)+                     [ "Synonym for dead-let-elimination [deprecated]" ]  .+ Eval .+ Shallow -- TODO: delete this at some point          -- , external "let-constructor-reuse" (promoteR $ not_defined "constructor-reuse" :: RewriteH Core)          --             [ "let v = C v1..vn in ... C v1..vn ... ==> let v = C v1..vn in ... v ..., fails otherwise" ] .+ Unimplemented .+ Eval          , external "let-float-app" (promoteExprR letFloatApp :: RewriteH Core)@@ -44,31 +53,53 @@          , external "let-float-arg" (promoteExprR letFloatArg :: RewriteH Core)                      [ "f (let v = ev in e) ==> let v = ev in f e" ]                    .+ Commute .+ Shallow .+ Bash          , external "let-float-lam" (promoteExprR letFloatLam :: RewriteH Core)-                     [ "(\\ v1 -> let v2 = e1 in e2)  ==>  let v2 = e1 in (\\ v1 -> e2)",-                       "Fails if v1 occurs in e1.",+                     [ "(\\ v1 -> let v2 = e1 in e2)  ==>  let v2 = e1 in (\\ v1 -> e2), if v1 is not free in e2.",                        "If v1 = v2 then v1 will be alpha-renamed."                      ]                                                                  .+ Commute .+ Shallow .+ Bash          , external "let-float-let" (promoteExprR letFloatLet :: RewriteH Core)                      [ "let v = (let w = ew in ev) in e ==> let w = ew in let v = ev in e" ] .+ Commute .+ Shallow .+ Bash-         , external "let-float-top" (promoteProgramR letFloatLetTop :: RewriteH Core)+         , external "let-float-case" (promoteExprR letFloatCase :: RewriteH Core)+                     [ "case (let v = ev in e) of ... ==> let v = ev in case e of ..." ]  .+ Commute .+ Shallow .+ Eval .+ Bash+         , external "let-float-top" (promoteProgR letFloatLetTop :: RewriteH Core)                      [ "v = (let w = ew in ev) : bds ==> w = ew : v = ev : bds" ] .+ Commute .+ Shallow .+ Bash-         , external "let-float" (promoteProgramR letFloatLetTop <+ promoteExprR letFloatExpr :: RewriteH Core)+         , external "let-float" (promoteProgR letFloatLetTop <+ promoteExprR letFloatExpr :: RewriteH Core)                      [ "Float a Let whatever the context." ] .+ Commute .+ Shallow .+ Bash          , external "let-to-case" (promoteExprR letToCase :: RewriteH Core)                      [ "let v = ev in e ==> case ev of v -> e" ] .+ Commute .+ Shallow .+ PreCondition          -- , external "let-to-case-unbox" (promoteR $ not_defined "let-to-case-unbox" :: RewriteH Core)          --             [ "let v = ev in e ==> case ev of C v1..vn -> let v = C v1..vn in e" ] .+ Unimplemented-         , external "nonrec-to-rec" (promoteBindR nonrecToRec :: RewriteH Core)-                     [ "convert a nonrec binding into a recursive binding group with a single binding"-                     , "NonRec v ev ==> Rec [(v,ev)]" ]          ] +-------------------------------------------------------------------------------------------+ -- | e => (let v = e in v), name of v is provided letIntro ::  TH.Name -> RewriteH CoreExpr-letIntro nm = prefixFailMsg "Let introduction failed: " $-              contextfreeT $ \ e -> do letvar <- newVarH (show nm) (exprType e)-                                       return $ Let (NonRec letvar e) (Var letvar)+letIntro nm = prefixFailMsg "Let-introduction failed: " $+              contextfreeT $ \ e -> do guardMsg (not $ isType e) "let expressions may not return a type."+                                       v <- newIdH (show nm) (exprTypeOrKind e)+                                       return $ Let (NonRec v e) (Var v) +-- | Remove an unused let binding.+--   (let v = E1 in E2) => E2, if v is not free in E2+letElim :: RewriteH CoreExpr+letElim = prefixFailMsg "Dead-let-elimination failed: " $+          withPatFailMsg (wrongExprForm "Let (NonRec v e1) e2") $+      do Let (NonRec v _) e <- idR+         guardMsg (v `notElem` coreExprFreeVars e) "let-bound variable appears in the expression."+         return e++-- | let v = ev in e ==> case ev of v -> e+letToCase :: RewriteH CoreExpr+letToCase = prefixFailMsg "Converting Let to Case failed: " $+            withPatFailMsg (wrongExprForm "Let (NonRec v e1) e2") $+  do Let (NonRec v ev) _ <- idR+     guardMsg (not $ isType ev) "cannot case on a type."+     nameModifier <- freshNameGenT Nothing+     caseBndr <- constT (cloneVarH nameModifier v)+     letT mempty (replaceVarR v caseBndr) $ \ () e' -> Case ev caseBndr (varType v) [(DEFAULT, [], e')]++-------------------------------------------------------------------------------------------+ -- | (let v = ev in e) x ==> let v = ev in e x letFloatApp :: RewriteH CoreExpr letFloatApp = prefixFailMsg "Let floating from App function failed: " $@@ -102,27 +133,28 @@       then alphaLam Nothing >>> letFloatLam       else return (Let (NonRec v2 e1) (Lam v1 e2)) +-- | @case (let bnds in e) of wild alts ==> let bnds in (case e of wild alts)@+--   Fails if any variables bound in @bnds@ occurs in @alts@.+letFloatCase :: RewriteH CoreExpr+letFloatCase = prefixFailMsg "Let floating from Case failed: " $+  do captures <- caseT letVarsT+                       (\ _ -> altFreeVarsExclWildT)+                       (\ vs wild _ fs -> vs `intersect` concatMap ($ wild) fs)+     caseT (if null captures then idR else alphaLetVars captures)+           (const idR)+           (\ (Let bnds e) wild ty alts -> Let bnds (Case e wild ty alts))+ -- | Float a Let through an expression, whatever the context. letFloatExpr :: RewriteH CoreExpr letFloatExpr = setFailMsg "Unsuitable expression for Let floating." $-               letFloatApp <+ letFloatArg <+ letFloatLet <+ letFloatLam---- | NonRec v (Let (NonRec w ew) ev) : bds ==> NonRec w ew : NonRec v ev : bds-letFloatLetTop :: RewriteH CoreProgram-letFloatLetTop = setFailMsg ("Let floating to top level failed: " ++ wrongExprForm "NonRec v (Let (NonRec w ew) ev) : bds") $-  do NonRec v (Let (NonRec w ew) ev) : bds <- idR-     return (NonRec w ew : NonRec v ev : bds)+               letFloatApp <+ letFloatArg <+ letFloatLet <+ letFloatLam <+ letFloatCase --- | let v = ev in e ==> case ev of v -> e-letToCase :: RewriteH CoreExpr-letToCase = prefixFailMsg "Converting Let to Case failed: " $-            withPatFailMsg (wrongExprForm "Let (NonRec v e1) e2") $-  do Let (NonRec v ev) _ <- idR-     nameModifier <- freshNameGenT Nothing-     caseBndr <- constT (cloneIdH nameModifier v)-     letT mempty (renameIdR v caseBndr) $ \ () e' -> Case ev caseBndr (varType v) [(DEFAULT, [], e')]+-- | NonRec v (Let (NonRec w ew) ev) `ProgCons` p ==> NonRec w ew `ProgCons` NonRec v ev `ProgCons` p+letFloatLetTop :: RewriteH CoreProg+letFloatLetTop = prefixFailMsg "Let floating to top level failed: " $+                 withPatFailMsg (wrongExprForm "NonRec v (Let (NonRec w ew) ev) `ProgCons` p") $+  do NonRec v (Let (NonRec w ew) ev) `ProgCons` p <- idR+     guardMsg (not $ isType ew) "type bindings are not allowed at the top level."+     return (NonRec w ew `ProgCons` NonRec v ev `ProgCons` p) -nonrecToRec :: RewriteH CoreBind-nonrecToRec = do-    NonRec v ev <- idR-    return $ Rec [(v,ev)]+-------------------------------------------------------------------------------------------
src/Language/HERMIT/Primitive/Navigation.hs view
@@ -13,16 +13,17 @@  import GhcPlugins as GHC +import Language.HERMIT.Core import Language.HERMIT.Kure import Language.HERMIT.External import Language.HERMIT.GHC  import Control.Arrow -import Data.Monoid- import qualified Language.Haskell.TH as TH +---------------------------------------------------------------------------------------+ -- | 'External's involving navigating to named entities. externals :: [External] externals = map (.+ Navigation)@@ -38,6 +39,8 @@                 [ "binding-group-of '<v> focuses on the binding group that binds the variable <v>" ]             ] +---------------------------------------------------------------------------------------+ -- | Find the path to the RHS of the binding group of the given name. bindingGroupOf :: TH.Name -> TranslateH Core Path bindingGroupOf = oneNonEmptyPathToT . bindGroup@@ -52,23 +55,30 @@  -- | Verify that this is a binding group defining the given name. bindGroup :: TH.Name -> Core -> Bool-bindGroup nm (BindCore (NonRec v _))  =  nm `cmpTHName2Id` v-bindGroup nm (BindCore (Rec bds))     =  any (cmpTHName2Id nm . fst) bds+bindGroup nm (BindCore (NonRec v _))  =  nm `cmpTHName2Var` v+bindGroup nm (BindCore (Rec bds))     =  any (cmpTHName2Var nm . fst) bds bindGroup _  _                        =  False  -- | Verify that this is the definition of the given name. namedBinding :: TH.Name -> Core -> Bool-namedBinding nm (BindCore (NonRec v _))  =  nm `cmpTHName2Id` v-namedBinding nm (DefCore (Def v _))      =  nm `cmpTHName2Id` v+namedBinding nm (BindCore (NonRec v _))  =  nm `cmpTHName2Var` v+namedBinding nm (DefCore (Def v _))      =  nm `cmpTHName2Var` v namedBinding _  _                        =  False  -- | Find all the possible targets of \"consider\". considerTargets :: TranslateH Core [String]-considerTargets = allT (collectT (promoteT $ nonRec <+ rec)) >>> arr concat-    where nonRec = nonRecT mempty (\ v () -> [unqualifiedIdName v])-          rec    = recT (const (arr (\ (Def v _) -> unqualifiedIdName v))) id+considerTargets = allT $ collectT (promoteBindT nonRec <+ promoteDefT def)+    where+      nonRec :: TranslateH CoreBind String+      nonRec = nonRecT (return ()) constUnq +      def :: TranslateH CoreDef String+      def = defT (return ()) constUnq +      constUnq :: Var -> () -> String+      constUnq v () = unqualifiedVarName v++ data Considerable = Binding | Definition | CaseAlt | Variable | Literal | Application | Lambda | LetIn | CaseOf | Casty | Ticky | TypeVar | Coerce  recognizedConsiderables :: String@@ -115,3 +125,5 @@ underConsideration TypeVar     (ExprCore (Type _))        = True underConsideration Coerce      (ExprCore (Coercion _))    = True underConsideration _           _                          = False++---------------------------------------------------------------------------------------
src/Language/HERMIT/Primitive/New.hs view
@@ -1,5 +1,3 @@-{-# LANGUAGE TypeFamilies, FlexibleInstances #-}- -- Placeholder for new prims module Language.HERMIT.Primitive.New where @@ -7,41 +5,28 @@  import Control.Applicative import Control.Arrow-import Control.Monad -import Data.List(intercalate,intersect)+import Data.List(intersect) -import Language.HERMIT.Context+import Language.HERMIT.Core import Language.HERMIT.Monad import Language.HERMIT.Kure import Language.HERMIT.External import Language.HERMIT.GHC++import Language.HERMIT.Primitive.Common import Language.HERMIT.Primitive.GHC-import Language.HERMIT.Primitive.Utils import Language.HERMIT.Primitive.Local-import Language.HERMIT.Primitive.Local.Case-import Language.HERMIT.Primitive.Local.Let import Language.HERMIT.Primitive.Inline -- import Language.HERMIT.Primitive.Debug  import qualified Language.Haskell.TH as TH --- import Debug.Trace-import MonadUtils (MonadIO) -- GHC's MonadIO - externals ::  [External] externals = map ((.+ Experiment) . (.+ TODO))-         [ external "info" (info :: TranslateH Core String)-                [ "tell me what you know about this expression or binding" ] .+ Unimplemented-         , external "expr-type" (promoteExprT exprTypeT :: TranslateH Core String)-                [ "display the type of this expression"]-         , external "test" (testQuery :: RewriteH Core -> TranslateH Core String)+         [ external "test" (testQuery :: RewriteH Core -> TranslateH Core String)                 [ "determines if a rewrite could be successfully applied" ]-         , external "fix-intro" (promoteDefR fixIntro :: RewriteH Core)-                [ "rewrite a recursive binding into a non-recursive binding using fix" ]-         , external "fix-spec" (promoteExprR fixSpecialization :: RewriteH Core)-                [ "specialize a fix with a given argument"] .+ Shallow          , external "cleanup-unfold" (promoteExprR cleanupUnfold :: RewriteH Core)                 [ "clean up immeduate nested fully-applied lambdas, from the bottom up"]          , external "unfold" (promoteExprR . unfold :: TH.Name -> RewriteH Core)@@ -56,148 +41,62 @@                  [ "var '<v> returns successfully for variable v, and fails otherwise.",                    "Useful in combination with \"when\", as in: when (var v) r" ] .+ Predicate          , external "simplify" (simplifyR :: RewriteH Core)-                [ "innermost (unfold '. <+ beta-reduce-plus <+ safe-let-subst <+ case-reduce <+ dead-code-elimination)" ]+                [ "innermost (unfold '. <+ beta-reduce-plus <+ safe-let-subst <+ case-reduce <+ dead-let-elimination)" ]          , external "let-tuple" (promoteExprR . letTupleR :: TH.Name -> RewriteH Core)                 [ "let x = e1 in (let y = e2 in e) ==> let t = (e1,e2) in (let x = fst t in (let y = snd t in e))" ]          , external "any-call" (withUnfold :: RewriteH Core -> RewriteH Core)                 [ "any-call (.. unfold command ..) applies an unfold commands to all applications"                 , "preference is given to applications with more arguments"                 ] .+ Deep-         , external "abstract" (promoteExprR . abstract :: TH.Name -> RewriteH Core)-                [ "Abstract over a variable using a lambda.",-                  "e  ==>  (\\ x -> e) x"-                ] .+ Shallow .+ Introduce .+ Context          ] +------------------------------------------------------------------------------------------------------ +-- TODO: what about Type constructors around TyVars? isVar :: TH.Name -> TranslateH CoreExpr ()-isVar nm = varT (cmpTHName2Id nm) >>= guardM+isVar nm = varT (cmpTHName2Var nm) >>= guardM +------------------------------------------------------------------------------------------------------+ simplifyR :: RewriteH Core-simplifyR = innermostR (promoteExprR (unfold (TH.mkName ".") <+ betaReducePlus <+ safeLetSubstR <+ caseReduce <+ dce))+simplifyR = setFailMsg "Simplify failed: nothing to simplify." $+            innermostR (promoteExprR (unfold (TH.mkName ".") <+ betaReducePlus <+ safeLetSubstR <+ caseReduce <+ letElim)) --- This left for Neil's IFL presentation. letTupleR is the more general version.-letPairR :: TH.Name -> RewriteH CoreExpr-letPairR nm = do-    Let (NonRec x e1) (Let (NonRec y e2) e) <- idR-    ifM (letT (nonRecT (pure ()) const)-              (letT (nonRecT freeVarsT (flip const)) (pure ()) const)-              elem)-        (fail "'x' is used in 'e2'")-        (translate $ \ c _ -> do-              tupleConId <- findId c "(,)"-              fstId <- findId c "Data.Tuple.fst"-              sndId <- findId c "Data.Tuple.snd"-              let e1TyE = Type (exprType e1)-                  e2TyE = Type (exprType e2)-                  rhs = mkCoreApps (Var tupleConId) [e1TyE, e2TyE, e1, e2]-              letId <- newVarH (show nm) (exprType rhs)-              let fstE = mkCoreApps (Var fstId) [e1TyE, e2TyE, Var letId]-                  sndE = mkCoreApps (Var sndId) [e1TyE, e2TyE, Var letId]-              return $ Let (NonRec letId rhs)-                      $ Let (NonRec x fstE)-                       $ Let (NonRec y sndE) e) -letTupleR :: TH.Name -> RewriteH CoreExpr-letTupleR nm = translate $ \ c e -> do-    let collectLets :: CoreExpr -> ([(Id, CoreExpr)],CoreExpr)-        collectLets (Let (NonRec x e1) e2) = let (bs,expr) = collectLets e2-                                             in ((x,e1):bs, expr)-        collectLets expr = ([],expr)--        (bnds, body) = collectLets e--    guardMsg (length bnds > 1) "cannot tuple: need at least two nonrec lets"--    -- until we no longer need letPairR-    if length bnds == 2-      then apply (letPairR nm) c e-      else do-        -- check if tupling the bindings would cause unbound variables-        let (ids, rhss) = unzip bnds--        frees <- mapM (apply freeVarsT c) (drop 1 rhss)+collectLets :: CoreExpr -> ([(Var, CoreExpr)],CoreExpr)+collectLets (Let (NonRec x e1) e2) = let (bs,expr) = collectLets e2 in ((x,e1):bs, expr)+collectLets expr                   = ([],expr) -        let used = concat $ zipWith intersect (map (flip take ids) [1..]) frees+-- | Combine nested non-recursive lets into case of a tuple.+letTupleR :: TH.Name -> RewriteH CoreExpr+letTupleR nm = prefixFailMsg "Let-tuple failed: " $+  do (bnds, body) <- arr collectLets+     let numBnds = length bnds+     guardMsg (numBnds > 1) "at least two non-recursive let bindings required." -        if null used-          then do-            tupleConId <- findId c $ "(" ++ replicate (length bnds - 1) ',' ++ ")"+     let (vs, rhss)  = unzip bnds+     guardMsg (all isId vs) "cannot tuple type variables." -- TODO: it'd be better if collectLets stopped on reaching a TyVar -            let rhs = mkCoreApps (Var tupleConId) $ map (Type . exprType) rhss ++ rhss-                varList = concat $ iterate (zipWith (flip (++)) $ repeat "0") $ map (:[]) ['a'..'z']-            dc <- maybe (fail "cannot find tuple datacon") return $ isDataConId_maybe tupleConId-            vs <- zipWithM newVarH varList $ dataConInstOrigArgTys dc $ map exprType rhss+     -- check if tupling the bindings would cause unbound variables+     let+         rhsTypes = map exprType rhss+         frees    = map coreExprFreeVars (drop 1 rhss)+         used     = concat $ zipWith intersect (map (`take` vs) [1..]) frees+     if null used+       then do tupleConId <- findIdT $ TH.mkName $ "(" ++ replicate (numBnds - 1) ',' ++ ")"+               case isDataConId_maybe tupleConId of+                 Nothing -> fail "cannot find tuple data constructor."+                 Just dc -> let rhs = mkCoreApps (Var tupleConId) $ map Type rhsTypes ++ rhss+                             in constT $ do wild <- newIdH (show nm) (exprType rhs)+                                            return $ Case rhs wild (exprType body) [(DataAlt dc, vs, body)] -            letId <- newVarH (show nm) (exprType rhs)-            return $ Let (NonRec letId rhs)-                     $ foldr (\ (i,(v,oe)) b -> Let (NonRec v (Case (Var letId) letId (exprType oe) [(DataAlt dc, vs, Var $ vs !! i)])) b)-                             body $ zip [0..] bnds-          else fail "cannot tuple: some bindings are used in the rhs of others"+       else fail $ "the following bound variables are used in subsequent bindings: " ++ showVars used  -- Others -- let v = E1 in E2 E3 <=> (let v = E1 in E2) E3 -- let v = E1 in E2 E3 <=> E2 (let v = E1 in E3) --- A few Queries.--info :: TranslateH Core String-info = translate $ \ c core -> do-         dynFlags <- getDynFlags-         let pa       = "Path: " ++ show (contextPath c)-             node     = "Node: " ++ coreNode core-             con      = "Constructor: " ++ coreConstructor core-             bds      = "Bindings in Scope: " ++ (show $ map unqualifiedIdName $ listBindings c)-             expExtra = case core of-                          ExprCore e -> ["Type: " ++ showExprType dynFlags e] ++-                                        ["Free Variables: " ++ showVars dynFlags (coreExprFreeVars e)] ++-                                           case e of-                                             Var v -> ["Identifier Info: " ++ showIdInfo dynFlags v]-                                             _     -> []-                          _          -> []--         return (intercalate "\n" $ [pa,node,con,bds] ++ expExtra)--exprTypeT :: TranslateH CoreExpr String-exprTypeT = contextfreeT $ \ e -> do-    dynFlags <- getDynFlags-    return $ showExprType dynFlags e--showExprType :: DynFlags -> CoreExpr -> String-showExprType dynFlags = showPpr dynFlags . exprType--showIdInfo :: DynFlags -> Id -> String-showIdInfo dynFlags v = showSDoc dynFlags $ ppIdInfo v $ idInfo v--coreNode :: Core -> String-coreNode (ModGutsCore _) = "Module"-coreNode (ProgramCore _) = "Program"-coreNode (BindCore _)    = "Binding Group"-coreNode (DefCore _)     = "Recursive Definition"-coreNode (ExprCore _)    = "Expression"-coreNode (AltCore _)     = "Case Alternative"--coreConstructor :: Core -> String-coreConstructor (ModGutsCore _)    = "ModGuts"-coreConstructor (ProgramCore prog) = case prog of-                                       []    -> "[]"-                                       (_:_) -> "(:)"-coreConstructor (BindCore bnd)     = case bnd of-                                       Rec _      -> "Rec"-                                       NonRec _ _ -> "NonRec"-coreConstructor (DefCore _)        = "Def"-coreConstructor (AltCore _)        = "(,,)"-coreConstructor (ExprCore expr)    = case expr of-                                       Var _        -> "Var"-                                       Type _       -> "Type"-                                       Lit _        -> "Lit"-                                       App _ _      -> "App"-                                       Lam _ _      -> "Lam"-                                       Let _ _      -> "Let"-                                       Case _ _ _ _ -> "Case"-                                       Cast _ _     -> "Cast"-                                       Tick _ _     -> "Tick"-                                       Coercion _   -> "Coercion"+------------------------------------------------------------------------------------------------------  testQuery :: RewriteH Core -> TranslateH Core String testQuery r = f <$> testM r@@ -205,80 +104,7 @@     f True  = "Rewrite would succeed."     f False = "Rewrite would fail." -findId :: (MonadUnique m, MonadIO m, MonadThings m, HasDynFlags m) => Context -> String -> m Id-findId c = findIdMG (hermitModGuts c)--findIdMG :: (MonadUnique m, MonadIO m, MonadThings m, HasDynFlags m) => ModGuts -> String -> m Id-findIdMG modguts nm =-    case filter isValName $ findNameFromTH (mg_rdr_env modguts) $ TH.mkName nm of-        []  -> fail $ "cannot find " ++ nm-        [n] -> lookupId n-        ns  -> do dynFlags <- getDynFlags-                  fail $ "too many " ++ nm ++ " found:\n" ++ intercalate ", " (map (showPpr dynFlags) ns)---- |  f = e   ==>   f = fix (\ f -> e)-fixIntro :: RewriteH CoreDef-fixIntro = prefixFailMsg "Fix introduction failed: " $-           do (c, Def f e) <- exposeT-              constT $ do fixId <- findId c "Data.Function.fix"-                          f' <- cloneIdH id f-                          let coreFix = App (App (Var fixId) (Type (idType f)))-                              emptySub = mkEmptySubst (mkInScopeSet (exprFreeVars e))-                              sub      = extendSubst emptySub f (Var f')-                          return $ Def f (coreFix (Lam f' (substExpr (text "fixIntro") sub e)))---- ironically, this is an instance of worker/wrapper itself.--fixSpecialization :: RewriteH CoreExpr-fixSpecialization = do-        fixId <- translate $ \ c _ -> findId c "Data.Function.fix"--        -- fix (t::*) (f :: t -> t) (a :: t) :: t-        App (App (App (Var fx) (Type _)) _) _ <- idR--        guardMsg (fx == fixId) "fixSpecialization only works on fix"--        let rr :: RewriteH CoreExpr-            rr = multiEtaExpand [TH.mkName "f",TH.mkName "a"]--            sub :: RewriteH Core-            sub = pathR [0,1] (promoteR rr)-        -- be careful this does not loop (it should not)-        extractR sub >>> fixSpecialization'---fixSpecialization' :: RewriteH CoreExpr-fixSpecialization' = do-        -- In normal form now-        App (App (App (Var fx) (Type t))-                 (Lam _ (Lam v2 (App (App e _) _a2)))-            )-            a <- idR--        let t' = case a of-                   Type t2  -> applyTy t t2-                   (Var x) | isTyVar x -> applyTy t (mkTyVarTy x)---                   Var  a2  -> mkAppTy t (exprType t2)---                   mkAppTy t t'---        -- TODO: t2' isn't used anywhere -- which means that a2 is never used ???---        let t2' = case a2 of---                   Type t2  -> applyTy t t2---                   Var  a2  -> mkAppTy t (exprType t2)---                   mkAppTy t t'---        v3 <- constT $ newVarH "f" t' -- (funArgTy t')-        v4 <- constT $ newTypeVarH "a" (tyVarKind v2)--         -- f' :: \/ a -> T [a] -> (\/ b . T [b])-        let f' = Lam v4  (Cast (Var v3)-                               (mkUnsafeCo t' (applyTy t (mkTyVarTy v4))))-        let e' = Lam v3 (App (App e f') a)--        return $ App (App (Var fx) (Type t')) e'-+------------------------------------------------------------------------------------------------------  -- | cleanupUnfold cleans a unfold operation --  (for example, an inline or rule application)@@ -313,6 +139,7 @@         rec :: RewriteH Core         rec = withUnfold rr +------------------------------------------------------------------------------------------------------  -- | Push a function through a Case or Let expression. --   Unsafe if the function is not strict.@@ -321,7 +148,7 @@      do e <- idR         case collectArgs e of           (Var v,args) -> do-                  guardMsg (nm `cmpTHName2Id` v) $ "could not find name " ++ show nm+                  guardMsg (nm `cmpTHName2Var` v) $ "cannot find name " ++ show nm                   guardMsg (not $ null args) $ "no argument for " ++ show nm                   guardMsg (all isTypeArg $ init args) $ "initial arguments are not type arguments for " ++ show nm                   case last args of@@ -330,13 +157,4 @@                      _       -> fail "argument is not a Case or Let."           _ -> fail "no function to match." --- | Abstract over a variable using a lambda.---   e  ==>  (\ x. e) x-abstract :: TH.Name -> RewriteH CoreExpr-abstract nm = prefixFailMsg "abstraction failed: " $-    do (c,e) <- exposeT-       let name = TH.nameBase nm-       case filter (cmpTHName2Id nm) (listBindings c) of-         []         -> fail $ name ++ " is not in scope."-         [v]        -> return (App (Lam v e) (Var v)) -- There might be issues if "v" is a type variable, I'm not sure.-         _ : _ : _  -> fail $ "multiple variables named " ++ name ++ " in scope."+------------------------------------------------------------------------------------------------------
src/Language/HERMIT/Primitive/Unfold.hs view
@@ -13,7 +13,7 @@ import Language.HERMIT.Primitive.GHC hiding (externals) import Language.HERMIT.Primitive.Common -import Language.HERMIT.CoreExtra+import Language.HERMIT.Core import Language.HERMIT.Kure import Language.HERMIT.Monad import Language.HERMIT.External@@ -70,7 +70,7 @@ getUnfolding :: Monad m              => Bool -- ^ Get the scrutinee instead of the patten match (for case binders).              -> Bool -- ^ Only succeed if this variable is a case binder.-             -> Id -> Context -> m (CoreExpr, Int)+             -> Id -> HermitC -> m (CoreExpr, Int) getUnfolding scrutinee caseBinderOnly i c =     case lookupHermitBinding i c of         Nothing -> case unfoldingInfo (idInfo i) of
− src/Language/HERMIT/Primitive/Utils.hs
@@ -1,12 +0,0 @@---- Utils for primitives, not the primitives themselves--module Language.HERMIT.Primitive.Utils where--import GhcPlugins as GHC---- appCount counts the number of applications / arguments are present-appCount :: CoreExpr -> Int-appCount (App e1 _) = appCount e1 + 1-appCount _          = 0-
src/Language/HERMIT/Shell/Command.hs view
@@ -23,14 +23,16 @@ import qualified Data.Map as M import Data.Maybe +import Language.HERMIT.Core+import Language.HERMIT.Monad+import Language.HERMIT.Kure import Language.HERMIT.Dictionary import Language.HERMIT.Expr import Language.HERMIT.External import Language.HERMIT.Interp import Language.HERMIT.Kernel.Scoped-import Language.HERMIT.Kure-import Language.HERMIT.Monad import Language.HERMIT.PrettyPrinter+ import Language.HERMIT.Primitive.Navigation import Language.HERMIT.Primitive.Inline @@ -43,13 +45,12 @@  import System.Console.Haskeline hiding (catch) --- There are 3 types of commands, AST effect-ful, Shell effect-ful, and Queries.+-- There are 4 types of commands, AST effect-ful, Shell effect-ful, Queries, and Meta-commands. -data ShellCommand :: * where-   AstEffect     :: AstEffect                -> ShellCommand-   ShellEffect   :: ShellEffect              -> ShellCommand-   QueryFun      :: QueryFun                 -> ShellCommand-   MetaCommand   :: MetaCommand              -> ShellCommand+data ShellCommand =  AstEffect   AstEffect+                  |  ShellEffect ShellEffect+                  |  QueryFun    QueryFun+                  |  MetaCommand MetaCommand  -- | AstEffects are things that are recorded in our log and saved files. @@ -60,8 +61,8 @@    | Pathfinder (TranslateH Core Path)    -- | This changes the currect location using directions    | Direction  Direction-   -- | This changes the current location using a give path-   | PushFocus Path+   --  | This changes the current location using a give path+--   | PushFocus Path     | BeginScope    | EndScope@@ -71,9 +72,9 @@    deriving Typeable  instance Extern AstEffect where-    type Box AstEffect = AstEffect-    box i = i-    unbox i = i+   type Box AstEffect = AstEffect+   box i = i+   unbox i = i  data ShellEffect :: * where    SessionStateEffect    :: (CommandLineState -> SessionState -> IO SessionState) -> ShellEffect@@ -89,9 +90,9 @@    deriving Typeable  instance Extern QueryFun where-    type Box QueryFun = QueryFun-    box i = i-    unbox i = i+   type Box QueryFun = QueryFun+   box i = i+   unbox i = i  data MetaCommand    = Resume@@ -129,7 +130,6 @@ interpShellCommand :: [Interp ShellCommand] interpShellCommand =                 [ interp $ \ (ShellCommandBox cmd)       -> cmd-                , interp $ \ (IntBox i)                  -> AstEffect (PushFocus [i])                 , interp $ \ (RewriteCoreBox rr)         -> AstEffect (Apply rr)                 , interp $ \ (TranslateCorePathBox tt)   -> AstEffect (Pathfinder tt)                 , interp $ \ (StringBox str)             -> QueryFun (Message str)@@ -222,7 +222,7 @@ changeRenderer :: String -> ShellEffect changeRenderer renderer = SessionStateEffect $ \ _ st ->         case lookup renderer finalRenders of-          Nothing -> return st          -- should fail with message+          Nothing -> return st          -- TODO: should fail with message           Just r  -> return $ st { cl_render = r }  ----------------------------------------------------------------------------------@@ -251,20 +251,20 @@ type CLM m a = ErrorT String (StateT CommandLineState m) a  -- TODO: Come up with names for these, and/or better characterise these abstractions.-iokm2clm' :: MonadIO m => String -> (a -> CLM m b) -> IO (KureMonad a) -> CLM m b-iokm2clm' msg ret m = liftIO m >>= runKureMonad ret (throwError . (msg ++))+iokm2clm' :: MonadIO m => String -> (a -> CLM m b) -> IO (KureM a) -> CLM m b+iokm2clm' msg ret m = liftIO m >>= runKureM ret (throwError . (msg ++)) -iokm2clm :: MonadIO m => String -> IO (KureMonad a) -> CLM m a+iokm2clm :: MonadIO m => String -> IO (KureM a) -> CLM m a iokm2clm msg = iokm2clm' msg return  data CommandLineState = CommandLineState         { cl_graph       :: [(SAST,ExprH,SAST)]         , cl_tags        :: [(String,SAST)]         -- these two should be in a reader-        , cl_dict        :: M.Map String [Dynamic]-        , cl_kernel       :: ScopedKernel+        , cl_dict        :: Dictionary+        , cl_kernel      :: ScopedKernel         -- and the session state (perhaps in a seperate state?)-        , cl_session      :: SessionState+        , cl_session     :: SessionState         }  newSAST :: ExprH -> SAST -> CommandLineState -> CommandLineState@@ -274,14 +274,14 @@  -- Session-local issues; things that are never saved. data SessionState = SessionState-        { cl_cursor      :: SAST              -- ^ the current AST-        , cl_pretty      :: String           -- ^ which pretty printer to use-        , cl_pretty_opts :: PrettyOptions -- ^ The options for the pretty printer+        { cl_cursor      :: SAST                                       -- ^ the current AST+        , cl_pretty      :: String                                     -- ^ which pretty printer to use+        , cl_pretty_opts :: PrettyOptions                              -- ^ The options for the pretty printer         , cl_render      :: Handle -> PrettyOptions -> DocH -> IO ()   -- ^ the way of outputing to the screen-        , cl_width       :: Int                 -- ^ how wide is the screen?-        , cl_nav         :: Bool        -- ^ keyboard input the the nav panel-        , cl_loading     :: Bool        -- ^ if loading a file-        , cl_tick        :: TVar (M.Map String Int)     -- ^ The list of ticked messages+        , cl_width       :: Int                                        -- ^ how wide is the screen?+        , cl_nav         :: Bool                                       -- ^ keyboard input the the nav panel+        , cl_loading     :: Bool                                       -- ^ if loading a file+        , cl_tick        :: TVar (M.Map String Int)                    -- ^ The list of ticked messages         }  -------------------------------------------------------------------------------@@ -292,7 +292,7 @@                     | AmbiguousC [CompletionType]  -- completionType function needs to be more specific     deriving (Show) --- todo: reverse rPrev and parse it, to better figure out what possiblities are in context?+-- TODO: reverse rPrev and parse it, to better figure out what possiblities are in context? --       for instance, completing "any-bu (inline " should be different than completing just "inline " --       this would also allow typed completion? completionType :: String -> CompletionType@@ -324,7 +324,7 @@     --     $ queryS (cl_kernel st) (cl_cursor (cl_session st)) targetQuery     -- TODO: I expect you want to build a silent version of the kernal_env for this query     mcls <- queryS (cl_kernel st) (cl_cursor (cl_session st)) targetQuery (cl_kernel_env (cl_session st))-    cl <- runKureMonad return fail mcls -- TO DO: probably shouldn't use fail here.+    cl <- runKureM return fail mcls -- TO DO: probably shouldn't use fail here.     return $ (map simpleCompletion . nub . filter (so_far `isPrefixOf`)) cl  -- | The first argument is a list of files to load.@@ -383,7 +383,7 @@                          `ourCatch` (liftIO . putStrLn)                            >> loop' -ourCatch :: (MonadIO n) => CLM IO () -> (String -> CLM n ()) -> CLM n ()+ourCatch :: MonadIO m => CLM IO () -> (String -> CLM m ()) -> CLM m () ourCatch m failure = do                 st <- get                 (res,st') <- liftIO $ runStateT (runErrorT m) st@@ -394,7 +394,7 @@   -evalStmts :: (MonadIO m) => [StmtH ExprH] -> CLM m ()+evalStmts :: MonadIO m => [StmtH ExprH] -> CLM m () evalStmts = mapM_ evalExpr . scopes     where scopes :: [StmtH ExprH] -> [ExprH]           scopes [] = []@@ -402,7 +402,7 @@           scopes (ScopeH s:ss) = (CmdName "{" : scopes s) ++ [CmdName "}"] ++ scopes ss  -evalExpr :: (MonadIO m) => ExprH -> CLM m ()+evalExpr :: MonadIO m => ExprH -> CLM m () evalExpr expr = do     dict <- gets cl_dict     case interpExprH dict interpShellCommand expr of@@ -437,20 +437,11 @@  performAstEffect (Direction dir) expr = do     st <- get-    -- This seems unnecassary.  But if you restore it, note that it needs editing so that it doesn't print if we're loading a file.-    -- child_count <- iokm2clm "Could not compute number of children:" $ queryS (cl_kernel st) (cl_cursor (cl_session st)) numChildrenT (cl_kernel_env (cl_session st))-    -- liftIO $ print (child_count, dir)     ast <- iokm2clm "Invalid move: " $ modPathS (cl_kernel st) (cl_cursor $ cl_session st) (moveLocally dir) (cl_kernel_env $ cl_session st)     put $ newSAST expr ast st     -- something changed, to print     showFocus -performAstEffect (PushFocus p) expr = do-    st <- get-    ast <- iokm2clm "Invalid push: " $ modPathS (cl_kernel st) (cl_cursor $ cl_session st) (extendLocalPath p) (cl_kernel_env $ cl_session st)-    put $ newSAST expr ast st-    showFocus- performAstEffect BeginScope expr = do         st <- get         ast <- liftIO $ beginScopeS (cl_kernel st) (cl_cursor (cl_session st))@@ -471,14 +462,8 @@         st <- get         -- TODO: Again, we may want a quiet version of the kernel_env         liftIO (queryS (cl_kernel st) (cl_cursor $ cl_session st) q (cl_kernel_env $ cl_session st))-          >>= runKureMonad (\ () -> putStrToConsole $ unparseExprH expr ++ " [correct]")-                           (\ err -> fail $ unparseExprH expr ++ " [exception: " ++ err ++ "]")-        -- correctness <- liftIO (try $ queryS (cl_kernel st) (cl_cursor (cl_session st)) q)-        -- case correctness of-        --   Right ()  -> do putStrToConsole $ unparseExprH expr ++ " [correct]"-        --   Left (err :: IOException)-        --            -> fail $ unparseExprH expr ++ " [exception: " ++ show err ++ "]"-+          >>= runKureM (\ () -> putStrToConsole $ unparseExprH expr ++ " [correct]")+                       (\ err -> fail $ unparseExprH expr ++ " [exception: " ++ err ++ "]")  ------------------------------------------------------------------------------- @@ -508,13 +493,6 @@ -- These two need to use Inquiry performQuery (Message msg) = liftIO (putStrLn msg) performQuery Display = showFocus-  -- do-  --   st <- get-  --   liftIO $ do-  --       ps <- pathS (cl_kernel st) (cl_cursor (cl_session st))-  --       putStrLn $ "Paths: " ++ show ps-  --       print ("Graph",cl_graph st)-  --       print ("This",cl_cursor (cl_session st))  ------------------------------------------------------------------------------- @@ -525,12 +503,12 @@ performMetaCommand (Dump fileName _pp renderer width) = do     st <- get     case (M.lookup (cl_pretty (cl_session st)) pp_dictionary,lookup renderer finalRenders) of-        (Just pp, Just r) -> do doc <- iokm2clm "Bad pretty-printer or renderer option: " $-                                           queryS (cl_kernel st) (cl_cursor $ cl_session st) (pp (cl_pretty_opts $ cl_session st)) (cl_kernel_env $ cl_session st)-                                liftIO $ do h <- openFile fileName WriteMode-                                            r h ((cl_pretty_opts $ cl_session st) { po_width = width }) doc-                                            hClose h-        _ -> throwError "dump: bad pretty-printer or renderer option"+      (Just pp, Just r) -> do doc <- iokm2clm "Bad pretty-printer or renderer option: " $+                                         queryS (cl_kernel st) (cl_cursor $ cl_session st) (pp (cl_pretty_opts $ cl_session st)) (cl_kernel_env $ cl_session st)+                              liftIO $ do h <- openFile fileName WriteMode+                                          r h ((cl_pretty_opts $ cl_session st) { po_width = width }) doc+                                          hClose h+      _ -> throwError "dump: bad pretty-printer or renderer option" performMetaCommand (LoadFile fileName) = do         putStrToConsole $ "[loading " ++ fileName ++ "]"         res <- liftIO $ try (readFile fileName)@@ -619,14 +597,14 @@            all_nds <- listS (cl_kernel st)            if SAST n `elem` all_nds               then return $ sess_st { cl_cursor = SAST n }-              else fail $ "Can not find AST #" ++ show n+              else fail $ "Cannot find AST #" ++ show n ++ "."       GotoTag tag -> case lookup tag (cl_tags st) of                        Just sast -> return $ sess_st { cl_cursor = sast }-                       Nothing   -> fail $ "Can not find tag " ++ show tag+                       Nothing   -> fail $ "Cannot find tag " ++ show tag ++ "."       Step -> do            let ns = [ edge | edge@(s,_,_) <- cl_graph st, s == cl_cursor (cl_session st) ]            case ns of-             [] -> fail "Cannot step forward (no more steps)"+             [] -> fail "Cannot step forward (no more steps)."              [(_,cmd,d) ] -> do                            putStrLn $ "step : " ++ unparseExprH cmd                            return $ sess_st { cl_cursor = d }@@ -634,11 +612,11 @@       Back -> do            let ns = [ edge | edge@(_,_,d) <- cl_graph st, d == cl_cursor (cl_session st) ]            case ns of-             []         -> fail "Cannot step backwards (no more steps)"+             []         -> fail "Cannot step backwards (no more steps)."              [(s,cmd,_) ] -> do                            putStrLn $ "back, unstepping : " ++ unparseExprH cmd                            return $ sess_st { cl_cursor = s }-             _          -> fail "Cannot step backwards (multiple choices, impossible!)"+             _          -> fail "Cannot step backwards (multiple choices, impossible!)."  --------------------------------------------------------