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
This commit is contained in:
parent
d2b04a8bc7
commit
7f18d7cbc1
103 changed files with 3736 additions and 3368 deletions
|
|
@ -1,5 +1,8 @@
|
||||||
discard """
|
discard """
|
||||||
output: "action 3 arg"
|
output: '''
|
||||||
|
action 3 arg
|
||||||
|
action 3 arg
|
||||||
|
'''
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import tables
|
import tables
|
||||||
|
|
@ -17,10 +20,18 @@ proc action4(arg: string) =
|
||||||
echo "action 4 ", arg
|
echo "action 4 ", arg
|
||||||
|
|
||||||
var
|
var
|
||||||
actionTable = {
|
actionTable1 = {
|
||||||
"A": action1,
|
"A": action1,
|
||||||
"B": action2,
|
"B": action2,
|
||||||
"C": action3,
|
"C": action3,
|
||||||
"D": action4}.toTable
|
"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 """
|
discard """
|
||||||
file: "tarray.nim"
|
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
|
type
|
||||||
TMyArray = array[0..2, int]
|
MetadataArray* = object
|
||||||
TMyRecord = tuple[x, y: int]
|
data*: array[8, int]
|
||||||
|
len*: int
|
||||||
|
|
||||||
proc sum(a: TMyarray): int =
|
# Commenting the converter removes the error "lib/system.nim(3536, 3) Error: for a 'var' type a variable needs to be passed"
|
||||||
result = 0
|
converter toMetadataArray*(se: varargs[int]): MetadataArray {.inline.} =
|
||||||
var i = 0
|
result.len = se.len
|
||||||
while i < len(a):
|
for i in 0..<se.len:
|
||||||
inc(result, a[i])
|
result.data[i] = se[i]
|
||||||
inc(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 =
|
block troofregression:
|
||||||
result = r.x + r.y
|
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]))
|
## With Nim devel from the start of the week (~Oct30) I managed to trigger "lib/system.nim(3536, 4) Error: expression has no address"
|
||||||
write(stdout, sum([]))
|
## but I can't anymore after updating Nim (Nov5)
|
||||||
write(stdout, getPos( (x: 5, y: 7) ))
|
## 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"
|
||||||
#OUT 10012
|
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)
|
proc test[T](sx: MySeq[T]) =
|
||||||
const arr1: array[0, int] = []
|
# Removing the backward index removes the error "lib/system.nim(3536, 3) Error: for a 'var' type a variable needs to be passed"
|
||||||
const arr2 = []
|
echo sx.data[^1] # error here
|
||||||
let arr3: array[0, string] = []
|
|
||||||
|
|
||||||
doAssert(arr1.len == 0)
|
let s = MySeq[int](data: @[1, 2, 3])
|
||||||
doAssert(arr2.len == 0)
|
s.test()
|
||||||
doAssert(arr3.len == 0)
|
|
||||||
|
|
||||||
# Negative array length is not allowed (#6852)
|
|
||||||
doAssert(not compiles(block:
|
# bug #6989
|
||||||
var arr: array[-1, int]))
|
|
||||||
|
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
|
# 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
|
proc test() =
|
||||||
TRec = object
|
var
|
||||||
x, y: int
|
a, b: TRec
|
||||||
s: string
|
a.x = 1
|
||||||
seq: seq[string]
|
a.y = 2
|
||||||
arr: seq[seq[array[0..3, string]]]
|
a.s = "Hallo!"
|
||||||
TRecSeq = seq[TRec]
|
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
|
var
|
||||||
a, b: TRec
|
t: Other
|
||||||
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!
|
t.a = "test"
|
||||||
b.seq = @["xyz", "huch", "was", "soll"]
|
t.b = 1
|
||||||
writeLine(stdout, len(a.seq))
|
t.c = 2
|
||||||
writeLine(stdout, a.seq[3])
|
t.haha = 3
|
||||||
writeLine(stdout, len(b.seq))
|
|
||||||
writeLine(stdout, b.seq[3])
|
|
||||||
writeLine(stdout, b.y)
|
|
||||||
|
|
||||||
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 """
|
discard """
|
||||||
output: '''yeah A enumB
|
output: '''
|
||||||
|
yeah A enumB
|
||||||
yeah A enumB
|
yeah A enumB
|
||||||
yeah CD enumD
|
yeah CD enumD
|
||||||
yeah CD enumE
|
yeah CD enumE
|
||||||
|
|
@ -10,7 +11,8 @@ yeah A enumB
|
||||||
yeah B enumC
|
yeah B enumC
|
||||||
yeah A enumB
|
yeah A enumB
|
||||||
yeah A enumB
|
yeah A enumB
|
||||||
yeah A enumB'''
|
yeah A enumB
|
||||||
|
'''
|
||||||
"""
|
"""
|
||||||
|
|
||||||
type
|
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 """
|
discard """
|
||||||
file: "tclosure.nim"
|
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*(
|
proc each(n: openarray[int], fn: proc(x: int) {.closure.}) =
|
||||||
MutatorCount: static[int],
|
for i in 0..n.len-1:
|
||||||
mTable: static[array[MutatorCount, Mutator]], input: string) =
|
fn(n[i])
|
||||||
for i in 0..<MutatorCount: echo mTable[i](input)
|
|
||||||
|
|
||||||
proc mutator0(matched: string): string =
|
var myData: array[0..4, int] = [0, 1, 2, 3, 4]
|
||||||
"foo"
|
|
||||||
|
|
||||||
const
|
proc testA() =
|
||||||
mTable = [Mutator(mutator0)]
|
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,35 +0,0 @@
|
||||||
discard """
|
|
||||||
output: '''
|
|
||||||
onetwothree
|
|
||||||
onetwothree
|
|
||||||
onetwothree
|
|
||||||
one1two2three3
|
|
||||||
'''
|
|
||||||
"""
|
|
||||||
|
|
||||||
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,17 +1,69 @@
|
||||||
discard """
|
discard """
|
||||||
file: "tcnstseq.nim"
|
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
|
# Test the new implicit conversion from sequences to arrays in a constant
|
||||||
# context.
|
# context.
|
||||||
|
|
||||||
import strutils
|
import strutils
|
||||||
|
|
||||||
const
|
|
||||||
myWords = "Angelika Anne Anna Anka Anja".split()
|
|
||||||
|
|
||||||
for x in items(myWords):
|
block t1:
|
||||||
write(stdout, x) #OUT AngelikaAnneAnnaAnkaAnja
|
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 sets, hashes, algorithm
|
||||||
import hashes
|
|
||||||
import algorithm
|
|
||||||
|
|
||||||
block setEquality:
|
block setEquality:
|
||||||
var
|
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 """
|
discard """
|
||||||
cmd: "nim c --threads:on $file"
|
file: "ttables.nim"
|
||||||
output: '''true'''
|
output: '''
|
||||||
|
done
|
||||||
|
And we get here
|
||||||
|
true
|
||||||
|
true
|
||||||
|
true
|
||||||
|
true
|
||||||
|
'''
|
||||||
"""
|
"""
|
||||||
|
import hashes, sequtils, tables
|
||||||
|
|
||||||
import hashes, tables, sharedtables
|
|
||||||
|
|
||||||
const
|
block tableadds:
|
||||||
data = {
|
proc main =
|
||||||
"34": 123456, "12": 789,
|
var tab = newTable[string, string]()
|
||||||
"90": 343, "0": 34404,
|
for i in 0..1000:
|
||||||
"1": 344004, "2": 344774,
|
tab.add "key", "value " & $i
|
||||||
"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 = {
|
main()
|
||||||
"---00": 346677844,
|
echo "done"
|
||||||
"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:
|
block tcounttable:
|
||||||
var t = initTable[string, float]()
|
# bug #2625
|
||||||
t["test"] = 1.2345
|
const s_len = 32
|
||||||
t["111"] = 1.000043
|
var substr_counts: CountTable[string] = initCountTable[string]()
|
||||||
t["123"] = 1.23
|
var my_string = "Hello, this is sadly broken for strings over 64 characters. Note that it *does* appear to work for short strings."
|
||||||
t.del("111")
|
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
|
echo "And we get here"
|
||||||
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
|
block thashes:
|
||||||
assert("111" notin t)
|
# 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
|
# Test with char
|
||||||
for key, val in items(data): assert t[key] == val.toFloat
|
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
|
# Test with enum
|
||||||
assert t.hasKeyOrPut("012", 3.0) # test present key
|
block:
|
||||||
var x = t.mgetOrPut("111", 1.5) # test absent key
|
type
|
||||||
x = x * 2
|
E = enum eA, eB, eC
|
||||||
assert x == 3.0
|
var t = initTable[E,int]()
|
||||||
x = t.mgetOrPut("test", 1.5) # test present key
|
t[eA] = 42
|
||||||
x = x * 2
|
t[eB] = t[eA] + 1
|
||||||
assert x == 2 * 1.2345
|
assert(t[eA] == 42)
|
||||||
|
assert(t[eB] == 43)
|
||||||
|
let t2 = {eA: 1, eB: 2}.toTable
|
||||||
|
assert(t2[eB] == 2)
|
||||||
|
|
||||||
block orderedTableTest1:
|
# Test with range
|
||||||
var t = initOrderedTable[string, int](2)
|
block:
|
||||||
for key, val in items(data): t[key] = val
|
type
|
||||||
for key, val in items(data): assert t[key] == val
|
R = range[1..10]
|
||||||
var i = 0
|
var t = initTable[R,int]() # causes warning, why?
|
||||||
# `pairs` needs to yield in insertion order:
|
t[1] = 42 # causes warning, why?
|
||||||
for key, val in pairs(t):
|
t[2] = t[1] + 1
|
||||||
assert key == data[i][0]
|
assert(t[1] == 42)
|
||||||
assert val == data[i][1]
|
assert(t[2] == 43)
|
||||||
inc(i)
|
let t2 = {1.R: 1, 2.R: 2}.toTable
|
||||||
|
assert(t2[2.R] == 2)
|
||||||
|
|
||||||
for key, val in mpairs(t): val = 99
|
# Test which combines the generics for tuples + ordinals
|
||||||
for val in mvalues(t): assert val == 99
|
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:
|
# Test to check if overloading is possible
|
||||||
var
|
# Unfortunately, this does not seem to work for int
|
||||||
s = initOrderedTable[string, int]()
|
# The same test with a custom hash(s: string) does
|
||||||
t = initOrderedTable[string, int]()
|
# work though.
|
||||||
assert s == t
|
block:
|
||||||
for key, val in items(data): t[key] = val
|
proc hash(x: int): Hash {.inline.} =
|
||||||
assert s != t
|
echo "overloaded hash"
|
||||||
for key, val in items(sorteddata): s[key] = val
|
result = x
|
||||||
assert s != t
|
var t = initTable[int, int]()
|
||||||
t.clear()
|
t[0] = 0
|
||||||
assert s != t
|
|
||||||
for key, val in items(sorteddata): t[key] = val
|
|
||||||
assert s == t
|
|
||||||
|
|
||||||
block countTableTest1:
|
# Check hashability of all integer types (issue #5429)
|
||||||
var s = data.toTable
|
block:
|
||||||
var t = initCountTable[string]()
|
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)
|
echo "true"
|
||||||
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:
|
block tindexby:
|
||||||
var
|
doAssert indexBy(newSeq[int](), proc(x: int):int = x) == initTable[int, int](), "empty int table"
|
||||||
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 tbl1 = initTable[int, int]()
|
||||||
var t = initTable[string, int]()
|
tbl1.add(1,1)
|
||||||
t["a"] = 1
|
tbl1.add(2,2)
|
||||||
t["b"] = 2
|
doAssert indexBy(@[1,2], proc(x: int):int = x) == tbl1, "int table"
|
||||||
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:
|
type
|
||||||
if k == "a" or k == "c":
|
TElem = object
|
||||||
assert v == 9
|
foo: int
|
||||||
else:
|
bar: string
|
||||||
assert v != 1 and v != 3
|
|
||||||
|
|
||||||
block SyntaxTest:
|
let
|
||||||
var x = toTable[int, string]({:})
|
elem1 = TElem(foo: 1, bar: "bar")
|
||||||
|
elem2 = TElem(foo: 2, bar: "baz")
|
||||||
|
|
||||||
block zeroHashKeysTest:
|
var tbl2 = initTable[string, TElem]()
|
||||||
proc doZeroHashValueTest[T, K, V](t: T, nullHashKey: K, value: V) =
|
tbl2.add("bar", elem1)
|
||||||
let initialLen = t.len
|
tbl2.add("baz", elem2)
|
||||||
var testTable = t
|
doAssert indexBy(@[elem1,elem2], proc(x: TElem): string = x.bar) == tbl2, "element table"
|
||||||
testTable[nullHashKey] = value
|
|
||||||
assert testTable[nullHashKey] == value
|
|
||||||
assert testTable.len == initialLen + 1
|
|
||||||
testTable.del(nullHashKey)
|
|
||||||
assert testTable.len == initialLen
|
|
||||||
|
|
||||||
# with empty table
|
block tableconstr:
|
||||||
doZeroHashValueTest(toTable[int,int]({:}), 0, 42)
|
# Test if the new table constructor syntax works:
|
||||||
doZeroHashValueTest(toTable[string,int]({:}), "", 23)
|
|
||||||
doZeroHashValueTest(toOrderedTable[int,int]({:}), 0, 42)
|
|
||||||
doZeroHashValueTest(toOrderedTable[string,int]({:}), "", 23)
|
|
||||||
|
|
||||||
# with non-empty table
|
template ignoreExpr(e) =
|
||||||
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
|
discard
|
||||||
|
|
||||||
block takeTest:
|
# test first class '..' syntactical citizen:
|
||||||
var t = initTable[string, int]()
|
ignoreExpr x <> 2..4
|
||||||
t["key"] = 123
|
# test table constructor:
|
||||||
|
ignoreExpr({:})
|
||||||
|
ignoreExpr({2: 3, "key": "value"})
|
||||||
|
|
||||||
var val = 0
|
# NEW:
|
||||||
assert(t.take("key", val))
|
assert 56 in 50..100
|
||||||
assert(val == 123)
|
|
||||||
|
|
||||||
val = -1
|
assert 56 in ..60
|
||||||
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()
|
block ttables2:
|
||||||
echo "true"
|
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
|
|
||||||
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue