Commit 612d3c08 authored by Michael Hanus 's avatar Michael Hanus
Browse files

Curry Analysis Server System added, currydoc connected to CASS

parent a4bcbef7
-------------------------------------------------------------------------
--- This module contains the datatypes, constructors, and other
--- operations to create and process analyses used in the
--- generic analysis system.
---
--- Each analysis has a name which is used to identify the analysis
--- stored in files, when passing analysis information between workers etc.
---
--- **Important:** Use the constructor operations to define new analyses
--- (instead of the data constructors).
---
--- @author Heiko Hoffmann, Michael Hanus
--- @version March 2013
-------------------------------------------------------------------------
module Analysis(Analysis(..),
simpleFuncAnalysis,simpleTypeAnalysis,
simpleConstructorAnalysis,
dependencyFuncAnalysis,dependencyTypeAnalysis,
combinedSimpleFuncAnalysis,combinedSimpleTypeAnalysis,
combinedDependencyFuncAnalysis,combinedDependencyTypeAnalysis,
isSimpleAnalysis,isCombinedAnalysis,
analysisName,baseAnalysisName,startValue)
where
import FlatCurry(ConsDecl,FuncDecl,TypeDecl,QName)
import FlatCurryGoodies(progImports)
import GenericProgInfo(ProgInfo,combineProgInfo,lookupProgInfo)
import LoadAnalysis(loadCompleteAnalysis,getInterfaceInfos)
import CurryFiles(getImports)
data Analysis a =
SimpleFuncAnalysis String (FuncDecl -> a)
| SimpleTypeAnalysis String (TypeDecl -> a)
| SimpleConstructorAnalysis String (ConsDecl -> TypeDecl -> a)
| DependencyFuncAnalysis String a (FuncDecl -> [(QName,a)] -> a)
| DependencyTypeAnalysis String a (TypeDecl -> [(QName,a)] -> a)
| CombinedSimpleFuncAnalysis String String Bool
(String -> IO (FuncDecl -> a))
| CombinedSimpleTypeAnalysis String String Bool
(String -> IO (TypeDecl -> a))
| CombinedDependencyFuncAnalysis String String Bool a
(String -> IO (FuncDecl -> [(QName,a)] -> a))
| CombinedDependencyTypeAnalysis String String Bool a
(String -> IO (TypeDecl -> [(QName,a)] -> a))
--- A simple analysis for functions takes an operation that computes
--- some information from a given function declaration.
simpleFuncAnalysis :: String -> (FuncDecl -> a) -> Analysis a
simpleFuncAnalysis anaName anaFunc =
SimpleFuncAnalysis anaName anaFunc
--- A simple analysis for types takes an operation that computes
--- some information from a given type declaration.
simpleTypeAnalysis :: String -> (TypeDecl -> a) -> Analysis a
simpleTypeAnalysis anaName anaFunc =
SimpleTypeAnalysis anaName anaFunc
--- A simple analysis for data constructors takes an operation that computes
--- some information for a constructor declaration and its type declaration
--- to which it belongs.
simpleConstructorAnalysis :: String -> (ConsDecl -> TypeDecl -> a) -> Analysis a
simpleConstructorAnalysis anaName anaFunc =
SimpleConstructorAnalysis anaName anaFunc
--- Construct a function analysis with dependencies.
--- The analysis has a name, a start value (representing "no initial
--- information") and an operation to process a function declaration
--- with analysis information
--- for the operations directly called in this function declaration.
--- The analysis will be performed by a fixpoint iteration
--- starting with the given start value.
dependencyFuncAnalysis :: String -> a -> (FuncDecl -> [(QName,a)] -> a)
-> Analysis a
dependencyFuncAnalysis anaName startval anaFunc =
DependencyFuncAnalysis anaName startval anaFunc
--- Construct a type analysis with dependencies.
--- The analysis has a name, a start value (representing "no initial
--- information") and an operation to process a type declaration
--- with analysis information
--- for the type constructors occurring in the type declaration.
--- The analysis will be performed by a fixpoint iteration
--- starting with the given start value.
dependencyTypeAnalysis :: String -> a -> (TypeDecl -> [(QName,a)] -> a)
-> Analysis a
dependencyTypeAnalysis anaName startval anaType =
DependencyTypeAnalysis anaName startval anaType
--- A simple combined analysis for functions.
--- The analysis is based on an operation that computes
--- some information from a given function declaration
--- and information provided by some base analysis.
--- The base analysis is provided as the second argument.
combinedSimpleFuncAnalysis :: String -> Analysis b
-> (ProgInfo b -> FuncDecl -> a) -> Analysis a
combinedSimpleFuncAnalysis ananame baseAnalysis anaFunc =
CombinedSimpleFuncAnalysis analysisAName ananame True
(runWithBaseAnalysis baseAnalysis anaFunc)
where analysisAName = analysisName baseAnalysis
--- A simple combined analysis for types.
--- The analysis is based on an operation that computes
--- some information from a given type declaration
--- and information provided by some base analysis.
--- The base analysis is provided as the second argument.
combinedSimpleTypeAnalysis :: String -> Analysis b
-> (ProgInfo b -> TypeDecl -> a) -> Analysis a
combinedSimpleTypeAnalysis ananame baseAnalysis anaFunc =
CombinedSimpleTypeAnalysis analysisAName ananame True
(runWithBaseAnalysis baseAnalysis anaFunc)
where analysisAName = analysisName baseAnalysis
--- A combined analysis for functions with dependencies.
--- The analysis is based on an operation that computes
--- from information provided by some base analysis
--- for each function declaration and information about its
--- directly called operation some information for the declared function.
--- The analysis will be performed by a fixpoint iteration
--- starting with the given start value (fourth argument).
--- The base analysis is provided as the second argument.
combinedDependencyFuncAnalysis :: String -> Analysis b -> a
-> (ProgInfo b -> FuncDecl -> [(QName,a)] -> a) -> Analysis a
combinedDependencyFuncAnalysis ananame baseAnalysis startval anaFunc =
CombinedDependencyFuncAnalysis baseAnaName ananame True startval
(runWithBaseAnalysis baseAnalysis anaFunc)
where
baseAnaName = analysisName baseAnalysis
--- A combined analysis for types with dependencies.
--- The analysis is based on an operation that computes
--- from information provided by some base analysis
--- for each type declaration and information about its
--- directly used types some information for the declared type.
--- The analysis will be performed by a fixpoint iteration
--- starting with the given start value (fourth argument).
--- The base analysis is provided as the second argument.
combinedDependencyTypeAnalysis :: String -> Analysis b -> a
-> (ProgInfo b -> TypeDecl -> [(QName,a)] -> a) -> Analysis a
combinedDependencyTypeAnalysis ananame baseAnalysis startval anaType =
CombinedDependencyTypeAnalysis baseAnaName ananame True startval
(runWithBaseAnalysis baseAnalysis anaType)
where
baseAnaName = analysisName baseAnalysis
--- Loads the results of the base analysis and put it as the first
--- argument of the main analysis operation which is returned.
runWithBaseAnalysis :: Analysis a -> (ProgInfo a -> (input -> b)) -> String
-> IO (input -> b)
runWithBaseAnalysis baseAnalysis analysisFunction moduleName = do
importedModules <- getImports moduleName
let baseananame = analysisName baseAnalysis
impbaseinfos <- getInterfaceInfos baseananame importedModules
mainbaseinfos <- loadCompleteAnalysis baseananame moduleName
let baseinfos = combineProgInfo impbaseinfos mainbaseinfos
return (analysisFunction baseinfos)
--- Is the analysis a simple analysis?
--- Otherwise, it is a dependency analysis which requires a fixpoint
--- computation to compute the results.
isSimpleAnalysis :: Analysis a -> Bool
isSimpleAnalysis analysis = case analysis of
SimpleFuncAnalysis _ _ -> True
SimpleTypeAnalysis _ _ -> True
SimpleConstructorAnalysis _ _ -> True
CombinedSimpleFuncAnalysis _ _ _ _ -> True
CombinedSimpleTypeAnalysis _ _ _ _ -> True
_ -> False
--- Is the analysis a combined analysis?
isCombinedAnalysis :: Analysis a -> Bool
isCombinedAnalysis analysis = case analysis of
CombinedSimpleFuncAnalysis _ _ _ _ -> True
CombinedSimpleTypeAnalysis _ _ _ _ -> True
CombinedDependencyFuncAnalysis _ _ _ _ _ -> True
CombinedDependencyTypeAnalysis _ _ _ _ _ -> True
_ -> False
--- Name of the analysis to be used in server communication and
--- analysis files.
analysisName :: Analysis a -> String
analysisName (SimpleFuncAnalysis name _) = name
analysisName (SimpleTypeAnalysis name _) = name
analysisName (SimpleConstructorAnalysis name _) = name
analysisName (DependencyFuncAnalysis name _ _) = name
analysisName (DependencyTypeAnalysis name _ _) = name
analysisName (CombinedSimpleFuncAnalysis _ nameB _ _) = nameB
analysisName (CombinedSimpleTypeAnalysis _ nameB _ _) = nameB
analysisName (CombinedDependencyFuncAnalysis _ nameB _ _ _) = nameB
analysisName (CombinedDependencyTypeAnalysis _ nameB _ _ _) = nameB
--- Name of the base analysis of a combined analysis.
baseAnalysisName (CombinedSimpleFuncAnalysis bName _ _ _) = bName
baseAnalysisName (CombinedSimpleTypeAnalysis bName _ _ _) = bName
baseAnalysisName (CombinedDependencyFuncAnalysis bName _ _ _ _) = bName
baseAnalysisName (CombinedDependencyTypeAnalysis bName _ _ _ _) = bName
--- Start value of a dependency analysis.
startValue :: Analysis a -> a
startValue (DependencyFuncAnalysis _ startval _) = startval
startValue (DependencyTypeAnalysis _ startval _) = startval
startValue (CombinedDependencyFuncAnalysis _ _ _ startval _) = startval
startValue (CombinedDependencyTypeAnalysis _ _ _ startval _) = startval
--------------------------------------------------------------------
--- This module collects all analyses in the analysis system.
---
--- Each analysis available in the analysis system must be
--- registered in the top part of this module.
---
--- @author Heiko Hoffmann, Michael Hanus
--- @version March 2013
--------------------------------------------------------------------
module AnalysisCollection(
analysisInfos,functionAnalysisInfos,registeredAnalysisNames,
lookupRegAnaWorker,runAnalysisWithWorkers,analyzeMain) where
import FlatCurry
import FlatCurryGoodies(progImports)
import IO
import IOExts
import XML
import Analysis
import Configuration(debugMessageLevel,numberOfWorkers)
import CurryFiles(getImports)
import GenericProgInfo
import AnalysisDependencies(getModulesToAnalyze)
import ServerFunctions(workerLoop)
import WorkerFunctions(analysisClient)
import LoadAnalysis(loadCompleteAnalysis)
--------------------------------------------------------------------
-- Configurable part of this module.
--------------------------------------------------------------------
import Deterministic
import HigherOrder
import RightLinearity
import SolutionCompleteness
import TotallyDefined
import Indeterministic
--- Each analysis name should be added here together with a short explanation.
--- The first component is the registered analysis name.
--- These names will be visible by the server message `GetAnalysis`.
--- The second and third components, which might be used in interactive tools
--- like the CurryBrowser, are a longer analysis name and some explanation
--- of the analysis and their result values.
analysisInfos = functionAnalysisInfos ++ typeAnalysisInfos
functionAnalysisInfos =
[("Overlapping", "Overlapping rules", "Overlapping function analysis"),
("Deterministic","Deterministic operations",
"(Non-)determinism function analysis"),
("SetValued", "Set-valued operations", "Set-valued function analysis"),
("PatComplete", "Pattern completeness", "Pattern completeness analysis"),
("Total", "Totally defined operations",
"Totally definedness analysis"),
("SolComplete", "Solution completeness","Solution completeness analysis"),
("Indeterministic","Indeterministic operations",
"Indeterminism function analysis"),
("RightLinear", "Right-linear operations","Right-linear function analysis"),
("HiOrderFunc", "Higher-order functions","Higher-order function analysis")]
typeAnalysisInfos =
[("HiOrderType", "Higher-order datatypes", "Higher-order datatype analysis"),
("HiOrderConstr","Higher-order constructors",
"Higher-order constructor analysis"),
("SiblingCons", "Sibling constructors","Sibling constructor analysis")]
--------------------------------------------------------------------
--- Each analysis used in our tool must be registered in this list
--- together with an operation to show the analysis result as a string.
registeredAnalysis :: [RegisteredAnalysis]
registeredAnalysis =
[scAnalysis overlapAnalysis showOverlap
,scAnalysis ndAnalysis showDet
,scAnalysis setValAnalysis showSetValued
,scAnalysis rlinAnalysis showRightLinear
,scAnalysis solcompAnalysis showSolComplete
,scAnalysis patCompAnalysis showComplete
,scAnalysis totalAnalysis showTotally
,scAnalysis indetAnalysis showIndet
,scAnalysis hiOrdType showOrder
,scAnalysis hiOrdCons showOrder
,scAnalysis hiOrdFunc show
,scAnalysis siblingCons show
]
--------------------------------------------------------------------
-- Static part of this module follows below
--------------------------------------------------------------------
--- The type of all registered analysis.
--- The first component is the name of the analysis.
--- The second component is the operation used by the server
--- to distribute analysis work to the clients.
--- The third component is the worker operation to analyze a list of modules.
data RegisteredAnalysis =
RegAna String
(String -> [Handle] -> Bool -> IO (Either (ProgInfo String) String))
([String] -> IO ())
regAnaName (RegAna n _ _) = n
regAnaServer (RegAna _ a _) = a
regAnaWorker (RegAna _ _ a) = a
--- Names of all registered analyses.
registeredAnalysisNames = map regAnaName registeredAnalysis
lookupRegAna :: String -> [RegisteredAnalysis] -> Maybe RegisteredAnalysis
lookupRegAna _ [] = Nothing
lookupRegAna aname (ra@(RegAna raname _ _) : ras) =
if aname==raname then Just ra else lookupRegAna aname ras
-- Look up a registered analysis server with a given analysis name.
lookupRegAnaServer :: String
-> (String -> [Handle] -> Bool -> IO (Either (ProgInfo String) String))
lookupRegAnaServer aname =
maybe (\_ _ _ -> return (Right ("unknown analysis: "++aname)))
regAnaServer
(lookupRegAna aname registeredAnalysis)
-- Look up a registered analysis worker with a given analysis name.
lookupRegAnaWorker :: String -> ([String] -> IO ())
lookupRegAnaWorker aname =
maybe (const done) regAnaWorker (lookupRegAna aname registeredAnalysis)
--- This auxiliary operation creates new analysis operations to be used
--- by the server/client analysis tool from a given analysis and
--- analysis show function.
scAnalysis :: Analysis a -> (a->String) -> RegisteredAnalysis
scAnalysis analysis showres =
RegAna (analysisName analysis)
(analyzeAsString analysis showres)
(analysisClient analysis)
--------------------------------------------------------------------
debugMessage dl message =
debugMessageLevel dl ("AnalysisCollection: "++message)
--------------------------------------------------------------------
-- Run an analysis with a given name on a given module with a list
-- of workers identified by their handles and return the analysis results.
runAnalysisWithWorkers :: String -> [Handle] -> String
-> IO (Either (ProgInfo String) String)
runAnalysisWithWorkers ananame handles moduleName =
(lookupRegAnaServer ananame) moduleName handles True
-- Run an analysis with a given name on a given module with a list
-- of workers identified by their handles but do not load analysis results.
runAnalysisWithWorkersNoLoad :: String -> [Handle] -> String -> IO ()
runAnalysisWithWorkersNoLoad ananame handles moduleName =
(lookupRegAnaServer ananame) moduleName handles False >> done
--- Generic operation to analyze a module.
--- The parameters are the analysis, the show operation for analysis results,
--- the name of the main module to be analyzed, the handles for the workers,
--- and a flag indicating whether the analysis results should be loaded
--- and returned (if the flag is false, the result contains the empty
--- program information).
--- An error occurred during the analysis is returned as `(Right ...)`.
analyzeAsString :: Analysis a -> (a->String) -> String -> [Handle] -> Bool
-> IO (Either (ProgInfo String) String)
analyzeAsString analysis showres modname handles load = do
analyzeMain analysis modname handles load >>=
return . either (Left . mapProgInfo showres) Right
--- Generic operation to analyze a module.
--- The parameters are the analysis, the name of the main module
--- to be analyzed, the handles for the workers,
--- and a flag indicating whether the analysis results should be loaded
--- and returned (if the flag is false, the result contains the empty
--- program information).
--- An error occurred during the analysis is returned as `(Right ...)`.
analyzeMain :: Analysis a -> String -> [Handle] -> Bool
-> IO (Either (ProgInfo a) String)
analyzeMain analysis modname handles load = do
let ananame = analysisName analysis
debugMessage 2 ("start analysis "++modname++"/"++ananame)
modulesToDo <- getModulesToAnalyze analysis modname
workresult <-
if null modulesToDo
then return Nothing
else do
prepareCombinedAnalysis analysis modname (map fst modulesToDo) handles
numworkers <- numberOfWorkers
if numworkers>0
then do debugMessage 2 "start WorkerLoop"
workerLoop handles [] ananame modname modulesToDo []
else analyzeLocally ananame (map fst modulesToDo)
result <-
maybe (if load
then do debugMessage 3 ("Reading analysis of: "++modname)
loadCompleteAnalysis ananame modname >>= return . Left
else return (Left emptyProgInfo))
(return . Right)
workresult
debugMessage 4 ("result: " ++ either showProgInfo id result)
return result
-- Analyze a module and all its imports locally without worker processes.
analyzeLocally :: String -> [String] -> IO (Maybe String)
analyzeLocally ananame modules = do
debugMessage 3 ("Local analysis of: "++ananame++"/"++show modules)
(lookupRegAnaWorker ananame) modules -- run client
return Nothing
-- Perform the first analysis part of a combined analysis
-- so that their results are available for the main analysis.
prepareCombinedAnalysis:: Analysis a -> String -> [String] -> [Handle] -> IO ()
prepareCombinedAnalysis analysis moduleName depmods handles =
if isCombinedAnalysis analysis
then
if isSimpleAnalysis analysis
then do
-- the directly imported interface information might be required...
importedModules <- getImports moduleName
mapIO_ (runAnalysisWithWorkersNoLoad baseAnaName handles)
(importedModules++[moduleName])
else do
-- for a dependency analysis, the information of all implicitly
-- imported modules might be required:
mapIO_ (runAnalysisWithWorkersNoLoad baseAnaName handles) depmods
else done
where
baseAnaName = baseAnalysisName analysis
--------------------------------------------------------------------
-----------------------------------------------------------------------
--- Operations to handle dependencies of analysis files.
---
--- @author Heiko Hoffmann, Michael Hanus
--- @version March 2013
-----------------------------------------------------------------------
module AnalysisDependencies(getModulesToAnalyze,reduceDependencies,
readNewestFlatCurry) where
import FlatCurry
import FlatCurryGoodies(progImports)
import ReadShowTerm(readQTerm,showQTerm)
import Directory(doesFileExist,getModificationTime)
import Distribution(findFileInLoadPath)
import Maybe(fromMaybe)
import List(delete)
import Time(ClockTime)
import Analysis
import GenericProgInfo
import LoadAnalysis(getAnalysisPublicFile,storeImportModuleList,getImportModuleListFile)
import Configuration(debugMessageLevel,getWithPrelude)
import CurryFiles
debugMessage dl message = debugMessageLevel dl ("Dependencies: "++message)
-----------------------------------------------------------------------
--- Compute the modules and their imports which must be analyzed
--- w.r.t. a given analysis and main module.
getModulesToAnalyze :: Analysis a -> String -> IO [(String,[String])]
getModulesToAnalyze analysis moduleName =
if isSimpleAnalysis analysis
then do
ananewer <- isAnalysisFileNewer ananame moduleName
return (if ananewer then [] else [(moduleName,[])])
else do
valid <- isAnalysisValid ananame moduleName
if valid
then do
debugMessage 3 ("Analysis file for '"++moduleName++"' up-to-date")
return []
else do
moduleList <- getDependencyList [moduleName] []
debugMessage 3 ("Complete module list: "++ show moduleList)
storeImportModuleList moduleName (map fst moduleList)
sourceTimeList <- mapIO getSourceFileTime (map fst moduleList)
--debugMessage 3 ("Source time list: "++ show sourceTimeList)
anaTimeList <- mapIO (getAnaFileTime ananame) (map fst moduleList)
--debugMessage 3 ("Analysis time list: "++ show anaTimeList)
let (modulesToDo,modulesUpToDate) =
findModulesToAnalyze moduleList anaTimeList sourceTimeList ([],[])
--debugMessage 3 ("Modules up-to-date: "++ show modulesUpToDate)
withprelude <- getWithPrelude
let modulesToAnalyze =
if withprelude=="no"
then let reduced = reduceDependencies modulesToDo
(modulesUpToDate ++ ["Prelude"])
in case reduced of (("Prelude",_):remaining) -> remaining
_ -> reduced
else reduceDependencies modulesToDo modulesUpToDate
debugMessage 3 ("Modules to analyze: " ++ show modulesToAnalyze)
return modulesToAnalyze
where
ananame = analysisName analysis
-- Check whether the analysis file is newer than the source file.
isAnalysisFileNewer ananame modname = do
atime <- getAnaFileTime ananame modname
stime <- getSourceFileTime modname
return (snd atime >= Just (snd stime))
-- Read current import dependencies.
isAnalysisValid ananame modname =
getImportModuleListFile modname >>= maybe
(return False)
(\importListFile -> do
itime <- getModificationTime importListFile
stime <- getSourceFileTime modname >>= return . snd
if itime>=stime
then do
implist <- readFile importListFile >>= return . readQTerm
sourceTimeList <- mapIO getSourceFileTime implist
anaTimeList <- mapIO (getAnaFileTime ananame) implist
return (all (uncurry (>=))
(zip (map snd anaTimeList) (map (Just . snd) sourceTimeList)))
else return False)
--- Gets the list of all modules required by the first module.
--- The result is sorted according to their dependencies
--- (Prelude first, main module last)
getDependencyList :: [String] -> [(String,[String])]
-> IO [(String,[String])]
getDependencyList [] moddeps = return moddeps
getDependencyList (mname:mods) moddeps =
let (newmoddeps,imps,processed) = checkAndReorder mname [] moddeps
in if not processed
then do --debugMessage 3 ("Getting imports of "++ mname)
--debugMessage 3 ("Still to do: "++ show mods)
imports <- getImports mname
let newimports = filter (`notElem` mods) imports
getDependencyList (mods++newimports) ((mname,imports):moddeps)
else getDependencyList (mods++imps) newmoddeps
checkAndReorder _ _ [] = ([], [], False)
checkAndReorder key1 list1 ((key2,value):rest)
| key1==key2 = ((key2,value):reverse list1++rest, value, True)
| otherwise = checkAndReorder key1 ((key2,value):list1) rest
-- get timestamp of analysis file
getAnaFileTime :: String -> String -> IO (String,Maybe ClockTime)
getAnaFileTime anaName moduleName = do
fileName <- getAnalysisPublicFile moduleName anaName
fileExists <- doesFileExist fileName
if fileExists
then do time <- getModificationTime fileName
return (moduleName,Just time)
else return (moduleName,Nothing)
-- check if analysis result of a module can be loaded or needs to be
-- newly analyzed
findModulesToAnalyze :: [(String,[String])] -> [(String,Maybe ClockTime)]
-> [(String,ClockTime)]
-> ([(String,[String])],[String])
-> ([(String,[String])],[String])
findModulesToAnalyze [] _ _ (modulesToDo,modulesUpToDate) =
(reverse modulesToDo, modulesUpToDate)
findModulesToAnalyze (m:ms) anaTimeList sourceTimeList resultLists =
let (mod,imports)= m
(modulesToDo,modulesUpToDate) = resultLists in
case (lookup mod anaTimeList) of
Just Nothing -> findModulesToAnalyze ms anaTimeList sourceTimeList
((m:modulesToDo),modulesUpToDate)
Just(Just time) ->
if checkTime mod time imports anaTimeList sourceTimeList modulesToDo
then findModulesToAnalyze ms anaTimeList sourceTimeList
(modulesToDo,(mod:modulesUpToDate))
else findModulesToAnalyze ms anaTimeList sourceTimeList
((m:modulesToDo),modulesUpToDate)
-- function to check if result file is up-to-date
-- compares timestamp of analysis result file with module source file
-- and with timpestamp of result files of all imported modules
checkTime :: String -> ClockTime -> [String] -> [(String,Maybe ClockTime)]
-> [(String,ClockTime)] -> [(String,[String])] -> Bool
checkTime mod time1 [] _ sourceTimeList _ =
(Just time1) >= (lookup mod sourceTimeList)
checkTime mod time1 (impt:impts) anaTimeList sourceTimeList resultList =
((lookup impt resultList)==Nothing)
&&((Just time1)>=(fromMaybe Nothing (lookup impt anaTimeList)))
&&(checkTime mod time1 impts anaTimeList sourceTimeList resultList)
-----------------------------------------------------------------------
-- Remove the module analysis dependencies (first argument) w.r.t.
-- a list of modules that are already analyzed (second argument).
reduceDependencies :: [(String,[String])] -> [String] -> [(String,[String])]
reduceDependencies modulesToDo [] = modulesToDo
reduceDependencies modulesToDo (mod:mods) =
let modulesToDo2 = map (\ (m,list) -> (m,(delete mod list))) modulesToDo
in reduceDependencies modulesToDo2 mods
--------------------------------------------------------------------------
--- This is the main module of the analysis system.
--- One can either use the 'main' operation to start the system
--- in "server mode" or "batch mode" or use one of the operations below
--- to use the analysis system in another Curry program.
---
--- @author Heiko Hoffmann, Michael Hanus
--- @version March 2013
--------------------------------------------------------------------------
module AnalysisServer(main,analyzeModuleForBrowser,analyzeGeneric,
analyzeInterface) where
import FlatCurry(QName)
import Socket(Socket(..),listenOnFresh,sClose,waitForSocketAccept)
import IO
import ReadShowTerm(readQTerm,showQTerm)
import System(system,sleep,setEnviron,getArgs)
import AnalysisCollection
import ServerFormats
import ServerFunctions(WorkerMessage(..))
import Configuration
import GenericProgInfo(ProgInfo,publicListFromProgInfo)
import Analysis(Analysis)
-- Messages to communicate with the analysis server from external programs.
data AnalysisServerMessage =
GetAnalysis
| AnalyzeModule String String String Bool
| AnalyzeEntity String String String String
| StopServer
| SetCurryPath String
| ParseError
--- Main function to start the server.
--- Without any program arguments, the server is started on a socket.
--- Otherwise, it is started in batch mode to analyze a module.