коды для lua скриптов
Как написать Lua скрипты и где они используются? Подробный обзор
Lua-скрипты пишутся на языке программирования Lua, что очень даже естественно. Lua — это интерпретируемый скриптовой язык родом из Бразилии. Год его рождения — 1993-й год. С тех пор он постоянно развивается и расширяет свои возможности. Lua — это язык свободного распространения. По своей функциональности он ближе к JavaScript, но по некоторым компетентным мнениям он более гибкий, чем JS.
Скрипты Lua
Скрипты Lua не имеют собственной функции, с которой бы начиналось их выполнение. Это просто список заданных инструкций, которы е выполняются по порядку, стартуя с первой.
Скрипты Луа могут быть:
Переменные в скриптах Lua
Есть 4 требования при наименовании переменных:
Все переменные, как и в любом другом языке, делятся на 2 основных типа и могут быть:
Какую типизацию данных воспринимают скрипты Луа
Сам по себе язык Lua воспринимает следующую типизацию данных:
Любая переменная готова использовать любой из перечисленных типов — это определяет динамическая типизация языка Lua.
Комментарии в скриптах Lua
Комментарии в скриптах Lua могут быть:
Где используются скрипты Lua
Скриптинг Lua не так распространен, как JavaScript, но все равно за долгие годы существования этого языка он нашел последователей и занял свое место. Скрипты Lua применяются в проектах из разных сфер, некоторые из них довольно известные. Например:
Заключение
Отметим несколько достоинств скриптов Луа:
Да, Lua не самый популярный язык программирования, но он однозначно достоин внимания.
Мы будем очень благодарны
если под понравившемся материалом Вы нажмёте одну из кнопок социальных сетей и поделитесь с друзьями.
Что такое скрипты и с чем их едят — Lua & C++
Добрый день, Хабрахабр!
Решил написать этот топик на тему скриптов
Что нужно знать?
Но есть способ, на голову выше — использование скриптов.
Решение проблемы
«Окей, для таких дел хватает обычного файла с описанием характеристиков игрока. Но что делать, если в бурно развивающемся проекте почти каждый день приходится немножко изменять логику главного игрока, и, следовательно, много раз компилировать проект?»
Хороший вопрос. В этом случае нам на помощь приходят скрипты, держащие именно логику игрока со всеми характеристиками либо какой-либо другой части игры.
Естественно, удобнее всего держать, логику игрока в виде кода какого-нибудь языка программирования.
Первая мысль — написать свой интерпретатор своего скриптового языка, выкидывается из мозга через несколько секунд. Логика игрока определенно не стоит таких жутких затрат.
К счастью, есть специальные библиотеки скриптовых языков для С++, которые принимают на вход текстовый файл и выполняют его.
Об одном таком скриптовом языке Lua пойдет речь.
Как это работает?
Прежде чем начать, важно понимать, как работает скриптовый язык. Дело в том, что в скриптовых языках есть очень мало функций, при наличии конструкций for, while, if, прочих.
В основном это функции вывода текста в консоль, математические функции и функции для работы с файлами.
Как же тогда можно управлять игроком через скрипты?
Мы в С++-программе делаем какие-либо функции, «регистрируем» их под каким-нибудь именем в скрипте и вызываем в скрипте. То есть если мы зарегистрировали функцию SetPos(x,y) для определения позиции игрока в С++-программе, то, встретив эту функцию в скрипте, «интерпретатор» из библиотеки скриптового языка вызывает эту функцию в С++-программе, естественно, с передачей всех методов.
Удивительно, да? 🙂
UPD: Внимание! Один юзер обратился мне с мейлом, что, когда я заливал код, я не полностью устранил все ошибки — habrahabr.ru/post/196272/#comment_6850016
В коде с позволения хабра проникли жучки
Замените участки кода вроде
И еще вместо lua_CFunction проскакивает lua_cfunction
Спасибо!
Я готов!
Когда вы поняли преимущества скриптовых языков программирования, самое время начать работать!
Скачайте из репозитория на гитхабе (низ топика) lib’у и includ’ы Lua, либо возмите их на официальном сайте.
Создаем консольный проект либо Win32 (это неважно) в Visual Studio (у меня стоит версия 2012)
Заходим в Проект->Свойства->Свойства конфигурации->Каталоги VC++ и в «каталоги включения» и «каталоги библиотек» добавьте папку Include и Lib из репозитория соответственно.
Теперь создаем файл main.cpp, пишем в нем:
Как вы догадались, у меня консольное приложение.
Теперь переходим к кодингу
Обещаю, что буду тщательно объяснять каждый момент
У нас за скрипты будет отвечать класс Script. Я буду объявлять и одновременно реализовывать функции в Script.h/.cpp
Создаем Script.cpp и пишем в нем
Создаем Script.h и пишем в нем
После 2 строчки и перед #endif мы определяем класс скриптов
Этот код пишется для предотвращения взаимного включения файлов. Допустим, что файл Game.h подключает Script.h, а Script.h подключает Game.h — непорядок! А с таким кодом включение выполняется только 1 раз
Теперь пишем внутри этого кода вот это
Первая строчка подключает сам lua.lib из архива.
Для чего нужен extern «C»? Дело в том, что lua написан на С и поэтому такой код необходим для подключения библиотек.
Дальше идет подключение хорошо известных многим файлов для работы с консолью
Теперь приступим к определению класса
Самый главный объект библиотеки Lua для C++ — lua_State, он необходим для выполнения скриптов
Дальше идут публичные функции
Эта функция инициализирует lua_State
Его определение в Script.cpp
Первой строчкой мы инициализируем наш lua_State.
Потом мы объявляем список «подключенных библиотек». Дело в том, что в «чистом» виде в луа есть только функция print(). Для математических и прочих функций требуется подключать специальные библиотеки и потом вызывать их как math.foo, base.foo, io.foo. Для подключения других библиотек добавьте в lualibs, например, <«math», luaopen_math>. Все названия библиотек начинаются с luaopen_. в конце lialibs должен стоять
Просто используем lua_close()
А эта функция выполняет файл. На вход она принимает название файла, например, «C:\\script.lua».
Почему она возвращает int? Просто некоторые скрипты могут содержать return, прерывая работу скрипта и возвращая какое-нибудь значение.
Как вы видите, я выполняю скрипт и возвращаю int. Но возращать функция может не только int, но еще и bool и char*, просто я всегда возвращаю числа (lua_toboolean, lua_tostring)
Теперь мы сделаем функцию, регистрирующую константы (числа, строки, функции)
Мы действуем через шаблоны. Пример вызова функции:
Ее определение
Для каждого возможного значения class T мы определяем свои действия.
*Капитан* последнее определение — регистрация функции
Функции, годные для регистрации, выглядят так:
Где n — количество возвращаемых значений. Если n = 2, то в Луа можно сделать так:
Читайте мануалы по Луа, если были удивлены тем, что одна функция возвращает несколько значений 🙂
Следующая функция создает таблицу для Луа. Если непонятно, что это значит, то тамошная таблица все равно что массив
Следующая функция регистрирует элемент в таблице.
Если вы не знаете Lua, вы, наверное, удивлены тем, что в один массив помещается столько типов? 🙂
На самом деле в элементе таблицы может содержаться еще и таблица, я так никогда не делаю.
Наконец, заполненную таблицу нужно зарегистрировать
Ничего особенного нет
Следующие функции предназначены в основном только для функций типа int foo(lua_State*), которые нужны для регистрации в Луа.
Первая из них — получает количество аргументов
Эта функция нужна, например, для функции Write(), куда можно запихать сколь угодно аргументов, а можно и ни одного
Подобную функцию мы реализуем позже
Следующая функция получает аргумент, переданный функции в скрипте
Можно получить все типы, описывавшиеся ранее, кроме таблиц и функций
index — это номер аргумента. И первый аргумент начинается с 1.
Наконец, последняя функция, которая возвращает значение в скрипт
Боевой код
Пора что-нибудь сделать!
Изменяем main.cpp
Компилируем. Теперь можно приступить к тестированию нашего класса
Помните, я обещал сделать функцию Write? 🙂
Видоизменяем main.cpp
А в папке с проектом создаем файл script.lua
Компилируем и запускаем проект.
Теперь изменяем script.lua
Теперь программа будет выводить по 2 строки («\n» — создание новой строки), ждать нажатия Enter и снова выводить строки.
Экспериментируйте со скриптами!
Вот пример main.cpp с функциями и пример script.lua
Полезные советы
Вопросы и ответы
Основы декларативного программирования на Lua
Луа (Lua) — мощный, быстрый, лёгкий, расширяемый и встраиваемый скриптовый язык программирования. Луа удобно использовать для написания бизнес-логики приложений.
Отдельные части логики приложения часто бывает удобно описывать в декларативном стиле. Декларативный стиль программирования отличается от более привычного многим императивного тем, что описывается, в первую очередь, каково нечто а не как именно оно создаётся. Написание кода в декларативном стиле часто позволяет скрыть лишние детали реализации.
Луа — мультипарадигменный язык программирования. Одна из сильных сторон Луа — хорошая поддержка декларативного стиля. В этой статье я кратко опишу базовые декларативные средства, предоставлямые языком Луа.
Пример
В качестве наивного примера возьмём код создания диалогового окна с текстовым сообщением и кнопкой в императивном стиле:
function build_message_box ( gui_builder )
local my_dialog = gui_builder:dialog ( )
my_dialog:set_title ( «Message Box» )
local my_label = gui_builder:label ( )
my_label:set_text ( «Hello, world!» )
local my_button = gui_builder:button ( )
В декларативном стиле этот код мог бы выглядеть так:
build_message_box = gui:dialog «Message Box»
Гораздо нагляднее. Но как сделать, чтобы это работало?
Основы
Чтобы разобраться в чём дело, нужно знать о некоторых особенностях языка Луа. Я поверхностно расскажу о самых важных для понимания данной статьи. Более подробную информацию можно получить по ссылкам ниже.
Динамическая типизация
Важно помнить, что Луа — язык с динамической типизацией. Это значит, что тип в языке связан не с переменной, а с её значением. Одна и та же переменная может принимать значения разных типов:
Таблицы
Таблицы (table) — основное средство композиции данных в Луа. Таблица — это и record и array и dictionary и set и object.
Для программирования на Луа очень важно хорошо знать этот тип данных. Я кратко остановлюсь лишь на самых важных для понимания деталях.
Создаются таблицы при помощи «конструктора таблиц» (table constructor) — пары фигурных скобок.
Создадим пустую таблицу t:
Запишем в таблицу t строку «one» по ключу 1 и число 1 по ключу «one»:
Содержимое таблицы можно указать при её создании:
Таблица в Луа может содержать ключи и значения всех типов (кроме nil). Но чаще всего в качестве ключей используются целые положительные числа (array) или строки (record / dictionary). Для работы с этими типами ключей язык предоставляет особые средства. Я остановлюсь только на синтаксисе.
Во-первых: при создании таблицы можно опускать положительные целочисленные ключи для идущих подряд элементов. При этом элементы получают ключи в том же порядке, в каком они указаны в конструкторе таблицы. Первый неявный ключ — всегда единица. Явно указанные ключи при выдаче неявных игнорируются.
Следующие две формы записи эквивалентны:
Во-вторых: При использовании строковых литералов в качестве ключей можно опускать кавычки и квадратные скобки, если литерал удовлетворяет ограничениям, налагаемым на луашные идентификаторы.
При создании таблицы следующие две формы записи эквивалентны:
Аналогично для индексации при записи…
Функции
Функции в Луа — значения первого класса. Это значит, что функцию можно использовать во всех случаях, что и, например, строку: присваивать переменной, хранить в таблице в качестве ключа или значения, передавать в качестве аргумента или возвращаемого значения другой функции.
Функции в Луа можно создавать динамически в любом месте кода. При этом внутри функции доступны не только её аргументы и глобальные переменные, но и локальные переменные из внешних областей видимости. Функции в Луа, на самом деле, это замыкания (closures).
function make_multiplier ( coeff )
return function ( value )
return value * coeff
local x5 = make_multiplier ( 5 )
Важно помнить, что «объявление функции» в Луа — на самом деле синтаксический сахар, скрывающий создание значения типа «функция» и присвоение его переменной.
Следующие два способа создания функции эквивалентны. Создаётся новая функция и присваивается глобальной переменной mul.
function mul ( lhs, rhs ) return lhs * rhs end
mul = function ( lhs, rhs ) return lhs * rhs end
Вызов функции без круглых скобок
В Луа можно не ставить круглые скобки при вызове функции с единственным аргументом, если этот аргумент — строковый литерал или конструктор таблицы. Это очень удобно при написании кода в декларативном стиле.
print ( «Shopping list:» )
for name, qty in pairs ( items ) do
Цепочки вызовов
Как я уже упоминал, функция в Луа может вернуть другую функцию (или даже саму себя). Возвращённую функцию можно вызвать сразу же:
chain_print ( 1 ) ( «alpha» ) ( 2 ) ( «beta» ) ( 3 ) ( «gamma» )
В примере выше можно опустить скобки вокруг строковых литералов:
chain_print ( 1 ) «alpha» ( 2 ) «beta» ( 3 ) «gamma»
Для наглядности приведу эквивалентный код без «выкрутасов»:
local tmp1 = chain_print ( 1 )
local tmp2 = tmp1 ( «alpha» )
local tmp3 = tmp2 ( 2 )
local tmp4 = tmp3 ( «beta» )
local tmp5 = tmp4 ( 3 )
Методы
Объекты в Луа — чаще всего реализуются при помощи таблиц.
За методами, обычно, скрываются значения-функции, получаемые индексированием таблицы по строковому ключу-идентификатору.
Луа предоставляет специальный синтаксический сахар для объявления и вызова методов — двоеточие. Двоеточие скрывает первый аргумент метода — self, сам объект.
Следующие три формы записи эквивалентны. Создаётся глобальная переменная myobj, в которую записывается таблица-объект с единственным методом foo.
function myobj:foo ( b )
function myobj.foo ( self, b )
myobj [ «foo» ] = function ( self, b )
print ( self [ «a_» ] + b )
Примечание: Как можно заметить, при вызове метода без использования двоеточия, myobj упоминается два раза. Следующие два примера, очевидно, не эквивалентны в случае, когда get_myobj() выполняется с побочными эффектами.
Чтобы код был эквивалентен варианту с двоеточием, нужна временная переменная:
local tmp = get_myobj ( )
При вызове методов через двоеточие также можно опускать круглые скобки, если методу передаётся единственный явный аргумент — строковый литерал или конструктор таблицы:
Реализация
Теперь мы знаем почти всё, что нужно для того, чтобы наш декларативный код заработал. Напомню как он выглядит:
build_message_box = gui:dialog «Message Box»
Что же там написано?
Приведу эквивалентную реализацию без декларативных «выкрутасов»:
local tmp_1 = gui : label ( «Hello, world!» )
local tmp_2 = gui : button ( «OK» )
local button = tmp_2 ( < >)
local tmp_3 = gui : dialog ( «Message Box» )
Интерфейс объекта gui
Как мы видим, всю работу выполняет объект gui — «конструктор» нашей функции build_message_box(). Теперь уже видны очертания его интерфейса.
Опишем их в псевдокоде:
Декларативный метод
В интерфейсе объекта gui чётко виден шаблон — метод, принимающий часть аргументов и возвращающий функцию, принимающую остальные аргументы и возвращающую окончательный результат.
Для простоты, будем считать, что мы надстраиваем декларативную модель поверх существующего API gui_builder, упомянутого в императивном примере в начале статьи. Напомню код примера:
function build_message_box ( gui_builder )
local my_dialog = gui_builder:dialog ( )
my_dialog:set_title ( «Message Box» )
local my_label = gui_builder:label ( )
my_label:set_text ( «Hello, world!» )
local my_button = gui_builder:button ( )
Попробуем представить себе, как мог бы выглядеть метод gui:dialog():
return function ( element_list )
return function ( gui_builder )
local my_dialog = gui_builder:dialog ( )
element_list [ i ] ( gui_builder )
Ситуация с [gui_element] прояснилась. Это — функция-конструктор, создающая соответствующий элемент диалога.
Функция build_message_box() создаёт диалог, вызывает функции-конструкторы для дочерних элементов, после чего добавляет эти элементы к диалогу. Функции-конструкторы для элементов диалога явно очень похожи по устройству на build_message_box(). Генерирующие их методы объекта gui тоже будут похожи.
Напрашивается как минимум такое обобщение:
function declarative_method ( method )
return function ( self, name )
return function ( data )
return method ( self, name, data )
Теперь gui:dialog() можно записать нагляднее:
gui.dialog = declarative_method ( function ( self, title, element_list )
return function ( gui_builder )
local my_dialog = gui_builder:dialog ( )
element_list [ i ] ( gui_builder )
Реализация методов gui:label() и gui:button() стала очевидна:
gui.label = declarative_method ( function ( self, text, parameters )
return function ( gui_builder )
local my_label = gui_builder:label ( )
if parameters.font_size then
gui.button = declarative_method ( function ( self, title, parameters )
return function ( gui_builder )
local my_button = gui_builder:button ( )
— Так сложилось, что у нашей кнопки нет параметров.
Что же у нас получилось?
Проблема улучшения читаемости нашего наивного императивного примера успешно решена.
В результате нашей работы мы, фактически, реализовали с помощью Луа собственный предметно-ориентированный декларативный язык описания «игрушечного» пользовательского интерфейса (DSL).
Благодаря особенностям Луа реализация получилась дешёвой и достаточно гибкой и мощной.
В реальной жизни всё, конечно, несколько сложнее. В зависимости от решаемой задачи нашему механизму могут потребоваться достаточно серьёзные доработки.
Например, если на нашем микро-языке будут писать пользователи, нам понадобится поместить выполняемый код в песочницу. Также, нужно будет серьёзно поработать над понятностью сообщений об ошибках.
Описанный механизм — не панацея, и применять его нужно с умом как и любой другой. Но, тем не менее, даже в таком простейшем виде, декларативный код может сильно повысить читаемость программы и облегчить жизнь программистам.
Полностью работающий пример можно посмотреть здесь.
Информация Гайд Всё о Lua скриптинге для MoonLoader
Для лёгкой и удобной работы с кодом Lua скриптов вам понадобится настроить для себя среду разработки. Для работы с Lua достаточно любого текстового редактора, но какой-нибудь блокнот Windows для этого подходит совсем плохо, поэтому лучше использовать специализированные программы. На текущий момент полная поддержка MoonLoader есть в Atom и Notepad++, помимо этого есть пользовательские дополнения для Visual Studio Code и Sublime Text.
Проект по-умолчанию.
В меню File выбираем пункт Open Folder. и указываем путь до папки moonloader, после этого она откроется как проект.
Проект по-умолчанию.
Как и в Atom, здесь есть возможность показа меню проекта, а точнее «Папка как Проект». В меню «Файл» выбираем пункт «Открыть Папку как Проект» и указываем путь к папке «moonloader».
Кодировка по-умолчанию.
Над лентой выбираем пункт Опции и переходим в Настройки. В меню слева выбираем пункт Новый документ и в разделе кодировки ставим флажок на список, в котором выбираем кодировку Windows-1251
После установки среды разработки, изучения основ Lua и ознакомления с документацией MoonLoader, можно приступать от теории к практике. Давайте сначала рассмотрим самое основное, на всякий случай.
В этом примере показаны не все директивы, за полным списком обращайтесь к соответствующей странице на вики.
События и колбэки
Событиями, а точнее их обработчиками, в MoonLoader называются функции, вызывающиеся в скриптах автоматически при каком-либо действии в игре, требующим обработки. Обработчики событий могут иметь входящие и возвращаемые параметры: входящие передают какую-то информацию скрипту, а возвращаемые позволяют повлиять на дальнейшую обработку после совершения события.
Зарегистрировать обработчик события можно двумя способами: просто добавить в скрипт функцию с соответствующим именем, либо воспользоваться функцией addEventHandler. Учтите, что первым способом обработчик может быть зарегистрирован только один раз.
Скрипты с зарегистрированными событиями не завершаются самостоятельно.
Пример: onScriptTerminate вызывается при завершении какого-либо скрипта
С основными принципами разработки вы теперь знакомы и при этих знаниях сможете выполнить большинство задач, однако некоторые задачи требуют применения специальных техник. Давайте рассмотрим некоторые из них.
Создание модулей
Модули делятся на два типа: Lua и DLL. Lua-модули пишутся, как вы уже могли догадаться, на языке Lua и в результате представляют из себя привычные Lua-скрипты, только с некоторыми особенностями.
Давайте рассмотрим пример простого модуля, назовём его example:
Lua 5.3 Руководство
by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes
перевел Ведерников Николай, Лысьва.
1 – Введение
Как и любое другое руководство, это руководство местами сухо. Описание решений принятых в основе дизайна Lua есть на технических страницах официального сайта. Детальное введение в программирование на Lua представлено в книге Роберто Иерусалимского Programming in Lua.
2 – Базовые концепции
Этот раздел описывает базовые концепции языка.
2.1 – Значения и типы
Lua динамически типизированный язык. Это означает, что значения не имеют типов; только значения. Язык не имеет определений типов. Все значения несут свой собственный тип.
Все значения в Lua первоклассные. Это означает что все значения могут быть сохранены в переменных, переданы как аргументы другим функциям, и возвращены как результаты.
В Lua существует восемь базовых типов: nil, boolean, number, string, function, userdata, thread и table.
Тип nil (нуль) имеет одно единственное значение, nil, его главное свойство это отличаться от любых других значений; обычно это означает отсутствие используемого значения.
Тип boolean (логический) имеет два значения: false (ложь) и true (истина). Оба nil и false означают false; любое другое значение означает true.
Тип number (число) представляет целые (integer) и вещественные (float) числа.
Тип string (строка) представляет неизменные последовательности байт. Строки в Lua могут содержать любое 8-битное значение, включая нули (‘ \0 ‘). Также Lua противник кодировок; никаких предположений о содержимом строки не делается.
Lua может вызывать и манипулировать функциями написанными на Lua и на С (см. §3.4.10). Оба типа функций в Lua представлены типом function (функция).
Тип thread (поток) представляет независимый поток выполнения и используется для реализации сопрограмм (coroutine) (см. §2.6). Lua потоки это не реальные потоки операционной системы. Lua поддерживает сопрограммы на всех системах, даже на тех, где это не поддерживается операционной системой.
Как и индексы, значения полей в таблице могут быть любого типа. В частности, т.к. функции это первоклассные значения, поля таблицы могут содержать функции. Такие таблицы также могут содержать методы (см. §3.4.11).
Библиотечная функция type возвращает строку с названием переданного ей типа (см. §6.1).
2.2 – Окружения и глобальное окружение
Lua хранит особое окружение, называемое глобальное окружение. Это значение хранится по специальному индексу в С реестре (см. §4.5). В Lua, глобальная переменная _G инициализируется тем же значением. ( _G никогда не используется непосредственно.)
Когда Lua загружает кусок (chunk), по умолчанию его _ENV upvalue присваивается значение глобального окружения (см. load ). Следовательно, по умолчанию, свободные имена в Lua коде ссылаются на элементы в глобальном окружении (и, следовательно, они также называются глобальными переменными). Кроме того, все стандартные библиотеки загружаются в глобальное окружение и некоторые их функции действуют в этом окружении. Вы можете использовать load (или loadfile ) для загрузки куска с другим окружением. (В C, вы загружаете кусок и затем изменяете его первое upvalue.)
2.3 – Обработка ошибок
Так как Lua встроенный язык расширений, все Lua действия начинаются с C кода; код в хостовой программе вызывает функцию в Lua библиотеке. (При использовании автономного интерпретатора Lua, программа lua выступает в качестве хоста.) Всякий раз, когда происходит ошибка компиляции или выполнения куска Lua кода, управление возвращается хостовой программе, которая может предпринять соответствующие меры (такие как печать сообщения об ошибке).
При каждой ошибке, создается объект ошибки (также называемый сообщением об ошибке) с информацией об ошибке. Самостоятельно Lua генерирует только те ошибки, где объект ошибки содержит строку, но программы могут генерировать ошибки с любым значением в объекте ошибки. Объекты ошибки (исключения) пробрасываются вверх в Lua или в хост для обработки.
2.4 – Метатаблицы и метаметоды
Каждое значение в Lua может иметь метатаблицу. Эта метатаблица обычная Lua таблица, которая определяет поведение оригинального значения в определенных специальных операциях. Вы можете изменять различные аспекты поведения в операциях со значением, изменяя специфические поля в метатаблице. Например, когда не цифровое значение является операндом в сложении, Lua проверяет есть ли в его метатаблице поле » __add » с функцией. И, если оно существует, Lua вызывает эту функцию для выполнения сложения.
Таблицы и полные пользовательские данные (full userdata) имеют индивидуальные метатаблицы (хотя таблицы и пользовательские данные могут совместно использовать свои метатаблицы). Значения остальных типов используют одну метатаблицу на тип; т.е, существует одна метатаблица для всех чисел, одна для всех строк и т.д. По умолчанию, значения не имеют метатаблицу, но строковая библиотека создает метатаблицу для строкового типа (см. §6.4).
Метатаблица контролирует, как объект ведет себя в арифметических и битовых операциях, сравнениях при сортировке, конкатенации, определении длины, вызовах и индексировании. Метатаблица также может определять функцию, которая будет вызвана для таблицы или пользовательских данных при уничтожении сборщиком мусора (§2.5).
Детальное описание событий, контролируемых метатаблицами, представлено ниже. Каждая операция идентифицируется соответсвующим именем события. Ключ для каждого события это строка начинающаяся с двух подчеркиваний, ‘ __ ‘; например, ключ для операции «add» строка » __add «. Имейте ввиду, что запросы метаметодов всегда прямые; доступ к метаметоду не запускает других метаметодов
Хорошая практика, добавлять все необходимые метаметоды в таблицу перед тем, как назначить её метатаблицей какого-то объекта. В частности, метаметод » __gc » работает только если была соблюдена эта последовательность (см. §2.5.1).
2.5 – Сборка мусора
Lua выполняет автоматическое управление памятью. Это означает, что вы не должны беспокоиться о выделении памяти новым объектам или об освобождении памяти, когда объекты больше не нужны. Lua управляет памятью, запуская сборщик мусора для сборки всех мёртвых объектов (т.е., объектов более не доступных из Lua). Вся память, используемая Lua, подлежит автоматическому управлению: строки, таблицы, пользовательские данные, функции, потоки, внутренние структуры и т.д.
Lua реализует пошаговый отмечающий-и-очищающий сборщик. Для контроля циклов очистки мусора используются два числа: пауза сборщика мусора и множитель шагов сборщика мусора. Оба числа используют процентные пункты как единицы (т.е., значение 100 означает внутреннее значение 1).
Пауза сборщика мусора контролирует, как долго сборщик ждет перед началом нового цикла. Чем больше значение, тем менее агрессивен сборщик. Значения меньше 100 означают, что сборщик не останавливается перед началом нового цикла. Значение 200 означает, что сборщик, перед тем как начать новый цикл, ждет повышения использования общей памяти в два раза.
Множитель шагов сборщика мусора контролирует относительную скорость сборщика по отношению к скорости выделения памяти. Большие значения делают сборщик более агрессивным, но также увеличивают размер каждого шага. Вы не должны использовать значения меньше 100, т.к. они сделают сборщик настолько медленным, что он никогда не завершит цикл. По умолчанию, используется значение 200, которое означает, что сборщик выполняется в два раза быстрее скорости выделения памяти.
Если вы установите множитель шагов очень большым (больше чем 10% от максимального числа байт, которые может использовать программа), сборщик поведет себя как останавливающий мир. Если вы установите паузу 200, сборщик будет вести себя как в старых версиях Lua, производя полную очистку каждый раз, когда Lua удваивает использование памяти.
Вы можете изменять эти числа, вызывая lua_gc в C или collectgarbage в Lua. Вы также можете использовать эти функции для прямого контроля сборщика (т.е., его остановки и перезапуска).
2.5.1 – Метаметоды сборки мусора
Вы можете установить метаметоды сборки мусора для таблиц и, используя C API, для полных пользовательских данных (см. §2.4). Эти метаметоды также называются деструкторы (finalizers). Деструкторы позволяют координировать сборку мусора в Lua с внешним управлением ресурсами (таким как закрытие файлов, сетевый подключения, подключения к базам данных или освобождение вашей памяти).
Для объекта (таблицы или пользовательских данных) чтобы быть уничтоженным при сборке мусора, вы должны отметить его на уничтожение. Вы отмечаете объект на уничтожение, когда устанавливаете для него метатаблицу, содержащую поле » __gc «. Имейте ввиду, что если вы установите метатаблицу без поля __gc и затем создадите это поле в метатаблице, то объект не будет отмечен на уничтожение.
Когда отмеченный объект становится мусором, он не уничтожается напрямую сборщиком мусора. Вместо этого, Lua ложит его в список. После завершения сборки, Lua проходит по этому списку. Для каждого объекта в списке проверяется метаметод __gc : если это функция, Lua вызывает её с объектом в качестве единственного аргумента; если метаметод не функция, Lua просто игнорирует его.
В конце каждого цикла сборки мусора, деструкторы объектов вызываются в порядке обратном порядку их отметки на уничтожение; т.е., первым деструктор будет вызван для последнего отмеченного на уничтожение объекта. Выполнение каждого деструктора может произойти в любое время при выполнении основного кода.
Так как объект подлежащий уничтожению должен быть использован в деструкторе, этот объект (и остальные объекты доступные через него) должны быть воскрешены Lua. Обычно, это воскрешение нерезидентно, и память объекта освобождается при следующем цикле сборки мусора. Тем не менее, если деструктор сохраняет объект в каком-то глобальном месте (т.е. глобальной переменной), воскрешение постоянно. Более того, если деструктор отмечает уничтожаемый объект для уничтожения снова, его деструктор будет вызван снова в следующем цикле, где объект не доступен. В любом случае, память объекта освобождается только в цикле сборки мусора, где объект недоступен и не отмечен на уничтожение через деструктор.
Когда вы закрываете контекст (см. lua_close ), Lua вызывает деструкторы всех объектов отмеченных на уничтожение, следуя порядку обратному порядку их отметки на уничтожение. Если любой деструктор отмечает объекты для уничтожения в этой фазе, эти отметки не имеют никакого эффекта.
2.5.2 – Слабые таблицы
Слабая таблица может иметь слабые ключи, слабые значения или и то и другое. Таблица со слабыми значениями позволяет уничтожать её значения, но препятствует уничтожению её ключей. Таблица со слабыми значениями и ключами позволяет уничтожать и ключи и значения. В любом случае, если ключ или значение уничтожены, эта пара удаляется из таблицы. Слабость таблицы контролируется полем __mode в её метатаблице. Если поле __mode это строка содержащая символ ‘ k ‘, в таблице слабые ключи. Если поле __mode содержит ‘ v ‘, в таблице слабые значения.
Таблица со слабыми ключами и сильными значениями называется эфемерной таблицей (ephemeron table). В эфемерной таблице, значение достижимо только если его ключ достижим. В частности, если ссылка на ключ приходит через его значение, пара удаляется.
Любое изменение слабости таблицы будет иметь эффект только в следующем цикле сборки мусора. В частности, если вы сменили слабый на сильный режим, Lua может продолжить сбор некоторых элементов из этой таблицы, пока изменения не будут иметь эффект.
Только объекты, имеющие явную конструкцию, удаляются из слабых таблиц. Значения, такие как числа и легкие C функции, не являются субъектами для сборки мусора, и следовательно не удаляются из слабых таблиц (пока их ассоциированные значения не удалены). Хотя строки субъекты для сборки мусора, они не имеют явную конструкцию, и следовательно не удаляются из слабых таблиц.
Воскрешенные объекты (т.е., объекты подлежащие уничтожению и объекты достпупные через них) имеют специальное поведение в слабых таблицах. Они удаляются из слабых значений перед запуском их деструкторов, но удаляются из слабых ключей только в следующем цикле сборки, после запуска их деструкторов, когда эти объекты действительно освобождены. Это поведение позволяет деструктору получить доступ к свойствам, ассоциированным с объектом через слабые таблицы.
Если слабая таблица среди воскрешенных объектов в цикле сборки, она не может быть правильно очищена до следующего цикла сборки.
2.6 – Сопрограммы
Lua поддерживает сопрограммы, так называемую совместную многопоточность. Сопрограмма в Lua представляет независимый поток выполнения. В отличе от потоков в многопоточных системах, сопрограммма прерывает свое исполнение только явным вызовом функции yield (уступить).
Сопрограмма может завершить свое исполнение двумя путями: нормально, когда её главная функция вернет управление (явно или не явно, после последней инструкции); и ненормально, если произойдет незащищенная ошибка. В случае нормального завершения, coroutine.resume вернет true и значения, возвращенные главной фунцией сопрограммы. В случае ошибок, coroutine.resume вернет false и сообщение об ошибке.
Для примера работы сопрограммы, рассмотрите следующий код:
Запустив его, вы получите следующий результат:
3 – Язык
Этот раздел описывает лексику, синтаксис и семантику Lua. Другими словами, этот раздел описывает какие лексемы (tokens) правильны, как они могут быть скомбинированы, и что их комбинации означают.
Языковые конструкции будут объясняться используя обычную расширенную БНФ нотацию, в которой <a> означает 0 или больше a, и [a] означает опциональную a. Нетерминалы показаны как non-terminal, ключевые слова показаны как kword, и другие терминальные символы показаны как ‘=’. Полный синтасис Lua описан в §9 в конце руководства.
3.1 – Лексические соглашения
Имена (также называемые идентификаторами) в Lua могут быть любой строкой из букв, цифр и подчеркиваний, не начинающейся с цифры. Идентификаторы используются для именования значений, полей таблиц и меток (labels).
Следующие ключевые слова зарезервированы и не могут использоваться как имена:
Следующие строки разделяют другие лексемы:
Литеральные строки могут быть ограничены сочетающимися одинарными или двойными кавычками, и могут содержать С-подобные управляющие последовательности: ‘ \a ‘ (bell), ‘ \b ‘ (backspace), ‘ \f ‘ (form feed), ‘ \n ‘ (newline), ‘ \r ‘ (carriage return), ‘ \t ‘ (horizontal tab), ‘ \v ‘ (vertical tab), ‘ \\ ‘ (backslash), ‘ \» ‘ (двойная кавычка) и ‘ \’ ‘ (апостроф [одинарная кавычка]). Обратный слеш, сопровождаемый реальным переходом на новую строку (newline), формирует переход строки (newline) в строке (string). Управляющая последовательность ‘ \z ‘ пропускает следующий за ней диапазон пробелов, включая переходы строки; это особенно полезно, чтобы разбить и отступить длинную литеральную строку на несколько линий без добавления переводов строки и пробелов в содержимое строки.
Любой байт в литеральной строке не подвержен влиянию правил своего представления. Тем не менее, Lua открывает файлы для парсинга в текстовом режиме, и функции системы могут иметь проблемы с некоторыми управляющими символами. Поэтому, для безопасного представления не текстовых данных в строке, следует использовать управляющие последовательности.
Для удобства, когда открывается длинная скобка с непосредственным переводом строки за ней, перевод строки не включается в результирующую строку. Например, в системе использующей ASCII (в которой ‘ a ‘ кодируется как 97, newline кодируется как 10 и ‘ 1 ‘ кодируется как 49), пять литеральных строк ниже кодируют одинаковые строки:
Примеры допустимых вещественных чисел:
3.2 – Переменные
Одно имя может означать глобальную или локальную переменную (или формальный параметр функции, который является частным случаем локальной переменной):
Name означает идентификаторы, как описано в §3.1.
Любое имя переменной предполагается глобальным, пока явно не определено локальным (см. §3.3.7). Локальные переменные лексически ограниченные: локальные переменные свободно доступны функциям, определенным внутри их области видимости (см. §3.5).
Перед первым присваиванием переменной, её значение равно nil.
Квадратные скобки используются для индексирования в таблице:
3.3 – Выражения
Lua поддерживает почти стандартный набор выражений, подобный наборам в Pascal или C. Этот набор включает в себя присваивания, управляющие структуры, вызовы функций и определения переменных.
3.3.1 – Блоки
Lua допускает пустые выражения, что позволяет вам разделять выражения с помощью точки с запятой (;), начинать блок с точки с запятой или писать две точки с запятой подряд:
Вызовы функций и присваивания могут начинаться с открывающейся скобки. Эта возможность ведет к неоднозначности в грамматике Lua. Рассмотрим следующий фрагмент:
Грамматика может рассматривать это двумя путями:
Текущий парсер всегда рассматривает такие констркции первым путем, интерпретируя открывающуюся скобку, как начало аргументов для вызова. Для избежания этой неоднозначности, лучше всегда ставить точку с запятой (;) перед выражениями начинающимися со скобок:
Блок может быть явно выделен для создания единственного выражения:
Явные блоки полезны для контроля за областью видимости переменных. Явные блоки также иногда используются для добавления выражения return в середину другого блока (см. §3.3.4).
3.3.2 – Куски
Единица компиляции в Lua называется куском (chunk). Синтаксически, кусок это простой блок:
Кусок может храниться в файле или в строке внутри хостовой программы. Для запуска куска, Lua сперва загружает его (load), прекомпилируя код куска в инструкции виртуальной машины, и затем запускает скомпилированный код.
3.3.3 – Присваивание
Lua позволяет множественные присваивания. Синтаксис присваивания определяет список переменных с левой строны и список выражений с правой стороны. Элементы в обоих списках разделяются запятыми:
Выражения обсуждаются в §3.4.
Перед присваиванием, список значений корректируется до длины списка переменных. Если значений больше чем нужно, лишние значения отбрасываются. Если значений меньше чем нужно, список расширяется добавлением необходимого числа значений nil. Если список выражений заканчивается вызовом функции, все значения, возвращенные этой функцией, попадают в список значений перед присваиванием. (кроме вызова заключенного в скобки; см. §3.4).
Оператор присваивания сперва вычисляет все свои выражения и лишь затем выполняет присваивание. Таким образом код
Присванивание глобальной переменной x = val эквивалентно присваиванию _ENV.x = val (см. §2.2).
3.3.4 – Управляющие конструкции
Управляющие конструкции if, while и repeat имеют обычное значение и знакомый синтаксис:
Lua также имеет две формы оператора for (см. §3.3.5).
Условное выражение в управляющей конструкции может возвращать любое значение. False и nil рассматриваются как false. Все значения, отличные от nil и false, рассматриваются как true (в частности, число 0 и пустая строка это тоже true).
В цикле repeat–until, внутренний блок заканчивается после всего условия, а не на ключевом слове until. Так, условие может ссылаться на локальные переменные объявленные внутри цикла.
Оператор goto передает управление на метку. По синтаксическим причинам, метки в Lua тоже считаются выражениями:
Метка видна в блоке где объявлена, за исключением вложенных блоков, где определена метка с таким же именем и вложенных функций. Goto может переходить на любую видимую метку, так далеко, пока не войдет в область видимости локальной переменной.
Метки и пустые выражения называются пустыми выражениями, так как они не производят дейтсвий.
Выражение break завершает исполнение цикла while, repeat или for, пропуская оставшиеся команды цикла:
break завершает самый внутренний цикл.
Выражение return используется для возврата значений из функции или куска (который является анонимной функцией). Функции могут возвращать несколько значений, поэтому синтаксис для выражения return следующий:
3.3.5 – Конструкция For
Конструкция for имеет две формы: цифровую и общую.
Цифровой цикл for повторяет блок кода, пока управляющая переменная изменяется в арифметической прогрессии. Он имеет следующий синтаксис:
block повторяется для name начиная с первого значения exp, пока не достигнет значения втрого exp, шагами равными третьему exp. Более точно, выражение for
эквивалентно следующему коду:
Общий for работает через функции, называемые итераторами. На каждой итерации, функция-итератор вызывается чтобы выдать новое значение, остановка происходит, когда новое значение равно nil. Общий цикл for имеет следующий синтаксис:
эквивалентно следующему коду:
3.3.6 – Вызовы функций как выражения
Чтобы позволить побочные эффекты, вызовы функций могут запускаться как выражения:
В этом случае все возвращенные значения отбрасываются. Вызовы функций рассматриваются в §3.4.10.
3.3.7 – Локальные определения
Локальные переменные могут быть объявлены в любой части блока. Определение может содержать начальное присваивание (инициализацию):
Если есть начальное присваивание, то оно имеет семантику схожую с множественным присваиванием (см. §3.3.3). Иначе, все переменные инициализируются значением nil.
Кусок также является блоком (см. §3.3.2), и следовательно локальные переменные могут быть объявлены в куске вне всякого явного блока.
Правила видимости локальных переменных рассматриваются в §3.5.
3.4 – Выражения
Базовые выражения в Lua следующие:
Бинарные операторы, включая арифметические (см. §3.4.1), битовые операторы (см. §3.4.2), операторы сравнения (см. §3.4.4), логические операторы (см. §3.4.5), и оператор конкатенации (см. §3.4.6). Одноместные операторы, включая одноместный минус (см. §3.4.1), одноместный битовый НЕ (см. §3.4.2), одноместный логический not (см. §3.4.5), и одноместный оператор длины (см. §3.4.7).
Функции и выражения с переменным числом аргументов могут возвращать несколько значений. Если вызов функции используется как выражение (см. §3.3.6), он возвращает список скорректированный до нуля элементов, т.е. отброшены все возвращенные значения. Если выражение используется последним элементом в списке выражений (или оно только одно), то корректировка не производится (если выражение не заключено в скобки). Во всех остальных случаях Lua корректирует список результатов до одного элемента, отбрасывая все значения кроме первого, или добавляя один nil, если значений нет.
Здесь несколько примеров:
Любое выражение, заключенное в скобки, всегда возвращает только одно значение. Т.е., (f(x,y,z)) всегда одно значение, даже если f возвращает несколько значений. (Значение (f(x,y,z)) это первое из значений возвращенных f или nil, если f не вернет ни одного значения.)
3.4.1 – Арифметические операторы
За исключением возведения в степень и деления, арифметические операторы работают следующим образом: Если оба операнда целые, операция производится над целыми и результатом является целое. Иначе, если оба операнда числа или строки, которые могут быть сконвертированы в числа (см. §3.4.3), они конвертируются в числа с плавающей запятой (float), операции производятся согласно обычным правилам арифметики вещественных чисел (обычно стандарт IEEE 754), и результатом будет число с плавающей запятой.
Возведение в степень и деление ( / ) всегда конвертирует операнды в вещественные числа и результат вещественное число. Возведение в степень использует функцию pow из ISO C, она работает и для не целых экспонент тоже.
Модуль определено как остаток от деления, которое округляет частное по отношению к минус беспонечности (целочисленное деление).
В случае переполнения целочисленной арифметики, все операции циклически переходят, в соответствии с обычными правилами арифметики двоичного дополнения. (Другими словами, они возвращают уникальное представимое целое, которое равно по модулю 2 64 математическому результату.)
3.4.2 – Битовые операторы
: одноместное битовое НЕ
Все битовые операторы преобразуют свои операнды в целые (см. §3.4.3), оперируют всеми битами этих целых и результат тоже целое.
Правый и левый сдвиги заполняют свободные биты нулями. Отрицательное смещение сдвигает в противоположном направлении; смещения с абсолютными значениями большими (или равными), чем число бит в целом, дают результат ноль (все биты сдвинуты наружу).
3.4.3 – Приведения и преобразования
Lua производит некоторые автоматические преобразования между типами и представлениями во время выполнения. Битовые операторы всегда конвертируют вещественные операнды в целые. Возведение в степень и деление всегда конвертируют целые операнды в вещественные. Все остальные арифметические операции, примененные к смешанным числам (целые и вещественные), преобразуют целые цисла в вещественные; это называется обычное правило. C API также конвертирует целые в вещественные и вещественные в целые, при необходимости. Более того, конкатенация строк принимает числа, как аргументы между строками.
Lua также конвертирует строки в числа, когда ожидается число.
В преобразовании целого в вещественное, если целое значение имеет точное представление как вещественное, это представление и будет результатом. Иначе, преобразование получает ближайшее большее или ближайшее меньшее представимое значение. Этот тип преобразования всегда успешен.
Преобразование вещественного в целое проверяет, что вещественное имеет точное представление как целое (т.е., вещественное имеет целое значение и в диапазоне представления целых). Если это так, то это представление будет результатом. Иначе, преобразование терпит неудачу.
Преобразование строк в числа идет следующим образом: Первое, строка преобразуется в целое или вещественное, следуя синтаксису и правилам лексера Lua. (Строка может содержать начальные и конечные пробелы и знак.) Затем, получившееся число (целое или вещественное) преобразуется в тип (целое или вещественное), требуемый в данном контексте (т.е., требуемый операцией которая конвертирует принудительно).
Преобразование чисел в строки использует не определенный читабельный формат. Для полного контроля над тем, как числа конвертируются в строки, используйте функцию format из строковой библиотеки (см. string.format ).
3.4.4 – Операторы сравнения
Эти операторы всегда возвращают false или true.
Равенство ( == ) сперва сравнивает типы операндов. Если типы разные, то результат false. Иначе, сравниваются значения операндов. Строки сравниваются очевидным способом. Числа равны, если они обозначают одинаковые математические значения.
Таблицы, пользовательские данные и потоки сравниваются по ссылке: два объекта считаются равными только, если это один и тот же объект. Всегда, когда вы создаете новый объект (таблицу, пользовательские данные или поток), этот новый объект отличен от любого существующего объекта. Замыкания (closure) с одинаковыми ссылками всегда равны. Замыкания с любыми обнаруживаемыми различиями (разное поведение, разное определение) всегда различны.
Используя метаметод «eq», вы можете изменить способ, которым Lua сравнивает таблицы и пользовательские данные (см. §2.4).
Проверка на равенство не конвертирует строки в числа и наоборот. Так, «0»==0 вернет false, t[0] и t[«0»] означают разные элементы в таблице.
= это явное отрицание равенства ( == ).
Следуя стандарту IEEE 754, NaN рассматривается как никакой: не меньший, не больший, не равный ни одному значению (включая себя самого).
3.4.5 – Логические операторы
В Lua существуют следующие логические операторы: and (И), or (ИЛИ) и not (НЕ). Как и управляющие структуры (см. §3.3.4), все логические операторы считают false и nil как false, а все остальное как true.
Оператор отрицания not всегда возвращает false или true. Оператор конъюнкции and возвращает свой первый аргумент, если его значение false или nil; иначе, and возвращает второй аргумент. Оператор дизъюнкции or возвращает свой первый аргумент, если его значение отлично от nil и false; иначе, or возвращает второй аргумент. Оба and и or используют ленивое вычисление; т.е., второй операнд вычисляется только если необходимо. Несколько примеров:
3.4.6 – Конкатенация
3.4.7 – Оператор длины
Программа может модифицировать поведение оператора длины для любого значения, кроме строк, используя метаметод __len (см. §2.4).
Пока метаметод __len не определен, длина таблицы t определена только, если таблица t последовательность, т.е., набор её положительных числовых ключей равен для какого-то положительного целого n. В этом случае, n это длина. Имейте ввиду, таблица как
3.4.8 – Приоритет
Приоритет операторов в Lua представлен далее, с меньшего к большему приоритету:
3.4.9 – Конструкторы таблиц
Порядок присваиваний в конструкторе не определен. (Этот порядок важен только для повторяющихся ключей.)
Если последнее поле в списке имеет вид exp и выражение это вызов функции или обозначение множества аргументов (. ), то все значения, возвращенные этим выражением, последовательно включаются в список (см. §3.4.10).
Список полей может иметь опциональный конечный разделитель, для удобства машинно-сгенерированного кода.
3.4.10 – Вызовы функций
Вызов функции в Lua имеет следующий синтаксис:
При вызове функции, сперва вычисляются prefixexp и args. Если значение prefixexp имеет тип function, то вызывается эта функция с данными аргументами. Иначе, для объекта prefixexp вызывается метаметод «call», в качестве первого параметра передается значение prefixexp, затем остальные аргументы вызова. (см. §2.4).
Аргументы имеют следующий синтаксис:
Все выражения в аргументах вычисляются перед вызовом.
Вызов вида f<fields> это синтаксическое украшение для f(<fields>) ; т.е. в качестве аргумента передается одна новая таблица.
Вызов вида f’string‘ (или f»string» или f[[string]] ) это синтаксическое украшение для f(‘string‘) ; т.е. в качестве аргумента передается одна литеральная строка.
Вызов вида return functioncall называется хвостовым вызовом (tail call). Lua реализует соответствующие хвостовые вызовы (proper tail call) (или соответствующую хвостовую рекурсию): в хвостовом вызове, вызванная функция повторно использует элементы стека вызывающей функции. Следовательно, не существует лимита на число вложенных хвостовых вызовов, выполняемых программой. Тем не менее, хвостовой вызов затирает любую отладочную информацию о вызывающей функции. Имейте ввиду, что хвостовой вызов происходит только с конкретным синтаксисом, где return имеет только один вызов функции в качестве аргумента; при таком синтаксисе вызывающая функция возвращает тоже, что и вызванная функция. Так, в следующих примерах хвостовой вызов не происходит:
3.4.11 – Определения функций
Синтаксис для определения функции:
Следующее синтаксическое украшение упрощает определение функций:
Параметры действуют как локальные переменные, инициализированные значениями аргументов:
Например, рассмотрим следующие определения:
Мы получим следующее соответствие аргументов параметрам и vararg-выражению:
Результаты возвращаются выражением return (см. §3.3.4). Если управление достигает конца функции без выражения return, то функция не возвращает результатов.
Существует системозависимый предел числа значений, которые может вернуть функция. Этот предел гарантированно больше 1000.
это синтаксическое украшение для
3.5 – Правила видимости
Согласно правилам видимости, локальные переменные могут быть свободно доступны функциям, определенным в их зоне видимости. Локальная переменная, которая используется внутренней функцией, внутри данной функции называется upvalue или внешняя локальная переменная.
Обратите внимание, каждое выполнение выражения local определяет новую локальную переменную. Рассмотрим следующий пример:
4 – Программный интерфейс (API)
Каждый раз, когда мы используем термин «функция», любая возможность в API может быть реализована как макрос. Везде, где не оговорено обратное, все такие макросы используют каждый свой аргумент только один раз (исключая первый аргумент, который всегда является контекстом Lua) и не генерируют ни каких скрытых побочных эффектов.
4.1 – Стек
Чтобы передавать значения из и в С Lua использует виртуальный стек. Каждый элемент этого стека представляет Lua значение (nil, number, string и др.).
Кажды раз, когда Lua вызывает C, вызванная функция получает новый стек, который независим от предыдущих стеков и стеков активных в данный момент C функций. Этот стек изначально содержит все аргументы для C функции, туда же C функция ложит свои результаты, чтобы вернуть вызывающей стороне (см. lua_CFunction ).
4.2 – Размер стека
Когда вы работаете с Lua API, вы ответственны за гарантирование согласованности. В частности, вы ответственны за контроль над переполнением стека. Вы можете использовать функцию lua_checkstack чтобы проверять, что стек имеет достаточно места для новых элементов.
Каждый раз, когда Lua вызывает C, он убеждается, что стек имеет место для как минимум LUA_MINSTACK дополнительных слотов. LUA_MINSTACK определен равным 20, так обычно вы не должны беспокоиться о размере стека, пока ваш код не содержит циклы, помещающие элементы в стек.
4.3 – Правильные и допустимые индексы
Любая API функция, получающая стековые индексы, работает только с правильными индексами или допустимыми индексами.
Функции, не нуждающиеся в специфической изменяемой позиции, а нуждающиеся только в значении (т.е., функции запросов), могут быть вызваны с допустимыми индексами. Допустимым индексом может быть любой правильный индекс, но это также может быть любой положительный индекс после вершины стека внутри пространства, выделенного для стека, т.е., индексы выше размера стека. (Учтите, что 0 это всегда недопустимый индекс.) Если не оговорено иное, API функции работают с допустимыми индексами.
Допустимые индексы служат для избежания дополнительных тестов вершины стека при запросах. Например, C функция может запросить свой третий аргумент без проверки его существования, т.е., без проверки того, что индекс 3 является правильным.
4.4 – C замыкания
Когда C функция создана, можно ассоциировать с ней несколько значений, таким образом создав C замыкание (closure) (см. lua_pushcclosure ); эти значения называются upvalue и доступны функции во время вызова.
4.5 – Реестр
Целочисленные ключи в реестре используются механизмом ссылок (см. luaL_ref ) и некоторыми предопределенными значениями. Следовательно, целочисленные ключи не должны использоваться для других целей.
4.6 – Обработка ошибок в C
Функция паники запускается как обработчик сообщений (см. §2.3); в частности, сообщение об ошибке лежит на вершине стека. Тем не менее, это не гарантирует стековое пространство. Чтобы положить что-либо на стек, функция паники должна сперва проверить доступное место (см. §4.2).
Большинство API функций могут возбуждать ошибки, например при выделении памяти. Описание для каждой функции предупреждает, что она может возбуждать ошибки.
4.7 – Обработка уступок в C
Допустим, выполняющийся поток уступает во время выполнения вызываемой функции. Затем поток продолжается, это в конечном счете завершит вызываемую функцию. Тем не менее, вызываемая функция не может вернуться в оригинальную, т.к. её фрейм в C стеке был уничтожен уступкой. Взамен, Lua вызывает функцию продолжения, которая передается как аргумент вызываемой функции. Как подразумевается, продолжающая функция должна продолжить выполнение задачи оригинальной функции.
Как иллюстрацию, рассмотрим следующую функцию:
Обратите внимание на внешний явный вызов продолжения: Lua будет вызывать продолжение только при необходимости, т.е. в случае ошибок или возобновления после уступки. Если вызванная функция возвратится нормально, без уступок, lua_pcallk (и lua_callk ) также возвратятся нормально. (Конечно, в этом случае вместо вызова продолжения, вы можете выполнить эквивалентную работу прямо внутри оригинальной функции.)
Lua обрабатывает функцию продолжения так, как будто это оригинальная функция. Функция продолжения получает тот же Lua стек из оригинальной функции, в том же состоянии, как если бы вызываемая функция вернулась. (Например, после lua_callk функция и её аргументы удалены из стека и заменены результатами вызова.) Она также будет иметь те же upvalue. Результаты, которые она вернет, будут обработаны Lua так, как будто их вернула оригинальная функция.
4.8 – Функции и типы
Здесь представлен список всех функций и типов из C API в алфавитном порядке. Каждая функция имеет индикатор вида: [-o, +p, x]
lua_absindex
Конвертирует допустимый индекс idx в эквивалентный абсолютный индекс (который не зависит от вершины стека).
lua_Alloc
Lua предполагает следующее поведение функции выделения памяти:
lua_arith
Выполняет арифметическую или битовую операцию над двумя значениями (или одним, в случае отрицаний), находящимися на вершине стека, значение на вершине является вторым операндом, удаляет эти значения со стека и ложит результат операции. Функция следует семантике соответствующего оператора (т.е., может вызывать метаметоды).
lua_atpanic
Устанавливает новую функцию паники и возвращает старую (см. §4.6).
lua_call
Любая ошибка внутри вызванной функции распространяется вверх (с longjmp ).
Следующий пример показывает, как хостовая программа может выполнить действия эквивалентные этому Lua коду:
Обратите внимание, что код выше сбалансирован: после его выполнения стек возвращается в первоначальное состояние. Это хорошая практика програмирования.
lua_callk
lua_CFunction
Например, следующая функция получает переменное количество числовых аргументов и возвращает их среднее и их сумму:
lua_checkstack
Проверяет, что стек имеет место для как минимум n дополнительных слотов. Функция возвращает false, если не может выполнить запрос, потому что размер стека больше фиксированного максимума (обычно несколько тысяч элементов) или поскольку не может выделить память для дополнительных слотов. Эта функция никогда не уменьшает стек; если стек уже больше чем новый размер, он остаётся без изменений.
lua_close
Уничтожает все объекты в Lua состоянии (вызываются соответствующие метаметоды сборки мусора, если существуют) и освобождает всю динамическую память, использованную этим состоянием. На некоторых платформах, вы можете не вызывать эту функцию, т.к. все ресурсы освобождаются при завершении хостовой программы. С другой стороны, долго работающие программы, которые создают множество состояний, такие как демоны или веб-серверы, вероятно будут нуждаться в закрытии состояний, когда они станут ненужными.
lua_compare
lua_concat
Производит конкатенацию n значений на вершине стека, снимает их со стека и оставляет результат на вершине стека. Если n = 1, результат это одно значение на стеке (т.е., функция ничего не делает); если n = 0, результат пустая строка. Конкатенация выполняется следуя обычной семантике Lua (см. §3.4.6).
lua_copy
lua_createtable
lua_dump
Если strip = true, бинарное представление может не включать всю отладочную информацию о функции, для уменьшения размера.
Возвращаемое значение: код ошибки, возвращенный при последнем вызове функции writer; 0 означает нет ошибок.
Эта функция не убирает Lua функцию со стека.
lua_error
Генерирует ошибку Lua, используя значение на вершине стека, как объект ошибки. Эта функция производит длинный переход (long jump) и никогда не возвращается (см. luaL_error ).
lua_gc
Управляет сборщиком мусора.
lua_getallocf
lua_getfield
Возвращает тип положенного на стек значения.
lua_getextraspace
Возвращает указатель на область «сырой» (raw) памяти, ассоциированную с данным Lua состоянием. Приложение может использовать эту область для любых целей; Lua не использует эту область.
Каждый новый поток имеет такую область, инициализированную копией области главного потока.
По умолчанию, эта область имеет размер пустого указателя [ sizeof(void*) ], но вы можете перекомпилировать Lua с другим размером для этой области (см. LUA_EXTRASPACE в luaconf.h ).
lua_getglobal
lua_geti
Возвращает тип положенного на стек значения.
lua_getmetatable
Если значение по индексу index имеет метатаблицу, функция ложит эту метатаблицу на стек и возвращает 1. Иначе, функция возвращает 0 и ничего не ложит на стек.
lua_gettable
Эта функция снимает ключ со стека и ложит результирующее значение на его место. Как и в Lua, эта функция может запускать метаметод для события «index» (см. §2.4).
Возвращает тип положенного на стек значения.
lua_gettop
Возвращает индекс элемента на вершине стека. Т.к. индексы начинаются с 1, результат равен количеству элементов в стеке; в частности, 0 означает, что стек пуст.
lua_getuservalue
Ложит на стек Lua значение ассоциированное с пользовательскими данными (userdata), находящимися по индексу index.
Возвращает тип положенного на стек значения.
lua_insert
Перемещает верхний элемент стека в полученный правильный индекс, сдвигая вверх элементы выше этого индекса. Эта функция не может быть использована с псевдоиндексом, т.к. псевдоиндекс не обозначает актуальной позиции на стеке.
lua_Integer
lua_isboolean
Возвращает 1, если значение по индексу index имеет тип boolean, иначе возвращает 0.
lua_iscfunction
Возвращает 1, если значение по индексу index это C функция, иначе возвращает 0.
lua_isfunction
Возвращает 1, если значение по индексу index это функция (любая C или Lua), иначе возвращает 0.
lua_isinteger
Возвращает 1, если значение по индексу index это целое (т.е., это число и оно представлено как целое [integer]), иначе возвращает 0.
lua_islightuserdata
Возвращает 1, если значение по индексу index это легкие пользовательские данные (light userdata), иначе возвращает 0.
lua_isnil
Возвращает 1, если значение по индексу index это nil, иначе возвращает 0.
lua_isnone
Возвращает 1, если полученный индекс не правильный, иначе возвращает 0.
lua_isnoneornil
Возвращает 1, если полученный индекс не правильный или значение по индексу это nil, иначе возвращает 0.
lua_isnumber
Возвращает 1, если значение по индексу index это число или строка конвертируемая в число, иначе возвращает 0.
lua_isstring
Возвращает 1, если значение по индексу index это строка или число (которое всегда можно преобразовать в строку), иначе возвращает 0.
lua_istable
Возвращает 1, если значение по индексу index это таблица, иначе возвращает 0.
lua_isthread
Возвращает 1, если значение по индексу index это поток (thread), иначе возвращает 0.
lua_isuserdata
Возвращает 1, если значение по индексу index это пользовательские данные (любые полные или легкие), иначе возвращает 0.
lua_isyieldable
Возвращает 1, если данная сопрограмма может уступить (yield), иначе возвращает 0.
lua_KContext
lua_KFunction
Тип для функций продолжения (см. §4.7).
lua_len
Возвращает длину значения по индексу index. Это эквивалент Lua оператору ‘ # ‘ (см. §3.4.7) и может вызывать метаметод для события «length» (см. §2.4). Результат ложится на стек.
lua_load
Загружает Lua кусок без запуска его на исполнение. Если ошибок нет, lua_load ложит на стек скомпилированный кусок, как Lua функцию. Иначе, ложит на стек сообщение об ошибке.
Аргумент chunkname дает куску имя, которое используется для сообщений об ошибках и в отладочной информации (см. §4.9).
lua_load использует стек непосредственно, поэтому функция reader всегда должна оставлять его неизменным после возвращения.
Если результирующая функция имеет внешние локальные переменные (upvalue), её первое upvalue устанавливается в значение глобального окружения, записанное в реестре по индексу LUA_RIDX_GLOBALS (см. §4.5). При загрузке главных кусков, это upvalue будет переменной _ENV (см. §2.2). Остальные upvalue инициализируются значением nil.
lua_newstate
lua_newtable
lua_newthread
Не существует явной функции для закрытия или уничтожения потока. Потоки это субъект для сборки мусора, как и любой Lua объект.
lua_newuserdata
Функция выделяет новый блок памяти размером size, ложит на стек новый объект full userdata (полные пользовательские данные) с адресом этого блока, и возвращает этот адрес. Хостовая программа может свободно использовать эту память.
lua_next
Снимает ключ со стека, ложит пару ключ-значение из таблицы, находящейся по индексу index («следующая» пара после данного ключа). Если в таблице больше нет элементов, lua_next возвращает 0 (и ничего не ложит на стек).
Типичный перебор элементов таблицы выглядит так:
Смотри функцию next для предостережений о модификации таблицы во время её перебора.
lua_Number
Тип вещественных чисел в Lua.
По умолчанию, это тип double, но он может быть изменен в single float или long double (см. LUA_FLOAT_TYPE в luaconf.h ).
lua_numbertointeger
Этот макрос может вычислять свои аргументы несколько раз.
lua_pcall
[-(nargs + 1), +(nresults|1), –]
Вызывает функцию в защищенном режиме.
lua_pcallk
[-(nargs + 1), +(nresults|1), –]
lua_pop
Снимает n элементов со стека.
lua_pushboolean
lua_pushcclosure
Ложит на стек новое C замыкание.
Максимальное значение для n это 255.
Когда n = 0, эта функция создает лёгкую C функцию, которая является лишь указателем на C функцию. В этом случае, она никогда не вызывает ошибку памяти.
lua_pushcfunction
Любая функция, чтобы быть работоспособной в Lua, должна следовать корректному протоколу приема параметров и возврата результатов (см. lua_CFunction ).
lua_pushfstring
lua_pushglobaltable
Ложит глобальное окружение в стек.
lua_pushinteger
lua_pushlightuserdata
Ложит на стек легкие пользовательские данные (light userdata).
lua_pushliteral
lua_pushlstring
Возвращает указатель на внутреннюю копию строки.
lua_pushnil
Ложит на стек значение nil.
lua_pushnumber
lua_pushstring
Возвращает указатель на внутреннюю копию строки.
lua_pushthread
lua_pushvalue
Ложит на стек копию элемента по индексу index.
lua_pushvfstring
lua_rawequal
Возвращает 1, если два значения по индексам index1 и index2 примитивно равны (т.е. без вызова метаметодов). Иначе возвращает 0. Также возвращает 0, если любой из индексов не правильный.
lua_rawget
lua_rawgeti
Возвращает тип положенного на стек значения.
lua_rawgetp
Возвращает тип положенного на стек значения.
lua_rawlen
Возвращет сырую «длину» значения по индексу index: для строк это длина строки; для таблиц это результат оператора длины (‘ # ‘) без метаметодов; для пользовательских данных это размер выделенного блока памяти; для остальных значений это 0.
lua_rawset
lua_rawseti
Эта функция снимает значение со стека. Присваивание «сырое», т.е. без вызова метаметодов.
lua_rawsetp
Эта функция снимает значение со стека. Присваивание «сырое», т.е. без вызова метаметодов.
lua_Reader
lua_register
lua_remove
Удаляет элемент по данному правильному индексу, сдвигая вниз элементы выше этого индекса, чтобы заполнить промежуток. Эта функция не может быть вызвана с псевдоиндексом, т.к. псевдоиндекс не является действительной позицией в стеке.
lua_replace
Перемещяет элемент с вершины стека в позицию по правильному индексу index без сдвига элементов (следовательно, заменяя значение по данному индексу) и затем снимает вехний элемент со стека.
lua_resume
В случае ошибок, стек не раскручивается, так вы можете использовать отладочные API на нём. Сообщение об ошибке находится на вершине стека.
lua_rotate
lua_setallocf
lua_setfield
Эта функция снимает значение со стека. Как и в Lua, эта функция может запускать метаметод для события «newindex» (см. §2.4).
lua_setglobal
lua_seti
Эта функция снимает значение со стека. Как и в Lua, эта функция может запускать метаметод для события «newindex» (см. §2.4).
lua_setmetatable
Снимает таблицу со стека и устанавливает её в качестве новой метатаблицы для значения по индексу index.
lua_settable
Эта функция снимает со стека ключ и значение. Как и в Lua, эта функция может запускать метаметод для события «newindex» (см. §2.4).
lua_settop
Принимает любой индекс или 0, и устанавливает вершину стека равной этому индексу. Если новая вершина больше предыдущей, новые элементы заполняются значением nil. Если index = 0, то все элементы стека удаляются.
lua_setuservalue
Снимает значение со стека и устанавливает его в качестве нового значения, ассоциированного с пользовальскими данными (userdata) по индексу index.
lua_State
Непрозрачная структура, которая указывает на поток и косвенно (через поток) на целое состояние интерпретатора Lua. Библиотека Lua полностью повторно входимая: она не имеет глобальных переменных. Вся информация о состоянии доступна через эту структуру.
lua_status
lua_stringtonumber
Преобразует завершаемую нулем строку s в число, ложит это число на стек и возвращает общий размер строки, т.е. её длину + 1. Результатом преобразования может быть целое или вещественное число, в соответствии с лексическими соглашениями Lua (см. §3.1). Строка может иметь начальные и конечные пробелы и знак. Если строка не правильное число, функция возвращает 0 и ничего не ложит на стек. (Имейте ввиду, что результат может быть использован как логическое значение, если преобразование успешно, то результат true.)
lua_toboolean
Преобразует Lua значение по индексу index в C boolean (0 или 1). Как и все проверки в Lua, lua_toboolean возвращает true для любого Lua значения отличного от false и nil; иначе, возвращает false. (Если вы хотите принимать только значения типа boolean, используйте lua_isboolean для проверки.)
lua_tocfunction
lua_tointeger
lua_tointegerx
lua_tolstring
lua_tolstring возвращает полностью выровненный указатель на строку внутри Lua состояния. Эта строка всегда имеет завершающий ноль (‘ \0 ‘) после последнего символа (как в C), но может содержать другие нули в своем теле.
lua_tonumber
lua_tonumberx
Преобразует Lua значение по индексу index в C тип lua_Number (см. lua_Number ). Lua значение должно быть числом или строкой, преобразуемой в число (см. §3.4.3); иначе, lua_tonumberx возвращает 0.
lua_topointer
Обычно эта функция используется для хеширования и отладочной информации.
lua_tostring
lua_tothread
lua_touserdata
lua_type
lua_typename
lua_Unsigned
lua_upvalueindex
lua_version
lua_Writer
Функция writer возвращает код ошибки; 0 означает нет ошибок; любое другое значение означает ошибку и останавливает lua_dump от последующих вызовов writer.
lua_xmove
Обмен значениями между разными потоками одного состояния.
lua_yield
lua_yieldk
Устапает сопрограмму (поток).
Обычно эта функция не возвращается; когда сопрограмма в конечном счете возобновляется, она выполняет фукнцию продолжения. Тем не менее, есть один специальный случай, который случается когда функция вызвана из построчного перехватчика (см. §4.9). В этом случает, lua_yieldk должна быть вызвана без продолжения (вероятно в форме lua_yield ), и перехватчик должен вернуться непосредственно после вызова. Lua уступит и, когда сопрограмма вновь возобновится, она продолжит нормальное исполнение (Lua) функции, которая инициировала перехват.
Эта функция может вызывать ошибку, если вызвана из потока с незаконченным C вызовом без функции продолжения, или если вызвана из потока, который не запущен внутри сопрограммы (т.е., главный поток).
4.9 – Отладочный интерфейс
Lua не имеет встроенных отладочных средств. Взамен, он предлагает специальный интерфейс функций и перехватчиков (hook). Этот интерфейс позволяет строить различные типы отладчиков, профилировщиков и других инструментов, нуждающихся во «внутренней информации» интерпретатора.
lua_Debug
lua_gethook
Возвращает текущую функцию перехватчик.
lua_gethookcount
Возвращает количество перехватчиков.
lua_gethookmask
Возвращает текущую маску перехватов.
lua_getinfo
Предоставляет информацию о специфической функции или о вызове функции.
Для получения информации о вызове функции, параметр ar должен быть правильной записью активации, которая заполняется вызовом lua_getstack или передается как аргумент в перехватчик (см. lua_Hook ).
Если эта опция получена вместе с опцией ‘ f ‘, таблица ложится в стек после функции.
Эта функция возвращает 0 при ошибке (например, при неправильной опции в строке what ).
lua_getlocal
Предоставляет информацию о локальной переменной данной записи активации или функции.
В первом случае, параметр ar должен быть правильной записью активации, которая заполнена предыдущим вызовом lua_getstack или передана как аргумент перехватчику (см. lua_Hook ). Индекс n выбирает локальную переменную для проверки; см. debug.getlocal для подробностей о индексах и именах переменных.
lua_getlocal ложит в стек значение переменной и возвращает её имя.
Возвращает NULL (и ничего не ложит на стек), когда индекс больше чем количество активных локальных переменных.
lua_getstack
Предоставляет информацию о исполняемом (runtime) стеке интерпретатора.
lua_getupvalue
Upvalue не имеют конкретного порядка, как они активны внутри функции. Они нумеруются в произвольном порядке.
lua_Hook
Тип для отладочных функций перехватчиков.
Пока Lua выполняет перехватчик, все остальные перехватчики отключаются. Следовательно, если перехватчик вызывает Lua для выполнения функции или куска, это выполнение произойдет без вызова перехватчиков.
Функции перехватчики могут уступать при следующих условиях: только счетные и события строк могут уступать; для уступки, функция перехватчик должна завершить свое исполнение, вызвав lua_yield с nresults = 0 (т.е. без значений).
lua_sethook
Устанавливает отладочную функцию-перехватчик.
Перехват отключается установкой mask = 0.
lua_setlocal
Устанавливает значение локальной переменной в данной записи активации (ar). Устанавливает переменной значение с вершины стека и возвращает её имя, затем удаляет значение из стека.
Возвращает NULL (и ничего не удаляет со стека), когда индекс больше количества активных локальных переменных.
lua_setupvalue
Устанавливает значение для upvalue замыкания. Устанавливает upvalue равным значению с вершины стека и возвращает её имя, затем удаляет значение из стека
Возвращает NULL (и ничего не удаляет со стека), когда индекс больше количества upvalue.
lua_upvalueid
Эти уникальные идентификаторы позволяют программе проверить, когда замыкания совместно используют upvalue. Lua замыкания, которые совместно используют upvalue (т.е., обращаются к одной внешней локальной переменной), вернут одинаковые идентификаторы для индексов своих upvalue.
lua_upvaluejoin
5 – Вспомогательная библиотека
Вспомогательная библиотека предоставляет различные удобные функции для взаимодействия C с Lua. Когда базовые API предоставляют примитивные функции для всех взаимодействий между C и Lua, вспомогательная библиотека предоставляет высокоуровневые функции для некоторых общих задач.
Все функции вспомогательной библиотеки строятся из базовых API, и так они не предоставляют ничего, чего нельзя было бы сделать с помощью этих API. Тем не менее, использование вспомогательной библиотеки гарантирует большую стабильность вашему коду.
Различные функции вспомогательной библиотеки используют внутри несколько дополнительных слотов. Когда функция вспомогательной библиотеки использует меньше пяти слотов, она не проверяет размер стека; она просто предполагает, что там достаточно слотов.
Различные функции вспомогательной библиотеки используются для проверки аргументов C функций. Так как сообщение об ошибке формируется для аргументов (т.е., » bad argument #1 «), вы не должны использовать эти функции для других значений стека.
Функции luaL_check* всегда генерируют ошибку, если проверка не удовлетворена.
5.1 – Функции и типы
Здесь представлен список всех функций и типов вспомогательной библиотеки в алфавитном порядке.
luaL_addchar
Добавляет байт c в буфер B (см. luaL_Buffer ).
luaL_addlstring
Добавляет строку по указателю s длиной l в буфер B (см. luaL_Buffer ). Строка может содержать встроенные нули.
luaL_addsize
luaL_addstring
Добавляет завершаемую нулем строку по указателю s в буфер B (см. luaL_Buffer ).
luaL_addvalue
Добавляет значение с вершины стека в буфер B (см. luaL_Buffer ). Снимает значение со стека.
Только эта функция для строковых буферов может (и должна) вызываться с дополнительным аргументом на стеке, являющимся значением для добавления в буфер.
luaL_argcheck
Проверяет когда cond истина. Если это не так, генерирует ошибку со стандартным сообщением (см. luaL_argerror ).
luaL_argerror
Генерирует ошибку, сообщающую о проблеме с аргументом arg для C функции, которая вызвала luaL_argerror. Используется стандартное сообщение, включающее extramsg как комментарий:
Эта функция никогда не возвращается.
luaL_Buffer
Тип для строкового буфера.
luaL_buffinit
luaL_buffinitsize
luaL_callmeta
luaL_checkany
luaL_checkinteger
luaL_checklstring
Эта функция использует lua_tolstring для получения результата, так все преобразования и предостережения этой функции относятся и сюда.
luaL_checknumber
Проверяет, что аргумент функции arg это число, и возвращает это число.
luaL_checkoption
Проверяет, что аргумент функции arg это строка, и ищет эту строку в массиве lst (который должен завершаться NULL-символом). Возвращает индекс в массиве, где найдена строка. Генерирует ошибку, если аргумент не строка или строка не найдена в массиве.
Эта функция полезна для отображения строк в C перечисления (enum). (Обычно, для выбора опций в Lua библиотеках принято использовать строки вместо чисел.)
luaL_checkstack
luaL_checkstring
Проверяет, что аргумент функции arg это строка, и возвращает эту строку.
Эта функция использует lua_tolstring для получения результата, так все преобразования и предостережения этой функции относятся и сюда.
luaL_checktype
luaL_checkudata
Проверяет, что аргумент функции arg это пользовательские данные типа tname (см. luaL_newmetatable ), и возвращает адрес пользовательских данных (см. lua_touserdata ).
luaL_checkversion
Проверяет, что ядро, выполняющее вызов, ядро, создавшее Lua состояние, и код, производящий вызов, все используют одну версию Lua. Также проверяет, что ядро, выполняющее вызов, и ядро, создавшее Lua состояние, используют одно адресное пространство.
luaL_dofile
Загружает и запускает данный файл. Определена как макрос:
Возвращает false, если ошибок нет, или true в случае ошибок.
luaL_dostring
Загружает и запускает переданную строку. Определена как макрос:
Возвращает false, если ошибок нет, или true в случае ошибок.
luaL_error
luaL_execresult
Эта функция выдает возвращаемые значения для связанных с процессами функций стандартной библиотеки ( os.execute и io.close ).
luaL_fileresult
luaL_getmetafield
luaL_getmetatable
Ложит на стек метатаблицу, ассоциированную с именем tname в реестре (см. luaL_newmetatable ) (nil, если метатаблицы с таким именем нет). Возвращает тип положенного на стек значения.
luaL_getsubtable
luaL_gsub
luaL_len
Возвращает «длину» значения по индексу index как число; эквивалентна Lua оператору ‘ # ‘ (см. §3.4.7). Генерирует ошибку, если результат операции не целое. (Это может случиться только через метаметоды.)
luaL_loadbuffer
luaL_loadbufferx
luaL_loadfile
luaL_loadfilex
luaL_loadstring
luaL_newlib
Реализована как макрос:
Массив l должен быть фактическим массивом, не указателем на него.
luaL_newlibtable
Создает новую таблицу с размером, оптимизированным для хранения всех записей массива l (но фактически не сохраняет их). Она предполагается для использования в связке с luaL_setfuncs (см. luaL_newlib ).
Реализована как макрос. Массив l должен быть фактическим массивом, не указателем на него.
luaL_newmetatable
В обоих случаях ложит на стек финальное значение ассоциированное с tname в реестре.
luaL_newstate
luaL_openlibs
Открывает все стандартные библиотеки Lua в данное состояние.
luaL_optinteger
luaL_optlstring
luaL_optnumber
luaL_optstring
luaL_prepbuffer
luaL_prepbuffsize
luaL_pushresult
luaL_pushresultsize
luaL_ref
luaL_Reg
luaL_requiref
Оставляет копию модуля на стеке.
luaL_setfuncs
Регистрирует все функции в массиве l (см. luaL_Reg ) в таблицу на вершине стека (ниже опциональных upvalue, см. далее).
luaL_setmetatable
Устанавливает метатаблицей объекта на вершине стека метатаблицу, ассоциированную с именем tname в реестре (см. luaL_newmetatable ).
luaL_Stream
Стандартное представление для описателей файлов (handle), которые используются стандартной библиотекой ввода-вывода.
luaL_testudata
luaL_tolstring
luaL_traceback
luaL_typename
Возвращает имя типа для значения по индексу index.
luaL_unref
Освобождает ссылку ref из таблицы по индексу t (см. luaL_ref ). Элемент удаляется из таблицы, так что ассоциированный объект может быть собран сборщиком мусора. Ссылка ref также освобождается для повторного использования.
luaL_where
Ложит на стек строку, идентифицирующую текущую позицию на управляющем уровне lvl в стеке вызовов. Обычно эта строка имеет следующий формат:
Эта функция используется для формирования префикса сообщений об ошибках.
6 – Стандартные библиотеки
Стандартные библиотеки Lua предоставляют полезные функции, реализованные напрямую через C API. Некоторые из этих функций предоставляют существенные службы языка (например, type и getmetatable ); другие предоставляют доступ к «внешним» сервисам (например, I/O); и другие могут быть реализованы в Lua самостоятельно, но очень полезны и имеют критические требования к производительности, что заслуживает реализации в C (например, table.sort ).
За исключением базовой и пакетной библиотек, каждая библиотека предоставляет все свои функции, как поля глобальной таблицы или методы её объектов.
6.1 – Базовые функции
Базовая библиотека предоставляет функции ядра для Lua. Если вы не включите эту библиотеку в ваше приложение, вы должны проявлять осторожность, когда будете нуждаться в предоставлении реализаций для некоторых её возможностей.
assert (v [, message])
collectgarbage ([opt [, arg]])
dofile ([filename])
error (message [, level])
getmetatable (object)
ipairs (t)
Возвращет три значения (функцию итератор, таблицу t и 0), так что конструкция
load (chunk [, chunkname [, mode [, env]]])
Если chunk это строка, кусок будет этой строкой. Если chunk это функция, load многократно вызывает её, чобы получить части куска. Каждый вызов chunk должен возвращать строку, которая присоединяется к предыдущим результатам. Возврат пустой строки, nil или ничего сигнализирует о конце куска.
Если в куске нет синтаксических ошибок, возвращает скомпилированный кусок, как функцию; иначе, возвращает nil и сообщение об ошибке.
Lua не проверяет правильность бинарных кусков. Злонамеренно созданный бинарный кусок может разрушить интерпретатор.
loadfile ([filename [, mode [, env]]])
next (table [, index])
Порядок перечисления индексов не определен, даже для числовых индексов. (Для просмотра таблицы в числовом порядке, используйте числовой for.)
Поведение next неопределено, если во время просмотра вы присваиваете любое значение несуществующему полю в таблице. Тем не менее вы можете модифицировать существующие поля. В частности, вы можете очищать существующие поля.
pairs (t)
См. функцию next для предострежений о модификации таблицы во время просмотра.
pcall (f [, arg1, ···])
print (···)
rawequal (v1, v2)
rawget (table, index)
rawlen (v)
rawset (table, index, value)
select (index, ···)
setmetatable (table, metatable)
tonumber (e [, base])
Преобразование строк может выдавать в результате целые или вещественные числа, в соответствии с лексическими соглашениями Lua (см. §3.1). (Строка может иметь начальные и конечные пробелы и знак.)
tostring (v)
type (v)
_VERSION
xpcall (f, msgh [, arg1, ···])
6.2 – Работа с сопроцессами
coroutine.create (f)
coroutine.isyieldable ()
Возвращает true, когда запущенный сопроцесс может уступить.
Запущенный сопроцесс может уступать, если это не главный поток и он не внутри неприостанавливаемой C функции.
coroutine.resume (co [, val1, ···])
Если сопроцесс запущен без ошибок, resume возвращает true и все значения, переданные в yield (когда сопроцесс уступает) или все значения, возвращенные функцией сопроцесса (когда сопроцесс завершается). В случае ошибок, resume возвращает false и сообщение об ошибке.
coroutine.running ()
Возвращает запущенный сопроцесс и логическое значение; true, если сопроцесс это главный поток.
coroutine.status (co)
coroutine.wrap (f)
coroutine.yield (···)
6.3 – Модули
require (modname)
Если во время загрузки или запуска модуля происходит ошибка, или если не найден ни один загрузчик для модуля, require генерирует ошибку.
package.config
package.cpath
Этот путь используется require для поиска C загрузчика.
package.loaded
Таблица, используемая require для контроля за тем, какие модули уже загружены. Когда вы загружаете модуль modname и package.loaded[modname] не false, require просто возвращает хранящееся там значение.
package.loadlib (libname, funcname)
Если funcname = » * «, то она только связывает с библиотекой, делая экспортируемые библиотекой символы доступными для других динамических библиотек. Иначе, она ищет функцию funcname внутри библиотеки и возвращает эту функцию, как C функцию. Так, funcname должна соответствовать прототипу lua_CFunction (см. lua_CFunction ).
Эта функция не поддерживается стандартным C. Т.к., она доступна только для некоторых платформ (Windows, Linux, Mac OS X, Solaris, BSD и другие Unix системы, которые поддерживаю стандарт dlfcn ).
package.path
Этот путь используется require для поиска Lua загрузчика.
package.preload
Таблица для хранения загрузчиков для специфических модулей (см. require ).
package.searchers
Таблица, используемая require для контроля над тем, как загружать модули.
Каждый элемент в этой таблице это функция искатель (searcher). Когда ищется модуль, require вызывает каждую из этих функций в возрастающем порядке, с именем модуля (аргумент переданный в require ) в качестве единственного параметра. Функция может вернуть другую функцию (загрузчик модуля) и дополнительное значение, которое будет передано загрузчику, или строку, объясняющую, почему модуль не найден (или nil если нечего сказать).
Lua инициализирует эту таблицу четырьмя функциями искателями.
package.searchpath (name, path [, sep [, rep]])
Например, если путь это строка
Возвращает результирующее имя первого файла, который можно открыть в режиме чтения (после закрытия файла), или nil и сообщение об ошибке, если ничего не удалось. (Это сообщение об ошибке перечисляет все имена файлов, которые пыталась открыть функция.)
6.4 – Работа со строками
Строковая библиотека предполагает кодирование символов одним байтом.
string.byte (s [, i [, j]])
Цифровые коды не обязательно портабельны между платформами.
string.char (···)
Цифровые коды не обязательно портабельны между платформами.
string.dump (function [, strip])
Возвращает строку содержащую бинарное представление (бинарный кусок) переданной функции, так что load для этой строки возвращает копию функции (но с новыми upvalue). Если strip = true, бинарное представление может не включать всю отладочную информацию о функции, для уменьшения размера.
Функции с upvalue сохраняют только количество upvalue. При загрузке, эти upvalue получают свежие экземпляры, содержащие nil. (Вы можете использовать отладочную библиотеку, чтобы сохранить и перезагрузить upvalue функции в том виде, как вам нужно.)
string.find (s, pattern [, init [, plain]])
Если шаблон имеет захваты (capture), то при успешном совпадении захваченные значения также возвращаются, после двух индексов.
string.format (formatstring, ···)
может выдать строку:
Когда Lua скомпилирована с не C99 компилятором, опции A и a (шестнадцатиричные вещественные числа) не поддерживают модификаторы (флаги, ширина, длина).
string.gmatch (s, pattern)
Следующий пример собирает в таблице все пары key=value из строки:
Для этой функции, символ ‘ ^ ‘ в начале шаблона не работает как якорь, т.к. это мешает итерации.
string.gsub (s, pattern, repl [, n])
Если repl это таблица, то таблица запрашивается для каждого совпадения, используя первое захваченное значение, как ключ.
Если repl это функция, то эта функция вызывается для каждого совпадения, все захваченные подстроки передаются в качестве аргументов, по порядку.
В любом случае, если шаблон не имеет захватов, то он ведет себя так, будто весь шаблон находится в захвате.
Если значение, возвращенное из табличного запроса или из функции, это строка или число, то оно используется, как замещающая строка; иначе, если это false или nil, то замена не производится (т.е. оригинальное содержимое совпадения сохраняется в строке).
string.len (s)
string.lower (s)
string.match (s, pattern [, init])
string.pack (fmt, v1, v2, ···)
string.packsize (fmt)
Возвращает размер результирующей строки из string.pack с переданным форматом. Форматная строка не может иметь опций переменной длины ‘ s ‘ или ‘ z ‘ (см. §6.4.2).
string.rep (s, n [, sep])
string.reverse (s)
string.sub (s, i [, j])
string.unpack (fmt, s [, pos])
string.upper (s)
6.4.1 – Шаблоны
Символьный класс:
Элемент шаблона:
Шаблон:
Захваты (capture):
6.4.2 – Формат строк для string.pack и string.unpack
Выравнивание работает так: для каждой опции формат получает дополнительное заполнение, пока не начнутся данные по смещению, которое равно произведению минимума между размером опции и максимального выравнивания; этот минимум должен быть степенью 2. Опции » c » и » z » не выравниваются; опция » s » следует выравниванию её начального целого.
Все заполнения заполняются нулями в string.pack (и игнорируются в string.unpack ).
6.5 – Поддержка UTF-8
Пока не установлено иначе, все функции, которые ожидают позицию байта, как параметр, предполагают, что переданная позиция является также началом последовательности байт или позиция плюс длина строки. Как и в строковой библиотеке, отрицательные индексы отсчитываются с конца строки.
utf8.char (···)
utf8.charpattern
utf8.codes (s)
Возвращает значения такие, что конструкция
utf8.codepoint (s [, i [, j]])
utf8.len (s [, i [, j]])
utf8.offset (s, n [, i])
Эта функция предполагает, что s это правильная строка UTF-8.
6.6 – Работа с таблицами
Помните, что когда операция нуждается в длине таблицы, таблица должа содержать соответсвующую последовательность или иметь метаметод __len (см. §3.4.7). Все функции игнорируют не цифровые ключи в таблицах, полученных как аргументы.
table.concat (list [, sep [, i [, j]]])
table.insert (list, [pos,] value)
table.move (a1, f, e, t [,a2])
table.pack (···)
Возвращает новую таблицу, в которой все параметры сохранены с ключами 1, 2 и т.д. и поле » n » содержит количество параметров. Учтите, что результирующая таблица может не быть последовательностью.
table.remove (list [, pos])
table.sort (list [, comp])
Алгоритм сортировки не стабилен; т.е. элементы, считающиеся равными в этом упорядочении, в результате сортировки могут изменить свои относительные позиции.
table.unpack (list [, i [, j]])
Возвращает элементы из полученного списка. Эта функция эквивалентна
6.7 – Математические функции
math.abs (x)
math.acos (x)
Возвращает арккосинус x (в радианах).
math.asin (x)
Возвращает арксинус x (в радианах).
math.atan (y [, x])
Возвращает арктангенс y/x (в радианах), но использует знаки обоих параметров для поиска квадранта результата. (Также корректно обрабатывает случай, когда x = 0.)
math.ceil (x)
math.cos (x)
Возвращает косинус x (в радианах).
math.deg (x)
Преобразует угол x из радиан в градусы.
math.exp (x)
math.floor (x)
math.fmod (x, y)
math.huge
math.log (x [, base])
math.max (x, ···)
math.maxinteger
math.min (x, ···)
math.mininteger
math.modf (x)
math.pi
math.rad (x)
Преобразует угол x из градусов в радианы.
math.random ([m [, n]])
Эта функция является интерфейсом к генератору псевдослучайных чисел, предоставляемому C. Нет гарантий для его статистических свойств.
math.randomseed (x)
Устанавливает x как «затравку» (seed) для генератора псевдослучайных чисел: одинаковые затравки производят одинаковые последовательности чисел.
math.sin (x)
Возвращает синус x (в радианах).
math.sqrt (x)
math.tan (x)
Возвращает тангенс x (в радианах).
math.tointeger (x)
Если значение x можно преобразовать в целое, возвращает целое. Иначе, возвращает nil.
math.type (x)
math.ult (m, n)
6.8 – Средства ввода-вывода
Библиотека ввода-вывода предоставляет два разных стиля для файловых манипуляций. Первый использует подразумевающиеся описатели файлов (handle); т.е. там есть операции установки файла ввода и файла вывода по умолчанию, и все операции ввода-вывода используют эти файлы. Второй стиль использует явные описатели файлов.
io.close ([file])
io.flush ()
io.input ([file])
Когда вызвана с именем файла, открывает данный файл (в текстовом режиме), и устанавливает его описатель, как файл ввода по умолчанию. Когда вызвана с описателем файла, просто устанавливает этот описатель, как файл ввода по умолчанию Когда вызвана без параметров, возвращает текущий файл ввода по умолчанию.
В случае ошибок эта функция генерирует ошибку, вместо возвращения кода ошибки.
io.lines ([filename ···])
Открывает переданный файл в режиме чтения и возвращает функцию итератор, которая работает подобно file:lines(···) для открытого файла. Когда итератор доходит до конца файла, он ничего не возвращает (для завершения цикла) и автоматически закрывает файл.
Вызов io.lines() (без имени файла) эквивалентно io.input():lines(«*l») ; т.е. он перебирает линии файла ввода по умолчанию. В этом случае он не закрывает файл при завершении цикла.
В случае ошибок эта функция генерирует ошибку, вместо возвращения кода ошибки.
io.open (filename [, mode])
Строка mode также может содержать ‘ b ‘ в конце, это нужно на некоторых системах для открытия файла в бинарном режиме.
io.output ([file])
io.popen (prog [, mode])
Эта функция зависит от системы и не доступна на некоторых платформах.
io.read (···)
io.tmpfile ()
Возвращает описатель для временного файла. Этот файл открывается в режиме обновления и автоматически удаляется по завершении программы.
io.type (obj)
io.write (···)
file:close ()
file:flush ()
file:lines (···)
Возвращает функцию итератор, которая при каждом вызове читает файл в соответствии с переданными форматами. Когда формат не передан, использует » l «, по умолчанию. Например, конструкция
В случае ошибок эта функция генерирует ошибку, вместо возвращения кода ошибки.
file:read (···)
Форматы » l » и » L » должны использоваться только для текстовых файлов.
file:seek ([whence [, offset]])
В случае успеха, seek возвращает окончательную позицию в файле, измеряемую в байтах от начала файла. При ошибке, возвращает nil и сообщение об ошибке.
file:setvbuf (mode [, size])
Для двух последних случаев size определяет размер буфера, в байтах. По умолчанию это подходящий размер.
file:write (···)
6.9 – Средства операционной системы
os.clock ()
Возвращает апроксимацию количества секунд времени процессора, использованного программой.
os.date ([format [, time]])
Если аргумент time передан, то он является временем для форматирования (см. функцию os.time для описания этого значения). Иначе, date форматирует текущее время.
Когда вызвана без аргументов, date возвращает разумное представление даты и времени, зависящее от хостовой системы и текущей локали (т.е. os.date() эквивалентно os.date(«%c») ).
os.difftime (t2, t1)
os.execute ([command])
os.exit ([code [, close]])
Вызывает ISO C функцию exit для завершения хостовой программы. Если code = true, возвращается статус EXIT_SUCCESS ; если code = false, возвращается статус EXIT_FAILURE ; если code это число, возвращается статус равный этому числу. По умолчанию, code = true.
Если опциональный второй аргумент close = true, закрывает Lua состояние перед выходом.
os.getenv (varname)
os.remove (filename)
Удаляет файл (или пустую директорию, на POSIX системах) с переданным именем. Если функция терпит неудачу, она возвращает nil, сообщение об ошибке и код ошибки.
os.rename (oldname, newname)
os.setlocale (locale [, category])
Если locale это пустая строка, текущая локаль устанавливается в засимую от реализации родную локаль. Если locale это строка » C «, текущая локаль устанавливается в стандартную C локаль.
Когда вызвана с nil в качестве первого аргумента, эта функция только возвращает имя текущей локали для данной категории.
os.time ([table])
os.tmpname ()
Возвращает строку с именем файла, который может быть использован, как временный. Файл должен быть явно открыт перед использованием и явно удален, когда больше не нужен.
На POSIX системах эта функция также создает файл с этим именем, для избежания рисков беззопасности. (Кто-нибудь другой может создать файл с неправильными разрешениями в промежуток времени между получением имени файла и его созданием.) Вы по прежнему должны открыть файл для его использования и удалить его (даже если не использовали).
6.10 – Библиотека отладки
Эта библиотека предоставляет Lua программам функциональность отладочного интерфейса (§4.9). Используя эту библиотеку, вы должны проявлять внимательность. Различные функции этой билиотеки нарушают базовые предположения о Lua коде (например, что локальные переменные функции не могут быть доступны снаружи; что метатаблицы пользовательских данных не могут изменяться Lua кодом; что Lua программы не падают) и следовательно могут скомпрометировать защищенный код. Кроме того, некоторые функции в этой библиотеке могут быть медленными.
debug.debug ()
Учтите, что команды для debug.debug не являются лексически вложенными ни в одну функцию и не имеют прямого доступа к локальным переменным.
debug.gethook ([thread])
Возвращает настройки текущего перехватчика потока, как три значения: текущая функция-перехватчик, текущая маска перехвата и текущий счетчик перехвата (как установлено функцией debug.sethook ).
debug.getinfo ([thread,] f [, what])
debug.getlocal ([thread,] f, local)
Эта функция возвращает имя и значение локальной переменной с индексом local функции на уровне f стека вызовов. Эта функция получает доступ не только к явным локальным переменным, но также к параметрам, временным переменныи и др.
Имена переменных, начинающиеся с ‘ ( ‘ (открывающая скобка) представляют переменные с неизвестными именами (внутренние переменные, такие как переменные управления циклом, и переменные из кусков, сохраненных без отладочной информации).
Параметр f также может быть функцией. В этом случае getlocal возвращает только имена параметров функции.
debug.getmetatable (value)
Возвращает метатаблицу переданного значения value или nil, если у значения нет метатаблицы.
debug.getregistry ()
Возвращает таблицу реестра (см. §4.5).
debug.getupvalue (f, up)
debug.getuservalue (u)
debug.sethook ([thread,] hook, mask [, count])
Кроме того, с count не равным нулю, перехватчик вызывается также через каждые count инструкций (count в значении «количество»).
Когда вызвана без аргументов, debug.sethook выключает перехват.
debug.setlocal ([thread,] level, local, value)
Эта функция присваивает значение value локальной переменной по индексу local функции на уровне level в стеке вызовов. Функция возвращает nil, если локальная переменная с данным индексом не существует, и генерирует ошибку, когда вызвана с level вне диапазона. (Вы можете использовать getinfo чтобы проверить какой уровень допустим.) Иначе, возвращает имя локальной переменной.
См. debug.getlocal для дополнительной информации о именах и индексах переменных.
debug.setmetatable (value, table)
debug.setupvalue (f, up, value)
debug.setuservalue (udata, value)
debug.traceback ([thread,] [message [, level]])
debug.upvalueid (f, n)
Возвращает уникальный идентификатор (как лёгкие пользовательские данные) для upvalue под номером n из переданной функции.
Эти уникальные идентификаторы позволяют программе проверить, когда разные замыкания совместно используют одни upvalue. Lua замыкания, которые совместно используют upvalue (т.е. имеют доступ к одной внешней локальной переменной) вернут одинаковые идентификаторы для этих upvalue.
debug.upvaluejoin (f1, n1, f2, n2)
7 – Интерпретатор Lua
Хотя Lua был разработан, как язык расширений, чтобы встраивать в хостовую C программу, он также часто используется, как автономный язык. Интерпретатор Lua, как автономного языка, называется просто lua и предоставляется в стандартном дистрибутиве. Автономный интерпретатор включает все стандартные библиотеки, в том числе отладочную библиотеку. Синтаксис командной строки:
Если в вызове нет скрипта, имя интерпретатора идет по индексу 0, далее идут другие аргументы. Например, вызов
В интерактивном режиме, Lua многократно выдает приглащение и ждет ввода строки. После ввода строки, Lua сначала пробует интерпретировать строку как выражение. В случае успеха, печатает её значение. Иначе, интерпретирует строку как оператор. Если вы напишете незавершенное выражение, интерпретатор будет ждать его завершения, выдывая приглашение.
При нормальном завершении интерпретатор закрывает своё главное Lua состояние (см. lua_close ). Скрипт может избежать этого шага, вызвав os.exit для завершения.
более портабельное решение.)
8 – Несовместимости с предыдущей версией
Здесь приведен список несовместимостей, которые вы можете встретить при портировании программы с Lua 5.2 в Lua 5.3. Вы можете избежать некоторые несовместимости, скомпилировав Lua с соответствующими опциями (см. файл luaconf.h ). Тем не менее, все эти опции совметимости будут убраны в будущем.
Версии Lua всегда могут изменить C API способами, которые не подразумевают изменение исходного кода программы, такие, как цифровые значения констант или реализация функций через макросы. Следовательно, вы не должны ожидать бинарной совметимости между разными версиями Lua. Всегда перекомпилируйте клиентов Lua API, когда используете новую версию.
Аналогично, версии Lua всегда могут изменить внутреннее представление скомпилированных кусков; скомпилированные куски не совместимы между разными версиями Lua.
Стандартные пути в официальном дистрибутиве могут меняться между версиями.
8.1 – Изменения в языке
8.2 – Изменения в библиотеках
8.3 – Изменения в API
9 – Полный синтаксис Lua
Здесь приведен полный синтаксис Lua в БНФ. Как обычно в расширенной БНФ, означает 0 или более A, и [A] означает опциональное A. (Для приоритета операторов, см. §3.4.8; для описания терминалов Name, Numeral и LiteralString, см. §3.1.)
Last update: Wed Jun 10 18:31:15 BRT 2015 Last change: revised for Lua 5.3.1