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,
21 StrictnessMark(..), isMarkedUnboxed, isMarkedStrict
24 #include "HsVersions.h"
26 import BasicTypes ( NewOrData(..) )
31 %************************************************************************
33 \subsection{The @Demand@ data type}
35 %************************************************************************
39 = WwLazy -- Argument is lazy as far as we know
40 MaybeAbsent -- (does not imply worker's existence [etc]).
41 -- If MaybeAbsent == True, then it is
42 -- *definitely* lazy. (NB: Absence implies
45 | WwStrict -- Argument is strict but that's all we know
46 -- (does not imply worker's existence or any
47 -- calling-convention magic)
49 | WwUnpack -- Argument is strict & a single-constructor type
51 Bool -- True <=> wrapper unpacks it; False <=> doesn't
52 [Demand] -- Its constituent parts (whose StrictInfos
53 -- are in the list) should be passed
54 -- as arguments to the worker.
56 | WwPrim -- Argument is of primitive type, therefore
57 -- strict; doesn't imply existence of a worker;
58 -- argument should be passed as is to worker.
60 | WwEnum -- Argument is strict & an enumeration type;
61 -- an Int# representing the tag (start counting
62 -- at zero) should be passed to the worker.
65 type MaybeAbsent = Bool -- True <=> not even used
67 -- versions that don't worry about Absence:
70 wwUnpackData xs = WwUnpack DataType False xs
71 wwUnpackNew x = ASSERT( isStrict x) -- Invariant
72 WwUnpack NewType False [x]
76 seqDemand :: Demand -> ()
77 seqDemand (WwLazy a) = a `seq` ()
78 seqDemand (WwUnpack nd b ds) = nd `seq` b `seq` seqDemands ds
82 seqDemands (d:ds) = seqDemand d `seq` seqDemands ds
86 %************************************************************************
88 \subsection{Functions over @Demand@}
90 %************************************************************************
93 isLazy :: Demand -> Bool
94 -- Even a demand of (WwUnpack NewType _ _) is strict
95 -- We don't create such a thing unless the demand inside is strict
96 isLazy (WwLazy _) = True
99 isStrict :: Demand -> Bool
100 isStrict d = not (isLazy d)
102 isPrim :: Demand -> Bool
108 %************************************************************************
110 \subsection{Instances}
112 %************************************************************************
116 pprDemands demands bot = hcat (map pprDemand demands) <> pp_bot
118 pp_bot | bot = ptext SLIT("B")
122 pprDemand (WwLazy False) = char 'L'
123 pprDemand (WwLazy True) = char 'A'
124 pprDemand WwStrict = char 'S'
125 pprDemand WwPrim = char 'P'
126 pprDemand WwEnum = char 'E'
127 pprDemand (WwUnpack nd wu args) = char ch <> parens (hcat (map pprDemand args))
135 instance Outputable Demand where
136 ppr (WwLazy False) = empty
137 ppr other_demand = ptext SLIT("__D") <+> pprDemand other_demand
139 instance Show Demand where
140 showsPrec p d = showsPrecSDoc p (ppr d)
142 -- Reading demands is done in Lex.lhs
146 %************************************************************************
148 \subsection[strictness-IdInfo]{Strictness info about an @Id@}
150 %************************************************************************
152 We specify the strictness of a function by giving information about
153 each of the ``wrapper's'' arguments (see the description about
154 worker/wrapper-style transformations in the PJ/Launchbury paper on
157 The list of @Demands@ specifies: (a)~the strictness properties of a
158 function's arguments; and (b)~the type signature of that worker (if it
159 exists); i.e. its calling convention.
161 Note that the existence of a worker function is now denoted by the Id's
168 | StrictnessInfo [Demand] -- Demands on the arguments.
170 Bool -- True <=> the function diverges regardless of its arguments
171 -- Useful for "error" and other disguised variants thereof.
172 -- BUT NB: f = \x y. error "urk"
173 -- will have info SI [SS] True
174 -- but still (f) and (f 2) are not bot; only (f 3 2) is bot
177 -- NOTA BENE: if the arg demands are, say, [S,L], this means that
178 -- (f bot) is not necy bot, only (f bot x) is bot
179 -- We simply cannot express accurately the strictness of a function
180 -- like f = \x -> case x of (a,b) -> \y -> ...
181 -- The up-side is that we don't need to restrict the strictness info
182 -- to the visible arity of the function.
184 seqStrictnessInfo :: StrictnessInfo -> ()
185 seqStrictnessInfo (StrictnessInfo ds b) = b `seq` seqDemands ds
186 seqStrictnessInfo other = ()
190 mkStrictnessInfo :: ([Demand], Bool) -> StrictnessInfo
192 mkStrictnessInfo (xs, is_bot)
193 | all totally_boring xs && not is_bot = NoStrictnessInfo -- Uninteresting
194 | otherwise = StrictnessInfo xs is_bot
196 totally_boring (WwLazy False) = True
197 totally_boring other = False
199 noStrictnessInfo = NoStrictnessInfo
201 isBottomingStrictness (StrictnessInfo _ bot) = bot
202 isBottomingStrictness NoStrictnessInfo = False
204 -- appIsBottom returns true if an application to n args would diverge
205 appIsBottom (StrictnessInfo ds bot) n = bot && (n >= length ds)
206 appIsBottom NoStrictnessInfo n = False
208 ppStrictnessInfo NoStrictnessInfo = empty
209 ppStrictnessInfo (StrictnessInfo wrapper_args bot) = hsep [pprDemands wrapper_args bot]
213 %************************************************************************
215 \subsection{Strictness indication}
217 %************************************************************************
219 The strictness annotations on types in data type declarations
220 e.g. data T = MkT !Int !(Bool,Bool)
224 = MarkedUserStrict -- "!" in a source decl
225 | MarkedStrict -- "!" in an interface decl: strict but not unboxed
226 | MarkedUnboxed -- "!!" in an interface decl: unboxed
227 | NotMarkedStrict -- No annotation at all
230 isMarkedUnboxed MarkedUnboxed = True
231 isMarkedUnboxed other = False
233 isMarkedStrict NotMarkedStrict = False
234 isMarkedStrict other = True -- All others are strict
236 instance Outputable StrictnessMark where
237 ppr MarkedUserStrict = ptext SLIT("!u")
238 ppr MarkedStrict = ptext SLIT("!")
239 ppr MarkedUnboxed = ptext SLIT("! !")
240 ppr NotMarkedStrict = empty