bcc ((CONSTCASE r code def):xs)
   | intConsts code
     = do
         is <- get
         let i = level is
         codes <- mapM getCode code
         defs <- showDefS def
         tell $ concatMap (iCase i (creg r)) codes
         tell $ indent i ++ "{\n" ++ defs ++ indent i ++ "}\n"
         bcc xs
   | strConsts code
     = do
         is <- get
         let i = level is
         codes <- mapM getCode code
         defs <- showDefS def
         tell $ concatMap (strCase i ("GETSTR(" ++ creg r ++ ")")) codes
             ++ indent i ++ "{\n" ++ defs ++ indent i ++ "}\n"
         bcc xs
   | bigintConsts code
     = do
         is <- get
         let i = level is
         codes <- mapM getCode code
         defs <- showDefS def
         tell $ concatMap (biCase i (creg r)) codes ++
            indent i ++ "{\n" ++ defs ++ indent i ++ "}\n"
         bcc xs
   | otherwise = error $ "Can't happen: Can't compile const case " ++ show code
  where
    intConsts ((I _, _ ) : _) = True
    intConsts ((Ch _, _ ) : _) = True
    intConsts ((B8 _, _ ) : _) = True
    intConsts ((B16 _, _ ) : _) = True
    intConsts ((B32 _, _ ) : _) = True
    intConsts ((B64 _, _ ) : _) = True
    intConsts _ = False

    bigintConsts ((BI _, _ ) : _) = True
    bigintConsts _ = False

    strConsts ((Str _, _ ) : _) = True
    strConsts _ = False

    getCode (x, code) = do
        c <- getBC code xs
        return (x, c)

    strCase i sv (s, bc) =
        indent i ++ "if (strcmp(" ++ sv ++ ", " ++ show s ++ ") == 0) {\n" ++
            bc ++ indent i ++ "} else\n"
    biCase i bv (BI b, bc) =
        indent i ++ "if (bigEqConst(" ++ bv ++ ", " ++ show b ++ ")) {\n"
           ++  bc ++ indent i ++ "} else\n"
    iCase i v (I b, bc) =
        indent i ++ "if (GETINT(" ++ v ++ ") == " ++ show b ++ ") {\n"
           ++ bc ++ indent i ++ "} else\n"
    iCase i v (Ch b, bc) =
        indent i ++ "if (GETINT(" ++ v ++ ") == " ++ show (fromEnum b) ++ ") {\n"
           ++ bc ++ indent i ++ "} else\n"
    iCase i v (B8 w, bc) =
        indent i ++ "if (GETBITS8(" ++ v ++ ") == " ++ show (fromEnum w) ++ ") {\n"
           ++ bc ++ indent i ++ "} else\n"
    iCase i v (B16 w, bc) =
        indent i ++ "if (GETBITS16(" ++ v ++ ") == " ++ show (fromEnum w) ++ ") {\n"
           ++ bc ++ indent i ++ "} else\n"
    iCase i v (B32 w, bc) =
        indent i ++ "if (GETBITS32(" ++ v ++ ") == " ++ show (fromEnum w) ++ ") {\n"
           ++ bc ++ indent i ++ "} else\n"
    iCase i v (B64 w, bc) =
        indent i ++ "if (GETBITS64(" ++ v ++ ") == " ++ show (fromEnum w) ++ ") {\n"
           ++ bc ++ indent i ++ "} else\n"

    showDefS Nothing = return ""
    showDefS (Just c) = getBC c xs
bcc ((CONSTCASE r code def):xs)
   | intConsts code
     = do
         is <- get
         let i = level is
         codes <- mapM getCode code
         defs <- showDefS def
         tell $ concatMap (iCase i (creg r)) codes
         tell $ indent i ++ "{\n" ++ defs ++ indent i ++ "}\n"
         bcc xs
   | strConsts code
     = do
         is <- get
         let i = level is
         codes <- mapM getCode code
         defs <- showDefS def
         tell $ concatMap (strCase i ("GETSTR(" ++ creg r ++ ")")) codes
             ++ indent i ++ "{\n" ++ defs ++ indent i ++ "}\n"
         bcc xs
   | bigintConsts code
     = do
         is <- get
         let i = level is
         codes <- mapM getCode code
         defs <- showDefS def
         tell $ concatMap (biCase i (creg r)) codes ++
            indent i ++ "{\n" ++ defs ++ indent i ++ "}\n"
         bcc xs
   | otherwise = error $ "Can't happen: Can't compile const case " ++ show code
  where
    intConsts ((I _, _ ) : _) = True
    intConsts ((Ch _, _ ) : _) = True
    intConsts ((B8 _, _ ) : _) = True
    intConsts ((B16 _, _ ) : _) = True
    intConsts ((B32 _, _ ) : _) = True
    intConsts ((B64 _, _ ) : _) = True
    intConsts _ = False

    bigintConsts ((BI _, _ ) : _) = True
    bigintConsts _ = False

    strConsts ((Str _, _ ) : _) = True
    strConsts _ = False

    getCode (x, code) = do
        c <- getBC code xs
        return (x, c)

    strCase i sv (s, bc) =
        indent i ++ "if (strcmp(" ++ sv ++ ", " ++ show s ++ ") == 0) {\n" ++
            bc ++ indent i ++ "} else\n"
    biCase i bv (BI b, bc) =
        indent i ++ "if (bigEqConst(" ++ bv ++ ", " ++ show b ++ ")) {\n"
           ++  bc ++ indent i ++ "} else\n"
    iCase i v (I b, bc) =
        indent i ++ "if (GETINT(" ++ v ++ ") == " ++ show b ++ ") {\n"
           ++ bc ++ indent i ++ "} else\n"
    iCase i v (Ch b, bc) =
        indent i ++ "if (GETINT(" ++ v ++ ") == " ++ show (fromEnum b) ++ ") {\n"
           ++ bc ++ indent i ++ "} else\n"
    iCase i v (B8 w, bc) =
        indent i ++ "if (GETBITS8(" ++ v ++ ") == " ++ show (fromEnum w) ++ ") {\n"
           ++ bc ++ indent i ++ "} else\n"
    iCase i v (B16 w, bc) =
        indent i ++ "if (GETBITS16(" ++ v ++ ") == " ++ show (fromEnum w) ++ ") {\n"
           ++ bc ++ indent i ++ "} else\n"
    iCase i v (B32 w, bc) =
        indent i ++ "if (GETBITS32(" ++ v ++ ") == " ++ show (fromEnum w) ++ ") {\n"
           ++ bc ++ indent i ++ "} else\n"
    iCase i v (B64 w, bc) =
        indent i ++ "if (GETBITS64(" ++ v ++ ") == " ++ show (fromEnum w) ++ ") {\n"
           ++ bc ++ indent i ++ "} else\n"

    showDefS Nothing = return ""
    showDefS (Just c) = getBC c xs
bcc ((CONSTCASE r code def):xs)
   | intConsts code
     = do
         is <- get
         let i = level is
         codes <- mapM getCode code
         defs <- showDefS def
         tell $ concatMap (iCase i (creg r)) codes
         tell $ indent i ++ "{\n" ++ defs ++ indent i ++ "}\n"
         bcc xs
   | strConsts code
     = do
         is <- get
         let i = level is
         codes <- mapM getCode code
         defs <- showDefS def
         tell $ concatMap (strCase i ("GETSTR(" ++ creg r ++ ")")) codes
             ++ indent i ++ "{\n" ++ defs ++ indent i ++ "}\n"
         bcc xs
   | bigintConsts code
     = do
         is <- get
         let i = level is
         codes <- mapM getCode code
         defs <- showDefS def
         tell $ concatMap (biCase i (creg r)) codes ++
            indent i ++ "{\n" ++ defs ++ indent i ++ "}\n"
         bcc xs
   | otherwise = error $ "Can't happen: Can't compile const case " ++ show code
  where
    intConsts ((I _, _ ) : _) = True
    intConsts ((Ch _, _ ) : _) = True
    intConsts ((B8 _, _ ) : _) = True
    intConsts ((B16 _, _ ) : _) = True
    intConsts ((B32 _, _ ) : _) = True
    intConsts ((B64 _, _ ) : _) = True
    intConsts _ = False

    bigintConsts ((BI _, _ ) : _) = True
    bigintConsts _ = False

    strConsts ((Str _, _ ) : _) = True
    strConsts _ = False

    getCode (x, code) = do
        c <- getBC code xs
        return (x, c)

    strCase i sv (s, bc) =
        indent i ++ "if (strcmp(" ++ sv ++ ", " ++ show s ++ ") == 0) {\n" ++
            bc ++ indent i ++ "} else\n"
    biCase i bv (BI b, bc) =
        indent i ++ "if (bigEqConst(" ++ bv ++ ", " ++ show b ++ ")) {\n"
           ++  bc ++ indent i ++ "} else\n"
    iCase i v (I b, bc) =
        indent i ++ "if (GETINT(" ++ v ++ ") == " ++ show b ++ ") {\n"
           ++ bc ++ indent i ++ "} else\n"
    iCase i v (Ch b, bc) =
        indent i ++ "if (GETINT(" ++ v ++ ") == " ++ show (fromEnum b) ++ ") {\n"
           ++ bc ++ indent i ++ "} else\n"
    iCase i v (B8 w, bc) =
        indent i ++ "if (GETBITS8(" ++ v ++ ") == " ++ show (fromEnum w) ++ ") {\n"
           ++ bc ++ indent i ++ "} else\n"
    iCase i v (B16 w, bc) =
        indent i ++ "if (GETBITS16(" ++ v ++ ") == " ++ show (fromEnum w) ++ ") {\n"
           ++ bc ++ indent i ++ "} else\n"
    iCase i v (B32 w, bc) =
        indent i ++ "if (GETBITS32(" ++ v ++ ") == " ++ show (fromEnum w) ++ ") {\n"
           ++ bc ++ indent i ++ "} else\n"
    iCase i v (B64 w, bc) =
        indent i ++ "if (GETBITS64(" ++ v ++ ") == " ++ show (fromEnum w) ++ ") {\n"
           ++ bc ++ indent i ++ "} else\n"

    showDefS Nothing = return ""
    showDefS (Just c) = getBC c xs