1 * Can a scoped type variable denote a type scheme?
3 * Relation between separate type sigs and pattern type sigs
5 f :: b->b = e -- No: monomorphic
8 f :: forall a. a->a -- OK
10 f :: forall a. [a] -> [a]
11 f :: forall b. b->b = e ???
14 -------------------------------
15 NB: all floats are let-binds, but some non-rec lets
16 may be unlifted (with RHS ok-for-speculation)
19 simplArg: [use strictness]
20 [used for non-top-lvl non-rec RHS or function arg]
21 if strict-type || demanded
24 simplExpr ---> (floats,expr)
25 float all the floats if exposes constr app, return expr
27 simpl (applied lambda) ==> simplNonRecBind
28 simpl (Let (NonRec ...) ..) ==> simplNonRecBind
30 simpl (Let (Rec ...) ..) ==> simplRecBind
33 simplify binders (but not its IdInfo)
34 simplify the pairs one at a time
37 simplNonRecBind: [was simplBeta]
38 [used for non-top-lvl non-rec bindings]
39 - check for PreInlineUnconditionally
40 - simplify binder, including its IdInfo
43 addCaseBind [which makes a let if ok-for-spec]
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)
60 completeLazyBind: [given a simplified RHS]
61 [used for both rec and non-rec bindings, top level and not]
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..]
69 - add unfolding [this is the only place we add an unfolding]
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.
86 It's harder to make the rule match if we ANF-ise the constructor,
87 or eta-expand the PAP:
89 f (let { a = g x; b = h x } in (a,b))
92 On the other hand if we see the let-defns
97 then we *do* want to ANF-ise and eta-expand, so that p and q
98 can be safely inlined.
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.
104 r = let x = e in (x,x)
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.
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.
117 For eta expansion, we want to catch things like
119 case e of (a,b) -> \x -> case a of (p,q) -> \y -> r
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.