Add hasClosure to std/typetraits (#17501)

* fix nim js cmp fails at CT

* Add `hasClosure` to `std/effecttraits`

* type

* Update changelog.md

Co-authored-by: Timothee Cour <timothee.cour2@gmail.com>

* Update lib/std/effecttraits.nim

Co-authored-by: Timothee Cour <timothee.cour2@gmail.com>
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
This commit is contained in:
flywind 2021-03-29 20:22:29 +08:00 • committed by GitHub
commit 81e54c1d30
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 109 additions and 0 deletions

View file

@ -246,6 +246,8 @@
- Added dollar `$` and `len` for `jsre.RegExp`.
- Added `hasClosure` to `std/typetraits`.
## Language changes

View file

@ -316,3 +316,7 @@ proc registerAdditionalOps*(c: PCtx) =
let fn = getNode(a, 0)
setResult(a, (fn.typ != nil and tfNoSideEffect in fn.typ.flags) or
(fn.kind == nkSym and fn.sym.kind == skFunc))
registerCallback c, "stdlib.typetraits.hasClosureImpl", proc (a: VmArgs) =
let fn = getNode(a, 0)
setResult(a, fn.kind == nkClosure or (fn.typ != nil and fn.typ.callConv == ccClosure))

View file

@ -263,3 +263,14 @@ since (1, 1):
type T2 = T
genericParamsImpl(T2)
proc hasClosureImpl(n: NimNode): bool = discard "see compiler/vmops.nim"
proc hasClosure*(fn: NimNode): bool {.since: (1, 5, 1).} =
## Return true if the func/proc/etc `fn` has `closure`.
## `fn` has to be a resolved symbol of kind `nnkSym`. This
## implies that the macro that calls this proc should accept `typed`
## arguments and not `untyped` arguments.
expectKind fn, nnkSym
result = hasClosureImpl(fn)

View file

@ -0,0 +1,92 @@
discard """
targets: "c cpp js"
"""
import std/typetraits
macro testClosure(fn: typed, flag: static bool) =
if flag:
doAssert hasClosure(fn)
else:
doAssert not hasClosure(fn)
block:
proc h1() =
echo 1
testClosure(h1, false)
proc h2() {.nimcall.} =
echo 2
testClosure(h2, false)
block:
proc fn(): auto =
proc hello() {.nimcall.} =
echo 3
hello
let name = fn()
testClosure(name, false)
block:
proc fn(): auto =
proc hello() =
echo 3
hello
let name = fn()
testClosure(name, false)
block:
proc fn(): auto =
var x = 0
proc hello() =
echo 3
inc x
hello
let name = fn()
testClosure(name, true)
block:
proc fn(): auto =
var x = 0
proc hello() {.closure.} =
echo 3
inc x
hello
let name = fn()
testClosure(name, true)
block:
proc fn(): auto =
var x = 0
proc hello() {.closure.} =
echo 3
inc x
hello
let name = fn()
testClosure(name, true)
let name2 = name
testClosure(name2, true)
block:
iterator hello(): int =
yield 1
testClosure(hello, false)
when not defined(js):
block:
iterator hello(): int {.closure.}=
yield 1
testClosure(hello, true)