brittany/source/library/Language/Haskell/Brittany/Internal/ParseExact.hs

347 lines
17 KiB
Haskell

{-# LANGUAGE NoImplicitPrelude #-}
module Language.Haskell.Brittany.Internal.ParseExact
( parseModule
, parseModuleFromString
)
where
import Language.Haskell.Brittany.Internal.Prelude
import qualified Control.Monad
import qualified Control.Monad.Trans.Except as Except
import qualified GHC hiding ( parseModule )
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 System.IO
-- TODO why are redirecting to parseModuleFromString here?
parseModule
:: [String]
-> System.IO.FilePath
-> (GHC.DynFlags -> IO (Either String a))
-> IO (Either String (GHC.ParsedSource, a))
parseModule args fp dynCheck = do
str <- System.IO.readFile fp
parseModuleFromString args fp dynCheck str
-- | Parses a Haskell module. Although this nominally requires IO, it is
-- morally pure. It should have no observable effects.
parseModuleFromString
:: [String]
-> System.IO.FilePath
-> (GHC.DynFlags -> IO (Either String a))
-> String
-> IO (Either String (GHC.ParsedSource, a))
parseModuleFromString 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.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 parsedMod -> case ExactPrint.makeDeltaAst' parsedMod of
-- res -> pure (res, dynFlagsResult)
-- Right (L l (GHC.HsModule ann lay name xprt imp decls depr hdr)) ->
-- case ExactPrint.runTransform (ExactPrint.balanceCommentsList decls) of
-- (decls', _, _) ->
-- pure
-- ( L l (GHC.HsModule ann lay name xprt imp decls' depr hdr)
-- , dynFlagsResult
-- )
Right res -> pure (res, dynFlagsResult)
handleLeftovers
:: Monad m => [GHC.Types.SrcLoc.Located String] -> Except.ExceptT String m ()
handleLeftovers leftovers =
Control.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.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_ghcRTSWays = ""
, GHC.Driver.Session.platformMisc_ghcRtsWithLibdw = 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.Platform.PlatformConstants
_initialPlatformConstants = GHC.Platform.PlatformConstants
{ GHC.Platform.pc_AP_STACK_SPLIM = 0
, GHC.Platform.pc_BITMAP_BITS_SHIFT = 0
, GHC.Platform.pc_BLOCK_SIZE = 0
, GHC.Platform.pc_BLOCKS_PER_MBLOCK = 0
, GHC.Platform.pc_CINT_SIZE = 0
, GHC.Platform.pc_CLONG_LONG_SIZE = 0
, GHC.Platform.pc_CLONG_SIZE = 0
, GHC.Platform.pc_CONTROL_GROUP_CONST_291 = 0
, GHC.Platform.pc_ILDV_CREATE_MASK = 0
, GHC.Platform.pc_ILDV_STATE_CREATE = 0
, GHC.Platform.pc_ILDV_STATE_USE = 0
, GHC.Platform.pc_LDV_SHIFT = 0
, GHC.Platform.pc_MAX_CHARLIKE = 0
, GHC.Platform.pc_MAX_Double_REG = 0
, GHC.Platform.pc_MAX_Float_REG = 0
, GHC.Platform.pc_MAX_INTLIKE = 0
, GHC.Platform.pc_MAX_Long_REG = 0
, GHC.Platform.pc_MAX_Real_Double_REG = 0
, GHC.Platform.pc_MAX_Real_Float_REG = 0
, GHC.Platform.pc_MAX_Real_Long_REG = 0
, GHC.Platform.pc_MAX_Real_Vanilla_REG = 0
, GHC.Platform.pc_MAX_Real_XMM_REG = 0
, GHC.Platform.pc_MAX_SPEC_AP_SIZE = 0
, GHC.Platform.pc_MAX_SPEC_SELECTEE_SIZE = 0
, GHC.Platform.pc_MAX_Vanilla_REG = 0
, GHC.Platform.pc_MAX_XMM_REG = 0
, GHC.Platform.pc_MIN_CHARLIKE = 0
, GHC.Platform.pc_MIN_INTLIKE = 0
, GHC.Platform.pc_MIN_PAYLOAD_SIZE = 0
, GHC.Platform.pc_MUT_ARR_PTRS_CARD_BITS = 0
, GHC.Platform.pc_OFFSET_bdescr_blocks = 0
, GHC.Platform.pc_OFFSET_bdescr_flags = 0
, GHC.Platform.pc_OFFSET_bdescr_free = 0
, GHC.Platform.pc_OFFSET_bdescr_start = 0
, GHC.Platform.pc_OFFSET_Capability_r = 0
, GHC.Platform.pc_OFFSET_CostCentreStack_mem_alloc = 0
, GHC.Platform.pc_OFFSET_CostCentreStack_scc_count = 0
, GHC.Platform.pc_OFFSET_StgArrBytes_bytes = 0
, GHC.Platform.pc_OFFSET_stgEagerBlackholeInfo = 0
, GHC.Platform.pc_OFFSET_StgEntCounter_allocd = 0
, GHC.Platform.pc_OFFSET_StgEntCounter_allocs = 0
, GHC.Platform.pc_OFFSET_StgEntCounter_entry_count = 0
, GHC.Platform.pc_OFFSET_StgEntCounter_link = 0
, GHC.Platform.pc_OFFSET_StgEntCounter_registeredp = 0
, GHC.Platform.pc_OFFSET_StgFunInfoExtraFwd_arity = 0
, GHC.Platform.pc_OFFSET_StgFunInfoExtraRev_arity = 0
, GHC.Platform.pc_OFFSET_stgGCEnter1 = 0
, GHC.Platform.pc_OFFSET_stgGCFun = 0
, GHC.Platform.pc_OFFSET_StgHeader_ccs = 0
, GHC.Platform.pc_OFFSET_StgHeader_ldvw = 0
, GHC.Platform.pc_OFFSET_StgMutArrPtrs_ptrs = 0
, GHC.Platform.pc_OFFSET_StgMutArrPtrs_size = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rCCCS = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rCurrentNursery = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rCurrentTSO = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rD1 = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rD2 = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rD3 = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rD4 = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rD5 = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rD6 = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rF1 = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rF2 = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rF3 = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rF4 = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rF5 = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rF6 = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rHp = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rHpAlloc = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rHpLim = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rL1 = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rR1 = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rR10 = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rR2 = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rR3 = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rR4 = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rR5 = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rR6 = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rR7 = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rR8 = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rR9 = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rSp = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rSpLim = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rXMM1 = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rXMM2 = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rXMM3 = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rXMM4 = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rXMM5 = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rXMM6 = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rYMM1 = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rYMM2 = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rYMM3 = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rYMM4 = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rYMM5 = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rYMM6 = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rZMM1 = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rZMM2 = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rZMM3 = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rZMM4 = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rZMM5 = 0
, GHC.Platform.pc_OFFSET_StgRegTable_rZMM6 = 0
, GHC.Platform.pc_OFFSET_StgSmallMutArrPtrs_ptrs = 0
, GHC.Platform.pc_OFFSET_StgStack_sp = 0
, GHC.Platform.pc_OFFSET_StgStack_stack = 0
, GHC.Platform.pc_OFFSET_StgTSO_alloc_limit = 0
, GHC.Platform.pc_OFFSET_StgTSO_cccs = 0
, GHC.Platform.pc_OFFSET_StgTSO_stackobj = 0
, GHC.Platform.pc_OFFSET_StgUpdateFrame_updatee = 0
, GHC.Platform.pc_PROF_HDR_SIZE = 0
, GHC.Platform.pc_REP_CostCentreStack_mem_alloc = 0
, GHC.Platform.pc_REP_CostCentreStack_scc_count = 0
, GHC.Platform.pc_REP_StgEntCounter_allocd = 0
, GHC.Platform.pc_REP_StgEntCounter_allocs = 0
, GHC.Platform.pc_REP_StgFunInfoExtraFwd_arity = 0
, GHC.Platform.pc_REP_StgFunInfoExtraRev_arity = 0
, GHC.Platform.pc_RESERVED_C_STACK_BYTES = 0
, GHC.Platform.pc_RESERVED_STACK_WORDS = 0
, GHC.Platform.pc_SIZEOF_CostCentreStack = 0
, GHC.Platform.pc_SIZEOF_StgArrBytes_NoHdr = 0
, GHC.Platform.pc_SIZEOF_StgFunInfoExtraRev = 0
, GHC.Platform.pc_SIZEOF_StgMutArrPtrs_NoHdr = 0
, GHC.Platform.pc_SIZEOF_StgSmallMutArrPtrs_NoHdr = 0
, GHC.Platform.pc_SIZEOF_StgSMPThunkHeader = 0
, GHC.Platform.pc_SIZEOF_StgUpdateFrame_NoHdr = 0
, GHC.Platform.pc_STD_HDR_SIZE = 0
, GHC.Platform.pc_TAG_BITS = 0
, GHC.Platform.pc_TICKY_BIN_COUNT = 0
, GHC.Platform.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.platformArchOS = initialArchOS
, 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
, GHC.Settings.platform_constants = Nothing
}
initialArchOS :: GHC.Platform.ArchOS
initialArchOS = GHC.Platform.ArchOS
{ GHC.Platform.archOS_arch = GHC.Platform.ArchUnknown -- why do we need to specify these?
, GHC.Platform.archOS_OS = GHC.Platform.OSUnknown -- why do we need to specify these?
}
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 = ""
}