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

Internal analyzer.lua error failure when returning multiple records from a require() #227

Closed jrfondren closed 10 months ago

jrfondren commented 11 months ago

Bug description

I split off some regex code into its own module, which included a test. So that I could run the test without adding it to the module's namespace, I considered returning a second record containing the test.

Code example

local M = @record{}
local T = @record{}

function M.f() print('f') end
function T.f() assert(false) end

return M, T

Expected behavior

To work or to be forbidden:

$ nelua -i 'local mod, tests = require("multimod") tests.f()'
/home/jfondren/nelua/bug/multimod.nelua:7:1: runtime error: assertion failed!
function T.f() assert(false) end
                      ^~~~~

$ nelua -i 'local mod, tests = require("multimod") tests.f()'
multimod.nelua:7:1: error: multiple record returns from require() is not supported

Actual behavior

$ nelua -i 'local mod, tests = require("multimod") tests.f()'
/home/jfondren/nelua/nelua-lang/nelua-lua: /home/jfondren/nelua/nelua-lang/lualib/nelua/analyzer.lua:2350: assertion failed!
stack traceback:
    [C]: in function 'assert'
    /home/jfondren/nelua/nelua-lang/lualib/nelua/analyzer.lua:2350: in field '?'
    .../jfondren/nelua/nelua-lang/lualib/nelua/analyzercontext.lua:112: in function 'nelua.analyzercontext.traverse_node'
    ...e/jfondren/nelua/nelua-lang/lualib/nelua/visitorcontext.lua:190: in function 'nelua.visitorcontext.traverse_nodes'
    /home/jfondren/nelua/nelua-lang/lualib/nelua/analyzer.lua:1884: in field '?'
    .../jfondren/nelua/nelua-lang/lualib/nelua/analyzercontext.lua:112: in function 'nelua.analyzercontext.traverse_node'
    /home/jfondren/nelua/nelua-lang/lualib/nelua/analyzer.lua:3391: in function 'nelua.analyzer.analyze'
    /home/jfondren/nelua/nelua-lang/lualib/nelua/runner.lua:182: in function </home/jfondren/nelua/nelua-lang/lualib/nelua/runner.lua:181>
    [C]: in function 'xpcall'
    /home/jfondren/nelua/nelua-lang/lualib/nelua/utils/except.lua:135: in function 'nelua.utils.except.try'
    /home/jfondren/nelua/nelua-lang/lualib/nelua/runner.lua:181: in upvalue 'run'
    /home/jfondren/nelua/nelua-lang/lualib/nelua/runner.lua:257: in function </home/jfondren/nelua/nelua-lang/lualib/nelua/runner.lua:256>
    [C]: in function 'xpcall'
    /home/jfondren/nelua/nelua-lang/lualib/nelua/utils/except.lua:135: in function 'nelua.utils.except.try'
    /home/jfondren/nelua/nelua-lang/lualib/nelua/runner.lua:256: in function 'nelua.runner.run'
    /home/jfondren/nelua/nelua-lang/lualib/nelua.lua:4: in main chunk
    [C]: in function 'require'
    [C]: in ?
stack traceback:
    [C]: in function 'error'
    /home/jfondren/nelua/nelua-lang/lualib/nelua/utils/except.lua:108: in function 'nelua.utils.except.reraise'
    /home/jfondren/nelua/nelua-lang/lualib/nelua/utils/except.lua:146: in function 'nelua.utils.except.try'
    /home/jfondren/nelua/nelua-lang/lualib/nelua/runner.lua:181: in upvalue 'run'
    /home/jfondren/nelua/nelua-lang/lualib/nelua/runner.lua:257: in function </home/jfondren/nelua/nelua-lang/lualib/nelua/runner.lua:256>
    [C]: in function 'xpcall'
    /home/jfondren/nelua/nelua-lang/lualib/nelua/utils/except.lua:135: in function 'nelua.utils.except.try'
    /home/jfondren/nelua/nelua-lang/lualib/nelua/runner.lua:256: in function 'nelua.runner.run'
    /home/jfondren/nelua/nelua-lang/lualib/nelua.lua:4: in main chunk
    [C]: in function 'require'
    [C]: in ?
stack traceback:
    [C]: in function 'error'
    /home/jfondren/nelua/nelua-lang/lualib/nelua/utils/except.lua:108: in function 'nelua.utils.except.reraise'
    /home/jfondren/nelua/nelua-lang/lualib/nelua/utils/except.lua:146: in function 'nelua.utils.except.try'
    /home/jfondren/nelua/nelua-lang/lualib/nelua/runner.lua:256: in function 'nelua.runner.run'
    /home/jfondren/nelua/nelua-lang/lualib/nelua.lua:4: in main chunk
    [C]: in function 'require'
    [C]: in ?

Workaround

I'd prefer tests in a separate file anyway, but a very similar usage is possible with:

local M = @record{}
global M.tests = @record{}

function M.f() print('f') end
function M.tests.f() assert(false) end

return M

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

Multiple returns was designed to be used only with runtime variables, not for compile-time stuff (like types). So you hit an unsupported feature, I added an error for this in https://github.com/edubart/nelua-lang/commit/a1b4a34e68e3b0cbb92ea5a45be165770798ac74