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
|
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"
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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` "
|
||||||
|
|
|
||||||
|
|
@ -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
|
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)
|
|
||||||
|
|
|
||||||
|
|
@ -12,4 +12,4 @@ proc main() =
|
||||||
|
|
||||||
doAssert counter <= 4
|
doAssert counter <= 4
|
||||||
|
|
||||||
for i in 0 .. 10: main()
|
for i in 0 .. 4: main()
|
||||||
|
|
|
||||||
|
|
@ -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.} =
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -99,4 +99,3 @@ proc server() {.async.} =
|
||||||
|
|
||||||
when isMainModule:
|
when isMainModule:
|
||||||
waitFor server()
|
waitFor server()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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}) =
|
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)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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>]"
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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
|
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))
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ collide: thing, unit |
|
||||||
do nothing
|
do nothing
|
||||||
'''
|
'''
|
||||||
joinable: false
|
joinable: false
|
||||||
|
disabled: true
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ discard """
|
||||||
Hi derived!
|
Hi derived!
|
||||||
hello
|
hello
|
||||||
'''
|
'''
|
||||||
|
disabled: true
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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))
|
||||||
|
|
|
||||||
|
|
@ -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)]
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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),") }"
|
" 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:
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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 """
|
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()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
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"
|
||||||
|
|
|
||||||
|
|
@ -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 """
|
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
|
||||||
|
|
|
||||||
|
|
@ -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 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
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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.} =
|
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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue