Merge remote-tracking branch 'origin/concepts-rebased' into araq
This commit is contained in:
commit
529609f7ed
47 changed files with 2038 additions and 345 deletions
15
tests/concepts/matrix.nim
Normal file
15
tests/concepts/matrix.nim
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
type
|
||||
Matrix*[M, N: static[int]; T] = object
|
||||
data: array[M*N, T]
|
||||
|
||||
proc `[]`*(M: Matrix; m, n: int): M.T =
|
||||
M.data[m * M.N + n]
|
||||
|
||||
proc `[]=`*(M: var Matrix; m, n: int; v: M.T) =
|
||||
M.data[m * M.N + n] = v
|
||||
|
||||
# Adapt the Matrix type to the concept's requirements
|
||||
template Rows*(M: type Matrix): expr = M.M
|
||||
template Cols*(M: type Matrix): expr = M.N
|
||||
template ValueType*(M: type Matrix): typedesc = M.T
|
||||
|
||||
28
tests/concepts/matrixalgo.nim
Normal file
28
tests/concepts/matrixalgo.nim
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
import typetraits
|
||||
|
||||
type
|
||||
AnyMatrix*[R, C: static[int]; T] = concept m, var mvar, type M
|
||||
M.ValueType is T
|
||||
M.Rows == R
|
||||
M.Cols == C
|
||||
|
||||
m[int, int] is T
|
||||
mvar[int, int] = T
|
||||
|
||||
type TransposedType = stripGenericParams(M)[C, R, T]
|
||||
|
||||
AnySquareMatrix*[N: static[int], T] = AnyMatrix[N, N, T]
|
||||
|
||||
AnyTransform3D* = AnyMatrix[4, 4, float]
|
||||
|
||||
proc transposed*(m: AnyMatrix): m.TransposedType =
|
||||
for r in 0 .. <m.R:
|
||||
for c in 0 .. <m.C:
|
||||
result[r, c] = m[c, r]
|
||||
|
||||
proc determinant*(m: AnySquareMatrix): int =
|
||||
return 0
|
||||
|
||||
proc setPerspectiveProjection*(m: AnyTransform3D) =
|
||||
discard
|
||||
|
||||
21
tests/concepts/t1128.nim
Normal file
21
tests/concepts/t1128.nim
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
discard """
|
||||
output: "true\ntrue"
|
||||
"""
|
||||
|
||||
type
|
||||
TFooContainer[T] = object
|
||||
|
||||
TContainer[T] = generic 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()
|
||||
|
||||
41
tests/concepts/t3330.nim
Normal file
41
tests/concepts/t3330.nim
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
discard """
|
||||
errormsg: "type mismatch: got (Bar[system.int])"
|
||||
nimout: '''
|
||||
t3330.nim(40, 4) Error: type mismatch: got (Bar[system.int])
|
||||
but expected one of:
|
||||
proc test(foo: Foo[int])
|
||||
t3330.nim(25, 8) Hint: Non-matching candidates for add(k, string, T)
|
||||
proc add[T](x: var seq[T]; y: T)
|
||||
proc add(result: var string; x: float)
|
||||
proc add(x: var string; y: string)
|
||||
proc add(x: var string; y: cstring)
|
||||
proc add(x: var string; y: char)
|
||||
proc add(result: var string; x: int64)
|
||||
proc add[T](x: var seq[T]; y: openArray[T])
|
||||
|
||||
t3330.nim(25, 8) template/generic instantiation from here
|
||||
t3330.nim(32, 6) Foo: 'bar.value' cannot be assigned to
|
||||
t3330.nim(25, 8) template/generic instantiation from here
|
||||
t3330.nim(33, 6) Foo: 'bar.x' cannot be assigned to
|
||||
'''
|
||||
"""
|
||||
|
||||
type
|
||||
Foo[T] = concept k
|
||||
add(k, string, T)
|
||||
|
||||
Bar[T] = object
|
||||
value: T
|
||||
x: string
|
||||
|
||||
proc add[T](bar: Bar[T], x: string, val: T) =
|
||||
bar.value = val
|
||||
bar.x = x
|
||||
|
||||
proc test(foo: Foo[int]) =
|
||||
foo.add("test", 42)
|
||||
echo(foo.x)
|
||||
|
||||
var bar = Bar[int]()
|
||||
bar.test()
|
||||
|
||||
32
tests/concepts/t976.nim
Normal file
32
tests/concepts/t976.nim
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
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)
|
||||
|
||||
69
tests/concepts/tconcepts_overload_precedence.nim
Normal file
69
tests/concepts/tconcepts_overload_precedence.nim
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
discard """
|
||||
output: '''x as ParameterizedType[T]
|
||||
x as ParameterizedType[T]
|
||||
x as ParameterizedType[T]
|
||||
x as ParameterizedType
|
||||
x as ParameterizedType
|
||||
x as CustomTypeClass'''
|
||||
"""
|
||||
|
||||
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]())
|
||||
|
||||
120
tests/concepts/texplain.nim
Normal file
120
tests/concepts/texplain.nim
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
discard """
|
||||
cmd: "nim c --verbosity:0 --colors:off $file"
|
||||
nimout: '''
|
||||
texplain.nim(99, 10) Hint: Non-matching candidates for e(y)
|
||||
proc e(i: int): int
|
||||
|
||||
texplain.nim(102, 7) Hint: Non-matching candidates for e(10)
|
||||
proc e(o: ExplainedConcept): int
|
||||
texplain.nim(65, 6) ExplainedConcept: undeclared field: 'foo'
|
||||
texplain.nim(65, 6) ExplainedConcept: undeclared field: '.'
|
||||
texplain.nim(65, 6) ExplainedConcept: expression '.' cannot be called
|
||||
texplain.nim(65, 5) ExplainedConcept: type class predicate failed
|
||||
texplain.nim(66, 6) ExplainedConcept: undeclared field: 'bar'
|
||||
texplain.nim(66, 6) ExplainedConcept: undeclared field: '.'
|
||||
texplain.nim(66, 6) ExplainedConcept: expression '.' cannot be called
|
||||
texplain.nim(65, 5) ExplainedConcept: type class predicate failed
|
||||
|
||||
texplain.nim(105, 10) Hint: Non-matching candidates for e(10)
|
||||
proc e(o: ExplainedConcept): int
|
||||
texplain.nim(65, 6) ExplainedConcept: undeclared field: 'foo'
|
||||
texplain.nim(65, 6) ExplainedConcept: undeclared field: '.'
|
||||
texplain.nim(65, 6) ExplainedConcept: expression '.' cannot be called
|
||||
texplain.nim(65, 5) ExplainedConcept: type class predicate failed
|
||||
texplain.nim(66, 6) ExplainedConcept: undeclared field: 'bar'
|
||||
texplain.nim(66, 6) ExplainedConcept: undeclared field: '.'
|
||||
texplain.nim(66, 6) ExplainedConcept: expression '.' cannot be called
|
||||
texplain.nim(65, 5) ExplainedConcept: type class predicate failed
|
||||
|
||||
texplain.nim(109, 20) Error: type mismatch: got (NonMatchingType)
|
||||
but expected one of:
|
||||
proc e(o: ExplainedConcept): int
|
||||
texplain.nim(65, 5) ExplainedConcept: type class predicate failed
|
||||
proc e(i: int): int
|
||||
|
||||
texplain.nim(110, 20) Error: type mismatch: got (NonMatchingType)
|
||||
but expected one of:
|
||||
proc r(o: RegularConcept): int
|
||||
texplain.nim(69, 5) RegularConcept: type class predicate failed
|
||||
proc r[T](a: SomeNumber; b: T; c: auto)
|
||||
proc r(i: string): int
|
||||
|
||||
texplain.nim(111, 20) Hint: Non-matching candidates for r(y)
|
||||
proc r[T](a: SomeNumber; b: T; c: auto)
|
||||
proc r(i: string): int
|
||||
|
||||
texplain.nim(119, 2) Error: type mismatch: got (MatchingType)
|
||||
but expected one of:
|
||||
proc f(o: NestedConcept)
|
||||
texplain.nim(69, 6) RegularConcept: undeclared field: 'foo'
|
||||
texplain.nim(69, 6) RegularConcept: undeclared field: '.'
|
||||
texplain.nim(69, 6) RegularConcept: expression '.' cannot be called
|
||||
texplain.nim(69, 5) RegularConcept: type class predicate failed
|
||||
texplain.nim(70, 6) RegularConcept: undeclared field: 'bar'
|
||||
texplain.nim(70, 6) RegularConcept: undeclared field: '.'
|
||||
texplain.nim(70, 6) RegularConcept: expression '.' cannot be called
|
||||
texplain.nim(69, 5) RegularConcept: type class predicate failed
|
||||
texplain.nim(73, 5) NestedConcept: type class predicate failed
|
||||
'''
|
||||
line: 119
|
||||
errormsg: "type mismatch: got (MatchingType)"
|
||||
"""
|
||||
|
||||
type
|
||||
ExplainedConcept {.explain.} = concept o
|
||||
o.foo is int
|
||||
o.bar is string
|
||||
|
||||
RegularConcept = concept o
|
||||
o.foo is int
|
||||
o.bar is string
|
||||
|
||||
NestedConcept = concept o
|
||||
o.foo is RegularConcept
|
||||
|
||||
NonMatchingType = object
|
||||
foo: int
|
||||
bar: int
|
||||
|
||||
MatchingType = object
|
||||
foo: int
|
||||
bar: string
|
||||
|
||||
proc e(o: ExplainedConcept): int = 1
|
||||
proc e(i: int): int = i
|
||||
|
||||
proc r[T](a: SomeNumber, b: T, c: auto) = discard
|
||||
proc r(o: RegularConcept): int = 1
|
||||
proc r(i: string): int = 1
|
||||
|
||||
proc f(o: NestedConcept) = discard
|
||||
|
||||
var n = NonMatchingType(foo: 10, bar: 20)
|
||||
var y = MatchingType(foo: 10, bar: "bar")
|
||||
|
||||
# no diagnostic here:
|
||||
discard e(y)
|
||||
|
||||
# explain that e(int) doesn't match
|
||||
discard e(y) {.explain.}
|
||||
|
||||
# explain that e(ExplainedConcept) doesn't match
|
||||
echo(e(10) {.explain.}, 20)
|
||||
|
||||
# explain that e(ExplainedConcept) doesn't again
|
||||
discard e(10)
|
||||
|
||||
static:
|
||||
# provide diagnostics why the compile block failed
|
||||
assert(compiles(e(n)) {.explain.} == false)
|
||||
assert(compiles(r(n)) {.explain.} == false)
|
||||
assert(compiles(r(y)) {.explain.} == true)
|
||||
|
||||
# these should not produce any output
|
||||
assert(compiles(r(10)) == false)
|
||||
assert(compiles(e(10)) == true)
|
||||
|
||||
# finally, provide multiple nested explanations for failed matching
|
||||
# of regular concepts, even when the explain pragma is not used
|
||||
f(y)
|
||||
|
||||
102
tests/concepts/tmapconcept.nim
Normal file
102
tests/concepts/tmapconcept.nim
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
discard """
|
||||
output: '''10
|
||||
10
|
||||
nil
|
||||
1'''
|
||||
msg: '''
|
||||
K=string V=int
|
||||
K=int64 V=string
|
||||
K=int V=int
|
||||
'''
|
||||
"""
|
||||
|
||||
import tables, typetraits
|
||||
|
||||
template ok(check) = assert check
|
||||
template no(check) = assert(not check)
|
||||
|
||||
type
|
||||
Enumerable[T] = concept e
|
||||
for v in e:
|
||||
v is T
|
||||
|
||||
Map[K, V] = concept m, var mvar
|
||||
m[K] is V
|
||||
mvar[K] = V
|
||||
m.contains(K) is bool
|
||||
m.valuesSeq is Enumerable[V]
|
||||
|
||||
TreeMap[K, V] = object
|
||||
root: int
|
||||
|
||||
SparseSeq = object
|
||||
data: seq[int]
|
||||
|
||||
JudyArray = object
|
||||
data: SparseSeq
|
||||
|
||||
static:
|
||||
ok seq[int] is Enumerable[int]
|
||||
ok seq[string] is Enumerable
|
||||
ok seq[int] is Enumerable[SomeNumber]
|
||||
ok SparseSeq.data is Enumerable
|
||||
no seq[string] is Enumerable[int]
|
||||
no int is Enumerable
|
||||
no int is Enumerable[int]
|
||||
|
||||
# Complete the map concept implementation for the Table type
|
||||
proc valuesSeq[K, V](t: Table[K, V]): seq[V] =
|
||||
result = @[]
|
||||
for k, v in t:
|
||||
result.add v
|
||||
|
||||
# Map concept inplementation for TreeMap
|
||||
proc valuesSeq(t: TreeMap): array[1, TreeMap.V] =
|
||||
var v: t.V
|
||||
result = [v]
|
||||
|
||||
proc contains[K, V](t: TreeMap[K, V], key: K): bool = true
|
||||
|
||||
proc `[]=`[K, V](t: var TreeMap[K, V], key: K, val: V) = discard
|
||||
proc `[]`(t: TreeMap, key: t.K): TreeMap.V = discard
|
||||
|
||||
# Map concept implementation for the non-generic JudyArray
|
||||
proc valuesSeq(j: JudyArray): SparseSeq = j.data
|
||||
|
||||
proc contains(t: JudyArray, key: int): bool = true
|
||||
|
||||
proc `[]=`(t: var JudyArray, key, val: int) = discard
|
||||
proc `[]`(t: JudyArray, key: int): int = discard
|
||||
|
||||
iterator items(s: SparseSeq): int =
|
||||
for i in s.data: yield i
|
||||
|
||||
# Generic proc defined over map
|
||||
proc getFirstValue[K,V](m : Map[K,V]): V =
|
||||
static: echo "K=", K.name, " V=", V.name
|
||||
|
||||
for i in m.valuesSeq:
|
||||
return i
|
||||
|
||||
raise newException(RangeError, "no values")
|
||||
|
||||
proc useConceptProcInGeneric[K, V](t: Table[K, V]): V =
|
||||
return t.getFirstValue
|
||||
|
||||
var t = initTable[string, int]()
|
||||
t["test"] = 10
|
||||
|
||||
echo t.getFirstValue
|
||||
echo t.useConceptProcInGeneric
|
||||
|
||||
var tm = TreeMap[int64, string](root: 0)
|
||||
echo getFirstValue(tm)
|
||||
|
||||
var j = JudyArray(data: SparseSeq(data: @[1, 2, 3]))
|
||||
echo getFirstValue(j)
|
||||
|
||||
static:
|
||||
ok Table[int, float] is Map
|
||||
ok Table[int, string] is Map[SomeNumber, string]
|
||||
no JudyArray is Map[string, int]
|
||||
|
||||
81
tests/concepts/tmatrixconcept.nim
Normal file
81
tests/concepts/tmatrixconcept.nim
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
discard """
|
||||
output: "0\n0\n0"
|
||||
msg: '''
|
||||
R=3 C=3 TE=9 FF=14 FC=20 T=int
|
||||
R=3 C=3 T=int
|
||||
'''
|
||||
"""
|
||||
|
||||
import typetraits
|
||||
|
||||
template ok(x) = assert x
|
||||
template no(x) = assert(not x)
|
||||
|
||||
const C = 10
|
||||
|
||||
type
|
||||
Matrix[Rows, Cols, TotalElements, FromFoo, FromConst: static[int]; T] = concept m, var mvar, type M
|
||||
M.M == Rows
|
||||
Cols == M.N
|
||||
M.T is T
|
||||
|
||||
m[int, int] is T
|
||||
mvar[int, int] = T
|
||||
|
||||
FromConst == C * 2
|
||||
|
||||
# more complicated static param inference cases
|
||||
m.data is array[TotalElements, T]
|
||||
m.foo(array[0..FromFoo, type m[int, 10]])
|
||||
|
||||
MyMatrix[M, K: static[int]; T] = object
|
||||
data: array[M*K, T]
|
||||
|
||||
# adaptor for the concept's non-matching expectations
|
||||
template N(M: type MyMatrix): expr = M.K
|
||||
|
||||
proc `[]`(m: MyMatrix; r, c: int): m.T =
|
||||
m.data[r * m.K + c]
|
||||
|
||||
proc `[]=`(m: var MyMatrix; r, c: int, v: m.T) =
|
||||
m.data[r * m.K + c] = v
|
||||
|
||||
proc foo(x: MyMatrix, arr: array[15, x.T]) = discard
|
||||
|
||||
proc genericMatrixProc[R, C, TE, FF, FC, T](m: Matrix[R, C, TE, FF, FC, T]): T =
|
||||
static:
|
||||
echo "R=", R, " C=", C, " TE=", TE, " FF=", FF, " FC=", FC, " T=", T.name
|
||||
|
||||
m[0, 0]
|
||||
|
||||
proc implicitMatrixProc(m: Matrix): m.T =
|
||||
static:
|
||||
echo "R=", m.Rows,
|
||||
" C=", m.Cols,
|
||||
# XXX: fix these
|
||||
#" TE=", m.TotalElements,
|
||||
#" FF=", m.FromFoo,
|
||||
#" FC=", m.FromConst,
|
||||
" T=", m.T.name
|
||||
|
||||
m[0, 0]
|
||||
|
||||
proc myMatrixProc(x: MyMatrix): MyMatrix.T = genericMatrixProc(x)
|
||||
|
||||
var x: MyMatrix[3, 3, int]
|
||||
|
||||
static:
|
||||
# ok x is Matrix
|
||||
ok x is Matrix[3, 3, 9, 14, 20, int]
|
||||
|
||||
no x is Matrix[3, 3, 8, 15, 20, int]
|
||||
no x is Matrix[3, 3, 9, 10, 20, int]
|
||||
no x is Matrix[3, 3, 9, 15, 21, int]
|
||||
no x is Matrix[3, 3, 9, 15, 20, float]
|
||||
no x is Matrix[4, 3, 9, 15, 20, int]
|
||||
no x is Matrix[3, 4, 9, 15, 20, int]
|
||||
|
||||
echo x.myMatrixProc
|
||||
echo x.genericMatrixProc
|
||||
echo x.implicitMatrixProc
|
||||
|
||||
31
tests/concepts/tmatrixlib.nim
Normal file
31
tests/concepts/tmatrixlib.nim
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
discard """
|
||||
output: "0"
|
||||
"""
|
||||
|
||||
import matrix, matrixalgo
|
||||
|
||||
import typetraits # XXX: this should be removed
|
||||
|
||||
var m: Matrix[3, 3, int]
|
||||
var projectionMatrix: Matrix[4, 4, float]
|
||||
|
||||
echo m.transposed.determinant
|
||||
setPerspectiveProjection projectionMatrix
|
||||
|
||||
template ok(x) = assert x
|
||||
template no(x) = assert(not x)
|
||||
|
||||
static:
|
||||
ok projectionMatrix is AnyTransform3D
|
||||
no m is AnyTransform3D
|
||||
|
||||
type SquareStringMatrix = Matrix[5, 5, string]
|
||||
|
||||
ok SquareStringMatrix is AnyMatrix
|
||||
ok SquareStringMatrix is AnySquareMatrix
|
||||
no SquareStringMatrix is AnyTransform3D
|
||||
|
||||
ok Matrix[5, 10, int] is AnyMatrix
|
||||
no Matrix[7, 15, float] is AnySquareMatrix
|
||||
no Matrix[4, 4, int] is AnyTransform3D
|
||||
|
||||
100
tests/concepts/tmisc_issues.nim
Normal file
100
tests/concepts/tmisc_issues.nim
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
discard """
|
||||
output: '''true
|
||||
true
|
||||
true
|
||||
true
|
||||
p has been called.
|
||||
p has been called.
|
||||
implicit generic
|
||||
generic
|
||||
false
|
||||
true
|
||||
-1'''
|
||||
"""
|
||||
|
||||
# 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 = generic 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 = generic
|
||||
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()
|
||||
|
||||
63
tests/concepts/tstackconcept.nim
Normal file
63
tests/concepts/tstackconcept.nim
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
discard """
|
||||
output: "20\n10"
|
||||
msg: '''
|
||||
INFERRED int
|
||||
VALUE TYPE int
|
||||
VALUE TYPE NAME INT
|
||||
IMPLICIT INFERRED int int
|
||||
IMPLICIT VALUE TYPE int int
|
||||
IMPLICIT VALUE TYPE NAME INT INT
|
||||
'''
|
||||
"""
|
||||
|
||||
import typetraits, strutils
|
||||
|
||||
template reject(e: expr) =
|
||||
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.toUpper
|
||||
|
||||
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)
|
||||
|
||||
|
|
@ -2,20 +2,22 @@ discard """
|
|||
output: '''Sortable
|
||||
Sortable
|
||||
Container
|
||||
true
|
||||
true
|
||||
false
|
||||
false
|
||||
false
|
||||
TObj
|
||||
int
|
||||
'''
|
||||
"""
|
||||
|
||||
import typetraits
|
||||
|
||||
template reject(expr) = assert(not compiles(x))
|
||||
|
||||
type
|
||||
TObj = object
|
||||
x: int
|
||||
|
||||
JSonValue = object
|
||||
val: string
|
||||
|
||||
Sortable = concept x, y
|
||||
(x < y) is bool
|
||||
|
||||
|
|
@ -23,7 +25,7 @@ type
|
|||
C.len is Ordinal
|
||||
for v in items(C):
|
||||
v.type is tuple|object
|
||||
|
||||
|
||||
proc foo(c: ObjectContainer) =
|
||||
echo "Container"
|
||||
|
||||
|
|
@ -36,33 +38,62 @@ foo(@[TObj(x: 10), TObj(x: 20)])
|
|||
|
||||
proc intval(x: int): int = 10
|
||||
|
||||
# check real and virtual fields
|
||||
type
|
||||
TFoo = concept T
|
||||
T.x
|
||||
y(T)
|
||||
intval T.y
|
||||
let z = intval(T.y)
|
||||
TFoo = concept o, type T, ref r, var v, ptr p, static s
|
||||
o.x
|
||||
y(o) is int
|
||||
|
||||
var str: string
|
||||
var intref: ref int
|
||||
|
||||
refproc(ref T, ref int)
|
||||
varproc(var T)
|
||||
ptrproc(ptr T, str)
|
||||
|
||||
staticproc(static[T])
|
||||
|
||||
typeproc T
|
||||
T.typeproc
|
||||
typeproc o.type
|
||||
o.type.typeproc
|
||||
|
||||
o.to(type string)
|
||||
o.to(type JsonValue)
|
||||
|
||||
refproc(r, intref)
|
||||
varproc(v)
|
||||
p.ptrproc(string)
|
||||
staticproc s
|
||||
typeproc(T)
|
||||
|
||||
const TypeName = T.name
|
||||
type MappedType = type(o.y)
|
||||
|
||||
intval y(o)
|
||||
let z = intval(o.y)
|
||||
|
||||
static:
|
||||
assert T.name.len == 4
|
||||
reject o.name
|
||||
reject o.typeproc
|
||||
reject staticproc(o)
|
||||
reject o.varproc
|
||||
reject T.staticproc
|
||||
reject p.staticproc
|
||||
|
||||
proc y(x: TObj): int = 10
|
||||
|
||||
proc testFoo(x: TFoo) = discard
|
||||
proc varproc(x: var TObj) = discard
|
||||
proc refproc(x: ref TObj, y: ref int) = discard
|
||||
proc ptrproc(x: ptr TObj, y: string) = discard
|
||||
proc staticproc(x: static[TObj]) = discard
|
||||
proc typeproc(t: type TObj) = discard
|
||||
proc to(x: TObj, t: type string) = discard
|
||||
proc to(x: TObj, t: type JSonValue) = discard
|
||||
|
||||
proc testFoo(x: TFoo) =
|
||||
echo x.TypeName
|
||||
echo x.MappedType.name
|
||||
|
||||
testFoo(TObj(x: 10))
|
||||
|
||||
type
|
||||
Matrix[Rows, Cols: static[int]; T] = concept M
|
||||
M.M == Rows
|
||||
M.N == Cols
|
||||
M.T is T
|
||||
|
||||
MyMatrix[M, N: static[int]; T] = object
|
||||
data: array[M*N, T]
|
||||
|
||||
var x: MyMatrix[3, 3, int]
|
||||
|
||||
echo x is Matrix
|
||||
echo x is Matrix[3, 3, int]
|
||||
echo x is Matrix[3, 3, float]
|
||||
echo x is Matrix[4, 3, int]
|
||||
echo x is Matrix[3, 4, int]
|
||||
|
||||
|
|
|
|||
15
tests/concepts/tvectorspace.nim
Normal file
15
tests/concepts/tvectorspace.nim
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
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
|
||||
|
||||
29
tests/generics/tgenericdotrettype.nim
Normal file
29
tests/generics/tgenericdotrettype.nim
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
discard """
|
||||
output: '''string
|
||||
int
|
||||
(int, string)
|
||||
'''
|
||||
"""
|
||||
|
||||
import typetraits
|
||||
|
||||
type
|
||||
Foo[T, U] = object
|
||||
x: T
|
||||
y: U
|
||||
|
||||
proc bar[T](a: T): T.U =
|
||||
echo result.type.name
|
||||
|
||||
proc bas(x: auto): x.T =
|
||||
echo result.type.name
|
||||
|
||||
proc baz(x: Foo): (Foo.T, x.U) =
|
||||
echo result.type.name
|
||||
|
||||
var
|
||||
f: Foo[int, string]
|
||||
x = bar f
|
||||
z = bas f
|
||||
y = baz f
|
||||
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
discard """
|
||||
line: 28
|
||||
nimout: '''tgc_unsafe2.nim(22, 5) Warning: 'trick' is not GC-safe as it accesses 'global' which is a global using GC'ed memory
|
||||
tgc_unsafe2.nim(26, 5) Warning: 'track' is not GC-safe as it calls 'trick'
|
||||
tgc_unsafe2.nim(28, 5) Error: 'consumer' is not GC-safe as it calls 'track'
|
||||
nimout: '''tgc_unsafe2.nim(22, 6) Warning: 'trick' is not GC-safe as it accesses 'global' which is a global using GC'ed memory [GcUnsafe2]
|
||||
tgc_unsafe2.nim(26, 6) Warning: 'track' is not GC-safe as it calls 'trick' [GcUnsafe2]
|
||||
tgc_unsafe2.nim(28, 6) Error: 'consumer' is not GC-safe as it calls 'track'
|
||||
'''
|
||||
errormsg: "'consumer' is not GC-safe as it calls 'track'"
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -63,6 +63,8 @@ let
|
|||
|
||||
var targets = {low(TTarget)..high(TTarget)}
|
||||
|
||||
proc normalizeMsg(s: string): string = s.strip.replace("\C\L", "\L")
|
||||
|
||||
proc callCompiler(cmdTemplate, filename, options: string,
|
||||
target: TTarget): TSpec =
|
||||
let c = parseCmdLine(cmdTemplate % ["target", targetToCmd[target],
|
||||
|
|
@ -184,6 +186,8 @@ proc addResult(r: var TResults, test: TTest,
|
|||
proc cmpMsgs(r: var TResults, expected, given: TSpec, test: TTest) =
|
||||
if strip(expected.msg) notin strip(given.msg):
|
||||
r.addResult(test, expected.msg, given.msg, reMsgsDiffer)
|
||||
elif expected.nimout.len > 0 and expected.nimout.normalizeMsg notin given.nimout.normalizeMsg:
|
||||
r.addResult(test, expected.nimout, given.nimout, reMsgsDiffer)
|
||||
elif expected.tfile == "" and extractFilename(expected.file) != extractFilename(given.file) and
|
||||
"internal error:" notin expected.msg:
|
||||
r.addResult(test, expected.file, given.file, reFilesDiffer)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue