- pp_data_or_new = case data_or_new of
- DataType -> uppPStr SLIT("data")
- NewType -> uppPStr SLIT("newtype")
-
- ppr_context [] = uppNil
--- ppr_context [(c,t)] = uppCat [ppr_name c, ppr_ty t, uppPStr SLIT("=>")]
- ppr_context cs
- = uppBesides[uppStr "{{",
- uppInterleave uppComma [uppCat [ppr_name c, ppr_ty t] | (c,t) <- cs],
- uppStr "}}", uppPStr SLIT(" =>")]
-
- pp_condecls
- = let
- (c:cs) = cons
- in
- uppCat ((ppr_con c) : (map ppr_next_con cs))
-
- ppr_next_con con = uppCat [uppChar '|', ppr_con con]
-
- ppr_con con
- = let
- con_arg_tys = dataConRawArgTys con
- labels = dataConFieldLabels con -- none if not a record
- strict_marks = dataConStrictMarks con
- in
- uppCat [ppr_name con, ppr_fields labels strict_marks con_arg_tys]
-
- ppr_fields labels strict_marks con_arg_tys
- = if null labels then -- not a record thingy
- uppIntersperse uppSP (zipWithEqual "ppr_fields" ppr_bang_ty strict_marks con_arg_tys)
- else
- uppCat [ uppChar '{',
- uppInterleave uppComma (zipWith3Equal "ppr_field" ppr_field labels strict_marks con_arg_tys),
- uppChar '}' ]
-
- ppr_bang_ty b t
- = uppBeside (case b of { MarkedStrict -> uppChar '!'; _ -> uppNil })
- (prettyToUn (pprParendType PprInterface t))
-
- ppr_field l b t
- = uppBesides [ppr_name l, uppPStr SLIT(" :: "),
- case b of { MarkedStrict -> uppChar '!'; _ -> uppNil },
- ppr_ty t]
+ id_type = idType id
+ core_idinfo = idInfo id
+ stg_idinfo = get_idinfo id
+
+ hs_idinfo | opt_OmitInterfacePragmas = []
+ | otherwise = arity_hsinfo ++ caf_hsinfo ++ cpr_hsinfo ++
+ strict_hsinfo ++ wrkr_hsinfo ++ unfold_hsinfo
+
+ ------------ Arity --------------
+ arity_info = arityInfo stg_idinfo
+ stg_arity = arityLowerBound arity_info
+ arity_hsinfo = case arityInfo stg_idinfo of
+ a@(ArityExactly n) -> [HsArity a]
+ other -> []
+
+ ------------ Caf Info --------------
+ caf_hsinfo = case cafInfo stg_idinfo of
+ NoCafRefs -> [HsNoCafRefs]
+ otherwise -> []
+
+ ------------ CPR Info --------------
+ cpr_hsinfo = case cprInfo core_idinfo of
+ ReturnsCPR -> [HsCprInfo]
+ NoCPRInfo -> []
+
+ ------------ Strictness --------------
+ strict_info = strictnessInfo core_idinfo
+ bottoming_fn = isBottomingStrictness strict_info
+ strict_hsinfo = case strict_info of
+ NoStrictnessInfo -> []
+ info -> [HsStrictness info]
+
+
+ ------------ Worker --------------
+ -- We only treat a function as having a worker if
+ -- the exported arity (which is now the number of visible lambdas)
+ -- is the same as the arity at the moment of the w/w split
+ -- If so, we can safely omit the unfolding inside the wrapper, and
+ -- instead re-generate it from the type/arity/strictness info
+ -- But if the arity has changed, we just take the simple path and
+ -- put the unfolding into the interface file, forgetting the fact
+ -- that it's a wrapper.
+ --
+ -- How can this happen? Sometimes we get
+ -- f = coerce t (\x y -> $wf x y)
+ -- at the moment of w/w split; but the eta reducer turns it into
+ -- f = coerce t $wf
+ -- which is perfectly fine except that the exposed arity so far as
+ -- the code generator is concerned (zero) differs from the arity
+ -- when we did the split (2).
+ --
+ -- All this arises because we use 'arity' to mean "exactly how many
+ -- top level lambdas are there" in interface files; but during the
+ -- compilation of this module it means "how many things can I apply
+ -- this to".
+ work_info = workerInfo core_idinfo
+ HasWorker work_id _ = work_info
+
+ has_worker = case work_info of
+ HasWorker work_id wrap_arity
+ | wrap_arity == stg_arity -> True
+ | otherwise -> pprTrace "ifaceId: arity change:" (ppr id)
+ False
+
+ other -> False
+
+ wrkr_hsinfo | has_worker = [HsWorker (toRdrName work_id)]
+ | otherwise = []
+
+ ------------ Unfolding --------------
+ inline_pragma = inlinePragInfo core_idinfo
+ dont_inline = isNeverInlinePrag inline_pragma
+
+ unfold_hsinfo | show_unfold = [HsUnfold inline_pragma (toUfExpr rhs)]
+ | otherwise = []
+
+ show_unfold = not has_worker && -- Not unnecessary
+ not bottoming_fn && -- Not necessary
+ not dont_inline &&
+ not loop_breaker &&
+ rhs_is_small && -- Small enough
+ okToUnfoldInHiFile rhs -- No casms etc
+
+ rhs_is_small = couldBeSmallEnoughToInline opt_UF_HiFileThreshold rhs
+
+ ------------ Specialisations --------------
+ spec_info = specInfo core_idinfo
+
+ ------------ Occ info --------------
+ loop_breaker = isLoopBreaker (occInfo core_idinfo)
+
+ ------------ Extra free Ids --------------
+ new_needed_ids | opt_OmitInterfacePragmas = emptyVarSet
+ | otherwise = worker_ids `unionVarSet`
+ unfold_ids `unionVarSet`
+ spec_ids
+
+ worker_ids | has_worker && interestingId work_id = unitVarSet work_id
+ -- Conceivably, the worker might come from
+ -- another module
+ | otherwise = emptyVarSet
+
+ spec_ids = filterVarSet interestingId (rulesRhsFreeVars spec_info)
+
+ unfold_ids | show_unfold = find_fvs rhs
+ | otherwise = emptyVarSet
+
+ find_fvs expr = exprSomeFreeVars interestingId expr
+
+interestingId id = isId id && isLocallyDefined id && not (hasNoBinding id)