Получить все ошибки из lua pcall(L, 0, 0, 0)

можно ли получить все ошибки в стеке lua из C / C++? вот что я пробовал

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")

выход:

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

Я также пробовал цикл, даже если размер стека равен 0 или отрицательный, но я не понимаю, как стек может быть отрицательным, и программа аварийно завершает работу после нескольких попыток.

2 ответов


чтобы обернуть мои комментарии в ответ:

по данным Lua docs on lua_pcall, pcall возвращает либо успех (конец куска), либо первую ошибку. Так что в последнем случае он будет толкать единственный сообщение в стек. Он никогда не будет продолжать выполнение после первой ошибки.

то, что вы пытаетесь достичь, это проверка возможных ошибок в файле. В статически типизированных языках, таких как C, каждая переменная должна быть определена в время компиляции, поэтому компилятор может определить экземпляры вызова несуществующей функции.

Lua, однако, является динамически типизированным языком, в котором переменные не имеют типов, а являются заполнителями для значений (которые имеют типы). Это означает, что Lua не может сказать заранее,printMessage - это функция, строка, значение или если оно не существует (nil). Только во время выполнения, когда переменная собирается быть вызвана, Lua проверяет ее тип.

поэтому не таким образом можно достичь желаемого. Запуск кода за пределами первой необработанной ошибки также бессмыслен, так как ошибка может сделать предположения в последующих фрагментах недействительными (например, о глобальных переменных, которые должна была установить несуществующая функция) - это будет беспорядок.

что касается синтаксических ошибок, они обычно обнаруживаются при компиляции исходного файла, то есть при загрузке. Однако Lua parser останавливается при первой обнаруженной синтаксической ошибке. Это связано с тем, это много раз синтаксические ошибки в одном месте аннулируют все, что следует за ним. Как отметил Этан в своем комментарии, многие Парсеры сообщают о последующих ошибках, которые исчезают или изменяются после того, как вы исправили ошибки, предшествующие им. Это также верно для даже тяжелых парсеров, таких как в MSVS.


(по вопросу, который вы уточнили в комментариях) невозможно сообщить о нескольких синтаксических ошибках (сообщается только первая); поэтому в следующем фрагменте сообщается только первая ошибка в строке 1:

if true the --<-- first syntax error
end
if false the --<-- second syntax error
end
свободный парсер строительство.

это не возможно сообщить о нескольких ошибках во время выполнения (сообщается только о первой); поэтому в следующем фрагменте pcall сообщит только о первой ошибке:

pcall(function()
  nonExistingFunction1() --<-- only this error will be reported
  nonExistingFunction2()
end)