prosidyc-0.1.0.0: src/Prosidy/Compile/Run.hs
{-|
Module : Prosidy.Compile.Run
Description : Interpretation of compilation rules.
Copyright : ©2020 James Alexander Feldman-Crough
License : MPL-2.0
Maintainer : alex@fldcr.com
-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE LambdaCase #-}
module Prosidy.Compile.Run (run, runM) where
import Lens.Micro
import Prosidy.Compile.Core
import Prosidy.Compile.Error
import Control.Monad.Trans ( MonadIO(..)
, MonadTrans(..)
)
import Control.Monad.Except ( ExceptT(..) )
import Data.Functor.Identity ( Identity(..) )
import qualified Prosidy as P
-------------------------------------------------------------------------------
-- | Run a 'Rule' against an input, returning a parse result.
run :: IsError e => RuleT i e Identity a -> i -> Either (ErrorSet e) a
run rule = runIdentity . runM rule
-- | Run a 'RuleT' against an input, returning a contextual parse result.
runM
:: (Monad context, IsError e)
=> RuleT i e context a
-> i
-> context (Either (ErrorSet e) a)
runM rule = (\(Run x) -> x) . runRun rule
-------------------------------------------------------------------------------
newtype Run error context output = Run
(context (Either (ErrorSet error) output))
deriving (Functor, Applicative, Monad, MonadError (ErrorSet error))
via (ExceptT (ErrorSet error) context)
instance MonadIO context => MonadIO (Run error context) where
liftIO = lift . liftIO
instance MonadTrans (Run error) where
lift = Run . fmap Right
runRun
:: (Monad context, IsError e) => RuleT i e context a -> i -> Run e context a
runRun rule = interpretWith rule interpret
interpret
:: (Monad context, IsError error)
=> Interpret error context (Run error context)
interpret input = \case
Fail e -> throwError1 e
Lift lifted -> lift (lifted input) >>= either throwError1 pure
TestMatch matches ->
attachLocation input $ evalPatterns matches interpret input
Traverse f g rule -> do
fmap g . traverse (runRun rule) $ f input
GetContent rule -> runRun rule $ input ^. P.content
GetProperty k key -> input ^. P.hasProperty key & pure . k
GetSetting k key parse ->
input ^. P.atSetting key & traverse parse & either
(throwError1 . ParseError key)
(pure . k)
GetRequiredSetting key parse -> do
raw <-
input ^. P.atSetting key & maybe (throwError1 $ Required key) pure
either (throwError1 . ParseError key) pure $ parse raw
GetSelf k -> pure $ k input