content: {-# OPTIONS_GHC -Wno-implicit-prelude #-}
  
  module Language.Haskell.Brittany.Internal.ParseModule where
  
  import qualified Control.Monad as Monad
  import qualified Control.Monad.IO.Class as IO
  import qualified Control.Monad.Trans.Except as Except
  import qualified GHC
  import qualified GHC.ByteOrder
  import qualified GHC.Data.Bag
  import qualified GHC.Data.StringBuffer
  import qualified GHC.Driver.Session
  import qualified GHC.Parser.Header
  import qualified GHC.Platform
  import qualified GHC.Settings
  import qualified GHC.Types.SrcLoc
  import qualified GHC.Utils.Error
  import qualified GHC.Utils.Fingerprint
  import qualified Language.Haskell.GHC.ExactPrint.Parsers as ExactPrint
  import qualified Language.Haskell.GHC.ExactPrint.Types as ExactPrint
  
  -- | Parses a Haskell module. Although this nominally requires IO, it is
  -- morally pure. It should have no observable effects.
  parseModule
    :: IO.MonadIO io
    => [String]
    -> FilePath
    -> (GHC.Driver.Session.DynFlags -> io (Either String a))
    -> String
    -> io (Either String (ExactPrint.Anns, GHC.ParsedSource, a))
  parseModule arguments1 filePath checkDynFlags string = Except.runExceptT $ do
    let
      dynFlags1 = GHC.Driver.Session.gopt_set
        -- It feels like this should be either @Sf_Ignore@ or @Sf_None@, but both
        -- of those modes have trouble parsing safe imports (@import safe ...@).
        -- Neither passing in @"-XUnsafe"@ as a command line argument nor having
        -- @{-# LANGUAGE Unsafe #-}@ in the source file seem to help.
        initialDynFlags
          { GHC.Driver.Session.safeHaskell = GHC.Driver.Session.Sf_Unsafe
          }
        GHC.Driver.Session.Opt_KeepRawTokenStream
    (dynFlags2, leftovers1, _) <-
      GHC.Driver.Session.parseDynamicFlagsCmdLine dynFlags1
        $ fmap GHC.Types.SrcLoc.noLoc arguments1
    handleLeftovers leftovers1
    let
      stringBuffer = GHC.Data.StringBuffer.stringToStringBuffer string
      arguments2 = GHC.Parser.Header.getOptions dynFlags2 stringBuffer filePath
    (dynFlags3, leftovers2, _) <- GHC.Driver.Session.parseDynamicFilePragma
      dynFlags2
      arguments2
    handleLeftovers leftovers2
    dynFlagsResult <- Except.ExceptT $ checkDynFlags dynFlags3
    let
      parseResult =
        ExactPrint.parseModuleFromStringInternal dynFlags3 filePath string
    case parseResult of
      Left errorMessages -> handleErrorMessages errorMessages
      Right (anns, parsedSource) -> pure (anns, parsedSource, dynFlagsResult)
  
  handleLeftovers
    :: Monad m => [GHC.Types.SrcLoc.Located String] -> Except.ExceptT String m ()
  handleLeftovers leftovers =
    Monad.unless (null leftovers) . Except.throwE $ "leftovers: " <> show
      (fmap GHC.Types.SrcLoc.unLoc leftovers)
  
  handleErrorMessages
    :: Monad m => GHC.Utils.Error.ErrorMessages -> Except.ExceptT String m a
  handleErrorMessages =
    Except.throwE . mappend "errorMessages: " . show . GHC.Data.Bag.bagToList
  
  initialDynFlags :: GHC.Driver.Session.DynFlags
  initialDynFlags = GHC.Driver.Session.defaultDynFlags initialSettings initialLlvmConfig
  
  initialSettings :: GHC.Driver.Session.Settings
  initialSettings = GHC.Driver.Session.Settings
    { GHC.Driver.Session.sGhcNameVersion = initialGhcNameVersion
    , GHC.Driver.Session.sFileSettings = initialFileSettings
    , GHC.Driver.Session.sTargetPlatform = initialTargetPlatform
    , GHC.Driver.Session.sToolSettings = initialToolSettings
    , GHC.Driver.Session.sPlatformMisc = initialPlatformMisc
    , GHC.Driver.Session.sPlatformConstants = initialPlatformConstants
    , GHC.Driver.Session.sRawSettings = []
    }
  
  initialFileSettings :: GHC.Driver.Session.FileSettings
  initialFileSettings = GHC.Driver.Session.FileSettings
    { GHC.Driver.Session.fileSettings_ghciUsagePath = ""
    , GHC.Driver.Session.fileSettings_ghcUsagePath = ""
    , GHC.Driver.Session.fileSettings_globalPackageDatabase = ""
    , GHC.Driver.Session.fileSettings_tmpDir = ""
    , GHC.Driver.Session.fileSettings_toolDir = Nothing
    , GHC.Driver.Session.fileSettings_topDir = ""
    }
  
  initialGhcNameVersion :: GHC.Driver.Session.GhcNameVersion
  initialGhcNameVersion = GHC.Driver.Session.GhcNameVersion
    { GHC.Driver.Session.ghcNameVersion_programName = ""
    , GHC.Driver.Session.ghcNameVersion_projectVersion = ""
    }
  
  initialPlatformMisc :: GHC.Driver.Session.PlatformMisc
  initialPlatformMisc = GHC.Driver.Session.PlatformMisc
    { GHC.Driver.Session.platformMisc_ghcDebugged = False
    , GHC.Driver.Session.platformMisc_ghcRTSWays = ""
    , GHC.Driver.Session.platformMisc_ghcRtsWithLibdw = False
    , GHC.Driver.Session.platformMisc_ghcThreaded = False
    , GHC.Driver.Session.platformMisc_ghcWithInterpreter = False
    , GHC.Driver.Session.platformMisc_ghcWithSMP = False
    , GHC.Driver.Session.platformMisc_libFFI = False
    , GHC.Driver.Session.platformMisc_llvmTarget = ""
    , GHC.Driver.Session.platformMisc_targetPlatformString = ""
    }
  
  initialLlvmConfig :: GHC.Driver.Session.LlvmConfig
  initialLlvmConfig = GHC.Driver.Session.LlvmConfig
    { GHC.Driver.Session.llvmPasses = []
    , GHC.Driver.Session.llvmTargets = []
    }
  
  initialPlatformConstants :: GHC.Settings.PlatformConstants
  initialPlatformConstants = GHC.Settings.PlatformConstants
    { GHC.Settings.pc_AP_STACK_SPLIM = 0
    , GHC.Settings.pc_BITMAP_BITS_SHIFT = 0
    , GHC.Settings.pc_BLOCK_SIZE = 0
    , GHC.Settings.pc_BLOCKS_PER_MBLOCK = 0
    , GHC.Settings.pc_CINT_SIZE = 0
    , GHC.Settings.pc_CLONG_LONG_SIZE = 0
    , GHC.Settings.pc_CLONG_SIZE = 0
    , GHC.Settings.pc_CONTROL_GROUP_CONST_291 = 0
    , GHC.Settings.pc_DYNAMIC_BY_DEFAULT = False
    , GHC.Settings.pc_ILDV_CREATE_MASK = 0
    , GHC.Settings.pc_ILDV_STATE_CREATE = 0
    , GHC.Settings.pc_ILDV_STATE_USE = 0
    , GHC.Settings.pc_LDV_SHIFT = 0
    , GHC.Settings.pc_MAX_CHARLIKE = 0
    , GHC.Settings.pc_MAX_Double_REG = 0
    , GHC.Settings.pc_MAX_Float_REG = 0
    , GHC.Settings.pc_MAX_INTLIKE = 0
    , GHC.Settings.pc_MAX_Long_REG = 0
    , GHC.Settings.pc_MAX_Real_Double_REG = 0
    , GHC.Settings.pc_MAX_Real_Float_REG = 0
    , GHC.Settings.pc_MAX_Real_Long_REG = 0
    , GHC.Settings.pc_MAX_Real_Vanilla_REG = 0
    , GHC.Settings.pc_MAX_Real_XMM_REG = 0
    , GHC.Settings.pc_MAX_SPEC_AP_SIZE = 0
    , GHC.Settings.pc_MAX_SPEC_SELECTEE_SIZE = 0
    , GHC.Settings.pc_MAX_Vanilla_REG = 0
    , GHC.Settings.pc_MAX_XMM_REG = 0
    , GHC.Settings.pc_MIN_CHARLIKE = 0
    , GHC.Settings.pc_MIN_INTLIKE = 0
    , GHC.Settings.pc_MIN_PAYLOAD_SIZE = 0
    , GHC.Settings.pc_MUT_ARR_PTRS_CARD_BITS = 0
    , GHC.Settings.pc_OFFSET_bdescr_blocks = 0
    , GHC.Settings.pc_OFFSET_bdescr_flags = 0
    , GHC.Settings.pc_OFFSET_bdescr_free = 0
    , GHC.Settings.pc_OFFSET_bdescr_start = 0
    , GHC.Settings.pc_OFFSET_Capability_r = 0
    , GHC.Settings.pc_OFFSET_CostCentreStack_mem_alloc = 0
    , GHC.Settings.pc_OFFSET_CostCentreStack_scc_count = 0
    , GHC.Settings.pc_OFFSET_StgArrBytes_bytes = 0
    , GHC.Settings.pc_OFFSET_stgEagerBlackholeInfo = 0
    , GHC.Settings.pc_OFFSET_StgEntCounter_allocd = 0
    , GHC.Settings.pc_OFFSET_StgEntCounter_allocs = 0
    , GHC.Settings.pc_OFFSET_StgEntCounter_entry_count = 0
    , GHC.Settings.pc_OFFSET_StgEntCounter_link = 0
    , GHC.Settings.pc_OFFSET_StgEntCounter_registeredp = 0
    , GHC.Settings.pc_OFFSET_StgFunInfoExtraFwd_arity = 0
    , GHC.Settings.pc_OFFSET_StgFunInfoExtraRev_arity = 0
    , GHC.Settings.pc_OFFSET_stgGCEnter1 = 0
    , GHC.Settings.pc_OFFSET_stgGCFun = 0
    , GHC.Settings.pc_OFFSET_StgHeader_ccs = 0
    , GHC.Settings.pc_OFFSET_StgHeader_ldvw = 0
    , GHC.Settings.pc_OFFSET_StgMutArrPtrs_ptrs = 0
    , GHC.Settings.pc_OFFSET_StgMutArrPtrs_size = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rCCCS = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rCurrentNursery = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rCurrentTSO = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rD1 = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rD2 = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rD3 = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rD4 = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rD5 = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rD6 = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rF1 = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rF2 = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rF3 = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rF4 = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rF5 = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rF6 = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rHp = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rHpAlloc = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rHpLim = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rL1 = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rR1 = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rR10 = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rR2 = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rR3 = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rR4 = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rR5 = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rR6 = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rR7 = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rR8 = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rR9 = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rSp = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rSpLim = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rXMM1 = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rXMM2 = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rXMM3 = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rXMM4 = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rXMM5 = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rXMM6 = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rYMM1 = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rYMM2 = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rYMM3 = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rYMM4 = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rYMM5 = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rYMM6 = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rZMM1 = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rZMM2 = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rZMM3 = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rZMM4 = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rZMM5 = 0
    , GHC.Settings.pc_OFFSET_StgRegTable_rZMM6 = 0
    , GHC.Settings.pc_OFFSET_StgSmallMutArrPtrs_ptrs = 0
    , GHC.Settings.pc_OFFSET_StgStack_sp = 0
    , GHC.Settings.pc_OFFSET_StgStack_stack = 0
    , GHC.Settings.pc_OFFSET_StgTSO_alloc_limit = 0
    , GHC.Settings.pc_OFFSET_StgTSO_cccs = 0
    , GHC.Settings.pc_OFFSET_StgTSO_stackobj = 0
    , GHC.Settings.pc_OFFSET_StgUpdateFrame_updatee = 0
    , GHC.Settings.pc_PROF_HDR_SIZE = 0
    , GHC.Settings.pc_REP_CostCentreStack_mem_alloc = 0
    , GHC.Settings.pc_REP_CostCentreStack_scc_count = 0
    , GHC.Settings.pc_REP_StgEntCounter_allocd = 0
    , GHC.Settings.pc_REP_StgEntCounter_allocs = 0
    , GHC.Settings.pc_REP_StgFunInfoExtraFwd_arity = 0
    , GHC.Settings.pc_REP_StgFunInfoExtraRev_arity = 0
    , GHC.Settings.pc_RESERVED_C_STACK_BYTES = 0
    , GHC.Settings.pc_RESERVED_STACK_WORDS = 0
    , GHC.Settings.pc_SIZEOF_CostCentreStack = 0
    , GHC.Settings.pc_SIZEOF_StgArrBytes_NoHdr = 0
    , GHC.Settings.pc_SIZEOF_StgFunInfoExtraRev = 0
    , GHC.Settings.pc_SIZEOF_StgMutArrPtrs_NoHdr = 0
    , GHC.Settings.pc_SIZEOF_StgSmallMutArrPtrs_NoHdr = 0
    , GHC.Settings.pc_SIZEOF_StgSMPThunkHeader = 0
    , GHC.Settings.pc_SIZEOF_StgUpdateFrame_NoHdr = 0
    , GHC.Settings.pc_STD_HDR_SIZE = 0
    , GHC.Settings.pc_TAG_BITS = 0
    , GHC.Settings.pc_TICKY_BIN_COUNT = 0
    , GHC.Settings.pc_WORD_SIZE = 0
    }
  
  initialPlatformMini :: GHC.Settings.PlatformMini
  initialPlatformMini = GHC.Settings.PlatformMini
    { GHC.Settings.platformMini_arch = GHC.Platform.ArchX86_64
    , GHC.Settings.platformMini_os = GHC.Platform.OSLinux
    }
  
  initialTargetPlatform :: GHC.Settings.Platform
  initialTargetPlatform = GHC.Settings.Platform
    { GHC.Settings.platformByteOrder = GHC.ByteOrder.LittleEndian
    , GHC.Settings.platformHasGnuNonexecStack = False
    , GHC.Settings.platformHasIdentDirective = False
    , GHC.Settings.platformHasSubsectionsViaSymbols = False
    , GHC.Settings.platformIsCrossCompiling = False
    , GHC.Settings.platformLeadingUnderscore = False
    , GHC.Settings.platformMini = initialPlatformMini
    , GHC.Settings.platformTablesNextToCode = False
    , GHC.Settings.platformUnregisterised = False
    , GHC.Settings.platformWordSize = GHC.Platform.PW8
    }
  
  initialToolSettings :: GHC.Settings.ToolSettings
  initialToolSettings = GHC.Settings.ToolSettings
    { GHC.Settings.toolSettings_ccSupportsNoPie = False
    , GHC.Settings.toolSettings_extraGccViaCFlags = []
    , GHC.Settings.toolSettings_ldIsGnuLd = False
    , GHC.Settings.toolSettings_ldSupportsBuildId = False
    , GHC.Settings.toolSettings_ldSupportsCompactUnwind = False
    , GHC.Settings.toolSettings_ldSupportsFilelist = False
    , GHC.Settings.toolSettings_opt_a = []
    , GHC.Settings.toolSettings_opt_c = []
    , GHC.Settings.toolSettings_opt_cxx = []
    , GHC.Settings.toolSettings_opt_F = []
    , GHC.Settings.toolSettings_opt_i = []
    , GHC.Settings.toolSettings_opt_l = []
    , GHC.Settings.toolSettings_opt_L = []
    , GHC.Settings.toolSettings_opt_lc = []
    , GHC.Settings.toolSettings_opt_lcc = []
    , GHC.Settings.toolSettings_opt_lm = []
    , GHC.Settings.toolSettings_opt_lo = []
    , GHC.Settings.toolSettings_opt_P = []
    , GHC.Settings.toolSettings_opt_P_fingerprint =
      GHC.Utils.Fingerprint.fingerprint0
    , GHC.Settings.toolSettings_opt_windres = []
    , GHC.Settings.toolSettings_pgm_a = ("", [])
    , GHC.Settings.toolSettings_pgm_ar = ""
    , GHC.Settings.toolSettings_pgm_c = ""
    , GHC.Settings.toolSettings_pgm_dll = ("", [])
    , GHC.Settings.toolSettings_pgm_F = ""
    , GHC.Settings.toolSettings_pgm_i = ""
    , GHC.Settings.toolSettings_pgm_install_name_tool = ""
    , GHC.Settings.toolSettings_pgm_l = ("", [])
    , GHC.Settings.toolSettings_pgm_L = ""
    , GHC.Settings.toolSettings_pgm_lc = ("", [])
    , GHC.Settings.toolSettings_pgm_lcc = ("", [])
    , GHC.Settings.toolSettings_pgm_libtool = ""
    , GHC.Settings.toolSettings_pgm_lm = ("", [])
    , GHC.Settings.toolSettings_pgm_lo = ("", [])
    , GHC.Settings.toolSettings_pgm_otool = ""
    , GHC.Settings.toolSettings_pgm_P = ("", [])
    , GHC.Settings.toolSettings_pgm_ranlib = ""
    , GHC.Settings.toolSettings_pgm_T = ""
    , GHC.Settings.toolSettings_pgm_windres = ""
    }
  