diff options
Diffstat (limited to 'tests/specialops')
-rw-r--r-- | tests/specialops/tcallops.nim | 49 | ||||
-rw-r--r-- | tests/specialops/tcallprecedence.nim | 44 | ||||
-rw-r--r-- | tests/specialops/tdotops.nim | 12 | ||||
-rw-r--r-- | tests/specialops/terrmsgs.nim | 76 | ||||
-rw-r--r-- | tests/specialops/tnewseq.nim | 22 | ||||
-rw-r--r-- | tests/specialops/tsetter.nim | 10 |
6 files changed, 212 insertions, 1 deletions
diff --git a/tests/specialops/tcallops.nim b/tests/specialops/tcallops.nim new file mode 100644 index 000000000..c541a0c1d --- /dev/null +++ b/tests/specialops/tcallops.nim @@ -0,0 +1,49 @@ +import macros + +{.experimental: "callOperator".} + +type Foo[T: proc] = object + callback: T + +macro `()`(foo: Foo, args: varargs[untyped]): untyped = + result = newCall(newDotExpr(foo, ident"callback")) + for a in args: + result.add(a) + +var f1Calls = 0 +var f = Foo[proc()](callback: proc() = inc f1Calls) +doAssert f1Calls == 0 +f() +doAssert f1Calls == 1 +var f2Calls = 0 +f.callback = proc() = inc f2Calls +doAssert f2Calls == 0 +f() +doAssert f2Calls == 1 + +let g = Foo[proc (x: int): int](callback: proc (x: int): int = x * 2 + 1) +doAssert g(15) == 31 + +proc `()`(args: varargs[string]): string = + result = "(" + for a in args: result.add(a) + result.add(')') + +let a = "1" +let b = "2" +let c = "3" + +doAssert a(b) == "(12)" +doAssert a.b(c) == `()`(b, a, c) +doAssert (a.b)(c) == `()`(a.b, c) +doAssert `()`(a.b, c) == `()`(`()`(b, a), c) + +block: # bug #1072 + var x: int + + proc foo(some:int):int = some + proc `()`(l,r:string): string = discard + + block: + var foo = 42 + doAssert x.foo == 0 diff --git a/tests/specialops/tcallprecedence.nim b/tests/specialops/tcallprecedence.nim new file mode 100644 index 000000000..6116f83d5 --- /dev/null +++ b/tests/specialops/tcallprecedence.nim @@ -0,0 +1,44 @@ +import macros + +{.experimental: "dotOperators".} +{.experimental: "callOperator".} + +block: + template `.()`(foo: int, args: varargs[untyped]): untyped {.used.} = + ".()" + + template `()`(foo: int, args: varargs[untyped]): untyped = + "()" + + let a = (b: 1) + let c = 3 + + doAssert a.b(c) == "()" + doAssert not compiles(a(c)) + doAssert (a.b)(c) == "()" + +macro `()`(args: varargs[typed]): untyped = + result = newLit("() " & args.treeRepr) + +macro `.`(args: varargs[typed]): untyped = + result = newLit(". " & args.treeRepr) + +block: + let a = 1 + let b = 2 + doAssert a.b == `()`(b, a) + +block: + let a = 1 + proc b(): int {.used.} = 2 + doAssert a.b == `.`(a, b) + +block: + let a = 1 + proc b(x: int): int = x + 1 + let c = 3 + + doAssert a.b(c) == `.`(a, b, c) + doAssert a(b) == `()`(a, b) + doAssert (a.b)(c) == `()`(a.b, c) + doAssert a.b == b(a) diff --git a/tests/specialops/tdotops.nim b/tests/specialops/tdotops.nim index 227204f51..ca5eee665 100644 --- a/tests/specialops/tdotops.nim +++ b/tests/specialops/tdotops.nim @@ -1,5 +1,6 @@ discard """ output: ''' + 10 assigning z = 20 reading field y @@ -12,9 +13,18 @@ no params call to b 100 one param call to c with 10 100 -0 4''' +0 4 +''' """ +block: + type Foo = object + var a: Foo + template `.`(a: Foo, b: untyped): untyped = astToStr(b) + template callme(a, f): untyped = a.f + doAssert callme(a, f2) == "f2" # not `f` + doAssert a.callme(f3) == "f3" + type T1 = object x*: int diff --git a/tests/specialops/terrmsgs.nim b/tests/specialops/terrmsgs.nim new file mode 100644 index 000000000..081bca451 --- /dev/null +++ b/tests/specialops/terrmsgs.nim @@ -0,0 +1,76 @@ +discard """ +action: reject +cmd: '''nim check $options $file''' +matrix: "; -d:testWithout; --mm:refc" +""" + +when not defined(testWithout): # test for same errors before and after + {.experimental: "dotOperators".} + {.experimental: "callOperator".} + +# issue #13063 + +block: + type Foo = object + type Bar = object + x1: int + var b: Bar + block: + template `.`(a: Foo, b: untyped): untyped = 123 + echo b.x #[tt.Error + ^ undeclared field: 'x' for type terrmsgs.Bar [type declared in terrmsgs.nim(15, 8)]]# + block: + template `.()`(a: Foo, b: untyped): untyped = 123 + echo b.x() #[tt.Error + ^ attempting to call undeclared routine: 'x']# + block: + template `.=`(a: Foo, b: untyped, c: untyped) = b = c + b.x = 123 #[tt.Error + ^ undeclared field: 'x=' for type terrmsgs.Bar [type declared in terrmsgs.nim(15, 8)]]# + # yeah it says x= but does it matter in practice + block: + template `()`(a: Foo, b: untyped, c: untyped) = echo "something" + + # completely undeclared:: + xyz(123) #[tt.Error + ^ undeclared identifier: 'xyz']# + + # already declared routine: + min(123) #[tt.Error + ^ type mismatch: got <int literal(123)>]# + + # non-routine type shows `()` overloads: + b(123) #[tt.Error + ^ attempting to call routine: 'b']# + + echo b.x #[tt.Error + ^ undeclared field: 'x' for type terrmsgs.Bar [type declared in terrmsgs.nim(15, 8)]]# + echo b.x() #[tt.Error + ^ attempting to call undeclared routine: 'x']# + +# issue #7777 + +import macros + +block: + type TestType = object + private_field: string + + when false: + template getField(obj, field: untyped): untyped = obj.field + + macro `.`(obj: TestType, field: untyped): untyped = + let private = newIdentNode("private_" & $field) + result = quote do: + `obj`.getField(`private`) #[tt.Error + ^ attempting to call undeclared routine: 'getField']# + + var tt: TestType + discard tt.field + +block: # related to issue #6981 + proc `()`(a:string, b:string):string = a & b + proc mewSeq[T](a,b:int)=discard + proc mewSeq[T](c:int)= discard + mewSeq[int]() #[tt.Error + ^ type mismatch: got <>]# diff --git a/tests/specialops/tnewseq.nim b/tests/specialops/tnewseq.nim new file mode 100644 index 000000000..970a5a8c2 --- /dev/null +++ b/tests/specialops/tnewseq.nim @@ -0,0 +1,22 @@ +# issue #6981 + +import std/assertions + +{.experimental: "callOperator".} + +block: # issue #6981 + proc `()`(a:string, b:string):string = a & b + + var s = newSeq[int](3) + + doAssert s == @[0, 0, 0] + +block: # generalized example from #6981 + proc mewSeq[T](a: int)=discard + proc mewSeq[T]()= discard + mewSeq[int]() + +block: # issue #9831 + type Foo = object + proc `()`(foo: Foo) = discard + let x = newSeq[int]() diff --git a/tests/specialops/tsetter.nim b/tests/specialops/tsetter.nim new file mode 100644 index 000000000..6175cbec4 --- /dev/null +++ b/tests/specialops/tsetter.nim @@ -0,0 +1,10 @@ +block: # ensure RHS of setter statement is treated as call operand + proc `b=`(a: var int, c: proc (x: int): int) = + a = c(a) + + proc foo(x: int): int = x + 1 + proc foo(x: float): float = x - 1 + + var a = 123 + a.b = foo + doAssert a == 124 |