Id.lhs 17.7 KB
Newer Older
1
%
Simon Marlow's avatar
Simon Marlow committed
2
% (c) The University of Glasgow 2006
3
% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
4
5
6
7
%
\section[Id]{@Ids@: Value and constructor identifiers}

\begin{code}
8
module Id (
9
	Id, DictId,
10

11
	-- Simple construction
12
	mkGlobalId, mkLocalId, mkLocalIdWithInfo, 
13
	mkSysLocal, mkUserLocal, mkVanillaGlobal,
14
	mkTemplateLocals, mkTemplateLocalsNum, mkWildId, mkTemplateLocal,
15
	mkWorkerId, mkExportedLocalId,
16
17

	-- Taking an Id apart
18
	idName, idType, idUnique, idInfo,
19
	isId, globalIdDetails, idPrimRep,
20
	recordSelectorFieldLabel,
21

22
	-- Modifying an Id
23
	setIdName, setIdUnique, Id.setIdType, setIdExported, setIdNotExported, 
24
	setIdInfo, lazySetIdInfo, modifyIdInfo, maybeModifyIdInfo,
25
	zapLamIdInfo, zapDemandIdInfo, zapFragileIdInfo,
26
27

	-- Predicates
28
	isImplicitId, isDeadBinder, isDictId, isStrictId,
29
	isExportedId, isLocalId, isGlobalId,
30
	isRecordSelector, isNaughtyRecordSelector,
31
	isClassOpId_maybe,
32
	isPrimOpId, isPrimOpId_maybe, 
33
	isFCallId, isFCallId_maybe,
34
	isDataConWorkId, isDataConWorkId_maybe, isDataConId_maybe, idDataCon,
35
	isBottomingId, idIsFrom,
36
        isTickBoxOp, isTickBoxOp_maybe,
37
	hasNoBinding, 
38
39
40
41

	-- Inline pragma stuff
	idInlinePragma, setInlinePragma, modifyInlinePragma, 

42

43
	-- One shot lambda stuff
44
45
	isOneShotBndr, isOneShotLambda, isStateHackType,
	setOneShotLambda, clearOneShotLambda,
46

47
48
	-- IdInfo stuff
	setIdUnfolding,
49
	setIdArity,
50
51
	setIdNewDemandInfo, 
	setIdNewStrictness, zapIdNewStrictness,
52
	setIdWorkerInfo,
53
	setIdSpecialisation,
54
	setIdCafInfo,
55
	setIdOccInfo,
56

57
#ifdef OLD_STRICTNESS
58
59
60
61
62
63
64
65
	idDemandInfo, 
	idStrictness, 
	idCprInfo,
	setIdStrictness, 
	setIdDemandInfo, 
	setIdCprInfo,
#endif

66
	idArity, 
67
	idNewDemandInfo, idNewDemandInfo_maybe,
68
	idNewStrictness, idNewStrictness_maybe, 
69
70
	idWorkerInfo,
	idUnfolding,
simonpj@microsoft.com's avatar
simonpj@microsoft.com committed
71
	idSpecialisation, idCoreRules, idHasRules,
72
73
	idCafInfo,
	idLBVarInfo,
74
	idOccInfo,
75

76
#ifdef OLD_STRICTNESS
77
	newStrictnessFromOld 	-- Temporary
78
#endif
79

80
    ) where
81

82
#include "HsVersions.h"
sof's avatar
sof committed
83

Simon Marlow's avatar
Simon Marlow committed
84
85
86
87
88
89
90
91
import CoreSyn
import BasicTypes
import qualified Var
import Var hiding (mkLocalId, mkGlobalId, mkExportedLocalId)
import TyCon
import Type
import TcType
import TysPrim
92
import IdInfo 
93
#ifdef OLD_STRICTNESS
Simon Marlow's avatar
Simon Marlow committed
94
import qualified Demand
95
#endif
Simon Marlow's avatar
Simon Marlow committed
96
97
98
99
import DataCon
import NewDemand
import Name
import Module
twanvl's avatar
twanvl committed
100
101
102
import Class
import PrimOp
import ForeignCall
Simon Marlow's avatar
Simon Marlow committed
103
104
105
import OccName
import Maybes
import SrcLoc
106
import Outputable
Simon Marlow's avatar
Simon Marlow committed
107
108
109
import Unique
import FastString
import StaticFlags
110

111
-- infixl so you can say (id `set` a `set` b)
112
infixl 	1 `setIdUnfolding`,
113
	  `setIdArity`,
114
115
	  `setIdNewDemandInfo`,
	  `setIdNewStrictness`,
116
	  `setIdWorkerInfo`,
117
	  `setIdSpecialisation`,
118
	  `setInlinePragma`,
119
	  `idCafInfo`
120
#ifdef OLD_STRICTNESS
121
122
123
124
	  ,`idCprInfo`
	  ,`setIdStrictness`
	  ,`setIdDemandInfo`
#endif
125
126
127
\end{code}


128

129
130
%************************************************************************
%*									*
131
\subsection{Simple Id construction}
132
133
134
%*									*
%************************************************************************

135
136
137
Absolutely all Ids are made by mkId.  It is just like Var.mkId,
but in addition it pins free-tyvar-info onto the Id's type, 
where it can easily be found.
138

139
\begin{code}
140
mkLocalIdWithInfo :: Name -> Type -> IdInfo -> Id
Ian Lynagh's avatar
Ian Lynagh committed
141
mkLocalIdWithInfo name ty info = Var.mkLocalId name ty info
142

143
mkExportedLocalId :: Name -> Type -> Id
Ian Lynagh's avatar
Ian Lynagh committed
144
mkExportedLocalId name ty = Var.mkExportedLocalId name ty vanillaIdInfo
145

146
mkGlobalId :: GlobalIdDetails -> Name -> Type -> IdInfo -> Id
Ian Lynagh's avatar
Ian Lynagh committed
147
mkGlobalId details name ty info = Var.mkGlobalId details name ty info
148
\end{code}
149

150
\begin{code}
151
mkLocalId :: Name -> Type -> Id
152
mkLocalId name ty = mkLocalIdWithInfo name ty vanillaIdInfo
153
154

-- SysLocal: for an Id being created by the compiler out of thin air...
155
156
157
158
mkSysLocal :: FastString -> Unique -> Type -> Id
mkSysLocal fs uniq ty = mkLocalId (mkSystemVarName uniq fs) ty


159
-- UserLocal: an Id with a name the user might recognize...
160
mkUserLocal :: OccName -> Unique -> Type -> SrcSpan -> Id
161
mkVanillaGlobal :: Name -> Type -> IdInfo -> Id
162

163
mkUserLocal occ uniq ty loc = mkLocalId (mkInternalName    uniq occ loc) ty
164
mkVanillaGlobal 	    = mkGlobalId VanillaGlobal
165
\end{code}
166
167
168
169

Make some local @Ids@ for a template @CoreExpr@.  These have bogus
@Uniques@, but that's OK because the templates are supposed to be
instantiated before use.
170
 
171
\begin{code}
172
173
-- "Wild Id" typically used when you need a binder that you don't expect to use
mkWildId :: Type -> Id
174
mkWildId ty = mkSysLocal FSLIT("wild") (mkBuiltinUnique 1) ty
175

176
mkWorkerId :: Unique -> Id -> Type -> Id
177
-- A worker gets a local name.  CoreTidy will externalise it if necessary.
178
179
180
mkWorkerId uniq unwrkr ty
  = mkLocalId wkr_name ty
  where
181
    wkr_name = mkInternalName uniq (mkWorkerOcc (getOccName unwrkr)) (getSrcSpan unwrkr)
182

183
-- "Template locals" typically used in unfoldings
184
mkTemplateLocals :: [Type] -> [Id]
185
mkTemplateLocals tys = zipWith mkTemplateLocal [1..] tys
186

187
mkTemplateLocalsNum :: Int -> [Type] -> [Id]
188
-- The Int gives the starting point for unique allocation
189
mkTemplateLocalsNum n tys = zipWith mkTemplateLocal [n..] tys
190

191
mkTemplateLocal :: Int -> Type -> Id
192
mkTemplateLocal i ty = mkSysLocal FSLIT("tpl") (mkBuiltinUnique i) ty
193
194
195
\end{code}


196
197
198
199
200
201
202
%************************************************************************
%*									*
\subsection[Id-general-funs]{General @Id@-related functions}
%*									*
%************************************************************************

\begin{code}
203
setIdType :: Id -> Type -> Id
204
	-- Add free tyvar info to the type
Ian Lynagh's avatar
Ian Lynagh committed
205
setIdType id ty = seqType ty `seq` Var.setIdType id ty
sof's avatar
sof committed
206

207
208
idPrimRep :: Id -> PrimRep
idPrimRep id = typePrimRep (idType id)
209
210
211
212
213
\end{code}


%************************************************************************
%*									*
214
\subsection{Special Ids}
215
216
217
%*									*
%************************************************************************

218
\begin{code}
219
recordSelectorFieldLabel :: Id -> (TyCon, FieldLabel)
220
221
recordSelectorFieldLabel id
  = case globalIdDetails id of
twanvl's avatar
twanvl committed
222
223
224
225
226
227
228
229
230
231
232
233
234
235
        RecordSelId { sel_tycon = tycon, sel_label = lbl } -> (tycon,lbl)
        _ -> panic "recordSelectorFieldLabel"

isRecordSelector        :: Var -> Bool
isNaughtyRecordSelector :: Var -> Bool
isPrimOpId              :: Var -> Bool
isFCallId               :: Var -> Bool
isDataConWorkId         :: Var -> Bool
hasNoBinding            :: Var -> Bool

isClassOpId_maybe       :: Var -> Maybe Class
isPrimOpId_maybe        :: Var -> Maybe PrimOp
isFCallId_maybe         :: Var -> Maybe ForeignCall
isDataConWorkId_maybe   :: Var -> Maybe DataCon
sof's avatar
sof committed
236

237
isRecordSelector id = case globalIdDetails id of
twanvl's avatar
twanvl committed
238
239
                        RecordSelId {}  -> True
                        _               -> False
sof's avatar
sof committed
240

241
isNaughtyRecordSelector id = case globalIdDetails id of
twanvl's avatar
twanvl committed
242
243
                        RecordSelId { sel_naughty = n } -> n
                        _                               -> False
244

245
246
247
248
isClassOpId_maybe id = case globalIdDetails id of
			ClassOpId cls -> Just cls
			_other        -> Nothing

249
isPrimOpId id = case globalIdDetails id of
twanvl's avatar
twanvl committed
250
251
                        PrimOpId _ -> True
                        _          -> False
252

253
isPrimOpId_maybe id = case globalIdDetails id of
twanvl's avatar
twanvl committed
254
255
                        PrimOpId op -> Just op
                        _           -> Nothing
256

257
isFCallId id = case globalIdDetails id of
twanvl's avatar
twanvl committed
258
259
                        FCallId _ -> True
                        _         -> False
260
261

isFCallId_maybe id = case globalIdDetails id of
twanvl's avatar
twanvl committed
262
263
                        FCallId call -> Just call
                        _            -> Nothing
264

265
isDataConWorkId id = case globalIdDetails id of
twanvl's avatar
twanvl committed
266
267
                        DataConWorkId _ -> True
                        _               -> False
sof's avatar
sof committed
268

269
isDataConWorkId_maybe id = case globalIdDetails id of
twanvl's avatar
twanvl committed
270
271
                        DataConWorkId con -> Just con
                        _                 -> Nothing
sof's avatar
sof committed
272

273
274
isDataConId_maybe :: Id -> Maybe DataCon
isDataConId_maybe id = case globalIdDetails id of
twanvl's avatar
twanvl committed
275
276
277
                         DataConWorkId con -> Just con
                         DataConWrapId con -> Just con
                         _                 -> Nothing
278

279
280
281
282
283
284
idDataCon :: Id -> DataCon
-- Get from either the worker or the wrapper to the DataCon
-- Currently used only in the desugarer
--	 INVARIANT: idDataCon (dataConWrapId d) = d
-- (Remember, dataConWrapId can return either the wrapper or the worker.)
idDataCon id = case globalIdDetails id of
twanvl's avatar
twanvl committed
285
286
287
                  DataConWorkId con -> con
                  DataConWrapId con -> con
                  _                 -> pprPanic "idDataCon" (ppr id)
288
289


290
291
292
isDictId :: Id -> Bool
isDictId id = isDictTy (idType id)

293
294
295
296
-- hasNoBinding returns True of an Id which may not have a
-- binding, even though it is defined in this module.  
-- Data constructor workers used to be things of this kind, but
-- they aren't any more.  Instead, we inject a binding for 
297
298
-- them at the CorePrep stage. 
-- EXCEPT: unboxed tuples, which definitely have no binding
299
hasNoBinding id = case globalIdDetails id of
300
			PrimOpId _  	 -> True	-- See Note [Primop wrappers]
301
302
			FCallId _   	 -> True
			DataConWorkId dc -> isUnboxedTupleCon dc
twanvl's avatar
twanvl committed
303
			_                -> False
304

305
isImplicitId :: Id -> Bool
306
307
308
	-- isImplicitId tells whether an Id's info is implied by other
	-- declarations, so we don't need to put its signature in an interface
	-- file, even if it's mentioned in some other interface unfolding.
309
isImplicitId id
310
  = case globalIdDetails id of
311
	RecordSelId {}  -> True
312
        FCallId _       -> True
313
        PrimOpId _      -> True
314
	ClassOpId _	-> True
315
        DataConWorkId _ -> True
316
317
	DataConWrapId _ -> True
		-- These are are implied by their type or class decl;
318
		-- remember that all type and class decls appear in the interface file.
319
320
		-- The dfun id is not an implicit Id; it must *not* be omitted, because 
		-- it carries version info for the instance decl
twanvl's avatar
twanvl committed
321
        _               -> False
322
323
324

idIsFrom :: Module -> Id -> Bool
idIsFrom mod id = nameIsLocalOrFrom mod (idName id)
325
326
\end{code}

327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
Note [Primop wrappers]
~~~~~~~~~~~~~~~~~~~~~~
Currently hasNoBinding claims that PrimOpIds don't have a curried
function definition.  But actually they do, in GHC.PrimopWrappers,
which is auto-generated from prelude/primops.txt.pp.  So actually, hasNoBinding
could return 'False' for PrimOpIds.

But we'd need to add something in CoreToStg to swizzle any unsaturated
applications of GHC.Prim.plusInt# to GHC.PrimopWrappers.plusInt#.

Nota Bene: GHC.PrimopWrappers is needed *regardless*, because it's
used by GHCi, which does not implement primops direct at all.



342
343
\begin{code}
isDeadBinder :: Id -> Bool
344
isDeadBinder bndr | isId bndr = isDeadOcc (idOccInfo bndr)
345
		  | otherwise = False	-- TyVars count as not dead
346
347
\end{code}

348
349
350
351
\begin{code}
isTickBoxOp :: Id -> Bool
isTickBoxOp id = 
  case globalIdDetails id of
twanvl's avatar
twanvl committed
352
    TickBoxOpId _    -> True
353
354
355
356
357
358
359
360
    _                -> False

isTickBoxOp_maybe :: Id -> Maybe TickBoxOp
isTickBoxOp_maybe id = 
  case globalIdDetails id of
    TickBoxOpId tick -> Just tick
    _                -> Nothing
\end{code}
361

362
363
%************************************************************************
%*									*
364
\subsection{IdInfo stuff}
365
366
367
%*									*
%************************************************************************

368
\begin{code}
369
370
	---------------------------------
	-- ARITY
371
idArity :: Id -> Arity
372
idArity id = arityInfo (idInfo id)
373

374
375
setIdArity :: Id -> Arity -> Id
setIdArity id arity = modifyIdInfo (`setArityInfo` arity) id
376

377
#ifdef OLD_STRICTNESS
378
	---------------------------------
379
	-- (OLD) STRICTNESS 
380
idStrictness :: Id -> StrictnessInfo
381
idStrictness id = strictnessInfo (idInfo id)
382

383
setIdStrictness :: Id -> StrictnessInfo -> Id
384
setIdStrictness id strict_info = modifyIdInfo (`setStrictnessInfo` strict_info) id
385
#endif
386

387
388
-- isBottomingId returns true if an application to n args would diverge
isBottomingId :: Id -> Bool
389
390
391
392
393
394
395
396
397
398
isBottomingId id = isBottomingSig (idNewStrictness id)

idNewStrictness_maybe :: Id -> Maybe StrictSig
idNewStrictness :: Id -> StrictSig

idNewStrictness_maybe id = newStrictnessInfo (idInfo id)
idNewStrictness       id = idNewStrictness_maybe id `orElse` topSig

setIdNewStrictness :: Id -> StrictSig -> Id
setIdNewStrictness id sig = modifyIdInfo (`setNewStrictnessInfo` Just sig) id
399

400
401
zapIdNewStrictness :: Id -> Id
zapIdNewStrictness id = modifyIdInfo (`setNewStrictnessInfo` Nothing) id
402
403
404
405
406
407
408
409
410
411
412
413
414
415
\end{code}

This predicate says whether the id has a strict demand placed on it or
has a type such that it can always be evaluated strictly (e.g., an
unlifted type, but see the comment for isStrictType).  We need to
check separately whether <id> has a so-called "strict type" because if
the demand for <id> hasn't been computed yet but <id> has a strict
type, we still want (isStrictId <id>) to be True.
\begin{code}
isStrictId :: Id -> Bool
isStrictId id
  = ASSERT2( isId id, text "isStrictId: not an id: " <+> ppr id )
           (isStrictDmd (idNewDemandInfo id)) || 
           (isStrictType (idType id))
416

417
	---------------------------------
418
	-- WORKER ID
419
420
idWorkerInfo :: Id -> WorkerInfo
idWorkerInfo id = workerInfo (idInfo id)
421
422

setIdWorkerInfo :: Id -> WorkerInfo -> Id
423
setIdWorkerInfo id work_info = modifyIdInfo (`setWorkerInfo` work_info) id
424

425
426
	---------------------------------
	-- UNFOLDING
427
428
idUnfolding :: Id -> Unfolding
idUnfolding id = unfoldingInfo (idInfo id)
429

430
setIdUnfolding :: Id -> Unfolding -> Id
431
setIdUnfolding id unfolding = modifyIdInfo (`setUnfoldingInfo` unfolding) id
sof's avatar
sof committed
432

433
#ifdef OLD_STRICTNESS
434
	---------------------------------
435
	-- (OLD) DEMAND
436
idDemandInfo :: Id -> Demand.Demand
437
idDemandInfo id = demandInfo (idInfo id)
438

439
setIdDemandInfo :: Id -> Demand.Demand -> Id
440
setIdDemandInfo id demand_info = modifyIdInfo (`setDemandInfo` demand_info) id
441
#endif
442

443
444
445
446
447
idNewDemandInfo_maybe :: Id -> Maybe NewDemand.Demand
idNewDemandInfo       :: Id -> NewDemand.Demand

idNewDemandInfo_maybe id = newDemandInfo (idInfo id)
idNewDemandInfo       id = newDemandInfo (idInfo id) `orElse` NewDemand.topDmd
448
449

setIdNewDemandInfo :: Id -> NewDemand.Demand -> Id
450
setIdNewDemandInfo id dmd = modifyIdInfo (`setNewDemandInfo` Just dmd) id
451

452
453
	---------------------------------
	-- SPECIALISATION
454
idSpecialisation :: Id -> SpecInfo
455
idSpecialisation id = specInfo (idInfo id)
456

457
458
idCoreRules :: Id -> [CoreRule]
idCoreRules id = specInfoRules (idSpecialisation id)
459

simonpj@microsoft.com's avatar
simonpj@microsoft.com committed
460
461
462
idHasRules :: Id -> Bool
idHasRules id = not (isEmptySpecInfo (idSpecialisation id))

463
setIdSpecialisation :: Id -> SpecInfo -> Id
464
setIdSpecialisation id spec_info = modifyIdInfo (`setSpecInfo` spec_info) id
465

466
467
	---------------------------------
	-- CAF INFO
468
idCafInfo :: Id -> CafInfo
469
#ifdef OLD_STRICTNESS
470
471
472
473
idCafInfo id = case cgInfo (idInfo id) of
		  NoCgInfo -> pprPanic "idCafInfo" (ppr id)
		  info     -> cgCafInfo info
#else
474
idCafInfo id = cafInfo (idInfo id)
475
#endif
476
477
478
479

setIdCafInfo :: Id -> CafInfo -> Id
setIdCafInfo id caf_info = modifyIdInfo (`setCafInfo` caf_info) id

480
481
	---------------------------------
	-- CPR INFO
482
#ifdef OLD_STRICTNESS
483
idCprInfo :: Id -> CprInfo
484
idCprInfo id = cprInfo (idInfo id)
485
486

setIdCprInfo :: Id -> CprInfo -> Id
487
setIdCprInfo id cpr_info = modifyIdInfo (`setCprInfo` cpr_info) id
488
#endif
489
490
491

	---------------------------------
	-- Occcurrence INFO
492
493
idOccInfo :: Id -> OccInfo
idOccInfo id = occInfo (idInfo id)
494
495
496

setIdOccInfo :: Id -> OccInfo -> Id
setIdOccInfo id occ_info = modifyIdInfo (`setOccInfo` occ_info) id
497
498
\end{code}

sof's avatar
sof committed
499

500
501
502
503
	---------------------------------
	-- INLINING
The inline pragma tells us to be very keen to inline this Id, but it's still
OK not to if optimisation is switched off.
504
505

\begin{code}
506
507
idInlinePragma :: Id -> InlinePragInfo
idInlinePragma id = inlinePragInfo (idInfo id)
508

509
setInlinePragma :: Id -> InlinePragInfo -> Id
510
setInlinePragma id prag = modifyIdInfo (`setInlinePragInfo` prag) id
511

512
modifyInlinePragma :: Id -> (InlinePragInfo -> InlinePragInfo) -> Id
513
modifyInlinePragma id fn = modifyIdInfo (\info -> info `setInlinePragInfo` (fn (inlinePragInfo info))) id
514
\end{code}
515
516
517
518
519


	---------------------------------
	-- ONE-SHOT LAMBDAS
\begin{code}
520
521
522
idLBVarInfo :: Id -> LBVarInfo
idLBVarInfo id = lbvarInfo (idInfo id)

523
524
525
isOneShotBndr :: Id -> Bool
-- This one is the "business end", called externally.
-- Its main purpose is to encapsulate the Horrible State Hack
526
isOneShotBndr id = isOneShotLambda id || isStateHackType (idType id)
527

528
529
isStateHackType :: Type -> Bool
isStateHackType ty
530
531
532
  | opt_NoStateHack 
  = False
  | otherwise
533
534
  = case splitTyConApp_maybe ty of
	Just (tycon,_) -> tycon == statePrimTyCon
twanvl's avatar
twanvl committed
535
        _              -> False
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
	-- This is a gross hack.  It claims that 
	-- every function over realWorldStatePrimTy is a one-shot
	-- function.  This is pretty true in practice, and makes a big
	-- difference.  For example, consider
	--	a `thenST` \ r -> ...E...
	-- The early full laziness pass, if it doesn't know that r is one-shot
	-- will pull out E (let's say it doesn't mention r) to give
	--	let lvl = E in a `thenST` \ r -> ...lvl...
	-- When `thenST` gets inlined, we end up with
	--	let lvl = E in \s -> case a s of (r, s') -> ...lvl...
	-- and we don't re-inline E.
	--
	-- It would be better to spot that r was one-shot to start with, but
	-- I don't want to rely on that.
	--
	-- Another good example is in fill_in in PrelPack.lhs.  We should be able to
	-- spot that fill_in has arity 2 (and when Keith is done, we will) but we can't yet.


-- The OneShotLambda functions simply fiddle with the IdInfo flag
556
isOneShotLambda :: Id -> Bool
557
558
559
isOneShotLambda id = case idLBVarInfo id of
                       IsOneShotLambda  -> True
                       NoLBVarInfo      -> False
560
561

setOneShotLambda :: Id -> Id
562
setOneShotLambda id = modifyIdInfo (`setLBVarInfo` IsOneShotLambda) id
563
564
565
566
567
568
569
570
571

clearOneShotLambda :: Id -> Id
clearOneShotLambda id 
  | isOneShotLambda id = modifyIdInfo (`setLBVarInfo` NoLBVarInfo) id
  | otherwise	       = id			

-- But watch out: this may change the type of something else
--	f = \x -> e
-- If we change the one-shot-ness of x, f's type changes
572
\end{code}
573
574

\begin{code}
575
576
577
zapInfo :: (IdInfo -> Maybe IdInfo) -> Id -> Id
zapInfo zapper id = maybeModifyIdInfo (zapper (idInfo id)) id

578
zapLamIdInfo :: Id -> Id
579
580
zapLamIdInfo = zapInfo zapLamInfo

twanvl's avatar
twanvl committed
581
zapDemandIdInfo :: Id -> Id
582
zapDemandIdInfo = zapInfo zapDemandInfo
583

584
585
zapFragileIdInfo :: Id -> Id
zapFragileIdInfo = zapInfo zapFragileInfo 
586
\end{code}
587