- SpecInfo [t1, a, t3] (\d1 d2 -> $f1 a)
-
-Based on this SpecInfo, a call instance of f
-
- ...(f t1 t2 t3)...
-
-should get replaced by
-
- ...(\d1 d2 -> $f1 t2)...
-
-(But that is the business of the simplifier.)
-
-\begin{code}
-mkOneInst :: CallInstance
- -> [CallInstance] -- Any explicit cis for this inst
- -> Int -- No of dicts to specialise
- -> Bool -- Top level binders?
- -> [CallInstance] -- Instantiated call insts for binders
- -> [Id] -- New binders
- -> CoreBinding -- Unprocessed
- -> SpecM (Maybe CoreBinding, -- Instantiated version of input
- UsageDetails,
- [Maybe SpecInfo] -- One for each id in the original binding
- )
-
-mkOneInst do_cis@(CallInstance _ spec_tys dict_args _ _) explicit_cis
- no_of_dicts_to_specialise top_lev inst_cis new_ids orig_bind
- = newSpecIds new_ids spec_tys no_of_dicts_to_specialise
- `thenSM` \ spec_ids ->
- newTyVars (length [() | Nothing <- spec_tys]) `thenSM` \ poly_tyvars ->
- let
- -- arg_tys is spec_tys with tyvars instead of the Nothing spec_tys
- -- which correspond to unspecialised args
- arg_tys :: [Type]
- (_,arg_tys) = mapAccumL do_the_wotsit poly_tyvars spec_tys
-
- args :: [CoreArg]
- args = map TyArg arg_tys ++ dict_args
-
- (new_id:_) = new_ids
- (spec_id:_) = spec_ids
-
- do_bind (NonRec orig_id rhs)
- = do_one_rhs (spec_id, new_id, (orig_id,rhs))
- `thenSM` \ (maybe_spec, rhs_uds, spec_info) ->
- case maybe_spec of
- Just (spec_id, rhs) -> returnSM (Just (NonRec spec_id rhs), rhs_uds, [spec_info])
- Nothing -> returnSM (Nothing, rhs_uds, [spec_info])
-
- do_bind (Rec pairs)
- = mapAndUnzip3SM do_one_rhs (zip3 spec_ids new_ids pairs)
- `thenSM` \ (maybe_pairs, rhss_uds_s, spec_infos) ->
- returnSM (Just (Rec (catMaybes maybe_pairs)),
- unionUDList rhss_uds_s, spec_infos)
-
- do_one_rhs (spec_id, new_id, (orig_id, orig_rhs))
-
- -- Avoid duplicating a spec which has already been created ...
- -- This can arise in a Rec involving a dfun for which a
- -- a specialised instance has been created but specialisation
- -- "required" by one of the other Ids in the Rec
- | top_lev && maybeToBool lookup_orig_spec
- = (if opt_SpecialiseTrace
- then trace_nospec " Exists: " orig_id
- else id) (
-
- returnSM (Nothing, emptyUDs, Nothing)
- )
-
- -- Check for a (single) explicit call instance for this id
- | not (null explicit_cis_for_this_id)
- = ASSERT (length explicit_cis_for_this_id == 1)
- (if opt_SpecialiseTrace
- then trace_nospec " Explicit: " explicit_id
- else id) (
-
- returnSM (Nothing, tickSpecInsts emptyUDs, Just explicit_spec_info)
- )
-
- -- Apply the specialiser to (orig_rhs t1 a t3 d1 d2)
- | otherwise
- = ASSERT (no_of_dicts_to_specialise == length dict_args)
- specExpr orig_rhs args `thenSM` \ (inst_rhs, inst_uds) ->
- let
- -- For a local binding we dump the usage details, creating
- -- any local dict bindings required
- -- At the top-level the uds will be dumped in specBindAndScope
- -- and the dict bindings made *global*
-
- (local_dict_binds, final_uds)
- = if not top_lev then
- dumpUDs inst_uds False False inst_cis new_ids []
- else
- ([], inst_uds)
-
- spec_info = Just (SpecInfo spec_tys no_of_dicts_to_specialise spec_id)
- in
- if isUnboxedType (idType spec_id) then
- ASSERT (null poly_tyvars)
- liftId spec_id `thenSM` \ (lift_spec_id, unlift_spec_id) ->
- mkTyConInstance liftDataCon [idType unlift_spec_id]
- `thenSM` \ lift_uds ->
- returnSM (Just (lift_spec_id,
- mkCoLetsNoUnboxed local_dict_binds (liftExpr unlift_spec_id inst_rhs)),
- tickSpecInsts (final_uds `unionUDs` lift_uds), spec_info)
- else
- returnSM (Just (spec_id,
- mkCoLetsNoUnboxed local_dict_binds (mkTyLam poly_tyvars inst_rhs)),
- tickSpecInsts final_uds, spec_info)
- where
- lookup_orig_spec = lookupSpecEnv (getIdSpecialisation orig_id) arg_tys
-
- explicit_cis_for_this_id = filter (isCIofTheseIds [new_id]) explicit_cis
- [CallInstance _ _ _ _ (Just explicit_spec_info)] = explicit_cis_for_this_id
- SpecInfo _ _ explicit_id = explicit_spec_info
-
- trace_nospec :: String -> Id -> a -> a
- trace_nospec str spec_id
- = pprTrace str
- (hsep [ppr PprDebug new_id, hsep (map pp_ty arg_tys),
- ptext SLIT("==>"), ppr PprDebug spec_id])
- in
- (if opt_SpecialiseTrace then
- pprTrace "Specialising:"
- (hang (hcat [char '{',
- interppSP PprDebug new_ids,
- char '}'])
- 4 (vcat [
- hcat [ptext SLIT("types: "), hsep (map pp_ty arg_tys)],
- if isExplicitCI do_cis then empty else
- hcat [ptext SLIT("dicts: "), hsep (map pp_dict dict_args)],
- hcat [ptext SLIT("specs: "), ppr PprDebug spec_ids]]))
- else id) (
-
- do_bind orig_bind `thenSM` \ (maybe_inst_bind, inst_uds, spec_infos) ->
-
- returnSM (maybe_inst_bind, inst_uds, spec_infos)
- )