edubart / nelua-lang

Minimal, efficient, statically-typed and meta-programmable systems programming language heavily inspired by Lua, which compiles to C and native code.
https://nelua.io
MIT License
1.99k stars 64 forks source link

Comparison of a pointer with nil generates unexpected C code #249

Closed baysmith closed 7 months ago

baysmith commented 7 months ago

Comparison of a pointer with nil generates unexpected C code.

For example, this code

local p: *integer
local x = p == nil

generates this C code

x = (p, NELUA_NIL, false);

Expected behavior

It was expected that the C code would be comparison of the pointer with NULL.

x = p == NULL;

Environment

jrfondren commented 7 months ago

You're looking for nilptr:

$ nelua -i 'local p: *integer  local x = p == nilptr  print(x)'
true
$ nelua --print-code -i 'local p: *integer  local x = p == nilptr  print(x)'|grep NULL
  eval_B6wLM8M3v3j_x = (eval_B6wLM8M3v3j_p == (nlint64_ptr)NULL);

nil and == have more Lua-like semantics. As only nil can be equal to nil, your code reduces to constant false (with some overhead, I imagine, to ensure execution of side effects and to pacify dead code elimination).

I'm not a huge fan of this behavior, especially in cases like

$ nelua -i 'local notastring = "b"_u8  assert(notastring == "b")'
eval_BQds3GgUC6y:1:46: runtime error: assertion failed!

where I've forgotten _u8 and silently had tests would never succeed, instead of a clear type error:

$ rdmd --eval 'byte notastring; writeln(notastring == "b")'
/tmp/.rdmd-1000/eval.19B690DD18DF18E03E108A2FE7BF74DB.d(18): Error: incompatible types for `(notastring) == ("b")`: `byte` and `string`
edubart commented 7 months ago

Not a bug, nil is not the same as nilptr, nil is like an empty value without even a known type. While nilptr is an empty pointer, it does have a type. The are different because they have different types, however both will collapse to false when trying to convert to a boolean, so you could do this instead:

local p: *integer
local x = not p