[project @ 2000-10-23 09:03:26 by simonpj]
[ghc-hetmet.git] / ghc / compiler / ghci / CmLink.lhs
1 %
2 % (c) The University of Glasgow, 2000
3 %
4 \section[CmLink]{Linker for GHCI}
5
6 \begin{code}
7 module CmLink ( Linkable(..),  Unlinked(..),
8                 filterModuleLinkables, 
9                 modname_of_linkable, is_package_linkable,
10                 LinkResult(..),
11                 link, 
12                 PersistentLinkerState{-abstractly!-}, emptyPLS )
13 where
14
15 import StgInterp        ( linkIModules, ClosureEnv, ItblEnv )
16
17 import CmStaticInfo     ( PackageConfigInfo )
18 import Module           ( ModuleName, PackageName )
19 import InterpSyn        ( UnlinkedIBind, HValue, binder )
20 import Module           ( Module )
21 import Outputable       ( SDoc )
22 import FiniteMap        ( emptyFM )
23 import Digraph          ( SCC(..) )
24 import Outputable
25 import Panic            ( panic )
26
27 #include "HsVersions.h"
28 \end{code}
29
30 \begin{code}
31 data PersistentLinkerState 
32    = PersistentLinkerState {
33         closure_env :: ClosureEnv,
34         itbl_env    :: ItblEnv
35         -- notionally here, but really lives in the C part of the linker:
36         --            object_symtab :: FiniteMap String Addr
37      }
38
39 data LinkResult 
40    = LinkOK   PersistentLinkerState
41    | LinkErrs PersistentLinkerState [SDoc]
42
43 data Unlinked
44    = DotO FilePath
45    | DotA FilePath
46    | DotDLL FilePath
47    | Trees [UnlinkedIBind]      -- bunch of interpretable bindings
48
49 instance Outputable Unlinked where
50    ppr (DotO path)   = text "DotO" <+> text path
51    ppr (DotA path)   = text "DotA" <+> text path
52    ppr (DotDLL path) = text "DotDLL" <+> text path
53    ppr (Trees binds) = text "Trees" <+> ppr (map binder binds)
54
55
56 isObject (DotO _) = True
57 isObject (DotA _) = True
58 isObject (DotDLL _) = True
59 isObject _ = False
60
61 isInterpretable (Trees _) = True
62 isInterpretable _ = False
63
64 data Linkable
65    = LM ModuleName [Unlinked]
66    | LP PackageName
67
68 instance Outputable Linkable where
69    ppr (LM mod_nm unlinkeds) = text "LinkableM" <+> ppr mod_nm <+> ppr unlinkeds
70    ppr (LP package_nm)       = text "LinkableP" <+> ptext package_nm
71
72 emptyPLS :: IO PersistentLinkerState
73 emptyPLS = return (PersistentLinkerState { closure_env = emptyFM, 
74                                            itbl_env    = emptyFM })
75 \end{code}
76
77 \begin{code}
78 link :: PackageConfigInfo 
79      -> [SCC Linkable] 
80      -> PersistentLinkerState 
81      -> IO LinkResult
82
83 #ifndef GHCI_NOTYET
84 --link = panic "CmLink.link: not implemented"
85 link pci groups pls1
86    = do putStrLn "Hello from the Linker!"
87         putStrLn (showSDoc (vcat (map ppLinkableSCC groups)))
88         putStrLn "Bye-bye from the Linker!"
89         return (LinkOK pls1)
90
91 ppLinkableSCC :: SCC Linkable -> SDoc
92 ppLinkableSCC (CyclicSCC xs) = ppr xs
93 ppLinkableSCC (AcyclicSCC x) = ppr [x]
94
95
96 #else
97 link pci [] pls = return (LinkOK pls)
98 link pci (group:groups) pls = do
99    -- the group is either all objects or all interpretable, for now
100    if all isObject group
101         then do mapM loadObj [ file | DotO file <- group ]
102                 resolveObjs
103                 link pci groups pls
104     else if all isInterpretable group
105         then do (new_closure_env, new_itbl_env) <-
106                    linkIModules (closure_env pls)
107                                 (itbl_env pls)
108                                 [ trees | Trees trees <- group ]
109                 link pci groups (PersistentLinkerState{
110                                    closure_env=new_closure_env,
111                                    itbl_env=new_itbl_env})
112     else
113         return (LinkErrs pls (ptext SLIT("linker: group must contain all objects or all interpreted modules")))
114 #endif
115
116 modname_of_linkable (LM nm _) = nm
117 modname_of_linkable (LP _)    = panic "modname_of_linkable: package"
118
119 is_package_linkable (LP _)   = True
120 is_package_linkable (LM _ _) = False
121
122 filterModuleLinkables :: (ModuleName -> Bool) 
123                       -> [Linkable] 
124                       -> [Linkable]
125 filterModuleLinkables p [] = []
126 filterModuleLinkables p (li:lis)
127    = case li of
128         LP _       -> retain
129         LM modnm _ -> if p modnm then retain else dump
130      where
131         dump   = filterModuleLinkables p lis
132         retain = li : dump
133 \end{code}