prettyCode :: DexFile -> AF.AccessFlags -> MethodId -> CodeItem -> PP.Doc
prettyCode dex flags mid codeItem =
  vsep [ "      code       -"
          , prettyField16 "      registers" (codeRegs codeItem)
          , prettyField16 "      ins" (codeInSize codeItem)
          , prettyField16 "      outs" (codeOutSize codeItem)
          , prettyField "      insns size" (word32Dec (fromIntegral (length insnUnits)) <+> "16-bit code units")
          , word24HexFixed nameAddr <> ":                                        |[" <> word24HexFixed nameAddr <> "] " <> methodStr dex mid
          , insnText
          , prettyField "      catches" (if null tries then "(none)" else word32Dec (fromIntegral (length tries)))
          , vsep (map (prettyTryBlock dex codeItem) tries)
          , prettyField "      positions" ""
          , vsep (map prettyPosition (reverse (dbgPositions debugState)))
          , prettyField "      locals" ""
          , vsep (map (prettyLocal dex) locals)
          ]
  where
    tries = codeTryItems codeItem
    insnUnits = codeInsns codeItem
    debugState = either (const DI.emptyDebugState) id (DI.executeDebugInsns dex codeItem flags mid)
    addr = codeInsnOff codeItem
    nameAddr = addr - 16
    decodeErrorMsg = maybe "Unknown error" decodeErrorAsString . E.fromException
    insnText = either (\msg -> "error parsing instructions: " <> PP.text (decodeErrorMsg msg))
                      (formatInstructions dex addr 0 insnUnits)
                      (decodeInstructions insnUnits)
    locals = L.sortBy cmpLocal [ (r, l) | (r, ls) <- Map.toList (dbgLocals debugState)
                                        , l <- ls
                                        , hasLocal l
                                        ]
    cmpLocal (_, LocalInfo n _ e _ _ _) (_, LocalInfo n' _ e' _ _ _) =
      compare (e, n) (e', n')
    hasLocal (LocalInfo _ _ _ nid _ _) = nid /= (-1)
prettyCode :: DexFile -> AF.AccessFlags -> MethodId -> CodeItem -> PP.Doc
prettyCode dex flags mid codeItem =
  vsep [ "      code       -"
          , prettyField16 "      registers" (codeRegs codeItem)
          , prettyField16 "      ins" (codeInSize codeItem)
          , prettyField16 "      outs" (codeOutSize codeItem)
          , prettyField "      insns size" (word32Dec (fromIntegral (length insnUnits)) <+> "16-bit code units")
          , word24HexFixed nameAddr <> ":                                        |[" <> word24HexFixed nameAddr <> "] " <> methodStr dex mid
          , insnText
          , prettyField "      catches" (if null tries then "(none)" else word32Dec (fromIntegral (length tries)))
          , vsep (map (prettyTryBlock dex codeItem) tries)
          , prettyField "      positions" ""
          , vsep (map prettyPosition (reverse (dbgPositions debugState)))
          , prettyField "      locals" ""
          , vsep (map (prettyLocal dex) locals)
          ]
  where
    tries = codeTryItems codeItem
    insnUnits = codeInsns codeItem
    debugState = either (const DI.emptyDebugState) id (DI.executeDebugInsns dex codeItem flags mid)
    addr = codeInsnOff codeItem
    nameAddr = addr - 16
    decodeErrorMsg = maybe "Unknown error" decodeErrorAsString . E.fromException
    insnText = either (\msg -> "error parsing instructions: " <> PP.text (decodeErrorMsg msg))
                      (formatInstructions dex addr 0 insnUnits)
                      (decodeInstructions insnUnits)
    locals = L.sortBy cmpLocal [ (r, l) | (r, ls) <- Map.toList (dbgLocals debugState)
                                        , l <- ls
                                        , hasLocal l
                                        ]
    cmpLocal (_, LocalInfo n _ e _ _ _) (_, LocalInfo n' _ e' _ _ _) =
      compare (e, n) (e', n')
    hasLocal (LocalInfo _ _ _ nid _ _) = nid /= (-1)
prettyCode dex flags mid codeItem =
  vsep [ "      code       -"
          , prettyField16 "      registers" (codeRegs codeItem)
          , prettyField16 "      ins" (codeInSize codeItem)
          , prettyField16 "      outs" (codeOutSize codeItem)
          , prettyField "      insns size" (word32Dec (fromIntegral (length insnUnits)) <+> "16-bit code units")
          , word24HexFixed nameAddr <> ":                                        |[" <> word24HexFixed nameAddr <> "] " <> methodStr dex mid
          , insnText
          , prettyField "      catches" (if null tries then "(none)" else word32Dec (fromIntegral (length tries)))
          , vsep (map (prettyTryBlock dex codeItem) tries)
          , prettyField "      positions" ""
          , vsep (map prettyPosition (reverse (dbgPositions debugState)))
          , prettyField "      locals" ""
          , vsep (map (prettyLocal dex) locals)
          ]
  where
    tries = codeTryItems codeItem
    insnUnits = codeInsns codeItem
    debugState = either (const DI.emptyDebugState) id (DI.executeDebugInsns dex codeItem flags mid)
    addr = codeInsnOff codeItem
    nameAddr = addr - 16
    decodeErrorMsg = maybe "Unknown error" decodeErrorAsString . E.fromException
    insnText = either (\msg -> "error parsing instructions: " <> PP.text (decodeErrorMsg msg))
                      (formatInstructions dex addr 0 insnUnits)
                      (decodeInstructions insnUnits)
    locals = L.sortBy cmpLocal [ (r, l) | (r, ls) <- Map.toList (dbgLocals debugState)
                                        , l <- ls
                                        , hasLocal l
                                        ]
    cmpLocal (_, LocalInfo n _ e _ _ _) (_, LocalInfo n' _ e' _ _ _) =
      compare (e, n) (e', n')
    hasLocal (LocalInfo _ _ _ nid _ _) = nid /= (-1)