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 ''' joinable: false """ 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 = initHashSet[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)