-arityType dflags (Var v)
- = mk (idArity v) (arg_tys (idType v))
- where
- mk :: Arity -> [Type] -> ArityType
- -- The argument types are only to steer the "state hack"
- -- Consider case x of
- -- True -> foo
- -- False -> \(s:RealWorld) -> e
- -- where foo has arity 1. Then we want the state hack to
- -- apply to foo too, so we can eta expand the case.
- mk 0 tys | isBottomingId v = ABot
- | (ty:tys) <- tys, isStateHackType ty = AFun True ATop
- | otherwise = ATop
- mk n (ty:tys) = AFun (isStateHackType ty) (mk (n-1) tys)
- mk n [] = AFun False (mk (n-1) [])
-
- arg_tys :: Type -> [Type] -- Ignore for-alls
- arg_tys ty
- | Just (_, ty') <- splitForAllTy_maybe ty = arg_tys ty'
- | Just (arg,res) <- splitFunTy_maybe ty = arg : arg_tys res
- | otherwise = []
+ f' = \p. \s. ((error "...") |> g1) s
+ f = f' |> (String -> g2)
+
+Discard args for bottomming function
+
+ f' = \p. \s. ((error "...") |> g1 |> g3
+ g3 :: (S -> (S,T)) ~ (S,T)
+
+Extrude g1.g3
+
+ f'' = \p. \s. (error "...")
+ f' = f'' |> (String -> S -> g1.g3)
+
+And now we can repeat the whole loop. Aargh! The bug is in applying the
+state hack to a function which then swallows the argument.
+
+
+-------------------- Main arity code ----------------------------
+\begin{code}
+-- If e has ArityType (AT n r), then the term 'e'
+-- * Must be applied to at least n *value* args
+-- before doing any significant work
+-- * It will not diverge before being applied to n
+-- value arguments
+-- * If 'r' is ABot, then it guarantees to diverge if
+-- applied to n arguments (or more)
+
+data ArityType = AT Arity ArityRes
+data ArityRes = ATop -- Know nothing
+ | ABot -- Diverges
+
+vanillaArityType :: ArityType
+vanillaArityType = AT 0 ATop -- Totally uninformative
+
+incArity :: ArityType -> ArityType
+incArity (AT a r) = AT (a+1) r
+
+decArity :: ArityType -> ArityType
+decArity (AT 0 r) = AT 0 r
+decArity (AT a r) = AT (a-1) r
+
+andArityType :: ArityType -> ArityType -> ArityType -- Used for branches of a 'case'
+andArityType (AT a1 ATop) (AT a2 ATop) = AT (a1 `min` a2) ATop
+andArityType (AT _ ABot) (AT a2 ATop) = AT a2 ATop
+andArityType (AT a1 ATop) (AT _ ABot) = AT a1 ATop
+andArityType (AT a1 ABot) (AT a2 ABot) = AT (a1 `max` a2) ABot
+
+trimArity :: Bool -> ArityType -> ArityType
+-- We have something like (let x = E in b), where b has the given
+-- arity type. Then
+-- * If E is cheap we can push it inside as far as we like
+-- * If b eventually diverges, we allow ourselves to push inside
+-- arbitrarily, even though that is not quite right
+trimArity _cheap (AT a ABot) = AT a ABot
+trimArity True (AT a ATop) = AT a ATop
+trimArity False (AT _ ATop) = AT 0 ATop -- Bale out
+
+---------------------------
+arityType :: Bool -> CoreExpr -> ArityType
+arityType _ (Var v)
+ | Just strict_sig <- idNewStrictness_maybe v
+ , (ds, res) <- splitStrictSig strict_sig
+ , isBotRes res
+ = AT (length ds) ABot -- Function diverges
+ | otherwise
+ = AT (idArity v) ATop