module System.Console.Quickterm.Internal ( Quickterm (..) , param ) where import System.Console.Quickterm.CanMarshall import System.Console.Quickterm.Deserializer import System.Console.Quickterm.Help import Control.Applicative import Control.Monad -- |Quickterm represents a non-deterministic calculation of a most predictable -- |command based on a breadth-first parsing strategy. The Quickterm is applied -- |to a [String] to achieve parsing of command line arguments. newtype Quickterm a = Quickterm { runQuickterm :: Int -> Help -> [String] -> [String] -> [(a, Int, Help, [String], [String])] } instance Functor Quickterm where fmap f m = Quickterm $ \i h pi as -> fmap (\(a,i',h',pi',as') -> (f a,i',h',pi',as')) (runQuickterm m i h pi as) instance Applicative Quickterm where pure a = Quickterm $ \i h pi as -> pure (a,i,h,pi,as) f <*> m = Quickterm $ \i h pi as -> join $ (\(g,i',h', pi',as') -> (\(a,i'',h'', pi'',as'') -> (g a,i'',h'',pi'',as'')) <$> runQuickterm m i' h' pi' as') <$> runQuickterm f i h pi as instance Alternative Quickterm where empty = Quickterm (const (const (const (const empty)))) m <|> n = Quickterm $ \i h pi as -> filter (\(_,i,_,_,_) -> i < 1000) $ runQuickterm m i h pi as <|> runQuickterm n i h pi as instance Monad Quickterm where return = pure m >>= f = Quickterm $ \i h pi as -> runQuickterm m i h pi as >>= \(a,i',h',pi',as') -> runQuickterm (f a) i' h' pi' as' instance MonadPlus Quickterm where mzero = empty mplus = (<|>) param :: (CanMarshall a) => Quickterm a param = Quickterm $ \i h pi as -> case as of [] -> let d = defaultM in [(d,i+10,h,asInput d:pi,[])] (a:as') -> deserialize deserializer a 0 >>= \(a, _, i') -> return (a, i + i', h, asInput a:pi, as')