tests and docs for call operator (#16980)
* tests and docs for call operator * fix leftover * add extra dot test
This commit is contained in:
parent
d1210a3bb9
commit
aac8f67573
4 changed files with 124 additions and 1 deletions
|
|
@ -408,7 +408,7 @@ The matched dot operators can be symbols of any callable kind (procs,
|
|||
templates and macros), depending on the desired effect:
|
||||
|
||||
.. code-block:: nim
|
||||
template `.` (js: PJsonNode, field: untyped): JSON = js[astToStr(field)]
|
||||
template `.`(js: PJsonNode, field: untyped): JSON = js[astToStr(field)]
|
||||
|
||||
var js = parseJson("{ x: 1, y: 2}")
|
||||
echo js.x # outputs 1
|
||||
|
|
@ -434,6 +434,38 @@ This operator will be matched against assignments to missing fields.
|
|||
.. code-block:: nim
|
||||
a.b = c # becomes `.=`(a, b, c)
|
||||
|
||||
Call operator
|
||||
-------------
|
||||
The call operator, `()`, matches all kinds of unresolved calls and takes
|
||||
precedence over dot operators, however it does not match missing overloads
|
||||
for existing routines. The experimental `callOperator` switch must be enabled
|
||||
to use this operator.
|
||||
|
||||
.. code-block:: nim
|
||||
{.experimental: "callOperator".}
|
||||
|
||||
template `()`(a: int, b: float): untyped = $(a, b)
|
||||
|
||||
block:
|
||||
let a = 1.0
|
||||
let b = 2
|
||||
doAssert b(a) == `()`(b, a)
|
||||
doAssert a.b == `()`(b, a)
|
||||
|
||||
block:
|
||||
let a = 1.0
|
||||
proc b(): int = 2
|
||||
doAssert not compiles(b(a))
|
||||
doAssert not compiles(a.b) # `()` not called
|
||||
|
||||
block:
|
||||
let a = 1.0
|
||||
proc b(x: float): int = int(x + 1)
|
||||
let c = 3.0
|
||||
|
||||
doAssert not compiles(a.b(c)) # gives a type mismatch error same as b(a, c)
|
||||
doAssert (a.b)(c) == `()`(a.b, c)
|
||||
|
||||
|
||||
Not nil annotation
|
||||
==================
|
||||
|
|
|
|||
39
tests/specialops/tcallops.nim
Normal file
39
tests/specialops/tcallops.nim
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
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)
|
||||
44
tests/specialops/tcallprecedence.nim
Normal file
44
tests/specialops/tcallprecedence.nim
Normal file
|
|
@ -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)
|
||||
|
|
@ -17,6 +17,14 @@ one param call to c with 10
|
|||
'''
|
||||
"""
|
||||
|
||||
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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue