faster CIs (#13803)

* ttables: smaller table, 5x speedup

* thavlak: less iterations, less loops; 30% speedup

* tasyncclosestall: shorter timeout; 35% speedup

* gcleak4: less iterations, 2x speedup

* ttimes: remove deprecated stuff

* tdangerisrelease: remove cpp backend, 3x speedup

* tfrexp1: smaller range, 2x speedup

* trtree: fix warnings, less iterations, 6x speedup

* tasyncawait_cyclebreaker: smaller swarm size; 2x speedup

* trealloc: smaller number of iterations; 10x speedup

* towned_binary_tree: less iterations, 4x speedup

* tclosure: remove unused code, less iterations; 2x speedup

* twaitany: less durations; 1.4x speedup

* tasync_misc: less iterations, 2x speedup

* t8535: smaller sleep, 1.5x speedup

* tmanyjoin: smaller sleep, 2x speedup

* t12221: shorter sleeps, removed two slower tests; 1.6x speedup

* tfuturestream: smaller sleep; 1.5x speedup

* growobjcrash: less iterations; 2x speedup

* ttryrecv: smaller sleep; 1.5x speedup

* treusetvar: less threads; 2x speedup

* delete tthreadanalysis2, basically a duplicate of tthreadanalysis

* t7758: less iterations, 1.5x speedup

* tasyncawait: smaller swarm, less messages; 1.5x speedup

* tjsandnativeasync: smaller sleep, 1.5x speedup

* tpendingcheck: smaller sleep, 1.5x speedup

* remove rodfiles test category

* move tseq from its own category to 'collections' category

* remove unneeded tests and helpers from 'assert' category

* stdlib: merge tbitops2 into tbitops

* remove 'trepr2' from 'stdlib' cat

* merge 'tstreams' into one file

* remove 'tinefficient_const_table' from 'ccbugs' cat

* merge 'tcollections_to_string' into 'tcollections'

* tblocking_channel: smaller sleep, small speedup

* tconvexhull: less iterartions; 1.2x speedup

* merge 'tdeepcopy2' into 'tdeepcopy'

* merge 'tdisjoint_slice2' into 'tdisjoint_slice1'

* tmissing_deepcopy: smaller sequence

* tsendtwice: smaller arrays; 5x speedup

* remove 'tindexerrorformatbounds'

* disable multimethod tests

* remove 'gc:none' and 'refc' without 'd:useRealtimeGC' from gc tests

* koch.nim: bootstrap just with '-d:release', no need for 'csource'

* add github workflow for documentation

* testament: no need for 8 sub-second decimals
This commit is contained in:
Miran 2020-03-30 13:18:12 +02:00 • committed by GitHub
commit 8088633250
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
72 changed files with 532 additions and 1082 deletions

45
.github/workflows/ci_docs.yml vendored Normal file
View file

@ -0,0 +1,45 @@
name: Nim Docs CI
on:
pull_request:
# Run only on changes on these files
paths:
- 'lib/*.nim'
- 'doc/*.rst'
jobs:
build:
name: 'Docs builder'
runs-on: ubuntu-18.04
steps:
- name: 'Checkout'
uses: actions/checkout@v2
- name: 'Checkout csources'
uses: actions/checkout@v2
with:
repository: nim-lang/csources
path: csources
- name: 'Add build binaries to PATH'
shell: bash
run: echo "::add-path::${{ github.workspace }}/bin"
- name: 'Build 1-stage compiler from csources'
shell: bash
run: |
ncpu=$(nproc)
[[ -z "$ncpu" || $ncpu -le 0 ]] && ncpu=1
make -C csources -j $ncpu CC=gcc ucpu='amd64'
- name: 'Build koch'
shell: bash
run: nim c koch
- name: 'Build the real compiler'
shell: bash
run: ./koch boot
- name: 'Build documentation'
shell: bash
run: ./koch doc

View file

@ -481,10 +481,6 @@ proc runCI(cmd: string) =
doAssert cmd.len == 0, cmd # avoid silently ignoring
echo "runCI: ", cmd
echo hostInfo()
# note(@araq): Do not replace these commands with direct calls (eg boot())
# as that would weaken our testing efforts.
when defined(posix): # appveyor (on windows) didn't run this
kochExecFold("Boot", "boot")
# boot without -d:nimHasLibFFI to make sure this still works
kochExecFold("Boot in release mode", "boot -d:release")
@ -494,7 +490,7 @@ proc runCI(cmd: string) =
if getEnv("NIM_TEST_PACKAGES", "false") == "true":
execFold("Test selected Nimble packages", "nim c -r testament/testament cat nimble-packages")
else:
buildTools() # altenatively, kochExec "tools --toolsNoNimble"
buildTools()
## run tests
execFold("Test nimscript", "nim e tests/test_nimscript.nims")
@ -504,7 +500,7 @@ proc runCI(cmd: string) =
# main bottleneck here
execFold("Run tester", "nim c -r -d:nimCoroutines testament/testament --pedantic all -d:nimCoroutines")
block: # CT FFI
block CT_FFI:
when defined(posix): # windows can be handled in future PR's
execFold("nimble install -y libffi", "nimble install -y libffi")
const nimFFI = "./bin/nim.ctffi"
@ -517,15 +513,6 @@ proc runCI(cmd: string) =
when defined(posix):
execFold("Run nimsuggest tests", "nim c -r nimsuggest/tester")
## remaining actions
when defined(posix):
kochExecFold("Docs", "docs --git.commit:devel")
kochExecFold("C sources", "csource")
elif defined(windows):
when false:
kochExec "csource"
kochExec "zip"
proc pushCsources() =
if not dirExists("../csources/.git"):
quit "[Error] no csources git repository found"

View file

@ -169,16 +169,8 @@ proc dllTests(r: var TResults, cat: Category, options: string) =
# ------------------------------ GC tests -------------------------------------
proc gcTests(r: var TResults, cat: Category, options: string) =
template testWithNone(filename: untyped) =
testSpec r, makeTest("tests/gc" / filename, options &
" --gc:none", cat)
testSpec r, makeTest("tests/gc" / filename, options &
" -d:release --gc:none", cat)
template testWithoutMs(filename: untyped) =
testSpec r, makeTest("tests/gc" / filename, options, cat)
testSpec r, makeTest("tests/gc" / filename, options &
" -d:release", cat)
testSpec r, makeTest("tests/gc" / filename, options &
" -d:release -d:useRealtimeGC", cat)
when filename != "gctest":
@ -193,6 +185,7 @@ proc gcTests(r: var TResults, cat: Category, options: string) =
" --gc:markAndSweep", cat)
testSpec r, makeTest("tests/gc" / filename, options &
" -d:release --gc:markAndSweep", cat)
template test(filename: untyped) =
testWithoutBoehm filename
when not defined(windows) and not defined(android):
@ -210,7 +203,6 @@ proc gcTests(r: var TResults, cat: Category, options: string) =
test "gcleak"
test "gcleak2"
testWithoutBoehm "gctest"
testWithNone "gctest"
test "gcleak3"
test "gcleak4"
# Disabled because it works and takes too long to run:

View file

@ -260,7 +260,7 @@ proc addResult(r: var TResults, test: TTest, target: TTarget,
let success = if test.spec.timeout > 0.0 and duration > test.spec.timeout: reTimeout
else: successOrig
let durationStr = duration.formatFloat(ffDecimal, precision = 8).align(11)
let durationStr = duration.formatFloat(ffDecimal, precision = 2).align(5)
if backendLogging:
backend.writeTestResult(name = name,
category = test.cat.string,
@ -271,7 +271,7 @@ proc addResult(r: var TResults, test: TTest, target: TTarget,
given = given)
r.data.addf("$#\t$#\t$#\t$#", name, expected, given, $success)
if success == reSuccess:
maybeStyledEcho fgGreen, "PASS: ", fgCyan, alignLeft(name, 60), fgBlue, " (", durationStr, " secs)"
maybeStyledEcho fgGreen, "PASS: ", fgCyan, alignLeft(name, 60), fgBlue, " (", durationStr, " sec)"
elif success == reDisabled:
maybeStyledEcho styleDim, fgYellow, "SKIP: ", styleBright, fgCyan, name
elif success == reJoined:

View file

@ -1,45 +1,30 @@
discard """
output: '''
test1:ok
test2:ok
test3:ok
test4:ok
test5:ok
test6:ok
test7:ok
`false` first assertion from bar
`false` second assertion from bar
-1
tassert2.nim
test8:ok
test9:ok
test10:ok
test11:ok
'''
"""
import testhelper
from strutils import endsWith
type
TLineInfo = tuple[filename: string, line: int, column: int]
TMyError = object of Exception
lineinfo: TLineInfo
EMyError = ref TMyError
echo("")
# NOTE: when entering newlines, adjust `expectedEnd` outputs
try:
doAssert(false, "msg1") # doAssert test
except AssertionError as e:
checkMsg(e.msg, "tassert2.nim(30, 11) `false` msg1", "test1")
try:
assert false, "msg2" # assert test
except AssertionError as e:
checkMsg(e.msg, "tassert2.nim(35, 10) `false` msg2", "test2")
assert e.msg.endsWith "tassert2.nim(20, 11) `false` msg1"
try:
assert false # assert test with no msg
except AssertionError as e:
checkMsg(e.msg, "tassert2.nim(40, 10) `false` ", "test3")
assert e.msg.endsWith "tassert2.nim(25, 10) `false` "
try:
let a = 1
@ -47,13 +32,13 @@ try:
# BUG: const folding would make "1+1==1" appear as `false` in
# assert message
except AssertionError as e:
checkMsg(e.msg, "`a + a == 1` ", "test4")
assert e.msg.endsWith "`a + a == 1` "
try:
let a = 1
doAssert a+a==1 # ditto with `doAssert` and no parens
except AssertionError as e:
checkMsg(e.msg, "`a + a == 1` ", "test5")
assert e.msg.endsWith "`a + a == 1` "
proc fooStatic() =
# protect against https://github.com/nim-lang/Nim/issues/8758
@ -80,12 +65,12 @@ block:
proc bar: int =
# local overrides that are active only in this proc
onFailedAssert(msg):
checkMsg(msg, "tassert2.nim(85, 11) `false` first assertion from bar", "test6")
echo msg[^32..^1]
assert(false, "first assertion from bar")
onFailedAssert(msg):
checkMsg(msg, "tassert2.nim(91, 11) `false` second assertion from bar", "test7")
echo msg[^33..^1]
return -1
assert(false, "second assertion from bar")
@ -97,8 +82,7 @@ block:
foo()
except:
let e = EMyError(getCurrentException())
echo e.lineinfo.filename
checkMsg(e.msg, "tassert2.nim(77, 11) `false` assertion from foo", "test8")
assert e.msg.endsWith "tassert2.nim(62, 11) `false` assertion from foo"
block: ## checks for issue https://github.com/nim-lang/Nim/issues/8518
template fun(a: string): string =
@ -109,14 +93,14 @@ block: ## checks for issue https://github.com/nim-lang/Nim/issues/8518
doAssert fun("foo1") == fun("foo2"), "mymsg"
except AssertionError as e:
# used to expand out the template instantiaiton, sometimes filling hundreds of lines
checkMsg(e.msg, """tassert2.nim(109, 14) `fun("foo1") == fun("foo2")` mymsg""", "test9")
assert e.msg.endsWith ""
block: ## checks for issue https://github.com/nim-lang/Nim/issues/9301
try:
doAssert 1 + 1 == 3
except AssertionError as e:
# used to const fold as false
checkMsg(e.msg, "tassert2.nim(116, 14) `1 + 1 == 3` ", "test10")
assert e.msg.endsWith "tassert2.nim(100, 14) `1 + 1 == 3` "
block: ## checks AST isn't transformed as it used to
let a = 1
@ -124,4 +108,4 @@ block: ## checks AST isn't transformed as it used to
doAssert a > 1
except AssertionError as e:
# used to rewrite as `1 < a`
checkMsg(e.msg, "tassert2.nim(124, 14) `a > 1` ", "test11")
assert e.msg.endsWith "tassert2.nim(108, 14) `a > 1` "

View file

@ -1,20 +0,0 @@
discard """
cmd: "nim $target -d:release $options $file"
output: '''
test1:ok
test2:ok
'''
"""
import testhelper
onFailedAssert(msg):
checkMsg(msg, "tdoassert.nim(15, 9) `a == 2` foo", "test1")
var a = 1
doAssert(a == 2, "foo")
onFailedAssert(msg):
checkMsg(msg, "tdoassert.nim(20, 10) `a == 3` ", "test2")
doAssert a == 3

View file

@ -1,12 +0,0 @@
from strutils import endsWith, split
from os import isAbsolute
proc checkMsg*(msg, expectedEnd, name: string, absolute = true)=
let filePrefix = msg.split(' ', maxSplit = 1)[0]
if absolute and not filePrefix.isAbsolute:
echo name, ":not absolute: `", msg & "`"
elif not msg.endsWith expectedEnd:
echo name, ":expected suffix:\n`" & expectedEnd & "`\ngot:\n`" & msg & "`"
else:
echo name, ":ok"

View file

@ -1,11 +0,0 @@
discard """
cmd: "nim $target $options --excessiveStackTrace:off $file"
output: '''
test:ok
'''
"""
import testhelper
try:
doAssert(false, "msg")
except AssertionError as e:
checkMsg(e.msg, "trelativeassert.nim(9, 11) `false` msg", "test", false)

View file

@ -1,7 +1,7 @@
import asyncdispatch, os, times
proc doubleSleep(hardSleep: int) {.async.} =
await sleepAsync(100)
await sleepAsync(50)
sleep(hardSleep)
template assertTime(target, timeTook: float): untyped {.dirty.} =
@ -16,37 +16,25 @@ var
# NOTE: this uses poll(3000) to limit timing error potential.
start = epochTime()
fut = sleepAsync(50) and sleepAsync(150) and doubleSleep(40)
fut = sleepAsync(40) and sleepAsync(100) and doubleSleep(20)
while not fut.finished:
poll(3000)
poll(1000)
assertTime(150, epochTime() - start)
start = epochTime()
fut = sleepAsync(50) and sleepAsync(150) and doubleSleep(100)
fut = sleepAsync(40) and sleepAsync(100) and doubleSleep(50)
while not fut.finished:
poll(3000)
poll(1000)
assertTime(200, epochTime() - start)
start = epochTime()
fut = sleepAsync(50) and sleepAsync(150) and doubleSleep(40) and sleepAsync(300)
fut = sleepAsync(40) and sleepAsync(100) and doubleSleep(20) and sleepAsync(200)
while not fut.finished:
poll(3000)
poll(1000)
assertTime(300, epochTime() - start)
start = epochTime()
fut = sleepAsync(50) and sleepAsync(150) and doubleSleep(100) and sleepAsync(300)
fut = (sleepAsync(40) and sleepAsync(100) and doubleSleep(20)) or sleepAsync(300)
while not fut.finished:
poll(3000)
assertTime(300, epochTime() - start)
start = epochTime()
fut = (sleepAsync(50) and sleepAsync(150) and doubleSleep(40)) or sleepAsync(700)
while not fut.finished:
poll(3000)
poll(1000)
assertTime(150, epochTime() - start)
start = epochTime()
fut = (sleepAsync(50) and sleepAsync(150) and doubleSleep(100)) or sleepAsync(700)
while not fut.finished:
poll(3000)
assertTime(200, epochTime() - start)

View file

@ -12,4 +12,4 @@ proc main() =
doAssert counter <= 4
for i in 0 .. 10: main()
for i in 0 .. 4: main()

View file

@ -9,11 +9,11 @@ block: #6100
done.complete(1)
proc asyncSum: Future[int] {.async.} =
for _ in 1..10_000_000:
for _ in 1..1_000_000:
result += await done
let res = waitFor asyncSum()
doAssert(res == 10000000)
doAssert(res == 1_000_000)
block: #7985
proc getData(): Future[JsonNode] {.async.} =

View file

@ -1,13 +1,13 @@
discard """
output: "5000"
output: "2000"
"""
import asyncdispatch, asyncnet, nativesockets, net, strutils, os
var msgCount = 0
const
swarmSize = 50
messagesToSend = 100
swarmSize = 40
messagesToSend = 50
var clientCount = 0

View file

@ -1,5 +1,5 @@
discard """
output: "50000"
output: "20000"
cmd: "nim c -d:nimTypeNames -d:nimCycleBreaker $file"
"""
import asyncdispatch, asyncnet, nativesockets, net, strutils, os
@ -7,8 +7,8 @@ import asyncdispatch, asyncnet, nativesockets, net, strutils, os
var msgCount = 0
const
swarmSize = 500
messagesToSend = 100
swarmSize = 400
messagesToSend = 50
var clientCount = 0

View file

@ -99,4 +99,3 @@ proc server() {.async.} =
when isMainModule:
waitFor server()

View file

@ -17,7 +17,7 @@ var fs = newFutureStream[int]()
proc alpha() {.async.} =
for i in 0 .. 5:
await fs.write(i)
await sleepAsync(200)
await sleepAsync(100)
echo("Done")
fs.complete()

View file

@ -19,7 +19,7 @@ else:
proc foo() {.async.} =
echo "hi"
var s = epochTime()
await sleepAsync(500)
await sleepAsync(200)
var e = epochTime()
doAssert(e - s > 0.1)
echo "bye"

View file

@ -7,7 +7,7 @@ import asyncdispatch
doAssert(not hasPendingOperations())
proc test() {.async.} =
await sleepAsync(100)
await sleepAsync(50)
var f = test()
while not f.finished:

View file

@ -1,27 +0,0 @@
discard """
output: '''a
long
list
of
words'''
cmd: r"nim c --hints:on $options -d:release $file"
ccodecheck: "! @'genericSeqAssign'"
target: "c"
"""
# bug #4354
import tables
import sets
import strutils
#const FRUITS = ["banana", "apple", "grapes"]
#let FRUITS = ["banana", "apple", "grapes"].toSet
const FRUITS = {"banana":0, "apple":0, "grapes":0}.toTable
proc main() =
let L = "a long list of words".split()
for word in L:
if word notin FRUITS:
echo(word)
main()

View file

@ -41,10 +41,6 @@ block tclosure:
proc map(n: var openarray[int], fn: proc (x: int): int {.closure}) =
for i in 0..n.len-1: n[i] = fn(n[i])
proc foldr(n: openarray[int], fn: proc (x, y: int): int {.closure}): int =
for i in 0..n.len-1:
result = fn(result, n[i])
proc each(n: openarray[int], fn: proc(x: int) {.closure.}) =
for i in 0..n.len-1:
fn(n[i])
@ -67,18 +63,6 @@ block tclosure:
#OUT 2 4 6 8 10
type
ITest = tuple[
setter: proc(v: int),
getter: proc(): int]
proc getInterf(): ITest =
var shared: int
return (setter: proc (x: int) = shared = x,
getter: proc (): int = return shared)
# bug #5015
type Mutator = proc(matched: string): string {.noSideEffect, gcsafe, locks: 0.}
@ -180,7 +164,7 @@ block tclosure0:
block tclosure3:
proc main =
const n = 30
for iterations in 0..50_000:
for iterations in 0..10_000:
var s: seq[proc(): string {.closure.}] = @[]
for i in 0 .. n-1:
(proc () =
@ -203,210 +187,12 @@ block tclosure4:
let json_elems = json_params["files"].elems
# These fail compilation.
var files = map(json_elems, proc (x: JsonNode): string = x.str)
#var files = json_elems.map do (x: JsonNode) -> string: x.str
let text = """{"files": ["a", "b", "c"]}"""
run((text.parseJson).fields)
import hashes, math
block tclosurebug2:
type
TSlotEnum = enum seEmpty, seFilled, seDeleted
TKeyValuePair[A, B] = tuple[slot: TSlotEnum, key: A, val: B]
TKeyValuePairSeq[A, B] = seq[TKeyValuePair[A, B]]
TOrderedKeyValuePair[A, B] = tuple[
slot: TSlotEnum, next: int, key: A, val: B]
TOrderedKeyValuePairSeq[A, B] = seq[TOrderedKeyValuePair[A, B]]
OrderedTable[A, B] = object ## table that remembers insertion order
data: TOrderedKeyValuePairSeq[A, B]
counter, first, last: int
const
growthFactor = 2
proc mustRehash(length, counter: int): bool {.inline.} =
assert(length > counter)
result = (length * 2 < counter * 3) or (length - counter < 4)
proc nextTry(h, maxHash: Hash): Hash {.inline.} =
result = ((5 * h) + 1) and maxHash
template rawGetImpl() {.dirty.} =
var h: Hash = hash(key) and high(t.data) # start with real hash value
while t.data[h].slot != seEmpty:
if t.data[h].key == key and t.data[h].slot == seFilled:
return h
h = nextTry(h, high(t.data))
result = -1
template rawInsertImpl() {.dirty.} =
var h: Hash = hash(key) and high(data)
while data[h].slot == seFilled:
h = nextTry(h, high(data))
data[h].key = key
data[h].val = val
data[h].slot = seFilled
template addImpl() {.dirty.} =
if mustRehash(len(t.data), t.counter): enlarge(t)
rawInsert(t, t.data, key, val)
inc(t.counter)
template putImpl() {.dirty.} =
var index = rawGet(t, key)
if index >= 0:
t.data[index].val = val
else:
addImpl()
proc len[A, B](t: OrderedTable[A, B]): int {.inline.} =
## returns the number of keys in `t`.
result = t.counter
template forAllOrderedPairs(yieldStmt: untyped) {.dirty.} =
var h = t.first
while h >= 0:
var nxt = t.data[h].next
if t.data[h].slot == seFilled: yieldStmt
h = nxt
iterator pairs[A, B](t: OrderedTable[A, B]): tuple[key: A, val: B] =
## iterates over any (key, value) pair in the table `t` in insertion
## order.
forAllOrderedPairs:
yield (t.data[h].key, t.data[h].val)
iterator mpairs[A, B](t: var OrderedTable[A, B]): tuple[key: A, val: var B] =
## iterates over any (key, value) pair in the table `t` in insertion
## order. The values can be modified.
forAllOrderedPairs:
yield (t.data[h].key, t.data[h].val)
iterator keys[A, B](t: OrderedTable[A, B]): A =
## iterates over any key in the table `t` in insertion order.
forAllOrderedPairs:
yield t.data[h].key
iterator values[A, B](t: OrderedTable[A, B]): B =
## iterates over any value in the table `t` in insertion order.
forAllOrderedPairs:
yield t.data[h].val
iterator mvalues[A, B](t: var OrderedTable[A, B]): var B =
## iterates over any value in the table `t` in insertion order. The values
## can be modified.
forAllOrderedPairs:
yield t.data[h].val
proc rawGet[A, B](t: OrderedTable[A, B], key: A): int =
rawGetImpl()
proc `[]`[A, B](t: OrderedTable[A, B], key: A): B =
## retrieves the value at ``t[key]``. If `key` is not in `t`,
## default empty value for the type `B` is returned
## and no exception is raised. One can check with ``hasKey`` whether the key
## exists.
var index = rawGet(t, key)
if index >= 0: result = t.data[index].val
proc mget[A, B](t: var OrderedTable[A, B], key: A): var B =
## retrieves the value at ``t[key]``. The value can be modified.
## If `key` is not in `t`, the ``EInvalidKey`` exception is raised.
var index = rawGet(t, key)
if index >= 0: result = t.data[index].val
else: raise newException(KeyError, "key not found: " & $key)
proc hasKey[A, B](t: OrderedTable[A, B], key: A): bool =
## returns true iff `key` is in the table `t`.
result = rawGet(t, key) >= 0
proc rawInsert[A, B](t: var OrderedTable[A, B],
data: var TOrderedKeyValuePairSeq[A, B],
key: A, val: B) =
rawInsertImpl()
data[h].next = -1
if t.first < 0: t.first = h
if t.last >= 0: data[t.last].next = h
t.last = h
proc enlarge[A, B](t: var OrderedTable[A, B]) =
var n: TOrderedKeyValuePairSeq[A, B]
newSeq(n, len(t.data) * growthFactor)
var h = t.first
t.first = -1
t.last = -1
while h >= 0:
var nxt = t.data[h].next
if t.data[h].slot == seFilled:
rawInsert(t, n, t.data[h].key, t.data[h].val)
h = nxt
swap(t.data, n)
proc `[]=`[A, B](t: var OrderedTable[A, B], key: A, val: B) =
## puts a (key, value)-pair into `t`.
putImpl()
proc add[A, B](t: var OrderedTable[A, B], key: A, val: B) =
## puts a new (key, value)-pair into `t` even if ``t[key]`` already exists.
addImpl()
proc iniOrderedTable[A, B](initialSize=64): OrderedTable[A, B] =
## creates a new ordered hash table that is empty. `initialSize` needs to be
## a power of two.
assert isPowerOfTwo(initialSize)
result.counter = 0
result.first = -1
result.last = -1
newSeq(result.data, initialSize)
proc toOrderedTable[A, B](pairs: openarray[tuple[key: A,
val: B]]): OrderedTable[A, B] =
## creates a new ordered hash table that contains the given `pairs`.
result = iniOrderedTable[A, B](nextPowerOfTwo(pairs.len+10))
for key, val in items(pairs): result[key] = val
proc sort[A, B](t: var OrderedTable[A,B],
cmp: proc (x, y: tuple[key: A, val: B]): int {.closure.}) =
## sorts the ordered table so that the entry with the highest counter comes
## first. This is destructive (with the advantage of being efficient)!
## You must not modify `t` afterwards!
## You can use the iterators `pairs`, `keys`, and `values` to iterate over
## `t` in the sorted order.
# we use shellsort here; fast enough and simple
var h = 1
while true:
h = 3 * h + 1
if h >= high(t.data): break
while true:
h = h div 3
for i in countup(h, high(t.data)):
var j = i
#echo(t.data.len, " ", j, " - ", h)
#echo(repr(t.data[j-h]))
proc rawCmp(x, y: TOrderedKeyValuePair[A, B]): int =
if x.slot in {seEmpty, seDeleted} and y.slot in {seEmpty, seDeleted}:
return 0
elif x.slot in {seEmpty, seDeleted}:
return -1
elif y.slot in {seEmpty, seDeleted}:
return 1
else:
let item1 = (x.key, x.val)
let item2 = (y.key, y.val)
return cmp(item1, item2)
while rawCmp(t.data[j-h], t.data[j]) <= 0:
swap(t.data[j], t.data[j-h])
j = j-h
if j < h: break
if h == 1: break
import sugar
block inference3304:
type
@ -513,7 +299,7 @@ block tflatmap:
let g: A -> Rand[B] = (a: A) => ((rng: RNG) => (f(a), rng))
flatMap(s, g)
let f = nextInt.map(i => i - i mod 2)
discard nextInt.map(i => i - i mod 2)

View file

@ -2,7 +2,7 @@ discard """
output: ""
"""
import deques, sequtils
import sets, tables, deques, lists, critbits, sequtils
block tapply:
@ -52,3 +52,109 @@ block tmapit:
# since ``len`` is not available
var r = st.mapIt($(it+10))
doAssert r == @["10", "11", "12", "13", "14"]
# Collections to string:
# Tests for tuples
doAssert $(1, 2, 3) == "(1, 2, 3)"
doAssert $("1", "2", "3") == """("1", "2", "3")"""
doAssert $('1', '2', '3') == """('1', '2', '3')"""
# Tests for seqs
doAssert $(@[1, 2, 3]) == "@[1, 2, 3]"
doAssert $(@["1", "2", "3"]) == """@["1", "2", "3"]"""
doAssert $(@['1', '2', '3']) == """@['1', '2', '3']"""
# Tests for sets
doAssert $(toHashSet([1])) == "{1}"
doAssert $(toHashSet(["1"])) == """{"1"}"""
doAssert $(toHashSet(['1'])) == """{'1'}"""
doAssert $(toOrderedSet([1, 2, 3])) == "{1, 2, 3}"
doAssert $(toOrderedSet(["1", "2", "3"])) == """{"1", "2", "3"}"""
doAssert $(toOrderedSet(['1', '2', '3'])) == """{'1', '2', '3'}"""
# Tests for tables
doAssert $({1: "1", 2: "2"}.toTable) == """{1: "1", 2: "2"}"""
doAssert $({"1": 1, "2": 2}.toTable) == """{"1": 1, "2": 2}"""
# Tests for deques
block:
var d = initDeque[int]()
d.addLast(1)
doAssert $d == "[1]"
block:
var d = initDeque[string]()
d.addLast("1")
doAssert $d == """["1"]"""
block:
var d = initDeque[char]()
d.addLast('1')
doAssert $d == "['1']"
# Tests for lists
block:
var l = initDoublyLinkedList[int]()
l.append(1)
l.append(2)
l.append(3)
doAssert $l == "[1, 2, 3]"
block:
var l = initDoublyLinkedList[string]()
l.append("1")
l.append("2")
l.append("3")
doAssert $l == """["1", "2", "3"]"""
block:
var l = initDoublyLinkedList[char]()
l.append('1')
l.append('2')
l.append('3')
doAssert $l == """['1', '2', '3']"""
# Tests for critbits
block:
var t: CritBitTree[int]
t["a"] = 1
doAssert $t == """{"a": 1}"""
block:
var t: CritBitTree[string]
t["a"] = "1"
doAssert $t == """{"a": "1"}"""
block:
var t: CritBitTree[char]
t["a"] = '1'
doAssert $t == """{"a": '1'}"""
# Test escaping behavior
block:
var s = ""
s.addQuoted('\0')
s.addQuoted('\31')
s.addQuoted('\127')
doAssert s == "'\\x00''\\x1F''\\x7F'"
block:
var s = ""
s.addQuoted('\\')
s.addQuoted('\'')
s.addQuoted('\"')
doAssert s == """'\\''\'''\"'"""
block:
var s = ""
s.addQuoted("å")
s.addQuoted("ä")
s.addQuoted("ö")
s.addEscapedChar('\xFF')
doAssert s == """"å""ä""ö"\xFF"""
# Test customized element representation
type CustomString = object
proc addQuoted(s: var string, x: CustomString) =
s.add("<CustomString>")
block:
let s = @[CustomString()]
doAssert $s == "@[<CustomString>]"

View file

@ -173,19 +173,15 @@ block tableconstr:
block ttables2:
proc TestHashIntInt() =
var tab = initTable[int,int]()
when defined(nimTestsTablesDisableSlow):
# helps every single time when this test needs to be debugged
let n = 1_000
else:
let n = 1_000_000
let n = 100_000
for i in 1..n:
tab[i] = i
for i in 1..n:
var x = tab[i]
if x != i : echo "not found ", i
proc run1() = # occupied Memory stays constant, but
for i in 1 .. 50: # aborts at run: 44 on win32 with 3.2GB with out of memory
proc run1() =
for i in 1 .. 50:
TestHashIntInt()
# bug #2107

View file

@ -1,7 +1,7 @@
discard """
cmd: '''nim c -d:nimAllocStats --newruntime $file'''
output: '''331665
(allocCount: 333335, deallocCount: 333335)'''
output: '''31665
(allocCount: 33335, deallocCount: 33335)'''
"""
# bug #11053
@ -72,7 +72,7 @@ proc main() =
cur = 5'i32
res = 0
for i in 1 ..< 1000000:
for i in 1 ..< 100000:
let a = i mod 3
cur = (cur * 57 + 43) mod 10007
case a:

View file

@ -1,31 +0,0 @@
import os, osproc, strutils
const characters = "abcdefghijklmnopqrstuvwxyz"
var s: string
# # chcks.nim:23
# # test formatErrorIndexBound returns correct bounds
block:
s = characters
try:
discard s[0..999]
except IndexError:
let msg = getCurrentExceptionMsg()
let expected = "index $# not in 0 .. $#" % [$len(s), $(len(s)-1)]
doAssert msg.contains expected, $(msg, expected)
block:
try:
discard paramStr(999)
except IndexError:
let msg = getCurrentExceptionMsg()
let expected = "index 999 not in 0 .. 0"
doAssert msg.contains expected, $(msg, expected)
block:
const nim = getCurrentCompilerExe()
for i in 1..4:
let (outp, errC) = execCmdEx("$# e tests/exception/testindexerroroutput.nims test$#" % [nim, $i])
let expected = "index 3 not in 0 .. 2"
doAssert errC != 0
doAssert outp.contains expected, $(outp, errC, expected, i)

View file

@ -35,7 +35,7 @@ proc newPlus(a, b: sink(ref TExpr)): ref TPlusExpr =
const Limit = when compileOption("gc", "markAndSweep") or compileOption("gc", "boehm"): 5*1024*1024 else: 500_000
for i in 0..100_000:
for i in 0..50_000:
var s: array[0..11, ref TExpr]
for j in 0..high(s):
s[j] = newPlus(newPlus(newLit(j), newLit(2)), newLit(4))

View file

@ -18,7 +18,7 @@ const Limit = 5*1024*1024
proc main =
var counter = 0
for i in 0 .. 100_000:
for i in 0 .. 10_000:
for k, v in handleRequest("nick=Elina2&type=activate"):
inc counter
if counter mod 100 == 0:

View file

@ -1,13 +1,13 @@
discard """
output: '''Welcome to LoopTesterApp, Nim edition
Constructing Simple CFG...
15000 dummy loops
5000 dummy loops
Constructing CFG...
Performing Loop Recognition
1 Iteration
Another 5 iterations...
.....
Found 1 loops (including artificial root node) (5)'''
Another 3 iterations...
...
Found 1 loops (including artificial root node) (3)'''
"""
# bug #3184
@ -384,9 +384,9 @@ proc run(self: var LoopTesterApp) =
discard self.cfg.createNode(1)
self.buildConnect(0, 2)
echo "15000 dummy loops"
echo "5000 dummy loops"
for i in 1..15000:
for i in 1..5000:
withScratchRegion:
var h = newHavlakLoopFinder(self.cfg, newLsg())
discard h.findLoops
@ -414,10 +414,10 @@ proc run(self: var LoopTesterApp) =
var h = newHavlakLoopFinder(self.cfg, newLsg())
var loops = h.findLoops
echo "Another 5 iterations..."
echo "Another 3 iterations..."
var sum = 0
for i in 1..5:
for i in 1..3:
withScratchRegion:
write stdout, "."
flushFile(stdout)

View file

@ -72,20 +72,20 @@ proc newRStarTree*[M, D: Dim; RT, LT](minFill: range[30 .. 50] = 40): RStarTree[
result.root = newLeaf[M, D, RT, LT]()
proc center(r: Box): auto =#BoxCenter[r.len, type(r[0].a)] =
var result: BoxCenter[r.len, type(r[0].a)]
var res: BoxCenter[r.len, type(r[0].a)]
for i in 0 .. r.high:
when r[0].a is SomeInteger:
result[i] = (r[i].a + r[i].b) div 2
res[i] = (r[i].a + r[i].b) div 2
elif r[0].a is SomeFloat:
result[i] = (r[i].a + r[i].b) / 2
res[i] = (r[i].a + r[i].b) / 2
else: assert false
return result
return res
proc distance(c1, c2: BoxCenter): auto =
var result: type(c1[0])
var res: type(c1[0])
for i in 0 .. c1.high:
result += (c1[i] - c2[i]) * (c1[i] - c2[i])
return result
res += (c1[i] - c2[i]) * (c1[i] - c2[i])
return res
proc overlap(r1, r2: Box): auto =
result = type(r1[0].a)(1)
@ -177,21 +177,6 @@ proc chooseSubtree[M, D: Dim; RT, LT](t: RTree[M, D, RT, LT]; b: Box[D, RT]; lev
n = nn.a[i0].n
return n
proc chooseLeaf[M, D: Dim; RT, LT](t: RTree[M, D, RT, LT]; b: Box[D, RT]; level: int): H[M, D, RT, LT] =
assert level >= 0
var n = t.root
while n.level > level:
var j = -1 # selected index
var x: type(b[0].a)
let nn = Node[M, D, RT, LT](n)
for i in 0 ..< n.numEntries:
let h = enlargement(nn.a[i].b, b)
if j < 0 or h < x or (x == h and area(nn.a[i].b) < area(nn.a[j].b)):
x = h
j = i
n = nn.a[j].n
return n
proc pickSeeds[M, D: Dim; RT, LT](t: RTree[M, D, RT, LT]; n: Node[M, D, RT, LT] | Leaf[M, D, RT, LT]; bx: Box[D, RT]): (int, int) =
var i0, j0: int
var bi, bj: type(bx)
@ -412,12 +397,7 @@ proc adjustTree[M, D: Dim; RT, LT](t: RTree[M, D, RT, LT]; l, ll: H[M, D, RT, LT
nn = nil
else:
let h: N[M, D, RT, LT] = (b, nn)
if t of RStarTree[M, D, RT, LT]:
nn = overflowTreatment(RStarTree[M, D, RT, LT](t), p, h)
elif t of RTree[M, D, RT, LT]:
nn = quadraticSplit(RTree[M, D, RT, LT](t), p, h)
else:
assert false
nn = quadraticSplit(t, p, h)
assert n == H[M, D, RT, LT](p)
assert n != nil
assert t.root != nil
@ -567,18 +547,16 @@ proc condenseTree[M, D: Dim; RT, LT](t: RTree[M, D, RT, LT]; leaf: Leaf[M, D, RT
rsinsert(RStarTree[M, D, RT, LT](t), Node[M, D, RT, LT](n).a[i], n.level)
else:
assert false
elif t of RTree[M, D, RT, LT]:
else:
for n in q:
if n of Leaf[M, D, RT, LT]:
for i in 0 ..< n.numEntries:
insert(RTree[M, D, RT, LT](t), Leaf[M, D, RT, LT](n).a[i])
insert(t, Leaf[M, D, RT, LT](n).a[i])
elif n of Node[M, D, RT, LT]:
for i in 0 ..< n.numEntries:
insert(RTree[M, D, RT, LT](t), Node[M, D, RT, LT](n).a[i], n.level)
insert(t, Node[M, D, RT, LT](n).a[i], n.level)
else:
assert false
else:
assert false
proc delete*[M, D: Dim; RT, LT](t: RTree[M, D, RT, LT]; leaf: L[D, RT, LT]): bool {.discardable.} =
let l = findLeaf(t, leaf)
@ -659,6 +637,4 @@ proc test(n: int) =
assert r.len == r2.len
assert r.sorted(system.cmp) == r2.sorted(system.cmp)
test(1500)
# 651 lines
test(500)

View file

@ -10,6 +10,7 @@ collide: thing, unit |
do nothing
'''
joinable: false
disabled: true
"""

View file

@ -4,6 +4,7 @@ discard """
Hi derived!
hello
'''
disabled: true
"""

View file

@ -1,6 +1,5 @@
discard """
cmd: "nim $target $options -r $file"
targets: "c cpp"
cmd: "nim c $options -r $file"
matrix: "-d:danger; -d:release"
output: '''
a

View file

@ -25,11 +25,11 @@ proc emitter() =
spawn emitter()
# At this point emitter should be stuck in `send`
sleep(100) # Sleep a bit to ensure that it is still stuck
sleep(50) # Sleep a bit to ensure that it is still stuck
doAssert(not msgSent)
spawn receiver()
sleep(100) # Sleep a bit to let receicer consume the messages
sleep(50) # Sleep a bit to let receicer consume the messages
doAssert(msgSent) # Sender should be unblocked
doAssert(chan.trySend(4))

View file

@ -51,12 +51,11 @@ proc convex_hull[T](points: var seq[T], cmp: proc(x, y: T): int {.closure.}) : s
ul[k] = spawn half[T](points, k == 0)
result = concat(^ul[0], ^ul[1])
var s = map(toSeq(0..99999), proc(x: int): Point = (float(x div 1000), float(x mod 1000)))
var s = map(toSeq(0..9999), proc(x: int): Point = (float(x div 100), float(x mod 100)))
# On some runs, this pool size reduction will set the "shutdown" attribute on the
# worker thread that executes our spawned task, before we can read the flowvars.
setMaxPoolSize 2
#echo convex_hull[Point](s, cmpPoint)
for i in 0..5:
for i in 0..2:
doAssert convex_hull[Point](s, cmpPoint) ==
@[(0.0, 0.0), (99.0, 0.0), (99.0, 999.0), (0.0, 999.0)]
@[(0.0, 0.0), (99.0, 0.0), (99.0, 99.0), (0.0, 99.0)]

View file

@ -1,18 +1,54 @@
discard """
output: '''13 abc'''
output: '''
13 abc
called deepCopy for int
called deepCopy for int
done999 999
'''
"""
type
PBinaryTree = ref object
le, ri: PBinaryTree
value: int
import threadpool
block one:
type
PBinaryTree = ref object
le, ri: PBinaryTree
value: int
proc main =
var x: PBinaryTree
deepCopy(x, PBinaryTree(ri: PBinaryTree(le: PBinaryTree(value: 13))))
var y: string
deepCopy y, "abc"
echo x.ri.le.value, " ", y
main()
proc main =
var x: PBinaryTree
deepCopy(x, PBinaryTree(ri: PBinaryTree(le: PBinaryTree(value: 13))))
var y: string
deepCopy y, "abc"
echo x.ri.le.value, " ", y
block two:
type
Bar[T] = object
x: T
main()
proc `=deepCopy`[T](b: ref Bar[T]): ref Bar[T] =
result.new
result.x = b.x
when T is int:
echo "called deepCopy for int"
else:
echo "called deepCopy for something else"
proc foo(b: ref Bar[int]): int = 999
# test that the disjoint checker deals with 'a = spawn f(); g = spawn f()':
proc main =
var dummy: ref Bar[int]
new(dummy)
dummy.x = 44
#parallel:
let f = spawn foo(dummy)
let b = spawn foo(dummy)
echo "done", ^f, " ", ^b
main()

View file

@ -1,7 +1,9 @@
discard """
output: '''called deepCopy for int
output: '''
called deepCopy for int
done999 999'''
called deepCopy for int
done999 999
'''
"""
import threadpool

View file

@ -2,20 +2,49 @@ discard """
outputsub: "EVEN 28"
"""
import threadpool
import threadpool, locks
proc odd(a: int) = echo "ODD ", a
proc even(a: int) = echo "EVEN ", a
block one:
proc odd(a: int) = echo "ODD ", a
proc even(a: int) = echo "EVEN ", a
proc main() =
var a: array[0..30, int]
for i in low(a)..high(a): a[i] = i
parallel:
var i = 0
while i <= 29:
spawn even(a[i])
spawn odd(a[i+1])
inc i, 2
# is correct here
proc main() =
var a: array[0..30, int]
for i in low(a)..high(a): a[i] = i
parallel:
var i = 0
while i <= 29:
spawn even(a[i])
spawn odd(a[i+1])
inc i, 2
# is correct here
main()
main()
block two:
var echoLock: Lock
initLock echoLock
proc f(a: openArray[int]) =
for x in a:
withLock echoLock:
echo x
proc f(a: int) =
withLock echoLock:
echo a
proc main() =
var a: array[0..9, int] = [0,1,2,3,4,5,6,7,8,9]
parallel:
spawn f(a[0..2])
#spawn f(a[16..30])
var i = 3
while i <= 8:
spawn f(a[i])
spawn f(a[i+1])
inc i, 2
# is correct here
main()

View file

@ -1,40 +0,0 @@
discard """
output: '''0
1
2
3
4
5
6
7
8'''
sortoutput: true
"""
import threadpool, locks
var echoLock: Lock
initLock echoLock
proc f(a: openArray[int]) =
for x in a:
withLock echoLock:
echo x
proc f(a: int) =
withLock echoLock:
echo a
proc main() =
var a: array[0..9, int] = [0,1,2,3,4,5,6,7,8,9]
parallel:
spawn f(a[0..2])
#spawn f(a[16..30])
var i = 3
while i <= 8:
spawn f(a[i])
spawn f(a[i+1])
inc i, 2
# is correct here
main()

View file

@ -26,10 +26,10 @@ proc greet(p:Person) =
" friend:", p.friend.name, "(", cast[int](addr p.friend.name),") }"
proc setup =
for i in 0 ..< 20:
for i in 0 ..< 10:
people.add newPerson("Person" & $(i + 1))
for i in 0 ..< 20:
people[i].friend = people[19-i]
for i in 0 ..< 10:
people[i].friend = people[9-i]
proc update =
parallel:

View file

@ -17,9 +17,9 @@ import tables
type
Base* = ref object of RootObj
someSeq: seq[int]
baseData: array[400000, byte]
baseData: array[40000, byte]
Derived* = ref object of Base
data: array[400000, byte]
data: array[40000, byte]
type
ThreadPool = ref object

View file

@ -3,7 +3,7 @@ discard """
"""
# bug #7638
import threadpool, os, strformat
import threadpool, os
proc timer(d: int): int =
#echo fmt"sleeping {d}"
@ -11,7 +11,7 @@ proc timer(d: int): int =
#echo fmt"done {d}"
return d
var durations = [1000, 1500, 2000, 2500, 3000]
var durations = [1000, 1500, 2000]
var tasks: seq[FlowVarBase] = @[]
var results: seq[int] = @[]
@ -25,11 +25,9 @@ while index != -1:
#echo repr results
index = blockUntilAny(tasks)
doAssert results.len == 5
doAssert results.len == 3
doAssert 1000 in results
doAssert 1500 in results
doAssert 2000 in results
doAssert 2500 in results
doAssert 3000 in results
sync()
echo "true"

View file

@ -1,9 +0,0 @@
discard """
output: "ugly conversion successful"
"""
import int2bool
if 4:
echo "ugly conversion successful"

View file

@ -1,13 +0,0 @@
type
TBaseClass* = object of RootObj
proc newBaseClass*: ref TBaseClass =
new result
method echoType*(x: ref TBaseClass) {.base.} =
echo "base class"
proc echoAlias*(x: ref TBaseClass) =
echoType x

View file

@ -1,9 +0,0 @@
discard """
output: "ugly conversion successful 2"
"""
import int2bool
if 4:
echo "ugly conversion successful 2"

View file

@ -1,29 +0,0 @@
discard """
output: '''derived class
base class
'''
"""
import amethods
type
TDerivedClass* = object of TBaseClass
proc newDerivedClass: ref TDerivedClass =
new result
method echoType*(x: ref TDerivedClass) =
echo "derived class"
var b, d: ref TBaseClass
b = newBaseClass()
d = newDerivedClass()
#b.echoType()
#d.echoType()
echoAlias d
echoAlias b

View file

@ -1,29 +0,0 @@
discard """
output: '''derived class 2
base class
'''
"""
import amethods
type
TDerivedClass* = object of TBaseClass
proc newDerivedClass: ref TDerivedClass =
new result
method echoType*(x: ref TDerivedClass) =
echo "derived class 2"
var b, d: ref TBaseClass
b = newBaseClass()
d = newDerivedClass()
#b.echoType()
#d.echoType()
echoAlias d
echoAlias b

View file

@ -1,8 +0,0 @@
discard """
output: '''246
'''
"""
import deadg, deadb

View file

@ -1,12 +0,0 @@
discard """
output: '''246
xyzabc
'''
"""
import deadg, deadb
# now add call to previously unused proc p2:
echo p2("xyz", "abc")

View file

@ -1,7 +0,0 @@
import deadg
echo p1(123, 123)

View file

@ -1,7 +0,0 @@
proc p1*(x, y: int): int =
result = x + y
proc p2*(x, y: string): string =
result = x & y

View file

@ -1,14 +0,0 @@
import
cairo, glib2, gtk2
proc destroy(widget: PWidget, data: Pgpointer) {.cdecl.} =
main_quit()
var
window: PWidget
nim_init()
window = window_new(WINDOW_TOPLEVEL)
discard signal_connect(window, "destroy",
SIGNAL_FUNC(gtkex1.destroy), nil)
show(window)
main()

View file

@ -1,22 +0,0 @@
import
glib2, gtk2
proc destroy(widget: PWidget, data: Pgpointer){.cdecl.} =
main_quit()
var
window: PWidget
button: PWidget
nim_init()
window = window_new(WINDOW_TOPLEVEL)
button = button_new("Click me")
set_border_width(PContainer(window), 5)
add(PContainer(window), button)
discard signal_connect(window, "destroy",
SIGNAL_FUNC(gtkex2.destroy), nil)
show(button)
show(window)
main()

View file

@ -1,6 +0,0 @@
discard """
output: "Hello World"
"""
echo "Hello World"

View file

@ -1,17 +0,0 @@
discard """
output: "Hello World"
"""
# Test incremental type information
type
TNode = object {.pure.}
le, ri: ref TNode
data: string
proc newNode(data: string): ref TNode =
new(result)
result.data = data
echo newNode("Hello World").data

View file

@ -1,7 +0,0 @@
{.overflowchecks: on.}
converter uglyToBool*(x: int): bool =
result = x != 0

View file

@ -1,2 +0,0 @@
--nimcache:"$projectPath/nimcache"
--symbolFiles:on

View file

@ -1,13 +0,0 @@
discard """
output: "abcd"
"""
import tables
var x = initTable[int, string]()
x[2] = "ab"
x[5] = "cd"
echo x[2], x[5]

View file

@ -1,13 +0,0 @@
discard """
output: "abef"
"""
import tables
var x = initTable[int, string]()
x[2] = "ab"
x[5] = "ef"
echo x[2], x[5]

View file

@ -1,10 +1,13 @@
discard """
nimout: "OK"
output: "OK"
output: '''
OK
OK
'''
"""
import bitops
proc main() =
proc main1() =
const U8 = 0b0011_0010'u8
const I8 = 0b0011_0010'i8
const U16 = 0b00100111_00101000'u16
@ -261,7 +264,172 @@ block: # not ready for vm because exception is compile error
doAssert false
main()
main1()
static:
# test everything on vm as well
main()
main1()
proc main2() =
const U8 = 0b0011_0010'u8
const I8 = 0b0011_0010'i8
const U16 = 0b00100111_00101000'u16
const I16 = 0b00100111_00101000'i16
const U32 = 0b11010101_10011100_11011010_01010000'u32
const I32 = 0b11010101_10011100_11011010_01010000'i32
const U64A = 0b01000100_00111111_01111100_10001010_10011001_01001000_01111010_00010001'u64
const I64A = 0b01000100_00111111_01111100_10001010_10011001_01001000_01111010_00010001'i64
const U64B = 0b00110010_11011101_10001111_00101000_00000000_00000000_00000000_00000000'u64
const I64B = 0b00110010_11011101_10001111_00101000_00000000_00000000_00000000_00000000'i64
doAssert( U64A.fastLog2 == 62)
doAssert( I64A.fastLog2 == 62)
doAssert( U64A.countLeadingZeroBits == 1)
doAssert( I64A.countLeadingZeroBits == 1)
doAssert( U64A.countTrailingZeroBits == 0)
doAssert( I64A.countTrailingZeroBits == 0)
doAssert( U64A.firstSetBit == 1)
doAssert( I64A.firstSetBit == 1)
doAssert( U64A.parityBits == 1)
doAssert( I64A.parityBits == 1)
doAssert( U64A.countSetBits == 29)
doAssert( I64A.countSetBits == 29)
doAssert( U64A.rotateLeftBits(37) == 0b00101001_00001111_01000010_00101000_10000111_11101111_10010001_01010011'u64)
doAssert( U64A.rotateRightBits(37) == 0b01010100_11001010_01000011_11010000_10001010_00100001_11111011_11100100'u64)
doAssert( U64B.firstSetBit == 36)
doAssert( I64B.firstSetBit == 36)
doAssert( U32.fastLog2 == 31)
doAssert( I32.fastLog2 == 31)
doAssert( U32.countLeadingZeroBits == 0)
doAssert( I32.countLeadingZeroBits == 0)
doAssert( U32.countTrailingZeroBits == 4)
doAssert( I32.countTrailingZeroBits == 4)
doAssert( U32.firstSetBit == 5)
doAssert( I32.firstSetBit == 5)
doAssert( U32.parityBits == 0)
doAssert( I32.parityBits == 0)
doAssert( U32.countSetBits == 16)
doAssert( I32.countSetBits == 16)
doAssert( U32.rotateLeftBits(21) == 0b01001010_00011010_10110011_10011011'u32)
doAssert( U32.rotateRightBits(21) == 0b11100110_11010010_10000110_10101100'u32)
doAssert( U16.fastLog2 == 13)
doAssert( I16.fastLog2 == 13)
doAssert( U16.countLeadingZeroBits == 2)
doAssert( I16.countLeadingZeroBits == 2)
doAssert( U16.countTrailingZeroBits == 3)
doAssert( I16.countTrailingZeroBits == 3)
doAssert( U16.firstSetBit == 4)
doAssert( I16.firstSetBit == 4)
doAssert( U16.parityBits == 0)
doAssert( I16.parityBits == 0)
doAssert( U16.countSetBits == 6)
doAssert( I16.countSetBits == 6)
doAssert( U16.rotateLeftBits(12) == 0b10000010_01110010'u16)
doAssert( U16.rotateRightBits(12) == 0b01110010_10000010'u16)
doAssert( U8.fastLog2 == 5)
doAssert( I8.fastLog2 == 5)
doAssert( U8.countLeadingZeroBits == 2)
doAssert( I8.countLeadingZeroBits == 2)
doAssert( U8.countTrailingZeroBits == 1)
doAssert( I8.countTrailingZeroBits == 1)
doAssert( U8.firstSetBit == 2)
doAssert( I8.firstSetBit == 2)
doAssert( U8.parityBits == 1)
doAssert( I8.parityBits == 1)
doAssert( U8.countSetBits == 3)
doAssert( I8.countSetBits == 3)
doAssert( U8.rotateLeftBits(3) == 0b10010001'u8)
doAssert( U8.rotateRightBits(3) == 0b0100_0110'u8)
static :
# test bitopts at compile time with vm
doAssert( U8.fastLog2 == 5)
doAssert( I8.fastLog2 == 5)
doAssert( U8.countLeadingZeroBits == 2)
doAssert( I8.countLeadingZeroBits == 2)
doAssert( U8.countTrailingZeroBits == 1)
doAssert( I8.countTrailingZeroBits == 1)
doAssert( U8.firstSetBit == 2)
doAssert( I8.firstSetBit == 2)
doAssert( U8.parityBits == 1)
doAssert( I8.parityBits == 1)
doAssert( U8.countSetBits == 3)
doAssert( I8.countSetBits == 3)
doAssert( U8.rotateLeftBits(3) == 0b10010001'u8)
doAssert( U8.rotateRightBits(3) == 0b0100_0110'u8)
template test_undefined_impl(ffunc: untyped; expected: int; is_static: bool) =
doAssert( ffunc(0'u8) == expected)
doAssert( ffunc(0'i8) == expected)
doAssert( ffunc(0'u16) == expected)
doAssert( ffunc(0'i16) == expected)
doAssert( ffunc(0'u32) == expected)
doAssert( ffunc(0'i32) == expected)
doAssert( ffunc(0'u64) == expected)
doAssert( ffunc(0'i64) == expected)
template test_undefined(ffunc: untyped; expected: int) =
test_undefined_impl(ffunc, expected, false)
static:
test_undefined_impl(ffunc, expected, true)
when defined(noUndefinedBitOpts):
# check for undefined behavior with zero.
test_undefined(countSetBits, 0)
test_undefined(parityBits, 0)
test_undefined(firstSetBit, 0)
test_undefined(countLeadingZeroBits, 0)
test_undefined(countTrailingZeroBits, 0)
test_undefined(fastLog2, -1)
# check for undefined behavior with rotate by zero.
doAssert( U8.rotateLeftBits(0) == U8)
doAssert( U8.rotateRightBits(0) == U8)
doAssert( U16.rotateLeftBits(0) == U16)
doAssert( U16.rotateRightBits(0) == U16)
doAssert( U32.rotateLeftBits(0) == U32)
doAssert( U32.rotateRightBits(0) == U32)
doAssert( U64A.rotateLeftBits(0) == U64A)
doAssert( U64A.rotateRightBits(0) == U64A)
# check for undefined behavior with rotate by integer width.
doAssert( U8.rotateLeftBits(8) == U8)
doAssert( U8.rotateRightBits(8) == U8)
doAssert( U16.rotateLeftBits(16) == U16)
doAssert( U16.rotateRightBits(16) == U16)
doAssert( U32.rotateLeftBits(32) == U32)
doAssert( U32.rotateRightBits(32) == U32)
doAssert( U64A.rotateLeftBits(64) == U64A)
doAssert( U64A.rotateRightBits(64) == U64A)
static: # check for undefined behavior with rotate by zero.
doAssert( U8.rotateLeftBits(0) == U8)
doAssert( U8.rotateRightBits(0) == U8)
doAssert( U16.rotateLeftBits(0) == U16)
doAssert( U16.rotateRightBits(0) == U16)
doAssert( U32.rotateLeftBits(0) == U32)
doAssert( U32.rotateRightBits(0) == U32)
doAssert( U64A.rotateLeftBits(0) == U64A)
doAssert( U64A.rotateRightBits(0) == U64A)
# check for undefined behavior with rotate by integer width.
doAssert( U8.rotateLeftBits(8) == U8)
doAssert( U8.rotateRightBits(8) == U8)
doAssert( U16.rotateLeftBits(16) == U16)
doAssert( U16.rotateRightBits(16) == U16)
doAssert( U32.rotateLeftBits(32) == U32)
doAssert( U32.rotateRightBits(32) == U32)
doAssert( U64A.rotateLeftBits(64) == U64A)
doAssert( U64A.rotateRightBits(64) == U64A)
echo "OK"
main2()

View file

@ -1,167 +0,0 @@
discard """
output: "OK"
"""
import bitops
proc main() =
const U8 = 0b0011_0010'u8
const I8 = 0b0011_0010'i8
const U16 = 0b00100111_00101000'u16
const I16 = 0b00100111_00101000'i16
const U32 = 0b11010101_10011100_11011010_01010000'u32
const I32 = 0b11010101_10011100_11011010_01010000'i32
const U64A = 0b01000100_00111111_01111100_10001010_10011001_01001000_01111010_00010001'u64
const I64A = 0b01000100_00111111_01111100_10001010_10011001_01001000_01111010_00010001'i64
const U64B = 0b00110010_11011101_10001111_00101000_00000000_00000000_00000000_00000000'u64
const I64B = 0b00110010_11011101_10001111_00101000_00000000_00000000_00000000_00000000'i64
doAssert( U64A.fastLog2 == 62)
doAssert( I64A.fastLog2 == 62)
doAssert( U64A.countLeadingZeroBits == 1)
doAssert( I64A.countLeadingZeroBits == 1)
doAssert( U64A.countTrailingZeroBits == 0)
doAssert( I64A.countTrailingZeroBits == 0)
doAssert( U64A.firstSetBit == 1)
doAssert( I64A.firstSetBit == 1)
doAssert( U64A.parityBits == 1)
doAssert( I64A.parityBits == 1)
doAssert( U64A.countSetBits == 29)
doAssert( I64A.countSetBits == 29)
doAssert( U64A.rotateLeftBits(37) == 0b00101001_00001111_01000010_00101000_10000111_11101111_10010001_01010011'u64)
doAssert( U64A.rotateRightBits(37) == 0b01010100_11001010_01000011_11010000_10001010_00100001_11111011_11100100'u64)
doAssert( U64B.firstSetBit == 36)
doAssert( I64B.firstSetBit == 36)
doAssert( U32.fastLog2 == 31)
doAssert( I32.fastLog2 == 31)
doAssert( U32.countLeadingZeroBits == 0)
doAssert( I32.countLeadingZeroBits == 0)
doAssert( U32.countTrailingZeroBits == 4)
doAssert( I32.countTrailingZeroBits == 4)
doAssert( U32.firstSetBit == 5)
doAssert( I32.firstSetBit == 5)
doAssert( U32.parityBits == 0)
doAssert( I32.parityBits == 0)
doAssert( U32.countSetBits == 16)
doAssert( I32.countSetBits == 16)
doAssert( U32.rotateLeftBits(21) == 0b01001010_00011010_10110011_10011011'u32)
doAssert( U32.rotateRightBits(21) == 0b11100110_11010010_10000110_10101100'u32)
doAssert( U16.fastLog2 == 13)
doAssert( I16.fastLog2 == 13)
doAssert( U16.countLeadingZeroBits == 2)
doAssert( I16.countLeadingZeroBits == 2)
doAssert( U16.countTrailingZeroBits == 3)
doAssert( I16.countTrailingZeroBits == 3)
doAssert( U16.firstSetBit == 4)
doAssert( I16.firstSetBit == 4)
doAssert( U16.parityBits == 0)
doAssert( I16.parityBits == 0)
doAssert( U16.countSetBits == 6)
doAssert( I16.countSetBits == 6)
doAssert( U16.rotateLeftBits(12) == 0b10000010_01110010'u16)
doAssert( U16.rotateRightBits(12) == 0b01110010_10000010'u16)
doAssert( U8.fastLog2 == 5)
doAssert( I8.fastLog2 == 5)
doAssert( U8.countLeadingZeroBits == 2)
doAssert( I8.countLeadingZeroBits == 2)
doAssert( U8.countTrailingZeroBits == 1)
doAssert( I8.countTrailingZeroBits == 1)
doAssert( U8.firstSetBit == 2)
doAssert( I8.firstSetBit == 2)
doAssert( U8.parityBits == 1)
doAssert( I8.parityBits == 1)
doAssert( U8.countSetBits == 3)
doAssert( I8.countSetBits == 3)
doAssert( U8.rotateLeftBits(3) == 0b10010001'u8)
doAssert( U8.rotateRightBits(3) == 0b0100_0110'u8)
static :
# test bitopts at compile time with vm
doAssert( U8.fastLog2 == 5)
doAssert( I8.fastLog2 == 5)
doAssert( U8.countLeadingZeroBits == 2)
doAssert( I8.countLeadingZeroBits == 2)
doAssert( U8.countTrailingZeroBits == 1)
doAssert( I8.countTrailingZeroBits == 1)
doAssert( U8.firstSetBit == 2)
doAssert( I8.firstSetBit == 2)
doAssert( U8.parityBits == 1)
doAssert( I8.parityBits == 1)
doAssert( U8.countSetBits == 3)
doAssert( I8.countSetBits == 3)
doAssert( U8.rotateLeftBits(3) == 0b10010001'u8)
doAssert( U8.rotateRightBits(3) == 0b0100_0110'u8)
template test_undefined_impl(ffunc: untyped; expected: int; is_static: bool) =
doAssert( ffunc(0'u8) == expected)
doAssert( ffunc(0'i8) == expected)
doAssert( ffunc(0'u16) == expected)
doAssert( ffunc(0'i16) == expected)
doAssert( ffunc(0'u32) == expected)
doAssert( ffunc(0'i32) == expected)
doAssert( ffunc(0'u64) == expected)
doAssert( ffunc(0'i64) == expected)
template test_undefined(ffunc: untyped; expected: int) =
test_undefined_impl(ffunc, expected, false)
static:
test_undefined_impl(ffunc, expected, true)
when defined(noUndefinedBitOpts):
# check for undefined behavior with zero.
test_undefined(countSetBits, 0)
test_undefined(parityBits, 0)
test_undefined(firstSetBit, 0)
test_undefined(countLeadingZeroBits, 0)
test_undefined(countTrailingZeroBits, 0)
test_undefined(fastLog2, -1)
# check for undefined behavior with rotate by zero.
doAssert( U8.rotateLeftBits(0) == U8)
doAssert( U8.rotateRightBits(0) == U8)
doAssert( U16.rotateLeftBits(0) == U16)
doAssert( U16.rotateRightBits(0) == U16)
doAssert( U32.rotateLeftBits(0) == U32)
doAssert( U32.rotateRightBits(0) == U32)
doAssert( U64A.rotateLeftBits(0) == U64A)
doAssert( U64A.rotateRightBits(0) == U64A)
# check for undefined behavior with rotate by integer width.
doAssert( U8.rotateLeftBits(8) == U8)
doAssert( U8.rotateRightBits(8) == U8)
doAssert( U16.rotateLeftBits(16) == U16)
doAssert( U16.rotateRightBits(16) == U16)
doAssert( U32.rotateLeftBits(32) == U32)
doAssert( U32.rotateRightBits(32) == U32)
doAssert( U64A.rotateLeftBits(64) == U64A)
doAssert( U64A.rotateRightBits(64) == U64A)
static: # check for undefined behavior with rotate by zero.
doAssert( U8.rotateLeftBits(0) == U8)
doAssert( U8.rotateRightBits(0) == U8)
doAssert( U16.rotateLeftBits(0) == U16)
doAssert( U16.rotateRightBits(0) == U16)
doAssert( U32.rotateLeftBits(0) == U32)
doAssert( U32.rotateRightBits(0) == U32)
doAssert( U64A.rotateLeftBits(0) == U64A)
doAssert( U64A.rotateRightBits(0) == U64A)
# check for undefined behavior with rotate by integer width.
doAssert( U8.rotateLeftBits(8) == U8)
doAssert( U8.rotateRightBits(8) == U8)
doAssert( U16.rotateLeftBits(16) == U16)
doAssert( U16.rotateRightBits(16) == U16)
doAssert( U32.rotateLeftBits(32) == U32)
doAssert( U32.rotateRightBits(32) == U32)
doAssert( U64A.rotateLeftBits(64) == U64A)
doAssert( U64A.rotateRightBits(64) == U64A)
echo "OK"
main()

View file

@ -1,2 +0,0 @@
-d:noIntrinsicsBitOpts
-d:noUndefinedBitOps

View file

@ -41,6 +41,6 @@ when manualTest:
frexp_test(-1000.0, 1000.0, 0.0125)
else:
frexp_test(-1000000.0, 1000000.0, 0.125)
frexp_test(-200000.0, 200000.0, 0.125)
echo "ok"

View file

@ -1,37 +0,0 @@
discard """
outputsub: ""
"""
# output not testable because repr prints pointer addresses
# test the new "repr" built-in proc
type
TEnum = enum
en1, en2, en3, en4, en5, en6
TPoint {.final.} = object
x, y, z: int
s: array[0..1, string]
e: TEnum
var
p: TPoint
q: ref TPoint
s: seq[ref TPoint]
p.x = 0
p.y = 13
p.z = 45
p.s[0] = "abc"
p.s[1] = "xyz"
p.e = en6
new(q)
q[] = p
s = @[q, q, q, q]
writeLine(stdout, repr(p))
writeLine(stdout, repr(q))
writeLine(stdout, repr(s))
writeLine(stdout, repr(en4))

View file

@ -1,11 +1,16 @@
discard """
input: "Arne"
output: '''
input: "Arne"
output: '''
Hello! What is your name?
Nice name: Arne
fs is: nil
threw exception
'''
nimout: '''
I
AM
GROOT
'''
disabled: "windows"
"""
@ -38,3 +43,9 @@ block tstreams3:
var fs = openFileStream("shouldneverexist.txt")
except IoError:
echo "threw exception"
static:
var s = newStringStream("I\nAM\nGROOT")
for line in s.lines:
echo line
s.close

View file

@ -1,12 +0,0 @@
discard """
output: '''fs is: nil'''
"""
import streams
var
fs = newFileStream("amissingfile.txt")
line = ""
echo "fs is: ",repr(fs)
if not isNil(fs):
while fs.readLine(line):
echo line
fs.close()

View file

@ -1,20 +0,0 @@
discard """
output: "threw exception"
nimout: '''
I
AM
GROOT
'''
"""
import streams
try:
var fs = openFileStream("shouldneverexist.txt")
except IoError:
echo "threw exception"
static:
var s = newStringStream("I\nAM\nGROOT")
for line in s.lines:
echo line
s.close

View file

@ -309,7 +309,7 @@ suite "ttimes":
check dt.nanosecond == convert(Milliseconds, Nanoseconds, 1)
check d(seconds = 1, milliseconds = 500) * 2 == d(seconds = 3)
check d(seconds = 3) div 2 == d(seconds = 1, milliseconds = 500)
check d(milliseconds = 1001).seconds == 1
check d(milliseconds = 1001).inSeconds == 1
check d(seconds = 1, milliseconds = 500) - d(milliseconds = 1250) ==
d(milliseconds = 250)
check d(seconds = 1, milliseconds = 1) < d(seconds = 1, milliseconds = 2)
@ -504,12 +504,6 @@ suite "ttimes":
check $parse("02 Fir 2019", "dd MMM yyyy", utc(), loc) == "2019-01-02T00:00:00Z"
check $parse("Fourthy 6, 2017", "MMMM d, yyyy", utc(), loc) == "2017-04-06T00:00:00Z"
test "countLeapYears":
# 1920, 2004 and 2020 are leap years, and should be counted starting at the following year
check countLeapYears(1920) + 1 == countLeapYears(1921)
check countLeapYears(2004) + 1 == countLeapYears(2005)
check countLeapYears(2020) + 1 == countLeapYears(2021)
test "timezoneConversion":
var l = now()
let u = l.utc

View file

@ -11,12 +11,12 @@ const BUFFER_SIZE = 5000
var buffer = cast[ptr uint16](alloc(BUFFER_SIZE))
var total_size: int64 = 0
for i in 0 .. 4000:
let size = BUFFER_SIZE * i
#echo "requesting ", size
total_size += size.int64
buffer = cast[ptr uint16](realloc(buffer, size))
#echo totalSize, " total: ", getTotalMem(), " occupied: ", getOccupiedMem(), " free: ", getFreeMem()
for i in 0 .. 1000:
let size = BUFFER_SIZE * i
#echo "requesting ", size
total_size += size.int64
buffer = cast[ptr uint16](realloc(buffer, size))
#echo totalSize, " total: ", getTotalMem(), " occupied: ", getOccupiedMem(), " free: ", getFreeMem()
dealloc(buffer)
echo "success"

View file

@ -22,7 +22,7 @@ import asyncdispatch
import threadpool
proc f1() =
waitFor sleepAsync(100)
waitFor sleepAsync(20)
echo "hello"
spawn f1()

View file

@ -12,7 +12,7 @@ type
const
ThreadsCount = 129
SleepTime = 1000
SleepTime = 250
proc worker(p: Marker) {.thread.} =
acquire(p.lock)

View file

@ -1,8 +1,8 @@
discard """
outputsub: "129"
outputsub: "65"
"""
import os, locks
import locks
type
MarkerObj = object
@ -11,7 +11,7 @@ type
Marker = ptr MarkerObj
const
ThreadsCount = 129
ThreadsCount = 65
proc worker(p: Marker) {.thread.} =
acquire(p.lock)

View file

@ -1,51 +0,0 @@
discard """
errormsg: "'threadFunc' is not GC-safe"
file: "tthreadanalysis2.nim"
line: 37
cmd: "nim $target --hints:on --threads:on $options $file"
"""
import os
var
thr: array[0..5, Thread[tuple[a, b: int]]]
proc doNothing() = discard
type
PNode = ref TNode
TNode = object {.pure.}
le, ri: PNode
data: string
var
root: PNode
proc buildTree(depth: int): PNode =
if depth == 3: return nil
new(result)
result.le = buildTree(depth-1)
result.ri = buildTree(depth-1)
result.data = $depth
proc echoLeTree(n: PNode) =
var it = n
while it != nil:
echo it.data
it = it.le
proc threadFunc(interval: tuple[a, b: int]) {.thread.} =
doNothing()
for i in interval.a..interval.b:
var r = buildTree(i)
echoLeTree(r) # for local data
root = buildTree(2) # BAD!
#echoLeTree(root) # and the same for foreign data :-)
proc main =
root = buildTree(5)
for i in 0..high(thr):
createThread(thr[i], threadFunc, (i*100, i*100+50))
joinThreads(thr)
main()

View file

@ -11,7 +11,7 @@ type PComm = ptr Channel[int]
proc doAction(outC: PComm) {.thread.} =
for i in 0 ..< 5:
sleep(rand(100))
sleep(rand(50))
send(outC[], i)
var