packages feed

free-theorems-0.2: src/ParserPrettyPrinterTests.hs



module ParserPrettyPrinterTests (tests) where



import Control.Monad (liftM, replicateM)
import Control.Monad.Writer (runWriter)
import Data.Generics (everywhere, mkT)
import Test.QuickCheck
import Text.PrettyPrint (vcat)

import Language.Haskell.FreeTheorems.Syntax
import qualified Language.Haskell.FreeTheorems.Parser.Haskell98 as Haskell98
import qualified Language.Haskell.FreeTheorems.Parser.Hsx as Hsx
import Language.Haskell.FreeTheorems.PrettyTypes

import Tests



-- | All test cases.

tests :: IO ()
tests = do
  doTest "Haskell98.parse . prettyPrint == id" prop_parsePrettyPrint_Haskell98
  doTest "Hsx.parse . prettyPrint == id" prop_parsePrettyPrint_Hsx



-- | Property: Parsing a pretty-printed declaration results in the same
--   declaration. This property is based on the Haskell98 parser.

prop_parsePrettyPrint_Haskell98 decls = 
  let (pds, es) = runWriter . Haskell98.parse 
                            . show . vcat . map prettyDeclaration $ ds
   in not (null ds) ==> (null es && not (null pds) && pds == ds)
  where
    types = decls :: ListOfDeclarations
    ds = map modifyTypeExpressions (getDeclarations decls)

    -- type expressions have to be modified because arbitrary type expressions
    -- may contain FixedTypeExpressions, explicit type abstractions and 
    -- type constructors applied to a wrong number of arguments
    modifyTypeExpressions = everywhere (mkT adjustType)

    adjustType t = case t of
      TypeCon ConUnit _       -> TypeCon ConUnit []
      TypeCon ConList []      -> TypeCon ConList [TypeCon ConUnit []]
      TypeCon ConList (x:_)   -> TypeCon ConList [x]
      TypeCon (ConTuple _) [] -> TypeCon ConUnit []
      TypeCon (ConTuple n) xs -> if length xs == 1
                                   then TypeCon ConList xs
                                   else TypeCon (ConTuple (length xs)) xs
      TypeCon ConInt _        -> TypeCon ConInt []
      TypeCon ConInteger _    -> TypeCon ConInteger []
      TypeCon ConFloat _      -> TypeCon ConFloat []
      TypeCon ConDouble _     -> TypeCon ConDouble []
      TypeCon ConChar _       -> TypeCon ConChar []
      TypeAbs _ _ t'          -> t'
      TypeExp (TF i)          -> TypeVar (TV i)
      otherwise               -> t



-- | Property: Parsing a pretty-printed declaration results in the same
--   declaration. This property is based on the Hsx parser.

prop_parsePrettyPrint_Hsx decls = 
  let (pds, es) = runWriter . Hsx.parse 
                            . show . vcat . map prettyDeclaration $ ds
   in not (null ds) ==> (null es && not (null pds) && pds == ds)
  where
    types = decls :: ListOfDeclarations
    ds = map modifyTypeExpressions (getDeclarations decls)

    -- type expressions have to be modified because arbitrary type expressions
    -- may contain FixedTypeExpressions, explicit type abstractions and 
    -- type constructors applied to a wrong number of arguments
    modifyTypeExpressions = everywhere (mkT adjustType)

    adjustType t = case t of
      TypeCon ConUnit _       -> TypeCon ConUnit []
      TypeCon ConList []      -> TypeCon ConList [TypeCon ConUnit []]
      TypeCon ConList (x:_)   -> TypeCon ConList [x]
      TypeCon (ConTuple _) [] -> TypeCon ConUnit []
      TypeCon (ConTuple n) xs -> if length xs == 1
                                   then TypeCon ConList xs
                                   else TypeCon (ConTuple (length xs)) xs
      TypeCon ConInt _        -> TypeCon ConInt []
      TypeCon ConInteger _    -> TypeCon ConInteger []
      TypeCon ConFloat _      -> TypeCon ConFloat []
      TypeCon ConDouble _     -> TypeCon ConDouble []
      TypeCon ConChar _       -> TypeCon ConChar []
      TypeAbs _ _ t'          -> t'
      TypeExp (TF i)          -> TypeVar (TV i)
      otherwise               -> t