@@ -8,22 +8,23 @@ module Main ( main ) where
88
99import Nix.Utils
1010import Control.Comonad ( extract )
11- import qualified Control.DeepSeq as Deep
12- import qualified Control.Exception as Exc
11+ import qualified Control.Exception as Exception
1312import GHC.Err ( errorWithoutStackTrace )
1413import Control.Monad.Free
1514import Control.Monad.Ref ( MonadRef (readRef ) )
1615import Control.Monad.Catch
17- import System.IO ( hPutStrLn , getContents )
16+ import System.IO ( hPutStrLn
17+ , getContents
18+ )
1819import qualified Data.HashMap.Lazy as M
1920import qualified Data.Map as Map
2021import Data.Maybe ( fromJust )
2122import qualified Data.String as String
2223import Data.Time
2324import qualified Data.Text.IO as Text
24- import Nix
25+ import Text.Show.Pretty ( ppShow )
26+ import Nix hiding ( force )
2527import Nix.Convert
26- import qualified Nix.Eval as Eval
2728import Nix.Fresh.Basic
2829import Nix.Json
2930import Nix.Options.Parser
@@ -35,11 +36,10 @@ import qualified Nix.Type.Infer as HM
3536import Nix.Value.Monad
3637import Options.Applicative hiding ( ParserResult (.. ) )
3738import Prettyprinter hiding ( list )
38- import Prettyprinter.Render.Text
39+ import Prettyprinter.Render.Text ( renderIO )
3940import qualified Repl
4041import System.FilePath
41- import qualified Text.Show.Pretty as PS
42- import Nix.Utils.Fix1 ( Fix1T )
42+ import Nix.Eval
4343
4444main :: IO ()
4545main =
@@ -50,45 +50,65 @@ main =
5050 main' opts
5151
5252main' :: Options -> IO ()
53- main' ( opts@ Options {.. }) = runWithBasicEffectsIO opts execContentsFilesOrRepl
53+ main' opts@ Options {.. } = runWithBasicEffectsIO opts execContentsFilesOrRepl
5454 where
55+ -- 2021-07-15: NOTE: This logic should be weaved stronger through CLI options logic (OptParse-Applicative code)
56+ -- As this logic is not stated in the CLI documentation, for example. So user has no knowledge of these.
57+ execContentsFilesOrRepl :: StandardT (StdIdT IO ) ()
5558 execContentsFilesOrRepl =
56- firstJust
57- -- The `--read` option: load expression from a serialized file.
58- [ readFrom <&> \ path -> do
59- let file = addExtension (dropExtension path) " nixc"
60- process (Just file) =<< liftIO (readCache path)
59+ fromMaybe
60+ loadFromCLIFilePathList
61+ ( loadBinaryCacheFile <|>
62+ loadLiteralExpression <|>
63+ loadExpressionFromFile
64+ )
65+ where
66+ -- | The base case: read expressions from the last CLI directive (@[FILE]@) listed on the command line.
67+ loadFromCLIFilePathList =
68+ case filePaths of
69+ [] -> runRepl
70+ [" -" ] -> readExpressionFromStdin
71+ _paths -> processSeveralFiles _paths
72+ where
73+ -- | Fall back to running the REPL
74+ runRepl = withEmptyNixContext Repl. main
6175
62- -- The `--expr` option: read expression from the argument string
63- , expression <&> processText
76+ readExpressionFromStdin =
77+ do
78+ expr <- liftIO Text. getContents
79+ processExpr expr
6480
65- -- The `--file` argument: read expressions from the files listed in the argument file
66- , fromFile <&> \ x ->
67- -- We can start use Text as in the base case, requires changing FilePath -> Text
68- traverse_ processFile . String. lines =<< liftIO
69- (case x of
70- " -" -> getContents
71- fp -> readFile fp
72- )
73- ]
74- `orElse`
75- -- The base case: read expressions from the files listed on the command line
76- case filePaths of
77- -- With no files, fall back to running the REPL
78- [] -> withNixContext mempty Repl. main
79- [" -" ] -> processText =<< liftIO Text. getContents
80- _paths -> traverse_ processFile _paths
81+ processSeveralFiles files = traverse_ processFile files
82+ where
83+ processFile path = handleResult (pure path) =<< parseNixFileLoc path
8184
82- firstJust :: [Maybe a ] -> Maybe a
83- firstJust = asum
85+ -- | The `--read` option: load expression from a serialized file.
86+ loadBinaryCacheFile =
87+ (\ binaryCacheFile ->
88+ do
89+ let file = replaceExtension binaryCacheFile " nixc"
90+ processCLIOptions (Just file) =<< liftIO (readCache binaryCacheFile)
91+ ) <$> readFrom
92+
93+ -- | The `--expr` option: read expression from the argument string
94+ loadLiteralExpression = processExpr <$> expression
8495
85- orElse :: Maybe a -> a -> a
86- orElse = flip fromMaybe
96+ -- | The `--file` argument: read expressions from the files listed in the argument file
97+ loadExpressionFromFile =
98+ -- We can start use Text as in the base case, requires changing FilePath -> Text
99+ -- But that is a gradual process:
100+ -- https://github.com/haskell-nix/hnix/issues/912
101+ (processSeveralFiles . String. lines <=< liftIO) .
102+ (\ case
103+ " -" -> getContents
104+ _fp -> readFile _fp
105+ ) <$> fromFile
87106
88- processText text = handleResult Nothing $ parseNixTextLoc text
107+ processExpr text = handleResult Nothing $ parseNixTextLoc text
89108
90- processFile path = handleResult ( Just path) =<< parseNixFileLoc path
109+ withEmptyNixContext = withNixContext mempty
91110
111+ -- 2021-07-15: NOTE: @handleResult@ & @process@ - have atrocious size & compexity, they need to be decomposed & refactored.
92112 handleResult mpath =
93113 either
94114 (\ err ->
@@ -103,18 +123,18 @@ main' (opts@Options{..}) = runWithBasicEffectsIO opts execContentsFilesOrRepl
103123 do
104124 when check $
105125 do
106- expr' <- liftIO ( reduceExpr mpath expr)
126+ expr' <- liftIO $ reduceExpr mpath expr
107127 either
108- (\ err -> errorWithoutStackTrace $ " Type error: " <> PS. ppShow err)
109- (\ ty -> liftIO $ putStrLn $ " Type of expression: " <> PS. ppShow
110- (fromJust $ Map. lookup " it" (coerce ty :: Map Text [ Scheme ] ))
128+ (\ err -> errorWithoutStackTrace $ " Type error: " <> ppShow err)
129+ (\ ty -> liftIO $ putStrLn $ " Type of expression: " <>
130+ ppShow (fromJust $ Map. lookup @ VarName @ [ Scheme ] " it" (coerce ty))
111131 )
112132 (HM. inferTop mempty [(" it" , stripAnnotation expr')])
113133
114134 -- liftIO $ putStrLn $ runST $
115135 -- runLintM opts . renderSymbolic =<< lint opts expr
116136
117- catch (process mpath expr) $
137+ catch (processCLIOptions mpath expr) $
118138 \ case
119139 NixException frames ->
120140 errorWithoutStackTrace . show =<<
@@ -124,50 +144,64 @@ main' (opts@Options{..}) = runWithBasicEffectsIO opts execContentsFilesOrRepl
124144 frames
125145
126146 when repl $
127- withNixContext mempty $
147+ withEmptyNixContext $
128148 bool
129149 Repl. main
130150 (do
131- val <- Nix. nixEvalExprLoc mpath expr
151+ val <- nixEvalExprLoc mpath expr
132152 Repl. main' $ pure val
133153 )
134154 evaluate
135155 )
136156
137- process mpath expr
157+ -- 2021-07-15: NOTE: Logic of CLI Option processing is scattered over several functions, needs to be consolicated.
158+ processCLIOptions :: Maybe FilePath -> NExprLoc -> StandardT (StdIdT IO ) ()
159+ processCLIOptions mpath expr
138160 | evaluate =
139161 if
140- | tracing -> evaluateExpression mpath Nix. nixTracingEvalExprLoc printer expr
141- | Just path <- reduce -> evaluateExpression mpath (reduction path) printer expr
142- | not ( null arg && null argstr) -> evaluateExpression mpath Nix. nixEvalExprLoc printer expr
143- | otherwise -> processResult printer =<< Nix. nixEvalExprLoc mpath expr
144- | xml = fail " Rendering expression trees to XML is not yet implemented"
145- | json = fail " Rendering expression trees to JSON is not implemented"
146- | verbose >= DebugInfo = liftIO $ putStr $ PS. ppShow $ stripAnnotation expr
147- | cache , Just path <- mpath = liftIO $ writeCache (addExtension (dropExtension path) " nixc" ) expr
148- | parseOnly = void $ liftIO $ Exc . evaluate $ Deep. force expr
162+ | tracing -> evaluateExprWithEvaluator nixTracingEvalExprLoc expr
163+ | Just path <- reduce -> evaluateExprWithEvaluator (reduction path) expr
164+ | null arg || null argstr -> evaluateExprWithEvaluator nixEvalExprLoc expr
165+ | otherwise -> processResult printer <=< nixEvalExprLoc mpath $ expr
166+ | xml = fail " Rendering expression trees to XML is not yet implemented"
167+ | json = fail " Rendering expression trees to JSON is not implemented"
168+ | verbose >= DebugInfo = liftIO . putStr . ppShow . stripAnnotation $ expr
169+ | cache , Just path <- mpath = liftIO . writeCache (replaceExtension path " nixc" ) $ expr
170+ | parseOnly = void . liftIO . Exception . evaluate . force $ expr
149171 | otherwise =
150- liftIO $
172+ liftIO .
151173 renderIO
152174 stdout
153175 . layoutPretty (LayoutOptions $ AvailablePerLine 80 0.4 )
154176 . prettyNix
155177 . stripAnnotation
156178 $ expr
157179 where
180+ evaluateExprWithEvaluator evaluator = evaluateExpression mpath evaluator printer
181+
158182 printer
159183 | finder = findAttrs <=< fromValue @ (AttrSet (StdValue (StandardT (StdIdT IO ))))
160- | xml = liftIO . Text. putStrLn . stringIgnoreContext . toXML <=< normalForm
161- -- 2021-05-27: NOTE: With naive fix of the #941
162- -- This is overall a naive printer implementation, as options should interact/respect one another.
163- -- A nice question: "Should respect one another to what degree?": Go full combinator way, for which
164- -- old Nix CLI is nototrious for (and that would mean to reimplement the old Nix CLI),
165- -- OR: https://github.com/haskell-nix/hnix/issues/172 and have some sane standart/default behaviour for (most) keys.
166- | json = liftIO . Text. putStrLn . stringIgnoreContext <=< nvalueToJSONNixString <=< normalForm
167- | strict = liftIO . print . prettyNValue <=< normalForm
168- | values = liftIO . print . prettyNValueProv <=< removeEffects
169- | otherwise = liftIO . print . prettyNValue <=< removeEffects
184+ | otherwise = printer'
170185 where
186+ printer'
187+ | xml = go (stringIgnoreContext . toXML) normalForm
188+ -- 2021-05-27: NOTE: With naive fix of the #941
189+ -- This is overall a naive printer implementation, as options should interact/respect one another.
190+ -- A nice question: "Should respect one another to what degree?": Go full combinator way, for which
191+ -- old Nix CLI is nototrious for (and that would mean to reimplement the old Nix CLI),
192+ -- OR: https://github.com/haskell-nix/hnix/issues/172 and have some sane standart/default behaviour for (most) keys.
193+ | json = go (stringIgnoreContext . mempty . nvalueToJSONNixString) normalForm
194+ | strict = go (show . prettyNValue) normalForm
195+ | values = go (show . prettyNValueProv) removeEffects
196+ | otherwise = go (show . prettyNValue) removeEffects
197+ where
198+ go
199+ :: (b -> Text )
200+ -> (a -> StandardT (StdIdT IO ) b )
201+ -> a
202+ -> StandardT (StdIdT IO ) ()
203+ go g f = liftIO . Text. putStrLn . g <=< f
204+
171205 findAttrs
172206 :: AttrSet (StdValue (StandardT (StdIdT IO )))
173207 -> StandardT (StdIdT IO ) ()
@@ -200,7 +234,7 @@ main' (opts@Options{..}) = runWithBasicEffectsIO opts execContentsFilesOrRepl
200234 (pure . pure . Free )
201235 nv
202236 )
203- (sortWith fst $ M. toList s)
237+ (sortWith fst $ M. toList $ M. mapKeys coerce s)
204238 traverse_
205239 (\ (k, mv) ->
206240 do
@@ -214,7 +248,7 @@ main' (opts@Options{..}) = runWithBasicEffectsIO opts execContentsFilesOrRepl
214248 maybe
215249 pass
216250 (\ case
217- NVSet s' _ -> go (path <> " ." ) s'
251+ NVSet _ s' -> go (path <> " ." ) s'
218252 _ -> pass
219253 )
220254 mv
@@ -239,10 +273,10 @@ main' (opts@Options{..}) = runWithBasicEffectsIO opts execContentsFilesOrRepl
239273 _ -> (True , True )
240274
241275 forceEntry
242- :: MonadValue a (Fix1T StandardTF (StdIdT IO ))
276+ :: MonadValue a (StandardT (StdIdT IO ))
243277 => Text
244278 -> a
245- -> Fix1T StandardTF (StdIdT IO ) (Maybe a )
279+ -> StandardT (StdIdT IO ) (Maybe a )
246280 forceEntry k v =
247281 catch
248282 (pure <$> demand v)
@@ -259,15 +293,15 @@ main' (opts@Options{..}) = runWithBasicEffectsIO opts execContentsFilesOrRepl
259293 pure Nothing
260294 )
261295
262- reduction path mp x =
296+ reduction path mpathToContext annExpr =
263297 do
264298 eres <-
265- Nix. withNixContext
266- mp
267- (Nix. reducingEvalExpr
268- Eval. evalContent
269- mp
270- x
299+ withNixContext
300+ mpathToContext
301+ (reducingEvalExpr
302+ evalContent
303+ mpathToContext
304+ annExpr
271305 )
272306 handleReduced path eres
273307
0 commit comments