hnix/src/Nix/Render/Frame.hs

231 lines
7.5 KiB
Haskell
Raw Normal View History

{-# LANGUAGE CPP #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiWayIf #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
module Nix.Render.Frame where
2018-04-25 08:09:43 +02:00
import Control.Monad.Reader
import Data.Fix
import Data.Typeable
2018-11-17 05:51:18 +01:00
import Data.Text.Prettyprint.Doc
2018-04-25 08:09:43 +02:00
import Nix.Eval
import Nix.Exec
import Nix.Expr
import Nix.Frames
import Nix.Normal
import Nix.Options
import Nix.Pretty
import Nix.Render
import Nix.Thunk
import Nix.Utils
import Nix.Value
import Text.Megaparsec.Pos
2018-05-13 23:17:55 +02:00
#ifdef MIN_VERSION_pretty_show
import qualified Text.Show.Pretty as PS
#endif
2018-11-17 05:51:18 +01:00
renderFrames
:: forall v t f e m ann
. ( MonadReader e m
, Has e Options
, MonadFile m
, MonadCitedThunks t f m
, Typeable v
)
2018-11-17 05:51:18 +01:00
=> Frames -> m (Doc ann)
renderFrames [] = pure mempty
renderFrames (x:xs) = do
opts :: Options <- asks (view hasLens)
frames <-
if | verbose opts <= ErrorsOnly ->
renderFrame @v @t @f x
| verbose opts <= Informational -> do
f <- renderFrame @v @t @f x
pure $ concatMap go (reverse xs) ++ f
| otherwise ->
concat <$> mapM (renderFrame @v @t @f) (reverse (x:xs))
pure $ case frames of
[] -> mempty
2018-11-17 05:51:18 +01:00
_ -> vsep frames
where
2018-11-17 05:51:18 +01:00
go :: NixFrame -> [Doc ann]
go f = case framePos @v @m f of
Just pos ->
2018-11-17 05:51:18 +01:00
["While evaluating at "
<> pretty (sourcePosPretty pos)
<> colon]
Nothing -> []
framePos :: forall v (m :: * -> *). (Typeable m, Typeable v)
=> NixFrame -> Maybe SourcePos
framePos (NixFrame _ f)
| Just (e :: EvalFrame m v) <- fromException f = case e of
EvaluatingExpr _ (Fix (Compose (Ann (SrcSpan beg _) _))) ->
Just beg
_ -> Nothing
| otherwise = Nothing
renderFrame
:: forall v t f e m ann.
( MonadReader e m
, Has e Options
, MonadFile m
, MonadCitedThunks t f m
, Typeable v
)
=> NixFrame -> m [Doc ann]
renderFrame (NixFrame level f)
| Just (e :: EvalFrame m v) <- fromException f = renderEvalFrame level e
| Just (e :: ThunkLoop) <- fromException f = renderThunkLoop level e
| Just (e :: ValueFrame t f m) <- fromException f = renderValueFrame level e
| Just (e :: NormalLoop t f m) <- fromException f = renderNormalLoop level e
| Just (e :: ExecFrame t f m) <- fromException f = renderExecFrame level e
| Just (e :: ErrorCall) <- fromException f = pure [pretty (show e)]
| Just (e :: SynHoleInfo m v) <- fromException f = pure [pretty (show e)]
| otherwise = error $ "Unrecognized frame: " ++ show f
2018-04-25 08:09:43 +02:00
wrapExpr :: NExprF r -> NExpr
wrapExpr x = Fix (Fix (NSym "<?>") <$ x)
renderEvalFrame :: (MonadReader e m, Has e Options, MonadFile m)
2018-11-17 05:51:18 +01:00
=> NixLevel -> EvalFrame m v -> m [Doc ann]
renderEvalFrame level f = do
opts :: Options <- asks (view hasLens)
case f of
EvaluatingExpr scope e@(Fix (Compose (Ann ann _))) -> do
2018-11-17 05:51:18 +01:00
let scopeInfo | scopes opts = [pretty $ show scope]
| otherwise = []
fmap (\x -> scopeInfo ++ [x]) $ renderLocation ann
=<< renderExpr level "While evaluating" "Expression" e
ForcingExpr _scope e@(Fix (Compose (Ann ann _)))
| thunks opts ->
fmap (:[]) $ renderLocation ann
=<< renderExpr level "While forcing thunk from"
"Forcing thunk" e
2018-05-06 09:35:21 +02:00
Calling name ann ->
fmap (:[]) $ renderLocation ann $
2018-11-17 05:51:18 +01:00
"While calling builtins." <> pretty name
2018-05-06 09:35:21 +02:00
2018-11-18 00:20:59 +01:00
SynHole synfo -> sequence $
let e@(Fix (Compose (Ann ann _))) = _synHoleInfo_expr synfo
in [ renderLocation ann =<<
renderExpr level "While evaluating" "Syntactic Hole" e
2019-03-10 18:41:31 +01:00
, pure $ pretty $ show (_synHoleInfo_scope synfo)
2018-11-18 00:20:59 +01:00
]
ForcingExpr _ _ -> pure []
renderExpr :: (MonadReader e m, Has e Options, MonadFile m)
2018-11-17 05:51:18 +01:00
=> NixLevel -> String -> String -> NExprLoc -> m (Doc ann)
renderExpr _level longLabel shortLabel e@(Fix (Compose (Ann _ x))) = do
opts :: Options <- asks (view hasLens)
let rendered
| verbose opts >= DebugInfo =
2018-05-13 23:17:55 +02:00
#ifdef MIN_VERSION_pretty_show
2018-11-17 05:51:18 +01:00
pretty (PS.ppShow (stripAnnotation e))
#else
2018-11-17 05:51:18 +01:00
pretty (show (stripAnnotation e))
#endif
| verbose opts >= Chatty =
prettyNix (stripAnnotation e)
| otherwise =
prettyNix (Fix (Fix (NSym "<?>") <$ x))
pure $ if verbose opts >= Chatty
2018-11-17 05:51:18 +01:00
then vsep $
[ pretty (longLabel ++ ":\n>>>>>>>>")
, indent 2 rendered
, "<<<<<<<<"
]
else pretty shortLabel <> fillSep [": ", rendered]
renderValueFrame
:: ( MonadReader e m
, Has e Options
, MonadFile m
, MonadCitedThunks t f m
)
=> NixLevel -> ValueFrame t f m -> m [Doc ann]
2018-08-05 01:05:01 +02:00
renderValueFrame level = fmap (:[]) . \case
2018-11-17 05:51:18 +01:00
ForcingThunk -> pure "ForcingThunk"
ConcerningValue _v -> pure "ConcerningValue"
Comparison _ _ -> pure "Comparing"
Addition _ _ -> pure "Adding"
Division _ _ -> pure "Dividing"
Multiplication _ _ -> pure "Multiplying"
Coercion x y -> pure $ mconcat
[ desc
, pretty (describeValue x)
, " to "
, pretty (describeValue y)
]
where
desc | level <= Error = "Cannot coerce "
| otherwise = "While coercing "
CoercionToJson v -> do
v' <- renderValue level "" "" v
pure $ "CoercionToJson " <> v'
2018-11-17 05:51:18 +01:00
CoercionFromJson _j -> pure "CoercionFromJson"
ExpectationNF _t _v -> pure "ExpectationNF"
2018-08-05 01:05:01 +02:00
Expectation t v -> do
v' <- renderValue level "" "" v
2018-11-17 05:51:18 +01:00
pure $ "Saw " <> v'
<> " but expected " <> pretty (describeValue t)
renderValue
:: ( MonadReader e m
, Has e Options
, MonadFile m
, MonadCitedThunks t f m
)
=> NixLevel -> String -> String -> NValue t f m -> m (Doc ann)
renderValue _level _longLabel _shortLabel v = do
opts :: Options <- asks (view hasLens)
if values opts
then prettyNValueProv v
else prettyNValue v
renderExecFrame
:: ( MonadReader e m
, Has e Options
, MonadFile m
, MonadCitedThunks t f m
)
=> NixLevel -> ExecFrame t f m -> m [Doc ann]
renderExecFrame level = \case
Assertion ann v ->
fmap (:[]) $ renderLocation ann
2018-11-17 05:51:18 +01:00
=<< ((\d -> fillSep ["Assertion failed:", d])
<$> renderValue level "" "" v)
renderThunkLoop
:: (MonadReader e m, Has e Options, MonadFile m, Show (ThunkId m))
=> NixLevel -> ThunkLoop -> m [Doc ann]
renderThunkLoop _level = pure . (:[]) . \case
ThunkLoop n -> pretty $ "Infinite recursion in thunk " ++ n
2018-08-05 21:48:52 +02:00
renderNormalLoop
:: ( MonadReader e m
, Has e Options
, MonadFile m
, MonadCitedThunks t f m
)
=> NixLevel -> NormalLoop t f m -> m [Doc ann]
2018-08-05 21:48:52 +02:00
renderNormalLoop level = fmap (:[]) . \case
NormalLoop v -> do
v' <- renderValue level "" "" v
2018-11-25 04:09:28 +01:00
pure $ "Infinite recursion during normalization forcing " <> v'