Merge branch 'devel' into feature/async-streams

This commit is contained in:
Araq 2017-02-25 11:18:48 +01:00
commit 1961e444c3
115 changed files with 2208 additions and 877 deletions

View file

@ -0,0 +1,26 @@
discard """
output: '''false'''
"""
# bug #5402
import lists
type
Container[T] = ref object
obj: T
ListOfContainers[T] = ref object
list: DoublyLinkedList[Container[T]]
proc contains[T](this: ListOfContainers[T], obj: T): bool =
for item in this.list.items():
if item.obj == obj: return true
return false
proc newListOfContainers[T](): ListOfContainers[T] =
new(result)
result.list = initDoublyLinkedList[Container[T]]()
let q = newListOfContainers[int64]()
echo q.contains(123)

View file

@ -0,0 +1,16 @@
discard """
"""
# bug #5404
import parseopt2
{.emit: """typedef struct {
int key;
} foo;""".}
type foo* {.importc: "foo", nodecl.} = object
key* {.importc: "key".}: cint
for kind, key, value in parseopt2.getopt():
discard

View file

@ -0,0 +1,23 @@
discard """
outputsub: '''tproper_stacktrace3.nim(21) main'''
exitcode: 1
"""
# bug #5400
type Container = object
val: int
proc actualResolver(x: ptr Container): ptr Container = x
template resolve(): untyped = actualResolver(db)
proc myfail(): int =
doAssert false
proc main() =
var db: ptr Container = nil
# actualResolver(db).val = myfail() # actualResolver is not included in stack trace.
resolve().val = myfail() # resolve template is included in stack trace.
main()

88
tests/gc/foreign_thr.nim Normal file
View file

@ -0,0 +1,88 @@
discard """
output: '''
Hello from thread
Hello from thread
Hello from thread
Hello from thread
'''
cmd: "nim $target --hints:on --threads:on --tlsEmulation:off $options $file"
"""
# Copied from stdlib
import strutils
const
StackGuardSize = 4096
ThreadStackMask = 1024*256*sizeof(int)-1
ThreadStackSize = ThreadStackMask+1 - StackGuardSize
type ThreadFunc = proc() {.thread.}
when defined(posix):
import posix
proc runInForeignThread(f: ThreadFunc) =
proc wrapper(p: pointer): pointer {.noconv.} =
let thr = cast[ThreadFunc](p)
setupForeignThreadGc()
thr()
tearDownForeignThreadGc()
setupForeignThreadGc()
thr()
tearDownForeignThreadGc()
result = nil
var attrs {.noinit.}: PthreadAttr
doAssert pthread_attr_init(addr attrs) == 0
doAssert pthread_attr_setstacksize(addr attrs, ThreadStackSize) == 0
var tid: Pthread
doAssert pthread_create(addr tid, addr attrs, wrapper, f) == 0
doAssert pthread_join(tid, nil) == 0
elif defined(windows):
import winlean
type
WinThreadProc = proc (x: pointer): int32 {.stdcall.}
proc createThread(lpThreadAttributes: pointer, dwStackSize: DWORD,
lpStartAddress: WinThreadProc,
lpParameter: pointer,
dwCreationFlags: DWORD,
lpThreadId: var DWORD): Handle {.
stdcall, dynlib: "kernel32", importc: "CreateThread".}
proc wrapper(p: pointer): int32 {.stdcall.} =
let thr = cast[ThreadFunc](p)
setupForeignThreadGc()
thr()
tearDownForeignThreadGc()
setupForeignThreadGc()
thr()
tearDownForeignThreadGc()
result = 0'i32
proc runInForeignThread(f: ThreadFunc) =
var dummyThreadId: DWORD
var h = createThread(nil, ThreadStackSize.int32, wrapper.WinThreadProc, cast[pointer](f), 0, dummyThreadId)
doAssert h != 0.Handle
doAssert waitForSingleObject(h, -1'i32) == 0.DWORD
else:
{.fatal: "Unknown system".}
proc runInNativeThread(f: ThreadFunc) =
proc wrapper(f: ThreadFunc) {.thread.} =
# These operations must be NOP
setupForeignThreadGc()
tearDownForeignThreadGc()
f()
f()
var thr: Thread[ThreadFunc]
createThread(thr, wrapper, f)
joinThread(thr)
proc f {.thread.} =
var msg = "Hello " & "from thread"
echo msg
runInForeignThread(f)
runInNativeThread(f)

View file

@ -0,0 +1,17 @@
type
Test = object
x: int
case p: bool
of true:
a: int
else:
case q: bool
of true:
b: int
else:
discard
proc f[T](t: typedesc[T]): int =
1
assert Test.f == 1

View file

@ -1,15 +1,24 @@
discard """
output: "wof!"
output: '''wof!
wof!'''
"""
# bug #1659
type Animal = ref object {.inheritable.}
type Dog = ref object of Animal
method say(a: Animal): auto = "wat!"
method say(a: Animal): auto {.base.} = "wat!"
method say(a: Dog): auto = "wof!"
proc saySomething(a: Animal): auto = a.say()
method ec(a: Animal): auto {.base.} = echo "wat!"
method ec(a: Dog): auto = echo "wof!"
proc ech(a: Animal): auto = a.ec()
var a = Dog()
echo saySomething(a)
ech a

View file

@ -29,10 +29,10 @@ method runInput[T, O](self: Parser[T, O], inp: Input[T]): Result[T, O] =
# XXX: above needed for now, as without the `tmp` bit below, it compiles to invalid C.
tmp(self)(inp)
method run*[T, O](self: Parser[T, O], toks: seq[T]): Result[T, O] =
proc run*[T, O](self: Parser[T, O], toks: seq[T]): Result[T, O] =
self.runInput(Input[T](toks: toks, index: 0))
method chain*[T, O1, O2](self: Parser[T, O1], nextp: proc (v: O1): Parser[T, O2]): Parser[T, O2] =
proc chain*[T, O1, O2](self: Parser[T, O1], nextp: proc (v: O1): Parser[T, O2]): Parser[T, O2] =
result = proc (inp: Input[T]): Result[T, O2] =
let r = self.runInput(inp)
case r.kind:
@ -41,7 +41,7 @@ method chain*[T, O1, O2](self: Parser[T, O1], nextp: proc (v: O1): Parser[T, O2]
of rkFailure:
Result[T, O2](kind: rkFailure)
method skip[T](self: Input[T], n: int): Input[T] =
method skip[T](self: Input[T], n: int): Input[T] {.base.} =
Input[T](toks: self.toks, index: self.index + n)
proc pskip*[T](n: int): Parser[T, tuple[]] =
@ -69,11 +69,11 @@ proc `+`*[T, O](first: Parser[T, O], second: Parser[T, O]): Parser[T, O] =
# end of primitives (definitions involving Parser(..))
method map*[T, O1, O2](self: Parser[T, O1], p: proc (v: O1): O2): Parser[T, O2] =
proc map*[T, O1, O2](self: Parser[T, O1], p: proc (v: O1): O2): Parser[T, O2] =
self.chain(proc (v: O1): Parser[T, O2] =
unit[T, O2](p(v)))
method then*[T, O1, O2](self: Parser[T, O1], next: Parser[T, O2]): Parser[T, O2] =
proc then*[T, O1, O2](self: Parser[T, O1], next: Parser[T, O2]): Parser[T, O2] =
self.chain(proc (v: O1): Parser[T, O2] =
next)

View file

@ -1,3 +0,0 @@
import strutils
let x = stdin.readLine()
echo x.parseInt + 5

5
tests/osproc/ta_in.nim Normal file
View file

@ -0,0 +1,5 @@
# This file is prefixed with an "a", because other tests
# depend on it and it must be compiled first.
import strutils
let x = stdin.readLine()
echo x.parseInt + 5

16
tests/osproc/ta_out.nim Normal file
View file

@ -0,0 +1,16 @@
# This file is prefixed with an "a", because other tests
# depend on it and it must be compiled first.
stdout.writeLine("to stdout")
stdout.flushFile()
stdout.writeLine("to stdout")
stdout.flushFile()
stderr.writeLine("to stderr")
stderr.flushFile()
stderr.writeLine("to stderr")
stderr.flushFile()
stdout.writeLine("to stdout")
stdout.flushFile()
stdout.writeLine("to stdout")
stdout.flushFile()

View file

@ -4,7 +4,7 @@ discard """
"""
import osproc, os, streams
const filename = when defined(Windows): "ta.exe" else: "ta"
const filename = when defined(Windows): "ta_in.exe" else: "ta_in"
doAssert fileExists(getCurrentDir() / "tests" / "osproc" / filename)

29
tests/osproc/tstdout.nim Normal file
View file

@ -0,0 +1,29 @@
discard """
output: '''--------------------------------------
to stdout
to stdout
to stderr
to stderr
to stdout
to stdout
--------------------------------------
'''
"""
import osproc, os, streams
const filename = when defined(Windows): "ta_out.exe" else: "ta_out"
doAssert fileExists(getCurrentDir() / "tests" / "osproc" / filename)
var p = startProcess(filename, getCurrentDir() / "tests" / "osproc",
options={poStdErrToStdOut})
let outputStream = p.outputStream
var x = newStringOfCap(120)
var output = ""
while outputStream.readLine(x.TaintedString):
output.add(x & "\n")
echo "--------------------------------------"
stdout.write output
echo "--------------------------------------"

View file

@ -19,7 +19,7 @@ when true:
q(B()) # This call reported as ambiguous.
# bug #2219
template testPred(a: expr) =
template testPred(a: untyped) =
block:
type A = object of RootObj
type B = object of A

13
tests/pragmas/tlocks.nim Normal file
View file

@ -0,0 +1,13 @@
type SomeBase* = ref object of RootObj
type SomeDerived* = ref object of SomeBase
memberProc*: proc ()
method testMethod(g: SomeBase) {.base, locks: "unknown".} = discard
method testMethod(g: SomeDerived) =
if g.memberProc != nil:
g.memberProc()
# ensure int literals still work
proc plain*() {.locks: 0.} =
discard

13
tests/pragmas/tused.nim Normal file
View file

@ -0,0 +1,13 @@
discard """
output: '''8'''
"""
template implementArithOps(T) =
proc echoAdd(a, b: T) {.used.} =
echo a + b
proc echoSub(a, b: T) {.used.} =
echo a - b
# no warning produced for the unused 'echoSub'
implementArithOps(int)
echoAdd 3, 5

11
tests/stdlib/tbug5382.nim Normal file
View file

@ -0,0 +1,11 @@
discard """
output: '''
02
'''
"""
import re
let regexp = re"^\/([0-9]{2})\.html$"
var matches: array[1, string]
discard "/02.html".find(regexp, matches)
echo matches[0]

View file

@ -0,0 +1,14 @@
template makeDomElement(x: untyped, name: string = nil) =
const tag {.gensym.} = if name == nil: astToStr(x) else: name
proc x*(p: int|float) =
echo tag, p
proc x*(p: string|cstring) =
echo tag, p
#proc wrappedUp[T](x: T) =
# mixin foo, bar
makeDomElement(foo, "foo")
makeDomElement(bar)

View file

@ -0,0 +1,14 @@
discard """
output: '''foo55
foo8.0
fooaha
bar7'''
"""
# bug #5419
import mgensym_generic_cross_module
foo(55)
foo 8.0
foo "aha"
bar 7

View file

@ -0,0 +1,18 @@
# bug #5417
import macros
macro genBody: untyped =
let sbx = genSym(nskLabel, "test")
when true:
result = quote do:
block `sbx`:
break `sbx`
else:
template foo(s1, s2) =
block s1:
break s2
result = getAst foo(sbx, sbx)
proc test() =
genBody()

View file

@ -1,3 +1,10 @@
discard """
output: '''[0.0, 0.0, 0.0]
[0.0, 0.0, 0.0, 0.0]
5050'''
"""
template mathPerComponent(op: untyped): untyped =
proc op*[N,T](v,u: array[N,T]): array[N,T] {.inline.} =
@ -19,3 +26,24 @@ proc foo(): void =
echo repr(v1 *** v2)
foo()
# bug #5383
import sequtils
proc zipWithIndex[A](ts: seq[A]): seq[(int, A)] =
toSeq(pairs(ts))
proc main =
discard zipWithIndex(@["foo", "bar"])
discard zipWithIndex(@[1, 2])
discard zipWithIndex(@[true, false])
main()
# bug #5405
proc main2() =
let s = toSeq(1..100).foldL(a + b)
echo s
main2()

View file

@ -5,8 +5,8 @@ import macros
# Test that parameters are properly gensym'ed finally:
template genNodeKind(kind, name: expr): stmt =
proc name*(children: varargs[PNimrodNode]): PNimrodNode {.compiletime.}=
template genNodeKind(kind, name: untyped) =
proc name*(children: varargs[NimNode]): NimNode {.compiletime.}=
result = newNimNode(kind)
for c in children:
result.add(c)
@ -22,7 +22,7 @@ type Something = object
proc testA(x: Something) = discard
template def(name: expr) {.immediate.} =
template def(name: untyped) =
proc testB[T](reallyUniqueName: T) =
`test name`(reallyUniqueName)
def A
@ -35,8 +35,7 @@ testB(x)
# Test that templates in generics still work (regression to fix the
# regression...)
template forStatic(index: expr, slice: Slice[int], predicate: stmt):
stmt {.immediate.} =
template forStatic(index, slice, predicate: untyped) =
const a = slice.a
const b = slice.b
when a <= b:

View file

@ -147,6 +147,7 @@ proc gcTests(r: var TResults, cat: Category, options: string) =
testSpec r, makeTest("tests/gc" / filename, options &
" -d:release --gc:boehm", cat, actionRun)
testWithoutBoehm "foreign_thr"
test "gcemscripten"
test "growobjcrash"
test "gcbench"

View file

@ -76,7 +76,236 @@ for i in 1..10:
echo(name)
discard db.getRow(
SqlQuery("INSERT INTO tags(name) VALUES(\'$1\') RETURNING id" % [name]))
# get column details
db.exec(SqlQuery("DROP TABLE IF EXISTS dbtypes;"))
db.exec(SqlQuery("DROP TYPE IF EXISTS custom_enum;"))
db.exec(SqlQuery("CREATE TYPE custom_enum AS ENUM ('1', '2', '3');"))
db.exec(SqlQuery("DROP TYPE IF EXISTS custom_composite;"))
db.exec(SqlQuery("CREATE TYPE custom_composite AS (r double precision, i double precision);"))
db.exec(SqlQuery("""CREATE TABLE dbtypes(
id serial UNIQUE,
bytea_col bytea,
smallint_col smallint,
integer_col integer,
bigint_col bigint,
decimal_col decimal,
numeric_col numeric,
real_col real,
double_precision_col double precision,
smallserial_col smallserial,
serial_col serial,
bigserial_col bigserial,
money_col money,
varchar_col varchar(10),
character_col character(1),
text_col text,
timestamp_col timestamp,
date_col date,
time_col time,
interval_col interval,
bool_col boolean,
custom_enum_col custom_enum,
point_col point,
line_col line,
lseg_col lseg,
box_col box,
path_col path,
polygon_col polygon,
circle_col circle,
cidr_col cidr,
inet_col inet,
macaddr_col macaddr,
bit_col bit,
varbit_col bit(3),
tsvector_col tsvector,
tsquery_col tsquery,
uuid_col uuid,
xml_col xml,
json_col json,
array_col integer[],
custom_composite_col custom_composite,
range_col int4range
);"""))
db.exec(SqlQuery("INSERT INTO dbtypes (id) VALUES(0);"))
var dbCols : DbColumns = @[]
for row in db.instantRows(dbCols, sql"SELECT * FROM dbtypes"):
doAssert len(dbCols) == 42
doAssert dbCols[0].name == "id"
doAssert dbCols[0].typ.kind == DbTypeKind.dbInt
doAssert dbCols[0].typ.name == "int4"
doAssert dbCols[0].typ.size == 4
doAssert dbCols[1].name == "bytea_col"
doAssert dbCols[1].typ.kind == DbTypeKind.dbBlob
doAssert dbCols[1].typ.name == "bytea"
doAssert dbCols[2].name == "smallint_col"
doAssert dbCols[2].typ.kind == DbTypeKind.dbInt
doAssert dbCols[2].typ.name == "int2"
doAssert dbCols[2].typ.size == 2
doAssert dbCols[3].name == "integer_col"
doAssert dbCols[3].typ.kind == DbTypeKind.dbInt
doAssert dbCols[3].typ.name == "int4"
doAssert dbCols[3].typ.size == 4
doAssert dbCols[4].name == "bigint_col"
doAssert dbCols[4].typ.kind == DbTypeKind.dbInt
doAssert dbCols[4].typ.name == "int8"
doAssert dbCols[4].typ.size == 8
doAssert dbCols[5].name == "decimal_col"
doAssert dbCols[5].typ.kind == DbTypeKind.dbDecimal
doAssert dbCols[5].typ.name == "numeric"
doAssert dbCols[6].name == "numeric_col"
doAssert dbCols[6].typ.kind == DbTypeKind.dbDecimal
doAssert dbCols[6].typ.name == "numeric"
doAssert dbCols[7].name == "real_col"
doAssert dbCols[7].typ.kind == DbTypeKind.dbFloat
doAssert dbCols[7].typ.name == "float4"
doAssert dbCols[8].name == "double_precision_col"
doAssert dbCols[8].typ.kind == DbTypeKind.dbFloat
doAssert dbCols[8].typ.name == "float8"
doAssert dbCols[9].name == "smallserial_col"
doAssert dbCols[9].typ.kind == DbTypeKind.dbInt
doAssert dbCols[9].typ.name == "int2"
doAssert dbCols[10].name == "serial_col"
doAssert dbCols[10].typ.kind == DbTypeKind.dbInt
doAssert dbCols[10].typ.name == "int4"
doAssert dbCols[11].name == "bigserial_col"
doAssert dbCols[11].typ.kind == DbTypeKind.dbInt
doAssert dbCols[11].typ.name == "int8"
doAssert dbCols[12].name == "money_col"
doAssert dbCols[12].typ.kind == DbTypeKind.dbDecimal
doAssert dbCols[12].typ.name == "money"
doAssert dbCols[13].name == "varchar_col"
doAssert dbCols[13].typ.kind == DbTypeKind.dbVarchar
doAssert dbCols[13].typ.name == "varchar"
doAssert dbCols[14].name == "character_col"
doAssert dbCols[14].typ.kind == DbTypeKind.dbFixedChar
doAssert dbCols[14].typ.name == "bpchar"
doAssert dbCols[15].name == "text_col"
doAssert dbCols[15].typ.kind == DbTypeKind.dbVarchar
doAssert dbCols[15].typ.name == "text"
doAssert dbCols[16].name == "timestamp_col"
doAssert dbCols[16].typ.kind == DbTypeKind.dbTimestamp
doAssert dbCols[16].typ.name == "timestamp"
doAssert dbCols[17].name == "date_col"
doAssert dbCols[17].typ.kind == DbTypeKind.dbDate
doAssert dbCols[17].typ.name == "date"
doAssert dbCols[18].name == "time_col"
doAssert dbCols[18].typ.kind == DbTypeKind.dbTime
doAssert dbCols[18].typ.name == "time"
doAssert dbCols[19].name == "interval_col"
doAssert dbCols[19].typ.kind == DbTypeKind.dbTimeInterval
doAssert dbCols[19].typ.name == "interval"
doAssert dbCols[20].name == "bool_col"
doAssert dbCols[20].typ.kind == DbTypeKind.dbBool
doAssert dbCols[20].typ.name == "bool"
doAssert dbCols[21].name == "custom_enum_col"
doAssert dbCols[21].typ.kind == DbTypeKind.dbUnknown
doAssert parseInt(dbCols[21].typ.name) > 0
doAssert dbCols[22].name == "point_col"
doAssert dbCols[22].typ.kind == DbTypeKind.dbPoint
doAssert dbCols[22].typ.name == "point"
doAssert dbCols[23].name == "line_col"
doAssert dbCols[23].typ.kind == DbTypeKind.dbLine
doAssert dbCols[23].typ.name == "line"
doAssert dbCols[24].name == "lseg_col"
doAssert dbCols[24].typ.kind == DbTypeKind.dbLseg
doAssert dbCols[24].typ.name == "lseg"
doAssert dbCols[25].name == "box_col"
doAssert dbCols[25].typ.kind == DbTypeKind.dbBox
doAssert dbCols[25].typ.name == "box"
doAssert dbCols[26].name == "path_col"
doAssert dbCols[26].typ.kind == DbTypeKind.dbPath
doAssert dbCols[26].typ.name == "path"
doAssert dbCols[27].name == "polygon_col"
doAssert dbCols[27].typ.kind == DbTypeKind.dbPolygon
doAssert dbCols[27].typ.name == "polygon"
doAssert dbCols[28].name == "circle_col"
doAssert dbCols[28].typ.kind == DbTypeKind.dbCircle
doAssert dbCols[28].typ.name == "circle"
doAssert dbCols[29].name == "cidr_col"
doAssert dbCols[29].typ.kind == DbTypeKind.dbInet
doAssert dbCols[29].typ.name == "cidr"
doAssert dbCols[30].name == "inet_col"
doAssert dbCols[30].typ.kind == DbTypeKind.dbInet
doAssert dbCols[30].typ.name == "inet"
doAssert dbCols[31].name == "macaddr_col"
doAssert dbCols[31].typ.kind == DbTypeKind.dbMacAddress
doAssert dbCols[31].typ.name == "macaddr"
doAssert dbCols[32].name == "bit_col"
doAssert dbCols[32].typ.kind == DbTypeKind.dbBit
doAssert dbCols[32].typ.name == "bit"
doAssert dbCols[33].name == "varbit_col"
doAssert dbCols[33].typ.kind == DbTypeKind.dbBit
doAssert dbCols[33].typ.name == "bit"
doAssert dbCols[34].name == "tsvector_col"
doAssert dbCols[34].typ.kind == DbTypeKind.dbVarchar
doAssert dbCols[34].typ.name == "tsvector"
doAssert dbCols[35].name == "tsquery_col"
doAssert dbCols[35].typ.kind == DbTypeKind.dbVarchar
doAssert dbCols[35].typ.name == "tsquery"
doAssert dbCols[36].name == "uuid_col"
doAssert dbCols[36].typ.kind == DbTypeKind.dbVarchar
doAssert dbCols[36].typ.name == "uuid"
doAssert dbCols[37].name == "xml_col"
doAssert dbCols[37].typ.kind == DbTypeKind.dbXml
doAssert dbCols[37].typ.name == "xml"
doAssert dbCols[38].name == "json_col"
doAssert dbCols[38].typ.kind == DbTypeKind.dbJson
doAssert dbCols[38].typ.name == "json"
doAssert dbCols[39].name == "array_col"
doAssert dbCols[39].typ.kind == DbTypeKind.dbArray
doAssert dbCols[39].typ.name == "int4[]"
doAssert dbCols[40].name == "custom_composite_col"
doAssert dbCols[40].typ.kind == DbTypeKind.dbUnknown
doAssert parseInt(dbCols[40].typ.name) > 0
doAssert dbCols[41].name == "range_col"
doAssert dbCols[41].typ.kind == DbTypeKind.dbComposite
doAssert dbCols[41].typ.name == "int4range"
echo("All tests succeeded!")
db.close()