diff options
Diffstat (limited to 'tests/concepts/tconcepts.nim')
-rw-r--r-- | tests/concepts/tconcepts.nim | 451 |
1 files changed, 451 insertions, 0 deletions
diff --git a/tests/concepts/tconcepts.nim b/tests/concepts/tconcepts.nim new file mode 100644 index 000000000..ea3ddc401 --- /dev/null +++ b/tests/concepts/tconcepts.nim @@ -0,0 +1,451 @@ +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) |