Merge tests into a larger file (part 1 of ∞) (#9318)
* merge actiontable tests * merge arithm tests * merge array tests * merge assign tests * merge bind tests * merge casestmt tests * merge closure tests * merge cnt seq tests * merge collections tests * merge concept issues tests * merge concept tests * fix failing tests * smaller outputs Use `doAssert` where possible. * fix wrong output * split `tcomputedgoto` * revert merging concepts * fix failing test
This commit is contained in:
parent
d2b04a8bc7
commit
7f18d7cbc1
103 changed files with 3736 additions and 3368 deletions
|
|
@ -1,21 +0,0 @@
|
|||
discard """
|
||||
output: "true\ntrue"
|
||||
"""
|
||||
|
||||
type
|
||||
TFooContainer[T] = object
|
||||
|
||||
TContainer[T] = concept var c
|
||||
foo(c, T)
|
||||
|
||||
proc foo[T](c: var TFooContainer[T], val: T) =
|
||||
discard
|
||||
|
||||
proc bar(c: var TContainer) =
|
||||
discard
|
||||
|
||||
var fooContainer: TFooContainer[int]
|
||||
echo fooContainer is TFooContainer # true.
|
||||
echo fooContainer is TFooContainer[int] # true.
|
||||
fooContainer.bar()
|
||||
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
type
|
||||
View[T] = concept v
|
||||
v.empty is bool
|
||||
v.front is T
|
||||
popFront v
|
||||
|
||||
proc find(view: View; target: View.T): View =
|
||||
result = view
|
||||
|
||||
while not result.empty:
|
||||
if view.front == target:
|
||||
return
|
||||
|
||||
mixin popFront
|
||||
popFront result
|
||||
|
||||
proc popFront[T](s: var seq[T]) = discard
|
||||
proc empty[T](s: seq[T]): bool = false
|
||||
|
||||
var s1 = @[1, 2, 3]
|
||||
let s2 = s1.find(10)
|
||||
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
discard """
|
||||
output: 9
|
||||
"""
|
||||
|
||||
type DataTable = concept x
|
||||
x is object
|
||||
for f in fields(x):
|
||||
f is seq
|
||||
|
||||
type Students = object
|
||||
id : seq[int]
|
||||
name : seq[string]
|
||||
age: seq[int]
|
||||
|
||||
proc nrow*(dt: DataTable) : Natural =
|
||||
var totalLen = 0
|
||||
for f in fields(dt):
|
||||
totalLen += f.len
|
||||
return totalLen
|
||||
|
||||
let
|
||||
stud = Students(id : @[1,2,3], name : @["Vas", "Pas", "NafNaf"], age : @[10,16,32])
|
||||
|
||||
echo nrow(stud)
|
||||
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
discard """
|
||||
output: '''
|
||||
true
|
||||
true
|
||||
true
|
||||
f
|
||||
0
|
||||
'''
|
||||
"""
|
||||
|
||||
import t5888lib/ca, t5888lib/opt
|
||||
|
||||
type LocalCA = ca.CA
|
||||
|
||||
proc f(c: CA) =
|
||||
echo "f"
|
||||
echo c.x
|
||||
|
||||
var o = new(Opt)
|
||||
|
||||
echo o is CA
|
||||
echo o is LocalCA
|
||||
echo o is ca.CA
|
||||
|
||||
o.f()
|
||||
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
discard """
|
||||
exitcode: 0
|
||||
"""
|
||||
|
||||
type
|
||||
Enumerable[T] = concept e
|
||||
for it in e:
|
||||
it is T
|
||||
|
||||
proc cmap[T, G](e: Enumerable[T], fn: proc(t: T): G): seq[G] =
|
||||
result = @[]
|
||||
for it in e: result.add(fn(it))
|
||||
|
||||
import json
|
||||
|
||||
var x = %["hello", "world"]
|
||||
|
||||
var z = x.cmap(proc(it: JsonNode): string = it.getStr & "!")
|
||||
assert z == @["hello!", "world!"]
|
||||
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
discard """
|
||||
output: "20.0 USD"
|
||||
"""
|
||||
|
||||
import typetraits
|
||||
|
||||
const currencies = ["USD", "EUR"] # in real code 120 currencies
|
||||
|
||||
type USD* = distinct float # in real code 120 types generates using macro
|
||||
type EUR* = distinct float
|
||||
|
||||
type CurrencyAmount = concept c
|
||||
type t = c.type
|
||||
const name = c.type.name
|
||||
name in currencies
|
||||
|
||||
proc `$`(x: CurrencyAmount): string =
|
||||
$float(x) & " " & x.name
|
||||
|
||||
let amount = 20.USD
|
||||
echo amount
|
||||
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
discard """
|
||||
output: "true"
|
||||
"""
|
||||
|
||||
import future
|
||||
|
||||
type
|
||||
FilterMixin*[T] = ref object
|
||||
test*: (T) -> bool
|
||||
trans*: (T) -> T
|
||||
|
||||
SeqGen*[T] = ref object
|
||||
fil*: FilterMixin[T]
|
||||
|
||||
WithFilter[T] = concept a
|
||||
a.fil is FilterMixin[T]
|
||||
|
||||
proc test*[T](a: WithFilter[T]): (T) -> bool =
|
||||
a.fil.test
|
||||
|
||||
var s = SeqGen[int](fil: FilterMixin[int](test: nil, trans: nil))
|
||||
echo s.test() == nil
|
||||
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
discard """
|
||||
output: '''
|
||||
10
|
||||
10
|
||||
'''
|
||||
"""
|
||||
|
||||
type GA = concept c
|
||||
c.a is int
|
||||
|
||||
type A = object
|
||||
a: int
|
||||
|
||||
type AA = object
|
||||
case exists: bool
|
||||
of true:
|
||||
a: int
|
||||
else:
|
||||
discard
|
||||
|
||||
proc print(inp: GA) =
|
||||
echo inp.a
|
||||
|
||||
let failing = AA(exists: true, a: 10)
|
||||
let working = A(a:10)
|
||||
print(working)
|
||||
print(failing)
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
discard """
|
||||
output: 5
|
||||
"""
|
||||
|
||||
type
|
||||
HasLen = concept iter
|
||||
len(iter) is int
|
||||
|
||||
proc echoLen(x: HasLen) =
|
||||
echo len(x)
|
||||
|
||||
echoLen([1, 2, 3, 4, 5])
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
discard """
|
||||
output: "()"
|
||||
"""
|
||||
|
||||
type
|
||||
Iterable[T] = concept x
|
||||
for elem in x:
|
||||
elem is T
|
||||
|
||||
proc max[A](iter: Iterable[A]): A =
|
||||
discard
|
||||
|
||||
type
|
||||
MyType = object
|
||||
|
||||
echo max(@[MyType()])
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
discard """
|
||||
output: '''Printable'''
|
||||
"""
|
||||
|
||||
import macros
|
||||
|
||||
type
|
||||
int1 = distinct int
|
||||
int2 = distinct int
|
||||
|
||||
int1g = concept x
|
||||
x is int1
|
||||
|
||||
int2g = concept x
|
||||
x is int2
|
||||
|
||||
proc take[T: int1g](value: int1) =
|
||||
when T is int2:
|
||||
static: error("killed in take(int1)")
|
||||
|
||||
proc take[T: int2g](vale: int2) =
|
||||
when T is int1:
|
||||
static: error("killed in take(int2)")
|
||||
|
||||
var i1: int1 = 1.int1
|
||||
var i2: int2 = 2.int2
|
||||
|
||||
take[int1](i1)
|
||||
take[int2](i2)
|
||||
|
||||
template reject(e) =
|
||||
static: assert(not compiles(e))
|
||||
|
||||
reject take[string](i2)
|
||||
reject take[int1](i2)
|
||||
|
||||
# bug #6249
|
||||
type
|
||||
Obj1[T] = object
|
||||
v: T
|
||||
|
||||
Obj2 = ref object
|
||||
|
||||
PrintAble = concept x
|
||||
$x is string
|
||||
|
||||
converter toObj1[T](t: T): Obj1[T] =
|
||||
return Obj1[T](v: t)
|
||||
|
||||
proc `$`[T](nt: Obj1[T]): string =
|
||||
when T is PrintAble: result = "Printable"
|
||||
else: result = "Non Printable"
|
||||
|
||||
echo Obj2()
|
||||
441
tests/concepts/tconcepts.nim
Normal file
441
tests/concepts/tconcepts.nim
Normal file
|
|
@ -0,0 +1,441 @@
|
|||
discard """
|
||||
file: "tconcepts.nim"
|
||||
output: '''
|
||||
10
|
||||
20
|
||||
int
|
||||
20
|
||||
3
|
||||
x as ParameterizedType[T]
|
||||
x as ParameterizedType[T]
|
||||
x as ParameterizedType[T]
|
||||
x as ParameterizedType
|
||||
x as ParameterizedType
|
||||
x as CustomTypeClass
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
a
|
||||
b
|
||||
t
|
||||
e
|
||||
s
|
||||
t
|
||||
z
|
||||
e
|
||||
1
|
||||
2
|
||||
3
|
||||
20
|
||||
10
|
||||
5
|
||||
'''
|
||||
"""
|
||||
|
||||
|
||||
import typetraits, strutils
|
||||
|
||||
|
||||
block tcomparable:
|
||||
type
|
||||
Comparable = concept a
|
||||
(a < a) is bool
|
||||
|
||||
proc myMax(a, b: Comparable): Comparable =
|
||||
if a < b:
|
||||
return b
|
||||
else:
|
||||
return a
|
||||
|
||||
doAssert myMax(5, 10) == 10
|
||||
doAssert myMax(31.3, 1.23124) == 31.3
|
||||
|
||||
|
||||
|
||||
block tconceptinclosure:
|
||||
type
|
||||
FonConcept = concept x
|
||||
x.x is int
|
||||
GenericConcept[T] = concept x
|
||||
x.x is T
|
||||
const L = T.name.len
|
||||
Implementation = object
|
||||
x: int
|
||||
Closure = object
|
||||
f: proc()
|
||||
|
||||
proc f1(x: FonConcept): Closure =
|
||||
result.f = proc () =
|
||||
echo x.x
|
||||
|
||||
proc f2(x: GenericConcept): Closure =
|
||||
result.f = proc () =
|
||||
echo x.x
|
||||
echo GenericConcept.T.name
|
||||
|
||||
proc f3[T](x: GenericConcept[T]): Closure =
|
||||
result.f = proc () =
|
||||
echo x.x
|
||||
echo x.L
|
||||
|
||||
let x = Implementation(x: 10)
|
||||
let y = Implementation(x: 20)
|
||||
|
||||
let a = x.f1
|
||||
let b = x.f2
|
||||
let c = x.f1
|
||||
let d = y.f2
|
||||
let e = y.f3
|
||||
|
||||
a.f()
|
||||
d.f()
|
||||
e.f()
|
||||
|
||||
|
||||
|
||||
block overload_precedence:
|
||||
type ParameterizedType[T] = object
|
||||
|
||||
type CustomTypeClass = concept
|
||||
true
|
||||
|
||||
# 3 competing procs
|
||||
proc a[T](x: ParameterizedType[T]) =
|
||||
echo "x as ParameterizedType[T]"
|
||||
|
||||
proc a(x: ParameterizedType) =
|
||||
echo "x as ParameterizedType"
|
||||
|
||||
proc a(x: CustomTypeClass) =
|
||||
echo "x as CustomTypeClass"
|
||||
|
||||
# the same procs in different order
|
||||
proc b(x: ParameterizedType) =
|
||||
echo "x as ParameterizedType"
|
||||
|
||||
proc b(x: CustomTypeClass) =
|
||||
echo "x as CustomTypeClass"
|
||||
|
||||
proc b[T](x: ParameterizedType[T]) =
|
||||
echo "x as ParameterizedType[T]"
|
||||
|
||||
# and yet another order
|
||||
proc c(x: CustomTypeClass) =
|
||||
echo "x as CustomTypeClass"
|
||||
|
||||
proc c(x: ParameterizedType) =
|
||||
echo "x as ParameterizedType"
|
||||
|
||||
proc c[T](x: ParameterizedType[T]) =
|
||||
echo "x as ParameterizedType[T]"
|
||||
|
||||
# remove the most specific one
|
||||
proc d(x: ParameterizedType) =
|
||||
echo "x as ParameterizedType"
|
||||
|
||||
proc d(x: CustomTypeClass) =
|
||||
echo "x as CustomTypeClass"
|
||||
|
||||
# then shuffle the order again
|
||||
proc e(x: CustomTypeClass) =
|
||||
echo "x as CustomTypeClass"
|
||||
|
||||
proc e(x: ParameterizedType) =
|
||||
echo "x as ParameterizedType"
|
||||
|
||||
# the least specific one is a match
|
||||
proc f(x: CustomTypeClass) =
|
||||
echo "x as CustomTypeClass"
|
||||
|
||||
a(ParameterizedType[int]())
|
||||
b(ParameterizedType[int]())
|
||||
c(ParameterizedType[int]())
|
||||
d(ParameterizedType[int]())
|
||||
e(ParameterizedType[int]())
|
||||
f(ParameterizedType[int]())
|
||||
|
||||
|
||||
|
||||
block templates:
|
||||
template typeLen(x): int = x.type.name.len
|
||||
|
||||
template bunchOfChecks(x) =
|
||||
x.typeLen > 3
|
||||
x != 10 is bool
|
||||
|
||||
template stmtListExprTmpl(x: untyped): untyped =
|
||||
x is int
|
||||
x
|
||||
|
||||
type
|
||||
Obj = object
|
||||
x: int
|
||||
|
||||
Gen[T] = object
|
||||
x: T
|
||||
|
||||
Eq = concept x, y
|
||||
(x == y) is bool
|
||||
|
||||
NotEq = concept x, y
|
||||
(x != y) is bool
|
||||
|
||||
ConceptUsingTemplate1 = concept x
|
||||
echo x
|
||||
sizeof(x) is int
|
||||
bunchOfChecks x
|
||||
|
||||
ConceptUsingTemplate2 = concept x
|
||||
stmtListExprTmpl x
|
||||
|
||||
template ok(x) =
|
||||
static: assert(x)
|
||||
|
||||
template no(x) =
|
||||
static: assert(not(x))
|
||||
|
||||
ok int is Eq
|
||||
ok int is NotEq
|
||||
ok string is Eq
|
||||
ok string is NotEq
|
||||
ok Obj is Eq
|
||||
ok Obj is NotEq
|
||||
ok Gen[string] is Eq
|
||||
ok Gen[int] is NotEq
|
||||
|
||||
no int is ConceptUsingTemplate1
|
||||
ok float is ConceptUsingTemplate1
|
||||
no string is ConceptUsingTemplate1
|
||||
|
||||
ok int is ConceptUsingTemplate2
|
||||
no float is ConceptUsingTemplate2
|
||||
no string is ConceptUsingTemplate2
|
||||
|
||||
|
||||
|
||||
block titerable:
|
||||
type
|
||||
Iterable[T] = concept x
|
||||
for value in x:
|
||||
type(value) is T
|
||||
|
||||
proc sum[T](iter: Iterable[T]): T =
|
||||
static: echo T.name
|
||||
for element in iter:
|
||||
static: echo element.type.name
|
||||
result += element
|
||||
|
||||
doAssert sum([1, 2, 3, 4, 5]) == 15
|
||||
|
||||
|
||||
|
||||
block tmanual:
|
||||
template accept(e) =
|
||||
static: assert compiles(e)
|
||||
|
||||
template reject(e) =
|
||||
static: assert(not compiles(e))
|
||||
|
||||
type
|
||||
Container[T] = concept c
|
||||
c.len is Ordinal
|
||||
items(c) is T
|
||||
for value in c:
|
||||
type(value) is T
|
||||
|
||||
proc takesIntContainer(c: Container[int]) =
|
||||
for e in c: echo e
|
||||
|
||||
takesIntContainer(@[1, 2, 3])
|
||||
reject takesIntContainer(@["x", "y"])
|
||||
|
||||
proc takesContainer(c: Container) =
|
||||
for e in c: echo e
|
||||
|
||||
takesContainer(@[4, 5, 6])
|
||||
takesContainer(@["a", "b"])
|
||||
takesContainer "test"
|
||||
reject takesContainer(10)
|
||||
|
||||
|
||||
|
||||
block modifiers_in_place:
|
||||
type
|
||||
VarContainer[T] = concept c
|
||||
put(var c, T)
|
||||
AltVarContainer[T] = concept var c
|
||||
put(c, T)
|
||||
NonVarContainer[T] = concept c
|
||||
put(c, T)
|
||||
GoodContainer = object
|
||||
x: int
|
||||
BadContainer = object
|
||||
x: int
|
||||
|
||||
proc put(x: BadContainer, y: int) = discard
|
||||
proc put(x: var GoodContainer, y: int) = discard
|
||||
|
||||
template ok(x) = assert(x)
|
||||
template no(x) = assert(not(x))
|
||||
|
||||
static:
|
||||
ok GoodContainer is VarContainer[int]
|
||||
ok GoodContainer is AltVarContainer[int]
|
||||
no BadContainer is VarContainer[int]
|
||||
no BadContainer is AltVarContainer[int]
|
||||
ok GoodContainer is NonVarContainer[int]
|
||||
ok BadContainer is NonVarContainer[int]
|
||||
|
||||
|
||||
|
||||
block treversable:
|
||||
type
|
||||
Reversable[T] = concept a
|
||||
a[int] is T
|
||||
a.high is int
|
||||
a.len is int
|
||||
a.low is int
|
||||
|
||||
proc get[T](s: Reversable[T], n: int): T =
|
||||
s[n]
|
||||
|
||||
proc hi[T](s: Reversable[T]): int =
|
||||
s.high
|
||||
|
||||
proc lo[T](s: Reversable[T]): int =
|
||||
s.low
|
||||
|
||||
iterator reverse[T](s: Reversable[T]): T =
|
||||
assert hi(s) - lo(s) == len(s) - 1
|
||||
for z in hi(s).countdown(lo(s)):
|
||||
yield s.get(z)
|
||||
|
||||
for s in @["e", "z"].reverse:
|
||||
echo s
|
||||
|
||||
|
||||
|
||||
block tmonoid:
|
||||
type Monoid = concept x, y
|
||||
x + y is type(x)
|
||||
type(z(type(x))) is type(x)
|
||||
|
||||
proc z(x: typedesc[int]): int = 0
|
||||
|
||||
doAssert(int is Monoid)
|
||||
|
||||
# https://github.com/nim-lang/Nim/issues/8126
|
||||
type AdditiveMonoid = concept x, y, type T
|
||||
x + y is T
|
||||
|
||||
# some redundant checks to test an alternative approaches:
|
||||
type TT = type(x)
|
||||
x + y is type(x)
|
||||
x + y is TT
|
||||
|
||||
doAssert(1 is AdditiveMonoid)
|
||||
|
||||
|
||||
|
||||
block tesqofconcept:
|
||||
type
|
||||
MyConcept = concept x
|
||||
someProc(x)
|
||||
SomeSeq = seq[MyConcept]
|
||||
|
||||
proc someProc(x:int) = echo x
|
||||
|
||||
proc work (s: SomeSeq) =
|
||||
for item in s:
|
||||
someProc item
|
||||
|
||||
var s = @[1, 2, 3]
|
||||
work s
|
||||
|
||||
|
||||
|
||||
block tvectorspace:
|
||||
type VectorSpace[K] = concept x, y
|
||||
x + y is type(x)
|
||||
zero(type(x)) is type(x)
|
||||
-x is type(x)
|
||||
x - y is type(x)
|
||||
var k: K
|
||||
k * x is type(x)
|
||||
|
||||
proc zero(T: typedesc): T = 0
|
||||
|
||||
static:
|
||||
assert float is VectorSpace[float]
|
||||
# assert float is VectorSpace[int]
|
||||
# assert int is VectorSpace
|
||||
|
||||
|
||||
|
||||
block tstack:
|
||||
template reject(e) =
|
||||
static: assert(not compiles(e))
|
||||
|
||||
type
|
||||
ArrayStack = object
|
||||
data: seq[int]
|
||||
|
||||
proc push(s: var ArrayStack, item: int) =
|
||||
s.data.add item
|
||||
|
||||
proc pop(s: var ArrayStack): int =
|
||||
return s.data.pop()
|
||||
|
||||
type
|
||||
Stack[T] = concept var s
|
||||
s.push(T)
|
||||
s.pop() is T
|
||||
|
||||
type ValueType = T
|
||||
const ValueTypeName = T.name.toUpperAscii
|
||||
|
||||
proc genericAlgorithm[T](s: var Stack[T], y: T) =
|
||||
static:
|
||||
echo "INFERRED ", T.name
|
||||
echo "VALUE TYPE ", s.ValueType.name
|
||||
echo "VALUE TYPE NAME ", s.ValueTypeName
|
||||
|
||||
s.push(y)
|
||||
echo s.pop
|
||||
|
||||
proc implicitGeneric(s: var Stack): auto =
|
||||
static:
|
||||
echo "IMPLICIT INFERRED ", s.T.name, " ", Stack.T.name
|
||||
echo "IMPLICIT VALUE TYPE ", s.ValueType.name, " ", Stack.ValueType.name
|
||||
echo "IMPLICIT VALUE TYPE NAME ", s.ValueTypeName, " ", Stack.ValueTypeName
|
||||
|
||||
return s.pop()
|
||||
|
||||
var s = ArrayStack(data: @[])
|
||||
|
||||
s.push 10
|
||||
s.genericAlgorithm 20
|
||||
echo s.implicitGeneric
|
||||
|
||||
reject s.genericAlgorithm "x"
|
||||
reject s.genericAlgorithm 1.0
|
||||
reject "str".implicitGeneric
|
||||
reject implicitGeneric(10)
|
||||
|
||||
|
||||
|
||||
import libs/[trie_database, trie]
|
||||
block ttrie:
|
||||
proc takeDb(d: TrieDatabase) = discard
|
||||
var mdb: MemDB
|
||||
takeDb(mdb)
|
||||
|
||||
|
||||
|
||||
import mvarconcept
|
||||
block tvar:
|
||||
# bug #2346, bug #2404
|
||||
echo randomInt(5)
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
# bug #3452
|
||||
import math
|
||||
|
||||
type
|
||||
Node* = concept n
|
||||
`==`(n, n) is bool
|
||||
|
||||
Graph1* = concept g
|
||||
type N = Node
|
||||
distance(g, N, N) is float
|
||||
|
||||
Graph2 = concept g
|
||||
distance(g, Node, Node) is float
|
||||
|
||||
Graph3 = concept g
|
||||
var x: Node
|
||||
distance(g, x, x) is float
|
||||
|
||||
XY* = tuple[x, y: int]
|
||||
|
||||
MyGraph* = object
|
||||
points: seq[XY]
|
||||
|
||||
static:
|
||||
assert XY is Node
|
||||
|
||||
proc distance*( g: MyGraph, a, b: XY): float =
|
||||
sqrt( pow(float(a.x - b.x), 2) + pow(float(a.y - b.y), 2) )
|
||||
|
||||
static:
|
||||
assert MyGraph is Graph1
|
||||
assert MyGraph is Graph2
|
||||
assert MyGraph is Graph3
|
||||
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
|
||||
# bug #6691
|
||||
type
|
||||
ConceptA = concept c
|
||||
|
||||
ConceptB = concept c
|
||||
c.myProc(ConceptA)
|
||||
|
||||
Obj = object
|
||||
|
||||
proc myProc(obj: Obj, x: ConceptA) = discard
|
||||
|
||||
echo Obj is ConceptB
|
||||
421
tests/concepts/tissues.nim
Normal file
421
tests/concepts/tissues.nim
Normal file
|
|
@ -0,0 +1,421 @@
|
|||
discard """
|
||||
file: "tissues.nim"
|
||||
output: '''
|
||||
20.0 USD
|
||||
Printable
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
f
|
||||
0
|
||||
10
|
||||
10
|
||||
5
|
||||
()
|
||||
false
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
p has been called.
|
||||
p has been called.
|
||||
implicit generic
|
||||
generic
|
||||
false
|
||||
true
|
||||
-1
|
||||
Meow
|
||||
'''
|
||||
"""
|
||||
|
||||
import macros, typetraits
|
||||
|
||||
|
||||
block t5983:
|
||||
const currencies = ["USD", "EUR"] # in real code 120 currencies
|
||||
|
||||
type USD = distinct float # in real code 120 types generates using macro
|
||||
type EUR = distinct float
|
||||
|
||||
type CurrencyAmount = concept c
|
||||
type t = c.type
|
||||
const name = c.type.name
|
||||
name in currencies
|
||||
|
||||
proc `$`(x: CurrencyAmount): string =
|
||||
$float(x) & " " & x.name
|
||||
|
||||
let amount = 20.USD
|
||||
echo amount
|
||||
|
||||
|
||||
block t3414:
|
||||
type
|
||||
View[T] = concept v
|
||||
v.empty is bool
|
||||
v.front is T
|
||||
popFront v
|
||||
|
||||
proc find(view: View; target: View.T): View =
|
||||
result = view
|
||||
|
||||
while not result.empty:
|
||||
if view.front == target:
|
||||
return
|
||||
|
||||
mixin popFront
|
||||
popFront result
|
||||
|
||||
proc popFront[T](s: var seq[T]) = discard
|
||||
proc empty[T](s: seq[T]): bool = false
|
||||
|
||||
var s1 = @[1, 2, 3]
|
||||
let s2 = s1.find(10)
|
||||
|
||||
|
||||
|
||||
type
|
||||
Obj1[T] = object
|
||||
v: T
|
||||
converter toObj1[T](t: T): Obj1[T] =
|
||||
return Obj1[T](v: t)
|
||||
block t976:
|
||||
type
|
||||
int1 = distinct int
|
||||
int2 = distinct int
|
||||
int1g = concept x
|
||||
x is int1
|
||||
int2g = concept x
|
||||
x is int2
|
||||
|
||||
proc take[T: int1g](value: int1) =
|
||||
when T is int2:
|
||||
static: error("killed in take(int1)")
|
||||
|
||||
proc take[T: int2g](vale: int2) =
|
||||
when T is int1:
|
||||
static: error("killed in take(int2)")
|
||||
|
||||
var i1: int1 = 1.int1
|
||||
var i2: int2 = 2.int2
|
||||
|
||||
take[int1](i1)
|
||||
take[int2](i2)
|
||||
|
||||
template reject(e) =
|
||||
static: assert(not compiles(e))
|
||||
|
||||
reject take[string](i2)
|
||||
reject take[int1](i2)
|
||||
|
||||
# bug #6249
|
||||
type
|
||||
Obj2 = ref object
|
||||
PrintAble = concept x
|
||||
$x is string
|
||||
|
||||
proc `$`[T](nt: Obj1[T]): string =
|
||||
when T is PrintAble: result = "Printable"
|
||||
else: result = "Non Printable"
|
||||
|
||||
echo Obj2()
|
||||
|
||||
|
||||
|
||||
block t1128:
|
||||
type
|
||||
TFooContainer[T] = object
|
||||
|
||||
TContainer[T] = concept var c
|
||||
foo(c, T)
|
||||
|
||||
proc foo[T](c: var TFooContainer[T], val: T) =
|
||||
discard
|
||||
|
||||
proc bar(c: var TContainer) =
|
||||
discard
|
||||
|
||||
var fooContainer: TFooContainer[int]
|
||||
echo fooContainer is TFooContainer # true.
|
||||
echo fooContainer is TFooContainer[int] # true.
|
||||
fooContainer.bar()
|
||||
|
||||
|
||||
|
||||
block t5642:
|
||||
type DataTable = concept x
|
||||
x is object
|
||||
for f in fields(x):
|
||||
f is seq
|
||||
|
||||
type Students = object
|
||||
id : seq[int]
|
||||
name : seq[string]
|
||||
age: seq[int]
|
||||
|
||||
proc nrow(dt: DataTable) : Natural =
|
||||
var totalLen = 0
|
||||
for f in fields(dt):
|
||||
totalLen += f.len
|
||||
return totalLen
|
||||
|
||||
let
|
||||
stud = Students(id: @[1,2,3], name: @["Vas", "Pas", "NafNaf"], age: @[10,16,32])
|
||||
|
||||
doAssert nrow(stud) == 9
|
||||
|
||||
|
||||
|
||||
import t5888lib/ca, t5888lib/opt
|
||||
block t5888:
|
||||
type LocalCA = ca.CA
|
||||
|
||||
proc f(c: CA) =
|
||||
echo "f"
|
||||
echo c.x
|
||||
|
||||
var o = new(Opt)
|
||||
|
||||
echo o is CA
|
||||
echo o is LocalCA
|
||||
echo o is ca.CA
|
||||
|
||||
o.f()
|
||||
|
||||
|
||||
|
||||
import json
|
||||
block t5968:
|
||||
type
|
||||
Enumerable[T] = concept e
|
||||
for it in e:
|
||||
it is T
|
||||
|
||||
proc cmap[T, G](e: Enumerable[T], fn: proc(t: T): G): seq[G] =
|
||||
result = @[]
|
||||
for it in e: result.add(fn(it))
|
||||
|
||||
var x = %["hello", "world"]
|
||||
|
||||
var z = x.cmap(proc(it: JsonNode): string = it.getStr & "!")
|
||||
assert z == @["hello!", "world!"]
|
||||
|
||||
|
||||
|
||||
import sugar
|
||||
block t6462:
|
||||
type
|
||||
FilterMixin[T] = ref object
|
||||
test: (T) -> bool
|
||||
trans: (T) -> T
|
||||
|
||||
SeqGen[T] = ref object
|
||||
fil: FilterMixin[T]
|
||||
|
||||
WithFilter[T] = concept a
|
||||
a.fil is FilterMixin[T]
|
||||
|
||||
proc test[T](a: WithFilter[T]): (T) -> bool =
|
||||
a.fil.test
|
||||
|
||||
var s = SeqGen[int](fil: FilterMixin[int](test: nil, trans: nil))
|
||||
doAssert s.test() == nil
|
||||
|
||||
|
||||
|
||||
block t6770:
|
||||
type GA = concept c
|
||||
c.a is int
|
||||
|
||||
type A = object
|
||||
a: int
|
||||
|
||||
type AA = object
|
||||
case exists: bool
|
||||
of true:
|
||||
a: int
|
||||
else:
|
||||
discard
|
||||
|
||||
proc print(inp: GA) =
|
||||
echo inp.a
|
||||
|
||||
let failing = AA(exists: true, a: 10)
|
||||
let working = A(a:10)
|
||||
print(working)
|
||||
print(failing)
|
||||
|
||||
|
||||
|
||||
block t7952:
|
||||
type
|
||||
HasLen = concept iter
|
||||
len(iter) is int
|
||||
|
||||
proc echoLen(x: HasLen) =
|
||||
echo len(x)
|
||||
|
||||
echoLen([1, 2, 3, 4, 5])
|
||||
|
||||
|
||||
|
||||
block t8280:
|
||||
type
|
||||
Iterable[T] = concept x
|
||||
for elem in x:
|
||||
elem is T
|
||||
|
||||
proc max[A](iter: Iterable[A]): A =
|
||||
discard
|
||||
|
||||
type
|
||||
MyType = object
|
||||
|
||||
echo max(@[MyType()])
|
||||
|
||||
|
||||
|
||||
import math
|
||||
block t3452:
|
||||
type
|
||||
Node = concept n
|
||||
`==`(n, n) is bool
|
||||
Graph1 = concept g
|
||||
type N = Node
|
||||
distance(g, N, N) is float
|
||||
Graph2 = concept g
|
||||
distance(g, Node, Node) is float
|
||||
Graph3 = concept g
|
||||
var x: Node
|
||||
distance(g, x, x) is float
|
||||
XY = tuple[x, y: int]
|
||||
MyGraph = object
|
||||
points: seq[XY]
|
||||
|
||||
static:
|
||||
assert XY is Node
|
||||
|
||||
proc distance( g: MyGraph, a, b: XY): float =
|
||||
sqrt( pow(float(a.x - b.x), 2) + pow(float(a.y - b.y), 2) )
|
||||
|
||||
static:
|
||||
assert MyGraph is Graph1
|
||||
assert MyGraph is Graph2
|
||||
assert MyGraph is Graph3
|
||||
|
||||
|
||||
|
||||
block t6691:
|
||||
type
|
||||
ConceptA = concept c
|
||||
ConceptB = concept c
|
||||
c.myProc(ConceptA)
|
||||
Obj = object
|
||||
|
||||
proc myProc(obj: Obj, x: ConceptA) = discard
|
||||
|
||||
echo Obj is ConceptB
|
||||
|
||||
|
||||
|
||||
block misc_issues:
|
||||
# https://github.com/nim-lang/Nim/issues/1147
|
||||
type TTest = object
|
||||
vals: seq[int]
|
||||
|
||||
proc add(self: var TTest, val: int) =
|
||||
self.vals.add(val)
|
||||
|
||||
type CAddable = concept x
|
||||
x[].add(int)
|
||||
|
||||
echo((ref TTest) is CAddable) # true
|
||||
|
||||
# https://github.com/nim-lang/Nim/issues/1570
|
||||
type ConcretePointOfFloat = object
|
||||
x, y: float
|
||||
|
||||
type ConcretePoint[Value] = object
|
||||
x, y: Value
|
||||
|
||||
type AbstractPointOfFloat = concept p
|
||||
p.x is float and p.y is float
|
||||
|
||||
let p1 = ConcretePointOfFloat(x: 0, y: 0)
|
||||
let p2 = ConcretePoint[float](x: 0, y: 0)
|
||||
|
||||
echo p1 is AbstractPointOfFloat # true
|
||||
echo p2 is AbstractPointOfFloat # true
|
||||
echo p2.x is float and p2.y is float # true
|
||||
|
||||
# https://github.com/nim-lang/Nim/issues/2018
|
||||
type ProtocolFollower = concept
|
||||
true # not a particularly involved protocol
|
||||
|
||||
type ImplementorA = object
|
||||
type ImplementorB = object
|
||||
|
||||
proc p[A: ProtocolFollower, B: ProtocolFollower](a: A, b: B) =
|
||||
echo "p has been called."
|
||||
|
||||
p(ImplementorA(), ImplementorA())
|
||||
p(ImplementorA(), ImplementorB())
|
||||
|
||||
# https://github.com/nim-lang/Nim/issues/2423
|
||||
proc put[T](c: seq[T], x: T) = echo "generic"
|
||||
proc put(c: seq) = echo "implicit generic"
|
||||
|
||||
type
|
||||
Container[T] = concept c
|
||||
put(c)
|
||||
put(c, T)
|
||||
|
||||
proc c1(x: Container) = echo "implicit generic"
|
||||
c1(@[1])
|
||||
|
||||
proc c2[T](x: Container[T]) = echo "generic"
|
||||
c2(@[1])
|
||||
|
||||
# https://github.com/nim-lang/Nim/issues/2882
|
||||
type
|
||||
Paper = object
|
||||
name: string
|
||||
|
||||
Bendable = concept x
|
||||
bend(x is Bendable)
|
||||
|
||||
proc bend(p: Paper): Paper = Paper(name: "bent-" & p.name)
|
||||
|
||||
var paper = Paper(name: "red")
|
||||
echo paper is Bendable
|
||||
|
||||
type
|
||||
A = concept self
|
||||
size(self) is int
|
||||
|
||||
B = object
|
||||
|
||||
proc size(self: B): int =
|
||||
return -1
|
||||
|
||||
proc size(self: A): int =
|
||||
return 0
|
||||
|
||||
let b = B()
|
||||
echo b is A
|
||||
echo b.size()
|
||||
|
||||
# https://github.com/nim-lang/Nim/issues/7125
|
||||
type
|
||||
Thing = concept x
|
||||
x.hello is string
|
||||
Cat = object
|
||||
|
||||
proc hello(d: Cat): string = "Meow"
|
||||
|
||||
proc sayHello(c: Thing) = echo(c.hello)
|
||||
|
||||
var a: Thing = Cat()
|
||||
a.sayHello()
|
||||
|
|
@ -1,113 +0,0 @@
|
|||
discard """
|
||||
output: '''true
|
||||
true
|
||||
true
|
||||
true
|
||||
p has been called.
|
||||
p has been called.
|
||||
implicit generic
|
||||
generic
|
||||
false
|
||||
true
|
||||
-1
|
||||
Meow'''
|
||||
"""
|
||||
|
||||
# https://github.com/nim-lang/Nim/issues/1147
|
||||
type TTest = object
|
||||
vals: seq[int]
|
||||
|
||||
proc add*(self: var TTest, val: int) =
|
||||
self.vals.add(val)
|
||||
|
||||
type CAddable = concept x
|
||||
x[].add(int)
|
||||
|
||||
echo((ref TTest) is CAddable) # true
|
||||
|
||||
# https://github.com/nim-lang/Nim/issues/1570
|
||||
type ConcretePointOfFloat = object
|
||||
x, y: float
|
||||
|
||||
type ConcretePoint[Value] = object
|
||||
x, y: Value
|
||||
|
||||
type AbstractPointOfFloat = concept p
|
||||
p.x is float and p.y is float
|
||||
|
||||
let p1 = ConcretePointOfFloat(x: 0, y: 0)
|
||||
let p2 = ConcretePoint[float](x: 0, y: 0)
|
||||
|
||||
echo p1 is AbstractPointOfFloat # true
|
||||
echo p2 is AbstractPointOfFloat # true
|
||||
echo p2.x is float and p2.y is float # true
|
||||
|
||||
# https://github.com/nim-lang/Nim/issues/2018
|
||||
type ProtocolFollower = concept
|
||||
true # not a particularly involved protocol
|
||||
|
||||
type ImplementorA = object
|
||||
type ImplementorB = object
|
||||
|
||||
proc p[A: ProtocolFollower, B: ProtocolFollower](a: A, b: B) =
|
||||
echo "p has been called."
|
||||
|
||||
p(ImplementorA(), ImplementorA())
|
||||
p(ImplementorA(), ImplementorB())
|
||||
|
||||
# https://github.com/nim-lang/Nim/issues/2423
|
||||
proc put*[T](c: seq[T], x: T) = echo "generic"
|
||||
proc put*(c: seq) = echo "implicit generic"
|
||||
|
||||
type
|
||||
Container[T] = concept c
|
||||
put(c)
|
||||
put(c, T)
|
||||
|
||||
proc c1(x: Container) = echo "implicit generic"
|
||||
c1(@[1])
|
||||
|
||||
proc c2[T](x: Container[T]) = echo "generic"
|
||||
c2(@[1])
|
||||
|
||||
# https://github.com/nim-lang/Nim/issues/2882
|
||||
type
|
||||
Paper = object
|
||||
name: string
|
||||
|
||||
Bendable = concept x
|
||||
bend(x is Bendable)
|
||||
|
||||
proc bend(p: Paper): Paper = Paper(name: "bent-" & p.name)
|
||||
|
||||
var paper = Paper(name: "red")
|
||||
echo paper is Bendable
|
||||
|
||||
type
|
||||
A = concept self
|
||||
size(self) is int
|
||||
|
||||
B = object
|
||||
|
||||
proc size(self: B): int =
|
||||
return -1
|
||||
|
||||
proc size(self: A): int =
|
||||
return 0
|
||||
|
||||
let b = B()
|
||||
echo b is A
|
||||
echo b.size()
|
||||
|
||||
# https://github.com/nim-lang/Nim/issues/7125
|
||||
type
|
||||
Thing = concept x
|
||||
x.hello is string
|
||||
Cat = object
|
||||
|
||||
proc hello(d: Cat): string = "Meow"
|
||||
|
||||
proc sayHello(c: Thing) = echo(c.hello)
|
||||
|
||||
var a: Thing = Cat()
|
||||
a.sayHello()
|
||||
Loading…
Add table
Add a link
Reference in a new issue