2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
4 \section[Demand]{@Demand@: the amount of demand on a value}
10 wwLazy, wwStrict, wwUnpackData, wwUnpackNew, wwPrim, wwEnum,
11 isStrict, isLazy, isPrim,
13 pprDemands, seqDemand, seqDemands,
18 ppStrictnessInfo, seqStrictnessInfo,
19 isBottomingStrictness, appIsBottom,
22 #include "HsVersions.h"
24 import BasicTypes ( NewOrData(..) )
29 %************************************************************************
31 \subsection{The @Demand@ data type}
33 %************************************************************************
37 = WwLazy -- Argument is lazy as far as we know
38 MaybeAbsent -- (does not imply worker's existence [etc]).
39 -- If MaybeAbsent == True, then it is
40 -- *definitely* lazy. (NB: Absence implies
43 | WwStrict -- Argument is strict but that's all we know
44 -- (does not imply worker's existence or any
45 -- calling-convention magic)
47 | WwUnpack -- Argument is strict & a single-constructor type
49 Bool -- True <=> wrapper unpacks it; False <=> doesn't
50 [Demand] -- Its constituent parts (whose StrictInfos
51 -- are in the list) should be passed
52 -- as arguments to the worker.
54 | WwPrim -- Argument is of primitive type, therefore
55 -- strict; doesn't imply existence of a worker;
56 -- argument should be passed as is to worker.
58 | WwEnum -- Argument is strict & an enumeration type;
59 -- an Int# representing the tag (start counting
60 -- at zero) should be passed to the worker.
63 type MaybeAbsent = Bool -- True <=> not even used
65 -- versions that don't worry about Absence:
68 wwUnpackData xs = WwUnpack DataType False xs
69 wwUnpackNew x = WwUnpack NewType False [x]
73 seqDemand :: Demand -> ()
74 seqDemand (WwLazy a) = a `seq` ()
75 seqDemand (WwUnpack nd b ds) = nd `seq` b `seq` seqDemands ds
79 seqDemands (d:ds) = seqDemand d `seq` seqDemands ds
83 %************************************************************************
85 \subsection{Functions over @Demand@}
87 %************************************************************************
90 isStrict :: Demand -> Bool
91 isStrict (WwUnpack NewType _ ds) = isStrict (head ds)
92 isStrict (WwUnpack other _ _) = True
93 isStrict WwStrict = True
94 isStrict WwEnum = True
95 isStrict WwPrim = True
98 isPrim :: Demand -> Bool
104 isLazy :: Demand -> Bool
105 isLazy (WwLazy False) = True -- NB "Absent" args do *not* count!
106 isLazy _ = False -- (as they imply a worker)
110 %************************************************************************
112 \subsection{Instances}
114 %************************************************************************
118 pprDemands demands bot = hcat (map pprDemand demands) <> pp_bot
120 pp_bot | bot = ptext SLIT("B")
124 pprDemand (WwLazy False) = char 'L'
125 pprDemand (WwLazy True) = char 'A'
126 pprDemand WwStrict = char 'S'
127 pprDemand WwPrim = char 'P'
128 pprDemand WwEnum = char 'E'
129 pprDemand (WwUnpack nd wu args) = char ch <> parens (hcat (map pprDemand args))
137 instance Outputable Demand where
138 ppr (WwLazy False) = empty
139 ppr other_demand = ptext SLIT("__D") <+> pprDemand other_demand
141 instance Show Demand where
142 showsPrec p d = showsPrecSDoc p (ppr d)
144 -- Reading demands is done in Lex.lhs
148 %************************************************************************
150 \subsection[strictness-IdInfo]{Strictness info about an @Id@}
152 %************************************************************************
154 We specify the strictness of a function by giving information about
155 each of the ``wrapper's'' arguments (see the description about
156 worker/wrapper-style transformations in the PJ/Launchbury paper on
159 The list of @Demands@ specifies: (a)~the strictness properties of a
160 function's arguments; and (b)~the type signature of that worker (if it
161 exists); i.e. its calling convention.
163 Note that the existence of a worker function is now denoted by the Id's
170 | StrictnessInfo [Demand] -- Demands on the arguments.
172 Bool -- True <=> the function diverges regardless of its arguments
173 -- Useful for "error" and other disguised variants thereof.
174 -- BUT NB: f = \x y. error "urk"
175 -- will have info SI [SS] True
176 -- but still (f) and (f 2) are not bot; only (f 3 2) is bot
178 -- NOTA BENE: if the arg demands are, say, [S,L], this means that
179 -- (f bot) is not necy bot, only (f bot x) is bot
180 -- We simply cannot express accurately the strictness of a function
181 -- like f = \x -> case x of (a,b) -> \y -> ...
182 -- The up-side is that we don't need to restrict the strictness info
183 -- to the visible arity of the function.
185 seqStrictnessInfo :: StrictnessInfo -> ()
186 seqStrictnessInfo (StrictnessInfo ds b) = b `seq` seqDemands ds
187 seqStrictnessInfo other = ()
191 mkStrictnessInfo :: ([Demand], Bool) -> StrictnessInfo
193 mkStrictnessInfo (xs, is_bot)
194 | all isLazy xs && not is_bot = NoStrictnessInfo -- Uninteresting
195 | otherwise = StrictnessInfo xs is_bot
197 noStrictnessInfo = NoStrictnessInfo
199 isBottomingStrictness (StrictnessInfo _ bot) = bot
200 isBottomingStrictness NoStrictnessInfo = False
202 -- appIsBottom returns true if an application to n args would diverge
203 appIsBottom (StrictnessInfo ds bot) n = bot && (n >= length ds)
204 appIsBottom NoStrictnessInfo n = False
206 ppStrictnessInfo NoStrictnessInfo = empty
207 ppStrictnessInfo (StrictnessInfo wrapper_args bot)
208 = hsep [ptext SLIT("__S"), pprDemands wrapper_args bot]