summary refs log tree commit diff stats
path: root/tests/specialops
diff options
context:
space:
mode:
Diffstat (limited to 'tests/specialops')
-rw-r--r--tests/specialops/tcallops.nim49
-rw-r--r--tests/specialops/tcallprecedence.nim44
-rw-r--r--tests/specialops/tdotops.nim12
-rw-r--r--tests/specialops/terrmsgs.nim76
-rw-r--r--tests/specialops/tnewseq.nim22
-rw-r--r--tests/specialops/tsetter.nim10
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