BNFC-2.9.1: A compiler front-end generator.
Safe HaskellSafe-Inferred



Backend base module.

Defines the type of the backend and some useful functions.



type MkFiles a = WriterT [(FilePath, String)] IO a Source #

Define the type of the backend functions For more purity, instead of having each backend writing the generated files to disk, they return a list of pairs containing the (relative) file path and the file content. This allow for 1) easier testing, 2) implement common options like changing the output dir or providing a diff instead of overwritting the files on a highter level and 3) more purity.

The writer monad provides a more convenient API to generate the list. Note that we still use the IO monad for now because some backends insist on printing stuff to the screen while generating the files.

execBackend :: MkFiles () -> IO [(FilePath, String)] Source #

Named after execWriter, this function execute the given backend and returns the generated file paths and contents.

mkfile :: FileContent c => FilePath -> c -> MkFiles () Source #

A specialized version of tell that adds a file and its content to the list of generated files.

liftIO :: MonadIO m => IO a -> m a #

Lift a computation from the IO monad. This allows us to run IO computations in any monadic stack, so long as it supports these kinds of operations (i.e. IO is the base monad for the stack).


import Control.Monad.Trans.State -- from the "transformers" library

printState :: Show s => StateT s IO ()
printState = do
  state <- get
  liftIO $ print state

Had we omitted liftIO, we would have ended up with this error:

• Couldn't match type ‘IO’ with ‘StateT s IO’
 Expected type: StateT s IO ()
   Actual type: IO ()

The important part here is the mismatch between StateT s IO () and IO ().

Luckily, we know of a function that takes an IO a and returns an (m a): liftIO, enabling us to run the program and see the expected results:

> evalStateT printState "hello"

> evalStateT printState 3

writeFiles :: FilePath -> MkFiles () -> IO () Source #

Write a set of files to disk. the first argument is the root directory inside which all the generated files will be written. This root directory and sub-directories will be created as needed (ex: if the files contains a a/b/file.txt, writeFiles will create the directories $ROOT/a and $ROOT/a/b)