mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-19 22:10:33 +00:00
Merge tests into a larger file (part 1 of ∞) (#9318)
* merge actiontable tests
* merge arithm tests
* merge array tests
* merge assign tests
* merge bind tests
* merge casestmt tests
* merge closure tests
* merge cnt seq tests
* merge collections tests
* merge concept issues tests
* merge concept tests
* fix failing tests
* smaller outputs
Use `doAssert` where possible.
* fix wrong output
* split `tcomputedgoto`
* revert merging concepts
* fix failing test
(cherry picked from commit 7f18d7cbc1)
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
discard """
|
||||
output: "action 3 arg"
|
||||
output: '''
|
||||
action 3 arg
|
||||
action 3 arg
|
||||
'''
|
||||
"""
|
||||
|
||||
import tables
|
||||
@@ -17,10 +20,18 @@ proc action4(arg: string) =
|
||||
echo "action 4 ", arg
|
||||
|
||||
var
|
||||
actionTable = {
|
||||
actionTable1 = {
|
||||
"A": action1,
|
||||
"B": action2,
|
||||
"C": action3,
|
||||
"D": action4}.toTable
|
||||
|
||||
actionTable["C"]("arg")
|
||||
const
|
||||
actionTable2 = {
|
||||
"A": action1,
|
||||
"B": action2,
|
||||
"C": action3,
|
||||
"D": action4}.toTable
|
||||
|
||||
actionTable1["C"]("arg")
|
||||
actionTable2["C"]("arg")
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
discard """
|
||||
output: "action 3 arg"
|
||||
"""
|
||||
|
||||
import tables
|
||||
|
||||
proc action1(arg: string) =
|
||||
echo "action 1 ", arg
|
||||
|
||||
proc action2(arg: string) =
|
||||
echo "action 2 ", arg
|
||||
|
||||
proc action3(arg: string) =
|
||||
echo "action 3 ", arg
|
||||
|
||||
proc action4(arg: string) =
|
||||
echo "action 4 ", arg
|
||||
|
||||
const
|
||||
actionTable = {
|
||||
"A": action1,
|
||||
"B": action2,
|
||||
"C": action3,
|
||||
"D": action4}.toTable
|
||||
|
||||
actionTable["C"]("arg")
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
discard """
|
||||
output: '''int32
|
||||
int32
|
||||
1280
|
||||
1280'''
|
||||
"""
|
||||
|
||||
# bug #5216
|
||||
|
||||
import typetraits
|
||||
|
||||
echo(name type((0x0A'i8 and 0x7F'i32) shl 7'i32))
|
||||
|
||||
let i8 = 0x0A'i8
|
||||
echo(name type((i8 and 0x7F'i32) shl 7'i32))
|
||||
|
||||
echo((0x0A'i8 and 0x7F'i32) shl 7'i32)
|
||||
|
||||
let ii8 = 0x0A'i8
|
||||
echo((ii8 and 0x7F'i32) shl 7'i32)
|
||||
173
tests/arithm/tarithm.nim
Normal file
173
tests/arithm/tarithm.nim
Normal file
@@ -0,0 +1,173 @@
|
||||
discard """
|
||||
output: '''
|
||||
int32
|
||||
int32
|
||||
1280
|
||||
1280
|
||||
'''
|
||||
"""
|
||||
|
||||
import typetraits
|
||||
|
||||
|
||||
block tand:
|
||||
# bug #5216
|
||||
echo(name type((0x0A'i8 and 0x7F'i32) shl 7'i32))
|
||||
|
||||
let i8 = 0x0A'i8
|
||||
echo(name type((i8 and 0x7F'i32) shl 7'i32))
|
||||
|
||||
echo((0x0A'i8 and 0x7F'i32) shl 7'i32)
|
||||
|
||||
let ii8 = 0x0A'i8
|
||||
echo((ii8 and 0x7F'i32) shl 7'i32)
|
||||
|
||||
|
||||
|
||||
block tcast:
|
||||
template crossCheck(ty: untyped, exp: untyped) =
|
||||
let rt = ty(exp)
|
||||
const ct = ty(exp)
|
||||
if $rt != $ct:
|
||||
echo "Got ", ct
|
||||
echo "Expected ", rt
|
||||
|
||||
template add1(x: uint8): untyped = x + 1
|
||||
template add1(x: uint16): untyped = x + 1
|
||||
template add1(x: uint32): untyped = x + 1
|
||||
|
||||
template sub1(x: uint8): untyped = x - 1
|
||||
template sub1(x: uint16): untyped = x - 1
|
||||
template sub1(x: uint32): untyped = x - 1
|
||||
|
||||
crossCheck(int8, 0'i16 - 5'i16)
|
||||
crossCheck(int16, 0'i32 - 5'i32)
|
||||
crossCheck(int32, 0'i64 - 5'i64)
|
||||
|
||||
crossCheck(uint8, 0'u8 - 5'u8)
|
||||
crossCheck(uint16, 0'u16 - 5'u16)
|
||||
crossCheck(uint32, 0'u32 - 5'u32)
|
||||
crossCheck(uint64, 0'u64 - 5'u64)
|
||||
|
||||
crossCheck(uint8, uint8.high + 5'u8)
|
||||
crossCheck(uint16, uint16.high + 5'u16)
|
||||
crossCheck(uint32, uint32.high + 5'u32)
|
||||
crossCheck(uint64, (-1).uint64 + 5'u64)
|
||||
|
||||
doAssert $sub1(0'u8) == "255"
|
||||
doAssert $sub1(0'u16) == "65535"
|
||||
doAssert $sub1(0'u32) == "4294967295"
|
||||
|
||||
doAssert $add1(255'u8) == "0"
|
||||
doAssert $add1(65535'u16) == "0"
|
||||
doAssert $add1(4294967295'u32) == "0"
|
||||
|
||||
crossCheck(int32, high(int32))
|
||||
crossCheck(int32, high(int32).int32)
|
||||
crossCheck(int32, low(int32))
|
||||
crossCheck(int32, low(int32).int32)
|
||||
crossCheck(int64, high(int8).int16.int32.int64)
|
||||
crossCheck(int64, low(int8).int16.int32.int64)
|
||||
|
||||
crossCheck(int64, 0xFFFFFFFFFFFFFFFF'u64)
|
||||
crossCheck(int32, 0xFFFFFFFFFFFFFFFF'u64)
|
||||
crossCheck(int16, 0xFFFFFFFFFFFFFFFF'u64)
|
||||
crossCheck(int8 , 0xFFFFFFFFFFFFFFFF'u64)
|
||||
|
||||
|
||||
|
||||
block tnot:
|
||||
# Signed types
|
||||
block:
|
||||
const t0: int8 = not 4
|
||||
const t1: int16 = not 4
|
||||
const t2: int32 = not 4
|
||||
const t3: int64 = not 4
|
||||
const t4: int8 = not -5
|
||||
const t5: int16 = not -5
|
||||
const t6: int32 = not -5
|
||||
const t7: int64 = not -5
|
||||
doAssert t0 == -5
|
||||
doAssert t1 == -5
|
||||
doAssert t2 == -5
|
||||
doAssert t3 == -5
|
||||
doAssert t4 == 4
|
||||
doAssert t5 == 4
|
||||
doAssert t6 == 4
|
||||
doAssert t7 == 4
|
||||
|
||||
# Unsigned types
|
||||
block:
|
||||
const t0: uint8 = not 4'u8
|
||||
const t1: uint16 = not 4'u16
|
||||
const t2: uint32 = not 4'u32
|
||||
const t3: uint64 = not 4'u64
|
||||
const t4: uint8 = not 251'u8
|
||||
const t5: uint16 = not 65531'u16
|
||||
const t6: uint32 = not 4294967291'u32
|
||||
const t7: uint64 = not 18446744073709551611'u64
|
||||
doAssert t0 == 251
|
||||
doAssert t1 == 65531
|
||||
doAssert t2 == 4294967291'u32
|
||||
doAssert t3 == 18446744073709551611'u64
|
||||
doAssert t4 == 4
|
||||
doAssert t5 == 4
|
||||
doAssert t6 == 4
|
||||
doAssert t7 == 4
|
||||
|
||||
|
||||
|
||||
block tshl:
|
||||
# Signed types
|
||||
block:
|
||||
const t0: int8 = 1'i8 shl 8
|
||||
const t1: int16 = 1'i16 shl 16
|
||||
const t2: int32 = 1'i32 shl 32
|
||||
const t3: int64 = 1'i64 shl 64
|
||||
doAssert t0 == 0
|
||||
doAssert t1 == 0
|
||||
doAssert t2 == 1
|
||||
doAssert t3 == 1
|
||||
|
||||
# Unsigned types
|
||||
block:
|
||||
const t0: uint8 = 1'u8 shl 8
|
||||
const t1: uint16 = 1'u16 shl 16
|
||||
const t2: uint32 = 1'u32 shl 32
|
||||
const t3: uint64 = 1'u64 shl 64
|
||||
doAssert t0 == 0
|
||||
doAssert t1 == 0
|
||||
doAssert t2 == 0
|
||||
doAssert t3 == 1
|
||||
|
||||
|
||||
|
||||
block tshr:
|
||||
proc T() =
|
||||
# let VI = -8
|
||||
let VI64 = -8'i64
|
||||
let VI32 = -8'i32
|
||||
let VI16 = -8'i16
|
||||
let VI8 = -8'i8
|
||||
# doAssert( (VI shr 1) == 9_223_372_036_854_775_804, "Actual: " & $(VI shr 1))
|
||||
doAssert( (VI64 shr 1) == 9_223_372_036_854_775_804, "Actual: " & $(VI64 shr 1))
|
||||
doAssert( (VI32 shr 1) == 2_147_483_644, "Actual: " & $(VI32 shr 1))
|
||||
doAssert( (VI16 shr 1) == 32_764, "Actual: " & $(VI16 shr 1))
|
||||
doAssert( (VI8 shr 1) == 124, "Actual: " & $(VI8 shr 1))
|
||||
|
||||
T()
|
||||
static:
|
||||
T()
|
||||
|
||||
|
||||
|
||||
block tsubrange:
|
||||
# bug #5854
|
||||
type
|
||||
n16 = range[0'i16..high(int16)]
|
||||
|
||||
var level: n16 = 1
|
||||
let maxLevel: n16 = 1
|
||||
|
||||
level = min(level + 2, maxLevel)
|
||||
doAssert level == 1
|
||||
@@ -1,95 +0,0 @@
|
||||
discard """
|
||||
output: '''
|
||||
B0
|
||||
B1
|
||||
B2
|
||||
B3
|
||||
B4
|
||||
B5
|
||||
B6
|
||||
'''
|
||||
"""
|
||||
|
||||
template crossCheck(ty: untyped, exp: untyped) =
|
||||
let rt = ty(exp)
|
||||
const ct = ty(exp)
|
||||
if $rt != $ct:
|
||||
echo "Got ", ct
|
||||
echo "Expected ", rt
|
||||
|
||||
template add1(x: uint8): untyped = x + 1
|
||||
template add1(x: uint16): untyped = x + 1
|
||||
template add1(x: uint32): untyped = x + 1
|
||||
|
||||
template sub1(x: uint8): untyped = x - 1
|
||||
template sub1(x: uint16): untyped = x - 1
|
||||
template sub1(x: uint32): untyped = x - 1
|
||||
|
||||
block:
|
||||
when true:
|
||||
echo "B0"
|
||||
crossCheck(int8, 0'i16 - 5'i16)
|
||||
crossCheck(int16, 0'i32 - 5'i32)
|
||||
crossCheck(int32, 0'i64 - 5'i64)
|
||||
|
||||
echo "B1"
|
||||
crossCheck(uint8, 0'u8 - 5'u8)
|
||||
crossCheck(uint16, 0'u16 - 5'u16)
|
||||
crossCheck(uint32, 0'u32 - 5'u32)
|
||||
crossCheck(uint64, 0'u64 - 5'u64)
|
||||
|
||||
echo "B2"
|
||||
crossCheck(uint8, uint8.high + 5'u8)
|
||||
crossCheck(uint16, uint16.high + 5'u16)
|
||||
crossCheck(uint32, uint32.high + 5'u32)
|
||||
crossCheck(uint64, (-1).uint64 + 5'u64)
|
||||
|
||||
echo "B3"
|
||||
doAssert $sub1(0'u8) == "255"
|
||||
doAssert $sub1(0'u16) == "65535"
|
||||
doAssert $sub1(0'u32) == "4294967295"
|
||||
|
||||
echo "B4"
|
||||
doAssert $add1(255'u8) == "0"
|
||||
doAssert $add1(65535'u16) == "0"
|
||||
doAssert $add1(4294967295'u32) == "0"
|
||||
|
||||
echo "B5"
|
||||
crossCheck(int32, high(int32))
|
||||
crossCheck(int32, high(int32).int32)
|
||||
crossCheck(int32, low(int32))
|
||||
crossCheck(int32, low(int32).int32)
|
||||
crossCheck(int64, high(int8).int16.int32.int64)
|
||||
crossCheck(int64, low(int8).int16.int32.int64)
|
||||
|
||||
echo "B6"
|
||||
crossCheck(int64, 0xFFFFFFFFFFFFFFFF'u64)
|
||||
crossCheck(int32, 0xFFFFFFFFFFFFFFFF'u64)
|
||||
crossCheck(int16, 0xFFFFFFFFFFFFFFFF'u64)
|
||||
crossCheck(int8 , 0xFFFFFFFFFFFFFFFF'u64)
|
||||
|
||||
# Out of range conversion, caught for `let`s only
|
||||
# crossCheck(int8, 0'u8 - 5'u8)
|
||||
# crossCheck(int16, 0'u16 - 5'u16)
|
||||
# crossCheck(int32, 0'u32 - 5'u32)
|
||||
# crossCheck(int64, 0'u64 - 5'u64)
|
||||
|
||||
# crossCheck(int8, 0'u16 - 129'u16)
|
||||
# crossCheck(uint8, 0'i16 + 257'i16)
|
||||
|
||||
# Signed integer {under,over}flow is guarded against
|
||||
|
||||
# crossCheck(int8, int8.high + 5'i8)
|
||||
# crossCheck(int16, int16.high + 5'i16)
|
||||
# crossCheck(int32, int32.high + 5'i32)
|
||||
# crossCheck(int64, int64.high + 5'i64)
|
||||
|
||||
# crossCheck(int8, int8.low - 5'i8)
|
||||
# crossCheck(int16, int16.low - 5'i16)
|
||||
# crossCheck(int32, int32.low - 5'i32)
|
||||
# crossCheck(int64, int64.low - 5'i64)
|
||||
|
||||
# crossCheck(uint8, 0'i8 - 5'i8)
|
||||
# crossCheck(uint16, 0'i16 - 5'i16)
|
||||
# crossCheck(uint32, 0'i32 - 5'i32)
|
||||
# crossCheck(uint64, 0'i64 - 5'i64)
|
||||
@@ -1,58 +0,0 @@
|
||||
discard """
|
||||
output: '''
|
||||
-5
|
||||
-5
|
||||
-5
|
||||
-5
|
||||
4
|
||||
4
|
||||
4
|
||||
4
|
||||
251
|
||||
65531
|
||||
4294967291
|
||||
18446744073709551611
|
||||
4
|
||||
4
|
||||
4
|
||||
4
|
||||
'''
|
||||
"""
|
||||
|
||||
# Signed types
|
||||
block:
|
||||
const t0: int8 = not 4
|
||||
const t1: int16 = not 4
|
||||
const t2: int32 = not 4
|
||||
const t3: int64 = not 4
|
||||
const t4: int8 = not -5
|
||||
const t5: int16 = not -5
|
||||
const t6: int32 = not -5
|
||||
const t7: int64 = not -5
|
||||
echo t0
|
||||
echo t1
|
||||
echo t2
|
||||
echo t3
|
||||
echo t4
|
||||
echo t5
|
||||
echo t6
|
||||
echo t7
|
||||
|
||||
# Unsigned types
|
||||
block:
|
||||
const t0: uint8 = not 4'u8
|
||||
const t1: uint16 = not 4'u16
|
||||
const t2: uint32 = not 4'u32
|
||||
const t3: uint64 = not 4'u64
|
||||
const t4: uint8 = not 251'u8
|
||||
const t5: uint16 = not 65531'u16
|
||||
const t6: uint32 = not 4294967291'u32
|
||||
const t7: uint64 = not 18446744073709551611'u64
|
||||
echo t0
|
||||
echo t1
|
||||
echo t2
|
||||
echo t3
|
||||
echo t4
|
||||
echo t5
|
||||
echo t6
|
||||
echo t7
|
||||
@@ -1,34 +0,0 @@
|
||||
discard """
|
||||
output: '''
|
||||
0
|
||||
0
|
||||
1
|
||||
1
|
||||
0
|
||||
0
|
||||
0
|
||||
1
|
||||
'''
|
||||
"""
|
||||
|
||||
# Signed types
|
||||
block:
|
||||
const t0: int8 = 1'i8 shl 8
|
||||
const t1: int16 = 1'i16 shl 16
|
||||
const t2: int32 = 1'i32 shl 32
|
||||
const t3: int64 = 1'i64 shl 64
|
||||
echo t0
|
||||
echo t1
|
||||
echo t2
|
||||
echo t3
|
||||
|
||||
# Unsigned types
|
||||
block:
|
||||
const t0: uint8 = 1'u8 shl 8
|
||||
const t1: uint16 = 1'u16 shl 16
|
||||
const t2: uint32 = 1'u32 shl 32
|
||||
const t3: uint64 = 1'u64 shl 64
|
||||
echo t0
|
||||
echo t1
|
||||
echo t2
|
||||
echo t3
|
||||
@@ -1,20 +0,0 @@
|
||||
discard """
|
||||
output: ''''''
|
||||
"""
|
||||
|
||||
proc T() =
|
||||
# let VI = -8
|
||||
let VI64 = -8'i64
|
||||
let VI32 = -8'i32
|
||||
let VI16 = -8'i16
|
||||
let VI8 = -8'i8
|
||||
# doAssert( (VI shr 1) == 9_223_372_036_854_775_804, "Actual: " & $(VI shr 1))
|
||||
doAssert( (VI64 shr 1) == 9_223_372_036_854_775_804, "Actual: " & $(VI64 shr 1))
|
||||
doAssert( (VI32 shr 1) == 2_147_483_644, "Actual: " & $(VI32 shr 1))
|
||||
doAssert( (VI16 shr 1) == 32_764, "Actual: " & $(VI16 shr 1))
|
||||
doAssert( (VI8 shr 1) == 124, "Actual: " & $(VI8 shr 1))
|
||||
|
||||
|
||||
T()
|
||||
static:
|
||||
T()
|
||||
@@ -1,13 +0,0 @@
|
||||
discard """
|
||||
output: '''1'''
|
||||
"""
|
||||
|
||||
# bug #5854
|
||||
type
|
||||
n16* = range[0'i16..high(int16)]
|
||||
|
||||
var level: n16 = 1
|
||||
let maxLevel: n16 = 1
|
||||
|
||||
level = min(level + 2, maxLevel)
|
||||
echo level
|
||||
@@ -1,132 +0,0 @@
|
||||
discard """
|
||||
output: "OK"
|
||||
"""
|
||||
|
||||
# bug #7818
|
||||
# this is not a macro bug, but array construction bug
|
||||
# I use macro to avoid object slicing
|
||||
# see #7712 and #7637
|
||||
import macros
|
||||
|
||||
type
|
||||
Vehicle[T] = object of RootObj
|
||||
tire: T
|
||||
Car[T] = object of Vehicle[T]
|
||||
Bike[T] = object of Vehicle[T]
|
||||
|
||||
macro peek(n: typed): untyped =
|
||||
let val = getTypeImpl(n).treeRepr
|
||||
newLit(val)
|
||||
|
||||
block test_t7818:
|
||||
var v = Vehicle[int](tire: 3)
|
||||
var c = Car[int](tire: 4)
|
||||
var b = Bike[int](tire: 2)
|
||||
|
||||
let y = peek([c, b, v])
|
||||
let z = peek([v, c, b])
|
||||
doAssert(y == z)
|
||||
|
||||
block test_t7906_1:
|
||||
proc init(x: typedesc, y: int): ref x =
|
||||
result = new(ref x)
|
||||
result.tire = y
|
||||
|
||||
var v = init(Vehicle[int], 3)
|
||||
var c = init(Car[int], 4)
|
||||
var b = init(Bike[int], 2)
|
||||
|
||||
let y = peek([c, b, v])
|
||||
let z = peek([v, c, b])
|
||||
doAssert(y == z)
|
||||
|
||||
block test_t7906_2:
|
||||
var v = Vehicle[int](tire: 3)
|
||||
var c = Car[int](tire: 4)
|
||||
var b = Bike[int](tire: 2)
|
||||
|
||||
let y = peek([c.addr, b.addr, v.addr])
|
||||
let z = peek([v.addr, c.addr, b.addr])
|
||||
doAssert(y == z)
|
||||
|
||||
block test_t7906_3:
|
||||
type
|
||||
Animal[T] = object of RootObj
|
||||
hair: T
|
||||
Mammal[T] = object of Animal[T]
|
||||
Monkey[T] = object of Mammal[T]
|
||||
|
||||
var v = Animal[int](hair: 3)
|
||||
var c = Mammal[int](hair: 4)
|
||||
var b = Monkey[int](hair: 2)
|
||||
|
||||
let z = peek([c.addr, b.addr, v.addr])
|
||||
let y = peek([v.addr, c.addr, b.addr])
|
||||
doAssert(y == z)
|
||||
|
||||
type
|
||||
Fruit[T] = ref object of RootObj
|
||||
color: T
|
||||
Apple[T] = ref object of Fruit[T]
|
||||
Banana[T] = ref object of Fruit[T]
|
||||
|
||||
proc testArray[T](x: array[3, Fruit[T]]): string =
|
||||
result = ""
|
||||
for c in x:
|
||||
result.add $c.color
|
||||
|
||||
proc testOpenArray[T](x: openArray[Fruit[T]]): string =
|
||||
result = ""
|
||||
for c in x:
|
||||
result.add $c.color
|
||||
|
||||
block test_t7906_4:
|
||||
var v = Fruit[int](color: 3)
|
||||
var c = Apple[int](color: 4)
|
||||
var b = Banana[int](color: 2)
|
||||
|
||||
let y = peek([c, b, v])
|
||||
let z = peek([v, c, b])
|
||||
doAssert(y == z)
|
||||
|
||||
block test_t7906_5:
|
||||
var a = Fruit[int](color: 1)
|
||||
var b = Apple[int](color: 2)
|
||||
var c = Banana[int](color: 3)
|
||||
|
||||
doAssert(testArray([a, b, c]) == "123")
|
||||
doAssert(testArray([b, c, a]) == "231")
|
||||
|
||||
doAssert(testOpenArray([a, b, c]) == "123")
|
||||
doAssert(testOpenArray([b, c, a]) == "231")
|
||||
|
||||
doAssert(testOpenArray(@[a, b, c]) == "123")
|
||||
doAssert(testOpenArray(@[b, c, a]) == "231")
|
||||
|
||||
proc testArray[T](x: array[3, ptr Vehicle[T]]): string =
|
||||
result = ""
|
||||
for c in x:
|
||||
result.add $c.tire
|
||||
|
||||
proc testOpenArray[T](x: openArray[ptr Vehicle[T]]): string =
|
||||
result = ""
|
||||
for c in x:
|
||||
result.add $c.tire
|
||||
|
||||
block test_t7906_6:
|
||||
var u = Vehicle[int](tire: 1)
|
||||
var v = Bike[int](tire: 2)
|
||||
var w = Car[int](tire: 3)
|
||||
|
||||
doAssert(testArray([u.addr, v.addr, w.addr]) == "123")
|
||||
doAssert(testArray([w.addr, u.addr, v.addr]) == "312")
|
||||
|
||||
doAssert(testOpenArray([u.addr, v.addr, w.addr]) == "123")
|
||||
doAssert(testOpenArray([w.addr, u.addr, v.addr]) == "312")
|
||||
|
||||
doAssert(testOpenArray(@[u.addr, v.addr, w.addr]) == "123")
|
||||
doAssert(testOpenArray(@[w.addr, u.addr, v.addr]) == "312")
|
||||
|
||||
echo "OK"
|
||||
|
||||
|
||||
@@ -1,52 +1,534 @@
|
||||
discard """
|
||||
file: "tarray.nim"
|
||||
output: "100124"
|
||||
output:
|
||||
'''
|
||||
[4, 5, 6]
|
||||
|
||||
[16, 25, 36]
|
||||
|
||||
[16, 25, 36]
|
||||
|
||||
apple
|
||||
banana
|
||||
Fruit
|
||||
2
|
||||
4
|
||||
3
|
||||
none
|
||||
skin
|
||||
paper
|
||||
@[2, 3, 4]321
|
||||
9.0 4.0
|
||||
3
|
||||
@[(Field0: 1, Field1: 2), (Field0: 3, Field1: 5)]
|
||||
2
|
||||
@["a", "new one", "c"]
|
||||
@[1, 2, 3]
|
||||
3
|
||||
dflfdjkl__abcdefgasfsgdfgsgdfggsdfasdfsafewfkljdsfajs
|
||||
dflfdjkl__abcdefgasfsgdfgsgdfggsdfasdfsafewfkljdsfajsdf
|
||||
kgdchlfniambejop
|
||||
fjpmholcibdgeakn
|
||||
'''
|
||||
"""
|
||||
# simple check for one dimensional arrays
|
||||
|
||||
block tarray:
|
||||
type
|
||||
TMyArray = array[0..2, int]
|
||||
TMyRecord = tuple[x, y: int]
|
||||
TObj = object
|
||||
arr: TMyarray
|
||||
|
||||
|
||||
proc sum(a: openarray[int]): int =
|
||||
result = 0
|
||||
var i = 0
|
||||
while i < len(a):
|
||||
inc(result, a[i])
|
||||
inc(i)
|
||||
|
||||
proc getPos(r: TMyRecord): int =
|
||||
result = r.x + r.y
|
||||
|
||||
doAssert sum([1, 2, 3, 4]) == 10
|
||||
doAssert sum([]) == 0
|
||||
doAssert getPos( (x: 5, y: 7) ) == 12
|
||||
|
||||
# bug #1669
|
||||
let filesToCreate = ["tempdir/fl1.a", "tempdir/fl2.b",
|
||||
"tempdir/tempdir2/fl3.e", "tempdir/tempdir2/tempdir3/fl4.f"]
|
||||
|
||||
var found: array[0..filesToCreate.high, bool]
|
||||
|
||||
doAssert found.len == 4
|
||||
|
||||
# make sure empty arrays are assignable (bug #6853)
|
||||
const arr1: array[0, int] = []
|
||||
const arr2 = []
|
||||
let arr3: array[0, string] = []
|
||||
|
||||
doAssert(arr1.len == 0)
|
||||
doAssert(arr2.len == 0)
|
||||
doAssert(arr3.len == 0)
|
||||
|
||||
# Negative array length is not allowed (#6852)
|
||||
doAssert(not compiles(block:
|
||||
var arr: array[-1, int]))
|
||||
|
||||
|
||||
proc mul(a, b: TMyarray): TMyArray =
|
||||
result = a
|
||||
for i in 0..len(a)-1:
|
||||
result[i] = a[i] * b[i]
|
||||
|
||||
var
|
||||
x, y: TMyArray
|
||||
o: TObj
|
||||
|
||||
proc varArr1(x: var TMyArray): var TMyArray = x
|
||||
proc varArr2(x: var TObj): var TMyArray = x.arr
|
||||
|
||||
x = [4, 5, 6]
|
||||
echo repr(varArr1(x))
|
||||
|
||||
y = x
|
||||
echo repr(mul(x, y))
|
||||
|
||||
o.arr = mul(x, y)
|
||||
echo repr(varArr2(o))
|
||||
|
||||
|
||||
const
|
||||
myData = [[1,2,3], [4, 5, 6]]
|
||||
|
||||
doAssert myData[0][2] == 3
|
||||
|
||||
|
||||
|
||||
block tarraycons:
|
||||
type
|
||||
TEnum = enum
|
||||
eA, eB, eC, eD, eE, eF
|
||||
|
||||
const
|
||||
myMapping: array[TEnum, array[0..1, int]] = [
|
||||
eA: [1, 2],
|
||||
eB: [3, 4],
|
||||
[5, 6],
|
||||
eD: [0: 8, 1: 9],
|
||||
eE: [0: 8, 9],
|
||||
eF: [2, 1: 9]
|
||||
]
|
||||
|
||||
doAssert myMapping[eC][1] == 6
|
||||
|
||||
|
||||
|
||||
block tarraycons_ptr_generic:
|
||||
type
|
||||
Fruit = object of RootObj
|
||||
name: string
|
||||
Apple = object of Fruit
|
||||
Banana = object of Fruit
|
||||
|
||||
var
|
||||
ir = Fruit(name: "Fruit")
|
||||
ia = Apple(name: "apple")
|
||||
ib = Banana(name: "banana")
|
||||
|
||||
let x = [ia.addr, ib.addr, ir.addr]
|
||||
for c in x: echo c.name
|
||||
|
||||
type
|
||||
Vehicle[T] = object of RootObj
|
||||
tire: T
|
||||
Car[T] = object of Vehicle[T]
|
||||
Bike[T] = object of Vehicle[T]
|
||||
|
||||
var v = Vehicle[int](tire: 3)
|
||||
var c = Car[int](tire: 4)
|
||||
var b = Bike[int](tire: 2)
|
||||
|
||||
let y = [b.addr, c.addr, v.addr]
|
||||
for c in y: echo c.tire
|
||||
|
||||
type
|
||||
Book[T] = ref object of RootObj
|
||||
cover: T
|
||||
Hard[T] = ref object of Book[T]
|
||||
Soft[T] = ref object of Book[T]
|
||||
|
||||
var bn = Book[string](cover: "none")
|
||||
var hs = Hard[string](cover: "skin")
|
||||
var bp = Soft[string](cover: "paper")
|
||||
|
||||
let z = [bn, hs, bp]
|
||||
for c in z: echo c.cover
|
||||
|
||||
|
||||
|
||||
block tarraylen:
|
||||
var a: array[0, int]
|
||||
doAssert a.len == 0
|
||||
doAssert array[0..0, int].len == 1
|
||||
doAssert array[0..0, int]([1]).len == 1
|
||||
doAssert array[1..1, int].len == 1
|
||||
doAssert array[1..1, int]([1]).len == 1
|
||||
doAssert array[2, int].len == 2
|
||||
doAssert array[2, int]([1, 2]).len == 2
|
||||
doAssert array[1..3, int].len == 3
|
||||
doAssert array[1..3, int]([1, 2, 3]).len == 3
|
||||
doAssert array[0..2, int].len == 3
|
||||
doAssert array[0..2, int]([1, 2, 3]).len == 3
|
||||
doAssert array[-2 .. -2, int].len == 1
|
||||
doAssert([1, 2, 3].len == 3)
|
||||
doAssert([42].len == 1)
|
||||
|
||||
|
||||
|
||||
|
||||
type ustring = distinct string
|
||||
converter toUString(s: string): ustring = ustring(s)
|
||||
|
||||
block tarrayindx:
|
||||
proc putEnv(key, val: string) =
|
||||
# XXX: we have to leak memory here, as we cannot
|
||||
# free it before the program ends (says Borland's
|
||||
# documentation)
|
||||
var
|
||||
env: ptr array[0..500000, char]
|
||||
env = cast[ptr array[0..500000, char]](alloc(len(key) + len(val) + 2))
|
||||
for i in 0..len(key)-1: env[i] = key[i]
|
||||
env[len(key)] = '='
|
||||
for i in 0..len(val)-1:
|
||||
env[len(key)+1+i] = val[i]
|
||||
|
||||
# bug #7153
|
||||
const
|
||||
UnsignedConst = 1024'u
|
||||
type
|
||||
SomeObject = object
|
||||
s1: array[UnsignedConst, uint32]
|
||||
|
||||
var
|
||||
obj: SomeObject
|
||||
|
||||
doAssert obj.s1[0] == 0
|
||||
doAssert obj.s1[0u] == 0
|
||||
|
||||
# bug #8049
|
||||
proc `[]`(s: ustring, i: int): ustring = s
|
||||
doAssert "abcdefgh"[1..2] == "bc"
|
||||
doAssert "abcdefgh"[1..^2] == "bcdefg"
|
||||
|
||||
|
||||
|
||||
block troof:
|
||||
proc foo[T](x, y: T): T = x
|
||||
|
||||
var a = @[1, 2, 3, 4]
|
||||
var b: array[3, array[2, float]] = [[1.0,2], [3.0,4], [8.0,9]]
|
||||
echo a[1.. ^1], a[^2], a[^3], a[^4]
|
||||
echo b[^1][^1], " ", (b[^2]).foo(b[^1])[^1]
|
||||
|
||||
b[^1] = [8.8, 8.9]
|
||||
|
||||
var c: seq[(int, int)] = @[(1,2), (3,4)]
|
||||
|
||||
proc takeA(x: ptr int) = echo x[]
|
||||
|
||||
takeA(addr c[^1][0])
|
||||
c[^1][1] = 5
|
||||
echo c
|
||||
|
||||
proc useOpenarray(x: openArray[int]) =
|
||||
echo x[^2]
|
||||
|
||||
proc mutOpenarray(x: var openArray[string]) =
|
||||
x[^2] = "new one"
|
||||
|
||||
useOpenarray([1, 2, 3])
|
||||
|
||||
var z = @["a", "b", "c"]
|
||||
mutOpenarray(z)
|
||||
echo z
|
||||
|
||||
# bug #6675
|
||||
var y: array[1..5, int] = [1,2,3,4,5]
|
||||
y[3..5] = [1, 2, 3]
|
||||
echo y[3..5]
|
||||
|
||||
|
||||
var d: array['a'..'c', string] = ["a", "b", "c"]
|
||||
doAssert d[^1] == "c"
|
||||
|
||||
|
||||
|
||||
|
||||
import strutils, sequtils, typetraits, os
|
||||
|
||||
type
|
||||
TMyArray = array[0..2, int]
|
||||
TMyRecord = tuple[x, y: int]
|
||||
MetadataArray* = object
|
||||
data*: array[8, int]
|
||||
len*: int
|
||||
|
||||
proc sum(a: TMyarray): int =
|
||||
result = 0
|
||||
var i = 0
|
||||
while i < len(a):
|
||||
inc(result, a[i])
|
||||
inc(i)
|
||||
# Commenting the converter removes the error "lib/system.nim(3536, 3) Error: for a 'var' type a variable needs to be passed"
|
||||
converter toMetadataArray*(se: varargs[int]): MetadataArray {.inline.} =
|
||||
result.len = se.len
|
||||
for i in 0..<se.len:
|
||||
result.data[i] = se[i]
|
||||
|
||||
proc sum(a: openarray[int]): int =
|
||||
result = 0
|
||||
var i = 0
|
||||
while i < len(a):
|
||||
inc(result, a[i])
|
||||
inc(i)
|
||||
|
||||
proc getPos(r: TMyRecord): int =
|
||||
result = r.x + r.y
|
||||
block troofregression:
|
||||
when NimVersion >= "0.17.3":
|
||||
type Index = int or BackwardsIndex
|
||||
template `^^`(s, i: untyped): untyped =
|
||||
when i is BackwardsIndex:
|
||||
s.len - int(i)
|
||||
else: i
|
||||
else:
|
||||
type Index = int
|
||||
template `^^`(s, i: untyped): untyped =
|
||||
i
|
||||
|
||||
write(stdout, sum([1, 2, 3, 4]))
|
||||
write(stdout, sum([]))
|
||||
write(stdout, getPos( (x: 5, y: 7) ))
|
||||
#OUT 10012
|
||||
## With Nim devel from the start of the week (~Oct30) I managed to trigger "lib/system.nim(3536, 4) Error: expression has no address"
|
||||
## but I can't anymore after updating Nim (Nov5)
|
||||
## Now commenting this plain compiles and removes the error "lib/system.nim(3536, 3) Error: for a 'var' type a variable needs to be passed"
|
||||
proc `[]`(a: var MetadataArray, idx: Index): var int {.inline.} =
|
||||
a.data[a ^^ idx]
|
||||
|
||||
# bug #1669
|
||||
let filesToCreate = ["tempdir/fl1.a", "tempdir/fl2.b",
|
||||
"tempdir/tempdir2/fl3.e", "tempdir/tempdir2/tempdir3/fl4.f"]
|
||||
|
||||
var found: array[0..filesToCreate.high, bool]
|
||||
##############################
|
||||
### Completely unrelated lib that triggers the issue
|
||||
|
||||
echo found.len
|
||||
type
|
||||
MySeq[T] = ref object
|
||||
data: seq[T]
|
||||
|
||||
# make sure empty arrays are assignable (bug #6853)
|
||||
const arr1: array[0, int] = []
|
||||
const arr2 = []
|
||||
let arr3: array[0, string] = []
|
||||
proc test[T](sx: MySeq[T]) =
|
||||
# Removing the backward index removes the error "lib/system.nim(3536, 3) Error: for a 'var' type a variable needs to be passed"
|
||||
echo sx.data[^1] # error here
|
||||
|
||||
doAssert(arr1.len == 0)
|
||||
doAssert(arr2.len == 0)
|
||||
doAssert(arr3.len == 0)
|
||||
let s = MySeq[int](data: @[1, 2, 3])
|
||||
s.test()
|
||||
|
||||
# Negative array length is not allowed (#6852)
|
||||
doAssert(not compiles(block:
|
||||
var arr: array[-1, int]))
|
||||
|
||||
# bug #6989
|
||||
|
||||
type Dist = distinct int
|
||||
|
||||
proc mypred[T: Ordinal](x: T): T = T(int(x)-1)
|
||||
proc cons(x: int): Dist = Dist(x)
|
||||
|
||||
var d: Dist
|
||||
|
||||
template `^+`(s, i: untyped): untyped =
|
||||
(when i is BackwardsIndex: s.len - int(i) else: int(i))
|
||||
|
||||
proc `...`[T, U](a: T, b: U): HSlice[T, U] =
|
||||
result.a = a
|
||||
result.b = b
|
||||
|
||||
proc `...`[T](b: T): HSlice[int, T] =
|
||||
result.b = b
|
||||
|
||||
template `...<`(a, b: untyped): untyped =
|
||||
## a shortcut for 'a..pred(b)'.
|
||||
a ... pred(b)
|
||||
|
||||
template check(a, b) =
|
||||
if $a != b:
|
||||
echo "Failure ", a, " != ", b
|
||||
|
||||
check type(4 ...< 1), "HSlice[system.int, system.int]"
|
||||
check type(4 ...< ^1), "HSlice[system.int, system.BackwardsIndex]"
|
||||
check type(4 ... pred(^1)), "HSlice[system.int, system.BackwardsIndex]"
|
||||
check type(4 ... mypred(8)), "HSlice[system.int, system.int]"
|
||||
check type(4 ... mypred(^1)), "HSlice[system.int, system.BackwardsIndex]"
|
||||
|
||||
var rot = 8
|
||||
|
||||
proc bug(s: string): string =
|
||||
result = s
|
||||
result = result[result.len - rot .. ^1] & "__" & result[0 ..< ^rot]
|
||||
|
||||
const testStr = "abcdefgasfsgdfgsgdfggsdfasdfsafewfkljdsfajsdflfdjkl"
|
||||
|
||||
echo bug(testStr)
|
||||
echo testStr[testStr.len - 8 .. testStr.len - 1] & "__" & testStr[0 .. testStr.len - pred(rot)]
|
||||
|
||||
var
|
||||
instructions = readFile(getAppDir() / "troofregression2.txt").split(',')
|
||||
programs = "abcdefghijklmnop"
|
||||
|
||||
proc dance(dancers: string): string =
|
||||
result = dancers
|
||||
for instr in instructions:
|
||||
let rem = instr[1 .. instr.high]
|
||||
case instr[0]
|
||||
of 's':
|
||||
let rot = rem.parseInt
|
||||
result = result[result.len - rot .. ^1] & result[0 ..< ^rot]
|
||||
of 'x':
|
||||
let
|
||||
x = rem.split('/')
|
||||
a = x[0].parseInt
|
||||
b = x[1].parseInt
|
||||
swap(result[a], result[b])
|
||||
of 'p':
|
||||
let
|
||||
a = result.find(rem[0])
|
||||
b = result.find(rem[^1])
|
||||
result[a] = rem[^1]
|
||||
result[b] = rem[0]
|
||||
else: discard
|
||||
|
||||
proc longDance(dancers: string, iterations = 1_000_000_000): string =
|
||||
var
|
||||
dancers = dancers
|
||||
seen = @[dancers]
|
||||
for i in 1 .. iterations:
|
||||
dancers = dancers.dance()
|
||||
if dancers in seen:
|
||||
return seen[iterations mod i]
|
||||
seen.add(dancers)
|
||||
|
||||
echo dance(programs)
|
||||
echo longDance(programs)
|
||||
|
||||
|
||||
|
||||
block tunchecked:
|
||||
{.boundchecks: on.}
|
||||
type Unchecked {.unchecked.} = array[0, char]
|
||||
|
||||
var x = cast[ptr Unchecked](alloc(100))
|
||||
x[5] = 'x'
|
||||
|
||||
|
||||
|
||||
import macros
|
||||
block t7818:
|
||||
# bug #7818
|
||||
# this is not a macro bug, but array construction bug
|
||||
# I use macro to avoid object slicing
|
||||
# see #7712 and #7637
|
||||
|
||||
type
|
||||
Vehicle[T] = object of RootObj
|
||||
tire: T
|
||||
Car[T] = object of Vehicle[T]
|
||||
Bike[T] = object of Vehicle[T]
|
||||
|
||||
macro peek(n: typed): untyped =
|
||||
let val = getTypeImpl(n).treeRepr
|
||||
newLit(val)
|
||||
|
||||
block test_t7818:
|
||||
var v = Vehicle[int](tire: 3)
|
||||
var c = Car[int](tire: 4)
|
||||
var b = Bike[int](tire: 2)
|
||||
|
||||
let y = peek([c, b, v])
|
||||
let z = peek([v, c, b])
|
||||
doAssert(y == z)
|
||||
|
||||
block test_t7906_1:
|
||||
proc init(x: typedesc, y: int): ref x =
|
||||
result = new(ref x)
|
||||
result.tire = y
|
||||
|
||||
var v = init(Vehicle[int], 3)
|
||||
var c = init(Car[int], 4)
|
||||
var b = init(Bike[int], 2)
|
||||
|
||||
let y = peek([c, b, v])
|
||||
let z = peek([v, c, b])
|
||||
doAssert(y == z)
|
||||
|
||||
block test_t7906_2:
|
||||
var v = Vehicle[int](tire: 3)
|
||||
var c = Car[int](tire: 4)
|
||||
var b = Bike[int](tire: 2)
|
||||
|
||||
let y = peek([c.addr, b.addr, v.addr])
|
||||
let z = peek([v.addr, c.addr, b.addr])
|
||||
doAssert(y == z)
|
||||
|
||||
block test_t7906_3:
|
||||
type
|
||||
Animal[T] = object of RootObj
|
||||
hair: T
|
||||
Mammal[T] = object of Animal[T]
|
||||
Monkey[T] = object of Mammal[T]
|
||||
|
||||
var v = Animal[int](hair: 3)
|
||||
var c = Mammal[int](hair: 4)
|
||||
var b = Monkey[int](hair: 2)
|
||||
|
||||
let z = peek([c.addr, b.addr, v.addr])
|
||||
let y = peek([v.addr, c.addr, b.addr])
|
||||
doAssert(y == z)
|
||||
|
||||
type
|
||||
Fruit[T] = ref object of RootObj
|
||||
color: T
|
||||
Apple[T] = ref object of Fruit[T]
|
||||
Banana[T] = ref object of Fruit[T]
|
||||
|
||||
proc testArray[T](x: array[3, Fruit[T]]): string =
|
||||
result = ""
|
||||
for c in x:
|
||||
result.add $c.color
|
||||
|
||||
proc testOpenArray[T](x: openArray[Fruit[T]]): string =
|
||||
result = ""
|
||||
for c in x:
|
||||
result.add $c.color
|
||||
|
||||
block test_t7906_4:
|
||||
var v = Fruit[int](color: 3)
|
||||
var c = Apple[int](color: 4)
|
||||
var b = Banana[int](color: 2)
|
||||
|
||||
let y = peek([c, b, v])
|
||||
let z = peek([v, c, b])
|
||||
doAssert(y == z)
|
||||
|
||||
block test_t7906_5:
|
||||
var a = Fruit[int](color: 1)
|
||||
var b = Apple[int](color: 2)
|
||||
var c = Banana[int](color: 3)
|
||||
|
||||
doAssert(testArray([a, b, c]) == "123")
|
||||
doAssert(testArray([b, c, a]) == "231")
|
||||
|
||||
doAssert(testOpenArray([a, b, c]) == "123")
|
||||
doAssert(testOpenArray([b, c, a]) == "231")
|
||||
|
||||
doAssert(testOpenArray(@[a, b, c]) == "123")
|
||||
doAssert(testOpenArray(@[b, c, a]) == "231")
|
||||
|
||||
proc testArray[T](x: array[3, ptr Vehicle[T]]): string =
|
||||
result = ""
|
||||
for c in x:
|
||||
result.add $c.tire
|
||||
|
||||
proc testOpenArray[T](x: openArray[ptr Vehicle[T]]): string =
|
||||
result = ""
|
||||
for c in x:
|
||||
result.add $c.tire
|
||||
|
||||
block test_t7906_6:
|
||||
var u = Vehicle[int](tire: 1)
|
||||
var v = Bike[int](tire: 2)
|
||||
var w = Car[int](tire: 3)
|
||||
|
||||
doAssert(testArray([u.addr, v.addr, w.addr]) == "123")
|
||||
doAssert(testArray([w.addr, u.addr, v.addr]) == "312")
|
||||
|
||||
doAssert(testOpenArray([u.addr, v.addr, w.addr]) == "123")
|
||||
doAssert(testOpenArray([w.addr, u.addr, v.addr]) == "312")
|
||||
|
||||
doAssert(testOpenArray(@[u.addr, v.addr, w.addr]) == "123")
|
||||
doAssert(testOpenArray(@[w.addr, u.addr, v.addr]) == "312")
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
discard """
|
||||
file: "tarray2.nim"
|
||||
output: "[4, 5, 6]\n\n[16, 25, 36]\n\n[16, 25, 36]"
|
||||
"""
|
||||
# simple check for one dimensional arrays
|
||||
|
||||
type
|
||||
TMyArray = array[0..2, int]
|
||||
|
||||
TObj = object
|
||||
arr: TMyarray
|
||||
|
||||
proc mul(a, b: TMyarray): TMyArray =
|
||||
result = a
|
||||
for i in 0..len(a)-1:
|
||||
result[i] = a[i] * b[i]
|
||||
|
||||
var
|
||||
x, y: TMyArray
|
||||
o: TObj
|
||||
|
||||
proc varArr1(x: var TMyArray): var TMyArray = x
|
||||
proc varArr2(x: var TObj): var TMyArray = x.arr
|
||||
|
||||
x = [ 4, 5, 6 ]
|
||||
echo repr(varArr1(x))
|
||||
|
||||
y = x
|
||||
echo repr(mul(x, y))
|
||||
|
||||
o.arr = mul(x, y)
|
||||
echo repr(varArr2(o))
|
||||
|
||||
#OUT [16, 25, 36]
|
||||
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
discard """
|
||||
file: "tarray3.nim"
|
||||
output: "3"
|
||||
"""
|
||||
# simple check for two dimensional arrays
|
||||
|
||||
const
|
||||
myData = [[1,2,3], [4, 5, 6]]
|
||||
|
||||
echo myData[0][2] #OUT 3
|
||||
|
||||
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
discard """
|
||||
file: "tarraycons.nim"
|
||||
output: "6"
|
||||
"""
|
||||
|
||||
type
|
||||
TEnum = enum
|
||||
eA, eB, eC, eD, eE, eF
|
||||
|
||||
const
|
||||
myMapping: array[TEnum, array[0..1, int]] = [
|
||||
eA: [1, 2],
|
||||
eB: [3, 4],
|
||||
[5, 6],
|
||||
eD: [0: 8, 1: 9],
|
||||
eE: [0: 8, 9],
|
||||
eF: [2, 1: 9]
|
||||
]
|
||||
|
||||
echo myMapping[eC][1]
|
||||
|
||||
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
discard """
|
||||
output: '''apple
|
||||
banana
|
||||
Fruit
|
||||
2
|
||||
4
|
||||
3
|
||||
none
|
||||
skin
|
||||
paper
|
||||
'''
|
||||
"""
|
||||
type
|
||||
Fruit = object of RootObj
|
||||
name: string
|
||||
Apple = object of Fruit
|
||||
Banana = object of Fruit
|
||||
|
||||
var
|
||||
ir = Fruit(name: "Fruit")
|
||||
ia = Apple(name: "apple")
|
||||
ib = Banana(name: "banana")
|
||||
|
||||
let x = [ia.addr, ib.addr, ir.addr]
|
||||
for c in x: echo c.name
|
||||
|
||||
type
|
||||
Vehicle[T] = object of RootObj
|
||||
tire: T
|
||||
Car[T] = object of Vehicle[T]
|
||||
Bike[T] = object of Vehicle[T]
|
||||
|
||||
var v = Vehicle[int](tire: 3)
|
||||
var c = Car[int](tire: 4)
|
||||
var b = Bike[int](tire: 2)
|
||||
|
||||
let y = [b.addr, c.addr, v.addr]
|
||||
for c in y: echo c.tire
|
||||
|
||||
type
|
||||
Book[T] = ref object of RootObj
|
||||
cover: T
|
||||
Hard[T] = ref object of Book[T]
|
||||
Soft[T] = ref object of Book[T]
|
||||
|
||||
var bn = Book[string](cover: "none")
|
||||
var hs = Hard[string](cover: "skin")
|
||||
var bp = Soft[string](cover: "paper")
|
||||
|
||||
let z = [bn, hs, bp]
|
||||
for c in z: echo c.cover
|
||||
@@ -1,18 +0,0 @@
|
||||
discard """
|
||||
output: ""
|
||||
"""
|
||||
var a: array[0, int]
|
||||
doAssert a.len == 0
|
||||
doAssert array[0..0, int].len == 1
|
||||
doAssert array[0..0, int]([1]).len == 1
|
||||
doAssert array[1..1, int].len == 1
|
||||
doAssert array[1..1, int]([1]).len == 1
|
||||
doAssert array[2, int].len == 2
|
||||
doAssert array[2, int]([1, 2]).len == 2
|
||||
doAssert array[1..3, int].len == 3
|
||||
doAssert array[1..3, int]([1, 2, 3]).len == 3
|
||||
doAssert array[0..2, int].len == 3
|
||||
doAssert array[0..2, int]([1, 2, 3]).len == 3
|
||||
doAssert array[-2 .. -2, int].len == 1
|
||||
doAssert([1, 2, 3].len == 3)
|
||||
doAssert([42].len == 1)
|
||||
@@ -1,43 +0,0 @@
|
||||
discard """
|
||||
output: '''0
|
||||
0
|
||||
bc
|
||||
bcdefg'''
|
||||
"""
|
||||
|
||||
# test another strange bug ... (I hate this compiler; it is much too buggy!)
|
||||
|
||||
proc putEnv(key, val: string) =
|
||||
# XXX: we have to leak memory here, as we cannot
|
||||
# free it before the program ends (says Borland's
|
||||
# documentation)
|
||||
var
|
||||
env: ptr array[0..500000, char]
|
||||
env = cast[ptr array[0..500000, char]](alloc(len(key) + len(val) + 2))
|
||||
for i in 0..len(key)-1: env[i] = key[i]
|
||||
env[len(key)] = '='
|
||||
for i in 0..len(val)-1:
|
||||
env[len(key)+1+i] = val[i]
|
||||
|
||||
# bug #7153
|
||||
const
|
||||
UnsignedConst = 1024'u
|
||||
type
|
||||
SomeObject* = object
|
||||
s1: array[UnsignedConst, uint32]
|
||||
|
||||
var
|
||||
obj: SomeObject
|
||||
|
||||
echo obj.s1[0]
|
||||
echo obj.s1[0u]
|
||||
|
||||
|
||||
# bug #8049
|
||||
|
||||
when true:
|
||||
type ustring* = distinct string
|
||||
converter toUString*(s: string): ustring = ustring(s)
|
||||
proc `[]`*(s: ustring, i: int): ustring = s
|
||||
echo "abcdefgh"[1..2]
|
||||
echo "abcdefgh"[1..^2]
|
||||
@@ -1,43 +0,0 @@
|
||||
discard """
|
||||
output: '''@[2, 3, 4]321
|
||||
9.0 4.0
|
||||
3
|
||||
@[(Field0: 1, Field1: 2), (Field0: 3, Field1: 5)]
|
||||
2
|
||||
@["a", "new one", "c"]
|
||||
@[1, 2, 3]'''
|
||||
"""
|
||||
|
||||
proc foo[T](x, y: T): T = x
|
||||
|
||||
var a = @[1, 2, 3, 4]
|
||||
var b: array[3, array[2, float]] = [[1.0,2], [3.0,4], [8.0,9]]
|
||||
echo a[1.. ^1], a[^2], a[^3], a[^4]
|
||||
echo b[^1][^1], " ", (b[^2]).foo(b[^1])[^1]
|
||||
|
||||
b[^1] = [8.8, 8.9]
|
||||
|
||||
var c: seq[(int, int)] = @[(1,2), (3,4)]
|
||||
|
||||
proc takeA(x: ptr int) = echo x[]
|
||||
|
||||
takeA(addr c[^1][0])
|
||||
c[^1][1] = 5
|
||||
echo c
|
||||
|
||||
proc useOpenarray(x: openArray[int]) =
|
||||
echo x[^2]
|
||||
|
||||
proc mutOpenarray(x: var openArray[string]) =
|
||||
x[^2] = "new one"
|
||||
|
||||
useOpenarray([1, 2, 3])
|
||||
|
||||
var z = @["a", "b", "c"]
|
||||
mutOpenarray(z)
|
||||
echo z
|
||||
|
||||
# bug #6675
|
||||
var y: array[1..5, int] = [1,2,3,4,5]
|
||||
y[3..5] = [1, 2, 3]
|
||||
echo y[3..5]
|
||||
@@ -1,7 +0,0 @@
|
||||
discard """
|
||||
output: '''c'''
|
||||
"""
|
||||
|
||||
var a: array['a'..'c', string] = ["a", "b", "c"]
|
||||
|
||||
echo a[^1]
|
||||
@@ -1,46 +0,0 @@
|
||||
###############################
|
||||
#### part from Arraymancer
|
||||
|
||||
type
|
||||
MetadataArray* = object
|
||||
data*: array[8, int]
|
||||
len*: int
|
||||
|
||||
# Commenting the converter removes the error "lib/system.nim(3536, 3) Error: for a 'var' type a variable needs to be passed"
|
||||
converter toMetadataArray*(se: varargs[int]): MetadataArray {.inline.} =
|
||||
result.len = se.len
|
||||
for i in 0..<se.len:
|
||||
result.data[i] = se[i]
|
||||
|
||||
|
||||
when NimVersion >= "0.17.3":
|
||||
type Index = int or BackwardsIndex
|
||||
template `^^`(s, i: untyped): untyped =
|
||||
when i is BackwardsIndex:
|
||||
s.len - int(i)
|
||||
else: i
|
||||
else:
|
||||
type Index = int
|
||||
template `^^`(s, i: untyped): untyped =
|
||||
i
|
||||
|
||||
## With Nim devel from the start of the week (~Oct30) I managed to trigger "lib/system.nim(3536, 4) Error: expression has no address"
|
||||
## but I can't anymore after updating Nim (Nov5)
|
||||
## Now commenting this plain compiles and removes the error "lib/system.nim(3536, 3) Error: for a 'var' type a variable needs to be passed"
|
||||
proc `[]`*(a: var MetadataArray, idx: Index): var int {.inline.} =
|
||||
a.data[a ^^ idx]
|
||||
|
||||
|
||||
##############################
|
||||
### Completely unrelated lib that triggers the issue
|
||||
|
||||
type
|
||||
MySeq[T] = ref object
|
||||
data: seq[T]
|
||||
|
||||
proc test[T](sx: MySeq[T]) =
|
||||
# Removing the backward index removes the error "lib/system.nim(3536, 3) Error: for a 'var' type a variable needs to be passed"
|
||||
echo sx.data[^1] # error here
|
||||
|
||||
let s = MySeq[int](data: @[1, 2, 3])
|
||||
s.test()
|
||||
@@ -1,102 +0,0 @@
|
||||
discard """
|
||||
output: '''OK
|
||||
OK
|
||||
OK
|
||||
OK
|
||||
OK
|
||||
dflfdjkl__abcdefgasfsgdfgsgdfggsdfasdfsafewfkljdsfajs
|
||||
dflfdjkl__abcdefgasfsgdfgsgdfggsdfasdfsafewfkljdsfajsdf
|
||||
kgdchlfniambejop
|
||||
fjpmholcibdgeakn
|
||||
'''
|
||||
"""
|
||||
|
||||
import strutils, sequtils, typetraits, os
|
||||
# bug #6989
|
||||
|
||||
type Dist = distinct int
|
||||
|
||||
proc mypred[T: Ordinal](x: T): T = T(int(x)-1)
|
||||
proc cons(x: int): Dist = Dist(x)
|
||||
|
||||
var d: Dist
|
||||
|
||||
template `^+`(s, i: untyped): untyped =
|
||||
(when i is BackwardsIndex: s.len - int(i) else: int(i))
|
||||
|
||||
proc `...`*[T, U](a: T, b: U): HSlice[T, U] =
|
||||
result.a = a
|
||||
result.b = b
|
||||
|
||||
proc `...`*[T](b: T): HSlice[int, T] =
|
||||
result.b = b
|
||||
|
||||
template `...<`*(a, b: untyped): untyped =
|
||||
## a shortcut for 'a..pred(b)'.
|
||||
a ... pred(b)
|
||||
|
||||
template check(a, b) =
|
||||
if $a == b: echo "OK"
|
||||
else: echo "Failure ", a, " != ", b
|
||||
|
||||
check type(4 ...< 1), "HSlice[system.int, system.int]"
|
||||
|
||||
check type(4 ...< ^1), "HSlice[system.int, system.BackwardsIndex]"
|
||||
check type(4 ... pred(^1)), "HSlice[system.int, system.BackwardsIndex]"
|
||||
|
||||
check type(4 ... mypred(8)), "HSlice[system.int, system.int]"
|
||||
|
||||
check type(4 ... mypred(^1)), "HSlice[system.int, system.BackwardsIndex]"
|
||||
|
||||
var rot = 8
|
||||
|
||||
proc bug(s: string): string =
|
||||
result = s
|
||||
result = result[result.len - rot .. ^1] & "__" & result[0 ..< ^rot]
|
||||
|
||||
const testStr = "abcdefgasfsgdfgsgdfggsdfasdfsafewfkljdsfajsdflfdjkl"
|
||||
|
||||
echo bug(testStr)
|
||||
echo testStr[testStr.len - 8 .. testStr.len - 1] & "__" & testStr[0 .. testStr.len - pred(rot)]
|
||||
|
||||
|
||||
|
||||
var
|
||||
instructions = readFile(getAppDir() / "troofregression2.txt").split(',')
|
||||
programs = "abcdefghijklmnop"
|
||||
|
||||
proc dance(dancers: string): string =
|
||||
result = dancers
|
||||
for instr in instructions:
|
||||
let rem = instr[1 .. instr.high]
|
||||
case instr[0]
|
||||
of 's':
|
||||
let rot = rem.parseInt
|
||||
result = result[result.len - rot .. ^1] & result[0 ..< ^rot]
|
||||
of 'x':
|
||||
let
|
||||
x = rem.split('/')
|
||||
a = x[0].parseInt
|
||||
b = x[1].parseInt
|
||||
swap(result[a], result[b])
|
||||
of 'p':
|
||||
let
|
||||
a = result.find(rem[0])
|
||||
b = result.find(rem[^1])
|
||||
result[a] = rem[^1]
|
||||
result[b] = rem[0]
|
||||
else: discard
|
||||
|
||||
proc longDance(dancers: string, iterations = 1_000_000_000): string =
|
||||
var
|
||||
dancers = dancers
|
||||
seen = @[dancers]
|
||||
for i in 1 .. iterations:
|
||||
dancers = dancers.dance()
|
||||
if dancers in seen:
|
||||
return seen[iterations mod i]
|
||||
seen.add(dancers)
|
||||
|
||||
|
||||
echo dance(programs)
|
||||
echo longDance(programs)
|
||||
@@ -1,5 +0,0 @@
|
||||
{.boundchecks: on.}
|
||||
type Unchecked {.unchecked.} = array[0, char]
|
||||
|
||||
var x = cast[ptr Unchecked](alloc(100))
|
||||
x[5] = 'x'
|
||||
@@ -1,31 +1,208 @@
|
||||
discard """
|
||||
file: "tassign.nim"
|
||||
output:
|
||||
'''
|
||||
TEMP=C:\Programs\xyz\bin
|
||||
8 5 0 0
|
||||
pre test a:test b:1 c:2 haha:3
|
||||
assignment test a:test b:1 c:2 haha:3
|
||||
Concrete '='
|
||||
Concrete '='
|
||||
Concrete '='
|
||||
Concrete '='
|
||||
Concrete '='
|
||||
GenericT[T] '=' int
|
||||
GenericT[T] '=' float
|
||||
GenericT[T] '=' float
|
||||
GenericT[T] '=' float
|
||||
GenericT[T] '=' string
|
||||
GenericT[T] '=' int8
|
||||
GenericT[T] '=' bool
|
||||
GenericT[T] '=' bool
|
||||
GenericT[T] '=' bool
|
||||
GenericT[T] '=' bool
|
||||
'''
|
||||
"""
|
||||
|
||||
block tassign:
|
||||
# Test the assignment operator for complex types which need RTTI
|
||||
type
|
||||
TRec = object
|
||||
x, y: int
|
||||
s: string
|
||||
seq: seq[string]
|
||||
arr: seq[seq[array[0..3, string]]]
|
||||
TRecSeq = seq[TRec]
|
||||
|
||||
type
|
||||
TRec = object
|
||||
x, y: int
|
||||
s: string
|
||||
seq: seq[string]
|
||||
arr: seq[seq[array[0..3, string]]]
|
||||
TRecSeq = seq[TRec]
|
||||
proc test() =
|
||||
var
|
||||
a, b: TRec
|
||||
a.x = 1
|
||||
a.y = 2
|
||||
a.s = "Hallo!"
|
||||
a.seq = @["abc", "def", "ghi", "jkl"]
|
||||
a.arr = @[]
|
||||
setLen(a.arr, 4)
|
||||
a.arr[0] = @[]
|
||||
a.arr[1] = @[]
|
||||
|
||||
b = a # perform a deep copy here!
|
||||
b.seq = @["xyz", "huch", "was", "soll"]
|
||||
doAssert len(a.seq) == 4
|
||||
doAssert a.seq[3] == "jkl"
|
||||
doAssert len(b.seq) == 4
|
||||
doAssert b.seq[3] == "soll"
|
||||
doAssert b.y == 2
|
||||
|
||||
test()
|
||||
|
||||
|
||||
|
||||
import strutils
|
||||
block tcopy:
|
||||
proc main() =
|
||||
const
|
||||
example = r"TEMP=C:\Programs\xyz\bin"
|
||||
var
|
||||
a, b: string
|
||||
p: int
|
||||
p = find(example, "=")
|
||||
a = substr(example, 0, p-1)
|
||||
b = substr(example, p+1)
|
||||
writeLine(stdout, a & '=' & b)
|
||||
|
||||
main()
|
||||
|
||||
|
||||
|
||||
block tgenericassign:
|
||||
type
|
||||
TAny = object {.pure.}
|
||||
value: pointer
|
||||
rawType: pointer
|
||||
|
||||
proc newAny(value, rawType: pointer): TAny =
|
||||
result.value = value
|
||||
result.rawType = rawType
|
||||
|
||||
var name: cstring = "example"
|
||||
|
||||
var ret: seq[tuple[name: string, a: TAny]] = @[]
|
||||
for i in 0 .. 8000:
|
||||
var tup = ($name, newAny(nil, nil))
|
||||
assert(tup[0] == "example")
|
||||
ret.add(tup)
|
||||
assert(ret[ret.len()-1][0] == "example")
|
||||
|
||||
|
||||
|
||||
block tgenericassign_tuples:
|
||||
var t, s: tuple[x: string, c: int]
|
||||
|
||||
proc ugh: seq[tuple[x: string, c: int]] =
|
||||
result = @[("abc", 232)]
|
||||
|
||||
t = ugh()[0]
|
||||
s = t
|
||||
s = ugh()[0]
|
||||
|
||||
doAssert s[0] == "abc"
|
||||
doAssert s[1] == 232
|
||||
|
||||
|
||||
|
||||
block tobjasgn:
|
||||
type
|
||||
TSomeObj = object of RootObj
|
||||
a, b: int
|
||||
PSomeObj = ref object
|
||||
a, b: int
|
||||
|
||||
var a = TSomeObj(a: 8)
|
||||
var b = PSomeObj(a: 5)
|
||||
echo a.a, " ", b.a, " ", a.b, " ", b.b
|
||||
|
||||
# bug #575
|
||||
|
||||
type
|
||||
Something = object of RootObj
|
||||
a: string
|
||||
b, c: int32
|
||||
|
||||
type
|
||||
Other = object of Something
|
||||
haha: int
|
||||
|
||||
proc `$`(x: Other): string =
|
||||
result = "a:" & x.a & " b:" & $x.b & " c:" & $x.c & " haha:" & $x.haha
|
||||
|
||||
proc test() =
|
||||
var
|
||||
a, b: TRec
|
||||
a.x = 1
|
||||
a.y = 2
|
||||
a.s = "Hallo!"
|
||||
a.seq = @["abc", "def", "ghi", "jkl"]
|
||||
a.arr = @[]
|
||||
setLen(a.arr, 4)
|
||||
a.arr[0] = @[]
|
||||
a.arr[1] = @[]
|
||||
t: Other
|
||||
|
||||
b = a # perform a deep copy here!
|
||||
b.seq = @["xyz", "huch", "was", "soll"]
|
||||
writeLine(stdout, len(a.seq))
|
||||
writeLine(stdout, a.seq[3])
|
||||
writeLine(stdout, len(b.seq))
|
||||
writeLine(stdout, b.seq[3])
|
||||
writeLine(stdout, b.y)
|
||||
t.a = "test"
|
||||
t.b = 1
|
||||
t.c = 2
|
||||
t.haha = 3
|
||||
|
||||
test()
|
||||
echo "pre test ", $t
|
||||
var x = t
|
||||
echo "assignment test ", x
|
||||
|
||||
|
||||
import typetraits
|
||||
block toverload_asgn:
|
||||
type
|
||||
Concrete = object
|
||||
a, b: string
|
||||
|
||||
proc `=`(d: var Concrete; src: Concrete) =
|
||||
shallowCopy(d.a, src.a)
|
||||
shallowCopy(d.b, src.b)
|
||||
echo "Concrete '='"
|
||||
|
||||
var x, y: array[0..2, Concrete]
|
||||
var cA, cB: Concrete
|
||||
|
||||
var cATup, cBTup: tuple[x: int, ha: Concrete]
|
||||
|
||||
x = y
|
||||
cA = cB
|
||||
cATup = cBTup
|
||||
|
||||
type
|
||||
GenericT[T] = object
|
||||
a, b: T
|
||||
|
||||
proc `=`[T](d: var GenericT[T]; src: GenericT[T]) =
|
||||
shallowCopy(d.a, src.a)
|
||||
shallowCopy(d.b, src.b)
|
||||
echo "GenericT[T] '=' ", type(T).name
|
||||
|
||||
var ag: GenericT[int]
|
||||
var bg: GenericT[int]
|
||||
|
||||
ag = bg
|
||||
|
||||
var xg, yg: array[0..2, GenericT[float]]
|
||||
var cAg, cBg: GenericT[string]
|
||||
|
||||
var cATupg, cBTupg: tuple[x: int, ha: GenericT[int8]]
|
||||
|
||||
xg = yg
|
||||
cAg = cBg
|
||||
cATupg = cBTupg
|
||||
|
||||
var caSeqg, cbSeqg: seq[GenericT[bool]]
|
||||
newSeq(cbSeqg, 4)
|
||||
caSeqg = cbSeqg
|
||||
|
||||
when false:
|
||||
type
|
||||
Foo = object
|
||||
case b: bool
|
||||
of false: xx: GenericT[int]
|
||||
of true: yy: bool
|
||||
|
||||
var
|
||||
a, b: Foo
|
||||
a = b
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
discard """
|
||||
file: "tcopy.nim"
|
||||
output: "TEMP=C:\\Programs\\xyz\\bin"
|
||||
"""
|
||||
# tests the substr proc
|
||||
|
||||
import
|
||||
strutils
|
||||
|
||||
proc main() =
|
||||
const
|
||||
example = r"TEMP=C:\Programs\xyz\bin"
|
||||
var
|
||||
a, b: string
|
||||
p: int
|
||||
p = find(example, "=")
|
||||
a = substr(example, 0, p-1)
|
||||
b = substr(example, p+1)
|
||||
writeLine(stdout, a & '=' & b)
|
||||
#writeLine(stdout, b)
|
||||
|
||||
main()
|
||||
#OUT TEMP=C:\Programs\xyz\bin
|
||||
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
discard """
|
||||
output: '''came here'''
|
||||
"""
|
||||
|
||||
type
|
||||
TAny* = object {.pure.}
|
||||
value*: pointer
|
||||
rawType: pointer
|
||||
|
||||
proc newAny(value, rawType: pointer): TAny =
|
||||
result.value = value
|
||||
result.rawType = rawType
|
||||
|
||||
var name: cstring = "example"
|
||||
|
||||
var ret: seq[tuple[name: string, a: TAny]] = @[]
|
||||
for i in 0..8000:
|
||||
var tup = ($name, newAny(nil, nil))
|
||||
assert(tup[0] == "example")
|
||||
ret.add(tup)
|
||||
assert(ret[ret.len()-1][0] == "example")
|
||||
|
||||
echo "came here"
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
discard """
|
||||
output: '''abc232'''
|
||||
"""
|
||||
|
||||
var t, s: tuple[x: string, c: int]
|
||||
|
||||
proc ugh: seq[tuple[x: string, c: int]] =
|
||||
result = @[("abc", 232)]
|
||||
|
||||
t = ugh()[0]
|
||||
s = t
|
||||
s = ugh()[0]
|
||||
|
||||
echo s[0], t[1]
|
||||
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
discard """
|
||||
output: '''8 5 0 0
|
||||
pre test a:test b:1 c:2 haha:3
|
||||
assignment test a:test b:1 c:2 haha:3
|
||||
'''
|
||||
"""
|
||||
|
||||
# bug #1005
|
||||
|
||||
type
|
||||
TSomeObj = object of RootObj
|
||||
a, b: int
|
||||
PSomeObj = ref object
|
||||
a, b: int
|
||||
|
||||
var a = TSomeObj(a: 8)
|
||||
var b = PSomeObj(a: 5)
|
||||
echo a.a, " ", b.a, " ", a.b, " ", b.b
|
||||
|
||||
# bug #575
|
||||
|
||||
type
|
||||
Something = object of RootObj
|
||||
a: string
|
||||
b, c: int32
|
||||
|
||||
type
|
||||
Other = object of Something
|
||||
haha: int
|
||||
|
||||
proc `$`(x: Other): string =
|
||||
result = "a:" & x.a & " b:" & $x.b & " c:" & $x.c & " haha:" & $x.haha
|
||||
|
||||
var
|
||||
t: Other
|
||||
|
||||
t.a = "test"
|
||||
t.b = 1
|
||||
t.c = 2
|
||||
t.haha = 3
|
||||
|
||||
echo "pre test ", $t
|
||||
var x = t
|
||||
echo "assignment test ", x
|
||||
@@ -1,76 +0,0 @@
|
||||
discard """
|
||||
output: '''Concrete '='
|
||||
Concrete '='
|
||||
Concrete '='
|
||||
Concrete '='
|
||||
Concrete '='
|
||||
GenericT[T] '=' int
|
||||
GenericT[T] '=' float
|
||||
GenericT[T] '=' float
|
||||
GenericT[T] '=' float
|
||||
GenericT[T] '=' string
|
||||
GenericT[T] '=' int8
|
||||
GenericT[T] '=' bool
|
||||
GenericT[T] '=' bool
|
||||
GenericT[T] '=' bool
|
||||
GenericT[T] '=' bool'''
|
||||
disabled: "true"
|
||||
"""
|
||||
|
||||
import typetraits
|
||||
|
||||
type
|
||||
Concrete = object
|
||||
a, b: string
|
||||
|
||||
proc `=`(d: var Concrete; src: Concrete) =
|
||||
shallowCopy(d.a, src.a)
|
||||
shallowCopy(d.b, src.b)
|
||||
echo "Concrete '='"
|
||||
|
||||
var x, y: array[0..2, Concrete]
|
||||
var cA, cB: Concrete
|
||||
|
||||
var cATup, cBTup: tuple[x: int, ha: Concrete]
|
||||
|
||||
x = y
|
||||
cA = cB
|
||||
cATup = cBTup
|
||||
|
||||
type
|
||||
GenericT[T] = object
|
||||
a, b: T
|
||||
|
||||
proc `=`[T](d: var GenericT[T]; src: GenericT[T]) =
|
||||
shallowCopy(d.a, src.a)
|
||||
shallowCopy(d.b, src.b)
|
||||
echo "GenericT[T] '=' ", type(T).name
|
||||
|
||||
var ag: GenericT[int]
|
||||
var bg: GenericT[int]
|
||||
|
||||
ag = bg
|
||||
|
||||
var xg, yg: array[0..2, GenericT[float]]
|
||||
var cAg, cBg: GenericT[string]
|
||||
|
||||
var cATupg, cBTupg: tuple[x: int, ha: GenericT[int8]]
|
||||
|
||||
xg = yg
|
||||
cAg = cBg
|
||||
cATupg = cBTupg
|
||||
|
||||
var caSeqg, cbSeqg: seq[GenericT[bool]]
|
||||
newSeq(cbSeqg, 4)
|
||||
caSeqg = cbSeqg
|
||||
|
||||
when false:
|
||||
type
|
||||
Foo = object
|
||||
case b: bool
|
||||
of false: xx: GenericT[int]
|
||||
of true: yy: bool
|
||||
|
||||
var
|
||||
a, b: Foo
|
||||
a = b
|
||||
69
tests/bind/tbind.nim
Normal file
69
tests/bind/tbind.nim
Normal file
@@ -0,0 +1,69 @@
|
||||
discard """
|
||||
file: "tbind.nim"
|
||||
output:
|
||||
'''
|
||||
3
|
||||
1
|
||||
1
|
||||
1
|
||||
'''
|
||||
"""
|
||||
|
||||
|
||||
block tbind:
|
||||
# Test the new ``bind`` keyword for templates
|
||||
|
||||
proc p1(x: int8, y: int): int = return x + y
|
||||
|
||||
template tempBind(x, y): untyped =
|
||||
bind p1
|
||||
p1(x, y)
|
||||
|
||||
proc p1(x: int, y: int8): int = return x - y
|
||||
|
||||
# This is tricky: the call to ``p1(1'i8, 2'i8)`` should not fail in line 6,
|
||||
# because it is not ambiguous there. But it is ambiguous after line 8.
|
||||
|
||||
echo tempBind(1'i8, 2'i8) #OUT 3
|
||||
|
||||
|
||||
import mbind3
|
||||
echo genId() #OUT 1
|
||||
|
||||
|
||||
import strtabs
|
||||
block tbinoverload:
|
||||
template t() =
|
||||
block:
|
||||
bind newStringTable
|
||||
discard {"Content-Type": "text/html"}.newStringTable()
|
||||
|
||||
discard {:}.newStringTable
|
||||
#discard {"Content-Type": "text/html"}.newStringTable()
|
||||
t()
|
||||
|
||||
|
||||
block tmixin:
|
||||
type
|
||||
TFoo1 = object of RootObj
|
||||
v: int
|
||||
TFoo2 = object of TFoo1
|
||||
v2: int
|
||||
|
||||
proc test(f: TFoo1) =
|
||||
echo "1"
|
||||
|
||||
proc Foo[T](f: T) =
|
||||
mixin test
|
||||
test(f)
|
||||
|
||||
var
|
||||
a: TFoo1
|
||||
b: TFoo2
|
||||
|
||||
|
||||
proc test(f: TFoo2) =
|
||||
echo "2"
|
||||
|
||||
Foo(a)
|
||||
Foo(b)
|
||||
@@ -1,21 +0,0 @@
|
||||
discard """
|
||||
file: "tbind1.nim"
|
||||
output: "3"
|
||||
"""
|
||||
# Test the new ``bind`` keyword for templates
|
||||
|
||||
proc p1(x: int8, y: int): int = return x + y
|
||||
|
||||
template tempBind(x, y): untyped =
|
||||
bind p1
|
||||
p1(x, y)
|
||||
|
||||
proc p1(x: int, y: int8): int = return x - y
|
||||
|
||||
# This is tricky: the call to ``p1(1'i8, 2'i8)`` should not fail in line 6,
|
||||
# because it is not ambiguous there. But it is ambiguous after line 8.
|
||||
|
||||
echo tempBind(1'i8, 2'i8) #OUT 3
|
||||
|
||||
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
discard """
|
||||
file: "tbind3.nim"
|
||||
output: "1"
|
||||
"""
|
||||
# Module B
|
||||
import mbind3
|
||||
|
||||
echo genId() #OUT 1
|
||||
|
||||
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
import strtabs
|
||||
|
||||
template t*() =
|
||||
block:
|
||||
bind newStringTable
|
||||
discard {"Content-Type": "text/html"}.newStringTable()
|
||||
|
||||
discard {:}.newStringTable
|
||||
|
||||
#discard {"Content-Type": "text/html"}.newStringTable()
|
||||
|
||||
t()
|
||||
@@ -1,27 +0,0 @@
|
||||
discard """
|
||||
output: "1\n2"
|
||||
"""
|
||||
|
||||
type
|
||||
TFoo1 = object of RootObj
|
||||
v: int
|
||||
TFoo2 = object of TFoo1
|
||||
v2: int
|
||||
|
||||
proc test(f: TFoo1) =
|
||||
echo "1"
|
||||
|
||||
proc Foo[T](f: T) =
|
||||
mixin test
|
||||
test(f)
|
||||
|
||||
var
|
||||
a: TFoo1
|
||||
b: TFoo2
|
||||
|
||||
|
||||
proc test(f: TFoo2) =
|
||||
echo "2"
|
||||
|
||||
Foo(a)
|
||||
Foo(b)
|
||||
@@ -1,10 +0,0 @@
|
||||
discard """
|
||||
output: "1"
|
||||
"""
|
||||
|
||||
converter toInt*(x: char): int =
|
||||
x.int
|
||||
|
||||
case 0
|
||||
of 'a': echo 0
|
||||
else: echo 1
|
||||
@@ -1,19 +0,0 @@
|
||||
discard """
|
||||
output: '''Not found!
|
||||
Found!'''
|
||||
"""
|
||||
|
||||
const
|
||||
md_extension = [".md", ".markdown"]
|
||||
|
||||
proc test(ext: string) =
|
||||
case ext
|
||||
of ".txt", md_extension:
|
||||
echo "Found!"
|
||||
else:
|
||||
echo "Not found!"
|
||||
|
||||
test(".something")
|
||||
# ensure it's not evaluated at compile-time:
|
||||
var foo = ".markdown"
|
||||
test(foo)
|
||||
@@ -1,24 +0,0 @@
|
||||
discard """
|
||||
file: "tcaseofwhen.nim"
|
||||
outputsub: "compiles for 1\ni am always two\ndefault for 3\nset is 4 not 5\narray is 6 not 7\ndefault for 8"
|
||||
exitcode: "0"
|
||||
"""
|
||||
|
||||
proc whenCase(a: int) =
|
||||
case a
|
||||
of (when compiles(whenCase(1)): 1 else: {}): echo "compiles for 1"
|
||||
of {}: echo "me not fail"
|
||||
of 2: echo "i am always two"
|
||||
of []: echo "me neither"
|
||||
of {4,5}: echo "set is 4 not 5"
|
||||
of [6,7]: echo "array is 6 not 7"
|
||||
of (when compiles(neverCompilesIBet()): 3 else: {}): echo "compiles for 3"
|
||||
#of {},[]: echo "me neither"
|
||||
else: echo "default for ", a
|
||||
|
||||
whenCase(1)
|
||||
whenCase(2)
|
||||
whenCase(3)
|
||||
whenCase(4)
|
||||
whenCase(6)
|
||||
whenCase(8)
|
||||
@@ -1,15 +0,0 @@
|
||||
discard """
|
||||
output: "an identifier"
|
||||
"""
|
||||
|
||||
const
|
||||
SymChars: set[char] = {'a'..'z', 'A'..'Z', '\x80'..'\xFF'}
|
||||
|
||||
proc classify(s: string) =
|
||||
case s[0]
|
||||
of SymChars, '_': echo "an identifier"
|
||||
of {'0'..'9'}: echo "a number"
|
||||
else: echo "other"
|
||||
|
||||
classify("Hurra")
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
discard """
|
||||
file: "tcasestm.nim"
|
||||
output: "ayyydd"
|
||||
"""
|
||||
# Test the case statement
|
||||
|
||||
type
|
||||
Tenum = enum eA, eB, eC
|
||||
|
||||
var
|
||||
x: string = "yyy"
|
||||
y: Tenum = eA
|
||||
i: int
|
||||
|
||||
case y
|
||||
of eA: write(stdout, "a")
|
||||
of eB, eC: write(stdout, "b or c")
|
||||
|
||||
case x
|
||||
of "Andreas", "Rumpf": write(stdout, "Hallo Meister!")
|
||||
of "aa", "bb": write(stdout, "Du bist nicht mein Meister")
|
||||
of "cc", "hash", "when": discard
|
||||
of "will", "it", "finally", "be", "generated": discard
|
||||
|
||||
var z = case i
|
||||
of 1..5, 8, 9: "aa"
|
||||
of 6, 7: "bb"
|
||||
elif x == "Ha":
|
||||
"cc"
|
||||
elif x == "yyy":
|
||||
write(stdout, x)
|
||||
"dd"
|
||||
else:
|
||||
"zz"
|
||||
|
||||
echo z
|
||||
#OUT ayyy
|
||||
|
||||
let str1 = "Y"
|
||||
let str2 = "NN"
|
||||
let a = case str1:
|
||||
of "Y": true
|
||||
of "N": false
|
||||
else:
|
||||
echo "no good"
|
||||
quit("quiting")
|
||||
|
||||
proc toBool(s: string): bool =
|
||||
case s:
|
||||
of "": raise newException(ValueError, "Invalid boolean")
|
||||
elif s[0] == 'Y': true
|
||||
elif s[0] == 'N': false
|
||||
else: "error".quit(2)
|
||||
|
||||
|
||||
let b = "NN".toBool()
|
||||
|
||||
doAssert(a == true)
|
||||
doAssert(b == false)
|
||||
|
||||
static:
|
||||
#bug #7407
|
||||
let bstatic = "N".toBool()
|
||||
doAssert(bstatic == false)
|
||||
|
||||
var bb: bool
|
||||
doassert(not compiles(
|
||||
bb = case str2:
|
||||
of "": raise newException(ValueError, "Invalid boolean")
|
||||
elif str.startsWith("Y"): true
|
||||
elif str.startsWith("N"): false
|
||||
))
|
||||
|
||||
doassert(not compiles(
|
||||
bb = case str2:
|
||||
of "Y": true
|
||||
of "N": false
|
||||
))
|
||||
|
||||
doassert(not compiles(
|
||||
bb = case str2:
|
||||
of "Y": true
|
||||
of "N": raise newException(ValueError, "N not allowed")
|
||||
))
|
||||
|
||||
doassert(not compiles(
|
||||
bb = case str2:
|
||||
of "Y": raise newException(ValueError, "Invalid Y")
|
||||
else: raise newException(ValueError, "Invalid N")
|
||||
))
|
||||
|
||||
|
||||
doassert(not compiles(
|
||||
bb = case str2:
|
||||
of "Y":
|
||||
raise newException(ValueError, "Invalid Y")
|
||||
true
|
||||
else: raise newException(ValueError, "Invalid")
|
||||
))
|
||||
|
||||
|
||||
doassert(not compiles(
|
||||
bb = case str2:
|
||||
of "Y":
|
||||
"invalid Y".quit(3)
|
||||
true
|
||||
else: raise newException(ValueError, "Invalid")
|
||||
))
|
||||
229
tests/casestmt/tcasestmt.nim
Normal file
229
tests/casestmt/tcasestmt.nim
Normal file
@@ -0,0 +1,229 @@
|
||||
discard """
|
||||
file: "tcasestmt.nim"
|
||||
output:
|
||||
'''
|
||||
Not found!
|
||||
Found!
|
||||
1
|
||||
compiles for 1
|
||||
i am always two
|
||||
default for 3
|
||||
set is 4 not 5
|
||||
array is 6 not 7
|
||||
default for 8
|
||||
an identifier
|
||||
OK
|
||||
OK
|
||||
OK
|
||||
ayyydd
|
||||
'''
|
||||
"""
|
||||
|
||||
|
||||
block arrayconstr:
|
||||
const md_extension = [".md", ".markdown"]
|
||||
|
||||
proc test(ext: string) =
|
||||
case ext
|
||||
of ".txt", md_extension:
|
||||
echo "Found!"
|
||||
else:
|
||||
echo "Not found!"
|
||||
|
||||
test(".something")
|
||||
# ensure it's not evaluated at compile-time:
|
||||
var foo = ".markdown"
|
||||
test(foo)
|
||||
|
||||
|
||||
converter toInt(x: char): int =
|
||||
x.int
|
||||
block t8333:
|
||||
case 0
|
||||
of 'a': echo 0
|
||||
else: echo 1
|
||||
|
||||
|
||||
block emptyset_when:
|
||||
proc whenCase(a: int) =
|
||||
case a
|
||||
of (when compiles(whenCase(1)): 1 else: {}): echo "compiles for 1"
|
||||
of {}: echo "me not fail"
|
||||
of 2: echo "i am always two"
|
||||
of []: echo "me neither"
|
||||
of {4,5}: echo "set is 4 not 5"
|
||||
of [6,7]: echo "array is 6 not 7"
|
||||
of (when compiles(neverCompilesIBet()): 3 else: {}): echo "compiles for 3"
|
||||
#of {},[]: echo "me neither"
|
||||
else: echo "default for ", a
|
||||
|
||||
whenCase(1)
|
||||
whenCase(2)
|
||||
whenCase(3)
|
||||
whenCase(4)
|
||||
whenCase(6)
|
||||
whenCase(8)
|
||||
|
||||
|
||||
block setconstr:
|
||||
const
|
||||
SymChars: set[char] = {'a'..'z', 'A'..'Z', '\x80'..'\xFF'}
|
||||
|
||||
proc classify(s: string) =
|
||||
case s[0]
|
||||
of SymChars, '_': echo "an identifier"
|
||||
of {'0'..'9'}: echo "a number"
|
||||
else: echo "other"
|
||||
|
||||
classify("Hurra")
|
||||
|
||||
|
||||
|
||||
block tduplicates:
|
||||
type Kind = enum A, B
|
||||
var k = A
|
||||
|
||||
template reject(b) =
|
||||
static: doAssert(not compiles(b))
|
||||
|
||||
reject:
|
||||
var i = 2
|
||||
case i
|
||||
of [1, 1]: discard
|
||||
else: discard
|
||||
|
||||
reject:
|
||||
var i = 2
|
||||
case i
|
||||
of 1, { 1..2 }: discard
|
||||
else: discard
|
||||
|
||||
reject:
|
||||
var i = 2
|
||||
case i
|
||||
of { 1, 1 }: discard
|
||||
of { 1, 1 }: discard
|
||||
else: discard
|
||||
|
||||
reject:
|
||||
case k
|
||||
of [A, A]: discard
|
||||
|
||||
var i = 2
|
||||
case i
|
||||
of { 1, 1 }: discard
|
||||
of { 2, 2 }: echo "OK"
|
||||
else: discard
|
||||
|
||||
case i
|
||||
of { 10..30, 15..25, 5..15, 25..35 }: discard
|
||||
else: echo "OK"
|
||||
|
||||
case k
|
||||
of {A, A..A}: echo "OK"
|
||||
of B: discard
|
||||
|
||||
|
||||
block tcasestm:
|
||||
type
|
||||
Tenum = enum eA, eB, eC
|
||||
|
||||
var
|
||||
x: string = "yyy"
|
||||
y: Tenum = eA
|
||||
i: int
|
||||
|
||||
case y
|
||||
of eA: write(stdout, "a")
|
||||
of eB, eC: write(stdout, "b or c")
|
||||
|
||||
case x
|
||||
of "Andreas", "Rumpf": write(stdout, "Hallo Meister!")
|
||||
of "aa", "bb": write(stdout, "Du bist nicht mein Meister")
|
||||
of "cc", "hash", "when": discard
|
||||
of "will", "it", "finally", "be", "generated": discard
|
||||
|
||||
var z = case i
|
||||
of 1..5, 8, 9: "aa"
|
||||
of 6, 7: "bb"
|
||||
elif x == "Ha":
|
||||
"cc"
|
||||
elif x == "yyy":
|
||||
write(stdout, x)
|
||||
"dd"
|
||||
else:
|
||||
"zz"
|
||||
|
||||
echo z
|
||||
#OUT ayyy
|
||||
|
||||
let str1 = "Y"
|
||||
let str2 = "NN"
|
||||
let a = case str1:
|
||||
of "Y": true
|
||||
of "N": false
|
||||
else:
|
||||
echo "no good"
|
||||
quit("quiting")
|
||||
|
||||
proc toBool(s: string): bool =
|
||||
case s:
|
||||
of "": raise newException(ValueError, "Invalid boolean")
|
||||
elif s[0] == 'Y': true
|
||||
elif s[0] == 'N': false
|
||||
else: "error".quit(2)
|
||||
|
||||
|
||||
let b = "NN".toBool()
|
||||
|
||||
doAssert(a == true)
|
||||
doAssert(b == false)
|
||||
|
||||
static:
|
||||
#bug #7407
|
||||
let bstatic = "N".toBool()
|
||||
doAssert(bstatic == false)
|
||||
|
||||
var bb: bool
|
||||
doassert(not compiles(
|
||||
bb = case str2:
|
||||
of "": raise newException(ValueError, "Invalid boolean")
|
||||
elif str.startsWith("Y"): true
|
||||
elif str.startsWith("N"): false
|
||||
))
|
||||
|
||||
doassert(not compiles(
|
||||
bb = case str2:
|
||||
of "Y": true
|
||||
of "N": false
|
||||
))
|
||||
|
||||
doassert(not compiles(
|
||||
bb = case str2:
|
||||
of "Y": true
|
||||
of "N": raise newException(ValueError, "N not allowed")
|
||||
))
|
||||
|
||||
doassert(not compiles(
|
||||
bb = case str2:
|
||||
of "Y": raise newException(ValueError, "Invalid Y")
|
||||
else: raise newException(ValueError, "Invalid N")
|
||||
))
|
||||
|
||||
|
||||
doassert(not compiles(
|
||||
bb = case str2:
|
||||
of "Y":
|
||||
raise newException(ValueError, "Invalid Y")
|
||||
true
|
||||
else: raise newException(ValueError, "Invalid")
|
||||
))
|
||||
|
||||
|
||||
doassert(not compiles(
|
||||
bb = case str2:
|
||||
of "Y":
|
||||
"invalid Y".quit(3)
|
||||
true
|
||||
else: raise newException(ValueError, "Invalid")
|
||||
))
|
||||
@@ -1,5 +1,6 @@
|
||||
discard """
|
||||
output: '''yeah A enumB
|
||||
output: '''
|
||||
yeah A enumB
|
||||
yeah A enumB
|
||||
yeah CD enumD
|
||||
yeah CD enumE
|
||||
@@ -10,7 +11,8 @@ yeah A enumB
|
||||
yeah B enumC
|
||||
yeah A enumB
|
||||
yeah A enumB
|
||||
yeah A enumB'''
|
||||
yeah A enumB
|
||||
'''
|
||||
"""
|
||||
|
||||
type
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
discard """
|
||||
output: '''
|
||||
OK
|
||||
OK
|
||||
OK
|
||||
'''
|
||||
"""
|
||||
|
||||
type Kind = enum A, B
|
||||
var k = A
|
||||
|
||||
template reject(b) =
|
||||
static: doAssert(not compiles(b))
|
||||
|
||||
reject:
|
||||
var i = 2
|
||||
case i
|
||||
of [1, 1]: discard
|
||||
else: discard
|
||||
|
||||
reject:
|
||||
var i = 2
|
||||
case i
|
||||
of 1, { 1..2 }: discard
|
||||
else: discard
|
||||
|
||||
reject:
|
||||
var i = 2
|
||||
case i
|
||||
of { 1, 1 }: discard
|
||||
of { 1, 1 }: discard
|
||||
else: discard
|
||||
|
||||
reject:
|
||||
case k
|
||||
of [A, A]: discard
|
||||
|
||||
var i = 2
|
||||
case i
|
||||
of { 1, 1 }: discard
|
||||
of { 2, 2 }: echo "OK"
|
||||
else: discard
|
||||
|
||||
case i
|
||||
of { 10..30, 15..25, 5..15, 25..35 }: discard
|
||||
else: echo "OK"
|
||||
|
||||
case k
|
||||
of {A, A..A}: echo "OK"
|
||||
of B: discard
|
||||
@@ -1,64 +1,706 @@
|
||||
discard """
|
||||
file: "tclosure.nim"
|
||||
output: '''1 3 6 11 20 foo'''
|
||||
output: '''
|
||||
1 3 6 11 20 foo
|
||||
foo88
|
||||
23 24foo 88
|
||||
18
|
||||
18
|
||||
99
|
||||
99
|
||||
99
|
||||
99 99
|
||||
99 99
|
||||
12 99 99
|
||||
12 99 99
|
||||
success
|
||||
@[1, 2, 5]
|
||||
click at 10,20
|
||||
lost focus 1
|
||||
lost focus 2
|
||||
registered handler for UserEvent 1
|
||||
registered handler for UserEvent 2
|
||||
registered handler for UserEvent 3
|
||||
registered handler for UserEvent 4
|
||||
asdas
|
||||
processClient end
|
||||
false
|
||||
baro0
|
||||
foo88
|
||||
23 24foo 88
|
||||
foo88
|
||||
23 24foo 88
|
||||
11
|
||||
@[1, 10, 45, 120, 210, 252, 210, 120, 45, 10, 1]
|
||||
'''
|
||||
"""
|
||||
# Test the closure implementation
|
||||
|
||||
proc map(n: var openarray[int], fn: proc (x: int): int {.closure}) =
|
||||
for i in 0..n.len-1: n[i] = fn(n[i])
|
||||
|
||||
proc foldr(n: openarray[int], fn: proc (x, y: int): int {.closure}): int =
|
||||
for i in 0..n.len-1:
|
||||
result = fn(result, n[i])
|
||||
|
||||
proc each(n: openarray[int], fn: proc(x: int) {.closure.}) =
|
||||
for i in 0..n.len-1:
|
||||
fn(n[i])
|
||||
|
||||
var
|
||||
myData: array[0..4, int] = [0, 1, 2, 3, 4]
|
||||
|
||||
proc testA() =
|
||||
var p = 0
|
||||
map(myData, proc (x: int): int =
|
||||
result = x + 1 shl (proc (y: int): int =
|
||||
return y + p
|
||||
)(0)
|
||||
inc(p))
|
||||
|
||||
testA()
|
||||
|
||||
myData.each do (x: int):
|
||||
write(stdout, x)
|
||||
write(stdout, " ")
|
||||
|
||||
#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
|
||||
block tclosure:
|
||||
proc map(n: var openarray[int], fn: proc (x: int): int {.closure}) =
|
||||
for i in 0..n.len-1: n[i] = fn(n[i])
|
||||
|
||||
type Mutator* = proc(matched: string): string {.noSideEffect, gcsafe, locks: 0.}
|
||||
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 putMutated*(
|
||||
MutatorCount: static[int],
|
||||
mTable: static[array[MutatorCount, Mutator]], input: string) =
|
||||
for i in 0..<MutatorCount: echo mTable[i](input)
|
||||
proc each(n: openarray[int], fn: proc(x: int) {.closure.}) =
|
||||
for i in 0..n.len-1:
|
||||
fn(n[i])
|
||||
|
||||
proc mutator0(matched: string): string =
|
||||
"foo"
|
||||
var myData: array[0..4, int] = [0, 1, 2, 3, 4]
|
||||
|
||||
const
|
||||
mTable = [Mutator(mutator0)]
|
||||
proc testA() =
|
||||
var p = 0
|
||||
map(myData, proc (x: int): int =
|
||||
result = x + 1 shl (proc (y: int): int =
|
||||
return y + p
|
||||
)(0)
|
||||
inc(p))
|
||||
|
||||
putMutated(1, mTable, "foo")
|
||||
testA()
|
||||
|
||||
myData.each do (x: int):
|
||||
write(stdout, x)
|
||||
write(stdout, " ")
|
||||
|
||||
#OUT 2 4 6 8 10
|
||||
|
||||
type
|
||||
ITest = tuple[
|
||||
setter: proc(v: int),
|
||||
getter: proc(): int]
|
||||
|
||||
proc getInterf(): ITest =
|
||||
var shared: int
|
||||
|
||||
return (setter: proc (x: int) = shared = x,
|
||||
getter: proc (): int = return shared)
|
||||
|
||||
|
||||
# bug #5015
|
||||
|
||||
type Mutator = proc(matched: string): string {.noSideEffect, gcsafe, locks: 0.}
|
||||
|
||||
proc putMutated(
|
||||
MutatorCount: static[int],
|
||||
mTable: static[array[MutatorCount, Mutator]], input: string) =
|
||||
for i in 0..<MutatorCount: echo mTable[i](input)
|
||||
|
||||
proc mutator0(matched: string): string =
|
||||
"foo"
|
||||
|
||||
const
|
||||
mTable = [Mutator(mutator0)]
|
||||
|
||||
putMutated(1, mTable, "foo")
|
||||
|
||||
|
||||
|
||||
block tclosure0:
|
||||
when true:
|
||||
# test simple closure within dummy 'main':
|
||||
proc dummy =
|
||||
proc main2(param: int) =
|
||||
var fooB = 23
|
||||
proc outer(outerParam: string) =
|
||||
var outerVar = 88
|
||||
echo outerParam, outerVar
|
||||
proc inner() =
|
||||
block Test:
|
||||
echo fooB, " ", param, outerParam, " ", outerVar
|
||||
inner()
|
||||
outer("foo")
|
||||
main2(24)
|
||||
|
||||
dummy()
|
||||
|
||||
when true:
|
||||
proc outer2(x:int) : proc(y:int):int = # curry-ed application
|
||||
return proc(y:int):int = x*y
|
||||
|
||||
var fn = outer2(6) # the closure
|
||||
echo fn(3) # it works
|
||||
|
||||
var rawP = fn.rawProc()
|
||||
var rawE = fn.rawEnv()
|
||||
|
||||
# A type to cast the function pointer into a nimcall
|
||||
type TimesClosure = proc(a: int, x: pointer): int {.nimcall.}
|
||||
|
||||
# Call the function with its closure
|
||||
echo cast[TimesClosure](rawP)(3, rawE)
|
||||
|
||||
when true:
|
||||
proc outer =
|
||||
var x, y: int = 99
|
||||
proc innerA = echo x
|
||||
proc innerB =
|
||||
echo y
|
||||
innerA()
|
||||
|
||||
innerA()
|
||||
innerB()
|
||||
|
||||
outer()
|
||||
|
||||
when true:
|
||||
proc indirectDep =
|
||||
var x, y: int = 99
|
||||
proc innerA = echo x, " ", y
|
||||
proc innerB =
|
||||
innerA()
|
||||
|
||||
innerA()
|
||||
innerB()
|
||||
|
||||
indirectDep()
|
||||
|
||||
when true:
|
||||
proc needlessIndirection =
|
||||
var x, y: int = 99
|
||||
proc indirection =
|
||||
var z = 12
|
||||
proc innerA = echo z, " ", x, " ", y
|
||||
proc innerB =
|
||||
innerA()
|
||||
|
||||
innerA()
|
||||
innerB()
|
||||
indirection()
|
||||
|
||||
needlessIndirection()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
block tclosure3:
|
||||
proc main =
|
||||
const n = 30
|
||||
for iterations in 0..50_000:
|
||||
var s: seq[proc(): string {.closure.}] = @[]
|
||||
for i in 0 .. n-1:
|
||||
(proc () =
|
||||
let ii = i
|
||||
s.add(proc(): string = return $(ii*ii)))()
|
||||
for i in 0 .. n-1:
|
||||
let val = s[i]()
|
||||
if val != $(i*i): echo "bug ", val
|
||||
|
||||
if getOccupiedMem() > 5000_000: quit("still a leak!")
|
||||
echo "success"
|
||||
|
||||
main()
|
||||
|
||||
|
||||
|
||||
import json, tables, sequtils
|
||||
block tclosure4:
|
||||
proc run(json_params: OrderedTable) =
|
||||
let json_elems = json_params["files"].elems
|
||||
# These fail compilation.
|
||||
var files = map(json_elems, proc (x: JsonNode): string = x.str)
|
||||
#var files = json_elems.map do (x: JsonNode) -> string: x.str
|
||||
|
||||
let text = """{"files": ["a", "b", "c"]}"""
|
||||
run((text.parseJson).fields)
|
||||
|
||||
|
||||
|
||||
import hashes, math
|
||||
block tclosurebug2:
|
||||
type
|
||||
TSlotEnum = enum seEmpty, seFilled, seDeleted
|
||||
TKeyValuePair[A, B] = tuple[slot: TSlotEnum, key: A, val: B]
|
||||
TKeyValuePairSeq[A, B] = seq[TKeyValuePair[A, B]]
|
||||
|
||||
TOrderedKeyValuePair[A, B] = tuple[
|
||||
slot: TSlotEnum, next: int, key: A, val: B]
|
||||
TOrderedKeyValuePairSeq[A, B] = seq[TOrderedKeyValuePair[A, B]]
|
||||
OrderedTable[A, B] = object ## table that remembers insertion order
|
||||
data: TOrderedKeyValuePairSeq[A, B]
|
||||
counter, first, last: int
|
||||
|
||||
const
|
||||
growthFactor = 2
|
||||
|
||||
proc mustRehash(length, counter: int): bool {.inline.} =
|
||||
assert(length > counter)
|
||||
result = (length * 2 < counter * 3) or (length - counter < 4)
|
||||
|
||||
proc nextTry(h, maxHash: Hash): Hash {.inline.} =
|
||||
result = ((5 * h) + 1) and maxHash
|
||||
|
||||
template rawGetImpl() {.dirty.} =
|
||||
var h: Hash = hash(key) and high(t.data) # start with real hash value
|
||||
while t.data[h].slot != seEmpty:
|
||||
if t.data[h].key == key and t.data[h].slot == seFilled:
|
||||
return h
|
||||
h = nextTry(h, high(t.data))
|
||||
result = -1
|
||||
|
||||
template rawInsertImpl() {.dirty.} =
|
||||
var h: Hash = hash(key) and high(data)
|
||||
while data[h].slot == seFilled:
|
||||
h = nextTry(h, high(data))
|
||||
data[h].key = key
|
||||
data[h].val = val
|
||||
data[h].slot = seFilled
|
||||
|
||||
template addImpl() {.dirty.} =
|
||||
if mustRehash(len(t.data), t.counter): enlarge(t)
|
||||
rawInsert(t, t.data, key, val)
|
||||
inc(t.counter)
|
||||
|
||||
template putImpl() {.dirty.} =
|
||||
var index = rawGet(t, key)
|
||||
if index >= 0:
|
||||
t.data[index].val = val
|
||||
else:
|
||||
addImpl()
|
||||
|
||||
proc len[A, B](t: OrderedTable[A, B]): int {.inline.} =
|
||||
## returns the number of keys in `t`.
|
||||
result = t.counter
|
||||
|
||||
template forAllOrderedPairs(yieldStmt: untyped) {.dirty.} =
|
||||
var h = t.first
|
||||
while h >= 0:
|
||||
var nxt = t.data[h].next
|
||||
if t.data[h].slot == seFilled: yieldStmt
|
||||
h = nxt
|
||||
|
||||
iterator pairs[A, B](t: OrderedTable[A, B]): tuple[key: A, val: B] =
|
||||
## iterates over any (key, value) pair in the table `t` in insertion
|
||||
## order.
|
||||
forAllOrderedPairs:
|
||||
yield (t.data[h].key, t.data[h].val)
|
||||
|
||||
iterator mpairs[A, B](t: var OrderedTable[A, B]): tuple[key: A, val: var B] =
|
||||
## iterates over any (key, value) pair in the table `t` in insertion
|
||||
## order. The values can be modified.
|
||||
forAllOrderedPairs:
|
||||
yield (t.data[h].key, t.data[h].val)
|
||||
|
||||
iterator keys[A, B](t: OrderedTable[A, B]): A =
|
||||
## iterates over any key in the table `t` in insertion order.
|
||||
forAllOrderedPairs:
|
||||
yield t.data[h].key
|
||||
|
||||
iterator values[A, B](t: OrderedTable[A, B]): B =
|
||||
## iterates over any value in the table `t` in insertion order.
|
||||
forAllOrderedPairs:
|
||||
yield t.data[h].val
|
||||
|
||||
iterator mvalues[A, B](t: var OrderedTable[A, B]): var B =
|
||||
## iterates over any value in the table `t` in insertion order. The values
|
||||
## can be modified.
|
||||
forAllOrderedPairs:
|
||||
yield t.data[h].val
|
||||
|
||||
proc rawGet[A, B](t: OrderedTable[A, B], key: A): int =
|
||||
rawGetImpl()
|
||||
|
||||
proc `[]`[A, B](t: OrderedTable[A, B], key: A): B =
|
||||
## retrieves the value at ``t[key]``. If `key` is not in `t`,
|
||||
## default empty value for the type `B` is returned
|
||||
## and no exception is raised. One can check with ``hasKey`` whether the key
|
||||
## exists.
|
||||
var index = rawGet(t, key)
|
||||
if index >= 0: result = t.data[index].val
|
||||
|
||||
proc mget[A, B](t: var OrderedTable[A, B], key: A): var B =
|
||||
## retrieves the value at ``t[key]``. The value can be modified.
|
||||
## If `key` is not in `t`, the ``EInvalidKey`` exception is raised.
|
||||
var index = rawGet(t, key)
|
||||
if index >= 0: result = t.data[index].val
|
||||
else: raise newException(KeyError, "key not found: " & $key)
|
||||
|
||||
proc hasKey[A, B](t: OrderedTable[A, B], key: A): bool =
|
||||
## returns true iff `key` is in the table `t`.
|
||||
result = rawGet(t, key) >= 0
|
||||
|
||||
proc rawInsert[A, B](t: var OrderedTable[A, B],
|
||||
data: var TOrderedKeyValuePairSeq[A, B],
|
||||
key: A, val: B) =
|
||||
rawInsertImpl()
|
||||
data[h].next = -1
|
||||
if t.first < 0: t.first = h
|
||||
if t.last >= 0: data[t.last].next = h
|
||||
t.last = h
|
||||
|
||||
proc enlarge[A, B](t: var OrderedTable[A, B]) =
|
||||
var n: TOrderedKeyValuePairSeq[A, B]
|
||||
newSeq(n, len(t.data) * growthFactor)
|
||||
var h = t.first
|
||||
t.first = -1
|
||||
t.last = -1
|
||||
while h >= 0:
|
||||
var nxt = t.data[h].next
|
||||
if t.data[h].slot == seFilled:
|
||||
rawInsert(t, n, t.data[h].key, t.data[h].val)
|
||||
h = nxt
|
||||
swap(t.data, n)
|
||||
|
||||
proc `[]=`[A, B](t: var OrderedTable[A, B], key: A, val: B) =
|
||||
## puts a (key, value)-pair into `t`.
|
||||
putImpl()
|
||||
|
||||
proc add[A, B](t: var OrderedTable[A, B], key: A, val: B) =
|
||||
## puts a new (key, value)-pair into `t` even if ``t[key]`` already exists.
|
||||
addImpl()
|
||||
|
||||
proc iniOrderedTable[A, B](initialSize=64): OrderedTable[A, B] =
|
||||
## creates a new ordered hash table that is empty. `initialSize` needs to be
|
||||
## a power of two.
|
||||
assert isPowerOfTwo(initialSize)
|
||||
result.counter = 0
|
||||
result.first = -1
|
||||
result.last = -1
|
||||
newSeq(result.data, initialSize)
|
||||
|
||||
proc toOrderedTable[A, B](pairs: openarray[tuple[key: A,
|
||||
val: B]]): OrderedTable[A, B] =
|
||||
## creates a new ordered hash table that contains the given `pairs`.
|
||||
result = iniOrderedTable[A, B](nextPowerOfTwo(pairs.len+10))
|
||||
for key, val in items(pairs): result[key] = val
|
||||
|
||||
proc sort[A, B](t: var OrderedTable[A,B],
|
||||
cmp: proc (x, y: tuple[key: A, val: B]): int {.closure.}) =
|
||||
## sorts the ordered table so that the entry with the highest counter comes
|
||||
## first. This is destructive (with the advantage of being efficient)!
|
||||
## You must not modify `t` afterwards!
|
||||
## You can use the iterators `pairs`, `keys`, and `values` to iterate over
|
||||
## `t` in the sorted order.
|
||||
|
||||
# we use shellsort here; fast enough and simple
|
||||
var h = 1
|
||||
while true:
|
||||
h = 3 * h + 1
|
||||
if h >= high(t.data): break
|
||||
while true:
|
||||
h = h div 3
|
||||
for i in countup(h, high(t.data)):
|
||||
var j = i
|
||||
#echo(t.data.len, " ", j, " - ", h)
|
||||
#echo(repr(t.data[j-h]))
|
||||
proc rawCmp(x, y: TOrderedKeyValuePair[A, B]): int =
|
||||
if x.slot in {seEmpty, seDeleted} and y.slot in {seEmpty, seDeleted}:
|
||||
return 0
|
||||
elif x.slot in {seEmpty, seDeleted}:
|
||||
return -1
|
||||
elif y.slot in {seEmpty, seDeleted}:
|
||||
return 1
|
||||
else:
|
||||
let item1 = (x.key, x.val)
|
||||
let item2 = (y.key, y.val)
|
||||
return cmp(item1, item2)
|
||||
|
||||
while rawCmp(t.data[j-h], t.data[j]) <= 0:
|
||||
swap(t.data[j], t.data[j-h])
|
||||
j = j-h
|
||||
if j < h: break
|
||||
if h == 1: break
|
||||
|
||||
|
||||
|
||||
import sugar
|
||||
block inference3304:
|
||||
type
|
||||
List[T] = ref object
|
||||
val: T
|
||||
|
||||
proc foo[T](l: List[T]): seq[int] =
|
||||
@[1,2,3,5].filter(x => x != l.val)
|
||||
|
||||
echo(foo(List[int](val: 3)))
|
||||
|
||||
|
||||
|
||||
block tcodegenerr1923:
|
||||
type
|
||||
Foo[M] = proc() : M
|
||||
|
||||
proc bar[M](f : Foo[M]) =
|
||||
discard f()
|
||||
|
||||
proc baz() : int = 42
|
||||
|
||||
bar(baz)
|
||||
|
||||
|
||||
|
||||
block doNotation:
|
||||
type
|
||||
Button = object
|
||||
Event = object
|
||||
x, y: int
|
||||
|
||||
proc onClick(x: Button, handler: proc(x: Event)) =
|
||||
handler(Event(x: 10, y: 20))
|
||||
|
||||
proc onFocusLost(x: Button, handler: proc()) =
|
||||
handler()
|
||||
|
||||
proc onUserEvent(x: Button, eventName: string, handler: proc) =
|
||||
echo "registered handler for ", eventName
|
||||
|
||||
var b = Button()
|
||||
|
||||
b.onClick do (e: Event):
|
||||
echo "click at ", e.x, ",", e.y
|
||||
|
||||
b.onFocusLost:
|
||||
echo "lost focus 1"
|
||||
|
||||
b.onFocusLost do:
|
||||
echo "lost focus 2"
|
||||
|
||||
b.onUserEvent("UserEvent 1") do:
|
||||
discard
|
||||
|
||||
b.onUserEvent "UserEvent 2":
|
||||
discard
|
||||
|
||||
b.onUserEvent("UserEvent 3"):
|
||||
discard
|
||||
|
||||
b.onUserEvent("UserEvent 4", () => echo "event 4")
|
||||
|
||||
|
||||
|
||||
import tables
|
||||
block fib50:
|
||||
proc memoize(f: proc (a: int64): int64): proc (a: int64): int64 =
|
||||
var previous = initTable[int64, int64]()
|
||||
return proc(i: int64): int64 =
|
||||
if not previous.hasKey i:
|
||||
previous[i] = f(i)
|
||||
return previous[i]
|
||||
|
||||
var fib: proc(a: int64): int64
|
||||
|
||||
fib = memoize(proc (i: int64): int64 =
|
||||
if i == 0 or i == 1:
|
||||
return 1
|
||||
return fib(i-1) + fib(i-2)
|
||||
)
|
||||
|
||||
doAssert fib(50) == 20365011074
|
||||
|
||||
|
||||
|
||||
block tflatmap:
|
||||
# bug #3995
|
||||
type
|
||||
RNG = tuple[]
|
||||
Rand[A] = (RNG) -> (A, RNG)
|
||||
|
||||
proc nextInt(r: RNG): (int, RNG) =
|
||||
(1, ())
|
||||
|
||||
proc flatMap[A,B](f: Rand[A], g: A -> Rand[B]): Rand[B] =
|
||||
(rng: RNG) => (
|
||||
let (a, rng2) = f(rng);
|
||||
let g1 = g(a);
|
||||
g1(rng2)
|
||||
)
|
||||
|
||||
proc map[A,B](s: Rand[A], f: A -> B): Rand[B] =
|
||||
let g: A -> Rand[B] = (a: A) => ((rng: RNG) => (f(a), rng))
|
||||
flatMap(s, g)
|
||||
|
||||
let f = nextInt.map(i => i - i mod 2)
|
||||
|
||||
|
||||
|
||||
block tforum:
|
||||
type
|
||||
PAsyncHttpServer = ref object
|
||||
value: string
|
||||
PFutureBase = ref object
|
||||
callback: proc () {.closure.}
|
||||
value: string
|
||||
failed: bool
|
||||
|
||||
proc accept(server: PAsyncHttpServer): PFutureBase =
|
||||
new(result)
|
||||
result.callback = proc () =
|
||||
discard
|
||||
server.value = "hahaha"
|
||||
|
||||
proc processClient(): PFutureBase =
|
||||
new(result)
|
||||
|
||||
proc serve(server: PAsyncHttpServer): PFutureBase =
|
||||
iterator serveIter(): PFutureBase {.closure.} =
|
||||
echo server.value
|
||||
while true:
|
||||
var acceptAddrFut = server.accept()
|
||||
yield acceptAddrFut
|
||||
var fut = acceptAddrFut.value
|
||||
|
||||
var f = processClient()
|
||||
f.callback =
|
||||
proc () =
|
||||
echo("processClient end")
|
||||
echo(f.failed)
|
||||
yield f
|
||||
var x = serveIter
|
||||
for i in 0 .. 1:
|
||||
result = x()
|
||||
result.callback()
|
||||
|
||||
discard serve(PAsyncHttpServer(value: "asdas"))
|
||||
|
||||
|
||||
|
||||
block futclosure2138:
|
||||
proc any[T](list: varargs[T], pred: (T) -> bool): bool =
|
||||
for item in list:
|
||||
if pred(item):
|
||||
result = true
|
||||
break
|
||||
|
||||
proc contains(s: string, words: varargs[string]): bool =
|
||||
any(words, (word) => s.contains(word))
|
||||
|
||||
|
||||
|
||||
block tinterf:
|
||||
type
|
||||
ITest = tuple[
|
||||
setter: proc(v: int) {.closure.},
|
||||
getter1: proc(): int {.closure.},
|
||||
getter2: proc(): int {.closure.}]
|
||||
|
||||
proc getInterf(): ITest =
|
||||
var shared1, shared2: int
|
||||
|
||||
return (setter: proc (x: int) =
|
||||
shared1 = x
|
||||
shared2 = x + 10,
|
||||
getter1: proc (): int = result = shared1,
|
||||
getter2: proc (): int = return shared2)
|
||||
|
||||
var i = getInterf()
|
||||
i.setter(56)
|
||||
|
||||
doAssert i.getter1() == 56
|
||||
doAssert i.getter2() == 66
|
||||
|
||||
|
||||
|
||||
block tjester:
|
||||
type
|
||||
Future[T] = ref object
|
||||
data: T
|
||||
callback: proc () {.closure.}
|
||||
|
||||
proc cbOuter(response: string) {.discardable.} =
|
||||
iterator cbIter(): Future[int] {.closure.} =
|
||||
for i in 0..7:
|
||||
proc foo(): int =
|
||||
iterator fooIter(): Future[int] {.closure.} =
|
||||
echo response, i
|
||||
yield Future[int](data: 17)
|
||||
var iterVar = fooIter
|
||||
iterVar().data
|
||||
yield Future[int](data: foo())
|
||||
|
||||
var iterVar2 = cbIter
|
||||
proc cb2() {.closure.} =
|
||||
try:
|
||||
if not finished(iterVar2):
|
||||
let next = iterVar2()
|
||||
if next != nil:
|
||||
next.callback = cb2
|
||||
except:
|
||||
echo "WTF"
|
||||
cb2()
|
||||
|
||||
cbOuter "baro"
|
||||
|
||||
|
||||
|
||||
block tnamedparamanonproc:
|
||||
type
|
||||
PButton = ref object
|
||||
TButtonClicked = proc(button: PButton) {.nimcall.}
|
||||
|
||||
proc newButton(onClick: TButtonClicked) =
|
||||
discard
|
||||
|
||||
proc main() =
|
||||
newButton(onClick = proc(b: PButton) =
|
||||
var requestomat = 12
|
||||
)
|
||||
|
||||
main()
|
||||
|
||||
|
||||
|
||||
block tnestedclosure:
|
||||
proc main(param: int) =
|
||||
var foo = 23
|
||||
proc outer(outerParam: string) =
|
||||
var outerVar = 88
|
||||
echo outerParam, outerVar
|
||||
proc inner() =
|
||||
block Test:
|
||||
echo foo, " ", param, outerParam, " ", outerVar
|
||||
inner()
|
||||
outer("foo")
|
||||
|
||||
# test simple closure within dummy 'main':
|
||||
proc dummy =
|
||||
proc main2(param: int) =
|
||||
var fooB = 23
|
||||
proc outer(outerParam: string) =
|
||||
var outerVar = 88
|
||||
echo outerParam, outerVar
|
||||
proc inner() =
|
||||
block Test:
|
||||
echo fooB, " ", param, outerParam, " ", outerVar
|
||||
inner()
|
||||
outer("foo")
|
||||
main2(24)
|
||||
|
||||
dummy()
|
||||
|
||||
main(24)
|
||||
|
||||
# Jester + async triggered this bug:
|
||||
proc cbOuter() =
|
||||
var response = "hohoho"
|
||||
block:
|
||||
proc cbIter() =
|
||||
block:
|
||||
proc fooIter() =
|
||||
doAssert response == "hohoho"
|
||||
fooIter()
|
||||
cbIter()
|
||||
cbOuter()
|
||||
|
||||
|
||||
|
||||
block tnestedproc:
|
||||
proc p(x, y: int): int =
|
||||
result = x + y
|
||||
|
||||
echo p((proc (): int =
|
||||
var x = 7
|
||||
return x)(),
|
||||
(proc (): int = return 4)())
|
||||
|
||||
|
||||
|
||||
block tnoclosure:
|
||||
proc pascal(n: int) =
|
||||
var row = @[1]
|
||||
for r in 1..n:
|
||||
row = zip(row & @[0], @[0] & row).mapIt(it[0] + it[1])
|
||||
echo row
|
||||
pascal(10)
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
discard """
|
||||
output: '''foo88
|
||||
23 24foo 88
|
||||
18
|
||||
18
|
||||
99
|
||||
99
|
||||
99
|
||||
99 99
|
||||
99 99
|
||||
12 99 99
|
||||
12 99 99'''
|
||||
"""
|
||||
|
||||
when true:
|
||||
# test simple closure within dummy 'main':
|
||||
proc dummy =
|
||||
proc main2(param: int) =
|
||||
var fooB = 23
|
||||
proc outer(outerParam: string) =
|
||||
var outerVar = 88
|
||||
echo outerParam, outerVar
|
||||
proc inner() =
|
||||
block Test:
|
||||
echo fooB, " ", param, outerParam, " ", outerVar
|
||||
inner()
|
||||
outer("foo")
|
||||
main2(24)
|
||||
|
||||
dummy()
|
||||
|
||||
when true:
|
||||
proc outer2(x:int) : proc(y:int):int = # curry-ed application
|
||||
return proc(y:int):int = x*y
|
||||
|
||||
var fn = outer2(6) # the closure
|
||||
echo fn(3) # it works
|
||||
|
||||
var rawP = fn.rawProc()
|
||||
var rawE = fn.rawEnv()
|
||||
|
||||
# A type to cast the function pointer into a nimcall
|
||||
type
|
||||
TimesClosure = proc(a: int, x: pointer): int {.nimcall.}
|
||||
|
||||
# Call the function with its closure
|
||||
echo cast[TimesClosure](rawP)(3, rawE)
|
||||
|
||||
when true:
|
||||
proc outer =
|
||||
var x, y: int = 99
|
||||
proc innerA = echo x
|
||||
proc innerB =
|
||||
echo y
|
||||
innerA()
|
||||
|
||||
innerA()
|
||||
innerB()
|
||||
|
||||
outer()
|
||||
|
||||
when true:
|
||||
proc indirectDep =
|
||||
var x, y: int = 99
|
||||
proc innerA = echo x, " ", y
|
||||
proc innerB =
|
||||
innerA()
|
||||
|
||||
innerA()
|
||||
innerB()
|
||||
|
||||
indirectDep()
|
||||
|
||||
when true:
|
||||
proc needlessIndirection =
|
||||
var x, y: int = 99
|
||||
proc indirection =
|
||||
var z = 12
|
||||
proc innerA = echo z, " ", x, " ", y
|
||||
proc innerB =
|
||||
innerA()
|
||||
|
||||
innerA()
|
||||
innerB()
|
||||
indirection()
|
||||
|
||||
needlessIndirection()
|
||||
@@ -1,101 +0,0 @@
|
||||
discard """
|
||||
output: '''0
|
||||
11
|
||||
1
|
||||
11
|
||||
2
|
||||
11
|
||||
3
|
||||
11
|
||||
4
|
||||
11
|
||||
5
|
||||
11
|
||||
6
|
||||
11
|
||||
7
|
||||
11
|
||||
8
|
||||
11
|
||||
9
|
||||
11
|
||||
11
|
||||
py
|
||||
py
|
||||
py
|
||||
py
|
||||
px
|
||||
6'''
|
||||
"""
|
||||
|
||||
when true:
|
||||
proc ax =
|
||||
for xxxx in 0..9:
|
||||
var i = 0
|
||||
proc bx =
|
||||
if i > 10:
|
||||
echo xxxx
|
||||
return
|
||||
i += 1
|
||||
#for j in 0 .. 0: echo i
|
||||
bx()
|
||||
|
||||
bx()
|
||||
echo i
|
||||
|
||||
ax()
|
||||
|
||||
when true:
|
||||
proc accumulator(start: int): (proc(): int {.closure.}) =
|
||||
var x = start-1
|
||||
#let dummy = proc =
|
||||
# discard start
|
||||
|
||||
result = proc (): int =
|
||||
#var x = 9
|
||||
for i in 0 .. 0: x = x + 1
|
||||
|
||||
return x
|
||||
|
||||
var a = accumulator(3)
|
||||
let b = accumulator(4)
|
||||
echo a() + b() + a()
|
||||
|
||||
|
||||
proc outer =
|
||||
|
||||
proc py() =
|
||||
# no closure here:
|
||||
for i in 0..3: echo "py"
|
||||
|
||||
py()
|
||||
|
||||
outer()
|
||||
|
||||
|
||||
when true:
|
||||
proc outer2 =
|
||||
var errorValue = 3
|
||||
proc fac[T](n: T): T =
|
||||
if n < 0: result = errorValue
|
||||
elif n <= 1: result = 1
|
||||
else: result = n * fac(n-1)
|
||||
|
||||
proc px() {.closure.} =
|
||||
echo "px"
|
||||
|
||||
proc py() {.closure.} =
|
||||
echo "py"
|
||||
|
||||
let
|
||||
mapping = {
|
||||
"abc": px,
|
||||
"xyz": py
|
||||
}
|
||||
mapping[0][1]()
|
||||
|
||||
echo fac(3)
|
||||
|
||||
|
||||
outer2()
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
discard """
|
||||
file: "tclosure3.nim"
|
||||
output: "success"
|
||||
"""
|
||||
|
||||
proc main =
|
||||
const n = 30
|
||||
for iterations in 0..50_000:
|
||||
var s: seq[proc(): string {.closure.}] = @[]
|
||||
for i in 0 .. n-1:
|
||||
(proc () =
|
||||
let ii = i
|
||||
s.add(proc(): string = return $(ii*ii)))()
|
||||
for i in 0 .. n-1:
|
||||
let val = s[i]()
|
||||
if val != $(i*i): echo "bug ", val
|
||||
|
||||
if getOccupiedMem() > 5000_000: quit("still a leak!")
|
||||
echo "success"
|
||||
|
||||
main()
|
||||
@@ -1,13 +0,0 @@
|
||||
|
||||
import json, tables, sequtils
|
||||
|
||||
proc run(json_params: OrderedTable) =
|
||||
let json_elems = json_params["files"].elems
|
||||
# These fail compilation.
|
||||
var files = map(json_elems, proc (x: JsonNode): string = x.str)
|
||||
#var files = json_elems.map do (x: JsonNode) -> string: x.str
|
||||
echo "Hey!"
|
||||
|
||||
when isMainModule:
|
||||
let text = """{"files": ["a", "b", "c"]}"""
|
||||
run((text.parseJson).fields)
|
||||
@@ -1,194 +0,0 @@
|
||||
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: 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: TOrderedTable[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: 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(KeyError, "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
|
||||
@@ -1,15 +0,0 @@
|
||||
discard """
|
||||
output: '''@[1, 2, 5]'''
|
||||
"""
|
||||
|
||||
import future, sequtils
|
||||
|
||||
type
|
||||
List[T] = ref object
|
||||
val: T
|
||||
|
||||
proc foo[T](l: List[T]): seq[int] =
|
||||
@[1,2,3,5].filter(x => x != l.val)
|
||||
|
||||
when isMainModule:
|
||||
echo(foo(List[int](val: 3)))
|
||||
@@ -1,9 +0,0 @@
|
||||
type
|
||||
Foo[M] = proc() : M
|
||||
|
||||
proc bar[M](f : Foo[M]) =
|
||||
discard f()
|
||||
|
||||
proc baz() : int = 42
|
||||
|
||||
bar(baz)
|
||||
@@ -1,20 +0,0 @@
|
||||
discard """
|
||||
output: '''int: 108'''
|
||||
"""
|
||||
|
||||
# bug #4070
|
||||
|
||||
proc id(f: (proc())): auto =
|
||||
return f
|
||||
|
||||
proc foo(myinteger: int): (iterator(): int) =
|
||||
return iterator(): int {.closure.} =
|
||||
proc bar() =
|
||||
proc kk() =
|
||||
echo "int: ", myinteger
|
||||
|
||||
kk()
|
||||
|
||||
id(bar)()
|
||||
|
||||
discard foo(108)()
|
||||
@@ -1,50 +0,0 @@
|
||||
discard """
|
||||
output: '''
|
||||
click at 10,20
|
||||
lost focus 1
|
||||
lost focus 2
|
||||
registered handler for UserEvent 1
|
||||
registered handler for UserEvent 2
|
||||
registered handler for UserEvent 3
|
||||
registered handler for UserEvent 4
|
||||
'''
|
||||
"""
|
||||
|
||||
import future
|
||||
|
||||
type
|
||||
Button = object
|
||||
Event = object
|
||||
x, y: int
|
||||
|
||||
proc onClick(x: Button, handler: proc(x: Event)) =
|
||||
handler(Event(x: 10, y: 20))
|
||||
|
||||
proc onFocusLost(x: Button, handler: proc()) =
|
||||
handler()
|
||||
|
||||
proc onUserEvent(x: Button, eventName: string, handler: proc) =
|
||||
echo "registered handler for ", eventName
|
||||
|
||||
var b = Button()
|
||||
|
||||
b.onClick do (e: Event):
|
||||
echo "click at ", e.x, ",", e.y
|
||||
|
||||
b.onFocusLost:
|
||||
echo "lost focus 1"
|
||||
|
||||
b.onFocusLost do:
|
||||
echo "lost focus 2"
|
||||
|
||||
b.onUserEvent("UserEvent 1") do:
|
||||
discard
|
||||
|
||||
b.onUserEvent "UserEvent 2":
|
||||
discard
|
||||
|
||||
b.onUserEvent("UserEvent 3"):
|
||||
discard
|
||||
|
||||
b.onUserEvent("UserEvent 4", () => echo "event 4")
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
discard """
|
||||
output: "20365011074"
|
||||
"""
|
||||
|
||||
import tables
|
||||
|
||||
proc memoize(f: proc (a: int64): int64): proc (a: int64): int64 =
|
||||
var previous = initTable[int64, int64]()
|
||||
return proc(i: int64): int64 =
|
||||
if not previous.hasKey i:
|
||||
previous[i] = f(i)
|
||||
return previous[i]
|
||||
|
||||
var fib: proc(a: int64): int64
|
||||
|
||||
fib = memoize(proc (i: int64): int64 =
|
||||
if i == 0 or i == 1:
|
||||
return 1
|
||||
return fib(i-1) + fib(i-2)
|
||||
)
|
||||
|
||||
echo fib(50)
|
||||
@@ -1,24 +0,0 @@
|
||||
|
||||
# bug #3995
|
||||
|
||||
import future
|
||||
|
||||
type
|
||||
RNG* = tuple[]
|
||||
Rand*[A] = (RNG) -> (A, RNG)
|
||||
|
||||
proc nextInt*(r: RNG): (int, RNG) =
|
||||
(1, ())
|
||||
|
||||
proc flatMap[A,B](f: Rand[A], g: A -> Rand[B]): Rand[B] =
|
||||
(rng: RNG) => (
|
||||
let (a, rng2) = f(rng);
|
||||
let g1 = g(a);
|
||||
g1(rng2)
|
||||
)
|
||||
|
||||
proc map[A,B](s: Rand[A], f: A -> B): Rand[B] =
|
||||
let g: A -> Rand[B] = (a: A) => ((rng: RNG) => (f(a), rng))
|
||||
flatMap(s, g)
|
||||
|
||||
let f = nextInt.map(i => i - i mod 2)
|
||||
@@ -1,44 +0,0 @@
|
||||
discard """
|
||||
output: '''asdas
|
||||
processClient end
|
||||
false
|
||||
'''
|
||||
"""
|
||||
|
||||
type
|
||||
PAsyncHttpServer = ref object
|
||||
value: string
|
||||
PFutureBase = ref object
|
||||
callback: proc () {.closure.}
|
||||
value: string
|
||||
failed: bool
|
||||
|
||||
proc accept(server: PAsyncHttpServer): PFutureBase =
|
||||
new(result)
|
||||
result.callback = proc () =
|
||||
discard
|
||||
server.value = "hahaha"
|
||||
|
||||
proc processClient(): PFutureBase =
|
||||
new(result)
|
||||
|
||||
proc serve(server: PAsyncHttpServer): PFutureBase =
|
||||
iterator serveIter(): PFutureBase {.closure.} =
|
||||
echo server.value
|
||||
while true:
|
||||
var acceptAddrFut = server.accept()
|
||||
yield acceptAddrFut
|
||||
var fut = acceptAddrFut.value
|
||||
|
||||
var f = processClient()
|
||||
f.callback =
|
||||
proc () =
|
||||
echo("processClient end")
|
||||
echo(f.failed)
|
||||
yield f
|
||||
var x = serveIter
|
||||
for i in 0 .. 1:
|
||||
result = x()
|
||||
result.callback()
|
||||
|
||||
discard serve(PAsyncHttpServer(value: "asdas"))
|
||||
@@ -1,10 +0,0 @@
|
||||
import future, sequtils
|
||||
|
||||
proc any[T](list: varargs[T], pred: (T) -> bool): bool =
|
||||
for item in list:
|
||||
if pred(item):
|
||||
result = true
|
||||
break
|
||||
|
||||
proc contains(s: string, words: varargs[string]): bool =
|
||||
any(words, (word) => s.contains(word))
|
||||
@@ -1,24 +0,0 @@
|
||||
discard """
|
||||
output: '''56 66'''
|
||||
"""
|
||||
|
||||
type
|
||||
ITest = tuple[
|
||||
setter: proc(v: int) {.closure.},
|
||||
getter1: proc(): int {.closure.},
|
||||
getter2: proc(): int {.closure.}]
|
||||
|
||||
proc getInterf(): ITest =
|
||||
var shared1, shared2: int
|
||||
|
||||
return (setter: proc (x: int) =
|
||||
shared1 = x
|
||||
shared2 = x + 10,
|
||||
getter1: proc (): int = result = shared1,
|
||||
getter2: proc (): int = return shared2)
|
||||
|
||||
var i = getInterf()
|
||||
i.setter(56)
|
||||
|
||||
echo i.getter1(), " ", i.getter2()
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
import sequtils
|
||||
let xs: seq[tuple[key: string, val: seq[string]]] = @[("foo", @["bar"])]
|
||||
|
||||
let maps = xs.map(
|
||||
proc(x: auto): tuple[typ: string, maps: seq[string]] =
|
||||
(x.key, x.val.map(proc(x: string): string = x)))
|
||||
@@ -1,3 +0,0 @@
|
||||
block:
|
||||
var i = 0
|
||||
proc p() = inc(i)
|
||||
@@ -1,16 +0,0 @@
|
||||
type
|
||||
TBinOp*[T] = proc (x,y: T): bool
|
||||
|
||||
THeap*[T] = object
|
||||
cmp*: TBinOp[T]
|
||||
|
||||
proc less*[T](x,y: T): bool =
|
||||
x < y
|
||||
|
||||
proc initHeap*[T](cmp: TBinOp[T]): THeap[T] =
|
||||
result.cmp = cmp
|
||||
|
||||
when isMainModule:
|
||||
var h = initHeap[int](less[int])
|
||||
|
||||
echo h.cmp(2,3)
|
||||
@@ -1,7 +0,0 @@
|
||||
proc foo(x: int) : auto =
|
||||
|
||||
proc helper() : int = x
|
||||
proc bar() : int = helper()
|
||||
proc baz() : int = helper()
|
||||
|
||||
return (bar, baz)
|
||||
@@ -1,4 +0,0 @@
|
||||
for i in 1..1:
|
||||
var reported = false
|
||||
proc report() =
|
||||
reported = true
|
||||
55
tests/closure/tissues.nim
Normal file
55
tests/closure/tissues.nim
Normal file
@@ -0,0 +1,55 @@
|
||||
discard """
|
||||
file: "tissues.nim"
|
||||
output: '''true'''
|
||||
"""
|
||||
|
||||
|
||||
block tissue600:
|
||||
for i in 1..1:
|
||||
var reported = false
|
||||
proc report() =
|
||||
reported = true
|
||||
|
||||
|
||||
|
||||
import sequtils
|
||||
block tissue1502def:
|
||||
let xs: seq[tuple[key: string, val: seq[string]]] = @[("foo", @["bar"])]
|
||||
|
||||
let maps = xs.map(
|
||||
proc(x: auto): tuple[typ: string, maps: seq[string]] =
|
||||
(x.key, x.val.map(proc(x: string): string = x)))
|
||||
|
||||
|
||||
|
||||
block tissue1642:
|
||||
var i = 0
|
||||
proc p() = inc(i)
|
||||
|
||||
|
||||
|
||||
block tissue1846:
|
||||
type
|
||||
TBinOp[T] = proc (x,y: T): bool
|
||||
THeap[T] = object
|
||||
cmp: TBinOp[T]
|
||||
|
||||
proc less[T](x,y: T): bool =
|
||||
x < y
|
||||
|
||||
proc initHeap[T](cmp: TBinOp[T]): THeap[T] =
|
||||
result.cmp = cmp
|
||||
|
||||
var h = initHeap[int](less[int])
|
||||
echo h.cmp(2,3)
|
||||
|
||||
|
||||
|
||||
block tissue1911:
|
||||
proc foo(x: int) : auto =
|
||||
|
||||
proc helper() : int = x
|
||||
proc bar() : int = helper()
|
||||
proc baz() : int = helper()
|
||||
|
||||
return (bar, baz)
|
||||
@@ -1,32 +0,0 @@
|
||||
discard """
|
||||
output: '''baro0'''
|
||||
"""
|
||||
|
||||
type
|
||||
Future[T] = ref object
|
||||
data: T
|
||||
callback: proc () {.closure.}
|
||||
|
||||
proc cbOuter(response: string) {.discardable.} =
|
||||
iterator cbIter(): Future[int] {.closure.} =
|
||||
for i in 0..7:
|
||||
proc foo(): int =
|
||||
iterator fooIter(): Future[int] {.closure.} =
|
||||
echo response, i
|
||||
yield Future[int](data: 17)
|
||||
var iterVar = fooIter
|
||||
iterVar().data
|
||||
yield Future[int](data: foo())
|
||||
|
||||
var iterVar2 = cbIter
|
||||
proc cb2() {.closure.} =
|
||||
try:
|
||||
if not finished(iterVar2):
|
||||
let next = iterVar2()
|
||||
if next != nil:
|
||||
next.callback = cb2
|
||||
except:
|
||||
echo "WTF"
|
||||
cb2()
|
||||
|
||||
cbOuter "baro"
|
||||
@@ -1,14 +0,0 @@
|
||||
|
||||
type
|
||||
PButton = ref object
|
||||
TButtonClicked = proc(button: PButton) {.nimcall.}
|
||||
|
||||
proc newButton*(onClick: TButtonClicked) =
|
||||
discard
|
||||
|
||||
proc main() =
|
||||
newButton(onClick = proc(b: PButton) =
|
||||
var requestomat = 12
|
||||
)
|
||||
|
||||
main()
|
||||
180
tests/closure/tnested.nim
Normal file
180
tests/closure/tnested.nim
Normal file
@@ -0,0 +1,180 @@
|
||||
discard """
|
||||
file: "tnested.nim"
|
||||
output: '''
|
||||
foo88
|
||||
23 24foo 88
|
||||
foo88
|
||||
23 24foo 88
|
||||
11
|
||||
int: 108
|
||||
0
|
||||
11
|
||||
1
|
||||
11
|
||||
2
|
||||
11
|
||||
3
|
||||
11
|
||||
4
|
||||
11
|
||||
5
|
||||
11
|
||||
6
|
||||
11
|
||||
7
|
||||
11
|
||||
8
|
||||
11
|
||||
9
|
||||
11
|
||||
11
|
||||
py
|
||||
py
|
||||
py
|
||||
py
|
||||
px
|
||||
6
|
||||
'''
|
||||
"""
|
||||
|
||||
|
||||
block tnestedclosure:
|
||||
proc main(param: int) =
|
||||
var foo = 23
|
||||
proc outer(outerParam: string) =
|
||||
var outerVar = 88
|
||||
echo outerParam, outerVar
|
||||
proc inner() =
|
||||
block Test:
|
||||
echo foo, " ", param, outerParam, " ", outerVar
|
||||
inner()
|
||||
outer("foo")
|
||||
|
||||
# test simple closure within dummy 'main':
|
||||
proc dummy =
|
||||
proc main2(param: int) =
|
||||
var fooB = 23
|
||||
proc outer(outerParam: string) =
|
||||
var outerVar = 88
|
||||
echo outerParam, outerVar
|
||||
proc inner() =
|
||||
block Test:
|
||||
echo fooB, " ", param, outerParam, " ", outerVar
|
||||
inner()
|
||||
outer("foo")
|
||||
main2(24)
|
||||
|
||||
dummy()
|
||||
|
||||
main(24)
|
||||
|
||||
# Jester + async triggered this bug:
|
||||
proc cbOuter() =
|
||||
var response = "hohoho"
|
||||
block:
|
||||
proc cbIter() =
|
||||
block:
|
||||
proc fooIter() =
|
||||
doAssert response == "hohoho"
|
||||
fooIter()
|
||||
cbIter()
|
||||
cbOuter()
|
||||
|
||||
|
||||
block tnestedproc:
|
||||
proc p(x, y: int): int =
|
||||
result = x + y
|
||||
|
||||
echo p((proc (): int =
|
||||
var x = 7
|
||||
return x)(),
|
||||
(proc (): int = return 4)())
|
||||
|
||||
|
||||
block deeplynested:
|
||||
# bug #4070
|
||||
proc id(f: (proc())): auto =
|
||||
return f
|
||||
|
||||
proc foo(myinteger: int): (iterator(): int) =
|
||||
return iterator(): int {.closure.} =
|
||||
proc bar() =
|
||||
proc kk() =
|
||||
echo "int: ", myinteger
|
||||
kk()
|
||||
id(bar)()
|
||||
|
||||
discard foo(108)()
|
||||
|
||||
|
||||
block tclosure2:
|
||||
when true:
|
||||
proc ax =
|
||||
for xxxx in 0..9:
|
||||
var i = 0
|
||||
proc bx =
|
||||
if i > 10:
|
||||
echo xxxx
|
||||
return
|
||||
i += 1
|
||||
#for j in 0 .. 0: echo i
|
||||
bx()
|
||||
|
||||
bx()
|
||||
echo i
|
||||
|
||||
ax()
|
||||
|
||||
when true:
|
||||
proc accumulator(start: int): (proc(): int {.closure.}) =
|
||||
var x = start-1
|
||||
#let dummy = proc =
|
||||
# discard start
|
||||
|
||||
result = proc (): int =
|
||||
#var x = 9
|
||||
for i in 0 .. 0: x = x + 1
|
||||
|
||||
return x
|
||||
|
||||
var a = accumulator(3)
|
||||
let b = accumulator(4)
|
||||
echo a() + b() + a()
|
||||
|
||||
|
||||
proc outer =
|
||||
|
||||
proc py() =
|
||||
# no closure here:
|
||||
for i in 0..3: echo "py"
|
||||
|
||||
py()
|
||||
|
||||
outer()
|
||||
|
||||
|
||||
when true:
|
||||
proc outer2 =
|
||||
var errorValue = 3
|
||||
proc fac[T](n: T): T =
|
||||
if n < 0: result = errorValue
|
||||
elif n <= 1: result = 1
|
||||
else: result = n * fac(n-1)
|
||||
|
||||
proc px() {.closure.} =
|
||||
echo "px"
|
||||
|
||||
proc py() {.closure.} =
|
||||
echo "py"
|
||||
|
||||
let
|
||||
mapping = {
|
||||
"abc": px,
|
||||
"xyz": py
|
||||
}
|
||||
mapping[0][1]()
|
||||
|
||||
echo fac(3)
|
||||
|
||||
|
||||
outer2()
|
||||
@@ -1,51 +0,0 @@
|
||||
discard """
|
||||
output: '''foo88
|
||||
23 24foo 88
|
||||
foo88
|
||||
23 24foo 88
|
||||
hohoho'''
|
||||
"""
|
||||
|
||||
# test nested closure
|
||||
proc main(param: int) =
|
||||
var foo = 23
|
||||
proc outer(outerParam: string) =
|
||||
var outerVar = 88
|
||||
echo outerParam, outerVar
|
||||
proc inner() =
|
||||
block Test:
|
||||
echo foo, " ", param, outerParam, " ", outerVar
|
||||
inner()
|
||||
outer("foo")
|
||||
|
||||
# test simple closure within dummy 'main':
|
||||
proc dummy =
|
||||
proc main2(param: int) =
|
||||
var fooB = 23
|
||||
proc outer(outerParam: string) =
|
||||
var outerVar = 88
|
||||
echo outerParam, outerVar
|
||||
proc inner() =
|
||||
block Test:
|
||||
echo fooB, " ", param, outerParam, " ", outerVar
|
||||
inner()
|
||||
outer("foo")
|
||||
main2(24)
|
||||
|
||||
dummy()
|
||||
|
||||
main(24)
|
||||
|
||||
# Jester + async triggered this bug:
|
||||
proc cbOuter() =
|
||||
var response = "hohoho"
|
||||
block:
|
||||
proc cbIter() =
|
||||
block:
|
||||
proc fooIter() =
|
||||
echo response
|
||||
fooIter()
|
||||
|
||||
cbIter()
|
||||
|
||||
cbOuter()
|
||||
@@ -1,12 +0,0 @@
|
||||
discard """
|
||||
output: "11"
|
||||
"""
|
||||
|
||||
proc p(x, y: int): int =
|
||||
result = x + y
|
||||
|
||||
echo p((proc (): int =
|
||||
var x = 7
|
||||
return x)(),
|
||||
(proc (): int = return 4)())
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
discard """
|
||||
output: '''@[1]
|
||||
@[1, 1]
|
||||
@[1, 2, 1]
|
||||
@[1, 3, 3, 1]
|
||||
@[1, 4, 6, 4, 1]
|
||||
@[1, 5, 10, 10, 5, 1]
|
||||
@[1, 6, 15, 20, 15, 6, 1]
|
||||
@[1, 7, 21, 35, 35, 21, 7, 1]
|
||||
@[1, 8, 28, 56, 70, 56, 28, 8, 1]
|
||||
@[1, 9, 36, 84, 126, 126, 84, 36, 9, 1]'''
|
||||
"""
|
||||
|
||||
import sequtils
|
||||
|
||||
proc pascal(n: int) =
|
||||
var row = @[1]
|
||||
for r in 1..n:
|
||||
echo row
|
||||
row = zip(row & @[0], @[0] & row).mapIt(it[0] + it[1])
|
||||
|
||||
pascal(10)
|
||||
|
||||
# bug #3499 last snippet fixed
|
||||
# bug 705 last snippet fixed
|
||||
@@ -1,17 +1,69 @@
|
||||
discard """
|
||||
file: "tcnstseq.nim"
|
||||
output: "AngelikaAnneAnnaAnkaAnja"
|
||||
output: '''
|
||||
AngelikaAnneAnnaAnkaAnja
|
||||
AngelikaAnneAnnaAnkaAnja
|
||||
AngelikaAnneAnnaAnkaAnja
|
||||
onetwothree
|
||||
onetwothree
|
||||
onetwothree
|
||||
one1two2three3
|
||||
'''
|
||||
"""
|
||||
# Test the new implicit conversion from sequences to arrays in a constant
|
||||
# context.
|
||||
|
||||
import strutils
|
||||
|
||||
const
|
||||
myWords = "Angelika Anne Anna Anka Anja".split()
|
||||
|
||||
for x in items(myWords):
|
||||
write(stdout, x) #OUT AngelikaAnneAnnaAnkaAnja
|
||||
block t1:
|
||||
const
|
||||
myWords = "Angelika Anne Anna Anka Anja".split()
|
||||
|
||||
for x in items(myWords):
|
||||
write(stdout, x) #OUT AngelikaAnneAnnaAnkaAnja
|
||||
echo ""
|
||||
|
||||
|
||||
block t2:
|
||||
const
|
||||
myWords = @["Angelika", "Anne", "Anna", "Anka", "Anja"]
|
||||
|
||||
for i in 0 .. high(myWords):
|
||||
write(stdout, myWords[i]) #OUT AngelikaAnneAnnaAnkaAnja
|
||||
echo ""
|
||||
|
||||
|
||||
block t3:
|
||||
for w in items(["Angelika", "Anne", "Anna", "Anka", "Anja"]):
|
||||
write(stdout, w) #OUT AngelikaAnneAnnaAnkaAnja
|
||||
echo ""
|
||||
|
||||
|
||||
block t2656:
|
||||
iterator it1(args: seq[string]): string =
|
||||
for s in args: yield s
|
||||
iterator it2(args: seq[string]): string {.closure.} =
|
||||
for s in args: yield s
|
||||
iterator it3(args: openArray[string]): string {.closure.} =
|
||||
for s in args: yield s
|
||||
iterator it4(args: openArray[(string, string)]): string {.closure.} =
|
||||
for s1, s2 in items(args): yield s1 & s2
|
||||
|
||||
block:
|
||||
const myConstSeq = @["one", "two", "three"]
|
||||
for s in it1(myConstSeq):
|
||||
stdout.write s
|
||||
echo ""
|
||||
for s in it2(myConstSeq):
|
||||
stdout.write s
|
||||
echo ""
|
||||
for s in it3(myConstSeq):
|
||||
stdout.write s
|
||||
echo ""
|
||||
|
||||
block:
|
||||
const myConstSeq = @[("one", "1"), ("two", "2"), ("three", "3")]
|
||||
for s in it4(myConstSeq):
|
||||
stdout.write s
|
||||
echo ""
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
discard """
|
||||
output: "AngelikaAnneAnnaAnkaAnja"
|
||||
"""
|
||||
|
||||
const
|
||||
myWords = @["Angelika", "Anne", "Anna", "Anka", "Anja"]
|
||||
|
||||
for i in 0 .. high(myWords):
|
||||
write(stdout, myWords[i]) #OUT AngelikaAnneAnnaAnkaAnja
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
discard """
|
||||
output: "AngelikaAnneAnnaAnkaAnja"
|
||||
"""
|
||||
|
||||
for w in items(["Angelika", "Anne", "Anna", "Anka", "Anja"]):
|
||||
write(stdout, w) #OUT AngelikaAnneAnnaAnkaAnja
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
discard """
|
||||
output: '''done'''
|
||||
"""
|
||||
|
||||
import tables
|
||||
|
||||
proc main =
|
||||
var tab = newTable[string, string]()
|
||||
for i in 0..1000:
|
||||
tab.add "key", "value " & $i
|
||||
|
||||
main()
|
||||
echo "done"
|
||||
@@ -1,11 +0,0 @@
|
||||
discard """
|
||||
output: '''true'''
|
||||
"""
|
||||
|
||||
import sequtils
|
||||
|
||||
var x = @[1, 2, 3]
|
||||
x.apply(proc(x: var int) = x = x+10)
|
||||
x.apply(proc(x: int): int = x+100)
|
||||
x.applyIt(it+5000)
|
||||
echo x == @[5111, 5112, 5113]
|
||||
56
tests/collections/tcollections.nim
Normal file
56
tests/collections/tcollections.nim
Normal file
@@ -0,0 +1,56 @@
|
||||
discard """
|
||||
file: "tcollections.nim"
|
||||
output: '''
|
||||
'''
|
||||
"""
|
||||
|
||||
import deques, sequtils
|
||||
|
||||
|
||||
block tapply:
|
||||
var x = @[1, 2, 3]
|
||||
x.apply(proc(x: var int) = x = x+10)
|
||||
x.apply(proc(x: int): int = x+100)
|
||||
x.applyIt(it+5000)
|
||||
doAssert x == @[5111, 5112, 5113]
|
||||
|
||||
|
||||
block tdeques:
|
||||
proc index(self: Deque[int], idx: Natural): int =
|
||||
self[idx]
|
||||
|
||||
proc main =
|
||||
var testDeque = initDeque[int]()
|
||||
testDeque.addFirst(1)
|
||||
assert testDeque.index(0) == 1
|
||||
|
||||
main()
|
||||
|
||||
|
||||
block tmapit:
|
||||
var x = @[1, 2, 3]
|
||||
# This mapIt call will run with preallocation because ``len`` is available.
|
||||
var y = x.mapIt($(it+10))
|
||||
doAssert y == @["11", "12", "13"]
|
||||
|
||||
type structureWithoutLen = object
|
||||
a: array[5, int]
|
||||
|
||||
iterator items(s: structureWithoutLen): int {.inline.} =
|
||||
yield s.a[0]
|
||||
yield s.a[1]
|
||||
yield s.a[2]
|
||||
yield s.a[3]
|
||||
yield s.a[4]
|
||||
|
||||
var st: structureWithoutLen
|
||||
st.a[0] = 0
|
||||
st.a[1] = 1
|
||||
st.a[2] = 2
|
||||
st.a[3] = 3
|
||||
st.a[4] = 4
|
||||
|
||||
# this will run without preallocating the result
|
||||
# since ``len`` is not available
|
||||
var r = st.mapIt($(it+10))
|
||||
doAssert r == @["10", "11", "12", "13", "14"]
|
||||
@@ -1,19 +0,0 @@
|
||||
discard """
|
||||
output: "And we get here"
|
||||
"""
|
||||
|
||||
# bug #2625
|
||||
|
||||
const s_len = 32
|
||||
|
||||
import tables
|
||||
var substr_counts: CountTable[string] = initCountTable[string]()
|
||||
var my_string = "Hello, this is sadly broken for strings over 64 characters. Note that it *does* appear to work for short strings."
|
||||
for i in 0..(my_string.len - s_len):
|
||||
let s = my_string[i..i+s_len-1]
|
||||
substr_counts[s] = 1
|
||||
# substr_counts[s] = substr_counts[s] + 1 # Also breaks, + 2 as well, etc.
|
||||
# substr_counts.inc(s) # This works
|
||||
#echo "Iteration ", i
|
||||
|
||||
echo "And we get here"
|
||||
@@ -1,17 +0,0 @@
|
||||
discard """
|
||||
output: '''true'''
|
||||
"""
|
||||
|
||||
import deques
|
||||
|
||||
|
||||
proc index(self: Deque[int], idx: Natural): int =
|
||||
self[idx]
|
||||
|
||||
proc main =
|
||||
var testDeque = initDeque[int]()
|
||||
testDeque.addFirst(1)
|
||||
assert testDeque.index(0) == 1
|
||||
|
||||
main()
|
||||
echo "true"
|
||||
@@ -1,90 +0,0 @@
|
||||
discard """
|
||||
output: '''true'''
|
||||
"""
|
||||
|
||||
import tables
|
||||
from hashes import Hash
|
||||
|
||||
# Test with int
|
||||
block:
|
||||
var t = initTable[int,int]()
|
||||
t[0] = 42
|
||||
t[1] = t[0] + 1
|
||||
assert(t[0] == 42)
|
||||
assert(t[1] == 43)
|
||||
let t2 = {1: 1, 2: 2}.toTable
|
||||
assert(t2[2] == 2)
|
||||
|
||||
# Test with char
|
||||
block:
|
||||
var t = initTable[char,int]()
|
||||
t['0'] = 42
|
||||
t['1'] = t['0'] + 1
|
||||
assert(t['0'] == 42)
|
||||
assert(t['1'] == 43)
|
||||
let t2 = {'1': 1, '2': 2}.toTable
|
||||
assert(t2['2'] == 2)
|
||||
|
||||
# Test with enum
|
||||
block:
|
||||
type
|
||||
E = enum eA, eB, eC
|
||||
var t = initTable[E,int]()
|
||||
t[eA] = 42
|
||||
t[eB] = t[eA] + 1
|
||||
assert(t[eA] == 42)
|
||||
assert(t[eB] == 43)
|
||||
let t2 = {eA: 1, eB: 2}.toTable
|
||||
assert(t2[eB] == 2)
|
||||
|
||||
# Test with range
|
||||
block:
|
||||
type
|
||||
R = range[1..10]
|
||||
var t = initTable[R,int]() # causes warning, why?
|
||||
t[1] = 42 # causes warning, why?
|
||||
t[2] = t[1] + 1
|
||||
assert(t[1] == 42)
|
||||
assert(t[2] == 43)
|
||||
let t2 = {1.R: 1, 2.R: 2}.toTable
|
||||
assert(t2[2.R] == 2)
|
||||
|
||||
# Test which combines the generics for tuples + ordinals
|
||||
block:
|
||||
type
|
||||
E = enum eA, eB, eC
|
||||
var t = initTable[(string, E, int, char), int]()
|
||||
t[("a", eA, 0, '0')] = 42
|
||||
t[("b", eB, 1, '1')] = t[("a", eA, 0, '0')] + 1
|
||||
assert(t[("a", eA, 0, '0')] == 42)
|
||||
assert(t[("b", eB, 1, '1')] == 43)
|
||||
let t2 = {("a", eA, 0, '0'): 1, ("b", eB, 1, '1'): 2}.toTable
|
||||
assert(t2[("b", eB, 1, '1')] == 2)
|
||||
|
||||
# Test to check if overloading is possible
|
||||
# Unfortunately, this does not seem to work for int
|
||||
# The same test with a custom hash(s: string) does
|
||||
# work though.
|
||||
block:
|
||||
proc hash(x: int): Hash {.inline.} =
|
||||
echo "overloaded hash"
|
||||
result = x
|
||||
var t = initTable[int, int]()
|
||||
t[0] = 0
|
||||
|
||||
# Check hashability of all integer types (issue #5429)
|
||||
block:
|
||||
let intTables = (
|
||||
newTable[int, string](),
|
||||
newTable[int8, string](),
|
||||
newTable[int16, string](),
|
||||
newTable[int32, string](),
|
||||
newTable[int64, string](),
|
||||
newTable[uint, string](),
|
||||
newTable[uint8, string](),
|
||||
newTable[uint16, string](),
|
||||
newTable[uint32, string](),
|
||||
newTable[uint64, string](),
|
||||
)
|
||||
|
||||
echo "true"
|
||||
@@ -1,22 +0,0 @@
|
||||
import tables
|
||||
|
||||
doAssert indexBy(newSeq[int](), proc(x: int):int = x) == initTable[int, int](), "empty int table"
|
||||
|
||||
var tbl1 = initTable[int, int]()
|
||||
tbl1.add(1,1)
|
||||
tbl1.add(2,2)
|
||||
doAssert indexBy(@[1,2], proc(x: int):int = x) == tbl1, "int table"
|
||||
|
||||
type
|
||||
TElem = object
|
||||
foo: int
|
||||
bar: string
|
||||
|
||||
let
|
||||
elem1 = TElem(foo: 1, bar: "bar")
|
||||
elem2 = TElem(foo: 2, bar: "baz")
|
||||
|
||||
var tbl2 = initTable[string, TElem]()
|
||||
tbl2.add("bar", elem1)
|
||||
tbl2.add("baz", elem2)
|
||||
doAssert indexBy(@[elem1,elem2], proc(x: TElem): string = x.bar) == tbl2, "element table"
|
||||
@@ -1,33 +0,0 @@
|
||||
discard """
|
||||
output: '''true
|
||||
true'''
|
||||
"""
|
||||
|
||||
import sequtils
|
||||
|
||||
var x = @[1, 2, 3]
|
||||
# This mapIt call will run with preallocation because ``len`` is available.
|
||||
var y = x.mapIt($(it+10))
|
||||
echo y == @["11", "12", "13"]
|
||||
|
||||
type structureWithoutLen = object
|
||||
a: array[5, int]
|
||||
|
||||
iterator items(s: structureWithoutLen): int {.inline.} =
|
||||
yield s.a[0]
|
||||
yield s.a[1]
|
||||
yield s.a[2]
|
||||
yield s.a[3]
|
||||
yield s.a[4]
|
||||
|
||||
var st: structureWithoutLen
|
||||
st.a[0] = 0
|
||||
st.a[1] = 1
|
||||
st.a[2] = 2
|
||||
st.a[3] = 3
|
||||
st.a[4] = 4
|
||||
|
||||
# this will run without preallocating the result
|
||||
# since ``len`` is not available
|
||||
var r = st.mapIt($(it+10))
|
||||
echo r == @["10", "11", "12", "13", "14"]
|
||||
@@ -1,6 +1,5 @@
|
||||
import sets
|
||||
import hashes
|
||||
import algorithm
|
||||
import sets, hashes, algorithm
|
||||
|
||||
|
||||
block setEquality:
|
||||
var
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
# Test if the new table constructor syntax works:
|
||||
|
||||
template ignoreExpr(e) =
|
||||
discard
|
||||
|
||||
# test first class '..' syntactical citizen:
|
||||
ignoreExpr x <> 2..4
|
||||
# test table constructor:
|
||||
ignoreExpr({:})
|
||||
ignoreExpr({2: 3, "key": "value"})
|
||||
|
||||
# NEW:
|
||||
assert 56 in 50..100
|
||||
|
||||
assert 56 in ..60
|
||||
|
||||
@@ -1,275 +1,375 @@
|
||||
discard """
|
||||
cmd: "nim c --threads:on $file"
|
||||
output: '''true'''
|
||||
file: "ttables.nim"
|
||||
output: '''
|
||||
done
|
||||
And we get here
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
'''
|
||||
"""
|
||||
import hashes, sequtils, tables
|
||||
|
||||
import hashes, tables, sharedtables
|
||||
|
||||
const
|
||||
data = {
|
||||
"34": 123456, "12": 789,
|
||||
"90": 343, "0": 34404,
|
||||
"1": 344004, "2": 344774,
|
||||
"3": 342244, "4": 3412344,
|
||||
"5": 341232144, "6": 34214544,
|
||||
"7": 3434544, "8": 344544,
|
||||
"9": 34435644, "---00": 346677844,
|
||||
"10": 34484, "11": 34474, "19": 34464,
|
||||
"20": 34454, "30": 34141244, "40": 344114,
|
||||
"50": 344490, "60": 344491, "70": 344492,
|
||||
"80": 344497}
|
||||
block tableadds:
|
||||
proc main =
|
||||
var tab = newTable[string, string]()
|
||||
for i in 0..1000:
|
||||
tab.add "key", "value " & $i
|
||||
|
||||
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}
|
||||
main()
|
||||
echo "done"
|
||||
|
||||
block tableTest1:
|
||||
var t = initTable[tuple[x, y: int], string]()
|
||||
t[(0,0)] = "00"
|
||||
t[(1,0)] = "10"
|
||||
t[(0,1)] = "01"
|
||||
t[(1,1)] = "11"
|
||||
for x in 0..1:
|
||||
for y in 0..1:
|
||||
assert t[(x,y)] == $x & $y
|
||||
assert($t ==
|
||||
"{(x: 0, y: 1): \"01\", (x: 0, y: 0): \"00\", (x: 1, y: 0): \"10\", (x: 1, y: 1): \"11\"}")
|
||||
|
||||
block tableTest2:
|
||||
var t = initTable[string, float]()
|
||||
t["test"] = 1.2345
|
||||
t["111"] = 1.000043
|
||||
t["123"] = 1.23
|
||||
t.del("111")
|
||||
block tcounttable:
|
||||
# bug #2625
|
||||
const s_len = 32
|
||||
var substr_counts: CountTable[string] = initCountTable[string]()
|
||||
var my_string = "Hello, this is sadly broken for strings over 64 characters. Note that it *does* appear to work for short strings."
|
||||
for i in 0..(my_string.len - s_len):
|
||||
let s = my_string[i..i+s_len-1]
|
||||
substr_counts[s] = 1
|
||||
# substr_counts[s] = substr_counts[s] + 1 # Also breaks, + 2 as well, etc.
|
||||
# substr_counts.inc(s) # This works
|
||||
#echo "Iteration ", i
|
||||
|
||||
t["012"] = 67.9
|
||||
t["123"] = 1.5 # test overwriting
|
||||
echo "And we get here"
|
||||
|
||||
assert t["123"] == 1.5
|
||||
try:
|
||||
echo t["111"] # deleted
|
||||
except KeyError:
|
||||
discard
|
||||
assert(not hasKey(t, "111"))
|
||||
|
||||
assert "123" in t
|
||||
assert("111" notin t)
|
||||
block thashes:
|
||||
# Test with int
|
||||
block:
|
||||
var t = initTable[int,int]()
|
||||
t[0] = 42
|
||||
t[1] = t[0] + 1
|
||||
assert(t[0] == 42)
|
||||
assert(t[1] == 43)
|
||||
let t2 = {1: 1, 2: 2}.toTable
|
||||
assert(t2[2] == 2)
|
||||
|
||||
for key, val in items(data): t[key] = val.toFloat
|
||||
for key, val in items(data): assert t[key] == val.toFloat
|
||||
# Test with char
|
||||
block:
|
||||
var t = initTable[char,int]()
|
||||
t['0'] = 42
|
||||
t['1'] = t['0'] + 1
|
||||
assert(t['0'] == 42)
|
||||
assert(t['1'] == 43)
|
||||
let t2 = {'1': 1, '2': 2}.toTable
|
||||
assert(t2['2'] == 2)
|
||||
|
||||
assert(not t.hasKeyOrPut("456", 4.0)) # test absent key
|
||||
assert t.hasKeyOrPut("012", 3.0) # test present key
|
||||
var x = t.mgetOrPut("111", 1.5) # test absent key
|
||||
x = x * 2
|
||||
assert x == 3.0
|
||||
x = t.mgetOrPut("test", 1.5) # test present key
|
||||
x = x * 2
|
||||
assert x == 2 * 1.2345
|
||||
# Test with enum
|
||||
block:
|
||||
type
|
||||
E = enum eA, eB, eC
|
||||
var t = initTable[E,int]()
|
||||
t[eA] = 42
|
||||
t[eB] = t[eA] + 1
|
||||
assert(t[eA] == 42)
|
||||
assert(t[eB] == 43)
|
||||
let t2 = {eA: 1, eB: 2}.toTable
|
||||
assert(t2[eB] == 2)
|
||||
|
||||
block orderedTableTest1:
|
||||
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
|
||||
var i = 0
|
||||
# `pairs` needs to yield in insertion order:
|
||||
for key, val in pairs(t):
|
||||
assert key == data[i][0]
|
||||
assert val == data[i][1]
|
||||
inc(i)
|
||||
# Test with range
|
||||
block:
|
||||
type
|
||||
R = range[1..10]
|
||||
var t = initTable[R,int]() # causes warning, why?
|
||||
t[1] = 42 # causes warning, why?
|
||||
t[2] = t[1] + 1
|
||||
assert(t[1] == 42)
|
||||
assert(t[2] == 43)
|
||||
let t2 = {1.R: 1, 2.R: 2}.toTable
|
||||
assert(t2[2.R] == 2)
|
||||
|
||||
for key, val in mpairs(t): val = 99
|
||||
for val in mvalues(t): assert val == 99
|
||||
# Test which combines the generics for tuples + ordinals
|
||||
block:
|
||||
type
|
||||
E = enum eA, eB, eC
|
||||
var t = initTable[(string, E, int, char), int]()
|
||||
t[("a", eA, 0, '0')] = 42
|
||||
t[("b", eB, 1, '1')] = t[("a", eA, 0, '0')] + 1
|
||||
assert(t[("a", eA, 0, '0')] == 42)
|
||||
assert(t[("b", eB, 1, '1')] == 43)
|
||||
let t2 = {("a", eA, 0, '0'): 1, ("b", eB, 1, '1'): 2}.toTable
|
||||
assert(t2[("b", eB, 1, '1')] == 2)
|
||||
|
||||
block orderedTableTest2:
|
||||
var
|
||||
s = initOrderedTable[string, int]()
|
||||
t = initOrderedTable[string, int]()
|
||||
assert s == t
|
||||
for key, val in items(data): t[key] = val
|
||||
assert s != t
|
||||
for key, val in items(sorteddata): s[key] = val
|
||||
assert s != t
|
||||
t.clear()
|
||||
assert s != t
|
||||
for key, val in items(sorteddata): t[key] = val
|
||||
assert s == t
|
||||
# Test to check if overloading is possible
|
||||
# Unfortunately, this does not seem to work for int
|
||||
# The same test with a custom hash(s: string) does
|
||||
# work though.
|
||||
block:
|
||||
proc hash(x: int): Hash {.inline.} =
|
||||
echo "overloaded hash"
|
||||
result = x
|
||||
var t = initTable[int, int]()
|
||||
t[0] = 0
|
||||
|
||||
block countTableTest1:
|
||||
var s = data.toTable
|
||||
var t = initCountTable[string]()
|
||||
# Check hashability of all integer types (issue #5429)
|
||||
block:
|
||||
let intTables = (
|
||||
newTable[int, string](),
|
||||
newTable[int8, string](),
|
||||
newTable[int16, string](),
|
||||
newTable[int32, string](),
|
||||
newTable[int64, string](),
|
||||
newTable[uint, string](),
|
||||
newTable[uint8, string](),
|
||||
newTable[uint16, string](),
|
||||
newTable[uint32, string](),
|
||||
newTable[uint64, string](),
|
||||
)
|
||||
|
||||
for k in s.keys: t.inc(k)
|
||||
for k in t.keys: assert t[k] == 1
|
||||
t.inc("90", 3)
|
||||
t.inc("12", 2)
|
||||
t.inc("34", 1)
|
||||
assert t.largest()[0] == "90"
|
||||
echo "true"
|
||||
|
||||
t.sort()
|
||||
var i = 0
|
||||
for k, v in t.pairs:
|
||||
case i
|
||||
of 0: assert k == "90" and v == 4
|
||||
of 1: assert k == "12" and v == 3
|
||||
of 2: assert k == "34" and v == 2
|
||||
else: break
|
||||
inc i
|
||||
|
||||
block countTableTest2:
|
||||
var
|
||||
s = initCountTable[int]()
|
||||
t = initCountTable[int]()
|
||||
assert s == t
|
||||
s.inc(1)
|
||||
assert s != t
|
||||
t.inc(2)
|
||||
assert s != t
|
||||
t.inc(1)
|
||||
assert s != t
|
||||
s.inc(2)
|
||||
assert s == t
|
||||
s.inc(1)
|
||||
assert s != t
|
||||
t.inc(1)
|
||||
assert s == t
|
||||
block tindexby:
|
||||
doAssert indexBy(newSeq[int](), proc(x: int):int = x) == initTable[int, int](), "empty int table"
|
||||
|
||||
block mpairsTableTest1:
|
||||
var t = initTable[string, int]()
|
||||
t["a"] = 1
|
||||
t["b"] = 2
|
||||
t["c"] = 3
|
||||
t["d"] = 4
|
||||
for k, v in t.mpairs:
|
||||
if k == "a" or k == "c":
|
||||
v = 9
|
||||
var tbl1 = initTable[int, int]()
|
||||
tbl1.add(1,1)
|
||||
tbl1.add(2,2)
|
||||
doAssert indexBy(@[1,2], proc(x: int):int = x) == tbl1, "int table"
|
||||
|
||||
for k, v in t.pairs:
|
||||
if k == "a" or k == "c":
|
||||
assert v == 9
|
||||
else:
|
||||
assert v != 1 and v != 3
|
||||
type
|
||||
TElem = object
|
||||
foo: int
|
||||
bar: string
|
||||
|
||||
block SyntaxTest:
|
||||
var x = toTable[int, string]({:})
|
||||
let
|
||||
elem1 = TElem(foo: 1, bar: "bar")
|
||||
elem2 = TElem(foo: 2, bar: "baz")
|
||||
|
||||
block zeroHashKeysTest:
|
||||
proc doZeroHashValueTest[T, K, V](t: T, nullHashKey: K, value: V) =
|
||||
let initialLen = t.len
|
||||
var testTable = t
|
||||
testTable[nullHashKey] = value
|
||||
assert testTable[nullHashKey] == value
|
||||
assert testTable.len == initialLen + 1
|
||||
testTable.del(nullHashKey)
|
||||
assert testTable.len == initialLen
|
||||
var tbl2 = initTable[string, TElem]()
|
||||
tbl2.add("bar", elem1)
|
||||
tbl2.add("baz", elem2)
|
||||
doAssert indexBy(@[elem1,elem2], proc(x: TElem): string = x.bar) == tbl2, "element table"
|
||||
|
||||
|
||||
# with empty table
|
||||
doZeroHashValueTest(toTable[int,int]({:}), 0, 42)
|
||||
doZeroHashValueTest(toTable[string,int]({:}), "", 23)
|
||||
doZeroHashValueTest(toOrderedTable[int,int]({:}), 0, 42)
|
||||
doZeroHashValueTest(toOrderedTable[string,int]({:}), "", 23)
|
||||
block tableconstr:
|
||||
# Test if the new table constructor syntax works:
|
||||
|
||||
# with non-empty table
|
||||
doZeroHashValueTest(toTable[int,int]({1:2}), 0, 42)
|
||||
doZeroHashValueTest(toTable[string,string]({"foo": "bar"}), "", "zero")
|
||||
doZeroHashValueTest(toOrderedTable[int,int]({3:4}), 0, 42)
|
||||
doZeroHashValueTest(toOrderedTable[string,string]({"egg": "sausage"}),
|
||||
"", "spam")
|
||||
|
||||
block clearTableTest:
|
||||
var t = data.toTable
|
||||
assert t.len() != 0
|
||||
t.clear()
|
||||
assert t.len() == 0
|
||||
|
||||
block clearOrderedTableTest:
|
||||
var t = data.toOrderedTable
|
||||
assert t.len() != 0
|
||||
t.clear()
|
||||
assert t.len() == 0
|
||||
|
||||
block clearCountTableTest:
|
||||
var t = initCountTable[string]()
|
||||
t.inc("90", 3)
|
||||
t.inc("12", 2)
|
||||
t.inc("34", 1)
|
||||
assert t.len() != 0
|
||||
t.clear()
|
||||
assert t.len() == 0
|
||||
|
||||
block withKeyTest:
|
||||
var t: SharedTable[int, int]
|
||||
t.init()
|
||||
t.withKey(1) do (k: int, v: var int, pairExists: var bool):
|
||||
assert(v == 0)
|
||||
pairExists = true
|
||||
v = 42
|
||||
assert(t.mget(1) == 42)
|
||||
t.withKey(1) do (k: int, v: var int, pairExists: var bool):
|
||||
assert(v == 42)
|
||||
pairExists = false
|
||||
try:
|
||||
discard t.mget(1)
|
||||
assert(false, "KeyError expected")
|
||||
except KeyError:
|
||||
discard
|
||||
t.withKey(2) do (k: int, v: var int, pairExists: var bool):
|
||||
pairExists = false
|
||||
try:
|
||||
discard t.mget(2)
|
||||
assert(false, "KeyError expected")
|
||||
except KeyError:
|
||||
template ignoreExpr(e) =
|
||||
discard
|
||||
|
||||
block takeTest:
|
||||
var t = initTable[string, int]()
|
||||
t["key"] = 123
|
||||
# test first class '..' syntactical citizen:
|
||||
ignoreExpr x <> 2..4
|
||||
# test table constructor:
|
||||
ignoreExpr({:})
|
||||
ignoreExpr({2: 3, "key": "value"})
|
||||
|
||||
var val = 0
|
||||
assert(t.take("key", val))
|
||||
assert(val == 123)
|
||||
# NEW:
|
||||
assert 56 in 50..100
|
||||
|
||||
val = -1
|
||||
assert(not t.take("key", val))
|
||||
assert(val == -1)
|
||||
|
||||
assert(not t.take("otherkey", val))
|
||||
assert(val == -1)
|
||||
|
||||
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
|
||||
assert 56 in ..60
|
||||
|
||||
|
||||
orderedTableSortTest()
|
||||
echo "true"
|
||||
block ttables2:
|
||||
proc TestHashIntInt() =
|
||||
var tab = initTable[int,int]()
|
||||
for i in 1..1_000_000:
|
||||
tab[i] = i
|
||||
for i in 1..1_000_000:
|
||||
var x = tab[i]
|
||||
if x != i : echo "not found ", i
|
||||
|
||||
proc run1() = # occupied Memory stays constant, but
|
||||
for i in 1 .. 50: # aborts at run: 44 on win32 with 3.2GB with out of memory
|
||||
TestHashIntInt()
|
||||
|
||||
# bug #2107
|
||||
|
||||
var delTab = initTable[int,int](4)
|
||||
|
||||
for i in 1..4:
|
||||
delTab[i] = i
|
||||
delTab.del(i)
|
||||
delTab[5] = 5
|
||||
|
||||
|
||||
run1()
|
||||
echo "true"
|
||||
|
||||
|
||||
block tablesref:
|
||||
const
|
||||
data = {
|
||||
"34": 123456, "12": 789,
|
||||
"90": 343, "0": 34404,
|
||||
"1": 344004, "2": 344774,
|
||||
"3": 342244, "4": 3412344,
|
||||
"5": 341232144, "6": 34214544,
|
||||
"7": 3434544, "8": 344544,
|
||||
"9": 34435644, "---00": 346677844,
|
||||
"10": 34484, "11": 34474, "19": 34464,
|
||||
"20": 34454, "30": 34141244, "40": 344114,
|
||||
"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 = newTable[tuple[x, y: int], string]()
|
||||
t[(0,0)] = "00"
|
||||
t[(1,0)] = "10"
|
||||
t[(0,1)] = "01"
|
||||
t[(1,1)] = "11"
|
||||
for x in 0..1:
|
||||
for y in 0..1:
|
||||
assert t[(x,y)] == $x & $y
|
||||
assert($t ==
|
||||
"{(x: 0, y: 1): \"01\", (x: 0, y: 0): \"00\", (x: 1, y: 0): \"10\", (x: 1, y: 1): \"11\"}")
|
||||
|
||||
block tableTest2:
|
||||
var t = newTable[string, float]()
|
||||
t["test"] = 1.2345
|
||||
t["111"] = 1.000043
|
||||
t["123"] = 1.23
|
||||
t.del("111")
|
||||
|
||||
t["012"] = 67.9
|
||||
t["123"] = 1.5 # test overwriting
|
||||
|
||||
assert t["123"] == 1.5
|
||||
try:
|
||||
echo t["111"] # deleted
|
||||
except KeyError:
|
||||
discard
|
||||
assert(not hasKey(t, "111"))
|
||||
assert "111" notin t
|
||||
|
||||
for key, val in items(data): t[key] = val.toFloat
|
||||
for key, val in items(data): assert t[key] == val.toFloat
|
||||
|
||||
|
||||
block orderedTableTest1:
|
||||
var t = newOrderedTable[string, int](2)
|
||||
for key, val in items(data): t[key] = val
|
||||
for key, val in items(data): assert t[key] == val
|
||||
var i = 0
|
||||
# `pairs` needs to yield in insertion order:
|
||||
for key, val in pairs(t):
|
||||
assert key == data[i][0]
|
||||
assert val == data[i][1]
|
||||
inc(i)
|
||||
|
||||
for key, val in mpairs(t): val = 99
|
||||
for val in mvalues(t): assert val == 99
|
||||
|
||||
block countTableTest1:
|
||||
var s = data.toTable
|
||||
var t = newCountTable[string]()
|
||||
for k in s.keys: t.inc(k)
|
||||
for k in t.keys: assert t[k] == 1
|
||||
t.inc("90", 3)
|
||||
t.inc("12", 2)
|
||||
t.inc("34", 1)
|
||||
assert t.largest()[0] == "90"
|
||||
|
||||
t.sort()
|
||||
var i = 0
|
||||
for k, v in t.pairs:
|
||||
case i
|
||||
of 0: assert k == "90" and v == 4
|
||||
of 1: assert k == "12" and v == 3
|
||||
of 2: assert k == "34" and v == 2
|
||||
else: break
|
||||
inc i
|
||||
|
||||
block SyntaxTest:
|
||||
var x = newTable[int, string]({:})
|
||||
discard x
|
||||
|
||||
block nilTest:
|
||||
var i, j: TableRef[int, int] = nil
|
||||
assert i == j
|
||||
j = newTable[int, int]()
|
||||
assert i != j
|
||||
assert j != i
|
||||
i = newTable[int, int]()
|
||||
assert i == j
|
||||
|
||||
proc orderedTableSortTest() =
|
||||
var t = newOrderedTable[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
|
||||
|
||||
block anonZipTest:
|
||||
let keys = @['a','b','c']
|
||||
let values = @[1, 2, 3]
|
||||
doAssert "{'a': 1, 'b': 2, 'c': 3}" == $ toTable zip(keys, values)
|
||||
|
||||
block clearTableTest:
|
||||
var t = newTable[string, float]()
|
||||
t["test"] = 1.2345
|
||||
t["111"] = 1.000043
|
||||
t["123"] = 1.23
|
||||
assert t.len() != 0
|
||||
t.clear()
|
||||
assert t.len() == 0
|
||||
|
||||
block clearOrderedTableTest:
|
||||
var t = newOrderedTable[string, int](2)
|
||||
for key, val in items(data): t[key] = val
|
||||
assert t.len() != 0
|
||||
t.clear()
|
||||
assert t.len() == 0
|
||||
|
||||
block clearCountTableTest:
|
||||
var t = newCountTable[string]()
|
||||
t.inc("90", 3)
|
||||
t.inc("12", 2)
|
||||
t.inc("34", 1)
|
||||
assert t.len() != 0
|
||||
t.clear()
|
||||
assert t.len() == 0
|
||||
|
||||
orderedTableSortTest()
|
||||
echo "true"
|
||||
|
||||
|
||||
block tablesref2:
|
||||
proc TestHashIntInt() =
|
||||
var tab = newTable[int,int]()
|
||||
for i in 1..1_000_000:
|
||||
tab[i] = i
|
||||
for i in 1..1_000_000:
|
||||
var x = tab[i]
|
||||
if x != i : echo "not found ", i
|
||||
|
||||
proc run1() = # occupied Memory stays constant, but
|
||||
for i in 1 .. 50: # aborts at run: 44 on win32 with 3.2GB with out of memory
|
||||
TestHashIntInt()
|
||||
|
||||
run1()
|
||||
echo "true"
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
discard """
|
||||
output: '''true'''
|
||||
"""
|
||||
|
||||
import tables
|
||||
|
||||
proc TestHashIntInt() =
|
||||
var tab = initTable[int,int]()
|
||||
for i in 1..1_000_000:
|
||||
tab[i] = i
|
||||
for i in 1..1_000_000:
|
||||
var x = tab[i]
|
||||
if x != i : echo "not found ", i
|
||||
|
||||
proc run1() = # occupied Memory stays constant, but
|
||||
for i in 1 .. 50: # aborts at run: 44 on win32 with 3.2GB with out of memory
|
||||
TestHashIntInt()
|
||||
|
||||
# bug #2107
|
||||
|
||||
var delTab = initTable[int,int](4)
|
||||
|
||||
for i in 1..4:
|
||||
delTab[i] = i
|
||||
delTab.del(i)
|
||||
delTab[5] = 5
|
||||
|
||||
|
||||
run1()
|
||||
echo "true"
|
||||
@@ -1,171 +0,0 @@
|
||||
discard """
|
||||
output: '''true'''
|
||||
"""
|
||||
|
||||
import hashes, tables, sequtils
|
||||
|
||||
const
|
||||
data = {
|
||||
"34": 123456, "12": 789,
|
||||
"90": 343, "0": 34404,
|
||||
"1": 344004, "2": 344774,
|
||||
"3": 342244, "4": 3412344,
|
||||
"5": 341232144, "6": 34214544,
|
||||
"7": 3434544, "8": 344544,
|
||||
"9": 34435644, "---00": 346677844,
|
||||
"10": 34484, "11": 34474, "19": 34464,
|
||||
"20": 34454, "30": 34141244, "40": 344114,
|
||||
"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 = newTable[tuple[x, y: int], string]()
|
||||
t[(0,0)] = "00"
|
||||
t[(1,0)] = "10"
|
||||
t[(0,1)] = "01"
|
||||
t[(1,1)] = "11"
|
||||
for x in 0..1:
|
||||
for y in 0..1:
|
||||
assert t[(x,y)] == $x & $y
|
||||
assert($t ==
|
||||
"{(x: 0, y: 1): \"01\", (x: 0, y: 0): \"00\", (x: 1, y: 0): \"10\", (x: 1, y: 1): \"11\"}")
|
||||
|
||||
block tableTest2:
|
||||
var t = newTable[string, float]()
|
||||
t["test"] = 1.2345
|
||||
t["111"] = 1.000043
|
||||
t["123"] = 1.23
|
||||
t.del("111")
|
||||
|
||||
t["012"] = 67.9
|
||||
t["123"] = 1.5 # test overwriting
|
||||
|
||||
assert t["123"] == 1.5
|
||||
try:
|
||||
echo t["111"] # deleted
|
||||
except KeyError:
|
||||
discard
|
||||
assert(not hasKey(t, "111"))
|
||||
assert "111" notin t
|
||||
|
||||
for key, val in items(data): t[key] = val.toFloat
|
||||
for key, val in items(data): assert t[key] == val.toFloat
|
||||
|
||||
|
||||
block orderedTableTest1:
|
||||
var t = newOrderedTable[string, int](2)
|
||||
for key, val in items(data): t[key] = val
|
||||
for key, val in items(data): assert t[key] == val
|
||||
var i = 0
|
||||
# `pairs` needs to yield in insertion order:
|
||||
for key, val in pairs(t):
|
||||
assert key == data[i][0]
|
||||
assert val == data[i][1]
|
||||
inc(i)
|
||||
|
||||
for key, val in mpairs(t): val = 99
|
||||
for val in mvalues(t): assert val == 99
|
||||
|
||||
block countTableTest1:
|
||||
var s = data.toTable
|
||||
var t = newCountTable[string]()
|
||||
for k in s.keys: t.inc(k)
|
||||
for k in t.keys: assert t[k] == 1
|
||||
t.inc("90", 3)
|
||||
t.inc("12", 2)
|
||||
t.inc("34", 1)
|
||||
assert t.largest()[0] == "90"
|
||||
|
||||
t.sort()
|
||||
var i = 0
|
||||
for k, v in t.pairs:
|
||||
case i
|
||||
of 0: assert k == "90" and v == 4
|
||||
of 1: assert k == "12" and v == 3
|
||||
of 2: assert k == "34" and v == 2
|
||||
else: break
|
||||
inc i
|
||||
|
||||
block SyntaxTest:
|
||||
var x = newTable[int, string]({:})
|
||||
discard x
|
||||
|
||||
block nilTest:
|
||||
var i, j: TableRef[int, int] = nil
|
||||
assert i == j
|
||||
j = newTable[int, int]()
|
||||
assert i != j
|
||||
assert j != i
|
||||
i = newTable[int, int]()
|
||||
assert i == j
|
||||
|
||||
proc orderedTableSortTest() =
|
||||
var t = newOrderedTable[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
|
||||
|
||||
block anonZipTest:
|
||||
let keys = @['a','b','c']
|
||||
let values = @[1, 2, 3]
|
||||
doAssert "{'a': 1, 'b': 2, 'c': 3}" == $ toTable zip(keys, values)
|
||||
|
||||
block clearTableTest:
|
||||
var t = newTable[string, float]()
|
||||
t["test"] = 1.2345
|
||||
t["111"] = 1.000043
|
||||
t["123"] = 1.23
|
||||
assert t.len() != 0
|
||||
t.clear()
|
||||
assert t.len() == 0
|
||||
|
||||
block clearOrderedTableTest:
|
||||
var t = newOrderedTable[string, int](2)
|
||||
for key, val in items(data): t[key] = val
|
||||
assert t.len() != 0
|
||||
t.clear()
|
||||
assert t.len() == 0
|
||||
|
||||
block clearCountTableTest:
|
||||
var t = newCountTable[string]()
|
||||
t.inc("90", 3)
|
||||
t.inc("12", 2)
|
||||
t.inc("34", 1)
|
||||
assert t.len() != 0
|
||||
t.clear()
|
||||
assert t.len() == 0
|
||||
|
||||
orderedTableSortTest()
|
||||
echo "true"
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
discard """
|
||||
output: '''true'''
|
||||
"""
|
||||
|
||||
import tables
|
||||
|
||||
proc TestHashIntInt() =
|
||||
var tab = newTable[int,int]()
|
||||
for i in 1..1_000_000:
|
||||
tab[i] = i
|
||||
for i in 1..1_000_000:
|
||||
var x = tab[i]
|
||||
if x != i : echo "not found ", i
|
||||
|
||||
proc run1() = # occupied Memory stays constant, but
|
||||
for i in 1 .. 50: # aborts at run: 44 on win32 with 3.2GB with out of memory
|
||||
TestHashIntInt()
|
||||
|
||||
run1()
|
||||
echo "true"
|
||||
275
tests/collections/ttablesthreads.nim
Normal file
275
tests/collections/ttablesthreads.nim
Normal file
@@ -0,0 +1,275 @@
|
||||
discard """
|
||||
cmd: "nim c --threads:on $file"
|
||||
output: '''true'''
|
||||
"""
|
||||
|
||||
import hashes, tables, sharedtables
|
||||
|
||||
const
|
||||
data = {
|
||||
"34": 123456, "12": 789,
|
||||
"90": 343, "0": 34404,
|
||||
"1": 344004, "2": 344774,
|
||||
"3": 342244, "4": 3412344,
|
||||
"5": 341232144, "6": 34214544,
|
||||
"7": 3434544, "8": 344544,
|
||||
"9": 34435644, "---00": 346677844,
|
||||
"10": 34484, "11": 34474, "19": 34464,
|
||||
"20": 34454, "30": 34141244, "40": 344114,
|
||||
"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"
|
||||
t[(1,0)] = "10"
|
||||
t[(0,1)] = "01"
|
||||
t[(1,1)] = "11"
|
||||
for x in 0..1:
|
||||
for y in 0..1:
|
||||
assert t[(x,y)] == $x & $y
|
||||
assert($t ==
|
||||
"{(x: 0, y: 1): \"01\", (x: 0, y: 0): \"00\", (x: 1, y: 0): \"10\", (x: 1, y: 1): \"11\"}")
|
||||
|
||||
block tableTest2:
|
||||
var t = initTable[string, float]()
|
||||
t["test"] = 1.2345
|
||||
t["111"] = 1.000043
|
||||
t["123"] = 1.23
|
||||
t.del("111")
|
||||
|
||||
t["012"] = 67.9
|
||||
t["123"] = 1.5 # test overwriting
|
||||
|
||||
assert t["123"] == 1.5
|
||||
try:
|
||||
echo t["111"] # deleted
|
||||
except KeyError:
|
||||
discard
|
||||
assert(not hasKey(t, "111"))
|
||||
|
||||
assert "123" in t
|
||||
assert("111" notin t)
|
||||
|
||||
for key, val in items(data): t[key] = val.toFloat
|
||||
for key, val in items(data): assert t[key] == val.toFloat
|
||||
|
||||
assert(not t.hasKeyOrPut("456", 4.0)) # test absent key
|
||||
assert t.hasKeyOrPut("012", 3.0) # test present key
|
||||
var x = t.mgetOrPut("111", 1.5) # test absent key
|
||||
x = x * 2
|
||||
assert x == 3.0
|
||||
x = t.mgetOrPut("test", 1.5) # test present key
|
||||
x = x * 2
|
||||
assert x == 2 * 1.2345
|
||||
|
||||
block orderedTableTest1:
|
||||
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
|
||||
var i = 0
|
||||
# `pairs` needs to yield in insertion order:
|
||||
for key, val in pairs(t):
|
||||
assert key == data[i][0]
|
||||
assert val == data[i][1]
|
||||
inc(i)
|
||||
|
||||
for key, val in mpairs(t): val = 99
|
||||
for val in mvalues(t): assert val == 99
|
||||
|
||||
block orderedTableTest2:
|
||||
var
|
||||
s = initOrderedTable[string, int]()
|
||||
t = initOrderedTable[string, int]()
|
||||
assert s == t
|
||||
for key, val in items(data): t[key] = val
|
||||
assert s != t
|
||||
for key, val in items(sorteddata): s[key] = val
|
||||
assert s != t
|
||||
t.clear()
|
||||
assert s != t
|
||||
for key, val in items(sorteddata): t[key] = val
|
||||
assert s == t
|
||||
|
||||
block countTableTest1:
|
||||
var s = data.toTable
|
||||
var t = initCountTable[string]()
|
||||
|
||||
for k in s.keys: t.inc(k)
|
||||
for k in t.keys: assert t[k] == 1
|
||||
t.inc("90", 3)
|
||||
t.inc("12", 2)
|
||||
t.inc("34", 1)
|
||||
assert t.largest()[0] == "90"
|
||||
|
||||
t.sort()
|
||||
var i = 0
|
||||
for k, v in t.pairs:
|
||||
case i
|
||||
of 0: assert k == "90" and v == 4
|
||||
of 1: assert k == "12" and v == 3
|
||||
of 2: assert k == "34" and v == 2
|
||||
else: break
|
||||
inc i
|
||||
|
||||
block countTableTest2:
|
||||
var
|
||||
s = initCountTable[int]()
|
||||
t = initCountTable[int]()
|
||||
assert s == t
|
||||
s.inc(1)
|
||||
assert s != t
|
||||
t.inc(2)
|
||||
assert s != t
|
||||
t.inc(1)
|
||||
assert s != t
|
||||
s.inc(2)
|
||||
assert s == t
|
||||
s.inc(1)
|
||||
assert s != t
|
||||
t.inc(1)
|
||||
assert s == t
|
||||
|
||||
block mpairsTableTest1:
|
||||
var t = initTable[string, int]()
|
||||
t["a"] = 1
|
||||
t["b"] = 2
|
||||
t["c"] = 3
|
||||
t["d"] = 4
|
||||
for k, v in t.mpairs:
|
||||
if k == "a" or k == "c":
|
||||
v = 9
|
||||
|
||||
for k, v in t.pairs:
|
||||
if k == "a" or k == "c":
|
||||
assert v == 9
|
||||
else:
|
||||
assert v != 1 and v != 3
|
||||
|
||||
block SyntaxTest:
|
||||
var x = toTable[int, string]({:})
|
||||
|
||||
block zeroHashKeysTest:
|
||||
proc doZeroHashValueTest[T, K, V](t: T, nullHashKey: K, value: V) =
|
||||
let initialLen = t.len
|
||||
var testTable = t
|
||||
testTable[nullHashKey] = value
|
||||
assert testTable[nullHashKey] == value
|
||||
assert testTable.len == initialLen + 1
|
||||
testTable.del(nullHashKey)
|
||||
assert testTable.len == initialLen
|
||||
|
||||
# with empty table
|
||||
doZeroHashValueTest(toTable[int,int]({:}), 0, 42)
|
||||
doZeroHashValueTest(toTable[string,int]({:}), "", 23)
|
||||
doZeroHashValueTest(toOrderedTable[int,int]({:}), 0, 42)
|
||||
doZeroHashValueTest(toOrderedTable[string,int]({:}), "", 23)
|
||||
|
||||
# with non-empty table
|
||||
doZeroHashValueTest(toTable[int,int]({1:2}), 0, 42)
|
||||
doZeroHashValueTest(toTable[string,string]({"foo": "bar"}), "", "zero")
|
||||
doZeroHashValueTest(toOrderedTable[int,int]({3:4}), 0, 42)
|
||||
doZeroHashValueTest(toOrderedTable[string,string]({"egg": "sausage"}),
|
||||
"", "spam")
|
||||
|
||||
block clearTableTest:
|
||||
var t = data.toTable
|
||||
assert t.len() != 0
|
||||
t.clear()
|
||||
assert t.len() == 0
|
||||
|
||||
block clearOrderedTableTest:
|
||||
var t = data.toOrderedTable
|
||||
assert t.len() != 0
|
||||
t.clear()
|
||||
assert t.len() == 0
|
||||
|
||||
block clearCountTableTest:
|
||||
var t = initCountTable[string]()
|
||||
t.inc("90", 3)
|
||||
t.inc("12", 2)
|
||||
t.inc("34", 1)
|
||||
assert t.len() != 0
|
||||
t.clear()
|
||||
assert t.len() == 0
|
||||
|
||||
block withKeyTest:
|
||||
var t: SharedTable[int, int]
|
||||
t.init()
|
||||
t.withKey(1) do (k: int, v: var int, pairExists: var bool):
|
||||
assert(v == 0)
|
||||
pairExists = true
|
||||
v = 42
|
||||
assert(t.mget(1) == 42)
|
||||
t.withKey(1) do (k: int, v: var int, pairExists: var bool):
|
||||
assert(v == 42)
|
||||
pairExists = false
|
||||
try:
|
||||
discard t.mget(1)
|
||||
assert(false, "KeyError expected")
|
||||
except KeyError:
|
||||
discard
|
||||
t.withKey(2) do (k: int, v: var int, pairExists: var bool):
|
||||
pairExists = false
|
||||
try:
|
||||
discard t.mget(2)
|
||||
assert(false, "KeyError expected")
|
||||
except KeyError:
|
||||
discard
|
||||
|
||||
block takeTest:
|
||||
var t = initTable[string, int]()
|
||||
t["key"] = 123
|
||||
|
||||
var val = 0
|
||||
assert(t.take("key", val))
|
||||
assert(val == 123)
|
||||
|
||||
val = -1
|
||||
assert(not t.take("key", val))
|
||||
assert(val == -1)
|
||||
|
||||
assert(not t.take("otherkey", val))
|
||||
assert(val == -1)
|
||||
|
||||
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,21 +0,0 @@
|
||||
discard """
|
||||
output: "true\ntrue"
|
||||
"""
|
||||
|
||||
type
|
||||
TFooContainer[T] = object
|
||||
|
||||
TContainer[T] = concept var c
|
||||
foo(c, T)
|
||||
|
||||
proc foo[T](c: var TFooContainer[T], val: T) =
|
||||
discard
|
||||
|
||||
proc bar(c: var TContainer) =
|
||||
discard
|
||||
|
||||
var fooContainer: TFooContainer[int]
|
||||
echo fooContainer is TFooContainer # true.
|
||||
echo fooContainer is TFooContainer[int] # true.
|
||||
fooContainer.bar()
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
type
|
||||
View[T] = concept v
|
||||
v.empty is bool
|
||||
v.front is T
|
||||
popFront v
|
||||
|
||||
proc find(view: View; target: View.T): View =
|
||||
result = view
|
||||
|
||||
while not result.empty:
|
||||
if view.front == target:
|
||||
return
|
||||
|
||||
mixin popFront
|
||||
popFront result
|
||||
|
||||
proc popFront[T](s: var seq[T]) = discard
|
||||
proc empty[T](s: seq[T]): bool = false
|
||||
|
||||
var s1 = @[1, 2, 3]
|
||||
let s2 = s1.find(10)
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
discard """
|
||||
output: 9
|
||||
"""
|
||||
|
||||
type DataTable = concept x
|
||||
x is object
|
||||
for f in fields(x):
|
||||
f is seq
|
||||
|
||||
type Students = object
|
||||
id : seq[int]
|
||||
name : seq[string]
|
||||
age: seq[int]
|
||||
|
||||
proc nrow*(dt: DataTable) : Natural =
|
||||
var totalLen = 0
|
||||
for f in fields(dt):
|
||||
totalLen += f.len
|
||||
return totalLen
|
||||
|
||||
let
|
||||
stud = Students(id : @[1,2,3], name : @["Vas", "Pas", "NafNaf"], age : @[10,16,32])
|
||||
|
||||
echo nrow(stud)
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
discard """
|
||||
output: '''
|
||||
true
|
||||
true
|
||||
true
|
||||
f
|
||||
0
|
||||
'''
|
||||
"""
|
||||
|
||||
import t5888lib/ca, t5888lib/opt
|
||||
|
||||
type LocalCA = ca.CA
|
||||
|
||||
proc f(c: CA) =
|
||||
echo "f"
|
||||
echo c.x
|
||||
|
||||
var o = new(Opt)
|
||||
|
||||
echo o is CA
|
||||
echo o is LocalCA
|
||||
echo o is ca.CA
|
||||
|
||||
o.f()
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
discard """
|
||||
exitcode: 0
|
||||
"""
|
||||
|
||||
type
|
||||
Enumerable[T] = concept e
|
||||
for it in e:
|
||||
it is T
|
||||
|
||||
proc cmap[T, G](e: Enumerable[T], fn: proc(t: T): G): seq[G] =
|
||||
result = @[]
|
||||
for it in e: result.add(fn(it))
|
||||
|
||||
import json
|
||||
|
||||
var x = %["hello", "world"]
|
||||
|
||||
var z = x.cmap(proc(it: JsonNode): string = it.getStr & "!")
|
||||
assert z == @["hello!", "world!"]
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
discard """
|
||||
output: "20.0 USD"
|
||||
"""
|
||||
|
||||
import typetraits
|
||||
|
||||
const currencies = ["USD", "EUR"] # in real code 120 currencies
|
||||
|
||||
type USD* = distinct float # in real code 120 types generates using macro
|
||||
type EUR* = distinct float
|
||||
|
||||
type CurrencyAmount = concept c
|
||||
type t = c.type
|
||||
const name = c.type.name
|
||||
name in currencies
|
||||
|
||||
proc `$`(x: CurrencyAmount): string =
|
||||
$float(x) & " " & x.name
|
||||
|
||||
let amount = 20.USD
|
||||
echo amount
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
discard """
|
||||
output: "true"
|
||||
"""
|
||||
|
||||
import future
|
||||
|
||||
type
|
||||
FilterMixin*[T] = ref object
|
||||
test*: (T) -> bool
|
||||
trans*: (T) -> T
|
||||
|
||||
SeqGen*[T] = ref object
|
||||
fil*: FilterMixin[T]
|
||||
|
||||
WithFilter[T] = concept a
|
||||
a.fil is FilterMixin[T]
|
||||
|
||||
proc test*[T](a: WithFilter[T]): (T) -> bool =
|
||||
a.fil.test
|
||||
|
||||
var s = SeqGen[int](fil: FilterMixin[int](test: nil, trans: nil))
|
||||
echo s.test() == nil
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
discard """
|
||||
output: '''
|
||||
10
|
||||
10
|
||||
'''
|
||||
"""
|
||||
|
||||
type GA = concept c
|
||||
c.a is int
|
||||
|
||||
type A = object
|
||||
a: int
|
||||
|
||||
type AA = object
|
||||
case exists: bool
|
||||
of true:
|
||||
a: int
|
||||
else:
|
||||
discard
|
||||
|
||||
proc print(inp: GA) =
|
||||
echo inp.a
|
||||
|
||||
let failing = AA(exists: true, a: 10)
|
||||
let working = A(a:10)
|
||||
print(working)
|
||||
print(failing)
|
||||
@@ -1,12 +0,0 @@
|
||||
discard """
|
||||
output: 5
|
||||
"""
|
||||
|
||||
type
|
||||
HasLen = concept iter
|
||||
len(iter) is int
|
||||
|
||||
proc echoLen(x: HasLen) =
|
||||
echo len(x)
|
||||
|
||||
echoLen([1, 2, 3, 4, 5])
|
||||
@@ -1,16 +0,0 @@
|
||||
discard """
|
||||
output: "()"
|
||||
"""
|
||||
|
||||
type
|
||||
Iterable[T] = concept x
|
||||
for elem in x:
|
||||
elem is T
|
||||
|
||||
proc max[A](iter: Iterable[A]): A =
|
||||
discard
|
||||
|
||||
type
|
||||
MyType = object
|
||||
|
||||
echo max(@[MyType()])
|
||||
@@ -1,54 +0,0 @@
|
||||
discard """
|
||||
output: '''Printable'''
|
||||
"""
|
||||
|
||||
import macros
|
||||
|
||||
type
|
||||
int1 = distinct int
|
||||
int2 = distinct int
|
||||
|
||||
int1g = concept x
|
||||
x is int1
|
||||
|
||||
int2g = concept x
|
||||
x is int2
|
||||
|
||||
proc take[T: int1g](value: int1) =
|
||||
when T is int2:
|
||||
static: error("killed in take(int1)")
|
||||
|
||||
proc take[T: int2g](vale: int2) =
|
||||
when T is int1:
|
||||
static: error("killed in take(int2)")
|
||||
|
||||
var i1: int1 = 1.int1
|
||||
var i2: int2 = 2.int2
|
||||
|
||||
take[int1](i1)
|
||||
take[int2](i2)
|
||||
|
||||
template reject(e) =
|
||||
static: assert(not compiles(e))
|
||||
|
||||
reject take[string](i2)
|
||||
reject take[int1](i2)
|
||||
|
||||
# bug #6249
|
||||
type
|
||||
Obj1[T] = object
|
||||
v: T
|
||||
|
||||
Obj2 = ref object
|
||||
|
||||
PrintAble = concept x
|
||||
$x is string
|
||||
|
||||
converter toObj1[T](t: T): Obj1[T] =
|
||||
return Obj1[T](v: t)
|
||||
|
||||
proc `$`[T](nt: Obj1[T]): string =
|
||||
when T is PrintAble: result = "Printable"
|
||||
else: result = "Non Printable"
|
||||
|
||||
echo Obj2()
|
||||
441
tests/concepts/tconcepts.nim
Normal file
441
tests/concepts/tconcepts.nim
Normal file
@@ -0,0 +1,441 @@
|
||||
discard """
|
||||
file: "tconcepts.nim"
|
||||
output: '''
|
||||
10
|
||||
20
|
||||
int
|
||||
20
|
||||
3
|
||||
x as ParameterizedType[T]
|
||||
x as ParameterizedType[T]
|
||||
x as ParameterizedType[T]
|
||||
x as ParameterizedType
|
||||
x as ParameterizedType
|
||||
x as CustomTypeClass
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
a
|
||||
b
|
||||
t
|
||||
e
|
||||
s
|
||||
t
|
||||
z
|
||||
e
|
||||
1
|
||||
2
|
||||
3
|
||||
20
|
||||
10
|
||||
5
|
||||
'''
|
||||
"""
|
||||
|
||||
|
||||
import typetraits, strutils
|
||||
|
||||
|
||||
block tcomparable:
|
||||
type
|
||||
Comparable = concept a
|
||||
(a < a) is bool
|
||||
|
||||
proc myMax(a, b: Comparable): Comparable =
|
||||
if a < b:
|
||||
return b
|
||||
else:
|
||||
return a
|
||||
|
||||
doAssert myMax(5, 10) == 10
|
||||
doAssert myMax(31.3, 1.23124) == 31.3
|
||||
|
||||
|
||||
|
||||
block tconceptinclosure:
|
||||
type
|
||||
FonConcept = concept x
|
||||
x.x is int
|
||||
GenericConcept[T] = concept x
|
||||
x.x is T
|
||||
const L = T.name.len
|
||||
Implementation = object
|
||||
x: int
|
||||
Closure = object
|
||||
f: proc()
|
||||
|
||||
proc f1(x: FonConcept): Closure =
|
||||
result.f = proc () =
|
||||
echo x.x
|
||||
|
||||
proc f2(x: GenericConcept): Closure =
|
||||
result.f = proc () =
|
||||
echo x.x
|
||||
echo GenericConcept.T.name
|
||||
|
||||
proc f3[T](x: GenericConcept[T]): Closure =
|
||||
result.f = proc () =
|
||||
echo x.x
|
||||
echo x.L
|
||||
|
||||
let x = Implementation(x: 10)
|
||||
let y = Implementation(x: 20)
|
||||
|
||||
let a = x.f1
|
||||
let b = x.f2
|
||||
let c = x.f1
|
||||
let d = y.f2
|
||||
let e = y.f3
|
||||
|
||||
a.f()
|
||||
d.f()
|
||||
e.f()
|
||||
|
||||
|
||||
|
||||
block overload_precedence:
|
||||
type ParameterizedType[T] = object
|
||||
|
||||
type CustomTypeClass = concept
|
||||
true
|
||||
|
||||
# 3 competing procs
|
||||
proc a[T](x: ParameterizedType[T]) =
|
||||
echo "x as ParameterizedType[T]"
|
||||
|
||||
proc a(x: ParameterizedType) =
|
||||
echo "x as ParameterizedType"
|
||||
|
||||
proc a(x: CustomTypeClass) =
|
||||
echo "x as CustomTypeClass"
|
||||
|
||||
# the same procs in different order
|
||||
proc b(x: ParameterizedType) =
|
||||
echo "x as ParameterizedType"
|
||||
|
||||
proc b(x: CustomTypeClass) =
|
||||
echo "x as CustomTypeClass"
|
||||
|
||||
proc b[T](x: ParameterizedType[T]) =
|
||||
echo "x as ParameterizedType[T]"
|
||||
|
||||
# and yet another order
|
||||
proc c(x: CustomTypeClass) =
|
||||
echo "x as CustomTypeClass"
|
||||
|
||||
proc c(x: ParameterizedType) =
|
||||
echo "x as ParameterizedType"
|
||||
|
||||
proc c[T](x: ParameterizedType[T]) =
|
||||
echo "x as ParameterizedType[T]"
|
||||
|
||||
# remove the most specific one
|
||||
proc d(x: ParameterizedType) =
|
||||
echo "x as ParameterizedType"
|
||||
|
||||
proc d(x: CustomTypeClass) =
|
||||
echo "x as CustomTypeClass"
|
||||
|
||||
# then shuffle the order again
|
||||
proc e(x: CustomTypeClass) =
|
||||
echo "x as CustomTypeClass"
|
||||
|
||||
proc e(x: ParameterizedType) =
|
||||
echo "x as ParameterizedType"
|
||||
|
||||
# the least specific one is a match
|
||||
proc f(x: CustomTypeClass) =
|
||||
echo "x as CustomTypeClass"
|
||||
|
||||
a(ParameterizedType[int]())
|
||||
b(ParameterizedType[int]())
|
||||
c(ParameterizedType[int]())
|
||||
d(ParameterizedType[int]())
|
||||
e(ParameterizedType[int]())
|
||||
f(ParameterizedType[int]())
|
||||
|
||||
|
||||
|
||||
block templates:
|
||||
template typeLen(x): int = x.type.name.len
|
||||
|
||||
template bunchOfChecks(x) =
|
||||
x.typeLen > 3
|
||||
x != 10 is bool
|
||||
|
||||
template stmtListExprTmpl(x: untyped): untyped =
|
||||
x is int
|
||||
x
|
||||
|
||||
type
|
||||
Obj = object
|
||||
x: int
|
||||
|
||||
Gen[T] = object
|
||||
x: T
|
||||
|
||||
Eq = concept x, y
|
||||
(x == y) is bool
|
||||
|
||||
NotEq = concept x, y
|
||||
(x != y) is bool
|
||||
|
||||
ConceptUsingTemplate1 = concept x
|
||||
echo x
|
||||
sizeof(x) is int
|
||||
bunchOfChecks x
|
||||
|
||||
ConceptUsingTemplate2 = concept x
|
||||
stmtListExprTmpl x
|
||||
|
||||
template ok(x) =
|
||||
static: assert(x)
|
||||
|
||||
template no(x) =
|
||||
static: assert(not(x))
|
||||
|
||||
ok int is Eq
|
||||
ok int is NotEq
|
||||
ok string is Eq
|
||||
ok string is NotEq
|
||||
ok Obj is Eq
|
||||
ok Obj is NotEq
|
||||
ok Gen[string] is Eq
|
||||
ok Gen[int] is NotEq
|
||||
|
||||
no int is ConceptUsingTemplate1
|
||||
ok float is ConceptUsingTemplate1
|
||||
no string is ConceptUsingTemplate1
|
||||
|
||||
ok int is ConceptUsingTemplate2
|
||||
no float is ConceptUsingTemplate2
|
||||
no string is ConceptUsingTemplate2
|
||||
|
||||
|
||||
|
||||
block titerable:
|
||||
type
|
||||
Iterable[T] = concept x
|
||||
for value in x:
|
||||
type(value) is T
|
||||
|
||||
proc sum[T](iter: Iterable[T]): T =
|
||||
static: echo T.name
|
||||
for element in iter:
|
||||
static: echo element.type.name
|
||||
result += element
|
||||
|
||||
doAssert sum([1, 2, 3, 4, 5]) == 15
|
||||
|
||||
|
||||
|
||||
block tmanual:
|
||||
template accept(e) =
|
||||
static: assert compiles(e)
|
||||
|
||||
template reject(e) =
|
||||
static: assert(not compiles(e))
|
||||
|
||||
type
|
||||
Container[T] = concept c
|
||||
c.len is Ordinal
|
||||
items(c) is T
|
||||
for value in c:
|
||||
type(value) is T
|
||||
|
||||
proc takesIntContainer(c: Container[int]) =
|
||||
for e in c: echo e
|
||||
|
||||
takesIntContainer(@[1, 2, 3])
|
||||
reject takesIntContainer(@["x", "y"])
|
||||
|
||||
proc takesContainer(c: Container) =
|
||||
for e in c: echo e
|
||||
|
||||
takesContainer(@[4, 5, 6])
|
||||
takesContainer(@["a", "b"])
|
||||
takesContainer "test"
|
||||
reject takesContainer(10)
|
||||
|
||||
|
||||
|
||||
block modifiers_in_place:
|
||||
type
|
||||
VarContainer[T] = concept c
|
||||
put(var c, T)
|
||||
AltVarContainer[T] = concept var c
|
||||
put(c, T)
|
||||
NonVarContainer[T] = concept c
|
||||
put(c, T)
|
||||
GoodContainer = object
|
||||
x: int
|
||||
BadContainer = object
|
||||
x: int
|
||||
|
||||
proc put(x: BadContainer, y: int) = discard
|
||||
proc put(x: var GoodContainer, y: int) = discard
|
||||
|
||||
template ok(x) = assert(x)
|
||||
template no(x) = assert(not(x))
|
||||
|
||||
static:
|
||||
ok GoodContainer is VarContainer[int]
|
||||
ok GoodContainer is AltVarContainer[int]
|
||||
no BadContainer is VarContainer[int]
|
||||
no BadContainer is AltVarContainer[int]
|
||||
ok GoodContainer is NonVarContainer[int]
|
||||
ok BadContainer is NonVarContainer[int]
|
||||
|
||||
|
||||
|
||||
block treversable:
|
||||
type
|
||||
Reversable[T] = concept a
|
||||
a[int] is T
|
||||
a.high is int
|
||||
a.len is int
|
||||
a.low is int
|
||||
|
||||
proc get[T](s: Reversable[T], n: int): T =
|
||||
s[n]
|
||||
|
||||
proc hi[T](s: Reversable[T]): int =
|
||||
s.high
|
||||
|
||||
proc lo[T](s: Reversable[T]): int =
|
||||
s.low
|
||||
|
||||
iterator reverse[T](s: Reversable[T]): T =
|
||||
assert hi(s) - lo(s) == len(s) - 1
|
||||
for z in hi(s).countdown(lo(s)):
|
||||
yield s.get(z)
|
||||
|
||||
for s in @["e", "z"].reverse:
|
||||
echo s
|
||||
|
||||
|
||||
|
||||
block tmonoid:
|
||||
type Monoid = concept x, y
|
||||
x + y is type(x)
|
||||
type(z(type(x))) is type(x)
|
||||
|
||||
proc z(x: typedesc[int]): int = 0
|
||||
|
||||
doAssert(int is Monoid)
|
||||
|
||||
# https://github.com/nim-lang/Nim/issues/8126
|
||||
type AdditiveMonoid = concept x, y, type T
|
||||
x + y is T
|
||||
|
||||
# some redundant checks to test an alternative approaches:
|
||||
type TT = type(x)
|
||||
x + y is type(x)
|
||||
x + y is TT
|
||||
|
||||
doAssert(1 is AdditiveMonoid)
|
||||
|
||||
|
||||
|
||||
block tesqofconcept:
|
||||
type
|
||||
MyConcept = concept x
|
||||
someProc(x)
|
||||
SomeSeq = seq[MyConcept]
|
||||
|
||||
proc someProc(x:int) = echo x
|
||||
|
||||
proc work (s: SomeSeq) =
|
||||
for item in s:
|
||||
someProc item
|
||||
|
||||
var s = @[1, 2, 3]
|
||||
work s
|
||||
|
||||
|
||||
|
||||
block tvectorspace:
|
||||
type VectorSpace[K] = concept x, y
|
||||
x + y is type(x)
|
||||
zero(type(x)) is type(x)
|
||||
-x is type(x)
|
||||
x - y is type(x)
|
||||
var k: K
|
||||
k * x is type(x)
|
||||
|
||||
proc zero(T: typedesc): T = 0
|
||||
|
||||
static:
|
||||
assert float is VectorSpace[float]
|
||||
# assert float is VectorSpace[int]
|
||||
# assert int is VectorSpace
|
||||
|
||||
|
||||
|
||||
block tstack:
|
||||
template reject(e) =
|
||||
static: assert(not compiles(e))
|
||||
|
||||
type
|
||||
ArrayStack = object
|
||||
data: seq[int]
|
||||
|
||||
proc push(s: var ArrayStack, item: int) =
|
||||
s.data.add item
|
||||
|
||||
proc pop(s: var ArrayStack): int =
|
||||
return s.data.pop()
|
||||
|
||||
type
|
||||
Stack[T] = concept var s
|
||||
s.push(T)
|
||||
s.pop() is T
|
||||
|
||||
type ValueType = T
|
||||
const ValueTypeName = T.name.toUpperAscii
|
||||
|
||||
proc genericAlgorithm[T](s: var Stack[T], y: T) =
|
||||
static:
|
||||
echo "INFERRED ", T.name
|
||||
echo "VALUE TYPE ", s.ValueType.name
|
||||
echo "VALUE TYPE NAME ", s.ValueTypeName
|
||||
|
||||
s.push(y)
|
||||
echo s.pop
|
||||
|
||||
proc implicitGeneric(s: var Stack): auto =
|
||||
static:
|
||||
echo "IMPLICIT INFERRED ", s.T.name, " ", Stack.T.name
|
||||
echo "IMPLICIT VALUE TYPE ", s.ValueType.name, " ", Stack.ValueType.name
|
||||
echo "IMPLICIT VALUE TYPE NAME ", s.ValueTypeName, " ", Stack.ValueTypeName
|
||||
|
||||
return s.pop()
|
||||
|
||||
var s = ArrayStack(data: @[])
|
||||
|
||||
s.push 10
|
||||
s.genericAlgorithm 20
|
||||
echo s.implicitGeneric
|
||||
|
||||
reject s.genericAlgorithm "x"
|
||||
reject s.genericAlgorithm 1.0
|
||||
reject "str".implicitGeneric
|
||||
reject implicitGeneric(10)
|
||||
|
||||
|
||||
|
||||
import libs/[trie_database, trie]
|
||||
block ttrie:
|
||||
proc takeDb(d: TrieDatabase) = discard
|
||||
var mdb: MemDB
|
||||
takeDb(mdb)
|
||||
|
||||
|
||||
|
||||
import mvarconcept
|
||||
block tvar:
|
||||
# bug #2346, bug #2404
|
||||
echo randomInt(5)
|
||||
@@ -1,34 +0,0 @@
|
||||
# bug #3452
|
||||
import math
|
||||
|
||||
type
|
||||
Node* = concept n
|
||||
`==`(n, n) is bool
|
||||
|
||||
Graph1* = concept g
|
||||
type N = Node
|
||||
distance(g, N, N) is float
|
||||
|
||||
Graph2 = concept g
|
||||
distance(g, Node, Node) is float
|
||||
|
||||
Graph3 = concept g
|
||||
var x: Node
|
||||
distance(g, x, x) is float
|
||||
|
||||
XY* = tuple[x, y: int]
|
||||
|
||||
MyGraph* = object
|
||||
points: seq[XY]
|
||||
|
||||
static:
|
||||
assert XY is Node
|
||||
|
||||
proc distance*( g: MyGraph, a, b: XY): float =
|
||||
sqrt( pow(float(a.x - b.x), 2) + pow(float(a.y - b.y), 2) )
|
||||
|
||||
static:
|
||||
assert MyGraph is Graph1
|
||||
assert MyGraph is Graph2
|
||||
assert MyGraph is Graph3
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
|
||||
# bug #6691
|
||||
type
|
||||
ConceptA = concept c
|
||||
|
||||
ConceptB = concept c
|
||||
c.myProc(ConceptA)
|
||||
|
||||
Obj = object
|
||||
|
||||
proc myProc(obj: Obj, x: ConceptA) = discard
|
||||
|
||||
echo Obj is ConceptB
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user