Skip to content

Commit 082320c

Browse files
timotheecourPMunch
authored andcommitted
improvements to addInt and $ for integer types (nim-lang#18592)
* improvements to $(SomeInteger) and addInt * remove mIntToStr, mInt64ToStr * improvements * fix tests/pragmas/tinjectstmt.nim; the diff is harmless, cgen code is identical with -d:danger or debug mode * rm tests/system/tstrmantle.nim * revert compiler/jsgen.nim for -d:nimVersion140
1 parent a8e1ea7 commit 082320c

File tree

12 files changed

+163
-187
lines changed

12 files changed

+163
-187
lines changed

compiler/ast.nim

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -652,8 +652,8 @@ type
652652
mUnaryMinusI, mUnaryMinusI64, mAbsI, mNot,
653653
mUnaryPlusI, mBitnotI,
654654
mUnaryPlusF64, mUnaryMinusF64,
655-
mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr,
656-
mFloatToStr, # for -d:nimVersion140
655+
mCharToStr, mBoolToStr,
656+
mIntToStr, mInt64ToStr, mFloatToStr, # for -d:nimVersion140
657657
mCStrToStr,
658658
mStrToStr, mEnumToStr,
659659
mAnd, mOr,
@@ -722,8 +722,8 @@ const
722722
mEqRef, mEqProc, mLePtr, mLtPtr, mEqCString, mXor,
723723
mUnaryMinusI, mUnaryMinusI64, mAbsI, mNot, mUnaryPlusI, mBitnotI,
724724
mUnaryPlusF64, mUnaryMinusF64,
725-
mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr,
726-
mFloatToStr,
725+
mCharToStr, mBoolToStr,
726+
mIntToStr, mInt64ToStr, mFloatToStr,
727727
mCStrToStr,
728728
mStrToStr, mEnumToStr,
729729
mAnd, mOr,

lib/std/private/digitsutils.nim

Lines changed: 53 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -29,18 +29,34 @@ const
2929
# doAssert res == digits100
3030

3131
proc utoa2Digits*(buf: var openArray[char]; pos: int; digits: uint32) {.inline.} =
32-
assert(digits <= 99)
3332
buf[pos] = digits100[2 * digits]
3433
buf[pos+1] = digits100[2 * digits + 1]
3534
#copyMem(buf, unsafeAddr(digits100[2 * digits]), 2 * sizeof((char)))
3635

3736
proc trailingZeros2Digits*(digits: uint32): int32 {.inline.} =
38-
assert(digits <= 99)
3937
return trailingZeros100[digits]
4038

41-
func addIntImpl*(result: var string, origin: uint64) =
39+
when defined(js):
40+
proc numToString(a: SomeInteger): cstring {.importjs: "((#) + \"\")".}
41+
42+
func addChars[T](result: var string, x: T, start: int, n: int) {.inline.} =
43+
let old = result.len
44+
result.setLen old + n
45+
template impl =
46+
for i in 0..<n: result[old + i] = x[start + i]
47+
when nimvm: impl
48+
else:
49+
when defined(js) or defined(nimscript): impl
50+
else:
51+
{.noSideEffect.}:
52+
copyMem result[old].addr, x[start].unsafeAddr, n
53+
54+
func addChars[T](result: var string, x: T) {.inline.} =
55+
addChars(result, x, 0, x.len)
56+
57+
func addIntImpl(result: var string, x: uint64) {.inline.} =
4258
var tmp {.noinit.}: array[24, char]
43-
var num = origin
59+
var num = x
4460
var next = tmp.len - 1
4561
const nbatch = 100
4662
@@ -60,17 +76,39 @@ func addIntImpl*(result: var string, origin: uint64) =
6076
tmp[next] = digits100[index + 1]
6177
tmp[next - 1] = digits100[index]
6278
dec next
63-
let n = result.len
64-
let length = tmp.len - next
65-
result.setLen n + length
66-
when nimvm:
67-
for i in 0..<length:
68-
result[n+i] = tmp[next+i]
79+
addChars(result, tmp, next, tmp.len - next)
80+
81+
func addInt*(result: var string, x: uint64) =
82+
when nimvm: addIntImpl(result, x)
6983
else:
70-
when defined(js) or defined(nimscript):
71-
for i in 0..<length:
72-
result[n+i] = tmp[next+i]
84+
when not defined(js): addIntImpl(result, x)
7385
else:
74-
{.noSideEffect.}:
75-
copyMem result[n].addr, tmp[next].addr, length
86+
addChars(result, numToString(x))
87+
88+
proc addInt*(result: var string; x: int64) =
89+
## Converts integer to its string representation and appends it to `result`.
90+
runnableExamples:
91+
var s = "foo"
92+
s.addInt(45)
93+
assert s == "foo45"
94+
template impl =
95+
var num: uint64
96+
if x < 0:
97+
if x == low(int64):
98+
num = uint64(x)
99+
else:
100+
num = uint64(-x)
101+
let base = result.len
102+
setLen(result, base + 1)
103+
result[base] = '-'
104+
else:
105+
num = uint64(x)
106+
addInt(result, num)
107+
when nimvm: impl()
108+
else:
109+
when defined(js):
110+
addChars(result, numToString(x))
111+
else: impl()
76112

113+
proc addInt*(result: var string; x: int) {.inline.} =
114+
addInt(result, int64(x))

lib/std/private/miscdollars.nim

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
1+
from std/private/digitsutils import addInt
2+
13
template toLocation*(result: var string, file: string | cstring, line: int, col: int) =
24
## avoids spurious allocations
35
# Hopefully this can be re-used everywhere so that if a user needs to customize,
46
# it can be done in a single place.
57
result.add file
68
if line > 0:
79
result.add "("
8-
# simplify this after moving moving `include strmantle` above import assertions`
9-
when declared(addInt): result.addInt line
10-
else: result.add $line
10+
addInt(result, line)
1111
if col > 0:
1212
result.add ", "
13-
when declared(addInt): result.addInt col
14-
else: result.add $col
13+
addInt(result, col)
1514
result.add ")"

lib/system.nim

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2463,14 +2463,13 @@ when notJSnotNims:
24632463
else:
24642464
{.error: "Only closure iterator is allowed!".}
24652465

2466+
from std/private/digitsutils import addInt
2467+
export addInt
2468+
24662469
when defined(js):
24672470
include "system/jssys"
24682471
include "system/reprjs"
24692472

2470-
when defined(js) or defined(nimscript):
2471-
proc addInt*(result: var string; x: int64) =
2472-
result.add $x
2473-
24742473
proc quit*(errormsg: string, errorcode = QuitFailure) {.noreturn.} =
24752474
## A shorthand for `echo(errormsg); quit(errorcode)`.
24762475
when defined(nimscript) or defined(js) or (hostOS == "standalone"):
@@ -2918,7 +2917,7 @@ proc addQuoted*[T](s: var string, x: T) =
29182917
s.addEscapedChar(x)
29192918
s.add("'")
29202919
# prevent temporary string allocation
2921-
elif T is SomeSignedInt:
2920+
elif T is SomeInteger:
29222921
s.addInt(x)
29232922
elif T is SomeFloat:
29242923
s.addFloat(x)

lib/system/assertions.nim

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import std/private/miscdollars
1212

1313
type InstantiationInfo = tuple[filename: string, line: int, column: int]
1414

15-
proc `$`(x: int): string {.magic: "IntToStr", noSideEffect.}
1615
proc `$`(info: InstantiationInfo): string =
1716
# The +1 is needed here
1817
# instead of overriding `$` (and changing its meaning), consider explicit name.
@@ -108,7 +107,9 @@ template doAssertRaises*(exception: typedesc, code: untyped) =
108107
wrong = true
109108
except exception:
110109
discard
111-
except Exception as e: raiseAssert(begin & " raised '" & $e.name & "'" & msgEnd)
110+
except Exception as e:
111+
mixin `$` # alternatively, we could define $cstring in this module
112+
raiseAssert(begin & " raised '" & $e.name & "'" & msgEnd)
112113
except: raisedForeign()
113114
if wrong:
114115
raiseAssert(begin & " nothing was raised" & msgEnd)

lib/system/dollars.nim

Lines changed: 24 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,31 @@
1+
## `$` is Nim's general way of spelling `toString`:idx:.
2+
runnableExamples:
3+
assert $0.1 == "0.1"
4+
assert $(-2*3) == "-6"
5+
16
import std/private/digitsutils
27
import system/formatfloat
38
export addFloat
49

5-
proc `$`*(x: int): string {.magic: "IntToStr", noSideEffect.}
6-
## The stringify operator for an integer argument. Returns `x`
7-
## converted to a decimal string. `$` is Nim's general way of
8-
## spelling `toString`:idx:.
9-
10-
template dollarImpl(x: uint | uint64, result: var string) =
11-
addIntImpl(result, x)
12-
13-
when defined(js):
14-
import std/private/since
15-
since (1, 3):
16-
proc `$`*(x: uint): string =
17-
## Caveat: currently implemented as $(cast[int](x)), tied to current
18-
## semantics of js' Number type.
19-
# for c, see strmantle.`$`
20-
when nimvm:
21-
dollarImpl(x, result)
22-
else:
23-
result = $(int(x))
24-
25-
proc `$`*(x: uint64): string =
26-
## Compatibility note:
27-
## the results may change in future releases if/when js target implements
28-
## 64bit ints.
29-
# pending https://github.com/nim-lang/RFCs/issues/187
30-
when nimvm:
31-
dollarImpl(x, result)
32-
else:
33-
result = $(cast[int](x))
34-
else:
35-
proc `$`*(x: uint64): string {.noSideEffect, raises: [].} =
36-
## The stringify operator for an unsigned integer argument. Returns `x`
37-
## converted to a decimal string.
38-
dollarImpl(x, result)
39-
40-
proc `$`*(x: int64): string {.magic: "Int64ToStr", noSideEffect.}
41-
## The stringify operator for an integer argument. Returns `x`
42-
## converted to a decimal string.
10+
proc `$`*(x: int): string {.raises: [].} =
11+
## Outplace version of `addInt`.
12+
result.addInt(x)
13+
14+
proc `$`*(x: int64): string {.raises: [].} =
15+
## Outplace version of `addInt`.
16+
result.addInt(x)
17+
18+
proc `$`*(x: uint64): string {.raises: [].} =
19+
## Outplace version of `addInt`.
20+
addInt(result, x)
21+
22+
# same as old `ctfeWhitelist` behavior, whether or not this is a good idea.
23+
template gen(T) =
24+
# xxx simplify this by supporting this in compiler: int{lit} | uint64{lit} | int64{lit}
25+
func `$`*(x: T{lit}): string {.compileTime.} = result.addInt(x)
26+
gen(int)
27+
gen(uint64)
28+
gen(int64)
4329

4430
func `$`*(x: float | float32): string =
4531
## Outplace version of `addFloat`.

lib/system/repr_v2.nim

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,17 @@ proc distinctBase(T: typedesc, recursive: static bool = true): typedesc {.magic:
88

99
proc repr*(x: NimNode): string {.magic: "Repr", noSideEffect.}
1010

11-
proc repr*(x: int): string {.magic: "IntToStr", noSideEffect.}
12-
## repr for an integer argument. Returns `x`
13-
## converted to a decimal string.
11+
proc repr*(x: int): string =
12+
## Same as $x
13+
$x
1414

15-
proc repr*(x: int64): string {.magic: "Int64ToStr", noSideEffect.}
16-
## repr for an integer argument. Returns `x`
17-
## converted to a decimal string.
15+
proc repr*(x: int64): string =
16+
## Same as $x
17+
$x
1818

1919
proc repr*(x: uint64): string {.noSideEffect.} =
20-
## repr for an unsigned integer argument. Returns `x`
21-
## converted to a decimal string.
22-
$x #Calls `$` from system/strmantle.nim
20+
## Same as $x
21+
$x
2322

2423
proc repr*(x: float): string =
2524
## Same as $x

lib/system/strmantle.nim

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -43,32 +43,6 @@ proc hashString(s: string): int {.compilerproc.} =
4343
h = h + h shl 15
4444
result = cast[int](h)
4545

46-
proc addInt*(result: var string; x: int64) =
47-
## Converts integer to its string representation and appends it to `result`.
48-
##
49-
## .. code-block:: Nim
50-
## var
51-
## a = "123"
52-
## b = 45
53-
## a.addInt(b) # a <- "12345"
54-
var num: uint64
55-
56-
if x < 0:
57-
if x == low(int64):
58-
num = uint64(x)
59-
else:
60-
num = uint64(-x)
61-
let base = result.len
62-
setLen(result, base + 1)
63-
result[base] = '-'
64-
else:
65-
num = uint64(x)
66-
addIntImpl(result, num)
67-
68-
proc nimIntToStr(x: int): string {.compilerRtl.} =
69-
result = newStringOfCap(sizeof(x)*4)
70-
result.addInt x
71-
7246
proc c_strtod(buf: cstring, endptr: ptr cstring): float64 {.
7347
importc: "strtod", header: "<stdlib.h>", noSideEffect.}
7448

@@ -240,10 +214,6 @@ proc nimParseBiggestFloat(s: string, number: var BiggestFloat,
240214
when defined(nimHasInvariant):
241215
{.pop.} # staticBoundChecks
242216

243-
proc nimInt64ToStr(x: int64): string {.compilerRtl.} =
244-
result = newStringOfCap(sizeof(x)*4)
245-
result.addInt x
246-
247217
proc nimBoolToStr(x: bool): string {.compilerRtl.} =
248218
return if x: "true" else: "false"
249219

nimsuggest/tests/tqualified_highlight.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@ highlight;;skProc;;1;;7;;4
1010
highlight;;skTemplate;;2;;7;;4
1111
highlight;;skTemplate;;2;;7;;4
1212
highlight;;skTemplate;;2;;7;;4
13-
highlight;;skProc;;3;;8;;1
13+
highlight;;skFunc;;3;;8;;1
1414
"""

tests/pragmas/tinjectstmt.nim

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,18 @@ ok0
77
ok1
88
onInject: 3
99
onInject: 4
10-
0
1110
onInject: 5
11+
0
1212
onInject: 6
13-
1
1413
onInject: 7
1514
onInject: 8
15+
1
16+
onInject: 9
17+
onInject: 10
18+
onInject: 11
1619
2
1720
ok2
18-
onInject: 9
21+
onInject: 12
1922
'''
2023
"""
2124

@@ -25,7 +28,7 @@ onInject: 9
2528
{.injectStmt.} pragma can be used to inject a statement before every
2629
other statement in the current module. It's now undocumented and may be removed
2730
in the future and replaced with something more general and without its limitations.
28-
e.g. (e.g. doesn't work in VM or js backends).
31+
(e.g. doesn't work in VM or js backends).
2932
]#
3033

3134
from system/ansi_c import c_printf
@@ -44,5 +47,5 @@ proc main()=
4447
echo a
4548
echo "ok2"
4649

47-
static: main() # xxx injectStmt not honred in VM
50+
static: main() # xxx injectStmt not honored in VM
4851
main()

0 commit comments

Comments
 (0)