Commit b0c4e678 authored by Michael Hanus 's avatar Michael Hanus

CPM updated

parent 23540461
......@@ -10,7 +10,10 @@ optimize/.cpm/packages/cass-2.0.0
optimize/.cpm/packages/cass-analysis-2.0.0
optimize/.cpm/packages/flatcurry-2.0.0
optimize/.cpm/packages/csv-1.0.0
optimize/.cpm/packages/scc-0.0.1
optimize/.cpm/packages/xml-2.0.0
optimize/.cpm/packages/frontend-exec-0.0.1
optimize/.cpm/packages/propertyfile-0.0.1
# executables
cpm/src/CPM.Main
......
......@@ -1043,6 +1043,41 @@ of the current package or in the meta-package
The option \ccode{--force} allows to overwrite existing dependencies
in the package description file.
\item[\fbox{\code{upload [--notagging] [--force]}}]
Uploads the current package to the central package index
so that it can be used by other developers via CPM
(if they update their local copy of the central package index
by \ccode{cypm update}).
For security reasons (this will be weakened in the future),
the package must have a source specification
(see Section~\ref{sec:publishing-a-package})
of the following form:
%
\begin{lstlisting}
{
...,
"source": {
"git": "$\ldots$git.ps.informatik.uni-kiel.de/curry-packages/$\ldots$.git",
"tag": "$\$$version"
}
}
\end{lstlisting}
%
Thus, the source is managed as a Git repository which is stored
at the server \code{git.ps.informatik.uni-kiel.de}
in group \code{curry-packages} and has an automatic version tag.
Unless the option \code{--nottagging} is given,
the version tag wil be automatically set in the local repository
(and pushed to the remote repository, i.e., one should have write access
to the remote repository).
Then the remote repository will be cloned and tested (by \ccode{cypm test}).
If this is successful, the package specification of the repository
will be added to the central package index (by a web service
of the central package index).
The option \ccode{--force} allows to overwrite
an existing version in the central package index.
\item[\fbox{\code{clean}}] Cleans the current package from the
generated auxiliary files, e.g., intermediate Curry files,
installed dependent packages, etc.
......
......@@ -12,18 +12,20 @@ module CPM.AbstractCurry
, applyModuleRenames
) where
import Distribution ( FrontendTarget (..), FrontendParams (..), defaultParams
, callFrontendWithParams, setQuiet, setFullPath
, sysLibPath, inCurrySubdir, modNameToPath
import Distribution ( sysLibPath, inCurrySubdir, modNameToPath
, inCurrySubdirModule, lookupModuleSource )
import List ( intercalate, nub )
import FilePath ( (</>), (<.>), takeFileName, replaceExtension )
import List ( intercalate, nub )
import FilePath ( (</>), (<.>), takeFileName, replaceExtension )
import System
import AbstractCurry.Files ( readAbstractCurryFile, writeAbstractCurryFile )
import AbstractCurry.Pretty ( showCProg )
import AbstractCurry.Select ( imports )
import AbstractCurry.Transform
import AbstractCurry.Types
import System
import System.FrontendExec ( FrontendTarget (..), FrontendParams (..)
, defaultParams, callFrontendWithParams
, setQuiet, setFullPath )
import CPM.ErrorLogger
import qualified CPM.PackageCache.Runtime as RuntimeCache
......
......@@ -23,8 +23,10 @@ import Maybe ( mapMaybe )
import PropertyFile ( readPropertyFile )
import Read ( readInt )
import System.Path ( getFileInPath )
import CPM.ErrorLogger
import CPM.FileUtil ( ifFileExists, getFileInPath )
import CPM.FileUtil ( ifFileExists )
import CPM.Helpers ( strip )
--- The default location of the central package index.
......@@ -50,8 +52,8 @@ data Config = Config {
, homePackageDir :: String
--- The executable of the Curry system used to compile and check packages
, curryExec :: String
--- The compiler version (name,major,minor) used to compile packages
, compilerVersion :: (String,Int,Int)
--- The compiler version (name,major,minor,rev) used to compile packages
, compilerVersion :: (String,Int,Int,Int)
--- The version of the base libraries used by the compiler
, compilerBaseVersion :: String
--- The version of the base libraries to be used for package installations
......@@ -71,7 +73,8 @@ defaultConfig = Config
, curryExec = Dist.installDir </> "bin" </> Dist.curryCompiler
, compilerVersion = ( Dist.curryCompiler
, Dist.curryCompilerMajorVersion
, Dist.curryCompilerMinorVersion )
, Dist.curryCompilerMinorVersion
, Dist.curryCompilerRevisionVersion )
, compilerBaseVersion = Dist.baseVersion
, baseVersion = ""
}
......@@ -94,8 +97,13 @@ showConfiguration cfg = unlines
--- Shows the compiler version in the configuration.
showCompilerVersion :: Config -> String
showCompilerVersion cfg =
let (cname,cmaj,cmin) = compilerVersion cfg
in cname ++ ' ' : show cmaj ++ "." ++ show cmin
let (cname,cmaj,cmin,crev) = compilerVersion cfg
in cname ++ ' ' : showVersionNumer (cmaj,cmin,crev)
--- Shows a version consisting of major/minor,revision number.
showVersionNumer :: (Int,Int,Int) -> String
showVersionNumer (maj,min,rev) =
show maj ++ "." ++ show min ++ "." ++ show rev
--- Sets an existing compiler executable in the configuration.
--- Try to use the predefined CURRYBIN value.
......@@ -119,8 +127,8 @@ setAppPackageDir cfg
| null (appPackageDir cfg)
= do homedir <- getHomeDirectory
let cpmdir = homedir </> ".cpm"
(cname,cmaj,cmin) = compilerVersion cfg
cmpname = cname ++ "_" ++ show cmaj ++ "." ++ show cmin
(cname,cmaj,cmin,crev) = compilerVersion cfg
cmpname = cname ++ "_" ++ showVersionNumer (cmaj,cmin,crev)
return cfg { appPackageDir = cpmdir </> "apps_" ++ cmpname }
| otherwise = return cfg
......@@ -132,9 +140,9 @@ setHomePackageDir cfg
let cpmdir = homedir </> ".cpm"
excpmdir <- doesDirectoryExist cpmdir
if excpmdir
then let (cname,cmaj,cmin) = compilerVersion cfg
cvname = cname ++ "-" ++ show cmaj ++ "." ++ show cmin
homepkgdir = cpmdir </> cvname ++ "-homepackage"
then let (cname,cmaj,cmin,crev) = compilerVersion cfg
cvname = cname ++ "-" ++ showVersionNumer (cmaj,cmin,crev)
homepkgdir = cpmdir </> cvname ++ "-homepackage"
in return cfg { homePackageDir = homepkgdir }
else return cfg
| otherwise = return cfg
......@@ -154,10 +162,11 @@ setCompilerVersion cfg0 = do
let cname = strip sname
cvers = strip svers
bvers = strip sbver
(majs:mins:_) = split (=='.') cvers
debugMessage $ "Compiler version: " ++ cname ++ " " ++ cvers
(majs:mins:revs:_) = split (=='.') cvers
debugMessage $ unwords ["Compiler version:",cname,cvers]
debugMessage $ "Base lib version: " ++ bvers
return cfg { compilerVersion = (cname, readInt majs, readInt mins)
return cfg { compilerVersion = (cname, readInt majs,
readInt mins, readInt revs)
, compilerBaseVersion = bvers
, baseVersion = if null initbase
then bvers
......@@ -181,7 +190,8 @@ setCompilerVersion cfg0 = do
return (sname,svers,sbver)
currVersion = (Dist.curryCompiler, Dist.curryCompilerMajorVersion,
Dist.curryCompilerMinorVersion)
Dist.curryCompilerMinorVersion
, Dist.curryCompilerRevisionVersion)
--- Reads the .cpmrc file from the user's home directory (if present) and
--- merges its contents and some given default settings (first argument)
......
......@@ -12,7 +12,6 @@ module CPM.FileUtil
, linkTarget
, copyDirectoryFollowingSymlinks
, quote
, fileInPath, getFileInPath
, tempDir
, inTempDir
, inDirectory
......@@ -81,27 +80,6 @@ linkTarget link = do
quote :: String -> String
quote s = "\"" ++ s ++ "\""
--- Checks whether a file exists in one of the directories on the PATH.
fileInPath :: String -> IO Bool
fileInPath file = do
path <- getEnviron "PATH"
let dirs = splitOn ":" path
(liftIO (any id)) $ mapIO (doesFileExist . (</> file)) dirs
--- Checks whether a file exists in one of the directories on the PATH
--- and returns absolute path, otherwise returns `Nothing`.
getFileInPath :: String -> IO (Maybe String)
getFileInPath file = do
path <- getEnviron "PATH"
checkPath (splitOn ":" path)
where
checkPath [] = return Nothing
checkPath (dir:dirs) = do
let dirfile = dir </> file
ifFileExists dirfile
(getAbsolutePath dirfile >>= return . Just)
(checkPath dirs)
--- Gets CPM's temporary directory.
tempDir :: IO String
tempDir = do
......
......@@ -15,6 +15,7 @@ import Either
import FilePath ( (</>), splitSearchPath, replaceExtension, takeExtension
, pathSeparator, isPathSeparator )
import IO ( hFlush, stdout )
import IOExts ( evalCmd )
import List ( groupBy, intercalate, isPrefixOf, isSuffixOf, nub, split
, splitOn )
import Sort ( sortBy )
......@@ -23,12 +24,13 @@ import System ( getArgs, getEnviron, setEnviron, unsetEnviron, exitWith
import Boxes ( table, render )
import OptParse
import System.Path ( fileInPath )
import Text.CSV ( showCSV )
import CPM.ErrorLogger
import CPM.FileUtil ( fileInPath, joinSearchPath, safeReadFile, whenFileExists
, ifFileExists, inDirectory, removeDirectoryComplete
, copyDirectory, quote )
import CPM.FileUtil ( joinSearchPath, safeReadFile, whenFileExists
, ifFileExists, inDirectory, inTempDir, recreateDirectory
, removeDirectoryComplete, copyDirectory, quote, tempDir )
import CPM.Config ( Config (..)
, readConfigurationWith, showCompilerVersion
, showConfiguration )
......@@ -37,7 +39,7 @@ import CPM.PackageCache.Global ( GlobalCache, readGlobalCache, allPackages
, uninstallPackage, packageInstalled )
import CPM.Package
import CPM.Package.Helpers ( cleanPackage, getLocalPackageSpec
, renderPackageInfo )
, renderPackageInfo, installPackageSourceTo )
import CPM.Resolution ( isCompatibleToCompiler, showResult )
import CPM.Repository ( Repository, findVersion, listPackages
, findAllVersions, findLatestVersion
......@@ -56,7 +58,7 @@ cpmBanner :: String
cpmBanner = unlines [bannerLine,bannerText,bannerLine]
where
bannerText =
"Curry Package Manager <curry-language.org/tools/cpm> (version of 15/11/2018)"
"Curry Package Manager <curry-language.org/tools/cpm> (version of 23/11/2018)"
bannerLine = take (length bannerText) (repeat '-')
main :: IO ()
......@@ -106,6 +108,7 @@ runWithArgs opts = do
Diff o -> diffCmd o config
Checkout o -> checkoutCmd o config
Install o -> installCmd o config
Upload o -> uploadCmd o config
Clean -> cleanPackage config Info
mapIO showLogEntry msgs
let allOk = all (levelGte Info) (map logLevelOf msgs) &&
......@@ -141,6 +144,7 @@ data Command
| Diff DiffOptions
| New NewOptions
| Clean
| Upload UploadOptions
data ConfigOptions = ConfigOptions
{ configAll :: Bool -- show also installed packages?
......@@ -203,6 +207,12 @@ data NewOptions = NewOptions
data UpdateOptions = UpdateOptions
{ indexURLs :: [String] -- the URLs of additional index repositories
, cleanCache :: Bool -- clean also repository cache?
}
data UploadOptions = UploadOptions
{ setTag :: Bool -- set the tag in the current repository?
, forceUpdate :: Bool -- force update if package with same version exists
}
data ExecOptions = ExecOptions
......@@ -295,7 +305,12 @@ newOpts s = case optCommand s of
updateOpts :: Options -> UpdateOptions
updateOpts s = case optCommand s of
Update opts -> opts
_ -> UpdateOptions []
_ -> UpdateOptions [] True
uploadOpts :: Options -> UploadOptions
uploadOpts s = case optCommand s of
Upload opts -> opts
_ -> UploadOptions True False
execOpts :: Options -> ExecOptions
execOpts s = case optCommand s of
......@@ -433,7 +448,12 @@ optionParser allargs = optParser
<|> command "add"
(help "Add a package (as dependency or to the local repository)")
Right
addArgs ) )
addArgs
<|> command "upload"
(help "Upload current package to package server")
(\a -> Right $ a { optCommand = Upload (uploadOpts a) })
uploadArgs
) )
where
configArgs =
flag (\a -> Right $ a { optCommand = Config (configOpts a)
......@@ -531,6 +551,23 @@ optionParser allargs = optParser
<> long "url"
<> metavar "URL"
<> help "URL of the central package index" )
<.> flag (\a -> Right $ a { optCommand = Update (updateOpts a)
{ cleanCache = False } })
( short "c"
<> long "cache"
<> help "Do not clean global package cache" )
uploadArgs =
flag (\a -> Right $ a { optCommand =
Upload (uploadOpts a) { setTag = False } })
( short "t"
<> long "notagging"
<> help "Do not tag git repository with current version" )
<.> flag (\a -> Right $ a { optCommand =
Upload (uploadOpts a) { forceUpdate = True } })
( short "f"
<> long "force"
<> help "Force, i.e., overwrite existing package version" )
execArgs =
rest (\_ a -> Right $ a { optCommand = Exec (execOpts a)
......@@ -769,7 +806,7 @@ updateCmd opts cfg = do
then cfg
else cfg { packageIndexURL = head (indexURLs opts) }
-- TODO: allow merging from several package indices
checkRequiredExecutables >> updateRepository cfg'
checkRequiredExecutables >> updateRepository cfg' (cleanCache opts)
------------------------------------------------------------------------------
-- `deps` command:
......@@ -903,7 +940,7 @@ installExecutable cfg pkg =
getLogLevel >>= \lvl ->
getEnviron "PATH" >>= \path ->
log Info ("Compiling main module: " ++ mainmod) |>
let (cmpname,_,_) = compilerVersion cfg
let (cmpname,_,_,_) = compilerVersion cfg
cmd = unwords $
[":set", if levelGte Debug lvl then "v1" else "v0"
, maybe "" id (lookup cmpname eopts)
......@@ -1369,7 +1406,7 @@ diffCmd opts cfg =
(diffUseAna opts) (diffModules opts)
else succeedIO ()
-- Implementation of the "curry" command.
-- Implementation of the `curry` command.
compiler :: ExecOptions -> Config -> IO (ErrorLogger ())
compiler o cfg =
getLocalPackageSpec cfg "." |>= \pkgdir ->
......@@ -1379,6 +1416,7 @@ compiler o cfg =
(ExecOptions $ unwords [curryExec cfg, "--nocypm", exeCommand o])
cfg pkgdir
-- Implementation of the `exec` command.
execCmd :: ExecOptions -> Config -> IO (ErrorLogger ())
execCmd o cfg =
getLocalPackageSpec cfg "." |>= execWithPkgDir o cfg
......@@ -1463,7 +1501,107 @@ newPackage (NewOptions pname) = do
, "> cypm curry :load Main :eval main :quit"
]
------------------------------------------------------------------------------
--- Uploads a package to package server.
uploadCmd :: UploadOptions -> Config -> IO (ErrorLogger ())
uploadCmd opts cfg =
getLocalPackageSpec cfg "." |>= \specDir ->
loadPackageSpec specDir |>= \lpkg ->
let pkgrepodir = repositoryDir cfg </>
name lpkg </> showVersion (version lpkg) in
doesDirectoryExist pkgrepodir >>= \exrepodir ->
(if exrepodir && not (forceUpdate opts)
then failIO $ "Package version already exists in repository!"
else succeedIO () ) |>
inDirectory specDir (setTagInGitIfNecessary opts lpkg) |>
tempDir >>= \instdir ->
recreateDirectory instdir >>
installPkg lpkg instdir |>
let pkgid = packageId lpkg in
loadPackageSpec (instdir </> pkgid) |>= \pkg ->
testPackage pkgid instdir >>= \ecode ->
if ecode > 0
then removeDirectoryComplete instdir >>
log Critical "ERROR in package, package not uploaded!"
else log Info "Uploading package to global repository..." |>
removeInstalledPkg pkgid >>
uploadPackageSpec (instdir </> pkgid </> "package.json") |>
-- add package to local copy of repository:
addPackageToRepo pkgrepodir (instdir </> pkgid) pkg >>
removeDirectoryComplete instdir >>
log Info ("Package '" ++ pkgid ++ "' uploaded")
where
addPackageToRepo pkgrepodir pkgdir pkg = do
exrepodir <- doesDirectoryExist pkgrepodir
infoMessage $ "Create directory: " ++ pkgrepodir
createDirectoryIfMissing True pkgrepodir
copyFile (pkgdir </> "package.json") (pkgrepodir </> "package.json")
if exrepodir then updatePackageInRepositoryCache cfg pkg
else addPackageToRepositoryCache cfg pkg
-- TODO: check url
installPkg pkg instdir = case source pkg of
Nothing -> failIO $ "No source specified for package"
Just (Git url rev) -> installPackageSourceTo pkg (Git url rev) instdir
_ -> failIO $ "No git source with version tag"
removeInstalledPkg pkgid = do
let pkgInstallDir = packageInstallDir cfg </> pkgid
expkgdir <- doesDirectoryExist pkgInstallDir
when expkgdir $ removeDirectoryComplete pkgInstallDir
testPackage pkgid instdir = do
curdir <- inDirectory instdir getCurrentDirectory
let bindir = curdir </> "pkgbin"
recreateDirectory bindir
let cmd = unwords
[ -- install possible binaries in bindir:
"cypm", "-d bin_install_path="++bindir, "install", "&&"
, "export PATH="++bindir++":$PATH", "&&"
, "cypm", "test", "&&"
, "cypm", "-d bin_install_path="++bindir, "uninstall"
]
putStrLn $ "Testing package: '" ++ pkgid ++ "' with command:\n" ++ cmd
inDirectory (instdir </> pkgid) $ system cmd
--- Set the package version as a tag in the local GIT repository and push it,
--- if the package source is a GIT with tag `$version`.
setTagInGitIfNecessary :: UploadOptions -> Package -> IO (ErrorLogger ())
setTagInGitIfNecessary opts pkg
| not (setTag opts) = succeedIO ()
| otherwise = case source pkg of
Just (Git _ (Just VersionAsTag)) -> setTagInGit pkg
_ -> succeedIO ()
setTagInGit :: Package -> IO (ErrorLogger ())
setTagInGit pkg = do
let ts = 'v' : showVersion (version pkg)
infoMessage $ "Tagging current git repository with tag '" ++ ts++ "'"
(_,gittag,_) <- evalCmd "git" ["tag","-l",ts] ""
let deltag = if null gittag then [] else ["git tag -d",ts,"&&"]
cmd = unwords $ deltag ++ ["git tag -a",ts,"-m",ts,"&&",
"git push --tags -f"]
infoMessage $ "Execute: " ++ cmd
ecode <- system cmd
if ecode == 0 then succeedIO ()
else failIO $ "ERROR in setting the git tag"
-- Uploads a package specification stored in a file (first argument).
uploadPackageSpec :: String -> IO (ErrorLogger ())
uploadPackageSpec pkgspecfname = do
pkgspec <- readFile pkgspecfname
(rc,out,err) <- evalCmd "curl" ["--data-binary", "@-", uploadURL ] pkgspec
unless (null out) $ infoMessage out
if rc == 0
then succeedIO ()
else log Info err |> failIO "Adding to global repository failed!"
-- URL of cpm-upload script.
uploadURL :: String
--uploadURL = "http://localhost/~mh/cpm-upload.cgi"
uploadURL = "https://www-ps.informatik.uni-kiel.de/~mh/cpm-upload.cgi"
------------------------------------------------------------------------------
--- Fail with a "package not found" message.
packageNotFoundFailure :: String -> IO (ErrorLogger _)
packageNotFoundFailure pkgname =
......
......@@ -176,6 +176,12 @@ data Package = Package {
}
deriving (Eq,Show)
-- A simple Show instance for Package (maybe useful for debugging):
--instance Show Package where
-- show p = "(Package " ++
-- unwords [name p, showVersion (version p)
-- , unwords (map showDependency (dependencies p))] ++ ")"
--- An empty package specification.
emptyPackage :: Package
emptyPackage = Package {
......
......@@ -16,10 +16,11 @@ import ReadShowTerm
import Database.CDBI.ER
import Database.CDBI.Connection
import System.Path ( fileInPath )
import CPM.Config ( Config, readConfigurationWith, repositoryDir )
import CPM.ErrorLogger
import CPM.FileUtil ( fileInPath, whenFileExists )
import CPM.FileUtil ( whenFileExists )
import CPM.Repository.RepositoryDB
import CPM.Package
import CPM.Repository
......
......@@ -28,14 +28,15 @@ import CPM.Repository.Select ( addPackageToRepositoryCache
------------------------------------------------------------------------------
--- Updates the package index from the central Git repository.
--- Cleans also the global package cache in order to support
--- downloading the newest versions.
updateRepository :: Config -> IO (ErrorLogger ())
updateRepository cfg = do
--- If the second argument is `True`, also the global package cache
--- is cleaned in order to support downloading the newest versions.
updateRepository :: Config -> Bool -> IO (ErrorLogger ())
updateRepository cfg cleancache = do
cleanRepositoryCache cfg
debugMessage $ "Deleting global package cache: '" ++
packageInstallDir cfg ++ "'"
removeDirectoryComplete (packageInstallDir cfg)
when cleancache $ do
debugMessage $ "Deleting global package cache: '" ++
packageInstallDir cfg ++ "'"
removeDirectoryComplete (packageInstallDir cfg)
debugMessage $ "Recreating package index: '" ++ repositoryDir cfg ++ "'"
recreateDirectory (repositoryDir cfg)
c <- inDirectory (repositoryDir cfg) downloadCommand
......
......@@ -137,6 +137,7 @@ showResult r@(ResolutionFailure _) = showConflict r
--- contains the conflict tree.
data ResolutionResult = ResolutionSuccess Package [Package]
| ResolutionFailure (Tree ConflictState)
deriving (Eq,Show)
--- Represents an activation of a package in the candidate tree. Activations
--- form a chain up to the initial activation, i.e. the initial package that
......@@ -145,7 +146,7 @@ data ResolutionResult = ResolutionSuccess Package [Package]
--- dependency led to the current package version being chosen.
data Activation = InitialA Package
| ChildA Package Dependency Activation
deriving Eq
deriving (Eq,Show)
--- Each tree node is labeled with the current activation and all former
--- activations.
......@@ -162,7 +163,7 @@ type State = (Activation, [Activation])
data Conflict = SecondaryConflict Activation Activation
| PrimaryConflict Activation
| CompilerConflict Activation
deriving Eq
deriving (Eq,Show)
--- A state and a potential conflict.
type ConflictState = (State, Maybe Conflict)
......@@ -218,6 +219,7 @@ clState = fst
--- A tree with a label and child nodes.
data Tree a = Node a [Tree a]
deriving (Eq,Show)
--- Recursively applies a function to each node in a tree.
mapTree :: (a -> b) -> Tree a -> Tree b
......@@ -284,6 +286,7 @@ candidateTree pkg ls = let s = InitialA pkg in
then tree' acts ds
else map (nodesForDep act d ds acts) $ findAllVersions ls p True
tree' _ [] = []
nodesForDep act d ds acts p' =
let
act' = ChildA p' d act
......@@ -499,9 +502,9 @@ isCompatibleToCompiler cfg p = case compats of
Nothing -> False -- No constraints for current compiler
-- => compiler is incompatible
Just (CompilerCompatibility _ c) ->
isDisjunctionCompatible (maj, min, 0, Nothing) c
isDisjunctionCompatible (maj, min, revi, Nothing) c
where
(name, maj, min) = compilerVersion cfg
(name, maj, min, revi) = compilerVersion cfg
compats = compilerCompatibility p
constraintForCompiler = find (\(CompilerCompatibility c _) -> c == name)
compats
......
......@@ -7,7 +7,8 @@
"license": "BSD-3-Clause",
"licenseFile": "LICENSE",
"dependencies": {
"wl-pprint": ">= 0.0.1"
"frontend-exec" : ">= 0.0.1",
"wl-pprint" : ">= 0.0.1"
},
"compilerCompatibility": {
"pakcs": ">= 2.0.0",
......
......@@ -7,22 +7,24 @@
--- extension `.acy` in the subdirectory `.curry`
---
--- @author Michael Hanus, Bjoern Peemoeller, Jan Tikovsky, Finn Teegen
--- @version November 2017
--- @category meta
--- @version November 2018
-- ---------------------------------------------------------------------------
module AbstractCurry.Files where
import AbstractCurry.Select (imports)
import AbstractCurry.Types
import Char (isSpace)
import Directory (doesFileExist, getModificationTime)
import Distribution
import FileGoodies (getFileInPath, lookupFileInPath)
import FilePath (takeFileName, (</>), (<.>))
import Maybe (isNothing)
import Char ( isSpace )
import Directory ( doesFileExist, getModificationTime )
import Distribution ( getLoadPathForModule, inCurrySubdir
, lookupModuleSourceInLoadPath, stripCurrySuffix )
import FileGoodies ( getFileInPath, lookupFileInPath )
import FilePath ( takeFileName, (</>), (<.>) )
import ReadShowTerm
import System.FrontendExec
import AbstractCurry.Select ( imports )
import AbstractCurry.Types
-- ---------------------------------------------------------------------------
--- I/O action which parses a Curry program and returns the corresponding
--- typed Abstract Curry program.
......
......@@ -4,8 +4,7 @@
--- This library provides a pretty-printer for AbstractCurry modules.
---
--- @author Yannik Potdevin (with changes by Michael Hanus)
--- @version October 2016
--- @category meta
--- @version June 2018
--- --------------------------------------------------------------------------