module Hix.CabalParsec where

import Distribution.Parsec (Parsec, eitherParsec)
import Exon (exon)
import Type.Reflection (typeRep)

import Hix.Data.Monad (M)
import Hix.Monad (eitherClient)

eitherParsecFor ::
  Parsec b =>
  ToString a =>
  String ->
  a ->
  Either String b
eitherParsecFor :: forall b a.
(Parsec b, ToString a) =>
String -> a -> Either String b
eitherParsecFor String
desc a
spec =
  (String -> String) -> Either String b -> Either String b
forall a b c. (a -> b) -> Either a c -> Either b c
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first String -> String
errorMessage (String -> Either String b
forall a. Parsec a => String -> Either String a
eitherParsec String
s)
  where
    errorMessage :: String -> String
errorMessage String
err = String -> String
forall a. HasCallStack => String -> a
error [exon|parsing #{desc} "#{s}": #{err}|]
    s :: String
s = a -> String
forall a. ToString a => a -> String
toString a
spec

unsafeParsecFor ::
  Parsec b =>
  ToString a =>
  String ->
  a ->
  b
unsafeParsecFor :: forall b a. (Parsec b, ToString a) => String -> a -> b
unsafeParsecFor String
desc a
spec =
  (String -> b) -> (b -> b) -> Either String b -> b
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either String -> b
forall a. HasCallStack => String -> a
error b -> b
forall a. a -> a
id (String -> a -> Either String b
forall b a.
(Parsec b, ToString a) =>
String -> a -> Either String b
eitherParsecFor String
desc a
spec)

unsafeParsec ::
   a b .
  Parsec b =>
  Typeable b =>
  ToString a =>
  a ->
  b
unsafeParsec :: forall a b. (Parsec b, Typeable b, ToString a) => a -> b
unsafeParsec =
  String -> a -> b
forall b a. (Parsec b, ToString a) => String -> a -> b
unsafeParsecFor (TypeRep b -> String
forall b a. (Show a, IsString b) => a -> b
show (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @b))

parsecM ::
  Parsec b =>
  ToString a =>
  String ->
  a ->
  M b
parsecM :: forall b a. (Parsec b, ToString a) => String -> a -> M b
parsecM String
desc a
spec =
  Either Text b -> M b
forall a. Either Text a -> M a
eitherClient ((String -> Text) -> Either String b -> Either Text b
forall a b c. (a -> b) -> Either a c -> Either b c
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first String -> Text
forall a. ToText a => a -> Text
toText (String -> a -> Either String b
forall b a.
(Parsec b, ToString a) =>
String -> a -> Either String b
eitherParsecFor String
desc a
spec))