[project @ 1996-06-05 06:44:31 by partain]
[ghc-hetmet.git] / ghc / compiler / simplCore / FoldrBuildWW.lhs
1 %
2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
3 %
4 \section[FoldrBuildWW]{Spliting suitable functions into Workers and Wrappers}
5
6 \begin{code}
7 #include "HsVersions.h"
8
9 module FoldrBuildWW ( mkFoldrBuildWW ) where
10
11 IMP_Ubiq(){-uitous-}
12
13 import CoreSyn          ( CoreBinding(..) )
14 import Util             ( panic{-ToDo:rm?-} )
15
16 --import Type           ( cloneTyVarFromTemplate, mkTyVarTy,
17 --                        splitFunTyExpandingDicts, eqTyCon,  mkForallTy )
18 --import TysPrim                ( alphaTy )
19 --import TyVar          ( alphaTyVar )
20 --
21 --import Type           ( Type(..) ) -- **** CAN SEE THE CONSTRUCTORS ****
22 --import UniqSupply     ( runBuiltinUs )
23 --import WwLib            -- share the same monad (is this eticit ?)
24 --import PrelInfo               ( listTyCon, mkListTy, nilDataCon, consDataCon,
25 --                        foldrId, buildId
26 --                      )
27 --import Id               ( getIdFBTypeInfo, mkWorkerId, getIdInfo,
28 --                        replaceIdInfo, mkSysLocal, idType
29 --                      )
30 --import IdInfo
31 --import Maybes
32 --import SrcLoc         ( mkUnknownSrcLoc, SrcLoc )
33 --import Util
34 \end{code}
35
36 \begin{code}
37 mkFoldrBuildWW
38         :: UniqSupply
39         -> [CoreBinding]
40         -> [CoreBinding]
41
42 mkFoldrBuildWW = panic "mkFoldrBuildWW (ToDo)"
43
44 {- LATER:
45 mkFoldrBuildWW us top_binds =
46    (mapWw wwBind top_binds `thenWw` \ top_binds2 ->
47    returnWw (concat top_binds2)) us
48 \end{code}
49
50 \begin{code}
51 wwBind :: CoreBinding -> WwM [CoreBinding]
52 wwBind (NonRec bndr expr)
53   = try_split_bind bndr expr    `thenWw` \ re ->
54     returnWw [NonRec bnds expr | (bnds,expr) <- re]
55 wwBind (Rec binds)
56   = mapWw (\ (bndr,expr) -> try_split_bind bndr expr) binds   `thenWw` \ res ->
57     returnWw [Rec (concat res)]
58
59 wwExpr :: CoreExpr -> WwM CoreExpr
60 wwExpr e@(Var _) = returnWw e
61 wwExpr e@(Lit _) = returnWw e
62 wwExpr e@(Con _ _ _) = returnWw e
63 wwExpr e@(Prim _ _ _) = returnWw e
64 wwExpr   (Lam ids e) =
65         wwExpr e                `thenWw` \ e' ->
66         returnWw (Lam ids e')
67 wwExpr   (CoTyLam tyvar e) =
68         wwExpr e                `thenWw` \ e' ->
69         returnWw (CoTyLam tyvar e')
70 wwExpr   (App f atom) =
71         wwExpr f                `thenWw` \ f' ->
72         returnWw (App f atom)
73 wwExpr   (CoTyApp f ty) =
74         wwExpr f                `thenWw` \ f' ->
75         returnWw (CoTyApp f' ty)
76 wwExpr   (SCC lab e) =
77         wwExpr e                `thenWw` \ e' ->
78         returnWw (SCC lab e')
79 wwExpr   (Coerce c ty e) =
80         wwExpr e                `thenWw` \ e' ->
81         returnWw (Coerce c ty e')
82 wwExpr   (Let bnds e) =
83         wwExpr e                `thenWw` \ e' ->
84         wwBind bnds             `thenWw` \ bnds' ->
85         returnWw (foldr Let e' bnds')
86 wwExpr   (Case e alts) =
87         wwExpr e                `thenWw` \ e' ->
88         wwAlts alts             `thenWw` \ alts' ->
89         returnWw  (Case e' alts')
90
91 wwAlts (AlgAlts alts deflt) =
92         mapWw (\(con,binders,e) ->
93                         wwExpr e        `thenWw` \ e' ->
94                         returnWw (con,binders,e')) alts `thenWw` \ alts' ->
95         wwDef deflt                                     `thenWw` \ deflt' ->
96         returnWw (AlgAlts alts' deflt)
97 wwAlts (PrimAlts alts deflt) =
98         mapWw (\(lit,e) ->
99                         wwExpr e        `thenWw` \ e' ->
100                         returnWw (lit,e')) alts         `thenWw` \ alts' ->
101         wwDef deflt                                     `thenWw` \ deflt' ->
102         returnWw (PrimAlts alts' deflt)
103
104 wwDef e@NoDefault = returnWw e
105 wwDef  (BindDefault v e) =
106         wwExpr e                                        `thenWw` \ e' ->
107         returnWw (BindDefault v e')
108 \end{code}
109
110 \begin{code}
111 try_split_bind :: Id -> CoreExpr -> WwM [(Id,CoreExpr)]
112 try_split_bind id expr =
113   wwExpr expr                   `thenWw` \ expr' ->
114   case getFBType (getIdFBTypeInfo id) of
115     Just (FBType consum prod)
116         |  FBGoodProd == prod ->
117 {-      || any (== FBGoodConsum) consum -}
118       let
119         (use_args,big_args,args,body) = collectBinders expr'
120       in
121         if length args /= length consum   -- funny number of arguments
122         then returnWw [(id,expr')]
123         else
124         -- f /\ t1 .. tn \ v1 .. vn -> e
125         --      ===>
126         -- f_wrk /\ t1 .. tn t_new \ v1 .. vn c n -> foldr <exprTy> <nTy> c n e
127         -- f /\ t1 .. tn \ v1 .. vn
128         --      -> build exprTy (\ c n -> f_wrk t1 .. tn t_new v1 .. vn c n)
129         pprTrace "WW:" (ppr PprDebug id) (returnWw ())
130                                 `thenWw` \ () ->
131         getUniqueWw             `thenWw` \ ty_new_uq ->
132         getUniqueWw             `thenWw` \ worker_new_uq ->
133         getUniqueWw             `thenWw` \ c_new_uq ->
134         getUniqueWw             `thenWw` \ n_new_uq ->
135       let
136         -- The *new* type
137         n_ty = alphaTy
138         n_ty_templ = alphaTy
139
140         (templ,arg_tys,res) = splitFunTyExpandingDicts (idType id)
141         expr_ty = getListTy res
142         getListTy res = panic "FoldrBuildWW:getListTy:ToDo" {-LATER:case res of
143                          UniData lty [ty] | lty `eqTyCon` listTyCon -> ty
144                          _ -> panic "Trying to split a non List datatype into Worker/Wrapper"-}
145
146         c_ty       = expr_ty `mkFunTy` (n_ty `mkFunTy` n_ty)
147         c_ty_templ = expr_ty `mkFunTy` (n_ty_templ `mkFunTy` n_ty_templ)
148
149         worker_ty = mkForallTy (templ  ++ [alphaTyVar])
150                         (foldr mkFunTy n_ty_templ (arg_tys++[c_ty_templ,n_ty_templ]))
151         wrapper_id  = id `replaceIdInfo`
152                               (getIdInfo id     `addInfo_UF`
153                                iWantToBeINLINEd UnfoldAlways)
154         worker_id  = mkWorkerId worker_new_uq id worker_ty
155                                 noIdInfo
156                 -- TODO : CHECK if mkWorkerId is thr
157                 -- right function to use ..
158         -- Now the bodies
159
160         c_id = mkSysLocal SLIT("_fbww") c_new_uq c_ty mkUnknownSrcLoc
161         n_id = mkSysLocal SLIT("_fbww") n_new_uq n_ty mkUnknownSrcLoc
162         worker_rhs
163           = mkTyLam [] (big_args ++ [alphaTyVar]) (args++[c_id,n_id]) worker_body
164                         
165         worker_body = runBuiltinUs (
166           mkCoApps
167             (Var foldrId `CoTyApp` expr_ty `CoTyApp` n_ty `App`
168                VarArg c_id `App` VarArg n_id)
169             [body])
170         wrapper_rhs = mkLam big_args args wrapper_body
171
172         wrapper_body = runBuiltinUs (
173                  mkCoApps (CoTyApp (Var buildId) expr_ty)
174                                 [mkLam [alphaTyVar] [c_id,n_id]
175                 (foldl App
176                         (mkCoTyApps (Var worker_id)
177                                 [mkTyVarTy t | t <- big_args ++ [alphaTyVar]])
178                         (map VarArg (args++[c_id,n_id])))])
179
180       in
181         if length args /= length arg_tys ||
182            length big_args /= length templ
183         then panic "LEN PROBLEM"
184         else
185         returnWw  [(worker_id,worker_rhs),(wrapper_id,wrapper_rhs)]
186     _ -> returnWw [(id,expr')]
187 -}
188 \end{code}