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