tcStmts ret (s:ss) = do
    (s',StmtType c) <- tcStmtBlock (loc s) "middle statement" $ tcStmt ret s
    -- if the following statements are never executed, issue an error
    case ss of
        [] -> return ()
        ss -> unless (hasStmtFallthru c) $ do
            ppss <- mapM pp ss
            tcError (locpos $ loc (head ss)) $ UnreachableDeadCode (vcat ppss)
    (ss',StmtType cs) <- tcStmts ret ss
    sBvs <- liftM (Map.keysSet . Map.filter (\b -> not b)) $ bvs $ bimap mkVarId (const ()) s
    ssFvs <- fvsSet $ map (bimap mkVarId (const ())) ss
    -- issue warning for unused variable declarations
    forSetM_ (sBvs `Set.difference` ssFvs) $ \(v::VarIdentifier) -> do
        ppv <- pp v
        tcWarn (locpos $ loc s) $ UnusedVariable (ppv)
    return (s':ss',StmtType $ extendStmtClasses c cs)

-- | Typecheck a non-empty statement
tcStmts ret (s:ss) = do
    (s',StmtType c) <- tcStmtBlock (loc s) "middle statement" $ tcStmt ret s
    -- if the following statements are never executed, issue an error
    case ss of
        [] -> return ()
        ss -> unless (hasStmtFallthru c) $ do
            ppss <- mapM pp ss
            tcError (locpos $ loc (head ss)) $ UnreachableDeadCode (vcat ppss)
    (ss',StmtType cs) <- tcStmts ret ss
    sBvs <- liftM (Map.keysSet . Map.filter (\b -> not b)) $ bvs $ bimap mkVarId (const ()) s
    ssFvs <- fvsSet $ map (bimap mkVarId (const ())) ss
    -- issue warning for unused variable declarations
    forSetM_ (sBvs `Set.difference` ssFvs) $ \(v::VarIdentifier) -> do
        ppv <- pp v
        tcWarn (locpos $ loc s) $ UnusedVariable (ppv)
    return (s':ss',StmtType $ extendStmtClasses c cs)

-- | Typecheck a non-empty statement
tcStmts ret (s:ss) = do
    (s',StmtType c) <- tcStmtBlock (loc s) "middle statement" $ tcStmt ret s
    -- if the following statements are never executed, issue an error
    case ss of
        [] -> return ()
        ss -> unless (hasStmtFallthru c) $ do
            ppss <- mapM pp ss
            tcError (locpos $ loc (head ss)) $ UnreachableDeadCode (vcat ppss)
    (ss',StmtType cs) <- tcStmts ret ss
    sBvs <- liftM (Map.keysSet . Map.filter (\b -> not b)) $ bvs $ bimap mkVarId (const ()) s
    ssFvs <- fvsSet $ map (bimap mkVarId (const ())) ss
    -- issue warning for unused variable declarations
    forSetM_ (sBvs `Set.difference` ssFvs) $ \(v::VarIdentifier) -> do
        ppv <- pp v
        tcWarn (locpos $ loc s) $ UnusedVariable (ppv)
    return (s':ss',StmtType $ extendStmtClasses c cs)

-- | Typecheck a non-empty statement