7

Is it possible to get all the errors in the lua stack from C/C++? here is what I've tried

c++

int main()
{
    lua_State* L = luaL_newstate();
    luaL_openlibs(L);

    if (luaL_loadfile(L, "LuaBridgeScript.lua"))
    {
        throw std::runtime_error("Unable to find lua file");
    }

    int error = lua_pcall(L, 0, 0, 0);
    while (error && lua_gettop(L))
    {
        std::cout << "stack = " << lua_gettop(L) << "\n";
        std::cout << "error = " << error << "\n";
        std::cout << "message = " << lua_tostring(L, -1) << "\n";
        lua_pop(L, 1);
        error = lua_pcall(L, 0, 0, 0);
    }
}

lua:

printMessage("hi")
printMessage2("hi2")

output:

stack = 1
error = 2
message = LuaBridgeScript.lua:1: attempt to call global 'printMessage' <a nil value>

I've also tried looping even if the stack size is 0 or negative, but I don't understand how the stack could be negative, and the program crashes after a few attempts.

hjpotter92
  • 78,589
  • 36
  • 144
  • 183
Zephilinox
  • 73
  • 2
  • 5
  • I'm not sure I follow. `lua_pcall` will return as soon as the first error is caught. It will stop at `printMessage` and not continue execution of the chunk. Where did you get the idea that there would be more errors on the stack? [Docs](http://www.lua.org/manual/5.1/manual.html#lua_pcall) states that clearly. – W.B. Aug 13 '14 at 11:30
  • Btw, why are you throwing errors in main? – W.B. Aug 13 '14 at 11:33
  • I thought since lua_pcall popped the function off the stack that it would continue throughout the file, I guess that's not correct? Do you know how I could go about doing this? As for throwing, I just copy and pasted this from a function and wrapped it in main for the sake of it. – Zephilinox Aug 13 '14 at 12:13
  • What are you trying to achieve? Check source file for any errors? – W.B. Aug 13 '14 at 12:24
  • Yeah, I'd like to be able to check if the lua file has errors such as calling an undefined function, or forgetting to put an "end" after a function. – Zephilinox Aug 13 '14 at 12:33
  • Lua is a dynamically typed language. It won't interpret what printMessage means until it's about to be called. So you're unlucky there. In terms of syntax errors, such as no end clause, it should be caught when compiling the source (loading). – W.B. Aug 13 '14 at 12:44
  • Ah I see, thanks for helping. I can now detect syntax errors, but can I do something similar to how a C++ compiler will give multiple syntax errors, rather than just one? either way if you create an answer I will accept it. – Zephilinox Aug 13 '14 at 12:54
  • Compilers attempt to give multiple syntax errors but often get that very wrong (or at least did last time I routinely saw such errors). The parser gets out of sync and can't correctly parse code anymore. Stopping at the first error prevents that sort of problem. – Etan Reisner Aug 13 '14 at 13:38

2 Answers2

5

To wrap up my comments into an answer:

According to Lua docs on lua_pcall, pcall returns on either success (end of chunk) or first error thrown. So in the latter case, it will push only one message to the stack. It will never continue execution after the first error.

What you're trying to achieve is checking for possible errors in the file. In statically typed languages like C, every variable has to be defined at compile time, so the compiler can spot instances of calling non existing function.

Lua, however, is a dynamically typed language, in which variables have no types but rather are placeholders for values (which do have types). This means, that Lua cannot tell in advance whether printMessage is a function, a string, a value or if it doesn't exist (nil). It is only at run time when the variable is about to be called that Lua checks its type.

It is therefore not possible to achieve what you want that way. Running the code beyond the first unhandled error is pointless as well, as the error may render assumptions in subsequent fragments invalid (for instance about global variables that the non existing function should have set) - it would be a mess.

As to syntax errors, these are generally caught when compiling the source file, that is while loading. However, Lua parser stops at first encountered syntax error. This is due to the fact that many times syntax errors in one place invalidate everything that follows it. As Etan pointed out in his comment, many parsers report subsequent errors that disappear or change once you've fixed errors that precede them. It is also true for even heavy weight parsers like those in MSVS.

W.B.
  • 5,445
  • 19
  • 29
1

(going by the question you clarified in comments) It's not possible to report multiple syntax errors (only the first one is reported); so in the following fragment only the first error on line 1 is reported:

if true the --<-- first syntax error
end
if false the --<-- second syntax error
end

You may however write your own parser (or modify one of the existing Lua parsers) that will continue processing even after finding the error. For example, you may review how David Manura's loose parser works.

It's not possible to report multiple run-time errors (only the first one is reported); so in the following fragment pcall will report only the first error:

pcall(function()
  nonExistingFunction1() --<-- only this error will be reported
  nonExistingFunction2()
end)
Paul Kulchenko
  • 25,884
  • 3
  • 38
  • 56