\section[CoreUtils]{Utility functions on @Core@ syntax}
\begin{code}
-#include "HsVersions.h"
-
module CoreUtils (
coreExprType, coreAltsType, coreExprCc,
, maybeErrorApp
, nonErrorRHSs
, squashableDictishCcExpr
-{-
- coreExprArity,
- isWrapperFor,
-
--} ) where
+ ) where
-IMP_Ubiq()
-IMPORT_DELOOPER(IdLoop) -- for pananoia-checking purposes
+#include "HsVersions.h"
import CoreSyn
import CostCentre ( isDictCC, CostCentre, noCostCentre )
-import Id ( idType, mkSysLocal, getIdArity, isBottomingId,
+import Id ( idType, mkSysLocal, isBottomingId,
toplevelishId, mkIdWithNewUniq, applyTypeEnvToId,
+ dataConRepType,
addOneToIdEnv, growIdEnvList, lookupIdEnv,
- isNullIdEnv, SYN_IE(IdEnv),
- GenId{-instances-}
+ isNullIdEnv, IdEnv, Id
)
-import IdInfo ( arityMaybe )
-import Literal ( literalType, isNoRepLit, Literal(..) )
+import Literal ( literalType, Literal(..) )
import Maybes ( catMaybes, maybeToBool )
import PprCore
-import PprStyle ( PprStyle(..) )
-import PprType ( GenType{-instances-} )
-import Pretty ( ppAboves, ppStr )
-import PrelVals ( augmentId, buildId )
import PrimOp ( primOpType, PrimOp(..) )
-import SrcLoc ( mkUnknownSrcLoc )
+import SrcLoc ( noSrcLoc )
import TyVar ( cloneTyVar,
- isNullTyVarEnv, addOneToTyVarEnv, SYN_IE(TyVarEnv)
+ isEmptyTyVarEnv, addToTyVarEnv, TyVarEnv,
+ TyVar, GenTyVar
)
-import Type ( mkFunTy, mkForAllTy, mkForAllUsageTy, mkTyVarTy,
- getFunTy_maybe, applyTy, isPrimType,
- splitSigmaTy, splitFunTy, eqTy, applyTypeEnvToTy
+import Type ( mkFunTy, mkForAllTy, mkTyVarTy,
+ splitFunTy_maybe, applyTys, isUnpointedType,
+ splitSigmaTy, splitFunTys, instantiateTy,
+ Type
)
import TysWiredIn ( trueDataCon, falseDataCon )
-import UniqSupply ( initUs, returnUs, thenUs,
+import Unique ( Unique )
+import BasicTypes ( Unused )
+import UniqSupply ( returnUs, thenUs,
mapUs, mapAndUnzipUs, getUnique,
- SYN_IE(UniqSM), UniqSupply
+ UniqSM, UniqSupply
)
-import Usage ( SYN_IE(UVar) )
-import Util ( zipEqual, panic, pprPanic, assertPanic )
+import Util ( zipEqual )
+import Outputable
type TypeEnv = TyVarEnv Type
-applyUsage = panic "CoreUtils.applyUsage:ToDo"
\end{code}
%************************************************************************
-- a Con is a fully-saturated application of a data constructor
-- a Prim is <ditto> of a PrimOp
-coreExprType (Con con args) = applyTypeToArgs (idType con) args
+coreExprType (Con con args) =
+-- pprTrace "appTyArgs" (hsep [ppr con, semi,
+-- ppr con_ty, semi,
+-- ppr args]) $
+ applyTypeToArgs con_ty args
+ where
+ con_ty = dataConRepType con
+
coreExprType (Prim op args) = applyTypeToArgs (primOpType op) args
coreExprType (Lam (ValBinder binder) expr)
coreExprType (Lam (TyBinder tyvar) expr)
= mkForAllTy tyvar (coreExprType expr)
-coreExprType (Lam (UsageBinder uvar) expr)
- = mkForAllUsageTy uvar (panic "coreExprType:Lam UsageBinder") (coreExprType expr)
-
coreExprType (App expr (TyArg ty))
- = applyTy (coreExprType expr) ty
-
-coreExprType (App expr (UsageArg use))
- = applyUsage (coreExprType expr) use
+ = -- Gather type args; more efficient to instantiate the type all at once
+ go expr [ty]
+ where
+ go (App expr (TyArg ty)) tys = go expr (ty:tys)
+ go expr tys = applyTys (coreExprType expr) tys
coreExprType (App expr val_arg)
= ASSERT(isValArg val_arg)
let
fun_ty = coreExprType expr
in
- case (getFunTy_maybe fun_ty) of
+ case (splitFunTy_maybe fun_ty) of
Just (_, result_ty) -> result_ty
#ifdef DEBUG
Nothing -> pprPanic "coreExprType:\n"
- (ppAboves [ppr PprDebug fun_ty,
- ppr PprShowAll (App expr val_arg)])
+ (vcat [ppr fun_ty, ppr (App expr val_arg)])
#endif
\end{code}
\end{code}
\begin{code}
-applyTypeToArgs op_ty args = foldl applyTypeToArg op_ty args
+applyTypeToArgs op_ty (TyArg ty : args)
+ = -- Accumulate type arguments so we can instantiate all at once
+ applyTypeToArgs (applyTys op_ty tys) rest_args
+ where
+ (tys, rest_args) = go [ty] args
+ go tys (TyArg ty : args) = go (ty:tys) args
+ go tys rest_args = (reverse tys, rest_args)
-applyTypeToArg op_ty (TyArg ty) = applyTy op_ty ty
-applyTypeToArg op_ty (UsageArg _) = panic "applyTypeToArg: UsageArg"
-applyTypeToArg op_ty val_or_lit_arg = case (getFunTy_maybe op_ty) of
- Just (_, res_ty) -> res_ty
+applyTypeToArgs op_ty (val_or_lit_arg:args)
+ = case (splitFunTy_maybe op_ty) of
+ Just (_, res_ty) -> applyTypeToArgs res_ty args
+
+applyTypeToArgs op_ty [] = op_ty
\end{code}
coreExprCc gets the cost centre enclosing an expression, if any.
It looks inside lambdas because (scc "foo" \x.e) = \x.scc "foo" e
\begin{code}
-coreExprCc :: GenCoreExpr val_bdr val_occ tyvar uvar -> CostCentre
+coreExprCc :: GenCoreExpr val_bdr val_occ flexi -> CostCentre
coreExprCc (SCC cc e) = cc
coreExprCc (Lam _ e) = coreExprCc e
coreExprCc other = noCostCentre
in
getUnique `thenUs` \ uniq ->
let
- new_var = mkSysLocal SLIT("a") uniq e_ty mkUnknownSrcLoc
+ new_var = mkSysLocal SLIT("a") uniq e_ty noSrcLoc
in
returnUs (VarArg new_var, Just (NonRec new_var other_expr))
\end{code}
\begin{code}
argToExpr ::
- GenCoreArg val_occ tyvar uvar -> GenCoreExpr val_bdr val_occ tyvar uvar
+ GenCoreArg val_occ flexi -> GenCoreExpr val_bdr val_occ flexi
argToExpr (VarArg v) = Var v
argToExpr (LitArg lit) = Lit lit
\end{code}
-\begin{code}
-{-LATER:
-coreExprArity
- :: (Id -> Maybe (GenCoreExpr bndr Id))
- -> GenCoreExpr bndr Id
- -> Int
-coreExprArity f (Lam _ expr) = coreExprArity f expr + 1
-coreExprArity f (CoTyLam _ expr) = coreExprArity f expr
-coreExprArity f (App expr arg) = max (coreExprArity f expr - 1) 0
-coreExprArity f (CoTyApp expr _) = coreExprArity f expr
-coreExprArity f (Var v) = max further info
- where
- further
- = case f v of
- Nothing -> 0
- Just expr -> coreExprArity f expr
- info = case (arityMaybe (getIdArity v)) of
- Nothing -> 0
- Just arity -> arity
-coreExprArity f _ = 0
-\end{code}
-
-@isWrapperFor@: we want to see exactly:
-\begin{verbatim}
-/\ ... \ args -> case <arg> of ... -> case <arg> of ... -> wrkr <stuff>
-\end{verbatim}
-
-Probably a little too HACKY [WDP].
-
-\begin{code}
-isWrapperFor :: CoreExpr -> Id -> Bool
-
-expr `isWrapperFor` var
- = case (collectBinders expr) of { (_, _, args, body) -> -- lambdas off the front
- unravel_casing args body
- --NO, THANKS: && not (null args)
- }
- where
- var's_worker = getWorkerId (getIdStrictness var)
-
- is_elem = isIn "isWrapperFor"
-
- --------------
- unravel_casing case_ables (Case scrut alts)
- = case (collectArgs scrut) of { (fun, _, _, vargs) ->
- case fun of
- Var scrut_var -> let
- answer =
- scrut_var /= var && all (doesn't_mention var) vargs
- && scrut_var `is_elem` case_ables
- && unravel_alts case_ables alts
- in
- answer
-
- _ -> False
- }
-
- unravel_casing case_ables other_expr
- = case (collectArgs other_expr) of { (fun, _, _, vargs) ->
- case fun of
- Var wrkr -> let
- answer =
- -- DOESN'T WORK: wrkr == var's_worker
- wrkr /= var
- && isWorkerId wrkr
- && all (doesn't_mention var) vargs
- && all (only_from case_ables) vargs
- in
- answer
-
- _ -> False
- }
-
- --------------
- unravel_alts case_ables (AlgAlts [(_,params,rhs)] NoDefault)
- = unravel_casing (params ++ case_ables) rhs
- unravel_alts case_ables other = False
-
- -------------------------
- doesn't_mention var (ValArg (VarArg v)) = v /= var
- doesn't_mention var other = True
-
- -------------------------
- only_from case_ables (ValArg (VarArg v)) = v `is_elem` case_ables
- only_from case_ables other = True
--}
-\end{code}
-
All the following functions operate on binders, perform a uniform
transformation on them; ie. the function @(\ x -> (x,False))@
annotates all binders with False.
\begin{code}
-unTagBinders :: GenCoreExpr (Id,tag) bdee tv uv -> GenCoreExpr Id bdee tv uv
+unTagBinders :: GenCoreExpr (Id,tag) bdee flexi -> GenCoreExpr Id bdee flexi
unTagBinders expr = bop_expr fst expr
-unTagBindersAlts :: GenCoreCaseAlts (Id,tag) bdee tv uv -> GenCoreCaseAlts Id bdee tv uv
+unTagBindersAlts :: GenCoreCaseAlts (Id,tag) bdee flexi -> GenCoreCaseAlts Id bdee flexi
unTagBindersAlts alts = bop_alts fst alts
\end{code}
\begin{code}
-bop_expr :: (a -> b) -> GenCoreExpr a bdee tv uv -> GenCoreExpr b bdee tv uv
+bop_expr :: (a -> b) -> GenCoreExpr a bdee flexi -> GenCoreExpr b bdee flexi
bop_expr f (Var b) = Var b
bop_expr f (Lit lit) = Lit lit
bop_binder f (ValBinder v) = ValBinder (f v)
bop_binder f (TyBinder t) = TyBinder t
-bop_binder f (UsageBinder u) = UsageBinder u
bop_bind f (NonRec b e) = NonRec (f b) (bop_expr f e)
bop_bind f (Rec pairs) = Rec [(f b, bop_expr f e) | (b, e) <- pairs]
Notice that the \tr{<alts>} don't get duplicated.
\begin{code}
-nonErrorRHSs :: GenCoreCaseAlts a Id TyVar UVar -> [GenCoreExpr a Id TyVar UVar]
+nonErrorRHSs :: GenCoreCaseAlts a Id Unused -> [GenCoreExpr a Id Unused]
nonErrorRHSs alts
= filter not_error_app (find_rhss alts)
\begin{code}
maybeErrorApp
- :: GenCoreExpr a Id TyVar UVar -- Expr to look at
+ :: GenCoreExpr a Id Unused -- Expr to look at
-> Maybe Type -- Just ty => a result type *already cloned*;
-- Nothing => don't know result ty; we
-- *pretend* that the result ty won't be
-- primitive -- somebody later must
-- ensure this.
- -> Maybe (GenCoreExpr a Id TyVar UVar)
+ -> Maybe (GenCoreExpr b Id Unused)
maybeErrorApp expr result_ty_maybe
= case (collectArgs expr) of
- (Var fun, [{-no usage???-}], [ty], other_args)
+ (Var fun, [ty], other_args)
| isBottomingId fun
&& maybeToBool result_ty_maybe -- we *know* the result type
-- (otherwise: live a fairy-tale existence...)
- && not (isPrimType result_ty) ->
+ && not (isUnpointedType result_ty) ->
case (splitSigmaTy (idType fun)) of
([tyvar], [], tau_ty) ->
- case (splitFunTy tau_ty) of { (arg_tys, res_ty) ->
+ case (splitFunTys tau_ty) of { (arg_tys, res_ty) ->
let
n_args_to_keep = length arg_tys
args_to_keep = take n_args_to_keep other_args
in
- if (res_ty `eqTy` mkTyVarTy tyvar)
+ if (res_ty == mkTyVarTy tyvar)
&& n_args_to_keep <= length other_args
then
-- Phew! We're in business
\end{code}
\begin{code}
-squashableDictishCcExpr :: CostCentre -> GenCoreExpr a b c d -> Bool
+squashableDictishCcExpr :: CostCentre -> GenCoreExpr a b c -> Bool
squashableDictishCcExpr cc expr
= if not (isDictCC cc) then
substCoreBindings venv tenv binds
-- if the envs are empty, then avoid doing anything
- = if (isNullIdEnv venv && isNullTyVarEnv tenv) then
+ = if (isNullIdEnv venv && isEmptyTyVarEnv tenv) then
returnUs binds
else
do_CoreBindings venv tenv binds
substCoreExpr venv tenv expr
- = if (isNullIdEnv venv && isNullTyVarEnv tenv) then
+ = if (isNullIdEnv venv && isEmptyTyVarEnv tenv) then
returnUs expr
else
do_CoreExpr venv tenv expr
)
do_CoreArg venv tenv (TyArg ty)
- = returnUs (AnArg (TyArg (applyTypeEnvToTy tenv ty)))
+ = returnUs (AnArg (TyArg (instantiateTy tenv ty)))
do_CoreArg venv tenv other_arg = returnUs (AnArg other_arg)
\end{code}
where
do_PrimOp (CCallOp label is_asm may_gc arg_tys result_ty)
= let
- new_arg_tys = map (applyTypeEnvToTy tenv) arg_tys
- new_result_ty = applyTypeEnvToTy tenv result_ty
+ new_arg_tys = map (instantiateTy tenv) arg_tys
+ new_result_ty = instantiateTy tenv result_ty
in
returnUs (CCallOp label is_asm may_gc new_arg_tys new_result_ty)
do_CoreExpr venv tenv (Lam (TyBinder tyvar) expr)
= dup_tyvar tyvar `thenUs` \ (new_tyvar, (old, new)) ->
let
- new_tenv = addOneToTyVarEnv tenv old new
+ new_tenv = addToTyVarEnv tenv old new
in
do_CoreExpr venv new_tenv expr `thenUs` \ new_expr ->
returnUs (Lam (TyBinder new_tyvar) new_expr)
-do_CoreExpr venv tenv (Lam _ expr) = panic "CoreUtils.do_CoreExpr:Lam UsageBinder"
-
do_CoreExpr venv tenv (App expr arg)
= do_CoreExpr venv tenv expr `thenUs` \ new_expr ->
do_CoreArg venv tenv arg `thenUs` \ new_arg ->
do_CoreExpr venv tenv (Coerce c ty expr)
= do_CoreExpr venv tenv expr `thenUs` \ new_expr ->
- returnUs (Coerce c (applyTypeEnvToTy tenv ty) new_expr)
+ returnUs (Coerce c (instantiateTy tenv ty) new_expr)
\end{code}
\begin{code}