Skip to content

Commit

Permalink
fix nim-lang#8242, fix nim-lang#12586: fix 'formatFloat' with 'precis…
Browse files Browse the repository at this point in the history
…ion = 0' (nim-lang#12592)

* fix nim-lang#8242, fix nim-lang#12586: fix 'formatFloat' with 'precision = 0'

'formatFloat' with 'precision = 0' now gives the same result
(a number without a decimal point) in all backends.
This is compatible with Python's formatters, too.

* fix failing tests

* add changelog entry

* add version switch
  • Loading branch information
narimiran authored and kiyolee committed Nov 7, 2019
1 parent ac8e029 commit 6d3a171
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 28 deletions.
39 changes: 30 additions & 9 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,47 @@

### Breaking changes in the standard library

- `base64.encode` no longer supports `lineLen` and `newLine` use `base64.encodeMIME` instead.
- `os.splitPath()` behavior synchronized with `os.splitFile()` to return "/" as the dir component of "/root_sub_dir" instead of the empty string.
- `sequtils.zip` now returns a sequence of anonymous tuples i.e. those tuples now do not have fields named "a" and "b".
- `base64.encode` no longer supports `lineLen` and `newLine`.
Use `base64.encodeMIME` instead.
- `os.splitPath()` behavior synchronized with `os.splitFile()` to return "/"
as the dir component of "/root_sub_dir" instead of the empty string.
- `sequtils.zip` now returns a sequence of anonymous tuples i.e. those tuples
now do not have fields named "a" and "b".
- `strutils.formatFloat` with `precision = 0` has the same behavior in all
backends, and it is compatible with Python's behavior,
e.g. `formatFloat(3.14159, precision = 0)` is now `3`, not `3.`.


### Breaking changes in the compiler

- Implicit conversions for `const` behave correctly now, meaning that code like `const SOMECONST = 0.int; procThatTakesInt32(SOMECONST)` will be illegal now.
- Implicit conversions for `const` behave correctly now, meaning that code like
`const SOMECONST = 0.int; procThatTakesInt32(SOMECONST)` will be illegal now.
Simply write `const SOMECONST = 0` instead.



## Library additions

- `macros.newLit` now works for ref object types.
- `system.writeFile` has been overloaded to also support `openarray[byte]`.
- Added overloaded `strformat.fmt` macro that use specified characters as delimiter instead of '{' and '}'.
- Added overloaded `strformat.fmt` macro that use specified characters as
delimiter instead of '{' and '}'.



## Library changes

- `asyncdispatch.drain` now properly takes into account `selector.hasPendingOperations` and only returns once all pending async operations are guaranteed to have completed.
- `asyncdispatch.drain` now consistently uses the passed timeout value for all iterations of the event loop, and not just the first iteration. This is more consistent with the other asyncdispatch apis, and allows `asyncdispatch.drain` to be more efficient.
- `asyncdispatch.drain` now properly takes into account `selector.hasPendingOperations`
and only returns once all pending async operations are guaranteed to have completed.
- `asyncdispatch.drain` now consistently uses the passed timeout value for all
iterations of the event loop, and not just the first iteration.
This is more consistent with the other asyncdispatch apis, and allows
`asyncdispatch.drain` to be more efficient.
- `base64.encode` and `base64.decode` was made faster by about 50%.
- `htmlgen` adds [MathML](https://wikipedia.org/wiki/MathML) support (ISO 40314).



## Language additions


Expand All @@ -45,9 +63,12 @@

### Compiler changes

- JS target indent is all spaces, instead of mixed spaces and tabs, for generated JavaScript.
- JS target indent is all spaces, instead of mixed spaces and tabs, for
generated JavaScript.



## Bugfixes

- The `FD` variant of `selector.unregister` for `ioselector_epoll` and `ioselector_select` now properly handle the `Event.User` select event type.
- The `FD` variant of `selector.unregister` for `ioselector_epoll` and
`ioselector_select` now properly handle the `Event.User` select event type.
5 changes: 2 additions & 3 deletions lib/pure/strformat.nim
Original file line number Diff line number Diff line change
Expand Up @@ -692,12 +692,11 @@ when isMainModule:
check &"{-123.456:.3f}", "-123.456"
check &"{123.456:1g}", "123.456"
check &"{123.456:.1f}", "123.5"
check &"{123.456:.0f}", "123."
#check &"{123.456:.0f}", "123."
check &"{123.456:.0f}", "123"
check &"{123.456:>9.3f}", " 123.456"
check &"{123.456:9.3f}", " 123.456"
check &"{123.456:>9.4f}", " 123.4560"
check &"{123.456:>9.0f}", " 123."
check &"{123.456:>9.0f}", " 123"
check &"{123.456:<9.4f}", "123.4560 "

# Float (scientific) tests
Expand Down
20 changes: 6 additions & 14 deletions lib/pure/strutils.nim
Original file line number Diff line number Diff line change
Expand Up @@ -2338,7 +2338,7 @@ proc formatBiggestFloat*(f: BiggestFloat, format: FloatFormatMode = ffDefault,
for i in 0 ..< result.len:
# Depending on the locale either dot or comma is produced,
# but nothing else is possible:
if result[i] in {'.', ','}: result[i] = decimalsep
if result[i] in {'.', ','}: result[i] = decimalSep
else:
const floatFormatToChar: array[FloatFormatMode, char] = ['g', 'f', 'e']
var
Expand Down Expand Up @@ -2369,6 +2369,10 @@ proc formatBiggestFloat*(f: BiggestFloat, format: FloatFormatMode = ffDefault,
# but nothing else is possible:
if buf[i] in {'.', ','}: result[i] = decimalSep
else: result[i] = buf[i]
when (NimMajor, NimMinor) >= (1, 1):
# remove trailing dot, compatible with Python's formatter and JS backend
if result[^1] == decimalSep:
result.setLen(len(result)-1)
when defined(windows):
# VS pre 2015 violates the C standard: "The exponent always contains at
# least two digits, and only as many more digits as necessary to
Expand Down Expand Up @@ -3135,8 +3139,7 @@ proc wordWrap*(s: string, maxLineWidth = 80,
when isMainModule:
proc nonStaticTests =
doAssert formatBiggestFloat(1234.567, ffDecimal, -1) == "1234.567000"
when not defined(js):
doAssert formatBiggestFloat(1234.567, ffDecimal, 0) == "1235." # <=== bug 8242
doAssert formatBiggestFloat(1234.567, ffDecimal, 0) == "1235" # bugs 8242, 12586
doAssert formatBiggestFloat(1234.567, ffDecimal, 1) == "1234.6"
doAssert formatBiggestFloat(0.00000000001, ffDecimal, 11) == "0.00000000001"
doAssert formatBiggestFloat(0.00000000001, ffScientific, 1, ',') in
Expand Down Expand Up @@ -3201,17 +3204,6 @@ when isMainModule:
doAssert alignLeft("1232", 6) == "1232 "
doAssert alignLeft("1232", 6, '#') == "1232##"

let
inp = """ this is a long text -- muchlongerthan10chars and here
it goes"""
outp = " this is a\nlong text\n--\nmuchlongerthan10chars\nand here\nit goes"
doAssert wordWrap(inp, 10, false) == outp

let
longInp = """ThisIsOneVeryLongStringWhichWeWillSplitIntoEightSeparatePartsNow"""
longOutp = "ThisIsOn\neVeryLon\ngStringW\nhichWeWi\nllSplitI\nntoEight\nSeparate\nPartsNow"
doAssert wordWrap(longInp, 8, true) == longOutp

doAssert "$animal eats $food." % ["animal", "The cat", "food", "fish"] ==
"The cat eats fish."

Expand Down
3 changes: 1 addition & 2 deletions tests/destructor/tnewruntime_strutils.nim
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ proc retTuple(): (seq[int], int) =

proc nonStaticTests =
doAssert formatBiggestFloat(1234.567, ffDecimal, -1) == "1234.567000"
when not defined(js):
doAssert formatBiggestFloat(1234.567, ffDecimal, 0) == "1235." # <=== bug 8242
doAssert formatBiggestFloat(1234.567, ffDecimal, 0) == "1235" # bugs 8242, 12586
doAssert formatBiggestFloat(1234.567, ffDecimal, 1) == "1234.6"
doAssert formatBiggestFloat(0.00000000001, ffDecimal, 11) == "0.00000000001"
doAssert formatBiggestFloat(0.00000000001, ffScientific, 1, ',') in
Expand Down

0 comments on commit 6d3a171

Please sign in to comment.