hpp: A Haskell pre-processor

[ bsd3, development, library, program ] [ Propose Tags ] [ Report a vulnerability ]

See the README for usage examples


[Skip to Readme]

Downloads

Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees

Candidates

  • No Candidates
Versions [RSS] 0.1.0.0, 0.3.0.0, 0.3.1.0, 0.4.0, 0.4.1, 0.5.0, 0.5.0.1, 0.5.1, 0.5.2, 0.6.0, 0.6.0.1, 0.6.1, 0.6.2, 0.6.3, 0.6.4, 0.6.5
Change log CHANGELOG.md
Dependencies base (>=4.8 && <5), bytestring, directory, filepath, ghc-prim, hpp, time (>=1.5), transformers (>=0.4), unordered-containers [details]
Tested with ghc ==8.4.4 || ==8.6.5 || ==8.8.4 || ==8.10.7 || ==9.0.2 || ==9.2.2
License BSD-3-Clause
Copyright (C) 2015-2016 Anthony Cowley
Author Anthony Cowley
Maintainer acowley@gmail.com
Category Development
Home page https://github.com/acowley/hpp
Source repo head: git clone http://github.com/acowley/hpp.git
Uploaded by AnthonyCowley at 2022-04-04T13:02:18Z
Distributions LTSHaskell:0.6.5, NixOS:0.6.5, Stackage:0.6.5
Reverse Dependencies 2 direct, 8 indirect [details]
Executables hpp
Downloads 11998 total (38 in the last 30 days)
Rating (no votes yet) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Docs available [build log]
Last success reported on 2022-04-04 [all 1 reports]

Readme for hpp-0.6.5

[back to package description]

The hpp Executable

hpp is a Haskell pre-processor that is also a C90-compatible pre-processor (with the addition of a --cpp flag). It is packaged as both a library and an executable.

To use as a Haskell preprocessor for resolving #ifdef conditionals and macro expansion, an invocation might look like,

hpp -DDEBUG Foo.hs 

To use as a C preprocessor, an invocation might look like,

hpp -DDEBUG --cpp foo.c 

To have GHC use hpp as the C pre-processor, add this line to the top of a Haskell source file that makes use of the CPP LANGUAGE pragma,

{-# OPTIONS_GHC -cpp -pgmPhpp #-} 

Or add this line to your .cabal file:

ghc-options: -pgmPhpp 

Note that you will need to ensure that the hpp executable is available in your build environment (e.g. you can add hpp as a build-depends in your .cabal file).

The hpp Library

The hpp executable is a command-line interface to the hpp library. While the hpp package has been designed to have minimal dependencies beyond what the GHC compiler itself uses, it does include a few small, framework-free unit tests that demonstrate basic usage as a library. In the testIf example, we preprocess the sourceIfdef input with a starting definition equivalent to #define FOO 1. In testArith1, we exercise basic integer arithmetic and comparison. The hppHelper function shows how to run your source input through the preprocessor: expand initialState (preproces mySource). If you want to support #includeing other files, you will use runHpp or streamHpp that operate in IO and support searching among a list of include paths.

{-# LANGUAGE OverloadedStrings #-} import Control.Monad.Trans.Except import Data.ByteString.Char8 (ByteString) import Data.Maybe (fromMaybe) import Data.Monoid ((<>)) import Hpp import System.Exit sourceIfdef :: [ByteString] sourceIfdef = [ "#ifdef FOO" , "x = 42" , "#else" , "x = 99" , "#endif" ] sourceArith1 :: ByteString -> [ByteString] sourceArith1 s = [ "#define x 3" , "#if 5 + x > " <> s , "yay" , "#else" , "boo" , "#endif" ] hppHelper :: HppState -> [ByteString] -> [ByteString] -> IO Bool hppHelper st src expected = case runExcept (expand st (preprocess src)) of Left e -> putStrLn ("Error running hpp: " ++ show e) >> return False Right (res, _) -> if hppOutput res == expected then return True else do putStr ("Expected "++show expected++", got") print (hppOutput res) return False testElse :: IO Bool testElse = hppHelper emptyHppState sourceIfdef ["x = 99\n","\n"] testIf :: IO Bool testIf = hppHelper (fromMaybe (error "Preprocessor definition did not parse") (addDefinition "FOO" "1" emptyHppState)) sourceIfdef ["x = 42\n","\n"] testArith1 :: IO Bool testArith1 = (&&) <$> hppHelper emptyHppState (sourceArith1 "7") ["yay\n","\n"] <*> hppHelper emptyHppState (sourceArith1 "8") ["boo\n","\n"] main :: IO () main = do results <- sequenceA [testElse, testIf, testArith1] if and results then exitWith ExitSuccess else exitWith (ExitFailure 1)