Commit 8bf94437 authored by Michael Hanus's avatar Michael Hanus
Browse files

currydoc removed from tools, cpm updated

parent b275300e
......@@ -34,10 +34,6 @@ make_analysis:
make_CASS: | make_analysis
@$(MAKE) now_$@
make_currydoc: | make_analysis make_CASS \
make_currypp # avoid conflicts in analysis
@$(MAKE) now_$@
make_currypp: | make_analysis make_CASS make_currycheck
@$(MAKE) now_$@
......
......@@ -896,4 +896,35 @@ directories \code{test} and \code{examples} could be as follows:
\end{description}
\section{Error Recovery}
\label{sec:recovery}
There might occur situations when your package or repository
is in an inconsistent state, e.g., when you manually changed
some internal files or such files have been inadvertently changed or
deleted, or a package is broken due to an incomplete download.
Since CPM checks these files, CPM might exit with an error message
that something is wrong.
In such cases, it might be a good idea to clean up your package file system.
Here are some suggestions how to do this:
\begin{description}
\item[\code{cpm clean}]~\\
This command cleans the current package from
generated auxiliariy files (see Section~\ref{sec:cmd-reference}).
Then you can re-install the package and packages on which it depends
by the command \code{cpm install}.
\item[\code{rm -rf \$HOME/.cpm/packages}] ~\\
This cleans all packages which have been previously installed
in the global package cache (see Section~\ref{sec:internals}).
Such an action might be reasonable in case of some download failure.
After clearing the global package cache, all necessary packages
are downloaded again when they are needed.
\item[\code{rm -rf \$HOME/.cpm/index}] ~\\
This removes the central package index of CPM
(see Section~\ref{sec:internals}).
You can simply re-install the newest version of this index
by the command \code{cpm update}.
\end{description}
\end{document}
......@@ -556,10 +556,14 @@ checkout (CheckoutOptions pkg (Just ver) _) cfg repo gc =
Just p -> acquireAndInstallPackageWithDependencies cfg repo gc p |>
checkoutPackage cfg repo gc p
-- Installs the binary provided by a package.
-- This is done by checking out the package into CPM's bin_packages
-- cache (default: $HOME/.cpm/bin_packages, see bin_package_path
-- in .cpmrc configuration file) and then install this package.
--- Installs the binary provided by a package.
--- This is done by checking out the package into CPM's bin_packages
--- cache (default: $HOME/.cpm/bin_packages, see bin_package_path
--- in .cpmrc configuration file) and then install this package.
---
--- Note: the installed package should not be cleaned or removed
--- after the installation since its execution might refer (via the
--- config module) to some data stored in the package.
installbin :: CheckoutOptions -> Config -> Repository -> GlobalCache
-> IO (ErrorLogger ())
installbin opts cfg repo gc = do
......@@ -569,8 +573,7 @@ installbin opts cfg repo gc = do
(checkout opts cfg repo gc |>
log Debug ("Change into directory " ++ copkgdir) |>
(setCurrentDirectory copkgdir >> succeedIO ()) |>
install (InstallOptions Nothing Nothing False True) cfg repo gc |>
cleanPackage Debug)
install (InstallOptions Nothing Nothing False True) cfg repo gc )
where
binpkgdir = binPackageDir cfg
copkgdir = binpkgdir </> coPackage opts
......
----------------------------------------------------------------------
--- Implementation of CurryDoc, a utility for the automatic
--- generation of HTML documentation from Curry programs.
---
--- @author Michael Hanus, Jan Tikovsky
--- @version June 2015
----------------------------------------------------------------------
-- * All comments to be put into the HTML documentation must be
-- prefixed by "--- " (also in literate programs!).
--
-- * The comment of a module must occur before the first "module" or
-- "import" line of this module.
--
-- * The comment of a function or datatype must occur before the
-- first definition of this function or datatype.
--
-- * The comments can contain at the end several special comments:
-- @cons id comment --> a comment for a constructor of a datatype
-- @param id comment --> comment for function parameter id
-- (list all parameters in left-to-right order)
-- @return comment --> comments for the return value of a function
-- @author comment --> the author of a module (only in module comments)
-- @version comment --> the version of a module (only in module comments)
--
-- * Current restriction: doesn't properly work for infix operator definitions
-- without a type definition (so it should be always included)
module CurryDoc where
import AbstractCurry.Files
import Directory
import Distribution
import FileGoodies
import FilePath ((</>), (<.>), dropFileName, takeFileName)
import FlatCurry.Types
import FlatCurry.Files
import FlatCurry.Read(readFlatCurryWithImports)
import Function
import List
import Maybe(fromJust)
import System
import Time
import AnalysisServer(initializeAnalysisSystem,analyzeInterface)
import Deterministic
import TotallyDefined
import Indeterministic
import SolutionCompleteness
import CurryDocAnaInfo
import CurryDocParams
import CurryDocRead
import CurryDocHtml
import CurryDocTeX
import CurryDocCDoc
import CurryDocConfig
--------------------------------------------------------------------------
-- Global definitions:
greeting :: String
greeting = "CurryDoc (" ++ currydocVersion ++ ") - the Curry Documentation Tool\n"
-- Directory where include files for generated documention (e.g., icons,
-- css, tex includes) are stored:
includeDir :: String
includeDir = installDir </> "include"
--------------------------------------------------------------------------
-- Check arguments and call main function:
main :: IO ()
main = do
args <- getArgs
processArgs defaultCurryDocParams args
processArgs :: DocParams -> [String] -> IO ()
processArgs params args = case args of
-- no markdown
("--nomarkdown":margs) -> processArgs (setMarkDown False params) margs
-- documentation type
("--html" :margs) -> processArgs (setDocType HtmlDoc params) margs
("--tex" :margs) -> processArgs (setDocType TexDoc params) margs
("--cdoc" :margs) -> processArgs (setDocType CDoc params) margs
-- HTML without index
["--noindexhtml",docdir,modname] ->
makeCompleteDoc (setIndex False (setDocType HtmlDoc params))
True docdir (stripCurrySuffix modname)
-- HTML index only
("--onlyindexhtml":docdir:modnames) ->
makeIndexPages docdir (map stripCurrySuffix modnames)
("--libsindexhtml":docdir:modnames) ->
makeSystemLibsIndex docdir modnames
(('-':_):_) -> putStrLn usageMessage
-- module
[modname] ->
makeCompleteDoc params (docType params == HtmlDoc)
("DOC_" ++ stripCurrySuffix (takeFileName modname))
(stripCurrySuffix modname)
-- docdir + module
[docdir,modname] ->
makeCompleteDoc params (docType params == HtmlDoc) docdir
(stripCurrySuffix modname)
_ -> putStrLn usageMessage
usageMessage :: String
usageMessage = unlines
[ "ERROR: Illegal arguments for currydoc"
, "Usage: curry doc [--nomarkdown] [--html|--tex|--cdoc] [<doc directory>] <module_name>"
, " curry doc [--nomarkdown] --noindexhtml <doc directory> <module_name>"
, " curry doc --onlyindexhtml <doc directory> <module_names>"
, " curry doc --libsindexhtml <doc directory> <module_names>"
]
-- create directory if not existent:
createDir :: String -> IO ()
createDir dir = do
exdir <- doesDirectoryExist dir
unless exdir $ system ("mkdir " ++ dir) >> done
--------------------------------------------------------------------------
--- The main function of the CurryDoc utility.
--- @param withindex - True if the index pages should also be generated
--- @param recursive - True if the documentation for the imported modules
--- should be also generated (if necessary)
--- @param docdir - the directory name containing all documentation files
--- @param modname - the name of the main module to be documented
makeCompleteDoc :: DocParams -> Bool -> String -> String -> IO ()
makeCompleteDoc docparams recursive reldocdir modpath = do
putStrLn greeting
docdir <- makeAbsolute reldocdir
prepareDocDir (docType docparams) docdir
lookupModuleSourceInLoadPath modpath >>=
maybe (error $ "Source code of module '"++modpath++"' not found!")
(\ (moddir,_) -> do
let modname = takeFileName modpath
setCurrentDirectory moddir
-- parsing source program:
callFrontend FCY modname
-- generate abstract curry representation
callFrontend ACY modname
-- when constructing CDOC the imported modules don't have to be read
-- from the FlatCurry file
(alltypes,allfuns) <- getProg modname $ docType docparams
makeDocIfNecessary docparams recursive docdir modname
when (withIndex docparams) $ do
genMainIndexPage docdir [modname]
genFunctionIndexPage docdir allfuns
genConsIndexPage docdir alltypes
-- change access rights to readable for everybody:
system ("chmod -R go+rX "++docdir)
putStrLn ("Documentation files written into directory "++docdir) )
where
getProg modname HtmlDoc = readTypesFuncsWithImports modname
getProg modname TexDoc = readTypesFuncsWithImports modname
getProg modname CDoc = do (Prog _ _ types funs _) <- readFlatCurry modname
return (types,funs)
--- Transform a file path into an absolute file path:
makeAbsolute :: String -> IO String
makeAbsolute f =
if isAbsolute f
then return f
else do curdir <- getCurrentDirectory
return (curdir </> f)
--- Generate only the index pages for a list of (already compiled!) modules:
makeIndexPages :: String -> [String] -> IO ()
makeIndexPages docdir modnames = do
putStrLn greeting
prepareDocDir HtmlDoc docdir
(alltypes,allfuns) <- mapIO readTypesFuncs modnames >>= return . unzip
genMainIndexPage docdir modnames
genFunctionIndexPage docdir (concat allfuns)
genConsIndexPage docdir (concat alltypes)
-- change access rights to readable for everybody:
system ("chmod -R go+rX "++docdir)
done
where
readTypesFuncs modname = do
fcyfile <- getFlatCurryFileInLoadPath modname
(Prog _ _ types funs _) <- readFlatCurryFile fcyfile
return (types,funs)
--- Generate a system library index page categorizing the given
--- (already compiled!) modules
makeSystemLibsIndex :: String -> [String] -> IO ()
makeSystemLibsIndex docdir modnames = do
-- generate index pages (main index, function index, constructor index)
makeIndexPages docdir modnames
putStrLn ("Categorizing modules ...")
modInfos <- mapIO getModInfo modnames
putStrLn ("Grouping modules by categories ...")
let grpMods = map sortByName $ groupByCategory $ sortByCategory modInfos
cats = sortBy (<=) $ nub $ map fst3 modInfos
genSystemLibsPage docdir cats grpMods
where
fst3 (x,_,_) = x
snd3 (_,y,_) = y
sortByCategory = sortBy ((<=) `on` fst3)
groupByCategory = groupBy ((==) `on` fst3)
sortByName = sortBy ((<=) `on` snd3)
getModInfo :: String -> IO (Category,String,String)
getModInfo modname = do
mmodsrc <- lookupModuleSourceInLoadPath modname
case mmodsrc of
Nothing -> error $ "Source code of module '"++modname++"' not found!"
Just (_,progname) -> do
(modcmts,_) <- readComments progname
let (modcmt,catcmts) = splitComment modcmts
category = readCategory $ getCommentType "category" catcmts
return (category,modname,firstPassage modcmt)
-- create documentation directory (if necessary) with gifs and stylesheets:
prepareDocDir :: DocType -> String -> IO ()
prepareDocDir HtmlDoc docdir = do
createDir docdir
--putStrLn ("Copying icons into documentation directory \""++docdir++"\"...")
-- copying all icons:
--copyIncludeIfPresent docdir "currydocicons/*.gif"
-- copy style sheet:
copyIncludeIfPresent docdir "currydoc.css"
prepareDocDir TexDoc docdir = do
createDir docdir
putStrLn $ "Copy macros into documentation directory \""++docdir++"\"..."
copyIncludeIfPresent docdir "currydoc.tex"
prepareDocDir CDoc docdir = do
createDir docdir
putStrLn ("Directory was succesfully created")
copyIncludeIfPresent :: String -> String -> IO ()
copyIncludeIfPresent docdir inclfile = do
existIDir <- doesDirectoryExist includeDir
when existIDir $
system ("cp "++includeDir++"/"++inclfile++" "++docdir) >> done
-- read and generate all analysis infos:
readAnaInfo :: String -> IO AnaInfo
readAnaInfo modname = do
initializeAnalysisSystem
nondet <- analyzeInterface nondetAnalysis modname >>= stopIfError
complete <- analyzeInterface patCompAnalysis modname >>= stopIfError
indet <- analyzeInterface indetAnalysis modname >>= stopIfError
solcomp <- analyzeInterface solcompAnalysis modname >>= stopIfError
return (AnaInfo (\qn -> nondet qn == NDet) complete indet solcomp)
where
stopIfError (Right err) = error ("Analysis error: "++err)
stopIfError (Left results) =
return (\qn -> maybe (error $ "No analysis result for function "++show qn)
id
(lookup qn results))
-- generate documentation for a single module:
makeDoc :: DocParams -> Bool -> String -> String -> IO ()
makeDoc docparams recursive docdir modname = do
Just (_,progname) <- lookupModuleSourceInLoadPath modname
putStrLn ("Reading comments from file '"++progname++"'...")
(modcmts,progcmts) <- readComments progname
putStrLn ("Reading analysis information for module \""++modname++"\"...")
anainfo <- readAnaInfo modname
makeDocWithComments (docType docparams) docparams recursive docdir
anainfo modname modcmts progcmts
makeDocWithComments :: DocType -> DocParams -> Bool -> String -> AnaInfo
-> String -> String -> [(SourceLine,String)] -> IO ()
makeDocWithComments HtmlDoc docparams recursive docdir anainfo modname
modcmts progcmts = do
-- ensure that the AbstractCurry file for the module exists
loadpath <- getLoadPathForModule modname
modpath <- lookupFileInPath (abstractCurryFileName modname) [""] loadpath
unless (modpath /= Nothing) $ callFrontend ACY modname
writeOutfile docparams recursive docdir modname
(generateHtmlDocs docparams anainfo modname modcmts progcmts)
translateSource2ColoredHtml docdir modname
writeOutfile (DocParams CDoc False False) False docdir modname
(generateCDoc modname modcmts progcmts anainfo)
makeDocWithComments TexDoc docparams recursive docdir anainfo modname
modcmts progcmts = do
writeOutfile docparams recursive docdir modname
(generateTexDocs docparams anainfo modname modcmts progcmts)
makeDocWithComments CDoc docparams recursive docdir anainfo modname
modcmts progcmts = do
writeOutfile docparams recursive docdir modname
(generateCDoc modname modcmts progcmts anainfo)
--- Generates the documentation for a module if it is necessary.
--- I.e., the documentation is generated if no previous documentation
--- file exists or if the existing documentation file is older than
--- the FlatCurry file.
makeDocIfNecessary :: DocParams -> Bool -> String -> String -> IO ()
makeDocIfNecessary docparams recursive docdir modname = do
let docfile = docdir </> modname ++
(if docType docparams == HtmlDoc then ".html" else ".tex")
docexists <- doesFileExist docfile
if not docexists
then copyOrMakeDoc docparams recursive docdir modname
else do
ctime <- getFlatCurryFileInLoadPath modname >>= getModificationTime
dftime <- getModificationTime docfile
if compareClockTime ctime dftime == GT
then copyOrMakeDoc docparams recursive docdir modname
else when recursive $ do
imports <- getImports modname
mapIO_ (makeDocIfNecessary docparams recursive docdir) imports
-- get imports of a module by reading the interface, if possible:
getImports :: String -> IO [String]
getImports modname = do
mbfintfile <- getLoadPathForModule modname >>=
lookupFileInPath (flatCurryIntName modname) [""]
(Prog _ imports _ _ _) <- maybe
(getFlatCurryFileInLoadPath modname >>=
readFlatCurryFile)
readFlatCurryFile
mbfintfile
return imports
copyOrMakeDoc :: DocParams -> Bool -> String -> String -> IO ()
copyOrMakeDoc docparams recursive docdir modname = do
hasCopied <- copyDocIfPossible docparams docdir modname
unless hasCopied $ makeDoc docparams recursive docdir modname
--- Copy the documentation file from standard documentation directoy "CDOC"
--- (used for documentation of system libraries) if possible.
--- Returns true if the copy was possible.
copyDocIfPossible :: DocParams -> String -> String -> IO Bool
copyDocIfPossible docparams docdir modname =
if docType docparams == TexDoc
then return False -- ignore copying for TeX docs
else do
mdir <- lookupModuleSourceInLoadPath modname >>= return . fst . fromJust
let docprogname = mdir </> "CDOC" </> modname
docHtmlFile = docprogname <.> "html"
docexists <- doesFileExist docHtmlFile
if not docexists
then return False
else do
ctime <- getModificationTime (mdir </> flatCurryFileName modname)
htime <- getModificationTime docHtmlFile
if compareClockTime ctime htime == GT
then return False
else do
putStrLn ("Copying doc file from " ++ docHtmlFile)
system ("cp " ++ docHtmlFile ++ ' ':docdir)
system ("cp " ++ docprogname ++ "_curry.html "++docdir)
return True
-----------------------------------------------------------------------
-- auxiliaries:
-- reads all types and function declarations (also imported ones) of
-- a module:
readTypesFuncsWithImports :: String -> IO ([TypeDecl],[FuncDecl])
readTypesFuncsWithImports modname = do
allprogs <- readFlatCurryWithImports modname
let (ts,fs) = unzip (map (\ (Prog _ _ types funs _) -> (types,funs)) allprogs)
return (concat ts, concat fs)
-- get the associated file extenstion from DocType
fileExtension :: DocType -> String
fileExtension HtmlDoc = "html"
fileExtension TexDoc = "tex"
fileExtension CDoc = "cdoc"
-- harmonized writeFile function for all docType
writeOutfile :: DocParams -> Bool -> String -> String -> IO String -> IO ()
writeOutfile docparams recursive docdir modname generate = do
doc <- generate
imports <- getImports modname
let outfile = docdir </> modname <.> fileExtension (docType docparams)
putStrLn ("Writing documentation to \"" ++ outfile ++ "\"...")
writeFile outfile doc
when recursive $
mapIO_ (makeDocIfNecessary docparams recursive docdir) imports
-- -----------------------------------------------------------------------
----------------------------------------------------------------------
--- Datatype and operations to handle analysis information in CurryDoc.
---
--- @author Michael Hanus
--- @version April 2016
----------------------------------------------------------------------
module CurryDocAnaInfo where
import FlatCurry.Types
import TotallyDefined(Completeness(..))
-----------------------------------------------------------------------
-- Datatype for passing analysis results:
data AnaInfo =
AnaInfo (QName -> Bool) -- non-deterministic?
(QName -> Completeness) -- completely defined?
(QName -> Bool) -- indeterministically defined?
(QName -> Bool) -- solution complete?
getNondetInfo :: AnaInfo -> QName -> Bool
getNondetInfo (AnaInfo oi _ _ _) = oi
getCompleteInfo :: AnaInfo -> QName -> Completeness
getCompleteInfo (AnaInfo _ cdi _ _) = cdi
getIndetInfo :: AnaInfo -> QName -> Bool
getIndetInfo (AnaInfo _ _ idi _) = idi
getOpCompleteInfo :: AnaInfo -> QName -> Bool
getOpCompleteInfo (AnaInfo _ _ _ oci) = oci
-- Translate a standard analysis result into functional form:
getFunctionInfo :: [(QName,a)] -> QName -> a
getFunctionInfo [] n = error ("No analysis result for function "++show n)
getFunctionInfo ((fn,fi):fnis) n = if fn == n then fi
else getFunctionInfo fnis n
--------------------------------------------------------------------------
----------------------------------------------------------------------
--- Functions to generate documentation in "CDoc" format.
---
--- @author Sandra Dylus
--- @version November 2015
----------------------------------------------------------------------
module CurryDocCDoc where
import CurryDocAnaInfo
import CurryDocParams
import CurryDocRead
import FlatCurry.Types
import FlatCurry.Files
import FlatCurry.FlexRigid
import List
import ReadShowTerm
generateCDoc :: String -> String -> [(SourceLine,String)] -> AnaInfo
-> IO String
generateCDoc modName modCmts progCmts anaInfo = do
fcyName <- getFlatCurryFileInLoadPath modName
Prog _ _ types functions _ <- readFlatCurryFile fcyName
let modInfo = ModuleInfo modName (author avCmts) mCmts
funcInfo (Func qName@(mName, fName) _ _ tExpr rule) =
FunctionInfo fName
tExpr
mName
(funcComment fName progCmts)
(getNondetInfo anaInfo qName)
(flexRigid rule)
typeInfo (Type (mName, tName) _ vars consDecl) =
TypeInfo tName
(map consSignature (filter (\(Cons _ _ vis _) -> vis == Public) consDecl))
vars
mName
(dataComment tName progCmts)
False
typeInfo (TypeSyn qName@(mName, tName) _ vars tExpr) =
TypeInfo tName
[(qName, [tExpr])]
vars
mName
(dataComment tName progCmts)
True
(mCmts, avCmts) = splitComment modCmts
funcInfos = map funcInfo (filter (\(Func _ _ vis _ _) -> vis == Public) functions)
typeInfos = map typeInfo (concatMap filterT types)
putStrLn $ "Writing " ++ modName ++ ".cdoc file"
return $ showTerm (CurryInfo modInfo funcInfos typeInfos)
where
filterT f@(Type _ vis _ _) = if vis == Public then [f] else []
filterT f@(TypeSyn _ vis _ _) = if vis == Public then [f] else []
funcComment :: String -> [(SourceLine,String)] -> String
funcComment str = fst . splitComment . getFuncComment str
dataComment :: String -> [(SourceLine,String)] -> String
dataComment str = fst . splitComment . getDataComment str
flexRigid :: Rule -> FlexRigidResult
flexRigid (Rule _ expr) = getFlexRigid expr
flexRigid (External _) = UnknownFR
-- the name
-- the author
-- the description
data ModuleInfo = ModuleInfo String String String
-- the module
-- the corresponding functions
-- the corresponding data and type declaration
data CurryInfo = CurryInfo ModuleInfo [FunctionInfo] [TypeInfo]
-- the name
-- the signature
-- the corresponding module
-- the description
-- True if property ist defined non-deterministically
-- the flex/rigid status
data FunctionInfo = FunctionInfo String TypeExpr String String Bool FlexRigidResult
-- the name
-- the signature (true indicates a type synonym, false a data type)
-- the corresponding module
-- the description
data TypeInfo = TypeInfo String [(QName, [TypeExpr])] [TVarIndex] String String Bool
-- auxilieres --------------------------------------------------------
author :: [(String, String)] -> String
author av = concat $ getCommentType "author" av
-- generate data and type constructors
consSignature :: ConsDecl -> (QName, [TypeExpr])
consSignature (Cons (mName, cName) _ _ tExprList) = ((mName, cName), tExprList)
----------------------------------------------------------------------
--- This module contains some configuration parameters for
--- the CurryDoc tool.
---
--- @author Michael Hanus, Jan Tikovsky
--- @version April 2016
----------------------------------------------------------------------
module CurryDocConfig where
import Distribution(curryCompiler)
--- Version of currydoc
currydocVersion :: String
currydocVersion = "Version 0.8.1 of April 24, 2016"
--- The URL of the base directory containing the styles, images, etc.
styleBaseURL :: String
styleBaseURL = if curryCompiler=="pakcs"
then "https://www.informatik.uni-kiel.de/~pakcs/bt3"
else "https://www-ps.informatik.uni-kiel.de/kics2/bt3"
--- The URL of the base directory containing the styles, images, etc.
currySystemURL :: String
currySystemURL = if curryCompiler=="pakcs"
then "https://www.informatik.uni-kiel.de/~pakcs"
else "https://www-ps.informatik.uni-kiel.de/kics2"
--- The name of this Curry system.
currySystem :: String
currySystem = if curryCompiler=="pakcs" then "PAKCS" else "KiCS2"
--- The URL of the API search
currygleURL :: String
currygleURL = "https://www-ps.informatik.uni-kiel.de/kics2/currygle/"
--- The URL of the Curry homepage
curryHomeURL :: String
curryHomeURL = "http://www.curry-language.org"
This diff is collapsed.
-- Auxuiliaries to handle the parameters of the CurryDoc tool.