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

If the 'string' module is required into elided code, generated C doesn't define nelua_nlstring___eq #228

Closed jrfondren closed 10 months ago

jrfondren commented 11 months ago

Bug description

I wrote a library with a function-localized require 'string', used that library, and then didn't use the function with the require. The resulting code failed to compile with a C compiler error.

Code example

-- require 'string' -- fix #1: uncomment
local function f()
  local ss = require 'string' -- fix #2: comment
end

local function g()
  return "a" == "b"
end

-- f() -- fix #3: uncomment
print(g())

Current behavior

$ nelua stringeq.nelua
/home/jfondren/.cache/nelua/stringeq.c: In function 'stringeq_g':
/home/jfondren/.cache/nelua/stringeq.c:94:10: error: implicit declaration of function 'nelua_nlstring___eq' [-Werror=implicit-function-declaration]
   94 |   return nelua_nlstring___eq(((nlstring){(uint8_t*)"a", 1}), ((nlstring){(uint8_t*)"b", 1}));
      |          ^~~~~~~~~~~~~~~~~~~
cc1: some warnings being treated as errors
error: C compilation for '/home/jfondren/.cache/nelua/stringeq' failed

Related example

I ran into another surprising effect from requiring 'string', and also thought it was a bug for a while:

local s1 <comptime> = 'a' .. 'b'

require 'string'

local s2 <comptime> = 'b' .. 'c'

Error:

stringcat.nelua:1:1: from: AST node Block
local s1 <comptime> = 'a' .. 'b'
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
stringcat.nelua:5:7: error: compile time variables can only assign to compile time expressions
local s2 <comptime> = 'b' .. 'c'
      ^~~~~~~~~~~~~

The easy workaround was to have lua do that:

local s1 <comptime> = #['a' .. 'b']#

require 'string'

local s2 <comptime> = #['b' .. 'c']#

Non-complaint

That Lua's involved in the compilation process is a strength of Nelua, so I accept that requiring a library can have apparently strange effects like the previous one. Even C compiler errors are reasonable when the library has ## linklib 'does-not-exist'.

Environment

arm64 linux Nelua 0.2.0-dev Build number: 1588 Git date: 2023-09-16 16:20:44 -0300 Git hash: 596fcca5c77932da8a07c249de59a9dff3099495 Semantic version: 0.2.0-dev.1588+596fcca5 Copyright (C) 2019-2022 Eduardo Bart (https://nelua.io/)

edubart commented 10 months ago

The string module is special because it is actually declared first by the compiler, and when you do require 'string' a library with extra functions is injected, so I enforced to only allow requiring it from the upper scope.

After commit https://github.com/edubart/nelua-lang/commit/01de5bf1ad8a89300e84e9ce9b3350131f419877 you will get better error messages when attempting to do this.

The related example is the expected behavior, without doing require 'string' you have a very crude version of string available, this is because the full string library pull lot of stuff, such as allocators and other dependencies. People targeting embedded systems may want to avoid it.