{-#LANGUAGE FlexibleContexts #-}
{-#LANGUAGE FlexibleInstances #-}
{-#LANGUAGE OverloadedStrings #-}
{-#LANGUAGE TupleSections #-}
{-#LANGUAGE TypeSynonymInstances #-}
{-#LANGUAGE MultiParamTypeClasses #-}
{-#LANGUAGE ScopedTypeVariables #-}
module Text.Ginger.Run.FuncUtils
where

import Prelude ( (.), ($), (==), (/=)
               , (>), (<), (>=), (<=)
               , (+), (-), (*), (/), div, (**), (^)
               , (||), (&&)
               , (++)
               , Show, show
               , undefined, otherwise
               , Maybe (..)
               , Bool (..)
               , Int, Integer, String
               , fromIntegral, floor, round
               , not
               , show
               , uncurry
               , seq
               , fst, snd
               , maybe
               , Either (..)
               , id
               )
import qualified Prelude
import Data.Maybe (fromMaybe, isJust)
import qualified Data.List as List
import Text.Ginger.AST
import Text.Ginger.Html
import Text.Ginger.GVal
import Text.Ginger.Run.Type
import Text.Printf
import Text.PrintfA
import Data.Scientific (formatScientific)

import Data.Text (Text)
import Data.String (fromString)
import qualified Data.Text as Text
import qualified Data.ByteString.UTF8 as UTF8
import Control.Monad
import Control.Monad.Identity
import Control.Monad.Writer
import Control.Monad.Reader
import Control.Monad.State
import Control.Applicative
import qualified Data.HashMap.Strict as HashMap
import Data.HashMap.Strict (HashMap)
import Data.Scientific (Scientific)
import Data.Scientific as Scientific
import Data.Default (def)
import Safe (readMay, lastDef, headMay)
import Network.HTTP.Types (urlEncode)
import Debug.Trace (trace)
import Data.Maybe (isNothing)
import Data.List (lookup, zipWith, unzip)

unaryFunc :: forall m h p. (Monad m) => (GVal (Run p m h) -> GVal (Run p m h)) -> Function (Run p m h)
unaryFunc :: (GVal (Run p m h) -> GVal (Run p m h)) -> Function (Run p m h)
unaryFunc GVal (Run p m h) -> GVal (Run p m h)
f [] = do
    RuntimeError p -> Run p m h ()
forall (m :: * -> *) p h. Monad m => RuntimeError p -> Run p m h ()
warn (RuntimeError p -> Run p m h ()) -> RuntimeError p -> Run p m h ()
forall a b. (a -> b) -> a -> b
$ Maybe Text -> Text -> RuntimeError p
forall p. Maybe Text -> Text -> RuntimeError p
ArgumentsError Maybe Text
forall a. Maybe a
Nothing Text
"expected exactly one argument (zero given)"
    GVal (Run p m h) -> Run p m h (GVal (Run p m h))
forall (m :: * -> *) a. Monad m => a -> m a
return GVal (Run p m h)
forall a. Default a => a
def
unaryFunc GVal (Run p m h) -> GVal (Run p m h)
f ((Maybe Text
_, GVal (Run p m h)
x):[]) =
    GVal (Run p m h) -> Run p m h (GVal (Run p m h))
forall (m :: * -> *) a. Monad m => a -> m a
return (GVal (Run p m h) -> GVal (Run p m h)
f GVal (Run p m h)
x)
unaryFunc GVal (Run p m h) -> GVal (Run p m h)
f ((Maybe Text
_, GVal (Run p m h)
x):[(Maybe Text, GVal (Run p m h))]
_) = do
    RuntimeError p -> Run p m h ()
forall (m :: * -> *) p h. Monad m => RuntimeError p -> Run p m h ()
warn (RuntimeError p -> Run p m h ()) -> RuntimeError p -> Run p m h ()
forall a b. (a -> b) -> a -> b
$ Maybe Text -> Text -> RuntimeError p
forall p. Maybe Text -> Text -> RuntimeError p
ArgumentsError Maybe Text
forall a. Maybe a
Nothing Text
"expected exactly one argument (more given)"
    GVal (Run p m h) -> Run p m h (GVal (Run p m h))
forall (m :: * -> *) a. Monad m => a -> m a
return (GVal (Run p m h) -> GVal (Run p m h)
f GVal (Run p m h)
x)

binaryFunc :: forall m h p. (Monad m) => (GVal (Run p m h) -> GVal (Run p m h) -> GVal (Run p m h)) -> Function (Run p m h)
binaryFunc :: (GVal (Run p m h) -> GVal (Run p m h) -> GVal (Run p m h))
-> Function (Run p m h)
binaryFunc GVal (Run p m h) -> GVal (Run p m h) -> GVal (Run p m h)
f [] = do
    RuntimeError p -> Run p m h ()
forall (m :: * -> *) p h. Monad m => RuntimeError p -> Run p m h ()
warn (RuntimeError p -> Run p m h ()) -> RuntimeError p -> Run p m h ()
forall a b. (a -> b) -> a -> b
$ Maybe Text -> Text -> RuntimeError p
forall p. Maybe Text -> Text -> RuntimeError p
ArgumentsError Maybe Text
forall a. Maybe a
Nothing Text
"expected exactly two arguments (zero given)"
    GVal (Run p m h) -> Run p m h (GVal (Run p m h))
forall (m :: * -> *) a. Monad m => a -> m a
return GVal (Run p m h)
forall a. Default a => a
def
binaryFunc GVal (Run p m h) -> GVal (Run p m h) -> GVal (Run p m h)
f ((Maybe Text, GVal (Run p m h))
_:[]) = do
    RuntimeError p -> Run p m h ()
forall (m :: * -> *) p h. Monad m => RuntimeError p -> Run p m h ()
warn (RuntimeError p -> Run p m h ()) -> RuntimeError p -> Run p m h ()
forall a b. (a -> b) -> a -> b
$ Maybe Text -> Text -> RuntimeError p
forall p. Maybe Text -> Text -> RuntimeError p
ArgumentsError Maybe Text
forall a. Maybe a
Nothing Text
"expected exactly two arguments (one given)"
    GVal (Run p m h) -> Run p m h (GVal (Run p m h))
forall (m :: * -> *) a. Monad m => a -> m a
return GVal (Run p m h)
forall a. Default a => a
def
binaryFunc GVal (Run p m h) -> GVal (Run p m h) -> GVal (Run p m h)
f ((Maybe Text
_, GVal (Run p m h)
x):(Maybe Text
_, GVal (Run p m h)
y):[]) =
    GVal (Run p m h) -> Run p m h (GVal (Run p m h))
forall (m :: * -> *) a. Monad m => a -> m a
return (GVal (Run p m h) -> GVal (Run p m h) -> GVal (Run p m h)
f GVal (Run p m h)
x GVal (Run p m h)
y)
binaryFunc GVal (Run p m h) -> GVal (Run p m h) -> GVal (Run p m h)
f ((Maybe Text
_, GVal (Run p m h)
x):(Maybe Text
_, GVal (Run p m h)
y):[(Maybe Text, GVal (Run p m h))]
_) = do
    RuntimeError p -> Run p m h ()
forall (m :: * -> *) p h. Monad m => RuntimeError p -> Run p m h ()
warn (RuntimeError p -> Run p m h ()) -> RuntimeError p -> Run p m h ()
forall a b. (a -> b) -> a -> b
$ Maybe Text -> Text -> RuntimeError p
forall p. Maybe Text -> Text -> RuntimeError p
ArgumentsError Maybe Text
forall a. Maybe a
Nothing Text
"expected exactly two arguments (more given)"
    GVal (Run p m h) -> Run p m h (GVal (Run p m h))
forall (m :: * -> *) a. Monad m => a -> m a
return (GVal (Run p m h) -> GVal (Run p m h) -> GVal (Run p m h)
f GVal (Run p m h)
x GVal (Run p m h)
y)

ignoreArgNames :: ([a] -> b) -> ([(c, a)] -> b)
ignoreArgNames :: ([a] -> b) -> [(c, a)] -> b
ignoreArgNames [a] -> b
f [(c, a)]
args = [a] -> b
f (((c, a) -> a) -> [(c, a)] -> [a]
forall a b. (a -> b) -> [a] -> [b]
Prelude.map (c, a) -> a
forall a b. (a, b) -> b
snd [(c, a)]
args)

variadicNumericFunc :: Monad m => Scientific -> ([Scientific] -> Scientific) -> [(Maybe Text, GVal (Run p m h))] -> Run p m h (GVal (Run p m h))
variadicNumericFunc :: Scientific
-> ([Scientific] -> Scientific)
-> [(Maybe Text, GVal (Run p m h))]
-> Run p m h (GVal (Run p m h))
variadicNumericFunc Scientific
zero [Scientific] -> Scientific
f [(Maybe Text, GVal (Run p m h))]
args =
    GVal (Run p m h) -> Run p m h (GVal (Run p m h))
forall (m :: * -> *) a. Monad m => a -> m a
return (GVal (Run p m h) -> Run p m h (GVal (Run p m h)))
-> ([Scientific] -> GVal (Run p m h))
-> [Scientific]
-> Run p m h (GVal (Run p m h))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Scientific -> GVal (Run p m h)
forall (m :: * -> *) a. ToGVal m a => a -> GVal m
toGVal (Scientific -> GVal (Run p m h))
-> ([Scientific] -> Scientific) -> [Scientific] -> GVal (Run p m h)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Scientific] -> Scientific
f ([Scientific] -> Run p m h (GVal (Run p m h)))
-> [Scientific] -> Run p m h (GVal (Run p m h))
forall a b. (a -> b) -> a -> b
$ [Scientific]
args'
    where
        args' :: [Scientific]
        args' :: [Scientific]
args' = ((Maybe Text, GVal (Run p m h)) -> Scientific)
-> [(Maybe Text, GVal (Run p m h))] -> [Scientific]
forall a b. (a -> b) -> [a] -> [b]
Prelude.map (Scientific -> Maybe Scientific -> Scientific
forall a. a -> Maybe a -> a
fromMaybe Scientific
zero (Maybe Scientific -> Scientific)
-> ((Maybe Text, GVal (Run p m h)) -> Maybe Scientific)
-> (Maybe Text, GVal (Run p m h))
-> Scientific
forall b c a. (b -> c) -> (a -> b) -> a -> c
. GVal (Run p m h) -> Maybe Scientific
forall (m :: * -> *). GVal m -> Maybe Scientific
asNumber (GVal (Run p m h) -> Maybe Scientific)
-> ((Maybe Text, GVal (Run p m h)) -> GVal (Run p m h))
-> (Maybe Text, GVal (Run p m h))
-> Maybe Scientific
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Maybe Text, GVal (Run p m h)) -> GVal (Run p m h)
forall a b. (a, b) -> b
snd) [(Maybe Text, GVal (Run p m h))]
args

unaryNumericFunc :: Monad m => Scientific -> (Scientific -> Scientific) -> [(Maybe Text, GVal (Run p m h))] -> Run p m h (GVal (Run p m h))
unaryNumericFunc :: Scientific
-> (Scientific -> Scientific)
-> [(Maybe Text, GVal (Run p m h))]
-> Run p m h (GVal (Run p m h))
unaryNumericFunc Scientific
zero Scientific -> Scientific
f [(Maybe Text, GVal (Run p m h))]
args =
    GVal (Run p m h) -> Run p m h (GVal (Run p m h))
forall (m :: * -> *) a. Monad m => a -> m a
return (GVal (Run p m h) -> Run p m h (GVal (Run p m h)))
-> (Scientific -> GVal (Run p m h))
-> Scientific
-> Run p m h (GVal (Run p m h))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Scientific -> GVal (Run p m h)
forall (m :: * -> *) a. ToGVal m a => a -> GVal m
toGVal (Scientific -> GVal (Run p m h))
-> (Scientific -> Scientific) -> Scientific -> GVal (Run p m h)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Scientific -> Scientific
f (Scientific -> Run p m h (GVal (Run p m h)))
-> Scientific -> Run p m h (GVal (Run p m h))
forall a b. (a -> b) -> a -> b
$ Scientific
args'
    where
        args' :: Scientific
        args' :: Scientific
args' = case [(Maybe Text, GVal (Run p m h))]
args of
                    [] -> Scientific
0
                    ((Maybe Text, GVal (Run p m h))
arg:[(Maybe Text, GVal (Run p m h))]
_) -> Scientific -> Maybe Scientific -> Scientific
forall a. a -> Maybe a -> a
fromMaybe Scientific
zero (Maybe Scientific -> Scientific)
-> ((Maybe Text, GVal (Run p m h)) -> Maybe Scientific)
-> (Maybe Text, GVal (Run p m h))
-> Scientific
forall b c a. (b -> c) -> (a -> b) -> a -> c
. GVal (Run p m h) -> Maybe Scientific
forall (m :: * -> *). GVal m -> Maybe Scientific
asNumber (GVal (Run p m h) -> Maybe Scientific)
-> ((Maybe Text, GVal (Run p m h)) -> GVal (Run p m h))
-> (Maybe Text, GVal (Run p m h))
-> Maybe Scientific
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Maybe Text, GVal (Run p m h)) -> GVal (Run p m h)
forall a b. (a, b) -> b
snd ((Maybe Text, GVal (Run p m h)) -> Scientific)
-> (Maybe Text, GVal (Run p m h)) -> Scientific
forall a b. (a -> b) -> a -> b
$ (Maybe Text, GVal (Run p m h))
arg

variadicStringFunc :: Monad m => ([Text] -> Text) -> [(Maybe Text, GVal (Run p m h))] -> Run p m h (GVal (Run p m h))
variadicStringFunc :: ([Text] -> Text)
-> [(Maybe Text, GVal (Run p m h))] -> Run p m h (GVal (Run p m h))
variadicStringFunc [Text] -> Text
f [(Maybe Text, GVal (Run p m h))]
args =
    GVal (Run p m h) -> Run p m h (GVal (Run p m h))
forall (m :: * -> *) a. Monad m => a -> m a
return (GVal (Run p m h) -> Run p m h (GVal (Run p m h)))
-> ([Text] -> GVal (Run p m h))
-> [Text]
-> Run p m h (GVal (Run p m h))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> GVal (Run p m h)
forall (m :: * -> *) a. ToGVal m a => a -> GVal m
toGVal (Text -> GVal (Run p m h))
-> ([Text] -> Text) -> [Text] -> GVal (Run p m h)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Text] -> Text
f ([Text] -> Run p m h (GVal (Run p m h)))
-> [Text] -> Run p m h (GVal (Run p m h))
forall a b. (a -> b) -> a -> b
$ [Text]
args'
    where
        args' :: [Text]
        args' :: [Text]
args' = ((Maybe Text, GVal (Run p m h)) -> Text)
-> [(Maybe Text, GVal (Run p m h))] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
Prelude.map (GVal (Run p m h) -> Text
forall (m :: * -> *). GVal m -> Text
asText (GVal (Run p m h) -> Text)
-> ((Maybe Text, GVal (Run p m h)) -> GVal (Run p m h))
-> (Maybe Text, GVal (Run p m h))
-> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Maybe Text, GVal (Run p m h)) -> GVal (Run p m h)
forall a b. (a, b) -> b
snd) [(Maybe Text, GVal (Run p m h))]
args

-- | Match args according to a given arg spec, Python style.
-- The return value is a triple of @(matched, args, kwargs, unmatchedNames)@,
-- where @matches@ is a hash map of named captured arguments, args is a list of
-- remaining unmatched positional arguments, kwargs is a list of remaining
-- unmatched named arguments, and @unmatchedNames@ contains the argument names
-- that haven't been matched.
extractArgs :: [Text] -> [(Maybe Text, a)] -> (HashMap Text a, [a], HashMap Text a, [Text])
extractArgs :: [Text]
-> [(Maybe Text, a)]
-> (HashMap Text a, [a], HashMap Text a, [Text])
extractArgs [Text]
argNames [(Maybe Text, a)]
args =
    let ([(Text, a)]
matchedPositional, [Text]
argNames', [(Maybe Text, a)]
args') = [Text]
-> [(Maybe Text, a)] -> ([(Text, a)], [Text], [(Maybe Text, a)])
forall a.
[Text]
-> [(Maybe Text, a)] -> ([(Text, a)], [Text], [(Maybe Text, a)])
matchPositionalArgs [Text]
argNames [(Maybe Text, a)]
args
        ([(Text, a)]
matchedKeyword, [Text]
argNames'', [(Maybe Text, a)]
args'') = [Text]
-> [(Maybe Text, a)] -> ([(Text, a)], [Text], [(Maybe Text, a)])
forall a.
[Text]
-> [(Maybe Text, a)] -> ([(Text, a)], [Text], [(Maybe Text, a)])
matchKeywordArgs [Text]
argNames' [(Maybe Text, a)]
args'
        unmatchedPositional :: [a]
unmatchedPositional = [ a
a | (Maybe Text
Nothing, a
a) <- [(Maybe Text, a)]
args'' ]
        unmatchedKeyword :: HashMap Text a
unmatchedKeyword = [(Text, a)] -> HashMap Text a
forall k v. (Eq k, Hashable k) => [(k, v)] -> HashMap k v
HashMap.fromList [ (Text
k, a
v) | (Just Text
k, a
v) <- [(Maybe Text, a)]
args'' ]
    in ( [(Text, a)] -> HashMap Text a
forall k v. (Eq k, Hashable k) => [(k, v)] -> HashMap k v
HashMap.fromList ([(Text, a)]
matchedPositional [(Text, a)] -> [(Text, a)] -> [(Text, a)]
forall a. [a] -> [a] -> [a]
++ [(Text, a)]
matchedKeyword)
       , [a]
unmatchedPositional
       , HashMap Text a
unmatchedKeyword
       , [Text]
argNames''
       )
    where
        matchPositionalArgs :: [Text] -> [(Maybe Text, a)] -> ([(Text, a)], [Text], [(Maybe Text, a)])
        matchPositionalArgs :: [Text]
-> [(Maybe Text, a)] -> ([(Text, a)], [Text], [(Maybe Text, a)])
matchPositionalArgs [] [(Maybe Text, a)]
args = ([], [], [(Maybe Text, a)]
args)
        matchPositionalArgs [Text]
names [] = ([], [Text]
names, [])
        matchPositionalArgs names :: [Text]
names@(Text
n:[Text]
ns) allArgs :: [(Maybe Text, a)]
allArgs@((Maybe Text
anm, a
arg):[(Maybe Text, a)]
args)
            | Text -> Maybe Text
forall a. a -> Maybe a
Just Text
n Maybe Text -> Maybe Text -> Bool
forall a. Eq a => a -> a -> Bool
== Maybe Text
anm Bool -> Bool -> Bool
|| Maybe Text -> Bool
forall a. Maybe a -> Bool
isNothing Maybe Text
anm =
                let ([(Text, a)]
matched, [Text]
ns', [(Maybe Text, a)]
args') = [Text]
-> [(Maybe Text, a)] -> ([(Text, a)], [Text], [(Maybe Text, a)])
forall a.
[Text]
-> [(Maybe Text, a)] -> ([(Text, a)], [Text], [(Maybe Text, a)])
matchPositionalArgs [Text]
ns [(Maybe Text, a)]
args
                in ((Text
n, a
arg)(Text, a) -> [(Text, a)] -> [(Text, a)]
forall a. a -> [a] -> [a]
:[(Text, a)]
matched, [Text]
ns', [(Maybe Text, a)]
args')
            | Bool
otherwise = ([], [Text]
names, [(Maybe Text, a)]
allArgs)

        matchKeywordArgs :: [Text] -> [(Maybe Text, a)] -> ([(Text, a)], [Text], [(Maybe Text, a)])
        matchKeywordArgs :: [Text]
-> [(Maybe Text, a)] -> ([(Text, a)], [Text], [(Maybe Text, a)])
matchKeywordArgs [] [(Maybe Text, a)]
args = ([], [], [(Maybe Text, a)]
args)
        matchKeywordArgs [Text]
names allArgs :: [(Maybe Text, a)]
allArgs@((Maybe Text
Nothing, a
arg):[(Maybe Text, a)]
args) =
            let ([(Text, a)]
matched, [Text]
ns', [(Maybe Text, a)]
args') = [Text]
-> [(Maybe Text, a)] -> ([(Text, a)], [Text], [(Maybe Text, a)])
forall a.
[Text]
-> [(Maybe Text, a)] -> ([(Text, a)], [Text], [(Maybe Text, a)])
matchKeywordArgs [Text]
names [(Maybe Text, a)]
args
            in ([(Text, a)]
matched, [Text]
ns', (Maybe Text
forall a. Maybe a
Nothing, a
arg)(Maybe Text, a) -> [(Maybe Text, a)] -> [(Maybe Text, a)]
forall a. a -> [a] -> [a]
:[(Maybe Text, a)]
args')
        matchKeywordArgs names :: [Text]
names@(Text
n:[Text]
ns) [(Maybe Text, a)]
args =
            case (Maybe Text -> [(Maybe Text, a)] -> Maybe a
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup (Text -> Maybe Text
forall a. a -> Maybe a
Just Text
n) [(Maybe Text, a)]
args) of
                Maybe a
Nothing ->
                    let ([(Text, a)]
matched, [Text]
ns', [(Maybe Text, a)]
args') = [Text]
-> [(Maybe Text, a)] -> ([(Text, a)], [Text], [(Maybe Text, a)])
forall a.
[Text]
-> [(Maybe Text, a)] -> ([(Text, a)], [Text], [(Maybe Text, a)])
matchKeywordArgs [Text]
ns [(Maybe Text, a)]
args
                    in ([(Text, a)]
matched, Text
nText -> [Text] -> [Text]
forall a. a -> [a] -> [a]
:[Text]
ns', [(Maybe Text, a)]
args')
                Just a
v ->
                    let args' :: [(Maybe Text, a)]
args' = [ (Maybe Text
k,a
v) | (Maybe Text
k,a
v) <- [(Maybe Text, a)]
args, Maybe Text
k Maybe Text -> Maybe Text -> Bool
forall a. Eq a => a -> a -> Bool
/= Text -> Maybe Text
forall a. a -> Maybe a
Just Text
n ]
                        ([(Text, a)]
matched, [Text]
ns', [(Maybe Text, a)]
args'') = [Text]
-> [(Maybe Text, a)] -> ([(Text, a)], [Text], [(Maybe Text, a)])
forall a.
[Text]
-> [(Maybe Text, a)] -> ([(Text, a)], [Text], [(Maybe Text, a)])
matchKeywordArgs [Text]
ns [(Maybe Text, a)]
args'
                    in ((Text
n,a
v)(Text, a) -> [(Text, a)] -> [(Text, a)]
forall a. a -> [a] -> [a]
:[(Text, a)]
matched, [Text]
ns', [(Maybe Text, a)]
args'')

-- | Parse argument list into type-safe argument structure.
extractArgsT :: ([Maybe a] -> b) -> [Text] -> [(Maybe Text, a)] -> Either ([a], HashMap Text a, [Text]) b
extractArgsT :: ([Maybe a] -> b)
-> [Text]
-> [(Maybe Text, a)]
-> Either ([a], HashMap Text a, [Text]) b
extractArgsT [Maybe a] -> b
f [Text]
argNames [(Maybe Text, a)]
args =
    let (HashMap Text a
matchedMap, [a]
freeArgs, HashMap Text a
freeKwargs, [Text]
unmatched) = [Text]
-> [(Maybe Text, a)]
-> (HashMap Text a, [a], HashMap Text a, [Text])
forall a.
[Text]
-> [(Maybe Text, a)]
-> (HashMap Text a, [a], HashMap Text a, [Text])
extractArgs [Text]
argNames [(Maybe Text, a)]
args
    in if [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
List.null [a]
freeArgs Bool -> Bool -> Bool
&& HashMap Text a -> Bool
forall k v. HashMap k v -> Bool
HashMap.null HashMap Text a
freeKwargs
        then b -> Either ([a], HashMap Text a, [Text]) b
forall a b. b -> Either a b
Right ([Maybe a] -> b
f ([Maybe a] -> b) -> [Maybe a] -> b
forall a b. (a -> b) -> a -> b
$ (Text -> Maybe a) -> [Text] -> [Maybe a]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\Text
name -> Text -> HashMap Text a -> Maybe a
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
HashMap.lookup Text
name HashMap Text a
matchedMap) [Text]
argNames)
        else ([a], HashMap Text a, [Text])
-> Either ([a], HashMap Text a, [Text]) b
forall a b. a -> Either a b
Left ([a]
freeArgs, HashMap Text a
freeKwargs, [Text]
unmatched)

-- | Parse argument list into flat list of matched arguments.
extractArgsL :: [Text] -> [(Maybe Text, a)] -> Either ([a], HashMap Text a, [Text]) [Maybe a]
extractArgsL :: [Text]
-> [(Maybe Text, a)]
-> Either ([a], HashMap Text a, [Text]) [Maybe a]
extractArgsL = ([Maybe a] -> [Maybe a])
-> [Text]
-> [(Maybe Text, a)]
-> Either ([a], HashMap Text a, [Text]) [Maybe a]
forall a b.
([Maybe a] -> b)
-> [Text]
-> [(Maybe Text, a)]
-> Either ([a], HashMap Text a, [Text]) b
extractArgsT [Maybe a] -> [Maybe a]
forall a. a -> a
id

extractArgsDefL :: [(Text, a)] -> [(Maybe Text, a)] -> Either ([a], HashMap Text a, [Text]) [a]
extractArgsDefL :: [(Text, a)]
-> [(Maybe Text, a)] -> Either ([a], HashMap Text a, [Text]) [a]
extractArgsDefL [(Text, a)]
argSpec [(Maybe Text, a)]
args =
    let ([Text]
names, [a]
defs) = [(Text, a)] -> ([Text], [a])
forall a b. [(a, b)] -> ([a], [b])
unzip [(Text, a)]
argSpec
    in [a] -> [Maybe a] -> [a]
forall a. [a] -> [Maybe a] -> [a]
injectDefaults [a]
defs ([Maybe a] -> [a])
-> Either ([a], HashMap Text a, [Text]) [Maybe a]
-> Either ([a], HashMap Text a, [Text]) [a]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Text]
-> [(Maybe Text, a)]
-> Either ([a], HashMap Text a, [Text]) [Maybe a]
forall a.
[Text]
-> [(Maybe Text, a)]
-> Either ([a], HashMap Text a, [Text]) [Maybe a]
extractArgsL [Text]
names [(Maybe Text, a)]
args

injectDefaults :: [a] -> [Maybe a] -> [a]
injectDefaults :: [a] -> [Maybe a] -> [a]
injectDefaults = (a -> Maybe a -> a) -> [a] -> [Maybe a] -> [a]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith a -> Maybe a -> a
forall a. a -> Maybe a -> a
fromMaybe