Skip to content

Commit

Permalink
Merge pull request #246 from NixOS/fix-floats
Browse files Browse the repository at this point in the history
Don't rewrite floats and don't break e+ syntax
  • Loading branch information
infinisil authored Sep 3, 2024
2 parents 2efce29 + 1e3a25c commit 8a73acf
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 57 deletions.
74 changes: 21 additions & 53 deletions src/Nixfmt/Parser/Float.hs
Original file line number Diff line number Diff line change
@@ -1,66 +1,34 @@
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}

module Nixfmt.Parser.Float (floatParse) where

import "base" Control.Monad (void)
import qualified "base" Data.Char as Char
import "base" Data.Foldable (foldl')
import "base" Data.Proxy (Proxy (..))
import "megaparsec" Text.Megaparsec (
import Data.List (singleton)
import Data.Text (Text, pack)
import Text.Megaparsec (
MonadParsec,
Token,
chunkToTokens,
notFollowedBy,
many,
oneOf,
option,
takeWhile1P,
satisfy,
some,
try,
(<?>),
(<|>),
)
import "megaparsec" Text.Megaparsec.Char (char, char', digitChar)
import "megaparsec" Text.Megaparsec.Char.Lexer (decimal, signed)
import "scientific" Data.Scientific (scientific, toRealFloat)
import Text.Megaparsec.Char (char, digitChar)

-- copied (and modified) from Text.Megaparsec.Char.Lexer
data SP = SP !Integer {-# UNPACK #-} !Int

floatParse :: (MonadParsec e s m, Token s ~ Char, RealFloat a) => m a
floatParse = do
notFollowedBy $ char '0' >> digitChar
notFollowedBy (char' 'e')
c' <- (decimal <?> "decimal") <|> return 0
toRealFloat
<$> ( ( do
SP c e' <- dotDecimal_ c'
e <- option e' (try $ exponent_ e')
return (scientific c e)
floatParse :: (MonadParsec e s m, Token s ~ Char, Semigroup (m [Char])) => m Text
floatParse =
-- This mirrors https://github.com/NixOS/nix/blob/b89eca9aecc69d4dfc0f0afd9353c126eb7b5858/src/libexpr/lexer.l#L96:
-- (([1-9][0-9]*\.[0-9]*)|(0?\.[0-9]+))([Ee][+-]?[0-9]+)?
pack
<$> ( ( try oneThroughNineStart
<|> zeroDotStart
)
<|> (scientific c' <$> exponent_ 0)
<> scientific
)
{-# INLINE floatParse #-}

-- copied from Text.Megaparsec.Char.Lexer
dotDecimal_ ::
forall e s m.
(MonadParsec e s m, Token s ~ Char) =>
Integer ->
m SP
dotDecimal_ c' = do
void (char '.')
let mkNum = foldl' step (SP c' 0) . chunkToTokens @s Proxy
step (SP a e') c =
SP
(a * 10 + fromIntegral (Char.digitToInt c))
(e' - 1)
mkNum <$> takeWhile1P (Just "digit") Char.isDigit
{-# INLINE dotDecimal_ #-}

-- copied from Text.Megaparsec.Char.Lexer
exponent_ :: (MonadParsec e s m, Token s ~ Char) => Int -> m Int
exponent_ e' = do
void (char' 'e')
(+ e') <$> signed (return ()) decimal
{-# INLINE exponent_ #-}
where
oneThroughNineStart = oneThroughNine <> many digitChar <> (singleton <$> char '.') <> many digitChar
zeroDotStart = option "" (singleton <$> char '0') <> (singleton <$> char '.') <> some digitChar
scientific = option "" ((singleton <$> oneOf "Ee") <> option "" (singleton <$> oneOf "+-") <> some digitChar)
oneThroughNine = singleton <$> satisfy (\c -> '1' <= c && c <= '9')
4 changes: 2 additions & 2 deletions src/Nixfmt/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,7 @@ instance (LanguageElement a) => LanguageElement (NonEmpty a) where

data Token
= Integer Int
| Float Double
| Float Text
| Identifier Text
| EnvPath Text
| KAssert
Expand Down Expand Up @@ -588,7 +588,7 @@ operators =
tokenText :: Token -> Text
tokenText (Identifier i) = i
tokenText (Integer i) = pack (show i)
tokenText (Float f) = pack (show f)
tokenText (Float f) = f
tokenText (EnvPath p) = "<" <> p <> ">"
tokenText KAssert = "assert"
tokenText KElse = "else"
Expand Down
23 changes: 23 additions & 0 deletions test/correct/numbers.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[
(-9223372036854775807)
(-1)
0
1
# 01
# 0000000000000000000000000000000000000000000001
9223372036854775807

.1
0.1
1.0
.1e0
1.0e0
1.e0
.1e-0
1.0e-0
1.e-0
.1e+0
1.0e+0
1.e+0

]
2 changes: 1 addition & 1 deletion test/diff/operator-after-operator/out-pure.nix
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# https://github.com/NixOS/nixfmt/issues/122
(1 + 1) (1 + 0.4)
(1 + 1) (1 + .4)
2 changes: 1 addition & 1 deletion test/diff/operator-after-operator/out.nix
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# https://github.com/NixOS/nixfmt/issues/122
(1 + 1) (1 + 0.4)
(1 + 1) (1 + .4)

0 comments on commit 8a73acf

Please sign in to comment.