diff --git a/changelog.md b/changelog.md index d04378c90..fe44dc340 100644 --- a/changelog.md +++ b/changelog.md @@ -44,7 +44,9 @@ This is more consistent with the other asyncdispatch apis, and allows `asyncdispatch.drain` to be more efficient. - `base64.encode` and `base64.decode` was made faster by about 50%. -- `htmlgen` adds [MathML](https://wikipedia.org/wiki/MathML) support (ISO 40314). +- `htmlgen` adds [MathML](https://wikipedia.org/wiki/MathML) support + (ISO 40314). +- `macros.eqIdent` is now invariant to export markers and backtick quotes. diff --git a/compiler/vm.nim b/compiler/vm.nim index 4589d3a25..922208034 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -1644,10 +1644,22 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = of opcEqIdent: decodeBC(rkInt) # aliases for shorter and easier to understand code below - let aNode = regs[rb].node - let bNode = regs[rc].node - # these are cstring to prevent string copy, and cmpIgnoreStyle from - # takes cstring arguments + var aNode = regs[rb].node + var bNode = regs[rc].node + # Skipping both, `nkPostfix` and `nkAccQuoted` for both + # arguments. `nkPostfix` exists only to tag exported symbols + # and therefor it can be safely skipped. Nim has no postfix + # operator. `nkAccQuoted` is used to quote an identifier that + # wouldn't be allowed to use in an unquoted context. + if aNode.kind == nkPostfix: + aNode = aNode[1] + if aNode.kind == nkAccQuoted: + aNode = aNode[0] + if bNode.kind == nkPostfix: + bNode = bNode[1] + if bNode.kind == nkAccQuoted: + bNode = bNode[0] + # These vars are of type `cstring` to prevent unnecessary string copy. var aStrVal: cstring = nil var bStrVal: cstring = nil # extract strVal from argument ``a`` @@ -1674,7 +1686,6 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = bStrVal = bNode[0].sym.name.s.cstring else: discard - # set result regs[ra].intVal = if aStrVal != nil and bStrVal != nil: ord(idents.cmpIgnoreStyle(aStrVal, bStrVal, high(int)) == 0) diff --git a/lib/core/macros.nim b/lib/core/macros.nim index 818b62a40..b513be403 100644 --- a/lib/core/macros.nim +++ b/lib/core/macros.nim @@ -1378,16 +1378,22 @@ when defined(nimVmEqIdent): ## Style insensitive comparison. proc eqIdent*(a: NimNode; b: string): bool {.magic: "EqIdent", noSideEffect.} - ## Style insensitive comparison. - ## ``a`` can be an identifier or a symbol. + ## Style insensitive comparison. ``a`` can be an identifier or a + ## symbol. ``a`` may be wrapped in an export marker + ## (``nnkPostfix``) or quoted with backticks (``nnkAccQuoted``), + ## these nodes will be unwrapped. proc eqIdent*(a: string; b: NimNode): bool {.magic: "EqIdent", noSideEffect.} - ## Style insensitive comparison. - ## ``b`` can be an identifier or a symbol. + ## Style insensitive comparison. ``b`` can be an identifier or a + ## symbol. ``b`` may be wrapped in an export marker + ## (``nnkPostfix``) or quoted with backticks (``nnkAccQuoted``), + ## these nodes will be unwrapped. proc eqIdent*(a: NimNode; b: NimNode): bool {.magic: "EqIdent", noSideEffect.} - ## Style insensitive comparison. - ## ``a`` and ``b`` can be an identifier or a symbol. + ## Style insensitive comparison. ``a`` and ``b`` can be an + ## identifier or a symbol. Both may be wrapped in an export marker + ## (``nnkPostfix``) or quoted with backticks (``nnkAccQuoted``), + ## these nodes will be unwrapped. else: # this procedure is optimized for native code, it should not be compiled to nimVM bytecode. diff --git a/tests/macros/tmacro1.nim b/tests/macros/tmacro1.nim index 7e9120b65..18bbeb53d 100644 --- a/tests/macros/tmacro1.nim +++ b/tests/macros/tmacro1.nim @@ -77,6 +77,22 @@ static: assert fooSym.eqIdent("fOO") assertNot fooSym.eqIdent("bar") + # eqIdent on exported and backtick quoted identifiers + let procName = ident("proc") + let quoted = nnkAccQuoted.newTree(procName) + let exported = nnkPostfix.newTree(ident"*", procName) + let exportedQuoted = nnkPostfix.newTree(ident"*", quoted) + + let nodes = @[procName, quoted, exported, exportedQuoted] + + for i in 0 ..< nodes.len: + for j in 0 ..< nodes.len: + doAssert eqIdent(nodes[i], nodes[j]) + + for node in nodes: + doAssert eqIdent(node, "proc") + + var empty: NimNode var myLit = newLit("str")