{-# LANGUAGE DeriveAnyClass             #-}
{-# LANGUAGE DerivingStrategies         #-}
{-# LANGUAGE DerivingVia                #-}
{-# LANGUAGE GeneralisedNewtypeDeriving #-}
{-# LANGUAGE LambdaCase                 #-}
{-# LANGUAGE MultiWayIf                 #-}
{-# LANGUAGE OverloadedStrings          #-}
{-# LANGUAGE RecordWildCards            #-}
{-# LANGUAGE ScopedTypeVariables        #-}
{-# LANGUAGE StandaloneDeriving         #-}
{-# LANGUAGE TupleSections              #-}

module HS.Types.CompilerTool
  ( Compiler(..)
  , Tool(..)
  , CompilerVersion(..)
  , ToolName(..)
  , compiler
  , compiler'
  , compilerVersion
  , toolVersion
  , compilerToGhcTool
  , compilerToTool
  , toolToCompiler
  , toolToCompiler'
  ) where

import           Data.Char
import           Data.Coerce
import           Data.Default
import           Data.Possibly
import           Data.Text(Text)
import qualified Data.Text              as T
import           Fmt
import           Text.Enum.Text


-- | @ghc@ or @ghc-8.10.4@, etc.
newtype Compiler = Compiler { Compiler -> Maybe CompilerVersion
getCompiler :: Maybe CompilerVersion }
  deriving (Compiler -> Compiler -> Bool
(Compiler -> Compiler -> Bool)
-> (Compiler -> Compiler -> Bool) -> Eq Compiler
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Compiler -> Compiler -> Bool
$c/= :: Compiler -> Compiler -> Bool
== :: Compiler -> Compiler -> Bool
$c== :: Compiler -> Compiler -> Bool
Eq,Eq Compiler
Eq Compiler
-> (Compiler -> Compiler -> Ordering)
-> (Compiler -> Compiler -> Bool)
-> (Compiler -> Compiler -> Bool)
-> (Compiler -> Compiler -> Bool)
-> (Compiler -> Compiler -> Bool)
-> (Compiler -> Compiler -> Compiler)
-> (Compiler -> Compiler -> Compiler)
-> Ord Compiler
Compiler -> Compiler -> Bool
Compiler -> Compiler -> Ordering
Compiler -> Compiler -> Compiler
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Compiler -> Compiler -> Compiler
$cmin :: Compiler -> Compiler -> Compiler
max :: Compiler -> Compiler -> Compiler
$cmax :: Compiler -> Compiler -> Compiler
>= :: Compiler -> Compiler -> Bool
$c>= :: Compiler -> Compiler -> Bool
> :: Compiler -> Compiler -> Bool
$c> :: Compiler -> Compiler -> Bool
<= :: Compiler -> Compiler -> Bool
$c<= :: Compiler -> Compiler -> Bool
< :: Compiler -> Compiler -> Bool
$c< :: Compiler -> Compiler -> Bool
compare :: Compiler -> Compiler -> Ordering
$ccompare :: Compiler -> Compiler -> Ordering
$cp1Ord :: Eq Compiler
Ord,Int -> Compiler -> ShowS
[Compiler] -> ShowS
Compiler -> String
(Int -> Compiler -> ShowS)
-> (Compiler -> String) -> ([Compiler] -> ShowS) -> Show Compiler
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Compiler] -> ShowS
$cshowList :: [Compiler] -> ShowS
show :: Compiler -> String
$cshow :: Compiler -> String
showsPrec :: Int -> Compiler -> ShowS
$cshowsPrec :: Int -> Compiler -> ShowS
Show)

-- | @ghci@ or @ghc-pkg-9.0.1@, etc.
newtype Tool = Tool { Tool -> (ToolName, Maybe CompilerVersion)
getTool :: (ToolName,Maybe CompilerVersion) }
  deriving (Tool -> Tool -> Bool
(Tool -> Tool -> Bool) -> (Tool -> Tool -> Bool) -> Eq Tool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Tool -> Tool -> Bool
$c/= :: Tool -> Tool -> Bool
== :: Tool -> Tool -> Bool
$c== :: Tool -> Tool -> Bool
Eq,Eq Tool
Eq Tool
-> (Tool -> Tool -> Ordering)
-> (Tool -> Tool -> Bool)
-> (Tool -> Tool -> Bool)
-> (Tool -> Tool -> Bool)
-> (Tool -> Tool -> Bool)
-> (Tool -> Tool -> Tool)
-> (Tool -> Tool -> Tool)
-> Ord Tool
Tool -> Tool -> Bool
Tool -> Tool -> Ordering
Tool -> Tool -> Tool
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Tool -> Tool -> Tool
$cmin :: Tool -> Tool -> Tool
max :: Tool -> Tool -> Tool
$cmax :: Tool -> Tool -> Tool
>= :: Tool -> Tool -> Bool
$c>= :: Tool -> Tool -> Bool
> :: Tool -> Tool -> Bool
$c> :: Tool -> Tool -> Bool
<= :: Tool -> Tool -> Bool
$c<= :: Tool -> Tool -> Bool
< :: Tool -> Tool -> Bool
$c< :: Tool -> Tool -> Bool
compare :: Tool -> Tool -> Ordering
$ccompare :: Tool -> Tool -> Ordering
$cp1Ord :: Eq Tool
Ord,Int -> Tool -> ShowS
[Tool] -> ShowS
Tool -> String
(Int -> Tool -> ShowS)
-> (Tool -> String) -> ([Tool] -> ShowS) -> Show Tool
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Tool] -> ShowS
$cshowList :: [Tool] -> ShowS
show :: Tool -> String
$cshow :: Tool -> String
showsPrec :: Int -> Tool -> ShowS
$cshowsPrec :: Int -> Tool -> ShowS
Show)

-- | @8.6.5@, etc.
newtype CompilerVersion = CompilerVersion { CompilerVersion -> (Int, Int, Int)
getCompilerVersion :: (Int,Int,Int) }
  deriving (CompilerVersion -> CompilerVersion -> Bool
(CompilerVersion -> CompilerVersion -> Bool)
-> (CompilerVersion -> CompilerVersion -> Bool)
-> Eq CompilerVersion
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CompilerVersion -> CompilerVersion -> Bool
$c/= :: CompilerVersion -> CompilerVersion -> Bool
== :: CompilerVersion -> CompilerVersion -> Bool
$c== :: CompilerVersion -> CompilerVersion -> Bool
Eq,Eq CompilerVersion
Eq CompilerVersion
-> (CompilerVersion -> CompilerVersion -> Ordering)
-> (CompilerVersion -> CompilerVersion -> Bool)
-> (CompilerVersion -> CompilerVersion -> Bool)
-> (CompilerVersion -> CompilerVersion -> Bool)
-> (CompilerVersion -> CompilerVersion -> Bool)
-> (CompilerVersion -> CompilerVersion -> CompilerVersion)
-> (CompilerVersion -> CompilerVersion -> CompilerVersion)
-> Ord CompilerVersion
CompilerVersion -> CompilerVersion -> Bool
CompilerVersion -> CompilerVersion -> Ordering
CompilerVersion -> CompilerVersion -> CompilerVersion
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: CompilerVersion -> CompilerVersion -> CompilerVersion
$cmin :: CompilerVersion -> CompilerVersion -> CompilerVersion
max :: CompilerVersion -> CompilerVersion -> CompilerVersion
$cmax :: CompilerVersion -> CompilerVersion -> CompilerVersion
>= :: CompilerVersion -> CompilerVersion -> Bool
$c>= :: CompilerVersion -> CompilerVersion -> Bool
> :: CompilerVersion -> CompilerVersion -> Bool
$c> :: CompilerVersion -> CompilerVersion -> Bool
<= :: CompilerVersion -> CompilerVersion -> Bool
$c<= :: CompilerVersion -> CompilerVersion -> Bool
< :: CompilerVersion -> CompilerVersion -> Bool
$c< :: CompilerVersion -> CompilerVersion -> Bool
compare :: CompilerVersion -> CompilerVersion -> Ordering
$ccompare :: CompilerVersion -> CompilerVersion -> Ordering
$cp1Ord :: Eq CompilerVersion
Ord,Int -> CompilerVersion -> ShowS
[CompilerVersion] -> ShowS
CompilerVersion -> String
(Int -> CompilerVersion -> ShowS)
-> (CompilerVersion -> String)
-> ([CompilerVersion] -> ShowS)
-> Show CompilerVersion
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [CompilerVersion] -> ShowS
$cshowList :: [CompilerVersion] -> ShowS
show :: CompilerVersion -> String
$cshow :: CompilerVersion -> String
showsPrec :: Int -> CompilerVersion -> ShowS
$cshowsPrec :: Int -> CompilerVersion -> ShowS
Show)

-- | @ghc@, @ghc-pkg@, @ghci@, etc.
data ToolName
  = TN_ghc
  | TN_ghc_pkg
  | TN_ghci
  | TN_haddock
  | TN_h2ps
  | TN_hpc
  | TN_hsc2hs
  | TN_runghc
  | TN_runhaskell
  deriving stock    (ToolName
ToolName -> ToolName -> Bounded ToolName
forall a. a -> a -> Bounded a
maxBound :: ToolName
$cmaxBound :: ToolName
minBound :: ToolName
$cminBound :: ToolName
Bounded,Int -> ToolName
ToolName -> Int
ToolName -> [ToolName]
ToolName -> ToolName
ToolName -> ToolName -> [ToolName]
ToolName -> ToolName -> ToolName -> [ToolName]
(ToolName -> ToolName)
-> (ToolName -> ToolName)
-> (Int -> ToolName)
-> (ToolName -> Int)
-> (ToolName -> [ToolName])
-> (ToolName -> ToolName -> [ToolName])
-> (ToolName -> ToolName -> [ToolName])
-> (ToolName -> ToolName -> ToolName -> [ToolName])
-> Enum ToolName
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: ToolName -> ToolName -> ToolName -> [ToolName]
$cenumFromThenTo :: ToolName -> ToolName -> ToolName -> [ToolName]
enumFromTo :: ToolName -> ToolName -> [ToolName]
$cenumFromTo :: ToolName -> ToolName -> [ToolName]
enumFromThen :: ToolName -> ToolName -> [ToolName]
$cenumFromThen :: ToolName -> ToolName -> [ToolName]
enumFrom :: ToolName -> [ToolName]
$cenumFrom :: ToolName -> [ToolName]
fromEnum :: ToolName -> Int
$cfromEnum :: ToolName -> Int
toEnum :: Int -> ToolName
$ctoEnum :: Int -> ToolName
pred :: ToolName -> ToolName
$cpred :: ToolName -> ToolName
succ :: ToolName -> ToolName
$csucc :: ToolName -> ToolName
Enum,ToolName -> ToolName -> Bool
(ToolName -> ToolName -> Bool)
-> (ToolName -> ToolName -> Bool) -> Eq ToolName
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ToolName -> ToolName -> Bool
$c/= :: ToolName -> ToolName -> Bool
== :: ToolName -> ToolName -> Bool
$c== :: ToolName -> ToolName -> Bool
Eq,Eq ToolName
Eq ToolName
-> (ToolName -> ToolName -> Ordering)
-> (ToolName -> ToolName -> Bool)
-> (ToolName -> ToolName -> Bool)
-> (ToolName -> ToolName -> Bool)
-> (ToolName -> ToolName -> Bool)
-> (ToolName -> ToolName -> ToolName)
-> (ToolName -> ToolName -> ToolName)
-> Ord ToolName
ToolName -> ToolName -> Bool
ToolName -> ToolName -> Ordering
ToolName -> ToolName -> ToolName
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: ToolName -> ToolName -> ToolName
$cmin :: ToolName -> ToolName -> ToolName
max :: ToolName -> ToolName -> ToolName
$cmax :: ToolName -> ToolName -> ToolName
>= :: ToolName -> ToolName -> Bool
$c>= :: ToolName -> ToolName -> Bool
> :: ToolName -> ToolName -> Bool
$c> :: ToolName -> ToolName -> Bool
<= :: ToolName -> ToolName -> Bool
$c<= :: ToolName -> ToolName -> Bool
< :: ToolName -> ToolName -> Bool
$c< :: ToolName -> ToolName -> Bool
compare :: ToolName -> ToolName -> Ordering
$ccompare :: ToolName -> ToolName -> Ordering
$cp1Ord :: Eq ToolName
Ord,Int -> ToolName -> ShowS
[ToolName] -> ShowS
ToolName -> String
(Int -> ToolName -> ShowS)
-> (ToolName -> String) -> ([ToolName] -> ShowS) -> Show ToolName
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ToolName] -> ShowS
$cshowList :: [ToolName] -> ShowS
show :: ToolName -> String
$cshow :: ToolName -> String
showsPrec :: Int -> ToolName -> ShowS
$cshowsPrec :: Int -> ToolName -> ShowS
Show)
  deriving anyclass (Bounded ToolName
Enum ToolName
Eq ToolName
Ord ToolName
Show ToolName
TextParsable ToolName
Buildable ToolName
Int -> ToolName -> Int
Text -> Possibly ToolName
Buildable ToolName
-> Bounded ToolName
-> Enum ToolName
-> Eq ToolName
-> Ord ToolName
-> Show ToolName
-> TextParsable ToolName
-> (ToolName -> EnumTextConfig)
-> (ToolName -> Text)
-> (ToolName -> Builder)
-> (Text -> Possibly ToolName)
-> (ToolName -> ByteString)
-> (forall (m :: * -> *). MonadFail m => ByteString -> m ToolName)
-> (Int -> ToolName -> Int)
-> EnumText ToolName
ToolName -> ByteString
ToolName -> Builder
ToolName -> Text
ToolName -> EnumTextConfig
forall e.
Buildable e
-> Bounded e
-> Enum e
-> Eq e
-> Ord e
-> Show e
-> TextParsable e
-> (e -> EnumTextConfig)
-> (e -> Text)
-> (e -> Builder)
-> (Text -> Possibly e)
-> (e -> ByteString)
-> (forall (m :: * -> *). MonadFail m => ByteString -> m e)
-> (Int -> e -> Int)
-> EnumText e
forall (m :: * -> *). MonadFail m => ByteString -> m ToolName
hashWithSaltEnumText :: Int -> ToolName -> Int
$chashWithSaltEnumText :: Int -> ToolName -> Int
fromFieldEnumText_ :: ByteString -> m ToolName
$cfromFieldEnumText_ :: forall (m :: * -> *). MonadFail m => ByteString -> m ToolName
toFieldEnumText :: ToolName -> ByteString
$ctoFieldEnumText :: ToolName -> ByteString
parseEnumText :: Text -> Possibly ToolName
$cparseEnumText :: Text -> Possibly ToolName
buildEnumText :: ToolName -> Builder
$cbuildEnumText :: ToolName -> Builder
renderEnumText :: ToolName -> Text
$crenderEnumText :: ToolName -> Text
configEnumText :: ToolName -> EnumTextConfig
$cconfigEnumText :: ToolName -> EnumTextConfig
$cp7EnumText :: TextParsable ToolName
$cp6EnumText :: Show ToolName
$cp5EnumText :: Ord ToolName
$cp4EnumText :: Eq ToolName
$cp3EnumText :: Enum ToolName
$cp2EnumText :: Bounded ToolName
$cp1EnumText :: Buildable ToolName
EnumText)
  deriving (ToolName -> Builder
(ToolName -> Builder) -> Buildable ToolName
forall p. (p -> Builder) -> Buildable p
build :: ToolName -> Builder
$cbuild :: ToolName -> Builder
Buildable,Text -> Possibly ToolName
(Text -> Possibly ToolName) -> TextParsable ToolName
forall a. (Text -> Possibly a) -> TextParsable a
parseText :: Text -> Possibly ToolName
$cparseText :: Text -> Possibly ToolName
TextParsable) via UsingEnumText ToolName

instance Buildable    Compiler where build :: Compiler -> Builder
build     = Compiler -> Builder
build_compiler
instance TextParsable Compiler where parseText :: Text -> Possibly Compiler
parseText = Text -> Possibly Compiler
parse_compiler
instance Buildable    Tool     where build :: Tool -> Builder
build     = Tool -> Builder
build_tool
instance TextParsable Tool     where parseText :: Text -> Possibly Tool
parseText = Text -> Possibly Tool
parse_tool

instance Buildable CompilerVersion where
  build :: CompilerVersion -> Builder
build (CompilerVersion (Int
a,Int
b,Int
c)) = Builder
""Builder -> Builder -> Builder
forall b. FromBuilder b => Builder -> Builder -> b
+|Int
aInt -> Builder -> Builder
forall a b. (Buildable a, FromBuilder b) => a -> Builder -> b
|+Builder
"."Builder -> Builder -> Builder
forall b. FromBuilder b => Builder -> Builder -> b
+|Int
bInt -> Builder -> Builder
forall a b. (Buildable a, FromBuilder b) => a -> Builder -> b
|+Builder
"."Builder -> Builder -> Builder
forall b. FromBuilder b => Builder -> Builder -> b
+|Int
cInt -> Builder -> Builder
forall a b. (Buildable a, FromBuilder b) => a -> Builder -> b
|+Builder
""

instance TextParsable CompilerVersion where
  parseText :: Text -> Possibly CompilerVersion
parseText Text
vrn =
    case Text -> Text -> [Text]
T.splitOn Text
"." Text
vrn of
      [Text
a_t,Text
b_t,Text
c_t] -> ((Int, Int, Int) -> CompilerVersion)
-> Either String (Int, Int, Int) -> Possibly CompilerVersion
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Int, Int, Int) -> CompilerVersion
CompilerVersion (Either String (Int, Int, Int) -> Possibly CompilerVersion)
-> Either String (Int, Int, Int) -> Possibly CompilerVersion
forall a b. (a -> b) -> a -> b
$
                            (,,) (Int -> Int -> Int -> (Int, Int, Int))
-> Either String Int
-> Either String (Int -> Int -> (Int, Int, Int))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> Either String Int
forall a. TextParsable a => Text -> Possibly a
parseText Text
a_t Either String (Int -> Int -> (Int, Int, Int))
-> Either String Int -> Either String (Int -> (Int, Int, Int))
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Text -> Either String Int
forall a. TextParsable a => Text -> Possibly a
parseText Text
b_t Either String (Int -> (Int, Int, Int))
-> Either String Int -> Either String (Int, Int, Int)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Text -> Either String Int
forall a. TextParsable a => Text -> Possibly a
parseText Text
c_t
      [Text]
_             -> String -> Possibly CompilerVersion
forall a b. a -> Either a b
Left (String -> Possibly CompilerVersion)
-> String -> Possibly CompilerVersion
forall a b. (a -> b) -> a -> b
$ Builder
"expected version a.b.c : "Builder -> Builder -> String
forall b. FromBuilder b => Builder -> Builder -> b
+|Text
vrnText -> Builder -> Builder
forall a b. (Buildable a, FromBuilder b) => a -> Builder -> b
|+Builder
""

instance Default CompilerVersion where
  def :: CompilerVersion
def = (Int, Int, Int) -> CompilerVersion
CompilerVersion (Int
8,Int
10,Int
4)

compiler :: CompilerVersion -> Compiler
compiler :: CompilerVersion -> Compiler
compiler = Maybe CompilerVersion -> Compiler
compiler' (Maybe CompilerVersion -> Compiler)
-> (CompilerVersion -> Maybe CompilerVersion)
-> CompilerVersion
-> Compiler
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CompilerVersion -> Maybe CompilerVersion
forall a. a -> Maybe a
Just

compiler' :: Maybe CompilerVersion -> Compiler
compiler' :: Maybe CompilerVersion -> Compiler
compiler' = Maybe CompilerVersion -> Compiler
coerce

compilerVersion :: Compiler -> Maybe CompilerVersion
compilerVersion :: Compiler -> Maybe CompilerVersion
compilerVersion = Compiler -> Maybe CompilerVersion
coerce

toolVersion :: Tool -> Maybe CompilerVersion
toolVersion :: Tool -> Maybe CompilerVersion
toolVersion = Compiler -> Maybe CompilerVersion
compilerVersion (Compiler -> Maybe CompilerVersion)
-> (Tool -> Compiler) -> Tool -> Maybe CompilerVersion
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Tool -> Compiler
toolToCompiler

compilerToGhcTool :: Compiler -> Tool
compilerToGhcTool :: Compiler -> Tool
compilerToGhcTool = (ToolName, Compiler) -> Tool
compilerToTool ((ToolName, Compiler) -> Tool)
-> (Compiler -> (ToolName, Compiler)) -> Compiler -> Tool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (,) ToolName
TN_ghc

compilerToTool :: (ToolName,Compiler) -> Tool
compilerToTool :: (ToolName, Compiler) -> Tool
compilerToTool = (ToolName, Compiler) -> Tool
coerce

toolToCompiler :: Tool -> Compiler
toolToCompiler :: Tool -> Compiler
toolToCompiler = (ToolName, Compiler) -> Compiler
forall a b. (a, b) -> b
snd ((ToolName, Compiler) -> Compiler)
-> (Tool -> (ToolName, Compiler)) -> Tool -> Compiler
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Tool -> (ToolName, Compiler)
toolToCompiler'

toolToCompiler' :: Tool -> (ToolName,Compiler)
toolToCompiler' :: Tool -> (ToolName, Compiler)
toolToCompiler' = Tool -> (ToolName, Compiler)
coerce


----------------------------------------------------------------------------------------------------
-- build_compiler, parse_compiler
----------------------------------------------------------------------------------------------------

build_compiler :: Compiler -> Builder
build_compiler :: Compiler -> Builder
build_compiler = Tool -> Builder
forall p. Buildable p => p -> Builder
build (Tool -> Builder) -> (Compiler -> Tool) -> Compiler -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Compiler -> Tool
compilerToGhcTool

parse_compiler :: Text -> Possibly Compiler
parse_compiler :: Text -> Possibly Compiler
parse_compiler Text
txt = Tool -> Possibly Compiler
chk (Tool -> Possibly Compiler) -> Possibly Tool -> Possibly Compiler
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Text -> Possibly Tool
forall a. TextParsable a => Text -> Possibly a
parseText Text
txt
  where
    chk :: Tool -> Possibly Compiler
    chk :: Tool -> Possibly Compiler
chk Tool
tl | ToolName
tn ToolName -> ToolName -> Bool
forall a. Eq a => a -> a -> Bool
== ToolName
TN_ghc = Compiler -> Possibly Compiler
forall (m :: * -> *) a. Monad m => a -> m a
return Compiler
cp
           | Bool
otherwise    = String -> Possibly Compiler
forall a b. a -> Either a b
Left (String -> Possibly Compiler) -> String -> Possibly Compiler
forall a b. (a -> b) -> a -> b
$ Builder
"expected 'ghc' but saw "Builder -> Builder -> String
forall b. FromBuilder b => Builder -> Builder -> b
+|ToolName
tnToolName -> Builder -> Builder
forall a b. (Buildable a, FromBuilder b) => a -> Builder -> b
|+Builder
" in: "Builder -> Builder -> Builder
forall b. FromBuilder b => Builder -> Builder -> b
+|Text
txtText -> Builder -> Builder
forall a b. (Buildable a, FromBuilder b) => a -> Builder -> b
|+Builder
""
      where
        (ToolName
tn,Compiler
cp) = Tool -> (ToolName, Compiler)
toolToCompiler' Tool
tl


----------------------------------------------------------------------------------------------------
-- build_tool, parse_tool
----------------------------------------------------------------------------------------------------

build_tool :: Tool -> Builder
build_tool :: Tool -> Builder
build_tool Tool
tl = Builder
""Builder -> Builder -> Builder
forall b. FromBuilder b => Builder -> Builder -> b
+|ToolName
tnToolName -> Builder -> Builder
forall a b. (Buildable a, FromBuilder b) => a -> Builder -> b
|++|Builder
-> (CompilerVersion -> Builder) -> Maybe CompilerVersion -> Builder
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Builder
"" ((Builder
"-"Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>) (Builder -> Builder)
-> (CompilerVersion -> Builder) -> CompilerVersion -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CompilerVersion -> Builder
forall p. Buildable p => p -> Builder
build) Maybe CompilerVersion
mb_vrn
  where
    mb_vrn :: Maybe CompilerVersion
mb_vrn  = Compiler -> Maybe CompilerVersion
compilerVersion Compiler
cp
    (ToolName
tn,Compiler
cp) = Tool -> (ToolName, Compiler)
toolToCompiler' Tool
tl

parse_tool :: Text -> Possibly Tool
parse_tool :: Text -> Possibly Tool
parse_tool Text
txt0 = case Text -> Text -> (Text, Text)
T.breakOnEnd Text
"-" Text
txt0 of
    (Text
frt,Text
vrn) | Bool -> Bool
not (Text -> Bool
T.null Text
frt) Bool -> Bool -> Bool
&& Text -> Bool
plausible_vrn Text
vrn
                          -> Text -> Text -> Possibly Tool
with_vrn ((Char -> Bool) -> Text -> Text
T.dropWhileEnd (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
==Char
'-') Text
frt) Text
vrn
              | Bool
otherwise -> (ToolName, Maybe CompilerVersion) -> Tool
Tool ((ToolName, Maybe CompilerVersion) -> Tool)
-> (ToolName -> (ToolName, Maybe CompilerVersion))
-> ToolName
-> Tool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (,Maybe CompilerVersion
forall a. Maybe a
Nothing) (ToolName -> Tool) -> Possibly ToolName -> Possibly Tool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> Possibly ToolName
forall a. TextParsable a => Text -> Possibly a
parseText Text
txt0
  where
    with_vrn :: Text -> Text -> Possibly Tool
    with_vrn :: Text -> Text -> Possibly Tool
with_vrn Text
tool Text
vrn = ((ToolName, Maybe CompilerVersion) -> Tool)
-> Either String (ToolName, Maybe CompilerVersion) -> Possibly Tool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (ToolName, Maybe CompilerVersion) -> Tool
Tool (Either String (ToolName, Maybe CompilerVersion) -> Possibly Tool)
-> Either String (ToolName, Maybe CompilerVersion) -> Possibly Tool
forall a b. (a -> b) -> a -> b
$
          (,) (ToolName
 -> Maybe CompilerVersion -> (ToolName, Maybe CompilerVersion))
-> Possibly ToolName
-> Either
     String (Maybe CompilerVersion -> (ToolName, Maybe CompilerVersion))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> Possibly ToolName
forall a. TextParsable a => Text -> Possibly a
parseText Text
tool Either
  String (Maybe CompilerVersion -> (ToolName, Maybe CompilerVersion))
-> Either String (Maybe CompilerVersion)
-> Either String (ToolName, Maybe CompilerVersion)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (CompilerVersion -> Maybe CompilerVersion
forall a. a -> Maybe a
Just (CompilerVersion -> Maybe CompilerVersion)
-> Possibly CompilerVersion
-> Either String (Maybe CompilerVersion)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> Possibly CompilerVersion
forall a. TextParsable a => Text -> Possibly a
parseText Text
vrn)

plausible_vrn :: Text -> Bool
plausible_vrn :: Text -> Bool
plausible_vrn = (Char -> Bool) -> Text -> Bool
T.all Char -> Bool
is_vrn_c
  where
    is_vrn_c :: Char -> Bool
    is_vrn_c :: Char -> Bool
is_vrn_c Char
c = Char -> Bool
isDigit Char
c Bool -> Bool -> Bool
|| Char
cChar -> Char -> Bool
forall a. Eq a => a -> a -> Bool
==Char
'.'