Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

when nimvm branch does not work correctly with nimscript #21687

Open
rockcavera opened this issue Apr 18, 2023 · 2 comments
Open

when nimvm branch does not work correctly with nimscript #21687

rockcavera opened this issue Apr 18, 2023 · 2 comments

Comments

@rockcavera
Copy link
Contributor

rockcavera commented Apr 18, 2023

Description

When executing Nim code via nimscript (nim e file), for some reason the code in the else branch of when nimvm attempts to resolve its symbols, which, in the case of system.copyMem do example below, is not declared for nimscript. This results in an error.

const num = 0x807060504030201'u64
const num2 = 0x102030405060708'u64

proc toByte(x: uint64): array[8, byte] =
  when nimVm:
    for i in 0 .. 7:
      let p = (x shr (i * 8)) and 0xff'u64
      result[i] = byte(p)
  else:
    copyMem(addr result, unsafeAddr(x), 8)

const ctByteNum = toByte(num)
let rtByteNum2 = toByte(num2)

echo ctByteNum
echo rtByteNum2

Nim Version

Nim Compiler Version 1.9.3 [Windows: amd64]
Compiled at 2023-04-17
Copyright (c) 2006-2023 by Andreas Rumpf

git hash: 9dc1f2d
active boot switches: -d:release

Current Output

nim e bug.nim
Hint: used config file 'E:\Nim\config\nim.cfg' [Conf]
Hint: used config file 'E:\Nim\config\config.nims' [Conf]
C:\Users\josep\desktop\bug.nim(10, 5) Error: undeclared identifier: 'copyMem'
candidates (edit distance, scope distance); see '--spellSuggest':
 (4, 2): 'toByte'
 (4, 4): '=copy'
 (4, 4): 'compiles'
 (4, 4): 'ctypes'
 (4, 4): 'open'

Expected Output

[1, 2, 3, 4, 5, 6, 7, 8]
[8, 7, 6, 5, 4, 3, 2, 1]

Possible Solution

A stopgap solution is to prepend this:

proc toByte(x: uint64): array[8, byte] =
  when nimVm:
    for i in 0 .. 7:
      let p = (x shr (i * 8)) and 0xff'u64
      result[i] = byte(p)
  else:
    when not defined(nimscript):
      copyMem(addr result, unsafeAddr(x), 8)

This solution seems to work for all versions from 1.0.0

Additional Information

The code works normally for c and cpp backend, demonstrating that during compile time toByte is executed correctly and the when nimvm branch as well.

@metagn
Copy link
Collaborator

metagn commented Apr 19, 2023

when nimvm still "compiles" both branches. It just decides which branch to use when generating code for the VM or for the backend. Your workaround is used in the standard library, see string cmp, similar workaround here in lexbase, here in streams etc.

Maybe we could change when nimvm to always be true on NimScript and never compile the bottom branch, but we would have to see if it works well

@litlighilit
Copy link
Contributor

litlighilit commented Jun 15, 2023

See https://forum.nim-lang.org/t/9214#60384
,it's the same case.

Also, there is another minimum example, which'll also error in nimscript

when nimvm: discard
else: {.error: "This msg will also showed in nimscript".}

To show a more strange example:

import std/os
when nimvm: discard
else: echo getCurrentProcessId()
# the proc has a `{.noWeirdTarget.}` which in fact a `{.error: xx.}` pragma.

The above still can't run in nimscript
I mean it's counterintuitive but long-standing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants