{-# LANGUAGE CPP #-}
{-# LANGUAGE TemplateHaskell #-}

-- | This module exports version information about the Futhark
-- compiler.
module Futhark.Version
  ( version,
    versionString,
  )
where

import Data.ByteString.Char8 qualified as BS
import Data.FileEmbed
import Data.Text qualified as T
import Data.Version
import Futhark.Util (showText, trim)
import GitHash
import Paths_futhark qualified

{-# NOINLINE version #-}

-- | The version of Futhark that we are using.  This is equivalent to
-- the version defined in the .cabal file.
version :: Version
version :: Version
version = Version
Paths_futhark.version

{-# NOINLINE versionString #-}

-- | The version of Futhark that we are using, in human-readable form.
versionString :: T.Text
versionString :: Text
versionString =
  String -> Text
T.pack (Version -> String
showVersion Version
version) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
unreleased Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Either String GitInfo -> Text
forall {a}. Either a GitInfo -> Text
gitversion $$Bool
Int
String
[String]
String
-> String
-> Bool
-> String
-> Int
-> [String]
-> String
-> String
-> String
-> GitInfo
GitInfo -> Either String GitInfo
forall a b. b -> Either a b
tGitInfoCwdTry Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
ghcversion
  where
    unreleased :: Text
unreleased =
      if [Int] -> Int
forall a. HasCallStack => [a] -> a
last (Version -> [Int]
versionBranch Version
version) Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0
        then Text
" (prerelease - include info below when reporting bugs)"
        else Text
forall a. Monoid a => a
mempty
    gitversion :: Either a GitInfo -> Text
gitversion (Left a
_) =
      case Maybe String
commitIdFromFile of
        Maybe String
Nothing -> Text
""
        Just String
commit -> Text
"\ngit: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack String
commit
    gitversion (Right GitInfo
gi) =
      [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
        [ Text
"\n",
          Text
"git: ",
          Text
branch,
          String -> Text
T.pack (Int -> String -> String
forall a. Int -> [a] -> [a]
take Int
7 (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ GitInfo -> String
giHash GitInfo
gi),
          Text
" (",
          String -> Text
T.pack (GitInfo -> String
giCommitDate GitInfo
gi),
          Text
")",
          Text
dirty,
          Text
"\n"
        ]
      where
        branch :: Text
branch
          | GitInfo -> String
giBranch GitInfo
gi String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"master" = Text
""
          | Bool
otherwise = String -> Text
T.pack (GitInfo -> String
giBranch GitInfo
gi) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" @ "
        dirty :: Text
dirty = if GitInfo -> Bool
giDirty GitInfo
gi then Text
" [modified]" else Text
""

    ghcversion :: Text
ghcversion = Text
"Compiled with GHC " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Int -> Text
forall a. Show a => a -> Text
showText Int
a Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"." Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Int -> Text
forall a. Show a => a -> Text
showText Int
b Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"." Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Int -> Text
forall a. Show a => a -> Text
showText Int
c Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
".\n"
      where
        a, b, c :: Int
        a :: Int
a = __GLASGOW_HASKELL__ `div` 100
        b :: Int
b = __GLASGOW_HASKELL__ `mod` 100
        c :: Int
c = __GLASGOW_HASKELL_PATCHLEVEL1__

commitIdFromFile :: Maybe String
commitIdFromFile :: Maybe String
commitIdFromFile = String -> String
trim (String -> String)
-> (ByteString -> String) -> ByteString -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> String
BS.unpack (ByteString -> String) -> Maybe ByteString -> Maybe String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> $(embedFileIfExists "./commit-id")