2 % (c) The University of Glasgow 2006
3 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
5 \section[Demand]{@Demand@: the amount of demand on a value}
9 -- The above warning supression flag is a temporary kludge.
10 -- While working on this module you are encouraged to remove it and fix
11 -- any warnings in the module. See
12 -- http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#Warnings
15 #ifndef OLD_STRICTNESS
16 module Demand () where
22 wwLazy, wwStrict, wwUnpack, wwPrim, wwEnum,
23 isStrict, isLazy, isPrim,
25 pprDemands, seqDemand, seqDemands,
30 ppStrictnessInfo, seqStrictnessInfo,
31 isBottomingStrictness, appIsBottom,
35 #include "HsVersions.h"
42 %************************************************************************
44 \subsection{The @Demand@ data type}
46 %************************************************************************
50 = WwLazy -- Argument is lazy as far as we know
51 MaybeAbsent -- (does not imply worker's existence [etc]).
52 -- If MaybeAbsent == True, then it is
53 -- *definitely* lazy. (NB: Absence implies
56 | WwStrict -- Argument is strict but that's all we know
57 -- (does not imply worker's existence or any
58 -- calling-convention magic)
60 | WwUnpack -- Argument is strict & a single-constructor type
61 Bool -- True <=> wrapper unpacks it; False <=> doesn't
62 [Demand] -- Its constituent parts (whose StrictInfos
63 -- are in the list) should be passed
64 -- as arguments to the worker.
66 | WwPrim -- Argument is of primitive type, therefore
67 -- strict; doesn't imply existence of a worker;
68 -- argument should be passed as is to worker.
70 | WwEnum -- Argument is strict & an enumeration type;
71 -- an Int# representing the tag (start counting
72 -- at zero) should be passed to the worker.
75 type MaybeAbsent = Bool -- True <=> not even used
77 -- versions that don't worry about Absence:
80 wwUnpack xs = WwUnpack False xs
84 seqDemand :: Demand -> ()
85 seqDemand (WwLazy a) = a `seq` ()
86 seqDemand (WwUnpack b ds) = b `seq` seqDemands ds
90 seqDemands (d:ds) = seqDemand d `seq` seqDemands ds
94 %************************************************************************
96 \subsection{Functions over @Demand@}
98 %************************************************************************
101 isLazy :: Demand -> Bool
102 isLazy (WwLazy _) = True
105 isStrict :: Demand -> Bool
106 isStrict d = not (isLazy d)
108 isPrim :: Demand -> Bool
114 %************************************************************************
116 \subsection{Instances}
118 %************************************************************************
122 pprDemands demands bot = hcat (map pprDemand demands) <> pp_bot
124 pp_bot | bot = ptext SLIT("B")
128 pprDemand (WwLazy False) = char 'L'
129 pprDemand (WwLazy True) = char 'A'
130 pprDemand WwStrict = char 'S'
131 pprDemand WwPrim = char 'P'
132 pprDemand WwEnum = char 'E'
133 pprDemand (WwUnpack wu args) = char ch <> parens (hcat (map pprDemand args))
135 ch = if wu then 'U' else 'u'
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
179 -- NOTA BENE: if the arg demands are, say, [S,L], this means that
180 -- (f bot) is not necy bot, only (f bot x) is bot
181 -- We simply cannot express accurately the strictness of a function
182 -- like f = \x -> case x of (a,b) -> \y -> ...
183 -- The up-side is that we don't need to restrict the strictness info
184 -- to the visible arity of the function.
186 seqStrictnessInfo :: StrictnessInfo -> ()
187 seqStrictnessInfo (StrictnessInfo ds b) = b `seq` seqDemands ds
188 seqStrictnessInfo other = ()
192 mkStrictnessInfo :: ([Demand], Bool) -> StrictnessInfo
194 mkStrictnessInfo (xs, is_bot)
195 | all totally_boring xs && not is_bot = NoStrictnessInfo -- Uninteresting
196 | otherwise = StrictnessInfo xs is_bot
198 totally_boring (WwLazy False) = True
199 totally_boring other = False
201 noStrictnessInfo = NoStrictnessInfo
203 isBottomingStrictness (StrictnessInfo _ bot) = bot
204 isBottomingStrictness NoStrictnessInfo = False
206 -- appIsBottom returns true if an application to n args would diverge
207 appIsBottom (StrictnessInfo ds bot) n = bot && (listLengthCmp ds n /=GT) -- not more than 'n' elts in 'ds'.
208 appIsBottom NoStrictnessInfo n = False
210 ppStrictnessInfo NoStrictnessInfo = empty
211 ppStrictnessInfo (StrictnessInfo wrapper_args bot) = hsep [pprDemands wrapper_args bot]
215 #endif /* OLD_STRICTNESS */