callGraph' f (TECase ty expr cases)                     = do
  env <- ask
  exprSize <- sizeOf' f expr
  let exprType = getTypeAnno expr
  let isRecType = (== exprType)
  variant <- lift $ getVariantType exprType
  caseGraphs <- forM cases $ \(id, (vars, caseExpr)) -> do
                  caseTypes <- case lookup id variant of
                                 Just ts -> return ts
                                 Nothing -> throwError $ CallGraphError "Incompatible pattern"
                  let annoVars = zip vars caseTypes
                  let argEnv = map (\(v, t) -> if isRecType t
                                               then (v, DataPos $ D exprSize)
                                               else (v, DataPos $ Var v)) annoVars
                  let isBaseCase = all (\(v,t) -> not $ isRecType t) annoVars
                  if isBaseCase
                  then let newF = updateControlPoint f exprSize (const Min)
                           caseEnv = addData argEnv . addHints [(expr, id)] . addControlPoint newF .
                                     addData (map (\(name, size) -> (name, DataPos Min)) $ filter (\(_, DataPos size) -> size == exprSize) (dataPositions env))
                       in local caseEnv $ callGraph' newF caseExpr
                  else let newF = updateControlPoint f exprSize NotMin
                           caseEnv = addData argEnv . addHints [(expr, id)] . addControlPoint newF .
                                     addData (map (\(name, DataPos size) -> (name, DataPos $ NotMin size)) $ filter (\(_, DataPos size) -> size == exprSize) (dataPositions env))
                       in local caseEnv $ callGraph' newF caseExpr
  return $ concat caseGraphs
callGraph' f (TECase ty expr cases)                     = do
  env <- ask
  exprSize <- sizeOf' f expr
  let exprType = getTypeAnno expr
  let isRecType = (== exprType)
  variant <- lift $ getVariantType exprType
  caseGraphs <- forM cases $ \(id, (vars, caseExpr)) -> do
                  caseTypes <- case lookup id variant of
                                 Just ts -> return ts
                                 Nothing -> throwError $ CallGraphError "Incompatible pattern"
                  let annoVars = zip vars caseTypes
                  let argEnv = map (\(v, t) -> if isRecType t
                                               then (v, DataPos $ D exprSize)
                                               else (v, DataPos $ Var v)) annoVars
                  let isBaseCase = all (\(v,t) -> not $ isRecType t) annoVars
                  if isBaseCase
                  then let newF = updateControlPoint f exprSize (const Min)
                           caseEnv = addData argEnv . addHints [(expr, id)] . addControlPoint newF .
                                     addData (map (\(name, size) -> (name, DataPos Min)) $ filter (\(_, DataPos size) -> size == exprSize) (dataPositions env))
                       in local caseEnv $ callGraph' newF caseExpr
                  else let newF = updateControlPoint f exprSize NotMin
                           caseEnv = addData argEnv . addHints [(expr, id)] . addControlPoint newF .
                                     addData (map (\(name, DataPos size) -> (name, DataPos $ NotMin size)) $ filter (\(_, DataPos size) -> size == exprSize) (dataPositions env))
                       in local caseEnv $ callGraph' newF caseExpr
  return $ concat caseGraphs
callGraph' f (TECase ty expr cases)                     = do
  env <- ask
  exprSize <- sizeOf' f expr
  let exprType = getTypeAnno expr
  let isRecType = (== exprType)
  variant <- lift $ getVariantType exprType
  caseGraphs <- forM cases $ \(id, (vars, caseExpr)) -> do
                  caseTypes <- case lookup id variant of
                                 Just ts -> return ts
                                 Nothing -> throwError $ CallGraphError "Incompatible pattern"
                  let annoVars = zip vars caseTypes
                  let argEnv = map (\(v, t) -> if isRecType t
                                               then (v, DataPos $ D exprSize)
                                               else (v, DataPos $ Var v)) annoVars
                  let isBaseCase = all (\(v,t) -> not $ isRecType t) annoVars
                  if isBaseCase
                  then let newF = updateControlPoint f exprSize (const Min)
                           caseEnv = addData argEnv . addHints [(expr, id)] . addControlPoint newF .
                                     addData (map (\(name, size) -> (name, DataPos Min)) $ filter (\(_, DataPos size) -> size == exprSize) (dataPositions env))
                       in local caseEnv $ callGraph' newF caseExpr
                  else let newF = updateControlPoint f exprSize NotMin
                           caseEnv = addData argEnv . addHints [(expr, id)] . addControlPoint newF .
                                     addData (map (\(name, DataPos size) -> (name, DataPos $ NotMin size)) $ filter (\(_, DataPos size) -> size == exprSize) (dataPositions env))
                       in local caseEnv $ callGraph' newF caseExpr
  return $ concat caseGraphs