Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions compiler/ast.nim
Original file line number Diff line number Diff line change
Expand Up @@ -652,8 +652,8 @@ type
mUnaryMinusI, mUnaryMinusI64, mAbsI, mNot,
mUnaryPlusI, mBitnotI,
mUnaryPlusF64, mUnaryMinusF64,
mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr,
mFloatToStr, # for -d:nimVersion140
mCharToStr, mBoolToStr,
mIntToStr, mInt64ToStr, mFloatToStr, # for -d:nimVersion140
mCStrToStr,
mStrToStr, mEnumToStr,
mAnd, mOr,
Expand Down Expand Up @@ -722,8 +722,8 @@ const
mEqRef, mEqProc, mLePtr, mLtPtr, mEqCString, mXor,
mUnaryMinusI, mUnaryMinusI64, mAbsI, mNot, mUnaryPlusI, mBitnotI,
mUnaryPlusF64, mUnaryMinusF64,
mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr,
mFloatToStr,
mCharToStr, mBoolToStr,
mIntToStr, mInt64ToStr, mFloatToStr,
mCStrToStr,
mStrToStr, mEnumToStr,
mAnd, mOr,
Expand Down
68 changes: 53 additions & 15 deletions lib/std/private/digitsutils.nim
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,34 @@ const
# doAssert res == digits100

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

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

func addIntImpl*(result: var string, origin: uint64) =
when defined(js):
proc numToString(a: SomeInteger): cstring {.importjs: "((#) + \"\")".}

func addChars[T](result: var string, x: T, start: int, n: int) {.inline.} =
let old = result.len
result.setLen old + n
template impl =
for i in 0..<n: result[old + i] = x[start + i]
when nimvm: impl
else:
when defined(js) or defined(nimscript): impl
else:
{.noSideEffect.}:
copyMem result[old].addr, x[start].unsafeAddr, n

func addChars[T](result: var string, x: T) {.inline.} =
addChars(result, x, 0, x.len)

func addIntImpl(result: var string, x: uint64) {.inline.} =
var tmp {.noinit.}: array[24, char]
var num = origin
var num = x
var next = tmp.len - 1
const nbatch = 100

Expand All @@ -60,17 +76,39 @@ func addIntImpl*(result: var string, origin: uint64) =
tmp[next] = digits100[index + 1]
tmp[next - 1] = digits100[index]
dec next
let n = result.len
let length = tmp.len - next
result.setLen n + length
when nimvm:
for i in 0..<length:
result[n+i] = tmp[next+i]
addChars(result, tmp, next, tmp.len - next)

func addInt*(result: var string, x: uint64) =
when nimvm: addIntImpl(result, x)
else:
when defined(js) or defined(nimscript):
for i in 0..<length:
result[n+i] = tmp[next+i]
when not defined(js): addIntImpl(result, x)
else:
{.noSideEffect.}:
copyMem result[n].addr, tmp[next].addr, length
addChars(result, numToString(x))

proc addInt*(result: var string; x: int64) =
## Converts integer to its string representation and appends it to `result`.
runnableExamples:
var s = "foo"
s.addInt(45)
assert s == "foo45"
template impl =
var num: uint64
if x < 0:
if x == low(int64):
num = uint64(x)
else:
num = uint64(-x)
let base = result.len
setLen(result, base + 1)
result[base] = '-'
else:
num = uint64(x)
addInt(result, num)
when nimvm: impl()
else:
when defined(js):
addChars(result, numToString(x))
else: impl()

proc addInt*(result: var string; x: int) {.inline.} =
addInt(result, int64(x))
9 changes: 4 additions & 5 deletions lib/std/private/miscdollars.nim
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
from std/private/digitsutils import addInt

template toLocation*(result: var string, file: string | cstring, line: int, col: int) =
## avoids spurious allocations
# Hopefully this can be re-used everywhere so that if a user needs to customize,
# it can be done in a single place.
result.add file
if line > 0:
result.add "("
# simplify this after moving moving `include strmantle` above import assertions`
when declared(addInt): result.addInt line
else: result.add $line
addInt(result, line)
if col > 0:
result.add ", "
when declared(addInt): result.addInt col
else: result.add $col
addInt(result, col)
result.add ")"
9 changes: 4 additions & 5 deletions lib/system.nim
Original file line number Diff line number Diff line change
Expand Up @@ -2463,14 +2463,13 @@ when notJSnotNims:
else:
{.error: "Only closure iterator is allowed!".}

from std/private/digitsutils import addInt
export addInt

when defined(js):
include "system/jssys"
include "system/reprjs"

when defined(js) or defined(nimscript):
proc addInt*(result: var string; x: int64) =
result.add $x

proc quit*(errormsg: string, errorcode = QuitFailure) {.noreturn.} =
## A shorthand for `echo(errormsg); quit(errorcode)`.
when defined(nimscript) or defined(js) or (hostOS == "standalone"):
Expand Down Expand Up @@ -2918,7 +2917,7 @@ proc addQuoted*[T](s: var string, x: T) =
s.addEscapedChar(x)
s.add("'")
# prevent temporary string allocation
elif T is SomeSignedInt:
elif T is SomeInteger:
s.addInt(x)
elif T is SomeFloat:
s.addFloat(x)
Expand Down
5 changes: 3 additions & 2 deletions lib/system/assertions.nim
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import std/private/miscdollars

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

proc `$`(x: int): string {.magic: "IntToStr", noSideEffect.}
proc `$`(info: InstantiationInfo): string =
# The +1 is needed here
# instead of overriding `$` (and changing its meaning), consider explicit name.
Expand Down Expand Up @@ -108,7 +107,9 @@ template doAssertRaises*(exception: typedesc, code: untyped) =
wrong = true
except exception:
discard
except Exception as e: raiseAssert(begin & " raised '" & $e.name & "'" & msgEnd)
except Exception as e:
mixin `$` # alternatively, we could define $cstring in this module
raiseAssert(begin & " raised '" & $e.name & "'" & msgEnd)
except: raisedForeign()
if wrong:
raiseAssert(begin & " nothing was raised" & msgEnd)
62 changes: 24 additions & 38 deletions lib/system/dollars.nim
Original file line number Diff line number Diff line change
@@ -1,45 +1,31 @@
## `$` is Nim's general way of spelling `toString`:idx:.
runnableExamples:
assert $0.1 == "0.1"
assert $(-2*3) == "-6"

import std/private/digitsutils
import system/formatfloat
export addFloat

proc `$`*(x: int): string {.magic: "IntToStr", noSideEffect.}
## The stringify operator for an integer argument. Returns `x`
## converted to a decimal string. `$` is Nim's general way of
## spelling `toString`:idx:.

template dollarImpl(x: uint | uint64, result: var string) =
addIntImpl(result, x)

when defined(js):
import std/private/since
since (1, 3):
proc `$`*(x: uint): string =
## Caveat: currently implemented as $(cast[int](x)), tied to current
## semantics of js' Number type.
# for c, see strmantle.`$`
when nimvm:
dollarImpl(x, result)
else:
result = $(int(x))

proc `$`*(x: uint64): string =
## Compatibility note:
## the results may change in future releases if/when js target implements
## 64bit ints.
# pending https://github.com/nim-lang/RFCs/issues/187
when nimvm:
dollarImpl(x, result)
else:
result = $(cast[int](x))
else:
proc `$`*(x: uint64): string {.noSideEffect, raises: [].} =
## The stringify operator for an unsigned integer argument. Returns `x`
## converted to a decimal string.
dollarImpl(x, result)

proc `$`*(x: int64): string {.magic: "Int64ToStr", noSideEffect.}
## The stringify operator for an integer argument. Returns `x`
## converted to a decimal string.
proc `$`*(x: int): string {.raises: [].} =
## Outplace version of `addInt`.
result.addInt(x)

proc `$`*(x: int64): string {.raises: [].} =
## Outplace version of `addInt`.
result.addInt(x)

proc `$`*(x: uint64): string {.raises: [].} =
## Outplace version of `addInt`.
addInt(result, x)

# same as old `ctfeWhitelist` behavior, whether or not this is a good idea.
template gen(T) =
# xxx simplify this by supporting this in compiler: int{lit} | uint64{lit} | int64{lit}
func `$`*(x: T{lit}): string {.compileTime.} = result.addInt(x)
gen(int)
gen(uint64)
gen(int64)

func `$`*(x: float | float32): string =
## Outplace version of `addFloat`.
Expand Down
17 changes: 8 additions & 9 deletions lib/system/repr_v2.nim
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,17 @@ proc distinctBase(T: typedesc, recursive: static bool = true): typedesc {.magic:

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

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

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

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

proc repr*(x: float): string =
## Same as $x
Expand Down
30 changes: 0 additions & 30 deletions lib/system/strmantle.nim
Original file line number Diff line number Diff line change
Expand Up @@ -43,32 +43,6 @@ proc hashString(s: string): int {.compilerproc.} =
h = h + h shl 15
result = cast[int](h)

proc addInt*(result: var string; x: int64) =
## Converts integer to its string representation and appends it to `result`.
##
## .. code-block:: Nim
## var
## a = "123"
## b = 45
## a.addInt(b) # a <- "12345"
var num: uint64

if x < 0:
if x == low(int64):
num = uint64(x)
else:
num = uint64(-x)
let base = result.len
setLen(result, base + 1)
result[base] = '-'
else:
num = uint64(x)
addIntImpl(result, num)

proc nimIntToStr(x: int): string {.compilerRtl.} =
result = newStringOfCap(sizeof(x)*4)
result.addInt x

proc c_strtod(buf: cstring, endptr: ptr cstring): float64 {.
importc: "strtod", header: "<stdlib.h>", noSideEffect.}

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

proc nimInt64ToStr(x: int64): string {.compilerRtl.} =
result = newStringOfCap(sizeof(x)*4)
result.addInt x

proc nimBoolToStr(x: bool): string {.compilerRtl.} =
return if x: "true" else: "false"

Expand Down
2 changes: 1 addition & 1 deletion nimsuggest/tests/tqualified_highlight.nim
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ highlight;;skProc;;1;;7;;4
highlight;;skTemplate;;2;;7;;4
highlight;;skTemplate;;2;;7;;4
highlight;;skTemplate;;2;;7;;4
highlight;;skProc;;3;;8;;1
highlight;;skFunc;;3;;8;;1
"""
13 changes: 8 additions & 5 deletions tests/pragmas/tinjectstmt.nim
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,18 @@ ok0
ok1
onInject: 3
onInject: 4
0
onInject: 5
0
onInject: 6
1
onInject: 7
onInject: 8
1
onInject: 9
onInject: 10
onInject: 11
2
ok2
onInject: 9
onInject: 12
'''
"""

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

from system/ansi_c import c_printf
Expand All @@ -44,5 +47,5 @@ proc main()=
echo a
echo "ok2"

static: main() # xxx injectStmt not honred in VM
static: main() # xxx injectStmt not honored in VM
main()
Loading