trifecta 0.23 → 0.24
raw patch · 10 files changed
+264/−110 lines, 10 files
Files
- Text/Trifecta/Diagnostic.hs +17/−3
- Text/Trifecta/Diagnostic/Class.hs +48/−18
- Text/Trifecta/Diagnostic/Combinators.hs +45/−0
- Text/Trifecta/Diagnostic/Err.hs +10/−52
- Text/Trifecta/Diagnostic/Err/State.hs +5/−4
- Text/Trifecta/Diagnostic/Level.hs +2/−2
- Text/Trifecta/Parser/Class.hs +82/−0
- Text/Trifecta/Parser/Prim.hs +22/−30
- Text/Trifecta/Parser/Token/Class.hs +31/−0
- trifecta.cabal +2/−1
Text/Trifecta/Diagnostic.hs view
@@ -1,17 +1,31 @@ module Text.Trifecta.Diagnostic - ( Diagnostic(..)+ ( + -- * Diagnostics+ Diagnostic(..) , tellDiagnostic- , MonadDiagnostic(..)- , DiagnosticLevel(..)+ -- * Rendering , Renderable(..) , Source , rendering , Caret(..), Careted(..) , Span(..), Spanned(..) , Fixit(..), Rendered(..)+ -- * Emitting diagnostics+ , MonadDiagnostic(..)+ , fatal+ , err+ , warn+ , note+ , verbose+ , warnWith+ , noteWith+ , verboseWith+ -- * Diagnostic Levels+ , DiagnosticLevel(..) ) where import Text.Trifecta.Diagnostic.Prim import Text.Trifecta.Diagnostic.Class+import Text.Trifecta.Diagnostic.Combinators import Text.Trifecta.Diagnostic.Level import Text.Trifecta.Diagnostic.Rendering
Text/Trifecta/Diagnostic/Class.hs view
@@ -6,28 +6,58 @@ import Control.Monad.Trans.Class import Control.Monad.Trans.State.Lazy as Lazy import Control.Monad.Trans.State.Strict as Strict+import Control.Monad.Trans.RWS.Lazy as Lazy+import Control.Monad.Trans.RWS.Strict as Strict+import Control.Monad.Trans.Writer.Lazy as Lazy+import Control.Monad.Trans.Writer.Strict as Strict+import Control.Monad.Trans.Reader+import Control.Monad.Trans.Identity+import Data.Monoid import Text.Trifecta.Diagnostic.Prim+import Text.Trifecta.Diagnostic.Level+import Text.Trifecta.Diagnostic.Rendering.Prim class Monad m => MonadDiagnostic e m | m -> e where- record :: Diagnostic e -> m ()- fatal :: e -> m a -- consuming error- err :: e -> m a -- non-consuming error- warn :: e -> m ()- note :: e -> m ()- verbose :: Int -> e -> m ()+ fatalWith :: [Diagnostic e] -> [Rendering] -> e -> m a -- consuming error+ errWith :: [Diagnostic e] -> [Rendering] -> e -> m a -- non-consuming error, handled by <|> + logWith :: DiagnosticLevel -> [Diagnostic e] -> [Rendering] -> e -> m () -- log an error and continue instance MonadDiagnostic e m => MonadDiagnostic e (Lazy.StateT s m) where- record = lift . record- fatal = lift . fatal- err = lift . err- warn = lift . warn- note = lift . note- verbose n = lift . verbose n+ fatalWith d r e = lift (fatalWith d r e)+ errWith d r e = lift (errWith d r e)+ logWith l d r e = lift (logWith l d r e) instance MonadDiagnostic e m => MonadDiagnostic e (Strict.StateT s m) where- record = lift . record- fatal = lift . fatal- err = lift . err- warn = lift . warn- note = lift . note- verbose n = lift . verbose n+ fatalWith d r e = lift (fatalWith d r e)+ errWith d r e = lift (errWith d r e)+ logWith l d r e = lift (logWith l d r e)++instance MonadDiagnostic e m => MonadDiagnostic e (ReaderT r m) where+ fatalWith d r e = lift (fatalWith d r e)+ errWith d r e = lift (errWith d r e)+ logWith l d r e = lift (logWith l d r e)++instance (MonadDiagnostic e m, Monoid w) => MonadDiagnostic e (Lazy.WriterT w m) where+ fatalWith d r e = lift (fatalWith d r e)+ errWith d r e = lift (errWith d r e)+ logWith l d r e = lift (logWith l d r e)++instance (MonadDiagnostic e m, Monoid w) => MonadDiagnostic e (Strict.WriterT w m) where+ fatalWith d r e = lift (fatalWith d r e)+ errWith d r e = lift (errWith d r e)+ logWith l d r e = lift (logWith l d r e)++instance (MonadDiagnostic e m, Monoid w) => MonadDiagnostic e (Lazy.RWST r w s m) where+ fatalWith d r e = lift (fatalWith d r e)+ errWith d r e = lift (errWith d r e)+ logWith l d r e = lift (logWith l d r e)++instance (MonadDiagnostic e m, Monoid w) => MonadDiagnostic e (Strict.RWST r w s m) where+ fatalWith d r e = lift (fatalWith d r e)+ errWith d r e = lift (errWith d r e)+ logWith l d r e = lift (logWith l d r e)++instance MonadDiagnostic e m => MonadDiagnostic e (IdentityT m) where+ fatalWith d r e = lift (fatalWith d r e)+ errWith d r e = lift (errWith d r e)+ logWith l d r e = lift (logWith l d r e)
+ Text/Trifecta/Diagnostic/Combinators.hs view
@@ -0,0 +1,45 @@+module Text.Trifecta.Diagnostic.Combinators + ( fatal+ , err+ , warn+ , note+ , verbose+ , warnWith+ , noteWith+ , verboseWith+ ) where++import Text.Trifecta.Diagnostic.Class+import Text.Trifecta.Diagnostic.Prim+import Text.Trifecta.Diagnostic.Level+import Text.Trifecta.Diagnostic.Rendering.Prim++fatal :: MonadDiagnostic e m => e -> m a+fatal = fatalWith [] []++err :: MonadDiagnostic e m => e -> m a+err = errWith [] []++warn :: MonadDiagnostic e m => e -> m ()+warn = warnWith [] []++note :: MonadDiagnostic e m => e -> m ()+note = noteWith [] []++verbose :: MonadDiagnostic e m => Int -> e -> m ()+verbose n = verboseWith n [] []++warnWith :: MonadDiagnostic e m => [Diagnostic e] -> [Rendering] -> e -> m ()+warnWith = logWith Warning++noteWith :: MonadDiagnostic e m => [Diagnostic e] -> [Rendering] -> e -> m ()+noteWith = logWith Note++verboseWith :: MonadDiagnostic e m => Int -> [Diagnostic e] -> [Rendering] -> e -> m ()+verboseWith n = logWith (Verbose n)++-- sublimate :: MonadDiagnostic e m => m a -> m a+-- sublimate a = a `catchError` \e -> +-- if fatalErr e then throwError e else do +-- m <- here+-- tell (diagnose m e)
Text/Trifecta/Diagnostic/Err.hs view
@@ -1,12 +1,9 @@ module Text.Trifecta.Diagnostic.Err ( Err(..)- , diagnose , knownErr , fatalErr ) where -import Control.Applicative-import Control.Comonad import Data.Semigroup import Data.Monoid import Data.Functor.Plus@@ -14,71 +11,32 @@ import Text.Trifecta.Diagnostic.Level import Text.Trifecta.Diagnostic.Rendering.Prim import Text.PrettyPrint.Free-import System.Console.Terminfo.PrettyPrint --- | unlocated error messages+-- | unlocated error data Err e = EmptyErr- | UnexpectedErr String- | EndOfFileErr- | FailErr String - | RichErr (Rendering -> Diagnostic e) -- relocates with us as we try- | FatalErr (Diagnostic e)--instance Show e => Show (Err e) where- showsPrec _ EmptyErr = showString "EmptyErr"- showsPrec d (FailErr s) = showParen (d > 10) $- showString "FailErr " . showsPrec 11 s- showsPrec d (UnexpectedErr s) = showParen (d > 10) $- showString "UnexpectedErr " . showsPrec 11 s- showsPrec d (FatalErr e) = showParen (d > 10) $ showString "FatalErr " . showsPrec 11 e- showsPrec _ EndOfFileErr = showString "EndOfFileErr"- showsPrec d (RichErr _) = showParen (d > 10) $ - showString "RichErr ..."+ | FailErr String+ | Err [Rendering] !DiagnosticLevel e [Diagnostic e]+ deriving Show knownErr :: Err e -> Bool knownErr EmptyErr = False knownErr _ = True fatalErr :: Err e -> Bool-fatalErr FatalErr{} = True+fatalErr (Err _ Fatal _ _) = True fatalErr _ = False -diagnose :: (t -> Doc e) -> Rendering -> Err t -> Diagnostic (Doc e)-diagnose _ r EmptyErr = Diagnostic r Error (text "unexpected") []-diagnose _ r (FailErr m) = Diagnostic r Error (fillSep $ text <$> words m) []-diagnose _ r (UnexpectedErr s) = Diagnostic r Error (fillSep $ fmap text $ "unexpected" : words s) []-diagnose _ r EndOfFileErr = Diagnostic r Error (text "unexpected EOF") []-diagnose k _ (FatalErr e) = fmap k e-diagnose k r (RichErr f) = fmap k (f r)--diagnose0 :: Pretty t => Err t -> Diagnostic (Doc e)-diagnose0 = diagnose pretty emptyRendering--diagnoseTerm0 :: PrettyTerm t => Err t -> Diagnostic TermDoc-diagnoseTerm0 = diagnose prettyTerm emptyRendering--instance Pretty t => Pretty (Err t) where- pretty = pretty . extract . diagnose0- prettyList = prettyList . map (extract . diagnose0)--instance PrettyTerm t => PrettyTerm (Err t) where- prettyTerm = prettyTerm . diagnoseTerm0- prettyTermList = prettyTermList . map diagnoseTerm0- instance Functor Err where fmap _ EmptyErr = EmptyErr fmap _ (FailErr s) = FailErr s- fmap _ EndOfFileErr = EndOfFileErr- fmap f (FatalErr e) = FatalErr (fmap f e)- fmap _ (UnexpectedErr s) = UnexpectedErr s - fmap f (RichErr k) = RichErr (fmap f . k)+ fmap f (Err rs l e es) = Err rs l (f e) (fmap (fmap f) es) instance Alt Err where- EmptyErr <!> a = a- e@FatalErr{} <!> _ = e- _ <!> e@FatalErr{} = e- a <!> _ = a + a <!> EmptyErr = a+ _ <!> a@(Err _ Fatal _ _) = a+ a@(Err _ Fatal _ _) <!> _ = a+ _ <!> b = b {-# INLINE (<!>) #-} instance Plus Err where
Text/Trifecta/Diagnostic/Err/State.hs view
@@ -6,22 +6,23 @@ import Data.Set as Set import Data.Semigroup import Data.Monoid+import Text.PrettyPrint.Free import Text.Trifecta.Diagnostic.Err data ErrState e = ErrState- { errExpected :: !(Set String)- , errMessage :: !(Err e)+ { errExpected :: !(Set String)+ , errMessage :: !(Err e) } instance Functor ErrState where fmap f (ErrState a b) = ErrState a (fmap f b) instance Alt ErrState where- ErrState a b <!> ErrState a' b' = ErrState (a <> a') (b <!> b')+ ErrState a b <!> ErrState a' b' = ErrState (a <> a') (b <> b') {-# INLINE (<!>) #-} instance Plus ErrState where- zero = ErrState mempty zero+ zero = ErrState mempty mempty instance Semigroup (ErrState e) where (<>) = (<!>)
Text/Trifecta/Diagnostic/Level.hs view
@@ -34,7 +34,7 @@ instance PrettyTerm DiagnosticLevel where prettyTerm (Verbose n) = blue $ text "verbose (" <> int n <> char ')'- prettyTerm Note = text "note"+ prettyTerm Note = black $ text "note" prettyTerm Warning = magenta $ text "warning" prettyTerm Error = red $ text "error"- prettyTerm Fatal = blink $ red $ text "fatal"+ prettyTerm Fatal = standout $ red $ text "fatal"
Text/Trifecta/Parser/Class.hs view
@@ -18,6 +18,7 @@ , (<?>) , slicedWith , sliced+ , rend ) where import Control.Applicative@@ -25,12 +26,22 @@ import Control.Monad.Trans.Class import Control.Monad.Trans.State.Lazy as Lazy import Control.Monad.Trans.State.Strict as Strict+import Control.Monad.Trans.Writer.Lazy as Lazy+import Control.Monad.Trans.Writer.Strict as Strict+import Control.Monad.Trans.RWS.Lazy as Lazy+import Control.Monad.Trans.RWS.Strict as Strict+import Control.Monad.Trans.Reader+import Control.Monad.Trans.Identity+import Data.Monoid+-- import Control.Monad.Trans.Maybe.Strict as Strict+-- import Control.Monad.Trans.Either.Strict as Strict import Data.ByteString as Strict import Data.Semigroup import Data.Set as Set import Text.Trifecta.Rope.Delta import Text.Trifecta.Rope.Prim import Text.Trifecta.Parser.It+import Text.Trifecta.Diagnostic.Rendering.Prim infix 0 <?> @@ -72,6 +83,75 @@ unexpected = lift . unexpected satisfyAscii = lift . satisfyAscii +instance MonadParser m => MonadParser (ReaderT e m) where+ satisfy = lift . satisfy+ try (ReaderT m) = ReaderT $ try . m+ labels (ReaderT m) ss = ReaderT $ \s -> labels (m s) ss+ line = lift line+ liftIt = lift . liftIt+ mark = lift mark + release = lift . release+ unexpected = lift . unexpected+ satisfyAscii = lift . satisfyAscii++instance (MonadParser m, Monoid w) => MonadParser (Strict.WriterT w m) where+ satisfy = lift . satisfy+ try (Strict.WriterT m) = Strict.WriterT $ try m+ labels (Strict.WriterT m) ss = Strict.WriterT $ labels m ss+ line = lift line+ liftIt = lift . liftIt+ mark = lift mark + release = lift . release+ unexpected = lift . unexpected+ satisfyAscii = lift . satisfyAscii++instance (MonadParser m, Monoid w) => MonadParser (Lazy.WriterT w m) where+ satisfy = lift . satisfy+ try (Lazy.WriterT m) = Lazy.WriterT $ try m+ labels (Lazy.WriterT m) ss = Lazy.WriterT $ labels m ss+ line = lift line+ liftIt = lift . liftIt+ mark = lift mark + release = lift . release+ unexpected = lift . unexpected+ satisfyAscii = lift . satisfyAscii++instance (MonadParser m, Monoid w) => MonadParser (Lazy.RWST r w s m) where+ satisfy = lift . satisfy+ try (Lazy.RWST m) = Lazy.RWST $ \r s -> try (m r s)+ labels (Lazy.RWST m) ss = Lazy.RWST $ \r s -> labels (m r s) ss+ line = lift line+ liftIt = lift . liftIt+ mark = lift mark + release = lift . release+ unexpected = lift . unexpected+ satisfyAscii = lift . satisfyAscii++instance (MonadParser m, Monoid w) => MonadParser (Strict.RWST r w s m) where+ satisfy = lift . satisfy+ try (Strict.RWST m) = Strict.RWST $ \r s -> try (m r s)+ labels (Strict.RWST m) ss = Strict.RWST $ \r s -> labels (m r s) ss+ line = lift line+ liftIt = lift . liftIt+ mark = lift mark + release = lift . release+ unexpected = lift . unexpected+ satisfyAscii = lift . satisfyAscii++instance MonadParser m => MonadParser (IdentityT m) where+ satisfy = lift . satisfy+ try (IdentityT m) = IdentityT $ try m+ labels (IdentityT m) = IdentityT . labels m+ line = lift line+ liftIt = lift . liftIt+ mark = lift mark + release = lift . release+ unexpected = lift . unexpected+ satisfyAscii = lift . satisfyAscii++-- instance (MonadParser m, Monoid w) => MonadParser (MaybeT m) where+-- instance (Error e, MonadParser m, Monoid w) => MonadParser (ErrorT e m) where+ -- useful when we've just recognized something out of band using access to the current line skipping :: (MonadParser m, HasDelta d) => d -> m d skipping d = do@@ -100,3 +180,5 @@ sliced :: MonadParser m => m a -> m ByteString sliced = slicedWith (\_ bs -> bs) +rend :: MonadParser m => m Rendering+rend = rendering <$> mark <*> line
Text/Trifecta/Parser/Prim.hs view
@@ -107,14 +107,13 @@ {-# INLINE (>>=) #-} (>>) = (*>) {-# INLINE (>>) #-}- fail = throwError . FailErr+ fail s = Parser $ \ _ ee _ _ -> ee mempty { errMessage = FailErr s } {-# INLINE fail #-} instance MonadPlus (Parser e) where mzero = empty mplus = (<|>) - instance MonadWriter (Seq (Diagnostic e)) (Parser e) where tell w = Parser $ \eo _ _ _ l -> eo () mempty (l <> w) {-# INLINE tell #-}@@ -133,28 +132,19 @@ mempty {-# INLINE pass #-} -logging :: DiagnosticLevel -> e -> Parser e ()-logging level e = do- m <- mark- l <- line- tell $ return $ Diagnostic (addCaret m $ rendering m l) level e []- instance MonadDiagnostic e (Parser e) where- record = tell . return- fatal e = Parser $ \_ _ _ ce l d bs -> ce mempty { errMessage = FatalErr (Diagnostic (addCaret d $ rendering d bs) Fatal e []) } l d bs- err e = do- m <- mark- throwError $ RichErr $ \r -> Diagnostic (addCaret m r) Error e [] -- showing the actual location- warn = logging Warning- note = logging Note- verbose = logging . Verbose--instance MonadError (Err e) (Parser e) where- throwError m = Parser $ \_ ee _ _ -> ee mempty { errMessage = m } + fatalWith ds rs e = Parser $ \_ _ _ ce -> + ce mempty { errMessage = Err rs Fatal e ds }+ errWith ds rs e = Parser $ \_ ee _ _ -> + ee mempty { errMessage = Err rs Error e ds }+ logWith v ds rs e = Parser $ \eo _ _ _ l d bs -> + eo () mempty (l |> Diagnostic (addCaret d $ Prelude.foldr (<>) (rendering d bs) rs) v e ds) d bs+ +instance MonadError (ErrState e) (Parser e) where+ throwError m = Parser $ \_ ee _ _ -> ee m {-# INLINE throwError #-} catchError (Parser m) k = Parser $ \ eo ee co ce -> - m eo (\e -> unparser (k (errMessage e)) (\a e'-> eo a (e <> e')) (\e' -> ee (e <> e')) co ce) - co ce+ m eo (\e -> unparser (k e) eo ee co ce) co ce {-# INLINE catchError #-} instance MonadParser (Parser e) where@@ -162,11 +152,11 @@ try (Parser m) = Parser $ \ eo ee co ce -> m eo ee co $ \e -> if fatalErr (errMessage e) then ce e else ee e {-# INLINE try #-}- unexpected s = Parser $ \ _ ee _ _ -> ee mempty { errMessage = UnexpectedErr s } + unexpected s = Parser $ \ _ ee _ _ -> ee mempty { errMessage = FailErr $ "unexpected " ++ s } labels (Parser p) msgs = Parser $ \ eo ee -> p- (\a e -> eo a $ if knownErr (errMessage e) - then e { errExpected = errExpected e }+ (\a e -> eo a $ if knownErr (errMessage e)+ then e { errExpected = msgs `union` errExpected e } else e) (\e -> ee e { errExpected = msgs }) {-# INLINE labels #-}@@ -186,7 +176,7 @@ {-# INLINE line #-} satisfy f = Parser $ \ _ ee co _ l d bs -> case UTF8.uncons $ Strict.drop (columnByte d) bs of- Nothing -> ee mempty { errMessage = EndOfFileErr } l d bs+ Nothing -> ee mempty { errMessage = FailErr "unexpected EOF" } l d bs Just (c, xs) | not (f c) -> ee mempty l d bs | Strict.null xs -> let ddc = d <> delta c in@@ -201,7 +191,7 @@ | b == Strict.length bs - 1 -> let ddc = d <> delta c in join $ fillIt (co c mempty l ddc bs) (co c mempty l) ddc | otherwise -> co c mempty l (d <> delta c) bs- else ee mempty { errMessage = EndOfFileErr } l d bs+ else ee mempty { errMessage = FailErr "unexpected EOF" } l d bs {-# INLINE satisfyAscii #-} data St e a = JuSt a !(ErrState e) !(ErrLog e) !Delta !ByteString@@ -225,14 +215,16 @@ NoSt e l d bs -> Failure (yl <$> l) $ y e d bs) (go <*> k) ---- explain an error in terms of the expected set, when we are running the step parser for pretty printing why :: Pretty e => (e -> Doc t) -> ErrState e -> Delta -> ByteString -> Diagnostic (Doc t) why pp (ErrState ss m) d bs - | Set.null ss = diagnose pp (addCaret d $ rendering d bs) m- | otherwise = expected <$> diagnose pp (addCaret d $ rendering d bs) m + | Set.null ss = explicate m + | otherwise = expected <$> explicate m where expected doc = doc <> text ", expected" <+> fillSep (punctuate (char ',') $ text <$> toList ss)+ r = addCaret d $ rendering d bs+ explicate EmptyErr = Diagnostic r Error (text "error") []+ explicate (FailErr s) = Diagnostic r Error (fillSep $ text <$> words s) []+ explicate (Err rs l e es) = Diagnostic (addCaret d $ Prelude.foldr (<>) (rendering d bs) rs) l (pp e) (fmap (fmap pp) es) parseTest :: Show a => Parser String a -> String -> IO () parseTest p s = case starve $ feed st $ UTF8.fromString s of
Text/Trifecta/Parser/Token/Class.hs view
@@ -17,6 +17,13 @@ import Control.Monad.Trans.Class import Control.Monad.Trans.State.Lazy as Lazy import Control.Monad.Trans.State.Strict as Strict+import Control.Monad.Trans.Writer.Lazy as Lazy+import Control.Monad.Trans.Writer.Strict as Strict+import Control.Monad.Trans.RWS.Lazy as Lazy+import Control.Monad.Trans.RWS.Strict as Strict+import Control.Monad.Trans.Reader+import Control.Monad.Trans.Identity+import Data.Monoid import Text.Trifecta.Parser.Class class MonadParser m => MonadTokenParser m where@@ -44,6 +51,10 @@ lexeme :: m a -> m a lexeme p = p <* whiteSpace +instance MonadTokenParser m => MonadTokenParser (ReaderT r m) where+ whiteSpace = lift whiteSpace+ lexeme (ReaderT m) = ReaderT $ lexeme . m+ instance MonadTokenParser m => MonadTokenParser (Lazy.StateT s m) where whiteSpace = lift whiteSpace lexeme (Lazy.StateT m) = Lazy.StateT $ lexeme . m@@ -51,3 +62,23 @@ instance MonadTokenParser m => MonadTokenParser (Strict.StateT s m) where whiteSpace = lift whiteSpace lexeme (Strict.StateT m) = Strict.StateT $ lexeme . m++instance (MonadTokenParser m, Monoid w) => MonadTokenParser (Lazy.WriterT w m) where+ whiteSpace = lift whiteSpace+ lexeme (Lazy.WriterT m) = Lazy.WriterT $ lexeme m++instance (MonadTokenParser m, Monoid w) => MonadTokenParser (Strict.WriterT w m) where+ whiteSpace = lift whiteSpace+ lexeme (Strict.WriterT m) = Strict.WriterT $ lexeme m++instance (MonadTokenParser m, Monoid w) => MonadTokenParser (Lazy.RWST r w s m) where+ whiteSpace = lift whiteSpace+ lexeme (Lazy.RWST m) = Lazy.RWST $ \r s -> lexeme (m r s)++instance (MonadTokenParser m, Monoid w) => MonadTokenParser (Strict.RWST r w s m) where+ whiteSpace = lift whiteSpace+ lexeme (Strict.RWST m) = Strict.RWST $ \r s -> lexeme (m r s)++instance MonadTokenParser m => MonadTokenParser (IdentityT m) where+ whiteSpace = lift whiteSpace+ lexeme = IdentityT . lexeme . runIdentityT
trifecta.cabal view
@@ -1,6 +1,6 @@ name: trifecta category: Text, Parsing, Diagnostics, Pretty Printer, Logging-version: 0.23+version: 0.24 license: BSD3 cabal-version: >= 1.6 license-file: LICENSE@@ -38,6 +38,7 @@ Text.Trifecta.Diagnostic Text.Trifecta.Diagnostic.Prim Text.Trifecta.Diagnostic.Class+ Text.Trifecta.Diagnostic.Combinators Text.Trifecta.Diagnostic.Level Text.Trifecta.Diagnostic.Err Text.Trifecta.Diagnostic.Err.State