fixes more nil handling regressions
This commit is contained in:
parent
d60bb1b289
commit
420ed0596b
13 changed files with 49 additions and 60 deletions
|
|
@ -971,8 +971,8 @@ const
|
||||||
tyFloat..tyFloat128, tyUInt..tyUInt64}
|
tyFloat..tyFloat128, tyUInt..tyUInt64}
|
||||||
ConstantDataTypes*: TTypeKinds = {tyArray, tySet,
|
ConstantDataTypes*: TTypeKinds = {tyArray, tySet,
|
||||||
tyTuple, tySequence}
|
tyTuple, tySequence}
|
||||||
NilableTypes*: TTypeKinds = {tyPointer, tyCString, tyRef, tyPtr, tySequence,
|
NilableTypes*: TTypeKinds = {tyPointer, tyCString, tyRef, tyPtr,
|
||||||
tyProc, tyString, tyError}
|
tyProc, tyError}
|
||||||
ExportableSymKinds* = {skVar, skConst, skProc, skFunc, skMethod, skType,
|
ExportableSymKinds* = {skVar, skConst, skProc, skFunc, skMethod, skType,
|
||||||
skIterator,
|
skIterator,
|
||||||
skMacro, skTemplate, skConverter, skEnumField, skLet, skStub, skAlias}
|
skMacro, skTemplate, skConverter, skEnumField, skLet, skStub, skAlias}
|
||||||
|
|
|
||||||
|
|
@ -21,14 +21,17 @@ type
|
||||||
formals: int
|
formals: int
|
||||||
c: PContext
|
c: PContext
|
||||||
subMatch: bool # subnode matches are special
|
subMatch: bool # subnode matches are special
|
||||||
|
mappingIsFull: bool
|
||||||
PPatternContext = var TPatternContext
|
PPatternContext = var TPatternContext
|
||||||
|
|
||||||
proc getLazy(c: PPatternContext, sym: PSym): PNode =
|
proc getLazy(c: PPatternContext, sym: PSym): PNode =
|
||||||
if not isNil(c.mapping):
|
if c.mappingIsFull:
|
||||||
result = c.mapping[sym.position]
|
result = c.mapping[sym.position]
|
||||||
|
|
||||||
proc putLazy(c: PPatternContext, sym: PSym, n: PNode) =
|
proc putLazy(c: PPatternContext, sym: PSym, n: PNode) =
|
||||||
if isNil(c.mapping): newSeq(c.mapping, c.formals)
|
if not c.mappingIsFull:
|
||||||
|
newSeq(c.mapping, c.formals)
|
||||||
|
c.mappingIsFull = true
|
||||||
c.mapping[sym.position] = n
|
c.mapping[sym.position] = n
|
||||||
|
|
||||||
proc matches(c: PPatternContext, p, n: PNode): bool
|
proc matches(c: PPatternContext, p, n: PNode): bool
|
||||||
|
|
@ -211,6 +214,7 @@ proc matchStmtList(c: PPatternContext, p, n: PNode): PNode =
|
||||||
# we need to undo any bindings:
|
# we need to undo any bindings:
|
||||||
when defined(nimNoNilSeqs):
|
when defined(nimNoNilSeqs):
|
||||||
c.mapping = @[]
|
c.mapping = @[]
|
||||||
|
c.mappingIsFull = false
|
||||||
else:
|
else:
|
||||||
if not isNil(c.mapping): c.mapping = nil
|
if not isNil(c.mapping): c.mapping = nil
|
||||||
return false
|
return false
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,6 @@ type
|
||||||
t: Thread[ptr Actor[In, Out]]
|
t: Thread[ptr Actor[In, Out]]
|
||||||
|
|
||||||
PActor*[In, Out] = ptr Actor[In, Out] ## an actor
|
PActor*[In, Out] = ptr Actor[In, Out] ## an actor
|
||||||
{.deprecated: [TTask: Task, TActor: Actor].}
|
|
||||||
|
|
||||||
proc spawn*[In, Out](action: proc(
|
proc spawn*[In, Out](action: proc(
|
||||||
self: PActor[In, Out]){.thread.}): PActor[In, Out] =
|
self: PActor[In, Out]){.thread.}): PActor[In, Out] =
|
||||||
|
|
@ -168,7 +167,7 @@ proc terminate*[In, Out](a: var ActorPool[In, Out]) =
|
||||||
for i in 0..<a.actors.len: join(a.actors[i])
|
for i in 0..<a.actors.len: join(a.actors[i])
|
||||||
when Out isnot void:
|
when Out isnot void:
|
||||||
close(a.outputs)
|
close(a.outputs)
|
||||||
a.actors = nil
|
a.actors = @[]
|
||||||
|
|
||||||
proc join*[In, Out](a: var ActorPool[In, Out]) =
|
proc join*[In, Out](a: var ActorPool[In, Out]) =
|
||||||
## short-cut for `sync` and then `terminate`.
|
## short-cut for `sync` and then `terminate`.
|
||||||
|
|
|
||||||
|
|
@ -378,23 +378,23 @@ proc newMultipartData*: MultipartData =
|
||||||
## Constructs a new ``MultipartData`` object.
|
## Constructs a new ``MultipartData`` object.
|
||||||
MultipartData(content: @[])
|
MultipartData(content: @[])
|
||||||
|
|
||||||
proc add*(p: var MultipartData, name, content: string, filename: string = nil,
|
proc add*(p: var MultipartData, name, content: string, filename: string = "",
|
||||||
contentType: string = nil) =
|
contentType: string = "") =
|
||||||
## Add a value to the multipart data. Raises a `ValueError` exception if
|
## Add a value to the multipart data. Raises a `ValueError` exception if
|
||||||
## `name`, `filename` or `contentType` contain newline characters.
|
## `name`, `filename` or `contentType` contain newline characters.
|
||||||
|
|
||||||
if {'\c','\L'} in name:
|
if {'\c','\L'} in name:
|
||||||
raise newException(ValueError, "name contains a newline character")
|
raise newException(ValueError, "name contains a newline character")
|
||||||
if filename != nil and {'\c','\L'} in filename:
|
if {'\c','\L'} in filename:
|
||||||
raise newException(ValueError, "filename contains a newline character")
|
raise newException(ValueError, "filename contains a newline character")
|
||||||
if contentType != nil and {'\c','\L'} in contentType:
|
if {'\c','\L'} in contentType:
|
||||||
raise newException(ValueError, "contentType contains a newline character")
|
raise newException(ValueError, "contentType contains a newline character")
|
||||||
|
|
||||||
var str = "Content-Disposition: form-data; name=\"" & name & "\""
|
var str = "Content-Disposition: form-data; name=\"" & name & "\""
|
||||||
if filename != nil:
|
if filename.len > 0:
|
||||||
str.add("; filename=\"" & filename & "\"")
|
str.add("; filename=\"" & filename & "\"")
|
||||||
str.add("\c\L")
|
str.add("\c\L")
|
||||||
if contentType != nil:
|
if contentType.len > 0:
|
||||||
str.add("Content-Type: " & contentType & "\c\L")
|
str.add("Content-Type: " & contentType & "\c\L")
|
||||||
str.add("\c\L" & content & "\c\L")
|
str.add("\c\L" & content & "\c\L")
|
||||||
|
|
||||||
|
|
@ -434,7 +434,7 @@ proc addFiles*(p: var MultipartData, xs: openarray[tuple[name, file: string]]):
|
||||||
var contentType: string
|
var contentType: string
|
||||||
let (_, fName, ext) = splitFile(file)
|
let (_, fName, ext) = splitFile(file)
|
||||||
if ext.len > 0:
|
if ext.len > 0:
|
||||||
contentType = m.getMimetype(ext[1..ext.high], nil)
|
contentType = m.getMimetype(ext[1..ext.high], "")
|
||||||
p.add(name, readFile(file), fName & ext, contentType)
|
p.add(name, readFile(file), fName & ext, contentType)
|
||||||
result = p
|
result = p
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,10 +47,10 @@ let a = case str1:
|
||||||
|
|
||||||
proc toBool(s: string): bool =
|
proc toBool(s: string): bool =
|
||||||
case s:
|
case s:
|
||||||
of nil, "": raise newException(ValueError, "Invalid boolean")
|
of "": raise newException(ValueError, "Invalid boolean")
|
||||||
elif s[0] == 'Y': true
|
elif s[0] == 'Y': true
|
||||||
elif s[0] == 'N': false
|
elif s[0] == 'N': false
|
||||||
else: "error".quit(2)
|
else: "error".quit(2)
|
||||||
|
|
||||||
|
|
||||||
let b = "NN".toBool()
|
let b = "NN".toBool()
|
||||||
|
|
@ -66,7 +66,7 @@ static:
|
||||||
var bb: bool
|
var bb: bool
|
||||||
doassert(not compiles(
|
doassert(not compiles(
|
||||||
bb = case str2:
|
bb = case str2:
|
||||||
of nil, "": raise newException(ValueError, "Invalid boolean")
|
of "": raise newException(ValueError, "Invalid boolean")
|
||||||
elif str.startsWith("Y"): true
|
elif str.startsWith("Y"): true
|
||||||
elif str.startsWith("N"): false
|
elif str.startsWith("N"): false
|
||||||
))
|
))
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,10 @@ Check passed'''
|
||||||
# bug #5628
|
# bug #5628
|
||||||
|
|
||||||
proc checkException(ex: ref Exception) =
|
proc checkException(ex: ref Exception) =
|
||||||
doAssert(ex.name == "ValueError")
|
doAssert(ex.name == cstring"ValueError")
|
||||||
doAssert(ex.msg == "SecondException")
|
doAssert(ex.msg == "SecondException")
|
||||||
doAssert(ex.parent != nil)
|
doAssert(ex.parent != nil)
|
||||||
doAssert(ex.parent.name == "KeyError")
|
doAssert(ex.parent.name == cstring"KeyError")
|
||||||
doAssert(ex.parent.msg == "FirstException")
|
doAssert(ex.parent.msg == "FirstException")
|
||||||
echo "Check passed"
|
echo "Check passed"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
discard """
|
discard """
|
||||||
line: 22
|
line: 13
|
||||||
errormsg: "type mismatch"
|
errormsg: "type mismatch"
|
||||||
"""
|
"""
|
||||||
{.experimental: "notnil".}
|
{.experimental: "notnil".}
|
||||||
|
|
@ -8,16 +8,6 @@ type
|
||||||
TObj = object
|
TObj = object
|
||||||
x: int
|
x: int
|
||||||
|
|
||||||
MyString = string not nil
|
|
||||||
|
|
||||||
#var x: PObj = nil
|
|
||||||
|
|
||||||
proc p(x: string not nil): int =
|
|
||||||
result = 45
|
|
||||||
|
|
||||||
proc q(x: MyString) = discard
|
|
||||||
proc q2(x: string) = discard
|
proc q2(x: string) = discard
|
||||||
|
|
||||||
q2(nil)
|
q2(nil)
|
||||||
q(nil)
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,4 +2,4 @@
|
||||||
|
|
||||||
template serializationKey*(s: string) {.pragma.}
|
template serializationKey*(s: string) {.pragma.}
|
||||||
template defaultValue*(V: typed) {.pragma.}
|
template defaultValue*(V: typed) {.pragma.}
|
||||||
template alternativeKey*(s: string = nil, V: typed) {.pragma.}
|
template alternativeKey*(s: string = "", V: typed) {.pragma.}
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,8 @@ doAssert "nan" == $(0.0/0.0)
|
||||||
var x: seq[string]
|
var x: seq[string]
|
||||||
doAssert "nil" == $(x)
|
doAssert "nil" == $(x)
|
||||||
|
|
||||||
var y: string = nil
|
var y: string
|
||||||
doAssert nil == $(y)
|
doAssert "" == $(y)
|
||||||
|
|
||||||
type
|
type
|
||||||
Foo = object
|
Foo = object
|
||||||
|
|
@ -54,7 +54,7 @@ doAssert $arr == "['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!', '
|
||||||
doAssert $cstring(unsafeAddr arr) == "Hello World!"
|
doAssert $cstring(unsafeAddr arr) == "Hello World!"
|
||||||
|
|
||||||
proc takes(c: cstring) =
|
proc takes(c: cstring) =
|
||||||
doAssert c == ""
|
doAssert c == cstring""
|
||||||
|
|
||||||
proc testm() =
|
proc testm() =
|
||||||
var x: string
|
var x: string
|
||||||
|
|
@ -90,12 +90,8 @@ proc stringCompare() =
|
||||||
|
|
||||||
doAssert e == ""
|
doAssert e == ""
|
||||||
doAssert "" == e
|
doAssert "" == e
|
||||||
doAssert nil == e
|
|
||||||
doAssert e == nil
|
|
||||||
doAssert f == g
|
doAssert f == g
|
||||||
doAssert "" == ""
|
doAssert "" == ""
|
||||||
doAssert "" == nil
|
|
||||||
doAssert nil == ""
|
|
||||||
|
|
||||||
g.setLen(10)
|
g.setLen(10)
|
||||||
doAssert g == "\0\0\0\0\0\0\0\0\0\0"
|
doAssert g == "\0\0\0\0\0\0\0\0\0\0"
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,9 @@ discard """
|
||||||
import actors
|
import actors
|
||||||
|
|
||||||
var
|
var
|
||||||
pool: TActorPool[int, void]
|
pool: ActorPool[int, void]
|
||||||
createActorPool(pool)
|
createActorPool(pool)
|
||||||
for i in 0 .. < 300:
|
for i in 0 ..< 300:
|
||||||
pool.spawn(i, proc (x: int) {.thread.} = echo x)
|
pool.spawn(i, proc (x: int) {.thread.} = echo x)
|
||||||
pool.join()
|
pool.join()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ type
|
||||||
|
|
||||||
const
|
const
|
||||||
DefaultPrec = 6 ## Default precision for floating point numbers.
|
DefaultPrec = 6 ## Default precision for floating point numbers.
|
||||||
DefaultFmt: Format = (ftDefault, -1, -1, nil, faDefault, fsMinus, false, false, false, nil)
|
DefaultFmt: Format = (ftDefault, -1, -1, "", faDefault, fsMinus, false, false, false, "")
|
||||||
## Default format corresponding to the empty format string, i.e.
|
## Default format corresponding to the empty format string, i.e.
|
||||||
## `x.format("") == x.format(DefaultFmt)`.
|
## `x.format("") == x.format(DefaultFmt)`.
|
||||||
round_nums = [0.5, 0.05, 0.005, 0.0005, 0.00005, 0.000005, 0.0000005, 0.00000005]
|
round_nums = [0.5, 0.05, 0.005, 0.0005, 0.00005, 0.000005, 0.0000005, 0.00000005]
|
||||||
|
|
@ -124,7 +124,7 @@ proc parse(fmt: string): Format {.nosideeffect.} =
|
||||||
if fmt.rawmatch(p, 0, caps) < 0:
|
if fmt.rawmatch(p, 0, caps) < 0:
|
||||||
raise newException(FormatError, "Invalid format string")
|
raise newException(FormatError, "Invalid format string")
|
||||||
|
|
||||||
result.fill = fmt.get(caps, 0, nil)
|
result.fill = fmt.get(caps, 0, "")
|
||||||
|
|
||||||
case fmt.get(caps, 1, 0.char)
|
case fmt.get(caps, 1, 0.char)
|
||||||
of '<': result.align = faLeft
|
of '<': result.align = faLeft
|
||||||
|
|
@ -144,7 +144,7 @@ proc parse(fmt: string): Format {.nosideeffect.} =
|
||||||
result.width = fmt.get(caps, 4, -1)
|
result.width = fmt.get(caps, 4, -1)
|
||||||
|
|
||||||
if caps.has(4) and fmt[caps.bounds(4).first] == '0':
|
if caps.has(4) and fmt[caps.bounds(4).first] == '0':
|
||||||
if result.fill != nil:
|
if result.fill != "":
|
||||||
raise newException(FormatError, "Leading 0 in with not allowed with explicit fill character")
|
raise newException(FormatError, "Leading 0 in with not allowed with explicit fill character")
|
||||||
if result.align != faDefault:
|
if result.align != faDefault:
|
||||||
raise newException(FormatError, "Leading 0 in with not allowed with explicit alignment")
|
raise newException(FormatError, "Leading 0 in with not allowed with explicit alignment")
|
||||||
|
|
@ -171,7 +171,7 @@ proc parse(fmt: string): Format {.nosideeffect.} =
|
||||||
of '%': result.typ = ftPercent
|
of '%': result.typ = ftPercent
|
||||||
else: result.typ = ftDefault
|
else: result.typ = ftDefault
|
||||||
|
|
||||||
result.arysep = fmt.get(caps, 8, nil, 1)
|
result.arysep = fmt.get(caps, 8, "", 1)
|
||||||
|
|
||||||
proc getalign(fmt: Format; defalign: FmtAlign; slen: int) : tuple[left, right:int] {.nosideeffect.} =
|
proc getalign(fmt: Format; defalign: FmtAlign; slen: int) : tuple[left, right:int] {.nosideeffect.} =
|
||||||
## Returns the number of left and right padding characters for a
|
## Returns the number of left and right padding characters for a
|
||||||
|
|
@ -218,7 +218,7 @@ proc writefill(o: var Writer; fmt: Format; n: int; signum: int = 0) =
|
||||||
elif fmt.sign == fsPlus: write(o, '+')
|
elif fmt.sign == fsPlus: write(o, '+')
|
||||||
elif fmt.sign == fsSpace: write(o, ' ')
|
elif fmt.sign == fsSpace: write(o, ' ')
|
||||||
|
|
||||||
if fmt.fill == nil:
|
if fmt.fill.len == 0:
|
||||||
for i in 1..n: write(o, ' ')
|
for i in 1..n: write(o, ' ')
|
||||||
else:
|
else:
|
||||||
for i in 1..n:
|
for i in 1..n:
|
||||||
|
|
@ -626,19 +626,19 @@ proc splitfmt(s: string): seq[Part] {.compiletime, nosideeffect.} =
|
||||||
else:
|
else:
|
||||||
lvl.dec
|
lvl.dec
|
||||||
let clpos = pos
|
let clpos = pos
|
||||||
var fmtpart = Part(kind: pkFmt, arg: -1, fmt: s.substr(oppos+1, clpos-1), field: nil, index: int.high, nested: nested)
|
var fmtpart = Part(kind: pkFmt, arg: -1, fmt: s.substr(oppos+1, clpos-1), field: "", index: int.high, nested: nested)
|
||||||
if fmtpart.fmt.len > 0:
|
if fmtpart.fmt.len > 0:
|
||||||
var m: array[0..3, string]
|
var m: array[0..3, string]
|
||||||
if not fmtpart.fmt.match(subpeg, m):
|
if not fmtpart.fmt.match(subpeg, m):
|
||||||
error("invalid format string")
|
error("invalid format string")
|
||||||
|
|
||||||
if m[1] != nil and m[1].len > 0:
|
if m[1].len > 0:
|
||||||
fmtpart.field = m[1].substr(1)
|
fmtpart.field = m[1].substr(1)
|
||||||
if m[2] != nil and m[2].len > 0:
|
if m[2].len > 0:
|
||||||
discard parseInt(m[2].substr(1, m[2].len-2), fmtpart.index)
|
discard parseInt(m[2].substr(1, m[2].len-2), fmtpart.index)
|
||||||
|
|
||||||
if m[0].len > 0: discard parseInt(m[0], fmtpart.arg)
|
if m[0].len > 0: discard parseInt(m[0], fmtpart.arg)
|
||||||
if m[3] == nil or m[3].len == 0:
|
if m[3].len == 0:
|
||||||
fmtpart.fmt = ""
|
fmtpart.fmt = ""
|
||||||
elif m[3][0] == ':':
|
elif m[3][0] == ':':
|
||||||
fmtpart.fmt = m[3].substr(1)
|
fmtpart.fmt = m[3].substr(1)
|
||||||
|
|
@ -650,7 +650,7 @@ proc splitfmt(s: string): seq[Part] {.compiletime, nosideeffect.} =
|
||||||
proc literal(s: string): NimNode {.compiletime, nosideeffect.} =
|
proc literal(s: string): NimNode {.compiletime, nosideeffect.} =
|
||||||
## Return the nim literal of string `s`. This handles the case if
|
## Return the nim literal of string `s`. This handles the case if
|
||||||
## `s` is nil.
|
## `s` is nil.
|
||||||
result = if s == nil: newNilLit() else: newLit(s)
|
result = newLit(s)
|
||||||
|
|
||||||
proc literal(b: bool): NimNode {.compiletime, nosideeffect.} =
|
proc literal(b: bool): NimNode {.compiletime, nosideeffect.} =
|
||||||
## Return the nim literal of boolean `b`. This is either `true`
|
## Return the nim literal of boolean `b`. This is either `true`
|
||||||
|
|
@ -713,7 +713,7 @@ proc generatefmt(fmtstr: string;
|
||||||
args[arg].cnt = args[arg].cnt + 1
|
args[arg].cnt = args[arg].cnt + 1
|
||||||
arg.inc
|
arg.inc
|
||||||
# possible field access
|
# possible field access
|
||||||
if part.field != nil and part.field.len > 0:
|
if part.field.len > 0:
|
||||||
argexpr = newDotExpr(argexpr, part.field.ident)
|
argexpr = newDotExpr(argexpr, part.field.ident)
|
||||||
# possible array access
|
# possible array access
|
||||||
if part.index < int.high:
|
if part.index < int.high:
|
||||||
|
|
@ -724,7 +724,7 @@ proc generatefmt(fmtstr: string;
|
||||||
# nested format string. Compute the format string by
|
# nested format string. Compute the format string by
|
||||||
# concatenating the parts of the substring.
|
# concatenating the parts of the substring.
|
||||||
for e in generatefmt(part.fmt, args, arg):
|
for e in generatefmt(part.fmt, args, arg):
|
||||||
var newexpr = if part.fmt == nil: e.val else: newCall(bindsym"format", e.val, e.fmt)
|
var newexpr = if part.fmt.len == 0: e.val else: newCall(bindsym"format", e.val, e.fmt)
|
||||||
if fmtexpr != nil and fmtexpr.kind != nnkNilLit:
|
if fmtexpr != nil and fmtexpr.kind != nnkNilLit:
|
||||||
fmtexpr = infix(fmtexpr, "&", newexpr)
|
fmtexpr = infix(fmtexpr, "&", newexpr)
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@ discard """
|
||||||
@[1, 2, 3]'''
|
@[1, 2, 3]'''
|
||||||
"""
|
"""
|
||||||
|
|
||||||
template foo(s: string = nil) =
|
template foo(s: string = "") =
|
||||||
if isNil(s):
|
if s.len == 0:
|
||||||
echo "it's nil"
|
echo "it's nil"
|
||||||
else:
|
else:
|
||||||
echo s
|
echo s
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ when true:
|
||||||
import os
|
import os
|
||||||
|
|
||||||
type
|
type
|
||||||
In_out = tuple[src, dest, options: string]
|
In_out = tuple[src, dest: string, options: ref int]
|
||||||
|
|
||||||
let
|
let
|
||||||
nil_var: In_out = ("hey"/"there", "something", nil)
|
nil_var: In_out = ("hey"/"there", "something", nil)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue