    module GHC.CmmToLlvm.Version
      ( LlvmVersion(..)
      , supportedLlvmVersionLowerBound
      , supportedLlvmVersionUpperBound
      , parseLlvmVersion
      , llvmVersionSupported
      , llvmVersionStr
      , llvmVersionList
      )
    where

    import GHC.Prelude

    import GHC.CmmToLlvm.Version.Type
    import GHC.CmmToLlvm.Version.Bounds

    import Data.Char (isDigit)
    import Data.List (intercalate)
    import qualified Data.List.NonEmpty as NE

    parseLlvmVersion :: String -> Maybe LlvmVersion
    parseLlvmVersion :: String -> Maybe LlvmVersion
    parseLlvmVersion =
        (NonEmpty Int -> LlvmVersion)
    -> Maybe (NonEmpty Int) -> Maybe LlvmVersion
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap NonEmpty Int -> LlvmVersion
    LlvmVersion (Maybe (NonEmpty Int) -> Maybe LlvmVersion)
    -> (String -> Maybe (NonEmpty Int)) -> String -> Maybe LlvmVersion
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [Int] -> Maybe (NonEmpty Int)
    forall a. [a] -> Maybe (NonEmpty a)
    NE.nonEmpty ([Int] -> Maybe (NonEmpty Int))
    -> (String -> [Int]) -> String -> Maybe (NonEmpty Int)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [Int] -> String -> [Int]
    forall {a}. Read a => [a] -> String -> [a]
    go [] (String -> [Int]) -> (String -> String) -> String -> [Int]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Char -> Bool) -> String -> String
    forall a. (a -> Bool) -> [a] -> [a]
    dropWhile (Bool -> Bool
    not (Bool -> Bool) -> (Char -> Bool) -> Char -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Char -> Bool
    isDigit)
      where
        go :: [a] -> String -> [a]
    go [a]
    vs String
    s
          | String -> Bool
    forall a. [a] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null String
    ver_str
          = [a] -> [a]
    forall a. [a] -> [a]
    reverse [a]
    vs
          | Char
    '.' : String
    rest' <- String
    rest
          = [a] -> String -> [a]
    go (String -> a
    forall a. Read a => String -> a
    read String
    ver_str a -> [a] -> [a]
    forall a. a -> [a] -> [a]
    : [a]
    vs) String
    rest'
          | Bool
    otherwise
          = [a] -> [a]
    forall a. [a] -> [a]
    reverse (String -> a
    forall a. Read a => String -> a
    read String
    ver_str a -> [a] -> [a]
    forall a. a -> [a] -> [a]
    : [a]
    vs)
          where
            (String
    ver_str, String
    rest) = (Char -> Bool) -> String -> (String, String)
    forall a. (a -> Bool) -> [a] -> ([a], [a])
    span Char -> Bool
    isDigit String
    s

    llvmVersionSupported :: LlvmVersion -> Bool
    llvmVersionSupported :: LlvmVersion -> Bool
    llvmVersionSupported LlvmVersion
    v =
      LlvmVersion
    v LlvmVersion -> LlvmVersion -> Bool
    forall a. Ord a => a -> a -> Bool
    >= LlvmVersion
    supportedLlvmVersionLowerBound Bool -> Bool -> Bool
    && LlvmVersion
    v LlvmVersion -> LlvmVersion -> Bool
    forall a. Ord a => a -> a -> Bool
    < LlvmVersion
    supportedLlvmVersionUpperBound

    llvmVersionStr :: LlvmVersion -> String
    llvmVersionStr :: LlvmVersion -> String
    llvmVersionStr = String -> [String] -> String
    forall a. [a] -> [[a]] -> [a]
    intercalate String
    "." ([String] -> String)
    -> (LlvmVersion -> [String]) -> LlvmVersion -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Int -> String) -> [Int] -> [String]
    forall a b. (a -> b) -> [a] -> [b]
    map Int -> String
    forall a. Show a => a -> String
    show ([Int] -> [String])
    -> (LlvmVersion -> [Int]) -> LlvmVersion -> [String]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . LlvmVersion -> [Int]
    llvmVersionList

    llvmVersionList :: LlvmVersion -> [Int]
    llvmVersionList :: LlvmVersion -> [Int]
    llvmVersionList = NonEmpty Int -> [Int]
    forall a. NonEmpty a -> [a]
    NE.toList (NonEmpty Int -> [Int])
    -> (LlvmVersion -> NonEmpty Int) -> LlvmVersion -> [Int]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . LlvmVersion -> NonEmpty Int
    llvmVersionNE