mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-31 02:12:11 +00:00
509 lines
12 KiB
Nim
509 lines
12 KiB
Nim
discard """
|
|
output: '''
|
|
true012innertrue
|
|
m1
|
|
tup1
|
|
another number: 123
|
|
yay
|
|
helloa 1 b 2 x @[3, 4, 5] y 6 z 7
|
|
yay
|
|
12
|
|
ref ref T ptr S
|
|
dynamic: let
|
|
dynamic: var
|
|
static: const
|
|
static: literal
|
|
static: constant folding
|
|
static: static string
|
|
foo1
|
|
1
|
|
'''
|
|
"""
|
|
|
|
|
|
import strutils, sequtils
|
|
|
|
|
|
block overl2:
|
|
# Test new overloading resolution rules
|
|
proc toverl2(x: int): string = return $x
|
|
proc toverl2(x: bool): string = return $x
|
|
|
|
iterator toverl2(x: int): int =
|
|
var res = 0
|
|
while res < x:
|
|
yield res
|
|
inc(res)
|
|
|
|
var
|
|
pp: proc (x: bool): string {.nimcall.} = toverl2
|
|
|
|
stdout.write(pp(true))
|
|
|
|
for x in toverl2(3):
|
|
stdout.write(toverl2(x))
|
|
|
|
block:
|
|
proc toverl2(x: int): string = return "inner"
|
|
stdout.write(toverl2(5))
|
|
stdout.write(true)
|
|
|
|
stdout.write("\n")
|
|
#OUT true012innertrue
|
|
|
|
|
|
|
|
block overl3:
|
|
# Tests more specific generic match:
|
|
proc m[T](x: T) = echo "m2"
|
|
proc m[T](x: var ref T) = echo "m1"
|
|
proc tup[S, T](x: tuple[a: S, b: ref T]) = echo "tup1"
|
|
proc tup[S, T](x: tuple[a: S, b: T]) = echo "tup2"
|
|
|
|
var
|
|
obj: ref int
|
|
tu: tuple[a: int, b: ref bool]
|
|
|
|
m(obj)
|
|
tup(tu)
|
|
|
|
|
|
|
|
block toverprc:
|
|
# Test overloading of procs when used as function pointers
|
|
proc parseInt(x: float): int {.noSideEffect.} = discard
|
|
proc parseInt(x: bool): int {.noSideEffect.} = discard
|
|
proc parseInt(x: float32): int {.noSideEffect.} = discard
|
|
proc parseInt(x: int8): int {.noSideEffect.} = discard
|
|
proc parseInt(x: File): int {.noSideEffect.} = discard
|
|
proc parseInt(x: char): int {.noSideEffect.} = discard
|
|
proc parseInt(x: int16): int {.noSideEffect.} = discard
|
|
|
|
proc parseInt[T](x: T): int = echo x; 34
|
|
|
|
type
|
|
TParseInt = proc (x: string): int {.noSideEffect.}
|
|
|
|
var
|
|
q = TParseInt(parseInt)
|
|
p: TParseInt = parseInt
|
|
|
|
proc takeParseInt(x: proc (y: string): int {.noSideEffect.}): int =
|
|
result = x("123")
|
|
|
|
if false:
|
|
echo "Give a list of numbers (separated by spaces): "
|
|
var x = stdin.readline.split.map(parseInt).max
|
|
echo x, " is the maximum!"
|
|
echo "another number: ", takeParseInt(parseInt)
|
|
|
|
|
|
type
|
|
TFoo[a,b] = object
|
|
lorem: a
|
|
ipsum: b
|
|
|
|
proc bar[a,b](f: TFoo[a,b], x: a) = echo(x, " ", f.lorem, f.ipsum)
|
|
proc bar[a,b](f: TFoo[a,b], x: b) = echo(x, " ", f.lorem, f.ipsum)
|
|
|
|
discard parseInt[string]("yay")
|
|
|
|
|
|
|
|
block toverwr:
|
|
# Test the overloading resolution in connection with a qualifier
|
|
proc write(t: File, s: string) =
|
|
discard # a nop
|
|
system.write(stdout, "hello")
|
|
#OUT hello
|
|
|
|
|
|
|
|
block tparams_after_varargs:
|
|
proc test(a, b: int, x: varargs[int]; y, z: int) =
|
|
echo "a ", a, " b ", b, " x ", @x, " y ", y, " z ", z
|
|
|
|
test 1, 2, 3, 4, 5, 6, 7
|
|
|
|
# XXX maybe this should also work with ``varargs[untyped]``
|
|
template takesBlockA(a, b: untyped; x: varargs[typed]; blck: untyped): untyped =
|
|
blck
|
|
echo a, b
|
|
|
|
takesBlockA 1, 2, "some", 0.90, "random stuff":
|
|
echo "yay"
|
|
|
|
|
|
|
|
block tprefer_specialized_generic:
|
|
proc foo[T](x: T) =
|
|
echo "only T"
|
|
|
|
proc foo[T](x: ref T) =
|
|
echo "ref T"
|
|
|
|
proc foo[T, S](x: ref ref T; y: ptr S) =
|
|
echo "ref ref T ptr S"
|
|
|
|
proc foo[T, S](x: ref T; y: ptr S) =
|
|
echo "ref T ptr S"
|
|
|
|
proc foo[T](x: ref T; default = 0) =
|
|
echo "ref T; default"
|
|
|
|
var x: ref ref int
|
|
var y: ptr ptr int
|
|
foo(x, y)
|
|
|
|
|
|
|
|
block tstaticoverload:
|
|
proc foo(s: string) =
|
|
echo "dynamic: ", s
|
|
|
|
proc foo(s: static[string]) =
|
|
echo "static: ", s
|
|
|
|
let l = "let"
|
|
var v = "var"
|
|
const c = "const"
|
|
|
|
type staticString = static[string]
|
|
|
|
foo(l)
|
|
foo(v)
|
|
foo(c)
|
|
foo("literal")
|
|
foo("constant" & " " & "folding")
|
|
foo(staticString("static string"))
|
|
|
|
# bug #8568 (2)
|
|
|
|
proc goo(a: int): string = "int"
|
|
proc goo(a: static[int]): string = "static int"
|
|
proc goo(a: var int): string = "var int"
|
|
proc goo[T: int](a: T): string = "T: int"
|
|
#proc goo[T](a: T): string = "nur T"
|
|
|
|
const tmp1 = 1
|
|
let tmp2 = 1
|
|
var tmp3 = 1
|
|
|
|
doAssert goo(1) == "static int"
|
|
doAssert goo(tmp1) == "static int"
|
|
doAssert goo(tmp2) == "int"
|
|
doAssert goo(tmp3) == "var int"
|
|
|
|
doAssert goo[int](1) == "T: int"
|
|
|
|
doAssert goo[int](tmp1) == "T: int"
|
|
doAssert goo[int](tmp2) == "T: int"
|
|
doAssert goo[int](tmp3) == "T: int"
|
|
|
|
# bug #6076
|
|
|
|
type A[T] = object
|
|
|
|
proc regr(a: A[void]) = echo "foo1"
|
|
proc regr[T](a: A[T]) = doAssert(false)
|
|
|
|
regr(A[void]())
|
|
|
|
|
|
type Foo[T] = object
|
|
|
|
proc regr[T](p: Foo[T]): seq[T] =
|
|
discard
|
|
|
|
proc regr(p: Foo[void]): seq[int] =
|
|
discard
|
|
|
|
|
|
discard regr(Foo[int]())
|
|
discard regr(Foo[void]())
|
|
|
|
|
|
type
|
|
Sha2Context*[bits: static[int],
|
|
bsize: static[int],
|
|
T: uint32|uint64] = object
|
|
count: array[2, T]
|
|
state: array[8, T]
|
|
buffer: array[bsize, byte]
|
|
|
|
sha224* = Sha2Context[224, 64, uint32]
|
|
sha256* = Sha2Context[256, 64, uint32]
|
|
sha384* = Sha2Context[384, 128, uint64]
|
|
sha512* = Sha2Context[512, 128, uint64]
|
|
sha512_224* = Sha2Context[224, 128, uint64]
|
|
sha512_256* = Sha2Context[256, 128, uint64]
|
|
|
|
type
|
|
RipemdContext*[bits: static[int]] = object
|
|
count: array[2, uint32]
|
|
state: array[bits div 32, uint32]
|
|
buffer: array[64, byte]
|
|
|
|
ripemd128* = RipemdContext[128]
|
|
ripemd160* = RipemdContext[160]
|
|
ripemd256* = RipemdContext[256]
|
|
ripemd320* = RipemdContext[320]
|
|
|
|
const
|
|
MaxHmacBlockSize = 256
|
|
|
|
type
|
|
HMAC*[HashType] = object
|
|
mdctx: HashType
|
|
opadctx: HashType
|
|
|
|
template sizeBlock*(h: HMAC[Sha2Context]): uint = 1u
|
|
template sizeBlock*(h: HMAC[RipemdContext]): uint = 0u
|
|
|
|
proc init*[T](hmctx: HMAC[T], key: ptr byte, ulen: uint) =
|
|
const sizeBlock = hmctx.sizeBlock
|
|
echo sizeBlock
|
|
|
|
proc hmac*[A, B](HashType: typedesc, key: openarray[A],
|
|
data: openarray[B]) =
|
|
var ctx: HMAC[HashType]
|
|
ctx.init(nil, 0)
|
|
|
|
sha256.hmac("", "")
|
|
|
|
|
|
|
|
# nested generic types
|
|
block:
|
|
type
|
|
Foo[T] = object
|
|
f: T
|
|
Bar[T] = object
|
|
b: T
|
|
Baz[T] = object
|
|
z: T
|
|
FooBar[T] = Foo[Bar[T]]
|
|
FooBarBaz[T] = FooBar[Baz[T]]
|
|
#Int = int
|
|
Int = SomeInteger
|
|
FooBarBazInt = FooBarBaz[Int]
|
|
FooBarBazX = FooBarBaz[int]
|
|
|
|
proc p00(x: Foo): auto = x.f
|
|
proc p01[T](x: Foo[T]): auto = x.f
|
|
proc p02[T:Foo](x: T): auto = x.f
|
|
|
|
proc p10(x: FooBar): auto = x.f
|
|
proc p11[T](x: FooBar[T]): auto = x.f
|
|
proc p12[T:FooBar](x: T): auto = x.f
|
|
proc p13(x: Foo[Bar]): auto = x.f
|
|
proc p14[T](x: Foo[Bar[T]]): auto = x.f
|
|
proc p15[T:Bar](x: Foo[T]): auto = x.f
|
|
proc p16[T:Foo[Bar]](x: T): auto = x.f
|
|
|
|
proc p20(x: FooBarBaz): auto = x.f
|
|
proc p21[T](x: FooBarBaz[T]): auto = x.f
|
|
proc p22[T:FooBarBaz](x: T): auto = x.f
|
|
proc p23(x: FooBar[Baz]): auto = x.f
|
|
proc p24[T](x: FooBar[Baz[T]]): auto = x.f
|
|
proc p25[T:Baz](x: FooBar[T]): auto = x.f
|
|
proc p26[T:FooBar[Baz]](x: T): auto = x.f
|
|
proc p27(x: Foo[Bar[Baz]]): auto = x.f
|
|
proc p28[T](x: Foo[Bar[Baz[T]]]): auto = x.f
|
|
proc p29[T:Baz](x: Foo[Bar[T]]): auto = x.f
|
|
proc p2A[T:Bar[Baz]](x: Foo[T]): auto = x.f
|
|
proc p2B[T:Foo[Bar[Baz]]](x: T): auto = x.f
|
|
|
|
proc p30(x: FooBarBazInt): auto = x.f
|
|
proc p31[T:FooBarBazInt](x: T): auto = x.f
|
|
proc p32(x: FooBarBaz[Int]): auto = x.f
|
|
proc p33[T:Int](x: FooBarBaz[T]): auto = x.f
|
|
proc p34[T:FooBarBaz[Int]](x: T): auto = x.f
|
|
proc p35(x: FooBar[Baz[Int]]): auto = x.f
|
|
proc p36[T:Int](x: FooBar[Baz[T]]): auto = x.f
|
|
proc p37[T:Baz[Int]](x: FooBar[T]): auto = x.f
|
|
proc p38[T:FooBar[Baz[Int]]](x: T): auto = x.f
|
|
proc p39(x: Foo[Bar[Baz[Int]]]): auto = x.f
|
|
proc p3A[T:Int](x: Foo[Bar[Baz[T]]]): auto = x.f
|
|
proc p3B[T:Baz[Int]](x: Foo[Bar[T]]): auto = x.f
|
|
proc p3C[T:Bar[Baz[Int]]](x: Foo[T]): auto = x.f
|
|
proc p3D[T:Foo[Bar[Baz[Int]]]](x: T): auto = x.f
|
|
|
|
template test(x: typed) =
|
|
let t00 = p00(x)
|
|
let t01 = p01(x)
|
|
let t02 = p02(x)
|
|
let t10 = p10(x)
|
|
let t11 = p11(x)
|
|
let t12 = p12(x)
|
|
#let t13 = p13(x)
|
|
let t14 = p14(x)
|
|
#let t15 = p15(x)
|
|
#let t16 = p16(x)
|
|
let t20 = p20(x)
|
|
let t21 = p21(x)
|
|
let t22 = p22(x)
|
|
#let t23 = p23(x)
|
|
let t24 = p24(x)
|
|
#let t25 = p25(x)
|
|
#let t26 = p26(x)
|
|
#let t27 = p27(x)
|
|
let t28 = p28(x)
|
|
#let t29 = p29(x)
|
|
#let t2A = p2A(x)
|
|
#let t2B = p2B(x)
|
|
let t30 = p30(x)
|
|
let t31 = p31(x)
|
|
let t32 = p32(x)
|
|
let t33 = p33(x)
|
|
let t34 = p34(x)
|
|
let t35 = p35(x)
|
|
let t36 = p36(x)
|
|
let t37 = p37(x)
|
|
let t38 = p38(x)
|
|
let t39 = p39(x)
|
|
let t3A = p3A(x)
|
|
let t3B = p3B(x)
|
|
let t3C = p3C(x)
|
|
let t3D = p3D(x)
|
|
|
|
var a: Foo[Bar[Baz[int]]]
|
|
test(a)
|
|
var b: FooBar[Baz[int]]
|
|
test(b)
|
|
var c: FooBarBaz[int]
|
|
test(c)
|
|
var d: FooBarBazX
|
|
test(d)
|
|
|
|
|
|
# overloading on tuples with generic alias
|
|
block:
|
|
type
|
|
Foo[F,T] = object
|
|
exArgs: T
|
|
FooUn[F,T] = Foo[F,tuple[a:T]]
|
|
FooBi[F,T1,T2] = Foo[F,tuple[a:T1,b:T2]]
|
|
|
|
proc foo1[F,T](x: Foo[F,tuple[a:T]]): int = 1
|
|
proc foo1[F,T1,T2](x: Foo[F,tuple[a:T1,b:T2]]): int = 2
|
|
proc foo2[F,T](x: FooUn[F,T]): int = 1
|
|
proc foo2[F,T1,T2](x: FooBi[F,T1,T2]):int = 2
|
|
|
|
template bar1[F,T](x: Foo[F,tuple[a:T]]): int = 1
|
|
template bar1[F,T1,T2](x: Foo[F,tuple[a:T1,b:T2]]): int = 2
|
|
template bar2[F,T](x: FooUn[F,T]): int = 1
|
|
template bar2[F,T1,T2](x: FooBi[F,T1,T2]): int = 2
|
|
|
|
proc test(x: any, n: int) =
|
|
doAssert(foo1(x) == n)
|
|
doAssert(foo2(x) == n)
|
|
doAssert(bar1(x) == n)
|
|
doAssert(bar2(x) == n)
|
|
|
|
var a: Foo[int, tuple[a:int]]
|
|
test(a, 1)
|
|
var b: FooUn[int, int]
|
|
test(b, 1)
|
|
var c: Foo[int, tuple[a:int,b:int]]
|
|
test(c, 2)
|
|
var d: FooBi[int, int, int]
|
|
test(d, 2)
|
|
|
|
|
|
# inheritance and generics
|
|
block:
|
|
type
|
|
Foo[T] = object of RootObj
|
|
x: T
|
|
Bar[T] = object of Foo[T]
|
|
y: T
|
|
Baz[T] = object of Bar[T]
|
|
z: T
|
|
|
|
template t0(x: Foo[int]): int = 0
|
|
template t0(x: Bar[int]): int = 1
|
|
template t0(x: Foo[bool or int]): int = 10
|
|
template t0(x: Bar[bool or int]): int = 11
|
|
#template t0[T:bool or int](x: Bar[T]): int = 11
|
|
template t0[T](x: Foo[T]): int = 20
|
|
template t0[T](x: Bar[T]): int = 21
|
|
proc p0(x: Foo[int]): int = 0
|
|
proc p0(x: Bar[int]): int = 1
|
|
#proc p0(x: Foo[bool or int]): int = 10
|
|
#proc p0(x: Bar[bool or int]): int = 11
|
|
proc p0[T](x: Foo[T]): int = 20
|
|
proc p0[T](x: Bar[T]): int = 21
|
|
|
|
var a: Foo[int]
|
|
var b: Bar[int]
|
|
var c: Baz[int]
|
|
var d: Foo[bool]
|
|
var e: Bar[bool]
|
|
var f: Baz[bool]
|
|
var g: Foo[float]
|
|
var h: Bar[float]
|
|
var i: Baz[float]
|
|
doAssert(t0(a) == 0)
|
|
doAssert(t0(b) == 1)
|
|
doAssert(t0(c) == 1)
|
|
doAssert(t0(d) == 10)
|
|
doAssert(t0(e) == 11)
|
|
doAssert(t0(f) == 11)
|
|
doAssert(t0(g) == 20)
|
|
doAssert(t0(h) == 21)
|
|
#doAssert(t0(i) == 21)
|
|
doAssert(p0(a) == 0)
|
|
doAssert(p0(b) == 1)
|
|
doAssert(p0(c) == 1)
|
|
#doAssert(p0(d) == 10)
|
|
#doAssert(p0(e) == 11)
|
|
#doAssert(p0(f) == 11)
|
|
doAssert(p0(g) == 20)
|
|
doAssert(p0(h) == 21)
|
|
doAssert(p0(i) == 21)
|
|
|
|
#type
|
|
# f0 = proc(x:Foo)
|
|
|
|
|
|
block:
|
|
type
|
|
TilesetCT[n: static[int]] = distinct int
|
|
TilesetRT = int
|
|
Tileset = TilesetCT | TilesetRT
|
|
|
|
func prepareTileset(tileset: var Tileset) = discard
|
|
|
|
func prepareTileset(tileset: Tileset): Tileset =
|
|
result = tileset
|
|
result.prepareTileset
|
|
|
|
var parsedTileset: TilesetRT
|
|
prepareTileset(parsedTileset)
|
|
|
|
|
|
block:
|
|
proc p1[T,U: SomeInteger|SomeFloat](x: T, y: U): int|float =
|
|
when T is SomeInteger and U is SomeInteger:
|
|
result = int(x) + int(y)
|
|
else:
|
|
result = float(x) + float(y)
|
|
doAssert(p1(1,2) == 3)
|
|
doAssert(p1(1.0,2) == 3.0)
|
|
doAssert(p1(1,2.0) == 3.0)
|
|
doAssert(p1(1.0,2.0) == 3.0)
|
|
|
|
type Foo[T,U] = U
|
|
template F[T,U](t: typedesc[T], x: U): untyped = Foo[T,U](x)
|
|
proc p2[T; U,V:Foo[T,SomeNumber]](x: U, y: V): T =
|
|
T(x) + T(y)
|
|
#proc p2[T; U:Foo[T,SomeNumber], V:Foo[not T,SomeNumber]](x: U, y: V): T =
|
|
# T(x) + T(y)
|
|
doAssert(p2(F(int,1),F(int,2)) == 3)
|
|
doAssert(p2(F(float,1),F(float,2)) == 3.0)
|
|
doAssert(p2(F(float,1),F(float,2.0)) == 3.0)
|
|
doAssert(p2(F(float,1.0),F(float,2)) == 3.0)
|
|
doAssert(p2(F(float,1.0),F(float,2.0)) == 3.0)
|
|
#doAssert(p2(F(float,1),F(int,2.0)) == 3.0)
|