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 doAssert cmd.len == 0, cmd # avoid silently ignoring
echo "runCI: ", cmd echo "runCI: ", cmd
echo hostInfo() 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 # boot without -d:nimHasLibFFI to make sure this still works
kochExecFold("Boot in release mode", "boot -d:release") kochExecFold("Boot in release mode", "boot -d:release")
@ -494,7 +490,7 @@ proc runCI(cmd: string) =
if getEnv("NIM_TEST_PACKAGES", "false") == "true": if getEnv("NIM_TEST_PACKAGES", "false") == "true":
execFold("Test selected Nimble packages", "nim c -r testament/testament cat nimble-packages") execFold("Test selected Nimble packages", "nim c -r testament/testament cat nimble-packages")
else: else:
buildTools() # altenatively, kochExec "tools --toolsNoNimble" buildTools()
## run tests ## run tests
execFold("Test nimscript", "nim e tests/test_nimscript.nims") execFold("Test nimscript", "nim e tests/test_nimscript.nims")
@ -504,7 +500,7 @@ proc runCI(cmd: string) =
# main bottleneck here # main bottleneck here
execFold("Run tester", "nim c -r -d:nimCoroutines testament/testament --pedantic all -d:nimCoroutines") 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 when defined(posix): # windows can be handled in future PR's
execFold("nimble install -y libffi", "nimble install -y libffi") execFold("nimble install -y libffi", "nimble install -y libffi")
const nimFFI = "./bin/nim.ctffi" const nimFFI = "./bin/nim.ctffi"
@ -517,15 +513,6 @@ proc runCI(cmd: string) =
when defined(posix): when defined(posix):
execFold("Run nimsuggest tests", "nim c -r nimsuggest/tester") 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() = proc pushCsources() =
if not dirExists("../csources/.git"): if not dirExists("../csources/.git"):
quit "[Error] no csources git repository found" quit "[Error] no csources git repository found"

View file

@ -169,16 +169,8 @@ proc dllTests(r: var TResults, cat: Category, options: string) =
# ------------------------------ GC tests ------------------------------------- # ------------------------------ GC tests -------------------------------------
proc gcTests(r: var TResults, cat: Category, options: string) = 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) = template testWithoutMs(filename: untyped) =
testSpec r, makeTest("tests/gc" / filename, options, cat) 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 & testSpec r, makeTest("tests/gc" / filename, options &
" -d:release -d:useRealtimeGC", cat) " -d:release -d:useRealtimeGC", cat)
when filename != "gctest": when filename != "gctest":
@ -193,6 +185,7 @@ proc gcTests(r: var TResults, cat: Category, options: string) =
" --gc:markAndSweep", cat) " --gc:markAndSweep", cat)
testSpec r, makeTest("tests/gc" / filename, options & testSpec r, makeTest("tests/gc" / filename, options &
" -d:release --gc:markAndSweep", cat) " -d:release --gc:markAndSweep", cat)
template test(filename: untyped) = template test(filename: untyped) =
testWithoutBoehm filename testWithoutBoehm filename
when not defined(windows) and not defined(android): when not defined(windows) and not defined(android):
@ -210,7 +203,6 @@ proc gcTests(r: var TResults, cat: Category, options: string) =
test "gcleak" test "gcleak"
test "gcleak2" test "gcleak2"
testWithoutBoehm "gctest" testWithoutBoehm "gctest"
testWithNone "gctest"
test "gcleak3" test "gcleak3"
test "gcleak4" test "gcleak4"
# Disabled because it works and takes too long to run: # 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 let success = if test.spec.timeout > 0.0 and duration > test.spec.timeout: reTimeout
else: successOrig else: successOrig
let durationStr = duration.formatFloat(ffDecimal, precision = 8).align(11) let durationStr = duration.formatFloat(ffDecimal, precision = 2).align(5)
if backendLogging: if backendLogging:
backend.writeTestResult(name = name, backend.writeTestResult(name = name,
category = test.cat.string, category = test.cat.string,
@ -271,7 +271,7 @@ proc addResult(r: var TResults, test: TTest, target: TTarget,
given = given) given = given)
r.data.addf("$#\t$#\t$#\t$#", name, expected, given, $success) r.data.addf("$#\t$#\t$#\t$#", name, expected, given, $success)
if success == reSuccess: 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: elif success == reDisabled:
maybeStyledEcho styleDim, fgYellow, "SKIP: ", styleBright, fgCyan, name maybeStyledEcho styleDim, fgYellow, "SKIP: ", styleBright, fgCyan, name
elif success == reJoined: elif success == reJoined:

View file

@ -1,45 +1,30 @@
discard """ discard """
output: ''' output: '''
test1:ok `false` first assertion from bar
test2:ok `false` second assertion from bar
test3:ok
test4:ok
test5:ok
test6:ok
test7:ok
-1 -1
tassert2.nim
test8:ok
test9:ok
test10:ok
test11:ok
''' '''
""" """
import testhelper from strutils import endsWith
type type
TLineInfo = tuple[filename: string, line: int, column: int] TLineInfo = tuple[filename: string, line: int, column: int]
TMyError = object of Exception TMyError = object of Exception
lineinfo: TLineInfo lineinfo: TLineInfo
EMyError = ref TMyError EMyError = ref TMyError
echo("")
# NOTE: when entering newlines, adjust `expectedEnd` outputs # NOTE: when entering newlines, adjust `expectedEnd` outputs
try: try:
doAssert(false, "msg1") # doAssert test doAssert(false, "msg1") # doAssert test
except AssertionError as e: except AssertionError as e:
checkMsg(e.msg, "tassert2.nim(30, 11) `false` msg1", "test1") assert e.msg.endsWith "tassert2.nim(20, 11) `false` msg1"
try:
assert false, "msg2" # assert test
except AssertionError as e:
checkMsg(e.msg, "tassert2.nim(35, 10) `false` msg2", "test2")
try: try:
assert false # assert test with no msg assert false # assert test with no msg
except AssertionError as e: except AssertionError as e:
checkMsg(e.msg, "tassert2.nim(40, 10) `false` ", "test3") assert e.msg.endsWith "tassert2.nim(25, 10) `false` "
try: try:
let a = 1 let a = 1
@ -47,13 +32,13 @@ try:
# BUG: const folding would make "1+1==1" appear as `false` in # BUG: const folding would make "1+1==1" appear as `false` in
# assert message # assert message
except AssertionError as e: except AssertionError as e:
checkMsg(e.msg, "`a + a == 1` ", "test4") assert e.msg.endsWith "`a + a == 1` "
try: try:
let a = 1 let a = 1
doAssert a+a==1 # ditto with `doAssert` and no parens doAssert a+a==1 # ditto with `doAssert` and no parens
except AssertionError as e: except AssertionError as e:
checkMsg(e.msg, "`a + a == 1` ", "test5") assert e.msg.endsWith "`a + a == 1` "
proc fooStatic() = proc fooStatic() =
# protect against https://github.com/nim-lang/Nim/issues/8758 # protect against https://github.com/nim-lang/Nim/issues/8758
@ -80,12 +65,12 @@ block:
proc bar: int = proc bar: int =
# local overrides that are active only in this proc # local overrides that are active only in this proc
onFailedAssert(msg): onFailedAssert(msg):
checkMsg(msg, "tassert2.nim(85, 11) `false` first assertion from bar", "test6") echo msg[^32..^1]
assert(false, "first assertion from bar") assert(false, "first assertion from bar")
onFailedAssert(msg): onFailedAssert(msg):
checkMsg(msg, "tassert2.nim(91, 11) `false` second assertion from bar", "test7") echo msg[^33..^1]
return -1 return -1
assert(false, "second assertion from bar") assert(false, "second assertion from bar")
@ -97,8 +82,7 @@ block:
foo() foo()
except: except:
let e = EMyError(getCurrentException()) let e = EMyError(getCurrentException())
echo e.lineinfo.filename assert e.msg.endsWith "tassert2.nim(62, 11) `false` assertion from foo"
checkMsg(e.msg, "tassert2.nim(77, 11) `false` assertion from foo", "test8")
block: ## checks for issue https://github.com/nim-lang/Nim/issues/8518 block: ## checks for issue https://github.com/nim-lang/Nim/issues/8518
template fun(a: string): string = 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" doAssert fun("foo1") == fun("foo2"), "mymsg"
except AssertionError as e: except AssertionError as e:
# used to expand out the template instantiaiton, sometimes filling hundreds of lines # 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 block: ## checks for issue https://github.com/nim-lang/Nim/issues/9301
try: try:
doAssert 1 + 1 == 3 doAssert 1 + 1 == 3
except AssertionError as e: except AssertionError as e:
# used to const fold as false # 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 block: ## checks AST isn't transformed as it used to
let a = 1 let a = 1
@ -124,4 +108,4 @@ block: ## checks AST isn't transformed as it used to
doAssert a > 1 doAssert a > 1
except AssertionError as e: except AssertionError as e:
# used to rewrite as `1 < a` # 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 import asyncdispatch, os, times
proc doubleSleep(hardSleep: int) {.async.} = proc doubleSleep(hardSleep: int) {.async.} =
await sleepAsync(100) await sleepAsync(50)
sleep(hardSleep) sleep(hardSleep)
template assertTime(target, timeTook: float): untyped {.dirty.} = template assertTime(target, timeTook: float): untyped {.dirty.} =
@ -16,37 +16,25 @@ var
# NOTE: this uses poll(3000) to limit timing error potential. # NOTE: this uses poll(3000) to limit timing error potential.
start = epochTime() start = epochTime()
fut = sleepAsync(50) and sleepAsync(150) and doubleSleep(40) fut = sleepAsync(40) and sleepAsync(100) and doubleSleep(20)
while not fut.finished: while not fut.finished:
poll(3000) poll(1000)
assertTime(150, epochTime() - start) assertTime(150, epochTime() - start)
start = epochTime() start = epochTime()
fut = sleepAsync(50) and sleepAsync(150) and doubleSleep(100) fut = sleepAsync(40) and sleepAsync(100) and doubleSleep(50)
while not fut.finished: while not fut.finished:
poll(3000) poll(1000)
assertTime(200, epochTime() - start) assertTime(200, epochTime() - start)
start = epochTime() 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: while not fut.finished:
poll(3000) poll(1000)
assertTime(300, epochTime() - start) assertTime(300, epochTime() - start)
start = epochTime() 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: while not fut.finished:
poll(3000) poll(1000)
assertTime(300, epochTime() - start)
start = epochTime()
fut = (sleepAsync(50) and sleepAsync(150) and doubleSleep(40)) or sleepAsync(700)
while not fut.finished:
poll(3000)
assertTime(150, epochTime() - start) 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 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) done.complete(1)
proc asyncSum: Future[int] {.async.} = proc asyncSum: Future[int] {.async.} =
for _ in 1..10_000_000: for _ in 1..1_000_000:
result += await done result += await done
let res = waitFor asyncSum() let res = waitFor asyncSum()
doAssert(res == 10000000) doAssert(res == 1_000_000)
block: #7985 block: #7985
proc getData(): Future[JsonNode] {.async.} = proc getData(): Future[JsonNode] {.async.} =

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -7,7 +7,7 @@ import asyncdispatch
doAssert(not hasPendingOperations()) doAssert(not hasPendingOperations())
proc test() {.async.} = proc test() {.async.} =
await sleepAsync(100) await sleepAsync(50)
var f = test() var f = test()
while not f.finished: 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}) = proc map(n: var openarray[int], fn: proc (x: int): int {.closure}) =
for i in 0..n.len-1: n[i] = fn(n[i]) 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.}) = proc each(n: openarray[int], fn: proc(x: int) {.closure.}) =
for i in 0..n.len-1: for i in 0..n.len-1:
fn(n[i]) fn(n[i])
@ -67,18 +63,6 @@ block tclosure:
#OUT 2 4 6 8 10 #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 # bug #5015
type Mutator = proc(matched: string): string {.noSideEffect, gcsafe, locks: 0.} type Mutator = proc(matched: string): string {.noSideEffect, gcsafe, locks: 0.}
@ -180,7 +164,7 @@ block tclosure0:
block tclosure3: block tclosure3:
proc main = proc main =
const n = 30 const n = 30
for iterations in 0..50_000: for iterations in 0..10_000:
var s: seq[proc(): string {.closure.}] = @[] var s: seq[proc(): string {.closure.}] = @[]
for i in 0 .. n-1: for i in 0 .. n-1:
(proc () = (proc () =
@ -203,210 +187,12 @@ block tclosure4:
let json_elems = json_params["files"].elems let json_elems = json_params["files"].elems
# These fail compilation. # These fail compilation.
var files = map(json_elems, proc (x: JsonNode): string = x.str) 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"]}""" let text = """{"files": ["a", "b", "c"]}"""
run((text.parseJson).fields) 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 import sugar
block inference3304: block inference3304:
type type
@ -513,7 +299,7 @@ block tflatmap:
let g: A -> Rand[B] = (a: A) => ((rng: RNG) => (f(a), rng)) let g: A -> Rand[B] = (a: A) => ((rng: RNG) => (f(a), rng))
flatMap(s, g) 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: "" output: ""
""" """
import deques, sequtils import sets, tables, deques, lists, critbits, sequtils
block tapply: block tapply:
@ -52,3 +52,109 @@ block tmapit:
# since ``len`` is not available # since ``len`` is not available
var r = st.mapIt($(it+10)) var r = st.mapIt($(it+10))
doAssert r == @["10", "11", "12", "13", "14"] 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: block ttables2:
proc TestHashIntInt() = proc TestHashIntInt() =
var tab = initTable[int,int]() var tab = initTable[int,int]()
when defined(nimTestsTablesDisableSlow): let n = 100_000
# helps every single time when this test needs to be debugged
let n = 1_000
else:
let n = 1_000_000
for i in 1..n: for i in 1..n:
tab[i] = i tab[i] = i
for i in 1..n: for i in 1..n:
var x = tab[i] var x = tab[i]
if x != i : echo "not found ", i if x != i : echo "not found ", i
proc run1() = # occupied Memory stays constant, but proc run1() =
for i in 1 .. 50: # aborts at run: 44 on win32 with 3.2GB with out of memory for i in 1 .. 50:
TestHashIntInt() TestHashIntInt()
# bug #2107 # bug #2107

View file

@ -1,7 +1,7 @@
discard """ discard """
cmd: '''nim c -d:nimAllocStats --newruntime $file''' cmd: '''nim c -d:nimAllocStats --newruntime $file'''
output: '''331665 output: '''31665
(allocCount: 333335, deallocCount: 333335)''' (allocCount: 33335, deallocCount: 33335)'''
""" """
# bug #11053 # bug #11053
@ -72,7 +72,7 @@ proc main() =
cur = 5'i32 cur = 5'i32
res = 0 res = 0
for i in 1 ..< 1000000: for i in 1 ..< 100000:
let a = i mod 3 let a = i mod 3
cur = (cur * 57 + 43) mod 10007 cur = (cur * 57 + 43) mod 10007
case a: 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 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] var s: array[0..11, ref TExpr]
for j in 0..high(s): for j in 0..high(s):
s[j] = newPlus(newPlus(newLit(j), newLit(2)), newLit(4)) s[j] = newPlus(newPlus(newLit(j), newLit(2)), newLit(4))

View file

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

View file

@ -1,13 +1,13 @@
discard """ discard """
output: '''Welcome to LoopTesterApp, Nim edition output: '''Welcome to LoopTesterApp, Nim edition
Constructing Simple CFG... Constructing Simple CFG...
15000 dummy loops 5000 dummy loops
Constructing CFG... Constructing CFG...
Performing Loop Recognition Performing Loop Recognition
1 Iteration 1 Iteration
Another 5 iterations... Another 3 iterations...
..... ...
Found 1 loops (including artificial root node) (5)''' Found 1 loops (including artificial root node) (3)'''
""" """
# bug #3184 # bug #3184
@ -384,9 +384,9 @@ proc run(self: var LoopTesterApp) =
discard self.cfg.createNode(1) discard self.cfg.createNode(1)
self.buildConnect(0, 2) self.buildConnect(0, 2)
echo "15000 dummy loops" echo "5000 dummy loops"
for i in 1..15000: for i in 1..5000:
withScratchRegion: withScratchRegion:
var h = newHavlakLoopFinder(self.cfg, newLsg()) var h = newHavlakLoopFinder(self.cfg, newLsg())
discard h.findLoops discard h.findLoops
@ -414,10 +414,10 @@ proc run(self: var LoopTesterApp) =
var h = newHavlakLoopFinder(self.cfg, newLsg()) var h = newHavlakLoopFinder(self.cfg, newLsg())
var loops = h.findLoops var loops = h.findLoops
echo "Another 5 iterations..." echo "Another 3 iterations..."
var sum = 0 var sum = 0
for i in 1..5: for i in 1..3:
withScratchRegion: withScratchRegion:
write stdout, "." write stdout, "."
flushFile(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]() result.root = newLeaf[M, D, RT, LT]()
proc center(r: Box): auto =#BoxCenter[r.len, type(r[0].a)] = 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: for i in 0 .. r.high:
when r[0].a is SomeInteger: 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: 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 else: assert false
return result return res
proc distance(c1, c2: BoxCenter): auto = proc distance(c1, c2: BoxCenter): auto =
var result: type(c1[0]) var res: type(c1[0])
for i in 0 .. c1.high: for i in 0 .. c1.high:
result += (c1[i] - c2[i]) * (c1[i] - c2[i]) res += (c1[i] - c2[i]) * (c1[i] - c2[i])
return result return res
proc overlap(r1, r2: Box): auto = proc overlap(r1, r2: Box): auto =
result = type(r1[0].a)(1) 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 n = nn.a[i0].n
return 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) = 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 i0, j0: int
var bi, bj: type(bx) 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 nn = nil
else: else:
let h: N[M, D, RT, LT] = (b, nn) let h: N[M, D, RT, LT] = (b, nn)
if t of RStarTree[M, D, RT, LT]: nn = quadraticSplit(t, p, h)
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
assert n == H[M, D, RT, LT](p) assert n == H[M, D, RT, LT](p)
assert n != nil assert n != nil
assert t.root != 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) rsinsert(RStarTree[M, D, RT, LT](t), Node[M, D, RT, LT](n).a[i], n.level)
else: else:
assert false assert false
elif t of RTree[M, D, RT, LT]: else:
for n in q: for n in q:
if n of Leaf[M, D, RT, LT]: if n of Leaf[M, D, RT, LT]:
for i in 0 ..< n.numEntries: 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]: elif n of Node[M, D, RT, LT]:
for i in 0 ..< n.numEntries: 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: else:
assert false 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.} = 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) let l = findLeaf(t, leaf)
@ -659,6 +637,4 @@ proc test(n: int) =
assert r.len == r2.len assert r.len == r2.len
assert r.sorted(system.cmp) == r2.sorted(system.cmp) assert r.sorted(system.cmp) == r2.sorted(system.cmp)
test(1500) test(500)
# 651 lines

View file

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

View file

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

View file

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

View file

@ -25,11 +25,11 @@ proc emitter() =
spawn emitter() spawn emitter()
# At this point emitter should be stuck in `send` # 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) doAssert(not msgSent)
spawn receiver() 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(msgSent) # Sender should be unblocked
doAssert(chan.trySend(4)) 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) ul[k] = spawn half[T](points, k == 0)
result = concat(^ul[0], ^ul[1]) 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 # 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. # worker thread that executes our spawned task, before we can read the flowvars.
setMaxPoolSize 2 setMaxPoolSize 2
#echo convex_hull[Point](s, cmpPoint) for i in 0..2:
for i in 0..5:
doAssert convex_hull[Point](s, cmpPoint) == 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 """ discard """
output: '''13 abc''' output: '''
13 abc
called deepCopy for int
called deepCopy for int
done999 999
'''
""" """
type import threadpool
PBinaryTree = ref object
le, ri: PBinaryTree block one:
value: int 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 = block two:
var x: PBinaryTree type
deepCopy(x, PBinaryTree(ri: PBinaryTree(le: PBinaryTree(value: 13)))) Bar[T] = object
var y: string x: T
deepCopy y, "abc"
echo x.ri.le.value, " ", y
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 """ discard """
output: '''called deepCopy for int output: '''
called deepCopy for int called deepCopy for int
done999 999''' called deepCopy for int
done999 999
'''
""" """
import threadpool import threadpool

View file

@ -2,20 +2,49 @@ discard """
outputsub: "EVEN 28" outputsub: "EVEN 28"
""" """
import threadpool import threadpool, locks
proc odd(a: int) = echo "ODD ", a block one:
proc even(a: int) = echo "EVEN ", a proc odd(a: int) = echo "ODD ", a
proc even(a: int) = echo "EVEN ", a
proc main() = proc main() =
var a: array[0..30, int] var a: array[0..30, int]
for i in low(a)..high(a): a[i] = i for i in low(a)..high(a): a[i] = i
parallel: parallel:
var i = 0 var i = 0
while i <= 29: while i <= 29:
spawn even(a[i]) spawn even(a[i])
spawn odd(a[i+1]) spawn odd(a[i+1])
inc i, 2 inc i, 2
# is correct here # 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),") }" " friend:", p.friend.name, "(", cast[int](addr p.friend.name),") }"
proc setup = proc setup =
for i in 0 ..< 20: for i in 0 ..< 10:
people.add newPerson("Person" & $(i + 1)) people.add newPerson("Person" & $(i + 1))
for i in 0 ..< 20: for i in 0 ..< 10:
people[i].friend = people[19-i] people[i].friend = people[9-i]
proc update = proc update =
parallel: parallel:

View file

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

View file

@ -3,7 +3,7 @@ discard """
""" """
# bug #7638 # bug #7638
import threadpool, os, strformat import threadpool, os
proc timer(d: int): int = proc timer(d: int): int =
#echo fmt"sleeping {d}" #echo fmt"sleeping {d}"
@ -11,7 +11,7 @@ proc timer(d: int): int =
#echo fmt"done {d}" #echo fmt"done {d}"
return d return d
var durations = [1000, 1500, 2000, 2500, 3000] var durations = [1000, 1500, 2000]
var tasks: seq[FlowVarBase] = @[] var tasks: seq[FlowVarBase] = @[]
var results: seq[int] = @[] var results: seq[int] = @[]
@ -25,11 +25,9 @@ while index != -1:
#echo repr results #echo repr results
index = blockUntilAny(tasks) index = blockUntilAny(tasks)
doAssert results.len == 5 doAssert results.len == 3
doAssert 1000 in results doAssert 1000 in results
doAssert 1500 in results doAssert 1500 in results
doAssert 2000 in results doAssert 2000 in results
doAssert 2500 in results
doAssert 3000 in results
sync() sync()
echo "true" 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 """ discard """
nimout: "OK" nimout: "OK"
output: "OK" output: '''
OK
OK
'''
""" """
import bitops import bitops
proc main() = proc main1() =
const U8 = 0b0011_0010'u8 const U8 = 0b0011_0010'u8
const I8 = 0b0011_0010'i8 const I8 = 0b0011_0010'i8
const U16 = 0b00100111_00101000'u16 const U16 = 0b00100111_00101000'u16
@ -261,7 +264,172 @@ block: # not ready for vm because exception is compile error
doAssert false doAssert false
main() main1()
static: static:
# test everything on vm as well # 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) frexp_test(-1000.0, 1000.0, 0.0125)
else: else:
frexp_test(-1000000.0, 1000000.0, 0.125) frexp_test(-200000.0, 200000.0, 0.125)
echo "ok" 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 """ discard """
input: "Arne" input: "Arne"
output: ''' output: '''
Hello! What is your name? Hello! What is your name?
Nice name: Arne Nice name: Arne
fs is: nil fs is: nil
threw exception threw exception
'''
nimout: '''
I
AM
GROOT
''' '''
disabled: "windows" disabled: "windows"
""" """
@ -38,3 +43,9 @@ block tstreams3:
var fs = openFileStream("shouldneverexist.txt") var fs = openFileStream("shouldneverexist.txt")
except IoError: except IoError:
echo "threw exception" 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 dt.nanosecond == convert(Milliseconds, Nanoseconds, 1)
check d(seconds = 1, milliseconds = 500) * 2 == d(seconds = 3) check d(seconds = 1, milliseconds = 500) * 2 == d(seconds = 3)
check d(seconds = 3) div 2 == d(seconds = 1, milliseconds = 500) 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) == check d(seconds = 1, milliseconds = 500) - d(milliseconds = 1250) ==
d(milliseconds = 250) d(milliseconds = 250)
check d(seconds = 1, milliseconds = 1) < d(seconds = 1, milliseconds = 2) 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("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" 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": test "timezoneConversion":
var l = now() var l = now()
let u = l.utc let u = l.utc

View file

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

View file

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

View file

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

View file

@ -1,8 +1,8 @@
discard """ discard """
outputsub: "129" outputsub: "65"
""" """
import os, locks import locks
type type
MarkerObj = object MarkerObj = object
@ -11,7 +11,7 @@ type
Marker = ptr MarkerObj Marker = ptr MarkerObj
const const
ThreadsCount = 129 ThreadsCount = 65
proc worker(p: Marker) {.thread.} = proc worker(p: Marker) {.thread.} =
acquire(p.lock) 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.} = proc doAction(outC: PComm) {.thread.} =
for i in 0 ..< 5: for i in 0 ..< 5:
sleep(rand(100)) sleep(rand(50))
send(outC[], i) send(outC[], i)
var var