packages feed

hermit 0.6.0.0 → 0.7.0.0

raw patch · 80 files changed

+6247/−3483 lines, 80 filesdep +data-default-classdep +transformers-compatdep −data-defaultdep ~kuredep ~transformersPVP ok

version bump matches the API change (PVP)

Dependencies added: data-default-class, transformers-compat

Dependencies removed: data-default

Dependency ranges changed: kure, transformers

API changes (from Hackage documentation)

- HERMIT.Core: deprecatedLeftSibling :: Crumb -> Maybe Crumb
- HERMIT.Core: deprecatedRightSibling :: Crumb -> Maybe Crumb
- HERMIT.Dictionary.Common: inScope :: ReadBindings c => c -> Var -> Bool
- HERMIT.Dictionary.Fold: stashFoldAnyR :: (ReadBindings c, HasStash m, MonadCatch m) => Rewrite c m CoreExpr
- HERMIT.Dictionary.Fold: stashFoldR :: (ReadBindings c, HasStash m, MonadCatch m) => RememberedName -> Rewrite c m CoreExpr
- HERMIT.Dictionary.Fold: tyMatchesToCoreExpr :: [(TyVar, Type)] -> [(Var, CoreExpr)]
- HERMIT.Dictionary.Fold: unifyTypes :: [TyVar] -> Type -> Type -> Maybe [(TyVar, Type)]
- HERMIT.Dictionary.Function: buildApplicationM :: (HasDynFlags m, MonadCatch m, MonadIO m) => CoreExpr -> CoreExpr -> m CoreExpr
- HERMIT.Dictionary.GHC: substCoreAlt :: Var -> CoreExpr -> CoreAlt -> CoreAlt
- HERMIT.Dictionary.GHC: substCoreExpr :: Var -> CoreExpr -> (CoreExpr -> CoreExpr)
- HERMIT.Dictionary.Reasoning: alphaEqualityR :: (Var -> Bool) -> (String -> String) -> RewriteH Equality
- HERMIT.Dictionary.Reasoning: flipEquality :: Equality -> Equality
- HERMIT.Dictionary.Reasoning: insertLemmaR :: (HasLemmas m, Monad m) => LemmaName -> Lemma -> Rewrite c m a
- HERMIT.Dictionary.Reasoning: instance BuildEquality (CoreExpr, CoreExpr)
- HERMIT.Dictionary.Reasoning: instance BuildEquality a => BuildEquality (CoreExpr -> a)
- HERMIT.Dictionary.Reasoning: instantiateEquality :: MonadIO m => [(Var, CoreExpr, [Var])] -> Equality -> m Equality
- HERMIT.Dictionary.Reasoning: instantiateEqualityVar :: MonadIO m => (Var -> Bool) -> CoreExpr -> [Var] -> Equality -> m Equality
- HERMIT.Dictionary.Reasoning: instantiateEqualityVarR :: (Var -> Bool) -> CoreString -> RewriteH Equality
- HERMIT.Dictionary.Reasoning: lemmaR :: LemmaName -> BiRewriteH CoreExpr
- HERMIT.Dictionary.Reasoning: markLemmaUsedR :: (HasLemmas m, Monad m) => LemmaName -> Rewrite c m a
- HERMIT.Dictionary.Reasoning: modifyLemmaR :: (HasLemmas m, Monad m) => LemmaName -> (LemmaName -> LemmaName) -> Rewrite c m Equality -> (Bool -> Bool) -> (Bool -> Bool) -> Rewrite c m a
- HERMIT.Dictionary.Reasoning: ppEqualityT :: PrettyPrinter -> TransformH Equality DocH
- HERMIT.Dictionary.Reasoning: proveEqualityT :: (AddBindings c, Monad m, ReadPath c Crumb) => EqualityProof c m -> Transform c m Equality ()
- HERMIT.Dictionary.Reasoning: unshadowEqualityR :: RewriteH Equality
- HERMIT.Dictionary.Reasoning: verifyEqualityT :: Monad m => Transform c m Equality ()
- HERMIT.Dictionary.Rules: ruleNameToEqualityT :: (BoundVars c, HasCoreRules c, HasDynFlags m, HasHermitMEnv m, LiftCoreM m, MonadCatch m, MonadIO m, MonadThings m) => RuleName -> Transform c m a Equality
- HERMIT.Dictionary.Rules: ruleR :: (AddBindings c, ExtendPath c Crumb, HasCoreRules c, HasEmptyContext c, ReadBindings c, ReadPath c Crumb, HasDynFlags m, HasHermitMEnv m, HasLemmas m, LiftCoreM m, MonadCatch m, MonadIO m, MonadThings m, MonadUnique m) => RuleName -> Rewrite c m CoreExpr
- HERMIT.Dictionary.Rules: ruleToEqualityT :: (BoundVars c, HasDynFlags m, HasHermitMEnv m, MonadThings m, MonadCatch m) => Transform c m CoreRule Equality
- HERMIT.Dictionary.Rules: rulesR :: (AddBindings c, ExtendPath c Crumb, HasCoreRules c, HasEmptyContext c, ReadBindings c, ReadPath c Crumb, HasDynFlags m, HasHermitMEnv m, HasLemmas m, LiftCoreM m, MonadCatch m, MonadIO m, MonadThings m, MonadUnique m) => [RuleName] -> Rewrite c m CoreExpr
- HERMIT.Dictionary.Unfold: rememberR :: RememberedName -> Rewrite c HermitM Core
- HERMIT.Dictionary.Unfold: showStashT :: Injection CoreDef a => PrettyC -> PrettyH a -> Transform c HermitM a DocH
- HERMIT.Dictionary.Unfold: unfoldStashR :: ReadBindings c => RememberedName -> Rewrite c HermitM CoreExpr
- HERMIT.Dictionary.Unsafe: unsafeReplaceStashR :: RememberedName -> RewriteH CoreExpr
- HERMIT.Dictionary.WorkerWrapper.Common: assumptionAEqualityT :: (BoundVars c, HasDynFlags m, HasHermitMEnv m, HasHscEnv m, MonadCatch m, MonadIO m, MonadThings m) => CoreExpr -> CoreExpr -> Transform c m x Equality
- HERMIT.Dictionary.WorkerWrapper.Common: assumptionBEqualityT :: (BoundVars c, HasDynFlags m, HasHermitMEnv m, HasHscEnv m, MonadCatch m, MonadIO m, MonadThings m) => CoreExpr -> CoreExpr -> CoreExpr -> Transform c m x Equality
- HERMIT.Dictionary.WorkerWrapper.Common: assumptionCEqualityT :: (BoundVars c, HasDynFlags m, HasHermitMEnv m, HasHscEnv m, MonadCatch m, MonadIO m, MonadThings m) => CoreExpr -> CoreExpr -> CoreExpr -> Transform c m x Equality
- HERMIT.Dictionary.WorkerWrapper.Fix: wwGenerateFusionR :: Maybe WWAssumption -> RewriteH Core
- HERMIT.Dictionary.WorkerWrapper.FixResult: wwResultGenerateFusionR :: Maybe WWAssumption -> RewriteH Core
- HERMIT.External: BiRewriteCoreBox :: (BiRewriteH Core) -> BiRewriteCoreBox
- HERMIT.External: RewriteCoreBox :: (RewriteH Core) -> RewriteCoreBox
- HERMIT.External: RewriteCoreListBox :: [RewriteH Core] -> RewriteCoreListBox
- HERMIT.External: RewriteCoreTCBox :: (RewriteH CoreTC) -> RewriteCoreTCBox
- HERMIT.External: RewriteEqualityBox :: (RewriteH Equality) -> RewriteEqualityBox
- HERMIT.External: TransformCoreCheckBox :: (TransformH Core ()) -> TransformCoreCheckBox
- HERMIT.External: TransformCorePathBox :: (TransformH Core LocalPathH) -> TransformCorePathBox
- HERMIT.External: TransformCoreStringBox :: (TransformH Core String) -> TransformCoreStringBox
- HERMIT.External: TransformCoreTCCheckBox :: (TransformH CoreTC ()) -> TransformCoreTCCheckBox
- HERMIT.External: TransformCoreTCPathBox :: (TransformH CoreTC LocalPathH) -> TransformCoreTCPathBox
- HERMIT.External: TransformCoreTCStringBox :: (TransformH CoreTC String) -> TransformCoreTCStringBox
- HERMIT.External: TransformEqualityStringBox :: (TransformH Equality String) -> TransformEqualityStringBox
- HERMIT.External: data BiRewriteCoreBox
- HERMIT.External: data RewriteCoreBox
- HERMIT.External: data RewriteCoreListBox
- HERMIT.External: data RewriteCoreTCBox
- HERMIT.External: data RewriteEqualityBox
- HERMIT.External: data TransformCoreCheckBox
- HERMIT.External: data TransformCorePathBox
- HERMIT.External: data TransformCoreStringBox
- HERMIT.External: data TransformCoreTCCheckBox
- HERMIT.External: data TransformCoreTCPathBox
- HERMIT.External: data TransformCoreTCStringBox
- HERMIT.External: data TransformEqualityStringBox
- HERMIT.External: instance Extern (BiRewriteH Core)
- HERMIT.External: instance Extern (RewriteH Core)
- HERMIT.External: instance Extern (RewriteH CoreTC)
- HERMIT.External: instance Extern (RewriteH Equality)
- HERMIT.External: instance Extern (TransformH Core ())
- HERMIT.External: instance Extern (TransformH Core LocalPathH)
- HERMIT.External: instance Extern (TransformH Core String)
- HERMIT.External: instance Extern (TransformH CoreTC ())
- HERMIT.External: instance Extern (TransformH CoreTC LocalPathH)
- HERMIT.External: instance Extern (TransformH CoreTC String)
- HERMIT.External: instance Extern (TransformH Equality String)
- HERMIT.External: instance Extern RememberedName
- HERMIT.External: instance Extern [RewriteH Core]
- HERMIT.External: instance Typeable BiRewriteCoreBox
- HERMIT.External: instance Typeable RewriteCoreBox
- HERMIT.External: instance Typeable RewriteCoreListBox
- HERMIT.External: instance Typeable RewriteCoreTCBox
- HERMIT.External: instance Typeable RewriteEqualityBox
- HERMIT.External: instance Typeable TransformCoreCheckBox
- HERMIT.External: instance Typeable TransformCorePathBox
- HERMIT.External: instance Typeable TransformCoreStringBox
- HERMIT.External: instance Typeable TransformCoreTCCheckBox
- HERMIT.External: instance Typeable TransformCoreTCPathBox
- HERMIT.External: instance Typeable TransformCoreTCStringBox
- HERMIT.External: instance Typeable TransformEqualityStringBox
- HERMIT.Kernel.Scoped: L :: Direction
- HERMIT.Kernel.Scoped: R :: Direction
- HERMIT.Kernel.Scoped: SAST :: Int -> SAST
- HERMIT.Kernel.Scoped: ScopedKernel :: (forall m. (MonadIO m, MonadCatch m) => SAST -> m ()) -> (forall m. MonadIO m => m ()) -> (forall g m. (MonadIO m, MonadCatch m, Injection ModGuts g, Walker HermitC g) => RewriteH g -> KernelEnv -> SAST -> m SAST) -> (forall g a m. (MonadIO m, MonadCatch m, Injection ModGuts g, Walker HermitC g) => TransformH g a -> KernelEnv -> SAST -> m a) -> (forall m. (MonadIO m, MonadCatch m) => SAST -> m ()) -> (forall m. MonadIO m => m [SAST]) -> (forall m. (MonadIO m, MonadCatch m) => SAST -> m [PathH]) -> (forall m. (MonadIO m, MonadCatch m) => (LocalPathH -> LocalPathH) -> KernelEnv -> SAST -> m SAST) -> (forall m. (MonadIO m, MonadCatch m) => SAST -> m SAST) -> (forall m. (MonadIO m, MonadCatch m) => SAST -> m SAST) -> Kernel -> (forall m. (MonadIO m, MonadCatch m) => SAST -> m AST) -> ScopedKernel
- HERMIT.Kernel.Scoped: T :: Direction
- HERMIT.Kernel.Scoped: U :: Direction
- HERMIT.Kernel.Scoped: abortS :: ScopedKernel -> forall m. MonadIO m => m ()
- HERMIT.Kernel.Scoped: applyS :: ScopedKernel -> forall g m. (MonadIO m, MonadCatch m, Injection ModGuts g, Walker HermitC g) => RewriteH g -> KernelEnv -> SAST -> m SAST
- HERMIT.Kernel.Scoped: beginScopeS :: ScopedKernel -> forall m. (MonadIO m, MonadCatch m) => SAST -> m SAST
- HERMIT.Kernel.Scoped: data Direction
- HERMIT.Kernel.Scoped: data ScopedKernel
- HERMIT.Kernel.Scoped: deleteS :: ScopedKernel -> forall m. (MonadIO m, MonadCatch m) => SAST -> m ()
- HERMIT.Kernel.Scoped: endScopeS :: ScopedKernel -> forall m. (MonadIO m, MonadCatch m) => SAST -> m SAST
- HERMIT.Kernel.Scoped: instance Eq Direction
- HERMIT.Kernel.Scoped: instance Eq SAST
- HERMIT.Kernel.Scoped: instance Ord SAST
- HERMIT.Kernel.Scoped: instance Show Direction
- HERMIT.Kernel.Scoped: instance Show SAST
- HERMIT.Kernel.Scoped: kernelS :: ScopedKernel -> Kernel
- HERMIT.Kernel.Scoped: listS :: ScopedKernel -> forall m. MonadIO m => m [SAST]
- HERMIT.Kernel.Scoped: modPathS :: ScopedKernel -> forall m. (MonadIO m, MonadCatch m) => (LocalPathH -> LocalPathH) -> KernelEnv -> SAST -> m SAST
- HERMIT.Kernel.Scoped: moveLocally :: Direction -> LocalPathH -> LocalPathH
- HERMIT.Kernel.Scoped: newtype SAST
- HERMIT.Kernel.Scoped: pathS :: ScopedKernel -> forall m. (MonadIO m, MonadCatch m) => SAST -> m [PathH]
- HERMIT.Kernel.Scoped: queryS :: ScopedKernel -> forall g a m. (MonadIO m, MonadCatch m, Injection ModGuts g, Walker HermitC g) => TransformH g a -> KernelEnv -> SAST -> m a
- HERMIT.Kernel.Scoped: resumeS :: ScopedKernel -> forall m. (MonadIO m, MonadCatch m) => SAST -> m ()
- HERMIT.Kernel.Scoped: scopedKernel :: (ScopedKernel -> SAST -> IO ()) -> ModGuts -> CoreM ModGuts
- HERMIT.Kernel.Scoped: toASTS :: ScopedKernel -> forall m. (MonadIO m, MonadCatch m) => SAST -> m AST
- HERMIT.Kernel.Scoped: type LocalPath = SnocPath
- HERMIT.Kure: deprecatedIntToCrumbT :: Monad m => Int -> Transform c m Core Crumb
- HERMIT.Kure: deprecatedIntToPathT :: Monad m => Int -> Transform c m Core LocalPathH
- HERMIT.Kure.SumTypes: AltCore :: CoreAlt -> Core
- HERMIT.Kure.SumTypes: BindCore :: CoreBind -> Core
- HERMIT.Kure.SumTypes: CoercionCore :: Coercion -> TyCo
- HERMIT.Kure.SumTypes: Core :: Core -> CoreTC
- HERMIT.Kure.SumTypes: DefCore :: CoreDef -> Core
- HERMIT.Kure.SumTypes: ExprCore :: CoreExpr -> Core
- HERMIT.Kure.SumTypes: GutsCore :: ModGuts -> Core
- HERMIT.Kure.SumTypes: ProgCore :: CoreProg -> Core
- HERMIT.Kure.SumTypes: TyCo :: TyCo -> CoreTC
- HERMIT.Kure.SumTypes: TypeCore :: Type -> TyCo
- HERMIT.Kure.SumTypes: coreAlphaEq :: Core -> Core -> Bool
- HERMIT.Kure.SumTypes: coreSyntaxEq :: Core -> Core -> Bool
- HERMIT.Kure.SumTypes: coreTCAlphaEq :: CoreTC -> CoreTC -> Bool
- HERMIT.Kure.SumTypes: coreTCSyntaxEq :: CoreTC -> CoreTC -> Bool
- HERMIT.Kure.SumTypes: data Core
- HERMIT.Kure.SumTypes: data CoreTC
- HERMIT.Kure.SumTypes: data TyCo
- HERMIT.Kure.SumTypes: freeVarsCore :: Core -> VarSet
- HERMIT.Kure.SumTypes: freeVarsCoreTC :: CoreTC -> VarSet
- HERMIT.Kure.SumTypes: freeVarsTyCo :: TyCo -> VarSet
- HERMIT.Kure.SumTypes: instance Injection Coercion CoreTC
- HERMIT.Kure.SumTypes: instance Injection Coercion TyCo
- HERMIT.Kure.SumTypes: instance Injection Core CoreTC
- HERMIT.Kure.SumTypes: instance Injection CoreAlt Core
- HERMIT.Kure.SumTypes: instance Injection CoreAlt CoreTC
- HERMIT.Kure.SumTypes: instance Injection CoreBind Core
- HERMIT.Kure.SumTypes: instance Injection CoreBind CoreTC
- HERMIT.Kure.SumTypes: instance Injection CoreDef Core
- HERMIT.Kure.SumTypes: instance Injection CoreDef CoreTC
- HERMIT.Kure.SumTypes: instance Injection CoreExpr Core
- HERMIT.Kure.SumTypes: instance Injection CoreExpr CoreTC
- HERMIT.Kure.SumTypes: instance Injection CoreProg Core
- HERMIT.Kure.SumTypes: instance Injection CoreProg CoreTC
- HERMIT.Kure.SumTypes: instance Injection ModGuts Core
- HERMIT.Kure.SumTypes: instance Injection ModGuts CoreTC
- HERMIT.Kure.SumTypes: instance Injection TyCo CoreTC
- HERMIT.Kure.SumTypes: instance Injection Type CoreTC
- HERMIT.Kure.SumTypes: instance Injection Type TyCo
- HERMIT.Kure.SumTypes: promoteAltR :: (Monad m, Injection CoreAlt g) => Rewrite c m CoreAlt -> Rewrite c m g
- HERMIT.Kure.SumTypes: promoteAltT :: (Monad m, Injection CoreAlt g) => Transform c m CoreAlt b -> Transform c m g b
- HERMIT.Kure.SumTypes: promoteBindR :: (Monad m, Injection CoreBind g) => Rewrite c m CoreBind -> Rewrite c m g
- HERMIT.Kure.SumTypes: promoteBindT :: (Monad m, Injection CoreBind g) => Transform c m CoreBind b -> Transform c m g b
- HERMIT.Kure.SumTypes: promoteCoercionR :: (Monad m, Injection Coercion g) => Rewrite c m Coercion -> Rewrite c m g
- HERMIT.Kure.SumTypes: promoteCoercionT :: (Monad m, Injection Coercion g) => Transform c m Coercion b -> Transform c m g b
- HERMIT.Kure.SumTypes: promoteDefR :: (Monad m, Injection CoreDef g) => Rewrite c m CoreDef -> Rewrite c m g
- HERMIT.Kure.SumTypes: promoteDefT :: (Monad m, Injection CoreDef g) => Transform c m CoreDef b -> Transform c m g b
- HERMIT.Kure.SumTypes: promoteExprBiR :: (Monad m, Injection CoreExpr g) => BiRewrite c m CoreExpr -> BiRewrite c m g
- HERMIT.Kure.SumTypes: promoteExprR :: (Monad m, Injection CoreExpr g) => Rewrite c m CoreExpr -> Rewrite c m g
- HERMIT.Kure.SumTypes: promoteExprT :: (Monad m, Injection CoreExpr g) => Transform c m CoreExpr b -> Transform c m g b
- HERMIT.Kure.SumTypes: promoteModGutsR :: (Monad m, Injection ModGuts g) => Rewrite c m ModGuts -> Rewrite c m g
- HERMIT.Kure.SumTypes: promoteModGutsT :: (Monad m, Injection ModGuts g) => Transform c m ModGuts b -> Transform c m g b
- HERMIT.Kure.SumTypes: promoteProgR :: (Monad m, Injection CoreProg g) => Rewrite c m CoreProg -> Rewrite c m g
- HERMIT.Kure.SumTypes: promoteProgT :: (Monad m, Injection CoreProg g) => Transform c m CoreProg b -> Transform c m g b
- HERMIT.Kure.SumTypes: promoteTypeR :: (Monad m, Injection Type g) => Rewrite c m Type -> Rewrite c m g
- HERMIT.Kure.SumTypes: promoteTypeT :: (Monad m, Injection Type g) => Transform c m Type b -> Transform c m g b
- HERMIT.Kure.SumTypes: tyCoAlphaEq :: TyCo -> TyCo -> Bool
- HERMIT.Kure.SumTypes: tyCoSyntaxEq :: TyCo -> TyCo -> Bool
- HERMIT.Monad: Equality :: [CoreBndr] -> CoreExpr -> CoreExpr -> Equality
- HERMIT.Monad: HermitMEnv :: ModGuts -> DefStash -> Lemmas -> HermitMEnv
- HERMIT.Monad: Lemma :: Equality -> Bool -> Bool -> Lemma
- HERMIT.Monad: LemmaName :: String -> LemmaName
- HERMIT.Monad: RememberedName :: String -> RememberedName
- HERMIT.Monad: class HasStash m
- HERMIT.Monad: data Equality
- HERMIT.Monad: data Lemma
- HERMIT.Monad: getStash :: HasStash m => m DefStash
- HERMIT.Monad: hEnvLemmas :: HermitMEnv -> Lemmas
- HERMIT.Monad: hEnvModGuts :: HermitMEnv -> ModGuts
- HERMIT.Monad: hEnvStash :: HermitMEnv -> DefStash
- HERMIT.Monad: hResStash :: HermitMResult a -> DefStash
- HERMIT.Monad: instance Eq LemmaName
- HERMIT.Monad: instance Eq RememberedName
- HERMIT.Monad: instance HasStash HermitM
- HERMIT.Monad: instance IsString LemmaName
- HERMIT.Monad: instance IsString RememberedName
- HERMIT.Monad: instance Ord LemmaName
- HERMIT.Monad: instance Ord RememberedName
- HERMIT.Monad: instance Show LemmaName
- HERMIT.Monad: instance Show RememberedName
- HERMIT.Monad: instance Typeable LemmaName
- HERMIT.Monad: instance Typeable RememberedName
- HERMIT.Monad: lemmaEq :: Lemma -> Equality
- HERMIT.Monad: lemmaP :: Lemma -> Bool
- HERMIT.Monad: lemmaU :: Lemma -> Bool
- HERMIT.Monad: lookupDef :: (HasStash m, Monad m) => RememberedName -> m CoreDef
- HERMIT.Monad: newtype LemmaName
- HERMIT.Monad: newtype RememberedName
- HERMIT.Monad: putStash :: HasStash m => DefStash -> m ()
- HERMIT.Monad: saveDef :: (HasStash m, Monad m) => RememberedName -> CoreDef -> m ()
- HERMIT.Monad: type DefStash = Map RememberedName CoreDef
- HERMIT.Monad: type Lemmas = Map LemmaName Lemma
- HERMIT.Plugin.Builder: type PluginPass = PassInfo -> [CommandLineOption] -> ModGuts -> CoreM ModGuts
- HERMIT.Plugin.Display: getFocusPath :: PluginM PathH
- HERMIT.Plugin.Types: instance Error PException
- HERMIT.Plugin.Types: iokm :: (MonadIO m, MonadCatch m) => String -> IO (KureM a) -> m a
- HERMIT.Plugin.Types: iokm' :: (MonadIO m, MonadCatch m) => String -> (a -> m b) -> IO (KureM a) -> m b
- HERMIT.Plugin.Types: iokm'' :: (MonadIO m, MonadCatch m) => IO (KureM a) -> m a
- HERMIT.PrettyPrinter.Common: TransformCoreTCDocHBox :: (TransformDocH CoreTC) -> TransformCoreTCDocHBox
- HERMIT.PrettyPrinter.Common: TransformDocH :: (PrettyC -> PrettyH a -> TransformH a DocH) -> TransformDocH a
- HERMIT.PrettyPrinter.Common: data TransformCoreTCDocHBox
- HERMIT.PrettyPrinter.Common: instance Extern (TransformDocH CoreTC)
- HERMIT.PrettyPrinter.Common: instance Typeable TransformCoreTCDocHBox
- HERMIT.PrettyPrinter.Common: newtype TransformDocH a
- HERMIT.PrettyPrinter.Common: unTransformDocH :: TransformDocH a -> PrettyC -> PrettyH a -> TransformH a DocH
- HERMIT.Shell.Command: interpShellCommand :: (MonadCatch m, MonadException m, CLMonad m) => [Interp m ()]
- HERMIT.Shell.Command: shellComplete :: (MonadCatch m, MonadIO m, MonadState CommandLineState m) => String -> String -> m [Completion]
- HERMIT.Shell.Completion: shellComplete :: (MonadCatch m, MonadIO m, MonadState CommandLineState m) => String -> String -> m [Completion]
- HERMIT.Shell.KernelEffect: beginScope :: (MonadCatch m, CLMonad m) => ExprH -> m ()
- HERMIT.Shell.KernelEffect: deleteSAST :: (MonadCatch m, CLMonad m) => SAST -> m ()
- HERMIT.Shell.KernelEffect: endScope :: (MonadCatch m, CLMonad m) => ExprH -> m ()
- HERMIT.Shell.KernelEffect: goDirection :: (MonadCatch m, CLMonad m) => Direction -> ExprH -> m ()
- HERMIT.Shell.Proof: DumpLemma :: LemmaName -> String -> String -> Int -> ProofCommand
- HERMIT.Shell.Proof: InteractiveProof :: LemmaName -> ProofCommand
- HERMIT.Shell.Proof: ShowLemmas :: (Maybe LemmaName) -> ProofCommand
- HERMIT.Shell.Proof: data ProofCommand
- HERMIT.Shell.Proof: instance Extern ProofCommand
- HERMIT.Shell.Proof: instance Typeable ProofCommand
- HERMIT.Shell.Proof: instance Typeable UserProofTechniqueBox
- HERMIT.Shell.Proof: performProofCommand :: (MonadCatch m, MonadException m, CLMonad m) => ProofCommand -> m ()
- HERMIT.Shell.Proof: ppLemmaT :: PrettyPrinter -> LemmaName -> TransformH Lemma DocH
- HERMIT.Shell.ScriptToRewrite: setRunningScript :: MonadState CommandLineState m => Maybe Script -> m ()
- HERMIT.Shell.ShellEffect: Dump :: (CommandLineState -> TransformH CoreTC DocH) -> String -> String -> Int -> ShellEffect
- HERMIT.Shell.Types: AddTag :: String -> VersionCmd
- HERMIT.Shell.Types: CorrectnessCritera :: TransformH g () -> QueryFun
- HERMIT.Shell.Types: Display :: QueryFun
- HERMIT.Shell.Types: VersionStore :: [(SAST, ExprH, SAST)] -> [(String, SAST)] -> VersionStore
- HERMIT.Shell.Types: cl_initSAST :: CommandLineState -> SAST
- HERMIT.Shell.Types: cl_version :: CommandLineState -> VersionStore
- HERMIT.Shell.Types: data VersionStore
- HERMIT.Shell.Types: instance Error CLException
- HERMIT.Shell.Types: newSAST :: ExprH -> SAST -> CommandLineState -> CommandLineState
- HERMIT.Shell.Types: showGraph :: [(SAST, ExprH, SAST)] -> [(String, SAST)] -> SAST -> String
- HERMIT.Shell.Types: vs_graph :: VersionStore -> [(SAST, ExprH, SAST)]
- HERMIT.Shell.Types: vs_tags :: VersionStore -> [(String, SAST)]
+ HERMIT.Context: inScope :: BoundVars c => c -> Var -> Bool
+ HERMIT.Core: Conj_Lhs :: Crumb
+ HERMIT.Core: Conj_Rhs :: Crumb
+ HERMIT.Core: Disj_Lhs :: Crumb
+ HERMIT.Core: Disj_Rhs :: Crumb
+ HERMIT.Core: Eq_Lhs :: Crumb
+ HERMIT.Core: Eq_Rhs :: Crumb
+ HERMIT.Core: Forall_Body :: Crumb
+ HERMIT.Core: Impl_Lhs :: Crumb
+ HERMIT.Core: Impl_Rhs :: Crumb
+ HERMIT.Core: betaReduceAll :: CoreExpr -> [CoreExpr] -> (CoreExpr, [CoreExpr])
+ HERMIT.Core: leftSibling :: Crumb -> Maybe Crumb
+ HERMIT.Core: mkDataConApp :: [Type] -> DataCon -> [Var] -> CoreExpr
+ HERMIT.Core: rightSibling :: Crumb -> Maybe Crumb
+ HERMIT.Core: substCoreAlt :: Var -> CoreExpr -> CoreAlt -> CoreAlt
+ HERMIT.Core: substCoreExpr :: Var -> CoreExpr -> (CoreExpr -> CoreExpr)
+ HERMIT.Dictionary.Fold: Equality :: [CoreBndr] -> CoreExpr -> CoreExpr -> Equality
+ HERMIT.Dictionary.Fold: compileFold :: [Equality] -> CompiledFold
+ HERMIT.Dictionary.Fold: data CompiledFold
+ HERMIT.Dictionary.Fold: data Equality
+ HERMIT.Dictionary.Fold: flipEquality :: Equality -> Equality
+ HERMIT.Dictionary.Fold: foldVarConfigR :: (ReadBindings c, MonadCatch m, MonadUnique m) => InlineConfig -> Maybe BindingDepth -> Var -> Rewrite c m CoreExpr
+ HERMIT.Dictionary.Fold: freeVarsEquality :: Equality -> VarSet
+ HERMIT.Dictionary.Fold: instance Extern (RewriteH Equality)
+ HERMIT.Dictionary.Fold: instance Extern (TransformH Equality ())
+ HERMIT.Dictionary.Fold: instance Extern (TransformH Equality String)
+ HERMIT.Dictionary.Fold: instance Fold AMap
+ HERMIT.Dictionary.Fold: instance Fold CLMap
+ HERMIT.Dictionary.Fold: instance Fold EMap
+ HERMIT.Dictionary.Fold: instance Fold QMap
+ HERMIT.Dictionary.Fold: instance Fold TyLitMap
+ HERMIT.Dictionary.Fold: instance Fold TyMap
+ HERMIT.Dictionary.Fold: instance Fold VMap
+ HERMIT.Dictionary.Fold: instance Fold m => Fold (ListMap m)
+ HERMIT.Dictionary.Fold: instance Typeable RewriteEqualityBox
+ HERMIT.Dictionary.Fold: instance Typeable TransformEqualityStringBox
+ HERMIT.Dictionary.Fold: instance Typeable TransformEqualityUnitBox
+ HERMIT.Dictionary.Fold: lemmaMatch :: [Var] -> Quantified -> Quantified -> Maybe (VarEnv CoreExpr)
+ HERMIT.Dictionary.Fold: ppEqualityT :: PrettyPrinter -> PrettyH Equality
+ HERMIT.Dictionary.Fold: proves :: Quantified -> Quantified -> Bool
+ HERMIT.Dictionary.Fold: runFold :: BoundVars c => CompiledFold -> c -> CoreExpr -> Maybe CoreExpr
+ HERMIT.Dictionary.Fold: runFoldMatches :: BoundVars c => CompiledFold -> c -> CoreExpr -> Maybe (CoreExpr, VarEnv CoreExpr)
+ HERMIT.Dictionary.Fold: runFoldR :: (BoundVars c, Monad m) => CompiledFold -> Rewrite c m CoreExpr
+ HERMIT.Dictionary.Fold: toEqualities :: Quantified -> [Equality]
+ HERMIT.Dictionary.Function: buildAppM :: MonadCatch m => CoreExpr -> CoreExpr -> m CoreExpr
+ HERMIT.Dictionary.Function: buildAppsM :: MonadCatch m => CoreExpr -> [CoreExpr] -> m CoreExpr
+ HERMIT.Dictionary.GHC: loadLemmaLibraryT :: HermitName -> TransformH x ()
+ HERMIT.Dictionary.GHC: type LemmaLibrary = TransformH () Lemmas
+ HERMIT.Dictionary.Inline: getUnfoldingsT :: (ReadBindings c, MonadCatch m) => InlineConfig -> Transform c m Id [(CoreExpr, BindingDepth -> Bool)]
+ HERMIT.Dictionary.Local.Case: caseExprsForM :: MonadUnique m => CoreExpr -> m [CoreExpr]
+ HERMIT.Dictionary.Local.Case: casesForM :: MonadUnique m => CoreExpr -> m [(DataCon, [Id])]
+ HERMIT.Dictionary.Local.Cast: castFloatLamR :: MonadCatch m => Rewrite c m CoreExpr
+ HERMIT.Dictionary.Reasoning: abstractQuantifiedR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb, HasDebugChan m, HasHermitMEnv m, HasLemmas m, LiftCoreM m, MonadCatch m, MonadUnique m) => String -> Transform c m Quantified CoreExpr -> Rewrite c m Quantified
+ HERMIT.Dictionary.Reasoning: getObligationNotProvenT :: (HasLemmas m, Monad m) => Transform c m x [NamedLemma]
+ HERMIT.Dictionary.Reasoning: insertLemmaT :: (HasLemmas m, Monad m) => LemmaName -> Lemma -> Transform c m a ()
+ HERMIT.Dictionary.Reasoning: insertLemmasT :: (HasLemmas m, Monad m) => [NamedLemma] -> Transform c m a ()
+ HERMIT.Dictionary.Reasoning: instantiateQuantifiedVarR :: (Var -> Bool) -> CoreString -> RewriteH Quantified
+ HERMIT.Dictionary.Reasoning: lemmaBiR :: (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb, HasLemmas m, MonadCatch m, MonadUnique m) => Used -> LemmaName -> BiRewrite c m CoreExpr
+ HERMIT.Dictionary.Reasoning: lemmaConsequentR :: (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb, HasLemmas m, MonadCatch m, MonadUnique m) => Used -> LemmaName -> Rewrite c m Quantified
+ HERMIT.Dictionary.Reasoning: lintQuantifiedT :: (AddBindings c, BoundVars c, ReadPath c Crumb, ExtendPath c Crumb, HasDynFlags m, MonadCatch m) => Transform c m Quantified String
+ HERMIT.Dictionary.Reasoning: markLemmaAssumedT :: (HasLemmas m, Monad m) => Bool -> LemmaName -> Transform c m a ()
+ HERMIT.Dictionary.Reasoning: markLemmaProvedT :: (HasLemmas m, Monad m) => LemmaName -> Transform c m a ()
+ HERMIT.Dictionary.Reasoning: markLemmaUsedT :: (HasLemmas m, Monad m) => LemmaName -> Used -> Transform c m a ()
+ HERMIT.Dictionary.Reasoning: modifyLemmaT :: (HasLemmas m, Monad m) => LemmaName -> (LemmaName -> LemmaName) -> Rewrite c m Quantified -> (Proven -> Proven) -> (Used -> Used) -> Transform c m a ()
+ HERMIT.Dictionary.Reasoning: ppLCoreTCT :: PrettyPrinter -> PrettyH LCoreTC
+ HERMIT.Dictionary.Reasoning: ppLemmaT :: PrettyPrinter -> LemmaName -> PrettyH Lemma
+ HERMIT.Dictionary.Reasoning: ppQuantifiedT :: PrettyPrinter -> PrettyH Quantified
+ HERMIT.Dictionary.Reasoning: showLemmaT :: LemmaName -> PrettyPrinter -> PrettyH a
+ HERMIT.Dictionary.Reasoning: showLemmasT :: Maybe LemmaName -> PrettyPrinter -> PrettyH a
+ HERMIT.Dictionary.Reasoning: unshadowQuantifiedR :: MonadUnique m => Rewrite c m Quantified
+ HERMIT.Dictionary.Reasoning: verifyEquivalentT :: (HasLemmas m, MonadCatch m) => Used -> LemmaName -> Transform c m Quantified ()
+ HERMIT.Dictionary.Reasoning: verifyOrCreateT :: (HasLemmas m, MonadCatch m) => Used -> LemmaName -> Lemma -> Transform c m a ()
+ HERMIT.Dictionary.Reasoning: verifyQuantifiedT :: (AddBindings c, ReadPath c Crumb, ExtendPath c Crumb, MonadCatch m) => Transform c m Quantified ()
+ HERMIT.Dictionary.Remembered: compileRememberedT :: (HasLemmas m, Monad m) => Transform c m x CompiledFold
+ HERMIT.Dictionary.Remembered: externals :: [External]
+ HERMIT.Dictionary.Remembered: foldAnyRememberedR :: (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb, HasLemmas m, MonadCatch m, MonadUnique m) => Rewrite c m CoreExpr
+ HERMIT.Dictionary.Remembered: foldRememberedR :: (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb, HasLemmas m, MonadCatch m, MonadUnique m) => Used -> LemmaName -> Rewrite c m CoreExpr
+ HERMIT.Dictionary.Remembered: prefixRemembered :: LemmaName -> LemmaName
+ HERMIT.Dictionary.Remembered: rememberR :: (AddBindings c, ExtendPath c Crumb, ReadPath c Crumb, HasLemmas m, MonadCatch m) => LemmaName -> Transform c m Core ()
+ HERMIT.Dictionary.Remembered: unfoldRememberedR :: (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb, HasLemmas m, MonadCatch m, MonadUnique m) => Used -> LemmaName -> Rewrite c m CoreExpr
+ HERMIT.Dictionary.Rules: compileRulesT :: (BoundVars c, HasCoreRules c, HasHermitMEnv m, LiftCoreM m, MonadCatch m, MonadIO m, MonadThings m) => [RuleName] -> Transform c m a CompiledFold
+ HERMIT.Dictionary.Rules: foldRuleR :: (AddBindings c, ExtendPath c Crumb, HasCoreRules c, HasEmptyContext c, ReadBindings c, ReadPath c Crumb, HasDynFlags m, HasHermitMEnv m, HasLemmas m, LiftCoreM m, MonadCatch m, MonadIO m, MonadThings m, MonadUnique m) => Used -> RuleName -> Rewrite c m CoreExpr
+ HERMIT.Dictionary.Rules: foldRulesR :: (AddBindings c, ExtendPath c Crumb, HasCoreRules c, HasEmptyContext c, ReadBindings c, ReadPath c Crumb, HasDynFlags m, HasHermitMEnv m, HasLemmas m, LiftCoreM m, MonadCatch m, MonadIO m, MonadThings m, MonadUnique m) => Used -> [RuleName] -> Rewrite c m CoreExpr
+ HERMIT.Dictionary.Rules: ruleNameToQuantifiedT :: (BoundVars c, HasCoreRules c, HasDynFlags m, HasHermitMEnv m, LiftCoreM m, MonadCatch m, MonadIO m, MonadThings m) => RuleName -> Transform c m a Quantified
+ HERMIT.Dictionary.Rules: ruleToQuantifiedT :: (BoundVars c, HasHermitMEnv m, MonadThings m, MonadCatch m) => Transform c m CoreRule Quantified
+ HERMIT.Dictionary.Rules: unfoldRuleR :: (AddBindings c, ExtendPath c Crumb, HasCoreRules c, HasEmptyContext c, ReadBindings c, ReadPath c Crumb, HasDynFlags m, HasHermitMEnv m, HasLemmas m, LiftCoreM m, MonadCatch m, MonadIO m, MonadThings m, MonadUnique m) => Used -> RuleName -> Rewrite c m CoreExpr
+ HERMIT.Dictionary.Rules: unfoldRulesR :: (AddBindings c, ExtendPath c Crumb, HasCoreRules c, HasEmptyContext c, ReadBindings c, ReadPath c Crumb, HasDynFlags m, HasHermitMEnv m, HasLemmas m, LiftCoreM m, MonadCatch m, MonadIO m, MonadThings m, MonadUnique m) => Used -> [RuleName] -> Rewrite c m CoreExpr
+ HERMIT.Dictionary.Undefined: applyToUndefinedT :: (BoundVars c, HasDynFlags m, HasHscEnv m, HasHermitMEnv m, MonadCatch m, MonadIO m, MonadThings m) => CoreExpr -> Transform c m x CoreExpr
+ HERMIT.Dictionary.WorkerWrapper.Common: assumptionAQuantifiedT :: (BoundVars c, HasHermitMEnv m, HasHscEnv m, MonadCatch m, MonadIO m, MonadThings m) => CoreExpr -> CoreExpr -> Transform c m x Quantified
+ HERMIT.Dictionary.WorkerWrapper.Common: assumptionBQuantifiedT :: (BoundVars c, HasHermitMEnv m, HasHscEnv m, MonadCatch m, MonadIO m, MonadThings m) => CoreExpr -> CoreExpr -> CoreExpr -> Transform c m x Quantified
+ HERMIT.Dictionary.WorkerWrapper.Common: assumptionCQuantifiedT :: (BoundVars c, HasHermitMEnv m, HasHscEnv m, MonadCatch m, MonadIO m, MonadThings m) => CoreExpr -> CoreExpr -> CoreExpr -> Transform c m x Quantified
+ HERMIT.Dictionary.WorkerWrapper.Fix: wwGenerateFusionT :: Maybe WWAssumption -> TransformH LCore ()
+ HERMIT.Dictionary.WorkerWrapper.FixResult: wwResultGenerateFusionT :: Maybe WWAssumption -> TransformH LCore ()
+ HERMIT.External: BiRewriteLCoreBox :: (BiRewriteH LCore) -> BiRewriteLCoreBox
+ HERMIT.External: BiRewriteLCoreTCBox :: (BiRewriteH LCoreTC) -> BiRewriteLCoreTCBox
+ HERMIT.External: RewriteLCoreBox :: (RewriteH LCore) -> RewriteLCoreBox
+ HERMIT.External: RewriteLCoreListBox :: [RewriteH LCore] -> RewriteLCoreListBox
+ HERMIT.External: RewriteLCoreTCBox :: (RewriteH LCoreTC) -> RewriteLCoreTCBox
+ HERMIT.External: RewriteLCoreTCListBox :: [RewriteH LCoreTC] -> RewriteLCoreTCListBox
+ HERMIT.External: Safe :: CmdTag
+ HERMIT.External: TransformLCorePathBox :: (TransformH LCore LocalPathH) -> TransformLCorePathBox
+ HERMIT.External: TransformLCoreStringBox :: (TransformH LCore String) -> TransformLCoreStringBox
+ HERMIT.External: TransformLCoreTCLCoreBox :: (TransformH LCoreTC LCore) -> TransformLCoreTCLCoreBox
+ HERMIT.External: TransformLCoreTCPathBox :: (TransformH LCoreTC LocalPathH) -> TransformLCoreTCPathBox
+ HERMIT.External: TransformLCoreTCStringBox :: (TransformH LCoreTC String) -> TransformLCoreTCStringBox
+ HERMIT.External: TransformLCoreTCUnitBox :: (TransformH LCoreTC ()) -> TransformLCoreTCUnitBox
+ HERMIT.External: TransformLCoreUnitBox :: (TransformH LCore ()) -> TransformLCoreUnitBox
+ HERMIT.External: data BiRewriteLCoreBox
+ HERMIT.External: data BiRewriteLCoreTCBox
+ HERMIT.External: data RewriteLCoreBox
+ HERMIT.External: data RewriteLCoreListBox
+ HERMIT.External: data RewriteLCoreTCBox
+ HERMIT.External: data RewriteLCoreTCListBox
+ HERMIT.External: data TransformLCorePathBox
+ HERMIT.External: data TransformLCoreStringBox
+ HERMIT.External: data TransformLCoreTCLCoreBox
+ HERMIT.External: data TransformLCoreTCPathBox
+ HERMIT.External: data TransformLCoreTCStringBox
+ HERMIT.External: data TransformLCoreTCUnitBox
+ HERMIT.External: data TransformLCoreUnitBox
+ HERMIT.External: instance Extern (BiRewriteH LCore)
+ HERMIT.External: instance Extern (BiRewriteH LCoreTC)
+ HERMIT.External: instance Extern (RewriteH LCore)
+ HERMIT.External: instance Extern (RewriteH LCoreTC)
+ HERMIT.External: instance Extern (TransformH LCore ())
+ HERMIT.External: instance Extern (TransformH LCore LocalPathH)
+ HERMIT.External: instance Extern (TransformH LCore String)
+ HERMIT.External: instance Extern (TransformH LCoreTC ())
+ HERMIT.External: instance Extern (TransformH LCoreTC LCore)
+ HERMIT.External: instance Extern (TransformH LCoreTC LocalPathH)
+ HERMIT.External: instance Extern (TransformH LCoreTC String)
+ HERMIT.External: instance Extern [RewriteH LCoreTC]
+ HERMIT.External: instance Extern [RewriteH LCore]
+ HERMIT.External: instance Typeable BiRewriteLCoreBox
+ HERMIT.External: instance Typeable BiRewriteLCoreTCBox
+ HERMIT.External: instance Typeable RewriteLCoreBox
+ HERMIT.External: instance Typeable RewriteLCoreListBox
+ HERMIT.External: instance Typeable RewriteLCoreTCBox
+ HERMIT.External: instance Typeable RewriteLCoreTCListBox
+ HERMIT.External: instance Typeable TransformLCorePathBox
+ HERMIT.External: instance Typeable TransformLCoreStringBox
+ HERMIT.External: instance Typeable TransformLCoreTCLCoreBox
+ HERMIT.External: instance Typeable TransformLCoreTCPathBox
+ HERMIT.External: instance Typeable TransformLCoreTCStringBox
+ HERMIT.External: instance Typeable TransformLCoreTCUnitBox
+ HERMIT.External: instance Typeable TransformLCoreUnitBox
+ HERMIT.GHC: throwCmdLineErrorS :: DynFlags -> SDoc -> IO a
+ HERMIT.Kernel: Always :: String -> CommitMsg
+ HERMIT.Kernel: Changed :: String -> CommitMsg
+ HERMIT.Kernel: Never :: CommitMsg
+ HERMIT.Kernel: data ASTMap
+ HERMIT.Kernel: data CommitMsg
+ HERMIT.Kernel: firstAST :: AST
+ HERMIT.Kernel: instance Enum AST
+ HERMIT.Kernel: instance Extern AST
+ HERMIT.Kernel: instance Read AST
+ HERMIT.Kernel: instance Typeable AST
+ HERMIT.Kernel: tellK :: Kernel -> (MonadIO m, MonadCatch m) => String -> AST -> m AST
+ HERMIT.Kure: (<$>) :: Monad m => (a -> b) -> m a -> m b
+ HERMIT.Kure: (<*>) :: Monad m => m (a -> b) -> m a -> m b
+ HERMIT.Kure: conjAllR :: (ExtendPath c Crumb, Monad m) => Rewrite c m Quantified -> Rewrite c m Quantified -> Rewrite c m Clause
+ HERMIT.Kure: conjT :: (ExtendPath c Crumb, Monad m) => Transform c m Quantified a1 -> Transform c m Quantified a2 -> (a1 -> a2 -> b) -> Transform c m Clause b
+ HERMIT.Kure: disjAllR :: (ExtendPath c Crumb, Monad m) => Rewrite c m Quantified -> Rewrite c m Quantified -> Rewrite c m Clause
+ HERMIT.Kure: disjT :: (ExtendPath c Crumb, Monad m) => Transform c m Quantified a1 -> Transform c m Quantified a2 -> (a1 -> a2 -> b) -> Transform c m Clause b
+ HERMIT.Kure: equivAllR :: (ExtendPath c Crumb, Monad m) => Rewrite c m CoreExpr -> Rewrite c m CoreExpr -> Rewrite c m Clause
+ HERMIT.Kure: equivT :: (ExtendPath c Crumb, Monad m) => Transform c m CoreExpr a1 -> Transform c m CoreExpr a2 -> (a1 -> a2 -> b) -> Transform c m Clause b
+ HERMIT.Kure: implAllR :: (ExtendPath c Crumb, Monad m) => Rewrite c m Quantified -> Rewrite c m Quantified -> Rewrite c m Clause
+ HERMIT.Kure: implT :: (ExtendPath c Crumb, Monad m) => Transform c m Quantified a1 -> Transform c m Quantified a2 -> (a1 -> a2 -> b) -> Transform c m Clause b
+ HERMIT.Kure: instance (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadPath c Crumb) => Walker c LCore
+ HERMIT.Kure: instance (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadPath c Crumb) => Walker c LCoreTC
+ HERMIT.Kure: quantifiedR :: (ExtendPath c Crumb, AddBindings c, ReadPath c Crumb, Monad m) => Rewrite c m [CoreBndr] -> Rewrite c m Clause -> Rewrite c m Quantified
+ HERMIT.Kure: quantifiedT :: (ExtendPath c Crumb, AddBindings c, ReadPath c Crumb, Monad m) => Transform c m [CoreBndr] a1 -> Transform c m Clause a2 -> (a1 -> a2 -> b) -> Transform c m Quantified b
+ HERMIT.Kure.Universes: AltCore :: CoreAlt -> Core
+ HERMIT.Kure.Universes: BindCore :: CoreBind -> Core
+ HERMIT.Kure.Universes: CoercionCore :: Coercion -> TyCo
+ HERMIT.Kure.Universes: Core :: Core -> CoreTC
+ HERMIT.Kure.Universes: DefCore :: CoreDef -> Core
+ HERMIT.Kure.Universes: ExprCore :: CoreExpr -> Core
+ HERMIT.Kure.Universes: GutsCore :: ModGuts -> Core
+ HERMIT.Kure.Universes: LClause :: Clause -> LCore
+ HERMIT.Kure.Universes: LCore :: Core -> LCore
+ HERMIT.Kure.Universes: LQuantified :: Quantified -> LCore
+ HERMIT.Kure.Universes: LTCCore :: LCore -> LCoreTC
+ HERMIT.Kure.Universes: LTCTyCo :: TyCo -> LCoreTC
+ HERMIT.Kure.Universes: ProgCore :: CoreProg -> Core
+ HERMIT.Kure.Universes: TyCo :: TyCo -> CoreTC
+ HERMIT.Kure.Universes: TypeCore :: Type -> TyCo
+ HERMIT.Kure.Universes: coreAlphaEq :: Core -> Core -> Bool
+ HERMIT.Kure.Universes: coreSyntaxEq :: Core -> Core -> Bool
+ HERMIT.Kure.Universes: coreTCAlphaEq :: CoreTC -> CoreTC -> Bool
+ HERMIT.Kure.Universes: coreTCSyntaxEq :: CoreTC -> CoreTC -> Bool
+ HERMIT.Kure.Universes: data Core
+ HERMIT.Kure.Universes: data CoreTC
+ HERMIT.Kure.Universes: data LCore
+ HERMIT.Kure.Universes: data LCoreTC
+ HERMIT.Kure.Universes: data TyCo
+ HERMIT.Kure.Universes: freeVarsCore :: Core -> VarSet
+ HERMIT.Kure.Universes: freeVarsCoreTC :: CoreTC -> VarSet
+ HERMIT.Kure.Universes: freeVarsTyCo :: TyCo -> VarSet
+ HERMIT.Kure.Universes: instance Injection Clause LCore
+ HERMIT.Kure.Universes: instance Injection Clause LCoreTC
+ HERMIT.Kure.Universes: instance Injection Coercion CoreTC
+ HERMIT.Kure.Universes: instance Injection Coercion LCoreTC
+ HERMIT.Kure.Universes: instance Injection Coercion TyCo
+ HERMIT.Kure.Universes: instance Injection Core CoreTC
+ HERMIT.Kure.Universes: instance Injection Core LCore
+ HERMIT.Kure.Universes: instance Injection Core LCoreTC
+ HERMIT.Kure.Universes: instance Injection CoreAlt Core
+ HERMIT.Kure.Universes: instance Injection CoreAlt CoreTC
+ HERMIT.Kure.Universes: instance Injection CoreAlt LCore
+ HERMIT.Kure.Universes: instance Injection CoreAlt LCoreTC
+ HERMIT.Kure.Universes: instance Injection CoreBind Core
+ HERMIT.Kure.Universes: instance Injection CoreBind CoreTC
+ HERMIT.Kure.Universes: instance Injection CoreBind LCore
+ HERMIT.Kure.Universes: instance Injection CoreBind LCoreTC
+ HERMIT.Kure.Universes: instance Injection CoreDef Core
+ HERMIT.Kure.Universes: instance Injection CoreDef CoreTC
+ HERMIT.Kure.Universes: instance Injection CoreDef LCore
+ HERMIT.Kure.Universes: instance Injection CoreDef LCoreTC
+ HERMIT.Kure.Universes: instance Injection CoreExpr Core
+ HERMIT.Kure.Universes: instance Injection CoreExpr CoreTC
+ HERMIT.Kure.Universes: instance Injection CoreExpr LCore
+ HERMIT.Kure.Universes: instance Injection CoreExpr LCoreTC
+ HERMIT.Kure.Universes: instance Injection CoreProg Core
+ HERMIT.Kure.Universes: instance Injection CoreProg CoreTC
+ HERMIT.Kure.Universes: instance Injection CoreProg LCore
+ HERMIT.Kure.Universes: instance Injection CoreProg LCoreTC
+ HERMIT.Kure.Universes: instance Injection CoreTC LCoreTC
+ HERMIT.Kure.Universes: instance Injection LCore LCoreTC
+ HERMIT.Kure.Universes: instance Injection ModGuts Core
+ HERMIT.Kure.Universes: instance Injection ModGuts CoreTC
+ HERMIT.Kure.Universes: instance Injection ModGuts LCore
+ HERMIT.Kure.Universes: instance Injection ModGuts LCoreTC
+ HERMIT.Kure.Universes: instance Injection Quantified LCore
+ HERMIT.Kure.Universes: instance Injection Quantified LCoreTC
+ HERMIT.Kure.Universes: instance Injection TyCo CoreTC
+ HERMIT.Kure.Universes: instance Injection TyCo LCoreTC
+ HERMIT.Kure.Universes: instance Injection Type CoreTC
+ HERMIT.Kure.Universes: instance Injection Type LCoreTC
+ HERMIT.Kure.Universes: instance Injection Type TyCo
+ HERMIT.Kure.Universes: lcoreSyntaxEq :: LCore -> LCore -> Bool
+ HERMIT.Kure.Universes: lcoreTCSyntaxEq :: LCoreTC -> LCoreTC -> Bool
+ HERMIT.Kure.Universes: promoteAltR :: (Monad m, Injection CoreAlt g) => Rewrite c m CoreAlt -> Rewrite c m g
+ HERMIT.Kure.Universes: promoteAltT :: (Monad m, Injection CoreAlt g) => Transform c m CoreAlt b -> Transform c m g b
+ HERMIT.Kure.Universes: promoteBindR :: (Monad m, Injection CoreBind g) => Rewrite c m CoreBind -> Rewrite c m g
+ HERMIT.Kure.Universes: promoteBindT :: (Monad m, Injection CoreBind g) => Transform c m CoreBind b -> Transform c m g b
+ HERMIT.Kure.Universes: promoteClauseR :: (Monad m, Injection Clause g) => Rewrite c m Clause -> Rewrite c m g
+ HERMIT.Kure.Universes: promoteClauseT :: (Monad m, Injection Clause g) => Transform c m Clause b -> Transform c m g b
+ HERMIT.Kure.Universes: promoteCoercionR :: (Monad m, Injection Coercion g) => Rewrite c m Coercion -> Rewrite c m g
+ HERMIT.Kure.Universes: promoteCoercionT :: (Monad m, Injection Coercion g) => Transform c m Coercion b -> Transform c m g b
+ HERMIT.Kure.Universes: promoteCoreR :: (Monad m, Injection Core g) => Rewrite c m Core -> Rewrite c m g
+ HERMIT.Kure.Universes: promoteCoreT :: (Monad m, Injection Core g) => Transform c m Core b -> Transform c m g b
+ HERMIT.Kure.Universes: promoteCoreTCR :: (Monad m, Injection CoreTC g) => Rewrite c m CoreTC -> Rewrite c m g
+ HERMIT.Kure.Universes: promoteCoreTCT :: (Monad m, Injection CoreTC g) => Transform c m CoreTC b -> Transform c m g b
+ HERMIT.Kure.Universes: promoteDefR :: (Monad m, Injection CoreDef g) => Rewrite c m CoreDef -> Rewrite c m g
+ HERMIT.Kure.Universes: promoteDefT :: (Monad m, Injection CoreDef g) => Transform c m CoreDef b -> Transform c m g b
+ HERMIT.Kure.Universes: promoteExprBiR :: (Monad m, Injection CoreExpr g) => BiRewrite c m CoreExpr -> BiRewrite c m g
+ HERMIT.Kure.Universes: promoteExprR :: (Monad m, Injection CoreExpr g) => Rewrite c m CoreExpr -> Rewrite c m g
+ HERMIT.Kure.Universes: promoteExprT :: (Monad m, Injection CoreExpr g) => Transform c m CoreExpr b -> Transform c m g b
+ HERMIT.Kure.Universes: promoteLCoreR :: (Monad m, Injection LCore g) => Rewrite c m LCore -> Rewrite c m g
+ HERMIT.Kure.Universes: promoteLCoreT :: (Monad m, Injection LCore g) => Transform c m LCore b -> Transform c m g b
+ HERMIT.Kure.Universes: promoteModGutsR :: (Monad m, Injection ModGuts g) => Rewrite c m ModGuts -> Rewrite c m g
+ HERMIT.Kure.Universes: promoteModGutsT :: (Monad m, Injection ModGuts g) => Transform c m ModGuts b -> Transform c m g b
+ HERMIT.Kure.Universes: promoteProgR :: (Monad m, Injection CoreProg g) => Rewrite c m CoreProg -> Rewrite c m g
+ HERMIT.Kure.Universes: promoteProgT :: (Monad m, Injection CoreProg g) => Transform c m CoreProg b -> Transform c m g b
+ HERMIT.Kure.Universes: promoteQuantifiedR :: (Monad m, Injection Quantified g) => Rewrite c m Quantified -> Rewrite c m g
+ HERMIT.Kure.Universes: promoteQuantifiedT :: (Monad m, Injection Quantified g) => Transform c m Quantified b -> Transform c m g b
+ HERMIT.Kure.Universes: promoteTypeR :: (Monad m, Injection Type g) => Rewrite c m Type -> Rewrite c m g
+ HERMIT.Kure.Universes: promoteTypeT :: (Monad m, Injection Type g) => Transform c m Type b -> Transform c m g b
+ HERMIT.Kure.Universes: tyCoAlphaEq :: TyCo -> TyCo -> Bool
+ HERMIT.Kure.Universes: tyCoSyntaxEq :: TyCo -> TyCo -> Bool
+ HERMIT.Lemma: Assumed :: Bool -> Proven
+ HERMIT.Lemma: Conj :: Quantified -> Quantified -> Clause
+ HERMIT.Lemma: Disj :: Quantified -> Quantified -> Clause
+ HERMIT.Lemma: Equiv :: CoreExpr -> CoreExpr -> Clause
+ HERMIT.Lemma: Impl :: Quantified -> Quantified -> Clause
+ HERMIT.Lemma: Lemma :: Quantified -> Proven -> Used -> Bool -> Lemma
+ HERMIT.Lemma: LemmaName :: String -> LemmaName
+ HERMIT.Lemma: NotProven :: Proven
+ HERMIT.Lemma: NotUsed :: Used
+ HERMIT.Lemma: Obligation :: Used
+ HERMIT.Lemma: Proven :: Proven
+ HERMIT.Lemma: Quantified :: [CoreBndr] -> Clause -> Quantified
+ HERMIT.Lemma: UnsafeUsed :: Used
+ HERMIT.Lemma: andP :: Proven -> Proven -> Proven
+ HERMIT.Lemma: clauseSyntaxEq :: Clause -> Clause -> Bool
+ HERMIT.Lemma: data Clause
+ HERMIT.Lemma: data Lemma
+ HERMIT.Lemma: data Proven
+ HERMIT.Lemma: data Quantified
+ HERMIT.Lemma: data Used
+ HERMIT.Lemma: discardUniVars :: Quantified -> Quantified
+ HERMIT.Lemma: dropBinders :: Quantified -> Quantified
+ HERMIT.Lemma: freeVarsQuantified :: Quantified -> VarSet
+ HERMIT.Lemma: instQuantified :: MonadCatch m => VarSet -> (Var -> Bool) -> CoreExpr -> Quantified -> m Quantified
+ HERMIT.Lemma: instance Eq LemmaName
+ HERMIT.Lemma: instance Eq Proven
+ HERMIT.Lemma: instance Eq Used
+ HERMIT.Lemma: instance IsString LemmaName
+ HERMIT.Lemma: instance Monoid LemmaName
+ HERMIT.Lemma: instance Ord LemmaName
+ HERMIT.Lemma: instance Ord Proven
+ HERMIT.Lemma: instance Show LemmaName
+ HERMIT.Lemma: instance Show Proven
+ HERMIT.Lemma: instance Show Used
+ HERMIT.Lemma: instance Typeable LemmaName
+ HERMIT.Lemma: instance Typeable Proven
+ HERMIT.Lemma: instance Typeable Used
+ HERMIT.Lemma: instsQuantified :: MonadCatch m => VarSet -> [(Var, CoreExpr)] -> Quantified -> m Quantified
+ HERMIT.Lemma: lemmaP :: Lemma -> Proven
+ HERMIT.Lemma: lemmaQ :: Lemma -> Quantified
+ HERMIT.Lemma: lemmaT :: Lemma -> Bool
+ HERMIT.Lemma: lemmaU :: Lemma -> Used
+ HERMIT.Lemma: mkQuantified :: [CoreBndr] -> CoreExpr -> CoreExpr -> Quantified
+ HERMIT.Lemma: newtype LemmaName
+ HERMIT.Lemma: orP :: Proven -> Proven -> Proven
+ HERMIT.Lemma: quantifiedSyntaxEq :: Quantified -> Quantified -> Bool
+ HERMIT.Lemma: redundantDicts :: Quantified -> Quantified
+ HERMIT.Lemma: substQuantified :: Var -> CoreArg -> Quantified -> Quantified
+ HERMIT.Lemma: substQuantifieds :: [(Var, CoreArg)] -> Quantified -> Quantified
+ HERMIT.Lemma: type Lemmas = Map LemmaName Lemma
+ HERMIT.Lemma: type NamedLemma = (LemmaName, Lemma)
+ HERMIT.Libraries.Int: lemmas :: LemmaLibrary
+ HERMIT.Monad: deleteLemma :: (HasLemmas m, Monad m) => LemmaName -> m ()
+ HERMIT.Monad: findLemma :: (HasLemmas m, Monad m) => LemmaName -> m Lemma
+ HERMIT.Monad: hResChanged :: HermitMResult a -> Bool
+ HERMIT.Monad: putLemmas :: HasLemmas m => Lemmas -> m ()
+ HERMIT.Monad: withLemmas :: HasLemmas m => Lemmas -> m a -> m a
+ HERMIT.Name: cloneVarFSH :: MonadUnique m => (FastString -> FastString) -> Var -> m Var
+ HERMIT.Plugin.Builder: type HERMITPass = IORef (Maybe (AST, ASTMap)) -> PassInfo -> [CommandLineOption] -> ModGuts -> CoreM ModGuts
+ HERMIT.Plugin.Types: ps_focus :: PluginState -> AbsolutePath Crumb
+ HERMIT.PrettyPrinter.AST: externals :: [External]
+ HERMIT.PrettyPrinter.Clean: externals :: [External]
+ HERMIT.PrettyPrinter.Clean: symbol :: AbsolutePathH -> Char -> DocH
+ HERMIT.PrettyPrinter.Common: ASCII :: String -> ASCII
+ HERMIT.PrettyPrinter.Common: Detailed :: ShowOption
+ HERMIT.PrettyPrinter.Common: PrettyHLCoreBox :: (PrettyH LCore) -> PrettyHLCoreBox
+ HERMIT.PrettyPrinter.Common: PrettyHLCoreTCBox :: (PrettyH LCoreTC) -> PrettyHLCoreTCBox
+ HERMIT.PrettyPrinter.Common: TransformLCoreDocHBox :: (TransformH LCore DocH) -> TransformLCoreDocHBox
+ HERMIT.PrettyPrinter.Common: TransformLCoreTCDocHBox :: (TransformH LCoreTC DocH) -> TransformLCoreTCDocHBox
+ HERMIT.PrettyPrinter.Common: data PrettyHLCoreBox
+ HERMIT.PrettyPrinter.Common: data PrettyHLCoreTCBox
+ HERMIT.PrettyPrinter.Common: data TransformLCoreDocHBox
+ HERMIT.PrettyPrinter.Common: data TransformLCoreTCDocHBox
+ HERMIT.PrettyPrinter.Common: instance Extern (PrettyH LCore)
+ HERMIT.PrettyPrinter.Common: instance Extern (PrettyH LCoreTC)
+ HERMIT.PrettyPrinter.Common: instance Extern (TransformH LCore DocH)
+ HERMIT.PrettyPrinter.Common: instance Extern (TransformH LCoreTC DocH)
+ HERMIT.PrettyPrinter.Common: instance Extern PrettyPrinter
+ HERMIT.PrettyPrinter.Common: instance Typeable PrettyHLCoreBox
+ HERMIT.PrettyPrinter.Common: instance Typeable PrettyHLCoreTCBox
+ HERMIT.PrettyPrinter.Common: instance Typeable PrettyPrinter
+ HERMIT.PrettyPrinter.Common: instance Typeable TransformLCoreDocHBox
+ HERMIT.PrettyPrinter.Common: instance Typeable TransformLCoreTCDocHBox
+ HERMIT.PrettyPrinter.Common: newtype ASCII
+ HERMIT.PrettyPrinter.GHC: externals :: [External]
+ HERMIT.Shell.Command: interpShell :: (MonadCatch m, CLMonad m) => [Interp m ()]
+ HERMIT.Shell.Completion: completer :: (MonadCatch m, CLMonad m) => String -> String -> m [Completion]
+ HERMIT.Shell.Proof: PCUser :: UserProofTechnique -> ProofShellCommand
+ HERMIT.Shell.Proof: data ProofShellCommand
+ HERMIT.Shell.Proof: forceProofs :: (MonadCatch m, CLMonad m) => m ()
+ HERMIT.Shell.Proof: instance Typeable UserProofTechnique
+ HERMIT.Shell.Proof: performProofShellCommand :: (MonadCatch m, CLMonad m) => ProofShellCommand -> ExprH -> m ()
+ HERMIT.Shell.Proof: withProofExternals :: (MonadError CLException m, MonadState CommandLineState m) => m a -> m a
+ HERMIT.Shell.ScriptToRewrite: fileToScript :: CLMonad m => FilePath -> m Script
+ HERMIT.Shell.ScriptToRewrite: pushScript :: MonadState CommandLineState m => Script -> m ()
+ HERMIT.Shell.ScriptToRewrite: pushScriptLine :: MonadState CommandLineState m => ExprH -> m ()
+ HERMIT.Shell.ShellEffect: dumpT :: FilePath -> PrettyPrinter -> String -> Int -> TransformH DocH ()
+ HERMIT.Shell.Types: MarkProven :: LemmaName -> Bool -> ProofTodo
+ HERMIT.Shell.Types: NoSafety :: Safety
+ HERMIT.Shell.Types: NormalSafety :: Safety
+ HERMIT.Shell.Types: QueryPrettyH :: PrettyH a -> QueryFun
+ HERMIT.Shell.Types: QueryUnit :: TransformH a () -> QueryFun
+ HERMIT.Shell.Types: StrictSafety :: Safety
+ HERMIT.Shell.Types: T :: Direction
+ HERMIT.Shell.Types: Tag :: TagName -> VersionCmd
+ HERMIT.Shell.Types: U :: Direction
+ HERMIT.Shell.Types: Unproven :: LemmaName -> Lemma -> HermitC -> [NamedLemma] -> PathStack -> ProofTodo
+ HERMIT.Shell.Types: addAST :: CLMonad m => AST -> m ()
+ HERMIT.Shell.Types: addFocusR :: (Injection a g, Walker HermitC g, CLMonad m) => RewriteH g -> m (RewriteH a)
+ HERMIT.Shell.Types: addFocusT :: (Injection a g, Walker HermitC g, CLMonad m) => TransformH g b -> m (TransformH a b)
+ HERMIT.Shell.Types: announceProven :: (MonadCatch m, CLMonad m) => m ()
+ HERMIT.Shell.Types: announceUnprovens :: (MonadCatch m, CLMonad m) => m ()
+ HERMIT.Shell.Types: cl_foci :: CommandLineState -> Map AST PathStack
+ HERMIT.Shell.Types: cl_proofstack :: CommandLineState -> Map AST [ProofTodo]
+ HERMIT.Shell.Types: cl_safety :: CommandLineState -> Safety
+ HERMIT.Shell.Types: cl_tags :: CommandLineState -> Map AST [String]
+ HERMIT.Shell.Types: copyPathStack :: CLMonad m => AST -> m ()
+ HERMIT.Shell.Types: copyProofStack :: CLMonad m => AST -> m ()
+ HERMIT.Shell.Types: currentLemma :: CLMonad m => m (LemmaName, Lemma, HermitC, [NamedLemma], PathStack)
+ HERMIT.Shell.Types: data Direction
+ HERMIT.Shell.Types: data ProofTodo
+ HERMIT.Shell.Types: data Safety
+ HERMIT.Shell.Types: filterSafety :: Safety -> [External] -> [External]
+ HERMIT.Shell.Types: getFocusPath :: CLMonad m => m PathH
+ HERMIT.Shell.Types: getPathStack :: CLMonad m => m ([LocalPathH], LocalPathH)
+ HERMIT.Shell.Types: getProofStack :: CLMonad m => m [ProofTodo]
+ HERMIT.Shell.Types: getProofStackEmpty :: CLMonad m => m [ProofTodo]
+ HERMIT.Shell.Types: inProofFocusR :: ProofTodo -> RewriteH LCoreTC -> TransformH Core Quantified
+ HERMIT.Shell.Types: inProofFocusT :: ProofTodo -> TransformH LCoreTC b -> TransformH Core b
+ HERMIT.Shell.Types: instance Eq Direction
+ HERMIT.Shell.Types: instance MonadException m => MonadException (ExceptT e m)
+ HERMIT.Shell.Types: instance Show Direction
+ HERMIT.Shell.Types: modifyLocalPath :: (MonadCatch m, CLMonad m) => (LocalPathH -> LocalPathH) -> ExprH -> m ()
+ HERMIT.Shell.Types: pathStack2Path :: ([LocalPath crumb], LocalPath crumb) -> Path crumb
+ HERMIT.Shell.Types: pathStackToLens :: (Injection a g, Walker HermitC g) => [LocalPathH] -> LocalPathH -> LensH a g
+ HERMIT.Shell.Types: popProofStack :: CLMonad m => m ProofTodo
+ HERMIT.Shell.Types: printLemma :: (MonadCatch m, MonadError CLException m, MonadIO m, MonadState CommandLineState m) => Handle -> HermitC -> PathStack -> (LemmaName, Lemma) -> m ()
+ HERMIT.Shell.Types: ptAssumed :: ProofTodo -> [NamedLemma]
+ HERMIT.Shell.Types: ptContext :: ProofTodo -> HermitC
+ HERMIT.Shell.Types: ptLemma :: ProofTodo -> Lemma
+ HERMIT.Shell.Types: ptName :: ProofTodo -> LemmaName
+ HERMIT.Shell.Types: ptPath :: ProofTodo -> PathStack
+ HERMIT.Shell.Types: ptTemp :: ProofTodo -> Bool
+ HERMIT.Shell.Types: pushProofStack :: CLMonad m => ProofTodo -> m ()
+ HERMIT.Shell.Types: queryInContext :: (MonadCatch m, CLMonad m) => TransformH LCoreTC b -> CommitMsg -> m b
+ HERMIT.Shell.Types: queryInFocus :: (Walker HermitC g, Injection ModGuts g, MonadCatch m, CLMonad m) => TransformH g b -> CommitMsg -> m b
+ HERMIT.Shell.Types: requireDifferent :: Monad m => LocalPathH -> LocalPathH -> m ()
+ HERMIT.Shell.Types: type PathStack = ([LocalPathH], LocalPathH)
+ HERMIT.Shell.Types: type TagName = String
+ HERMIT.Shell.Types: withLemmasInScope :: HasLemmas m => [(LemmaName, Lemma)] -> Transform c m a b -> Transform c m a b
- HERMIT.Dictionary.Composite: bashDebugR :: (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb, HasDebugChan m, HasDynFlags m, MonadCatch m, MonadUnique m) => Rewrite c m Core
+ HERMIT.Dictionary.Composite: bashDebugR :: (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb, HasDebugChan m, HasDynFlags m, MonadCatch m, MonadUnique m) => Rewrite c m LCore
- HERMIT.Dictionary.Composite: bashExtendedWithR :: (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb, MonadCatch m, MonadUnique m) => [Rewrite c m Core] -> Rewrite c m Core
+ HERMIT.Dictionary.Composite: bashExtendedWithR :: (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb, MonadCatch m, MonadUnique m) => [Rewrite c m LCore] -> Rewrite c m LCore
- HERMIT.Dictionary.Composite: bashR :: (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb, MonadCatch m, MonadUnique m) => Rewrite c m Core
+ HERMIT.Dictionary.Composite: bashR :: (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb, MonadCatch m, MonadUnique m) => Rewrite c m LCore
- HERMIT.Dictionary.Composite: bashUsingR :: (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadPath c Crumb, MonadCatch m) => [Rewrite c m Core] -> Rewrite c m Core
+ HERMIT.Dictionary.Composite: bashUsingR :: (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadPath c Crumb, MonadCatch m) => [Rewrite c m LCore] -> Rewrite c m LCore
- HERMIT.Dictionary.Composite: simplifyR :: (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb, MonadCatch m, MonadUnique m) => Rewrite c m Core
+ HERMIT.Dictionary.Composite: simplifyR :: (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb, MonadCatch m, MonadUnique m) => Rewrite c m LCore
- HERMIT.Dictionary.Composite: smashExtendedWithR :: (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb, MonadCatch m, MonadUnique m) => [Rewrite c m Core] -> Rewrite c m Core
+ HERMIT.Dictionary.Composite: smashExtendedWithR :: (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb, MonadCatch m, MonadUnique m) => [Rewrite c m LCore] -> Rewrite c m LCore
- HERMIT.Dictionary.Composite: smashR :: (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb, MonadCatch m, MonadUnique m) => Rewrite c m Core
+ HERMIT.Dictionary.Composite: smashR :: (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb, MonadCatch m, MonadUnique m) => Rewrite c m LCore
- HERMIT.Dictionary.Composite: smashUsingR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, HasEmptyContext c, MonadCatch m) => [Rewrite c m Core] -> [Rewrite c m Core] -> Rewrite c m Core
+ HERMIT.Dictionary.Composite: smashUsingR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, HasEmptyContext c, MonadCatch m) => [Rewrite c m LCore] -> [Rewrite c m LCore] -> Rewrite c m LCore
- HERMIT.Dictionary.Debug: bracketR :: (Injection a CoreTC, ReadBindings c, ReadPath c Crumb, HasDebugChan m, MonadCatch m) => String -> Rewrite c m a -> Rewrite c m a
+ HERMIT.Dictionary.Debug: bracketR :: (Injection a LCoreTC, ReadBindings c, ReadPath c Crumb, HasDebugChan m, MonadCatch m) => String -> Rewrite c m a -> Rewrite c m a
- HERMIT.Dictionary.Debug: observeFailureR :: (Injection a CoreTC, ReadBindings c, ReadPath c Crumb, HasDebugChan m, MonadCatch m) => String -> Rewrite c m a -> Rewrite c m a
+ HERMIT.Dictionary.Debug: observeFailureR :: (Injection a LCoreTC, ReadBindings c, ReadPath c Crumb, HasDebugChan m, MonadCatch m) => String -> Rewrite c m a -> Rewrite c m a
- HERMIT.Dictionary.Debug: observeR :: (Injection a CoreTC, ReadBindings c, ReadPath c Crumb, HasDebugChan m, Monad m) => String -> Rewrite c m a
+ HERMIT.Dictionary.Debug: observeR :: (Injection a LCoreTC, ReadBindings c, ReadPath c Crumb, HasDebugChan m, Monad m) => String -> Rewrite c m a
- HERMIT.Dictionary.Fold: fold :: Id -> CoreExpr -> CoreExpr -> Maybe CoreExpr
+ HERMIT.Dictionary.Fold: fold :: BoundVars c => [Equality] -> c -> CoreExpr -> Maybe CoreExpr
- HERMIT.Dictionary.Function: buildCompositionT :: (BoundVars c, HasDynFlags m, HasHermitMEnv m, HasHscEnv m, MonadCatch m, MonadIO m, MonadThings m) => CoreExpr -> CoreExpr -> Transform c m x CoreExpr
+ HERMIT.Dictionary.Function: buildCompositionT :: (BoundVars c, HasHermitMEnv m, HasHscEnv m, MonadCatch m, MonadIO m, MonadThings m) => CoreExpr -> CoreExpr -> Transform c m x CoreExpr
- HERMIT.Dictionary.GHC: occurAnalyseAndDezombifyR :: (AddBindings c, ExtendPath c Crumb, ReadPath c Crumb, HasEmptyContext c, MonadCatch m) => Rewrite c m Core
+ HERMIT.Dictionary.GHC: occurAnalyseAndDezombifyR :: (AddBindings c, ExtendPath c Crumb, ReadPath c Crumb, HasEmptyContext c, MonadCatch m, Walker c u, Injection CoreExpr u) => Rewrite c m u
- HERMIT.Dictionary.GHC: occurAnalyseChangedR :: (AddBindings c, ExtendPath c Crumb, ReadPath c Crumb, HasEmptyContext c, MonadCatch m) => Rewrite c m Core
+ HERMIT.Dictionary.GHC: occurAnalyseChangedR :: (AddBindings c, ExtendPath c Crumb, ReadPath c Crumb, HasEmptyContext c, MonadCatch m) => Rewrite c m LCore
- HERMIT.Dictionary.GHC: occurAnalyseR :: (AddBindings c, ExtendPath c Crumb, ReadPath c Crumb, HasEmptyContext c, MonadCatch m) => Rewrite c m Core
+ HERMIT.Dictionary.GHC: occurAnalyseR :: (AddBindings c, ExtendPath c Crumb, ReadPath c Crumb, HasEmptyContext c, MonadCatch m, Walker c u, Injection CoreExpr u) => Rewrite c m u
- HERMIT.Dictionary.Inline: inlineTargetsT :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c, MonadCatch m) => Transform c m Core [String]
+ HERMIT.Dictionary.Inline: inlineTargetsT :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c, MonadCatch m) => Transform c m LCore [String]
- HERMIT.Dictionary.Local.Case: caseFloatArgLemmaR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb, HasHermitMEnv m, HasHscEnv m, HasDynFlags m, HasLemmas m, MonadCatch m, MonadIO m, MonadThings m, MonadUnique m) => LemmaName -> Rewrite c m CoreExpr
+ HERMIT.Dictionary.Local.Case: caseFloatArgLemmaR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb, HasHermitMEnv m, HasHscEnv m, HasDynFlags m, HasLemmas m, MonadCatch m, MonadIO m, MonadThings m, MonadUnique m) => Used -> LemmaName -> Rewrite c m CoreExpr
- HERMIT.Dictionary.Local.Case: caseSplitInlineR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c, MonadCatch m, MonadUnique m) => (Id -> Bool) -> Rewrite c m CoreExpr
+ HERMIT.Dictionary.Local.Case: caseSplitInlineR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c, MonadCatch m, MonadUnique m) => CoreExpr -> Rewrite c m CoreExpr
- HERMIT.Dictionary.Local.Case: caseSplitR :: (MonadCatch m, MonadUnique m) => (Id -> Bool) -> Rewrite c m CoreExpr
+ HERMIT.Dictionary.Local.Case: caseSplitR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, HasEmptyContext c, ReadPath c Crumb, MonadCatch m, MonadUnique m) => CoreExpr -> Rewrite c m CoreExpr
- HERMIT.Dictionary.Navigation: bindingGroupOfT :: (AddBindings c, ExtendPath c Crumb, ReadPath c Crumb, HasEmptyContext c, MonadCatch m) => (Var -> Bool) -> Transform c m CoreTC LocalPathH
+ HERMIT.Dictionary.Navigation: bindingGroupOfT :: (AddBindings c, ExtendPath c Crumb, ReadPath c Crumb, HasEmptyContext c, MonadCatch m) => (Var -> Bool) -> Transform c m LCoreTC LocalPathH
- HERMIT.Dictionary.Navigation: bindingGroupOfTargetsT :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, HasEmptyContext c, MonadCatch m) => Transform c m CoreTC VarSet
+ HERMIT.Dictionary.Navigation: bindingGroupOfTargetsT :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, HasEmptyContext c, MonadCatch m) => Transform c m LCoreTC VarSet
- HERMIT.Dictionary.Navigation: bindingOfT :: (AddBindings c, ExtendPath c Crumb, ReadPath c Crumb, HasEmptyContext c, MonadCatch m) => (Var -> Bool) -> Transform c m CoreTC LocalPathH
+ HERMIT.Dictionary.Navigation: bindingOfT :: (AddBindings c, ExtendPath c Crumb, ReadPath c Crumb, HasEmptyContext c, MonadCatch m) => (Var -> Bool) -> Transform c m LCoreTC LocalPathH
- HERMIT.Dictionary.Navigation: bindingOfTargetsT :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, HasEmptyContext c, MonadCatch m) => Transform c m CoreTC VarSet
+ HERMIT.Dictionary.Navigation: bindingOfTargetsT :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, HasEmptyContext c, MonadCatch m) => Transform c m LCoreTC VarSet
- HERMIT.Dictionary.Navigation: considerConstructT :: (AddBindings c, ExtendPath c Crumb, ReadPath c Crumb, HasEmptyContext c, MonadCatch m) => Considerable -> Transform c m Core LocalPathH
+ HERMIT.Dictionary.Navigation: considerConstructT :: (AddBindings c, ExtendPath c Crumb, ReadPath c Crumb, HasEmptyContext c, MonadCatch m) => Considerable -> Transform c m LCore LocalPathH
- HERMIT.Dictionary.Navigation: occurrenceOfT :: (AddBindings c, ExtendPath c Crumb, ReadPath c Crumb, HasEmptyContext c, MonadCatch m) => (Var -> Bool) -> Transform c m CoreTC LocalPathH
+ HERMIT.Dictionary.Navigation: occurrenceOfT :: (AddBindings c, ExtendPath c Crumb, ReadPath c Crumb, HasEmptyContext c, MonadCatch m) => (Var -> Bool) -> Transform c m LCoreTC LocalPathH
- HERMIT.Dictionary.Navigation: occurrenceOfTargetsT :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, HasEmptyContext c, MonadCatch m) => Transform c m CoreTC VarSet
+ HERMIT.Dictionary.Navigation: occurrenceOfTargetsT :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, HasEmptyContext c, MonadCatch m) => Transform c m LCoreTC VarSet
- HERMIT.Dictionary.Navigation: rhsOfT :: (AddBindings c, ExtendPath c Crumb, ReadPath c Crumb, HasEmptyContext c, MonadCatch m) => (Var -> Bool) -> Transform c m Core LocalPathH
+ HERMIT.Dictionary.Navigation: rhsOfT :: (AddBindings c, ExtendPath c Crumb, ReadPath c Crumb, HasEmptyContext c, MonadCatch m) => (Var -> Bool) -> Transform c m LCoreTC LocalPathH
- HERMIT.Dictionary.Navigation: rhsOfTargetsT :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, HasEmptyContext c, MonadCatch m) => Transform c m CoreTC VarSet
+ HERMIT.Dictionary.Navigation: rhsOfTargetsT :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, HasEmptyContext c, MonadCatch m) => Transform c m LCoreTC VarSet
- HERMIT.Dictionary.Query: compareCoreAtT :: (ExtendPath c Crumb, AddBindings c, ReadBindings c, ReadPath c Crumb, HasEmptyContext c, MonadCatch m) => Transform c m Core LocalPathH -> Transform c m Core LocalPathH -> Transform c m Core ()
+ HERMIT.Dictionary.Query: compareCoreAtT :: (ExtendPath c Crumb, AddBindings c, ReadBindings c, ReadPath c Crumb, HasEmptyContext c, MonadCatch m) => Transform c m LCoreTC LocalPathH -> Transform c m LCoreTC LocalPathH -> Transform c m LCoreTC ()
- HERMIT.Dictionary.Reasoning: birewrite :: (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb, MonadCatch m, MonadUnique m) => Equality -> BiRewrite c m CoreExpr
+ HERMIT.Dictionary.Reasoning: birewrite :: (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb, MonadCatch m, MonadUnique m) => Quantified -> BiRewrite c m CoreExpr
- HERMIT.Dictionary.Reasoning: bothR :: (AddBindings c, MonadCatch m, ReadPath c Crumb) => Rewrite c m CoreExpr -> Rewrite c m Equality
+ HERMIT.Dictionary.Reasoning: bothR :: (AddBindings c, MonadCatch m, ReadPath c Crumb, ExtendPath c Crumb) => Rewrite c m LCore -> Rewrite c m Quantified
- HERMIT.Dictionary.Reasoning: bothT :: (AddBindings c, Monad m, ReadPath c Crumb) => Transform c m CoreExpr b -> Transform c m Equality (b, b)
+ HERMIT.Dictionary.Reasoning: bothT :: (AddBindings c, ReadPath c Crumb, ExtendPath c Crumb, Monad m) => Transform c m LCore a -> Transform c m Quantified (a, a)
- HERMIT.Dictionary.Reasoning: discardUniVars :: Equality -> Equality
+ HERMIT.Dictionary.Reasoning: discardUniVars :: Quantified -> Quantified
- HERMIT.Dictionary.Reasoning: eqLhsIntroR :: Equality -> Rewrite c HermitM Core
+ HERMIT.Dictionary.Reasoning: eqLhsIntroR :: Quantified -> Rewrite c HermitM Core
- HERMIT.Dictionary.Reasoning: eqRhsIntroR :: Equality -> Rewrite c HermitM Core
+ HERMIT.Dictionary.Reasoning: eqRhsIntroR :: Quantified -> Rewrite c HermitM Core
- HERMIT.Dictionary.Reasoning: extensionalityR :: Maybe String -> Rewrite c HermitM Equality
+ HERMIT.Dictionary.Reasoning: extensionalityR :: Maybe String -> Rewrite c HermitM Quantified
- HERMIT.Dictionary.Reasoning: forallVarsT :: Monad m => Transform c m [Var] b -> Transform c m Equality b
+ HERMIT.Dictionary.Reasoning: forallVarsT :: (AddBindings c, ReadPath c Crumb, ExtendPath c Crumb, Monad m) => Transform c m [Var] b -> Transform c m Quantified b
- HERMIT.Dictionary.Reasoning: instantiateDictsR :: RewriteH Equality
+ HERMIT.Dictionary.Reasoning: instantiateDictsR :: RewriteH Quantified
- HERMIT.Dictionary.Reasoning: lhsR :: (AddBindings c, Monad m, ReadPath c Crumb) => Rewrite c m CoreExpr -> Rewrite c m Equality
+ HERMIT.Dictionary.Reasoning: lhsR :: (AddBindings c, Monad m, ReadPath c Crumb, ExtendPath c Crumb) => Rewrite c m LCore -> Rewrite c m Quantified
- HERMIT.Dictionary.Reasoning: lhsT :: (AddBindings c, Monad m, ReadPath c Crumb) => Transform c m CoreExpr b -> Transform c m Equality b
+ HERMIT.Dictionary.Reasoning: lhsT :: (AddBindings c, ReadPath c Crumb, ExtendPath c Crumb, Monad m) => Transform c m LCore a -> Transform c m Quantified a
- HERMIT.Dictionary.Reasoning: rhsR :: (AddBindings c, Monad m, ReadPath c Crumb) => Rewrite c m CoreExpr -> Rewrite c m Equality
+ HERMIT.Dictionary.Reasoning: rhsR :: (AddBindings c, Monad m, ReadPath c Crumb, ExtendPath c Crumb) => Rewrite c m LCore -> Rewrite c m Quantified
- HERMIT.Dictionary.Reasoning: rhsT :: (AddBindings c, Monad m, ReadPath c Crumb) => Transform c m CoreExpr b -> Transform c m Equality b
+ HERMIT.Dictionary.Reasoning: rhsT :: (AddBindings c, ReadPath c Crumb, ExtendPath c Crumb, Monad m) => Transform c m LCore a -> Transform c m Quantified a
- HERMIT.Dictionary.Undefined: buildStrictnessLemmaT :: (BoundVars c, HasDynFlags m, HasHscEnv m, HasHermitMEnv m, HasLemmas m, MonadCatch m, MonadIO m, MonadThings m) => LemmaName -> CoreExpr -> Transform c m x ()
+ HERMIT.Dictionary.Undefined: buildStrictnessLemmaT :: (BoundVars c, HasDynFlags m, HasHscEnv m, HasHermitMEnv m, HasLemmas m, MonadCatch m, MonadIO m, MonadThings m) => Used -> LemmaName -> CoreExpr -> Transform c m x ()
- HERMIT.Dictionary.WorkerWrapper.Common: split1BetaR :: (BoundVars c, HasDynFlags m, HasHermitMEnv m, HasHscEnv m, HasLemmas m, MonadCatch m, MonadIO m, MonadThings m, MonadUnique m) => LemmaName -> CoreExpr -> CoreExpr -> Rewrite c m CoreExpr
+ HERMIT.Dictionary.WorkerWrapper.Common: split1BetaR :: (BoundVars c, HasHermitMEnv m, HasHscEnv m, HasLemmas m, MonadCatch m, MonadIO m, MonadThings m, MonadUnique m) => Used -> LemmaName -> CoreExpr -> CoreExpr -> Rewrite c m CoreExpr
- HERMIT.Dictionary.WorkerWrapper.Common: split2BetaR :: (BoundVars c, HasDynFlags m, HasHermitMEnv m, HasHscEnv m, HasLemmas m, MonadCatch m, MonadIO m, MonadThings m, MonadUnique m) => LemmaName -> CoreExpr -> CoreExpr -> Rewrite c m CoreExpr
+ HERMIT.Dictionary.WorkerWrapper.Common: split2BetaR :: (BoundVars c, HasHermitMEnv m, HasHscEnv m, HasLemmas m, MonadCatch m, MonadIO m, MonadThings m, MonadUnique m) => Used -> LemmaName -> CoreExpr -> CoreExpr -> Rewrite c m CoreExpr
- HERMIT.Dictionary.WorkerWrapper.Common: workLabel :: RememberedName
+ HERMIT.Dictionary.WorkerWrapper.Common: workLabel :: LemmaName
- HERMIT.Kernel: abortK :: Kernel -> IO ()
+ HERMIT.Kernel: abortK :: Kernel -> MonadIO m => m ()
- HERMIT.Kernel: applyK :: Kernel -> AST -> RewriteH ModGuts -> KernelEnv -> IO (KureM AST)
+ HERMIT.Kernel: applyK :: Kernel -> (MonadIO m, MonadCatch m) => RewriteH ModGuts -> CommitMsg -> KernelEnv -> AST -> m AST
- HERMIT.Kernel: deleteK :: Kernel -> AST -> IO ()
+ HERMIT.Kernel: deleteK :: Kernel -> MonadIO m => AST -> m ()
- HERMIT.Kernel: hermitKernel :: (Kernel -> AST -> IO ()) -> ModGuts -> CoreM ModGuts
+ HERMIT.Kernel: hermitKernel :: IORef (Maybe (AST, ASTMap)) -> String -> (Kernel -> AST -> IO ()) -> ModGuts -> CoreM ModGuts
- HERMIT.Kernel: listK :: Kernel -> IO [AST]
+ HERMIT.Kernel: listK :: Kernel -> MonadIO m => m [(AST, Maybe String, Maybe AST)]
- HERMIT.Kernel: queryK :: Kernel -> forall a. AST -> TransformH ModGuts a -> KernelEnv -> IO (KureM a)
+ HERMIT.Kernel: queryK :: Kernel -> (MonadIO m, MonadCatch m) => TransformH ModGuts a -> CommitMsg -> KernelEnv -> AST -> m (AST, a)
- HERMIT.Kernel: resumeK :: Kernel -> AST -> IO ()
+ HERMIT.Kernel: resumeK :: Kernel -> MonadIO m => AST -> m ()
- HERMIT.Monad: DebugCore :: String -> c -> CoreTC -> DebugMessage
+ HERMIT.Monad: DebugCore :: String -> c -> LCoreTC -> DebugMessage
- HERMIT.Monad: HermitMResult :: DefStash -> Lemmas -> a -> HermitMResult a
+ HERMIT.Monad: HermitMResult :: Bool -> Lemmas -> a -> HermitMResult a
- HERMIT.Monad: embedHermitM :: (HasDebugChan m, HasHermitMEnv m, HasLemmas m, HasStash m, LiftCoreM m) => HermitM a -> m a
+ HERMIT.Monad: embedHermitM :: (HasDebugChan m, HasHermitMEnv m, HasLemmas m, LiftCoreM m) => HermitM a -> m a
- HERMIT.Monad: insertLemma :: HasLemmas m => LemmaName -> Lemma -> m ()
+ HERMIT.Monad: insertLemma :: (HasLemmas m, Monad m) => LemmaName -> Lemma -> m ()
- HERMIT.Monad: mkEnv :: ModGuts -> DefStash -> Lemmas -> HermitMEnv
+ HERMIT.Monad: mkEnv :: ModGuts -> Lemmas -> HermitMEnv
- HERMIT.Name: hnUnqualified :: HermitName -> String
+ HERMIT.Name: hnUnqualified :: HermitName -> FastString
- HERMIT.ParserCore: parse2BeforeT :: (BoundVars c, HasDebugChan m, HasHermitMEnv m, HasLemmas m, HasStash m, LiftCoreM m) => (CoreExpr -> CoreExpr -> Translate c m a b) -> CoreString -> CoreString -> Translate c m a b
+ HERMIT.ParserCore: parse2BeforeT :: (ReadBindings c, HasDebugChan m, HasHermitMEnv m, HasLemmas m, LiftCoreM m) => (CoreExpr -> CoreExpr -> Translate c m a b) -> CoreString -> CoreString -> Translate c m a b
- HERMIT.ParserCore: parse3BeforeT :: (BoundVars c, HasDebugChan m, HasHermitMEnv m, HasLemmas m, HasStash m, LiftCoreM m) => (CoreExpr -> CoreExpr -> CoreExpr -> Translate c m a b) -> CoreString -> CoreString -> CoreString -> Translate c m a b
+ HERMIT.ParserCore: parse3BeforeT :: (ReadBindings c, HasDebugChan m, HasHermitMEnv m, HasLemmas m, LiftCoreM m) => (CoreExpr -> CoreExpr -> CoreExpr -> Translate c m a b) -> CoreString -> CoreString -> CoreString -> Translate c m a b
- HERMIT.ParserCore: parseCore :: BoundVars c => CoreString -> c -> HermitM CoreExpr
+ HERMIT.ParserCore: parseCore :: ReadBindings c => CoreString -> c -> HermitM CoreExpr
- HERMIT.ParserCore: parseCoreExprT :: (BoundVars c, HasDebugChan m, HasHermitMEnv m, HasLemmas m, HasStash m, LiftCoreM m) => CoreString -> Transform c m a CoreExpr
+ HERMIT.ParserCore: parseCoreExprT :: (ReadBindings c, HasDebugChan m, HasHermitMEnv m, HasLemmas m, LiftCoreM m) => CoreString -> Transform c m a CoreExpr
- HERMIT.Plugin: defPS :: SAST -> ScopedKernel -> PassInfo -> IO PluginState
+ HERMIT.Plugin: defPS :: AST -> Kernel -> PassInfo -> IO PluginState
- HERMIT.Plugin.Builder: buildPlugin :: PluginPass -> Plugin
+ HERMIT.Plugin.Builder: buildPlugin :: HERMITPass -> Plugin
- HERMIT.Plugin.Display: display :: Maybe PathH -> PluginM ()
+ HERMIT.Plugin.Display: display :: Maybe Handle -> Maybe PathH -> PluginM ()
- HERMIT.Plugin.Types: PResume :: SAST -> PException
+ HERMIT.Plugin.Types: PResume :: AST -> PException
- HERMIT.Plugin.Types: PluginState :: SAST -> PrettyPrinter -> (Handle -> PrettyOptions -> Either String DocH -> IO ()) -> TVar (Map String Int) -> Bool -> Bool -> Bool -> ScopedKernel -> PassInfo -> PluginState
+ HERMIT.Plugin.Types: PluginState :: AST -> AbsolutePath Crumb -> PrettyPrinter -> (Handle -> PrettyOptions -> Either String DocH -> IO ()) -> TVar (Map String Int) -> Bool -> Bool -> Bool -> Kernel -> PassInfo -> PluginState
- HERMIT.Plugin.Types: PluginT :: ErrorT PException (StateT PluginState m) a -> PluginT m a
+ HERMIT.Plugin.Types: PluginT :: ExceptT PException (StateT PluginState m) a -> PluginT m a
- HERMIT.Plugin.Types: ps_cursor :: PluginState -> SAST
+ HERMIT.Plugin.Types: ps_cursor :: PluginState -> AST
- HERMIT.Plugin.Types: ps_kernel :: PluginState -> ScopedKernel
+ HERMIT.Plugin.Types: ps_kernel :: PluginState -> Kernel
- HERMIT.Plugin.Types: unPluginT :: PluginT m a -> ErrorT PException (StateT PluginState m) a
+ HERMIT.Plugin.Types: unPluginT :: PluginT m a -> ExceptT PException (StateT PluginState m) a
- HERMIT.PrettyPrinter.Common: liftPrettyH :: (ReadBindings c, ReadPath c Crumb) => PrettyOptions -> PrettyH a -> Transform c HermitM a DocH
+ HERMIT.PrettyPrinter.Common: liftPrettyH :: (ReadBindings c, ReadPath c Crumb) => PrettyOptions -> Transform PrettyC HermitM a b -> Transform c HermitM a b
- HERMIT.Shell.Command: commandLine :: (MonadCatch m, MonadException m, CLMonad m) => [Interp m ()] -> [CommandLineOption] -> [External] -> m ()
+ HERMIT.Shell.Command: commandLine :: (MonadCatch m, MonadException m, CLMonad m) => [CommandLineOption] -> [External] -> m ()
- HERMIT.Shell.Command: evalScript :: (MonadCatch m, CLMonad m) => [Interp m ()] -> String -> m ()
+ HERMIT.Shell.Command: evalScript :: (MonadCatch m, CLMonad m) => String -> m ()
- HERMIT.Shell.Command: getFocusPath :: PluginM PathH
+ HERMIT.Shell.Command: getFocusPath :: CLMonad m => m PathH
- HERMIT.Shell.Externals: setWindow :: CommandLineState -> IO CommandLineState
+ HERMIT.Shell.Externals: setWindow :: CommandLineState -> IO (Either CLException CommandLineState)
- HERMIT.Shell.Externals: showRefactorTrail :: (Eq a, Show a) => [(a, [String], a)] -> [(a, String)] -> a -> a -> [String]
+ HERMIT.Shell.Externals: showRefactorTrail :: (Eq a, Show a) => [(a, [String], a)] -> a -> a -> [String]
- HERMIT.Shell.Externals: testAllT :: CommandLineState -> TransformH Core String
+ HERMIT.Shell.Externals: testAllT :: CommandLineState -> TransformH LCore String
- HERMIT.Shell.Externals: testRewrites :: Bool -> [(ExternalName, RewriteH Core)] -> TransformH Core String
+ HERMIT.Shell.Externals: testRewrites :: Bool -> [(ExternalName, RewriteH LCore)] -> TransformH LCore String
- HERMIT.Shell.Externals: versionCmd :: VersionCmd -> CommandLineState -> IO CommandLineState
+ HERMIT.Shell.Externals: versionCmd :: VersionCmd -> CommandLineState -> IO (Either CLException CommandLineState)
- HERMIT.Shell.KernelEffect: Delete :: SAST -> KernelEffect
+ HERMIT.Shell.KernelEffect: Delete :: AST -> KernelEffect
- HERMIT.Shell.KernelEffect: applyRewrite :: (Injection ModGuts g, Walker HermitC g, MonadCatch m, CLMonad m) => RewriteH g -> ExprH -> m ()
+ HERMIT.Shell.KernelEffect: applyRewrite :: (MonadCatch m, CLMonad m) => RewriteH LCoreTC -> ExprH -> m ()
- HERMIT.Shell.KernelEffect: setPath :: (Injection ModGuts g, Walker HermitC g, MonadCatch m, CLMonad m) => TransformH g LocalPathH -> ExprH -> m ()
+ HERMIT.Shell.KernelEffect: setPath :: (Injection a LCoreTC, MonadCatch m, CLMonad m) => TransformH a LocalPathH -> ExprH -> m ()
- HERMIT.Shell.Proof: userProofTechnique :: TransformH Equality () -> UserProofTechnique
+ HERMIT.Shell.Proof: userProofTechnique :: TransformH LCoreTC () -> UserProofTechnique
- HERMIT.Shell.ScriptToRewrite: SaveFile :: FilePath -> ScriptEffect
+ HERMIT.Shell.ScriptToRewrite: SaveFile :: Bool -> FilePath -> ScriptEffect
- HERMIT.Shell.ScriptToRewrite: performScriptEffect :: (MonadCatch m, CLMonad m) => (ExprH -> m ()) -> ScriptEffect -> m ()
+ HERMIT.Shell.ScriptToRewrite: performScriptEffect :: (MonadCatch m, CLMonad m) => ScriptEffect -> m ()
- HERMIT.Shell.ScriptToRewrite: scriptToRewrite :: CLMonad m => Script -> m (RewriteH Core)
+ HERMIT.Shell.ScriptToRewrite: scriptToRewrite :: CLMonad m => Script -> m (RewriteH LCore)
- HERMIT.Shell.ShellEffect: CLSModify :: (CommandLineState -> IO CommandLineState) -> ShellEffect
+ HERMIT.Shell.ShellEffect: CLSModify :: (CommandLineState -> IO (Either CLException CommandLineState)) -> ShellEffect
- HERMIT.Shell.ShellEffect: PluginComp :: (PluginM ()) -> ShellEffect
+ HERMIT.Shell.ShellEffect: PluginComp :: PluginM () -> ShellEffect
- HERMIT.Shell.ShellEffect: data ShellEffect
+ HERMIT.Shell.ShellEffect: data ShellEffect :: *
- HERMIT.Shell.ShellEffect: dump :: (MonadCatch m, MonadIO m, MonadState CommandLineState m) => (CommandLineState -> TransformH CoreTC DocH) -> String -> String -> Int -> m ()
+ HERMIT.Shell.ShellEffect: dump :: FilePath -> PrettyPrinter -> String -> Int -> CommandLineState -> IO (Either CLException CommandLineState)
- HERMIT.Shell.ShellEffect: performShellEffect :: (MonadCatch m, MonadError CLException m, MonadIO m, MonadState CommandLineState m) => ShellEffect -> m ()
+ HERMIT.Shell.ShellEffect: performShellEffect :: (MonadCatch m, CLMonad m) => ShellEffect -> m ()
- HERMIT.Shell.Types: CLResume :: SAST -> CLException
+ HERMIT.Shell.Types: CLResume :: AST -> CLException
- HERMIT.Shell.Types: CLT :: ErrorT CLException (StateT CommandLineState m) a -> CLT m a
+ HERMIT.Shell.Types: CLT :: ExceptT CLException (StateT CommandLineState m) a -> CLT m a
- HERMIT.Shell.Types: CommandLineState :: PluginState -> Int -> [(ScriptName, Script)] -> Bool -> VersionStore -> PathH -> [External] -> Maybe Script -> SAST -> CommandLineState
+ HERMIT.Shell.Types: CommandLineState :: PluginState -> Int -> [(ScriptName, Script)] -> Bool -> Map AST PathStack -> Map AST [String] -> Map AST [ProofTodo] -> PathH -> [External] -> Maybe Script -> Safety -> CommandLineState
- HERMIT.Shell.Types: Diff :: SAST -> SAST -> QueryFun
+ HERMIT.Shell.Types: Diff :: AST -> AST -> QueryFun
- HERMIT.Shell.Types: Goto :: Int -> VersionCmd
+ HERMIT.Shell.Types: Goto :: AST -> VersionCmd
- HERMIT.Shell.Types: GotoTag :: String -> VersionCmd
+ HERMIT.Shell.Types: GotoTag :: TagName -> VersionCmd
- HERMIT.Shell.Types: QueryDocH :: (PrettyC -> PrettyH CoreTC -> TransformH CoreTC DocH) -> QueryFun
+ HERMIT.Shell.Types: QueryDocH :: TransformH a DocH -> QueryFun
- HERMIT.Shell.Types: QueryString :: TransformH g String -> QueryFun
+ HERMIT.Shell.Types: QueryString :: TransformH a String -> QueryFun
- HERMIT.Shell.Types: abort :: MonadError CLException m => m ()
+ HERMIT.Shell.Types: abort :: MonadError CLException m => m a
- HERMIT.Shell.Types: cl_cursor :: CommandLineState -> SAST
+ HERMIT.Shell.Types: cl_cursor :: CommandLineState -> AST
- HERMIT.Shell.Types: cl_kernel :: CommandLineState -> ScopedKernel
+ HERMIT.Shell.Types: cl_kernel :: CommandLineState -> Kernel
- HERMIT.Shell.Types: continue :: MonadError CLException m => CommandLineState -> m ()
+ HERMIT.Shell.Types: continue :: MonadError CLException m => CommandLineState -> m a
- HERMIT.Shell.Types: ppWholeProgram :: (MonadIO m, MonadState CommandLineState m) => AST -> m DocH
+ HERMIT.Shell.Types: ppWholeProgram :: (CLMonad m, MonadCatch m) => AST -> m DocH
- HERMIT.Shell.Types: resume :: MonadError CLException m => SAST -> m ()
+ HERMIT.Shell.Types: resume :: MonadError CLException m => AST -> m a
- HERMIT.Shell.Types: setCursor :: CommandLineState -> SAST -> CommandLineState
+ HERMIT.Shell.Types: setCursor :: AST -> CommandLineState -> CommandLineState
- HERMIT.Shell.Types: showWindow :: CLMonad m => m ()
+ HERMIT.Shell.Types: showWindow :: (MonadCatch m, CLMonad m) => Maybe Handle -> m ()
- HERMIT.Shell.Types: unCLT :: CLT m a -> ErrorT CLException (StateT CommandLineState m) a
+ HERMIT.Shell.Types: unCLT :: CLT m a -> ExceptT CLException (StateT CommandLineState m) a

Files

+ README.md view
@@ -0,0 +1,6 @@+# HERMIT [![Hackage version](https://img.shields.io/hackage/v/hermit.svg?style=flat)](http://hackage.haskell.org/package/hermit) [![Build Status](https://img.shields.io/travis/ku-fpg/hermit.svg?style=flat)](https://travis-ci.org/ku-fpg/hermit)++The Haskell Equational Reasoning Model-to-Implementation Tunnel.++## Links+* http://www.ittc.ku.edu/csdl/fpg/Tools/HERMIT
dist/build/HERMIT/ParserCore.hs view
@@ -1,6 +1,7 @@ {-# OPTIONS_GHC -w #-} {-# OPTIONS -fglasgow-exts -cpp #-} {-# LANGUAGE CPP #-}+{-# LANGUAGE TupleSections #-} module HERMIT.ParserCore     ( parseCore     , parseCoreExprT@@ -18,6 +19,7 @@ import Control.Arrow import Control.Monad.Reader import Data.Char (isSpace, isDigit)+import qualified Data.Map as M  import HERMIT.Context import HERMIT.External@@ -335,27 +337,35 @@  --------------------------------------------- -parseCore :: BoundVars c => CoreString -> c -> HermitM CoreExpr+parseCore :: ReadBindings c => CoreString -> c -> HermitM CoreExpr parseCore (CoreString s) c =     case lexer s of         Left msg -> fail msg-        Right tokens -> runReaderT (parser tokens) (boundVars c)+        Right tokens ->+            -- Since we are comparing occurrence names, only take the+            -- most recently defined (deepest) when variables shadow each other.+            let comb v1@(_,d1) v2@(_,d2) = if d1 > d2 then v1 else v2+                vars = mkVarSet . map fst . M.elems+                     $ M.mapKeysWith comb getOccString+                     $ M.mapWithKey (\k -> (k,) . hbDepth)+                     $ hermitBindings c+            in runReaderT (parser tokens) vars  ---------------------------------------------  -- These should probably go somewhere else.  -- | Parse a 'CoreString' to a 'CoreExpr', using the current context.-parseCoreExprT :: (BoundVars c, HasDebugChan m, HasHermitMEnv m, HasLemmas m, HasStash m, LiftCoreM m)+parseCoreExprT :: (ReadBindings c, HasDebugChan m, HasHermitMEnv m, HasLemmas m, LiftCoreM m)                => CoreString -> Transform c m a CoreExpr parseCoreExprT cs = contextonlyT $ embedHermitM . parseCore cs -parse2BeforeT :: (BoundVars c, HasDebugChan m, HasHermitMEnv m, HasLemmas m, HasStash m, LiftCoreM m)+parse2BeforeT :: (ReadBindings c, HasDebugChan m, HasHermitMEnv m, HasLemmas m, LiftCoreM m)               => (CoreExpr -> CoreExpr -> Translate c m a b)               -> CoreString -> CoreString -> Translate c m a b parse2BeforeT f s1 s2 = parseCoreExprT s1 &&& parseCoreExprT s2 >>= uncurry f -parse3BeforeT :: (BoundVars c, HasDebugChan m, HasHermitMEnv m, HasLemmas m, HasStash m, LiftCoreM m)+parse3BeforeT :: (ReadBindings c, HasDebugChan m, HasHermitMEnv m, HasLemmas m, LiftCoreM m)               => (CoreExpr -> CoreExpr -> CoreExpr -> Translate c m a b)               -> CoreString -> CoreString -> CoreString -> Translate c m a b parse3BeforeT f s1 s2 s3 = (parseCoreExprT s1 &&& parseCoreExprT s2) &&& parseCoreExprT s3 >>= (uncurry . uncurry $ f)
examples/concatVanishes/ConcatVanishes.hss view
@@ -9,7 +9,7 @@   lam-body   eta-expand 'acc   lam-body-  bash-extended-with [ push 'repH StrictRepH, forward ww-result-fusion, apply-rules ["repH ++","repH (:)","repH []"] ]+  bash-extended-with [ push 'repH StrictRepH, forward ww-result-fusion, unfold-rules-unsafe ["repH ++","repH (:)","repH []"] ]   try (bash-extended-with [push-unsafe 'work]) } one-td (unfold 'absH)
+ examples/flatten/Flatten.hec view
@@ -0,0 +1,102 @@+load-as-rewrite "WWA" "WW-Ass-A.hss"+define-rewrite "WWC" "ww-result-AssA-to-AssC WWA"+load-as-rewrite "StrictRepH" "StrictRepH.hss"++-- module main:Main where+--   flatten :: forall a . Tree a -> [a]+--   $dShow :: Show [Char]+--   main :: IO ()+--   main :: IO ()++binding-of 'flatten++-- flatten = \ * ds ->+--   case ds of wild *+--     Node l r -> (++) * (flatten * l) (flatten * r)+--     Leaf a -> (:) * a ([] *)++ww-result-split-static-arg 1 [0] [| absH |] [| repH |] WWC++-- flatten = \ * ds ->+--   (let f = \ flatten' ds ->+--          case ds of wild *+--            Node l r -> (++) * (flatten' l) (flatten' r)+--            Leaf a -> (:) * a ([] *)+--        rec work = \ x1 -> repH * (f (\ x2 -> absH * (work x2)) x1)+--    in \ x0 -> absH * (work x0)) ds++bash+{++-- flatten = \ * ->+--   let rec work = \ x1 ->+--             repH *+--                  (case x1 of wild *+--                     Node l r -> (++) * (absH * (work l)) (absH * (work r))+--                     Leaf a -> (:) * a ([] *))+--   in \ x0 -> absH * (work x0)++rhs-of 'work++-- \ x1 ->+--   repH *+--        (case x1 of wild *+--           Node l r -> (++) * (absH * (work l)) (absH * (work r))+--           Leaf a -> (:) * a ([] *))++alpha-lam 'tree++-- \ tree ->+--   repH *+--        (case tree of wild *+--           Node l r -> (++) * (absH * (work l)) (absH * (work r))+--           Leaf a -> (:) * a ([] *))++lam-body++-- repH *+--      (case tree of wild *+--         Node l r -> (++) * (absH * (work l)) (absH * (work r))+--         Leaf a -> (:) * a ([] *))++eta-expand 'acc++-- \ acc ->+--   repH *+--        (case tree of wild *+--           Node l r -> (++) * (absH * (work l)) (absH * (work r))+--           Leaf a -> (:) * a ([] *))+--        acc++lam-body++-- repH *+--      (case tree of wild *+--         Node l r -> (++) * (absH * (work l)) (absH * (work r))+--         Leaf a -> (:) * a ([] *))+--      acc++bash-extended-with [push 'repH StrictRepH,forward ww-result-fusion,unfold-rules-unsafe ["repH ++","repH (:)","repH []"]]++-- case tree of wild *+--   Node l r -> work l (work r acc)+--   Leaf a -> (:) * a acc++ }++-- flatten = \ * ->+--   let rec work = \ tree acc ->+--             case tree of wild *+--               Node l r -> work l (work r acc)+--               Leaf a -> (:) * a acc+--   in \ x0 -> absH * (work x0)++one-td (unfold 'absH)++-- flatten = \ * ->+--   let rec work = \ tree acc ->+--             case tree of wild *+--               Node l r -> work l (work r acc)+--               Leaf a -> (:) * a acc+--   in \ x0 -> work x0 ([] *)+
− examples/flatten/Flatten.hss
@@ -1,14 +0,0 @@-load-as-rewrite "WWA" "WW-Ass-A.hss"-define-rewrite "WWC" "ww-result-AssA-to-AssC WWA"-load-as-rewrite "StrictRepH" "StrictRepH.hss"-binding-of 'flatten-ww-result-split-static-arg 1 [0] [| absH |] [| repH |] WWC-bash-{ rhs-of 'work-  alpha-lam 'tree-  lam-body-  eta-expand 'acc-  lam-body-  bash-extended-with [push 'repH StrictRepH, forward ww-result-fusion, apply-rules ["repH ++", "repH (:)", "repH []"] ]-}-one-td (unfold 'absH)
+ examples/last/NewLast.hss view
@@ -0,0 +1,15 @@+flatten-module+set-pp-type Show++binding-of 'last+fix-intro+{ application-of 'fix+  split-1-beta last [| wrap |] [| unwrap |]+  -- prove the assumption+  lhs (repeat (any-call (unfold ['., 'wrap, 'unwrap])))+  both smash+  end-proof++  repeat (any-call (unfold ['g, 'wrap, 'unwrap, 'fix]))+  bash+}
+ examples/new_reverse/HList.hs view
@@ -0,0 +1,30 @@+module HList+    ( H+    , repH+    , absH+    , myAppend+    ) where++type H a = [a] -> [a]++{-# INLINABLE repH #-}+repH :: [a] -> H a+repH xs = (xs ++)++{-# INLINABLE absH #-}+absH :: H a -> [a]+absH f = f []++-- Because we can't get unfolding for +++myAppend :: [a] -> [a] -> [a]+myAppend []     ys = ys+myAppend (x:xs) ys = x : myAppend xs ys+{-# RULES "appendFix" [~] (++) = myAppend #-}++-- Algebra for repH+{-# RULES "repH []"  [~]               repH [] = id #-}+{-# RULES "repH (:)" [~] forall x xs.  repH (x:xs) = (x:) . repH xs #-}+{-# RULES "repH ++"  [~] forall xs ys. repH (xs ++ ys) = repH xs . repH ys #-}++-- Needed because the fusion rule we generate isn't too useful yet.+{-# RULES "repH-absH-fusion" [~] forall h. repH (absH h) = h #-}
+ examples/new_reverse/Reverse.hec view
@@ -0,0 +1,674 @@+flatten-module+rule-to-lemma "++ []"++-- module main:Main where+--   absR :: forall a . ([a] -> H a) -> [a] -> [a]+--   repR :: forall a . ([a] -> [a]) -> [a] -> H a+--   rev :: forall a . [a] -> [a]+--   main :: IO ()+--   main :: IO ()++prove-lemma "++ []"++-- Goal:+-- forall * xs. (++) * xs ([] *) = xs++lhs (one-td (unfold-rule appendFix))++-- Goal:+-- forall *. (++) * = myAppend *++assume -- proven appendFix++-- Goal:+-- forall * xs. myAppend * xs ([] *) = xs++induction 'xs++-- Goal:+-- forall *. myAppend * (undefined *) ([] *) = undefined *++lhs unfold++-- Goal:+-- forall *.+-- case undefined * of wild *+--   [] -> [] *+--   (:) x xs -> (:) * x (myAppend * xs ([] *))+-- =+-- undefined *++lhs undefined-expr++-- Goal:+-- forall *. undefined * = undefined *++end-case -- proven "++ []-induction-case-undefined"++-- Goal:+-- forall *. myAppend * ([] *) ([] *) = [] *++lhs unfold++-- Goal:+-- forall *.+-- case [] * of wild *+--   [] -> [] *+--   (:) x xs -> (:) * x (myAppend * xs ([] *))+-- =+-- [] *++lhs simplify++-- Goal:+-- forall *. [] * = [] *++end-case -- proven "++ []-induction-case-[]"++-- Assumed lemmas:+-- ind-hyp-0 (Assumed)+--   myAppend * b ([] *) = b+-- Goal:+-- forall * a b. myAppend * ((:) * a b) ([] *) = (:) * a b++lhs unfold++-- Assumed lemmas:+-- ind-hyp-0 (Assumed)+--   myAppend * b ([] *) = b+-- Goal:+-- forall * a b.+-- case (:) * a b of wild *+--   [] -> [] *+--   (:) x xs -> (:) * x (myAppend * xs ([] *))+-- =+-- (:) * a b++lhs simplify++-- Assumed lemmas:+-- ind-hyp-0 (Assumed)+--   myAppend * b ([] *) = b+-- Goal:+-- forall * a b. (:) * a (myAppend * b ([] *)) = (:) * a b++lhs (one-td (lemma-forward ind-hyp-0))++-- Assumed lemmas:+-- ind-hyp-0 (Assumed)+--   myAppend * b ([] *) = b+-- Goal:+-- forall * a b. (:) * a b = (:) * a b++end-case -- proven "++ []-induction-case-:"+-- proven "++ []"+rule-to-lemma "repH []"++-- module main:Main where+--   absR :: forall a . ([a] -> H a) -> [a] -> [a]+--   repR :: forall a . ([a] -> [a]) -> [a] -> H a+--   rev :: forall a . [a] -> [a]+--   main :: IO ()+--   main :: IO ()++prove-lemma "repH []"++-- Goal:+-- forall *. repH * ([] *) = id *++lhs unfold++-- Goal:+-- forall *. (++) * ([] *) = id *++extensionality++-- Goal:+-- forall * x. (++) * ([] *) x = id * x++lhs (one-td (unfold-rule appendFix))++-- Goal:+-- forall * x. myAppend * ([] *) x = id * x++lhs unfold++-- Goal:+-- forall * x.+-- case [] * of wild *+--   [] -> x+--   (:) x xs -> (:) * x (myAppend * xs x)+-- =+-- id * x++both smash++-- Goal:+-- forall * x. x = x++end-proof -- proven "repH []"+rule-to-lemma "repH (:)"++-- module main:Main where+--   absR :: forall a . ([a] -> H a) -> [a] -> [a]+--   repR :: forall a . ([a] -> [a]) -> [a] -> H a+--   rev :: forall a . [a] -> [a]+--   main :: IO ()+--   main :: IO ()++prove-lemma "repH (:)"++-- Goal:+-- forall * x xs. repH * ((:) * x xs) = (.) * * * ((:) * x) (repH * xs)++both (any-call (unfold 'repH))++-- Goal:+-- forall * x xs. (++) * ((:) * x xs) = (.) * * * ((:) * x) ((++) * xs)++both (any-call (unfold-rule appendFix))++-- Goal:+-- forall * x xs. myAppend * ((:) * x xs) = (.) * * * ((:) * x) (myAppend * xs)++rhs unfold++-- Goal:+-- forall * x xs. myAppend * ((:) * x xs) = \ x -> (:) * x (myAppend * xs x)++lhs (unfold >>> smash)++-- Goal:+-- forall * x xs. \ ys -> (:) * x (myAppend * xs ys) = \ x -> (:) * x (myAppend * xs x)++end-proof -- proven "repH (:)"+rule-to-lemma "repH ++"++-- module main:Main where+--   absR :: forall a . ([a] -> H a) -> [a] -> [a]+--   repR :: forall a . ([a] -> [a]) -> [a] -> H a+--   rev :: forall a . [a] -> [a]+--   main :: IO ()+--   main :: IO ()++prove-lemma "repH ++"++-- Goal:+-- forall * xs ys. repH * ((++) * xs ys) = (.) * * * (repH * xs) (repH * ys)++both (any-call (unfold 'repH))++-- Goal:+-- forall * xs ys. (++) * ((++) * xs ys) = (.) * * * ((++) * xs) ((++) * ys)++both (any-call (unfold-rule appendFix))++-- Goal:+-- forall * xs ys. myAppend * (myAppend * xs ys) = (.) * * * (myAppend * xs) (myAppend * ys)++lhs (eta-expand 'x)++-- Goal:+-- forall * xs ys. \ x -> myAppend * (myAppend * xs ys) x = (.) * * * (myAppend * xs) (myAppend * ys)++rhs unfold++-- Goal:+-- forall * xs ys. \ x -> myAppend * (myAppend * xs ys) x = \ x -> myAppend * xs (myAppend * ys x)++induction 'xs++-- Goal:+-- forall * ys x. myAppend * (myAppend * (undefined *) ys) x = myAppend * (undefined *) (myAppend * ys x)++both (replicate 2 (any-call (unfold 'myAppend)))++-- Goal:+-- forall * ys x.+-- case case undefined * of wild *+--        [] -> ys+--        (:) x xs -> (:) * x (myAppend * xs ys)+--  of wild *+--   [] -> x+--   (:) x xs ->+--     (:) * x+--         (case xs of wild *+--            [] -> x+--            (:) x xs -> (:) * x (myAppend * xs x))+-- =+-- case undefined * of wild *+--   [] ->+--     case ys of wild *+--       [] -> x+--       (:) x xs ->+--         (:) * x+--             (case xs of wild *+--                [] -> x+--                (:) x xs -> (:) * x (myAppend * xs x))+--   (:) x xs ->+--     (:) * x+--         (case xs of wild *+--            [] ->+--              case ys of wild *+--                [] -> x+--                (:) x xs ->+--                  (:) * x+--                      (case xs of wild *+--                         [] -> x+--                         (:) x xs -> (:) * x (myAppend * xs x))+--            (:) x xs ->+--              (:) * x+--                  (myAppend * xs+--                            (case ys of wild *+--                               [] -> x+--                               (:) x xs ->+--                                 (:) * x+--                                     (case xs of wild *+--                                        [] -> x+--                                        (:) x xs -> (:) * x (myAppend * xs x)))))++both (innermost undefined-expr)++-- Goal:+-- forall * ys x. undefined * = undefined *++end-case -- proven "repH ++-induction-case-undefined"++-- Goal:+-- forall * ys x. myAppend * (myAppend * ([] *) ys) x = myAppend * ([] *) (myAppend * ys x)++both (replicate 2 (any-call (unfold 'myAppend)))++-- Goal:+-- forall * ys x.+-- case case [] * of wild *+--        [] -> ys+--        (:) x xs -> (:) * x (myAppend * xs ys)+--  of wild *+--   [] -> x+--   (:) x xs ->+--     (:) * x+--         (case xs of wild *+--            [] -> x+--            (:) x xs -> (:) * x (myAppend * xs x))+-- =+-- case [] * of wild *+--   [] ->+--     case ys of wild *+--       [] -> x+--       (:) x xs ->+--         (:) * x+--             (case xs of wild *+--                [] -> x+--                (:) x xs -> (:) * x (myAppend * xs x))+--   (:) x xs ->+--     (:) * x+--         (case xs of wild *+--            [] ->+--              case ys of wild *+--                [] -> x+--                (:) x xs ->+--                  (:) * x+--                      (case xs of wild *+--                         [] -> x+--                         (:) x xs -> (:) * x (myAppend * xs x))+--            (:) x xs ->+--              (:) * x+--                  (myAppend * xs+--                            (case ys of wild *+--                               [] -> x+--                               (:) x xs ->+--                                 (:) * x+--                                     (case xs of wild *+--                                        [] -> x+--                                        (:) x xs -> (:) * x (myAppend * xs x)))))++both smash++-- Goal:+-- forall * ys x.+-- case ys of wild *+--   [] -> x+--   (:) x xs ->+--     (:) * x+--         (case xs of wild *+--            [] -> x+--            (:) x xs -> (:) * x (myAppend * xs x))+-- =+-- case ys of wild *+--   [] -> x+--   (:) x xs ->+--     (:) * x+--         (case xs of wild *+--            [] -> x+--            (:) x xs -> (:) * x (myAppend * xs x))++end-case -- proven "repH ++-induction-case-[]"++-- Assumed lemmas:+-- ind-hyp-0 (Assumed)+--   \ x -> myAppend * (myAppend * b ys) x = \ x -> myAppend * b (myAppend * ys x)+-- Goal:+-- forall * ys a b x. myAppend * (myAppend * ((:) * a b) ys) x = myAppend * ((:) * a b) (myAppend * ys x)++both (one-td unfold)++-- Assumed lemmas:+-- ind-hyp-0 (Assumed)+--   \ x -> myAppend * (myAppend * b ys) x = \ x -> myAppend * b (myAppend * ys x)+-- Goal:+-- forall * ys a b x.+-- case myAppend * ((:) * a b) ys of wild *+--   [] -> x+--   (:) x xs -> (:) * x (myAppend * xs x)+-- =+-- case (:) * a b of wild *+--   [] -> myAppend * ys x+--   (:) x xs -> (:) * x (myAppend * xs (myAppend * ys x))++lhs (one-td unfold)++-- Assumed lemmas:+-- ind-hyp-0 (Assumed)+--   \ x -> myAppend * (myAppend * b ys) x = \ x -> myAppend * b (myAppend * ys x)+-- Goal:+-- forall * ys a b x.+-- case case (:) * a b of wild *+--        [] -> ys+--        (:) x xs -> (:) * x (myAppend * xs ys)+--  of wild *+--   [] -> x+--   (:) x xs -> (:) * x (myAppend * xs x)+-- =+-- case (:) * a b of wild *+--   [] -> myAppend * ys x+--   (:) x xs -> (:) * x (myAppend * xs (myAppend * ys x))++both smash++-- Assumed lemmas:+-- ind-hyp-0 (Assumed)+--   \ x -> myAppend * (myAppend * b ys) x = \ x -> myAppend * b (myAppend * ys x)+-- Goal:+-- forall * ys a b x. (:) * a (myAppend * (myAppend * b ys) x) = (:) * a (myAppend * b (myAppend * ys x))++rhs (one-td (lemma-backward ind-hyp-0))++-- Assumed lemmas:+-- ind-hyp-0 (Assumed)+--   \ x -> myAppend * (myAppend * b ys) x = \ x -> myAppend * b (myAppend * ys x)+-- Goal:+-- forall * ys a b x. (:) * a (myAppend * (myAppend * b ys) x) = (:) * a (myAppend * (myAppend * b ys) x)++end-case -- proven "repH ++-induction-case-:"+-- proven "repH ++"++-- module main:Main where+--   absR :: forall a . ([a] -> H a) -> [a] -> [a]+--   repR :: forall a . ([a] -> [a]) -> [a] -> H a+--   rev :: forall a . [a] -> [a]+--   main :: IO ()+--   main :: IO ()++binding-of 'rev++-- rev = \ * ds ->+--   case ds of wild *+--     [] -> [] *+--     (:) x xs -> (++) * (rev * xs) ((:) * x ([] *))++fix-intro++-- rev = \ * ->+--   fix *+--       (\ rev ds ->+--          case ds of wild *+--            [] -> [] *+--            (:) x xs -> (++) * (rev xs) ((:) * x ([] *)))++application-of 'fix++-- fix *+--     (\ rev ds ->+--        case ds of wild *+--          [] -> [] *+--          (:) x xs -> (++) * (rev xs) ((:) * x ([] *)))++split-1-beta rev [| absR |] [| repR |]++-- Goal:+-- fix *+--     ((.) * * * (absR *)+--          ((.) * * * (repR *)+--               (\ rev ds ->+--                  case ds of wild *+--                    [] -> [] *+--                    (:) x xs -> (++) * (rev xs) ((:) * x ([] *)))))+-- =+-- fix *+--     (\ rev ds ->+--        case ds of wild *+--          [] -> [] *+--          (:) x xs -> (++) * (rev xs) ((:) * x ([] *)))++both (unfold >>> smash)++-- Goal:+-- let rec x =+--           absR *+--                (repR *+--                      (\ ds ->+--                         case ds of wild *+--                           [] -> [] *+--                           (:) x xs -> (++) * (x xs) ((:) * x ([] *))))+-- in x+-- =+-- let rec x = \ ds ->+--           case ds of wild *+--             [] -> [] *+--             (:) x xs -> (++) * (x xs) ((:) * x ([] *))+-- in x++lhs (replicate 5 ((one-td unfold) >+> smash))++-- Goal:+-- let rec x = \ x ->+--           (++) *+--                (case x of wild *+--                   [] -> [] *+--                   (:) x xs -> (++) * (x xs) ((:) * x ([] *)))+--                ([] *)+-- in x+-- =+-- let rec x = \ ds ->+--           case ds of wild *+--             [] -> [] *+--             (:) x xs -> (++) * (x xs) ((:) * x ([] *))+-- in x++lhs (one-td (lemma-forward "++ []"))++-- Goal:+-- let rec x = \ x ->+--           case x of wild *+--             [] -> [] *+--             (:) x xs -> (++) * (x xs) ((:) * x ([] *))+-- in x+-- =+-- let rec x = \ ds ->+--           case ds of wild *+--             [] -> [] *+--             (:) x xs -> (++) * (x xs) ((:) * x ([] *))+-- in x++end-proof -- proven rev-assumption++-- let g =+--       (.) * * * (repR *)+--           ((.) * * *+--                (\ rev ds ->+--                   case ds of wild *+--                     [] -> [] *+--                     (:) x xs -> (++) * (rev xs) ((:) * x ([] *)))+--                (absR *))+--     worker = fix * g+-- in absR * worker++any-call (unfold ['absR,'repR])++-- let g =+--       (.) * * * (\ eta -> (\ f -> (.) * * * (repH *) f) eta)+--           ((.) * * *+--                (\ rev ds ->+--                   case ds of wild *+--                     [] -> [] *+--                     (:) x xs -> (++) * (rev xs) ((:) * x ([] *)))+--                (\ eta -> (\ g -> (.) * * * (absH *) g) eta))+--     worker = fix * g+-- in (\ g -> (.) * * * (absH *) g) worker++repeat (any-call (unfold '.)) ; smash++-- let worker =+--       fix *+--           (\ x x ->+--              repH *+--                   (case x of wild *+--                      [] -> [] *+--                      (:) x xs -> (++) * (absH * (x xs)) ((:) * x ([] *))))+-- in \ x -> absH * (worker x)++one-td (case-float-arg-lemma repHstrict)++-- Goal:+-- forall *. repH * (undefined *) = undefined *++lhs unfold++-- Goal:+-- forall *. (++) * (undefined *) = undefined *++lhs (one-td (unfold-rule appendFix))++-- Goal:+-- forall *. myAppend * (undefined *) = undefined *++lhs unfold++-- Goal:+-- forall *.+-- \ ys ->+--   case undefined * of wild *+--     [] -> ys+--     (:) x xs -> (:) * x (myAppend * xs ys)+-- =+-- undefined *++both (innermost undefined-expr)++-- Goal:+-- forall *. undefined * = undefined *++end-proof -- proven repHstrict++-- let worker =+--       fix *+--           (\ x x ->+--              case x of wild *+--                [] -> repH * ([] *)+--                (:) x xs -> repH * ((++) * (absH * (x xs)) ((:) * x ([] *))))+-- in \ x -> absH * (worker x)++one-td (lemma-forward "repH ++")++-- let worker =+--       fix *+--           (\ x x ->+--              case x of wild *+--                [] -> repH * ([] *)+--                (:) x xs -> (.) * * * (repH * (absH * (x xs))) (repH * ((:) * x ([] *))))+-- in \ x -> absH * (worker x)++repeat (any-call (unfold '.))++-- let worker =+--       fix *+--           (\ x x ->+--              case x of wild *+--                [] -> repH * ([] *)+--                (:) x xs -> \ x -> repH * (absH * (x xs)) (repH * ((:) * x ([] *)) x))+-- in \ x -> absH * (worker x)++one-td (unfold-rule repH-absH-fusion)++-- Goal:+-- forall * h. repH * (absH * h) = h++assume -- proven repH-absH-fusion++-- let worker =+--       fix *+--           (\ x x ->+--              case x of wild *+--                [] -> repH * ([] *)+--                (:) x xs -> \ x -> x xs (repH * ((:) * x ([] *)) x))+-- in \ x -> absH * (worker x)++one-td (lemma-forward "repH (:)")++-- let worker =+--       fix *+--           (\ x x ->+--              case x of wild *+--                [] -> repH * ([] *)+--                (:) x xs -> \ x -> x xs ((.) * * * ((:) * x) (repH * ([] *)) x))+-- in \ x -> absH * (worker x)++any-td (lemma-forward "repH []")++-- let worker =+--       fix *+--           (\ x x ->+--              case x of wild *+--                [] -> id *+--                (:) x xs -> \ x -> x xs ((.) * * * ((:) * x) (id *) x))+-- in \ x -> absH * (worker x)++any-call (unfold 'fix)++-- let worker =+--       let rec x =+--                 (\ x x ->+--                    case x of wild *+--                      [] -> id *+--                      (:) x xs -> \ x -> x xs ((.) * * * ((:) * x) (id *) x)) x+--       in x+-- in \ x -> absH * (worker x)++any-call (unfold 'absH)++-- let worker =+--       let rec x =+--                 (\ x x ->+--                    case x of wild *+--                      [] -> id *+--                      (:) x xs -> \ x -> x xs ((.) * * * ((:) * x) (id *) x)) x+--       in x+-- in \ x -> worker x ([] *)++bash++-- let rec x = \ x ->+--           case x of wild *+--             [] -> \ x -> x+--             (:) x xs -> \ x -> x xs ((:) * x x)+-- in \ x -> x x ([] *)++unshadow++-- let rec x = \ x0 ->+--           case x0 of wild *+--             [] -> \ x1 -> x1+--             (:) x1 xs -> \ x2 -> x xs ((:) * x1 x2)+-- in \ x0 -> x x0 ([] *)+
+ examples/new_reverse/Reverse.hs view
@@ -0,0 +1,22 @@+module Main where++import HList+import Data.Function (fix)++{-# INLINE repR #-}+repR :: ([a] -> [a]) -> ([a] -> H a)+repR f = repH . f++{-# INLINE absR #-}+absR :: ([a] -> H a) -> ([a] -> [a])+absR g = absH . g++rev :: [a] -> [a]+rev []     = []+rev (x:xs) = rev xs ++ [x]++main :: IO ()+main = print $ rev [1..10]++-- useful auxilliary lemma for proving the w/w assumption+{-# RULES "++ []" [~] forall xs. xs ++ [] = xs #-}
+ examples/nub/Nub.hs view
@@ -0,0 +1,27 @@+module Main where++import qualified Data.Set as Set+import Data.Set (Set)++import Prelude hiding (filter) -- because we can't get unfolding for filter++filter :: (a -> Bool) -> [a] -> [a]+filter _ [] = []+filter p (x:xs) = if p x then x : filter p xs else filter p xs++nub :: [Int] -> [Int]+nub [] = []+nub (x:xs) = x : nub (filter (/= x) xs)++absN :: ([Int] -> Set Int -> [Int]) -> [Int] -> [Int]+absN h [] = []+absN h (x:xs) = x : h xs (Set.singleton x)++repN :: ([Int] -> [Int]) -> [Int] -> Set Int -> [Int]+repN h xs s = h (filter (`Set.notMember` s) xs)++main :: IO ()+main = print (nub [ x | n <- [1..1000], x <- [1..n] ])++{-# RULES "filter-fusion" [~] forall p q ys. filter p (filter q ys) = filter (\y -> p y && q y) ys #-}+{-# RULES "member-fusion" [~] forall y x s. (y /= x) && (y `Set.notMember` s) = y `Set.notMember` (Set.insert x s) #-}
+ examples/nub/Nub.hss view
@@ -0,0 +1,37 @@+set-pp-type Show++flatten-module++binding-of 'nub+fix-intro ; def-rhs+split-2-beta nub [| absN |] [| repN |] ; assume++-- this bit to essentially undo the fix-intro+{ application-of 'repN ; app-arg ; let-intro 'nub ; one-td (unfold 'fix) ; simplify }+innermost let-float+alpha-let ['nub'] -- rename x to nub'++-- back to the derivation+binding-of 'worker+one-td (unfold 'repN)+remember origworker+one-td (unfold 'filter)+one-td (case-float-arg-lemma nubStrict)++-- prove strictness condition+lhs (unfold >>> undefined-expr)+end-proof++one-td (unfold 'nub')+simplify++one-td (case-float-arg-lemma nubStrict)+{ consider case ; consider case ; case-alt 1 ; alt-rhs+  unfold ; simplify+  one-td (unfold-rule "filter-fusion") ; assume+  simplify+  one-td (unfold-rule "member-fusion") ; assume+}+nonrec-to-rec+any-td (fold-remembered origworker)+
examples/qsort/HList.hs view
@@ -22,3 +22,6 @@ {-# 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     #-}++-- Needed because the fusion rule we generate isn't too useful yet.+{-# RULES "repH-absH-fusion" [~] forall h. repH (absH h) = h #-}
examples/qsort/QSort.hs view
@@ -7,6 +7,14 @@  data Tree a = Node (Tree a) (Tree a) | Leaf a +{-# INLINE repR #-}+repR :: ([a] -> [a]) -> ([a] -> H a)+repR f = repH . f++{-# INLINE absR #-}+absR :: ([a] -> H a) -> ([a] -> [a])+absR g = absH . g+ qsort :: Ord a => [a] -> [a] qsort []     = [] qsort (a:as) = qsort bs ++ [a] ++ qsort cs
examples/qsort/QSort.hss view
@@ -1,15 +1,25 @@-load-as-rewrite "WWA" "WW-Ass-A.hss"-define-rewrite "WWC" "ww-result-AssA-to-AssC WWA"-load-as-rewrite "StrictRepH" "StrictRepH.hss"+flatten-module binding-of 'qsort-ww-result-split-static-arg 2 [0] [| absH |] [| repH |] WWC-bash-{ rhs-of 'work-  alpha-lam 'xs-  lam-body-  eta-expand 'acc-  lam-body-  bash-extended-with [push 'repH StrictRepH, forward ww-result-fusion, apply-rules ["repH ++", "repH (:)", "repH []"] ]-  bash-extended-with [push-unsafe 'work]+static-arg+{+    binding-of 'qsort'+    fix-intro+    def-rhs+    split-1-beta qsort [|absR|] [|repR|] ; assume+    rhs-of 'worker+    repeat (any-call (unfold ['.,'fix,'g,'repR,'absR]))+    simplify+    one-td (case-float-arg-lemma repHstrict) ; assume+    innermost let-float+    any-td (unfold-rule "repH ++") ; assume+    any-call (unfold-rule repH-absH-fusion) ; assume+    unshadow+    any-td (inline 'ds1)+    simplify+    alpha-let [worker]+    repeat (any-call (unfold-rules ["repH (:)","repH []"]))+    assume ; assume }-one-td (unfold 'absH)+repeat (any-call (unfold ['.,'absR, 'absH]))+innermost let-float+bash
examples/reverse/Reverse.hss view
@@ -9,6 +9,6 @@   lam-body   eta-expand 'acc   lam-body-  bash-extended-with [push 'repH StrictRepH, forward ww-result-fusion, apply-rules ["repH ++", "repH (:)", "repH []"] ]+  bash-extended-with [push 'repH StrictRepH, forward ww-result-fusion, unfold-rules-unsafe ["repH ++", "repH (:)", "repH []"] ] } one-td (unfold 'absH)
hermit.cabal view
@@ -1,22 +1,9 @@ Name:                hermit-Version:             0.6.0.0+Version:             0.7.0.0 Synopsis:            Haskell Equational Reasoning Model-to-Implementation Tunnel Description:-  HERMIT uses Haskell to express semi-formal models,-  efficient implementations, and provide a bridging DSL-  to describe via stepwise refinement the connection between-  these models and implementations. The key transformation-  in the bridging DSL is the worker/wrapper transformation.-  .-  This is an alpha `please give feedback' release.-  Shortcomings/gotchas include:-  .-    * Command line completion is ad hoc at the moment.-  .-    * log command prints linearly, even if command history is a tree.-  .-    * A number of rewrites don't enforce preconditions. eg: cast elimination-      always works, even if the cast is necessary+  HERMIT is a Haskell-specific toolkit designed to mechanize+  equational reasoning and program transformation during compilation in GHC.   .   Examples can be found in the examples sub-directory.   .@@ -28,12 +15,12 @@   .   @    $ hermit Reverse.hs Reverse.hss resume-   [starting HERMIT v0.6.0.0 on Reverse.hs]+   [starting HERMIT v0.7.0.0 on Reverse.hs]    % ghc Reverse.hs -fforce-recomp -O2 -dcore-lint -fexpose-all-unfoldings -fsimple-list-literals -fplugin=HERMIT -fplugin-opt=HERMIT:Main:Reverse.hss -fplugin-opt=HERMIT:Main:resume    [1 of 2] Compiling HList            ( HList.hs, HList.o )    Loading package ghc-prim ... linking ... done.    ...-   Loading package hermit-0.6.0.0 ... linking ... done.+   Loading package hermit-0.7.0.0 ... linking ... done.    [2 of 2] Compiling Main             ( Reverse.hs, Reverse.o )    Linking Reverse ...    $ ./Reverse@@ -44,12 +31,12 @@   .   @    $ hermit Reverse.hs-   [starting HERMIT v0.6.0.0 on Reverse.hs]+   [starting HERMIT v0.7.0.0 on Reverse.hs]    % ghc Reverse.hs -fforce-recomp -O2 -dcore-lint -fexpose-all-unfoldings -fsimple-list-literals -fplugin=HERMIT -fplugin-opt=HERMIT:*:    [1 of 2] Compiling HList            ( HList.hs, HList.o )    Loading package ghc-prim ... linking ... done.    ...-   Loading package hermit-0.6.0.0 ... linking ... done.+   Loading package hermit-0.7.0.0 ... linking ... done.    [2 of 2] Compiling Main             ( Reverse.hs, Reverse.o )    ===================== Welcome to HERMIT =====================    HERMIT is a toolkit for the interactive transformation of GHC@@ -95,12 +82,13 @@ License:             BSD3 License-file:        LICENSE Author:              Andrew Farmer, Andy Gill, Ed Komp, Neil Sculthorpe-Maintainer:          Andy Gill <andygill@ku.edu>-Stability:           alpha+Maintainer:          Andrew Farmer <afarmer@ittc.ku.edu>+Stability:           beta build-type:          Simple Cabal-Version:       >= 1.14  extra-source-files:+    README.md     examples/concatVanishes/ConcatVanishes.hss     examples/concatVanishes/Flatten.hs     examples/concatVanishes/Flatten.hss@@ -121,38 +109,45 @@     examples/fib-tuple/Fib.hss     examples/flatten/HList.hs     examples/flatten/Flatten.hs-    examples/flatten/Flatten.hss+    examples/flatten/Flatten.hec     examples/hanoi/Hanoi.hs     examples/hanoi/Hanoi.hss     examples/last/Last.hs     examples/last/Last.hss+    examples/last/NewLast.hss     examples/mean/Mean.hs     examples/mean/Mean.hss+    examples/nub/Nub.hs+    examples/nub/Nub.hss     examples/qsort/HList.hs     examples/qsort/QSort.hs     examples/qsort/QSort.hss     examples/reverse/HList.hs     examples/reverse/Reverse.hs     examples/reverse/Reverse.hss+    examples/new_reverse/HList.hs+    examples/new_reverse/Reverse.hs+    examples/new_reverse/Reverse.hec  Library   ghc-options: -Wall -fno-warn-orphans-  Build-Depends: base >= 4 && < 5,-                 ansi-terminal >= 0.5.5,+  Build-Depends: base                >= 4 && < 5,+                 ansi-terminal       >= 0.5.5,                  array,-                 containers >= 0.5.0.0,-                 data-default >= 0.5.0,-                 directory >= 1.2.0.0,-                 ghc >= 7.8,-                 haskeline >= 0.7.0.3,-                 kure >= 2.16.4,-                 marked-pretty >= 0.1,-                 mtl >= 2.1.2,-                 operational >= 0.2.2.1,-                 process >= 1.1.0.2,-                 stm >= 2.4,-                 temporary >= 1.2.0.3,-                 transformers+                 containers          >= 0.5.0.0,+                 data-default-class  >= 0.0.1,+                 directory           >= 1.2.0.0,+                 ghc                 >= 7.8,+                 haskeline           >= 0.7.0.3,+                 kure                >= 2.16.8,+                 marked-pretty       >= 0.1,+                 mtl                 >= 2.1.2,+                 operational         >= 0.2.2.1,+                 process             >= 1.1.0.2,+                 stm                 >= 2.4,+                 temporary           >= 1.2.0.3,+                 transformers        >= 0.2,+                 transformers-compat >= 0.4    if os(windows)     build-depends: Win32@@ -193,6 +188,7 @@        HERMIT.Dictionary.New        HERMIT.Dictionary.Query        HERMIT.Dictionary.Reasoning+       HERMIT.Dictionary.Remembered        HERMIT.Dictionary.Rules        HERMIT.Dictionary.Undefined        HERMIT.Dictionary.Unfold@@ -205,9 +201,9 @@        HERMIT.GHC        HERMIT.GHC.Typechecker        HERMIT.Kernel-       HERMIT.Kernel.Scoped        HERMIT.Kure-       HERMIT.Kure.SumTypes+       HERMIT.Kure.Universes+       HERMIT.Lemma        HERMIT.Monad        HERMIT.Name        HERMIT.Parser@@ -237,6 +233,8 @@        HERMIT.Shell.Types         HERMIT.Utilities++       HERMIT.Libraries.Int    Other-modules:        HERMIT.Syntax
src/HERMIT/Context.hs view
@@ -35,6 +35,7 @@        , lookupHermitBinding        , lookupHermitBindingDepth        , lookupHermitBindingSite+       , inScope          -- ** Accessing GHC rewrite rules from the context        , HasCoreRules(..)          -- ** An empty Context@@ -59,7 +60,6 @@ -- | The depth of a binding.  Used, for example, to detect shadowing when inlining. type BindingDepth = Int - -- | HERMIT\'s representation of variable bindings. --   Bound expressions cannot be inlined without checking for shadowing issues (using the depth information). data HermitBindingSite = LAM                                -- ^ A lambda-bound variable.@@ -190,6 +190,11 @@ -- | Determine if a variable is bound in a context. boundIn :: ReadBindings c => Var -> c -> Bool boundIn i c = i `member` hermitBindings c++-- | Determine whether a variable is in scope.+inScope :: BoundVars c => c -> Var -> Bool+inScope c v = not (isDeadBinder v || (isLocalVar v && (v `notElemVarSet` boundVars c)))+-- Used in Dictionary.Inline and Dictionary.Fold to check if variables are in scope.  -- | Lookup the binding for a variable in a context. lookupHermitBinding :: (ReadBindings c, Monad m) => Var -> c -> m HermitBinding
src/HERMIT/Core.hs view
@@ -1,79 +1,81 @@ {-# LANGUAGE CPP, LambdaCase #-} module HERMIT.Core-          (-          -- * Generic Data Type-            CoreProg(..)-          , CoreDef(..)-          , CoreTickish-          -- * Equality-          -- | We define both syntactic equality and alpha equality.+    ( -- * Generic Data Type+      CoreProg(..)+    , CoreDef(..)+    , CoreTickish+      -- * Equality+      -- | We define both syntactic equality and alpha equality. -          -- ** Syntactic Equality-          , progSyntaxEq-          , bindSyntaxEq-          , defSyntaxEq-          , exprSyntaxEq-          , altSyntaxEq-          , typeSyntaxEq-          , coercionSyntaxEq+      -- ** Syntactic Equality+    , progSyntaxEq+    , bindSyntaxEq+    , defSyntaxEq+    , exprSyntaxEq+    , altSyntaxEq+    , typeSyntaxEq+    , coercionSyntaxEq -          -- ** Alpha Equality-          , progAlphaEq-          , bindAlphaEq-          , defAlphaEq-          , exprAlphaEq-          , altAlphaEq-          , typeAlphaEq-          , coercionAlphaEq+      -- ** Alpha Equality+    , progAlphaEq+    , bindAlphaEq+    , defAlphaEq+    , exprAlphaEq+    , altAlphaEq+    , typeAlphaEq+    , coercionAlphaEq -          -- * Conversions to/from 'Core'-          , defsToRecBind-          , defToIdExpr-          , progToBinds-          , bindsToProg-          , bindToVarExprs+      -- * Conversions to/from 'Core'+    , defsToRecBind+    , defToIdExpr+    , progToBinds+    , bindsToProg+    , bindToVarExprs -          -- * Collecting variable bindings-          , progIds-          , bindVars-          , defId-          , altVars+      -- * Collecting variable bindings+    , progIds+    , bindVars+    , defId+    , altVars -          -- * Collecting free variables-          -- $freeVarsNote-          , freeVarsProg-          , freeVarsBind-          , freeVarsDef-          , freeVarsExpr-          , freeVarsAlt-          , freeVarsVar-          , localFreeVarsAlt-          , freeVarsType-          , freeVarsCoercion-          , localFreeVarsExpr-          , freeIdsExpr-          , localFreeIdsExpr+      -- * Collecting free variables+      -- $freeVarsNote+    , freeVarsProg+    , freeVarsBind+    , freeVarsDef+    , freeVarsExpr+    , freeVarsAlt+    , freeVarsVar+    , localFreeVarsAlt+    , freeVarsType+    , freeVarsCoercion+    , localFreeVarsExpr+    , freeIdsExpr+    , localFreeIdsExpr -          -- * Utilities-          , isCoArg-          , exprKindOrType-          , exprTypeM-          , endoFunTypeM-          , splitTyConAppM-          , splitFunTypeM-          , endoFunExprTypeM-          , funExprArgResTypesM-          , funExprsWithInverseTypes-          , appCount-          , mapAlts+      -- * Utilities+    , isCoArg+    , exprKindOrType+    , exprTypeM+    , endoFunTypeM+    , splitTyConAppM+    , splitFunTypeM+    , endoFunExprTypeM+    , funExprArgResTypesM+    , funExprsWithInverseTypes+    , appCount+    , mapAlts+    , substCoreAlt+    , substCoreExpr+    , betaReduceAll+    , mkDataConApp -          -- * Crumbs-          , Crumb(..)-          , showCrumbs---          , crumbToDeprecatedInt-          , deprecatedLeftSibling-          , deprecatedRightSibling-) where+      -- * Crumbs+    , Crumb(..)+    , showCrumbs+    , leftSibling+    , rightSibling+    ) where  import Control.Monad ((>=>)) @@ -277,24 +279,39 @@ -- The GHC Function exprFreeVars defined in "CoreFVs" only returns *locally-defined* free variables. -- In HERMIT, this is typically not what we want, so we define our own functions. -- We reuse some of the functionality in "CoreFVs", but alas much of it is not exposed, so we have to reimplement some of it.---- | Find all free variables in an expression.-freeVarsExpr :: CoreExpr -> VarSet-freeVarsExpr = exprSomeFreeVars (const True)+-- We do not use GHC's exprSomeFreeVars because it does not return the full set of free vars for a Var.+-- It only returns the Var itself, rather than extendVarSet (freeVarsVar v) v like it should.  -- | Find all free identifiers in an expression. freeIdsExpr :: CoreExpr -> IdSet-freeIdsExpr = exprSomeFreeVars isId+freeIdsExpr = filterVarSet isId . freeVarsExpr  -- | Find all locally defined free variables in an expression. localFreeVarsExpr :: CoreExpr -> VarSet-localFreeVarsExpr = exprSomeFreeVars isLocalVar+localFreeVarsExpr = filterVarSet isLocalVar . freeVarsExpr  -- | Find all locally defined free identifiers in an expression. localFreeIdsExpr :: CoreExpr -> VarSet-localFreeIdsExpr = exprSomeFreeVars isLocalId+localFreeIdsExpr = filterVarSet isLocalId . freeVarsExpr +-- | Find all free variables in an expression.+freeVarsExpr :: CoreExpr -> VarSet+freeVarsExpr (Var v) = extendVarSet (freeVarsVar v) v+freeVarsExpr (Lit {}) = emptyVarSet+freeVarsExpr (App e1 e2) = freeVarsExpr e1 `unionVarSet` freeVarsExpr e2+freeVarsExpr (Lam b e) = delVarSet (freeVarsExpr e) b+freeVarsExpr (Let b e) = freeVarsBind b `unionVarSet` delVarSetList (freeVarsExpr e) (bindersOf b)+freeVarsExpr (Case s b ty alts) = let altFVs = delVarSet (unionVarSets $ map freeVarsAlt alts) b+                                  in unionVarSets [freeVarsExpr s, freeVarsType ty, altFVs]+freeVarsExpr (Cast e co) = freeVarsExpr e `unionVarSet` freeVarsCoercion co+freeVarsExpr (Tick t e) = freeVarsTick t `unionVarSet` freeVarsExpr e+freeVarsExpr (Type ty) = freeVarsType ty+freeVarsExpr (Coercion co) = freeVarsCoercion co +freeVarsTick :: Tickish Id -> VarSet+freeVarsTick (Breakpoint _ ids) = mkVarSet ids+freeVarsTick _ = emptyVarSet+ -- | Find all free identifiers in a binding group, which excludes any variables bound in the group. freeVarsBind :: CoreBind -> VarSet freeVarsBind (NonRec v e) = freeVarsExpr e `unionVarSet` freeVarsVar v@@ -448,10 +465,14 @@            | NthCo_Int | NthCo_Co            | InstCo_Co | InstCo_Type            | LRCo_LR | LRCo_Co+           -- Quantified+           | Forall_Body+           | Conj_Lhs | Conj_Rhs+           | Disj_Lhs | Disj_Rhs+           | Impl_Lhs | Impl_Rhs+           | Eq_Lhs | Eq_Rhs            deriving (Eq,Read,Show)-           -- TODO: Write a prettier Show instance - showCrumbs :: [Crumb] -> String showCrumbs crs = "[" ++ intercalate ", " (map showCrumb crs) ++ "]" @@ -501,65 +522,70 @@                InstCo_Co         -> "inst-co"                InstCo_Type       -> "inst-type"                LRCo_Co           -> "lr-co"--               _              -> "Warning: Crumb should not be in use!  This is probably Neil's fault."+               -- Quantified+               Forall_Body -> "forall-body"+               Conj_Lhs    -> "conj-lhs"+               Conj_Rhs    -> "conj-rhs"+               Disj_Lhs    -> "disj-lhs"+               Disj_Rhs    -> "disj-rhs"+               Impl_Lhs    -> "antecedent"+               Impl_Rhs    -> "consequent"+               Eq_Lhs      -> "eq-lhs"+               Eq_Rhs      -> "eq-rhs"+               _ -> "Warning: Crumb should not be in use!  This is probably Neil's fault." -{---- | Earlier versions of HERMIT used 'Int' as the crumb type.---   This function maps a 'Crumb' back to that corresponding 'Int', for backwards compatibility purposes.-crumbToDeprecatedInt :: Crumb -> Maybe Int-crumbToDeprecatedInt = \case-                          ModGuts_Prog   -> Just 0-                          ProgCons_Bind  -> Just 0-                          ProgCons_Tail  -> Just 1-                          NonRec_RHS     -> Just 0-                          NonRec_Var     -> Nothing-                          Rec_Def n      -> Just n-                          Def_Id         -> Nothing-                          Def_RHS        -> Just 0-                          App_Fun        -> Just 0-                          App_Arg        -> Just 1-                          Lam_Var        -> Nothing-                          Lam_Body       -> Just 0-                          Let_Bind       -> Just 0-                          Let_Body       -> Just 1-                          Case_Scrutinee -> Just 0-                          Case_Binder    -> Nothing-                          Case_Type      -> Nothing-                          Case_Alt n     -> Just (n + 1)-                          Cast_Expr      -> Just 0-                          Cast_Co        -> Nothing-                          Tick_Tick      -> Nothing-                          Tick_Expr      -> Just 0-                          Type_Type      -> Nothing-                          Co_Co          -> Nothing-                          Alt_Con        -> Nothing-                          Alt_Var _      -> Nothing-                          Alt_RHS        -> Just 0--} -- | Converts a 'Crumb' into the 'Crumb' pointing to its left-sibling, if a such a 'Crumb' exists.---   This is for backwards compatibility purposes with the old Int representation.-deprecatedLeftSibling :: Crumb -> Maybe Crumb-deprecatedLeftSibling = \case-                           ProgCons_Tail       -> Just ProgCons_Head-                           Rec_Def n | n > 0   -> Just (Rec_Def (n-1))-                           App_Arg             -> Just App_Fun-                           Let_Body            -> Just Let_Bind-                           Case_Alt n | n == 0 -> Just Case_Scrutinee-                                      | n >  0 -> Just (Case_Alt (n-1))-                           _                   -> Nothing+--   This is used for moving 'left' in the shell.+leftSibling :: Crumb -> Maybe Crumb+leftSibling = \case+                   ProgCons_Tail       -> Just ProgCons_Head+                   Rec_Def n | n > 0   -> Just (Rec_Def (n-1))+                   App_Arg             -> Just App_Fun+                   Let_Body            -> Just Let_Bind+                   Case_Alt n | n == 0 -> Just Case_Scrutinee+                              | n >  0 -> Just (Case_Alt (n-1))+                   _                   -> Nothing  -- | Converts a 'Crumb' into the 'Crumb' pointing to its right-sibling, if a such a 'Crumb' exists.---   This is for backwards compatibility purposes with the old Int representation.-deprecatedRightSibling :: Crumb -> Maybe Crumb-deprecatedRightSibling = \case-                           ProgCons_Head       -> Just ProgCons_Tail-                           Rec_Def n           -> Just (Rec_Def (n+1))-                           App_Fun             -> Just App_Arg-                           Let_Bind            -> Just Let_Body-                           Case_Scrutinee      -> Just (Case_Alt 0)-                           Case_Alt n          -> Just (Case_Alt (n+1))-                           _                   -> Nothing-+--   This is used for moving 'right' in the shell.+rightSibling :: Crumb -> Maybe Crumb+rightSibling = \case+                   ProgCons_Head       -> Just ProgCons_Tail+                   Rec_Def n           -> Just (Rec_Def (n+1))+                   App_Fun             -> Just App_Arg+                   Let_Bind            -> Just Let_Body+                   Case_Scrutinee      -> Just (Case_Alt 0)+                   Case_Alt n          -> Just (Case_Alt (n+1))+                   _                   -> Nothing  -----------------------------------------------------------------------++-- | Substitute all occurrences of a variable with an expression, in an expression.+substCoreExpr :: Var -> CoreExpr -> (CoreExpr -> CoreExpr)+substCoreExpr v e expr = substExpr (text "substCoreExpr") (extendSubst emptySub v e) expr+    where emptySub = mkEmptySubst (mkInScopeSet (localFreeVarsExpr (Let (NonRec v e) expr)))++-- | Substitute all occurrences of a variable with an expression, in a case alternative.+substCoreAlt :: Var -> CoreExpr -> CoreAlt -> CoreAlt+substCoreAlt v e alt = let (con, vs, rhs) = alt+                           inS            = (flip delVarSet v . unionVarSet (localFreeVarsExpr e) . localFreeVarsAlt) alt+                           subst          = extendSubst (mkEmptySubst (mkInScopeSet inS)) v e+                           (subst', vs')  = substBndrs subst vs+                        in (con, vs', substExpr (text "alt-rhs") subst' rhs)++-- | Beta-reduce as many lambda-binders as possible.+betaReduceAll :: CoreExpr -> [CoreExpr] -> (CoreExpr, [CoreExpr])+betaReduceAll (Lam v body) (a:as) = betaReduceAll (substCoreExpr v a body) as+betaReduceAll e            as     = (e,as)++-- | Build a constructor application.+--   Accepts a list of types to which the type constructor is instantiated. Ex.+--+-- > data T a b = C a b Int+--+-- Pseudocode:+--+-- > mkDataConApp [a',b'] C [x,y,z] ==> C a' b' (x::a') (y::b') (z::Int) :: T a' b'+--+mkDataConApp :: [Type] -> DataCon -> [Var] -> CoreExpr+mkDataConApp tys dc vs = mkCoreConApps dc (map Type tys ++ map (varToCoreExpr . zapVarOccInfo) vs)
src/HERMIT/Dictionary.hs view
@@ -16,6 +16,7 @@     , module HERMIT.Dictionary.New     , module HERMIT.Dictionary.Query     , module HERMIT.Dictionary.Reasoning+    , module HERMIT.Dictionary.Remembered     , module HERMIT.Dictionary.Rules     , module HERMIT.Dictionary.Undefined     , module HERMIT.Dictionary.Unfold@@ -57,6 +58,8 @@ import qualified HERMIT.Dictionary.Query as Query import           HERMIT.Dictionary.Reasoning hiding (externals) import qualified HERMIT.Dictionary.Reasoning as Reasoning+import           HERMIT.Dictionary.Remembered hiding (externals)+import qualified HERMIT.Dictionary.Remembered as Remembered import           HERMIT.Dictionary.Rules hiding (externals) import qualified HERMIT.Dictionary.Rules as Rules import           HERMIT.Dictionary.Undefined hiding (externals)@@ -71,7 +74,12 @@ import qualified HERMIT.Dictionary.WorkerWrapper.Fix as WorkerWrapperFix import           HERMIT.Dictionary.WorkerWrapper.FixResult hiding (externals) import qualified HERMIT.Dictionary.WorkerWrapper.FixResult as WorkerWrapperFixResult+-------------------------------------------------------------------------- +import qualified HERMIT.PrettyPrinter.AST as AST+import qualified HERMIT.PrettyPrinter.Clean as Clean+import qualified HERMIT.PrettyPrinter.GHC as GHCPP+ --------------------------------------------------------------------------  -- | List of all 'External's provided by HERMIT.@@ -91,6 +99,7 @@     ++ New.externals     ++ Query.externals     ++ Reasoning.externals+    ++ Remembered.externals     ++ Rules.externals     ++ Undefined.externals     ++ Unfold.externals@@ -98,5 +107,8 @@     ++ WorkerWrapperCommon.externals     ++ WorkerWrapperFix.externals     ++ WorkerWrapperFixResult.externals+    ++ AST.externals+    ++ Clean.externals+    ++ GHCPP.externals  --------------------------------------------------------------------------
src/HERMIT/Dictionary/AlphaConversion.hs view
@@ -54,33 +54,33 @@ -- | Externals for alpha-renaming. externals :: [External] externals = map (.+ Deep)-         [  external "alpha" (alphaR :: RewriteH Core)+         [  external "alpha" (promoteCoreR alphaR :: RewriteH LCore)                [ "Renames the bound variables at the current node."]-         ,  external "alpha-lam" (promoteExprR . alphaLamR . Just :: String -> RewriteH Core)+         ,  external "alpha-lam" (promoteExprR . alphaLamR . Just :: String -> RewriteH LCore)                [ "Renames the bound variable in a Lambda expression to the given name."]-         ,  external "alpha-lam" (promoteExprR  (alphaLamR Nothing) :: RewriteH Core)+         ,  external "alpha-lam" (promoteExprR  (alphaLamR Nothing) :: RewriteH LCore)                [ "Renames the bound variable in a Lambda expression."]-         ,  external "alpha-case-binder" (promoteExprR . alphaCaseBinderR . Just :: String -> RewriteH Core)+         ,  external "alpha-case-binder" (promoteExprR . alphaCaseBinderR . Just :: String -> RewriteH LCore)                [ "Renames the binder in a Case expression to the given name."]-         ,  external "alpha-case-binder" (promoteExprR (alphaCaseBinderR Nothing) :: RewriteH Core)+         ,  external "alpha-case-binder" (promoteExprR (alphaCaseBinderR Nothing) :: RewriteH LCore)                [ "Renames the binder in a Case expression."]-         ,  external "alpha-alt" (promoteAltR alphaAltR :: RewriteH Core)+         ,  external "alpha-alt" (promoteAltR alphaAltR :: RewriteH LCore)                [ "Renames all binders in a Case alternative."]-         ,  external "alpha-alt" (promoteAltR . alphaAltWithR :: [String] -> RewriteH Core)+         ,  external "alpha-alt" (promoteAltR . alphaAltWithR :: [String] -> RewriteH LCore)                [ "Renames all binders in a Case alternative using the user-provided list of new names."]-         ,  external "alpha-case" (promoteExprR alphaCaseR :: RewriteH Core)+         ,  external "alpha-case" (promoteExprR alphaCaseR :: RewriteH LCore)                [ "Renames all binders in a Case alternative."]-         ,  external "alpha-let" (promoteExprR . alphaLetWithR :: [String] -> RewriteH Core)+         ,  external "alpha-let" (promoteExprR . alphaLetWithR :: [String] -> RewriteH LCore)                [ "Renames the bound variables in a Let expression using a list of suggested names."]-         ,  external "alpha-let" (promoteExprR alphaLetR :: RewriteH Core)+         ,  external "alpha-let" (promoteExprR alphaLetR :: RewriteH LCore)                [ "Renames the bound variables in a Let expression."]-         ,  external "alpha-top" (promoteProgR . alphaProgConsWithR :: [String] -> RewriteH Core)+         ,  external "alpha-top" (promoteProgR . alphaProgConsWithR :: [String] -> RewriteH LCore)                [ "Renames the bound identifiers in the top-level binding group at the head of the program using a list of suggested names."]-         ,  external "alpha-top" (promoteProgR alphaProgConsR :: RewriteH Core)+         ,  external "alpha-top" (promoteProgR alphaProgConsR :: RewriteH LCore)                [ "Renames the bound identifiers in the top-level binding at the head of the program."]-         ,  external "alpha-prog" (promoteProgR alphaProgR :: RewriteH Core)+         ,  external "alpha-prog" (promoteProgR alphaProgR :: RewriteH LCore)                [ "Rename all top-level identifiers in the program."]-         ,  external "unshadow" (unshadowR :: RewriteH Core)+         ,  external "unshadow" (promoteCoreR unshadowR :: RewriteH LCore)                 [ "Rename local variables with manifestly unique names (x, x0, x1, ...)."]          ] @@ -99,7 +99,8 @@  -- | Collect all visible variables (in the expression or the context). visibleVarsT :: (BoundVars c, Monad m) => Transform c m CoreTC VarSet-visibleVarsT = liftM2 unionVarSet boundVarsT (arr freeVarsCoreTC)+visibleVarsT = -- TODO: implement freeVarsLCoreTC+               liftM2 unionVarSet boundVarsT (promoteT $ arr freeVarsCoreTC)  -- | If a name is provided, use that as the name of the new variable. --   Otherwise modify the variable name making sure to /not/ clash with the given variables or any visible variables.@@ -403,6 +404,8 @@ --       Though really, we first need to improve KURE to have a version of (<+) that maintains the existing error message in the case of non-matching constructors henceforth.  -- TODO 2: Also, we should be able to rename inside types and coercions.++-- TODO 3: Also, we should be able to rename lemma quantifiers  ----------------------------------------------------------------------- 
src/HERMIT/Dictionary/Common.hs view
@@ -36,7 +36,6 @@     , varBindingDepthT     , varIsOccurrenceOfT     , exprIsOccurrenceOfT-    , inScope     , withVarsInScope       -- Miscellaneous     , wrongExprForm@@ -91,9 +90,9 @@  -- | Succeeds if we are looking at a fully saturated function call. callSaturatedT :: Monad m => Transform c m CoreExpr (CoreExpr, [CoreExpr])-callSaturatedT = callPredT (\ i args -> idArity i == length args)--- TODO: probably better to calculate arity based on Id's type, as---       idArity is conservatively set to zero by default.+callSaturatedT = callPredT (\ i args -> let (tvs, ty) = splitForAllTys (varType i)+                                            (bs,_) = splitFunTys ty+                                        in (length tvs + length bs) == length args)  -- | Succeeds if we are looking at an application of given function callNameG :: MonadCatch m => HermitName -> Transform c m CoreExpr ()@@ -213,19 +212,6 @@ findTypeT :: (BoundVars c, HasHermitMEnv m, HasHscEnv m, MonadCatch m, MonadIO m, MonadThings m)           => HermitName -> Transform c m a Type findTypeT nm = prefixFailMsg ("Cannot resolve name " ++ show nm ++ ", ") $ contextonlyT (findType nm)---- TODO: "inScope" was defined elsewhere, but I've moved it here.  Should it be combined with the above functions?--- Used in Dictionary.Inline to check if variables an in scope.--- Used in Dictionary.Fold---- | Determine whether a variable is in scope.-inScope :: ReadBindings c => c -> Var -> Bool-inScope c v = (v `boundIn` c) ||                 -- defined in this module-              (isId v &&                         -- idInfo panics on TyVars-               case unfoldingInfo (idInfo v) of-                CoreUnfolding {} -> True         -- defined elsewhere-                DFunUnfolding {} -> True-                _                -> False)  -- | Modify transformation to apply to current expression as if it were the body of a lambda binding the given variables. withVarsInScope :: (AddBindings c, ReadPath c Crumb) => [Var] -> Transform c m a b -> Transform c m a b
src/HERMIT/Dictionary/Composite.hs view
@@ -14,6 +14,7 @@     ) where  import Control.Arrow+import Control.Monad  import Data.String (fromString) @@ -25,6 +26,7 @@ import HERMIT.Monad import HERMIT.Name +import HERMIT.Dictionary.Common import HERMIT.Dictionary.Debug hiding (externals) import HERMIT.Dictionary.GHC hiding (externals) import HERMIT.Dictionary.Inline hiding (externals)@@ -35,24 +37,24 @@  externals ::  [External] externals =-    [ external "unfold-basic-combinator" (promoteExprR unfoldBasicCombinatorR :: RewriteH Core)+    [ external "unfold-basic-combinator" (promoteExprR unfoldBasicCombinatorR :: RewriteH LCore)         [ "Unfold the current expression if it is one of the basic combinators:"         , "($), (.), id, flip, const, fst, snd, curry, and uncurry." ]-    , external "simplify" (simplifyR :: RewriteH Core)+    , external "simplify" (simplifyR :: RewriteH LCore)         [ "innermost (unfold-basic-combinator <+ beta-reduce-plus <+ safe-let-subst <+ case-reduce <+ let-elim)" ]-    , external "bash" (bashR :: RewriteH Core)+    , external "bash" (bashR :: RewriteH LCore)         bashHelp .+ Eval .+ Deep .+ Loop-    , external "smash" (smashR :: RewriteH Core)+    , external "smash" (smashR :: RewriteH LCore)         smashHelp .+ Eval .+ Deep .+ Loop .+ Experiment-    , external "bash-extended-with" (bashExtendedWithR :: [RewriteH Core] -> RewriteH Core)+    , external "bash-extended-with" (bashExtendedWithR :: [RewriteH LCore] -> RewriteH LCore)         [ "Run \"bash\" extended with additional rewrites.",           "Note: be sure that the new rewrite either fails or makes progress, else this may loop."         ] .+ Eval .+ Deep .+ Loop-    , external "smash-extended-with" (smashExtendedWithR :: [RewriteH Core] -> RewriteH Core)+    , external "smash-extended-with" (smashExtendedWithR :: [RewriteH LCore] -> RewriteH LCore)         [ "Run \"smash\" extended with additional rewrites.",           "Note: be sure that the new rewrite either fails or makes progress, else this may loop."         ] .+ Eval .+ Deep .+ Loop-    , external "bash-debug" (bashDebugR :: RewriteH Core)+    , external "bash-debug" (bashDebugR :: RewriteH LCore)         [ "verbose bash - most useful with set-auto-corelint True" ] .+ Eval .+ Deep .+ Loop     ] @@ -67,11 +69,13 @@ unfoldBasicCombinatorR :: ( AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb                           , MonadCatch m )                        => Rewrite c m CoreExpr-unfoldBasicCombinatorR = setFailMsg "unfold-basic-combinator failed." $ unfoldNamesR basicCombinators+unfoldBasicCombinatorR = setFailMsg "unfold-basic-combinator failed." $ orR (map f basicCombinators)+    where f nm = voidM (callNameT nm) >> voidM callSaturatedT >> unfoldR+          voidM = liftM (const ()) -- can't wait for AMP  simplifyR :: ( AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb              , MonadCatch m, MonadUnique m )-          => Rewrite c m Core+          => Rewrite c m LCore simplifyR = setFailMsg "Simplify failed: nothing to simplify." $     innermostR (   promoteBindR recToNonrecR                 <+ promoteExprR ( unfoldBasicCombinatorR@@ -91,13 +95,13 @@ -- IdInfo attributes relied-upon by GHC. bashR :: ( AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb          , MonadCatch m, MonadUnique m )-      => Rewrite c m Core+      => Rewrite c m LCore bashR = bashExtendedWithR []  -- | An extensible bash. Given rewrites are performed before normal bash rewrites. bashExtendedWithR :: ( AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb                      , MonadCatch m, MonadUnique m )-                  => [Rewrite c m Core] -> Rewrite c m Core+                  => [Rewrite c m LCore] -> Rewrite c m LCore bashExtendedWithR rs = bashUsingR (rs ++ map fst bashComponents)  -- | Like 'bashR', but outputs name of each successful sub-rewrite, providing a log.@@ -107,13 +111,13 @@ -- Useful for debugging the bash command itself. bashDebugR :: ( AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb               , HasDebugChan m, HasDynFlags m, MonadCatch m, MonadUnique m )-           => Rewrite c m Core+           => Rewrite c m LCore bashDebugR = bashUsingR [ bracketR nm r >>> catchM (promoteT lintExprT >> idR) traceR                         | (r,nm) <- bashComponents ]  -- | Perform the 'bash' algorithm with a given list of rewrites. bashUsingR :: (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadPath c Crumb, MonadCatch m)-           => [Rewrite c m Core] -> Rewrite c m Core+           => [Rewrite c m LCore] -> Rewrite c m LCore bashUsingR rs = setFailMsg "bash failed: nothing to do." $     repeatR (occurAnalyseR >>> onetdR (catchesT rs)) >+> anytdR (promoteExprR dezombifyR) >+> occurAnalyseChangedR @@ -134,12 +138,12 @@  bashHelp :: [String] bashHelp = "Iteratively apply the following rewrites until nothing changes:"-         : map snd (bashComponents :: [(RewriteH Core,String)] -- to resolve ambiguity+         : map snd (bashComponents :: [(RewriteH LCore,String)] -- to resolve ambiguity                                                                                        ) -- TODO: Think about a good order for bash. bashComponents :: ( AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb                   , MonadCatch m, MonadUnique m )-               => [(Rewrite c m Core, String)]+               => [(Rewrite c m LCore, String)] bashComponents =   [ -- (promoteExprR occurAnalyseExprChangedR, "occur-analyse-expr")    -- ??     (promoteExprR betaReduceR, "beta-reduce")                        -- O(1)@@ -176,16 +180,16 @@ -- and is intended for use during proving tasks. smashR :: ( AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb           , MonadCatch m, MonadUnique m )-       => Rewrite c m Core+       => Rewrite c m LCore smashR = smashExtendedWithR []  smashExtendedWithR :: ( AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb                       , MonadCatch m, MonadUnique m )-                   => [Rewrite c m Core] -> Rewrite c m Core+                   => [Rewrite c m LCore] -> Rewrite c m LCore smashExtendedWithR rs = smashUsingR (rs ++ map fst smashComponents1) (map fst smashComponents2)  -smashUsingR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, HasEmptyContext c, MonadCatch m) => [Rewrite c m Core] -> [Rewrite c m Core] -> Rewrite c m Core+smashUsingR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, HasEmptyContext c, MonadCatch m) => [Rewrite c m LCore] -> [Rewrite c m LCore] -> Rewrite c m LCore smashUsingR rs1 rs2 =     setFailMsg "smash failed: nothing to do." $     repeatR (occurAnalyseR >>> (onetdR (catchesT rs1) <+ onetdR (catchesT rs2))) >+> anytdR (promoteExprR dezombifyR) >+> occurAnalyseChangedR@@ -193,14 +197,14 @@  smashHelp :: [String] smashHelp = "A more powerful but less efficient version of \"bash\", intended for use while proving lemmas.  Iteratively apply the following rewrites until nothing changes:" : map snd (smashComponents1 ++ smashComponents2-                                                                                           :: [(RewriteH Core,String)] -- to resolve ambiguity+                                                                                           :: [(RewriteH LCore,String)] -- to resolve ambiguity                                                                                         )   -- | As bash, but with "let-nonrec-subst" instead of "let-nonrec-subst-safe". smashComponents1 :: ( AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb                     , MonadCatch m, MonadUnique m )-                 => [(Rewrite c m Core, String)]+                 => [(Rewrite c m LCore, String)] smashComponents1 =   [ -- (promoteExprR occurAnalyseExprChangedR, "occur-analyse-expr")    -- ??     (promoteExprR betaReduceR, "beta-reduce")                        -- O(1)@@ -226,12 +230,14 @@   , (promoteProgR letFloatTopR, "let-float-top")                     -- O(n)   , (promoteExprR castElimReflR, "cast-elim-refl")                   -- O(1)   , (promoteExprR castElimSymR, "cast-elim-sym")                     -- O(1)+  , (promoteExprR castFloatAppR, "cast-float-app")                   -- O(1)+  , (promoteExprR castFloatLamR, "cast-float-lam")                   -- O(1) --  , (promoteExprR dezombifyR, "dezombify")                           -- O(1) -- performed at the end   ]  smashComponents2 :: ( ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c                     , MonadCatch m, MonadUnique m )-                 => [(Rewrite c m Core, String)]+                 => [(Rewrite c m LCore, String)] smashComponents2 =     [ (promoteExprR caseElimMergeAltsR, "case-elim-merge-alts") -- do this last, lest it prevent other simplifications     ]
src/HERMIT/Dictionary/Debug.hs view
@@ -19,23 +19,23 @@ -- | Exposed debugging 'External's. externals :: [External] externals = map (.+ Debug)-    [ external "trace" (traceR :: String -> RewriteH Core)+    [ external "trace" (traceR :: String -> RewriteH LCoreTC)         [ "give a side-effect message as output when processing this command" ]-    , external "observe" (observeR :: String -> RewriteH Core)+    , external "observe" (observeR :: String -> RewriteH LCoreTC)         [ "give a side-effect message as output, and observe the value being processed" ]-    , external "observe-failure" (observeFailureR :: String -> RewriteH Core -> RewriteH Core)+    , external "observe-failure" (observeFailureR :: String -> RewriteH LCoreTC -> RewriteH LCoreTC)         [ "give a side-effect message if the rewrite fails, including the failing input" ]-    , external "bracket" (bracketR :: String -> RewriteH Core -> RewriteH Core)+    , external "bracket" (bracketR :: String -> RewriteH LCoreTC -> RewriteH LCoreTC)         [ "if given rewrite succeeds, see its input and output" ]     ]  -- | If the 'Rewrite' fails, print out the 'Core', with a message.-observeFailureR :: (Injection a CoreTC, ReadBindings c, ReadPath c Crumb, HasDebugChan m, MonadCatch m)+observeFailureR :: (Injection a LCoreTC, ReadBindings c, ReadPath c Crumb, HasDebugChan m, MonadCatch m)                 => String -> Rewrite c m a -> Rewrite c m a observeFailureR str m = m <+ observeR str  -- | Print out the 'Core', with a message.-observeR :: (Injection a CoreTC, ReadBindings c, ReadPath c Crumb, HasDebugChan m, Monad m)+observeR :: (Injection a LCoreTC, ReadBindings c, ReadPath c Crumb, HasDebugChan m, Monad m)          => String -> Rewrite c m a observeR msg = extractR $ sideEffectR $ \ cxt -> sendDebugMessage . DebugCore msg cxt @@ -44,7 +44,7 @@ traceR msg = sideEffectR $ \ _ _ -> sendDebugMessage $ DebugTick msg  -- | Show before and after a rewrite.-bracketR :: (Injection a CoreTC, ReadBindings c, ReadPath c Crumb, HasDebugChan m, MonadCatch m)+bracketR :: (Injection a LCoreTC, ReadBindings c, ReadPath c Crumb, HasDebugChan m, MonadCatch m)          => String -> Rewrite c m a -> Rewrite c m a bracketR msg rr = do     -- Be careful to only run the rr once, in case it has side effects.@@ -53,4 +53,3 @@                             return e' >>> observeR after) r     where before = msg ++ " (before)"           after  = msg ++ " (after)"--- attemptM :: MonadCatch m => m a -> m (Either String a)
src/HERMIT/Dictionary/FixPoint.hs view
@@ -14,7 +14,6 @@     , isFixExprT     ) where -import Control.Applicative import Control.Arrow import Control.Monad import Control.Monad.IO.Class@@ -43,21 +42,21 @@ -- | Externals for manipulating fixed points. externals ::  [External] externals =-    [ external "fix-intro" (fixIntroR :: RewriteH Core)+    [ external "fix-intro" (promoteCoreR fixIntroR :: RewriteH LCore)         [ "rewrite a function binding into a non-recursive binding using fix" ] .+ Introduce .+ Context-    , external "fix-computation-rule" (promoteExprBiR fixComputationRuleBR :: BiRewriteH Core)+    , external "fix-computation-rule" (promoteExprBiR fixComputationRuleBR :: BiRewriteH LCore)         [ "Fixed-Point Computation Rule",           "fix t f  <==>  f (fix t f)"         ] .+ Context-    , external "fix-rolling-rule" (promoteExprBiR fixRollingRuleBR :: BiRewriteH Core)+    , external "fix-rolling-rule" (promoteExprBiR fixRollingRuleBR :: BiRewriteH LCore)         [ "Rolling Rule",           "fix tyA (\\ a -> f (g a))  <==>  f (fix tyB (\\ b -> g (f b))"         ] .+ Context     , external "fix-fusion-rule" ((\ f g h r1 r2 strictf -> promoteExprBiR                                                                 (fixFusionRule (Just (r1,r2)) (Just strictf) f g h))                                                                 :: CoreString -> CoreString -> CoreString-                                                                    -> RewriteH Core -> RewriteH Core-                                                                    -> RewriteH Core -> BiRewriteH Core)+                                                                    -> RewriteH LCore -> RewriteH LCore+                                                                    -> RewriteH LCore -> BiRewriteH LCore)         [ "Fixed-point Fusion Rule"         , "Given f :: A -> B, g :: A -> A, h :: B -> B, and"         , "proofs that, for some x, (f (g a) ==> x) and (h (f a) ==> x) and that f is strict, then"@@ -65,7 +64,7 @@         ] .+ Context     , external "fix-fusion-rule-unsafe" ((\ f g h r1 r2 -> promoteExprBiR (fixFusionRule (Just (r1,r2)) Nothing f g h))                                                             :: CoreString -> CoreString -> CoreString-                                                                -> RewriteH Core -> RewriteH Core -> BiRewriteH Core)+                                                                -> RewriteH LCore -> RewriteH LCore -> BiRewriteH LCore)         [ "(Unsafe) Fixed-point Fusion Rule"         , "Given f :: A -> B, g :: A -> A, h :: B -> B, and"         , "a proof that, for some x, (f (g a) ==> x) and (h (f a) ==> x), then"@@ -73,7 +72,7 @@         , "Note that the precondition that f is strict is required to hold."         ] .+ Context .+ PreCondition     , external "fix-fusion-rule-unsafe" ((\ f g h -> promoteExprBiR (fixFusionRule Nothing Nothing f g h))-                                                        :: CoreString -> CoreString -> CoreString -> BiRewriteH Core)+                                                        :: CoreString -> CoreString -> CoreString -> BiRewriteH LCore)         [ "(Very Unsafe) Fixed-point Fusion Rule"         , "Given f :: A -> B, g :: A -> A, h :: B -> B, then"         , "f (fix g) <==> fix h"@@ -216,7 +215,7 @@                        App f <$> buildFixT g  -- | If @f@ is strict, then (@f (g a)@ == @h (f a)@)  ==>  (@f (fix g)@ == @fix h@)-fixFusionRule :: Maybe (RewriteH Core, RewriteH Core) -> Maybe (RewriteH Core) -> CoreString -> CoreString -> CoreString -> BiRewriteH CoreExpr+fixFusionRule :: Maybe (RewriteH LCore, RewriteH LCore) -> Maybe (RewriteH LCore) -> CoreString -> CoreString -> CoreString -> BiRewriteH CoreExpr fixFusionRule meq mfstrict = parse3beforeBiR $ fixFusionRuleBR ((extractR *** extractR) <$> meq) (extractR <$> mfstrict)  --------------------------------------------------------------------------------------------------
src/HERMIT/Dictionary/Fold.hs view
@@ -1,42 +1,61 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE InstanceSigs #-}+{-# LANGUAGE TupleSections #-} {-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeSynonymInstances #-} module HERMIT.Dictionary.Fold     ( -- * Fold/Unfold Transformation       externals     , foldR     , foldVarR-    , stashFoldR-    , stashFoldAnyR+    , foldVarConfigR+    , runFoldR       -- * Unlifted fold interface-    , fold-    , unifyTypes -- TODO: remove in favor of GHC's unification-    , tyMatchesToCoreExpr+    , fold, compileFold, runFold, runFoldMatches, CompiledFold+    , proves -- for now+    , lemmaMatch+      -- * Equality+    , Equality(..)+    , toEqualities+    , flipEquality+    , freeVarsEquality+    , ppEqualityT     ) where  import Control.Arrow-import Control.Applicative import Control.Monad import Control.Monad.IO.Class -import qualified Data.Map as Map+import Data.List (delete, (\\), intersect)+import qualified Data.Map as M+import Data.Maybe (catMaybes, fromMaybe, maybeToList)+import qualified Data.IntMap.Lazy as I+import Data.Typeable  import HERMIT.Core import HERMIT.Context import HERMIT.External import HERMIT.GHC import HERMIT.Kure+import HERMIT.Lemma import HERMIT.Monad import HERMIT.Name+import HERMIT.Utilities -import HERMIT.Dictionary.Common (varBindingDepthT,inScope,findIdT)+import HERMIT.Dictionary.Common (varBindingDepthT,findIdT) import HERMIT.Dictionary.Inline hiding (externals) +import HERMIT.PrettyPrinter.Common+import qualified Text.PrettyPrint.MarkedHughesPJ as PP+ import Prelude hiding (exp)  ------------------------------------------------------------------------  externals :: [External] externals =-    [ external "fold" (promoteExprR . foldR :: HermitName -> RewriteH Core)+    [ external "fold" (promoteExprR . foldR :: HermitName -> RewriteH LCore)         [ "fold a definition"         , ""         , "double :: Int -> Int"@@ -48,208 +67,580 @@         , ""         , "Note: due to associativity, if you wanted to fold 5 + 6 + 6, "         , "you first need to apply an associativity rewrite." ]  .+ Context .+ Deep-    , external "fold-remembered" (promoteExprR . stashFoldR :: RememberedName -> RewriteH Core)-        [ "Fold a remembered definition." ]                      .+ Context .+ Deep-    , external "fold-any" (promoteExprR stashFoldAnyR :: RewriteH Core)-        [ "Attempt to fold any of the remembered definitions." ] .+ Context .+ Deep     ]  ------------------------------------------------------------------------ -stashFoldR :: (ReadBindings c, HasStash m, MonadCatch m) => RememberedName -> Rewrite c m CoreExpr-stashFoldR label = prefixFailMsg "Fold failed: " $-    transform $ \ c e -> do-        Def i rhs <- lookupDef label-        guardMsg (inScope c i) $ unqualifiedName i ++ " is not in scope.\n(A common cause of this error is trying to fold a recursive call while being in the body of a non-recursive definition.  This can be resolved by calling \"nonrec-to-rec\" on the non-recursive binding group.)"-        maybe (fail "no match.")-              return-              (fold i rhs e)--stashFoldAnyR :: (ReadBindings c, HasStash m, MonadCatch m) => Rewrite c m CoreExpr-stashFoldAnyR = setFailMsg "Fold failed: no definitions could be folded." $-                catchesM =<< liftM (map stashFoldR) (liftM Map.keys (constT getStash))- foldR :: (ReadBindings c, HasHermitMEnv m, HasHscEnv m, MonadCatch m, MonadIO m, MonadThings m, MonadUnique m)       => HermitName -> Rewrite c m CoreExpr foldR nm = prefixFailMsg "Fold failed: " $ findIdT nm >>= foldVarR Nothing  foldVarR :: (ReadBindings c, MonadCatch m, MonadUnique m) => Maybe BindingDepth -> Var -> Rewrite c m CoreExpr-foldVarR md v = do+foldVarR = foldVarConfigR AllBinders++foldVarConfigR :: (ReadBindings c, MonadCatch m, MonadUnique m)+               => InlineConfig -> Maybe BindingDepth -> Var -> Rewrite c m CoreExpr+foldVarConfigR config md v = do     case md of         Nothing    -> return ()         Just depth -> do depth' <- varBindingDepthT v                          guardMsg (depth == depth') "Specified binding depth does not match that of variable binding, this is probably a shadowing occurrence."-    e <- idR-    (rhs,_) <- getUnfoldingT AllBinders <<< return v-    maybe (fail "no match.") return (fold v rhs e)+    rhss <- liftM (map fst) $ getUnfoldingsT config <<< return v+    transform $ \ c -> maybeM "no match." . fold [mkEquality [] rhs (varToCoreExpr v) | rhs <- rhss] c +-- | Rewrite using a compiled fold. Useful inside traversal strategies like+-- anytdR, because you can compile the fold once outside the traversal, then+-- apply it everywhere in the tree.+runFoldR :: (BoundVars c, Monad m) => CompiledFold -> Rewrite c m CoreExpr+runFoldR compiled = transform $ \c -> maybeM "no match." . runFold compiled c+ ------------------------------------------------------------------------ -countBinders :: CoreExpr -> Int-countBinders e = length vs-    where (vs,_) = collectBinders e+newtype CompiledFold = CompiledFold (EMap ([Var], CoreExpr)) -collectNBinders :: Int -> CoreExpr -> Maybe ([Var], CoreExpr)-collectNBinders = go []-  where-    go bs 0 e         = return (reverse bs, e)-    go bs i (Lam b e) = go (b:bs) (i-1) e-    go _ _  _         = Nothing+-- | Attempt to apply a list of Equalitys to the given expression, folding the+-- left-hand side into an application of the right-hand side. This+-- implementation depends on `Equality` being well-formed. That is, both the+-- LHS and RHS are NOT lambda expressions. Always use `mkEquality` to ensure+-- this is the case.+fold :: BoundVars c => [Equality] -> c -> CoreExpr -> Maybe CoreExpr+fold = runFold . compileFold -unifyHoles :: Ord k-           => [k]              -- keys we care about (TODO: figure out what else is getting in there)-           -> (a -> a -> Bool) -- notion of equality-           -> [(k,a)]          -- list of key/values-           -> Maybe [(k,a)]    -- list of unified key/values, or failure-unifyHoles vs eq kvs = do-    -- return Nothing if not equal, so sequence will fail below-    let checkEqual m1 m2 = ifM (eq <$> m1 <*> m2) m1 Nothing-        m = Map.fromListWith checkEqual [(k,Just v) | (k,v) <- kvs ]+-- | Compile a list of Equality's into a single fold matcher.+compileFold :: [Equality] -> CompiledFold+compileFold = CompiledFold . foldr addFold fEmpty+    where addFold (Equality vs lhs rhs) =+            let hs = vs `intersect` varSetElems (freeVarsExpr lhs)+            in insertFold emptyAlphaEnv vs lhs (hs, rhs) -    es <- sequence [ join (Map.lookup v m) | v <- vs ]-    return $ zip vs es+-- | Attempt to fold an expression using a matcher in a given context.+runFold :: BoundVars c => CompiledFold -> c -> CoreExpr -> Maybe CoreExpr+runFold f c e = fst <$> runFoldMatches f c e -fold :: Id -> CoreExpr -> CoreExpr -> Maybe CoreExpr-fold i lam exp = do-    (vs,body) <- collectNBinders (countBinders lam - countBinders exp) lam-    al <- foldMatch vs [] body exp+-- | Attempt to fold an expression using a matcher in a given context.+-- Return resulting expression and a map of what when in the holes in the pattern.+runFoldMatches :: BoundVars c => CompiledFold -> c -> CoreExpr -> Maybe (CoreExpr, VarEnv CoreExpr)+runFoldMatches (CompiledFold f) c exp = do+    (hs, (vs', rhs')) <- soleElement $ filterOutOfScope c $ findFold exp f+    args <- sequence [ lookupVarEnv hs v | v <- vs' ]+    return (uncurry mkCoreApps $ betaReduceAll (mkCoreLams vs' rhs') args, hs) -    es <- liftM (map snd) $ unifyHoles vs exprAlphaEq al+insertFold :: Fold m => AlphaEnv -> [Var] -> Key m -> a -> m a -> m a+insertFold env vs k x = fAlter env vs k (const (Just x)) -    return $ mkCoreApps (varToCoreExpr i) es+findFold :: Fold m => Key m -> m a -> [(VarEnv CoreExpr, a)]+findFold = fFold emptyVarEnv emptyAlphaEnv --- Note: Var in the concrete instance is first--- (not the Var found in the definition we are trying to fold).-addAlpha :: Var -> Var -> [(Var,Var)] -> [(Var,Var)]-addAlpha rId lId alphas | rId == lId = alphas-                        | otherwise  = (rId,lId) : alphas+filterOutOfScope :: BoundVars c => c -> [(VarEnv CoreExpr, ([Var], CoreExpr))] -> [(VarEnv CoreExpr, ([Var], CoreExpr))]+filterOutOfScope c = go+    where go [] = []+          go (x@(_,(vs,e)):r)+            | isEmptyVarSet (filterVarSet (not . inScope c) (delVarSetList (freeVarsExpr e) vs)) = x : go r+            | otherwise = go r -matchWithTypes :: [Var] -> [(Var,Var)] -> Id -> CoreExpr -> Maybe [(Var,CoreExpr)]-matchWithTypes vs as i e = do-    tys <- foldMatchType vs as (idType i) (exprType e)-    return $ (i,e) : tyMatchesToCoreExpr tys+------------------------------------------------------------------------ -tyMatchesToCoreExpr :: [(TyVar, Type)] -> [(Var, CoreExpr)]-tyMatchesToCoreExpr = map (\(v,t) -> (v, Type t))+data AlphaEnv = AE { _aeNext :: Int, _aeEnv :: VarEnv Int } +emptyAlphaEnv :: AlphaEnv+emptyAlphaEnv = AE 0 emptyVarEnv++extendAlphaEnv :: Var -> AlphaEnv -> AlphaEnv+extendAlphaEnv v (AE i env) = AE (i+1) (extendVarEnv env v i)++lookupAlphaEnv :: Var -> AlphaEnv -> Maybe Int+lookupAlphaEnv v (AE _ env) = lookupVarEnv env v+ ------------------------------------------------------------------------ --- Note: return list can have duplicate keys, caller is responsible--- for checking that dupes refer to same expression-foldMatch :: [Var]          -- ^ vars that can unify with anything-          -> [(Var,Var)]    -- ^ alpha equivalences, wherever there is binding-                            --   note: we depend on behavior of lookup here, so new entries-                            --         should always be added to the front of the list so-                            --         we don't have to explicity remove them when shadowing occurs-          -> CoreExpr       -- ^ pattern we are matching on-          -> CoreExpr       -- ^ expression we are checking-          -> Maybe [(Var,CoreExpr)] -- ^ mapping of vars to expressions, or failure+-- TODO: Maybe a -> a ??? -- we never need to delete+type A a = Maybe a -> Maybe a -foldMatch vs as (Var i) e | i `elem` vs = matchWithTypes vs as i e-                          | otherwise   = case e of-                                            Var i' | maybe False (==i) (lookup i' as) -> matchWithTypes vs as i e-                                                   | i == i' -> liftM tail $ matchWithTypes vs as i e-                                                                -- note we depend on (i,e) being at front here-                                                                -- this is not strictly necessary, but is faster-                                            _                -> Nothing-foldMatch _  _ (Lit l) (Lit l') | l == l' = return []+toA :: Fold m => (m a -> m a) -> Maybe (m a) -> Maybe (m a)+toA f = Just . f . fromMaybe fEmpty -foldMatch vs as (App e a) (App e' a') = do-    x <- foldMatch vs as e e'-    y <- foldMatch vs as a a'-    return (x ++ y)+type LMap a = M.Map Literal a+type BMap = TyMap -- Binders are de-bruijn indexed, so we only compare their types -foldMatch vs as (Lam v e) (Lam v' e') = foldMatch (filter (/=v) vs) (addAlpha v' v as) e e'+------------------------------------------------------------------------ -foldMatch vs as (Let (NonRec v rhs) e) (Let (NonRec v' rhs') e') = do-    x <- foldMatch vs as rhs rhs'-    y <- foldMatch (filter (/=v) vs) (addAlpha v' v as) e e'-    return (x ++ y)+class Fold m where+    type Key m :: *+    fEmpty :: m a+    fAlter :: AlphaEnv -> [Var] -> Key m -> A a -> m a -> m a+    fFold :: VarEnv CoreExpr -> AlphaEnv -> Key m -> m a -> [(VarEnv CoreExpr, a)] --- TODO: this depends on bindings being in the same order-foldMatch vs as (Let (Rec bnds) e) (Let (Rec bnds') e') | length bnds == length bnds' = do-    let vs' = filter (`notElem` map fst bnds) vs-        as' = foldr (uncurry addAlpha) as $ zip (map fst bnds) (map fst bnds')-        bmatch (_,rhs) (_,rhs') = foldMatch vs' as' rhs rhs'-    x <- zipWithM bmatch bnds bnds'-    y <- foldMatch vs' as' e e'-    return (concat x ++ y)+-- TODO: Idea ... Generalized Tries with Effects+--       Reader - De Bruijn indexing+--       State-ish - Folding with hole filling -foldMatch vs as (Tick t e) (Tick t' e') | t == t' = foldMatch vs as e e'+------------------------------------------------------------------------ -foldMatch vs as (Case s b ty alts) (Case s' b' ty' alts') = do-    guard (length alts == length alts')-    t <- foldMatchType vs as ty ty'-    x <- foldMatch vs as s s'-    let as' = addAlpha b' b as-        vs' = filter (/=b) vs-        altMatch (ac, is, e) (ac', is', e') | ac == ac' =-            foldMatch (filter (`notElem` is) vs') (foldr (uncurry addAlpha) as' $ zip is' is) e e'-        altMatch _ _ = Nothing-    y <- zipWithM altMatch alts alts'-    return (x ++ tyMatchesToCoreExpr t ++ concat y)+-- Note [Var Uniques]+-- Free variable occurrences can have the same unique at a different type!+-- The reason is that when GHC substitutes into the type of the Var, it DOES NOT+-- freshen the unique of the Var. This is not normally a problem for GHC, because+-- if two Vars with the same unique are bound within scope of each other, one gets+-- freshened at creation. However, with Lemmas, we have the possibility of applying+-- a fold from one subtree to a completely different subtree, so can cross scopes.+--+-- To solve this, we first look up the Var by unique, then check it's type with a TyMap.+-- This is unnecessary for bound vars, because their types are checked when we pass+-- the binding itself. -foldMatch vs as (Cast e c) (Cast e' c') = do-    guard (coreEqCoercion c c')-    foldMatch vs as e e'+data VMap a = VM { bvmap :: I.IntMap a, fvmap :: VarEnv (TyMap a) } -- See Note [Var Uniques]+            | VMEmpty -foldMatch vs as (Type t1) (Type t2) = liftM tyMatchesToCoreExpr $ foldMatchType vs as t1 t2+instance Fold VMap where+    type Key VMap = Var --- TODO: do we want to descend into these? There are Types in here.-foldMatch _ _ (Coercion c) (Coercion c') | coreEqCoercion c c' = return []+    fEmpty :: VMap a+    fEmpty = VMEmpty -foldMatch _ _ _ _ = Nothing+    fAlter :: AlphaEnv -> [Var] -> Key VMap -> A a -> VMap a -> VMap a+    fAlter env vs v f VMEmpty = fAlter env vs v f (VM I.empty emptyVarEnv)+    fAlter env vs v f m@VM{}+        | Just bv <- lookupAlphaEnv v env = m { bvmap = I.alter f bv (bvmap m) }+        | otherwise                       = m { fvmap = alterVarEnv (toA (fAlter env vs (varType v) f)) (fvmap m) v } +    fFold :: VarEnv CoreExpr -> AlphaEnv -> Key VMap -> VMap a -> [(VarEnv CoreExpr, a)]+    fFold _  _   _ VMEmpty = []+    fFold hs env v m@VM{}+        | Just bv <- lookupAlphaEnv v env = maybeToList $ (hs,) <$> I.lookup bv (bvmap m)+        | otherwise                       = do+            m' <- maybeToList $ lookupVarEnv (fvmap m) v+            fFold hs env (varType v) m'+ ------------------------------------------------------------------------ --- | Given list of TyVars which can match any type (the holes),--- a pattern, and a concrete type, return mapping from hole to type--- for successful unification.-unifyTypes :: [TyVar] -> Type -> Type -> Maybe [(TyVar, Type)]-unifyTypes holes pat ty = do-    al <- foldMatchType holes [] pat ty-    -- unlike folding itself, we don't care that every hole is assigned-    let found = [ v | (v,_) <- al, v `elem` holes ]-    unifyHoles found typeAlphaEq al+data TyMap a = TyMEmpty+             | TyM { tmHole   :: TyMap (M.Map Var a)+                   , tmVar    :: VMap a+                   , tmApp    :: TyMap (TyMap a)+                   , tmFun    :: TyMap (TyMap a)+                   , tmTcApp  :: NameEnv (ListMap TyMap a)+                   , tmForall :: TyMap (BMap a)+                   , tmTyLit  :: TyLitMap a+                   } -foldMatchType :: [TyVar]              -- ^ vars that can unify with anything-              -> [(TyVar,TyVar)]      -- ^ alpha equivalences, wherever there is binding-                                      --   note: we depend on behavior of lookup here, so new entries-                                      --         should always be added to the front of the list so-                                      --         we don't have to explicity remove them when shadowing occurs-              -> Type                 -- ^ pattern we are matching on-              -> Type                 -- ^ expression we are checking-              -> Maybe [(TyVar,Type)] -- ^ mapping of vars to types, or failure+instance Fold TyMap where+    type Key TyMap = Type --- look through type synonyms-foldMatchType vs as t1 t2 | Just t1' <- tcView t1 = foldMatchType vs as t1' t2-                          | Just t2' <- tcView t2 = foldMatchType vs as t1 t2'+    fEmpty :: TyMap a+    fEmpty = TyMEmpty -foldMatchType vs as (TyVarTy v) t | v `elem` vs = return [(v,t)]-                                  | otherwise = case t of-                                                  TyVarTy v' | maybe False (==v) (lookup v' as) -> return [(v,t)]-                                                             | v == v' {- compare kinds? -} -> return []-                                                  _ -> Nothing+    fAlter :: AlphaEnv -> [Var] -> Key TyMap -> A a -> TyMap a -> TyMap a+    fAlter env vs ty f TyMEmpty = fAlter env vs ty f (TyM fEmpty fEmpty fEmpty fEmpty emptyNameEnv fEmpty fEmpty)+    fAlter env vs ty f m@TyM{} = go ty+        where go (TyVarTy v)+                | v `elem` vs  = m { tmHole = fAlter env vs (varType v) (Just . M.alter f v . fromMaybe M.empty) (tmHole m) }+                | otherwise    = m { tmVar = fAlter env vs v f (tmVar m) }+              go (AppTy t1 t2) = m { tmApp = fAlter env vs t1 (toA (fAlter env vs t2 f)) (tmApp m) }+              go (FunTy t1 t2) = m { tmFun = fAlter env vs t1 (toA (fAlter env vs t2 f)) (tmFun m) }+              go (TyConApp tc tys) = m { tmTcApp = alterNameEnv (toA (fAlter env vs tys f)) (tmTcApp m) (getName tc) }+              go (ForAllTy tv t) = m { tmForall = fAlter (extendAlphaEnv tv env) (delete tv vs) t+                                                         (toA (fAlter env vs (varType tv) f)) (tmForall m) }+              go (LitTy l)     = m { tmTyLit = fAlter env vs l f (tmTyLit m) } -foldMatchType vs as (AppTy ty1 ty2) (AppTy ty1' ty2') = do-    x <- foldMatchType vs as ty1 ty1'-    y <- foldMatchType vs as ty2 ty2'-    return (x ++ y)+    fFold :: VarEnv CoreExpr -> AlphaEnv -> Key TyMap -> TyMap a -> [(VarEnv CoreExpr, a)]+    fFold _ _ _ TyMEmpty = []+    fFold hs env ty m@TyM{} = hss ++ go ty+        where hss = do+                (hs', m') <- fFold hs env (typeKind ty) (tmHole m)+                extendResult m' (Type ty) hs' -foldMatchType vs as (TyConApp tc1 kOrTys1) (TyConApp tc2 kOrTys2) = do-    guard ((tc1 == tc2) && (length kOrTys1 == length kOrTys2))-    let f ty1 ty2 | isKind ty1 && eqKind ty1 ty2 = return []-                  | otherwise = foldMatchType vs as ty1 ty2-    liftM concat $ zipWithM f kOrTys1 kOrTys2+              go (TyVarTy v) = fFold hs env v (tmVar m)+              go (AppTy t1 t2) = do+                (hs', m') <- fFold hs env t1 (tmApp m)+                fFold hs' env t2 m'+              go (FunTy t1 t2) = do+                (hs', m') <- fFold hs env t1 (tmFun m)+                fFold hs' env t2 m'+              go (TyConApp tc tys) = maybeToList (lookupNameEnv (tmTcApp m) (getName tc)) >>= fFold hs env tys+              go (ForAllTy tv t) = do+                (hs', m') <- fFold hs (extendAlphaEnv tv env) t (tmForall m)+                fFold hs' env (varType tv) m'+              go (LitTy l) = fFold hs env l (tmTyLit m) -foldMatchType vs as (FunTy ty1 ty2) (FunTy ty1' ty2') = do-    x <- foldMatchType vs as ty1 ty1'-    y <- foldMatchType vs as ty2 ty2'-    return (x ++ y)+------------------------------------------------------------------------ -foldMatchType vs as (ForAllTy v ty) (ForAllTy v' ty') = foldMatchType (filter (/=v) vs) (addAlpha v' v as) ty ty'+data TyLitMap a = TLM { tlmNumber :: M.Map Integer a+                      , tlmString :: M.Map FastString a+                      } -foldMatchType _ _ (LitTy l1) (LitTy l2) | l1 == l2 = return []+instance Fold TyLitMap where+    type Key TyLitMap = TyLit -foldMatchType _ _ _ _ = Nothing+    fEmpty :: TyLitMap a+    fEmpty = TLM M.empty M.empty +    fAlter :: AlphaEnv -> [Var] -> Key TyLitMap -> A a -> TyLitMap a -> TyLitMap a+    fAlter _ _ l f m = go l+        where go (NumTyLit n) = m { tlmNumber = M.alter f n (tlmNumber m) }+              go (StrTyLit s) = m { tlmString = M.alter f s (tlmString m) }++    fFold :: VarEnv CoreExpr -> AlphaEnv -> Key TyLitMap -> TyLitMap a -> [(VarEnv CoreExpr, a)]+    fFold hs _ l m = go l+        where go (NumTyLit n) = maybeToList $ (hs,) <$> M.lookup n (tlmNumber m)+              go (StrTyLit s) = maybeToList $ (hs,) <$> M.lookup s (tlmString m)++------------------------------------------------------------------------++-- Note [Coercions]+-- We don't actually care about the structure of the coercion evidence+-- itself when we are folding types and expressions. We merely care that+-- there are two coercions with the same type. Hence, we look up the type+-- of the coercion in a TyMap.++-- Note [Tick]+-- We completely look through Ticks, discarding them from pattern expressions+-- at insertion and from candidate expressions at folding/lookup. It is assumed+-- that the Tick is properly present in the RHS, which is the ultimate return+-- value of fFold, thus it will appear in the resulting code.++-- Note [Holes]+-- Holes are distinguished variables which can match any expression. (The universally+-- quantified variables in an Equality.) They are stored as a TyMap, so the type+-- of the expression can be checked against the type of the hole. This wraps a+-- map from Var to result. We use a regular map instead of a VarEnv so we can get+-- the Var back, which allows us to assign it to the expression when building+-- the fold result.++data EMap a = EMEmpty+            | EM { emHole  :: TyMap (M.Map Var a) -- See Note [Holes]+                 , emVar   :: VMap a+                 , emLit   :: LMap a+                 , emCo    :: TyMap a        -- See Note [Coercions]+                 , emType  :: TyMap a+                 , emCast  :: EMap (TyMap a) -- See Note [Coercions]+                 , emApp   :: EMap (EMap a)+                 , emLam   :: EMap (BMap a)+                 , emLetN  :: EMap (EMap (BMap a))+                   -- consider using set rather than list for order-independence+                 , emLetR  :: ListMap EMap (EMap (ListMap BMap a))+                 , emCase  :: EMap (ListMap AMap a)+                 , emECase :: EMap (TyMap a)+                 }++emptyEMapWrapper :: EMap a+emptyEMapWrapper = EM fEmpty fEmpty M.empty fEmpty fEmpty fEmpty+                      fEmpty fEmpty fEmpty fEmpty fEmpty fEmpty++instance Fold EMap where+    type Key EMap = CoreExpr+    fEmpty = EMEmpty++    fAlter :: AlphaEnv -> [Var] -> Key EMap -> A a -> EMap a -> EMap a+    fAlter env vs exp f EMEmpty = fAlter env vs exp f emptyEMapWrapper+    fAlter env vs exp f m@EM{} = go exp+        where go (Var v)+                | v `elem` vs = m { emHole = fAlter env vs (varType v) (Just . M.alter f v . fromMaybe M.empty) (emHole m) }+                | otherwise   = m { emVar  = fAlter env vs v f (emVar m) }+              go (Lit l)      = m { emLit  = M.alter f l (emLit m) }+              go (Coercion c) = m { emCo   = fAlter env vs (coercionType c) f (emCo m) }+              go (Type t)     = m { emType = fAlter env vs t f (emType m) }+              go (Cast e c)   = m { emCast = fAlter env vs e (toA (fAlter env vs (coercionType c) f)) (emCast m) }+              go (Tick _ e)   = fAlter env vs e f m -- See Note [Tick]+              go (App l r)    = m { emApp  = fAlter env vs l (toA (fAlter env vs r f)) (emApp m) }+              go (Lam b e)    = m { emLam  = fAlter (extendAlphaEnv b env) (delete b vs) e+                                                    (toA (fAlter env vs (varType b) f))+                                                    (emLam m) }+              go (Case s _ t []) = m { emECase = fAlter env vs s (toA (fAlter env vs t f)) (emECase m) }+              go (Case s b _ as) = m { emCase = fAlter env vs s+                                                       (toA (fAlter (extendAlphaEnv b env) (delete b vs) as f))+                                                       (emCase m) }+              go (Let (NonRec b r) e) = m { emLetN = fAlter (extendAlphaEnv b env) (delete b vs) e+                                                            (toA (fAlter env vs r (toA (fAlter env vs (varType b) f))))+                                                            (emLetN m) }+              go (Let (Rec ds) e) = let (bs, rhss) = unzip ds+                                        env' = foldr extendAlphaEnv env bs+                                        vs' = vs \\ bs+                                    in m { emLetR = fAlter env' vs' rhss+                                                           (toA (fAlter env' vs' e+                                                                        (toA (fAlter env vs (map varType bs) f))))+                                                           (emLetR m) }++    fFold :: VarEnv CoreExpr -> AlphaEnv -> Key EMap -> EMap a -> [(VarEnv CoreExpr, a)]+    fFold _  _   _ EMEmpty = []+    fFold hs env exp m@EM{} = hss ++ go exp+        where hss = do+                (hs', m') <- fFold hs env (exprKindOrType exp) (emHole m)+                extendResult m' exp hs'++              go (Var v)      = fFold hs env v (emVar m)+              go (Lit l)      = maybeToList $ (hs,) <$> M.lookup l (emLit m)+              go (Coercion c) = fFold hs env (coercionType c) (emCo m)+              go (Type t)     = fFold hs env t (emType m)+              go (Cast e c)   = do+                (hs', m') <- fFold hs env e (emCast m)+                fFold hs' env (coercionType c) m'+              go (Tick _ e)   = fFold hs env e m -- See Note [Tick]+              go (App l r)    = do+                (hs', m') <- fFold hs env l (emApp m)+                fFold hs' env r m'+              go (Lam b e)    = do+                (hs', m') <- fFold hs (extendAlphaEnv b env) e (emLam m)+                fFold hs' env (varType b) m'+              go (Case s _ t []) = do+                (hs', m') <- fFold hs env s (emECase m)+                fFold hs' env t m'+              go (Case s b _ as) = do+                (hs', m') <- fFold hs env s (emCase m)+                fFold hs' (extendAlphaEnv b env) as m'+              go (Let (NonRec b r) e) = do+                (hs' , m' ) <- fFold hs (extendAlphaEnv b env) e (emLetN m)+                (hs'', m'') <- fFold hs' env r m'+                fFold hs'' env (varType b) m''+              go (Let (Rec ds) e) = do+                let (bs, rhss) = unzip ds+                    env' = foldr extendAlphaEnv env bs+                (hs' , m' ) <- fFold hs env' rhss (emLetR m)+                (hs'', m'') <- fFold hs' env' e m'+                fFold hs'' env (map varType bs) m''++-- Add the matched expression to the holes map, fails if expression differs from one already in hole.+extendResult :: M.Map Var a -> CoreExpr -> VarEnv CoreExpr -> [(VarEnv CoreExpr, a)]+extendResult hm e m = catMaybes+    [ case lookupVarEnv m v of+        Nothing -> return (extendVarEnv m v e, x)+        Just e' -> sameExpr e e' >> return (m, x)+    | (v,x) <- M.assocs hm ]++-- | Determine if two expressions are alpha-equivalent.+sameExpr :: CoreExpr -> CoreExpr -> Maybe ()+sameExpr e1 e2 = snd <$> soleElement (findFold e2 m)+    where m = insertFold emptyAlphaEnv [] e1 () EMEmpty++-- | Determine if the left Quantified 'proves' the right one.+-- Here, 'proves' means that the right Quantified is a substitution+-- of the left one, where only the top-level binders of the left+-- Quantified can be substituted.+proves :: Quantified -> Quantified -> Bool+proves (Quantified bs cl1) (Quantified _ cl2) = maybe False (const True) $ soleElement (findFold cl2 m)+    where m = insertFold emptyAlphaEnv bs cl1 () CLMEmpty++-- | Determine if the right Quantified is a substitution+-- instance of the left Quantified (which is a pattern+-- with a given set of holes).+lemmaMatch :: [Var] -> Quantified -> Quantified -> Maybe (VarEnv CoreExpr)+lemmaMatch hs ql qr = fmap fst $ soleElement (findFold qr m)+    where m = insertFold emptyAlphaEnv hs ql () emptyQMapWrapper++------------------------------------------------------------------------++data ListMap m a+  = ListMap { lmNil  :: Maybe a+            , lmCons :: m (ListMap m a) }++instance Fold m => Fold (ListMap m) where+    type Key (ListMap m) = [Key m]++    fEmpty :: ListMap m a+    fEmpty = ListMap Nothing fEmpty++    fAlter :: AlphaEnv -> [Var] -> Key (ListMap m) -> A a -> ListMap m a -> ListMap m a+    fAlter _   _  []     f m = m { lmNil  = f (lmNil m) }+    fAlter env vs (x:xs) f m = m { lmCons = fAlter env vs x (toA (fAlter env vs xs f)) (lmCons m) }++    fFold :: VarEnv CoreExpr -> AlphaEnv -> Key (ListMap m) -> ListMap m a -> [(VarEnv CoreExpr, a)]+    fFold hs _   []     m = maybeToList $ (hs,) <$> lmNil m+    fFold hs env (x:xs) m = do+        (hs', m') <- fFold hs env x (lmCons m)+        fFold hs' env xs m'++------------------------------------------------------------------------++-- Note [Alt Binders]+-- We don't store the uniques/types of the alt-binders, because they are+-- completely determined by the scrutinee/datacon/rhs.++data AMap a = AMEmpty+            | AM { amDef  :: EMap a+                 , amData :: NameEnv (EMap a) -- See Note [Alt Binders]+                 , amLit  :: LMap (EMap a) }++instance Fold AMap where+    type Key AMap = Alt CoreBndr++    fEmpty :: AMap a+    fEmpty = AMEmpty++    fAlter :: AlphaEnv -> [Var] -> Key AMap -> A a -> AMap a -> AMap a+    fAlter env vs alt f AMEmpty = fAlter env vs alt f (AM fEmpty emptyNameEnv M.empty)+    fAlter env vs alt f m@AM{} = go alt+        where go (DEFAULT  , _ , rhs) = m { amDef  = fAlter env vs rhs f (amDef m) }+              go (DataAlt d, bs, rhs) = m { amData = alterNameEnv+                                                        (toA (fAlter (foldr extendAlphaEnv env bs) (vs \\ bs) rhs f))+                                                        (amData m) (getName d) }+              go (LitAlt l , _ , rhs) = m { amLit  = M.alter (toA (fAlter env vs rhs f)) l (amLit m) }++    fFold :: VarEnv CoreExpr -> AlphaEnv -> Key AMap -> AMap a -> [(VarEnv CoreExpr, a)]+    fFold _ _ _ AMEmpty = []+    fFold hs env alt m@AM{} = go alt+        where go (DEFAULT  , _ , rhs) = fFold hs env rhs (amDef m)+              go (DataAlt d, bs, rhs) = do+                m' <- maybeToList (lookupNameEnv (amData m) (getName d))+                fFold hs (foldr extendAlphaEnv env bs) rhs m'+              go (LitAlt l , _ , rhs) = maybeToList (M.lookup l (amLit m)) >>= fFold hs env rhs++----------------------------------------------------------------------------++data QMap a = QM { qmap :: CLMap (ListMap BMap a) }++emptyQMapWrapper :: QMap a+emptyQMapWrapper = QM fEmpty++instance Fold QMap where+    type Key QMap = Quantified++    fEmpty :: QMap a+    fEmpty = emptyQMapWrapper++    fAlter :: AlphaEnv -> [Var] -> Key QMap -> A a -> QMap a -> QMap a+    fAlter env vs (Quantified bs cl) f m =+        m { qmap = fAlter (foldr extendAlphaEnv env bs) (vs \\ bs) cl+                          (toA (fAlter env vs (map varType bs) f)) (qmap m) }++    fFold :: VarEnv CoreExpr -> AlphaEnv -> Key QMap -> QMap a -> [(VarEnv CoreExpr, a)]+    fFold hs env (Quantified bs cl) m = do+        (hs', m') <- fFold hs (foldr extendAlphaEnv env bs) cl (qmap m)+        fFold hs' env (map varType bs) m'++----------------------------------------------------------------------------++data CLMap a = CLMEmpty+             | CLM { clmConj  :: QMap (QMap a)+                   , clmDisj  :: QMap (QMap a)+                   , clmImpl  :: QMap (QMap a)+                   , clmEquiv :: EMap (EMap a)+                   }++emptyCLMapWrapper :: CLMap a+emptyCLMapWrapper = CLM fEmpty fEmpty fEmpty fEmpty++instance Fold CLMap where+    type Key CLMap = Clause++    fEmpty :: CLMap a+    fEmpty = CLMEmpty++    fAlter :: AlphaEnv -> [Var] -> Key CLMap -> A a -> CLMap a -> CLMap a+    fAlter env vs cl f CLMEmpty = fAlter env vs cl f emptyCLMapWrapper+    fAlter env vs cl f m@(CLM{}) = go cl+        where go (Conj  q1 q2) = m { clmConj  = fAlter env vs q1 (toA (fAlter env vs q2 f)) (clmConj  m) }+              go (Disj  q1 q2) = m { clmDisj  = fAlter env vs q1 (toA (fAlter env vs q2 f)) (clmDisj  m) }+              go (Impl  q1 q2) = m { clmImpl  = fAlter env vs q1 (toA (fAlter env vs q2 f)) (clmImpl  m) }+              go (Equiv e1 e2) = m { clmEquiv = fAlter env vs e1 (toA (fAlter env vs e2 f)) (clmEquiv m) }++    fFold :: VarEnv CoreExpr -> AlphaEnv -> Key CLMap -> CLMap a -> [(VarEnv CoreExpr, a)]+    fFold _  _   _  CLMEmpty = []+    fFold hs env cl m@CLM{}  = go cl+        where go (Conj q1 q2) = do+                (hs', m') <- fFold hs env q1 (clmConj m)+                fFold hs' env q2 m'+              go (Disj q1 q2) = do+                (hs', m') <- fFold hs env q1 (clmDisj m)+                fFold hs' env q2 m'+              go (Impl q1 q2) = do+                (hs', m') <- fFold hs env q1 (clmImpl m)+                fFold hs' env q2 m'+              go (Equiv e1 e2) = do+                (hs', m') <- fFold hs env e1 (clmEquiv m)+                fFold hs' env e2 m'++----------------------------------------------------------------------------++-- | An equality is represented as a set of universally quantified binders, and the LHS and RHS of the equality.+data Equality = Equality [CoreBndr] CoreExpr CoreExpr++-- | Build an equality from a list of universally quantified binders and two expressions.+-- If the head of either expression is a lambda expression, it's binder will become a universally quantified binder+-- over both sides. It is assumed the two expressions have the same type.+--+-- Ex.    mkEquality [] (\x. foo x) bar === forall x. foo x = bar x+--        mkEquality [] (baz y z) (\x. foo x x) === forall x. baz y z x = foo x x+--        mkEquality [] (\x. foo x) (\y. bar y) === forall x. foo x = bar x+mkEquality :: [CoreBndr] -> CoreExpr -> CoreExpr -> Equality+mkEquality vs lhs rhs = case mkQuantified vs lhs rhs of+                            Quantified vs' (Equiv lhs' rhs') -> Equality vs' lhs' rhs'++toEqualities :: Quantified -> [Equality]+toEqualities = go []+    where go qs (Quantified vs cl) = go2 (qs++vs) cl++          go2 qs (Equiv e1 e2) = [mkEquality qs e1 e2]+          go2 qs (Conj q1 q2)  = go qs q1 ++ go qs q2+          go2 _  _             = []++ppEqualityT :: PrettyPrinter -> PrettyH Equality+ppEqualityT pp = do+    Equality bs lhs rhs <- idR+    dfa <- return bs >>> pForall pp+    d1 <- return lhs >>> extractT (pCoreTC pp)+    d2 <- return rhs >>> extractT (pCoreTC pp)+    return $ PP.sep [dfa,d1,PP.text "=",d2]++------------------------------------------------------------------------------++-- | Flip the LHS and RHS of a 'Equality'.+flipEquality :: Equality -> Equality+flipEquality (Equality xs lhs rhs) = Equality xs rhs lhs++------------------------------------------------------------------------------++{-+-- Idea: use Haskell's functions to fill the holes automagically+--+-- plusId <- findIdT "+"+-- timesId <- findIdT "*"+-- mkEquality $ \ x -> ( mkCoreApps (Var plusId)  [x,x]+--                     , mkCoreApps (Var timesId) [Lit 2, x])+--+-- TODO: need to know type of 'x' to generate a variable.+class BuildEquality a where+    mkEquality :: a -> HermitM Equality++instance BuildEquality (CoreExpr,CoreExpr) where+    mkEquality :: (CoreExpr,CoreExpr) -> HermitM Equality+    mkEquality (lhs,rhs) = return $ Equality [] lhs rhs++instance BuildEquality a => BuildEquality (CoreExpr -> a) where+    mkEquality :: (CoreExpr -> a) -> HermitM Equality+    mkEquality f = do+        x <- newIdH "x" (error "need to create a type")+        Equality bnds lhs rhs <- mkEquality (f (varToCoreExpr x))+        return $ Equality (x:bnds) lhs rhs+-}++------------------------------------------------------------------------------++freeVarsEquality :: Equality -> VarSet+freeVarsEquality (Equality bs lhs rhs) =+    delVarSetList (unionVarSets (map freeVarsExpr [lhs,rhs])) bs++------------------------------------------------------------------------------++data RewriteEqualityBox = RewriteEqualityBox (RewriteH Equality) deriving Typeable++instance Extern (RewriteH Equality) where+    type Box (RewriteH Equality) = RewriteEqualityBox+    box = RewriteEqualityBox+    unbox (RewriteEqualityBox r) = r++-----------------------------------------------------------------++data TransformEqualityStringBox = TransformEqualityStringBox (TransformH Equality String) deriving Typeable++instance Extern (TransformH Equality String) where+    type Box (TransformH Equality String) = TransformEqualityStringBox+    box = TransformEqualityStringBox+    unbox (TransformEqualityStringBox t) = t++-----------------------------------------------------------------++data TransformEqualityUnitBox = TransformEqualityUnitBox (TransformH Equality ()) deriving Typeable++instance Extern (TransformH Equality ()) where+    type Box (TransformH Equality ()) = TransformEqualityUnitBox+    box = TransformEqualityUnitBox+    unbox (TransformEqualityUnitBox i) = i
src/HERMIT/Dictionary/Function.hs view
@@ -2,7 +2,8 @@ module HERMIT.Dictionary.Function     ( externals     , appArgM-    , buildApplicationM+    , buildAppM+    , buildAppsM     , buildCompositionT     , buildFixT     , buildIdT@@ -13,6 +14,7 @@     ) where  import Control.Arrow+import Control.Monad import Control.Monad.IO.Class  import Data.List (nub, intercalate, intersect, partition, transpose)@@ -28,15 +30,14 @@ import HERMIT.Name  import HERMIT.Dictionary.Common-import HERMIT.Dictionary.GHC hiding (externals)  externals ::  [External] externals =-    [ external "static-arg" (promoteDefR staticArgR :: RewriteH Core)+    [ external "static-arg" (promoteDefR staticArgR :: RewriteH LCore)         [ "perform the static argument transformation on a recursive function." ]-    , external "static-arg-types" (promoteDefR staticArgTypesR :: RewriteH Core)+    , external "static-arg-types" (promoteDefR staticArgTypesR :: RewriteH LCore)         [ "perform the static argument transformation on a recursive function, only transforming type arguments." ]-    , external "static-arg-pos" (promoteDefR . staticArgPosR :: [Int] -> RewriteH Core)+    , external "static-arg-pos" (promoteDefR . staticArgPosR :: [Int] -> RewriteH LCore)         [ "perform the static argument transformation on a recursive function, only transforming the arguments specified (by index)." ]     ] @@ -131,29 +132,25 @@                              else return $ l !! n  -- | Build composition of two functions.-buildCompositionT :: (BoundVars c, HasDynFlags m, HasHermitMEnv m, HasHscEnv m, MonadCatch m, MonadIO m, MonadThings m)+buildCompositionT :: (BoundVars c, HasHermitMEnv m, HasHscEnv m, MonadCatch m, MonadIO m, MonadThings m)                   => CoreExpr -> CoreExpr -> Transform c m x CoreExpr buildCompositionT f g = do     composeId <- findIdT $ fromString "Data.Function.."-    fDot <- buildApplicationM (varToCoreExpr composeId) f-    buildApplicationM fDot g+    fDot <- prefixFailMsg "building (.) f failed:" $ buildAppM (varToCoreExpr composeId) f+    prefixFailMsg "building f . g failed:" $ buildAppM fDot g +buildAppsM :: MonadCatch m => CoreExpr -> [CoreExpr] -> m CoreExpr+buildAppsM = foldM buildAppM+ -- | Given expression for f and for x, build f x, figuring out the type arguments.-buildApplicationM :: (HasDynFlags m, MonadCatch m, MonadIO m) => CoreExpr -> CoreExpr -> m CoreExpr-buildApplicationM f x = do+buildAppM :: MonadCatch m => CoreExpr -> CoreExpr -> m CoreExpr+buildAppM f x = do     (vsF, domF, _) <- splitFunTypeM (exprType f)     let (vsX, xTy) = splitForAllTys (exprType x)         allTvs = vsF ++ vsX         bindFn v = if v `elem` allTvs then BindMe else Skolem -    sub <- maybe (do d <- getDynFlags-                     liftIO $ putStrLn $ "f: " ++ showPpr d f-                     liftIO $ putStrLn $ "x: " ++ showPpr d x-                     liftIO $ putStrLn $ "vsF: " ++ showPpr d vsF-                     liftIO $ putStrLn $ "domF: " ++ showPpr d domF-                     liftIO $ putStrLn $ "vsX: " ++ showPpr d vsX-                     liftIO $ putStrLn $ "xTy: " ++ showPpr d xTy-                     fail "buildApplicationM - domain of f and type of x do not unify")+    sub <- maybe (fail "buildAppM - domain of f and type of x do not unify")                  return                  (tcUnifyTys bindFn [domF] [xTy]) 
src/HERMIT/Dictionary/GHC.hs view
@@ -1,18 +1,18 @@ {-# LANGUAGE CPP, FlexibleContexts #-} module HERMIT.Dictionary.GHC     ( -- * GHC-based Transformations-     -- | This module contains transformations that are reflections of GHC functions, or derived from GHC functions.-     externals-     -- ** Substitution+      -- | This module contains transformations that are reflections of GHC functions, or derived from GHC functions.+      externals+      -- ** Dynamic Loading+    , loadLemmaLibraryT+    , LemmaLibrary+      -- ** Substitution     , substR-    , substCoreAlt-    , substCoreExpr-     -- ** Utilities-    --      , inScope+      -- ** Utilities     , dynFlagsT     , arityOf-     -- ** Lifted GHC capabilities-     -- A zombie is an identifer that has 'OccInfo' 'IAmDead', but still has occurrences.+      -- ** Lifted GHC capabilities+      -- A zombie is an identifer that has 'OccInfo' 'IAmDead', but still has occurrences.     , lintExprT     , lintModuleT     , occurAnalyseR@@ -33,13 +33,15 @@  import           Data.Char (isSpace) import           Data.List (mapAccumL)+import qualified Data.Map as M+import           Data.String  import           HERMIT.Core import           HERMIT.Context-import           HERMIT.Dictionary.Debug hiding (externals) import           HERMIT.External import           HERMIT.GHC import           HERMIT.Kure+import           HERMIT.Lemma import           HERMIT.Monad import           HERMIT.Name @@ -48,21 +50,23 @@ -- | Externals that reflect GHC functions, or are derived from GHC functions. externals :: [External] externals =-         [ external "deshadow-prog" (promoteProgR deShadowProgR :: RewriteH Core)-                [ "Deshadow a program." ] .+ Deep-         , external "dezombify" (promoteExprR dezombifyR :: RewriteH Core)-                [ "Zap the occurrence information in the current identifer if it is a zombie."] .+ Shallow-         , external "occurrence-analysis" (occurrenceAnalysisR :: RewriteH Core)-                [ "Perform dependency analysis on all sub-expressions; simplifying and updating identifer info."] .+ Deep-         , external "lint-expr" (promoteExprT lintExprT :: TransformH CoreTC String)-                [ "Runs GHC's Core Lint, which typechecks the current expression."-                , "Note: this can miss several things that a whole-module core lint will find."-                , "For instance, running this on the RHS of a binding, the type of the RHS will"-                , "not be checked against the type of the binding. Running on the whole let expression"-                , "will catch that however."] .+ Deep .+ Debug .+ Query-         , external "lint-module" (promoteModGutsT lintModuleT :: TransformH CoreTC String)-                [ "Runs GHC's Core Lint, which typechecks the current module."] .+ Deep .+ Debug .+ Query-         ]+    [ external "deshadow-prog" (promoteProgR deShadowProgR :: RewriteH LCore)+        [ "Deshadow a program." ] .+ Deep+    , external "dezombify" (promoteExprR dezombifyR :: RewriteH LCore)+        [ "Zap the occurrence information in the current identifer if it is a zombie."] .+ Shallow+    , external "occurrence-analysis" (occurrenceAnalysisR :: RewriteH LCore)+        [ "Perform dependency analysis on all sub-expressions; simplifying and updating identifer info."] .+ Deep+    , external "lint-expr" (promoteExprT lintExprT :: TransformH LCoreTC String)+        [ "Runs GHC's Core Lint, which typechecks the current expression."+        , "Note: this can miss several things that a whole-module core lint will find."+        , "For instance, running this on the RHS of a binding, the type of the RHS will"+        , "not be checked against the type of the binding. Running on the whole let expression"+        , "will catch that however."] .+ Deep .+ Debug .+ Query+    , external "lint-module" (promoteModGutsT lintModuleT :: TransformH LCoreTC String)+        [ "Runs GHC's Core Lint, which typechecks the current module."] .+ Deep .+ Debug .+ Query+    , external "load-lemma-library" (loadLemmaLibraryT :: HermitName -> TransformH LCore ())+        [ "Dynamically load a library of lemmas." ]+    ]  ------------------------------------------------------------------------ @@ -71,16 +75,6 @@ substR v e = setFailMsg "Can only perform substitution on expressions, case alternatives or programs." $              promoteExprR (arr $ substCoreExpr v e) <+ promoteProgR (substTopBindR v e) <+ promoteAltR (arr $ substCoreAlt v e) --- | Substitute all occurrences of a variable with an expression, in an expression.-substCoreExpr :: Var -> CoreExpr -> (CoreExpr -> CoreExpr)-substCoreExpr v e 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 (localFreeVarsExpr (Let (NonRec v e) expr)))-     in substExpr (text "substCoreExpr") (extendSubst emptySub v e) expr- -- | Substitute all occurrences of a variable with an expression, in a program. substTopBindR :: Monad m => Var -> CoreExpr -> Rewrite c m CoreProg substTopBindR v e =  contextfreeT $ \ p -> do@@ -88,14 +82,6 @@     let emptySub =  emptySubst -- mkEmptySubst (mkInScopeSet (exprFreeVars exp))     return $ bindsToProg $ snd (mapAccumL substBind (extendSubst emptySub v e) (progToBinds p)) --- | Substitute all occurrences of a variable with an expression, in a case alternative.-substCoreAlt :: Var -> CoreExpr -> CoreAlt -> CoreAlt-substCoreAlt v e alt = let (con, vs, rhs) = alt-                           inS            = (flip delVarSet v . unionVarSet (localFreeVarsExpr e) . localFreeVarsAlt) alt-                           subst          = extendSubst (mkEmptySubst (mkInScopeSet inS)) v e-                           (subst', vs')  = substBndrs subst vs-                        in (con, vs', substExpr (text "alt-rhs") subst' rhs)- ------------------------------------------------------------------------  -- | [from GHC documentation] De-shadowing the program is sometimes a useful pre-pass.@@ -134,7 +120,7 @@          dumpSDocs endMsg = Bag.foldBag (\ d r -> d ++ ('\n':r)) (showSDoc dynFlags) endMsg      if Bag.isEmptyBag errs        then return $ dumpSDocs "Core Lint Passed" warns-       else observeR (dumpSDocs "" errs) >>> fail "Core Lint Failed"+       else fail $ "Core Lint Failed:\n" ++ dumpSDocs "" errs  -- | Note: this can miss several things that a whole-module core lint will find. -- For instance, running this on the RHS of a binding, the type of the RHS will@@ -164,7 +150,7 @@ dezombifyR = varR (acceptR isDeadBinder >>^ zapVarOccInfo)  -- | Apply 'occurAnalyseExprR' to all sub-expressions.-occurAnalyseR :: (AddBindings c, ExtendPath c Crumb, ReadPath c Crumb, HasEmptyContext c, MonadCatch m) => Rewrite c m Core+occurAnalyseR :: (AddBindings c, ExtendPath c Crumb, ReadPath c Crumb, HasEmptyContext c, MonadCatch m, Walker c u, Injection CoreExpr u) => Rewrite c m u occurAnalyseR = let r  = promoteExprR (arr occurAnalyseExpr_NoBinderSwap) -- See Note [No Binder Swap]                     go = r <+ anyR go                  in tryR go -- always succeed@@ -184,14 +170,14 @@ occurAnalyseExprChangedR = changedByR exprSyntaxEq (arr occurAnalyseExpr_NoBinderSwap) -- See Note [No Binder Swap]  -- | Occurrence analyse all sub-expressions, failing if the result is syntactically equal to the initial expression.-occurAnalyseChangedR :: (AddBindings c, ExtendPath c Crumb, ReadPath c Crumb, HasEmptyContext c, MonadCatch m) => Rewrite c m Core-occurAnalyseChangedR = changedByR coreSyntaxEq occurAnalyseR+occurAnalyseChangedR :: (AddBindings c, ExtendPath c Crumb, ReadPath c Crumb, HasEmptyContext c, MonadCatch m) => Rewrite c m LCore+occurAnalyseChangedR = changedByR lcoreSyntaxEq occurAnalyseR  -- | Run GHC's occurrence analyser, and also eliminate any zombies.-occurAnalyseAndDezombifyR :: (AddBindings c, ExtendPath c Crumb, ReadPath c Crumb, HasEmptyContext c, MonadCatch m) => Rewrite c m Core+occurAnalyseAndDezombifyR :: (AddBindings c, ExtendPath c Crumb, ReadPath c Crumb, HasEmptyContext c, MonadCatch m, Walker c u, Injection CoreExpr u) => Rewrite c m u occurAnalyseAndDezombifyR = allbuR (tryR $ promoteExprR dezombifyR) >>> occurAnalyseR -occurrenceAnalysisR :: (AddBindings c, ExtendPath c Crumb, ReadPath c Crumb, HasEmptyContext c, MonadCatch m) => Rewrite c m Core+occurrenceAnalysisR :: (AddBindings c, ExtendPath c Crumb, ReadPath c Crumb, HasEmptyContext c, MonadCatch m, Walker c LCore) => Rewrite c m LCore occurrenceAnalysisR = occurAnalyseAndDezombifyR  {- Does not work (no export)@@ -224,7 +210,8 @@             nonC = mkNonCanonical $ CtWanted { ctev_pred = predTy, ctev_evar = evar, ctev_loc = loc }             wCs = mkFlatWC [nonC]         (wCs', bnds) <- solveWantedsTcM wCs-        reportAllUnsolved wCs'+        -- reportAllUnsolved wCs' -- this is causing a panic with dictionary instantiation+                                  -- revist and fix!         return (evar, bnds)     bnds <- runDsM $ dsEvBinds bs     return (i,bnds)@@ -239,3 +226,42 @@     return $ case bnds of                 [NonRec v e] | i == v -> e -- the common case that we would have gotten a single non-recursive let                 _ -> mkCoreLets bnds (varToCoreExpr i)++-- | A LemmaLibrary is a transformation that produces a set of lemmas,+-- which are then added to the lemma store. It is not allowed to insert+-- its own lemmas directly (if it tries they are throw away), but can+-- certainly read the existing store.+type LemmaLibrary = TransformH () Lemmas++loadLemmaLibraryT :: HermitName -> TransformH x ()+loadLemmaLibraryT nm = contextonlyT $ \ c -> do+    hscEnv <- getHscEnv+    comp <- liftAndCatchIO $ loadLemmaLibrary hscEnv nm+    m' <- applyT comp c () -- TODO: discard side effects+    m <- getLemmas+    putLemmas $ m' `M.union` m++loadLemmaLibrary :: HscEnv -> HermitName -> IO LemmaLibrary+loadLemmaLibrary hscEnv hnm = do+    name <- lookupHermitNameForPlugins hscEnv varNS hnm+    lib_tycon_name <- lookupHermitNameForPlugins hscEnv tyConClassNS $ fromString "HERMIT.Dictionary.GHC.LemmaLibrary"+    lib_tycon <- forceLoadTyCon hscEnv lib_tycon_name+    mb_v <- getValueSafely hscEnv name $ mkTyConTy lib_tycon+    let dflags = hsc_dflags hscEnv+    maybe (fail $ showSDoc dflags $ hsep+                [ ptext (sLit "The value"), ppr name+                , ptext (sLit "did not have the type")+                , ppr lib_tycon, ptext (sLit "as required.")])+          return mb_v++lookupHermitNameForPlugins :: HscEnv -> NameSpace -> HermitName -> IO Name+lookupHermitNameForPlugins hscEnv ns hnm = do+    modName <- maybe (fail "name must be fully qualified with module name.") return (hnModuleName hnm)+    let dflags = hsc_dflags hscEnv+        rdrName = toRdrName ns hnm+    mbName <- lookupRdrNameInModuleForPlugins hscEnv modName rdrName+    maybe (fail $ showSDoc dflags $ hsep+            [ ptext (sLit "The module"), ppr modName+            , ptext (sLit "did not export the name")+            , ppr rdrName ])+          return mbName
src/HERMIT/Dictionary/Induction.hs view
@@ -3,26 +3,20 @@ module HERMIT.Dictionary.Induction   ( -- * Induction     inductionCaseSplit---  , inductionOnT---  , listInductionOnT   ) where  import Control.Arrow --- import Data.List (delete)- import HERMIT.Context import HERMIT.Core import HERMIT.GHC import HERMIT.Kure import HERMIT.Monad import HERMIT.Name--- import HERMIT.Utilities (soleElement)  import HERMIT.Dictionary.Common import HERMIT.Dictionary.Local.Case (caseSplitInlineR)--- import HERMIT.Dictionary.Reasoning import HERMIT.Dictionary.Undefined  ------------------------------------------------------------------------------@@ -44,7 +38,7 @@         -- then case split on the identifier, inlining the pattern        -- we consider the other universally quantified variables to be in scope while doing so-       Case _ _ _ alts <- withVarsInScope vs (caseSplitInlineR (==i)) <<< return contrivedExpr+       Case _ _ _ alts <- withVarsInScope vs (caseSplitInlineR (varToCoreExpr i)) <<< return contrivedExpr        let dataConCases = map compressAlts alts         lhsUndefined <- extractR (replaceIdWithUndefinedR i) <<< return lhsE@@ -60,46 +54,3 @@     compressAlts _ = error "Bug in inductionCaseSplit"  --- NOTE: Most of the Induction infrastructure has moved to HERMIT/Shell/Proof.hs----- -- | A general induction principle.  TODO: Is this valid for infinite data types?  Probably not.--- inductionOnT :: forall c. (AddBindings c, ReadBindings c, ReadPath c Crumb, ExtendPath c Crumb, Walker c Core)---                     => (Id -> Bool) -> (DataCon -> [BiRewrite c HermitM CoreExpr] -> CoreExprEqualityProof c HermitM) -> Transform c HermitM CoreExprEquality ()--- inductionOnT idPred genCaseAltProofs = prefixFailMsg "Induction failed: " $---     do eq@(CoreExprEquality bs lhs rhs) <- idR----        i <- setFailMsg "specified identifier is not universally quantified in this equality lemma." $ soleElement (filter idPred bs)----        cases <- inductionCaseSplit bs i lhs rhs----        -- TODO: will this work if vs contains TyVars or CoVars?  Maybe we need to sort the Vars in order: TyVars; CoVars; Ids.---        let verifyInductiveCaseT :: (DataCon,[Var],CoreExpr,CoreExpr) -> Transform c HermitM x ()---            verifyInductiveCaseT (con,vs,lhsE,rhsE) =---                 let vs_matching_i_type = filter (typeAlphaEq (varType i) . varType) vs---                     eqs = [ discardUniVars (instantiateCoreExprEq [(i,Var i')] eq) | i' <- vs_matching_i_type ]---                     brs = map birewrite eqs -- These eqs now have no universally quantified variables.---                                             -- Thus they can only be used on variables in the induction hypothesis.---                                             -- TODO: consider whether this is unneccassarily restrictive---                     caseEq = CoreExprEquality (delete i bs ++ vs) lhsE rhsE---                 in return caseEq >>> verifyCoreExprEqualityT (genCaseAltProofs con brs)----        mapM_ verifyInductiveCaseT cases---- -- | An induction principle for lists.--- listInductionOnT :: (AddBindings c, ReadBindings c, ReadPath c Crumb, ExtendPath c Crumb, Walker c Core)---                 => (Id -> Bool) -- Id to case split on---                 -> CoreExprEqualityProof c HermitM -- proof for [] case---                 -> (BiRewrite c HermitM CoreExpr -> CoreExprEqualityProof c HermitM) -- proof for (:) case, given smaller proof---                 -> Transform c HermitM CoreExprEquality ()--- listInductionOnT idPred nilCaseProof consCaseProof = inductionOnT idPred $ \ con brs ->---                                                                 if | con == nilDataCon   -> case brs of---                                                                                                   [] -> nilCaseProof---                                                                                                   _  -> error "Bug!"---                                                                    | con == consDataCon  -> case brs of---                                                                                                   [br] -> consCaseProof br---                                                                                                   _    -> error "Bug!"---                                                                    | otherwise           -> let msg = "Mystery constructor, this is a bug."---                                                                                              in (fail msg, fail msg)--------------------------------------------------------------------------------
src/HERMIT/Dictionary/Inline.hs view
@@ -5,6 +5,7 @@     , InlineConfig(..)     , CaseBinderInlineOption(..)     , getUnfoldingT+    , getUnfoldingsT     , ensureBoundT     , inlineR     , inlineNameR@@ -33,16 +34,16 @@ -- | 'External's for inlining variables. externals :: [External] externals =-    [ external "inline" (promoteExprR inlineR :: RewriteH Core)+    [ external "inline" (promoteExprR inlineR :: RewriteH LCore)         [ "(Var v) ==> <defn of v>" ].+ Eval .+ Deep-    , external "inline" (promoteExprR . inlineMatchingPredR . mkOccPred :: OccurrenceName -> RewriteH Core)+    , external "inline" (promoteExprR . inlineMatchingPredR . mkOccPred :: OccurrenceName -> RewriteH LCore)         [ "Given a specific v, (Var v) ==> <defn of v>" ] .+ Eval .+ Deep-    , external "inline" (promoteExprR . inlineNamesR :: [String] -> RewriteH Core)+    , external "inline" (promoteExprR . inlineNamesR :: [String] -> RewriteH LCore)         [ "If the current variable matches any of the given names, then inline it." ] .+ Eval .+ Deep-    , external "inline-case-scrutinee" (promoteExprR inlineCaseScrutineeR :: RewriteH Core)+    , external "inline-case-scrutinee" (promoteExprR inlineCaseScrutineeR :: RewriteH LCore)         [ "if v is a case binder, replace (Var v) with the bound case scrutinee." ] .+ Eval .+ Deep-    , external "inline-case-alternative" (promoteExprR inlineCaseAlternativeR :: RewriteH Core)-        [ "if v is a case binder, replace (Var v) with the bound case-alternative pattern." ] .+ Eval .+ Deep .+ Unsafe+    , external "inline-case-alternative" (promoteExprR inlineCaseAlternativeR :: RewriteH LCore)+        [ "if v is a case binder, replace (Var v) with the bound case-alternative pattern." ] .+ Eval .+ Deep     ]  ------------------------------------------------------------------------@@ -142,7 +143,16 @@ getUnfoldingT :: (ReadBindings c, MonadCatch m)               => InlineConfig               -> Transform c m Id (CoreExpr, BindingDepth -> Bool)-getUnfoldingT config = transform $ \ c i ->+getUnfoldingT config = do+    r <- getUnfoldingsT config+    case r of+        [] -> fail "no unfolding for variable."+        (u:_) -> return u++getUnfoldingsT :: (ReadBindings c, MonadCatch m)+               => InlineConfig+               -> Transform c m Id [(CoreExpr, BindingDepth -> Bool)]+getUnfoldingsT config = transform $ \ c i ->     case lookupHermitBinding i c of       Nothing -> do requireAllBinders config                     let uncaptured = (<= 0) -- i.e. is global@@ -151,34 +161,38 @@                     -- will give a reasonable error message if something goes wrong, instead of a GHC panic.                     guardMsg (isId i) "type variable is not in Env (this should not happen)."                     case unfoldingInfo (idInfo i) of-                      CoreUnfolding { uf_tmpl = uft } -> return (uft, uncaptured)-                      dunf@(DFunUnfolding {})         -> liftM (,uncaptured) $ dFunExpr dunf+                      CoreUnfolding { uf_tmpl = uft } -> single (uft, uncaptured)+                      dunf@(DFunUnfolding {})         -> single . (,uncaptured) =<< dFunExpr dunf                       _                               -> fail $ "cannot find unfolding in Env or IdInfo."       Just b -> let depth = hbDepth b                 in case hbSite b of                           CASEBINDER s alt -> let tys             = tyConAppArgs (idType i)-                                                  altExprDepthM   = liftM (, (<= depth+1)) $ alt2Exp tys alt-                                                  scrutExprDepthM = return (s, (< depth))+                                                  altExprDepthM   = single . (, (<= depth+1)) =<< alt2Exp tys alt+                                                  scrutExprDepthM = single (s, (< depth))                                                in case config of                                                     CaseBinderOnly Scrutinee   -> scrutExprDepthM                                                     CaseBinderOnly Alternative -> altExprDepthM-                                                    AllBinders                 -> altExprDepthM <+ scrutExprDepthM+                                                    AllBinders                 -> do+                                                        au <- altExprDepthM <+ return []+                                                        su <- scrutExprDepthM+                                                        return $ au ++ su                            NONREC e         -> do requireAllBinders config-                                                 return (e, (< depth))+                                                 single (e, (< depth))                            REC e            -> do requireAllBinders config-                                                 return (e, (<= depth))+                                                 single (e, (<= depth))                            MUTUALREC e      -> do requireAllBinders config-                                                 return (e, (<= depth+1))+                                                 single (e, (<= depth+1))                            TOPLEVEL e       -> do requireAllBinders config-                                                 return (e, (<= depth)) -- Depth should always be 0 for top-level bindings.+                                                 single (e, (<= depth)) -- Depth should always be 0 for top-level bindings.                                                                         -- Any inlined variables should only refer to top-level bindings or global things, else they've been captured.                            _                -> fail "variable is not bound to an expression."   where+    single = return . (:[])     requireAllBinders :: Monad m => InlineConfig -> m ()     requireAllBinders AllBinders         = return ()     requireAllBinders (CaseBinderOnly _) = fail "not a case binder."@@ -196,12 +210,12 @@ alt2Exp :: Monad m => [Type] -> (AltCon,[Var]) -> m CoreExpr alt2Exp _   (DEFAULT   , _ ) = fail "DEFAULT alternative cannot be converted to an expression." alt2Exp _   (LitAlt l  , _ ) = return $ Lit l-alt2Exp tys (DataAlt dc, vs) = return $ mkCoreConApps dc (map Type tys ++ map (varToCoreExpr . zapVarOccInfo) vs)+alt2Exp tys (DataAlt dc, vs) = return $ mkDataConApp tys dc vs  -- | Get list of possible inline targets. Used by shell for completion. inlineTargetsT :: ( ExtendPath c Crumb, ReadPath c Crumb, AddBindings c                   , ReadBindings c, HasEmptyContext c, MonadCatch m )-               => Transform c m Core [String]+               => Transform c m LCore [String] inlineTargetsT = collectT $ promoteT $ whenM (testM inlineR) (varT $ arr unqualifiedName)  -- | Build a CoreExpr for a DFunUnfolding
src/HERMIT/Dictionary/Kure.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE FlexibleContexts, ScopedTypeVariables #-}+{-# LANGUAGE FlexibleContexts, ScopedTypeVariables, LambdaCase #-}  module HERMIT.Dictionary.Kure     ( -- * KURE Strategies@@ -21,95 +21,117 @@ -- | -- This list contains reflections of the KURE strategies as 'External's. externals :: [External] externals = map (.+ KURE)-   [ external "id"         (idR :: RewriteH Core)+   [ external "id"         (idR :: RewriteH LCore)        [ "Perform an identity rewrite."] .+ Shallow-   , external "success"    (successT :: TransformH Core ())+   , external "id"         (idR :: RewriteH LCoreTC)+       [ "Perform an identity rewrite."] .+ Shallow+   , external "success"    (successT :: TransformH LCore ())        [ "An always succeeding translation." ]-   , external "fail"       (fail :: String -> RewriteH Core)+   , external "fail"       (fail :: String -> RewriteH LCore)        [ "A failing rewrite."]-   , external "<+"         ((<+) :: RewriteH Core -> RewriteH Core -> RewriteH Core)+   , external "<+"         ((<+) :: RewriteH LCore -> RewriteH LCore -> RewriteH LCore)        [ "Perform the first rewrite, and then, if it fails, perform the second rewrite." ]-   , external "<+"         ((<+) :: TransformH Core () -> TransformH Core () -> TransformH Core ())+   , external "<+"         ((<+) :: TransformH LCore () -> TransformH LCore () -> TransformH LCore ())        [ "Perform the first check, and then, if it fails, perform the second check." ]-   , external ">>>"        ((>>>) :: RewriteH Core -> RewriteH Core -> RewriteH Core)+   , external ">>>"        ((>>>) :: RewriteH LCore -> RewriteH LCore -> RewriteH LCore)        [ "Compose rewrites, requiring both to succeed." ]-   , external ">>>"        ((>>>) :: BiRewriteH Core -> BiRewriteH Core -> BiRewriteH Core)+   , external ">>>"        ((>>>) :: BiRewriteH LCore -> BiRewriteH LCore -> BiRewriteH LCore)        [ "Compose bidirectional rewrites, requiring both to succeed." ]-   , external ">+>"        ((>+>) :: RewriteH Core -> RewriteH Core -> RewriteH Core)+   , external ">>>"        ((>>>) :: RewriteH LCoreTC -> RewriteH LCoreTC -> RewriteH LCoreTC)+       [ "Compose rewrites, requiring both to succeed." ]+   , external ">+>"        ((>+>) :: RewriteH LCore -> RewriteH LCore -> RewriteH LCore)        [ "Compose rewrites, allowing one to fail." ]-   , external "try"        (tryR :: RewriteH Core -> RewriteH Core)+   , external "try"        (tryR :: RewriteH LCore -> RewriteH LCore)        [ "Try a rewrite, and perform the identity if the rewrite fails." ]-   , external "repeat"     (repeatR :: RewriteH Core -> RewriteH Core)+   , external "repeat"     (repeatR :: RewriteH LCore -> RewriteH LCore)        [ "Repeat a rewrite until it would fail." ] .+ Loop-   , external "replicate"  ((\ n -> andR . replicate n)  :: Int -> RewriteH Core -> RewriteH Core)+   , external "replicate"  ((\ n -> andR . replicate n)  :: Int -> RewriteH LCore -> RewriteH LCore)        [ "Repeat a rewrite n times." ]-   , external "all"        (allR :: RewriteH Core -> RewriteH Core)+   , external "all"        (allR :: RewriteH LCore -> RewriteH LCore)        [ "Apply a rewrite to all children of the node, requiring success at every child." ] .+ Shallow-   , external "any"        (anyR :: RewriteH Core -> RewriteH Core)+   , external "any"        (anyR :: RewriteH LCore -> RewriteH LCore)        [ "Apply a rewrite to all children of the node, requiring success for at least one child." ] .+ Shallow-   , external "one"        (oneR :: RewriteH Core -> RewriteH Core)+   , external "one"        (oneR :: RewriteH LCore -> RewriteH LCore)        [ "Apply a rewrite to the first child of the node for which it can succeed." ] .+ Shallow-   , external "all-bu"     (allbuR :: RewriteH Core -> RewriteH Core)+   , external "all-bu"     (allbuR :: RewriteH LCore -> RewriteH LCore)        [ "Promote a rewrite to operate over an entire tree in bottom-up order, requiring success at every node." ] .+ Deep-   , external "all-td"     (alltdR :: RewriteH Core -> RewriteH Core)+   , external "all-td"     (alltdR :: RewriteH LCore -> RewriteH LCore)        [ "Promote a rewrite to operate over an entire tree in top-down order, requiring success at every node." ] .+ Deep-   , external "all-du"     (allduR :: RewriteH Core -> RewriteH Core)+   , external "all-du"     (allduR :: RewriteH LCore -> RewriteH LCore)        [ "Apply a rewrite twice, in a top-down and bottom-up way, using one single tree traversal,",          "succeeding if they all succeed."] .+ Deep-   , external "any-bu"     (anybuR :: RewriteH Core -> RewriteH Core)+   , external "any-bu"     (anybuR :: RewriteH LCore -> RewriteH LCore)        [ "Promote a rewrite to operate over an entire tree in bottom-up order, requiring success for at least one node." ] .+ Deep-   , external "any-td"     (anytdR :: RewriteH Core -> RewriteH Core)+   , external "any-td"     (anytdR :: RewriteH LCore -> RewriteH LCore)        [ "Promote a rewrite to operate over an entire tree in top-down order, requiring success for at least one node." ] .+ Deep-   , external "any-du"     (anyduR :: RewriteH Core -> RewriteH Core)+   , external "any-du"     (anyduR :: RewriteH LCore -> RewriteH LCore)        [ "Apply a rewrite twice, in a top-down and bottom-up way, using one single tree traversal,",          "succeeding if any succeed."] .+ Deep-   , external "one-td"     (onetdR :: RewriteH Core -> RewriteH Core)+   , external "one-td"     (onetdR :: RewriteH LCore -> RewriteH LCore)        [ "Apply a rewrite to the first node (in a top-down order) for which it can succeed." ] .+ Deep-   , external "one-bu"     (onebuR :: RewriteH Core -> RewriteH Core)+   , external "one-bu"     (onebuR :: RewriteH LCore -> RewriteH LCore)        [ "Apply a rewrite to the first node (in a bottom-up order) for which it can succeed." ] .+ Deep-   , external "prune-td"   (prunetdR :: RewriteH Core -> RewriteH Core)+   , external "prune-td"   (prunetdR :: RewriteH LCore -> RewriteH LCore)        [ "Attempt to apply a rewrite in a top-down manner, prunning at successful rewrites." ] .+ Deep-   , external "innermost"  (innermostR :: RewriteH Core -> RewriteH Core)+   , external "innermost"  (innermostR :: RewriteH LCore -> RewriteH LCore)        [ "A fixed-point traveral, starting with the innermost term." ] .+ Deep .+ Loop-   , external "focus"      (hfocusR :: TransformH CoreTC LocalPathH -> RewriteH CoreTC -> RewriteH CoreTC)+   , external "focus"      (hfocusR :: TransformH LCoreTC LocalPathH -> RewriteH LCoreTC -> RewriteH LCoreTC)        [ "Apply a rewrite to a focal point."] .+ Navigation .+ Deep-   , external "focus"      (hfocusT :: TransformH CoreTC LocalPathH -> TransformH CoreTC String -> TransformH CoreTC String)+   , external "focus"      (hfocusT :: TransformH LCoreTC LocalPathH -> TransformH LCoreTC String -> TransformH LCoreTC String)        [ "Apply a query at a focal point."] .+ Navigation .+ Deep-   , external "focus"      (hfocusR . return :: LocalPathH -> RewriteH CoreTC -> RewriteH CoreTC)+   , external "focus"      ((\p -> hfocusR (return p)) :: LocalPathH -> RewriteH LCoreTC -> RewriteH LCoreTC)        [ "Apply a rewrite to a focal point."] .+ Navigation .+ Deep-   , external "focus"      (hfocusT . return :: LocalPathH -> TransformH CoreTC String -> TransformH CoreTC String)+   , external "focus"      ((\p -> hfocusT (return p)) :: LocalPathH -> TransformH LCoreTC String -> TransformH LCoreTC String)        [ "Apply a query at a focal point."] .+ Navigation .+ Deep-   , external "when"       ((>>) :: TransformH Core () -> RewriteH Core -> RewriteH Core)+   , external "focus"      (hfocusR :: TransformH LCore LocalPathH -> RewriteH LCore -> RewriteH LCore)+       [ "Apply a rewrite to a focal point."] .+ Navigation .+ Deep+   , external "focus"      (hfocusT :: TransformH LCore LocalPathH -> TransformH LCore String -> TransformH LCore String)+       [ "Apply a query at a focal point."] .+ Navigation .+ Deep+   , external "focus"      ((\p -> hfocusR (return p)) :: LocalPathH -> RewriteH LCore -> RewriteH LCore)+       [ "Apply a rewrite to a focal point."] .+ Navigation .+ Deep+   , external "focus"      ((\p -> hfocusT (return p)) :: LocalPathH -> TransformH LCore String -> TransformH LCore String)+       [ "Apply a query at a focal point."] .+ Navigation .+ Deep+   , external "when"       ((>>) :: TransformH LCore () -> RewriteH LCore -> RewriteH LCore)        [ "Apply a rewrite only if the check succeeds." ] .+ Predicate-   , external "not"        (notM :: TransformH Core () -> TransformH Core ())+   , external "not"        (notM :: TransformH LCore () -> TransformH LCore ())        [ "Cause a failing check to succeed, a succeeding check to fail." ] .+ Predicate-   , external "invert"     (invertBiT :: BiRewriteH Core -> BiRewriteH Core)+   , external "invert"     (invertBiT :: BiRewriteH LCore -> BiRewriteH LCore)        [ "Reverse a bidirectional rewrite." ]-   , external "forward"    (forwardT :: BiRewriteH Core -> RewriteH Core)+   , external "forward"    (forwardT :: BiRewriteH LCore -> RewriteH LCore)        [ "Apply a bidirectional rewrite forewards." ]-   , external "backward"   (backwardT :: BiRewriteH Core -> RewriteH Core)+   , external "backward"   (backwardT :: BiRewriteH LCore -> RewriteH LCore)        [ "Apply a bidirectional rewrite backwards." ]-   , external "test"       (testQuery :: RewriteH Core -> TransformH Core String)+   , external "test"       (testQuery :: RewriteH LCore -> TransformH LCore String)        [ "Determine if a rewrite could be successfully applied." ]-   , external "any-call"   (anyCallR :: RewriteH Core -> RewriteH Core)+   , external "any-call"   (anyCallR_LCore :: RewriteH LCore -> RewriteH LCore)        [ "any-call (.. unfold command ..) applies an unfold command to all applications."        , "Preference is given to applications with more arguments." ] .+ Deep-   , external "promote"    (promoteR :: RewriteH Core -> RewriteH CoreTC)+   , external "promote"    (promoteR :: RewriteH LCore -> RewriteH LCoreTC)        [ "Promote a RewriteCore to a RewriteCoreTC" ]-   , external "extract"    (extractR :: RewriteH CoreTC -> RewriteH Core)+   , external "extract"    (extractR :: RewriteH LCoreTC -> RewriteH LCore)        [ "Extract a RewriteCore from a RewriteCoreTC" ]-   , external "between"    (betweenR :: Int -> Int -> RewriteH CoreTC -> RewriteH CoreTC)+   , external "extract"    (extractT :: TransformH LCoreTC String -> TransformH LCore String)+       [ "Extract a TransformLCoreString from a TransformLCoreTCString" ]+   , external "between"    (betweenR :: Int -> Int -> RewriteH LCoreTC -> RewriteH LCoreTC)        [ "between x y rr -> perform rr at least x times and at most y times." ]+   , external "atPath"     (flip hfocusT idR :: TransformH LCore LocalPathH -> TransformH LCore LCore)+       [ "return the expression found at the given path" ]+   , external "atPath"     (flip hfocusT idR :: TransformH LCoreTC LocalPathH -> TransformH LCoreTC LCoreTC)+       [ "return the expression found at the given path" ]+   , external "atPath"     (extractT . flip hfocusT projectT :: TransformH LCoreTC LocalPathH -> TransformH LCore LCore)+       [ "return the expression found at the given path" ]    ]  ------------------------------------------------------------------------------------ -hfocusR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, HasEmptyContext c, MonadCatch m) => Transform c m CoreTC LocalPathH -> Rewrite c m CoreTC -> Rewrite c m CoreTC+hfocusR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, HasEmptyContext c, Walker c u, MonadCatch m)+        => Transform c m u LocalPathH -> Rewrite c m u -> Rewrite c m u hfocusR tp r = do lp <- tp                   localPathR lp r {-# INLINE hfocusR #-} -hfocusT :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, HasEmptyContext c, MonadCatch m) => Transform c m CoreTC LocalPathH -> Transform c m CoreTC String -> Transform c m CoreTC String+hfocusT :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, HasEmptyContext c, Walker c u, MonadCatch m)+        => Transform c m u LocalPathH -> Transform c m u b -> Transform c m u b hfocusT tp t = do lp <- tp                   localPathT lp t {-# INLINE hfocusT #-}@@ -131,13 +153,24 @@ anyCallR :: forall c m. (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, HasEmptyContext c, MonadCatch m)          => Rewrite c m Core -> Rewrite c m Core anyCallR rr = prefixFailMsg "any-call failed: " $-              readerT $ \ e -> case e of-        ExprCore (App {}) -> childR App_Arg rec >+> (rr <+ childR App_Fun rec)-        ExprCore (Var {}) -> rr-        _                 -> anyR rec-    where rec :: Rewrite c m Core-          rec = anyCallR rr+              readerT $ \case+                           ExprCore (App {}) -> childR App_Arg (anyCallR rr)+                                                >+> (rr <+ childR App_Fun (anyCallR rr))+                           ExprCore (Var {}) -> rr+                           _                 -> anyR (anyCallR rr) +-- | Top-down traversal tuned to matching function calls.+anyCallR_LCore :: forall c m. (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, HasEmptyContext c, MonadCatch m)+         => Rewrite c m LCore -> Rewrite c m LCore+anyCallR_LCore rr = prefixFailMsg "any-call failed: " $+              readerT $ \case+                           LCore (ExprCore (App {})) ->     childR App_Arg (anyCallR_LCore rr)+                                                        >+> (rr <+ childR App_Fun (anyCallR_LCore rr))+                           LCore (ExprCore (Var {})) -> rr+                           _                         -> anyR (anyCallR_LCore rr)++-- TODO: sort out this duplication+ ------------------------------------------------------------------------------------  -- | betweenR x y rr -> perform rr at least x times and at most y times.@@ -150,3 +183,4 @@                | c < l  = rr >>> go (c+1)   -- haven't hit lower bound yet                | otherwise = tryR (rr >>> go (c+1))  -- met lower bound +------------------------------------------------------------------------------------
src/HERMIT/Dictionary/Local.hs view
@@ -34,7 +34,6 @@ import HERMIT.Utilities  import HERMIT.Dictionary.Common-import HERMIT.Dictionary.GHC (substCoreExpr) import HERMIT.Dictionary.Local.Bind hiding (externals) import qualified HERMIT.Dictionary.Local.Bind as Bind import HERMIT.Dictionary.Local.Case hiding (externals)@@ -52,31 +51,31 @@ --   (Many taken from Chapter 3 of Andre Santos' dissertation.) externals :: [External] externals =-    [ external "beta-reduce" (promoteExprR betaReduceR :: RewriteH Core)+    [ external "beta-reduce" (promoteExprR betaReduceR :: RewriteH LCore)         [ "((\\ 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-expand" (promoteExprR betaExpandR :: RewriteH Core)+    , external "beta-expand" (promoteExprR betaExpandR :: RewriteH LCore)         [ "(let v = e1 in e2) ==> (\\ v -> e2) e1" ]                            .+ Shallow-    , external "eta-reduce" (promoteExprR etaReduceR :: RewriteH Core)+    , external "eta-reduce" (promoteExprR etaReduceR :: RewriteH LCore)         [ "(\\ v -> e1 v) ==> e1" ]                                             .+ Eval .+ Shallow-    , external "eta-expand" (promoteExprR . etaExpandR :: String -> RewriteH Core)+    , external "eta-expand" (promoteExprR . etaExpandR :: String -> RewriteH LCore)         [ "\"eta-expand 'v\" performs e1 ==> (\\ v -> e1 v)" ]                  .+ Shallow .+ Introduce-    , external "flatten-module" (promoteModGutsR flattenModuleR :: RewriteH Core)+    , external "flatten-module" (promoteModGutsR flattenModuleR :: RewriteH LCore)         [ "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)+    , external "flatten-program" (promoteProgR flattenProgramR :: RewriteH LCore)         [ "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 apply GHC RULES." ]-    , external "abstract" (promoteExprR . abstractR . mkOccPred :: OccurrenceName -> RewriteH Core)+    , external "abstract" (promoteExprR . abstractR . mkOccPred :: OccurrenceName -> RewriteH LCore)         [ "Abstract over a variable using a lambda."         , "e  ==>  (\\ x -> e) x" ]                                             .+ Shallow .+ Introduce .+ Context-    , external "push" ((\ nm strictf -> push (Just strictf) (cmpString2Var nm)) :: String -> RewriteH Core -> RewriteH Core)+    , external "push" ((\ nm strictf -> push (Just strictf) (cmpString2Var nm)) :: String -> RewriteH LCore -> RewriteH LCore)         [ "Push a function 'f into a case-expression or let-expression argument,"         , "given a proof that f (fully saturated with type arguments) is strict." ] .+ Shallow .+ Commute-    , external "push-unsafe" (push Nothing . cmpString2Var :: String -> RewriteH Core)+    , external "push-unsafe" (push Nothing . cmpString2Var :: String -> RewriteH LCore)         [ "Push a function 'f into a case-expression or let-expression argument."-        , "Requires 'f to be strict." ] .+ Shallow .+ Commute .+ PreCondition+        , "Requires 'f to be strict." ] .+ Shallow .+ Commute .+ PreCondition .+ Unsafe     ]     ++ Bind.externals     ++ Case.externals@@ -163,9 +162,9 @@  ------------------------------------------------------------------------------------------------------ -push :: Maybe (RewriteH Core) -- ^ a proof that the function (after being applied to its type arguments) is strict+push :: Maybe (RewriteH LCore) -- ^ a proof that the function (after being applied to its type arguments) is strict      -> (Id -> Bool)          -- ^ a predicate to identify the function-     -> RewriteH Core+     -> RewriteH LCore push mstrict p = promoteExprR (pushR (extractR `fmap` mstrict) p)  -- | Push a function through a Case or Let expression.
src/HERMIT/Dictionary/Local/Bind.hs view
@@ -17,10 +17,10 @@ -- | Externals for manipulating binding groups. externals :: [External] externals =-    [ external "nonrec-to-rec" (promoteBindR nonrecToRecR :: RewriteH Core)+    [ external "nonrec-to-rec" (promoteBindR nonrecToRecR :: RewriteH LCore)         [ "Convert a non-recursive binding into a recursive binding group with a single definition."         , "NonRec v e ==> Rec [Def v e]" ]                           .+ Shallow-    , external "rec-to-nonrec" (promoteBindR recToNonrecR :: RewriteH Core)+    , external "rec-to-nonrec" (promoteBindR recToNonrecR :: RewriteH LCore)         [ "Convert a singleton recursive binding into a non-recursive binding group."         , "Rec [Def v e] ==> NonRec v e,  (v not free in e)" ]     ]
src/HERMIT/Dictionary/Local/Case.hs view
@@ -16,8 +16,9 @@     , caseReduceR     , caseReduceDataconR     , caseReduceLiteralR-    -- , caseReduceIdR     , caseReduceUnfoldR+    , casesForM+    , caseExprsForM     , caseSplitR     , caseSplitInlineR     , caseInlineScrutineeR@@ -32,7 +33,6 @@     ) where  import Control.Arrow-import Control.Applicative import Control.Monad import Control.Monad.IO.Class @@ -44,96 +44,101 @@ import HERMIT.External import HERMIT.GHC import HERMIT.Kure+import HERMIT.Lemma import HERMIT.Monad import HERMIT.Name import HERMIT.ParserCore import HERMIT.Utilities +import HERMIT.Dictionary.AlphaConversion hiding (externals) import HERMIT.Dictionary.Common+import HERMIT.Dictionary.Fold hiding (externals) import HERMIT.Dictionary.Inline hiding (externals)-import HERMIT.Dictionary.AlphaConversion hiding (externals)-import HERMIT.Dictionary.Fold (foldVarR)-import HERMIT.Dictionary.GHC (substCoreExpr) import HERMIT.Dictionary.Undefined (verifyStrictT, buildStrictnessLemmaT) import HERMIT.Dictionary.Unfold (unfoldR) --- NOTE: these are hard to test in small examples, as GHC does them for us, so use with caution ------------------------------------------------------------------------------  -- | Externals relating to Case expressions. externals :: [External] externals =-    [ external "case-float-app" (promoteExprR caseFloatAppR :: RewriteH Core)+    [ external "case-float-app" (promoteExprR caseFloatAppR :: RewriteH LCore)         [ "(case ec of alt -> e) v ==> case ec of alt -> e v" ] .+ Commute .+ Shallow-    , external "case-float-arg" ((\ strict -> promoteExprR (caseFloatArg Nothing (Just strict))) :: RewriteH Core -> RewriteH Core)+    , external "case-float-arg" ((\ strict -> promoteExprR (caseFloatArg Nothing (Just strict))) :: RewriteH LCore -> RewriteH LCore)         [ "Given a proof that f is strict, then"         , "f (case s of alt -> e) ==> case s of alt -> f e" ]   .+ Commute .+ Shallow-    , external "case-float-arg" ((\ f strict -> promoteExprR (caseFloatArg (Just f) (Just strict))) :: CoreString -> RewriteH Core -> RewriteH Core)+    , external "case-float-arg" ((\ f strict -> promoteExprR (caseFloatArg (Just f) (Just strict))) :: CoreString -> RewriteH LCore -> RewriteH LCore)         [ "For a specified f, given a proof that f is strict, then"         , "f (case s of alt -> e) ==> case s of alt -> f e" ]   .+ Commute .+ Shallow-    , external "case-float-arg-unsafe" ((\ f -> promoteExprR (caseFloatArg (Just f) Nothing)) :: CoreString -> RewriteH Core)+    , external "case-float-arg-unsafe" ((\ f -> promoteExprR (caseFloatArg (Just f) Nothing)) :: CoreString -> RewriteH LCore)         [ "For a specified f,"         , "f (case s of alt -> e) ==> case s of alt -> f e" ]   .+ Commute .+ Shallow .+ PreCondition .+ Strictness-    , external "case-float-arg-unsafe" (promoteExprR (caseFloatArg Nothing Nothing) :: RewriteH Core)-        [ "f (case s of alt -> e) ==> case s of alt -> f e" ]   .+ Commute .+ Shallow .+ PreCondition .+ Strictness-    , external "case-float-arg-lemma" (promoteExprR . caseFloatArgLemmaR :: LemmaName -> RewriteH Core)+    , external "case-float-arg-unsafe" (promoteExprR . caseFloatArgLemmaR UnsafeUsed :: LemmaName -> RewriteH LCore)+        [ "f (case s of alt -> e) ==> case s of alt -> f e" ]   .+ Commute .+ Shallow .+ PreCondition .+ Strictness .+ Unsafe+    , external "case-float-arg-lemma" (promoteExprR . caseFloatArgLemmaR Obligation :: LemmaName -> RewriteH LCore)         [ "f (case s of alt -> e) ==> case s of alt -> f e"         , "Generates a lemma with given name for strictness side condition on f." ] .+ Commute .+ Shallow .+ PreCondition .+ Strictness-    , external "case-float-case" (promoteExprR caseFloatCaseR :: RewriteH Core)+    , external "case-float-case" (promoteExprR caseFloatCaseR :: RewriteH LCore)         [ "case (case ec of alt1 -> e1) of alta -> ea ==> case ec of alt1 -> case e1 of alta -> ea" ] .+ Commute .+ Eval-    , external "case-float-cast" (promoteExprR caseFloatCastR :: RewriteH Core)+    , external "case-float-cast" (promoteExprR caseFloatCastR :: RewriteH LCore)         [ "cast (case s of p -> e) co ==> case s of p -> cast e co" ]        .+ Shallow .+ Commute-    , external "case-float-let" (promoteExprR caseFloatLetR :: RewriteH Core)+    , external "case-float-let" (promoteExprR caseFloatLetR :: RewriteH LCore)         [ "let v = case ec of alt1 -> e1 in e ==> case ec of alt1 -> let v = e1 in e" ] .+ Commute .+ Shallow .+ Strictness-    , external "case-float" (promoteExprR caseFloatR :: RewriteH Core)+    , external "case-float" (promoteExprR caseFloatR :: RewriteH LCore)         [ "case-float = case-float-app <+ case-float-case <+ case-float-let <+ case-float-cast" ] .+ Commute .+ Shallow .+ Strictness-    , external "case-float-in" (promoteExprR caseFloatInR :: RewriteH Core)+    , external "case-float-in" (promoteExprR caseFloatInR :: RewriteH LCore)         [ "Float in a Case whatever the context." ]                             .+ Commute .+ Shallow .+ PreCondition-    , external "case-float-in-args" (promoteExprR caseFloatInArgsR :: RewriteH Core)+    , external "case-float-in-args" (promoteExprR caseFloatInArgsR :: RewriteH LCore)         [ "Float in a Case whose alternatives are parallel applications of the same function." ] .+ Commute .+ Shallow .+ PreCondition .+ Strictness-    -- , external "case-float-in-app" (promoteExprR caseFloatInApp :: RewriteH Core)+    -- , external "case-float-in-app" (promoteExprR caseFloatInApp :: RewriteH LCore)     --     [ "Float in a Case whose alternatives are applications of different functions with the same arguments." ] .+ Commute .+ Shallow .+ PreCondition-    , external "case-reduce" (promoteExprR (caseReduceR True) :: RewriteH Core)+    , external "case-reduce" (promoteExprR (caseReduceR True) :: RewriteH LCore)         [ "Case of Known Constructor"         , "case-reduce-datacon <+ case-reduce-literal" ]                     .+ Shallow .+ Eval-    , external "case-reduce-datacon" (promoteExprR (caseReduceDataconR True) :: RewriteH Core)+    , external "case-reduce-datacon" (promoteExprR (caseReduceDataconR True) :: RewriteH LCore)         [ "Case of Known Constructor"         , "case C v1..vn of C w1..wn -> e ==> let { w1 = v1 ; .. ; wn = vn } in e" ]    .+ Shallow .+ Eval-    , external "case-reduce-literal" (promoteExprR (caseReduceLiteralR True) :: RewriteH Core)+    , external "case-reduce-literal" (promoteExprR (caseReduceLiteralR True) :: RewriteH LCore)         [ "Case of Known Constructor"         , "case L of L -> e ==> e" ]                                         .+ Shallow .+ Eval-    , external "case-reduce-unfold" (promoteExprR (caseReduceUnfoldR True) :: RewriteH Core)+    , external "case-reduce-unfold" (promoteExprR (caseReduceUnfoldR True) :: RewriteH LCore)         [ "Unfold the case scrutinee and then case-reduce." ] .+ Shallow .+ Eval .+ Context-    , external "case-split" (promoteExprR . caseSplitR . cmpString2Var :: String -> RewriteH Core)+    , external "case-split" ((\nm -> findVarT (unOccurrenceName nm) >>= promoteExprR . caseSplitR . varToCoreExpr) :: OccurrenceName -> RewriteH LCore)         [ "case-split 'x"-        , "e ==> case x of C1 vs -> e; C2 vs -> e, where x is free in e" ] .+ Shallow .+ Strictness-    , external "case-split-inline" (promoteExprR . caseSplitInlineR . cmpString2Var :: String -> RewriteH Core)+        , "e ==> case x of C1 vs -> e; C2 vs -> e, where x is free in e" ] .+ Deep .+ Strictness+    , external "case-split" (parseCoreExprT >=> promoteR . caseSplitR :: CoreString -> RewriteH LCore)+        [ "case-split [| expr |]"+        , "e ==> case expr of C1 vs -> e; C2 vs -> e"] .+ Deep .+ Strictness+    , external "case-split-inline" ((\nm -> findVarT (unOccurrenceName nm) >>= promoteExprR . caseSplitInlineR . varToCoreExpr) :: OccurrenceName -> RewriteH LCore)         [ "Like case-split, but additionally inlines the matched constructor "         , "applications for all occurances of the named variable." ] .+ Deep .+ Strictness-    , external "case-intro-seq" (promoteExprR . caseIntroSeqR . cmpString2Var :: String -> RewriteH Core)+    , external "case-split-inline" (parseCoreExprT >=> promoteExprR . caseSplitInlineR :: CoreString -> RewriteH LCore)+        [ "Like case-split, but additionally inlines the matched constructor "+        , "applications for all occurances of the case binder." ] .+ Deep .+ Strictness+    , external "case-intro-seq" (promoteExprR . caseIntroSeqR . cmpString2Var :: String -> RewriteH LCore)         [ "Force evaluation of a variable by introducing a case."         , "case-intro-seq 'v is is equivalent to adding @(seq v)@ in the source code." ] .+ Shallow .+ Introduce .+ Strictness-    , external "case-elim-seq" (promoteExprR caseElimSeqR :: RewriteH Core)+    , external "case-elim-seq" (promoteExprR caseElimSeqR :: RewriteH LCore)         [ "Eliminate a case that corresponds to a pointless seq."  ] .+ Deep .+ Eval .+ Strictness-    , external "case-inline-alternative" (promoteExprR caseInlineAlternativeR :: RewriteH Core)+    , external "case-inline-alternative" (promoteExprR caseInlineAlternativeR :: RewriteH LCore)         [ "Inline the case binder as the case-alternative pattern everywhere in the case alternatives." ] .+ Deep-    , external "case-inline-scrutinee" (promoteExprR caseInlineScrutineeR :: RewriteH Core)+    , external "case-inline-scrutinee" (promoteExprR caseInlineScrutineeR :: RewriteH LCore)         [ "Inline the case binder as the case scrutinee everywhere in the case alternatives." ] .+ Deep-    , external "case-merge-alts" (promoteExprR caseMergeAltsR :: RewriteH Core)+    , external "case-merge-alts" (promoteExprR caseMergeAltsR :: RewriteH LCore)         [ "Merge all case alternatives into a single default case."         , "The RHS of each alternative must be the same."         , "case s of {pat1 -> e ; pat2 -> e ; ... ; patn -> e} ==> case s of {_ -> e}" ]-    , external "case-merge-alts-with-binder" (promoteExprR caseMergeAltsWithBinderR :: RewriteH Core)+    , external "case-merge-alts-with-binder" (promoteExprR caseMergeAltsWithBinderR :: RewriteH LCore)         [ "A cleverer version of 'mergeCaseAlts' that first attempts to"         , "abstract out any occurrences of the alternative pattern using the case binder." ] .+ Deep-    , external "case-elim" (promoteExprR caseElimR :: RewriteH Core)+    , external "case-elim" (promoteExprR caseElimR :: RewriteH LCore)         [ "case s of w; C vs -> e ==> e if w and vs are not free in e" ]     .+ Shallow .+ Strictness-    , external "case-elim-inline-scrutinee" (promoteExprR caseElimInlineScrutineeR :: RewriteH Core)+    , external "case-elim-inline-scrutinee" (promoteExprR caseElimInlineScrutineeR :: RewriteH LCore)         [ "Eliminate a case, inlining any occurrences of the case binder as the scrutinee." ] .+ Deep-    , external "case-elim-merge-alts" (promoteExprR caseElimMergeAltsR :: RewriteH Core)+    , external "case-elim-merge-alts" (promoteExprR caseElimMergeAltsR :: RewriteH LCore)         [ "Eliminate a case, merging the case alternatives into a single default alternative",           "and inlining the case binder as the scrutinee (if possible)." ] .+ Deep-    , external "case-fold-binder" (promoteExprR caseFoldBinderR :: RewriteH Core)+    , external "case-fold-binder" (promoteExprR caseFoldBinderR :: RewriteH LCore)         [ "In the case alternatives, fold any occurrences of the case alt patterns to the case binder." ]     ] @@ -166,7 +171,7 @@           (\(Case s b _ alts) v -> let newAlts = mapAlts (`App` v) alts                                     in Case s b (coreAltsType newAlts) newAlts) -caseFloatArg :: Maybe CoreString -> Maybe (RewriteH Core) -> RewriteH CoreExpr+caseFloatArg :: Maybe CoreString -> Maybe (RewriteH LCore) -> RewriteH CoreExpr caseFloatArg mfstr mstrictCore = let mstrict = extractR <$> mstrictCore                                   in case mfstr of                                        Nothing    -> caseFloatArgR Nothing mstrict@@ -202,9 +207,9 @@ --   Only safe if @f@ is strict, so introduces a lemma to prove. caseFloatArgLemmaR :: ( AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb, HasHermitMEnv m                       , HasHscEnv m, HasDynFlags m, HasLemmas m, MonadCatch m, MonadIO m, MonadThings m, MonadUnique m )-                   => LemmaName -> Rewrite c m CoreExpr-caseFloatArgLemmaR nm = prefixFailMsg "Case floating from application argument failed: " $-                        withPatFailMsg "App f (Case s w ty alts)" $ do+                   => Used -> LemmaName -> Rewrite c m CoreExpr+caseFloatArgLemmaR u nm = prefixFailMsg "Case floating from application argument failed: " $+                          withPatFailMsg "App f (Case s w ty alts)" $ do     App f (Case s w _ alts) <- idR      let fvs         = freeVarsExpr f@@ -215,7 +220,7 @@             appAllR idR (alphaCaseBinderR Nothing) >>> caseFloatArgR Nothing Nothing        | all isEmptyVarSet altCaptures -> do             let new_alts = mapAlts (App f) alts-            buildStrictnessLemmaT nm f+            buildStrictnessLemmaT u nm f             return $ Case s w (coreAltsType new_alts) new_alts        | otherwise ->             appAllR idR (caseAllR idR idR idR (\ n -> let vs = varSetElems (altCaptures !! n)@@ -363,25 +368,44 @@                               | otherwise                  -> caseOneR (fail "scrutinee") (fail "binder") (fail "type") (\ _ -> acceptR (\ (dc'',_,_) -> dc'' == dc') >>> alphaAltVarsR shadows) >>> go -- WARNING: The alpha-renaming to avoid variable capture has not been tested.  We need testing infrastructure! --- | Case split a free identifier in an expression:+-- | Case split on an arbitrary scrutinee s. All free variables in s should be in scope. ----- E.g. Assume expression e which mentions i :: [a]+-- E.g. If s has type [a], then case-split s: ----- e ==> case i of i---         []     -> e---         (a:as) -> e-caseSplitR :: (MonadCatch m, MonadUnique m) => (Id -> Bool) -> Rewrite c m CoreExpr-caseSplitR idPred = prefixFailMsg "caseSplit failed: " $-               do i            <- matchingFreeIdT idPred-                  (tycon, tys) <- splitTyConAppM (idType i)-                  let aNms     = map (:[]) $ cycle ['a'..'z']-                  contextfreeT $ \ e -> do dcsAndVars <- mapM (\ dc -> liftM (dc,) (sequence [ newIdH a ty | (a,ty) <- zip aNms $ dataConInstArgTys dc tys ]))-                                                              (tyConDataCons tycon)-                                           w <- cloneVarH (++ "'") i-                                           let e' = substCoreExpr i (Var w) e-                                               alts = [ (DataAlt dc, as, e') | (dc,as) <- dcsAndVars ]-                                           return $ Case (Var i) w (coreAltsType alts) alts+-- e ==> case s of w+--         []     -> e[w/s]+--         (a:as) -> e[w/s]+--+-- Note that occurrences of s in e are replaced with the case binder.+caseSplitR :: forall c m. ( AddBindings c, BoundVars c, ExtendPath c Crumb, HasEmptyContext c, ReadPath c Crumb+                          , MonadCatch m, MonadUnique m )+           => CoreExpr -> Rewrite c m CoreExpr+caseSplitR s = prefixFailMsg "case-split failed: " $ do+    c <- contextT+    guardMsg (all (inScope c) $ varSetElems $ freeVarsExpr s) "variables in desired scrutinee are unbound."+    w <- constT $ newVarH "w" (exprType s)+    let f = compileFold [Equality [] s (varToCoreExpr w)]+    e' <- tryR $ withVarsInScope [w] $ extractR (anytdR (promoteR $ runFoldR f) :: Rewrite c m Core)+    constT $ do+        dcsAndBss <- casesForM s+        let alts = [ (DataAlt dc, bs, e') | (dc,bs) <- dcsAndBss ]+        guardMsg (not (null alts)) "no constructors for scrutinee of that type."+        return $ Case s w (exprType e') alts +casesForM :: MonadUnique m => CoreExpr -> m [(DataCon, [Id])]+casesForM e = do+    (tyCon, tys) <- splitTyConAppM (exprType e)+    let aNms = map (:[]) $ cycle ['a'..'z']+    forM (tyConDataCons tyCon) $ \ dc -> do+        bs <- sequence [ newIdH a ty | (a,ty) <- zip aNms $ dataConInstArgTys dc tys ]+        return (dc,bs)++caseExprsForM :: MonadUnique m => CoreExpr -> m [CoreExpr]+caseExprsForM e = do+    (_, tys) <- splitTyConAppM (exprType e)+    cases <- casesForM e+    return [ mkDataConApp tys dc vs | (dc,vs) <- cases ]+ -- | Force evaluation of an identifier by introducing a case. --   This is equivalent to adding @(seq v)@ in the source code. --@@ -411,8 +435,8 @@ -- > caseSplitInline idPred = caseSplit idPred >>> caseInlineAlternativeR caseSplitInlineR :: ( ExtendPath c Crumb, ReadPath c Crumb, AddBindings c                     , ReadBindings c, HasEmptyContext c, MonadCatch m, MonadUnique m )-                 => (Id -> Bool) -> Rewrite c m CoreExpr-caseSplitInlineR idPred = caseSplitR idPred >>> caseInlineAlternativeR+                 => CoreExpr -> Rewrite c m CoreExpr+caseSplitInlineR s = caseSplitR s >>> caseInlineAlternativeR  ------------------------------------------------------------------------------ @@ -458,10 +482,12 @@ caseFoldBinderR :: forall c m. ( ExtendPath c Crumb, ReadPath c Crumb, AddBindings c                                , ReadBindings c, HasEmptyContext c, MonadCatch m, MonadUnique m )                 => Rewrite c m CoreExpr-caseFoldBinderR = prefixFailMsg "case-fold-binder failed: " $ do-    w <- caseBinderIdT-    caseAllR idR idR idR $ \ _ -> do depth <- varBindingDepthT w-                                     extractR $ anybuR (promoteExprR (foldVarR (Just depth) w) :: Rewrite c m Core)+caseFoldBinderR = prefixFailMsg "case-fold-binder failed: " $+    -- ensure the case binder is not dead, or else fold will fail+    caseAllR idR (arr (flip setIdOccInfo NoOccInfo)) idR (const idR) >>> (do+        w <- caseBinderIdT+        caseAllR idR idR idR $ \ _ -> do depth <- varBindingDepthT w+                                         extractR $ anybuR (promoteExprR (foldVarR (Just depth) w) :: Rewrite c m Core))  -- | A cleverer version of 'mergeCaseAlts' that first attempts to abstract out any occurrences of the alternative pattern using the case binder. caseMergeAltsWithBinderR :: ( ExtendPath c Crumb, ReadPath c Crumb, AddBindings c
src/HERMIT/Dictionary/Local/Cast.hs view
@@ -6,6 +6,7 @@     , castElimReflR     , castElimSymR     , castFloatAppR+    , castFloatLamR     , castElimSymPlusR -- TODO: revisit     ) where@@ -17,9 +18,9 @@  import HERMIT.Core import HERMIT.Context-import HERMIT.Kure import HERMIT.External import HERMIT.GHC+import HERMIT.Kure  import HERMIT.Dictionary.Common @@ -28,17 +29,19 @@ -- | Externals relating to Case expressions. externals :: [External] externals =-    [ external "cast-elim" (promoteExprR castElimR :: RewriteH Core)+    [ external "cast-elim" (promoteExprR castElimR :: RewriteH LCore)         [ "cast-elim-refl <+ cast-elim-sym" ] .+ Shallow -- don't include in "Bash", as sub-rewrites are tagged "Bash" already.-    , external "cast-elim-refl" (promoteExprR castElimReflR :: RewriteH Core)+    , external "cast-elim-refl" (promoteExprR castElimReflR :: RewriteH LCore)         [ "cast e co ==> e ; if co is a reflexive coercion" ] .+ Shallow-    , external "cast-elim-sym" (promoteExprR castElimSymR :: RewriteH Core)+    , external "cast-elim-sym" (promoteExprR castElimSymR :: RewriteH LCore)         [ "removes pairs of symmetric casts" ]                .+ Shallow-    , external "cast-elim-sym-plus" (promoteExprR castElimSymPlusR :: RewriteH Core)+    , external "cast-elim-sym-plus" (promoteExprR castElimSymPlusR :: RewriteH LCore)         [ "removes pairs of symmetric casts possibly separated by let or case forms" ] .+ Deep .+ TODO-    , external "cast-float-app" (promoteExprR castFloatAppR :: RewriteH Core)+    , external "cast-float-app" (promoteExprR castFloatAppR :: RewriteH LCore)         [ "(cast e (c1 -> c2)) x ==> cast (e (cast x (sym c1))) c2" ] .+ Shallow-    , external "cast-elim-unsafe" (promoteExprR castElimUnsafeR :: RewriteH Core)+    , external "cast-float-lam" (promoteExprR castFloatLamR :: RewriteH LCore)+        [ "\\ x::a -> cast x (a -> b) ==> cast (\\x::a -> x) ((a -> a) -> (a -> b))" ] .+ Shallow+    , external "cast-elim-unsafe" (promoteExprR castElimUnsafeR :: RewriteH LCore)         [ "removes casts regardless of whether it is safe to do so" ] .+ Shallow .+ Experiment .+ Unsafe .+ TODO     ] @@ -78,6 +81,16 @@                 return (Cast (App e1 e2) (Coercion.substCo (Coercion.extendTvSubst emptyCvSubst t x') c2))             _ -> fail "castFloatApp" +-- (\ x::a -> cast e (b -> c)) :: a -> c+-- cast (\x::a -> e) ((a -> b) -> (a -> c))+castFloatLamR :: MonadCatch m => Rewrite c m CoreExpr+castFloatLamR = prefixFailMsg "Cast float from lambda failed: " $+                withPatFailMsg (wrongExprForm "Lam b (Cast e co)") $ do+    Lam b (Cast e co) <- idR+    let r = coercionRole co+        aTy = varType b+    return (Cast (Lam b e) (mkFunCo r (mkReflCo r aTy) co))+ -- | Attempts to tease a coercion apart into a type constructor and the application -- of a number of coercion arguments to that constructor splitTyConAppCo_maybe :: Coercion -> Maybe (TyCon, [Coercion])@@ -124,4 +137,3 @@  castElimUnsafeR :: (ExtendPath c Crumb, Monad m) => Rewrite c m CoreExpr castElimUnsafeR = castT idR idR const-
src/HERMIT/Dictionary/Local/Let.hs view
@@ -69,81 +69,81 @@ -- | Externals relating to 'Let' expressions. externals :: [External] externals =-    [ external "let-subst" (promoteExprR letSubstR :: RewriteH Core)+    [ external "let-subst" (promoteExprR letSubstR :: RewriteH LCore)         [ "Let substitution: (let x = e1 in e2) ==> (e2[e1/x])"         , "x must not be free in e1." ]                                         .+ Deep .+ Eval-    , external "let-subst-safe" (promoteExprR letSubstSafeR :: RewriteH Core)+    , external "let-subst-safe" (promoteExprR letSubstSafeR :: RewriteH LCore)         [ "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-    , external "let-nonrec-subst-safe" (promoteExprR letNonRecSubstSafeR :: RewriteH Core)+    , external "let-nonrec-subst-safe" (promoteExprR letNonRecSubstSafeR :: RewriteH LCore)         [ "As let-subst-safe, but does not try to convert a recursive let into a non-recursive let first." ] .+ Deep .+ Eval-    -- , external "safe-let-subst-plus" (promoteExprR safeLetSubstPlusR :: RewriteH Core)+    -- , external "safe-let-subst-plus" (promoteExprR safeLetSubstPlusR :: RewriteH LCore)     --     [ "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 "let-intro" (promoteExprR . letIntroR :: String -> RewriteH Core)+    , external "let-intro" (promoteExprR . letIntroR :: String -> RewriteH LCore)         [ "e => (let v = e in v), name of v is provided" ]                      .+ Shallow .+ Introduce-    , external "let-intro-unfolding" (promoteExprR . letIntroUnfoldingR :: HermitName -> RewriteH Core)+    , external "let-intro-unfolding" (promoteExprR . letIntroUnfoldingR :: HermitName -> RewriteH LCore)         [ "e => let f' = defn[f'/f] in e[f'/f], name of f is provided" ]-    , external "let-elim" (promoteExprR letElimR :: RewriteH Core)+    , external "let-elim" (promoteExprR letElimR :: RewriteH LCore)         [ "Remove an unused let binding."         , "(let v = e1 in e2) ==> e2, if v is not free in e1 or e2." ]          .+ Eval .+ Shallow---    , external "let-constructor-reuse" (promoteR $ not_defined "constructor-reuse" :: RewriteH Core)+--    , external "let-constructor-reuse" (promoteR $ not_defined "constructor-reuse" :: RewriteH LCore) --        [ "let v = C v1..vn in ... C v1..vn ... ==> let v = C v1..vn in ... v ..., fails otherwise" ] .+ Eval-    , external "let-float-app" (promoteExprR letFloatAppR :: RewriteH Core)+    , external "let-float-app" (promoteExprR letFloatAppR :: RewriteH LCore)         [ "(let v = ev in e) x ==> let v = ev in e x" ]                         .+ Commute .+ Shallow-    , external "let-float-arg" (promoteExprR letFloatArgR :: RewriteH Core)+    , external "let-float-arg" (promoteExprR letFloatArgR :: RewriteH LCore)         [ "f (let v = ev in e) ==> let v = ev in f e" ]                         .+ Commute .+ Shallow-    , external "let-float-lam" (promoteExprR letFloatLamR :: RewriteH Core)+    , external "let-float-lam" (promoteExprR letFloatLamR :: RewriteH LCore)         [ "The Full Laziness Transformation"         , "(\\ 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-    , external "let-float-let" (promoteExprR letFloatLetR :: RewriteH Core)+    , external "let-float-let" (promoteExprR letFloatLetR :: RewriteH LCore)         [ "let v = (let w = ew in ev) in e ==> let w = ew in let v = ev in e" ] .+ Commute .+ Shallow-    , external "let-float-case" (promoteExprR letFloatCaseR :: RewriteH Core)+    , external "let-float-case" (promoteExprR letFloatCaseR :: RewriteH LCore)         [ "case (let v = ev in e) of ... ==> let v = ev in case e of ..." ]     .+ Commute .+ Shallow .+ Eval-    , external "let-float-case-alt" (promoteExprR (letFloatCaseAltR Nothing) :: RewriteH Core)+    , external "let-float-case-alt" (promoteExprR (letFloatCaseAltR Nothing) :: RewriteH LCore)         [ "case s of { ... ; p -> let v = ev in e ; ... } "         , "==> let v = ev in case s of { ... ; p -> e ; ... } " ]               .+ Commute .+ Shallow .+ Eval-    , external "let-float-case-alt" (promoteExprR . letFloatCaseAltR . Just :: Int -> RewriteH Core)+    , external "let-float-case-alt" (promoteExprR . letFloatCaseAltR . Just :: Int -> RewriteH LCore)         [ "Float a let binding from specified alternative."         , "case s of { ... ; p -> let v = ev in e ; ... } "         , "==> let v = ev in case s of { ... ; p -> e ; ... } " ]               .+ Commute .+ Shallow .+ Eval-    , external "let-float-cast" (promoteExprR letFloatCastR :: RewriteH Core)+    , external "let-float-cast" (promoteExprR letFloatCastR :: RewriteH LCore)         [ "cast (let bnds in e) co ==> let bnds in cast e co" ]                 .+ Commute .+ Shallow-    , external "let-float-top" (promoteProgR letFloatTopR :: RewriteH Core)+    , external "let-float-top" (promoteProgR letFloatTopR :: RewriteH LCore)         [ "v = (let bds in e) : prog ==> bds : v = e : prog" ]                  .+ Commute .+ Shallow-    , external "let-float" (promoteProgR letFloatTopR <+ promoteExprR letFloatExprR :: RewriteH Core)+    , external "let-float" (promoteProgR letFloatTopR <+ promoteExprR letFloatExprR :: RewriteH LCore)         [ "Float a Let whatever the context." ]                                 .+ Commute .+ Shallow  -- Don't include in bash, as each sub-rewrite is tagged "Bash" already.-    , external "let-to-case" (promoteExprR letToCaseR :: RewriteH Core)+    , external "let-to-case" (promoteExprR letToCaseR :: RewriteH LCore)         [ "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)+--    , external "let-to-case-unbox" (promoteR $ not_defined "let-to-case-unbox" :: RewriteH LCore) --        [ "let v = ev in e ==> case ev of C v1..vn -> let v = C v1..vn in e" ]-    , external "let-float-in" (promoteExprR letFloatInR :: RewriteH Core)+    , external "let-float-in" (promoteExprR letFloatInR :: RewriteH LCore)         [ "Float-in a let if possible." ]                                        .+ Commute .+ Shallow-    , external "let-float-in-app" ((promoteExprR letFloatInAppR >+> anybuR (promoteExprR letElimR)) :: RewriteH Core)+    , external "let-float-in-app" ((promoteExprR letFloatInAppR >+> anybuR (promoteExprR letElimR)) :: RewriteH LCore)         [ "let v = ev in f a ==> (let v = ev in f) (let v = ev in a)" ]         .+ Commute .+ Shallow-    , external "let-float-in-case" ((promoteExprR letFloatInCaseR >+> anybuR (promoteExprR letElimR)) :: RewriteH Core)+    , external "let-float-in-case" ((promoteExprR letFloatInCaseR >+> anybuR (promoteExprR letElimR)) :: RewriteH LCore)         [ "let v = ev in case s of p -> e ==> case (let v = ev in s) of p -> let v = ev in e"         , "if v does not shadow a pattern binder in p" ]                        .+ Commute .+ Shallow-    , external "let-float-in-lam" ((promoteExprR letFloatInLamR >+> anybuR (promoteExprR letElimR)) :: RewriteH Core)+    , external "let-float-in-lam" ((promoteExprR letFloatInLamR >+> anybuR (promoteExprR letElimR)) :: RewriteH LCore)         [ "let v = ev in \\ x -> e ==> \\ x -> let v = ev in e"         , "if v does not shadow x" ]                                            .+ Commute .+ Shallow-    , external "reorder-lets" (promoteExprR . reorderNonRecLetsR :: [String] -> RewriteH Core)+    , external "reorder-lets" (promoteExprR . reorderNonRecLetsR :: [String] -> RewriteH LCore)         [ "Re-order a sequence of nested non-recursive let bindings."         , "The argument list should contain the let-bound variables, in the desired order." ]-    , external "let-tuple" (promoteExprR . letTupleR :: String -> RewriteH Core)+    , external "let-tuple" (promoteExprR . letTupleR :: String -> RewriteH LCore)         [ "Combine nested non-recursive lets into case of a tuple."         , "E.g. let {v1 = e1 ; v2 = e2 ; v3 = e3} in body ==> case (e1,e2,e3) of {(v1,v2,v3) -> body}" ] .+ Commute-    , external "prog-bind-elim" (promoteProgR progBindElimR :: RewriteH Core)+    , external "prog-bind-elim" (promoteProgR progBindElimR :: RewriteH LCore)         [ "Remove unused top-level binding(s)."         , "prog-bind-nonrec-elim <+ prog-bind-rec-elim" ]                       .+ Eval .+ Shallow-    , external "prog-bind-nonrec-elim" (promoteProgR progBindNonRecElimR :: RewriteH Core)+    , external "prog-bind-nonrec-elim" (promoteProgR progBindNonRecElimR :: RewriteH LCore)         [ "Remove unused top-level binding(s)."         , "v = e : prog ==> prog, if v is not free in prog and not exported." ] .+ Eval .+ Shallow-    , external "prog-bind-rec-elim" (promoteProgR progBindRecElimR :: RewriteH Core)+    , external "prog-bind-rec-elim" (promoteProgR progBindRecElimR :: RewriteH LCore)         [ "Remove unused top-level binding(s)."         , "v+ = e+ : prog ==> v* = e* : prog, where v* is a subset of v+ consisting"         , "of vs that are free in prog or e+, or exported." ]                   .+ Eval .+ Shallow
src/HERMIT/Dictionary/Navigation.hs view
@@ -1,4 +1,10 @@-{-# LANGUAGE DeriveDataTypeable, FlexibleContexts, FlexibleInstances, InstanceSigs, ScopedTypeVariables, TypeFamilies #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE InstanceSigs #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}  module HERMIT.Dictionary.Navigation     ( -- * Navigation@@ -19,16 +25,18 @@     , string2considerable     ) where +import Control.Arrow+import Control.Monad+ import Data.Dynamic (Typeable) import Data.Monoid -import Control.Arrow- import HERMIT.Core import HERMIT.Context import HERMIT.External import HERMIT.GHC hiding ((<>)) import HERMIT.Kure+import HERMIT.Lemma(Quantified(..)) import HERMIT.Name  import HERMIT.Dictionary.Navigation.Crumbs@@ -39,29 +47,29 @@ externals :: [External] externals = crumbExternals     ++ map (.+ Navigation)-        [ external "rhs-of" (rhsOfT . mkRhsOfPred :: RhsOfName -> TransformH Core LocalPathH)+        [ external "rhs-of" (rhsOfT . mkRhsOfPred :: RhsOfName -> TransformH LCoreTC LocalPathH)             [ "Find the path to the RHS of the binding of the named variable." ]-        , external "binding-group-of" (bindingGroupOfT . cmpString2Var :: String -> TransformH CoreTC LocalPathH)+        , external "binding-group-of" (bindingGroupOfT . cmpString2Var :: String -> TransformH LCoreTC LocalPathH)             [ "Find the path to the binding group of the named variable." ]-        , external "binding-of" (bindingOfT . mkBindingPred :: BindingName -> TransformH CoreTC LocalPathH)+        , external "binding-of" (bindingOfT . mkBindingPred :: BindingName -> TransformH LCoreTC LocalPathH)             [ "Find the path to the binding of the named variable." ]-        , external "occurrence-of" (occurrenceOfT . mkOccPred :: OccurrenceName -> TransformH CoreTC LocalPathH)+        , external "occurrence-of" (occurrenceOfT . mkOccPred :: OccurrenceName -> TransformH LCoreTC LocalPathH)             [ "Find the path to the first occurrence of the named variable." ]-        , external "application-of" (applicationOfT . mkOccPred :: OccurrenceName -> TransformH CoreTC LocalPathH)+        , external "application-of" (applicationOfT . mkOccPred :: OccurrenceName -> TransformH LCoreTC LocalPathH)             [ "Find the path to the first application of the named variable." ]-        , external "consider" (considerConstructT :: Considerable -> TransformH Core LocalPathH)+        , external "consider" (considerConstructT :: Considerable -> TransformH LCore LocalPathH)             [ "consider <c> focuses on the first construct <c>.", recognizedConsiderables ]-        , external "arg" (promoteExprT . nthArgPath :: Int -> TransformH Core LocalPathH)+        , external "arg" (promoteExprT . nthArgPath :: Int -> TransformH LCore LocalPathH)             [ "arg n focuses on the (n-1)th argument of a nested application." ]-        , external "lams-body" (promoteExprT lamsBodyT :: TransformH Core LocalPathH)+        , external "lams-body" (promoteExprT lamsBodyT :: TransformH LCore LocalPathH)             [ "Descend into the body after a sequence of lambdas." ]-        , external "lets-body" (promoteExprT letsBodyT :: TransformH Core LocalPathH)+        , external "lets-body" (promoteExprT letsBodyT :: TransformH LCore LocalPathH)             [ "Descend into the body after a sequence of let bindings." ]-        , external "prog-end" (promoteModGutsT gutsProgEndT <+ promoteProgT progEndT :: TransformH Core LocalPathH)+        , external "prog-end" (promoteModGutsT gutsProgEndT <+ promoteProgT progEndT :: TransformH LCore LocalPathH)             [ "Descend to the end of a program." ]-        , external "parent-of" (parentOfT :: TransformH Core LocalPathH -> TransformH Core LocalPathH)+        , external "parent-of" (parentOfT :: TransformH LCore LocalPathH -> TransformH LCore LocalPathH)             [ "Focus on the parent of another focal point." ]-        , external "parent-of" (parentOfT :: TransformH CoreTC LocalPathH -> TransformH CoreTC LocalPathH)+        , external "parent-of" (parentOfT :: TransformH LCoreTC LocalPathH -> TransformH LCoreTC LocalPathH)             [ "Focus on the parent of another focal point." ]         ] @@ -76,7 +84,7 @@ -----------------------------------------------------------------------  -- | Find the path to the RHS of a binding.-rhsOfT :: (AddBindings c, ExtendPath c Crumb, ReadPath c Crumb, HasEmptyContext c, MonadCatch m) => (Var -> Bool) -> Transform c m Core LocalPathH+rhsOfT :: (AddBindings c, ExtendPath c Crumb, ReadPath c Crumb, HasEmptyContext c, MonadCatch m) => (Var -> Bool) -> Transform c m LCoreTC LocalPathH rhsOfT p = prefixFailMsg ("rhs-of failed: ") $            do lp <- onePathToT (arr $ bindingOf p . inject)               case lastCrumb lp of@@ -85,26 +93,27 @@                                 Let_Bind      -> return (lp @@ NonRec_RHS)                                 ProgCons_Head -> return (lp @@ NonRec_RHS)                                 _             -> fail "does not have a RHS."-                Nothing -> defOrNonRecT successT lastCrumbT (\ () cr -> mempty @@ cr)+                Nothing -> promoteCoreT (defOrNonRecT successT lastCrumbT (\ () cr -> mempty @@ cr))  -- | Find the path to the binding group of a variable.-bindingGroupOfT :: (AddBindings c, ExtendPath c Crumb, ReadPath c Crumb, HasEmptyContext c, MonadCatch m) => (Var -> Bool) -> Transform c m CoreTC LocalPathH+bindingGroupOfT :: (AddBindings c, ExtendPath c Crumb, ReadPath c Crumb, HasEmptyContext c, MonadCatch m) => (Var -> Bool) -> Transform c m LCoreTC LocalPathH bindingGroupOfT p = prefixFailMsg ("binding-group-of failed: ") $                     oneNonEmptyPathToT (promoteBindT $ arr $ bindingGroupOf p)  -- | Find the path to the binding of a variable.-bindingOfT :: (AddBindings c, ExtendPath c Crumb, ReadPath c Crumb, HasEmptyContext c, MonadCatch m) => (Var -> Bool) -> Transform c m CoreTC LocalPathH+bindingOfT :: (AddBindings c, ExtendPath c Crumb, ReadPath c Crumb, HasEmptyContext c, MonadCatch m) => (Var -> Bool) -> Transform c m LCoreTC LocalPathH bindingOfT p = prefixFailMsg ("binding-of failed: ") $                oneNonEmptyPathToT (arr $ bindingOf p)  -- | Find the path to the first occurrence of a variable.-occurrenceOfT :: (AddBindings c, ExtendPath c Crumb, ReadPath c Crumb, HasEmptyContext c, MonadCatch m) => (Var -> Bool) -> Transform c m CoreTC LocalPathH+occurrenceOfT :: (AddBindings c, ExtendPath c Crumb, ReadPath c Crumb, HasEmptyContext c, MonadCatch m)+              => (Var -> Bool) -> Transform c m LCoreTC LocalPathH occurrenceOfT p = prefixFailMsg ("occurrence-of failed: ") $                   oneNonEmptyPathToT (arr $ occurrenceOf p)  -- | Find the path to an application of a given function. applicationOfT :: (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, MonadCatch m, ReadPath c Crumb)-               => (Var -> Bool) -> Transform c m CoreTC LocalPathH+               => (Var -> Bool) -> Transform c m LCoreTC LocalPathH applicationOfT p = prefixFailMsg "application-of failed:" $ oneNonEmptyPathToT go     where go = promoteExprT (appT (extractT go) successT const) <+ arr (occurrenceOf p) @@ -115,13 +124,16 @@  ----------------------------------------------------------------------- -bindingOf :: (Var -> Bool) -> CoreTC -> Bool+bindingOf :: (Var -> Bool) -> LCoreTC -> Bool bindingOf p = any p . varSetElems . binders -binders :: CoreTC -> VarSet-binders (Core core)              = bindersCore core-binders (TyCo (TypeCore ty))     = binderType ty-binders (TyCo (CoercionCore co)) = binderCoercion co+-- TODO: check this is correct, written in a hurry+binders :: LCoreTC -> VarSet+binders (LTCCore (LQuantified (Quantified bs _)))  = mkVarSet bs+binders (LTCCore (LClause _))                      = emptyVarSet+binders (LTCCore (LCore core))                     = bindersCore core+binders (LTCTyCo (TypeCore ty))                    = binderType ty+binders (LTCTyCo (CoercionCore co))                = binderCoercion co  bindersCore :: Core -> VarSet bindersCore (BindCore bnd)  = binderBind bnd@@ -152,14 +164,14 @@  ----------------------------------------------------------------------- -occurrenceOf :: (Var -> Bool) -> CoreTC -> Bool-occurrenceOf p = maybe False p . varOccurrence+occurrenceOf :: (Var -> Bool) -> LCoreTC -> Bool+occurrenceOf p = maybe False p . (projectM >=> varOccurrence) -varOccurrence :: CoreTC -> Maybe Var-varOccurrence (Core (ExprCore e))      = varOccurrenceExpr e-varOccurrence (TyCo (TypeCore ty))     = varOccurrenceType ty-varOccurrence (TyCo (CoercionCore co)) = varOccurrenceCoercion co-varOccurrence _                        = Nothing+varOccurrence :: LCoreTC -> Maybe Var+varOccurrence (LTCCore (LCore (ExprCore e))) = varOccurrenceExpr e+varOccurrence (LTCTyCo (TypeCore ty))        = varOccurrenceType ty+varOccurrence (LTCTyCo (CoercionCore co))    = varOccurrenceCoercion co+varOccurrence _                              = Nothing  varOccurrenceExpr :: CoreExpr -> Maybe Var varOccurrenceExpr (Var v)       = Just v@@ -176,19 +188,19 @@ -----------------------------------------------------------------------  -- | Find all possible targets of 'occurrenceOfT'.-occurrenceOfTargetsT :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, HasEmptyContext c, MonadCatch m) => Transform c m CoreTC VarSet+occurrenceOfTargetsT :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, HasEmptyContext c, MonadCatch m) => Transform c m LCoreTC VarSet occurrenceOfTargetsT = allT $ crushbuT (arr varOccurrence >>> projectT >>^ unitVarSet)  -- | Find all possible targets of 'bindingOfT'.-bindingOfTargetsT :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, HasEmptyContext c, MonadCatch m) => Transform c m CoreTC VarSet+bindingOfTargetsT :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, HasEmptyContext c, MonadCatch m) => Transform c m LCoreTC VarSet bindingOfTargetsT = allT $ crushbuT (arr binders)  -- | Find all possible targets of 'bindingGroupOfT'.-bindingGroupOfTargetsT :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, HasEmptyContext c, MonadCatch m) => Transform c m CoreTC VarSet+bindingGroupOfTargetsT :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, HasEmptyContext c, MonadCatch m) => Transform c m LCoreTC VarSet bindingGroupOfTargetsT = allT $ crushbuT (promoteBindT $ arr (mkVarSet . bindVars))  -- | Find all possible targets of 'rhsOfT'.-rhsOfTargetsT :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, HasEmptyContext c, MonadCatch m) => Transform c m CoreTC VarSet+rhsOfTargetsT :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, HasEmptyContext c, MonadCatch m) => Transform c m LCoreTC VarSet rhsOfTargetsT = crushbuT (promoteBindT (arr binderBind) <+ promoteDefT (arr binderDef))  -----------------------------------------------------------------------@@ -223,12 +235,18 @@                   ]  -- | Find the path to the first matching construct.-considerConstructT :: (AddBindings c, ExtendPath c Crumb, ReadPath c Crumb, HasEmptyContext c, MonadCatch m) => Considerable -> Transform c m Core LocalPathH-considerConstructT con = oneNonEmptyPathToT (arr $ underConsideration con)+considerConstructT :: (AddBindings c, ExtendPath c Crumb, ReadPath c Crumb, HasEmptyContext c, MonadCatch m) => Considerable -> Transform c m LCore LocalPathH+considerConstructT con = oneNonEmptyPathToT (arr $ underConsiderationLCore con)  string2considerable :: String -> Maybe Considerable string2considerable = flip lookup considerables +-- TODO: cleanup this code++underConsiderationLCore :: Considerable -> LCore -> Bool+underConsiderationLCore con (LCore c) = underConsideration con c+underConsiderationLCore _   _         = False+ underConsideration :: Considerable -> Core -> Bool underConsideration Binding      (BindCore _)               = True underConsideration Definition   (BindCore (NonRec _ _))    = True@@ -262,24 +280,22 @@   setEmptyContext ec = ec { baseContext = setEmptyContext (baseContext ec)                           , extraContext = mempty } -exhaustRepeatCrumbT :: (AddBindings c, ReadPath c Crumb, ExtendPath c Crumb, HasEmptyContext c, Walker c CoreTC, MonadCatch m) => Crumb -> Transform c m CoreTC LocalPathH+exhaustRepeatCrumbT :: (AddBindings c, ReadPath c Crumb, ExtendPath c Crumb, HasEmptyContext c, Walker c LCoreTC, MonadCatch m) => Crumb -> Transform c m LCoreTC LocalPathH exhaustRepeatCrumbT cr = let l = exhaustPathL (repeat cr)                           in withLocalPathT (focusT l exposeLocalPathT)  -- | Construct a path to the body of a sequence of lambdas.-lamsBodyT :: (AddBindings c, ReadPath c Crumb, ExtendPath c Crumb, HasEmptyContext c, Walker c CoreTC, MonadCatch m) => Transform c m CoreExpr LocalPathH+lamsBodyT :: (AddBindings c, ReadPath c Crumb, ExtendPath c Crumb, HasEmptyContext c, Walker c LCoreTC, MonadCatch m) => Transform c m CoreExpr LocalPathH lamsBodyT = extractT (exhaustRepeatCrumbT Lam_Body)  -- | Construct a path to the body of a sequence of let bindings.-letsBodyT :: (AddBindings c, ReadPath c Crumb, ExtendPath c Crumb, HasEmptyContext c, Walker c CoreTC, MonadCatch m) => Transform c m CoreExpr LocalPathH+letsBodyT :: (AddBindings c, ReadPath c Crumb, ExtendPath c Crumb, HasEmptyContext c, Walker c LCoreTC, MonadCatch m) => Transform c m CoreExpr LocalPathH letsBodyT = extractT (exhaustRepeatCrumbT Let_Body)  -- | Construct a path to end of a program.-progEndT :: (AddBindings c, ReadPath c Crumb, ExtendPath c Crumb, HasEmptyContext c, Walker c CoreTC, MonadCatch m) => Transform c m CoreProg LocalPathH+progEndT :: (AddBindings c, ReadPath c Crumb, ExtendPath c Crumb, HasEmptyContext c, Walker c LCoreTC, MonadCatch m) => Transform c m CoreProg LocalPathH progEndT = extractT (exhaustRepeatCrumbT ProgCons_Tail) --- | Construct a path to teh end of a program, starting at the 'ModGuts'.-gutsProgEndT :: (AddBindings c, ReadPath c Crumb, ExtendPath c Crumb, HasEmptyContext c, Walker c CoreTC, MonadCatch m) => Transform c m ModGuts LocalPathH+-- | Construct a path to the end of a program, starting at the 'ModGuts'.+gutsProgEndT :: (AddBindings c, ReadPath c Crumb, ExtendPath c Crumb, HasEmptyContext c, Walker c LCoreTC, MonadCatch m) => Transform c m ModGuts LocalPathH gutsProgEndT = modGutsT progEndT (\ _ p -> (mempty @@ ModGuts_Prog) <> p)-----------------------------------------------------------------------------------------
src/HERMIT/Dictionary/Navigation/Crumbs.hs view
@@ -1,8 +1,7 @@ module HERMIT.Dictionary.Navigation.Crumbs-       ( -- * Navigating Using Crumbs-         crumbExternals-       )-where+    ( -- * Navigating Using Crumbs+      crumbExternals+    ) where  import HERMIT.Core import HERMIT.External@@ -12,89 +11,106 @@ -- | 'External's for individual 'Crumb's. crumbExternals :: [External] crumbExternals = map (.+ Navigation)-            [-              external "prog" ModGuts_Prog-                [ "Descend into the program within a module." ]-            , external "prog-head" ProgCons_Head-                [ "Descend into the first binding group in a program." ]-            , external "prog-tail" ProgCons_Tail-                [ "Descend into the tail of the program." ]-            , external "nonrec-rhs" NonRec_RHS-                [ "Descend into the right-hand side of a non-recursive binding." ]-            , external "rec-def" Rec_Def-                [ "Descend into the (n-1)th definition in a recursive binding group." ]-            , external "def-rhs" Def_RHS-                [ "Descend into the right-hand side of a recursive definition." ]-            , external "app-fun" App_Fun-                [ "Descend into the function in an application." ]-            , external "app-arg" App_Arg-                [ "Descend into the argument in an application." ]-            , external "lam-body" Lam_Body-                [ "Descend into the body of a lambda." ]-            , external "let-bind" Let_Bind-                [ "Descend into the binding group of a let expression." ]-            , external "let-body" Let_Body-                [ "Descend into the body of a let expression." ]-            , external "case-expr" Case_Scrutinee-                [ "Descend into the scrutinised expression in a case expression." ]-            , external "case-type" Case_Type-                [ "Descend into the type of a case expression." ]-            , external "case-alt" Case_Alt-                [ "Descend into the (n-1)th alternative in a case expression." ]-            , external "cast-expr" Cast_Expr-                [ "Descend into the expression in a cast." ]-            , external "cast-co" Cast_Co-                [ "Descend into the coercion in a cast." ]-            , external "tick-expr" Tick_Expr-                [ "Descend into the expression in a tick." ]-            , external "alt-rhs" Alt_RHS-                [ "Descend into the right-hand side of a case alternative." ]-            , external "type" Type_Type-                [ "Descend into the type within a type expression." ]-            , external "coercion" Co_Co-                [ "Descend into the coercion within a coercion expression." ]-            , external "appTy-fun" AppTy_Fun-                [ "Descend into the type function in a type application." ]-            , external "appTy-arg" AppTy_Fun-                [ "Descend into the type argument in a type application." ]-            , external "tyCon-arg" TyConApp_Arg-                [ "Descend into the (n-1)th argument of a type constructor application." ]-            , external "fun-dom" FunTy_Dom-                [ "Descend into the domain of a function type." ]-            , external "fun-cod" FunTy_CoDom-                [ "Descend into the codomain of a function type." ]-            , external "forall-body" ForAllTy_Body-                [ "Descend into the body of a forall type." ]-            , external "refl-type" Refl_Type-                [ "Descend into the (n-1)th argument of a type constructor coercion." ]-            , external "coCon-arg" TyConAppCo_Arg-                [ "Descend into the function of a coercion application." ]-            , external "appCo-fun" AppCo_Fun-                [ "Descend into the coercion function in a coercion application." ]-            , external "appCo-arg" AppCo_Arg-                [ "Descend into the coercion argument in a coercion application." ]-            , external "coForall-body" ForAllCo_Body-                [ "Descend into the body of a forall coercion." ]-            , external "axiom-inst" AxiomInstCo_Arg-                [ "Descend into the (n-1)th argument of a coercion axiom instantiation." ]-            , external "unsafe-left" UnsafeCo_Left-                [ "Descend into the left-hand type of an unsafe coercion." ]-            , external "unsafe-right" UnsafeCo_Right-                [ "Descend into the right-hand type of an unsafe coercion." ]-            , external "sym-co" SymCo_Co-                [ "Descend into the coercion within a symmetric coercion." ]-            , external "trans-left" TransCo_Left-                [ "Descend into the left-hand type of a transitive coercion." ]-            , external "trans-right" TransCo_Right-                [ "Descend into the right-hand type of a transitive coercion." ]-            , external "nth-co" NthCo_Co-                [ "Descend into the coercion within an nth projection coercion." ]-            , external "inst-co" InstCo_Co-                [ "Descend into the coercion within a coercion instantiation." ]-            , external "inst-type" InstCo_Type-                [ "Descend into the type within a coercion instantiation." ]-            , external "lr-co" LRCo_Co-                [ "Descend into the coercion within a left/right projection coercion." ]-            ]+    [ external "prog" ModGuts_Prog+        [ "Descend into the program within a module." ]+    , external "prog-head" ProgCons_Head+        [ "Descend into the first binding group in a program." ]+    , external "prog-tail" ProgCons_Tail+        [ "Descend into the tail of the program." ]+    , external "nonrec-rhs" NonRec_RHS+        [ "Descend into the right-hand side of a non-recursive binding." ]+    , external "rec-def" Rec_Def+        [ "Descend into the (n-1)th definition in a recursive binding group." ]+    , external "def-rhs" Def_RHS+        [ "Descend into the right-hand side of a recursive definition." ]+    , external "app-fun" App_Fun+        [ "Descend into the function in an application." ]+    , external "app-arg" App_Arg+        [ "Descend into the argument in an application." ]+    , external "lam-body" Lam_Body+        [ "Descend into the body of a lambda." ]+    , external "let-bind" Let_Bind+        [ "Descend into the binding group of a let expression." ]+    , external "let-body" Let_Body+        [ "Descend into the body of a let expression." ]+    , external "case-expr" Case_Scrutinee+        [ "Descend into the scrutinised expression in a case expression." ]+    , external "case-type" Case_Type+        [ "Descend into the type of a case expression." ]+    , external "case-alt" Case_Alt+        [ "Descend into the (n-1)th alternative in a case expression." ]+    , external "cast-expr" Cast_Expr+        [ "Descend into the expression in a cast." ]+    , external "cast-co" Cast_Co+        [ "Descend into the coercion in a cast." ]+    , external "tick-expr" Tick_Expr+        [ "Descend into the expression in a tick." ]+    , external "alt-rhs" Alt_RHS+        [ "Descend into the right-hand side of a case alternative." ]+    , external "type" Type_Type+        [ "Descend into the type within a type expression." ]+    , external "coercion" Co_Co+        [ "Descend into the coercion within a coercion expression." ]+    , external "appTy-fun" AppTy_Fun+        [ "Descend into the type function in a type application." ]+    , external "appTy-arg" AppTy_Fun+        [ "Descend into the type argument in a type application." ]+    , external "tyCon-arg" TyConApp_Arg+        [ "Descend into the (n-1)th argument of a type constructor application." ]+    , external "fun-dom" FunTy_Dom+        [ "Descend into the domain of a function type." ]+    , external "fun-cod" FunTy_CoDom+        [ "Descend into the codomain of a function type." ]+    , external "forall-body" ForAllTy_Body+        [ "Descend into the body of a forall type." ]+    , external "refl-type" Refl_Type+        [ "Descend into the (n-1)th argument of a type constructor coercion." ]+    , external "coCon-arg" TyConAppCo_Arg+        [ "Descend into the function of a coercion application." ]+    , external "appCo-fun" AppCo_Fun+        [ "Descend into the coercion function in a coercion application." ]+    , external "appCo-arg" AppCo_Arg+        [ "Descend into the coercion argument in a coercion application." ]+    , external "coForall-body" ForAllCo_Body+        [ "Descend into the body of a forall coercion." ]+    , external "axiom-inst" AxiomInstCo_Arg+        [ "Descend into the (n-1)th argument of a coercion axiom instantiation." ]+    , external "unsafe-left" UnsafeCo_Left+        [ "Descend into the left-hand type of an unsafe coercion." ]+    , external "unsafe-right" UnsafeCo_Right+        [ "Descend into the right-hand type of an unsafe coercion." ]+    , external "sym-co" SymCo_Co+        [ "Descend into the coercion within a symmetric coercion." ]+    , external "trans-left" TransCo_Left+        [ "Descend into the left-hand type of a transitive coercion." ]+    , external "trans-right" TransCo_Right+        [ "Descend into the right-hand type of a transitive coercion." ]+    , external "nth-co" NthCo_Co+        [ "Descend into the coercion within an nth projection coercion." ]+    , external "inst-co" InstCo_Co+        [ "Descend into the coercion within a coercion instantiation." ]+    , external "inst-type" InstCo_Type+        [ "Descend into the type within a coercion instantiation." ]+    , external "lr-co" LRCo_Co+        [ "Descend into the coercion within a left/right projection coercion." ]+    , external "forall-body" Forall_Body+        [ "Descend into the clause of a quantified clause." ]+    , external "conj-lhs" Conj_Lhs+        [ "Descend into left-hand side of a conjunction." ]+    , external "conj-rhs" Conj_Rhs+        [ "Descend into right-hand side of a conjunction." ]+    , external "disj-lhs" Disj_Lhs+        [ "Descend into left-hand side of a disjunction." ]+    , external "disj-rhs" Disj_Rhs+        [ "Descend into right-hand side of a disjunction." ]+    , external "antecedent" Impl_Lhs+        [ "Descend into antecedent of an implication." ]+    , external "consequent" Impl_Rhs+        [ "Descend into consequent of an implication." ]+    , external "eq-lhs" Eq_Lhs+        [ "Descend into left-hand side of an equivalence." ]+    , external "eq-rhs" Eq_Rhs+        [ "Descend into right-hand side of an equivalence." ]+    ]  ---------------------------------------------------------------------------------------
src/HERMIT/Dictionary/New.hs view
@@ -14,11 +14,11 @@  externals ::  [External] externals = map ((.+ Experiment) . (.+ TODO))-         [ external "var" (promoteExprT . isVar :: String -> TransformH Core ())+         [ external "var" (promoteExprT . isVar :: String -> TransformH LCore ())                 [ "var '<v> returns successfully for variable v, and fails otherwise."                 , "Useful in combination with \"when\", as in: when (var v) r"                 ] .+ Predicate-         , external "nonrec-intro" (nonRecIntro :: String -> CoreString -> RewriteH Core)+         , external "nonrec-intro" ((\ s str -> promoteCoreR (nonRecIntro s str)) :: String -> CoreString -> RewriteH LCore)                 [ "Introduce a new non-recursive binding.  Only works at Expression or Program nodes."                 , "nonrec-into 'v [| e |]"                 , "body ==> let v = e in body"
src/HERMIT/Dictionary/Query.hs view
@@ -31,16 +31,17 @@ -- | Externals that reflect GHC functions, or are derived from GHC functions. externals :: [External] externals =-    [ external "info" (infoT :: TransformH CoreTC String)+    [ external "info" (promoteCoreTCT infoT :: TransformH LCoreTC String)         [ "Display information about the current node." ] .+ Query-    , external "compare-bound-ids" (compareBoundIds :: HermitName -> HermitName -> TransformH CoreTC ())+    , external "compare-bound-ids" (compareBoundIds :: HermitName -> HermitName -> TransformH LCoreTC ())         [ "Compare the definitions of two in-scope identifiers for alpha equality."] .+ Query .+ Predicate-    , external "compare-core-at" (compareCoreAtT ::  TransformH Core LocalPathH -> TransformH Core LocalPathH -> TransformH Core ())+    , external "compare-core-at" (compareCoreAtT ::  TransformH LCoreTC LocalPathH -> TransformH LCoreTC LocalPathH -> TransformH LCoreTC ())         [ "Compare the core fragments at the end of the given paths for alpha-equality."] .+ Query .+ Predicate     ]  -------------------------------------------------------- +-- TODO: update this to cope with lemmas infoT :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, BoundVars c, HasEmptyContext c, HasDynFlags m, MonadCatch m) => Transform c m CoreTC String infoT =   do crumbs <- childrenT@@ -162,12 +163,13 @@ --------------------------------------------------------  -- | Compare the core fragments at the end of the specified 'LocalPathH's.-compareCoreAtT :: (ExtendPath c Crumb, AddBindings c, ReadBindings c, ReadPath c Crumb, HasEmptyContext c, MonadCatch m) => Transform c m Core LocalPathH -> Transform c m Core LocalPathH -> Transform c m Core ()+compareCoreAtT :: (ExtendPath c Crumb, AddBindings c, ReadBindings c, ReadPath c Crumb, HasEmptyContext c, MonadCatch m) => Transform c m LCoreTC LocalPathH -> Transform c m LCoreTC LocalPathH -> Transform c m LCoreTC () compareCoreAtT p1T p2T =   do p1 <- p1T      p2 <- p2T-     core1 <- localPathT p1 idR-     core2 <- localPathT p2 idR+     -- TODO: temproary hack.  Need to properly check whether the paths point to COre or not, and report a decent error message+     LTCCore (LCore core1) <- localPathT p1 idR+     LTCCore (LCore core2) <- localPathT p2 idR      guardMsg (core1 `coreAlphaEq` core2) "core fragments are not alpha-equivalent."  -- | Compare the definitions of two identifiers for alpha-equality.
src/HERMIT/Dictionary/Reasoning.hs view
@@ -1,74 +1,89 @@-{-# LANGUAGE CPP, DeriveDataTypeable, FlexibleContexts, FlexibleInstances, InstanceSigs,-             ScopedTypeVariables, TupleSections, TypeFamilies #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE InstanceSigs #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TypeFamilies #-}  module HERMIT.Dictionary.Reasoning     ( -- * Equational Reasoning       externals     , EqualityProof-    , flipEquality     , eqLhsIntroR     , eqRhsIntroR     , birewrite     , extensionalityR     , getLemmasT     , getLemmaByNameT-    , insertLemmaR-    , lemmaR-    , markLemmaUsedR-    , modifyLemmaR-    -- ** Lifting transformations over 'Equality'+    , getObligationNotProvenT+    , insertLemmaT+    , insertLemmasT+    , lemmaBiR+    , lemmaConsequentR+    , markLemmaUsedT+    , markLemmaProvedT+    , markLemmaAssumedT+    , modifyLemmaT+    , showLemmaT+    , showLemmasT+    , ppLemmaT+    , ppQuantifiedT+    , ppLCoreTCT+      -- ** Lifting transformations over 'Quantified'     , lhsT     , rhsT     , bothT-    , forallVarsT     , lhsR     , rhsR     , bothR-    , ppEqualityT-    , proveEqualityT-    , verifyEqualityT+    , forallVarsT+    , verifyQuantifiedT+    , verifyEquivalentT+    , verifyOrCreateT+    , lintQuantifiedT     , verifyEqualityLeftToRightT     , verifyEqualityCommonTargetT     , verifyIsomorphismT     , verifyRetractionT     , retractionBR-    , alphaEqualityR-    , unshadowEqualityR+    , unshadowQuantifiedR     , instantiateDictsR-    , instantiateEquality-    , instantiateEqualityVar-    , instantiateEqualityVarR+    , instantiateQuantifiedVarR+    , abstractQuantifiedR     , discardUniVars     ) where -import           Control.Applicative-import           Control.Arrow+import           Control.Arrow hiding ((<+>)) import           Control.Monad-import           Control.Monad.IO.Class +import           Data.Either (partitionEithers)+import           Data.List (isInfixOf, nubBy) import qualified Data.Map as Map-import           Data.List (nubBy) import           Data.Maybe (fromMaybe) import           Data.Monoid  import           HERMIT.Context import           HERMIT.Core import           HERMIT.External-import           HERMIT.GHC+import           HERMIT.GHC hiding ((<>), (<+>), nest, ($+$)) import           HERMIT.Kure+import           HERMIT.Lemma import           HERMIT.Monad import           HERMIT.Name import           HERMIT.ParserCore import           HERMIT.ParserType import           HERMIT.PrettyPrinter.Common+import           HERMIT.PrettyPrinter.Clean (symbol) -- this should be in Common import           HERMIT.Utilities-                -import           HERMIT.Dictionary.AlphaConversion hiding (externals)+ import           HERMIT.Dictionary.Common import           HERMIT.Dictionary.Fold hiding (externals) import           HERMIT.Dictionary.GHC hiding (externals) import           HERMIT.Dictionary.Local.Let (nonRecIntroR)-import           HERMIT.Dictionary.Unfold hiding (externals)  import qualified Text.PrettyPrint.MarkedHughesPJ as PP @@ -76,71 +91,103 @@  externals :: [External] externals =-    [ external "retraction" ((\ f g r -> promoteExprBiR $ retraction (Just r) f g) :: CoreString -> CoreString -> RewriteH Core -> BiRewriteH Core)+    [ external "retraction" ((\ f g r -> promoteExprBiR $ retraction (Just r) f g) :: CoreString -> CoreString -> RewriteH LCore -> BiRewriteH LCore)         [ "Given f :: X -> Y and g :: Y -> X, and a proof that f (g y) ==> y, then"         , "f (g y) <==> y."         ] .+ Shallow-    , external "retraction-unsafe" ((\ f g -> promoteExprBiR $ retraction Nothing f g) :: CoreString -> CoreString -> BiRewriteH Core)+    , external "retraction-unsafe" ((\ f g -> promoteExprBiR $ retraction Nothing f g) :: CoreString -> CoreString -> BiRewriteH LCore)         [ "Given f :: X -> Y and g :: Y -> X, then"         , "f (g y) <==> y."         , "Note that the precondition (f (g y) == y) is expected to hold."         ] .+ Shallow .+ PreCondition-    , external "alpha-equality" ((\ nm newName -> alphaEqualityR (cmpString2Var nm) (const newName)))-        [ "Alpha-rename a universally quantified variable." ]-    , external "unshadow-equality" unshadowEqualityR-        [ "Unshadow an equality." ]-    , external "lemma" (promoteExprBiR . lemmaR :: LemmaName -> BiRewriteH Core)+    , external "unshadow-quantified" (promoteQuantifiedR unshadowQuantifiedR :: RewriteH LCoreTC)+        [ "Unshadow a quantified clause." ]+    , external "merge-quantifiers" (\n1 n2 -> promoteR (mergeQuantifiersR (cmpHN2Var n1) (cmpHN2Var n2)) :: RewriteH LCore)+        [ "Merge quantifiers from two clauses if they have the same type."+        , "Example:"+        , "(forall (x::Int). foo x = x) ^ (forall (y::Int). bar y y = 5)"+        , "merge-quantifiers 'x 'y"+        , "forall (x::Int). (foo x = x) ^ (bar x x = 5)"+        , "Note: if only one quantifier matches, it will be floated if possible." ]+    , external "float-left" (\n1 -> promoteR (mergeQuantifiersR (cmpHN2Var n1) (const False)) :: RewriteH LCore)+        [ "Float quantifier out of left-hand side." ]+    , external "float-right" (\n1 -> promoteR (mergeQuantifiersR (const False) (cmpHN2Var n1)) :: RewriteH LCore)+        [ "Float quantifier out of right-hand side." ]+    , external "conjunct" (\n1 n2 n3 -> conjunctLemmasT n1 n2 n3 :: TransformH LCore ())+        [ "conjunt new-name lhs-name rhs-name" ]+    , external "disjunct" (\n1 n2 n3 -> disjunctLemmasT n1 n2 n3 :: TransformH LCore ())+        [ "disjunt new-name lhs-name rhs-name" ]+    , external "imply" (\n1 n2 n3 -> implyLemmasT n1 n2 n3 :: TransformH LCore ())+        [ "imply new-name antecedent-name consequent-name" ]+    , external "lint" (promoteT lintQuantifiedT :: TransformH LCoreTC String)+        [ "Lint check a quantified clause." ]+    , external "lemma-birewrite" (promoteExprBiR . lemmaBiR Obligation :: LemmaName -> BiRewriteH LCore)         [ "Generate a bi-directional rewrite from a lemma." ]-    , external "lemma-lhs-intro" (lemmaLhsIntroR :: LemmaName -> RewriteH Core)+    , external "lemma-forward" (forwardT . promoteExprBiR . lemmaBiR Obligation :: LemmaName -> RewriteH LCore)+        [ "Generate a rewrite from a lemma, left-to-right." ]+    , external "lemma-backward" (backwardT . promoteExprBiR . lemmaBiR Obligation :: LemmaName -> RewriteH LCore)+        [ "Generate a rewrite from a lemma, right-to-left." ]+    , external "lemma-consequent" (promoteQuantifiedR . lemmaConsequentR Obligation :: LemmaName -> RewriteH LCore)+        [ "Match the current lemma with the consequent of an implication lemma."+        , "Upon success, replaces with antecedent of the implication, properly instantiated." ]+    , external "lemma-consequent-birewrite" (promoteExprBiR . lemmaConsequentBiR Obligation :: LemmaName -> BiRewriteH LCore)+        [ "Generate a bi-directional rewrite from the consequent of an implication lemma."+        , "The antecedent is instantiated and introduced as an unproven obligation." ]+    , external "lemma-lhs-intro" (promoteCoreR . lemmaLhsIntroR :: LemmaName -> RewriteH LCore)         [ "Introduce the LHS of a lemma as a non-recursive binding, in either an expression or a program."         , "body ==> let v = lhs in body" ] .+ Introduce .+ Shallow-    , external "lemma-rhs-intro" (lemmaRhsIntroR :: LemmaName -> RewriteH Core)+    , external "lemma-rhs-intro" (promoteCoreR . lemmaRhsIntroR :: LemmaName -> RewriteH LCore)         [ "Introduce the RHS of a lemma as a non-recursive binding, in either an expression or a program."         , "body ==> let v = rhs in body" ] .+ Introduce .+ Shallow-    , external "inst-lemma" (\ nm v cs -> modifyLemmaR nm id (instantiateEqualityVarR (cmpString2Var v) cs) id id :: RewriteH Core)+    , external "inst-lemma" (\ nm v cs -> modifyLemmaT nm id (instantiateQuantifiedVarR (cmpHN2Var v) cs) id id :: TransformH LCore ())         [ "Instantiate one of the universally quantified variables of the given lemma,"         , "with the given Core expression, creating a new lemma. Instantiating an"         , "already proven lemma will result in the new lemma being considered proven." ]-    , external "inst-lemma-dictionaries" (\ nm -> modifyLemmaR nm id instantiateDictsR id id :: RewriteH Core)-        [ "Instantiate all of the universally quantified dictionaries of the given lemma."-        , "Only works on dictionaries whose types are monomorphic (no free type variables)." ]-    , external "copy-lemma" (\ nm newName -> modifyLemmaR nm (const newName) idR id id :: RewriteH Core)+    , external "inst-dictionaries" (promoteQuantifiedR instantiateDictsR :: RewriteH LCore)+        [ "Instantiate all of the universally quantified dictionaries of the given lemma." ]+    , external "abstract" ((\nm -> promoteQuantifiedR . abstractQuantifiedR nm . csInQBodyT) :: String -> CoreString -> RewriteH LCore)+        [ "Weaken a lemma by abstracting an expression to a new quantifier." ]+    , external "abstract" ((\nm rr -> promoteQuantifiedR $ abstractQuantifiedR nm $ extractT rr >>> setFailMsg "path must focus on an expression" projectT) :: String -> RewriteH LCore -> RewriteH LCore)+        [ "Weaken a lemma by abstracting an expression to a new quantifier." ]+    , external "copy-lemma" (\ nm newName -> modifyLemmaT nm (const newName) idR id id :: TransformH LCore ())         [ "Copy a given lemma, with a new name." ]-    , external "modify-lemma" (\ nm rr -> modifyLemmaR nm id rr (const False) (const False) :: RewriteH Core)-        [ "Modify a given lemma. Resets the proven status to Not Proven and used status to Not Used." ]-    , external "query-lemma" ((\ nm t -> getLemmaByNameT nm >>> arr lemmaEq >>> t) :: LemmaName -> TransformH Equality String -> TransformH Core String)+    , external "modify-lemma" ((\ nm rr -> modifyLemmaT nm id (extractR rr) (const NotProven) (const NotUsed)) :: LemmaName -> RewriteH LCore -> TransformH LCore ())+        [ "Modify a given lemma. Resets proven status to Not Proven and used status to Not Used." ]+    , external "query-lemma" ((\ nm t -> getLemmaByNameT nm >>> arr lemmaQ >>> extractT t) :: LemmaName -> TransformH LCore String -> TransformH LCore String)         [ "Apply a transformation to a lemma, returning the result." ]-    , external "extensionality" (extensionalityR . Just :: String -> RewriteH Equality)+    , external "show-lemma" ((\pp n -> showLemmaT n pp) :: PrettyPrinter -> LemmaName -> PrettyH LCore)+        [ "Display a lemma." ]+    , external "show-lemmas" ((\pp n -> showLemmasT (Just n) pp) :: PrettyPrinter -> LemmaName -> PrettyH LCore)+        [ "List lemmas whose names match search string." ]+    , external "show-lemmas" (showLemmasT Nothing :: PrettyPrinter -> PrettyH LCore)+        [ "List lemmas." ]+    , external "extensionality" (promoteR . extensionalityR . Just :: String -> RewriteH LCore)         [ "Given a name 'x, then"         , "f == g  ==>  forall x.  f x == g x" ]-    , external "extensionality" (extensionalityR Nothing :: RewriteH Equality)+    , external "extensionality" (promoteR (extensionalityR Nothing) :: RewriteH LCore)         [ "f == g  ==>  forall x.  f x == g x" ]-    , external "lhs" (lhsR . extractR :: RewriteH Core -> RewriteH Equality)-        [ "Apply a rewrite to the LHS of an equality." ]-    , external "lhs" (lhsT . extractT :: TransformH CoreTC String -> TransformH Equality String)-        [ "Apply a transformation to the LHS of an equality." ]-    , external "rhs" (rhsR . extractR :: RewriteH Core -> RewriteH Equality)-        [ "Apply a rewrite to the RHS of an equality." ]-    , external "rhs" (rhsT . extractT :: TransformH CoreTC String -> TransformH Equality String)-        [ "Apply a transformation to the RHS of an equality." ]-    , external "both" (bothR . extractR :: RewriteH Core -> RewriteH Equality)+    , external "lhs" (promoteQuantifiedR . lhsR :: RewriteH LCore -> RewriteH LCore)+        [ "Apply a rewrite to the LHS of a quantified clause." ]+    , external "lhs" (promoteQuantifiedT . lhsT :: TransformH LCore String -> TransformH LCore String)+        [ "Apply a transformation to the LHS of a quantified clause." ]+    , external "rhs" (promoteQuantifiedR . rhsR :: RewriteH LCore -> RewriteH LCore)+        [ "Apply a rewrite to the RHS of a quantified clause." ]+    , external "rhs" (promoteQuantifiedT . rhsT :: TransformH LCore String -> TransformH LCore String)+        [ "Apply a transformation to the RHS of a quantified clause." ]+    , external "both" (promoteQuantifiedR . bothR :: RewriteH LCore -> RewriteH LCore)         [ "Apply a rewrite to both sides of an equality, succeeding if either succeed." ]-    , external "both" ((\t -> liftM (\(r,s) -> unlines [r,s]) (bothT (extractT t))) :: TransformH CoreTC String -> TransformH Equality String)-        [ "Apply a transformation to the RHS of an equality." ]+    , external "both" ((\t -> do (r,s) <- promoteQuantifiedT (bothT t); return (unlines [r,s])) :: TransformH LCore String -> TransformH LCore String)+        [ "Apply a transformation to both sides of a quantified clause." ]     ]  ------------------------------------------------------------------------------  type EqualityProof c m = (Rewrite c m CoreExpr, Rewrite c m CoreExpr) --- | Flip the LHS and RHS of a 'Equality'.-flipEquality :: Equality -> Equality-flipEquality (Equality xs lhs rhs) = Equality xs rhs lhs- -- | f == g  ==>  forall x.  f x == g x-extensionalityR :: Maybe String -> Rewrite c HermitM Equality+extensionalityR :: Maybe String -> Rewrite c HermitM Quantified extensionalityR mn = prefixFailMsg "extensionality failed: " $-  do Equality vs lhs rhs <- idR+  do Quantified vs (Equiv lhs rhs) <- idR       let tyL = exprKindOrType lhs          tyR = exprKindOrType rhs@@ -152,123 +199,179 @@       let x = varToCoreExpr v -     return $ Equality (vs ++ [v]) (mkCoreApp lhs x) (mkCoreApp rhs x)+     return $ Quantified (vs ++ [v]) $ Equiv (mkCoreApp lhs x) (mkCoreApp rhs x)  ------------------------------------------------------------------------------  -- | @e@ ==> @let v = lhs in e@-eqLhsIntroR :: Equality -> Rewrite c HermitM Core-eqLhsIntroR (Equality bs lhs _) = nonRecIntroR "lhs" (mkCoreLams bs lhs)+eqLhsIntroR :: Quantified -> Rewrite c HermitM Core+eqLhsIntroR (Quantified bs (Equiv lhs _)) = nonRecIntroR "lhs" (mkCoreLams bs lhs)+eqLhsIntroR _                             = fail "compound lemmas not supported."  -- | @e@ ==> @let v = rhs in e@-eqRhsIntroR :: Equality -> Rewrite c HermitM Core-eqRhsIntroR (Equality bs _ rhs) = nonRecIntroR "rhs" (mkCoreLams bs rhs)+eqRhsIntroR :: Quantified -> Rewrite c HermitM Core+eqRhsIntroR (Quantified bs (Equiv _ rhs)) = nonRecIntroR "rhs" (mkCoreLams bs rhs)+eqRhsIntroR _                             = fail "compound lemmas not supported."  ------------------------------------------------------------------------------ --- | Create a 'BiRewrite' from a 'Equality'.------ The high level idea: create a temporary function with two definitions.--- Fold one of the defintions, then immediately unfold the other.+-- | Create a 'BiRewrite' from a 'Quantified'. birewrite :: ( AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c              , ReadPath c Crumb, MonadCatch m, MonadUnique m )-          => Equality -> BiRewrite c m CoreExpr-birewrite (Equality bnds l r) = bidirectional (foldUnfold l r) (foldUnfold r l)-    where foldUnfold lhs rhs = transform $ \ c e -> do-            let lhsLam = mkCoreLams bnds lhs-            -- we use a unique, transitory variable for the 'function' we are folding-            v <- newIdH "biTemp" (exprType lhsLam)-            e' <- maybe (fail "folding LHS failed") return (fold v lhsLam e)-            let rhsLam = mkCoreLams bnds rhs-                -- create a temporary context with an unfolding for the-                -- transitory function so we can reuse unfoldR.-                c' = addHermitBindings [(v, NONREC rhsLam, mempty)] c-            applyT unfoldR c' e'+          => Quantified -> BiRewrite c m CoreExpr+birewrite q = bidirectional (foldUnfold "left" id) (foldUnfold "right" flipEquality)+    where foldUnfold side f = transform $ \ c ->+                                maybeM ("expression did not match "++side++"-hand side")+                                . fold (map f (toEqualities q)) c --- | Lift a transformation over 'CoreExpr' into a transformation over the left-hand side of a 'Equality'.-lhsT :: (AddBindings c, Monad m, ReadPath c Crumb) => Transform c m CoreExpr b -> Transform c m Equality b-lhsT t = idR >>= \ (Equality vs lhs _) -> return lhs >>> withVarsInScope vs t+------------------------------------------------------------------------------+-- TODO: deprecate these?+-- Yes, but later.  They're in the paper now.+-- We should be using "childR crumb", really. --- | Lift a transformation over 'CoreExpr' into a transformation over the right-hand side of a 'Equality'.-rhsT :: (AddBindings c, Monad m, ReadPath c Crumb) => Transform c m CoreExpr b -> Transform c m Equality b-rhsT t = idR >>= \ (Equality vs _ rhs) -> return rhs >>> withVarsInScope vs t+-- | Lift a transformation over 'LCoreTC' into a transformation over the left-hand side of a 'Quantified'.+lhsT :: (AddBindings c, ReadPath c Crumb, ExtendPath c Crumb, Monad m)+     => Transform c m LCore a -> Transform c m Quantified a+lhsT t = quantifiedT successT (clauseT t successT (\_ l _ -> l)) (flip const) --- | Lift a transformation over 'CoreExpr' into a transformation over both sides of a 'Equality'.-bothT :: (AddBindings c, Monad m, ReadPath c Crumb) => Transform c m CoreExpr b -> Transform c m Equality (b,b)-bothT t = liftM2 (,) (lhsT t) (rhsT t) -- Can't wait for Applicative to be a superclass of Monad+-- | Lift a transformation over 'LCoreTC' into a transformation over the right-hand side of a 'Quantified'.+rhsT :: (AddBindings c, ReadPath c Crumb, ExtendPath c Crumb, Monad m)+     => Transform c m LCore a -> Transform c m Quantified a+rhsT t = quantifiedT successT (clauseT successT t (\_ _ r -> r)) (flip const) --- | Lift a transformation over '[Var]' into a transformation over the universally quantified variables of a 'Equality'.-forallVarsT :: Monad m => Transform c m [Var] b -> Transform c m Equality b-forallVarsT t = idR >>= \ (Equality vs _ _) -> return vs >>> t+-- | Lift a transformation over 'LCoreTC' into a transformation over both sides of a 'Quantified'.+bothT :: (AddBindings c, ReadPath c Crumb, ExtendPath c Crumb, Monad m)+      => Transform c m LCore a -> Transform c m Quantified (a, a)+bothT t = quantifiedT successT (clauseT t t (const (,))) (flip const) --- | Lift a rewrite over 'CoreExpr' into a rewrite over the left-hand side of a 'Equality'.-lhsR :: (AddBindings c, Monad m, ReadPath c Crumb) => Rewrite c m CoreExpr -> Rewrite c m Equality-lhsR r = do-    Equality vs lhs rhs <- idR-    lhs' <- withVarsInScope vs r <<< return lhs-    return $ Equality vs lhs' rhs+-- | Lift a rewrite over 'LCoreTC' into a rewrite over the left-hand side of a 'Quantified'.+lhsR :: (AddBindings c, Monad m, ReadPath c Crumb, ExtendPath c Crumb)+     => Rewrite c m LCore -> Rewrite c m Quantified+lhsR r = quantifiedR idR (clauseR r idR) --- | Lift a rewrite over 'CoreExpr' into a rewrite over the right-hand side of a 'Equality'.-rhsR :: (AddBindings c, Monad m, ReadPath c Crumb) => Rewrite c m CoreExpr -> Rewrite c m Equality-rhsR r = do-    Equality vs lhs rhs <- idR-    rhs' <- withVarsInScope vs r <<< return rhs-    return $ Equality vs lhs rhs'+-- | Lift a rewrite over 'LCoreTC' into a rewrite over the right-hand side of a 'Quantified'.+rhsR :: (AddBindings c, Monad m, ReadPath c Crumb, ExtendPath c Crumb)+     => Rewrite c m LCore -> Rewrite c m Quantified+rhsR r = quantifiedR idR (clauseR idR r) --- | Lift a rewrite over 'CoreExpr' into a rewrite over both sides of a 'Equality'.-bothR :: (AddBindings c, MonadCatch m, ReadPath c Crumb) => Rewrite c m CoreExpr -> Rewrite c m Equality+-- | Lift a rewrite over 'LCoreTC' into a rewrite over both sides of a 'Quantified'.+bothR :: (AddBindings c, MonadCatch m, ReadPath c Crumb, ExtendPath c Crumb)+      => Rewrite c m LCore -> Rewrite c m Quantified bothR r = lhsR r >+> rhsR r  ------------------------------------------------------------------------------ -ppEqualityT :: PrettyPrinter -> TransformH Equality DocH-ppEqualityT pp = do-    let pos = pOptions pp-    d1 <- forallVarsT (liftPrettyH pos $ pForall pp)-    (d2,d3) <- bothT (liftPrettyH pos $ extractT $ pCoreTC pp)-    return $ PP.sep [d1,d2,syntaxColor (PP.text "="),d3]+-- | Original clause passed to function so it can decide how to handle connective.+clauseT :: (Monad m, ExtendPath c Crumb) => Transform c m LCore a -> Transform c m LCore b -> (Clause -> a -> b -> d) -> Transform c m Clause d+clauseT t1 t2 f = readerT $ \ cl -> case cl of+                                      Conj{}  -> conjT  (extractT t1) (extractT t2) (f cl)+                                      Disj{}  -> disjT  (extractT t1) (extractT t2) (f cl)+                                      Impl{}  -> implT  (extractT t1) (extractT t2) (f cl)+                                      Equiv{} -> equivT (extractT t1) (extractT t2) (f cl) +clauseR :: (Monad m, ExtendPath c Crumb) => Rewrite c m LCore -> Rewrite c m LCore -> Rewrite c m Clause+clauseR r1 r2 = readerT $ \case+                             Conj{}  -> conjAllR (extractR r1) (extractR r2)+                             Disj{}  -> disjAllR (extractR r1) (extractR r2)+                             Impl{}  -> implAllR (extractR r1) (extractR r2)+                             Equiv{} -> equivAllR (extractR r1) (extractR r2)++-- | Lift a transformation over '[Var]' into a transformation over the universally quantified variables of a 'Quantified'.+forallVarsT :: (AddBindings c, ReadPath c Crumb, ExtendPath c Crumb, Monad m) => Transform c m [Var] b -> Transform c m Quantified b+forallVarsT t = quantifiedT t successT const+ ------------------------------------------------------------------------------ --- Idea: use Haskell's functions to fill the holes automagically------ plusId <- findIdT "+"--- timesId <- findIdT "*"--- mkEquality $ \ x -> ( mkCoreApps (Var plusId)  [x,x]---                     , mkCoreApps (Var timesId) [Lit 2, x])------ TODO: need to know type of 'x' to generate a variable.-class BuildEquality a where-    mkEquality :: a -> HermitM Equality+showLemmasT :: Maybe LemmaName -> PrettyPrinter -> PrettyH a+showLemmasT mnm pp = do+    ls <- getLemmasT+    let ls' = Map.toList $ Map.filterWithKey (maybe (\ _ _ -> True) (\ nm n _ -> show nm `isInfixOf` show n) mnm) ls+    ds <- forM ls' $ \(nm,l) -> return l >>> ppLemmaT pp nm+    return $ PP.vcat ds -instance BuildEquality (CoreExpr,CoreExpr) where-    mkEquality :: (CoreExpr,CoreExpr) -> HermitM Equality-    mkEquality (lhs,rhs) = return $ Equality [] lhs rhs+showLemmaT :: LemmaName -> PrettyPrinter -> PrettyH a+showLemmaT nm pp = getLemmaByNameT nm >>> ppLemmaT pp nm -instance BuildEquality a => BuildEquality (CoreExpr -> a) where-    mkEquality :: (CoreExpr -> a) -> HermitM Equality-    mkEquality f = do-        x <- newIdH "x" (error "need to create a type")-        Equality bnds lhs rhs <- mkEquality (f (varToCoreExpr x))-        return $ Equality (x:bnds) lhs rhs+ppLemmaT :: PrettyPrinter -> LemmaName -> PrettyH Lemma+ppLemmaT pp nm = do+    Lemma q p _u _t <- idR+    qDoc <- return q >>> ppQuantifiedT pp+    let hDoc = PP.text (show nm) PP.<+> PP.text ("(" ++ show p ++ ")")+    return $ hDoc PP.$+$ PP.nest 2 qDoc +ppLCoreTCT :: PrettyPrinter -> PrettyH LCoreTC+ppLCoreTCT pp = promoteT (ppQuantifiedT pp) <+ promoteT (ppClauseT pp) <+ promoteT (pCoreTC pp)++ppQuantifiedT :: PrettyPrinter -> PrettyH Quantified+ppQuantifiedT pp = do+    (d1,d2) <- quantifiedT (pForall pp) (ppClauseT pp) (,)+    return $ PP.sep [d1,d2]++ppClauseT :: PrettyPrinter -> PrettyH Clause+ppClauseT pp = do+    let t = absPathT &&& (promoteT (ppQuantifiedT pp) <+ promoteT (extractT (pCoreTC pp) :: PrettyH Core)) -- TODO: temporary hack, need to think about what's going on here and fix it+        parenify (p1,d1) (p2,d2) o = ( symbol p1 '(' PP.<> d1 PP.<> symbol p1 ')'+                                     , symbol p2 '(' PP.<> d2 PP.<> symbol p2 ')'+                                     , syntaxColor (PP.text o)+                                     )+    (d1,d2,oper) <- clauseT t t (\ cl r1 r2 ->+                                    case cl of+                                        Conj {} -> parenify r1 r2 "^"+                                        Disj {} -> parenify r1 r2 "v"+                                        Impl {} -> parenify r1 r2 "=>"+                                        Equiv {} -> (snd r1, snd r2, syntaxColor $ PP.text "="))+    return $ PP.sep [d1,oper,d2]+ ------------------------------------------------------------------------------ --- | Verify that a 'Equality' holds, by applying a rewrite to each side, and checking that the results are equal.-proveEqualityT :: forall c m. (AddBindings c, Monad m, ReadPath c Crumb)-                        => EqualityProof c m -> Transform c m Equality ()-proveEqualityT (l,r) = lhsR l >>> rhsR r >>> verifyEqualityT+verifyQuantifiedT :: (AddBindings c, ReadPath c Crumb, ExtendPath c Crumb, MonadCatch m) => Transform c m Quantified ()+verifyQuantifiedT = quantifiedT successT verifyClauseT (flip const) --- | Verify that the left- and right-hand sides of a 'Equality' are alpha equivalent.-verifyEqualityT :: Monad m => Transform c m Equality ()-verifyEqualityT = do-    Equality _ lhs rhs <- idR-    guardMsg (exprAlphaEq lhs rhs) "the two sides of the equality do not match."+verifyClauseT :: (AddBindings c, ReadPath c Crumb, ExtendPath c Crumb, MonadCatch m) => Transform c m Clause ()+verifyClauseT =+    readerT (\case Conj  q1 q2 -> (return q1 >>> verifyQuantifiedT) >> (return q2 >>> verifyQuantifiedT)+                   Disj  q1 q2 -> (return q1 >>> verifyQuantifiedT) <+ (return q2 >>> verifyQuantifiedT)+                   Impl  _  _  -> fail "verifyClauseT: Impl TODO"+                   Equiv e1 e2 -> guardMsg (exprAlphaEq e1 e2) "the two sides of the equality do not match.") +verifyEquivalentT :: (HasLemmas m, MonadCatch m) => Used -> LemmaName -> Transform c m Quantified ()+verifyEquivalentT used nm = prefixFailMsg "verification failed: " $ do+    Lemma q _ _ _ <- getLemmaByNameT nm+    eq <- arr (q `proves`)+    guardMsg eq "lemmas are not equivalent."+    markLemmaUsedT nm used++verifyOrCreateT :: (HasLemmas m, MonadCatch m) => Used -> LemmaName -> Lemma -> Transform c m a ()+verifyOrCreateT u nm l = do+    exists <- testM $ getLemmaByNameT nm+    if exists+    then return (lemmaQ l) >>> verifyEquivalentT u nm+    else insertLemmaT nm l+ ------------------------------------------------------------------------------ --- TODO: are these other functions used? If so, can they be rewritten in terms of lhsR and rhsR as above?+lintQuantifiedT :: (AddBindings c, BoundVars c, ReadPath c Crumb, ExtendPath c Crumb, HasDynFlags m, MonadCatch m)+                => Transform c m Quantified String+lintQuantifiedT = lintQuantifiedWorkT [] +lintQuantifiedWorkT :: (AddBindings c, BoundVars c, ReadPath c Crumb, ExtendPath c Crumb, HasDynFlags m, MonadCatch m)+                    => [Var] -> Transform c m Quantified String+lintQuantifiedWorkT bs = readerT $ \ (Quantified bs' _) -> quantifiedT successT (lintClauseT (bs++bs')) (flip const)++lintClauseT :: (AddBindings c, BoundVars c, ReadPath c Crumb, ExtendPath c Crumb, HasDynFlags m, MonadCatch m)+            => [Var] -> Transform c m Clause String+lintClauseT bs = do+    t <- readerT $ \case Equiv {} -> return $ promoteT ({- arr (mkCoreLams bs) >>> -} lintExprT) -- TODO: why does this break core lint?!+                         _        -> return $ promoteT (lintQuantifiedWorkT bs)+    (w1,w2) <- clauseT t t (const (,))+    return $ unlines [w1,w2]++------------------------------------------------------------------------------++-- TODO: everything between here and instantiateDictsR needs to be rethought/removed++-- TODO: this is used in century plugin, but otherwise should be removed+ -- | Given two expressions, and a rewrite from the former to the latter, verify that rewrite. verifyEqualityLeftToRightT :: MonadCatch m => CoreExpr -> CoreExpr -> Rewrite c m CoreExpr -> Transform c m a () verifyEqualityLeftToRightT sourceExpr targetExpr r =@@ -331,13 +434,13 @@          return y  -- | Given @f :: X -> Y@ and @g :: Y -> X@, and a proof that @f (g y)@ ==> @y@, then @f (g y)@ <==> @y@.-retraction :: Maybe (RewriteH Core) -> CoreString -> CoreString -> BiRewriteH CoreExpr+retraction :: Maybe (RewriteH LCore) -> CoreString -> CoreString -> BiRewriteH CoreExpr retraction mr = parse2beforeBiR (retractionBR (extractR <$> mr))  ------------------------------------------------------------------------------  -- TODO: revisit this for binder re-ordering issue-instantiateDictsR :: RewriteH Equality+instantiateDictsR :: RewriteH Quantified instantiateDictsR = prefixFailMsg "Dictionary instantiation failed: " $ do     bs <- forallVarsT idR     let dArgs = filter (\b -> isId b && isDictTy (varType b)) bs@@ -346,160 +449,264 @@     ds <- forM uniqDs $ \ b -> constT $ do             (i,bnds) <- buildDictionary b             let dExpr = case bnds of-                            [NonRec v e] | i == v -> e -- the common case that we would have gotten a single non-recursive let+                            -- the common case that we would have gotten a single non-recursive let+                            [NonRec v e] | i == v -> e                             _ -> mkCoreLets bnds (varToCoreExpr i)-                new = varSetElems $ delVarSetList (localFreeVarsExpr dExpr) bs-            return (b,dExpr,new)-    let buildSubst :: Monad m => Var -> m (Var, CoreExpr, [Var])-        buildSubst b = case [ (b,e,[]) | (b',e,_) <- ds, eqType (varType b) (varType b') ] of+            return (b,dExpr)+    let buildSubst :: Monad m => Var -> m (Var, CoreExpr)+        buildSubst b = case [ (b,e) | (b',e) <- ds, eqType (varType b) (varType b') ] of                         [] -> fail "cannot find equivalent dictionary expression (impossible!)"                         [t] -> return t                         _   -> fail "multiple dictionary expressions found (impossible!)"-        lookup3 :: Var -> [(Var,CoreExpr,[Var])] -> (Var,CoreExpr,[Var])-        lookup3 v l = head [ t | t@(v',_,_) <- l, v == v' ]+        lookup2 :: Var -> [(Var,CoreExpr)] -> (Var,CoreExpr)+        lookup2 v l = head [ t | t@(v',_) <- l, v == v' ]     allDs <- forM dArgs $ \ b -> constT $ do                 if b `elem` uniqDs-                then return $ lookup3 b ds+                then return $ lookup2 b ds                 else buildSubst b-    contextfreeT $ instantiateEquality allDs+    transform (\ c -> instsQuantified (boundVars c) allDs) >>> arr redundantDicts  ------------------------------------------------------------------------------ -alphaEqualityR :: (Var -> Bool) -> (String -> String) -> RewriteH Equality-alphaEqualityR p f = prefixFailMsg "Alpha-renaming binder in equality failed: " $ do-    Equality bs lhs rhs <- idR-    guardMsg (any p bs) "specified variable is not universally quantified."+conjunctLemmasT :: (HasLemmas m, Monad m) => LemmaName -> LemmaName -> LemmaName -> Transform c m a ()+conjunctLemmasT new lhs rhs = do+    Lemma ql pl _ tl <- getLemmaByNameT lhs+    Lemma qr pr _ tr <- getLemmaByNameT rhs+    insertLemmaT new $ Lemma (Quantified [] (Conj ql qr)) (pl `andP` pr) NotUsed (tl || tr) -    let (bs',i:vs) = break p bs -- this is safe because we know i is in bs-    i' <- constT $ cloneVarH f i+disjunctLemmasT :: (HasLemmas m, Monad m) => LemmaName -> LemmaName -> LemmaName -> Transform c m a ()+disjunctLemmasT new lhs rhs = do+    Lemma ql pl _ tl <- getLemmaByNameT lhs+    Lemma qr pr _ tr <- getLemmaByNameT rhs+    insertLemmaT new $ Lemma (Quantified [] (Disj ql qr)) (pl `orP` pr) NotUsed (tl || tr) -    let inS           = delVarSetList (unionVarSets (map localFreeVarsExpr [lhs, rhs] ++ map freeVarsVar vs)) (i:i':vs)-        subst         = extendSubst (mkEmptySubst (mkInScopeSet inS)) i (varToCoreExpr i')-        (subst', vs') = substBndrs subst vs-        lhs'          = substExpr (text "coreExprEquality-lhs") subst' lhs-        rhs'          = substExpr (text "coreExprEquality-rhs") subst' rhs-    return $ Equality (bs'++(i':vs')) lhs' rhs'+implyLemmasT :: (HasLemmas m, Monad m) => LemmaName -> LemmaName -> LemmaName -> Transform c m a ()+implyLemmasT new lhs rhs = do+    Lemma ql _  _ tl <- getLemmaByNameT lhs+    Lemma qr pr _ tr <- getLemmaByNameT rhs+    insertLemmaT new $ Lemma (Quantified [] (Impl ql qr)) pr NotUsed (tl || tr) -unshadowEqualityR :: RewriteH Equality-unshadowEqualityR = prefixFailMsg "Unshadowing equality failed: " $ do-    c@(Equality bs _ _) <- idR-    bvs <- boundVarsT-    let visible = unionVarSets [bvs , freeVarsEquality c]-    ss <- varSetElems <$> detectShadowsM bs visible-    guardMsg (not (null ss)) "no shadows to eliminate."-    let f = freshNameGenAvoiding Nothing . extendVarSet visible-    andR [ alphaEqualityR (==s) (f s) | s <- reverse ss ] >>> bothR (tryR unshadowExprR)+------------------------------------------------------------------------------ -freeVarsEquality :: Equality -> VarSet-freeVarsEquality (Equality bs lhs rhs) =-    delVarSetList (unionVarSets (map freeVarsExpr [lhs,rhs])) bs+mergeQuantifiersR :: MonadCatch m => (Var -> Bool) -> (Var -> Bool) -> Rewrite c m Quantified+mergeQuantifiersR pl pr = contextfreeT $ mergeQuantifiers pl pr +mergeQuantifiers :: MonadCatch m => (Var -> Bool) -> (Var -> Bool) -> Quantified -> m Quantified+mergeQuantifiers pl pr (Quantified bs cl) = prefixFailMsg "merge-quantifiers failed: " $ do+    (con,lq@(Quantified bsl cll),rq@(Quantified bsr clr)) <- case cl of+        Conj q1 q2 -> return (Conj,q1,q2)+        Disj q1 q2 -> return (Disj,q1,q2)+        Impl q1 q2 -> return (Impl,q1,q2)+        _ -> fail "no quantifiers on either side."++    let (lBefore,lbs) = break pl bsl+        (rBefore,rbs) = break pr bsr+        check b q l r = guardMsg (not (b `elemVarSet` freeVarsQuantified q)) $+                                 "specified "++l++" binder would capture in "++r++"-hand clause."+        checkUB v vs = let fvs = freeVarsVar v+                       in guardMsg (not (any (`elemVarSet` fvs) vs)) $ "binder " ++ getOccString v +++                            " cannot be floated because it depends on binders not being floated."++    case (lbs,rbs) of+        ([],[])        -> fail "no quantifiers match."+        ([],rb:rAfter) -> do+            check rb lq "right" "left"+            checkUB rb rBefore+            return $ Quantified (bs++[rb]) $ con lq (Quantified (rBefore++rAfter) clr)+        (lb:lAfter,[]) -> do+            check lb rq "left" "right"+            checkUB lb lBefore+            return $ Quantified (bs++[lb]) $ con (Quantified (lBefore++lAfter) cll) rq+        (lb:lAfter,rb:rAfter) -> do+            guardMsg (eqType (varType lb) (varType rb)) "specified quantifiers have differing types."+            check lb rq "left" "right"+            check rb lq "right" "left"+            checkUB lb lBefore+            checkUB rb rBefore++            let Quantified partial clr' = substQuantified rb (varToCoreExpr lb) $ Quantified rAfter clr+                rq' = Quantified (rBefore ++ partial) clr'+                lq' = Quantified (lBefore ++ lAfter) cll++            return $ Quantified (bs++[lb]) (con lq' rq')+ ------------------------------------------------------------------------------ -instantiateEqualityVarR :: (Var -> Bool) -> CoreString -> RewriteH Equality-instantiateEqualityVarR p cs = prefixFailMsg "instantiation failed: " $ do-    bs <- forallVarsT idR-    (e,new) <- case filter p bs of-                [] -> fail "no universally quantified variables match predicate."-                (b:_) | isId b    -> let (before,_) = break (==b) bs-                                     in liftM (,[]) $ withVarsInScope before $ parseCoreExprT cs-                      | otherwise -> do let (before,_) = break (==b) bs-                                        (ty, tvs) <- withVarsInScope before $ parseTypeWithHolesT cs-                                        return (Type ty, tvs)-    eq <- contextfreeT $ instantiateEqualityVar p e new-    (_,_) <- return eq >>> bothT lintExprT -- sanity check-    return eq+unshadowQuantifiedR :: MonadUnique m => Rewrite c m Quantified+unshadowQuantifiedR = contextfreeT unshadowQuantified --- | Instantiate one of the universally quantified variables in a 'Equality'.--- Note: assumes implicit ordering of variables, such that substitution happens to the right--- as it does in case alternatives. Only first variable that matches predicate is--- instantiated.-instantiateEqualityVar :: MonadIO m => (Var -> Bool) -- predicate to select var-                                    -> CoreExpr      -- expression to instantiate with-                                    -> [Var]         -- new binders to add in place of var-                                    -> Equality -> m Equality-instantiateEqualityVar p e new (Equality bs lhs rhs)-    | not (any p bs) = fail "specified variable is not universally quantified."-    | otherwise = do-        let (bs',i:vs) = break p bs -- this is safe because we know i is in bs-            tyVars    = filter isTyVar bs'-            failMsg   = fail "type of provided expression differs from selected binder."+unshadowQuantified :: MonadUnique m => Quantified -> m Quantified+unshadowQuantified q = go emptySubst (mapUniqSet fs (freeVarsQuantified q)) q+    where fs = occNameFS . getOccName -            -- unifyTypes will give back mappings from a TyVar to itself-            -- we don't want to do these instantiations, or else variables-            -- become unbound-            dropSelfSubst :: [(TyVar, Type)] -> [(TyVar,Type)]-            dropSelfSubst ps = [ (v,t) | (v,t) <- ps, case t of-                                                        TyVarTy v' | v' == v -> False-                                                        _ -> True ]-        tvs <- maybe failMsg (return . tyMatchesToCoreExpr . dropSelfSubst)-                $ unifyTypes tyVars (varType i) (exprKindOrType e)+          go subst seen (Quantified bs cl) = go1 subst seen bs [] cl -        let inS           = delVarSetList (unionVarSets (map localFreeVarsExpr [lhs, rhs, e] ++ map freeVarsVar vs)) (i:vs)-            subst         = extendSubst (mkEmptySubst (mkInScopeSet inS)) i e-            (subst', vs') = substBndrs subst vs-            lhs'          = substExpr (text "equality-lhs") subst' lhs-            rhs'          = substExpr (text "equality-rhs") subst' rhs-        instantiateEquality (noAdds tvs) $ Equality (bs'++new++vs') lhs' rhs'+          go1 subst seen []     bs' cl = do+            cl' <- go2 subst seen cl+            return $ Quantified (reverse bs') cl'+          go1 subst seen (b:bs) bs' cl+            | fsb `elementOfUniqSet` seen = do+                b'' <- cloneVarFSH (inventNames seen) b'+                go1 (extendSubst subst' b' (varToCoreExpr b'')) (addOneToUniqSet seen (fs b'')) bs (b'':bs') cl+            | otherwise = go1 subst' (addOneToUniqSet seen fsb) bs (b':bs') cl+                where fsb = fs b'+                      (subst', b') = substBndr subst b -noAdds :: [(Var,CoreExpr)] -> [(Var,CoreExpr,[Var])]-noAdds ps = [ (v,e,[]) | (v,e) <- ps ]+          go2 subst seen (Conj q1 q2) = do+            q1' <- go subst seen q1+            q2' <- go subst seen q2+            return $ Conj q1' q2'+          go2 subst seen (Disj q1 q2) = do+            q1' <- go subst seen q1+            q2' <- go subst seen q2+            return $ Disj q1' q2'+          go2 subst seen (Impl q1 q2) = do+            q1' <- go subst seen q1+            q2' <- go subst seen q2+            return $ Impl q1' q2'+          go2 subst _ (Equiv e1 e2) =+            let e1' = substExpr (text "unshadowQuantified e1") subst e1+                e2' = substExpr (text "unshadowQuantified e2") subst e2+            in return $ Equiv e1' e2' --- | Instantiate a set of universally quantified variables in a 'Equality'.--- It is important that all type variables appear before any value-level variables in the first argument.-instantiateEquality :: MonadIO m => [(Var,CoreExpr,[Var])] -> Equality -> m Equality-instantiateEquality = flip (foldM (\ eq (v,e,vs) -> instantiateEqualityVar (==v) e vs eq)) . reverse--- foldM is a left-to-right fold, so the reverse is important to do substitutions in reverse order--- which is what we want (all value variables should be instantiated before type variables).+inventNames :: UniqSet FastString -> FastString -> FastString+inventNames s nm = head [ nm' | i :: Int <- [0..]+                              , let nm' = nm `appendFS` (mkFastString (show i))+                              , not (nm' `elementOfUniqSet` s) ]  ------------------------------------------------------------------------------ -discardUniVars :: Equality -> Equality-discardUniVars (Equality _ lhs rhs) = Equality [] lhs rhs+instantiateQuantifiedVarR :: (Var -> Bool) -> CoreString -> RewriteH Quantified+instantiateQuantifiedVarR p cs = prefixFailMsg "instantiation failed: " $ do+    bs <- forallVarsT idR+    e <- case filter p bs of+                [] -> fail "no universally quantified variables match predicate."+                (b:_) | isId b    -> let (before,_) = break (==b) bs+                                     in withVarsInScope before $ parseCoreExprT cs+                      | otherwise -> let (before,_) = break (==b) bs+                                     in liftM (Type . fst) $ withVarsInScope before $ parseTypeWithHolesT cs+    transform (\ c -> instQuantified (boundVars c) p e) >>> (lintQuantifiedT >> idR) -- lint for sanity  ------------------------------------------------------------------------------ +-- | Replace all occurrences of the given expression with a new quantified variable.+abstractQuantifiedR :: forall c m.+                       ( AddBindings c, BoundVars c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb+                       , HasDebugChan m, HasHermitMEnv m, HasLemmas m, LiftCoreM m, MonadCatch m, MonadUnique m )+                    => String -> Transform c m Quantified CoreExpr -> Rewrite c m Quantified+abstractQuantifiedR nm tr = prefixFailMsg "abstraction failed: " $ do+    e <- tr+    Quantified bs cl <- idR+    b <- constT $ newVarH nm (exprKindOrType e)+    let f = compileFold [Equality [] e (varToCoreExpr b)] -- we don't use mkEquality on purpose, so we can abstract lambdas+    liftM dropBinders $ return (Quantified (bs++[b]) cl) >>>+                            extractR (anytdR $ promoteExprR $ runFoldR f :: Rewrite c m LCoreTC)++csInQBodyT :: ( AddBindings c, ReadBindings c, ReadPath c Crumb, HasDebugChan m, HasHermitMEnv m, HasLemmas m, LiftCoreM m ) => CoreString -> Transform c m Quantified CoreExpr+csInQBodyT cs = do+    Quantified bs _ <- idR+    withVarsInScope bs $ parseCoreExprT cs++------------------------------------------------------------------------------+ getLemmasT :: HasLemmas m => Transform c m x Lemmas getLemmasT = constT getLemmas  getLemmaByNameT :: (HasLemmas m, Monad m) => LemmaName -> Transform c m x Lemma getLemmaByNameT nm = getLemmasT >>= maybe (fail $ "No lemma named: " ++ show nm) return . Map.lookup nm -lemmaR :: LemmaName -> BiRewriteH CoreExpr-lemmaR nm = afterBiR (beforeBiR (getLemmaByNameT nm) (birewrite . lemmaEq)) (markLemmaUsedR nm)+getObligationNotProvenT :: (HasLemmas m, Monad m) => Transform c m x [NamedLemma]+getObligationNotProvenT = do+    ls <- getLemmasT+    return [ (nm,l) | (nm, l@(Lemma _ NotProven Obligation _)) <- Map.toList ls ]  ------------------------------------------------------------------------------ --- We use sideEffectR because only rewrites generate new state in the Kernel.+lemmaBiR :: ( AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb+            , HasLemmas m, MonadCatch m, MonadUnique m)+         => Used -> LemmaName -> BiRewrite c m CoreExpr+lemmaBiR u nm = afterBiR (beforeBiR (getLemmaByNameT nm) (birewrite . lemmaQ)) (markLemmaUsedT nm u >> idR) -insertLemmaR :: (HasLemmas m, Monad m) => LemmaName -> Lemma -> Rewrite c m a-insertLemmaR nm l = sideEffectR $ \ _ _ -> insertLemma nm l+lemmaConsequentR :: forall c m. ( AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c+                                , ReadPath c Crumb, HasLemmas m, MonadCatch m, MonadUnique m)+                 => Used -> LemmaName -> Rewrite c m Quantified+lemmaConsequentR u nm = prefixFailMsg "lemma-consequent failed:" $+                        withPatFailMsg "lemma is not an implication." $ do+    Quantified hs (Impl ante con) <- lemmaQ <$> getLemmaByNameT nm+    q' <- transform $ \ c q -> do+        m <- maybeM ("consequent did not match.") $ lemmaMatch hs con q+        subs <- maybeM ("some quantifiers not instantiated.") $+                mapM (\h -> (h,) <$> lookupVarEnv m h) hs+        let q' = substQuantifieds subs ante+        guardMsg (all (inScope c) $ varSetElems (freeVarsQuantified q'))+                 "some variables in result would be out of scope."+        return q'+    markLemmaUsedT nm u+    return q' -modifyLemmaR :: (HasLemmas m, Monad m)+lemmaConsequentBiR :: forall c m. ( AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c+                                  , ReadPath c Crumb, HasLemmas m, MonadCatch m, MonadUnique m)+                   => Used -> LemmaName -> BiRewrite c m CoreExpr+lemmaConsequentBiR u nm = afterBiR (beforeBiR (getLemmaByNameT nm) (go . lemmaQ)) (markLemmaUsedT nm u >> idR)+    where go :: Quantified -> BiRewrite c m CoreExpr+          go (Quantified bs (Impl ante (Quantified bs' cl))) = do+            let eqs = toEqualities $ Quantified (bs++bs') cl -- consequent+                foldUnfold side f =+                    transform $ \ c e -> do+                        let cf = compileFold $ map f eqs+                        (e',hs) <- maybeM ("expression did not match "++side++"-hand side") $ runFoldMatches cf c e+                        let matches = [ case lookupVarEnv hs b of+                                            Nothing -> Left b+                                            Just arg -> Right (b,arg)+                                      | b <- bs ]+                            (unmatched, subs) = partitionEithers matches+                            Quantified aBs acl = substQuantifieds subs ante+                            q = Quantified (unmatched++aBs) acl+                        insertLemma (nm <> "-antecedent") $ Lemma q NotProven u True+                        return e'+            bidirectional (foldUnfold "left" id) (foldUnfold "right" flipEquality)+          go _ = let t = fail $ show nm ++ " is not an implication."+                 in bidirectional t t++------------------------------------------------------------------------------++insertLemmaT :: (HasLemmas m, Monad m) => LemmaName -> Lemma -> Transform c m a ()+insertLemmaT nm l = constT $ insertLemma nm l++insertLemmasT :: (HasLemmas m, Monad m) => [NamedLemma] -> Transform c m a ()+insertLemmasT = constT . mapM_ (uncurry insertLemma)++modifyLemmaT :: (HasLemmas m, Monad m)              => LemmaName              -> (LemmaName -> LemmaName) -- ^ modify lemma name-             -> Rewrite c m Equality     -- ^ rewrite the equality-             -> (Bool -> Bool)           -- ^ modify proven status-             -> (Bool -> Bool)           -- ^ modify used status-             -> Rewrite c m a-modifyLemmaR nm nFn rr pFn uFn = do-    Lemma eq p u <- getLemmaByNameT nm-    eq' <- rr <<< return eq-    sideEffectR $ \ _ _ -> insertLemma (nFn nm) $ Lemma eq' (pFn p) (uFn u)+             -> Rewrite c m Quantified   -- ^ rewrite the quantified clause+             -> (Proven -> Proven)       -- ^ modify proven status+             -> (Used -> Used)           -- ^ modify used status+             -> Transform c m a ()+modifyLemmaT nm nFn rr pFn uFn = do+    Lemma q p u t <- getLemmaByNameT nm+    q' <- rr <<< return q+    constT $ insertLemma (nFn nm) $ Lemma q' (pFn p) (uFn u) t -markLemmaUsedR :: (HasLemmas m, Monad m) => LemmaName -> Rewrite c m a-markLemmaUsedR nm = modifyLemmaR nm id idR id (const True)+markLemmaUsedT :: (HasLemmas m, Monad m) => LemmaName -> Used -> Transform c m a ()+markLemmaUsedT nm u = modifyLemmaT nm id idR id (const u) +markLemmaProvedT :: (HasLemmas m, Monad m) => LemmaName -> Transform c m a ()+markLemmaProvedT nm = modifyLemmaT nm id idR (const Proven) id++markLemmaAssumedT :: (HasLemmas m, Monad m) => Bool -> LemmaName -> Transform c m a ()+markLemmaAssumedT user nm = modifyLemmaT nm id idR (const (Assumed user)) id ------------------------------------------------------------------------------ -lemmaNameToEqualityT :: (HasLemmas m, Monad m) => LemmaName -> Transform c m x Equality-lemmaNameToEqualityT nm = liftM lemmaEq $ getLemmaByNameT nm+lemmaNameToQuantifiedT :: (HasLemmas m, Monad m) => LemmaName -> Transform c m x Quantified+lemmaNameToQuantifiedT nm = liftM lemmaQ $ getLemmaByNameT nm  -- | @e@ ==> @let v = lhs in e@  (also works in a similar manner at Program nodes) lemmaLhsIntroR :: LemmaName -> RewriteH Core-lemmaLhsIntroR = lemmaNameToEqualityT >=> eqLhsIntroR+lemmaLhsIntroR = lemmaNameToQuantifiedT >=> eqLhsIntroR  -- | @e@ ==> @let v = rhs in e@  (also works in a similar manner at Program nodes) lemmaRhsIntroR :: LemmaName -> RewriteH Core-lemmaRhsIntroR = lemmaNameToEqualityT >=> eqRhsIntroR+lemmaRhsIntroR = lemmaNameToQuantifiedT >=> eqRhsIntroR +------------------------------------------------------------------------------
+ src/HERMIT/Dictionary/Remembered.hs view
@@ -0,0 +1,87 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TupleSections #-}++module HERMIT.Dictionary.Remembered+    ( -- * Remembering definitions.+      externals+    , prefixRemembered+    , rememberR+    , unfoldRememberedR+    , foldRememberedR+    , foldAnyRememberedR+    , compileRememberedT+    ) where++import           Control.Monad++import qualified Data.Map as Map+import           Data.List (isPrefixOf)+import           Data.Monoid++import           HERMIT.Context+import           HERMIT.Core+import           HERMIT.External+import           HERMIT.GHC hiding ((<>), (<+>), nest, ($+$))+import           HERMIT.Kure+import           HERMIT.Lemma+import           HERMIT.Monad+import           HERMIT.PrettyPrinter.Common++import           HERMIT.Dictionary.Fold hiding (externals)+import           HERMIT.Dictionary.Reasoning hiding (externals)++------------------------------------------------------------------------------++externals :: [External]+externals =+    [ external "remember" (promoteCoreT . rememberR :: LemmaName -> TransformH LCore ())+        [ "Remember the current binding, allowing it to be folded/unfolded in the future." ] .+ Context+    , external "unfold-remembered" (promoteExprR . unfoldRememberedR Obligation :: LemmaName -> RewriteH LCore)+        [ "Unfold a remembered definition." ] .+ Deep .+ Context+    , external "fold-remembered" (promoteExprR . foldRememberedR Obligation :: LemmaName -> RewriteH LCore)+        [ "Fold a remembered definition." ]                      .+ Context .+ Deep+    , external "fold-any-remembered" (promoteExprR foldAnyRememberedR :: RewriteH LCore)+        [ "Attempt to fold any of the remembered definitions." ] .+ Context .+ Deep+    , external "show-remembered" (promoteCoreT . showLemmasT (Just "remembered-") :: PrettyPrinter -> PrettyH LCore)+        [ "Display all remembered definitions." ]+    ]++------------------------------------------------------------------------------++prefixRemembered :: LemmaName -> LemmaName+prefixRemembered = ("remembered-" <>)++-- | Remember a binding with a name for later use. Allows us to look at past definitions.+rememberR :: (AddBindings c, ExtendPath c Crumb, ReadPath c Crumb, HasLemmas m, MonadCatch m)+          => LemmaName -> Transform c m Core ()+rememberR nm = prefixFailMsg "remember failed: " $ do+    Def v e <- setFailMsg "not applied to a binding." $ defOrNonRecT idR idR Def+    insertLemmaT (prefixRemembered nm) $ Lemma (mkQuantified [] (varToCoreExpr v) e) Proven NotUsed False++-- | Unfold a remembered definition (like unfoldR, but looks in stash instead of context).+unfoldRememberedR :: ( AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb+                     , HasLemmas m, MonadCatch m, MonadUnique m)+                  => Used -> LemmaName -> Rewrite c m CoreExpr+unfoldRememberedR u = prefixFailMsg "Unfolding remembered definition failed: " . forwardT . lemmaBiR u . prefixRemembered++-- | Fold a remembered definition (like foldR, but looks in stash instead of context).+foldRememberedR :: ( AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb+                   , HasLemmas m, MonadCatch m, MonadUnique m)+                => Used -> LemmaName -> Rewrite c m CoreExpr+foldRememberedR u = prefixFailMsg "Folding remembered definition failed: " . backwardT . lemmaBiR u . prefixRemembered++-- | Fold any of the remembered definitions.+foldAnyRememberedR :: ( AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb+                      , HasLemmas m, MonadCatch m, MonadUnique m)+                   => Rewrite c m CoreExpr+foldAnyRememberedR = setFailMsg "Fold failed: no definitions could be folded."+                   $ compileRememberedT >>= runFoldR++-- | Compile all remembered definitions into something that can be run with `runFoldR`+compileRememberedT :: (HasLemmas m, Monad m) => Transform c m x CompiledFold+compileRememberedT = do+    qs <- liftM (map lemmaQ . Map.elems . Map.filterWithKey (\ k _ -> "remembered-" `isPrefixOf` show k)) getLemmasT+    return $ compileFold $ concatMap (map flipEquality . toEqualities) qs -- fold rhs to lhs
src/HERMIT/Dictionary/Rules.hs view
@@ -5,10 +5,13 @@       -- ** Rules     , RuleName(..)     , RuleNameListBox(..)-    , ruleR-    , rulesR-    , ruleToEqualityT-    , ruleNameToEqualityT+    , foldRuleR+    , foldRulesR+    , unfoldRuleR+    , unfoldRulesR+    , compileRulesT+    , ruleToQuantifiedT+    , ruleNameToQuantifiedT     , getHermitRuleT     , getHermitRulesT       -- ** Specialisation@@ -27,18 +30,20 @@ import Data.List (deleteFirstsBy,intercalate) import Data.String (IsString(..)) -import HERMIT.Core import HERMIT.Context-import HERMIT.Monad-import HERMIT.Kure+import HERMIT.Core import HERMIT.External import HERMIT.GHC+import HERMIT.Kure+import HERMIT.Lemma+import HERMIT.Monad -import HERMIT.Dictionary.GHC (dynFlagsT)+import HERMIT.Dictionary.Fold (compileFold, CompiledFold, toEqualities) import HERMIT.Dictionary.Kure (anyCallR) import HERMIT.Dictionary.Reasoning hiding (externals)-import HERMIT.Dictionary.Unfold (betaReducePlusR) +import HERMIT.PrettyPrinter.Common+ import IOEnv hiding (liftIO)  ------------------------------------------------------------------------@@ -46,22 +51,27 @@ -- | Externals dealing with GHC rewrite rules. externals :: [External] externals =-    [ external "rule-help" (rulesHelpListT :: TransformH CoreTC String)+    [ external "show-rules" (rulesHelpListT :: TransformH LCoreTC String)         [ "List all the rules in scope." ] .+ Query-    , external "rule-help" (ruleHelpT :: RuleName -> TransformH CoreTC String)+    , external "show-rule" (ruleHelpT :: PrettyPrinter -> RuleName -> TransformH LCoreTC DocH)         [ "Display details on the named rule." ] .+ Query-    , external "apply-rule" (promoteExprR . ruleR :: RuleName -> RewriteH Core)-        [ "Apply a named GHC rule" ] .+ Shallow-    , external "apply-rules" (promoteExprR . rulesR :: [RuleName] -> RewriteH Core)-        [ "Apply named GHC rules, succeed if any of the rules succeed" ] .+ Shallow-    , external "unfold-rule" ((\ nm -> promoteExprR (ruleR nm >>> tryR betaReducePlusR)) :: RuleName -> RewriteH Core)-        [ "Unfold a named GHC rule" ] .+ Deep .+ Context .+ TODO -- TODO: does not work with rules with no arguments-    , external "rule-to-lemma" (\nm -> do eq <- ruleNameToEqualityT nm-                                          insertLemmaR (fromString (show nm)) $ Lemma eq False False :: RewriteH Core)+    , external "fold-rule" (promoteExprR . foldRuleR Obligation :: RuleName -> RewriteH LCore)+        [ "Apply a named GHC rule right-to-left." ] .+ Shallow+    , external "fold-rules" (promoteExprR . foldRulesR Obligation :: [RuleName] -> RewriteH LCore)+        [ "Apply named GHC rules right-to-left, succeed if any of the rules succeed." ] .+ Shallow+    , external "unfold-rule" (promoteExprR . unfoldRuleR Obligation :: RuleName -> RewriteH LCore)+        [ "Apply a named GHC rule left-to-right." ] .+ Shallow+    , external "unfold-rule-unsafe" (promoteExprR . unfoldRuleR UnsafeUsed :: RuleName -> RewriteH LCore)+        [ "Apply a named GHC rule left-to-right." ] .+ Shallow .+ Unsafe+    , external "unfold-rules" (promoteExprR . unfoldRulesR Obligation :: [RuleName] -> RewriteH LCore)+        [ "Apply named GHC rules left-to-right, succeed if any of the rules succeed" ] .+ Shallow+    , external "unfold-rules-unsafe" (promoteExprR . unfoldRulesR UnsafeUsed :: [RuleName] -> RewriteH LCore)+        [ "Apply named GHC rules left-to-right, succeed if any of the rules succeed" ] .+ Shallow .+ Unsafe+    , external "rule-to-lemma" ((\pp nm -> ruleToLemmaT nm >> liftPrettyH (pOptions pp) (showLemmaT (fromString (show nm)) pp)) :: PrettyPrinter -> RuleName -> TransformH LCore DocH)         [ "Create a lemma from a GHC RULE." ]-    , external "spec-constr" (promoteModGutsR specConstrR :: RewriteH Core)+    , external "spec-constr" (promoteModGutsR specConstrR :: RewriteH LCore)         [ "Run GHC's SpecConstr pass, which performs call pattern specialization."] .+ Deep-    , external "specialise" (promoteModGutsR specialiseR :: RewriteH Core)+    , external "specialise" (promoteModGutsR specialiseR :: RewriteH LCore)         [ "Run GHC's specialisation pass, which performs type and dictionary specialisation."] .+ Deep     ] @@ -84,19 +94,49 @@     box = RuleNameListBox     unbox (RuleNameListBox l) = l --- | Lookup a rule by name, attempt to apply it. If successful, record it as an unproven lemma.-ruleR :: ( AddBindings c, ExtendPath c Crumb, HasCoreRules c, HasEmptyContext c, ReadBindings c, ReadPath c Crumb-         , HasDynFlags m, HasHermitMEnv m, HasLemmas m, LiftCoreM m, MonadCatch m, MonadIO m, MonadThings m, MonadUnique m )-      => RuleName -> Rewrite c m CoreExpr-ruleR nm = do-    eq <- ruleNameToEqualityT nm-    forwardT (birewrite eq) >>> sideEffectR (\ _ _ -> addLemma (fromString (show nm)) $ Lemma eq False True)+-- | Lookup a rule by name, attempt to apply it left-to-right. If successful, record it as an unproven lemma.+foldRuleR :: ( AddBindings c, ExtendPath c Crumb, HasCoreRules c, HasEmptyContext c, ReadBindings c, ReadPath c Crumb+               , HasDynFlags m, HasHermitMEnv m, HasLemmas m, LiftCoreM m, MonadCatch m, MonadIO m, MonadThings m, MonadUnique m )+            => Used -> RuleName -> Rewrite c m CoreExpr+foldRuleR u nm = do+    q <- ruleNameToQuantifiedT nm+    backwardT (birewrite q) >>> (verifyOrCreateT u (fromString (show nm)) (Lemma q NotProven u False) >> idR) -rulesR :: ( AddBindings c, ExtendPath c Crumb, HasCoreRules c, HasEmptyContext c, ReadBindings c, ReadPath c Crumb-          , HasDynFlags m, HasHermitMEnv m, HasLemmas m, LiftCoreM m, MonadCatch m, MonadIO m, MonadThings m, MonadUnique m )-       => [RuleName] -> Rewrite c m CoreExpr-rulesR = orR . map ruleR+-- | Lookup a set of rules by name, attempt to apply them left-to-right. Record an unproven lemma for the one that succeeds.+foldRulesR :: ( AddBindings c, ExtendPath c Crumb, HasCoreRules c, HasEmptyContext c, ReadBindings c, ReadPath c Crumb+              , HasDynFlags m, HasHermitMEnv m, HasLemmas m, LiftCoreM m, MonadCatch m, MonadIO m, MonadThings m, MonadUnique m )+           => Used -> [RuleName] -> Rewrite c m CoreExpr+foldRulesR u = orR . map (foldRuleR u) +-- | Lookup a rule by name, attempt to apply it left-to-right. If successful, record it as an unproven lemma.+unfoldRuleR :: ( AddBindings c, ExtendPath c Crumb, HasCoreRules c, HasEmptyContext c, ReadBindings c, ReadPath c Crumb+               , HasDynFlags m, HasHermitMEnv m, HasLemmas m, LiftCoreM m, MonadCatch m, MonadIO m, MonadThings m, MonadUnique m )+            => Used -> RuleName -> Rewrite c m CoreExpr+unfoldRuleR u nm = do+    q <- ruleNameToQuantifiedT nm+    forwardT (birewrite q) >>> (verifyOrCreateT u (fromString (show nm)) (Lemma q NotProven u False) >> idR)++-- | Lookup a set of rules by name, attempt to apply them left-to-right. Record an unproven lemma for the one that succeeds.+unfoldRulesR :: ( AddBindings c, ExtendPath c Crumb, HasCoreRules c, HasEmptyContext c, ReadBindings c, ReadPath c Crumb+                , HasDynFlags m, HasHermitMEnv m, HasLemmas m, LiftCoreM m, MonadCatch m, MonadIO m, MonadThings m, MonadUnique m )+             => Used -> [RuleName] -> Rewrite c m CoreExpr+unfoldRulesR u = orR . map (unfoldRuleR u)++-- | Can be used with runFoldR. Note: currently doesn't create a lemma for the rule used.+compileRulesT :: (BoundVars c, HasCoreRules c, HasHermitMEnv m, LiftCoreM m, MonadCatch m, MonadIO m, MonadThings m)+              => [RuleName] -> Transform c m a CompiledFold+compileRulesT nms = do+    let suggestion = "If you think the rule exists, try running the flatten-module command at the top level."+    let failMsg []   = "no rule names supplied."+        failMsg [nm] = "failed to find rule: " ++ show nm ++ ". " ++ suggestion+        failMsg _    = "failed to find any rules named " ++ intercalate ", " (map show nms) ++ ". " ++ suggestion+    allRules <- getHermitRulesT+    case filter ((`elem` nms) . fst) allRules of+        [] -> fail (failMsg nms)+        rs -> liftM (compileFold . concatMap toEqualities)+                $ forM (map snd rs) $ \ r -> return r >>> ruleToQuantifiedT++ -- | Return all in-scope CoreRules (including specialization RULES on binders), with their names. getHermitRulesT :: (HasCoreRules c, HasHermitMEnv m, LiftCoreM m, MonadIO m) => Transform c m a [(RuleName, CoreRule)] getHermitRulesT = contextonlyT $ \ c -> do@@ -123,29 +163,32 @@     rulesEnv <- getHermitRulesT     return (intercalate "\n" $ reverse $ map (show.fst) rulesEnv) --- | Print a named CoreRule using GHC's pretty printer for rewrite rules.--- TODO: use our own Equality pretty printer.-ruleHelpT :: (HasCoreRules c, HasDynFlags m, HasHermitMEnv m, LiftCoreM m, MonadIO m)-          => RuleName -> Transform c m a String-ruleHelpT nm = do-    r <- getHermitRuleT nm-    dflags <- dynFlagsT-    return $ showSDoc dflags $ pprRulesForUser [r]+-- | Print a named CoreRule using the quantified printer.+ruleHelpT :: (HasCoreRules c, ReadBindings c, ReadPath c Crumb) => PrettyPrinter -> RuleName -> Transform c HermitM a DocH+ruleHelpT pp nm = ruleNameToQuantifiedT nm >>> liftPrettyH (pOptions pp) (ppQuantifiedT pp) --- | Build an Equality from a named GHC rewrite rule.-ruleNameToEqualityT :: ( BoundVars c, HasCoreRules c, HasDynFlags m, HasHermitMEnv m+-- | Build an Quantified from a named GHC rewrite rule.+ruleNameToQuantifiedT :: ( BoundVars c, HasCoreRules c, HasDynFlags m, HasHermitMEnv m                        , LiftCoreM m, MonadCatch m, MonadIO m, MonadThings m )-                    => RuleName -> Transform c m a Equality-ruleNameToEqualityT name = getHermitRuleT name >>> ruleToEqualityT+                    => RuleName -> Transform c m a Quantified+ruleNameToQuantifiedT name = getHermitRuleT name >>> ruleToQuantifiedT --- | Transform GHC's CoreRule into an Equality.-ruleToEqualityT :: (BoundVars c, HasDynFlags m, HasHermitMEnv m, MonadThings m, MonadCatch m)-                => Transform c m CoreRule Equality-ruleToEqualityT = withPatFailMsg "HERMIT cannot handle built-in rules yet." $-  do r@Rule{} <- idR -- other possibility is "BuiltinRule"-     f <- lookupId $ ru_fn r-     return $ Equality (ru_bndrs r) (mkCoreApps (Var f) (ru_args r)) (ru_rhs r)+-- | Transform GHC's CoreRule into an Quantified.+ruleToQuantifiedT :: (BoundVars c, HasHermitMEnv m, MonadThings m, MonadCatch m)+                => Transform c m CoreRule Quantified+ruleToQuantifiedT = withPatFailMsg "HERMIT cannot handle built-in rules yet." $ do+    r@Rule{} <- idR -- other possibility is "BuiltinRule"+    f <- lookupId $ ru_fn r+    let lhs = mkCoreApps (varToCoreExpr f) (ru_args r)+    return $ mkQuantified (ru_bndrs r) lhs (ru_rhs r) +ruleToLemmaT :: ( BoundVars c, HasCoreRules c, HasDynFlags m, HasHermitMEnv m, HasLemmas m+                , LiftCoreM m, MonadCatch m, MonadIO m, MonadThings m)+             => RuleName -> Transform c m a ()+ruleToLemmaT nm = do+    q <- ruleNameToQuantifiedT nm+    insertLemmaT (fromString (show nm)) $ Lemma q NotProven NotUsed False+ ------------------------------------------------------------------------  -- | Run GHC's specConstr pass, and apply any rules generated.@@ -202,6 +245,6 @@ rulesToRewrite :: ( AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb                   , HasDynFlags m, HasHermitMEnv m, MonadCatch m, MonadThings m, MonadUnique m )                => [CoreRule] -> Rewrite c m CoreExpr-rulesToRewrite rs = catchesM [ (return r >>> ruleToEqualityT) >>= forwardT . birewrite | r <- rs ]+rulesToRewrite rs = catchesM [ (return r >>> ruleToQuantifiedT) >>= forwardT . birewrite | r <- rs ]  ------------------------------------------------------------------------
src/HERMIT/Dictionary/Undefined.hs view
@@ -5,6 +5,7 @@       externals     , buildStrictnessLemmaT     , verifyStrictT+    , applyToUndefinedT     , mkUndefinedValT     , isUndefinedValT     , replaceCurrentExprWithUndefinedR@@ -31,6 +32,7 @@ import HERMIT.External import HERMIT.GHC hiding ((<>)) import HERMIT.Kure+import HERMIT.Lemma import HERMIT.Monad import HERMIT.Name @@ -41,40 +43,40 @@ ------------------------------------------------------------------------  externals :: [External]-externals = map (.+ Unsafe)-    [ external "replace-current-expr-with-undefined" (promoteExprR replaceCurrentExprWithUndefinedR :: RewriteH Core)+externals = map (.+ Strictness)+    [ external "replace-current-expr-with-undefined" (promoteExprR replaceCurrentExprWithUndefinedR :: RewriteH LCore)         [ "Set the current expression to \"undefined\"."         ] .+ Shallow .+ Context .+ Unsafe-    , external "replace-id-with-undefined" (replaceIdWithUndefined :: HermitName -> RewriteH Core)+    , external "replace-id-with-undefined" (promoteCoreR . replaceIdWithUndefined :: HermitName -> RewriteH LCore)         [ "Replace the specified identifier with \"undefined\"."         ] .+ Deep .+ Context .+ Unsafe-    , external "error-to-undefined" (promoteExprR errorToUndefinedR :: RewriteH Core)+    , external "error-to-undefined" (promoteExprR errorToUndefinedR :: RewriteH LCore)         [ "error ty string  ==>  undefined ty"         ] .+ Shallow .+ Context-    , external "is-undefined-val" (promoteExprT isUndefinedValT :: TransformH Core ())+    , external "is-undefined-val" (promoteExprT isUndefinedValT :: TransformH LCore ())         [ "Succeed if the current expression is an undefined value."         ] .+ Shallow .+ Context .+ Predicate-    , external "undefined-expr" (promoteExprR undefinedExprR :: RewriteH Core)+    , external "undefined-expr" (promoteExprR undefinedExprR :: RewriteH LCore)         [ "undefined-app <+ undefined-lam <+ undefined-let <+ undefined-cast <+ undefined-tick <+ undefined-case"         ] .+ Eval .+ Shallow .+ Context-    , external "undefined-app" (promoteExprR undefinedAppR :: RewriteH Core)+    , external "undefined-app" (promoteExprR undefinedAppR :: RewriteH LCore)         [ "(undefined ty1) e  ==>  undefined ty2"         ] .+ Eval .+ Shallow .+ Context-    , external "undefined-lam" (promoteExprR undefinedLamR :: RewriteH Core)+    , external "undefined-lam" (promoteExprR undefinedLamR :: RewriteH LCore)         [ "(\\ v -> undefined ty1)  ==>  undefined ty2   (where v is not a 'TyVar')"         ] .+ Eval .+ Shallow .+ Context-    , external "undefined-let" (promoteExprR undefinedLetR :: RewriteH Core)+    , external "undefined-let" (promoteExprR undefinedLetR :: RewriteH LCore)         [ "let bds in (undefined ty)  ==>  undefined ty"         ] .+ Eval .+ Shallow .+ Context-    , external "undefined-case" (promoteExprR undefinedCaseR :: RewriteH Core)+    , external "undefined-case" (promoteExprR undefinedCaseR :: RewriteH LCore)         [ "case (undefined ty) of alts  ==>  undefined ty"         , "OR"         , "case e of {pat_1 -> undefined ty ; pat_2 -> undefined ty ; ... ; pat_n -> undefined ty} ==> undefined ty"         ] .+ Eval .+ Shallow .+ Context-    , external "undefined-cast" (promoteExprR undefinedCastR :: RewriteH Core)+    , external "undefined-cast" (promoteExprR undefinedCastR :: RewriteH LCore)         [ "Cast (undefined ty1) co  ==>  undefined ty2"         ] .+ Eval .+ Shallow .+ Context-    , external "undefined-tick" (promoteExprR undefinedTickR :: RewriteH Core)+    , external "undefined-tick" (promoteExprR undefinedTickR :: RewriteH LCore)         [ "Tick tick (undefined ty1)  ==>  undefined ty1"         ] .+ Eval .+ Shallow .+ Context     ]@@ -216,10 +218,10 @@ -- | Add a lemma for the strictness of a function. -- Note: assumes added lemma has been used buildStrictnessLemmaT :: (BoundVars c, HasDynFlags m, HasHscEnv m, HasHermitMEnv m, HasLemmas m, MonadCatch m, MonadIO m, MonadThings m)-                      => LemmaName -> CoreExpr -> Transform c m x ()-buildStrictnessLemmaT nm f = do+                      => Used -> LemmaName -> CoreExpr -> Transform c m x ()+buildStrictnessLemmaT u nm f = do     (tvs, lhs) <- liftM collectTyBinders $ applyToUndefinedT f     rhs <- mkUndefinedValT (exprType lhs)-    constT $ insertLemma nm $ Lemma (Equality tvs lhs rhs) False True+    verifyOrCreateT u nm $ Lemma (mkQuantified tvs lhs rhs) NotProven u False  ------------------------------------------------------------------------
src/HERMIT/Dictionary/Unfold.hs view
@@ -2,27 +2,18 @@ module HERMIT.Dictionary.Unfold     ( externals     , betaReducePlusR-    , rememberR-    , showStashT     , unfoldR     , unfoldPredR     , unfoldNameR     , unfoldNamesR     , unfoldSaturatedR-    , unfoldStashR     , specializeR     ) where  import Control.Arrow import Control.Monad -import Data.List (intercalate)-import qualified Data.Map as Map--import HERMIT.PrettyPrinter.Common (DocH, PrettyH, TransformDocH(..), PrettyC)- import HERMIT.Dictionary.Common-import HERMIT.Dictionary.GHC (substCoreExpr) import HERMIT.Dictionary.Inline (inlineR)  import HERMIT.Core@@ -35,30 +26,22 @@  import Prelude hiding (exp) -import qualified Text.PrettyPrint.MarkedHughesPJ as PP- ------------------------------------------------------------------------  externals :: [External] externals =-    [ external "beta-reduce-plus" (promoteExprR betaReducePlusR :: RewriteH Core)+    [ external "beta-reduce-plus" (promoteExprR betaReducePlusR :: RewriteH LCore)         [ "Perform one or more beta-reductions."]                               .+ Eval .+ Shallow-    , external "remember" (rememberR :: RememberedName -> RewriteH Core)-        [ "Remember the current binding, allowing it to be folded/unfolded in the future." ] .+ Context-    , external "unfold-remembered" (promoteExprR . unfoldStashR :: RememberedName -> RewriteH Core)-        [ "Unfold a remembered definition." ] .+ Deep .+ Context-    , external "unfold" (promoteExprR unfoldR :: RewriteH Core)+    , external "unfold" (promoteExprR unfoldR :: RewriteH LCore)         [ "In application f x y z, unfold f." ] .+ Deep .+ Context-    , external "unfold" (promoteExprR . unfoldNameR . unOccurrenceName :: OccurrenceName -> RewriteH Core)+    , external "unfold" (promoteExprR . unfoldNameR . unOccurrenceName :: OccurrenceName -> RewriteH LCore)         [ "Inline a definition, and apply the arguments; traditional unfold." ] .+ Deep .+ Context-    , external "unfold" (promoteExprR . unfoldNamesR . map unOccurrenceName:: [OccurrenceName] -> RewriteH Core)+    , external "unfold" (promoteExprR . unfoldNamesR . map unOccurrenceName:: [OccurrenceName] -> RewriteH LCore)         [ "Unfold a definition if it is named in the list." ] .+ Deep .+ Context-    , external "unfold-saturated" (promoteExprR unfoldSaturatedR :: RewriteH Core)+    , external "unfold-saturated" (promoteExprR unfoldSaturatedR :: RewriteH LCore)         [ "Unfold a definition only if the function is fully applied." ] .+ Deep .+ Context-    , external "specialize" (promoteExprR specializeR :: RewriteH Core)+    , external "specialize" (promoteExprR specializeR :: RewriteH LCore)         [ "Specialize an application to its type and coercion arguments." ] .+ Deep .+ Context-    , external "show-remembered" (TransformDocH showStashT :: TransformDocH CoreTC)-        [ "Display all remembered definitions." ]     ]  ------------------------------------------------------------------------@@ -104,45 +87,3 @@  specializeR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => Rewrite c HermitM CoreExpr specializeR = unfoldPredR (const $ all isTyCoArg)---- NOTE: Using a Rewrite because of the way the Kernel is set up.---       This is a temporary hack until we work out the best way to structure the Kernel.---- | Stash a binding with a name for later use.--- Allows us to look at past definitions.-rememberR :: RememberedName -> Rewrite c HermitM Core-rememberR label = sideEffectR $ \ _ -> \case-                                          DefCore def           -> saveDef label def-                                          BindCore (NonRec i e) -> saveDef label (Def i e)-                                          _                     -> fail "remember failed: not applied to a binding."---- | Stash a binding with a name for later use.--- Allows us to look at past definitions.--- rememberR :: String -> Transform c m Core ()--- rememberR label = contextfreeT $ \ core ->---     case core of---         DefCore def -> saveDef label def---         BindCore (NonRec i e) -> saveDef label (Def i e)---         _           -> fail "remember: not a binding"---- | Apply a stashed definition (like inline, but looks in stash instead of context).-unfoldStashR :: ReadBindings c => RememberedName -> Rewrite c HermitM CoreExpr-unfoldStashR label = prefixFailMsg "Inlining stashed definition failed: " $-                     withPatFailMsg (wrongExprForm "Var v") $-    do (c, Var v) <- exposeT-       constT $ do Def i rhs <- lookupDef label-                   dflags <- getDynFlags-                   if idName i == idName v -- TODO: Is there a reason we're not just using equality on Id?-                   then let fvars = varSetElems $ localFreeVarsExpr rhs-                        in if all (inScope c) fvars-                           then return rhs-                           else fail $ "free variables " ++ intercalate "," (map (showPpr dflags) (filter (not . inScope c) fvars)) ++ " in stashed definition are no longer in scope."-                   else fail $ "stashed definition applies to " ++ unqualifiedName i ++ " not " ++ unqualifiedName v--showStashT :: Injection CoreDef a => PrettyC -> PrettyH a -> Transform c HermitM a DocH-showStashT pctx pp = do-    stash <- constT getStash-    docs <- forM (Map.toList stash) $ \ (l,d) -> do-                dfn <- constT $ applyT (extractT pp) pctx d-                return $ PP.text ("[ " ++ show l ++ " ]") PP.$+$ dfn PP.$+$ PP.space-    return $ PP.vcat docs
src/HERMIT/Dictionary/Unsafe.hs view
@@ -1,7 +1,6 @@ module HERMIT.Dictionary.Unsafe     ( externals     , unsafeReplaceR-    , unsafeReplaceStashR     ) where  import Control.Monad@@ -9,7 +8,6 @@ import HERMIT.Core import HERMIT.Kure import HERMIT.GHC-import HERMIT.Monad import HERMIT.External import HERMIT.ParserCore @@ -19,12 +17,9 @@  externals :: [External] externals = map (.+ Unsafe)-    [ external "unsafe-replace" (promoteExprR . unsafeReplaceR :: CoreString -> RewriteH Core)+    [ external "unsafe-replace" (promoteExprR . unsafeReplaceR :: CoreString -> RewriteH LCore)         [ "replace the currently focused expression with a new expression"         , "DOES NOT ensure that free variables in the replacement expression are in scope" ]-    , external "unsafe-replace" (promoteExprR . unsafeReplaceStashR :: RememberedName -> RewriteH Core)-        [ "replace the currently focused expression with a remembered expression"-        , "DOES NOT ensure that free variables in the replacement expression are in scope" ]     ]  ------------------------------------------------------------------------@@ -35,12 +30,5 @@         e' <- parseCore core c         guardMsg (eqType (exprKindOrType e) (exprKindOrType e')) "expression types differ."         return e'--unsafeReplaceStashR :: RememberedName -> RewriteH CoreExpr-unsafeReplaceStashR label = prefixFailMsg "unsafe-replace failed: " $-    contextfreeT $ \ e -> do-        Def _ rhs <- lookupDef label-        guardMsg (eqType (exprKindOrType e) (exprKindOrType rhs)) "expression types differ."-        return rhs  ------------------------------------------------------------------------
src/HERMIT/Dictionary/WorkerWrapper/Common.hs view
@@ -3,9 +3,9 @@     ( externals     , WWAssumptionTag(..)     , WWAssumption(..)-    , assumptionAEqualityT-    , assumptionBEqualityT-    , assumptionCEqualityT+    , assumptionAQuantifiedT+    , assumptionBQuantifiedT+    , assumptionCQuantifiedT     , split1BetaR     , split2BetaR     , workLabel@@ -21,6 +21,7 @@ import HERMIT.External import HERMIT.GHC import HERMIT.Kure+import HERMIT.Lemma import HERMIT.Monad import HERMIT.ParserCore @@ -36,30 +37,30 @@ externals = map (.+ Proof)     [ external "intro-ww-assumption-A"         (\nm absC repC -> do-            eq <- parse2BeforeT assumptionAEqualityT absC repC-            insertLemmaR nm $ Lemma eq False False :: RewriteH Core)+            q <- parse2BeforeT assumptionAQuantifiedT absC repC+            insertLemmaT nm $ Lemma q NotProven NotUsed False :: TransformH LCore ())         [ "Introduce a lemma for worker/wrapper assumption A"         , "using given abs and rep functions." ]     , external "intro-ww-assumption-B"         (\nm absC repC bodyC -> do-            eq <- parse3BeforeT assumptionBEqualityT absC repC bodyC-            insertLemmaR nm $ Lemma eq False False :: RewriteH Core)+            q <- parse3BeforeT assumptionBQuantifiedT absC repC bodyC+            insertLemmaT nm $ Lemma q NotProven NotUsed False :: TransformH LCore ())         [ "Introduce a lemma for worker/wrapper assumption B"         , "using given abs, rep, and body functions." ]     , external "intro-ww-assumption-C"         (\nm absC repC bodyC -> do-            eq <- parse3BeforeT assumptionCEqualityT absC repC bodyC-            insertLemmaR nm $ Lemma eq False False :: RewriteH Core)+            q <- parse3BeforeT assumptionCQuantifiedT absC repC bodyC+            insertLemmaT nm $ Lemma q NotProven NotUsed False :: TransformH LCore ())         [ "Introduce a lemma for worker/wrapper assumption C"         , "using given abs, rep, and body functions." ]-    , external "split-1-beta" (\ nm absC -> promoteExprR . parse2BeforeT (split1BetaR nm) absC :: CoreString -> RewriteH Core)+    , external "split-1-beta" (\ nm absC -> promoteExprR . parse2BeforeT (split1BetaR Obligation nm) absC :: CoreString -> RewriteH LCore)         [ "split-1-beta <name> <abs expression> <rep expression>"         , "Perform worker/wrapper split with condition 1-beta."         , "Given lemma name argument is used as prefix to two introduced lemmas."         , "  <name>-assumption: unproven lemma for w/w assumption C."         , "  <name>-fusion: assumed lemma for w/w fusion."         ]-    , external "split-2-beta" (\ nm absC -> promoteExprR . parse2BeforeT (split2BetaR nm) absC :: CoreString -> RewriteH Core)+    , external "split-2-beta" (\ nm absC -> promoteExprR . parse2BeforeT (split2BetaR Obligation nm) absC :: CoreString -> RewriteH LCore)         [ "split-2-beta <name> <abs expression> <rep expression>"         , "Perform worker/wrapper split with condition 2-beta."         , "Given lemma name argument is used as prefix to two introduced lemmas."@@ -87,94 +88,95 @@ -- That would have to exist at the Shell level though.  -- This isn't entirely safe, as a malicious the user could define a label with this name.-workLabel :: RememberedName+workLabel :: LemmaName workLabel = fromString "recursive-definition-of-work-for-use-by-ww-fusion"  --------------------------------------------------------------------------------------------------  -- Given abs and rep expressions, build "abs . rep = id"-assumptionAEqualityT :: ( BoundVars c, HasDynFlags m, HasHermitMEnv m, HasHscEnv m+assumptionAQuantifiedT :: ( BoundVars c, HasHermitMEnv m, HasHscEnv m                         , MonadCatch m, MonadIO m, MonadThings m )-                     => CoreExpr -> CoreExpr -> Transform c m x Equality-assumptionAEqualityT absE repE = prefixFailMsg "Building assumption A failed: " $ do+                     => CoreExpr -> CoreExpr -> Transform c m x Quantified+assumptionAQuantifiedT absE repE = prefixFailMsg "Building assumption A failed: " $ do     comp <- buildCompositionT absE repE     let (_,compBody) = collectTyBinders comp     (tvs, xTy, _) <- splitFunTypeM (exprType comp)     idE <- buildIdT xTy-    return $ Equality tvs compBody idE+    return $ Quantified tvs (Equiv compBody idE)  -- Given abs, rep, and f expressions, build "abs . rep . f = f"-assumptionBEqualityT :: ( BoundVars c, HasDynFlags m, HasHermitMEnv m, HasHscEnv m+assumptionBQuantifiedT :: ( BoundVars c, HasHermitMEnv m, HasHscEnv m                         , MonadCatch m, MonadIO m, MonadThings m)-                     => CoreExpr -> CoreExpr -> CoreExpr -> Transform c m x Equality-assumptionBEqualityT absE repE fE = prefixFailMsg "Building assumption B failed: " $ do+                     => CoreExpr -> CoreExpr -> CoreExpr -> Transform c m x Quantified+assumptionBQuantifiedT absE repE fE = prefixFailMsg "Building assumption B failed: " $ do     repAfterF <- buildCompositionT repE fE     comp <- buildCompositionT absE repAfterF     let (tvs,lhs) = collectTyBinders comp     rhs <- appArgM 5 lhs >>= appArgM 5 -- get f with proper tvs applied-    return $ Equality tvs lhs rhs+    return $ Quantified tvs (Equiv lhs rhs)  -- Given abs, rep, and f expressions, build "fix (abs . rep . f) = fix f"-assumptionCEqualityT :: (BoundVars c, HasDynFlags m, HasHermitMEnv m, HasHscEnv m, MonadCatch m, MonadIO m, MonadThings m)-                     => CoreExpr -> CoreExpr -> CoreExpr -> Transform c m x Equality-assumptionCEqualityT absE repE fE = prefixFailMsg "Building assumption C failed: " $ do-    Equality vs lhs rhs <- assumptionBEqualityT absE repE fE+assumptionCQuantifiedT :: (BoundVars c, HasHermitMEnv m, HasHscEnv m, MonadCatch m, MonadIO m, MonadThings m)+                     => CoreExpr -> CoreExpr -> CoreExpr -> Transform c m x Quantified+assumptionCQuantifiedT absE repE fE = prefixFailMsg "Building assumption C failed: " $ do+    Quantified vs (Equiv lhs rhs) <- assumptionBQuantifiedT absE repE fE     lhs' <- buildFixT lhs     rhs' <- buildFixT rhs-    return $ Equality vs lhs' rhs'+    return $ Quantified vs (Equiv lhs' rhs')  -- Given abs, rep, and 'fix g' expressions, build "rep (abs (fix g)) = fix g"-wwFusionEqualityT :: (HasDynFlags m, MonadCatch m, MonadIO m)-                  => CoreExpr -> CoreExpr -> CoreExpr -> Transform c m x Equality-wwFusionEqualityT absE repE fixgE = prefixFailMsg "Building worker/wrapper fusion lemma failed: " $ do-    protoLhs <- buildApplicationM repE =<< buildApplicationM absE fixgE+wwFusionQuantifiedT :: MonadCatch m => CoreExpr -> CoreExpr -> CoreExpr -> Transform c m x Quantified+wwFusionQuantifiedT absE repE fixgE = prefixFailMsg "Building worker/wrapper fusion lemma failed: " $ do+    protoLhs <- buildAppM repE =<< buildAppM absE fixgE     let (tvs, lhs) = collectTyBinders protoLhs     -- This way, the rhs is applied to the proper type variables.     rhs <- case lhs of             (App _ (App _ rhs)) -> return rhs             _                   -> fail "lhs malformed"-    return $ Equality tvs lhs rhs+    return $ Quantified tvs (Equiv lhs rhs)  -- Perform the worker/wrapper split using condition 1-beta, introducing -- an unproven lemma for assumption C, and an appropriate w/w fusion lemma.-split1BetaR :: ( BoundVars c, HasDynFlags m, HasHermitMEnv m, HasHscEnv m, HasLemmas m+split1BetaR :: ( BoundVars c, HasHermitMEnv m, HasHscEnv m, HasLemmas m                , MonadCatch m, MonadIO m, MonadThings m, MonadUnique m )-            => LemmaName -> CoreExpr -> CoreExpr -> Rewrite c m CoreExpr-split1BetaR nm absE repE = do+            => Used -> LemmaName -> CoreExpr -> CoreExpr -> Rewrite c m CoreExpr+split1BetaR u nm absE repE = do     (_fixId, [_tyA, f]) <- callNameT $ fromString "Data.Function.fix" -    g <- buildCompositionT repE =<< buildCompositionT f absE+    g <- prefixFailMsg "building (rep . f . abs) failed: "+       $ buildCompositionT repE =<< buildCompositionT f absE     gId <- constT $ newIdH "g" $ exprType g      workRhs <- buildFixT $ varToCoreExpr gId     workId <- constT $ newIdH "worker" $ exprType workRhs -    newRhs <- buildApplicationM absE (varToCoreExpr workId)+    newRhs <- prefixFailMsg "building (abs work) failed: "+            $ buildAppM absE (varToCoreExpr workId) -    assumptionEq <- assumptionCEqualityT absE repE f-    _ <- insertLemmaR (fromString (show nm ++ "-assumption")) $ Lemma assumptionEq False True -- unproven, used+    assumptionQ <- assumptionCQuantifiedT absE repE f+    verifyOrCreateT u (fromString (show nm ++ "-assumption")) $ Lemma assumptionQ NotProven u False -- unproven, used, permanent -    wwFusionEq <- wwFusionEqualityT absE repE workRhs-    _ <- insertLemmaR (fromString (show nm ++ "-fusion")) $ Lemma wwFusionEq True False -- proven (assumed), unused+    wwFusionQ <- wwFusionQuantifiedT absE repE workRhs+    insertLemmaT (fromString (show nm ++ "-fusion")) $ Lemma wwFusionQ (Assumed False) NotUsed False -- assumed, unused, permanent      return $ mkCoreLets [NonRec gId g, NonRec workId workRhs] newRhs -split2BetaR :: ( BoundVars c, HasDynFlags m, HasHermitMEnv m, HasHscEnv m, HasLemmas m+split2BetaR :: ( BoundVars c, HasHermitMEnv m, HasHscEnv m, HasLemmas m                , MonadCatch m, MonadIO m, MonadThings m, MonadUnique m )-            => LemmaName -> CoreExpr -> CoreExpr -> Rewrite c m CoreExpr-split2BetaR nm absE repE = do+            => Used -> LemmaName -> CoreExpr -> CoreExpr -> Rewrite c m CoreExpr+split2BetaR u nm absE repE = do     (_fixId, [_tyA, f]) <- callNameT $ fromString "Data.Function.fix"     fixfE <- idR -    repFixFE <- buildApplicationM repE fixfE+    repFixFE <- buildAppM repE fixfE     workId <- constT $ newIdH "worker" $ exprType repFixFE -    newRhs <- buildApplicationM absE (varToCoreExpr workId)+    newRhs <- buildAppM absE (varToCoreExpr workId) -    assumptionEq <- assumptionCEqualityT absE repE f-    _ <- insertLemmaR (fromString (show nm ++ "-assumption")) $ Lemma assumptionEq False True -- unproven, used+    assumptionQ <- assumptionCQuantifiedT absE repE f+    verifyOrCreateT u (fromString (show nm ++ "-assumption")) $ Lemma assumptionQ NotProven u False -- unproven, used, permanent -    wwFusionEq <- wwFusionEqualityT absE repE (varToCoreExpr workId)-    _ <- insertLemmaR (fromString (show nm ++ "-fusion")) $ Lemma wwFusionEq True False -- proven (assumed), unused+    wwFusionQ <- wwFusionQuantifiedT absE repE (varToCoreExpr workId)+    insertLemmaT (fromString (show nm ++ "-fusion")) $ Lemma wwFusionQ (Assumed False) NotUsed False -- assumed, unused, permanent      return $ mkCoreLets [NonRec workId repFixFE] newRhs
src/HERMIT/Dictionary/WorkerWrapper/Fix.hs view
@@ -5,14 +5,13 @@     , wwFacBR     , wwSplitR     , wwSplitStaticArg-    , wwGenerateFusionR+    , wwGenerateFusionT     , wwFusionBR     , wwAssA     , wwAssB     , wwAssC     ) where -import Control.Applicative import Control.Arrow  import Data.String (fromString)@@ -21,6 +20,7 @@ import HERMIT.External import HERMIT.GHC import HERMIT.Kure+import HERMIT.Lemma import HERMIT.Monad import HERMIT.Name import HERMIT.ParserCore@@ -44,21 +44,21 @@ externals =          [            external "ww-factorisation" ((\ wrap unwrap assC -> promoteExprBiR $ wwFac (mkWWAssC assC) wrap unwrap)-                                          :: CoreString -> CoreString -> RewriteH Core -> BiRewriteH Core)+                                          :: CoreString -> CoreString -> RewriteH LCore -> BiRewriteH LCore)                 [ "Worker/Wrapper Factorisation",                   "For any \"f :: A -> A\", and given \"wrap :: B -> A\" and \"unwrap :: A -> B\" as arguments,",                   "and a proof of Assumption C (fix A (\\ a -> wrap (unwrap (f a))) ==> fix A f), then",                   "fix A f  ==>  wrap (fix B (\\ b -> unwrap (f (wrap b))))"                 ] .+ Introduce .+ Context          , external "ww-factorisation-unsafe" ((\ wrap unwrap -> promoteExprBiR $ wwFac Nothing wrap unwrap)-                                               :: CoreString -> CoreString -> BiRewriteH Core)+                                               :: CoreString -> CoreString -> BiRewriteH LCore)                 [ "Unsafe Worker/Wrapper Factorisation",                   "For any \"f :: A -> A\", and given \"wrap :: B -> A\" and \"unwrap :: A -> B\" as arguments, then",                   "fix A f  <==>  wrap (fix B (\\ b -> unwrap (f (wrap b))))",                   "Note: the pre-condition \"fix A (\\ a -> wrap (unwrap (f a))) == fix A f\" is expected to hold."                 ] .+ Introduce .+ Context .+ PreCondition          , external "ww-split" ((\ wrap unwrap assC -> promoteDefR $ wwSplit (mkWWAssC assC) wrap unwrap)-                                  :: CoreString -> CoreString -> RewriteH Core -> RewriteH Core)+                                  :: CoreString -> CoreString -> RewriteH LCore -> RewriteH LCore)                 [ "Worker/Wrapper Split",                   "For any \"prog :: A\", and given \"wrap :: B -> A\" and \"unwrap :: A -> B\" as arguments,",                   "and a proof of Assumption C (fix A (\\ a -> wrap (unwrap (f a))) ==> fix A f), then",@@ -67,7 +67,7 @@                   "                              in wrap work"                 ] .+ Introduce .+ Context          , external "ww-split-unsafe" ((\ wrap unwrap -> promoteDefR $ wwSplit Nothing wrap unwrap)-                                       :: CoreString -> CoreString -> RewriteH Core)+                                       :: CoreString -> CoreString -> RewriteH LCore)                 [ "Unsafe Worker/Wrapper Split",                   "For any \"prog :: A\", and given \"wrap :: B -> A\" and \"unwrap :: A -> B\" as arguments, then",                   "prog = expr  ==>  prog = let f = \\ prog -> expr",@@ -76,79 +76,79 @@                   "Note: the pre-condition \"fix A (wrap . unwrap . f) == fix A f\" is expected to hold."                 ] .+ Introduce .+ Context .+ PreCondition          , external "ww-split-static-arg" ((\ n is wrap unwrap assC -> promoteDefR $ wwSplitStaticArg n is (mkWWAssC assC) wrap unwrap)-                                      :: Int -> [Int] -> CoreString -> CoreString -> RewriteH Core -> RewriteH Core)+                                      :: Int -> [Int] -> CoreString -> CoreString -> RewriteH LCore -> RewriteH LCore)                 [ "Worker/Wrapper Split - Static Argument Variant",                   "Perform the static argument transformation on the first n arguments, then perform the worker/wrapper split,",                   "applying the given wrap and unwrap functions to the specified (by index) static arguments before use."                 ] .+ Introduce .+ Context          , external "ww-split-static-arg-unsafe" ((\ n is wrap unwrap -> promoteDefR $ wwSplitStaticArg n is Nothing wrap unwrap)-                                      :: Int -> [Int] -> CoreString -> CoreString -> RewriteH Core)+                                      :: Int -> [Int] -> CoreString -> CoreString -> RewriteH LCore)                 [ "Unsafe Worker/Wrapper Split - Static Argument Variant",                   "Perform the static argument transformation on the first n arguments, then perform the (unsafe) worker/wrapper split,",                   "applying the given wrap and unwrap functions to the specified (by index) static arguments before use."                 ] .+ Introduce .+ Context .+ PreCondition          , external "ww-assumption-A" ((\ wrap unwrap assA -> promoteExprBiR $ wwA (Just $ extractR assA) wrap unwrap)-                                       :: CoreString -> CoreString -> RewriteH Core -> BiRewriteH Core)+                                       :: CoreString -> CoreString -> RewriteH LCore -> BiRewriteH LCore)                 [ "Worker/Wrapper Assumption A",                   "For a \"wrap :: B -> A\" and an \"unwrap :: A -> B\",",                   "and given a proof of \"wrap (unwrap a) ==> a\", then",                   "wrap (unwrap a)  <==>  a"                 ] .+ Introduce .+ Context          , external "ww-assumption-B" ((\ wrap unwrap f assB -> promoteExprBiR $ wwB (Just $ extractR assB) wrap unwrap f)-                                       :: CoreString -> CoreString -> CoreString -> RewriteH Core -> BiRewriteH Core)+                                       :: CoreString -> CoreString -> CoreString -> RewriteH LCore -> BiRewriteH LCore)                 [ "Worker/Wrapper Assumption B",                   "For a \"wrap :: B -> A\", an \"unwrap :: A -> B\", and an \"f :: A -> A\",",                   "and given a proof of \"wrap (unwrap (f a)) ==> f a\", then",                   "wrap (unwrap (f a))  <==>  f a"                 ] .+ Introduce .+ Context          , external "ww-assumption-C" ((\ wrap unwrap f assC -> promoteExprBiR $ wwC (Just $ extractR assC) wrap unwrap f)-                                       :: CoreString -> CoreString -> CoreString -> RewriteH Core -> BiRewriteH Core)+                                       :: CoreString -> CoreString -> CoreString -> RewriteH LCore -> BiRewriteH LCore)                 [ "Worker/Wrapper Assumption C",                   "For a \"wrap :: B -> A\", an \"unwrap :: A -> B\", and an \"f :: A -> A\",",                   "and given a proof of \"fix A (\\ a -> wrap (unwrap (f a))) ==> fix A f\", then",                   "fix A (\\ a -> wrap (unwrap (f a)))  <==>  fix A f"                 ] .+ Introduce .+ Context          , external "ww-assumption-A-unsafe" ((\ wrap unwrap -> promoteExprBiR $ wwA Nothing wrap unwrap)-                                              :: CoreString -> CoreString -> BiRewriteH Core)+                                              :: CoreString -> CoreString -> BiRewriteH LCore)                 [ "Unsafe Worker/Wrapper Assumption A",                   "For a \"wrap :: B -> A\" and an \"unwrap :: A -> B\", then",                   "wrap (unwrap a)  <==>  a",                   "Note: only use this if it's true!"                 ] .+ Introduce .+ Context .+ PreCondition          , external "ww-assumption-B-unsafe" ((\ wrap unwrap f -> promoteExprBiR $ wwB Nothing wrap unwrap f)-                                              :: CoreString -> CoreString -> CoreString -> BiRewriteH Core)+                                              :: CoreString -> CoreString -> CoreString -> BiRewriteH LCore)                 [ "Unsafe Worker/Wrapper Assumption B",                   "For a \"wrap :: B -> A\", an \"unwrap :: A -> B\", and an \"f :: A -> A\", then",                   "wrap (unwrap (f a))  <==>  f a",                   "Note: only use this if it's true!"                 ] .+ Introduce .+ Context .+ PreCondition          , external "ww-assumption-C-unsafe" ((\ wrap unwrap f -> promoteExprBiR $ wwC Nothing wrap unwrap f)-                                              :: CoreString -> CoreString -> CoreString -> BiRewriteH Core)+                                              :: CoreString -> CoreString -> CoreString -> BiRewriteH LCore)                 [ "Unsafe Worker/Wrapper Assumption C",                   "For a \"wrap :: B -> A\", an \"unwrap :: A -> B\", and an \"f :: A -> A\", then",                   "fix A (\\ a -> wrap (unwrap (f a)))  <==>  fix A f",                   "Note: only use this if it's true!"                 ] .+ Introduce .+ Context .+ PreCondition-         , external "ww-AssA-to-AssB" (promoteExprR . wwAssAimpliesAssB . extractR :: RewriteH Core -> RewriteH Core)+         , external "ww-AssA-to-AssB" (promoteExprR . wwAssAimpliesAssB . extractR :: RewriteH LCore -> RewriteH LCore)                    [ "Convert a proof of worker/wrapper Assumption A into a proof of worker/wrapper Assumption B."                    ]-         , external "ww-AssB-to-AssC" (promoteExprR . wwAssBimpliesAssC . extractR :: RewriteH Core -> RewriteH Core)+         , external "ww-AssB-to-AssC" (promoteExprR . wwAssBimpliesAssC . extractR :: RewriteH LCore -> RewriteH LCore)                    [ "Convert a proof of worker/wrapper Assumption B into a proof of worker/wrapper Assumption C."                    ]-         , external "ww-AssA-to-AssC" (promoteExprR . wwAssAimpliesAssC . extractR :: RewriteH Core -> RewriteH Core)+         , external "ww-AssA-to-AssC" (promoteExprR . wwAssAimpliesAssC . extractR :: RewriteH LCore -> RewriteH LCore)                    [ "Convert a proof of worker/wrapper Assumption A into a proof of worker/wrapper Assumption C."                    ]-         , external "ww-generate-fusion" (wwGenerateFusionR . mkWWAssC :: RewriteH Core -> RewriteH Core)+         , external "ww-generate-fusion" (wwGenerateFusionT . mkWWAssC :: RewriteH LCore -> TransformH LCore ())                    [ "Given a proof of Assumption C (fix A (\\ a -> wrap (unwrap (f a))) ==> fix A f), then",                      "execute this command on \"work = unwrap (f (wrap work))\" to enable the \"ww-fusion\" rule thereafter.",                      "Note that this is performed automatically as part of \"ww-split\"."                    ] .+ Experiment .+ TODO-         , external "ww-generate-fusion-unsafe" (wwGenerateFusionR Nothing :: RewriteH Core)+         , external "ww-generate-fusion-unsafe" (wwGenerateFusionT Nothing :: TransformH LCore ())                    [ "Execute this command on \"work = unwrap (f (wrap work))\" to enable the \"ww-fusion\" rule thereafter.",                      "The precondition \"fix A (wrap . unwrap . f) == fix A f\" is expected to hold.",                      "Note that this is performed automatically as part of \"ww-split\"."                    ] .+ Experiment .+ TODO-         , external "ww-fusion" (promoteExprBiR wwFusion :: BiRewriteH Core)+         , external "ww-fusion" (promoteExprBiR wwFusion :: BiRewriteH LCore)                 [ "Worker/Wrapper Fusion",                   "unwrap (wrap work)  <==>  work",                   "Note: you are required to have previously executed the command \"ww-generate-fusion\" on the definition",@@ -156,7 +156,7 @@                 ] .+ Introduce .+ Context .+ PreCondition .+ TODO          ]   where-    mkWWAssC :: RewriteH Core -> Maybe WWAssumption+    mkWWAssC :: RewriteH LCore -> Maybe WWAssumption     mkWWAssC r = Just (WWAssumption C (extractR r))  --------------------------------------------------------------------------------------------------@@ -203,9 +203,9 @@ wwFusionBR =     beforeBiR (prefixFailMsg "worker/wrapper fusion failed: " $                withPatFailMsg "malformed WW Fusion rule." $-               do Def w (App unwrap (App _f (App wrap (Var w')))) <- constT (lookupDef workLabel)-                  guardMsg (w == w') "malformed WW Fusion rule."-                  return (wrap,unwrap,Var w)+               do Quantified _ (Equiv w (App unwrap (App _f (App wrap w')))) <- constT (lemmaQ <$> findLemma workLabel)+                  guardMsg (exprSyntaxEq w w') "malformed WW Fusion rule."+                  return (wrap,unwrap,w)               )               (\ (wrap,unwrap,work) -> bidirectional (fusL wrap unwrap work) (fusR wrap unwrap work))   where@@ -237,14 +237,14 @@ -- | Save the recursive definition of work in the stash, so that we can later verify uses of 'wwFusionBR'. --   Must be applied to a definition of the form: @work = unwrap (f (wrap work))@ --   Note that this is performed automatically as part of 'wwSplitR'.-wwGenerateFusionR :: Maybe WWAssumption -> RewriteH Core-wwGenerateFusionR mAss =+wwGenerateFusionT :: Maybe WWAssumption -> TransformH LCore ()+wwGenerateFusionT mAss =     prefixFailMsg "generate WW fusion failed: " $     withPatFailMsg wrongForm $-    do Def w (App unwrap (App f (App wrap (Var w')))) <- projectT+    do Def w e@(App unwrap (App f (App wrap (Var w')))) <- projectT        guardMsg (w == w') wrongForm        whenJust (verifyWWAss wrap unwrap f) mAss-       rememberR workLabel+       insertLemmaT workLabel $ Lemma (Quantified [] (Equiv (varToCoreExpr w) e)) Proven NotUsed False   where     wrongForm = "definition does not have the form: work = unwrap (f (wrap work))" @@ -260,7 +260,7 @@                                           >>> appAllR idR ( unfoldNameR (fromString "Data.Function.fix")                                                             >>> alphaLetWithR ["work"]                                                             >>> letRecAllR (\ _ -> defAllR idR (betaReduceR >>> letNonRecSubstR)-                                                                                   >>> extractR (wwGenerateFusionR mAss)+                                                                                   >>> (extractT (wwGenerateFusionT mAss) >> idR)                                                                            )                                                                            idR                                                           )
src/HERMIT/Dictionary/WorkerWrapper/FixResult.hs view
@@ -7,7 +7,7 @@     , wwResultFacBR     , wwResultSplitR     , wwResultSplitStaticArg-    , wwResultGenerateFusionR+    , wwResultGenerateFusionT     , wwResultFusionBR     , wwResultAssA     , wwResultAssB@@ -24,6 +24,7 @@ import HERMIT.External import HERMIT.GHC import HERMIT.Kure+import HERMIT.Lemma import HERMIT.Monad import HERMIT.Name import HERMIT.ParserCore@@ -47,21 +48,21 @@ externals =          [            external "ww-result-factorisation" ((\ abs rep assC -> promoteExprBiR $ wwFac (mkWWAssC assC) abs rep)-                                          :: CoreString -> CoreString -> RewriteH Core -> BiRewriteH Core)+                                          :: CoreString -> CoreString -> RewriteH LCore -> BiRewriteH LCore)                 [ "Worker/Wrapper Factorisation (Result Variant)",                   "For any \"f :: (X -> A) -> (X -> A)\", and given \"abs :: B -> A\" and \"rep :: A -> B\" as arguments,",                   "and a proof of Assumption C (fix (X -> A) (\\ h x -> abs (rep (f h x))) ==> fix (X->A) f), then",                   "fix (X->A) f  ==>  \\ x1 -> abs (fix (X->B) (\\ h x2 -> rep (f (\\ x3 -> abs (h x3)) x2)) x1"                 ] .+ Introduce .+ Context          , external "ww-result-factorisation-unsafe" ((\ abs rep -> promoteExprBiR $ wwFac Nothing abs rep)-                                               :: CoreString -> CoreString -> BiRewriteH Core)+                                               :: CoreString -> CoreString -> BiRewriteH LCore)                 [ "Unsafe Worker/Wrapper Factorisation (Result Variant)",                   "For any \"f :: (X -> A) -> (X -> A)\", and given \"abs :: B -> A\" and \"rep :: A -> B\" as arguments, then",                   "fix (X->A) f  ==>  \\ x1 -> abs (fix (X->B) (\\ h x2 -> rep (f (\\ x3 -> abs (h x3)) x2)) x1",                   "Note: the pre-condition \"fix (X -> A) (\\ h x -> abs (rep (f h x))) == fix (X->A) f\" is expected to hold."                 ] .+ Introduce .+ Context .+ PreCondition          , external "ww-result-split" ((\ abs rep assC -> promoteDefR $ wwSplit (mkWWAssC assC) abs rep)-                                  :: CoreString -> CoreString -> RewriteH Core -> RewriteH Core)+                                  :: CoreString -> CoreString -> RewriteH LCore -> RewriteH LCore)                 [ "Worker/Wrapper Split (Result Variant)",                   "For any \"prog :: X -> A\", and given \"abs :: B -> A\" and \"rep :: A -> B\" as arguments,",                   "and a proof of Assumption C (fix (X->A) (\\ h x -> abs (rep (f h x))) ==> fix (X->A) f), then",@@ -70,88 +71,88 @@                   "                              in \\ x0 -> abs (work x0)"                 ] .+ Introduce .+ Context          , external "ww-result-split-unsafe" ((\ abs rep -> promoteDefR $ wwSplit Nothing abs rep)-                                       :: CoreString -> CoreString -> RewriteH Core)+                                       :: CoreString -> CoreString -> RewriteH LCore)                 [ "Unsafe Worker/Wrapper Split (Result Variant)",                   "For any \"prog :: X -> A\", and given \"abs :: B -> A\" and \"rep :: A -> B\" as arguments, then",                   "prog = expr  ==>  prog = let f = \\ prog -> expr",                   "                          in let work = \\ x1 -> rep (f (\\ x2 -> abs (work x2)) x1)",                   "                              in \\ x0 -> abs (work x0)",                   "Note: the pre-condition \"fix (X->A) (\\ h x -> abs (rep (f h x))) == fix (X->A) f\" is expected to hold."-                ] .+ Introduce .+ Context .+ PreCondition+                ] .+ Introduce .+ Context .+ PreCondition .+ Unsafe          , external "ww-result-split-static-arg" ((\ n is abs rep assC -> promoteDefR $ wwResultSplitStaticArg n is (mkWWAssC assC) abs rep)-                                      :: Int -> [Int] -> CoreString -> CoreString -> RewriteH Core -> RewriteH Core)+                                      :: Int -> [Int] -> CoreString -> CoreString -> RewriteH LCore -> RewriteH LCore)                 [ "Worker/Wrapper Split - Static Argument Variant (Result Variant)",                   "Perform the static argument transformation on the first n arguments, then perform the worker/wrapper split,",                   "applying the given abs and rep functions to the specified (by index) static arguments before use."                 ] .+ Introduce .+ Context          , external "ww-result-split-static-arg-unsafe" ((\ n is abs rep -> promoteDefR $ wwResultSplitStaticArg n is Nothing abs rep)-                                      :: Int -> [Int] -> CoreString -> CoreString -> RewriteH Core)+                                      :: Int -> [Int] -> CoreString -> CoreString -> RewriteH LCore)                 [ "Unsafe Worker/Wrapper Split - Static Argument Variant (Result Variant)",                   "Perform the static argument transformation on the first n arguments, then perform the (unsafe) worker/wrapper split,",                   "applying the given abs and rep functions to the specified (by index) static arguments before use."-                ] .+ Introduce .+ Context .+ PreCondition+                ] .+ Introduce .+ Context .+ PreCondition .+ Unsafe          , external "ww-result-assumption-A" ((\ abs rep assA -> promoteExprBiR $ wwA (Just $ extractR assA) abs rep)-                                       :: CoreString -> CoreString -> RewriteH Core -> BiRewriteH Core)+                                       :: CoreString -> CoreString -> RewriteH LCore -> BiRewriteH LCore)                 [ "Worker/Wrapper Assumption A (Result Variant)",                   "For a \"abs :: B -> A\" and a \"rep :: A -> B\",",                   "and given a proof of \"abs (rep a)  ==>  a\", then",                   "abs (rep a)  <==>  a"                 ] .+ Introduce .+ Context          , external "ww-result-assumption-B" ((\ abs rep f assB -> promoteExprBiR $ wwB (Just $ extractR assB) abs rep f)-                                       :: CoreString -> CoreString -> CoreString -> RewriteH Core -> BiRewriteH Core)+                                       :: CoreString -> CoreString -> CoreString -> RewriteH LCore -> BiRewriteH LCore)                 [ "Worker/Wrapper Assumption B (Result Variant)",                   "For a \"abs :: B -> A\", an \"rep :: A -> B\", and an \"f :: (X -> A) -> X -> A\",",                   "and given a proof of \"abs (rep (f h x))  ==>  f h x\", then",                   "abs (rep (f h x))  <==>  f h x"                 ] .+ Introduce .+ Context          , external "ww-result-assumption-C" ((\ abs rep f assC -> promoteExprBiR $ wwC (Just $ extractR assC) abs rep f)-                                       :: CoreString -> CoreString -> CoreString -> RewriteH Core -> BiRewriteH Core)+                                       :: CoreString -> CoreString -> CoreString -> RewriteH LCore -> BiRewriteH LCore)                 [ "Worker/Wrapper Assumption C (Result Variant)",                   "For a \"abs :: B -> A\", an \"rep :: A -> B\", and an \"f :: (X -> A) -> X -> A\",",                   "and given a proof of \"fix (X->A) (\\ h x -> abs (rep (f h x))) ==> fix (X->A) f\", then",                   "fix (X->A) (\\ h x -> abs (rep (f h x)))  <==>  fix (X->A) f"                 ] .+ Introduce .+ Context          , external "ww-result-assumption-A-unsafe" ((\ abs rep -> promoteExprBiR $ wwA Nothing abs rep)-                                              :: CoreString -> CoreString -> BiRewriteH Core)+                                              :: CoreString -> CoreString -> BiRewriteH LCore)                 [ "Unsafe Worker/Wrapper Assumption A (Result Variant)",                   "For a \"abs :: B -> A\" and a \"rep :: A -> B\", then",                   "abs (rep a)  <==>  a",                   "Note: only use this if it's true!"                 ] .+ Introduce .+ Context .+ PreCondition          , external "ww-result-assumption-B-unsafe" ((\ abs rep f -> promoteExprBiR $ wwB Nothing abs rep f)-                                              :: CoreString -> CoreString -> CoreString -> BiRewriteH Core)+                                              :: CoreString -> CoreString -> CoreString -> BiRewriteH LCore)                 [ "Unsafe Worker/Wrapper Assumption B (Result Variant)",                   "For a \"abs :: B -> A\", an \"rep :: A -> B\", and an \"f :: (X -> A) -> X -> A\", then",                   "abs (rep (f h x))  <==>  f h x",                   "Note: only use this if it's true!"                 ] .+ Introduce .+ Context .+ PreCondition          , external "ww-result-assumption-C-unsafe" ((\ abs rep f -> promoteExprBiR $ wwC Nothing abs rep f)-                                              :: CoreString -> CoreString -> CoreString -> BiRewriteH Core)+                                              :: CoreString -> CoreString -> CoreString -> BiRewriteH LCore)                 [ "Unsafe Worker/Wrapper Assumption C (Result Variant)",                   "For a \"abs :: B -> A\", an \"rep :: A -> B\", and an \"f :: (X -> A) -> X -> A\", then",                   "fix (X->A) (\\ h x -> abs (rep (f h x)))  <==>  fix (X->A) f",                   "Note: only use this if it's true!"                 ] .+ Introduce .+ Context .+ PreCondition-         , external "ww-result-AssA-to-AssB" (promoteExprR . wwResultAssAimpliesAssB . extractR :: RewriteH Core -> RewriteH Core)+         , external "ww-result-AssA-to-AssB" (promoteExprR . wwResultAssAimpliesAssB . extractR :: RewriteH LCore -> RewriteH LCore)                    [ "Convert a proof of worker/wrapper Assumption A into a proof of worker/wrapper Assumption B."                    ]-         , external "ww-result-AssB-to-AssC" (promoteExprR . wwResultAssBimpliesAssC . extractR :: RewriteH Core -> RewriteH Core)+         , external "ww-result-AssB-to-AssC" (promoteExprR . wwResultAssBimpliesAssC . extractR :: RewriteH LCore -> RewriteH LCore)                    [ "Convert a proof of worker/wrapper Assumption B into a proof of worker/wrapper Assumption C."                    ]-         , external "ww-result-AssA-to-AssC" (promoteExprR . wwResultAssAimpliesAssC . extractR :: RewriteH Core -> RewriteH Core)+         , external "ww-result-AssA-to-AssC" (promoteExprR . wwResultAssAimpliesAssC . extractR :: RewriteH LCore -> RewriteH LCore)                    [ "Convert a proof of worker/wrapper Assumption A into a proof of worker/wrapper Assumption C."                    ]-         , external "ww-result-generate-fusion" (wwResultGenerateFusionR . mkWWAssC :: RewriteH Core -> RewriteH Core)+         , external "ww-result-generate-fusion" (wwResultGenerateFusionT . mkWWAssC :: RewriteH LCore -> TransformH LCore ())                    [ "Given a proof of Assumption C (fix (X->A) (\\ h x -> abs (rep (f h x))) ==> fix (X->A) f), then",                      "execute this command on \"work = \\ x1 -> rep (f (\\ x2 -> abs (work x2)) x1)\" to enable the \"ww-result-fusion\" rule thereafter.",                      "Note that this is performed automatically as part of \"ww-result-split\"."                    ] .+ Experiment .+ TODO-         , external "ww-result-generate-fusion-unsafe" (wwResultGenerateFusionR Nothing :: RewriteH Core)+         , external "ww-result-generate-fusion-unsafe" (wwResultGenerateFusionT Nothing :: TransformH LCore ())                    [ "Execute this command on \"work = \\ x1 -> rep (f (\\ x2 -> abs (work x2)) x1)\" to enable the \"ww-fusion\" rule thereafter.",                      "The precondition \"fix (X->A) (\\ h x -> abs (rep (f h x))) == fix (X->A) f\" is expected to hold.",                      "Note that this is performed automatically as part of \"ww-result-split\"."                    ] .+ Experiment .+ TODO-         , external "ww-result-fusion" (promoteExprBiR wwFusion :: BiRewriteH Core)+         , external "ww-result-fusion" (promoteExprBiR wwFusion :: BiRewriteH LCore)                 [ "Worker/Wrapper Fusion (Result Variant)",                   "rep (abs (work x))  <==>  work x",                   "Note: you are required to have previously executed the command \"ww-generate-fusion\" on the definition",@@ -159,7 +160,7 @@                 ] .+ Introduce .+ Context .+ PreCondition .+ TODO          ]   where-    mkWWAssC :: RewriteH Core -> Maybe WWAssumption+    mkWWAssC :: RewriteH LCore -> Maybe WWAssumption     mkWWAssC r = Just (WWAssumption C (extractR r))  --------------------------------------------------------------------------------------------------@@ -223,14 +224,15 @@ wwResultFusionBR =     beforeBiR (prefixFailMsg "worker/wrapper fusion failed: " $                withPatFailMsg "malformed WW Fusion rule." $-               do Def w (Lam x1 (App rep-                                     (App (App _ (Lam x2 (App abs (App (Var w') (Var x2')))))+               do Quantified _ (Equiv w+                        (Lam x1 (App rep+                                     (App (App _ (Lam x2 (App abs (App w' (Var x2')))))                                           (Var x1')                                      )                                 )-                        ) <- constT (lookupDef workLabel)-                  guardMsg (w == w' && x1 == x1' && x2 == x2') "malformed WW Fusion rule."-                  return (abs,rep,Var w)+                        )) <- constT (lemmaQ <$> findLemma workLabel)+                  guardMsg (exprSyntaxEq w w' && x1 == x1' && x2 == x2') "malformed WW Fusion rule."+                  return (abs,rep,w)               )               (\ (abs,rep,work) -> bidirectional (fusL abs rep work) (fusR abs rep work))   where@@ -262,19 +264,19 @@ -- | Save the recursive definition of work in the stash, so that we can later verify uses of 'wwResultFusionBR'. --   Must be applied to a definition of the form: @work = \\ x1 -> rep (f (\\ x2 -> abs (work x2)) x1)@ --   Note that this is performed automatically as part of 'wwResultSplitR'.-wwResultGenerateFusionR :: Maybe WWAssumption -> RewriteH Core-wwResultGenerateFusionR mAss =+wwResultGenerateFusionT :: Maybe WWAssumption -> TransformH LCore ()+wwResultGenerateFusionT mAss =     prefixFailMsg "generate WW fusion failed: " $     withPatFailMsg wrongForm $-    do Def w (Lam x1 (App rep+    do Def w e@(Lam x1 (App rep                           (App (App f (Lam x2 (App abs (App (Var w') (Var x2')))))                                (Var x1')                           )-                     )-             ) <- projectT+                       )+               ) <- projectT        guardMsg (w == w' && x1 == x1' && x2 == x2') wrongForm        whenJust (verifyWWAss abs rep f) mAss-       rememberR workLabel+       insertLemmaT workLabel $ Lemma (Quantified [] (Equiv (varToCoreExpr w) e)) Proven NotUsed False   where     wrongForm = "definition does not have the form: work = \\ x1 -> rep (f (\\ x2 -> abs (work x2)) x1)" @@ -291,7 +293,7 @@                                           >>> lamAllR idR (appAllR idR (appAllR ( unfoldNameR (fromString "Data.Function.fix")                                                                                   >>> alphaLetWithR ["work"]                                                                                   >>> letRecAllR (\ _ -> defAllR idR (betaReduceR >>> letNonRecSubstR)-                                                                                                         >>> extractR (wwResultGenerateFusionR mAss)+                                                                                                         >>> (extractT (wwResultGenerateFusionT mAss) >> idR)                                                                                                  )                                                                                                  idR                                                                                 )
src/HERMIT/External.hs view
@@ -26,26 +26,29 @@     , dictionaryOfTags       -- * Boxes       -- | Boxes are used by the 'Extern' class.-    , BiRewriteCoreBox(..)     , CoreString(..)     , CrumbBox(..)     , IntBox(..)     , IntListBox(..)     , PathBox(..)-    , RewriteCoreBox(..)-    , RewriteCoreListBox(..)-    , RewriteCoreTCBox(..)-    , RewriteEqualityBox(..)     , StringBox(..)     , StringListBox(..)     , TagBox(..)-    , TransformCoreCheckBox(..)-    , TransformCorePathBox(..)-    , TransformCoreStringBox(..)-    , TransformCoreTCCheckBox(..)-    , TransformCoreTCPathBox(..)-    , TransformCoreTCStringBox(..)-    , TransformEqualityStringBox(..)+      -- ** LCore Boxes+    , TransformLCoreStringBox(..)+    , TransformLCoreUnitBox(..)+    , TransformLCorePathBox(..)+    , RewriteLCoreBox(..)+    , BiRewriteLCoreBox(..)+    , RewriteLCoreListBox(..)+      -- ** LCoreTC Boxes+    , TransformLCoreTCStringBox(..)+    , TransformLCoreTCUnitBox(..)+    , TransformLCoreTCLCoreBox(..)+    , TransformLCoreTCPathBox(..)+    , RewriteLCoreTCBox(..)+    , BiRewriteLCoreTCBox(..)+    , RewriteLCoreTCListBox(..)     ) where  import Data.Map hiding (map)@@ -56,7 +59,7 @@ import HERMIT.Core import HERMIT.Context (LocalPathH) import HERMIT.Kure-import HERMIT.Monad+import HERMIT.Lemma  ----------------------------------------------------------------- @@ -90,6 +93,8 @@             | Context        -- ^ A command that uses its context, such as inlining.             | Unsafe         -- ^ Commands that are not type safe (may cause Core Lint to fail),                              --   or may otherwise change the semantics of the program.+                             --   Only available in unsafe mode!+            | Safe           -- ^ Include in Strict Safety mode (currently unused)             | Proof          -- ^ Commands related to proving lemmas.              | TODO           -- ^ An incomplete or potentially buggy command.@@ -235,12 +240,13 @@  -- | Remove the word 'Box' from a string. deBoxify :: String -> String-deBoxify xs-    | "CLSBox -> " `isPrefixOf` xs = deBoxify (drop 10 xs)-deBoxify xs-    | "Box" `isPrefixOf` xs        = deBoxify (drop 3 xs)-deBoxify (x:xs)                    = x : deBoxify xs-deBoxify []                        = []+deBoxify s | "CLSBox -> "        `isPrefixOf` s = go (drop 10 s)+           | "PrettyPrinter -> " `isPrefixOf` s = go (drop 17 s)+           | otherwise = go s+    where go xs+            | "Box" `isPrefixOf` xs = go (drop 3 xs)+          go (x:xs)                 = x : go xs+          go []                     = []  externTypeArgResString :: External -> ([String], String) externTypeArgResString e = (map (deBoxify . show) aTys, deBoxify (show rTy))@@ -301,182 +307,181 @@  ----------------------------------------------------------------- -data RewriteCoreBox = RewriteCoreBox (RewriteH Core) deriving Typeable+-- TODO: Considering unifying CrumbBox and PathBox under TransformLCoreTCPathBox.+data CrumbBox = CrumbBox Crumb deriving Typeable -instance Extern (RewriteH Core) where-    type Box (RewriteH Core) = RewriteCoreBox-    box = RewriteCoreBox-    unbox (RewriteCoreBox r) = r+instance Extern Crumb where+    type Box Crumb = CrumbBox+    box = CrumbBox+    unbox (CrumbBox cr) = cr  ----------------------------------------------------------------- -data RewriteCoreTCBox = RewriteCoreTCBox (RewriteH CoreTC) deriving Typeable+data PathBox = PathBox LocalPathH deriving Typeable -instance Extern (RewriteH CoreTC) where-    type Box (RewriteH CoreTC) = RewriteCoreTCBox-    box = RewriteCoreTCBox-    unbox (RewriteCoreTCBox r) = r+instance Extern LocalPathH where+    type Box LocalPathH = PathBox+    box = PathBox+    unbox (PathBox p) = p  ----------------------------------------------------------------- -data BiRewriteCoreBox = BiRewriteCoreBox (BiRewriteH Core) deriving Typeable+newtype CoreString = CoreString { unCoreString :: String } deriving Typeable -instance Extern (BiRewriteH Core) where-    type Box (BiRewriteH Core) = BiRewriteCoreBox-    box = BiRewriteCoreBox-    unbox (BiRewriteCoreBox b) = b+instance Extern CoreString where+    type Box CoreString = CoreString+    box = id+    unbox = id  ----------------------------------------------------------------- -data TransformCoreTCStringBox = TransformCoreTCStringBox (TransformH CoreTC String) deriving Typeable+data StringBox = StringBox String deriving Typeable -instance Extern (TransformH CoreTC String) where-    type Box (TransformH CoreTC String) = TransformCoreTCStringBox-    box = TransformCoreTCStringBox-    unbox (TransformCoreTCStringBox t) = t+instance Extern String where+    type Box String = StringBox+    box = StringBox+    unbox (StringBox s) = s  ----------------------------------------------------------------- -data TransformCoreStringBox = TransformCoreStringBox (TransformH Core String) deriving Typeable+data StringListBox = StringListBox [String] deriving Typeable -instance Extern (TransformH Core String) where-    type Box (TransformH Core String) = TransformCoreStringBox-    box = TransformCoreStringBox-    unbox (TransformCoreStringBox t) = t+instance Extern [String] where+    type Box [String] = StringListBox+    box = StringListBox+    unbox (StringListBox l) = l  ----------------------------------------------------------------- -data TransformCoreTCCheckBox = TransformCoreTCCheckBox (TransformH CoreTC ()) deriving Typeable+data IntListBox = IntListBox [Int] deriving Typeable -instance Extern (TransformH CoreTC ()) where-    type Box (TransformH CoreTC ()) = TransformCoreTCCheckBox-    box = TransformCoreTCCheckBox-    unbox (TransformCoreTCCheckBox t) = t+instance Extern [Int] where+    type Box [Int] = IntListBox+    box = IntListBox+    unbox (IntListBox l) = l  ----------------------------------------------------------------- -data TransformCoreCheckBox = TransformCoreCheckBox (TransformH Core ()) deriving Typeable--instance Extern (TransformH Core ()) where-    type Box (TransformH Core ()) = TransformCoreCheckBox-    box = TransformCoreCheckBox-    unbox (TransformCoreCheckBox t) = t+instance Extern LemmaName where+    type Box LemmaName = LemmaName+    box = id+    unbox = id  ----------------------------------------------------------------- --- TODO: We now have CrumbBoc, PathBox and TransformCorePathBox.---       Ints are interpreted as a TransformCorePathBox.---       This all needs cleaning up.--data CrumbBox = CrumbBox Crumb deriving Typeable+data RewriteLCoreBox = RewriteLCoreBox (RewriteH LCore) deriving Typeable -instance Extern Crumb where-    type Box Crumb = CrumbBox-    box = CrumbBox-    unbox (CrumbBox cr) = cr+instance Extern (RewriteH LCore) where+    type Box (RewriteH LCore) = RewriteLCoreBox+    box = RewriteLCoreBox+    unbox (RewriteLCoreBox r) = r  ----------------------------------------------------------------- -data PathBox = PathBox LocalPathH deriving Typeable+data TransformLCoreStringBox = TransformLCoreStringBox (TransformH LCore String) deriving Typeable -instance Extern LocalPathH where-    type Box LocalPathH = PathBox-    box = PathBox-    unbox (PathBox p) = p+instance Extern (TransformH LCore String) where+    type Box (TransformH LCore String) = TransformLCoreStringBox+    box = TransformLCoreStringBox+    unbox (TransformLCoreStringBox t) = t  ----------------------------------------------------------------- -data TransformCorePathBox = TransformCorePathBox (TransformH Core LocalPathH) deriving Typeable+data TransformLCoreUnitBox = TransformLCoreUnitBox (TransformH LCore ()) deriving Typeable -instance Extern (TransformH Core LocalPathH) where-    type Box (TransformH Core LocalPathH) = TransformCorePathBox-    box = TransformCorePathBox-    unbox (TransformCorePathBox t) = t+instance Extern (TransformH LCore ()) where+    type Box (TransformH LCore ()) = TransformLCoreUnitBox+    box = TransformLCoreUnitBox+    unbox (TransformLCoreUnitBox t) = t  ----------------------------------------------------------------- -data TransformCoreTCPathBox = TransformCoreTCPathBox (TransformH CoreTC LocalPathH) deriving Typeable+data TransformLCorePathBox = TransformLCorePathBox (TransformH LCore LocalPathH) deriving Typeable -instance Extern (TransformH CoreTC LocalPathH) where-    type Box (TransformH CoreTC LocalPathH) = TransformCoreTCPathBox-    box = TransformCoreTCPathBox-    unbox (TransformCoreTCPathBox t) = t+instance Extern (TransformH LCore LocalPathH) where+    type Box (TransformH LCore LocalPathH) = TransformLCorePathBox+    box = TransformLCorePathBox+    unbox (TransformLCorePathBox t) = t  ----------------------------------------------------------------- -newtype CoreString = CoreString { unCoreString :: String } deriving Typeable+data BiRewriteLCoreBox = BiRewriteLCoreBox (BiRewriteH LCore) deriving Typeable -instance Extern CoreString where-    type Box CoreString = CoreString-    box = id-    unbox = id+instance Extern (BiRewriteH LCore) where+    type Box (BiRewriteH LCore) = BiRewriteLCoreBox+    box = BiRewriteLCoreBox+    unbox (BiRewriteLCoreBox b) = b  ----------------------------------------------------------------- -data StringBox = StringBox String deriving Typeable+data RewriteLCoreListBox = RewriteLCoreListBox [RewriteH LCore] deriving Typeable -instance Extern String where-    type Box String = StringBox-    box = StringBox-    unbox (StringBox s) = s+instance Extern [RewriteH LCore] where+    type Box [RewriteH LCore] = RewriteLCoreListBox+    box = RewriteLCoreListBox+    unbox (RewriteLCoreListBox l) = l  ----------------------------------------------------------------- -data StringListBox = StringListBox [String] deriving Typeable+data RewriteLCoreTCBox = RewriteLCoreTCBox (RewriteH LCoreTC) deriving Typeable -instance Extern [String] where-    type Box [String] = StringListBox-    box = StringListBox-    unbox (StringListBox l) = l+instance Extern (RewriteH LCoreTC) where+    type Box (RewriteH LCoreTC) = RewriteLCoreTCBox+    box = RewriteLCoreTCBox+    unbox (RewriteLCoreTCBox r) = r  ----------------------------------------------------------------- -data IntListBox = IntListBox [Int] deriving Typeable+data TransformLCoreTCStringBox = TransformLCoreTCStringBox (TransformH LCoreTC String) deriving Typeable -instance Extern [Int] where-    type Box [Int] = IntListBox-    box = IntListBox-    unbox (IntListBox l) = l+instance Extern (TransformH LCoreTC String) where+    type Box (TransformH LCoreTC String) = TransformLCoreTCStringBox+    box = TransformLCoreTCStringBox+    unbox (TransformLCoreTCStringBox t) = t  ----------------------------------------------------------------- -data RewriteCoreListBox = RewriteCoreListBox [RewriteH Core] deriving Typeable+data TransformLCoreTCUnitBox = TransformLCoreTCUnitBox (TransformH LCoreTC ()) deriving Typeable -instance Extern [RewriteH Core] where-    type Box [RewriteH Core] = RewriteCoreListBox-    box = RewriteCoreListBox-    unbox (RewriteCoreListBox l) = l+instance Extern (TransformH LCoreTC ()) where+    type Box (TransformH LCoreTC ()) = TransformLCoreTCUnitBox+    box = TransformLCoreTCUnitBox+    unbox (TransformLCoreTCUnitBox t) = t  ----------------------------------------------------------------- -instance Extern RememberedName where-    type Box RememberedName = RememberedName-    box = id-    unbox = id+data TransformLCoreTCLCoreBox = TransformLCoreTCLCoreBox (TransformH LCoreTC LCore) deriving Typeable +instance Extern (TransformH LCoreTC LCore) where+    type Box (TransformH LCoreTC LCore) = TransformLCoreTCLCoreBox+    box = TransformLCoreTCLCoreBox+    unbox (TransformLCoreTCLCoreBox t) = t+ ----------------------------------------------------------------- -instance Extern LemmaName where-    type Box LemmaName = LemmaName-    box = id-    unbox = id+data TransformLCoreTCPathBox = TransformLCoreTCPathBox (TransformH LCoreTC LocalPathH) deriving Typeable +instance Extern (TransformH LCoreTC LocalPathH) where+    type Box (TransformH LCoreTC LocalPathH) = TransformLCoreTCPathBox+    box = TransformLCoreTCPathBox+    unbox (TransformLCoreTCPathBox t) = t+ ----------------------------------------------------------------- -data RewriteEqualityBox = RewriteEqualityBox (RewriteH Equality) deriving Typeable+data BiRewriteLCoreTCBox = BiRewriteLCoreTCBox (BiRewriteH LCoreTC) deriving Typeable -instance Extern (RewriteH Equality) where-    type Box (RewriteH Equality) = RewriteEqualityBox-    box = RewriteEqualityBox-    unbox (RewriteEqualityBox r) = r+instance Extern (BiRewriteH LCoreTC) where+    type Box (BiRewriteH LCoreTC) = BiRewriteLCoreTCBox+    box = BiRewriteLCoreTCBox+    unbox (BiRewriteLCoreTCBox b) = b  ----------------------------------------------------------------- -data TransformEqualityStringBox = TransformEqualityStringBox (TransformH Equality String) deriving Typeable+data RewriteLCoreTCListBox = RewriteLCoreTCListBox [RewriteH LCoreTC] deriving Typeable -instance Extern (TransformH Equality String) where-    type Box (TransformH Equality String) = TransformEqualityStringBox-    box = TransformEqualityStringBox-    unbox (TransformEqualityStringBox t) = t+instance Extern [RewriteH LCoreTC] where+    type Box [RewriteH LCoreTC] = RewriteLCoreTCListBox+    box = RewriteLCoreTCListBox+    unbox (RewriteLCoreTCListBox l) = l  -----------------------------------------------------------------
src/HERMIT/GHC.hs view
@@ -19,6 +19,7 @@     , TyLit(..)     , GhcException(..)     , throwGhcException+    , throwCmdLineErrorS     , exprArity     , occurAnalyseExpr_NoBinderSwap     , isKind@@ -44,6 +45,7 @@     , module Class     , module DsBinds     , module DsMonad+    , module DynamicLoading     , module ErrUtils     , module PrelNames     , module TcEnv@@ -65,12 +67,13 @@ import qualified CoreMonad -- for getHscEnv import           DsBinds (dsEvBinds) import           DsMonad (DsM, initDsTc)+import           DynamicLoading (forceLoadTyCon, getValueSafely, lookupRdrNameInModuleForPlugins) import           Encoding (zEncodeString) import           ErrUtils (pprErrMsgBag) import           Finder (findImportedModule, cannotFindModule) -- we hide these so that they don't get inadvertently used. -- several are redefined in Core.hs and elsewhere-import           GhcPlugins hiding (exprFreeVars, exprFreeIds, bindFreeVars, PluginPass, getHscEnv, RuleName)+import           GhcPlugins hiding (exprSomeFreeVars, exprFreeVars, exprFreeIds, bindFreeVars, getHscEnv, RuleName) import           Kind (isKind,isLiftedTypeKindCon) import           LoadIface (loadSysInterface) import qualified OccName -- for varName
src/HERMIT/Kernel.hs view
@@ -1,149 +1,236 @@-{-# LANGUAGE RankNTypes, ScopedTypeVariables, TupleSections, GADTs #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TypeFamilies #-}  module HERMIT.Kernel     ( -- * The HERMIT Kernel       AST+    , firstAST+    , ASTMap     , Kernel     , KernelEnv(..)     , hermitKernel+    , CommitMsg(..)+      -- ** Kernel Interface     , resumeK     , abortK     , applyK     , queryK     , deleteK     , listK+    , tellK     ) where -import Prelude hiding (lookup)+import Prelude hiding (lookup, null) -import HERMIT.Context-import HERMIT.Monad-import HERMIT.Kure-import HERMIT.GHC hiding (singleton, empty)+import Control.Concurrent+import Control.Monad+import Control.Monad.IO.Class +import Data.IORef import Data.Map-import Control.Concurrent+import Data.Typeable --- | 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.+import HERMIT.Context+import HERMIT.External+import HERMIT.GHC hiding (singleton, empty)+import HERMIT.Kure+import HERMIT.Lemma+import HERMIT.Monad++-- | A 'Kernel' is a repository for complete Core syntax trees ('ModGuts') and Lemmas. 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 ModGuts     -> KernelEnv -> IO (KureM AST) -- ^ Apply a 'Rewrite' to the specified 'AST' and return a handle to the resulting 'AST'.-  , queryK  :: forall a . AST -> TransformH ModGuts a -> KernelEnv -> IO (KureM a)   -- ^ Apply a 'TransformH' 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'.+  { -- | Halt the 'Kernel' and return control to GHC, which compiles the specified 'AST'.+    resumeK :: MonadIO m =>                                   AST -> m ()+    -- | Halt the 'Kernel' and abort GHC without compiling.+  , abortK  :: MonadIO m =>                                          m ()+    -- | Apply a 'Rewrite' to the specified 'AST' and return a handle to the resulting 'AST'.+  , applyK  :: (MonadIO m, MonadCatch m)+            => RewriteH ModGuts     -> CommitMsg -> KernelEnv -> AST -> m AST+    -- | Apply a 'TransformH' to the 'AST', return the resulting value, and potentially a new 'AST'.+  , queryK  :: (MonadIO m, MonadCatch m)+            => TransformH ModGuts a -> CommitMsg -> KernelEnv -> AST -> m (AST,a)+    -- | Delete the internal record of the specified 'AST'.+  , deleteK :: MonadIO m =>                                   AST -> m ()+    -- | List all the 'AST's tracked by the 'Kernel', including version data.+  , listK   :: MonadIO m =>                                          m [(AST,Maybe String, Maybe AST)]+    -- | Log a new AST with same Lemmas/ModGuts as given AST.+  , tellK   :: (MonadIO m, MonadCatch m) => String         -> AST -> m AST   } +data CommitMsg = Always String | Changed String | Never++msg :: CommitMsg -> Maybe String+msg Never = Nothing+msg (Always s) = Just s+msg (Changed s) = Just s+ -- | 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)+    deriving (Eq, Ord, Typeable) -data Msg s r = forall a . Req (s -> CoreM (KureM (a,s))) (MVar (KureM a))-             | Done (s -> CoreM r)+firstAST :: AST+firstAST = AST 0 -type ASTMap = Map AST KernelState+-- for succ+instance Enum AST where+    toEnum = AST+    fromEnum (AST i) = i -data KernelState = KernelState { _ksStash  :: DefStash-                               , _ksLemmas :: Lemmas-                               , ksGuts   :: ModGuts-                               }+instance Show AST where+    show (AST i) = show i -fromHermitMResult :: HermitMResult ModGuts -> KernelState-fromHermitMResult hRes = sideEffectsOnly hRes (hResult hRes)+instance Read AST where+    readsPrec p s = [ (AST i,s') | (i,s') <- readsPrec p s ] -sideEffectsOnly :: HermitMResult a -> ModGuts -> KernelState-sideEffectsOnly hRes = KernelState (hResStash hRes) (hResLemmas hRes)+instance Extern AST where+    type Box AST = AST+    box i = i+    unbox i = i -data KernelEnv = KernelEnv { kEnvChan :: DebugMessage -> HermitM () }+data ASTMap = ASTMap { astNext :: AST+                     , astMap  :: Map AST KernelState+                     } --- | Start a HERMIT client by providing an IO function that takes the initial 'Kernel' and inital 'AST' handle.---   The 'Modguts' to 'CoreM' Modguts' function required by GHC Plugins is returned.---   The callback is only ever called once.-hermitKernel :: (Kernel -> AST -> IO ()) -> ModGuts -> CoreM ModGuts-hermitKernel callback modGuts = do+emptyASTMap :: ASTMap+emptyASTMap = ASTMap firstAST empty -        msgMV :: MVar (Msg ASTMap ModGuts) <- liftIO newEmptyMVar+data KernelState = KernelState { ksLemmas  :: Lemmas+                               , ksGuts    :: ModGuts+                               , _ksParent :: Maybe AST+                               , _ksCommit :: Maybe String+                               } -        nextASTname :: MVar AST <- liftIO newEmptyMVar+data KernelEnv = KernelEnv { kEnvChan :: DebugMessage -> HermitM () } -        _ <- liftIO $ forkIO $ let loop n = do putMVar nextASTname (AST n)-                                               loop (succ n)-                                in loop 0+-- | Internal API. The 'Kernel' object wraps these calls.+data Msg where+    Apply  :: AST -> (KernelState -> CoreM (KureM (Maybe KernelState, a)))+                  -> (MVar (KureM (AST, a))) -> Msg+    Read   :: (Map AST KernelState -> IO ()) -> Msg+    Delete :: AST                            -> Msg+    Done   :: Maybe AST                      -> Msg -        let sendDone :: (ASTMap -> CoreM ModGuts) -> IO ()-            sendDone = putMVar msgMV . Done+-- | Put a 'KernelState' in the 'ASTMap', returning+-- the 'AST' to which it was assigned.+insertAST :: KernelState -> ASTMap -> (AST, ASTMap)+insertAST ks (ASTMap k m) = (k, ASTMap (succ k) (insert k ks m)) -        let sendReq :: (ASTMap -> CoreM (KureM (a, ASTMap))) -> IO (KureM a)-            sendReq fn = do rep  <- newEmptyMVar-                            putMVar msgMV (Req fn rep)-                            takeMVar rep+findAST :: AST -> Map AST KernelState -> (String -> b) -> (KernelState -> b) -> b+findAST ast m f = find ast m (f $ "Cannot find syntax tree: " ++ show ast) -        let sendReqRead :: (ASTMap -> CoreM (KureM a)) -> IO (KureM a)-            sendReqRead fn = sendReq (\ st -> (fmap.fmap) (,st) $ fn st) -- >>= return . fmap fst+-- | Start a HERMIT client by providing an IO callback that takes the+--   initial 'Kernel' and inital 'AST' handle. The callback is only+--   ever called once. The 'Modguts -> CoreM Modguts' function+--   required by GHC Plugins is returned.+hermitKernel :: IORef (Maybe (AST, ASTMap)) -- ^ Global (across passes) AST store.+             -> String                      -- ^ Last GHC pass name+             -> (Kernel -> AST -> IO ())    -- ^ Callback+             -> ModGuts -> CoreM ModGuts+hermitKernel store lastPass callback modGuts = do -        let sendReqWrite :: (ASTMap -> CoreM ASTMap) -> IO ()-            sendReqWrite fn = sendReq (fmap ( return . ((),) ) . fn) >>= {- fmap fst . -} liftKureM+    msgMV :: MVar Msg <- liftIO newEmptyMVar -        let kernel :: Kernel-            kernel = Kernel-                { resumeK = \ name ->-                                sendDone $ \ st ->-                                    findWithErrMsg name-                                                   st-                                                   (\ msg -> throwGhcException-                                                             $ ProgramError-                                                             $ msg ++ ", exiting HERMIT and aborting GHC compilation.")-                                                   (return.ksGuts)+    let withAST :: (MonadIO m, MonadCatch m)+                => AST -> (KernelState -> CoreM (KureM (Maybe KernelState, a))) -> m (AST, a)+        withAST ast k = do+            r <- liftIO $ do+                    resVar <- newEmptyMVar+                    putMVar msgMV $ Apply ast k resVar+                    takeMVar resVar+            runKureM return fail r -                , abortK  = sendDone $ \ _ -> throwGhcException-                                              $ ProgramError "Exiting HERMIT and aborting GHC compilation."+        readOnly :: MonadIO m => (Map AST KernelState -> KureM a) -> m (KureM a)+        readOnly f = liftIO $ do+            resVar <- newEmptyMVar+            putMVar msgMV (Read (runKureM (putMVar resVar . return)+                                          (putMVar resVar . fail) . f))+            takeMVar resVar -                , applyK = \ name r kEnv ->-                                sendReq $ \ st ->-                                    findWithErrMsg name st fail $ \ (KernelState defs lemmas guts) ->-                                        runHM (kEnvChan kEnv)-                                              (mkEnv guts defs lemmas)-                                              (\ hRes -> do-                                                    ast <- liftIO $ takeMVar nextASTname-                                                    return $ return (ast, insert ast (fromHermitMResult hRes) st))-                                              (return . fail)-                                              (applyT r (topLevelHermitC guts) guts)+    let kernel :: Kernel+        kernel = Kernel+            { resumeK = liftIO . putMVar msgMV . Done . Just -                , queryK = \ name t kEnv ->-                                sendReqRead $ \ st ->-                                    findWithErrMsg name st fail $ \ (KernelState defs lemmas guts) ->-                                        runHM (kEnvChan kEnv)-                                              (mkEnv guts defs lemmas)-                                              (return . return . hResult)-                                              (return . fail)-                                              (applyT t (topLevelHermitC guts) guts)+            , abortK  = liftIO $ putMVar msgMV (Done Nothing) -                , deleteK = \ name -> sendReqWrite (return . delete name)+            , applyK = \ rr cm kEnv ast -> liftM fst $+                            withAST ast $ \ (KernelState lemmas guts _ _) -> do+                                let handleS hRes = return $ return+                                                   (Just (KernelState (hResLemmas hRes) (hResult hRes) (Just ast) (msg cm)), ())+                                runHM (kEnvChan kEnv)+                                      (mkEnv guts lemmas)+                                      handleS+                                      (return . fail)+                                      (applyT rr (topLevelHermitC guts) guts) -                , listK = sendReqRead (return . return . keys) >>= liftKureM-                }+            , queryK = \ t cm kEnv ast ->+                            withAST ast $ \ (KernelState lemmas guts _ _) -> do+                                let handleS hRes+                                        | hResChanged hRes = f (Just (KernelState (hResLemmas hRes) guts (Just ast) (msg cm)), r)+                                        | Always s <- cm   = f (Just (KernelState lemmas guts (Just ast) (Just s)), r)+                                        | otherwise        = f (Nothing, r) -- pure query, not recorded in AST store+                                        where r = hResult hRes+                                              f = return . return+                                runHM (kEnvChan kEnv)+                                      (mkEnv guts lemmas)+                                      handleS+                                      (return . fail)+                                      (applyT t (topLevelHermitC guts) guts) -        -- We always start with AST 0-        ast0 <- liftIO $ takeMVar nextASTname+            , deleteK = liftIO . putMVar msgMV . Delete -        let loop :: ASTMap -> CoreM ModGuts-            loop st = do-                m <- liftIO $ takeMVar msgMV-                case m of-                  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+            , listK = readOnly (\m -> return [ (ast,cm,p) | (ast,KernelState _ _ p cm) <- toList m ])+                        >>= runKureM return fail -        _pid <- liftIO $ forkIO $ callback kernel ast0+            , tellK = \ str ast -> liftM fst $+                            withAST ast $ \ (KernelState lemmas guts _ _) ->+                                return $ return (Just $ KernelState lemmas guts (Just ast) (Just str), ())+            } -        loop (singleton ast0 $ KernelState empty empty modGuts)+    let loop :: ASTMap -> CoreM ModGuts+        loop m = do+            cmd <- liftIO $ takeMVar msgMV+            case cmd of+              Apply ast f resVar -> do+                kr <- findAST ast (astMap m) (return . fail) f+                let handleS (mbKS, r) =+                        case mbKS of+                            Nothing -> liftIO (putMVar resVar $ return (ast,r)) >> loop m+                            Just ks -> let (ast', m') = insertAST ks m in+                                       liftIO (putMVar resVar (return (ast',r))) >> loop m'+                    handleF str = liftIO (putMVar resVar $ fail str) >> loop m+                runKureM handleS handleF kr+              Read fn -> liftIO (fn (astMap m)) >> loop m+              Delete ast -> loop $ ASTMap (astNext m) $ delete ast (astMap m)+              Done mbAST ->+                case mbAST of+                    Nothing  ->+                        abortKernel "Exiting HERMIT and aborting GHC compilation."+                    Just ast -> do+                        findAST ast (astMap m)+                            (\str -> abortKernel $ str ++ ", exiting HERMIT and aborting GHC compilation.")+                            (\ks -> liftIO (writeIORef store (Just (ast, m))) >> return (ksGuts ks)) -        -- (Kill the pid'd thread? do we need to?)+    -- Get the most recent AST and ASTMap the last HERMIT pass resumed with.+    mbS <- liftIO $ readIORef store+    (ast0,m) <- case mbS of+        Nothing      -> return $ insertAST (KernelState empty modGuts Nothing Nothing) emptyASTMap+        Just (ast,m) -> do+            ls <- findAST ast (astMap m)+                    (\str -> abortKernel $ str ++ ", exiting HERMIT and aborting GHC compilation.")+                    (return . ksLemmas)+            return $ insertAST (KernelState ls modGuts (Just ast) (Just lastPass)) m -findWithErrMsg :: AST -> Map AST v -> (String -> b) -> (v -> b) -> b-findWithErrMsg ast m f = find ast m (f $ "Cannot find syntax tree: " ++ show ast)+    void $ liftIO $ forkIO $ callback kernel ast0++    loop m++abortKernel :: String -> CoreM a+abortKernel = throwGhcException . ProgramError  find :: Ord k => k -> Map k v -> b -> (v -> b) -> b find k m f s = maybe f s (lookup k m)
− src/HERMIT/Kernel/Scoped.hs
@@ -1,167 +0,0 @@-{-# LANGUAGE RankNTypes, FlexibleContexts, InstanceSigs #-}-module HERMIT.Kernel.Scoped-    ( Direction(..)-    , LocalPath-    , moveLocally-    , ScopedKernel(..)-    , SAST(..)-    , scopedKernel-    ) where--import Control.Arrow-import Control.Concurrent.STM-import Control.Exception (bracketOnError)-import Control.Monad-import Control.Monad.IO.Class--import Data.Maybe (fromMaybe)-import Data.Monoid (mempty)-import qualified Data.IntMap as I--import HERMIT.Core-import HERMIT.Context-import HERMIT.Kure-import HERMIT.GHC hiding (Direction,L)-import HERMIT.Kernel---------------------------------------------------------------------------------- | A primitive means of denoting navigation of a tree (within a local scope).-data Direction = L -- ^ Left-               | R -- ^ Right-               | U -- ^ Up-               | T -- ^ Top-               deriving (Eq,Show)--pathStack2Paths :: [LocalPath crumb] -> LocalPath crumb -> [Path crumb]-pathStack2Paths ps p = reverse (map snocPathToPath (p:ps))---- | Movement confined within the local scope.-moveLocally :: Direction -> LocalPathH -> LocalPathH-moveLocally d (SnocPath p) = case p of-                               []     -> mempty-                               cr:crs -> case d of-                                           T -> mempty-                                           U -> SnocPath crs-                                           L -> SnocPath (fromMaybe cr (deprecatedLeftSibling cr)  : crs)-                                           R -> SnocPath (fromMaybe cr (deprecatedRightSibling cr) : crs)---pathStackToLens :: (Injection ModGuts g, Walker HermitC g) => [LocalPathH] -> LocalPathH -> LensH ModGuts g-pathStackToLens ps p = injectL >>> pathL (concat $ pathStack2Paths ps p)---- This function is used to check the validity of paths, so which sum type we use is important.-testPathStackT :: [LocalPathH] -> LocalPathH -> TransformH ModGuts Bool-testPathStackT ps p = testLensT (pathStackToLens ps p :: LensH ModGuts CoreTC)---------------------------------------------------------------------------------- | An alternative HERMIT kernel, that provides scoping.-data ScopedKernel = ScopedKernel-    { resumeS      :: (MonadIO m, MonadCatch m) =>               SAST -> m ()-    , abortS       ::  MonadIO m                =>                       m ()-    , applyS       :: (MonadIO m, MonadCatch m, Injection ModGuts g, Walker HermitC g)-                   => RewriteH g     -> KernelEnv ->             SAST -> m SAST-    , queryS       :: (MonadIO m, MonadCatch m, Injection ModGuts g, Walker HermitC g)-                   => TransformH g a -> KernelEnv ->             SAST -> m a-    , deleteS      :: (MonadIO m, MonadCatch m) =>               SAST -> m ()-    , listS        ::  MonadIO m                =>                       m [SAST]-    , pathS        :: (MonadIO m, MonadCatch m) =>               SAST -> m [PathH]-    , modPathS     :: (MonadIO m, MonadCatch m)-                   => (LocalPathH -> LocalPathH) -> KernelEnv -> SAST -> m SAST-    , beginScopeS  :: (MonadIO m, MonadCatch m) =>               SAST -> m SAST-    , endScopeS    :: (MonadIO m, MonadCatch m) =>               SAST -> m SAST-    -- means of accessing the underlying kernel, obviously for unsafe purposes-    , kernelS      ::                                                    Kernel-    , toASTS       :: (MonadIO m, MonadCatch m) =>               SAST -> m AST-    }---- | A /handle/ for an 'AST' combined with scoping information.-newtype SAST = SAST Int deriving (Eq, Ord, Show)---- path stack, representing the base path, then the relative path-type SASTStore = I.IntMap (AST, [LocalPathH], LocalPathH)--get :: Monad m => Int -> SASTStore -> m (AST, [LocalPathH], LocalPathH)-get sAst m = maybe (fail "scopedKernel: invalid SAST") return (I.lookup sAst m)---- | Ensures that the TMVar is replaced when an error is thrown, and all exceptions are lifted into MonadCatch failures.-safeTakeTMVar :: (MonadCatch m, MonadIO m) => TMVar a -> (a -> IO b) -> m b-safeTakeTMVar mvar = liftAndCatchIO . bracketOnError (atomically $ takeTMVar mvar) (atomically . putTMVar mvar)---- | Start a HERMIT client by providing an IO function that takes the initial 'ScopedKernel' and inital 'SAST' handle.---   The 'Modguts' to 'CoreM' Modguts' function required by GHC Plugins is returned.-scopedKernel :: (ScopedKernel -> SAST -> IO ()) -> ModGuts -> CoreM ModGuts-scopedKernel callback = hermitKernel $ \ kernel initAST -> do-    store <- newTMVarIO $ I.fromList [(0,(initAST, [], mempty))]-    key <- newTMVarIO (1::Int)--    let newKey = do-            k <- takeTMVar key-            putTMVar key (k+1)-            return k--        skernel = ScopedKernel-            { resumeS     = \ (SAST sAst) -> liftAndCatchIO $ do-                                m <- atomically $ readTMVar store-                                (ast,_,_) <- get sAst m-                                resumeK kernel ast-            , abortS      = liftIO $ abortK kernel-            , applyS      = \ rr env (SAST sAst) -> safeTakeTMVar store $ \ m -> do-                                (ast, base, rel) <- get sAst m-                                applyK kernel ast (focusR (pathStackToLens base rel) rr) env-                                  >>= runKureM (\ ast' -> atomically $ do-                                                    k <- newKey-                                                    putTMVar store $ I.insert k (ast', base, rel) m-                                                    return (SAST k))-                                               fail-            , queryS      = \ t env (SAST sAst) -> liftAndCatchIO $ do-                                m <- atomically $ readTMVar store-                                (ast, base, rel) <- get sAst m-                                queryK kernel ast (focusT (pathStackToLens base rel) t) env-                                    >>= liftKureM-            , deleteS     = \ (SAST sAst) -> safeTakeTMVar store $ \ m -> do-                                (ast,_,_) <- get sAst m-                                let m' = I.delete sAst m-                                    fst3 (x,_,_) = x-                                    asts = I.foldr ((:) . fst3) [] m'-                                when (ast `notElem` asts) $ deleteK kernel ast-                                atomically $ putTMVar store m'-            , listS       = do m <- liftIO $ atomically $ readTMVar store-                               return [ SAST sAst | sAst <- I.keys m ]-            , pathS       = \ (SAST sAst) -> liftAndCatchIO $ do-                                m <- atomically $ readTMVar store-                                (_, base, rel) <- get sAst m-                                return $ pathStack2Paths base rel-            , modPathS    = \ f env (SAST sAst) -> safeTakeTMVar store $ \ m -> do-                                (ast, base, rel) <- get sAst m-                                let rel' = f rel-                                queryK kernel ast (testPathStackT base rel') env-                                  >>= runKureM (\ b -> if rel == rel'-                                                        then fail "Path is unchanged, nothing to do."-                                                        else if b-                                                              then atomically $ do k <- newKey-                                                                                   putTMVar store $ I.insert k (ast, base, rel') m-                                                                                   return $ SAST k-                                                              else fail "Invalid path created.")-                                               fail-            , beginScopeS = \ (SAST sAst) -> safeTakeTMVar store $ \m -> do-                                (ast, base, rel) <- get sAst m-                                atomically $ do k <- newKey-                                                putTMVar store $ I.insert k (ast, rel : base, mempty) m-                                                return $ SAST k-            , endScopeS   = \ (SAST sAst) -> safeTakeTMVar store $ \m -> do-                                (ast, base, _) <- get sAst m-                                case base of-                                    []          -> fail "Scoped Kernel: no scope to end."-                                    rel : base' -> atomically $ do k <- newKey-                                                                   putTMVar store $ I.insert k (ast, base', rel) m-                                                                   return $ SAST k-            , kernelS     = kernel-            , toASTS      = \ (SAST sAst) -> liftAndCatchIO $ do-                                m <- atomically $ readTMVar store-                                (ast, _, _) <- get sAst m-                                return ast-            }--    callback skernel $ SAST 0
src/HERMIT/Kure.hs view
@@ -1,84 +1,96 @@-{-# LANGUAGE CPP, LambdaCase, FlexibleInstances, MultiParamTypeClasses, FlexibleContexts, UndecidableInstances, ScopedTypeVariables, InstanceSigs #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE InstanceSigs #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE UndecidableInstances #-}  module HERMIT.Kure-       (-       -- * KURE+    ( -- * KURE -       -- | 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.BiTransform-       , module Language.KURE.Lens-       , module Language.KURE.ExtendableContext-       , module Language.KURE.Pathfinder-       -- * Sub-Modules-       , module HERMIT.Kure.SumTypes-       -- * Synonyms-       , TransformH-       , RewriteH-       , BiRewriteH-       , LensH-       , PathH+      -- | 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.BiTransform+    , module Language.KURE.Lens+    , module Language.KURE.ExtendableContext+    , module Language.KURE.Pathfinder+      -- * Sub-Modules+    , module HERMIT.Kure.Universes+      -- * Synonyms+    , TransformH+    , RewriteH+    , BiRewriteH+    , LensH+    , PathH -       -- * Congruence combinators-       -- ** Modguts-       , modGutsT, modGutsR-       -- ** Program-       , progNilT-       , progConsT, progConsAllR, progConsAnyR, progConsOneR-       -- ** Binding Groups-       , nonRecT, nonRecAllR, nonRecAnyR, nonRecOneR-       , recT, recAllR, recAnyR, recOneR-       -- ** Recursive Definitions-       , defT, defAllR, defAnyR, defOneR-       -- ** Case Alternatives-       , altT, altAllR, altAnyR, altOneR-       -- ** Expressions-       , varT, varR-       , litT, litR-       , appT, appAllR, appAnyR, appOneR-       , lamT, lamAllR, lamAnyR, lamOneR-       , letT, letAllR, letAnyR, letOneR-       , caseT, caseAllR, caseAnyR, caseOneR-       , castT, castAllR, castAnyR, castOneR-       , tickT, tickAllR, tickAnyR, tickOneR-       , typeT, typeR-       , coercionT, coercionR-       -- ** Composite Congruence Combinators-       , defOrNonRecT, defOrNonRecAllR, defOrNonRecAnyR, defOrNonRecOneR-       , recDefT, recDefAllR, recDefAnyR, recDefOneR-       , letNonRecT, letNonRecAllR, letNonRecAnyR, letNonRecOneR-       , letRecT, letRecAllR, letRecAnyR, letRecOneR-       , letRecDefT, letRecDefAllR, letRecDefAnyR, letRecDefOneR-       , consNonRecT, consNonRecAllR, consNonRecAnyR, consNonRecOneR-       , consRecT, consRecAllR, consRecAnyR, consRecOneR-       , consRecDefT, consRecDefAllR, consRecDefAnyR, consRecDefOneR-       , caseAltT, caseAltAllR, caseAltAnyR, caseAltOneR-       -- ** Recursive Composite Congruence Combinators-       , progBindsT, progBindsAllR, progBindsAnyR, progBindsOneR-       -- ** Types-       , tyVarT, tyVarR-       , litTyT, litTyR-       , appTyT, appTyAllR, appTyAnyR, appTyOneR-       , funTyT, funTyAllR, funTyAnyR, funTyOneR-       , forAllTyT, forAllTyAllR, forAllTyAnyR, forAllTyOneR-       , tyConAppT, tyConAppAllR, tyConAppAnyR, tyConAppOneR-       -- ** Coercions-       , reflT, reflR-       , tyConAppCoT, tyConAppCoAllR, tyConAppCoAnyR, tyConAppCoOneR-       , appCoT, appCoAllR, appCoAnyR, appCoOneR-       , forAllCoT, forAllCoAllR, forAllCoAnyR, forAllCoOneR-       , coVarCoT, coVarCoR-       , axiomInstCoT, axiomInstCoAllR, axiomInstCoAnyR, axiomInstCoOneR-       , symCoT, symCoR-       , transCoT, transCoAllR, transCoAnyR, transCoOneR-       , nthCoT, nthCoAllR, nthCoAnyR, nthCoOneR-       , instCoT, instCoAllR, instCoAnyR, instCoOneR-       , lrCoT, lrCoAllR, lrCoAnyR, lrCoOneR-       -- * Conversion to deprecated Int representation-       , deprecatedIntToCrumbT-       , deprecatedIntToPathT-       )-where+      -- * Congruence combinators+      -- ** Modguts+    , modGutsT, modGutsR+      -- ** Program+    , progNilT+    , progConsT, progConsAllR, progConsAnyR, progConsOneR+      -- ** Binding Groups+    , nonRecT, nonRecAllR, nonRecAnyR, nonRecOneR+    , recT, recAllR, recAnyR, recOneR+      -- ** Recursive Definitions+    , defT, defAllR, defAnyR, defOneR+      -- ** Case Alternatives+    , altT, altAllR, altAnyR, altOneR+      -- ** Expressions+    , varT, varR+    , litT, litR+    , appT, appAllR, appAnyR, appOneR+    , lamT, lamAllR, lamAnyR, lamOneR+    , letT, letAllR, letAnyR, letOneR+    , caseT, caseAllR, caseAnyR, caseOneR+    , castT, castAllR, castAnyR, castOneR+    , tickT, tickAllR, tickAnyR, tickOneR+    , typeT, typeR+    , coercionT, coercionR+      -- ** Composite Congruence Combinators+    , defOrNonRecT, defOrNonRecAllR, defOrNonRecAnyR, defOrNonRecOneR+    , recDefT, recDefAllR, recDefAnyR, recDefOneR+    , letNonRecT, letNonRecAllR, letNonRecAnyR, letNonRecOneR+    , letRecT, letRecAllR, letRecAnyR, letRecOneR+    , letRecDefT, letRecDefAllR, letRecDefAnyR, letRecDefOneR+    , consNonRecT, consNonRecAllR, consNonRecAnyR, consNonRecOneR+    , consRecT, consRecAllR, consRecAnyR, consRecOneR+    , consRecDefT, consRecDefAllR, consRecDefAnyR, consRecDefOneR+    , caseAltT, caseAltAllR, caseAltAnyR, caseAltOneR+      -- ** Recursive Composite Congruence Combinators+    , progBindsT, progBindsAllR, progBindsAnyR, progBindsOneR+      -- ** Types+    , tyVarT, tyVarR+    , litTyT, litTyR+    , appTyT, appTyAllR, appTyAnyR, appTyOneR+    , funTyT, funTyAllR, funTyAnyR, funTyOneR+    , forAllTyT, forAllTyAllR, forAllTyAnyR, forAllTyOneR+    , tyConAppT, tyConAppAllR, tyConAppAnyR, tyConAppOneR+      -- ** Coercions+    , reflT, reflR+    , tyConAppCoT, tyConAppCoAllR, tyConAppCoAnyR, tyConAppCoOneR+    , appCoT, appCoAllR, appCoAnyR, appCoOneR+    , forAllCoT, forAllCoAllR, forAllCoAnyR, forAllCoOneR+    , coVarCoT, coVarCoR+    , axiomInstCoT, axiomInstCoAllR, axiomInstCoAnyR, axiomInstCoOneR+    , symCoT, symCoR+    , transCoT, transCoAllR, transCoAnyR, transCoOneR+    , nthCoT, nthCoAllR, nthCoAnyR, nthCoOneR+    , instCoT, instCoAllR, instCoAnyR, instCoOneR+    , lrCoT, lrCoAllR, lrCoAnyR, lrCoOneR+      -- ** Lemmas+    , conjT, conjAllR+    , disjT, disjAllR+    , implT, implAllR+    , equivT, equivAllR+    , quantifiedT, quantifiedR+      -- * Applicative+      -- | Remove in 7.10+    , (<$>)+    , (<*>)+    ) where  import Language.KURE import Language.KURE.BiTransform@@ -89,13 +101,12 @@ import HERMIT.Context import HERMIT.Core import HERMIT.GHC+import HERMIT.Kure.Universes+import HERMIT.Lemma import HERMIT.Monad-import HERMIT.Kure.SumTypes  import Control.Monad -import Data.Monoid (mempty)- ---------------------------------------------------------------------  type TransformH a b = Transform HermitC HermitM a b@@ -164,9 +175,6 @@                               _       -> idR       {-# INLINE allRexpr #-} --- NOTE: I tried telling GHC to inline allR and compilation hit the (default) simplifier tick limit.--- TODO: Investigate whether that was achieving useful optimisations.- ---------------------------------------------------------------------  -- | Walking over types (only).@@ -228,7 +236,56 @@  --------------------------------------------------------------------- --- | Walking over modules, programs, binding groups, definitions, expressions and case alternatives.+-- | Walking over modules, programs, binding groups, definitions, expressions, case alternatives, lemma quantifiers and lemma clauses.+instance (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadPath c Crumb) => Walker c LCore where++    allR :: forall m. MonadCatch m => Rewrite c m LCore -> Rewrite c m LCore+    allR r = prefixFailMsg "allR failed: " $+                rewrite $ \ c -> \case+                    LQuantified q  -> inject <$> applyT allRquantified c q+                    LClause cl     -> inject <$> applyT allRclause c cl+                    LCore core     -> inject <$> applyT (allR $ extractR r) c core -- exploiting the fact that quantified/clause does not appear within Core+        where+            allRquantified :: MonadCatch m => Rewrite c m Quantified+            allRquantified = quantifiedR idR (extractR r) -- we don't descend into the binders+            {-# INLINE allRquantified #-}++            allRclause :: MonadCatch m => Rewrite c m Clause+            allRclause = readerT $ \case+                                Conj{}  -> conjAllR  (extractR r) (extractR r)+                                Disj{}  -> disjAllR  (extractR r) (extractR r)+                                Impl{}  -> implAllR  (extractR r) (extractR r)+                                Equiv{} -> equivAllR (extractR r) (extractR r)+            {-# INLINE allRclause #-}++---------------------------------------------------------------------++-- | Walking over modules, programs, binding groups, definitions, expressions, case alternatives, types, coercions, lemma quantifiers and lemma clauses.+instance (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadPath c Crumb) => Walker c LCoreTC where++    allR :: forall m. MonadCatch m => Rewrite c m LCoreTC -> Rewrite c m LCoreTC+    allR r = prefixFailMsg "allR failed: " $+                rewrite $ \ c -> \case+                    LTCCore (LQuantified q)  -> inject <$> applyT allRquantified c q+                    LTCCore (LClause cl)     -> inject <$> applyT allRclause c cl+                    LTCCore (LCore core)     -> inject <$> applyT (allR (extractR r :: Rewrite c m CoreTC)) c (Core core) -- convert to CoreTC, and exploit the fact that quantifiers and clauses will not appear in Core/CoreTC+                    LTCTyCo tyCo             -> inject <$> applyT (allR $ extractR r) c tyCo -- exploiting the fact that only types and coercions appear within types and coercions+        where+            allRquantified :: MonadCatch m => Rewrite c m Quantified+            allRquantified = quantifiedR idR (extractR r) -- we don't descend into the binders+            {-# INLINE allRquantified #-}++            allRclause :: MonadCatch m => Rewrite c m Clause+            allRclause = readerT $ \case+                                Conj{}  -> conjAllR (extractR r) (extractR r)+                                Disj{}  -> disjAllR (extractR r) (extractR r)+                                Impl{}  -> implAllR  (extractR r) (extractR r)+                                Equiv{} -> equivAllR (extractR r) (extractR r)+            {-# INLINE allRclause #-}++---------------------------------------------------------------------++-- | Walking over modules, programs, binding groups, definitions, expressions, case alternatives, types and coercions. instance (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, HasEmptyContext c) => Walker c CoreTC where    allR :: forall m. MonadCatch m => Rewrite c m CoreTC -> Rewrite c m CoreTC@@ -1232,38 +1289,73 @@ {-# INLINE instCoOneR #-}  ------------------------------------------------------------------------------------------------------------------------------------------- --- | Earlier versions of HERMIT used 'Int' as the crumb type.---   This translation maps an 'Int' to the corresponding 'Crumb', for backwards compatibility purposes.-deprecatedIntToCrumbT :: Monad m => Int -> Transform c m Core Crumb-deprecatedIntToCrumbT n = contextfreeT $ \case-                                            GutsCore _                 | n == 0                        -> return ModGuts_Prog-                                            AltCore _                  | n == 0                        -> return Alt_RHS-                                            DefCore _                  | n == 0                        -> return Def_RHS-                                            ProgCore (ProgCons _ _)    | n == 0                        -> return ProgCons_Head-                                                                       | n == 1                        -> return ProgCons_Tail-                                            BindCore (NonRec _ _)      | n == 0                        -> return NonRec_RHS-                                            BindCore (Rec bds)         | (n >= 0) && (n < length bds)  -> return (Rec_Def n)-                                            ExprCore (App _ _)         | n == 0                        -> return App_Fun-                                                                       | n == 1                        -> return App_Arg-                                            ExprCore (Lam _ _)         | n == 0                        -> return Lam_Body-                                            ExprCore (Let _ _)         | n == 0                        -> return Let_Bind-                                                                       | n == 1                        -> return Let_Body-                                            ExprCore (Case _ _ _ alts) | n == 0                        -> return Case_Scrutinee-                                                                       | (n > 0) && (n <= length alts) -> return (Case_Alt (n-1))-                                            ExprCore (Cast _ _)        | n == 0                        -> return Cast_Expr-                                            ExprCore (Tick _ _)        | n == 0                        -> return Tick_Expr-                                            _                                                          -> fail ("Child " ++ show n ++ " does not exist.")-{-# INLINE deprecatedIntToCrumbT #-}+-- | Transform a clause of the form: @Conj@ 'Quantified' 'Quantified'+conjT :: (ExtendPath c Crumb, Monad m) => Transform c m Quantified a1 -> Transform c m Quantified a2 -> (a1 -> a2 -> b) -> Transform c m Clause b+conjT t1 t2 f = transform $ \ c -> \case+                                     Conj q1 q2 -> f <$> applyT t1 (c @@ Conj_Lhs) q1 <*> applyT t2 (c @@ Conj_Rhs) q2+                                     _          -> fail "not a conjunction."+{-# INLINE conjT #-} --- | Builds a path to the first child, based on the old numbering system.-deprecatedIntToPathT :: Monad m => Int -> Transform c m Core LocalPathH-deprecatedIntToPathT =  liftM (mempty @@) . deprecatedIntToCrumbT-{-# INLINE deprecatedIntToPathT #-}+-- | Rewrite all children of a clause of the form: : @Conj@ 'Quantified' 'Quantified'+conjAllR :: (ExtendPath c Crumb, Monad m) => Rewrite c m Quantified -> Rewrite c m Quantified -> Rewrite c m Clause+conjAllR r1 r2 = conjT r1 r2 Conj+{-# INLINE conjAllR #-} ++-- | Transform a clause of the form: @Disj@ 'Quantified' 'Quantified'+disjT :: (ExtendPath c Crumb, Monad m) => Transform c m Quantified a1 -> Transform c m Quantified a2 -> (a1 -> a2 -> b) -> Transform c m Clause b+disjT t1 t2 f = transform $ \ c -> \case+                                     Conj q1 q2 -> f <$> applyT t1 (c @@ Disj_Lhs) q1 <*> applyT t2 (c @@ Disj_Rhs) q2+                                     _          -> fail "not a disjunction."+{-# INLINE disjT #-}++-- | Rewrite all children of a clause of the form: : @Disj@ 'Quantified' 'Quantified'+disjAllR :: (ExtendPath c Crumb, Monad m) => Rewrite c m Quantified -> Rewrite c m Quantified -> Rewrite c m Clause+disjAllR r1 r2 = disjT r1 r2 Disj+{-# INLINE disjAllR #-}+++-- | Transform a clause of the form: @Impl@ 'Quantified' 'Quantified'+implT :: (ExtendPath c Crumb, Monad m) => Transform c m Quantified a1 -> Transform c m Quantified a2 -> (a1 -> a2 -> b) -> Transform c m Clause b+implT t1 t2 f = transform $ \ c -> \case+                                     Impl q1 q2 -> f <$> applyT t1 (c @@ Impl_Lhs) q1 <*> applyT t2 (c @@ Impl_Rhs) q2+                                     _          -> fail "not an implication."+{-# INLINE implT #-}++-- | Rewrite all children of a clause of the form: : @Impl@ 'Quantified' 'Quantified'+implAllR :: (ExtendPath c Crumb, Monad m) => Rewrite c m Quantified -> Rewrite c m Quantified -> Rewrite c m Clause+implAllR r1 r2 = implT r1 r2 Impl+{-# INLINE implAllR #-}++-- | Transform a clause of the form: @Equiv@ 'CoreExpr' 'CoreExpr'+equivT :: (ExtendPath c Crumb, Monad m) => Transform c m CoreExpr a1 -> Transform c m CoreExpr a2 -> (a1 -> a2 -> b) -> Transform c m Clause b+equivT t1 t2 f = transform $ \ c -> \case+                                     Equiv e1 e2 -> f <$> applyT t1 (c @@ Eq_Lhs) e1 <*> applyT t2 (c @@ Eq_Rhs) e2+                                     _           -> fail "not an equivalence."+{-# INLINE equivT #-}++-- | Rewrite all children of a clause of the form: : @Equiv@ 'CoreExpr' 'CoreExpr'+equivAllR :: (ExtendPath c Crumb, Monad m) => Rewrite c m CoreExpr -> Rewrite c m CoreExpr -> Rewrite c m Clause+equivAllR r1 r2 = equivT r1 r2 Equiv+{-# INLINE equivAllR #-}+ ---------------------------------------------------------------------++-- | Transform a quantifier of the form: @Quantified@ 'Clause'+quantifiedT :: (ExtendPath c Crumb, AddBindings c, ReadPath c Crumb, Monad m) => Transform c m [CoreBndr] a1 -> Transform c m Clause a2 -> (a1 -> a2 -> b) -> Transform c m Quantified b+quantifiedT t1 t2 f = transform $ \ c (Quantified bs cl) -> let c' = foldl (flip addLambdaBinding) c bs+                                                             in f <$> applyT t1 c bs <*> applyT t2 (c' @@ Forall_Body) cl+{-# INLINE quantifiedT #-}++-- | Rewrite the clause of a quantifier of the form: @Quantified@ 'Clause'+quantifiedR :: (ExtendPath c Crumb, AddBindings c, ReadPath c Crumb, Monad m) => Rewrite c m [CoreBndr] -> Rewrite c m Clause -> Rewrite c m Quantified+quantifiedR r1 r2 = quantifiedT r1 r2 Quantified+{-# INLINE quantifiedR #-}+ ---------------------------------------------------------------------  instance HasDynFlags m => HasDynFlags (Transform c m a) where     getDynFlags = constT getDynFlags++---------------------------------------------------------------------
− src/HERMIT/Kure/SumTypes.hs
@@ -1,453 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, FlexibleContexts, InstanceSigs, LambdaCase #-}--module HERMIT.Kure.SumTypes-  ( -- * Sum Types-    Core(..)-  , TyCo(..)-  , CoreTC(..)-  -- * Equality-  -- ** Syntactic Equality-  , coreSyntaxEq-  , tyCoSyntaxEq-  , coreTCSyntaxEq-  -- ** Alpha Equality-  , coreAlphaEq-  , tyCoAlphaEq-  , coreTCAlphaEq-  -- ** Collecting Free Variables-  , freeVarsCore-  , freeVarsTyCo-  , freeVarsCoreTC-  -- * Promotion Combinators-  -- ** Transform Promotions-  , promoteModGutsT-  , promoteProgT-  , promoteBindT-  , promoteDefT-  , promoteExprT-  , promoteAltT-  , promoteTypeT-  , promoteCoercionT-  -- ** Rewrite Promotions-  , promoteModGutsR-  , promoteProgR-  , promoteBindR-  , promoteDefR-  , promoteExprR-  , promoteAltR-  , promoteTypeR-  , promoteCoercionR-  -- ** BiRewrite Promotions-  , promoteExprBiR-  )-where--import Language.KURE.Transform-import Language.KURE.Injection-import Language.KURE.BiTransform--import HERMIT.Core-import HERMIT.GHC--------------------------------------------------------------------------- | Core is a sum type for use by KURE.  Core = ModGuts + CoreProg + CoreBind + CoreDef + CoreExpr + CoreAlt-data Core = GutsCore  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.---- | TyCo is a sum type for use by KURE.  TyCo = Type + Coercion-data TyCo = TypeCore Type                -- ^ A type.-          | CoercionCore Coercion        -- ^ A coercion.---- | CoreTC is a sum type for use by KURE.  CoreTC = Core + TyCo-data CoreTC = Core Core-            | TyCo TyCo--------------------------------------------------------------------------- | Alpha equality of 'Core' fragments.-coreAlphaEq :: Core -> Core -> Bool-coreAlphaEq (GutsCore g1) (GutsCore g2) = progAlphaEq (bindsToProg $ mg_binds g1) (bindsToProg $ mg_binds g2)-coreAlphaEq (ProgCore p1) (ProgCore p2) = progAlphaEq p1 p2-coreAlphaEq (BindCore b1) (BindCore b2) = bindAlphaEq b1 b2-coreAlphaEq (DefCore d1)  (DefCore d2)  = defAlphaEq d1 d2-coreAlphaEq (ExprCore e1) (ExprCore e2) = exprAlphaEq e1 e2-coreAlphaEq (AltCore a1)  (AltCore a2)  = altAlphaEq a1 a2-coreAlphaEq _             _             = False---- | Alpha equality of 'TyCo' fragments.-tyCoAlphaEq :: TyCo -> TyCo -> Bool-tyCoAlphaEq (TypeCore ty1)     (TypeCore ty2)     = typeAlphaEq ty1 ty2-tyCoAlphaEq (CoercionCore co1) (CoercionCore co2) = coercionAlphaEq co1 co2-tyCoAlphaEq _                  _                  = False---- | Alpha equality of 'CoreTC' fragments.-coreTCAlphaEq :: CoreTC -> CoreTC -> Bool-coreTCAlphaEq (Core c1)  (Core c2)  = coreAlphaEq c1 c2-coreTCAlphaEq (TyCo tc1) (TyCo tc2) = tyCoAlphaEq tc1 tc2-coreTCAlphaEq _          _          = False--------------------------------------------------------------------------- | Syntactic equality of 'Core' fragments.-coreSyntaxEq :: Core -> Core -> Bool-coreSyntaxEq (GutsCore g1) (GutsCore g2) = all2 bindSyntaxEq (mg_binds g1) (mg_binds g2)-coreSyntaxEq (ProgCore p1) (ProgCore p2) = progSyntaxEq p1 p2-coreSyntaxEq (BindCore b1) (BindCore b2) = bindSyntaxEq b1 b2-coreSyntaxEq (DefCore d1)  (DefCore d2)  = defSyntaxEq d1 d2-coreSyntaxEq (ExprCore e1) (ExprCore e2) = exprSyntaxEq e1 e2-coreSyntaxEq (AltCore a1)  (AltCore a2)  = altSyntaxEq a1 a2-coreSyntaxEq _             _             = False---- | Syntactic equality of 'TyCo' fragments.-tyCoSyntaxEq :: TyCo -> TyCo -> Bool-tyCoSyntaxEq (TypeCore ty1)     (TypeCore ty2)     = typeSyntaxEq ty1 ty2-tyCoSyntaxEq (CoercionCore co1) (CoercionCore co2) = coercionSyntaxEq co1 co2-tyCoSyntaxEq _                  _                  = False---- | Syntactic equality of 'CoreTC' fragments.-coreTCSyntaxEq :: CoreTC -> CoreTC -> Bool-coreTCSyntaxEq (Core c1)  (Core c2)  = coreSyntaxEq c1 c2-coreTCSyntaxEq (TyCo tc1) (TyCo tc2) = tyCoSyntaxEq tc1 tc2-coreTCSyntaxEq _          _          = False--------------------------------------------------------------------------- | Find all free variables in a 'Core' node.-freeVarsCore :: Core -> VarSet-freeVarsCore = \case-                  GutsCore g -> freeVarsProg (bindsToProg $ mg_binds g)-                  ProgCore p -> freeVarsProg p-                  BindCore b -> freeVarsBind b-                  DefCore d  -> freeVarsDef d-                  ExprCore e -> freeVarsExpr e-                  AltCore a  -> freeVarsAlt a---- | Find all free variables in a 'TyCo' node.-freeVarsTyCo :: TyCo -> VarSet-freeVarsTyCo = \case-                  TypeCore ty     -> tyVarsOfType ty-                  CoercionCore co -> tyCoVarsOfCo co---- | Find all free variables in a 'CoreTC' node.-freeVarsCoreTC :: CoreTC -> VarSet-freeVarsCoreTC = \case-                    TyCo tyco -> freeVarsTyCo tyco-                    Core core -> freeVarsCore core-------------------------------------------------------------------------instance Injection ModGuts Core where--  inject :: ModGuts -> Core-  inject = GutsCore-  {-# INLINE inject #-}--  project :: Core -> Maybe ModGuts-  project (GutsCore guts) = Just guts-  project _               = Nothing-  {-# INLINE project #-}---instance Injection CoreProg Core where--  inject :: CoreProg -> Core-  inject = ProgCore-  {-# INLINE inject #-}--  project :: Core -> Maybe CoreProg-  project (ProgCore bds) = Just bds-  project _              = Nothing-  {-# INLINE project #-}---instance Injection CoreBind Core where--  inject :: CoreBind -> Core-  inject = BindCore-  {-# INLINE inject #-}--  project :: Core -> Maybe CoreBind-  project (BindCore bnd)  = Just bnd-  project _               = Nothing-  {-# INLINE project #-}---instance Injection CoreDef Core where--  inject :: CoreDef -> Core-  inject = DefCore-  {-# INLINE inject #-}--  project :: Core -> Maybe CoreDef-  project (DefCore def) = Just def-  project _             = Nothing-  {-# INLINE project #-}---instance Injection CoreAlt Core where--  inject :: CoreAlt -> Core-  inject = AltCore-  {-# INLINE inject #-}--  project :: Core -> Maybe CoreAlt-  project (AltCore expr) = Just expr-  project _              = Nothing-  {-# INLINE project #-}---instance Injection CoreExpr Core where--  inject :: CoreExpr -> Core-  inject = ExprCore-  {-# INLINE inject #-}--  project :: Core -> Maybe CoreExpr-  project (ExprCore expr) = Just expr-  project _               = Nothing-  {-# INLINE project #-}-------------------------------------------------------------------------instance Injection Type TyCo where--  inject :: Type -> TyCo-  inject = TypeCore-  {-# INLINE inject #-}--  project :: TyCo -> Maybe Type-  project (TypeCore ty) = Just ty-  project _             = Nothing-  {-# INLINE project #-}---instance Injection Coercion TyCo where--  inject :: Coercion -> TyCo-  inject = CoercionCore-  {-# INLINE inject #-}--  project :: TyCo -> Maybe Coercion-  project (CoercionCore ty) = Just ty-  project _                 = Nothing-  {-# INLINE project #-}-------------------------------------------------------------------------instance Injection Core CoreTC where--  inject :: Core -> CoreTC-  inject = Core-  {-# INLINE inject #-}--  project :: CoreTC -> Maybe Core-  project (Core core) = Just core-  project _           = Nothing-  {-# INLINE project #-}---instance Injection TyCo CoreTC where--  inject :: TyCo -> CoreTC-  inject = TyCo-  {-# INLINE inject #-}--  project :: CoreTC -> Maybe TyCo-  project (TyCo tyCo) = Just tyCo-  project _           = Nothing-  {-# INLINE project #-}-------------------------------------------------------------------------instance Injection ModGuts CoreTC where--  inject :: ModGuts -> CoreTC-  inject = Core . GutsCore-  {-# INLINE inject #-}--  project :: CoreTC -> Maybe ModGuts-  project (Core (GutsCore guts)) = Just guts-  project _                      = Nothing-  {-# INLINE project #-}---instance Injection CoreProg CoreTC where--  inject :: CoreProg -> CoreTC-  inject = Core . ProgCore-  {-# INLINE inject #-}--  project :: CoreTC -> Maybe CoreProg-  project (Core (ProgCore bds)) = Just bds-  project _                     = Nothing-  {-# INLINE project #-}---instance Injection CoreBind CoreTC where--  inject :: CoreBind -> CoreTC-  inject = Core . BindCore-  {-# INLINE inject #-}--  project :: CoreTC -> Maybe CoreBind-  project (Core (BindCore bnd))  = Just bnd-  project _                      = Nothing-  {-# INLINE project #-}---instance Injection CoreDef CoreTC where--  inject :: CoreDef -> CoreTC-  inject = Core . DefCore-  {-# INLINE inject #-}--  project :: CoreTC -> Maybe CoreDef-  project (Core (DefCore def)) = Just def-  project _                    = Nothing-  {-# INLINE project #-}---instance Injection CoreAlt CoreTC where--  inject :: CoreAlt -> CoreTC-  inject = Core . AltCore-  {-# INLINE inject #-}--  project :: CoreTC -> Maybe CoreAlt-  project (Core (AltCore expr)) = Just expr-  project _                     = Nothing-  {-# INLINE project #-}---instance Injection CoreExpr CoreTC where--  inject :: CoreExpr -> CoreTC-  inject = Core . ExprCore-  {-# INLINE inject #-}--  project :: CoreTC -> Maybe CoreExpr-  project (Core (ExprCore expr)) = Just expr-  project _                      = Nothing-  {-# INLINE project #-}---instance Injection Type CoreTC where--  inject :: Type -> CoreTC-  inject = TyCo . TypeCore-  {-# INLINE inject #-}--  project :: CoreTC -> Maybe Type-  project (TyCo (TypeCore ty)) = Just ty-  project _                    = Nothing-  {-# INLINE project #-}---instance Injection Coercion CoreTC where--  inject :: Coercion -> CoreTC-  inject = TyCo . CoercionCore-  {-# INLINE inject #-}--  project :: CoreTC -> Maybe Coercion-  project (TyCo (CoercionCore ty)) = Just ty-  project _                        = Nothing-  {-# INLINE project #-}--------------------------------------------------------------------------- | Promote a translate on 'ModGuts'.-promoteModGutsT :: (Monad m, Injection ModGuts g) => Transform c m ModGuts b -> Transform c m g b-promoteModGutsT = promoteWithFailMsgT "This translate can only succeed at the module level."-{-# INLINE promoteModGutsT #-}---- | Promote a translate on 'CoreProg'.-promoteProgT :: (Monad m, Injection CoreProg g) => Transform c m CoreProg b -> Transform c m g b-promoteProgT = promoteWithFailMsgT "This translate can only succeed at program nodes (the top-level)."-{-# INLINE promoteProgT #-}---- | Promote a translate on 'CoreBind'.-promoteBindT :: (Monad m, Injection CoreBind g) => Transform c m CoreBind b -> Transform c m g b-promoteBindT = promoteWithFailMsgT "This translate can only succeed at binding group nodes."-{-# INLINE promoteBindT #-}---- | Promote a translate on 'CoreDef'.-promoteDefT :: (Monad m, Injection CoreDef g) => Transform c m CoreDef b -> Transform c m g b-promoteDefT = promoteWithFailMsgT "This translate can only succeed at recursive definition nodes."-{-# INLINE promoteDefT #-}---- | Promote a translate on 'CoreAlt'.-promoteAltT :: (Monad m, Injection CoreAlt g) => Transform c m CoreAlt b -> Transform c m g b-promoteAltT = promoteWithFailMsgT "This translate can only succeed at case alternative nodes."-{-# INLINE promoteAltT #-}---- | Promote a translate on 'CoreExpr'.-promoteExprT :: (Monad m, Injection CoreExpr g) => Transform c m CoreExpr b -> Transform c m g b-promoteExprT = promoteWithFailMsgT "This translate can only succeed at expression nodes."-{-# INLINE promoteExprT #-}---- | Promote a translate on 'Type'.-promoteTypeT :: (Monad m, Injection Type g) => Transform c m Type b -> Transform c m g b-promoteTypeT = promoteWithFailMsgT "This translate can only succeed at type nodes."-{-# INLINE promoteTypeT #-}---- | Promote a translate on 'Coercion'.-promoteCoercionT :: (Monad m, Injection Coercion g) => Transform c m Coercion b -> Transform c m g b-promoteCoercionT = promoteWithFailMsgT "This translate can only succeed at coercion nodes."-{-# INLINE promoteCoercionT #-}--------------------------------------------------------------------------- | Promote a rewrite on 'ModGuts'.-promoteModGutsR :: (Monad m, Injection ModGuts g) => Rewrite c m ModGuts -> Rewrite c m g-promoteModGutsR = promoteWithFailMsgR "This rewrite can only succeed at the module level."-{-# INLINE promoteModGutsR #-}---- | Promote a rewrite on 'CoreProg'.-promoteProgR :: (Monad m, Injection CoreProg g) => Rewrite c m CoreProg -> Rewrite c m g-promoteProgR = promoteWithFailMsgR "This rewrite can only succeed at program nodes (the top-level)."-{-# INLINE promoteProgR #-}---- | Promote a rewrite on 'CoreBind'.-promoteBindR :: (Monad m, Injection CoreBind g) => Rewrite c m CoreBind -> Rewrite c m g-promoteBindR = promoteWithFailMsgR "This rewrite can only succeed at binding group nodes."-{-# INLINE promoteBindR #-}---- | Promote a rewrite on 'CoreDef'.-promoteDefR :: (Monad m, Injection CoreDef g) => Rewrite c m CoreDef -> Rewrite c m g-promoteDefR = promoteWithFailMsgR "This rewrite can only succeed at recursive definition nodes."-{-# INLINE promoteDefR #-}---- | Promote a rewrite on 'CoreAlt'.-promoteAltR :: (Monad m, Injection CoreAlt g) => Rewrite c m CoreAlt -> Rewrite c m g-promoteAltR = promoteWithFailMsgR "This rewrite can only succeed at case alternative nodes."-{-# INLINE promoteAltR #-}---- | Promote a rewrite on 'CoreExpr'.-promoteExprR :: (Monad m, Injection CoreExpr g) => Rewrite c m CoreExpr -> Rewrite c m g-promoteExprR = promoteWithFailMsgR "This rewrite can only succeed at expression nodes."-{-# INLINE promoteExprR #-}---- | Promote a rewrite on 'Type'.-promoteTypeR :: (Monad m, Injection Type g) => Rewrite c m Type -> Rewrite c m g-promoteTypeR = promoteWithFailMsgR "This rewrite can only succeed at type nodes."-{-# INLINE promoteTypeR #-}---- | Promote a rewrite on 'Coercion'.-promoteCoercionR :: (Monad m, Injection Coercion g) => Rewrite c m Coercion -> Rewrite c m g-promoteCoercionR = promoteWithFailMsgR "This rewrite can only succeed at coercion nodes."-{-# INLINE promoteCoercionR #-}--------------------------------------------------------------------------- | Promote a bidirectional rewrite on 'CoreExpr'.-promoteExprBiR :: (Monad m, Injection CoreExpr g) => BiRewrite c m CoreExpr -> BiRewrite c m g-promoteExprBiR b = bidirectional (promoteExprR $ forwardT b) (promoteExprR $ backwardT b)-{-# INLINE promoteExprBiR #-}-----------------------------------------------------------------------
+ src/HERMIT/Kure/Universes.hs view
@@ -0,0 +1,813 @@+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE InstanceSigs #-}+{-# LANGUAGE LambdaCase #-}++module HERMIT.Kure.Universes+    ( -- * Universes+      Core(..)+    , TyCo(..)+    , LCore(..)+    , LCoreTC(..)+    , CoreTC(..)+      -- * Equality+      -- ** Syntactic Equality+    , coreSyntaxEq+    , tyCoSyntaxEq+    , coreTCSyntaxEq+    , lcoreSyntaxEq+    , lcoreTCSyntaxEq+      -- ** Alpha Equality+    , coreAlphaEq+    , tyCoAlphaEq+    , coreTCAlphaEq+      -- ** Collecting Free Variables+    , freeVarsCore+    , freeVarsTyCo+    , freeVarsCoreTC+      -- * Promotion Combinators+      -- ** Transform Promotions+    , promoteModGutsT+    , promoteProgT+    , promoteBindT+    , promoteDefT+    , promoteExprT+    , promoteAltT+    , promoteTypeT+    , promoteCoercionT+    , promoteQuantifiedT+    , promoteClauseT+    , promoteCoreT+    , promoteLCoreT+    , promoteCoreTCT+      -- ** Rewrite Promotions+    , promoteModGutsR+    , promoteProgR+    , promoteBindR+    , promoteDefR+    , promoteExprR+    , promoteAltR+    , promoteTypeR+    , promoteCoercionR+    , promoteQuantifiedR+    , promoteClauseR+    , promoteCoreR+    , promoteLCoreR+    , promoteCoreTCR+      -- ** BiRewrite Promotions+    , promoteExprBiR+    ) where++import Language.KURE.Transform+import Language.KURE.Injection+import Language.KURE.BiTransform++import HERMIT.Core+import HERMIT.GHC+import HERMIT.Lemma++---------------------------------------------------------------------++-- | Core is a KURE universe for traversing GHC Core, excluding types and coercions.+--   Core = ModGuts + CoreProg + CoreBind + CoreDef + CoreExpr + CoreAlt+data Core = GutsCore  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.++-- | TyCo is a KURE universe for traversing types and coercions.+--   TyCo = Type + Coercion+data TyCo = TypeCore Type                -- ^ A type.+          | CoercionCore Coercion        -- ^ A coercion.++-- | Core is a KURE universe for traversing GHC Core, including types and coercions.+--   CoreTC = Core + TyCo+data CoreTC = Core Core+            | TyCo TyCo++-- | LCore is a KURE universe for traversing HERMIT lemmas and the Core expressions they contain.+--   Types and coercions are not traversed (for that, use 'LCoreTC').+--   LCore = Core + Quantified + Clause+data LCore = LQuantified Quantified+           | LClause     Clause+           | LCore       Core++-- | LCoreTC is a KURE universe for traversing HERMIT lemmas and the Core expressions they contain.+--   Unlike 'LCore', types and coercions are also traversed.+--   LCore = LCore + TyCo+data LCoreTC = LTCCore LCore+             | LTCTyCo TyCo++---------------------------------------------------------------------++-- | Alpha equality of 'Core' fragments.+coreAlphaEq :: Core -> Core -> Bool+coreAlphaEq (GutsCore g1) (GutsCore g2) = progAlphaEq (bindsToProg $ mg_binds g1) (bindsToProg $ mg_binds g2)+coreAlphaEq (ProgCore p1) (ProgCore p2) = progAlphaEq p1 p2+coreAlphaEq (BindCore b1) (BindCore b2) = bindAlphaEq b1 b2+coreAlphaEq (DefCore d1)  (DefCore d2)  = defAlphaEq d1 d2+coreAlphaEq (ExprCore e1) (ExprCore e2) = exprAlphaEq e1 e2+coreAlphaEq (AltCore a1)  (AltCore a2)  = altAlphaEq a1 a2+coreAlphaEq _             _             = False++-- | Alpha equality of 'TyCo' fragments.+tyCoAlphaEq :: TyCo -> TyCo -> Bool+tyCoAlphaEq (TypeCore ty1)     (TypeCore ty2)     = typeAlphaEq ty1 ty2+tyCoAlphaEq (CoercionCore co1) (CoercionCore co2) = coercionAlphaEq co1 co2+tyCoAlphaEq _                  _                  = False++-- | Alpha equality of 'CoreTC' fragments.+coreTCAlphaEq :: CoreTC -> CoreTC -> Bool+coreTCAlphaEq (Core c1)  (Core c2)  = coreAlphaEq c1 c2+coreTCAlphaEq (TyCo tc1) (TyCo tc2) = tyCoAlphaEq tc1 tc2+coreTCAlphaEq _          _          = False++-- TODO: alpha equality for LCore and LCoreTC++---------------------------------------------------------------------++-- | Syntactic equality of 'Core' fragments.+coreSyntaxEq :: Core -> Core -> Bool+coreSyntaxEq (GutsCore g1) (GutsCore g2) = all2 bindSyntaxEq (mg_binds g1) (mg_binds g2)+coreSyntaxEq (ProgCore p1) (ProgCore p2) = progSyntaxEq p1 p2+coreSyntaxEq (BindCore b1) (BindCore b2) = bindSyntaxEq b1 b2+coreSyntaxEq (DefCore d1)  (DefCore d2)  = defSyntaxEq d1 d2+coreSyntaxEq (ExprCore e1) (ExprCore e2) = exprSyntaxEq e1 e2+coreSyntaxEq (AltCore a1)  (AltCore a2)  = altSyntaxEq a1 a2+coreSyntaxEq _             _             = False++-- | Syntactic equality of 'TyCo' fragments.+tyCoSyntaxEq :: TyCo -> TyCo -> Bool+tyCoSyntaxEq (TypeCore ty1)     (TypeCore ty2)     = typeSyntaxEq ty1 ty2+tyCoSyntaxEq (CoercionCore co1) (CoercionCore co2) = coercionSyntaxEq co1 co2+tyCoSyntaxEq _                  _                  = False++-- | Syntactic equality of 'CoreTC' fragments.+coreTCSyntaxEq :: CoreTC -> CoreTC -> Bool+coreTCSyntaxEq (Core c1)  (Core c2)  = coreSyntaxEq c1 c2+coreTCSyntaxEq (TyCo tc1) (TyCo tc2) = tyCoSyntaxEq tc1 tc2+coreTCSyntaxEq _          _          = False++-- | Syntactic equality of 'LCore' fragments.+lcoreSyntaxEq :: LCore -> LCore -> Bool+lcoreSyntaxEq (LCore c1)       (LCore c2)       = coreSyntaxEq c1 c2+lcoreSyntaxEq (LClause cl1)    (LClause cl2)    = clauseSyntaxEq cl1 cl2+lcoreSyntaxEq (LQuantified q1) (LQuantified q2) = quantifiedSyntaxEq q1 q2+lcoreSyntaxEq _                _                = False++-- | Syntactic equality of 'LCoreTC' fragments.+lcoreTCSyntaxEq :: LCoreTC -> LCoreTC -> Bool+lcoreTCSyntaxEq (LTCCore lc1) (LTCCore lc2) = lcoreSyntaxEq lc1 lc2+lcoreTCSyntaxEq (LTCTyCo tc1) (LTCTyCo tc2) = tyCoSyntaxEq tc1 tc2+lcoreTCSyntaxEq _             _             = False++---------------------------------------------------------------------++-- | Find all free variables in a 'Core' node.+freeVarsCore :: Core -> VarSet+freeVarsCore = \case+                  GutsCore g -> freeVarsProg (bindsToProg $ mg_binds g)+                  ProgCore p -> freeVarsProg p+                  BindCore b -> freeVarsBind b+                  DefCore d  -> freeVarsDef d+                  ExprCore e -> freeVarsExpr e+                  AltCore a  -> freeVarsAlt a++-- | Find all free variables in a 'TyCo' node.+freeVarsTyCo :: TyCo -> VarSet+freeVarsTyCo = \case+                  TypeCore ty     -> tyVarsOfType ty+                  CoercionCore co -> tyCoVarsOfCo co++-- | Find all free variables in a 'CoreTC' node.+freeVarsCoreTC :: CoreTC -> VarSet+freeVarsCoreTC = \case+                    TyCo tyco -> freeVarsTyCo tyco+                    Core core -> freeVarsCore core++---------------------------------------------------------------------++instance Injection ModGuts Core where++  inject :: ModGuts -> Core+  inject = GutsCore+  {-# INLINE inject #-}++  project :: Core -> Maybe ModGuts+  project (GutsCore guts) = Just guts+  project _               = Nothing+  {-# INLINE project #-}+++instance Injection CoreProg Core where++  inject :: CoreProg -> Core+  inject = ProgCore+  {-# INLINE inject #-}++  project :: Core -> Maybe CoreProg+  project (ProgCore bds) = Just bds+  project _              = Nothing+  {-# INLINE project #-}+++instance Injection CoreBind Core where++  inject :: CoreBind -> Core+  inject = BindCore+  {-# INLINE inject #-}++  project :: Core -> Maybe CoreBind+  project (BindCore bnd)  = Just bnd+  project _               = Nothing+  {-# INLINE project #-}+++instance Injection CoreDef Core where++  inject :: CoreDef -> Core+  inject = DefCore+  {-# INLINE inject #-}++  project :: Core -> Maybe CoreDef+  project (DefCore def) = Just def+  project _             = Nothing+  {-# INLINE project #-}+++instance Injection CoreAlt Core where++  inject :: CoreAlt -> Core+  inject = AltCore+  {-# INLINE inject #-}++  project :: Core -> Maybe CoreAlt+  project (AltCore expr) = Just expr+  project _              = Nothing+  {-# INLINE project #-}+++instance Injection CoreExpr Core where++  inject :: CoreExpr -> Core+  inject = ExprCore+  {-# INLINE inject #-}++  project :: Core -> Maybe CoreExpr+  project (ExprCore expr) = Just expr+  project _               = Nothing+  {-# INLINE project #-}++---------------------------------------------------------------------++instance Injection Type TyCo where++  inject :: Type -> TyCo+  inject = TypeCore+  {-# INLINE inject #-}++  project :: TyCo -> Maybe Type+  project (TypeCore ty) = Just ty+  project _             = Nothing+  {-# INLINE project #-}+++instance Injection Coercion TyCo where++  inject :: Coercion -> TyCo+  inject = CoercionCore+  {-# INLINE inject #-}++  project :: TyCo -> Maybe Coercion+  project (CoercionCore ty) = Just ty+  project _                 = Nothing+  {-# INLINE project #-}++---------------------------------------------------------------------++instance Injection Core LCore where++  inject :: Core -> LCore+  inject = LCore+  {-# INLINE inject #-}++  project :: LCore -> Maybe Core+  project (LCore c) = Just c+  project _         = Nothing+  {-# INLINE project #-}+++instance Injection Clause LCore where++  inject :: Clause -> LCore+  inject = LClause+  {-# INLINE inject #-}++  project :: LCore -> Maybe Clause+  project (LClause cl) = Just cl+  project _            = Nothing+  {-# INLINE project #-}+++instance Injection Quantified LCore where++  inject :: Quantified -> LCore+  inject = LQuantified+  {-# INLINE inject #-}++  project :: LCore -> Maybe Quantified+  project (LQuantified q) = Just q+  project _               = Nothing+  {-# INLINE project #-}++---------------------------------------------------------------------++instance Injection LCore LCoreTC where++  inject :: LCore -> LCoreTC+  inject = LTCCore+  {-# INLINE inject #-}++  project :: LCoreTC -> Maybe LCore+  project (LTCCore core) = Just core+  project _              = Nothing+  {-# INLINE project #-}+++instance Injection TyCo LCoreTC where++  inject :: TyCo -> LCoreTC+  inject = LTCTyCo+  {-# INLINE inject #-}++  project :: LCoreTC -> Maybe TyCo+  project (LTCTyCo tyCo) = Just tyCo+  project _              = Nothing+  {-# INLINE project #-}++---------------------------------------------------------------------++instance Injection ModGuts LCore where++  inject :: ModGuts -> LCore+  inject = LCore . inject+  {-# INLINE inject #-}++  project :: LCore -> Maybe ModGuts+  project (LCore c) = project c+  project _         = Nothing+  {-# INLINE project #-}++instance Injection CoreProg LCore where++  inject :: CoreProg -> LCore+  inject = LCore . inject+  {-# INLINE inject #-}++  project :: LCore -> Maybe CoreProg+  project (LCore c) = project c+  project _         = Nothing+  {-# INLINE project #-}++instance Injection CoreExpr LCore where+  inject :: CoreExpr -> LCore+  inject = LCore . inject+  {-# INLINE inject #-}++  project :: LCore -> Maybe CoreExpr+  project (LCore c) = project c+  project _         = Nothing+  {-# INLINE project #-}++instance Injection CoreBind LCore where+  inject :: CoreBind -> LCore+  inject = LCore . inject+  {-# INLINE inject #-}++  project :: LCore -> Maybe CoreBind+  project (LCore c) = project c+  project _         = Nothing+  {-# INLINE project #-}++instance Injection CoreDef LCore where+  inject :: CoreDef -> LCore+  inject = LCore . inject+  {-# INLINE inject #-}++  project :: LCore -> Maybe CoreDef+  project (LCore c) = project c+  project _         = Nothing+  {-# INLINE project #-}++instance Injection CoreAlt LCore where+  inject :: CoreAlt -> LCore+  inject = LCore . inject+  {-# INLINE inject #-}++  project :: LCore -> Maybe CoreAlt+  project (LCore c) = project c+  project _         = Nothing+  {-# INLINE project #-}++---------------------------------------------------------------------++instance Injection Quantified LCoreTC where++  inject :: Quantified -> LCoreTC+  inject = LTCCore . inject+  {-# INLINE inject #-}++  project :: LCoreTC -> Maybe Quantified+  project (LTCCore lc) = project lc+  project _            = Nothing+  {-# INLINE project #-}++instance Injection Clause LCoreTC where++  inject :: Clause -> LCoreTC+  inject = LTCCore . inject+  {-# INLINE inject #-}++  project :: LCoreTC -> Maybe Clause+  project (LTCCore lc) = project lc+  project _            = Nothing+  {-# INLINE project #-}++instance Injection Core LCoreTC where++  inject :: Core -> LCoreTC+  inject = LTCCore . inject+  {-# INLINE inject #-}++  project :: LCoreTC -> Maybe Core+  project (LTCCore lc) = project lc+  project _            = Nothing+  {-# INLINE project #-}++---------------------------------------------------------------------++instance Injection ModGuts LCoreTC where++  inject :: ModGuts -> LCoreTC+  inject = LTCCore . inject+  {-# INLINE inject #-}++  project :: LCoreTC -> Maybe ModGuts+  project (LTCCore lc) = project lc+  project _            = Nothing+  {-# INLINE project #-}++instance Injection CoreProg LCoreTC where++  inject :: CoreProg -> LCoreTC+  inject = LTCCore . inject+  {-# INLINE inject #-}++  project :: LCoreTC -> Maybe CoreProg+  project (LTCCore lc) = project lc+  project _            = Nothing+  {-# INLINE project #-}++instance Injection CoreExpr LCoreTC where+  inject :: CoreExpr -> LCoreTC+  inject = LTCCore . inject+  {-# INLINE inject #-}++  project :: LCoreTC -> Maybe CoreExpr+  project (LTCCore lc) = project lc+  project _            = Nothing+  {-# INLINE project #-}++instance Injection CoreBind LCoreTC where+  inject :: CoreBind -> LCoreTC+  inject = LTCCore . inject+  {-# INLINE inject #-}++  project :: LCoreTC -> Maybe CoreBind+  project (LTCCore lc) = project lc+  project _            = Nothing+  {-# INLINE project #-}++instance Injection CoreDef LCoreTC where+  inject :: CoreDef -> LCoreTC+  inject = LTCCore . inject+  {-# INLINE inject #-}++  project :: LCoreTC -> Maybe CoreDef+  project (LTCCore lc) = project lc+  project _            = Nothing+  {-# INLINE project #-}++instance Injection CoreAlt LCoreTC where+  inject :: CoreAlt -> LCoreTC+  inject = LTCCore . inject+  {-# INLINE inject #-}++  project :: LCoreTC -> Maybe CoreAlt+  project (LTCCore lc) = project lc+  project _            = Nothing+  {-# INLINE project #-}++instance Injection Type LCoreTC where+  inject :: Type -> LCoreTC+  inject = LTCTyCo . inject+  {-# INLINE inject #-}++  project :: LCoreTC -> Maybe Type+  project (LTCTyCo tc) = project tc+  project _            = Nothing+  {-# INLINE project #-}++instance Injection Coercion LCoreTC where+  inject :: Coercion -> LCoreTC+  inject = LTCTyCo . inject+  {-# INLINE inject #-}++  project :: LCoreTC -> Maybe Coercion+  project (LTCTyCo tc) = project tc+  project _            = Nothing+  {-# INLINE project #-}++---------------------------------------------------------------------++instance Injection Core CoreTC where++  inject :: Core -> CoreTC+  inject = Core+  {-# INLINE inject #-}++  project :: CoreTC -> Maybe Core+  project (Core core) = Just core+  project _           = Nothing+  {-# INLINE project #-}+++instance Injection TyCo CoreTC where++  inject :: TyCo -> CoreTC+  inject = TyCo+  {-# INLINE inject #-}++  project :: CoreTC -> Maybe TyCo+  project (TyCo tyCo) = Just tyCo+  project _           = Nothing+  {-# INLINE project #-}++---------------------------------------------------------------------++instance Injection ModGuts CoreTC where++  inject :: ModGuts -> CoreTC+  inject = Core . GutsCore+  {-# INLINE inject #-}++  project :: CoreTC -> Maybe ModGuts+  project (Core (GutsCore guts)) = Just guts+  project _                      = Nothing+  {-# INLINE project #-}+++instance Injection CoreProg CoreTC where++  inject :: CoreProg -> CoreTC+  inject = Core . ProgCore+  {-# INLINE inject #-}++  project :: CoreTC -> Maybe CoreProg+  project (Core (ProgCore bds)) = Just bds+  project _                     = Nothing+  {-# INLINE project #-}+++instance Injection CoreBind CoreTC where++  inject :: CoreBind -> CoreTC+  inject = Core . BindCore+  {-# INLINE inject #-}++  project :: CoreTC -> Maybe CoreBind+  project (Core (BindCore bnd))  = Just bnd+  project _                      = Nothing+  {-# INLINE project #-}+++instance Injection CoreDef CoreTC where++  inject :: CoreDef -> CoreTC+  inject = Core . DefCore+  {-# INLINE inject #-}++  project :: CoreTC -> Maybe CoreDef+  project (Core (DefCore def)) = Just def+  project _                    = Nothing+  {-# INLINE project #-}+++instance Injection CoreAlt CoreTC where++  inject :: CoreAlt -> CoreTC+  inject = Core . AltCore+  {-# INLINE inject #-}++  project :: CoreTC -> Maybe CoreAlt+  project (Core (AltCore expr)) = Just expr+  project _                     = Nothing+  {-# INLINE project #-}+++instance Injection CoreExpr CoreTC where++  inject :: CoreExpr -> CoreTC+  inject = Core . ExprCore+  {-# INLINE inject #-}++  project :: CoreTC -> Maybe CoreExpr+  project (Core (ExprCore expr)) = Just expr+  project _                      = Nothing+  {-# INLINE project #-}+++instance Injection Type CoreTC where++  inject :: Type -> CoreTC+  inject = TyCo . TypeCore+  {-# INLINE inject #-}++  project :: CoreTC -> Maybe Type+  project (TyCo (TypeCore ty)) = Just ty+  project _                    = Nothing+  {-# INLINE project #-}+++instance Injection Coercion CoreTC where++  inject :: Coercion -> CoreTC+  inject = TyCo . CoercionCore+  {-# INLINE inject #-}++  project :: CoreTC -> Maybe Coercion+  project (TyCo (CoercionCore ty)) = Just ty+  project _                        = Nothing+  {-# INLINE project #-}++---------------------------------------------------------------------++-- This one's a bit unusual, as it doesn't directly follow the structure of the sum types.++instance Injection CoreTC LCoreTC where++  inject :: CoreTC -> LCoreTC+  inject (Core c)  = LTCCore (LCore c)+  inject (TyCo tc) = LTCTyCo tc+  {-# INLINE inject #-}++  project :: LCoreTC -> Maybe CoreTC+  project (LTCCore c)  = Core `fmap` project c+  project (LTCTyCo tc) = Just (TyCo tc)+  {-# INLINE project #-}++---------------------------------------------------------------------++-- | Promote a translate on 'ModGuts'.+promoteModGutsT :: (Monad m, Injection ModGuts g) => Transform c m ModGuts b -> Transform c m g b+promoteModGutsT = promoteWithFailMsgT "This translate can only succeed at the module level."+{-# INLINE promoteModGutsT #-}++-- | Promote a translate on 'CoreProg'.+promoteProgT :: (Monad m, Injection CoreProg g) => Transform c m CoreProg b -> Transform c m g b+promoteProgT = promoteWithFailMsgT "This translate can only succeed at program nodes (the top-level)."+{-# INLINE promoteProgT #-}++-- | Promote a translate on 'CoreBind'.+promoteBindT :: (Monad m, Injection CoreBind g) => Transform c m CoreBind b -> Transform c m g b+promoteBindT = promoteWithFailMsgT "This translate can only succeed at binding group nodes."+{-# INLINE promoteBindT #-}++-- | Promote a translate on 'CoreDef'.+promoteDefT :: (Monad m, Injection CoreDef g) => Transform c m CoreDef b -> Transform c m g b+promoteDefT = promoteWithFailMsgT "This translate can only succeed at recursive definition nodes."+{-# INLINE promoteDefT #-}++-- | Promote a translate on 'CoreAlt'.+promoteAltT :: (Monad m, Injection CoreAlt g) => Transform c m CoreAlt b -> Transform c m g b+promoteAltT = promoteWithFailMsgT "This translate can only succeed at case alternative nodes."+{-# INLINE promoteAltT #-}++-- | Promote a translate on 'CoreExpr'.+promoteExprT :: (Monad m, Injection CoreExpr g) => Transform c m CoreExpr b -> Transform c m g b+promoteExprT = promoteWithFailMsgT "This translate can only succeed at expression nodes."+{-# INLINE promoteExprT #-}++-- | Promote a translate on 'Type'.+promoteTypeT :: (Monad m, Injection Type g) => Transform c m Type b -> Transform c m g b+promoteTypeT = promoteWithFailMsgT "This translate can only succeed at type nodes."+{-# INLINE promoteTypeT #-}++-- | Promote a translate on 'Coercion'.+promoteCoercionT :: (Monad m, Injection Coercion g) => Transform c m Coercion b -> Transform c m g b+promoteCoercionT = promoteWithFailMsgT "This translate can only succeed at coercion nodes."+{-# INLINE promoteCoercionT #-}++-- | Promote a translate on 'Quantified'.+promoteQuantifiedT :: (Monad m, Injection Quantified g) => Transform c m Quantified b -> Transform c m g b+promoteQuantifiedT = promoteWithFailMsgT "This translate can only succeed at quantified nodes."+{-# INLINE promoteQuantifiedT #-}++-- | Promote a translate on 'Clause'.+promoteClauseT :: (Monad m, Injection Clause g) => Transform c m Clause b -> Transform c m g b+promoteClauseT = promoteWithFailMsgT "This translate can only succeed at clause nodes."+{-# INLINE promoteClauseT #-}++-- | Promote a translate on 'Core'.+promoteCoreT :: (Monad m, Injection Core g) => Transform c m Core b -> Transform c m g b+promoteCoreT = promoteWithFailMsgT "This translate can only succeed at core nodes."+{-# INLINE promoteCoreT #-}++-- | Promote a translate on 'LCore'.+promoteLCoreT :: (Monad m, Injection LCore g) => Transform c m LCore b -> Transform c m g b+promoteLCoreT = promoteWithFailMsgT "This translate can only succeed at lemma or core nodes."+{-# INLINE promoteLCoreT #-}++-- | Promote a translate on 'CoreTC'.+promoteCoreTCT :: (Monad m, Injection CoreTC g) => Transform c m CoreTC b -> Transform c m g b+promoteCoreTCT = promoteWithFailMsgT "This translate can only succeed at core nodes."+{-# INLINE promoteCoreTCT #-}++---------------------------------------------------------------------++-- | Promote a rewrite on 'ModGuts'.+promoteModGutsR :: (Monad m, Injection ModGuts g) => Rewrite c m ModGuts -> Rewrite c m g+promoteModGutsR = promoteWithFailMsgR "This rewrite can only succeed at the module level."+{-# INLINE promoteModGutsR #-}++-- | Promote a rewrite on 'CoreProg'.+promoteProgR :: (Monad m, Injection CoreProg g) => Rewrite c m CoreProg -> Rewrite c m g+promoteProgR = promoteWithFailMsgR "This rewrite can only succeed at program nodes (the top-level)."+{-# INLINE promoteProgR #-}++-- | Promote a rewrite on 'CoreBind'.+promoteBindR :: (Monad m, Injection CoreBind g) => Rewrite c m CoreBind -> Rewrite c m g+promoteBindR = promoteWithFailMsgR "This rewrite can only succeed at binding group nodes."+{-# INLINE promoteBindR #-}++-- | Promote a rewrite on 'CoreDef'.+promoteDefR :: (Monad m, Injection CoreDef g) => Rewrite c m CoreDef -> Rewrite c m g+promoteDefR = promoteWithFailMsgR "This rewrite can only succeed at recursive definition nodes."+{-# INLINE promoteDefR #-}++-- | Promote a rewrite on 'CoreAlt'.+promoteAltR :: (Monad m, Injection CoreAlt g) => Rewrite c m CoreAlt -> Rewrite c m g+promoteAltR = promoteWithFailMsgR "This rewrite can only succeed at case alternative nodes."+{-# INLINE promoteAltR #-}++-- | Promote a rewrite on 'CoreExpr'.+promoteExprR :: (Monad m, Injection CoreExpr g) => Rewrite c m CoreExpr -> Rewrite c m g+promoteExprR = promoteWithFailMsgR "This rewrite can only succeed at expression nodes."+{-# INLINE promoteExprR #-}++-- | Promote a rewrite on 'Type'.+promoteTypeR :: (Monad m, Injection Type g) => Rewrite c m Type -> Rewrite c m g+promoteTypeR = promoteWithFailMsgR "This rewrite can only succeed at type nodes."+{-# INLINE promoteTypeR #-}++-- | Promote a rewrite on 'Coercion'.+promoteCoercionR :: (Monad m, Injection Coercion g) => Rewrite c m Coercion -> Rewrite c m g+promoteCoercionR = promoteWithFailMsgR "This rewrite can only succeed at coercion nodes."+{-# INLINE promoteCoercionR #-}++-- | Promote a rewrite on 'Quantified'.+promoteQuantifiedR :: (Monad m, Injection Quantified g) => Rewrite c m Quantified -> Rewrite c m g+promoteQuantifiedR = promoteWithFailMsgR "This rewrite can only succeed at quantified nodes."+{-# INLINE promoteQuantifiedR #-}++-- | Promote a rewrite on 'Clause'.+promoteClauseR :: (Monad m, Injection Clause g) => Rewrite c m Clause -> Rewrite c m g+promoteClauseR = promoteWithFailMsgR "This rewrite can only succeed at quantified nodes."+{-# INLINE promoteClauseR #-}++-- | Promote a rewrite on 'Core'.+promoteCoreR :: (Monad m, Injection Core g) => Rewrite c m Core -> Rewrite c m g+promoteCoreR = promoteWithFailMsgR "This rewrite can only succeed at core nodes."+{-# INLINE promoteCoreR #-}++-- | Promote a rewrite on 'Core'.+promoteLCoreR :: (Monad m, Injection LCore g) => Rewrite c m LCore -> Rewrite c m g+promoteLCoreR = promoteWithFailMsgR "This rewrite can only succeed at lemma or core nodes."+{-# INLINE promoteLCoreR #-}++-- | Promote a rewrite on 'CoreTC'.+promoteCoreTCR :: (Monad m, Injection CoreTC g) => Rewrite c m CoreTC -> Rewrite c m g+promoteCoreTCR = promoteWithFailMsgR "This rewrite can only succeed at core nodes."+{-# INLINE promoteCoreTCR #-}++---------------------------------------------------------------------++-- | Promote a bidirectional rewrite on 'CoreExpr'.+promoteExprBiR :: (Monad m, Injection CoreExpr g) => BiRewrite c m CoreExpr -> BiRewrite c m g+promoteExprBiR = promoteWithFailMsgBiR "This rewrite can only succeed at expression nodes."+{-# INLINE promoteExprBiR #-}++---------------------------------------------------------------------
+ src/HERMIT/Lemma.hs view
@@ -0,0 +1,303 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE InstanceSigs #-}++module HERMIT.Lemma+    ( -- * Quantified+      Quantified(..)+    , mkQuantified+    , Clause(..)+    , instQuantified+    , instsQuantified+    , discardUniVars+    , freeVarsQuantified+    , clauseSyntaxEq+    , quantifiedSyntaxEq+    , substQuantified+    , substQuantifieds+    , dropBinders+    , redundantDicts+      -- * Lemmas+    , LemmaName(..)+    , Lemma(..)+    , Proven(..)+    , andP, orP+    , Used(..)+    , Lemmas+    , NamedLemma+    ) where++import Prelude hiding (lookup)++import Control.Monad++import Data.Dynamic (Typeable)+import Data.String (IsString(..))+import qualified Data.Map as M+import Data.Monoid++import HERMIT.Core+import HERMIT.GHC hiding ((<>))+import Language.KURE.MonadCatch++----------------------------------------------------------------------------++-- | Build a Quantified from a list of universally quantified binders and two expressions.+-- If the head of either expression is a lambda expression, it's binder will become a universally quantified binder+-- over both sides. It is assumed the two expressions have the same type.+--+-- Ex.    mkQuantified [] (\x. foo x) bar === forall x. foo x = bar x+--        mkQuantified [] (baz y z) (\x. foo x x) === forall x. baz y z x = foo x x+--        mkQuantified [] (\x. foo x) (\y. bar y) === forall x. foo x = bar x+mkQuantified :: [CoreBndr] -> CoreExpr -> CoreExpr -> Quantified+mkQuantified vs lhs rhs = redundantDicts $ dropBinders $ Quantified (tvs++vs++lbs++rbs) (Equiv lhs' rbody)+    where (lbs, lbody) = collectBinders lhs+          rhs' = uncurry mkCoreApps $ betaReduceAll rhs $ map varToCoreExpr lbs+          (rbs, rbody) = collectBinders rhs'+          lhs' = mkCoreApps lbody $ map varToCoreExpr rbs+          -- now quantify over the free type variables+          tvs = varSetElems+              $ filterVarSet isTyVar+              $ delVarSetList (unionVarSets $ map freeVarsExpr [lhs',rbody]) (vs++lbs++rbs)++freeVarsQuantified :: Quantified -> VarSet+freeVarsQuantified (Quantified bs cl) = delVarSetList (freeVarsClause cl) bs++freeVarsClause :: Clause -> VarSet+freeVarsClause (Conj  q1 q2) = unionVarSets $ map freeVarsQuantified [q1,q2]+freeVarsClause (Disj  q1 q2) = unionVarSets $ map freeVarsQuantified [q1,q2]+freeVarsClause (Impl  q1 q2) = unionVarSets $ map freeVarsQuantified [q1,q2]+freeVarsClause (Equiv e1 e2) = unionVarSets $ map freeVarsExpr [e1,e2]++dropBinders :: Quantified -> Quantified+dropBinders (Quantified bs cl) =+    case bs of+        []      -> Quantified [] (dropBindersClause cl)+        (b:bs') -> case dropBinders (Quantified bs' cl) of+                    q@(Quantified bs'' cl')+                        | b `elemVarSet` freeVarsQuantified q -> Quantified (b:bs'') cl'+                        | otherwise -> q++dropBindersClause :: Clause -> Clause+dropBindersClause (Conj q1 q2) = Conj (dropBinders q1) (dropBinders q2)+dropBindersClause (Disj q1 q2) = Disj (dropBinders q1) (dropBinders q2)+dropBindersClause (Impl q1 q2) = Impl (dropBinders q1) (dropBinders q2)+dropBindersClause equiv        = equiv+++-- | A name for lemmas. Use a newtype so we can tab-complete in shell.+newtype LemmaName = LemmaName String deriving (Eq, Ord, Typeable)++instance Monoid LemmaName where+    mempty = LemmaName mempty+    mappend (LemmaName n1) (LemmaName n2) = LemmaName (mappend n1 n2)++instance IsString LemmaName where fromString = LemmaName+instance Show LemmaName where show (LemmaName s) = s++-- | An equality with a proven/used status.+data Lemma = Lemma { lemmaQ :: Quantified+                   , lemmaP :: Proven     -- whether lemma has been proven+                   , lemmaU :: Used       -- whether lemma has been used+                   , lemmaT :: Bool       -- whether lemma is temporary+                   }++data Proven = Proven+            | Assumed Bool -- ^ True = assumed by user, False = assumed by library/HERMIT for good reason+            | NotProven+    deriving (Eq, Typeable)++instance Show Proven where+    show Proven = "Proven"+    show (Assumed _) = "Assumed"+    show NotProven = "Not Proven"++-- Ordering: NotProven < Assumed True < Assumed False < Proven+instance Ord Proven where+    compare :: Proven -> Proven -> Ordering+    compare Proven    Proven    = EQ+    compare (Assumed l) (Assumed r)+        | l && (not r) = LT+        | (not l) && r = GT+        | otherwise = EQ+    compare NotProven NotProven = EQ+    compare Proven    _         = GT+    compare _         Proven    = LT+    compare NotProven _         = LT+    compare _         NotProven = GT++-- When conjuncting, result is as proven as the least of the two+andP :: Proven -> Proven -> Proven+andP = min++-- When disjuncting, result is as proven as the most of the two+orP :: Proven -> Proven -> Proven+orP = max++data Used = Obligation -- ^ this MUST be proven immediately+          | UnsafeUsed -- ^ used, but can be proven later (only introduced in unsafe shell)+          | NotUsed    -- ^ not used+    deriving (Eq, Typeable)++instance Show Used where+    show Obligation = "Obligation"+    show UnsafeUsed = "Used"+    show NotUsed    = "Not Used"++data Quantified = Quantified [CoreBndr] Clause++data Clause = Conj Quantified Quantified+            | Disj Quantified Quantified+            | Impl Quantified Quantified+            | Equiv CoreExpr CoreExpr++-- | A collection of named lemmas.+type Lemmas = M.Map LemmaName Lemma++-- | A LemmaName, Lemma pair.+type NamedLemma = (LemmaName, Lemma)++------------------------------------------------------------------------------++discardUniVars :: Quantified -> Quantified+discardUniVars (Quantified _ cl) = Quantified [] cl++------------------------------------------------------------------------------++-- | Assumes Var is free in Quantified. If not, no substitution will happen, though uniques might be freshened.+substQuantified :: Var -> CoreArg -> Quantified -> Quantified+substQuantified v e = substQuantifieds [(v,e)]++substQuantifieds :: [(Var,CoreArg)] -> Quantified -> Quantified+substQuantifieds ps q = substQuantifiedSubst (extendSubstList sub ps) q+    where (vs,es) = unzip ps+          sub = mkEmptySubst+              $ mkInScopeSet+              $ delVarSetList (unionVarSets $ freeVarsQuantified q : map freeVarsExpr es) vs++-- | Note: Subst must be properly set up with an InScopeSet that includes all vars+-- in scope in the *range* of the substitution.+substQuantifiedSubst :: Subst -> Quantified -> Quantified+substQuantifiedSubst = go+    where go sub (Quantified bs cl) =+            let (bs', cl') = go1 sub bs [] cl+            in Quantified bs' cl'++          go1 subst [] bs' cl = (reverse bs', go2 subst cl)+          go1 subst (b:bs) bs' cl =+            let (subst',b') = substBndr subst b+            in go1 subst' bs (b':bs') cl+          go2 subst (Conj q1 q2) = Conj (go subst q1) (go subst q2)+          go2 subst (Disj q1 q2) = Disj (go subst q1) (go subst q2)+          go2 subst (Impl q1 q2) = Impl (go subst q1) (go subst q2)+          go2 subst (Equiv e1 e2) =+            let e1' = substExpr (text "substQuantified e1") subst e1+                e2' = substExpr (text "substQuantified e2") subst e2+            in Equiv e1' e2'++------------------------------------------------------------------------------++redundantDicts :: Quantified -> Quantified+redundantDicts (Quantified bs cl) = go [] [] cl bs+    where go bnds _   c [] = Quantified (reverse bnds) c+          go bnds tys c (b:bs')+              | isDictTy bTy = -- is a dictionary binder+                let match = [ varToCoreExpr pb | (pb,ty) <- tys , eqType bTy ty ]+                in if null match+                   then go (b:bnds) ((b,bTy):tys) c bs' -- not seen before+                   else let Quantified bs'' c' = substQuantified b (head match) $ Quantified bs' c+                        in go bnds tys c' bs'' -- seen+              | otherwise = go (b:bnds) tys c bs'+            where bTy = varType b++------------------------------------------------------------------------------++-- | Instantiate one of the universally quantified variables in a 'Quantified'.+-- Note: assumes implicit ordering of variables, such that substitution happens to the right+-- as it does in case alternatives. Only first variable that matches predicate is+-- instantiated.+instQuantified :: MonadCatch m => VarSet        -- vars in scope+                               -> (Var -> Bool) -- predicate to select var+                               -> CoreExpr      -- expression to instantiate with+                               -> Quantified -> m Quantified+instQuantified inScope p e = liftM fst . go []+    where go bbs (Quantified bs cl)+            | not (any p bs) = -- not quantified at this level, so try further down+                let go2 con q1 q2 = do+                        er <- attemptM $ go (bs++bbs) q1+                        (cl',s) <- case er of+                            Right (q1',s) -> return (con q1' q2, s)+                            Left _ -> do+                                er' <- attemptM $ go (bs++bbs) q2+                                case er' of+                                    Right (q2',s) -> return (con q1 q2', s)+                                    Left msg -> fail msg+                        return (replaceVars s bs (Quantified [] cl'), s)+                in case cl of+                    Equiv{} -> fail "specified variable is not universally quantified."+                    Conj q1 q2 -> go2 Conj q1 q2+                    Disj q1 q2 -> go2 Disj q1 q2+                    Impl q1 q2 -> go2 Impl q1 q2++            | otherwise = do -- quantified here, so do substitution and start bubbling up+                let (bs',i:vs) = break p bs -- this is safe because we know i is in bs+                    (eTvs, eTy) = splitForAllTys $ exprKindOrType e+                    bsInScope = bs'++bbs+                    tyVars = eTvs ++ filter isTyVar bsInScope+                    failMsg = fail "type of provided expression differs from selected binder."++                    bindFn v = if v `elem` tyVars then BindMe else Skolem++                sub <- maybe failMsg return $ tcUnifyTys bindFn [varType i] [eTy]++                    -- if i is a tyvar, we know e is a type, so free vars will be tyvars+                let e' = mkCoreApps e [ case lookupTyVar sub v of+                                            Nothing -> Type (mkTyVarTy v)+                                            Just ty -> Type ty | v <- eTvs ]+                let newBs = varSetElems+                          $ filterVarSet (\v -> not (isId v) || isLocalId v)+                          $ delVarSetList (minusVarSet (freeVarsExpr e') inScope) bsInScope+                    q' = substQuantified i e' $ Quantified vs cl++                return (replaceVars sub (bs' ++ newBs) q', sub)++-- | The function which 'bubbles up' after the instantiation takes place,+-- replacing any type variables that were instantiated as a result of specialization.+replaceVars :: TvSubst -> [Var] -> Quantified -> Quantified+replaceVars sub vs = go (reverse vs)+    where addB b (Quantified bs cl) = Quantified (b:bs) cl++          go [] q = q+          go (b:bs) q+            | isTyVar b = case lookupTyVar sub b of+                            Nothing -> go bs (addB b q)+                            Just ty -> let new = varSetElems (freeVarsType ty)+                                       in go (new++bs) (substQuantified b (Type ty) q)+            | otherwise = go bs (addB b q)++-- tvSubstToSubst :: TvSubst -> Subst+-- tvSubstToSubst (TvSubst inS tEnv) = mkSubst inS tEnv emptyVarEnv emptyVarEnv++-- | Instantiate a set of universally quantified variables in a 'Quantified'.+-- It is important that all type variables appear before any value-level variables in the first argument.+instsQuantified :: MonadCatch m => VarSet -> [(Var,CoreExpr)] -> Quantified -> m Quantified+instsQuantified inScope = flip (foldM (\ q (v,e) -> instQuantified inScope (==v) e q)) . reverse+-- foldM is a left-to-right fold, so the reverse is important to do substitutions in reverse order+-- which is what we want (all value variables should be instantiated before type variables).++------------------------------------------------------------------------------++-- Syntactic Equality++-- | Syntactic Equality of clauses.+clauseSyntaxEq :: Clause -> Clause -> Bool+clauseSyntaxEq (Conj q1 q2)  (Conj p1 p2)    = quantifiedSyntaxEq q1 p1 && quantifiedSyntaxEq q2 p2+clauseSyntaxEq (Disj q1 q2)  (Disj p1 p2)    = quantifiedSyntaxEq q1 p1 && quantifiedSyntaxEq q2 p2+clauseSyntaxEq (Impl q1 q2)  (Impl p1 p2)    = quantifiedSyntaxEq q1 p1 && quantifiedSyntaxEq q2 p2+clauseSyntaxEq (Equiv e1 e2) (Equiv e1' e2') = exprSyntaxEq e1 e1'      && exprSyntaxEq e2 e2'+clauseSyntaxEq _             _               = False++-- | Syntactic Equality of quantifiers.+quantifiedSyntaxEq :: Quantified -> Quantified -> Bool+quantifiedSyntaxEq (Quantified bs1 cl1) (Quantified bs2 cl2) = (bs1 == bs2) && clauseSyntaxEq cl1 cl2++------------------------------------------------------------------------------
+ src/HERMIT/Libraries/Int.hs view
@@ -0,0 +1,78 @@+{-# LANGUAGE OverloadedStrings #-}+module HERMIT.Libraries.Int where++import Control.Arrow++import qualified Data.Map as M++import HERMIT.GHC hiding (intTy)+import HERMIT.Kure+import HERMIT.Lemma+import HERMIT.Name+import HERMIT.Dictionary.Common+import HERMIT.Dictionary.GHC++{-+Defines the following lemmas:++forall n m.  (m == n) = (n == m)+forall n m.  (m < n ) = (n > m)+forall n m.  (m <= n) = (n >= m)+forall n m.  (m >= n) = (n < m)++forall n m.  (m <= n) = False  =>  (m == n) = False+forall n m.  (m == n) = True  =>  (m <= n) = True++forall n m.  (min n m)  =  (min m n)+forall n m.  (max n m)  =  (max m n)+forall n m.  (min n m <= n) = True+forall n m.  (max n m >= n) = True+-}++lemmas :: LemmaLibrary+lemmas = do+    intTy <- findTypeT "Prelude.Int"++    nId <- constT $ newIdH "n" intTy+    mId <- constT $ newIdH "m" intTy++    let n = varToCoreExpr nId+        m = varToCoreExpr mId+        appTo i e = return $ mkCoreApp (varToCoreExpr i) e+        appToInt i = appTo i (Type intTy)+        appToDict e = do+            let (aTys, _) = splitFunTys (exprType e)+            case aTys of+                (ty:_) | isDictTy ty -> return ty >>> buildDictionaryT >>> arr (mkCoreApp e)+                _ -> fail "first argument is not a dictionary."++        appMN e = mkCoreApps e [m,n]+        appNM e = mkCoreApps e [n,m]+        mkEL l r = mkL (Equiv l r)+        mkL cl = Lemma (Quantified [mId,nId] cl) (Assumed False) NotUsed False+        mkIL al ar cl cr = mkL (Impl (Quantified [] $ Equiv al ar) (Quantified [] $ Equiv cl cr))++    eqE <- findIdT "Data.Eq.==" >>= appToInt >>= appToDict++    gtE <- findIdT "Data.Ord.>" >>= appToInt >>= appToDict+    ltE <- findIdT "Data.Ord.<" >>= appToInt >>= appToDict+    gteE <- findIdT "Data.Ord.>=" >>= appToInt >>= appToDict+    lteE <- findIdT "Data.Ord.<=" >>= appToInt >>= appToDict+    minE <- findIdT "Data.Ord.min" >>= appToInt >>= appToDict+    maxE <- findIdT "Data.Ord.max" >>= appToInt >>= appToDict++    trueE <- varToCoreExpr <$> findIdT "Data.Bool.True"+    falseE <- varToCoreExpr <$> findIdT "Data.Bool.False"++    return $ M.fromList+                [ ("EqCommutativeInt", mkEL (appMN eqE) (appNM eqE))+                , ("LtGtInt", mkEL (appMN ltE) (appNM gtE))+                , ("LteGteInt", mkEL (appMN lteE) (appNM gteE))+                , ("GteLtInt", mkEL (appMN gteE) (appNM ltE))+                , ("LteFalseImpliesEqFalseInt", mkIL (appMN lteE) falseE (appMN eqE) falseE)+                , ("EqTrueImpliesLteTrueInt", mkIL (appMN eqE) trueE (appMN lteE) trueE)+                , ("MinCommutativeInt", mkEL (appMN minE) (appNM minE))+                , ("MaxCommutativeInt", mkEL (appMN maxE) (appNM maxE))+                , ("MinLteInt", mkEL (mkCoreApps lteE [appNM minE, n]) trueE)+                , ("MaxGteInt", mkEL (mkCoreApps gteE [appNM maxE, n]) trueE)+                ]
src/HERMIT/Monad.hs view
@@ -1,34 +1,29 @@-{-# LANGUAGE CPP, DeriveDataTypeable, FlexibleContexts, GADTs, InstanceSigs, KindSignatures #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE InstanceSigs #-}+{-# LANGUAGE KindSignatures #-}  module HERMIT.Monad     ( -- * The HERMIT Monad       HermitM     , runHM     , embedHermitM-    , HermitMEnv(..)+    , HermitMEnv     , HermitMResult(..)     , LiftCoreM(..)     , runTcM     , runDsM-      -- * Saving Definitions-    , RememberedName(..)-    , DefStash-    , saveDef-    , lookupDef-    , HasStash(..)       -- * Lemmas-    , Equality(..)-    , LemmaName(..)-    , Lemma(..)-    , Lemmas+    , HasLemmas(..)     , addLemma+    , findLemma+    , insertLemma+    , deleteLemma       -- * Reader Information     , HasHermitMEnv(..)     , mkEnv     , getModGuts     , HasHscEnv(..)-      -- * Writer Information-    , HasLemmas(..)       -- * Messages     , HasDebugChan(..)     , DebugMessage(..)@@ -37,78 +32,50 @@  import Prelude hiding (lookup) -import Data.Dynamic (Typeable)-import Data.Map-import Data.String (IsString(..))- import Control.Applicative-import Control.Arrow import Control.Concurrent.STM import Control.Monad import Control.Monad.IO.Class +import Data.Map+ import Language.KURE  import HERMIT.Core import HERMIT.Context-import HERMIT.Kure.SumTypes import HERMIT.GHC import HERMIT.GHC.Typechecker+import HERMIT.Kure.Universes+import HERMIT.Lemma  ---------------------------------------------------------------------------- --- | A label for individual definitions. Use a newtype so we can tab-complete in shell.-newtype RememberedName = RememberedName String deriving (Eq, Ord, Typeable)--instance IsString RememberedName where fromString = RememberedName-instance Show RememberedName where show (RememberedName s) = s---- | A store of saved definitions.-type DefStash = Map RememberedName CoreDef---- | An equality is represented as a set of universally quantified binders, and the LHS and RHS of the equality.-data Equality = Equality [CoreBndr] CoreExpr CoreExpr---- | A name for lemmas. Use a newtype so we can tab-complete in shell.-newtype LemmaName = LemmaName String deriving (Eq, Ord, Typeable)--instance IsString LemmaName where fromString = LemmaName-instance Show LemmaName where show (LemmaName s) = s---- | An equality with a proven status.-data Lemma = Lemma { lemmaEq :: Equality-                   , lemmaP  :: Bool     -- whether lemma has been proven-                   , lemmaU  :: Bool     -- whether lemma has been used-                   }---- | A collectin of named lemmas.-type Lemmas = Map LemmaName Lemma---- | The HermitM reader environment.-data HermitMEnv = HermitMEnv { hEnvModGuts   :: ModGuts -- ^ Note: this is a snapshot of the ModGuts from+-- | The HermitM environment.+data HermitMEnv = HermitMEnv { hEnvChanged   :: Bool -- ^ Whether Lemmas have changed+                             , hEnvModGuts   :: ModGuts -- ^ Note: this is a snapshot of the ModGuts from                                                         --         before the current transformation.-                             , hEnvStash     :: DefStash                              , hEnvLemmas    :: Lemmas                              } -mkEnv :: ModGuts -> DefStash -> Lemmas -> HermitMEnv-mkEnv = HermitMEnv+mkEnv :: ModGuts -> Lemmas -> HermitMEnv+mkEnv = HermitMEnv False  -- | The HermitM result record.-data HermitMResult a = HermitMResult { hResStash  :: DefStash+data HermitMResult a = HermitMResult { hResChanged :: Bool -- ^ Whether Lemmas have changed                                      , hResLemmas :: Lemmas                                      , hResult    :: a                                      } -mkResult :: DefStash -> Lemmas -> a -> HermitMResult a-mkResult = HermitMResult+changedResult :: Lemmas -> a -> HermitMResult a+changedResult = HermitMResult True -mkResultEnv :: HermitMEnv -> a -> HermitMResult a-mkResultEnv env = mkResult (hEnvStash env) (hEnvLemmas env)+-- Does not change the Changed status of Lemmas+mkResult :: HermitMEnv -> a -> HermitMResult a+mkResult env = HermitMResult (hEnvChanged env) (hEnvLemmas env)  -- | The HERMIT monad is kept abstract. ----- It provides a reader for ModGuts, state for DefStash and Lemmas,+-- It provides a reader for ModGuts, state for Lemmas, -- and access to a debugging channel. newtype HermitM a = HermitM { runHermitM :: DebugChan -> HermitMEnv -> CoreM (KureM (HermitMResult a)) } @@ -124,7 +91,7 @@ runHM chan env success failure ma = runHermitM ma chan env >>= runKureM success failure  -- | Allow HermitM to be embedded in another monad with proper capabilities.-embedHermitM :: (HasDebugChan m, HasHermitMEnv m, HasLemmas m, HasStash m, LiftCoreM m) => HermitM a -> m a+embedHermitM :: (HasDebugChan m, HasHermitMEnv m, HasLemmas m, LiftCoreM m) => HermitM a -> m a embedHermitM hm = do     env <- getHermitMEnv     c <- liftCoreM $ liftIO newTChanIO -- we are careful to do IO within liftCoreM to avoid the MonadIO constraint@@ -137,8 +104,7 @@                 Just dm -> chan dm >> relayDebugMessages      relayDebugMessages-    putStash $ hResStash r-    forM_ (toList (hResLemmas r)) $ uncurry insertLemma+    forM_ (toList (hResLemmas r)) $ uncurry insertLemma -- TODO: fix     return $ hResult r  instance Functor HermitM where@@ -154,12 +120,12 @@  instance Monad HermitM where   return :: a -> HermitM a-  return a = HermitM $ \ _ env -> return (return (mkResultEnv env a))+  return a = HermitM $ \ _ env -> return (return (mkResult env a))    (>>=) :: HermitM a -> (a -> HermitM b) -> HermitM b   (HermitM gcm) >>= f =-        HermitM $ \ chan env -> gcm chan env >>= runKureM (\ (HermitMResult s ls a) ->-                                                            let env' = env { hEnvStash = s, hEnvLemmas = ls }+        HermitM $ \ chan env -> gcm chan env >>= runKureM (\ (HermitMResult c ls a) ->+                                                            let env' = env { hEnvChanged = c, hEnvLemmas = ls }                                                             in  runHermitM (f a) chan env')                                                           (return . fail) @@ -202,34 +168,12 @@  ---------------------------------------------------------------------------- -class HasStash m where-    -- | Get the stash of saved definitions.-    getStash :: m DefStash--    -- | Replace the stash of saved definitions.-    putStash :: DefStash -> m ()--instance HasStash HermitM where-    getStash = HermitM $ \ _ env -> return $ return $ mkResultEnv env $ hEnvStash env--    putStash s = HermitM $ \ _ env -> return $ return $ mkResult s (hEnvLemmas env) ()---- | Save a definition for future use.-saveDef :: (HasStash m, Monad m) => RememberedName -> CoreDef -> m ()-saveDef l d = getStash >>= (insert l d >>> putStash)---- | Lookup a previously saved definition.-lookupDef :: (HasStash m, Monad m) => RememberedName -> m CoreDef-lookupDef l = getStash >>= (lookup l >>> maybe (fail "Definition not found.") return)------------------------------------------------------------------------------- class HasHermitMEnv m where     -- | Get the HermitMEnv     getHermitMEnv :: m HermitMEnv  instance HasHermitMEnv HermitM where-    getHermitMEnv = HermitM $ \ _ env -> return $ return $ mkResultEnv env env+    getHermitMEnv = HermitM $ \ _ env -> return $ return $ mkResult env env  getModGuts :: (HasHermitMEnv m, Monad m) => m ModGuts getModGuts = liftM hEnvModGuts getHermitMEnv@@ -241,7 +185,7 @@     getDebugChan :: m (DebugMessage -> m ())  instance HasDebugChan HermitM where-    getDebugChan = HermitM $ \ chan env -> return $ return $ mkResultEnv env chan+    getDebugChan = HermitM $ \ chan env -> return $ return $ mkResult env chan  sendDebugMessage :: (HasDebugChan m, Monad m) => DebugMessage -> m () sendDebugMessage msg = getDebugChan >>= ($ msg)@@ -260,15 +204,23 @@ ----------------------------------------------------------------------------  class HasLemmas m where-    -- | Add (or replace) a named lemma.-    insertLemma :: LemmaName -> Lemma -> m ()-     getLemmas :: m Lemmas+    putLemmas :: Lemmas -> m ()+    withLemmas :: Lemmas -> m a -> m a  instance HasLemmas HermitM where-    insertLemma nm l = HermitM $ \ _ env -> return $ return $ mkResult (hEnvStash env) (insert nm l $ hEnvLemmas env) ()+    getLemmas = HermitM $ \ _ env -> return $ return $ mkResult env (hEnvLemmas env)+    putLemmas m = HermitM $ \ _ _ -> return $ return $ changedResult m ()+    withLemmas ls (HermitM f) = HermitM $ \ d env -> do+                                    kr <- f d (env { hEnvLemmas = union ls (hEnvLemmas env) })+                                    runKureM (\ (HermitMResult c ls' a) ->+                                                    let ls'' = difference ls' ls+                                                    in return $ return $ HermitMResult c ls'' a)+                                             (return . fail) kr -    getLemmas = HermitM $ \ _ env -> return $ return $ mkResultEnv env (hEnvLemmas env)+-- | Insert or replace a lemma.+insertLemma :: (HasLemmas m, Monad m) => LemmaName -> Lemma -> m ()+insertLemma nm l = getLemmas >>= putLemmas . insert nm l  -- | Only adds a lemma if doesn't already exist. addLemma :: (HasLemmas m, Monad m) => LemmaName -> Lemma -> m ()@@ -276,6 +228,15 @@     ls <- getLemmas     maybe (insertLemma nm l) (\ _ -> return ()) (lookup nm ls) +-- | Find a lemma by name. Fails if lemma does not exist.+findLemma :: (HasLemmas m, Monad m) => LemmaName -> m Lemma+findLemma nm = do+    r <- liftM (lookup nm) getLemmas+    maybe (fail $ "lemma does not exist: " ++ show nm) return r++deleteLemma :: (HasLemmas m, Monad m) => LemmaName -> m ()+deleteLemma nm = getLemmas >>= putLemmas . delete nm+ ----------------------------------------------------------------------------  class Monad m => LiftCoreM m where@@ -283,14 +244,14 @@     liftCoreM :: CoreM a -> m a  instance LiftCoreM HermitM where-    liftCoreM coreM = HermitM $ \ _ env -> coreM >>= return . return . mkResultEnv env+    liftCoreM coreM = HermitM $ \ _ env -> coreM >>= return . return . mkResult env  ----------------------------------------------------------------------------  -- | A message packet. data DebugMessage :: * where-    DebugTick ::                                       String                -> DebugMessage-    DebugCore :: (ReadBindings c, ReadPath c Crumb) => String -> c -> CoreTC -> DebugMessage+    DebugTick ::                                       String                 -> DebugMessage+    DebugCore :: (ReadBindings c, ReadPath c Crumb) => String -> c -> LCoreTC -> DebugMessage  ---------------------------------------------------------------------------- 
src/HERMIT/Name.hs view
@@ -33,6 +33,7 @@     , newCoVarH     , newVarH     , cloneVarH+    , cloneVarFSH       -- * Name Lookup     , findId     , findVar@@ -99,7 +100,7 @@ -- like GHC's 'RdrName', but without specifying which 'NameSpace' -- the name is found in. data HermitName = HermitName { hnModuleName  :: Maybe ModuleName-                             , hnUnqualified :: String+                             , hnUnqualified :: FastString                              }     deriving (Eq, Typeable) @@ -123,16 +124,16 @@     | Just mn <- hm     , Just m  <- nameModule_maybe n = (mn == moduleName m) && sameOccName     | otherwise     = sameOccName-    where sameOccName = nm == unqualifiedName n+    where sameOccName = nm == occNameFS (getOccName n)  -- | Make a qualified HermitName from a String representing the module name -- and a String representing the occurrence name. mkQualified :: String -> String -> HermitName-mkQualified mnm nm = HermitName (Just $ mkModuleName mnm) nm+mkQualified mnm = HermitName (Just $ mkModuleName mnm) . mkFastString  -- | Make an unqualified HermitName from a String. mkUnqualified :: String -> HermitName-mkUnqualified = HermitName Nothing+mkUnqualified = HermitName Nothing . mkFastString  -- | Parse a HermitName from a String. parseName :: String -> HermitName@@ -149,18 +150,18 @@  -- | Turn a HermitName into a (possibly fully-qualified) String. showName :: HermitName -> String-showName (HermitName mnm nm) = maybe id (\ m n -> moduleNameString m ++ ('.' : n)) mnm nm+showName (HermitName mnm nm) = maybe id (\ m n -> moduleNameString m ++ ('.' : n)) mnm $ unpackFS nm  -- | Make a HermitName from a RdrName fromRdrName :: RdrName -> HermitName fromRdrName nm = case isQual_maybe nm of-                    Nothing         -> HermitName Nothing    (occNameString $ rdrNameOcc nm)-                    Just (mnm, onm) -> HermitName (Just mnm) (occNameString onm)+                    Nothing         -> HermitName Nothing    (occNameFS $ rdrNameOcc nm)+                    Just (mnm, onm) -> HermitName (Just mnm) (occNameFS onm)  -- | Make a RdrName for the given NameSpace and HermitName toRdrName :: NameSpace -> HermitName -> RdrName toRdrName ns (HermitName mnm nm) = maybe (mkRdrUnqual onm) (flip mkRdrQual onm) mnm-    where onm = mkOccName ns nm+    where onm = mkOccNameFS ns nm  -- | Make a RdrName for each given NameSpace. toRdrNames :: [NameSpace] -> HermitName -> [RdrName]@@ -327,33 +328,25 @@               | isTyVarName n   = fail "nameToNamed: impossible, TyVars are not exported and cannot be looked up."               | otherwise       = fail "nameToNamed: unknown name type" --- Someday, when Applicative is a superclass of monad, we can uncomment the--- nicer applicative definitions. For now, we don't want the extra constraint.- -- | Make a 'Name' from a string. newName :: MonadUnique m => String -> m Name-newName nm = getUniqueM >>= return . flip mkSystemVarName (mkFastString nm)--- newName nm = mkSystemVarName <$> getUniqueM <*> pure (mkFastString nm)+newName nm = mkSystemVarName <$> getUniqueM <*> return (mkFastString nm)  -- | Make a unique global identifier for a specified type, using a provided name. newGlobalIdH :: MonadUnique m => String -> Type -> m Id-newGlobalIdH nm ty = newName nm >>= return . flip mkVanillaGlobal ty--- newGlobalIdH nm ty = mkVanillaGlobal <$> newName nm <*> pure ty+newGlobalIdH nm ty = mkVanillaGlobal <$> newName nm <*> return ty  -- | Make a unique identifier for a specified type, using a provided name. newIdH :: MonadUnique m => String -> Type -> m Id-newIdH nm ty = newName nm >>= return . flip mkLocalId ty--- newIdH nm ty = mkLocalId <$> newName nm <*> pure ty+newIdH nm ty = mkLocalId <$> newName nm <*> return ty  -- | Make a unique type variable for a specified kind, using a provided name. newTyVarH :: MonadUnique m => String -> Kind -> m TyVar-newTyVarH nm k = newName nm >>= return . flip mkTyVar k--- newTyVarH nm k = mkTyVar <$> newName nm <*> pure k+newTyVarH nm k = mkTyVar <$> newName nm <*> return k  -- | Make a unique coercion variable for a specified type, using a provided name. newCoVarH :: MonadUnique m => String -> Type -> m TyVar-newCoVarH nm ty = newName nm >>= return . flip mkCoVar ty--- newCoVarH nm ty = mkCoVar <$> newName nm <*> pure ty+newCoVarH nm ty = mkCoVar <$> newName nm <*> return ty  -- TODO: not sure if the predicates are correct. -- | Experimental, use at your own risk.@@ -370,4 +363,14 @@                     | otherwise = fail "If this variable isn't a type, coercion or identifier, then what is it?"   where     name = nameMod (unqualifiedName v)+    ty   = varType v++-- | Make a new variable of the same type, with a modified textual name.+cloneVarFSH :: MonadUnique m => (FastString -> FastString) -> Var -> m Var+cloneVarFSH nameMod v | isTyVar v = newTyVarH name ty+                      | isCoVar v = newCoVarH name ty+                      | isId v    = newIdH name ty+                      | otherwise = fail "If this variable isn't a type, coercion or identifier, then what is it?"+  where+    name = unpackFS $ nameMod $ occNameFS $ getOccName v     ty   = varType v
src/HERMIT/ParserCore.y view
@@ -1,5 +1,6 @@ { {-# LANGUAGE CPP #-}+{-# LANGUAGE TupleSections #-} module HERMIT.ParserCore     ( parseCore     , parseCoreExprT@@ -17,6 +18,7 @@ import Control.Arrow import Control.Monad.Reader import Data.Char (isSpace, isDigit)+import qualified Data.Map as M  import HERMIT.Context import HERMIT.External@@ -168,27 +170,35 @@  --------------------------------------------- -parseCore :: BoundVars c => CoreString -> c -> HermitM CoreExpr+parseCore :: ReadBindings c => CoreString -> c -> HermitM CoreExpr parseCore (CoreString s) c =     case lexer s of         Left msg -> fail msg-        Right tokens -> runReaderT (parser tokens) (boundVars c)+        Right tokens ->+            -- Since we are comparing occurrence names, only take the+            -- most recently defined (deepest) when variables shadow each other.+            let comb v1@(_,d1) v2@(_,d2) = if d1 > d2 then v1 else v2+                vars = mkVarSet . map fst . M.elems+                     $ M.mapKeysWith comb getOccString+                     $ M.mapWithKey (\k -> (k,) . hbDepth)+                     $ hermitBindings c+            in runReaderT (parser tokens) vars  ---------------------------------------------  -- These should probably go somewhere else.  -- | Parse a 'CoreString' to a 'CoreExpr', using the current context.-parseCoreExprT :: (BoundVars c, HasDebugChan m, HasHermitMEnv m, HasLemmas m, HasStash m, LiftCoreM m)+parseCoreExprT :: (ReadBindings c, HasDebugChan m, HasHermitMEnv m, HasLemmas m, LiftCoreM m)                => CoreString -> Transform c m a CoreExpr parseCoreExprT cs = contextonlyT $ embedHermitM . parseCore cs -parse2BeforeT :: (BoundVars c, HasDebugChan m, HasHermitMEnv m, HasLemmas m, HasStash m, LiftCoreM m)+parse2BeforeT :: (ReadBindings c, HasDebugChan m, HasHermitMEnv m, HasLemmas m, LiftCoreM m)               => (CoreExpr -> CoreExpr -> Translate c m a b)               -> CoreString -> CoreString -> Translate c m a b parse2BeforeT f s1 s2 = parseCoreExprT s1 &&& parseCoreExprT s2 >>= uncurry f -parse3BeforeT :: (BoundVars c, HasDebugChan m, HasHermitMEnv m, HasLemmas m, HasStash m, LiftCoreM m)+parse3BeforeT :: (ReadBindings c, HasDebugChan m, HasHermitMEnv m, HasLemmas m, LiftCoreM m)               => (CoreExpr -> CoreExpr -> CoreExpr -> Translate c m a b)               -> CoreString -> CoreString -> CoreString -> Translate c m a b parse3BeforeT f s1 s2 s3 = (parseCoreExprT s1 &&& parseCoreExprT s2) &&& parseCoreExprT s3 >>= (uncurry . uncurry $ f)
src/HERMIT/Plugin.hs view
@@ -1,4 +1,5 @@-{-# LANGUAGE KindSignatures, GADTs, FlexibleContexts, GeneralizedNewtypeDeriving, LambdaCase, CPP #-}+{-# LANGUAGE KindSignatures, GADTs, FlexibleContexts, GeneralizedNewtypeDeriving, LambdaCase #-}+{-# LANGUAGE TupleSections #-} module HERMIT.Plugin     ( -- * The HERMIT Plugin       hermitPlugin@@ -31,21 +32,19 @@ import Control.Applicative import Control.Arrow import Control.Concurrent.STM-#if MIN_VERSION_mtl(2,2,1)-import Control.Monad.Except hiding (guard)-#else-import Control.Monad.Error hiding (guard)-#endif+import Control.Monad (when)+import Control.Monad.IO.Class (MonadIO(..)) import Control.Monad.Operational-import Control.Monad.State hiding (guard)+import Control.Monad.State (gets, modify)+import Control.Monad.Trans.Class (MonadTrans(..)) -import Data.Monoid+import Data.IORef import qualified Data.Map as M+import Data.Monoid  import HERMIT.Dictionary import HERMIT.External hiding (Query, Shell)-import HERMIT.Kernel (KernelEnv)-import HERMIT.Kernel.Scoped+import HERMIT.Kernel import HERMIT.Context import HERMIT.Kure import HERMIT.GHC hiding (singleton, liftIO, display, (<>))@@ -64,13 +63,14 @@ import Prelude hiding (until)  hermitPlugin :: ([CommandLineOption] -> HPM ()) -> Plugin-hermitPlugin f = buildPlugin $ \ passInfo -> runHPM passInfo . f+hermitPlugin f = buildPlugin $ \ store passInfo -> runHPM store passInfo . f -defPS :: SAST -> ScopedKernel -> PassInfo -> IO PluginState-defPS initSAST kernel passInfo = do+defPS :: AST -> Kernel -> PassInfo -> IO PluginState+defPS initAST kernel passInfo = do     emptyTick <- liftIO $ atomically $ newTVar M.empty     return $ PluginState-                { ps_cursor         = initSAST+                { ps_cursor         = initAST+                , ps_focus          = mempty                 , ps_pretty         = Clean.pretty                 , ps_render         = unicodeConsole                 , ps_tick           = emptyTick@@ -91,17 +91,22 @@ newtype HPM a = HPM { unHPM :: ProgramT HPMInst PluginM a }     deriving (Functor, Applicative, Monad, MonadIO) -runHPM :: PassInfo -> HPM () -> ModGuts -> CoreM ModGuts-runHPM passInfo hpass = scopedKernel $ \ kernel initSAST -> do-    ps <- defPS initSAST kernel passInfo+lpName :: PassInfo -> String+lpName pInfo = case passesDone pInfo of+                    [] -> "-- front end" -- comment format in case these appear in dumped script+                    ps -> "-- GHC - " ++ show (last ps)++runHPM :: IORef (Maybe (AST, ASTMap)) -> PassInfo -> HPM () -> ModGuts -> CoreM ModGuts+runHPM store passInfo hpass = hermitKernel store (lpName passInfo) $ \ kernel initAST -> do+    ps <- defPS initAST kernel passInfo     (r,st) <- hpmToIO ps hpass-    let cleanup sast = do-            if sast /= initSAST -- only do this if we actually changed the AST-            then applyS kernel occurAnalyseAndDezombifyR (mkKernelEnv st) sast >>= resumeS kernel-            else resumeS kernel sast-    either (\case PAbort       -> abortS kernel-                  PResume sast -> cleanup sast-                  PError  err  -> putStrLn err >> abortS kernel)+    let cleanup ast = do+            if ast /= initAST -- only do this if we actually changed the AST+            then applyK kernel (extractR (occurAnalyseAndDezombifyR :: RewriteH Core)) Never (mkKernelEnv st) ast >>= resumeK kernel+            else resumeK kernel ast+    either (\case PAbort      -> abortK kernel+                  PResume ast -> cleanup ast+                  PError  err -> putStrLn err >> abortK kernel)            (\ _ -> cleanup $ ps_cursor st) r  hpmToIO :: PluginState -> HPM a -> IO (Either PException a, PluginState)@@ -109,63 +114,37 @@  eval :: ProgramT HPMInst PluginM a -> PluginM a eval comp = do-    (kernel, env) <- gets $ ps_kernel &&& mkKernelEnv+    (kernel, (env, path)) <- gets $ ps_kernel &&& mkKernelEnv &&& ps_focus     v <- viewT comp     case v of-        Return x            -> return x-        RR rr       :>>= k  -> runS (applyS kernel rr env) >>= eval . k-        Query tr    :>>= k  -> runK (queryS kernel tr env) >>= eval . k-        Shell es os :>>= k -> do-            -- We want to discard the current focus, open the shell at-            -- the top level, then restore the current focus.-            paths <- resetScoping env-            clm (commandLine interpShellCommand os es)-            _ <- resetScoping env-            restoreScoping env paths-            eval $ k ()+        Return x           -> return x+        RR rr       :>>= k -> runS (applyK kernel (extractR $ localPathR path rr) Never env) >>= eval . k+        Query tr    :>>= k -> runQ (queryK kernel (extractT $ localPathT path tr) Never env) >>= eval . k+        Shell es os :>>= k -> clm (commandLine os es) >>= eval . k         Guard p (HPM m)  :>>= k  -> gets (p . ps_pass) >>= \ b -> when b (eval m) >>= eval . k         Focus tp (HPM m) :>>= k  -> do-            p <- runK (queryS kernel tp env)  -- run the pathfinding translation-            runS $ beginScopeS kernel         -- remember the current path-            runS $ modPathS kernel (<> p) env -- modify the current path+            p <- runQ (queryK kernel (extractT tp) Never env)  -- run the pathfinding translation+            old_p <- gets ps_focus+            modify $ \st -> st { ps_focus = old_p <> p }             r <- eval m             	      -- run the focused computation-            runS $ endScopeS kernel           -- endscope on it, so we go back to where we started+            modify $ \st -> st { ps_focus = old_p }             eval $ k r  ------------------------- Shell-related helpers -------------------------------------- -resetScoping :: KernelEnv -> PluginM [PathH]-resetScoping env = do-    kernel <- gets ps_kernel-    paths <- runK $ pathS kernel-    replicateM_ (length paths - 1) $ runS $ endScopeS kernel-    -- modPathS commonly fails here because the path is unchanged, so throw away failures-    catchM (runS $ modPathS kernel (const mempty) env) (const (return ()))-    return paths--restoreScoping :: KernelEnv -> [PathH] -> PluginM ()-restoreScoping _   []    = return ()-restoreScoping env (h:t) = do-    kernel <- gets ps_kernel--    let go p []      = restore p-        go p (p':ps) = restore p >> runS (beginScopeS kernel) >> go p' ps--        -- modPathS commonly fails here because the path is unchanged, so throw away failures-        restore p = catchM (runS $ modPathS kernel (<> pathToSnocPath p) env)-                           (const (return ()))--    go h t---- | Run a kernel function on the current SAST-runK :: (SAST -> PluginM a) -> PluginM a+-- | Run a kernel function on the current AST+runK :: (AST -> PluginM a) -> PluginM a runK f = gets ps_cursor >>= f --- | Run a kernel function on the current SAST and update ps_cursor-runS :: (SAST -> PluginM SAST) -> PluginM ()-runS f = do-    sast <- runK f+-- | Run a kernel function on the current AST and update ps_cursor+runS :: (AST -> PluginM AST) -> PluginM ()+runS f = runQ (fmap (,()) . f)++runQ :: (AST -> PluginM (AST, a)) -> PluginM a+runQ f = do+    (sast, r) <- runK f     modify $ \st -> st { ps_cursor = sast }+    return r  interactive :: [External] -> [CommandLineOption] -> HPM () interactive es os = HPM . singleton $ Shell (externals ++ es) os@@ -215,7 +194,7 @@ getPassInfo = HPM $ lift $ gets ps_pass  display :: HPM ()-display = HPM $ lift $ Display.display Nothing+display = HPM $ lift $ Display.display Nothing Nothing  modifyCLS :: (PluginState -> PluginState) -> HPM () modifyCLS = HPM . modify
src/HERMIT/Plugin/Builder.hs view
@@ -2,7 +2,7 @@  module HERMIT.Plugin.Builder     ( -- * The HERMIT Plugin-      PluginPass+      HERMITPass     , buildPlugin     , CorePass(..)     , getCorePass@@ -11,16 +11,19 @@     , getPassFlag     )  where +import Data.IORef import Data.List-import System.IO  import HERMIT.GHC+import HERMIT.Kernel +import System.IO+ -- | Given a list of 'CommandLineOption's, produce the 'ModGuts' to 'ModGuts' function required to build a plugin.-type PluginPass = PassInfo -> [CommandLineOption] -> ModGuts -> CoreM ModGuts+type HERMITPass = IORef (Maybe (AST, ASTMap)) -> PassInfo -> [CommandLineOption] -> ModGuts -> CoreM ModGuts  -- | Build a plugin. This mainly handles the per-module options.-buildPlugin :: PluginPass -> Plugin+buildPlugin :: HERMITPass -> Plugin buildPlugin hp = defaultPlugin { installCoreToDos = install }     where         install :: [CommandLineOption] -> [CoreToDo] -> CoreM [CoreToDo]@@ -36,36 +39,50 @@             liftIO initStaticOpts #endif +            store <- liftIO $ newIORef (Nothing :: Maybe (ModuleName, IORef (Maybe (AST, ASTMap))))             let todos' = flattenTodos todos                 passes = map getCorePass todos'                 allPasses = foldr (\ (n,p,seen,notyet) r -> mkPass n seen notyet : p : r)                                   [mkPass (length todos') passes []]                                   (zip4 [0..] todos' (inits passes) (tails passes))-                mkPass n ps ps' = CoreDoPluginPass ("HERMIT" ++ show n) $ modFilter hp (PassInfo n ps ps') opts+                mkPass n ps ps' = CoreDoPluginPass ("HERMIT" ++ show n)+                                $ modFilter store hp (PassInfo n ps ps') opts              return allPasses --- | Determine whether to act on this module, choose plugin pass.+-- | Determine whether to act on this module, selecting global store. -- NB: we have the ability to stick module info in the pass info here-modFilter :: PluginPass -> PluginPass-modFilter hp pInfo opts guts+modFilter :: IORef (Maybe (ModuleName, IORef (Maybe (AST, ASTMap)))) -- global store+          -> HERMITPass+          -> PassInfo+          -> [CommandLineOption]+          -> ModGuts -> CoreM ModGuts+modFilter store hp pInfo opts guts     | null modOpts && notNull opts = return guts -- don't process this module-    | otherwise                    = hp pInfo (h_opts ++ filter notNull modOpts) guts-    where modOpts = filterOpts m_opts guts+    | otherwise                    = do mb <- liftIO $ readIORef store+                                        modStore <- case mb of+                                                        Just (nm,ref) | nm == modName -> return ref+                                                        _ -> liftIO $ do+                                                            ref <- newIORef Nothing+                                                            writeIORef store $ Just (modName, ref)+                                                            return ref+                                        hp modStore pInfo (h_opts ++ filter notNull modOpts) guts+    where modOpts = filterOpts m_opts modName           (m_opts, h_opts) = partition (isInfixOf ":") opts+          modName = moduleName $ mg_module guts  -- | Filter options to those pertaining to this module, stripping module prefix.-filterOpts :: [CommandLineOption] -> ModGuts -> [CommandLineOption]-filterOpts opts guts = [ opt | nm <- opts-                             , let mopt = if modName `isPrefixOf` nm-                                          then Just (drop len nm)-                                          else if "*:" `isPrefixOf` nm-                                               then Just (drop 2 nm)-                                               else Nothing-                             , Just opt <- [mopt]-                             ]-    where modName = moduleNameString $ moduleName $ mg_module guts-          len = length modName + 1 -- for the colon+filterOpts :: [CommandLineOption] -> ModuleName -> [CommandLineOption]+filterOpts opts mname = [ opt | nm <- opts+                              , let mopt = if modName `isPrefixOf` nm+                                           then Just (drop len nm)+                                           else if "*:" `isPrefixOf` nm+                                                then Just (drop 2 nm)+                                                else Nothing+                              , Just opt <- [mopt]+                              ]+    where modName = moduleNameString mname+          len = lengthFS (moduleNameFS mname) + 1 -- for the colon  -- | An enumeration type for GHC's passes. data CorePass = FloatInwards
src/HERMIT/Plugin/Display.hs view
@@ -1,7 +1,6 @@ {-# LANGUAGE FlexibleContexts #-} module HERMIT.Plugin.Display     ( display-    , getFocusPath     , ps_putStr     , ps_putStrLn     ) where@@ -9,28 +8,25 @@ import Control.Monad.State  import Data.Maybe (fromMaybe)+import Data.Monoid -import HERMIT.Kernel (queryK)-import HERMIT.Kernel.Scoped+import HERMIT.Kernel (queryK, CommitMsg(..)) import HERMIT.Kure import HERMIT.Plugin.Types import HERMIT.PrettyPrinter.Common  import System.IO -getFocusPath :: PluginM PathH-getFocusPath = get >>= \ st -> liftM concat $ prefixFailMsg "getFocusPath - pathS failed: " $ pathS (ps_kernel st) (ps_cursor st)--display :: Maybe PathH -> PluginM ()-display window = do+display :: Maybe Handle -> Maybe PathH -> PluginM ()+display mbh window = do     st <- get-    focusPath <- getFocusPath-    let skernel = ps_kernel st-        ppOpts = (pOptions $ ps_pretty st) { po_focus = Just focusPath }-    iokm' "Rendering error: "-        (liftIO . ps_render st stdout ppOpts . Right)-        (toASTS skernel (ps_cursor st) >>= \ ast ->-            queryK (kernelS skernel) ast (extractT $ pathT (fromMaybe focusPath window) $ liftPrettyH ppOpts $ pCoreTC $ ps_pretty st) (mkKernelEnv st))+    let k = ps_kernel st+        ast = ps_cursor st+        ppOpts = pOptions $ ps_pretty st+        h = fromMaybe stdout mbh+    d <- queryK k (extractT $ pathT (fromMaybe mempty window) $ liftPrettyH ppOpts $ pCoreTC $ ps_pretty st)+                Never (mkKernelEnv st) ast+    liftIO $ ps_render st h ppOpts $ Right $ snd d -- discard new AST, assuming pretty printer won't create one  ps_putStr :: (MonadIO m, MonadState PluginState m) => String -> m () ps_putStr str = do
src/HERMIT/Plugin/Renderer.hs view
@@ -25,10 +25,10 @@ import System.Process  changeRenderer :: String -> PluginM ()-changeRenderer renderer = modify $ \ st ->-        case lookup renderer shellRenderers of-          Nothing -> st          -- TODO: should fail with message-          Just r  -> st { ps_render = r }+changeRenderer renderer =+    case lookup renderer shellRenderers of+        Nothing -> fail "bad renderer option."+        Just r  -> modify $ \ st -> st { ps_render = r }  shellRenderers :: [(String,Handle -> PrettyOptions -> Either String DocH -> IO ())] shellRenderers = [ ("unicode-terminal", unicodeConsole) ]
src/HERMIT/Plugin/Types.hs view
@@ -1,45 +1,42 @@ {-# LANGUAGE TypeFamilies, DeriveDataTypeable, FlexibleContexts,              LambdaCase, GADTs, GeneralizedNewtypeDeriving,-             ScopedTypeVariables, FlexibleInstances, CPP #-}+             ScopedTypeVariables, FlexibleInstances #-} module HERMIT.Plugin.Types where  import Control.Applicative import Control.Concurrent.STM-#if MIN_VERSION_mtl(2,2,1)-import Control.Monad.Except-#else-import Control.Monad.Error-#endif-import Control.Monad.State+import Control.Monad.Error.Class (MonadError(..))+import Control.Monad.IO.Class (MonadIO(..))+import Control.Monad.State (MonadState(..), StateT(..))+import Control.Monad.Trans.Class (MonadTrans(..))+import Control.Monad.Trans.Except (ExceptT, runExceptT)  import Data.Dynamic import qualified Data.Map as M +import HERMIT.Core (Crumb) import HERMIT.Kure import HERMIT.External-import HERMIT.Kernel (KernelEnv(..))-import HERMIT.Kernel.Scoped+import HERMIT.Kernel import HERMIT.Monad import HERMIT.Plugin.Builder import HERMIT.PrettyPrinter.Common+import HERMIT.Dictionary.Reasoning  import System.IO  type PluginM = PluginT IO-#if MIN_VERSION_mtl(2,2,1) newtype PluginT m a = PluginT { unPluginT :: ExceptT PException (StateT PluginState m) a }-#else-newtype PluginT m a = PluginT { unPluginT :: ErrorT PException (StateT PluginState m) a }-#endif-    deriving (Functor, Applicative, Monad, MonadIO, MonadError PException, MonadState PluginState)+    deriving (Functor, Applicative, MonadIO, MonadError PException, MonadState PluginState)  runPluginT :: PluginState -> PluginT m a -> m (Either PException a, PluginState)-#if MIN_VERSION_mtl(2,2,1) runPluginT ps = flip runStateT ps . runExceptT . unPluginT-#else-runPluginT ps = flip runStateT ps . runErrorT . unPluginT-#endif +instance Monad m => Monad (PluginT m) where+    return = PluginT . return+    PluginT m >>= k = PluginT (m >>= unPluginT . k)+    fail = PluginT . throwError . PError+ instance MonadTrans PluginT where     lift = PluginT . lift . lift @@ -57,7 +54,8 @@  -- Session-local issues; things that are never saved. data PluginState = PluginState-    { ps_cursor         :: SAST                                     -- ^ the current AST+    { ps_cursor         :: AST                                      -- ^ the current AST+    , ps_focus          :: AbsolutePath Crumb                       -- ^ current focused path     , ps_pretty         :: PrettyPrinter                            -- ^ which pretty printer to use     , ps_render         :: Handle -> PrettyOptions -> Either String DocH -> IO () -- ^ the way of outputing to the screen     , ps_tick           :: TVar (M.Map String Int)                  -- ^ the list of ticked messages@@ -65,15 +63,11 @@     , ps_diffonly       :: Bool                                     -- ^ if true, show diffs rather than pp full code (TODO: move into pretty opts)     , ps_failhard       :: Bool                                     -- ^ if true, abort on *any* failure     -- this should be in a reader-    , ps_kernel         :: ScopedKernel+    , ps_kernel         :: Kernel     , ps_pass           :: PassInfo     } deriving (Typeable) -data PException = PAbort | PResume SAST | PError String--#if !(MIN_VERSION_mtl(2,2,1))-instance Error PException where strMsg = PError-#endif+data PException = PAbort | PResume AST | PError String  newtype PSBox = PSBox PluginState deriving Typeable instance Extern PluginState where@@ -100,16 +94,7 @@                 DebugTick    msg'      -> do                         c <- liftIO $ tick (ps_tick st) msg'                         out $ "<" ++ show c ++ "> " ++ msg'-                DebugCore  msg' cxt core -> do+                DebugCore  msg' cxt qc -> do                         out $ "[" ++ msg' ++ "]"-                        doc :: DocH <- applyT (pCoreTC pp) (liftPrettyC (pOptions pp) cxt) (inject core)+                        doc :: DocH <- applyT (ppLCoreTCT pp) (liftPrettyC (pOptions pp) cxt) qc                         liftIO $ ps_render st stdout (pOptions pp) (Right doc)--iokm' :: (MonadIO m, MonadCatch m) => String -> (a -> m b) -> IO (KureM a) -> m b-iokm' msg ret m = liftIO m >>= runKureM ret (fail . (msg ++))--iokm :: (MonadIO m, MonadCatch m) => String -> IO (KureM a) -> m a-iokm msg = iokm' msg return--iokm'' :: (MonadIO m, MonadCatch m) => IO (KureM a) -> m a-iokm'' = iokm ""
src/HERMIT/PrettyPrinter/AST.hs view
@@ -3,7 +3,8 @@ -- | Output the raw Expr constructors. Helpful for writing pattern matching rewrites. module HERMIT.PrettyPrinter.AST   ( -- * HERMIT's AST Pretty-Printer for GHC Core-    pretty+    externals+  , pretty   , ppCoreTC   , ppModGuts   , ppCoreProg@@ -19,14 +20,13 @@ import Control.Arrow hiding ((<+>))  import Data.Char (isSpace)-import Data.Default+import Data.Default.Class +import HERMIT.Core+import HERMIT.External import HERMIT.GHC hiding (($$), (<+>), (<>), ($+$), cat, nest, parens, text, empty, hsep) import HERMIT.Kure-import HERMIT.Core -import HERMIT.Dictionary (dynFlagsT)- import HERMIT.PrettyPrinter.Common  import Text.PrettyPrint.MarkedHughesPJ as PP@@ -41,11 +41,14 @@  --------------------------------------------------------------------------- +externals :: [External]+externals = [ external "ast" pretty ["AST pretty printer."] ]+ pretty :: PrettyPrinter pretty = PP { pForall = ppForallQuantification             , pCoreTC = ppCoreTC             , pOptions = def-            } +            }  -- | Pretty print a fragment of GHC Core using HERMIT's \"AST\" pretty printer. --   This displays the tree of constructors using nested indentation.@@ -63,7 +66,7 @@ -- Use for any GHC structure, the 'showSDoc' prefix is to remind us -- that we are eliding infomation here. ppSDoc :: Outputable a => PrettyH a-ppSDoc =  do dynFlags   <- dynFlagsT+ppSDoc =  do dynFlags   <- constT getDynFlags              hideNotes  <- (po_notes . prettyC_options) ^<< contextT              arr (toDoc . (if hideNotes then id else ("showSDoc: " ++)) . showPpr dynFlags)     where toDoc s | any isSpace s = parens (text s)
src/HERMIT/PrettyPrinter/Clean.hs view
@@ -2,7 +2,8 @@  module HERMIT.PrettyPrinter.Clean     ( -- * HERMIT's Clean Pretty-Printer for GHC Core-      pretty+      externals+    , pretty     , ppCoreTC     , ppModGuts     , ppCoreProg@@ -12,18 +13,18 @@     , ppKindOrType     , ppCoercion     , ppForallQuantification+    , symbol -- should be in Common     ) where  import Control.Arrow hiding ((<+>))-import Control.Applicative ((<$>))  import Data.Char (isSpace)-import Data.Default+import Data.Default.Class import Data.Monoid (mempty)  import HERMIT.Context import HERMIT.Core-import HERMIT.Dictionary (dynFlagsT)+import HERMIT.External import HERMIT.GHC hiding ((<+>), (<>), ($$), ($+$), cat, sep, fsep, hsep, empty, nest, vcat, char, text, keyword, hang) import HERMIT.Kure import HERMIT.Monad@@ -34,6 +35,9 @@  ------------------------------------------------------------------------------------------------ +externals :: [External]+externals = [ external "clean" pretty ["Clean pretty printer."] ]+ pretty :: PrettyPrinter pretty = PP { pForall = ppForallQuantification             , pCoreTC = ppCoreTC@@ -215,7 +219,7 @@  -- Use for any GHC structure ppSDoc :: Outputable a => PrettyH a-ppSDoc = do dynFlags <- dynFlagsT+ppSDoc = do dynFlags <- constT getDynFlags             p        <- absPathT             doc      <- arr (showPpr dynFlags)             if any isSpace doc@@ -263,6 +267,12 @@ ppTyConCo :: PrettyH TyCon ppTyConCo = getName ^>> ppName CoercionColor +ppDetailedVar :: PrettyH Var+ppDetailedVar = do+    p <- absPathT+    (v,ty) <- ppVar &&& (varType ^>> ppKindOrType)+    return $ cleanParens p $ v <+> typeOfSymbol p <+> ty+ -- binders are vars that is bound by lambda or case, etc. -- depending on the mode, they might not be displayed ppBinderMode :: PrettyH Var@@ -273,15 +283,19 @@                      | isTyVar v -> case po_exprTypes opts of                                                            Omit     -> return empty                                                            Abstract -> return (typeBindSymbol p)+                                                           Detailed -> ppDetailedVar                                                            _        -> ppVar                      | isCoVar v -> case po_coercions opts of                                                            Omit     -> return empty                                                            Abstract -> return (coercionBindSymbol p)+                                                           Detailed -> ppDetailedVar                                                            Show     -> ppVar                                                            Kind     -> do pCoKind <- ppCoKind <<^ CoVarCo                                                                           return $ cleanParens p (coercionBindSymbol p <+> typeOfSymbol p <+> pCoKind)                                                           -- TODO: refactor this to be more systematic.  It should be possible to request type sigs for all type bindings.-                     | otherwise       -> ppVar+                     | otherwise -> case po_exprTypes opts of+                                        Detailed -> ppDetailedVar+                                        _        -> ppVar  ppModGuts :: PrettyH ModGuts ppModGuts = do p    <- absPathT@@ -409,7 +423,7 @@   do vs <- mapT ppBinderMode      if null vs      then return empty-     else return $ specialSymbol mempty ForallSymbol <+> hsep vs <> symbol mempty '.'+     else return $ specialSymbol mempty ForallSymbol <+> sep vs <> symbol mempty '.'  -------------------------------------------------------------------- @@ -422,8 +436,8 @@                      case po_coercions opts of                        Omit     -> return RetEmpty                        Abstract -> return (RetAtom $ coercionSymbol p)-                       Show     -> ppCoercionR                        Kind     -> ppCoKind >>^ (\ k -> RetExpr (coercionSymbol p <+> coTypeSymbol p <+> k))+                       _        -> ppCoercionR  ppCoercionR :: Transform PrettyC HermitM Coercion RetExpr ppCoercionR = absPathT >>= ppCoercionPR
src/HERMIT/PrettyPrinter/Common.hs view
@@ -6,6 +6,7 @@     , Attr(..)     , attrP     , HTML(..)+    , ASCII(..)       -- ** Colors     , coercionColor     , idColor@@ -28,12 +29,14 @@       -- * Pretty Printer Traversals     , PrettyPrinter(..)     , PrettyH+    , PrettyHLCoreBox(..)+    , PrettyHLCoreTCBox(..)+    , TransformLCoreDocHBox(..)+    , TransformLCoreTCDocHBox(..)     , liftPrettyH     , PrettyC(..)     , initPrettyC     , liftPrettyC-    , TransformDocH(..)-    , TransformCoreTCDocHBox(..)       -- * Pretty Printer Options     , PrettyOptions(..)     , updateCoShowOption@@ -47,7 +50,7 @@     ) where  import Data.Char-import Data.Default+import Data.Default.Class import Data.Monoid hiding ((<>)) import qualified Data.Map as M import Data.Typeable@@ -69,16 +72,6 @@ -- A HERMIT document type DocH = MDoc HermitMark --- newtype wrapper for proper instance selection-newtype TransformDocH a = TransformDocH { unTransformDocH :: PrettyC -> PrettyH a -> TransformH a DocH }--data TransformCoreTCDocHBox = TransformCoreTCDocHBox (TransformDocH CoreTC) deriving Typeable--instance Extern (TransformDocH CoreTC) where-    type Box (TransformDocH CoreTC) = TransformCoreTCDocHBox-    box = TransformCoreTCDocHBox-    unbox (TransformCoreTCDocHBox i) = i- -- These are the zero-width marks on the document data HermitMark         = PushAttr Attr@@ -133,10 +126,46 @@                         , pCoreTC  :: PrettyH CoreTC                         , pOptions :: PrettyOptions                         }+    deriving Typeable +instance Extern PrettyPrinter where+    type Box PrettyPrinter = PrettyPrinter+    box i = i+    unbox i = i+ type PrettyH a = Transform PrettyC HermitM a DocH -- TODO: change monads to something more restricted? +data PrettyHLCoreBox = PrettyHLCoreBox (PrettyH LCore) deriving Typeable++instance Extern (PrettyH LCore) where+    type Box (PrettyH LCore) = PrettyHLCoreBox+    box = PrettyHLCoreBox+    unbox (PrettyHLCoreBox i) = i++data TransformLCoreDocHBox = TransformLCoreDocHBox (TransformH LCore DocH) deriving Typeable++instance Extern (TransformH LCore DocH) where+    type Box (TransformH LCore DocH) = TransformLCoreDocHBox+    box = TransformLCoreDocHBox+    unbox (TransformLCoreDocHBox i) = i++data PrettyHLCoreTCBox = PrettyHLCoreTCBox (PrettyH LCoreTC) deriving Typeable++instance Extern (PrettyH LCoreTC) where+    type Box (PrettyH LCoreTC) = PrettyHLCoreTCBox+    box = PrettyHLCoreTCBox+    unbox (PrettyHLCoreTCBox i) = i++data TransformLCoreTCDocHBox = TransformLCoreTCDocHBox (TransformH LCoreTC DocH) deriving Typeable++instance Extern (TransformH LCoreTC DocH) where+    type Box (TransformH LCoreTC DocH) = TransformLCoreTCDocHBox+    box = TransformLCoreTCDocHBox+    unbox (TransformLCoreTCDocHBox i) = i++-------------------------------------------------------------------------------+ -- | Context for PrettyH translations. data PrettyC = PrettyC { prettyC_path    :: AbsolutePathH                        , prettyC_vars    :: M.Map Var AbsolutePathH@@ -176,7 +205,7 @@  ------------------------------------------------------------------------ -liftPrettyH :: (ReadBindings c, ReadPath c Crumb) => PrettyOptions -> PrettyH a -> Transform c HermitM a DocH+liftPrettyH :: (ReadBindings c, ReadPath c Crumb) => PrettyOptions -> Transform PrettyC HermitM a b -> Transform c HermitM a b liftPrettyH = liftContext . liftPrettyC  liftPrettyC :: (ReadBindings c, ReadPath c Crumb) => PrettyOptions -> c -> PrettyC@@ -206,7 +235,7 @@         , po_width           :: Int         } deriving Show -data ShowOption = Show | Abstract | Omit | Kind deriving (Eq, Ord, Show, Read)+data ShowOption = Show | Abstract | Detailed | Omit | Kind deriving (Eq, Ord, Show, Read)  -- Types don't have a Kind showing option. updateTypeShowOption :: ShowOption -> PrettyOptions -> PrettyOptions@@ -282,7 +311,7 @@         renderSpecial CoercionBindSymbol  = ASCII "~#"   -- <<coercion binding>>>         renderSpecial TypeSymbol          = ASCII "*"    -- <<type>>>         renderSpecial TypeBindSymbol      = ASCII "*"    -- <<type binding>>>-        renderSpecial ForallSymbol        = ASCII "\\/"+        renderSpecial ForallSymbol        = ASCII "forall"  newtype Unicode = Unicode Char 
src/HERMIT/PrettyPrinter/GHC.hs view
@@ -1,7 +1,8 @@ -- | Output the raw Expr constructors. Helpful for writing pattern matching rewrites. module HERMIT.PrettyPrinter.GHC   ( -- * GHC's standard Pretty-Printer for GHC Core-    pretty+    externals+  , pretty   , ppCoreTC   , ppModGuts   , ppCoreProg@@ -17,16 +18,21 @@ import Control.Arrow hiding ((<+>))  import Data.Char (isSpace)-import Data.Default+import Data.Default.Class -import HERMIT.Kure import HERMIT.Core+import HERMIT.External import HERMIT.GHC hiding ((<+>), (<>), char, text, parens, hsep, empty)+import HERMIT.Kure+ import HERMIT.PrettyPrinter.Common  import Text.PrettyPrint.MarkedHughesPJ as PP  ---------------------------------------------------------------------------++externals :: [External]+externals = [ external "ghc" pretty ["GHC pretty printer."] ]  pretty :: PrettyPrinter pretty = PP { pForall = ppForallQuantification
src/HERMIT/Shell/Command.hs view
@@ -1,9 +1,17 @@-{-# LANGUAGE ConstraintKinds, CPP, FlexibleContexts, GADTs, LambdaCase, ScopedTypeVariables, TypeFamilies #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MultiWayIf #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}  module HERMIT.Shell.Command     ( -- * The HERMIT Command-line Shell       commandLine-    , interpShellCommand+    , interpShell     , unicodeConsole     , diffDocH     , diffR@@ -11,7 +19,6 @@     , performQuery     , cl_kernel_env     , getFocusPath-    , shellComplete     , evalScript     ) where @@ -25,11 +32,9 @@ import HERMIT.Context import HERMIT.External import qualified HERMIT.GHC as GHC-import HERMIT.Kernel.Scoped hiding (abortS, resumeS) import HERMIT.Kure import HERMIT.Parser -import HERMIT.Plugin.Display import HERMIT.Plugin.Renderer  import HERMIT.PrettyPrinter.Common@@ -92,27 +97,19 @@  -- | The first argument includes a list of files to load. commandLine :: forall m. (MonadCatch m, MonadException m, CLMonad m)-            => [Interp m ()] -> [GHC.CommandLineOption] -> [External] -> m ()-commandLine intp opts exts = do+            => [GHC.CommandLineOption] -> [External] -> m ()+commandLine opts exts = do     let (flags, filesToLoad) = partition (isPrefixOf "-") opts-        ws_complete = " ()"--    modify $ \ st -> st { cl_externals = shell_externals ++ exts }--    let loop :: InputT m ()-        loop = do-            st <- lift get-            let SAST n = cl_cursor st-            mLine <- if cl_nav st-                     then liftIO getNavCmd-                     else getInputLine $ "hermit<" ++ show n ++ "> "+        ws_complete = " ()" -- treated as 'whitespace' by completer+        safeMode = "-safety=strict" `elem` flags+        unsafeMode = "-safety=unsafe" `elem` flags+        safetyMode = if | unsafeMode -> NoSafety+                        | safeMode   -> StrictSafety+                        | otherwise  -> NormalSafety -            case mLine of-                Nothing          -> lift $ performShellEffect Resume-                Just ('-':'-':_) -> loop-                Just line        -> if all isSpace line-                                    then loop-                                    else lift (evalScript intp line `catchFailHard` cl_putStrLn) >> loop+    modify $ \ st -> st { cl_externals = filterSafety safetyMode $ shell_externals ++ exts+                        , cl_safety = safetyMode+                        }      -- Display the banner     if any (`elem` ["-v0", "-v1"]) flags@@ -129,57 +126,87 @@     -- Load and run any scripts     setRunningScript $ Just []     sequence_ [ case fileName of-                 "abort"  -> performShellEffect Abort-                 "resume" -> performShellEffect Resume-                 _        -> performScriptEffect (runExprH intp) $ loadAndRun fileName+                 "abort"  -> parseScriptCLT "abort" >>= pushScript+                 "resume" -> parseScriptCLT "resume" >>= pushScript+                 _        -> fileToScript fileName >>= pushScript               | fileName <- reverse filesToLoad               , not (null fileName)               ] `catchFailHard` \ msg -> cl_putStrLn $ "Booting Failure: " ++ msg-    setRunningScript Nothing +    let -- Main proof input loop+        loop :: InputT m ()+        loop = do+            el <- lift $ do tryM () announceProven+                            tryM () forceProofs+                            attemptM currentLemma+            let prompt = either (const "hermit") (const "proof") el+            mExpr <- lift popScriptLine+            case mExpr of+                Nothing -> do -- no script running+                    lift $ ifM isRunningScript (return ()) (showWindow Nothing)+                            `catchFailHard` (cl_putStrLn . ("cannot showWindow: " ++))+                    st <- lift get+                    mLine <- if cl_nav st+                             then liftIO getNavCmd+                             else getInputLine $ prompt ++ "<" ++ show (cl_cursor st) ++ "> "++                    case mLine of+                        Nothing          -> lift $ performShellEffect Resume+                        Just ('-':'-':_) -> loop+                        Just line        -> if all isSpace line+                                            then loop+                                            else lift (evalScript line `catchFailHard` cl_putStrLn) >> loop+                Just e -> lift (runExprH e `catchFailHard` (\ msg -> setRunningScript Nothing >> cl_putStrLn msg)) >> loop+     -- Start the CLI-    showWindow-    let settings = setComplete (completeWordWithPrev Nothing ws_complete shellComplete) defaultSettings+    let settings = setComplete (completeWordWithPrev Nothing ws_complete completer) defaultSettings     runInputT settings loop  -- | Like 'catchM', but checks the 'cl_failhard' setting and does so if needed. catchFailHard :: (MonadCatch m, CLMonad m) => m () -> (String -> m ()) -> m ()-catchFailHard m failure = catchM m $ \ msg -> ifM (gets cl_failhard) (performQuery Display (CmdName "display") >> cl_putStrLn msg >> abort) (failure msg)+catchFailHard m failure =+    catchM m $ \ msg -> ifM (gets cl_failhard)+                            (do pp <- gets cl_pretty+                                performQuery (QueryPrettyH $ pCoreTC pp) (CmdName "display")+                                cl_putStrLn msg+                                abort)+                            (failure msg) -evalScript :: (MonadCatch m, CLMonad m) => [Interp m ()] -> String -> m ()-evalScript intp = parseScriptCLT >=> mapM_ (runExprH intp)+evalScript :: (MonadCatch m, CLMonad m) => String -> m ()+evalScript = parseScriptCLT >=> mapM_ runExprH -runExprH :: (MonadCatch m, CLMonad m) => [Interp m ()] -> ExprH -> m ()-runExprH intp expr = prefixFailMsg ("Error in expression: " ++ unparseExprH expr ++ "\n") $ interpExprH intp expr+runExprH :: (MonadCatch m, CLMonad m) => ExprH -> m ()+runExprH expr = prefixFailMsg ("Error in expression: " ++ unparseExprH expr ++ "\n") $ do+    ps <- getProofStackEmpty+    (if null ps then id else withProofExternals) $ interpExprH interpShell expr  -- | Interpret a boxed thing as one of the four possible shell command types.-interpShellCommand :: (MonadCatch m, MonadException m, CLMonad m) => [Interp m ()]-interpShellCommand =-  [ interpEM $ \ (RewriteCoreBox rr)           -> applyRewrite rr-  , interpEM $ \ (RewriteCoreTCBox rr)         -> applyRewrite rr-  , interpEM $ \ (BiRewriteCoreBox br)         -> applyRewrite $ whicheverR br-  , interpEM $ \ (CrumbBox cr)                 -> setPath (return (mempty @@ cr) :: TransformH CoreTC LocalPathH)-  , interpEM $ \ (PathBox p)                   -> setPath (return p :: TransformH CoreTC LocalPathH)-  , interpEM $ \ (TransformCorePathBox tt)     -> setPath tt-  , interpEM $ \ (TransformCoreTCPathBox tt)   -> setPath tt-  , interpEM $ \ (StringBox str)               -> performQuery (message str)-  , interpEM $ \ (TransformCoreStringBox tt)   -> performQuery (QueryString tt)-  , interpEM $ \ (TransformCoreTCStringBox tt) -> performQuery (QueryString tt)-  , interpEM $ \ (TransformCoreTCDocHBox tt)   -> performQuery (QueryDocH $ unTransformDocH tt)-  , interpEM $ \ (TransformCoreCheckBox tt)    -> performQuery (CorrectnessCritera tt)-  , interpEM $ \ (TransformCoreTCCheckBox tt)  -> performQuery (CorrectnessCritera tt)-  , interpEM $ \ (effect :: KernelEffect)      -> flip performKernelEffect effect-  , interpM  $ \ (effect :: ShellEffect)       -> performShellEffect effect-  , interpM  $ \ (effect :: ScriptEffect)      -> performScriptEffect (runExprH interpShellCommand) effect-  , interpEM $ \ (query :: QueryFun)           -> performQuery query-  , interpM  $ \ (cmd :: ProofCommand)         -> performProofCommand cmd+interpShell :: (MonadCatch m, CLMonad m) => [Interp m ()]+interpShell =+  [ interpEM $ \ (CrumbBox cr)                  -> setPath (return (mempty @@ cr) :: TransformH LCoreTC LocalPathH)+  , interpEM $ \ (PathBox p)                    -> setPath (return p :: TransformH LCoreTC LocalPathH)+  , interpEM $ \ (StringBox str)                -> performQuery (message str)+  , interpEM $ \ (effect :: KernelEffect)       -> flip performKernelEffect effect+  , interpM  $ \ (effect :: ShellEffect)        -> performShellEffect effect+  , interpM  $ \ (effect :: ScriptEffect)       -> performScriptEffect effect+  , interpEM $ \ (query :: QueryFun)            -> performQuery query+  , interpEM $ \ (t :: UserProofTechnique)      -> performProofShellCommand $ PCUser t+  , interpEM $ \ (cmd :: ProofShellCommand)     -> performProofShellCommand cmd+  , interpEM $ \ (TransformLCoreStringBox tt)   -> performQuery (QueryString tt)+  , interpEM $ \ (TransformLCoreTCStringBox tt) -> performQuery (QueryString tt)+  , interpEM $ \ (TransformLCoreUnitBox tt)     -> performQuery (QueryUnit tt)+  , interpEM $ \ (TransformLCoreTCUnitBox tt)   -> performQuery (QueryUnit tt)+  , interpEM $ \ (TransformLCorePathBox tt)     -> setPath tt+  , interpEM $ \ (TransformLCoreTCPathBox tt)   -> setPath tt+  , interpEM $ \ (TransformLCoreDocHBox t)      -> performQuery (QueryDocH t)+  , interpEM $ \ (TransformLCoreTCDocHBox t)      -> performQuery (QueryDocH t)+  , interpEM $ \ (RewriteLCoreBox rr)           -> applyRewrite $ promoteLCoreR rr+  , interpEM $ \ (RewriteLCoreTCBox rr)         -> applyRewrite rr+  , interpEM $ \ (BiRewriteLCoreBox br)         -> applyRewrite $ promoteLCoreR $ whicheverR br+  , interpEM $ \ (BiRewriteLCoreTCBox br)       -> applyRewrite $ whicheverR br+  , interpEM $ \ (PrettyHLCoreBox t)            -> performQuery (QueryPrettyH t)+  , interpEM $ \ (PrettyHLCoreTCBox t)          -> performQuery (QueryPrettyH t)   ]------------------------------------------------------------------------------------- TODO: This can be refactored. We always showWindow. Also, Perhaps return a modifier, not ()---   UPDATE: Not true.  We don't always showWindow.--- TODO: All of these should through an exception if they fail to execute the command as given.  ------------------------------------------------------------------------------- 
src/HERMIT/Shell/Completion.hs view
@@ -1,5 +1,7 @@-{-# LANGUAGE FlexibleContexts, LambdaCase #-}-module HERMIT.Shell.Completion (shellComplete) where+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE LambdaCase #-}+module HERMIT.Shell.Completion (completer) where  import Control.Applicative import Control.Arrow@@ -7,14 +9,13 @@  import Data.Dynamic import Data.List (isPrefixOf, nub)-import Data.Map (keys)+import qualified Data.Map as M import Data.Maybe (fromMaybe)  import HERMIT.Kure import HERMIT.External import qualified HERMIT.GHC as GHC-import HERMIT.Kernel.Scoped-import HERMIT.Monad+import HERMIT.Kernel import HERMIT.Parser  import HERMIT.Dictionary.Inline@@ -23,13 +24,21 @@ import HERMIT.Dictionary.Rules  import HERMIT.Shell.Interpreter+import HERMIT.Shell.Proof import HERMIT.Shell.Types  import System.Console.Haskeline hiding (catch, display)  ---------------------------------------------------------------------------------- -shellComplete :: (MonadCatch m, MonadIO m, MonadState CommandLineState m) => String -> String -> m [Completion]+completer :: (MonadCatch m, CLMonad m) => String -> String -> m [Completion]+completer rPrev so_far = do+    ps <- getProofStackEmpty+    case ps of+        [] -> shellComplete rPrev so_far+        _  -> withProofExternals $ shellComplete rPrev so_far++shellComplete :: (MonadCatch m, CLMonad m) => String -> String -> m [Completion] shellComplete rPrev so_far = do     let (partial, _) = toUnmatched rPrev     if null partial@@ -46,15 +55,14 @@                                              , not (null args) ]                         completionsFor so_far $ filterUnknowns $ map (completionType.show) ts -completionsFor :: (MonadCatch m, MonadIO m, MonadState CommandLineState m)+completionsFor :: (MonadCatch m, CLMonad m)                => String -> [CompletionType] -> m [Completion] completionsFor so_far cts = do     qs <- mapM completionQuery cts-    (k,(env,sast)) <- gets (cl_kernel &&& cl_kernel_env &&& cl_cursor)-    cls <- forM qs $ \ q -> catchM (queryS k q env sast) (\_ -> return [])+    cls <- forM qs $ \ q -> queryInContext q Never `catchM` (\_ -> return [])     return $ map simpleCompletion $ nub $ filter (so_far `isPrefixOf`) $ concat cls -data CompletionType = ConsiderC       -- considerable constructs and (deprecated) bindingOfT+data CompletionType = ConsiderC       -- considerable constructs                     | BindingOfC      -- bindingOfT                     | BindingGroupOfC -- bindingGroupOfT                     | RhsOfC          -- rhsOfT@@ -66,7 +74,6 @@                     | CoreC           -- complete with opening Core fragment bracket [|                     | NothingC        -- no completion                     | RuleC           -- complete with GHC rewrite rule name-                    | StashC          -- complete with remembered labels                     | StringC         -- complete with open quotes                     | UnknownC String -- unknown Extern instance (empty completion) @@ -79,7 +86,6 @@               , ("IntBox"        , NothingC)               , ("LemmaName"     , LemmaC)               , ("OccurrenceName", OccurrenceOfC)-              , ("RememberedName", StashC)               , ("RewriteCoreBox", CommandC) -- be more specific than CommandC?               , ("RhsOfName"     , RhsOfC)               , ("RuleName"      , RuleC)@@ -90,18 +96,23 @@ filterUnknowns l = if null l' then l else l'     where l' = filter (\case UnknownC _ -> False ; _ -> True) l -completionQuery :: (MonadIO m, MonadState CommandLineState m) => CompletionType -> m (TransformH CoreTC [String])+completionQuery :: (MonadIO m, MonadState CommandLineState m) => CompletionType -> m (TransformH LCoreTC [String]) completionQuery ConsiderC       = return $ pure $ map fst considerables-completionQuery OccurrenceOfC   = return $ occurrenceOfTargetsT    >>^ GHC.varSetToStrings >>^ map ('\'':)-completionQuery BindingOfC      = return $ bindingOfTargetsT       >>^ GHC.varSetToStrings >>^ map ('\'':)-completionQuery BindingGroupOfC = return $ bindingGroupOfTargetsT  >>^ GHC.varSetToStrings >>^ map ('\'':)-completionQuery RhsOfC          = return $ rhsOfTargetsT           >>^ GHC.varSetToStrings >>^ map ('\'':)-completionQuery InlineC         = return $ promoteT inlineTargetsT >>^                         map ('\'':)+completionQuery OccurrenceOfC   = return $ occurrenceOfTargetsT   >>^ GHC.varSetToStrings >>^ map ('\'':)+completionQuery BindingOfC      = return $ bindingOfTargetsT      >>^ GHC.varSetToStrings >>^ map ('\'':)+completionQuery BindingGroupOfC = return $ bindingGroupOfTargetsT >>^ GHC.varSetToStrings >>^ map ('\'':)+completionQuery RhsOfC          = return $ rhsOfTargetsT          >>^ GHC.varSetToStrings >>^ map ('\'':)+completionQuery InlineC         = return $ promoteLCoreT inlineTargetsT >>^                   map ('\'':) completionQuery InScopeC        = return $ pure ["'"] -- TODO-completionQuery LemmaC          = return $ liftM (map show . keys) $ getLemmasT+completionQuery LemmaC          = do+    let findTemps [] = []+        findTemps (pt@(Unproven {}) : _) = map (show . fst) (ptAssumed pt)+        findTemps (_ : r) = findTemps r+    cur <- gets cl_cursor+    tempLemmas <- gets (findTemps . fromMaybe [] . M.lookup cur . cl_proofstack)+    return $ liftM ((tempLemmas ++) . map show . M.keys) $ getLemmasT completionQuery NothingC        = return $ pure [] completionQuery RuleC           = return $ liftM (map (show . fst)) $ getHermitRulesT-completionQuery StashC          = return $ liftM (map show . keys) $ constT getStash completionQuery StringC         = return $ pure ["\""] completionQuery CommandC        = gets cl_externals >>= return . pure . map externName completionQuery CoreC           = return $ pure ["[|"]@@ -124,4 +135,3 @@           go n acc (')':cs) = go (n+1) (')':acc) cs           go n acc (c:cs)   = go n     (c:acc)   cs           go _ acc []       = (acc, [])-
src/HERMIT/Shell/Externals.hs view
@@ -2,21 +2,25 @@  module HERMIT.Shell.Externals where -import Control.Applicative+import Control.Arrow+import Control.Monad (liftM) +import Data.Dynamic (fromDynamic) import Data.List (intercalate) import qualified Data.Map as M-import Control.Monad (liftM)-import Data.Dynamic (fromDynamic)+import Data.Maybe (fromMaybe)+import Data.Monoid (mempty) -import HERMIT.Context-import HERMIT.Kure import HERMIT.External-import HERMIT.Kernel.Scoped+import HERMIT.Kernel+import HERMIT.Kure+import HERMIT.Lemma import HERMIT.Parser import HERMIT.Plugin.Renderer import HERMIT.PrettyPrinter.Common +import HERMIT.Dictionary.Reasoning+ import HERMIT.Shell.Dictionary import HERMIT.Shell.KernelEffect import HERMIT.Shell.Proof as Proof@@ -28,221 +32,220 @@  shell_externals :: [External] shell_externals = map (.+ Shell)-   [-     external "resume"          Resume    -- HERMIT Kernel Exit-       [ "stops HERMIT; resumes compile" ]-   , external "abort"           Abort     -- UNIX Exit-       [ "hard UNIX-style exit; does not return to GHC; does not save" ]-   , external "continue"        Continue  -- Shell Exit, but not HERMIT-       [ "exits shell; resumes HERMIT" ]-   , external "gc"              (Delete . SAST)-       [ "garbage-collect a given AST; does not remove from command log" ]-   , external "gc"              (CLSModify gc)-       [ "garbage-collect all ASTs except for the initial and current AST" ]-   , external "display"         Display-       [ "redisplays current state" ]-   , external "left"            (Direction L)-       [ "move to the next child"]-   , external "right"           (Direction R)-       [ "move to the previous child"]-   , external "up"              (Direction U)-       [ "move to the parent node"]-   , external "down"            (deprecatedIntToPathT 0 :: TransformH Core LocalPathH) -- TODO: short-term solution-       [ "move to the first child"]-   , external "navigate"        (CLSModify $ \ st -> return $ st { cl_nav = True })-       [ "switch to navigate mode" ]-   , external "command-line"    (CLSModify $ \ st -> return $ st { cl_nav = False })-       [ "switch to command line mode" ]-   , external "set-window"      (CLSModify setWindow)-       [ "fix the window to the current focus" ]-   , external "top"             (Direction T)-       [ "move to root of current scope" ]-   , external "back"            (CLSModify $ versionCmd Back)-       [ "go back in the derivation" ]                                          .+ VersionControl-   , external "log"             (Inquiry showDerivationTree)-       [ "go back in the derivation" ]                                          .+ VersionControl-   , external "step"            (CLSModify $ versionCmd Step)-       [ "step forward in the derivation" ]                                     .+ VersionControl-   , external "goto"            (CLSModify . versionCmd . Goto)-       [ "goto a specific step in the derivation" ]                             .+ VersionControl-   , external "goto"            (CLSModify . versionCmd . GotoTag)-       [ "goto a named step in the derivation" ]-   , external "tag"             (CLSModify . versionCmd . AddTag)-       [ "tag <label> names the current AST with a label" ]                     .+ VersionControl-   , external "diff"            (\ s1 s2 -> Diff (SAST s1) (SAST s2))-       [ "show diff of two ASTs" ]                                              .+ VersionControl-   , external "set-pp-diffonly" (\ bStr -> CLSModify $ \ st ->+    [ external "resume"          Resume    -- HERMIT Kernel Exit+        [ "stops HERMIT; resumes compile" ]+    , external "abort"           Abort     -- UNIX Exit+        [ "hard UNIX-style exit; does not return to GHC; does not save" ]+    , external "continue"        Continue  -- Shell Exit, but not HERMIT+        [ "exits shell; resumes HERMIT" ]+    , external "gc"              Delete+        [ "garbage-collect a given AST" ]+    , external "gc"              (CLSModify $ liftM Right . gc)+        [ "garbage-collect all ASTs except for the initial and current AST" ]+    , external "display"         (CLSModify $ \ st -> do (er,st') <- runCLT st (showWindow Nothing)+                                                         return $ fmap (const st') er)+        [ "redisplays current state" ]+    , external "up"              (Direction U)+        [ "move to the parent node"]+    , external "navigate"        (CLSModify $ \ st -> return $ Right $ st { cl_nav = True })+        [ "switch to navigate mode" ]+    , external "command-line"    (CLSModify $ \ st -> return $ Right $ st { cl_nav = False })+        [ "switch to command line mode" ]+    , external "set-window"      (CLSModify setWindow)+        [ "fix the window to the current focus" ]+    , external "top"             (Direction T)+        [ "move to root of current scope" ]+    , external "log"             (Inquiry showDerivationTree)+        [ "go back in the derivation" ]                                          .+ VersionControl+    , external "back"            (CLSModify $ versionCmd Back)+        [ "go back in the derivation" ]                                          .+ VersionControl+    , external "step"            (CLSModify $ versionCmd Step)+        [ "step forward in the derivation" ]                                     .+ VersionControl+    , external "goto"            (CLSModify . versionCmd . Goto)+        [ "goto a specific step in the derivation" ]                             .+ VersionControl+    , external "goto"            (CLSModify . versionCmd . GotoTag)+        [ "goto a specific step in the derivation by tag name" ]                 .+ VersionControl+    , external "tag"             (CLSModify . versionCmd . Tag)+        [ "name the current step in the derivation" ]                            .+ VersionControl+    , external "diff"            Diff+        [ "show diff of two ASTs" ]                                              .+ VersionControl+    , external "set-pp-diffonly" (\ bStr -> CLSModify $ \ st ->         case reads bStr of-            [(b,"")] -> return $ setDiffOnly st b-            _        -> return st)-       [ "set-pp-diffonly <True|False>; False by default"-       , "print diffs rather than full code after a rewrite" ]-   , external "set-fail-hard"   (\ bStr -> CLSModify $ \ st ->+            [(b,"")] -> return $ Right $ setDiffOnly st b+            _        -> return $ Left $ CLError "valid arguments are True and False" )+        [ "set-pp-diffonly <True|False>; False by default"+        , "print diffs rather than full code after a rewrite" ]+    , external "set-fail-hard"   (\ bStr -> CLSModify $ \ st ->         case reads bStr of-            [(b,"")] -> return $ setFailHard st b-            _        -> return st)-       [ "set-fail-hard <True|False>; False by default"-       , "any rewrite failure causes compilation to abort" ]-   , external "set-auto-corelint" (\ bStr -> CLSModify $ \ st ->+            [(b,"")] -> return $ Right $ setFailHard st b+            _        -> return $ Left $ CLError "valid arguments are True and False" )+        [ "set-fail-hard <True|False>; False by default"+        , "any rewrite failure causes compilation to abort" ]+    , external "set-auto-corelint" (\ bStr -> CLSModify $ \ st ->         case reads bStr of-            [(b,"")] -> return $ setCoreLint st b-            _        -> return st )-       [ "set-auto-corelint <True|False>; False by default"-       , "run core lint type-checker after every rewrite, reverting on failure" ]-   , external "set-pp"          (\ name -> CLSModify $ \ st ->-       case M.lookup name pp_dictionary of-         Nothing -> do-            putStrLn $ "List of Pretty Printers: " ++ intercalate ", " (M.keys pp_dictionary)-            return st-         Just pp -> return $ flip setPrettyOpts (cl_pretty_opts st) $ setPretty st pp) -- careful to preserve the current options-       [ "set the pretty printer"-       , "use 'set-pp ls' to list available pretty printers" ]-   , external "set-pp-renderer"    (PluginComp . changeRenderer)-       [ "set the output renderer mode"]-   , external "set-pp-renderer"    showRenderers-       [ "set the output renderer mode"]-   , external "dump" (Dump (\st -> liftPrettyH (cl_pretty_opts st) $ pCoreTC $ cl_pretty st))-       [ "dump <filename> <renderer> <width>"]-   , external "set-pp-width" (\ w -> CLSModify $ \ st ->-        return $ setPrettyOpts st (updateWidthOption w (cl_pretty_opts st)))-       ["set the width of the screen"]-   , external "set-pp-type" (\ str -> CLSModify $ \ st ->+            [(b,"")] -> return $ Right $ setCoreLint st b+            _        -> return $ Left $ CLError "valid arguments are True and False" )+        [ "set-auto-corelint <True|False>; False by default"+        , "run core lint type-checker after every rewrite, reverting on failure" ]+    , external "set-pp"          (\ name -> CLSModify $ \ st ->+        case M.lookup name pp_dictionary of+            Nothing -> return $ Left $ CLError $ "List of Pretty Printers: " ++ intercalate ", " (M.keys pp_dictionary)+            Just pp -> return $ Right $ flip setPrettyOpts (cl_pretty_opts st) $ setPretty st pp) -- careful to preserve the current options+        [ "set the pretty printer"+        , "use 'set-pp ls' to list available pretty printers" ]+    , external "set-pp-renderer"    (PluginComp . changeRenderer)+        [ "set the output renderer mode"]+    , external "set-pp-renderer"    showRenderers+        [ "set the output renderer mode"]+    , -- DEPRECATED - this dump behavior uses the current pretty printer selected in the shell+      external "dump" (\pp fp r w -> CLSModify (dump fp pp r w))+        [ "dump <filename> <renderer> <width> - DEPRECATED"]+    , external "dump" (\fp pp r w -> CLSModify (dump fp pp r w))+        [ "dump <filename> <pretty-printer> <renderer> <width>"]+    , external "dump-lemma" ((\nm fp pp r w -> getLemmaByNameT nm >>> liftPrettyH (pOptions pp) (ppLemmaT pp nm) >>> dumpT fp pp r w) :: LemmaName -> FilePath -> PrettyPrinter -> String -> Int -> TransformH LCoreTC ())+        [ "Dump named lemma to a file."+        , "dump-lemma <lemma-name> <filename> <pretty-printer> <renderer> <width>" ]+    , external "dump-lemma" ((\pp nm fp r w -> getLemmaByNameT nm >>> liftPrettyH (pOptions pp) (ppLemmaT pp nm) >>> dumpT fp pp r w) :: PrettyPrinter -> LemmaName -> FilePath -> String -> Int -> TransformH LCoreTC ())+        [ "Dump named lemma to a file."+        , "dump-lemma <lemma-name> <filename> <pretty-printer> <renderer> <width>" ]+    , external "set-pp-width" (\ w -> CLSModify $ \ st ->+            return $ Right $ setPrettyOpts st (updateWidthOption w (cl_pretty_opts st)))+        ["set the width of the screen"]+    , external "set-pp-type" (\ str -> CLSModify $ \ st ->         case reads str :: [(ShowOption,String)] of-            [(opt,"")] -> return $ setPrettyOpts st (updateTypeShowOption opt (cl_pretty_opts st))-            _          -> return st)-       ["set how to show expression-level types (Show|Abstact|Omit)"]-   , external "set-pp-coercion" (\ str -> CLSModify $ \ st ->+            [(opt,"")] -> return $ Right $ setPrettyOpts st (updateTypeShowOption opt (cl_pretty_opts st))+            _          -> return $ Left $ CLError "valid arguments are Show, Abstract, and Omit")+        ["set how to show expression-level types (Show|Abstact|Omit)"]+    , external "set-pp-coercion" (\ str -> CLSModify $ \ st ->         case reads str :: [(ShowOption,String)] of-            [(opt,"")] -> return $ setPrettyOpts st (updateCoShowOption opt (cl_pretty_opts st))-            _          -> return st)-       ["set how to show coercions (Show|Abstact|Omit)"]-   , external "set-pp-uniques" (\ str -> CLSModify $ \ st ->+            [(opt,"")] -> return $ Right $ setPrettyOpts st (updateCoShowOption opt (cl_pretty_opts st))+            _          -> return $ Left $ CLError "valid arguments are Show, Abstract, and Omit")+        ["set how to show coercions (Show|Abstact|Omit)"]+    , external "set-pp-uniques" (\ str -> CLSModify $ \ st ->         case reads str of-            [(b,"")] -> return $ setPrettyOpts st ((cl_pretty_opts st) { po_showUniques = b } )-            _        -> return st)-       ["set whether uniques are printed with variable names"]-   , external "{"   BeginScope-       ["push current lens onto a stack"]       -- tag as internal-   , external "}"   EndScope-       ["pop a lens off a stack"]               -- tag as internal-   , external "load"  LoadFile-       ["load <script-name> <file-name> : load a HERMIT script from a file and save it under the specified name."]-   , external "load-and-run"  loadAndRun-       ["load-and-run <file-name> : load a HERMIT script from a file and run it immediately."]-   , external "save"  SaveFile-       ["save <filename> : save the current complete derivation into a file."]-   , external "save-script" SaveScript-       ["save-script <filename> <script name> : save a loaded or manually defined script to a file." ]-   , external "load-as-rewrite" (\ rewriteName fileName -> SeqMeta [LoadFile rewriteName fileName, ScriptToRewrite rewriteName rewriteName])-       ["load-as-rewrite <rewrite-name> <filepath> : load a HERMIT script from a file, and convert it to a rewrite."-       ,"Note that there are significant limitations on the commands the script may contain."] .+ Experiment .+ TODO-   , external "script-to-rewrite" ScriptToRewrite-       ["script-to-rewrite <rewrite-name> <script-name> : create a new rewrite from a pre-loaded (or manually defined) HERMIT script."-       ,"Note that there are significant limitations on the commands the script may contain."] .+ Experiment .+ TODO-   , external "define-script" DefineScript-       ["Define a new HERMIT script and bind it to a name."-       ,"Note that any names in the script will not be resolved until the script is *run*."-       ,"Example usage: define-script \"MyScriptName\" \"any-td beta-reduce ; let-subst ; bash\""]-   , external "define-rewrite" (\ name str -> SeqMeta [DefineScript name str, ScriptToRewrite name name])-       ["Define a new HERMIT rewrite and bind it to a name."-       ,"Note that this also saves the input script under the same name."-       ,"Example usage: define-rewrite \"MyRewriteName\" \"let-subst >>> bash\""]-   , external "run-script" RunScript-       ["Run a pre-loaded (or manually defined) HERMIT script."-       ,"Note that any names in the script will not be resolved until the script is *run*." ]-   , external "display-scripts" displayScripts-       ["Display all loaded scripts."]-   , external "stop-script" (CLSModify $ \st -> return $ st { cl_running_script = Nothing })-       [ "Stop running the current script." ]-   --, external "test-rewrites" (testRewrites :: [(ExternalName,RewriteH Core)] -> TransformH Core String) ["Test a given set of rewrites to see if they succeed"] .+ Experiment-   , external "possible-rewrites" (testAllT:: CommandLineState-> TransformH Core String) ["Test all given set of rewrites to see if they succeed"] .+ Experiment-     -- TODO: maybe add a "list-scripts" as well that just lists the names of loaded scripts?-   ] ++ Proof.externals+            [(b,"")] -> return $ Right $ setPrettyOpts st ((cl_pretty_opts st) { po_showUniques = b } )+            _        -> return $ Left $ CLError "valid arguments are True and False")+        ["set whether uniques are printed with variable names"]+    , external "{"   BeginScope+        ["push current lens onto a stack"]       -- tag as internal+    , external "}"   EndScope+        ["pop a lens off a stack"]               -- tag as internal+    , external "load"  LoadFile+        ["load <script-name> <file-name> : load a HERMIT script from a file and save it under the specified name."]+    , external "load-and-run"  loadAndRun+        ["load-and-run <file-name> : load a HERMIT script from a file and run it immediately."]+    , external "save"  (SaveFile False)+        ["save <filename> : save the current complete derivation into a file."]+    , external "save-verbose"  (SaveFile True)+        ["save-verbose <filename> : save the current complete derivation into a file,"+        ,"including output of each command as a comment."]+    , external "save-script" SaveScript+        ["save-script <filename> <script name> : save a loaded or manually defined script to a file." ]+    , external "load-as-rewrite" (\ rewriteName fileName -> SeqMeta [LoadFile rewriteName fileName, ScriptToRewrite rewriteName rewriteName])+        ["load-as-rewrite <rewrite-name> <filepath> : load a HERMIT script from a file, and convert it to a rewrite."+        ,"Note that there are significant limitations on the commands the script may contain."] .+ Experiment .+ TODO+    , external "script-to-rewrite" ScriptToRewrite+        ["script-to-rewrite <rewrite-name> <script-name> : create a new rewrite from a pre-loaded (or manually defined) HERMIT script."+        ,"Note that there are significant limitations on the commands the script may contain."] .+ Experiment .+ TODO+    , external "define-script" DefineScript+        ["Define a new HERMIT script and bind it to a name."+        ,"Note that any names in the script will not be resolved until the script is *run*."+        ,"Example usage: define-script \"MyScriptName\" \"any-td beta-reduce ; let-subst ; bash\""]+    , external "define-rewrite" (\ name str -> SeqMeta [DefineScript name str, ScriptToRewrite name name])+        ["Define a new HERMIT rewrite and bind it to a name."+        ,"Note that this also saves the input script under the same name."+        ,"Example usage: define-rewrite \"MyRewriteName\" \"let-subst >>> bash\""]+    , external "run-script" RunScript+        ["Run a pre-loaded (or manually defined) HERMIT script."+        ,"Note that any names in the script will not be resolved until the script is *run*." ]+    , external "display-scripts" displayScripts+        ["Display all loaded scripts."]+    , external "stop-script" (CLSModify $ \st -> return $ Right $ st { cl_running_script = Nothing })+        [ "Stop running the current script." ]+    --, external "test-rewrites" (testRewrites :: [(ExternalName,RewriteH Core)] -> TransformH Core String)+    --  ["Test a given set of rewrites to see if they succeed"] .+ Experiment+    , external "possible-rewrites" (testAllT:: CommandLineState -> TransformH LCore String)+        ["Test all given set of rewrites to see if they succeed"] .+ Experiment+    -- TODO: maybe add a "list-scripts" as well that just lists the names of loaded scripts?+    ] ++ Proof.externals  gc :: CommandLineState -> IO CommandLineState gc st = do     let k = cl_kernel st         cursor = cl_cursor st-        initSAST = cl_initSAST st-    asts <- listS k-    mapM_ (deleteS k) [ sast | sast <- asts, sast `notElem` [cursor, initSAST] ]+    asts <- listK k+    mapM_ (deleteK k) [ ast | (ast,_,_) <- asts, ast `notElem` [cursor, firstAST] ]     return st  ---------------------------------------------------------------------------------- -setWindow :: CommandLineState -> IO CommandLineState+setWindow :: CommandLineState -> IO (Either CLException CommandLineState) setWindow st = do-    paths <- concat <$> pathS (cl_kernel st) (cl_cursor st)-    return $ st { cl_window = paths }+    let ps = fromMaybe ([],mempty) (M.lookup (cl_cursor st) (cl_foci st))+    return $ Right $ st { cl_window = pathStack2Path ps }  showRenderers :: QueryFun showRenderers = message $ "set-renderer " ++ show (map fst shellRenderers)  -------------------------------------------------------- -versionCmd :: VersionCmd -> CommandLineState -> IO CommandLineState-versionCmd whereTo st =+versionCmd :: VersionCmd -> CommandLineState -> IO (Either CLException CommandLineState)+versionCmd whereTo st = do+    all_asts <- listK (cl_kernel st)     case whereTo of-        Goto n -> do-            all_nds <- listS (cl_kernel st)-            if SAST n `elem` all_nds-                then return $ setCursor st (SAST n)-                else fail $ "Cannot find AST #" ++ show n ++ "."-        GotoTag tag -> case lookup tag (vs_tags (cl_version st)) of-                        Just sast -> return $ setCursor st sast-                        Nothing   -> fail $ "Cannot find tag " ++ show tag ++ "."+        Goto ast ->+            if ast `elem` [ ast' | (ast',_,_) <- all_asts ]+                then return $ Right $ setCursor ast st+                else return $ Left $ CLError $ "Cannot find AST #" ++ show ast ++ "."+        GotoTag nm ->+            case [ ast | (ast,nms) <- M.toList (cl_tags st), nm `elem` nms ] of+                [] -> return $ Left $ CLError $ "No tag named: " ++ nm+                (ast:_) -> return $ Right $ setCursor ast st+        Tag nm ->+            return $ Right $ st { cl_tags = M.insertWith (++) (cl_cursor st) [nm] (cl_tags st) }         Step -> do-            let ns = [ edge | edge@(s,_,_) <- vs_graph (cl_version st), s == cl_cursor st ]+            let ns = [ (fromMaybe "unknown" msg, ast) | (ast,msg,Just p) <- all_asts, p == cl_cursor st ]             case ns of-                [] -> fail "Cannot step forward (no more steps)."-                [(_,cmd,d) ] -> do-                    putStrLn $ "step : " ++ unparseExprH cmd-                    return $ setCursor st d-                _ -> fail "Cannot step forward (multiple choices)"+                [] -> return $ Left $ CLError "Cannot step forward (no more steps)."+                [(cmd,ast)] -> do+                    putStrLn $ "step : " ++ cmd+                    return $ Right $ setCursor ast st+                _ -> return $ Left $ CLError $ "Cannot step forward (multiple choices), use goto {"+                                                ++ intercalate "," (map (show.snd) ns) ++ "}"         Back -> do-            let ns = [ edge | edge@(_,_,d) <- vs_graph (cl_version st), d == cl_cursor st ]+            let ns = [ (fromMaybe "unknown" msg, p) | (ast,msg,Just p) <- all_asts, ast == cl_cursor st ]             case ns of-                []         -> fail "Cannot step backwards (no more steps)."-                [(s,cmd,_) ] -> do-                    putStrLn $ "back, unstepping : " ++ unparseExprH cmd-                    return $ setCursor st s-                _          -> fail "Cannot step backwards (multiple choices, impossible!)."-        AddTag tag -> do-            return $ st { cl_version = (cl_version st) { vs_tags = (tag, cl_cursor st) : vs_tags (cl_version st) }}+                [] -> return $ Left $ CLError "Cannot step backwards (no more steps)."+                [(cmd,ast)] -> do+                    putStrLn $ "back, unstepping : " ++ cmd+                    return $ Right $ setCursor ast st+                _ -> return $ Left $ CLError "Cannot step backwards (multiple choices, impossible!)."  -------------------------------------------------------------------------------  showDerivationTree :: CommandLineState -> IO String-showDerivationTree st = return $ unlines $ showRefactorTrail graph tags start me-  where-          graph = [ (a,[unparseExprH b],c) | (SAST a,b,SAST c) <- vs_graph (cl_version st) ]-          tags  = [ (n,nm) | (nm,SAST n) <- vs_tags (cl_version st) ]-          SAST me = cl_cursor st-          SAST start = cl_initSAST st+showDerivationTree st = do+    all_asts <- listK (cl_kernel st)+    let graph = [ (a,[fromMaybe "-- command missing!" b],c) | (c,b,Just a) <- all_asts ]+    return $ unlines $ showRefactorTrail graph firstAST (cl_cursor st) -showRefactorTrail :: (Eq a, Show a) => [(a,[String],a)] -> [(a,String)] -> a -> a -> [String]-showRefactorTrail db tags a me =+showRefactorTrail :: (Eq a, Show a) => [(a,[String],a)] -> a -> a -> [String]+showRefactorTrail db a me =         case [ (b,c) | (a0,b,c) <- db, a == a0 ] of-           [] -> [show' 3 a ++ " " ++ dot ++ tags_txt]+           [] -> [show' 3 a ++ " " ++ dot]            ((b,c):bs) ->-                      [show' 3 a ++ " " ++ dot ++ (if not (null bs) then "->" else "") ++ tags_txt ] +++                      [show' 3 a ++ " " ++ dot ++ (if not (null bs) then "->" else "") ] ++                       ["    " ++ "| " ++ txt | txt <- b ] ++-                      showRefactorTrail db tags c me +++                      showRefactorTrail db c me ++                       if null bs                       then []                       else [] :                           showRefactorTrail [ (a',b',c') | (a',b',c') <- db-                                                          , not (a == a' && c == c')-                                                          ]  tags a me--  where-          dot = if a == me then "*" else "o"-          show' n x = replicate (n - length (show a)) ' ' ++ show x-          tags_txt = concat [ ' ' : txt-                            | (n,txt) <- tags-                            , n == a-                            ]+                                                         , not (a == a' && c == c')+                                                         ] a me +  where dot = if a == me then "*" else "o"+        show' n x = replicate (n - length (show a)) ' ' ++ show x  ------------------------------------------------------------------------------- @@ -253,14 +256,14 @@ showScripts = concatMap (\ (name,script) -> name ++ ": " ++ unparseScript script ++ "\n\n")  --------------------------------------------------------------------------------testAllT :: CommandLineState -> TransformH Core String+testAllT :: CommandLineState -> TransformH LCore String testAllT st = do                 let es  = cl_externals st-                    mbs = map (\d -> (externName d, fromDynamic (externDyn d) :: Maybe RewriteCoreBox)) es+                    mbs = map (\d -> (externName d, fromDynamic (externDyn d) :: Maybe RewriteLCoreBox)) es                     namedRewrites = [(name ,unbox boxedR) | (name, Just boxedR) <- mbs]                 testRewrites False namedRewrites -testRewrites :: Bool-> [(ExternalName, RewriteH Core)] -> TransformH Core String+testRewrites :: Bool-> [(ExternalName, RewriteH LCore)] -> TransformH LCore String testRewrites debug rewrites = case debug of                        True -> let list =  mapM (\ (n,r) -> liftM (f n) (testM r)) rewrites                                in  liftM unlines list
src/HERMIT/Shell/Interpreter.hs view
@@ -1,5 +1,5 @@ {-# LANGUAGE ConstraintKinds, KindSignatures, GADTs, InstanceSigs,-             FlexibleContexts, ScopedTypeVariables, CPP #-}+             FlexibleContexts, ScopedTypeVariables #-}  module HERMIT.Shell.Interpreter     ( -- * The HERMIT Interpreter@@ -11,20 +11,17 @@     , exprToDyns     ) where -#if MIN_VERSION_mtl(2,2,1)-import Control.Monad.Except-#else-import Control.Monad.Error-#endif-import Control.Monad.State+import Control.Monad (liftM, liftM2)+import Control.Monad.State (MonadState(get), gets)  import Data.Char import Data.Dynamic import qualified Data.Map as M  import HERMIT.External+import HERMIT.Kernel (AST) import HERMIT.Kure-import HERMIT.Monad+import HERMIT.Lemma import HERMIT.Name import HERMIT.Parser @@ -87,19 +84,18 @@     return $    toBoxedList dyns StringListBox              ++ toBoxedList dyns (PathBox . pathToSnocPath)                 -- ugly hack.  The whole dynamic stuff could do with overhauling.-             ++ toBoxedList dyns (TransformCorePathBox . return . pathToSnocPath)+             ++ toBoxedList dyns (TransformLCorePathBox . return . pathToSnocPath)              ++ toBoxedList dyns IntListBox              ++ toBoxedList dyns OccurrenceNameListBox-             ++ toBoxedList dyns RewriteCoreListBox              ++ toBoxedList dyns RuleNameListBox+             ++ toBoxedList dyns RewriteLCoreListBox  exprToDyns' rhs (CmdName str)     | all isDigit str = do         let i = read str-        return [ -- An Int is either a Path, or will be interpreted specially later.+        return [ -- An Int is either an AST, or will be interpreted specially later.                  toDyn $ IntBox i-                 -- TODO: Find a better long-term solution.-               , toDyn $ TransformCorePathBox (deprecatedIntToPathT i)+               , toDyn $ (read str :: AST)                ]     | otherwise = do         dict <- gets (mkDictionary . cl_externals)@@ -112,20 +108,21 @@             Nothing | rhs       -> let f = maybe id ((:) . toDyn) $ string2considerable str                                    in return $ f [ toDyn $ StringBox str                                                  , toDyn $ LemmaName str-                                                 , toDyn $ RememberedName str                                                  , toDyn $ RuleName str]                     | otherwise -> fail $ "User error, unrecognised HERMIT command: " ++ show str exprToDyns' _ (AppH e1 e2) = liftM2 dynCrossApply (exprToDyns' False e1) (exprToDyns' True e2) --- We treat externals of the type 'CommandLineState -> b' specially,--- providing them the shell state here, so they don't need a monadic return type+-- We treat externals of the type 'CommandLineState -> b' and 'PrettyPrinter -> b' specially,+-- providing their arguments from the shell state here, so they don't need a monadic return type -- in order to access it themselves. provideState :: MonadState CommandLineState m => Dynamic -> m Dynamic provideState dyn = do     st <- get     case dynApply dyn (toDyn $ box st) of         Just d  -> return d-        Nothing -> return dyn+        Nothing -> case dynApply dyn (toDyn $ box $ cl_pretty st) of+                    Just d' -> return d'+                    Nothing -> return dyn  -- Cross product of possible applications. dynCrossApply :: [Dynamic] -> [Dynamic] -> [Dynamic]
src/HERMIT/Shell/KernelEffect.hs view
@@ -1,43 +1,37 @@ {-# LANGUAGE ConstraintKinds, DeriveDataTypeable, FlexibleContexts, LambdaCase, TypeFamilies #-}+{-# LANGUAGE ScopedTypeVariables #-}  module HERMIT.Shell.KernelEffect     ( KernelEffect(..)     , performKernelEffect     , applyRewrite     , setPath-    , goDirection-    , beginScope-    , endScope-    , deleteSAST     ) where +import Control.Arrow import Control.Monad.State +import qualified Data.Map as M import Data.Monoid import Data.Typeable  import HERMIT.Context import HERMIT.Dictionary import HERMIT.External-import qualified HERMIT.GHC as GHC-import HERMIT.Kernel (queryK)-import HERMIT.Kernel.Scoped hiding (abortS, resumeS)+import HERMIT.Kernel import HERMIT.Kure+import HERMIT.Lemma import HERMIT.Parser -import HERMIT.Plugin.Renderer--import HERMIT.PrettyPrinter.Common- import HERMIT.Shell.Types  -------------------------------------------------------------------------------  -- | KernelEffects are things that affect the state of the Kernel-data KernelEffect = Direction  Direction -- Change the currect location using directions.-                  | BeginScope           -- Begin scope.-                  | EndScope             -- End scope.-                  | Delete     SAST      -- Delete an AST+data KernelEffect = Direction Direction -- Move up or top.+                  | BeginScope          -- Begin scope.+                  | EndScope            -- End scope.+                  | Delete AST          -- Delete an AST    deriving Typeable  instance Extern KernelEffect where@@ -47,71 +41,89 @@  performKernelEffect :: (MonadCatch m, CLMonad m) => ExprH -> KernelEffect -> m () performKernelEffect e = \case-                            Direction dir -> goDirection dir e-                            BeginScope    -> beginScope e-                            EndScope      -> endScope e-                            Delete sast   -> deleteSAST sast+                            Direction d -> goUp d e+                            BeginScope  -> beginScope e+                            EndScope    -> endScope e+                            Delete sast -> deleteAST sast  ------------------------------------------------------------------------------- -applyRewrite :: (Injection GHC.ModGuts g, Walker HermitC g, MonadCatch m, CLMonad m)-             => RewriteH g -> ExprH -> m ()+applyRewrite :: (MonadCatch m, CLMonad m) => RewriteH LCoreTC -> ExprH -> m () applyRewrite rr expr = do-    st <- get--    let sk = cl_kernel st-        kEnv = cl_kernel_env st-        sast = cl_cursor st-        ppOpts = cl_pretty_opts st-        pp = pCoreTC $ cl_pretty st+    ps <- getProofStackEmpty+    let str = unparseExprH expr+    case ps of+        todo@(Unproven {}) : todos -> do+            q' <- queryInFocus (inProofFocusR todo (promoteR rr) >>> (contextfreeT (applyT lintQuantifiedT (ptContext todo)) >> idR) :: TransformH Core Quantified) (Always str)+            let todo' = todo { ptLemma = (ptLemma todo) { lemmaQ = q' } }+            modify $ \ st -> st { cl_proofstack = M.insert (cl_cursor st) (todo':todos) (cl_proofstack st) }+        _ -> do+            (k,(kEnv,(ast,cl))) <- gets (cl_kernel &&& cl_kernel_env &&& cl_cursor &&& cl_corelint) -    sast' <- prefixFailMsg "Rewrite failed: " $ applyS sk rr kEnv sast+            rr' <- addFocusR (extractR rr :: RewriteH CoreTC)+            ast' <- prefixFailMsg "Rewrite failed:" $ applyK k rr' (Always str) kEnv ast -    let commit = put (newSAST expr sast' st) >> showResult-        showResult = if cl_diffonly st then showDiff else showWindow-        showDiff = do doc1 <- queryS sk (liftPrettyH ppOpts pp) kEnv sast-                      doc2 <- queryS sk (liftPrettyH ppOpts pp) kEnv sast'-                      diffDocH (cl_pretty st) doc1 doc2 >>= cl_putStr+            when cl $ do+                warns <- liftM snd (queryK k lintModuleT Never kEnv ast')+                            `catchM` (\ errs -> deleteK k ast' >> fail errs)+                putStrToConsole warns -    if cl_corelint st-        then do ast' <- toASTS sk sast'-                liftIO (queryK (kernelS sk) ast' lintModuleT kEnv)-                >>= runKureM (\ warns -> putStrToConsole warns >> commit)-                             (\ errs  -> liftIO (deleteS sk sast') >> fail errs)-        else commit+            addAST ast' -setPath :: (Injection GHC.ModGuts g, Walker HermitC g, MonadCatch m, CLMonad m)-        => TransformH g LocalPathH -> ExprH -> m ()+setPath :: (Injection a LCoreTC, MonadCatch m, CLMonad m) => TransformH a LocalPathH -> ExprH -> m () setPath t expr = do-    st <- get-    -- An extension to the Path-    p <- prefixFailMsg "Cannot find path: " $ queryS (cl_kernel st) t (cl_kernel_env st) (cl_cursor st)-    ast <- prefixFailMsg "Path is invalid: " $ modPathS (cl_kernel st) (<> p) (cl_kernel_env st) (cl_cursor st)-    put $ newSAST expr ast st-    showWindow+    p <- prefixFailMsg "Cannot find path: " $ queryInContext (promoteT t) Never+    modifyLocalPath (<> p) expr -goDirection :: (MonadCatch m, CLMonad m) => Direction -> ExprH -> m ()-goDirection dir expr = do-    st <- get-    ast <- prefixFailMsg "Invalid move: " $ modPathS (cl_kernel st) (moveLocally dir) (cl_kernel_env st) (cl_cursor st)-    put $ newSAST expr ast st-    showWindow+goUp :: (MonadCatch m, CLMonad m) => Direction -> ExprH -> m ()+goUp T expr = modifyLocalPath (const mempty) expr+goUp U expr = do+    (_,rel) <- getPathStack+    case rel of+        SnocPath [] -> fail "cannot move up, at root of scope."+        SnocPath (_:cs) -> modifyLocalPath (const $ SnocPath cs) expr  beginScope :: (MonadCatch m, CLMonad m) => ExprH -> m () beginScope expr = do-    st <- get-    ast <- beginScopeS (cl_kernel st) (cl_cursor st)-    put $ newSAST expr ast st-    showWindow+    ps <- getProofStackEmpty+    let logExpr = do+            (k,ast) <- gets (cl_kernel &&& cl_cursor)+            tellK k (unparseExprH expr) ast+    case ps of+        [] -> do+            (base, rel) <- getPathStack+            addAST =<< logExpr+            modify $ \ st -> st { cl_foci = M.insert (cl_cursor st) (rel : base, mempty) (cl_foci st) }+        Unproven nm l c ls (base,p) : todos -> do+            addAST =<< logExpr+            let todos' = Unproven nm l c ls (p : base, mempty) : todos+            modify $ \ st -> st { cl_proofstack = M.insert (cl_cursor st) todos' (cl_proofstack st) }+        _ -> fail "beginScope: impossible case!"  endScope :: (MonadCatch m, CLMonad m) => ExprH -> m () endScope expr = do-    st <- get-    ast <- endScopeS (cl_kernel st) (cl_cursor st)-    put $ newSAST expr ast st-    showWindow+    ps <- getProofStackEmpty+    let logExpr = do+            (k,ast) <- gets (cl_kernel &&& cl_cursor)+            tellK k (unparseExprH expr) ast+    case ps of+        [] -> do+            (base, _) <- getPathStack+            case base of+                [] -> fail "no scope to end."+                (rel:base') -> do+                    addAST =<< logExpr+                    modify $ \ st -> st { cl_foci = M.insert (cl_cursor st) (base', rel) (cl_foci st) }+        Unproven nm l c ls (base,_) : todos -> do+            case base of+                [] -> fail "no scope to end."+                (p:base') -> do+                    addAST =<< logExpr+                    let todos' = Unproven nm l c ls (base', p) : todos+                    modify $ \ st -> st { cl_proofstack = M.insert (cl_cursor st) todos' (cl_proofstack st) }+        _ -> fail "endScope: impossible case!" -deleteSAST :: (MonadCatch m, CLMonad m) => SAST -> m ()-deleteSAST sast = gets cl_kernel >>= flip deleteS sast+deleteAST :: (MonadCatch m, CLMonad m) => AST -> m ()+deleteAST ast = gets cl_kernel >>= flip deleteK ast  -------------------------------------------------------------------------------
src/HERMIT/Shell/Proof.hs view
@@ -1,322 +1,322 @@-{-# LANGUAGE ConstraintKinds, DeriveDataTypeable, FlexibleContexts, FlexibleInstances, LambdaCase,-             MultiParamTypeClasses, ScopedTypeVariables, TypeFamilies, TypeSynonymInstances, CPP #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeSynonymInstances #-}  module HERMIT.Shell.Proof     ( externals-    , ProofCommand(..)-    , performProofCommand     , UserProofTechnique     , userProofTechnique-    , ppLemmaT+    , withProofExternals+    , performProofShellCommand+    , forceProofs+    , ProofShellCommand(PCUser)     ) where  import Control.Arrow hiding (loop, (<+>))-import Control.Concurrent-#if MIN_VERSION_mtl(2,2,1)-import Control.Monad.Except-#else-import Control.Monad.Error-#endif-import Control.Monad.State+import Control.Monad (forM, forM_, liftM, unless)+import Control.Monad.Error.Class (MonadError(..))+import Control.Monad.State (MonadState, modify, gets) -import Data.Char (isSpace) import Data.Dynamic-import Data.List (delete, isInfixOf)-import Data.Map (filterWithKey, toList)+import Data.List (delete, zipWith4)+import qualified Data.Map as M+import Data.Monoid import Data.String (fromString) +import HERMIT.Context import HERMIT.Core import HERMIT.External import HERMIT.GHC hiding (settings, (<>), text, sep, (<+>), ($+$), nest)-import HERMIT.Kernel.Scoped+import HERMIT.Kernel import HERMIT.Kure+import HERMIT.Lemma import HERMIT.Monad+import HERMIT.Name import HERMIT.Parser+import HERMIT.Syntax import HERMIT.Utilities -import HERMIT.Dictionary.GHC hiding (externals) import HERMIT.Dictionary.Induction+import HERMIT.Dictionary.Local.Case hiding (externals) import HERMIT.Dictionary.Reasoning hiding (externals)--import HERMIT.Plugin.Types-import HERMIT.PrettyPrinter.Common+import HERMIT.Dictionary.Undefined hiding (externals) -import HERMIT.Shell.Completion-import HERMIT.Shell.Interpreter-import HERMIT.Shell.KernelEffect-import HERMIT.Shell.ScriptToRewrite import HERMIT.Shell.ShellEffect import HERMIT.Shell.Types -import System.Console.Haskeline hiding (catch, display)-import System.IO--import Text.PrettyPrint.MarkedHughesPJ as PP- -------------------------------------------------------------------------------------------------------- --- | Externals that get us into the prover shell, or otherwise deal with lemmas.--- TODO: InteractiveProof is the only one that should be here, rest in Reasoning+-- | Externals that get us into the prover shell. externals :: [External] externals = map (.+ Proof)-    [ external "show-lemma" (ShowLemmas . Just)-        [ "List lemmas whose names match search string." ]-    , external "show-lemmas" (ShowLemmas Nothing)-        [ "List lemmas." ]-    , external "prove-lemma" InteractiveProof+    [ external "prove-lemma" (CLSModify . interactiveProofIO)         [ "Proof a lemma interactively." ]-    , external "dump-lemma" DumpLemma-        [ "Dump named lemma to a file."-        , "dump-lemma <lemma-name> <filename> <renderer> <width>" ]     ]  -- | Externals that are added to the dictionary only when in interactive proof mode. proof_externals :: [External] proof_externals = map (.+ Proof)-    [ external "induction" (PCInduction . cmpString2Var :: String -> ProofShellCommand)+    [ external "lemma" (PCEnd . Right . (Obligation,))+        [ "Prove lemma by asserting it is alpha-equivalent to an already proven lemma." ]+    , external "lemma-unsafe" (PCEnd . Right . (UnsafeUsed,))+        [ "Prove lemma by asserting it is alpha-equivalent to an already proven lemma." ] .+ Unsafe+    , external "induction" (PCInduction . cmpString2Var :: String -> ProofShellCommand)         [ "Perform induction on given universally quantified variable."-        , "Each constructor case will generate a new equality to be proven."+        , "Each constructor case will generate a new lemma to be proven."         ]-    , external "dump" PCDump-        [ "dump <filename> <renderer> <width>" ]-    , external "end-proof" PCEnd+    , external "prove-by-cases" (PCByCases . cmpString2Var :: String -> ProofShellCommand)+        [ "Case split on given universally quantified variable."+        , "Each constructor case will generate a new lemma to be proven."+        ]+    , external "prove-consequent" PCConsequent+        [ "Prove the consequent of an implication by assuming the antecedent." ]+    , external "prove-conjunction" PCConjunction+        [ "Prove a conjunction by proving both sides of it." ]+    , external "inst-assumed" (\ i nm cs -> PCInstAssumed i (cmpHN2Var nm) cs)+        [ "Split an assumed lemma which is a conjunction/disjunction." ]+    , external "split-assumed" PCSplitAssumed+        [ "Split an assumed lemma which is a conjunction/disjunction." ]+    , external "end-proof" (PCEnd (Left False))         [ "check for alpha-equality, marking the lemma as proven" ]-    , external "end-case" PCEnd+    , external "end-case" (PCEnd (Left False))         [ "check for alpha-equality, marking the proof case as proven" ]+    , external "assume" (PCEnd (Left True))+        [ "mark lemma as assumed" ]     ]  -------------------------------------------------------------------------------------------------------- -data ProofCommand-    = InteractiveProof LemmaName-    | ShowLemmas (Maybe LemmaName)-    | DumpLemma LemmaName String String Int-    deriving (Typeable)--instance Extern ProofCommand where-    type Box ProofCommand = ProofCommand-    box i = i-    unbox i = i------------------------------------------------------------------------------------------------------------performProofCommand :: (MonadCatch m, MonadException m, CLMonad m) => ProofCommand -> m ()--performProofCommand (InteractiveProof nm) = do-    st <- gets cl_pstate-    l <- queryS (ps_kernel st) (getLemmaByNameT nm :: TransformH Core Lemma) (mkKernelEnv st) (ps_cursor st)-    interactiveProof True False (nm,l)--performProofCommand (DumpLemma nm fn r w) = dump (\ st -> getLemmaByNameT nm >>> ppLemmaT (cl_pretty st) nm) fn r w--performProofCommand (ShowLemmas mnm) = do-    st <- gets cl_pstate-    ls <- queryS (ps_kernel st) (getLemmasT :: TransformH Core Lemmas) (mkKernelEnv st) (ps_cursor st)-    mapM_ printLemma $ toList $ filterWithKey (maybe (\ _ _ -> True) (\ nm n _ -> show nm `isInfixOf` show n) mnm) ls-------------------------------------------------------------------------------------------------------------printLemma :: (MonadCatch m, MonadError CLException m, MonadIO m, MonadState CommandLineState m)-           => (LemmaName,Lemma) -> m ()-printLemma (nm,lem) = do-    st <- get-    doc <- queryS (cl_kernel st) (return lem >>> ppLemmaT (cl_pretty st) nm :: TransformH Core DocH) (cl_kernel_env st) (cl_cursor st)-    liftIO $ cl_render st stdout (cl_pretty_opts st) (Right doc)--ppLemmaT :: PrettyPrinter -> LemmaName -> TransformH Lemma DocH-ppLemmaT pp nm = do-    Lemma eq p u <- idR-    eqDoc <- return eq >>> ppEqualityT pp-    let hDoc = text (show nm) <+> text (if p then "(Proven)" else "(Not Proven)")-                              <+> text (if u then "(Used)"   else "(Not Used)")-    return $ hDoc $+$ nest 2 eqDoc------------------------------------------------------------------------------------------------------------type NamedLemma = (LemmaName, Lemma)--interactiveProof :: forall m. (MonadCatch m, MonadException m, CLMonad m) => Bool -> Bool -> NamedLemma -> m ()-interactiveProof topLevel isTemporary lem@(nm,_) = do-    origSt <- get-    origEs <- addProofExternals topLevel--    let ws_complete = " ()"--        -- Main proof input loop-        loop :: NamedLemma -> InputT m ()-        loop l = do-            mExpr <- lift popScriptLine-            case mExpr of-                Nothing -> do-                    lift $ printLemma l-                    mLine <- getInputLine $ "proof> "-                    case mLine of-                        Nothing          -> fail "proof aborted (input: Nothing)"-                        Just ('-':'-':_) -> loop l-                        Just line        -> if all isSpace line-                                            then loop l-                                            else lift (evalProofScript l line `catchM` (\msg -> cl_putStrLn msg >> return l)) >>= loop-                Just e -> lift (runExprH l e `catchM` (\msg -> setRunningScript Nothing >> cl_putStrLn msg >> return l)) >>= loop--    -- Display a proof banner?--    -- Start the CLI-    let settings = setComplete (completeWordWithPrev Nothing ws_complete shellComplete) defaultSettings-        cleanup s = put (s { cl_externals = origEs })-    catchError (runInputT settings (loop lem))-               (\case-                    CLAbort        -> cleanup origSt >> unless topLevel abort -- abandon proof attempt, bubble out to regular shell-                    CLContinue st' -> do-                        cl_putStrLn $ "Successfully proven: " ++ show nm-                        if isTemporary-                        then cleanup st'    -- successfully proven-                        else do sast <- applyS (cl_kernel st')-                                               (modifyLemmaR nm id idR (const True) id :: RewriteH Core)-                                               (mkKernelEnv $ cl_pstate st')-                                               (cl_cursor st')-                                cleanup $ newSAST (CmdName "proven") sast st'--                    CLError msg    -> fail $ "Prover error: " ++ msg-                    _              -> fail "unsupported exception in interactive prover")+-- | Top level entry point!+interactiveProofIO :: LemmaName -> CommandLineState -> IO (Either CLException CommandLineState)+interactiveProofIO nm s = do+    (r,st) <- runCLT s $ do+                ps <- getProofStackEmpty+                let t :: TransformH x (HermitC,Lemma)+                    t = contextT &&& getLemmaByNameT nm+                (c,l) <- case ps of+                            [] -> queryInFocus (t :: TransformH Core (HermitC,Lemma))+                                               (Always $ "prove-lemma " ++ quoteShow nm)+                            todo : _ -> queryInFocus (inProofFocusT todo t) Never+                pushProofStack $ Unproven nm l c [] mempty+    return $ fmap (const st) r -addProofExternals :: MonadState CommandLineState m => Bool -> m [External]-addProofExternals topLevel = do-    st <- get-    let es = cl_externals st+withProofExternals :: (MonadError CLException m, MonadState CommandLineState m) => m a -> m a+withProofExternals comp = do+    (es,sf) <- gets (cl_externals &&& cl_safety)+    let pes = filterSafety sf proof_externals         -- commands with same same in proof_externals will override those in normal externals-        newEs = proof_externals ++ filter ((`notElem` (map externName proof_externals)) . externName) es-    when topLevel $ modify $ \ s -> s { cl_externals = newEs }-    return es--evalProofScript :: (MonadCatch m, MonadException m, CLMonad m) => NamedLemma -> String -> m NamedLemma-evalProofScript lem = parseScriptCLT >=> foldM runExprH lem+        newEs = pes ++ filter ((`notElem` (map externName pes)) . externName) es+        reset s = s { cl_externals = es }+    modify $ \ s -> s { cl_externals = newEs }+    r <- comp `catchError` (\case CLContinue s -> continue (reset s)+                                  other        -> modify reset >> throwError other)+    modify reset+    return r -runExprH :: (MonadCatch m, MonadException m, CLMonad m) => NamedLemma -> ExprH -> m NamedLemma-runExprH lem expr = prefixFailMsg ("Error in expression: " ++ unparseExprH expr ++ "\n")-                  $ interpExprH interpProof expr >>= performProofShellCommand lem+forceProofs :: (MonadCatch m, CLMonad m) => m ()+forceProofs = do+    (c,nls) <- queryInFocus (contextT &&& getObligationNotProvenT :: TransformH Core (HermitC, [NamedLemma])) Never+    todos <- getProofStackEmpty+    let already = map ptName todos+        nls' = [ nl | nl@(nm,_) <- nls, not (nm `elem` already) ]+    if null nls'+    then return ()+    else do+        c' <- case todos of+                todo : _ -> queryInFocus (inProofFocusT todo contextT) Never+                _        -> return c+        forM_ nls' $ \ (nm,l) -> pushProofStack (Unproven nm l c' [] mempty)  -- | Verify that the lemma has been proven. Throws an exception if it has not.-endProof :: (MonadCatch m, MonadError CLException m, MonadIO m, MonadState CommandLineState m) => NamedLemma -> m ()-endProof (nm, Lemma eq _ _) = do-    st <- get+endProof :: (MonadCatch m, CLMonad m) => Either Bool (Used,LemmaName) -> ExprH -> m ()+endProof reason expr = do+    Unproven nm (Lemma q _ _ temp) c ls _ : _ <- getProofStack+    let msg = "The two sides of " ++ quoteShow nm ++ " are not alpha-equivalent."+        deleteOr tr = if temp then constT (deleteLemma nm) else tr+        t = case reason of+                Left assumed+                    | assumed   -> deleteOr (markLemmaAssumedT True nm)+                    | otherwise -> setFailMsg msg verifyQuantifiedT >> deleteOr (markLemmaProvedT nm)+                Right (u,nm') -> verifyEquivalentT u nm' >> deleteOr (markLemmaProvedT nm)+    queryInFocus (constT (withLemmas (M.fromList ls) $ applyT t c q) :: TransformH Core ())+                 (Always $ unparseExprH expr ++ " -- proven " ++ quoteShow nm)+    _ <- popProofStack+    cl_putStrLn $ "Successfully proven: " ++ show nm -    let sk = cl_kernel st-        kEnv = cl_kernel_env st-        sast = cl_cursor st+-- Note [Query]+-- We want to do our proof in the current context of the shell, whatever that is,+-- so we run them using queryInFocus below. This has the benefit that proof commands+-- can generate additional lemmas, and add to the version history.+performProofShellCommand :: (MonadCatch m, CLMonad m)+                         => ProofShellCommand -> ExprH -> m ()+performProofShellCommand cmd expr = go cmd+    where str = unparseExprH expr+          go (PCInduction idPred) = performInduction (Always str) idPred+          go (PCByCases idPred)   = proveByCases (Always str) idPred+          go PCConsequent         = proveConsequent str+          go PCConjunction        = proveConjunction str+          go (PCInstAssumed i v cs) = instAssumed i v cs str+          go (PCSplitAssumed i)   = splitAssumed i str+          go (PCUser prf)         = do+                let UserProofTechnique t = prf -- may add more constructors later+                -- note: we assume that if 't' completes without failing,+                -- the lemma is proved, we don't actually check+                todo : _ <- getProofStack+                queryInFocus (inProofFocusT todo t >> unless (lemmaT $ ptLemma todo) (markLemmaProvedT (ptName todo)))+                             (Changed str)+                _ <- popProofStack+                cl_putStrLn $ "Successfully proven: " ++ show (ptName todo)+          go (PCEnd why)          = endProof why expr -    -- Why do a query? We want to do our proof in the current context of the shell, whatever that is.-    b <- (queryS sk (return eq >>> testM verifyEqualityT :: TransformH Core Bool) kEnv sast)-    if b then continue st else fail $ "The two sides of " ++ show nm ++ " are not alpha-equivalent."+proveConsequent :: (MonadCatch m, CLMonad m) => String -> m ()+proveConsequent expr = do+    todo : _ <- getProofStack+    (c, Impl ante con) <- setFailMsg "not an implication" $+                          queryInFocus (inProofFocusT todo (contextT &&& projectT)) Never+    let nm = ptName todo+        ls = (nm <> "-antecedent", Lemma ante (Assumed False) NotUsed True) : ptAssumed todo+    (k,ast) <- gets (cl_kernel &&& cl_cursor)+    addAST =<< tellK k expr ast+    _ <- popProofStack+    pushProofStack $ MarkProven nm (lemmaT (ptLemma todo)) -- proving the consequent proves the lemma+    pushProofStack $ Unproven (nm <> "-consequent") (Lemma con NotProven Obligation True) c ls mempty -performProofShellCommand :: (MonadCatch m, MonadException m, CLMonad m) => NamedLemma -> ProofShellCommand -> m NamedLemma-performProofShellCommand lem@(nm, Lemma eq p u) = go-    where go (PCRewrite rr)         = do-                st <- get-                let sk = cl_kernel st-                    kEnv = cl_kernel_env st-                    sast = cl_cursor st+proveConjunction :: (MonadCatch m, CLMonad m) => String -> m ()+proveConjunction expr = do+    Unproven nm (Lemma (Quantified bs cl) p u t) c ls _ : _ <- getProofStack+    case cl of+        Conj (Quantified lbs lcl) (Quantified rbs rcl) -> do+            (k,ast) <- gets (cl_kernel &&& cl_cursor)+            addAST =<< tellK k expr ast+            _ <- popProofStack+            pushProofStack $ MarkProven nm t+            pushProofStack $ Unproven (nm <> "-r") (Lemma (Quantified (bs++rbs) rcl) p u True) c ls mempty+            pushProofStack $ Unproven (nm <> "-l") (Lemma (Quantified (bs++lbs) lcl) p u True) c ls mempty+        _ -> fail "not a conjunction." -                -- Why do a query? We want to do our proof in the current context of the shell, whatever that is.-                -- TODO: query doesn't save side effects, which are needed for stash/lemmas-                eq' <- queryS sk (return eq >>> rr >>> (bothT lintExprT >> idR) :: TransformH Core Equality) kEnv sast-                return (nm, Lemma eq' p u)-          go (PCTransform t)      = do-                st <- get-                let sk = cl_kernel st-                    kEnv = cl_kernel_env st-                    sast = cl_cursor st+splitAssumed :: (MonadCatch m, CLMonad m) => Int -> String -> m ()+splitAssumed i expr = do+    Unproven nm lem c ls ps : _ <- getProofStack+    (b, (n, Lemma q p u t):a) <- getIth i ls+    qs <- splitQuantified q+    let nls = [ (n <> fromString (show j), Lemma q' p u t) | (j::Int,q') <- zip [0..] qs ]+    (k,ast) <- gets (cl_kernel &&& cl_cursor)+    addAST =<< tellK k expr ast+    _ <- popProofStack+    pushProofStack $ Unproven nm lem c (b ++ nls ++ a) ps -                -- Why do a query? See above.-                res <- queryS sk (return eq >>> t :: TransformH Core String) kEnv sast-                cl_putStrLn res-                return lem-          go (PCInduction idPred) = performInduction lem idPred-          go (PCShell effect)     = performShellEffect effect >> return lem-          go (PCScript effect)    = do-                lemVar <- liftIO $ newMVar lem -- couldn't resist that name-                let lemHack e = liftIO (takeMVar lemVar) >>= flip runExprH e >>= \l -> liftIO (putMVar lemVar l)-                performScriptEffect lemHack effect-                liftIO $ takeMVar lemVar-          go (PCQuery query)      = performQuery query (error "PCQuery ExprH") >> return lem-          go (PCProofCommand cmd) = performProofCommand cmd >> return lem-          go (PCUser prf)         = let UserProofTechnique t = prf in -- may add more constructors later-             do-                st <- get-                -- Why do a query? We want to do our proof in the current context of the shell, whatever that is.-                queryS (cl_kernel st) (return eq >>> t :: TransformH Core ()) (cl_kernel_env st) (cl_cursor st)-                continue st -- note: we assume that if 't' completes without failing, the lemma is proved, we don't actually check-                return lem       -- never reached-          go (PCDump fName r w)   = dump (\ st -> return (snd lem) >>> ppLemmaT (cl_pretty st) (fst lem)) fName r w >> return lem-          go PCEnd                = endProof lem >> return lem-          go (PCUnsupported s)    = cl_putStrLn (s ++ " command unsupported in proof mode.") >> return lem+instAssumed :: (MonadCatch m, CLMonad m) => Int -> (Var -> Bool) -> CoreString -> String -> m ()+instAssumed i pr cs expr = do+    todo : _ <- getProofStack+    (b, orig@(n, Lemma q p u t):a) <- getIth i $ ptAssumed todo+    q' <- queryInFocus (inProofFocusT todo $ return q >>> instantiateQuantifiedVarR pr cs) Never+    (k,ast) <- gets (cl_kernel &&& cl_cursor)+    addAST =<< tellK k expr ast+    _ <- popProofStack+    pushProofStack $ todo { ptAssumed = b ++ orig:(n <> "'", Lemma q' p u t):a } -performInduction :: (MonadCatch m, MonadException m, CLMonad m) => NamedLemma -> (Id -> Bool) -> m NamedLemma-performInduction lem@(nm, Lemma eq@(Equality bs lhs rhs) _ _) idPred = do-    st <- get-    let sk = cl_kernel st-        kEnv = cl_kernel_env st-        sast = cl_cursor st+getIth :: MonadCatch m => Int -> [a] -> m ([a],[a])+getIth _ [] = fail "getIth: out of range"+getIth n (x:xs) = go n x xs []+    where go 0 y ys zs = return (reverse zs, y:ys)+          go _ _ [] _  = fail "getIth: out of range"+          go i z (y:ys) zs = go (i-1) y ys (z:zs) -    i <- setFailMsg "specified identifier is not universally quantified in this equality lemma." $ soleElement (filter idPred bs)+-- | Always returns non-empty list, or fails.+splitQuantified :: MonadCatch m => Quantified -> m [Quantified]+splitQuantified (Quantified bs cl) = do+    case cl of+        Conj (Quantified lbs lcl) (Quantified rbs rcl) ->+            return [Quantified (bs++lbs) lcl, Quantified (bs++rbs) rcl]+        Disj (Quantified lbs lcl) (Quantified rbs rcl) ->+            return [Quantified (bs++lbs) lcl, Quantified (bs++rbs) rcl]+        Impl (Quantified lbs lcl) (Quantified rbs rcl) ->+            return [Quantified (bs++lbs) lcl, Quantified (bs++rbs) rcl]+        _ -> fail "equalities cannot be split!"++performInduction :: (MonadCatch m, CLMonad m)+                 => CommitMsg -> (Id -> Bool) -> m ()+performInduction cm idPred = do+    (nm, Lemma q@(Quantified bs (Equiv lhs rhs)) _ _ temp, ctxt, ls, _) <- currentLemma+    i <- setFailMsg "specified identifier is not universally quantified in this equality lemma." $+         soleElement (filter idPred bs)+     -- Why do a query? We want to do our proof in the current context of the shell, whatever that is.-    cases <- queryS sk (inductionCaseSplit bs i lhs rhs :: TransformH Core [(Maybe DataCon,[Var],CoreExpr,CoreExpr)]) kEnv sast+    cases <- queryInContext+                (inductionCaseSplit bs i lhs rhs :: TransformH LCoreTC [(Maybe DataCon, [Var], CoreExpr, CoreExpr)])+                cm -    forM_ cases $ \ (mdc,vs,lhsE,rhsE) -> do+    -- replace the current lemma with the three subcases+    -- proving them will prove this case automatically+    _ <- popProofStack+    pushProofStack $ MarkProven nm temp+    forM_ (reverse cases) $ \ (mdc,vs,lhsE,rhsE) -> do          let vs_matching_i_type = filter (typeAlphaEq (varType i) . varType) vs+            caseName = maybe "undefined" unqualifiedName mdc          -- Generate list of specialized induction hypotheses for the recursive cases.-        eqs <- forM vs_matching_i_type $ \ i' ->-                    liftM discardUniVars $ instantiateEqualityVar (==i) (Var i') [] eq+        qs <- forM vs_matching_i_type $ \ i' -> do+                liftM discardUniVars $ instQuantified (boundVars ctxt) (==i) (Var i') q+                -- TODO rethink the discardUniVars          let nms = [ fromString ("ind-hyp-" ++ show n) | n :: Int <- [0..] ]-            hypLemmas = zip nms $ zipWith3 Lemma eqs (repeat True) (repeat False)-            lemmaName = fromString $ show nm ++ "-induction-on-"-                                             ++ unqualifiedName i ++ "-case-"-                                             ++ maybe "undefined" unqualifiedName mdc-            caseLemma = Lemma (Equality (delete i bs ++ vs) lhsE rhsE) False False+            hypLemmas = zip nms $ zipWith4 Lemma qs (repeat (Assumed False)) (repeat NotUsed) (repeat True)+            lemmaName = fromString $ show nm ++ "-induction-case-" ++ caseName+            caseLemma = Lemma (mkQuantified (delete i bs ++ vs) lhsE rhsE) NotProven Obligation True -        -- this is pretty hacky-        sast' <- addLemmas hypLemmas  -- add temporary lemmas-        interactiveProof False True (lemmaName,caseLemma) -- recursion!-        modify $ flip setCursor sast' -- discard temporary lemmas+        pushProofStack $ Unproven lemmaName caseLemma ctxt (hypLemmas ++ ls) mempty -    get >>= continue-    return lem -- this is never reached, but the type says we need it.+proveByCases :: (MonadCatch m, CLMonad m)+             => CommitMsg -> (Id -> Bool) -> m ()+proveByCases cm idPred = do+    (nm, Lemma (Quantified bs cl) _ _ temp, ctxt, ls, _) <- currentLemma+    guardMsg (any idPred bs) "specified identifier is not universally quantified in this lemma."+    let (as,b:bs') = break idPred bs -- safe because above guard+    guardMsg (not (any idPred bs')) "multiple matching quantifiers." -addLemmas :: (MonadCatch m, MonadError CLException m, MonadIO m, MonadState CommandLineState m)-          => [NamedLemma] -> m SAST-addLemmas lems = do-    ifM isRunningScript (return ()) $ forM_ lems printLemma-    let addAllAtOnceR :: RewriteH Core-        addAllAtOnceR = sideEffectR $ \ _ _ -> forM_ lems $ \ (nm,l) -> insertLemma nm l+    cases <- queryInContext (do ue <- mkUndefinedValT (varType b)+                                liftM (ue:) (constT (caseExprsForM (varToCoreExpr b)))) cm -    st <- get-    sast <- applyS (cl_kernel st) addAllAtOnceR (mkKernelEnv $ cl_pstate st) (cl_cursor st)-    put $ newSAST (CmdName "adding lemmas") sast st+    -- replace the current lemma with the three subcases+    -- proving them will prove the overall lemma automatically+    _ <- popProofStack+    pushProofStack $ MarkProven nm temp+    forM_ (zip [(0::Int)..] $ reverse cases) $ \ (i,e) -> do -    -- return original SAST-    return $ cl_cursor st+        let lemmaName = fromString $ show nm ++ "-case-" ++ show i+            Quantified bs'' cl' = substQuantified b e $ Quantified bs' cl+            fvs = varSetElems $ localFreeVarsExpr e+            caseLemma = Lemma (Quantified (as++fvs++bs'') cl') NotProven Obligation True +        pushProofStack $ Unproven lemmaName caseLemma ctxt ls mempty+ data ProofShellCommand-    = PCRewrite (RewriteH Equality)-    | PCTransform (TransformH Equality String)-    | PCInduction (Id -> Bool)-    | PCShell ShellEffect-    | PCScript ScriptEffect-    | PCQuery QueryFun-    | PCProofCommand ProofCommand+    = PCInduction (Id -> Bool)+    | PCByCases (Id -> Bool)+    | PCConsequent+    | PCConjunction+    | PCSplitAssumed Int+    | PCInstAssumed Int (Var -> Bool) CoreString     | PCUser UserProofTechnique-    | PCDump String String Int-    | PCEnd-    | PCUnsupported String+    | PCEnd (Either Bool (Used,LemmaName)) -- ^ Left True = assume this lemma+                                           --   Left False = check for alpha-equivalence+                                           --   Right (u,nm) = try to prove with given lemma, marking it u     deriving Typeable  -- keep abstract to avoid breaking things if we modify this later-newtype UserProofTechnique = UserProofTechnique (TransformH Equality ())+newtype UserProofTechnique = UserProofTechnique (TransformH LCoreTC ())+    deriving Typeable -userProofTechnique :: TransformH Equality () -> UserProofTechnique+userProofTechnique :: TransformH LCoreTC () -> UserProofTechnique userProofTechnique = UserProofTechnique  instance Extern ProofShellCommand where@@ -324,36 +324,7 @@     box i = i     unbox i = i -data UserProofTechniqueBox = UserProofTechniqueBox UserProofTechnique deriving Typeable- instance Extern UserProofTechnique where-    type Box UserProofTechnique = UserProofTechniqueBox-    box = UserProofTechniqueBox-    unbox (UserProofTechniqueBox t) = t--interpProof :: Monad m => [Interp m ProofShellCommand]-interpProof =-  [ interp $ \ (RewriteCoreBox rr)            -> PCRewrite $ bothR $ extractR rr-  , interp $ \ (RewriteCoreTCBox rr)          -> PCRewrite $ bothR $ extractR rr-  , interp $ \ (BiRewriteCoreBox br)          -> PCRewrite $ bothR $ (extractR (forwardT br) <+ extractR (backwardT br))-  , interp $ \ (effect :: ShellEffect)        -> PCShell effect-  , interp $ \ (effect :: ScriptEffect)       -> PCScript effect-  , interp $ \ (StringBox str)                -> PCQuery (message str)-  , interp $ \ (query :: QueryFun)            -> PCQuery query-  , interp $ \ (cmd :: ProofCommand)          -> PCProofCommand cmd-  , interp $ \ (RewriteEqualityBox r)         -> PCRewrite r-  , interp $ \ (TransformEqualityStringBox t) -> PCTransform t-  , interp $ \ (UserProofTechniqueBox t)      -> PCUser t-  , interp $ \ (cmd :: ProofShellCommand)     -> cmd-  , interp $ \ (CrumbBox _cr)                 -> PCUnsupported "CrumbBox"-  , interp $ \ (PathBox _p)                   -> PCUnsupported "PathBox"-  , interp $ \ (TransformCorePathBox _tt)     -> PCUnsupported "TransformCorePathBox"-  , interp $ \ (TransformCoreTCPathBox _tt)   -> PCUnsupported "TransformCoreTCPathBox"-  , interp $ \ (TransformCoreStringBox _tt)   -> PCUnsupported "TransformCoreStringBox"-  , interp $ \ (TransformCoreTCStringBox _tt) -> PCUnsupported "TransformCoreTCStringBox"-  , interp $ \ (TransformCoreTCDocHBox _tt)   -> PCUnsupported "TransformCoreTCDocHBox"-  , interp $ \ (TransformCoreCheckBox _tt)    -> PCUnsupported "TransformCoreCheckBox"-  , interp $ \ (TransformCoreTCCheckBox _tt)  -> PCUnsupported "TransformCoreTCCheckBox"-  , interp $ \ (_effect :: KernelEffect)      -> PCUnsupported "KernelEffect"-  ]-+    type Box UserProofTechnique = UserProofTechnique+    box i = i+    unbox i = i
src/HERMIT/Shell/ScriptToRewrite.hs view
@@ -1,5 +1,5 @@ {-# LANGUAGE ConstraintKinds, DeriveDataTypeable, FlexibleContexts, LambdaCase,-             MultiParamTypeClasses, ScopedTypeVariables, TypeFamilies, CPP #-}+             MultiParamTypeClasses, ScopedTypeVariables, TypeFamilies #-}  module HERMIT.Shell.ScriptToRewrite     ( -- * Converting Scripts to Rewrites@@ -9,36 +9,39 @@     , parseScriptCLT     , performScriptEffect     , popScriptLine+    , pushScriptLine+    , pushScript     , runScript+    , fileToScript     , scriptToRewrite-    , setRunningScript     , ScriptEffect(..)     ) where  import Control.Arrow-#if MIN_VERSION_mtl(2,2,1)-import Control.Monad.Except-#else-import Control.Monad.Error-#endif-import Control.Monad.State+import Control.Monad+import Control.Monad.IO.Class (liftIO)+import Control.Monad.State (MonadState, gets, modify) import Control.Exception hiding (catch)  import Data.Dynamic+import qualified Data.Map as M  import HERMIT.Context(LocalPathH)-import HERMIT.Kernel.Scoped-import HERMIT.Kure import HERMIT.External+import HERMIT.Kernel+import HERMIT.Kure+import HERMIT.Lemma import HERMIT.Parser(Script, ExprH, unparseExprH, parseScript, unparseScript)--import HERMIT.PrettyPrinter.Common(TransformCoreTCDocHBox(..))+import HERMIT.Dictionary.Reasoning+import HERMIT.PrettyPrinter.Common+import qualified HERMIT.PrettyPrinter.Clean as Clean  import HERMIT.Shell.KernelEffect import HERMIT.Shell.Interpreter import HERMIT.Shell.ShellEffect import HERMIT.Shell.Types +import qualified Text.PrettyPrint.MarkedHughesPJ as PP ------------------------------------  type RewriteName = String@@ -47,7 +50,7 @@     = DefineScript ScriptName String     | LoadFile ScriptName FilePath  -- load a file on top of the current node     | RunScript ScriptName-    | SaveFile FilePath+    | SaveFile Bool FilePath        -- Bool = whether to dump code/lemma between commands     | SaveScript FilePath ScriptName     | ScriptToRewrite RewriteName ScriptName     | SeqMeta [ScriptEffect]@@ -68,27 +71,74 @@     where go = popScriptLine >>= maybe (return ()) (\e -> run e >> go)  popScriptLine :: MonadState CommandLineState m => m (Maybe ExprH)-popScriptLine = gets cl_running_script >>= maybe (return Nothing) (\case []     -> setRunningScript Nothing >> return Nothing-                                                                         (e:es) -> setRunningScript (Just es) >> return (Just e))+popScriptLine = gets cl_running_script >>= maybe (return Nothing)+                                                 (\case []     -> setRunningScript Nothing >> return Nothing+                                                        (e:es) -> setRunningScript (Just es) >> return (Just e)) -performScriptEffect :: (MonadCatch m, CLMonad m) => (ExprH -> m ()) -> ScriptEffect -> m ()-performScriptEffect runner = go+pushScriptLine :: MonadState CommandLineState m => ExprH -> m ()+pushScriptLine = pushScript . (:[])++pushScript :: MonadState CommandLineState m => Script -> m ()+pushScript es = modify $ \ st -> st { cl_running_script = Just $ maybe es (++es) (cl_running_script st) }++getFragment :: (MonadCatch m, CLMonad m) => Bool -> AST -> m String+getFragment False _  = return ""+getFragment True ast = do+    (now,opts) <- gets (cl_cursor &&& cl_pretty_opts)+    modify $ setCursor ast+    ps <- getProofStackEmpty+    let discardProvens [] = []+        discardProvens r@(Unproven{} : _) = r+        discardProvens (_:r) = discardProvens r+    doc <- case discardProvens ps of+            Unproven _ (Lemma q _ _ _) _ ls p : _ -> do+                as <- case ls of+                        [] -> return []+                        _  -> liftM (PP.text "Assumed lemmas: " :) $+                                queryInFocus ((liftPrettyH opts $+                                                forM ls $ \(n',l') ->+                                                    return l' >>> ppLemmaT Clean.pretty n'+                                              ) :: TransformH Core [DocH]) Never+                d <- queryInFocus (liftPrettyH opts $+                                    return q >>> extractT (pathT (pathStack2Path p) (ppLCoreTCT Clean.pretty)) :: TransformH Core DocH) Never+                return $ PP.vcat $ as ++ [PP.text "Goal:", d]+            _                             -> queryInFocus (liftPrettyH opts $ pCoreTC Clean.pretty) Never+    let ASCII str = renderCode opts doc+        str' = unlines $ ("" :) $ map ("-- " ++) $ lines str+    modify $ setCursor now+    return str'++fileToScript :: CLMonad m => FilePath -> m Script+fileToScript fileName = do+    putStrToConsole $ "Loading \"" ++ fileName ++ "\"..."+    res <- liftIO $ try (readFile fileName)+    case res of+        Left (err :: IOException) -> fail ("IO error: " ++ show err)+        Right str -> parseScriptCLT str++performScriptEffect :: (MonadCatch m, CLMonad m) => ScriptEffect -> m ()+performScriptEffect = go     where go (SeqMeta ms) = mapM_ go ms           go (LoadFile scriptName fileName) = do-            putStrToConsole $ "Loading \"" ++ fileName ++ "\"..."-            res <- liftIO $ try (readFile fileName)-            case res of-                Left (err :: IOException) -> fail ("IO error: " ++ show err)-                Right str -> do-                    script <- parseScriptCLT str-                    modify $ \ st -> st {cl_scripts = (scriptName,script) : cl_scripts st}-                    putStrToConsole ("Script \"" ++ scriptName ++ "\" loaded successfully from \"" ++ fileName ++ "\".")+            script <- fileToScript fileName+            modify $ \ st -> st {cl_scripts = (scriptName,script) : cl_scripts st}+            putStrToConsole ("Script \"" ++ scriptName ++ "\" loaded successfully from \"" ++ fileName ++ "\".") -          go (SaveFile fileName) = do-            version <- gets cl_version+          go (SaveFile verb fileName) = do             putStrToConsole $ "[saving " ++ fileName ++ "]"+            (k,cur) <- gets (cl_kernel &&& cl_cursor)+            all_asts <- listK k+            let m = M.fromList [ (ast,(msg,p)) | (ast,msg,p) <- all_asts ]+                follow ast+                    | Just (msg, p) <- M.lookup ast m = do+                        f <- getFragment verb ast+                        (ls,lastFrag) <- maybe (return ([],"")) follow p+                        let g = if f == lastFrag then id else (f:)+                        return (g $ maybe (maybe id (const ("-- missing command!":)) p) (:) msg ls, f)+                    | otherwise = return ([],"")             -- no checks to see if you are clobering; be careful-            liftIO $ writeFile fileName $ showGraph (vs_graph version) (vs_tags version) (SAST 0)+            ls <- fst <$> follow cur+            liftIO $ writeFile fileName $ unlines $ reverse ls            go (ScriptToRewrite rewriteName scriptName) = do             script <- lookupScript scriptName@@ -103,11 +153,9 @@           go (RunScript scriptName) = do             script <- lookupScript scriptName             running_script_st <- gets cl_running_script-            setRunningScript $ Just script-            runScript runner `catchError` (\ err -> setRunningScript running_script_st >> throwError err)-            setRunningScript running_script_st-            putStrToConsole ("Script \"" ++ scriptName ++ "\" ran successfully.")-            showWindow+            setRunningScript $ case running_script_st of+                                Nothing -> Just script+                                Just es -> Just (script ++ es)            go (SaveScript fileName scriptName) = do             script <- lookupScript scriptName@@ -137,9 +185,9 @@               | ScriptPrimSc ExprH PrimScriptR  data PrimScriptR-       = ScriptRewriteHCore (RewriteH Core)+       = ScriptRewriteHCore (RewriteH LCore)        | ScriptPath PathH-       | ScriptTransformHCorePath (TransformH Core LocalPathH)+       | ScriptTransformHCorePath (TransformH LCore LocalPathH)   -- TODO: Hacky parsing, needs cleaning up@@ -171,28 +219,27 @@  interpScriptR :: Monad m => [Interp m UnscopedScriptR] interpScriptR =-  [ interp (\ (RewriteCoreBox r)           -> ScriptPrimUn $ ScriptRewriteHCore r)-  , interp (\ (RewriteCoreTCBox _)         -> ScriptUnsupported "rewrite that traverses types and coercions") -- TODO-  , interp (\ (BiRewriteCoreBox br)        -> ScriptPrimUn $ ScriptRewriteHCore $ whicheverR br)-  , interp (\ (CrumbBox cr)                -> ScriptPrimUn $ ScriptPath [cr])-  , interp (\ (PathBox p)                  -> ScriptPrimUn $ ScriptPath (snocPathToPath p))-  , interp (\ (TransformCorePathBox t)     -> ScriptPrimUn $ ScriptTransformHCorePath t)-  , interp (\ (effect :: KernelEffect)     -> case effect of+  [ interp (\ (RewriteLCoreBox r)           -> ScriptPrimUn $ ScriptRewriteHCore r)+  , interp (\ (RewriteLCoreTCBox _)         -> ScriptUnsupported "rewrite that traverses types and coercions") -- TODO+  , interp (\ (BiRewriteLCoreBox br)        -> ScriptPrimUn $ ScriptRewriteHCore $ whicheverR br)+  , interp (\ (CrumbBox cr)                 -> ScriptPrimUn $ ScriptPath [cr])+  , interp (\ (PathBox p)                   -> ScriptPrimUn $ ScriptPath (snocPathToPath p))+  , interp (\ (TransformLCorePathBox t)     -> ScriptPrimUn $ ScriptTransformHCorePath t)+  , interp (\ (effect :: KernelEffect)      -> case effect of                                                 BeginScope -> ScriptBeginScope                                                 EndScope   -> ScriptEndScope                                                 _          -> ScriptUnsupported "Kernel effect" )-  , interp (\ (_ :: ShellEffect)           -> ScriptUnsupported "shell effect")-  , interp (\ (_ :: QueryFun)              -> ScriptUnsupported "query")-  , interp (\ (TransformCoreStringBox _)   -> ScriptUnsupported "query")-  , interp (\ (TransformCoreTCStringBox _) -> ScriptUnsupported "query")-  , interp (\ (TransformCoreTCDocHBox _)   -> ScriptUnsupported "query")-  , interp (\ (TransformCoreCheckBox _)    -> ScriptUnsupported "predicate")-  , interp (\ (StringBox _)                -> ScriptUnsupported "message")+  , interp (\ (_ :: ShellEffect)            -> ScriptUnsupported "shell effect")+  , interp (\ (_ :: QueryFun)               -> ScriptUnsupported "query")+  , interp (\ (TransformLCoreStringBox _)   -> ScriptUnsupported "query")+  , interp (\ (TransformLCoreTCStringBox _) -> ScriptUnsupported "query")+  , interp (\ (TransformLCoreUnitBox _)     -> ScriptUnsupported "predicate")+  , interp (\ (StringBox _)                 -> ScriptUnsupported "message")   ]  ----------------------------------- -scopedScriptsToRewrite :: [ScopedScriptR] -> RewriteH Core+scopedScriptsToRewrite :: [ScopedScriptR] -> RewriteH LCore scopedScriptsToRewrite []        = idR scopedScriptsToRewrite (x : xs)  = let rest = scopedScriptsToRewrite xs                                        failWith e = prefixFailMsg ("Error in script expression: " ++ unparseExprH e ++ "\n")@@ -206,7 +253,7 @@  ----------------------------------- -scriptToRewrite :: CLMonad m => Script -> m (RewriteH Core)+scriptToRewrite :: CLMonad m => Script -> m (RewriteH LCore) scriptToRewrite scr = do     unscoped <- mapM (interpExprH interpScriptR) scr     scoped   <- unscopedToScopedScriptR $ zip scr unscoped@@ -225,9 +272,3 @@  ----------------------------------- --- I find it annoying that Functor is not a superclass of Monad.-(<$>) :: Monad m => (a -> b) -> m a -> m b-(<$>) = liftM-{-# INLINE (<$>) #-}-------------------------------------
src/HERMIT/Shell/ShellEffect.hs view
@@ -1,25 +1,29 @@-{-# LANGUAGE CPP, KindSignatures, GADTs, FlexibleContexts, TypeFamilies,-             DeriveDataTypeable, GeneralizedNewtypeDeriving, LambdaCase,-             MultiParamTypeClasses, ScopedTypeVariables #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}  module HERMIT.Shell.ShellEffect     ( ShellEffect(..)     , performShellEffect+    , dumpT     , dump     ) where -#if MIN_VERSION_mtl(2,2,1)-import Control.Monad.Except-#else-import Control.Monad.Error-#endif-import Control.Monad.State+import Control.Monad.Error.Class (MonadError(..))+import Control.Monad.IO.Class (MonadIO(..))+import Control.Monad.State (MonadState(..), gets)  import Data.Typeable  import HERMIT.External import HERMIT.Kure-import HERMIT.Kernel.Scoped import HERMIT.PrettyPrinter.Common  import HERMIT.Plugin.Renderer@@ -31,13 +35,12 @@  ---------------------------------------------------------------------------------- -data ShellEffect-    = Abort -- ^ Abort GHC-    | CLSModify (CommandLineState -> IO CommandLineState) -- ^ Modify shell state-    | PluginComp (PluginM ())-    | Continue -- ^ exit the shell, but don't abort/resume-    | Dump (CommandLineState -> TransformH CoreTC DocH) String String Int-    | Resume+data ShellEffect :: * where+    Abort      :: ShellEffect+    CLSModify  :: (CommandLineState -> IO (Either CLException CommandLineState)) -> ShellEffect+    PluginComp :: PluginM () -> ShellEffect+    Continue   :: ShellEffect+    Resume     :: ShellEffect     deriving Typeable  instance Extern ShellEffect where@@ -47,22 +50,31 @@  ---------------------------------------------------------------------------------- -performShellEffect :: (MonadCatch m, MonadError CLException m, MonadIO m, MonadState CommandLineState m) => ShellEffect -> m ()+performShellEffect :: (MonadCatch m, CLMonad m) => ShellEffect -> m () performShellEffect Abort  = abort-performShellEffect Resume = gets cl_cursor >>= resume-performShellEffect Continue = get >>= continue-performShellEffect (Dump pp fileName renderer width) = dump pp fileName renderer width+performShellEffect Resume = announceUnprovens >> gets cl_cursor >>= resume+performShellEffect Continue = announceUnprovens >> get >>= continue -performShellEffect (CLSModify f) = get >>= liftAndCatchIO . f >>= put >> showWindow+performShellEffect (CLSModify f)  = get >>= liftAndCatchIO . f >>= either throwError put -performShellEffect (PluginComp m) = pluginM m >> showWindow+performShellEffect (PluginComp m) = pluginM m -dump :: (MonadCatch m, MonadIO m, MonadState CommandLineState m) => (CommandLineState -> TransformH CoreTC DocH) -> String -> String -> Int -> m ()-dump pp fileName renderer width = do-    st <- get+dumpT :: FilePath -> PrettyPrinter -> String -> Int -> TransformH DocH ()+dumpT fileName pp renderer width = do     case lookup renderer shellRenderers of-      Just r -> do doc <- prefixFailMsg "Bad renderer option: " $ queryS (cl_kernel st) (pp st) (cl_kernel_env st) (cl_cursor st)+      Just r -> do doc <- idR                    liftIO $ do h <- openFile fileName WriteMode-                               r h ((cl_pretty_opts st) { po_width = width }) (Right doc)+                               r h ((pOptions pp) { po_width = width }) (Right doc)                                hClose h-      _ -> fail "dump: bad pretty-printer or renderer option"+      _ -> fail "dump: bad renderer option"++dump :: FilePath -> PrettyPrinter -> String -> Int -> CommandLineState -> IO (Either CLException CommandLineState)+dump fileName pp renderer width st = do+    let st' = setPrettyOpts (setPretty st pp) $ (cl_pretty_opts st) { po_width = width }+    (r, _st'') <- runCLT st' $ do+        pluginM (changeRenderer renderer)+        h <- liftIO $ openFile fileName WriteMode+        showWindow (Just h)+        liftIO $ hClose h+    return $ fmap (const st) r+
src/HERMIT/Shell/Types.hs view
@@ -1,33 +1,47 @@-{-# LANGUAGE ConstraintKinds, CPP, KindSignatures, GADTs, FlexibleContexts, DeriveDataTypeable,-             FunctionalDependencies, GeneralizedNewtypeDeriving, InstanceSigs,-             LambdaCase, RankNTypes, ScopedTypeVariables, TypeFamilies #-}-+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE InstanceSigs #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-} module HERMIT.Shell.Types where  import Control.Applicative+import Control.Arrow import Control.Concurrent.STM-import Control.Monad.State-#if MIN_VERSION_mtl(2,2,1)-import Control.Monad.Except-#else-import Control.Monad.Error-#endif+import Control.Monad (liftM, unless, when, forM_)+import Control.Monad.Error.Class (MonadError(..))+import Control.Monad.IO.Class (MonadIO(..))+import Control.Monad.State (MonadState(..), StateT(..), gets, modify)+import Control.Monad.Trans.Class (MonadTrans(..))+import Control.Monad.Trans.Except (ExceptT(..), runExceptT)  import Data.Dynamic-import Data.List (intercalate) import qualified Data.Map as M import Data.Maybe (fromMaybe, isJust)-import Data.Monoid (mempty)+import Data.Monoid (mempty, (<>))+import Data.String (fromString)  import HERMIT.Context import HERMIT.Core-import HERMIT.Kure+import HERMIT.Dictionary.Reasoning hiding (externals) import HERMIT.External import qualified HERMIT.GHC as GHC-import HERMIT.Kernel (AST, queryK, KernelEnv)-import HERMIT.Kernel.Scoped+import HERMIT.Kernel+import HERMIT.Kure+import HERMIT.Lemma+import HERMIT.Monad import HERMIT.Parser import HERMIT.PrettyPrinter.Common+import HERMIT.Syntax  import HERMIT.Plugin.Display import HERMIT.Plugin.Renderer@@ -42,16 +56,17 @@ import System.Console.Terminfo (setupTermFromEnv, getCapability, termColumns, termLines) #endif +import qualified Text.PrettyPrint.MarkedHughesPJ as PP+ ----------------------------------------------------------------------------------  data QueryFun :: * where-   QueryString   :: (Injection GHC.ModGuts g, Walker HermitC g)-                 => TransformH g String                                   -> QueryFun-   QueryDocH     :: (PrettyC -> PrettyH CoreTC -> TransformH CoreTC DocH) -> QueryFun-   Diff          :: SAST -> SAST                                          -> QueryFun-   Display       ::                                                          QueryFun-   Inquiry       :: (CommandLineState -> IO String)                       -> QueryFun-   CorrectnessCritera :: (Injection GHC.ModGuts g, Walker HermitC g) => TransformH g () -> QueryFun+   QueryString  :: Injection a LCoreTC => TransformH a String       -> QueryFun+   QueryDocH    :: Injection a LCoreTC => TransformH a DocH         -> QueryFun+   QueryPrettyH :: Injection a LCoreTC => PrettyH a                 -> QueryFun+   Diff         :: AST -> AST                                       -> QueryFun+   Inquiry      :: (CommandLineState -> IO String)                  -> QueryFun+   QueryUnit    :: Injection a LCoreTC => TransformH a ()           -> QueryFun    deriving Typeable  message :: String -> QueryFun@@ -63,91 +78,85 @@    unbox i = i  performQuery :: (MonadCatch m, CLMonad m) => QueryFun -> ExprH -> m ()--performQuery (QueryString q) _ = do-    st <- get-    str <- prefixFailMsg "Query failed: " $ queryS (cl_kernel st) q (cl_kernel_env st) (cl_cursor st)-    putStrToConsole str+performQuery qf expr = go qf+    where cm = Changed $ unparseExprH expr+          go (QueryString q) =+            putStrToConsole =<< prefixFailMsg "Query failed: " (queryInContext (promoteT q) cm) -performQuery (QueryDocH q) _ = do-    st <- get-    doc <- prefixFailMsg "Query failed: " $ queryS (cl_kernel st) (q (initPrettyC $ cl_pretty_opts st) $ pCoreTC $ cl_pretty st) (cl_kernel_env st) (cl_cursor st)-    liftIO $ cl_render st stdout (cl_pretty_opts st) (Right doc)+          go (QueryDocH q) = do+            doc <- prefixFailMsg "Query failed: " $ queryInContext (promoteT q) cm+            st <- get+            liftIO $ cl_render st stdout (cl_pretty_opts st) (Right doc) -performQuery (Inquiry f) _ = get >>= liftIO . f >>= putStrToConsole+          go (QueryPrettyH q) = do+            st <- get+            doc <- prefixFailMsg "Query failed: " $ queryInContext (liftPrettyH (pOptions (cl_pretty st)) $ promoteT q) cm+            liftIO $ cl_render st stdout (cl_pretty_opts st) (Right doc) -performQuery (Diff s1 s2) _ = do-    st <- get+          go (Inquiry f) = get >>= liftIO . f >>= putStrToConsole -    ast1 <- toASTS (cl_kernel st) s1-    ast2 <- toASTS (cl_kernel st) s2-    let getCmds sast | sast == s1 = []-                     | otherwise = case [ (f,c) | (f,c,to) <- vs_graph (cl_version st), to == sast ] of-                                    [(sast',cmd)] -> unparseExprH cmd : getCmds sast'-                                    _ -> ["error: history broken!"] -- should be impossible+          go (Diff ast1 ast2) = do+            st <- get+            all_asts <- listK (cl_kernel st) -    cl_putStrLn "Commands:"-    cl_putStrLn "========="-    cl_putStrLn $ unlines $ reverse $ getCmds s2+            let getCmds ast+                    | ast == ast1 = []+                    | otherwise   = case [ (p,msg) | (to,msg,Just p) <- all_asts, to == ast ] of+                                            [(ast',msg)] -> fromMaybe "-- unknown command!" msg : getCmds ast'+                                            _ -> ["error: history broken!"] -- should be impossible -    doc1 <- ppWholeProgram ast1-    doc2 <- ppWholeProgram ast2+            cl_putStrLn "Commands:"+            cl_putStrLn "========="+            cl_putStrLn $ unlines $ reverse $ getCmds ast2 -    r <- diffDocH (cl_pretty st) doc1 doc2+            doc1 <- ppWholeProgram ast1+            doc2 <- ppWholeProgram ast2 -    cl_putStrLn "Diff:"-    cl_putStrLn "====="-    cl_putStr r+            r <- diffDocH (cl_pretty st) doc1 doc2 --- Explicit calls to display should work no matter what the loading state is.-performQuery Display _ = do-    running_script_st <- gets cl_running_script-    setRunningScript Nothing-    showWindow-    setRunningScript running_script_st+            cl_putStrLn "Diff:"+            cl_putStrLn "====="+            cl_putStr r -performQuery (CorrectnessCritera q) expr = do-    st <- get-    -- TODO: Again, we may want a quiet version of the kernel_env-    modFailMsg (\ err -> unparseExprH expr ++ " [exception: " ++ err ++ "]")-        $ queryS (cl_kernel st) q (cl_kernel_env st) (cl_cursor st)-    putStrToConsole $ unparseExprH expr ++ " [correct]"+          go (QueryUnit q) = do+            -- TODO: Again, we may want a quiet version of the kernel_env+            let str = unparseExprH expr+            modFailMsg (\ err -> str ++ " [exception: " ++ err ++ "]") $ queryInContext (promoteT q) cm+            putStrToConsole $ str ++ " [correct]" -ppWholeProgram :: (MonadIO m, MonadState CommandLineState m) => AST -> m DocH+ppWholeProgram :: (CLMonad m, MonadCatch m) => AST -> m DocH ppWholeProgram ast = do     st <- get-    liftIO (queryK (kernelS $ cl_kernel st)-            ast-            (extractT $ pathT [ModGuts_Prog] $ liftPrettyH (cl_pretty_opts st) $ pCoreTC $ cl_pretty st)-            (cl_kernel_env st)) >>= runKureM return fail+    d <- queryK (cl_kernel st)+                (extractT $ pathT [ModGuts_Prog] $ liftPrettyH (cl_pretty_opts st) $ pCoreTC $ cl_pretty st)+                Never+                (cl_kernel_env st) ast+    return $ snd d -- discard new AST, assuming pp won't create one  ---------------------------------------------------------------------------------- -data VersionCmd = Back                  -- back (up) the derivation tree-                | Step                  -- down one step; assumes only one choice-                | Goto Int              -- goto a specific node, if possible-                | GotoTag String        -- goto a specific named tag-                | AddTag String         -- add a tag+type TagName = String+data VersionCmd = Back            -- back (up) the derivation tree+                | Step            -- down one step; assumes only one choice+                | Goto AST        -- goto a specific AST+                | GotoTag TagName -- goto a specific AST, by tag name+                | Tag TagName     -- tag the current AST with a name         deriving Show  ----------------------------------------------------------------------------------  data CLException = CLAbort-                 | CLResume SAST+                 | CLResume AST                  | CLContinue CommandLineState -- TODO: needed?                  | CLError String -#if !(MIN_VERSION_mtl(2,2,1))-instance Error CLException where strMsg = CLError-#endif--abort :: MonadError CLException m => m ()+abort :: MonadError CLException m => m a abort = throwError CLAbort -resume :: MonadError CLException m => SAST -> m ()+resume :: MonadError CLException m => AST -> m a resume = throwError . CLResume -continue :: MonadError CLException m => CommandLineState -> m ()+continue :: MonadError CLException m => CommandLineState -> m a continue = throwError . CLContinue  rethrowCLE :: CLException -> PluginM a@@ -171,20 +180,14 @@ -- management in the command line code. -- -- NB: an alternative to monad transformers, like Oleg's Extensible Effects, might be useful here.-#if MIN_VERSION_mtl(2,2,1) newtype CLT m a = CLT { unCLT :: ExceptT CLException (StateT CommandLineState m) a }-#else-newtype CLT m a = CLT { unCLT :: ErrorT CLException (StateT CommandLineState m) a }-#endif     deriving (Functor, Applicative, MonadIO, MonadError CLException, MonadState CommandLineState)  -- Adapted from System.Console.Haskeline.MonadException, which hasn't provided an instance for ExceptT yet-#if MIN_VERSION_mtl(2,2,1) instance MonadException m => MonadException (ExceptT e m) where     controlIO f = ExceptT $ controlIO $ \(RunIO run) -> let                     run' = RunIO (fmap ExceptT . run . runExceptT)                     in fmap runExceptT $ f run'-#endif  instance MonadException m => MonadException (CLT m) where     controlIO f = CLT $ controlIO $ \(RunIO run) -> let run' = RunIO (fmap CLT . run . unCLT)@@ -214,11 +217,7 @@  -- | Run a CLT computation. runCLT :: CommandLineState -> CLT m a -> m (Either CLException a, CommandLineState)-#if MIN_VERSION_mtl(2,2,1) runCLT s = flip runStateT s . runExceptT . unCLT-#else-runCLT s = flip runStateT s . runErrorT . unCLT-#endif  -- | Lift a CLT IO computation into a CLT computation over an arbitrary MonadIO. clm2clt :: MonadIO m => CLT IO a -> CLT m a@@ -259,20 +258,6 @@  ---------------------------------------------------------------------------------- -data VersionStore = VersionStore-    { vs_graph       :: [(SAST,ExprH,SAST)]-    , vs_tags        :: [(String,SAST)]-    }--newSAST :: ExprH -> SAST -> CommandLineState -> CommandLineState-newSAST expr sast st = st { cl_pstate  = pstate  { ps_cursor = sast }-                          , cl_version = version { vs_graph = (ps_cursor pstate, expr, sast) : vs_graph version }-                          }-    where pstate  = cl_pstate st-          version = cl_version st------------------------------------------------------------------------------------- -- Session-local issues; things that are never saved (except the PluginState). data CommandLineState = CommandLineState     { cl_pstate         :: PluginState            -- ^ Access to the enclosing plugin state. This is propagated back@@ -281,14 +266,37 @@     , cl_height         :: Int                    -- ^ console height, in lines     , cl_scripts        :: [(ScriptName,Script)]     , cl_nav            :: Bool                   -- ^ keyboard input the nav panel-    , cl_version        :: VersionStore+    , cl_foci           :: M.Map AST PathStack    -- ^ focus assigned to each AST+    , cl_tags           :: M.Map AST [String]     -- ^ list of tags on an AST+    , cl_proofstack     :: M.Map AST [ProofTodo]  -- ^ stack of todos for the proof shell     , cl_window         :: PathH                  -- ^ path to beginning of window, always a prefix of focus path in kernel     , cl_externals      :: [External]             -- ^ Currently visible externals     , cl_running_script :: Maybe Script           -- ^ Nothing = no script running, otherwise the remaining script commands-    -- this should be in a reader-    , cl_initSAST       :: SAST+    , cl_safety         :: Safety                 -- ^ which level of safety we are running in     } deriving (Typeable) +type PathStack = ([LocalPathH], LocalPathH)++data ProofTodo = Unproven+                    { ptName    :: LemmaName    -- ^ lemma we are proving+                    , ptLemma   :: Lemma+                    , ptContext :: HermitC      -- ^ context in which lemma is being proved+                    , ptAssumed :: [NamedLemma] -- ^ temporary lemmas in scope+                    , ptPath    :: PathStack    -- ^ path into lemma to focus on+                    }+               | MarkProven { ptName :: LemmaName, ptTemp :: Bool } -- ^ lemma successfully proven, temporary status++data Safety = StrictSafety | NormalSafety | NoSafety++filterSafety :: Safety -> [External] -> [External]+filterSafety NoSafety     = id+filterSafety NormalSafety = filter ((Unsafe `notElem`) . externTags)+filterSafety StrictSafety = filter ((`notElem` ["assume"]) . externName) . filterSafety NormalSafety+-- TODO: currently, we only prevent assuming proofs in strict mode+-- it would probably be better to explicitly tag every command allowed+-- in strict safety mode with the 'Safe' tag, then change this to:+-- filterSafety StrictSafety = filter ((Safe `elem`) . externTags)+ -- To ease the pain of nested records, define some boilerplate here. cl_corelint :: CommandLineState -> Bool cl_corelint = ps_corelint . cl_pstate@@ -296,11 +304,11 @@ setCoreLint :: CommandLineState -> Bool -> CommandLineState setCoreLint st b = st { cl_pstate = (cl_pstate st) { ps_corelint = b } } -cl_cursor :: CommandLineState -> SAST+cl_cursor :: CommandLineState -> AST cl_cursor = ps_cursor . cl_pstate -setCursor :: CommandLineState -> SAST -> CommandLineState-setCursor st sast = st { cl_pstate = (cl_pstate st) { ps_cursor = sast } }+setCursor :: AST -> CommandLineState -> CommandLineState+setCursor sast st = st { cl_pstate = (cl_pstate st) { ps_cursor = sast } }  cl_diffonly :: CommandLineState -> Bool cl_diffonly = ps_diffonly . cl_pstate@@ -314,7 +322,7 @@ setFailHard :: CommandLineState -> Bool -> CommandLineState setFailHard st b = st { cl_pstate = (cl_pstate st) { ps_failhard = b } } -cl_kernel :: CommandLineState -> ScopedKernel+cl_kernel :: CommandLineState -> Kernel cl_kernel = ps_kernel . cl_pstate  cl_kernel_env :: CommandLineState -> KernelEnv@@ -345,11 +353,13 @@                               , cl_height         = h                               , cl_scripts        = []                               , cl_nav            = False-                              , cl_version        = VersionStore { vs_graph = [] , vs_tags = [] }+                              , cl_foci           = M.empty+                              , cl_tags           = M.empty+                              , cl_proofstack     = M.empty                               , cl_window         = mempty                               , cl_externals      = [] -- Note, empty dictionary.                               , cl_running_script = Nothing-                              , cl_initSAST       = ps_cursor ps+                              , cl_safety         = NormalSafety                               }     return $ setPrettyOpts st $ (cl_pretty_opts st) { po_width = w } @@ -401,32 +411,230 @@  ------------------------------------------------------------------------------ +pathStack2Path :: ([LocalPath crumb], LocalPath crumb) -> Path crumb+pathStack2Path (ps,p) = concat $ reverse (map snocPathToPath (p:ps))++-- | A primitive means of denoting navigation of a tree (within a local scope).+data Direction = U -- ^ Up+               | T -- ^ Top+               deriving (Eq,Show)++pathStackToLens :: (Injection a g, Walker HermitC g) => [LocalPathH] -> LocalPathH -> LensH a g+pathStackToLens ps p = injectL >>> pathL (pathStack2Path (ps,p))++getPathStack :: CLMonad m => m ([LocalPathH], LocalPathH)+getPathStack = do+    st <- get+    return $ fromMaybe ([],mempty) (M.lookup (cl_cursor st) (cl_foci st))++getFocusPath :: CLMonad m => m PathH+getFocusPath = liftM pathStack2Path getPathStack++addFocusT :: (Injection a g, Walker HermitC g, CLMonad m) => TransformH g b -> m (TransformH a b)+addFocusT t = do+    (base, rel) <- getPathStack+    return $ focusT (pathStackToLens base rel) t++addFocusR :: (Injection a g, Walker HermitC g, CLMonad m) => RewriteH g -> m (RewriteH a)+addFocusR r = do+    (base, rel) <- getPathStack+    return $ focusR (pathStackToLens base rel) r++------------------------------------------------------------------------------++addAST :: CLMonad m => AST -> m ()+addAST ast = do+    copyProofStack ast+    copyPathStack ast+    modify $ setCursor ast++modifyLocalPath :: (MonadCatch m, CLMonad m) => (LocalPathH -> LocalPathH) -> ExprH -> m ()+modifyLocalPath f expr = do+    ps <- getProofStackEmpty+    (k,(kEnv,ast)) <- gets (cl_kernel &&& cl_kernel_env &&& cl_cursor)+    case ps of+        todo@(Unproven _ (Lemma q _ _ _) c _ _) : todos -> do+            let (base, rel) = ptPath todo+                rel' = f rel+            requireDifferent rel rel'+            (ast',()) <- queryK k (constT+                                    (applyT+                                      (setFailMsg "invalid path."+                                        (focusT (pathStackToLens base rel' :: LensH Quantified LCoreTC) successT))+                                      c q))+                                  (Always $ unparseExprH expr) kEnv ast+            addAST ast'+            let todo' = todo { ptPath = (base, rel') }+            modify $ \ st -> st { cl_proofstack = M.insert (cl_cursor st) (todo':todos) (cl_proofstack st) }+        _ -> do+            (base, rel) <- getPathStack+            let rel' = f rel+            requireDifferent rel rel'+            -- we are testing paths, so the sum type matters+            (ast',()) <- queryK k (setFailMsg "invalid path."+                                    (focusT (pathStackToLens base rel' :: LensH GHC.ModGuts CoreTC) successT))+                                  (Always $ unparseExprH expr) kEnv ast+            addAST ast'+            modify $ \ st -> st { cl_foci = M.insert (cl_cursor st) (base, rel') (cl_foci st) }++requireDifferent :: Monad m => LocalPathH -> LocalPathH -> m ()+requireDifferent p1 p2 = when (p1 == p2) $ fail "path unchanged, nothing to do."++copyPathStack :: CLMonad m => AST -> m ()+copyPathStack ast = do+    (base, rel) <- getPathStack+    modify $ \ st -> st { cl_foci = M.insert ast (base, rel) (cl_foci st) }++copyProofStack :: CLMonad m => AST -> m ()+copyProofStack ast = modify $ \ st -> let newStack = fromMaybe [] $ M.lookup (cl_cursor st) (cl_proofstack st)+                                      in st { cl_proofstack = M.insert ast newStack (cl_proofstack st) }++pushProofStack :: CLMonad m => ProofTodo -> m ()+pushProofStack todo = modify $ \ st -> st { cl_proofstack = M.insertWith (++) (cl_cursor st) [todo] (cl_proofstack st) }++popProofStack :: CLMonad m => m ProofTodo+popProofStack = do+    t : ts <- getProofStack+    modify $ \ st -> st { cl_proofstack = M.insert (cl_cursor st) ts (cl_proofstack st) }+    return t++currentLemma :: CLMonad m => m (LemmaName, Lemma, HermitC, [NamedLemma], PathStack)+currentLemma = do+    todo : _ <- getProofStack++    case todo of+        Unproven nm l c ls p -> return (nm, l, c, ls, p)+        _ -> fail "currentLemma: unproven lemma not on top of stack!"++announceProven :: (MonadCatch m, CLMonad m) => m ()+announceProven = getProofStack >>= go+    where go (MarkProven nm temp : r) = do+            queryInFocus (if temp then constT (deleteLemma nm) else modifyLemmaT nm id idR (const Proven) id :: TransformH Core ())+                         (Always $ "-- proven " ++ quoteShow nm) -- comment in script+            -- take it off the stack for the new AST+            modify $ \ st -> st { cl_proofstack = M.insert (cl_cursor st) r (cl_proofstack st) }+            cl_putStrLn ("Successfully proven: " ++ show nm) >> go r+          go _ = return ()++announceUnprovens :: (MonadCatch m, CLMonad m) => m ()+announceUnprovens = do+    (c,m) <- queryInFocus (contextT &&& getLemmasT :: TransformH LCore (HermitC,Lemmas)) Never+    sf <- gets cl_safety+    case sf of+        StrictSafety -> do+            let ls = [ nl | nl@(_,Lemma _ p u _) <- M.toList m, p `elem` [NotProven, Assumed True], u /= NotUsed ]+            forM_ ls $ \ nl@(nm,_) -> do+                cl_putStrLn $ "Fatal: Lemma " ++ show nm ++ " has not been proven, but was used."+                printLemma stdout c mempty nl+            unless (null ls) abort -- don't finish if this happens+        NormalSafety -> do+            let np = [ nl | nl@(_,Lemma _ NotProven u _) <- M.toList m, u /= NotUsed ]+            forM_ np $ \ nl@(nm,_) -> do+                cl_putStrLn $ "Fatal: Lemma " ++ show nm ++ " has not been proven, but was used."+                printLemma stdout c mempty nl+            unless (null np) abort -- don't finish if this happens+            let as = [ nl | nl@(_,Lemma _ (Assumed True) u _) <- M.toList m, u /= NotUsed ]+            forM_ as $ \ nl@(nm,_) -> do+                cl_putStrLn $ "Warning: Lemma " ++ show nm ++ " was assumed but not proven."+                printLemma stdout c mempty nl+        NoSafety -> return ()++-- | Always returns a non-empty list.+getProofStack :: CLMonad m => m [ProofTodo]+getProofStack = do+    todos <- getProofStackEmpty+    case todos of+        [] -> fail "No lemma currently being proved."+        _ -> return todos++getProofStackEmpty :: CLMonad m => m [ProofTodo]+getProofStackEmpty = do+    (ps, ast) <- gets (cl_proofstack &&& cl_cursor)++    maybe (return []) return $ M.lookup ast ps++------------------------------------------------------------------------------+ fixWindow :: CLMonad m => m () fixWindow = do-    st <- get     -- check to make sure new path is still inside window-    focusPath <- pluginM getFocusPath+    focusPath <- getFocusPath     -- move the window in two cases:     --  1. window path is not prefix of focus path     --  2. window path is empty (since at the top level we only show type sigs)     {- when (not (isPrefixOf (cl_window st) focusPath) || null (cl_window st))        $ put $ st { cl_window = focusPath } -}-    put $ st { cl_window = focusPath } -- TODO: temporary until we figure out a better highlight interface+    modify $ \ st -> st { cl_window = focusPath  } -- TODO: temporary until we figure out a better highlight interface -showWindow :: CLMonad m => m ()-showWindow = ifM isRunningScript (return ()) $ fixWindow >> gets cl_window >>= pluginM . display . Just+showWindow :: (MonadCatch m, CLMonad m) => Maybe Handle -> m ()+showWindow mbh = do+    (ps,(ast,(pp,render))) <- gets (cl_proofstack &&& cl_cursor &&& cl_pretty &&& (ps_render . cl_pstate))+    let h = fromMaybe stdout mbh+        pStr = render h (pOptions pp) . Left+    case M.lookup ast ps of+        Just (Unproven _ l c ls p : _)  -> do+            unless (null ls) $ do+                liftIO $ pStr "Assumed lemmas:\n"+                mapM_ (printLemma h c mempty)+                      [ (fromString (show i) <> ": " <> n, lem)+                      | (i::Int,(n,lem)) <- zip [0..] ls ]+            printLemma h c p ("Goal:",l)+        _ -> do st <- get+                if cl_diffonly st+                then do+                    let k = cl_kernel st -------------------------------------------------------------------------------+                    all_asts <- listK k -showGraph :: [(SAST,ExprH,SAST)] -> [(String,SAST)] -> SAST -> String-showGraph graph tags this@(SAST n) =-        (if length paths > 1 then "tag " ++ show n ++ "\n" else "") ++-        concat (intercalate-                ["goto " ++ show n ++ "\n"]-                [ [ unparseExprH b ++ "\n" ++ showGraph graph tags c ]-                | (b,c) <- paths-                ])-  where-          paths = [ (b,c) | (a,b,c) <- graph, a == this ]+                    let kEnv = cl_kernel_env st+                        ast' = head $ [ cur | (cur, _, Just p) <- all_asts, p == ast ] ++ [ast]+                        ppOpts = cl_pretty_opts st +                    q <- addFocusT $ liftPrettyH ppOpts $ pCoreTC pp+                    (_,doc1) <- queryK k q Never kEnv ast+                    (_,doc2) <- queryK k q Never kEnv ast'+                    diffDocH pp doc1 doc2 >>= liftIO . pStr -- TODO+                else fixWindow >> gets cl_window >>= pluginM . display mbh . Just --TODO++printLemma :: (MonadCatch m, MonadError CLException m, MonadIO m, MonadState CommandLineState m)+           => Handle -> HermitC -> PathStack -> (LemmaName,Lemma) -> m ()+printLemma h c p (nm,Lemma q _ _ _) = do -- TODO+    pp <- gets cl_pretty+    doc <- queryInFocus ((constT $ applyT (extractT (liftPrettyH (pOptions pp) (pathT (pathStack2Path p) (ppLCoreTCT pp)))) c q) :: TransformH Core DocH) Never+    let doc' = PP.text (show nm) PP.$+$ PP.nest 2 doc+    st <- get+    liftIO $ cl_render st h (cl_pretty_opts st) (Right doc')+ ------------------------------------------------------------------------------++queryInFocus :: (Walker HermitC g, Injection GHC.ModGuts g, MonadCatch m, CLMonad m)+             => TransformH g b -> CommitMsg -> m b+queryInFocus t msg = do+    q <- addFocusT t+    st <- get+    (ast', r) <- queryK (cl_kernel st) q msg (cl_kernel_env st) (cl_cursor st)+    addAST ast'+    return r++-- meant to be used inside queryInFocus+inProofFocusT :: ProofTodo -> TransformH LCoreTC b -> TransformH Core b+inProofFocusT (Unproven _ (Lemma q _ _ _) c ls ps) t =+    contextfreeT $ withLemmas (M.fromList ls) . applyT (return q >>> extractT (pathT (pathStack2Path ps) t)) c+inProofFocusT _ _ = fail "no proof in progress."++inProofFocusR :: ProofTodo -> RewriteH LCoreTC -> TransformH Core Quantified+inProofFocusR (Unproven _ (Lemma q _ _ _) c ls ps) rr =+    contextfreeT $ withLemmas (M.fromList ls) . applyT (return q >>> extractR (pathR (pathStack2Path ps) rr)) c+inProofFocusR _ _ = fail "no proof in progress."++withLemmasInScope :: HasLemmas m => [(LemmaName,Lemma)] -> Transform c m a b -> Transform c m a b+withLemmasInScope ls t = transform $ \ c -> withLemmas (M.fromList ls) . applyT t c++-- TODO: better name+queryInContext :: forall b m. (MonadCatch m, CLMonad m) => TransformH LCoreTC b -> CommitMsg -> m b+queryInContext tr cm = do+    ps <- getProofStackEmpty+    case ps of+        todo@(Unproven {}) : _+          -> {- GHC.trace "in proof context" $  -}  queryInFocus (inProofFocusT todo tr) cm+        _ -> {- GHC.trace "in modguts context" $ -} queryInFocus (extractT tr :: TransformH CoreTC b) cm
src/HERMIT/Syntax.hs view
@@ -1,6 +1,6 @@ module HERMIT.Syntax-   (-      -- * Utility Predicates for lexing Identifiers+    ( -- * Utility Predicates for lexing Identifiers+      quoteShow,       -- ** Lexing HERMIT Scripts       isScriptIdFirstChar,       isScriptIdChar,@@ -9,8 +9,7 @@       isCoreIdFirstChar,       isCoreIdChar,       isCoreInfixIdChar-   )-where+    ) where  import Data.Char (isAlphaNum, isAlpha) @@ -57,3 +56,7 @@ infixOperatorSymbols = "!£$%^&*-+=@#<>?/.:|"  ---------------------------------------------------------------------++quoteShow :: Show a => a -> String+quoteShow x = if all isScriptIdChar s then s else show s+    where s = show x
src/HERMIT/Win32/IO.hsc view
@@ -25,11 +25,7 @@ import Data.Char (ord) import Data.Typeable -#if MIN_VERSION_base(4,7,0) import Foreign-#else-import Foreign hiding (unsafePerformIO)-#endif import Foreign.C.Types  import GHC.IO.FD (FD(..)) -- A wrapper around an Int32