merged upstream master
This commit is contained in:
commit
81a3585872
127 changed files with 4440 additions and 1496 deletions
8
tests/compile/mexporta.nim
Normal file
8
tests/compile/mexporta.nim
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
# module A
|
||||
import mexportb
|
||||
export mexportb.TMyObject, mexportb.xyz
|
||||
|
||||
export mexportb.q
|
||||
|
||||
proc `$`*(x: TMyObject): string = "my object"
|
||||
|
||||
7
tests/compile/mexportb.nim
Normal file
7
tests/compile/mexportb.nim
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# module B
|
||||
type TMyObject* = object
|
||||
|
||||
const xyz* = 13
|
||||
|
||||
proc q*(x: int): int = 6
|
||||
proc q*(x: string): string = "8"
|
||||
13
tests/compile/tclosure4.nim
Normal file
13
tests/compile/tclosure4.nim
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
|
||||
import json, tables
|
||||
|
||||
proc run(json_params: TTable) =
|
||||
let json_elems = json_params["files"].elems
|
||||
# These fail compilation.
|
||||
var files = map(json_elems, proc (x: PJsonNode): string = x.str)
|
||||
#var files = json_elems.map do (x: PJsonNode) -> string: x.str
|
||||
echo "Hey!"
|
||||
|
||||
when isMainModule:
|
||||
let text = """{"files": ["a", "b", "c"]}"""
|
||||
run(toTable((text.parseJson).fields))
|
||||
194
tests/compile/tclosurebug2.nim
Normal file
194
tests/compile/tclosurebug2.nim
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
import hashes, math
|
||||
|
||||
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]]
|
||||
TOrderedTable*[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: THash): THash {.inline.} =
|
||||
result = ((5 * h) + 1) and maxHash
|
||||
|
||||
template rawGetImpl() {.dirty.} =
|
||||
var h: THash = 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: THash = 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: TOrderedTable[A, B]): int {.inline.} =
|
||||
## returns the number of keys in `t`.
|
||||
result = t.counter
|
||||
|
||||
template forAllOrderedPairs(yieldStmt: stmt) {.dirty, immediate.} =
|
||||
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: TOrderedTable[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 TOrderedTable[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: TOrderedTable[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: TOrderedTable[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 TOrderedTable[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: TOrderedTable[A, B], key: A): int =
|
||||
rawGetImpl()
|
||||
|
||||
proc `[]`*[A, B](t: TOrderedTable[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 TOrderedTable[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(EInvalidKey, "key not found: " & $key)
|
||||
|
||||
proc hasKey*[A, B](t: TOrderedTable[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 TOrderedTable[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 TOrderedTable[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 TOrderedTable[A, B], key: A, val: B) =
|
||||
## puts a (key, value)-pair into `t`.
|
||||
putImpl()
|
||||
|
||||
proc add*[A, B](t: var TOrderedTable[A, B], key: A, val: B) =
|
||||
## puts a new (key, value)-pair into `t` even if ``t[key]`` already exists.
|
||||
AddImpl()
|
||||
|
||||
proc initOrderedTable*[A, B](initialSize=64): TOrderedTable[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]]): TOrderedTable[A, B] =
|
||||
## creates a new ordered hash table that contains the given `pairs`.
|
||||
result = initOrderedTable[A, B](nextPowerOfTwo(pairs.len+10))
|
||||
for key, val in items(pairs): result[key] = val
|
||||
|
||||
proc sort*[A, B](t: var TOrderedTable[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
|
||||
12
tests/compile/tcolonisproc.nim
Normal file
12
tests/compile/tcolonisproc.nim
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
|
||||
proc p(a, b: int, c: proc ()) =
|
||||
c()
|
||||
|
||||
|
||||
p(1, 3):
|
||||
echo 1
|
||||
echo 3
|
||||
|
||||
p(1, 1, proc() =
|
||||
echo 1
|
||||
echo 2)
|
||||
17
tests/compile/teffects1.nim
Normal file
17
tests/compile/teffects1.nim
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
|
||||
type
|
||||
PMenu = ref object
|
||||
PMenuItem = ref object
|
||||
|
||||
proc createMenuItem*(menu: PMenu, label: string,
|
||||
action: proc (i: PMenuItem, p: pointer) {.cdecl.}) = nil
|
||||
|
||||
var s: PMenu
|
||||
createMenuItem(s, "Go to definition...",
|
||||
proc (i: PMenuItem, p: pointer) {.cdecl.} =
|
||||
try:
|
||||
echo(i.repr)
|
||||
except EInvalidValue:
|
||||
echo("blah")
|
||||
)
|
||||
|
||||
10
tests/compile/texport.nim
Normal file
10
tests/compile/texport.nim
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
discard """
|
||||
output: "my object68"
|
||||
"""
|
||||
|
||||
import mexporta
|
||||
|
||||
# B.TMyObject has been imported implicitly here:
|
||||
var x: TMyObject
|
||||
echo($x, q(0), q"0")
|
||||
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
discard """
|
||||
output: "1.0000000000000000e+00 10"
|
||||
ccodecheck: "!@'ClEnv'"
|
||||
"""
|
||||
|
||||
proc p[T](a, b: T): T
|
||||
|
|
|
|||
|
|
@ -272,7 +272,7 @@ proc handleWebMessage(state: PState, line: string) =
|
|||
message.add(limitCommitMsg(commit["message"].str))
|
||||
|
||||
# Send message to #nimrod.
|
||||
state.ircClient[].privmsg(joinChans[0], message)
|
||||
state.ircClient.privmsg(joinChans[0], message)
|
||||
elif json.existsKey("redisinfo"):
|
||||
assert json["redisinfo"].existsKey("port")
|
||||
#let redisPort = json["redisinfo"]["port"].num
|
||||
|
|
@ -336,10 +336,11 @@ proc hubConnect(state: PState) =
|
|||
|
||||
state.dispatcher.register(state.sock)
|
||||
|
||||
proc handleIrc(irc: var TAsyncIRC, event: TIRCEvent, state: PState) =
|
||||
proc handleIrc(irc: PAsyncIRC, event: TIRCEvent, state: PState) =
|
||||
case event.typ
|
||||
of EvConnected: nil
|
||||
of EvDisconnected:
|
||||
while not state.ircClient[].isConnected:
|
||||
while not state.ircClient.isConnected:
|
||||
try:
|
||||
state.ircClient.connect()
|
||||
except:
|
||||
|
|
@ -355,12 +356,12 @@ proc handleIrc(irc: var TAsyncIRC, event: TIRCEvent, state: PState) =
|
|||
let msg = event.params[event.params.len-1]
|
||||
let words = msg.split(' ')
|
||||
template pm(msg: string): stmt =
|
||||
state.ircClient[].privmsg(event.origin, msg)
|
||||
state.ircClient.privmsg(event.origin, msg)
|
||||
case words[0]
|
||||
of "!ping": pm("pong")
|
||||
of "!lag":
|
||||
if state.ircClient[].getLag != -1.0:
|
||||
var lag = state.ircClient[].getLag
|
||||
if state.ircClient.getLag != -1.0:
|
||||
var lag = state.ircClient.getLag
|
||||
lag = lag * 1000.0
|
||||
pm($int(lag) & "ms between me and the server.")
|
||||
else:
|
||||
|
|
@ -433,7 +434,7 @@ proc open(port: TPort = TPort(5123)): PState =
|
|||
res.hubPort = port
|
||||
res.hubConnect()
|
||||
let hirc =
|
||||
proc (a: var TAsyncIRC, ev: TIRCEvent) =
|
||||
proc (a: PAsyncIRC, ev: TIRCEvent) =
|
||||
handleIrc(a, ev, res)
|
||||
# Connect to the irc server.
|
||||
res.ircClient = AsyncIrc(ircServer, nick = botNickname, user = botNickname,
|
||||
|
|
|
|||
21
tests/compile/titerovl.nim
Normal file
21
tests/compile/titerovl.nim
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
discard """
|
||||
output: '''9
|
||||
1
|
||||
2
|
||||
3
|
||||
'''
|
||||
"""
|
||||
|
||||
# Test the new overloading rules for iterators:
|
||||
|
||||
# test that iterator 'p' is preferred:
|
||||
proc p(): seq[int] = @[1, 2, 3]
|
||||
iterator p(): int = yield 9
|
||||
|
||||
for x in p(): echo x
|
||||
|
||||
# test that 'q' works in this position:
|
||||
proc q(): seq[int] = @[1, 2, 3]
|
||||
|
||||
for x in q(): echo x
|
||||
|
||||
14
tests/compile/tnamedparamanonproc.nim
Normal file
14
tests/compile/tnamedparamanonproc.nim
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
|
||||
type
|
||||
PButton = ref object
|
||||
TButtonClicked = proc(button: PButton) {.nimcall.}
|
||||
|
||||
proc newButton*(onClick: TButtonClicked) =
|
||||
nil
|
||||
|
||||
proc main() =
|
||||
newButton(onClick = proc(b: PButton) =
|
||||
var requestomat = 12
|
||||
)
|
||||
|
||||
main()
|
||||
28
tests/compile/tobject3.nim
Normal file
28
tests/compile/tobject3.nim
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
type
|
||||
TFoo = ref object of TObject
|
||||
Data: int
|
||||
TBar = ref object of TFoo
|
||||
nil
|
||||
TBar2 = ref object of TBar
|
||||
d2: int
|
||||
|
||||
template super(self: TBar): TFoo = self
|
||||
|
||||
template super(self: TBar2): TBar = self
|
||||
|
||||
proc Foo(self: TFoo) =
|
||||
echo "TFoo"
|
||||
|
||||
#proc Foo(self: TBar) =
|
||||
# echo "TBar"
|
||||
# Foo(super(self))
|
||||
# works when this code is uncommented
|
||||
|
||||
proc Foo(self: TBar2) =
|
||||
echo "TBar2"
|
||||
Foo(super(self))
|
||||
|
||||
var b: TBar2
|
||||
new(b)
|
||||
|
||||
Foo(b)
|
||||
|
|
@ -21,7 +21,7 @@ proc takeParseInt(x: proc (y: string): int {.noSideEffect.}): int =
|
|||
result = x("123")
|
||||
|
||||
echo "Give a list of numbers (separated by spaces): "
|
||||
var x = stdin.readline.split.each(parseInt).max
|
||||
var x = stdin.readline.split.map(parseInt).max
|
||||
echo x, " is the maximum!"
|
||||
echo "another number: ", takeParseInt(parseInt)
|
||||
|
||||
|
|
|
|||
28
tests/compile/tsecondarrayproperty.nim
Normal file
28
tests/compile/tsecondarrayproperty.nim
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
|
||||
type
|
||||
TFoo = object
|
||||
data: array[0..100, int]
|
||||
TSecond = distinct TFoo
|
||||
|
||||
proc `[]` (self: var TFoo, x: int): var int =
|
||||
return self.data[x]
|
||||
|
||||
proc `[]=` (self: var TFoo, x, y: int) =
|
||||
# only `[]` returning a 'var T' seems to not work for now :-/
|
||||
self.data[x] = y
|
||||
|
||||
proc second(self: var TFoo): var TSecond =
|
||||
return TSecond(self)
|
||||
|
||||
proc `[]`(self: var TSecond, x: int): var int =
|
||||
return TFoo(self).data[2*x]
|
||||
|
||||
var f: TFoo
|
||||
|
||||
for i in 0..f.data.high: f[i] = 2 * i
|
||||
|
||||
echo f.second[1]
|
||||
|
||||
#echo `second[]`(f,1)
|
||||
# this is the only way I could use it, but not what I expected
|
||||
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
# iterate over all files with a given filter:
|
||||
|
||||
import
|
||||
os, times
|
||||
"../../lib/pure/os.nim", ../../ lib / pure / times
|
||||
|
||||
proc main(filter: string) =
|
||||
for filename in walkFiles(filter):
|
||||
|
|
|
|||
13
tests/patterns/thoist.nim
Normal file
13
tests/patterns/thoist.nim
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
discard """
|
||||
output: '''true
|
||||
true'''
|
||||
"""
|
||||
|
||||
import pegs
|
||||
|
||||
template optPeg{peg(pattern)}(pattern: string{lit}): TPeg =
|
||||
var gl {.global, gensym.} = peg(pattern)
|
||||
gl
|
||||
|
||||
echo match("(a b c)", peg"'(' @ ')'")
|
||||
echo match("W_HI_Le", peg"\y 'while'")
|
||||
11
tests/patterns/tpartial.nim
Normal file
11
tests/patterns/tpartial.nim
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
discard """
|
||||
output: '''-2'''
|
||||
"""
|
||||
|
||||
proc p(x, y: int; cond: bool): int =
|
||||
result = if cond: x + y else: x - y
|
||||
|
||||
template optP{p(x, y, true)}(x, y: expr): expr = x - y
|
||||
template optP{p(x, y, false)}(x, y: expr): expr = x + y
|
||||
|
||||
echo p(2, 4, true)
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
discard """
|
||||
file: "system.nim"
|
||||
line: 663
|
||||
line: 669
|
||||
errormsg: "type mismatch"
|
||||
"""
|
||||
|
||||
|
|
|
|||
10
tests/reject/timportexcept.nim
Normal file
10
tests/reject/timportexcept.nim
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
discard """
|
||||
line: 9
|
||||
errormsg: "undeclared identifier: '%'"
|
||||
"""
|
||||
|
||||
import strutils except `%`
|
||||
|
||||
# doesn't work
|
||||
echo "$1" % "abc"
|
||||
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
discard """
|
||||
line: 11
|
||||
line: 22
|
||||
errormgs: "type mismatch"
|
||||
"""
|
||||
|
||||
|
|
@ -7,9 +7,17 @@ type
|
|||
PObj = ref TObj not nil
|
||||
TObj = object
|
||||
x: int
|
||||
|
||||
MyString = string not nil
|
||||
|
||||
var x: PObj = nil
|
||||
#var x: PObj = nil
|
||||
|
||||
proc p(x: string not nil): int =
|
||||
result = 45
|
||||
|
||||
proc q(x: MyString) = nil
|
||||
proc q2(x: string) = nil
|
||||
|
||||
q2(nil)
|
||||
q(nil)
|
||||
|
||||
|
|
|
|||
21
tests/run/tastoverload1.nim
Normal file
21
tests/run/tastoverload1.nim
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
discard """
|
||||
output: '''string literal
|
||||
no string literal
|
||||
no string literal'''
|
||||
"""
|
||||
|
||||
proc optLit(a: string{lit}) =
|
||||
echo "string literal"
|
||||
|
||||
proc optLit(a: string) =
|
||||
echo "no string literal"
|
||||
|
||||
const
|
||||
constant = "abc"
|
||||
|
||||
var
|
||||
variable = "xyz"
|
||||
|
||||
optLit("literal")
|
||||
optLit(constant)
|
||||
optLit(variable)
|
||||
17
tests/run/tdomulttest.nim
Normal file
17
tests/run/tdomulttest.nim
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
discard """
|
||||
file: "tdomulttest.nim"
|
||||
output: "555\ntest\nmulti lines\n99999999\nend"
|
||||
disabled: true
|
||||
"""
|
||||
proc foo(bar, baz: proc (x: int): int) =
|
||||
echo bar(555)
|
||||
echo baz(99999999)
|
||||
|
||||
foo do (x: int) -> int:
|
||||
return x
|
||||
do (x: int) -> int:
|
||||
echo("test")
|
||||
echo("multi lines")
|
||||
return x
|
||||
|
||||
echo("end")
|
||||
30
tests/run/tgenericconverter.nim
Normal file
30
tests/run/tgenericconverter.nim
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
discard """
|
||||
output: '''666
|
||||
666'''
|
||||
"""
|
||||
|
||||
# test the new generic converters:
|
||||
|
||||
type
|
||||
TFoo2[T] = object
|
||||
x: T
|
||||
|
||||
TFoo[T] = object
|
||||
data: array[0..100, T]
|
||||
|
||||
converter toFoo[T](a: TFoo2[T]): TFoo[T] =
|
||||
result.data[0] = a.x
|
||||
|
||||
proc p(a: TFoo[int]) =
|
||||
echo a.data[0]
|
||||
|
||||
proc q[T](a: TFoo[T]) =
|
||||
echo a.data[0]
|
||||
|
||||
|
||||
var
|
||||
aa: TFoo2[int]
|
||||
aa.x = 666
|
||||
|
||||
p aa
|
||||
q aa
|
||||
|
|
@ -4,17 +4,17 @@ discard """
|
|||
0'''
|
||||
"""
|
||||
|
||||
iterator count(x: int, skip: bool): int {.closure.} =
|
||||
iterator count[T](x: T, skip: bool): int {.closure.} =
|
||||
if skip: return x+10
|
||||
else: yield x+1
|
||||
|
||||
if skip: return x+10
|
||||
else: yield x+2
|
||||
|
||||
proc takeProc(x: iterator (x: int, skip: bool): int) =
|
||||
proc takeProc[T](x: iterator (x: T, skip: bool): int) =
|
||||
echo x(4, false)
|
||||
echo x(4, true)
|
||||
echo x(4, false)
|
||||
|
||||
takeProc(count)
|
||||
takeProc(count[int])
|
||||
|
||||
|
|
|
|||
30
tests/run/tmultim6.nim
Normal file
30
tests/run/tmultim6.nim
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
discard """
|
||||
output: "collide: unit, thing | collide: unit, thing | collide: thing, unit |"
|
||||
"""
|
||||
# Test multi methods
|
||||
|
||||
type
|
||||
TThing = object {.inheritable.}
|
||||
TUnit[T] = object of TThing
|
||||
x: T
|
||||
TParticle = object of TThing
|
||||
a, b: int
|
||||
|
||||
method collide(a, b: TThing) {.inline.} =
|
||||
quit "to override!"
|
||||
|
||||
method collide[T](a: TThing, b: TUnit[T]) {.inline.} =
|
||||
write stdout, "collide: thing, unit | "
|
||||
|
||||
method collide[T](a: TUnit[T], b: TThing) {.inline.} =
|
||||
write stdout, "collide: unit, thing | "
|
||||
|
||||
proc test(a, b: TThing) {.inline.} =
|
||||
collide(a, b)
|
||||
|
||||
var
|
||||
a: TThing
|
||||
b, c: TUnit[string]
|
||||
collide(b, TThing(c))
|
||||
test(b, c)
|
||||
collide(a, b)
|
||||
|
|
@ -19,6 +19,25 @@ const
|
|||
"50": 344490, "60": 344491, "70": 344492,
|
||||
"80": 344497}
|
||||
|
||||
sorteddata = {
|
||||
"---00": 346677844,
|
||||
"0": 34404,
|
||||
"1": 344004,
|
||||
"10": 34484,
|
||||
"11": 34474,
|
||||
"12": 789,
|
||||
"19": 34464,
|
||||
"2": 344774, "20": 34454,
|
||||
"3": 342244, "30": 34141244,
|
||||
"34": 123456,
|
||||
"4": 3412344, "40": 344114,
|
||||
"5": 341232144, "50": 344490,
|
||||
"6": 34214544, "60": 344491,
|
||||
"7": 3434544, "70": 344492,
|
||||
"8": 344544, "80": 344497,
|
||||
"9": 34435644,
|
||||
"90": 343}
|
||||
|
||||
block tableTest1:
|
||||
var t = initTable[tuple[x, y: int], string]()
|
||||
t[(0,0)] = "00"
|
||||
|
|
@ -86,5 +105,25 @@ block countTableTest1:
|
|||
block SyntaxTest:
|
||||
var x = toTable[int, string]({:})
|
||||
|
||||
proc orderedTableSortTest() =
|
||||
var t = initOrderedTable[string, int](2)
|
||||
for key, val in items(data): t[key] = val
|
||||
for key, val in items(data): assert t[key] == val
|
||||
t.sort(proc (x, y: tuple[key: string, val: int]): int = cmp(x.key, y.key))
|
||||
var i = 0
|
||||
# `pairs` needs to yield in sorted order:
|
||||
for key, val in pairs(t):
|
||||
doAssert key == sorteddata[i][0]
|
||||
doAssert val == sorteddata[i][1]
|
||||
inc(i)
|
||||
|
||||
# check that lookup still works:
|
||||
for key, val in pairs(t):
|
||||
doAssert val == t[key]
|
||||
# check that insert still works:
|
||||
t["newKeyHere"] = 80
|
||||
|
||||
|
||||
orderedTableSortTest()
|
||||
echo "true"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
discard """
|
||||
output: "23456"
|
||||
output: "2345623456"
|
||||
"""
|
||||
|
||||
template toSeq*(iter: expr): expr {.immediate.} =
|
||||
var result: seq[type(iter)] = @[]
|
||||
for x in iter: add(result, x)
|
||||
result
|
||||
|
||||
import sequtils
|
||||
|
||||
for x in toSeq(countup(2, 6)):
|
||||
stdout.write(x)
|
||||
for x in items(toSeq(countup(2, 6))):
|
||||
stdout.write(x)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#
|
||||
#
|
||||
# Nimrod Tester
|
||||
# (c) Copyright 2012 Andreas Rumpf
|
||||
# (c) Copyright 2013 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
|
|
|
|||
114
tests/tester.nim
114
tests/tester.nim
|
|
@ -1,7 +1,7 @@
|
|||
#
|
||||
#
|
||||
# Nimrod Tester
|
||||
# (c) Copyright 2012 Andreas Rumpf
|
||||
# (c) Copyright 2013 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
|
|
@ -25,22 +25,35 @@ const
|
|||
type
|
||||
TTestAction = enum
|
||||
actionCompile, actionRun, actionReject
|
||||
TSpec {.pure.} = object
|
||||
TResultEnum = enum
|
||||
reNimrodcCrash, # nimrod compiler seems to have crashed
|
||||
reMsgsDiffer, # error messages differ
|
||||
reFilesDiffer, # expected and given filenames differ
|
||||
reLinesDiffer, # expected and given line numbers differ
|
||||
reOutputsDiffer,
|
||||
reExitcodesDiffer,
|
||||
reInvalidPeg,
|
||||
reCodegenFailure,
|
||||
reCodeNotFound,
|
||||
reExeNotFound,
|
||||
reIgnored, # test is ignored
|
||||
reSuccess # test was successful
|
||||
TTarget = enum
|
||||
targetC, targetCpp, targetObjC, targetJS
|
||||
|
||||
TSpec = object
|
||||
action: TTestAction
|
||||
file, cmd: string
|
||||
outp: string
|
||||
line, exitCode: int
|
||||
msg: string
|
||||
err: bool
|
||||
disabled: bool
|
||||
ccodeCheck: string
|
||||
err: TResultEnum
|
||||
substr: bool
|
||||
TResults {.pure.} = object
|
||||
TResults = object
|
||||
total, passed, skipped: int
|
||||
data: string
|
||||
|
||||
TResultEnum = enum
|
||||
reFailure, reIgnored, reSuccess
|
||||
|
||||
# ----------------------- Spec parser ----------------------------------------
|
||||
|
||||
when not defined(parseCfgBool):
|
||||
|
|
@ -82,9 +95,9 @@ template parseSpecAux(fillResult: stmt) {.immediate.} =
|
|||
|
||||
proc parseSpec(filename: string): TSpec =
|
||||
result.file = filename
|
||||
result.err = true
|
||||
result.msg = ""
|
||||
result.outp = ""
|
||||
result.ccodeCheck = ""
|
||||
result.cmd = cmdTemplate
|
||||
parseSpecAux:
|
||||
case normalize(e.key)
|
||||
|
|
@ -103,8 +116,10 @@ proc parseSpec(filename: string): TSpec =
|
|||
of "exitcode":
|
||||
discard parseInt(e.value, result.exitCode)
|
||||
of "errormsg", "msg": result.msg = e.value
|
||||
of "disabled": result.disabled = parseCfgBool(e.value)
|
||||
of "disabled":
|
||||
if parseCfgBool(e.value): result.err = reIgnored
|
||||
of "cmd": result.cmd = e.value
|
||||
of "ccodecheck": result.ccodeCheck = e.value
|
||||
else: echo ignoreMsg(p, e)
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
|
|
@ -134,7 +149,6 @@ proc callCompiler(cmdTemplate, filename, options: string): TSpec =
|
|||
result.msg = ""
|
||||
result.file = ""
|
||||
result.outp = ""
|
||||
result.err = true
|
||||
result.line = -1
|
||||
if err =~ pegLineError:
|
||||
result.file = extractFilename(matches[0])
|
||||
|
|
@ -143,7 +157,7 @@ proc callCompiler(cmdTemplate, filename, options: string): TSpec =
|
|||
elif err =~ pegOtherError:
|
||||
result.msg = matches[0]
|
||||
elif suc =~ pegSuccess:
|
||||
result.err = false
|
||||
result.err = reSuccess
|
||||
|
||||
proc initResults: TResults =
|
||||
result.total = 0
|
||||
|
|
@ -164,9 +178,9 @@ proc `$`(x: TResults): string =
|
|||
|
||||
proc colorResult(r: TResultEnum): string =
|
||||
case r
|
||||
of reFailure: result = "<span style=\"color:red\">no</span>"
|
||||
of reIgnored: result = "<span style=\"color:fuchsia\">ignored</span>"
|
||||
of reSuccess: result = "<span style=\"color:green\">yes</span>"
|
||||
else: result = "<span style=\"color:red\">no</span>"
|
||||
|
||||
const
|
||||
TableHeader4 = "<table border=\"1\"><tr><td>Test</td><td>Expected</td>" &
|
||||
|
|
@ -217,12 +231,12 @@ proc listResults(reject, compile, run: TResults) =
|
|||
|
||||
proc cmpMsgs(r: var TResults, expected, given: TSpec, test: string) =
|
||||
if strip(expected.msg) notin strip(given.msg):
|
||||
r.addResult(test, expected.msg, given.msg, reFailure)
|
||||
r.addResult(test, expected.msg, given.msg, reMsgsDiffer)
|
||||
elif extractFilename(expected.file) != extractFilename(given.file) and
|
||||
"internal error:" notin expected.msg:
|
||||
r.addResult(test, expected.file, given.file, reFailure)
|
||||
r.addResult(test, expected.file, given.file, reFilesDiffer)
|
||||
elif expected.line != given.line and expected.line != 0:
|
||||
r.addResult(test, $expected.line, $given.line, reFailure)
|
||||
r.addResult(test, $expected.line, $given.line, reLinesDiffer)
|
||||
else:
|
||||
r.addResult(test, expected.msg, given.msg, reSuccess)
|
||||
inc(r.passed)
|
||||
|
|
@ -233,7 +247,7 @@ proc rejectSingleTest(r: var TResults, test, options: string) =
|
|||
inc(r.total)
|
||||
echo t
|
||||
var expected = parseSpec(test)
|
||||
if expected.disabled:
|
||||
if expected.err == reIgnored:
|
||||
r.addResult(t, "", "", reIgnored)
|
||||
inc(r.skipped)
|
||||
else:
|
||||
|
|
@ -244,31 +258,47 @@ proc reject(r: var TResults, dir, options: string) =
|
|||
## handle all the tests that the compiler should reject
|
||||
for test in os.walkFiles(dir / "t*.nim"): rejectSingleTest(r, test, options)
|
||||
|
||||
proc codegenCheck(test, check, ext: string, given: var TSpec) =
|
||||
if check.len > 0:
|
||||
try:
|
||||
let (path, name, ext2) = test.splitFile
|
||||
echo path / "nimcache" / name.changeFileExt(ext)
|
||||
let contents = readFile(path / "nimcache" / name.changeFileExt(ext)).string
|
||||
if contents.find(check.peg) < 0:
|
||||
given.err = reCodegenFailure
|
||||
except EInvalidValue:
|
||||
given.err = reInvalidPeg
|
||||
except EIO:
|
||||
given.err = reCodeNotFound
|
||||
|
||||
proc codegenChecks(test: string, expected: TSpec, given: var TSpec) =
|
||||
codegenCheck(test, expected.ccodeCheck, ".c", given)
|
||||
|
||||
proc compile(r: var TResults, pattern, options: string) =
|
||||
for test in os.walkFiles(pattern):
|
||||
let t = extractFilename(test)
|
||||
echo t
|
||||
inc(r.total)
|
||||
let expected = parseSpec(test)
|
||||
if expected.disabled:
|
||||
if expected.err == reIgnored:
|
||||
r.addResult(t, "", reIgnored)
|
||||
inc(r.skipped)
|
||||
else:
|
||||
var given = callCompiler(expected.cmd, test, options)
|
||||
r.addResult(t, given.msg, if given.err: reFailure else: reSuccess)
|
||||
if not given.err: inc(r.passed)
|
||||
if given.err == reSuccess:
|
||||
codegenChecks(test, expected, given)
|
||||
r.addResult(t, given.msg, given.err)
|
||||
if given.err == reSuccess: inc(r.passed)
|
||||
|
||||
proc compileSingleTest(r: var TResults, test, options: string) =
|
||||
# does not extract the spec because the file is not supposed to have any
|
||||
let test = test.addFileExt(".nim")
|
||||
let t = extractFilename(test)
|
||||
inc(r.total)
|
||||
echo t
|
||||
let given = callCompiler(cmdTemplate, test, options)
|
||||
r.addResult(t, given.msg, if given.err: reFailure else: reSuccess)
|
||||
if not given.err: inc(r.passed)
|
||||
|
||||
type
|
||||
TTarget = enum targetC, targetJS
|
||||
r.addResult(t, given.msg, given.err)
|
||||
if given.err == reSuccess: inc(r.passed)
|
||||
|
||||
proc runSingleTest(r: var TResults, test, options: string, target: TTarget) =
|
||||
var test = test.addFileExt(".nim")
|
||||
|
|
@ -276,13 +306,13 @@ proc runSingleTest(r: var TResults, test, options: string, target: TTarget) =
|
|||
echo t
|
||||
inc(r.total)
|
||||
var expected = parseSpec(test)
|
||||
if expected.disabled:
|
||||
if expected.err == reIgnored:
|
||||
r.addResult(t, "", "", reIgnored)
|
||||
inc(r.skipped)
|
||||
else:
|
||||
var given = callCompiler(expected.cmd, test, options)
|
||||
if given.err:
|
||||
r.addResult(t, "", given.msg, reFailure)
|
||||
if given.err != reSuccess:
|
||||
r.addResult(t, "", given.msg, given.err)
|
||||
else:
|
||||
var exeFile: string
|
||||
if target == targetC:
|
||||
|
|
@ -296,25 +326,26 @@ proc runSingleTest(r: var TResults, test, options: string, target: TTarget) =
|
|||
(if target==targetJS: "node " else: "") & exeFile)
|
||||
if exitCode != expected.ExitCode:
|
||||
r.addResult(t, "exitcode: " & $expected.ExitCode,
|
||||
"exitcode: " & $exitCode, reFailure)
|
||||
"exitcode: " & $exitCode, reExitCodesDiffer)
|
||||
else:
|
||||
var success = strip(buf.string) == strip(expected.outp)
|
||||
if expected.substr and not success:
|
||||
success = expected.outp in buf.string
|
||||
if success: inc(r.passed)
|
||||
r.addResult(t, expected.outp,
|
||||
buf.string, if success: reSuccess else: reFailure)
|
||||
if strip(buf.string) != strip(expected.outp):
|
||||
if not (expected.substr and expected.outp in buf.string):
|
||||
given.err = reOutputsDiffer
|
||||
if given.err == reSuccess:
|
||||
codeGenChecks(test, expected, given)
|
||||
if given.err == reSuccess: inc(r.passed)
|
||||
r.addResult(t, expected.outp, buf.string, given.err)
|
||||
else:
|
||||
r.addResult(t, expected.outp, "executable not found", reFailure)
|
||||
r.addResult(t, expected.outp, "executable not found", reExeNotFound)
|
||||
|
||||
proc runSingleTest(r: var TResults, test, options: string) =
|
||||
runSingleTest(r, test, options, targetC)
|
||||
|
||||
|
||||
proc run(r: var TResults, dir, options: string) =
|
||||
for test in os.walkFiles(dir / "t*.nim"): runSingleTest(r, test, options)
|
||||
|
||||
include specials
|
||||
|
||||
|
||||
proc compileExample(r: var TResults, pattern, options: string) =
|
||||
for test in os.walkFiles(pattern): compileSingleTest(r, test, options)
|
||||
|
||||
|
|
@ -392,7 +423,12 @@ proc main() =
|
|||
runDLLTests r, p.cmdLineRest.string
|
||||
of "gc":
|
||||
runGCTests(r, p.cmdLineRest.string)
|
||||
of "test", "comp", "rej":
|
||||
of "test":
|
||||
if p.kind != cmdArgument: quit usage
|
||||
var testFile = p.key.string
|
||||
p.next()
|
||||
runSingleTest(r, testFile, p.cmdLineRest.string)
|
||||
of "comp", "rej":
|
||||
if p.kind != cmdArgument: quit usage
|
||||
var testFile = p.key.string
|
||||
p.next()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue