[project @ 2004-02-12 02:04:59 by mthomas]
[ghc-hetmet.git] / ghc / compiler / NOTES
1 * Can a scoped type variable denote a type scheme?
2
3 * Relation between separate type sigs and pattern type sigs
4 f :: forall a. a->a
5 f :: b->b = e   -- No: monomorphic
6
7 f :: forall a. a->a
8 f :: forall a. a->a  -- OK
9
10 f :: forall a. [a] -> [a]
11 f :: forall b. b->b = e  ???
12
13
14 -------------------------------
15 NB: all floats are let-binds, but some non-rec lets
16     may be unlifted (with RHS ok-for-speculation)
17
18
19 simplArg:  [use strictness]
20            [used for non-top-lvl non-rec RHS or function arg]
21   if strict-type || demanded
22         simplStrictExpr
23   else
24         simplExpr ---> (floats,expr)
25         float all the floats if exposes constr app, return expr
26
27 simpl (applied lambda)      ==> simplNonRecBind
28 simpl (Let (NonRec ...) ..) ==> simplNonRecBind
29
30 simpl (Let (Rec ...)    ..) ==> simplRecBind
31
32 simplRecBind:
33   simplify binders (but not its IdInfo)
34   simplify the pairs one at a time
35         using simplRecPair
36
37 simplNonRecBind:        [was simplBeta]
38         [used for non-top-lvl non-rec bindings]
39   - check for PreInlineUnconditionally
40   - simplify binder, including its IdInfo
41   - simplArg
42   - if strict-type 
43         addCaseBind [which makes a let if ok-for-spec]
44     else
45         completeLazyBind
46
47 simplLazyBind:  [binder already simplified, but not its IdInfo]
48                 [used for both rec and top-lvl non-rec]
49                 [must not be strict/unboxed; case not allowed]
50   - check for PreInlineUnconditionally
51   - substituteIdInfo and add result to in-scope 
52         [so that rules are available in rec rhs]
53   - simplExpr --> (floats,expr)
54   - float: lifted floats only
55         if exposes constructor or pap (even if non-triv args)
56         or if top level
57   - completeLazyBind
58   
59
60 completeLazyBind:       [given a simplified RHS]
61         [used for both rec and non-rec bindings, top level and not]
62   - try discarding dead
63   - try PostInlineUnconditionally
64   - let-bind coerce arg and repeat
65   - try rhs tylam (float)
66   - try eta expand (float)    [not if any float is unlifted && (non-spec || top_lvl || rec)]
67   - let-bind constructor args [not if any float is ..as above..]
68
69   - add unfolding [this is the only place we add an unfolding]
70     add arity
71
72
73
74 Right hand sides and arguments
75 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
76 In many ways we want to treat 
77         (a) the right hand side of a let(rec), and 
78         (b) a function argument
79 in the same way.  But not always!  In particular, we would
80 like to leave these arguments exactly as they are, so they
81 will match a RULE more easily.
82         
83         f (g x, h x)    
84         g (+ x)
85
86 It's harder to make the rule match if we ANF-ise the constructor,
87 or eta-expand the PAP:
88
89         f (let { a = g x; b = h x } in (a,b))
90         g (\y. + x y)
91
92 On the other hand if we see the let-defns
93
94         p = (g x, h x)
95         q = + x
96
97 then we *do* want to ANF-ise and eta-expand, so that p and q
98 can be safely inlined.   
99
100 Even floating lets out is a bit dubious.  For let RHS's we float lets
101 out if that exposes a value, so that the value can be inlined more vigorously.
102 For example
103
104         r = let x = e in (x,x)
105
106 Here, if we float the let out we'll expose a nice constructor. We did experiments
107 that showed this to be a generally good thing.  But it was a bad thing to float
108 lets out unconditionally, because that meant they got allocated more often.
109
110 For function arguments, there's less reason to expose a constructor (it won't
111 get inlined).  Just possibly it might make a rule match, but I'm pretty skeptical.
112 So for the moment we don't float lets out of function arguments either.
113
114
115 Eta expansion
116 ~~~~~~~~~~~~~~
117 For eta expansion, we want to catch things like
118
119         case e of (a,b) -> \x -> case a of (p,q) -> \y -> r
120
121 If the \x was on the RHS of a let, we'd eta expand to bring the two
122 lambdas together.  And in general that's a good thing to do.  Perhaps
123 we should eta expand wherever we find a (value) lambda?  Then the eta
124 expansion at a let RHS can concentrate solely on the PAP case.