mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-01 19:02:18 +00:00
* Add testcase This tries to use a concept with a doc comment which currently leads to a segfault * Ignore nil nodes which happen when there are doc comments in new style concept This was done instead of semming the comments since `semConceptDecl` says it only supports lists of actual statements * Go with alternative fix: Sem comments but ignore them Since `nil` could mean anything it is best to not silently ignore it (In case another nil problem happens in future Also fix test case so it isn't an infinite loop
452 lines
8.0 KiB
Nim
452 lines
8.0 KiB
Nim
discard """
|
|
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
|
|
9
|
|
'''
|
|
"""
|
|
|
|
|
|
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 c
|
|
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)
|
|
|
|
block tcomment:
|
|
type
|
|
Foo = concept
|
|
## Some comment
|
|
proc bar(x: Self)
|
|
|
|
proc bar(x: int) = echo x
|
|
proc foo(x: Foo) = x.bar
|
|
foo(9)
|