Commit 445bbde2 authored by Michael Hanus 's avatar Michael Hanus

Adds options --time and --noiotest

parent d0df9d7a
*~
cdoc/
docs/*.aux
docs/*.pdf
docs/*.toc
docs/*.log
docs/*.out
docs/*.synctex.gz
.curry
.cpm
src/CurryCheckConfig.curry
src/CC/Config.curry
......@@ -80,6 +80,12 @@ S.~Antoy and M.~Hanus.
Aspects of Declarative Languages (PADL 2012)}, pages 33--47. Springer LNCS
7149, 2012.
\bibitem{AntoyHanus18FLOPS}
S.~Antoy and M.~Hanus.
\newblock Equivalence checking of non-deterministic operations.
\newblock In {\em Proc. of the 14th International Symposium on
Functional and Logic Programming (FLOPS 2018)}, to appear in Springer LNCS.
\bibitem{ChristiansenFischer08FLOPS}
J.~Christiansen and S.~Fischer.
\newblock {EasyCheck} - test data for free.
......
......@@ -550,11 +550,12 @@ sortSatisfiesSpecification x = sort x <~> sort'spec x
\subsection{Checking Equivalence of Operations}
CurryCheck supports also equivalence checks for operations.
CurryCheck supports also equivalence tests for operations.
Two operations are considered as \emph{equivalent} if they
can be replaced by each other in any possible context
without changing the computed values (see \cite{AntoyHanus12PADL}
for a precise definition).
without changing the computed values (this is also called
\emph{contextual equivalence} and precisely defined in
\cite{AntoyHanus12PADL} for functional logic programs).
For instance, the Boolean operations
\begin{curry}
f1 :: Bool -> Bool f2 :: Bool -> Bool
......@@ -575,12 +576,16 @@ property combinator \code{<=>}:
f1_equiv_f2 = f1 <=> f2
g1_equiv_g2 = g1 <=> g2
\end{curry}
The left and right argument of this combinator must be a defined operation
or a defined operation with a type annotation in order to specify
the argument types used for checking this property.
CurryCheck transforms such properties into properties
where both operations are compared w.r.t.\ all partial
values and partial results.
The details are described in an upcoming paper.
The details are described in \cite{AntoyHanus18FLOPS}.
It should be noted that CurryCheck can also check
It should be noted that CurryCheck can test
the equivalence of non-terminating operations provided
that they are \emph{productive}, i.e., always generate
(outermost) constructors after a finite number of steps
......@@ -594,13 +599,15 @@ ints2 n = n : ints2 (n+2)
-- This property will be falsified by CurryCheck:
ints1_equiv_ints2 = ints1 <=> ints2
\end{curry}
This is done by guessing depth-bounds and comparing the results
of both operations up to this depth-bound.
This is done by iteratively guessing depth-bounds, computing both operations
up to these depth-bounds, and comparing the computed results.
Since this might be a long process, CurryCheck supports
a faster comparison of operations when it is known
that they are terminating.
If the name of a test contains the suffix \code{'TERMINATE},
then CurryCheck does not iterate over depth-bounds
CurryCheck assumes that the operations to be tested are terminating,
i.e., they always yields a result when applied to ground terms.
In this case, CurryCheck does not iterate over depth-bounds
but evaluates operations completely.
For instance, consider the following definition of
permutation sort (the operations \code{perm} and \code{sorted}
......
......@@ -13,7 +13,7 @@
"pakcs": ">= 1.14.0, < 2.0.0",
"kics2": ">= 0.5.0, < 2.0.0"
},
"configModule": "CurryCheckConfig",
"configModule": "CC.Config",
"executable": {
"name": "curry-check",
"main": "CurryCheck"
......
------------------------------------------------------------------------------
--- Definition and processing of options for CurryCheck
------------------------------------------------------------------------------
module CC.Options where
import Char ( toUpper )
import GetOpt
import IO
import List ( isPrefixOf )
import ReadNumeric ( readNat )
------------------------------------------------------------------------------
-- Representation of command line options.
data Options = Options
{ optHelp :: Bool
, optVerb :: Int
, optKeep :: Bool
, optMaxTest :: Int
, optMaxFail :: Int
, optDefType :: String
, optSource :: Bool
, optIOTest :: Bool
, optProp :: Bool
, optSpec :: Bool
, optDet :: Bool
, optProof :: Bool
, optEquiv :: EquivOption
, optTime :: Bool
, optColor :: Bool
, optMainProg :: String
}
-- Default command line options.
defaultOptions :: Options
defaultOptions = Options
{ optHelp = False
, optVerb = 1
, optKeep = False
, optMaxTest = 0
, optMaxFail = 0
, optDefType = "Ordering"
, optSource = True
, optIOTest = True
, optProp = True
, optSpec = True
, optDet = True
, optProof = True
, optEquiv = Manual
, optTime = False
, optColor = True
, optMainProg = ""
}
--- Options for equivalence tests.
data EquivOption = Safe | Autoselect | Manual
-- Definition of actual command line options.
options :: [OptDescr (Options -> Options)]
options =
[ Option "h?" ["help"] (NoArg (\opts -> opts { optHelp = True }))
"print help and exit"
, Option "q" ["quiet"] (NoArg (\opts -> opts { optVerb = 0 }))
"run quietly (no output, only exit code)"
, Option "v" ["verbosity"]
(OptArg (maybe (checkVerb 3) (safeReadNat checkVerb)) "<n>")
"verbosity level:\n0: quiet (same as `-q')\n1: show test names (default)\n2: show more information about test generation\n3: show test data (same as `-v')\n4: show also some debug information"
, Option "k" ["keep"] (NoArg (\opts -> opts { optKeep = True }))
"keep temporarily generated program files"
, Option "m" ["maxtests"]
(ReqArg (safeReadNat (\n opts -> opts { optMaxTest = n })) "<n>")
"maximal number of tests (default: 100)"
, Option "f" ["maxfails"]
(ReqArg (safeReadNat (\n opts -> opts { optMaxFail = n })) "<n>")
"maximal number of condition failures\n(default: 10000)"
, Option "d" ["deftype"]
(ReqArg checkDefType "<t>")
"type for defaulting polymorphic tests:\nBool | Int | Char | Ordering (default)"
--, Option "e" ["equivalence"]
-- (ReqArg checkEquivOption "<e>")
-- "option for equivalence tests:\nsafe | autoselect | manual (default)"
, Option "t" ["time"] (NoArg (\opts -> opts { optTime = True }))
"show run time for executing each property test"
, Option "" ["nosource"]
(NoArg (\opts -> opts { optSource = False }))
"do not perform source code checks"
, Option "" ["noiotest"]
(NoArg (\opts -> opts { optIOTest = False }))
"do not test I/O properties"
, Option "" ["noprop"]
(NoArg (\opts -> opts { optProp = False }))
"do not perform property tests"
, Option "" ["nospec"]
(NoArg (\opts -> opts { optSpec = False }))
"do not perform specification/postcondition tests"
, Option "" ["nodet"]
(NoArg (\opts -> opts { optDet = False }))
"do not perform determinism tests"
, Option "" ["noproof"]
(NoArg (\opts -> opts { optProof = False }))
"do not consider proofs to simplify properties"
, Option "" ["nocolor"]
(NoArg (\opts -> opts { optColor = False }))
"do not use colors when showing tests"
, Option "" ["mainprog"]
(ReqArg (\s opts -> opts { optMainProg = s }) "<prog>")
"name of generated main program\n(default: TEST<pid>.curry)"
]
where
safeReadNat opttrans s opts =
let numError = error "Illegal number argument (try `-h' for help)" in
maybe numError
(\ (n,rs) -> if null rs then opttrans n opts else numError)
(readNat s)
checkVerb n opts = if n>=0 && n<5
then opts { optVerb = n }
else error "Illegal verbosity level (try `-h' for help)"
checkDefType s opts = if s `elem` ["Bool","Int","Char","Ordering"]
then opts { optDefType = s }
else error "Illegal default type (try `-h' for help)"
checkEquivOption s opts
| ls `isPrefixOf` "SAFE" = opts { optEquiv = Safe }
| ls `isPrefixOf` "AUTOSELECT" = opts { optEquiv = Autoselect }
| ls `isPrefixOf` "MANUAL" = opts { optEquiv = Manual }
| otherwise = error "Illegal equivalence option (try `-h' for help)"
where ls = map toUpper s
--- Further option processing, e.g., setting coloring mode.
processOpts :: Options -> IO Options
processOpts opts = do
isterm <- hIsTerminalDevice stdout
return $ if isterm then opts else opts { optColor = False}
isQuiet :: Options -> Bool
isQuiet opts = optVerb opts == 0
--- Print second argument if verbosity level is not quiet:
putStrIfNormal :: Options -> String -> IO ()
putStrIfNormal opts s = unless (isQuiet opts) (putStr s >> hFlush stdout)
--- Print second argument if verbosity level > 1:
putStrIfDetails :: Options -> String -> IO ()
putStrIfDetails opts s = when (optVerb opts > 1) (putStr s >> hFlush stdout)
--- Print second argument if verbosity level > 3:
putStrLnIfDebug :: Options -> String -> IO ()
putStrLnIfDebug opts s = when (optVerb opts > 3) (putStrLn s >> hFlush stdout)
--- use some coloring (from library AnsiCodes) if color option is on:
withColor :: Options -> (String -> String) -> String -> String
withColor opts coloring = if optColor opts then coloring else id
------------------------------------------------------------------------------
......@@ -14,172 +14,53 @@
--- (together with possible preconditions).
---
--- @author Michael Hanus, Jan-Patrick Baye
--- @version December 2017
--- @version June 2018
-------------------------------------------------------------------------
import AnsiCodes
import Char ( toUpper )
import Distribution
import FilePath ( (</>), pathSeparator, takeDirectory )
import GetOpt
import List
import Maybe ( fromJust, isJust )
import System ( system, exitWith, getArgs, getPID, getEnviron )
import AbstractCurry.Types
import AbstractCurry.Files
import AbstractCurry.Select
import AbstractCurry.Build
import AbstractCurry.Pretty (showCProg)
import AbstractCurry.Transform (renameCurryModule,updCProg,updQNamesInCProg)
import AnsiCodes
import Char (toUpper)
import Distribution
import FilePath ((</>), pathSeparator, takeDirectory)
import qualified FlatCurry.Types as FC
import FlatCurry.Files
import qualified FlatCurry.Goodies as FCG
import GetOpt
import IO
import List
import Maybe (fromJust, isJust)
import ReadNumeric (readNat)
import System (system, exitWith, getArgs, getPID, getEnviron)
import CheckDetUsage (checkDetUse, containsDetOperations)
import CC.Config ( packagePath, packageVersion )
import CC.Options
import CheckDetUsage ( checkDetUse, containsDetOperations)
import ContractUsage
import CurryCheckConfig (packagePath, packageVersion)
import DefaultRuleUsage (checkDefaultRules, containsDefaultRules)
import DefaultRuleUsage ( checkDefaultRules, containsDefaultRules )
import PropertyUsage
import SimplifyPostConds (simplifyPostConditionsWithTheorems)
import SimplifyPostConds ( simplifyPostConditionsWithTheorems )
import TheoremUsage
import UsageCheck (checkBlacklistUse, checkSetUse)
--- Maximal arity of check functions and tuples currently supported:
maxArity :: Int
maxArity = 5
import UsageCheck ( checkBlacklistUse, checkSetUse )
-- Banner of this tool:
ccBanner :: String
ccBanner = unlines [bannerLine,bannerText,bannerLine]
where
bannerText = "CurryCheck: a tool for testing Curry programs (Version " ++
packageVersion ++ " of 14/12/2017)"
packageVersion ++ " of 01/06/2018)"
bannerLine = take (length bannerText) (repeat '-')
-- Help text
usageText :: String
usageText = usageInfo ("Usage: curry check [options] <module names>\n") options
-------------------------------------------------------------------------
-- Representation of command line options.
data Options = Options
{ optHelp :: Bool
, optVerb :: Int
, optKeep :: Bool
, optMaxTest :: Int
, optMaxFail :: Int
, optDefType :: String
, optSource :: Bool
, optProp :: Bool
, optSpec :: Bool
, optDet :: Bool
, optProof :: Bool
, optColor :: Bool
, optMainProg :: String
}
-- Default command line options.
defaultOptions :: Options
defaultOptions = Options
{ optHelp = False
, optVerb = 1
, optKeep = False
, optMaxTest = 0
, optMaxFail = 0
, optDefType = "Ordering"
, optSource = True
, optProp = True
, optSpec = True
, optDet = True
, optProof = True
, optColor = True
, optMainProg = ""
}
-- Definition of actual command line options.
options :: [OptDescr (Options -> Options)]
options =
[ Option "h?" ["help"] (NoArg (\opts -> opts { optHelp = True }))
"print help and exit"
, Option "q" ["quiet"] (NoArg (\opts -> opts { optVerb = 0 }))
"run quietly (no output, only exit code)"
, Option "v" ["verbosity"]
(OptArg (maybe (checkVerb 3) (safeReadNat checkVerb)) "<n>")
"verbosity level:\n0: quiet (same as `-q')\n1: show test names (default)\n2: show more information about test generation\n3: show test data (same as `-v')\n4: show also some debug information"
, Option "k" ["keep"] (NoArg (\opts -> opts { optKeep = True }))
"keep temporarily generated program files"
, Option "m" ["maxtests"]
(ReqArg (safeReadNat (\n opts -> opts { optMaxTest = n })) "<n>")
"maximal number of tests (default: 100)"
, Option "f" ["maxfails"]
(ReqArg (safeReadNat (\n opts -> opts { optMaxFail = n })) "<n>")
"maximal number of condition failures\n(default: 10000)"
, Option "d" ["deftype"]
(ReqArg checkDefType "<t>")
"type for defaulting polymorphic tests:\nBool | Int | Char | Ordering (default)"
, Option "" ["nosource"]
(NoArg (\opts -> opts { optSource = False }))
"do not perform source code checks"
, Option "" ["noprop"]
(NoArg (\opts -> opts { optProp = False }))
"do not perform any property tests"
, Option "" ["nospec"]
(NoArg (\opts -> opts { optSpec = False }))
"do not perform specification/postcondition tests"
, Option "" ["nodet"]
(NoArg (\opts -> opts { optDet = False }))
"do not perform determinism tests"
, Option "" ["noproof"]
(NoArg (\opts -> opts { optProof = False }))
"do not consider proofs to simplify properties"
, Option "" ["nocolor"]
(NoArg (\opts -> opts { optColor = False }))
"do not use colors when showing tests"
, Option "" ["mainprog"]
(ReqArg (\s opts -> opts { optMainProg = s }) "<prog>")
"name of generated main program\n(default: TEST<pid>.curry)"
]
where
safeReadNat opttrans s opts =
let numError = error "Illegal number argument (try `-h' for help)" in
maybe numError
(\ (n,rs) -> if null rs then opttrans n opts else numError)
(readNat s)
checkVerb n opts = if n>=0 && n<5
then opts { optVerb = n }
else error "Illegal verbosity level (try `-h' for help)"
usageText = usageInfo ("Usage: curry-check [options] <module names>\n") options
checkDefType s opts = if s `elem` ["Bool","Int","Char","Ordering"]
then opts { optDefType = s }
else error "Illegal default type (try `-h' for help)"
--- Further option processing, e.g., setting coloring mode.
processOpts :: Options -> IO Options
processOpts opts = do
isterm <- hIsTerminalDevice stdout
return $ if isterm then opts else opts { optColor = False}
isQuiet :: Options -> Bool
isQuiet opts = optVerb opts == 0
--- Print second argument if verbosity level is not quiet:
putStrIfNormal :: Options -> String -> IO ()
putStrIfNormal opts s = unless (isQuiet opts) (putStr s >> hFlush stdout)
--- Print second argument if verbosity level > 1:
putStrIfVerbose :: Options -> String -> IO ()
putStrIfVerbose opts s = when (optVerb opts > 1) (putStr s >> hFlush stdout)
--- Print second argument if verbosity level > 3:
putStrLnIfDebug :: Options -> String -> IO ()
putStrLnIfDebug opts s = when (optVerb opts > 3) (putStrLn s >> hFlush stdout)
--- use some coloring (from library AnsiCodes) if color option is on:
withColor :: Options -> (String -> String) -> String -> String
withColor opts coloring = if optColor opts then coloring else id
--- Maximal arity of check functions and tuples currently supported:
maxArity :: Int
maxArity = 5
-------------------------------------------------------------------------
-- The names of suffixes added to specific tests.
......@@ -226,23 +107,34 @@ isEquivTest :: Test -> Bool
isEquivTest t = case t of EquivTest _ _ _ _ _ -> True
_ -> False
-- Returns the names of the operations of an equivalence test.
equivTestOps :: Test -> [QName]
equivTestOps t = case t of EquivTest _ f1 f2 _ _ -> [f1,f2]
_ -> []
-- The name of a test:
getTestName :: Test -> QName
getTestName (PropTest n _ _) = n
getTestName (IOTest n _) = n
getTestName (EquivTest n _ _ _ _) = n
testName :: Test -> QName
testName (PropTest n _ _) = n
testName (IOTest n _) = n
testName (EquivTest n _ _ _ _) = n
-- The line number of a test:
getTestLine :: Test -> Int
getTestLine (PropTest _ _ n) = n
getTestLine (IOTest _ n) = n
getTestLine (EquivTest _ _ _ _ n) = n
testLine :: Test -> Int
testLine (PropTest _ _ n) = n
testLine (IOTest _ n) = n
testLine (EquivTest _ _ _ _ n) = n
-- Generates a useful error message for tests (with module and line number)
genTestMsg :: String -> Test -> String
genTestMsg file test =
snd (getTestName test) ++
" (module " ++ file ++ ", line " ++ show (getTestLine test) ++ ")"
snd (testName test) ++
" (module " ++ file ++ ", line " ++ show (testLine test) ++ ")"
-- Generates the name of a test in the main test module from the test name.
genTestName :: Test -> String
genTestName test =
let (modName, fName) = testName test
in fName ++ "_" ++ modNameToId modName
-------------------------------------------------------------------------
-- Representation of the information about a module to be tested:
......@@ -293,11 +185,11 @@ equivPropTypes testmod = concatMap equivTypesOf (propTests testmod)
-------------------------------------------------------------------------
-- Transform all tests of a module into operations that perform
-- appropriate calls to EasyCheck:
createTests :: Options -> String -> TestModule -> [CFuncDecl]
createTests opts mainmod tm = map createTest (propTests tm)
genTestFuncs :: Options -> String -> TestModule -> [CFuncDecl]
genTestFuncs opts mainmod tm = map createTest (propTests tm)
where
createTest test =
cfunc (mainmod, (genTestName $ getTestName test)) 0 Public
cfunc (mainmod, (genTestName $ testName test)) 0 Public
(ioType (maybeType stringType))
(case test of
PropTest name t _ -> propBody name t test
......@@ -327,27 +219,27 @@ createTests opts mainmod tm = map createTest (propTests tm)
-- Operation equivalence test for terminating operations:
equivBodyTerm f1 f2 texp test =
let xvar = (1,"x")
let xvars = map (\i -> (i,"x"++show i)) [1 .. arityOfType texp]
pvalOfFunc = ctype2pvalOf mainmod "pvalOf" (resultType texp)
in propOrEquivBody (map (\t -> (t,True)) (argTypes texp)) test
(CLambda [CPVar xvar]
(CLambda (map CPVar xvars)
(applyF (easyCheckModule,"<~>")
[applyE pvalOfFunc [applyF f1 [CVar xvar]],
applyE pvalOfFunc [applyF f2 [CVar xvar]]]))
[applyE pvalOfFunc [applyF f1 (map CVar xvars)],
applyE pvalOfFunc [applyF f2 (map CVar xvars)]]))
-- Operation equivalence test for arbitrary operations:
equivBodyAny f1 f2 texp test =
let xvar = (1,"x")
pvar = (2,"p")
let xvars = map (\i -> (i,"x"++show i)) [1 .. arityOfType texp]
pvar = (2,"p")
pvalOfFunc = ctype2pvalOf mainmod "peval" (resultType texp)
in propOrEquivBody
(map (\t -> (t,True)) (argTypes texp) ++
[(ctype2BotType mainmod (resultType texp), False)])
test
(CLambda [CPVar xvar, CPVar pvar]
(CLambda (map CPVar xvars ++ [CPVar pvar])
(applyF (easyCheckModule,"<~>")
[applyE pvalOfFunc [applyF f1 [CVar xvar], CVar pvar],
applyE pvalOfFunc [applyF f2 [CVar xvar], CVar pvar]]))
[applyE pvalOfFunc [applyF f1 (map CVar xvars), CVar pvar],
applyE pvalOfFunc [applyF f2 (map CVar xvars), CVar pvar]]))
propBody qname texp test =
propOrEquivBody (map (\t -> (t,False)) (argTypes texp))
......@@ -381,17 +273,17 @@ createTests opts mainmod tm = map createTest (propTests tm)
in if n==0 then stdConfigOp
else applyF (easyCheckExecModule,"setMaxTest")
[cInt n, stdConfigOp]
configOpWithMaxFail =
let n = optMaxFail opts
in if n==0 then configOpWithMaxTest
else applyF (easyCheckExecModule,"setMaxFail")
[cInt n, configOpWithMaxTest]
msgvar = (0,"msg")
stdConfigOp = constF (easyCheckConfig opts)
ioTestBody (_, name) test =
[simpleRule [] $ applyF (easyCheckExecModule,"checkPropIOWithMsg")
[stdConfigOp, msgOf test, CSymbol (testmname,name)]]
......@@ -484,8 +376,7 @@ classifyTests opts prog = map makeProperty
then IOTest tname 0
else maybe (PropTest tname (funcType test) 0)
(\ (f1,f2) -> EquivTest tname f1 f2
(poly2defaultType (optDefType opts)
(funcTypeOf f1))
(poly2defaultType opts (funcTypeOf f1))
0)
(isEquivProperty test)
where tname = funcName test
......@@ -518,7 +409,7 @@ transformTests opts srcdir
(realtests,ignoredtests) = partition fst $
if not (optProp opts)
then []
else concatMap (poly2default (optDefType opts)) $
else concatMap (poly2default opts) $
-- ignore already proved properties:
filter (\fd -> funcName fd `notElem` map funcName theofuncs)
usertests ++
......@@ -553,7 +444,7 @@ transformDetTests opts prooffiles
opDecls)
where
preCondOps = preCondOperations functions
-- generate determinism tests:
detOpTests = genDetOpTests prooffiles preCondOps functions
......@@ -565,7 +456,7 @@ transformDetTests opts prooffiles
(realtests,ignoredtests) = partition fst $
if not (optProp opts)
then []
else concatMap (poly2default (optDefType opts))
else concatMap (poly2default opts)
(if optDet opts then detOpTests else [])
-- Get all operations with a defined precondition from a list of functions.
......@@ -680,25 +571,28 @@ genDetProp prefuns (CFunc (mn,fn) ar _ texp _) =
-- Generates auxiliary (base-type instantiated) test functions for
-- polymorphically typed test function.
-- The flag indicates whether the test function should be actually passed
-- to the test tool.
poly2default :: String -> CFuncDecl -> [(Bool,CFuncDecl)]
poly2default dt (CmtFunc _ name arity vis ftype rules) =
poly2default dt (CFunc name arity vis ftype rules)
poly2default dt fdecl@(CFunc (mn,fname) arity vis ftype _)
-- The returned flag indicates whether the test function should actually
-- be passed to the test tool.
-- Thus, IO tests are flagged by `False` if the corresponding option is set.
poly2default :: Options -> CFuncDecl -> [(Bool,CFuncDecl)]
poly2default opts (CmtFunc _ name arity vis ftype rules) =
poly2default opts (CFunc name arity vis ftype rules)
poly2default opts fdecl@(CFunc (mn,fname) arity vis ftype rs)
| isPolyType ftype
= [(False,fdecl)
,(True, CFunc (mn,fname++defTypeSuffix) arity vis
(poly2defaultType dt ftype)
(poly2defaultType opts ftype)
[simpleRule [] (applyF (mn,fname) [])])
]
| not (optIOTest opts) && isPropIOType ftype
= [(False,fdecl)]
| otherwise
= [(True,fdecl)]
poly2defaultType :: String -> CTypeExpr -> CTypeExpr
poly2defaultType dt texp = p2dt texp
poly2defaultType :: Options -> CTypeExpr -> CTypeExpr
poly2defaultType opts texp = p2dt texp
where
p2dt (CTVar _) = baseType (pre dt)
p2dt (CTVar _) = baseType (pre (optDefType opts))
p2dt (CFuncType t1 t2) = CFuncType (p2dt t1) (p2dt t2)
p2dt (CTCons ct ts) = CTCons ct (map p2dt ts)
......@@ -738,7 +632,7 @@ analyseModule opts modname = do
staticProgAnalysis :: Options -> String -> String -> CurryProg
-> IO ([String],[(QName,String)])
staticProgAnalysis opts modname progtxt prog = do
putStrIfVerbose opts "Checking source code for static errors...\n"
putStrIfDetails opts "Checking source code for static errors...\n"
useerrs <- if optSource opts then checkBlacklistUse prog else return []
seterrs <- if optSource opts then readFlatCurry modname >>= checkSetUse
else return []
......@@ -767,13 +661,13 @@ analyseCurryProg opts modname orgprog = do
let srcdir = takeDirectory srcfilename
putStrLnIfDebug opts $ "Source file: " ++ srcfilename
prooffiles <- if optProof opts then getProofFiles srcdir else return []
unless (null prooffiles) $ putStrIfVerbose opts $
unless (null prooffiles) $ putStrIfDetails opts $
unlines ("Proof files found:" : map ("- " ++) prooffiles)
progtxt <- readFile srcfilename
(missingCPP,staticoperrs) <- staticProgAnalysis opts modname progtxt prog
let words = map firstWord (lines progtxt)
staticerrs = missingCPP ++ map (showOpError words) staticoperrs
putStrIfVerbose opts "Generating property tests...\n"
putStrIfDetails opts "Generating property tests...\n"
(rawTests,ignoredTests,pubmod) <-
transformTests opts srcdir . renameCurryModule (modname++"_PUBLIC")
. makeAllPublic $ prog
......@@ -1044,16 +938,16 @@ genMainTestModule opts mainmod modules = do
let bottypes = map (genBottomType mainmod) equvtypedecls
pevalfuns = map (genPeval mainmod) equvtypedecls