Познакомимся с load
. Эта функция берёт первым аргументом строку и компилирует её.
local str = "Тест!"
print(load(str))
--> nil [string "Тест!"]:1: unexpected symbol near '<\208>'
Код выше вернёт странные идеограммы, но если присмотреться, то становится заметно, что именно там происходит.
Если строка, которую мы дали, содержит невалидный Lua код (не луа-код совсем или с синтаксическими ошибками),
то load
возвращает nil
и описание ошибки.
local str = "Тест!"
local chunk, err = load(str)
print(err)
--> [string "Тест!"]:1: unexpected symbol near '<\208>'
Если же load
видит, что мы дали валидный код на Lua, то он его, как уже сказал, компилирует.
И преобразует в функцию, которую load
вернёт.
local str = [[print("Hello, world!")]]
local chunk, err = load(str)
chunk()
--> Hello, world!
Да, как видно, если мы вызовем эту функцию, то будет исполнен переданный лоаду код. Круто.
Что будет, если в коде возникнет ошибка?
local str = [[error("Ошибка!")]]
local chunk, err = load(str)
chunk()
print("Всё ок?")
Упс. На третьей строке у нас вся программа остановится и выбросит ошибку.
Такая же штука будет, если в str
мы засунем что-то вроде [[print("удав" + "собака")]]
.
К счастью, мы можем и эту ошибку отловить. Для чего теперь уже используется функция pcall
.
Она принимает как аргумент функцию и параметры к ней. После чего вызывает переданную функцию и, если
в коде возникает ошибка, возвращает false
и описание ошибки.
local str = [[print("кот" + "собака")]]
local chunk, err = load(str)
local result, err = pcall(chunk)
print(err)
--> [string "print("кот" + "собака")"]:1: attempt to perform arithmetic on a string value
Если же ошибок не будет, pcall
вернёт true
и всё то, что в коде передано через return
.
local str = [[print("кот + собака")]]
local chunk, err = load(str)
local result, err = pcall(chunk)
print(result, err)
--> true nil
Отлично. Осталось теперь всё это оформить. Для чего мы создадим отдельную функцию.
local function runCode(code)
local chunk, err = load(code)
if not chunk then
-- load вернул ошибку
return false, err
end
local success, returnValue = pcall(chunk)
if not success then
-- pcall поймал ошибку
return false, returnValue
end
-- всё хорошо, ошибок нет
return true, returnValue
end
print(runCode([[print(rip irc)]]))
--> false [string "print(rip irc)"]:1: ')' expected near 'irc'
print(runCode([[print("rip" + "irc")]]))
--> false [string "print("rip" + "irc")"]:1: attempt to perform arithmetic on a string value
print(runCode([[print("rip" .. "irc")]]))
--> ripirc
--> true nil