2018-04-14 05:29:18 +03:00
|
|
|
{-# LANGUAGE FlexibleContexts #-}
|
2018-04-06 07:10:06 +03:00
|
|
|
{-# LANGUAGE LambdaCase #-}
|
2018-04-12 07:31:48 +03:00
|
|
|
{-# LANGUAGE OverloadedStrings #-}
|
2018-04-14 05:29:18 +03:00
|
|
|
{-# LANGUAGE ScopedTypeVariables #-}
|
2018-04-30 20:41:21 +03:00
|
|
|
{-# LANGUAGE TupleSections #-}
|
2018-04-25 23:00:41 +03:00
|
|
|
{-# LANGUAGE TypeApplications #-}
|
2019-03-11 23:55:40 +03:00
|
|
|
{-# LANGUAGE TypeFamilies #-}
|
2019-03-18 04:43:23 +03:00
|
|
|
{-# LANGUAGE ViewPatterns #-}
|
2018-03-30 01:35:12 +03:00
|
|
|
|
2015-06-24 00:53:07 +03:00
|
|
|
module Main where
|
|
|
|
|
2019-03-18 04:43:23 +03:00
|
|
|
import Control.Comonad ( extract )
|
2019-03-18 00:47:38 +03:00
|
|
|
import qualified Control.DeepSeq as Deep
|
|
|
|
import qualified Control.Exception as Exc
|
2018-04-04 00:21:33 +03:00
|
|
|
import Control.Monad
|
2018-04-21 08:36:40 +03:00
|
|
|
import Control.Monad.Catch
|
2019-03-19 03:04:11 +03:00
|
|
|
import Control.Monad.Free
|
2018-04-14 05:29:18 +03:00
|
|
|
import Control.Monad.IO.Class
|
2021-03-06 19:39:21 +03:00
|
|
|
import Data.Foldable ( traverse_ )
|
2019-03-18 00:47:38 +03:00
|
|
|
import qualified Data.HashMap.Lazy as M
|
|
|
|
import qualified Data.Map as Map
|
|
|
|
import Data.List ( sortOn )
|
|
|
|
import Data.Maybe ( fromJust )
|
2018-05-03 07:32:00 +03:00
|
|
|
import Data.Time
|
2019-03-18 00:47:38 +03:00
|
|
|
import qualified Data.Text as Text
|
|
|
|
import qualified Data.Text.IO as Text
|
2018-04-14 19:44:55 +03:00
|
|
|
import Nix
|
2018-04-18 00:24:52 +03:00
|
|
|
import Nix.Convert
|
2019-03-18 00:47:38 +03:00
|
|
|
import qualified Nix.Eval as Eval
|
2019-03-23 10:56:40 +03:00
|
|
|
import Nix.Fresh.Basic
|
2018-12-09 21:57:58 +03:00
|
|
|
import Nix.Json
|
2018-05-09 02:40:56 +03:00
|
|
|
import Nix.Options.Parser
|
2019-03-23 01:16:01 +03:00
|
|
|
import Nix.Standard
|
2019-03-11 18:04:15 +03:00
|
|
|
import Nix.Thunk.Basic
|
2019-03-18 00:47:38 +03:00
|
|
|
import qualified Nix.Type.Env as Env
|
|
|
|
import qualified Nix.Type.Infer as HM
|
2018-04-18 00:24:52 +03:00
|
|
|
import Nix.Utils
|
2019-03-11 18:04:15 +03:00
|
|
|
import Nix.Var
|
2019-03-19 03:04:11 +03:00
|
|
|
import Nix.Value.Monad
|
2019-03-18 00:47:38 +03:00
|
|
|
import Options.Applicative hiding ( ParserResult(..) )
|
2021-03-06 20:34:16 +03:00
|
|
|
import Prettyprinter hiding ( list )
|
2020-08-04 07:25:57 +03:00
|
|
|
import Prettyprinter.Render.Text
|
2018-04-18 00:24:52 +03:00
|
|
|
import qualified Repl
|
2018-04-12 00:35:17 +03:00
|
|
|
import System.FilePath
|
2018-04-18 00:24:52 +03:00
|
|
|
import System.IO
|
2019-03-18 00:47:38 +03:00
|
|
|
import qualified Text.Show.Pretty as PS
|
2015-06-24 00:53:07 +03:00
|
|
|
|
|
|
|
main :: IO ()
|
|
|
|
main = do
|
2019-03-18 07:58:35 +03:00
|
|
|
time <- getCurrentTime
|
2019-03-18 00:47:38 +03:00
|
|
|
opts <- execParser (nixOptionsInfo time)
|
2021-03-06 20:34:16 +03:00
|
|
|
|
|
|
|
runWithBasicEffectsIO opts $ execContentsFilesOrRepl opts
|
|
|
|
|
|
|
|
where
|
|
|
|
execContentsFilesOrRepl opts =
|
2021-03-06 19:52:34 +03:00
|
|
|
maybe
|
|
|
|
(maybe
|
|
|
|
(maybe
|
|
|
|
(list
|
2021-03-06 20:34:16 +03:00
|
|
|
(withNixContext mempty Repl.main) -- run REPL
|
2021-03-06 19:52:34 +03:00
|
|
|
(\case
|
2021-03-06 20:34:16 +03:00
|
|
|
["-"] -> handleResult opts mempty . parseNixTextLoc =<< liftIO Text.getContents
|
2021-03-06 19:52:34 +03:00
|
|
|
_paths -> traverse_ (processFile opts) _paths
|
|
|
|
)
|
|
|
|
(filePaths opts)
|
|
|
|
)
|
2021-03-06 20:34:16 +03:00
|
|
|
(\ x ->
|
|
|
|
-- use Text as in the base case, requires changing FilePath -> Text
|
|
|
|
traverse_ (processFile opts) . lines =<< liftIO
|
|
|
|
(case x of
|
|
|
|
"-" -> getContents -- get user input
|
|
|
|
_path -> readFile _path
|
|
|
|
)
|
2021-03-06 19:52:34 +03:00
|
|
|
)
|
|
|
|
(fromFile opts)
|
|
|
|
)
|
|
|
|
(handleResult opts mempty . parseNixTextLoc)
|
|
|
|
(expression opts)
|
|
|
|
)
|
|
|
|
(\ path ->
|
|
|
|
do
|
|
|
|
let file = addExtension (dropExtension path) "nixc"
|
|
|
|
process opts (pure file) =<< liftIO (readCache path)
|
|
|
|
)
|
|
|
|
(readFrom opts)
|
2021-03-06 20:34:16 +03:00
|
|
|
|
2019-03-18 00:47:38 +03:00
|
|
|
processFile opts path = do
|
|
|
|
eres <- parseNixFileLoc path
|
2021-02-10 12:00:36 +03:00
|
|
|
handleResult opts (pure path) eres
|
2019-03-18 00:47:38 +03:00
|
|
|
|
|
|
|
handleResult opts mpath = \case
|
|
|
|
Failure err ->
|
2021-02-26 15:11:24 +03:00
|
|
|
bool
|
2021-02-25 20:42:09 +03:00
|
|
|
errorWithoutStackTrace
|
|
|
|
(liftIO . hPutStrLn stderr)
|
|
|
|
(ignoreErrors opts)
|
2021-02-26 15:11:24 +03:00
|
|
|
$ "Parse failed: " <> show err
|
2019-03-18 00:47:38 +03:00
|
|
|
|
|
|
|
Success expr -> do
|
|
|
|
when (check opts) $ do
|
|
|
|
expr' <- liftIO (reduceExpr mpath expr)
|
2021-02-25 20:42:09 +03:00
|
|
|
either
|
|
|
|
(\ err -> errorWithoutStackTrace $ "Type error: " <> PS.ppShow err)
|
|
|
|
(\ ty -> liftIO $ putStrLn $ "Type of expression: " <> PS.ppShow
|
|
|
|
(fromJust $ Map.lookup "it" $ Env.types ty)
|
|
|
|
)
|
|
|
|
(HM.inferTop Env.empty [("it", stripAnnotation expr')])
|
2019-03-18 00:47:38 +03:00
|
|
|
|
|
|
|
-- liftIO $ putStrLn $ runST $
|
|
|
|
-- runLintM opts . renderSymbolic =<< lint opts expr
|
|
|
|
|
|
|
|
catch (process opts mpath expr) $ \case
|
|
|
|
NixException frames ->
|
|
|
|
errorWithoutStackTrace
|
|
|
|
. show
|
2019-03-23 10:56:40 +03:00
|
|
|
=<< renderFrames @(StdValue (StandardT (StdIdT IO)))
|
|
|
|
@(StdThunk (StandardT (StdIdT IO)))
|
2019-03-23 01:16:01 +03:00
|
|
|
frames
|
2019-03-18 00:47:38 +03:00
|
|
|
|
2020-06-30 15:13:47 +03:00
|
|
|
when (repl opts) $
|
2021-02-25 20:42:09 +03:00
|
|
|
withNixContext mempty $
|
|
|
|
bool
|
|
|
|
Repl.main
|
|
|
|
(do
|
|
|
|
val <- Nix.nixEvalExprLoc mpath expr
|
|
|
|
Repl.main' $ pure val
|
|
|
|
)
|
|
|
|
(evaluate opts)
|
2019-03-18 00:47:38 +03:00
|
|
|
|
|
|
|
process opts mpath expr
|
|
|
|
| evaluate opts
|
|
|
|
, tracing opts
|
|
|
|
= evaluateExpression mpath Nix.nixTracingEvalExprLoc printer expr
|
|
|
|
| evaluate opts
|
|
|
|
, Just path <- reduce opts
|
|
|
|
= evaluateExpression mpath (reduction path) printer expr
|
|
|
|
| evaluate opts
|
|
|
|
, not (null (arg opts) && null (argstr opts))
|
|
|
|
= evaluateExpression mpath Nix.nixEvalExprLoc printer expr
|
|
|
|
| evaluate opts
|
|
|
|
= processResult printer =<< Nix.nixEvalExprLoc mpath expr
|
|
|
|
| xml opts
|
|
|
|
= error "Rendering expression trees to XML is not yet implemented"
|
|
|
|
| json opts
|
2020-08-19 00:26:35 +03:00
|
|
|
= error "Rendering expression trees to JSON is not implemented"
|
2019-03-18 00:47:38 +03:00
|
|
|
| verbose opts >= DebugInfo
|
|
|
|
= liftIO $ putStr $ PS.ppShow $ stripAnnotation expr
|
|
|
|
| cache opts
|
|
|
|
, Just path <- mpath
|
|
|
|
= liftIO $ writeCache (addExtension (dropExtension path) "nixc") expr
|
|
|
|
| parseOnly opts
|
|
|
|
= void $ liftIO $ Exc.evaluate $ Deep.force expr
|
|
|
|
| otherwise
|
|
|
|
= liftIO
|
|
|
|
$ renderIO stdout
|
|
|
|
. layoutPretty (LayoutOptions $ AvailablePerLine 80 0.4)
|
|
|
|
. prettyNix
|
|
|
|
. stripAnnotation
|
|
|
|
$ expr
|
|
|
|
where
|
|
|
|
printer
|
|
|
|
| finder opts
|
2019-03-23 10:56:40 +03:00
|
|
|
= fromValue @(AttrSet (StdValue (StandardT (StdIdT IO)))) >=> findAttrs
|
2019-03-18 00:47:38 +03:00
|
|
|
| xml opts
|
|
|
|
= liftIO
|
|
|
|
. putStrLn
|
|
|
|
. Text.unpack
|
2021-01-07 05:34:11 +03:00
|
|
|
. stringIgnoreContext
|
2019-03-18 00:47:38 +03:00
|
|
|
. toXML
|
|
|
|
<=< normalForm
|
|
|
|
| json opts
|
|
|
|
= liftIO
|
|
|
|
. Text.putStrLn
|
2021-01-07 05:34:11 +03:00
|
|
|
. stringIgnoreContext
|
2019-03-18 00:47:38 +03:00
|
|
|
<=< nvalueToJSONNixString
|
|
|
|
| strict opts
|
2019-03-27 07:21:12 +03:00
|
|
|
= liftIO . print . prettyNValue <=< normalForm
|
2019-03-18 00:47:38 +03:00
|
|
|
| values opts
|
2019-03-27 07:21:12 +03:00
|
|
|
= liftIO . print . prettyNValueProv <=< removeEffects
|
2019-03-18 00:47:38 +03:00
|
|
|
| otherwise
|
2019-03-27 07:21:12 +03:00
|
|
|
= liftIO . print . prettyNValue <=< removeEffects
|
2019-03-18 00:47:38 +03:00
|
|
|
where
|
2019-03-27 07:21:12 +03:00
|
|
|
findAttrs
|
|
|
|
:: AttrSet (StdValue (StandardT (StdIdT IO)))
|
|
|
|
-> StandardT (StdIdT IO) ()
|
2021-02-25 20:42:09 +03:00
|
|
|
findAttrs = go mempty
|
2019-03-18 00:47:38 +03:00
|
|
|
where
|
|
|
|
go prefix s = do
|
2021-02-25 20:42:09 +03:00
|
|
|
xs <- forM (sortOn fst (M.toList s)) $ \(k, nv) ->
|
|
|
|
free
|
|
|
|
(\ (StdThunk (extract -> Thunk _ _ ref)) -> do
|
|
|
|
let path = prefix <> Text.unpack k
|
|
|
|
(_, descend) = filterEntry path k
|
|
|
|
val <- readVar @(StandardT (StdIdT IO)) ref
|
|
|
|
case val of
|
|
|
|
Computed _ -> pure (k, Nothing)
|
2021-02-26 18:36:47 +03:00
|
|
|
_ | descend -> (k, ) <$> forceEntry path nv
|
2021-02-25 20:42:09 +03:00
|
|
|
| otherwise -> pure (k, Nothing)
|
|
|
|
)
|
|
|
|
(\ v -> pure (k, pure (Free v)))
|
|
|
|
nv
|
2019-03-18 00:47:38 +03:00
|
|
|
forM_ xs $ \(k, mv) -> do
|
2021-02-10 10:55:04 +03:00
|
|
|
let path = prefix <> Text.unpack k
|
2019-03-18 00:47:38 +03:00
|
|
|
(report, descend) = filterEntry path k
|
|
|
|
when report $ do
|
|
|
|
liftIO $ putStrLn path
|
2021-02-25 20:42:09 +03:00
|
|
|
when descend $
|
|
|
|
maybe
|
|
|
|
(pure ())
|
|
|
|
(\case
|
|
|
|
NVSet s' _ -> go (path <> ".") s'
|
|
|
|
_ -> pure ()
|
|
|
|
)
|
|
|
|
mv
|
2019-03-18 00:47:38 +03:00
|
|
|
where
|
|
|
|
filterEntry path k = case (path, k) of
|
|
|
|
("stdenv", "stdenv" ) -> (True, True)
|
|
|
|
(_ , "stdenv" ) -> (False, False)
|
|
|
|
(_ , "out" ) -> (True, False)
|
|
|
|
(_ , "src" ) -> (True, False)
|
|
|
|
(_ , "mirrorsFile" ) -> (True, False)
|
|
|
|
(_ , "buildPhase" ) -> (True, False)
|
|
|
|
(_ , "builder" ) -> (False, False)
|
|
|
|
(_ , "drvPath" ) -> (False, False)
|
|
|
|
(_ , "outPath" ) -> (False, False)
|
|
|
|
(_ , "__impureHostDeps") -> (False, False)
|
|
|
|
(_ , "__sandboxProfile") -> (False, False)
|
|
|
|
("pkgs" , "pkgs" ) -> (True, True)
|
|
|
|
(_ , "pkgs" ) -> (False, False)
|
|
|
|
(_ , "drvAttrs" ) -> (False, False)
|
|
|
|
_ -> (True, True)
|
|
|
|
|
|
|
|
forceEntry k v =
|
2021-03-05 01:02:30 +03:00
|
|
|
catch (pure <$> (pure =<< demand v)) $ \(NixException frames) ->
|
|
|
|
do
|
|
|
|
liftIO
|
|
|
|
. putStrLn
|
|
|
|
. ("Exception forcing " <>)
|
|
|
|
. (k <>)
|
|
|
|
. (": " <>)
|
|
|
|
. show
|
|
|
|
=<< renderFrames @(StdValue (StandardT (StdIdT IO)))
|
|
|
|
@(StdThunk (StandardT (StdIdT IO)))
|
|
|
|
frames
|
|
|
|
pure Nothing
|
2019-03-18 00:47:38 +03:00
|
|
|
|
|
|
|
reduction path mp x = do
|
|
|
|
eres <- Nix.withNixContext mp
|
|
|
|
$ Nix.reducingEvalExpr (Eval.eval . annotated . getCompose) mp x
|
|
|
|
handleReduced path eres
|
|
|
|
|
|
|
|
handleReduced
|
|
|
|
:: (MonadThrow m, MonadIO m)
|
|
|
|
=> FilePath
|
|
|
|
-> (NExprLoc, Either SomeException (NValue t f m))
|
|
|
|
-> m (NValue t f m)
|
|
|
|
handleReduced path (expr', eres) = do
|
|
|
|
liftIO $ do
|
2021-02-10 10:55:04 +03:00
|
|
|
putStrLn $ "Wrote winnowed expression tree to " <> path
|
2019-03-18 00:47:38 +03:00
|
|
|
writeFile path $ show $ prettyNix (stripAnnotation expr')
|
2021-02-25 20:42:09 +03:00
|
|
|
either
|
|
|
|
throwM
|
|
|
|
pure
|
|
|
|
eres
|