CurryInfo: verify-non-fail-2.0.0 / Main.verifyModule

definition:
verifyModule :: TermDomain a => Analysis a -> IORef ProgInfo
             -> IORef (AnalysisStore a) -> Options -> String -> Prog -> IO ()
verifyModule valueanalysis pistore astore opts mname flatprog = do
  let orgfdecls     = progFuncs flatprog
      numfdecls     = length orgfdecls
      visfuncs      = map funcName (filter ((== Public) . funcVisibility)
                                          orgfdecls)
      visfuncset    = Set.fromList visfuncs
      isVisible qf  = Set.member qf visfuncset
      showfuncset   = Set.fromList
                        (filter (\fn -> optGenerated opts || isCurryID fn)
                                visfuncs)
      isShowable qf = Set.member qf showfuncset
  imps@(impconsinfos,impacalltypes,impnftypes,impiotypes) <-
    if optImports opts
      then do
        let imports = progImports flatprog
        whenStatus opts $ printInfoString $
          "Reading abstract types of imports: " ++ unwords imports
        -- if only verification results should be shown, use quiet mode and
        -- do not show in/out types for imports:
        let impopts = if optVerb opts <= 1
                        then opts { optVerb = 0, optIOTypes = False }
                        else opts
        readTypesOfModules impopts
                           (verifyModuleIfNew valueanalysis pistore astore)
                           imports
      else return ([],[],[],[])
  if optTime opts then do whenStatus opts $ printInfoString "..."
                          (id $## imps) `seq` printWhenStatus opts "done"
                  else printWhenStatus opts ""
  let modconsinfos = consInfoOfTypeDecls (progTypes flatprog)
      consinfos = modconsinfos ++ impconsinfos
      -- verify function declarations with completed branches:
      fdecls  = map (completeBranchesInFunc consinfos False) orgfdecls
      funusage = funcDecls2Usage mname fdecls
  mtime <- getModuleModTime mname
  -- infer initial abstract call types:
  mboldacalltypes <- readCallTypeFile opts mtime mname
  (acalltypes, numntacalltypes, numpubacalltypes) <- id $!!  
    inferCallTypes opts consinfos isVisible mname mtime flatprog mboldacalltypes
  -- infer in/out types:
  iotypes <- id $!! inferIOTypes opts valueanalysis astore flatprog
  printIOTypesIfDemanded opts isShowable iotypes
  -- read previously inferred non-fail conditions:
  mbnfconds <- readNonFailCondFile opts mtime mname

  vstate <- initVerifyState pistore flatprog consinfos
                            (Map.fromList impacalltypes)
                            (Map.fromList impnftypes)
                            (Map.fromList acalltypes)
                            (Map.fromList (iotypes ++ impiotypes))
                            (maybe [] id mbnfconds) opts
  enforceNormalForm opts "VERIFYSTATE" vstate
  printWhenAll opts $ unlines $
    ("Function usage in module '" ++ mname ++ "':") :
    map (\ (qf, qfs) -> snd qf ++ ": used in " ++
                        unwords (map (snd . funcName) qfs))
        (Map.toList funusage)
  let withverify = optVerify opts &&
                   (null (optFunction opts) ||
                    isNothing mbnfconds || isNothing mboldacalltypes)
  (vnumits, vtime, vst) <-
   if withverify
     then do
       printWhenStatus opts $ "Start verification of '" ++ mname ++ "' (" ++
         show numfdecls ++ " functions):"
       pi1 <- getProcessInfos
       (numits,st) <- tryVerifyProg opts 0 vstate mname funusage fdecls
       pi2 <- getProcessInfos
       printVerifyResult opts st mname isShowable
       let tdiff = maybe 0 id (lookup ElapsedTime pi2) -
                   maybe 0 id (lookup ElapsedTime pi1)
       when (optTime opts && optVerb opts > 0) $ printInfoLine $
         "TOTAL VERIFICATION TIME: " ++ show tdiff ++ " msec"
       return (numits, tdiff, st)
     else return (0, 0, vstate)
  -- print statistics:
  let finalacalltypes   = Map.toList (vstCallTypes vst)
      finalntacalltypes = filter (not . isTotalACallType . snd) finalacalltypes
      ntiotypes         = filter (not . isAnyIOType . snd) iotypes
      numpubntiotypes   = length (filter (isShowable . fst) ntiotypes)
      numvisfuncs       = length visfuncs
      (stattxt,statcsv) = showStatistics opts vtime vnumits isShowable
                            numvisfuncs numfdecls
                            (numpubntiotypes, length ntiotypes)
                            (numpubacalltypes, numntacalltypes)
                            finalntacalltypes
                            (map fst (vstFunConds vst)) (vstStats vst)
  when (optStats opts) $ printInfoString stattxt
  when withverify $ do
    storeTypes opts mname fdecls modconsinfos finalacalltypes
      (filter (isVisible .fst) finalntacalltypes) (vstFunConds vst)
      (filter (isVisible . fst) iotypes)
    storeStatistics opts mname stattxt statcsv
    when (optStoreFuncs opts) $ do
      let nfname = mname ++ ".NONFAIL"
          flname = mname ++ ".FAIL"  
          totalfuncs = filter (isTotalACallType . snd) finalacalltypes
      writeFile nfname
        (unlines (map (\((mn,fn),_) -> mn ++ " " ++ fn) totalfuncs))
      printWhenStatus opts $
        "Non-failing functions stored in '" ++ nfname ++ "'."
      writeFile flname
        (unlines (map (\((mn,fn),_) -> mn ++ " " ++ fn) finalntacalltypes))
      printWhenStatus opts $
        "Possibly failing functions stored in '" ++ flname ++ "'."
  unless (null (optFunction opts)) $ showFunctionInfo opts mname vst
  when (vstError vst) $ exitWith 1
demand:
no demanded arguments
deterministic:
deterministic operation
documentation:
--- Verify a single module.
indeterministic:
might be indeterministic
infix:
no fixity defined
name:
verifyModule
precedence:
no precedence defined
result-values:
_
signature:
Analysis.TermDomain.TermDomain a => Analysis.Types.Analysis a
-> Data.IORef.IORef Verify.ProgInfo.ProgInfo
-> Data.IORef.IORef (Verify.Helpers.AnalysisStore a) -> Verify.Options.Options
-> String -> FlatCurry.Types.Prog -> Prelude.IO ()
solution-complete:
operation might suspend on free variables
terminating:
possibly non-terminating
totally-defined:
possibly non-reducible on same data term