From eaca31124c25dfaea13a1d3ea44a067f96efd2cd Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Mon, 24 Jan 2022 12:32:25 +0200 Subject: [PATCH 01/70] Value.Equal: compateAttrSetsM: refactor into lambda --- src/Nix/Value/Equal.hs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/Nix/Value/Equal.hs b/src/Nix/Value/Equal.hs index d078e7544..50e2d1770 100644 --- a/src/Nix/Value/Equal.hs +++ b/src/Nix/Value/Equal.hs @@ -141,19 +141,19 @@ compareAttrSetsM -> AttrSet t -> m Bool compareAttrSetsM f eq lm rm = - do - l <- isDerivationM f lm - bool - compareAttrs - (do - r <- isDerivationM f rm - case r of - True - | Just lp <- HashMap.Lazy.lookup "outPath" lm, - Just rp <- HashMap.Lazy.lookup "outPath" rm -> eq lp rp - _ -> compareAttrs - ) - l + bool + compareAttrs + ( bool + compareAttrs + (fromMaybe + compareAttrs + $ liftA2 eq + (HashMap.Lazy.lookup "outPath" lm) + (HashMap.Lazy.lookup "outPath" rm) + ) + =<< isDerivationM f rm + ) + =<< isDerivationM f lm where compareAttrs = alignEqM eq lm rm From f361feafea1c12e9e9a83a7336e6b5acc887b6e0 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Mon, 24 Jan 2022 12:34:45 +0200 Subject: [PATCH 02/70] Value.Equal: compateAttrSetsM: refactor into lambda M src/Nix/Value/Equal.hs --- src/Nix/Value/Equal.hs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Nix/Value/Equal.hs b/src/Nix/Value/Equal.hs index 50e2d1770..dfddbaddd 100644 --- a/src/Nix/Value/Equal.hs +++ b/src/Nix/Value/Equal.hs @@ -147,9 +147,7 @@ compareAttrSetsM f eq lm rm = compareAttrs (fromMaybe compareAttrs - $ liftA2 eq - (HashMap.Lazy.lookup "outPath" lm) - (HashMap.Lazy.lookup "outPath" rm) + $ on (liftA2 eq) (HashMap.Lazy.lookup "outPath") lm rm ) =<< isDerivationM f rm ) From 5741973a5bce14f13781550bb0cf5a78985154cb Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Mon, 24 Jan 2022 12:35:20 +0200 Subject: [PATCH 03/70] Value.Equal: compateAttrSetsM: refactor into lambda --- src/Nix/Value/Equal.hs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/Nix/Value/Equal.hs b/src/Nix/Value/Equal.hs index dfddbaddd..f7b260951 100644 --- a/src/Nix/Value/Equal.hs +++ b/src/Nix/Value/Equal.hs @@ -141,17 +141,16 @@ compareAttrSetsM -> AttrSet t -> m Bool compareAttrSetsM f eq lm rm = - bool - compareAttrs - ( bool + do + l <- isDerivationM f lm + r <- isDerivationM f rm + bool + compareAttrs + (fromMaybe compareAttrs - (fromMaybe - compareAttrs - $ on (liftA2 eq) (HashMap.Lazy.lookup "outPath") lm rm - ) - =<< isDerivationM f rm - ) - =<< isDerivationM f lm + $ on (liftA2 eq) (HashMap.Lazy.lookup "outPath") lm rm + ) + (l && r) where compareAttrs = alignEqM eq lm rm From 43c55ac910044a2d36689f96ff0b31f4917aee14 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Mon, 24 Jan 2022 12:35:57 +0200 Subject: [PATCH 04/70] Value.Equal: compateAttrSetsM: refactor into lambda --- src/Nix/Value/Equal.hs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Nix/Value/Equal.hs b/src/Nix/Value/Equal.hs index f7b260951..048cc76ca 100644 --- a/src/Nix/Value/Equal.hs +++ b/src/Nix/Value/Equal.hs @@ -146,14 +146,17 @@ compareAttrSetsM f eq lm rm = r <- isDerivationM f rm bool compareAttrs - (fromMaybe + (maybe compareAttrs - $ on (liftA2 eq) (HashMap.Lazy.lookup "outPath") lm rm + (uncurry eq) + outPaths ) (l && r) where compareAttrs = alignEqM eq lm rm + outPaths = on (liftA2 (,)) (HashMap.Lazy.lookup "outPath") lm rm + compareAttrSets :: (t -> Maybe NixString) -> (t -> t -> Bool) From 11fdadbfef83f84d743d6bb677588d6234d76d09 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Mon, 24 Jan 2022 12:39:38 +0200 Subject: [PATCH 05/70] Value.Equal: compateAttrSetsM: refactor into lambda --- src/Nix/Value/Equal.hs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Nix/Value/Equal.hs b/src/Nix/Value/Equal.hs index 048cc76ca..89d43f9b5 100644 --- a/src/Nix/Value/Equal.hs +++ b/src/Nix/Value/Equal.hs @@ -142,8 +142,7 @@ compareAttrSetsM -> m Bool compareAttrSetsM f eq lm rm = do - l <- isDerivationM f lm - r <- isDerivationM f rm + (l, r) <- on (liftA2 (,)) (isDerivationM f) lm rm bool compareAttrs (maybe From 18c9c03b26dc83d8f9b50766236c1e0525e6c41a Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Mon, 24 Jan 2022 12:40:35 +0200 Subject: [PATCH 06/70] Value.Equal: compateAttrSetsM: refactor into lambda --- src/Nix/Value/Equal.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Nix/Value/Equal.hs b/src/Nix/Value/Equal.hs index 89d43f9b5..8c123f6b3 100644 --- a/src/Nix/Value/Equal.hs +++ b/src/Nix/Value/Equal.hs @@ -142,7 +142,7 @@ compareAttrSetsM -> m Bool compareAttrSetsM f eq lm rm = do - (l, r) <- on (liftA2 (,)) (isDerivationM f) lm rm + b <- on (liftA2 (&&)) (isDerivationM f) lm rm bool compareAttrs (maybe @@ -150,7 +150,7 @@ compareAttrSetsM f eq lm rm = (uncurry eq) outPaths ) - (l && r) + b where compareAttrs = alignEqM eq lm rm From a9aa57add0e6eaf6bc54e6814e2247f4b94f710d Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Mon, 24 Jan 2022 13:44:33 +0200 Subject: [PATCH 07/70] Value.Equal: isDerivationM: refactor --- src/Nix/Value/Equal.hs | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/Nix/Value/Equal.hs b/src/Nix/Value/Equal.hs index 8c123f6b3..eb34393f6 100644 --- a/src/Nix/Value/Equal.hs +++ b/src/Nix/Value/Equal.hs @@ -73,17 +73,13 @@ isDerivationM -> m Bool isDerivationM f m = maybe - (pure False) - p - (HashMap.Lazy.lookup "type" m) - where - p t = - maybe - -- We should probably really make sure the context is empty here - -- but the C++ implementation ignores it. - False - ((==) "derivation" . ignoreContext) - <$> f t + False + -- (2019-03-18): + -- We should probably really make sure the context is empty here + -- but the C++ implementation ignores it. + ((==) "derivation" . ignoreContext) + . join <$> traverse f (HashMap.Lazy.lookup "type" m) + isDerivation :: Monad m From 0a1e05f2a79c0f360fef498a059b9f13ef9e0cc4 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Mon, 24 Jan 2022 13:47:06 +0200 Subject: [PATCH 08/70] hlint: advise traverse --- .hlint.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.hlint.yaml b/.hlint.yaml index 844c000a3..5d54207cc 100644 --- a/.hlint.yaml +++ b/.hlint.yaml @@ -125,19 +125,19 @@ note: Applying this hint would mean that some actions that were being executed previously would no longer be executed. rhs: orM s - hint: - lhs: "fmap and (mapM f s)" + lhs: "fmap and (traversable f s)" note: Applying this hint would mean that some actions that were being executed previously would no longer be executed. rhs: allM f s - hint: - lhs: "and <$> mapM f s" + lhs: "and <$> traversable f s" note: Applying this hint would mean that some actions that were being executed previously would no longer be executed. rhs: allM f s - hint: - lhs: "fmap or (mapM f s)" + lhs: "fmap or (traversable f s)" note: Applying this hint would mean that some actions that were being executed previously would no longer be executed. rhs: anyM f s - hint: - lhs: "or <$> mapM f s" + lhs: "or <$> traversable f s" note: Applying this hint would mean that some actions that were being executed previously would no longer be executed. rhs: anyM f s - warn: From 2be2103fbe5ebe539e690e472a76bc4b62770e85 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Mon, 24 Jan 2022 13:55:38 +0200 Subject: [PATCH 09/70] hlint: stop advising for{,M}{,_}, use traverse{,_} --- .hlint.yaml | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/.hlint.yaml b/.hlint.yaml index 5d54207cc..ac15e6117 100644 --- a/.hlint.yaml +++ b/.hlint.yaml @@ -1141,15 +1141,14 @@ note: "'foldl'' is already exported from Relude" rhs: "foldl'" - warn: - lhs: Data.Foldable.forM_ - name: "Use 'forM_' from Relude" - note: "'forM_' is already exported from Relude" - rhs: forM_ + lhs: forM_ b a + name: "Use 'traverse_'" + rhs: traverse_ a b - warn: - lhs: Data.Foldable.for_ - name: "Use 'for_' from Relude" + lhs: for_ b a + name: "Use 'traverse_'" note: "'for_' is already exported from Relude" - rhs: for_ + rhs: traverse a b - warn: lhs: Data.Foldable.sequenceA_ name: "Use 'sequenceA_' from Relude" @@ -1161,15 +1160,9 @@ note: "'toList' is already exported from Relude" rhs: toList - warn: - lhs: Data.Foldable.traverse_ - name: "Use 'traverse_' from Relude" - note: "'traverse_' is already exported from Relude" - rhs: traverse_ -- warn: - lhs: Data.Traversable.forM - name: "Use 'forM' from Relude" - note: "'forM' is already exported from Relude" - rhs: forM + lhs: forM b a + name: "Use 'traverse'" + rhs: traverse a b - warn: lhs: Data.Traversable.mapAccumL name: "Use 'mapAccumL' from Relude" From 058a74abe5bdc4b6dc1c3ebebb112f4c1f1d79ac Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Mon, 24 Jan 2022 14:06:20 +0200 Subject: [PATCH 10/70] treewide: stop using for{,M}{,_}, use traverse{,_} --- main/Repl.hs | 23 +++++++++++++---------- src/Nix/Lint.hs | 34 ++++++++++++++++++++-------------- tests/Main.hs | 17 ++++++++++------- 3 files changed, 43 insertions(+), 31 deletions(-) diff --git a/main/Repl.hs b/main/Repl.hs index ae854d075..4b926a79c 100644 --- a/main/Repl.hs +++ b/main/Repl.hs @@ -575,16 +575,19 @@ help :: (MonadNix e t f m, MonadIO m) -> Repl e t f m () help hs _ = do liftIO $ putStrLn "Available commands:\n" - for_ hs $ \h -> - liftIO . - Text.putStrLn . - Prettyprinter.renderStrict . - Prettyprinter.layoutPretty Prettyprinter.defaultLayoutOptions $ - ":" - <> Prettyprinter.pretty (helpOptionName h) <> space - <> helpOptionSyntax h - <> Prettyprinter.line - <> Prettyprinter.indent 4 (helpOptionDoc h) + traverse_ + (\h -> + liftIO . + Text.putStrLn . + Prettyprinter.renderStrict . + Prettyprinter.layoutPretty Prettyprinter.defaultLayoutOptions $ + ":" + <> Prettyprinter.pretty (helpOptionName h) <> space + <> helpOptionSyntax h + <> Prettyprinter.line + <> Prettyprinter.indent 4 (helpOptionDoc h) + ) + hs options :: (MonadNix e t f m, MonadIO m) diff --git a/src/Nix/Lint.hs b/src/Nix/Lint.hs index 3fa34c88c..eee58081e 100644 --- a/src/Nix/Lint.hs +++ b/src/Nix/Lint.hs @@ -460,20 +460,26 @@ lintApp context fun arg = (\case NAny -> throwError $ ErrorCall "Cannot apply something not known to be a function" - NMany xs -> do - (args, ys) <- fmap unzip $ forM xs $ \case - TClosure _params -> - (\case - NAny -> error "NYI" - NMany [TSet (Just _)] -> error "NYI" - NMany _ -> throwError $ ErrorCall "NYI: lintApp NMany not set" - ) =<< unpackSymbolic =<< arg - TBuiltin _ _f -> throwError $ ErrorCall "NYI: lintApp builtin" - TSet _m -> throwError $ ErrorCall "NYI: lintApp Set" - _x -> throwError $ ErrorCall "Attempt to call non-function" - - y <- everyPossible - (Unsafe.head args, ) <$> foldM (unify context) y ys + NMany xs -> + do + (args, ys) <- + unzip <$> + traverse + (\case + TClosure _params -> + (\case + NAny -> error "NYI" + NMany [TSet (Just _)] -> error "NYI" + NMany _ -> throwError $ ErrorCall "NYI: lintApp NMany not set" + ) =<< unpackSymbolic =<< arg + TBuiltin _ _f -> throwError $ ErrorCall "NYI: lintApp builtin" + TSet _m -> throwError $ ErrorCall "NYI: lintApp Set" + _x -> throwError $ ErrorCall "Attempt to call non-function" + ) + xs + + y <- everyPossible + (Unsafe.head args, ) <$> foldM (unify context) y ys ) =<< unpackSymbolic fun newtype Lint s a = Lint diff --git a/tests/Main.hs b/tests/Main.hs index 2baff1548..7f6e52bcf 100644 --- a/tests/Main.hs +++ b/tests/Main.hs @@ -65,13 +65,16 @@ ensureNixpkgsCanParse = when (null files) $ errorWithoutStackTrace $ "Directory " <> show dir <> " does not have any files" - for_ files $ \file -> - unless ("azure-cli/default.nix" `isSuffixOf` file || - "os-specific/linux/udisks/2-default.nix" `isSuffixOf` file) $ do - -- Parse and deepseq the resulting expression tree, to ensure the - -- parser is fully executed. - _ <- consider (coerce file) (parseNixFileLoc (coerce file)) $ Exc.evaluate . force - stub + traverse_ + (\ file -> + unless ("azure-cli/default.nix" `isSuffixOf` file || + "os-specific/linux/udisks/2-default.nix" `isSuffixOf` file) $ do + -- Parse and deepseq the resulting expression tree, to ensure the + -- parser is fully executed. + _ <- consider (coerce file) (parseNixFileLoc (coerce file)) $ Exc.evaluate . force + stub + ) + files v -> fail $ "Unexpected parse from default.nix: " <> show v where getExpr k m = From 5c8f1f60c3a7e2dfa00561629ee0aa144f8cac92 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Mon, 24 Jan 2022 14:40:05 +0200 Subject: [PATCH 11/70] Lint: add & use mkSymbolic1 --- src/Nix/Lint.hs | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/src/Nix/Lint.hs b/src/Nix/Lint.hs index eee58081e..c74cc4ec4 100644 --- a/src/Nix/Lint.hs +++ b/src/Nix/Lint.hs @@ -104,6 +104,12 @@ mkSymbolic -> m (Symbolic m) mkSymbolic = packSymbolic . NMany +mkSymbolic1 + :: MonadAtomicRef m + => NTypeF m (Symbolic m) + -> m (Symbolic m) +mkSymbolic1 = mkSymbolic . one + packSymbolic :: MonadAtomicRef m => NSymbolicF (NTypeF m (Symbolic m)) @@ -157,7 +163,7 @@ renderSymbolic = do (args, sym) <- do - f' <- mkSymbolic $ one f + f' <- mkSymbolic1 f lintApp (NAbs p mempty) f' everyPossible args' <- traverse renderSymbolic args sym' <- renderSymbolic sym @@ -334,12 +340,12 @@ instance MonadLint e m => MonadEval (Symbolic m) m where evalCurPos = do - f <- mkSymbolic $ one TPath - l <- mkSymbolic . one . TConstant $ one TInt - c <- mkSymbolic . one . TConstant $ one TInt - mkSymbolic . one . TSet . pure $ M.fromList [("file", f), ("line", l), ("col", c)] + f <- mkSymbolic1 TPath + l <- mkSymbolic1 $ TConstant $ one TInt + c <- mkSymbolic1 $ TConstant $ one TInt + mkSymbolic1 $ TSet . pure $ M.fromList [("file", f), ("line", l), ("col", c)] - evalConstant c = mkSymbolic $ one $ fun c + evalConstant c = mkSymbolic1 $ fun c where fun = \case @@ -349,12 +355,12 @@ instance MonadLint e m => MonadEval (Symbolic m) m where NBool _ -> TConstant $ one TBool NNull -> TConstant $ one TNull - evalString = const $ mkSymbolic $ one TStr - evalLiteralPath = const $ mkSymbolic $ one TPath - evalEnvPath = const $ mkSymbolic $ one TPath + evalString = const $ mkSymbolic1 TStr + evalLiteralPath = const $ mkSymbolic1 TPath + evalEnvPath = const $ mkSymbolic1 TPath evalUnary op arg = - unify (void $ NUnary op arg) arg =<< mkSymbolic (one $ TConstant [TInt, TBool]) + unify (void $ NUnary op arg) arg =<< mkSymbolic1 (TConstant [TInt, TBool]) evalBinary = lintBinaryOp @@ -378,20 +384,16 @@ instance MonadLint e m => MonadEval (Symbolic m) m where do t' <- t f' <- f - let e = NIf cond t' f' - - _ <- unify (void e) cond =<< mkSymbolic (one $ TConstant $ one TBool) - unify (void e) t' f' + let e = unify (void $ NIf cond t' f') + e t' f' <* (e cond =<< mkSymbolic1 (TConstant $ one TBool)) evalAssert cond body = do body' <- body - let e = NAssert cond body' - _ <- unify (void e) cond =<< mkSymbolic (one $ TConstant $ one TBool) - pure body' + body' <$ (unify (void (NAssert cond body')) cond =<< mkSymbolic1 (TConstant $ one TBool)) evalApp = (fmap snd .) . lintApp (join NApp mempty) - evalAbs params _ = mkSymbolic (one $ TClosure $ void params) + evalAbs params _ = mkSymbolic1 (TClosure $ void params) evalError = throwError From f7d1519994029a81d9df66374fb3bc33b07eddb8 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Mon, 24 Jan 2022 15:01:53 +0200 Subject: [PATCH 12/70] Lint: unify: allow any internal type in the context Allows not applying `void` externally. --- src/Nix/Lint.hs | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/Nix/Lint.hs b/src/Nix/Lint.hs index c74cc4ec4..9f7fd6ba9 100644 --- a/src/Nix/Lint.hs +++ b/src/Nix/Lint.hs @@ -256,13 +256,13 @@ merge context = go -- | Result @== NMany []@ -> @unify@ fails. unify - :: forall e m + :: forall e m a . MonadLint e m - => NExprF () + => NExprF a -> Symbolic m -> Symbolic m -> m (Symbolic m) -unify context (SV x) (SV y) = do +unify (void -> context) (SV x) (SV y) = do x' <- readRef x y' <- readRef y case (x', y') of @@ -360,7 +360,7 @@ instance MonadLint e m => MonadEval (Symbolic m) m where evalEnvPath = const $ mkSymbolic1 TPath evalUnary op arg = - unify (void $ NUnary op arg) arg =<< mkSymbolic1 (TConstant [TInt, TBool]) + unify (NUnary op arg) arg =<< mkSymbolic1 (TConstant [TInt, TBool]) evalBinary = lintBinaryOp @@ -384,13 +384,13 @@ instance MonadLint e m => MonadEval (Symbolic m) m where do t' <- t f' <- f - let e = unify (void $ NIf cond t' f') + let e = unify (NIf cond t' f') e t' f' <* (e cond =<< mkSymbolic1 (TConstant $ one TBool)) evalAssert cond body = do body' <- body - body' <$ (unify (void (NAssert cond body')) cond =<< mkSymbolic1 (TConstant $ one TBool)) + body' <$ (unify (NAssert cond body') cond =<< mkSymbolic1 (TConstant $ one TBool)) evalApp = (fmap snd .) . lintApp (join NApp mempty) evalAbs params _ = mkSymbolic1 (TClosure $ void params) @@ -442,13 +442,12 @@ lintBinaryOp op lsym rarg = check lsym rsym xs = do let - e = NBinary op lsym rsym - unifyE = unify (void e) + contextUnify = unify $ NBinary op lsym rsym m <- mkSymbolic xs - _ <- unifyE lsym m - _ <- unifyE rsym m - unifyE lsym rsym + _ <- contextUnify lsym m + _ <- contextUnify rsym m + contextUnify lsym rsym infixl 1 `lintApp` lintApp From 987093e91b10b97ffda16f94701e9888b660d49a Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Mon, 24 Jan 2022 15:27:06 +0200 Subject: [PATCH 13/70] Lint: merge: refactor --- src/Nix/Lint.hs | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/Nix/Lint.hs b/src/Nix/Lint.hs index 9f7fd6ba9..2813eac63 100644 --- a/src/Nix/Lint.hs +++ b/src/Nix/Lint.hs @@ -209,15 +209,17 @@ merge context = go (TSet x , TSet Nothing ) -> (one (TSet x) <>) <$> rest (TSet Nothing , TSet x ) -> (one (TSet x) <>) <$> rest (TSet (Just l), TSet (Just r)) -> do - hm <- sequenceA $ M.intersectionWith - (\ i j -> - do - i'' <- demand =<< i - j'' <- demand =<< j - (defer . unify context i'') j'' - ) - (pure <$> l) - (pure <$> r) + hm <- + sequenceA $ + M.intersectionWith + (\ i j -> + do + i'' <- i + j'' <- j + defer $ unify context i'' j'' + ) + (fmap demand l) + (fmap demand r) handlePresence id (const ((one (TSet $ pure hm) <>) <$>)) From 6af275dcd87c21bfd91c19a8598a268c0ad82928 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Sat, 22 Jan 2022 00:35:36 +0200 Subject: [PATCH 14/70] Parser: add & use NOpName --- src/Nix/Parser.hs | 35 ++++++++++++++++++++++++----------- src/Nix/Pretty.hs | 4 ++-- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/src/Nix/Parser.hs b/src/Nix/Parser.hs index f1ccc0bdd..d97755d27 100644 --- a/src/Nix/Parser.hs +++ b/src/Nix/Parser.hs @@ -15,6 +15,7 @@ module Nix.Parser , parseFromText , Result , reservedNames + , NOpName(..) , OperatorInfo(..) , NSpecialOp(..) , NAssoc(..) @@ -465,24 +466,36 @@ nixSearchPath = -- ** Operators +newtype NOpName = NOpName Text + deriving + (Eq, Ord, Generic, Typeable, Data, Show, NFData) + +instance IsString NOpName where + fromString = coerce . fromString @Text + +instance ToString NOpName where + toString = toString @Text . coerce + + data NSpecialOp = NHasAttrOp | NSelectOp deriving (Eq, Ord, Generic, Typeable, Data, Show, NFData) data NAssoc = NAssocNone | NAssocLeft | NAssocRight deriving (Eq, Ord, Generic, Typeable, Data, Show, NFData) +-- 2022-01-22: NOTE: NAppDef has only one associativity (left) data NOperatorDef - = NUnaryDef NUnaryOp Text - | NAppDef NAssoc Text - | NBinaryDef NAssoc NBinaryOp Text - | NSpecialDef NAssoc NSpecialOp Text + = NUnaryDef NUnaryOp NOpName + | NAppDef NAssoc NOpName + | NBinaryDef NAssoc NBinaryOp NOpName + | NSpecialDef NAssoc NSpecialOp NOpName deriving (Eq, Ord, Generic, Typeable, Data, Show, NFData) manyUnaryOp :: MonadPlus f => f (a -> a) -> f (a -> a) manyUnaryOp f = foldr1 (.) <$> some f -operator :: Text -> Parser Text -operator op = +operator :: NOpName -> Parser Text +operator (coerce -> op) = case op of c@"-" -> c `without` '>' c@"/" -> c `without` '/' @@ -494,7 +507,7 @@ operator op = without opChar noNextChar = lexeme . try $ chunk opChar <* notFollowedBy (char noNextChar) -opWithLoc :: (AnnUnit SrcSpan o -> a) -> o -> Text -> Parser a +opWithLoc :: (AnnUnit SrcSpan o -> a) -> o -> NOpName -> Parser a opWithLoc f op name = do AnnUnit ann _ <- @@ -507,12 +520,12 @@ binary :: NAssoc -> (Parser (NExprLoc -> NExprLoc -> NExprLoc) -> b) -> NBinaryOp - -> Text + -> NOpName -> (NOperatorDef, b) binary assoc fixity op name = (NBinaryDef assoc op name, fixity $ opWithLoc annNBinary op name) -binaryN, binaryL, binaryR :: NBinaryOp -> Text -> (NOperatorDef, Operator Parser NExprLoc) +binaryN, binaryL, binaryR :: NBinaryOp -> NOpName -> (NOperatorDef, Operator Parser NExprLoc) binaryN = binary NAssocNone InfixN binaryL = @@ -520,7 +533,7 @@ binaryL = binaryR = binary NAssocRight InfixR -prefix :: NUnaryOp -> Text -> (NOperatorDef, Operator Parser NExprLoc) +prefix :: NUnaryOp -> NOpName -> (NOperatorDef, Operator Parser NExprLoc) prefix op name = (NUnaryDef op name, Prefix $ manyUnaryOp $ opWithLoc annNUnary op name) -- postfix name op = (NUnaryDef name op, @@ -608,7 +621,7 @@ data OperatorInfo = OperatorInfo { precedence :: Int , associativity :: NAssoc - , operatorName :: Text + , operatorName :: NOpName } deriving (Eq, Ord, Generic, Typeable, Data, Show) diff --git a/src/Nix/Pretty.hs b/src/Nix/Pretty.hs index aa3109fd2..31b45724c 100644 --- a/src/Nix/Pretty.hs +++ b/src/Nix/Pretty.hs @@ -262,7 +262,7 @@ exprFNixDoc = \case opInfo $ hsep [ f NAssocLeft r1 - , pretty $ operatorName opInfo + , pretty @Text $ coerce @NOpName $ operatorName opInfo , f NAssocRight r2 ] where @@ -277,7 +277,7 @@ exprFNixDoc = \case NUnary op r1 -> mkNixDoc opInfo $ - pretty (operatorName opInfo) <> precedenceWrap opInfo r1 + pretty @Text (coerce $ operatorName opInfo) <> precedenceWrap opInfo r1 where opInfo = getUnaryOperator op NSelect o r' attr -> From 7e7fbae5c77c21efc9a42281a73a3f8cd64e2761 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Sat, 22 Jan 2022 01:24:30 +0200 Subject: [PATCH 15/70] Parser: add & use NOpPrecedence --- src/Nix/Parser.hs | 89 +++++++++++++++++++++++++++-------------------- 1 file changed, 52 insertions(+), 37 deletions(-) diff --git a/src/Nix/Parser.hs b/src/Nix/Parser.hs index d97755d27..b5029bccf 100644 --- a/src/Nix/Parser.hs +++ b/src/Nix/Parser.hs @@ -476,6 +476,20 @@ instance IsString NOpName where instance ToString NOpName where toString = toString @Text . coerce +newtype NOpPrecedence = NOpPrecedence Int + deriving (Eq, Ord, Generic, Bounded, Typeable, Data, Show, NFData) + +instance Enum NOpPrecedence where + toEnum = coerce + fromEnum = coerce + +instance Num NOpPrecedence where + (+) = coerce ((+) @Int) + (*) = coerce ((*) @Int) + abs = coerce (abs @Int) + signum = coerce (signum @Int) + fromInteger = coerce (fromInteger @Int) + negate = coerce (negate @Int) data NSpecialOp = NHasAttrOp | NSelectOp deriving (Eq, Ord, Generic, Typeable, Data, Show, NFData) @@ -485,10 +499,10 @@ data NAssoc = NAssocNone | NAssocLeft | NAssocRight -- 2022-01-22: NOTE: NAppDef has only one associativity (left) data NOperatorDef - = NUnaryDef NUnaryOp NOpName - | NAppDef NAssoc NOpName - | NBinaryDef NAssoc NBinaryOp NOpName - | NSpecialDef NAssoc NSpecialOp NOpName + = NUnaryDef NUnaryOp NOpName NOpPrecedence + | NAppDef NAssoc NOpName NOpPrecedence + | NBinaryDef NAssoc NBinaryOp NOpName NOpPrecedence + | NSpecialDef NAssoc NSpecialOp NOpName NOpPrecedence deriving (Eq, Ord, Generic, Typeable, Data, Show, NFData) manyUnaryOp :: MonadPlus f => f (a -> a) -> f (a -> a) @@ -521,11 +535,12 @@ binary -> (Parser (NExprLoc -> NExprLoc -> NExprLoc) -> b) -> NBinaryOp -> NOpName + -> NOpPrecedence -> (NOperatorDef, b) -binary assoc fixity op name = - (NBinaryDef assoc op name, fixity $ opWithLoc annNBinary op name) +binary assoc fixity op name precedence = + (NBinaryDef assoc op name precedence, fixity $ opWithLoc annNBinary op name) -binaryN, binaryL, binaryR :: NBinaryOp -> NOpName -> (NOperatorDef, Operator Parser NExprLoc) +binaryN, binaryL, binaryR :: NBinaryOp -> NOpName -> NOpPrecedence -> (NOperatorDef, Operator Parser NExprLoc) binaryN = binary NAssocNone InfixN binaryL = @@ -533,9 +548,9 @@ binaryL = binaryR = binary NAssocRight InfixR -prefix :: NUnaryOp -> NOpName -> (NOperatorDef, Operator Parser NExprLoc) -prefix op name = - (NUnaryDef op name, Prefix $ manyUnaryOp $ opWithLoc annNUnary op name) +prefix :: NUnaryOp -> NOpName -> NOpPrecedence -> (NOperatorDef, Operator Parser NExprLoc) +prefix op name precedence = + (NUnaryDef op name precedence, Prefix $ manyUnaryOp $ opWithLoc annNUnary op name) -- postfix name op = (NUnaryDef name op, -- Postfix (opWithLoc name op annNUnary)) @@ -563,48 +578,48 @@ nixOperators selector = {- 2 -} one - ( NAppDef NAssocLeft " " + ( NAppDef NAssocLeft " " 2 , -- Thanks to Brent Yorgey for showing me this trick! InfixL $ annNApp <$ symbols mempty ) , {- 3 -} - one $ prefix NNeg "-" + one $ prefix NNeg "-" 3 , {- 4 -} one - ( NSpecialDef NAssocLeft NHasAttrOp "?" + ( NSpecialDef NAssocLeft NHasAttrOp "?" 4 , Postfix $ symbol '?' *> (flip annNHasAttr <$> selector) ) , {- 5 -} - one $ binaryR NConcat "++" + one $ binaryR NConcat "++" 5 , {- 6 -} - [ binaryL NMult "*" - , binaryL NDiv "/" + [ binaryL NMult "*" 6 + , binaryL NDiv "/" 6 ] , {- 7 -} - [ binaryL NPlus "+" - , binaryL NMinus "-" + [ binaryL NPlus "+" 7 + , binaryL NMinus "-" 7 ] , {- 8 -} - one $ prefix NNot "!" + one $ prefix NNot "!" 8 , {- 9 -} - one $ binaryR NUpdate "//" + one $ binaryR NUpdate "//" 9 , {- 10 -} - [ binaryL NLt "<" - , binaryL NGt ">" - , binaryL NLte "<=" - , binaryL NGte ">=" + [ binaryL NLt "<" 10 + , binaryL NGt ">" 10 + , binaryL NLte "<=" 10 + , binaryL NGte ">=" 10 ] , {- 11 -} - [ binaryN NEq "==" - , binaryN NNEq "!=" + [ binaryN NEq "==" 11 + , binaryN NNEq "!=" 11 ] , {- 12 -} - one $ binaryL NAnd "&&" + one $ binaryL NAnd "&&" 12 , {- 13 -} - one $ binaryL NOr "||" + one $ binaryL NOr "||" 13 , {- 14 -} - one $ binaryR NImpl "->" + one $ binaryR NImpl "->" 14 ] -- 2021-11-09: NOTE: rename OperatorInfo accessors to `get*` @@ -619,7 +634,7 @@ nixOperators selector = -- details: https://github.com/haskell-nix/hnix/issues/982 data OperatorInfo = OperatorInfo - { precedence :: Int + { precedence :: NOpPrecedence , associativity :: NAssoc , operatorName :: NOpName } @@ -627,7 +642,7 @@ data OperatorInfo = detectPrecedence :: Ord a - => ( Int + => ( NOpPrecedence -> (NOperatorDef, Operator Parser NExprLoc) -> [(a, OperatorInfo)] ) @@ -649,10 +664,10 @@ detectPrecedence spec = (mapOfOpWithPrecedence Map.!) getUnaryOperator :: NUnaryOp -> OperatorInfo getUnaryOperator = detectPrecedence spec where - spec :: Int -> (NOperatorDef, b) -> [(NUnaryOp, OperatorInfo)] + spec :: NOpPrecedence -> (NOperatorDef, b) -> [(NUnaryOp, OperatorInfo)] spec i = \case - (NUnaryDef op name, _) -> one (op, OperatorInfo i NAssocNone name) + (NUnaryDef op name _, _) -> one (op, OperatorInfo i NAssocNone name) _ -> mempty getAppOperator :: OperatorInfo @@ -666,20 +681,20 @@ getAppOperator = getBinaryOperator :: NBinaryOp -> OperatorInfo getBinaryOperator = detectPrecedence spec where - spec :: Int -> (NOperatorDef, b) -> [(NBinaryOp, OperatorInfo)] + spec :: NOpPrecedence -> (NOperatorDef, b) -> [(NBinaryOp, OperatorInfo)] spec i = \case - (NBinaryDef assoc op name, _) -> one (op, OperatorInfo i assoc name) + (NBinaryDef assoc op name _, _) -> one (op, OperatorInfo i assoc name) _ -> mempty getSpecialOperator :: NSpecialOp -> OperatorInfo getSpecialOperator NSelectOp = OperatorInfo 1 NAssocLeft "." getSpecialOperator o = detectPrecedence spec o where - spec :: Int -> (NOperatorDef, b) -> [(NSpecialOp, OperatorInfo)] + spec :: NOpPrecedence -> (NOperatorDef, b) -> [(NSpecialOp, OperatorInfo)] spec i = \case - (NSpecialDef assoc op name, _) -> one (op, OperatorInfo i assoc name) + (NSpecialDef assoc op name _, _) -> one (op, OperatorInfo i assoc name) _ -> mempty -- ** x: y lambda function From a3e3b505134c6278789c60ae5474ed058c5fc0fd Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Sat, 22 Jan 2022 01:54:33 +0200 Subject: [PATCH 16/70] Parser: cast precedence (NOperatorDef->OperatorInfo) directly --- src/Nix/Parser.hs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Nix/Parser.hs b/src/Nix/Parser.hs index b5029bccf..f1d6bde7d 100644 --- a/src/Nix/Parser.hs +++ b/src/Nix/Parser.hs @@ -665,9 +665,9 @@ getUnaryOperator :: NUnaryOp -> OperatorInfo getUnaryOperator = detectPrecedence spec where spec :: NOpPrecedence -> (NOperatorDef, b) -> [(NUnaryOp, OperatorInfo)] - spec i = + spec _ = \case - (NUnaryDef op name _, _) -> one (op, OperatorInfo i NAssocNone name) + (NUnaryDef op name prec, _) -> one (op, OperatorInfo prec NAssocNone name) _ -> mempty getAppOperator :: OperatorInfo @@ -682,9 +682,9 @@ getBinaryOperator :: NBinaryOp -> OperatorInfo getBinaryOperator = detectPrecedence spec where spec :: NOpPrecedence -> (NOperatorDef, b) -> [(NBinaryOp, OperatorInfo)] - spec i = + spec _ = \case - (NBinaryDef assoc op name _, _) -> one (op, OperatorInfo i assoc name) + (NBinaryDef assoc op name prec, _) -> one (op, OperatorInfo prec assoc name) _ -> mempty getSpecialOperator :: NSpecialOp -> OperatorInfo @@ -692,9 +692,9 @@ getSpecialOperator NSelectOp = OperatorInfo 1 NAssocLeft "." getSpecialOperator o = detectPrecedence spec o where spec :: NOpPrecedence -> (NOperatorDef, b) -> [(NSpecialOp, OperatorInfo)] - spec i = + spec _ = \case - (NSpecialDef assoc op name _, _) -> one (op, OperatorInfo i assoc name) + (NSpecialDef assoc op name prec, _) -> one (op, OperatorInfo prec assoc name) _ -> mempty -- ** x: y lambda function From 8857e529184db8f57d035abcafcb5fb2a716f5be Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Sat, 22 Jan 2022 16:41:50 +0200 Subject: [PATCH 17/70] Parser: NAppDef: rm NAssoc --- src/Nix/Parser.hs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Nix/Parser.hs b/src/Nix/Parser.hs index f1d6bde7d..d4e69428d 100644 --- a/src/Nix/Parser.hs +++ b/src/Nix/Parser.hs @@ -500,7 +500,7 @@ data NAssoc = NAssocNone | NAssocLeft | NAssocRight -- 2022-01-22: NOTE: NAppDef has only one associativity (left) data NOperatorDef = NUnaryDef NUnaryOp NOpName NOpPrecedence - | NAppDef NAssoc NOpName NOpPrecedence + | NAppDef NOpName NOpPrecedence | NBinaryDef NAssoc NBinaryOp NOpName NOpPrecedence | NSpecialDef NAssoc NSpecialOp NOpName NOpPrecedence deriving (Eq, Ord, Generic, Typeable, Data, Show, NFData) @@ -578,10 +578,10 @@ nixOperators selector = {- 2 -} one - ( NAppDef NAssocLeft " " 2 + ( NAppDef " " 2 , -- Thanks to Brent Yorgey for showing me this trick! - InfixL $ annNApp <$ symbols mempty + InfixL $ annNApp <$ symbols mempty -- NApp is left associative ) , {- 3 -} one $ prefix NNeg "-" 3 From f8b7fff2dbd206d3009439b1256ada5ca4e72221 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Sat, 22 Jan 2022 16:58:27 +0200 Subject: [PATCH 18/70] Parser: OperatorInfo: ord fields Ordering in the cardinality/use. --- src/Nix/Parser.hs | 12 ++++++------ src/Nix/Pretty.hs | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Nix/Parser.hs b/src/Nix/Parser.hs index d4e69428d..67ad94038 100644 --- a/src/Nix/Parser.hs +++ b/src/Nix/Parser.hs @@ -634,8 +634,8 @@ nixOperators selector = -- details: https://github.com/haskell-nix/hnix/issues/982 data OperatorInfo = OperatorInfo - { precedence :: NOpPrecedence - , associativity :: NAssoc + { associativity :: NAssoc + , precedence :: NOpPrecedence , operatorName :: NOpName } deriving (Eq, Ord, Generic, Typeable, Data, Show) @@ -667,7 +667,7 @@ getUnaryOperator = detectPrecedence spec spec :: NOpPrecedence -> (NOperatorDef, b) -> [(NUnaryOp, OperatorInfo)] spec _ = \case - (NUnaryDef op name prec, _) -> one (op, OperatorInfo prec NAssocNone name) + (NUnaryDef op name prec, _) -> one (op, OperatorInfo NAssocNone prec name) _ -> mempty getAppOperator :: OperatorInfo @@ -684,17 +684,17 @@ getBinaryOperator = detectPrecedence spec spec :: NOpPrecedence -> (NOperatorDef, b) -> [(NBinaryOp, OperatorInfo)] spec _ = \case - (NBinaryDef assoc op name prec, _) -> one (op, OperatorInfo prec assoc name) + (NBinaryDef assoc op name prec, _) -> one (op, OperatorInfo assoc prec name) _ -> mempty getSpecialOperator :: NSpecialOp -> OperatorInfo -getSpecialOperator NSelectOp = OperatorInfo 1 NAssocLeft "." +getSpecialOperator NSelectOp = OperatorInfo NAssocLeft 1 "." getSpecialOperator o = detectPrecedence spec o where spec :: NOpPrecedence -> (NOperatorDef, b) -> [(NSpecialOp, OperatorInfo)] spec _ = \case - (NSpecialDef assoc op name prec, _) -> one (op, OperatorInfo prec assoc name) + (NSpecialDef assoc op name prec, _) -> one (op, OperatorInfo assoc prec name) _ -> mempty -- ** x: y lambda function diff --git a/src/Nix/Pretty.hs b/src/Nix/Pretty.hs index 31b45724c..b483b6e20 100644 --- a/src/Nix/Pretty.hs +++ b/src/Nix/Pretty.hs @@ -59,7 +59,7 @@ mkNixDoc o d = NixDoc { getDoc = d, rootOp = o, wasPath = False } -- behaves as if its root operator had a precedence higher than all -- other operators (including function application). simpleExpr :: Doc ann -> NixDoc ann -simpleExpr = mkNixDoc $ OperatorInfo minBound NAssocNone "simple expr" +simpleExpr = mkNixDoc $ OperatorInfo NAssocNone minBound "simple expr" pathExpr :: Doc ann -> NixDoc ann pathExpr d = (simpleExpr d) { wasPath = True } @@ -71,7 +71,7 @@ pathExpr d = (simpleExpr d) { wasPath = True } -- binding). leastPrecedence :: Doc ann -> NixDoc ann leastPrecedence = - mkNixDoc $ OperatorInfo maxBound NAssocNone "least precedence" + mkNixDoc $ OperatorInfo NAssocNone maxBound "least precedence" appOp :: OperatorInfo appOp = getAppOperator From 48d9979f5674b6be72299f15f7b550c8627e324e Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Sat, 22 Jan 2022 17:44:20 +0200 Subject: [PATCH 19/70] Parser: NOperatorDef: ord fields --- src/Nix/Parser.hs | 67 +++++++++++++++++++++++------------------------ 1 file changed, 33 insertions(+), 34 deletions(-) diff --git a/src/Nix/Parser.hs b/src/Nix/Parser.hs index 67ad94038..ce4d21e12 100644 --- a/src/Nix/Parser.hs +++ b/src/Nix/Parser.hs @@ -497,12 +497,11 @@ data NSpecialOp = NHasAttrOp | NSelectOp data NAssoc = NAssocNone | NAssocLeft | NAssocRight deriving (Eq, Ord, Generic, Typeable, Data, Show, NFData) --- 2022-01-22: NOTE: NAppDef has only one associativity (left) data NOperatorDef - = NUnaryDef NUnaryOp NOpName NOpPrecedence - | NAppDef NOpName NOpPrecedence - | NBinaryDef NAssoc NBinaryOp NOpName NOpPrecedence - | NSpecialDef NAssoc NSpecialOp NOpName NOpPrecedence + = NAppDef NOpPrecedence NOpName + | NUnaryDef NUnaryOp NOpPrecedence NOpName + | NBinaryDef NAssoc NBinaryOp NOpPrecedence NOpName + | NSpecialDef NAssoc NSpecialOp NOpPrecedence NOpName deriving (Eq, Ord, Generic, Typeable, Data, Show, NFData) manyUnaryOp :: MonadPlus f => f (a -> a) -> f (a -> a) @@ -534,13 +533,13 @@ binary :: NAssoc -> (Parser (NExprLoc -> NExprLoc -> NExprLoc) -> b) -> NBinaryOp - -> NOpName -> NOpPrecedence + -> NOpName -> (NOperatorDef, b) -binary assoc fixity op name precedence = - (NBinaryDef assoc op name precedence, fixity $ opWithLoc annNBinary op name) +binary assoc fixity op precedence name = + (NBinaryDef assoc op precedence name, fixity $ opWithLoc annNBinary op name) -binaryN, binaryL, binaryR :: NBinaryOp -> NOpName -> NOpPrecedence -> (NOperatorDef, Operator Parser NExprLoc) +binaryN, binaryL, binaryR :: NBinaryOp -> NOpPrecedence -> NOpName -> (NOperatorDef, Operator Parser NExprLoc) binaryN = binary NAssocNone InfixN binaryL = @@ -548,9 +547,9 @@ binaryL = binaryR = binary NAssocRight InfixR -prefix :: NUnaryOp -> NOpName -> NOpPrecedence -> (NOperatorDef, Operator Parser NExprLoc) -prefix op name precedence = - (NUnaryDef op name precedence, Prefix $ manyUnaryOp $ opWithLoc annNUnary op name) +prefix :: NUnaryOp -> NOpPrecedence -> NOpName -> (NOperatorDef, Operator Parser NExprLoc) +prefix op precedence name = + (NUnaryDef op precedence name, Prefix $ manyUnaryOp $ opWithLoc annNUnary op name) -- postfix name op = (NUnaryDef name op, -- Postfix (opWithLoc name op annNUnary)) @@ -578,48 +577,48 @@ nixOperators selector = {- 2 -} one - ( NAppDef " " 2 + ( NAppDef 2 " " , -- Thanks to Brent Yorgey for showing me this trick! InfixL $ annNApp <$ symbols mempty -- NApp is left associative ) , {- 3 -} - one $ prefix NNeg "-" 3 + one $ prefix NNeg 3 "-" , {- 4 -} one - ( NSpecialDef NAssocLeft NHasAttrOp "?" 4 + ( NSpecialDef NAssocLeft NHasAttrOp 4 "?" , Postfix $ symbol '?' *> (flip annNHasAttr <$> selector) ) , {- 5 -} - one $ binaryR NConcat "++" 5 + one $ binaryR NConcat 5 "++" , {- 6 -} - [ binaryL NMult "*" 6 - , binaryL NDiv "/" 6 + [ binaryL NMult 6 "*" + , binaryL NDiv 6 "/" ] , {- 7 -} - [ binaryL NPlus "+" 7 - , binaryL NMinus "-" 7 + [ binaryL NPlus 7 "+" + , binaryL NMinus 7 "-" ] , {- 8 -} - one $ prefix NNot "!" 8 + one $ prefix NNot 8 "!" , {- 9 -} - one $ binaryR NUpdate "//" 9 + one $ binaryR NUpdate 9 "//" , {- 10 -} - [ binaryL NLt "<" 10 - , binaryL NGt ">" 10 - , binaryL NLte "<=" 10 - , binaryL NGte ">=" 10 + [ binaryL NLt 10 "<" + , binaryL NGt 10 ">" + , binaryL NLte 10 "<=" + , binaryL NGte 10 ">=" ] , {- 11 -} - [ binaryN NEq "==" 11 - , binaryN NNEq "!=" 11 + [ binaryN NEq 11 "==" + , binaryN NNEq 11 "!=" ] , {- 12 -} - one $ binaryL NAnd "&&" 12 + one $ binaryL NAnd 12 "&&" , {- 13 -} - one $ binaryL NOr "||" 13 + one $ binaryL NOr 13 "||" , {- 14 -} - one $ binaryR NImpl "->" 14 + one $ binaryR NImpl 14 "->" ] -- 2021-11-09: NOTE: rename OperatorInfo accessors to `get*` @@ -667,7 +666,7 @@ getUnaryOperator = detectPrecedence spec spec :: NOpPrecedence -> (NOperatorDef, b) -> [(NUnaryOp, OperatorInfo)] spec _ = \case - (NUnaryDef op name prec, _) -> one (op, OperatorInfo NAssocNone prec name) + (NUnaryDef op prec name, _) -> one (op, OperatorInfo NAssocNone prec name) _ -> mempty getAppOperator :: OperatorInfo @@ -684,7 +683,7 @@ getBinaryOperator = detectPrecedence spec spec :: NOpPrecedence -> (NOperatorDef, b) -> [(NBinaryOp, OperatorInfo)] spec _ = \case - (NBinaryDef assoc op name prec, _) -> one (op, OperatorInfo assoc prec name) + (NBinaryDef assoc op prec name, _) -> one (op, OperatorInfo assoc prec name) _ -> mempty getSpecialOperator :: NSpecialOp -> OperatorInfo @@ -694,7 +693,7 @@ getSpecialOperator o = detectPrecedence spec o spec :: NOpPrecedence -> (NOperatorDef, b) -> [(NSpecialOp, OperatorInfo)] spec _ = \case - (NSpecialDef assoc op name prec, _) -> one (op, OperatorInfo assoc prec name) + (NSpecialDef assoc op prec name, _) -> one (op, OperatorInfo assoc prec name) _ -> mempty -- ** x: y lambda function From 42b74b218d2a3c203129a257d1ce339332336bc8 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Sat, 22 Jan 2022 17:48:04 +0200 Subject: [PATCH 20/70] Parser: NOperatorDef: ord fields to match OperatorInfo --- src/Nix/Parser.hs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Nix/Parser.hs b/src/Nix/Parser.hs index ce4d21e12..ac1520a9f 100644 --- a/src/Nix/Parser.hs +++ b/src/Nix/Parser.hs @@ -499,9 +499,9 @@ data NAssoc = NAssocNone | NAssocLeft | NAssocRight data NOperatorDef = NAppDef NOpPrecedence NOpName - | NUnaryDef NUnaryOp NOpPrecedence NOpName - | NBinaryDef NAssoc NBinaryOp NOpPrecedence NOpName - | NSpecialDef NAssoc NSpecialOp NOpPrecedence NOpName + | NUnaryDef NUnaryOp NOpPrecedence NOpName + | NBinaryDef NBinaryOp NAssoc NOpPrecedence NOpName + | NSpecialDef NSpecialOp NAssoc NOpPrecedence NOpName deriving (Eq, Ord, Generic, Typeable, Data, Show, NFData) manyUnaryOp :: MonadPlus f => f (a -> a) -> f (a -> a) @@ -537,7 +537,7 @@ binary -> NOpName -> (NOperatorDef, b) binary assoc fixity op precedence name = - (NBinaryDef assoc op precedence name, fixity $ opWithLoc annNBinary op name) + (NBinaryDef op assoc precedence name, fixity $ opWithLoc annNBinary op name) binaryN, binaryL, binaryR :: NBinaryOp -> NOpPrecedence -> NOpName -> (NOperatorDef, Operator Parser NExprLoc) binaryN = @@ -586,7 +586,7 @@ nixOperators selector = one $ prefix NNeg 3 "-" , {- 4 -} one - ( NSpecialDef NAssocLeft NHasAttrOp 4 "?" + ( NSpecialDef NHasAttrOp NAssocLeft 4 "?" , Postfix $ symbol '?' *> (flip annNHasAttr <$> selector) ) , {- 5 -} @@ -683,7 +683,7 @@ getBinaryOperator = detectPrecedence spec spec :: NOpPrecedence -> (NOperatorDef, b) -> [(NBinaryOp, OperatorInfo)] spec _ = \case - (NBinaryDef assoc op prec name, _) -> one (op, OperatorInfo assoc prec name) + (NBinaryDef op assoc prec name, _) -> one (op, OperatorInfo assoc prec name) _ -> mempty getSpecialOperator :: NSpecialOp -> OperatorInfo @@ -693,7 +693,7 @@ getSpecialOperator o = detectPrecedence spec o spec :: NOpPrecedence -> (NOperatorDef, b) -> [(NSpecialOp, OperatorInfo)] spec _ = \case - (NSpecialDef assoc op prec name, _) -> one (op, OperatorInfo assoc prec name) + (NSpecialDef op assoc prec name, _) -> one (op, OperatorInfo assoc prec name) _ -> mempty -- ** x: y lambda function From 2cb05cd3b214ec5b70979c900d2ce829958fca93 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Sat, 22 Jan 2022 17:52:39 +0200 Subject: [PATCH 21/70] Parser: NOperatorDef: start merging OperatorInfo --- src/Nix/Parser.hs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Nix/Parser.hs b/src/Nix/Parser.hs index ac1520a9f..f48e3e12b 100644 --- a/src/Nix/Parser.hs +++ b/src/Nix/Parser.hs @@ -500,7 +500,7 @@ data NAssoc = NAssocNone | NAssocLeft | NAssocRight data NOperatorDef = NAppDef NOpPrecedence NOpName | NUnaryDef NUnaryOp NOpPrecedence NOpName - | NBinaryDef NBinaryOp NAssoc NOpPrecedence NOpName + | NBinaryDef NBinaryOp OperatorInfo | NSpecialDef NSpecialOp NAssoc NOpPrecedence NOpName deriving (Eq, Ord, Generic, Typeable, Data, Show, NFData) @@ -537,7 +537,7 @@ binary -> NOpName -> (NOperatorDef, b) binary assoc fixity op precedence name = - (NBinaryDef op assoc precedence name, fixity $ opWithLoc annNBinary op name) + (NBinaryDef op (OperatorInfo assoc precedence name), fixity $ opWithLoc annNBinary op name) binaryN, binaryL, binaryR :: NBinaryOp -> NOpPrecedence -> NOpName -> (NOperatorDef, Operator Parser NExprLoc) binaryN = @@ -637,7 +637,7 @@ data OperatorInfo = , precedence :: NOpPrecedence , operatorName :: NOpName } - deriving (Eq, Ord, Generic, Typeable, Data, Show) + deriving (Eq, Ord, Generic, Typeable, Data, NFData, Show) detectPrecedence :: Ord a @@ -683,7 +683,7 @@ getBinaryOperator = detectPrecedence spec spec :: NOpPrecedence -> (NOperatorDef, b) -> [(NBinaryOp, OperatorInfo)] spec _ = \case - (NBinaryDef op assoc prec name, _) -> one (op, OperatorInfo assoc prec name) + (NBinaryDef op operatorInfo, _) -> one (op, operatorInfo) _ -> mempty getSpecialOperator :: NSpecialOp -> OperatorInfo From 983e83c6f273289cf3ee31427bc2e7af944c3957 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Sat, 22 Jan 2022 17:54:37 +0200 Subject: [PATCH 22/70] Parser: NOperatorDef: continue merging OperatorInfo --- src/Nix/Parser.hs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Nix/Parser.hs b/src/Nix/Parser.hs index f48e3e12b..24d8b1260 100644 --- a/src/Nix/Parser.hs +++ b/src/Nix/Parser.hs @@ -501,7 +501,7 @@ data NOperatorDef = NAppDef NOpPrecedence NOpName | NUnaryDef NUnaryOp NOpPrecedence NOpName | NBinaryDef NBinaryOp OperatorInfo - | NSpecialDef NSpecialOp NAssoc NOpPrecedence NOpName + | NSpecialDef NSpecialOp OperatorInfo deriving (Eq, Ord, Generic, Typeable, Data, Show, NFData) manyUnaryOp :: MonadPlus f => f (a -> a) -> f (a -> a) @@ -586,7 +586,7 @@ nixOperators selector = one $ prefix NNeg 3 "-" , {- 4 -} one - ( NSpecialDef NHasAttrOp NAssocLeft 4 "?" + ( NSpecialDef NHasAttrOp (OperatorInfo NAssocLeft 4 "?") , Postfix $ symbol '?' *> (flip annNHasAttr <$> selector) ) , {- 5 -} @@ -693,7 +693,7 @@ getSpecialOperator o = detectPrecedence spec o spec :: NOpPrecedence -> (NOperatorDef, b) -> [(NSpecialOp, OperatorInfo)] spec _ = \case - (NSpecialDef op assoc prec name, _) -> one (op, OperatorInfo assoc prec name) + (NSpecialDef op operatorInfo, _) -> one (op, operatorInfo) _ -> mempty -- ** x: y lambda function From 81894821954d4233fb28f61ab0b2b752dc0acb50 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Sat, 22 Jan 2022 19:19:00 +0200 Subject: [PATCH 23/70] Parser: refactor get{Unary,Binary,Special}Operator Step further to move from `OperatorInfo` rough edges & `nixOperators` implicitness. --- src/Nix/Parser.hs | 78 ++++++++++++++++------------------------------- src/Nix/Pretty.hs | 2 +- 2 files changed, 28 insertions(+), 52 deletions(-) diff --git a/src/Nix/Parser.hs b/src/Nix/Parser.hs index 24d8b1260..679a2e334 100644 --- a/src/Nix/Parser.hs +++ b/src/Nix/Parser.hs @@ -21,7 +21,7 @@ module Nix.Parser , NAssoc(..) , NOperatorDef , getUnaryOperator - , getAppOperator + , appOperatorInfo , getBinaryOperator , getSpecialOperator , nixExpr @@ -498,8 +498,8 @@ data NAssoc = NAssocNone | NAssocLeft | NAssocRight deriving (Eq, Ord, Generic, Typeable, Data, Show, NFData) data NOperatorDef - = NAppDef NOpPrecedence NOpName - | NUnaryDef NUnaryOp NOpPrecedence NOpName + = NAppDef NOpPrecedence NOpName + | NUnaryDef NUnaryOp NOpPrecedence NOpName | NBinaryDef NBinaryOp OperatorInfo | NSpecialDef NSpecialOp OperatorInfo deriving (Eq, Ord, Generic, Typeable, Data, Show, NFData) @@ -551,7 +551,7 @@ prefix :: NUnaryOp -> NOpPrecedence -> NOpName -> (NOperatorDef, Operator Parser prefix op precedence name = (NUnaryDef op precedence name, Prefix $ manyUnaryOp $ opWithLoc annNUnary op name) -- postfix name op = (NUnaryDef name op, --- Postfix (opWithLoc name op annNUnary)) +-- Postfix (opWithLoc annNUnary op name)) nixOperators :: Parser (AnnUnit SrcSpan (NAttrPath NExprLoc)) @@ -586,7 +586,7 @@ nixOperators selector = one $ prefix NNeg 3 "-" , {- 4 -} one - ( NSpecialDef NHasAttrOp (OperatorInfo NAssocLeft 4 "?") + ( NSpecialDef NHasAttrOp $ getSpecialOperator NHasAttrOp , Postfix $ symbol '?' *> (flip annNHasAttr <$> selector) ) , {- 5 -} @@ -639,38 +639,12 @@ data OperatorInfo = } deriving (Eq, Ord, Generic, Typeable, Data, NFData, Show) -detectPrecedence - :: Ord a - => ( NOpPrecedence - -> (NOperatorDef, Operator Parser NExprLoc) - -> [(a, OperatorInfo)] - ) - -> a - -> OperatorInfo -detectPrecedence spec = (mapOfOpWithPrecedence Map.!) - where - mapOfOpWithPrecedence = - Map.fromList $ - fold $ - zipWith - (foldMap . spec) - [1 ..] - l - where - l :: [[(NOperatorDef, Operator Parser NExprLoc)]] - l = nixOperators $ fail "unused" - getUnaryOperator :: NUnaryOp -> OperatorInfo -getUnaryOperator = detectPrecedence spec - where - spec :: NOpPrecedence -> (NOperatorDef, b) -> [(NUnaryOp, OperatorInfo)] - spec _ = - \case - (NUnaryDef op prec name, _) -> one (op, OperatorInfo NAssocNone prec name) - _ -> mempty - -getAppOperator :: OperatorInfo -getAppOperator = +getUnaryOperator NNeg = OperatorInfo NAssocNone 3 "-" +getUnaryOperator NNot = OperatorInfo NAssocNone 8 "!" + +appOperatorInfo :: OperatorInfo +appOperatorInfo = OperatorInfo { precedence = 1 -- inside the code it is 1, inside the Nix they are +1 , associativity = NAssocLeft @@ -678,23 +652,25 @@ getAppOperator = } getBinaryOperator :: NBinaryOp -> OperatorInfo -getBinaryOperator = detectPrecedence spec - where - spec :: NOpPrecedence -> (NOperatorDef, b) -> [(NBinaryOp, OperatorInfo)] - spec _ = - \case - (NBinaryDef op operatorInfo, _) -> one (op, operatorInfo) - _ -> mempty +getBinaryOperator NConcat = OperatorInfo NAssocRight 5 "++" +getBinaryOperator NMult = OperatorInfo NAssocLeft 6 "*" +getBinaryOperator NDiv = OperatorInfo NAssocLeft 6 "/" +getBinaryOperator NPlus = OperatorInfo NAssocLeft 7 "+" +getBinaryOperator NMinus = OperatorInfo NAssocLeft 7 "-" +getBinaryOperator NUpdate = OperatorInfo NAssocRight 9 "//" +getBinaryOperator NLt = OperatorInfo NAssocLeft 10 "<" +getBinaryOperator NLte = OperatorInfo NAssocLeft 10 "<=" +getBinaryOperator NGt = OperatorInfo NAssocLeft 10 ">" +getBinaryOperator NGte = OperatorInfo NAssocLeft 10 ">=" +getBinaryOperator NEq = OperatorInfo NAssocNone 11 "==" +getBinaryOperator NNEq = OperatorInfo NAssocNone 11 "!=" +getBinaryOperator NAnd = OperatorInfo NAssocLeft 12 "&&" +getBinaryOperator NOr = OperatorInfo NAssocLeft 13 "||" +getBinaryOperator NImpl = OperatorInfo NAssocRight 14 "->" getSpecialOperator :: NSpecialOp -> OperatorInfo -getSpecialOperator NSelectOp = OperatorInfo NAssocLeft 1 "." -getSpecialOperator o = detectPrecedence spec o - where - spec :: NOpPrecedence -> (NOperatorDef, b) -> [(NSpecialOp, OperatorInfo)] - spec _ = - \case - (NSpecialDef op operatorInfo, _) -> one (op, operatorInfo) - _ -> mempty +getSpecialOperator NSelectOp = OperatorInfo NAssocLeft 1 "." +getSpecialOperator NHasAttrOp = OperatorInfo NAssocLeft 4 "?" -- ** x: y lambda function diff --git a/src/Nix/Pretty.hs b/src/Nix/Pretty.hs index b483b6e20..67c3660b1 100644 --- a/src/Nix/Pretty.hs +++ b/src/Nix/Pretty.hs @@ -74,7 +74,7 @@ leastPrecedence = mkNixDoc $ OperatorInfo NAssocNone maxBound "least precedence" appOp :: OperatorInfo -appOp = getAppOperator +appOp = appOperatorInfo appOpNonAssoc :: OperatorInfo appOpNonAssoc = appOp { associativity = NAssocNone } From 233315f58c9ef730466d160ff76112539b4a7986 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Sat, 22 Jan 2022 19:27:47 +0200 Subject: [PATCH 24/70] Parser: nixSelector: m refactor --- src/Nix/Parser.hs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Nix/Parser.hs b/src/Nix/Parser.hs index 679a2e334..9e42350f0 100644 --- a/src/Nix/Parser.hs +++ b/src/Nix/Parser.hs @@ -803,10 +803,7 @@ keyName = dynamicKey <|> staticKey nixSelector :: Parser (AnnUnit SrcSpan (NAttrPath NExprLoc)) nixSelector = - annotateLocation1 $ - do - (x : xs) <- keyName `sepBy1` selDot - pure $ x :| xs + annotateLocation1 $ fromList <$> keyName `sepBy1` selDot nixSelect :: Parser NExprLoc -> Parser NExprLoc nixSelect term = From 91742a85c3f4353b83aaf2863c690147181b5602 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Sat, 22 Jan 2022 19:40:23 +0200 Subject: [PATCH 25/70] Parser: opWithLoc: refactor --- src/Nix/Expr/Shorthands.hs | 2 +- src/Nix/Parser.hs | 8 +------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/Nix/Expr/Shorthands.hs b/src/Nix/Expr/Shorthands.hs index 4959c67d1..516b28a40 100644 --- a/src/Nix/Expr/Shorthands.hs +++ b/src/Nix/Expr/Shorthands.hs @@ -215,7 +215,7 @@ mkIf e1 e2 = Fix . NIf e1 e2 mkFunction :: Params NExpr -> NExpr -> NExpr mkFunction params = Fix . NAbs params --- | General dot-reference with optional alternative if the jey does not exist. +-- | General dot-reference with optional alternative if the key does not exist. -- @since 0.15.0 getRefOrDefault :: Maybe NExpr -> NExpr -> Text -> NExpr getRefOrDefault alt obj = Fix . NSelect alt obj . mkSelector diff --git a/src/Nix/Parser.hs b/src/Nix/Parser.hs index 9e42350f0..d741f95f4 100644 --- a/src/Nix/Parser.hs +++ b/src/Nix/Parser.hs @@ -521,13 +521,7 @@ operator (coerce -> op) = lexeme . try $ chunk opChar <* notFollowedBy (char noNextChar) opWithLoc :: (AnnUnit SrcSpan o -> a) -> o -> NOpName -> Parser a -opWithLoc f op name = - do - AnnUnit ann _ <- - annotateLocation1 $ - operator name - - pure . f $ AnnUnit ann op +opWithLoc f op name = f . (op <$) <$> annotateLocation1 (operator name) binary :: NAssoc From e7019088ceaec120c30b72d16c1144aea39c749e Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Sat, 22 Jan 2022 20:05:15 +0200 Subject: [PATCH 26/70] Parser: NOperatorDef: use Map --- src/Nix/Parser.hs | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/src/Nix/Parser.hs b/src/Nix/Parser.hs index d741f95f4..15918757c 100644 --- a/src/Nix/Parser.hs +++ b/src/Nix/Parser.hs @@ -64,8 +64,8 @@ import Data.Char ( isAlpha import Data.Data ( Data(..) ) import Data.Fix ( Fix(..) ) import qualified Data.HashSet as HashSet -import qualified Data.Map as Map import qualified Data.Text as Text +import qualified Data.Map.Strict as M import Nix.Expr.Types import Nix.Expr.Shorthands hiding ( ($>) ) import Nix.Expr.Types.Annotated @@ -500,7 +500,7 @@ data NAssoc = NAssocNone | NAssocLeft | NAssocRight data NOperatorDef = NAppDef NOpPrecedence NOpName | NUnaryDef NUnaryOp NOpPrecedence NOpName - | NBinaryDef NBinaryOp OperatorInfo + | NBinaryDef (Map NBinaryOp OperatorInfo) | NSpecialDef NSpecialOp OperatorInfo deriving (Eq, Ord, Generic, Typeable, Data, Show, NFData) @@ -531,7 +531,7 @@ binary -> NOpName -> (NOperatorDef, b) binary assoc fixity op precedence name = - (NBinaryDef op (OperatorInfo assoc precedence name), fixity $ opWithLoc annNBinary op name) + (NBinaryDef $ one (op, OperatorInfo assoc precedence name), fixity $ opWithLoc annNBinary op name) binaryN, binaryL, binaryR :: NBinaryOp -> NOpPrecedence -> NOpName -> (NOperatorDef, Operator Parser NExprLoc) binaryN = @@ -645,22 +645,27 @@ appOperatorInfo = , operatorName = " " } +binOpInfMap :: Map NBinaryOp OperatorInfo +binOpInfMap = fromList + [ (NConcat, OperatorInfo NAssocRight 5 "++") + , (NMult , OperatorInfo NAssocLeft 6 "*" ) + , (NDiv , OperatorInfo NAssocLeft 6 "/" ) + , (NPlus , OperatorInfo NAssocLeft 7 "+" ) + , (NMinus , OperatorInfo NAssocLeft 7 "-" ) + , (NUpdate, OperatorInfo NAssocRight 9 "//") + , (NLt , OperatorInfo NAssocLeft 10 "<" ) + , (NLte , OperatorInfo NAssocLeft 10 "<=") + , (NGt , OperatorInfo NAssocLeft 10 ">" ) + , (NGte , OperatorInfo NAssocLeft 10 ">=") + , (NEq , OperatorInfo NAssocNone 11 "==") + , (NNEq , OperatorInfo NAssocNone 11 "!=") + , (NAnd , OperatorInfo NAssocLeft 12 "&&") + , (NOr , OperatorInfo NAssocLeft 13 "||") + , (NImpl , OperatorInfo NAssocRight 14 "->") + ] + getBinaryOperator :: NBinaryOp -> OperatorInfo -getBinaryOperator NConcat = OperatorInfo NAssocRight 5 "++" -getBinaryOperator NMult = OperatorInfo NAssocLeft 6 "*" -getBinaryOperator NDiv = OperatorInfo NAssocLeft 6 "/" -getBinaryOperator NPlus = OperatorInfo NAssocLeft 7 "+" -getBinaryOperator NMinus = OperatorInfo NAssocLeft 7 "-" -getBinaryOperator NUpdate = OperatorInfo NAssocRight 9 "//" -getBinaryOperator NLt = OperatorInfo NAssocLeft 10 "<" -getBinaryOperator NLte = OperatorInfo NAssocLeft 10 "<=" -getBinaryOperator NGt = OperatorInfo NAssocLeft 10 ">" -getBinaryOperator NGte = OperatorInfo NAssocLeft 10 ">=" -getBinaryOperator NEq = OperatorInfo NAssocNone 11 "==" -getBinaryOperator NNEq = OperatorInfo NAssocNone 11 "!=" -getBinaryOperator NAnd = OperatorInfo NAssocLeft 12 "&&" -getBinaryOperator NOr = OperatorInfo NAssocLeft 13 "||" -getBinaryOperator NImpl = OperatorInfo NAssocRight 14 "->" +getBinaryOperator = fromMaybe (error "Impossible, the key should be in the map") . (`M.lookup` binOpInfMap) getSpecialOperator :: NSpecialOp -> OperatorInfo getSpecialOperator NSelectOp = OperatorInfo NAssocLeft 1 "." From cf5037e1a6581037b7deb48ecd3a3a7f3f594720 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Sat, 22 Jan 2022 20:22:22 +0200 Subject: [PATCH 27/70] Parser: NOperatorDef: use Map; unify get*Operation --- src/Nix/Parser.hs | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/src/Nix/Parser.hs b/src/Nix/Parser.hs index 15918757c..d48280e01 100644 --- a/src/Nix/Parser.hs +++ b/src/Nix/Parser.hs @@ -501,7 +501,7 @@ data NOperatorDef = NAppDef NOpPrecedence NOpName | NUnaryDef NUnaryOp NOpPrecedence NOpName | NBinaryDef (Map NBinaryOp OperatorInfo) - | NSpecialDef NSpecialOp OperatorInfo + | NSpecialDef (Map NSpecialOp OperatorInfo) deriving (Eq, Ord, Generic, Typeable, Data, Show, NFData) manyUnaryOp :: MonadPlus f => f (a -> a) -> f (a -> a) @@ -580,7 +580,7 @@ nixOperators selector = one $ prefix NNeg 3 "-" , {- 4 -} one - ( NSpecialDef NHasAttrOp $ getSpecialOperator NHasAttrOp + ( NSpecialDef (one (NHasAttrOp, getSpecialOperator NHasAttrOp)) , Postfix $ symbol '?' *> (flip annNHasAttr <$> selector) ) , {- 5 -} @@ -633,10 +633,6 @@ data OperatorInfo = } deriving (Eq, Ord, Generic, Typeable, Data, NFData, Show) -getUnaryOperator :: NUnaryOp -> OperatorInfo -getUnaryOperator NNeg = OperatorInfo NAssocNone 3 "-" -getUnaryOperator NNot = OperatorInfo NAssocNone 8 "!" - appOperatorInfo :: OperatorInfo appOperatorInfo = OperatorInfo @@ -664,12 +660,29 @@ binOpInfMap = fromList , (NImpl , OperatorInfo NAssocRight 14 "->") ] -getBinaryOperator :: NBinaryOp -> OperatorInfo -getBinaryOperator = fromMaybe (error "Impossible, the key should be in the map") . (`M.lookup` binOpInfMap) +specOpInfMap :: Map NSpecialOp OperatorInfo +specOpInfMap = fromList + [ (NSelectOp , OperatorInfo NAssocLeft 1 ".") + , (NHasAttrOp, OperatorInfo NAssocLeft 4 "?") + ] + +unaryOpInfMap :: Map NUnaryOp OperatorInfo +unaryOpInfMap = fromList + [ (NNeg, OperatorInfo NAssocNone 3 "-") + , (NNot, OperatorInfo NAssocNone 8 "!") + ] + +getOperatorInfo :: Ord k => Map k c -> k -> c +getOperatorInfo mp = fromMaybe (error "Impossible, the key should be in the map") . (`M.lookup` mp) + +getUnaryOperator :: NUnaryOp -> OperatorInfo +getUnaryOperator = getOperatorInfo unaryOpInfMap + +getBinaryOperator :: NBinaryOp -> OperatorInfo +getBinaryOperator = getOperatorInfo binOpInfMap getSpecialOperator :: NSpecialOp -> OperatorInfo -getSpecialOperator NSelectOp = OperatorInfo NAssocLeft 1 "." -getSpecialOperator NHasAttrOp = OperatorInfo NAssocLeft 4 "?" +getSpecialOperator = getOperatorInfo specOpInfMap -- ** x: y lambda function From c19cb905cb1666c8d3c21cbfe8871602a654da39 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Sun, 23 Jan 2022 00:08:51 +0200 Subject: [PATCH 28/70] Parser: m refactor --- src/Nix/Parser.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Nix/Parser.hs b/src/Nix/Parser.hs index d48280e01..eaa00585d 100644 --- a/src/Nix/Parser.hs +++ b/src/Nix/Parser.hs @@ -672,8 +672,8 @@ unaryOpInfMap = fromList , (NNot, OperatorInfo NAssocNone 8 "!") ] -getOperatorInfo :: Ord k => Map k c -> k -> c -getOperatorInfo mp = fromMaybe (error "Impossible, the key should be in the map") . (`M.lookup` mp) +getOperatorInfo :: Ord k => Map k OperatorInfo -> k -> OperatorInfo +getOperatorInfo mp k = M.findWithDefault (OperatorInfo NAssocNone 1 "Impossible, the key should be in the operator map.") k mp getUnaryOperator :: NUnaryOp -> OperatorInfo getUnaryOperator = getOperatorInfo unaryOpInfMap From 70006a1630397bc7389c8b8fcdfa2fdb8c43152a Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Sun, 23 Jan 2022 00:10:51 +0200 Subject: [PATCH 29/70] Parser: m org --- src/Nix/Parser.hs | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/Nix/Parser.hs b/src/Nix/Parser.hs index eaa00585d..f6b3a8a81 100644 --- a/src/Nix/Parser.hs +++ b/src/Nix/Parser.hs @@ -476,6 +476,22 @@ instance IsString NOpName where instance ToString NOpName where toString = toString @Text . coerce +operator :: NOpName -> Parser Text +operator (coerce -> op) = + case op of + c@"-" -> c `without` '>' + c@"/" -> c `without` '/' + c@"<" -> c `without` '=' + c@">" -> c `without` '=' + n -> symbols n + where + without :: Text -> Char -> Parser Text + without opChar noNextChar = + lexeme . try $ chunk opChar <* notFollowedBy (char noNextChar) + +opWithLoc :: (AnnUnit SrcSpan o -> a) -> o -> NOpName -> Parser a +opWithLoc f op name = f . (op <$) <$> annotateLocation1 (operator name) + newtype NOpPrecedence = NOpPrecedence Int deriving (Eq, Ord, Generic, Bounded, Typeable, Data, Show, NFData) @@ -504,25 +520,15 @@ data NOperatorDef | NSpecialDef (Map NSpecialOp OperatorInfo) deriving (Eq, Ord, Generic, Typeable, Data, Show, NFData) +prefix :: NUnaryOp -> NOpPrecedence -> NOpName -> (NOperatorDef, Operator Parser NExprLoc) +prefix op precedence name = + (NUnaryDef op precedence name, Prefix $ manyUnaryOp $ opWithLoc annNUnary op name) +-- postfix name op = (NUnaryDef name op, +-- Postfix (opWithLoc annNUnary op name)) + manyUnaryOp :: MonadPlus f => f (a -> a) -> f (a -> a) manyUnaryOp f = foldr1 (.) <$> some f -operator :: NOpName -> Parser Text -operator (coerce -> op) = - case op of - c@"-" -> c `without` '>' - c@"/" -> c `without` '/' - c@"<" -> c `without` '=' - c@">" -> c `without` '=' - n -> symbols n - where - without :: Text -> Char -> Parser Text - without opChar noNextChar = - lexeme . try $ chunk opChar <* notFollowedBy (char noNextChar) - -opWithLoc :: (AnnUnit SrcSpan o -> a) -> o -> NOpName -> Parser a -opWithLoc f op name = f . (op <$) <$> annotateLocation1 (operator name) - binary :: NAssoc -> (Parser (NExprLoc -> NExprLoc -> NExprLoc) -> b) @@ -541,12 +547,6 @@ binaryL = binaryR = binary NAssocRight InfixR -prefix :: NUnaryOp -> NOpPrecedence -> NOpName -> (NOperatorDef, Operator Parser NExprLoc) -prefix op precedence name = - (NUnaryDef op precedence name, Prefix $ manyUnaryOp $ opWithLoc annNUnary op name) --- postfix name op = (NUnaryDef name op, --- Postfix (opWithLoc annNUnary op name)) - nixOperators :: Parser (AnnUnit SrcSpan (NAttrPath NExprLoc)) -> [[ ( NOperatorDef From 8f0a3374b5874a7640b79556b45b514cdfd733ab Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Sun, 23 Jan 2022 00:41:09 +0200 Subject: [PATCH 30/70] Parser: refactor --- src/Nix/Parser.hs | 60 ++++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 32 deletions(-) diff --git a/src/Nix/Parser.hs b/src/Nix/Parser.hs index f6b3a8a81..1371b0eee 100644 --- a/src/Nix/Parser.hs +++ b/src/Nix/Parser.hs @@ -530,22 +530,19 @@ manyUnaryOp :: MonadPlus f => f (a -> a) -> f (a -> a) manyUnaryOp f = foldr1 (.) <$> some f binary - :: NAssoc - -> (Parser (NExprLoc -> NExprLoc -> NExprLoc) -> b) - -> NBinaryOp - -> NOpPrecedence - -> NOpName - -> (NOperatorDef, b) -binary assoc fixity op precedence name = - (NBinaryDef $ one (op, OperatorInfo assoc precedence name), fixity $ opWithLoc annNBinary op name) - -binaryN, binaryL, binaryR :: NBinaryOp -> NOpPrecedence -> NOpName -> (NOperatorDef, Operator Parser NExprLoc) -binaryN = - binary NAssocNone InfixN -binaryL = - binary NAssocLeft InfixL -binaryR = - binary NAssocRight InfixR + :: NBinaryOp + -> (NOperatorDef, Operator Parser NExprLoc) +binary op = + ( NBinaryDef $ one (op, operatorInfo) + , mapAssocToInfix (associativity operatorInfo) $ opWithLoc annNBinary op $ operatorName operatorInfo + ) + where + operatorInfo = getBinaryOperator op + +mapAssocToInfix :: NAssoc -> m (a -> a -> a) -> Operator m a +mapAssocToInfix NAssocNone = InfixN +mapAssocToInfix NAssocLeft = InfixL +mapAssocToInfix NAssocRight = InfixR nixOperators :: Parser (AnnUnit SrcSpan (NAttrPath NExprLoc)) @@ -584,42 +581,41 @@ nixOperators selector = , Postfix $ symbol '?' *> (flip annNHasAttr <$> selector) ) , {- 5 -} - one $ binaryR NConcat 5 "++" + one $ binary NConcat , {- 6 -} - [ binaryL NMult 6 "*" - , binaryL NDiv 6 "/" + [ binary NMult + , binary NDiv ] , {- 7 -} - [ binaryL NPlus 7 "+" - , binaryL NMinus 7 "-" + [ binary NPlus + , binary NMinus ] , {- 8 -} one $ prefix NNot 8 "!" , {- 9 -} - one $ binaryR NUpdate 9 "//" + one $ binary NUpdate , {- 10 -} - [ binaryL NLt 10 "<" - , binaryL NGt 10 ">" - , binaryL NLte 10 "<=" - , binaryL NGte 10 ">=" + [ binary NLt + , binary NGt + , binary NLte + , binary NGte ] , {- 11 -} - [ binaryN NEq 11 "==" - , binaryN NNEq 11 "!=" + [ binary NEq + , binary NNEq ] , {- 12 -} - one $ binaryL NAnd 12 "&&" + one $ binary NAnd , {- 13 -} - one $ binaryL NOr 13 "||" + one $ binary NOr , {- 14 -} - one $ binaryR NImpl 14 "->" + one $ binary NImpl ] -- 2021-11-09: NOTE: rename OperatorInfo accessors to `get*` -- 2021-08-10: NOTE: -- All this is a sidecar: -- * This type --- * detectPrecedence -- * getUnaryOperation -- * getBinaryOperation -- * getSpecialOperation From 5020d4194ab36c9ead8f30ccca3a7db7a31e0a81 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Sun, 23 Jan 2022 15:37:59 +0200 Subject: [PATCH 31/70] Parser: m refactor --- src/Nix/Parser.hs | 138 +++++++++++++++++++++++----------------------- 1 file changed, 69 insertions(+), 69 deletions(-) diff --git a/src/Nix/Parser.hs b/src/Nix/Parser.hs index 1371b0eee..3bb9114cd 100644 --- a/src/Nix/Parser.hs +++ b/src/Nix/Parser.hs @@ -175,7 +175,7 @@ symbols :: Text -> Parser Text symbols = lexeme . chunk -- We restrict the type of 'parens' and 'brackets' here because if they were to --- take a @Parser NExprLoc@ argument they would parse additional text which +-- take a 'Parser NExprLoc' argument they would parse additional text which -- wouldn't be captured in the source location annotation. -- -- Braces and angles in hnix don't enclose a single expression so this type @@ -544,74 +544,6 @@ mapAssocToInfix NAssocNone = InfixN mapAssocToInfix NAssocLeft = InfixL mapAssocToInfix NAssocRight = InfixR -nixOperators - :: Parser (AnnUnit SrcSpan (NAttrPath NExprLoc)) - -> [[ ( NOperatorDef - , Operator Parser NExprLoc - ) - ]] -nixOperators selector = - [ -- This is not parsed here, even though technically it's part of the - -- expression table. The problem is that in some cases, such as list - -- membership, it's also a term. And since terms are effectively the - -- highest precedence entities parsed by the expression parser, it ends up - -- working out that we parse them as a kind of "meta-term". - - -- {- 1 -} - -- [ ( NSpecialDef "." NSelectOp NAssocLeft - -- , Postfix $ - -- do - -- sel <- seldot *> selector - -- mor <- optional (reserved "or" *> term) - -- pure $ \x -> annNSelect x sel mor) - -- ] - - {- 2 -} - one - ( NAppDef 2 " " - , - -- Thanks to Brent Yorgey for showing me this trick! - InfixL $ annNApp <$ symbols mempty -- NApp is left associative - ) - , {- 3 -} - one $ prefix NNeg 3 "-" - , {- 4 -} - one - ( NSpecialDef (one (NHasAttrOp, getSpecialOperator NHasAttrOp)) - , Postfix $ symbol '?' *> (flip annNHasAttr <$> selector) - ) - , {- 5 -} - one $ binary NConcat - , {- 6 -} - [ binary NMult - , binary NDiv - ] - , {- 7 -} - [ binary NPlus - , binary NMinus - ] - , {- 8 -} - one $ prefix NNot 8 "!" - , {- 9 -} - one $ binary NUpdate - , {- 10 -} - [ binary NLt - , binary NGt - , binary NLte - , binary NGte - ] - , {- 11 -} - [ binary NEq - , binary NNEq - ] - , {- 12 -} - one $ binary NAnd - , {- 13 -} - one $ binary NOr - , {- 14 -} - one $ binary NImpl - ] - -- 2021-11-09: NOTE: rename OperatorInfo accessors to `get*` -- 2021-08-10: NOTE: -- All this is a sidecar: @@ -853,6 +785,74 @@ nixSynHole = annotateLocation $ mkSynHoleF <$> coerce (char '^' *> identifier) -- ** Expr & its constituents (Language term, expr algebra) +-- | Bundles operators with parsers for them, since @megaparsec@ requires the @[[op]]@ form. +nixOperators + :: Parser (AnnUnit SrcSpan (NAttrPath NExprLoc)) + -> [[ ( NOperatorDef + , Operator Parser NExprLoc + ) + ]] +nixOperators selector = + [ -- This is not parsed here, even though technically it's part of the + -- expression table. The problem is that in some cases, such as list + -- membership, it's also a term. And since terms are effectively the + -- highest precedence entities parsed by the expression parser, it ends up + -- working out that we parse them as a kind of "meta-term". + + -- {- 1 -} + -- [ ( NSpecialDef "." NSelectOp NAssocLeft + -- , Postfix $ + -- do + -- sel <- seldot *> selector + -- mor <- optional (reserved "or" *> term) + -- pure $ \x -> annNSelect x sel mor) + -- ] + + {- 2 -} + one + ( NAppDef 2 " " + , -- Thanks to Brent Yorgey for showing me this trick! + InfixL $ annNApp <$ symbols mempty -- NApp is left associative + ) + , {- 3 -} + one $ prefix NNeg 3 "-" + , {- 4 -} + one + ( NSpecialDef (one (NHasAttrOp, getSpecialOperator NHasAttrOp)) + , Postfix $ symbol '?' *> (flip annNHasAttr <$> selector) + ) + , {- 5 -} + one $ binary NConcat + , {- 6 -} + [ binary NMult + , binary NDiv + ] + , {- 7 -} + [ binary NPlus + , binary NMinus + ] + , {- 8 -} + one $ prefix NNot 8 "!" + , {- 9 -} + one $ binary NUpdate + , {- 10 -} + [ binary NLt + , binary NGt + , binary NLte + , binary NGte + ] + , {- 11 -} + [ binary NEq + , binary NNEq + ] + , {- 12 -} + one $ binary NAnd + , {- 13 -} + one $ binary NOr + , {- 14 -} + one $ binary NImpl + ] + nixTerm :: Parser NExprLoc nixTerm = do From 2d271b520bb115b0f47779c37d281a7a68588041 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Sun, 23 Jan 2022 15:38:29 +0200 Subject: [PATCH 32/70] Parser: m refactor --- src/Nix/Parser.hs | 34 +++++++++++++++++----------------- src/Nix/Utils.hs | 5 ++--- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/src/Nix/Parser.hs b/src/Nix/Parser.hs index 3bb9114cd..0ac216ad9 100644 --- a/src/Nix/Parser.hs +++ b/src/Nix/Parser.hs @@ -99,7 +99,7 @@ isAlphanumeric :: Char -> Bool isAlphanumeric x = isAlpha x || isDigit x {-# inline isAlphanumeric #-} --- | @<|>@ with additional preservation of @MonadPlus@ constraint. +-- | Alternative "<|>" with additional preservation of 'MonadPlus' constraint. infixl 3 <|> (<|>) :: MonadPlus m => m a -> m a -> m a (<|>) = mplus @@ -883,7 +883,7 @@ nixTerm = -- "Expression algebra" is to explain @megaparsec@ use of the term "Expression" (parser for language algebraic coperators without any statements (without @let@ etc.)), which is essentially an algebra inside the language. nixExprAlgebra :: Parser NExprLoc nixExprAlgebra = - makeExprParser + makeExprParser -- This requires to convert precedence to [[op]] nixTerm (snd <<$>> nixOperators nixSelector @@ -899,24 +899,24 @@ nixExpr = keywords <|> nixLambda <|> nixExprAlgebra type Result a = Either (Doc Void) a -parseFromFileEx :: MonadFile m => Parser a -> Path -> m (Result a) -parseFromFileEx parser file = - do - input <- liftIO $ readFile file - - pure $ - either - (Left . pretty . errorBundlePretty) - pure - $ (`evalState` initialPos (coerce file)) $ runParserT parser (coerce file) input -parseFromText :: Parser a -> Text -> Result a -parseFromText parser input = - let stub = "" in +parseWith + :: Parser a + -> Path + -> Text + -> Either (Doc Void) a +parseWith parser file input = either (Left . pretty . errorBundlePretty) pure - $ (`evalState` initialPos stub) $ (`runParserT` stub) parser input + $ (`evalState` initialPos (coerce file)) $ (`runParserT` coerce file) parser input + + +parseFromFileEx :: MonadFile m => Parser a -> Path -> m (Result a) +parseFromFileEx parser file = parseWith parser file <$> readFile file + +parseFromText :: Parser a -> Text -> Result a +parseFromText = (`parseWith` "") fullContent :: Parser NExprLoc fullContent = whiteSpace *> nixExpr <* eof @@ -945,7 +945,7 @@ parseNixTextLoc :: Text -> Result NExprLoc parseNixTextLoc = parseNixText' id -parseExpr :: (MonadFail m) => Text -> m NExpr +parseExpr :: MonadFail m => Text -> m NExpr parseExpr = either (fail . show) diff --git a/src/Nix/Utils.hs b/src/Nix/Utils.hs index e19290677..ff81c917d 100644 --- a/src/Nix/Utils.hs +++ b/src/Nix/Utils.hs @@ -74,7 +74,6 @@ import Control.Monad.Trans.Control ( MonadTransControl(..) ) import qualified Data.Aeson as A import Data.Fix ( Fix(..) ) import qualified Data.Text as Text -import qualified Data.Text.IO as Text import Lens.Family2 as X ( view , over @@ -308,8 +307,8 @@ replaceExtension :: Path -> String -> Path replaceExtension = coerce FilePath.replaceExtension -- | 'Path's 'FilePath.readFile'. -readFile :: Path -> IO Text -readFile = Text.readFile . coerce +readFile :: MonadIO m => Path -> m Text +readFile = readFileText . coerce -- * Recursion scheme From 8fc276db21104ff78cca3d81798d98d33d0db550 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Sun, 23 Jan 2022 17:31:58 +0200 Subject: [PATCH 33/70] Parser: NAssoc: NAssoc(None->) Also ordered the constructors, putting the NAssocLeft first, with a hope this would improve order of parsing matches. --- src/Nix/Parser.hs | 20 +++++++++++++------- src/Nix/Pretty.hs | 10 +++++----- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/Nix/Parser.hs b/src/Nix/Parser.hs index 0ac216ad9..e49154d71 100644 --- a/src/Nix/Parser.hs +++ b/src/Nix/Parser.hs @@ -510,7 +510,13 @@ instance Num NOpPrecedence where data NSpecialOp = NHasAttrOp | NSelectOp deriving (Eq, Ord, Generic, Typeable, Data, Show, NFData) -data NAssoc = NAssocNone | NAssocLeft | NAssocRight +data NAssoc + = NAssocLeft + -- Nota bene: @parser-combinators@ named "associative property" as 'InfixN' stating it as "non-associative property". + -- Binary operators having some associativity is a basis property in mathematical algebras in use (for example, in Category theory). Having no associativity in operators makes theory mostly impossible in use and so non-associativity is not encountered in notations, therefore under 'InfixN' @parser-combinators@ meant "associative". + -- | Bidirectional associativity, or simply: associative property. + | NAssoc + | NAssocRight deriving (Eq, Ord, Generic, Typeable, Data, Show, NFData) data NOperatorDef @@ -540,8 +546,8 @@ binary op = operatorInfo = getBinaryOperator op mapAssocToInfix :: NAssoc -> m (a -> a -> a) -> Operator m a -mapAssocToInfix NAssocNone = InfixN mapAssocToInfix NAssocLeft = InfixL +mapAssocToInfix NAssoc = InfixN mapAssocToInfix NAssocRight = InfixR -- 2021-11-09: NOTE: rename OperatorInfo accessors to `get*` @@ -581,8 +587,8 @@ binOpInfMap = fromList , (NLte , OperatorInfo NAssocLeft 10 "<=") , (NGt , OperatorInfo NAssocLeft 10 ">" ) , (NGte , OperatorInfo NAssocLeft 10 ">=") - , (NEq , OperatorInfo NAssocNone 11 "==") - , (NNEq , OperatorInfo NAssocNone 11 "!=") + , (NEq , OperatorInfo NAssoc 11 "==") + , (NNEq , OperatorInfo NAssoc 11 "!=") , (NAnd , OperatorInfo NAssocLeft 12 "&&") , (NOr , OperatorInfo NAssocLeft 13 "||") , (NImpl , OperatorInfo NAssocRight 14 "->") @@ -596,12 +602,12 @@ specOpInfMap = fromList unaryOpInfMap :: Map NUnaryOp OperatorInfo unaryOpInfMap = fromList - [ (NNeg, OperatorInfo NAssocNone 3 "-") - , (NNot, OperatorInfo NAssocNone 8 "!") + [ (NNeg, OperatorInfo NAssoc 3 "-") + , (NNot, OperatorInfo NAssoc 8 "!") ] getOperatorInfo :: Ord k => Map k OperatorInfo -> k -> OperatorInfo -getOperatorInfo mp k = M.findWithDefault (OperatorInfo NAssocNone 1 "Impossible, the key should be in the operator map.") k mp +getOperatorInfo mp k = M.findWithDefault (OperatorInfo NAssoc 1 "Impossible, the key should be in the operator map.") k mp getUnaryOperator :: NUnaryOp -> OperatorInfo getUnaryOperator = getOperatorInfo unaryOpInfMap diff --git a/src/Nix/Pretty.hs b/src/Nix/Pretty.hs index 67c3660b1..a278285d1 100644 --- a/src/Nix/Pretty.hs +++ b/src/Nix/Pretty.hs @@ -59,7 +59,7 @@ mkNixDoc o d = NixDoc { getDoc = d, rootOp = o, wasPath = False } -- behaves as if its root operator had a precedence higher than all -- other operators (including function application). simpleExpr :: Doc ann -> NixDoc ann -simpleExpr = mkNixDoc $ OperatorInfo NAssocNone minBound "simple expr" +simpleExpr = mkNixDoc $ OperatorInfo NAssoc minBound "simple expr" pathExpr :: Doc ann -> NixDoc ann pathExpr d = (simpleExpr d) { wasPath = True } @@ -71,13 +71,13 @@ pathExpr d = (simpleExpr d) { wasPath = True } -- binding). leastPrecedence :: Doc ann -> NixDoc ann leastPrecedence = - mkNixDoc $ OperatorInfo NAssocNone maxBound "least precedence" + mkNixDoc $ OperatorInfo NAssoc maxBound "least precedence" appOp :: OperatorInfo appOp = appOperatorInfo appOpNonAssoc :: OperatorInfo -appOpNonAssoc = appOp { associativity = NAssocNone } +appOpNonAssoc = appOp { associativity = NAssoc } selectOp :: OperatorInfo selectOp = getSpecialOperator NSelectOp @@ -103,7 +103,7 @@ precedenceWrap op subExpr = precedence root < precedence op || ( precedence root == precedence op && associativity root == associativity op - && associativity op /= NAssocNone + && associativity op /= NAssoc ) root = rootOp subExpr @@ -272,7 +272,7 @@ exprFNixDoc = \case precedenceWrap $ bool opInfo - (opInfo { associativity = NAssocNone }) + (opInfo { associativity = NAssoc }) (associativity opInfo /= x) NUnary op r1 -> mkNixDoc From 0c0460a6ee4608a8427a5269df23b081b8e23550 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Sun, 23 Jan 2022 18:23:45 +0200 Subject: [PATCH 34/70] Parser: refactor Map was not needed here. It is operation definition (single) after all. --- src/Nix/Parser.hs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Nix/Parser.hs b/src/Nix/Parser.hs index e49154d71..4c4b4c9e9 100644 --- a/src/Nix/Parser.hs +++ b/src/Nix/Parser.hs @@ -519,11 +519,12 @@ data NAssoc | NAssocRight deriving (Eq, Ord, Generic, Typeable, Data, Show, NFData) +-- | Single operator grammar entries. data NOperatorDef = NAppDef NOpPrecedence NOpName | NUnaryDef NUnaryOp NOpPrecedence NOpName - | NBinaryDef (Map NBinaryOp OperatorInfo) - | NSpecialDef (Map NSpecialOp OperatorInfo) + | NBinaryDef NBinaryOp OperatorInfo + | NSpecialDef NSpecialOp OperatorInfo deriving (Eq, Ord, Generic, Typeable, Data, Show, NFData) prefix :: NUnaryOp -> NOpPrecedence -> NOpName -> (NOperatorDef, Operator Parser NExprLoc) @@ -539,7 +540,7 @@ binary :: NBinaryOp -> (NOperatorDef, Operator Parser NExprLoc) binary op = - ( NBinaryDef $ one (op, operatorInfo) + ( NBinaryDef op operatorInfo , mapAssocToInfix (associativity operatorInfo) $ opWithLoc annNBinary op $ operatorName operatorInfo ) where @@ -824,7 +825,7 @@ nixOperators selector = one $ prefix NNeg 3 "-" , {- 4 -} one - ( NSpecialDef (one (NHasAttrOp, getSpecialOperator NHasAttrOp)) + ( NSpecialDef NHasAttrOp $ getSpecialOperator NHasAttrOp , Postfix $ symbol '?' *> (flip annNHasAttr <$> selector) ) , {- 5 -} From 701c5919014c8fbca97f905dbf2b8d735702c6d8 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Mon, 24 Jan 2022 17:47:39 +0200 Subject: [PATCH 35/70] Value.Equal: refactor --- src/Nix/Value/Equal.hs | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/src/Nix/Value/Equal.hs b/src/Nix/Value/Equal.hs index eb34393f6..f4437f407 100644 --- a/src/Nix/Value/Equal.hs +++ b/src/Nix/Value/Equal.hs @@ -31,9 +31,9 @@ checkComparable -> m () checkComparable x y = case (x, y) of - (NVConstant (NFloat _), NVConstant (NInt _)) -> stub - (NVConstant (NInt _), NVConstant (NFloat _)) -> stub (NVConstant (NInt _), NVConstant (NInt _)) -> stub + (NVConstant (NInt _), NVConstant (NFloat _)) -> stub + (NVConstant (NFloat _), NVConstant (NInt _)) -> stub (NVConstant (NFloat _), NVConstant (NFloat _)) -> stub (NVStr _ , NVStr _ ) -> stub (NVPath _ , NVPath _ ) -> stub @@ -62,7 +62,8 @@ alignEqM eq fa fb = (Data.Semialign.align fa fb) alignEq :: (Align f, Traversable f) => (a -> b -> Bool) -> f a -> f b -> Bool -alignEq eq fa fb = runIdentity $ alignEqM ((Identity .) . eq) fa fb +alignEq eq fa fb = + runIdentity $ alignEqM ((Identity .) . eq) fa fb isDerivationM :: Monad m @@ -158,11 +159,12 @@ compareAttrSets -> AttrSet t -> AttrSet t -> Bool -compareAttrSets f eq lm rm = runIdentity - $ compareAttrSetsM (Identity . f) ((Identity .) . eq) lm rm +compareAttrSets f eq lm rm = + runIdentity $ compareAttrSetsM (Identity . f) ((Identity .) . eq) lm rm valueEqM - :: (MonadThunk t m (NValue t f m), NVConstraint f) + :: forall t f m + . (MonadThunk t m (NValue t f m), NVConstraint f) => NValue t f m -> NValue t f m -> m Bool @@ -171,12 +173,13 @@ valueEqM ( Pure x) y@(Free _) = thunkEqM x =<< thunk (pure y) valueEqM x@(Free _) ( Pure y) = (`thunkEqM` y) =<< thunk (pure x) valueEqM (Free (NValue' (extract -> x))) (Free (NValue' (extract -> y))) = valueFEqM - (compareAttrSetsM f valueEqM) + (compareAttrSetsM findNVStr valueEqM) valueEqM x y where - f = + findNVStr :: NValue t f m -> m (Maybe NixString) + findNVStr = free (pure . (\case @@ -190,6 +193,8 @@ valueEqM (Free (NValue' (extract -> x))) (Free (NValue' (extract -> y))) = _ -> mempty ) +-- This function has mutual recursion with `valueEqM`, and this function so far is not used across the project, +-- but that one is. thunkEqM :: (MonadThunk t m (NValue t f m), NVConstraint f) => t -> t -> m Bool thunkEqM lt rt = do @@ -198,9 +203,10 @@ thunkEqM lt rt = let unsafePtrEq = - case (lt, rt) of - (thunkId -> lid, thunkId -> rid) | lid == rid -> pure True - _ -> valueEqM lv rv + bool + (valueEqM lv rv) + (pure True) + $ on (==) thunkId lt rt case (lv, rv) of (NVClosure _ _, NVClosure _ _) -> unsafePtrEq From d0f9ff3ebf259551db5a8e3e3f939128c70307ac Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Mon, 24 Jan 2022 18:24:51 +0200 Subject: [PATCH 36/70] Value.Equal: compareAttrSetsM: refactor --- src/Nix/Value/Equal.hs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/Nix/Value/Equal.hs b/src/Nix/Value/Equal.hs index f4437f407..e711f9af1 100644 --- a/src/Nix/Value/Equal.hs +++ b/src/Nix/Value/Equal.hs @@ -141,17 +141,14 @@ compareAttrSetsM f eq lm rm = do b <- on (liftA2 (&&)) (isDerivationM f) lm rm bool - compareAttrs - (maybe - compareAttrs - (uncurry eq) - outPaths - ) + id + (`fromMaybe` outPaths) b + compareAttrs where compareAttrs = alignEqM eq lm rm - outPaths = on (liftA2 (,)) (HashMap.Lazy.lookup "outPath") lm rm + outPaths = on (liftA2 eq) (HashMap.Lazy.lookup "outPath") lm rm compareAttrSets :: (t -> Maybe NixString) From fc3f327636480103e07c4646fa46cb98dac031c2 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Wed, 26 Jan 2022 02:30:28 +0200 Subject: [PATCH 37/70] Parser: add NOp class & instances --- src/Nix/Parser.hs | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/Nix/Parser.hs b/src/Nix/Parser.hs index 4c4b4c9e9..72889e872 100644 --- a/src/Nix/Parser.hs +++ b/src/Nix/Parser.hs @@ -527,6 +527,26 @@ data NOperatorDef | NSpecialDef NSpecialOp OperatorInfo deriving (Eq, Ord, Generic, Typeable, Data, Show, NFData) +-- -- | Class to get a private free construction to abstract away the gap between the Nix operation types +-- -- 'NUnaryOp', 'NBinaryOp', 'NSpecialOp'. +-- -- And in doing remove 'OperatorInfo' from existance. +class NOp a where + getOpDef :: a -> OperatorInfo + getOpPrecedence :: a -> NOpPrecedence + +instance NOp NUnaryOp where + getOpDef op = getOperatorInfo unaryOpInfMap op + getOpPrecedence = precedence . getOpDef + +instance NOp NBinaryOp where + getOpDef op = getOperatorInfo binOpInfMap op + getOpPrecedence = precedence . getOpDef + +instance NOp NSpecialOp where + getOpDef op = getOperatorInfo specOpInfMap op + getOpPrecedence = precedence . getOpDef + + prefix :: NUnaryOp -> NOpPrecedence -> NOpName -> (NOperatorDef, Operator Parser NExprLoc) prefix op precedence name = (NUnaryDef op precedence name, Prefix $ manyUnaryOp $ opWithLoc annNUnary op name) @@ -611,13 +631,13 @@ getOperatorInfo :: Ord k => Map k OperatorInfo -> k -> OperatorInfo getOperatorInfo mp k = M.findWithDefault (OperatorInfo NAssoc 1 "Impossible, the key should be in the operator map.") k mp getUnaryOperator :: NUnaryOp -> OperatorInfo -getUnaryOperator = getOperatorInfo unaryOpInfMap +getUnaryOperator = getOpDef getBinaryOperator :: NBinaryOp -> OperatorInfo -getBinaryOperator = getOperatorInfo binOpInfMap +getBinaryOperator = getOpDef getSpecialOperator :: NSpecialOp -> OperatorInfo -getSpecialOperator = getOperatorInfo specOpInfMap +getSpecialOperator = getOpDef -- ** x: y lambda function From d14bcb23baf3a6c66cc5c6a00e17b5a259bfa202 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Wed, 26 Jan 2022 02:43:31 +0200 Subject: [PATCH 38/70] Parser: argExpr: refactor: return Variadic first --- src/Nix/Parser.hs | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/Nix/Parser.hs b/src/Nix/Parser.hs index 72889e872..0192b768b 100644 --- a/src/Nix/Parser.hs +++ b/src/Nix/Parser.hs @@ -628,7 +628,11 @@ unaryOpInfMap = fromList ] getOperatorInfo :: Ord k => Map k OperatorInfo -> k -> OperatorInfo -getOperatorInfo mp k = M.findWithDefault (OperatorInfo NAssoc 1 "Impossible, the key should be in the operator map.") k mp +getOperatorInfo mp k = + M.findWithDefault + (OperatorInfo NAssoc 1 "Impossible, the key should be in the operator map.") + k + mp getUnaryOperator :: NUnaryOp -> OperatorInfo getUnaryOperator = getOpDef @@ -666,13 +670,13 @@ argExpr = try $ do name <- identifier <* symbol '@' - (pset, variadic) <- params + (variadic, pset) <- params pure $ ParamSet (pure name) variadic pset -- Parameters named by an identifier on the right, or none (`{x, y} @ args`) atRight = do - (pset, variadic) <- params + (variadic, pset) <- params name <- optional $ symbol '@' *> identifier pure $ ParamSet name variadic pset @@ -681,18 +685,20 @@ argExpr = -- Collects the parameters within curly braces. Returns the parameters and -- an flag indication if the parameters are variadic. + getParams :: Parser (Variadic, [(VarName, Maybe NExprLoc)]) getParams = go mempty where -- Attempt to parse `...`. If this succeeds, stop and return True. -- Otherwise, attempt to parse an argument, optionally with a -- default. If this fails, then return what has been accumulated -- so far. - go acc = ((acc, Variadic) <$ symbols "...") <|> getMore + go :: [(VarName, Maybe NExprLoc)] -> Parser (Variadic, [(VarName, Maybe NExprLoc)]) + go acc = ((Variadic, acc) <$ symbols "...") <|> getMore where - getMore :: Parser ([(VarName, Maybe NExprLoc)], Variadic) + getMore :: Parser (Variadic, [(VarName, Maybe NExprLoc)]) getMore = -- Could be nothing, in which just return what we have so far. - option (acc, mempty) $ + option (mempty, acc) $ do -- Get an argument name and an optional default. pair <- @@ -703,7 +709,7 @@ argExpr = let args = acc <> one pair -- Either return this, or attempt to get a comma and restart. - option (args, mempty) $ symbol ',' *> go args + option (mempty, args) $ symbol ',' *> go args nixLambda :: Parser NExprLoc nixLambda = From 066ff49c5de6d2bfb57ab3fa1b9fc5ce8d36c408 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Wed, 26 Jan 2022 04:08:04 +0200 Subject: [PATCH 39/70] Parser: m refactor --- src/Nix/Parser.hs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Nix/Parser.hs b/src/Nix/Parser.hs index 0192b768b..2709bae84 100644 --- a/src/Nix/Parser.hs +++ b/src/Nix/Parser.hs @@ -322,17 +322,16 @@ indented = try $ do indentedQuotationMark - (Plain <$> ("''" <$ char '\'' <|> "$" <$ char '$')) + Plain <$> ("''" <$ char '\'' <|> "$" <$ char '$') <|> do - _ <- char '\\' - c <- escapeCode + c <- char '\\' *> escapeCode pure $ bool EscapedNewline (Plain $ one c) - (c /= '\n') + ('\n' /= c) -- | Enclosed into indented quatation "'' ''" inIndentedQuotation :: Parser a -> Parser a From a249ffe152b15afd63e2dccb1053b535361b9149 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Wed, 26 Jan 2022 05:23:31 +0200 Subject: [PATCH 40/70] Parser: refactor: groundwork to rm OperatorInfo: add class NOp --- src/Nix/Parser.hs | 136 +++++++++++++++++++++++++++++----------------- 1 file changed, 85 insertions(+), 51 deletions(-) diff --git a/src/Nix/Parser.hs b/src/Nix/Parser.hs index 2709bae84..f03322e64 100644 --- a/src/Nix/Parser.hs +++ b/src/Nix/Parser.hs @@ -518,6 +518,8 @@ data NAssoc | NAssocRight deriving (Eq, Ord, Generic, Typeable, Data, Show, NFData) +-- 2022-01-26: NOTE: Maybe split up this type into according? Would make NOp class total. + -- | Single operator grammar entries. data NOperatorDef = NAppDef NOpPrecedence NOpName @@ -526,24 +528,94 @@ data NOperatorDef | NSpecialDef NSpecialOp OperatorInfo deriving (Eq, Ord, Generic, Typeable, Data, Show, NFData) --- -- | Class to get a private free construction to abstract away the gap between the Nix operation types --- -- 'NUnaryOp', 'NBinaryOp', 'NSpecialOp'. --- -- And in doing remove 'OperatorInfo' from existance. + +-- 2022-01-26: NOTE: After `OperatorInfo` type is removed from code base +-- , think to remove these maps in favour of direct pattern matching in instances. +-- That would make those instances total. +unaryOpDefMap :: Map NUnaryOp NOperatorDef +unaryOpDefMap = fromList + [ (NNeg, NUnaryDef NNeg 3 "-") + , (NNot, NUnaryDef NNot 8 "!") + ] + +binaryOpDefMap :: Map NBinaryOp NOperatorDef +binaryOpDefMap = fromList + [ (NConcat, NBinaryDef NConcat $ OperatorInfo NAssocRight 5 "++") + , (NMult , NBinaryDef NMult $ OperatorInfo NAssocLeft 6 "*" ) + , (NDiv , NBinaryDef NDiv $ OperatorInfo NAssocLeft 6 "/" ) + , (NPlus , NBinaryDef NPlus $ OperatorInfo NAssocLeft 7 "+" ) + , (NMinus , NBinaryDef NMinus $ OperatorInfo NAssocLeft 7 "-" ) + , (NUpdate, NBinaryDef NUpdate $ OperatorInfo NAssocRight 9 "//") + , (NLt , NBinaryDef NLt $ OperatorInfo NAssocLeft 10 "<" ) + , (NLte , NBinaryDef NLte $ OperatorInfo NAssocLeft 10 "<=") + , (NGt , NBinaryDef NGt $ OperatorInfo NAssocLeft 10 ">" ) + , (NGte , NBinaryDef NGte $ OperatorInfo NAssocLeft 10 ">=") + , (NEq , NBinaryDef NEq $ OperatorInfo NAssoc 11 "==") + , (NNEq , NBinaryDef NNEq $ OperatorInfo NAssoc 11 "!=") + , (NAnd , NBinaryDef NAnd $ OperatorInfo NAssocLeft 12 "&&") + , (NOr , NBinaryDef NOr $ OperatorInfo NAssocLeft 13 "||") + , (NImpl , NBinaryDef NImpl $ OperatorInfo NAssocRight 14 "->") + ] + +specOpDefMap :: Map NSpecialOp NOperatorDef +specOpDefMap = fromList + [ (NSelectOp , NSpecialDef NSelectOp $ OperatorInfo NAssocLeft 1 ".") + , (NHasAttrOp, NSpecialDef NHasAttrOp $ OperatorInfo NAssocLeft 4 "?") + ] + +-- 2022-01-26: NOTE: When total - make sure to hide & inline all these instances to get free solution. +-- | Class to get a private free construction to abstract away the gap between the Nix operation types +-- 'NUnaryOp', 'NBinaryOp', 'NSpecialOp'. +-- And in doing remove 'OperatorInfo' from existance. class NOp a where - getOpDef :: a -> OperatorInfo + getOpDef :: a -> NOperatorDef getOpPrecedence :: a -> NOpPrecedence + getOpInf :: a -> OperatorInfo instance NOp NUnaryOp where - getOpDef op = getOperatorInfo unaryOpInfMap op - getOpPrecedence = precedence . getOpDef + getOpDef op = + M.findWithDefault + (error "Impossible happened: unary operation should be includded into the definition map.") + op + unaryOpDefMap + getOpPrecedence = fun . getOpDef + where + fun (NUnaryDef _op prec _name) = prec + fun _ = error "Impossible happened, match should been `show NUnaryDef`." + getOpInf = fun . getOpDef + where + fun (NUnaryDef _op prec name) = OperatorInfo NAssoc prec name + fun _ = error "Impossible happened, match should been `NUnaryDef`." instance NOp NBinaryOp where - getOpDef op = getOperatorInfo binOpInfMap op - getOpPrecedence = precedence . getOpDef + getOpDef op = + M.findWithDefault + (error "Impossible, binary operation should be includded into the definition map.") + op + binaryOpDefMap + getOpPrecedence = fun . getOpDef + where + fun (NBinaryDef _op opInfo) = precedence opInfo + fun _ = error "Impossible happened, match should been 'NBinaryDef'." + getOpInf = fun . getOpDef + where + fun (NBinaryDef _op operInfo) = operInfo + fun _ = error "Impossible happened, match should been `NBinaryDef`." instance NOp NSpecialOp where - getOpDef op = getOperatorInfo specOpInfMap op - getOpPrecedence = precedence . getOpDef + getOpDef op = + M.findWithDefault + (error "Impossible, special operation should be includded into the definition map.") + op + specOpDefMap + getOpPrecedence = fun . getOpDef + where + fun (NSpecialDef _op opInfo) = precedence opInfo + fun _ = error "Impossible happened, special operation should been matched." + getOpInf = fun . getOpDef + where + fun (NSpecialDef _op operInfo) = operInfo + fun _ = error "Impossible happened, special operation should been matched." prefix :: NUnaryOp -> NOpPrecedence -> NOpName -> (NOperatorDef, Operator Parser NExprLoc) @@ -595,52 +667,14 @@ appOperatorInfo = , operatorName = " " } -binOpInfMap :: Map NBinaryOp OperatorInfo -binOpInfMap = fromList - [ (NConcat, OperatorInfo NAssocRight 5 "++") - , (NMult , OperatorInfo NAssocLeft 6 "*" ) - , (NDiv , OperatorInfo NAssocLeft 6 "/" ) - , (NPlus , OperatorInfo NAssocLeft 7 "+" ) - , (NMinus , OperatorInfo NAssocLeft 7 "-" ) - , (NUpdate, OperatorInfo NAssocRight 9 "//") - , (NLt , OperatorInfo NAssocLeft 10 "<" ) - , (NLte , OperatorInfo NAssocLeft 10 "<=") - , (NGt , OperatorInfo NAssocLeft 10 ">" ) - , (NGte , OperatorInfo NAssocLeft 10 ">=") - , (NEq , OperatorInfo NAssoc 11 "==") - , (NNEq , OperatorInfo NAssoc 11 "!=") - , (NAnd , OperatorInfo NAssocLeft 12 "&&") - , (NOr , OperatorInfo NAssocLeft 13 "||") - , (NImpl , OperatorInfo NAssocRight 14 "->") - ] - -specOpInfMap :: Map NSpecialOp OperatorInfo -specOpInfMap = fromList - [ (NSelectOp , OperatorInfo NAssocLeft 1 ".") - , (NHasAttrOp, OperatorInfo NAssocLeft 4 "?") - ] - -unaryOpInfMap :: Map NUnaryOp OperatorInfo -unaryOpInfMap = fromList - [ (NNeg, OperatorInfo NAssoc 3 "-") - , (NNot, OperatorInfo NAssoc 8 "!") - ] - -getOperatorInfo :: Ord k => Map k OperatorInfo -> k -> OperatorInfo -getOperatorInfo mp k = - M.findWithDefault - (OperatorInfo NAssoc 1 "Impossible, the key should be in the operator map.") - k - mp - getUnaryOperator :: NUnaryOp -> OperatorInfo -getUnaryOperator = getOpDef +getUnaryOperator = getOpInf getBinaryOperator :: NBinaryOp -> OperatorInfo -getBinaryOperator = getOpDef +getBinaryOperator = getOpInf getSpecialOperator :: NSpecialOp -> OperatorInfo -getSpecialOperator = getOpDef +getSpecialOperator = getOpInf -- ** x: y lambda function From adc200229f7789bd01624f356cc304672b44dfb7 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Wed, 26 Jan 2022 05:32:57 +0200 Subject: [PATCH 41/70] Parser: m refactor --- src/Nix/Parser.hs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Nix/Parser.hs b/src/Nix/Parser.hs index f03322e64..258525dd4 100644 --- a/src/Nix/Parser.hs +++ b/src/Nix/Parser.hs @@ -798,8 +798,8 @@ nixAssert = -- ** . - reference (selector) into attr -selDot :: Parser () -selDot = label "." $ try (symbol '.' *> notFollowedBy nixPath) +selectorDot :: Parser () +selectorDot = label "." $ try (symbol '.' *> notFollowedBy nixPath) keyName :: Parser (NKeyName NExprLoc) keyName = dynamicKey <|> staticKey @@ -809,7 +809,7 @@ keyName = dynamicKey <|> staticKey nixSelector :: Parser (AnnUnit SrcSpan (NAttrPath NExprLoc)) nixSelector = - annotateLocation1 $ fromList <$> keyName `sepBy1` selDot + annotateLocation1 $ fromList <$> keyName `sepBy1` selectorDot nixSelect :: Parser NExprLoc -> Parser NExprLoc nixSelect term = @@ -818,11 +818,11 @@ nixSelect term = liftA2 build term (optional $ - liftA2 (,) - (selDot *> nixSelector) + liftA2 (flip (,)) + (selectorDot *> nixSelector) (optional $ reserved "or" *> nixTerm) ) - continues <- optional $ lookAhead selDot + continues <- optional $ lookAhead selectorDot maybe id @@ -833,14 +833,14 @@ nixSelect term = build :: NExprLoc -> Maybe - ( AnnUnit SrcSpan (NAttrPath NExprLoc) - , Maybe NExprLoc + ( Maybe NExprLoc + , AnnUnit SrcSpan (NAttrPath NExprLoc) ) -> NExprLoc build t = maybe t - (\ (a, m) -> (`annNSelect` t) m a) + (uncurry (`annNSelect` t)) -- ** _ - syntax hole From d56f3405bd3f54525ca7368704034ce5fa5a546e Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Wed, 26 Jan 2022 16:09:49 +0200 Subject: [PATCH 42/70] Value.Equal: compareAttrSets: refactor --- src/Nix/Value/Equal.hs | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/Nix/Value/Equal.hs b/src/Nix/Value/Equal.hs index e711f9af1..57aea9d53 100644 --- a/src/Nix/Value/Equal.hs +++ b/src/Nix/Value/Equal.hs @@ -138,17 +138,14 @@ compareAttrSetsM -> AttrSet t -> m Bool compareAttrSetsM f eq lm rm = - do - b <- on (liftA2 (&&)) (isDerivationM f) lm rm - bool - id - (`fromMaybe` outPaths) - b - compareAttrs + bool + compareAttrs + (fromMaybe compareAttrs equalOutPaths) + =<< areDerivations where - compareAttrs = alignEqM eq lm rm - - outPaths = on (liftA2 eq) (HashMap.Lazy.lookup "outPath") lm rm + areDerivations = on (liftA2 (&&)) (isDerivationM f ) lm rm + equalOutPaths = on (liftA2 eq) (HashMap.Lazy.lookup "outPath") lm rm + compareAttrs = alignEqM eq lm rm compareAttrSets :: (t -> Maybe NixString) From 667889b1aa25c01e8f5b0639bd21e1ba1f6fafc1 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Wed, 26 Jan 2022 16:22:55 +0200 Subject: [PATCH 43/70] hlint: mapM -> traverse --- .hlint.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.hlint.yaml b/.hlint.yaml index ac15e6117..b26bab946 100644 --- a/.hlint.yaml +++ b/.hlint.yaml @@ -2740,3 +2740,8 @@ lhs: "map" note: "Use `fmap`" rhs: fmap + +- hint: + lhs: "mapM" + note: "Use `traverse`" + rhs: traverse From 9aecc9d5e810d35f66482a9ad4ef5daa45e71f91 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Wed, 26 Jan 2022 16:23:27 +0200 Subject: [PATCH 44/70] Parser: refactor --- src/Nix/Parser.hs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/Nix/Parser.hs b/src/Nix/Parser.hs index 258525dd4..6da7b0b98 100644 --- a/src/Nix/Parser.hs +++ b/src/Nix/Parser.hs @@ -138,14 +138,11 @@ reserved :: Text -> Parser () reserved n = lexeme $ try $ chunk n *> lookAhead (void (satisfy reservedEnd) <|> eof) -exprAfterP :: Parser a -> Parser NExprLoc -exprAfterP p = p *> nixExpr - exprAfterSymbol :: Char -> Parser NExprLoc -exprAfterSymbol p = exprAfterP $ symbol p +exprAfterSymbol p = symbol p *> nixExpr exprAfterReservedWord :: Text -> Parser NExprLoc -exprAfterReservedWord word = exprAfterP $ reserved word +exprAfterReservedWord word = reserved word *> nixExpr -- | A literal copy of @megaparsec@ one but with addition of the @\r@ for Windows EOL case (@\r\n@). -- Overall, parser should simply @\r\n -> \n@. @@ -758,14 +755,16 @@ nixLet = annotateNamedLocation "let block" $ reserved "let" *> (letBody <|> letBinders) where + -- | Expressions `let {..., body = ...}' are just desugared + -- into `(rec {..., body = ...}).body'. + letBody = (\ expr -> NSelect Nothing expr (one $ StaticKey "body")) <$> attrset + where + attrset = annotateLocation $ NSet Recursive <$> braces nixBinders + -- | Regular `let` letBinders = liftA2 NLet nixBinders (exprAfterReservedWord "in") - -- Let expressions `let {..., body = ...}' are just desugared - -- into `(rec {..., body = ...}).body'. - letBody = (\x -> NSelect Nothing x (one $ StaticKey "body")) <$> aset - aset = annotateLocation $ NSet Recursive <$> braces nixBinders -- ** if then else From 816e928ed93e1980a1a6e98f3bbbd2bef6502f83 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Wed, 26 Jan 2022 19:45:54 +0200 Subject: [PATCH 45/70] Parser: NOperatorDef: rm OperatorInfo use form the data type --- src/Nix/Parser.hs | 92 +++++++++++++++++++++++++++++++---------------- 1 file changed, 61 insertions(+), 31 deletions(-) diff --git a/src/Nix/Parser.hs b/src/Nix/Parser.hs index 6da7b0b98..eae8fe083 100644 --- a/src/Nix/Parser.hs +++ b/src/Nix/Parser.hs @@ -462,6 +462,7 @@ nixSearchPath = -- ** Operators +-- 2022-01-26: NOTE: Rename to 'literal' newtype NOpName = NOpName Text deriving (Eq, Ord, Generic, Typeable, Data, Show, NFData) @@ -521,8 +522,8 @@ data NAssoc data NOperatorDef = NAppDef NOpPrecedence NOpName | NUnaryDef NUnaryOp NOpPrecedence NOpName - | NBinaryDef NBinaryOp OperatorInfo - | NSpecialDef NSpecialOp OperatorInfo + | NBinaryDef NBinaryOp NAssoc NOpPrecedence NOpName + | NSpecialDef NSpecialOp NAssoc NOpPrecedence NOpName deriving (Eq, Ord, Generic, Typeable, Data, Show, NFData) @@ -537,27 +538,27 @@ unaryOpDefMap = fromList binaryOpDefMap :: Map NBinaryOp NOperatorDef binaryOpDefMap = fromList - [ (NConcat, NBinaryDef NConcat $ OperatorInfo NAssocRight 5 "++") - , (NMult , NBinaryDef NMult $ OperatorInfo NAssocLeft 6 "*" ) - , (NDiv , NBinaryDef NDiv $ OperatorInfo NAssocLeft 6 "/" ) - , (NPlus , NBinaryDef NPlus $ OperatorInfo NAssocLeft 7 "+" ) - , (NMinus , NBinaryDef NMinus $ OperatorInfo NAssocLeft 7 "-" ) - , (NUpdate, NBinaryDef NUpdate $ OperatorInfo NAssocRight 9 "//") - , (NLt , NBinaryDef NLt $ OperatorInfo NAssocLeft 10 "<" ) - , (NLte , NBinaryDef NLte $ OperatorInfo NAssocLeft 10 "<=") - , (NGt , NBinaryDef NGt $ OperatorInfo NAssocLeft 10 ">" ) - , (NGte , NBinaryDef NGte $ OperatorInfo NAssocLeft 10 ">=") - , (NEq , NBinaryDef NEq $ OperatorInfo NAssoc 11 "==") - , (NNEq , NBinaryDef NNEq $ OperatorInfo NAssoc 11 "!=") - , (NAnd , NBinaryDef NAnd $ OperatorInfo NAssocLeft 12 "&&") - , (NOr , NBinaryDef NOr $ OperatorInfo NAssocLeft 13 "||") - , (NImpl , NBinaryDef NImpl $ OperatorInfo NAssocRight 14 "->") + [ (NConcat, NBinaryDef NConcat NAssocRight 5 "++") + , (NMult , NBinaryDef NMult NAssocLeft 6 "*" ) + , (NDiv , NBinaryDef NDiv NAssocLeft 6 "/" ) + , (NPlus , NBinaryDef NPlus NAssocLeft 7 "+" ) + , (NMinus , NBinaryDef NMinus NAssocLeft 7 "-" ) + , (NUpdate, NBinaryDef NUpdate NAssocRight 9 "//") + , (NLt , NBinaryDef NLt NAssocLeft 10 "<" ) + , (NLte , NBinaryDef NLte NAssocLeft 10 "<=") + , (NGt , NBinaryDef NGt NAssocLeft 10 ">" ) + , (NGte , NBinaryDef NGte NAssocLeft 10 ">=") + , (NEq , NBinaryDef NEq NAssoc 11 "==") + , (NNEq , NBinaryDef NNEq NAssoc 11 "!=") + , (NAnd , NBinaryDef NAnd NAssocLeft 12 "&&") + , (NOr , NBinaryDef NOr NAssocLeft 13 "||") + , (NImpl , NBinaryDef NImpl NAssocRight 14 "->") ] specOpDefMap :: Map NSpecialOp NOperatorDef specOpDefMap = fromList - [ (NSelectOp , NSpecialDef NSelectOp $ OperatorInfo NAssocLeft 1 ".") - , (NHasAttrOp, NSpecialDef NHasAttrOp $ OperatorInfo NAssocLeft 4 "?") + [ (NSelectOp , NSpecialDef NSelectOp NAssocLeft 1 ".") + , (NHasAttrOp, NSpecialDef NHasAttrOp NAssocLeft 4 "?") ] -- 2022-01-26: NOTE: When total - make sure to hide & inline all these instances to get free solution. @@ -566,7 +567,9 @@ specOpDefMap = fromList -- And in doing remove 'OperatorInfo' from existance. class NOp a where getOpDef :: a -> NOperatorDef + getOpAssoc :: a -> NAssoc getOpPrecedence :: a -> NOpPrecedence + getOpName :: a -> NOpName getOpInf :: a -> OperatorInfo instance NOp NUnaryOp where @@ -575,14 +578,23 @@ instance NOp NUnaryOp where (error "Impossible happened: unary operation should be includded into the definition map.") op unaryOpDefMap + -- 2022-01-26: NOTE: This instance is a lie, - remove it after `OperatorInfo` is removed from the module. + getOpAssoc = fun . getOpDef + where + fun (NUnaryDef _op _prec _name) = NAssoc + fun _ = error "Impossible happened, unary operation should been matched." getOpPrecedence = fun . getOpDef where fun (NUnaryDef _op prec _name) = prec - fun _ = error "Impossible happened, match should been `show NUnaryDef`." + fun _ = error "Impossible happened, unary operation should been matched." + getOpName = fun . getOpDef + where + fun (NUnaryDef _op _prec name) = name + fun _ = error "Impossible happened, unary operation should been matched." getOpInf = fun . getOpDef where fun (NUnaryDef _op prec name) = OperatorInfo NAssoc prec name - fun _ = error "Impossible happened, match should been `NUnaryDef`." + fun _ = error "Impossible happened, unary operation should been matched." instance NOp NBinaryOp where getOpDef op = @@ -590,14 +602,22 @@ instance NOp NBinaryOp where (error "Impossible, binary operation should be includded into the definition map.") op binaryOpDefMap + getOpAssoc = fun . getOpDef + where + fun (NBinaryDef _op assoc _prec _name) = assoc + fun _ = error "Impossible happened, binary operation should been matched." getOpPrecedence = fun . getOpDef where - fun (NBinaryDef _op opInfo) = precedence opInfo - fun _ = error "Impossible happened, match should been 'NBinaryDef'." + fun (NBinaryDef _op _assoc prec _name) = prec + fun _ = error "Impossible happened, binary operation should been matched." + getOpName = fun . getOpDef + where + fun (NBinaryDef _op _assoc _prec name) = name + fun _ = error "Impossible happened, binary operation should been matched." getOpInf = fun . getOpDef where - fun (NBinaryDef _op operInfo) = operInfo - fun _ = error "Impossible happened, match should been `NBinaryDef`." + fun (NBinaryDef _op assoc prec name) = OperatorInfo assoc prec name + fun _ = error "Impossible happened, binary operation should been matched." instance NOp NSpecialOp where getOpDef op = @@ -605,13 +625,21 @@ instance NOp NSpecialOp where (error "Impossible, special operation should be includded into the definition map.") op specOpDefMap + getOpAssoc = fun . getOpDef + where + fun (NSpecialDef _op assoc _prec _name) = assoc + fun _ = error "Impossible happened, special operation should been matched." getOpPrecedence = fun . getOpDef where - fun (NSpecialDef _op opInfo) = precedence opInfo + fun (NSpecialDef _op _assoc prec _name) = prec + fun _ = error "Impossible happened, special operation should been matched." + getOpName = fun . getOpDef + where + fun (NSpecialDef _op _assoc _prec name) = name fun _ = error "Impossible happened, special operation should been matched." getOpInf = fun . getOpDef where - fun (NSpecialDef _op operInfo) = operInfo + fun (NSpecialDef _op assoc prec name) = OperatorInfo assoc prec name fun _ = error "Impossible happened, special operation should been matched." @@ -628,11 +656,13 @@ binary :: NBinaryOp -> (NOperatorDef, Operator Parser NExprLoc) binary op = - ( NBinaryDef op operatorInfo - , mapAssocToInfix (associativity operatorInfo) $ opWithLoc annNBinary op $ operatorName operatorInfo + ( def + , mapAssocToInfix assoc $ opWithLoc annNBinary op name ) where - operatorInfo = getBinaryOperator op + assoc = getOpAssoc op + name = getOpName op + def = getOpDef op mapAssocToInfix :: NAssoc -> m (a -> a -> a) -> Operator m a mapAssocToInfix NAssocLeft = InfixL @@ -883,7 +913,7 @@ nixOperators selector = one $ prefix NNeg 3 "-" , {- 4 -} one - ( NSpecialDef NHasAttrOp $ getSpecialOperator NHasAttrOp + ( getOpDef NHasAttrOp , Postfix $ symbol '?' *> (flip annNHasAttr <$> selector) ) , {- 5 -} From 00a834cbd5aaeb197fbf92b165a234710db8908b Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Wed, 26 Jan 2022 19:51:29 +0200 Subject: [PATCH 46/70] Parser: m note --- src/Nix/Parser.hs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Nix/Parser.hs b/src/Nix/Parser.hs index eae8fe083..91e467842 100644 --- a/src/Nix/Parser.hs +++ b/src/Nix/Parser.hs @@ -489,6 +489,9 @@ operator (coerce -> op) = opWithLoc :: (AnnUnit SrcSpan o -> a) -> o -> NOpName -> Parser a opWithLoc f op name = f . (op <$) <$> annotateLocation1 (operator name) +-- 2022-01-26: NOTE: Make presedence free and type safe by moving it into type level: +-- https://youtu.be/qaPdg0mZavM?t=1757 +-- https://wiki.haskell.org/The_Monad.Reader/Issue5/Number_Param_Types newtype NOpPrecedence = NOpPrecedence Int deriving (Eq, Ord, Generic, Bounded, Typeable, Data, Show, NFData) From a9efefb249516e19e390bef77789809a81808ecd Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Wed, 26 Jan 2022 20:13:49 +0200 Subject: [PATCH 47/70] mv OperatorInfo: mod (Parser->Pretty) --- src/Nix/Parser.hs | 60 +++++------------------------------------------ src/Nix/Pretty.hs | 45 +++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 54 deletions(-) diff --git a/src/Nix/Parser.hs b/src/Nix/Parser.hs index 91e467842..f361c65f6 100644 --- a/src/Nix/Parser.hs +++ b/src/Nix/Parser.hs @@ -15,15 +15,11 @@ module Nix.Parser , parseFromText , Result , reservedNames + , NAssoc(..) + , NOpPrecedence(..) , NOpName(..) - , OperatorInfo(..) , NSpecialOp(..) - , NAssoc(..) - , NOperatorDef - , getUnaryOperator - , appOperatorInfo - , getBinaryOperator - , getSpecialOperator + , NOperatorDef(..) , nixExpr , nixExprAlgebra , nixSet @@ -39,6 +35,9 @@ module Nix.Parser , nixBool , nixNull , whiteSpace + + -- 2022-01-26: NOTE: Try to hide it after OperatorInfo is removed + , NOp(..) ) where @@ -573,7 +572,6 @@ class NOp a where getOpAssoc :: a -> NAssoc getOpPrecedence :: a -> NOpPrecedence getOpName :: a -> NOpName - getOpInf :: a -> OperatorInfo instance NOp NUnaryOp where getOpDef op = @@ -594,10 +592,6 @@ instance NOp NUnaryOp where where fun (NUnaryDef _op _prec name) = name fun _ = error "Impossible happened, unary operation should been matched." - getOpInf = fun . getOpDef - where - fun (NUnaryDef _op prec name) = OperatorInfo NAssoc prec name - fun _ = error "Impossible happened, unary operation should been matched." instance NOp NBinaryOp where getOpDef op = @@ -617,10 +611,6 @@ instance NOp NBinaryOp where where fun (NBinaryDef _op _assoc _prec name) = name fun _ = error "Impossible happened, binary operation should been matched." - getOpInf = fun . getOpDef - where - fun (NBinaryDef _op assoc prec name) = OperatorInfo assoc prec name - fun _ = error "Impossible happened, binary operation should been matched." instance NOp NSpecialOp where getOpDef op = @@ -640,10 +630,6 @@ instance NOp NSpecialOp where where fun (NSpecialDef _op _assoc _prec name) = name fun _ = error "Impossible happened, special operation should been matched." - getOpInf = fun . getOpDef - where - fun (NSpecialDef _op assoc prec name) = OperatorInfo assoc prec name - fun _ = error "Impossible happened, special operation should been matched." prefix :: NUnaryOp -> NOpPrecedence -> NOpName -> (NOperatorDef, Operator Parser NExprLoc) @@ -672,40 +658,6 @@ mapAssocToInfix NAssocLeft = InfixL mapAssocToInfix NAssoc = InfixN mapAssocToInfix NAssocRight = InfixR --- 2021-11-09: NOTE: rename OperatorInfo accessors to `get*` --- 2021-08-10: NOTE: --- All this is a sidecar: --- * This type --- * getUnaryOperation --- * getBinaryOperation --- * getSpecialOperation --- can reduced in favour of adding precedence field into @NOperatorDef@. --- details: https://github.com/haskell-nix/hnix/issues/982 -data OperatorInfo = - OperatorInfo - { associativity :: NAssoc - , precedence :: NOpPrecedence - , operatorName :: NOpName - } - deriving (Eq, Ord, Generic, Typeable, Data, NFData, Show) - -appOperatorInfo :: OperatorInfo -appOperatorInfo = - OperatorInfo - { precedence = 1 -- inside the code it is 1, inside the Nix they are +1 - , associativity = NAssocLeft - , operatorName = " " - } - -getUnaryOperator :: NUnaryOp -> OperatorInfo -getUnaryOperator = getOpInf - -getBinaryOperator :: NBinaryOp -> OperatorInfo -getBinaryOperator = getOpInf - -getSpecialOperator :: NSpecialOp -> OperatorInfo -getSpecialOperator = getOpInf - -- ** x: y lambda function -- | Gets all of the arguments for a function. diff --git a/src/Nix/Pretty.hs b/src/Nix/Pretty.hs index a278285d1..88e8b07dc 100644 --- a/src/Nix/Pretty.hs +++ b/src/Nix/Pretty.hs @@ -1,5 +1,6 @@ {-# language CPP #-} {-# language AllowAmbiguousTypes #-} +{-# language DeriveAnyClass #-} {-# options_ghc -fno-warn-name-shadowing #-} @@ -7,6 +8,7 @@ module Nix.Pretty where import Nix.Prelude hiding ( toList, group ) import Control.Monad.Free ( Free(Free) ) +import Data.Data ( Data(..) ) import Data.Fix ( Fix(..) , foldFix ) import Data.HashMap.Lazy ( toList ) @@ -29,6 +31,49 @@ import Nix.String import Nix.Thunk import Nix.Value +-- 2021-11-09: NOTE: rename OperatorInfo accessors to `get*` +-- 2021-08-10: NOTE: +-- All this is a sidecar: +-- * This type +-- * getUnaryOperation +-- * getBinaryOperation +-- * getSpecialOperation +-- can reduced in favour of adding precedence field into @NOperatorDef@. +-- details: https://github.com/haskell-nix/hnix/issues/982 +data OperatorInfo = + OperatorInfo + { associativity :: NAssoc + , precedence :: NOpPrecedence + , operatorName :: NOpName + } + deriving (Eq, Ord, Generic, Typeable, Data, NFData, Show) + +appOperatorInfo :: OperatorInfo +appOperatorInfo = + OperatorInfo + { precedence = 1 -- inside the code it is 1, inside the Nix it is 2 + , associativity = NAssocLeft + , operatorName = " " + } + +getUnaryOperator :: NUnaryOp -> OperatorInfo +getUnaryOperator = fun . getOpDef + where + fun (NUnaryDef _op prec name) = OperatorInfo NAssoc prec name + fun _ = error "Impossible happened, unary operation should been matched." + +getBinaryOperator :: NBinaryOp -> OperatorInfo +getBinaryOperator = fun . getOpDef + where + fun (NBinaryDef _op assoc prec name) = OperatorInfo assoc prec name + fun _ = error "Impossible happened, binary operation should been matched." + +getSpecialOperator :: NSpecialOp -> OperatorInfo +getSpecialOperator = fun . getOpDef + where + fun (NSpecialDef _op assoc prec name) = OperatorInfo assoc prec name + fun _ = error "Impossible happened, special operation should been matched." + -- | This type represents a pretty printed nix expression -- together with some information about the expression. data NixDoc ann = NixDoc From 15cd046b28ae348db2e3e7922bc533b1d7b539ac Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Wed, 26 Jan 2022 20:18:04 +0200 Subject: [PATCH 48/70] Pretty: rm appOp --- ChangeLog.md | 1 + src/Nix/Pretty.hs | 7 ++----- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index f6c4f2ee6..e4a010467 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -10,6 +10,7 @@ * `Nix.Value` * [(link)](https://github.com/haskell-nix/hnix/pull/1046/files) Unify builder `mkNV*` and `NV*` patterns by bidirectional synonyms, a lot of builders `mkNV*` are removed, and merged to `NV*`. e.g. instead of builder `mkNVList`, `NVList` should be used. * [(link)](https://github.com/haskell-nix/hnix/pull/1046/files) Constraint `NVConstraint f = (Comonad f, Applicative f)` was introduced, in order to unify builder `mkNV*` and `NV*` patterns. + * [(link)](https://github.com/haskell-nix/hnix/pull/1047/files) `Nix.Pretty`: rm `appOp` ## [(diff)](https://github.com/haskell-nix/hnix/compare/0.15.0...0.16.0#files_bucket) 0.16.0 diff --git a/src/Nix/Pretty.hs b/src/Nix/Pretty.hs index 88e8b07dc..51446ef44 100644 --- a/src/Nix/Pretty.hs +++ b/src/Nix/Pretty.hs @@ -118,11 +118,8 @@ leastPrecedence :: Doc ann -> NixDoc ann leastPrecedence = mkNixDoc $ OperatorInfo NAssoc maxBound "least precedence" -appOp :: OperatorInfo -appOp = appOperatorInfo - appOpNonAssoc :: OperatorInfo -appOpNonAssoc = appOp { associativity = NAssoc } +appOpNonAssoc = appOperatorInfo { associativity = NAssoc } selectOp :: OperatorInfo selectOp = getSpecialOperator NSelectOp @@ -301,7 +298,7 @@ exprFNixDoc = \case , getDoc body ] NApp fun arg -> - mkNixDoc appOp (precedenceWrap appOp fun <> " " <> precedenceWrap appOpNonAssoc arg) + mkNixDoc appOperatorInfo (precedenceWrap appOperatorInfo fun <> " " <> precedenceWrap appOpNonAssoc arg) NBinary op r1 r2 -> mkNixDoc opInfo $ From cf28a83f494f2f391bfaf9ad45a6c1e1ce3ca8a1 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Wed, 26 Jan 2022 21:38:33 +0200 Subject: [PATCH 49/70] Pretty: rm OperatorInfo --- src/Nix/Parser.hs | 45 ++++++++++++----- src/Nix/Pretty.hs | 123 ++++++++++++++++++---------------------------- 2 files changed, 80 insertions(+), 88 deletions(-) diff --git a/src/Nix/Parser.hs b/src/Nix/Parser.hs index f361c65f6..d9b792634 100644 --- a/src/Nix/Parser.hs +++ b/src/Nix/Parser.hs @@ -38,6 +38,7 @@ module Nix.Parser -- 2022-01-26: NOTE: Try to hide it after OperatorInfo is removed , NOp(..) + , appOpDef ) where @@ -506,7 +507,9 @@ instance Num NOpPrecedence where fromInteger = coerce (fromInteger @Int) negate = coerce (negate @Int) -data NSpecialOp = NHasAttrOp | NSelectOp +-- 2022-01-26: NOTE: This type belongs into 'Type.Expr' & be used in NExprF. +data NSpecialOp = + NHasAttrOp | NSelectOp | NTerm deriving (Eq, Ord, Generic, Typeable, Data, Show, NFData) data NAssoc @@ -518,16 +521,18 @@ data NAssoc | NAssocRight deriving (Eq, Ord, Generic, Typeable, Data, Show, NFData) --- 2022-01-26: NOTE: Maybe split up this type into according? Would make NOp class total. - +-- 2022-01-26: NOTE: Maybe split up this type into according set? Would make NOp class total. -- | Single operator grammar entries. data NOperatorDef - = NAppDef NOpPrecedence NOpName - | NUnaryDef NUnaryOp NOpPrecedence NOpName + = NAppDef NOpPrecedence NOpName + | NUnaryDef NUnaryOp NOpPrecedence NOpName | NBinaryDef NBinaryOp NAssoc NOpPrecedence NOpName | NSpecialDef NSpecialOp NAssoc NOpPrecedence NOpName + -- 2022-01-26: NOTE: Ord can be the order of evaluation of precedence (which 'Pretty' printing also accounts for). deriving (Eq, Ord, Generic, Typeable, Data, Show, NFData) +appOpDef :: NOperatorDef +appOpDef = NAppDef 1 " " -- This defined as "2" in Nix lang spec. -- 2022-01-26: NOTE: After `OperatorInfo` type is removed from code base -- , think to remove these maps in favour of direct pattern matching in instances. @@ -631,6 +636,26 @@ instance NOp NSpecialOp where fun (NSpecialDef _op _assoc _prec name) = name fun _ = error "Impossible happened, special operation should been matched." +instance NOp NOperatorDef where + getOpDef op = op + getOpAssoc op = fun op + where + fun (NAppDef _prec _name) = NAssocLeft + fun (NBinaryDef _op assoc _prec _name) = assoc + fun (NSpecialDef _op assoc _prec _name) = assoc + fun _ = error "Impossible happened, operator seems to have no associativity getter defined." + getOpPrecedence = fun . getOpDef + where + fun (NAppDef prec _name) = prec + fun (NBinaryDef _op _assoc prec _name) = prec + fun (NSpecialDef _op _assoc prec _name) = prec + fun _ = error "Impossible happened, operator seems to have no precedence getter defined." + getOpName = fun . getOpDef + where + fun (NAppDef _prec name) = name + fun (NBinaryDef _op _assoc _prec name) = name + fun (NSpecialDef _op _assoc _prec name) = name + fun _ = error "Impossible happened, operator seems to have no name getter defined." prefix :: NUnaryOp -> NOpPrecedence -> NOpName -> (NOperatorDef, Operator Parser NExprLoc) prefix op precedence name = @@ -645,13 +670,9 @@ binary :: NBinaryOp -> (NOperatorDef, Operator Parser NExprLoc) binary op = - ( def - , mapAssocToInfix assoc $ opWithLoc annNBinary op name + ( getOpDef op + , mapAssocToInfix (getOpAssoc op) $ opWithLoc annNBinary op (getOpName op) ) - where - assoc = getOpAssoc op - name = getOpName op - def = getOpDef op mapAssocToInfix :: NAssoc -> m (a -> a -> a) -> Operator m a mapAssocToInfix NAssocLeft = InfixL @@ -860,7 +881,7 @@ nixOperators selector = {- 2 -} one - ( NAppDef 2 " " + ( appOpDef , -- Thanks to Brent Yorgey for showing me this trick! InfixL $ annNApp <$ symbols mempty -- NApp is left associative ) diff --git a/src/Nix/Pretty.hs b/src/Nix/Pretty.hs index 51446ef44..0ea6d00be 100644 --- a/src/Nix/Pretty.hs +++ b/src/Nix/Pretty.hs @@ -1,6 +1,5 @@ {-# language CPP #-} {-# language AllowAmbiguousTypes #-} -{-# language DeriveAnyClass #-} {-# options_ghc -fno-warn-name-shadowing #-} @@ -8,7 +7,6 @@ module Nix.Pretty where import Nix.Prelude hiding ( toList, group ) import Control.Monad.Free ( Free(Free) ) -import Data.Data ( Data(..) ) import Data.Fix ( Fix(..) , foldFix ) import Data.HashMap.Lazy ( toList ) @@ -31,49 +29,6 @@ import Nix.String import Nix.Thunk import Nix.Value --- 2021-11-09: NOTE: rename OperatorInfo accessors to `get*` --- 2021-08-10: NOTE: --- All this is a sidecar: --- * This type --- * getUnaryOperation --- * getBinaryOperation --- * getSpecialOperation --- can reduced in favour of adding precedence field into @NOperatorDef@. --- details: https://github.com/haskell-nix/hnix/issues/982 -data OperatorInfo = - OperatorInfo - { associativity :: NAssoc - , precedence :: NOpPrecedence - , operatorName :: NOpName - } - deriving (Eq, Ord, Generic, Typeable, Data, NFData, Show) - -appOperatorInfo :: OperatorInfo -appOperatorInfo = - OperatorInfo - { precedence = 1 -- inside the code it is 1, inside the Nix it is 2 - , associativity = NAssocLeft - , operatorName = " " - } - -getUnaryOperator :: NUnaryOp -> OperatorInfo -getUnaryOperator = fun . getOpDef - where - fun (NUnaryDef _op prec name) = OperatorInfo NAssoc prec name - fun _ = error "Impossible happened, unary operation should been matched." - -getBinaryOperator :: NBinaryOp -> OperatorInfo -getBinaryOperator = fun . getOpDef - where - fun (NBinaryDef _op assoc prec name) = OperatorInfo assoc prec name - fun _ = error "Impossible happened, binary operation should been matched." - -getSpecialOperator :: NSpecialOp -> OperatorInfo -getSpecialOperator = fun . getOpDef - where - fun (NSpecialDef _op assoc prec name) = OperatorInfo assoc prec name - fun _ = error "Impossible happened, special operation should been matched." - -- | This type represents a pretty printed nix expression -- together with some information about the expression. data NixDoc ann = NixDoc @@ -84,7 +39,7 @@ data NixDoc ann = NixDoc -- the expression tree. For example, in '(a * b) + c', '+' would be the root -- operator. It is needed to determine if we need to wrap the expression in -- parentheses. - , rootOp :: OperatorInfo + , rootOp :: NOperatorDef , wasPath :: Bool -- This is needed so that when a path is used in a selector path -- we can add brackets appropriately } @@ -97,14 +52,15 @@ data NixDoc ann = NixDoc antiquote :: NixDoc ann -> Doc ann antiquote x = "${" <> getDoc x <> "}" -mkNixDoc :: OperatorInfo -> Doc ann -> NixDoc ann +mkNixDoc :: NOperatorDef -> Doc ann -> NixDoc ann mkNixDoc o d = NixDoc { getDoc = d, rootOp = o, wasPath = False } -- | A simple expression is never wrapped in parentheses. The expression -- behaves as if its root operator had a precedence higher than all -- other operators (including function application). simpleExpr :: Doc ann -> NixDoc ann -simpleExpr = mkNixDoc $ OperatorInfo NAssoc minBound "simple expr" +simpleExpr = + mkNixDoc $ NSpecialDef NTerm NAssoc minBound "simple expr" pathExpr :: Doc ann -> NixDoc ann pathExpr d = (simpleExpr d) { wasPath = True } @@ -116,20 +72,18 @@ pathExpr d = (simpleExpr d) { wasPath = True } -- binding). leastPrecedence :: Doc ann -> NixDoc ann leastPrecedence = - mkNixDoc $ OperatorInfo NAssoc maxBound "least precedence" + mkNixDoc $ NSpecialDef NTerm NAssoc maxBound "least precedence" -appOpNonAssoc :: OperatorInfo -appOpNonAssoc = appOperatorInfo { associativity = NAssoc } -selectOp :: OperatorInfo -selectOp = getSpecialOperator NSelectOp +selectOp :: NOperatorDef +selectOp = getOpDef NSelectOp -hasAttrOp :: OperatorInfo -hasAttrOp = getSpecialOperator NHasAttrOp +hasAttrOp :: NOperatorDef +hasAttrOp = getOpDef NHasAttrOp -- | Determine if to return doc wraped into parens, -- according the given operator. -precedenceWrap :: OperatorInfo -> NixDoc ann -> Doc ann +precedenceWrap :: NOperatorDef -> NixDoc ann -> Doc ann precedenceWrap op subExpr = maybeWrap $ getDoc subExpr where @@ -142,18 +96,35 @@ precedenceWrap op subExpr = where needsParens :: Bool needsParens = - precedence root < precedence op - || ( precedence root == precedence op - && associativity root == associativity op - && associativity op /= NAssoc + getOpPrecedence root < getOpPrecedence op + || ( getOpPrecedence root == getOpPrecedence op + && getOpAssoc root == getOpAssoc op + && getOpAssoc op /= NAssoc ) root = rootOp subExpr +precedenceWrapAssoc :: NOperatorDef -> NixDoc ann -> Doc ann +precedenceWrapAssoc op subExpr = + maybeWrap $ getDoc subExpr + where + maybeWrap :: Doc ann -> Doc ann + maybeWrap = + bool + parens + id + needsParens + where + needsParens :: Bool + needsParens = + getOpPrecedence root < getOpPrecedence op + + root = rootOp subExpr + -- Used in the selector case to print a path in a selector as -- "${./abc}" -wrapPath :: OperatorInfo -> NixDoc ann -> Doc ann +wrapPath :: NOperatorDef -> NixDoc ann -> Doc ann wrapPath op sub = bool (precedenceWrap op sub) @@ -285,7 +256,7 @@ exprFNixDoc = \case NConstant atom -> prettyAtom atom NStr str -> simpleExpr $ prettyString str NList xs -> - prettyContainer "[" (precedenceWrap appOpNonAssoc) "]" xs + prettyContainer "[" (precedenceWrapAssoc appOpDef) "]" xs NSet NonRecursive xs -> prettyContainer "{" prettyBind "}" xs NSet Recursive xs -> @@ -298,37 +269,37 @@ exprFNixDoc = \case , getDoc body ] NApp fun arg -> - mkNixDoc appOperatorInfo (precedenceWrap appOperatorInfo fun <> " " <> precedenceWrap appOpNonAssoc arg) + mkNixDoc appOpDef (precedenceWrap appOpDef fun <> " " <> precedenceWrapAssoc appOpDef arg) NBinary op r1 r2 -> mkNixDoc - opInfo $ + opDef $ hsep [ f NAssocLeft r1 - , pretty @Text $ coerce @NOpName $ operatorName opInfo + , pretty @Text $ coerce @NOpName $ getOpName op , f NAssocRight r2 ] where - opInfo = getBinaryOperator op + opDef = getOpDef op f :: NAssoc -> NixDoc ann -> Doc ann f x = - precedenceWrap - $ bool - opInfo - (opInfo { associativity = NAssoc }) - (associativity opInfo /= x) + bool + precedenceWrap + precedenceWrapAssoc + (getOpAssoc opDef /= x) + opDef NUnary op r1 -> mkNixDoc - opInfo $ - pretty @Text (coerce $ operatorName opInfo) <> precedenceWrap opInfo r1 + opDef $ + pretty @Text (coerce $ getOpName op) <> precedenceWrap opDef r1 where - opInfo = getUnaryOperator op + opDef = getOpDef op NSelect o r' attr -> maybe (mkNixDoc selectOp) (const leastPrecedence) o - $ wrapPath selectOp (mkNixDoc selectOp (precedenceWrap appOpNonAssoc r')) <> "." <> prettySelector attr <> - ((" or " <>) . precedenceWrap appOpNonAssoc) `whenJust` o + $ wrapPath selectOp (mkNixDoc selectOp (precedenceWrapAssoc appOpDef r')) <> "." <> prettySelector attr <> + ((" or " <>) . precedenceWrapAssoc appOpDef) `whenJust` o NHasAttr r attr -> mkNixDoc hasAttrOp (precedenceWrap hasAttrOp r <> " ? " <> prettySelector attr) NEnvPath p -> simpleExpr $ pretty @String $ "<" <> coerce p <> ">" From 0edf6d7a41c60d19a2a887ede2ba8403319eedf7 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Wed, 26 Jan 2022 22:50:29 +0200 Subject: [PATCH 50/70] Pretty: (precedenceWrap -> wrap), precedence(Only -> )Wrap --- ChangeLog.md | 1 + src/Nix/Parser.hs | 6 ++- src/Nix/Pretty.hs | 95 +++++++++++++++++++++++------------------------ 3 files changed, 52 insertions(+), 50 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index e4a010467..fb8cc9daf 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -11,6 +11,7 @@ * [(link)](https://github.com/haskell-nix/hnix/pull/1046/files) Unify builder `mkNV*` and `NV*` patterns by bidirectional synonyms, a lot of builders `mkNV*` are removed, and merged to `NV*`. e.g. instead of builder `mkNVList`, `NVList` should be used. * [(link)](https://github.com/haskell-nix/hnix/pull/1046/files) Constraint `NVConstraint f = (Comonad f, Applicative f)` was introduced, in order to unify builder `mkNV*` and `NV*` patterns. * [(link)](https://github.com/haskell-nix/hnix/pull/1047/files) `Nix.Pretty`: rm `appOp` + * [(link)](https://github.com/haskell-nix/hnix/pull/1047/files) `Nix.Pretty`: `precedenceWrap` behaviour is changed (to be literal to the name), the old behaviour is now a `wrap` function. ## [(diff)](https://github.com/haskell-nix/hnix/compare/0.15.0...0.16.0#files_bucket) 0.16.0 diff --git a/src/Nix/Parser.hs b/src/Nix/Parser.hs index d9b792634..d15b87e9f 100644 --- a/src/Nix/Parser.hs +++ b/src/Nix/Parser.hs @@ -508,8 +508,10 @@ instance Num NOpPrecedence where negate = coerce (negate @Int) -- 2022-01-26: NOTE: This type belongs into 'Type.Expr' & be used in NExprF. -data NSpecialOp = - NHasAttrOp | NSelectOp | NTerm +data NSpecialOp + = NHasAttrOp + | NSelectOp + | NTerm -- ^ For special handling of internal print cases. deriving (Eq, Ord, Generic, Typeable, Data, Show, NFData) data NAssoc diff --git a/src/Nix/Pretty.hs b/src/Nix/Pretty.hs index 0ea6d00be..e1e4d3d50 100644 --- a/src/Nix/Pretty.hs +++ b/src/Nix/Pretty.hs @@ -81,53 +81,48 @@ selectOp = getOpDef NSelectOp hasAttrOp :: NOperatorDef hasAttrOp = getOpDef NHasAttrOp +data WrapMode + = ProcessAllWrap + | PrecedenceWrap + deriving Eq + +needsParens + :: WrapMode + -> NOperatorDef + -> NOperatorDef + -> Bool +needsParens mode host sub = + getOpPrecedence host > getOpPrecedence sub + || bool + False + ( NAssoc /= getOpAssoc host + && on (==) getOpAssoc host sub + && on (==) getOpPrecedence host sub + ) + (ProcessAllWrap == mode) + +maybeWrapDoc :: WrapMode -> NOperatorDef -> NixDoc ann -> Doc ann +maybeWrapDoc mode host sub = + bool + parens + id + (needsParens mode host (rootOp sub)) + (getDoc sub) + -- | Determine if to return doc wraped into parens, -- according the given operator. -precedenceWrap :: NOperatorDef -> NixDoc ann -> Doc ann -precedenceWrap op subExpr = - maybeWrap $ getDoc subExpr - where - maybeWrap :: Doc ann -> Doc ann - maybeWrap = - bool - parens - id - needsParens - where - needsParens :: Bool - needsParens = - getOpPrecedence root < getOpPrecedence op - || ( getOpPrecedence root == getOpPrecedence op - && getOpAssoc root == getOpAssoc op - && getOpAssoc op /= NAssoc - ) - - root = rootOp subExpr - -precedenceWrapAssoc :: NOperatorDef -> NixDoc ann -> Doc ann -precedenceWrapAssoc op subExpr = - maybeWrap $ getDoc subExpr - where - maybeWrap :: Doc ann -> Doc ann - maybeWrap = - bool - parens - id - needsParens - where - needsParens :: Bool - needsParens = - getOpPrecedence root < getOpPrecedence op - - root = rootOp subExpr +wrap :: NOperatorDef -> NixDoc ann -> Doc ann +wrap = maybeWrapDoc ProcessAllWrap +precedenceWrap :: NOperatorDef -> NixDoc ann -> Doc ann +precedenceWrap = maybeWrapDoc PrecedenceWrap -- Used in the selector case to print a path in a selector as -- "${./abc}" wrapPath :: NOperatorDef -> NixDoc ann -> Doc ann wrapPath op sub = bool - (precedenceWrap op sub) + (wrap op sub) (dquotes $ antiquote sub) (wasPath sub) @@ -256,7 +251,7 @@ exprFNixDoc = \case NConstant atom -> prettyAtom atom NStr str -> simpleExpr $ prettyString str NList xs -> - prettyContainer "[" (precedenceWrapAssoc appOpDef) "]" xs + prettyContainer "[" (precedenceWrap appOpDef) "]" xs NSet NonRecursive xs -> prettyContainer "{" prettyBind "}" xs NSet Recursive xs -> @@ -269,7 +264,7 @@ exprFNixDoc = \case , getDoc body ] NApp fun arg -> - mkNixDoc appOpDef (precedenceWrap appOpDef fun <> " " <> precedenceWrapAssoc appOpDef arg) + mkNixDoc appOpDef (wrap appOpDef fun <> " " <> precedenceWrap appOpDef arg) NBinary op r1 r2 -> mkNixDoc opDef $ @@ -282,15 +277,19 @@ exprFNixDoc = \case opDef = getOpDef op f :: NAssoc -> NixDoc ann -> Doc ann f x = - bool - precedenceWrap - precedenceWrapAssoc - (getOpAssoc opDef /= x) + maybeWrapDoc + mode opDef + where + mode = + bool + ProcessAllWrap + PrecedenceWrap + (getOpAssoc opDef /= x) NUnary op r1 -> mkNixDoc opDef $ - pretty @Text (coerce $ getOpName op) <> precedenceWrap opDef r1 + pretty @Text (coerce $ getOpName op) <> wrap opDef r1 where opDef = getOpDef op NSelect o r' attr -> @@ -298,10 +297,10 @@ exprFNixDoc = \case (mkNixDoc selectOp) (const leastPrecedence) o - $ wrapPath selectOp (mkNixDoc selectOp (precedenceWrapAssoc appOpDef r')) <> "." <> prettySelector attr <> - ((" or " <>) . precedenceWrapAssoc appOpDef) `whenJust` o + $ wrapPath selectOp (mkNixDoc selectOp (wrap appOpDef r')) <> "." <> prettySelector attr <> + ((" or " <>) . precedenceWrap appOpDef) `whenJust` o NHasAttr r attr -> - mkNixDoc hasAttrOp (precedenceWrap hasAttrOp r <> " ? " <> prettySelector attr) + mkNixDoc hasAttrOp (wrap hasAttrOp r <> " ? " <> prettySelector attr) NEnvPath p -> simpleExpr $ pretty @String $ "<" <> coerce p <> ">" NLiteralPath p -> pathExpr $ From 9d98a641bf0b3efb901349926560eab41fe50d1d Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Wed, 26 Jan 2022 23:08:34 +0200 Subject: [PATCH 51/70] upd ChangeLog --- ChangeLog.md | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index fb8cc9daf..85f21d76e 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -10,8 +10,22 @@ * `Nix.Value` * [(link)](https://github.com/haskell-nix/hnix/pull/1046/files) Unify builder `mkNV*` and `NV*` patterns by bidirectional synonyms, a lot of builders `mkNV*` are removed, and merged to `NV*`. e.g. instead of builder `mkNVList`, `NVList` should be used. * [(link)](https://github.com/haskell-nix/hnix/pull/1046/files) Constraint `NVConstraint f = (Comonad f, Applicative f)` was introduced, in order to unify builder `mkNV*` and `NV*` patterns. - * [(link)](https://github.com/haskell-nix/hnix/pull/1047/files) `Nix.Pretty`: rm `appOp` - * [(link)](https://github.com/haskell-nix/hnix/pull/1047/files) `Nix.Pretty`: `precedenceWrap` behaviour is changed (to be literal to the name), the old behaviour is now a `wrap` function. + + * `Nix.Parser`: + * [(link)](https://github.com/haskell-nix/hnix/pull/1047/files) rm `OperatorInfo`, using `NOperatorDef`. Number of functions changed signatures accordingly: + * In `Nix.Pretty`: + * `NixDoc ann` + * `mkNixDoc` + * `selectOp` + * `hasAttrOp` + * `precedenceWrap` + * `wrapPath` + * In `Nix.Parser`: + * rm `get{App,Unary,Binary,Special}Operator`, currely `NOp` class instances are used instead. + + * `Nix.Pretty`: + * [(link)](https://github.com/haskell-nix/hnix/pull/1047/files) rm `appOp`, instead use `appOpDef`. + * [(link)](https://github.com/haskell-nix/hnix/pull/1047/files) `precedenceWrap` behaviour is changed (to be literal to the name), the old behaviour is now a `wrap` function. ## [(diff)](https://github.com/haskell-nix/hnix/compare/0.15.0...0.16.0#files_bucket) 0.16.0 From 75ed3873217d18017359ced194fdfd36b22a5e7d Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Wed, 26 Jan 2022 23:55:38 +0200 Subject: [PATCH 52/70] treewide: (unless -> when) --- src/Nix/Builtins.hs | 2 +- src/Nix/Normal.hs | 30 ++++++++++++++++++------------ tests/EvalTests.hs | 2 +- tests/Main.hs | 37 ++++++++++++++++++++----------------- 4 files changed, 40 insertions(+), 31 deletions(-) diff --git a/src/Nix/Builtins.hs b/src/Nix/Builtins.hs index 65655e000..a2552f12a 100644 --- a/src/Nix/Builtins.hs +++ b/src/Nix/Builtins.hs @@ -357,7 +357,7 @@ absolutePathFromValue = let path = coerce . toString $ ignoreContext ns - unless (isAbsolute path) $ throwError $ ErrorCall $ "string " <> show path <> " doesn't represent an absolute path" + when (not (isAbsolute path)) $ throwError $ ErrorCall $ "string " <> show path <> " doesn't represent an absolute path" pure path NVPath path -> pure path diff --git a/src/Nix/Normal.hs b/src/Nix/Normal.hs index b9ae8f08c..7fdc647d1 100644 --- a/src/Nix/Normal.hs +++ b/src/Nix/Normal.hs @@ -61,12 +61,15 @@ normalizeValue v = run $ iterNValueM run (flip go) (fmap Free . sequenceNValue' (pure $ pure t) b - seen t = do - let tid = thunkId t - lift $ do - res <- gets $ member tid - unless res $ modify $ insert tid - pure res + seen :: t -> ReaderT Int (StateT (Set (ThunkId m)) m) Bool + seen t = + do + let tnkid = thunkId t + lift $ + do + thunkWasVisited <- gets $ member tnkid + when (not thunkWasVisited) $ modify $ insert tnkid + pure thunkWasVisited -- 2021-05-09: NOTE: This seems a bit excessive. If these functorial versions are not used for recursion schemes - just free from it. -- | Normalization HOF (functorial) version of @normalizeValue@. Accepts the special thunk operating/forcing/nirmalizing function & internalizes it. @@ -107,12 +110,15 @@ normalizeValueF f = run . iterNValueM run (flip go) (fmap Free . sequenceNValue' (pure $ pure t) b - seen t = do - let tid = thunkId t - lift $ do - res <- gets $ member tid - unless res $ modify $ insert tid - pure res + seen :: t -> ReaderT Int (StateT (Set (ThunkId m)) m) Bool + seen t = + do + let tnkid = thunkId t + lift $ + do + thunkWasVisited <- gets $ member tnkid + when (not thunkWasVisited) $ modify $ insert tnkid + pure thunkWasVisited -- | Normalize value. -- Detect cycles. diff --git a/tests/EvalTests.hs b/tests/EvalTests.hs index 5caef884a..b5513facd 100644 --- a/tests/EvalTests.hs +++ b/tests/EvalTests.hs @@ -646,7 +646,7 @@ assertNixEvalThrows a = (normalForm =<< nixEvalExprLoc mempty a') ) (\(_ :: NixException) -> pure True) - unless errored $ assertFailure "Did not catch nix exception" + when (not errored) $ assertFailure "Did not catch nix exception" sameFreeVars :: Text -> [VarName] -> Assertion sameFreeVars a xs = diff --git a/tests/Main.hs b/tests/Main.hs index 7f6e52bcf..928ea0e3c 100644 --- a/tests/Main.hs +++ b/tests/Main.hs @@ -35,7 +35,7 @@ import Test.Tasty.HUnit ensureLangTestsPresent :: Assertion ensureLangTestsPresent = do exist <- fileExist "data/nix/tests/local.mk" - unless exist $ + when (not exist) $ errorWithoutStackTrace $ String.unlines [ "Directory data/nix does not have any files." , "Did you forget to run" @@ -56,29 +56,32 @@ ensureNixpkgsCanParse = time <- getCurrentTime runWithBasicEffectsIO (defaultOptions time) $ Nix.nixEvalExprLoc mempty expr - let dir = ignoreContext ns - exists <- fileExist $ toString dir - unless exists $ + let dir = toString $ ignoreContext ns + exists <- fileExist dir + when (not exists) $ errorWithoutStackTrace $ "Directory " <> show dir <> " does not exist" - files <- globDir1 (compile "**/*.nix") $ toString dir - when (null files) $ - errorWithoutStackTrace $ - "Directory " <> show dir <> " does not have any files" - traverse_ - (\ file -> - unless ("azure-cli/default.nix" `isSuffixOf` file || - "os-specific/linux/udisks/2-default.nix" `isSuffixOf` file) $ do - -- Parse and deepseq the resulting expression tree, to ensure the - -- parser is fully executed. - _ <- consider (coerce file) (parseNixFileLoc (coerce file)) $ Exc.evaluate . force - stub + files <- globDir1 (compile "**/*.nix") dir + handlePresence + (errorWithoutStackTrace $ + "Directory " <> show dir <> " does not have any files") + (traverse_ + (\ file -> + let fileIsNotSuffix = not `isSuffixOf` file in + when + (on (&&) fileIsNotSuffix "azure-cli/default.nix" "os-specific/linux/udisks/2-default.nix") + $ do + -- Parse and deepseq the resulting expression tree, to ensure the + -- parser is fully executed. + _ <- consider (coerce file) (parseNixFileLoc (coerce file)) $ Exc.evaluate . force + stub + ) ) files v -> fail $ "Unexpected parse from default.nix: " <> show v where getExpr k m = - let Just (Just r) = lookup k m in + let Just r = join $ lookup k m in r getString k m = let Fix (NStr (DoubleQuoted [Plain str])) = getExpr k m in From e0c13fea17d2653b724264e784cce44b085eff61 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Wed, 26 Jan 2022 23:56:19 +0200 Subject: [PATCH 53/70] hlint: stop use unless --- .hlint.yaml | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/.hlint.yaml b/.hlint.yaml index b26bab946..f71a65da5 100644 --- a/.hlint.yaml +++ b/.hlint.yaml @@ -14,6 +14,8 @@ - "-XTupleSections" - "-XTypeApplications" - "-XViewPatterns" +- ignore: + name: Use unless - ignore: name: Use head - ignore: @@ -180,9 +182,6 @@ lhs: forever note: "'forever' is loosely typed and may hide errors" rhs: infinitely -- warn: - lhs: "whenM (not <$> x)" - rhs: unlessM x - warn: lhs: "unlessM (not <$> x)" rhs: whenM x @@ -950,11 +949,6 @@ name: "Use 'guard' from Relude" note: "'guard' is already exported from Relude" rhs: guard -- warn: - lhs: Control.Monad.unless - name: "Use 'unless' from Relude" - note: "'unless' is already exported from Relude" - rhs: unless - warn: lhs: Control.Monad.when name: "Use 'when' from Relude" @@ -2745,3 +2739,8 @@ lhs: "mapM" note: "Use `traverse`" rhs: traverse + +- hint: + lhs: "unless b" + note: "Use `when not` as it reads intuitively." + rhs: when (not b) From eb86d91c7f8ace21ca0aaac4894a09996e763374 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Thu, 27 Jan 2022 00:06:34 +0200 Subject: [PATCH 54/70] tests: Main: refactor --- tests/Main.hs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/tests/Main.hs b/tests/Main.hs index 928ea0e3c..5ff54fccd 100644 --- a/tests/Main.hs +++ b/tests/Main.hs @@ -66,15 +66,13 @@ ensureNixpkgsCanParse = (errorWithoutStackTrace $ "Directory " <> show dir <> " does not have any files") (traverse_ - (\ file -> - let fileIsNotSuffix = not `isSuffixOf` file in + (\ path -> + let notEndsIn suffix = not $ isSuffixOf suffix path in when - (on (&&) fileIsNotSuffix "azure-cli/default.nix" "os-specific/linux/udisks/2-default.nix") - $ do - -- Parse and deepseq the resulting expression tree, to ensure the - -- parser is fully executed. - _ <- consider (coerce file) (parseNixFileLoc (coerce file)) $ Exc.evaluate . force - stub + (on (&&) notEndsIn "azure-cli/default.nix" "os-specific/linux/udisks/2-default.nix") + $ -- Parse and deepseq the resulting expression tree, to ensure the + -- parser is fully executed. + mempty <$ consider (coerce path) (parseNixFileLoc (coerce path)) $ Exc.evaluate . force ) ) files From f9112ab164497f5ba57145f805911463eb748f5b Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Thu, 27 Jan 2022 00:13:30 +0200 Subject: [PATCH 55/70] Parser: refactor --- src/Nix/Parser.hs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/Nix/Parser.hs b/src/Nix/Parser.hs index d15b87e9f..b2fd022b1 100644 --- a/src/Nix/Parser.hs +++ b/src/Nix/Parser.hs @@ -860,12 +860,11 @@ nixSynHole = annotateLocation $ mkSynHoleF <$> coerce (char '^' *> identifier) -- | Bundles operators with parsers for them, since @megaparsec@ requires the @[[op]]@ form. nixOperators - :: Parser (AnnUnit SrcSpan (NAttrPath NExprLoc)) - -> [[ ( NOperatorDef - , Operator Parser NExprLoc - ) - ]] -nixOperators selector = + :: [[ ( NOperatorDef + , Operator Parser NExprLoc + ) + ]] +nixOperators = [ -- This is not parsed here, even though technically it's part of the -- expression table. The problem is that in some cases, such as list -- membership, it's also a term. And since terms are effectively the @@ -892,7 +891,7 @@ nixOperators selector = , {- 4 -} one ( getOpDef NHasAttrOp - , Postfix $ symbol '?' *> (flip annNHasAttr <$> selector) + , Postfix $ symbol '?' *> (flip annNHasAttr <$> nixSelector) ) , {- 5 -} one $ binary NConcat @@ -959,7 +958,7 @@ nixExprAlgebra = makeExprParser -- This requires to convert precedence to [[op]] nixTerm (snd <<$>> - nixOperators nixSelector + nixOperators ) nixExpr :: Parser NExprLoc From 44f7b5ae567b059f19ac4c6c83c33501f92cb384 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Thu, 27 Jan 2022 00:24:33 +0200 Subject: [PATCH 56/70] Parser: refactor clean-up `nixOperators` table. --- src/Nix/Parser.hs | 37 ++++++++++++------------------------- 1 file changed, 12 insertions(+), 25 deletions(-) diff --git a/src/Nix/Parser.hs b/src/Nix/Parser.hs index b2fd022b1..0e647a50c 100644 --- a/src/Nix/Parser.hs +++ b/src/Nix/Parser.hs @@ -659,9 +659,9 @@ instance NOp NOperatorDef where fun (NSpecialDef _op _assoc _prec name) = name fun _ = error "Impossible happened, operator seems to have no name getter defined." -prefix :: NUnaryOp -> NOpPrecedence -> NOpName -> (NOperatorDef, Operator Parser NExprLoc) -prefix op precedence name = - (NUnaryDef op precedence name, Prefix $ manyUnaryOp $ opWithLoc annNUnary op name) +prefix :: NUnaryOp -> Operator Parser NExprLoc +prefix op = + Prefix $ manyUnaryOp $ opWithLoc annNUnary op $ getOpName op -- postfix name op = (NUnaryDef name op, -- Postfix (opWithLoc annNUnary op name)) @@ -670,11 +670,9 @@ manyUnaryOp f = foldr1 (.) <$> some f binary :: NBinaryOp - -> (NOperatorDef, Operator Parser NExprLoc) + -> Operator Parser NExprLoc binary op = - ( getOpDef op - , mapAssocToInfix (getOpAssoc op) $ opWithLoc annNBinary op (getOpName op) - ) + mapAssocToInfix (getOpAssoc op) $ opWithLoc annNBinary op (getOpName op) mapAssocToInfix :: NAssoc -> m (a -> a -> a) -> Operator m a mapAssocToInfix NAssocLeft = InfixL @@ -860,10 +858,7 @@ nixSynHole = annotateLocation $ mkSynHoleF <$> coerce (char '^' *> identifier) -- | Bundles operators with parsers for them, since @megaparsec@ requires the @[[op]]@ form. nixOperators - :: [[ ( NOperatorDef - , Operator Parser NExprLoc - ) - ]] + :: [[ Operator Parser NExprLoc ]] nixOperators = [ -- This is not parsed here, even though technically it's part of the -- expression table. The problem is that in some cases, such as list @@ -881,18 +876,12 @@ nixOperators = -- ] {- 2 -} - one - ( appOpDef - , -- Thanks to Brent Yorgey for showing me this trick! - InfixL $ annNApp <$ symbols mempty -- NApp is left associative - ) + -- 2018-05-07: jwiegley: Thanks to Brent Yorgey for showing me this trick! + one (InfixL $ annNApp <$ symbols mempty) -- NApp is left associative , {- 3 -} - one $ prefix NNeg 3 "-" + one $ prefix NNeg , {- 4 -} - one - ( getOpDef NHasAttrOp - , Postfix $ symbol '?' *> (flip annNHasAttr <$> nixSelector) - ) + one ( Postfix $ symbol '?' *> (flip annNHasAttr <$> nixSelector) ) , {- 5 -} one $ binary NConcat , {- 6 -} @@ -904,7 +893,7 @@ nixOperators = , binary NMinus ] , {- 8 -} - one $ prefix NNot 8 "!" + one $ prefix NNot , {- 9 -} one $ binary NUpdate , {- 10 -} @@ -957,9 +946,7 @@ nixExprAlgebra :: Parser NExprLoc nixExprAlgebra = makeExprParser -- This requires to convert precedence to [[op]] nixTerm - (snd <<$>> - nixOperators - ) + nixOperators nixExpr :: Parser NExprLoc nixExpr = keywords <|> nixLambda <|> nixExprAlgebra From 8273157d18c63a18dd056aee71a863e275a15cd5 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Thu, 27 Jan 2022 01:28:00 +0200 Subject: [PATCH 57/70] Parser: refactor: construct operator parser list --- hnix.cabal | 1 + src/Nix/Parser.hs | 121 +++++++++++++++++++++------------------------- 2 files changed, 57 insertions(+), 65 deletions(-) diff --git a/hnix.cabal b/hnix.cabal index 0db782bc4..46ca9aafd 100644 --- a/hnix.cabal +++ b/hnix.cabal @@ -404,6 +404,7 @@ library , deriving-compat >= 0.3 && < 0.7 , directory >= 1.3.1 && < 1.4 , exceptions >= 0.10.0 && < 0.11 + , extra >= 1.7 && < 1.8 , filepath >= 1.4.2 && < 1.5 , free >= 5.1 && < 5.2 , gitrev >= 1.1.0 && < 1.4 diff --git a/src/Nix/Parser.hs b/src/Nix/Parser.hs index 0e647a50c..23be3c0c4 100644 --- a/src/Nix/Parser.hs +++ b/src/Nix/Parser.hs @@ -62,6 +62,7 @@ import Data.Char ( isAlpha , isSpace ) import Data.Data ( Data(..) ) +import Data.List.Extra ( groupSort ) import Data.Fix ( Fix(..) ) import qualified Data.HashSet as HashSet import qualified Data.Text as Text @@ -511,7 +512,7 @@ instance Num NOpPrecedence where data NSpecialOp = NHasAttrOp | NSelectOp - | NTerm -- ^ For special handling of internal print cases. + | NTerm -- ^ For special handling of internal special cases. deriving (Eq, Ord, Generic, Typeable, Data, Show, NFData) data NAssoc @@ -820,7 +821,7 @@ nixSelect :: Parser NExprLoc -> Parser NExprLoc nixSelect term = do res <- - liftA2 build + liftA2 builder term (optional $ liftA2 (flip (,)) @@ -835,14 +836,14 @@ nixSelect term = continues (pure res) where - build + builder :: NExprLoc -> Maybe ( Maybe NExprLoc , AnnUnit SrcSpan (NAttrPath NExprLoc) ) -> NExprLoc - build t = + builder t = maybe t (uncurry (`annNSelect` t)) @@ -851,68 +852,52 @@ nixSelect term = -- ** _ - syntax hole nixSynHole :: Parser NExprLoc -nixSynHole = annotateLocation $ mkSynHoleF <$> coerce (char '^' *> identifier) - - --- ** Expr & its constituents (Language term, expr algebra) - --- | Bundles operators with parsers for them, since @megaparsec@ requires the @[[op]]@ form. -nixOperators - :: [[ Operator Parser NExprLoc ]] -nixOperators = - [ -- This is not parsed here, even though technically it's part of the - -- expression table. The problem is that in some cases, such as list - -- membership, it's also a term. And since terms are effectively the - -- highest precedence entities parsed by the expression parser, it ends up - -- working out that we parse them as a kind of "meta-term". - - -- {- 1 -} - -- [ ( NSpecialDef "." NSelectOp NAssocLeft - -- , Postfix $ - -- do - -- sel <- seldot *> selector - -- mor <- optional (reserved "or" *> term) - -- pure $ \x -> annNSelect x sel mor) - -- ] - - {- 2 -} +nixSynHole = + annotateLocation $ mkSynHoleF <$> coerce (char '^' *> identifier) + +opParsers :: [(NOpPrecedence, Operator Parser NExprLoc)] +opParsers = + -- This is not parsed here, even though technically it's part of the + -- expression table. The problem is that in some cases, such as list + -- membership, it's also a term. And since terms are effectively the + -- highest precedence entities parsed by the expression parser, it ends up + -- working out that we parse them as a kind of "meta-term". + + -- {- 1 -} + -- [ ( NSpecialDef "." NSelectOp NAssocLeft + -- , Postfix $ + -- do + -- sel <- seldot *> selector + -- mor <- optional (reserved "or" *> term) + -- pure $ \x -> annNSelect x sel mor) + -- ] + + -- NApp is left associative -- 2018-05-07: jwiegley: Thanks to Brent Yorgey for showing me this trick! - one (InfixL $ annNApp <$ symbols mempty) -- NApp is left associative - , {- 3 -} - one $ prefix NNeg - , {- 4 -} - one ( Postfix $ symbol '?' *> (flip annNHasAttr <$> nixSelector) ) - , {- 5 -} - one $ binary NConcat - , {- 6 -} - [ binary NMult - , binary NDiv - ] - , {- 7 -} - [ binary NPlus - , binary NMinus - ] - , {- 8 -} - one $ prefix NNot - , {- 9 -} - one $ binary NUpdate - , {- 10 -} - [ binary NLt - , binary NGt - , binary NLte - , binary NGte + one (entry appOpDef (const (InfixL $ annNApp <$ symbols mempty))) <> + one (entry NHasAttrOp (const (Postfix $ symbol '?' *> (flip annNHasAttr <$> nixSelector)))) <> + fmap (`entry` prefix) [NNeg, NNot] <> + fmap (`entry` binary) + [ NConcat + , NMult + , NDiv + , NPlus + , NMinus + , NUpdate + , NLt + , NGt + , NLte + , NGte + , NEq + , NNEq + , NAnd + , NOr + , NImpl ] - , {- 11 -} - [ binary NEq - , binary NNEq - ] - , {- 12 -} - one $ binary NAnd - , {- 13 -} - one $ binary NOr - , {- 14 -} - one $ binary NImpl - ] + where + entry op parser = (getOpPrecedence op, parser op) + +-- ** Expr & its constituents (Language term, expr algebra) nixTerm :: Parser NExprLoc nixTerm = @@ -940,11 +925,17 @@ nixTerm = <> [ nixNull | c == 'n' ] <> one (nixSelect nixSym) +-- | Bundles parsers into @[[]]@ based on precedence (form is required for `megaparsec`). +nixOperators :: [[ Operator Parser NExprLoc ]] +nixOperators = + snd <$> + groupSort opParsers + -- | Nix expression algebra parser. -- "Expression algebra" is to explain @megaparsec@ use of the term "Expression" (parser for language algebraic coperators without any statements (without @let@ etc.)), which is essentially an algebra inside the language. nixExprAlgebra :: Parser NExprLoc nixExprAlgebra = - makeExprParser -- This requires to convert precedence to [[op]] + makeExprParser nixTerm nixOperators From cbb368ac5d08e751e6e83971f443afa37ef8b263 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Thu, 27 Jan 2022 01:49:05 +0200 Subject: [PATCH 58/70] Parser: refactor --- src/Nix/Parser.hs | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/src/Nix/Parser.hs b/src/Nix/Parser.hs index 23be3c0c4..917614125 100644 --- a/src/Nix/Parser.hs +++ b/src/Nix/Parser.hs @@ -855,6 +855,7 @@ nixSynHole :: Parser NExprLoc nixSynHole = annotateLocation $ mkSynHoleF <$> coerce (char '^' *> identifier) +-- List of Nix operation parsers with their precedence. opParsers :: [(NOpPrecedence, Operator Parser NExprLoc)] opParsers = -- This is not parsed here, even though technically it's part of the @@ -874,29 +875,21 @@ opParsers = -- NApp is left associative -- 2018-05-07: jwiegley: Thanks to Brent Yorgey for showing me this trick! - one (entry appOpDef (const (InfixL $ annNApp <$ symbols mempty))) <> - one (entry NHasAttrOp (const (Postfix $ symbol '?' *> (flip annNHasAttr <$> nixSelector)))) <> - fmap (`entry` prefix) [NNeg, NNot] <> - fmap (`entry` binary) - [ NConcat - , NMult - , NDiv - , NPlus - , NMinus - , NUpdate - , NLt - , NGt - , NLte - , NGte - , NEq - , NNEq - , NAnd - , NOr - , NImpl - ] + specialBuilder appOpDef (InfixL $ annNApp <$ symbols mempty) <> + specialBuilder NHasAttrOp (Postfix $ symbol '?' *> (flip annNHasAttr <$> nixSelector)) <> + builder prefix <> + builder binary where + specialBuilder :: NOp t => t -> b -> [(NOpPrecedence, b)] + specialBuilder op parser = one (entry op (const parser)) + + builder :: (Enum t, Bounded t, NOp t) => (t -> b) -> [(NOpPrecedence, b)] + builder tp = fmap (`entry` tp) universe + + entry :: NOp t => t -> (t -> b) -> (NOpPrecedence, b) entry op parser = (getOpPrecedence op, parser op) + -- ** Expr & its constituents (Language term, expr algebra) nixTerm :: Parser NExprLoc From d306bdc204ede96897d050ae2284c8678214a0f3 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Thu, 27 Jan 2022 01:56:28 +0200 Subject: [PATCH 59/70] Parser: instance NOp NUnaryOp: rm getOpAssoc --- src/Nix/Parser.hs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Nix/Parser.hs b/src/Nix/Parser.hs index 917614125..5041879a4 100644 --- a/src/Nix/Parser.hs +++ b/src/Nix/Parser.hs @@ -587,11 +587,6 @@ instance NOp NUnaryOp where (error "Impossible happened: unary operation should be includded into the definition map.") op unaryOpDefMap - -- 2022-01-26: NOTE: This instance is a lie, - remove it after `OperatorInfo` is removed from the module. - getOpAssoc = fun . getOpDef - where - fun (NUnaryDef _op _prec _name) = NAssoc - fun _ = error "Impossible happened, unary operation should been matched." getOpPrecedence = fun . getOpDef where fun (NUnaryDef _op prec _name) = prec From cbbf835bf61c8bd0b619578f1b8751e1566bba97 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Thu, 27 Jan 2022 02:52:08 +0200 Subject: [PATCH 60/70] Parser: upd class NOp instances --- src/Nix/Parser.hs | 124 +++++++++++++++++++++++----------------------- src/Nix/Pretty.hs | 9 ++-- 2 files changed, 67 insertions(+), 66 deletions(-) diff --git a/src/Nix/Parser.hs b/src/Nix/Parser.hs index 5041879a4..3c39518b7 100644 --- a/src/Nix/Parser.hs +++ b/src/Nix/Parser.hs @@ -66,7 +66,6 @@ import Data.List.Extra ( groupSort ) import Data.Fix ( Fix(..) ) import qualified Data.HashSet as HashSet import qualified Data.Text as Text -import qualified Data.Map.Strict as M import Nix.Expr.Types import Nix.Expr.Shorthands hiding ( ($>) ) import Nix.Expr.Types.Annotated @@ -508,6 +507,10 @@ instance Num NOpPrecedence where fromInteger = coerce (fromInteger @Int) negate = coerce (negate @Int) +-- 2022-01-26: NOTE: This type belongs into 'Type.Expr' & be used in NExprF. +data NAppOp = NAppOp + deriving (Eq, Ord, Generic, Typeable, Data, Show, NFData) + -- 2022-01-26: NOTE: This type belongs into 'Type.Expr' & be used in NExprF. data NSpecialOp = NHasAttrOp @@ -527,66 +530,51 @@ data NAssoc -- 2022-01-26: NOTE: Maybe split up this type into according set? Would make NOp class total. -- | Single operator grammar entries. data NOperatorDef - = NAppDef NOpPrecedence NOpName + = NAppDef NAppOp NOpPrecedence NOpName | NUnaryDef NUnaryOp NOpPrecedence NOpName | NBinaryDef NBinaryOp NAssoc NOpPrecedence NOpName | NSpecialDef NSpecialOp NAssoc NOpPrecedence NOpName -- 2022-01-26: NOTE: Ord can be the order of evaluation of precedence (which 'Pretty' printing also accounts for). deriving (Eq, Ord, Generic, Typeable, Data, Show, NFData) +-- Supplied since its definition gets called/used frequently. +-- | Functional application operator definition, left associative, high precedence. appOpDef :: NOperatorDef -appOpDef = NAppDef 1 " " -- This defined as "2" in Nix lang spec. - --- 2022-01-26: NOTE: After `OperatorInfo` type is removed from code base --- , think to remove these maps in favour of direct pattern matching in instances. --- That would make those instances total. -unaryOpDefMap :: Map NUnaryOp NOperatorDef -unaryOpDefMap = fromList - [ (NNeg, NUnaryDef NNeg 3 "-") - , (NNot, NUnaryDef NNot 8 "!") - ] - -binaryOpDefMap :: Map NBinaryOp NOperatorDef -binaryOpDefMap = fromList - [ (NConcat, NBinaryDef NConcat NAssocRight 5 "++") - , (NMult , NBinaryDef NMult NAssocLeft 6 "*" ) - , (NDiv , NBinaryDef NDiv NAssocLeft 6 "/" ) - , (NPlus , NBinaryDef NPlus NAssocLeft 7 "+" ) - , (NMinus , NBinaryDef NMinus NAssocLeft 7 "-" ) - , (NUpdate, NBinaryDef NUpdate NAssocRight 9 "//") - , (NLt , NBinaryDef NLt NAssocLeft 10 "<" ) - , (NLte , NBinaryDef NLte NAssocLeft 10 "<=") - , (NGt , NBinaryDef NGt NAssocLeft 10 ">" ) - , (NGte , NBinaryDef NGte NAssocLeft 10 ">=") - , (NEq , NBinaryDef NEq NAssoc 11 "==") - , (NNEq , NBinaryDef NNEq NAssoc 11 "!=") - , (NAnd , NBinaryDef NAnd NAssocLeft 12 "&&") - , (NOr , NBinaryDef NOr NAssocLeft 13 "||") - , (NImpl , NBinaryDef NImpl NAssocRight 14 "->") - ] - -specOpDefMap :: Map NSpecialOp NOperatorDef -specOpDefMap = fromList - [ (NSelectOp , NSpecialDef NSelectOp NAssocLeft 1 ".") - , (NHasAttrOp, NSpecialDef NHasAttrOp NAssocLeft 4 "?") - ] +appOpDef = NAppDef NAppOp 1 " " -- This defined as "2" in Nix lang spec. -- 2022-01-26: NOTE: When total - make sure to hide & inline all these instances to get free solution. -- | Class to get a private free construction to abstract away the gap between the Nix operation types -- 'NUnaryOp', 'NBinaryOp', 'NSpecialOp'. -- And in doing remove 'OperatorInfo' from existance. class NOp a where + {-# minimal getOpDef, getOpPrecedence, getOpName #-} + getOpDef :: a -> NOperatorDef getOpAssoc :: a -> NAssoc + getOpAssoc _ = NAssocLeft getOpPrecedence :: a -> NOpPrecedence getOpName :: a -> NOpName +instance NOp NAppOp where + getOpDef NAppOp = appOpDef + getOpAssoc _op = fun appOpDef + where + fun (NAppDef _op _prec _name) = NAssocLeft + fun _ = error "Impossible happened, funapp operation should been matched." + getOpPrecedence _op = fun appOpDef + where + fun (NAppDef _op prec _name) = prec + fun _ = error "Impossible happened, funapp operation should been matched." + getOpName _ = fun appOpDef + where + fun (NAppDef _op _prec name) = name + fun _ = error "Impossible happened, funapp operation should been matched." + instance NOp NUnaryOp where - getOpDef op = - M.findWithDefault - (error "Impossible happened: unary operation should be includded into the definition map.") - op - unaryOpDefMap + getOpDef = + \case + NNeg -> NUnaryDef NNeg 3 "-" + NNot -> NUnaryDef NNot 8 "!" getOpPrecedence = fun . getOpDef where fun (NUnaryDef _op prec _name) = prec @@ -597,11 +585,23 @@ instance NOp NUnaryOp where fun _ = error "Impossible happened, unary operation should been matched." instance NOp NBinaryOp where - getOpDef op = - M.findWithDefault - (error "Impossible, binary operation should be includded into the definition map.") - op - binaryOpDefMap + getOpDef = + \case + NConcat -> NBinaryDef NConcat NAssocRight 5 "++" + NMult -> NBinaryDef NMult NAssocLeft 6 "*" + NDiv -> NBinaryDef NDiv NAssocLeft 6 "/" + NPlus -> NBinaryDef NPlus NAssocLeft 7 "+" + NMinus -> NBinaryDef NMinus NAssocLeft 7 "-" + NUpdate -> NBinaryDef NUpdate NAssocRight 9 "//" + NLt -> NBinaryDef NLt NAssocLeft 10 "<" + NLte -> NBinaryDef NLte NAssocLeft 10 "<=" + NGt -> NBinaryDef NGt NAssocLeft 10 ">" + NGte -> NBinaryDef NGte NAssocLeft 10 ">=" + NEq -> NBinaryDef NEq NAssoc 11 "==" + NNEq -> NBinaryDef NNEq NAssoc 11 "!=" + NAnd -> NBinaryDef NAnd NAssocLeft 12 "&&" + NOr -> NBinaryDef NOr NAssocLeft 13 "||" + NImpl -> NBinaryDef NImpl NAssocRight 14 "->" getOpAssoc = fun . getOpDef where fun (NBinaryDef _op assoc _prec _name) = assoc @@ -616,11 +616,11 @@ instance NOp NBinaryOp where fun _ = error "Impossible happened, binary operation should been matched." instance NOp NSpecialOp where - getOpDef op = - M.findWithDefault - (error "Impossible, special operation should be includded into the definition map.") - op - specOpDefMap + getOpDef = + \case + NSelectOp -> NSpecialDef NSelectOp NAssocLeft 1 "." + NHasAttrOp -> NSpecialDef NHasAttrOp NAssocLeft 4 "?" + NTerm -> NSpecialDef NTerm NAssocLeft 1 "???" getOpAssoc = fun . getOpDef where fun (NSpecialDef _op assoc _prec _name) = assoc @@ -638,22 +638,22 @@ instance NOp NOperatorDef where getOpDef op = op getOpAssoc op = fun op where - fun (NAppDef _prec _name) = NAssocLeft - fun (NBinaryDef _op assoc _prec _name) = assoc + fun (NAppDef _op _prec _name) = getOpAssoc NAppOp + fun (NUnaryDef op _prec _name) = getOpAssoc op -- is a lie + fun (NBinaryDef _op assoc _prec _name) = assoc fun (NSpecialDef _op assoc _prec _name) = assoc - fun _ = error "Impossible happened, operator seems to have no associativity getter defined." getOpPrecedence = fun . getOpDef where - fun (NAppDef prec _name) = prec - fun (NBinaryDef _op _assoc prec _name) = prec + fun (NAppDef _op prec _name) = prec + fun (NUnaryDef _op prec _name) = prec + fun (NBinaryDef _op _assoc prec _name) = prec fun (NSpecialDef _op _assoc prec _name) = prec - fun _ = error "Impossible happened, operator seems to have no precedence getter defined." getOpName = fun . getOpDef where - fun (NAppDef _prec name) = name - fun (NBinaryDef _op _assoc _prec name) = name + fun (NAppDef _op _prec name) = name + fun (NUnaryDef _op _prec name) = name + fun (NBinaryDef _op _assoc _prec name) = name fun (NSpecialDef _op _assoc _prec name) = name - fun _ = error "Impossible happened, operator seems to have no name getter defined." prefix :: NUnaryOp -> Operator Parser NExprLoc prefix op = @@ -870,7 +870,7 @@ opParsers = -- NApp is left associative -- 2018-05-07: jwiegley: Thanks to Brent Yorgey for showing me this trick! - specialBuilder appOpDef (InfixL $ annNApp <$ symbols mempty) <> + specialBuilder NAppOp (InfixL $ annNApp <$ symbols mempty) <> specialBuilder NHasAttrOp (Postfix $ symbol '?' *> (flip annNHasAttr <$> nixSelector)) <> builder prefix <> builder binary diff --git a/src/Nix/Pretty.hs b/src/Nix/Pretty.hs index e1e4d3d50..ba05c84dd 100644 --- a/src/Nix/Pretty.hs +++ b/src/Nix/Pretty.hs @@ -269,14 +269,15 @@ exprFNixDoc = \case mkNixDoc opDef $ hsep - [ f NAssocLeft r1 + [ pickWrapMode NAssocLeft r1 , pretty @Text $ coerce @NOpName $ getOpName op - , f NAssocRight r2 + , pickWrapMode NAssocRight r2 ] where opDef = getOpDef op - f :: NAssoc -> NixDoc ann -> Doc ann - f x = + + pickWrapMode :: NAssoc -> NixDoc ann -> Doc ann + pickWrapMode x = maybeWrapDoc mode opDef From 63148eb89a11ff774827cf5c2559f902f1a57b71 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Thu, 27 Jan 2022 03:01:52 +0200 Subject: [PATCH 61/70] Pretty: m refactor --- src/Nix/Pretty.hs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/Nix/Pretty.hs b/src/Nix/Pretty.hs index ba05c84dd..59624efe8 100644 --- a/src/Nix/Pretty.hs +++ b/src/Nix/Pretty.hs @@ -278,15 +278,11 @@ exprFNixDoc = \case pickWrapMode :: NAssoc -> NixDoc ann -> Doc ann pickWrapMode x = - maybeWrapDoc - mode + bool + wrap + precedenceWrap + (getOpAssoc opDef /= x) opDef - where - mode = - bool - ProcessAllWrap - PrecedenceWrap - (getOpAssoc opDef /= x) NUnary op r1 -> mkNixDoc opDef $ From 0a984463268f9612c61ac55e9c654f1cbf41a1e1 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Thu, 27 Jan 2022 03:37:07 +0200 Subject: [PATCH 62/70] Parser: upd NOperatorDef --- src/Nix/Parser.hs | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/src/Nix/Parser.hs b/src/Nix/Parser.hs index 3c39518b7..d190d15c7 100644 --- a/src/Nix/Parser.hs +++ b/src/Nix/Parser.hs @@ -530,8 +530,8 @@ data NAssoc -- 2022-01-26: NOTE: Maybe split up this type into according set? Would make NOp class total. -- | Single operator grammar entries. data NOperatorDef - = NAppDef NAppOp NOpPrecedence NOpName - | NUnaryDef NUnaryOp NOpPrecedence NOpName + = NAppDef NAppOp NAssoc NOpPrecedence NOpName + | NUnaryDef NUnaryOp NAssoc NOpPrecedence NOpName | NBinaryDef NBinaryOp NAssoc NOpPrecedence NOpName | NSpecialDef NSpecialOp NAssoc NOpPrecedence NOpName -- 2022-01-26: NOTE: Ord can be the order of evaluation of precedence (which 'Pretty' printing also accounts for). @@ -540,18 +540,17 @@ data NOperatorDef -- Supplied since its definition gets called/used frequently. -- | Functional application operator definition, left associative, high precedence. appOpDef :: NOperatorDef -appOpDef = NAppDef NAppOp 1 " " -- This defined as "2" in Nix lang spec. +appOpDef = NAppDef NAppOp NAssocLeft 1 " " -- This defined as "2" in Nix lang spec. -- 2022-01-26: NOTE: When total - make sure to hide & inline all these instances to get free solution. -- | Class to get a private free construction to abstract away the gap between the Nix operation types -- 'NUnaryOp', 'NBinaryOp', 'NSpecialOp'. -- And in doing remove 'OperatorInfo' from existance. class NOp a where - {-# minimal getOpDef, getOpPrecedence, getOpName #-} + {-# minimal getOpDef, getOpAssoc, getOpPrecedence, getOpName #-} getOpDef :: a -> NOperatorDef getOpAssoc :: a -> NAssoc - getOpAssoc _ = NAssocLeft getOpPrecedence :: a -> NOpPrecedence getOpName :: a -> NOpName @@ -559,29 +558,33 @@ instance NOp NAppOp where getOpDef NAppOp = appOpDef getOpAssoc _op = fun appOpDef where - fun (NAppDef _op _prec _name) = NAssocLeft + fun (NAppDef _op assoc _prec _name) = assoc fun _ = error "Impossible happened, funapp operation should been matched." getOpPrecedence _op = fun appOpDef where - fun (NAppDef _op prec _name) = prec + fun (NAppDef _op _assoc prec _name) = prec fun _ = error "Impossible happened, funapp operation should been matched." getOpName _ = fun appOpDef where - fun (NAppDef _op _prec name) = name + fun (NAppDef _op _assoc _prec name) = name fun _ = error "Impossible happened, funapp operation should been matched." instance NOp NUnaryOp where getOpDef = \case - NNeg -> NUnaryDef NNeg 3 "-" - NNot -> NUnaryDef NNot 8 "!" + NNeg -> NUnaryDef NNeg NAssocRight 3 "-" + NNot -> NUnaryDef NNot NAssocRight 8 "!" + getOpAssoc = fun . getOpDef + where + fun (NUnaryDef _op assoc _prec _name) = assoc + fun _ = error "Impossible happened, unary operation should been matched." getOpPrecedence = fun . getOpDef where - fun (NUnaryDef _op prec _name) = prec + fun (NUnaryDef _op _assoc prec _name) = prec fun _ = error "Impossible happened, unary operation should been matched." getOpName = fun . getOpDef where - fun (NUnaryDef _op _prec name) = name + fun (NUnaryDef _op _assoc _prec name) = name fun _ = error "Impossible happened, unary operation should been matched." instance NOp NBinaryOp where @@ -638,20 +641,20 @@ instance NOp NOperatorDef where getOpDef op = op getOpAssoc op = fun op where - fun (NAppDef _op _prec _name) = getOpAssoc NAppOp - fun (NUnaryDef op _prec _name) = getOpAssoc op -- is a lie + fun (NAppDef _op assoc _prec _name) = assoc + fun (NUnaryDef _op assoc _prec _name) = assoc fun (NBinaryDef _op assoc _prec _name) = assoc fun (NSpecialDef _op assoc _prec _name) = assoc getOpPrecedence = fun . getOpDef where - fun (NAppDef _op prec _name) = prec - fun (NUnaryDef _op prec _name) = prec + fun (NAppDef _op _assoc prec _name) = prec + fun (NUnaryDef _op _assoc prec _name) = prec fun (NBinaryDef _op _assoc prec _name) = prec fun (NSpecialDef _op _assoc prec _name) = prec getOpName = fun . getOpDef where - fun (NAppDef _op _prec name) = name - fun (NUnaryDef _op _prec name) = name + fun (NAppDef _op _assoc _prec name) = name + fun (NUnaryDef _op _assoc _prec name) = name fun (NBinaryDef _op _assoc _prec name) = name fun (NSpecialDef _op _assoc _prec name) = name From 95ba14b22c4d5a32ba74c0fb1d506b63a4ef8751 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Thu, 27 Jan 2022 03:38:03 +0200 Subject: [PATCH 63/70] Pretty: make selectOp & hasAttrOp local --- src/Nix/Pretty.hs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/Nix/Pretty.hs b/src/Nix/Pretty.hs index 59624efe8..6913d9beb 100644 --- a/src/Nix/Pretty.hs +++ b/src/Nix/Pretty.hs @@ -75,12 +75,6 @@ leastPrecedence = mkNixDoc $ NSpecialDef NTerm NAssoc maxBound "least precedence" -selectOp :: NOperatorDef -selectOp = getOpDef NSelectOp - -hasAttrOp :: NOperatorDef -hasAttrOp = getOpDef NHasAttrOp - data WrapMode = ProcessAllWrap | PrecedenceWrap @@ -296,8 +290,16 @@ exprFNixDoc = \case o $ wrapPath selectOp (mkNixDoc selectOp (wrap appOpDef r')) <> "." <> prettySelector attr <> ((" or " <>) . precedenceWrap appOpDef) `whenJust` o + where + selectOp :: NOperatorDef + selectOp = getOpDef NSelectOp + NHasAttr r attr -> mkNixDoc hasAttrOp (wrap hasAttrOp r <> " ? " <> prettySelector attr) + where + hasAttrOp :: NOperatorDef + hasAttrOp = getOpDef NHasAttrOp + NEnvPath p -> simpleExpr $ pretty @String $ "<" <> coerce p <> ">" NLiteralPath p -> pathExpr $ From 194553ce4405c68d2e427389317a2527f5a27e20 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Thu, 27 Jan 2022 03:38:26 +0200 Subject: [PATCH 64/70] Pretty: exprFNixDoc: m refactor --- src/Nix/Pretty.hs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/Nix/Pretty.hs b/src/Nix/Pretty.hs index 6913d9beb..72ca042d2 100644 --- a/src/Nix/Pretty.hs +++ b/src/Nix/Pretty.hs @@ -325,15 +325,14 @@ exprFNixDoc = \case NIf cond trueBody falseBody -> leastPrecedence $ group $ - nest 2 $ - ifThenElse getDoc + nest 2 ifThenElse where - ifThenElse :: (NixDoc ann -> Doc ann) -> Doc ann - ifThenElse wp = + ifThenElse :: Doc ann + ifThenElse = sep - [ "if " <> wp cond - , align ("then " <> wp trueBody) - , align ("else " <> wp falseBody) + [ "if " <> getDoc cond + , align $ "then " <> getDoc trueBody + , align $ "else " <> getDoc falseBody ] NWith scope body -> prettyAddScope "with " scope body From 2bf9da960a85dbbba1eed9771013a5a06fd6d263 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Thu, 27 Jan 2022 03:39:00 +0200 Subject: [PATCH 65/70] Expr.Types: mv NApp a bit earlier --- src/Nix/Expr/Types.hs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Nix/Expr/Types.hs b/src/Nix/Expr/Types.hs index ee2733217..27d9e7c19 100644 --- a/src/Nix/Expr/Types.hs +++ b/src/Nix/Expr/Types.hs @@ -594,15 +594,15 @@ data NExprF r -- environment variable. For example, @@. -- -- > NEnvPath "x" ~ + | NApp !r !r + -- ^ Functional application (aka F.A., apply a function to an argument). + -- + -- > NApp f x ~ f x | NUnary !NUnaryOp !r -- ^ Application of a unary operator to an expression. -- -- > NUnary NNeg x ~ - x -- > NUnary NNot x ~ ! x - | NApp !r !r - -- ^ Functional application (aka F.A., apply a function to an argument). - -- - -- > NApp f x ~ f x | NBinary !NBinaryOp !r !r -- ^ Application of a binary operator to two expressions. -- From 5d9c7b58bd7b2868bbf343117501aba6fce5d821 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Mon, 31 Jan 2022 11:28:25 +0200 Subject: [PATCH 66/70] m org M src/Nix/Exec.hs M src/Nix/Standard.hs M src/Nix/Value.hs --- src/Nix/Exec.hs | 2 +- src/Nix/Standard.hs | 13 +++++-------- src/Nix/Value.hs | 2 +- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/Nix/Exec.hs b/src/Nix/Exec.hs index 71bec3547..93dae2d08 100644 --- a/src/Nix/Exec.hs +++ b/src/Nix/Exec.hs @@ -320,11 +320,11 @@ callFunc fun arg = fun' <- demand fun case fun' of - NVClosure _params f -> f arg NVBuiltin name f -> do span <- askSpan withFrame Info ((Calling @m @(NValue t f m)) name span) $ f arg -- Is this cool? + NVClosure _params f -> f arg (NVSet _ m) | Just f <- M.lookup "__functor" m -> (`callFunc` arg) =<< (`callFunc` fun') f _x -> throwError $ ErrorCall $ "Attempt to call non-function: " <> show _x diff --git a/src/Nix/Standard.hs b/src/Nix/Standard.hs index 5af000b46..846283a45 100644 --- a/src/Nix/Standard.hs +++ b/src/Nix/Standard.hs @@ -47,14 +47,9 @@ newtype StdCited m a = StdCited (Cited (StdThunk m) (StdCited m) m a) deriving - ( Generic - , Typeable - , Functor - , Applicative - , Foldable - , Traversable - , Comonad - , ComonadEnv [Provenance m (StdValue m)] + ( Generic, Typeable + , Functor, Applicative, Comonad, ComonadEnv [Provenance m (StdValue m)] + , Foldable, Traversable ) newtype StdThunk m = @@ -173,6 +168,8 @@ instance -- * @instance MonadThunkF@ (Kleisli functor HOFs) +-- | This is a functorized version in CPS. + -- Please do not use MonadThunkF instances to define MonadThunk. as MonadThunk uses specialized functions. instance ( Typeable m diff --git a/src/Nix/Value.hs b/src/Nix/Value.hs index f38c7bf4c..d46ba2d4d 100644 --- a/src/Nix/Value.hs +++ b/src/Nix/Value.hs @@ -603,8 +603,8 @@ pattern NVStr ns = Free (NVStr' ns) pattern NVPath x = Free (NVPath' x) pattern NVList l = Free (NVList' l) pattern NVSet s x = Free (NVSet' s x) -pattern NVClosure x f = Free (NVClosure' x f) pattern NVBuiltin name f = Free (NVBuiltin' name f) +pattern NVClosure x f = Free (NVClosure' x f) {-# complete NVThunk, NVConstant, NVStr, NVPath, NVList, NVSet, NVClosure, NVBuiltin #-} From 65a1e3fe796d8011749ebcca8336b59f4360ea02 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Mon, 31 Jan 2022 11:31:22 +0200 Subject: [PATCH 67/70] Utils: inline handlePresence Stramgely, profiling shown that in this bool a pretty big part of time was spent. --- src/Nix/Utils.hs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Nix/Utils.hs b/src/Nix/Utils.hs index ff81c917d..fdb2fb612 100644 --- a/src/Nix/Utils.hs +++ b/src/Nix/Utils.hs @@ -209,6 +209,7 @@ whenJust = isPresent :: Foldable t => t a -> Bool isPresent = not . null +{-# inline isPresent #-} -- | 'maybe'-like eliminator, for foldable empty/inhabited structures. @@ -218,6 +219,7 @@ handlePresence d f t = d (f t) (isPresent t) +{-# inline handlePresence #-} whenText :: a -> (Text -> a) -> Text -> a From 966f2f1e03acefea4fb90601fac3fd5bd9d28b81 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Mon, 31 Jan 2022 11:32:57 +0200 Subject: [PATCH 68/70] Utils.Fix1: m clean-up --- src/Nix/Utils/Fix1.hs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/Nix/Utils/Fix1.hs b/src/Nix/Utils/Fix1.hs index eebae4c87..ca4ef6fb4 100644 --- a/src/Nix/Utils/Fix1.hs +++ b/src/Nix/Utils/Fix1.hs @@ -5,7 +5,12 @@ {-# language PolyKinds #-} {-# language UndecidableInstances #-} -module Nix.Utils.Fix1 where +module Nix.Utils.Fix1 + ( Fix1(..) + , Fix1T(..) + , MonadFix1T + ) +where import Nix.Prelude import Control.Monad.Fix ( MonadFix ) @@ -22,6 +27,7 @@ import Control.Monad.Catch ( MonadCatch -- https://gist.github.com/gmalecha/ceb3778b9fdaa4374976e325ac8feced newtype Fix1 (t :: (k -> Type) -> k -> Type) (a :: k) = Fix1 { unFix1 :: t (Fix1 t) a } +deriving instance Generic (Fix1 t a) deriving instance Functor (t (Fix1 t)) => Functor (Fix1 t) deriving instance Applicative (t (Fix1 t)) @@ -49,6 +55,7 @@ deriving instance MonadState s (t (Fix1 t)) newtype Fix1T (t :: (k -> Type) -> (Type -> Type) -> k -> Type) (m :: Type -> Type) (a :: k) = Fix1T { unFix1T :: t (Fix1T t m) m a } +deriving instance Generic (Fix1T t m m) deriving instance Functor (t (Fix1T t m) m) => Functor (Fix1T t m) deriving instance Applicative (t (Fix1T t m) m) @@ -95,7 +102,6 @@ instance writeRef r = lift . writeRef r {-# inline writeRef #-} - instance ( MonadFix1T t m , MonadAtomicRef m @@ -109,8 +115,10 @@ instance newtype Flip (f :: i -> j -> *) (a :: j) (b :: i) = Flip { unFlip :: f b a } --- | Natural Transformations (Included from --- [compdata](https://hackage.haskell.org/package/compdata)) +-- | Natural Transformations +-- ( Included from +-- [compdata](https://hackage.haskell.org/package/compdata) +-- ) type (:->) f g = forall a. f a -> g a class HFunctor f where From 619832b98945eb64613b33759a8bc4ce42847086 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Mon, 31 Jan 2022 11:38:02 +0200 Subject: [PATCH 69/70] Normal: m refactor --- src/Nix/Normal.hs | 80 +++++++++++++++++++++++------------------------ 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/src/Nix/Normal.hs b/src/Nix/Normal.hs index 7fdc647d1..f5b6e3e27 100644 --- a/src/Nix/Normal.hs +++ b/src/Nix/Normal.hs @@ -34,42 +34,42 @@ normalizeValue ) => NValue t f m -> m (NValue t f m) -normalizeValue v = run $ iterNValueM run (flip go) (fmap Free . sequenceNValue' run) v +normalizeValue v = run $ iterNValueM run go (fmap Free . sequenceNValue' run) v where start = 0 :: Int + maxDepth = 2000 table = mempty run :: ReaderT Int (StateT (Set (ThunkId m)) m) r -> m r run = (`evalStateT` table) . (`runReaderT` start) go - :: t - -> ( NValue t f m + :: ( NValue t f m -> ReaderT Int (StateT (Set (ThunkId m)) m) (NValue t f m) ) + -> t -> ReaderT Int (StateT (Set (ThunkId m)) m) (NValue t f m) - go t k = do - b <- seen t + go k tnk = bool (do i <- ask - when (i > 2000) $ fail "Exceeded maximum normalization depth of 2000 levels" + when (i > maxDepth) $ fail $ "Exceeded maximum normalization depth of " <> show maxDepth <> " levels." (lifted . lifted) - (=<< force t) - (local succ . k) + (=<< force tnk) + (local (+1) . k) ) - (pure $ pure t) - b - - seen :: t -> ReaderT Int (StateT (Set (ThunkId m)) m) Bool - seen t = - do - let tnkid = thunkId t - lift $ - do - thunkWasVisited <- gets $ member tnkid - when (not thunkWasVisited) $ modify $ insert tnkid - pure thunkWasVisited + (pure $ pure tnk) + =<< seen tnk + where + seen :: t -> ReaderT Int (StateT (Set (ThunkId m)) m) Bool + seen t = + do + let tnkid = thunkId t + lift $ + do + thunkWasVisited <- gets $ member tnkid + when (not thunkWasVisited) $ modify $ insert tnkid + pure thunkWasVisited -- 2021-05-09: NOTE: This seems a bit excessive. If these functorial versions are not used for recursion schemes - just free from it. -- | Normalization HOF (functorial) version of @normalizeValue@. Accepts the special thunk operating/forcing/nirmalizing function & internalizes it. @@ -83,42 +83,42 @@ normalizeValueF => (forall r . t -> (NValue t f m -> m r) -> m r) -> NValue t f m -> m (NValue t f m) -normalizeValueF f = run . iterNValueM run (flip go) (fmap Free . sequenceNValue' run) +normalizeValueF f = run . iterNValueM run go (fmap Free . sequenceNValue' run) where start = 0 :: Int + maxDepth = 2000 table = mempty run :: ReaderT Int (StateT (Set (ThunkId m)) m) r -> m r run = (`evalStateT` table) . (`runReaderT` start) go - :: t - -> ( NValue t f m + :: ( NValue t f m -> ReaderT Int (StateT (Set (ThunkId m)) m) (NValue t f m) ) + -> t -> ReaderT Int (StateT (Set (ThunkId m)) m) (NValue t f m) - go t k = do - b <- seen t + go k tnk = bool (do i <- ask - when (i > 2000) $ fail "Exceeded maximum normalization depth of 2000 levels" + when (i > maxDepth) $ fail $ "Exceeded maximum normalization depth of " <> show maxDepth <> " levels." (lifted . lifted) - (f t) - (local succ . k) + (f tnk) + (local (+1) . k) ) - (pure $ pure t) - b - - seen :: t -> ReaderT Int (StateT (Set (ThunkId m)) m) Bool - seen t = - do - let tnkid = thunkId t - lift $ - do - thunkWasVisited <- gets $ member tnkid - when (not thunkWasVisited) $ modify $ insert tnkid - pure thunkWasVisited + (pure $ pure tnk) + =<< seen tnk + where + seen :: t -> ReaderT Int (StateT (Set (ThunkId m)) m) Bool + seen t = + do + let tnkid = thunkId t + lift $ + do + thunkWasVisited <- gets $ member tnkid + when (not thunkWasVisited) $ modify $ insert tnkid + pure thunkWasVisited -- | Normalize value. -- Detect cycles. From e9d9a2f0a5a9aff6537c803cf6b25a6071054ae5 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Mon, 31 Jan 2022 11:55:18 +0200 Subject: [PATCH 70/70] Parser: m: add current note --- src/Nix/Parser.hs | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/Nix/Parser.hs b/src/Nix/Parser.hs index d190d15c7..626ead9d8 100644 --- a/src/Nix/Parser.hs +++ b/src/Nix/Parser.hs @@ -527,7 +527,20 @@ data NAssoc | NAssocRight deriving (Eq, Ord, Generic, Typeable, Data, Show, NFData) --- 2022-01-26: NOTE: Maybe split up this type into according set? Would make NOp class total. +-- 2022-01-31: NOTE: This type and related typeclasses & their design, probably need a refinement. +-- +-- In the "Nix.Pretty", the code probably should be well-typed to the type of operations its processes. +-- Therefor splitting operation types into separate types there is probably needed. +-- +-- After that: +-- +-- > { NAssoc, NOpPrecedence, NOpName } +-- +-- Can be formed into a type. +-- +-- Also 'NAppDef' really has only 1 implementation, @{ NAssoc, NOpPrecedence, NOpName }@ +-- were added there only to make type uniformal. +-- All impossible cases ideally should be unrepresentable. -- | Single operator grammar entries. data NOperatorDef = NAppDef NAppOp NAssoc NOpPrecedence NOpName @@ -639,12 +652,11 @@ instance NOp NSpecialOp where instance NOp NOperatorDef where getOpDef op = op - getOpAssoc op = fun op - where - fun (NAppDef _op assoc _prec _name) = assoc - fun (NUnaryDef _op assoc _prec _name) = assoc - fun (NBinaryDef _op assoc _prec _name) = assoc - fun (NSpecialDef _op assoc _prec _name) = assoc + getOpAssoc = \case + (NAppDef _op assoc _prec _name) -> assoc + (NUnaryDef _op assoc _prec _name) -> assoc + (NBinaryDef _op assoc _prec _name) -> assoc + (NSpecialDef _op assoc _prec _name) -> assoc getOpPrecedence = fun . getOpDef where fun (NAppDef _op _assoc prec _name) = prec