{-# LANGUAGE RankNTypes, ViewPatterns #-}
module Test.Tasty.Patterns.Eval (Path, eval, withFields, asB) where

import Prelude hiding (Ordering(..))
import Control.Monad ((<=<))
import Control.Monad.Trans.Class (lift)
import Control.Monad.Trans.Reader (ReaderT, runReaderT, ask)
import qualified Data.Sequence as Seq
import Data.Foldable
import Data.List (findIndex, intercalate, isInfixOf, isPrefixOf, tails)
import Data.Maybe
import Data.Char
import Test.Tasty.Patterns.Types
#if !MIN_VERSION_base(4,9,0)
import Control.Applicative
import Data.Traversable
#endif

type Path = Seq.Seq String

data Value
  = VN !Int
  | VS !Bool String
    -- ^ The 'Bool' is 'True' if the source of the string
    -- allows it to be numeric
  | Uninitialized
  deriving Int -> Value -> ShowS
[Value] -> ShowS
Value -> String
(Int -> Value -> ShowS)
-> (Value -> String) -> ([Value] -> ShowS) -> Show Value
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Value] -> ShowS
$cshowList :: [Value] -> ShowS
show :: Value -> String
$cshow :: Value -> String
showsPrec :: Int -> Value -> ShowS
$cshowsPrec :: Int -> Value -> ShowS
Show

type M = ReaderT Path (Either String)

throwError :: String -> M a
throwError :: String -> M a
throwError String
s = Either String a -> M a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (Either String a -> M a) -> Either String a -> M a
forall a b. (a -> b) -> a -> b
$ String -> Either String a
forall a b. a -> Either a b
Left String
s

asS :: Value -> M String
asS :: Value -> M String
asS Value
v = String -> M String
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> M String) -> String -> M String
forall a b. (a -> b) -> a -> b
$
  case Value
v of
    VN Int
n -> Int -> String
forall a. Show a => a -> String
show Int
n
    VS Bool
_ String
s -> String
s
    Value
Uninitialized -> String
""

-- readMaybe was not in base-4.3 yet
parseN :: String -> Maybe Int
parseN :: String -> Maybe Int
parseN String
s =
  case String -> [(Int, String)]
forall a. Read a => String -> a
read String
s of
    [(Int
n, String
"")] -> Int -> Maybe Int
forall a. a -> Maybe a
Just Int
n
    [(Int, String)]
_ -> Maybe Int
forall a. Maybe a
Nothing

asN :: Value -> M Int
asN :: Value -> M Int
asN Value
v =
  case Value
v of
    VN Int
n -> Int -> M Int
forall (m :: * -> *) a. Monad m => a -> m a
return Int
n
    VS Bool
True String
s ->
      case String -> Maybe Int
parseN String
s of
        Just Int
n -> Int -> M Int
forall (m :: * -> *) a. Monad m => a -> m a
return Int
n
        Maybe Int
Nothing -> String -> M Int
forall a. String -> M a
throwError (String -> M Int) -> String -> M Int
forall a b. (a -> b) -> a -> b
$ String
"Not a number: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ ShowS
forall a. Show a => a -> String
show String
s
    VS Bool
False String
s -> String -> M Int
forall a. String -> M a
throwError (String -> M Int) -> String -> M Int
forall a b. (a -> b) -> a -> b
$ String
"String is not numeric: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ ShowS
forall a. Show a => a -> String
show String
s
    Value
Uninitialized -> Int -> M Int
forall (m :: * -> *) a. Monad m => a -> m a
return Int
0

isN :: Value -> Bool
isN :: Value -> Bool
isN Value
v =
  case Value
v of
    VN Int
_ -> Bool
True
    Value
_ -> Bool
False

isNumeric :: Value -> Bool
isNumeric :: Value -> Bool
isNumeric Value
v =
  case Value
v of
    VS Bool
b String
s -> Bool
b Bool -> Bool -> Bool
&& Maybe Int -> Bool
forall a. Maybe a -> Bool
isJust (String -> Maybe Int
parseN String
s)
    Value
_ -> Bool
True

asB :: Value -> M Bool
asB :: Value -> M Bool
asB Value
v = Bool -> M Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> M Bool) -> Bool -> M Bool
forall a b. (a -> b) -> a -> b
$
  case Value
v of
    VN Int
0 -> Bool
False
    VS Bool
_ String
"" -> Bool
False
    Value
_ -> Bool
True

fromB :: Bool -> Value
fromB :: Bool -> Value
fromB = Int -> Value
VN (Int -> Value) -> (Bool -> Int) -> Bool -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> Int
forall a. Enum a => a -> Int
fromEnum

-- | Evaluate an awk expression
eval :: Expr -> M Value
eval :: Expr -> M Value
eval Expr
e0 =
  case Expr
e0 of
    IntLit Int
n -> Value -> M Value
forall (m :: * -> *) a. Monad m => a -> m a
return (Value -> M Value) -> Value -> M Value
forall a b. (a -> b) -> a -> b
$ Int -> Value
VN Int
n
    StringLit String
s -> Value -> M Value
forall (m :: * -> *) a. Monad m => a -> m a
return (Value -> M Value) -> Value -> M Value
forall a b. (a -> b) -> a -> b
$ Bool -> String -> Value
VS Bool
False String
s
    Expr
NF -> Int -> Value
VN (Int -> Value) -> (Seq String -> Int) -> Seq String -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Int -> Int
forall a. Num a => a -> a -> a
subtract Int
1 (Int -> Int) -> (Seq String -> Int) -> Seq String -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Seq String -> Int
forall a. Seq a -> Int
Seq.length (Seq String -> Value)
-> ReaderT (Seq String) (Either String) (Seq String) -> M Value
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReaderT (Seq String) (Either String) (Seq String)
forall (m :: * -> *) r. Monad m => ReaderT r m r
ask
    Add Expr
e1 Expr
e2 -> (Int -> Int -> Int) -> Expr -> Expr -> M Value
binNumOp Int -> Int -> Int
forall a. Num a => a -> a -> a
(+) Expr
e1 Expr
e2
    Sub Expr
e1 Expr
e2 -> (Int -> Int -> Int) -> Expr -> Expr -> M Value
binNumOp (-) Expr
e1 Expr
e2
    Neg Expr
e1 -> Int -> Value
VN (Int -> Value) -> (Int -> Int) -> Int -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Int
forall a. Num a => a -> a
negate (Int -> Value) -> M Int -> M Value
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Value -> M Int
asN (Value -> M Int) -> M Value -> M Int
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Expr -> M Value
eval Expr
e1)
    Not Expr
e1 -> Bool -> Value
fromB (Bool -> Value) -> (Bool -> Bool) -> Bool -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> Bool
not (Bool -> Value) -> M Bool -> M Value
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Value -> M Bool
asB (Value -> M Bool) -> M Value -> M Bool
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Expr -> M Value
eval Expr
e1)
    And Expr
e1 Expr
e2 -> (Bool -> Bool -> Bool) -> Expr -> Expr -> M Value
binLglOp Bool -> Bool -> Bool
(&&) Expr
e1 Expr
e2
    Or Expr
e1 Expr
e2  -> (Bool -> Bool -> Bool) -> Expr -> Expr -> M Value
binLglOp Bool -> Bool -> Bool
(||) Expr
e1 Expr
e2
    LT Expr
e1 Expr
e2 -> (forall a. Ord a => a -> a -> Bool) -> Expr -> Expr -> M Value
binCmpOp forall a. Ord a => a -> a -> Bool
(<)  Expr
e1 Expr
e2
    LE Expr
e1 Expr
e2 -> (forall a. Ord a => a -> a -> Bool) -> Expr -> Expr -> M Value
binCmpOp forall a. Ord a => a -> a -> Bool
(<=) Expr
e1 Expr
e2
    GT Expr
e1 Expr
e2 -> (forall a. Ord a => a -> a -> Bool) -> Expr -> Expr -> M Value
binCmpOp forall a. Ord a => a -> a -> Bool
(>)  Expr
e1 Expr
e2
    GE Expr
e1 Expr
e2 -> (forall a. Ord a => a -> a -> Bool) -> Expr -> Expr -> M Value
binCmpOp forall a. Ord a => a -> a -> Bool
(>=) Expr
e1 Expr
e2
    EQ Expr
e1 Expr
e2 -> (forall a. Ord a => a -> a -> Bool) -> Expr -> Expr -> M Value
binCmpOp forall a. Eq a => a -> a -> Bool
forall a. Ord a => a -> a -> Bool
(==) Expr
e1 Expr
e2
    NE Expr
e1 Expr
e2 -> (forall a. Ord a => a -> a -> Bool) -> Expr -> Expr -> M Value
binCmpOp forall a. Eq a => a -> a -> Bool
forall a. Ord a => a -> a -> Bool
(/=) Expr
e1 Expr
e2
    Concat Expr
e1 Expr
e2 -> Bool -> String -> Value
VS Bool
False (String -> Value) -> M String -> M Value
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (String -> ShowS
forall a. [a] -> [a] -> [a]
(++) (String -> ShowS)
-> M String -> ReaderT (Seq String) (Either String) ShowS
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Value -> M String
asS (Value -> M String) -> M Value -> M String
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Expr -> M Value
eval Expr
e1) ReaderT (Seq String) (Either String) ShowS -> M String -> M String
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Value -> M String
asS (Value -> M String) -> M Value -> M String
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Expr -> M Value
eval Expr
e2))
    If Expr
cond Expr
e1 Expr
e2 -> do
      Bool
condV <- Value -> M Bool
asB (Value -> M Bool) -> M Value -> M Bool
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Expr -> M Value
eval Expr
cond
      if Bool
condV then Expr -> M Value
eval Expr
e1 else Expr -> M Value
eval Expr
e2
    Field Expr
e1 -> do
      Int
n <- Value -> M Int
asN (Value -> M Int) -> M Value -> M Int
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Expr -> M Value
eval Expr
e1
      Seq String
fields <- ReaderT (Seq String) (Either String) (Seq String)
forall (m :: * -> *) r. Monad m => ReaderT r m r
ask
      Value -> M Value
forall (m :: * -> *) a. Monad m => a -> m a
return (Value -> M Value) -> Value -> M Value
forall a b. (a -> b) -> a -> b
$ if Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Seq String -> Int
forall a. Seq a -> Int
Seq.length Seq String
fields Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
        then Value
Uninitialized
        else Bool -> String -> Value
VS Bool
True (String -> Value) -> String -> Value
forall a b. (a -> b) -> a -> b
$ Seq String -> Int -> String
forall a. Seq a -> Int -> a
Seq.index Seq String
fields Int
n
    ERE String
pat -> do
      String
str <- Seq String -> Int -> String
forall a. Seq a -> Int -> a
Seq.index (Seq String -> Int -> String)
-> ReaderT (Seq String) (Either String) (Seq String)
-> ReaderT (Seq String) (Either String) (Int -> String)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReaderT (Seq String) (Either String) (Seq String)
forall (m :: * -> *) r. Monad m => ReaderT r m r
ask ReaderT (Seq String) (Either String) (Int -> String)
-> M Int -> M String
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Int -> M Int
forall (f :: * -> *) a. Applicative f => a -> f a
pure Int
0
      Value -> M Value
forall (m :: * -> *) a. Monad m => a -> m a
return (Value -> M Value) -> (Bool -> Value) -> Bool -> M Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> Value
fromB (Bool -> M Value) -> Bool -> M Value
forall a b. (a -> b) -> a -> b
$ String -> String -> Bool
match String
pat String
str
    Match Expr
e1 String
pat -> do
      String
str <- Value -> M String
asS (Value -> M String) -> M Value -> M String
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Expr -> M Value
eval Expr
e1
      Value -> M Value
forall (m :: * -> *) a. Monad m => a -> m a
return (Value -> M Value) -> (Bool -> Value) -> Bool -> M Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> Value
fromB (Bool -> M Value) -> Bool -> M Value
forall a b. (a -> b) -> a -> b
$ String -> String -> Bool
match String
pat String
str
    NoMatch Expr
e1 String
pat -> do
      String
str <- Value -> M String
asS (Value -> M String) -> M Value -> M String
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Expr -> M Value
eval Expr
e1
      Value -> M Value
forall (m :: * -> *) a. Monad m => a -> m a
return (Value -> M Value) -> (Bool -> Value) -> Bool -> M Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> Value
fromB (Bool -> Value) -> (Bool -> Bool) -> Bool -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> Bool
not (Bool -> M Value) -> Bool -> M Value
forall a b. (a -> b) -> a -> b
$ String -> String -> Bool
match String
pat String
str
    ToUpperFn Expr
e1 ->
      Bool -> String -> Value
VS Bool
True (String -> Value) -> ShowS -> String -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Char) -> ShowS
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toUpper (String -> Value) -> M String -> M Value
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Value -> M String
asS (Value -> M String) -> M Value -> M String
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Expr -> M Value
eval Expr
e1)
    ToLowerFn Expr
e1 ->
      Bool -> String -> Value
VS Bool
True (String -> Value) -> ShowS -> String -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Char) -> ShowS
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower (String -> Value) -> M String -> M Value
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Value -> M String
asS (Value -> M String) -> M Value -> M String
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Expr -> M Value
eval Expr
e1)
    SubstrFn Expr
e1 Expr
e2 Maybe Expr
mb_e3 -> do
      String
s <- Value -> M String
asS (Value -> M String) -> M Value -> M String
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Expr -> M Value
eval Expr
e1
      Int
m <- Value -> M Int
asN (Value -> M Int) -> M Value -> M Int
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Expr -> M Value
eval Expr
e2
      Maybe Int
mb_n <- (Expr -> M Int)
-> Maybe Expr -> ReaderT (Seq String) (Either String) (Maybe Int)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse (Value -> M Int
asN (Value -> M Int) -> (Expr -> M Value) -> Expr -> M Int
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< Expr -> M Value
eval) Maybe Expr
mb_e3
      Value -> M Value
forall (m :: * -> *) a. Monad m => a -> m a
return (Value -> M Value) -> Value -> M Value
forall a b. (a -> b) -> a -> b
$ Bool -> String -> Value
VS Bool
True (String -> Value) -> String -> Value
forall a b. (a -> b) -> a -> b
$
        ShowS -> (Int -> ShowS) -> Maybe Int -> ShowS
forall b a. b -> (a -> b) -> Maybe a -> b
maybe ShowS
forall a. a -> a
id Int -> ShowS
forall a. Int -> [a] -> [a]
take Maybe Int
mb_n ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> ShowS
forall a. Int -> [a] -> [a]
drop (Int
mInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$ String
s
    LengthFn (Expr -> Maybe Expr -> Expr
forall a. a -> Maybe a -> a
fromMaybe (Expr -> Expr
Field (Int -> Expr
IntLit Int
0)) ->  Expr
e1) ->
      Int -> Value
VN (Int -> Value) -> (String -> Int) -> String -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (String -> Value) -> M String -> M Value
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Value -> M String
asS (Value -> M String) -> M Value -> M String
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Expr -> M Value
eval Expr
e1)
    MatchFn Expr
e1 String
pat -> do
      String
s <- Value -> M String
asS (Value -> M String) -> M Value -> M String
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Expr -> M Value
eval Expr
e1
      Value -> M Value
forall (m :: * -> *) a. Monad m => a -> m a
return (Value -> M Value) -> ([String] -> Value) -> [String] -> M Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Value
VN (Int -> Value) -> ([String] -> Int) -> [String] -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> (Int -> Int) -> Maybe Int -> Int
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Int
0 (Int -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) (Maybe Int -> Int) -> ([String] -> Maybe Int) -> [String] -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> Bool) -> [String] -> Maybe Int
forall a. (a -> Bool) -> [a] -> Maybe Int
findIndex (String
pat String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf`) ([String] -> M Value) -> [String] -> M Value
forall a b. (a -> b) -> a -> b
$ String -> [String]
forall a. [a] -> [[a]]
tails String
s

  where
    binNumOp :: (Int -> Int -> Int) -> Expr -> Expr -> M Value
binNumOp Int -> Int -> Int
op Expr
e1 Expr
e2 = Int -> Value
VN (Int -> Value) -> M Int -> M Value
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Int -> Int -> Int
op (Int -> Int -> Int)
-> M Int -> ReaderT (Seq String) (Either String) (Int -> Int)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Value -> M Int
asN (Value -> M Int) -> M Value -> M Int
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Expr -> M Value
eval Expr
e1) ReaderT (Seq String) (Either String) (Int -> Int) -> M Int -> M Int
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Value -> M Int
asN (Value -> M Int) -> M Value -> M Int
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Expr -> M Value
eval Expr
e2))
    binLglOp :: (Bool -> Bool -> Bool) -> Expr -> Expr -> M Value
binLglOp Bool -> Bool -> Bool
op Expr
e1 Expr
e2 = Bool -> Value
fromB (Bool -> Value) -> M Bool -> M Value
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Bool -> Bool -> Bool
op (Bool -> Bool -> Bool)
-> M Bool -> ReaderT (Seq String) (Either String) (Bool -> Bool)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Value -> M Bool
asB (Value -> M Bool) -> M Value -> M Bool
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Expr -> M Value
eval Expr
e1) ReaderT (Seq String) (Either String) (Bool -> Bool)
-> M Bool -> M Bool
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Value -> M Bool
asB (Value -> M Bool) -> M Value -> M Bool
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Expr -> M Value
eval Expr
e2))
    binCmpOp :: (forall a . Ord a => a -> a -> Bool) -> Expr -> Expr -> M Value
    binCmpOp :: (forall a. Ord a => a -> a -> Bool) -> Expr -> Expr -> M Value
binCmpOp forall a. Ord a => a -> a -> Bool
op Expr
e1 Expr
e2 = do
      Value
v1 <- Expr -> M Value
eval Expr
e1
      Value
v2 <- Expr -> M Value
eval Expr
e2
      let
        compareAsNumbers :: Bool
compareAsNumbers =
          Value -> Bool
isN Value
v1 Bool -> Bool -> Bool
&& Value -> Bool
isNumeric Value
v2 Bool -> Bool -> Bool
||
          Value -> Bool
isN Value
v2 Bool -> Bool -> Bool
&& Value -> Bool
isNumeric Value
v1
      if Bool
compareAsNumbers
        then Bool -> Value
fromB (Bool -> Value) -> M Bool -> M Value
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
op (Int -> Int -> Bool)
-> M Int -> ReaderT (Seq String) (Either String) (Int -> Bool)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> M Int
asN Value
v1 ReaderT (Seq String) (Either String) (Int -> Bool)
-> M Int -> M Bool
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Value -> M Int
asN Value
v2)
        else Bool -> Value
fromB (Bool -> Value) -> M Bool -> M Value
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (String -> String -> Bool
forall a. Ord a => a -> a -> Bool
op (String -> String -> Bool)
-> M String
-> ReaderT (Seq String) (Either String) (String -> Bool)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> M String
asS Value
v1 ReaderT (Seq String) (Either String) (String -> Bool)
-> M String -> M Bool
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Value -> M String
asS Value
v2)

match
  :: String -- ^ pattern
  -> String -- ^ string
  -> Bool
match :: String -> String -> Bool
match String
pat String
str = String
pat String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isInfixOf` String
str

-- | Run the 'M' monad with a given list of fields
--
-- The field list should not include @$0@; it's calculated automatically.
withFields :: Seq.Seq String -> M a -> Either String a
withFields :: Seq String -> M a -> Either String a
withFields Seq String
fields M a
a = M a -> Seq String -> Either String a
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT M a
a (String
whole String -> Seq String -> Seq String
forall a. a -> Seq a -> Seq a
Seq.<| Seq String
fields)
  where whole :: String
whole = String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
"." ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ Seq String -> [String]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList Seq String
fields