Merge branch 'araq-stringify-array' into devel
This commit is contained in:
commit
13f974336e
24 changed files with 247 additions and 130 deletions
|
|
@ -5,3 +5,6 @@
|
||||||
- Removed basic2d/basic3d out of the stdlib and into Nimble packages.
|
- Removed basic2d/basic3d out of the stdlib and into Nimble packages.
|
||||||
These packages deprecated however, use the ``glm``, ``arraymancer``, ``neo``
|
These packages deprecated however, use the ``glm``, ``arraymancer``, ``neo``
|
||||||
or another package.
|
or another package.
|
||||||
|
- Arrays of char cannot be converted to ``cstring`` anymore, pointers to
|
||||||
|
arrays of char can! This means ``$`` for arrays can finally exist
|
||||||
|
in ``system.nim`` and do the right thing.
|
||||||
|
|
|
||||||
|
|
@ -108,3 +108,4 @@ proc initDefines*() =
|
||||||
defineSymbol("nimHasCppDefine")
|
defineSymbol("nimHasCppDefine")
|
||||||
defineSymbol("nimGenericInOutFlags")
|
defineSymbol("nimGenericInOutFlags")
|
||||||
when false: defineSymbol("nimHasOpt")
|
when false: defineSymbol("nimHasOpt")
|
||||||
|
defineSymbol("nimNoArrayToCstringConversion")
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,9 @@
|
||||||
## x = y where y is read only once
|
## x = y where y is read only once
|
||||||
## is the same as: move(x, y)
|
## is the same as: move(x, y)
|
||||||
##
|
##
|
||||||
|
## Actually the more general rule is: The *last* read of ``y``
|
||||||
|
## can become a move if ``y`` is the result of a construction.
|
||||||
|
##
|
||||||
## We also need to keep in mind here that the number of reads is
|
## We also need to keep in mind here that the number of reads is
|
||||||
## control flow dependent:
|
## control flow dependent:
|
||||||
## let x = foo()
|
## let x = foo()
|
||||||
|
|
@ -183,10 +186,67 @@ when false:
|
||||||
of nkVarSection, nkLetSection: collectVarSection(c, n)
|
of nkVarSection, nkLetSection: collectVarSection(c, n)
|
||||||
else: discard
|
else: discard
|
||||||
|
|
||||||
|
type
|
||||||
|
Con = object
|
||||||
|
owner: PSym
|
||||||
|
g: ControlFlowGraph
|
||||||
|
tmps: PType
|
||||||
|
|
||||||
|
proc isHarmlessVar*(s: PSym; c: Con): bool =
|
||||||
|
# 's' is harmless if it used only once and its
|
||||||
|
# definition/usage are not split by any labels:
|
||||||
|
#
|
||||||
|
# let s = foo()
|
||||||
|
# while true:
|
||||||
|
# a[i] = s
|
||||||
|
#
|
||||||
|
# produces:
|
||||||
|
#
|
||||||
|
# def s
|
||||||
|
# L1:
|
||||||
|
# use s
|
||||||
|
# goto L1
|
||||||
|
#
|
||||||
|
# let s = foo()
|
||||||
|
# if cond:
|
||||||
|
# a[i] = s
|
||||||
|
# else:
|
||||||
|
# a[j] = s
|
||||||
|
#
|
||||||
|
# produces:
|
||||||
|
#
|
||||||
|
# def s
|
||||||
|
# fork L2
|
||||||
|
# use s
|
||||||
|
# goto L3
|
||||||
|
# L2:
|
||||||
|
# use s
|
||||||
|
# L3
|
||||||
|
#
|
||||||
|
# So this analysis is for now overly conservative, but correct.
|
||||||
|
discard
|
||||||
|
|
||||||
|
template interestingSym(s: PSym): bool =
|
||||||
|
s.owner == owner and s.kind in InterestingSyms and hasDestructor(s.typ)
|
||||||
|
|
||||||
|
proc p(n, parent: PNode; c: var Con) =
|
||||||
|
case n.kind
|
||||||
|
of nkVarSection, nkLetSection:
|
||||||
|
discard "transform; var x = y to var x; x op y where op is a move or copy"
|
||||||
|
of nkCallKinds:
|
||||||
|
if n.typ != nil and hasDestructor(n.typ):
|
||||||
|
discard "produce temp creation"
|
||||||
|
of nkAsgn, nkFastAsgn:
|
||||||
|
if n[0].kind == nkSym and interestingSym(n[0].sym):
|
||||||
|
discard "use move or assignment"
|
||||||
|
else:
|
||||||
|
for i in 0..<n.len:
|
||||||
|
p(n[i], n, c)
|
||||||
|
|
||||||
proc injectDestructorCalls*(owner: PSym; n: PNode;
|
proc injectDestructorCalls*(owner: PSym; n: PNode;
|
||||||
disableExceptions = false): PNode =
|
disableExceptions = false): PNode =
|
||||||
when false:
|
when false:
|
||||||
var c = Con(t: initTable[int, VarInfo](), owner: owner)
|
var c = Con(t: initTable[int, VarInfo](), owner: owner)
|
||||||
collectData(c, n)
|
collectData(c, n)
|
||||||
var allTemps = createObj(owner, n.info)
|
var allTemps = createObj(owner, n.info)
|
||||||
|
let cfg = constructCfg(owner, n)
|
||||||
|
|
|
||||||
|
|
@ -1011,7 +1011,10 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
||||||
of nkPrefix:
|
of nkPrefix:
|
||||||
gsub(g, n, 0)
|
gsub(g, n, 0)
|
||||||
if n.len > 1:
|
if n.len > 1:
|
||||||
if n[1].kind == nkPrefix:
|
let opr = if n[0].kind == nkIdent: n[0].ident
|
||||||
|
elif n[0].kind == nkSym: n[0].sym.name
|
||||||
|
else: nil
|
||||||
|
if n[1].kind == nkPrefix or (opr != nil and renderer.isKeyword(opr)):
|
||||||
put(g, tkSpaces, Space)
|
put(g, tkSpaces, Space)
|
||||||
if n.sons[1].kind == nkInfix:
|
if n.sons[1].kind == nkInfix:
|
||||||
put(g, tkParLe, "(")
|
put(g, tkParLe, "(")
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
## Serialization utilities for the compiler.
|
## Serialization utilities for the compiler.
|
||||||
import strutils
|
import strutils
|
||||||
|
|
||||||
proc c_sprintf(buf, frmt: cstring) {.importc: "sprintf", header: "<stdio.h>", nodecl, varargs.}
|
proc c_snprintf(s: cstring; n:uint; frmt: cstring): cint {.importc: "snprintf", header: "<stdio.h>", nodecl, varargs.}
|
||||||
|
|
||||||
proc toStrMaxPrecision*(f: BiggestFloat, literalPostfix = ""): string =
|
proc toStrMaxPrecision*(f: BiggestFloat, literalPostfix = ""): string =
|
||||||
if f != f:
|
if f != f:
|
||||||
|
|
@ -20,10 +20,15 @@ proc toStrMaxPrecision*(f: BiggestFloat, literalPostfix = ""): string =
|
||||||
elif f == 0.5 * f:
|
elif f == 0.5 * f:
|
||||||
if f > 0.0: result = "INF"
|
if f > 0.0: result = "INF"
|
||||||
else: result = "-INF"
|
else: result = "-INF"
|
||||||
|
else:
|
||||||
|
when defined(nimNoArrayToCstringConversion):
|
||||||
|
result = newString(81)
|
||||||
|
let n = c_snprintf(result.cstring, result.len.uint, "%#.16e%s", f, literalPostfix.cstring)
|
||||||
|
setLen(result, n)
|
||||||
else:
|
else:
|
||||||
var buf: array[0..80, char]
|
var buf: array[0..80, char]
|
||||||
c_sprintf(buf, "%#.16e" & literalPostfix, f)
|
discard c_snprintf(buf.cstring, buf.len.uint, "%#.16e%s", f, literalPostfix.cstring)
|
||||||
result = $buf
|
result = $buf.cstring
|
||||||
|
|
||||||
proc encodeStr*(s: string, result: var string) =
|
proc encodeStr*(s: string, result: var string) =
|
||||||
for i in countup(0, len(s) - 1):
|
for i in countup(0, len(s) - 1):
|
||||||
|
|
@ -133,4 +138,3 @@ iterator decodeStrArray*(s: cstring): string =
|
||||||
while s[i] != '\0':
|
while s[i] != '\0':
|
||||||
yield decodeStr(s, i)
|
yield decodeStr(s, i)
|
||||||
if s[i] == ' ': inc i
|
if s[i] == ' ': inc i
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1288,11 +1288,12 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType,
|
||||||
of tyString: result = isConvertible
|
of tyString: result = isConvertible
|
||||||
of tyPtr:
|
of tyPtr:
|
||||||
# ptr[Tag, char] is not convertible to 'cstring' for now:
|
# ptr[Tag, char] is not convertible to 'cstring' for now:
|
||||||
if a.len == 1 and a.sons[0].kind == tyChar: result = isConvertible
|
if a.len == 1:
|
||||||
of tyArray:
|
let pointsTo = a.sons[0].skipTypes(abstractInst)
|
||||||
if (firstOrd(a.sons[0]) == 0) and
|
if pointsTo.kind == tyChar: result = isConvertible
|
||||||
(skipTypes(a.sons[0], {tyRange}).kind in {tyInt..tyInt64}) and
|
elif pointsTo.kind == tyArray and firstOrd(pointsTo.sons[0]) == 0 and
|
||||||
(a.sons[1].kind == tyChar):
|
skipTypes(pointsTo.sons[0], {tyRange}).kind in {tyInt..tyInt64} and
|
||||||
|
pointsTo.sons[1].kind == tyChar:
|
||||||
result = isConvertible
|
result = isConvertible
|
||||||
else: discard
|
else: discard
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -667,14 +667,6 @@ proc lengthOrd*(t: PType): BiggestInt =
|
||||||
else:
|
else:
|
||||||
result = lastOrd(t) - firstOrd(t) + 1
|
result = lastOrd(t) - firstOrd(t) + 1
|
||||||
|
|
||||||
proc isCompatibleToCString*(a: PType): bool =
|
|
||||||
if a.kind == tyArray:
|
|
||||||
if (firstOrd(a.sons[0]) == 0) and
|
|
||||||
(skipTypes(a.sons[0], {tyRange, tyGenericInst, tyAlias}).kind in
|
|
||||||
{tyInt..tyInt64, tyUInt..tyUInt64}) and
|
|
||||||
(a.sons[1].kind == tyChar):
|
|
||||||
result = true
|
|
||||||
|
|
||||||
# -------------- type equality -----------------------------------------------
|
# -------------- type equality -----------------------------------------------
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
|
||||||
|
|
@ -63,16 +63,16 @@ proc recvLine*(sock: SecureSocket, line: var TaintedString): bool =
|
||||||
setLen(line.string, 0)
|
setLen(line.string, 0)
|
||||||
while true:
|
while true:
|
||||||
var c: array[0..0, char]
|
var c: array[0..0, char]
|
||||||
var n = BIO_read(sock.bio, c, c.len.cint)
|
var n = BIO_read(sock.bio, addr c, c.len.cint)
|
||||||
if n <= 0: return false
|
if n <= 0: return false
|
||||||
if c[0] == '\r':
|
if c[0] == '\r':
|
||||||
n = BIO_read(sock.bio, c, c.len.cint)
|
n = BIO_read(sock.bio, addr c, c.len.cint)
|
||||||
if n > 0 and c[0] == '\L':
|
if n > 0 and c[0] == '\L':
|
||||||
return true
|
return true
|
||||||
elif n <= 0:
|
elif n <= 0:
|
||||||
return false
|
return false
|
||||||
elif c[0] == '\L': return true
|
elif c[0] == '\L': return true
|
||||||
add(line.string, c)
|
add(line.string, c[0])
|
||||||
|
|
||||||
|
|
||||||
proc send*(sock: SecureSocket, data: string) =
|
proc send*(sock: SecureSocket, data: string) =
|
||||||
|
|
|
||||||
|
|
@ -496,11 +496,12 @@ proc getLocalAddr*(socket: SocketHandle, domain: Domain): (string, Port) =
|
||||||
addr(namelen)) == -1'i32:
|
addr(namelen)) == -1'i32:
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
# Cannot use INET6_ADDRSTRLEN here, because it's a C define.
|
# Cannot use INET6_ADDRSTRLEN here, because it's a C define.
|
||||||
var buf: array[64, char]
|
result[0] = newString(64)
|
||||||
if inet_ntop(name.sin6_family.cint,
|
if inet_ntop(name.sin6_family.cint,
|
||||||
addr name.sin6_addr, buf.cstring, sizeof(buf).int32).isNil:
|
addr name.sin6_addr, addr result[0][0], (result[0].len+1).int32).isNil:
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
result = ($buf, Port(nativesockets.ntohs(name.sin6_port)))
|
setLen(result[0], result[0].cstring.len)
|
||||||
|
result[1] = Port(nativesockets.ntohs(name.sin6_port))
|
||||||
else:
|
else:
|
||||||
raiseOSError(OSErrorCode(-1), "invalid socket family in getLocalAddr")
|
raiseOSError(OSErrorCode(-1), "invalid socket family in getLocalAddr")
|
||||||
|
|
||||||
|
|
@ -532,11 +533,12 @@ proc getPeerAddr*(socket: SocketHandle, domain: Domain): (string, Port) =
|
||||||
addr(namelen)) == -1'i32:
|
addr(namelen)) == -1'i32:
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
# Cannot use INET6_ADDRSTRLEN here, because it's a C define.
|
# Cannot use INET6_ADDRSTRLEN here, because it's a C define.
|
||||||
var buf: array[64, char]
|
result[0] = newString(64)
|
||||||
if inet_ntop(name.sin6_family.cint,
|
if inet_ntop(name.sin6_family.cint,
|
||||||
addr name.sin6_addr, buf.cstring, sizeof(buf).int32).isNil:
|
addr name.sin6_addr, addr result[0][0], (result[0].len+1).int32).isNil:
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
result = ($buf, Port(nativesockets.ntohs(name.sin6_port)))
|
setLen(result[0], result[0].cstring.len)
|
||||||
|
result[1] = Port(nativesockets.ntohs(name.sin6_port))
|
||||||
else:
|
else:
|
||||||
raiseOSError(OSErrorCode(-1), "invalid socket family in getLocalAddr")
|
raiseOSError(OSErrorCode(-1), "invalid socket family in getLocalAddr")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -790,7 +790,10 @@ iterator walkDir*(dir: string; relative=false): tuple[kind: PathComponent, path:
|
||||||
while true:
|
while true:
|
||||||
var x = readdir(d)
|
var x = readdir(d)
|
||||||
if x == nil: break
|
if x == nil: break
|
||||||
var y = $x.d_name
|
when defined(nimNoArrayToCstringConversion):
|
||||||
|
var y = $cstring(addr x.d_name)
|
||||||
|
else:
|
||||||
|
var y = $x.d_name.cstring
|
||||||
if y != "." and y != "..":
|
if y != "." and y != "..":
|
||||||
var s: Stat
|
var s: Stat
|
||||||
if not relative:
|
if not relative:
|
||||||
|
|
|
||||||
|
|
@ -1890,10 +1890,16 @@ proc formatBiggestFloat*(f: BiggestFloat, format: FloatFormatMode = ffDefault,
|
||||||
frmtstr[3] = '*'
|
frmtstr[3] = '*'
|
||||||
frmtstr[4] = floatFormatToChar[format]
|
frmtstr[4] = floatFormatToChar[format]
|
||||||
frmtstr[5] = '\0'
|
frmtstr[5] = '\0'
|
||||||
|
when defined(nimNoArrayToCstringConversion):
|
||||||
|
L = c_sprintf(addr buf, addr frmtstr, precision, f)
|
||||||
|
else:
|
||||||
L = c_sprintf(buf, frmtstr, precision, f)
|
L = c_sprintf(buf, frmtstr, precision, f)
|
||||||
else:
|
else:
|
||||||
frmtstr[1] = floatFormatToChar[format]
|
frmtstr[1] = floatFormatToChar[format]
|
||||||
frmtstr[2] = '\0'
|
frmtstr[2] = '\0'
|
||||||
|
when defined(nimNoArrayToCstringConversion):
|
||||||
|
L = c_sprintf(addr buf, addr frmtstr, f)
|
||||||
|
else:
|
||||||
L = c_sprintf(buf, frmtstr, f)
|
L = c_sprintf(buf, frmtstr, f)
|
||||||
result = newString(L)
|
result = newString(L)
|
||||||
for i in 0 ..< L:
|
for i in 0 ..< L:
|
||||||
|
|
|
||||||
|
|
@ -1875,7 +1875,7 @@ proc `$` *(x: float): string {.magic: "FloatToStr", noSideEffect.}
|
||||||
proc `$` *(x: bool): string {.magic: "BoolToStr", noSideEffect.}
|
proc `$` *(x: bool): string {.magic: "BoolToStr", noSideEffect.}
|
||||||
## The stringify operator for a boolean argument. Returns `x`
|
## The stringify operator for a boolean argument. Returns `x`
|
||||||
## converted to the string "false" or "true".
|
## converted to the string "false" or "true".
|
||||||
|
#
|
||||||
proc `$` *(x: char): string {.magic: "CharToStr", noSideEffect.}
|
proc `$` *(x: char): string {.magic: "CharToStr", noSideEffect.}
|
||||||
## The stringify operator for a character argument. Returns `x`
|
## The stringify operator for a character argument. Returns `x`
|
||||||
## converted to a string.
|
## converted to a string.
|
||||||
|
|
@ -2437,20 +2437,28 @@ proc `$`*[T: tuple|object](x: T): string =
|
||||||
result.add("...")
|
result.add("...")
|
||||||
result.add(")")
|
result.add(")")
|
||||||
|
|
||||||
proc collectionToString[T: set | seq](x: T, b, e: string): string =
|
proc collectionToString[T](x: T, prefix, separator, suffix: string): string =
|
||||||
when x is seq:
|
result = prefix
|
||||||
if x.isNil: return "nil"
|
|
||||||
result = b
|
|
||||||
var firstElement = true
|
var firstElement = true
|
||||||
for value in items(x):
|
for value in items(x):
|
||||||
if not firstElement: result.add(", ")
|
if firstElement:
|
||||||
|
firstElement = false
|
||||||
|
else:
|
||||||
|
result.add(separator)
|
||||||
|
|
||||||
when compiles(value.isNil):
|
when compiles(value.isNil):
|
||||||
if value.isNil: result.add "nil"
|
# this branch should not be necessary
|
||||||
else: result.add($value)
|
if value.isNil:
|
||||||
|
result.add "nil"
|
||||||
else:
|
else:
|
||||||
result.add($value)
|
result.add($value)
|
||||||
firstElement = false
|
# prevent temporary string allocation
|
||||||
result.add(e)
|
elif compiles(result.add(value)):
|
||||||
|
result.add(value)
|
||||||
|
else:
|
||||||
|
result.add($value)
|
||||||
|
|
||||||
|
result.add(suffix)
|
||||||
|
|
||||||
proc `$`*[T](x: set[T]): string =
|
proc `$`*[T](x: set[T]): string =
|
||||||
## generic ``$`` operator for sets that is lifted from the components
|
## generic ``$`` operator for sets that is lifted from the components
|
||||||
|
|
@ -2458,7 +2466,7 @@ proc `$`*[T](x: set[T]): string =
|
||||||
##
|
##
|
||||||
## .. code-block:: nim
|
## .. code-block:: nim
|
||||||
## ${23, 45} == "{23, 45}"
|
## ${23, 45} == "{23, 45}"
|
||||||
collectionToString(x, "{", "}")
|
collectionToString(x, "{", ", ", "}")
|
||||||
|
|
||||||
proc `$`*[T](x: seq[T]): string =
|
proc `$`*[T](x: seq[T]): string =
|
||||||
## generic ``$`` operator for seqs that is lifted from the components
|
## generic ``$`` operator for seqs that is lifted from the components
|
||||||
|
|
@ -2466,13 +2474,10 @@ proc `$`*[T](x: seq[T]): string =
|
||||||
##
|
##
|
||||||
## .. code-block:: nim
|
## .. code-block:: nim
|
||||||
## $(@[23, 45]) == "@[23, 45]"
|
## $(@[23, 45]) == "@[23, 45]"
|
||||||
collectionToString(x, "@[", "]")
|
if x.isNil:
|
||||||
|
"nil"
|
||||||
when false:
|
else:
|
||||||
# causes bootstrapping to fail as we use array of chars and cstring should
|
collectionToString(x, "@[", ", ", "]")
|
||||||
# match better ...
|
|
||||||
proc `$`*[T, IDX](x: array[IDX, T]): string =
|
|
||||||
collectionToString(x, "[", "]")
|
|
||||||
|
|
||||||
# ----------------- GC interface ---------------------------------------------
|
# ----------------- GC interface ---------------------------------------------
|
||||||
|
|
||||||
|
|
@ -3329,6 +3334,10 @@ elif defined(JS):
|
||||||
include "system/sysio"
|
include "system/sysio"
|
||||||
|
|
||||||
|
|
||||||
|
proc `$`*[T, IDX](x: array[IDX, T]): string =
|
||||||
|
## generic ``$`` operator for arrays that is lifted from the components
|
||||||
|
collectionToString(x, "[", ", ", "]")
|
||||||
|
|
||||||
proc quit*(errormsg: string, errorcode = QuitFailure) {.noReturn.} =
|
proc quit*(errormsg: string, errorcode = QuitFailure) {.noReturn.} =
|
||||||
## a shorthand for ``echo(errormsg); quit(errorcode)``.
|
## a shorthand for ``echo(errormsg); quit(errorcode)``.
|
||||||
echo(errormsg)
|
echo(errormsg)
|
||||||
|
|
|
||||||
|
|
@ -142,6 +142,9 @@ elif defined(windows) or defined(dos):
|
||||||
dec(m)
|
dec(m)
|
||||||
k = k div 10
|
k = k div 10
|
||||||
if k == 0: break
|
if k == 0: break
|
||||||
|
when defined(nimNoArrayToCstringConversion):
|
||||||
|
result = getProcAddress(cast[THINSTANCE](lib), addr decorated)
|
||||||
|
else:
|
||||||
result = getProcAddress(cast[THINSTANCE](lib), decorated)
|
result = getProcAddress(cast[THINSTANCE](lib), decorated)
|
||||||
if result != nil: return
|
if result != nil: return
|
||||||
procAddrError(name)
|
procAddrError(name)
|
||||||
|
|
|
||||||
|
|
@ -76,10 +76,10 @@ proc `==`(a, b: StaticStr): bool =
|
||||||
return true
|
return true
|
||||||
|
|
||||||
proc `==`(a: StaticStr, b: cstring): bool =
|
proc `==`(a: StaticStr, b: cstring): bool =
|
||||||
result = c_strcmp(a.data, b) == 0
|
result = c_strcmp(unsafeAddr a.data, b) == 0
|
||||||
|
|
||||||
proc write(f: File, s: StaticStr) =
|
proc write(f: File, s: StaticStr) =
|
||||||
write(f, cstring(s.data))
|
write(f, cstring(unsafeAddr s.data))
|
||||||
|
|
||||||
proc listBreakPoints() =
|
proc listBreakPoints() =
|
||||||
write(stdout, EndbBeg)
|
write(stdout, EndbBeg)
|
||||||
|
|
@ -260,8 +260,8 @@ proc parseBreakpoint(s: cstring, start: int): Breakpoint =
|
||||||
if result.high == 0: result.high = result.low
|
if result.high == 0: result.high = result.low
|
||||||
i = scanFilename(s, dbgTemp, i)
|
i = scanFilename(s, dbgTemp, i)
|
||||||
if dbgTemp.len != 0:
|
if dbgTemp.len != 0:
|
||||||
if not hasExt(dbgTemp.data): add(dbgTemp, ".nim")
|
if not hasExt(addr dbgTemp.data): add(dbgTemp, ".nim")
|
||||||
result.filename = canonFilename(dbgTemp.data.cstring)
|
result.filename = canonFilename(addr dbgTemp.data)
|
||||||
if result.filename.isNil:
|
if result.filename.isNil:
|
||||||
debugOut("[Warning] no breakpoint could be set; unknown filename ")
|
debugOut("[Warning] no breakpoint could be set; unknown filename ")
|
||||||
return
|
return
|
||||||
|
|
@ -292,12 +292,12 @@ proc dbgEvaluate(stream: File, s: cstring, start: int, f: PFrame) =
|
||||||
i = scanAndAppendWord(s, dbgTemp, i)
|
i = scanAndAppendWord(s, dbgTemp, i)
|
||||||
for i in 0 .. getGlobalLen()-1:
|
for i in 0 .. getGlobalLen()-1:
|
||||||
let v = getGlobal(i)
|
let v = getGlobal(i)
|
||||||
if c_strcmp(v.name, dbgTemp.data) == 0:
|
if c_strcmp(v.name, addr dbgTemp.data) == 0:
|
||||||
writeVariable(stream, v)
|
writeVariable(stream, v)
|
||||||
else:
|
else:
|
||||||
for i in 0 .. f.len-1:
|
for i in 0 .. f.len-1:
|
||||||
let v = getLocal(f, i)
|
let v = getLocal(f, i)
|
||||||
if c_strcmp(v.name, dbgTemp.data) == 0:
|
if c_strcmp(v.name, addr dbgTemp.data) == 0:
|
||||||
writeVariable(stream, v)
|
writeVariable(stream, v)
|
||||||
|
|
||||||
proc dbgOut(s: cstring, start: int, currFrame: PFrame) =
|
proc dbgOut(s: cstring, start: int, currFrame: PFrame) =
|
||||||
|
|
@ -306,7 +306,7 @@ proc dbgOut(s: cstring, start: int, currFrame: PFrame) =
|
||||||
if dbgTemp.len == 0:
|
if dbgTemp.len == 0:
|
||||||
invalidCommand()
|
invalidCommand()
|
||||||
return
|
return
|
||||||
var stream = openAppend(dbgTemp.data)
|
var stream = openAppend(addr dbgTemp.data)
|
||||||
if stream == nil:
|
if stream == nil:
|
||||||
debugOut("[Warning] could not open or create file ")
|
debugOut("[Warning] could not open or create file ")
|
||||||
return
|
return
|
||||||
|
|
@ -320,7 +320,7 @@ proc dbgStackFrame(s: cstring, start: int, currFrame: PFrame) =
|
||||||
# just write it to stdout:
|
# just write it to stdout:
|
||||||
listFrame(stdout, currFrame)
|
listFrame(stdout, currFrame)
|
||||||
else:
|
else:
|
||||||
var stream = openAppend(dbgTemp.data)
|
var stream = openAppend(addr dbgTemp.data)
|
||||||
if stream == nil:
|
if stream == nil:
|
||||||
debugOut("[Warning] could not open or create file ")
|
debugOut("[Warning] could not open or create file ")
|
||||||
return
|
return
|
||||||
|
|
@ -369,7 +369,7 @@ proc commandPrompt() =
|
||||||
if not readLine(stdin, dbgUser): break
|
if not readLine(stdin, dbgUser): break
|
||||||
if dbgUser.len == 0: dbgUser.len = oldLen
|
if dbgUser.len == 0: dbgUser.len = oldLen
|
||||||
# now look what we have to do:
|
# now look what we have to do:
|
||||||
var i = scanWord(dbgUser.data, dbgTemp, 0)
|
var i = scanWord(addr dbgUser.data, dbgTemp, 0)
|
||||||
template `?`(x: expr): expr = dbgTemp == cstring(x)
|
template `?`(x: expr): expr = dbgTemp == cstring(x)
|
||||||
if ?"s" or ?"step":
|
if ?"s" or ?"step":
|
||||||
dbgState = dbStepInto
|
dbgState = dbStepInto
|
||||||
|
|
@ -400,13 +400,13 @@ proc commandPrompt() =
|
||||||
prevState = dbgState
|
prevState = dbgState
|
||||||
prevSkipFrame = dbgSkipToFrame
|
prevSkipFrame = dbgSkipToFrame
|
||||||
dbgState = dbSkipCurrent
|
dbgState = dbSkipCurrent
|
||||||
dbgEvaluate(stdout, dbgUser.data, i, dbgFramePtr)
|
dbgEvaluate(stdout, addr dbgUser.data, i, dbgFramePtr)
|
||||||
dbgState = prevState
|
dbgState = prevState
|
||||||
dbgSkipToFrame = prevSkipFrame
|
dbgSkipToFrame = prevSkipFrame
|
||||||
elif ?"o" or ?"out":
|
elif ?"o" or ?"out":
|
||||||
dbgOut(dbgUser.data, i, dbgFramePtr)
|
dbgOut(addr dbgUser.data, i, dbgFramePtr)
|
||||||
elif ?"stackframe":
|
elif ?"stackframe":
|
||||||
dbgStackFrame(dbgUser.data, i, dbgFramePtr)
|
dbgStackFrame(addr dbgUser.data, i, dbgFramePtr)
|
||||||
elif ?"w" or ?"where":
|
elif ?"w" or ?"where":
|
||||||
dbgShowExecutionPoint()
|
dbgShowExecutionPoint()
|
||||||
elif ?"l" or ?"locals":
|
elif ?"l" or ?"locals":
|
||||||
|
|
@ -444,16 +444,16 @@ proc commandPrompt() =
|
||||||
elif ?"bt" or ?"backtrace":
|
elif ?"bt" or ?"backtrace":
|
||||||
dbgWriteStackTrace(framePtr)
|
dbgWriteStackTrace(framePtr)
|
||||||
elif ?"b" or ?"break":
|
elif ?"b" or ?"break":
|
||||||
createBreakPoint(dbgUser.data, i)
|
createBreakPoint(addr dbgUser.data, i)
|
||||||
elif ?"breakpoints":
|
elif ?"breakpoints":
|
||||||
listBreakPoints()
|
listBreakPoints()
|
||||||
elif ?"toggle":
|
elif ?"toggle":
|
||||||
breakpointToggle(dbgUser.data, i)
|
breakpointToggle(addr dbgUser.data, i)
|
||||||
elif ?"filenames":
|
elif ?"filenames":
|
||||||
listFilenames()
|
listFilenames()
|
||||||
elif ?"maxdisplay":
|
elif ?"maxdisplay":
|
||||||
var parsed: int
|
var parsed: int
|
||||||
i = scanNumber(dbgUser.data, parsed, i)
|
i = scanNumber(addr dbgUser.data, parsed, i)
|
||||||
if dbgUser.data[i-1] in {'0'..'9'}:
|
if dbgUser.data[i-1] in {'0'..'9'}:
|
||||||
if parsed == 0: maxDisplayRecDepth = -1
|
if parsed == 0: maxDisplayRecDepth = -1
|
||||||
else: maxDisplayRecDepth = parsed
|
else: maxDisplayRecDepth = parsed
|
||||||
|
|
|
||||||
|
|
@ -289,8 +289,12 @@ proc raiseExceptionAux(e: ref Exception) =
|
||||||
add(buf, " [")
|
add(buf, " [")
|
||||||
xadd(buf, e.name, e.name.len)
|
xadd(buf, e.name, e.name.len)
|
||||||
add(buf, "]\n")
|
add(buf, "]\n")
|
||||||
unhandled(buf):
|
when defined(nimNoArrayToCstringConversion):
|
||||||
showErrorMessage(buf)
|
template tbuf(): untyped = addr buf
|
||||||
|
else:
|
||||||
|
template tbuf(): untyped = buf
|
||||||
|
unhandled(tbuf()):
|
||||||
|
showErrorMessage(tbuf())
|
||||||
quitOrDebug()
|
quitOrDebug()
|
||||||
|
|
||||||
proc raiseException(e: ref Exception, ename: cstring) {.compilerRtl.} =
|
proc raiseException(e: ref Exception, ename: cstring) {.compilerRtl.} =
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,11 @@ proc reprInt(x: int64): string {.compilerproc.} = return $x
|
||||||
proc reprFloat(x: float): string {.compilerproc.} = return $x
|
proc reprFloat(x: float): string {.compilerproc.} = return $x
|
||||||
|
|
||||||
proc reprPointer(x: pointer): string {.compilerproc.} =
|
proc reprPointer(x: pointer): string {.compilerproc.} =
|
||||||
|
when defined(nimNoArrayToCstringConversion):
|
||||||
|
result = newString(60)
|
||||||
|
let n = c_sprintf(addr result[0], "%p", x)
|
||||||
|
setLen(result, n)
|
||||||
|
else:
|
||||||
var buf: array[0..59, char]
|
var buf: array[0..59, char]
|
||||||
discard c_sprintf(buf, "%p", x)
|
discard c_sprintf(buf, "%p", x)
|
||||||
return $buf
|
return $buf
|
||||||
|
|
@ -24,19 +29,19 @@ proc `$`(x: uint64): string =
|
||||||
if x == 0:
|
if x == 0:
|
||||||
result = "0"
|
result = "0"
|
||||||
else:
|
else:
|
||||||
var buf: array[60, char]
|
result = newString(60)
|
||||||
var i = 0
|
var i = 0
|
||||||
var n = x
|
var n = x
|
||||||
while n != 0:
|
while n != 0:
|
||||||
let nn = n div 10'u64
|
let nn = n div 10'u64
|
||||||
buf[i] = char(n - 10'u64 * nn + ord('0'))
|
result[i] = char(n - 10'u64 * nn + ord('0'))
|
||||||
inc i
|
inc i
|
||||||
n = nn
|
n = nn
|
||||||
|
result.setLen i
|
||||||
|
|
||||||
let half = i div 2
|
let half = i div 2
|
||||||
# Reverse
|
# Reverse
|
||||||
for t in 0 .. < half: swap(buf[t], buf[i-t-1])
|
for t in 0 .. < half: swap(result[t], result[i-t-1])
|
||||||
result = $buf
|
|
||||||
|
|
||||||
proc reprStrAux(result: var string, s: cstring; len: int) =
|
proc reprStrAux(result: var string, s: cstring; len: int) =
|
||||||
if cast[pointer](s) == nil:
|
if cast[pointer](s) == nil:
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,9 @@ proc cmpStrings(a, b: NimString): int {.inline, compilerProc.} =
|
||||||
if a == b: return 0
|
if a == b: return 0
|
||||||
if a == nil: return -1
|
if a == nil: return -1
|
||||||
if b == nil: return 1
|
if b == nil: return 1
|
||||||
|
when defined(nimNoArrayToCstringConversion):
|
||||||
|
return c_strcmp(addr a.data, addr b.data)
|
||||||
|
else:
|
||||||
return c_strcmp(a.data, b.data)
|
return c_strcmp(a.data, b.data)
|
||||||
|
|
||||||
proc eqStrings(a, b: NimString): bool {.inline, compilerProc.} =
|
proc eqStrings(a, b: NimString): bool {.inline, compilerProc.} =
|
||||||
|
|
@ -320,6 +323,9 @@ proc nimIntToStr(x: int): string {.compilerRtl.} =
|
||||||
|
|
||||||
proc add*(result: var string; x: float) =
|
proc add*(result: var string; x: float) =
|
||||||
var buf: array[0..64, char]
|
var buf: array[0..64, char]
|
||||||
|
when defined(nimNoArrayToCstringConversion):
|
||||||
|
var n: int = c_sprintf(addr buf, "%.16g", x)
|
||||||
|
else:
|
||||||
var n: int = c_sprintf(buf, "%.16g", x)
|
var n: int = c_sprintf(buf, "%.16g", x)
|
||||||
var hasDot = false
|
var hasDot = false
|
||||||
for i in 0..n-1:
|
for i in 0..n-1:
|
||||||
|
|
@ -342,7 +348,10 @@ proc add*(result: var string; x: float) =
|
||||||
else:
|
else:
|
||||||
result.add "inf"
|
result.add "inf"
|
||||||
else:
|
else:
|
||||||
result.add buf
|
var i = 0
|
||||||
|
while buf[i] != '\0':
|
||||||
|
result.add buf[i]
|
||||||
|
inc i
|
||||||
|
|
||||||
proc nimFloatToStr(f: float): string {.compilerproc.} =
|
proc nimFloatToStr(f: float): string {.compilerproc.} =
|
||||||
result = newStringOfCap(8)
|
result = newStringOfCap(8)
|
||||||
|
|
@ -507,6 +516,9 @@ proc nimParseBiggestFloat(s: string, number: var BiggestFloat,
|
||||||
t[ti-2] = ('0'.ord + abs_exponent mod 10).char; abs_exponent = abs_exponent div 10
|
t[ti-2] = ('0'.ord + abs_exponent mod 10).char; abs_exponent = abs_exponent div 10
|
||||||
t[ti-3] = ('0'.ord + abs_exponent mod 10).char
|
t[ti-3] = ('0'.ord + abs_exponent mod 10).char
|
||||||
|
|
||||||
|
when defined(nimNoArrayToCstringConversion):
|
||||||
|
number = c_strtod(addr t, nil)
|
||||||
|
else:
|
||||||
number = c_strtod(t, nil)
|
number = c_strtod(t, nil)
|
||||||
|
|
||||||
proc nimInt64ToStr(x: int64): string {.compilerRtl.} =
|
proc nimInt64ToStr(x: int64): string {.compilerRtl.} =
|
||||||
|
|
|
||||||
|
|
@ -590,13 +590,13 @@ proc md5_Transform*(c: var MD5_CTX; b: ptr cuchar){.importc: "MD5_Transform".}
|
||||||
|
|
||||||
from strutils import toHex, toLowerAscii
|
from strutils import toHex, toLowerAscii
|
||||||
|
|
||||||
proc hexStr (buf:cstring): string =
|
proc hexStr(buf: cstring): string =
|
||||||
# turn md5s output into a nice hex str
|
# turn md5s output into a nice hex str
|
||||||
result = newStringOfCap(32)
|
result = newStringOfCap(32)
|
||||||
for i in 0 .. <16:
|
for i in 0 .. <16:
|
||||||
result.add toHex(buf[i].ord, 2).toLowerAscii
|
result.add toHex(buf[i].ord, 2).toLowerAscii
|
||||||
|
|
||||||
proc md5_File* (file: string): string {.raises: [IOError,Exception].} =
|
proc md5_File*(file: string): string {.raises: [IOError,Exception].} =
|
||||||
## Generate MD5 hash for a file. Result is a 32 character
|
## Generate MD5 hash for a file. Result is a 32 character
|
||||||
# hex string with lowercase characters (like the output
|
# hex string with lowercase characters (like the output
|
||||||
# of `md5sum`
|
# of `md5sum`
|
||||||
|
|
@ -611,14 +611,14 @@ proc md5_File* (file: string): string {.raises: [IOError,Exception].} =
|
||||||
while(let bytes = f.readChars(buf, 0, sz); bytes > 0):
|
while(let bytes = f.readChars(buf, 0, sz); bytes > 0):
|
||||||
discard md5_update(ctx, buf[0].addr, bytes)
|
discard md5_update(ctx, buf[0].addr, bytes)
|
||||||
|
|
||||||
discard md5_final( buf[0].addr, ctx )
|
discard md5_final(buf[0].addr, ctx)
|
||||||
f.close
|
f.close
|
||||||
|
|
||||||
result = hexStr(buf)
|
result = hexStr(addr buf)
|
||||||
|
|
||||||
proc md5_Str*(str:string): string =
|
proc md5_Str*(str: string): string =
|
||||||
##Generate MD5 hash for a string. Result is a 32 character
|
## Generate MD5 hash for a string. Result is a 32 character
|
||||||
#hex string with lowercase characters
|
## hex string with lowercase characters
|
||||||
var
|
var
|
||||||
ctx: MD5_CTX
|
ctx: MD5_CTX
|
||||||
res: array[MD5_DIGEST_LENGTH,char]
|
res: array[MD5_DIGEST_LENGTH,char]
|
||||||
|
|
@ -631,5 +631,5 @@ proc md5_Str*(str:string): string =
|
||||||
discard md5_update(ctx, input[i].addr, L)
|
discard md5_update(ctx, input[i].addr, L)
|
||||||
i += L
|
i += L
|
||||||
|
|
||||||
discard md5_final(res,ctx)
|
discard md5_final(addr res, ctx)
|
||||||
result = hexStr(res)
|
result = hexStr(addr res)
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ proc launchSwarm(name: ptr SockAddr) {.async.} =
|
||||||
16384, cast[ptr SockAddr](addr saddr),
|
16384, cast[ptr SockAddr](addr saddr),
|
||||||
addr slen)
|
addr slen)
|
||||||
size = 0
|
size = 0
|
||||||
var grammString = $buffer
|
var grammString = $cstring(addr buffer)
|
||||||
if grammString == message:
|
if grammString == message:
|
||||||
saveSendingPort(sockport)
|
saveSendingPort(sockport)
|
||||||
inc(recvCount)
|
inc(recvCount)
|
||||||
|
|
@ -84,7 +84,7 @@ proc readMessages(server: AsyncFD) {.async.} =
|
||||||
16384, cast[ptr SockAddr](addr(saddr)),
|
16384, cast[ptr SockAddr](addr(saddr)),
|
||||||
addr(slen))
|
addr(slen))
|
||||||
size = 0
|
size = 0
|
||||||
var grammString = $buffer
|
var grammString = $cstring(addr buffer)
|
||||||
if grammString.startswith("Message ") and
|
if grammString.startswith("Message ") and
|
||||||
saddr.sin_addr.s_addr == 0x100007F:
|
saddr.sin_addr.s_addr == 0x100007F:
|
||||||
await sendTo(server, addr grammString[0], len(grammString),
|
await sendTo(server, addr grammString[0], len(grammString),
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ proc c_sprintf(buf, fmt: cstring) {.importc:"sprintf", header: "<stdio.h>", vara
|
||||||
|
|
||||||
proc floatToStr(f: float64): string =
|
proc floatToStr(f: float64): string =
|
||||||
var buffer: array[128, char]
|
var buffer: array[128, char]
|
||||||
c_sprintf(buffer, "%.16e", f)
|
c_sprintf(addr buffer, "%.16e", f)
|
||||||
result = ""
|
result = ""
|
||||||
for ch in buffer:
|
for ch in buffer:
|
||||||
if ch == '\0':
|
if ch == '\0':
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ type
|
||||||
of nkList: sons: seq[PCaseNode]
|
of nkList: sons: seq[PCaseNode]
|
||||||
else: unused: seq[string]
|
else: unused: seq[string]
|
||||||
|
|
||||||
TIdObj* = object of TObject
|
TIdObj* = object of RootObj
|
||||||
id*: int # unique id; use this for comparisons and not the pointers
|
id*: int # unique id; use this for comparisons and not the pointers
|
||||||
|
|
||||||
PIdObj* = ref TIdObj
|
PIdObj* = ref TIdObj
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,8 @@ when not defined(windows):
|
||||||
var buf: array[0..10, char]
|
var buf: array[0..10, char]
|
||||||
while true:
|
while true:
|
||||||
var r = read(0, addr(buf), sizeof(buf)-1)
|
var r = read(0, addr(buf), sizeof(buf)-1)
|
||||||
add inp, $buf
|
add inp, $cstring(addr buf)
|
||||||
if r != sizeof(buf)-1: break
|
if r != sizeof(buf)-1: break
|
||||||
|
|
||||||
echo inp
|
echo inp
|
||||||
#dafkladskölklödsaf ölksdakölfölksfklwe4iojr389wr 89uweokf sdlkf jweklr jweflksdj fioewjfsdlfsd
|
#dafkladskölklödsaf ölksdakölfölksfklwe4iojr389wr 89uweokf sdlkf jweklr jweflksdj fioewjfsdlfsd
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,42 +1,53 @@
|
||||||
discard """
|
discard """
|
||||||
output:'''@[23, 45]
|
output:""
|
||||||
@[, foo, bar]
|
|
||||||
{a, b, c}
|
|
||||||
2.3242
|
|
||||||
2.982
|
|
||||||
123912.1
|
|
||||||
123912.1823
|
|
||||||
5.0
|
|
||||||
1e+100
|
|
||||||
inf
|
|
||||||
-inf
|
|
||||||
nan
|
|
||||||
nil
|
|
||||||
nil'''
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
echo($(@[23, 45]))
|
doAssert "@[23, 45]" == $(@[23, 45])
|
||||||
echo($(@["", "foo", "bar"]))
|
doAssert "[32, 45]" == $([32, 45])
|
||||||
#echo($(["", "foo", "bar"]))
|
doAssert "@[, foo, bar]" == $(@["", "foo", "bar"])
|
||||||
#echo($([23, 45]))
|
doAssert "[, foo, bar]" == $(["", "foo", "bar"])
|
||||||
|
|
||||||
# bug #2395
|
# bug #2395
|
||||||
|
|
||||||
let alphaSet: set[char] = {'a'..'c'}
|
let alphaSet: set[char] = {'a'..'c'}
|
||||||
echo alphaSet
|
doAssert "{a, b, c}" == $alphaSet
|
||||||
|
doAssert "2.3242" == $(2.3242)
|
||||||
echo($(2.3242))
|
doAssert "2.982" == $(2.982)
|
||||||
echo($(2.982))
|
doAssert "123912.1" == $(123912.1)
|
||||||
echo($(123912.1))
|
doAssert "123912.1823" == $(123912.1823)
|
||||||
echo($(123912.1823))
|
doAssert "5.0" == $(5.0)
|
||||||
echo($(5.0))
|
doAssert "1e+100" == $(1e100)
|
||||||
echo($(1e100))
|
doAssert "inf" == $(1e1000000)
|
||||||
echo($(1e1000000))
|
doAssert "-inf" == $(-1e1000000)
|
||||||
echo($(-1e1000000))
|
doAssert "nan" == $(0.0/0.0)
|
||||||
echo($(0.0/0.0))
|
|
||||||
|
|
||||||
# nil tests
|
# nil tests
|
||||||
|
# maybe a bit inconsistent in types
|
||||||
var x: seq[string]
|
var x: seq[string]
|
||||||
var y: string
|
doAssert "nil" == $(x)
|
||||||
echo(x)
|
|
||||||
echo(y)
|
var y: string = nil
|
||||||
|
doAssert nil == $(y)
|
||||||
|
|
||||||
|
type
|
||||||
|
Foo = object
|
||||||
|
a: int
|
||||||
|
b: string
|
||||||
|
|
||||||
|
var foo1: Foo
|
||||||
|
|
||||||
|
# nil string should be an some point in time equal to the empty string
|
||||||
|
doAssert(($foo1)[0..9] == "(a: 0, b: ")
|
||||||
|
|
||||||
|
const
|
||||||
|
data = @['a','b', '\0', 'c','d']
|
||||||
|
dataStr = $data
|
||||||
|
|
||||||
|
# ensure same result when on VM or when at program execution
|
||||||
|
doAssert dataStr == $data
|
||||||
|
|
||||||
|
import strutils
|
||||||
|
# array test
|
||||||
|
|
||||||
|
let arr = ['H','e','l','l','o',' ','W','o','r','l','d','!','\0']
|
||||||
|
doAssert $arr == "[H, e, l, l, o, , W, o, r, l, d, !, \0]"
|
||||||
|
doAssert $cstring(unsafeAddr arr) == "Hello World!"
|
||||||
|
|
|
||||||
1
todo.txt
1
todo.txt
|
|
@ -1,7 +1,6 @@
|
||||||
version 1.0 battle plan
|
version 1.0 battle plan
|
||||||
=======================
|
=======================
|
||||||
|
|
||||||
- disallow conversions from ``array`` to ``cstring``!
|
|
||||||
- make 'not nil' the default (produce warnings instead of errors for
|
- make 'not nil' the default (produce warnings instead of errors for
|
||||||
a smooth migration path)
|
a smooth migration path)
|
||||||
- case objects needs to be safe and need to support pattern matching
|
- case objects needs to be safe and need to support pattern matching
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue