-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | A Haskell pre-processor -- -- See the README for usage examples @package hpp @version 0.5.0 -- | HELPERS for working with Strings module Hpp.String -- | Stringification puts double quotes around a string and backslashes -- before existing double quote characters and backslash characters. stringify :: String -> String -- | Remove double quote characters from the ends of a string. unquote :: String -> String -- | Trim trailing spaces from a String trimSpaces :: String -> String -- | Similar to the function of the same name in the text package. -- -- breakOn needles haystack finds the first instance of an -- element of needles in haystack. The first component -- of the result is the needle tag, the second component is the prefix of -- haystack before the matched needle, the third component is -- the remainder of the haystack after the needle.. breakOn :: [(String, t)] -> String -> Maybe (t, String, String) -- | Used to make switching to the text package easier. cons :: a -> [a] -> [a] module Hpp.StringSig data CharOrSub s CharMatch :: !s -> !s -> CharOrSub s SubMatch :: !s -> !s -> CharOrSub s NoMatch :: CharOrSub s class (IsString s, Monoid s) => Stringy s -- | Stringification puts double quotes around a string and backslashes -- before existing double quote characters and backslash characters. stringify :: Stringy s => s -> s -- | Remove double quote characters from the ends of a string. unquote :: Stringy s => s -> s -- | Trim trailing spaces from a String trimSpaces :: Stringy s => s -> s -- | Similar to the function of the same name in the text package. -- -- breakOn needles haystack finds the first instance of an -- element of needles in haystack. The first component -- of the result is the needle tag, the second component is the prefix of -- haystack before the matched needle, the third component is -- the remainder of the haystack after the needle.. breakOn :: Stringy s => [(s, t)] -> s -> Maybe (t, s, s) -- | A special case of breakOn in which we are looking for either a -- special character or a particular substring. breakCharOrSub :: Stringy s => Char -> s -> s -> CharOrSub s cons :: Stringy s => Char -> s -> s uncons :: Stringy s => s -> Maybe (Char, s) snoc :: Stringy s => s -> Char -> s unsnoc :: Stringy s => s -> Maybe (s, Char) sdrop :: Stringy s => Int -> s -> s sbreak :: Stringy s => (Char -> Maybe t) -> s -> Maybe (t, s, s) sall :: Stringy s => (Char -> Bool) -> s -> Bool sIsPrefixOf :: Stringy s => s -> s -> Bool isEmpty :: Stringy s => s -> Bool readLines :: Stringy s => FilePath -> IO [s] putStringy :: Stringy s => Handle -> s -> IO () toChars :: Stringy s => s -> [Char] -- | An opportunity to copy a string to its own storage to help with GC copy :: Stringy s => s -> s boolJust :: Bool -> Maybe () predicateJust :: (a -> Bool) -> a -> Maybe a sdropWhile :: Stringy s => (Char -> Bool) -> s -> s infixr 5 :. instance Hpp.StringSig.Stringy GHC.Base.String instance Hpp.StringSig.Stringy Data.ByteString.Internal.ByteString -- | Tokenization breaks a String into pieces of whitespace, -- constants, symbols, and identifiers. module Hpp.Tokens -- | Tokenization is words except the white space is tagged rather -- than discarded. data Token s -- | Identifiers, symbols, and constants Important :: s -> Token s -- | White space, etc. Other :: s -> Token s -- | Extract the contents of a Token. detok :: Token s -> s -- | True if the given Token is Important; -- False otherwise. isImportant :: Token s -> Bool -- | True if the given Token is not Important; -- False otherwise. notImportant :: Token s -> Bool -- | Return the contents of only Important (non-space) tokens. importants :: [Token s] -> [s] -- | Trim Other Tokens from both ends of a list of -- Tokens. trimUnimportant :: [Token s] -> [Token s] -- | Collapse a sequence of Tokens back into a String. -- detokenize . tokenize == id. detokenize :: Monoid s => [Token s] -> s -- | Break an input String into a sequence of Tokens. -- Warning: This may not exactly correspond to your target language's -- definition of a valid identifier! tokenize :: Stringy s => s -> [Token s] -- | Is a Token a newline character? newLine :: (Eq s, IsString s) => Token s -> Bool skipLiteral :: Stringy s => s -> (s, s) instance GHC.Show.Show s => GHC.Show.Show (Hpp.Tokens.Token s) instance GHC.Classes.Ord s => GHC.Classes.Ord (Hpp.Tokens.Token s) instance GHC.Classes.Eq s => GHC.Classes.Eq (Hpp.Tokens.Token s) instance GHC.Base.Functor Hpp.Tokens.Token -- | An expression language corresponding to the subset of C syntax that -- may be used in preprocessor conditional directives. See -- https://gcc.gnu.org/onlinedocs/cpp/If.html module Hpp.Expr -- | Expressions are literal values, binary operators applied to two -- sub-expressions, or unary operators applied to a single -- sub-expression. data Expr ELit :: Lit -> Expr EBinOp :: BinOp -> Expr -> Expr -> Expr EUnaryOp :: UnaryOp -> Expr -> Expr -- | Read a literal integer. These may be decimal, octal, or hexadecimal, -- and may have a case-insensitive suffix of u, l, or -- ul. readLitInt :: String -> Maybe CppInt -- | Try to read an Expr from a sequence of Tokens. parseExpr :: [Token String] -> Maybe Expr -- | Pretty-print an Expr to something semantically equivalent to -- the original C syntax (some parentheses may be added). renderExpr :: Expr -> String -- | All Exprs can be evaluated to an Int. evalExpr :: Expr -> Int instance GHC.Show.Show Hpp.Expr.Expr instance GHC.Classes.Ord Hpp.Expr.Expr instance GHC.Classes.Eq Hpp.Expr.Expr instance GHC.Show.Show Hpp.Expr.FunLike instance GHC.Classes.Ord Hpp.Expr.FunLike instance GHC.Classes.Eq Hpp.Expr.FunLike instance GHC.Show.Show Hpp.Expr.Assoc instance GHC.Classes.Ord Hpp.Expr.Assoc instance GHC.Classes.Eq Hpp.Expr.Assoc instance GHC.Show.Show Hpp.Expr.Parsed instance GHC.Classes.Ord Hpp.Expr.Parsed instance GHC.Classes.Eq Hpp.Expr.Parsed instance GHC.Show.Show Hpp.Expr.Lit instance GHC.Classes.Ord Hpp.Expr.Lit instance GHC.Classes.Eq Hpp.Expr.Lit instance GHC.Show.Show Hpp.Expr.UnaryOp instance GHC.Classes.Ord Hpp.Expr.UnaryOp instance GHC.Classes.Eq Hpp.Expr.UnaryOp instance GHC.Show.Show Hpp.Expr.BinOp instance GHC.Classes.Ord Hpp.Expr.BinOp instance GHC.Classes.Eq Hpp.Expr.BinOp instance GHC.Classes.Eq Hpp.Expr.CppInt instance GHC.Classes.Ord Hpp.Expr.CppInt instance GHC.Num.Num Hpp.Expr.CppInt -- | A name binding context, or environment. module Hpp.Env emptyEnv :: Trie a insertPair :: (ByteString, a) -> Trie a -> Trie a deleteKey :: ByteString -> Trie a -> Trie a lookupKey :: ByteString -> Trie a -> Maybe a -- | Preprocessor Configuration module Hpp.Config -- | A String representing a time. newtype TimeString TimeString :: String -> TimeString [getTimeString] :: TimeString -> String -- | A String representing a date. newtype DateString DateString :: String -> DateString [getDateString] :: DateString -> String -- | Pre-processor configuration parameterized over a functor. This is used -- to normalize partial configurations, ConfigF Maybe, and -- configurations suitable for the pre-processor logic, ConfigF -- Identity. Specifically, the source file name of the file being -- processed must be set. data ConfigF f Config :: f FilePath -> f [FilePath] -> f Bool -> f Bool -> f Bool -> f Bool -> f DateString -> f TimeString -> ConfigF f -- | Name of the file being preprocessed. Hpp will update this as new files -- are included. The user must set it manually for the starting input -- file. [curFileNameF] :: ConfigF f -> f FilePath -- | Paths to be searched for included files. [includePathsF] :: ConfigF f -> f [FilePath] -- | A backslash as the last character of a line causes the next line to be -- appended to the current one eliding the newline character present in -- the source input. [spliceLongLinesF] :: ConfigF f -> f Bool -- | Erase line comments (starting with //) and block comments -- (delimited by /* and */). [eraseCCommentsF] :: ConfigF f -> f Bool -- | Do not emit #line directives. [inhibitLinemarkersF] :: ConfigF f -> f Bool -- | Replace trigraph sequences (each of which starts with two consecutive -- question marks ("??") with the characters they encode. [replaceTrigraphsF] :: ConfigF f -> f Bool -- | Format string for __DATE__. [prepDateF] :: ConfigF f -> f DateString -- | Format string for __TIME__. [prepTimeF] :: ConfigF f -> f TimeString -- | A fully-populated configuration for the pre-processor. type Config = ConfigF Identity -- | Ensure that required configuration fields are supplied. realizeConfig :: ConfigF Maybe -> Maybe Config -- | Extract the current file name from a configuration. curFileName :: Config -> FilePath -- | Extract the include paths name from a configuration. includePaths :: Config -> [FilePath] -- | Determine if continued long lines should be spliced. spliceLongLines :: Config -> Bool -- | Determine if C-style comments should be erased. eraseCComments :: Config -> Bool -- | Determine if generation of linemarkers should be inhibited. inhibitLinemarkers :: Config -> Bool -- | Determine if trigraph sequences should be replaced. replaceTrigraphs :: Config -> Bool -- | The date the pre-processor was run on. prepDate :: Config -> DateString -- | The time of the active pre-processor invocation. prepTime :: Config -> TimeString -- | A default configuration with no current file name set. Note that long -- line splicing is enabled, C++-style comments are erased, #line markers -- are inhibited, and trigraph replacement is disabled. defaultConfigF :: ConfigF Maybe -- | Format a date according to the C spec. formatPrepDate :: UTCTime -> DateString -- | Format a time according to the C spec. formatPrepTime :: UTCTime -> TimeString -- | A default preprocessor configuration with date and time stamps taken -- from the current system time. defaultConfigFNow :: IO (ConfigF Maybe) instance GHC.Show.Show Hpp.Config.DateString instance GHC.Classes.Ord Hpp.Config.DateString instance GHC.Classes.Eq Hpp.Config.DateString instance GHC.Show.Show Hpp.Config.TimeString instance GHC.Classes.Ord Hpp.Config.TimeString instance GHC.Classes.Eq Hpp.Config.TimeString -- | The core types involved used by the pre-processor. module Hpp.Types -- | Line numbers are represented as Ints type LineNum = Int -- | A macro binding environment. type Env = Trie Macro type String = ByteString type TOKEN = Token ByteString -- | Error conditions we may encounter. data Error UnterminatedBranch :: Error BadMacroDefinition :: LineNum -> Error BadIfPredicate :: Error BadLineArgument :: LineNum -> String -> Error IncludeDoesNotExist :: LineNum -> FilePath -> Error FailedInclude :: LineNum -> FilePath -> Error UserError :: LineNum -> String -> Error UnknownCommand :: LineNum -> String -> Error TooFewArgumentsToMacro :: LineNum -> String -> Error BadMacroArguments :: LineNum -> String -> Error NoInputFile :: Error BadCommandLine :: String -> Error RanOutOfInput :: Error -- | Hpp can raise various parsing errors. class HasError m throwError :: HasError m => Error -> m a -- | Base functor for a free monad transformer data FreeF f a r PureF :: a -> FreeF f a r FreeF :: (f r) -> FreeF f a r -- | Dynamic state of the preprocessor engine. data HppState HppState :: Config -> LineNum -> Env -> HppState [hppConfig] :: HppState -> Config [hppLineNum] :: HppState -> LineNum [hppEnv] :: HppState -> Env -- | A free monad construction to strictly delimit what capabilities we -- need to perform pre-processing. data HppF t r ReadFile :: Int -> FilePath -> (t -> r) -> HppF t r ReadNext :: Int -> FilePath -> (t -> r) -> HppF t r WriteOutput :: t -> r -> HppF t r -- | A free monad transformer specialized to HppF as the base functor. newtype HppT t m a HppT :: m (FreeF (HppF t) a (HppT t m a)) -> HppT t m a [runHppT] :: HppT t m a -> m (FreeF (HppF t) a (HppT t m a)) writeOutput :: Monad m => t -> HppT t m () -- | An interpreter capability to modify dynamic state. class HasHppState m getState :: HasHppState m => m HppState setState :: HasHppState m => HppState -> m () -- | An interpreter capability of threading a binding environment. class HasEnv m getEnv :: HasEnv m => m Env setEnv :: HasEnv m => Env -> m () -- | Macro expansion involves treating tokens differently if they appear in -- the original source or as the result of a previous macro expansion. -- This distinction is used to prevent divergence by masking out -- definitions that could be used recursively. -- -- Things are made somewhat more complicated than one might expect due to -- the fact that the scope of this masking is not structurally -- recursive. A object-like macro can expand into a fragment of a macro -- function application, one of whose arguments is a token matching the -- original object-like macro. That argument should not be -- expanded. data Scan Unmask :: String -> Scan Mask :: String -> Scan Scan :: (Token String) -> Scan Rescan :: (Token String) -> Scan -- | There are object-like macros and function-like macros. data Macro -- | An object-like macro is replaced with its definition Object :: [Token String] -> Macro -- | A function-like macro of some arity taks macro-expanded and raw -- versions of its arguments, then substitutes them into a body producing -- a new set of tokens. Function :: Int -> ([([Scan], String)] -> [Scan]) -> Macro -- | Looks up a Macro in the current environment. If the -- Macro is found, the environment is juggled so that subsequent -- lookups of the same Macro may evaluate more quickly. lookupMacro :: (HasEnv m, Monad m) => String -> m (Maybe Macro) type Lens s a = forall f. Functor f => (a -> f a) -> s -> f s setL :: Lens s a -> a -> s -> s getL :: Lens s a -> s -> a over :: Lens s a -> (a -> a) -> s -> s emptyHppState :: Config -> HppState config :: Lens HppState Config lineNum :: Lens HppState LineNum env :: Lens HppState Env use :: (HasHppState m, Functor m) => Lens HppState a -> m a (.=) :: (HasHppState m, Monad m) => Lens HppState a -> a -> m () infix 4 .= (%=) :: (HasHppState m, Monad m) => Lens HppState a -> (a -> a) -> m () infix 4 %= instance GHC.Show.Show Hpp.Types.Scan instance GHC.Classes.Eq Hpp.Types.Scan instance GHC.Show.Show Hpp.Types.Error instance GHC.Classes.Ord Hpp.Types.Error instance GHC.Classes.Eq Hpp.Types.Error instance GHC.Exception.Exception Hpp.Types.Error instance GHC.Base.Monad m => Hpp.Types.HasError (Control.Monad.Trans.Except.ExceptT Hpp.Types.Error m) instance (GHC.Base.Monad m, Hpp.Types.HasHppState m) => Hpp.Types.HasHppState (Control.Monad.Trans.Except.ExceptT e m) instance (GHC.Base.Monad m, Hpp.Types.HasError m) => Hpp.Types.HasError (Control.Monad.Trans.State.Strict.StateT s m) instance (GHC.Base.Monad m, Hpp.Types.HasError m) => Hpp.Types.HasError (Hpp.Types.HppT t m) instance GHC.Base.Functor f => GHC.Base.Functor (Hpp.Types.FreeF f a) instance GHC.Base.Functor (Hpp.Types.HppF t) instance GHC.Base.Functor m => GHC.Base.Functor (Hpp.Types.HppT t m) instance GHC.Base.Monad m => GHC.Base.Applicative (Hpp.Types.HppT t m) instance GHC.Base.Monad m => GHC.Base.Monad (Hpp.Types.HppT t m) instance Control.Monad.Trans.Class.MonadTrans (Hpp.Types.HppT t) instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Hpp.Types.HppT t m) instance GHC.Base.Monad m => Hpp.Types.HasHppState (Control.Monad.Trans.State.Strict.StateT Hpp.Types.HppState m) instance (GHC.Base.Monad m, Hpp.Types.HasHppState m) => Hpp.Types.HasHppState (Control.Monad.Trans.State.Strict.StateT s m) instance (GHC.Base.Monad m, Hpp.Types.HasHppState m) => Hpp.Types.HasHppState (Hpp.Types.HppT t m) instance (GHC.Base.Monad m, Hpp.Types.HasHppState m) => Hpp.Types.HasEnv (Hpp.Types.HppT t m) instance GHC.Base.Monad m => Hpp.Types.HasEnv (Control.Monad.Trans.State.Strict.StateT Hpp.Types.HppState m) instance GHC.Base.Monad m => Hpp.Types.HasEnv (Control.Monad.Trans.State.Strict.StateT Hpp.Types.Env m) instance (Hpp.Types.HasEnv m, GHC.Base.Monad m) => Hpp.Types.HasEnv (Control.Monad.Trans.Except.ExceptT e m) instance GHC.Show.Show Hpp.Types.Macro -- | Parsers over streaming input. module Hpp.Parser type Parser m i = ParserT m (RopeM m [i]) i -- | A Parser is a bit of state carrying a source of input. type ParserT m src i = StateT (Headspring m src i, src) m -- | Run a Parser with a given input stream. parse :: Monad m => Parser m i o -> [i] -> m (o, RopeM m [i]) evalParse :: Monad m => Parser m i o -> [i] -> m o await :: Monad m => ParserT m src i (Maybe i) -- | awaitP that throws an error with the given message if no more -- input is available. This may be used to locate where in a processing -- pipeline input was unexpectedly exhausted. awaitJust :: (Monad m, HasError m) => String -> ParserT m src i i -- | Push a value back into a parser's source. replace :: (Monad m) => i -> ParserT m src i () -- | Discard all values until one fails to satisfy a predicate. At that -- point, the failing value is replaced, and the -- droppingWhile stream stops. droppingWhile :: (Monad m) => (i -> Bool) -> ParserT m src i () -- | Push a stream of values back into a parser's source. precede :: Monad m => [i] -> ParserT m src i () -- | Echo all values until one fails to satisfy a predicate. At that point, -- the failing value is replaced, and the takingWhile -- stream stops. takingWhile :: (Monad m) => (i -> Bool) -> ParserT m src i [i] onChunks :: Monad m => ParserT m (RopeM m [i]) [i] r -> Parser m i r onElements :: Monad m => ParserT m (RopeM m [[i]]) i r -> Parser m [i] r onInputSegment :: Monad m => (src -> src) -> ParserT m (RopeM m src) i () insertInputSegment :: Monad m => src -> m () -> ParserT m (RopeM m src) i () onIsomorphism :: forall m a b src r. Monad m => (a -> b) -> (b -> Maybe a) -> ParserT m ([b], src) b r -> ParserT m src a r runParser :: Monad m => Parser m i o -> RopeM m [i] -> m (o, RopeM m [i]) -- | Line expansion is the core input token processing logic. Object-like -- macros are substituted, and function-like macro applications are -- expanded. module Hpp.Expansion -- | Expand all macros to the end of the current line or until all -- in-progress macro invocations are complete, whichever comes last. expandLine :: (HasError m, Monad m, HasEnv m) => Config -> Int -> Parser m [TOKEN] [TOKEN] -- | Mid-level interface to the pre-processor. module Hpp.RunHpp -- | Parse the definition of an object-like or function macro. parseDefinition :: [TOKEN] -> Maybe (String, Macro) -- | Run a stream of lines through the preprocessor. preprocess :: (Monad m, HppCaps m) => [String] -> HppT [String] (Parser m [TOKEN]) () runHpp :: forall m a src. (MonadIO m, HasHppState m) => (FilePath -> m src) -> (src -> m ()) -> HppT src m a -> m (Either (FilePath, Error) (HppResult a)) -- | General hpp runner against input source file lines. Output lines are -- fed to the caller-supplied sink function. Any errors encountered are -- thrown with error. hppIOSink :: Config -> Env -> ([String] -> IO ()) -> [String] -> IO [FilePath] -- | The dynamic capabilities offered by HPP type HppCaps t = (HasError t, HasHppState t, HasEnv t) -- | hpp runner that returns output lines. hppIO :: Config -> Env -> FilePath -> [String] -> IO (Either Error ([FilePath], [String])) data HppResult a HppResult :: [FilePath] -> a -> HppResult a [hppFilesRead] :: HppResult a -> [FilePath] [hppResult] :: HppResult a -> a -- | Front-end interface to the pre-processor. module Hpp -- | Lower level parsing of macro definitions. Will typically be used with -- insertPair for manual construction of a Env binding -- environment. parseDefinition :: ByteString -> ByteString -> Maybe (ByteString, Macro) -- | Preprocess lines of input. preprocess :: Monad m => [ByteString] -> HppT m () -- | Dynamic state of the preprocessor engine. data HppState -- | An HppState containing no macro definitions, and default values -- for the starting configuration: the name of the current file is -- "NoFile", there are no paths to be searched for included -- files, etc. See Config for more information on available -- configuration. emptyHppState :: HppState -- | Create a HppState with the given Config and Env. initHppState :: Config -> Env -> HppState -- | addDefinition name expression adds a binding of name -- to expression in the preprocessor’s internal state. addDefinition :: ByteString -> ByteString -> HppState -> Maybe HppState -- | Run a preprocessor action with some initial state. Returns the result -- of preprocessing as well as an updated preprocessor state -- representation. runHpp :: MonadIO m => HppState -> HppT m a -> ExceptT Error m (HppOutput, HppState) -- | streamHpp state sink action runs a preprocessor -- action with some initial state. Output is streamed -- to the caller-provided output sink as it is generated. The -- list of files read during preprocessing is returned along with an -- updated preprocessor state representation. streamHpp :: MonadIO m => HppState -> ([ByteString] -> m ()) -> HppT m a -> ExceptT Error m ([FilePath], HppState) -- | The type of preprocessor actions. Created with preprocess and -- executed with runHpp or streamHpp. data HppT m a -- | The result of running hpp data HppOutput HppOutput :: [FilePath] -> [ByteString] -> HppOutput [hppFilesRead] :: HppOutput -> [FilePath] [hppOutput] :: HppOutput -> [ByteString] instance GHC.Base.Monad m => GHC.Base.Monad (Hpp.HppT m) instance GHC.Base.Monad m => GHC.Base.Applicative (Hpp.HppT m) instance GHC.Base.Functor m => GHC.Base.Functor (Hpp.HppT m) instance Control.Monad.Trans.Class.MonadTrans Hpp.HppT -- | A front-end to run Hpp with textual arguments as from a command line -- invocation. module Hpp.CmdLine -- | Run Hpp with the given commandline arguments. runWithArgs :: [String] -> IO ()