hermit 0.5.0.0 → 0.6.0.0
raw patch · 78 files changed
+3708/−2857 lines, 78 filesdep +Win32dep ~ghcdep ~kurePVP ok
version bump matches the API change (PVP)
Dependencies added: Win32
Dependency ranges changed: ghc, kure
API changes (from Hackage documentation)
- HERMIT.Core: endoFunExprType :: Monad m => CoreExpr -> m Type
- HERMIT.Core: endoFunType :: Monad m => Type -> m Type
- HERMIT.Core: funExprArgResTypes :: Monad m => CoreExpr -> m (Type, Type)
- HERMIT.Dictionary.Common: callsR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, HasEmptyContext c, MonadCatch m) => String -> Rewrite c m CoreExpr -> Rewrite c m Core
- HERMIT.Dictionary.Common: callsT :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, HasEmptyContext c, MonadCatch m) => String -> Transform c m CoreExpr b -> Transform c m Core [b]
- HERMIT.Dictionary.FixPoint: mkFixT :: (BoundVars c, MonadCatch m, HasModGuts m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => CoreExpr -> Transform c m z CoreExpr
- HERMIT.Dictionary.Local: betaReducePlusR :: MonadCatch m => Rewrite c m CoreExpr
- HERMIT.Dictionary.Local.Case: caseReduceIdR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => Bool -> Rewrite c HermitM CoreExpr
- HERMIT.Dictionary.Reasoning: CoreExprEquality :: [CoreBndr] -> CoreExpr -> CoreExpr -> CoreExprEquality
- HERMIT.Dictionary.Reasoning: RewriteCoreExprEqualityBox :: (RewriteH CoreExprEquality) -> RewriteCoreExprEqualityBox
- HERMIT.Dictionary.Reasoning: TransformCoreExprEqualityStringBox :: (TransformH CoreExprEquality String) -> TransformCoreExprEqualityStringBox
- HERMIT.Dictionary.Reasoning: data CoreExprEquality
- HERMIT.Dictionary.Reasoning: data RewriteCoreExprEqualityBox
- HERMIT.Dictionary.Reasoning: data TransformCoreExprEqualityStringBox
- HERMIT.Dictionary.Reasoning: flipCoreExprEquality :: CoreExprEquality -> CoreExprEquality
- HERMIT.Dictionary.Reasoning: instance Extern (RewriteH CoreExprEquality)
- HERMIT.Dictionary.Reasoning: instance Extern (TransformH CoreExprEquality String)
- HERMIT.Dictionary.Reasoning: instance Typeable RewriteCoreExprEqualityBox
- HERMIT.Dictionary.Reasoning: instance Typeable TransformCoreExprEqualityStringBox
- HERMIT.Dictionary.Reasoning: ppCoreExprEqualityT :: PrettyPrinter -> TransformH CoreExprEquality DocH
- HERMIT.Dictionary.Reasoning: proveCoreExprEqualityT :: (AddBindings c, Monad m, ReadPath c Crumb) => CoreExprEqualityProof c m -> Transform c m CoreExprEquality ()
- HERMIT.Dictionary.Reasoning: type CoreExprEqualityProof c m = (Rewrite c m CoreExpr, Rewrite c m CoreExpr)
- HERMIT.Dictionary.Reasoning: verifyCoreExprEqualityT :: Monad m => Transform c m CoreExprEquality ()
- HERMIT.Dictionary.Rules: type RuleNameString = String
- HERMIT.Dictionary.Unfold: cleanupUnfoldR :: (AddBindings c, ExtendPath c Crumb, MonadCatch m) => Rewrite c m CoreExpr
- HERMIT.External: CoreBox :: CoreString -> CoreBox
- HERMIT.External: addToDictionary :: External -> Dictionary -> Dictionary
- HERMIT.External: data CoreBox
- HERMIT.External: instance Typeable CoreBox
- HERMIT.External: toDictionary :: [External] -> Dictionary
- HERMIT.External: type Dictionary = Map ExternalName [Dynamic]
- HERMIT.GHC: buildDictionary :: ModGuts -> Id -> CoreM (Id, [CoreBind])
- HERMIT.GHC: buildTypeable :: ModGuts -> Type -> CoreM (Id, [CoreBind])
- HERMIT.GHC: findNamesFromString :: GlobalRdrEnv -> String -> [Name]
- HERMIT.GHC: fqName :: Name -> String
- HERMIT.GHC: lookupRdrNameInModuleForPlugins :: HscEnv -> ModGuts -> ModuleName -> RdrName -> IO (Maybe Name)
- HERMIT.GHC: mkPhiTy :: [PredType] -> Type -> Type
- HERMIT.GHC: mkSigmaTy :: [TyVar] -> [PredType] -> Type -> Type
- HERMIT.GHC: occurAnalyseExpr :: CoreExpr -> CoreExpr
- HERMIT.GHC: runDsMtoCoreM :: ModGuts -> DsM a -> CoreM a
- HERMIT.GHC: runTcMtoCoreM :: ModGuts -> TcM a -> CoreM a
- HERMIT.GHC: uqName :: NamedThing nm => nm -> String
- HERMIT.GHC: var2String :: Var -> String
- HERMIT.Monad: class HasModGuts m
- HERMIT.Monad: cloneVarH :: (String -> String) -> Var -> HermitM Var
- HERMIT.Monad: hs_debugChan :: HermitMEnv -> DebugMessage -> HermitM ()
- HERMIT.Monad: instance HasModGuts HermitM
- HERMIT.Monad: mkHermitMEnv :: (DebugMessage -> HermitM ()) -> HermitMEnv
- HERMIT.Monad: newCoVarH :: String -> Type -> HermitM TyVar
- HERMIT.Monad: newGlobalIdH :: String -> Type -> HermitM Id
- HERMIT.Monad: newIdH :: String -> Type -> HermitM Id
- HERMIT.Monad: newTyVarH :: String -> Kind -> HermitM TyVar
- HERMIT.Monad: newVarH :: String -> KindOrType -> HermitM Var
- HERMIT.Monad: newtype HermitMEnv
- HERMIT.Monad: type Label = String
- HERMIT.Plugin: allPhases :: HPM () -> HPM ()
- HERMIT.Plugin: firstPhase :: HPM () -> HPM ()
- HERMIT.Plugin: getPhaseInfo :: HPM PhaseInfo
- HERMIT.Plugin: lastPhase :: HPM () -> HPM ()
- HERMIT.Plugin: phase :: Int -> HPM () -> HPM ()
- HERMIT.Plugin.Builder: PhaseInfo :: Int -> [CorePass] -> [CorePass] -> PhaseInfo
- HERMIT.Plugin.Builder: data PhaseInfo
- HERMIT.Plugin.Builder: getPhaseFlag :: [CommandLineOption] -> Maybe (Int, [CommandLineOption])
- HERMIT.Plugin.Builder: instance Eq PhaseInfo
- HERMIT.Plugin.Builder: instance Read PhaseInfo
- HERMIT.Plugin.Builder: instance Show PhaseInfo
- HERMIT.Plugin.Builder: phaseNum :: PhaseInfo -> Int
- HERMIT.Plugin.Builder: phasesDone :: PhaseInfo -> [CorePass]
- HERMIT.Plugin.Builder: phasesLeft :: PhaseInfo -> [CorePass]
- HERMIT.Plugin.Types: ps_phase :: PluginState -> PhaseInfo
- HERMIT.Shell.Dictionary: mkDict :: [External] -> Dictionary
- HERMIT.Shell.Externals: KernelEffect :: KernelEffect -> ShellCommand
- HERMIT.Shell.Externals: ProofCommand :: ProofCommand -> ShellCommand
- HERMIT.Shell.Externals: QueryFun :: QueryFun -> ShellCommand
- HERMIT.Shell.Externals: ScriptEffect :: ScriptEffect -> ShellCommand
- HERMIT.Shell.Externals: ShellEffect :: ShellEffect -> ShellCommand
- HERMIT.Shell.Externals: data ShellCommand
- HERMIT.Shell.Externals: interpShellCommand :: [Interp ShellCommand]
- HERMIT.Shell.Interpreter: instance Functor Interp
- HERMIT.Shell.KernelEffect: Apply :: RewriteH g -> KernelEffect
- HERMIT.Shell.KernelEffect: Pathfinder :: TransformH g LocalPathH -> KernelEffect
- HERMIT.Shell.Proof: ModifyLemma :: LemmaName -> (String -> String) -> (RewriteH CoreExprEquality) -> (Bool -> Bool) -> ProofCommand
- HERMIT.Shell.Proof: QueryLemma :: LemmaName -> (TransformH CoreExprEquality String) -> ProofCommand
- HERMIT.Shell.Proof: RuleToLemma :: RuleNameString -> ProofCommand
- HERMIT.Shell.Types: AmbiguousC :: [CompletionType] -> CompletionType
- HERMIT.Shell.Types: BindingGroupOfC :: CompletionType
- HERMIT.Shell.Types: BindingOfC :: CompletionType
- HERMIT.Shell.Types: CommandC :: CompletionType
- HERMIT.Shell.Types: ConsiderC :: CompletionType
- HERMIT.Shell.Types: InlineC :: CompletionType
- HERMIT.Shell.Types: OccurrenceOfC :: CompletionType
- HERMIT.Shell.Types: RhsOfC :: CompletionType
- HERMIT.Shell.Types: cl_lemmas :: CommandLineState -> [Lemma]
- HERMIT.Shell.Types: completionQuery :: CommandLineState -> CompletionType -> IO (TransformH CoreTC [String])
- HERMIT.Shell.Types: completionType :: String -> CompletionType
- HERMIT.Shell.Types: data CompletionType
- HERMIT.Shell.Types: instance Show CompletionType
- HERMIT.Shell.Types: shellComplete :: MVar CommandLineState -> String -> String -> IO [Completion]
- HERMIT.Shell.Types: type Lemma = (LemmaName, CoreExprEquality, Bool)
- HERMIT.Shell.Types: type LemmaName = String
+ HERMIT.Core: endoFunExprTypeM :: MonadCatch m => CoreExpr -> m ([TyVar], Type)
+ HERMIT.Core: endoFunTypeM :: MonadCatch m => Type -> m ([TyVar], Type)
+ HERMIT.Core: funExprArgResTypesM :: MonadCatch m => CoreExpr -> m ([TyVar], Type, Type)
+ 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: smashR :: (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb, MonadCatch m, MonadUnique m) => Rewrite c m Core
+ 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.FixPoint: fixIntroNonRecR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb, HasHermitMEnv m, HasHscEnv m, MonadCatch m, MonadIO m, MonadThings m, MonadUnique m) => Rewrite c m CoreBind
+ HERMIT.Dictionary.FixPoint: fixIntroRecR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb, HasHermitMEnv m, HasHscEnv m, MonadCatch m, MonadIO m, MonadThings m, MonadUnique m) => Rewrite c m CoreDef
+ HERMIT.Dictionary.Function: appArgM :: Monad m => Int -> CoreExpr -> m CoreExpr
+ HERMIT.Dictionary.Function: buildApplicationM :: (HasDynFlags m, MonadCatch m, MonadIO m) => CoreExpr -> CoreExpr -> m 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: buildFixT :: (BoundVars c, HasHscEnv m, HasHermitMEnv m, MonadCatch m, MonadIO m, MonadThings m) => CoreExpr -> Transform c m x CoreExpr
+ HERMIT.Dictionary.Function: buildIdT :: (BoundVars c, HasHscEnv m, HasHermitMEnv m, MonadCatch m, MonadIO m, MonadThings m) => Type -> Transform c m x CoreExpr
+ HERMIT.Dictionary.GHC: buildDictionary :: (HasDynFlags m, HasHermitMEnv m, HasHscEnv m, MonadIO m) => Id -> m (Id, [CoreBind])
+ HERMIT.Dictionary.GHC: buildDictionaryT :: (HasDynFlags m, HasHermitMEnv m, HasHscEnv m, MonadCatch m, MonadIO m, MonadUnique m) => Transform c m Type CoreExpr
+ HERMIT.Dictionary.GHC: buildTypeable :: (HasDynFlags m, HasHermitMEnv m, HasHscEnv m, MonadIO m) => Type -> m (Id, [CoreBind])
+ HERMIT.Dictionary.Kure: betweenR :: MonadCatch m => Int -> Int -> Rewrite c m a -> Rewrite c m a
+ 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.Let: letFloatCaseAltR :: MonadCatch m => Maybe Int -> Rewrite c m CoreExpr
+ HERMIT.Dictionary.Navigation: instance Extern Considerable
+ HERMIT.Dictionary.Navigation: instance Typeable Considerable
+ HERMIT.Dictionary.Navigation: string2considerable :: String -> Maybe Considerable
+ HERMIT.Dictionary.Reasoning: flipEquality :: Equality -> Equality
+ HERMIT.Dictionary.Reasoning: getLemmaByNameT :: (HasLemmas m, Monad m) => LemmaName -> Transform c m x Lemma
+ HERMIT.Dictionary.Reasoning: getLemmasT :: HasLemmas m => Transform c m x Lemmas
+ HERMIT.Dictionary.Reasoning: insertLemmaR :: (HasLemmas m, Monad m) => LemmaName -> Lemma -> Rewrite c m a
+ 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: type EqualityProof c m = (Rewrite c m CoreExpr, Rewrite c m CoreExpr)
+ HERMIT.Dictionary.Reasoning: verifyEqualityT :: Monad m => Transform c m Equality ()
+ HERMIT.Dictionary.Rules: RuleName :: String -> RuleName
+ HERMIT.Dictionary.Rules: RuleNameListBox :: [RuleName] -> RuleNameListBox
+ HERMIT.Dictionary.Rules: instance Eq RuleName
+ HERMIT.Dictionary.Rules: instance Extern RuleName
+ HERMIT.Dictionary.Rules: instance Extern [RuleName]
+ HERMIT.Dictionary.Rules: instance IsString RuleName
+ HERMIT.Dictionary.Rules: instance Show RuleName
+ HERMIT.Dictionary.Rules: instance Typeable RuleName
+ HERMIT.Dictionary.Rules: instance Typeable RuleNameListBox
+ HERMIT.Dictionary.Rules: newtype RuleName
+ HERMIT.Dictionary.Rules: newtype RuleNameListBox
+ HERMIT.Dictionary.Rules: specialiseR :: RewriteH ModGuts
+ 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.Unfold: betaReducePlusR :: MonadCatch m => Rewrite c m 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.Common: externals :: [External]
+ HERMIT.Dictionary.WorkerWrapper.Common: instance Extern WWAssumptionTag
+ HERMIT.Dictionary.WorkerWrapper.Common: instance Typeable WWAssumptionTag
+ 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: 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.Driver: usageOutput :: String
+ HERMIT.External: RewriteEqualityBox :: (RewriteH Equality) -> RewriteEqualityBox
+ HERMIT.External: Strictness :: CmdTag
+ HERMIT.External: TransformEqualityStringBox :: (TransformH Equality String) -> TransformEqualityStringBox
+ HERMIT.External: data RewriteEqualityBox
+ HERMIT.External: data TransformEqualityStringBox
+ HERMIT.External: instance Extern (RewriteH Equality)
+ HERMIT.External: instance Extern (TransformH Equality String)
+ HERMIT.External: instance Extern LemmaName
+ HERMIT.External: instance Extern RememberedName
+ HERMIT.External: instance Typeable CoreString
+ HERMIT.External: instance Typeable RewriteEqualityBox
+ HERMIT.External: instance Typeable TransformEqualityStringBox
+ HERMIT.External: splitFunTyArgs :: TypeRep -> ([TypeRep], TypeRep)
+ HERMIT.GHC: foldBag :: (r -> r -> r) -> (a -> r) -> r -> Bag a -> r
+ HERMIT.GHC: loadSysInterface :: SDoc -> Module -> IfM lcl ModIface
+ HERMIT.GHC: lookupRdrNameInModule :: HscEnv -> ModGuts -> ModuleName -> RdrName -> IO (Maybe Name)
+ HERMIT.GHC: occurAnalyseExpr_NoBinderSwap :: CoreExpr -> CoreExpr
+ HERMIT.GHC: qualifiedName :: Name -> String
+ HERMIT.GHC: reportAllUnsolved :: WantedConstraints -> TcM ()
+ HERMIT.GHC: unqualifiedName :: NamedThing nm => nm -> String
+ HERMIT.GHC: zEncodeString :: UserString -> EncodedString
+ HERMIT.Kernel: KernelEnv :: (DebugMessage -> HermitM ()) -> KernelEnv
+ HERMIT.Kernel: data KernelEnv
+ HERMIT.Kernel: kEnvChan :: KernelEnv -> DebugMessage -> HermitM ()
+ HERMIT.Kure: instance HasDynFlags m => HasDynFlags (Transform c m a)
+ HERMIT.Monad: Equality :: [CoreBndr] -> CoreExpr -> CoreExpr -> Equality
+ HERMIT.Monad: HermitMResult :: DefStash -> Lemmas -> a -> HermitMResult a
+ HERMIT.Monad: Lemma :: Equality -> Bool -> Bool -> Lemma
+ HERMIT.Monad: LemmaName :: String -> LemmaName
+ HERMIT.Monad: RememberedName :: String -> RememberedName
+ HERMIT.Monad: addLemma :: (HasLemmas m, Monad m) => LemmaName -> Lemma -> m ()
+ HERMIT.Monad: class HasDebugChan m
+ HERMIT.Monad: class HasLemmas m
+ HERMIT.Monad: class HasStash m
+ HERMIT.Monad: class Monad m => LiftCoreM m
+ HERMIT.Monad: data Equality
+ HERMIT.Monad: data HermitMEnv
+ HERMIT.Monad: data HermitMResult a
+ HERMIT.Monad: data Lemma
+ HERMIT.Monad: embedHermitM :: (HasDebugChan m, HasHermitMEnv m, HasLemmas m, HasStash m, LiftCoreM m) => HermitM a -> m a
+ HERMIT.Monad: getDebugChan :: HasDebugChan m => m (DebugMessage -> m ())
+ HERMIT.Monad: getLemmas :: HasLemmas m => m Lemmas
+ HERMIT.Monad: hEnvLemmas :: HermitMEnv -> Lemmas
+ HERMIT.Monad: hEnvModGuts :: HermitMEnv -> ModGuts
+ HERMIT.Monad: hEnvStash :: HermitMEnv -> DefStash
+ HERMIT.Monad: hResLemmas :: HermitMResult a -> Lemmas
+ HERMIT.Monad: hResStash :: HermitMResult a -> DefStash
+ HERMIT.Monad: hResult :: HermitMResult a -> a
+ HERMIT.Monad: insertLemma :: HasLemmas m => LemmaName -> Lemma -> m ()
+ HERMIT.Monad: instance Eq LemmaName
+ HERMIT.Monad: instance Eq RememberedName
+ HERMIT.Monad: instance HasDebugChan HermitM
+ HERMIT.Monad: instance HasLemmas HermitM
+ HERMIT.Monad: instance HasStash HermitM
+ HERMIT.Monad: instance IsString LemmaName
+ HERMIT.Monad: instance IsString RememberedName
+ HERMIT.Monad: instance LiftCoreM HermitM
+ 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: mkEnv :: ModGuts -> DefStash -> Lemmas -> HermitMEnv
+ HERMIT.Monad: newtype LemmaName
+ HERMIT.Monad: newtype RememberedName
+ HERMIT.Monad: putStash :: HasStash m => DefStash -> m ()
+ HERMIT.Monad: runDsM :: (HasDynFlags m, HasHermitMEnv m, HasHscEnv m, MonadIO m) => DsM a -> m a
+ HERMIT.Monad: runTcM :: (HasDynFlags m, HasHermitMEnv m, HasHscEnv m, MonadIO m) => TcM a -> m a
+ HERMIT.Monad: type Lemmas = Map LemmaName Lemma
+ HERMIT.Name: BindingName :: HermitName -> BindingName
+ HERMIT.Name: OccurrenceName :: HermitName -> OccurrenceName
+ HERMIT.Name: OccurrenceNameListBox :: [OccurrenceName] -> OccurrenceNameListBox
+ HERMIT.Name: RhsOfName :: HermitName -> RhsOfName
+ HERMIT.Name: cloneVarH :: MonadUnique m => (String -> String) -> Var -> m Var
+ HERMIT.Name: cmpHN2Name :: HermitName -> Name -> Bool
+ HERMIT.Name: cmpHN2Var :: HermitName -> Var -> Bool
+ HERMIT.Name: instance Eq HermitName
+ HERMIT.Name: instance Extern BindingName
+ HERMIT.Name: instance Extern HermitName
+ HERMIT.Name: instance Extern OccurrenceName
+ HERMIT.Name: instance Extern RhsOfName
+ HERMIT.Name: instance Extern [OccurrenceName]
+ HERMIT.Name: instance IsString HermitName
+ HERMIT.Name: instance Show HermitName
+ HERMIT.Name: instance Typeable BindingName
+ HERMIT.Name: instance Typeable HermitName
+ HERMIT.Name: instance Typeable OccurrenceName
+ HERMIT.Name: instance Typeable OccurrenceNameListBox
+ HERMIT.Name: instance Typeable RhsOfName
+ HERMIT.Name: mkBindingPred :: BindingName -> Var -> Bool
+ HERMIT.Name: mkOccPred :: OccurrenceName -> Var -> Bool
+ HERMIT.Name: mkRhsOfPred :: RhsOfName -> Var -> Bool
+ HERMIT.Name: newCoVarH :: MonadUnique m => String -> Type -> m TyVar
+ HERMIT.Name: newGlobalIdH :: MonadUnique m => String -> Type -> m Id
+ HERMIT.Name: newIdH :: MonadUnique m => String -> Type -> m Id
+ HERMIT.Name: newTyVarH :: MonadUnique m => String -> Kind -> m TyVar
+ HERMIT.Name: newVarH :: MonadUnique m => String -> KindOrType -> m Var
+ HERMIT.Name: newtype BindingName
+ HERMIT.Name: newtype OccurrenceName
+ HERMIT.Name: newtype OccurrenceNameListBox
+ HERMIT.Name: newtype RhsOfName
+ HERMIT.Name: showName :: HermitName -> String
+ HERMIT.Name: unBindingName :: BindingName -> HermitName
+ HERMIT.Name: unOccurrenceName :: OccurrenceName -> HermitName
+ HERMIT.Name: unRhsOfName :: RhsOfName -> HermitName
+ HERMIT.Parser: parseExprH :: String -> Either String ExprH
+ 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: 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.Plugin: allPasses :: HPM () -> HPM ()
+ HERMIT.Plugin: firstPass :: HPM () -> HPM ()
+ HERMIT.Plugin: getPassInfo :: HPM PassInfo
+ HERMIT.Plugin: lastPass :: HPM () -> HPM ()
+ HERMIT.Plugin: pass :: Int -> HPM () -> HPM ()
+ HERMIT.Plugin.Builder: PassInfo :: Int -> [CorePass] -> [CorePass] -> PassInfo
+ HERMIT.Plugin.Builder: data PassInfo
+ HERMIT.Plugin.Builder: getPassFlag :: [CommandLineOption] -> Maybe (Int, [CommandLineOption])
+ HERMIT.Plugin.Builder: instance Eq PassInfo
+ HERMIT.Plugin.Builder: instance Read PassInfo
+ HERMIT.Plugin.Builder: instance Show PassInfo
+ HERMIT.Plugin.Builder: passNum :: PassInfo -> Int
+ HERMIT.Plugin.Builder: passesDone :: PassInfo -> [CorePass]
+ HERMIT.Plugin.Builder: passesLeft :: PassInfo -> [CorePass]
+ HERMIT.Plugin.Types: ps_pass :: PluginState -> PassInfo
+ HERMIT.PrettyPrinter.Clean: instance Eq ArrowType
+ HERMIT.PrettyPrinter.Clean: instance Show ArrowType
+ HERMIT.PrettyPrinter.Common: pad :: MDoc a -> MDoc a
+ HERMIT.PrettyPrinter.Common: po_showUniques :: PrettyOptions -> Bool
+ HERMIT.Shell.Command: interpShellCommand :: (MonadCatch m, MonadException m, CLMonad m) => [Interp m ()]
+ HERMIT.Shell.Completion: shellComplete :: (MonadCatch m, MonadIO m, MonadState CommandLineState m) => String -> String -> m [Completion]
+ HERMIT.Shell.Dictionary: addToDictionary :: External -> Dictionary -> Dictionary
+ HERMIT.Shell.Dictionary: mkDictionary :: [External] -> Dictionary
+ HERMIT.Shell.Interpreter: exprToDyns :: MonadState CommandLineState m => ExprH -> m [Dynamic]
+ HERMIT.Shell.Interpreter: instance Monad m => Functor (Interp m)
+ HERMIT.Shell.Interpreter: interpEM :: (CLMonad m, Typeable b) => (b -> ExprH -> m a) -> Interp m a
+ HERMIT.Shell.Interpreter: interpM :: (CLMonad m, Typeable b) => (b -> m a) -> Interp m a
+ HERMIT.Shell.KernelEffect: applyRewrite :: (Injection ModGuts g, Walker HermitC g, MonadCatch m, CLMonad m) => RewriteH g -> ExprH -> m ()
+ 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.KernelEffect: setPath :: (Injection ModGuts g, Walker HermitC g, MonadCatch m, CLMonad m) => TransformH g LocalPathH -> ExprH -> m ()
+ HERMIT.Shell.Types: instance MonadException m => MonadException (CLT m)
+ HERMIT.Shell.Types: instance MonadException m => MonadException (StateT s m)
+ HERMIT.Shell.Types: type CLMonad m = (MonadIO m, MonadState CommandLineState m, MonadError CLException m)
- HERMIT.Context: findBoundVars :: BoundVars c => String -> c -> VarSet
+ HERMIT.Context: findBoundVars :: BoundVars c => (Var -> Bool) -> c -> VarSet
- HERMIT.Core: splitFunTypeM :: Monad m => Type -> m (Type, Type)
+ HERMIT.Core: splitFunTypeM :: MonadCatch m => Type -> m ([TyVar], Type, Type)
- HERMIT.Dictionary.AlphaConversion: alphaAltR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => Rewrite c HermitM CoreAlt
+ HERMIT.Dictionary.AlphaConversion: alphaAltR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m) => Rewrite c m CoreAlt
- HERMIT.Dictionary.AlphaConversion: alphaAltVarsR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => [Var] -> Rewrite c HermitM CoreAlt
+ HERMIT.Dictionary.AlphaConversion: alphaAltVarsR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m) => [Var] -> Rewrite c m CoreAlt
- HERMIT.Dictionary.AlphaConversion: alphaAltWithR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => [String] -> Rewrite c HermitM CoreAlt
+ HERMIT.Dictionary.AlphaConversion: alphaAltWithR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m) => [String] -> Rewrite c m CoreAlt
- HERMIT.Dictionary.AlphaConversion: alphaCaseBinderR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => Maybe String -> Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.AlphaConversion: alphaCaseBinderR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m) => Maybe String -> Rewrite c m CoreExpr
- HERMIT.Dictionary.AlphaConversion: alphaCaseR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.AlphaConversion: alphaCaseR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m) => Rewrite c m CoreExpr
- HERMIT.Dictionary.AlphaConversion: alphaLamR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => Maybe String -> Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.AlphaConversion: alphaLamR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m) => Maybe String -> Rewrite c m CoreExpr
- HERMIT.Dictionary.AlphaConversion: alphaLetR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.AlphaConversion: alphaLetR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m) => Rewrite c m CoreExpr
- HERMIT.Dictionary.AlphaConversion: alphaLetVarsR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => [Var] -> Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.AlphaConversion: alphaLetVarsR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m) => [Var] -> Rewrite c m CoreExpr
- HERMIT.Dictionary.AlphaConversion: alphaLetWithR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => [String] -> Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.AlphaConversion: alphaLetWithR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m) => [String] -> Rewrite c m CoreExpr
- HERMIT.Dictionary.AlphaConversion: alphaProgConsIdsR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => [Id] -> Rewrite c HermitM CoreProg
+ HERMIT.Dictionary.AlphaConversion: alphaProgConsIdsR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m) => [Id] -> Rewrite c m CoreProg
- HERMIT.Dictionary.AlphaConversion: alphaProgConsR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => Rewrite c HermitM CoreProg
+ HERMIT.Dictionary.AlphaConversion: alphaProgConsR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m) => Rewrite c m CoreProg
- HERMIT.Dictionary.AlphaConversion: alphaProgConsWithR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => [String] -> Rewrite c HermitM CoreProg
+ HERMIT.Dictionary.AlphaConversion: alphaProgConsWithR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m) => [String] -> Rewrite c m CoreProg
- HERMIT.Dictionary.AlphaConversion: alphaProgR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => Rewrite c HermitM CoreProg
+ HERMIT.Dictionary.AlphaConversion: alphaProgR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m) => Rewrite c m CoreProg
- HERMIT.Dictionary.AlphaConversion: alphaR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => Rewrite c HermitM Core
+ HERMIT.Dictionary.AlphaConversion: alphaR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m) => Rewrite c m Core
- HERMIT.Dictionary.AlphaConversion: cloneVarAvoidingT :: BoundVars c => Var -> Maybe String -> [Var] -> Transform c HermitM CoreTC Var
+ HERMIT.Dictionary.AlphaConversion: cloneVarAvoidingT :: (BoundVars c, MonadUnique m) => Var -> Maybe String -> [Var] -> Transform c m CoreTC Var
- HERMIT.Dictionary.AlphaConversion: unshadowAltR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb) => Rewrite c HermitM CoreAlt
+ HERMIT.Dictionary.AlphaConversion: unshadowAltR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb, MonadCatch m, MonadUnique m) => Rewrite c m CoreAlt
- HERMIT.Dictionary.AlphaConversion: unshadowExprR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb) => Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.AlphaConversion: unshadowExprR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb, MonadCatch m, MonadUnique m) => Rewrite c m CoreExpr
- HERMIT.Dictionary.AlphaConversion: unshadowProgR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb) => Rewrite c HermitM CoreProg
+ HERMIT.Dictionary.AlphaConversion: unshadowProgR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb, MonadCatch m, MonadUnique m) => Rewrite c m CoreProg
- HERMIT.Dictionary.AlphaConversion: unshadowR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, HasEmptyContext c, ReadPath c Crumb) => Rewrite c HermitM Core
+ HERMIT.Dictionary.AlphaConversion: unshadowR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, HasEmptyContext c, ReadPath c Crumb, MonadCatch m, MonadUnique m) => Rewrite c m Core
- HERMIT.Dictionary.Common: callNameG :: MonadCatch m => String -> Transform c m CoreExpr ()
+ HERMIT.Dictionary.Common: callNameG :: MonadCatch m => HermitName -> Transform c m CoreExpr ()
- HERMIT.Dictionary.Common: callNameT :: MonadCatch m => String -> Transform c m CoreExpr (CoreExpr, [CoreExpr])
+ HERMIT.Dictionary.Common: callNameT :: MonadCatch m => HermitName -> Transform c m CoreExpr (CoreExpr, [CoreExpr])
- HERMIT.Dictionary.Common: findBoundVarT :: (BoundVars c, MonadCatch m) => String -> Transform c m a Var
+ HERMIT.Dictionary.Common: findBoundVarT :: (BoundVars c, MonadCatch m) => (Var -> Bool) -> Transform c m a Var
- HERMIT.Dictionary.Common: findIdT :: (BoundVars c, HasModGuts m, HasHscEnv m, MonadCatch m, MonadIO m, MonadThings m) => String -> Transform c m a Id
+ HERMIT.Dictionary.Common: findIdT :: (BoundVars c, HasHermitMEnv m, HasHscEnv m, MonadCatch m, MonadIO m, MonadThings m) => HermitName -> Transform c m a Id
- HERMIT.Dictionary.Common: findTyConT :: (BoundVars c, HasModGuts m, HasHscEnv m, MonadCatch m, MonadIO m, MonadThings m) => String -> Transform c m a TyCon
+ HERMIT.Dictionary.Common: findTyConT :: (BoundVars c, HasHermitMEnv m, HasHscEnv m, MonadCatch m, MonadIO m, MonadThings m) => HermitName -> Transform c m a TyCon
- HERMIT.Dictionary.Common: findTypeT :: (BoundVars c, HasModGuts m, HasHscEnv m, MonadCatch m, MonadIO m, MonadThings m) => String -> Transform c m a Type
+ HERMIT.Dictionary.Common: findTypeT :: (BoundVars c, HasHermitMEnv m, HasHscEnv m, MonadCatch m, MonadIO m, MonadThings m) => HermitName -> Transform c m a Type
- HERMIT.Dictionary.Common: findVarT :: (BoundVars c, HasModGuts m, HasHscEnv m, MonadCatch m, MonadIO m, MonadThings m) => String -> Transform c m a Var
+ HERMIT.Dictionary.Common: findVarT :: (BoundVars c, HasHermitMEnv m, HasHscEnv m, MonadCatch m, MonadIO m, MonadThings m) => HermitName -> Transform c m a Var
- HERMIT.Dictionary.Composite: bashDebugR :: RewriteH 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 Core
- HERMIT.Dictionary.Composite: bashExtendedWithR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => [Rewrite c HermitM Core] -> Rewrite c HermitM Core
+ 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: bashR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => Rewrite c HermitM Core
+ 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: bashUsingR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, HasEmptyContext c, 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 Core] -> Rewrite c m Core
- HERMIT.Dictionary.Composite: simplifyR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => Rewrite c HermitM Core
+ 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: unfoldBasicCombinatorR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Composite: unfoldBasicCombinatorR :: (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb, MonadCatch m) => Rewrite c m CoreExpr
- HERMIT.Dictionary.Debug: bracketR :: Injection a CoreTC => String -> RewriteH a -> RewriteH a
+ 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: observeFailureR :: Injection a CoreTC => String -> RewriteH a -> RewriteH 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: observeR :: Injection a CoreTC => String -> RewriteH 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: traceR :: String -> RewriteH a
+ HERMIT.Dictionary.Debug: traceR :: (HasDebugChan m, Monad m) => String -> Rewrite c m a
- HERMIT.Dictionary.FixPoint: fixFusionRuleBR :: Maybe (CoreExprEqualityProof HermitC HermitM) -> Maybe (RewriteH CoreExpr) -> CoreExpr -> CoreExpr -> CoreExpr -> BiRewriteH CoreExpr
+ HERMIT.Dictionary.FixPoint: fixFusionRuleBR :: Maybe (EqualityProof HermitC HermitM) -> Maybe (RewriteH CoreExpr) -> CoreExpr -> CoreExpr -> CoreExpr -> BiRewriteH CoreExpr
- HERMIT.Dictionary.FixPoint: fixIntroR :: RewriteH CoreDef
+ HERMIT.Dictionary.FixPoint: fixIntroR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb, HasHermitMEnv m, HasHscEnv m, MonadCatch m, MonadIO m, MonadThings m, MonadUnique m) => Rewrite c m Core
- HERMIT.Dictionary.Fold: foldR :: ReadBindings c => String -> Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Fold: foldR :: (ReadBindings c, HasHermitMEnv m, HasHscEnv m, MonadCatch m, MonadIO m, MonadThings m, MonadUnique m) => HermitName -> Rewrite c m CoreExpr
- HERMIT.Dictionary.Fold: foldVarR :: ReadBindings c => Var -> Maybe BindingDepth -> Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Fold: foldVarR :: (ReadBindings c, MonadCatch m, MonadUnique m) => Maybe BindingDepth -> Var -> Rewrite c m CoreExpr
- HERMIT.Dictionary.Fold: stashFoldAnyR :: ReadBindings c => Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Fold: stashFoldAnyR :: (ReadBindings c, HasStash m, MonadCatch m) => Rewrite c m CoreExpr
- HERMIT.Dictionary.Fold: stashFoldR :: ReadBindings c => Label -> Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Fold: stashFoldR :: (ReadBindings c, HasStash m, MonadCatch m) => RememberedName -> Rewrite c m CoreExpr
- HERMIT.Dictionary.Function: staticArgPosR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, HasEmptyContext c) => [Int] -> Rewrite c HermitM CoreDef
+ HERMIT.Dictionary.Function: staticArgPosR :: (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadPath c Crumb, MonadCatch m, MonadUnique m) => [Int] -> Rewrite c m CoreDef
- HERMIT.Dictionary.Function: staticArgPredR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, HasEmptyContext c) => ([(Int, Var)] -> HermitM [Int]) -> Rewrite c HermitM CoreDef
+ HERMIT.Dictionary.Function: staticArgPredR :: (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadPath c Crumb, MonadCatch m, MonadUnique m) => ([(Int, Var)] -> m [Int]) -> Rewrite c m CoreDef
- HERMIT.Dictionary.Function: staticArgR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, HasEmptyContext c) => Rewrite c HermitM CoreDef
+ HERMIT.Dictionary.Function: staticArgR :: (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadPath c Crumb, MonadCatch m, MonadUnique m) => Rewrite c m CoreDef
- HERMIT.Dictionary.Function: staticArgTypesR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, HasEmptyContext c) => Rewrite c HermitM CoreDef
+ HERMIT.Dictionary.Function: staticArgTypesR :: (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadPath c Crumb, MonadCatch m, MonadUnique m) => Rewrite c m CoreDef
- HERMIT.Dictionary.Inline: configurableInlineR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => InlineConfig -> (Transform c HermitM Id Bool) -> Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Inline: configurableInlineR :: (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb, MonadCatch m) => InlineConfig -> (Transform c m Id Bool) -> Rewrite c m CoreExpr
- HERMIT.Dictionary.Inline: getUnfoldingT :: ReadBindings c => InlineConfig -> Transform c HermitM Id (CoreExpr, BindingDepth -> Bool)
+ HERMIT.Dictionary.Inline: getUnfoldingT :: (ReadBindings c, MonadCatch m) => InlineConfig -> Transform c m Id (CoreExpr, BindingDepth -> Bool)
- HERMIT.Dictionary.Inline: inlineCaseAlternativeR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Inline: inlineCaseAlternativeR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c, MonadCatch m) => Rewrite c m CoreExpr
- HERMIT.Dictionary.Inline: inlineCaseScrutineeR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Inline: inlineCaseScrutineeR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c, MonadCatch m) => Rewrite c m CoreExpr
- HERMIT.Dictionary.Inline: inlineMatchingPredR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => (Id -> Bool) -> Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Inline: inlineMatchingPredR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c, MonadCatch m) => (Id -> Bool) -> Rewrite c m CoreExpr
- HERMIT.Dictionary.Inline: inlineNameR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => String -> Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Inline: inlineNameR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c, MonadCatch m) => String -> Rewrite c m CoreExpr
- HERMIT.Dictionary.Inline: inlineNamesR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => [String] -> Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Inline: inlineNamesR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c, MonadCatch m) => [String] -> Rewrite c m CoreExpr
- HERMIT.Dictionary.Inline: inlineR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Inline: inlineR :: (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb, MonadCatch m) => Rewrite c m CoreExpr
- HERMIT.Dictionary.Inline: inlineTargetsT :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => Transform c HermitM Core [String]
+ 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.Local: abstractR :: ReadBindings c => String -> Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Local: abstractR :: (ReadBindings c, MonadCatch m, MonadUnique m) => (Var -> Bool) -> Rewrite c m CoreExpr
- HERMIT.Dictionary.Local.Case: caseElimInlineScrutineeR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Local.Case: caseElimInlineScrutineeR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c, MonadCatch m, MonadUnique m) => Rewrite c m CoreExpr
- HERMIT.Dictionary.Local.Case: caseElimMergeAltsR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Local.Case: caseElimMergeAltsR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c, MonadCatch m, MonadUnique m) => Rewrite c m CoreExpr
- HERMIT.Dictionary.Local.Case: caseElimR :: Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Local.Case: caseElimR :: MonadCatch m => Rewrite c m CoreExpr
- HERMIT.Dictionary.Local.Case: caseElimSeqR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Local.Case: caseElimSeqR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c, MonadCatch m, MonadUnique m) => Rewrite c m CoreExpr
- HERMIT.Dictionary.Local.Case: caseFloatAppR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c) => Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Local.Case: caseFloatAppR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, MonadCatch m, MonadUnique m) => Rewrite c m CoreExpr
- HERMIT.Dictionary.Local.Case: caseFloatArgR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => Maybe CoreExpr -> Maybe (Rewrite c HermitM CoreExpr) -> Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Local.Case: caseFloatArgR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, HasDynFlags m, HasHermitMEnv m, HasHscEnv m, MonadCatch m, MonadIO m, MonadThings m, MonadUnique m) => Maybe CoreExpr -> Maybe (Rewrite c m CoreExpr) -> Rewrite c m CoreExpr
- HERMIT.Dictionary.Local.Case: caseFloatCaseR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c) => Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Local.Case: caseFloatCaseR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, MonadCatch m, MonadUnique m) => Rewrite c m CoreExpr
- HERMIT.Dictionary.Local.Case: caseFloatLetR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c) => Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Local.Case: caseFloatLetR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, MonadCatch m, MonadUnique m) => Rewrite c m CoreExpr
- HERMIT.Dictionary.Local.Case: caseFloatR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c) => Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Local.Case: caseFloatR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, MonadCatch m, MonadUnique m) => Rewrite c m CoreExpr
- HERMIT.Dictionary.Local.Case: caseInlineAlternativeR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Local.Case: caseInlineAlternativeR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c, MonadCatch m, MonadUnique m) => Rewrite c m CoreExpr
- HERMIT.Dictionary.Local.Case: caseInlineScrutineeR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Local.Case: caseInlineScrutineeR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c, MonadCatch m, MonadUnique m) => Rewrite c m CoreExpr
- HERMIT.Dictionary.Local.Case: caseIntroSeqR :: (Id -> Bool) -> Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Local.Case: caseIntroSeqR :: (MonadCatch m, MonadUnique m) => (Id -> Bool) -> Rewrite c m CoreExpr
- HERMIT.Dictionary.Local.Case: caseMergeAltsWithBinderR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Local.Case: caseMergeAltsWithBinderR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c, MonadCatch m, MonadUnique m) => Rewrite c m CoreExpr
- HERMIT.Dictionary.Local.Case: caseReduceDataconR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c) => Bool -> Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Local.Case: caseReduceDataconR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, MonadCatch m, MonadUnique m) => Bool -> Rewrite c m CoreExpr
- HERMIT.Dictionary.Local.Case: caseReduceR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c) => Bool -> Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Local.Case: caseReduceR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, MonadCatch m, MonadUnique m) => Bool -> Rewrite c m CoreExpr
- HERMIT.Dictionary.Local.Case: caseReduceUnfoldR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => Bool -> Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Local.Case: caseReduceUnfoldR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c, MonadCatch m, MonadUnique m) => Bool -> Rewrite c m CoreExpr
- HERMIT.Dictionary.Local.Case: caseSplitInlineR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => (Id -> Bool) -> Rewrite c HermitM 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: caseSplitR :: (Id -> Bool) -> Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Local.Case: caseSplitR :: (MonadCatch m, MonadUnique m) => (Id -> Bool) -> Rewrite c m CoreExpr
- HERMIT.Dictionary.Local.Let: letFloatAppR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Local.Let: letFloatAppR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m) => Rewrite c m CoreExpr
- HERMIT.Dictionary.Local.Let: letFloatArgR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Local.Let: letFloatArgR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m) => Rewrite c m CoreExpr
- HERMIT.Dictionary.Local.Let: letFloatCaseR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Local.Let: letFloatCaseR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m) => Rewrite c m CoreExpr
- HERMIT.Dictionary.Local.Let: letFloatExprR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Local.Let: letFloatExprR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m) => Rewrite c m CoreExpr
- HERMIT.Dictionary.Local.Let: letFloatInAppR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb) => Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Local.Let: letFloatInAppR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb, MonadCatch m, MonadUnique m) => Rewrite c m CoreExpr
- HERMIT.Dictionary.Local.Let: letFloatInCaseR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb) => Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Local.Let: letFloatInCaseR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb, MonadCatch m, MonadUnique m) => Rewrite c m CoreExpr
- HERMIT.Dictionary.Local.Let: letFloatInR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb) => Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Local.Let: letFloatInR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb, MonadCatch m, MonadUnique m) => Rewrite c m CoreExpr
- HERMIT.Dictionary.Local.Let: letFloatLamR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Local.Let: letFloatLamR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m) => Rewrite c m CoreExpr
- HERMIT.Dictionary.Local.Let: letFloatLetR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Local.Let: letFloatLetR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m) => Rewrite c m CoreExpr
- HERMIT.Dictionary.Local.Let: letFloatTopR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => Rewrite c HermitM CoreProg
+ HERMIT.Dictionary.Local.Let: letFloatTopR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m) => Rewrite c m CoreProg
- HERMIT.Dictionary.Local.Let: letIntroR :: String -> Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Local.Let: letIntroR :: (MonadCatch m, MonadUnique m) => String -> Rewrite c m CoreExpr
- HERMIT.Dictionary.Local.Let: letIntroUnfoldingR :: (BoundVars c, ReadBindings c) => String -> Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Local.Let: letIntroUnfoldingR :: (BoundVars c, ReadBindings c, HasDynFlags m, HasHermitMEnv m, HasHscEnv m, MonadCatch m, MonadIO m, MonadThings m, MonadUnique m) => HermitName -> Rewrite c m CoreExpr
- HERMIT.Dictionary.Local.Let: letNonRecIntroR :: String -> CoreExpr -> Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Local.Let: letNonRecIntroR :: (MonadCatch m, MonadUnique m) => String -> CoreExpr -> Rewrite c m CoreExpr
- HERMIT.Dictionary.Local.Let: letToCaseR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c) => Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Local.Let: letToCaseR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, MonadCatch m, MonadUnique m) => Rewrite c m CoreExpr
- HERMIT.Dictionary.Local.Let: letTupleR :: String -> Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Local.Let: letTupleR :: (MonadCatch m, MonadUnique m) => String -> Rewrite c m CoreExpr
- HERMIT.Dictionary.Local.Let: nonRecIntroR :: String -> CoreExpr -> Rewrite c HermitM Core
+ HERMIT.Dictionary.Local.Let: nonRecIntroR :: (MonadCatch m, MonadUnique m) => String -> CoreExpr -> Rewrite c m Core
- HERMIT.Dictionary.Local.Let: progNonRecIntroR :: String -> CoreExpr -> Rewrite c HermitM CoreProg
+ HERMIT.Dictionary.Local.Let: progNonRecIntroR :: (MonadCatch m, MonadUnique m) => String -> CoreExpr -> Rewrite c m CoreProg
- HERMIT.Dictionary.Reasoning: alphaEqualityR :: (Var -> Bool) -> (String -> String) -> RewriteH CoreExprEquality
+ HERMIT.Dictionary.Reasoning: alphaEqualityR :: (Var -> Bool) -> (String -> String) -> RewriteH Equality
- HERMIT.Dictionary.Reasoning: birewrite :: (AddBindings c, ReadBindings c, ExtendPath c Crumb, ReadPath c Crumb, HasEmptyContext c) => CoreExprEquality -> BiRewrite c HermitM CoreExpr
+ 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: bothR :: (AddBindings c, MonadCatch m, ReadPath c Crumb) => Rewrite c m CoreExpr -> Rewrite c m CoreExprEquality
+ HERMIT.Dictionary.Reasoning: bothR :: (AddBindings c, MonadCatch m, ReadPath c Crumb) => Rewrite c m CoreExpr -> Rewrite c m Equality
- HERMIT.Dictionary.Reasoning: bothT :: (AddBindings c, Monad m, ReadPath c Crumb) => Transform c m CoreExpr b -> Transform c m CoreExprEquality (b, b)
+ 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: discardUniVars :: CoreExprEquality -> CoreExprEquality
+ HERMIT.Dictionary.Reasoning: discardUniVars :: Equality -> Equality
- HERMIT.Dictionary.Reasoning: eqLhsIntroR :: CoreExprEquality -> Rewrite c HermitM Core
+ HERMIT.Dictionary.Reasoning: eqLhsIntroR :: Equality -> Rewrite c HermitM Core
- HERMIT.Dictionary.Reasoning: eqRhsIntroR :: CoreExprEquality -> Rewrite c HermitM Core
+ HERMIT.Dictionary.Reasoning: eqRhsIntroR :: Equality -> Rewrite c HermitM Core
- HERMIT.Dictionary.Reasoning: extensionalityR :: Maybe String -> Rewrite c HermitM CoreExprEquality
+ HERMIT.Dictionary.Reasoning: extensionalityR :: Maybe String -> Rewrite c HermitM Equality
- HERMIT.Dictionary.Reasoning: forallVarsT :: Monad m => Transform c m [Var] b -> Transform c m CoreExprEquality b
+ HERMIT.Dictionary.Reasoning: forallVarsT :: Monad m => Transform c m [Var] b -> Transform c m Equality b
- HERMIT.Dictionary.Reasoning: instantiateDictsR :: RewriteH CoreExprEquality
+ HERMIT.Dictionary.Reasoning: instantiateDictsR :: RewriteH Equality
- HERMIT.Dictionary.Reasoning: instantiateEquality :: MonadIO m => [(Var, CoreExpr, [Var])] -> CoreExprEquality -> m CoreExprEquality
+ HERMIT.Dictionary.Reasoning: instantiateEquality :: MonadIO m => [(Var, CoreExpr, [Var])] -> Equality -> m Equality
- HERMIT.Dictionary.Reasoning: instantiateEqualityVar :: MonadIO m => (Var -> Bool) -> CoreExpr -> [Var] -> CoreExprEquality -> m CoreExprEquality
+ HERMIT.Dictionary.Reasoning: instantiateEqualityVar :: MonadIO m => (Var -> Bool) -> CoreExpr -> [Var] -> Equality -> m Equality
- HERMIT.Dictionary.Reasoning: instantiateEqualityVarR :: (Var -> Bool) -> CoreString -> RewriteH CoreExprEquality
+ HERMIT.Dictionary.Reasoning: instantiateEqualityVarR :: (Var -> Bool) -> CoreString -> RewriteH Equality
- HERMIT.Dictionary.Reasoning: lhsR :: (AddBindings c, Monad m, ReadPath c Crumb) => Rewrite c m CoreExpr -> Rewrite c m CoreExprEquality
+ HERMIT.Dictionary.Reasoning: lhsR :: (AddBindings c, Monad m, ReadPath c Crumb) => Rewrite c m CoreExpr -> Rewrite c m Equality
- HERMIT.Dictionary.Reasoning: lhsT :: (AddBindings c, Monad m, ReadPath c Crumb) => Transform c m CoreExpr b -> Transform c m CoreExprEquality b
+ HERMIT.Dictionary.Reasoning: lhsT :: (AddBindings c, Monad m, ReadPath c Crumb) => Transform c m CoreExpr b -> Transform c m Equality b
- HERMIT.Dictionary.Reasoning: rhsR :: (AddBindings c, Monad m, ReadPath c Crumb) => Rewrite c m CoreExpr -> Rewrite c m CoreExprEquality
+ HERMIT.Dictionary.Reasoning: rhsR :: (AddBindings c, Monad m, ReadPath c Crumb) => Rewrite c m CoreExpr -> Rewrite c m Equality
- HERMIT.Dictionary.Reasoning: rhsT :: (AddBindings c, Monad m, ReadPath c Crumb) => Transform c m CoreExpr b -> Transform c m CoreExprEquality b
+ HERMIT.Dictionary.Reasoning: rhsT :: (AddBindings c, Monad m, ReadPath c Crumb) => Transform c m CoreExpr b -> Transform c m Equality b
- HERMIT.Dictionary.Reasoning: unshadowEqualityR :: RewriteH CoreExprEquality
+ HERMIT.Dictionary.Reasoning: unshadowEqualityR :: RewriteH Equality
- HERMIT.Dictionary.Reasoning: verifyEqualityCommonTargetT :: MonadCatch m => CoreExpr -> CoreExpr -> CoreExprEqualityProof c m -> Transform c m a ()
+ HERMIT.Dictionary.Reasoning: verifyEqualityCommonTargetT :: MonadCatch m => CoreExpr -> CoreExpr -> EqualityProof c m -> Transform c m a ()
- HERMIT.Dictionary.Rules: getHermitRuleT :: HasCoreRules c => RuleNameString -> Transform c HermitM a CoreRule
+ HERMIT.Dictionary.Rules: getHermitRuleT :: (HasCoreRules c, HasHermitMEnv m, LiftCoreM m, MonadIO m) => RuleName -> Transform c m a CoreRule
- HERMIT.Dictionary.Rules: getHermitRulesT :: HasCoreRules c => Transform c HermitM a [(RuleNameString, CoreRule)]
+ HERMIT.Dictionary.Rules: getHermitRulesT :: (HasCoreRules c, HasHermitMEnv m, LiftCoreM m, MonadIO m) => Transform c m a [(RuleName, CoreRule)]
- HERMIT.Dictionary.Rules: ruleNameToEqualityT :: (BoundVars c, HasCoreRules c) => RuleNameString -> Transform c HermitM a CoreExprEquality
+ 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 :: (ReadBindings c, HasCoreRules c) => RuleNameString -> Rewrite c HermitM CoreExpr
+ 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, HasModGuts m, MonadThings m, MonadCatch m) => Transform c m CoreRule CoreExprEquality
+ HERMIT.Dictionary.Rules: ruleToEqualityT :: (BoundVars c, HasDynFlags m, HasHermitMEnv m, MonadThings m, MonadCatch m) => Transform c m CoreRule Equality
- HERMIT.Dictionary.Rules: rulesR :: (ReadBindings c, HasCoreRules c) => [RuleNameString] -> Rewrite c HermitM CoreExpr
+ 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.Undefined: errorToUndefinedR :: (BoundVars c, MonadCatch m, HasModGuts m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr
+ HERMIT.Dictionary.Undefined: errorToUndefinedR :: (BoundVars c, MonadCatch m, HasHermitMEnv m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr
- HERMIT.Dictionary.Undefined: isUndefinedValT :: (BoundVars c, MonadCatch m, HasModGuts m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Transform c m CoreExpr ()
+ HERMIT.Dictionary.Undefined: isUndefinedValT :: (BoundVars c, MonadCatch m, HasHermitMEnv m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Transform c m CoreExpr ()
- HERMIT.Dictionary.Undefined: mkUndefinedValT :: (BoundVars c, MonadCatch m, HasModGuts m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Type -> Transform c m a CoreExpr
+ HERMIT.Dictionary.Undefined: mkUndefinedValT :: (BoundVars c, MonadCatch m, HasHermitMEnv m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Type -> Transform c m a CoreExpr
- HERMIT.Dictionary.Undefined: replaceCurrentExprWithUndefinedR :: (BoundVars c, MonadCatch m, HasModGuts m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr
+ HERMIT.Dictionary.Undefined: replaceCurrentExprWithUndefinedR :: (BoundVars c, MonadCatch m, HasHermitMEnv m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr
- HERMIT.Dictionary.Undefined: replaceIdWithUndefinedR :: (BoundVars c, MonadCatch m, HasModGuts m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Id -> Rewrite c m Core
+ HERMIT.Dictionary.Undefined: replaceIdWithUndefinedR :: (BoundVars c, MonadCatch m, HasHermitMEnv m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Id -> Rewrite c m Core
- HERMIT.Dictionary.Undefined: undefinedAppR :: (BoundVars c, ExtendPath c Crumb, MonadCatch m, HasModGuts m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr
+ HERMIT.Dictionary.Undefined: undefinedAppR :: (BoundVars c, ExtendPath c Crumb, MonadCatch m, HasHermitMEnv m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr
- HERMIT.Dictionary.Undefined: undefinedCaseAltsR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb, MonadCatch m, HasModGuts m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr
+ HERMIT.Dictionary.Undefined: undefinedCaseAltsR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb, MonadCatch m, HasHermitMEnv m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr
- HERMIT.Dictionary.Undefined: undefinedCaseR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb, MonadCatch m, HasModGuts m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr
+ HERMIT.Dictionary.Undefined: undefinedCaseR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb, MonadCatch m, HasHermitMEnv m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr
- HERMIT.Dictionary.Undefined: undefinedCaseScrutineeR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb, MonadCatch m, HasModGuts m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr
+ HERMIT.Dictionary.Undefined: undefinedCaseScrutineeR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb, MonadCatch m, HasHermitMEnv m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr
- HERMIT.Dictionary.Undefined: undefinedCastR :: (BoundVars c, ExtendPath c Crumb, MonadCatch m, HasModGuts m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr
+ HERMIT.Dictionary.Undefined: undefinedCastR :: (BoundVars c, ExtendPath c Crumb, MonadCatch m, HasHermitMEnv m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr
- HERMIT.Dictionary.Undefined: undefinedExprR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb, MonadCatch m, HasModGuts m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr
+ HERMIT.Dictionary.Undefined: undefinedExprR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb, MonadCatch m, HasHermitMEnv m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr
- HERMIT.Dictionary.Undefined: undefinedLamR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb, MonadCatch m, HasModGuts m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr
+ HERMIT.Dictionary.Undefined: undefinedLamR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb, MonadCatch m, HasHermitMEnv m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr
- HERMIT.Dictionary.Undefined: undefinedLetR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb, MonadCatch m, HasModGuts m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr
+ HERMIT.Dictionary.Undefined: undefinedLetR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb, MonadCatch m, HasHermitMEnv m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr
- HERMIT.Dictionary.Undefined: undefinedTickR :: (BoundVars c, ExtendPath c Crumb, MonadCatch m, HasModGuts m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr
+ HERMIT.Dictionary.Undefined: undefinedTickR :: (BoundVars c, ExtendPath c Crumb, MonadCatch m, HasHermitMEnv m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr
- HERMIT.Dictionary.Undefined: verifyStrictT :: (BoundVars c, MonadCatch m, HasModGuts m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => CoreExpr -> Rewrite c m CoreExpr -> Transform c m a ()
+ HERMIT.Dictionary.Undefined: verifyStrictT :: (BoundVars c, MonadCatch m, HasHermitMEnv m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => CoreExpr -> Rewrite c m CoreExpr -> Transform c m a ()
- HERMIT.Dictionary.Unfold: rememberR :: Label -> Rewrite c HermitM Core
+ HERMIT.Dictionary.Unfold: rememberR :: RememberedName -> Rewrite c HermitM Core
- HERMIT.Dictionary.Unfold: unfoldNameR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => String -> Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Unfold: unfoldNameR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c, MonadCatch m) => HermitName -> Rewrite c m CoreExpr
- HERMIT.Dictionary.Unfold: unfoldNamesR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => [String] -> Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Unfold: unfoldNamesR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c, MonadCatch m) => [HermitName] -> Rewrite c m CoreExpr
- HERMIT.Dictionary.Unfold: unfoldPredR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => (Id -> [CoreExpr] -> Bool) -> Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Unfold: unfoldPredR :: (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb, MonadCatch m) => (Id -> [CoreExpr] -> Bool) -> Rewrite c m CoreExpr
- HERMIT.Dictionary.Unfold: unfoldR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Unfold: unfoldR :: (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb, MonadCatch m) => Rewrite c m CoreExpr
- HERMIT.Dictionary.Unfold: unfoldStashR :: ReadBindings c => String -> Rewrite c HermitM CoreExpr
+ HERMIT.Dictionary.Unfold: unfoldStashR :: ReadBindings c => RememberedName -> Rewrite c HermitM CoreExpr
- HERMIT.Dictionary.Unsafe: unsafeReplaceStashR :: String -> RewriteH CoreExpr
+ HERMIT.Dictionary.Unsafe: unsafeReplaceStashR :: RememberedName -> RewriteH CoreExpr
- HERMIT.Dictionary.WorkerWrapper.Common: workLabel :: Label
+ HERMIT.Dictionary.WorkerWrapper.Common: workLabel :: RememberedName
- HERMIT.Kernel: applyK :: Kernel -> AST -> RewriteH ModGuts -> HermitMEnv -> IO (KureM AST)
+ HERMIT.Kernel: applyK :: Kernel -> AST -> RewriteH ModGuts -> KernelEnv -> IO (KureM AST)
- HERMIT.Kernel: queryK :: Kernel -> forall a. AST -> TransformH ModGuts a -> HermitMEnv -> IO (KureM a)
+ HERMIT.Kernel: queryK :: Kernel -> forall a. AST -> TransformH ModGuts a -> KernelEnv -> IO (KureM a)
- 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 -> HermitMEnv -> SAST -> m SAST) -> (forall g a m. (MonadIO m, MonadCatch m, Injection ModGuts g, Walker HermitC g) => TransformH g a -> HermitMEnv -> 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) -> HermitMEnv -> 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: 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: applyS :: ScopedKernel -> forall g m. (MonadIO m, MonadCatch m, Injection ModGuts g, Walker HermitC g) => RewriteH g -> HermitMEnv -> SAST -> m SAST
+ 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: modPathS :: ScopedKernel -> forall m. (MonadIO m, MonadCatch m) => (LocalPathH -> LocalPathH) -> HermitMEnv -> SAST -> m SAST
+ HERMIT.Kernel.Scoped: modPathS :: ScopedKernel -> forall m. (MonadIO m, MonadCatch m) => (LocalPathH -> LocalPathH) -> KernelEnv -> SAST -> m SAST
- HERMIT.Kernel.Scoped: queryS :: ScopedKernel -> forall g a m. (MonadIO m, MonadCatch m, Injection ModGuts g, Walker HermitC g) => TransformH g a -> HermitMEnv -> SAST -> m a
+ 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.Monad: DebugCore :: String -> HermitC -> CoreTC -> DebugMessage
+ HERMIT.Monad: DebugCore :: String -> c -> CoreTC -> DebugMessage
- HERMIT.Monad: HermitMEnv :: (DebugMessage -> HermitM ()) -> HermitMEnv
+ HERMIT.Monad: HermitMEnv :: ModGuts -> DefStash -> Lemmas -> HermitMEnv
- HERMIT.Monad: data DebugMessage
+ HERMIT.Monad: data DebugMessage :: *
- HERMIT.Monad: getModGuts :: HasModGuts m => m ModGuts
+ HERMIT.Monad: getModGuts :: (HasHermitMEnv m, Monad m) => m ModGuts
- HERMIT.Monad: getStash :: HermitM DefStash
+ HERMIT.Monad: getStash :: HasStash m => m DefStash
- HERMIT.Monad: liftCoreM :: CoreM a -> HermitM a
+ HERMIT.Monad: liftCoreM :: LiftCoreM m => CoreM a -> m a
- HERMIT.Monad: lookupDef :: Label -> HermitM CoreDef
+ HERMIT.Monad: lookupDef :: (HasStash m, Monad m) => RememberedName -> m CoreDef
- HERMIT.Monad: runHM :: (ModGuts, HermitMEnv) -> DefStash -> (DefStash -> a -> CoreM b) -> (String -> CoreM b) -> HermitM a -> CoreM b
+ HERMIT.Monad: runHM :: DebugChan -> HermitMEnv -> (HermitMResult a -> CoreM b) -> (String -> CoreM b) -> HermitM a -> CoreM b
- HERMIT.Monad: saveDef :: Label -> CoreDef -> HermitM ()
+ HERMIT.Monad: saveDef :: (HasStash m, Monad m) => RememberedName -> CoreDef -> m ()
- HERMIT.Monad: sendDebugMessage :: DebugMessage -> HermitM ()
+ HERMIT.Monad: sendDebugMessage :: (HasDebugChan m, Monad m) => DebugMessage -> m ()
- HERMIT.Monad: type DefStash = Map Label CoreDef
+ HERMIT.Monad: type DefStash = Map RememberedName CoreDef
- HERMIT.Name: findId :: (BoundVars c, HasHscEnv m, HasModGuts m, MonadCatch m, MonadIO m, MonadThings m) => String -> c -> m Id
+ HERMIT.Name: findId :: (BoundVars c, HasHscEnv m, HasHermitMEnv m, MonadCatch m, MonadIO m, MonadThings m) => HermitName -> c -> m Id
- HERMIT.Name: findInNameSpace :: (BoundVars c, HasHscEnv m, HasModGuts m, MonadIO m, MonadThings m) => NameSpace -> String -> c -> m Named
+ HERMIT.Name: findInNameSpace :: (BoundVars c, HasHscEnv m, HasHermitMEnv m, MonadIO m, MonadThings m) => NameSpace -> HermitName -> c -> m Named
- HERMIT.Name: findInNameSpaces :: (BoundVars c, HasHscEnv m, HasModGuts m, MonadCatch m, MonadIO m, MonadThings m) => [NameSpace] -> String -> c -> m Named
+ HERMIT.Name: findInNameSpaces :: (BoundVars c, HasHscEnv m, HasHermitMEnv m, MonadCatch m, MonadIO m, MonadThings m) => [NameSpace] -> HermitName -> c -> m Named
- HERMIT.Name: findTyCon :: (BoundVars c, HasHscEnv m, HasModGuts m, MonadCatch m, MonadIO m, MonadThings m) => String -> c -> m TyCon
+ HERMIT.Name: findTyCon :: (BoundVars c, HasHscEnv m, HasHermitMEnv m, MonadCatch m, MonadIO m, MonadThings m) => HermitName -> c -> m TyCon
- HERMIT.Name: findType :: (BoundVars c, HasHscEnv m, HasModGuts m, MonadCatch m, MonadIO m, MonadThings m) => String -> c -> m Type
+ HERMIT.Name: findType :: (BoundVars c, HasHscEnv m, HasHermitMEnv m, MonadCatch m, MonadIO m, MonadThings m) => HermitName -> c -> m Type
- HERMIT.Name: findVar :: (BoundVars c, HasHscEnv m, HasModGuts m, MonadCatch m, MonadIO m, MonadThings m) => String -> c -> m Var
+ HERMIT.Name: findVar :: (BoundVars c, HasHscEnv m, HasHermitMEnv m, MonadCatch m, MonadIO m, MonadThings m) => HermitName -> c -> m Var
- HERMIT.ParserCore: parseCore :: CoreString -> HermitC -> HermitM CoreExpr
+ HERMIT.ParserCore: parseCore :: BoundVars c => CoreString -> c -> HermitM CoreExpr
- HERMIT.ParserCore: parseCoreExprT :: CoreString -> TransformH a CoreExpr
+ HERMIT.ParserCore: parseCoreExprT :: (BoundVars c, HasDebugChan m, HasHermitMEnv m, HasLemmas m, HasStash m, LiftCoreM m) => CoreString -> Transform c m a CoreExpr
- HERMIT.Plugin: defPS :: SAST -> ScopedKernel -> PhaseInfo -> IO PluginState
+ HERMIT.Plugin: defPS :: SAST -> ScopedKernel -> PassInfo -> IO PluginState
- HERMIT.Plugin.Builder: type PluginPass = PhaseInfo -> [CommandLineOption] -> ModGuts -> CoreM ModGuts
+ HERMIT.Plugin.Builder: type PluginPass = PassInfo -> [CommandLineOption] -> ModGuts -> CoreM ModGuts
- HERMIT.Plugin.Types: PluginState :: SAST -> PrettyPrinter -> (Handle -> PrettyOptions -> Either String DocH -> IO ()) -> TVar (Map String Int) -> Bool -> Bool -> Bool -> ScopedKernel -> PhaseInfo -> PluginState
+ 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: mkKernelEnv :: PluginState -> HermitMEnv
+ HERMIT.Plugin.Types: mkKernelEnv :: PluginState -> KernelEnv
- HERMIT.PrettyPrinter.Common: PrettyOptions :: Bool -> ShowOption -> ShowOption -> ShowOption -> Maybe PathH -> Maybe Int -> Bool -> Float -> Int -> PrettyOptions
+ HERMIT.PrettyPrinter.Common: PrettyOptions :: Bool -> ShowOption -> ShowOption -> ShowOption -> Bool -> Maybe PathH -> Maybe Int -> Bool -> Float -> Int -> PrettyOptions
- HERMIT.Shell.Command: cl_kernel_env :: CommandLineState -> HermitMEnv
+ HERMIT.Shell.Command: cl_kernel_env :: CommandLineState -> KernelEnv
- HERMIT.Shell.Command: commandLine :: [CommandLineOption] -> Behavior -> [External] -> CLT IO ()
+ HERMIT.Shell.Command: commandLine :: (MonadCatch m, MonadException m, CLMonad m) => [Interp m ()] -> [CommandLineOption] -> [External] -> m ()
- HERMIT.Shell.Command: evalScript :: (MonadCatch m, MonadError CLException m, MonadIO m, MonadState CommandLineState m) => String -> m ()
+ HERMIT.Shell.Command: evalScript :: (MonadCatch m, CLMonad m) => [Interp m ()] -> String -> m ()
- HERMIT.Shell.Command: performQuery :: (MonadCatch m, MonadError CLException m, MonadIO m, MonadState CommandLineState m) => QueryFun -> ExprH -> m ()
+ HERMIT.Shell.Command: performQuery :: (MonadCatch m, CLMonad m) => QueryFun -> ExprH -> m ()
- HERMIT.Shell.Command: shellComplete :: MVar CommandLineState -> String -> String -> IO [Completion]
+ HERMIT.Shell.Command: shellComplete :: (MonadCatch m, MonadIO m, MonadState CommandLineState m) => String -> String -> m [Completion]
- HERMIT.Shell.Interpreter: data Interp :: * -> *
+ HERMIT.Shell.Interpreter: data Interp :: (* -> *) -> * -> *
- HERMIT.Shell.Interpreter: interp :: Typeable a => (a -> cmd) -> Interp cmd
+ HERMIT.Shell.Interpreter: interp :: (Monad m, Typeable b) => (b -> a) -> Interp m a
- HERMIT.Shell.Interpreter: interpExprH :: MonadState CommandLineState m => [Interp b] -> ExprH -> m b
+ HERMIT.Shell.Interpreter: interpExprH :: CLMonad m => [Interp m b] -> ExprH -> m b
- HERMIT.Shell.KernelEffect: data KernelEffect :: *
+ HERMIT.Shell.KernelEffect: data KernelEffect
- HERMIT.Shell.KernelEffect: performKernelEffect :: (MonadCatch m, MonadError CLException m, MonadIO m, MonadState CommandLineState m) => KernelEffect -> ExprH -> m ()
+ HERMIT.Shell.KernelEffect: performKernelEffect :: (MonadCatch m, CLMonad m) => ExprH -> KernelEffect -> m ()
- HERMIT.Shell.Proof: performProofCommand :: (MonadCatch m, MonadError CLException m, MonadIO m, MonadState CommandLineState m) => ProofCommand -> m ()
+ HERMIT.Shell.Proof: performProofCommand :: (MonadCatch m, MonadException m, CLMonad m) => ProofCommand -> m ()
- HERMIT.Shell.Proof: ppLemmaT :: PrettyPrinter -> TransformH Lemma DocH
+ HERMIT.Shell.Proof: ppLemmaT :: PrettyPrinter -> LemmaName -> TransformH Lemma DocH
- HERMIT.Shell.Proof: userProofTechnique :: TransformH CoreExprEquality () -> UserProofTechnique
+ HERMIT.Shell.Proof: userProofTechnique :: TransformH Equality () -> UserProofTechnique
- HERMIT.Shell.ScriptToRewrite: addScriptToDict :: MonadState CommandLineState m => ScriptName -> Script -> m ()
+ HERMIT.Shell.ScriptToRewrite: addScriptToDict :: CLMonad m => ScriptName -> Script -> m ()
- HERMIT.Shell.ScriptToRewrite: performScriptEffect :: (MonadCatch m, MonadError CLException m, MonadIO m, MonadState CommandLineState m) => (ExprH -> m ()) -> ScriptEffect -> m ()
+ HERMIT.Shell.ScriptToRewrite: performScriptEffect :: (MonadCatch m, CLMonad m) => (ExprH -> m ()) -> ScriptEffect -> m ()
- HERMIT.Shell.ScriptToRewrite: scriptToRewrite :: MonadState CommandLineState m => Script -> m (RewriteH Core)
+ HERMIT.Shell.ScriptToRewrite: scriptToRewrite :: CLMonad m => Script -> m (RewriteH Core)
- HERMIT.Shell.Types: CommandLineState :: PluginState -> Int -> [(ScriptName, Script)] -> [Lemma] -> Bool -> VersionStore -> PathH -> [External] -> Maybe Script -> SAST -> CommandLineState
+ HERMIT.Shell.Types: CommandLineState :: PluginState -> Int -> [(ScriptName, Script)] -> Bool -> VersionStore -> PathH -> [External] -> Maybe Script -> SAST -> CommandLineState
- HERMIT.Shell.Types: cl_kernel_env :: CommandLineState -> HermitMEnv
+ HERMIT.Shell.Types: cl_kernel_env :: CommandLineState -> KernelEnv
- HERMIT.Shell.Types: cl_putStr :: (MonadError CLException m, MonadIO m, MonadState CommandLineState m) => String -> m ()
+ HERMIT.Shell.Types: cl_putStr :: CLMonad m => String -> m ()
- HERMIT.Shell.Types: cl_putStrLn :: (MonadError CLException m, MonadIO m, MonadState CommandLineState m) => String -> m ()
+ HERMIT.Shell.Types: cl_putStrLn :: CLMonad m => String -> m ()
- HERMIT.Shell.Types: fixWindow :: (MonadError CLException m, MonadIO m, MonadState CommandLineState m) => m ()
+ HERMIT.Shell.Types: fixWindow :: CLMonad m => m ()
- HERMIT.Shell.Types: performQuery :: (MonadCatch m, MonadError CLException m, MonadIO m, MonadState CommandLineState m) => QueryFun -> ExprH -> m ()
+ HERMIT.Shell.Types: performQuery :: (MonadCatch m, CLMonad m) => QueryFun -> ExprH -> m ()
- HERMIT.Shell.Types: pluginM :: (MonadError CLException m, MonadIO m, MonadState CommandLineState m) => PluginM a -> m a
+ HERMIT.Shell.Types: pluginM :: CLMonad m => PluginM a -> m a
- HERMIT.Shell.Types: putStrToConsole :: (MonadError CLException m, MonadIO m, MonadState CommandLineState m) => String -> m ()
+ HERMIT.Shell.Types: putStrToConsole :: CLMonad m => String -> m ()
- HERMIT.Shell.Types: showWindow :: (MonadError CLException m, MonadIO m, MonadState CommandLineState m) => m ()
+ HERMIT.Shell.Types: showWindow :: CLMonad m => m ()
Files
- dist/build/HERMIT/Parser.hs +134/−127
- dist/build/HERMIT/ParserCore.hs +20/−11
- dist/build/HERMIT/ParserType.hs +2/−10
- examples/concatVanishes/Flatten.hs +0/−4
- examples/concatVanishes/QSort.hs +0/−4
- examples/concatVanishes/Rev.hs +0/−4
- examples/evaluation/Eval.hs +0/−4
- examples/factorial/Fac.hs +0/−4
- examples/fib-stream/Fib.hs +0/−4
- examples/fib-tuple/Fib.hs +0/−5
- examples/flatten/Flatten.hs +0/−4
- examples/hanoi/Hanoi.hs +0/−4
- examples/last/Last.hs +0/−4
- examples/qsort/QSort.hs +0/−4
- examples/reverse/Reverse.hs +0/−4
- hermit.cabal +18/−12
- src/HERMIT.hs +3/−3
- src/HERMIT/Context.hs +3/−3
- src/HERMIT/Core.hs +21/−28
- src/HERMIT/Dictionary.hs +4/−0
- src/HERMIT/Dictionary/AlphaConversion.hs +126/−93
- src/HERMIT/Dictionary/Common.hs +32/−44
- src/HERMIT/Dictionary/Composite.hs +86/−69
- src/HERMIT/Dictionary/Debug.hs +27/−24
- src/HERMIT/Dictionary/FixPoint.hs +104/−74
- src/HERMIT/Dictionary/Fold.hs +25/−21
- src/HERMIT/Dictionary/Function.hs +106/−17
- src/HERMIT/Dictionary/GHC.hs +82/−41
- src/HERMIT/Dictionary/Induction.hs +2/−1
- src/HERMIT/Dictionary/Inline.hs +65/−96
- src/HERMIT/Dictionary/Kure.hs +18/−5
- src/HERMIT/Dictionary/Local.hs +33/−78
- src/HERMIT/Dictionary/Local/Bind.hs +6/−7
- src/HERMIT/Dictionary/Local/Case.hs +112/−90
- src/HERMIT/Dictionary/Local/Cast.hs +0/−6
- src/HERMIT/Dictionary/Local/Let.hs +158/−64
- src/HERMIT/Dictionary/Navigation.hs +60/−51
- src/HERMIT/Dictionary/Query.hs +21/−21
- src/HERMIT/Dictionary/Reasoning.hs +199/−141
- src/HERMIT/Dictionary/Rules.hs +109/−152
- src/HERMIT/Dictionary/Undefined.hs +50/−32
- src/HERMIT/Dictionary/Unfold.hs +41/−43
- src/HERMIT/Dictionary/Unsafe.hs +4/−4
- src/HERMIT/Dictionary/WorkerWrapper/Common.hs +163/−6
- src/HERMIT/Dictionary/WorkerWrapper/Fix.hs +24/−22
- src/HERMIT/Dictionary/WorkerWrapper/FixResult.hs +31/−29
- src/HERMIT/Driver.hs +11/−8
- src/HERMIT/External.hs +109/−110
- src/HERMIT/GHC.hs +80/−180
- src/HERMIT/GHC/Typechecker.hs +3/−9
- src/HERMIT/Kernel.hs +69/−40
- src/HERMIT/Kernel/Scoped.hs +16/−16
- src/HERMIT/Kure.hs +56/−145
- src/HERMIT/Monad.hs +212/−135
- src/HERMIT/Name.hs +182/−101
- src/HERMIT/Parser.y +6/−1
- src/HERMIT/ParserCore.y +20/−11
- src/HERMIT/ParserType.y +2/−10
- src/HERMIT/Plugin.hs +44/−38
- src/HERMIT/Plugin/Builder.hs +35/−32
- src/HERMIT/Plugin/Renderer.hs +8/−1
- src/HERMIT/Plugin/Types.hs +23/−8
- src/HERMIT/PrettyPrinter/AST.hs +0/−7
- src/HERMIT/PrettyPrinter/Clean.hs +57/−54
- src/HERMIT/PrettyPrinter/Common.hs +12/−9
- src/HERMIT/Shell/Command.hs +67/−30
- src/HERMIT/Shell/Completion.hs +127/−0
- src/HERMIT/Shell/Dictionary.hs +21/−4
- src/HERMIT/Shell/Externals.hs +5/−32
- src/HERMIT/Shell/Interpreter.hs +66/−48
- src/HERMIT/Shell/KernelEffect.hs +33/−26
- src/HERMIT/Shell/Proof.hs +122/−198
- src/HERMIT/Shell/ScriptToRewrite.hs +13/−8
- src/HERMIT/Shell/ShellEffect.hs +7/−8
- src/HERMIT/Shell/Types.hs +59/−103
- src/HERMIT/Utilities.hs +10/−11
- src/HERMIT/Win32/Console.hsc +105/−0
- src/HERMIT/Win32/IO.hsc +239/−0
dist/build/HERMIT/Parser.hs view
@@ -6,6 +6,7 @@ , unparseScript , unparseExprH , ExprH(..)+ , parseExprH ) where import Data.Char (isSpace)@@ -19,85 +20,84 @@ -- parser produced by Happy Version 1.19.3 -newtype HappyAbsSyn t4 t5 t6 t7 t8 t9 t10 t11 = HappyAbsSyn HappyAny+newtype HappyAbsSyn t5 t6 t7 t8 t9 t10 t11 t12 = HappyAbsSyn HappyAny #if __GLASGOW_HASKELL__ >= 607 type HappyAny = Happy_GHC_Exts.Any #else type HappyAny = forall a . a #endif-happyIn4 :: t4 -> (HappyAbsSyn t4 t5 t6 t7 t8 t9 t10 t11)-happyIn4 x = Happy_GHC_Exts.unsafeCoerce# x-{-# INLINE happyIn4 #-}-happyOut4 :: (HappyAbsSyn t4 t5 t6 t7 t8 t9 t10 t11) -> t4-happyOut4 x = Happy_GHC_Exts.unsafeCoerce# x-{-# INLINE happyOut4 #-}-happyIn5 :: t5 -> (HappyAbsSyn t4 t5 t6 t7 t8 t9 t10 t11)+happyIn5 :: t5 -> (HappyAbsSyn t5 t6 t7 t8 t9 t10 t11 t12) happyIn5 x = Happy_GHC_Exts.unsafeCoerce# x {-# INLINE happyIn5 #-}-happyOut5 :: (HappyAbsSyn t4 t5 t6 t7 t8 t9 t10 t11) -> t5+happyOut5 :: (HappyAbsSyn t5 t6 t7 t8 t9 t10 t11 t12) -> t5 happyOut5 x = Happy_GHC_Exts.unsafeCoerce# x {-# INLINE happyOut5 #-}-happyIn6 :: t6 -> (HappyAbsSyn t4 t5 t6 t7 t8 t9 t10 t11)+happyIn6 :: t6 -> (HappyAbsSyn t5 t6 t7 t8 t9 t10 t11 t12) happyIn6 x = Happy_GHC_Exts.unsafeCoerce# x {-# INLINE happyIn6 #-}-happyOut6 :: (HappyAbsSyn t4 t5 t6 t7 t8 t9 t10 t11) -> t6+happyOut6 :: (HappyAbsSyn t5 t6 t7 t8 t9 t10 t11 t12) -> t6 happyOut6 x = Happy_GHC_Exts.unsafeCoerce# x {-# INLINE happyOut6 #-}-happyIn7 :: t7 -> (HappyAbsSyn t4 t5 t6 t7 t8 t9 t10 t11)+happyIn7 :: t7 -> (HappyAbsSyn t5 t6 t7 t8 t9 t10 t11 t12) happyIn7 x = Happy_GHC_Exts.unsafeCoerce# x {-# INLINE happyIn7 #-}-happyOut7 :: (HappyAbsSyn t4 t5 t6 t7 t8 t9 t10 t11) -> t7+happyOut7 :: (HappyAbsSyn t5 t6 t7 t8 t9 t10 t11 t12) -> t7 happyOut7 x = Happy_GHC_Exts.unsafeCoerce# x {-# INLINE happyOut7 #-}-happyIn8 :: t8 -> (HappyAbsSyn t4 t5 t6 t7 t8 t9 t10 t11)+happyIn8 :: t8 -> (HappyAbsSyn t5 t6 t7 t8 t9 t10 t11 t12) happyIn8 x = Happy_GHC_Exts.unsafeCoerce# x {-# INLINE happyIn8 #-}-happyOut8 :: (HappyAbsSyn t4 t5 t6 t7 t8 t9 t10 t11) -> t8+happyOut8 :: (HappyAbsSyn t5 t6 t7 t8 t9 t10 t11 t12) -> t8 happyOut8 x = Happy_GHC_Exts.unsafeCoerce# x {-# INLINE happyOut8 #-}-happyIn9 :: t9 -> (HappyAbsSyn t4 t5 t6 t7 t8 t9 t10 t11)+happyIn9 :: t9 -> (HappyAbsSyn t5 t6 t7 t8 t9 t10 t11 t12) happyIn9 x = Happy_GHC_Exts.unsafeCoerce# x {-# INLINE happyIn9 #-}-happyOut9 :: (HappyAbsSyn t4 t5 t6 t7 t8 t9 t10 t11) -> t9+happyOut9 :: (HappyAbsSyn t5 t6 t7 t8 t9 t10 t11 t12) -> t9 happyOut9 x = Happy_GHC_Exts.unsafeCoerce# x {-# INLINE happyOut9 #-}-happyIn10 :: t10 -> (HappyAbsSyn t4 t5 t6 t7 t8 t9 t10 t11)+happyIn10 :: t10 -> (HappyAbsSyn t5 t6 t7 t8 t9 t10 t11 t12) happyIn10 x = Happy_GHC_Exts.unsafeCoerce# x {-# INLINE happyIn10 #-}-happyOut10 :: (HappyAbsSyn t4 t5 t6 t7 t8 t9 t10 t11) -> t10+happyOut10 :: (HappyAbsSyn t5 t6 t7 t8 t9 t10 t11 t12) -> t10 happyOut10 x = Happy_GHC_Exts.unsafeCoerce# x {-# INLINE happyOut10 #-}-happyIn11 :: t11 -> (HappyAbsSyn t4 t5 t6 t7 t8 t9 t10 t11)+happyIn11 :: t11 -> (HappyAbsSyn t5 t6 t7 t8 t9 t10 t11 t12) happyIn11 x = Happy_GHC_Exts.unsafeCoerce# x {-# INLINE happyIn11 #-}-happyOut11 :: (HappyAbsSyn t4 t5 t6 t7 t8 t9 t10 t11) -> t11+happyOut11 :: (HappyAbsSyn t5 t6 t7 t8 t9 t10 t11 t12) -> t11 happyOut11 x = Happy_GHC_Exts.unsafeCoerce# x {-# INLINE happyOut11 #-}-happyInTok :: (Token) -> (HappyAbsSyn t4 t5 t6 t7 t8 t9 t10 t11)+happyIn12 :: t12 -> (HappyAbsSyn t5 t6 t7 t8 t9 t10 t11 t12)+happyIn12 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyIn12 #-}+happyOut12 :: (HappyAbsSyn t5 t6 t7 t8 t9 t10 t11 t12) -> t12+happyOut12 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyOut12 #-}+happyInTok :: (Token) -> (HappyAbsSyn t5 t6 t7 t8 t9 t10 t11 t12) happyInTok x = Happy_GHC_Exts.unsafeCoerce# x {-# INLINE happyInTok #-}-happyOutTok :: (HappyAbsSyn t4 t5 t6 t7 t8 t9 t10 t11) -> (Token)+happyOutTok :: (HappyAbsSyn t5 t6 t7 t8 t9 t10 t11 t12) -> (Token) happyOutTok x = Happy_GHC_Exts.unsafeCoerce# x {-# INLINE happyOutTok #-} happyActOffsets :: HappyAddr-happyActOffsets = HappyA# "\x0e\x00\x1e\x00\x0e\x00\x06\x00\x00\x00\x00\x00\xfd\xff\x01\x00\x00\x00\x1a\x00\x0e\x00\x1a\x00\x0e\x00\x49\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x09\x00\x00\x00\x00\x00\x02\x00\x00\x00\x1a\x00\x0e\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1a\x00\x00\x00\x00\x00"#+happyActOffsets = HappyA# "\x0e\x00\x1a\x00\x1e\x00\x0e\x00\x06\x00\x01\x00\x00\x00\x1a\x00\x1a\x00\x4b\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\xfd\xff\x0e\x00\x0e\x00\x00\x00\x00\x00\x0e\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x09\x00\x00\x00\x02\x00\x00\x00\x1a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1a\x00\x00\x00\x00\x00\x00\x00\x00\x00"# happyGotoOffsets :: HappyAddr-happyGotoOffsets = HappyA# "\x45\x00\x00\x00\x3f\x00\x00\x00\x00\x00\x00\x00\x00\x00\xfe\xff\x00\x00\x4d\x00\x39\x00\x48\x00\x33\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x2d\x00\x27\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x19\x00\x00\x00\x00\x00"#+happyGotoOffsets = HappyA# "\x45\x00\x50\x00\x00\x00\x3f\x00\x00\x00\xfe\xff\x00\x00\x4d\x00\x48\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x39\x00\x33\x00\x00\x00\x00\x00\x2d\x00\x27\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x19\x00\x00\x00\x00\x00\x00\x00\x00\x00"# happyDefActions :: HappyAddr-happyDefActions = HappyA# "\xfa\xff\x00\x00\xfa\xff\x00\x00\xfc\xff\xfb\xff\xf9\xff\xf4\xff\xf2\xff\x00\x00\xfa\xff\xe8\xff\xfa\xff\x00\x00\xed\xff\xee\xff\xea\xff\xef\xff\xf1\xff\xf0\xff\xf6\xff\xe7\xff\x00\x00\xe9\xff\xfd\xff\x00\x00\xf3\xff\x00\x00\xfa\xff\xfa\xff\xfe\xff\xf7\xff\xf8\xff\xf5\xff\xeb\xff\xec\xff\x00\x00\xe6\xff"#+happyDefActions = HappyA# "\xf9\xff\x00\x00\x00\x00\xf9\xff\x00\x00\xf3\xff\xf1\xff\x00\x00\xe7\xff\x00\x00\xec\xff\xed\xff\xe9\xff\x00\x00\xfb\xff\xfa\xff\xf8\xff\xf9\xff\xf9\xff\xf5\xff\xfc\xff\xf9\xff\xf9\xff\xee\xff\xf0\xff\xef\xff\xe6\xff\x00\x00\xe8\xff\x00\x00\xf2\xff\x00\x00\xfd\xff\xf4\xff\xea\xff\xeb\xff\x00\x00\xf6\xff\xf7\xff\xe5\xff"# happyCheck :: HappyAddr-happyCheck = HappyA# "\xff\xff\x04\x00\x01\x00\x05\x00\x02\x00\x08\x00\x05\x00\x03\x00\x04\x00\x05\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x01\x00\x07\x00\x03\x00\x04\x00\x05\x00\x0e\x00\x06\x00\x08\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x01\x00\x03\x00\x04\x00\x05\x00\x05\x00\x07\x00\x03\x00\xff\xff\x09\x00\x0a\x00\x0b\x00\x0c\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x03\x00\x04\x00\x05\x00\xff\xff\x0b\x00\x0c\x00\x0d\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"#+happyCheck = HappyA# "\xff\xff\x04\x00\x01\x00\x05\x00\x02\x00\x08\x00\x05\x00\x03\x00\x04\x00\x05\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x01\x00\x07\x00\x03\x00\x04\x00\x05\x00\x0e\x00\x06\x00\x08\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x01\x00\x03\x00\x04\x00\x05\x00\x05\x00\x07\x00\x03\x00\xff\xff\x09\x00\x0a\x00\x0b\x00\x0c\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x03\x00\x04\x00\x05\x00\x03\x00\x04\x00\x05\x00\x0b\x00\x0c\x00\x0d\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"# happyTable :: HappyAddr-happyTable = HappyA# "\x00\x00\x1d\x00\x0a\x00\x1a\x00\x23\x00\x1e\x00\x0c\x00\x21\x00\x07\x00\x08\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x1c\x00\x0a\x00\x24\x00\x03\x00\x0b\x00\x0c\x00\xff\xff\x25\x00\x0d\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x0a\x00\x15\x00\x07\x00\x08\x00\x0c\x00\x25\x00\x03\x00\x00\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x1f\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\x20\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\x14\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\x18\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\x1e\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\x15\x00\x07\x00\x08\x00\x16\x00\x17\x00\x19\x00\x07\x00\x08\x00\x00\x00\x12\x00\x13\x00\x14\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"#+happyTable = HappyA# "\x00\x00\x16\x00\x08\x00\x1e\x00\x23\x00\x17\x00\x09\x00\x21\x00\x05\x00\x06\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x20\x00\x08\x00\x24\x00\x04\x00\x12\x00\x09\x00\xff\xff\x25\x00\x13\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x08\x00\x1a\x00\x05\x00\x06\x00\x09\x00\x27\x00\x04\x00\x00\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x25\x00\x0e\x00\x0f\x00\x10\x00\x05\x00\x06\x00\x26\x00\x0e\x00\x0f\x00\x10\x00\x05\x00\x06\x00\x13\x00\x0e\x00\x0f\x00\x10\x00\x05\x00\x06\x00\x14\x00\x0e\x00\x0f\x00\x10\x00\x05\x00\x06\x00\x20\x00\x0e\x00\x0f\x00\x10\x00\x05\x00\x06\x00\x0d\x00\x0e\x00\x0f\x00\x10\x00\x05\x00\x06\x00\x1a\x00\x05\x00\x06\x00\x1b\x00\x1c\x00\x1d\x00\x05\x00\x06\x00\x04\x00\x05\x00\x06\x00\x18\x00\x19\x00\x1a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"# -happyReduceArr = Happy_Data_Array.array (1, 25) [- (1 , happyReduce_1),+happyReduceArr = Happy_Data_Array.array (2, 26) [ (2 , happyReduce_2), (3 , happyReduce_3), (4 , happyReduce_4),@@ -121,205 +121,206 @@ (22 , happyReduce_22), (23 , happyReduce_23), (24 , happyReduce_24),- (25 , happyReduce_25)+ (25 , happyReduce_25),+ (26 , happyReduce_26) ] happy_n_terms = 15 :: Int happy_n_nonterms = 8 :: Int -happyReduce_1 = happySpecReduce_2 0# happyReduction_1-happyReduction_1 happy_x_2+happyReduce_2 = happySpecReduce_2 0# happyReduction_2+happyReduction_2 happy_x_2 happy_x_1- = case happyOut4 happy_x_2 of { happy_var_2 -> - happyIn4+ = case happyOut5 happy_x_2 of { happy_var_2 -> + happyIn5 (CmdName "{" : happy_var_2 )} -happyReduce_2 = happySpecReduce_2 0# happyReduction_2-happyReduction_2 happy_x_2+happyReduce_3 = happySpecReduce_2 0# happyReduction_3+happyReduction_3 happy_x_2 happy_x_1- = case happyOut4 happy_x_2 of { happy_var_2 -> - happyIn4+ = case happyOut5 happy_x_2 of { happy_var_2 -> + happyIn5 (CmdName "}" : happy_var_2 )} -happyReduce_3 = happySpecReduce_1 0# happyReduction_3-happyReduction_3 happy_x_1- = case happyOut5 happy_x_1 of { happy_var_1 -> - happyIn4- (happy_var_1- )}--happyReduce_4 = happySpecReduce_1 1# happyReduction_4+happyReduce_4 = happySpecReduce_1 0# happyReduction_4 happyReduction_4 happy_x_1 = case happyOut6 happy_x_1 of { happy_var_1 -> happyIn5 (happy_var_1 )} -happyReduce_5 = happySpecReduce_0 1# happyReduction_5-happyReduction_5 = happyIn5+happyReduce_5 = happySpecReduce_1 1# happyReduction_5+happyReduction_5 happy_x_1+ = case happyOut7 happy_x_1 of { happy_var_1 -> + happyIn6+ (happy_var_1+ )}++happyReduce_6 = happySpecReduce_0 1# happyReduction_6+happyReduction_6 = happyIn6 ([] ) -happyReduce_6 = happySpecReduce_1 2# happyReduction_6-happyReduction_6 happy_x_1- = case happyOut7 happy_x_1 of { happy_var_1 -> - happyIn6+happyReduce_7 = happySpecReduce_1 2# happyReduction_7+happyReduction_7 happy_x_1+ = case happyOut8 happy_x_1 of { happy_var_1 -> + happyIn7 ([happy_var_1] )} -happyReduce_7 = happySpecReduce_3 2# happyReduction_7-happyReduction_7 happy_x_3+happyReduce_8 = happySpecReduce_3 2# happyReduction_8+happyReduction_8 happy_x_3 happy_x_2 happy_x_1- = case happyOut7 happy_x_1 of { happy_var_1 -> - case happyOut4 happy_x_3 of { happy_var_3 -> - happyIn6+ = case happyOut8 happy_x_1 of { happy_var_1 -> + case happyOut5 happy_x_3 of { happy_var_3 -> + happyIn7 ([happy_var_1, CmdName "}"] ++ happy_var_3 )}} -happyReduce_8 = happySpecReduce_3 2# happyReduction_8-happyReduction_8 happy_x_3+happyReduce_9 = happySpecReduce_3 2# happyReduction_9+happyReduction_9 happy_x_3 happy_x_2 happy_x_1- = case happyOut7 happy_x_1 of { happy_var_1 -> - case happyOut4 happy_x_3 of { happy_var_3 -> - happyIn6+ = case happyOut8 happy_x_1 of { happy_var_1 -> + case happyOut5 happy_x_3 of { happy_var_3 -> + happyIn7 (happy_var_1 : happy_var_3 )}} -happyReduce_9 = happySpecReduce_2 2# happyReduction_9-happyReduction_9 happy_x_2+happyReduce_10 = happySpecReduce_2 2# happyReduction_10+happyReduction_10 happy_x_2 happy_x_1- = case happyOut4 happy_x_2 of { happy_var_2 -> - happyIn6+ = case happyOut5 happy_x_2 of { happy_var_2 -> + happyIn7 (happy_var_2 )} -happyReduce_10 = happySpecReduce_3 3# happyReduction_10-happyReduction_10 happy_x_3+happyReduce_11 = happySpecReduce_3 3# happyReduction_11+happyReduction_11 happy_x_3 happy_x_2 happy_x_1- = case happyOut8 happy_x_1 of { happy_var_1 -> + = case happyOut9 happy_x_1 of { happy_var_1 -> case happyOutTok happy_x_2 of { (InfixOp happy_var_2) -> - case happyOut7 happy_x_3 of { happy_var_3 -> - happyIn7+ case happyOut8 happy_x_3 of { happy_var_3 -> + happyIn8 (AppH (AppH (CmdName happy_var_2) happy_var_1) happy_var_3 )}}} -happyReduce_11 = happySpecReduce_1 3# happyReduction_11-happyReduction_11 happy_x_1- = case happyOut8 happy_x_1 of { happy_var_1 -> - happyIn7+happyReduce_12 = happySpecReduce_1 3# happyReduction_12+happyReduction_12 happy_x_1+ = case happyOut9 happy_x_1 of { happy_var_1 -> + happyIn8 (happy_var_1 )} -happyReduce_12 = happySpecReduce_2 4# happyReduction_12-happyReduction_12 happy_x_2+happyReduce_13 = happySpecReduce_2 4# happyReduction_13+happyReduction_13 happy_x_2 happy_x_1- = case happyOut8 happy_x_1 of { happy_var_1 -> - case happyOut9 happy_x_2 of { happy_var_2 -> - happyIn8+ = case happyOut9 happy_x_1 of { happy_var_1 -> + case happyOut10 happy_x_2 of { happy_var_2 -> + happyIn9 (AppH happy_var_1 happy_var_2 )}} -happyReduce_13 = happySpecReduce_1 4# happyReduction_13-happyReduction_13 happy_x_1- = case happyOut9 happy_x_1 of { happy_var_1 -> - happyIn8+happyReduce_14 = happySpecReduce_1 4# happyReduction_14+happyReduction_14 happy_x_1+ = case happyOut10 happy_x_1 of { happy_var_1 -> + happyIn9 (happy_var_1 )} -happyReduce_14 = happySpecReduce_2 5# happyReduction_14-happyReduction_14 happy_x_2+happyReduce_15 = happySpecReduce_2 5# happyReduction_15+happyReduction_15 happy_x_2 happy_x_1 = case happyOutTok happy_x_2 of { (Ident happy_var_2) -> - happyIn9+ happyIn10 (SrcName happy_var_2 )} -happyReduce_15 = happySpecReduce_2 5# happyReduction_15-happyReduction_15 happy_x_2+happyReduce_16 = happySpecReduce_2 5# happyReduction_16+happyReduction_16 happy_x_2 happy_x_1 = case happyOutTok happy_x_2 of { (InfixOp happy_var_2) -> - happyIn9+ happyIn10 (SrcName happy_var_2 )} -happyReduce_16 = happySpecReduce_2 5# happyReduction_16-happyReduction_16 happy_x_2+happyReduce_17 = happySpecReduce_2 5# happyReduction_17+happyReduction_17 happy_x_2 happy_x_1 = case happyOutTok happy_x_2 of { (Quote happy_var_2) -> - happyIn9+ happyIn10 (SrcName happy_var_2 )} -happyReduce_17 = happySpecReduce_1 5# happyReduction_17-happyReduction_17 happy_x_1+happyReduce_18 = happySpecReduce_1 5# happyReduction_18+happyReduction_18 happy_x_1 = case happyOutTok happy_x_1 of { (Quote happy_var_1) -> - happyIn9+ happyIn10 (CmdName happy_var_1 )} -happyReduce_18 = happySpecReduce_1 5# happyReduction_18-happyReduction_18 happy_x_1+happyReduce_19 = happySpecReduce_1 5# happyReduction_19+happyReduction_19 happy_x_1 = case happyOutTok happy_x_1 of { (CoreString happy_var_1) -> - happyIn9+ happyIn10 (CoreH happy_var_1 )} -happyReduce_19 = happySpecReduce_3 5# happyReduction_19-happyReduction_19 happy_x_3+happyReduce_20 = happySpecReduce_3 5# happyReduction_20+happyReduction_20 happy_x_3 happy_x_2 happy_x_1- = case happyOut10 happy_x_2 of { happy_var_2 -> - happyIn9+ = case happyOut11 happy_x_2 of { happy_var_2 -> + happyIn10 (ListH happy_var_2 )} -happyReduce_20 = happySpecReduce_3 5# happyReduction_20-happyReduction_20 happy_x_3+happyReduce_21 = happySpecReduce_3 5# happyReduction_21+happyReduction_21 happy_x_3 happy_x_2 happy_x_1- = case happyOut7 happy_x_2 of { happy_var_2 -> - happyIn9+ = case happyOut8 happy_x_2 of { happy_var_2 -> + happyIn10 (happy_var_2 )} -happyReduce_21 = happySpecReduce_1 5# happyReduction_21-happyReduction_21 happy_x_1+happyReduce_22 = happySpecReduce_1 5# happyReduction_22+happyReduction_22 happy_x_1 = case happyOutTok happy_x_1 of { (Ident happy_var_1) -> - happyIn9+ happyIn10 (CmdName happy_var_1 )} -happyReduce_22 = happySpecReduce_1 6# happyReduction_22-happyReduction_22 happy_x_1- = case happyOut11 happy_x_1 of { happy_var_1 -> - happyIn10+happyReduce_23 = happySpecReduce_1 6# happyReduction_23+happyReduction_23 happy_x_1+ = case happyOut12 happy_x_1 of { happy_var_1 -> + happyIn11 (happy_var_1 )} -happyReduce_23 = happySpecReduce_0 6# happyReduction_23-happyReduction_23 = happyIn10+happyReduce_24 = happySpecReduce_0 6# happyReduction_24+happyReduction_24 = happyIn11 ([] ) -happyReduce_24 = happySpecReduce_1 7# happyReduction_24-happyReduction_24 happy_x_1- = case happyOut7 happy_x_1 of { happy_var_1 -> - happyIn11+happyReduce_25 = happySpecReduce_1 7# happyReduction_25+happyReduction_25 happy_x_1+ = case happyOut8 happy_x_1 of { happy_var_1 -> + happyIn12 ([happy_var_1] )} -happyReduce_25 = happySpecReduce_3 7# happyReduction_25-happyReduction_25 happy_x_3+happyReduce_26 = happySpecReduce_3 7# happyReduction_26+happyReduction_26 happy_x_3 happy_x_2 happy_x_1- = case happyOut7 happy_x_1 of { happy_var_1 -> - case happyOut11 happy_x_3 of { happy_var_3 -> - happyIn11+ = case happyOut8 happy_x_1 of { happy_var_1 -> + case happyOut12 happy_x_3 of { happy_var_3 -> + happyIn12 (happy_var_1 : happy_var_3 )}} @@ -359,8 +360,11 @@ happyError' = parseError parser tks = happySomeParser where- happySomeParser = happyThen (happyParse 0# tks) (\x -> happyReturn (happyOut4 x))+ happySomeParser = happyThen (happyParse 0# tks) (\x -> happyReturn (happyOut5 x)) +exprParser tks = happySomeParser where+ happySomeParser = happyThen (happyParse 1# tks) (\x -> happyReturn (happyOut8 x))+ happySeq = happyDontSeq @@ -448,6 +452,9 @@ parseScript :: String -> Either String Script parseScript = lexer >=> parser++parseExprH :: String -> Either String ExprH+parseExprH = lexer >=> exprParser ---------------------------------------------
dist/build/HERMIT/ParserCore.hs view
@@ -4,6 +4,8 @@ module HERMIT.ParserCore ( parseCore , parseCoreExprT+ , parse2BeforeT+ , parse3BeforeT , parse2beforeBiR , parse3beforeBiR , parse4beforeBiR@@ -256,21 +258,17 @@ mkIntExpr' :: Integer -> CoreParseM CoreExpr-#if __GLASGOW_HASKELL__ > 706 mkIntExpr' i = do dflags <- lift getDynFlags return $ mkIntExpr dflags i-#else-mkIntExpr' i = return $ mkIntExpr i-#endif lookupName :: String -> CoreParseM CoreExpr lookupName nm = do- c <- ask- v <- lift $ prefixFailMsg (nm ++ " lookup: ") $ findId nm c+ vset <- ask+ v <- lift $ prefixFailMsg (nm ++ " lookup: ") $ findId (parseName nm) vset return $ varToCoreExpr v -type CoreParseM a = ReaderT HermitC HermitM a+type CoreParseM a = ReaderT VarSet HermitM a parseError :: Monad m => [Token] -> m a parseError ts = fail $ "core parse error: " ++ show ts@@ -337,19 +335,30 @@ --------------------------------------------- -parseCore :: CoreString -> HermitC -> HermitM CoreExpr+parseCore :: BoundVars c => CoreString -> c -> HermitM CoreExpr parseCore (CoreString s) c = case lexer s of Left msg -> fail msg- Right tokens -> runReaderT (parser tokens) c+ Right tokens -> runReaderT (parser tokens) (boundVars c) --------------------------------------------- -- These should probably go somewhere else. -- | Parse a 'CoreString' to a 'CoreExpr', using the current context.-parseCoreExprT :: CoreString -> TransformH a CoreExpr-parseCoreExprT = contextonlyT . parseCore+parseCoreExprT :: (BoundVars c, HasDebugChan m, HasHermitMEnv m, HasLemmas m, HasStash 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)+ => (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)+ => (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) parse2beforeBiR :: (CoreExpr -> CoreExpr -> BiRewriteH a) -> CoreString -> CoreString -> BiRewriteH a
dist/build/HERMIT/ParserType.hs view
@@ -2,15 +2,11 @@ {-# OPTIONS -fglasgow-exts -cpp #-} {-# LANGUAGE CPP #-} module HERMIT.ParserType-#if __GLASGOW_HASKELL__ <= 706- () where-#else ( parseType , parseTypeT , parseTypeWithHoles , parseTypeWithHolesT ) where-#endif import Control.Arrow import Control.Monad.State@@ -238,14 +234,10 @@ happySeq = happyDontSeq -#if __GLASGOW_HASKELL__ <= 706-findType = error "findType cannot be called in < GHC 7.8"-#endif- lookupName :: String -> TypeParseM Type lookupName nm = do c <- getContext- et <- lift $ attemptM $ findType nm c+ et <- lift $ attemptM $ findType (parseName nm) c either (const (addTyVar nm)) return et catchFrees :: Type -> TypeParseM ([TyVar], Type)@@ -268,7 +260,7 @@ addTyVar :: String -> TypeParseM Type addTyVar tvStr = do used <- gets tpUsed- case [ tv | tv <- used, getOccString tv == tvStr ] of+ case [ tv | tv <- used, unqualifiedName tv == tvStr ] of [] -> do tv <- lift $ newTyVarH tvStr liftedTypeKind modify $ \ st -> st { tpUsed = tv : tpUsed st } return $ mkTyVarTy tv
examples/concatVanishes/Flatten.hs view
@@ -3,10 +3,6 @@ import HList -#if __GLASGOW_HASKELL__ < 708-import Data.Function (fix)-#endif- data Tree a = Node (Tree a) (Tree a) | Leaf a flatten :: Tree a -> [a]
examples/concatVanishes/QSort.hs view
@@ -4,10 +4,6 @@ import HList import Data.List -#if __GLASGOW_HASKELL__ < 708-import Data.Function (fix)-#endif- data Tree a = Node (Tree a) (Tree a) | Leaf a qsort :: Ord a => [a] -> [a]
examples/concatVanishes/Rev.hs view
@@ -3,10 +3,6 @@ import HList -#if __GLASGOW_HASKELL__ < 708-import Data.Function (fix)-#endif- rev :: [a] -> [a] rev [] = [] rev (y:ys) = rev ys ++ [y]
examples/evaluation/Eval.hs view
@@ -3,10 +3,6 @@ import Prelude hiding (abs) -#if __GLASGOW_HASKELL__ < 708-import Data.Function (fix)-#endif- data Expr = Val Int | Add Expr Expr | Throw | Catch Expr Expr type Mint = Maybe Int
examples/factorial/Fac.hs view
@@ -6,10 +6,6 @@ import Prelude hiding ((*),(-)) import GHC.Exts -#if __GLASGOW_HASKELL__ < 708-import Data.Function (fix)-#endif- ------------------------------------ fac :: Int -> Int
examples/fib-stream/Fib.hs view
@@ -5,10 +5,6 @@ import Nat import Stream -#if __GLASGOW_HASKELL__ < 708-import Data.Function (fix)-#endif- fib :: Nat -> Nat fib Zero = Zero fib (Succ Zero) = Succ Zero
examples/fib-tuple/Fib.hs view
@@ -1,11 +1,6 @@ {-# LANGUAGE CPP #-} module Main where -#if __GLASGOW_HASKELL__ < 708--- so we can fix-intro-import Data.Function (fix)-#endif- import Prelude hiding ((+)) data Nat = Z | S Nat
examples/flatten/Flatten.hs view
@@ -3,10 +3,6 @@ import HList -#if __GLASGOW_HASKELL__ < 708-import Data.Function (fix)-#endif- data Tree a = Node (Tree a) (Tree a) | Leaf a flatten :: Tree a -> [a]
examples/hanoi/Hanoi.hs view
@@ -5,10 +5,6 @@ import Control.Monad (forM_) -#if __GLASGOW_HASKELL__ < 708-import Data.Function (fix)-#endif- data Nat = Z | S Nat toInt :: Nat -> Int
examples/last/Last.hs view
@@ -1,10 +1,6 @@ {-# LANGUAGE CPP #-} module Main where -#if __GLASGOW_HASKELL__ < 708-import Data.Function (fix)-#endif- import Prelude hiding (last) -------------------------------------------------
examples/qsort/QSort.hs view
@@ -3,10 +3,6 @@ import HList -#if __GLASGOW_HASKELL__ < 708-import Data.Function (fix)-#endif- import Data.List data Tree a = Node (Tree a) (Tree a) | Leaf a
examples/reverse/Reverse.hs view
@@ -4,10 +4,6 @@ import HList -- import Seq -#if __GLASGOW_HASKELL__ < 708-import Data.Function (fix)-#endif- rev :: [a] -> [a] rev [] = [] rev (x:xs) = rev xs ++ [x]
hermit.cabal view
@@ -1,5 +1,5 @@ Name: hermit-Version: 0.5.0.0+Version: 0.6.0.0 Synopsis: Haskell Equational Reasoning Model-to-Implementation Tunnel Description: HERMIT uses Haskell to express semi-formal models,@@ -28,12 +28,12 @@ . @ $ hermit Reverse.hs Reverse.hss resume- [starting HERMIT v0.5.0.0 on Reverse.hs]+ [starting HERMIT v0.6.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.5.0.0 ... linking ... done.+ Loading package hermit-0.6.0.0 ... linking ... done. [2 of 2] Compiling Main ( Reverse.hs, Reverse.o ) Linking Reverse ... $ ./Reverse@@ -44,12 +44,12 @@ . @ $ hermit Reverse.hs- [starting HERMIT v0.5.0.0 on Reverse.hs]+ [starting HERMIT v0.6.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.5.0.0 ... linking ... done.+ Loading package hermit-0.6.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@@ -143,9 +143,9 @@ containers >= 0.5.0.0, data-default >= 0.5.0, directory >= 1.2.0.0,- ghc >= 7.6,+ ghc >= 7.8, haskeline >= 0.7.0.3,- kure >= 2.16.0,+ kure >= 2.16.4, marked-pretty >= 0.1, mtl >= 2.1.2, operational >= 0.2.2.1,@@ -154,13 +154,13 @@ temporary >= 1.2.0.3, transformers - if !os(windows)+ if os(windows)+ build-depends: Win32+ else build-depends: terminfo >= 0.3.2.5 - if impl(ghc >= 7.8)- build-tools: happy >= 1.19.3, alex >= 3.1.3- else- build-tools: happy, alex+ build-tools: alex >= 3.1.3,+ happy >= 1.19.3 default-language: Haskell2010 @@ -226,6 +226,7 @@ HERMIT.PrettyPrinter.GHC HERMIT.Shell.Command+ HERMIT.Shell.Completion HERMIT.Shell.Dictionary HERMIT.Shell.Interpreter HERMIT.Shell.Externals@@ -241,6 +242,11 @@ HERMIT.Syntax Paths_hermit++ if os(windows)+ Other-modules:+ HERMIT.Win32.Console+ HERMIT.Win32.IO Hs-Source-Dirs: src
src/HERMIT.hs view
@@ -3,9 +3,9 @@ import Data.Maybe (fromMaybe) import HERMIT.GHC-import HERMIT.Plugin.Builder (getPhaseFlag)+import HERMIT.Plugin.Builder (getPassFlag) import HERMIT.Plugin plugin :: Plugin-plugin = hermitPlugin $ \ options -> let (pn,opts) = fromMaybe (0,options) (getPhaseFlag options)- in phase pn $ interactive [] opts+plugin = hermitPlugin $ \ options -> let (pn,opts) = fromMaybe (0,options) (getPassFlag options)+ in pass pn $ interactive [] opts
src/HERMIT/Context.hs view
@@ -178,9 +178,9 @@ boundVars :: VarSet -> VarSet boundVars = id --- | List all variables bound in the context that match the given name.-findBoundVars :: BoundVars c => String -> c -> VarSet-findBoundVars nm = filterVarSet (cmpString2Var nm) . boundVars+-- | List all variables bound in the context that match the given predicate.+findBoundVars :: BoundVars c => (Var -> Bool) -> c -> VarSet+findBoundVars p = filterVarSet p . boundVars -- | A class of contexts from which HERMIT bindings can be retrieved. class BoundVars c => ReadBindings c where
src/HERMIT/Core.hs view
@@ -58,11 +58,11 @@ , isCoArg , exprKindOrType , exprTypeM- , endoFunType+ , endoFunTypeM , splitTyConAppM , splitFunTypeM- , endoFunExprType- , funExprArgResTypes+ , endoFunExprTypeM+ , funExprArgResTypesM , funExprsWithInverseTypes , appCount , mapAlts@@ -184,24 +184,15 @@ -- | Syntactic Equality of 'Coercion's. coercionSyntaxEq :: Coercion -> Coercion -> Bool-#if __GLASGOW_HASKELL__ > 706 coercionSyntaxEq (Refl role1 ty1) (Refl role2 ty2) = role1 == role2 && typeSyntaxEq ty1 ty2 coercionSyntaxEq (TyConAppCo role1 tc1 cos1) (TyConAppCo role2 tc2 cos2) = role1 == role2 && tc1 == tc2 && all2 coercionSyntaxEq cos1 cos2-#else-coercionSyntaxEq (Refl ty1) (Refl ty2) = typeSyntaxEq ty1 ty2-coercionSyntaxEq (TyConAppCo tc1 cos1) (TyConAppCo tc2 cos2) = tc1 == tc2 && all2 coercionSyntaxEq cos1 cos2-#endif coercionSyntaxEq (AppCo co11 co12) (AppCo co21 co22) = coercionSyntaxEq co11 co21 && coercionSyntaxEq co12 co22 coercionSyntaxEq (ForAllCo v1 co1) (ForAllCo v2 co2) = v1 == v2 && coercionSyntaxEq co1 co2 coercionSyntaxEq (CoVarCo v1) (CoVarCo v2) = v1 == v2-#if __GLASGOW_HASKELL__ > 706 coercionSyntaxEq (AxiomInstCo con1 ind1 cos1) (AxiomInstCo con2 ind2 cos2) = con1 == con2 && ind1 == ind2 && all2 coercionSyntaxEq cos1 cos2 coercionSyntaxEq (LRCo lr1 co1) (LRCo lr2 co2) = lr1 == lr2 && coercionSyntaxEq co1 co2 coercionSyntaxEq (UnivCo role1 ty11 ty12) (UnivCo role2 ty21 ty22) = role1 == role2 && typeSyntaxEq ty11 ty21 && typeSyntaxEq ty12 ty22-#else-coercionSyntaxEq (AxiomInstCo con1 cos1) (AxiomInstCo con2 cos2) = con1 == con2 && all2 coercionSyntaxEq cos1 cos2-coercionSyntaxEq (UnsafeCo ty11 ty12) (UnsafeCo ty21 ty22) = typeSyntaxEq ty11 ty21 && typeSyntaxEq ty12 ty22-#endif+coercionSyntaxEq (SubCo co1) (SubCo co2) = coercionSyntaxEq co1 co2 coercionSyntaxEq (SymCo co1) (SymCo co2) = coercionSyntaxEq co1 co2 coercionSyntaxEq (TransCo co11 co12) (TransCo co21 co22) = coercionSyntaxEq co11 co21 && coercionSyntaxEq co12 co22 coercionSyntaxEq (NthCo n1 co1) (NthCo n2 co2) = n1 == n2 && coercionSyntaxEq co1 co2@@ -308,8 +299,7 @@ freeVarsBind :: CoreBind -> VarSet freeVarsBind (NonRec v e) = freeVarsExpr e `unionVarSet` freeVarsVar v freeVarsBind (Rec defs) = let (bs,es) = unzip defs- in delVarSetList (unionVarSets $ map freeVarsExpr es) bs- `unionVarSet` unionVarSets (map freeVarsVar bs)+ in delVarSetList (unionVarSets (map freeVarsVar bs ++ map freeVarsExpr es)) bs -- | Find all free variables on a binder. Equivalent to idFreeVars, but safe to call on type bindings. freeVarsVar :: Var -> VarSet@@ -380,30 +370,33 @@ splitTyConAppM :: Monad m => Type -> m (TyCon, [Type]) splitTyConAppM = maybeM "splitTyConApp failed." . splitTyConApp_maybe --- | Return the domain and codomain types of a function type, if it is a function type.-splitFunTypeM :: Monad m => Type -> m (Type,Type)-splitFunTypeM = maybeM "not a function type." . splitFunTy_maybe+-- | Get the quantified variables, domain, and codomain of a function type.+splitFunTypeM :: MonadCatch m => Type -> m ([TyVar], Type, Type)+splitFunTypeM ty = prefixFailMsg "Split function type failed: " $ do+ let (tvs, fTy) = splitForAllTys ty+ (argTy, resTy) <- maybeM "not a function type." $ splitFunTy_maybe fTy+ return (tvs, argTy, resTy) -- | Return the domain/codomain type of an endofunction type.-endoFunType :: Monad m => Type -> m Type-endoFunType ty =- do (ty1,ty2) <- splitFunTypeM ty+endoFunTypeM :: MonadCatch m => Type -> m ([TyVar], Type)+endoFunTypeM ty =+ do (tvs,ty1,ty2) <- splitFunTypeM ty guardMsg (eqType ty1 ty2) ("argument and result types differ.")- return ty1+ return (tvs, ty1) -- | Return the domain/codomain type of an endofunction expression.-endoFunExprType :: Monad m => CoreExpr -> m Type-endoFunExprType = exprTypeM >=> endoFunType+endoFunExprTypeM :: MonadCatch m => CoreExpr -> m ([TyVar], Type)+endoFunExprTypeM = exprTypeM >=> endoFunTypeM -- | Return the domain and codomain types of a function expression.-funExprArgResTypes :: Monad m => CoreExpr -> m (Type,Type)-funExprArgResTypes = exprTypeM >=> splitFunTypeM+funExprArgResTypesM :: MonadCatch m => CoreExpr -> m ([TyVar],Type,Type)+funExprArgResTypesM = exprTypeM >=> splitFunTypeM -- | Check two expressions have types @a -> b@ and @b -> a@, returning @(a,b)@. funExprsWithInverseTypes :: MonadCatch m => CoreExpr -> CoreExpr -> m (Type,Type) funExprsWithInverseTypes f g =- do (fdom,fcod) <- funExprArgResTypes f- (gdom,gcod) <- funExprArgResTypes g+ do (_,fdom,fcod) <- funExprArgResTypesM f -- TODO: don't throw away TyVars+ (_,gdom,gcod) <- funExprArgResTypesM g setFailMsg "functions do not have inverse types." $ do guardM (eqType fdom gcod) guardM (eqType gdom fcod)
src/HERMIT/Dictionary.hs view
@@ -20,6 +20,7 @@ , module HERMIT.Dictionary.Undefined , module HERMIT.Dictionary.Unfold , module HERMIT.Dictionary.Unsafe+ , module HERMIT.Dictionary.WorkerWrapper.Common -- TODO: rename , module HERMIT.Dictionary.WorkerWrapper.Fix , module HERMIT.Dictionary.WorkerWrapper.FixResult ) where@@ -64,6 +65,8 @@ import qualified HERMIT.Dictionary.Unfold as Unfold import HERMIT.Dictionary.Unsafe hiding (externals) import qualified HERMIT.Dictionary.Unsafe as Unsafe+import HERMIT.Dictionary.WorkerWrapper.Common hiding (externals)+import qualified HERMIT.Dictionary.WorkerWrapper.Common as WorkerWrapperCommon import HERMIT.Dictionary.WorkerWrapper.Fix hiding (externals) import qualified HERMIT.Dictionary.WorkerWrapper.Fix as WorkerWrapperFix import HERMIT.Dictionary.WorkerWrapper.FixResult hiding (externals)@@ -92,6 +95,7 @@ ++ Undefined.externals ++ Unfold.externals ++ Unsafe.externals+ ++ WorkerWrapperCommon.externals ++ WorkerWrapperFix.externals ++ WorkerWrapperFixResult.externals
src/HERMIT/Dictionary/AlphaConversion.hs view
@@ -1,50 +1,47 @@ {-# LANGUAGE FlexibleContexts, ScopedTypeVariables #-} module HERMIT.Dictionary.AlphaConversion- ( -- * Alpha-Renaming and Shadowing- externals- -- ** Alpha-Renaming- , alphaR- , alphaLamR- , alphaCaseBinderR- , alphaAltWithR- , alphaAltVarsR- , alphaAltR- , alphaCaseR- , alphaLetWithR- , alphaLetVarsR- , alphaLetR- , alphaProgConsWithR- , alphaProgConsIdsR- , alphaProgConsR- , alphaProgR- -- ** Shadow Detection and Unshadowing- , unshadowR- , unshadowExprR- , unshadowAltR- , unshadowProgR- , visibleVarsT- , cloneVarAvoidingT--- , freshNameGenAvoidingT- , freshNameGenAvoiding- , detectShadowsM- , replaceVarR- )-where+ ( -- * Alpha-Renaming and Shadowing+ externals+ -- ** Alpha-Renaming+ , alphaR+ , alphaLamR+ , alphaCaseBinderR+ , alphaAltWithR+ , alphaAltVarsR+ , alphaAltR+ , alphaCaseR+ , alphaLetWithR+ , alphaLetVarsR+ , alphaLetR+ , alphaProgConsWithR+ , alphaProgConsIdsR+ , alphaProgConsR+ , alphaProgR+ -- ** Shadow Detection and Unshadowing+ , unshadowR+ , unshadowExprR+ , unshadowAltR+ , unshadowProgR+ , visibleVarsT+ , cloneVarAvoidingT+ , freshNameGenAvoiding+ , detectShadowsM+ , replaceVarR+ ) where -import Control.Applicative import Control.Arrow-import Control.Monad (liftM2)+import Control.Monad (liftM, liftM2) import Data.Char (isDigit) import Data.Function (on)-import Data.List (intersect)-import Data.Maybe (fromMaybe, listToMaybe)+import Data.List (intersect, delete, elemIndex)+import Data.Maybe (listToMaybe) import HERMIT.Core import HERMIT.Context-import HERMIT.Monad import HERMIT.Kure import HERMIT.External import HERMIT.GHC+import HERMIT.Name import HERMIT.Utilities(dupsBy) import HERMIT.Dictionary.GHC hiding (externals)@@ -106,7 +103,7 @@ -- | 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.-cloneVarAvoidingT :: BoundVars c => Var -> Maybe String -> [Var] -> Transform c HermitM CoreTC Var+cloneVarAvoidingT :: (BoundVars c, MonadUnique m) => Var -> Maybe String -> [Var] -> Transform c m CoreTC Var cloneVarAvoidingT v mn vs = do vvs <- visibleVarsT let nameModifier = freshNameGenAvoiding mn (extendVarSetList vvs vs)@@ -125,7 +122,7 @@ , nm `notElem` names ] where- names = map uqName (varSetElems curr)+ names = varSetToStrings curr nums = reverse $ takeWhile isDigit (reverse old) baseLeng = length $ drop (length nums) old base = take baseLeng old@@ -136,8 +133,8 @@ -- | Discard variables from the first set that do not shadow a variable in the second set. shadowedBy :: VarSet -> VarSet -> VarSet-shadowedBy vs fvs = let fvUqNames = map uqName (varSetElems fvs)- in filterVarSet (\ v -> uqName v `elem` fvUqNames) vs+shadowedBy vs fvs = let fvNames = varSetToStrings fvs+ in filterVarSet (\ v -> unqualifiedName v `elem` fvNames) vs -- | Shadows are any duplicates in the list, or any occurrences of the list elements in the set. detectShadowsM :: Monad m => [Var] -> VarSet -> m VarSet@@ -147,72 +144,86 @@ -- | Rename local variables with manifestly unique names (x, x0, x1, ...). -- Does not rename top-level definitions.-unshadowR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, HasEmptyContext c, ReadPath c Crumb)- => Rewrite c HermitM Core+unshadowR :: ( AddBindings c, BoundVars c, ExtendPath c Crumb, HasEmptyContext c+ , ReadPath c Crumb, MonadCatch m, MonadUnique m )+ => Rewrite c m Core unshadowR = setFailMsg "No shadows to eliminate." $ anytdR (promoteExprR unshadowExprR <+ promoteAltR unshadowAltR <+ promoteProgR unshadowProgR) -unshadowExprR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb)- => Rewrite c HermitM CoreExpr+unshadowExprR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb, MonadCatch m, MonadUnique m)+ => Rewrite c m CoreExpr unshadowExprR = do- bs <- letVarsT <+ (return <$> (caseBinderIdT <+ lamVarT))- fvs <- unionVarSet <$> boundVarsT <*> arr freeVarsExpr+ bs <- letVarsT <+ (liftM return (caseBinderIdT <+ lamVarT))+ fvs <- liftM2 unionVarSet boundVarsT (arr freeVarsExpr) ss <- detectShadowsM bs fvs alphaLamR Nothing <+ alphaLetVarsR (varSetElems ss) <+ alphaCaseBinderR Nothing -unshadowAltR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb)- => Rewrite c HermitM CoreAlt+unshadowAltR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb, MonadCatch m, MonadUnique m)+ => Rewrite c m CoreAlt unshadowAltR = do bs <- arr altVars- fvs <- unionVarSet <$> boundVarsT <*> arr freeVarsAlt+ fvs <- liftM2 unionVarSet boundVarsT (arr freeVarsAlt) ss <- detectShadowsM bs fvs alphaAltVarsR (varSetElems ss) -unshadowProgR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb)- => Rewrite c HermitM CoreProg+unshadowProgR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb, MonadCatch m, MonadUnique m)+ => Rewrite c m CoreProg unshadowProgR = do bs <- progConsIdsT- fvs <- unionVarSet <$> boundVarsT <*> arr freeVarsProg+ fvs <- liftM2 unionVarSet boundVarsT (arr freeVarsProg) ss <- detectShadowsM bs fvs alphaProgConsIdsR (varSetElems ss) dupVars :: [Var] -> [Var]-dupVars = dupsBy ((==) `on` uqName)+dupVars = dupsBy ((==) `on` unqualifiedName) ----------------------------------------------------------------------- --- Maybe this should be defined elsewhere.+-- Maybe this should be defined in Dictionary.GHC. -- | Replace all occurrences of a specified variable. -- Arguments are the variable to replace and the replacement variable, respectively. replaceVarR :: (Injection a Core, MonadCatch m) => Var -> Var -> Rewrite c m a replaceVarR v v' = extractR $ tryR $ substR v $ varToCoreExpr v' --- | Given a variable to replace, and a replacement, produce a 'Var' @->@ 'Var' function that--- acts as an identity for all 'Var's except the one to replace, for which it returns the replacment.--- Don't export this, it'll likely just cause confusion.-replaceVar :: Var -> Var -> (Var -> Var)-replaceVar v v' = replaceVars [(v,v')]+-- TODO: Experimental+replaceRecBindVarR :: Monad m => Id -> Id -> Rewrite c m CoreBind+replaceRecBindVarR v v' =+ do Rec ies <- idR+ let (is,es) = unzip ies+ case elemIndex v is of+ Nothing -> fail "Specified identifier does not occur in the current recursive binding group."+ Just n -> let is0 = delete v is+ (is1,is2) = splitAt n is0+ is' = is1 ++ v' : is2+ es' = map (substCoreExpr v (Var v')) es+ -- TODO. Do we need to initialize the emptySubst with bindFreeVars?+ sub = extendSubst emptySubst v (Var v')+ in return $ snd $ substBind sub (Rec (zip is' es')) --- | Given a lists of variables to replace, and their replacements, produce a 'Var' @->@ 'Var' function that--- acts as in identity for all 'Var's except the ones to replace, for which it returns the replacment.--- Don't export this, it'll likely just cause confusion.-replaceVars :: [(Var,Var)] -> (Var -> Var)-replaceVars kvs v = fromMaybe v (lookup v kvs)+ -- let is0 = delete v is+ -- emptySub = mkEmptySubst $ mkInScopeSet $ unionVarSets (map (localFreeVarsExpr . Var) is0)+ -- sub = extendSubst emptySub v (Var v')+ -- (is1,is2) = splitAt n (snd $ substRecBndrs sub is0)+ -- is' = is1 ++ v' : is2+ -- es' = map (substCoreExpr v (Var v')) es+ -- in return $ Rec (zip is' es') ----------------------------------------------------------------------- -- | Alpha rename a lambda binder. Optionally takes a suggested new name.-alphaLamR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => Maybe String -> Rewrite c HermitM CoreExpr+alphaLamR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m)+ => Maybe String -> Rewrite c m CoreExpr alphaLamR mn = setFailMsg (wrongFormForAlpha "Lam v e") $ do v <- lamVarT v' <- extractT (cloneVarAvoidingT v mn [v])- lamAnyR (arr $ replaceVar v v') (replaceVarR v v')+ lamAnyR (return v') (replaceVarR v v') ----------------------------------------------------------------------- -- | Alpha rename a case binder. Optionally takes a suggested new name.-alphaCaseBinderR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => Maybe String -> Rewrite c HermitM CoreExpr+alphaCaseBinderR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m)+ => Maybe String -> Rewrite c m CoreExpr alphaCaseBinderR mn = setFailMsg (wrongFormForAlpha "Case e i ty alts") $ do i <- caseBinderIdT i' <- extractT (cloneVarAvoidingT i mn [i])@@ -221,7 +232,8 @@ ----------------------------------------------------------------------- -- | Rename the specified variable in a case alternative. Optionally takes a suggested new name.-alphaAltVarR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => Maybe String -> Var -> Rewrite c HermitM CoreAlt+alphaAltVarR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m)+ => Maybe String -> Var -> Rewrite c m CoreAlt alphaAltVarR mn v = do (con, vs, rhs) <- idR v' <- extractT (cloneVarAvoidingT v mn vs)@@ -238,129 +250,150 @@ -- | Rename the specified variables in a case alternative, using the suggested names where provided. -- Suggested names *must* be provided in left-to-right order matching the order of the alt binders.-alphaAltVarsWithR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => [(Maybe String,Var)] -> Rewrite c HermitM CoreAlt+alphaAltVarsWithR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m)+ => [(Maybe String,Var)] -> Rewrite c m CoreAlt alphaAltVarsWithR = andR . map (uncurry alphaAltVarR) . reverse -- note: right-to-left so type subst aren't undone -- | Rename the variables bound in a case alternative with the given list of suggested names.-alphaAltWithR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => [String] -> Rewrite c HermitM CoreAlt+alphaAltWithR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m)+ => [String] -> Rewrite c m CoreAlt alphaAltWithR ns = do vs <- arr altVars alphaAltVarsWithR $ zip (map Just ns) vs -- | Rename the specified variables in a case alternative.-alphaAltVarsR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => [Var] -> Rewrite c HermitM CoreAlt+alphaAltVarsR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m)+ => [Var] -> Rewrite c m CoreAlt alphaAltVarsR vs = do bs <- arr altVars alphaAltVarsWithR (zip (repeat Nothing) (bs `intersect` vs)) -- | Rename all identifiers bound in a case alternative.-alphaAltR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => Rewrite c HermitM CoreAlt+alphaAltR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m)+ => Rewrite c m CoreAlt alphaAltR = arr altVars >>= alphaAltVarsR ----------------------------------------------------------------------- -- | Rename all identifiers bound in a case expression.-alphaCaseR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => Rewrite c HermitM CoreExpr+alphaCaseR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m)+ => Rewrite c m CoreExpr alphaCaseR = alphaCaseBinderR Nothing >+> caseAllR idR idR idR (const alphaAltR) ----------------------------------------------------------------------- -- | Alpha rename a non-recursive let binder. Optionally takes a suggested new name.-alphaLetNonRecR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => Maybe String -> Rewrite c HermitM CoreExpr+alphaLetNonRecR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m)+ => Maybe String -> Rewrite c m CoreExpr alphaLetNonRecR mn = setFailMsg (wrongFormForAlpha "Let (NonRec v e1) e2") $ do v <- letNonRecVarT v' <- extractT (cloneVarAvoidingT v mn [v]) letNonRecAnyR (return v') idR (replaceVarR v v') -- | Alpha rename a non-recursive let binder if the variable appears in the argument list. Optionally takes a suggested new name.-alphaLetNonRecVarsR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => Maybe String -> [Var] -> Rewrite c HermitM CoreExpr-alphaLetNonRecVarsR mn vs = whenM ((`elem` vs) <$> letNonRecVarT) (alphaLetNonRecR mn)+alphaLetNonRecVarsR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m)+ => Maybe String -> [Var] -> Rewrite c m CoreExpr+alphaLetNonRecVarsR mn vs = whenM (liftM (`elem` vs) letNonRecVarT) (alphaLetNonRecR mn) -- TODO: Maybe it would be more efficient to rename all the Ids at once, rather than one by one? -- | Rename the specified identifiers in a recursive let, using the suggested names where provided.-alphaLetRecIdsWithR :: forall c. (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => [(Maybe String,Id)] -> Rewrite c HermitM CoreExpr+alphaLetRecIdsWithR :: forall c m. ( ExtendPath c Crumb, ReadPath c Crumb, AddBindings c+ , BoundVars c, MonadCatch m, MonadUnique m )+ => [(Maybe String,Id)] -> Rewrite c m CoreExpr alphaLetRecIdsWithR = andR . map (uncurry alphaLetRecIdR) where -- | Rename the specified identifier bound in a recursive let. Optionally takes a suggested new name.- alphaLetRecIdR :: Maybe String -> Id -> Rewrite c HermitM CoreExpr+ alphaLetRecIdR :: Maybe String -> Id -> Rewrite c m CoreExpr alphaLetRecIdR mn i = setFailMsg (wrongFormForAlpha "Let (Rec bs) e") $ do is <- letRecIdsT i' <- extractT (cloneVarAvoidingT i mn is)- letRecDefAnyR (\ _ -> (arr (replaceVar i i'), replaceVarR i i')) (replaceVarR i i')+ letAnyR (replaceRecBindVarR i i') (replaceVarR i i') -- | Rename the identifiers bound in a Let with the given list of suggested names.-alphaLetWithR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => [String] -> Rewrite c HermitM CoreExpr+alphaLetWithR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m)+ => [String] -> Rewrite c m CoreExpr alphaLetWithR ns = alphaLetNonRecR (listToMaybe ns) <+ (letRecIdsT >>= (alphaLetRecIdsWithR . zip (map Just ns))) -- | Rename the specified variables bound in a let.-alphaLetVarsR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => [Var] -> Rewrite c HermitM CoreExpr+alphaLetVarsR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m)+ => [Var] -> Rewrite c m CoreExpr alphaLetVarsR vs = alphaLetNonRecVarsR Nothing vs <+ (do bs <- letT (arr bindVars) successT const alphaLetRecIdsWithR (zip (repeat Nothing) (bs `intersect` vs)) ) -- | Rename all identifiers bound in a Let.-alphaLetR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => Rewrite c HermitM CoreExpr+alphaLetR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m)+ => Rewrite c m CoreExpr alphaLetR = letVarsT >>= alphaLetVarsR ----------------------------------------------------------------------- -- | Alpha rename a non-recursive top-level binder. Optionally takes a suggested new name.-alphaProgConsNonRecR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => Maybe String -> Rewrite c HermitM CoreProg+alphaProgConsNonRecR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m)+ => Maybe String -> Rewrite c m CoreProg alphaProgConsNonRecR mn = setFailMsg (wrongFormForAlpha "ProgCons (NonRec v e) p") $ do i <- progConsNonRecIdT- guardMsg (not $ isExportedId i) ("Identifier " ++ var2String i ++ " is exported, and thus cannot be alpha-renamed.")+ guardMsg (not $ isExportedId i) ("Identifier " ++ unqualifiedName i ++ " is exported, and thus cannot be alpha-renamed.") i' <- extractT (cloneVarAvoidingT i mn [i]) consNonRecAnyR (return i') idR (replaceVarR i i') -- | Alpha rename a non-recursive top-level binder if the identifier appears in the argument list. Optionally takes a suggested new name.-alphaProgConsNonRecIdsR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => Maybe String -> [Id] -> Rewrite c HermitM CoreProg-alphaProgConsNonRecIdsR mn is = whenM ((`elem` is) <$> progConsNonRecIdT) (alphaProgConsNonRecR mn)+alphaProgConsNonRecIdsR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m)+ => Maybe String -> [Id] -> Rewrite c m CoreProg+alphaProgConsNonRecIdsR mn is = whenM (liftM (`elem` is) progConsNonRecIdT) (alphaProgConsNonRecR mn) -- TODO: Maybe it would be more efficient to rename all the Ids at once, rather than one by one? -- | Rename the specified identifiers in a recursive top-level binding at the head of a program, using the suggested names where provided.-alphaProgConsRecIdsWithR :: forall c. (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => [(Maybe String,Id)] -> Rewrite c HermitM CoreProg+alphaProgConsRecIdsWithR :: forall c m. ( ExtendPath c Crumb, ReadPath c Crumb, AddBindings c+ , BoundVars c, MonadCatch m, MonadUnique m )+ => [(Maybe String,Id)] -> Rewrite c m CoreProg alphaProgConsRecIdsWithR = andR . map (uncurry alphaProgConsRecIdR) . filter (not . isExportedId . snd) where -- | Rename the specified identifier bound in a recursive top-level binder. Optionally takes a suggested new name.- alphaProgConsRecIdR :: Maybe String -> Id -> Rewrite c HermitM CoreProg+ alphaProgConsRecIdR :: Maybe String -> Id -> Rewrite c m CoreProg alphaProgConsRecIdR mn i = setFailMsg (wrongFormForAlpha "ProgCons (Rec bs) p") $ do is <- progConsRecIdsT i' <- extractT (cloneVarAvoidingT i mn is)- consRecDefAnyR (\ _ -> (arr (replaceVar i i'), replaceVarR i i')) (replaceVarR i i')+ progConsAnyR (replaceRecBindVarR i i') (replaceVarR i i') -- | Rename the identifiers bound in the top-level binding at the head of the program with the given list of suggested names.-alphaProgConsWithR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => [String] -> Rewrite c HermitM CoreProg+alphaProgConsWithR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m)+ => [String] -> Rewrite c m CoreProg alphaProgConsWithR ns = alphaProgConsNonRecR (listToMaybe ns) <+ (progConsRecIdsT >>= (alphaProgConsRecIdsWithR . zip (map Just ns))) -- | Rename the specified variables bound in the top-level binding at the head of the program.-alphaProgConsIdsR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => [Id] -> Rewrite c HermitM CoreProg+alphaProgConsIdsR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m)+ => [Id] -> Rewrite c m CoreProg alphaProgConsIdsR vs = alphaProgConsNonRecIdsR Nothing vs <+ (do bs <- progConsT (arr bindVars) successT const alphaProgConsRecIdsWithR (zip (repeat Nothing) (bs `intersect` vs)) ) -- | Rename all identifiers bound in the top-level binding at the head of the program.-alphaProgConsR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => Rewrite c HermitM CoreProg+alphaProgConsR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m)+ => Rewrite c m CoreProg alphaProgConsR = progConsIdsT >>= alphaProgConsIdsR ----------------------------------------------------------------------- -- | Rename all identifiers bound at the top-level.-alphaProgR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => Rewrite c HermitM CoreProg+alphaProgR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m)+ => Rewrite c m CoreProg alphaProgR = alphaProgConsR >+> progConsAllR idR alphaProgR ----------------------------------------------------------------------- -- | Alpha rename any bindings at this node. Note: does not rename case alternatives unless invoked on the alternative.-alphaR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => Rewrite c HermitM Core+alphaR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m)+ => Rewrite c m Core alphaR = setFailMsg "Cannot alpha-rename here." $ promoteExprR (alphaLamR Nothing <+ alphaCaseBinderR Nothing <+ alphaLetR) <+ promoteAltR alphaAltR
src/HERMIT/Dictionary/Common.hs view
@@ -13,8 +13,6 @@ , callNameG , callDataConT , callDataConNameT- , callsR- , callsT -- ** Collecting variable bindings , progConsIdsT , progConsRecIdsT@@ -32,11 +30,9 @@ , boundVarsT , findBoundVarT , findIdT-#if __GLASGOW_HASKELL__ > 706 , findVarT , findTyConT , findTypeT-#endif , varBindingDepthT , varIsOccurrenceOfT , exprIsOccurrenceOfT@@ -63,9 +59,9 @@ ------------------------------------------------------------------------------ --- | Apply a transformation to a value in the current context.+-- | apply a transformation to a value in the current context. applyInContextT :: Transform c m a b -> a -> Transform c m x b-applyInContextT t a = contextonlyT $ \ c -> apply t c a+applyInContextT t a = contextonlyT $ \ c -> applyT t c a -- Note: this is the same as: return a >>> t @@ -78,6 +74,7 @@ App {} -> return (collectArgs e) _ -> fail "not an application or variable occurence." +-- | Succeeds if we are looking at an application matching the given predicate. callPredT :: Monad m => (Id -> [CoreExpr] -> Bool) -> Transform c m CoreExpr (CoreExpr, [CoreExpr]) callPredT p = do call@(Var i, args) <- callT@@ -86,9 +83,11 @@ -- | Succeeds if we are looking at an application of given function -- returning zero or more arguments to which it is applied.-callNameT :: MonadCatch m => String -> Transform c m CoreExpr (CoreExpr, [CoreExpr])-callNameT nm = setFailMsg ("callNameT failed: not a call to '" ++ nm ++ ".") $- callPredT (const . cmpString2Var nm)+--+-- Note: comparison is performed with cmpHN2Var.+callNameT :: MonadCatch m => HermitName -> Transform c m CoreExpr (CoreExpr, [CoreExpr])+callNameT nm = prefixFailMsg ("callNameT failed: not a call to '" ++ show nm ++ ".")+ $ callPredT (const . cmpHN2Var nm) -- | Succeeds if we are looking at a fully saturated function call. callSaturatedT :: Monad m => Transform c m CoreExpr (CoreExpr, [CoreExpr])@@ -97,20 +96,15 @@ -- idArity is conservatively set to zero by default. -- | Succeeds if we are looking at an application of given function-callNameG :: MonadCatch m => String -> Transform c m CoreExpr ()-callNameG nm = prefixFailMsg "callNameG failed: " $ callNameT nm >>= \_ -> constT (return ())+callNameG :: MonadCatch m => HermitName -> Transform c m CoreExpr ()+callNameG nm = prefixFailMsg "callNameG failed: " $ callNameT nm >> return () -- | Succeeds if we are looking at an application of a data constructor. callDataConT :: MonadCatch m => Transform c m CoreExpr (DataCon, [Type], [CoreExpr]) callDataConT = prefixFailMsg "callDataConT failed:" $-#if __GLASGOW_HASKELL__ > 706 do mb <- contextfreeT $ \ e -> let in_scope = mkInScopeSet (mkVarEnv [ (v,v) | v <- varSetElems (localFreeVarsExpr e) ]) in return $ exprIsConApp_maybe (in_scope, idUnfolding) e maybe (fail "not a datacon application.") return mb-#else- contextfreeT (return . exprIsConApp_maybe idUnfolding)- >>= maybe (fail "not a datacon application.") return-#endif -- | Succeeds if we are looking at an application of a named data constructor. callDataConNameT :: MonadCatch m => String -> Transform c m CoreExpr (DataCon, [Type], [CoreExpr])@@ -119,16 +113,6 @@ guardMsg (cmpString2Name nm (dataConName dc)) "wrong datacon." return res --- TODO: Both callsR and callsT should be eliminated, now that we have callNameT--- | Apply a rewrite to all applications of a given function in a top-down manner, pruning on success.-callsR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, HasEmptyContext c, MonadCatch m) => String -> Rewrite c m CoreExpr -> Rewrite c m Core-callsR nm rr = prunetdR (promoteExprR $ callNameG nm >> rr)---- | Apply a translate to all applications of a given function in a top-down manner,--- pruning on success, collecting the results.-callsT :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, HasEmptyContext c, MonadCatch m) => String -> Transform c m CoreExpr b -> Transform c m Core [b]-callsT nm t = collectPruneT (promoteExprT $ callNameG nm >> t)- ------------------------------------------------------------------------------ -- | List the identifiers bound by the top-level binding group at the head of the program.@@ -200,35 +184,39 @@ boundVarsT = contextonlyT (return . boundVars) -- | Find the unique variable bound in the context that matches the given name, failing if it is not unique.-findBoundVarT :: (BoundVars c, MonadCatch m) => String -> Transform c m a Var-findBoundVarT nm = prefixFailMsg ("Cannot resolve name " ++ nm ++ ", ") $- do c <- contextT- case varSetElems (findBoundVars nm c) of- [] -> fail "no matching variables in scope."- [v] -> return v- _ : _ : _ -> fail "multiple matching variables in scope."+findBoundVarT :: (BoundVars c, MonadCatch m) => (Var -> Bool) -> Transform c m a Var+findBoundVarT p = do+ c <- contextT+ case varSetElems (findBoundVars p c) of+ [] -> fail "no matching variables in scope."+ [v] -> return v+ _ : _ : _ -> fail "multiple matching variables in scope." -------------------------------------------------------------------------------------------------- -- | Lookup the name in the context first, then, failing that, in GHC's global reader environment.-findIdT :: (BoundVars c, HasModGuts m, HasHscEnv m, MonadCatch m, MonadIO m, MonadThings m) => String -> Transform c m a Id-findIdT nm = prefixFailMsg ("Cannot resolve name " ++ nm ++ ", ") $ contextonlyT (findId nm)+findIdT :: (BoundVars c, HasHermitMEnv m, HasHscEnv m, MonadCatch m, MonadIO m, MonadThings m)+ => HermitName -> Transform c m a Id+findIdT nm = prefixFailMsg ("Cannot resolve name " ++ show nm ++ ", ") $ contextonlyT (findId nm) -#if __GLASGOW_HASKELL__ > 706 -- | Lookup the name in the context first, then, failing that, in GHC's global reader environment.-findVarT :: (BoundVars c, HasModGuts m, HasHscEnv m, MonadCatch m, MonadIO m, MonadThings m) => String -> Transform c m a Var-findVarT nm = prefixFailMsg ("Cannot resolve name " ++ nm ++ ", ") $ contextonlyT (findVar nm)+findVarT :: (BoundVars c, HasHermitMEnv m, HasHscEnv m, MonadCatch m, MonadIO m, MonadThings m)+ => HermitName -> Transform c m a Var+findVarT nm = prefixFailMsg ("Cannot resolve name " ++ show nm ++ ", ") $ contextonlyT (findVar nm) -- | Lookup the name in the context first, then, failing that, in GHC's global reader environment.-findTyConT :: (BoundVars c, HasModGuts m, HasHscEnv m, MonadCatch m, MonadIO m, MonadThings m) => String -> Transform c m a TyCon-findTyConT nm = prefixFailMsg ("Cannot resolve name " ++ nm ++ ", ") $ contextonlyT (findTyCon nm)+findTyConT :: (BoundVars c, HasHermitMEnv m, HasHscEnv m, MonadCatch m, MonadIO m, MonadThings m)+ => HermitName -> Transform c m a TyCon+findTyConT nm = prefixFailMsg ("Cannot resolve name " ++ show nm ++ ", ") $ contextonlyT (findTyCon nm) -- | Lookup the name in the context first, then, failing that, in GHC's global reader environment.-findTypeT :: (BoundVars c, HasModGuts m, HasHscEnv m, MonadCatch m, MonadIO m, MonadThings m) => String -> Transform c m a Type-findTypeT nm = prefixFailMsg ("Cannot resolve name " ++ nm ++ ", ") $ contextonlyT (findType nm)-#endif+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@@ -241,7 +229,7 @@ -- | 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-withVarsInScope vs t = transform $ apply t . flip (foldl (flip addLambdaBinding)) vs -- careful to add left-to-right+withVarsInScope vs t = transform $ applyT t . flip (foldl (flip addLambdaBinding)) vs -- careful to add left-to-right ------------------------------------------------------------------------------
src/HERMIT/Dictionary/Composite.hs view
@@ -8,17 +8,22 @@ , bashR , bashExtendedWithR , bashDebugR- )-where+ , smashR+ , smashUsingR+ , smashExtendedWithR+ ) where import Control.Arrow +import Data.String (fromString)+ import HERMIT.Context import HERMIT.Core+import HERMIT.External import HERMIT.GHC-import HERMIT.Monad import HERMIT.Kure-import HERMIT.External+import HERMIT.Monad+import HERMIT.Name import HERMIT.Dictionary.Debug hiding (externals) import HERMIT.Dictionary.GHC hiding (externals)@@ -31,7 +36,8 @@ externals :: [External] externals = [ external "unfold-basic-combinator" (promoteExprR unfoldBasicCombinatorR :: RewriteH Core)- [ "Unfold the current expression if it is one of the basic combinators: ($), (.), id, flip, const, fst or snd." ]+ [ "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) [ "innermost (unfold-basic-combinator <+ beta-reduce-plus <+ safe-let-subst <+ case-reduce <+ let-elim)" ] , external "bash" (bashR :: RewriteH Core)@@ -52,16 +58,20 @@ ------------------------------------------------------------------------------------------------------ -basicCombinators :: [String]-basicCombinators = ["$",".","id","flip","const","fst","snd","curry","uncurry"]+basicCombinators :: [HermitName]+basicCombinators = map fromString ["$",".","id","flip","const","fst","snd","curry","uncurry"] --- | Unfold the current expression if it is one of the basic combinators: ('$'), ('.'), 'id', 'flip', 'const', 'fst' or 'snd'.+-- | Unfold the current expression if it is one of the basic combinators:+-- ('$'), ('.'), 'id', 'flip', 'const', 'fst', 'snd', 'curry', and 'uncurry'. -- This is intended to be used as a component of simplification traversals such as 'simplifyR' or 'bashR'.-unfoldBasicCombinatorR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => Rewrite c HermitM CoreExpr-unfoldBasicCombinatorR = setFailMsg "unfold-basic-combinator failed." $- unfoldNamesR basicCombinators+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 -simplifyR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => Rewrite c HermitM Core+simplifyR :: ( AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb+ , MonadCatch m, MonadUnique m )+ => Rewrite c m Core simplifyR = setFailMsg "Simplify failed: nothing to simplify." $ innermostR ( promoteBindR recToNonrecR <+ promoteExprR ( unfoldBasicCombinatorR@@ -73,80 +83,68 @@ ------------------------------------------------------------------------------------------------------ -bashR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => Rewrite c HermitM Core+-- | Bash is intended as a general-purpose cleanup/simplification command.+-- It performs rewrites such as let floating, case floating, and case elimination, when safe.+-- It also performs dead binding elimination and case reduction, and unfolds a number of+-- basic combinators. See 'bashComponents' for a list of rewrites performed.+-- Bash also performs occurrence analysis and de-zombification on the result, to update+-- 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 bashR = bashExtendedWithR [] -bashExtendedWithR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => [Rewrite c HermitM Core] -> Rewrite c HermitM Core+-- | 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 bashExtendedWithR rs = bashUsingR (rs ++ map fst bashComponents) --smashR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => Rewrite c HermitM Core-smashR = smashExtendedWithR []--smashExtendedWithR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => [Rewrite c HermitM Core] -> Rewrite c HermitM Core-smashExtendedWithR rs = smashUsingR (rs ++ map fst smashComponents1) (map fst smashComponents2)----- | Like bashR, but outputs name of each successful sub-rewrite, providing a log.+-- | Like 'bashR', but outputs name of each successful sub-rewrite, providing a log. -- Also performs core lint on the result of a successful sub-rewrite. -- If core lint fails, shows core fragment before and after the sub-rewrite which introduced the problem. -- Note: core fragment which fails linting is still returned! Otherwise would behave differently than bashR. -- Useful for debugging the bash command itself.-bashDebugR :: RewriteH Core-bashDebugR = bashUsingR [ idR >>= \e -> r >>> traceR nm >>> (catchM (promoteT lintExprT >> idR)- (\s -> do _ <- return e >>> observeR "[before]"- observeR ("[" ++ nm ++ "]\n" ++ s)))+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+bashDebugR = bashUsingR [ bracketR nm r >>> catchM (promoteT lintExprT >> idR) traceR | (r,nm) <- bashComponents ] --- bashUsingR :: forall c m. (ExtendPath c Crumb, AddBindings c, MonadCatch m) => [Rewrite c m Core] -> Rewrite c m Core--- bashUsingR rs =--- setFailMsg "bash failed: nothing to do." $--- readerT $ \ core1 -> occurAnalyseR >>> readerT (\ core2 -> if core1 `coreSyntaxEq` core2--- then bashCoreR -- equal, no progress yet--- else tryR bashCoreR -- unequal, progress has already been made--- )--- -- the changedByR combinator doesn't quite do what we need here--- where--- bashCoreR :: Rewrite c m Core--- bashCoreR = repeatR (innermostR (catchesT rs) >>> occurAnalyseR)--bashUsingR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, HasEmptyContext c, MonadCatch m) => [Rewrite c m Core] -> Rewrite c m Core-bashUsingR rs =- setFailMsg "bash failed: nothing to do." $+-- | 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+bashUsingR rs = setFailMsg "bash failed: nothing to do." $ repeatR (occurAnalyseR >>> onetdR (catchesT rs)) >+> anytdR (promoteExprR dezombifyR) >+> occurAnalyseChangedR -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 rs1 rs2 =- setFailMsg "smash failed: nothing to do." $- repeatR (occurAnalyseR >>> (onetdR (catchesT rs1) <+ onetdR (catchesT rs2))) >+> anytdR (promoteExprR dezombifyR) >+> occurAnalyseChangedR--- -- occurAnalyseChangedR >+> (innermostR (catchesT rs) >>> occurAnalyseR)- {- Occurrence Analysis updates meta-data, as well as performing some basic simplifications. occurAnalyseR always succeeds, whereas occurAnalyseChangedR fails is the result is syntactically equivalent. The awkwardness is because: - we want bash to fail if nothing changes- - we want bash to succeed if the result is not syntactically-equivalent (ideally, if any changes are made at all, but that's not the case yet)+ - we want bash to succeed if the result is not syntactically-equivalent+ (ideally, if any changes are made at all, but that's not the case yet) - we want bash to update the meta-data - after running bash there should be nothing left to do (i.e. an immediately subsequent bash should always fail) -Also, it's still possible for some meta-data to be out-of-date after bash, despite the case analysis. For example, if the focal point is a case-alt rhs, this won't update the identifer info of variables bound in the alternative.+Also, it's still possible for some meta-data to be out-of-date after bash, despite the case analysis.+For example, if the focal point is a case-alt rhs, this won't update the identifer info of variables+bound in the alternative. -} bashHelp :: [String]-bashHelp = "Iteratively apply the following rewrites until nothing changes:" : map snd (bashComponents- :: [(RewriteH Core,String)] -- to resolve ambiguity+bashHelp = "Iteratively apply the following rewrites until nothing changes:"+ : map snd (bashComponents :: [(RewriteH Core,String)] -- to resolve ambiguity )- -- TODO: Think about a good order for bash.-bashComponents :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => [(Rewrite c HermitM Core, String)]+bashComponents :: ( AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb+ , MonadCatch m, MonadUnique m )+ => [(Rewrite c m Core, String)] bashComponents = [ -- (promoteExprR occurAnalyseExprChangedR, "occur-analyse-expr") -- ?? (promoteExprR betaReduceR, "beta-reduce") -- O(1) , (promoteExprR (caseReduceR True), "case-reduce") -- O(n)- , (promoteExprR (caseReduceIdR True), "case-reduce-id") -- O(n)+ , (promoteExprR (caseReduceUnfoldR True), "case-reduce-unfold") -- O(n) , (promoteExprR caseElimSeqR, "case-elim-seq") , (promoteExprR unfoldBasicCombinatorR, "unfold-basic-combinator") -- O(n) , (promoteExprR inlineCaseAlternativeR, "inline-case-alternative") -- O(n)@@ -171,6 +169,28 @@ ] +------------------------------------------------------------------------------------------------------++-- | Smash is a more powerful but less efficient version of bash.+-- Unlike bash, smash is not concerned with whether it duplicates work,+-- 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+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+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 rs1 rs2 =+ setFailMsg "smash failed: nothing to do." $+ repeatR (occurAnalyseR >>> (onetdR (catchesT rs1) <+ onetdR (catchesT rs2))) >+> anytdR (promoteExprR dezombifyR) >+> occurAnalyseChangedR++ 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@@ -178,12 +198,14 @@ -- | As bash, but with "let-nonrec-subst" instead of "let-nonrec-subst-safe".-smashComponents1 :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => [(Rewrite c HermitM Core, String)]+smashComponents1 :: ( AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb+ , MonadCatch m, MonadUnique m )+ => [(Rewrite c m Core, String)] smashComponents1 = [ -- (promoteExprR occurAnalyseExprChangedR, "occur-analyse-expr") -- ?? (promoteExprR betaReduceR, "beta-reduce") -- O(1) , (promoteExprR (caseReduceR True), "case-reduce") -- O(n)- , (promoteExprR (caseReduceIdR True), "case-reduce-id") -- O(n)+ , (promoteExprR (caseReduceUnfoldR True), "case-reduce-unfold") -- O(n) , (promoteExprR caseElimSeqR, "case-elim-seq") , (promoteExprR unfoldBasicCombinatorR, "unfold-basic-combinator") -- O(n) , (promoteExprR inlineCaseAlternativeR, "inline-case-alternative") -- O(n)@@ -207,14 +229,9 @@ -- , (promoteExprR dezombifyR, "dezombify") -- O(1) -- performed at the end ] -smashComponents2 :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => [(Rewrite c HermitM Core, String)]+smashComponents2 :: ( ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c+ , MonadCatch m, MonadUnique m )+ => [(Rewrite c m Core, String)] smashComponents2 =- [- (promoteExprR caseElimMergeAltsR, "case-elim-merge-alts") -- do this last, lest it prevent other simplifications- ]----- (beta-reduce <+ case-reduce <+ case-reduce-id <+ case-elim-seq <+ unfold-basic-combinator <+ inline-case-alternative <+ eta-reduce <+ let-subst <+ case-float-app <+ case-float-case <+ case-float-let <+ case-float-cast <+ let-float-app <+ let-float-arg <+ let-float-lam <+ let-float-let <+ let-float-case <+ let-float-cast <+ let-float-top <+ cast-elim-refl <+ cast-elim-sym---------------------------------------------------------------------------------------------------------+ [ (promoteExprR caseElimMergeAltsR, "case-elim-merge-alts") -- do this last, lest it prevent other simplifications+ ]
src/HERMIT/Dictionary/Debug.hs view
@@ -1,48 +1,51 @@ {-# LANGUAGE FlexibleContexts #-} module HERMIT.Dictionary.Debug- ( -- * Debugging Dictionarys- externals- , bracketR- , observeR- , observeFailureR- , traceR- )-where+ ( -- * Debugging Rewrites+ externals+ , bracketR+ , observeR+ , observeFailureR+ , traceR+ ) where import Control.Arrow -import HERMIT.Kure+import HERMIT.Context+import HERMIT.Core import HERMIT.External+import HERMIT.Kure import HERMIT.Monad -- | Exposed debugging 'External's. externals :: [External] externals = map (.+ Debug)- [ external "trace" (traceR :: String -> RewriteH Core)- [ "give a side-effect message as output when processing this command" ]- , external "observe" (observeR :: String -> RewriteH Core)- [ "give a side-effect message as output, and observe the value being processed" ]- , external "observe-failure" (observeFailureR :: String -> RewriteH Core -> RewriteH Core)- [ "give a side-effect message if the rewrite fails, including the failing input" ]- , external "bracket" (bracketR :: String -> RewriteH Core -> RewriteH Core)- [ "if given rewrite succeeds, see its input and output" ]- ]+ [ external "trace" (traceR :: String -> RewriteH Core)+ [ "give a side-effect message as output when processing this command" ]+ , external "observe" (observeR :: String -> RewriteH Core)+ [ "give a side-effect message as output, and observe the value being processed" ]+ , external "observe-failure" (observeFailureR :: String -> RewriteH Core -> RewriteH Core)+ [ "give a side-effect message if the rewrite fails, including the failing input" ]+ , external "bracket" (bracketR :: String -> RewriteH Core -> RewriteH Core)+ [ "if given rewrite succeeds, see its input and output" ]+ ] -- | If the 'Rewrite' fails, print out the 'Core', with a message.-observeFailureR :: Injection a CoreTC => String -> RewriteH a -> RewriteH a+observeFailureR :: (Injection a CoreTC, 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 => String -> RewriteH a-observeR msg = extractR $ sideEffectR $ \ cxt core ->- sendDebugMessage $ DebugCore msg cxt core+observeR :: (Injection a CoreTC, ReadBindings c, ReadPath c Crumb, HasDebugChan m, Monad m)+ => String -> Rewrite c m a+observeR msg = extractR $ sideEffectR $ \ cxt -> sendDebugMessage . DebugCore msg cxt -- | Just say something, every time the rewrite is done.-traceR :: String -> RewriteH a+traceR :: (HasDebugChan m, Monad m) => String -> Rewrite c m a traceR msg = sideEffectR $ \ _ _ -> sendDebugMessage $ DebugTick msg -- | Show before and after a rewrite.-bracketR :: Injection a CoreTC => String -> RewriteH a -> RewriteH a+bracketR :: (Injection a CoreTC, 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. (e,r) <- idR &&& attemptM rr
src/HERMIT/Dictionary/FixPoint.hs view
@@ -1,25 +1,25 @@-{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE FlexibleContexts, ScopedTypeVariables #-} module HERMIT.Dictionary.FixPoint- ( -- * Operations on the Fixed Point Operator (fix)- -- | Note that many of these operations require 'Data.Function.fix' to be explicitly imported, if it is not used in the source file.- HERMIT.Dictionary.FixPoint.externals- -- ** Rewrites and BiRewrites on Fixed Points- , fixIntroR- , fixComputationRuleBR- , fixRollingRuleBR- , fixFusionRuleBR- -- ** Utilities- , mkFixT- , isFixExprT- )-where+ ( -- * Operations on the Fixed Point Operator (fix)+ HERMIT.Dictionary.FixPoint.externals+ -- ** Rewrites and BiRewrites on Fixed Points+ , fixIntroR+ , fixIntroNonRecR+ , fixIntroRecR+ , fixComputationRuleBR+ , fixRollingRuleBR+ , fixFusionRuleBR+ -- ** Utilities+ , isFixExprT+ ) where import Control.Applicative import Control.Arrow+import Control.Monad import Control.Monad.IO.Class -import Data.Monoid (mempty)+import Data.String (fromString) import HERMIT.Context import HERMIT.Core@@ -27,60 +27,100 @@ import HERMIT.Kure import HERMIT.External import HERMIT.GHC+import HERMIT.Name import HERMIT.ParserCore import HERMIT.Utilities import HERMIT.Dictionary.Common-import HERMIT.Dictionary.GHC+import HERMIT.Dictionary.Function+import HERMIT.Dictionary.Kure import HERMIT.Dictionary.Reasoning import HERMIT.Dictionary.Undefined+import HERMIT.Dictionary.Unfold -------------------------------------------------------------------------------------------------- -- | Externals for manipulating fixed points. externals :: [External] externals =- [ external "fix-intro" (promoteDefR fixIntroR :: RewriteH Core)- [ "rewrite a recursive binding into a non-recursive binding using fix"- ] .+ Introduce .+ Context- , external "fix-computation-rule" (promoteExprBiR fixComputationRuleBR :: BiRewriteH Core)- [ "Fixed-Point Computation Rule",- "fix t f <==> f (fix t f)"- ] .+ Context- , external "fix-rolling-rule" (promoteExprBiR fixRollingRuleBR :: BiRewriteH Core)- [ "Rolling Rule",- "fix tyA (\\ a -> f (g a)) <==> f (fix tyB (\\ b -> g (f b))"- ] .+ Context- , external "fix-fusion-rule" ((\ f g h lhsR rhsR strictf -> promoteExprBiR (fixFusionRule (Just (lhsR,rhsR)) (Just strictf) f g h)) :: CoreString -> CoreString -> CoreString -> RewriteH Core -> RewriteH Core -> RewriteH Core -> BiRewriteH Core)- [ "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"- , "f (fix g) <==> fix h"- ] .+ Context- , external "fix-fusion-rule-unsafe" ((\ f g h lhsR rhsR -> promoteExprBiR (fixFusionRule (Just (lhsR,rhsR)) Nothing f g h)) :: CoreString -> CoreString -> CoreString -> RewriteH Core -> RewriteH Core -> BiRewriteH Core)- [ "(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"- , "f (fix g) <==> fix h"- , "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)- [ "(Very Unsafe) Fixed-point Fusion Rule"- , "Given f :: A -> B, g :: A -> A, h :: B -> B, then"- , "f (fix g) <==> fix h"- , "Note that the preconditions that f (g a) == h (f a) and that f is strict are required to hold."- ] .+ Context .+ PreCondition- ]+ [ external "fix-intro" (fixIntroR :: RewriteH Core)+ [ "rewrite a function binding into a non-recursive binding using fix" ] .+ Introduce .+ Context+ , external "fix-computation-rule" (promoteExprBiR fixComputationRuleBR :: BiRewriteH Core)+ [ "Fixed-Point Computation Rule",+ "fix t f <==> f (fix t f)"+ ] .+ Context+ , external "fix-rolling-rule" (promoteExprBiR fixRollingRuleBR :: BiRewriteH Core)+ [ "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)+ [ "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"+ , "f (fix g) <==> fix h"+ ] .+ 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)+ [ "(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"+ , "f (fix g) <==> fix h"+ , "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)+ [ "(Very Unsafe) Fixed-point Fusion Rule"+ , "Given f :: A -> B, g :: A -> A, h :: B -> B, then"+ , "f (fix g) <==> fix h"+ , "Note that the preconditions that f (g a) == h (f a) and that f is strict are required to hold."+ ] .+ Context .+ PreCondition+ ] -------------------------------------------------------------------------------------------------- +fixIntroR :: ( AddBindings c, BoundVars c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb+ , HasHermitMEnv m, HasHscEnv m, MonadCatch m, MonadIO m, MonadThings m, MonadUnique m )+ => Rewrite c m Core+fixIntroR = promoteR fixIntroRecR <+ promoteR fixIntroNonRecR++fixIntroNonRecR :: ( AddBindings c, BoundVars c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb+ , HasHermitMEnv m, HasHscEnv m, MonadCatch m, MonadIO m, MonadThings m, MonadUnique m )+ => Rewrite c m CoreBind+fixIntroNonRecR = prefixFailMsg "fix introduction failed: " $ do+ NonRec f rhs <- idR+ rhs' <- polyFixT f <<< return rhs+ return $ NonRec f rhs'+ -- | @f = e@ ==\> @f = fix (\\ f -> e)@-fixIntroR :: RewriteH CoreDef-fixIntroR = prefixFailMsg "fix introduction failed: " $- do Def f _ <- idR- f' <- constT $ cloneVarH id f- Def f <$> (mkFixT =<< (defT mempty (extractR $ substR f $ varToCoreExpr f') (\ () e' -> Lam f' e')))+fixIntroRecR :: ( AddBindings c, BoundVars c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb+ , HasHermitMEnv m, HasHscEnv m, MonadCatch m, MonadIO m, MonadThings m, MonadUnique m )+ => Rewrite c m CoreDef+fixIntroRecR = prefixFailMsg "fix introduction failed: " $ do+ Def f rhs <- idR+ rhs' <- polyFixT f <<< return rhs+ return $ Def f rhs' +-- | Helper for fixIntroNonRecR and fixIntroRecR. Argument is function name.+-- Meant to be applied to RHS of function.+polyFixT :: forall c m.+ ( AddBindings c, BoundVars c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb+ , HasHermitMEnv m, HasHscEnv m, MonadCatch m, MonadIO m, MonadThings m, MonadUnique m )+ => Id -> Rewrite c m CoreExpr+polyFixT f = do+ (tvs, body) <- arr collectTyBinders+ f' <- constT $ newIdH (unqualifiedName f) (exprType body)+ body' <- contextonlyT $ \ c -> do+ let constLam = mkCoreLams tvs $ varToCoreExpr f'+ c' = addBindingGroup (NonRec f constLam) -- we want to unfold f such as to throw away TyArgs+ $ addBindingGroup (NonRec f' body) c -- add f' to context so its in-scope after unfolding+ applyT (tryR (extractR (anyCallR (promoteR (unfoldPredR (const . (==f))) :: Rewrite c m Core)))) c' body+ liftM (mkCoreLams tvs) $ buildFixT $ Lam f' body'+ -------------------------------------------------------------------------------------------------- -- | @fix ty f@ \<==\> @f (fix ty f)@@@ -129,7 +169,7 @@ rollingRuleResult :: Type -> CoreExpr -> CoreExpr -> TransformH z CoreExpr rollingRuleResult ty f g = do x <- constT (newIdH "x" ty)- mkFixT (Lam x (App f (App g (Var x))))+ buildFixT (Lam x (App f (App g (Var x)))) wrongFixBody :: String wrongFixBody = "body of fix does not have the form: Lam v (App f (App g (Var v)))"@@ -141,12 +181,12 @@ -- h :: B -> B -- | If @f@ is strict, then (@f (g a)@ == @h (f a)@) ==\> (@f (fix g)@ == @fix h@)-fixFusionRuleBR :: Maybe (CoreExprEqualityProof HermitC HermitM) -> Maybe (RewriteH CoreExpr) -> CoreExpr -> CoreExpr -> CoreExpr -> BiRewriteH CoreExpr+fixFusionRuleBR :: Maybe (EqualityProof HermitC HermitM) -> Maybe (RewriteH CoreExpr) -> CoreExpr -> CoreExpr -> CoreExpr -> BiRewriteH CoreExpr fixFusionRuleBR meq mfstrict f g h = beforeBiR (prefixFailMsg "fixed-point fusion failed: " $- do (tyA,tyB) <- funExprArgResTypes f- tyA' <- endoFunExprType g- tyB' <- endoFunExprType h+ do (_,tyA,tyB) <- funExprArgResTypesM f -- TODO: don't throw away TyVars+ (_,tyA') <- endoFunExprTypeM g+ (_,tyB') <- endoFunExprTypeM h guardMsg (typeAlphaEq tyA tyA' && typeAlphaEq tyB tyB') "given functions do not have compatible types." whenJust (verifyStrictT f) mfstrict whenJust (\ eq ->@@ -167,13 +207,13 @@ guardMsg (exprAlphaEq f f') "first argument function does not match." (_,g') <- isFixExprT <<< return fixg guardMsg (exprAlphaEq g g') "second argument function does not match."- mkFixT h+ buildFixT h fixFusionR :: RewriteH CoreExpr fixFusionR = prefixFailMsg "(reversed) fixed-point fusion failed: " $ do (_,h') <- isFixExprT guardMsg (exprAlphaEq h h') "third argument function does not match."- App f <$> mkFixT g+ 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@@ -184,24 +224,14 @@ -- | Check that the expression has the form "fix t (f :: t -> t)", returning "t" and "f". isFixExprT :: TransformH CoreExpr (Type,CoreExpr) isFixExprT = withPatFailMsg (wrongExprForm "fix t f") $ -- fix :: forall a. (a -> a) -> a- do App (App (Var fixId) (Type ty)) f <- idR- fixId' <- findFixId- guardMsg (fixId == fixId') (var2String fixId ++ " does not match " ++ fixLocation)+ do (Var fixId, [Type ty, f]) <- callT+ fixId' <- findIdT fixLocation+ guardMsg (fixId == fixId') (unqualifiedName fixId ++ " does not match " ++ show fixLocation) return (ty,f) -------------------------------------------------------------------------------------------------- --- | f ==> fix f-mkFixT :: (BoundVars c, MonadCatch m, HasModGuts m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => CoreExpr -> Transform c m z CoreExpr-mkFixT f = do t <- endoFunExprType f- fixId <- findFixId- return $ mkCoreApps (varToCoreExpr fixId) [Type t, f]--fixLocation :: String-fixLocation = "Data.Function.fix"---- TODO: will crash if 'fix' is not used (or explicitly imported) in the source file.-findFixId :: (BoundVars c, MonadCatch m, HasModGuts m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Transform c m a Id-findFixId = findIdT fixLocation+fixLocation :: HermitName+fixLocation = fromString "Data.Function.fix" --------------------------------------------------------------------------------------------------
src/HERMIT/Dictionary/Fold.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE TypeFamilies #-} module HERMIT.Dictionary.Fold ( -- * Fold/Unfold Transformation externals@@ -7,24 +8,24 @@ , stashFoldAnyR -- * Unlifted fold interface , fold- , unifyTypes+ , unifyTypes -- TODO: remove in favor of GHC's unification , tyMatchesToCoreExpr- )--where+ ) where import Control.Arrow import Control.Applicative import Control.Monad+import Control.Monad.IO.Class import qualified Data.Map as Map import HERMIT.Core import HERMIT.Context-import HERMIT.Monad-import HERMIT.Kure import HERMIT.External import HERMIT.GHC+import HERMIT.Kure+import HERMIT.Monad+import HERMIT.Name import HERMIT.Dictionary.Common (varBindingDepthT,inScope,findIdT) import HERMIT.Dictionary.Inline hiding (externals)@@ -35,7 +36,7 @@ externals :: [External] externals =- [ external "fold" (promoteExprR . foldR :: String -> RewriteH Core)+ [ external "fold" (promoteExprR . foldR :: HermitName -> RewriteH Core) [ "fold a definition" , "" , "double :: Int -> Int"@@ -47,7 +48,7 @@ , "" , "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 :: Label -> RewriteH Core)+ , 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@@ -55,26 +56,25 @@ ------------------------------------------------------------------------ -stashFoldR :: ReadBindings c => Label -> Rewrite c HermitM CoreExpr+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) $ var2String 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.)"+ 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 => Rewrite c HermitM CoreExpr+stashFoldAnyR :: (ReadBindings c, HasStash m, MonadCatch m) => Rewrite c m CoreExpr stashFoldAnyR = setFailMsg "Fold failed: no definitions could be folded." $- catchesM =<< map stashFoldR <$> (Map.keys <$> constT getStash)+ catchesM =<< liftM (map stashFoldR) (liftM Map.keys (constT getStash)) -foldR :: ReadBindings c => String -> Rewrite c HermitM CoreExpr-foldR nm = prefixFailMsg "Fold failed: " $ do- v <- findIdT nm- foldVarR v Nothing+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 => Var -> Maybe BindingDepth -> Rewrite c HermitM CoreExpr-foldVarR v md = do+foldVarR :: (ReadBindings c, MonadCatch m, MonadUnique m) => Maybe BindingDepth -> Var -> Rewrite c m CoreExpr+foldVarR md v = do case md of Nothing -> return () Just depth -> do depth' <- varBindingDepthT v@@ -148,7 +148,7 @@ 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 + | 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@@ -190,7 +190,7 @@ return (x ++ tyMatchesToCoreExpr t ++ concat y) foldMatch vs as (Cast e c) (Cast e' c') = do- guard (coreEqCoercion c c') + guard (coreEqCoercion c c') foldMatch vs as e e' foldMatch vs as (Type t1) (Type t2) = liftM tyMatchesToCoreExpr $ foldMatchType vs as t1 t2@@ -221,6 +221,10 @@ -> Type -- ^ expression we are checking -> Maybe [(TyVar,Type)] -- ^ mapping of vars to types, or failure +-- 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'+ 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)]@@ -237,7 +241,7 @@ let f ty1 ty2 | isKind ty1 && eqKind ty1 ty2 = return [] | otherwise = foldMatchType vs as ty1 ty2 liftM concat $ zipWithM f kOrTys1 kOrTys2- + foldMatchType vs as (FunTy ty1 ty2) (FunTy ty1' ty2') = do x <- foldMatchType vs as ty1 ty1' y <- foldMatchType vs as ty2 ty2'
src/HERMIT/Dictionary/Function.hs view
@@ -1,25 +1,34 @@-{-# LANGUAGE FlexibleContexts, RankNTypes #-}+{-# LANGUAGE CPP, FlexibleContexts, RankNTypes, ScopedTypeVariables #-} module HERMIT.Dictionary.Function ( externals+ , appArgM+ , buildApplicationM+ , buildCompositionT+ , buildFixT+ , buildIdT , staticArgR , staticArgPosR , staticArgPredR , staticArgTypesR- )-where+ ) where import Control.Arrow+import Control.Monad.IO.Class import Data.List (nub, intercalate, intersect, partition, transpose)+import Data.Maybe (isNothing)+import Data.String (fromString) import HERMIT.Context import HERMIT.Core-import HERMIT.Monad-import HERMIT.Kure import HERMIT.External import HERMIT.GHC+import HERMIT.Kure+import HERMIT.Monad+import HERMIT.Name import HERMIT.Dictionary.Common+import HERMIT.Dictionary.GHC hiding (externals) externals :: [External] externals =@@ -34,15 +43,18 @@ ------------------------------------------------------------------------------------------------------ -- | Traditional Static Argument Transformation-staticArgR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, HasEmptyContext c) => Rewrite c HermitM CoreDef+staticArgR :: (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadPath c Crumb, MonadCatch m, MonadUnique m)+ => Rewrite c m CoreDef staticArgR = staticArgPredR (return . map fst) -- | Static Argument Transformation that only considers type arguments to be static.-staticArgTypesR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, HasEmptyContext c) => Rewrite c HermitM CoreDef+staticArgTypesR :: (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadPath c Crumb, MonadCatch m, MonadUnique m)+ => Rewrite c m CoreDef staticArgTypesR = staticArgPredR (return . map fst . filter (isTyVar . snd)) -- | Static Argument Transformations which requires that arguments in the given position are static.-staticArgPosR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, HasEmptyContext c) => [Int] -> Rewrite c HermitM CoreDef+staticArgPosR :: (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadPath c Crumb, MonadCatch m, MonadUnique m)+ => [Int] -> Rewrite c m CoreDef staticArgPosR is' = staticArgPredR $ \ss' -> let is = nub is' ss = map fst ss' in if is == (is `intersect` ss)@@ -50,9 +62,10 @@ else fail $ "args " ++ commas (filter (`notElem` ss) is) ++ " are not static." -- | Generalized Static Argument Transformation, which allows static arguments to be filtered.-staticArgPredR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, HasEmptyContext c)- => ([(Int, Var)] -> HermitM [Int]) -- ^ given list of static args and positions, decided which to transform- -> Rewrite c HermitM CoreDef+staticArgPredR :: forall c m. (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadPath c Crumb+ , MonadCatch m, MonadUnique m)+ => ([(Int, Var)] -> m [Int]) -- ^ given list of static args and positions, decided which to transform+ -> Rewrite c m CoreDef staticArgPredR decide = prefixFailMsg "static-arg failed: " $ do Def f rhs <- idR let (bnds, body) = collectBinders rhs@@ -60,9 +73,11 @@ contextonlyT $ \ c -> do let bodyContext = foldl (flip addLambdaBinding) c bnds - -- TODO: we convert an Id to string here, and callsT then uses cmpString2Var- -- refactor to avoid intermediate string!- callPats <- apply (callsT (var2String f) (callT >>> arr snd)) bodyContext (ExprCore body)+ callPatsT :: Transform c m CoreExpr [[CoreExpr]]+ callPatsT = extractT $ collectPruneT+ (promoteExprT $ callPredT (const . (== f)) >>> arr snd :: Transform c m Core [CoreExpr])++ callPats <- applyT callPatsT bodyContext body let argExprs = transpose callPats numCalls = length callPats allBinds = zip [0..] bnds@@ -92,17 +107,91 @@ $ "type variables in args " ++ commas (nub $ map fst unboundTys) ++ " would become unbound unless args " ++ commas (nub $ map snd unboundTys) ++ " are included in the transformation." - wkr <- newIdH (var2String f ++ "'") (exprType (mkCoreLams dbnds body))+ wkr <- newIdH (unqualifiedName f ++ "'") (exprType (mkCoreLams dbnds body)) let replaceCall :: Monad m => Rewrite c m CoreExpr replaceCall = do- (_,exprs) <- callT+ (_,exprs) <- callPredT (const . (== f)) return $ mkApps (Var wkr) [ e | (p,e) <- zip [0..] exprs, (p::Int) `elem` ps ] - ExprCore body' <- apply (callsR (var2String f) replaceCall) bodyContext (ExprCore body)+ body' <- applyT (extractR $ prunetdR (promoteExprR replaceCall :: Rewrite c m Core)) bodyContext body return $ Def f $ mkCoreLams bnds $ Let (Rec [(wkr, mkCoreLams dbnds body')]) $ mkApps (Var wkr) (varsToCoreExprs dbnds) +------------------------------------------------------------------------------++-- | Get the nth argument of an application. Arg 0 is the function being applied.+appArgM :: Monad m => Int -> CoreExpr -> m CoreExpr+appArgM n e | n < 0 = fail "appArgM: arg must be non-negative"+ | otherwise = let (fn,args) = collectArgs e+ l = fn : args+ in if n > length args+ then fail "appArgM: not enough arguments"+ else return $ l !! n++-- | Build composition of two functions.+buildCompositionT :: (BoundVars c, HasDynFlags m, 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++-- | 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+ (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")+ return+ (tcUnifyTys bindFn [domF] [xTy])++ f' <- substOrApply f [ (v, Type $ substTyVar sub v) | v <- vsF ]+ x' <- substOrApply x [ (v, Type $ substTyVar sub v) | v <- vsX ]+ let vs = [ v | v <- vsF ++ vsX, isNothing $ lookupTyVar sub v ] -- things we should stick back on as foralls+ -- TODO: make sure vsX don't capture anything in f'+ -- and vsF' doesn't capture anything in x'+ return $ mkCoreLams vs $ mkCoreApp f' x'++-- | Given expression for f, build fix f.+buildFixT :: (BoundVars c, HasHscEnv m, HasHermitMEnv m, MonadCatch m, MonadIO m, MonadThings m)+ => CoreExpr -> Transform c m x CoreExpr+buildFixT f = do+ (tvs, ty) <- endoFunExprTypeM f+ fixId <- findIdT $ fromString "Data.Function.fix"+ f' <- substOrApply f [ (v, varToCoreExpr v) | v <- tvs ]+ return $ mkCoreLams tvs $ mkCoreApps (varToCoreExpr fixId) [Type ty, f']++-- | Build an expression that is the monomorphic id function for given type.+buildIdT :: (BoundVars c, HasHscEnv m, HasHermitMEnv m, MonadCatch m, MonadIO m, MonadThings m)+ => Type -> Transform c m x CoreExpr+buildIdT ty = do+ idId <- findIdT $ fromString "Data.Function.id"+ return $ mkCoreApp (varToCoreExpr idId) (Type ty)++------------------------------------------------------------------------------+ commas :: Show a => [a] -> String commas = intercalate "," . map show++-- | Like mkCoreApps, but automatically beta-reduces when possible.+substOrApply :: Monad m => CoreExpr -> [(Var,CoreExpr)] -> m CoreExpr+substOrApply e [] = return e+substOrApply (Lam b e) ((v,ty):r) = if b == v+ then substOrApply e r >>= return . substCoreExpr b ty+ else fail $ "substOrApply: unexpected binder - "+ ++ unqualifiedName b ++ " - " ++ unqualifiedName v+substOrApply e rest = return $ mkCoreApps e (map snd rest)++------------------------------------------------------------------------------
src/HERMIT/Dictionary/GHC.hs view
@@ -1,42 +1,47 @@ {-# 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- , substR- , substCoreAlt- , substCoreExpr- -- ** Utilities- -- , inScope- , dynFlagsT- , arityOf- -- ** Lifted GHC capabilities- -- A zombie is an identifer that has 'OccInfo' 'IAmDead', but still has occurrences.- , lintExprT- , lintModuleT- , occurAnalyseR- , occurAnalyseChangedR- , occurAnalyseExprChangedR- , occurAnalyseAndDezombifyR- , dezombifyR- )-where+ ( -- * GHC-based Transformations+ -- | This module contains transformations that are reflections of GHC functions, or derived from GHC functions.+ externals+ -- ** Substitution+ , substR+ , substCoreAlt+ , substCoreExpr+ -- ** Utilities+ -- , inScope+ , dynFlagsT+ , arityOf+ -- ** Lifted GHC capabilities+ -- A zombie is an identifer that has 'OccInfo' 'IAmDead', but still has occurrences.+ , lintExprT+ , lintModuleT+ , occurAnalyseR+ , occurAnalyseChangedR+ , occurAnalyseExprChangedR+ , occurAnalyseAndDezombifyR+ , dezombifyR+ , buildDictionary+ , buildDictionaryT+ , buildTypeable+ ) where import qualified Bag import qualified CoreLint -import Control.Arrow--import Data.List (mapAccumL)+import Control.Arrow+import Control.Monad.IO.Class -import HERMIT.Core-import HERMIT.Context-import HERMIT.Kure-import HERMIT.External-import HERMIT.GHC+import Data.Char (isSpace)+import Data.List (mapAccumL) -import HERMIT.Dictionary.Debug hiding (externals)+import HERMIT.Core+import HERMIT.Context+import HERMIT.Dictionary.Debug hiding (externals)+import HERMIT.External+import HERMIT.GHC+import HERMIT.Kure+import HERMIT.Monad+import HERMIT.Name ------------------------------------------------------------------------ @@ -125,11 +130,7 @@ lintModuleT = do dynFlags <- dynFlagsT bnds <- arr mg_binds-#if __GLASGOW_HASKELL__ > 706 let (warns, errs) = CoreLint.lintCoreBindings [] bnds -- [] are vars to treat as in scope, used by GHCi-#else- let (warns, errs) = CoreLint.lintCoreBindings bnds-#endif dumpSDocs endMsg = Bag.foldBag (\ d r -> d ++ ('\n':r)) (showSDoc dynFlags) endMsg if Bag.isEmptyBag errs then return $ dumpSDocs "Core Lint Passed" warns@@ -143,11 +144,7 @@ lintExprT = transform $ \ c e -> do dflags <- getDynFlags maybe (return "Core Lint Passed") (fail . showSDoc dflags)-#if __GLASGOW_HASKELL__ > 706 $ CoreLint.lintExpr (varSetElems $ boundVars c) e-#else- $ CoreLint.lintUnfolding noSrcLoc (varSetElems $ boundVars c) e-#endif ------------------------------------------- @@ -168,13 +165,23 @@ -- | Apply 'occurAnalyseExprR' to all sub-expressions. occurAnalyseR :: (AddBindings c, ExtendPath c Crumb, ReadPath c Crumb, HasEmptyContext c, MonadCatch m) => Rewrite c m Core-occurAnalyseR = let r = promoteExprR (arr occurAnalyseExpr)+occurAnalyseR = let r = promoteExprR (arr occurAnalyseExpr_NoBinderSwap) -- See Note [No Binder Swap] go = r <+ anyR go in tryR go -- always succeed +{-+ Note [No Binder Swap]++ The binder swap performed by occurrence analysis in GHC <= 7.8.3 is buggy+ in that it can lead to unintended variable capture (Trac #9440). Concretely,+ this will send bash into a loop, or cause core lint to fail. As this is an+ un-expected change as far as HERMIT users are concerned anyway, we use the+ version that doesn't perform the binder swap.+-}+ -- | Occurrence analyse an expression, failing if the result is syntactically equal to the initial expression. occurAnalyseExprChangedR :: MonadCatch m => Rewrite c m CoreExpr-occurAnalyseExprChangedR = changedByR exprSyntaxEq (arr occurAnalyseExpr)+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@@ -198,3 +205,37 @@ -} ----------------------------------------------------------------------++-- TODO: this is mostly an example, move somewhere?+buildTypeable :: (HasDynFlags m, HasHermitMEnv m, HasHscEnv m, MonadIO m) => Type -> m (Id, [CoreBind])+buildTypeable ty = do+ evar <- runTcM $ do+ cls <- tcLookupClass typeableClassName+ let predTy = mkClassPred cls [typeKind ty, ty] -- recall that Typeable is now poly-kinded+ newWantedEvVar predTy+ buildDictionary evar++-- | Build a dictionary for the given+buildDictionary :: (HasDynFlags m, HasHermitMEnv m, HasHscEnv m, MonadIO m) => Id -> m (Id, [CoreBind])+buildDictionary evar = do+ (i, bs) <- runTcM $ do+ loc <- getCtLoc $ GivenOrigin UnkSkol+ let predTy = varType evar+ nonC = mkNonCanonical $ CtWanted { ctev_pred = predTy, ctev_evar = evar, ctev_loc = loc }+ wCs = mkFlatWC [nonC]+ (wCs', bnds) <- solveWantedsTcM wCs+ reportAllUnsolved wCs'+ return (evar, bnds)+ bnds <- runDsM $ dsEvBinds bs+ return (i,bnds)++buildDictionaryT :: (HasDynFlags m, HasHermitMEnv m, HasHscEnv m, MonadCatch m, MonadIO m, MonadUnique m)+ => Transform c m Type CoreExpr+buildDictionaryT = prefixFailMsg "buildDictionaryT failed: " $ contextfreeT $ \ ty -> do+ dflags <- getDynFlags+ binder <- newIdH ("$d" ++ zEncodeString (filter (not . isSpace) (showPpr dflags ty))) ty+ (i,bnds) <- buildDictionary binder+ guardMsg (notNull bnds) "no dictionary bindings generated."+ 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)
src/HERMIT/Dictionary/Induction.hs view
@@ -17,6 +17,7 @@ import HERMIT.GHC import HERMIT.Kure import HERMIT.Monad+import HERMIT.Name -- import HERMIT.Utilities (soleElement) import HERMIT.Dictionary.Common@@ -30,7 +31,7 @@ ------------------------------------------------------------------------------ -inductionCaseSplit :: (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb) +inductionCaseSplit :: (AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb) => [Var] -> Id -> CoreExpr -> CoreExpr -> Transform c HermitM x [(Maybe DataCon,[Var],CoreExpr,CoreExpr)] inductionCaseSplit vs i lhsE rhsE = do -- first construct an expression containing both the LHS and the RHS
src/HERMIT/Dictionary/Inline.hs view
@@ -1,40 +1,30 @@ {-# LANGUAGE CPP, TupleSections, FlexibleContexts, ScopedTypeVariables #-} module HERMIT.Dictionary.Inline- ( -- * Inlining- externals- , InlineConfig(..)- , CaseBinderInlineOption(..)- , getUnfoldingT- , ensureBoundT- , inlineR- , inlineNameR- , inlineNamesR- , inlineMatchingPredR- , inlineCaseScrutineeR- , inlineCaseAlternativeR- , configurableInlineR- , inlineTargetsT- )--where--#if __GLASGOW_HASKELL__ > 706-#else-import TcType (tcSplitDFunTy)-#endif+ ( -- * Inlining+ externals+ , InlineConfig(..)+ , CaseBinderInlineOption(..)+ , getUnfoldingT+ , ensureBoundT+ , inlineR+ , inlineNameR+ , inlineNamesR+ , inlineMatchingPredR+ , inlineCaseScrutineeR+ , inlineCaseAlternativeR+ , configurableInlineR+ , inlineTargetsT+ ) where import Control.Arrow-import Control.Applicative import Control.Monad -import Data.List (intercalate)- import HERMIT.Context import HERMIT.Core import HERMIT.External import HERMIT.GHC import HERMIT.Kure-import HERMIT.Monad+import HERMIT.Name import HERMIT.Dictionary.Common @@ -43,17 +33,17 @@ -- | 'External's for inlining variables. externals :: [External] externals =- [ external "inline" (promoteExprR inlineR :: RewriteH Core)- [ "(Var v) ==> <defn of v>" ].+ Eval .+ Deep- , external "inline" (promoteExprR . inlineNameR :: String -> RewriteH Core)- [ "Given a specific v, (Var v) ==> <defn of v>" ] .+ Eval .+ Deep- , external "inline" (promoteExprR . inlineNamesR :: [String] -> RewriteH Core)- [ "If the current variable matches any of the given names, then inline it." ] .+ Eval .+ Deep- , external "inline-case-scrutinee" (promoteExprR inlineCaseScrutineeR :: RewriteH Core)- [ "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" (promoteExprR inlineR :: RewriteH Core)+ [ "(Var v) ==> <defn of v>" ].+ Eval .+ Deep+ , external "inline" (promoteExprR . inlineMatchingPredR . mkOccPred :: OccurrenceName -> RewriteH Core)+ [ "Given a specific v, (Var v) ==> <defn of v>" ] .+ Eval .+ Deep+ , external "inline" (promoteExprR . inlineNamesR :: [String] -> RewriteH Core)+ [ "If the current variable matches any of the given names, then inline it." ] .+ Eval .+ Deep+ , external "inline-case-scrutinee" (promoteExprR inlineCaseScrutineeR :: RewriteH Core)+ [ "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+ ] ------------------------------------------------------------------------ @@ -62,37 +52,50 @@ data InlineConfig = CaseBinderOnly CaseBinderInlineOption | AllBinders deriving (Eq, Show) -- | If the current variable matches the given name, then inline it.-inlineNameR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => String -> Rewrite c HermitM CoreExpr+inlineNameR :: ( ExtendPath c Crumb, ReadPath c Crumb, AddBindings c+ , ReadBindings c, HasEmptyContext c, MonadCatch m )+ => String -> Rewrite c m CoreExpr inlineNameR nm = inlineMatchingPredR (cmpString2Var nm) -- | If the current variable matches any of the given names, then inline it.-inlineNamesR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => [String] -> Rewrite c HermitM CoreExpr+inlineNamesR :: ( ExtendPath c Crumb, ReadPath c Crumb, AddBindings c+ , ReadBindings c, HasEmptyContext c, MonadCatch m )+ => [String] -> Rewrite c m CoreExpr inlineNamesR [] = fail "inline-names failed: no names given." inlineNamesR nms = inlineMatchingPredR (\ v -> any (flip cmpString2Var v) nms) -- | If the current variable satisifies the predicate, then inline it.-inlineMatchingPredR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => (Id -> Bool) -> Rewrite c HermitM CoreExpr+inlineMatchingPredR :: ( ExtendPath c Crumb, ReadPath c Crumb, AddBindings c+ , ReadBindings c, HasEmptyContext c, MonadCatch m )+ => (Id -> Bool) -> Rewrite c m CoreExpr inlineMatchingPredR idPred = configurableInlineR AllBinders (arr $ idPred) -- | Inline the current variable.-inlineR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => Rewrite c HermitM CoreExpr+inlineR :: (AddBindings c, ExtendPath c Crumb, HasEmptyContext c,+ ReadBindings c, ReadPath c Crumb, MonadCatch m )+ => Rewrite c m CoreExpr inlineR = configurableInlineR AllBinders (return True) -- | Inline the current identifier if it is a case binder, using the scrutinee rather than the case-alternative pattern.-inlineCaseScrutineeR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => Rewrite c HermitM CoreExpr+inlineCaseScrutineeR :: ( ExtendPath c Crumb, ReadPath c Crumb, AddBindings c+ , ReadBindings c, HasEmptyContext c, MonadCatch m )+ => Rewrite c m CoreExpr inlineCaseScrutineeR = configurableInlineR (CaseBinderOnly Scrutinee) (return True) -- | Inline the current identifier if is a case binder, using the case-alternative pattern rather than the scrutinee.-inlineCaseAlternativeR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => Rewrite c HermitM CoreExpr+inlineCaseAlternativeR :: ( ExtendPath c Crumb, ReadPath c Crumb, AddBindings c+ , ReadBindings c, HasEmptyContext c, MonadCatch m )+ => Rewrite c m CoreExpr inlineCaseAlternativeR = configurableInlineR (CaseBinderOnly Alternative) (return True) -- | The implementation of inline, an important transformation. -- This *only* works if the current expression has the form @Var v@ (it does not traverse the expression). -- It can trivially be prompted to more general cases using traversal strategies.-configurableInlineR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c)+configurableInlineR :: ( AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c+ , ReadPath c Crumb, MonadCatch m ) => InlineConfig- -> (Transform c HermitM Id Bool) -- ^ Only inline identifiers that satisfy this predicate.- -> Rewrite c HermitM CoreExpr+ -> (Transform c m Id Bool) -- ^ Only inline identifiers that satisfy this predicate.+ -> Rewrite c m CoreExpr configurableInlineR config p = prefixFailMsg "Inline failed: " $ do b <- varT p@@ -106,8 +109,8 @@ -- Fails, listing unbound variables if not. ensureBoundT :: (Monad m, ReadBindings c) => Transform c m CoreExpr () ensureBoundT = do- unbound <- transform $ \ c -> return . filter (not . inScope c) . varSetElems . localFreeVarsExpr- guardMsg (null unbound) $ "the following variables are unbound: " ++ intercalate ", " (map getOccString unbound)+ unbound <- transform $ \ c -> return . filterVarSet (not . inScope c) . localFreeVarsExpr+ guardMsg (isEmptyVarSet unbound) $ "the following variables are unbound: " ++ showVarSet unbound -- NOTE: When inlining, we have to take care to avoid variable capture. -- Our approach is to track the binding depth of the inlined identifier.@@ -136,29 +139,25 @@ all uncaptured `liftM` extractT collectDepthsT -- | Return the unfolding of an identifier, and a predicate over the binding depths of all variables within that unfolding to determine if they have been captured in their new location.-getUnfoldingT :: ReadBindings c+getUnfoldingT :: (ReadBindings c, MonadCatch m) => InlineConfig- -> Transform c HermitM Id (CoreExpr, BindingDepth -> Bool)+ -> Transform c m Id (CoreExpr, BindingDepth -> Bool) getUnfoldingT config = transform $ \ c i -> case lookupHermitBinding i c of Nothing -> do requireAllBinders config let uncaptured = (<= 0) -- i.e. is global- -- this check is necessary because idInfo panics on TyVars, though it- -- should never be the case that a type variable is NOT in the context,- -- at least this will give a reasonable error message, instead of a GHC panic.- guardMsg (isId i) "type variable is not in Env (this should not happen)."+ -- This check is necessary because idInfo panics on TyVars. Type variables should+ -- ALWAYS be in the context (so we should never be in this branch), but at least this+ -- 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)-#if __GLASGOW_HASKELL__ > 706- dunf@(DFunUnfolding {}) -> (,uncaptured) <$> dFunExpr dunf-#else- DFunUnfolding _arity dc args -> (,uncaptured) <$> dFunExpr dc args (idType i)-#endif+ dunf@(DFunUnfolding {}) -> liftM (,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 = (, (<= depth+1)) <$> alt2Exp tys alt+ altExprDepthM = liftM (, (<= depth+1)) $ alt2Exp tys alt scrutExprDepthM = return (s, (< depth)) in case config of CaseBinderOnly Scrutinee -> scrutExprDepthM@@ -200,44 +199,14 @@ alt2Exp tys (DataAlt dc, vs) = return $ mkCoreConApps dc (map Type tys ++ map (varToCoreExpr . zapVarOccInfo) 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) => Transform c HermitM Core [String]-inlineTargetsT = collectT $ promoteT $ whenM (testM inlineR) (varT $ arr var2String)+inlineTargetsT :: ( ExtendPath c Crumb, ReadPath c Crumb, AddBindings c+ , ReadBindings c, HasEmptyContext c, MonadCatch m )+ => Transform c m Core [String]+inlineTargetsT = collectT $ promoteT $ whenM (testM inlineR) (varT $ arr unqualifiedName) -- | Build a CoreExpr for a DFunUnfolding-#if __GLASGOW_HASKELL__ > 706-{--data Unfolding- = ...- | DFunUnfolding { -- The Unfolding of a DFunId- -- See Note [DFun unfoldings]- -- df = /\a1..am. \d1..dn. MkD t1 .. tk- -- (op1 a1..am d1..dn)- -- (op2 a1..am d1..dn)- df_bndrs :: [Var], -- The bound variables [a1..m],[d1..dn]- df_con :: DataCon, -- The dictionary data constructor (never a newtype datacon)- df_args :: [CoreExpr] -- Args of the data con: types, superclasses and methods,- } -- in positional order--}-dFunExpr :: Unfolding -> HermitM CoreExpr--- TODO: is this correct?-dFunExpr dunf@(DFunUnfolding {}) = return $ mkCoreConApps (df_con dunf) (df_args dunf)+dFunExpr :: Monad m => Unfolding -> m CoreExpr+dFunExpr dunf@(DFunUnfolding {}) = return $ mkCoreLams (df_bndrs dunf) $ mkCoreConApps (df_con dunf) (df_args dunf) dFunExpr _ = fail "dFunExpr: not a DFunUnfolding"-#else-dFunExpr :: DataCon -> [DFunArg CoreExpr] -> Type -> HermitM CoreExpr-dFunExpr dc args ty = do- let (_, _, _, tcArgs) = tcSplitDFunTy ty- (forallTvs, ty') = splitForAllTys ty- (argTys, _resTy) = splitFunTys ty'-- ids <- mapM (uncurry newIdH) $ zip [ [ch] | ch <- cycle ['a'..'z'] ] argTys- vars <- mapM (cloneVarH id) forallTvs-- let allVars = varsToCoreExprs $ vars ++ ids-- mkArg (DFunLamArg i) = allVars !! i- mkArg (DFunPolyArg e) = mkCoreApps e allVars-- return $ mkCoreConApps dc $ map Type tcArgs ++ map mkArg args-#endif ------------------------------------------------------------------------
src/HERMIT/Dictionary/Kure.hs view
@@ -1,11 +1,11 @@ {-# LANGUAGE FlexibleContexts, ScopedTypeVariables #-} module HERMIT.Dictionary.Kure- ( -- * KURE Strategies- externals- , anyCallR- )-where+ ( -- * KURE Strategies+ externals+ , anyCallR+ , betweenR+ ) where import Control.Arrow import Control.Monad (liftM)@@ -98,6 +98,8 @@ [ "Promote a RewriteCore to a RewriteCoreTC" ] , external "extract" (extractR :: RewriteH CoreTC -> RewriteH Core) [ "Extract a RewriteCore from a RewriteCoreTC" ]+ , external "between" (betweenR :: Int -> Int -> RewriteH CoreTC -> RewriteH CoreTC)+ [ "between x y rr -> perform rr at least x times and at most y times." ] ] ------------------------------------------------------------------------------------@@ -137,3 +139,14 @@ rec = anyCallR rr ------------------------------------------------------------------------------------++-- | betweenR x y rr -> perform rr at least x times and at most y times.+betweenR :: MonadCatch m => Int -> Int -> Rewrite c m a -> Rewrite c m a+betweenR l h rr | l < 0 = fail "betweenR: lower limit below zero"+ | h < l = fail "betweenR: upper limit less than lower limit"+ | otherwise = go 0+ where -- 'c' is number of times rr has run already+ go c | c >= h = idR -- done+ | 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
@@ -1,37 +1,36 @@ {-# LANGUAGE FlexibleContexts #-} module HERMIT.Dictionary.Local- ( -- * Local Structural Manipulations- HERMIT.Dictionary.Local.externals- -- ** Binding Groups- , module HERMIT.Dictionary.Local.Bind- -- ** Case Expressions- , module HERMIT.Dictionary.Local.Case- -- ** Cast Expressions- , module HERMIT.Dictionary.Local.Cast- -- ** Let Expressions- , module HERMIT.Dictionary.Local.Let- -- ** Miscellaneous- , abstractR- , pushR- , betaReduceR- , betaReducePlusR- , betaExpandR- , etaReduceR- , etaExpandR- , multiEtaExpandR- , flattenModuleR- , flattenProgramR- , flattenProgramT- )-where+ ( -- * Local Structural Manipulations+ HERMIT.Dictionary.Local.externals+ -- ** Binding Groups+ , module HERMIT.Dictionary.Local.Bind+ -- ** Case Expressions+ , module HERMIT.Dictionary.Local.Case+ -- ** Cast Expressions+ , module HERMIT.Dictionary.Local.Cast+ -- ** Let Expressions+ , module HERMIT.Dictionary.Local.Let+ -- ** Miscellaneous+ , abstractR+ , pushR+ , betaReduceR+ , betaExpandR+ , etaReduceR+ , etaExpandR+ , multiEtaExpandR+ , flattenModuleR+ , flattenProgramR+ , flattenProgramT+ ) where import HERMIT.Core import HERMIT.Context-import HERMIT.Kure-import HERMIT.Monad import HERMIT.External import HERMIT.GHC+import HERMIT.Kure+import HERMIT.Monad+import HERMIT.Name import HERMIT.Utilities import HERMIT.Dictionary.Common@@ -57,8 +56,6 @@ [ "((\\ v -> E1) E2) ==> let v = E2 in E1" , "This form of beta-reduction is safe if E2 is an arbitrary expression" , "(won't duplicate work)." ] .+ Eval .+ Shallow- , external "beta-reduce-plus" (promoteExprR betaReducePlusR :: RewriteH Core)- [ "Perform one or more beta-reductions."] .+ Eval .+ Shallow , external "beta-expand" (promoteExprR betaExpandR :: RewriteH Core) [ "(let v = e1 in e2) ==> (\\ v -> e2) e1" ] .+ Shallow , external "eta-reduce" (promoteExprR etaReduceR :: RewriteH Core)@@ -71,7 +68,7 @@ , external "flatten-program" (promoteProgR flattenProgramR :: RewriteH Core) [ "Flatten all the top-level binding groups in a program (list of binding groups) to a single" , "recursive binding group. This can be useful if you intend to apply GHC RULES." ]- , external "abstract" (promoteExprR . abstractR :: String -> RewriteH Core)+ , external "abstract" (promoteExprR . abstractR . mkOccPred :: OccurrenceName -> RewriteH Core) [ "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)@@ -96,49 +93,6 @@ do App (Lam v e1) e2 <- idR return $ Let (NonRec v e2) e1 --multiBetaReduceR :: MonadCatch m => (Int -> Bool) -> Rewrite c m CoreExpr-multiBetaReduceR p = prefixFailMsg "Multi-Beta-Reduce failed: " $- do- e <- idR- let (f,xs) = collectArgs e- guardMsg (p (length xs)) "incorrect number of arguments."-- let (vs,e0) = collectBinders f-- guardMsg (length vs >= length xs) "insufficent lambdas."-- let (vs1,vs2) = splitAt (length xs) vs-- return- $ mkLets (zipWith NonRec vs1 xs)- $ mkLams vs2 e0---- TODO: inline this everywhere--- Neil: Are we sure we want to inline this?--- | Perform one or more beta-reductions.-betaReducePlusR :: MonadCatch m => Rewrite c m CoreExpr-betaReducePlusR = multiBetaReduceR (> 0)--{--- tagFailR "betaReducePlus failed." $- appT liftLambda idR App >>> beta_reduce- where- -- lift lambda finds the (perhaps hidden) lambda, and brings it out- liftLambda = observeR "pre-liftLambda" >>> liftLambda' >>> observeR "post-liftLambda"- liftLambda' =- (do e@(Lam {}) <- idR- return e)- <+ (betaReducePlus- >>> observeR "liftLambda(UP)"- -- let v = e in ...- -- TODO: check scope here- >>> (do Let bds (Lam v e) <- idR- return (Lam v (Let bds e)))- )--}- -- | (let v = e1 in e2) ==> (\\ v -> e2) e1 betaExpandR :: MonadCatch m => Rewrite c m CoreExpr betaExpandR = setFailMsg ("Beta-expansion failed: " ++ wrongExprForm "Let (NonRec v e1) e2") $@@ -158,7 +112,7 @@ Nothing -> fail "the argument expression is not a type variable." Just v2 -> guardMsg (v1 == v2) "type variables are not equal." _ -> fail "the argument expression is not a variable."- guardMsg (v1 `notElemVarSet` freeVarsExpr f) $ var2String v1 ++ " is free in the function being applied."+ guardMsg (v1 `notElemVarSet` freeVarsExpr f) $ unqualifiedName v1 ++ " is free in the function being applied." return f -- | e1 ==> (\\ v -> e1 v)@@ -199,12 +153,13 @@ -- | Abstract over a variable using a lambda. -- e ==> (\ x. e) x-abstractR :: (ReadBindings c) => String -> Rewrite c HermitM CoreExpr-abstractR nm = prefixFailMsg "abstraction failed: " $- do v <- findBoundVarT nm- v' <- constT (cloneVarH id v) -- currently uses the same visible name (via "id"). We could do something else here, e.g. add a prime suffix.+abstractR :: (ReadBindings c, MonadCatch m, MonadUnique m) => (Var -> Bool) -> Rewrite c m CoreExpr+abstractR p = prefixFailMsg "abstraction failed: " $+ do v <- findBoundVarT p+ v' <- constT (cloneVarH id v) -- currently uses the same visible name (via "id").+ -- We could do something else here, e.g. add a prime suffix. e <- arr (substCoreExpr v (varToCoreExpr v'))- return $ App (Lam v' e) (varToCoreExpr v)+ return $ mkCoreApp (Lam v' e) (varToCoreExpr v) ------------------------------------------------------------------------------------------------------
src/HERMIT/Dictionary/Local/Bind.hs view
@@ -1,10 +1,9 @@ module HERMIT.Dictionary.Local.Bind- ( -- * Rewrites on Binding Groups- externals- , nonrecToRecR- , recToNonrecR- )-where+ ( -- * Rewrites on Binding Groups+ externals+ , nonrecToRecR+ , recToNonrecR+ ) where import HERMIT.Core import HERMIT.External@@ -41,7 +40,7 @@ recToNonrecR = prefixFailMsg "Converting singleton recursive binding to non-recursive binding failed: " $ withPatFailMsg (wrongExprForm "Rec [Def v e]") $ do Rec [(v,e)] <- idR- guardMsg (v `notElemVarSet` freeIdsExpr e) ("'" ++ uqName v ++ " is recursively defined.")+ guardMsg (v `notElemVarSet` freeIdsExpr e) ("'" ++ unqualifiedName v ++ " is recursively defined.") return (NonRec v e) ------------------------------------------------------------------------------
src/HERMIT/Dictionary/Local/Case.hs view
@@ -5,6 +5,7 @@ externals , caseFloatAppR , caseFloatArgR+ , caseFloatArgLemmaR , caseFloatCaseR , caseFloatCastR , caseFloatLetR@@ -15,7 +16,7 @@ , caseReduceR , caseReduceDataconR , caseReduceLiteralR- , caseReduceIdR+ -- , caseReduceIdR , caseReduceUnfoldR , caseSplitR , caseSplitInlineR@@ -28,29 +29,32 @@ , caseElimMergeAltsR , caseIntroSeqR , caseElimSeqR- )-where+ ) where -import Data.List-import Data.Monoid import Control.Arrow import Control.Applicative+import Control.Monad+import Control.Monad.IO.Class +import Data.List+import Data.Monoid+ import HERMIT.Core import HERMIT.Context-import HERMIT.Monad-import HERMIT.Kure-import HERMIT.GHC import HERMIT.External-import HERMIT.Utilities+import HERMIT.GHC+import HERMIT.Kure+import HERMIT.Monad+import HERMIT.Name import HERMIT.ParserCore+import HERMIT.Utilities import HERMIT.Dictionary.Common 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)+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@@ -60,30 +64,33 @@ externals :: [External] externals = [ external "case-float-app" (promoteExprR caseFloatAppR :: RewriteH Core)- [ "(case ec of alt -> e) v ==> case ec of alt -> e v" ] .+ Commute .+ Shallow+ [ "(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) [ "Given a proof that f is strict, then"- , "f (case s of alt -> e) ==> case s of alt -> f e" ] .+ Commute .+ Shallow+ , "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) [ "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+ , "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) [ "For a specified f,"- , "f (case s of alt -> e) ==> case s of alt -> f e" ] .+ Commute .+ Shallow .+ PreCondition+ , "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+ [ "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)+ [ "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) [ "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) [ "cast (case s of p -> e) co ==> case s of p -> cast e co" ] .+ Shallow .+ Commute , external "case-float-let" (promoteExprR caseFloatLetR :: RewriteH Core)- [ "let v = case ec of alt1 -> e1 in e ==> case ec of alt1 -> let v = e1 in e" ] .+ Commute .+ Shallow+ [ "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)- [ "case-float = case-float-app <+ case-float-case <+ case-float-let <+ case-float-cast" ] .+ Commute .+ Shallow+ [ "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) [ "Float in a Case whatever the context." ] .+ Commute .+ Shallow .+ PreCondition , external "case-float-in-args" (promoteExprR caseFloatInArgsR :: RewriteH Core)- [ "Float in a Case whose alternatives are parallel applications of the same function." ] .+ Commute .+ Shallow .+ PreCondition+ [ "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) -- [ "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)@@ -95,21 +102,19 @@ , external "case-reduce-literal" (promoteExprR (caseReduceLiteralR True) :: RewriteH Core) [ "Case of Known Constructor" , "case L of L -> e ==> e" ] .+ Shallow .+ Eval- , external "case-reduce-id" (promoteExprR (caseReduceIdR True) :: RewriteH Core)- [ "Inline the case scrutinee (if it is an identifier) and then case-reduce." ] .+ Shallow .+ Eval .+ Context , external "case-reduce-unfold" (promoteExprR (caseReduceUnfoldR True) :: RewriteH Core)- [ "Unfold the case scrutinee (if it is a function application) and then case-reduce." ] .+ Shallow .+ Eval .+ Context+ [ "Unfold the case scrutinee and then case-reduce." ] .+ Shallow .+ Eval .+ Context , external "case-split" (promoteExprR . caseSplitR . cmpString2Var :: String -> RewriteH Core) [ "case-split 'x"- , "e ==> case x of C1 vs -> e; C2 vs -> e, where x is free in e" ] .+ Shallow+ , "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) [ "Like case-split, but additionally inlines the matched constructor "- , "applications for all occurances of the named variable." ] .+ Deep+ , "applications for all occurances of the named variable." ] .+ Deep .+ Strictness , external "case-intro-seq" (promoteExprR . caseIntroSeqR . cmpString2Var :: String -> RewriteH Core) [ "Force evaluation of a variable by introducing a case."- , "case-seq 'v is is equivalent to adding @(seq v)@ in the source code." ] .+ Shallow .+ Introduce+ , "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)- [ "Eliminate a case that corresponds to a pointless seq." ] .+ Deep .+ Eval+ [ "Eliminate a case that corresponds to a pointless seq." ] .+ Deep .+ Eval .+ Strictness , external "case-inline-alternative" (promoteExprR caseInlineAlternativeR :: RewriteH Core) [ "Inline the case binder as the case-alternative pattern everywhere in the case alternatives." ] .+ Deep , external "case-inline-scrutinee" (promoteExprR caseInlineScrutineeR :: RewriteH Core)@@ -122,7 +127,7 @@ [ "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)- [ "case s of w; C vs -> e ==> e if w and vs are not free in e" ] .+ Shallow+ [ "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) [ "Eliminate a case, inlining any occurrences of the case binder as the scrutinee." ] .+ Deep , external "case-elim-merge-alts" (promoteExprR caseElimMergeAltsR :: RewriteH Core)@@ -135,7 +140,7 @@ ------------------------------------------------------------------------------ -- | case s of w; C vs -> e ==> e if w and vs are not free in e-caseElimR :: Rewrite c HermitM CoreExpr+caseElimR :: MonadCatch m => Rewrite c m CoreExpr caseElimR = prefixFailMsg "Case elimination failed: " $ withPatFailMsg (wrongExprForm "Case s bnd ty alts") $ do Case _ bnd _ alts <- idR@@ -148,10 +153,11 @@ ------------------------------------------------------------------------------ -- | (case s of alt1 -> e1; alt2 -> e2) v ==> case s of alt1 -> e1 v; alt2 -> e2 v-caseFloatAppR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c) => Rewrite c HermitM CoreExpr+caseFloatAppR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, MonadCatch m, MonadUnique m)+ => Rewrite c m CoreExpr caseFloatAppR = prefixFailMsg "Case floating from App function failed: " $ do- captures <- appT (map mkVarSet <$> caseAltVarsT) (arr freeVarsExpr) (flip (map . intersectVarSet))+ captures <- appT (liftM (map mkVarSet) caseAltVarsT) (arr freeVarsExpr) (flip (map . intersectVarSet)) bndrCapture <- appT caseBinderIdT (arr freeVarsExpr) elemVarSet appT ((if not bndrCapture then idR else alphaCaseBinderR Nothing) >>> caseAllR idR idR idR (\i -> if isEmptyVarSet (captures !! i) then idR else alphaAltR)@@ -169,9 +175,10 @@ -- | @f (case s of alt1 -> e1; alt2 -> e2)@ ==> @case s of alt1 -> f e1; alt2 -> f e2@ -- Only safe if @f@ is strict.-caseFloatArgR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c)- => Maybe CoreExpr -> Maybe (Rewrite c HermitM CoreExpr) -- ^ Maybe the function to float past, and maybe a proof of its strictness.- -> Rewrite c HermitM CoreExpr+caseFloatArgR :: ( ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c+ , HasDynFlags m, HasHermitMEnv m, HasHscEnv m, MonadCatch m, MonadIO m, MonadThings m, MonadUnique m )+ => Maybe CoreExpr -> Maybe (Rewrite c m CoreExpr) -- ^ Maybe the function to float past, and maybe a proof of its strictness.+ -> Rewrite c m CoreExpr caseFloatArgR mf mstrict = prefixFailMsg "Case floating from App argument failed: " $ withPatFailMsg "App f (Case s w ty alts)" $ do App f (Case s w _ alts) <- idR@@ -191,39 +198,41 @@ ) ) >>> caseFloatArgR Nothing Nothing --- caseFloatArgR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, HasGlobalRdrEnv c)--- => Maybe (CoreExpr, Maybe (Rewrite c HermitM CoreExpr)) -- ^ Maybe the function to float past, and maybe a proof of its strictness.--- -> Rewrite c HermitM CoreExpr--- caseFloatArgR mfstrict = prefixFailMsg "Case floating from App argument failed: " $--- withPatFailMsg "App f (Case s w ty alts)" $--- do App f (Case s w _ alts) <- idR--- whenJust (\ (f', mstrict) ->--- do guardMsg (exprAlphaEq f f') "given function does not match current application."--- whenJust (verifyStrictT f) mstrict--- )--- mfstrict+-- | @f (case s of alt1 -> e1; alt2 -> e2)@ ==> @case s of alt1 -> f e1; alt2 -> f e2@+-- 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+ App f (Case s w _ alts) <- idR --- let fvs = freeVarsExpr f--- altCaptures = map (intersectVarSet fvs . mkVarSet . altVars) alts--- bndrCapture = elemVarSet w fvs+ let fvs = freeVarsExpr f+ altCaptures = map (intersectVarSet fvs . mkVarSet . altVars) alts+ bndrCapture = elemVarSet w fvs --- if | bndrCapture -> appAllR idR (alphaCaseBinderR Nothing) >>> caseFloatArgR Nothing--- | all isEmptyVarSet altCaptures -> let new_alts = mapAlts (App f) alts--- in return $ Case s w (coreAltsType new_alts) new_alts--- | otherwise -> appAllR idR (caseAllR idR idR idR (\ n -> let vs = varSetElems (altCaptures !! n)--- in if null vs then idR else alphaAltVarsR vs--- )--- ) >>> caseFloatArgR Nothing+ if | bndrCapture ->+ appAllR idR (alphaCaseBinderR Nothing) >>> caseFloatArgR Nothing Nothing+ | all isEmptyVarSet altCaptures -> do+ let new_alts = mapAlts (App f) alts+ buildStrictnessLemmaT nm f+ return $ Case s w (coreAltsType new_alts) new_alts+ | otherwise ->+ appAllR idR (caseAllR idR idR idR (\ n -> let vs = varSetElems (altCaptures !! n)+ in if null vs then idR else alphaAltVarsR vs+ )+ ) >>> caseFloatArgR Nothing Nothing -- | case (case s1 of alt11 -> e11; alt12 -> e12) of alt21 -> e21; alt22 -> e22 -- ==> -- case s1 of -- alt11 -> case e11 of alt21 -> e21; alt22 -> e22 -- alt12 -> case e12 of alt21 -> e21; alt22 -> e22-caseFloatCaseR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c) => Rewrite c HermitM CoreExpr+caseFloatCaseR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, MonadCatch m, MonadUnique m)+ => Rewrite c m CoreExpr caseFloatCaseR = prefixFailMsg "Case floating from Case failed: " $ do- captures <- caseT (map mkVarSet <$> caseAltVarsT) idR mempty (const $ arr freeVarsAlt) (\ vss w () fvs -> map (intersectVarSet (delVarSet (unionVarSets fvs) w)) vss)+ captures <- caseT (liftM (map mkVarSet) caseAltVarsT) idR mempty (const $ arr freeVarsAlt) (\ vss w () fvs -> map (intersectVarSet (delVarSet (unionVarSets fvs) w)) vss) -- does the binder of the inner case, shadow a free variable in any of the outer case alts? bndrCapture <- caseT caseBinderIdT idR mempty (const $ arr freeVarsAlt) (\ innerBndr w () fvs -> innerBndr `elemVarSet` (delVarSet (unionVarSets fvs) w)) caseT ((if not bndrCapture then idR else alphaCaseBinderR Nothing)@@ -235,7 +244,8 @@ (\ (Case s1 b1 _ alts1) b2 ty alts2 -> Case s1 b1 ty $ mapAlts (\s -> Case s b2 ty alts2) alts1) -- | let v = case s of alt1 -> e1 in e ==> case s of alt1 -> let v = e1 in e-caseFloatLetR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c) => Rewrite c HermitM CoreExpr+caseFloatLetR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, MonadCatch m, MonadUnique m)+ => Rewrite c m CoreExpr caseFloatLetR = prefixFailMsg "Case floating from Let failed: " $ do vs <- letNonRecT idR caseAltVarsT mempty (\ letVar caseVars () -> letVar `elem` concat caseVars) let bdsAction = if not vs then idR else nonRecAllR idR alphaCaseR@@ -252,7 +262,8 @@ -- | caseFloatR = caseFloatAppR <+ caseFloatCaseR <+ caseFloatLetR <+ caseFloatCastR -- Note: does NOT include caseFloatArg-caseFloatR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c) => Rewrite c HermitM CoreExpr+caseFloatR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, MonadCatch m, MonadUnique m)+ => Rewrite c m CoreExpr caseFloatR = setFailMsg "Unsuitable expression for Case floating." $ caseFloatAppR <+ caseFloatCaseR <+ caseFloatLetR <+ caseFloatCastR @@ -288,20 +299,18 @@ ------------------------------------------------------------------------------ --- | Inline the case scrutinee (if it is an identifier), and then perform case reduction.--- If first argument is True, perform substitution in RHS, if False, build let expressions.-caseReduceIdR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => Bool -> Rewrite c HermitM CoreExpr-caseReduceIdR subst = caseAllR inlineR idR idR (const idR) >>> caseReduceR subst---- | Inline the case scrutinee (if it is an identifier), and then perform case reduction.+-- | Unfold the case scrutinee and then perform case reduction. -- If first argument is True, perform substitution in RHS, if False, build let expressions.-caseReduceUnfoldR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => Bool -> Rewrite c HermitM CoreExpr+caseReduceUnfoldR :: ( ExtendPath c Crumb, ReadPath c Crumb, AddBindings c+ , ReadBindings c, HasEmptyContext c, MonadCatch m, MonadUnique m )+ => Bool -> Rewrite c m CoreExpr caseReduceUnfoldR subst = caseAllR unfoldR idR idR (const idR) >>> caseReduceR subst -- | Case of Known Constructor. -- Eliminate a case if the scrutinee is a data constructor or a literal. -- If first argument is True, perform substitution in RHS, if False, build let expressions.-caseReduceR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c) => Bool -> Rewrite c HermitM CoreExpr+caseReduceR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, MonadCatch m, MonadUnique m)+ => Bool -> Rewrite c m CoreExpr caseReduceR subst = setFailMsg "Unsuitable expression for Case reduction." $ caseReduceDataconR subst <+ caseReduceLiteralR subst@@ -315,12 +324,8 @@ prefixFailMsg "Case reduction failed: " $ withPatFailMsg (wrongExprForm "Case (Lit l) v t alts") $ do Case s bndr _ alts <- idR-#if __GLASGOW_HASKELL__ > 706 let in_scope = mkInScopeSet (localFreeVarsExpr s) case exprIsLiteral_maybe (in_scope, idUnfolding) s of-#else- case exprIsLiteral_maybe idUnfolding s of-#endif Nothing -> fail "scrutinee is not a literal." Just l -> do guardMsg (not (litIsLifted l)) "cannot case-reduce lifted literals" -- see Trac #5603 case findAlt (LitAlt l) alts of@@ -332,19 +337,17 @@ -- | Case of Known Constructor. -- Eliminate a case if the scrutinee is a data constructor. -- If first argument is True, perform substitution in RHS, if False, build let expressions.-caseReduceDataconR :: forall c. (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c) => Bool -> Rewrite c HermitM CoreExpr+caseReduceDataconR :: forall c m. ( ExtendPath c Crumb, ReadPath c Crumb, AddBindings c+ , ReadBindings c, MonadCatch m, MonadUnique m )+ => Bool -> Rewrite c m CoreExpr caseReduceDataconR subst = prefixFailMsg "Case reduction failed: " $ withPatFailMsg (wrongExprForm "Case e v t alts") go where- go :: Rewrite c HermitM CoreExpr+ go :: Rewrite c m CoreExpr go = do Case e bndr _ alts <- idR-#if __GLASGOW_HASKELL__ > 706 let in_scope = mkInScopeSet (localFreeVarsExpr e) case exprIsConApp_maybe (in_scope, idUnfolding) e of-#else- case exprIsConApp_maybe idUnfolding e of-#endif Nothing -> fail "head of scrutinee is not a data constructor." Just (dc, univTys, es) -> case findAlt (DataAlt dc) alts of Nothing -> fail "no matching alternative."@@ -367,12 +370,12 @@ -- e ==> case i of i -- [] -> e -- (a:as) -> e-caseSplitR :: (Id -> Bool) -> Rewrite c HermitM CoreExpr+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 -> (dc,) <$> sequence [ newIdH a ty | (a,ty) <- zip aNms $ dataConInstArgTys dc tys ])+ 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@@ -384,7 +387,7 @@ -- -- e -> case v of v -- _ -> e-caseIntroSeqR :: (Id -> Bool) -> Rewrite c HermitM CoreExpr+caseIntroSeqR :: (MonadCatch m, MonadUnique m) => (Id -> Bool) -> Rewrite c m CoreExpr caseIntroSeqR idPred = prefixFailMsg "case-intro-seq failed: " $ do i <- matchingFreeIdT idPred contextfreeT $ \ e -> do guardMsg (not $ isTyCoArg e) "cannot case on a type or coercion."@@ -406,25 +409,33 @@ -- for each occurance of the named variable. -- -- > caseSplitInline idPred = caseSplit idPred >>> caseInlineAlternativeR-caseSplitInlineR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => (Id -> Bool) -> Rewrite c HermitM CoreExpr+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 ------------------------------------------------------------------------------ -caseInlineBinderR :: forall c. (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => CaseBinderInlineOption -> Rewrite c HermitM CoreExpr+caseInlineBinderR :: forall c m. ( ExtendPath c Crumb, ReadPath c Crumb, AddBindings c+ , ReadBindings c, HasEmptyContext c, MonadCatch m, MonadUnique m )+ => CaseBinderInlineOption -> Rewrite c m CoreExpr caseInlineBinderR opt = do w <- caseBinderIdT caseAllR idR idR idR $ \ _ -> setFailMsg "no inlinable occurrences." $ do depth <- varBindingDepthT w- extractR $ anybuR (promoteExprR (configurableInlineR (CaseBinderOnly opt) (varIsOccurrenceOfT w depth)) :: Rewrite c HermitM Core)+ extractR $ anybuR (promoteExprR (configurableInlineR (CaseBinderOnly opt) (varIsOccurrenceOfT w depth)) :: Rewrite c m Core) -- | Inline the case binder as the case scrutinee everywhere in the case alternatives.-caseInlineScrutineeR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => Rewrite c HermitM CoreExpr+caseInlineScrutineeR :: ( ExtendPath c Crumb, ReadPath c Crumb, AddBindings c+ , ReadBindings c, HasEmptyContext c, MonadCatch m, MonadUnique m )+ => Rewrite c m CoreExpr caseInlineScrutineeR = prefixFailMsg "case-inline-scrutinee failed: " $ caseInlineBinderR Scrutinee -- | Inline the case binder as the case-alternative pattern everywhere in the case alternatives.-caseInlineAlternativeR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => Rewrite c HermitM CoreExpr+caseInlineAlternativeR :: ( ExtendPath c Crumb, ReadPath c Crumb, AddBindings c+ , ReadBindings c, HasEmptyContext c, MonadCatch m, MonadUnique m )+ => Rewrite c m CoreExpr caseInlineAlternativeR = prefixFailMsg "case-inline-alternative failed: " $ caseInlineBinderR Alternative @@ -444,31 +455,42 @@ return $ Case e w ty [(DEFAULT,[],head rhss)] -- | In the case alternatives, fold any occurrences of the case alt patterns to the case binder.-caseFoldBinderR :: forall c. (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => Rewrite c HermitM CoreExpr+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 w (Just depth)) :: Rewrite c HermitM Core)+ 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, ReadBindings c, HasEmptyContext c) => Rewrite c HermitM CoreExpr+caseMergeAltsWithBinderR :: ( ExtendPath c Crumb, ReadPath c Crumb, AddBindings c+ , ReadBindings c, HasEmptyContext c, MonadCatch m, MonadUnique m )+ => Rewrite c m CoreExpr caseMergeAltsWithBinderR = prefixFailMsg "merge-case-alts-with-binder failed: " $ withPatFailMsg (wrongExprForm "Case e w ty alts") $ tryR caseFoldBinderR >>> caseMergeAltsR -- | Eliminate a case, inlining any occurrences of the case binder as the scrutinee.-caseElimInlineScrutineeR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => Rewrite c HermitM CoreExpr+caseElimInlineScrutineeR :: ( ExtendPath c Crumb, ReadPath c Crumb, AddBindings c+ , ReadBindings c, HasEmptyContext c, MonadCatch m, MonadUnique m )+ => Rewrite c m CoreExpr caseElimInlineScrutineeR = alphaCaseBinderR Nothing >>> tryR caseInlineScrutineeR >>> caseElimR --- | Eliminate a case, merging the case alternatives into a single default alternative and inlining the case binder as the scrutinee (if possible).-caseElimMergeAltsR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => Rewrite c HermitM CoreExpr+-- | Eliminate a case, merging the case alternatives into a single default alternative+-- and inlining the case binder as the scrutinee (if possible).+caseElimMergeAltsR :: ( ExtendPath c Crumb, ReadPath c Crumb, AddBindings c+ , ReadBindings c, HasEmptyContext c, MonadCatch m, MonadUnique m )+ => Rewrite c m CoreExpr caseElimMergeAltsR = tryR caseFoldBinderR >>> tryR caseMergeAltsR >>> caseElimInlineScrutineeR ------------------------------------------------------------------------------ -- | Eliminate a case that corresponds to a pointless 'seq'.-caseElimSeqR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => Rewrite c HermitM CoreExpr+caseElimSeqR :: ( ExtendPath c Crumb, ReadPath c Crumb, AddBindings c+ , ReadBindings c, HasEmptyContext c, MonadCatch m, MonadUnique m )+ => Rewrite c m CoreExpr caseElimSeqR = prefixFailMsg "case-elim-seq failed: " $ withPatFailMsg "not a seq case." $ do Case s w _ [(DEFAULT,[],rhs)] <- idR
src/HERMIT/Dictionary/Local/Cast.hs view
@@ -70,11 +70,7 @@ withPatFailMsg (wrongExprForm "App (Cast e1 co) e2") $ do App (Cast e1 co) e2 <- idR case co of-#if __GLASGOW_HASKELL__ > 706 TyConAppCo _r t [c1, c2] -> do-#else- TyConAppCo t [c1, c2] -> do-#endif True <- return (isFunTyCon t) return $ Cast (App e1 (Cast e2 (SymCo c1))) c2 ForAllCo t c2 -> do@@ -82,14 +78,12 @@ return (Cast (App e1 e2) (Coercion.substCo (Coercion.extendTvSubst emptyCvSubst t x') c2)) _ -> fail "castFloatApp" -#if __GLASGOW_HASKELL__ > 706 -- | 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]) splitTyConAppCo_maybe (Refl ro ty) = (fmap . second . map) (Refl ro) (splitTyConApp_maybe ty) splitTyConAppCo_maybe (TyConAppCo _r tc cs) = Just (tc, cs) splitTyConAppCo_maybe _ = Nothing-#endif -- TODO: revisit castElimSymPlusR :: (ExtendPath c Crumb, AddBindings c, Monad m) => Rewrite c m CoreExpr
src/HERMIT/Dictionary/Local/Let.hs view
@@ -1,48 +1,49 @@ {-# LANGUAGE FlexibleContexts, ScopedTypeVariables, MultiWayIf, LambdaCase #-} module HERMIT.Dictionary.Local.Let- ( -- * Rewrites on Let Expressions- externals- -- ** Let Elimination- , letNonRecSubstR- , letNonRecSubstSafeR- , letSubstR- , letSubstSafeR- , letElimR- , letNonRecElimR- , letRecElimR- , progBindElimR- , progBindNonRecElimR- , progBindRecElimR- -- ** Let Introduction- , letIntroR- , letNonRecIntroR- , progNonRecIntroR- , nonRecIntroR- , letIntroUnfoldingR- -- ** Let Floating Out- , letFloatAppR- , letFloatArgR- , letFloatLetR- , letFloatLamR- , letFloatCaseR- , letFloatCastR- , letFloatExprR- , letFloatTopR- -- ** Let Floating In- , letFloatInR- , letFloatInAppR- , letFloatInCaseR- , letFloatInLamR- -- ** Miscallaneous- , reorderNonRecLetsR- , letTupleR- , letToCaseR- )-where+ ( -- * Rewrites on Let Expressions+ externals+ -- ** Let Elimination+ , letNonRecSubstR+ , letNonRecSubstSafeR+ , letSubstR+ , letSubstSafeR+ , letElimR+ , letNonRecElimR+ , letRecElimR+ , progBindElimR+ , progBindNonRecElimR+ , progBindRecElimR+ -- ** Let Introduction+ , letIntroR+ , letNonRecIntroR+ , progNonRecIntroR+ , nonRecIntroR+ , letIntroUnfoldingR+ -- ** Let Floating Out+ , letFloatAppR+ , letFloatArgR+ , letFloatLetR+ , letFloatLamR+ , letFloatCaseR+ , letFloatCaseAltR+ , letFloatCastR+ , letFloatExprR+ , letFloatTopR+ -- ** Let Floating In+ , letFloatInR+ , letFloatInAppR+ , letFloatInCaseR+ , letFloatInLamR+ -- ** Miscallaneous+ , reorderNonRecLetsR+ , letTupleR+ , letToCaseR+ ) where import Control.Arrow import Control.Monad+import Control.Monad.IO.Class import Data.List import Data.Monoid@@ -53,6 +54,7 @@ import HERMIT.Kure import HERMIT.External import HERMIT.GHC+import HERMIT.Name import HERMIT.Utilities import HERMIT.Dictionary.Common@@ -83,7 +85,7 @@ -- , "only matches non-recursive lets" ] .+ Deep .+ Eval , external "let-intro" (promoteExprR . letIntroR :: String -> RewriteH Core) [ "e => (let v = e in v), name of v is provided" ] .+ Shallow .+ Introduce- , external "let-intro-unfolding" (promoteExprR . letIntroUnfoldingR :: String -> RewriteH Core)+ , external "let-intro-unfolding" (promoteExprR . letIntroUnfoldingR :: HermitName -> RewriteH Core) [ "e => let f' = defn[f'/f] in e[f'/f], name of f is provided" ] , external "let-elim" (promoteExprR letElimR :: RewriteH Core) [ "Remove an unused let binding."@@ -102,6 +104,13 @@ [ "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) [ "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)+ [ "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)+ [ "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) [ "cast (let bnds in e) co ==> let bnds in cast e co" ] .+ Commute .+ Shallow , external "let-float-top" (promoteProgR letFloatTopR :: RewriteH Core)@@ -157,6 +166,29 @@ do Let (NonRec v rhs) body <- idR return (substCoreExpr v rhs body) +{-+TODO: This was written very early in the project by Andy.+ It was later modified somewhat by Neil, but without reassessing the heurisitc as a whole.+ It may need revisiting.++Safe Subst Heuristic+--------------------++Substitution is safe if (A) OR (B) OR (C).++(A) The let-bound variable is a type or coercion.++(B) The let-bound value is either:+ (i) a variable;+ (ii) a lambda;+ (iii) an application that requires more value arguments before it can perform any computation.++(C) In the body, the let-bound variable must NOT occur:+ (i) more than once;+ (ii) inside a lambda.++-}+ -- | Currently we always substitute types and coercions, and use a heuristic to decide whether to substitute expressions. -- This may need revisiting. letNonRecSubstSafeR :: forall c m. (AddBindings c, ExtendPath c Crumb, ReadPath c Crumb, ReadBindings c, HasEmptyContext c, MonadCatch m) => Rewrite c m CoreExpr@@ -270,7 +302,8 @@ ------------------------------------------------------------------------------------------- -- | @let v = ev in e@ ==> @case ev of v -> e@-letToCaseR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c) => Rewrite c HermitM CoreExpr+letToCaseR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, MonadCatch m, MonadUnique m)+ => Rewrite c m CoreExpr letToCaseR = prefixFailMsg "Converting Let to Case failed: " $ withPatFailMsg (wrongExprForm "Let (NonRec v e1) e2") $ do Let (NonRec v ev) _ <- idR@@ -281,7 +314,8 @@ ------------------------------------------------------------------------------------------- -- | @(let v = ev in e) x@ ==> @let v = ev in e x@-letFloatAppR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => Rewrite c HermitM CoreExpr+letFloatAppR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m)+ => Rewrite c m CoreExpr letFloatAppR = prefixFailMsg "Let floating from App function failed: " $ withPatFailMsg (wrongExprForm "App (Let bnds body) e") $ do App (Let bnds body) e <- idR@@ -291,7 +325,8 @@ else appAllR (alphaLetVarsR $ varSetElems vs) idR >>> letFloatAppR -- | @f (let v = ev in e)@ ==> @let v = ev in f e@-letFloatArgR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => Rewrite c HermitM CoreExpr+letFloatArgR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m)+ => Rewrite c m CoreExpr letFloatArgR = prefixFailMsg "Let floating from App argument failed: " $ withPatFailMsg (wrongExprForm "App f (Let bnds body)") $ do App f (Let bnds body) <- idR@@ -301,7 +336,8 @@ else appAllR idR (alphaLetVarsR $ varSetElems vs) >>> letFloatArgR -- | @let v = (let bds in e1) in e2@ ==> @let bds in let v = e1 in e2@-letFloatLetR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => Rewrite c HermitM CoreExpr+letFloatLetR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m)+ => Rewrite c m CoreExpr letFloatLetR = prefixFailMsg "Let floating from Let failed: " $ withPatFailMsg (wrongExprForm "Let (NonRec v (Let bds e1)) e2") $ do Let (NonRec v (Let bds e1)) e2 <- idR@@ -313,20 +349,22 @@ -- | @(\ v -> let binds in e2)@ ==> @let binds in (\ v1 -> e2)@ -- Fails if @v@ occurs in the RHS of @binds@. -- If @v@ is shadowed in binds, then @v@ will be alpha-renamed.-letFloatLamR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => Rewrite c HermitM CoreExpr+letFloatLamR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m)+ => Rewrite c m CoreExpr letFloatLamR = prefixFailMsg "Let floating from Lam failed: " $ withPatFailMsg (wrongExprForm "Lam v1 (Let bds body)") $ do Lam v (Let binds body) <- idR let bs = bindVars binds fvs = freeVarsBind binds- guardMsg (v `notElemVarSet` fvs) (var2String v ++ " occurs in the RHS of the let-bindings.")+ guardMsg (v `notElemVarSet` fvs) (unqualifiedName v ++ " occurs in the RHS of the let-bindings.") if v `elem` bs then alphaLamR Nothing >>> letFloatLamR else return $ Let binds (Lam v body) -- | @case (let bnds in e) of bndr alts@ ==> @let bnds in (case e of bndr alts)@ -- Fails if any variables bound in @bnds@ occurs in @alts@.-letFloatCaseR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => Rewrite c HermitM CoreExpr+letFloatCaseR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m)+ => Rewrite c m CoreExpr letFloatCaseR = prefixFailMsg "Let floating from Case failed: " $ withPatFailMsg (wrongExprForm "Case (Let bnds e) w ty alts") $ do Case (Let bnds e) w ty alts <- idR@@ -335,6 +373,57 @@ then return $ Let bnds (Case e w ty alts) else caseAllR (alphaLetVarsR $ varSetElems captures) idR idR (const idR) >>> letFloatCaseR +-- | case e of w { ... ; p -> let b = rhs in body ; ... } ==>+-- let b = rhs in case e of { ... ; p -> body ; ... }+--+-- where no variable in `p` or `w` occurs freely in `rhs`,+-- and where `b` does not capture a free variable in the overall case,+-- and where `w` is not rebound in `b`.+letFloatCaseAltR :: MonadCatch m => Maybe Int -> Rewrite c m CoreExpr+letFloatCaseAltR maybeN = prefixFailMsg "Let float from case alternative failed: " $+ withPatFailMsg (wrongExprForm "Case s w ty alts") $ do+ -- Perform the first safe let-floating out of a case alternative+ let letFloatOneAltM :: MonadCatch m => Id -> VarSet -> [CoreAlt] -> m (CoreBind,[CoreAlt])+ letFloatOneAltM w fvs = go+ where go [] = fail "no lets can be safely floated from alternatives."+ go (alt:rest) = (do (bind,alt') <- letFloatAltM w fvs alt+ return (bind,alt':rest))+ <+ liftM (second (alt :)) (go rest)++ -- (p -> let bnds in body) ==> (bnds, p -> body)+ letFloatAltM :: Monad m => Id -> VarSet -> CoreAlt -> m (CoreBind,CoreAlt)+ letFloatAltM w fvs (con, vs, Let bnds body) = do+ let bSet = mkVarSet (bindVars bnds)+ vSet = mkVarSet (w:vs)++ -- 'w' is not in 'fvs', but if it is rebound by 'b', doing this rewrite+ -- would cause it to bind things that were previously bound by 'b'.+ guardMsg (not (w `elemVarSet` bSet)) "floating would allow case binder to capture variables."++ -- no free vars in 'rhs' are bound by 'p' or 'w'+ guardMsg (isEmptyVarSet $ vSet `intersectVarSet` freeVarsBind bnds)+ "floating would cause variables in rhs to become unbound."++ -- no free vars in overall case are bound by 'b'+ guardMsg (isEmptyVarSet $ bSet `intersectVarSet` fvs)+ "floating would cause let binders to capture variables in case expression."++ return (bnds, (con, vs, body))+ letFloatAltM _ _ _ = fail "no let expression on alternative right-hand side."++ Case e w ty alts <- idR+ fvs <- arr freeVarsExpr+ let l = length alts - 1+ case maybeN of+ Just n | n < 0 || n > l -> fail $ "valid alternative indices: 0 to " ++ show l+ | otherwise -> do+ let (pre, alt:suf) = splitAt n alts+ (bnds,alt') <- letFloatAltM w fvs alt+ return $ Let bnds $ Case e w ty $ pre ++ (alt':suf)+ Nothing -> do+ (bnds,alts') <- letFloatOneAltM w fvs alts+ return $ Let bnds $ Case e w ty alts'+ -- | @cast (let bnds in e) co@ ==> @let bnds in cast e co@ letFloatCastR :: MonadCatch m => Rewrite c m CoreExpr letFloatCastR = prefixFailMsg "Let floating from Cast failed: " $@@ -343,12 +432,15 @@ return $ Let bnds (Cast e co) -- | Float a 'Let' through an expression, whatever the context.-letFloatExprR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => Rewrite c HermitM CoreExpr-letFloatExprR = setFailMsg "Unsuitable expression for Let floating." $- letFloatArgR <+ letFloatAppR <+ letFloatLetR <+ letFloatLamR <+ letFloatCaseR <+ letFloatCastR+letFloatExprR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m)+ => Rewrite c m CoreExpr+letFloatExprR = setFailMsg "Unsuitable expression for Let floating."+ $ letFloatArgR <+ letFloatAppR <+ letFloatLetR <+ letFloatLamR+ <+ letFloatCaseR <+ letFloatCaseAltR Nothing <+ letFloatCastR -- | @'ProgCons' ('NonRec' v ('Let' bds e)) p@ ==> @'ProgCons' bds ('ProgCons' ('NonRec' v e) p)@-letFloatTopR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c) => Rewrite c HermitM CoreProg+letFloatTopR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, BoundVars c, MonadCatch m, MonadUnique m)+ => Rewrite c m CoreProg letFloatTopR = prefixFailMsg "Let floating to top level failed: " $ withPatFailMsg (wrongExprForm "NonRec v (Let bds e) `ProgCons` p") $ do ProgCons (NonRec v (Let bds e)) p <- idR@@ -362,12 +454,14 @@ ------------------------------------------------------------------------------------------- -- | Float in a 'Let' if possible.-letFloatInR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb) => Rewrite c HermitM CoreExpr+letFloatInR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb, MonadCatch m, MonadUnique m)+ => Rewrite c m CoreExpr letFloatInR = letFloatInCaseR <+ letFloatInAppR <+ letFloatInLamR -- | @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@-letFloatInCaseR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb) => Rewrite c HermitM CoreExpr+letFloatInCaseR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb, MonadCatch m, MonadUnique m)+ => Rewrite c m CoreExpr letFloatInCaseR = prefixFailMsg "Let floating in to case failed: " $ withPatFailMsg (wrongExprForm "Let bnds (Case s w ty alts)") $ do Let bnds (Case s w ty alts) <- idR@@ -379,7 +473,8 @@ return (Case (Let bnds s) w ty alts) >>> caseAllR idR idR idR (\_ -> altAllR idR (\_ -> idR) (arr (Let bnds) >>> alphaLetR)) -- | @let v = ev in f a@ ==> @(let v = ev in f) (let v = ev in a)@-letFloatInAppR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb) => Rewrite c HermitM CoreExpr+letFloatInAppR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb, MonadCatch m, MonadUnique m)+ => Rewrite c m CoreExpr letFloatInAppR = prefixFailMsg "Let floating in to app failed: " $ withPatFailMsg (wrongExprForm "Let bnds (App e1 e2)") $ do Let bnds (App e1 e2) <- idR@@ -434,7 +529,7 @@ -- | 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}-letTupleR :: String -> Rewrite c HermitM CoreExpr+letTupleR :: (MonadCatch m, MonadUnique m) => String -> Rewrite c m CoreExpr letTupleR nm = prefixFailMsg "Let-tuple failed: " $ do (bnds, body) <- arr collectLets let numBnds = length bnds@@ -465,32 +560,29 @@ -- This code could be factored better. -- | @e@ ==> @let v = e in v@-letIntroR :: String -> Rewrite c HermitM CoreExpr+letIntroR :: (MonadCatch m, MonadUnique m) => String -> Rewrite c m CoreExpr letIntroR nm = do e <- idR Let (NonRec v e') _ <- letNonRecIntroR nm e return $ Let (NonRec v e') (varToCoreExpr v) -- | @body@ ==> @let v = e in body@-letNonRecIntroR :: String -> CoreExpr -> Rewrite c HermitM CoreExpr+letNonRecIntroR :: (MonadCatch m, MonadUnique m) => String -> CoreExpr -> Rewrite c m CoreExpr letNonRecIntroR nm e = prefixFailMsg "Let-introduction failed: " $- contextfreeT $ \ body -> do let tyk = exprKindOrType e- v <- if | isTypeArg e -> newTyVarH nm tyk- | isCoArg e -> newCoVarH nm tyk- | otherwise -> newIdH nm tyk+ contextfreeT $ \ body -> do v <- newVarH nm $ exprKindOrType e return $ Let (NonRec v e) body -- This isn't a "Let", but it's serving the same role. Maybe create a Local/Prog module? -- | @prog@ ==> @'ProgCons' (v = e) prog@-progNonRecIntroR :: String -> CoreExpr -> Rewrite c HermitM CoreProg+progNonRecIntroR :: (MonadCatch m, MonadUnique m) => String -> CoreExpr -> Rewrite c m CoreProg progNonRecIntroR nm e = prefixFailMsg "Top-level binding introduction failed: " $ do guardMsg (not $ isTyCoArg e) "Top-level type or coercion definitions are prohibited." contextfreeT $ \ prog -> do i <- newIdH nm (exprType e) return $ ProgCons (NonRec i e) prog -- | nonRecIntroR nm e = 'letNonRecIntroR nm e' <+ 'progNonRecIntroR nm e'-nonRecIntroR :: String -> CoreExpr -> Rewrite c HermitM Core+nonRecIntroR :: (MonadCatch m, MonadUnique m) => String -> CoreExpr -> Rewrite c m Core nonRecIntroR nm e = readerT $ \case ExprCore{} -> promoteExprR (letNonRecIntroR nm e) ProgCore{} -> promoteProgR (progNonRecIntroR nm e)@@ -498,7 +590,9 @@ -- | Introduce a local definition for a (possibly imported) identifier. -- Rewrites occurences of the identifier to point to this new local definiton.-letIntroUnfoldingR :: (BoundVars c, ReadBindings c) => String -> Rewrite c HermitM CoreExpr+letIntroUnfoldingR :: ( BoundVars c, ReadBindings c, HasDynFlags m, HasHermitMEnv m, HasHscEnv m+ , MonadCatch m, MonadIO m, MonadThings m, MonadUnique m )+ => HermitName -> Rewrite c m CoreExpr letIntroUnfoldingR nm = do i <- findIdT nm (rhs,_) <- getUnfoldingT AllBinders <<< return i
@@ -1,33 +1,35 @@-{-# LANGUAGE ScopedTypeVariables, FlexibleContexts, FlexibleInstances, InstanceSigs #-}+{-# LANGUAGE DeriveDataTypeable, FlexibleContexts, FlexibleInstances, InstanceSigs, ScopedTypeVariables, TypeFamilies #-} module HERMIT.Dictionary.Navigation- ( -- * Navigation- externals- , occurrenceOfT- , bindingOfT- , bindingGroupOfT- , rhsOfT- , parentOfT- , occurrenceOfTargetsT- , bindingOfTargetsT- , bindingGroupOfTargetsT- , rhsOfTargetsT- , Considerable(..)- , considerables- , considerConstructT- , nthArgPath- )-where+ ( -- * Navigation+ externals+ , occurrenceOfT+ , bindingOfT+ , bindingGroupOfT+ , rhsOfT+ , parentOfT+ , occurrenceOfTargetsT+ , bindingOfTargetsT+ , bindingGroupOfTargetsT+ , rhsOfTargetsT+ , Considerable(..)+ , considerables+ , considerConstructT+ , nthArgPath+ , string2considerable+ ) where +import Data.Dynamic (Typeable) import Data.Monoid import Control.Arrow import HERMIT.Core import HERMIT.Context-import HERMIT.Kure import HERMIT.External import HERMIT.GHC hiding ((<>))+import HERMIT.Kure+import HERMIT.Name import HERMIT.Dictionary.Navigation.Crumbs @@ -35,32 +37,33 @@ -- | 'External's involving navigating to named entities. externals :: [External]-externals = crumbExternals ++ map (.+ Navigation)- [ external "rhs-of" (rhsOfT . cmpString2Var :: String -> TransformH Core LocalPathH)- [ "Find the path to the RHS of the binding of the named variable." ]- , external "binding-group-of" (bindingGroupOfT . cmpString2Var :: String -> TransformH CoreTC LocalPathH)- [ "Find the path to the binding group of the named variable." ]- , external "binding-of" (bindingOfT . cmpString2Var :: String -> TransformH CoreTC LocalPathH)- [ "Find the path to the binding of the named variable." ]- , external "occurrence-of" (occurrenceOfT . cmpString2Var :: String -> TransformH CoreTC LocalPathH)- [ "Find the path to the first occurrence of the named variable." ]- , external "consider" (considerConstruct :: String -> TransformH Core LocalPathH)- [ "consider <c> focuses on the first construct <c>.",- recognizedConsiderables]- , external "arg" (promoteExprT . nthArgPath :: Int -> TransformH Core LocalPathH)- [ "arg n focuses on the (n-1)th argument of a nested application." ]- , external "lams-body" (promoteExprT lamsBodyT :: TransformH Core LocalPathH)- [ "Descend into the body after a sequence of lambdas." ]- , external "lets-body" (promoteExprT letsBodyT :: TransformH Core LocalPathH)- [ "Descend into the body after a sequence of let bindings." ]- , external "prog-end" (promoteModGutsT gutsProgEndT <+ promoteProgT progEndT :: TransformH Core LocalPathH)- [ "Descend to the end of a program." ]-- , external "parent-of" (parentOfT :: TransformH Core LocalPathH -> TransformH Core LocalPathH)- [ "Focus on the parent of another focal point." ]- , external "parent-of" (parentOfT :: TransformH CoreTC LocalPathH -> TransformH CoreTC LocalPathH)- [ "Focus on the parent of another focal point." ]- ]+externals = crumbExternals+ ++ map (.+ Navigation)+ [ external "rhs-of" (rhsOfT . mkRhsOfPred :: RhsOfName -> TransformH Core LocalPathH)+ [ "Find the path to the RHS of the binding of the named variable." ]+ , external "binding-group-of" (bindingGroupOfT . cmpString2Var :: String -> TransformH CoreTC LocalPathH)+ [ "Find the path to the binding group of the named variable." ]+ , external "binding-of" (bindingOfT . mkBindingPred :: BindingName -> TransformH CoreTC LocalPathH)+ [ "Find the path to the binding of the named variable." ]+ , external "occurrence-of" (occurrenceOfT . mkOccPred :: OccurrenceName -> TransformH CoreTC LocalPathH)+ [ "Find the path to the first occurrence of the named variable." ]+ , external "application-of" (applicationOfT . mkOccPred :: OccurrenceName -> TransformH CoreTC LocalPathH)+ [ "Find the path to the first application of the named variable." ]+ , external "consider" (considerConstructT :: Considerable -> TransformH Core LocalPathH)+ [ "consider <c> focuses on the first construct <c>.", recognizedConsiderables ]+ , external "arg" (promoteExprT . nthArgPath :: Int -> TransformH Core LocalPathH)+ [ "arg n focuses on the (n-1)th argument of a nested application." ]+ , external "lams-body" (promoteExprT lamsBodyT :: TransformH Core LocalPathH)+ [ "Descend into the body after a sequence of lambdas." ]+ , external "lets-body" (promoteExprT letsBodyT :: TransformH Core LocalPathH)+ [ "Descend into the body after a sequence of let bindings." ]+ , external "prog-end" (promoteModGutsT gutsProgEndT <+ promoteProgT progEndT :: TransformH Core LocalPathH)+ [ "Descend to the end of a program." ]+ , external "parent-of" (parentOfT :: TransformH Core LocalPathH -> TransformH Core LocalPathH)+ [ "Focus on the parent of another focal point." ]+ , external "parent-of" (parentOfT :: TransformH CoreTC LocalPathH -> TransformH CoreTC LocalPathH)+ [ "Focus on the parent of another focal point." ]+ ] --------------------------------------------------------------------------------------- @@ -99,6 +102,12 @@ 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+applicationOfT p = prefixFailMsg "application-of failed:" $ oneNonEmptyPathToT go+ where go = promoteExprT (appT (extractT go) successT const) <+ arr (occurrenceOf p)+ ----------------------------------------------------------------------- bindingGroupOf :: (Var -> Bool) -> CoreBind -> Bool@@ -186,7 +195,13 @@ -- | Language constructs that can be zoomed to. data Considerable = Binding | Definition | CaseAlt | Variable | Literal | Application | Lambda | LetExpr | CaseOf | Casty | Ticky | TypeExpr | CoercionExpr+ deriving Typeable +instance Extern Considerable where+ type Box Considerable = Considerable+ box = id+ unbox = id+ recognizedConsiderables :: String recognizedConsiderables = "Recognized constructs are: " ++ show (map fst considerables) @@ -206,12 +221,6 @@ , ("type",TypeExpr) , ("coerce",CoercionExpr) ]--considerConstruct :: (AddBindings c, ExtendPath c Crumb, ReadPath c Crumb, HasEmptyContext c, MonadCatch m) => String -> Transform c m Core LocalPathH-considerConstruct str = case string2considerable str of- Nothing -> fail $ "Unrecognized construct \"" ++ str ++ "\". Perhaps you meant \"binding-of '" ++ str ++ "\"? "- ++ recognizedConsiderables ++ "."- Just c -> considerConstructT c -- | 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
src/HERMIT/Dictionary/Query.hs view
@@ -1,13 +1,12 @@ {-# LANGUAGE CPP, LambdaCase, FlexibleContexts #-} module HERMIT.Dictionary.Query- ( -- * Queries and Predicates- externals- , infoT- , compareCoreAtT- , compareBoundIdsT- )-where+ ( -- * Queries and Predicates+ externals+ , infoT+ , compareCoreAtT+ , compareBoundIdsT+ ) where import Control.Arrow @@ -20,6 +19,7 @@ import HERMIT.GHC import HERMIT.Kure import HERMIT.Monad+import HERMIT.Name import HERMIT.Dictionary.AlphaConversion hiding (externals) import HERMIT.Dictionary.Common@@ -31,13 +31,13 @@ -- | Externals that reflect GHC functions, or are derived from GHC functions. externals :: [External] externals =- [ external "info" (infoT :: TransformH CoreTC String)- [ "Display information about the current node." ] .+ Query- , external "compare-bound-ids" (compareBoundIds :: String -> String -> TransformH CoreTC ())- [ "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 ())- [ "Compare the core fragments at the end of the given paths for alpha-equality."] .+ Query .+ Predicate- ]+ [ external "info" (infoT :: TransformH CoreTC String)+ [ "Display information about the current node." ] .+ Query+ , external "compare-bound-ids" (compareBoundIds :: HermitName -> HermitName -> TransformH CoreTC ())+ [ "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 ())+ [ "Compare the core fragments at the end of the given paths for alpha-equality."] .+ Query .+ Predicate+ ] -------------------------------------------------------- @@ -52,7 +52,7 @@ pa = "Path: " ++ showCrumbs (snocPathToPath $ absPath c) children = "Children: " ++ showCrumbs crumbs bds = "Local bindings in scope: " ++ concat- [ "\n " ++ var2String k ++ " : " ++ hermitBindingSummary hbs+ [ "\n " ++ unqualifiedName k ++ " : " ++ hermitBindingSummary hbs | (k,hbs) <- Map.toList (hermitBindings c) ] freevars = [ "Free local identifiers: " ++ showVarSet (filterVarSet isLocalId fvs)@@ -63,11 +63,14 @@ typeId = case coreTC of Core (ExprCore e) -> let tyK = exprKindOrType e+ modName i = case nameModule_maybe (getName i) of+ Nothing -> "no module name."+ Just m -> moduleNameString (moduleName m) in [(if isKind tyK then "Kind: " else "Type: ") ++ showPpr dynFlags tyK] ++ case e of Var i -> [ "" , "OccName: " ++ getOccString i- , if isLocalVar i then "Local" else "Global"+ , if isLocalVar i then "Local" else "Global: " ++ modName i , "Unique: " ++ show (getUnique i) , "Identifier arity: " ++ show (arityOf c i) , "Identifier binding depth: " ++ runKureM show id (lookupHermitBindingDepth i c)@@ -151,14 +154,10 @@ TransCo{} -> "TransCo" NthCo{} -> "NthCo" InstCo{} -> "InstCo"-#if __GLASGOW_HASKELL__ > 706 AxiomRuleCo{} -> "AxiomRuleCo" LRCo{} -> "LRCo" SubCo{} -> "SubCo" UnivCo{} -> "UnivCo"-#else- UnsafeCo{} -> "UnsafeCo"-#endif -------------------------------------------------------- @@ -180,7 +179,8 @@ guardMsg (e1 `exprAlphaEq` e2) "bindings are not alpha-equivalent." -- | Compare the definitions of the two named identifiers for alpha-equality.-compareBoundIds :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c) => String -> String -> Transform c HermitM x ()+compareBoundIds :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c)+ => HermitName -> HermitName -> Transform c HermitM x () compareBoundIds nm1 nm2 = do i1 <- findIdT nm1 i2 <- findIdT nm2 compareBoundIdsT i1 i2
src/HERMIT/Dictionary/Reasoning.hs view
@@ -4,16 +4,19 @@ module HERMIT.Dictionary.Reasoning ( -- * Equational Reasoning externals- , CoreExprEquality(..)- , RewriteCoreExprEqualityBox(..)- , TransformCoreExprEqualityStringBox(..)- , CoreExprEqualityProof- , flipCoreExprEquality+ , EqualityProof+ , flipEquality , eqLhsIntroR , eqRhsIntroR , birewrite , extensionalityR- -- ** Lifting transformations over 'CoreExprEquality'+ , getLemmasT+ , getLemmaByNameT+ , insertLemmaR+ , lemmaR+ , markLemmaUsedR+ , modifyLemmaR+ -- ** Lifting transformations over 'Equality' , lhsT , rhsT , bothT@@ -21,9 +24,9 @@ , lhsR , rhsR , bothR- , ppCoreExprEqualityT- , proveCoreExprEqualityT- , verifyCoreExprEqualityT+ , ppEqualityT+ , proveEqualityT+ , verifyEqualityT , verifyEqualityLeftToRightT , verifyEqualityCommonTargetT , verifyIsomorphismT@@ -38,36 +41,34 @@ , discardUniVars ) where -import Control.Applicative-import Control.Arrow-import Control.Monad-import Control.Monad.IO.Class--import Data.List (nubBy)-import Data.Maybe (fromMaybe)-import Data.Monoid-import Data.Typeable--import HERMIT.Context-import HERMIT.Core-import HERMIT.External-import HERMIT.GHC-import HERMIT.Kure-import HERMIT.Monad-import HERMIT.ParserCore-#if __GLASGOW_HASKELL__ >= 708-import HERMIT.ParserType-#endif-import HERMIT.Utilities+import Control.Applicative+import Control.Arrow+import Control.Monad+import Control.Monad.IO.Class -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 Data.Map as Map+import Data.List (nubBy)+import Data.Maybe (fromMaybe)+import Data.Monoid -import HERMIT.PrettyPrinter.Common+import HERMIT.Context+import HERMIT.Core+import HERMIT.External+import HERMIT.GHC+import HERMIT.Kure+import HERMIT.Monad+import HERMIT.Name+import HERMIT.ParserCore+import HERMIT.ParserType+import HERMIT.PrettyPrinter.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 @@ -88,72 +89,91 @@ [ "Alpha-rename a universally quantified variable." ] , external "unshadow-equality" unshadowEqualityR [ "Unshadow an equality." ]+ , external "lemma" (promoteExprBiR . lemmaR :: LemmaName -> BiRewriteH Core)+ [ "Generate a bi-directional rewrite from a lemma." ]+ , external "lemma-lhs-intro" (lemmaLhsIntroR :: LemmaName -> RewriteH Core)+ [ "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)+ [ "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)+ [ "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)+ [ "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)+ [ "Apply a transformation to a lemma, returning the result." ]+ , external "extensionality" (extensionalityR . Just :: String -> RewriteH Equality)+ [ "Given a name 'x, then"+ , "f == g ==> forall x. f x == g x" ]+ , external "extensionality" (extensionalityR Nothing :: RewriteH Equality)+ [ "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)+ [ "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." ] ] ------------------------------------------------------------------------------ --- | An equality is represented as a set of universally quantified binders, and then the LHS and RHS of the equality.-data CoreExprEquality = CoreExprEquality [CoreBndr] CoreExpr CoreExpr--data RewriteCoreExprEqualityBox =- RewriteCoreExprEqualityBox (RewriteH CoreExprEquality) deriving Typeable--instance Extern (RewriteH CoreExprEquality) where- type Box (RewriteH CoreExprEquality) = RewriteCoreExprEqualityBox- box = RewriteCoreExprEqualityBox- unbox (RewriteCoreExprEqualityBox r) = r--data TransformCoreExprEqualityStringBox =- TransformCoreExprEqualityStringBox (TransformH CoreExprEquality String) deriving Typeable--instance Extern (TransformH CoreExprEquality String) where- type Box (TransformH CoreExprEquality String) = TransformCoreExprEqualityStringBox- box = TransformCoreExprEqualityStringBox- unbox (TransformCoreExprEqualityStringBox t) = t--type CoreExprEqualityProof c m = (Rewrite c m CoreExpr, Rewrite c m CoreExpr)+type EqualityProof c m = (Rewrite c m CoreExpr, Rewrite c m CoreExpr) --- | Flip the LHS and RHS of a 'CoreExprEquality'.-flipCoreExprEquality :: CoreExprEquality -> CoreExprEquality-flipCoreExprEquality (CoreExprEquality xs lhs rhs) = CoreExprEquality xs rhs lhs+-- | 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 CoreExprEquality+extensionalityR :: Maybe String -> Rewrite c HermitM Equality extensionalityR mn = prefixFailMsg "extensionality failed: " $- do CoreExprEquality vs lhs rhs <- idR+ do Equality vs lhs rhs <- idR let tyL = exprKindOrType lhs tyR = exprKindOrType rhs guardMsg (tyL `typeAlphaEq` tyR) "type mismatch between sides of equality. This shouldn't happen, so is probably a bug." -- TODO: use the fresh-name-generator in AlphaConversion to avoid shadowing.- (argTy,_) <- splitFunTypeM tyL+ (_,argTy,_) <- splitFunTypeM tyL v <- constT $ newVarH (fromMaybe "x" mn) argTy let x = varToCoreExpr v - return $ CoreExprEquality (vs ++ [v])- (mkCoreApp lhs x)- (mkCoreApp rhs x)+ return $ Equality (vs ++ [v]) (mkCoreApp lhs x) (mkCoreApp rhs x) ------------------------------------------------------------------------------ -- | @e@ ==> @let v = lhs in e@-eqLhsIntroR :: CoreExprEquality -> Rewrite c HermitM Core-eqLhsIntroR (CoreExprEquality bs lhs _) = nonRecIntroR "lhs" (mkCoreLams bs lhs)+eqLhsIntroR :: Equality -> Rewrite c HermitM Core+eqLhsIntroR (Equality bs lhs _) = nonRecIntroR "lhs" (mkCoreLams bs lhs) -- | @e@ ==> @let v = rhs in e@-eqRhsIntroR :: CoreExprEquality -> Rewrite c HermitM Core-eqRhsIntroR (CoreExprEquality bs _ rhs) = nonRecIntroR "rhs" (mkCoreLams bs rhs)+eqRhsIntroR :: Equality -> Rewrite c HermitM Core+eqRhsIntroR (Equality bs _ rhs) = nonRecIntroR "rhs" (mkCoreLams bs rhs) ------------------------------------------------------------------------------ --- | Create a 'BiRewrite' from a 'CoreExprEquality'.+-- | 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.-birewrite :: (AddBindings c, ReadBindings c, ExtendPath c Crumb, ReadPath c Crumb, HasEmptyContext c) => CoreExprEquality -> BiRewrite c HermitM CoreExpr-birewrite (CoreExprEquality bnds l r) = bidirectional (foldUnfold l r) (foldUnfold r l)+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@@ -163,46 +183,46 @@ -- create a temporary context with an unfolding for the -- transitory function so we can reuse unfoldR. c' = addHermitBindings [(v, NONREC rhsLam, mempty)] c- apply unfoldR c' e'+ applyT unfoldR c' e' --- | Lift a transformation over 'CoreExpr' into a transformation over the left-hand side of a 'CoreExprEquality'.-lhsT :: (AddBindings c, Monad m, ReadPath c Crumb) => Transform c m CoreExpr b -> Transform c m CoreExprEquality b-lhsT t = idR >>= \ (CoreExprEquality vs lhs _) -> return lhs >>> withVarsInScope vs t+-- | 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 --- | Lift a transformation over 'CoreExpr' into a transformation over the right-hand side of a 'CoreExprEquality'.-rhsT :: (AddBindings c, Monad m, ReadPath c Crumb) => Transform c m CoreExpr b -> Transform c m CoreExprEquality b-rhsT t = idR >>= \ (CoreExprEquality vs _ rhs) -> return rhs >>> withVarsInScope vs t+-- | 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 'CoreExpr' into a transformation over both sides of a 'CoreExprEquality'.-bothT :: (AddBindings c, Monad m, ReadPath c Crumb) => Transform c m CoreExpr b -> Transform c m CoreExprEquality (b,b)+-- | 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 '[Var]' into a transformation over the universally quantified variables of a 'CoreExprEquality'.-forallVarsT :: Monad m => Transform c m [Var] b -> Transform c m CoreExprEquality b-forallVarsT t = idR >>= \ (CoreExprEquality vs _ _) -> return vs >>> t+-- | 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 rewrite over 'CoreExpr' into a rewrite over the left-hand side of a 'CoreExprEquality'.-lhsR :: (AddBindings c, Monad m, ReadPath c Crumb) => Rewrite c m CoreExpr -> Rewrite c m CoreExprEquality+-- | 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- CoreExprEquality vs lhs rhs <- idR+ Equality vs lhs rhs <- idR lhs' <- withVarsInScope vs r <<< return lhs- return $ CoreExprEquality vs lhs' rhs+ return $ Equality vs lhs' rhs --- | Lift a rewrite over 'CoreExpr' into a rewrite over the right-hand side of a 'CoreExprEquality'.-rhsR :: (AddBindings c, Monad m, ReadPath c Crumb) => Rewrite c m CoreExpr -> Rewrite c m CoreExprEquality+-- | 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- CoreExprEquality vs lhs rhs <- idR+ Equality vs lhs rhs <- idR rhs' <- withVarsInScope vs r <<< return rhs- return $ CoreExprEquality vs lhs rhs'+ return $ Equality vs lhs rhs' --- | Lift a rewrite over 'CoreExpr' into a rewrite over both sides of a 'CoreExprEquality'.-bothR :: (AddBindings c, MonadCatch m, ReadPath c Crumb) => Rewrite c m CoreExpr -> Rewrite c m CoreExprEquality+-- | 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 bothR r = lhsR r >+> rhsR r ------------------------------------------------------------------------------ -ppCoreExprEqualityT :: PrettyPrinter -> TransformH CoreExprEquality DocH-ppCoreExprEqualityT pp = do+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)@@ -219,30 +239,30 @@ -- -- TODO: need to know type of 'x' to generate a variable. class BuildEquality a where- mkEquality :: a -> HermitM CoreExprEquality+ mkEquality :: a -> HermitM Equality instance BuildEquality (CoreExpr,CoreExpr) where- mkEquality :: (CoreExpr,CoreExpr) -> HermitM CoreExprEquality- mkEquality (lhs,rhs) = return $ CoreExprEquality [] lhs rhs+ mkEquality :: (CoreExpr,CoreExpr) -> HermitM Equality+ mkEquality (lhs,rhs) = return $ Equality [] lhs rhs instance BuildEquality a => BuildEquality (CoreExpr -> a) where- mkEquality :: (CoreExpr -> a) -> HermitM CoreExprEquality+ mkEquality :: (CoreExpr -> a) -> HermitM Equality mkEquality f = do x <- newIdH "x" (error "need to create a type")- CoreExprEquality bnds lhs rhs <- mkEquality (f (varToCoreExpr x))- return $ CoreExprEquality (x:bnds) lhs rhs+ Equality bnds lhs rhs <- mkEquality (f (varToCoreExpr x))+ return $ Equality (x:bnds) lhs rhs ------------------------------------------------------------------------------ --- | Verify that a 'CoreExprEquality' holds, by applying a rewrite to each side, and checking that the results are equal.-proveCoreExprEqualityT :: forall c m. (AddBindings c, Monad m, ReadPath c Crumb)- => CoreExprEqualityProof c m -> Transform c m CoreExprEquality ()-proveCoreExprEqualityT (l,r) = lhsR l >>> rhsR r >>> verifyCoreExprEqualityT+-- | 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 --- | Verify that the left- and right-hand sides of a 'CoreExprEquality' are alpha equivalent.-verifyCoreExprEqualityT :: Monad m => Transform c m CoreExprEquality ()-verifyCoreExprEqualityT = do- CoreExprEquality _ lhs rhs <- idR+-- | 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." ------------------------------------------------------------------------------@@ -257,7 +277,7 @@ guardMsg (exprAlphaEq targetExpr resultExpr) "result of running proof on lhs of equality does not match rhs of equality." -- | Given two expressions, and a rewrite to apply to each, verify that the resulting expressions are equal.-verifyEqualityCommonTargetT :: MonadCatch m => CoreExpr -> CoreExpr -> CoreExprEqualityProof c m -> Transform c m a ()+verifyEqualityCommonTargetT :: MonadCatch m => CoreExpr -> CoreExpr -> EqualityProof c m -> Transform c m a () verifyEqualityCommonTargetT lhs rhs (l,r) = prefixFailMsg "equality verification failed: " $ do lhsResult <- l <<< return lhs@@ -317,16 +337,14 @@ ------------------------------------------------------------------------------ -- TODO: revisit this for binder re-ordering issue-instantiateDictsR :: RewriteH CoreExprEquality-#if __GLASGOW_HASKELL__ >= 708+instantiateDictsR :: RewriteH Equality instantiateDictsR = prefixFailMsg "Dictionary instantiation failed: " $ do bs <- forallVarsT idR let dArgs = filter (\b -> isId b && isDictTy (varType b)) bs uniqDs = nubBy (\ b1 b2 -> eqType (varType b1) (varType b2)) dArgs guardMsg (not (null uniqDs)) "no universally quantified dictionaries can be instantiated." ds <- forM uniqDs $ \ b -> constT $ do- guts <- getModGuts- (i,bnds) <- liftCoreM $ buildDictionary guts b+ (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 _ -> mkCoreLets bnds (varToCoreExpr i)@@ -344,15 +362,12 @@ then return $ lookup3 b ds else buildSubst b contextfreeT $ instantiateEquality allDs-#else-instantiateDictsR = fail "Dictionaries cannot be instantiated in GHC 7.6"-#endif ------------------------------------------------------------------------------ -alphaEqualityR :: (Var -> Bool) -> (String -> String) -> RewriteH CoreExprEquality+alphaEqualityR :: (Var -> Bool) -> (String -> String) -> RewriteH Equality alphaEqualityR p f = prefixFailMsg "Alpha-renaming binder in equality failed: " $ do- CoreExprEquality bs lhs rhs <- idR+ Equality bs lhs rhs <- idR guardMsg (any p bs) "specified variable is not universally quantified." let (bs',i:vs) = break p bs -- this is safe because we know i is in bs@@ -363,11 +378,11 @@ (subst', vs') = substBndrs subst vs lhs' = substExpr (text "coreExprEquality-lhs") subst' lhs rhs' = substExpr (text "coreExprEquality-rhs") subst' rhs- return $ CoreExprEquality (bs'++(i':vs')) lhs' rhs'+ return $ Equality (bs'++(i':vs')) lhs' rhs' -unshadowEqualityR :: RewriteH CoreExprEquality+unshadowEqualityR :: RewriteH Equality unshadowEqualityR = prefixFailMsg "Unshadowing equality failed: " $ do- c@(CoreExprEquality bs _ _) <- idR+ c@(Equality bs _ _) <- idR bvs <- boundVarsT let visible = unionVarSets [bvs , freeVarsEquality c] ss <- varSetElems <$> detectShadowsM bs visible@@ -375,39 +390,35 @@ let f = freshNameGenAvoiding Nothing . extendVarSet visible andR [ alphaEqualityR (==s) (f s) | s <- reverse ss ] >>> bothR (tryR unshadowExprR) -freeVarsEquality :: CoreExprEquality -> VarSet-freeVarsEquality (CoreExprEquality bs lhs rhs) =+freeVarsEquality :: Equality -> VarSet+freeVarsEquality (Equality bs lhs rhs) = delVarSetList (unionVarSets (map freeVarsExpr [lhs,rhs])) bs ------------------------------------------------------------------------------ -instantiateEqualityVarR :: (Var -> Bool) -> CoreString -> RewriteH CoreExprEquality+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-#if __GLASGOW_HASKELL__ >= 708 | otherwise -> do let (before,_) = break (==b) bs (ty, tvs) <- withVarsInScope before $ parseTypeWithHolesT cs return (Type ty, tvs)-#else- | otherwise -> fail "cannot instantiate type binders in GHC 7.6"-#endif eq <- contextfreeT $ instantiateEqualityVar p e new (_,_) <- return eq >>> bothT lintExprT -- sanity check return eq --- | Instantiate one of the universally quantified variables in a 'CoreExprEquality'.+-- | 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- -> CoreExprEquality -> m CoreExprEquality-instantiateEqualityVar p e new (CoreExprEquality bs lhs rhs)+ -> 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@@ -427,21 +438,68 @@ 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 "coreExprEquality-lhs") subst' lhs- rhs' = substExpr (text "coreExprEquality-rhs") subst' rhs- instantiateEquality (noAdds tvs) $ CoreExprEquality (bs'++new++vs') lhs' rhs'+ lhs' = substExpr (text "equality-lhs") subst' lhs+ rhs' = substExpr (text "equality-rhs") subst' rhs+ instantiateEquality (noAdds tvs) $ Equality (bs'++new++vs') lhs' rhs' noAdds :: [(Var,CoreExpr)] -> [(Var,CoreExpr,[Var])] noAdds ps = [ (v,e,[]) | (v,e) <- ps ] --- | Instantiate a set of universally quantified variables in a 'CoreExprEquality'.+-- | 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])] -> CoreExprEquality -> m CoreExprEquality+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). ------------------------------------------------------------------------------ -discardUniVars :: CoreExprEquality -> CoreExprEquality-discardUniVars (CoreExprEquality _ lhs rhs) = CoreExprEquality [] lhs rhs+discardUniVars :: Equality -> Equality+discardUniVars (Equality _ lhs rhs) = Equality [] lhs rhs++------------------------------------------------------------------------------++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)++------------------------------------------------------------------------------++-- We use sideEffectR because only rewrites generate new state in the Kernel.++insertLemmaR :: (HasLemmas m, Monad m) => LemmaName -> Lemma -> Rewrite c m a+insertLemmaR nm l = sideEffectR $ \ _ _ -> insertLemma nm l++modifyLemmaR :: (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)++markLemmaUsedR :: (HasLemmas m, Monad m) => LemmaName -> Rewrite c m a+markLemmaUsedR nm = modifyLemmaR nm id idR id (const True)++------------------------------------------------------------------------------++lemmaNameToEqualityT :: (HasLemmas m, Monad m) => LemmaName -> Transform c m x Equality+lemmaNameToEqualityT nm = liftM lemmaEq $ getLemmaByNameT nm++-- | @e@ ==> @let v = lhs in e@ (also works in a similar manner at Program nodes)+lemmaLhsIntroR :: LemmaName -> RewriteH Core+lemmaLhsIntroR = lemmaNameToEqualityT >=> eqLhsIntroR++-- | @e@ ==> @let v = rhs in e@ (also works in a similar manner at Program nodes)+lemmaRhsIntroR :: LemmaName -> RewriteH Core+lemmaRhsIntroR = lemmaNameToEqualityT >=> eqRhsIntroR+
src/HERMIT/Dictionary/Rules.hs view
@@ -1,33 +1,31 @@-{-# LANGUAGE CPP, FlexibleContexts #-}+{-# LANGUAGE CPP, DeriveDataTypeable, FlexibleContexts, FlexibleInstances, TypeFamilies #-} module HERMIT.Dictionary.Rules- ( -- * GHC Rewrite Rules and Specialisation- externals- -- ** Rules- , RuleNameString- , ruleR- , rulesR- , ruleToEqualityT- , ruleNameToEqualityT- , getHermitRuleT- , getHermitRulesT- -- , verifyCoreRuleT- -- , verifyRuleT- -- , ruleLhsIntroR- -- , ruleRhsIntroR- -- ** Specialisation- , specConstrR- )-where+ ( -- * GHC Rewrite Rules and Specialisation+ externals+ -- ** Rules+ , RuleName(..)+ , RuleNameListBox(..)+ , ruleR+ , rulesR+ , ruleToEqualityT+ , ruleNameToEqualityT+ , getHermitRuleT+ , getHermitRulesT+ -- ** Specialisation+ , specConstrR+ , specialiseR+ ) where -import IOEnv hiding (liftIO) import qualified SpecConstr import qualified Specialise import Control.Arrow import Control.Monad +import Data.Dynamic (Typeable) import Data.Function (on) import Data.List (deleteFirstsBy,intercalate)+import Data.String (IsString(..)) import HERMIT.Core import HERMIT.Context@@ -36,166 +34,117 @@ import HERMIT.External import HERMIT.GHC -import HERMIT.Dictionary.Common (inScope,callT) import HERMIT.Dictionary.GHC (dynFlagsT)--- import HERMIT.Dictionary.Induction import HERMIT.Dictionary.Kure (anyCallR) import HERMIT.Dictionary.Reasoning hiding (externals)-import HERMIT.Dictionary.Unfold (cleanupUnfoldR)+import HERMIT.Dictionary.Unfold (betaReducePlusR) +import IOEnv hiding (liftIO)+ ------------------------------------------------------------------------ --- | Externals that reflect GHC functions, or are derived from GHC functions.+-- | Externals dealing with GHC rewrite rules. externals :: [External] externals =- [ external "rules-help-list" (rulesHelpListT :: TransformH CoreTC String)- [ "List all the rules in scope." ] .+ Query- , external "rule-help" (ruleHelpT :: RuleNameString -> TransformH CoreTC String)- [ "Display details on the named rule." ] .+ Query- , external "apply-rule" (promoteExprR . ruleR :: RuleNameString -> RewriteH Core)- [ "Apply a named GHC rule" ] .+ Shallow- , external "apply-rules" (promoteExprR . rulesR :: [RuleNameString] -> RewriteH Core)- [ "Apply named GHC rules, succeed if any of the rules succeed" ] .+ Shallow- , external "add-rule" ((\ rule_name id_name -> promoteModGutsR (addCoreBindAsRule rule_name id_name)) :: String -> String -> RewriteH Core)- [ "add-rule \"rule-name\" <id> -- adds a new rule that freezes the right hand side of the <id>"] .+ Introduce- , external "unfold-rule" ((\ nm -> promoteExprR (ruleR nm >>> cleanupUnfoldR)) :: String -> RewriteH Core)- [ "Unfold a named GHC rule" ] .+ Deep .+ Context .+ TODO -- TODO: does not work with rules with no arguments- , external "spec-constr" (promoteModGutsR specConstrR :: RewriteH Core)- [ "Run GHC's SpecConstr pass, which performs call pattern specialization."] .+ Deep- , external "specialise" (promoteModGutsR specialise :: RewriteH Core)- [ "Run GHC's specialisation pass, which performs type and dictionary specialisation."] .+ Deep- ]+ [ external "rule-help" (rulesHelpListT :: TransformH CoreTC String)+ [ "List all the rules in scope." ] .+ Query+ , external "rule-help" (ruleHelpT :: RuleName -> TransformH CoreTC String)+ [ "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)+ [ "Create a lemma from a GHC RULE." ]+ , external "spec-constr" (promoteModGutsR specConstrR :: RewriteH Core)+ [ "Run GHC's SpecConstr pass, which performs call pattern specialization."] .+ Deep+ , external "specialise" (promoteModGutsR specialiseR :: RewriteH Core)+ [ "Run GHC's specialisation pass, which performs type and dictionary specialisation."] .+ Deep+ ] ------------------------------------------------------------------------ -{--lookupRule :: (Activation -> Bool) -- When rule is active- -> IdUnfoldingFun -- When Id can be unfolded- -> InScopeSet- -> Id -> [CoreExpr]- -> [CoreRule] -> Maybe (CoreRule, CoreExpr)--GHC HEAD:-type InScopeEnv = (InScopeSet, IdUnfoldingFun)+newtype RuleName = RuleName String deriving (Eq, Typeable) -lookupRule :: DynFlags -> InScopeEnv- -> (Activation -> Bool) -- When rule is active- -> Id -> [CoreExpr]- -> [CoreRule] -> Maybe (CoreRule, CoreExpr)--}+instance Extern RuleName where+ type Box RuleName = RuleName+ box = id+ unbox = id --- Neil: Commented this out as it's not (currently) used.--- rulesToEnv :: [CoreRule] -> Map.Map String (Rewrite c m CoreExpr)--- rulesToEnv rs = Map.fromList--- [ ( unpackFS (ruleName r), rulesToRewrite c m [r] )--- | r <- rs--- ]+instance IsString RuleName where fromString = RuleName+instance Show RuleName where show (RuleName s) = s -type RuleNameString = String+newtype RuleNameListBox = RuleNameListBox [RuleName] deriving Typeable --- TODO: deprecate this (and related functions) in favor of 'biRuleUnsafeR'-#if __GLASGOW_HASKELL__ > 706-rulesToRewriteH :: (ReadBindings c, HasDynFlags m, MonadCatch m) => [CoreRule] -> Rewrite c m CoreExpr-#else-rulesToRewriteH :: (ReadBindings c, MonadCatch m) => [CoreRule] -> Rewrite c m CoreExpr-#endif-rulesToRewriteH rs = prefixFailMsg "RulesToRewrite failed: " $- withPatFailMsg "rule not matched." $ do- (Var fn, args) <- callT- transform $ \ c e -> do- let in_scope = mkInScopeSet (mkVarEnv [ (v,v) | v <- varSetElems (localFreeVarsExpr e) ])-#if __GLASGOW_HASKELL__ > 706- dflags <- getDynFlags- case lookupRule dflags (in_scope, const NoUnfolding) (const True) fn args [r | r <- rs, ru_fn r == idName fn] of-#else- case lookupRule (const True) (const NoUnfolding) in_scope fn args [r | r <- rs, ru_fn r == idName fn] of-#endif- Nothing -> fail "rule not matched"- Just (r, expr) -> do- let e' = mkApps expr (drop (ruleArity r) args)- if all (inScope c) $ varSetElems $ localFreeVarsExpr e' -- TODO: The problem with this check, is that it precludes the case where this is an intermediate transformation. I can imagine situations where some variables would be out-of-scope at this point, but in scope again after a subsequent transformation.- then return e'- else fail $ unlines ["Resulting expression after rule application contains variables that are not in scope."- ,"This can probably be solved by running the flatten-module command at the top level."]+instance Extern [RuleName] where+ type Box [RuleName] = RuleNameListBox+ box = RuleNameListBox+ unbox (RuleNameListBox l) = l --- | Lookup a rule and attempt to construct a corresponding rewrite.-ruleR :: (ReadBindings c, HasCoreRules c) => RuleNameString -> Rewrite c HermitM CoreExpr-ruleR r = do- theRules <- getHermitRulesT- case lookup r theRules of- Nothing -> fail $ "failed to find rule: " ++ show r ++ ". If you think the rule exists, try running the flatten-module command at the top level."- Just rr -> rulesToRewriteH [rr]+-- | 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) -rulesR :: (ReadBindings c, HasCoreRules c) => [RuleNameString] -> Rewrite c HermitM CoreExpr+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 --- | Return all the RULES (including specialization RULES on binders) currently in scope.-getHermitRulesT :: HasCoreRules c => Transform c HermitM a [(RuleNameString, CoreRule)]+-- | 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 rb <- liftCoreM getRuleBase mgRules <- liftM mg_rules getModGuts hscEnv <- liftCoreM getHscEnv rb' <- liftM eps_rule_base $ liftIO $ runIOEnv () $ readMutVar (hsc_EPS hscEnv)- return [ (unpackFS (ruleName r), r)- | r <- hermitCoreRules c ++ mgRules ++ concat (nameEnvElts rb) ++ concat (nameEnvElts rb')- ]+ let allRules = hermitCoreRules c ++ mgRules ++ concat (nameEnvElts rb) ++ concat (nameEnvElts rb')+ return [ (fromString (unpackFS (ruleName r)), r) | r <- allRules ] -getHermitRuleT :: HasCoreRules c => RuleNameString -> Transform c HermitM a CoreRule+-- | Get a GHC CoreRule by name.+getHermitRuleT :: (HasCoreRules c, HasHermitMEnv m, LiftCoreM m, MonadIO m) => RuleName -> Transform c m a CoreRule getHermitRuleT name = do rulesEnv <- getHermitRulesT case filter ((name ==) . fst) rulesEnv of- [] -> fail ("Rule \"" ++ name ++ "\" not found.")+ [] -> fail $ "failed to find rule: " ++ show name ++ ". If you think the rule exists, "+ ++ "try running the flatten-module command at the top level." [(_,r)] -> return r- _ -> fail ("Rule name \"" ++ name ++ "\" is ambiguous.")+ _ -> fail ("Rule name \"" ++ show name ++ "\" is ambiguous.") -rulesHelpListT :: HasCoreRules c => Transform c HermitM a String+-- | List names of all CoreRules in scope.+rulesHelpListT :: (HasCoreRules c, HasHermitMEnv m, LiftCoreM m, MonadIO m) => Transform c m a String rulesHelpListT = do rulesEnv <- getHermitRulesT- return (intercalate "\n" $ reverse $ map fst rulesEnv)--ruleHelpT :: HasCoreRules c => RuleNameString -> Transform c HermitM a String-ruleHelpT name = showSDoc <$> dynFlagsT <*> ((pprRulesForUser . (:[])) <$> getHermitRuleT name)---- Too much information.--- rulesHelpT :: HasCoreRules c => Transform c HermitM a String--- rulesHelpT = do--- rulesEnv <- getHermitRulesT--- dynFlags <- dynFlagsT--- return $ (show (map fst rulesEnv) ++ "\n") ++--- showSDoc dynFlags (pprRulesForUser $ concatMap snd rulesEnv)+ return (intercalate "\n" $ reverse $ map (show.fst) rulesEnv) -makeRule :: RuleNameString -> Id -> CoreExpr -> CoreRule-makeRule rule_name nm = mkRule True -- auto-generated- False -- local- (mkFastString rule_name)- NeverActive -- because we need to call for these- (varName nm)- []- []+-- | 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] --- TODO: check if a top-level binding-addCoreBindAsRule :: Monad m => RuleNameString -> String -> Rewrite c m ModGuts-addCoreBindAsRule rule_name nm = contextfreeT $ \ modGuts ->- case [ (v,e)- | bnd <- mg_binds modGuts- , (v,e) <- bindToVarExprs bnd- , nm `cmpString2Var` v- ] of- [] -> fail $ "cannot find binding " ++ nm- [(v,e)] -> return $ modGuts { mg_rules = mg_rules modGuts- ++ [makeRule rule_name v e]- }- _ -> fail $ "found multiple bindings for " ++ nm+-- | Build an Equality from a named GHC rewrite rule.+ruleNameToEqualityT :: ( 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 --- | Returns the universally quantified binders, the LHS, and the RHS.-ruleToEqualityT :: (BoundVars c, HasDynFlags m, HasModGuts m, MonadThings m, MonadCatch m) => Transform c m CoreRule CoreExprEquality+-- | 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 $ CoreExprEquality (ru_bndrs r) (mkCoreApps (Var f) (ru_args r)) (ru_rhs r)--ruleNameToEqualityT :: (BoundVars c, HasCoreRules c) => RuleNameString -> Transform c HermitM a CoreExprEquality-ruleNameToEqualityT name = getHermitRuleT name >>> ruleToEqualityT+ f <- lookupId $ ru_fn r+ return $ Equality (ru_bndrs r) (mkCoreApps (Var f) (ru_args r)) (ru_rhs r) ------------------------------------------------------------------------ @@ -207,20 +156,20 @@ rs' <- return e' >>> extractT specRules let specRs = deleteFirstsBy ((==) `on` ru_name) rs' rs guardMsg (notNull specRs) "no rules created."- return e' >>> extractR (repeatR (anyCallR (promoteExprR $ rulesToRewriteH specRs)))+ let applyAllR = extractR+ $ repeatR+ $ anyCallR+ $ promoteExprR+ $ rulesToRewrite specRs+ return e' >>> applyAllR -- | Run GHC's specialisation pass, and apply any rules generated.-specialise :: RewriteH ModGuts-specialise = prefixFailMsg "specialisation failed: " $ do+specialiseR :: RewriteH ModGuts+specialiseR = prefixFailMsg "specialisation failed: " $ do gRules <- arr mg_rules lRules <- extractT specRules -#if __GLASGOW_HASKELL__ <= 706- dflags <- dynFlagsT- guts <- contextfreeT $ liftCoreM . Specialise.specProgram dflags-#else guts <- contextfreeT $ liftCoreM . Specialise.specProgram-#endif lRules' <- return guts >>> extractT specRules -- spec rules on bindings in this module let gRules' = mg_rules guts -- plus spec rules on imported bindings@@ -229,7 +178,7 @@ specRs = gSpecRs ++ lSpecRs guardMsg (notNull specRs) "no rules created." liftIO $ putStrLn $ unlines $ map (unpackFS . ru_name) specRs- return guts >>> extractR (repeatR (anyCallR (promoteExprR $ rulesToRewriteH specRs)))+ return guts >>> extractR (repeatR (anyCallR (promoteExprR $ rulesToRewrite specRs))) -- | Get all the specialization rules on a binding. -- These are created by SpecConstr and other GHC passes.@@ -246,5 +195,13 @@ -- | Find all specialization rules in a Core fragment. specRules :: TransformH Core [CoreRule] specRules = crushtdT $ promoteBindT bindSpecRules++-- | Turn a list of rules into a rewrite which succeeds on the first successful rule.+-- Note: this should only be used for built-in and compiler-generated rules which we assume+-- are correct, because it does not record a lemma obligation for the rules used.+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 ] ------------------------------------------------------------------------
src/HERMIT/Dictionary/Undefined.hs view
@@ -3,6 +3,7 @@ ( -- * Working with Undefined Values -- | Note that many of these operations require 'GHC.Err.undefined' to be explicitly imported if it is not used in the source file. externals+ , buildStrictnessLemmaT , verifyStrictT , mkUndefinedValT , isUndefinedValT@@ -18,12 +19,12 @@ , undefinedCaseR , undefinedCastR , undefinedTickR- )-where+ ) where -import Control.Monad ((>=>))+import Control.Monad ((>=>), liftM) import Control.Monad.IO.Class import Data.Monoid+import Data.String (fromString) import HERMIT.Context import HERMIT.Core@@ -31,6 +32,7 @@ import HERMIT.GHC hiding ((<>)) import HERMIT.Kure import HERMIT.Monad+import HERMIT.Name import HERMIT.Dictionary.Common import HERMIT.Dictionary.GHC (substR)@@ -43,7 +45,7 @@ [ external "replace-current-expr-with-undefined" (promoteExprR replaceCurrentExprWithUndefinedR :: RewriteH Core) [ "Set the current expression to \"undefined\"." ] .+ Shallow .+ Context .+ Unsafe- , external "replace-id-with-undefined" (replaceIdWithUndefined :: String -> RewriteH Core)+ , external "replace-id-with-undefined" (replaceIdWithUndefined :: HermitName -> RewriteH Core) [ "Replace the specified identifier with \"undefined\"." ] .+ Deep .+ Context .+ Unsafe , external "error-to-undefined" (promoteExprR errorToUndefinedR :: RewriteH Core)@@ -79,48 +81,46 @@ ------------------------------------------------------------------------ -undefinedLocation :: String-undefinedLocation = "GHC.Err.undefined"+undefinedLocation :: HermitName+undefinedLocation = fromString "GHC.Err.undefined" --- TODO: will crash if 'undefined' is not used (or explicitly imported) in the source file.-findUndefinedIdT :: (BoundVars c, MonadCatch m, HasModGuts m, HasHscEnv m, MonadIO m, MonadThings m) => Transform c m a Id+findUndefinedIdT :: (BoundVars c, MonadCatch m, HasHermitMEnv m, HasHscEnv m, MonadIO m, MonadThings m) => Transform c m a Id findUndefinedIdT = findIdT undefinedLocation -- | Check if the current expression is an undefined value.-isUndefinedValT :: (BoundVars c, MonadCatch m, HasModGuts m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Transform c m CoreExpr ()+isUndefinedValT :: (BoundVars c, MonadCatch m, HasHermitMEnv m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Transform c m CoreExpr () isUndefinedValT = prefixFailMsg "not an undefined value: " $ withPatFailMsg (wrongExprForm "App (Var undefined) (Type ty)") $ do App (Var un) (Type _) <- idR un' <- findUndefinedIdT- guardMsg (un == un') ("identifier is not " ++ undefinedLocation)+ guardMsg (un == un') ("identifier is not " ++ show undefinedLocation) ------------------------------------------------------------------------ -errorLocation :: String-errorLocation = "GHC.Err.error"+errorLocation :: HermitName+errorLocation = fromString "GHC.Err.error" --- TODO: will crash if 'error' is not used (or explicitly imported) in the source file.-findErrorIdT :: (BoundVars c, MonadCatch m, HasModGuts m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Transform c m a Id+findErrorIdT :: (BoundVars c, MonadCatch m, HasHermitMEnv m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Transform c m a Id findErrorIdT = findIdT errorLocation -- | Check if the current expression is an undefined value.-isErrorValT :: (BoundVars c, MonadCatch m, HasModGuts m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Transform c m CoreExpr ()+isErrorValT :: (BoundVars c, MonadCatch m, HasHermitMEnv m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Transform c m CoreExpr () isErrorValT = prefixFailMsg "not an error value: " $ withPatFailMsg (wrongExprForm "App (App (Var error) (Type ty)) string") $ do App (App (Var er) (Type _)) _ <- idR er' <- findErrorIdT- guardMsg (er == er') ("identifier is not " ++ errorLocation)+ guardMsg (er == er') ("identifier is not " ++ show errorLocation) ------------------------------------------------------------------------ -- | error ty string ==> undefined ty-errorToUndefinedR :: (BoundVars c, MonadCatch m, HasModGuts m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr+errorToUndefinedR :: (BoundVars c, MonadCatch m, HasHermitMEnv m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr errorToUndefinedR = prefixFailMsg "error-to-undefined failed: " (isErrorValT >> replaceCurrentExprWithUndefinedR) ------------------------------------------------------------------------ -- | Make an undefined value of the given type.-mkUndefinedValT :: (BoundVars c, MonadCatch m, HasModGuts m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Type -> Transform c m a CoreExpr+mkUndefinedValT :: (BoundVars c, MonadCatch m, HasHermitMEnv m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Type -> Transform c m a CoreExpr mkUndefinedValT ty = do un <- findUndefinedIdT return $ App (varToCoreExpr un) (Type ty)@@ -128,67 +128,67 @@ ------------------------------------------------------------------------------------------------------ -- | Set the current expression to 'undefined'.-replaceCurrentExprWithUndefinedR :: (BoundVars c, MonadCatch m, HasModGuts m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr+replaceCurrentExprWithUndefinedR :: (BoundVars c, MonadCatch m, HasHermitMEnv m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr replaceCurrentExprWithUndefinedR = contextfreeT exprTypeM >>= mkUndefinedValT -- | Replace all occurrences of the specified identifier with 'undefined'.-replaceIdWithUndefinedR :: (BoundVars c, MonadCatch m, HasModGuts m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Id -> Rewrite c m Core+replaceIdWithUndefinedR :: (BoundVars c, MonadCatch m, HasHermitMEnv m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Id -> Rewrite c m Core replaceIdWithUndefinedR i = mkUndefinedValT (idType i) >>= substR i -replaceIdWithUndefined :: (BoundVars c, MonadCatch m, HasModGuts m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => String -> Rewrite c m Core+replaceIdWithUndefined :: (BoundVars c, MonadCatch m, HasHermitMEnv m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => HermitName -> Rewrite c m Core replaceIdWithUndefined = findIdT >=> replaceIdWithUndefinedR ------------------------------------------------------------------------------------------------------ -- | undefinedExprR = undefinedAppR <+ undefinedLamR <+ undefinedLetR <+ undefinedCastR <+ undefinedTickR <+ undefinedCaseR-undefinedExprR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb, MonadCatch m, HasModGuts m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr+undefinedExprR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb, MonadCatch m, HasHermitMEnv m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr undefinedExprR = setFailMsg "undefined-expr failed." (undefinedAppR <+ undefinedLamR <+ undefinedLetR <+ undefinedCastR <+ undefinedTickR <+ undefinedCaseR) ------------------------------------------------------------------------------------------------------ -- | @(undefined ty1) e@ ==> @undefined ty2@-undefinedAppR :: (BoundVars c, ExtendPath c Crumb, MonadCatch m, HasModGuts m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr+undefinedAppR :: (BoundVars c, ExtendPath c Crumb, MonadCatch m, HasHermitMEnv m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr undefinedAppR = prefixFailMsg "undefined-app failed: " $ do appT isUndefinedValT successT (<>) replaceCurrentExprWithUndefinedR -- | @(\ v -> undefined ty1)@ ==> @undefined ty2@ (where v is not a 'TyVar')-undefinedLamR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb, MonadCatch m, HasModGuts m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr+undefinedLamR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb, MonadCatch m, HasHermitMEnv m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr undefinedLamR = prefixFailMsg "undefined-lam failed: " $ do lamT successT isUndefinedValT (<>) replaceCurrentExprWithUndefinedR -- | let bds in (undefined ty) ==> undefined ty-undefinedLetR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb, MonadCatch m, HasModGuts m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr+undefinedLetR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb, MonadCatch m, HasHermitMEnv m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr undefinedLetR = prefixFailMsg "undefined-let failed: " $ do letT successT isUndefinedValT (<>) replaceCurrentExprWithUndefinedR -- | Cast (undefined ty1) co ==> undefined ty2-undefinedCastR :: (BoundVars c, ExtendPath c Crumb, MonadCatch m, HasModGuts m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr+undefinedCastR :: (BoundVars c, ExtendPath c Crumb, MonadCatch m, HasHermitMEnv m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr undefinedCastR = prefixFailMsg "undefined-cast failed: " $ do castT isUndefinedValT successT (<>) replaceCurrentExprWithUndefinedR -- | Tick tick (undefined ty1) ==> undefined ty1-undefinedTickR :: (BoundVars c, ExtendPath c Crumb, MonadCatch m, HasModGuts m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr+undefinedTickR :: (BoundVars c, ExtendPath c Crumb, MonadCatch m, HasHermitMEnv m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr undefinedTickR = prefixFailMsg "undefined-tick failed: " $ do tickT successT isUndefinedValT (<>) replaceCurrentExprWithUndefinedR -- | undefinedCaseR = undefinedCaseScrutineeR <+ undefinedCaseAltsR-undefinedCaseR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb, MonadCatch m, HasModGuts m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr+undefinedCaseR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb, MonadCatch m, HasHermitMEnv m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr undefinedCaseR = setFailMsg "undefined-case failed" (undefinedCaseScrutineeR <+ undefinedCaseAltsR) -- | case (undefined ty) of alts ==> undefined ty-undefinedCaseScrutineeR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb, MonadCatch m, HasModGuts m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr+undefinedCaseScrutineeR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb, MonadCatch m, HasHermitMEnv m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr undefinedCaseScrutineeR = prefixFailMsg "undefined-case failed: " $ do caseT isUndefinedValT successT successT (const successT) (\ _ _ _ _ -> ()) replaceCurrentExprWithUndefinedR -- | case e of {pat_1 -> undefined ty ; pat_2 -> undefined ty ; ... ; pat_n -> undefined ty} ==> undefined ty-undefinedCaseAltsR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb, MonadCatch m, HasModGuts m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr+undefinedCaseAltsR :: (AddBindings c, BoundVars c, ExtendPath c Crumb, ReadPath c Crumb, MonadCatch m, HasHermitMEnv m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => Rewrite c m CoreExpr undefinedCaseAltsR = prefixFailMsg "undefined-case-alts failed: " $ do caseAltT successT successT successT (const (successT,const successT,isUndefinedValT)) (\ _ _ _ _ -> ()) replaceCurrentExprWithUndefinedR@@ -196,12 +196,30 @@ ------------------------------------------------------------------------ -- | Verify that the given rewrite is a proof that the given expression is a strict function.-verifyStrictT :: (BoundVars c, MonadCatch m, HasModGuts m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => CoreExpr -> Rewrite c m CoreExpr -> Transform c m a ()+verifyStrictT :: (BoundVars c, MonadCatch m, HasHermitMEnv m, HasDynFlags m, HasHscEnv m, MonadIO m, MonadThings m) => CoreExpr -> Rewrite c m CoreExpr -> Transform c m a () verifyStrictT f r = prefixFailMsg "strictness verification failed: " $- do (argTy, resTy) <- constT (funExprArgResTypes f)+ do (_, argTy, resTy) <- constT (funExprArgResTypesM f) undefArg <- mkUndefinedValT argTy rhs <- mkUndefinedValT resTy let lhs = App f undefArg verifyEqualityLeftToRightT lhs rhs r++-- | Apply the given expression to undefined, at the proper type.+applyToUndefinedT :: (BoundVars c, HasDynFlags m, HasHscEnv m, HasHermitMEnv m, MonadCatch m, MonadIO m, MonadThings m)+ => CoreExpr -> Transform c m x CoreExpr+applyToUndefinedT f = do+ let (tvs, body) = collectTyBinders f+ (_,dom,_) <- splitFunTypeM (exprType body)+ undef <- mkUndefinedValT dom+ return $ mkCoreLams tvs $ mkCoreApp body undef++-- | 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+ (tvs, lhs) <- liftM collectTyBinders $ applyToUndefinedT f+ rhs <- mkUndefinedValT (exprType lhs)+ constT $ insertLemma nm $ Lemma (Equality tvs lhs rhs) False True ------------------------------------------------------------------------
src/HERMIT/Dictionary/Unfold.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE FlexibleContexts, ScopedTypeVariables, TupleSections, LambdaCase #-} module HERMIT.Dictionary.Unfold ( externals- , cleanupUnfoldR+ , betaReducePlusR , rememberR , showStashT , unfoldR@@ -22,15 +22,16 @@ import HERMIT.PrettyPrinter.Common (DocH, PrettyH, TransformDocH(..), PrettyC) import HERMIT.Dictionary.Common+import HERMIT.Dictionary.GHC (substCoreExpr) import HERMIT.Dictionary.Inline (inlineR)-import HERMIT.Dictionary.Local.Let (letNonRecSubstR) import HERMIT.Core import HERMIT.Context-import HERMIT.Kure-import HERMIT.Monad import HERMIT.External import HERMIT.GHC+import HERMIT.Kure+import HERMIT.Monad+import HERMIT.Name import Prelude hiding (exp) @@ -40,17 +41,17 @@ externals :: [External] externals =- [ external "cleanup-unfold" (promoteExprR cleanupUnfoldR :: RewriteH Core)- [ "Clean up immediately nested fully-applied lambdas, from the bottom up" ] .+ Deep- , external "remember" (rememberR :: Label -> RewriteH Core)+ [ external "beta-reduce-plus" (promoteExprR betaReducePlusR :: RewriteH Core)+ [ "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 :: String -> RewriteH Core)+ , external "unfold-remembered" (promoteExprR . unfoldStashR :: RememberedName -> RewriteH Core) [ "Unfold a remembered definition." ] .+ Deep .+ Context , external "unfold" (promoteExprR unfoldR :: RewriteH Core) [ "In application f x y z, unfold f." ] .+ Deep .+ Context- , external "unfold" (promoteExprR . unfoldNameR :: String -> RewriteH Core)+ , external "unfold" (promoteExprR . unfoldNameR . unOccurrenceName :: OccurrenceName -> RewriteH Core) [ "Inline a definition, and apply the arguments; traditional unfold." ] .+ Deep .+ Context- , external "unfold" (promoteExprR . unfoldNamesR :: [String] -> RewriteH Core)+ , external "unfold" (promoteExprR . unfoldNamesR . map unOccurrenceName:: [OccurrenceName] -> RewriteH Core) [ "Unfold a definition if it is named in the list." ] .+ Deep .+ Context , external "unfold-saturated" (promoteExprR unfoldSaturatedR :: RewriteH Core) [ "Unfold a definition only if the function is fully applied." ] .+ Deep .+ Context@@ -62,44 +63,41 @@ ------------------------------------------------------------------------ --- | cleanupUnfoldR cleans a unfold operation--- (for example, an inline or rule application)--- It is used at the level of the top-redex.--- Invariant: will not introduce let bindings-cleanupUnfoldR :: (AddBindings c, ExtendPath c Crumb, MonadCatch m) => Rewrite c m CoreExpr-cleanupUnfoldR = do- (f, args) <- callT <+ arr (,[])- let (vs, body) = collectBinders f- lenargs = length args- lenvs = length vs- comp = compare lenargs lenvs- body' = case comp of- LT -> mkCoreLams (drop lenargs vs) body- _ -> body- bnds = zipWith NonRec vs args- body'' <- andR (replicate (length bnds) letNonRecSubstR) <<< return (mkCoreLets bnds body')- return $ case comp of- GT -> mkCoreApps body'' $ drop lenvs args- _ -> body''+-- | Perform one or more beta reductions.+betaReducePlusR :: MonadCatch m => Rewrite c m CoreExpr+betaReducePlusR = prefixFailMsg "Multi-beta-reduction failed: " $ do+ (f,args) <- callT+ let (f',args',atLeastOne) = reduceAll f args False+ reduceAll (Lam v body) (a:as) _ = reduceAll (substCoreExpr v a body) as True+ reduceAll e as b = (e,as,b)+ guardMsg atLeastOne "no beta reductions possible."+ return $ mkCoreApps f' args' -- | A more powerful 'inline'. Matches two cases: -- Var ==> inlines -- App ==> inlines the head of the function call for the app tree-unfoldR :: forall c. (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => Rewrite c HermitM CoreExpr-unfoldR = prefixFailMsg "unfold failed: " (go >>> cleanupUnfoldR)- where go :: Rewrite c HermitM CoreExpr+unfoldR :: forall c m. ( AddBindings c, ExtendPath c Crumb, HasEmptyContext c+ , ReadBindings c, ReadPath c Crumb, MonadCatch m )+ => Rewrite c m CoreExpr+unfoldR = prefixFailMsg "unfold failed: " (go >>> tryR betaReducePlusR)+ where go :: Rewrite c m CoreExpr go = appAllR go idR <+ inlineR -- this order gives better error messages -unfoldPredR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => (Id -> [CoreExpr] -> Bool) -> Rewrite c HermitM CoreExpr+unfoldPredR :: ( AddBindings c, ExtendPath c Crumb, HasEmptyContext c, ReadBindings c, ReadPath c Crumb+ , MonadCatch m )+ => (Id -> [CoreExpr] -> Bool) -> Rewrite c m CoreExpr unfoldPredR p = callPredT p >> unfoldR -unfoldNameR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => String -> Rewrite c HermitM CoreExpr-unfoldNameR nm = prefixFailMsg ("unfold '" ++ nm ++ " failed: ") (callNameT nm >> unfoldR)+unfoldNameR :: ( ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c+ , MonadCatch m )+ => HermitName -> Rewrite c m CoreExpr+unfoldNameR nm = prefixFailMsg ("unfold '" ++ show nm ++ " failed: ") (callNameT nm >> unfoldR) -unfoldNamesR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => [String] -> Rewrite c HermitM CoreExpr+unfoldNamesR :: ( ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c+ , MonadCatch m )+ => [HermitName] -> Rewrite c m CoreExpr unfoldNamesR [] = fail "unfold-names failed: no names given."-unfoldNamesR nms = setFailMsg "unfold-names failed." $- orR (map unfoldNameR nms)+unfoldNamesR nms = setFailMsg "unfold-names failed." $ orR (map unfoldNameR nms) unfoldSaturatedR :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, ReadBindings c, HasEmptyContext c) => Rewrite c HermitM CoreExpr unfoldSaturatedR = callSaturatedT >> unfoldR@@ -112,7 +110,7 @@ -- | Stash a binding with a name for later use. -- Allows us to look at past definitions.-rememberR :: Label -> Rewrite c HermitM Core+rememberR :: RememberedName -> Rewrite c HermitM Core rememberR label = sideEffectR $ \ _ -> \case DefCore def -> saveDef label def BindCore (NonRec i e) -> saveDef label (Def i e)@@ -128,7 +126,7 @@ -- _ -> fail "remember: not a binding" -- | Apply a stashed definition (like inline, but looks in stash instead of context).-unfoldStashR :: ReadBindings c => String -> Rewrite c HermitM CoreExpr+unfoldStashR :: ReadBindings c => RememberedName -> Rewrite c HermitM CoreExpr unfoldStashR label = prefixFailMsg "Inlining stashed definition failed: " $ withPatFailMsg (wrongExprForm "Var v") $ do (c, Var v) <- exposeT@@ -139,12 +137,12 @@ 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 " ++ var2String i ++ " not " ++ var2String v+ 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 $ apply (extractT pp) pctx d- return $ PP.text ("[ " ++ l ++ " ]") PP.$+$ dfn PP.$+$ PP.space+ 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
@@ -20,10 +20,10 @@ externals :: [External] externals = map (.+ Unsafe) [ external "unsafe-replace" (promoteExprR . unsafeReplaceR :: CoreString -> RewriteH Core)- [ "replace the currently focused expression with a new expression" + [ "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 :: String -> RewriteH Core)- [ "replace the currently focused expression with an expression from the stash"+ , 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" ] ] @@ -36,7 +36,7 @@ guardMsg (eqType (exprKindOrType e) (exprKindOrType e')) "expression types differ." return e' -unsafeReplaceStashR :: String -> RewriteH CoreExpr+unsafeReplaceStashR :: RememberedName -> RewriteH CoreExpr unsafeReplaceStashR label = prefixFailMsg "unsafe-replace failed: " $ contextfreeT $ \ e -> do Def _ rhs <- lookupDef label
src/HERMIT/Dictionary/WorkerWrapper/Common.hs view
@@ -1,12 +1,82 @@-module HERMIT.Dictionary.WorkerWrapper.Common where+{-# LANGUAGE CPP, DeriveDataTypeable, TypeFamilies #-}+module HERMIT.Dictionary.WorkerWrapper.Common+ ( externals+ , WWAssumptionTag(..)+ , WWAssumption(..)+ , assumptionAEqualityT+ , assumptionBEqualityT+ , assumptionCEqualityT+ , split1BetaR+ , split2BetaR+ , workLabel+ ) where -import HERMIT.Monad-import HERMIT.Kure+import Control.Monad.IO.Class++import Data.String (fromString)+import Data.Typeable++import HERMIT.Context+import HERMIT.Core+import HERMIT.External import HERMIT.GHC+import HERMIT.Kure+import HERMIT.Monad+import HERMIT.ParserCore +import HERMIT.Dictionary.Common+import HERMIT.Dictionary.Function hiding (externals)+import HERMIT.Dictionary.Reasoning hiding (externals)+import HERMIT.Name+ -------------------------------------------------------------------------------------------------- -data WWAssumptionTag = A | B | C deriving (Eq,Ord,Show,Read)+-- | New Worker/Wrapper-related externals.+externals :: [External]+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)+ [ "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)+ [ "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)+ [ "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)+ [ "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)+ [ "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."+ , " <name>-assumption: unproven lemma for w/w assumption C."+ , " <name>-fusion: assumed lemma for w/w fusion."+ ]+ ]++--------------------------------------------------------------------------------------------------++data WWAssumptionTag = A | B | C deriving (Eq,Ord,Show,Read,Typeable)++instance Extern WWAssumptionTag where+ type Box WWAssumptionTag = WWAssumptionTag+ box i = i+ unbox i = i+ data WWAssumption = WWAssumption WWAssumptionTag (RewriteH CoreExpr) --------------------------------------------------------------------------------------------------@@ -17,7 +87,94 @@ -- 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 :: Label-workLabel = "recursive-definition-of-work-for-use-by-ww-fusion"+workLabel :: RememberedName+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+ , MonadCatch m, MonadIO m, MonadThings m )+ => CoreExpr -> CoreExpr -> Transform c m x Equality+assumptionAEqualityT 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++-- Given abs, rep, and f expressions, build "abs . rep . f = f"+assumptionBEqualityT :: ( BoundVars c, HasDynFlags m, 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+ 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++-- 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+ lhs' <- buildFixT lhs+ rhs' <- buildFixT rhs+ return $ Equality vs 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+ 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++-- 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+ , MonadCatch m, MonadIO m, MonadThings m, MonadUnique m )+ => LemmaName -> CoreExpr -> CoreExpr -> Rewrite c m CoreExpr+split1BetaR nm absE repE = do+ (_fixId, [_tyA, f]) <- callNameT $ fromString "Data.Function.fix"++ g <- 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)++ assumptionEq <- assumptionCEqualityT absE repE f+ _ <- insertLemmaR (fromString (show nm ++ "-assumption")) $ Lemma assumptionEq False True -- unproven, used++ wwFusionEq <- wwFusionEqualityT absE repE workRhs+ _ <- insertLemmaR (fromString (show nm ++ "-fusion")) $ Lemma wwFusionEq True False -- proven (assumed), unused++ return $ mkCoreLets [NonRec gId g, NonRec workId workRhs] newRhs++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+split2BetaR nm absE repE = do+ (_fixId, [_tyA, f]) <- callNameT $ fromString "Data.Function.fix"+ fixfE <- idR++ repFixFE <- buildApplicationM repE fixfE+ workId <- constT $ newIdH "worker" $ exprType repFixFE++ newRhs <- buildApplicationM absE (varToCoreExpr workId)++ assumptionEq <- assumptionCEqualityT absE repE f+ _ <- insertLemmaR (fromString (show nm ++ "-assumption")) $ Lemma assumptionEq False True -- unproven, used++ wwFusionEq <- wwFusionEqualityT absE repE (varToCoreExpr workId)+ _ <- insertLemmaR (fromString (show nm ++ "-fusion")) $ Lemma wwFusionEq True False -- proven (assumed), unused++ return $ mkCoreLets [NonRec workId repFixFE] newRhs
src/HERMIT/Dictionary/WorkerWrapper/Fix.hs view
@@ -1,28 +1,30 @@ module HERMIT.Dictionary.WorkerWrapper.Fix- ( -- * The Worker/Wrapper Transformation- -- | Note that many of these operations require 'Data.Function.fix' to be in scope.- HERMIT.Dictionary.WorkerWrapper.Fix.externals- , wwFacBR- , wwSplitR- , wwSplitStaticArg- , wwGenerateFusionR- , wwFusionBR- , wwAssA- , wwAssB- , wwAssC- )-where+ ( -- * The Worker/Wrapper Transformation+ -- | Note that many of these operations require 'Data.Function.fix' to be in scope.+ HERMIT.Dictionary.WorkerWrapper.Fix.externals+ , wwFacBR+ , wwSplitR+ , wwSplitStaticArg+ , wwGenerateFusionR+ , wwFusionBR+ , wwAssA+ , wwAssB+ , wwAssC+ ) where import Control.Applicative import Control.Arrow +import Data.String (fromString)+ import HERMIT.Core-import HERMIT.Monad-import HERMIT.Kure import HERMIT.External import HERMIT.GHC-import HERMIT.Utilities+import HERMIT.Kure+import HERMIT.Monad+import HERMIT.Name import HERMIT.ParserCore+import HERMIT.Utilities import HERMIT.Dictionary.AlphaConversion import HERMIT.Dictionary.Common@@ -171,7 +173,7 @@ guardMsg (eqType tyA tA) ("wrapper/unwrapper types do not match fix body type.") whenJust (verifyWWAss wrap unwrap f) mAss b <- constT (newIdH "x" tyB)- App wrap <$> mkFixT (Lam b (App unwrap (App f (App wrap (Var b)))))+ App wrap <$> buildFixT (Lam b (App unwrap (App f (App wrap (Var b))))) wwR :: RewriteH CoreExpr wwR = prefixFailMsg "(reverse) worker/wrapper factorisation failed: " $@@ -183,7 +185,7 @@ guardMsg (equivalentBy exprAlphaEq [wrap, wrap1, wrap2]) "wrappers do not match." guardMsg (exprAlphaEq unwrap unwrap1) "unwrappers do not match." whenJust (verifyWWAss wrap unwrap f) mAss- mkFixT f+ buildFixT f wrongFixBody :: String wrongFixBody = "body of fix does not have the form Lam b (App unwrap (App f (App wrap (Var b))))"@@ -251,11 +253,11 @@ -- | \\ wrap unwrap -> (@prog = expr@ ==> @prog = let f = \\ prog -> expr in let work = unwrap (f (wrap work)) in wrap work)@ wwSplitR :: Maybe WWAssumption -> CoreExpr -> CoreExpr -> RewriteH CoreDef wwSplitR mAss wrap unwrap =- fixIntroR+ fixIntroRecR >>> defAllR idR ( appAllR idR (letIntroR "f") >>> letFloatArgR >>> letAllR idR ( forwardT (wwFacBR mAss wrap unwrap)- >>> appAllR idR ( unfoldNameR "fix"+ >>> appAllR idR ( unfoldNameR (fromString "Data.Function.fix") >>> alphaLetWithR ["work"] >>> letRecAllR (\ _ -> defAllR idR (betaReduceR >>> letNonRecSubstR) >>> extractR (wwGenerateFusionR mAss)@@ -440,8 +442,8 @@ prefixFailMsg ("verification of worker/wrapper assumption C failed: ") $ do (tyA,_) <- wrapUnwrapTypes wrap unwrap a <- constT (newIdH "a" tyA)- rhs <- mkFixT f- lhs <- mkFixT (Lam a (App wrap (App unwrap (App f (Var a)))))+ rhs <- buildFixT f+ lhs <- buildFixT (Lam a (App wrap (App unwrap (App f (Var a))))) verifyEqualityLeftToRightT lhs rhs assC --------------------------------------------------------------------------------------------------
src/HERMIT/Dictionary/WorkerWrapper/FixResult.hs view
@@ -1,31 +1,33 @@ {-# LANGUAGE TupleSections #-} module HERMIT.Dictionary.WorkerWrapper.FixResult- ( -- * The Worker/Wrapper Transformation (Result Variant)- -- | Note that many of these operations require 'Data.Function.fix' to be in scope.- HERMIT.Dictionary.WorkerWrapper.FixResult.externals- , wwResultFacBR- , wwResultSplitR- , wwResultSplitStaticArg- , wwResultGenerateFusionR- , wwResultFusionBR- , wwResultAssA- , wwResultAssB- , wwResultAssC- )-where+ ( -- * The Worker/Wrapper Transformation (Result Variant)+ -- | Note that many of these operations require 'Data.Function.fix' to be in scope.+ HERMIT.Dictionary.WorkerWrapper.FixResult.externals+ , wwResultFacBR+ , wwResultSplitR+ , wwResultSplitStaticArg+ , wwResultGenerateFusionR+ , wwResultFusionBR+ , wwResultAssA+ , wwResultAssB+ , wwResultAssC+ ) where import Prelude hiding (abs) import Control.Arrow +import Data.String (fromString)+ import HERMIT.Core-import HERMIT.Monad-import HERMIT.Kure import HERMIT.External import HERMIT.GHC-import HERMIT.Utilities+import HERMIT.Kure+import HERMIT.Monad+import HERMIT.Name import HERMIT.ParserCore+import HERMIT.Utilities import HERMIT.Dictionary.AlphaConversion import HERMIT.Dictionary.Common@@ -172,7 +174,7 @@ wwL :: Type -> Type -> RewriteH CoreExpr wwL tyA tyB = prefixFailMsg "worker/wrapper factorisation failed: " $ do (tyXA,f) <- isFixExprT- (tyX,tA) <- constT (splitFunTypeM tyXA)+ (_,tyX,tA) <- constT (splitFunTypeM tyXA) let tyXB = FunTy tyX tyB h <- constT (newIdH "h" tyXB) guardMsg (eqType tyA tA) ("abs/rep types do not match fix body type.")@@ -182,7 +184,7 @@ whenJust (verifyWWAss abs rep f) mAss - work <- mkFixT (Lam h (Lam x1 (App rep+ work <- buildFixT (Lam h (Lam x1 (App rep (App (App f (Lam x2 (App abs (App (Var h) (Var x2))))) (Var x1) )@@ -203,7 +205,7 @@ guardMsg (equivalentBy exprAlphaEq [abs, abs1, abs2]) "abs's do not match." guardMsg (exprAlphaEq rep rep1) "rep's do not match." whenJust (verifyWWAss abs rep f) mAss- mkFixT f+ buildFixT f wrongForm :: String wrongForm = wrongExprForm "\\ x1 -> abs (fix (\\ h x2 -> rep (f (\\ x3 -> abs (h x3)) x2)) x1)"@@ -282,11 +284,11 @@ -- | \\ abs rep -> (@prog = expr@ ==> @prog = let f = \\ prog -> expr in let work = \\ x1 -> rep (f (\\ x2 -> abs (work x2)) x1) in \\ x0 -> abs (work x0)@) wwResultSplitR :: Maybe WWAssumption -> CoreExpr -> CoreExpr -> RewriteH CoreDef wwResultSplitR mAss abs rep =- fixIntroR+ fixIntroRecR >>> defAllR idR ( appAllR idR (letIntroR "f") >>> letFloatArgR >>> letAllR idR ( forwardT (wwResultFacBR mAss abs rep)- >>> lamAllR idR (appAllR idR (appAllR ( unfoldNameR "fix"+ >>> lamAllR idR (appAllR idR (appAllR ( unfoldNameR (fromString "Data.Function.fix") >>> alphaLetWithR ["work"] >>> letRecAllR (\ _ -> defAllR idR (betaReduceR >>> letNonRecSubstR) >>> extractR (wwResultGenerateFusionR mAss)@@ -461,9 +463,9 @@ -> TransformH x () verifyAssB abs rep f assB = prefixFailMsg ("verification of worker/wrapper assumption B failed: ") $- do (tyA,_) <- absRepTypes abs rep- tyXA <- constT (endoFunExprType f)- (tyX,tA) <- constT (splitFunTypeM tyXA)+ do (tyA,_) <- absRepTypes abs rep+ (_,tyXA) <- constT (endoFunExprTypeM f)+ (_,tyX,tA) <- constT (splitFunTypeM tyXA) guardMsg (eqType tyA tA) "type of program body does not match types of abs/rep." h <- constT (newIdH "h" tyXA) x <- constT (newIdH "x" tyX)@@ -478,14 +480,14 @@ -> TransformH a () verifyAssC abs rep f assC = prefixFailMsg ("verification of worker/wrapper assumption C failed: ") $- do (tyA,_) <- absRepTypes abs rep- tyXA <- constT (endoFunExprType f)- (tyX,tA) <- constT (splitFunTypeM tyXA)+ do (tyA,_) <- absRepTypes abs rep+ (_,tyXA) <- constT (endoFunExprTypeM f)+ (_,tyX,tA) <- constT (splitFunTypeM tyXA) guardMsg (eqType tyA tA) "type of program body does not match types of abs/rep." h <- constT (newIdH "h" tyXA) x <- constT (newIdH "x" tyX)- rhs <- mkFixT f- lhs <- mkFixT (Lam h (Lam x (App abs (App rep (App (App f (Var h)) (Var x))))))+ rhs <- buildFixT f+ lhs <- buildFixT (Lam h (Lam x (App abs (App rep (App (App f (Var h)) (Var x)))))) verifyEqualityLeftToRightT lhs rhs assC --------------------------------------------------------------------------------------------------
src/HERMIT/Driver.hs view
@@ -1,9 +1,10 @@ {-# LANGUAGE ViewPatterns #-}-module HERMIT.Driver +module HERMIT.Driver ( hermitVersion , ghcFlags , hermitDriver , usage+ , usageOutput ) where import Data.List (isPrefixOf, partition)@@ -14,7 +15,7 @@ import System.Process import System.Exit -hermitVersion :: String +hermitVersion :: String hermitVersion = "HERMIT v" ++ showVersion P.version ghcFlags :: [String]@@ -26,11 +27,9 @@ -- , "-v0" ] -usage :: IO ()-usage = putStrLn $ unlines- [hermitVersion- ,""- ,"usage: hermit File.hs SCRIPTNAME"+usageOutput :: String+usageOutput = unlines+ ["usage: hermit File.hs SCRIPTNAME" ," - OR -" ," hermit File.hs [HERMIT_ARGS] [+module_name [MOD_ARGS]]* [-- [ghc-args]]" ,""@@ -45,6 +44,7 @@ ,"" ,"HERMIT_ARGS" ," -opt=MODULE : where MODULE is the module containing a HERMIT optimization plugin"+ ," -pN : where 0<=N<=17 is the stage in the optimization pipeline HERMIT targets" ," -vN : controls verbosity, where N is one of the following values:" ," 0 : suppress HERMIT messages, pass -v0 to GHC" ," 1 : suppress HERMIT messages"@@ -56,7 +56,10 @@ ," resume : skip interactive mode and resume compilation after any scripts" ] --- | Entry point for HERMIT driver executable. +usage :: IO ()+usage = mapM_ putStrLn [hermitVersion, "", usageOutput]++-- | Entry point for HERMIT driver executable. -- First String in list is expected to be target file name. hermitDriver :: [String] -> IO () hermitDriver [] = usage
src/HERMIT/External.hs view
@@ -1,54 +1,52 @@ {-# LANGUAGE GADTs, TypeFamilies, FlexibleContexts, FlexibleInstances, DeriveDataTypeable #-} module HERMIT.External- (- -- * Externals- External- , ExternalName- , ExternalHelp- , externName- , externDyn- , externHelp- , externTypeString- , externTypeArgResString- , Dictionary- , toDictionary- , addToDictionary- , toHelp- , external- , Extern(..)- , matchingExternals- -- * Tags- , CmdTag(..)- , TagE- , Tag((.+),remTag,tagMatch)- , (.&)- , (.||)- , notT- , externTags- , dictionaryOfTags- -- * Boxes- -- | Boxes are used by the 'Extern' class.- , TagBox(..)- , IntBox(..)- , RewriteCoreBox(..)- , RewriteCoreTCBox(..)- , BiRewriteCoreBox(..)- , TransformCoreStringBox(..)- , TransformCoreTCStringBox(..)- , TransformCoreCheckBox(..)- , TransformCoreTCCheckBox(..)- , TransformCorePathBox(..)- , TransformCoreTCPathBox(..)- , CoreString(..)- , CoreBox(..)- , CrumbBox(..)- , PathBox(..)- , StringBox(..)- , StringListBox(..)- , IntListBox(..)- , RewriteCoreListBox(..)-) where+ ( -- * Externals+ External+ , ExternalName+ , ExternalHelp+ , externName+ , externDyn+ , externHelp+ , externTypeString+ , externTypeArgResString+ , splitFunTyArgs+ , toHelp+ , external+ , Extern(..)+ , matchingExternals+ -- * Tags+ , CmdTag(..)+ , TagE+ , Tag((.+),remTag,tagMatch)+ , (.&)+ , (.||)+ , notT+ , externTags+ , 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(..)+ ) where import Data.Map hiding (map) import Data.Dynamic@@ -58,6 +56,7 @@ import HERMIT.Core import HERMIT.Context (LocalPathH) import HERMIT.Kure+import HERMIT.Monad ----------------------------------------------------------------- @@ -80,11 +79,12 @@ | Deep -- ^ Command may make a deep change, can be O(n). | Shallow -- ^ Command operates on local nodes only, O(1). | Navigation -- ^ Uses 'Path' or 'Lens' to focus onto something.- | Query -- ^ A question we ask.+ | Query -- ^ Extract information from an expression. | Predicate -- ^ Something that passes or fails. | Introduce -- ^ Introduce something, like a new name. | Commute -- ^ Commute is when you swap nested terms. | PreCondition -- ^ Operation has a (perhaps undocumented) precondition.+ | Strictness -- ^ Alters the strictness of the expression. | Debug -- ^ Commands specifically to help debugging. | VersionControl -- ^ Version control for Core syntax. | Context -- ^ A command that uses its context, such as inlining.@@ -96,22 +96,6 @@ | Experiment -- ^ Things we are trying out. | Deprecated -- ^ A command that will be removed in a future release; -- it has probably been renamed or subsumed by another command.----- Unsure about these-{-- | Local -- local thing, O(1)- | CaseCmd -- works on case statements- | Context -- something that uses the context- | GHC -- a tunnel into GHC- | Lens -- focuses into a specific node- | LetCmd -- works on let statements- | Meta -- combines other commands- | Restful -- RESTful API commands- | Slow -- this command is slow--}- -- Other String- -- etc deriving (Eq, Show, Read, Bounded, Enum) -- | Lists all the tags paired with a short description of what they're about.@@ -121,31 +105,30 @@ , tag `notElem` map fst notes ] where notes =- -- These should give the user a clue about what the sub-commands- -- might do- [ (Shell, "Shell-specific command.")- , (Eval, "The arrow of evaluation (reduces a term).")- , (KURE, "Direct reflection of a combinator from the KURE DSL.")- , (Loop, "Command may operate multiple times.")- , (Deep, "Command may make a deep change, can be O(n).")- , (Shallow, "Command operates on local nodes only, O(1).")- , (Navigation, "Navigate via focus, or directional command.")- , (Query, "A question we ask.")- , (Predicate, "Something that passes or fails.")- , (Introduce, "Introduce something, like a new name.")- , (Commute, "Commute is when you swap nested terms.")- , (PreCondition, "Operation has a (perhaps undocumented) precondition.")- , (Debug, "A command specifically to help debugging.")- , (VersionControl,"Version control for Core syntax.")- , (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.")- , (Proof, "Commands related to proving lemmas.")- , (TODO, "An incomplete or potentially buggy command.")- , (Experiment, "Things we are trying out, use at your own risk.")- , (Deprecated, "A command that will be removed in a future release; it has probably been renamed or subsumed by another command.")+ -- These should give the user a clue about what the sub-commands might do+ [ (Shell, "Shell-specific command.")+ , (Eval, "The arrow of evaluation (reduces a term).")+ , (KURE, "Direct reflection of a combinator from the KURE DSL.")+ , (Loop, "Command may operate multiple times.")+ , (Deep, "Command may make a deep change, can be O(n).")+ , (Shallow, "Command operates on local nodes only, O(1).")+ , (Navigation, "Navigate via focus, or directional command.")+ , (Query, "Extract information from an expression.")+ , (Predicate, "Something that passes or fails.")+ , (Introduce, "Introduce something, like a new name.")+ , (Commute, "Commute is when you swap nested terms.")+ , (PreCondition, "Operation has a (perhaps undocumented) precondition.")+ , (Strictness, "Alters the strictness of an expression.")+ , (Debug, "A command specifically to help debugging.")+ , (VersionControl, "Version control for Core syntax.")+ , (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.")+ , (Proof, "Commands related to proving lemmas.")+ , (TODO, "An incomplete or potentially buggy command.")+ , (Experiment, "Things we are trying out, use at your own risk.")+ , (Deprecated, "A command that will be removed in a future release; it has probably been renamed or subsumed by another command.") ] - -- Unfortunately, record update syntax seems to associate to the right. -- These operators save us some parentheses. infixl 3 .+@@ -234,20 +217,6 @@ matchingExternals tag exts = [ (e,tr) | e <- exts, tagMatch tag e , Just tr <- [fmap unbox $ fromDynamic $ externDyn e] ] --- | A 'Dictionary' is a collection of 'Dynamic's.--- Looking up a 'Dynamic' (via an 'ExternalName' key) returns a list, as there can be multiple 'Dynamic's with the same name.-type Dictionary = Map ExternalName [Dynamic]---- | Build a 'Data.Map' from names to 'Dynamic' values.-toDictionary :: [External] -> Dictionary-toDictionary = fromListWith (++) . map toEntry--toEntry :: External -> (ExternalName, [Dynamic])-toEntry e = (externName e, [externDyn e])--addToDictionary :: External -> Dictionary -> Dictionary-addToDictionary ex d = fromListWith (++) $ toEntry ex : toList d- -- | Build a 'Data.Map' from names to help information. toHelp :: [External] -> Map ExternalName ExternalHelp toHelp = fromListWith (++) . map toH@@ -266,9 +235,9 @@ -- | Remove the word 'Box' from a string. deBoxify :: String -> String-deBoxify xs +deBoxify xs | "CLSBox -> " `isPrefixOf` xs = deBoxify (drop 10 xs)-deBoxify xs +deBoxify xs | "Box" `isPrefixOf` xs = deBoxify (drop 3 xs) deBoxify (x:xs) = x : deBoxify xs deBoxify [] = []@@ -435,14 +404,12 @@ ----------------------------------------------------------------- --- TODO: Is this deliberately called "CoreBox" rather than "CoreStringBox"?-newtype CoreString = CoreString { unCoreString :: String }-data CoreBox = CoreBox CoreString deriving Typeable+newtype CoreString = CoreString { unCoreString :: String } deriving Typeable instance Extern CoreString where- type Box CoreString = CoreBox- box = CoreBox- unbox (CoreBox s) = s+ type Box CoreString = CoreString+ box = id+ unbox = id ----------------------------------------------------------------- @@ -479,5 +446,37 @@ type Box [RewriteH Core] = RewriteCoreListBox box = RewriteCoreListBox unbox (RewriteCoreListBox l) = l++-----------------------------------------------------------------++instance Extern RememberedName where+ type Box RememberedName = RememberedName+ box = id+ unbox = id++-----------------------------------------------------------------++instance Extern LemmaName where+ type Box LemmaName = LemmaName+ box = id+ unbox = id++-----------------------------------------------------------------++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 -----------------------------------------------------------------
src/HERMIT/GHC.hs view
@@ -1,7 +1,5 @@ {-# LANGUAGE CPP, InstanceSigs, TypeSynonymInstances, FlexibleInstances #-}-#if __GLASGOW_HASKELL__ > 706 {-# OPTIONS_GHC -fno-warn-name-shadowing #-}-#endif -- Above shadowing disabled because the eqExprX function has lots of shadowing module HERMIT.GHC ( -- * GHC Imports@@ -9,101 +7,95 @@ module GhcPlugins , ppIdInfo , zapVarOccInfo- , var2String , thRdrNameGuesses , varNameNS , isQualified , cmpString2Name , cmpString2Var- , fqName- , uqName- , findNamesFromString+ , qualifiedName+ , unqualifiedName , alphaTyVars , Type(..) , TyLit(..) , GhcException(..) , throwGhcException , exprArity- , occurAnalyseExpr+ , occurAnalyseExpr_NoBinderSwap , isKind , isLiftedTypeKindCon-#if __GLASGOW_HASKELL__ > 706- , coAxiomName- , CoAxiom.BranchIndex- , CoAxiom.CoAxiom- , CoAxiom.Branched-#endif , notElemVarSet , varSetToStrings , showVarSet , Pair(..) , bndrRuleAndUnfoldingVars-#if __GLASGOW_HASKELL__ <= 706- , exprType- , Control.Monad.IO.Class.liftIO-#else- , runDsMtoCoreM- , runTcMtoCoreM- , buildTypeable- , buildDictionary+ , coAxiomName+ , CoAxiom.BranchIndex+ , CoAxiom.CoAxiom+ , CoAxiom.Branched+ , Bag.foldBag , eqExprX- , lookupRdrNameInModuleForPlugins+ , loadSysInterface+ , lookupRdrNameInModule+ , reportAllUnsolved+ , zEncodeString+#ifdef mingw32_HOST_OS+ , initStaticOpts #endif- , mkPhiTy- , mkSigmaTy+ , module Class+ , module DsBinds+ , module DsMonad+ , module ErrUtils+ , module PrelNames+ , module TcEnv+ , module TcMType+ , module TcRnMonad+ , module TcRnTypes+ , module TcSimplify+ , module TcType+ , module Unify , getHscEnvCoreM ) where -#if __GLASGOW_HASKELL__ <= 706--- GHC 7.6-import qualified Control.Monad.IO.Class-import qualified MonadUtils (MonadIO,liftIO)-import GhcPlugins hiding (exprFreeVars, exprFreeIds, bindFreeVars, exprType, liftIO, PluginPass, getHscEnv)-import TysPrim (alphaTy, alphaTyVars)-import Panic (throwGhcException, GhcException(..))-import PprCore (pprCoreExpr)-import Data.Monoid hiding ((<>))-#else--- GHC 7.8-import Finder (findImportedModule, cannotFindModule)--- we hide these so that they don't get inadvertently used. See Core.hs-import GhcPlugins hiding (exprFreeVars, exprFreeIds, bindFreeVars, PluginPass, getHscEnv)-import LoadIface (loadPluginInterface)-import Panic (throwGhcException, throwGhcExceptionIO, GhcException(..))-import TcRnMonad (initIfaceTcRn)-import TysPrim (alphaTyVars)-#endif---- hacky direct GHC imports-import Convert (thRdrNameGuesses)-import CoreArity-import qualified CoreMonad -- for getHscEnv-import Kind (isKind,isLiftedTypeKindCon)-import qualified OccName -- for varName-import OccurAnal (occurAnalyseExpr)-import Pair (Pair(..))-import TcType (mkPhiTy, mkSigmaTy)-import TypeRep (Type(..),TyLit(..))--#if __GLASGOW_HASKELL__ <= 706-import Data.Maybe (isJust)-#else+-- Imports from GHC. import qualified Bag+import Class (classTyCon) import qualified CoAxiom -- for coAxiomName-import DsBinds (dsEvBinds)-import DsMonad (DsM, initDsTc)-import PrelNames (typeableClassName)-import TcEnv (tcLookupClass)-import TcMType (newWantedEvVar)-import TcRnMonad (getCtLoc)-import TcRnTypes (TcM, mkNonCanonical, mkFlatWC, CtEvidence(..), SkolemInfo(..), CtOrigin(..))-import TcSimplify (solveWantedsTcM)--import HERMIT.GHC.Typechecker+import Convert (thRdrNameGuesses)+import CoreArity+import qualified CoreMonad -- for getHscEnv+import DsBinds (dsEvBinds)+import DsMonad (DsM, initDsTc)+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 Kind (isKind,isLiftedTypeKindCon)+import LoadIface (loadSysInterface)+import qualified OccName -- for varName+import OccurAnal (occurAnalyseExpr_NoBinderSwap)+import Pair (Pair(..))+import Panic (throwGhcException, throwGhcExceptionIO, GhcException(..))+import PrelNames (typeableClassName)+#if mingw32_HOST_OS+import StaticFlags #endif+import TcEnv (tcLookupClass)+import TcErrors (reportAllUnsolved)+import TcMType (newWantedEvVar)+import TcRnMonad (getCtLoc, initIfaceTcRn)+import TcRnTypes (TcM, mkNonCanonical, mkFlatWC, CtEvidence(..), SkolemInfo(..), CtOrigin(..))+import TcSimplify (solveWantedsTcM)+import TcType (mkPhiTy, mkSigmaTy)+import TypeRep (Type(..),TyLit(..))+import TysPrim (alphaTyVars)+import Unify (tcUnifyTys, BindFlag(..)) import Data.List (intercalate) +import HERMIT.GHC.Typechecker+ -------------------------------------------------------------------------- -- | Rename this namespace, as 'varName' is already a function in Var.@@ -113,36 +105,11 @@ getHscEnvCoreM :: CoreM HscEnv getHscEnvCoreM = CoreMonad.getHscEnv -#if __GLASGOW_HASKELL__ <= 706--- Note: prior to 7.8, the Let case was buggy for type--- bindings, so we provide a fixed definition here.-exprType :: CoreExpr -> Type--- ^ Recover the type of a well-typed Core expression. Fails when--- applied to the actual 'CoreSyn.Type' expression as it cannot--- really be said to have a type-exprType (Var var) = idType var-exprType (Lit lit) = literalType lit-exprType (Coercion co) = coercionType co-exprType (Let bind body)- | NonRec tv rhs <- bind- , Type ty <- rhs = substTyWith [tv] [ty] (exprType body)- | otherwise = exprType body-exprType (Case _ _ ty _) = ty-exprType (Cast _ co) = pSnd (coercionKind co)-exprType (Tick _ e) = exprType e-exprType (Lam binder expr) = mkPiType binder (exprType expr)-exprType e@(App _ _)- = case collectArgs e of- (fun, args) -> applyTypeToArgs e (exprType fun) args--exprType other = pprTrace "exprType" (pprCoreExpr other) alphaTy-#endif- -------------------------------------------------------------------------- -- | Convert a 'VarSet' to a list of user-readable strings. varSetToStrings :: VarSet -> [String]-varSetToStrings = map var2String . varSetElems+varSetToStrings = map unqualifiedName . varSetElems -- | Show a human-readable version of a 'VarSet'. showVarSet :: VarSet -> String@@ -150,13 +117,8 @@ -------------------------------------------------------------------------- -#if __GLASGOW_HASKELL__ <= 706--- coAxiomName :: CoAxiom -> Name--- coAxiomName = coAxiomName-#else coAxiomName :: CoAxiom.CoAxiom br -> Name coAxiomName = CoAxiom.coAxiomName-#endif -- varName :: Var -> Name -- nameOccName :: Name -> OccName@@ -166,24 +128,20 @@ -- getOccString :: NamedThing a => a -> String -- | Get the unqualified name from a 'NamedThing'.-uqName :: NamedThing nm => nm -> String-uqName = getOccString+unqualifiedName :: NamedThing nm => nm -> String+unqualifiedName = getOccString -- | Get the fully qualified name from a 'Name'.-fqName :: Name -> String-fqName nm = modStr ++ uqName nm+qualifiedName :: Name -> String+qualifiedName nm = modStr ++ unqualifiedName nm where modStr = maybe "" (\m -> moduleNameString (moduleName m) ++ ".") (nameModule_maybe nm) --- | Convert a variable to a neat string for printing (unqualfied name).-var2String :: Var -> String-var2String = uqName . varName- -- | Compare a 'String' to a 'Name' for equality. -- Strings containing a period are assumed to be fully qualified names. -- (Except for ".", which is an unqualified reference to composition.) cmpString2Name :: String -> Name -> Bool-cmpString2Name str nm | isQualified str = str == fqName nm- | otherwise = str == uqName nm+cmpString2Name str nm | isQualified str = str == qualifiedName nm+ | otherwise = str == unqualifiedName nm isQualified :: String -> Bool isQualified [] = False@@ -193,12 +151,6 @@ cmpString2Var :: String -> Var -> Bool cmpString2Var str = cmpString2Name str . varName --- | Find 'Name's matching a given fully qualified or unqualified name.-findNamesFromString :: GlobalRdrEnv -> String -> [Name]-findNamesFromString rdrEnv str | isQualified str = res- | otherwise = res- where res = [ nm | elt <- globalRdrEnvElts rdrEnv, let nm = gre_name elt, cmpString2Name str nm ]- -- | Pretty-print an identifier. ppIdInfo :: Id -> IdInfo -> SDoc ppIdInfo v info@@ -224,12 +176,7 @@ has_caf_info = not (mayHaveCafRefs caf_info) str_info = strictnessInfo info- has_strictness =-#if __GLASGOW_HASKELL__ > 706- True-#else- isJust str_info-#endif+ has_strictness = True unf_info = unfoldingInfo info has_unf = hasSomeUnfolding unf_info@@ -255,23 +202,8 @@ notElemVarSet :: Var -> VarSet -> Bool notElemVarSet v vs = not (v `elemVarSet` vs) -#if __GLASGOW_HASKELL__ <= 706-instance Monoid VarSet where- mempty :: VarSet- mempty = emptyVarSet-- mappend :: VarSet -> VarSet -> VarSet- mappend = unionVarSet- -------------------------------------------------------------------------- -instance Control.Monad.IO.Class.MonadIO CoreM where- liftIO :: IO a -> CoreM a- liftIO = MonadUtils.liftIO-#endif----------------------------------------------------------------------------- -- This function is copied from GHC, which defines but doesn't expose it. -- A 'let' can bind a type variable, and idRuleVars assumes -- it's seeing an Id. This function tests first.@@ -281,44 +213,6 @@ -------------------------------------------------------------------------- -#if __GLASGOW_HASKELL__ > 706-runTcMtoCoreM :: ModGuts -> TcM a -> CoreM a-runTcMtoCoreM guts m = do- env <- CoreMonad.getHscEnv- -- What is the effect of HsSrcFile (should we be using something else?)- -- What should the boolean flag be set to?- (msgs, mr) <- liftIO $ initTcFromModGuts env guts HsSrcFile False m- -- There is probably something better for reporting the errors.- let dumpSDocs endMsg = Bag.foldBag (\ d r -> d ++ ('\n':r)) show endMsg- showMsgs (warns, errs) = "Errors:\n" ++ dumpSDocs ("Warnings:\n" ++ dumpSDocs "" warns) errs- maybe (fail $ showMsgs msgs) return mr--runDsMtoCoreM :: ModGuts -> DsM a -> CoreM a-runDsMtoCoreM guts = runTcMtoCoreM guts . initDsTc---- TODO: this is mostly an example, move somewhere?-buildTypeable :: ModGuts -> Type -> CoreM (Id, [CoreBind])-buildTypeable guts ty = do- evar <- runTcMtoCoreM guts $ do- cls <- tcLookupClass typeableClassName- let predTy = mkClassPred cls [typeKind ty, ty] -- recall that Typeable is now poly-kinded- newWantedEvVar predTy- buildDictionary guts evar---- | Build a dictionary for the given-buildDictionary :: ModGuts -> Id -> CoreM (Id, [CoreBind])-buildDictionary guts evar = do- (i, bs) <- runTcMtoCoreM guts $ do- loc <- getCtLoc $ GivenOrigin UnkSkol- let predTy = varType evar- nonC = mkNonCanonical $ CtWanted { ctev_pred = predTy, ctev_evar = evar, ctev_loc = loc }- wCs = mkFlatWC [nonC]- (_wCs', bnds) <- solveWantedsTcM wCs- -- TODO: check for unsolved constraints?- return (evar, bnds)- bnds <- runDsMtoCoreM guts $ dsEvBinds bs- return (i,bnds)- -- This function used to be in GHC itself, but was removed. -- It compares core for equality modulo alpha. eqExprX :: IdUnfoldingFun -> RnEnv2 -> CoreExpr -> CoreExpr -> Bool@@ -391,10 +285,16 @@ -- * If the module could not be found -- * If we could not determine the imports of the module ----- This is adapted from GHC's function of the same name, but using--- initTcFromModGuts instead of initTcInteractive.-lookupRdrNameInModuleForPlugins :: HscEnv -> ModGuts -> ModuleName -> RdrName -> IO (Maybe Name)-lookupRdrNameInModuleForPlugins hsc_env guts mod_name rdr_name = do+-- This is adapted from GHC's function called lookupRdrNameInModuleForPlugins,+-- but using initTcFromModGuts instead of initTcInteractive. Also, we ImportBySystem+-- instead of ImportByPlugin, so the EPS gets populated with RULES and instances from+-- the loaded module.+--+-- TODO: consider importing by plugin first, then only importing by system when a name+-- is successfully found... as written we will load RULES/instances if the module loads+-- successfully, even if the name is not found.+lookupRdrNameInModule :: HscEnv -> ModGuts -> ModuleName -> RdrName -> IO (Maybe Name)+lookupRdrNameInModule hsc_env guts mod_name rdr_name = do -- First find the package the module resides in by searching exposed packages and home modules found_module <- findImportedModule hsc_env mod_name Nothing case found_module of@@ -402,7 +302,8 @@ -- Find the exports of the module (_, mb_iface) <- initTcFromModGuts hsc_env guts HsSrcFile False $ initIfaceTcRn $- loadPluginInterface doc mod+ loadSysInterface doc mod+ case mb_iface of Just iface -> do -- Try and find the required name in the exports@@ -427,4 +328,3 @@ throwCmdLineError :: String -> IO a throwCmdLineError = throwGhcExceptionIO . CmdLineError-#endif
src/HERMIT/GHC/Typechecker.hs view
@@ -1,15 +1,11 @@ {-# LANGUAGE CPP, RankNTypes #-}-module HERMIT.GHC.Typechecker - ( -#if __GLASGOW_HASKELL__ > 706+module HERMIT.GHC.Typechecker+ ( initTcFromModGuts , mk_type_env , tcLookupGlobal-#endif ) where -#if __GLASGOW_HASKELL__ > 706- import Annotations (emptyAnnEnv) import HsSyn import RdrName@@ -34,7 +30,7 @@ import qualified Data.Set as Set import qualified Data.Map as Map -import Prelude +import Prelude import VarSet (emptyVarSet) -- Note: the contents of this module should eventually be folded into GHC proper.@@ -178,5 +174,3 @@ mk_dfun_n :: ModGuts -> OccSet -- TODO mk_dfun_n _ = emptyOccSet--#endif
src/HERMIT/Kernel.hs view
@@ -1,17 +1,18 @@ {-# LANGUAGE RankNTypes, ScopedTypeVariables, TupleSections, GADTs #-} module HERMIT.Kernel- ( -- * The HERMIT Kernel- AST- , Kernel- , hermitKernel- , resumeK- , abortK- , applyK- , queryK- , deleteK- , listK-) where+ ( -- * The HERMIT Kernel+ AST+ , Kernel+ , KernelEnv(..)+ , hermitKernel+ , resumeK+ , abortK+ , applyK+ , queryK+ , deleteK+ , listK+ ) where import Prelude hiding (lookup) @@ -27,12 +28,12 @@ -- For now, operations on a 'Kernel' are sequential, but later -- it will be possible to have two 'applyK's running in parallel. data Kernel = Kernel- { resumeK :: AST -> IO () -- ^ Halt the 'Kernel' and return control to GHC, which compiles the specified 'AST'.- , abortK :: IO () -- ^ Halt the 'Kernel' and abort GHC without compiling.- , applyK :: AST -> RewriteH ModGuts -> HermitMEnv -> 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 -> HermitMEnv -> 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'.+ { 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'. } -- | A /handle/ for a specific version of the 'ModGuts'.@@ -42,15 +43,28 @@ data Msg s r = forall a . Req (s -> CoreM (KureM (a,s))) (MVar (KureM a)) | Done (s -> CoreM r) -type KernelState = Map AST (DefStash, ModGuts)+type ASTMap = Map AST KernelState +data KernelState = KernelState { _ksStash :: DefStash+ , _ksLemmas :: Lemmas+ , ksGuts :: ModGuts+ }++fromHermitMResult :: HermitMResult ModGuts -> KernelState+fromHermitMResult hRes = sideEffectsOnly hRes (hResult hRes)++sideEffectsOnly :: HermitMResult a -> ModGuts -> KernelState+sideEffectsOnly hRes = KernelState (hResStash hRes) (hResLemmas hRes)++data KernelEnv = KernelEnv { kEnvChan :: DebugMessage -> HermitM () }+ -- | 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 - msgMV :: MVar (Msg KernelState ModGuts) <- liftIO newEmptyMVar+ msgMV :: MVar (Msg ASTMap ModGuts) <- liftIO newEmptyMVar nextASTname :: MVar AST <- liftIO newEmptyMVar @@ -58,38 +72,53 @@ loop (succ n) in loop 0 - let sendDone :: (KernelState -> CoreM ModGuts) -> IO ()+ let sendDone :: (ASTMap -> CoreM ModGuts) -> IO () sendDone = putMVar msgMV . Done - let sendReq :: (KernelState -> CoreM (KureM (a, KernelState))) -> IO (KureM a)+ let sendReq :: (ASTMap -> CoreM (KureM (a, ASTMap))) -> IO (KureM a) sendReq fn = do rep <- newEmptyMVar putMVar msgMV (Req fn rep) takeMVar rep - let sendReqRead :: (KernelState -> CoreM (KureM a)) -> IO (KureM a)- sendReqRead fn = sendReq (\ st -> (fmap.fmap) (,st) $ fn st)+ let sendReqRead :: (ASTMap -> CoreM (KureM a)) -> IO (KureM a)+ sendReqRead fn = sendReq (\ st -> (fmap.fmap) (,st) $ fn st) -- >>= return . fmap fst - let sendReqWrite :: (KernelState -> CoreM KernelState) -> IO ()- sendReqWrite fn = sendReq (fmap ( return . ((),) ) . fn) >>= liftKureM+ let sendReqWrite :: (ASTMap -> CoreM ASTMap) -> IO ()+ sendReqWrite fn = sendReq (fmap ( return . ((),) ) . fn) >>= {- fmap fst . -} liftKureM let kernel :: Kernel kernel = Kernel- { resumeK = \ name -> sendDone $ \ st -> findWithErrMsg name st (\ msg -> throwGhcException $ ProgramError $ msg ++ ", exiting HERMIT and aborting GHC compilation.") (return.snd)+ { resumeK = \ name ->+ sendDone $ \ st ->+ findWithErrMsg name+ st+ (\ msg -> throwGhcException+ $ ProgramError+ $ msg ++ ", exiting HERMIT and aborting GHC compilation.")+ (return.ksGuts) - , abortK = sendDone $ \ _ -> throwGhcException (ProgramError "Exiting HERMIT and aborting GHC compilation.")+ , abortK = sendDone $ \ _ -> throwGhcException+ $ ProgramError "Exiting HERMIT and aborting GHC compilation." - , applyK = \ name r hm_env -> sendReq $ \ st -> findWithErrMsg name st fail $ \ (defs, guts) -> runHM (guts,hm_env)- defs- (\ defs' guts' -> do ast <- liftIO $ takeMVar nextASTname- return $ return (ast, insert ast (defs',guts') st))- (return . fail)- (apply r (topLevelHermitC guts) guts)+ , 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) - , queryK = \ name t hm_env -> sendReqRead $ \ st -> findWithErrMsg name st fail $ \ (defs, guts) -> runHM (guts,hm_env)- defs- (\ _ -> return.return)- (return . fail)- (apply t (topLevelHermitC guts) guts)+ , 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) , deleteK = \ name -> sendReqWrite (return . delete name) @@ -99,7 +128,7 @@ -- We always start with AST 0 ast0 <- liftIO $ takeMVar nextASTname - let loop :: KernelState -> CoreM ModGuts+ let loop :: ASTMap -> CoreM ModGuts loop st = do m <- liftIO $ takeMVar msgMV case m of@@ -109,7 +138,7 @@ _pid <- liftIO $ forkIO $ callback kernel ast0 - loop (singleton ast0 (empty, modGuts))+ loop (singleton ast0 $ KernelState empty empty modGuts) -- (Kill the pid'd thread? do we need to?)
src/HERMIT/Kernel/Scoped.hs view
@@ -22,7 +22,6 @@ import HERMIT.Context import HERMIT.Kure import HERMIT.GHC hiding (Direction,L)-import HERMIT.Monad import HERMIT.Kernel ----------------------------------------------------------------------------@@ -59,22 +58,22 @@ -- | An alternative HERMIT kernel, that provides scoping. data ScopedKernel = ScopedKernel- { resumeS :: (MonadIO m, MonadCatch m) => SAST -> m ()- , abortS :: MonadIO m => m ()+ { resumeS :: (MonadIO m, MonadCatch m) => SAST -> m ()+ , abortS :: MonadIO m => m () , applyS :: (MonadIO m, MonadCatch m, Injection ModGuts g, Walker HermitC g)- => RewriteH g -> HermitMEnv -> SAST -> m SAST+ => RewriteH g -> KernelEnv -> SAST -> m SAST , queryS :: (MonadIO m, MonadCatch m, Injection ModGuts g, Walker HermitC g)- => TransformH g a -> HermitMEnv -> SAST -> m a- , deleteS :: (MonadIO m, MonadCatch m) => SAST -> m ()- , listS :: MonadIO m => m [SAST]- , pathS :: (MonadIO m, MonadCatch m) => SAST -> m [PathH]+ => 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) -> HermitMEnv -> SAST -> m SAST- , beginScopeS :: (MonadIO m, MonadCatch m) => SAST -> m SAST- , endScopeS :: (MonadIO m, MonadCatch m) => SAST -> m SAST+ => (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+ , kernelS :: Kernel+ , toASTS :: (MonadIO m, MonadCatch m) => SAST -> m AST } -- | A /handle/ for an 'AST' combined with scoping information.@@ -111,9 +110,10 @@ , 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)+ >>= 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
src/HERMIT/Kure.hs view
@@ -69,18 +69,11 @@ , forAllCoT, forAllCoAllR, forAllCoAnyR, forAllCoOneR , coVarCoT, coVarCoR , axiomInstCoT, axiomInstCoAllR, axiomInstCoAnyR, axiomInstCoOneR-#if __GLASGOW_HASKELL__ > 706-#else- , unsafeCoT, unsafeCoAllR, unsafeCoAnyR, unsafeCoOneR-#endif , symCoT, symCoR , transCoT, transCoAllR, transCoAnyR, transCoOneR , nthCoT, nthCoAllR, nthCoAnyR, nthCoOneR , instCoT, instCoAllR, instCoAnyR, instCoOneR-#if __GLASGOW_HASKELL__ > 706 , lrCoT, lrCoAllR, lrCoAnyR, lrCoOneR-#else-#endif -- * Conversion to deprecated Int representation , deprecatedIntToCrumbT , deprecatedIntToPathT@@ -129,12 +122,12 @@ allR :: forall m. MonadCatch m => Rewrite c m Core -> Rewrite c m Core allR r = prefixFailMsg "allR failed: " $ rewrite $ \ c -> \case- GutsCore guts -> inject <$> apply allRmodguts c guts- ProgCore p -> inject <$> apply allRprog c p- BindCore bn -> inject <$> apply allRbind c bn- DefCore def -> inject <$> apply allRdef c def- AltCore alt -> inject <$> apply allRalt c alt- ExprCore e -> inject <$> apply allRexpr c e+ GutsCore guts -> inject <$> applyT allRmodguts c guts+ ProgCore p -> inject <$> applyT allRprog c p+ BindCore bn -> inject <$> applyT allRbind c bn+ DefCore def -> inject <$> applyT allRdef c def+ AltCore alt -> inject <$> applyT allRalt c alt+ ExprCore e -> inject <$> applyT allRexpr c e where allRmodguts :: MonadCatch m => Rewrite c m ModGuts allRmodguts = modGutsR (extractR r)@@ -203,12 +196,8 @@ TransCo{} -> transCoAllR r r NthCo{} -> nthCoAllR idR r InstCo{} -> instCoAllR r idR-#if __GLASGOW_HASKELL__ > 706 LRCo{} -> lrCoAllR idR r AxiomInstCo{} -> axiomInstCoAllR idR idR (const r)-#else- AxiomInstCo{} -> axiomInstCoAllR idR (const r)-#endif _ -> idR ---------------------------------------------------------------------@@ -219,8 +208,8 @@ allR :: forall m. MonadCatch m => Rewrite c m TyCo -> Rewrite c m TyCo allR r = prefixFailMsg "allR failed: " $ rewrite $ \ c -> \case- TypeCore ty -> inject <$> apply (allR $ extractR r) c ty -- exploiting the fact that types do not contain coercions- CoercionCore co -> inject <$> apply allRcoercion c co+ TypeCore ty -> inject <$> applyT (allR $ extractR r) c ty -- exploiting the fact that types do not contain coercions+ CoercionCore co -> inject <$> applyT allRcoercion c co where allRcoercion :: MonadCatch m => Rewrite c m Coercion allRcoercion = readerT $ \case@@ -228,20 +217,12 @@ TyConAppCo{} -> tyConAppCoAllR idR (const $ extractR r) -- we don't descend into the TyCon AppCo{} -> appCoAllR (extractR r) (extractR r) ForAllCo{} -> forAllCoAllR idR (extractR r) -- we don't descend into the TyVar-#if __GLASGOW_HASKELL__ > 706-#else- UnsafeCo{} -> unsafeCoAllR (extractR r) (extractR r)-#endif SymCo{} -> symCoR (extractR r) TransCo{} -> transCoAllR (extractR r) (extractR r) InstCo{} -> instCoAllR (extractR r) (extractR r) NthCo{} -> nthCoAllR idR (extractR r) -- we don't descend into the Int-#if __GLASGOW_HASKELL__ > 706 LRCo{} -> lrCoAllR idR (extractR r) AxiomInstCo{} -> axiomInstCoAllR idR idR (const $ extractR r) -- we don't descend into the axiom or index-#else- AxiomInstCo{} -> axiomInstCoAllR idR (const $ extractR r) -- we don't descend into the axiom-#endif _ -> idR {-# INLINE allRcoercion #-} @@ -253,13 +234,13 @@ allR :: forall m. MonadCatch m => Rewrite c m CoreTC -> Rewrite c m CoreTC allR r = prefixFailMsg "allR failed: " $ rewrite $ \ c -> \case- Core (GutsCore guts) -> inject <$> apply allRmodguts c guts- Core (ProgCore p) -> inject <$> apply allRprog c p- Core (BindCore bn) -> inject <$> apply allRbind c bn- Core (DefCore def) -> inject <$> apply allRdef c def- Core (AltCore alt) -> inject <$> apply allRalt c alt- Core (ExprCore e) -> inject <$> apply allRexpr c e- TyCo tyCo -> inject <$> apply (allR $ extractR r) c tyCo -- exploiting the fact that only types and coercions appear within types and coercions+ Core (GutsCore guts) -> inject <$> applyT allRmodguts c guts+ Core (ProgCore p) -> inject <$> applyT allRprog c p+ Core (BindCore bn) -> inject <$> applyT allRbind c bn+ Core (DefCore def) -> inject <$> applyT allRdef c def+ Core (AltCore alt) -> inject <$> applyT allRalt c alt+ Core (ExprCore e) -> inject <$> applyT allRexpr c e+ TyCo tyCo -> inject <$> applyT (allR $ extractR r) c tyCo -- exploiting the fact that only types and coercions appear within types and coercions where allRmodguts :: MonadCatch m => Rewrite c m ModGuts allRmodguts = modGutsR (extractR r)@@ -307,7 +288,7 @@ -- | Transform a module. -- Slightly different to the other congruence combinators: it passes in /all/ of the original to the reconstruction function. modGutsT :: (ExtendPath c Crumb, HasEmptyContext c, Monad m) => Transform c m CoreProg a -> (ModGuts -> a -> b) -> Transform c m ModGuts b-modGutsT t f = transform $ \ c guts -> f guts <$> apply t (setEmptyContext c @@ ModGuts_Prog) (bindsToProg $ mg_binds guts)+modGutsT t f = transform $ \ c guts -> f guts <$> applyT t (setEmptyContext c @@ ModGuts_Prog) (bindsToProg $ mg_binds guts) {-# INLINE modGutsT #-} -- | Rewrite the 'CoreProg' child of a module.@@ -327,7 +308,7 @@ -- | Transform a program of the form: ('CoreBind' @:@ 'CoreProg') progConsT :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, Monad m) => Transform c m CoreBind a1 -> Transform c m CoreProg a2 -> (a1 -> a2 -> b) -> Transform c m CoreProg b progConsT t1 t2 f = transform $ \ c -> \case- ProgCons bd p -> f <$> apply t1 (c @@ ProgCons_Head) bd <*> apply t2 (addBindingGroup bd c @@ ProgCons_Tail) p+ ProgCons bd p -> f <$> applyT t1 (c @@ ProgCons_Head) bd <*> applyT t2 (addBindingGroup bd c @@ ProgCons_Tail) p _ -> fail "not a non-empty program." {-# INLINE progConsT #-} @@ -351,7 +332,7 @@ -- | Transform a binding group of the form: @NonRec@ 'Var' 'CoreExpr' nonRecT :: (ExtendPath c Crumb, Monad m) => Transform c m Var a1 -> Transform c m CoreExpr a2 -> (a1 -> a2 -> b) -> Transform c m CoreBind b nonRecT t1 t2 f = transform $ \ c -> \case- NonRec v e -> f <$> apply t1 (c @@ NonRec_Var) v <*> apply t2 (c @@ NonRec_RHS) e+ NonRec v e -> f <$> applyT t1 (c @@ NonRec_Var) v <*> applyT t2 (c @@ NonRec_RHS) e _ -> fail "not a non-recursive binding group." {-# INLINE nonRecT #-} @@ -375,7 +356,7 @@ recT :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, Monad m) => (Int -> Transform c m CoreDef a) -> ([a] -> b) -> Transform c m CoreBind b recT t f = transform $ \ c -> \case Rec bds -> -- The group is recursive, so we add all other bindings in the group to the context (excluding the one under consideration).- f <$> sequence [ apply (t n) (addDefBindingsExcept n bds c @@ Rec_Def n) (Def i e) -- here we convert from (Id,CoreExpr) to CoreDef+ f <$> sequence [ applyT (t n) (addDefBindingsExcept n bds c @@ Rec_Def n) (Def i e) -- here we convert from (Id,CoreExpr) to CoreDef | ((i,e),n) <- zip bds [0..] ] _ -> fail "not a recursive binding group."@@ -400,7 +381,7 @@ -- | Transform a recursive definition of the form: @Def@ 'Id' 'CoreExpr' defT :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, Monad m) => Transform c m Id a1 -> Transform c m CoreExpr a2 -> (a1 -> a2 -> b) -> Transform c m CoreDef b-defT t1 t2 f = transform $ \ c (Def i e) -> f <$> apply t1 (c @@ Def_Id) i <*> apply t2 (addDefBinding i c @@ Def_RHS) e+defT t1 t2 f = transform $ \ c (Def i e) -> f <$> applyT t1 (c @@ Def_Id) i <*> applyT t2 (addDefBinding i c @@ Def_RHS) e {-# INLINE defT #-} -- | Rewrite all children of a recursive definition of the form: @Def@ 'Id' 'CoreExpr'@@ -422,9 +403,9 @@ -- | Transform a case alternative of the form: ('AltCon', ['Var'], 'CoreExpr') altT :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, Monad m) => Transform c m AltCon a1 -> (Int -> Transform c m Var a2) -> Transform c m CoreExpr a3 -> (a1 -> [a2] -> a3 -> b) -> Transform c m CoreAlt b-altT t1 ts t2 f = transform $ \ c (con,vs,e) -> f <$> apply t1 (c @@ Alt_Con) con- <*> sequence [ apply (ts n) (c @@ Alt_Var n) v | (v,n) <- zip vs [1..] ]- <*> apply t2 (addAltBindings vs c @@ Alt_RHS) e+altT t1 ts t2 f = transform $ \ c (con,vs,e) -> f <$> applyT t1 (c @@ Alt_Con) con+ <*> sequence [ applyT (ts n) (c @@ Alt_Var n) v | (v,n) <- zip vs [1..] ]+ <*> applyT t2 (addAltBindings vs c @@ Alt_RHS) e {-# INLINE altT #-} -- | Rewrite all children of a case alternative of the form: ('AltCon', 'Id', 'CoreExpr')@@ -447,7 +428,7 @@ -- | Transform an expression of the form: @Var@ 'Id' varT :: (ExtendPath c Crumb, Monad m) => Transform c m Id b -> Transform c m CoreExpr b varT t = transform $ \ c -> \case- Var v -> apply t (c @@ Var_Id) v+ Var v -> applyT t (c @@ Var_Id) v _ -> fail "not a variable." {-# INLINE varT #-} @@ -460,7 +441,7 @@ -- | Transform an expression of the form: @Lit@ 'Literal' litT :: (ExtendPath c Crumb, Monad m) => Transform c m Literal b -> Transform c m CoreExpr b litT t = transform $ \ c -> \case- Lit x -> apply t (c @@ Lit_Lit) x+ Lit x -> applyT t (c @@ Lit_Lit) x _ -> fail "not a literal." {-# INLINE litT #-} @@ -473,7 +454,7 @@ -- | Transform an expression of the form: @App@ 'CoreExpr' 'CoreExpr' appT :: (ExtendPath c Crumb, Monad m) => Transform c m CoreExpr a1 -> Transform c m CoreExpr a2 -> (a1 -> a2 -> b) -> Transform c m CoreExpr b appT t1 t2 f = transform $ \ c -> \case- App e1 e2 -> f <$> apply t1 (c @@ App_Fun) e1 <*> apply t2 (c @@ App_Arg) e2+ App e1 e2 -> f <$> applyT t1 (c @@ App_Fun) e1 <*> applyT t2 (c @@ App_Arg) e2 _ -> fail "not an application." {-# INLINE appT #-} @@ -496,7 +477,7 @@ -- | Transform an expression of the form: @Lam@ 'Var' 'CoreExpr' lamT :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, Monad m) => Transform c m Var a1 -> Transform c m CoreExpr a2 -> (a1 -> a2 -> b) -> Transform c m CoreExpr b lamT t1 t2 f = transform $ \ c -> \case- Lam v e -> f <$> apply t1 (c @@ Lam_Var) v <*> apply t2 (addLambdaBinding v c @@ Lam_Body) e+ Lam v e -> f <$> applyT t1 (c @@ Lam_Var) v <*> applyT t2 (addLambdaBinding v c @@ Lam_Body) e _ -> fail "not a lambda." {-# INLINE lamT #-} @@ -521,7 +502,7 @@ letT t1 t2 f = transform $ \ c -> \case Let bds e -> -- Note we use the *original* context for the binding group. -- If the bindings are recursive, they will be added to the context by recT.- f <$> apply t1 (c @@ Let_Bind) bds <*> apply t2 (addBindingGroup bds c @@ Let_Body) e+ f <$> applyT t1 (c @@ Let_Bind) bds <*> applyT t2 (addBindingGroup bds c @@ Let_Body) e _ -> fail "not a let node." {-# INLINE letT #-} @@ -550,10 +531,10 @@ -> (e -> w -> ty -> [alt] -> b) -> Transform c m CoreExpr b caseT te tw tty talts f = transform $ \ c -> \case- Case e w ty alts -> f <$> apply te (c @@ Case_Scrutinee) e- <*> apply tw (c @@ Case_Binder) w- <*> apply tty (c @@ Case_Type) ty- <*> sequence [ apply (talts n) (addCaseBinderBinding (w,e,alt) c @@ Case_Alt n) alt+ Case e w ty alts -> f <$> applyT te (c @@ Case_Scrutinee) e+ <*> applyT tw (c @@ Case_Binder) w+ <*> applyT tty (c @@ Case_Type) ty+ <*> sequence [ applyT (talts n) (addCaseBinderBinding (w,e,alt) c @@ Case_Alt n) alt | (alt,n) <- zip alts [0..] ] _ -> fail "not a case."@@ -593,7 +574,7 @@ -- | Transform an expression of the form: @Cast@ 'CoreExpr' 'Coercion' castT :: (ExtendPath c Crumb, Monad m) => Transform c m CoreExpr a1 -> Transform c m Coercion a2 -> (a1 -> a2 -> b) -> Transform c m CoreExpr b castT t1 t2 f = transform $ \ c -> \case- Cast e co -> f <$> apply t1 (c @@ Cast_Expr) e <*> apply t2 (c @@ Cast_Co) co+ Cast e co -> f <$> applyT t1 (c @@ Cast_Expr) e <*> applyT t2 (c @@ Cast_Co) co _ -> fail "not a cast." {-# INLINE castT #-} @@ -616,7 +597,7 @@ -- | Transform an expression of the form: @Tick@ 'CoreTickish' 'CoreExpr' tickT :: (ExtendPath c Crumb, Monad m) => Transform c m CoreTickish a1 -> Transform c m CoreExpr a2 -> (a1 -> a2 -> b) -> Transform c m CoreExpr b tickT t1 t2 f = transform $ \ c -> \case- Tick tk e -> f <$> apply t1 (c @@ Tick_Tick) tk <*> apply t2 (c @@ Tick_Expr) e+ Tick tk e -> f <$> applyT t1 (c @@ Tick_Tick) tk <*> applyT t2 (c @@ Tick_Expr) e _ -> fail "not a tick." {-# INLINE tickT #-} @@ -639,7 +620,7 @@ -- | Transform an expression of the form: @Type@ 'Type' typeT :: (ExtendPath c Crumb, Monad m) => Transform c m Type b -> Transform c m CoreExpr b typeT t = transform $ \ c -> \case- Type ty -> apply t (c @@ Type_Type) ty+ Type ty -> applyT t (c @@ Type_Type) ty _ -> fail "not a type." {-# INLINE typeT #-} @@ -652,7 +633,7 @@ -- | Transform an expression of the form: @Coercion@ 'Coercion' coercionT :: (ExtendPath c Crumb, Monad m) => Transform c m Coercion b -> Transform c m CoreExpr b coercionT t = transform $ \ c -> \case- Coercion co -> apply t (c @@ Co_Co) co+ Coercion co -> applyT t (c @@ Co_Co) co _ -> fail "not a coercion." {-# INLINE coercionT #-} @@ -910,7 +891,7 @@ -- | Transform a type of the form: @TyVarTy@ 'TyVar' tyVarT :: (ExtendPath c Crumb, Monad m) => Transform c m TyVar b -> Transform c m Type b tyVarT t = transform $ \ c -> \case- TyVarTy v -> apply t (c @@ TyVarTy_TyVar) v+ TyVarTy v -> applyT t (c @@ TyVarTy_TyVar) v _ -> fail "not a type variable." {-# INLINE tyVarT #-} @@ -923,7 +904,7 @@ -- | Transform a type of the form: @LitTy@ 'TyLit' litTyT :: (ExtendPath c Crumb, Monad m) => Transform c m TyLit b -> Transform c m Type b litTyT t = transform $ \ c -> \case- LitTy x -> apply t (c @@ LitTy_TyLit) x+ LitTy x -> applyT t (c @@ LitTy_TyLit) x _ -> fail "not a type literal." {-# INLINE litTyT #-} @@ -936,7 +917,7 @@ -- | Transform a type of the form: @AppTy@ 'Type' 'Type' appTyT :: (ExtendPath c Crumb, Monad m) => Transform c m Type a1 -> Transform c m Type a2 -> (a1 -> a2 -> b) -> Transform c m Type b appTyT t1 t2 f = transform $ \ c -> \case- AppTy ty1 ty2 -> f <$> apply t1 (c @@ AppTy_Fun) ty1 <*> apply t2 (c @@ AppTy_Arg) ty2+ AppTy ty1 ty2 -> f <$> applyT t1 (c @@ AppTy_Fun) ty1 <*> applyT t2 (c @@ AppTy_Arg) ty2 _ -> fail "not a type application." {-# INLINE appTyT #-} @@ -959,7 +940,7 @@ -- | Transform a type of the form: @FunTy@ 'Type' 'Type' funTyT :: (ExtendPath c Crumb, Monad m) => Transform c m Type a1 -> Transform c m Type a2 -> (a1 -> a2 -> b) -> Transform c m Type b funTyT t1 t2 f = transform $ \ c -> \case- FunTy ty1 ty2 -> f <$> apply t1 (c @@ FunTy_Dom) ty1 <*> apply t2 (c @@ FunTy_CoDom) ty2+ FunTy ty1 ty2 -> f <$> applyT t1 (c @@ FunTy_Dom) ty1 <*> applyT t2 (c @@ FunTy_CoDom) ty2 _ -> fail "not a function type." {-# INLINE funTyT #-} @@ -982,7 +963,7 @@ -- | Transform a type of the form: @ForAllTy@ 'Var' 'Type' forAllTyT :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, Monad m) => Transform c m Var a1 -> Transform c m Type a2 -> (a1 -> a2 -> b) -> Transform c m Type b forAllTyT t1 t2 f = transform $ \ c -> \case- ForAllTy v ty -> f <$> apply t1 (c @@ ForAllTy_Var) v <*> apply t2 (addForallBinding v c @@ ForAllTy_Body) ty+ ForAllTy v ty -> f <$> applyT t1 (c @@ ForAllTy_Var) v <*> applyT t2 (addForallBinding v c @@ ForAllTy_Body) ty _ -> fail "not a forall type." {-# INLINE forAllTyT #-} @@ -1005,7 +986,7 @@ -- | Transform a type of the form: @TyConApp@ 'TyCon' ['KindOrType'] tyConAppT :: (ExtendPath c Crumb, Monad m) => Transform c m TyCon a1 -> (Int -> Transform c m KindOrType a2) -> (a1 -> [a2] -> b) -> Transform c m Type b tyConAppT t ts f = transform $ \ c -> \case- TyConApp con tys -> f <$> apply t (c @@ TyConApp_TyCon) con <*> sequence [ apply (ts n) (c @@ TyConApp_Arg n) ty | (ty,n) <- zip tys [0..] ]+ TyConApp con tys -> f <$> applyT t (c @@ TyConApp_TyCon) con <*> sequence [ applyT (ts n) (c @@ TyConApp_Arg n) ty | (ty,n) <- zip tys [0..] ] _ -> fail "not a type-constructor application." {-# INLINE tyConAppT #-} @@ -1030,43 +1011,23 @@ -- Coercions -- TODO: review and bring all these up-to-date for Coercions w/ Roles in 7.8 -#if __GLASGOW_HASKELL__ > 706 -- | Transform a coercion of the form: @Refl@ 'Role' 'Type' reflT :: (ExtendPath c Crumb, Monad m) => Transform c m Type a1 -> (Role -> a1 -> b) -> Transform c m Coercion b reflT t f = transform $ \ c -> \case- Refl r ty -> f r <$> apply t (c @@ Refl_Type) ty+ Refl r ty -> f r <$> applyT t (c @@ Refl_Type) ty _ -> fail "not a reflexive coercion." -- | Rewrite the 'Type' child of a coercion of the form: @Refl@ 'Role' 'Type' reflR :: (ExtendPath c Crumb, Monad m) => Rewrite c m Type -> Rewrite c m Coercion reflR r = reflT r Refl-#else--- | Transform a coercion of the form: @Refl@ 'Type'-reflT :: (ExtendPath c Crumb, Monad m) => Transform c m Type b -> Transform c m Coercion b-reflT t = transform $ \ c -> \case- Refl ty -> apply t (c @@ Refl_Type) ty- _ -> fail "not a reflexive coercion."---- | Rewrite the 'Type' child of a coercion of the form: @Refl@ 'Type'-reflR :: (ExtendPath c Crumb, Monad m) => Rewrite c m Type -> Rewrite c m Coercion-reflR r = reflT (Refl <$> r)-#endif {-# INLINE reflT #-} {-# INLINE reflR #-} -#if __GLASGOW_HASKELL__ > 706 -- | Transform a coercion of the form: @TyConAppCo@ 'Role' 'TyCon' ['Coercion'] tyConAppCoT :: (ExtendPath c Crumb, Monad m) => Transform c m TyCon a1 -> (Int -> Transform c m Coercion a2) -> (Role -> a1 -> [a2] -> b) -> Transform c m Coercion b tyConAppCoT t ts f = transform $ \ c -> \case- TyConAppCo r con coes -> f r <$> apply t (c @@ TyConAppCo_TyCon) con <*> sequence [ apply (ts n) (c @@ TyConAppCo_Arg n) co | (co,n) <- zip coes [0..] ]+ TyConAppCo r con coes -> f r <$> applyT t (c @@ TyConAppCo_TyCon) con <*> sequence [ applyT (ts n) (c @@ TyConAppCo_Arg n) co | (co,n) <- zip coes [0..] ] _ -> fail "not a type-constructor coercion."-#else--- | Transform a coercion of the form: @TyConAppCo@ 'TyCon' ['Coercion']-tyConAppCoT :: (ExtendPath c Crumb, Monad m) => Transform c m TyCon a1 -> (Int -> Transform c m Coercion a2) -> (a1 -> [a2] -> b) -> Transform c m Coercion b-tyConAppCoT t ts f = transform $ \ c -> \case- TyConAppCo con coes -> f <$> apply t (c @@ TyConAppCo_TyCon) con <*> sequence [ apply (ts n) (c @@ TyConAppCo_Arg n) co | (co,n) <- zip coes [0..] ]- _ -> fail "not a type-constructor coercion."-#endif {-# INLINE tyConAppCoT #-} -- | Rewrite all children of a coercion of the form: @TyConAppCo@ 'TyCon' ['Coercion']@@ -1088,7 +1049,7 @@ -- | Transform a coercion of the form: @AppCo@ 'Coercion' 'Coercion' appCoT :: (ExtendPath c Crumb, Monad m) => Transform c m Coercion a1 -> Transform c m Coercion a2 -> (a1 -> a2 -> b) -> Transform c m Coercion b appCoT t1 t2 f = transform $ \ c -> \case- AppCo co1 co2 -> f <$> apply t1 (c @@ AppCo_Fun) co1 <*> apply t2 (c @@ AppCo_Arg) co2+ AppCo co1 co2 -> f <$> applyT t1 (c @@ AppCo_Fun) co1 <*> applyT t2 (c @@ AppCo_Arg) co2 _ -> fail "not a coercion application." {-# INLINE appCoT #-} @@ -1111,7 +1072,7 @@ -- | Transform a coercion of the form: @ForAllCo@ 'TyVar' 'Coercion' forAllCoT :: (ExtendPath c Crumb, ReadPath c Crumb, AddBindings c, Monad m) => Transform c m TyVar a1 -> Transform c m Coercion a2 -> (a1 -> a2 -> b) -> Transform c m Coercion b forAllCoT t1 t2 f = transform $ \ c -> \case- ForAllCo v co -> f <$> apply t1 (c @@ ForAllCo_TyVar) v <*> apply t2 (addForallBinding v c @@ ForAllCo_Body) co+ ForAllCo v co -> f <$> applyT t1 (c @@ ForAllCo_TyVar) v <*> applyT t2 (addForallBinding v c @@ ForAllCo_Body) co _ -> fail "not a forall coercion." {-# INLINE forAllCoT #-} @@ -1134,7 +1095,7 @@ -- | Transform a coercion of the form: @CoVarCo@ 'CoVar' coVarCoT :: (ExtendPath c Crumb, Monad m) => Transform c m CoVar b -> Transform c m Coercion b coVarCoT t = transform $ \ c -> \case- CoVarCo v -> apply t (c @@ CoVarCo_CoVar) v+ CoVarCo v -> applyT t (c @@ CoVarCo_CoVar) v _ -> fail "not a coercion variable." {-# INLINE coVarCoT #-} @@ -1143,83 +1104,33 @@ coVarCoR r = coVarCoT (CoVarCo <$> r) {-# INLINE coVarCoR #-} -#if __GLASGOW_HASKELL__ > 706 -- | Transform a coercion of the form: @AxiomInstCo@ ('CoAxiom' 'Branched') 'BranchIndex' ['Coercion'] axiomInstCoT :: (ExtendPath c Crumb, Monad m) => Transform c m (CoAxiom Branched) a1 -> Transform c m BranchIndex a2 -> (Int -> Transform c m Coercion a3) -> (a1 -> a2 -> [a3] -> b) -> Transform c m Coercion b axiomInstCoT t1 t2 ts f = transform $ \ c -> \case- AxiomInstCo ax idx coes -> f <$> apply t1 (c @@ AxiomInstCo_Axiom) ax <*> apply t2 (c @@ AxiomInstCo_Index) idx <*> sequence [ apply (ts n) (c @@ AxiomInstCo_Arg n) co | (co,n) <- zip coes [0..] ]+ AxiomInstCo ax idx coes -> f <$> applyT t1 (c @@ AxiomInstCo_Axiom) ax <*> applyT t2 (c @@ AxiomInstCo_Index) idx <*> sequence [ applyT (ts n) (c @@ AxiomInstCo_Arg n) co | (co,n) <- zip coes [0..] ] _ -> fail "not a coercion axiom instantiation."-#else--- | Transform a coercion of the form: @AxiomInstCo@ 'CoAxiom' ['Coercion']-axiomInstCoT :: (ExtendPath c Crumb, Monad m) => Transform c m CoAxiom a1 -> (Int -> Transform c m Coercion a2) -> (a1 -> [a2] -> b) -> Transform c m Coercion b-axiomInstCoT t ts f = transform $ \ c -> \case- AxiomInstCo ax coes -> f <$> apply t (c @@ AxiomInstCo_Axiom) ax <*> sequence [ apply (ts n) (c @@ AxiomInstCo_Arg n) co | (co,n) <- zip coes [0..] ]- _ -> fail "not a coercion axiom instantiation."-#endif {-# INLINE axiomInstCoT #-} -#if __GLASGOW_HASKELL__ > 706 -- | Rewrite all children of a coercion of the form: @AxiomInstCo@ ('CoAxiom' 'Branched') 'BranchIndex' ['Coercion'] axiomInstCoAllR :: (ExtendPath c Crumb, Monad m) => Rewrite c m (CoAxiom Branched) -> Rewrite c m BranchIndex -> (Int -> Rewrite c m Coercion) -> Rewrite c m Coercion axiomInstCoAllR r1 r2 rs = axiomInstCoT r1 r2 rs AxiomInstCo-#else--- | Rewrite all children of a coercion of the form: @AxiomInstCo@ 'CoAxiom' ['Coercion']-axiomInstCoAllR :: (ExtendPath c Crumb, Monad m) => Rewrite c m CoAxiom -> (Int -> Rewrite c m Coercion) -> Rewrite c m Coercion-axiomInstCoAllR r rs = axiomInstCoT r rs AxiomInstCo-#endif {-# INLINE axiomInstCoAllR #-} -#if __GLASGOW_HASKELL__ > 706 -- | Rewrite any children of a coercion of the form: @AxiomInstCo@ ('CoAxiom' 'Branched') 'BranchIndex' ['Coercion'] axiomInstCoAnyR :: (ExtendPath c Crumb, MonadCatch m) => Rewrite c m (CoAxiom Branched) -> Rewrite c m BranchIndex -> (Int -> Rewrite c m Coercion) -> Rewrite c m Coercion axiomInstCoAnyR r1 r2 rs = unwrapAnyR $ axiomInstCoAllR (wrapAnyR r1) (wrapAnyR r2) (wrapAnyR . rs)-#else--- | Rewrite any children of a coercion of the form: @AxiomInstCo@ 'CoAxiom' ['Coercion']-axiomInstCoAnyR :: (ExtendPath c Crumb, MonadCatch m) => Rewrite c m CoAxiom -> (Int -> Rewrite c m Coercion) -> Rewrite c m Coercion-axiomInstCoAnyR r rs = unwrapAnyR $ axiomInstCoAllR (wrapAnyR r) (wrapAnyR . rs)-#endif {-# INLINE axiomInstCoAnyR #-} -#if __GLASGOW_HASKELL__ > 706 -- | Rewrite one child of a coercion of the form: @AxiomInstCo@ ('CoAxiom' 'Branched') 'BranchIndex' ['Coercion'] axiomInstCoOneR :: (ExtendPath c Crumb, MonadCatch m) => Rewrite c m (CoAxiom Branched) -> Rewrite c m BranchIndex -> (Int -> Rewrite c m Coercion) -> Rewrite c m Coercion axiomInstCoOneR r1 r2 rs = unwrapOneR $ axiomInstCoAllR (wrapOneR r1) (wrapOneR r2) (wrapOneR . rs)-#else--- | Rewrite one child of a coercion of the form: @AxiomInstCo@ 'CoAxiom' ['Coercion']-axiomInstCoOneR :: (ExtendPath c Crumb, MonadCatch m) => Rewrite c m CoAxiom -> (Int -> Rewrite c m Coercion) -> Rewrite c m Coercion-axiomInstCoOneR r rs = unwrapOneR $ axiomInstCoAllR (wrapOneR r) (wrapOneR . rs)-#endif {-# INLINE axiomInstCoOneR #-} -#if __GLASGOW_HASKELL__ > 706-#else--- | Transform a coercion of the form: @UnsafeCo@ 'Type' 'Type'-unsafeCoT :: (ExtendPath c Crumb, Monad m) => Transform c m Type a1 -> Transform c m Type a2 -> (a1 -> a2 -> b) -> Transform c m Coercion b-unsafeCoT t1 t2 f = transform $ \ c -> \case- UnsafeCo ty1 ty2 -> f <$> apply t1 (c @@ UnsafeCo_Left) ty1 <*> apply t2 (c @@ UnsafeCo_Right) ty2- _ -> fail "not an unsafe coercion."-{-# INLINE unsafeCoT #-} --- | Rewrite all children of a coercion of the form: @UnsafeCo@ 'Type' 'Type'-unsafeCoAllR :: (ExtendPath c Crumb, Monad m) => Rewrite c m Type -> Rewrite c m Type -> Rewrite c m Coercion-unsafeCoAllR r1 r2 = unsafeCoT r1 r2 UnsafeCo-{-# INLINE unsafeCoAllR #-}---- | Rewrite any children of a coercion of the form: @UnsafeCo@ 'Type' 'Type'-unsafeCoAnyR :: (ExtendPath c Crumb, MonadCatch m) => Rewrite c m Type -> Rewrite c m Type -> Rewrite c m Coercion-unsafeCoAnyR r1 r2 = unwrapAnyR $ unsafeCoAllR (wrapAnyR r1) (wrapAnyR r2)-{-# INLINE unsafeCoAnyR #-}---- | Rewrite one child of a coercion of the form: @UnsafeCo@ 'Type' 'Type'-unsafeCoOneR :: (ExtendPath c Crumb, MonadCatch m) => Rewrite c m Type -> Rewrite c m Type -> Rewrite c m Coercion-unsafeCoOneR r1 r2 = unwrapOneR $ unsafeCoAllR (wrapOneR r1) (wrapOneR r2)-{-# INLINE unsafeCoOneR #-}-#endif- -- | Transform a coercion of the form: @SymCo@ 'Coercion' symCoT :: (ExtendPath c Crumb, Monad m) => Transform c m Coercion b -> Transform c m Coercion b symCoT t = transform $ \ c -> \case- SymCo co -> apply t (c @@ SymCo_Co) co+ SymCo co -> applyT t (c @@ SymCo_Co) co _ -> fail "not a symmetric coercion." {-# INLINE symCoT #-} @@ -1232,7 +1143,7 @@ -- | Transform a coercion of the form: @TransCo@ 'Coercion' 'Coercion' transCoT :: (ExtendPath c Crumb, Monad m) => Transform c m Coercion a1 -> Transform c m Coercion a2 -> (a1 -> a2 -> b) -> Transform c m Coercion b transCoT t1 t2 f = transform $ \ c -> \case- TransCo co1 co2 -> f <$> apply t1 (c @@ TransCo_Left) co1 <*> apply t2 (c @@ TransCo_Right) co2+ TransCo co1 co2 -> f <$> applyT t1 (c @@ TransCo_Left) co1 <*> applyT t2 (c @@ TransCo_Right) co2 _ -> fail "not a transitive coercion." {-# INLINE transCoT #-} @@ -1255,7 +1166,7 @@ -- | Transform a coercion of the form: @NthCo@ 'Int' 'Coercion' nthCoT :: (ExtendPath c Crumb, Monad m) => Transform c m Int a1 -> Transform c m Coercion a2 -> (a1 -> a2 -> b) -> Transform c m Coercion b nthCoT t1 t2 f = transform $ \ c -> \case- NthCo n co -> f <$> apply t1 (c @@ NthCo_Int) n <*> apply t2 (c @@ NthCo_Co) co+ NthCo n co -> f <$> applyT t1 (c @@ NthCo_Int) n <*> applyT t2 (c @@ NthCo_Co) co _ -> fail "not an Nth coercion." {-# INLINE nthCoT #-} @@ -1275,11 +1186,10 @@ {-# INLINE nthCoOneR #-} -#if __GLASGOW_HASKELL__ > 706 -- | Transform a coercion of the form: @LRCo@ 'LeftOrRight' 'Coercion' lrCoT :: (ExtendPath c Crumb, Monad m) => Transform c m LeftOrRight a1 -> Transform c m Coercion a2 -> (a1 -> a2 -> b) -> Transform c m Coercion b lrCoT t1 t2 f = transform $ \ c -> \case- LRCo lr co -> f <$> apply t1 (c @@ LRCo_LR) lr <*> apply t2 (c @@ LRCo_Co) co+ LRCo lr co -> f <$> applyT t1 (c @@ LRCo_LR) lr <*> applyT t2 (c @@ LRCo_Co) co _ -> fail "not a left/right coercion." {-# INLINE lrCoT #-} @@ -1297,14 +1207,12 @@ lrCoOneR :: (ExtendPath c Crumb, MonadCatch m) => Rewrite c m LeftOrRight -> Rewrite c m Coercion -> Rewrite c m Coercion lrCoOneR r1 r2 = unwrapOneR $ lrCoAllR (wrapOneR r1) (wrapOneR r2) {-# INLINE lrCoOneR #-}-#else-#endif -- | Transform a coercion of the form: @InstCo@ 'Coercion' 'Type' instCoT :: (ExtendPath c Crumb, Monad m) => Transform c m Coercion a1 -> Transform c m Type a2 -> (a1 -> a2 -> b) -> Transform c m Coercion b instCoT t1 t2 f = transform $ \ c -> \case- InstCo co ty -> f <$> apply t1 (c @@ InstCo_Co) co <*> apply t2 (c @@ InstCo_Type) ty+ InstCo co ty -> f <$> applyT t1 (c @@ InstCo_Co) co <*> applyT t2 (c @@ InstCo_Type) ty _ -> fail "not a coercion instantiation." {-# INLINE instCoT #-} @@ -1356,3 +1264,6 @@ --------------------------------------------------------------------- ---------------------------------------------------------------------++instance HasDynFlags m => HasDynFlags (Transform c m a) where+ getDynFlags = constT getDynFlags
src/HERMIT/Monad.hs view
@@ -1,42 +1,51 @@-{-# LANGUAGE CPP, InstanceSigs #-}+{-# LANGUAGE CPP, DeriveDataTypeable, FlexibleContexts, GADTs, InstanceSigs, KindSignatures #-} module HERMIT.Monad- (- -- * The HERMIT Monad- HermitM- , runHM- , liftCoreM- , newGlobalIdH- , newIdH- , newTyVarH- , newCoVarH- , newVarH- , cloneVarH- -- * Saving Definitions- , Label- , DefStash- , saveDef- , lookupDef- , getStash- -- * Reader Information- , HasHermitMEnv(..)- , HasModGuts(..)- , HasHscEnv(..)- -- * Messages- , HermitMEnv(..)- , DebugMessage(..)- , mkHermitMEnv- , sendDebugMessage-) where+ ( -- * The HERMIT Monad+ HermitM+ , runHM+ , embedHermitM+ , HermitMEnv(..)+ , HermitMResult(..)+ , LiftCoreM(..)+ , runTcM+ , runDsM+ -- * Saving Definitions+ , RememberedName(..)+ , DefStash+ , saveDef+ , lookupDef+ , HasStash(..)+ -- * Lemmas+ , Equality(..)+ , LemmaName(..)+ , Lemma(..)+ , Lemmas+ , addLemma+ -- * Reader Information+ , HasHermitMEnv(..)+ , mkEnv+ , getModGuts+ , HasHscEnv(..)+ -- * Writer Information+ , HasLemmas(..)+ -- * Messages+ , HasDebugChan(..)+ , DebugMessage(..)+ , sendDebugMessage+ ) where import Prelude hiding (lookup) +import Data.Dynamic (Typeable) import Data.Map+import Data.String (IsString(..)) -import Control.Monad-import Control.Monad.IO.Class import Control.Applicative import Control.Arrow+import Control.Concurrent.STM+import Control.Monad+import Control.Monad.IO.Class import Language.KURE @@ -44,78 +53,93 @@ import HERMIT.Context import HERMIT.Kure.SumTypes import HERMIT.GHC--#if __GLASGOW_HASKELL__ > 706 import HERMIT.GHC.Typechecker-#endif ---------------------------------------------------------------------------- --- | A label for individual definitions.-type Label = String---- | A store of saved definitions.-type DefStash = Map Label CoreDef---- | A way of sending messages to top level-newtype HermitMEnv = HermitMEnv { hs_debugChan :: DebugMessage -> HermitM () }+-- | A label for individual definitions. Use a newtype so we can tab-complete in shell.+newtype RememberedName = RememberedName String deriving (Eq, Ord, Typeable) --- | The HERMIT monad is kept abstract.-newtype HermitM a = HermitM ((ModGuts,HermitMEnv) -> DefStash -> CoreM (KureM (DefStash, a)))+instance IsString RememberedName where fromString = RememberedName+instance Show RememberedName where show (RememberedName s) = s -runHermitM :: HermitM a -> (ModGuts,HermitMEnv) -> DefStash -> CoreM (KureM (DefStash, a))-runHermitM (HermitM f) = f+-- | A store of saved definitions.+type DefStash = Map RememberedName CoreDef --- | Eliminator for 'HermitM'.-runHM :: (ModGuts,HermitMEnv) -> DefStash -> (DefStash -> a -> CoreM b) -> (String -> CoreM b) -> HermitM a -> CoreM b-runHM env s success failure ma = runHermitM ma env s >>= runKureM (\ (a,b) -> success a b) failure+-- | 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) --- | Get the stash of saved definitions.-getStash :: HermitM DefStash-getStash = HermitM (\ _ s -> return $ return (s, s))+instance IsString LemmaName where fromString = LemmaName+instance Show LemmaName where show (LemmaName s) = s --- | Replace the stash of saved definitions.-putStash :: DefStash -> HermitM ()-putStash s = HermitM (\ _ _ -> return $ return (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+ } -class HasHermitMEnv m where- -- | Get the HermitMEnv- getHermitMEnv :: m HermitMEnv+-- | A collectin of named lemmas.+type Lemmas = Map LemmaName Lemma -instance HasHermitMEnv HermitM where- getHermitMEnv = HermitM (\ rdr s -> return $ return (s, snd rdr))+-- | The HermitM reader environment.+data HermitMEnv = HermitMEnv { hEnvModGuts :: ModGuts -- ^ Note: this is a snapshot of the ModGuts from+ -- before the current transformation.+ , hEnvStash :: DefStash+ , hEnvLemmas :: Lemmas+ } -class HasModGuts m where- -- | Get the ModGuts (Note: this is a snapshot of the ModGuts from before the current transformation.)- getModGuts :: m ModGuts+mkEnv :: ModGuts -> DefStash -> Lemmas -> HermitMEnv+mkEnv = HermitMEnv -instance HasModGuts HermitM where- getModGuts = HermitM (\ rdr s -> return $ return (s, fst rdr))+-- | The HermitM result record.+data HermitMResult a = HermitMResult { hResStash :: DefStash+ , hResLemmas :: Lemmas+ , hResult :: a+ } -class HasHscEnv m where- getHscEnv :: m HscEnv+mkResult :: DefStash -> Lemmas -> a -> HermitMResult a+mkResult = HermitMResult -instance HasHscEnv CoreM where- getHscEnv = getHscEnvCoreM+mkResultEnv :: HermitMEnv -> a -> HermitMResult a+mkResultEnv env = mkResult (hEnvStash env) (hEnvLemmas env) -instance HasHscEnv HermitM where- getHscEnv = liftCoreM getHscEnv+-- | The HERMIT monad is kept abstract.+--+-- It provides a reader for ModGuts, state for DefStash and Lemmas,+-- and access to a debugging channel.+newtype HermitM a = HermitM { runHermitM :: DebugChan -> HermitMEnv -> CoreM (KureM (HermitMResult a)) } -sendDebugMessage :: DebugMessage -> HermitM ()-sendDebugMessage msg = do env <- getHermitMEnv- hs_debugChan env msg+type DebugChan = DebugMessage -> HermitM () --- | Save a definition for future use.-saveDef :: Label -> CoreDef -> HermitM ()-saveDef l d = getStash >>= (insert l d >>> putStash)+-- | Eliminator for 'HermitM'.+runHM :: DebugChan -- debug chan+ -> HermitMEnv -- env+ -> (HermitMResult a -> CoreM b) -- success+ -> (String -> CoreM b) -- failure+ -> HermitM a -- ma+ -> CoreM b+runHM chan env success failure ma = runHermitM ma chan env >>= runKureM success failure --- | Lookup a previously saved definition.-lookupDef :: Label -> HermitM CoreDef-lookupDef l = getStash >>= (lookup l >>> maybe (fail "Definition not found.") return)+-- | 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 hm = do+ env <- getHermitMEnv+ c <- liftCoreM $ liftIO newTChanIO -- we are careful to do IO within liftCoreM to avoid the MonadIO constraint+ r <- liftCoreM (runHermitM hm (liftIO . atomically . writeTChan c) env) >>= runKureM return fail+ chan <- getDebugChan+ let relayDebugMessages = do+ mm <- liftCoreM $ liftIO $ atomically $ tryReadTChan c+ case mm of+ Nothing -> return ()+ Just dm -> chan dm >> relayDebugMessages -----------------------------------------------------------------------------+ relayDebugMessages+ putStash $ hResStash r+ forM_ (toList (hResLemmas r)) $ uncurry insertLemma+ return $ hResult r instance Functor HermitM where fmap :: (a -> b) -> HermitM a -> HermitM b@@ -130,24 +154,22 @@ instance Monad HermitM where return :: a -> HermitM a- return a = HermitM $ \ _ s -> return (return (s,a))+ return a = HermitM $ \ _ env -> return (return (mkResultEnv env a)) (>>=) :: HermitM a -> (a -> HermitM b) -> HermitM b- (HermitM gcm) >>= f = HermitM $ \ env -> gcm env >=> runKureM (\ (s', a) -> runHermitM (f a) env s') (return . fail)+ (HermitM gcm) >>= f =+ HermitM $ \ chan env -> gcm chan env >>= runKureM (\ (HermitMResult s ls a) ->+ let env' = env { hEnvStash = s, hEnvLemmas = ls }+ in runHermitM (f a) chan env')+ (return . fail) fail :: String -> HermitM a fail msg = HermitM $ \ _ _ -> return (fail msg) instance MonadCatch HermitM where catchM :: HermitM a -> (String -> HermitM a) -> HermitM a- (HermitM gcm) `catchM` f = HermitM $ \ env s -> gcm env s >>= runKureM (return.return) (\ msg -> runHermitM (f msg) env s)---------------------------------------------------------------------------------- | 'CoreM' can be lifted to 'HermitM'.-liftCoreM :: CoreM a -> HermitM a-liftCoreM ma = HermitM $ \ _ s -> do a <- ma- return (return (s,a))+ (HermitM gcm) `catchM` f = HermitM $ \ chan env -> gcm chan env >>= runKureM (return.return)+ (\ msg -> runHermitM (f msg) chan env) instance MonadIO HermitM where liftIO :: IO a -> HermitM a@@ -170,65 +192,120 @@ -- *most* things from the current module. However, -- some Ids, such as class method selectors, are not -- explicitly bound in the core, so will not be in- -- the context. These are instead kept in the + -- the context. These are instead kept in the -- ModGuts' list of instances. Which this will find.- lookupThing nm = do-#if __GLASGOW_HASKELL__ < 708- liftCoreM (lookupThing nm)-#else- guts <- getModGuts- liftCoreM $ runTcMtoCoreM guts $ tcLookupGlobal nm-#endif+ lookupThing nm = runTcM $ tcLookupGlobal nm instance HasDynFlags HermitM where- getDynFlags :: HermitM DynFlags- getDynFlags = liftCoreM getDynFlags+ getDynFlags :: HermitM DynFlags+ getDynFlags = liftCoreM getDynFlags ---------------------------------------------------------------------------- -newName :: String -> HermitM Name-newName nm = mkSystemVarName <$> getUniqueM <*> pure (mkFastString nm)+class HasStash m where+ -- | Get the stash of saved definitions.+ getStash :: m DefStash --- | Make a unique global identifier for a specified type, using a provided name.-newGlobalIdH :: String -> Type -> HermitM Id-newGlobalIdH nm ty = mkVanillaGlobal <$> newName nm <*> pure ty+ -- | Replace the stash of saved definitions.+ putStash :: DefStash -> m () --- | Make a unique identifier for a specified type, using a provided name.-newIdH :: String -> Type -> HermitM Id-newIdH nm ty = mkLocalId <$> newName nm <*> pure ty+instance HasStash HermitM where+ getStash = HermitM $ \ _ env -> return $ return $ mkResultEnv env $ hEnvStash env --- | Make a unique type variable for a specified kind, using a provided name.-newTyVarH :: String -> Kind -> HermitM TyVar-newTyVarH nm k = mkTyVar <$> newName nm <*> pure k+ putStash s = HermitM $ \ _ env -> return $ return $ mkResult s (hEnvLemmas env) () --- | Make a unique coercion variable for a specified type, using a provided name.-newCoVarH :: String -> Type -> HermitM TyVar-newCoVarH nm ty = mkCoVar <$> newName nm <*> pure ty+-- | Save a definition for future use.+saveDef :: (HasStash m, Monad m) => RememberedName -> CoreDef -> m ()+saveDef l d = getStash >>= (insert l d >>> putStash) --- TODO: not sure if the predicates are correct.--- | Experimental, use at your own risk.-newVarH :: String -> KindOrType -> HermitM Var-newVarH name tk | isCoVarType tk = newCoVarH name tk- | isKind tk = newTyVarH name tk- | otherwise = newIdH name tk+-- | Lookup a previously saved definition.+lookupDef :: (HasStash m, Monad m) => RememberedName -> m CoreDef+lookupDef l = getStash >>= (lookup l >>> maybe (fail "Definition not found.") return) --- | Make a new variable of the same type, with a modified textual name.-cloneVarH :: (String -> String) -> Var -> HermitM Var-cloneVarH 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 = nameMod (uqName v)- ty = varType v+---------------------------------------------------------------------------- +class HasHermitMEnv m where+ -- | Get the HermitMEnv+ getHermitMEnv :: m HermitMEnv++instance HasHermitMEnv HermitM where+ getHermitMEnv = HermitM $ \ _ env -> return $ return $ mkResultEnv env env++getModGuts :: (HasHermitMEnv m, Monad m) => m ModGuts+getModGuts = liftM hEnvModGuts getHermitMEnv+ ---------------------------------------------------------------------------- --- | A message packet.-data DebugMessage = DebugTick String- | DebugCore String HermitC CoreTC+class HasDebugChan m where+ -- | Get the debugging channel+ getDebugChan :: m (DebugMessage -> m ()) -mkHermitMEnv :: (DebugMessage -> HermitM ()) -> HermitMEnv-mkHermitMEnv debugger = HermitMEnv { hs_debugChan = debugger }+instance HasDebugChan HermitM where+ getDebugChan = HermitM $ \ chan env -> return $ return $ mkResultEnv env chan +sendDebugMessage :: (HasDebugChan m, Monad m) => DebugMessage -> m ()+sendDebugMessage msg = getDebugChan >>= ($ msg)+ ----------------------------------------------------------------------------++class HasHscEnv m where+ getHscEnv :: m HscEnv++instance HasHscEnv CoreM where+ getHscEnv = getHscEnvCoreM++instance HasHscEnv HermitM where+ getHscEnv = liftCoreM getHscEnv++----------------------------------------------------------------------------++class HasLemmas m where+ -- | Add (or replace) a named lemma.+ insertLemma :: LemmaName -> Lemma -> m ()++ getLemmas :: m Lemmas++instance HasLemmas HermitM where+ insertLemma nm l = HermitM $ \ _ env -> return $ return $ mkResult (hEnvStash env) (insert nm l $ hEnvLemmas env) ()++ getLemmas = HermitM $ \ _ env -> return $ return $ mkResultEnv env (hEnvLemmas env)++-- | Only adds a lemma if doesn't already exist.+addLemma :: (HasLemmas m, Monad m) => LemmaName -> Lemma -> m ()+addLemma nm l = do+ ls <- getLemmas+ maybe (insertLemma nm l) (\ _ -> return ()) (lookup nm ls)++----------------------------------------------------------------------------++class Monad m => LiftCoreM m where+ -- | 'CoreM' can be lifted to this monad.+ liftCoreM :: CoreM a -> m a++instance LiftCoreM HermitM where+ liftCoreM coreM = HermitM $ \ _ env -> coreM >>= return . return . mkResultEnv env++----------------------------------------------------------------------------++-- | A message packet.+data DebugMessage :: * where+ DebugTick :: String -> DebugMessage+ DebugCore :: (ReadBindings c, ReadPath c Crumb) => String -> c -> CoreTC -> DebugMessage++----------------------------------------------------------------------------++runTcM :: (HasDynFlags m, HasHermitMEnv m, HasHscEnv m, MonadIO m) => TcM a -> m a+runTcM m = do+ env <- getHscEnv+ dflags <- getDynFlags+ guts <- getModGuts+ -- What is the effect of HsSrcFile (should we be using something else?)+ -- What should the boolean flag be set to?+ (msgs, mr) <- liftIO $ initTcFromModGuts env guts HsSrcFile False m+ let showMsgs (warns, errs) = showSDoc dflags $ vcat+ $ text "Errors:" : pprErrMsgBag errs+ ++ text "Warnings:" : pprErrMsgBag warns+ maybe (fail $ showMsgs msgs) return mr++runDsM :: (HasDynFlags m, HasHermitMEnv m, HasHscEnv m, MonadIO m) => DsM a -> m a+runDsM = runTcM . initDsTc
src/HERMIT/Name.hs view
@@ -1,15 +1,23 @@-{-# LANGUAGE CPP #-}-#if __GLASGOW_HASKELL__ <= 706-{-# LANGUAGE ScopedTypeVariables #-}-#endif-module HERMIT.Name +{-# LANGUAGE CPP, DeriveDataTypeable, FlexibleInstances, TypeFamilies #-}+module HERMIT.Name ( HermitName+ , cmpHN2Name+ , cmpHN2Var , fromRdrName , toRdrName , toRdrNames , hnModuleName , hnUnqualified , parseName+ , showName+ -- * Wrappers+ , OccurrenceName(..)+ , OccurrenceNameListBox(..)+ , mkOccPred+ , BindingName(..)+ , mkBindingPred+ , RhsOfName(..)+ , mkRhsOfPred -- * Namespaces , Named(..) , varToNamed@@ -18,37 +26,36 @@ , tyConClassNS , tyVarNS , varNS+ -- * Variable Creation+ , newGlobalIdH+ , newIdH+ , newTyVarH+ , newCoVarH+ , newVarH+ , cloneVarH -- * Name Lookup , findId-#if __GLASGOW_HASKELL__ > 706 , findVar , findTyCon , findType , findInNameSpace , findInNameSpaces-#endif ) where import Control.Monad import Control.Monad.IO.Class -#if __GLASGOW_HASKELL__ <= 706 import Data.List (intercalate)-#endif+import Data.Dynamic (Typeable)+import Data.String (IsString(..)) import HERMIT.Context+import HERMIT.External import HERMIT.GHC import HERMIT.Kure import HERMIT.Monad --- | A 'HermitName' is an optionally fully-qualified name,--- like GHC's 'RdrName', but without specifying which 'NameSpace'--- the name is found in.-data HermitName = HermitName { hnModuleName :: Maybe ModuleName- , hnUnqualified :: String - }---- | Possible results from name lookup. +-- | Possible results from name lookup. -- Invariant: One constructor for each NameSpace. data Named = NamedId Id | NamedDataCon DataCon@@ -88,15 +95,63 @@ ---------------------------------------------------------- +-- | A 'HermitName' is an optionally fully-qualified name,+-- like GHC's 'RdrName', but without specifying which 'NameSpace'+-- the name is found in.+data HermitName = HermitName { hnModuleName :: Maybe ModuleName+ , hnUnqualified :: String+ }+ deriving (Eq, Typeable)++instance Extern HermitName where+ type Box HermitName = HermitName+ box = id+ unbox = id++instance IsString HermitName where fromString = parseName+instance Show HermitName where show = showName++-- | Compare a HermitName to a Var.+--+-- Only compare module names if the HermitName is fully qualified.+-- Otherwise match variables from any module with appropriate occurrence name.+cmpHN2Var :: HermitName -> Var -> Bool+cmpHN2Var hn = cmpHN2Name hn . varName++cmpHN2Name :: HermitName -> Name -> Bool+cmpHN2Name (HermitName hm nm) n+ | Just mn <- hm+ , Just m <- nameModule_maybe n = (mn == moduleName m) && sameOccName+ | otherwise = sameOccName+ where sameOccName = nm == unqualifiedName 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--- mkOccName--- mkRdrQual +-- | Make an unqualified HermitName from a String. mkUnqualified :: String -> HermitName mkUnqualified = HermitName Nothing--- mkRdrUnqual +-- | Parse a HermitName from a String.+parseName :: String -> HermitName+parseName s | isQualified s = parseQualified s+ | otherwise = mkUnqualified s++-- | Parse a qualified HermitName from a String.+parseQualified :: String -> HermitName+parseQualified [] = error "parseQualified: empty string"+parseQualified s = mkQualified mnm nm+ where (c:cs) = reverse s -- we are careful to parse 'Prelude..' correctly+ (rNm, _dot:rMod) = break (=='.') cs+ (nm, mnm) = (reverse (c:rNm), reverse rMod)++-- | 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++-- | Make a HermitName from a RdrName fromRdrName :: RdrName -> HermitName fromRdrName nm = case isQual_maybe nm of Nothing -> HermitName Nothing (occNameString $ rdrNameOcc nm)@@ -111,26 +166,55 @@ toRdrNames :: [NameSpace] -> HermitName -> [RdrName] toRdrNames nss hnm = [ toRdrName ns hnm | ns <- nss ] -parseQualified :: String -> HermitName-parseQualified [] = error "parseQualified: empty string"-parseQualified s = mkQualified mnm nm- where (c:cs) = reverse s -- we are careful to parse 'Prelude..' correctly- (rNm, _dot:rMod) = break (=='.') cs- (nm, mnm) = (reverse (c:rNm), reverse rMod)+-------------------------------------------------------------------------------------------------- --- | Parse a HermitName from a String.-parseName :: String -> HermitName-parseName s | isQualified s = parseQualified s- | otherwise = mkUnqualified s+-- Newtype wrappers used for type-based command completion +newtype BindingName = BindingName { unBindingName :: HermitName } deriving Typeable++instance Extern BindingName where+ type Box BindingName = BindingName+ box = id+ unbox = id++mkBindingPred :: BindingName -> Var -> Bool+mkBindingPred (BindingName hnm) = cmpHN2Var hnm++newtype OccurrenceName = OccurrenceName { unOccurrenceName :: HermitName } deriving Typeable++instance Extern OccurrenceName where+ type Box OccurrenceName = OccurrenceName+ box = id+ unbox = id++mkOccPred :: OccurrenceName -> Var -> Bool+mkOccPred (OccurrenceName hnm) = cmpHN2Var hnm++newtype OccurrenceNameListBox = OccurrenceNameListBox [OccurrenceName] deriving Typeable++instance Extern [OccurrenceName] where+ type Box [OccurrenceName] = OccurrenceNameListBox+ box = OccurrenceNameListBox+ unbox (OccurrenceNameListBox l) = l++newtype RhsOfName = RhsOfName { unRhsOfName :: HermitName } deriving Typeable++instance Extern RhsOfName where+ type Box RhsOfName = RhsOfName+ box = id+ unbox = id++mkRhsOfPred :: RhsOfName -> Var -> Bool+mkRhsOfPred (RhsOfName hnm) = cmpHN2Var hnm+ -------------------------------------------------------------------------------------------------- -- | An instance of 'MonadThings' for 'Transform', which looks in the context first. -- -- NB: we store TyVars in the context, but the 'TyThing' return type is not rich enough--- to return them. So 'lookupThing' cannot be used to look up TyVars. +-- to return them. So 'lookupThing' cannot be used to look up TyVars. -- TODO: add function for this, or modify GHC's 'TyThing'?-instance (MonadThings m, BoundVars c) => MonadThings (Transform c m a) where +instance (MonadThings m, BoundVars c) => MonadThings (Transform c m a) where lookupThing nm = contextonlyT $ \ c -> case varSetElems $ filterVarSet ((== nm) . varName) (boundVars c) of (i:_) | isVarName nm -> return $ AnId i@@ -140,9 +224,8 @@ -------------------------------------------------------------------------------------------------- -#if __GLASGOW_HASKELL__ > 706-findId :: (BoundVars c, HasHscEnv m, HasModGuts m, MonadCatch m, MonadIO m, MonadThings m) - => String -> c -> m Id+findId :: (BoundVars c, HasHscEnv m, HasHermitMEnv m, MonadCatch m, MonadIO m, MonadThings m)+ => HermitName -> c -> m Id findId nm c = do nmd <- findInNameSpaces [varNS, dataConNS] nm c case nmd of@@ -150,8 +233,8 @@ NamedDataCon dc -> return $ dataConWrapId dc other -> fail $ "findId: impossible Named returned: " ++ show other -findVar :: (BoundVars c, HasHscEnv m, HasModGuts m, MonadCatch m, MonadIO m, MonadThings m) - => String -> c -> m Var+findVar :: (BoundVars c, HasHscEnv m, HasHermitMEnv m, MonadCatch m, MonadIO m, MonadThings m)+ => HermitName -> c -> m Var findVar nm c = do nmd <- findInNameSpaces [varNS, tyVarNS, dataConNS] nm c case nmd of@@ -160,16 +243,16 @@ NamedDataCon dc -> return $ dataConWrapId dc other -> fail $ "findVar: impossible Named returned: " ++ show other -findTyCon :: (BoundVars c, HasHscEnv m, HasModGuts m, MonadCatch m, MonadIO m, MonadThings m) - => String -> c -> m TyCon+findTyCon :: (BoundVars c, HasHscEnv m, HasHermitMEnv m, MonadCatch m, MonadIO m, MonadThings m)+ => HermitName -> c -> m TyCon findTyCon nm c = do nmd <- findInNameSpace tyConClassNS nm c case nmd of NamedTyCon tc -> return tc other -> fail $ "findTyCon: impossible Named returned: " ++ show other -findType :: (BoundVars c, HasHscEnv m, HasModGuts m, MonadCatch m, MonadIO m, MonadThings m) - => String -> c -> m Type+findType :: (BoundVars c, HasHscEnv m, HasHermitMEnv m, MonadCatch m, MonadIO m, MonadThings m)+ => HermitName -> c -> m Type findType nm c = do nmd <- findInNameSpaces [tyVarNS, tyConClassNS] nm c case nmd of@@ -179,21 +262,21 @@ -------------------------------------------------------------------------------------------------- -findInNameSpaces :: (BoundVars c, HasHscEnv m, HasModGuts m, MonadCatch m, MonadIO m, MonadThings m) - => [NameSpace] -> String -> c -> m Named+findInNameSpaces :: (BoundVars c, HasHscEnv m, HasHermitMEnv m, MonadCatch m, MonadIO m, MonadThings m)+ => [NameSpace] -> HermitName -> c -> m Named findInNameSpaces nss nm c = setFailMsg "Variable not in scope." -- because catchesM clobbers failure messages. $ catchesM [ findInNameSpace ns nm c | ns <- nss ] -findInNameSpace :: (BoundVars c, HasHscEnv m, HasModGuts m, MonadIO m, MonadThings m) - => NameSpace -> String -> c -> m Named-findInNameSpace ns nm c = - case filter ((== ns) . occNameSpace . getOccName) $ varSetElems (findBoundVars nm c) of+findInNameSpace :: (BoundVars c, HasHscEnv m, HasHermitMEnv m, MonadIO m, MonadThings m)+ => NameSpace -> HermitName -> c -> m Named+findInNameSpace ns nm c =+ case varSetElems $ filterVarSet ((== ns) . occNameSpace . getOccName) $ findBoundVars (cmpHN2Var nm) c of _ : _ : _ -> fail "multiple matching variables in scope." [v] -> return $ varToNamed v- [] -> findInNSModGuts ns (parseName nm)+ [] -> findInNSModGuts ns nm -- | Looks for Named in current GlobalRdrEnv. If not present, calls 'findInNSPackageDB'.-findInNSModGuts :: (HasHscEnv m, HasModGuts m, MonadIO m, MonadThings m) +findInNSModGuts :: (HasHscEnv m, HasHermitMEnv m, MonadIO m, MonadThings m) => NameSpace -> HermitName -> m Named findInNSModGuts ns nm = do rdrEnv <- liftM mg_rdr_env getModGuts@@ -203,37 +286,37 @@ _ -> fail "findInNSModGuts: multiple names returned" -- | Looks for Named in package database, or built-in packages.-findInNSPackageDB :: (HasHscEnv m, HasModGuts m, MonadIO m, MonadThings m) +findInNSPackageDB :: (HasHscEnv m, HasHermitMEnv m, MonadIO m, MonadThings m) => NameSpace -> HermitName -> m Named findInNSPackageDB ns nm = do mnm <- lookupName ns nm case mnm of- Nothing -> findNamedBuiltIn ns (hnUnqualified nm)+ Nothing -> findNamedBuiltIn ns nm Just n -> nameToNamed n --- | Helper to call GHC's lookupRdrNameInModuleForPlugins-lookupName :: (HasModGuts m, HasHscEnv m, MonadIO m) => NameSpace -> HermitName -> m (Maybe Name)+-- | Helper to call lookupRdrNameInModule+lookupName :: (HasHermitMEnv m, HasHscEnv m, MonadIO m) => NameSpace -> HermitName -> m (Maybe Name) lookupName ns nm = case isQual_maybe rdrName of Nothing -> return Nothing -- we can't use lookupName on the current module Just (m,_) -> do hscEnv <- getHscEnv guts <- getModGuts- liftIO $ lookupRdrNameInModuleForPlugins hscEnv guts m rdrName+ liftIO $ lookupRdrNameInModule hscEnv guts m rdrName where rdrName = toRdrName ns nm -- | Looks for Named amongst GHC's built-in DataCons/TyCons.-findNamedBuiltIn :: Monad m => NameSpace -> String -> m Named-findNamedBuiltIn ns str- | isValNameSpace ns = - case [ dc | tc <- wiredInTyCons, dc <- tyConDataCons tc, str == getOccString dc ] of+findNamedBuiltIn :: Monad m => NameSpace -> HermitName -> m Named+findNamedBuiltIn ns hnm+ | isValNameSpace ns =+ case [ dc | tc <- wiredInTyCons, dc <- tyConDataCons tc, cmpHN2Name hnm (getName dc) ] of [] -> fail "name not in scope." [dc] -> return $ NamedDataCon dc- dcs -> fail $ "multiple DataCons match: " ++ show (map getOccString dcs)- | isTcClsNameSpace ns = - case [ tc | tc <- wiredInTyCons, str == getOccString tc ] of+ dcs -> fail $ "multiple DataCons match: " ++ intercalate ", " (map unqualifiedName dcs)+ | isTcClsNameSpace ns =+ case [ tc | tc <- wiredInTyCons, cmpHN2Name hnm (getName tc) ] of [] -> fail "type name not in scope." [tc] -> return $ NamedTyCon tc- tcs -> fail $ "multiple TyCons match: " ++ show (map getOccString tcs)+ tcs -> fail $ "multiple TyCons match: " ++ intercalate ", " (map unqualifiedName tcs) | otherwise = fail "findNameBuiltIn: unusable NameSpace" -- | We have a name, find the corresponding Named.@@ -244,49 +327,47 @@ | isTyVarName n = fail "nameToNamed: impossible, TyVars are not exported and cannot be looked up." | otherwise = fail "nameToNamed: unknown name type" -#else---- | Looks for Id with given name in the context. If it is not present, calls 'findIdMG'.-findId :: (BoundVars c, HasModGuts m, HasHscEnv m, MonadCatch m, MonadIO m, MonadThings m) => String -> c -> m Id-findId nm c = case varSetElems (findBoundVars nm c) of- [] -> findIdMG (parseName nm) - [v] -> return v- _ : _ : _ -> fail "multiple matching variables in scope."--findIdMG :: (HasModGuts m, MonadThings m) => HermitName -> m Id-findIdMG hnm = do- let nm = hnUnqualified hnm- rdrEnv <- liftM mg_rdr_env getModGuts- case filter isValName $ findNamesFromString rdrEnv nm of- [] -> findIdBuiltIn nm- [n] -> nameToId n- ns -> fail $ "multiple matches found:\n" ++ intercalate ", " (map getOccString ns)+-- Someday, when Applicative is a superclass of monad, we can uncomment the+-- nicer applicative definitions. For now, we don't want the extra constraint. --- | We have a name, find the corresponding Id.-nameToId :: MonadThings m => Name -> m Id-nameToId n | isVarName n = lookupId n- | isDataConName n = liftM dataConWrapId $ lookupDataCon n- | otherwise = fail "nameToId: unknown name type"+-- | 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) -findIdBuiltIn :: forall m. Monad m => String -> m Id-findIdBuiltIn = go- where go ":" = dataConId consDataCon- go "[]" = dataConId nilDataCon+-- | 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 - go "True" = return trueDataConId- go "False" = return falseDataConId+-- | 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 - go "<" = return ltDataConId- go "==" = return eqDataConId- go ">" = return gtDataConId+-- | 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 - go "I#" = dataConId intDataCon+-- | 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 - go "()" = return unitDataConId- -- TODO: add more as needed- -- http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/TysWiredIn.html- go _ = fail "variable not in scope."+-- TODO: not sure if the predicates are correct.+-- | Experimental, use at your own risk.+newVarH :: MonadUnique m => String -> KindOrType -> m Var+newVarH name tk | isCoVarType tk = newCoVarH name tk+ | isKind tk = newTyVarH name tk+ | otherwise = newIdH name tk - dataConId :: DataCon -> m Id- dataConId = return . dataConWorkId-#endif+-- | Make a new variable of the same type, with a modified textual name.+cloneVarH :: MonadUnique m => (String -> String) -> Var -> m Var+cloneVarH 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 = nameMod (unqualifiedName v)+ ty = varType v
src/HERMIT/Parser.y view
@@ -5,6 +5,7 @@ , unparseScript , unparseExprH , ExprH(..)+ , parseExprH ) where import Data.Char (isSpace)@@ -16,7 +17,8 @@ } -%name parser+%name parser scoped+%name exprParser ExprH %tokentype { Token } %error { parseError } %monad { Either String } { >>= } { return }@@ -162,6 +164,9 @@ parseScript :: String -> Either String Script parseScript = lexer >=> parser++parseExprH :: String -> Either String ExprH+parseExprH = lexer >=> exprParser ---------------------------------------------
src/HERMIT/ParserCore.y view
@@ -3,6 +3,8 @@ module HERMIT.ParserCore ( parseCore , parseCoreExprT+ , parse2BeforeT+ , parse3BeforeT , parse2beforeBiR , parse3beforeBiR , parse4beforeBiR@@ -89,21 +91,17 @@ { mkIntExpr' :: Integer -> CoreParseM CoreExpr-#if __GLASGOW_HASKELL__ > 706 mkIntExpr' i = do dflags <- lift getDynFlags return $ mkIntExpr dflags i-#else-mkIntExpr' i = return $ mkIntExpr i-#endif lookupName :: String -> CoreParseM CoreExpr lookupName nm = do- c <- ask- v <- lift $ prefixFailMsg (nm ++ " lookup: ") $ findId nm c+ vset <- ask+ v <- lift $ prefixFailMsg (nm ++ " lookup: ") $ findId (parseName nm) vset return $ varToCoreExpr v -type CoreParseM a = ReaderT HermitC HermitM a+type CoreParseM a = ReaderT VarSet HermitM a parseError :: Monad m => [Token] -> m a parseError ts = fail $ "core parse error: " ++ show ts@@ -170,19 +168,30 @@ --------------------------------------------- -parseCore :: CoreString -> HermitC -> HermitM CoreExpr+parseCore :: BoundVars c => CoreString -> c -> HermitM CoreExpr parseCore (CoreString s) c = case lexer s of Left msg -> fail msg- Right tokens -> runReaderT (parser tokens) c+ Right tokens -> runReaderT (parser tokens) (boundVars c) --------------------------------------------- -- These should probably go somewhere else. -- | Parse a 'CoreString' to a 'CoreExpr', using the current context.-parseCoreExprT :: CoreString -> TransformH a CoreExpr-parseCoreExprT = contextonlyT . parseCore+parseCoreExprT :: (BoundVars c, HasDebugChan m, HasHermitMEnv m, HasLemmas m, HasStash 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)+ => (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)+ => (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) parse2beforeBiR :: (CoreExpr -> CoreExpr -> BiRewriteH a) -> CoreString -> CoreString -> BiRewriteH a
src/HERMIT/ParserType.y view
@@ -1,15 +1,11 @@ { {-# LANGUAGE CPP #-} module HERMIT.ParserType-#if __GLASGOW_HASKELL__ <= 706- () where-#else ( parseType , parseTypeT , parseTypeWithHoles , parseTypeWithHolesT ) where-#endif import Control.Arrow import Control.Monad.State@@ -87,14 +83,10 @@ tyvar : NAME {% lookupName $1 } { -#if __GLASGOW_HASKELL__ <= 706-findType = error "findType cannot be called in < GHC 7.8"-#endif- lookupName :: String -> TypeParseM Type lookupName nm = do c <- getContext- et <- lift $ attemptM $ findType nm c+ et <- lift $ attemptM $ findType (parseName nm) c either (const (addTyVar nm)) return et catchFrees :: Type -> TypeParseM ([TyVar], Type)@@ -117,7 +109,7 @@ addTyVar :: String -> TypeParseM Type addTyVar tvStr = do used <- gets tpUsed- case [ tv | tv <- used, getOccString tv == tvStr ] of+ case [ tv | tv <- used, unqualifiedName tv == tvStr ] of [] -> do tv <- lift $ newTyVarH tvStr liftedTypeKind modify $ \ st -> st { tpUsed = tv : tpUsed st } return $ mkTyVarTy tv
src/HERMIT/Plugin.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE KindSignatures, GADTs, FlexibleContexts, GeneralizedNewtypeDeriving, LambdaCase #-}+{-# LANGUAGE KindSignatures, GADTs, FlexibleContexts, GeneralizedNewtypeDeriving, LambdaCase, CPP #-} module HERMIT.Plugin ( -- * The HERMIT Plugin hermitPlugin@@ -12,15 +12,15 @@ , setPrettyOptions -- ** Active modifiers , at- , phase+ , pass , after , before , until- , allPhases- , firstPhase- , lastPhase+ , allPasses+ , firstPass+ , lastPass -- ** Knobs and Dials- , getPhaseInfo+ , getPassInfo , modifyCLS -- ** Types , defPS@@ -31,7 +31,11 @@ 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.Operational import Control.Monad.State hiding (guard) @@ -40,12 +44,12 @@ import HERMIT.Dictionary import HERMIT.External hiding (Query, Shell)+import HERMIT.Kernel (KernelEnv) import HERMIT.Kernel.Scoped import HERMIT.Context import HERMIT.Kure import HERMIT.GHC hiding (singleton, liftIO, display, (<>)) import qualified HERMIT.GHC as GHC-import HERMIT.Monad import HERMIT.Plugin.Builder import qualified HERMIT.Plugin.Display as Display@@ -59,13 +63,11 @@ import Prelude hiding (until) -import System.Console.Haskeline (defaultBehavior)- hermitPlugin :: ([CommandLineOption] -> HPM ()) -> Plugin-hermitPlugin f = buildPlugin $ \ phaseInfo -> runHPM phaseInfo . f+hermitPlugin f = buildPlugin $ \ passInfo -> runHPM passInfo . f -defPS :: SAST -> ScopedKernel -> PhaseInfo -> IO PluginState-defPS initSAST kernel phaseInfo = do+defPS :: SAST -> ScopedKernel -> PassInfo -> IO PluginState+defPS initSAST kernel passInfo = do emptyTick <- liftIO $ atomically $ newTVar M.empty return $ PluginState { ps_cursor = initSAST@@ -76,12 +78,12 @@ , ps_diffonly = False , ps_failhard = False , ps_kernel = kernel- , ps_phase = phaseInfo+ , ps_pass = passInfo } data HPMInst :: * -> * where Shell :: [External] -> [CommandLineOption] -> HPMInst ()- Guard :: (PhaseInfo -> Bool) -> HPM () -> HPMInst ()+ Guard :: (PassInfo -> Bool) -> HPM () -> HPMInst () Focus :: (Injection ModGuts g, Walker HermitC g) => TransformH g LocalPathH -> HPM a -> HPMInst a RR :: (Injection ModGuts g, Walker HermitC g) => RewriteH g -> HPMInst () Query :: (Injection ModGuts g, Walker HermitC g) => TransformH g a -> HPMInst a@@ -89,14 +91,18 @@ newtype HPM a = HPM { unHPM :: ProgramT HPMInst PluginM a } deriving (Functor, Applicative, Monad, MonadIO) -runHPM :: PhaseInfo -> HPM () -> ModGuts -> CoreM ModGuts-runHPM phaseInfo pass = scopedKernel $ \ kernel initSAST -> do- ps <- defPS initSAST kernel phaseInfo- (r,st) <- hpmToIO ps pass+runHPM :: PassInfo -> HPM () -> ModGuts -> CoreM ModGuts+runHPM passInfo hpass = scopedKernel $ \ kernel initSAST -> do+ ps <- defPS initSAST 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 -> resumeS kernel sast+ PResume sast -> cleanup sast PError err -> putStrLn err >> abortS kernel)- (\ _ -> resumeS kernel $ ps_cursor st) r+ (\ _ -> cleanup $ ps_cursor st) r hpmToIO :: PluginState -> HPM a -> IO (Either PException a, PluginState) hpmToIO initState = runPluginT initState . eval . unHPM@@ -113,11 +119,11 @@ -- We want to discard the current focus, open the shell at -- the top level, then restore the current focus. paths <- resetScoping env- clm (commandLine os defaultBehavior es)+ clm (commandLine interpShellCommand os es) _ <- resetScoping env restoreScoping env paths eval $ k ()- Guard p (HPM m) :>>= k -> gets (p . ps_phase) >>= \ b -> when b (eval m) >>= 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@@ -128,7 +134,7 @@ ------------------------- Shell-related helpers -------------------------------------- -resetScoping :: HermitMEnv -> PluginM [PathH]+resetScoping :: KernelEnv -> PluginM [PathH] resetScoping env = do kernel <- gets ps_kernel paths <- runK $ pathS kernel@@ -137,7 +143,7 @@ catchM (runS $ modPathS kernel (const mempty) env) (const (return ())) return paths -restoreScoping :: HermitMEnv -> [PathH] -> PluginM ()+restoreScoping :: KernelEnv -> [PathH] -> PluginM () restoreScoping _ [] = return () restoreScoping env (h:t) = do kernel <- gets ps_kernel@@ -172,41 +178,41 @@ ----------------------------- guards ------------------------------ -guard :: (PhaseInfo -> Bool) -> HPM () -> HPM ()+guard :: (PassInfo -> Bool) -> HPM () -> HPM () guard p = HPM . singleton . Guard p at :: TransformH CoreTC LocalPathH -> HPM a -> HPM a at tp = HPM . singleton . Focus tp -phase :: Int -> HPM () -> HPM ()-phase n = guard ((n ==) . phaseNum)+pass :: Int -> HPM () -> HPM ()+pass n = guard ((n ==) . passNum) after :: CorePass -> HPM () -> HPM ()-after cp = guard (\phaseInfo -> case phasesDone phaseInfo of+after cp = guard (\passInfo -> case passesDone passInfo of [] -> False xs -> last xs == cp) before :: CorePass -> HPM () -> HPM ()-before cp = guard (\phaseInfo -> case phasesLeft phaseInfo of+before cp = guard (\passInfo -> case passesLeft passInfo of (x:_) | cp == x -> True _ -> False) until :: CorePass -> HPM () -> HPM ()-until cp = guard ((cp `elem`) . phasesLeft)+until cp = guard ((cp `elem`) . passesLeft) -allPhases :: HPM () -> HPM ()-allPhases = guard (const True)+allPasses :: HPM () -> HPM ()+allPasses = guard (const True) -firstPhase :: HPM () -> HPM ()-firstPhase = guard (null . phasesDone)+firstPass :: HPM () -> HPM ()+firstPass = guard (null . passesDone) -lastPhase :: HPM () -> HPM ()-lastPhase = guard (null . phasesLeft)+lastPass :: HPM () -> HPM ()+lastPass = guard (null . passesLeft) ----------------------------- other ------------------------------ -getPhaseInfo :: HPM PhaseInfo-getPhaseInfo = HPM $ lift $ gets ps_phase+getPassInfo :: HPM PassInfo+getPassInfo = HPM $ lift $ gets ps_pass display :: HPM () display = HPM $ lift $ Display.display Nothing
src/HERMIT/Plugin/Builder.hs view
@@ -7,8 +7,8 @@ , CorePass(..) , getCorePass , ghcPasses- , PhaseInfo(..)- , getPhaseFlag+ , PassInfo(..)+ , getPassFlag ) where import Data.List@@ -17,7 +17,7 @@ import HERMIT.GHC -- | Given a list of 'CommandLineOption's, produce the 'ModGuts' to 'ModGuts' function required to build a plugin.-type PluginPass = PhaseInfo -> [CommandLineOption] -> ModGuts -> CoreM ModGuts+type PluginPass = PassInfo -> [CommandLineOption] -> ModGuts -> CoreM ModGuts -- | Build a plugin. This mainly handles the per-module options. buildPlugin :: PluginPass -> Plugin@@ -31,6 +31,9 @@ liftIO $ hSetBuffering stdout NoBuffering #ifdef mingw32_HOST_OS liftIO $ hSetEncoding stdout utf8+ -- This is a hacky workaround of a bug in Windows GHC.+ -- See https://ghc.haskell.org/trac/ghc/ticket/8276+ liftIO initStaticOpts #endif let todos' = flattenTodos todos@@ -38,12 +41,12 @@ 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 (PhaseInfo n ps ps') opts+ mkPass n ps ps' = CoreDoPluginPass ("HERMIT" ++ show n) $ modFilter hp (PassInfo n ps ps') opts return allPasses -- | Determine whether to act on this module, choose plugin pass.--- NB: we have the ability to stick module info in the phase info here+-- NB: we have the ability to stick module info in the pass info here modFilter :: PluginPass -> PluginPass modFilter hp pInfo opts guts | null modOpts && notNull opts = return guts -- don't process this module@@ -64,7 +67,7 @@ where modName = moduleNameString $ moduleName $ mg_module guts len = length modName + 1 -- for the colon --- | An enumeration type for GHC's phases.+-- | An enumeration type for GHC's passes. data CorePass = FloatInwards | LiberateCase | PrintCore@@ -112,26 +115,26 @@ ] getCorePass :: CoreToDo -> CorePass-getCorePass CoreDoFloatInwards = FloatInwards-getCorePass CoreLiberateCase = LiberateCase-getCorePass CoreDoPrintCore = PrintCore-getCorePass CoreDoStaticArgs = StaticArgs-getCorePass CoreDoStrictness = Strictness-getCorePass CoreDoWorkerWrapper = WorkerWrapper-getCorePass CoreDoSpecialising = Specialising-getCorePass CoreDoSpecConstr = SpecConstr-getCorePass CoreCSE = CSE-getCorePass CoreDoVectorisation = Vectorisation-getCorePass CoreDesugar = Desugar-getCorePass CoreDesugarOpt = DesugarOpt-getCorePass CoreTidy = Tidy-getCorePass CorePrep = Prep-getCorePass (CoreDoSimplify {}) = Simplify+getCorePass CoreDoFloatInwards = FloatInwards+getCorePass CoreLiberateCase = LiberateCase+getCorePass CoreDoPrintCore = PrintCore+getCorePass CoreDoStaticArgs = StaticArgs+getCorePass CoreDoStrictness = Strictness+getCorePass CoreDoWorkerWrapper = WorkerWrapper+getCorePass CoreDoSpecialising = Specialising+getCorePass CoreDoSpecConstr = SpecConstr+getCorePass CoreCSE = CSE+getCorePass CoreDoVectorisation = Vectorisation+getCorePass CoreDesugar = Desugar+getCorePass CoreDesugarOpt = DesugarOpt+getCorePass CoreTidy = Tidy+getCorePass CorePrep = Prep+getCorePass (CoreDoSimplify {}) = Simplify getCorePass (CoreDoFloatOutwards {}) = FloatOutwards-getCorePass (CoreDoRuleCheck {}) = RuleCheck-getCorePass (CoreDoPasses {}) = Passes -- these should be flattened out in practice-getCorePass (CoreDoPluginPass nm _) = PluginPass nm-getCorePass CoreDoNothing = NoOp+getCorePass (CoreDoRuleCheck {}) = RuleCheck+getCorePass (CoreDoPasses {}) = Passes -- these should be flattened out in practice+getCorePass (CoreDoPluginPass nm _) = PluginPass nm+getCorePass CoreDoNothing = NoOp -- getCorePass _ = Unknown flattenTodos :: [CoreToDo] -> [CoreToDo]@@ -140,16 +143,16 @@ f CoreDoNothing = [] f other = [other] -data PhaseInfo =- PhaseInfo { phaseNum :: Int- , phasesDone :: [CorePass]- , phasesLeft :: [CorePass]- }+data PassInfo =+ PassInfo { passNum :: Int+ , passesDone :: [CorePass]+ , passesLeft :: [CorePass]+ } deriving (Read, Show, Eq) -- | If HERMIT user specifies the -pN flag, get the N -- TODO: as written will discard other flags that start with -p-getPhaseFlag :: [CommandLineOption] -> Maybe (Int, [CommandLineOption])-getPhaseFlag opts = case partition ("-p" `isPrefixOf`) opts of+getPassFlag :: [CommandLineOption] -> Maybe (Int, [CommandLineOption])+getPassFlag opts = case partition ("-p" `isPrefixOf`) opts of ([],_) -> Nothing (ps,r) -> Just (read (drop 2 (last ps)), r)
src/HERMIT/Plugin/Renderer.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE CPP, FlexibleContexts #-} module HERMIT.Plugin.Renderer where import Control.Arrow@@ -11,9 +11,16 @@ import HERMIT.Kure import HERMIT.Plugin.Types import HERMIT.PrettyPrinter.Common+#ifdef mingw32_HOST_OS+import HERMIT.Win32.IO (hPutStr, hPutStrLn)+#endif import System.Console.ANSI+#ifdef mingw32_HOST_OS+import System.IO hiding (hPutStr, hPutStrLn)+#else import System.IO+#endif import System.IO.Temp import System.Process
src/HERMIT/Plugin/Types.hs view
@@ -1,11 +1,15 @@-{-# LANGUAGE TypeFamilies, DeriveDataTypeable, FlexibleContexts, +{-# LANGUAGE TypeFamilies, DeriveDataTypeable, FlexibleContexts, LambdaCase, GADTs, GeneralizedNewtypeDeriving,- ScopedTypeVariables, FlexibleInstances #-}+ ScopedTypeVariables, FlexibleInstances, CPP #-} 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 Data.Dynamic@@ -13,6 +17,7 @@ import HERMIT.Kure import HERMIT.External+import HERMIT.Kernel (KernelEnv(..)) import HERMIT.Kernel.Scoped import HERMIT.Monad import HERMIT.Plugin.Builder@@ -21,11 +26,19 @@ 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) 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 MonadTrans PluginT where lift = PluginT . lift . lift@@ -53,12 +66,14 @@ , ps_failhard :: Bool -- ^ if true, abort on *any* failure -- this should be in a reader , ps_kernel :: ScopedKernel- , ps_phase :: PhaseInfo+ , 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 newtype PSBox = PSBox PluginState deriving Typeable instance Extern PluginState where@@ -76,25 +91,25 @@ writeTVar var (M.insert msg c m) return c -mkKernelEnv :: PluginState -> HermitMEnv+mkKernelEnv :: PluginState -> KernelEnv mkKernelEnv st = let pp = ps_pretty st out str = liftIO $ ps_render st stdout (pOptions pp) (Left $ str ++ "\n") - in mkHermitMEnv $ \ msg -> case msg of+ in KernelEnv $ \ msg -> case msg of DebugTick msg' -> do c <- liftIO $ tick (ps_tick st) msg' out $ "<" ++ show c ++ "> " ++ msg' DebugCore msg' cxt core -> do out $ "[" ++ msg' ++ "]"- doc :: DocH <- apply (pCoreTC pp) (liftPrettyC (pOptions pp) cxt) (inject core)+ doc :: DocH <- applyT (pCoreTC pp) (liftPrettyC (pOptions pp) cxt) (inject core) 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 :: (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'' :: (MonadIO m, MonadCatch m) => IO (KureM a) -> m a iokm'' = iokm ""
src/HERMIT/PrettyPrinter/AST.hs view
@@ -115,19 +115,12 @@ <+ transCoT ppCoercion ppCoercion (\ co1 co2 -> coText "TransCo" $$ nest 2 (cat [parens co1, parens co2])) <+ nthCoT (arr $ coText . show) ppCoercion (\ n co -> coText "NthCo" <+> n $$ parens co) <+ instCoT ppCoercion ppKindOrType (\ co ty -> coText "InstCo" $$ nest 2 (cat [parens co, parens ty]))-#if __GLASGOW_HASKELL__ > 706 -- TODO: Figure out how to properly pp new branched Axioms and Left/Right Coercions <+ reflT ppKindOrType (\ r ty -> coText "Refl" <+> coText (showRole r) $$ nest 2 (parens ty)) <+ axiomInstCoT ppSDoc ppSDoc (const ppCoercion) (\ ax idx coes -> coText "AxiomInstCo" <+> ax <+> idx $$ nest 2 (vlist $ map parens coes)) <+ lrCoT ppSDoc ppCoercion (\ lr co -> coText "LRCo" <+> lr $$ nest 2 (parens co)) <+ tyConAppCoT ppSDoc (const ppCoercion) (\ r con coes -> coText "TyConAppCo" <+> coText (showRole r) <+> con $$ nest 2 (vlist $ map parens coes)) -- TODO: add UnivCo and SubCo-#else- <+ reflT (ppKindOrType >>^ \ ty -> coText "Refl" $$ nest 2 (parens ty))- <+ tyConAppCoT ppSDoc (const ppCoercion) (\ con coes -> coText "TyConAppCo" <+> con $$ nest 2 (vlist $ map parens coes))- <+ unsafeCoT ppKindOrType ppKindOrType (\ ty1 ty2 -> coText "UnsafeCo" $$ nest 2 (cat [parens ty1, parens ty2]))- <+ axiomInstCoT ppSDoc (const ppCoercion) (\ ax coes -> coText "AxiomInstCo" <+> ax $$ nest 2 (vlist $ map parens coes))-#endif ppVar :: PrettyH Var ppVar = readerT $ \ v -> ppSDoc >>^ modCol v
src/HERMIT/PrettyPrinter/Clean.hs view
@@ -1,19 +1,18 @@ {-# LANGUAGE CPP, LambdaCase, MultiWayIf #-} module HERMIT.PrettyPrinter.Clean- ( -- * HERMIT's Clean Pretty-Printer for GHC Core- pretty- , ppCoreTC- , ppModGuts- , ppCoreProg- , ppCoreBind- , ppCoreExpr- , ppCoreAlt- , ppKindOrType- , ppCoercion- , ppForallQuantification- )-where+ ( -- * HERMIT's Clean Pretty-Printer for GHC Core+ pretty+ , ppCoreTC+ , ppModGuts+ , ppCoreProg+ , ppCoreBind+ , ppCoreExpr+ , ppCoreAlt+ , ppKindOrType+ , ppCoercion+ , ppForallQuantification+ ) where import Control.Arrow hiding ((<+>)) import Control.Applicative ((<$>))@@ -24,16 +23,12 @@ import HERMIT.Context import HERMIT.Core-import HERMIT.GHC hiding ((<+>), (<>), ($$), ($+$), sep, hsep, empty, nest, vcat, char, text, keyword, hang)+import HERMIT.Dictionary (dynFlagsT)+import HERMIT.GHC hiding ((<+>), (<>), ($$), ($+$), cat, sep, fsep, hsep, empty, nest, vcat, char, text, keyword, hang) import HERMIT.Kure import HERMIT.Monad-import HERMIT.Syntax--import HERMIT.Dictionary (dynFlagsT)- import HERMIT.PrettyPrinter.Common--import Pair+import HERMIT.Syntax import Text.PrettyPrint.MarkedHughesPJ as PP @@ -50,11 +45,13 @@ | RetLet AbsolutePathH [DocH] AbsolutePathH DocH | RetApp DocH [(AbsolutePathH,RetExpr)] | RetForAll AbsolutePathH [DocH] AbsolutePathH DocH- | RetArrowType DocH [(AbsolutePathH,DocH)] -- f -> (a -> (b -> c)) The path is for each arrow, starting from the left.+ | RetArrowType ArrowType DocH [(AbsolutePathH,DocH)] -- f -> (a -> (b -> c)) The path is for each arrow, starting from the left. | RetExpr DocH | RetAtom DocH -- parens not needed | RetEmpty +data ArrowType = ATType | ATCoercion deriving (Eq, Show)+ retApp :: AbsolutePathH -> Crumb -> Crumb -> RetExpr -> RetExpr -> RetExpr retApp _ _ _ f RetEmpty = f retApp _ _ _ RetEmpty e = e@@ -87,16 +84,11 @@ ty -> RetForAll p [v] (p @@ cr) (normalExpr ty) -- This is very hacky. There must be a better way of handling arrow types.-retArrowType :: AbsolutePathH -> Crumb -> Crumb -> RetExpr -> RetExpr -> RetExpr-retArrowType p cr1 cr2 ty1 = \case- RetArrowType ty2 ptys -> RetArrowType (normalParensExceptApp (p @@ cr1) ty1) ((p,ty2) : ptys)- ty2 -> RetArrowType (normalParensExceptApp (p @@ cr1) ty1) [(p , normalParensExceptApp (p @@ cr2) ty2)]----------------------------------------------------------------------------------------------------isAtom :: RetExpr -> Bool-isAtom (RetAtom _) = True-isAtom _ = False+retArrowType :: ArrowType -> AbsolutePathH -> Crumb -> Crumb -> RetExpr -> RetExpr -> RetExpr+retArrowType at@ATType p cr1 _cr2 ty1 (RetArrowType _ ty2 ptys)+ = RetArrowType at (normalParensExceptApp (p @@ cr1) ty1) ((p,ty2) : ptys)+retArrowType at p cr1 cr2 ty1 ty2+ = RetArrowType at (normalParensExceptApp (p @@ cr1) ty1) [(p , normalParensExceptApp (p @@ cr2) ty2)] ------------------------------------------------------------------------------------------------ @@ -106,11 +98,12 @@ normalExpr (RetExpr e) = e normalExpr (RetLam p vs pb e) = hang (specialSymbol p LambdaSymbol <+> hsep vs <+> specialSymbol pb RightArrowSymbol) 2 e normalExpr (RetLet p vs pb e) = sep [ keyword p "let" <+> vcat vs, keyword pb "in" <+> e ]-normalExpr (RetApp f pes) = let (pAtoms,pExprs) = span (isAtom.snd) pes- in sep [ hsep (f : map (normalExpr.snd) pAtoms)- , nest 2 (sep $ map (uncurry normalParens) pExprs) ]+normalExpr (RetApp f pes) = f <+> fsep (map (uncurry normalParens) pes) normalExpr (RetForAll p vs pb ty) = specialSymbol p ForallSymbol <+> hsep vs <+> symbol pb '.' <+> ty-normalExpr (RetArrowType ty ptys) = foldl (\ ty1 (p,ty2) -> ty1 <+> typeArrow p <+> ty2) ty ptys+normalExpr (RetArrowType at ty ptys) = let a = case at of+ ATType -> typeArrow+ ATCoercion -> coArrow+ in foldl (\ ty1 (p,ty2) -> ty1 <+> a p <+> ty2) ty ptys ------------------------------------------------------------------------------------------------ @@ -175,7 +168,14 @@ coKeyword :: AbsolutePathH -> String -> DocH coKeyword = coText -- An alternative would be keyword. +coArrow :: AbsolutePathH -> DocH+coArrow p = coSymbol p RightArrowSymbol +coTypeSymbol :: AbsolutePathH -> DocH+coTypeSymbol p = coSymbol p TypeOfSymbol++------------------------------------------------------------------------------------------------+ tyChar :: AbsolutePathH -> Char -> DocH tyChar p = attrP p . typeColor . char @@ -222,6 +222,7 @@ then return (cleanParens p (idText p doc)) else return (idText p doc) +-- For var bindings ppVar :: PrettyH Var ppVar = readerT $ \ v -> varName ^>> ppName (varColor v) @@ -241,7 +242,9 @@ ppName :: SyntaxForColor -> PrettyH Name ppName color = do p <- absPathT- name <- arr uqName+ c <- contextT+ name <- arr (\ n -> unqualifiedName n ++ (if po_showUniques (prettyC_options c)+ then '_' : show (getUnique n) else "")) let doc = attrP p $ markColor color $ text name -- TODO: is "isScriptInfixId" the right predicate to use here? if all isScriptInfixIdChar name@@ -312,7 +315,7 @@ ) (\ _ -> ppBinderMode) ppCoreExpr- (\ con vs e -> hang (con <+> hsep vs <+> specialSymbol p RightArrowSymbol) 2 e)+ (\ con vs e -> hang (con <+> fsep vs <+> specialSymbol p RightArrowSymbol) 2 e) ppCoreDef :: PrettyH CoreDef ppCoreDef = defT idR (ppCoreExprR &&& ppTypeSig) (,) >>> ppDef Def_RHS@@ -349,14 +352,15 @@ lamT ppBinderMode ppCoreExprR (retLam p) <+ letT ppCoreBind ppCoreExprR (retLet p) <+ appT ppCoreExprR ppCoreExprR (retApp p App_Fun App_Arg)- <+ caseT ppCoreExpr ppVar (ppTypeModeR >>> parenExpr) (const ppCoreAlt) (\ s w ty alts -> RetExpr ((keyword p "case" <+> s <+> keyword p "of" <+> w <+> ty) $$ nest 2 (vcat alts)))+ <+ caseT ppCoreExpr ppVar (ppTypeModeR >>> parenExpr) (const ppCoreAlt)+ (\ s w ty alts -> RetExpr (hang (keyword p "case" <+> s) 1 (keyword p "of" <+> w <+> ty) $+$ nest 2 (vcat alts))) <+ varT (RetAtom <$> ppVarOcc) <+ litT (RetAtom <$> ppSDoc) <+ typeT ppTypeModeR <+ coercionT ppCoercionModeR <+ (castT ppCoreExprR (ppCoercionModeR >>> parenExpr) (,) >>> readerT (\ (_,co) -> if isEmpty co then arr fst- else toFst parenExprExceptApp >>^ \ e -> RetExpr (e <+> castSymbol p <+> co)+ else toFst parenExprExceptApp >>^ \ e -> RetExpr (hang e 2 (castSymbol p <+> co)) )) <+ tickT ppSDoc (ppCoreExprR >>> parenExpr) (\ tk e -> RetExpr $ attrP p (text "Tick") $$ nest 2 (tk <+> e)) @@ -381,10 +385,10 @@ tyVarT (RetAtom <$> ppVarOcc) <+ litTyT (RetAtom <$> ppLitTy) <+ appTyT ppKindOrTypeR ppKindOrTypeR (retApp p AppTy_Fun AppTy_Arg)- <+ funTyT ppKindOrTypeR ppKindOrTypeR (retArrowType p FunTy_Dom FunTy_CoDom)+ <+ funTyT ppKindOrTypeR ppKindOrTypeR (retArrowType ATType p FunTy_Dom FunTy_CoDom) <+ forAllTyT ppVar ppKindOrTypeR (retForAll p ForAllTy_Body) <+ tyConAppT (forkFirst ppTyCon) (\ _ -> ppKindOrTypeR)- (\ (pCon,tyCon) tys -> if | isFunTyCon tyCon && length tys == 2 -> let [ty1,ty2] = tys in retArrowType p (TyConApp_Arg 0) (TyConApp_Arg 1) ty1 ty2+ (\ (pCon,tyCon) tys -> if | isFunTyCon tyCon && length tys == 2 -> let [ty1,ty2] = tys in retArrowType ATType p (TyConApp_Arg 0) (TyConApp_Arg 1) ty1 ty2 | tyCon == listTyCon -> RetAtom $ tyChar p '[' <> (case tys of [] -> empty t:_ -> normalExpr t)@@ -419,7 +423,7 @@ Omit -> return RetEmpty Abstract -> return (RetAtom $ coercionSymbol p) Show -> ppCoercionR- Kind -> ppCoKind >>^ (\ k -> RetExpr (coercionSymbol p <+> typeOfSymbol p <+> k))+ Kind -> ppCoKind >>^ (\ k -> RetExpr (coercionSymbol p <+> coTypeSymbol p <+> k)) ppCoercionR :: Transform PrettyC HermitM Coercion RetExpr ppCoercionR = absPathT >>= ppCoercionPR@@ -436,26 +440,25 @@ else RetExpr (cop2 <+> coChar p '@' <+> ty) ) <+ appCoT ppCoercionR ppCoercionR (retApp p AppCo_Fun AppCo_Arg)-#if __GLASGOW_HASKELL__ > 706 -- TODO: Figure out how to properly pp new branched Axioms and Left/Right Coercions <+ reflT (ppTypeModeR >>^ normalExpr) (\ r ty -> RetAtom $ if isEmpty ty then coText p "refl" else coChar p '<' <> coText p (showRole r ++ ":") <> ty <> coChar p '>')- <+ tyConAppCoT ppTyConCo (const ppCoercionR) (\ r tc -> retApps p TyConApp_Arg $ coText p (showRole r ++ ":") <> tc)+ <+ tyConAppCoT (forkFirst ppTyConCo) (const ppCoercionR)+ (\ r (ptc, tc) cs -> if isFunTyCon tc && (length cs == 2)+ then let [c1,c2] = cs+ in retArrowType ATCoercion p (TyConApp_Arg 0) (TyConApp_Arg 1) c1 c2+ else retApps p TyConApp_Arg (coText p (showRole r ++ ":") <> ptc) cs) <+ axiomInstCoT (coAxiomName ^>> ppName CoercionColor) ppSDoc (\ _ -> ppCoercionR >>> parenExpr) (\ ax idx coes -> RetExpr (coText p "axiomInst" <+> ax <+> idx <+> sep coes)) <+ lrCoT ppSDoc (ppCoercionR >>> parenExpr) (\ lr co -> RetExpr (coercionColor lr <+> co)) -- TODO: UnivCo and SubCo <+ constT (return . RetAtom $ text "Unsupported Coercion Constructor")-#else- <+ reflT (ppTypeModeR >>^ normalExpr >>^ \ ty -> RetAtom $ if isEmpty ty then coText p "refl" else coChar p '<' <> ty <> coChar p '>')- <+ tyConAppCoT ppTyConCo (const ppCoercionR) (retApps p TyConApp_Arg)- <+ unsafeCoT (ppTypeModeR >>> parenExpr) (ppTypeModeR >>> parenExpr) (\ ty1 ty2 -> (if isEmpty ty1 && isEmpty ty2 then RetAtom else RetExpr)- (coKeyword p "unsafe" <+> ty1 <+> ty2)- )- <+ axiomInstCoT (coAxiomName ^>> ppName CoercionColor) (\ _ -> ppCoercionR >>> parenExpr) (\ ax coes -> RetExpr (coText p "axiomInst" <+> ax <+> sep coes))-#endif ppCoKind :: PrettyH Coercion-ppCoKind = do p <- absPathT- (coercionKind >>> unPair) ^>> ((ppTypeModeR >>> parenExprExceptApp) *** (ppTypeModeR >>> parenExprExceptApp)) >>^ ( \(ty1,ty2) -> ty1 <+> coText p "~#" <+> ty2)+ppCoKind = do+ p <- absPathT+ (r, Pair co1 co2) <- arr (coercionRole &&& coercionKind)+ ty1 <- return co1 >>> ppTypeModeR >>> parenExprExceptApp+ ty2 <- return co2 >>> ppTypeModeR >>> parenExprExceptApp+ return $ cat [ty1, pad (coText p ("~" ++ showRole r)), ty2] --------------------------------------------------------------------
src/HERMIT/PrettyPrinter/Common.hs view
@@ -40,11 +40,10 @@ , updateTypeShowOption , updateWidthOption -- * Utilities+ , pad , hlist , vlist-#if __GLASGOW_HASKELL__ > 706 , showRole-#endif ) where import Data.Char@@ -56,18 +55,16 @@ import HERMIT.Context import HERMIT.Core import HERMIT.External-import HERMIT.GHC hiding (($$), (<>), (<+>))+import HERMIT.GHC hiding (($$), (<>), (<+>), char) import HERMIT.Kure import HERMIT.Monad import Text.PrettyPrint.MarkedHughesPJ as PP -#if __GLASGOW_HASKELL__ > 706 showRole :: Role -> String-showRole Nominal = "Nominal"-showRole Representational = "Representational"-showRole Phantom = "Phantom"-#endif+showRole Nominal = "N"+showRole Representational = "R"+showRole Phantom = "P" -- A HERMIT document type DocH = MDoc HermitMark@@ -201,6 +198,7 @@ , po_exprTypes :: ShowOption -- ^ Do you hide types, and type arguments, as <>? , po_coercions :: ShowOption -- ^ Do you hide coercions? , po_typesForBinders :: ShowOption -- ^ Do you give the types for all bindings?+ , po_showUniques :: Bool -- ^ Append uniques to OccNames? (Like GHC does) , po_focus :: Maybe PathH -- ^ This region should be highlighted (is the current focus) , po_depth :: Maybe Int -- ^ below this depth are ..., Nothing => infinite , po_notes :: Bool -- ^ notes might be added to output@@ -225,8 +223,9 @@ def = PrettyOptions { po_fullyQualified = False , po_exprTypes = Abstract- , po_coercions = Abstract+ , po_coercions = Kind , po_typesForBinders = Omit+ , po_showUniques = False , po_focus = Nothing , po_depth = Nothing , po_notes = False@@ -487,5 +486,9 @@ vlist, hlist :: [MDoc a] -> MDoc a vlist = listify ($$) hlist = listify (<+>)++-- | wrap a document in spaces+pad :: MDoc a -> MDoc a+pad d = char ' ' <> d <> char ' ' -------------------------------------------------------------------------------
src/HERMIT/Shell/Command.hs view
@@ -1,8 +1,9 @@-{-# LANGUAGE LambdaCase, ScopedTypeVariables, GADTs, FlexibleContexts, TypeFamilies #-}+{-# LANGUAGE ConstraintKinds, CPP, FlexibleContexts, GADTs, LambdaCase, ScopedTypeVariables, TypeFamilies #-} module HERMIT.Shell.Command ( -- * The HERMIT Command-line Shell commandLine+ , interpShellCommand , unicodeConsole , diffDocH , diffR@@ -14,14 +15,14 @@ , evalScript ) where -import Control.Concurrent import Control.Monad.State-import Control.Monad.Error import Data.Char import Data.List (isPrefixOf, partition) import Data.Maybe+import Data.Monoid +import HERMIT.Context import HERMIT.External import qualified HERMIT.GHC as GHC import HERMIT.Kernel.Scoped hiding (abortS, resumeS)@@ -31,6 +32,9 @@ import HERMIT.Plugin.Display import HERMIT.Plugin.Renderer +import HERMIT.PrettyPrinter.Common++import HERMIT.Shell.Completion import HERMIT.Shell.Externals import HERMIT.Shell.Interpreter import HERMIT.Shell.KernelEffect@@ -39,6 +43,10 @@ import HERMIT.Shell.ShellEffect import HERMIT.Shell.Types +#ifdef mingw32_HOST_OS+import HERMIT.Win32.Console+#endif+ import System.IO -- import System.Console.ANSI@@ -72,44 +80,58 @@ , "==============================================================" ] +#ifdef mingw32_HOST_OS+cygwinWarning :: String+cygwinWarning = unlines+ [ "WARNING: HERMIT invoked in a Unix-like shell such as Cygwin."+ , "Cygwin does not handle Ctrl-C or tab completion well in some"+ , "Haskell executables. It is recommended that you use a native"+ , "Windows console (such as cmd.exe or PowerShell) instead."+ ]+#endif+ -- | The first argument includes a list of files to load.-commandLine :: [GHC.CommandLineOption] -> Behavior -> [External] -> CLT IO ()-commandLine opts behavior exts = do+commandLine :: forall m. (MonadCatch m, MonadException m, CLMonad m)+ => [Interp m ()] -> [GHC.CommandLineOption] -> [External] -> m ()+commandLine intp opts exts = do let (flags, filesToLoad) = partition (isPrefixOf "-") opts ws_complete = " ()" modify $ \ st -> st { cl_externals = shell_externals ++ exts } - clState <- get- completionMVar <- liftIO $ newMVar clState-- let loop :: CLT (InputT IO) ()+ let loop :: InputT m () loop = do- st <- get+ st <- lift get let SAST n = cl_cursor st mLine <- if cl_nav st then liftIO getNavCmd- else do liftIO $ modifyMVar_ completionMVar (const $ return st) -- so the completion can get the current state- lift $ getInputLine $ "hermit<" ++ show n ++ "> "+ else getInputLine $ "hermit<" ++ show n ++ "> " case mLine of- Nothing -> performShellEffect Resume+ Nothing -> lift $ performShellEffect Resume Just ('-':'-':_) -> loop Just line -> if all isSpace line then loop- else (evalScript line `catchFailHard` cl_putStrLn) >> loop+ else lift (evalScript intp line `catchFailHard` cl_putStrLn) >> loop -- Display the banner if any (`elem` ["-v0", "-v1"]) flags then return () else cl_putStrLn banner +#ifdef mingw32_HOST_OS+ isCyg <- liftIO isCygwinConsole+ if isCyg+ then cl_putStrLn cygwinWarning+ else return ()+#endif+ -- Load and run any scripts setRunningScript $ Just [] sequence_ [ case fileName of "abort" -> performShellEffect Abort "resume" -> performShellEffect Resume- _ -> performScriptEffect runExprH $ loadAndRun fileName+ _ -> performScriptEffect (runExprH intp) $ loadAndRun fileName | fileName <- reverse filesToLoad , not (null fileName) ] `catchFailHard` \ msg -> cl_putStrLn $ "Booting Failure: " ++ msg@@ -117,26 +139,41 @@ -- Start the CLI showWindow- let settings = setComplete (completeWordWithPrev Nothing ws_complete (shellComplete completionMVar)) defaultSettings- (r,s) <- get >>= liftIO . runInputTBehavior behavior settings . flip runCLT loop- either throwError (\v -> put s >> return v) r+ let settings = setComplete (completeWordWithPrev Nothing ws_complete shellComplete) defaultSettings+ runInputT settings loop -- | Like 'catchM', but checks the 'cl_failhard' setting and does so if needed.-catchFailHard :: MonadIO m => CLT m () -> (String -> CLT m ()) -> CLT m ()+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) -evalScript :: (MonadCatch m, MonadError CLException m, MonadIO m, MonadState CommandLineState m) => String -> m ()-evalScript = parseScriptCLT >=> mapM_ runExprH+evalScript :: (MonadCatch m, CLMonad m) => [Interp m ()] -> String -> m ()+evalScript intp = parseScriptCLT >=> mapM_ (runExprH intp) -runExprH :: (MonadCatch m, MonadError CLException m, MonadIO m, MonadState CommandLineState m) => ExprH -> m ()-runExprH expr = prefixFailMsg ("Error in expression: " ++ unparseExprH expr ++ "\n") $ do- shellCmd <- interpExprH interpShellCommand expr- case shellCmd of- KernelEffect effect -> performKernelEffect effect expr- ScriptEffect effect -> performScriptEffect runExprH effect- ShellEffect effect -> performShellEffect effect- QueryFun query -> performQuery query expr- ProofCommand cmd -> performProofCommand cmd+runExprH :: (MonadCatch m, CLMonad m) => [Interp m ()] -> ExprH -> m ()+runExprH intp expr = prefixFailMsg ("Error in expression: " ++ unparseExprH expr ++ "\n") $ interpExprH intp 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+ ] -------------------------------------------------------------------------------
+ src/HERMIT/Shell/Completion.hs view
@@ -0,0 +1,127 @@+{-# LANGUAGE FlexibleContexts, LambdaCase #-}+module HERMIT.Shell.Completion (shellComplete) where++import Control.Applicative+import Control.Arrow+import Control.Monad.State++import Data.Dynamic+import Data.List (isPrefixOf, nub)+import Data.Map (keys)+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.Parser++import HERMIT.Dictionary.Inline+import HERMIT.Dictionary.Navigation+import HERMIT.Dictionary.Reasoning+import HERMIT.Dictionary.Rules++import HERMIT.Shell.Interpreter+import HERMIT.Shell.Types++import System.Console.Haskeline hiding (catch, display)++----------------------------------------------------------------------------------++shellComplete :: (MonadCatch m, MonadIO m, MonadState CommandLineState m) => String -> String -> m [Completion]+shellComplete rPrev so_far = do+ let (partial, _) = toUnmatched rPrev+ if null partial+ then completionsFor so_far [CommandC]+ else case parseExprH partial of+ Left _ -> return []+ Right e -> do+ eds <- attemptM $ exprToDyns e+ case eds of+ Left msg -> liftIO $ putStrLn ("\n" ++ msg) >> return []+ Right ds -> do+ let ts = [ head args | d <- ds+ , let args = fst (splitFunTyArgs (dynTypeRep d))+ , not (null args) ]+ completionsFor so_far $ filterUnknowns $ map (completionType.show) ts++completionsFor :: (MonadCatch m, MonadIO m, MonadState CommandLineState 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 [])+ return $ map simpleCompletion $ nub $ filter (so_far `isPrefixOf`) $ concat cls++data CompletionType = ConsiderC -- considerable constructs and (deprecated) bindingOfT+ | BindingOfC -- bindingOfT+ | BindingGroupOfC -- bindingGroupOfT+ | RhsOfC -- rhsOfT+ | OccurrenceOfC -- occurrenceOfT+ | InlineC -- complete with names that can be inlined+ | InScopeC -- complete with in-scope variable names+ | LemmaC -- complete with list of lemmas+ | CommandC -- complete using dictionary commands (default)+ | 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)++completionType :: String -> CompletionType+completionType s = fromMaybe (UnknownC s) (lookup s m)+ where m = [ ("BindingName" , BindingOfC)+ , ("Considerable" , ConsiderC)+ , ("CoreBox" , CoreC)+ , ("HermitName" , NothingC)+ , ("IntBox" , NothingC)+ , ("LemmaName" , LemmaC)+ , ("OccurrenceName", OccurrenceOfC)+ , ("RememberedName", StashC)+ , ("RewriteCoreBox", CommandC) -- be more specific than CommandC?+ , ("RhsOfName" , RhsOfC)+ , ("RuleName" , RuleC)+ , ("StringBox" , StringC)+ ]++filterUnknowns :: [CompletionType] -> [CompletionType]+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 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 InScopeC = return $ pure ["'"] -- TODO+completionQuery LemmaC = return $ liftM (map show . 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 ["[|"]+-- Need to modify opts in completionType function to add this type.+completionQuery (UnknownC s) = do+ liftIO $ putStrLn $ "\nCannot tab complete: unknown argument type: " ++ s+ return (pure [])++-- | Take a reversed string, find substring back to first unmatched open paren (or the end).+-- Returns that substring (unreversed), and remaining (reversed) string.+--+-- ex 1. toUnmatched "zab rab( oof" ==> ("bar baz" , "( oof")+-- ex 2. toUnmatched ")xuuq zab( rab( oof" ==> ("bar (baz quux)", "( oof")+toUnmatched :: String -> (String, String)+toUnmatched = go 0 ""+ where go :: Int -> String -> String -> (String, String)+ go n acc s@('(':cs)+ | n > 0 = go (n-1) ('(':acc) cs+ | otherwise = (acc, s)+ 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/Dictionary.hs view
@@ -1,11 +1,13 @@ {-# LANGUAGE ScopedTypeVariables #-} module HERMIT.Shell.Dictionary- ( mkDict+ ( mkDictionary+ , addToDictionary , pp_dictionary ) where +import Data.Dynamic import Data.List-import Data.Map (Map, fromList, toList)+import Data.Map (Map, fromList, toList, fromListWith) import HERMIT.External @@ -16,9 +18,24 @@ -------------------------------------------------------------------------- +-- | A 'Dictionary' is a collection of 'Dynamic's.+-- Looking up a 'Dynamic' (via an 'ExternalName' key) returns a list, as there+-- can be multiple 'Dynamic's with the same name.+type Dictionary = Map ExternalName [Dynamic]++-- | Build a 'Data.Map' from names to 'Dynamic' values.+toDictionary :: [External] -> Dictionary+toDictionary = fromListWith (++) . map toEntry++toEntry :: External -> (ExternalName, [Dynamic])+toEntry e = (externName e, [externDyn e])++addToDictionary :: External -> Dictionary -> Dictionary+addToDictionary ex d = fromListWith (++) $ toEntry ex : toList d+ -- | Create a dictionary from a list of 'External's.-mkDict :: [External] -> Dictionary-mkDict externs = toDictionary externs'+mkDictionary :: [External] -> Dictionary+mkDictionary externs = toDictionary externs' where msg = layoutTxt 60 (map (show . fst) dictionaryOfTags) externs' = externs ++
src/HERMIT/Shell/Externals.hs view
@@ -4,7 +4,6 @@ import Control.Applicative -import Data.Monoid import Data.List (intercalate) import qualified Data.Map as M import Control.Monad (liftM)@@ -19,7 +18,6 @@ import HERMIT.PrettyPrinter.Common import HERMIT.Shell.Dictionary-import HERMIT.Shell.Interpreter import HERMIT.Shell.KernelEffect import HERMIT.Shell.Proof as Proof import HERMIT.Shell.ScriptToRewrite@@ -28,36 +26,6 @@ ---------------------------------------------------------------------------------- --- | There are five types of commands.-data ShellCommand = KernelEffect KernelEffect -- ^ Command that modifies the state of the (scoped) kernel.- | ScriptEffect ScriptEffect -- ^ Command that deals with script files.- | ShellEffect ShellEffect -- ^ Command that modifies the state of the shell.- | QueryFun QueryFun -- ^ Command that queries the AST with a Transform (read only).- | ProofCommand ProofCommand -- ^ Command that deals with proofs.---- | Interpret a boxed thing as one of the four possible shell command types.-interpShellCommand :: [Interp ShellCommand]-interpShellCommand =- [ interp $ \ (RewriteCoreBox rr) -> KernelEffect (Apply rr)- , interp $ \ (RewriteCoreTCBox rr) -> KernelEffect (Apply rr)- , interp $ \ (BiRewriteCoreBox br) -> KernelEffect (Apply $ whicheverR br)- , interp $ \ (CrumbBox cr) -> KernelEffect (Pathfinder (return (mempty @@ cr) :: TransformH CoreTC LocalPathH))- , interp $ \ (PathBox p) -> KernelEffect (Pathfinder (return p :: TransformH CoreTC LocalPathH))- , interp $ \ (TransformCorePathBox tt) -> KernelEffect (Pathfinder tt)- , interp $ \ (TransformCoreTCPathBox tt) -> KernelEffect (Pathfinder tt)- , interp $ \ (StringBox str) -> QueryFun (message str)- , interp $ \ (TransformCoreStringBox tt) -> QueryFun (QueryString tt)- , interp $ \ (TransformCoreTCStringBox tt) -> QueryFun (QueryString tt)- , interp $ \ (TransformCoreTCDocHBox tt) -> QueryFun (QueryDocH $ unTransformDocH tt)- , interp $ \ (TransformCoreCheckBox tt) -> QueryFun (CorrectnessCritera tt)- , interp $ \ (TransformCoreTCCheckBox tt) -> QueryFun (CorrectnessCritera tt)- , interp $ \ (effect :: KernelEffect) -> KernelEffect effect- , interp $ \ (effect :: ShellEffect) -> ShellEffect effect- , interp $ \ (effect :: ScriptEffect) -> ScriptEffect effect- , interp $ \ (query :: QueryFun) -> QueryFun query- , interp $ \ (cmd :: ProofCommand) -> ProofCommand cmd- ]- shell_externals :: [External] shell_externals = map (.+ Shell) [@@ -148,6 +116,11 @@ [(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 ->+ 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
src/HERMIT/Shell/Interpreter.hs view
@@ -1,14 +1,21 @@-{-# LANGUAGE KindSignatures, GADTs, InstanceSigs, FlexibleContexts, ScopedTypeVariables #-}+{-# LANGUAGE ConstraintKinds, KindSignatures, GADTs, InstanceSigs,+ FlexibleContexts, ScopedTypeVariables, CPP #-} module HERMIT.Shell.Interpreter- ( -- * The HERMIT Interpreter- Interp- , interp- , interpExprH--- , runExprH- ) where+ ( -- * The HERMIT Interpreter+ Interp+ , interp+ , interpM+ , interpEM+ , interpExprH+ , exprToDyns+ ) where +#if MIN_VERSION_mtl(2,2,1)+import Control.Monad.Except+#else import Control.Monad.Error+#endif import Control.Monad.State import Data.Char@@ -16,48 +23,50 @@ import qualified Data.Map as M import HERMIT.External+import HERMIT.Kure+import HERMIT.Monad+import HERMIT.Name import HERMIT.Parser-import HERMIT.Kure +import HERMIT.Dictionary.Navigation+import HERMIT.Dictionary.Rules+ import HERMIT.Shell.Dictionary import HERMIT.Shell.Types -- | An 'Interp' @cmd@ is a /possible/ means of converting a 'Typeable' value to a value of type @cmd@.-data Interp :: * -> * where- Interp :: Typeable a => (a -> cmd) -> Interp cmd+data Interp :: (* -> *) -> * -> * where+ Interp :: Typeable b => (b -> ExprH -> m a) -> Interp m a --- | The primitive way of building an 'Interp'.-interp :: Typeable a => (a -> cmd) -> Interp cmd-interp = Interp+-- | An 'Interp' with no effects.+interp :: (Monad m, Typeable b) => (b -> a) -> Interp m a+interp f = Interp (const . return . f) -instance Functor Interp where- fmap :: (a -> b) -> Interp a -> Interp b- fmap f (Interp g) = Interp (f . g)+-- | An 'Interp' which can affect the shell.+interpM :: (CLMonad m, Typeable b) => (b -> m a) -> Interp m a+interpM f = Interp (const . f) -{--runExprH :: forall m r. (MonadCatch m, MonadError CLException m, MonadIO m, MonadState CommandLineState m) => ExprH -> m r-runExprH e = do- dyns <- interpExpr e- CmdInterps interps <- gets cl_interps- case [ performCommand $ f a | Interp f <- interps, Just a <- map fromDynamic dyns] of- [] -> fail $ "Does not type-check: " ++ unparseExprH e ++ "\n"- b:_ -> b :: m r--}+-- | Like 'InterpM', but with access to the original expression.+interpEM :: (CLMonad m, Typeable b) => (b -> ExprH -> m a) -> Interp m a+interpEM = Interp --- | Interpret an 'ExprH' by looking up the appropriate 'Dynamic'(s) in the provided 'Dictionary', --- then interpreting the 'Dynamic'(s) with the provided 'Interp's, returning the first --- interpretation to succeed (or an error string if none succeed).-interpExprH :: MonadState CommandLineState m => [Interp b] -> ExprH -> m b-interpExprH interps e = interpExpr e >>= runInterp e interps+instance Monad m => Functor (Interp m) where+ fmap :: (a -> b) -> Interp m a -> Interp m b+ fmap f (Interp g) = Interp (\ e -> liftM f . g e) -runInterp :: Monad m => ExprH -> [Interp b] -> [Dynamic] -> m b-runInterp e interps dyns = case [f a | Interp f <- interps, Just a <- map fromDynamic dyns] of- [] -> fail $ "Does not type-check: " ++ unparseExprH e ++ "\n"- b:_ -> return b+-- | Execute an 'ExprH' using a given interpreter. The given interpretations+-- are tried in order. The first one to match (have the proper type) will be executed.+interpExprH :: CLMonad m => [Interp m b] -> ExprH -> m b+interpExprH interps e = exprToDyns e >>= runInterp e interps -interpExpr :: MonadState CommandLineState m => ExprH -> m [Dynamic]-interpExpr = interpExpr' False+runInterp :: forall m b. CLMonad m => ExprH -> [Interp m b] -> [Dynamic] -> m b+runInterp e interps dyns = case [f a e :: m b | Interp f <- interps, Just a <- map fromDynamic dyns] of+ [] -> fail $ "Does not type-check: " ++ unparseExprH e ++ "\n"+ comp:_ -> comp +exprToDyns :: MonadState CommandLineState m => ExprH -> m [Dynamic]+exprToDyns = exprToDyns' False+ -- input: list length n, each elem is a variable length list of possible interpretations -- output: variable length list, each elem is list of length n fromDynList :: [[Dynamic]] -> [[Dynamic]]@@ -67,39 +76,48 @@ toBoxedList :: (Extern a, Typeable b) => [[Dynamic]] -> ([a] -> b) -> [Dynamic] toBoxedList dyns boxCon = [ toDyn $ boxCon (map unbox l) | dl <- dyns, Just l <- [mapM fromDynamic dl] ] -interpExpr' :: MonadState CommandLineState m => Bool -> ExprH -> m [Dynamic]-interpExpr' _ (SrcName str) = return [ toDyn $ StringBox str ]-interpExpr' _ (CoreH str) = return [ toDyn $ CoreBox (CoreString str) ]-interpExpr' _ (ListH exprs) = do - dyns <- liftM fromDynList $ mapM (interpExpr' True) exprs+exprToDyns' :: MonadState CommandLineState m => Bool -> ExprH -> m [Dynamic]+exprToDyns' _ (SrcName str) = do+ let hn = parseName str -- TODO: remove StringBox option below+ -- TODO: change to SrcName :: HermitName -> ExprH+ return [ toDyn hn, toDyn (BindingName hn), toDyn (OccurrenceName hn), toDyn (RhsOfName hn), toDyn (StringBox str) ]+exprToDyns' _ (CoreH str) = return [ toDyn $ CoreString str ]+exprToDyns' _ (ListH exprs) = do+ dyns <- liftM fromDynList $ mapM (exprToDyns' True) exprs 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 (TransformCorePathBox . return . pathToSnocPath) ++ toBoxedList dyns IntListBox+ ++ toBoxedList dyns OccurrenceNameListBox ++ toBoxedList dyns RewriteCoreListBox+ ++ toBoxedList dyns RuleNameListBox -interpExpr' rhs (CmdName str) +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. toDyn $ IntBox i -- TODO: Find a better long-term solution.- , toDyn $ TransformCorePathBox (deprecatedIntToPathT i) + , toDyn $ TransformCorePathBox (deprecatedIntToPathT i) ] | otherwise = do- dict <- gets (mkDict . cl_externals)+ dict <- gets (mkDictionary . cl_externals) case M.lookup str dict of Just dyns -> do dyns' <- mapM provideState dyns return $ if rhs then toDyn (StringBox str) : dyns' else dyns' -- not a command, try as a string arg... worst case: dynApply fails with "bad type of expression" -- best case: 'help ls' works instead of 'help "ls"'. this is likewise done in the clause above- Nothing | rhs -> return [toDyn $ StringBox str]+ 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-interpExpr' _ (AppH e1 e2) = liftM2 dynCrossApply (interpExpr' False e1) (interpExpr' True e2)+exprToDyns' _ (AppH e1 e2) = liftM2 dynCrossApply (exprToDyns' False e1) (exprToDyns' True e2) --- We essentially treat externals of the type 'CommandLineState -> b' specially,+-- We treat externals of the type 'CommandLineState -> b' specially, -- providing them 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
src/HERMIT/Shell/KernelEffect.hs view
@@ -1,12 +1,17 @@-{-# LANGUAGE DeriveDataTypeable, FlexibleContexts, GADTs, TypeFamilies #-}+{-# LANGUAGE ConstraintKinds, DeriveDataTypeable, FlexibleContexts, LambdaCase, TypeFamilies #-} -module HERMIT.Shell.KernelEffect +module HERMIT.Shell.KernelEffect ( KernelEffect(..) , performKernelEffect+ , applyRewrite+ , setPath+ , goDirection+ , beginScope+ , endScope+ , deleteSAST ) where import Control.Monad.State-import Control.Monad.Error import Data.Monoid import Data.Typeable@@ -28,21 +33,11 @@ ------------------------------------------------------------------------------- --- GADTs can't have docs on constructors. See Haddock ticket #43. -- | KernelEffects are things that affect the state of the Kernel--- - Apply a rewrite (giving a whole new lower-level AST).--- - Change the current location using a computed path.--- - Change the currect location using directions.--- - Begin or end a scope.--- - Delete an AST--- - Run a precondition or other predicate that must not fail.-data KernelEffect :: * where- Apply :: (Injection GHC.ModGuts g, Walker HermitC g) => RewriteH g -> KernelEffect- Pathfinder :: (Injection GHC.ModGuts g, Walker HermitC g) => TransformH g LocalPathH -> KernelEffect- Direction :: Direction -> KernelEffect- BeginScope :: KernelEffect- EndScope :: KernelEffect- Delete :: SAST -> KernelEffect+data KernelEffect = Direction Direction -- Change the currect location using directions.+ | BeginScope -- Begin scope.+ | EndScope -- End scope.+ | Delete SAST -- Delete an AST deriving Typeable instance Extern KernelEffect where@@ -50,12 +45,18 @@ box i = i unbox i = i --------------------------------------------------------------------------------+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 -performKernelEffect :: (MonadCatch m, MonadError CLException m, MonadIO m, MonadState CommandLineState m) - => KernelEffect -> ExprH -> m ()+------------------------------------------------------------------------------- -performKernelEffect (Apply rr) expr = do+applyRewrite :: (Injection GHC.ModGuts g, Walker HermitC g, MonadCatch m, CLMonad m)+ => RewriteH g -> ExprH -> m ()+applyRewrite rr expr = do st <- get let sk = cl_kernel st@@ -79,7 +80,9 @@ (\ errs -> liftIO (deleteS sk sast') >> fail errs) else commit -performKernelEffect (Pathfinder t) expr = do+setPath :: (Injection GHC.ModGuts g, Walker HermitC g, MonadCatch m, CLMonad m)+ => TransformH g 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)@@ -87,24 +90,28 @@ put $ newSAST expr ast st showWindow -performKernelEffect (Direction dir) expr = do+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 -performKernelEffect BeginScope expr = do+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 -performKernelEffect EndScope expr = do+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 -performKernelEffect (Delete sast) _ = gets cl_kernel >>= flip deleteS sast+deleteSAST :: (MonadCatch m, CLMonad m) => SAST -> m ()+deleteSAST sast = gets cl_kernel >>= flip deleteS sast -------------------------------------------------------------------------------
src/HERMIT/Shell/Proof.hs view
@@ -1,5 +1,5 @@-{-# LANGUAGE DeriveDataTypeable, FlexibleContexts, FlexibleInstances, MultiParamTypeClasses,- ScopedTypeVariables, TypeFamilies, TypeSynonymInstances #-}+{-# LANGUAGE ConstraintKinds, DeriveDataTypeable, FlexibleContexts, FlexibleInstances, LambdaCase,+ MultiParamTypeClasses, ScopedTypeVariables, TypeFamilies, TypeSynonymInstances, CPP #-} module HERMIT.Shell.Proof ( externals@@ -12,29 +12,36 @@ 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 Data.Char (isSpace) import Data.Dynamic import Data.List (delete, isInfixOf)+import Data.Map (filterWithKey, toList)+import Data.String (fromString) import HERMIT.Core import HERMIT.External import HERMIT.GHC hiding (settings, (<>), text, sep, (<+>), ($+$), nest) import HERMIT.Kernel.Scoped import HERMIT.Kure+import HERMIT.Monad import HERMIT.Parser import HERMIT.Utilities import HERMIT.Dictionary.GHC hiding (externals) import HERMIT.Dictionary.Induction import HERMIT.Dictionary.Reasoning hiding (externals)-import HERMIT.Dictionary.Rules hiding (externals) import HERMIT.Plugin.Types import HERMIT.PrettyPrinter.Common +import HERMIT.Shell.Completion import HERMIT.Shell.Interpreter import HERMIT.Shell.KernelEffect import HERMIT.Shell.ScriptToRewrite@@ -49,59 +56,18 @@ -------------------------------------------------------------------------------------------------------- -- | 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 :: [External] externals = map (.+ Proof)- [ external "rule-to-lemma" RuleToLemma- [ "Create a lemma from a GHC RULE." ]- , external "show-lemma" (ShowLemmas . Just)+ [ external "show-lemma" (ShowLemmas . Just) [ "List lemmas whose names match search string." ] , external "show-lemmas" (ShowLemmas Nothing) [ "List lemmas." ]- , external "lemma" ((\s -> promoteExprBiR . lemma False s) :: CommandLineState -> LemmaName -> BiRewriteH Core)- [ "Generate a bi-directional rewrite from a proven lemma." ]- , external "lemma-unsafe" ((\s -> promoteExprBiR . lemma True s) :: CommandLineState -> LemmaName -> BiRewriteH Core)- [ "Generate a bi-directional rewrite from a lemma, even if it is unproven." ]- , external "lemma-lhs-intro" (lemmaLhsIntroR :: CommandLineState -> LemmaName -> RewriteH Core)- [ "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 :: CommandLineState -> LemmaName -> RewriteH Core)- [ "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 "prove-lemma" InteractiveProof [ "Proof a lemma interactively." ]- , external "inst-lemma" (\ nm v cs -> ModifyLemma nm id (instantiateEqualityVarR (cmpString2Var v) cs) id)- [ "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 -> ModifyLemma nm id instantiateDictsR id)- [ "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 -> ModifyLemma nm (const newName) idR id)- [ "Copy a given lemma, with a new name." ]- , external "modify-lemma" (\ nm rr -> ModifyLemma nm id rr (const False))- [ "Modify a given lemma. Resets the proven status to Not Proven." ]- , external "query-lemma" QueryLemma- [ "Apply a transformation to a lemma, returning the result." ] , external "dump-lemma" DumpLemma [ "Dump named lemma to a file." , "dump-lemma <lemma-name> <filename> <renderer> <width>" ]- , external "extensionality" (extensionalityR . Just :: String -> RewriteH CoreExprEquality)- [ "Given a name 'x, then"- , "f == g ==> forall x. f x == g x" ]- , external "extensionality" (extensionalityR Nothing :: RewriteH CoreExprEquality)- [ "f == g ==> forall x. f x == g x" ]- , external "lhs" (lhsR . extractR :: RewriteH Core -> RewriteH CoreExprEquality)- [ "Apply a rewrite to the LHS of an equality." ]- , external "lhs" (lhsT . extractT :: TransformH CoreTC String -> TransformH CoreExprEquality String)- [ "Apply a transformation to the LHS of an equality." ]- , external "rhs" (rhsR . extractR :: RewriteH Core -> RewriteH CoreExprEquality)- [ "Apply a rewrite to the RHS of an equality." ]- , external "rhs" (rhsT . extractT :: TransformH CoreTC String -> TransformH CoreExprEquality String)- [ "Apply a transformation to the RHS of an equality." ]- , external "both" (bothR . extractR :: RewriteH Core -> RewriteH CoreExprEquality)- [ "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 CoreExprEquality String)- [ "Apply a transformation to the RHS of an equality." ] ] -- | Externals that are added to the dictionary only when in interactive proof mode.@@ -109,7 +75,7 @@ proof_externals = map (.+ Proof) [ external "induction" (PCInduction . cmpString2Var :: String -> ProofShellCommand) [ "Perform induction on given universally quantified variable."- , "Each constructor case will generate a new CoreExprEquality to be proven."+ , "Each constructor case will generate a new equality to be proven." ] , external "dump" PCDump [ "dump <filename> <renderer> <width>" ]@@ -122,10 +88,7 @@ -------------------------------------------------------------------------------------------------------- data ProofCommand- = RuleToLemma RuleNameString- | InteractiveProof LemmaName- | ModifyLemma LemmaName (String -> String) (RewriteH CoreExprEquality) (Bool -> Bool)- | QueryLemma LemmaName (TransformH CoreExprEquality String)+ = InteractiveProof LemmaName | ShowLemmas (Maybe LemmaName) | DumpLemma LemmaName String String Int deriving (Typeable)@@ -137,135 +100,86 @@ -------------------------------------------------------------------------------------------------------- -getLemmaByName :: Monad m => CommandLineState -> LemmaName -> m Lemma-getLemmaByName st nm =- case [ lm | lm@(n,_,_) <- cl_lemmas st, n == nm ] of- [] -> fail ("No lemma named: " ++ nm)- (l:_) -> return l--deleteLemmaByName :: MonadState CommandLineState m => LemmaName -> m ()-deleteLemmaByName nm = modify $ \ st -> st { cl_lemmas = [ l | l@(n,_,_) <- cl_lemmas st, nm /= n ] }--lemma :: Bool -> CommandLineState -> LemmaName -> BiRewriteH CoreExpr-lemma ok st nm = beforeBiR- (do (_,equality,proven) <- getLemmaByName st nm- guardMsg (proven || ok) ("Lemma " ++ nm ++ " has not been proven.")- return equality- )- birewrite------------------------------------------------------------------------------------------------------------lemmaNameToEqualityT :: Monad m => CommandLineState -> LemmaName -> m CoreExprEquality-lemmaNameToEqualityT st nm =- do (_,eq,_) <- getLemmaByName st nm- return eq---- | @e@ ==> @let v = lhs in e@ (also works in a similar manner at Program nodes)-lemmaLhsIntroR :: CommandLineState -> LemmaName -> RewriteH Core-lemmaLhsIntroR st = lemmaNameToEqualityT st >=> eqLhsIntroR---- | @e@ ==> @let v = rhs in e@ (also works in a similar manner at Program nodes)-lemmaRhsIntroR :: CommandLineState -> LemmaName -> RewriteH Core-lemmaRhsIntroR st = lemmaNameToEqualityT st >=> eqRhsIntroR----------------------------------------------------------------------------------------------------------+performProofCommand :: (MonadCatch m, MonadException m, CLMonad m) => ProofCommand -> m () -performProofCommand :: (MonadCatch m, MonadError CLException m, MonadIO m, MonadState CommandLineState m) => ProofCommand -> m ()-performProofCommand (RuleToLemma nm) = do+performProofCommand (InteractiveProof nm) = do st <- gets cl_pstate- equality <- queryS (ps_kernel st) (ruleNameToEqualityT nm :: TransformH Core CoreExprEquality) (mkKernelEnv st) (ps_cursor st)- _ <- addLemmas [(nm,equality,False)]- return ()--performProofCommand (InteractiveProof nm) = get >>= flip getLemmaByName nm >>= interactiveProof True--performProofCommand (ModifyLemma nm nFn rr pFn) = do- st <- get- (_,eq,p) <- getLemmaByName st nm-- -- query so lemma is transformed in current context- eq' <- queryS (cl_kernel st) (return eq >>> rr >>> (bothT lintExprT >> idR) :: TransformH Core CoreExprEquality) (cl_kernel_env st) (cl_cursor st)- deleteLemmaByName (nFn nm)- _ <- addLemmas [(nFn nm, eq', pFn p)]- return ()--performProofCommand (QueryLemma nm t) = do- st <- get- (_,eq,_) <- getLemmaByName st nm-- -- query so lemma is transformed in current context- res <- queryS (cl_kernel st) (return eq >>> t :: TransformH Core String) (cl_kernel_env st) (cl_cursor st)- cl_putStrLn res+ 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 -> getLemmaByName st nm >>> ppLemmaT (cl_pretty st)) fn r w+performProofCommand (DumpLemma nm fn r w) = dump (\ st -> getLemmaByNameT nm >>> ppLemmaT (cl_pretty st) nm) fn r w performProofCommand (ShowLemmas mnm) = do- ls <- gets $ filter (maybe (const True) (\ nm (n,_,_) -> nm `isInfixOf` n) mnm) . cl_lemmas- forM_ ls printLemma+ 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) => Lemma -> m ()-printLemma lem = do++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) :: TransformH Core DocH) (cl_kernel_env st) (cl_cursor st)+ 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 -> TransformH Lemma DocH-ppLemmaT pp = do- (nm, eq, p) <- idR- eqDoc <- return eq >>> ppCoreExprEqualityT pp- let hDoc = text nm <+> text (if p then "(Proven)" else "(Not Proven)")+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 -------------------------------------------------------------------------------------------------------- -completeProof :: (MonadError CLException m, MonadIO m, MonadState CommandLineState m) => LemmaName -> m ()-completeProof nm = do- cl_putStrLn $ "Successfully proven: " ++ nm- modify $ \ st -> st { cl_lemmas = [ (n,e, if n == nm then True else p) | (n,e,p) <- cl_lemmas st ] }- get >>= continue+type NamedLemma = (LemmaName, Lemma) -interactiveProof :: (MonadCatch m, MonadError CLException m, MonadIO m, MonadState CommandLineState m) => Bool -> Lemma -> m ()-interactiveProof topLevel lem = do- origEs <- addProofExternals topLevel+interactiveProof :: forall m. (MonadCatch m, MonadException m, CLMonad m) => Bool -> Bool -> NamedLemma -> m ()+interactiveProof topLevel isTemporary lem@(nm,_) = do origSt <- get- completionMVar <- liftIO $ newMVar origSt+ origEs <- addProofExternals topLevel let ws_complete = " ()" -- Main proof input loop- loop :: Lemma -> CLT (InputT IO) ()+ loop :: NamedLemma -> InputT m () loop l = do- mExpr <- popScriptLine+ mExpr <- lift popScriptLine case mExpr of Nothing -> do- printLemma l- st <- get- liftIO $ modifyMVar_ completionMVar (const $ return st) -- so the completion can get the current state- mLine <- lift $ getInputLine $ "proof> "+ 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 (evalProofScript l line `catchM` (\msg -> cl_putStrLn msg >> return l)) >>= loop- Just e -> (runExprH l e `catchM` (\msg -> setRunningScript Nothing >> cl_putStrLn msg >> return l)) >>= loop+ 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 completionMVar)) defaultSettings+ let settings = setComplete (completeWordWithPrev Nothing ws_complete shellComplete) defaultSettings cleanup s = put (s { cl_externals = origEs })- (r,_s) <- get >>= liftIO . runInputTBehavior defaultBehavior settings . flip runCLT (loop lem)- case r of- Right _ -> return () -- this case isn't possible, loop never returns- Left CLAbort -> cleanup origSt >> unless topLevel abort -- abandon proof attempt, bubble out to regular shell- Left (CLContinue st') -> cleanup st' -- successfully proven- Left (CLError msg) -> fail $ "Prover error: " ++ msg- Left _ -> fail "unsupported exception in interactive prover"+ 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")+ addProofExternals :: MonadState CommandLineState m => Bool -> m [External] addProofExternals topLevel = do st <- get@@ -275,16 +189,16 @@ when topLevel $ modify $ \ s -> s { cl_externals = newEs } return es -evalProofScript :: MonadIO m => Lemma -> String -> CLT m Lemma+evalProofScript :: (MonadCatch m, MonadException m, CLMonad m) => NamedLemma -> String -> m NamedLemma evalProofScript lem = parseScriptCLT >=> foldM runExprH lem -runExprH :: (MonadCatch m, MonadError CLException m, MonadIO m, MonadState CommandLineState m) => Lemma -> ExprH -> m Lemma+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 -- | 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) => Lemma -> m ()-endProof (nm, eq, _) = do+endProof :: (MonadCatch m, MonadError CLException m, MonadIO m, MonadState CommandLineState m) => NamedLemma -> m ()+endProof (nm, Lemma eq _ _) = do st <- get let sk = cl_kernel st@@ -292,11 +206,11 @@ sast = cl_cursor st -- 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 verifyCoreExprEqualityT :: TransformH Core Bool) kEnv sast)- if b then completeProof nm else fail $ "The two sides of " ++ nm ++ " are not alpha-equivalent."+ 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." -performProofShellCommand :: (MonadCatch m, MonadError CLException m, MonadIO m, MonadState CommandLineState m) => Lemma -> ProofShellCommand -> m Lemma-performProofShellCommand lem@(nm, eq, b) = go+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@@ -304,8 +218,9 @@ sast = cl_cursor st -- Why do a query? We want to do our proof in the current context of the shell, whatever that is.- eq' <- queryS sk (return eq >>> rr >>> (bothT lintExprT >> idR) :: TransformH Core CoreExprEquality) kEnv sast- return (nm, eq', b)+ -- 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@@ -330,14 +245,14 @@ 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)- completeProof nm -- note: we assume that if 't' completes without failing, the lemma is proved, we don't actually check+ 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 lem >>> ppLemmaT (cl_pretty st)) fName r w >> return lem+ 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 -performInduction :: (MonadCatch m, MonadError CLException m, MonadIO m, MonadState CommandLineState m) => Lemma -> (Id -> Bool) -> m Lemma-performInduction lem@(nm, eq@(CoreExprEquality bs lhs rhs), _) idPred = do+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@@ -355,29 +270,38 @@ eqs <- forM vs_matching_i_type $ \ i' -> liftM discardUniVars $ instantiateEqualityVar (==i) (Var i') [] eq - let nms = [ "ind-hyp-" ++ show n | n :: Int <- [0..] ]- hypLemmas = zip3 nms eqs (repeat True)- caseLemma = ( nm ++ "-induction-on-" ++ getOccString i ++ "-case-" ++ maybe "undefined" getOccString mdc- , CoreExprEquality (delete i bs ++ vs) lhsE rhsE- , False )+ 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 - origLemmas <- addLemmas hypLemmas- interactiveProof False caseLemma -- recursion!- modify $ \ s -> s { cl_lemmas = origLemmas } -- put original lemmas back+ -- this is pretty hacky+ sast' <- addLemmas hypLemmas -- add temporary lemmas+ interactiveProof False True (lemmaName,caseLemma) -- recursion!+ modify $ flip setCursor sast' -- discard temporary lemmas - completeProof nm+ get >>= continue return lem -- this is never reached, but the type says we need it. -addLemmas :: (MonadCatch m, MonadError CLException m, MonadIO m, MonadState CommandLineState m) => [Lemma] -> m [Lemma]+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+ st <- get- put $ st { cl_lemmas = cl_lemmas st ++ lems }- return $ cl_lemmas st+ sast <- applyS (cl_kernel st) addAllAtOnceR (mkKernelEnv $ cl_pstate st) (cl_cursor st)+ put $ newSAST (CmdName "adding lemmas") sast st + -- return original SAST+ return $ cl_cursor st+ data ProofShellCommand- = PCRewrite (RewriteH CoreExprEquality)- | PCTransform (TransformH CoreExprEquality String)+ = PCRewrite (RewriteH Equality)+ | PCTransform (TransformH Equality String) | PCInduction (Id -> Bool) | PCShell ShellEffect | PCScript ScriptEffect@@ -390,9 +314,9 @@ deriving Typeable -- keep abstract to avoid breaking things if we modify this later-newtype UserProofTechnique = UserProofTechnique (TransformH CoreExprEquality ())+newtype UserProofTechnique = UserProofTechnique (TransformH Equality ()) -userProofTechnique :: TransformH CoreExprEquality () -> UserProofTechnique+userProofTechnique :: TransformH Equality () -> UserProofTechnique userProofTechnique = UserProofTechnique instance Extern ProofShellCommand where@@ -407,29 +331,29 @@ box = UserProofTechniqueBox unbox (UserProofTechniqueBox t) = t -interpProof :: [Interp ProofShellCommand]+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 $ \ (RewriteCoreExprEqualityBox r) -> PCRewrite r- , interp $ \ (TransformCoreExprEqualityStringBox 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"+ [ 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" ]
src/HERMIT/Shell/ScriptToRewrite.hs view
@@ -1,4 +1,5 @@-{-# LANGUAGE DeriveDataTypeable, FlexibleContexts, LambdaCase, MultiParamTypeClasses, ScopedTypeVariables, TypeFamilies #-}+{-# LANGUAGE ConstraintKinds, DeriveDataTypeable, FlexibleContexts, LambdaCase,+ MultiParamTypeClasses, ScopedTypeVariables, TypeFamilies, CPP #-} module HERMIT.Shell.ScriptToRewrite ( -- * Converting Scripts to Rewrites@@ -15,7 +16,11 @@ ) 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.Exception hiding (catch) @@ -66,7 +71,7 @@ popScriptLine = gets cl_running_script >>= maybe (return Nothing) (\case [] -> setRunningScript Nothing >> return Nothing (e:es) -> setRunningScript (Just es) >> return (Just e)) -performScriptEffect :: (MonadCatch m, MonadError CLException m, MonadIO m, MonadState CommandLineState m) => (ExprH -> m ()) -> ScriptEffect -> m ()+performScriptEffect :: (MonadCatch m, CLMonad m) => (ExprH -> m ()) -> ScriptEffect -> m () performScriptEffect runner = go where go (SeqMeta ms) = mapM_ go ms go (LoadFile scriptName fileName) = do@@ -74,7 +79,7 @@ res <- liftIO $ try (readFile fileName) case res of Left (err :: IOException) -> fail ("IO error: " ++ show err)- Right str -> do + Right str -> do script <- parseScriptCLT str modify $ \ st -> st {cl_scripts = (scriptName,script) : cl_scripts st} putStrToConsole ("Script \"" ++ scriptName ++ "\" loaded successfully from \"" ++ fileName ++ "\".")@@ -104,7 +109,7 @@ putStrToConsole ("Script \"" ++ scriptName ++ "\" ran successfully.") showWindow - go (SaveScript fileName scriptName) = do + go (SaveScript fileName scriptName) = do script <- lookupScript scriptName putStrToConsole $ "Saving script \"" ++ scriptName ++ "\" to file \"" ++ fileName ++ "\"." liftIO $ writeFile fileName $ unparseScript script@@ -164,7 +169,7 @@ ----------------------------------- -interpScriptR :: [Interp UnscopedScriptR]+interpScriptR :: Monad m => [Interp m UnscopedScriptR] interpScriptR = [ interp (\ (RewriteCoreBox r) -> ScriptPrimUn $ ScriptRewriteHCore r) , interp (\ (RewriteCoreTCBox _) -> ScriptUnsupported "rewrite that traverses types and coercions") -- TODO@@ -201,7 +206,7 @@ ----------------------------------- -scriptToRewrite :: MonadState CommandLineState m => Script -> m (RewriteH Core)+scriptToRewrite :: CLMonad m => Script -> m (RewriteH Core) scriptToRewrite scr = do unscoped <- mapM (interpExprH interpScriptR) scr scoped <- unscopedToScopedScriptR $ zip scr unscoped@@ -210,13 +215,13 @@ ----------------------------------- -- | Insert a script into the 'Dictionary'.-addScriptToDict :: MonadState CommandLineState m => ScriptName -> Script -> m ()+addScriptToDict :: CLMonad m => ScriptName -> Script -> m () addScriptToDict nm scr = do r <- scriptToRewrite scr let ext = external nm r [ "User-loaded script." ] - modify $ \ st -> st { cl_externals = ext : cl_externals st } + modify $ \ st -> st { cl_externals = ext : cl_externals st } -----------------------------------
src/HERMIT/Shell/ShellEffect.hs view
@@ -2,18 +2,21 @@ DeriveDataTypeable, GeneralizedNewtypeDeriving, LambdaCase, MultiParamTypeClasses, ScopedTypeVariables #-} -module HERMIT.Shell.ShellEffect +module HERMIT.Shell.ShellEffect ( ShellEffect(..) , performShellEffect , dump ) where +#if MIN_VERSION_mtl(2,2,1)+import Control.Monad.Except+#else import Control.Monad.Error+#endif import Control.Monad.State import Data.Typeable -import HERMIT.Dictionary import HERMIT.External import HERMIT.Kure import HERMIT.Kernel.Scoped@@ -33,7 +36,7 @@ | 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 + | Dump (CommandLineState -> TransformH CoreTC DocH) String String Int | Resume deriving Typeable @@ -46,11 +49,7 @@ performShellEffect :: (MonadCatch m, MonadError CLException m, MonadIO m, MonadState CommandLineState m) => ShellEffect -> m () performShellEffect Abort = abort-performShellEffect Resume = do- st <- get- sast' <- applyS (cl_kernel st) occurAnalyseAndDezombifyR (cl_kernel_env st) (cl_cursor st)- resume sast'-+performShellEffect Resume = gets cl_cursor >>= resume performShellEffect Continue = get >>= continue performShellEffect (Dump pp fileName renderer width) = dump pp fileName renderer width
src/HERMIT/Shell/Types.hs view
@@ -1,21 +1,22 @@-{-# LANGUAGE CPP, KindSignatures, GADTs, FlexibleContexts, DeriveDataTypeable, +{-# LANGUAGE ConstraintKinds, CPP, KindSignatures, GADTs, FlexibleContexts, DeriveDataTypeable, FunctionalDependencies, GeneralizedNewtypeDeriving, InstanceSigs, LambdaCase, RankNTypes, ScopedTypeVariables, TypeFamilies #-} module HERMIT.Shell.Types where import Control.Applicative-import Control.Arrow-import Control.Concurrent 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 Data.Char (isSpace) import Data.Dynamic-import Data.List (intercalate, isPrefixOf, nub)+import Data.List (intercalate) import qualified Data.Map as M-import Data.Maybe (isJust)+import Data.Maybe (fromMaybe, isJust) import Data.Monoid (mempty) import HERMIT.Context@@ -23,9 +24,8 @@ import HERMIT.Kure import HERMIT.External import qualified HERMIT.GHC as GHC-import HERMIT.Kernel (AST, queryK)+import HERMIT.Kernel (AST, queryK, KernelEnv) import HERMIT.Kernel.Scoped-import HERMIT.Monad import HERMIT.Parser import HERMIT.PrettyPrinter.Common @@ -33,35 +33,17 @@ import HERMIT.Plugin.Renderer import HERMIT.Plugin.Types -import HERMIT.Dictionary.Inline-import HERMIT.Dictionary.Navigation-import HERMIT.Dictionary.Reasoning (CoreExprEquality)- import System.Console.Haskeline hiding (catch, display) import System.IO (Handle, stdout) -#ifndef mingw32_HOST_OS-import Data.Maybe (fromMaybe)+#ifdef mingw32_HOST_OS+import HERMIT.Win32.Console+#else import System.Console.Terminfo (setupTermFromEnv, getCapability, termColumns, termLines) #endif ---------------------------------------------------------------------------------- -{---- | How to perform a given set of commands.------ Mnemonic:--- c = command type--- a = extra arguments type (use tuple for more than one)--- r = result type------ Often, a and r are (), but sometimes we need more clever things.-class ShellCommandSet c a r | c -> a r where- performCommand :: (MonadCatch m, MonadError CLException m, MonadIO m, MonadState CommandLineState m) => c -> a -> m r--}------------------------------------------------------------------------------------- data QueryFun :: * where QueryString :: (Injection GHC.ModGuts g, Walker HermitC g) => TransformH g String -> QueryFun@@ -80,8 +62,7 @@ box i = i unbox i = i -performQuery :: (MonadCatch m, MonadError CLException m, MonadIO m, MonadState CommandLineState m)- => QueryFun -> ExprH -> m ()+performQuery :: (MonadCatch m, CLMonad m) => QueryFun -> ExprH -> m () performQuery (QueryString q) _ = do st <- get@@ -156,7 +137,9 @@ | 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 = throwError CLAbort@@ -181,16 +164,41 @@ ---------------------------------------------------------------------------------- -- | This type is similiar to PluginM, except that its exception and state types are--- supersets of those for PluginM, and it is a transformer. There are two functions: --- `clm` and `pluginM` for converting between the two. The reason we do this is to obtain --- a clean separation of plugin state from commandline state without nesting state --- transformers. Nesting StateT leads to a lot of awkward lifting and manual state +-- supersets of those for PluginM, and it is a transformer. There are two functions:+-- `clm` and `pluginM` for converting between the two. The reason we do this is to obtain+-- a clean separation of plugin state from commandline state without nesting state+-- transformers. Nesting StateT leads to a lot of awkward lifting and manual state -- 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)+ in fmap unCLT $ f run'++-- This is copied verbatim from Haskeline, which provides an instance for strict State only.+-- This allows lazy State to enjoy the same benefits.+instance MonadException m => MonadException (StateT s m) where+ controlIO f = StateT $ \s -> controlIO $ \(RunIO run) -> let+ run' = RunIO (fmap (StateT . const) . run . flip runStateT s)+ in fmap (flip runStateT s) $ f run'++type CLMonad m = (MonadIO m, MonadState CommandLineState m, MonadError CLException m)+ instance MonadTrans CLT where -- lift :: Monad m => m a -> CLT m a lift = CLT . lift . lift@@ -206,7 +214,11 @@ -- | 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@@ -225,7 +237,7 @@ Right r' -> put (cl_pstate s') >> return r' -- | Lift a PluginM computation into the CLM monad.-pluginM :: (MonadError CLException m, MonadIO m, MonadState CommandLineState m) => PluginM a -> m a+pluginM :: CLMonad m => PluginM a -> m a pluginM m = do s <- get (r,ps) <- liftIO $ runPluginT (cl_pstate s) m@@ -268,7 +280,6 @@ -- because nested StateT is a pain. , cl_height :: Int -- ^ console height, in lines , cl_scripts :: [(ScriptName,Script)]- , cl_lemmas :: [Lemma] -- ^ list of lemmas, with flag indicating whether proven , cl_nav :: Bool -- ^ keyboard input the nav panel , cl_version :: VersionStore , cl_window :: PathH -- ^ path to beginning of window, always a prefix of focus path in kernel@@ -306,7 +317,7 @@ cl_kernel :: CommandLineState -> ScopedKernel cl_kernel = ps_kernel . cl_pstate -cl_kernel_env :: CommandLineState -> HermitMEnv+cl_kernel_env :: CommandLineState -> KernelEnv cl_kernel_env = mkKernelEnv . cl_pstate cl_pretty :: CommandLineState -> PrettyPrinter@@ -324,16 +335,15 @@ cl_render :: CommandLineState -> (Handle -> PrettyOptions -> Either String DocH -> IO ()) cl_render = ps_render . cl_pstate --- | Create default CommandLineState from PluginState. +-- | Create default CommandLineState from PluginState. -- Note: the dictionary (cl_dict) will be empty, and should be populated if needed. mkCLS :: PluginM CommandLineState mkCLS = do ps <- get- (w,h) <- liftIO getTermDimensions + (w,h) <- liftIO getTermDimensions let st = CommandLineState { cl_pstate = ps , cl_height = h , cl_scripts = []- , cl_lemmas = [] , cl_nav = False , cl_version = VersionStore { vs_graph = [] , vs_tags = [] } , cl_window = mempty@@ -346,7 +356,8 @@ getTermDimensions :: IO (Int, Int) getTermDimensions = do #ifdef mingw32_HOST_OS- return (80,25) -- these are the standard windows CLI dimensions+ consoleSz <- getConsoleWindowSize+ return $ fromMaybe (80,25) consoleSz #else term <- setupTermFromEnv let w = fromMaybe 80 $ getCapability term termColumns@@ -361,8 +372,6 @@ box = CLSBox type ScriptName = String-type LemmaName = String-type Lemma = (LemmaName,CoreExprEquality,Bool) -- tick counter tick :: TVar (M.Map String Int) -> String -> IO Int@@ -374,10 +383,10 @@ writeTVar var (M.insert msg c m) return c -cl_putStr :: (MonadError CLException m, MonadIO m, MonadState CommandLineState m) => String -> m ()+cl_putStr :: CLMonad m => String -> m () cl_putStr = pluginM . ps_putStr -cl_putStrLn :: (MonadError CLException m, MonadIO m, MonadState CommandLineState m) => String -> m ()+cl_putStrLn :: CLMonad m => String -> m () cl_putStrLn = pluginM . ps_putStrLn isRunningScript :: MonadState CommandLineState m => m Bool@@ -387,65 +396,12 @@ setRunningScript ms = modify $ \st -> st { cl_running_script = ms } -- TODO: rename?-putStrToConsole :: (MonadError CLException m, MonadIO m, MonadState CommandLineState m) => String -> m ()+putStrToConsole :: CLMonad m => String -> m () putStrToConsole str = ifM isRunningScript (return ()) (cl_putStrLn str) ------------------------------------------------------------------------------ -shellComplete :: MVar CommandLineState -> String -> String -> IO [Completion]-shellComplete mvar rPrev so_far = do- st <- readMVar mvar- targetQuery <- completionQuery st (completionType rPrev)- -- (liftM.liftM) (map simpleCompletion . nub . filter (so_far `isPrefixOf`))- -- $ queryS (cl_kernel st) (cl_cursor (cl_session st)) targetQuery- -- TODO: I expect you want to build a silent version of the kernal_env for this query- cl <- catchM (queryS (cl_kernel st) targetQuery (cl_kernel_env st) (cl_cursor st)) (\_ -> return [])- return $ (map simpleCompletion . nub . filter (so_far `isPrefixOf`)) cl--data CompletionType = ConsiderC -- considerable constructs and (deprecated) bindingOfT- | BindingOfC -- bindingOfT- | BindingGroupOfC -- bindingGroupOfT- | RhsOfC -- rhsOfT- | OccurrenceOfC -- occurrenceOfT- | InlineC -- complete with names that can be inlined- | CommandC -- complete using dictionary commands (default)- | AmbiguousC [CompletionType] -- completionType function needs to be more specific- deriving (Show)---- TODO: reverse rPrev and parse it, to better figure out what possiblities are in context?--- for instance, completing "any-bu (inline " should be different than completing just "inline "--- this would also allow typed completion?-completionType :: String -> CompletionType-completionType = go . dropWhile isSpace- where go rPrev = case [ ty | (nm, ty) <- opts, reverse nm `isPrefixOf` rPrev ] of- [] -> CommandC- [t] -> t- ts -> AmbiguousC ts- opts = [ ("inline" , InlineC )- , ("consider" , ConsiderC)- , ("binding-of" , BindingOfC)- , ("binding-group-of", BindingGroupOfC)- , ("rhs-of" , RhsOfC)- , ("occurrence-of" , OccurrenceOfC)- ]--completionQuery :: CommandLineState -> CompletionType -> IO (TransformH CoreTC [String])-completionQuery _ ConsiderC = return $ bindingOfTargetsT >>^ GHC.varSetToStrings >>^ map ('\'':) >>^ (++ map fst considerables) -- the use of bindingOfTargetsT here is deprecated-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 s CommandC = return $ pure (map externName (cl_externals s))--- Need to modify opts in completionType function. No key can be a suffix of another key.-completionQuery _ (AmbiguousC ts) = do- putStrLn "\nCannot tab complete: ambiguous completion type."- putStrLn $ "Possibilities: " ++ intercalate ", " (map show ts)- return (pure [])----------------------------------------------------------------------------------fixWindow :: (MonadError CLException m, MonadIO m, MonadState CommandLineState m) => m ()+fixWindow :: CLMonad m => m () fixWindow = do st <- get -- check to make sure new path is still inside window@@ -457,7 +413,7 @@ $ put $ st { cl_window = focusPath } -} put $ st { cl_window = focusPath } -- TODO: temporary until we figure out a better highlight interface -showWindow :: (MonadError CLException m, MonadIO m, MonadState CommandLineState m) => m ()+showWindow :: CLMonad m => m () showWindow = ifM isRunningScript (return ()) $ fixWindow >> gets cl_window >>= pluginM . display . Just ------------------------------------------------------------------------------@@ -470,7 +426,7 @@ [ [ unparseExprH b ++ "\n" ++ showGraph graph tags c ] | (b,c) <- paths ])- where + where paths = [ (b,c) | (a,b,c) <- graph, a == this ] ------------------------------------------------------------------------------
src/HERMIT/Utilities.hs view
@@ -1,15 +1,14 @@ module HERMIT.Utilities- ( -- * Utilities- nodups- , dups- , dupsBy- , soleElement- , equivalentBy- , equivalent- , whenJust- , maybeM- )-where+ ( -- * Utilities+ nodups+ , dups+ , dupsBy+ , soleElement+ , equivalentBy+ , equivalent+ , whenJust+ , maybeM+ ) where ------------------------------------------------------------------------------
+ src/HERMIT/Win32/Console.hsc view
@@ -0,0 +1,105 @@+{-# LANGUAGE ForeignFunctionInterface #-}+-- | Taken from <https://github.com/batterseapower/ansi-terminal/blob/master/System/Console/ANSI/Windows/Foreign.hs> in the ansi-terminal package by batterseapower, licensed under BSD3+module HERMIT.Win32.Console+ (+ getConsoleWindowSize+ , isCygwinConsole+ ) where++import Control.Applicative+import Control.Exception (try)++import Foreign.C.Types+import Foreign.Marshal+import Foreign.Ptr+import Foreign.Storable++import System.Environment+import System.Win32.Types++#include <windows.h>+#let alignment t = "%lu", (unsigned long)offsetof(struct {char x__; t (y__); }, y__)++type SHORT = CShort++isCygwinConsole :: IO Bool+isCygwinConsole = do+ result <- try $ getEnv "_" -- Cygwin defines this, Windows Cmd does not+ return $ case (result :: Either IOError String) of+ Left _ -> False+ Right _ -> True++getConsoleWindowSize :: IO (Maybe (Int, Int))+getConsoleWindowSize = do+ hStdout <- getStdHandle sTD_OUTPUT_HANDLE+ csbiInfo <- getConsoleScreenBufferInfo hStdout+ return $ fmap coords csbiInfo+ where coords :: CONSOLE_SCREEN_BUFFER_INFO -> (Int, Int)+ coords info = case csbi_maximum_window_size info of+ (COORD x y) -> (fromIntegral x, fromIntegral y)++sTD_OUTPUT_HANDLE :: DWORD+sTD_OUTPUT_HANDLE = #{const STD_OUTPUT_HANDLE}++foreign import ccall unsafe "windows.h GetStdHandle"+ getStdHandle :: DWORD -> IO HANDLE+foreign import ccall unsafe "windows.h GetConsoleScreenBufferInfo"+ cGetConsoleScreenBufferInfo :: HANDLE -> Ptr CONSOLE_SCREEN_BUFFER_INFO -> IO BOOL++getConsoleScreenBufferInfo :: HANDLE -> IO (Maybe CONSOLE_SCREEN_BUFFER_INFO)+getConsoleScreenBufferInfo handle = alloca $ \ptr_console_screen_buffer_info -> do+ ret <- cGetConsoleScreenBufferInfo handle ptr_console_screen_buffer_info+ if ret then peek ptr_console_screen_buffer_info >>= return . Just+ else return Nothing++data CONSOLE_SCREEN_BUFFER_INFO = CONSOLE_SCREEN_BUFFER_INFO {+ _csbi_size :: COORD,+ _csbi_cursor_position :: COORD,+ _csbi_attributes :: WORD,+ _csbi_window :: SMALL_RECT,+ csbi_maximum_window_size :: COORD+ }++instance Storable CONSOLE_SCREEN_BUFFER_INFO where+ sizeOf _ = #{size CONSOLE_SCREEN_BUFFER_INFO}+ alignment _ = #{alignment CONSOLE_SCREEN_BUFFER_INFO}+ peek ptr = CONSOLE_SCREEN_BUFFER_INFO <$>+ #{peek CONSOLE_SCREEN_BUFFER_INFO, dwSize} ptr <*>+ #{peek CONSOLE_SCREEN_BUFFER_INFO, dwCursorPosition} ptr <*>+ #{peek CONSOLE_SCREEN_BUFFER_INFO, wAttributes} ptr <*>+ #{peek CONSOLE_SCREEN_BUFFER_INFO, srWindow} ptr <*>+ #{peek CONSOLE_SCREEN_BUFFER_INFO, dwMaximumWindowSize} ptr+ poke ptr (CONSOLE_SCREEN_BUFFER_INFO size cursor_position attributes window maximum_window_size) = do+ #{poke CONSOLE_SCREEN_BUFFER_INFO, dwSize} ptr size+ #{poke CONSOLE_SCREEN_BUFFER_INFO, dwCursorPosition} ptr cursor_position+ #{poke CONSOLE_SCREEN_BUFFER_INFO, wAttributes} ptr attributes+ #{poke CONSOLE_SCREEN_BUFFER_INFO, srWindow} ptr window+ #{poke CONSOLE_SCREEN_BUFFER_INFO, dwMaximumWindowSize} ptr maximum_window_size++data COORD = COORD SHORT SHORT++instance Storable COORD where+ sizeOf _ = #{size COORD}+ alignment _ = #{alignment COORD}+ peek ptr =+ COORD <$> #{peek COORD, X} ptr+ <*> #{peek COORD, Y} ptr+ poke ptr (COORD x y) = do+ #{poke COORD, X} ptr x+ #{poke COORD, Y} ptr y++data SMALL_RECT = SMALL_RECT SHORT SHORT SHORT SHORT++instance Storable SMALL_RECT where+ sizeOf _ = #{size SMALL_RECT}+ alignment _ = #{alignment SMALL_RECT}+ peek ptr =+ SMALL_RECT <$> #{peek SMALL_RECT, Left} ptr+ <*> #{peek SMALL_RECT, Top} ptr+ <*> #{peek SMALL_RECT, Right} ptr+ <*> #{peek SMALL_RECT, Bottom} ptr+ poke ptr (SMALL_RECT l t r b) = do+ #{poke SMALL_RECT, Left} ptr l+ #{poke SMALL_RECT, Top} ptr t+ #{poke SMALL_RECT, Right} ptr r+ #{poke SMALL_RECT, Bottom} ptr b
+ src/HERMIT/Win32/IO.hsc view
@@ -0,0 +1,239 @@+-- | Adapted from circular-ruin's StackOverflow answer at <http://stackoverflow.com/a/10779150>+{-# LANGUAGE ForeignFunctionInterface, CPP, NoImplicitPrelude #-}+module HERMIT.Win32.IO (+ HERMIT.Win32.IO.putChar+ , HERMIT.Win32.IO.putStr+ , HERMIT.Win32.IO.putStrLn+ , HERMIT.Win32.IO.print+ , ePutChar+ , ePutStr+ , ePutStrLn+ , ePrint+ , HERMIT.Win32.IO.hPutChar+ , HERMIT.Win32.IO.hPutStr+ , HERMIT.Win32.IO.hPutStrLn+ , HERMIT.Win32.IO.hPrint+ , trace+ , traceIO+ ) where++#include <windows.h>++import Control.Concurrent.MVar+import Control.Exception (bracket)++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+import GHC.IO.Handle.Types (Handle(..), Handle__(..))++import Prelude hiding (putStr, putStrLn) --(IO, Read, Show, String)++import qualified System.IO (hPutChar, hPutStr, hPutStrLn)+import System.IO hiding (putStr, putStrLn, hPutChar, hPutStr, hPutStrLn)+import System.IO.Unsafe (unsafePerformIO)+import System.Win32.Types (BOOL, HANDLE, DWORD, LPDWORD, LPWSTR, LPVOID)++-- | <http://msdn.microsoft.com/en-us/library/ms683231(VS.85).aspx>+-- HANDLE WINAPI GetStdHandle(DWORD nStdHandle);+-- returns INVALID_HANDLE_VALUE, NULL, or a valid handle+foreign import ccall unsafe "GetStdHandle"+ win32GetStdHandle :: DWORD -> IO HANDLE++sTD_OUTPUT_HANDLE, sTD_ERROR_HANDLE :: DWORD+sTD_OUTPUT_HANDLE = (#const STD_OUTPUT_HANDLE) -- all DWORD arithmetic is performed modulo 2^n+sTD_ERROR_HANDLE = (#const STD_ERROR_HANDLE)++-- | <http://msdn.microsoft.com/en-us/library/aa364960(VS.85).aspx>+-- DWORD WINAPI GetFileType(HANDLE hFile);+foreign import ccall unsafe "GetFileType"+ win32GetFileType :: HANDLE -> IO DWORD++fILE_TYPE_CHAR, fILE_TYPE_REMOTE :: DWORD+fILE_TYPE_CHAR = (#const FILE_TYPE_CHAR)+fILE_TYPE_REMOTE = (#const FILE_TYPE_REMOTE)++-- | <http://msdn.microsoft.com/en-us/library/ms683167(VS.85).aspx>+-- BOOL WINAPI GetConsoleMode(HANDLE hConsole, LPDWORD lpMode);+foreign import ccall unsafe "GetConsoleMode"+ win32GetConsoleMode :: HANDLE -> LPDWORD -> IO BOOL++iNVALID_HANDLE_VALUE :: HANDLE+iNVALID_HANDLE_VALUE = intPtrToPtr $ -1++isAConsole :: HANDLE -> IO Bool+isAConsole handle+ = if (handle == iNVALID_HANDLE_VALUE) then return False+ else do ft <- win32GetFileType handle+ if ((ft .&. complement fILE_TYPE_REMOTE) /= fILE_TYPE_CHAR) then return False+ else do ptr <- malloc+ cm <- win32GetConsoleMode handle ptr+ free ptr+ return cm++-- | BOOL WINAPI WriteConsoleW(HANDLE hOutput, LPWSTR lpBuffer, DWORD nChars,+-- LPDWORD lpCharsWritten, LPVOID lpReserved); -}+foreign import ccall unsafe "WriteConsoleW" win32WriteConsoleW+ :: HANDLE -> LPWSTR -> DWORD -> LPDWORD -> LPVOID -> IO BOOL++data ConsoleInfo = ConsoleInfo Int (Ptr CWchar) (Ptr DWORD) HANDLE++writeConsole :: ConsoleInfo -> String -> IO ()+writeConsole (ConsoleInfo bufsize buf written handle) string+ = let fillbuf :: Int -> String -> IO ()+ fillbuf i [] = emptybuf buf i []+ fillbuf i remain@(first:rest)+ | i + 1 < bufsize && ordf <= 0xffff = do pokeElemOff buf i asWord+ fillbuf (i+1) rest+ | i + 1 < bufsize && ordf > 0xffff = do pokeElemOff buf i word1+ pokeElemOff buf (i+1) word2+ fillbuf (i+2) rest+ | otherwise = emptybuf buf i remain+ where ordf = ord first+ asWord = fromInteger (toInteger ordf) :: CWchar+ sub = ordf - 0x10000+ word1' = ((shiftR sub 10) .&. 0x3ff) + 0xD800+ word2' = (sub .&. 0x3FF) + 0xDC00+ word1 = fromInteger . toInteger $ word1'+ word2 = fromInteger . toInteger $ word2'++ emptybuf :: (Ptr CWchar) -> Int -> String -> IO ()+ emptybuf _ 0 [] = return ()+ emptybuf _ 0 remain = fillbuf 0 remain+ emptybuf ptr nLeft remain+ = do let nLeft' = fromInteger . toInteger $ nLeft+ ret <- win32WriteConsoleW handle ptr nLeft' written nullPtr+ nWritten <- peek written+ let nWritten' = fromInteger . toInteger $ nWritten+ if ret && (nWritten > 0)+ then emptybuf (ptr `plusPtr` (nWritten' * szWChar)) (nLeft - nWritten') remain+ else fail "WriteConsoleW failed.\n"++ in fillbuf 0 string++szWChar :: Int+szWChar = sizeOf (0 :: CWchar)++makeConsoleInfo :: DWORD -> Handle -> IO (Either ConsoleInfo Handle)+makeConsoleInfo nStdHandle fallback = do+ handle <- win32GetStdHandle nStdHandle+ handleToConsoleInfo handle fallback++handleToConsoleInfo :: HANDLE -> Handle -> IO (Either ConsoleInfo Handle)+handleToConsoleInfo handle fallback = do+ isConsole <- isAConsole handle+ let bufsize = 10000+ if not isConsole then return $ Right fallback+ else do buf <- mallocBytes (szWChar * bufsize)+ written <- malloc+ return . Left $ ConsoleInfo bufsize buf written handle++{-# NOINLINE stdoutConsoleInfo #-}+stdoutConsoleInfo :: Either ConsoleInfo Handle+stdoutConsoleInfo = unsafePerformIO $ makeConsoleInfo sTD_OUTPUT_HANDLE stdout++{-# NOINLINE stderrConsoleInfo #-}+stderrConsoleInfo :: Either ConsoleInfo Handle+stderrConsoleInfo = unsafePerformIO $ makeConsoleInfo sTD_ERROR_HANDLE stderr++conPutChar :: ConsoleInfo -> Char -> IO ()+conPutChar ci = writeConsole ci . replicate 1++conPutStr :: ConsoleInfo -> String -> IO ()+conPutStr = writeConsole++conPutStrLn :: ConsoleInfo -> String -> IO ()+conPutStrLn ci = writeConsole ci . (++ "\n")++putChar :: Char -> IO ()+putChar = (either conPutChar System.IO.hPutChar) stdoutConsoleInfo++putStr :: String -> IO ()+putStr = (either conPutStr System.IO.hPutStr) stdoutConsoleInfo++putStrLn :: String -> IO ()+putStrLn = (either conPutStrLn System.IO.hPutStrLn) stdoutConsoleInfo++print :: Show a => a -> IO ()+print = putStrLn . show++ePutChar :: Char -> IO ()+ePutChar = (either conPutChar System.IO.hPutChar) stderrConsoleInfo++ePutStr :: String -> IO ()+ePutStr = (either conPutStr System.IO.hPutStr) stderrConsoleInfo++ePutStrLn :: String -> IO ()+ePutStrLn = (either conPutStrLn System.IO.hPutStrLn) stderrConsoleInfo++ePrint :: Show a => a -> IO ()+ePrint = ePutStrLn . show++hPutChar :: Handle -> Char -> IO ()+hPutChar haskHandle c = withHandleToHANDLE haskHandle $ \ winHandle -> do+ eitherHandle <- handleToConsoleInfo winHandle haskHandle+ either conPutChar System.IO.hPutChar eitherHandle c++hPutStr :: Handle -> String -> IO ()+hPutStr haskHandle str = withHandleToHANDLE haskHandle $ \ winHandle -> do+ eitherHandle <- handleToConsoleInfo winHandle haskHandle+ either conPutStr System.IO.hPutStr eitherHandle str++hPutStrLn :: Handle -> String -> IO ()+hPutStrLn haskHandle str = withHandleToHANDLE haskHandle $ \ winHandle -> do+ eitherHandle <- handleToConsoleInfo winHandle haskHandle+ either conPutStrLn System.IO.hPutStrLn eitherHandle str++hPrint :: Show a => Handle -> a -> IO ()+hPrint = (. show) . hPutStrLn++trace :: String -> a -> a+trace string expr = unsafePerformIO $ do+ traceIO string+ return expr++traceIO :: String -> IO ()+traceIO = ePutStrLn++-------------------------------------------------------------------------------+-- All code that follows is taken from ansi-terminal by batterseapower, which+-- is licensed under BSD3++-- This essential function comes from the C runtime system. It is certainly provided by msvcrt, and also seems to be provided by the mingw C library - hurrah!+foreign import ccall unsafe "_get_osfhandle"+ cget_osfhandle :: CInt -> IO HANDLE++-- | This bit is all highly dubious. The problem is that we want to output ANSI to arbitrary Handles rather than forcing+-- people to use stdout. However, the Windows ANSI emulator needs a Windows HANDLE to work it's magic, so we need to be able+-- to extract one of those from the Haskell Handle.+--+-- This code accomplishes this, albeit at the cost of only being compatible with GHC.+withHandleToHANDLE :: Handle -> (HANDLE -> IO a) -> IO a+withHandleToHANDLE haskell_handle action =+ -- Create a stable pointer to the Handle. This prevents the garbage collector+ -- getting to it while we are doing horrible manipulations with it, and hence+ -- stops it being finalized (and closed).+ withStablePtr haskell_handle $ const $ do+ -- Grab the write handle variable from the Handle+ let write_handle_mvar = case haskell_handle of+ FileHandle _ handle_mvar -> handle_mvar+ DuplexHandle _ _ handle_mvar -> handle_mvar -- This is "write" MVar, we could also take the "read" one++ Just fd <- fmap (\(Handle__ { haDevice = dev }) -> fmap fdFD (cast dev)) $ readMVar write_handle_mvar++ -- Finally, turn that (C-land) FD into a HANDLE using msvcrt+ windows_handle <- cget_osfhandle fd++ -- Do what the user originally wanted+ action windows_handle++withStablePtr :: a -> (StablePtr a -> IO b) -> IO b+withStablePtr value = bracket (newStablePtr value) freeStablePtr