summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--changelog.md3
-rw-r--r--compiler/ic/ic.nim2
-rw-r--r--compiler/lexer.nim2
-rw-r--r--compiler/renderer.nim2
-rw-r--r--compiler/rodutils.nim2
-rw-r--r--compiler/ropes.nim2
-rw-r--r--compiler/sem.nim3
-rw-r--r--compiler/semfold.nim2
-rw-r--r--compiler/types.nim2
-rw-r--r--compiler/vm.nim3
-rw-r--r--compiler/vmmarshal.nim2
-rw-r--r--compiler/vmops.nim4
-rw-r--r--lib/core/macros.nim2
-rw-r--r--lib/packages/docutils/rstgen.nim2
-rw-r--r--lib/pure/json.nim2
-rw-r--r--lib/std/formatfloat.nim142
-rw-r--r--lib/std/private/dragonbox.nim (renamed from lib/system/dragonbox.nim)27
-rw-r--r--lib/std/private/schubfach.nim (renamed from lib/system/schubfach.nim)12
-rw-r--r--lib/std/syncio.nim2
-rw-r--r--lib/system/chcks.nim2
-rw-r--r--lib/system/dollars.nim13
-rw-r--r--lib/system/formatfloat.nim141
-rw-r--r--lib/system/repr_v2.nim3
23 files changed, 201 insertions, 176 deletions
diff --git a/changelog.md b/changelog.md
index 80692e996..36f27ecf3 100644
--- a/changelog.md
+++ b/changelog.md
@@ -6,8 +6,7 @@
 - `addr` is now available for all addressable locations,
   `unsafeAddr` is now deprecated and an alias for `addr`.
 
-- `io` and `assertions` are about to move out of the `system` module.
-  You may instead import `std/syncio` and `std/assertions`.
+- `io`, `assertions`, `formatfloat` are about to move out of the `system` module. You may instead import `std/syncio`, `std/assertions` and `std/formatfloat`.
   The `-d:nimPreviewSlimSystem` option makes these imports required.
 
 - The `gc:v2` option is removed.
diff --git a/compiler/ic/ic.nim b/compiler/ic/ic.nim
index 38b6987f9..2ac441b3e 100644
--- a/compiler/ic/ic.nim
+++ b/compiler/ic/ic.nim
@@ -15,7 +15,7 @@ import ".." / [ast, idents, lineinfos, msgs, ropes, options,
 from os import removeFile, isAbsolute
 
 when defined(nimPreviewSlimSystem):
-  import std/[syncio, assertions]
+  import std/[syncio, assertions, formatfloat]
 
 type
   PackedConfig* = object
diff --git a/compiler/lexer.nim b/compiler/lexer.nim
index e795d52c0..f2c94e06a 100644
--- a/compiler/lexer.nim
+++ b/compiler/lexer.nim
@@ -20,7 +20,7 @@ import
   wordrecg, lineinfos, pathutils, parseutils
 
 when defined(nimPreviewSlimSystem):
-  import std/assertions
+  import std/[assertions, formatfloat]
 
 const
   MaxLineLength* = 80         # lines longer than this lead to a warning
diff --git a/compiler/renderer.nim b/compiler/renderer.nim
index f847aa094..d8c46fc92 100644
--- a/compiler/renderer.nim
+++ b/compiler/renderer.nim
@@ -18,7 +18,7 @@ import
   lexer, options, idents, strutils, ast, msgs, lineinfos
 
 when defined(nimPreviewSlimSystem):
-  import std/[syncio, assertions]
+  import std/[syncio, assertions, formatfloat]
 
 type
   TRenderFlag* = enum
diff --git a/compiler/rodutils.nim b/compiler/rodutils.nim
index 95b7b2d9e..e2e9e1eb2 100644
--- a/compiler/rodutils.nim
+++ b/compiler/rodutils.nim
@@ -42,7 +42,7 @@ when not declared(signbit):
   proc signbit*(x: SomeFloat): bool {.inline.} =
     result = c_signbit(x) != 0
 
-import system/formatfloat
+import std/formatfloat
 
 proc toStrMaxPrecision*(f: BiggestFloat | float32): string =
   const literalPostfix = when f is float32: "f" else: ""
diff --git a/compiler/ropes.nim b/compiler/ropes.nim
index 677a3ce09..3a2fbe44e 100644
--- a/compiler/ropes.nim
+++ b/compiler/ropes.nim
@@ -61,7 +61,7 @@ import
 from pathutils import AbsoluteFile
 
 when defined(nimPreviewSlimSystem):
-  import std/[assertions, syncio]
+  import std/[assertions, syncio, formatfloat]
 
 
 type
diff --git a/compiler/sem.nim b/compiler/sem.nim
index 8fac158ba..b6ee76cc9 100644
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -25,6 +25,9 @@ when defined(nimfix):
 when not defined(leanCompiler):
   import spawn
 
+when defined(nimPreviewSlimSystem):
+  import std/formatfloat
+
 # implementation
 
 proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType = nil): PNode
diff --git a/compiler/semfold.nim b/compiler/semfold.nim
index 72c8abaa9..f627bffc7 100644
--- a/compiler/semfold.nim
+++ b/compiler/semfold.nim
@@ -18,7 +18,7 @@ import
 from system/memory import nimCStrLen
 
 when defined(nimPreviewSlimSystem):
-  import std/assertions
+  import std/[assertions, formatfloat]
 
 proc errorType*(g: ModuleGraph): PType =
   ## creates a type representing an error state
diff --git a/compiler/types.nim b/compiler/types.nim
index 685577641..cd7d11b94 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -14,7 +14,7 @@ import
   lineinfos, int128, modulegraphs, astmsgs
 
 when defined(nimPreviewSlimSystem):
-  import std/assertions
+  import std/[assertions, formatfloat]
 
 type
   TPreferedDesc* = enum
diff --git a/compiler/vm.nim b/compiler/vm.nim
index 28df27ef3..1717fe119 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -18,6 +18,9 @@ import
   gorgeimpl, lineinfos, btrees, macrocacheimpl,
   modulegraphs, sighashes, int128, vmprofiler
 
+when defined(nimPreviewSlimSystem):
+  import std/formatfloat
+
 import ast except getstr
 from semfold import leValueConv, ordinalValToString
 from evaltempl import evalTemplate
diff --git a/compiler/vmmarshal.nim b/compiler/vmmarshal.nim
index 83c441283..e44bc0bea 100644
--- a/compiler/vmmarshal.nim
+++ b/compiler/vmmarshal.nim
@@ -13,7 +13,7 @@ import streams, json, intsets, tables, ast, astalgo, idents, types, msgs,
   options, lineinfos
 
 when defined(nimPreviewSlimSystem):
-  import std/assertions
+  import std/[assertions, formatfloat]
 
 proc ptrToInt(x: PNode): int {.inline.} =
   result = cast[int](x) # don't skip alignment
diff --git a/compiler/vmops.nim b/compiler/vmops.nim
index 01aa5a4b9..fef76940e 100644
--- a/compiler/vmops.nim
+++ b/compiler/vmops.nim
@@ -28,12 +28,12 @@ from std/os import getEnv, existsEnv, delEnv, putEnv, envPairs,
 from std/times import cpuTime
 from std/hashes import hash
 from std/osproc import nil
-from system/formatfloat import addFloatRoundtrip, addFloatSprintf
 
 
 when defined(nimPreviewSlimSystem):
   import std/syncio
-
+else:
+  from std/formatfloat import addFloatRoundtrip, addFloatSprintf 
 
 # There are some useful procs in vmconv.
 import vmconv, vmmarshal
diff --git a/lib/core/macros.nim b/lib/core/macros.nim
index ad87a0f64..ecf85935f 100644
--- a/lib/core/macros.nim
+++ b/lib/core/macros.nim
@@ -11,7 +11,7 @@ include "system/inclrtl"
 import std/private/since
 
 when defined(nimPreviewSlimSystem):
-  import std/assertions
+  import std/[assertions, formatfloat]
 
 
 ## This module contains the interface to the compiler's abstract syntax
diff --git a/lib/packages/docutils/rstgen.nim b/lib/packages/docutils/rstgen.nim
index 6232cb0be..791935da8 100644
--- a/lib/packages/docutils/rstgen.nim
+++ b/lib/packages/docutils/rstgen.nim
@@ -44,7 +44,7 @@ import strutils, os, hashes, strtabs, rstast, rst, highlite, tables, sequtils,
 
 
 when defined(nimPreviewSlimSystem):
-  import std/[assertions, syncio]
+  import std/[assertions, syncio, formatfloat]
 
 
 import ../../std/private/since
diff --git a/lib/pure/json.nim b/lib/pure/json.nim
index 928bc0fbf..d0b1a4051 100644
--- a/lib/pure/json.nim
+++ b/lib/pure/json.nim
@@ -165,7 +165,7 @@ import options # xxx remove this dependency using same approach as https://githu
 import std/private/since
 
 when defined(nimPreviewSlimSystem):
-  import std/[syncio, assertions]
+  import std/[syncio, assertions, formatfloat]
 
 export
   tables.`$`
diff --git a/lib/std/formatfloat.nim b/lib/std/formatfloat.nim
new file mode 100644
index 000000000..6f2383760
--- /dev/null
+++ b/lib/std/formatfloat.nim
@@ -0,0 +1,142 @@
+#
+#
+#            Nim's Runtime Library
+#        (c) Copyright 2022 Nim contributors
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+when defined(nimPreviewSlimSystem):
+  import std/assertions
+else:
+  {.deprecated: "formatfloat is about to move out of system; use `-d:nimPreviewSlimSystem` and import `std/formatfloat`".}
+
+proc c_memcpy(a, b: pointer, size: csize_t): pointer {.importc: "memcpy", header: "<string.h>", discardable.}
+
+proc addCstringN(result: var string, buf: cstring; buflen: int) =
+  # no nimvm support needed, so it doesn't need to be fast here either
+  let oldLen = result.len
+  let newLen = oldLen + buflen
+  result.setLen newLen
+  c_memcpy(result[oldLen].addr, buf, buflen.csize_t)
+
+import std/private/[dragonbox, schubfach]
+
+proc writeFloatToBufferRoundtrip*(buf: var array[65, char]; value: BiggestFloat): int =
+  ## This is the implementation to format floats.
+  ##
+  ## returns the amount of bytes written to `buf` not counting the
+  ## terminating '\0' character.
+  result = toChars(buf, value, forceTrailingDotZero=true)
+  buf[result] = '\0'
+
+proc writeFloatToBufferRoundtrip*(buf: var array[65, char]; value: float32): int =
+  result = float32ToChars(buf, value, forceTrailingDotZero=true)
+  buf[result] = '\0'
+
+proc c_sprintf(buf, frmt: cstring): cint {.header: "<stdio.h>",
+                                    importc: "sprintf", varargs, noSideEffect.}
+
+proc writeToBuffer(buf: var array[65, char]; value: cstring) =
+  var i = 0
+  while value[i] != '\0':
+    buf[i] = value[i]
+    inc i
+
+proc writeFloatToBufferSprintf*(buf: var array[65, char]; value: BiggestFloat): int =
+  ## This is the implementation to format floats.
+  ##
+  ## returns the amount of bytes written to `buf` not counting the
+  ## terminating '\0' character.
+  var n: int = c_sprintf(addr buf, "%.16g", value)
+  var hasDot = false
+  for i in 0..n-1:
+    if buf[i] == ',':
+      buf[i] = '.'
+      hasDot = true
+    elif buf[i] in {'a'..'z', 'A'..'Z', '.'}:
+      hasDot = true
+  if not hasDot:
+    buf[n] = '.'
+    buf[n+1] = '0'
+    buf[n+2] = '\0'
+    result = n + 2
+  else:
+    result = n
+  # On Windows nice numbers like '1.#INF', '-1.#INF' or '1.#NAN' or 'nan(ind)'
+  # of '-1.#IND' are produced.
+  # We want to get rid of these here:
+  if buf[n-1] in {'n', 'N', 'D', 'd', ')'}:
+    writeToBuffer(buf, "nan")
+    result = 3
+  elif buf[n-1] == 'F':
+    if buf[0] == '-':
+      writeToBuffer(buf, "-inf")
+      result = 4
+    else:
+      writeToBuffer(buf, "inf")
+      result = 3
+
+proc writeFloatToBuffer*(buf: var array[65, char]; value: BiggestFloat | float32): int {.inline.} =
+  when defined(nimPreviewFloatRoundtrip) or defined(nimPreviewSlimSystem):
+    writeFloatToBufferRoundtrip(buf, value)
+  else:
+    writeFloatToBufferSprintf(buf, value)
+
+proc addFloatRoundtrip*(result: var string; x: float | float32) =
+  when nimvm:
+    doAssert false
+  else:
+    var buffer {.noinit.}: array[65, char]
+    let n = writeFloatToBufferRoundtrip(buffer, x)
+    result.addCstringN(cstring(buffer[0].addr), n)
+
+proc addFloatSprintf*(result: var string; x: float) =
+  when nimvm:
+    doAssert false
+  else:
+    var buffer {.noinit.}: array[65, char]
+    let n = writeFloatToBufferSprintf(buffer, x)
+    result.addCstringN(cstring(buffer[0].addr), n)
+
+proc nimFloatToString(a: float): cstring =
+  ## ensures the result doesn't print like an integer, i.e. return 2.0, not 2
+  # print `-0.0` properly
+  asm """
+    function nimOnlyDigitsOrMinus(n) {
+      return n.toString().match(/^-?\d+$/);
+    }
+    if (Number.isSafeInteger(`a`))
+      `result` = `a` === 0 && 1 / `a` < 0 ? "-0.0" : `a`+".0"
+    else {
+      `result` = `a`+""
+      if(nimOnlyDigitsOrMinus(`result`)){
+        `result` = `a`+".0"
+      }
+    }
+  """
+
+proc addFloat*(result: var string; x: float | float32) {.inline.} =
+  ## Converts float to its string representation and appends it to `result`.
+  runnableExamples:
+    var
+      s = "foo:"
+      b = 45.67
+    s.addFloat(45.67)
+    assert s == "foo:45.67"
+  template impl =
+    when defined(nimPreviewFloatRoundtrip) or defined(nimPreviewSlimSystem):
+      addFloatRoundtrip(result, x)
+    else:
+      addFloatSprintf(result, x)
+  when defined(js):
+    when nimvm: impl()
+    else:
+      result.add nimFloatToString(x)
+  else: impl()
+
+when defined(nimPreviewSlimSystem):
+  func `$`*(x: float | float32): string =
+    ## Outplace version of `addFloat`.
+    result.addFloat(x)
diff --git a/lib/system/dragonbox.nim b/lib/std/private/dragonbox.nim
index 34ae9e210..23adff385 100644
--- a/lib/system/dragonbox.nim
+++ b/lib/std/private/dragonbox.nim
@@ -30,7 +30,6 @@ when defined(nimPreviewSlimSystem):
 const
   dtoaMinBufferLength*: cint = 64
 
-## --------------------------------------------------------------------------------------------------
 ##  This file contains an implementation of Junekey Jeon's Dragonbox algorithm.
 ##
 ##  It is a simplified version of the reference implementation found here:
@@ -38,14 +37,13 @@ const
 ##
 ##  The reference implementation also works with single-precision floating-point numbers and
 ##  has options to configure the rounding mode.
-## --------------------------------------------------------------------------------------------------
 
 template dragonbox_Assert*(x: untyped): untyped =
   assert(x)
 
-## ==================================================================================================
-##
-## ==================================================================================================
+# ==================================================================================================
+#
+# ==================================================================================================
 
 type
   ValueType* = float
@@ -106,10 +104,11 @@ proc isZero*(this: Double): bool {.noSideEffect.} =
 proc signBit*(this: Double): int {.noSideEffect.} =
   return ord((this.bits and signMask) != 0)
 
+
+# ==================================================================================================
+#
+# ==================================================================================================
 ##  namespace
-## ==================================================================================================
-##
-## ==================================================================================================
 ##  Returns floor(x / 2^n).
 ##
 ##  Technically, right-shift of negative integers is implementation defined...
@@ -133,9 +132,9 @@ proc floorLog10ThreeQuartersPow2*(e: int32): int32 {.inline.} =
   dragonbox_Assert(e <= 1500)
   return floorDivPow2(e * 1262611 - 524031, 22)
 
-## ==================================================================================================
-##
-## ==================================================================================================
+# ==================================================================================================
+#
+# ==================================================================================================
 
 type
   uint64x2* {.bycopy.} = object
@@ -1040,9 +1039,9 @@ proc toDecimal64*(ieeeSignificand: uint64; ieeeExponent: uint64): FloatingDecima
       dec(q)
   return FloatingDecimal64(significand: q, exponent: minusK + kappa)
 
-## ==================================================================================================
-##  ToChars
-## ==================================================================================================
+# ==================================================================================================
+#  ToChars
+# ==================================================================================================
 
 when false:
   template `+!`(x: cstring; offset: int): cstring = cast[cstring](cast[uint](x) + uint(offset))
diff --git a/lib/system/schubfach.nim b/lib/std/private/schubfach.nim
index 7d6861e35..5b965aaa7 100644
--- a/lib/system/schubfach.nim
+++ b/lib/std/private/schubfach.nim
@@ -3,12 +3,12 @@
 ##  Distributed under the Boost Software License, Version 1.0.
 ##   (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
 
-## --------------------------------------------------------------------------------------------------
+# --------------------------------------------------------------------------------------------------
 ##  This file contains an implementation of the Schubfach algorithm as described in
 ##
 ##  [1] Raffaello Giulietti, "The Schubfach way to render doubles",
 ##      https://drive.google.com/open?id=1luHhyQF9zKlM8yJ1nebU0OgVYhfC6CBN
-## --------------------------------------------------------------------------------------------------
+# --------------------------------------------------------------------------------------------------
 
 import std/private/digitsutils
 
@@ -19,9 +19,9 @@ when defined(nimPreviewSlimSystem):
 template sf_Assert(x: untyped): untyped =
   assert(x)
 
-## ==================================================================================================
-##
-## ==================================================================================================
+# ==================================================================================================
+#
+# ==================================================================================================
 
 type
   ValueType = float32
@@ -68,7 +68,7 @@ proc isZero(this: Single): bool {.noSideEffect.} =
 proc signBit(this: Single): int {.noSideEffect.} =
   return int((this.bits and signMask) != 0)
 
-## ==================================================================================================
+# ==================================================================================================
 ##  Returns floor(x / 2^n).
 ##
 ##  Technically, right-shift of negative integers is implementation defined...
diff --git a/lib/std/syncio.nim b/lib/std/syncio.nim
index eab96254a..22e981198 100644
--- a/lib/std/syncio.nim
+++ b/lib/std/syncio.nim
@@ -11,7 +11,7 @@
 
 include system/inclrtl
 import std/private/since
-import system/formatfloat
+import std/formatfloat
 
 # ----------------- IO Part ------------------------------------------------
 type
diff --git a/lib/system/chcks.nim b/lib/system/chcks.nim
index 1e1ce9c87..bdf2903d2 100644
--- a/lib/system/chcks.nim
+++ b/lib/system/chcks.nim
@@ -9,6 +9,8 @@
 
 # Implementation of some runtime checks.
 include system/indexerrors
+when defined(nimPreviewSlimSystem):
+  import std/formatfloat
 
 proc raiseRangeError(val: BiggestInt) {.compilerproc, noinline.} =
   when hostOS == "standalone":
diff --git a/lib/system/dollars.nim b/lib/system/dollars.nim
index b060aedb0..4ff3d0ae6 100644
--- a/lib/system/dollars.nim
+++ b/lib/system/dollars.nim
@@ -4,8 +4,14 @@ runnableExamples:
   assert $(-2*3) == "-6"
 
 import std/private/[digitsutils, miscdollars]
-import system/formatfloat
-export addFloat
+
+when not defined(nimPreviewSlimSystem):
+  import std/formatfloat
+  export addFloat
+
+  func `$`*(x: float | float32): string =
+    ## Outplace version of `addFloat`.
+    result.addFloat(x)
 
 proc `$`*(x: int): string {.raises: [].} =
   ## Outplace version of `addInt`.
@@ -27,9 +33,6 @@ gen(int)
 gen(uint64)
 gen(int64)
 
-func `$`*(x: float | float32): string =
-  ## Outplace version of `addFloat`.
-  result.addFloat(x)
 
 proc `$`*(x: bool): string {.magic: "BoolToStr", noSideEffect.}
   ## The stringify operator for a boolean argument. Returns `x`
diff --git a/lib/system/formatfloat.nim b/lib/system/formatfloat.nim
index aada3e1bf..70dd857d5 100644
--- a/lib/system/formatfloat.nim
+++ b/lib/system/formatfloat.nim
@@ -1,135 +1,6 @@
-#
-#
-#            Nim's Runtime Library
-#        (c) Copyright 2019 Nim contributors
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-when defined(nimPreviewSlimSystem):
-  import std/assertions
-
-proc c_memcpy(a, b: pointer, size: csize_t): pointer {.importc: "memcpy", header: "<string.h>", discardable.}
-
-proc addCstringN(result: var string, buf: cstring; buflen: int) =
-  # no nimvm support needed, so it doesn't need to be fast here either
-  let oldLen = result.len
-  let newLen = oldLen + buflen
-  result.setLen newLen
-  c_memcpy(result[oldLen].addr, buf, buflen.csize_t)
-
-import dragonbox, schubfach
-
-proc writeFloatToBufferRoundtrip*(buf: var array[65, char]; value: BiggestFloat): int =
-  ## This is the implementation to format floats.
-  ##
-  ## returns the amount of bytes written to `buf` not counting the
-  ## terminating '\0' character.
-  result = toChars(buf, value, forceTrailingDotZero=true)
-  buf[result] = '\0'
-
-proc writeFloatToBufferRoundtrip*(buf: var array[65, char]; value: float32): int =
-  result = float32ToChars(buf, value, forceTrailingDotZero=true)
-  buf[result] = '\0'
-
-proc c_sprintf(buf, frmt: cstring): cint {.header: "<stdio.h>",
-                                    importc: "sprintf", varargs, noSideEffect.}
-
-proc writeToBuffer(buf: var array[65, char]; value: cstring) =
-  var i = 0
-  while value[i] != '\0':
-    buf[i] = value[i]
-    inc i
-
-proc writeFloatToBufferSprintf*(buf: var array[65, char]; value: BiggestFloat): int =
-  ## This is the implementation to format floats.
-  ##
-  ## returns the amount of bytes written to `buf` not counting the
-  ## terminating '\0' character.
-  var n: int = c_sprintf(addr buf, "%.16g", value)
-  var hasDot = false
-  for i in 0..n-1:
-    if buf[i] == ',':
-      buf[i] = '.'
-      hasDot = true
-    elif buf[i] in {'a'..'z', 'A'..'Z', '.'}:
-      hasDot = true
-  if not hasDot:
-    buf[n] = '.'
-    buf[n+1] = '0'
-    buf[n+2] = '\0'
-    result = n + 2
-  else:
-    result = n
-  # On Windows nice numbers like '1.#INF', '-1.#INF' or '1.#NAN' or 'nan(ind)'
-  # of '-1.#IND' are produced.
-  # We want to get rid of these here:
-  if buf[n-1] in {'n', 'N', 'D', 'd', ')'}:
-    writeToBuffer(buf, "nan")
-    result = 3
-  elif buf[n-1] == 'F':
-    if buf[0] == '-':
-      writeToBuffer(buf, "-inf")
-      result = 4
-    else:
-      writeToBuffer(buf, "inf")
-      result = 3
-
-proc writeFloatToBuffer*(buf: var array[65, char]; value: BiggestFloat | float32): int {.inline.} =
-  when defined(nimPreviewFloatRoundtrip):
-    writeFloatToBufferRoundtrip(buf, value)
-  else:
-    writeFloatToBufferSprintf(buf, value)
-
-proc addFloatRoundtrip*(result: var string; x: float | float32) =
-  when nimvm:
-    doAssert false
-  else:
-    var buffer {.noinit.}: array[65, char]
-    let n = writeFloatToBufferRoundtrip(buffer, x)
-    result.addCstringN(cstring(buffer[0].addr), n)
-
-proc addFloatSprintf*(result: var string; x: float) =
-  when nimvm:
-    doAssert false
-  else:
-    var buffer {.noinit.}: array[65, char]
-    let n = writeFloatToBufferSprintf(buffer, x)
-    result.addCstringN(cstring(buffer[0].addr), n)
-
-proc nimFloatToString(a: float): cstring =
-  ## ensures the result doesn't print like an integer, i.e. return 2.0, not 2
-  # print `-0.0` properly
-  asm """
-    function nimOnlyDigitsOrMinus(n) {
-      return n.toString().match(/^-?\d+$/);
-    }
-    if (Number.isSafeInteger(`a`))
-      `result` = `a` === 0 && 1 / `a` < 0 ? "-0.0" : `a`+".0"
-    else {
-      `result` = `a`+""
-      if(nimOnlyDigitsOrMinus(`result`)){
-        `result` = `a`+".0"
-      }
-    }
-  """
-
-proc addFloat*(result: var string; x: float | float32) {.inline.} =
-  ## Converts float to its string representation and appends it to `result`.
-  runnableExamples:
-    var
-      s = "foo:"
-      b = 45.67
-    s.addFloat(45.67)
-    assert s == "foo:45.67"
-  template impl =
-    when defined(nimPreviewFloatRoundtrip):
-      addFloatRoundtrip(result, x)
-    else:
-      addFloatSprintf(result, x)
-  when defined(js):
-    when nimvm: impl()
-    else:
-      result.add nimFloatToString(x)
-  else: impl()
+when not defined(nimPreviewSlimSystem):
+  import std/formatfloat
+  export formatfloat
+  {.deprecated: "use `std/formatfloat`".}
+else:
+  {.error: "use `std/formatfloat`".}
diff --git a/lib/system/repr_v2.nim b/lib/system/repr_v2.nim
index 6ab5f3c3f..0e9bec0f3 100644
--- a/lib/system/repr_v2.nim
+++ b/lib/system/repr_v2.nim
@@ -1,5 +1,8 @@
 include system/inclrtl
 
+when defined(nimPreviewSlimSystem):
+  import std/formatfloat
+
 proc isNamedTuple(T: typedesc): bool {.magic: "TypeTrait".}
   ## imported from typetraits