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:
parent
2a278f6eba
commit
8088633250
72 changed files with 532 additions and 1082 deletions
45
.github/workflows/ci_docs.yml
vendored
Normal file
45
.github/workflows/ci_docs.yml
vendored
Normal 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
|
||||
17
koch.nim
17
koch.nim
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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` "
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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"
|
||||
|
||||
|
|
@ -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)
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -12,4 +12,4 @@ proc main() =
|
|||
|
||||
doAssert counter <= 4
|
||||
|
||||
for i in 0 .. 10: main()
|
||||
for i in 0 .. 4: main()
|
||||
|
|
|
|||
|
|
@ -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.} =
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -99,4 +99,3 @@ proc server() {.async.} =
|
|||
|
||||
when isMainModule:
|
||||
waitFor server()
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
@ -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)
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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>]"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ collide: thing, unit |
|
|||
do nothing
|
||||
'''
|
||||
joinable: false
|
||||
disabled: true
|
||||
"""
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ discard """
|
|||
Hi derived!
|
||||
hello
|
||||
'''
|
||||
disabled: true
|
||||
"""
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
discard """
|
||||
output: "ugly conversion successful"
|
||||
"""
|
||||
|
||||
import int2bool
|
||||
|
||||
if 4:
|
||||
echo "ugly conversion successful"
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
discard """
|
||||
output: "ugly conversion successful 2"
|
||||
"""
|
||||
|
||||
import int2bool
|
||||
|
||||
if 4:
|
||||
echo "ugly conversion successful 2"
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
discard """
|
||||
output: '''246
|
||||
'''
|
||||
"""
|
||||
|
||||
import deadg, deadb
|
||||
|
||||
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
discard """
|
||||
output: '''246
|
||||
xyzabc
|
||||
'''
|
||||
"""
|
||||
|
||||
import deadg, deadb
|
||||
|
||||
# now add call to previously unused proc p2:
|
||||
echo p2("xyz", "abc")
|
||||
|
||||
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
|
||||
import deadg
|
||||
|
||||
|
||||
echo p1(123, 123)
|
||||
|
||||
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
proc p1*(x, y: int): int =
|
||||
result = x + y
|
||||
|
||||
proc p2*(x, y: string): string =
|
||||
result = x & y
|
||||
|
||||
|
||||
|
|
@ -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()
|
||||
|
|
@ -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()
|
||||
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
discard """
|
||||
output: "Hello World"
|
||||
"""
|
||||
|
||||
echo "Hello World"
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
|
||||
{.overflowchecks: on.}
|
||||
|
||||
converter uglyToBool*(x: int): bool =
|
||||
result = x != 0
|
||||
|
||||
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
--nimcache:"$projectPath/nimcache"
|
||||
--symbolFiles:on
|
||||
|
|
@ -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]
|
||||
|
||||
|
|
@ -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]
|
||||
|
||||
|
|
@ -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()
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
-d:noIntrinsicsBitOpts
|
||||
-d:noUndefinedBitOps
|
||||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import asyncdispatch
|
|||
import threadpool
|
||||
|
||||
proc f1() =
|
||||
waitFor sleepAsync(100)
|
||||
waitFor sleepAsync(20)
|
||||
echo "hello"
|
||||
|
||||
spawn f1()
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ type
|
|||
|
||||
const
|
||||
ThreadsCount = 129
|
||||
SleepTime = 1000
|
||||
SleepTime = 250
|
||||
|
||||
proc worker(p: Marker) {.thread.} =
|
||||
acquire(p.lock)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue