AbstractCurry.curry 5.4 KB
Newer Older
Michael Hanus's avatar
Michael Hanus committed
1
2
3
4
5
6
7
8
--------------------------------------------------------------------------------
--- This module contains helper functions for dealing with AbstractCurry. In
--- particular, it contains functions that can read modules from a package and
--- its dependencies with all dependencies available to the Curry frontend.
--------------------------------------------------------------------------------

module CPM.AbstractCurry 
  ( loadPathForPackage
Michael Hanus's avatar
Michael Hanus committed
9
  , readAbstractCurryFromPackagePath
Michael Hanus's avatar
Michael Hanus committed
10
11
12
13
14
  , readAbstractCurryFromDeps
  , transformAbstractCurryInDeps 
  , applyModuleRenames
  ) where

Michael Hanus's avatar
Michael Hanus committed
15
16
17
18
import List         ( intercalate, nub )
import FilePath     ( (</>), (<.>), takeFileName, replaceExtension )
import System

19
20
21
import AbstractCurry.Files  ( readAbstractCurryFile, writeAbstractCurryFile )
import AbstractCurry.Pretty ( showCProg )
import AbstractCurry.Select ( imports )
Michael Hanus's avatar
Michael Hanus committed
22
import AbstractCurry.Transform
23
import AbstractCurry.Types
Michael Hanus's avatar
Michael Hanus committed
24
25
import System.CurryPath     ( sysLibPath, inCurrySubdir, modNameToPath
                            , inCurrySubdirModule, lookupModuleSource )
Michael Hanus's avatar
Michael Hanus committed
26
27
28
import System.FrontendExec  ( FrontendTarget (..), FrontendParams (..)
                            , defaultParams, callFrontendWithParams
                            , setQuiet, setFullPath )
Michael Hanus's avatar
Michael Hanus committed
29

Michael Hanus's avatar
Michael Hanus committed
30
import CPM.ErrorLogger
Michael Hanus's avatar
Michael Hanus committed
31
import qualified CPM.PackageCache.Runtime as RuntimeCache
Michael Hanus's avatar
Michael Hanus committed
32
import CPM.Package (Package, loadPackageSpec, sourceDirsOf)
Michael Hanus's avatar
Michael Hanus committed
33
34

--- Returns the load path for a package stored in some directory
Michael Hanus's avatar
Michael Hanus committed
35
--- w.r.t. the dependent packages.
Michael Hanus's avatar
Michael Hanus committed
36
---
Michael Hanus's avatar
Michael Hanus committed
37
38
--- @param - pkg - the package
--- @param - pkgDir - the directory containing this package
Michael Hanus's avatar
Michael Hanus committed
39
40
--- @param - deps - the resolved dependencies of the package
--- @return the full load path for modules in the package or dependent packages
Michael Hanus's avatar
Michael Hanus committed
41
42
43
44
45
loadPathForPackage :: Package -> String -> [Package] -> [String]
loadPathForPackage pkg pkgDir deps =
  (map (pkgDir </>) (sourceDirsOf pkg) ++
  RuntimeCache.dependencyPathsSeparate deps pkgDir)

Michael Hanus's avatar
Michael Hanus committed
46
47
--- Returns the full load path for a package stored in some directory.
---
Michael Hanus's avatar
Michael Hanus committed
48
49
--- @param - pkg - the package
--- @param - pkgDir - the directory containing this package
Michael Hanus's avatar
Michael Hanus committed
50
51
--- @param - deps - the resolved dependencies of the package
--- @return the full load path for modules in the package or dependent packages
Michael Hanus's avatar
Michael Hanus committed
52
53
54
55
56
fullLoadPathForPackage :: Package -> String -> [Package] -> [String]
fullLoadPathForPackage pkg pkgDir deps =
  loadPathForPackage pkg pkgDir deps ++ sysLibPath
  -- here we assume that the system libs are identical for each Curry system

Michael Hanus's avatar
Michael Hanus committed
57
58
59
60
61
--- Reads an AbstractCurry module from a package.
---
--- @param - dir the package's directory
--- @param - deps the resolved dependencies of the package
--- @param - mod the module to read
Michael Hanus's avatar
Michael Hanus committed
62
63
64
65
readAbstractCurryFromPackagePath :: Package -> String -> [Package] -> String
                                 -> IO CurryProg
readAbstractCurryFromPackagePath pkg pkgDir deps modname = do
  let loadPath = fullLoadPathForPackage pkg pkgDir deps
Michael Hanus's avatar
Michael Hanus committed
66
  params <- return $ setQuiet True (setFullPath loadPath defaultParams)
Michael Hanus's avatar
Michael Hanus committed
67
  callFrontendWithParams ACY params modname
Michael Hanus's avatar
Michael Hanus committed
68
69
70
71
  src <- lookupModuleSource loadPath modname
  acyName <- return $ case src of
    Nothing -> error $ "Module not found: " ++ modname
    Just (_, file) -> replaceExtension (inCurrySubdirModule modname file) ".acy"
Michael Hanus's avatar
Michael Hanus committed
72
73
74
75
76
77
78
79
80
81
82
83
  readAbstractCurryFile acyName >>= return . addPrimTypes
 where
  -- work-around for missing Prelude.Char|Int|Float declarations:
  addPrimTypes p@(CurryProg mname imports dfltdecl clsdecls instdecls
                            typedecls funcdecls opdecls)
   | mname == pre && primType "Int" `notElem` typedecls
   = CurryProg mname imports dfltdecl clsdecls instdecls
               (map primType ["Int","Float","Char"] ++ typedecls)
               funcdecls opdecls
   | otherwise = p
   where pre = "Prelude"
         primType n = CType ("Prelude",n) Public [] [] []
Michael Hanus's avatar
Michael Hanus committed
84

Michael Hanus's avatar
Michael Hanus committed
85
86
87
88
89
90
91
--- Reads an AbstractCurry module from a package or one of its dependencies.
---
--- @param dir - the package's directory
--- @param deps - the resolved dependencies of the package
--- @param mod - the module to read
readAbstractCurryFromDeps :: String -> [Package] -> String -> IO CurryProg
readAbstractCurryFromDeps pkgDir deps modname = do
Michael Hanus's avatar
Michael Hanus committed
92
  pkg <- fromErrorLogger (loadPackageSpec pkgDir)
Michael Hanus's avatar
Michael Hanus committed
93
  readAbstractCurryFromPackagePath pkg pkgDir deps modname
Michael Hanus's avatar
Michael Hanus committed
94
95
96
97
98
99
100
101
102

--- Applies a transformation function to a module from a package or one of its
--- dependencies and writes the modified module to a file in Curry form.
---
--- @param dir - the package's directory
--- @param deps - the resolved dependencies of the package
--- @param f - the transformation function
--- @param mod - the module to transform
--- @param dest - the destination file for the transformed module
Michael Hanus's avatar
Michael Hanus committed
103
transformAbstractCurryInDeps :: String -> [Package] -> (CurryProg -> CurryProg)
Michael Hanus's avatar
Michael Hanus committed
104
105
                             -> String -> String -> IO ()
transformAbstractCurryInDeps pkgDir deps transform modname destFile = do
Michael Hanus's avatar
Michael Hanus committed
106
  acy <- readAbstractCurryFromDeps pkgDir deps modname
Michael Hanus's avatar
Michael Hanus committed
107
108
109
110
111
112
113
114
  writeFile destFile $ showCProg (transform acy)

--- Renames all references to some modules in a Curry program.
--- 
--- @param mods - a map from old to new module names
--- @param prog - the program to modify
applyModuleRenames :: [(String, String)] -> CurryProg -> CurryProg
applyModuleRenames names prog =
115
116
  updCProg maybeRename (map maybeRename) id id id id id id
           (updQNamesInCProg rnm prog)
Michael Hanus's avatar
Michael Hanus committed
117
118
119
120
121
122
123
124
 where
  maybeRename n = case lookup n names of
    Just n' -> n'
    Nothing -> n
  rnm mn@(mod, n) = case lookup mod names of
    Just mod' -> (mod', n)
    Nothing   -> mn