Merge tests into a larger file (part 3 of ∞: generics) (#9347)
* merge generics issues tests * merge tgeneric * merge test with local imports * merge tcan tests * merge matcher tests * more issue tests merged * one more tcan test * merge various small tests into one file * add a test for #3717
This commit is contained in:
parent
afd5abdfc2
commit
9f8b93641e
65 changed files with 1236 additions and 1276 deletions
|
|
@ -1,29 +0,0 @@
|
||||||
discard """
|
|
||||||
msg: "int"
|
|
||||||
output: "4"
|
|
||||||
"""
|
|
||||||
|
|
||||||
import typetraits
|
|
||||||
|
|
||||||
type ArrayType[T] = distinct T
|
|
||||||
|
|
||||||
proc arrayItem(a: ArrayType): auto =
|
|
||||||
static: echo(name(type(a).T))
|
|
||||||
result = (type(a).T)(4)
|
|
||||||
|
|
||||||
var arr: ArrayType[int]
|
|
||||||
echo arrayItem(arr)
|
|
||||||
|
|
||||||
# bug #5597
|
|
||||||
|
|
||||||
template fail() = "what"
|
|
||||||
|
|
||||||
proc g[T](x: var T) =
|
|
||||||
x.fail = 3
|
|
||||||
|
|
||||||
type
|
|
||||||
Obj = object
|
|
||||||
fail: int
|
|
||||||
|
|
||||||
var y: Obj
|
|
||||||
g y
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
discard """
|
|
||||||
output: '''TMatrix[3, 3, system.int]
|
|
||||||
3'''
|
|
||||||
"""
|
|
||||||
|
|
||||||
import typetraits
|
|
||||||
|
|
||||||
type
|
|
||||||
TMatrix*[N,M: static[int], T] = object
|
|
||||||
data*: array[0..N*M-1, T]
|
|
||||||
|
|
||||||
TMat2[T] = TMatrix[2,2,T]
|
|
||||||
|
|
||||||
proc echoMatrix(a: TMatrix) =
|
|
||||||
echo a.type.name
|
|
||||||
echo TMatrix.N
|
|
||||||
|
|
||||||
proc echoMat2(a: TMat2) =
|
|
||||||
echo TMat2.M
|
|
||||||
|
|
||||||
var m = TMatrix[3,3,int](data: [1,2,3,4,5,6,7,8,9])
|
|
||||||
|
|
||||||
echoMatrix m
|
|
||||||
#echoMat2 m
|
|
||||||
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
discard """
|
|
||||||
output: "3\n0"
|
|
||||||
"""
|
|
||||||
|
|
||||||
# https://github.com/Araq/Nim/issues/1789
|
|
||||||
|
|
||||||
type
|
|
||||||
Foo[N: static[int]] = object
|
|
||||||
|
|
||||||
proc bindStaticN[N](foo: Foo[N]) =
|
|
||||||
var ar0: array[3, int]
|
|
||||||
var ar1: array[N, int]
|
|
||||||
var ar2: array[1..N, int]
|
|
||||||
var ar3: array[0..(N+10), float]
|
|
||||||
echo N
|
|
||||||
|
|
||||||
var f: Foo[3]
|
|
||||||
f.bindStaticN
|
|
||||||
|
|
||||||
# case 2
|
|
||||||
|
|
||||||
type
|
|
||||||
ObjectWithStatic[X, Y: static[int], T] = object
|
|
||||||
bar: array[X * Y, T] # this one works
|
|
||||||
|
|
||||||
AliasWithStatic[X, Y: static[int], T] = array[X * Y, T]
|
|
||||||
|
|
||||||
var
|
|
||||||
x: ObjectWithStatic[1, 2, int]
|
|
||||||
y: AliasWithStatic[2, 3, int]
|
|
||||||
|
|
||||||
# case 3
|
|
||||||
|
|
||||||
type
|
|
||||||
Bar[N: static[int], T] = object
|
|
||||||
bar: array[N, T]
|
|
||||||
|
|
||||||
proc `[]`*[N, T](f: Bar[N, T], n: range[0..(N - 1)]): T =
|
|
||||||
assert high(n) == N-1
|
|
||||||
result = f.bar[n]
|
|
||||||
|
|
||||||
var b: Bar[3, int]
|
|
||||||
echo b[2]
|
|
||||||
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
discard """
|
|
||||||
output: "42\n42"
|
|
||||||
"""
|
|
||||||
|
|
||||||
type
|
|
||||||
Foo[N: static[int]] = object
|
|
||||||
|
|
||||||
proc foo[N](x: Foo[N]) =
|
|
||||||
let n = N
|
|
||||||
echo N
|
|
||||||
echo n
|
|
||||||
|
|
||||||
var f1: Foo[42]
|
|
||||||
f1.foo
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
type
|
|
||||||
Vec*[N: static[int], T] = object
|
|
||||||
arr*: array[N, T]
|
|
||||||
|
|
||||||
Mat*[N,M: static[int], T] = object
|
|
||||||
arr*: array[N, Vec[M,T]]
|
|
||||||
|
|
||||||
var m : Mat[3,3,float]
|
|
||||||
var strMat : Mat[m.N, m.M, string]
|
|
||||||
var lenMat : Mat[m.N, m.M, int]
|
|
||||||
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
discard """
|
|
||||||
nimout: "type uint32\ntype uint32"
|
|
||||||
output: "(weight: 17.0, color: 100)"
|
|
||||||
"""
|
|
||||||
|
|
||||||
import macros
|
|
||||||
|
|
||||||
type
|
|
||||||
BaseFruit[T] = object of RootObj
|
|
||||||
color: T
|
|
||||||
|
|
||||||
Banana[T] = object of BaseFruit[uint32]
|
|
||||||
weight: T
|
|
||||||
|
|
||||||
macro printTypeName(typ: typed): untyped =
|
|
||||||
echo "type ", getType(typ).repr
|
|
||||||
|
|
||||||
proc setColor[K](self: var BaseFruit[K], c: int) =
|
|
||||||
printTypeName(self.color)
|
|
||||||
self.color = uint32(c)
|
|
||||||
|
|
||||||
var x: Banana[float64]
|
|
||||||
x.weight = 17
|
|
||||||
printTypeName(x.color)
|
|
||||||
x.setColor(100)
|
|
||||||
echo x
|
|
||||||
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
type
|
|
||||||
Matrix*[M, N: static[int], T: SomeFloat] = object
|
|
||||||
data: ref array[N * M, T]
|
|
||||||
|
|
||||||
Matrix64*[M, N: static[int]] = Matrix[M, N, float64]
|
|
||||||
|
|
||||||
proc zeros64(M,N: static[int]): Matrix64[M,N] =
|
|
||||||
new result.data
|
|
||||||
for i in 0 .. < (M * N):
|
|
||||||
result.data[i] = 0'f64
|
|
||||||
|
|
||||||
proc bar*[M,N: static[int], T](a: Matrix[M,N,T], b: Matrix[M,N,T]) =
|
|
||||||
discard
|
|
||||||
|
|
||||||
let a = zeros64(2,2)
|
|
||||||
bar(a,a)
|
|
||||||
# https://github.com/nim-lang/Nim/issues/5643
|
|
||||||
#
|
|
||||||
# The test case was failing here, because the compiler failed to
|
|
||||||
# detect the two matrix instantiations as the same type.
|
|
||||||
#
|
|
||||||
# The root cause was that the `T` type variable is a different
|
|
||||||
# type after the first Matrix type has been matched.
|
|
||||||
#
|
|
||||||
# Sigmatch was failing to match the second version of `T`, but
|
|
||||||
# due to some complex interplay between tyOr, tyTypeDesc and
|
|
||||||
# tyGenericParam this was allowed to went through. The generic
|
|
||||||
# instantiation of the second matrix was incomplete and the
|
|
||||||
# generic cache lookup failed, producing two separate types.
|
|
||||||
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
discard """
|
|
||||||
output: "perm: 22 det: 22"
|
|
||||||
"""
|
|
||||||
|
|
||||||
type Matrix[M,N: static[int]] = array[M, array[N, float]]
|
|
||||||
|
|
||||||
proc det[M,N](a: Matrix[M,N]): int = N*10 + M
|
|
||||||
proc perm[M,N](a: Matrix[M,N]): int = M*10 + N
|
|
||||||
|
|
||||||
const
|
|
||||||
a = [ [1.0, 2.0]
|
|
||||||
, [3.0, 4.0]
|
|
||||||
]
|
|
||||||
|
|
||||||
echo "perm: ", a.perm, " det: ", a.det
|
|
||||||
|
|
||||||
# This tests multiple instantiations of a generic
|
|
||||||
# proc involving static params:
|
|
||||||
type
|
|
||||||
Vector64*[N: static[int]] = ref array[N, float64]
|
|
||||||
Array64[N: static[int]] = array[N, float64]
|
|
||||||
|
|
||||||
proc vector*[N: static[int]](xs: Array64[N]): Vector64[N] =
|
|
||||||
new result
|
|
||||||
for i in 0 .. < N:
|
|
||||||
result[i] = xs[i]
|
|
||||||
|
|
||||||
let v1 = vector([1.0, 2.0, 3.0, 4.0, 5.0])
|
|
||||||
let v2 = vector([1.0, 2.0, 3.0, 4.0, 5.0])
|
|
||||||
let v3 = vector([1.0, 2.0, 3.0, 4.0])
|
|
||||||
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
discard """
|
|
||||||
output: '''
|
|
||||||
10
|
|
||||||
2.0
|
|
||||||
'''
|
|
||||||
"""
|
|
||||||
|
|
||||||
type
|
|
||||||
Data*[T:SomeNumber, U:SomeReal] = ref object
|
|
||||||
x*: T
|
|
||||||
value*: U
|
|
||||||
|
|
||||||
var d = Data[int, float64](x:10.int, value:2'f64)
|
|
||||||
echo d.x
|
|
||||||
echo d.value
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
discard """
|
|
||||||
output: "6.0"
|
|
||||||
"""
|
|
||||||
|
|
||||||
proc sum*[T](s: seq[T], R: typedesc): R =
|
|
||||||
var sum: R = 0
|
|
||||||
for x in s:
|
|
||||||
sum += R(x)
|
|
||||||
return sum
|
|
||||||
|
|
||||||
echo @[1, 2, 3].sum(float)
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
discard """
|
|
||||||
output: "1"
|
|
||||||
"""
|
|
||||||
|
|
||||||
type
|
|
||||||
Cardinal = enum
|
|
||||||
north, east, south, west
|
|
||||||
|
|
||||||
proc foo[cardinal: static[Cardinal]](): int = 1
|
|
||||||
echo(foo[north]())
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
discard """
|
|
||||||
output: '''
|
|
||||||
true
|
|
||||||
true
|
|
||||||
true
|
|
||||||
'''
|
|
||||||
"""
|
|
||||||
|
|
||||||
when true:
|
|
||||||
# Error: undeclared identifier: '|'
|
|
||||||
proc bar*[T](t:T): bool =
|
|
||||||
runnableExamples:
|
|
||||||
type Foo = int | float
|
|
||||||
true
|
|
||||||
echo bar(0)
|
|
||||||
|
|
||||||
when true:
|
|
||||||
# ok
|
|
||||||
proc bar*(t:int): bool =
|
|
||||||
runnableExamples:
|
|
||||||
type Foo = int | float
|
|
||||||
true
|
|
||||||
echo bar(0)
|
|
||||||
|
|
||||||
when true:
|
|
||||||
# Error: undeclared identifier: '|'
|
|
||||||
proc bar*(t:typedesc): bool =
|
|
||||||
runnableExamples:
|
|
||||||
type Foo = int | float
|
|
||||||
true
|
|
||||||
echo bar(int)
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
# Issue 88
|
|
||||||
|
|
||||||
type
|
|
||||||
BaseClass[V] = object of RootObj
|
|
||||||
b: V
|
|
||||||
|
|
||||||
proc new[V](t: typedesc[BaseClass], v: V): BaseClass[V] =
|
|
||||||
BaseClass[V](b: v)
|
|
||||||
|
|
||||||
proc baseMethod[V](v: BaseClass[V]): V = v.b
|
|
||||||
proc overriddenMethod[V](v: BaseClass[V]): V = v.baseMethod
|
|
||||||
|
|
||||||
type
|
|
||||||
ChildClass[V] = object of BaseClass[V]
|
|
||||||
c: V
|
|
||||||
|
|
||||||
proc new[V](t: typedesc[ChildClass], v1, v2: V): ChildClass[V] =
|
|
||||||
ChildClass[V](b: v1, c: v2)
|
|
||||||
|
|
||||||
proc overriddenMethod[V](v: ChildClass[V]): V = v.c
|
|
||||||
|
|
||||||
let c = ChildClass[string].new("Base", "Child")
|
|
||||||
|
|
||||||
assert c.baseMethod == "Base"
|
|
||||||
assert c.overriddenMethod == "Child"
|
|
||||||
|
|
||||||
|
|
||||||
# bug #4528
|
|
||||||
type GenericBase[T] = ref object of RootObj
|
|
||||||
type GenericSubclass[T] = ref object of GenericBase[T]
|
|
||||||
proc foo[T](g: GenericBase[T]) = discard
|
|
||||||
var bar: GenericSubclass[int]
|
|
||||||
foo(bar)
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
when true:
|
|
||||||
# stack overflow
|
|
||||||
template baz1*(iter: untyped): untyped =
|
|
||||||
runnableExamples:
|
|
||||||
import sugar
|
|
||||||
proc fun(a: proc(x:int): int) = discard
|
|
||||||
baz1(fun(x:int => x))
|
|
||||||
discard
|
|
||||||
|
|
||||||
proc foo1[A](ts: A) =
|
|
||||||
baz1(ts)
|
|
||||||
|
|
||||||
when true:
|
|
||||||
# ok
|
|
||||||
template baz2*(iter: untyped): untyped =
|
|
||||||
runnableExamples:
|
|
||||||
import sugar
|
|
||||||
proc fun(a: proc(x:int): int) = discard
|
|
||||||
baz2(fun(x:int => x))
|
|
||||||
discard
|
|
||||||
|
|
||||||
proc foo2(ts: int) =
|
|
||||||
baz2(ts)
|
|
||||||
|
|
||||||
when true:
|
|
||||||
# stack overflow
|
|
||||||
template baz3*(iter: untyped): untyped =
|
|
||||||
runnableExamples:
|
|
||||||
baz3(fun(x:int => x))
|
|
||||||
discard
|
|
||||||
|
|
||||||
proc foo3[A](ts: A) =
|
|
||||||
baz3(ts)
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
discard """
|
|
||||||
output: "true"
|
|
||||||
"""
|
|
||||||
|
|
||||||
# bug #2221
|
|
||||||
import tables
|
|
||||||
|
|
||||||
var tblo: TableRef[string, int]
|
|
||||||
echo tblo == nil
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
discard """
|
|
||||||
output: '''@[0.9, 0.1]'''
|
|
||||||
"""
|
|
||||||
|
|
||||||
# bug #2304
|
|
||||||
|
|
||||||
type TV2*[T:SomeNumber] = array[0..1, T]
|
|
||||||
proc newV2T*[T](x, y: T=0): TV2[T] = [x, y]
|
|
||||||
|
|
||||||
let x = newV2T[float](0.9, 0.1)
|
|
||||||
echo(@x)
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
discard """
|
|
||||||
output: "317"
|
|
||||||
"""
|
|
||||||
|
|
||||||
# bug #2599
|
|
||||||
|
|
||||||
import mbind_bracket
|
|
||||||
|
|
||||||
# also test that `[]` can be passed now as a first class construct:
|
|
||||||
|
|
||||||
template takeBracket(x, a, i: untyped) =
|
|
||||||
echo x(a, i)
|
|
||||||
|
|
||||||
var a: array[10, int]
|
|
||||||
a[8] = 317
|
|
||||||
|
|
||||||
takeBracket(`[]`, a, 8)
|
|
||||||
|
|
||||||
let reg = newRegistry[UUIDObject]()
|
|
||||||
reg.register(UUIDObject())
|
|
||||||
46
tests/generics/tcan.nim
Normal file
46
tests/generics/tcan.nim
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
discard """
|
||||||
|
output: '''
|
||||||
|
'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Created by Eric Doughty-Papassideris on 2011-02-16.
|
||||||
|
|
||||||
|
block talias_generic:
|
||||||
|
type
|
||||||
|
TGen[T] = object
|
||||||
|
TGen2[T] = TGen[T]
|
||||||
|
|
||||||
|
|
||||||
|
block talias_specialised:
|
||||||
|
type
|
||||||
|
TGen[T] = object
|
||||||
|
TSpef = TGen[string]
|
||||||
|
var s: TSpef
|
||||||
|
|
||||||
|
|
||||||
|
block tinherit:
|
||||||
|
type
|
||||||
|
TGen[T] = object of RootObj
|
||||||
|
x, y: T
|
||||||
|
TSpef[T] = object of TGen[T]
|
||||||
|
|
||||||
|
var s: TSpef[float]
|
||||||
|
s.x = 0.4
|
||||||
|
s.y = 0.6
|
||||||
|
|
||||||
|
|
||||||
|
block tspecialise:
|
||||||
|
type
|
||||||
|
TGen[T] = object {.inheritable.}
|
||||||
|
TSpef = object of TGen[string]
|
||||||
|
|
||||||
|
|
||||||
|
block tspecialised_equivalent:
|
||||||
|
type
|
||||||
|
TGen[T] = tuple[a: T]
|
||||||
|
TSpef = tuple[a: string]
|
||||||
|
|
||||||
|
var
|
||||||
|
a: TGen[string]
|
||||||
|
b: TSpef
|
||||||
|
a = b
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
##
|
|
||||||
## can_alias_generic Nim Module
|
|
||||||
##
|
|
||||||
## Created by Eric Doughty-Papassideris on 2011-02-16.
|
|
||||||
|
|
||||||
type
|
|
||||||
TGen[T] = object
|
|
||||||
TGen2[T] = TGen[T]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
discard """
|
|
||||||
disabled: false
|
|
||||||
"""
|
|
||||||
|
|
||||||
##
|
|
||||||
## can_alias_specialised_generic Nim Module
|
|
||||||
##
|
|
||||||
## Created by Eric Doughty-Papassideris on 2011-02-16.
|
|
||||||
|
|
||||||
type
|
|
||||||
TGen[T] = object
|
|
||||||
TSpef = TGen[string]
|
|
||||||
|
|
||||||
var
|
|
||||||
s: TSpef
|
|
||||||
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
##
|
|
||||||
## can_inherit_generic Nim Module
|
|
||||||
##
|
|
||||||
## Created by Eric Doughty-Papassideris on 2011-02-16.
|
|
||||||
|
|
||||||
type
|
|
||||||
TGen[T] = object of RootObj
|
|
||||||
x, y: T
|
|
||||||
|
|
||||||
TSpef[T] = object of TGen[T]
|
|
||||||
|
|
||||||
|
|
||||||
var s: TSpef[float]
|
|
||||||
s.x = 0.4
|
|
||||||
s.y = 0.6
|
|
||||||
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
##
|
|
||||||
## can_specialise_generic Nim Module
|
|
||||||
##
|
|
||||||
## Created by Eric Doughty-Papassideris on 2011-02-16.
|
|
||||||
|
|
||||||
type
|
|
||||||
TGen[T] = object {.inheritable.}
|
|
||||||
TSpef = object of TGen[string]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
discard """
|
|
||||||
output: "TEST2"
|
|
||||||
"""
|
|
||||||
|
|
||||||
# bug #2664
|
|
||||||
|
|
||||||
import mclosed_sym
|
|
||||||
|
|
||||||
proc same(r:R, d:int) = echo "TEST1"
|
|
||||||
|
|
||||||
doIt(Data[int](d:123), R())
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
import algorithm, future
|
|
||||||
|
|
||||||
type Deck = object
|
|
||||||
value: int
|
|
||||||
|
|
||||||
proc sort(h: var seq[Deck]) =
|
|
||||||
# works:
|
|
||||||
h.sort(proc (x, y: Deck): auto =
|
|
||||||
cmp(x.value, y.value))
|
|
||||||
# fails:
|
|
||||||
h.sort((x, y: Deck) => cmp(ord(x.value), ord(y.value)))
|
|
||||||
|
|
||||||
var player: seq[Deck] = @[]
|
|
||||||
|
|
||||||
player.sort()
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
|
|
||||||
type
|
|
||||||
TDict[TK, TV] = object
|
|
||||||
k: TK
|
|
||||||
v: TV
|
|
||||||
PDict[TK, TV] = ref TDict[TK, TV]
|
|
||||||
|
|
||||||
proc fakeNew[T](x: var ref T, destroy: proc (a: ref T) {.nimcall.}) =
|
|
||||||
discard
|
|
||||||
|
|
||||||
proc destroyDict[TK, TV](a: PDict[TK, TV]) =
|
|
||||||
return
|
|
||||||
proc newDict[TK, TV](a: TK, b: TV): PDict[TK, TV] =
|
|
||||||
fakeNew(result, destroyDict[TK, TV])
|
|
||||||
|
|
||||||
# Problem: destroyDict is not instantiated when newDict is instantiated!
|
|
||||||
|
|
||||||
discard newDict("a", "b")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
|
|
||||||
# bug #2752
|
|
||||||
|
|
||||||
import future, sequtils
|
|
||||||
|
|
||||||
proc myFilter[T](it: (iterator(): T), f: (proc(anything: T):bool)): (iterator(): T) =
|
|
||||||
iterator aNameWhichWillConflict(): T {.closure.}=
|
|
||||||
for x in it():
|
|
||||||
if f(x):
|
|
||||||
yield x
|
|
||||||
result = aNameWhichWillConflict
|
|
||||||
|
|
||||||
|
|
||||||
iterator testIt():int {.closure.}=
|
|
||||||
yield -1
|
|
||||||
yield 2
|
|
||||||
|
|
||||||
#let unusedVariable = myFilter(testIt, (x: int) => x > 0)
|
|
||||||
|
|
||||||
proc onlyPos(it: (iterator(): int)): (iterator(): int)=
|
|
||||||
iterator aNameWhichWillConflict(): int {.closure.}=
|
|
||||||
var filtered = onlyPos(myFilter(it, (x:int) => x > 0))
|
|
||||||
for x in filtered():
|
|
||||||
yield x
|
|
||||||
result = aNameWhichWillConflict
|
|
||||||
|
|
||||||
let x = onlyPos(testIt)
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
discard """
|
|
||||||
output: '''5 5 5
|
|
||||||
false'''
|
|
||||||
"""
|
|
||||||
|
|
||||||
import mdotlookup
|
|
||||||
|
|
||||||
foo(7)
|
|
||||||
# bug #1444
|
|
||||||
fn(4)
|
|
||||||
|
|
@ -1,61 +0,0 @@
|
||||||
discard """
|
|
||||||
output: '''
|
|
||||||
U[3]
|
|
||||||
U[(f: 3)]
|
|
||||||
U[[3]]
|
|
||||||
'''
|
|
||||||
"""
|
|
||||||
|
|
||||||
# https://github.com/nim-lang/Nim/issues/5106
|
|
||||||
|
|
||||||
import typetraits
|
|
||||||
|
|
||||||
block:
|
|
||||||
type T = distinct int
|
|
||||||
|
|
||||||
proc `+`(a, b: T): T =
|
|
||||||
T(int(a) + int(b))
|
|
||||||
|
|
||||||
type U[F: static[T]] = distinct int
|
|
||||||
|
|
||||||
proc `+`[P1, P2: static[T]](a: U[P1], b: U[P2]): U[P1 + P2] =
|
|
||||||
U[P1 + P2](int(a) + int(b))
|
|
||||||
|
|
||||||
var a = U[T(1)](1)
|
|
||||||
var b = U[T(2)](2)
|
|
||||||
var c = a + b
|
|
||||||
echo c.type.name
|
|
||||||
|
|
||||||
block:
|
|
||||||
type T = object
|
|
||||||
f: int
|
|
||||||
|
|
||||||
proc `+`(a, b: T): T =
|
|
||||||
T(f: a.f + b.f)
|
|
||||||
|
|
||||||
type U[F: static[T]] = distinct int
|
|
||||||
|
|
||||||
proc `+`[P1, P2: static[T]](a: U[P1], b: U[P2]): U[P1 + P2] =
|
|
||||||
U[P1 + P2](int(a) + int(b))
|
|
||||||
|
|
||||||
var a = U[T(f: 1)](1)
|
|
||||||
var b = U[T(f: 2)](2)
|
|
||||||
var c = a + b
|
|
||||||
echo c.type.name
|
|
||||||
|
|
||||||
block:
|
|
||||||
type T = distinct array[0..0, int]
|
|
||||||
|
|
||||||
proc `+`(a, b: T): T =
|
|
||||||
T([array[0..0, int](a)[0] + array[0..0, int](b)[0]])
|
|
||||||
|
|
||||||
type U[F: static[T]] = distinct int
|
|
||||||
|
|
||||||
proc `+`[P1, P2: static[T]](a: U[P1], b: U[P2]): U[P1 + P2] =
|
|
||||||
U[P1 + P2](int(a) + int(b))
|
|
||||||
|
|
||||||
var a = U[T([1])](1)
|
|
||||||
var b = U[T([2])](2)
|
|
||||||
var c = a + b
|
|
||||||
echo c.type.name
|
|
||||||
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
discard """
|
|
||||||
output: '''b()
|
|
||||||
720 120.0
|
|
||||||
720 120.0'''
|
|
||||||
"""
|
|
||||||
|
|
||||||
# bug #3055
|
|
||||||
proc b(t: int | string)
|
|
||||||
proc a(t: int) = b(t)
|
|
||||||
proc b(t: int | string) = echo "b()"
|
|
||||||
a(1)
|
|
||||||
|
|
||||||
# test recursive generics still work:
|
|
||||||
proc fac[T](x: T): T =
|
|
||||||
if x == 0: return 1
|
|
||||||
else: return fac(x-1)*x
|
|
||||||
|
|
||||||
echo fac(6), " ", fac(5.0)
|
|
||||||
|
|
||||||
# test recursive generic with forwarding:
|
|
||||||
proc fac2[T](x: T): T
|
|
||||||
|
|
||||||
echo fac2(6), " ", fac2(5.0)
|
|
||||||
|
|
||||||
proc fac2[T](x: T): T =
|
|
||||||
if x == 0: return 1
|
|
||||||
else: return fac2(x-1)*x
|
|
||||||
|
|
||||||
|
|
@ -1,27 +1,111 @@
|
||||||
|
discard """
|
||||||
|
output: '''
|
||||||
|
100 0
|
||||||
|
'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
import tables
|
import tables
|
||||||
|
|
||||||
type
|
|
||||||
TX = Table[string, int]
|
|
||||||
|
|
||||||
proc foo(models: seq[Table[string, float]]): seq[float] =
|
block tgeneric0:
|
||||||
result = @[]
|
type
|
||||||
for model in models.items:
|
TX = Table[string, int]
|
||||||
result.add model["foobar"]
|
|
||||||
|
|
||||||
# bug #686
|
proc foo(models: seq[Table[string, float]]): seq[float] =
|
||||||
type TType[T; A] = array[A, T]
|
result = @[]
|
||||||
|
for model in models.items:
|
||||||
|
result.add model["foobar"]
|
||||||
|
|
||||||
proc foo[T](p: TType[T, range[0..1]]) =
|
# bug #686
|
||||||
echo "foo"
|
type TType[T; A] = array[A, T]
|
||||||
proc foo[T](p: TType[T, range[0..2]]) =
|
|
||||||
echo "bar"
|
|
||||||
|
|
||||||
#bug #1366
|
proc foo[T](p: TType[T, range[0..1]]) =
|
||||||
|
echo "foo"
|
||||||
|
proc foo[T](p: TType[T, range[0..2]]) =
|
||||||
|
echo "bar"
|
||||||
|
|
||||||
proc reversed(x: auto) =
|
#bug #1366
|
||||||
for i in countdown(x.low, x.high):
|
|
||||||
echo i
|
|
||||||
|
|
||||||
reversed(@[-19, 7, -4, 6])
|
proc reversed(x: auto) =
|
||||||
|
for i in countdown(x.low, x.high):
|
||||||
|
echo i
|
||||||
|
|
||||||
|
reversed(@[-19, 7, -4, 6])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block tgeneric1:
|
||||||
|
type
|
||||||
|
TNode[T] = tuple[priority: int, data: T]
|
||||||
|
TBinHeap[T] = object
|
||||||
|
heap: seq[TNode[T]]
|
||||||
|
last: int
|
||||||
|
PBinHeap[T] = ref TBinHeap[T]
|
||||||
|
|
||||||
|
proc newBinHeap[T](heap: var PBinHeap[T], size: int) =
|
||||||
|
new(heap)
|
||||||
|
heap.last = 0
|
||||||
|
newSeq(heap.heap, size)
|
||||||
|
#newSeq(heap.seq, size)
|
||||||
|
|
||||||
|
proc parent(elem: int): int {.inline.} =
|
||||||
|
return (elem-1) div 2
|
||||||
|
|
||||||
|
proc siftUp[T](heap: PBinHeap[T], elem: int) =
|
||||||
|
var idx = elem
|
||||||
|
while idx != 0:
|
||||||
|
var p = parent(idx)
|
||||||
|
if heap.heap[idx].priority < heap.heap[p].priority:
|
||||||
|
swap(heap.heap[idx], heap.heap[p])
|
||||||
|
idx = p
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
|
||||||
|
proc add[T](heap: PBinHeap[T], priority: int, data: T) =
|
||||||
|
var node: TNode[T]
|
||||||
|
node.priority = priority
|
||||||
|
node.data = data
|
||||||
|
heap.heap[heap.last] = node
|
||||||
|
siftUp(heap, heap.last)
|
||||||
|
inc(heap.last)
|
||||||
|
|
||||||
|
proc print[T](heap: PBinHeap[T]) =
|
||||||
|
for i in countup(0, heap.last):
|
||||||
|
stdout.write($heap.heap[i].data, " ")
|
||||||
|
|
||||||
|
var heap: PBinHeap[int]
|
||||||
|
|
||||||
|
newBinHeap(heap, 256)
|
||||||
|
add(heap, 1, 100)
|
||||||
|
print(heap)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block tgeneric2:
|
||||||
|
type
|
||||||
|
TX = Table[string, int]
|
||||||
|
|
||||||
|
proc foo(models: seq[TX]): seq[int] =
|
||||||
|
result = @[]
|
||||||
|
for model in models.items:
|
||||||
|
result.add model["foobar"]
|
||||||
|
|
||||||
|
type
|
||||||
|
Obj = object
|
||||||
|
field: Table[string, string]
|
||||||
|
var t: Obj
|
||||||
|
discard initTable[type(t.field), string]()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block tgeneric4:
|
||||||
|
type
|
||||||
|
TIDGen[A: Ordinal] = object
|
||||||
|
next: A
|
||||||
|
free: seq[A]
|
||||||
|
|
||||||
|
proc newIDGen[A]: TIDGen[A] =
|
||||||
|
newSeq result.free, 0
|
||||||
|
|
||||||
|
var x = newIDGen[int]()
|
||||||
|
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
||||||
discard """
|
|
||||||
output: "100 0"
|
|
||||||
"""
|
|
||||||
|
|
||||||
# A min-heap.
|
|
||||||
type
|
|
||||||
TNode[T] = tuple[priority: int, data: T]
|
|
||||||
|
|
||||||
TBinHeap[T] = object
|
|
||||||
heap: seq[TNode[T]]
|
|
||||||
last: int
|
|
||||||
|
|
||||||
PBinHeap[T] = ref TBinHeap[T]
|
|
||||||
|
|
||||||
proc newBinHeap*[T](heap: var PBinHeap[T], size: int) =
|
|
||||||
new(heap)
|
|
||||||
heap.last = 0
|
|
||||||
newSeq(heap.heap, size)
|
|
||||||
#newSeq(heap.seq, size)
|
|
||||||
|
|
||||||
proc parent(elem: int): int {.inline.} =
|
|
||||||
return (elem-1) div 2
|
|
||||||
|
|
||||||
proc siftUp[T](heap: PBinHeap[T], elem: int) =
|
|
||||||
var idx = elem
|
|
||||||
while idx != 0:
|
|
||||||
var p = parent(idx)
|
|
||||||
if heap.heap[idx].priority < heap.heap[p].priority:
|
|
||||||
swap(heap.heap[idx], heap.heap[p])
|
|
||||||
idx = p
|
|
||||||
else:
|
|
||||||
break
|
|
||||||
|
|
||||||
proc add*[T](heap: PBinHeap[T], priority: int, data: T) =
|
|
||||||
var node: TNode[T]
|
|
||||||
node.priority = priority
|
|
||||||
node.data = data
|
|
||||||
heap.heap[heap.last] = node
|
|
||||||
siftUp(heap, heap.last)
|
|
||||||
inc(heap.last)
|
|
||||||
|
|
||||||
proc print*[T](heap: PBinHeap[T]) =
|
|
||||||
for i in countup(0, heap.last):
|
|
||||||
stdout.write($heap.heap[i].data, " ")
|
|
||||||
|
|
||||||
var
|
|
||||||
heap: PBinHeap[int]
|
|
||||||
|
|
||||||
newBinHeap(heap, 256)
|
|
||||||
add(heap, 1, 100)
|
|
||||||
print(heap)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
import tables
|
|
||||||
|
|
||||||
type
|
|
||||||
TX = Table[string, int]
|
|
||||||
|
|
||||||
proc foo(models: seq[TX]): seq[int] =
|
|
||||||
result = @[]
|
|
||||||
for model in models.items:
|
|
||||||
result.add model["foobar"]
|
|
||||||
|
|
||||||
type
|
|
||||||
Obj = object
|
|
||||||
field: Table[string, string]
|
|
||||||
var t: Obj
|
|
||||||
discard initTable[type(t.field), string]()
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
type
|
|
||||||
TIDGen*[A: Ordinal] = object
|
|
||||||
next: A
|
|
||||||
free: seq[A]
|
|
||||||
|
|
||||||
proc newIDGen*[A]: TIDGen[A] =
|
|
||||||
newSeq result.free, 0
|
|
||||||
|
|
||||||
var x = newIDGen[int]()
|
|
||||||
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
# Test to ensure TEventHandler is '.closure'
|
|
||||||
|
|
||||||
# bug #1187
|
|
||||||
|
|
||||||
type
|
|
||||||
TEventArgs* = object
|
|
||||||
skip*: bool
|
|
||||||
TEventHandler[T] = proc (e: var TEventArgs, data: T) {.closure.}
|
|
||||||
TEvent*[T] = object
|
|
||||||
#handlers: seq[TEventHandler[T]] # Does not work
|
|
||||||
handlers: seq[proc (e: var TEventArgs, d: T) {.closure.}] # works
|
|
||||||
|
|
||||||
TData = object
|
|
||||||
x: int
|
|
||||||
|
|
||||||
TSomething = object
|
|
||||||
s: TEvent[TData]
|
|
||||||
|
|
||||||
proc init*[T](e: var TEvent[T]) =
|
|
||||||
e.handlers.newSeq(0)
|
|
||||||
|
|
||||||
#proc add*[T](e: var TEvent[T], h: proc (e: var TEventArgs, data: T) {.closure.}) =
|
|
||||||
# this line works
|
|
||||||
proc add*[T](e: var TEvent[T], h: TEventHandler[T]) =
|
|
||||||
# this line does not work
|
|
||||||
e.handlers.add(h)
|
|
||||||
|
|
||||||
proc main () =
|
|
||||||
var something: TSomething
|
|
||||||
something.s.init()
|
|
||||||
var fromOutside = 4711
|
|
||||||
|
|
||||||
something.s.add() do (e: var TEventArgs, data: TData):
|
|
||||||
var x = data.x
|
|
||||||
x = fromOutside
|
|
||||||
|
|
||||||
main()
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
discard """
|
|
||||||
output: "0.0"
|
|
||||||
"""
|
|
||||||
|
|
||||||
# bug #1919
|
|
||||||
|
|
||||||
type
|
|
||||||
Base[M] = object of RootObj
|
|
||||||
a : M
|
|
||||||
|
|
||||||
Sub1[M] = object of Base[M]
|
|
||||||
b : int
|
|
||||||
|
|
||||||
Sub2[M] = object of Sub1[M]
|
|
||||||
c : int
|
|
||||||
|
|
||||||
var x: Sub2[float]
|
|
||||||
|
|
||||||
echo x.a
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
discard """
|
|
||||||
output: '''
|
|
||||||
@[1, 2]
|
|
||||||
@[3, 4]
|
|
||||||
1
|
|
||||||
'''
|
|
||||||
"""
|
|
||||||
|
|
||||||
# https://github.com/nim-lang/Nim/issues/5756
|
|
||||||
|
|
||||||
type
|
|
||||||
Vec*[N : static[int]] = object
|
|
||||||
x: int
|
|
||||||
arr*: array[N, int32]
|
|
||||||
|
|
||||||
Mat*[M,N: static[int]] = object
|
|
||||||
x: int
|
|
||||||
arr*: array[M, Vec[N]]
|
|
||||||
|
|
||||||
proc vec2*(x,y:int32) : Vec[2] =
|
|
||||||
result.arr = [x,y]
|
|
||||||
result.x = 10
|
|
||||||
|
|
||||||
proc mat2*(a,b: Vec[2]): Mat[2,2] =
|
|
||||||
result.arr = [a,b]
|
|
||||||
result.x = 20
|
|
||||||
|
|
||||||
const M = mat2(vec2(1, 2), vec2(3, 4))
|
|
||||||
|
|
||||||
let m1 = M
|
|
||||||
echo @(m1.arr[0].arr)
|
|
||||||
echo @(m1.arr[1].arr)
|
|
||||||
|
|
||||||
proc foo =
|
|
||||||
let m2 = M
|
|
||||||
echo m1.arr[0].arr[0]
|
|
||||||
|
|
||||||
foo()
|
|
||||||
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
type
|
|
||||||
TFoo[T, U, R = int] = object
|
|
||||||
x: T
|
|
||||||
y: U
|
|
||||||
z: R
|
|
||||||
|
|
||||||
TBar[T] = TFoo[T, array[4, T], T]
|
|
||||||
|
|
||||||
var x1: TFoo[int, float]
|
|
||||||
|
|
||||||
static:
|
|
||||||
assert type(x1.x) is int
|
|
||||||
assert type(x1.y) is float
|
|
||||||
assert type(x1.z) is int
|
|
||||||
|
|
||||||
var x2: TFoo[string, R = float, U = seq[int]]
|
|
||||||
|
|
||||||
static:
|
|
||||||
assert type(x2.x) is string
|
|
||||||
assert type(x2.y) is seq[int]
|
|
||||||
assert type(x2.z) is float
|
|
||||||
|
|
||||||
var x3: TBar[float]
|
|
||||||
|
|
||||||
static:
|
|
||||||
assert type(x3.x) is float
|
|
||||||
assert type(x3.y) is array[4, float]
|
|
||||||
assert type(x3.z) is float
|
|
||||||
|
|
||||||
|
|
@ -1,22 +1,40 @@
|
||||||
discard """
|
discard """
|
||||||
disabled: false
|
output: '''
|
||||||
|
'''
|
||||||
"""
|
"""
|
||||||
|
|
||||||
type
|
|
||||||
TMatcherKind = enum
|
|
||||||
mkTerminal, mkSequence, mkAlternation, mkRepeat
|
|
||||||
TMatcher[T] = object
|
|
||||||
case kind: TMatcherKind
|
|
||||||
of mkTerminal:
|
|
||||||
value: T
|
|
||||||
of mkSequence, mkAlternation:
|
|
||||||
matchers: seq[TMatcher[T]]
|
|
||||||
of mkRepeat:
|
|
||||||
matcher: PMatcher[T]
|
|
||||||
min, max: int
|
|
||||||
PMatcher[T] = ref TMatcher[T]
|
|
||||||
|
|
||||||
var
|
block tmatcher1:
|
||||||
m: PMatcher[int]
|
type
|
||||||
|
TMatcherKind = enum
|
||||||
|
mkTerminal, mkSequence, mkAlternation, mkRepeat
|
||||||
|
TMatcher[T] = object
|
||||||
|
case kind: TMatcherKind
|
||||||
|
of mkTerminal:
|
||||||
|
value: T
|
||||||
|
of mkSequence, mkAlternation:
|
||||||
|
matchers: seq[TMatcher[T]]
|
||||||
|
of mkRepeat:
|
||||||
|
matcher: PMatcher[T]
|
||||||
|
min, max: int
|
||||||
|
PMatcher[T] = ref TMatcher[T]
|
||||||
|
|
||||||
|
var m: PMatcher[int]
|
||||||
|
|
||||||
|
|
||||||
|
block tmatcher2:
|
||||||
|
type
|
||||||
|
TMatcherKind = enum
|
||||||
|
mkTerminal, mkSequence, mkAlternation, mkRepeat
|
||||||
|
TMatcher[T] = object
|
||||||
|
case kind: TMatcherKind
|
||||||
|
of mkTerminal:
|
||||||
|
value: T
|
||||||
|
of mkSequence, mkAlternation:
|
||||||
|
matchers: seq[TMatcher[T]]
|
||||||
|
of mkRepeat:
|
||||||
|
matcher: ref TMatcher[T]
|
||||||
|
min, max: int
|
||||||
|
|
||||||
|
var m: ref TMatcher[int]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
|
|
||||||
type
|
|
||||||
TMatcherKind = enum
|
|
||||||
mkTerminal, mkSequence, mkAlternation, mkRepeat
|
|
||||||
TMatcher[T] = object
|
|
||||||
case kind: TMatcherKind
|
|
||||||
of mkTerminal:
|
|
||||||
value: T
|
|
||||||
of mkSequence, mkAlternation:
|
|
||||||
matchers: seq[TMatcher[T]]
|
|
||||||
of mkRepeat:
|
|
||||||
matcher: ref TMatcher[T]
|
|
||||||
min, max: int
|
|
||||||
|
|
||||||
var
|
|
||||||
m: ref TMatcher[int]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
|
|
||||||
type
|
|
||||||
TProperty[T] = object of RootObj
|
|
||||||
getProc: proc(property: TProperty[T]): T {.nimcall.}
|
|
||||||
setProc: proc(property: TProperty[T], value: T) {.nimcall.}
|
|
||||||
value: T
|
|
||||||
|
|
||||||
proc newProperty[T](value: RootObj): TProperty[T] =
|
|
||||||
result.getProc = proc (property: TProperty[T]) =
|
|
||||||
return property.value
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
type
|
|
||||||
PA[T] = ref TA[T]
|
|
||||||
TA[T] = object
|
|
||||||
field: T
|
|
||||||
var a: PA[string]
|
|
||||||
new(a)
|
|
||||||
a.field = "some string"
|
|
||||||
|
|
||||||
|
|
||||||
proc someOther[T](len: string): seq[T] = discard
|
|
||||||
proc someOther[T](len: int): seq[T] = echo "we"
|
|
||||||
|
|
||||||
proc foo[T](x: T) =
|
|
||||||
var s = someOther[T](34)
|
|
||||||
#newSeq[T](34)
|
|
||||||
|
|
||||||
foo 23
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
when false:
|
|
||||||
# Compiles unless you use var a: PA[string]
|
|
||||||
type
|
|
||||||
PA = ref TA
|
|
||||||
TA[T] = object
|
|
||||||
|
|
||||||
|
|
||||||
# Cannot instantiate:
|
|
||||||
type
|
|
||||||
TA[T] = object
|
|
||||||
a: PA[T]
|
|
||||||
PA[T] = ref TA[T]
|
|
||||||
|
|
||||||
type
|
|
||||||
PA[T] = ref TA[T]
|
|
||||||
TA[T] = object
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
|
|
||||||
# bug #7854
|
|
||||||
|
|
||||||
type
|
|
||||||
Stream* = ref StreamObj
|
|
||||||
StreamObj* = object of RootObj
|
|
||||||
|
|
||||||
InhStream* = ref InhStreamObj
|
|
||||||
InhStreamObj* = object of Stream
|
|
||||||
f: string
|
|
||||||
|
|
||||||
proc newInhStream*(f: string): InhStream =
|
|
||||||
new(result)
|
|
||||||
result.f = f
|
|
||||||
|
|
||||||
var val: int
|
|
||||||
let str = newInhStream("input_file.json")
|
|
||||||
|
|
||||||
block:
|
|
||||||
# works:
|
|
||||||
proc load[T](data: var T, s: Stream) =
|
|
||||||
discard
|
|
||||||
load(val, str)
|
|
||||||
|
|
||||||
block:
|
|
||||||
# works
|
|
||||||
proc load[T](s: Stream, data: T) =
|
|
||||||
discard
|
|
||||||
load(str, val)
|
|
||||||
|
|
||||||
block:
|
|
||||||
# broken
|
|
||||||
proc load[T](s: Stream, data: var T) =
|
|
||||||
discard
|
|
||||||
load(str, val)
|
|
||||||
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
discard """
|
|
||||||
output: "12"
|
|
||||||
"""
|
|
||||||
|
|
||||||
# https://github.com/nim-lang/Nim/issues/5864
|
|
||||||
|
|
||||||
proc defaultStatic(s: openarray, N: static[int] = 1): int = N
|
|
||||||
proc defaultGeneric[T](a: T = 2): int = a
|
|
||||||
|
|
||||||
let a = [1, 2, 3, 4].defaultStatic()
|
|
||||||
let b = defaultGeneric()
|
|
||||||
|
|
||||||
echo a, b
|
|
||||||
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
||||||
discard """
|
|
||||||
file: "tgenericshardcases.nim"
|
|
||||||
output: "2\n5\n126\n3"
|
|
||||||
"""
|
|
||||||
|
|
||||||
import typetraits
|
|
||||||
|
|
||||||
proc typeNameLen(x: typedesc): int {.compileTime.} =
|
|
||||||
result = x.name.len
|
|
||||||
|
|
||||||
macro selectType(a, b: typedesc): typedesc =
|
|
||||||
result = a
|
|
||||||
|
|
||||||
type
|
|
||||||
Foo[T] = object
|
|
||||||
data1: array[T.high, int]
|
|
||||||
data2: array[typeNameLen(T), float]
|
|
||||||
data3: array[0..T.typeNameLen, selectType(float, int)]
|
|
||||||
|
|
||||||
MyEnum = enum A, B, C, D
|
|
||||||
|
|
||||||
var f1: Foo[MyEnum]
|
|
||||||
var f2: Foo[int8]
|
|
||||||
|
|
||||||
echo high(f1.data1) # (D = 3) - 1 == 2
|
|
||||||
echo high(f1.data2) # (MyEnum.len = 6) - 1 == 5
|
|
||||||
|
|
||||||
echo high(f2.data1) # 127 - 1 == 126
|
|
||||||
echo high(f2.data2) # int8.len - 1 == 3
|
|
||||||
|
|
||||||
static:
|
|
||||||
assert high(f1.data1) == ord(C)
|
|
||||||
assert high(f1.data2) == 5 # length of MyEnum minus one, because we used T.high
|
|
||||||
|
|
||||||
assert high(f2.data1) == 126
|
|
||||||
assert high(f2.data2) == 3
|
|
||||||
|
|
||||||
assert high(f1.data3) == 6 # length of MyEnum
|
|
||||||
assert high(f2.data3) == 4 # length of int8
|
|
||||||
|
|
||||||
assert f2.data3[0] is float
|
|
||||||
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
discard """
|
|
||||||
output: '''0
|
|
||||||
123'''
|
|
||||||
"""
|
|
||||||
|
|
||||||
# bug #3498
|
|
||||||
|
|
||||||
template defaultOf[T](t: T): untyped = (var d: T; d)
|
|
||||||
|
|
||||||
echo defaultOf(1) #<- excpected 0
|
|
||||||
|
|
||||||
# assignment using template
|
|
||||||
|
|
||||||
template tassign[T](x: var seq[T]) =
|
|
||||||
x = @[1, 2, 3]
|
|
||||||
|
|
||||||
var y: seq[int]
|
|
||||||
tassign(y) #<- x is expected = @[1, 2, 3]
|
|
||||||
tassign(y)
|
|
||||||
|
|
||||||
echo y[0], y[1], y[2]
|
|
||||||
45
tests/generics/timports.nim
Normal file
45
tests/generics/timports.nim
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
discard """
|
||||||
|
output: '''
|
||||||
|
317
|
||||||
|
TEST2
|
||||||
|
5 5 5
|
||||||
|
false
|
||||||
|
'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
import mbind_bracket, mclosed_sym, mdotlookup, mmodule_same_as_proc
|
||||||
|
|
||||||
|
|
||||||
|
block tbind_bracket:
|
||||||
|
# bug #2599
|
||||||
|
# also test that `[]` can be passed now as a first class construct:
|
||||||
|
|
||||||
|
template takeBracket(x, a, i: untyped) =
|
||||||
|
echo x(a, i)
|
||||||
|
|
||||||
|
var a: array[10, int]
|
||||||
|
a[8] = 317
|
||||||
|
|
||||||
|
takeBracket(`[]`, a, 8)
|
||||||
|
|
||||||
|
let reg = newRegistry[UUIDObject]()
|
||||||
|
reg.register(UUIDObject())
|
||||||
|
|
||||||
|
|
||||||
|
block tclosed_sym:
|
||||||
|
# bug #2664
|
||||||
|
proc same(r:R, d:int) = echo "TEST1"
|
||||||
|
doIt(Data[int](d:123), R())
|
||||||
|
|
||||||
|
|
||||||
|
block tdotlookup:
|
||||||
|
foo(7)
|
||||||
|
# bug #1444
|
||||||
|
fn(4)
|
||||||
|
|
||||||
|
|
||||||
|
block tmodule_same_as_proc:
|
||||||
|
# bug #1965
|
||||||
|
proc test[T](t: T) =
|
||||||
|
mmodule_same_as_proc"a"
|
||||||
|
test(0)
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
discard """
|
|
||||||
output: '''123
|
|
||||||
1
|
|
||||||
2
|
|
||||||
3'''
|
|
||||||
"""
|
|
||||||
|
|
||||||
import sequtils
|
|
||||||
# https://github.com/Araq/Nim/issues/797
|
|
||||||
proc foo[T](s:T):string = $s
|
|
||||||
|
|
||||||
type IntStringProc = proc(x: int): string
|
|
||||||
|
|
||||||
var f1 = IntStringProc(foo)
|
|
||||||
var f2: proc(x: int): string = foo
|
|
||||||
var f3: IntStringProc = foo
|
|
||||||
|
|
||||||
echo f1(1), f2(2), f3(3)
|
|
||||||
|
|
||||||
for x in map([1,2,3], foo): echo x
|
|
||||||
|
|
||||||
765
tests/generics/tissues.nim
Normal file
765
tests/generics/tissues.nim
Normal file
|
|
@ -0,0 +1,765 @@
|
||||||
|
discard """
|
||||||
|
output: '''
|
||||||
|
4
|
||||||
|
3
|
||||||
|
(weight: 17.0, color: 100)
|
||||||
|
perm: 22 det: 22
|
||||||
|
TMatrix[3, 3, system.int]
|
||||||
|
3
|
||||||
|
@[0.9, 0.1]
|
||||||
|
U[3]
|
||||||
|
U[(f: 3)]
|
||||||
|
U[[3]]
|
||||||
|
b()
|
||||||
|
@[1, 2]
|
||||||
|
@[3, 4]
|
||||||
|
1
|
||||||
|
concrete 88
|
||||||
|
123
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
!!Hi!!
|
||||||
|
G:0,1:0.1
|
||||||
|
G:0,1:0.1
|
||||||
|
H:1:0.1
|
||||||
|
'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
import macros, sequtils, sets, sugar, tables, typetraits
|
||||||
|
|
||||||
|
|
||||||
|
block t88:
|
||||||
|
type
|
||||||
|
BaseClass[V] = object of RootObj
|
||||||
|
b: V
|
||||||
|
|
||||||
|
proc new[V](t: typedesc[BaseClass], v: V): BaseClass[V] =
|
||||||
|
BaseClass[V](b: v)
|
||||||
|
|
||||||
|
proc baseMethod[V](v: BaseClass[V]): V = v.b
|
||||||
|
proc overriddenMethod[V](v: BaseClass[V]): V = v.baseMethod
|
||||||
|
|
||||||
|
type
|
||||||
|
ChildClass[V] = object of BaseClass[V]
|
||||||
|
c: V
|
||||||
|
|
||||||
|
proc new[V](t: typedesc[ChildClass], v1, v2: V): ChildClass[V] =
|
||||||
|
ChildClass[V](b: v1, c: v2)
|
||||||
|
|
||||||
|
proc overriddenMethod[V](v: ChildClass[V]): V = v.c
|
||||||
|
|
||||||
|
let c = ChildClass[string].new("Base", "Child")
|
||||||
|
|
||||||
|
assert c.baseMethod == "Base"
|
||||||
|
assert c.overriddenMethod == "Child"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t4528:
|
||||||
|
type GenericBase[T] = ref object of RootObj
|
||||||
|
type GenericSubclass[T] = ref object of GenericBase[T]
|
||||||
|
proc foo[T](g: GenericBase[T]) = discard
|
||||||
|
var bar: GenericSubclass[int]
|
||||||
|
foo(bar)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t1050_5597:
|
||||||
|
type ArrayType[T] = distinct T
|
||||||
|
|
||||||
|
proc arrayItem(a: ArrayType): auto =
|
||||||
|
static: echo(name(type(a).T))
|
||||||
|
result = (type(a).T)(4)
|
||||||
|
|
||||||
|
var arr: ArrayType[int]
|
||||||
|
echo arrayItem(arr)
|
||||||
|
|
||||||
|
# bug #5597
|
||||||
|
|
||||||
|
template fail() = "what"
|
||||||
|
|
||||||
|
proc g[T](x: var T) =
|
||||||
|
x.fail = 3
|
||||||
|
|
||||||
|
type
|
||||||
|
Obj = object
|
||||||
|
fail: int
|
||||||
|
|
||||||
|
var y: Obj
|
||||||
|
g y
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t1789:
|
||||||
|
type
|
||||||
|
Foo[N: static[int]] = object
|
||||||
|
|
||||||
|
proc bindStaticN[N](foo: Foo[N]) =
|
||||||
|
var ar0: array[3, int]
|
||||||
|
var ar1: array[N, int]
|
||||||
|
var ar2: array[1..N, int]
|
||||||
|
var ar3: array[0..(N+10), float]
|
||||||
|
echo N
|
||||||
|
|
||||||
|
var f: Foo[3]
|
||||||
|
f.bindStaticN
|
||||||
|
|
||||||
|
# case 2
|
||||||
|
|
||||||
|
type
|
||||||
|
ObjectWithStatic[X, Y: static[int], T] = object
|
||||||
|
bar: array[X * Y, T] # this one works
|
||||||
|
|
||||||
|
AliasWithStatic[X, Y: static[int], T] = array[X * Y, T]
|
||||||
|
|
||||||
|
var
|
||||||
|
x: ObjectWithStatic[1, 2, int]
|
||||||
|
y: AliasWithStatic[2, 3, int]
|
||||||
|
|
||||||
|
# case 3
|
||||||
|
|
||||||
|
type
|
||||||
|
Bar[N: static[int], T] = object
|
||||||
|
bar: array[N, T]
|
||||||
|
|
||||||
|
proc `[]`[N, T](f: Bar[N, T], n: range[0..(N - 1)]): T =
|
||||||
|
assert high(n) == N-1
|
||||||
|
result = f.bar[n]
|
||||||
|
|
||||||
|
var b: Bar[3, int]
|
||||||
|
doAssert b[2] == 0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t3977:
|
||||||
|
type Foo[N: static[int]] = object
|
||||||
|
|
||||||
|
proc foo[N](x: Foo[N]) =
|
||||||
|
let n = N
|
||||||
|
doAssert N == n
|
||||||
|
|
||||||
|
var f1: Foo[42]
|
||||||
|
f1.foo
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t5570:
|
||||||
|
type
|
||||||
|
BaseFruit[T] = object of RootObj
|
||||||
|
color: T
|
||||||
|
|
||||||
|
Banana[T] = object of BaseFruit[uint32]
|
||||||
|
weight: T
|
||||||
|
|
||||||
|
macro printTypeName(typ: typed): untyped =
|
||||||
|
echo "type ", getType(typ).repr
|
||||||
|
|
||||||
|
proc setColor[K](self: var BaseFruit[K], c: int) =
|
||||||
|
printTypeName(self.color)
|
||||||
|
self.color = uint32(c)
|
||||||
|
|
||||||
|
var x: Banana[float64]
|
||||||
|
x.weight = 17
|
||||||
|
printTypeName(x.color)
|
||||||
|
x.setColor(100)
|
||||||
|
echo x
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t5643:
|
||||||
|
type
|
||||||
|
Matrix[M, N: static[int], T: SomeFloat] = object
|
||||||
|
data: ref array[N * M, T]
|
||||||
|
Matrix64[M, N: static[int]] = Matrix[M, N, float64]
|
||||||
|
|
||||||
|
proc zeros64(M,N: static[int]): Matrix64[M,N] =
|
||||||
|
new result.data
|
||||||
|
for i in 0 ..< (M * N):
|
||||||
|
result.data[i] = 0'f64
|
||||||
|
|
||||||
|
proc bar[M,N: static[int], T](a: Matrix[M,N,T], b: Matrix[M,N,T]) =
|
||||||
|
discard
|
||||||
|
|
||||||
|
let a = zeros64(2,2)
|
||||||
|
bar(a,a)
|
||||||
|
# https://github.com/nim-lang/Nim/issues/5643
|
||||||
|
#
|
||||||
|
# The test case was failing here, because the compiler failed to
|
||||||
|
# detect the two matrix instantiations as the same type.
|
||||||
|
#
|
||||||
|
# The root cause was that the `T` type variable is a different
|
||||||
|
# type after the first Matrix type has been matched.
|
||||||
|
#
|
||||||
|
# Sigmatch was failing to match the second version of `T`, but
|
||||||
|
# due to some complex interplay between tyOr, tyTypeDesc and
|
||||||
|
# tyGenericParam this was allowed to went through. The generic
|
||||||
|
# instantiation of the second matrix was incomplete and the
|
||||||
|
# generic cache lookup failed, producing two separate types.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t5683:
|
||||||
|
type Matrix[M,N: static[int]] = array[M, array[N, float]]
|
||||||
|
|
||||||
|
proc det[M,N](a: Matrix[M,N]): int = N*10 + M
|
||||||
|
proc perm[M,N](a: Matrix[M,N]): int = M*10 + N
|
||||||
|
|
||||||
|
const
|
||||||
|
a = [ [1.0, 2.0]
|
||||||
|
, [3.0, 4.0]
|
||||||
|
]
|
||||||
|
|
||||||
|
echo "perm: ", a.perm, " det: ", a.det
|
||||||
|
|
||||||
|
# This tests multiple instantiations of a generic
|
||||||
|
# proc involving static params:
|
||||||
|
type
|
||||||
|
Vector64[N: static[int]] = ref array[N, float64]
|
||||||
|
Array64[N: static[int]] = array[N, float64]
|
||||||
|
|
||||||
|
proc vector[N: static[int]](xs: Array64[N]): Vector64[N] =
|
||||||
|
new result
|
||||||
|
for i in 0 ..< N:
|
||||||
|
result[i] = xs[i]
|
||||||
|
|
||||||
|
let v1 = vector([1.0, 2.0, 3.0, 4.0, 5.0])
|
||||||
|
let v2 = vector([1.0, 2.0, 3.0, 4.0, 5.0])
|
||||||
|
let v3 = vector([1.0, 2.0, 3.0, 4.0])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t7794:
|
||||||
|
type
|
||||||
|
Data[T:SomeNumber, U:SomeFloat] = ref object
|
||||||
|
x: T
|
||||||
|
value*: U
|
||||||
|
|
||||||
|
var d = Data[int, float64](x:10.int, value:2'f64)
|
||||||
|
doAssert d.x == 10
|
||||||
|
doAssert d.value == 2.0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t8403:
|
||||||
|
proc sum[T](s: seq[T], R: typedesc): R =
|
||||||
|
var sum: R = 0
|
||||||
|
for x in s:
|
||||||
|
sum += R(x)
|
||||||
|
return sum
|
||||||
|
|
||||||
|
doAssert @[1, 2, 3].sum(float) == 6.0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t8439:
|
||||||
|
type
|
||||||
|
Cardinal = enum
|
||||||
|
north, east, south, west
|
||||||
|
|
||||||
|
proc foo[cardinal: static[Cardinal]](): int = 1
|
||||||
|
doAssert foo[north]() == 1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t8694:
|
||||||
|
when true:
|
||||||
|
# Error: undeclared identifier: '|'
|
||||||
|
proc bar[T](t:T): bool =
|
||||||
|
runnableExamples:
|
||||||
|
type Foo = int | float
|
||||||
|
true
|
||||||
|
doAssert bar(0)
|
||||||
|
|
||||||
|
when true:
|
||||||
|
# ok
|
||||||
|
proc bar(t:int): bool =
|
||||||
|
runnableExamples:
|
||||||
|
type Foo = int | float
|
||||||
|
true
|
||||||
|
doAssert bar(0)
|
||||||
|
|
||||||
|
when true:
|
||||||
|
# Error: undeclared identifier: '|'
|
||||||
|
proc bar(t:typedesc): bool =
|
||||||
|
runnableExamples:
|
||||||
|
type Foo = int | float
|
||||||
|
true
|
||||||
|
doAssert bar(int)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t9130:
|
||||||
|
when true:
|
||||||
|
# stack overflow
|
||||||
|
template baz1(iter: untyped): untyped =
|
||||||
|
runnableExamples:
|
||||||
|
import sugar
|
||||||
|
proc fun(a: proc(x:int): int) = discard
|
||||||
|
baz1(fun(x:int => x))
|
||||||
|
discard
|
||||||
|
|
||||||
|
proc foo1[A](ts: A) =
|
||||||
|
baz1(ts)
|
||||||
|
|
||||||
|
when true:
|
||||||
|
# ok
|
||||||
|
template baz2(iter: untyped): untyped =
|
||||||
|
runnableExamples:
|
||||||
|
import sugar
|
||||||
|
proc fun(a: proc(x:int): int) = discard
|
||||||
|
baz2(fun(x:int => x))
|
||||||
|
discard
|
||||||
|
|
||||||
|
proc foo2(ts: int) =
|
||||||
|
baz2(ts)
|
||||||
|
|
||||||
|
when true:
|
||||||
|
# stack overflow
|
||||||
|
template baz3(iter: untyped): untyped =
|
||||||
|
runnableExamples:
|
||||||
|
baz3(fun(x:int => x))
|
||||||
|
discard
|
||||||
|
|
||||||
|
proc foo3[A](ts: A) =
|
||||||
|
baz3(ts)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t1056:
|
||||||
|
type
|
||||||
|
TMatrix[N,M: static[int], T] = object
|
||||||
|
data: array[0..N*M-1, T]
|
||||||
|
|
||||||
|
TMat2[T] = TMatrix[2,2,T]
|
||||||
|
|
||||||
|
proc echoMatrix(a: TMatrix) =
|
||||||
|
echo a.type.name
|
||||||
|
echo TMatrix.N
|
||||||
|
|
||||||
|
proc echoMat2(a: TMat2) =
|
||||||
|
echo TMat2.M
|
||||||
|
|
||||||
|
var m = TMatrix[3,3,int](data: [1,2,3,4,5,6,7,8,9])
|
||||||
|
|
||||||
|
echoMatrix m
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t4884:
|
||||||
|
type
|
||||||
|
Vec[N: static[int], T] = object
|
||||||
|
arr*: array[N, T]
|
||||||
|
|
||||||
|
Mat[N,M: static[int], T] = object
|
||||||
|
arr: array[N, Vec[M,T]]
|
||||||
|
|
||||||
|
var m : Mat[3,3,float]
|
||||||
|
var strMat : Mat[m.N, m.M, string]
|
||||||
|
var lenMat : Mat[m.N, m.M, int]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t2221:
|
||||||
|
var tblo: TableRef[string, int]
|
||||||
|
doAssert tblo == nil
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t2304:
|
||||||
|
type TV2[T:SomeNumber] = array[0..1, T]
|
||||||
|
proc newV2T[T](x, y: T=0): TV2[T] = [x, y]
|
||||||
|
|
||||||
|
let x = newV2T[float](0.9, 0.1)
|
||||||
|
echo(@x)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t2752:
|
||||||
|
proc myFilter[T](it: (iterator(): T), f: (proc(anything: T):bool)): (iterator(): T) =
|
||||||
|
iterator aNameWhichWillConflict(): T {.closure.}=
|
||||||
|
for x in it():
|
||||||
|
if f(x):
|
||||||
|
yield x
|
||||||
|
result = aNameWhichWillConflict
|
||||||
|
|
||||||
|
iterator testIt():int {.closure.}=
|
||||||
|
yield -1
|
||||||
|
yield 2
|
||||||
|
|
||||||
|
#let unusedVariable = myFilter(testIt, (x: int) => x > 0)
|
||||||
|
|
||||||
|
proc onlyPos(it: (iterator(): int)): (iterator(): int)=
|
||||||
|
iterator aNameWhichWillConflict(): int {.closure.}=
|
||||||
|
var filtered = onlyPos(myFilter(it, (x:int) => x > 0))
|
||||||
|
for x in filtered():
|
||||||
|
yield x
|
||||||
|
result = aNameWhichWillConflict
|
||||||
|
|
||||||
|
let x = onlyPos(testIt)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t5106:
|
||||||
|
block:
|
||||||
|
type T = distinct int
|
||||||
|
|
||||||
|
proc `+`(a, b: T): T =
|
||||||
|
T(int(a) + int(b))
|
||||||
|
|
||||||
|
type U[F: static[T]] = distinct int
|
||||||
|
|
||||||
|
proc `+`[P1, P2: static[T]](a: U[P1], b: U[P2]): U[P1 + P2] =
|
||||||
|
U[P1 + P2](int(a) + int(b))
|
||||||
|
|
||||||
|
var a = U[T(1)](1)
|
||||||
|
var b = U[T(2)](2)
|
||||||
|
var c = a + b
|
||||||
|
echo c.type.name
|
||||||
|
|
||||||
|
block:
|
||||||
|
type T = object
|
||||||
|
f: int
|
||||||
|
|
||||||
|
proc `+`(a, b: T): T =
|
||||||
|
T(f: a.f + b.f)
|
||||||
|
|
||||||
|
type U[F: static[T]] = distinct int
|
||||||
|
|
||||||
|
proc `+`[P1, P2: static[T]](a: U[P1], b: U[P2]): U[P1 + P2] =
|
||||||
|
U[P1 + P2](int(a) + int(b))
|
||||||
|
|
||||||
|
var a = U[T(f: 1)](1)
|
||||||
|
var b = U[T(f: 2)](2)
|
||||||
|
var c = a + b
|
||||||
|
echo c.type.name
|
||||||
|
|
||||||
|
block:
|
||||||
|
type T = distinct array[0..0, int]
|
||||||
|
|
||||||
|
proc `+`(a, b: T): T =
|
||||||
|
T([array[0..0, int](a)[0] + array[0..0, int](b)[0]])
|
||||||
|
|
||||||
|
type U[F: static[T]] = distinct int
|
||||||
|
|
||||||
|
proc `+`[P1, P2: static[T]](a: U[P1], b: U[P2]): U[P1 + P2] =
|
||||||
|
U[P1 + P2](int(a) + int(b))
|
||||||
|
|
||||||
|
var a = U[T([1])](1)
|
||||||
|
var b = U[T([2])](2)
|
||||||
|
var c = a + b
|
||||||
|
echo c.type.name
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t3055:
|
||||||
|
proc b(t: int | string)
|
||||||
|
proc a(t: int) = b(t)
|
||||||
|
proc b(t: int | string) = echo "b()"
|
||||||
|
a(1)
|
||||||
|
|
||||||
|
# test recursive generics still work:
|
||||||
|
proc fac[T](x: T): T =
|
||||||
|
if x == 0: return 1
|
||||||
|
else: return fac(x-1)*x
|
||||||
|
|
||||||
|
doAssert fac(6) == 720
|
||||||
|
doAssert fac(5.0) == 120.0
|
||||||
|
|
||||||
|
|
||||||
|
# test recursive generic with forwarding:
|
||||||
|
proc fac2[T](x: T): T
|
||||||
|
|
||||||
|
doAssert fac2(6) == 720
|
||||||
|
doAssert fac2(5.0) == 120.0
|
||||||
|
|
||||||
|
proc fac2[T](x: T): T =
|
||||||
|
if x == 0: return 1
|
||||||
|
else: return fac2(x-1)*x
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t1187:
|
||||||
|
type
|
||||||
|
TEventArgs = object
|
||||||
|
skip: bool
|
||||||
|
TEventHandler[T] = proc (e: var TEventArgs, data: T) {.closure.}
|
||||||
|
TEvent[T] = object
|
||||||
|
#handlers: seq[TEventHandler[T]] # Does not work
|
||||||
|
handlers: seq[proc (e: var TEventArgs, d: T) {.closure.}] # works
|
||||||
|
|
||||||
|
TData = object
|
||||||
|
x: int
|
||||||
|
|
||||||
|
TSomething = object
|
||||||
|
s: TEvent[TData]
|
||||||
|
|
||||||
|
proc init[T](e: var TEvent[T]) =
|
||||||
|
e.handlers.newSeq(0)
|
||||||
|
|
||||||
|
#proc add*[T](e: var TEvent[T], h: proc (e: var TEventArgs, data: T) {.closure.}) =
|
||||||
|
# this line works
|
||||||
|
proc add[T](e: var TEvent[T], h: TEventHandler[T]) =
|
||||||
|
# this line does not work
|
||||||
|
e.handlers.add(h)
|
||||||
|
|
||||||
|
proc main () =
|
||||||
|
var something: TSomething
|
||||||
|
something.s.init()
|
||||||
|
var fromOutside = 4711
|
||||||
|
|
||||||
|
something.s.add() do (e: var TEventArgs, data: TData):
|
||||||
|
var x = data.x
|
||||||
|
x = fromOutside
|
||||||
|
|
||||||
|
main()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t1919:
|
||||||
|
type
|
||||||
|
Base[M] = object of RootObj
|
||||||
|
a : M
|
||||||
|
Sub1[M] = object of Base[M]
|
||||||
|
b : int
|
||||||
|
Sub2[M] = object of Sub1[M]
|
||||||
|
c : int
|
||||||
|
|
||||||
|
var x: Sub2[float]
|
||||||
|
doAssert x.a == 0.0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t5756:
|
||||||
|
type
|
||||||
|
Vec[N : static[int]] = object
|
||||||
|
x: int
|
||||||
|
arr: array[N, int32]
|
||||||
|
|
||||||
|
Mat[M,N: static[int]] = object
|
||||||
|
x: int
|
||||||
|
arr: array[M, Vec[N]]
|
||||||
|
|
||||||
|
proc vec2(x,y:int32) : Vec[2] =
|
||||||
|
result.arr = [x,y]
|
||||||
|
result.x = 10
|
||||||
|
|
||||||
|
proc mat2(a,b: Vec[2]): Mat[2,2] =
|
||||||
|
result.arr = [a,b]
|
||||||
|
result.x = 20
|
||||||
|
|
||||||
|
const M = mat2(vec2(1, 2), vec2(3, 4))
|
||||||
|
|
||||||
|
let m1 = M
|
||||||
|
echo @(m1.arr[0].arr)
|
||||||
|
echo @(m1.arr[1].arr)
|
||||||
|
|
||||||
|
proc foo =
|
||||||
|
let m2 = M
|
||||||
|
echo m1.arr[0].arr[0]
|
||||||
|
|
||||||
|
foo()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t7854:
|
||||||
|
type
|
||||||
|
Stream = ref StreamObj
|
||||||
|
StreamObj = object of RootObj
|
||||||
|
|
||||||
|
InhStream = ref InhStreamObj
|
||||||
|
InhStreamObj = object of Stream
|
||||||
|
f: string
|
||||||
|
|
||||||
|
proc newInhStream(f: string): InhStream =
|
||||||
|
new(result)
|
||||||
|
result.f = f
|
||||||
|
|
||||||
|
var val: int
|
||||||
|
let str = newInhStream("input_file.json")
|
||||||
|
|
||||||
|
block:
|
||||||
|
# works:
|
||||||
|
proc load[T](data: var T, s: Stream) =
|
||||||
|
discard
|
||||||
|
load(val, str)
|
||||||
|
|
||||||
|
block:
|
||||||
|
# works
|
||||||
|
proc load[T](s: Stream, data: T) =
|
||||||
|
discard
|
||||||
|
load(str, val)
|
||||||
|
|
||||||
|
block:
|
||||||
|
# broken
|
||||||
|
proc load[T](s: Stream, data: var T) =
|
||||||
|
discard
|
||||||
|
load(str, val)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t5864:
|
||||||
|
proc defaultStatic(s: openarray, N: static[int] = 1): int = N
|
||||||
|
proc defaultGeneric[T](a: T = 2): int = a
|
||||||
|
|
||||||
|
let a = [1, 2, 3, 4].defaultStatic()
|
||||||
|
let b = defaultGeneric()
|
||||||
|
|
||||||
|
doAssert a == 1
|
||||||
|
doAssert b == 2
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t3498:
|
||||||
|
template defaultOf[T](t: T): untyped = (var d: T; d)
|
||||||
|
|
||||||
|
doAssert defaultOf(1) == 0
|
||||||
|
|
||||||
|
# assignment using template
|
||||||
|
|
||||||
|
template tassign[T](x: var seq[T]) =
|
||||||
|
x = @[1, 2, 3]
|
||||||
|
|
||||||
|
var y: seq[int]
|
||||||
|
tassign(y) #<- x is expected = @[1, 2, 3]
|
||||||
|
tassign(y)
|
||||||
|
|
||||||
|
doAssert y[0] == 1
|
||||||
|
doAssert y[1] == 2
|
||||||
|
doAssert y[2] == 3
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t3499:
|
||||||
|
proc foo[T](x: proc(): T) =
|
||||||
|
echo "generic ", x()
|
||||||
|
|
||||||
|
proc foo(x: proc(): int) =
|
||||||
|
echo "concrete ", x()
|
||||||
|
|
||||||
|
# note the following 'proc' is not .closure!
|
||||||
|
foo(proc (): auto {.nimcall.} = 88)
|
||||||
|
|
||||||
|
# bug #3499 last snippet fixed
|
||||||
|
# bug 705 last snippet fixed
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t797:
|
||||||
|
proc foo[T](s:T):string = $s
|
||||||
|
|
||||||
|
type IntStringProc = proc(x: int): string
|
||||||
|
|
||||||
|
var f1 = IntStringProc(foo)
|
||||||
|
var f2: proc(x: int): string = foo
|
||||||
|
var f3: IntStringProc = foo
|
||||||
|
|
||||||
|
echo f1(1), f2(2), f3(3)
|
||||||
|
|
||||||
|
for x in map([1,2,3], foo): echo x
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t4658:
|
||||||
|
var x = 123
|
||||||
|
proc twice[T](f: T -> T): T -> T = (x: T) => f(f(x))
|
||||||
|
proc quote(s: string): string = "!" & s & "!"
|
||||||
|
echo twice(quote)("Hi")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t4589:
|
||||||
|
type SimpleTable[TKey, TVal] = TableRef[TKey, TVal]
|
||||||
|
template newSimpleTable(TKey, TVal: typedesc): SimpleTable[TKey, TVal] = newTable[TKey, TVal]()
|
||||||
|
var fontCache : SimpleTable[string, SimpleTable[int32, int]]
|
||||||
|
fontCache = newSimpleTable(string, SimpleTable[int32, int])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t4600:
|
||||||
|
template foo(x: untyped): untyped = echo 1
|
||||||
|
template foo(x,y: untyped): untyped = echo 2
|
||||||
|
|
||||||
|
proc bar1[T](x: T) = foo(x)
|
||||||
|
proc bar2(x: float) = foo(x,x)
|
||||||
|
proc bar3[T](x: T) = foo(x,x)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t4672:
|
||||||
|
type
|
||||||
|
EnumContainer[T: enum] = object
|
||||||
|
v: T
|
||||||
|
SomeEnum {.pure.} = enum
|
||||||
|
A,B,C
|
||||||
|
|
||||||
|
proc value[T: enum](this: EnumContainer[T]): T =
|
||||||
|
this.v
|
||||||
|
|
||||||
|
var enumContainer: EnumContainer[SomeEnum]
|
||||||
|
discard enumContainer.value()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t4863:
|
||||||
|
type
|
||||||
|
G[i,j: static[int]] = object
|
||||||
|
v:float
|
||||||
|
H[j: static[int]] = G[0,j]
|
||||||
|
proc p[i,j: static[int]](x:G[i,j]) = echo "G:", i, ",", j, ":", x.v
|
||||||
|
proc q[j: static[int]](x:H[j]) = echo "H:", j, ":", x.v
|
||||||
|
|
||||||
|
var
|
||||||
|
g0 = G[0,1](v: 0.1)
|
||||||
|
h0:H[1] = g0
|
||||||
|
p(g0)
|
||||||
|
p(h0)
|
||||||
|
q(h0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t1684:
|
||||||
|
type
|
||||||
|
BaseType {.inheritable pure.} = object
|
||||||
|
idx: int
|
||||||
|
|
||||||
|
DerivedType {.final pure.} = object of BaseType
|
||||||
|
|
||||||
|
proc index[Toohoo: BaseType](h: Toohoo): int {.inline.} = h.idx
|
||||||
|
proc newDerived(idx: int): DerivedType {.inline.} = DerivedType(idx: idx)
|
||||||
|
|
||||||
|
let d = newDerived(2)
|
||||||
|
assert(d.index == 2)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t5632:
|
||||||
|
type Option[T] = object
|
||||||
|
|
||||||
|
proc point[A](v: A, t: typedesc[Option[A]]): Option[A] =
|
||||||
|
discard
|
||||||
|
|
||||||
|
discard point(1, Option)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t7247:
|
||||||
|
type n8 = range[0'i8..127'i8]
|
||||||
|
var tab = initSet[n8]()
|
||||||
|
doAssert tab.contains(8) == false
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t3717:
|
||||||
|
type
|
||||||
|
Foo[T] = object
|
||||||
|
a: T
|
||||||
|
Foo1[T] = Foo[T] | int
|
||||||
|
|
||||||
|
proc foo[T](s: Foo1[Foo[T]]): T =
|
||||||
|
5
|
||||||
|
|
||||||
|
var f: Foo[Foo[int]]
|
||||||
|
discard foo(f)
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
discard """
|
|
||||||
output: '''!!Hi!!'''
|
|
||||||
"""
|
|
||||||
# bug #4658
|
|
||||||
import future
|
|
||||||
|
|
||||||
var x = 123
|
|
||||||
|
|
||||||
proc twice[T](f: T -> T): T -> T = (x: T) => f(f(x))
|
|
||||||
|
|
||||||
proc quote(s: string): string = "!" & s & "!"
|
|
||||||
|
|
||||||
echo twice(quote)("Hi")
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
import future, sequtils
|
|
||||||
|
|
||||||
let x = map(@[1, 2, 3], x => x+10)
|
|
||||||
assert x == @[11, 12, 13]
|
|
||||||
|
|
||||||
let y = map(@[(1,"a"), (2,"b"), (3,"c")], x => $x[0] & x[1])
|
|
||||||
assert y == @["1a", "2b", "3c"]
|
|
||||||
|
|
||||||
proc eatsTwoArgProc[T,S,U](a: T, b: S, f: proc(t: T, s: S): U): U =
|
|
||||||
f(a,b)
|
|
||||||
|
|
||||||
let z = eatsTwoArgProc(1, "a", (t,s) => $t & s)
|
|
||||||
assert z == "1a"
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
|
|
||||||
# bug #1965
|
|
||||||
|
|
||||||
import mmodule_same_as_proc
|
|
||||||
|
|
||||||
proc test[T](t: T) =
|
|
||||||
mmodule_same_as_proc"a"
|
|
||||||
|
|
||||||
test(0)
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
discard """
|
|
||||||
output: '''OK'''
|
|
||||||
"""
|
|
||||||
#bug #5632
|
|
||||||
type
|
|
||||||
Option*[T] = object
|
|
||||||
|
|
||||||
proc point*[A](v: A, t: typedesc[Option[A]]): Option[A] =
|
|
||||||
discard
|
|
||||||
|
|
||||||
discard point(1, Option)
|
|
||||||
echo "OK"
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
|
|
||||||
import asyncdispatch
|
|
||||||
|
|
||||||
type
|
|
||||||
Callback = proc() {.closure, gcsafe.}
|
|
||||||
GameState = ref object
|
|
||||||
playerChangeHandlers: seq[Callback]
|
|
||||||
|
|
||||||
#proc dummy() =
|
|
||||||
# var x = newSeq[proc() {.cdecl, gcsafe.}]()
|
|
||||||
|
|
||||||
proc newGameState(): GameState =
|
|
||||||
result = GameState(
|
|
||||||
playerChangeHandlers: newSeq[Callback]() # this fails
|
|
||||||
)
|
|
||||||
|
|
||||||
#dummy()
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
type NSPasteboardItem* = ptr object
|
|
||||||
type NSPasteboard* = ptr object
|
|
||||||
type NSArrayAbstract = ptr object {.inheritable.}
|
|
||||||
type NSMutableArrayAbstract = ptr object of NSArrayAbstract
|
|
||||||
type NSArray*[T] = ptr object of NSArrayAbstract
|
|
||||||
type NSMutableArray*[T] = ptr object of NSArray[T]
|
|
||||||
|
|
||||||
proc newMutableArrayAbstract*(): NSMutableArrayAbstract = discard
|
|
||||||
|
|
||||||
template newMutableArray*(T: typedesc): NSMutableArray[T] =
|
|
||||||
cast[NSMutableArray[T]](newMutableArrayAbstract())
|
|
||||||
|
|
||||||
proc writeObjects*(p: NSPasteboard, o: NSArray[NSPasteboardItem]) = discard
|
|
||||||
|
|
||||||
let a = newMutableArray NSPasteboardItem
|
|
||||||
var x: NSMutableArray[NSPasteboardItem]
|
|
||||||
var y: NSArray[NSPasteboardItem] = x
|
|
||||||
|
|
||||||
writeObjects(nil, a)
|
|
||||||
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
type
|
|
||||||
Vec3[T] = array[3, T]
|
|
||||||
|
|
||||||
proc foo(x: Vec3, y: Vec3.T, z: x.T): x.type.T =
|
|
||||||
return 10
|
|
||||||
|
|
||||||
var y: Vec3[int] = [1, 2, 3]
|
|
||||||
var z: int = foo(y, 3, 4)
|
|
||||||
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
discard """
|
|
||||||
output: '''false'''
|
|
||||||
"""
|
|
||||||
|
|
||||||
when false:
|
|
||||||
import typetraits
|
|
||||||
|
|
||||||
proc `@`[T: SomeInteger](x, y: T): T = x
|
|
||||||
|
|
||||||
echo(type(5'i64 @ 6'i32))
|
|
||||||
|
|
||||||
echo(type(5'i32 @ 6'i64))
|
|
||||||
|
|
||||||
import sets
|
|
||||||
# bug #7247
|
|
||||||
type
|
|
||||||
n8 = range[0'i8..127'i8]
|
|
||||||
|
|
||||||
var tab = initSet[n8]()
|
|
||||||
|
|
||||||
echo tab.contains(8)
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
##
|
|
||||||
## specialised_is_equivalent Nim Module
|
|
||||||
##
|
|
||||||
## Created by Eric Doughty-Papassideris on 2011-02-16.
|
|
||||||
|
|
||||||
type
|
|
||||||
TGen[T] = tuple[a: T]
|
|
||||||
TSpef = tuple[a: string]
|
|
||||||
|
|
||||||
var
|
|
||||||
a: TGen[string]
|
|
||||||
b: TSpef
|
|
||||||
a = b
|
|
||||||
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
discard """
|
|
||||||
output: '''concrete 88'''
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Another regression triggered by changed closure computations:
|
|
||||||
|
|
||||||
proc foo[T](x: proc(): T) =
|
|
||||||
echo "generic ", x()
|
|
||||||
|
|
||||||
proc foo(x: proc(): int) =
|
|
||||||
echo "concrete ", x()
|
|
||||||
|
|
||||||
# note the following 'proc' is not .closure!
|
|
||||||
foo(proc (): auto {.nimcall.} = 88)
|
|
||||||
|
|
||||||
# bug #3499 last snippet fixed
|
|
||||||
# bug 705 last snippet fixed
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
discard """
|
|
||||||
output: '''G:0,1:0.1
|
|
||||||
G:0,1:0.1
|
|
||||||
H:1:0.1'''
|
|
||||||
"""
|
|
||||||
|
|
||||||
type
|
|
||||||
G[i,j:static[int]] = object
|
|
||||||
v:float
|
|
||||||
H[j:static[int]] = G[0,j]
|
|
||||||
proc p[i,j:static[int]](x:G[i,j]) = echo "G:",i,",",j,":",x.v
|
|
||||||
proc q[j:static[int]](x:H[j]) = echo "H:",j,":",x.v
|
|
||||||
|
|
||||||
var
|
|
||||||
g0 = G[0,1](v: 0.1)
|
|
||||||
h0:H[1] = g0
|
|
||||||
p(g0)
|
|
||||||
p(h0)
|
|
||||||
q(h0)
|
|
||||||
# bug #4863
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
|
|
||||||
# bug #1684
|
|
||||||
type
|
|
||||||
BaseType {.inheritable pure.} = object
|
|
||||||
idx: int
|
|
||||||
|
|
||||||
DerivedType* {.final pure.} = object of BaseType
|
|
||||||
|
|
||||||
proc index*[Toohoo: BaseType](h: Toohoo): int {.inline.} = h.idx
|
|
||||||
proc newDerived(idx: int): DerivedType {.inline.} = DerivedType(idx: idx)
|
|
||||||
|
|
||||||
let d = newDerived(2)
|
|
||||||
assert(d.index == 2)
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
# bug #4589
|
|
||||||
|
|
||||||
import tables
|
|
||||||
type SimpleTable*[TKey, TVal] = TableRef[TKey, TVal]
|
|
||||||
template newSimpleTable*(TKey, TVal: typedesc): SimpleTable[TKey, TVal] = newTable[TKey, TVal]()
|
|
||||||
var fontCache : SimpleTable[string, SimpleTable[int32, int]]
|
|
||||||
fontCache = newSimpleTable(string, SimpleTable[int32, int])
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
|
|
||||||
# bug #4600
|
|
||||||
template foo(x: untyped): untyped = echo 1
|
|
||||||
template foo(x,y: untyped): untyped = echo 2
|
|
||||||
|
|
||||||
proc bar1[T](x: T) = foo(x)
|
|
||||||
proc bar2(x: float) = foo(x,x)
|
|
||||||
proc bar3[T](x: T) = foo(x,x)
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
# bug #4672
|
|
||||||
type
|
|
||||||
EnumContainer[T: enum] = object
|
|
||||||
v: T
|
|
||||||
SomeEnum {.pure.} = enum
|
|
||||||
A,B,C
|
|
||||||
|
|
||||||
proc value[T: enum](this: EnumContainer[T]): T =
|
|
||||||
this.v
|
|
||||||
|
|
||||||
var enumContainer: EnumContainer[SomeEnum]
|
|
||||||
discard enumContainer.value()
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
discard """
|
|
||||||
output: "direct\ngeneric\ngeneric"
|
|
||||||
"""
|
|
||||||
|
|
||||||
proc withDirectType(args: string) =
|
|
||||||
echo "direct"
|
|
||||||
|
|
||||||
proc withDirectType[T](arg: T) =
|
|
||||||
echo "generic"
|
|
||||||
|
|
||||||
proc withOpenArray(args: openarray[string]) =
|
|
||||||
echo "openarray"
|
|
||||||
|
|
||||||
proc withOpenArray[T](arg: T) =
|
|
||||||
echo "generic"
|
|
||||||
|
|
||||||
proc withVarargs(args: varargs[string]) =
|
|
||||||
echo "varargs"
|
|
||||||
|
|
||||||
proc withVarargs[T](arg: T) =
|
|
||||||
echo "generic"
|
|
||||||
|
|
||||||
withDirectType "string"
|
|
||||||
withOpenArray "string"
|
|
||||||
withVarargs "string"
|
|
||||||
|
|
||||||
245
tests/generics/tvarious.nim
Normal file
245
tests/generics/tvarious.nim
Normal file
|
|
@ -0,0 +1,245 @@
|
||||||
|
discard """
|
||||||
|
output: '''
|
||||||
|
we
|
||||||
|
direct
|
||||||
|
generic
|
||||||
|
generic
|
||||||
|
'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
import algorithm, sugar, sequtils, typetraits, asyncdispatch
|
||||||
|
|
||||||
|
|
||||||
|
block tconfusing_arrow:
|
||||||
|
type Deck = object
|
||||||
|
value: int
|
||||||
|
|
||||||
|
proc sort(h: var seq[Deck]) =
|
||||||
|
# works:
|
||||||
|
h.sort(proc (x, y: Deck): auto =
|
||||||
|
cmp(x.value, y.value))
|
||||||
|
# fails:
|
||||||
|
h.sort((x, y: Deck) => cmp(ord(x.value), ord(y.value)))
|
||||||
|
|
||||||
|
var player: seq[Deck] = @[]
|
||||||
|
player.sort()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block tdictdestruct:
|
||||||
|
type
|
||||||
|
TDict[TK, TV] = object
|
||||||
|
k: TK
|
||||||
|
v: TV
|
||||||
|
PDict[TK, TV] = ref TDict[TK, TV]
|
||||||
|
|
||||||
|
proc fakeNew[T](x: var ref T, destroy: proc (a: ref T) {.nimcall.}) =
|
||||||
|
discard
|
||||||
|
|
||||||
|
proc destroyDict[TK, TV](a: PDict[TK, TV]) =
|
||||||
|
return
|
||||||
|
proc newDict[TK, TV](a: TK, b: TV): PDict[TK, TV] =
|
||||||
|
fakeNew(result, destroyDict[TK, TV])
|
||||||
|
|
||||||
|
# Problem: destroyDict is not instantiated when newDict is instantiated!
|
||||||
|
discard newDict("a", "b")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block tgenericdefaults:
|
||||||
|
type
|
||||||
|
TFoo[T, U, R = int] = object
|
||||||
|
x: T
|
||||||
|
y: U
|
||||||
|
z: R
|
||||||
|
|
||||||
|
TBar[T] = TFoo[T, array[4, T], T]
|
||||||
|
|
||||||
|
var x1: TFoo[int, float]
|
||||||
|
|
||||||
|
static:
|
||||||
|
assert type(x1.x) is int
|
||||||
|
assert type(x1.y) is float
|
||||||
|
assert type(x1.z) is int
|
||||||
|
|
||||||
|
var x2: TFoo[string, R = float, U = seq[int]]
|
||||||
|
|
||||||
|
static:
|
||||||
|
assert type(x2.x) is string
|
||||||
|
assert type(x2.y) is seq[int]
|
||||||
|
assert type(x2.z) is float
|
||||||
|
|
||||||
|
var x3: TBar[float]
|
||||||
|
|
||||||
|
static:
|
||||||
|
assert type(x3.x) is float
|
||||||
|
assert type(x3.y) is array[4, float]
|
||||||
|
assert type(x3.z) is float
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block tprop:
|
||||||
|
type
|
||||||
|
TProperty[T] = object of RootObj
|
||||||
|
getProc: proc(property: TProperty[T]): T {.nimcall.}
|
||||||
|
setProc: proc(property: TProperty[T], value: T) {.nimcall.}
|
||||||
|
value: T
|
||||||
|
|
||||||
|
proc newProperty[T](value: RootObj): TProperty[T] =
|
||||||
|
result.getProc = proc (property: TProperty[T]) =
|
||||||
|
return property.value
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block trefs:
|
||||||
|
type
|
||||||
|
PA[T] = ref TA[T]
|
||||||
|
TA[T] = object
|
||||||
|
field: T
|
||||||
|
var a: PA[string]
|
||||||
|
new(a)
|
||||||
|
a.field = "some string"
|
||||||
|
|
||||||
|
proc someOther[T](len: string): seq[T] = discard
|
||||||
|
proc someOther[T](len: int): seq[T] = echo "we"
|
||||||
|
|
||||||
|
proc foo[T](x: T) =
|
||||||
|
var s = someOther[T](34)
|
||||||
|
#newSeq[T](34)
|
||||||
|
|
||||||
|
foo 23
|
||||||
|
|
||||||
|
when false:
|
||||||
|
# Compiles unless you use var a: PA[string]
|
||||||
|
type
|
||||||
|
PA = ref TA
|
||||||
|
TA[T] = object
|
||||||
|
|
||||||
|
# Cannot instantiate:
|
||||||
|
type
|
||||||
|
TA[T] = object
|
||||||
|
a: PA[T]
|
||||||
|
PA[T] = ref TA[T]
|
||||||
|
|
||||||
|
type
|
||||||
|
PA[T] = ref TA[T]
|
||||||
|
TA[T] = object
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block tsharedcases:
|
||||||
|
proc typeNameLen(x: typedesc): int {.compileTime.} =
|
||||||
|
result = x.name.len
|
||||||
|
macro selectType(a, b: typedesc): typedesc =
|
||||||
|
result = a
|
||||||
|
|
||||||
|
type
|
||||||
|
Foo[T] = object
|
||||||
|
data1: array[T.high, int]
|
||||||
|
data2: array[typeNameLen(T), float]
|
||||||
|
data3: array[0..T.typeNameLen, selectType(float, int)]
|
||||||
|
MyEnum = enum A, B, C, D
|
||||||
|
|
||||||
|
var f1: Foo[MyEnum]
|
||||||
|
var f2: Foo[int8]
|
||||||
|
|
||||||
|
doAssert high(f1.data1) == 2 # (D = 3) - 1 == 2
|
||||||
|
doAssert high(f1.data2) == 5 # (MyEnum.len = 6) - 1 == 5
|
||||||
|
|
||||||
|
doAssert high(f2.data1) == 126 # 127 - 1 == 126
|
||||||
|
doAssert high(f2.data2) == 3 # int8.len - 1 == 3
|
||||||
|
|
||||||
|
static:
|
||||||
|
assert high(f1.data1) == ord(C)
|
||||||
|
assert high(f1.data2) == 5 # length of MyEnum minus one, because we used T.high
|
||||||
|
|
||||||
|
assert high(f2.data1) == 126
|
||||||
|
assert high(f2.data2) == 3
|
||||||
|
|
||||||
|
assert high(f1.data3) == 6 # length of MyEnum
|
||||||
|
assert high(f2.data3) == 4 # length of int8
|
||||||
|
|
||||||
|
assert f2.data3[0] is float
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block tmap_auto:
|
||||||
|
let x = map(@[1, 2, 3], x => x+10)
|
||||||
|
assert x == @[11, 12, 13]
|
||||||
|
|
||||||
|
let y = map(@[(1,"a"), (2,"b"), (3,"c")], x => $x[0] & x[1])
|
||||||
|
assert y == @["1a", "2b", "3c"]
|
||||||
|
|
||||||
|
proc eatsTwoArgProc[T,S,U](a: T, b: S, f: proc(t: T, s: S): U): U =
|
||||||
|
f(a,b)
|
||||||
|
|
||||||
|
let z = eatsTwoArgProc(1, "a", (t,s) => $t & s)
|
||||||
|
assert z == "1a"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block tproctypecache_falsepositive:
|
||||||
|
type
|
||||||
|
Callback = proc() {.closure, gcsafe.}
|
||||||
|
GameState = ref object
|
||||||
|
playerChangeHandlers: seq[Callback]
|
||||||
|
|
||||||
|
proc newGameState(): GameState =
|
||||||
|
result = GameState(
|
||||||
|
playerChangeHandlers: newSeq[Callback]() # this fails
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block tptrinheritance:
|
||||||
|
type NSPasteboardItem = ptr object
|
||||||
|
type NSPasteboard = ptr object
|
||||||
|
type NSArrayAbstract = ptr object {.inheritable.}
|
||||||
|
type NSMutableArrayAbstract = ptr object of NSArrayAbstract
|
||||||
|
type NSArray[T] = ptr object of NSArrayAbstract
|
||||||
|
type NSMutableArray[T] = ptr object of NSArray[T]
|
||||||
|
|
||||||
|
proc newMutableArrayAbstract(): NSMutableArrayAbstract = discard
|
||||||
|
|
||||||
|
template newMutableArray(T: typedesc): NSMutableArray[T] =
|
||||||
|
cast[NSMutableArray[T]](newMutableArrayAbstract())
|
||||||
|
|
||||||
|
proc writeObjects(p: NSPasteboard, o: NSArray[NSPasteboardItem]) = discard
|
||||||
|
|
||||||
|
let a = newMutableArray NSPasteboardItem
|
||||||
|
var x: NSMutableArray[NSPasteboardItem]
|
||||||
|
var y: NSArray[NSPasteboardItem] = x
|
||||||
|
|
||||||
|
writeObjects(nil, a)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block tsigtypeop:
|
||||||
|
type Vec3[T] = array[3, T]
|
||||||
|
|
||||||
|
proc foo(x: Vec3, y: Vec3.T, z: x.T): x.type.T =
|
||||||
|
return 10
|
||||||
|
|
||||||
|
var y: Vec3[int] = [1, 2, 3]
|
||||||
|
var z: int = foo(y, 3, 4)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block tvarargs_vs_generics:
|
||||||
|
proc withDirectType(args: string) =
|
||||||
|
echo "direct"
|
||||||
|
proc withDirectType[T](arg: T) =
|
||||||
|
echo "generic"
|
||||||
|
proc withOpenArray(args: openarray[string]) =
|
||||||
|
echo "openarray"
|
||||||
|
proc withOpenArray[T](arg: T) =
|
||||||
|
echo "generic"
|
||||||
|
proc withVarargs(args: varargs[string]) =
|
||||||
|
echo "varargs"
|
||||||
|
proc withVarargs[T](arg: T) =
|
||||||
|
echo "generic"
|
||||||
|
|
||||||
|
withDirectType "string"
|
||||||
|
withOpenArray "string"
|
||||||
|
withVarargs "string"
|
||||||
Loading…
Add table
Add a link
Reference in a new issue