2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
4 \section[Demand]{@Demand@: the amount of demand on a value}
10 wwLazy, wwStrict, wwUnpack, wwPrim, wwEnum,
11 isStrict, isLazy, isPrim,
13 pprDemands, seqDemand, seqDemands,
18 ppStrictnessInfo, seqStrictnessInfo,
19 isBottomingStrictness, appIsBottom,
23 #include "HsVersions.h"
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
48 Bool -- True <=> wrapper unpacks it; False <=> doesn't
49 [Demand] -- Its constituent parts (whose StrictInfos
50 -- are in the list) should be passed
51 -- as arguments to the worker.
53 | WwPrim -- Argument is of primitive type, therefore
54 -- strict; doesn't imply existence of a worker;
55 -- argument should be passed as is to worker.
57 | WwEnum -- Argument is strict & an enumeration type;
58 -- an Int# representing the tag (start counting
59 -- at zero) should be passed to the worker.
62 type MaybeAbsent = Bool -- True <=> not even used
64 -- versions that don't worry about Absence:
67 wwUnpack xs = WwUnpack False xs
71 seqDemand :: Demand -> ()
72 seqDemand (WwLazy a) = a `seq` ()
73 seqDemand (WwUnpack b ds) = b `seq` seqDemands ds
77 seqDemands (d:ds) = seqDemand d `seq` seqDemands ds
81 %************************************************************************
83 \subsection{Functions over @Demand@}
85 %************************************************************************
88 isLazy :: Demand -> Bool
89 isLazy (WwLazy _) = True
92 isStrict :: Demand -> Bool
93 isStrict d = not (isLazy d)
95 isPrim :: Demand -> Bool
101 %************************************************************************
103 \subsection{Instances}
105 %************************************************************************
109 pprDemands demands bot = hcat (map pprDemand demands) <> pp_bot
111 pp_bot | bot = ptext SLIT("B")
115 pprDemand (WwLazy False) = char 'L'
116 pprDemand (WwLazy True) = char 'A'
117 pprDemand WwStrict = char 'S'
118 pprDemand WwPrim = char 'P'
119 pprDemand WwEnum = char 'E'
120 pprDemand (WwUnpack wu args) = char ch <> parens (hcat (map pprDemand args))
122 ch = if wu then 'U' else 'u'
124 instance Outputable Demand where
125 ppr (WwLazy False) = empty
126 ppr other_demand = ptext SLIT("__D") <+> pprDemand other_demand
128 instance Show Demand where
129 showsPrec p d = showsPrecSDoc p (ppr d)
131 -- Reading demands is done in Lex.lhs
135 %************************************************************************
137 \subsection[strictness-IdInfo]{Strictness info about an @Id@}
139 %************************************************************************
141 We specify the strictness of a function by giving information about
142 each of the ``wrapper's'' arguments (see the description about
143 worker/wrapper-style transformations in the PJ/Launchbury paper on
146 The list of @Demands@ specifies: (a)~the strictness properties of a
147 function's arguments; and (b)~the type signature of that worker (if it
148 exists); i.e. its calling convention.
150 Note that the existence of a worker function is now denoted by the Id's
157 | StrictnessInfo [Demand] -- Demands on the arguments.
159 Bool -- True <=> the function diverges regardless of its arguments
160 -- Useful for "error" and other disguised variants thereof.
161 -- BUT NB: f = \x y. error "urk"
162 -- will have info SI [SS] True
163 -- but still (f) and (f 2) are not bot; only (f 3 2) is bot
166 -- NOTA BENE: if the arg demands are, say, [S,L], this means that
167 -- (f bot) is not necy bot, only (f bot x) is bot
168 -- We simply cannot express accurately the strictness of a function
169 -- like f = \x -> case x of (a,b) -> \y -> ...
170 -- The up-side is that we don't need to restrict the strictness info
171 -- to the visible arity of the function.
173 seqStrictnessInfo :: StrictnessInfo -> ()
174 seqStrictnessInfo (StrictnessInfo ds b) = b `seq` seqDemands ds
175 seqStrictnessInfo other = ()
179 mkStrictnessInfo :: ([Demand], Bool) -> StrictnessInfo
181 mkStrictnessInfo (xs, is_bot)
182 | all totally_boring xs && not is_bot = NoStrictnessInfo -- Uninteresting
183 | otherwise = StrictnessInfo xs is_bot
185 totally_boring (WwLazy False) = True
186 totally_boring other = False
188 noStrictnessInfo = NoStrictnessInfo
190 isBottomingStrictness (StrictnessInfo _ bot) = bot
191 isBottomingStrictness NoStrictnessInfo = False
193 -- appIsBottom returns true if an application to n args would diverge
194 appIsBottom (StrictnessInfo ds bot) n = bot && (n >= length ds)
195 appIsBottom NoStrictnessInfo n = False
197 ppStrictnessInfo NoStrictnessInfo = empty
198 ppStrictnessInfo (StrictnessInfo wrapper_args bot) = hsep [pprDemands wrapper_args bot]