- = do { (env', bind_usg, bind') <- scBind env (Rec prs)
- ; (body_usg, body') <- scExpr env' body
- ; return (bind_usg `combineUsage` body_usg, Let bind' body') }
-
-scExpr' env e@(App _ _)
- = do { let (fn, args) = collectArgs e
- ; (fn_usg, fn') <- scExpr env fn
- -- Process the function too. It's almost always a variable,
- -- but not always. In particular, if this pass follows float-in,
- -- which it may, we can get
- -- (let f = ...f... in f) arg1 arg2
- -- Also the substitution may replace a variable by a non-variable
-
- ; let fn_usg' = setScrutOcc env fn_usg fn' (ScrutOcc emptyUFM)
- -- We use setScrutOcc to record the fact that the function is called
- -- Perhaps we should check that it has at least one value arg,
- -- but currently we don't bother
-
- ; (arg_usgs, args') <- mapAndUnzipUs (scExpr env) args
- ; let call_usg = case fn' of
- Var f | Just RecFun <- lookupHowBound env f
- , not (null args) -- Not a proper call!
- -> SCU { calls = unitVarEnv f [(sc_cons env, args')],
- occs = emptyVarEnv }
- other -> nullUsage
- ; return (combineUsages arg_usgs `combineUsage` fn_usg'
- `combineUsage` call_usg,
- mkApps fn' args') }
-
+ = do { let (bndrs,rhss) = unzip prs
+ (rhs_env1,bndrs') = extendRecBndrs env bndrs
+ rhs_env2 = extendHowBound rhs_env1 bndrs' RecFun
+
+ ; (rhs_usgs, rhs_infos) <- mapAndUnzipM (scRecRhs rhs_env2) (bndrs' `zip` rhss)
+ ; (body_usg, body') <- scExpr rhs_env2 body
+
+ -- NB: start specLoop from body_usg
+ ; (spec_usg, specs) <- specLoop rhs_env2 (scu_calls body_usg) rhs_infos nullUsage
+ [SI [] 0 (Just usg) | usg <- rhs_usgs]
+
+ ; let all_usg = spec_usg `combineUsage` body_usg
+ bind' = Rec (concat (zipWith specInfoBinds rhs_infos specs))
+
+ ; return (all_usg { scu_calls = scu_calls all_usg `delVarEnvList` bndrs' },
+ Let bind' body') }
+
+-----------------------------------
+scApp :: ScEnv -> (InExpr, [InExpr]) -> UniqSM (ScUsage, CoreExpr)
+
+scApp env (Var fn, args) -- Function is a variable
+ = ASSERT( not (null args) )
+ do { args_w_usgs <- mapM (scExpr env) args
+ ; let (arg_usgs, args') = unzip args_w_usgs
+ arg_usg = combineUsages arg_usgs
+ ; case scSubstId env fn of
+ fn'@(Lam {}) -> scExpr (zapScSubst env) (doBeta fn' args')
+ -- Do beta-reduction and try again
+
+ Var fn' -> return (arg_usg `combineUsage` fn_usg, mkApps (Var fn') args')
+ where
+ fn_usg = case lookupHowBound env fn' of
+ Just RecFun -> SCU { scu_calls = unitVarEnv fn' [(sc_vals env, args')],
+ scu_occs = emptyVarEnv }
+ Just RecArg -> SCU { scu_calls = emptyVarEnv,
+ scu_occs = unitVarEnv fn' (ScrutOcc emptyUFM) }
+ Nothing -> nullUsage
+
+
+ other_fn' -> return (arg_usg, mkApps other_fn' args') }
+ -- NB: doing this ignores any usage info from the substituted
+ -- function, but I don't think that matters. If it does
+ -- we can fix it.
+ where
+ doBeta :: OutExpr -> [OutExpr] -> OutExpr
+ -- ToDo: adjust for System IF
+ doBeta (Lam bndr body) (arg : args) = Let (NonRec bndr arg) (doBeta body args)
+ doBeta fn args = mkApps fn args
+
+-- The function is almost always a variable, but not always.
+-- In particular, if this pass follows float-in,
+-- which it may, we can get
+-- (let f = ...f... in f) arg1 arg2
+scApp env (other_fn, args)
+ = do { (fn_usg, fn') <- scExpr env other_fn
+ ; (arg_usgs, args') <- mapAndUnzipM (scExpr env) args
+ ; return (combineUsages arg_usgs `combineUsage` fn_usg, mkApps fn' args') }