Lua руководство на русском

Роберто Иерусалимши,Луис Энрике де Фигейредо,Вальдемар Селес.

1-Введение

Lua-это мощный,эффективный,легкий,встраиваемый язык сценариев.Он поддерживает процедурное программирование,объектно-ориентированное программирование,функциональное программирование,программирование на основе данных и описание данных.

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

Lua реализован как библиотека, написанная на чистом C , общем подмножестве Standard C и C ++. Дистрибутив Lua включает хост-программу под названием lua , которая использует библиотеку Lua для предоставления полного автономного интерпретатора Lua для интерактивного или пакетного использования. Lua предназначен для использования как мощного, легкого, встраиваемого языка сценариев для любой программы, которая в нем нуждается, и как мощный, но легкий и эффективный автономный язык.

Как язык расширения Lua не имеет понятия «основная» программа: он работает встроенным в хост-клиент, называемый программой встраивания или просто хостом . (Часто этот хост является автономной программой lua .) Хост-программа может вызывать функции для выполнения части кода Lua, может записывать и читать переменные Lua и может регистрировать функции C для вызова кодом Lua. Благодаря использованию функций C, Lua может быть расширен, чтобы справиться с широким спектром различных доменов, тем самым создавая настраиваемые языки программирования, разделяющие синтаксическую структуру.

Lua является бесплатным программным обеспечением и предоставляется, как обычно, без каких-либо гарантий, как указано в его лицензии. Реализация, описанная в этом руководстве, доступна на официальном веб-сайте www.lua.org .

Как и любое другое справочное руководство, этот документ местами пересох. Для обсуждения решений, лежащих в основе дизайна Lua, см. Технические документы, доступные на веб-сайте Lua. Подробное введение в программирование на Lua см. В книге Роберто « Программирование на Lua» .

2-Основные понятия

В этом разделе описаны основные понятия языка.

2.1-Значения и типы

Lua-динамически типизированный язык.Это означает,что переменные не имеют типов;типы есть только у значений.В языке нет определений типов.Все значения имеют свой собственный тип.

Все значения в Lua являются значениями первого класса.Это означает,что все значения можно хранить в переменных,передавать в качестве аргументов другим функциям и возвращать в виде результатов.

В Lua есть восемь основных типов: nil , boolean , number , string , function , userdata , thread и table . Тип nil имеет одно единственное значение, nil , основное свойство которого должно отличаться от любого другого значения; это часто означает отсутствие полезной ценности. Тип boolean имеет два значения: false и true . И nil, и false делают условие ложным; все вместе они называются ложными ценностями . Любое другое значение делает условие истинным.

Тип номер представляет собой как целые числа и вещественные ( с плавающей точкой) числа, используя два подтипа: целые и с плавающей точкой . Стандартный Lua использует 64-битные целые числа и числа с плавающей запятой двойной точности (64-битные), но вы также можете скомпилировать Lua, чтобы он использовал 32-битные целые числа и / или одинарные (32-битные) числа с плавающей запятой. Вариант с 32 битами для целых чисел и чисел с плавающей запятой особенно привлекателен для небольших машин и встроенных систем. (См. Макрос LUA_32BITS в файле luaconf.h .)

Если не указано иное, любое переполнение при манипулировании целочисленными значениями происходит циклически в соответствии с обычными правилами арифметики с двумя дополнениями. (Другими словами, фактический результат — это уникальное представимое целое число, равное по модулю 2 n математическому результату, где n — количество битов целочисленного типа.)

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

Строка типа представляет неизменяемые последовательности байтов. Lua является 8-битным чистым: строки могут содержать любое 8-битное значение, включая встроенные нули (‘ ‘). Lua также не зависит от кодирования; он не делает никаких предположений о содержимом строки. Длина любой строки в Lua должна соответствовать целому числу Lua.

Lua может вызывать (и манипулировать) функциями, написанными на Lua, и функциями, написанными на C (см. §3.4.10 ). Оба представлены функцией типа .

Тип userdata позволяет хранить произвольные данные C в переменных Lua. Значение пользовательских данных представляет собой блок необработанной памяти. Существует два вида пользовательских данных: полные пользовательские данные , которые представляют собой объект с блоком памяти, управляемый Lua, и легкие пользовательские данные , которые представляют собой просто значение указателя C. Пользовательские данные не имеют предопределенных операций в Lua, кроме присваивания и проверки подлинности. Используя метатаблицы , программист может определить операции для полных значений пользовательских данных (см. §2.4 ). Значения пользовательских данных не могут быть созданы или изменены в Lua, только через C API. Это гарантирует целостность данных, принадлежащих основной программе и библиотекам C.

Тип thread представляет независимые потоки выполнения и используется для реализации сопрограмм (см. §2.6 ). Потоки Lua не связаны с потоками операционной системы. Lua поддерживает сопрограммы во всех системах, даже в тех, которые изначально не поддерживают потоки.

Тип таблиц реализует ассоциативные массивы, то есть массивы , которые могут иметь в качестве индексов не только цифры, но любое значение Lua , кроме нуля и NaN. ( Not a Number — это специальное значение с плавающей запятой, используемое стандартом IEEE 754 для представления неопределенных числовых результатов, таких как 0/0 .) Таблицы могут быть неоднородными ; то есть они могут содержать значения всех типов (кроме nil ). Любой ключ, связанный со значением nil , не считается частью таблицы. И наоборот, любой ключ, не являющийся частью таблицы, имеет связанное значение nil .

Таблицы — единственный механизм структурирования данных в Lua; их можно использовать для представления обычных массивов, списков, таблиц символов, наборов, записей, графиков, деревьев и т. д. Для представления записей Lua использует имя поля в качестве индекса. Язык поддерживает это представление, предоставляя a.name в качестве синтаксического сахара для a["name"] . В Lua есть несколько удобных способов создания таблиц (см. §3.4.9 ).

Как и индексы, значения полей таблицы могут быть любого типа. В частности, поскольку функции являются значениями первого класса, поля таблицы могут содержать функции. Таким образом, таблицы также могут содержать методы (см. §3.4.11 ).

Индексация таблиц соответствует определению необработанного равенства в языке. Выражения a[i] и a[j] обозначают один и тот же элемент таблицы тогда и только тогда, когда i и j необработанные равны (то есть равны без метаметодов). В частности, числа с плавающей запятой с целыми значениями равны соответствующим им целым числам (например, 1.0 == 1 ). Чтобы избежать двусмысленности, любое число с плавающей запятой, используемое в качестве ключа, равное целому числу, преобразуется в это целое число. Например, если вы напишете a[2.0] = true , фактический ключ, вставленный в таблицу, будет целым числом 2 .

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

Библиотека функций type возвращает строку , описывающую тип данного значения (см type ).

2.2-Окружающая среда и глобальная среда

Как мы обсудим далее в §3.2 и §3.3.3 , любая ссылка на свободное имя (т. е. имя, не связанное с каким-либо объявлением) var синтаксически преобразуется в _ENV.var . Более того, каждый фрагмент компилируется в области действия внешней локальной переменной с именем _ENV (см. §3.3.2 ), поэтому само _ENV никогда не является свободным именем в фрагменте.

Несмотря на существование этой внешней переменной _ENV и перевод свободных имен, _ENV — вполне обычное имя. В частности, вы можете определить новые переменные и параметры с этим именем. Каждая ссылка на свободное имя использует _ENV _ENV видимый в этой точке программы, в соответствии с обычными правилами видимости Lua (см. §3.5 ).

Любая таблица, используемая в качестве значения _ENV , называется средой .

Lua поддерживает особую среду, называемую глобальной средой . Это значение хранится в специальном индексе в реестре C (см. §4.3 ). В Lua глобальная переменная _G инициализируется этим же значением. ( _G никогда не используется внутри, поэтому изменение его значения повлияет только на ваш собственный код.)

Когда Lua загружает кусок, значение по умолчанию для его _ENV переменной глобальной окружающей среды (см load ). Поэтому по умолчанию свободные имена в коде Lua относятся к записям в глобальной среде и, следовательно, они также называются глобальными переменными . Более того, все стандартные библиотеки загружаются в глобальную среду, и некоторые функции работают в этой среде. Вы можете использовать load (или loadfile ) для загрузки фрагмента с другой средой. (В C вы должны загрузить фрагмент, а затем изменить значение его первого повышающего значения; см. lua_setupvalue .)

2.3-Обработка ошибок

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

Код Lua может явно вызвать ошибку, вызвав функцию error . (Эта функция никогда не возвращается.)

Чтобы отловить ошибки в Lua, вы можете сделать защищенный вызов , используя pcall (или xpcall ). Функция pcall вызывает заданную функцию в защищенном режиме . Любая ошибка при запуске функции останавливает ее выполнение, и управление немедленно возвращается в pcall , который возвращает код состояния.

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

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

Когда вы используете xpcall (или lua_pcall в C), вы можете указать обработчик сообщений, который будет вызываться в случае ошибок. Эта функция вызывается с исходным объектом ошибки и возвращает новый объект ошибки. Он вызывается до того, как ошибка раскручивает стек, чтобы он мог собрать больше информации об ошибке, например, путем проверки стека и создания трассировки стека. Этот обработчик сообщений по-прежнему защищен защищенным вызовом; поэтому ошибка внутри обработчика сообщений снова вызовет обработчик сообщений. Если этот цикл длится слишком долго, Lua прерывает его и возвращает соответствующее сообщение. Обработчик сообщений вызывается только для обычных ошибок времени выполнения. Он не вызывается ни для ошибок выделения памяти, ни для ошибок при запуске финализаторов или других обработчиков сообщений.

Lua также предлагает систему предупреждений (см. warn ). В отличие от ошибок, предупреждения никоим образом не мешают выполнению программы. Обычно они только генерируют сообщение для пользователя, хотя это поведение можно адаптировать из C (см. lua_setwarnf ).

2.4-Метатаблицы и метаметоды

Каждое значение в Lua может иметь метатаблицу . Эта метатаблица представляет собой обычную таблицу Lua, которая определяет поведение исходного значения при определенных событиях. Вы можете изменить несколько аспектов поведения значения, задав определенные поля в его метатаблице. Например, когда нечисловое значение является операндом добавления, Lua проверяет функцию в поле « __add » метатаблицы значения. Если он его находит, Lua вызывает эту функцию для выполнения добавления.

Ключом для каждого события в метатаблице является строка с именем события, которому предшествуют два символа подчеркивания; соответствующее значение называется метазначением . Для большинства событий метазначение должно быть функцией, которая затем называется метаметодом . В предыдущем примере ключ — это строка « __add », а метаметод — это функция, выполняющая добавление. Если не указано иное, метаметод может фактически быть любым вызываемым значением, которое является либо функцией, либо значением с __call .

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

Вы можете заменить метатаблицу таблиц с помощью функции setmetatable . Вы не можете изменить метатаблицу других типов из кода Lua, кроме как с помощью библиотеки отладки ( §6.10 ).

Таблицы и полные пользовательские данные имеют отдельные метатаблицы, хотя несколько таблиц и пользовательских данных могут совместно использовать свои метатаблицы. Значения всех других типов совместно используют одну единственную метатаблицу для каждого типа; то есть существует одна единственная метатаблица для всех чисел, одна для всех строк и т. д. По умолчанию значение не имеет метатаблицы, но библиотека строк устанавливает метатаблицу для строкового типа (см. §6.4 ) .

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

  • __add : операция сложения ( + ). Если какой-либо операнд для добавления не является числом, Lua попытается вызвать метаметод. Он начинается с проверки первого операнда (даже если это число); если этот операнд не определяет __add для __add , то Lua проверит второй операнд. Если Lua может найти метаметод, он вызывает метаметод с двумя операндами в качестве аргументов, и результат вызова (с поправкой на одно значение) является результатом операции. В противном случае, если метаметод не найден, Lua выдаст ошибку.
  • __sub : операция вычитания ( - ). Поведение аналогично операции сложения.
  • __mul : операция умножения ( * ). Поведение аналогично операции сложения.
  • __div : операция деления ( / ). Поведение аналогично операции сложения.
  • __mod : операция по модулю ( % ). Поведение аналогично операции сложения.
  • __pow : операция возведения в степень ( ^ ). Поведение аналогично операции сложения.
  • __unm : операция отрицания (унарная - ). Поведение аналогично операции сложения.
  • __idiv : операция деления этажа ( // ). Поведение аналогично операции сложения.
  • __band : операция побитового И ( & ). Поведение аналогично операции сложения, за исключением того, что Lua попытается использовать метаметод, если какой-либо операнд не является ни целым числом, ни числом с плавающей запятой, которое можно привести к целому числу (см. §3.4.3 ).
  • __bor : побитовая операция ИЛИ ( | ). Поведение аналогично побитовой операции И.
  • __bxor : побитовая операция исключающее ИЛИ (двоичное ~ ). Поведение аналогично побитовой операции И.
  • __bnot : побитовая операция НЕ (унарная ~ ). Поведение аналогично побитовой операции И.
  • __shl : операция побитового сдвига влево ( << ). Поведение аналогично побитовой операции И.
  • __shr : операция побитового сдвига вправо ( >> ). Поведение аналогично побитовой операции И.
  • __concat : операция конкатенации ( .. ). Поведение аналогично операции сложения, за исключением того, что Lua будет пробовать метаметод, если какой-либо операнд не является ни строкой, ни числом (которое всегда может быть приведено к строке).
  • __len : длина ( # ) операции. Если объект не является строкой, Lua попробует свой метаметод. Если есть метаметод, Lua вызывает его с объектом в качестве аргумента, а результат вызова (всегда настроенный на одно значение) является результатом операции. Если метаметода нет, но объект является таблицей, то Lua использует операцию длины таблицы (см. §3.4.7 ). В противном случае Lua выдает ошибку.
  • __eq : операция равенства ( == ). Поведение аналогично операции сложения, за исключением того, что Lua будет пробовать метаметод только тогда, когда сравниваемые значения являются либо обеими таблицами, либо обоими полными пользовательскими данными, и они примитивно не равны. Результат вызова всегда преобразуется в логическое значение.
  • __lt : операция «меньше» ( < ). Поведение аналогично операции сложения, за исключением того, что Lua будет пробовать метаметод только тогда, когда сравниваемые значения не являются ни числами, ни обеими строками. Более того, результат вызова всегда преобразуется в логическое значение.
  • __le : операция меньшего равенства ( <= ). Поведение аналогично операции «меньше чем».
  • __index : Таблица операций доступа к индексированию table[key] . Это событие происходит , когда table не является таблицей или когда key не присутствует в table . Метазначение ищется в метатаблице table .

    Метазначение для этого события может быть функцией, таблицей или любым значением с __index __index. Если это функция, она вызывается с table и key качестве аргументов, а результат вызова (с поправкой на одно значение) является результатом операции. В противном случае окончательный результат будет результатом индексации этого метазначения с помощью key . Это индексирование является обычным, а не исходным, и поэтому может вызвать другое __index __index.

  • __newindex : Таблица присвоения индексации table[key] = value . Как и событие index, это событие происходит, когда table не является таблицей или когда key отсутствует в table . Метазначение ищется в метатаблице table .

    Как и в случае с индексированием, мета-значение для этого события может быть функцией, таблицей или любым значением с __newindex __newindex. Если это функция, она вызывается с table , key и value качестве аргументов. В противном случае Lua повторяет присвоение индексации для этого метазначения с тем же ключом и значением. Это обычное назначение, а не исходное, поэтому оно может вызвать другое __newindex __newindex.

    Каждый раз, когда __newindex __newindex, Lua не выполняет примитивное присваивание. При необходимости сам rawset может вызвать rawset для выполнения назначения.

  • __call : функция вызова func(args) . Это событие происходит, когда Lua пытается вызвать значение, не являющееся функцией (то есть func не является функцией). Метаметод ищется в func . Если присутствует, метаметод вызывается с func в качестве первого аргумента, за которым следуют аргументы исходного вызова ( args ). Все результаты вызова являются результатами операции. Это единственный метаметод, позволяющий получить несколько результатов.

В дополнение к предыдущему списку интерпретатор также учитывает следующие ключи в метатаблицах: __gc (см. §2.5.3 ), __close (см. §3.3.8 ), __mode (см. §2.5.4 ) и __name . (Запись __name , если она содержит строку, может использоваться tostring и в сообщениях об ошибках.)

Для унарных операторов (отрицание,длина и побитовое НЕ)метаметод вычисляется и вызывается с фиктивным вторым операндом,равным первому.Этот дополнительный операнд служит только для упрощения внутренних функций Lua (заставляя эти операторы вести себя как бинарные операции)и может быть удален в будущих версиях.Для большинства применений этот дополнительный операнд не имеет значения.

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

Хорошей практикой является добавление всех необходимых метаметодов в таблицу перед ее установкой в ​​качестве метатаблицы какого-либо объекта. В частности, метаметод __gc работает только при соблюдении этого порядка (см. §2.5.3 ). Также хорошей практикой является установка метатаблицы объекта сразу после его создания.

2.5-Сбор мусора

Lua выполняет автоматическое управление памятью. Это означает, что вам не нужно беспокоиться о выделении памяти для новых объектов или ее освобождении, когда объекты больше не нужны. Lua автоматически управляет памятью, запустив сборщик мусора для сбора всех мертвых объектов. Вся память, используемая Lua, подлежит автоматическому управлению: строки, таблицы, пользовательские данные, функции, потоки, внутренние структуры и т. Д.

Объект считается мертвым , как только сборщик может быть уверен, что к объекту больше не будет доступа при нормальном выполнении программы. («Нормальное выполнение» здесь исключает финализаторы, которые могут воскрешать мертвые объекты (см. §2.5.3 ), а также исключает операции с использованием библиотеки отладки.) Обратите внимание, что время, когда сборщик может быть уверен, что объект мертв, может не совпадать с ожиданиями программиста. Единственная гарантия заключается в том, что Lua не соберет объект, к которому все еще можно получить доступ при нормальном выполнении программы, и в конечном итоге соберет объект, недоступный из Lua. (Здесь недоступные из Luaозначает, что ни переменная, ни другой живой объект не ссылаются на объект.) Поскольку Lua ничего не знает о коде C, он никогда не собирает объекты, доступные через реестр (см. §4.3), который включает глобальную среду (см. §2.2 ).

Сборщик мусора (GC)в Lua может работать в двух режимах:инкрементном и генерационном.

Режим GC по умолчанию с параметрами по умолчанию достаточен для большинства случаев.Однако программы,которые тратят большую часть своего времени на выделение и освобождение памяти,могут извлечь пользу из других настроек.Помните,что поведение GC непортативно как для разных платформ,так и для разных релизов Lua;поэтому оптимальные настройки также непортативны.

Вы можете изменить режим и параметры lua_gc вызвав lua_gc в C или collectgarbage в Lua. Вы также можете использовать эти функции для непосредственного управления сборщиком (например, для его остановки и перезапуска).

2.5.1-Инкрементная сборка мусора

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

Пауза сборщика мусора контролирует, как долго сборщик ждет перед запуском нового цикла. Сборщик начинает новый цикл, когда использование памяти достигает n% от использования после предыдущего сбора. Более высокие значения делают сборщика менее агрессивным. Значения, равные или меньшие 100, означают, что сборщик не будет ждать начала нового цикла. Значение 200 означает, что сборщик ожидает, пока общий объем используемой памяти удвоится, прежде чем начать новый цикл. Значение по умолчанию — 200; максимальное значение — 1000.

Множитель шага сборщика мусора контролирует скорость работы сборщика относительно распределения памяти,то есть,сколько элементов он помечает или зачищает на каждый выделенный килобайт памяти.Большие значения делают сборщик более агрессивным,но также увеличивают размер каждого дополнительного шага.Не следует использовать значения меньше 100,поскольку они делают сборщик слишком медленным и могут привести к тому,что сборщик никогда не завершит цикл.Значение по умолчанию-100;максимальное значение-1000.

Размер шага сборщика мусора контролирует размер каждого инкрементного шага, в частности, сколько байтов выделяет интерпретатор перед выполнением шага. Этот параметр является логарифмическим: значение n означает, что интерпретатор будет выделять 2 n байтов между шагами и выполнять эквивалентную работу во время шага. Большое значение (например, 60) делает сборщик остановившимся (не инкрементным) сборщиком. Значение по умолчанию — 13, что означает шаг примерно 8 Кбайт.

2.5.2-Генерационная сборка мусора

В режиме генерации сборщик часто выполняет второстепенные коллекции, которые проходят только недавно созданные объекты. Если после второстепенной коллекции использование памяти все еще превышает предел, сборщик выполняет основную коллекцию Stop-the-world , которая проходит по всем объектам. В режиме генерации используются два параметра: младший множитель и старший множитель .

Младший множитель контролирует частоту второстепенных сборов. Для второстепенного множителя x новая второстепенная коллекция будет выполнена, когда объем памяти станет на x% больше, чем объем используемой памяти после предыдущей основной коллекции. Например, для множителя 20 сборщик будет выполнять второстепенный сбор, когда использование памяти становится на 20% больше, чем использование после предыдущей основной коллекции. Значение по умолчанию — 20; максимальное значение — 200.

Главный множитель контролирует частоту крупных сборов. Для основного множителя x новая основная коллекция будет выполнена, когда объем памяти станет на x% больше, чем объем памяти, используемой после предыдущей основной коллекции. Например, для множителя 100 сборщик будет выполнять основную сборку, когда использование памяти становится больше, чем в два раза после предыдущего сбора. Значение по умолчанию — 100; максимальное значение — 1000.

2.5.3-Метаметоды сбора мусора

Вы можете установить метаметоды сборщика мусора для таблиц и, используя C API, для полных пользовательских данных (см. §2.4 ). Эти метаметоды, называемые финализаторами , вызываются, когда сборщик мусора обнаруживает, что соответствующая таблица или пользовательские данные мертвы. Финализаторы позволяют координировать сборку мусора Lua с управлением внешними ресурсами, такими как закрытие файлов, подключение к сети или базе данных или освобождение собственной памяти.

Чтобы объект (таблица или пользовательские данные) был завершен при сборе, вы должны пометить его для завершения. Вы помечаете объект для завершения, когда устанавливаете его метатаблицу, и метатаблица имеет поле, проиндексированное строкой « __gc ». Обратите внимание, что если вы установите метатаблицу без поля __gc , а затем создадите это поле в метатаблице, объект не будет помечен для завершения.

Когда отмеченный объект становится мертвым, сборщик мусора не собирает его немедленно. Вместо этого Lua помещает его в список. После сбора Lua просматривает этот список. Для каждого объекта в списке он проверяет __gc объекта __gc : если он присутствует, Lua вызывает его с объектом в качестве единственного аргумента.

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

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

Когда вы закрываете состояние (см. lua_close ), Lua вызывает финализаторы всех объектов, отмеченных для завершения, следуя порядку, обратному тому, в котором они были отмечены. Если какой-либо финализатор помечает объекты для сбора на этом этапе, эти отметки не действуют.

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

Любая ошибка при выполнении финализатора вызывает предупреждение;ошибка не распространяется.

2.5.4-Слабые таблицы

Слабая таблица представляет собой таблицу, элементы которой являются слабыми ссылками . Слабая ссылка игнорируется сборщиком мусора. Другими словами, если единственными ссылками на объект являются слабые ссылки, то сборщик мусора соберет этот объект.

Слабая таблица может иметь слабые ключи, слабые значения или и то, и другое. Таблица со слабыми значениями позволяет собирать свои значения, но не позволяет собирать ключи. Таблица со слабыми ключами и слабыми значениями позволяет собирать как ключи, так и значения. В любом случае, если собирается ключ или значение, вся пара удаляется из таблицы. Слабость таблицы контролируется полем __mode ее метатаблицы. Это метазначение, если оно присутствует, должно быть одной из следующих строк: « k » для таблицы со слабыми ключами; » v » для таблицы со слабыми значениями; или « kv » для таблицы со слабыми ключами и значениями.

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

Любое изменение слабости таблицы может вступить в силу только при следующем цикле сбора.В частности,если вы измените слабость на более сильный режим,Lua все равно может забрать некоторые предметы из этого стола до того,как изменение вступит в силу.

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

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

Если среди воскресших объектов в цикле сбора находится слабая таблица,то она может быть очищена надлежащим образом только в следующем цикле.

2.6-Корутины

Lua поддерживает сопрограммы, также называемые совместной многопоточностью . Сопрограмма в Lua представляет собой независимый поток выполнения. Однако, в отличие от потоков в многопоточных системах, сопрограмма приостанавливает свое выполнение только путем явного вызова функции yield.

Вы создаете сопрограмму, вызывая coroutine.create . Его единственный аргумент — это функция, которая является основной функцией сопрограммы. Функция create только создает новую сопрограмму и возвращает ее дескриптор (объект типа thread ); он не запускает сопрограмму.

Вы выполняете сопрограмму, вызывая coroutine.resume . Когда вы впервые вызываете coroutine.resume , передавая в качестве первого аргумента поток, возвращаемый coroutine.create , сопрограмма начинает свое выполнение, вызывая свою основную функцию. Дополнительные аргументы, переданные в coroutine.resume , передаются в качестве аргументов этой функции. После того , как сопрограмма начинает работать, он работает , пока он не закончит или выходы .

Сопрограмма может завершить свое выполнение двумя способами: обычно, когда возвращается ее основная функция (явно или неявно, после последней инструкции); и ненормально, если есть незащищенная ошибка. В случае нормального завершения, coroutine.resume возвращает true плюс любые значения, возвращаемые основной функцией сопрограммы. В случае ошибок coroutine.resume возвращает false плюс объект ошибки. В этом случае сопрограмма не раскручивает свой стек, чтобы можно было проверить его после ошибки с помощью API отладки.

Сопрограмма выдает результат, вызывая coroutine.yield . Когда сопрограмма уступает, соответствующий coroutine.resume возвращается немедленно, даже если доходность происходит внутри вызовов вложенных функций (то есть не в основной функции, а в функции, прямо или косвенно вызываемой основной функцией). В случае yield coroutine.resume также возвращает true плюс любые значения, переданные в coroutine.yield . В следующий раз, когда вы возобновите ту же сопрограмму, она продолжит выполнение с той точки, в которой она была завершена, при этом вызов coroutine.yield возвращает любые дополнительные аргументы, переданные в coroutine.resume .

Как и coroutine.create , функция coroutine.wrap также создает сопрограмму, но вместо того, чтобы возвращать саму сопрограмму, она возвращает функцию, которая при вызове возобновляет сопрограмму. Любые аргументы, переданные этой функции, передаются в coroutine.resume как дополнительные аргументы . coroutine.wrap возвращает все значения, возвращаемые coroutine.resume , кроме первого (логический код ошибки). В отличие от coroutine.resume , функция, созданная coroutine.wrap , передает любую ошибку вызывающей стороне. В этом случае функция также закрывает сопрограмму (см. coroutine.close ).

В качестве примера того,как работают корутины,рассмотрим следующий код:

function foo (a)
  print("foo", a)
  return coroutine.yield(2*a)
end

co = coroutine.create(function (a,b)
      print("co-body", a, b)
      local r = foo(a+1)
      print("co-body", r)
      local r, s = coroutine.yield(a+b, a-b)
      print("co-body", r, s)
      return b, "end"
end)

print("main", coroutine.resume(co, 1, 10))
print("main", coroutine.resume(co, "r"))
print("main", coroutine.resume(co, "x", "y"))
print("main", coroutine.resume(co, "x", "y"))

При запуске он выдает следующий результат:

co-body 1       10
foo     2
main    true    4
co-body r
main    true    11      -9
co-body x       y
main    true    10      end
main    false   cannot resume dead coroutine

Вы также можете создавать сопрограммы и управлять ими через API C: см. Функции lua_newthread , lua_resume и lua_yield .

3-Язык

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

Языковые конструкции будут объясняться с использованием обычной расширенной нотации BNF, в которой { a } означает 0 или более a , а [ a ] означает необязательное a . Нетерминалы отображаются как нетерминалы, ключевые слова отображаются как kword , а другие терминальные символы отображаются как ‘ = ‘. Полный синтаксис Lua можно найти в §9 в конце этого руководства.

3.1-Лексические конвенции

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

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

Следующие ключевые слова зарезервированы и не могут использоваться в качестве имен:

and       break     do        else      elseif    end
false     for       function  goto      if        in
local     nil       not       or        repeat    return
then      true      until     while

Lua — это язык с учетом регистра: and является зарезервированным словом, но And и AND — два разных допустимых имени. По соглашению программы должны избегать создания имен, которые начинаются с подчеркивания, за которым следует одна или несколько заглавных букв (например, _VERSION ).

Следующие строки обозначают другие жетоны:

+     -     *     /     %     ^     
&     ~     |     <<    >>    
==    ~=    <=    >=    <     >     =
(     )     {     }     [     ]     ::
;     :     ,     .     ..    ...

Короткая символьная строка может быть ограничена путем сопоставления одинарные или двойные кавычки, и может содержать следующую C-типа управляющих последовательностей: « a » (колокол), « b » (забой), « f » (форма подачи), ‘ n ‘ (новая строка), ‘ r ‘ (возврат каретки), ‘ t ‘ (горизонтальная табуляция), ‘ v ‘ (вертикальная табуляция), ‘ \ ‘ (обратная косая черта), ‘ " ‘ (кавычки [двойная кавычка]) и ‘ ' ‘(апостроф [одинарная кавычка]). Обратная косая черта, за которой следует разрыв строки, приводит к новой строке в строке. Управляющая последовательность’ z ‘пропускает следующий диапазон пробелов, включая разрывы строк; особенно полезно разбивать длинную буквальную строку на несколько строк и делать отступы без добавления новых строк и пробелов в содержимое строки. Короткая буквальная строка не может содержать неэкранированные разрывы строк или экранированные символы, не образующие допустимую escape-последовательность.

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

Кодировка UTF-8 символа Unicode может быть вставлена ​​в буквальную строку с помощью escape-последовательности u{XXX} (с обязательными закрывающими фигурными скобками), где XXX — это последовательность из одной или нескольких шестнадцатеричных цифр, представляющих кодовую точку символа. Эта кодовая точка может иметь любое значение меньше 2 31 . (Здесь Lua использует исходную спецификацию UTF-8, которая не ограничивается допустимыми кодовыми точками Unicode.)

Литеральные строки также могут быть определены с использованием длинного формата, заключенного в длинные скобки . Мы определяем открывающую длинную скобку уровня n как открывающую квадратную скобку, за которой следуют n знаков равенства, за которыми следует еще одна открывающая квадратная скобка. Итак, открывающая длинная скобка уровня 0 записывается как [[ , открывающая длинная скобка уровня 1 записывается как [=[ и так далее. Закрытия длинный кронштейн определяется аналогично; например, закрывающая длинная скобка уровня 4 записывается как ]====] . Долго буквальнымначинается с открывающей длинной скобки любого уровня и заканчивается первой закрывающей длинной скобкой того же уровня. Он может содержать любой текст, кроме закрывающей скобки того же уровня. Литералы в этой заключенной в квадратные скобки форме могут занимать несколько строк, не интерпретируют никаких управляющих последовательностей и игнорируют длинные скобки любого другого уровня. Любая последовательность конца строки (возврат каретки, новая строка, возврат каретки с последующим переводом строки или новая строка с последующим возвратом каретки) преобразуется в простой символ новой строки. Когда за открывающей длинной скобкой сразу следует перевод строки, новая строка не включается в строку.

Например, в системе, использующей ASCII (в которой ‘ a ‘ кодируется как 97, новая строка кодируется как 10, а ‘ 1 ‘ кодируется как 49), пять литеральных строк ниже обозначают одну и ту же строку:

a = 'alon123"'
a = "alon123""
a = '97lo104923"'
a = [[alo
123"]]
a = [==[
alo
123"]==]

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

Числовая константа (или цифра ) может быть записана с помощью дополнительного дробной части и дополнительный десятичное показатель, отмеченный буквой « e » или « E ». Lua также принимает шестнадцатеричные константы, которые начинаются с 0x или 0X . Шестнадцатеричные константы также принимают необязательную дробную часть плюс необязательную двоичную экспоненту, отмеченную буквой « p » или « P ».

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

Примерами допустимых целочисленных констант являются

3   345   0xff   0xBEBADA

Примерами действующих констант поплавка являются

3.0     3.1416     314.16e-2     0.31416E1     34e1
0x0.1E  0xA23p-4   0X1.921FB54442D18P+1

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

3.2-Переменные

Переменные-это места,где хранятся значения.В Lua есть три типа переменных:глобальные переменные,локальные переменные и поля таблиц.

Одно имя может обозначать глобальную или локальную переменную (или формальный параметр функции,которая является определенным видом локальной переменной):

var ::= Name

Имя обозначает идентификаторы (см. §3.1 ).

Любое имя переменной считается глобальным, если оно явно не объявлено как локальное (см. §3.3.7 ). Локальные переменные имеют лексическую область видимости : к локальным переменным могут свободно обращаться функции, определенные внутри их области видимости (см. §3.5 ).

Перед первым присваиванием переменной ее значение равно нулю .

Квадратные скобки используются для индексирования таблицы:

var ::= prefixexp ‘[’ exp ‘]’

Значение доступа к полям таблицы можно изменить с помощью метатаблиц (см. §2.4 ).

Синтаксис var.Name — это просто синтаксический сахар для var["Name"] :

var ::= prefixexp ‘.’ Name

Доступ к глобальной переменной x эквивалентен _ENV.x . Из-за того, как компилируются фрагменты, сама переменная _ENV никогда не бывает глобальной (см. §2.2 ).

3.3-Заявления

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

3.3.1-Блоки

Блок-это список операторов,которые выполняются последовательно:

block ::= {stat}

В Lua есть пустые операторы, которые позволяют разделять операторы точкой с запятой, начинать блок с точки с запятой или последовательно записывать две точки с запятой:

stat ::= ‘;’

Как вызовы функций,так и присваивания могут начинаться с открытой скобки.Такая возможность приводит к двусмысленности в грамматике Lua.Рассмотрим следующий фрагмент:

a = b + c
(print or io.write)('done')

Грамматика может рассматривать этот фрагмент двумя способами:

a = b + c(print or io.write)('done')

a = b + c; (print or io.write)('done')

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

;(print or io.write)('done')

Блок может быть четко разграничен для получения одного заявления:

stat ::= do block end

Явные блоки полезны для управления областью объявлений переменных. Явные блоки также иногда используются для добавления оператора возврата в середине другого блока (см. §3.3.4 ).

3.3.2-Чанки

Единица компиляции Lua называется чанком . Синтаксически чанк — это просто блок:

chunk ::= block

Lua обрабатывает фрагмент как тело анонимной функции с переменным числом аргументов (см. §3.4.11 ). Таким образом, куски могут определять локальные переменные, получать аргументы и возвращать значения. Более того, такая анонимная функция компилируется как в области действия внешней локальной переменной с именем _ENV (см. §2.2 ). Результирующая функция всегда имеет _ENV в качестве единственной внешней переменной, даже если она не использует эту переменную.

Фрагмент может храниться в файле или в строке внутри основной программы. Чтобы выполнить фрагмент, Lua сначала загружает его, предварительно компилируя код фрагмента в инструкции для виртуальной машины, а затем Lua выполняет скомпилированный код с интерпретатором для виртуальной машины.

Чанки также могут быть предварительно скомпилированы в двоичную форму; подробности см. в программе luac и в функции string.dump . Программы в исходной и скомпилированной формах взаимозаменяемы; Lua автоматически определяет тип файла и действует соответственно (см. load ).

3.3.3-Назначение

Луа допускает множественные назначения.Поэтому синтаксис присваивания определяет список переменных слева и список выражений справа.Элементы в обоих списках разделены запятыми:

stat ::= varlist ‘=’ explist
varlist ::= var {‘,’ var}
explist ::= exp {‘,’ exp}

Выражения обсуждаются в §3.4 .

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

Оператор присваивания сначала оценивает все свои выражения,и только затем выполняются присваивания.Таким образом,код

i = 3
i, a[i] = i+1, 20

устанавливает a[3] в 20, не влияя a[4] потому что i в a[i] оценивается (до 3) до того, как ему присваивается 4. Аналогично, строка

x, y = y, x

меняет местами значения x и y , и

x, y, z = y, z, x

циклически переставляет значения x , y и z .

Присвоение глобальному имени x = val эквивалентно присвоению _ENV.x = val (см. §2.2 ).

Значение присвоений полям таблицы и глобальным переменным (которые на самом деле тоже являются полями таблицы) можно изменить с помощью метатаблиц (см. §2.4 ).

3.3.4-Структуры управления

Управляющие структуры if , while и repeat имеют обычный смысл и знакомый синтаксис:

stat ::= while exp do block end
stat ::= repeat block until exp
stat ::= if exp then block {elseif exp then block} [else block] end

В Lua также есть оператор for в двух вариантах (см. §3.3.5 ).

Выражение условия управляющей структуры может возвращать любое значение. И ложь и ноль тест ложно. Все значения отличны от nil и false test true. В частности, число 0 и пустая строка также проверяют истинность.

В цикле Repeatuntil внутренний блок не заканчивается на ключевом слове until , а только после условия. Таким образом, условие может ссылаться на локальные переменные, объявленные внутри блока цикла.

Оператор goto передает управление программой метке. По синтаксическим причинам метки в Lua тоже считаются операторами:

stat ::= goto Name
stat ::= label
label ::= ‘::’ Name ‘::’

Метка видна во всем блоке,где она определена,за исключением вложенных функций.Команда goto может перейти к любой видимой метке,если она не входит в область видимости локальной переменной.Не следует объявлять метку там,где видна метка с тем же именем,даже если эта другая метка была объявлена в окружающем блоке.

Этикетки и пустые заявления называются недействительным заявление , так как они не выполняют никаких действий.

Оператор break завершает выполнение цикла while , repeat или for , переходя к следующему оператору после цикла:

stat ::= break

Перерыв заканчивает самую внутреннюю охватывающую петлю.

Оператор return используется для возврата значений из функции или фрагмента (который обрабатывается как анонимная функция). Функции могут возвращать более одного значения, поэтому синтаксис оператора возврата следующий :

stat ::= return [explist] [‘;’]

Оператор возврата может быть записан только как последний оператор блока. Если необходимо выполнить возврат в середине блока, то можно использовать явный внутренний блок, как в идиоме do return end , потому что теперь return является последним оператором в его (внутреннем) блоке.

3.3.5-Для заявления

Оператор for имеет две формы: числовую и общую.

Числовой цикл for

Числовой цикл for повторяет блок кода, в то время как управляющая переменная проходит через арифметическую прогрессию. Он имеет следующий синтаксис:

stat ::= for Name ‘=’ exp ‘,’ exp [‘,’ exp] do block end

Данный идентификатор (Имя) определяет управляющую переменную, которая является новой переменной, локальной для тела цикла ( блока ).

Цикл начинается с однократного вычисления трех управляющих выражений. Их значения называются соответственно начальным значением , пределом и шагом . Если шаг отсутствует, по умолчанию используется 1.

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

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

Для целочисленных циклов управляющая переменная никогда не оборачивается;вместо этого цикл завершается в случае переполнения.

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

Общий цикл for

Общий оператор for работает с функциями, называемыми итераторами . На каждой итерации вызывается функция итератора для создания нового значения, которая останавливается, когда это новое значение равно нулю . Общий цикл for имеет следующий синтаксис:

stat ::= for namelist in explist do block end
namelist ::= Name {‘,’ Name}

Для заявления как

for var_1, ···, var_n in explist do body end

работает следующим образом.

Имена var_i объявляют переменные цикла, локальные для тела цикла. Первая из этих переменных — это управляющая переменная .

Цикл начинается с вычисления Expist для получения четырех значений: функции итератора , состояния , начального значения для управляющей переменной и закрывающего значения .

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

Закрывающее значение ведет себя как подлежащая закрытию переменная (см. §3.3.8 ), которую можно использовать для высвобождения ресурсов после завершения цикла. В противном случае он не мешает петле.

Не следует изменять значение управляющей переменной во время цикла.

3.3.6-Вызовы функций как утверждения

Для обеспечения возможных побочных эффектов вызовы функций могут выполняться в виде операторов:

stat ::= functioncall

В этом случае все возвращаемые значения отбрасываются. Вызовы функций объясняются в §3.4.10 .

3.3.7-Локальные декларации

Локальные переменные могут быть объявлены в любом месте блока.Объявление может включать инициализацию:

stat ::= local attnamelist [‘=’ explist]
attnamelist ::=  Name attrib {‘,’ Name attrib}

Если присутствует, начальное присвоение имеет ту же семантику множественного присвоения (см. §3.3.3 ). В противном случае все переменные инициализируются nil .

Имя каждой переменной может быть постфиксировано атрибутом (имя в угловых скобках):

attrib ::= [‘<’ Name ‘>’]

Возможны два атрибута: const , который объявляет константную переменную, то есть переменную, которой нельзя присвоить значение после ее инициализации; и close , которая объявляет подлежащую закрытию переменную (см. §3.3.8 ). Список переменных может содержать не более одной подлежащей закрытию переменной.

Блок также является блоком (см. §3.3.2 ), поэтому локальные переменные могут быть объявлены в блоке вне любого явного блока.

Правила видимости для локальных переменных объясняются в §3.5 .

3.3.8-Переменные,которые должны быть закрыты

Закрытая переменная ведет себя как постоянная локальная переменная, за исключением того, что ее значение закрывается всякий раз, когда переменная выходит за пределы области видимости, включая нормальное завершение блока, выход из блока с помощью break / goto / return или выход по ошибке.

Здесь закрыть значение означает вызвать его __close . При вызове метаметода само значение передается как первый аргумент, а объект ошибки, вызвавший выход (если есть), передается как второй аргумент; если ошибки не было, второй аргумент равен нулю .

Значение, присвоенное закрываемой переменной, должно иметь __close или быть ложным. ( nil и false игнорируются как закрываемые значения.)

Если несколько закрываемых переменных выходят из области видимости при одном и том же событии,они закрываются в порядке,обратном порядку их объявления.

Если при выполнении закрывающего метода возникает какая-либо ошибка,она обрабатывается как ошибка в обычном коде,в котором была определена переменная.Однако Lua может вызвать метод еще раз.

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

Если сопрограмма завершается и больше никогда не возобновляется, некоторые переменные могут никогда не выйти за пределы области видимости, и, следовательно, они никогда не будут закрыты. (Эти переменные созданы внутри сопрограммы и в области видимости в точке, где сопрограмма выдала ошибку.) Точно так же, если сопрограмма завершается ошибкой, она не разворачивает свой стек, поэтому не закрывает никакую переменную. В обоих случаях вы можете использовать финализаторы или вызвать coroutine.close , чтобы закрыть переменные. Однако, если сопрограмма была создана через coroutine.wrap , то соответствующая функция закроет сопрограмму в случае ошибки.

3.4-Выражения

Основные выражения в Lua следующие:

exp ::= prefixexp
exp ::= nil | false | true
exp ::= Numeral
exp ::= LiteralString
exp ::= functiondef
exp ::= tableconstructor
exp ::= ‘...’
exp ::= exp binop exp
exp ::= unop exp
prefixexp ::= var | functioncall | ‘(’ exp ‘)’

Численные и литеральные строки объясняются в §3.1 ; переменные объясняются в §3.2 ; определения функций объясняются в §3.4.11 ; вызовы функций объясняются в §3.4.10 ; конструкторы таблиц объясняются в §3.4.9 . Выражения vararg, обозначаемые тремя точками (‘ ... ‘), могут использоваться только непосредственно внутри функции vararg; они объясняются в §3.4.11 .

Бинарные операторы включают арифметические операторы (см. §3.4.1 ), побитовые операторы (см. §3.4.2 ), операторы отношения (см. §3.4.4 ), логические операторы (см. §3.4.5 ) и оператор конкатенации (см. §3.4.5 ). 3.4.6 ). Унарные операторы включают унарный минус (см. §3.4.1 ), унарное побитовое НЕ (см. §3.4.2 ), унарное логическое НЕ (см. §3.4.5 ) и унарный оператор длины (см. §3.4.7 ). .

И вызовы функций, и выражения vararg могут привести к нескольким значениям. Если вызов функции используется как оператор (см. §3.3.6 ), то его возвращаемый список корректируется до нулевых элементов, таким образом отбрасывая все возвращаемые значения. Если выражение используется в качестве последнего (или единственного) элемента списка выражений, корректировка не выполняется (если только выражение не заключено в круглые скобки). Во всех других контекстах Lua корректирует список результатов до одного элемента, либо отбрасывая все значения, кроме первого, либо добавляя один ноль , если значений нет.

Вот несколько примеров:

f()                
g(f(), x)          
g(x, f())          
a,b,c = f(), x     
a,b = ...          
                   
                   

a,b,c = x, f()     
a,b,c = f()        
return f()         
return ...         
return x,y,f()     
{f()}              
{...}              
{f(), nil}         

Любое выражение, заключенное в круглые скобки, всегда дает только одно значение. Таким образом, (f(x,y,z)) всегда является одним значением, даже если f возвращает несколько значений. (Значение (f(x,y,z)) — это первое значение, возвращаемое f или nil, если f не возвращает никаких значений.)

3.4.1-Арифметические операторы

Lua поддерживает следующие арифметические операторы:

  • +: addition
  • -: subtraction
  • *: multiplication
  • / : деление с плавающей запятой
  • // : разделение этажей
  • %: modulo
  • ^: exponentiation
  • - : унарный минус

За исключением возведения в степень и деления с плавающей запятой, арифметические операторы работают следующим образом: Если оба операнда являются целыми числами, операция выполняется над целыми числами, и результатом является целое число. В противном случае, если оба операнда являются числами, они преобразуются в числа с плавающей запятой, операция выполняется в соответствии с правилами машины для арифметики с плавающей запятой (обычно стандарт IEEE 754), и результатом является число с плавающей запятой. (Библиотека строк приводит строки к числам в арифметических операциях; подробности см. в §3.4.3 .)

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

Деление по полу ( // ) — это деление, округляющее частное до минус бесконечности, в результате чего получается нижний предел деления его операндов.

Модуло определяется как остаток деления,который округляет коэффициент в сторону минус бесконечности (деление на этаж).

В случае переполнения в целочисленной арифметике все операции переносятся .

3.4.2-Побитовые операторы

Lua поддерживает следующие битовые операторы:

  • & : побитовое И
  • | : побитовое ИЛИ
  • ~ : побитовое исключающее ИЛИ
  • >> : сдвиг вправо
  • << : сдвиг влево
  • ~ : унарное побитовое НЕ

Все побитовые операции преобразуют свои операнды в целые числа (см. §3.4.3 ), работают со всеми битами этих целых чисел и приводят к целому числу.

Сдвиги вправо и влево заполняют пустые биты нулями.Отрицательные смещения смещаются в другую сторону;смещения с абсолютными значениями,равными или превышающими число битов в целочисленном выражении,приводят к нулю (так как все биты смещаются).

3.4.3-Коэрцитивы и преобразования

Lua обеспечивает некоторые автоматические преобразования между некоторыми типами и представлениями во время выполнения.Побитовые операторы всегда преобразуют операнды с плавающей точкой в целые числа.Экспоненция и деление с плавающей точкой всегда преобразуют целочисленные операнды в плавающие.Все остальные арифметические операции,применяемые к смешанным числам (целым и плавающим),преобразуют целочисленный операнд в плавающий.API языка Си также преобразует целые числа в плавающие и плавающие в целые,по мере необходимости.Более того,конкатенация строк принимает в качестве аргументов не только строки,но и числа.

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

При преобразовании из плавающих чисел в целые проверяется,имеет ли плавающий точное представление в виде целого числа (то есть плавающий имеет интегральное значение и находится в диапазоне целочисленного представления).Если да,то это представление является результатом.В противном случае преобразование не удастся.

В нескольких местах в Lua строки при необходимости преобразуются в числа.В частности,библиотека строк устанавливает метаметоды,которые пытаются преобразовать строки в числа во всех арифметических операциях.Если преобразование не удается,библиотека вызывает метаметод другого операнда (если он присутствует)или выдает ошибку.Обратите внимание,что побитовые операторы не выполняют такое принуждение.

Тем не менее всегда рекомендуется не полагаться на эти неявные приведения, поскольку они не всегда применяются; в частности, "1"==1 ложно, а "1"<1 вызывает ошибку (см. §3.4.4 ). Эти приведения существуют в основном для совместимости и могут быть удалены в будущих версиях языка.

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

Преобразование чисел в строки использует неуказанный удобочитаемый формат. Чтобы преобразовать числа в строки определенным образом, используйте функцию string.format .

3.4.4-Реляционные операторы

Lua поддерживает следующие реляционные операторы:

  • ==: equality
  • ~=: inequality
  • < : меньше чем
  • > : больше чем
  • <= : меньше или равно
  • >= : больше или равно

Эти операторы всегда приводят к ложному или истинному результату .

Равенство ( == ) сначала сравнивает тип своих операндов. Если типы разные, то результат ложный . В противном случае сравниваются значения операндов. Строки равны, если они имеют одинаковое байтовое содержимое. Числа равны, если они обозначают одно и то же математическое значение.

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

Вы можете изменить способ, которым Lua сравнивает таблицы и пользовательские данные, используя метаметод __eq (см. §2.4 ).

Сравнение на равенство не преобразует строки в числа и наоборот. Таким образом, "0"==0 оценивается как ложь , а t[0] и t["0"] обозначают разные записи в таблице.

Оператор ~= в точности отрицает равенство ( == ).

Операторы заказа работают следующим образом. Если оба аргумента являются числами, то они сравниваются в соответствии с их математическими значениями, независимо от их подтипов. В противном случае, если оба аргумента являются строками, то их значения сравниваются в соответствии с текущей локалью. В противном случае Lua пытается вызвать метаметод __lt или __le (см. §2.4 ). Сравнение a > b преобразуется в b < a , а a >= b преобразуется в b <= a .

В соответствии со стандартом IEEE 754,специальное значение NaN считается ни меньше,ни равным,ни больше любого значения,включая себя.

3.4.5-Логические операторы

Логические операторы в Lua — это и , или , и не . Подобно управляющим структурам (см. §3.3.4 ), все логические операторы рассматривают как false , так и nil как false, а все остальное как true.

Оператор отрицания не всегда возвращает false или true . Оператор соединения и возвращает свой первый аргумент, если это значение ложно или равно нулю ; в противном случае и возвращает свой второй аргумент. Оператор дизъюнкции or возвращает свой первый аргумент, если это значение отличается от nil и false ; в противном случае или возвращает свой второй аргумент. Оба and и or используют оценку короткого замыкания; то есть второй операнд оценивается только в случае необходимости. Вот некоторые примеры:

10 or 20            
10 or error()       
nil or "a"          
nil and 10          
false and error()   
false and nil       
false or nil        
10 and 20           
3.4.6-Конкатенация

Оператор конкатенации строк в Lua обозначается двумя точками (‘ .. ‘). Если оба операнда являются строками или числами, то числа преобразуются в строки в неуказанном формате (см. §3.4.3 ). В противном случае вызывается метаметод __concat (см.§2.4 ).

3.4.7-Оператор длины

Оператор длины обозначается унарным префиксным оператором # .

Длина строки-это количество байтов в ней.(Это обычное значение длины строки,когда каждый символ равен одному байту).

Оператор длины, примененный к таблице, возвращает границу в этой таблице. Границы в таблице t любое натуральное число , которое удовлетворяет следующему условию:

(border == 0 or t[border] ~= nil) and t[border + 1] == nil

Другими словами,граница-это любой (натуральный)индекс,присутствующий в таблице,за которым следует отсутствующий индекс (или ноль,когда индекс 1 отсутствует).

Таблица с одной границей называется последовательностью . Например, таблица {10, 20, 30, 40, 50} является последовательностью, так как у нее только одна граница (5). Таблица {10, 20, 30, nil, 50} имеет две границы (3 и 5), поэтому она не является последовательностью. ( Ноль в индексе 4 называется дырой .) Таблица {nil, 20, 30, nil, nil, 60, nil} имеет три границы (0, 3 и 6) и три дыры (в индексах 1, 4, и 5), так что это тоже не последовательность. Таблица {} представляет собой последовательность с границей 0. Обратите внимание, что неестественные ключи не влияют на то, является ли таблица последовательностью.

Когда t — последовательность, #t возвращает ее единственную границу, которая соответствует интуитивному представлению о длине последовательности. Когда t не является последовательностью, #t может возвращать любую из своих границ. (Точный зависит от деталей внутреннего представления таблицы, которое, в свою очередь, может зависеть от того, как таблица была заполнена, и адресов памяти ее нечисловых ключей.)

Вычисление длины таблицы имеет гарантированно худшее время O (log n) , где n — наибольший естественный ключ в таблице.

Программа может изменить поведение оператора длины для любого значения, кроме строк, с помощью метаметода __len (см. §2.4 ).

3.4.8-Приоритет

Приоритет оператора в Lua следует из нижеследующей таблицы,от более низкого к более высокому приоритету:

or
and
<     >     <=    >=    ~=    ==
|
~
&
<<    >>
..
+     -
*     /     
unary operators (not   #     -     ~)
^

Как обычно, вы можете использовать круглые скобки для изменения приоритета выражения. Операторы конкатенации (‘ .. ‘) и возведения в степень (‘ ^ ‘) являются правоассоциативными. Все остальные бинарные операторы левоассоциативны.

3.4.9-Конструкторы таблиц

Конструкторы таблиц-это выражения,которые создают таблицы.Каждый раз при оценке конструктора создается новая таблица.Конструктор может быть использован для создания пустой таблицы или для создания таблицы и инициализации некоторых ее полей.Общий синтаксис для конструкторов

tableconstructor ::= ‘{’ [fieldlist] ‘}’
fieldlist ::= field {fieldsep field} [fieldsep]
field ::= ‘[’ exp ‘]’ ‘=’ exp | Name ‘=’ exp | exp
fieldsep ::= ‘,’ | ‘;’

Каждое поле формы [exp1] = exp2 добавляет в новую таблицу запись с ключом exp1 и значением exp2 . Поле формы name = exp эквивалентно ["name"] = exp . Поля формы exp эквивалентны [i] = exp , где i — последовательные целые числа, начинающиеся с 1; поля в других форматах не влияют на этот подсчет. Например,

a = { [f(1)] = g

равносильно

do
  local t = {}
  t[f(1)] = g
  t[1] = "x"         
  t[2] = "y"         
  t.x = 1            
  t[3] = f(x)        
  t[30] = 23
  t[4] = 45          
  a = t
end

Порядок заданий в конструкторе не определен.(Этот порядок будет релевантен только при наличии повторяющихся клавиш).

Если последнее поле в списке имеет вид exp , а выражение является вызовом функции или выражением vararg, то все значения, возвращаемые этим выражением, входят в список последовательно (см. §3.4.10 ).

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

3.4.10-Вызовы функций

Вызов функции в Луа имеет следующий синтаксис:

functioncall ::= prefixexp args

При вызове функции оцениваются первое префиксное выражение и аргументы. Если значение prefixexp имеет тип function , то эта функция вызывается с заданными аргументами. В противном случае, если он присутствует, вызывается метаметод prefixexp __call : его первым аргументом является значение prefixexp, за которым следуют исходные аргументы вызова (см. §2.4 ).

The form

functioncall ::= prefixexp ‘:’ Name args

может использоваться для имитации методов. Вызов v:name(args) является синтаксическим сахаром для v.name(v,args) , за исключением того, что v вычисляется только один раз.

Аргументы имеют следующий синтаксис:

args ::= ‘(’ [explist] ‘)’
args ::= tableconstructor
args ::= LiteralString

Все выражения аргументов оцениваются перед вызовом. Вызов формы f{fields} является синтаксическим сахаром для f({fields}) ; то есть список аргументов — это одна новая таблица. Вызов формы f'string' (или f"string" или f[[string]] ) является синтаксическим сахаром для f('string') ; то есть список аргументов представляет собой одну буквальную строку.

Вызов формы return functioncall вне области действия закрываемой переменной называется хвостовым вызовом . Lua реализует правильные хвостовые вызовы (или правильную хвостовую рекурсию ): в хвостовом вызове вызываемая функция повторно использует запись в стеке вызывающей функции. Следовательно, нет ограничений на количество вложенных хвостовых вызовов, которые может выполнить программа. Однако хвостовой вызов стирает любую отладочную информацию о вызывающей функции. Обратите внимание, что хвостовой вызов происходит только с определенным синтаксисом, где returnимеет один единственный вызов функции в качестве аргумента, и он выходит за рамки любой закрываемой переменной. Этот синтаксис заставляет вызывающую функцию возвращать в точности результаты вызываемой функции без каких-либо промежуточных действий. Итак, ни один из следующих примеров не является хвостовым вызовом:

return (f(x))        
return 2 * f(x)      
return x, f(x)       
f(x); return         
return x or f(x)     
3.4.11-Определения функций

Синтаксис для определения функции

functiondef ::= function funcbody
funcbody ::= ‘(’ [parlist] ‘)’ block end

Следующий синтаксический сахар упрощает определение функций:

stat ::= function funcname funcbody
stat ::= local function Name funcbody
funcname ::= Name {‘.’ Name} [‘:’ Name]

The statement

function f () body end

translates to

f = function () body end

The statement

function t.a.b.c.f () body end

translates to

t.a.b.c.f = function () body end

The statement

local function f () body end

translates to

local f; f = function () body end

not to

local f = function () body end

(Это имеет значение только в том случае, если тело функции содержит ссылки на f .)

Определение функции — это исполняемое выражение, значение которого имеет тип function . Когда Lua прекомпилирует чанк, все его тела функций также прекомпилированы, но они еще не созданы. Затем, когда Lua выполняет определение функции, функция создается (или закрывается ). Этот экземпляр функции или закрытие является последним значением выражения.

Параметры действуют как локальные переменные,которые инициализируются значениями аргументов:

parlist ::= namelist [‘,’ ‘...’] | ‘...’

Когда вызывается функция Lua, она корректирует свой список аргументов в соответствии с длиной своего списка параметров, если только функция не является функцией vararg , что обозначено тремя точками (‘ ... ‘) в конце ее списка параметров. . Функция vararg не изменяет свой список аргументов; вместо этого он собирает все дополнительные аргументы и передает их функции через выражение vararg, который также записывается в виде трех точек. Значение этого выражения представляет собой список всех фактических дополнительных аргументов, аналогичный функции с несколькими результатами. Если выражение vararg используется внутри другого выражения или в середине списка выражений, то его возвращаемый список корректируется до одного элемента. Если выражение используется как последний элемент списка выражений, корректировка не производится (если последнее выражение не заключено в круглые скобки).

В качестве примера рассмотрим следующие определения:

function f(a, b) end
function g(a, b, ...) end
function r() return 1,2,3 end

Далее,у нас есть следующее отображение от аргументов к параметрам и к выражению vararg:

CALL             PARAMETERS

f(3)             a=3, b=nil
f(3, 4)          a=3, b=4
f(3, 4, 5)       a=3, b=4
f(r(), 10)       a=1, b=10
f(r())           a=1, b=2

g(3)             a=3, b=nil, ... 
g(3, 4)          a=3, b=4,   ... 
g(3, 4, 5, 8)    a=3, b=4,   ... 
g(5, r())        a=5, b=1,   ... 

Результаты возвращаются с помощью оператора return (см. §3.3.4 ). Если управление достигает конца функции, не встречая оператора return , то функция возвращается без результатов.

Существует системно-зависимое ограничение на количество значений,которые может вернуть функция.Это ограничение гарантированно больше 1000.

Толстой кишки синтаксис используется для эмуляции методов , добавляя неявный дополнительный параметр self к функции. Таким образом, заявление

function t.a.b.c:f (params) body end

синтаксический сахар для

t.a.b.c.f = function (self, params) body end
3.5-Правила видимости

Луа-это лексически скопированный язык.Область действия локальной переменной начинается с первого утверждения после ее объявления и продолжается до последнего неотвратимого утверждения самого внутреннего блока,который включает в себя объявление.Рассмотрим следующий пример:

x = 10                
do                    
  local x = x         
  print(x)            
  x = x+1
  do                  
    local x = x+1     
    print(x)          
  end
  print(x)            
end
print(x)              

Обратите внимание, что в таком объявлении, как local x = x , новый объявляемый x еще не входит в область видимости, и поэтому второй x относится к внешней переменной.

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

Обратите внимание, что каждое выполнение локального оператора определяет новые локальные переменные. Рассмотрим следующий пример:

a = {}
local x = 20
for i = 1, 10 do
  local y = 0
  a[i] = function () y = y + 1; return x + y end
end

Цикл создает десять замыканий (то есть десять экземпляров анонимной функции). Каждое из этих замыканий использует различную переменную y , в то время как все они имеют один и тот же x .

4-Интерфейс прикладных программ

В этом разделе описывается C API для Lua, то есть набор функций C, доступных главной программе для связи с Lua. Все функции API и связанные с ними типы и константы объявлены в заголовочном файле lua.h .

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

Как и в большинстве библиотек C, функции Lua API не проверяют свои аргументы на достоверность или согласованность. Однако вы можете изменить это поведение, скомпилировав Lua с определенным макросом LUA_USE_APICHECK .

Библиотека Lua полностью реентерабельна: в ней нет глобальных переменных. Он хранит всю необходимую информацию в динамической структуре, называемой состоянием Lua .

Каждое состояние Lua имеет один или несколько потоков, которые соответствуют независимым, кооперативным линиям выполнения. Тип lua_State (несмотря на название) относится к потоку. (Косвенно, через поток, это также относится к состоянию Lua, связанному с потоком.)

Указатель на поток должен быть передан в качестве первого аргумента каждой функции в библиотеке, кроме lua_newstate , которая создает состояние Lua с нуля и возвращает указатель на основной поток в новом состоянии.

4.1-Стек

Lua использует виртуальный стек для передачи значений в и из C. Каждый элемент в этом стеке представляет значение Lua ( ноль , число, строка и т. Д.). Функции в API могут обращаться к этому стеку через параметр состояния Lua, который они получают.

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

Для удобства большинство операций запросов в API не подчиняются строгой дисциплине стека. Вместо этого они могут ссылаться на любой элемент в стеке с помощью индекса : положительный индекс представляет собой абсолютную позицию в стеке, начиная с 1 как нижней части стека; отрицательный индекс представляет собой смещение относительно вершины стека. Более конкретно, если в стеке n элементов, то индекс 1 представляет первый элемент (то есть элемент, который был помещен в стек первым), а индекс n представляет последний элемент; index -1 также представляет последний элемент (то есть элемент вверху), а index -n представляет первый элемент.

4.1.1-Размер стека

Когда вы взаимодействуете с Lua API, вы несете ответственность за обеспечение согласованности. В частности, вы отвечаете за контроль переполнения стека . Вы можете использовать функцию lua_checkstack , чтобы убедиться, что в стеке достаточно места для добавления новых элементов.

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

Когда вы вызываете функцию Lua без фиксированного количества результатов (см. lua_call ), Lua гарантирует, что в стеке достаточно места для всех результатов, но не гарантирует дополнительного места. Итак, прежде чем lua_checkstack что-либо в стек после такого вызова, вы должны использовать lua_checkstack .

4.1.2-Допустимые и приемлемые индексы

Любая функция в API, которая получает индексы стека, работает только с действительными индексами или допустимыми индексами .

Действительный индекс — это индекс, ссылающийся на позицию, в которой хранится изменяемое значение Lua. Он содержит индексы стека от 1 до вершины стека ( 1 ≤ abs(index) ≤ top ) плюс псевдоиндексы , которые представляют некоторые позиции, доступные коду C, но не находящиеся в стеке. Псевдоиндексы используются для доступа к реестру (см. §4.3 ) и значениям вверх функции C (см. §4.2 ).

Функции, которым не требуется конкретная изменяемая позиция, а только значение (например, функции запросов), могут вызываться с допустимыми индексами. Приемлемым индексом может быть любой допустимый индекс, но он также может быть любым положительным индексом после вершины стека в пределах пространства, выделенного для стека, то есть индексы до размера стека. (Обратите внимание, что 0 никогда не является приемлемым индексом.) Индексы повышающих значений (см. §4.2 ), превышающие реальное количество повышающих значений в текущей функции C, также допустимы (но недействительны). Если не указано иное, функции в API работают с допустимыми индексами.

Допустимые индексы служат для того,чтобы избежать дополнительных проверок вершины стека при запросе стека.Например,функция языка Си может запросить свой третий аргумент без необходимости проверять,существует ли третий аргумент,то есть без необходимости проверять,является ли 3 допустимым индексом.

Для функций, которые могут быть вызваны с допустимыми индексами, любой недействительный индекс обрабатывается так, как если бы он содержал значение виртуального типа LUA_TNONE , которое ведет себя как значение nil.

4.1.3-Указатели на строки

Некоторые функции в API возвращают указатели ( const char* ) на строки Lua в стеке. (См. lua_pushfstring , lua_pushlstring , lua_pushstring и lua_tolstring . См. Также luaL_checklstring , luaL_checkstring и luaL_tolstring во вспомогательной библиотеке.)

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

Некоторые функции в интерфейсе отладки также возвращают указатели на строки, а именно lua_getlocal , lua_getupvalue , lua_setlocal и lua_setupvalue . Для этих функций указатель гарантированно действителен, пока вызывающая функция активна и данное закрытие (если оно было задано) находится в стеке.

За исключением этих гарантий,сборщик мусора может свободно аннулировать любой указатель на внутренние строки.

4.2-Закрытия C

Когда создается функция C, с ней можно связать некоторые значения, создавая таким образом замыкание на C (см. lua_pushcclosure ); эти значения называются upvalues и доступны функции всякий раз, когда она вызывается.

Всякий раз, когда вызывается функция C, ее восходящие значения располагаются по определенным псевдоиндексам. Эти псевдоиндексы создаются макросом lua_upvalueindex . Первое повышающее значение, связанное с функцией, имеет индекс lua_upvalueindex(1) и так далее. Любой доступ к lua_upvalueindex(n) , где n больше, чем количество повышающих значений текущей функции (но не больше 256, что составляет единицу плюс максимальное количество повышающих значений в закрытии), создает приемлемый, но недопустимый индекс.

Замыкание C также может изменять значения соответствующих ему ап-значений.

4.3-Реестр

Lua предоставляет реестр , предопределенную таблицу, которая может использоваться любым кодом C для хранения любых значений Lua, которые ему необходимы. Таблица реестра всегда доступна по псевдоиндексу LUA_REGISTRYINDEX . Любая библиотека C может хранить данные в этой таблице, но она должна позаботиться о том, чтобы выбрать ключи, отличные от тех, которые используются другими библиотеками, чтобы избежать коллизий. Как правило, вы должны использовать в качестве ключа строку, содержащую имя вашей библиотеки, или легкие пользовательские данные с адресом объекта C в вашем коде, или любого объекта Lua, созданного вашим кодом. Как и в случае с именами переменных, строковые ключи, начинающиеся с подчеркивания, за которым следуют прописные буквы, зарезервированы для Lua.

Целочисленные ключи в реестре используются ссылочным механизмом (см. luaL_ref ) и некоторыми предопределенными значениями. Следовательно, целочисленные ключи в реестре нельзя использовать для других целей.

Когда вы создаете новое состояние Lua, его реестр поставляется с некоторыми предопределенными значениями. Эти предопределенные значения , индексируются с целыми ключами , определенных как константы в lua.h . Определены следующие константы:

  • LUA_RIDX_MAINTHREAD : поэтому индексу в реестре есть главный поток состояния. (Основной поток создается вместе с состоянием.)
  • LUA_RIDX_GLOBALS : вэтом индексе реестр имеет глобальную среду.
4.4-Обработка ошибок в C

Внутренне Lua использует средство C longjmp для обработки ошибок. (Lua будет использовать исключения, если вы скомпилируете его как C ++; LUAI_THROW ищите LUAI_THROW в исходном коде.) Когда Lua сталкивается с какой-либо ошибкой, такой как ошибка выделения памяти или ошибка типа, возникает ошибка; то есть делает прыжок в длину. В защищенной среде для установки точки восстановления используется setjmp ; при любой ошибке выполняется переход к самой последней активной точке восстановления.

Внутри функции C вы можете явно вызвать ошибку, вызвав lua_error .

Большинство функций в API могут вызвать ошибку,например,из-за ошибки выделения памяти.Документация по каждой функции указывает,может ли она вызвать ошибку.

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

Функция паники, как следует из ее названия, является механизмом последней инстанции. Программы должны избегать этого. Как правило, когда функция C вызывается Lua с состоянием Lua, она может делать все, что захочет, в этом состоянии Lua, поскольку она уже должна быть защищена. Однако, когда код C работает с другими состояниями Lua (например, аргументом Lua-состояния функции, состоянием Lua, хранящимся в реестре, или результатом lua_newthread ), он должен использовать их только в вызовах API, которые не могут вызывать ошибки.

Функция паники работает так, как если бы она была обработчиком сообщений (см. §2.3 ); в частности, объект ошибки находится на вершине стека. Однако нет никаких гарантий относительно пространства в стеке. Чтобы поместить что-либо в стек, функция panic должна сначала проверить доступное пространство (см. §4.1.1 ).

4.4.1-Коды состояния

Некоторые функции,сообщающие об ошибках в API,используют следующие коды состояния для обозначения различных видов ошибок или других условий:

  • LUA_OK (0):ошибок нет.
  • LUA_ERRRUN :ошибка времени выполнения.
  • LUA_ERRMEM :ошибка выделения памяти. Для таких ошибок Lua не вызывает обработчик сообщений.
  • LUA_ERRERR :ошибка при запуске обработчика сообщений.
  • LUA_ERRSYNTAX :синтаксическая ошибка во время предварительной компиляции.
  • LUA_YIELD :поток (сопрограмма) уступает.
  • LUA_ERRFILE :ошибка, связанная с файлом; например, он не может открыть или прочитать файл.

Эти константы определены в файле заголовка lua.h .

4.5-Работа с доходностью в C

Внутри Lua использует средство C longjmp для создания сопрограммы. Следовательно, если функция C foo вызывает функцию API, и эта функция API дает результат (прямо или косвенно, вызывая другую функцию, которая дает результат), Lua больше не может вернуться к foo , потому что longjmp удаляет свой фрейм из стека C.

Чтобы избежать такого рода проблем, Lua выдает ошибку всякий раз, когда пытается выполнить уступку через вызов API, за исключением трех функций: lua_yieldk , lua_callk и lua_pcallk . Все эти функции получают функцию продолжения (как параметр с именем k ), чтобы продолжить выполнение после yield.

Нам нужно установить некоторую терминологию для объяснения продолжений. У нас есть функция C, вызываемая из Lua, которую мы будем вызывать исходной функцией . Затем эта исходная функция вызывает одну из этих трех функций в C API, которую мы будем называть вызываемой функцией , которая затем возвращает текущий поток. Это может произойти, когда вызываемая функция — это lua_yieldk , или когда вызываемая функция — это либо lua_callk , либо lua_pcallk , а функция, вызванная ими, дает результат.

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

В качестве иллюстрации рассмотрим следующую функцию:

int original_function (lua_State *L) {
  ...     
  status = lua_pcall(L, n, m, h);  
  ...     
}

Теперь мы хотим разрешить выполнение кода Lua с помощью lua_pcall . Во-первых, мы можем переписать нашу функцию, как здесь:

int k (lua_State *L, int status, lua_KContext ctx) {
  ...  
}

int original_function (lua_State *L) {
  ...     
  return k(L, lua_pcall(L, n, m, h), ctx);
}

В приведенном выше коде новая функция k является функцией продолжения (с типом lua_KFunction ), которая должна выполнять всю работу, которую выполняла исходная функция после вызова lua_pcall . Теперь мы должны сообщить Lua, что он должен вызвать k , если код Lua, выполняемый lua_pcall , каким-то образом прерывается (ошибки или уступка), поэтому мы переписываем код, как здесь, заменяя lua_pcall на lua_pcallk :

int original_function (lua_State *L) {
  ...     
  return k(L, lua_pcallk(L, n, m, h, ctx2, k), ctx1);
}

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

Помимо состояния Lua, функция продолжения имеет два других параметра: окончательный статус вызова и значение контекста ( ctx ), которое изначально было передано lua_pcallk . Lua не использует это значение контекста; он передает это значение только из исходной функции в функцию продолжения. Для lua_pcallk статус — это то же значение, которое было бы возвращено lua_pcallk , за исключением того, что это LUA_YIELD при выполнении после yield (вместо LUA_OK ). Для lua_yieldk и lua_callk статус всегда LUA_YIELD когда Lua вызывает продолжение. (Для этих двух функций Lua не будет вызывать продолжение в случае ошибок, потому что они не обрабатывают ошибки.) Аналогично, при использовании lua_callk вы должны вызывать функцию продолжения с LUA_OK в качестве статуса. (Для lua_yieldk нет особого смысла в прямом вызове функции продолжения, потому что lua_yieldk обычно не возвращает.)

Lua обрабатывает функцию продолжения, как если бы это была исходная функция. Функция продолжения получает тот же стек Lua от исходной функции, в том же состоянии, которое было бы, если бы вызываемая функция вернулась. (Например, после lua_callk функция и ее аргументы удаляются из стека и заменяются результатами вызова.) Она также имеет те же самые высокие значения. Все, что он возвращает, обрабатывается Lua, как если бы это был возврат исходной функции.

4.6 – Функции и типы[-o, +p, x ]

Здесь перечислены все функции и типы из C API в алфавитном порядке.У каждой функции есть такой индикатор:

Первое поле o — это количество элементов, извлекаемых функцией из стека. Второе поле, p , показывает, сколько элементов функция помещает в стек. (Любая функция всегда выталкивает свои результаты после извлечения своих аргументов.) Поле в форме x|y означает, что функция может выталкивать (или выталкивать) элементы x или y , в зависимости от ситуации; знак допроса » ? ‘означает, что мы не можем узнать, сколько элементов функция выталкивает / выталкивает, глядя только на ее аргументы. (Например, они могут зависеть от того, что находится в стеке.) Третье поле, x , сообщает, может ли функция вызывать ошибки: ‘ - ‘ означает, что функция никогда не вызывает никаких ошибок; ‘ m ‘означает, что функция может вызывать только ошибки нехватки памяти; ‘ v ‘ означает, что функция может вызывать ошибки, описанные в тексте; ‘ e ‘ означает, что функция может запускать произвольный код Lua напрямую или с помощью метаметодов и, следовательно, может вызывать любые ошибки.

lua_absindex[-0, +0, –]
int lua_absindex (lua_State *L, int idx);

Преобразует допустимый индекс idx в эквивалентный абсолютный индекс (то есть тот, который не зависит от вершины стека).

lua_Alloc
typedef void * (*lua_Alloc) (void *ud,
                             void *ptr,
                             size_t osize,
                             size_t nsize);

Тип функции распределения памяти, используемой Lua. Функция распределителя должна обеспечивать функциональность, аналогичную realloc , но не в точности такую ​​же. Его аргументы — ud , непрозрачный указатель, переданный lua_newstate ; ptr , указатель на блок, который выделяется / перераспределяется / освобождается; osize , исходный размер блока или некоторый код о том, что выделяется; и nsize — новый размер блока.

Когда ptr не равен NULL , osize — это размер блока, на который указывает ptr , то есть размер, заданный при его выделении или перераспределении.

Когда ptr равен NULL , osize кодирует тип объекта, который выделяет Lua. osize — это любое из LUA_TSTRING , LUA_TTABLE , LUA_TFUNCTION , LUA_TUSERDATA или LUA_TTHREAD , когда (и только когда) Lua создает новый объект этого типа. Когда osize — это какое-то другое значение, Lua выделяет память для чего-то еще.

Луа принимает следующее поведение от функции аллокатора:

Когда nsize равен нулю, распределитель должен вести себя как free а затем возвращать NULL .

Когда nsize не равен нулю, распределитель должен вести себя как realloc . В частности, распределитель возвращает NULL тогда и только тогда, когда он не может выполнить запрос.

Вот простая реализация функции распределителя. Он используется во вспомогательной библиотеке luaL_newstate .

static void *l_alloc (void *ud, void *ptr, size_t osize,
                                           size_t nsize) {
  (void)ud;  (void)osize;  
  if (nsize == 0) {
    free(ptr);
    return NULL;
  }
  else
    return realloc(ptr, nsize);
}

Обратите внимание, что Стандарт C гарантирует, что free(NULL) имеет никакого эффекта и что realloc(NULL,size) эквивалентен malloc(size) .

lua_arith[-(2|1), +1, e]
void lua_arith (lua_State *L, int op);

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

Значение op должно быть одной из следующих констант:

  • LUA_OPADD :выполняет сложение ( + )
  • LUA_OPSUB :выполняет вычитание ( - )
  • LUA_OPMUL :выполняет умножение ( * )
  • LUA_OPDIV :выполняет деление с плавающей запятой ( / )
  • LUA_OPIDIV :выполняет разделение этажа ( // )
  • LUA_OPMOD :выполняет по модулю ( % )
  • LUA_OPPOW :возведение в степень ( ^ )
  • LUA_OPUNM :выполняет математическое отрицание (унарный - )
  • LUA_OPBNOT :побитовое НЕ ( ~ )
  • LUA_OPBAND :выполняет побитовое И ( & )
  • LUA_OPBOR :выполняет побитовое ИЛИ ( | )
  • LUA_OPBXOR :выполняет побитовое исключающее ИЛИ ( ~ )
  • LUA_OPSHL :выполняет сдвиг влево ( << )
  • LUA_OPSHR :выполняет сдвиг вправо ( >> )
lua_atpanic[-0, +0, –]
lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf);

Устанавливает новую функцию паники и возвращает старую (см. §4.4 ).

lua_call[-(nargs+1), +nresults, e]
void lua_call (lua_State *L, int nargs, int nresults);

Вызывает функцию. Как и обычные вызовы Lua, lua_call уважает __call . Итак, здесь слово «функция» означает любое вызываемое значение.

Чтобы выполнить вызов, вы должны использовать следующий протокол: сначала вызываемая функция помещается в стек; затем аргументы вызова передаются в прямом порядке; то есть первым передается первый аргумент. Наконец, вы вызываете lua_call ; nargs — это количество аргументов, которые вы поместили в стек. Когда функция возвращается, все аргументы и значение функции выталкиваются, а результаты вызова помещаются в стек. Количество результатов корректируется до nresults , если nresults не LUA_MULTRET . В этом случае все результаты функции передаются; Lua заботится о том, чтобы возвращаемые значения помещались в пространство стека, но не обеспечивает дополнительного места в стеке. Результаты функции помещаются в стек в прямом порядке (первый результат помещается первым), так что после вызова последний результат находится на вершине стека.

Любая ошибка при вызове и запуске функции распространяется вверх (с помощью longjmp ).

Следующий пример показывает,как хост-программа может делать эквивалент этого кода Lua:

a = f("how", t.x, 14)

Вот он в Си:

lua_getglobal(L, "f");                  
lua_pushliteral(L, "how");                       
lua_getglobal(L, "t");                    
lua_getfield(L, -1, "x");        
lua_remove(L, -2);                  
lua_pushinteger(L, 14);                          
lua_call(L, 3, 1);     
lua_setglobal(L, "a");                         

Обратите внимание, что приведенный выше код сбалансирован : в его конце стек возвращается к своей исходной конфигурации. Это считается хорошей практикой программирования.

lua_callk[-(nargs + 1), +nresults, e]
void lua_callk (lua_State *L,
                int nargs,
                int nresults,
                lua_KContext ctx,
                lua_KFunction k);

Эта функция ведет себя точно так же, как lua_call , но позволяет вызываемой функции возвращаться (см. §4.5 ).

lua_CFunction
typedef int (*lua_CFunction) (lua_State *L);

Тип для функций С.

Чтобы правильно взаимодействовать с Lua, функция C должна использовать следующий протокол, который определяет способ передачи параметров и результатов: функция C получает свои аргументы из Lua в своем стеке в прямом порядке (первый аргумент помещается первым). Итак, когда функция запускается, lua_gettop(L) возвращает количество аргументов, полученных функцией. Первый аргумент (если есть) имеет индекс 1, а его последний аргумент — индекс lua_gettop(L) . Чтобы вернуть значения в Lua, функция C просто помещает их в стек в прямом порядке (первый результат помещается первым) и возвращает в C количество результатов. Любое другое значение в стеке под результатами будет правильно отброшено Lua. Как и функция Lua, функция C, вызываемая Lua, также может возвращать множество результатов.

В качестве примера,следующая функция получает переменное количество числовых аргументов и возвращает их среднее и сумму:

static int foo (lua_State *L) {
  int n = lua_gettop(L);    
  lua_Number sum = 0.0;
  int i;
  for (i = 1; i <= n; i++) {
    if (!lua_isnumber(L, i)) {
      lua_pushliteral(L, "incorrect argument");
      lua_error(L);
    }
    sum += lua_tonumber(L, i);
  }
  lua_pushnumber(L, sum/n);        
  lua_pushnumber(L, sum);         
  return 2;                   
}
lua_checkstack[-0, +0, –]
int lua_checkstack (lua_State *L, int n);

Гарантирует, что в стеке есть место как минимум для n дополнительных элементов, то есть вы можете безопасно вставить в него до n значений. Он возвращает false, если он не может выполнить запрос, либо потому, что это приведет к тому, что стек будет больше фиксированного максимального размера (обычно, по крайней мере, несколько тысяч элементов), либо потому, что он не может выделить память для дополнительного пространства. Эта функция никогда не сжимает стек; если в стеке уже есть место для дополнительных элементов, он остается без изменений.

lua_close[-0, +0, –]
void lua_close (lua_State *L);

Закрывает все активные закрываемые переменные в главном потоке,освобождает все объекты в данном состоянии Lua (вызывая соответствующие метаметоды сбора мусора,если таковые имеются),и освобождает всю динамическую память,используемую этим состоянием.

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

lua_compare[-0, +0, e]
int lua_compare (lua_State *L, int index1, int index2, int op);

Сравнивает два значения Lua. Возвращает 1, если значение в индексе index1 удовлетворяет op при сравнении со значением в индексе index2 , следуя семантике соответствующего оператора Lua (то есть он может вызывать метаметоды). В противном случае возвращает 0. Также возвращает 0, если какой-либо из индексов недействителен.

Значение op должно быть одной из следующих констант:

  • LUA_OPEQ :сравнивает на равенство ( == )
  • LUA_OPLT :сравнивает меньше чем ( < )
  • LUA_OPLE :сравнивает меньше или равно ( <= )
lua_concat[-n, +1, e]
void lua_concat (lua_State *L, int n);

Объединяет n значений в верхней части стека, извлекает их и оставляет результат наверху. Если n равно 1, результатом является единственное значение в стеке (то есть функция ничего не делает); если n равно 0, результатом является пустая строка. Конкатенация выполняется в соответствии с обычной семантикой Lua (см. §3.4.6 ).

lua_copy[-0, +0, –]
void lua_copy (lua_State *L, int fromidx, int toidx);

Копирует элемент с индексом fromidx в действительный индекс toidx , заменяя значение в этой позиции. Значения на других позициях не затронуты.

lua_createtable[-0, +1, m]
void lua_createtable (lua_State *L, int narr, int nrec);

Создает новую пустую таблицу и помещает ее в стек. Параметр narr указывает, сколько элементов в таблице будет в последовательности; Параметр nrec указывает, сколько других элементов будет в таблице. Lua может использовать эти подсказки для предварительного выделения памяти для новой таблицы. Это предварительное распределение может улучшить производительность, если вы заранее знаете, сколько элементов будет в таблице. В противном случае вы можете использовать функцию lua_newtable .

lua_dump[-0, +0, –]
int lua_dump (lua_State *L,
                        lua_Writer writer,
                        void *data,
                        int strip);

Выгружает функцию как двоичный фрагмент. Получает функцию Lua наверху стека и создает двоичный фрагмент, который при повторной загрузке приводит к функции, эквивалентной сброшенной. Как она производит части куска, lua_dump вызывает функцию writer (см lua_Writer ) с заданными data , чтобы записать их.

Если strip имеет значение true, двоичное представление может не включать всю отладочную информацию о функции для экономии места.

Возвращаемое значение-это код ошибки,возвращенный последним звонком писателю;0 означает отсутствие ошибок.

Эта функция не выводит функцию Lua из стека.

lua_error[-1, +0, v]
int lua_error (lua_State *L);

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

lua_gc[-0, +0, –]
int lua_gc (lua_State *L, int what, ...);

Управляет сборщиком мусора.

Эта функция выполняет несколько задач в зависимости от значения параметра what . Для параметров, которым требуются дополнительные аргументы, они перечислены после параметра.

  • LUA_GCCOLLECT : выполняет полный цикл сборки мусора.
  • LUA_GCSTOP : останавливает сборщик мусора.
  • LUA_GCRESTART : перезапускает сборщик мусора.
  • LUA_GCCOUNT : возвращает текущий объем памяти (в килобайтах), используемый Lua.
  • LUA_GCCOUNTB : возвращает остаток от деления текущего количества байтов памяти, используемой Lua, на 1024.
  • LUA_GCSTEP (int stepsize) : выполняет инкрементный шаг сборки мусора, соответствующий выделению stepsize килобайтах.

  • LUA_GCISRUNNING : возвращает логическое значение, которое сообщает, работает ли сборщик (т. Е. Не остановлен).
  • LUA_GCINC (int pause, int stepmul, stepsize): переводит сборщик в инкрементальный режим с заданными параметрами (см. §2.5.1 ). Возвращает предыдущий режим ( LUA_GCGEN или LUA_GCINC ).
  • LUA_GCGEN (int minormul, int majormul): переводит сборщик в режим генерации с заданными параметрами (см. §2.5.2 ). Возвращает предыдущий режим ( LUA_GCGEN или LUA_GCINC ).

Дополнительные сведения об этих параметрах см . В разделе collectgarbage .

lua_getallocf[-0, +0, –]
lua_Alloc lua_getallocf (lua_State *L, void **ud);

Возвращает функцию выделения памяти для данного состояния. Если ud не NULL , Lua сохраняет в *ud непрозрачный указатель, заданный при установке функции распределения памяти.

lua_getfield[-0, +1, e]
int lua_getfield (lua_State *L, int index, const char *k);

Помещает в стек значение t[k] , где t — значение по данному индексу. Как и в Lua, эта функция может запускать метаметод для события «index» (см. §2.4 ).

Возвращает тип подтолкнутого значения.

void *lua_getextraspace (lua_State *L);

Возвращает указатель на необработанную область памяти,связанную с данным состоянием Луа.Приложение может использовать эту область для любых целей;Lua не использует ее ни для чего.

В каждом новом потоке эта область инициализируется копией области основного потока.

По умолчанию эта область имеет размер указателя на void, но вы можете перекомпилировать Lua с другим размером для этой области. (См. LUA_EXTRASPACE в luaconf.h .)

lua_getglobal[-0, +1, e]
int lua_getglobal (lua_State *L, const char *name);

Помещает в стек значение глобального name . Возвращает тип этого значения.

lua_geti[-0, +1, e]
int lua_geti (lua_State *L, int index, lua_Integer i);

Помещает в стек значение t[i] , где t — значение по данному индексу. Как и в Lua, эта функция может запускать метаметод для события «index» (см. §2.4 ).

Возвращает тип подтолкнутого значения.

lua_getmetatable[-0, +(0|1), –]
int lua_getmetatable (lua_State *L, int index);

Если значение в данном индексе имеет метатрица,функция выталкивает метатрица на стек и возвращает 1.В противном случае функция возвращает 0 и ничего не выталкивает на стек.

lua_gettable[-1, +1, e]
int lua_gettable (lua_State *L, int index);

Помещает в стек значение t[k] , где t — значение по данному индексу, а k — значение на вершине стека.

Эта функция извлекает ключ из стека, помещая полученное значение на его место. Как и в Lua, эта функция может запускать метаметод для события «index» (см. §2.4 ).

Возвращает тип подтолкнутого значения.

lua_gettop[-0, +0, –]
int lua_gettop (lua_State *L);

Возвращает индекс верхнего элемента в стеке.Так как индексы начинаются с 1,то этот результат равен количеству элементов в стеке;в частности,0 означает пустой стек.

lua_getiuservalue[-0, +1, –]
int lua_getiuservalue (lua_State *L, int index, int n);

Помещает в стек n -е пользовательское значение, связанное с полными пользовательскими данными по заданному индексу, и возвращает тип помещенного значения.

Если пользовательские данные не имеют этого значения, LUA_TNONE nil и возвращает LUA_TNONE .

lua_insert[-1, +1, –]
void lua_insert (lua_State *L, int index);

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

lua_Integer
typedef ... lua_Integer;

Тип целых чисел в Луа.

По умолчанию этот тип long long (обычно 64-битное целое число с двумя дополнениями), но его можно изменить на long или int (обычно 32-битное целое число с двумя дополнениями). (См. LUA_INT_TYPE в luaconf.h .)

Lua также определяет константы LUA_MININTEGER и LUA_MAXINTEGER с минимальным и максимальным значениями, подходящими для этого типа.

lua_isboolean[-0, +0, –]
int lua_isboolean (lua_State *L, int index);

Возвращает 1,если значение в данном индексе является булевым,и 0 в противном случае.

lua_iscfunction[-0, +0, –]
int lua_iscfunction (lua_State *L, int index);

Возвращает 1,если значение на данном индексе является функцией C,и 0 в противном случае.

lua_isfunction[-0, +0, –]
int lua_isfunction (lua_State *L, int index);

Возвращает 1,если значение в данном индексе является функцией (либо C,либо Lua),и 0 в противном случае.

lua_isinteger[-0, +0, –]
int lua_isinteger (lua_State *L, int index);

Возвращает 1,если значение в данном индексе является целым числом (то есть значение является числом и представлено в виде целого числа),и 0 в противном случае.

lua_islightuserdata[-0, +0, –]
int lua_islightuserdata (lua_State *L, int index);

Возвращает 1,если значение в данном индексе является легким пользовательским,и 0 в противном случае.

lua_isnil[-0, +0, –]
int lua_isnil (lua_State *L, int index);

Возвращает 1, если значение данного индекса равно нулю , и 0 в противном случае.

lua_isnone[-0, +0, –]
int lua_isnone (lua_State *L, int index);

Возвращает 1,если данный индекс недействителен,и 0 в противном случае.

lua_isnoneornil[-0, +0, –]
int lua_isnoneornil (lua_State *L, int index);

Возвращает 1, если данный индекс недействителен или если значение этого индекса равно нулю , и 0 в противном случае.

lua_isnumber[-0, +0, –]
int lua_isnumber (lua_State *L, int index);

Возвращает 1,если значение в данном индексе является числом или строкой,конвертируемой в число,и 0 в противном случае.

lua_isstring[-0, +0, –]
int lua_isstring (lua_State *L, int index);

Возвращает 1,если значение в данном индексе является строкой или числом (которое всегда конвертируется в строку),и 0 в противном случае.

lua_istable[-0, +0, –]
int lua_istable (lua_State *L, int index);

Возвращает 1,если значение по данному индексу является табличным,и 0 в противном случае.

lua_isthread[-0, +0, –]
int lua_isthread (lua_State *L, int index);

Возвращает 1,если значение в данном индексе является нитью,и 0 в противном случае.

lua_isuserdata[-0, +0, –]
int lua_isuserdata (lua_State *L, int index);

Возвращает 1,если значение в данном индексе является пользовательским (либо полным,либо светлым),и 0 в противном случае.

lua_isyieldable[-0, +0, –]
int lua_isyieldable (lua_State *L);

Возвращает 1,если данный корутин может давать,и 0 в противном случае.

lua_KContext
typedef ... lua_KContext;

Тип контекстов функции продолжения. Это должен быть числовой тип. Этот тип определяется как intptr_t , когда доступен intptr_t , поэтому он также может хранить указатели. В противном случае он определяется как ptrdiff_t .

lua_KFunction
typedef int (*lua_KFunction) (lua_State *L, int status, lua_KContext ctx);

Введите для функций продолжения (см. §4.5 ).

lua_len[-0, +1, e]
void lua_len (lua_State *L, int index);

Возвращает длину значения по заданному индексу. Он эквивалентен оператору ‘ # ‘ в Lua (см. §3.4.7 ) и может запускать метаметод для события «length» (см. §2.4 ). Результат помещается в стек.

lua_load[-0, +1, –]
int lua_load (lua_State *L,
              lua_Reader reader,
              void *data,
              const char *chunkname,
              const char *mode);

Загружает блок Lua, не запуская его. Если ошибок нет, lua_load помещает скомпилированный фрагмент как функцию Lua поверх стека. В противном случае выдает сообщение об ошибке.

lua_load функция использует предоставленный пользователем для reader функцию , чтобы прочитать кусок (см lua_Reader ). data аргумент непрозрачное значение , переданное в функцию устройства считывания.

Аргумент chunkname задает имя блока, которое используется для сообщений об ошибках и в отладочной информации (см. §4.7 ).

lua_load автоматически определяет, является ли фрагмент текстовым или двоичным, и загружает его соответственно (см. программу luac ). Строковый mode работает так же, как и функция load , с той лишь NULL значение NULL эквивалентно строке « bt ».

lua_load использует стек внутри, поэтому функция чтения всегда должна оставлять стек неизмененным при возврате.

lua_load может возвращать LUA_OK , LUA_ERRSYNTAX или LUA_ERRMEM . Функция также может возвращать другие значения, соответствующие ошибкам, вызванным функцией чтения (см. §4.4.1 ).

Если результирующая функция имеет повышающие значения, ее первое повышающее значение устанавливается равным значению глобальной среды, хранящемуся в индексе LUA_RIDX_GLOBALS в реестре (см. §4.3 ). При загрузке основных фрагментов этим значением upvalue будет переменная _ENV (см. §2.2 ). Другие upvalue инициализируются nil .

lua_newstate[-0, +0, –]
lua_State *lua_newstate (lua_Alloc f, void *ud);

Создает новое независимое состояние и возвращает его основной поток. Возвращает NULL , если не может создать состояние (из-за нехватки памяти). Аргумент f — это функция распределения; Lua будет выделять всю память для этого состояния через эту функцию (см. lua_Alloc ). Второй аргумент ud — это непрозрачный указатель, который Lua передает распределителю при каждом вызове.

lua_newtable[-0, +1, m]
void lua_newtable (lua_State *L);

Создает новую пустую таблицу и помещает ее в стек. Это эквивалентно lua_createtable(L, 0, 0) .

lua_newthread[-0, +1, m]
lua_State *lua_newthread (lua_State *L);

Создает новый поток, помещает его в стек и возвращает указатель на lua_State , представляющий этот новый поток. Новый поток, возвращаемый этой функцией, разделяет с исходным потоком свою глобальную среду, но имеет независимый стек выполнения.

Нити подлежат сборке мусора,как и любой объект Lua.

lua_newuserdatauv[-0, +1, m]
void *lua_newuserdatauv (lua_State *L, size_t size, int nuvalue);

Эта функция создает и помещает в стек новые полные пользовательские данные со связанными с nuvalue значениями Lua, называемыми user values , плюс связанный блок необработанной памяти с size байтах. (Пользовательские значения могут быть установлены и прочитаны с помощью функций lua_setiuservalue и lua_getiuservalue .)

Функция возвращает адрес блока памяти. Lua гарантирует, что этот адрес действителен до тех пор, пока живы соответствующие пользовательские данные (см. §2.5 ). Более того, если пользовательские данные помечены для финализации (см. §2.5.3 ), их адрес действителен, по крайней мере, до вызова его финализатора.

lua_next[-1, +(2|0), v]
int lua_next (lua_State *L, int index);

Извлекает ключ из стека и выталкивает пару ключ-значение из таблицы по заданному индексу, «следующую» пару после данного ключа. Если в таблице больше нет элементов, то lua_next возвращает 0 и ничего не подталкивает.

Типичный обход таблицы выглядит следующим образом:

lua_pushnil(L);  
while (lua_next(L, t) != 0) {
  
  printf("%s - %sn",
         lua_typename(L, lua_type(L, -2)),
         lua_typename(L, lua_type(L, -1)));
  
  lua_pop(L, 1);
}

При обходе таблицы избегайте вызова lua_tolstring непосредственно для ключа, если вы не знаете, что ключ на самом деле является строкой. Напомним, что lua_tolstring может изменять значение по данному индексу; это сбивает с толку следующий вызов lua_next .

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

lua_Number
typedef ... lua_Number;

Тип поплавков в Луа.

По умолчанию это двойной тип, но его можно изменить на одинарное с плавающей запятой или длинное двойное. (См. LUA_FLOAT_TYPE в luaconf.h .)

lua_numbertointeger
int lua_numbertointeger (lua_Number n, lua_Integer *p);

Пытается преобразовать число с плавающей запятой Lua в целое число Lua; float n должен иметь целое значение. Если это значение находится в диапазоне целых чисел Lua, оно преобразуется в целое число и присваивается *p . Результатом макроса является логическое значение, указывающее, было ли преобразование успешным. (Обратите внимание, что этот тест диапазона может быть сложно выполнить правильно без этого макроса из-за округления.)

Данный макрос может оценивать свои аргументы не один раз.

lua_pcall[-(nargs + 1), +(nresults|1), –]
int lua_pcall (lua_State *L, int nargs, int nresults, int msgh);

Вызывает функцию (или вызываемый объект)в защищенном режиме.

И nargs , и nresults имеют то же значение, что и lua_call . Если во время вызова ошибок нет, lua_pcall ведет себя точно так же, как lua_call . Однако, если есть какая-либо ошибка, lua_pcall перехватывает ее , помещает в стек единственное значение (объект ошибки) и возвращает код ошибки. Как и lua_call , lua_pcall всегда удаляет функцию и ее аргументы из стека.

Если msgh равно 0, то объект ошибки, возвращаемый в стеке, является в точности исходным объектом ошибки. В противном случае msgh — это индекс стека обработчика сообщений . (Этот индекс не может быть псевдо-индексом.) В случае ошибок времени выполнения этот обработчик будет вызываться с объектом ошибки, и его возвращаемое значение будет объектом, возвращенным в стеке lua_pcall .

Обычно обработчик сообщений используется для добавления дополнительной отладочной информации к объекту ошибки, такой как обратная трассировка стека. Такая информация не может быть собрана после возврата lua_pcall , так как к этому моменту стек разматывается.

Функция lua_pcall возвращает один из следующих кодов состояния: LUA_OK , LUA_ERRRUN , LUA_ERRMEM или LUA_ERRERR .

lua_pcallk[-(nargs + 1), +(nresults|1), –]
int lua_pcallk (lua_State *L,
                int nargs,
                int nresults,
                int msgh,
                lua_KContext ctx,
                lua_KFunction k);

Эта функция ведет себя точно так же, как lua_pcall , за исключением того, что она позволяет вызываемой функции возвращаться (см. §4.5 ).

lua_pop[-n, +0, –]
void lua_pop (lua_State *L, int n);

Извлекает n элементов из стека.

lua_pushboolean[-0, +1, –]
void lua_pushboolean (lua_State *L, int b);

Помещает логическое значение со значением b в стек.

lua_pushcclosure[-n, +1, m]
void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n);

Помещает новое замыкание C в стек. Эта функция получает указатель на функцию C и помещает в стек Lua-значение типа function , которое при вызове вызывает соответствующую функцию C. Параметр n сообщает, сколько значений up будет иметь эта функция (см. §4.2 ).

Любая функция, вызываемая Lua, должна следовать правильному протоколу, чтобы получать свои параметры и возвращать результаты (см. lua_CFunction ).

Когда C-функция создается, с ней можно связать некоторые значения, так называемые upvalues; эти повышающие значения затем доступны для функции всякий раз, когда она вызывается. Эта ассоциация называется C-замыканием (см. §4.2 ). Чтобы создать C-замыкание, сначала в стек должны быть помещены начальные значения его upvalue. (При наличии нескольких значений upvalue сначала помещается первое значение.) Затем вызывается lua_pushcclosure n , указывающим, сколько значений будет связано с функцией. lua_pushcclosure также извлекает эти значения из стека.

Максимальное значение n — 255.

Когда n равно нулю, эта функция создает легкую функцию C , которая является просто указателем на функцию C. В этом случае он никогда не вызывает ошибку памяти.

lua_pushcfunction[-0, +1, –]
void lua_pushcfunction (lua_State *L, lua_CFunction f);

Помещает функцию C в стек. Эта функция эквивалентна lua_pushcclosure без повышающих значений.

lua_pushfstring[-0, +1, v]
const char *lua_pushfstring (lua_State *L, const char *fmt, ...);

Помещает в стек отформатированную строку и возвращает указатель на эту строку (см. §4.1.3 ). Она похожа на функцию ISO C sprintf , но имеет два важных отличия. Во-первых, вам не нужно выделять место под результат; результатом является строка Lua, и Lua позаботится о выделении памяти (и освобождении памяти посредством сборки мусора). Во-вторых, спецификаторы преобразования весьма ограничены. Здесь нет флагов, ширины или точности. Спецификаторы преобразования могут быть только ‘ %% ‘ (вставляет символ ‘ % ‘), ‘ %s ‘ (вставляет заканчивающуюся нулем строку без ограничений по размеру), ‘ %f ‘ (вставляет lua_Number ), ‘ %Ilua_Integer ), ‘ %p ‘ (вставляет указатель), ‘ %d ‘ (вставляет целое int ), ‘ %c ‘ (вставляет целое int как однобайтовый символ) и ‘ %U ‘ (вставляет long int как последовательность байтов UTF-8).

Эта функция может вызвать ошибки из-за переполнения памяти или неверного спецификатора преобразования.

lua_pushglobaltable[-0, +1, –]
void lua_pushglobaltable (lua_State *L);

Выталкивает глобальную окружающую среду в стек.

lua_pushinteger[-0, +1, –]
void lua_pushinteger (lua_State *L, lua_Integer n);

Помещает целое число со значением n в стек.

lua_pushlightuserdata[-0, +1, –]
void lua_pushlightuserdata (lua_State *L, void *p);

Выталкивает легкие пользовательские данные на стек.

Пользовательские данные представляют значения C в Lua. Свет UserData представляет собой указатель, а void* . Это значение (например, число): вы не создаете его, у него нет индивидуальной метатаблицы, и он не собирается (поскольку никогда не создавался). Легкие пользовательские данные равны «любым» легким пользовательским данным с тем же адресом C.

lua_pushliteral[-0, +1, m]
const char *lua_pushliteral (lua_State *L, const char *s);

Этот макрос эквивалентен lua_pushstring , но должен использоваться только тогда, когда s — это буквальная строка. (Lua может оптимизировать этот случай.)

lua_pushlstring[-0, +1, m]
const char *lua_pushlstring (lua_State *L, const char *s, size_t len);

Помещает строку, на которую указывает s , размером len в стек. Lua создаст или повторно использует внутреннюю копию данной строки, поэтому память в s может быть освобождена или повторно использована сразу после возврата из функции. Строка может содержать любые двоичные данные, включая встроенные нули.

Возвращает указатель на внутреннюю копию строки (см. §4.1.3 ).

lua_pushnil[-0, +1, –]
void lua_pushnil (lua_State *L);

Толкает нулевое значение в стек.

lua_pushnumber[-0, +1, –]
void lua_pushnumber (lua_State *L, lua_Number n);

Помещает в стек поплавок со значением n .

lua_pushstring[-0, +1, m]
const char *lua_pushstring (lua_State *L, const char *s);

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

Возвращает указатель на внутреннюю копию строки (см. §4.1.3 ).

Если s равно NULL , помещает nil и возвращает NULL .

lua_pushthread[-0, +1, –]
int lua_pushthread (lua_State *L);

Помещает нить, обозначенную буквой L , в стек. Возвращает 1, если этот поток является основным потоком своего состояния.

lua_pushvalue[-0, +1, –]
void lua_pushvalue (lua_State *L, int index);

Выталкивает копию элемента в данном индексе на стек.

lua_pushvfstring[-0, +1, v]
const char *lua_pushvfstring (lua_State *L,
                              const char *fmt,
                              va_list argp);

Эквивалентен lua_pushfstring , за исключением того, что он получает va_list вместо переменного числа аргументов.

lua_rawequal[-0, +0, –]
int lua_rawequal (lua_State *L, int index1, int index2);

Возвращает 1 , если два значения индексов index1 и index2 примитивно равно (то есть равный без вызова __eq метаметода). В противном случае возвращает 0. Также возвращает 0, если какой-либо из индексов недействителен.

lua_rawget[-1, +1, –]
int lua_rawget (lua_State *L, int index);

Подобно lua_gettable , но имеет прямой доступ (т.е. без метаметодов).

lua_rawgeti[-0, +1, –]
int lua_rawgeti (lua_State *L, int index, lua_Integer n);

Помещает в стек значение t[n] , где t — таблица по данному индексу. Доступ является необработанным, то есть не использует __index __index.

Возвращает тип подтолкнутого значения.

lua_rawgetp[-0, +1, –]
int lua_rawgetp (lua_State *L, int index, const void *p);

Помещает в стек значение t[k] , где t — таблица с заданным индексом, а k — указатель p , представленный как легкие пользовательские данные. Доступ сырой; то есть он не использует __index __index.

Возвращает тип подтолкнутого значения.

lua_rawlen[-0, +0, –]
lua_Unsigned lua_rawlen (lua_State *L, int index);

Возвращает необработанную «длину» значения по заданному индексу: для строк это длина строки; для таблиц это результат использования оператора длины (‘ # ‘) без метаметодов; для пользовательских данных это размер блока памяти, выделенного для пользовательских данных. Для других значений этот вызов возвращает 0.

lua_rawset[-2, +0, m]
void lua_rawset (lua_State *L, int index);

Аналогично lua_settable , но выполняет необработанное присваивание (т.е. без метаметодов).

lua_rawseti[-1, +0, m]
void lua_rawseti (lua_State *L, int index, lua_Integer i);

Выполняет эквивалент t[i] = v , где t — таблица с заданным индексом, а v — значение на вершине стека.

Эта функция извлекает значение из стека. Присвоение является необработанным, то есть в нем не используется __newindex __newindex.

lua_rawsetp [-1, +0, м ]
void lua_rawsetp (lua_State *L, int index, const void *p);

Выполняет эквивалент t[p] = v , где t — это таблица с заданным индексом, p кодируется как легкие пользовательские данные, а v — значение на вершине стека.

Эта функция извлекает значение из стека. Присвоение является необработанным, то есть в нем не используется __newindex __newindex.

lua_Reader
typedef const char * (*lua_Reader) (lua_State *L,
                                    void *data,
                                    size_t *size);

Функция чтения, используемая lua_load . Каждый раз, когда lua_load требуется еще одна часть чанка, он вызывает читателя, передавая его параметр data . Считыватель должен вернуть указатель на блок памяти с новой частью фрагмента и установить size равным размеру блока. Блок должен существовать до тех пор, пока функция чтения не будет вызвана снова. Чтобы сигнализировать о конце фрагмента, считыватель должен вернуть NULL или установить size равным нулю. Функция чтения может возвращать фрагменты любого размера больше нуля.

lua_register[-0, +0, e]
void lua_register (lua_State *L, const char *name, lua_CFunction f);

Устанавливает C-функцию f как новое значение глобального name . Он определяется как макрос:

#define lua_register(L,n,f) 
       (lua_pushcfunction(L, f), lua_setglobal(L, n))
lua_remove[-1, +0, –]
void lua_remove (lua_State *L, int index);

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

lua_replace[-1, +0, –]
void lua_replace (lua_State *L, int index);

Перемещает верхний элемент в заданный действительный индекс,не смещая ни одного элемента (таким образом,заменяя значение в этом индексе),а затем всплывает верхний элемент.

lua_resetthread[-0, +?, –]
int lua_resetthread (lua_State *L);

Сбрасывает поток, очищая его стек вызовов и закрывая все ожидающие закрытия переменные. Возвращает код состояния: LUA_OK при отсутствии ошибок в методах закрытия или статус ошибки в противном случае. В случае ошибки оставляет объект ошибки наверху стека,

lua_resume[-?, +?, –]
int lua_resume (lua_State *L, lua_State *from, int nargs,
                          int *nresults);

Запуск и возобновляет сопрограмму в данной нити L .

Чтобы запустить сопрограмму, вы помещаете основную функцию и любые аргументы в пустой стек потока. затем вы вызываете lua_resume , где nargs — это количество аргументов. Этот вызов возвращается, когда сопрограмма приостанавливает или заканчивает свое выполнение. Когда он возвращается, *nresults обновляется, и вершина стека содержит значения *nresults , переданные в lua_yield или возвращенные функцией body. lua_resume возвращает LUA_YIELD , если сопрограмма уступает, LUA_OK , если сопрограмма завершает свое выполнение без ошибок, или код ошибки в случае ошибок (см. §4.4.1) .). В случае ошибок объект ошибки находится на вершине стека.

Чтобы возобновить сопрограмму, вы удаляете полученные значения *nresults из ее стека, отправляете значения, которые должны быть переданы как результаты из yield , а затем вызываете lua_resume .

Параметр from представляет собой сопрограмму , что возобновляет L . Если такой сопрограммы нет, этот параметр может иметь NULL .

lua_rotate[-0, +0, –]
void lua_rotate (lua_State *L, int idx, int n);

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

lua_setallocf[-0, +0, –]
void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);

Изменяет функцию распределения заданного состояния на f с пользовательскими данными ud .

lua_setfield[-1, +0, e]
void lua_setfield (lua_State *L, int index, const char *k);

Эквивалентно t[k] = v , где t — значение по данному индексу, а v — значение на вершине стека.

Эта функция извлекает значение из стека. Как и в Lua, эта функция может запускать метаметод для события «newwindex» (см. §2.4 ).

lua_setglobal[-1, +0, e]
void lua_setglobal (lua_State *L, const char *name);

Извлекает значение из стека и устанавливает его как новое значение глобального name .

lua_seti[-1, +0, e]
void lua_seti (lua_State *L, int index, lua_Integer n);

Эквивалентно t[n] = v , где t — значение по данному индексу, а v — значение на вершине стека.

Эта функция извлекает значение из стека. Как и в Lua, эта функция может запускать метаметод для события «newwindex» (см. §2.4 ).

lua_setiuservalue[-1, +0, –]
int lua_setiuservalue (lua_State *L, int index, int n);

Извлекает значение из стека и устанавливает его в качестве нового n -го пользовательского значения, связанного с полными пользовательскими данными по заданному индексу. Возвращает 0, если пользовательские данные не имеют этого значения.

lua_setmetatable[-1, +0, –]
int lua_setmetatable (lua_State *L, int index);

Извлекает таблицу или nil из стека и устанавливает это значение в качестве новой метатаблицы для значения по данному индексу. ( nil означает отсутствие метатаблицы.)

(По историческим причинам эта функция возвращает int , который теперь всегда равен 1.)

lua_settable[-2, +0, e]
void lua_settable (lua_State *L, int index);

Эквивалентно t[k] = v , где t — значение по данному индексу, v — значение наверху стека, а k — значение чуть ниже вершины.

Эта функция извлекает из стека и ключ, и значение. Как и в Lua, эта функция может запускать метаметод для события «newwindex» (см. §2.4 ).

lua_settop[-?, +?, –]
void lua_settop (lua_State *L, int index);

Принимает любой индекс или 0 и устанавливает вершину стека на этот индекс. Если новая вершина больше старой, то новые элементы заполняются нулем . Если index равен 0, то удаляются все элементы стека.

lua_setwarnf[-0, +0, –]
void lua_setwarnf (lua_State *L, lua_WarnFunction f, void *ud);

Устанавливает функцию предупреждения, которая будет использоваться Lua для lua_WarnFunction предупреждений (см. Lua_WarnFunction ). Параметр ud устанавливает значение ud , передаваемое функции предупреждения.

lua_State
typedef struct lua_State lua_State;

Непрозрачная структура,которая указывает на нить и косвенно (через нить)на все состояние интерпретатора Lua.Библиотека Lua полностью реентерабельная:в ней нет глобальных переменных.Вся информация о состоянии доступна через эту структуру.

Указатель на эту структуру должен быть передан в качестве первого аргумента каждой функции в библиотеке, кроме lua_newstate , которая создает состояние Lua с нуля.

lua_status[-0, +0, –]
int lua_status (lua_State *L);

Возвращает состояние нити L .

Статус может быть LUA_OK для нормального потока, кодом ошибки, если поток завершил выполнение lua_resume с ошибкой, или LUA_YIELD , если поток приостановлен.

Вы можете вызывать функции только в потоках со статусом LUA_OK . Вы можете возобновить потоки со статусом LUA_OK (для запуска новой сопрограммы) или LUA_YIELD (для возобновления сопрограммы).

lua_stringtonumber[-0, +1, –]
size_t lua_stringtonumber (lua_State *L, const char *s);

Преобразует заканчивающуюся нулем строку s в число, помещает это число в стек и возвращает общий размер строки, то есть ее длину плюс один. Преобразование может привести к целому числу или вещественному числу в соответствии с лексическими соглашениями Lua (см. §3.1 ). Строка может иметь начальные и конечные пробелы и знак. Если строка не является допустимым числом, возвращает 0 и ничего не вставляет. (Обратите внимание, что результат может быть использован как логическое значение true, если преобразование прошло успешно.)

lua_toboolean[-0, +0, –]
int lua_toboolean (lua_State *L, int index);

Преобразует значение Lua по заданному индексу в логическое значение C (0 или 1). Как и все тесты в Lua, lua_toboolean возвращает true для любого значения Lua, отличного от false и nil ; в противном случае возвращается false. (Если вы хотите принимать только фактические логические значения, используйте lua_isboolean для проверки типа значения.)

lua_tocfunction[-0, +0, –]
lua_CFunction lua_tocfunction (lua_State *L, int index);

Преобразует значение по заданному индексу в функцию C. Это значение должно быть функцией C; в противном случае возвращает NULL .

lua_toclose[-0, +0, m]
void lua_toclose (lua_State *L, int index);

Отмечает данный индекс в стеке как подлежащую закрытию «переменную» (см. §3.3.8 ). Подобно переменной, подлежащей закрытию в Lua, значение по этому индексу в стеке будет закрыто, когда оно выйдет за пределы области видимости. Здесь, в контексте функции C, выход за пределы области видимости означает, что работающая функция возвращается в Lua, возникает ошибка или индекс удаляется из стека через lua_settop или lua_pop . Индекс, помеченный как подлежащий закрытию, не должен удаляться из стека какой-либо другой функцией API, кроме lua_settop или lua_pop .

Эта функция не должна вызываться для индекса,который равен или ниже активного закрываемого индекса.

В случае ошибки вне памяти,значение в данном индексе немедленно закрывается,как если бы оно уже было отмечено.

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

lua_tointeger[-0, +0, –]
lua_Integer lua_tointeger (lua_State *L, int index);

Эквивалентно lua_tointegerx с isnum равным NULL .

lua_tointegerx[-0, +0, –]
lua_Integer lua_tointegerx (lua_State *L, int index, int *isnum);

Преобразует значение Lua по заданному индексу в целочисленный тип со знаком lua_Integer . Значение Lua должно быть целым числом, либо числом, либо строкой, преобразуемой в целое число (см. §3.4.3 ); в противном случае lua_tointegerx возвращает 0.

Если isnum не NULL , его референту присваивается логическое значение, указывающее, успешно ли выполнена операция.

lua_tolstring[-0, +0, m]
const char *lua_tolstring (lua_State *L, int index, size_t *len);

Преобразует значение Lua по заданному индексу в строку C. Если len не NULL , он устанавливает *len с длиной строки. Значение Lua должно быть строкой или числом; в противном случае функция возвращает NULL . Если значение является числом, то lua_tolstring также изменяет фактическое значение в стеке на строку . (Это изменение сбивает с толку lua_next , когда lua_tolstring применяется к ключам во время обхода таблицы.)

lua_tolstring возвращает указатель на строку внутри состояния Lua (см. §4.1.3 ). Эта строка всегда имеет ноль (‘ ‘) после последнего символа (как в C), но может содержать и другие нули в своем теле.

lua_tonumber[-0, +0, –]
lua_Number lua_tonumber (lua_State *L, int index);

Эквивалентен lua_tonumberx с isnum равным NULL .

lua_tonumberx[-0, +0, –]
lua_Number lua_tonumberx (lua_State *L, int index, int *isnum);

Преобразует значение Lua по заданному индексу в тип C lua_Number (см. lua_Number ). Значение Lua должно быть числом или строкой, преобразуемой в число (см. §3.4.3 ); в противном случае lua_tonumberx возвращает 0.

Если isnum не NULL , его референту присваивается логическое значение, указывающее, успешно ли выполнена операция.

lua_topointer[-0, +0, –]
const void *lua_topointer (lua_State *L, int index);

Преобразует значение по заданному индексу в общий указатель C ( void* ). Значение может быть пользовательскими данными, таблицей, потоком, строкой или функцией; в противном случае lua_topointer возвращает NULL . Разные объекты будут давать разные указатели. Невозможно преобразовать указатель обратно в исходное значение.

Обычно эта функция используется только для хэширования и отладки информации.

lua_tostring[-0, +0, m]
const char *lua_tostring (lua_State *L, int index);

Эквивалентен lua_tolstring с len , равным NULL .

lua_tothread[-0, +0, –]
lua_State *lua_tothread (lua_State *L, int index);

Преобразует значение по заданному индексу в поток Lua (представленный как lua_State* ). Это значение должно быть потоком; в противном случае функция возвращает NULL .

lua_touserdata[-0, +0, –]
void *lua_touserdata (lua_State *L, int index);

Если значение в данном индексе является полными пользовательскими данными, возвращает его адрес блока памяти. Если значение — легкие пользовательские данные, возвращает его значение (указатель). В противном случае возвращает NULL .

lua_type[-0, +0, –]
int lua_type (lua_State *L, int index);

Возвращает тип значения в данном допустимом индексе или LUA_TNONE для недопустимого, но приемлемого индекса. Типы, возвращаемые lua_type , кодируются следующими константами, определенными в lua.h : LUA_TNIL , LUA_TNUMBER , LUA_TBOOLEAN , LUA_TSTRING , LUA_TTABLE , LUA_TFUNCTION , LUA_TUSERDATA , LUA_TTHREAD и LUA_TLIGHTUSERDATA .

lua_typename[-0, +0, –]
const char *lua_typename (lua_State *L, int tp);

Возвращает имя типа, закодированного значением tp , которое должно быть одним из значений, возвращаемых lua_type .

lua_Unsigned
typedef ... lua_Unsigned;

Беззнаковая версия lua_Integer .

lua_upvalueindex[-0, +0, –]
int lua_upvalueindex (int i);

Возвращает псевдоиндекс, представляющий i -е значение повышения текущей функции (см. §4.2 ). i должен быть в диапазоне [1,256] .

lua_version[-0, +0, –]
lua_Number lua_version (lua_State *L);

Возвращает номер версии данного ядра.

lua_WarnFunction
typedef void (*lua_WarnFunction) (void *ud, const char *msg, int tocont);

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

См. warn для получения дополнительных сведений о предупреждениях.

lua_warning[-0, +0, –]
void lua_warning (lua_State *L, const char *msg, int tocont);

Выдает предупреждение с данным сообщением. Сообщение в вызове с tocont true должно быть продолжено в другом вызове этой функции.

См. warn для получения дополнительных сведений о предупреждениях.

lua_Writer
typedef int (*lua_Writer) (lua_State *L,
                           const void* p,
                           size_t sz,
                           void* ud);

Тип функции записи, используемой lua_dump . Каждый раз, когда lua_dump создает новый фрагмент, он вызывает модуль записи , передавая буфер для записи ( p ), его размер ( sz ) и параметр ud , передаваемый в lua_dump .

Писатель возвращает код ошибки: 0 означает отсутствие ошибок; любое другое значение означает ошибку и не позволяет lua_dump снова вызывать писателя.

lua_xmove[-?, +?, –]
void lua_xmove (lua_State *from, lua_State *to, int n);

Обмен значениями между различными потоками одного и того же состояния.

Эта функция выскакивает n значений из стека from , и помещает их в стек to .

lua_yield[-?, +?, v]
int lua_yield (lua_State *L, int nresults);

Эта функция эквивалентна lua_yieldk , но не имеет продолжения (см. §4.5 ). Поэтому, когда поток возобновляется, он продолжает функцию, вызвавшую функцию, вызвавшую lua_yield . Чтобы избежать неожиданностей, эту функцию следует вызывать только в хвостовом вызове.

lua_yieldk[-?, +?, v]
int lua_yieldk (lua_State *L,
                int nresults,
                lua_KContext ctx,
                lua_KFunction k);

Дает корутин (нить).

Когда функция C вызывает lua_yieldk , работающая сопрограмма приостанавливает свое выполнение, и возвращается вызов lua_resume , запустивший эту сопрограмму. Параметр nresults — это количество значений из стека, которые будут переданы в качестве результатов в lua_resume .

Когда сопрограмма снова возобновляется, Lua вызывает заданную функцию продолжения k , чтобы продолжить выполнение функции C, которая завершилась (см. §4.5 ). Эта функция-продолжение получает тот же стек, что и предыдущая функция, с удалением n результатов и их заменой аргументами, переданными в lua_resume . Более того, функция продолжения получает значение ctx , которое было передано в lua_yieldk .

Обычно эта функция не возвращает значения; когда сопрограмма в конечном итоге возобновляется, она продолжает выполнять функцию продолжения. Однако есть один особый случай, когда эта функция вызывается из строки или ловушки счетчика (см. §4.7 ). В этом случае lua_yieldk должен вызываться без продолжения (вероятно, в форме lua_yield ) и без результатов, а хук должен возвращаться сразу после вызова. Lua уступит, и, когда сопрограмма снова возобновится, она продолжит нормальное выполнение функции (Lua), вызвавшей хук.

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

4.7-Интерфейс отладки

Lua не имеет встроенных средств отладки. Вместо этого он предлагает специальный интерфейс с помощью функций и хуков . Этот интерфейс позволяет создавать различные виды отладчиков, профилировщиков и других инструментов, которым требуется «внутренняя информация» интерпретатора.

lua_Debug
typedef struct lua_Debug {
  int event;
  const char *name;           
  const char *namewhat;       
  const char *what;           
  const char *source;         
  size_t srclen;              
  int currentline;            
  int linedefined;            
  int lastlinedefined;        
  unsigned char nups;         
  unsigned char nparams;      
  char isvararg;              
  char istailcall;            
  unsigned short ftransfer;   
  unsigned short ntransfer;   
  char short_src[LUA_IDSIZE]; 
  
  other fields
} lua_Debug;

Структура, используемая для передачи различной информации о функции или записи активации. lua_getstack заполняет только приватную часть этой структуры для дальнейшего использования. Чтобы заполнить другие поля lua_Debug полезной информацией, вы должны вызвать lua_getinfo .

Поля lua_Debug имеют следующее значение:

  • source : источник фрагмента, создавшего функцию. Если source начинается с « @ », это означает, что функция была определена в файле, имя которого следует за « @ ». Если source начинается с ‘ = ‘, остальная часть его содержимого описывает источник в зависимости от пользователя. В противном случае функция была определена в строке, где source является эта строка.
  • srclen : длина source строки .
  • short_src : » печатная » версия source , которая будет использоваться в сообщениях об ошибках.
  • linedefined : номер строки, с которой начинается определение функции.
  • lastlinedefined : номер строки, на которой заканчивается определение функции.
  • what : строка "Lua" если функция является функцией Lua, "C" если это функция C, "main" если это основная часть чанка.
  • currentline : текущая строка, в которой выполняется данная функция. Если информация о строке недоступна, для currentline устанавливается значение -1.
  • name : разумное имя для данной функции. Поскольку функции в Lua являются первоклассными значениями, они не имеют фиксированного имени: некоторые функции могут быть значениями нескольких глобальных переменных, а другие могут храниться только в поле таблицы. Функция lua_getinfo проверяет, как функция была вызвана, чтобы найти подходящее имя. Если не может найти имя, тогда name устанавливается в NULL .
  • namewhat : объясняет поле name . Значение namewhat может быть "global" , "local" , "method" , "field" , "upvalue" или "" (пустая строка), в зависимости от того, как была вызвана функция. (Lua использует пустую строку, когда кажется, что другой вариант не подходит.)
  • istailcall : true, если этот вызов функции был вызван хвостовым вызовом. В этом случае вызывающего этого уровня нет в стеке.
  • nups : количество повышающих значений функции.
  • nparams : количество параметров функции (всегда 0 для функций C).
  • isvararg : true, если функция является функцией vararg (всегда верно для функций C).
  • ftransfer : индекс в стеке первого «переданного» значения, то есть параметров в вызове или возвращаемых значений в возврате. (Остальные значения находятся в последовательных индексах.) Используя этот индекс, вы можете получить доступ и изменить эти значения через lua_getlocal и lua_setlocal . Это поле имеет смысл только во время ловушки вызова, обозначающей первый параметр, или ловушки возврата, обозначающей первое возвращаемое значение. (Для обработчиков вызовов это значение всегда равно 1.)
  • ntransfer : количество передаваемых значений (см. предыдущий пункт). (Для вызовов функций Lua это значение всегда равно nparams .)
lua_gethook[-0, +0, –]
lua_Hook lua_gethook (lua_State *L);

Возвращает текущую функцию крючка.

lua_gethookcount[-0, +0, –]
int lua_gethookcount (lua_State *L);

Возвращает текущее количество крючков.

lua_gethookmask[-0, +0, –]
int lua_gethookmask (lua_State *L);

Возвращает текущую маску крючка.

lua_getinfo[-(0|1), +(0|1|2), m]
int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);

Получает информацию об определенной функции или вызове функции.

Чтобы получить информацию о вызове функции, параметр ar должен быть допустимой записью активации, которая была заполнена предыдущим вызовом lua_getstack или передана в качестве аргумента lua_Hook (см. Lua_Hook ).

Чтобы получить информацию о функции, вы помещаете ее в стек и начинаете строку what с символа ‘ > ‘. (В этом случае lua_getinfo выталкивает функцию из вершины стека.) Например, чтобы узнать, в какой строке была определена функция f , вы можете написать следующий код:

lua_Debug ar;
lua_getglobal(L, "f");  
lua_getinfo(L, ">S", &ar);
printf("%dn", ar.linedefined);

Каждый символ в строке , what выбирает некоторые поля структуры ar должны быть заполнены или значение , которое будет в стек:

  • n ‘: заполняет name поля и namewhat ;
  • S ‘: заполняет поля source , short_src , linedefined , lastlinedefined , и what ;
  • l ‘: заполняет поле currentline ;
  • t ‘: заполняет поле istailcall ;
  • u ‘: заполняет поля nups , nparams и isvararg ;
  • f ‘: помещает в стек функцию, которая выполняется на данном уровне;
  • L ‘: помещает в стек таблицу, индексы которой являются номерами строк, допустимых для функции. ( Допустимая строка — это строка с некоторым связанным кодом, то есть строка, в которой вы можете поставить точку останова. Недействительные строки включают пустые строки и комментарии.)

    Если этот параметр указан вместе с параметром « f », его таблица помещается после функции.

    Это единственный вариант,который может вызвать ошибку памяти.

Эта функция возвращает 0, чтобы сигнализировать о недопустимой опции в what ; даже тогда действительные параметры обрабатываются правильно.

lua_getlocal[-0, +(0|1), –]
const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n);

Получает информацию о локальной переменной или временном значении данной записи активации или данной функции.

В первом случае параметр ar должен быть допустимой записью активации, которая была заполнена предыдущим вызовом lua_getstack или передана в качестве аргумента ловушки (см. lua_Hook ). Индекс n выбирает, какую локальную переменную проверять; см. debug.getlocal для получения подробной информации об индексах и именах переменных.

lua_getlocal помещает значение переменной в стек и возвращает ее имя.

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

Возвращает NULL (и ничего не отправляет), если индекс больше, чем количество активных локальных переменных.

lua_getstack[-0, +0, –]
int lua_getstack (lua_State *L, int level, lua_Debug *ar);

Получает информацию о стеке времени выполнения интерпретатора.

Эта функция заполняет части структуры lua_Debug идентификатором записи активации функции, выполняющейся на заданном уровне. Уровень 0 — это текущая запущенная функция, тогда как уровень n + 1 — это функция, которая вызвала уровень n (за исключением хвостовых вызовов, которые не учитываются в стеке). При вызове с уровнем, превышающим глубину стека, lua_getstack возвращает 0; в противном случае возвращается 1.

lua_getupvalue[-0, +(0|1), –]
const char *lua_getupvalue (lua_State *L, int funcindex, int n);

Получает информацию о n -м повышающем значении закрытия по индексу funcindex . Он помещает значение upvalue в стек и возвращает его имя. Возвращает NULL (и ничего не выталкивает), когда индекс n больше, чем количество повышающих значений.

См. debug.getupvalue для получения дополнительной информации о повышающих значениях.

lua_Hook
typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);

Тип для отладки функций крюка.

Всякий раз, когда вызывается ловушка, ее аргумент ar имеет свое event поля, установленное на конкретное событие, которое инициировало ловушку. Lua идентифицирует эти события с помощью следующих констант: LUA_HOOKCALL , LUA_HOOKRET , LUA_HOOKTAILCALL , LUA_HOOKLINE и LUA_HOOKCOUNT . Более того, для линейных событий также устанавливается поле currentline . Чтобы получить значение любого другого поля в ar , ловушка должна вызвать lua_getinfo .

Для событий вызова event может быть LUA_HOOKCALL , нормальным значением, или LUA_HOOKTAILCALL , для хвостового вызова; в этом случае не будет соответствующего события возврата.

Пока Луа работает с крючком,он отключает другие звонки на крючки.Таким образом,если крюк вызывает Lua для выполнения функции или фрагмента,это выполнение происходит без обращения к крюкам.

Функции- lua_yieldk не могут иметь продолжения, то есть они не могут вызывать lua_yieldk , lua_pcallk или lua_callk с ненулевым k .

Функции перехвата могут давать результат при следующих условиях: Только события count и line могут давать результат; чтобы уступить, функция-перехватчик должна завершить свое выполнение, вызвав lua_yield с nresults , равными нулю (то есть без значений).

lua_setcstacklimit[-0, +0, –]
int (lua_setcstacklimit) (lua_State *L, unsigned int limit);

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

lua_sethook[-0, +0, –]
void lua_sethook (lua_State *L, lua_Hook f, int mask, int count);

Устанавливает функцию отладочного крюка.

Аргумент f — это функция перехвата. mask определяет, для каких событий будет вызвана ловушка: она формируется побитовым ИЛИ констант LUA_MASKCALL , LUA_MASKRET , LUA_MASKLINE и LUA_MASKCOUNT . count аргументов имеет смысл только , когда маска включает в себя LUA_MASKCOUNT . Для каждого события хук вызывается, как описано ниже:

  • Ловушка вызова: вызывается, когда интерпретатор вызывает функцию. Хук вызывается сразу после того, как Lua входит в новую функцию.
  • Ловушка возврата: вызывается, когда интерпретатор возвращается из функции. Хук вызывается непосредственно перед выходом Lua из функции.
  • Перехватчик строки: вызывается, когда интерпретатор собирается начать выполнение новой строки кода или когда он возвращается в код (даже на ту же строку). Это событие происходит только тогда, когда Lua выполняет функцию Lua.
  • Ловушка счетчика: вызывается после того, как интерпретатор выполняет все инструкции count . Это событие происходит только тогда, когда Lua выполняет функцию Lua.

Хуки отключаются установкой mask на ноль.

lua_setlocal[-(0|1), +0, –]
const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n);

Устанавливает значение локальной переменной данной записи активации.Она присваивает переменной значение на вершине стека и возвращает ее имя.Она также извлекает значение из стека.

Возвращает NULL (и ничего не выдает), если индекс больше, чем количество активных локальных переменных.

Параметры ar и n такие же, как в функции lua_getlocal .

lua_setupvalue[-(0|1), +0, –]
const char *lua_setupvalue (lua_State *L, int funcindex, int n);

Устанавливает значение верхнего значения закрытия.Он присваивает значение на вершине стека значению upvalue и возвращает его имя.Она также извлекает значение из стека.

Возвращает NULL (и ничего не выдает ), если индекс n больше, чем количество повышающих значений.

Параметры funcindex и n такие же, как в функции lua_getupvalue .

lua_upvalueid[-0, +0, –]
void *lua_upvalueid (lua_State *L, int funcindex, int n);

Возвращает уникальный идентификатор для повышенного значения с номером n из закрытия по индексу funcindex .

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

Параметры funcindex и n такие же, как в функции lua_getupvalue , но n не может быть больше, чем количество повышающих значений.

lua_upvaluejoin[-0, +0, –]
void lua_upvaluejoin (lua_State *L, int funcindex1, int n1,
                                    int funcindex2, int n2);

Сделайте n1 -е восходящее значение закрытия Lua по индексу funcindex1 ссылкой на n2 -е восходящее значение закрытия Lua по индексу funcindex2 .

5-Вспомогательная библиотека

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

Все функции и типы из вспомогательной библиотеки определены в заголовочном файле lauxlib.h и имеют префикс luaL_ .

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

Некоторые функции вспомогательной библиотеки используют внутренние слоты стека.Когда функция во вспомогательной библиотеке использует менее пяти слотов,она не проверяет размер стека;она просто предполагает,что слотов достаточно.

Несколько функций из вспомогательной библиотеки используются для проверки аргументов функции C. Поскольку сообщение об ошибке отформатировано для аргументов (например, « bad argument #1 »), вы не должны использовать эти функции для других значений стека.

Функции luaL_check* всегда вызывают ошибку, если проверка не выполняется.

5.1-Функции и типы

Здесь в алфавитном порядке перечислены все функции и типы из вспомогательной библиотеки.

luaL_addchar[-?, +?, m]
void luaL_addchar (luaL_Buffer *B, char c);

Добавляет байт c в буфер B (см. luaL_Buffer ).

luaL_addgsub[-0, +0, m]
const void luaL_addgsub (luaL_Buffer *B, const char *s,
                         const char *p, const char *r);

Добавляет копию строки s в буфер B (см. luaL_Buffer ), заменяя любое вхождение строки p строкой r .

luaL_addlstring[-?, +?, m]
void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l);

Добавляет строку, luaL_Buffer s , длиной l в буфер B (см. LuaL_Buffer ). Строка может содержать встроенные нули.

luaL_addsize[-?, +?, –]
void luaL_addsize (luaL_Buffer *B, size_t n);

Добавляет в буфер B строку длины n , ранее скопированную в буферную область (см. luaL_prepbuffer ).

luaL_addstring[-?, +?, m]
void luaL_addstring (luaL_Buffer *B, const char *s);

Добавляет строку с завершающим нулем, на которую указывает s , в буфер B (см. luaL_Buffer ).

luaL_addvalue[-1, +?, m]
void luaL_addvalue (luaL_Buffer *B);

Добавляет значение наверху стека в буфер B (см. luaL_Buffer ). Выдвигает значение.

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

luaL_argcheck[-0, +0, v]
void luaL_argcheck (lua_State *L,
                    int cond,
                    int arg,
                    const char *extramsg);

Проверяет, истинно ли cond . Если это не так, luaL_argerror ошибку стандартным сообщением (см. LuaL_argerror ).

luaL_argerror[-0, +0, v]
int luaL_argerror (lua_State *L, int arg, const char *extramsg);

Вызывает ошибку, сообщающую о проблеме с аргументом arg extramsg его функции C, используя стандартное сообщение, которое включает extramsg в качестве комментария:

bad argument #arg to 'funcname' (extramsg)

Эта функция никогда не возвращается.

luaL_argexpected[-0, +0, v]
void luaL_argexpected (lua_State *L,
                       int cond,
                       int arg,
                       const char *tname);

Проверяет, истинно ли cond . Если это не так, выдает ошибку о типе аргумента arg со стандартным сообщением (см. luaL_typeerror ).

luaL_Buffer
typedef struct luaL_Buffer luaL_Buffer;

Тип строкового буфера .

Строковый буфер позволяет C-коду строить строки Lua по частям.Схема его использования выглядит следующим образом:

  • Сначала объявите переменную b типа luaL_Buffer .
  • Затем инициализируйте его вызовом luaL_buffinit(L, &b) .
  • Затем добавьте в буфер кусочки строки, вызывая любую из функций luaL_add* .
  • Завершите, вызвав luaL_pushresult(&b) . Этот вызов оставляет последнюю строку наверху стека.

Если вы заранее знаете максимальный размер результирующей строки,вы можете использовать буфер следующим образом:

  • Сначала объявите переменную b типа luaL_Buffer .
  • Затем инициализируйте его и предварительно выделите пространство размером sz с помощью вызова luaL_buffinitsize(L, &b, sz) .
  • Затем вставьте струну в это пространство.
  • Завершите вызовом luaL_pushresultsize(&b, sz) , где sz — это общий размер результирующей строки, скопированной в это пространство (которая может быть меньше или равна предварительно выделенному размеру).

Во время нормальной работы строковый буфер использует переменное количество слотов стека. Таким образом, при использовании буфера вы не можете предполагать, что знаете, где находится вершина стека. Вы можете использовать стек между последовательными вызовами буферных операций, если это использование сбалансировано; то есть, когда вы вызываете операцию с буфером, стек находится на том же уровне, что и сразу после предыдущей операции с буфером. (Единственное исключение из этого правила — luaL_addvalue .) После вызова luaL_pushresult стек возвращается на тот уровень, на котором был инициализирован буфер, плюс последняя строка на его вершине.

luaL_buffaddr[-0, +0, –]
char *luaL_buffaddr (luaL_Buffer *B);

Возвращает адрес текущего содержимого буфера B (см. luaL_Buffer ). Обратите внимание, что любое добавление к буферу может сделать этот адрес недействительным.

luaL_buffinit[-0, +0, –]
void luaL_buffinit (lua_State *L, luaL_Buffer *B);

Инициализирует буфер B (см. luaL_Buffer ). Эта функция не выделяет места; буфер должен быть объявлен как переменная.

luaL_bufflen[-0, +0, –]
size_t luaL_bufflen (luaL_Buffer *B);

Возвращает длину текущего содержимого буфера B (см. luaL_Buffer ).

luaL_buffinitsize[-?, +?, m]
char *luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz);

Эквивалент последовательности luaL_buffinit , luaL_prepbuffsize .

luaL_buffsub[-0, +0, –]
void luaL_buffsub (luaL_Buffer *B, int n);

Удаляет n байтов из буфера B (см. luaL_Buffer ). В буфере должно быть не менее этого количества байтов.

luaL_callmeta[-0, +(0|1), e]
int luaL_callmeta (lua_State *L, int obj, const char *e);

Это называется метаметод.

Если объект с индексом obj имеет метатаблицу, а эта метатаблица имеет поле e , эта функция вызывает это поле, передавая объект в качестве единственного аргумента. В этом случае эта функция возвращает истину и помещает в стек значение, возвращаемое вызовом. Если нет метатаблицы или метаметода, эта функция возвращает false, не помещая какое-либо значение в стек.

luaL_checkany[-0, +0, v]
void luaL_checkany (lua_State *L, int arg);

Проверяет, имеет ли функция аргумент любого типа (включая nil ) в позиции arg .

luaL_checkinteger[-0, +0, v]
lua_Integer luaL_checkinteger (lua_State *L, int arg);

Проверяет, является ли аргумент функции arg целым числом (или может быть преобразовано в целое число) и возвращает это целое число.

luaL_checklstring[-0, +0, v]
const char *luaL_checklstring (lua_State *L, int arg, size_t *l);

Проверяет, является ли аргумент функции arg строкой и возвращает эту строку; если l не NULL заполняет референт длиной строки.

Эта функция использует lua_tolstring для получения результата, поэтому здесь применяются все преобразования и предупреждения этой функции.

luaL_checknumber[-0, +0, v]
lua_Number luaL_checknumber (lua_State *L, int arg);

Проверяет, является ли аргумент функции arg числом, и возвращает это число, преобразованное в lua_Number .

luaL_checkoption[-0, +0, v]
int luaL_checkoption (lua_State *L,
                      int arg,
                      const char *def,
                      const char *const lst[]);

Проверяет, является ли аргумент функции arg строкой, и ищет эту строку в массиве lst (который должен оканчиваться NULL). Возвращает индекс в массиве, в котором была найдена строка. Вызывает ошибку, если аргумент не является строкой или если строка не может быть найдена.

Если def не равен NULL , функция использует def как значение по умолчанию, когда нет аргумента arg или когда этот аргумент равен nil .

Это полезная функция для сопоставления строк с C перечислениями.(Обычное соглашение в библиотеках Lua-использовать строки вместо чисел для выбора опций).

luaL_checkstack[-0, +0, v]
void luaL_checkstack (lua_State *L, int sz, const char *msg);

Увеличивает размер стека до элементов top + sz , вызывая ошибку, если стек не может вырасти до этого размера. msg — это дополнительный текст для сообщения об ошибке (или NULL ,если дополнительный текст не используется).

luaL_checkstring[-0, +0, v]
const char *luaL_checkstring (lua_State *L, int arg);

Проверяет, является ли аргумент функции arg строкой и возвращает эту строку.

Эта функция использует lua_tolstring для получения результата, поэтому здесь применяются все преобразования и предупреждения этой функции.

luaL_checktype[-0, +0, v]
void luaL_checktype (lua_State *L, int arg, int t);

Проверяет, имеет ли аргумент функции arg тип t . См. lua_type для кодировки типов для t .

luaL_checkudata[-0, +0, v]
void *luaL_checkudata (lua_State *L, int arg, const char *tname);

Проверяет, является ли аргумент функции arg пользовательскими данными типа tname (см. luaL_newmetatable ) и возвращает адрес блока памяти пользовательских данных (см. lua_touserdata ).

luaL_checkversion[-0, +0, v]
void luaL_checkversion (lua_State *L);

Проверяет,используют ли код,выполняющий вызов,и вызываемая библиотека Lua одну и ту же версию Lua и одни и те же числовые типы.

luaL_dofile[-0, +?, m]
int luaL_dofile (lua_State *L, const char *filename);

Загружает и запускает данный файл.Он определяется как следующий макрос:

(luaL_loadfile(L, filename) || lua_pcall(L, 0, LUA_MULTRET, 0))

Он возвращает LUA_OK , если ошибок нет, или код ошибки в случае ошибок (см. §4.4.1 ).

luaL_dostring[-0, +?, –]
int luaL_dostring (lua_State *L, const char *str);

Загружает и запускает данную строку.Определяется как следующий макрос:

(luaL_loadstring(L, str) || lua_pcall(L, 0, LUA_MULTRET, 0))

Он возвращает LUA_OK , если ошибок нет, или код ошибки в случае ошибок (см. §4.4.1 ).

luaL_error[-0, +0, v]
int luaL_error (lua_State *L, const char *fmt, ...);

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

Эта функция никогда не возвращается, но использовать ее в функциях C как return luaL_error(args) — это идиома .

luaL_execresult [-0, +3, м ]
int luaL_execresult (lua_State *L, int stat);

Эта функция производит возвращаемые значения для связанных с процессами функций в стандартной библиотеке ( os.execute и io.close ).

luaL_fileresult[-0, +(1|3), m]
int luaL_fileresult (lua_State *L, int stat, const char *fname);

Эта функция производит возвращаемые значения для файловых функций в стандартной библиотеке ( io.open , os.rename , file:seek и т. Д.).

luaL_getmetafield [-0, + (0 | 1), м ]
int luaL_getmetafield (lua_State *L, int obj, const char *e);

Помещает в стек поле e из метатаблицы объекта по индексу obj и возвращает тип помещенного значения. Если у объекта нет метатаблицы или если метатаблица не имеет этого поля, ничего не LUA_TNIL и возвращает LUA_TNIL .

luaL_getmetatable[-0, +1, m]
int luaL_getmetatable (lua_State *L, const char *tname);

Помещает в стек метатаблицу, связанную с именем tname в реестре (см. luaL_newmetatable ), или nil, если с этим именем не связана метатаблица. Возвращает тип переданного значения.

luaL_getsubtable[-0, +1, e]
int luaL_getsubtable (lua_State *L, int idx, const char *fname);

Гарантирует, что значение t[fname] , где t — значение индекса idx , является таблицей, и помещает эту таблицу в стек. Возвращает истину, если находит там предыдущую таблицу, и ложь, если создает новую таблицу.

luaL_gsub[-0, +1, m]
const char *luaL_gsub (lua_State *L,
                       const char *s,
                       const char *p,
                       const char *r);

Создает копию строки s , заменяя любое вхождение строки p строкой r . Помещает получившуюся строку в стек и возвращает ее.

luaL_len[-0, +0, e]
lua_Integer luaL_len (lua_State *L, int index);

Возвращает «длину» значения по заданному индексу в виде числа; он эквивалентен оператору ‘ # ‘ в Lua (см. §3.4.7 ). Выдает ошибку, если результат операции не является целым числом. (Этот случай может произойти только с помощью метаметодов.)

luaL_loadbuffer[-0, +1, –]
int luaL_loadbuffer (lua_State *L,
                     const char *buff,
                     size_t sz,
                     const char *name);

Эквивалентен luaL_loadbufferx с mode равным NULL .

luaL_loadbufferx[-0, +1, –]
int luaL_loadbufferx (lua_State *L,
                      const char *buff,
                      size_t sz,
                      const char *name,
                      const char *mode);

Загружает буфер как блок Lua. Эта функция использует lua_load для загрузки фрагмента в буфер, на который указывает buff , размером sz .

Эта функция возвращает те же результаты, что и lua_load . name — это имя блока, используемое для отладочной информации и сообщений об ошибках. Строковый mode работает как в функции lua_load .

luaL_loadfile[-0, +1, m]
int luaL_loadfile (lua_State *L, const char *filename);

Эквивалентен luaL_loadfilex с mode равным NULL .

luaL_loadfilex[-0, +1, m]
int luaL_loadfilex (lua_State *L, const char *filename,
                                            const char *mode);

Загружает файл в виде блока Lua. Эта функция использует lua_load для загрузки фрагмента в файл с именем filename . Если filename имеет NULL , он загружается из стандартного ввода. Первая строка в файле игнорируется, если она начинается с символа # .

Строковый mode работает как в функции lua_load .

Эта функция возвращает те же результаты, что и lua_load или LUA_ERRFILE для ошибок, связанных с файлами.

Как и lua_load , эта функция загружает только чанк; он его не запускает.

luaL_loadstring[-0, +1, –]
int luaL_loadstring (lua_State *L, const char *s);

Загружает строку как фрагмент Lua. Эта функция использует lua_load для загрузки фрагмента в строке s с нулевым символом в конце .

Эта функция возвращает те же результаты, что и lua_load .

Также как lua_load , эта функция загружает только фрагмент; он его не запускает.

luaL_newlib[-0, +1, m]
void luaL_newlib (lua_State *L, const luaL_Reg l[]);

Создает новую таблицу и регистрирует в ней функции из списка l .

Он реализован в виде следующего макроса:

(luaL_newlibtable(L,l), luaL_setfuncs(L,l,0))

Массив l должен быть фактическим массивом, а не указателем на него.

luaL_newlibtable[-0, +1, m]
void luaL_newlibtable (lua_State *L, const luaL_Reg l[]);

Создает новую таблицу с размером, оптимизированным для хранения всех записей в массиве l (но фактически не сохраняет их). Он предназначен для использования вместе с luaL_setfuncs (см. luaL_newlib ).

Он реализован как макрос. Массив l должен быть фактическим массивом, а не указателем на него.

luaL_newmetatable[-0, +1, m]
int luaL_newmetatable (lua_State *L, const char *tname);

Если в реестре уже есть ключ tname , возвращает 0. В противном случае создает новую таблицу, которая будет использоваться в качестве метатаблицы для пользовательских данных, добавляет в эту новую таблицу пару __name = tname , добавляет в реестр пару [tname] = new table и возвращает 1.

В обоих случаях функция помещает в стек последнее значение, связанное с tname в реестре.

luaL_newstate[-0, +0, –]
lua_State *luaL_newstate (void);

Создает новое состояние Lua. Он вызывает lua_newstate с распределителем, основанным на стандартных функциях распределения C, а затем устанавливает функцию предупреждения и функцию паники (см. §4.4 ), которые выводят сообщения в стандартный вывод ошибок.

Возвращает новое состояние или NULL , если есть ошибка выделения памяти.

luaL_openlibs[-0, +0, e]
void luaL_openlibs (lua_State *L);

Открывает все стандартные библиотеки Lua в данном состоянии.

luaL_opt[-0, +0, –]
T luaL_opt (L, func, arg, dflt);

Этот макрос определяется следующим образом:

(lua_isnoneornil(L,(arg)) ? (dflt) : func(L,(arg)))

На словах, если аргумент arg равен нулю или отсутствует, макрос dflt значение по умолчанию dflt . В противном случае это приводит к результату вызова func с состоянием L и индексом аргумента arg в качестве аргументов. Обратите внимание, что он оценивает выражение dflt только в случае необходимости.

luaL_optinteger[-0, +0, v]
lua_Integer luaL_optinteger (lua_State *L,
                             int arg,
                             lua_Integer d);

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

luaL_optlstring[-0, +0, v]
const char *luaL_optlstring (lua_State *L,
                             int arg,
                             const char *d,
                             size_t *l);

Если аргумент функции arg является строкой, возвращает эту строку. Если этот аргумент отсутствует или равен нулю , возвращает d . В противном случае выдает ошибку.

Если l не NULL , заполняет референт длиной результата. Если результатом является NULL (возможно только при возврате d и d == NULL ), его длина считается нулевой.

Эта функция использует lua_tolstring для получения результата, поэтому здесь применяются все преобразования и предупреждения этой функции.

luaL_optnumber[-0, +0, v]
lua_Number luaL_optnumber (lua_State *L, int arg, lua_Number d);

Если аргумент функции arg является числом, возвращает это число как lua_Number . Если этот аргумент отсутствует или равен нулю , возвращает d . В противном случае выдает ошибку.

luaL_optstring[-0, +0, v]
const char *luaL_optstring (lua_State *L,
                            int arg,
                            const char *d);

Если аргумент функции arg является строкой, возвращает эту строку. Если этот аргумент отсутствует или равен нулю , возвращает d . В противном случае выдает ошибку.

luaL_prepbuffer[-?, +?, m]
char *luaL_prepbuffer (luaL_Buffer *B);

Эквивалентно luaL_prepbuffsize с предопределенным размером LUAL_BUFFERSIZE .

luaL_prepbuffsize[-?, +?, m]
char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz);

Возвращает адрес в пространство размером sz , где вы можете скопировать строку для добавления в буфер B (см. luaL_Buffer ). После копирования строки в это пространство вы должны вызвать luaL_addsize с размером строки, чтобы фактически добавить ее в буфер.

luaL_pushfail[-0, +1, –]
void luaL_pushfail (lua_State *L);

Помещает значение ошибки в стек (см. §6 ).

luaL_pushresult[-?, +1, m]
void luaL_pushresult (luaL_Buffer *B);

Завершает использование буфера B , оставляя последнюю строку наверху стека.

luaL_pushresultsize[-?, +1, m]
void luaL_pushresultsize (luaL_Buffer *B, size_t sz);

Эквивалентно последовательности luaL_addsize , luaL_pushresult .

luaL_ref[-1, +0, m]
int luaL_ref (lua_State *L, int t);

Создает и возвращает ссылку в таблице с индексом t для объекта на вершине стека (и выталкивает объект).

Ссылка — это уникальный целочисленный ключ. Пока вы не добавляете вручную целочисленные ключи в таблицу t , luaL_ref гарантирует уникальность возвращаемого ключа. Вы можете получить объект, на который ссылается ссылка r , вызвав lua_rawgeti(L, t, r) . Функция luaL_unref освобождает ссылку.

Если объект на вершине стека равен нулю , luaL_ref возвращает константу LUA_REFNIL . Константа LUA_NOREF гарантированно отличается от любой ссылки, возвращаемой luaL_ref .

luaL_Reg
typedef struct luaL_Reg {
  const char *name;
  lua_CFunction func;
} luaL_Reg;

Тип для массивов функций, которые будут зарегистрированы luaL_setfuncs . name — это имя функции, а func — указатель на функцию. Любой массив luaL_Reg должен заканчиваться контрольной записью, в которой и name , и func равны NULL .

luaL_requiref[-0, +1, e]
void luaL_requiref (lua_State *L, const char *modname,
                    lua_CFunction openf, int glb);

Если package.loaded[modname] не истинно, вызывает функцию openf со строкой modname в качестве аргумента и устанавливает результат вызова в package.loaded[modname] , как если бы эта функция была вызвана через require .

Если glb истинно, модуль также сохраняется в глобальном имени modname .

Оставляет копию модуля на стеке.

luaL_setfuncs[-nup, +0, m]
void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup);

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

Когда nup не равен нулю, то все функции созданы с nup upvalues, инициализируются с копиями nup значений ранее в стек поверх библиотеки таблицы. Эти значения извлекаются из стека после регистрации.

luaL_setmetatable[-0, +0, –]
void luaL_setmetatable (lua_State *L, const char *tname);

Устанавливает метатаблицу объекта на вершине стека как метатаблицу, связанную с именем tname в реестре (см. luaL_newmetatable ).

luaL_Stream
typedef struct luaL_Stream {
  FILE *f;
  lua_CFunction closef;
} luaL_Stream;

Стандартное представление для файловых дескрипторов,используемое стандартной библиотекой ввода-вывода.

LUA_FILEHANDLE файла реализован как полные пользовательские данные с метатаблицей под названием LUA_FILEHANDLE (где LUA_FILEHANDLE — это макрос с фактическим именем метатаблицы). Метатаблица создается библиотекой ввода-вывода (см. luaL_newmetatable ).

Эти пользовательские данные должны начинаться со структуры luaL_Stream ; он может содержать другие данные после этой начальной структуры. Поле f указывает на соответствующий поток C (или оно может иметь NULL чтобы указать не полностью созданный дескриптор). Поле closef указывает на функцию Lua, которая будет вызываться для закрытия потока при закрытии или сборе дескриптора; эта функция получает дескриптор файла в качестве единственного аргумента и должна возвращать либо истинное значение в случае успеха, либо ложное значение плюс сообщение об ошибке в случае ошибки. Как только Lua вызывает это поле, он изменяет значение поля на NULL , чтобы сигнализировать, что дескриптор закрыт.

luaL_testudata[-0, +0, m]
void *luaL_testudata (lua_State *L, int arg, const char *tname);

Эта функция работает так luaL_checkudata , как luaL_checkudata , за исключением того, что в случае сбоя теста она возвращает NULL вместо того, чтобы вызывать ошибку.

luaL_tolstring[-0, +1, e]
const char *luaL_tolstring (lua_State *L, int idx, size_t *len);

Преобразует любое значение Lua по заданному индексу в строку C в приемлемом формате. Результирующая строка помещается в стек и также возвращается функцией (см. §4.1.3 ). Если len не равно NULL , функция также устанавливает *len с длиной строки.

Если значение имеет метатаблицу с полем __tostring , то luaL_tolstring вызывает соответствующий метаметод со значением в качестве аргумента и использует результат вызова в качестве своего результата.

luaL_traceback[-0, +1, m]
void luaL_traceback (lua_State *L, lua_State *L1, const char *msg,
                     int level);

Создает и отправляет обратную трассировку стека L1 . Если msg не NULL , оно добавляется в начале трассировки. Параметр level сообщает, с какого уровня начать трассировку.

luaL_typeerror[-0, +0, v]
const char *luaL_typeerror (lua_State *L,
                                      int arg,
                                      const char *tname);

Вызывает ошибку типа для аргумента arg вызывающей его функции C, используя стандартное сообщение; tname — это «имя» ожидаемого типа. Эта функция никогда не возвращается.

luaL_typename[-0, +0, –]
const char *luaL_typename (lua_State *L, int index);

Возвращает имя типа значения в данном индексе.

luaL_unref[-0, +0, –]
void luaL_unref (lua_State *L, int t, int ref);

Освобождает ссылку ref из таблицы по индексу t (см. luaL_ref ). Запись удаляется из таблицы, чтобы можно было собрать упомянутый объект. Ссылка ref также может быть использована снова.

Если refLUA_NOREF или LUA_REFNIL , luaL_unref ничего не делает.

luaL_where[-0, +1, m]
void luaL_where (lua_State *L, int lvl);

Помещает в стек строку, определяющую текущую позицию элемента управления на уровне lvl в стеке вызовов. Обычно эта строка имеет следующий формат:

chunkname:currentline:

Уровень 0-выполняющаяся функция,уровень 1-функция,вызывающая выполняющуюся функцию,и т.д.

Эта функция используется для построения префикса для сообщений об ошибках.

6-Стандартные библиотеки

Стандартные библиотеки Lua предоставляют полезные функции, которые реализованы на C через C API. Некоторые из этих функций предоставляют языку важные сервисы (например, type и getmetatable ); другие предоставляют доступ к внешним сервисам (например, ввод-вывод); и другие могут быть реализованы в самом Lua, но по разным причинам заслуживают реализации на C (например, table.sort ).

Все библиотеки реализованы через официальный API C и предоставляются как отдельные модули C. Если не указано иное, эти библиотечные функции не регулируют количество аргументов в соответствии с ожидаемыми параметрами. Например, функция, задокументированная как foo(arg) не должна вызываться без аргумента.

Обозначение fail означает ложное значение, представляющее какой-то сбой. (В настоящее время fail равно nil , но это может измениться в будущих версиях. Рекомендуется всегда проверять успешность этих функций с помощью (not status) вместо (status == nil) .)

В настоящее время Lua имеет следующие стандартные библиотеки:

  • базовая библиотека ( §6.1 );
  • библиотека сопрограмм ( §6.2 );
  • библиотека пакетов ( §6.3 );
  • манипуляции со строками ( §6.4 );
  • базовая поддержка UTF-8 ( §6.5 );
  • манипуляции с таблицами ( §6.6 );
  • математические функции ( §6.7 ) (sin, log и т. д.);
  • ввод и вывод ( §6.8 );
  • средства операционной системы ( §6.9 );
  • средства отладки ( §6.10 ).

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

Чтобы получить доступ к этим библиотекам, хост-программа C должна вызвать функцию luaL_openlibs , которая открывает все стандартные библиотеки. В качестве альтернативы хост-программа может открывать их по отдельности, используя luaL_requiref для вызова luaopen_base (для базовой библиотеки), luaopen_package (для библиотеки пакетов), luaopen_coroutine (для библиотеки сопрограмм), luaopen_string (для строковой библиотеки), luaopen_utf8 (для Библиотека UTF-8), luaopen_table (для библиотеки таблиц), luaopen_math (для математической библиотеки), luaopen_io (для библиотеки ввода-вывода), luaopen_os (для библиотеки операционной системы) и luaopen_debug (для библиотеки отладки). Эти функции объявлены в lualib.h .

6.1-Основные функции

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

assert (v [, message])

Вызывает ошибку, если значение его аргумента v ложно (т. Е. Nil или false ); в противном случае возвращает все свои аргументы. В случае ошибки message является объектом ошибки; когда отсутствует, по умолчанию используется » assertion failed! «

collectgarbage ([opt [, arg]])

Эта функция является общим интерфейсом сборщика мусора. Он выполняет разные функции в зависимости от своего первого аргумента opt :

  • » collect «: выполняет полный цикл сборки мусора. Это вариант по умолчанию.
  • « stop »: останавливает автоматическое выполнение сборщика мусора. Сборщик будет работать только при явном вызове до тех пор, пока не будет вызван его перезапуск.
  • « restart »: перезапускает автоматическое выполнение сборщика мусора.
  • « count »: возвращает общий объем памяти, используемый Lua в килобайтах. Значение имеет дробную часть, поэтому умножение на 1024 дает точное количество байтов, используемых Lua.
  • » step «: Выполняет сборку мусора. «Размер» шага контролируется arg . При нулевом значении коллектор выполнит один базовый (неделимый) шаг. Для ненулевых значений сборщик будет работать так, как если бы этот объем памяти (в килобайтах) был выделен Lua. Возвращает истину, если шаг завершил цикл сбора.
  • » isrunning «: возвращает логическое значение, которое сообщает, работает ли сборщик (т. е. не остановлен).
  • « incremental »: измените режим коллектора на инкрементный. За этой опцией могут следовать три числа: пауза сборщика мусора, множитель шага и размер шага (см. §2.5.1 ). Ноль означает не изменять это значение.
  • « generational »: Измените режим коллектора на «Generation». За этой опцией могут следовать два числа: второстепенный множитель сборщика мусора и старший множитель (см. §2.5.2 ). Ноль означает не изменять это значение.

См. §2.5 для более подробной информации о сборке мусора и некоторых из этих опций.

dofile ([filename])

Открывает названный файл и выполняет его содержимое как блок Lua. При вызове без аргументов dofile выполняет содержимое стандартного ввода ( stdin ). Возвращает все значения, возвращаемые чанком. В случае ошибок dofile передает ошибку вызывающей стороне . (То есть dofile не работает в защищенном режиме.)

error (message [, level])

Вызывает ошибку (см. §2.3 ) с @{message} в качестве объекта ошибки. Эта функция никогда не возвращается.

Обычно error добавляет некоторую информацию о позиции ошибки в начале сообщения, если сообщение является строкой. В level аргумент определяет , как получить позицию ошибки. При уровне 1 (по умолчанию) позиция ошибки — это место, где была вызвана функция error . Уровень 2 указывает на ошибку, где была вызвана функция, вызвавшая error ; и так далее. Передача уровня 0 позволяет избежать добавления в сообщение информации о местоположении ошибки.

_G

Глобальная переменная (не функция), содержащая глобальную среду (см. §2.2 ). Сам Lua не использует эту переменную; изменение его значения не влияет ни на какую среду, ни наоборот.

getmetatable (object)

Если object не имеет метатаблицы, возвращает ноль . В противном случае, если метатаблица объекта имеет поле __metatable , возвращает связанное значение. В противном случае возвращает метатаблицу данного объекта.

ipairs (t)

Возвращает три значения (функция итератора, таблица t и 0), так что конструкция

for i,v in ipairs(t) do body end

будет перебирать пары ключ-значение ( 1,t[1] ), ( 2,t[2] ), …, до первого отсутствующего индекса.

load (chunk [, chunkname [, mode [, env]]])

Загружает кусок.

Если chunk — это строка, фрагмент — это эта строка. Если chunk — это функция, load вызывает ее несколько раз, чтобы получить фрагменты фрагмента. Каждый вызов chunk должен возвращать строку, которая объединяется с предыдущими результатами. Возврат пустой строки, nil или отсутствия значения сигнализирует об окончании фрагмента.

Если синтаксических ошибок нет, load возвращает скомпилированный фрагмент как функцию; в противном случае возвращается ошибка плюс сообщение об ошибке.

Когда вы загружаете основной фрагмент, результирующая функция всегда будет иметь только одно значение upvalue, переменную _ENV (см. §2.2 ). Однако, когда вы загружаете двоичный фрагмент, созданный из функции (см. string.dump ), результирующая функция может иметь произвольное количество значений повышения, и нет гарантии, что ее первым значением повышения будет переменная _ENV . (Неосновная функция может даже не иметь повышающего значения _ENV .)

Независимо от того, имеет ли результирующая функция какие-либо повышающие значения, ее первое повышающее значение устанавливается равным значению env , если этот параметр задан, или значению глобальной среды. Остальные повышающие значения инициализируются нулем . Все upvalues ​​свежие, то есть они не используются ни одной другой функцией.

chunkname используется как имя блока для сообщений об ошибках и отладочной информации (см. §4.7 ). Когда он отсутствует, по умолчанию используется chunk , если chunk является строкой, или » =(load) » в противном случае.

Строковый mode определяет, может ли фрагмент быть текстовым или двоичным (то есть предварительно скомпилированным фрагментом). Это может быть строка « b » (только двоичные фрагменты), « t » (только текстовые фрагменты) или « bt » (двоичные и текстовые). По умолчанию — « bt ».

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

loadfile ([filename [, mode [, env]]])

Аналогично load , но получает фрагмент из filename файла файла или из стандартного ввода, если имя файла не указано.

next (table [, index])

Позволяет программе перемещаться по всем полям таблицы. Его первый аргумент — это таблица, а второй аргумент — это индекс в этой таблице. Вызов next возвращает следующий индекс таблицы и связанное с ним значение. При вызове со вторым аргументом nil , next возвращает начальный индекс и связанное с ним значение. При вызове с последним индексом или с nil в пустой таблице next возвращает nil . Если второй аргумент отсутствует, он интерпретируется как ноль . В частности, вы можете использовать next(t) чтобы проверить, пуста ли таблица.

Порядок нумерации индексов не указан даже для числовых индексов . (Чтобы перемещаться по таблице в числовом порядке, используйте числовой for .)

Поведение next не определено, если во время обхода вы присваиваете какое-либо значение несуществующему полю в таблице. Однако вы можете изменить существующие поля. В частности, вы можете установить для существующих полей значение nil.

pairs (t)

Если t имеет __pairs , вызывает его с аргументом t и возвращает первые три результата вызова.

В противном случае возвращает три значения: next функция, таблица t и nil , так что конструкция

for k,v in pairs(t) do body end

будет перебирать все пары ключ-значение таблицы t .

См. В функции next предостережения по изменению таблицы во время ее обхода.

pcall (f [, arg1, ···])

Вызывает функцию f с заданными аргументами в защищенном режиме . Это означает, что любая ошибка внутри f не распространяется; вместо этого pcall перехватывает ошибку и возвращает код состояния. Его первым результатом является код состояния (логическое значение), который является истинным, если вызов завершается успешно без ошибок. В таком случае pcall также возвращает все результаты вызова после этого первого результата. В случае какой-либо ошибки pcall возвращает false плюс объект ошибки. Обратите внимание, что ошибки, обнаруженные pcall , не вызывают обработчик сообщений.

print (···)

Получает любое количество аргументов и выводит их значения в stdout , преобразуя каждый аргумент в строку, следуя тем же правилам tostring .

Функция print не предназначена для форматированного вывода, а только как быстрый способ показать значение, например, для отладки. Для полного контроля над выводом используйте string.format и io.write .

rawequal (v1, v2)

Проверяет, равен ли v1 v2 , без вызова __eq . Возвращает логическое значение.

rawget (table, index)

Получает реальное значение table[index] без использования __index __index. table должен быть столом; index может иметь любое значение.

rawlen (v)

Возвращает длину объекта v , который должен быть таблицей или строкой, без вызова __len . Возвращает целое число.

rawset (table, index, value)

Устанавливает реальное значение table[index] к value , без использования __newindex metavalue. table должна быть таблицей, index любое значение, отличное от nil и NaN, и value любого значения Lua.

Эта функция возвращает table .

select (index, ···)

Если index является числом, возвращает все аргументы после аргумента number index ; отрицательное число индексирует с конца (-1 — последний аргумент). В противном случае index должен быть строкой "#" , а select возвращает общее количество полученных дополнительных аргументов.

setmetatable (table, metatable)

Устанавливает метатаблицу для данной таблицы. Если metatable равна нулю , удаляет метатаблицу данной таблицы. Если исходная метатаблица имеет поле __metatable , возникает ошибка.

Эта функция возвращает table .

Чтобы изменить метатаблицу других типов из кода Lua, вы должны использовать библиотеку отладки ( §6.10 ).

tonumber (e [, base])

Когда tonumber без base , tonumber пытается преобразовать свой аргумент в число. Если аргумент уже является числом или строкой, конвертируемой в число, то tonumber возвращает это число; в противном случае возвращается ошибка .

Преобразование строк может привести к целым числам или числам с плавающей запятой в соответствии с лексическими соглашениями Lua (см. §3.1 ). Строка может иметь начальные и конечные пробелы и знак.

При вызове с base , то e должен быть строкой следует интерпретировать как целое позиция в этой базе. Основание может быть любым целым числом от 2 до 36 включительно. В базах больше 10 буква « A » (в верхнем или нижнем регистре) представляет 10, « B » представляет 11 и т. Д., Где « Z » представляет 35. Если строка e не является допустимой цифрой в данном base функция возвращает ошибку .

tostring (v)

Получает значение любого типа и преобразует его в строку в человекочитаемом формате.

Если метатаблица v имеет поле __tostring , то tostring вызывает соответствующее значение с v в качестве аргумента и использует результат вызова в качестве своего результата. В противном случае, если метатаблица v имеет поле __name со строковым значением, tostring может использовать эту строку в своем окончательном результате.

Для полного контроля над преобразованием чисел используйте string.format .

type (v)

Возвращает тип своего единственного аргумента, закодированного в виде строки. Возможные результаты этой функции: « nil » (строка, а не значение nil ), « number », « string », « boolean », « table », « function », « thread » и « userdata ».

_VERSION

Глобальная переменная (не функция), которая содержит строку, содержащую запущенную версию Lua. Текущее значение этой переменной — « Lua 5.4 ».

warn (msg1, ···)

Выдает предупреждение с сообщением,состоящим из конкатенации всех его аргументов (которые должны быть строками).

По соглашению, цельное сообщение, начинающееся с ‘ @ ‘, должно быть управляющим сообщением , которое является сообщением самой системе предупреждений. В частности, стандартная функция предупреждения в Lua распознает управляющие сообщения « @off », чтобы остановить @on предупреждений, и « @on », чтобы (повторно) запустить эмиссию; он игнорирует неизвестные управляющие сообщения.

xpcall (f, msgh [, arg1, ···])

Эта функция похожа на pcall , за исключением того, что она устанавливает новый обработчик сообщений msgh .

6.2-Манипулирование корутинами

Эта библиотека содержит операции для управления сопрограммами, которые входят в coroutine таблицы . См. §2.6 для общего описания сопрограмм.

coroutine.close (co)

Закрывает сопрограмму co , то есть закрывает все ее ожидающие закрытия переменные и переводит сопрограмму в мертвое состояние. Данная сопрограмма должна быть мертвой или приостановленной. В случае ошибки закрытия какой-либо переменной возвращает false плюс объект ошибки; в противном случае возвращает истину .

coroutine.create (f)

Создает новую сопрограмму с телом f . f должна быть функцией. Возвращает эту новую сопрограмму, объект с типом "thread" .

coroutine.isyieldable ([co])

Возвращает истину , если сопрограммная co может дать. По умолчанию для co используется работающая сопрограмма.

Корутина является выводимой,если она не является главным потоком и не находится внутри невыводимой C-функции.

coroutine.resume (co [, val1, ···])

Запускает или продолжает выполнение сопрограммы co . Когда вы в первый раз возобновляете работу сопрограммы, она запускает свое тело. Значения val1 , … передаются в качестве аргументов функции тела. Если сопрограмма сдалась, resume перезапускает ее; значения val1 , … передаются как результаты yield.

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

coroutine.running ()

Возвращает бегущую коруэйн плюс булевую,верно,когда бегущая коруэйн является основной.

coroutine.status (co)

Возвращает статус сопрограммы co в виде строки: "running" , если сопрограмма выполняется (то есть это та, которая вызвала status ); "suspended" , если сопрограмма приостановлена ​​в вызове yield или если она еще не запущена; "normal" если сопрограмма активна, но не работает (то есть возобновила работу другой сопрограммы); и "dead" если сопрограмма завершила свою функцию тела или остановилась с ошибкой.

coroutine.wrap (f)

Создает новую сопрограмму с телом f ; f должна быть функцией. Возвращает функцию, которая возобновляет работу сопрограммы при каждом ее вызове. Любые аргументы, переданные этой функции, действуют как дополнительные аргументы для resume . Функция возвращает те же значения, что и resume , за исключением первого логического значения. В случае ошибки функция закрывает сопрограмму и распространяет ошибку.

coroutine.yield (···)

Приостанавливает выполнение вызывающей сопрограммы. Любые аргументы yield передаются как дополнительные результаты для resume .

6.3-Модули

Библиотека пакетов предоставляет базовые возможности для загрузки модулей в Lua. Он экспортирует одну функцию непосредственно в глобальную среду: require . Все остальное экспортируется в табличном package .

require (modname)

Загружает данный модуль. Функция начинается с просмотра таблицы package.loaded , чтобы определить, modname ли уже имя мода . Если это так, то require возвращает значение, хранящееся в package.loaded[modname] . (Отсутствие второго результата в этом случае означает, что этот вызов не должен загружать модуль.) В противном случае он пытается найти загрузчик для модуля.

Чтобы найти загрузчик, require руководствуется таблицей package.searchers . Каждый элемент в этой таблице представляет собой функцию поиска, которая ищет модуль определенным образом. Изменяя эту таблицу, мы можем изменить способ поиска модуля require . Следующее объяснение основано на конфигурации по умолчанию для package.searchers .

Сначала require запросы package.preload[modname] . Если у него есть значение, это значение (которое должно быть функцией) является загрузчиком. В противном случае require поиск загрузчика Lua, используя путь, хранящийся в package.path . Если и это не удается, он ищет загрузчик C, используя путь, хранящийся в package.cpath . Если безуспешна, он пытается в все-в-одном загрузчик (см package.searchers ).

Как только загрузчик найден, require вызывает загрузчик с двумя аргументами: имя modname и дополнительное значение, данные загрузчика , также возвращаемые поисковиком. Данные загрузчика могут иметь любое значение, полезное для модуля; для поисковиков по умолчанию он указывает, где был найден загрузчик. (Например, если загрузчик пришел из файла, это дополнительное значение — это путь к файлу.) Если загрузчик возвращает любое значение, package.loaded[modname] nil, require присваивает возвращаемое значение package.loaded [modname] . Если загрузчик не возвращает значение, package.loaded[modname] nil, и не присвоил никакого значения package.loaded [modname] , то require присваивает этой записи значение true . В любом случае require возвращает окончательное значение package.loaded[modname] . Помимо этого значения, require также возвращает в качестве второго результата данные загрузчика, возвращенные поисковой программой, которые указывают, как require нашел модуль.

Если возникает какая-либо ошибка при загрузке или запуске модуля, или если он не может найти загрузчик для модуля, тогда require вызывает ошибку.

package.config

Строка,описывающая некоторые конфигурации во время компиляции пакетов.Эта строка представляет собой последовательность строк:

  • Первая строка — это строка-разделитель каталогов. По умолчанию это ‘ ‘ для Windows и ‘ / ‘ для всех остальных систем.
  • Вторая строка — это символ, разделяющий шаблоны на пути. По умолчанию ‘ ; ».
  • Третья строка — это строка, которая отмечает точки замены в шаблоне. По умолчанию ‘ ? ».
  • Четвертая строка — это строка, которая в пути в Windows заменяется каталогом исполняемого файла. По умолчанию ‘ ! ».
  • Пятая строка — это отметка, чтобы игнорировать весь текст после нее при построении имени функции luaopen_ . По умолчанию — « - ».
package.cpath

Строка с путем, используемым командой require для поиска загрузчика C.

Lua инициализирует путь C package.cpath так же, как он инициализирует путь Lua package.path , используя переменную среды LUA_CPATH_5_4 , переменную среды LUA_CPATH или путь по умолчанию, определенный в luaconf.h .

package.loaded

Таблица, используемая require , чтобы контролировать, какие модули уже загружены. Когда требуется модуль modname и package.loaded[modname] не является ложным, require просто возвращает значение , хранящееся там.

Эта переменная всего лишь ссылка на реальную таблицу; присвоения этой переменной не изменяют таблицу, используемую require .

package.loadlib (libname, funcname)

Динамически связывает программу хоста с библиотекой C libname .

Если funcname — « * », то он связывается только с библиотекой, делая символы, экспортируемые библиотекой, доступными для других динамически подключаемых библиотек. В противном случае он ищет функцию funcname внутри библиотеки и возвращает эту функцию как функцию C. Итак, funcname должно соответствовать прототипу lua_CFunction (см. lua_CFunction ).

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

Эта функция не поддерживается стандартом C. Таким образом, она доступна только на некоторых платформах (Windows, Linux, Mac OS X, Solaris, BSD и другие системы Unix, поддерживающие стандарт dlfcn ).

Эта функция изначально небезопасна, поскольку позволяет Lua вызывать любую функцию из любой читаемой динамической библиотеки в системе. (Lua вызывает любую функцию, предполагая, что функция имеет правильный прототип и соблюдает правильный протокол (см. lua_CFunction ). Следовательно, вызов произвольной функции в произвольной динамической библиотеке чаще всего приводит к нарушению доступа.)

package.path

Строка с путем, используемым командой require для поиска загрузчика Lua.

При запуске Lua инициализирует эту переменную значением переменной среды LUA_PATH_5_4 или переменной среды LUA_PATH или путем по умолчанию, определенным в luaconf.h , если эти переменные среды не определены. Знак » ;; » в значении переменной среды заменяется путем по умолчанию.

package.preload

Таблица для хранения загрузчиков для определенных модулей (см. require ).

Эта переменная всего лишь ссылка на реальную таблицу; присвоения этой переменной не изменяют таблицу, используемую require .

package.searchers

Таблица, используемая require для управления поиском модулей.

Каждая запись в этой таблице является функцией поиска . При поиске модуля require вызывает каждый из этих искателей в возрастающем порядке, используя имя модуля (аргумент, указанный для require ) в качестве единственного аргумента. Если поисковик находит модуль, он возвращает другую функцию, загрузчик модуля , плюс дополнительное значение, данные загрузчика , которые будут переданы этому загрузчику и возвращены в качестве второго результата командой require . Если он не может найти модуль, он возвращает строку, объясняющую, почему (или nil, если ему нечего сказать).

Луа инициализирует эту таблицу четырьмя функциями поиска.

Первый поисковик просто ищет загрузчик в таблице package.preload .

Второй поисковик ищет загрузчик как библиотеку Lua, используя путь, хранящийся в package.path . Поиск выполняется, как описано в функции package.searchpath .

Третий поисковик ищет загрузчик как библиотеку C, используя путь, заданный переменной package.cpath . Опять же, поиск выполняется, как описано в функции package.searchpath . Например, если путь C — это строка

"./?.so;./?.dll;/usr/local/?/init.so"

поисковик модуля foo попытается открыть файлы ./foo.so , ./foo.dll и /usr/local/foo/init.so в указанном порядке. Найдя библиотеку C, этот поисковик сначала использует средство динамической компоновки, чтобы связать приложение с библиотекой. Затем он пытается найти внутри библиотеки функцию C, которая будет использоваться в качестве загрузчика. Имя этой функции C — это строка « luaopen_ », соединенная с копией имени модуля, где каждая точка заменена знаком подчеркивания. Более того, если в имени модуля есть дефис, его суффикс после (и включая) первого дефиса удаляется. Например, если имя модуля — a.b.c-v2.1 , имя функции будет luaopen_a_b_c .

Четвертый поисковик пробует универсальный загрузчик . Он выполняет поиск библиотеки по пути C для корневого имени данного модуля. Например, когда требуется a.b.c , он будет искать библиотеку C для a . Если он найден, он ищет в нем открытую функцию для подмодуля; в нашем примере это будет luaopen_a_b_c . С помощью этого средства пакет может упаковать несколько подмодулей C в одну библиотеку, при этом каждый подмодуль сохраняет свою исходную открытую функцию.

Все поисковые системы, кроме первого (предварительная загрузка), возвращают в качестве дополнительного значения путь к файлу, в котором был найден модуль, который возвращается package.searchpath . Первый искатель всегда возвращает строку « :preload: ».

Поисковики не должны вызывать ошибок и не иметь побочных эффектов в Lua.(Они могут иметь побочные эффекты в C,например,при связывании приложения с библиотекой).

package.searchpath (name, path [, sep [, rep]])

Ищет данное name по заданному path .

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

Например,если путь-это строка

"./?.lua;./?.lc;/usr/local/?/init.lua"

поиск по имени foo.a попытается открыть файлы ./foo/a.lua , ./foo/a.lc и /usr/local/foo/a/init.lua в указанном порядке.

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

6.4-Манипулирование строками

Эта библиотека предоставляет общие функции для работы со строками,такие как поиск и извлечение подстрок,а также сопоставление шаблонов.При индексировании строки в Lua первый символ находится в позиции 1 (а не в позиции 0,как в C).Индексы допускаются отрицательными и интерпретируются как индексирование в обратном направлении,начиная с конца строки.Таким образом,последний символ находится в позиции -1,и так далее.

Библиотека строк предоставляет все свои функции внутри string таблицы . Он также устанавливает метатаблицу для строк, где поле __index указывает на таблицу string . Следовательно, вы можете использовать строковые функции в объектно-ориентированном стиле. Например, string.byte(s,i) можно записать как s:byte(i) .

Библиотека строк предполагает однобайтовые символьные кодировки.

string.byte (s [, i [, j]])

Возвращает внутренние числовые коды символов s[i] , s[i+1] , …, s[j] . Значение по умолчанию для i — 1; значение по умолчанию для ji . Эти индексы корректируются по тем же правилам, что и функция string.sub .

Цифровые коды не обязательно переносятся между платформами.

string.char (···)

Получает ноль и более целых чисел.Возвращает строку длиной равной количеству аргументов,в которой каждый символ имеет внутренний числовой код,равный его соответствующему аргументу.

Цифровые коды не обязательно переносятся между платформами.

string.dump (function [, strip])

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

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

string.find (s, pattern [, init [, plain]])

Ищет первое совпадение с pattern (см. §6.4.1 ) в строке s . Если он находит совпадение, find возвращает индексы s , где это вхождение начинается и заканчивается; в противном случае возвращается ошибка . Третий необязательный числовой аргумент init указывает, с чего начать поиск; его значение по умолчанию равно 1 и может быть отрицательным. Значение true в качестве четвертого необязательного аргумента plain средства сопоставления с шаблоном, поэтому функция выполняет простую операцию «найти подстроку», при этом никакие символы в pattern не считаются магическими.

Если модель имеет захваты,то при успешном совпадении захваченные значения также возвращаются после двух индексов.

string.format (formatstring, ···)

Возвращает отформатированную версию своего переменного числа аргументов после описания, данного в его первом аргументе, который должен быть строкой. Строка формата следует тем же правилам, что и функция ISO C sprintf . Единственное отличие состоит в том, что спецификаторы и модификаторы преобразования * , h , L , l и n не поддерживаются и что есть дополнительный спецификатор q .

Спецификатор q форматирует логические значения, nil, числа и строки таким образом, чтобы результат был допустимой константой в исходном коде Lua. Логические значения и nil записываются очевидным образом ( true , false , nil ). Для сохранения полной точности числа с плавающей запятой записываются в шестнадцатеричном формате. Строка записывается в двойных кавычках с использованием управляющих последовательностей при необходимости, чтобы гарантировать, что она может быть безопасно прочитана интерпретатором Lua. Например, звонок

string.format('%q', 'a string with "quotes" and n new line')

может привести к появлению строки:

"a string with "quotes" and 
 new line"

Этот спецификатор не поддерживает модификаторы (флаги,ширина,длина).

Спецификаторы преобразования A , a , E , e , f , G и g ожидают число в качестве аргумента. Спецификаторы c , d , i , o , u , X и x ожидают целое число. Когда Lua скомпилирован с помощью компилятора C89, спецификаторы A и a (шестнадцатеричные числа с плавающей запятой) не поддерживают модификаторы.

Спецификатор s ожидает строку; если его аргумент не является строкой, он преобразуется в аргумент по тем же правилам tostring . Если у спецификатора есть какой-либо модификатор, соответствующий строковый аргумент не должен содержать встроенных нулей.

Спецификатор p форматирует указатель, возвращаемый lua_topointer . Это дает уникальный строковый идентификатор для таблиц, пользовательских данных, потоков, строк и функций. Для других значений (чисел, nil, логических) этот спецификатор приводит к строке, представляющей указатель NULL .

string.gmatch (s, pattern [, init])

Возвращает функцию-итератор, которая при каждом вызове возвращает следующий захват из pattern (см. §6.4.1 ) по строке s . Если pattern не указаны захваты, то при каждом вызове создается полное совпадение. Третий необязательный числовой аргумент init указывает, с чего начать поиск; его значение по умолчанию равно 1 и может быть отрицательным.

В качестве примера следующий цикл будет перебирать все слова из строки s , печатая по одному в каждой строке:

s = "hello world from Lua"
for w in string.gmatch(s, "%a+") do
  print(w)
end

Следующий пример собирает все пары key=value из заданной строки в таблицу:

t = {}
s = "from=world, to=Lua"
for k, v in string.gmatch(s, "(%w+)=(%w+)") do
  t[k] = v
end

Для этой функции курсор « ^ » в начале шаблона не работает как якорь, так как это предотвратит итерацию.

string.gsub (s, pattern, repl [, n])

Возвращает копию s , в которой все (или первые n , если даны) вхождения шаблона pattern см. §6.4.1 ) были заменены строкой замены, заданной repl , которая может быть строкой, таблицей или функция. gsub также возвращает в качестве второго значения общее количество совпадений. Название gsub происходит от Global SUBstitution .

Если repl — это строка, то ее значение используется для замены. Символ % работает как escape-символ: любая последовательность в repl в форме %d , где d находится между 1 и 9, обозначает значение d -й захваченной подстроки; последовательность %0 обозначает все совпадение; последовательность %% обозначает один % .

Если repl — это таблица, то таблица запрашивается для каждого совпадения, используя первый захват в качестве ключа.

Если repl является функцией, то эта функция вызывается каждый раз, когда происходит совпадение, со всеми захваченными подстроками, переданными в качестве аргументов по порядку.

В любом случае,если деталь не указывает никаких захватов,то она ведет себя так,как будто вся деталь находится внутри захвата.

Если значение, возвращаемое запросом таблицы или вызовом функции, является строкой или числом, то оно используется как строка замены; в противном случае, если оно равно false или nil , то замены нет (то есть исходное совпадение сохраняется в строке).

Вот несколько примеров:

x = string.gsub("hello world", "(%w+)", "%1 %1")


x = string.gsub("hello world", "%w+", "%0 %0", 1)


x = string.gsub("hello world from Lua", "(%w+)%s*(%w+)", "%2 %1")


x = string.gsub("home = $HOME, user = $USER", "%$(%w+)", os.getenv)


x = string.gsub("4+5 = $return 4+5$", "%$(.-)%$", function (s)
      return load(s)()
    end)


local t = {name="lua", version="5.4"}
x = string.gsub("$name-$version.tar.gz", "%$(%w+)", t)
string.len (s)

Получает строку и возвращает ее длину. Пустая строка "" имеет длину 0. Подсчитываются встроенные нули, поэтому "a00bc00" имеет длину 5.

string.lower (s)

Получает строку и возвращает копию этой строки со всеми прописными буквами,измененными на строчные.Все остальные символы остаются без изменений.Определение того,что такое заглавная буква,зависит от текущей локали.

string.match (s, pattern [, init])

Ищет первое совпадение шаблона (см. pattern ) в строке s . Если он находит его, то match возвращает захваты из шаблона; в противном случае он возвращает ошибку . Если pattern не указаны захваты, возвращается все совпадение. Третий необязательный числовой аргумент init указывает, с чего начать поиск; его значение по умолчанию равно 1 и может быть отрицательным.

string.pack (fmt, v1, v2, ···)

Возвращает двоичную строку, содержащую значения v1 , v2 и т. д., сериализованные в двоичной форме (упакованные) в соответствии со строкой формата fmt (см. §6.4.2 ).

string.packsize (fmt)

Возвращает размер строки, полученной из string.pack в заданном формате. Строка формата не может иметь опции переменной длины ‘ s ‘ или ‘ z ‘ (см. §6.4.2 ).

string.rep (s, n [, sep])

Возвращает строку, которая представляет собой конкатенацию n копий строки s , разделенных строкой sep . Значение по умолчанию для sep — это пустая строка (то есть без разделителя). Возвращает пустую строку, если n не положительно.

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

string.reverse (s)

Возвращает строку , которая является строка s обратной.

string.sub (s, i [, j])

Возвращает подстроку s , которая начинается с i и продолжается до j ; i и j могут быть отрицательными. Если j отсутствует, предполагается, что он равен -1 (что совпадает с длиной строки). В частности, вызов string.sub(s,1,j) возвращает префикс s длины j , а string.sub(s, -i) (для положительного i ) возвращает суффикс s длины i .

Если после преобразования отрицательных индексов i меньше 1, оно исправляется до 1. Если j больше длины строки, оно исправляется до этой длины. Если после этих исправлений i больше j , функция возвращает пустую строку.

string.unpack (fmt, s [, pos])

Возвращает значения, упакованные в строку s (см. string.pack ) в соответствии со строкой формата fmt (см. §6.4.2 ). Необязательный pos отмечает, где начать чтение в s (по умолчанию 1). После прочитанных значений эта функция также возвращает индекс первого непрочитанного байта в s .

string.upper (s)

Получает строку и возвращает копию этой строки со всеми строчными буквами,измененными на прописные.Все остальные символы остаются без изменений.Определение того,что такое строчная буква,зависит от текущей локали.

6.4.1-Узоры

Шаблоны в Lua описываются обычными строками, которые интерпретируются как шаблоны функциями сопоставления string.find , string.gmatch , string.gsub и string.match . В этом разделе описывается синтаксис и значение (то есть то, что они соответствуют) этих строк.

Character Class:

Класс символов используется для представления набора символов. При описании класса символов допустимы следующие комбинации:

  • x : (где x не является одним из волшебных символов ^$()%.[]*+-? ) представляет сам символ x .
  • . : (точка) представляет все символы.
  • %a : представляет все буквы.
  • %c : представляет все управляющие символы.
  • %d : представляет все цифры.
  • %g : представляет все печатаемые символы, кроме пробела.
  • %l : представляет все буквы нижнего регистра.
  • %p : представляет все символы пунктуации.
  • %s : представляет все символы пробела.
  • %u : представляет все буквы в верхнем регистре.
  • %w : представляет все буквенно-цифровые символы.
  • %x : представляет все шестнадцатеричные цифры.
  • %x : (где x — любой не буквенно-цифровой символ) представляет символ x . Это стандартный способ убежать от волшебных персонажей. Любому не буквенно-цифровому символу (включая все знаки препинания, даже немагические) может предшествовать » % «, чтобы представить себя в шаблоне.
  • [set] : представляет класс, который является объединением всех символов в наборе . Диапазон символов можно указать, разделив конечные символы диапазона в порядке возрастания знаком « - ». Все классы % x, описанные выше, также могут использоваться как компоненты в наборе . Все остальные символы в наборе представляют собой самих себя. Например, [%w_] (или [_%w] ) представляет все буквенно-цифровые символы плюс подчеркивание, [0-7] представляет восьмеричные цифры, а [0-7%l%-] представляет восьмеричные цифры плюс строчные буквы. буквы плюс символ » - «.

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

    Взаимодействие между диапазонами и классами не определено. Следовательно, такие шаблоны, как [%a-z] или [a-%%] , не имеют значения.

  • [^set] : представляет собой дополнение набора , где набор интерпретируется, как указано выше.

Для всех классов, представленных одиночными буквами ( %a , %c и т. Д.), Соответствующая заглавная буква представляет собой дополнение класса. Например, %S представляет все непробельные символы.

Определения букв, пробелов и других групп символов зависят от текущего языкового стандарта. В частности, класс [a-z] не может быть эквивалентен %l .

Pattern Item:

Элемент модели может быть

  • односимвольный класс,который соответствует любому односимвольному в классе;
  • односимвольный класс, за которым следует ‘ * ‘, что соответствует последовательностям из нуля или более символов в классе. Эти повторяющиеся элементы всегда будут соответствовать самой длинной возможной последовательности;
  • односимвольный класс, за которым следует ‘ + ‘, что соответствует последовательностям одного или нескольких символов в классе. Эти повторяющиеся элементы всегда будут соответствовать самой длинной возможной последовательности;
  • односимвольный класс, за которым следует ‘ - ‘, что также соответствует последовательностям из нуля или более символов в классе. В отличие от ‘ * ‘, эти повторяющиеся элементы всегда будут соответствовать самой короткой возможной последовательности;
  • односимвольный класс, за которым следует ‘ ? ‘, что соответствует нулю или одному вхождению символа в классе. Если возможно, он всегда соответствует одному вхождению;
  • %n для n от 1 до 9; такой элемент соответствует подстроке, равной n -й захваченной строке (см. ниже);
  • %bxy , где x и y — два разных символа; Такой элемент соответствует строкам , которые начинаются с й , с концом у , и где х и у являются сбалансированы . Это означает, что если кто-то читает строку слева направо, считая +1 для x и -1 для y , окончание y будет первым y, где счет достигает 0. Например, элемент %b() соответствует выражения со сбалансированными круглыми скобками.
  • %f[set] , образец границы ; такой элемент соответствует пустой строке в любой позиции, так что следующий символ принадлежит набору, а предыдущий символ не принадлежит набору . Набор набор интерпретируется , как описано ранее. Начало и конец темы обрабатываются так, как если бы они были символом ‘ ‘.
Pattern:

Шаблон представляет собой последовательность элементов образца. Каретка « ^ » в начале шаблона закрепляет совпадение в начале строки темы. Символ » $ » в конце шаблона закрепляет совпадение в конце строки темы. В других позициях ^ » ^ » и » $ » не имеют особого значения и обозначают сами себя.

Captures:

Шаблон может содержать вложенные шаблоны, заключенные в круглые скобки; они описывают захваты . При успешном совпадении подстроки строки темы, которые соответствуют захватам, сохраняются ( захватываются ) для будущего использования. Захваты нумеруются в соответствии с их левыми скобками. Например, в шаблоне "(a*(.)%w(%s*))" часть строки, соответствующей "a*(.)%w(%s*)" , сохраняется как первый захват, и поэтому имеет номер 1; соответствующий символ » . » записывается под номером 2, а часть, соответствующая » %s* «, имеет номер 3.

В качестве особого случая функция capture () фиксирует текущую позицию строки (число). Например, если мы применим шаблон "()aa()" к строке "flaaap" , будет два захвата: 3 и 5.

Multiple matches:

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

> string.gsub("abc", "()a*()", print);


Второй и третий результаты приходят из Lua, сопоставляя пустую строку после « b » и еще одну после « c ». Lua не соответствует пустой строке после ‘ a ‘, потому что она будет заканчиваться на той же позиции, что и предыдущее совпадение.

6.4.2-Строки формата для упаковки и распаковки

Первый аргумент для string.pack , string.packsize и string.unpack — это строка формата, которая описывает макет создаваемой или читаемой структуры.

Строка формата-это последовательность параметров преобразования.Опции преобразования представлены ниже:

  • < : устанавливает прямой порядок байтов
  • > : устанавливает прямой порядок байтов
  • = : устанавливает исходный порядок байтов
  • ![n] : устанавливает максимальное выравнивание равным n (по умолчанию — собственное выравнивание)
  • b : байт со знаком ( char )
  • B : беззнаковый байт ( char )
  • h : short подписанный (собственный размер)
  • H : беззнаковый short (собственный размер)
  • l : long знак со знаком (собственный размер)
  • L : беззнаковый long (собственный размер)
  • j: a lua_Integer
  • J: a lua_Unsigned
  • T : size_t (собственный размер)
  • i[n] : подписанное int с n байтами (по умолчанию — собственный размер)
  • I[n] : беззнаковое int с n байтами (по умолчанию — собственный размер)
  • f : float (собственный размер)
  • d : double (собственный размер)
  • n : lua_Number
  • cn : строка фиксированного размера с n байтами
  • z : строка с нулевым завершением
  • s[n] : строка, которой предшествует ее длина, закодированная как целое число без знака с n байтами (по умолчанию size_t )
  • x : один байт заполнения
  • Xop : пустой элемент, который выравнивается в соответствии с опцией op (которая в противном случае игнорируется)
  • »: (пробел) игнорируется

[n] » означает необязательное целое число.) За исключением заполнения, пробелов и конфигураций (параметры « xX <=>! »), Каждая опция соответствует аргументу в string.pack или результату в string.unpack .

Для опций « !n », « sn », « in » и « In » n может быть любым целым числом от 1 до 16. Все интегральные опции проверяют переполнение; string.pack проверяет, подходит ли данное значение заданному размеру; string.unpack проверяет, соответствует ли прочитанное значение целому числу Lua. Для параметров без знака целые числа Lua также рассматриваются как значения без знака.

Любая строка формата начинается с префикса » !1= «, то есть с максимального выравнивания 1 (без выравнивания) и естественного порядка байтов.

Нативная эндианальность предполагает,что вся система является либо big,либо little endian.Функции упаковки не будут корректно эмулировать поведение форматов со смешанным эндианом.

Выравнивание работает следующим образом: для каждой опции формат получает дополнительное заполнение до тех пор, пока данные не начнутся со смещения, кратного минимальному между размером опции и максимальным выравниванием; этот минимум должен быть степенью 2. Опции « c » и « z » не совпадают; опция « s » следует за выравниванием его начального целого числа.

Все отступы заполняются нулями в string.pack и игнорируются string.unpack .

6.5-Поддержка UTF-8

Эта библиотека обеспечивает базовую поддержку кодировки UTF-8. Он предоставляет все свои функции в таблице utf8 . Эта библиотека не поддерживает Unicode, кроме обработки кодировки. Любая операция, которая требует значения символа, например, классификация символов, выходит за рамки ее области.

Если не указано иначе,все функции,которые ожидают позицию байта в качестве параметра,предполагают,что данная позиция является либо началом последовательности байтов,либо единицей плюс длина предметной строки.Как и в библиотеке строк,отрицательные индексы отсчитываются от конца строки.

Функции, которые создают байтовые последовательности, принимают все значения до 0x7FFFFFFF , как определено в исходной спецификации UTF-8; это подразумевает байтовые последовательности до шести байтов.

Функции, интерпретирующие байтовые последовательности, принимают только допустимые последовательности (хорошо сформированные и не слишком длинные). По умолчанию они принимают только последовательности байтов, которые приводят к действительным кодовым точкам Unicode, отклоняют значения больше 10FFFF и суррогаты. Логический аргумент lax , если он доступен, снимает эти проверки, так что принимаются все значения до 0x7FFFFFFF . (Плохо сформированные и слишком длинные последовательности по-прежнему отклоняются.)

utf8.char (···)

Получает ноль или несколько целых чисел,преобразует каждое из них в соответствующую последовательность UTF-8 байт и возвращает строку с конкатенцией всех этих последовательностей.

utf8.charpattern

Шаблон (строка, а не функция) » [-x7FxC2-xFD][x80-xBF]* » (см. §6.4.1 ), который соответствует ровно одной последовательности байтов UTF-8, предполагая, что тема является допустимой строкой UTF-8.

utf8.codes (s [, lax])

Возвращает значения,чтобы конструкция

for p, c in utf8.codes(s) do body end

будет перебирать все символы UTF-8 в строке s , где p — позиция (в байтах), а c — кодовая точка каждого символа. Выдает ошибку, если встречает недопустимую последовательность байтов.

utf8.codepoint (s [, i [, j [, lax]]])

Возвращает кодовые точки (как целые числа) из всех символов в s , которые начинаются между байтовой позицией i и j (оба включены). По умолчанию для i установлено значение 1, а для ji . Выдает ошибку, если встречает недопустимую последовательность байтов.

utf8.len (s [, i [, j [, lax]]])

Возвращает количество символов UTF-8 в строке s , которые начинаются между позициями i и j (оба включительно). По умолчанию для i установлено значение 1, а для j — -1. Если обнаруживается недопустимая последовательность байтов, возвращается ошибка плюс позиция первого недопустимого байта.

utf8.offset (s, n [, i])

Возвращает позицию (в байтах), с которой начинается кодирование n -го символа s (считая с позиции i ). Отрицательное n получает символы перед позицией i . Значение по умолчанию для i равно 1, если n неотрицательно, и #s + 1 противном случае, так что utf8.offset(s, -n) получает смещение n -го символа от конца строки. Если указанный символ не находится ни в теме, ни сразу после его конца, функция возвращает ошибку .

В качестве особого случая, когда n равно 0, функция возвращает начало кодировки символа, который содержит i -й байт числа s .

Эта функция предполагает, что s — допустимая строка UTF-8.

6.6-Манипулирование таблицами

Эта библиотека предоставляет общие функции для управления таблицами. Он предоставляет все свои функции внутри таблицы table .

Помните, что всякий раз, когда операции требуется длина таблицы, применяются все предостережения относительно оператора длины (см. §3.4.7 ). Все функции игнорируют нечисловые ключи в таблицах, переданных в качестве аргументов.

table.concat (list [, sep [, i [, j]]])

Для списка, где все элементы являются строками или числами, возвращает строку list[i]..sep..list[i+1] ··· sep..list[j] . Значение по умолчанию для sep — пустая строка, значение по умолчанию для i — 1, а значение по умолчанию для j#list . Если i больше j , возвращает пустую строку.

table.insert (list, [pos,] value)

Вставляет value элемента в позицию pos list , сдвигая вверх элементы list[pos], list[pos+1], ···, list[#list] . Значение по умолчанию для pos#list+1 , так что вызов table.insert(t,x) вставляет x в конец списка t .

table.move (a1, f, e, t [,a2])

Перемещает элементы из таблицы a1 в таблицу a2 , выполняя эквивалент следующего множественного присваивания: a2[t],··· = a1[f],···,a1[e] . По умолчанию для a2 используется значение a1 . Целевой диапазон может пересекаться с исходным диапазоном. Количество перемещаемых элементов должно соответствовать целому числу Lua.

Возвращает целевую таблицу a2 .

table.pack (···)

Возвращает новую таблицу со всеми аргументами, хранящимися в ключах 1, 2 и т. Д., И с полем « n » с общим количеством аргументов. Обратите внимание, что результирующая таблица может не быть последовательностью, если некоторые аргументы равны нулю .

table.remove (list [, pos])

Удаляет из list элемент в позиции pos , возвращая значение удаленного элемента. Когда pos является целым числом от 1 до #list , он сдвигает вниз список элементов list[pos+1], list[pos+2], ···, list[#list] и стирает элемент list[#list] ; Индекс pos также может быть равен 0, если #list равен 0 или #list + 1 .

Значение pos по умолчанию — #list , так что вызов table.remove(l) удаляет последний элемент списка l .

table.sort (list [, comp])

Сортирует элементы списка в заданном порядке по месту , от list[1] до list[#list] . Если задано comp , то это должна быть функция, которая получает два элемента списка и возвращает истину, когда первый элемент должен стоять перед вторым в последнем порядке (так что после сортировки i < j означает not comp(list[j],list[i]) ). Если comp не указан, то вместо него используется стандартный оператор Lua < .

Обратите внимание, что функция comp должна определять строгий частичный порядок элементов в списке; то есть он должен быть асимметричным и транзитивным. В противном случае невозможна правильная сортировка.

Алгоритм сортировки не является стабильным:элементы,считающиеся равными по данному порядку,могут иметь измененные по сортировке относительные позиции.

table.unpack (list [, i [, j]])

Возвращает элементы из данного списка.Эта функция эквивалентна

return list[i], list[i+1], ···, list[j]

По умолчанию i равно 1, а j#list .

6.7-Математические функции

Эта библиотека предоставляет основные математические функции. Он предоставляет все свои функции и константы внутри таблицы math . Функции с аннотацией » integer/float » выдают целочисленные результаты для целочисленных аргументов и результаты с плавающей запятой для нецелочисленных аргументов. Функции округления math.ceil , math.floor и math.modf возвращают целое число, если результат попадает в диапазон целого числа, или число с плавающей запятой в противном случае.

math.abs (x)

Возвращает максимальное значение от x до -x . (целое число / число с плавающей запятой)

math.acos (x)

Возвращает арккосинус x (в радианах).

math.asin (x)

Возвращает арксинус x (в радианах).

math.atan (y [, x])

Возвращает арктангенс y/x (в радианах), но использует знаки обоих аргументов, чтобы найти квадрант результата. Он также правильно обрабатывает случай, когда x равен нулю.

Значение по умолчанию для x равно 1, так что вызов math.atan(y) возвращает арктангенс y .

math.ceil (x)

Возвращает наименьшее целое значение, большее или равное x .

math.cos (x)

Возвращает косинус x (предполагается, что он выражен в радианах).

math.deg (x)

Преобразует угол x из радиан в градусы.

math.exp (x)

Возвращает значение e x (где e — основание натурального логарифма).

math.floor (x)

Возвращает наибольшее целое значение, меньшее или равное x .

math.fmod (x, y)

Возвращает остаток от деления x на y , который округляет частное до нуля. (число / с плавающей точкой)

math.huge

Значение с плавающей запятой HUGE_VAL , значение больше, чем любое другое числовое значение.

math.log (x [, base])

Возвращает логарифм x по заданному основанию. По умолчанию для base установлено значение e (так что функция возвращает натуральный логарифм x ).

math.max (x, ···)

Возвращает аргумент с максимальным значением в соответствии с оператором Lua < .

math.maxinteger

Целое число с максимальным значением для целого числа.

math.min (x, ···)

Возвращает аргумент с минимальным значением в соответствии с оператором Lua < .

math.mininteger

Целое число с минимальным значением для целого числа.

math.modf (x)

Возвращает целую часть x и дробную часть x . Его второй результат — всегда число с плавающей точкой.

math.pi

Значение π .

math.rad (x)

Преобразует угол x из градусов в радианы.

math.random ([m [, n]])

При вызове без аргументов возвращает псевдослучайное число с плавающей запятой с равномерным распределением в диапазоне [0,1) . При вызове с двумя целыми числами m и n , math.random возвращает псевдо-случайное число с равномерным распределением в диапазоне [M, N] . Вызов math.random(n) для положительного n эквивалентен math.random(1,n) . Вызов math.random(0) производит целое число со всеми битами (псевдо) случайным образом.

Эта функция использует алгоритм xoshiro256** для создания псевдослучайных 64-битных целых чисел, которые являются результатами вызовов с аргументом 0. Остальные результаты (диапазоны и числа с плавающей запятой) извлекаются из этих целых чисел без смещения.

Lua инициализирует свой псевдослучайный генератор эквивалентом вызова math.randomseed без аргументов, так что math.random должен генерировать разные последовательности результатов при каждом запуске программы.

math.randomseed ([x [, y]])

При вызове хотя бы с одним аргументом целочисленные параметры x и y объединяются в 128-битное начальное число , которое используется для повторной инициализации генератора псевдослучайных чисел; равные семена дают равные последовательности чисел. Значение по умолчанию для y равно нулю.

При вызове без аргументов Lua генерирует семя со слабой попыткой случайности.

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

Чтобы обеспечить требуемый уровень случайности для начального состояния (или, наоборот, чтобы иметь детерминированную последовательность, например, при отладке программы), вы должны вызвать math.randomseed с явными аргументами.

math.sin (x)

Возвращает синус x (предполагается, что он выражен в радианах).

math.sqrt (x)

Возвращает квадратный корень из x . (Вы также можете использовать выражение x^0.5 для вычисления этого значения.)

math.tan (x)

Возвращает тангенс x (предполагается, что он выражен в радианах).

math.tointeger (x)

Если значение x можно преобразовать в целое число, возвращает это целое число. В противном случае возврат не состоится .

math.type (x)

Возвращает « integer », если x является целым числом, « float », если это число с плавающей запятой, или неудачно, если x не является числом.

math.ult (m, n)

Возвращает логическое значение true тогда и только тогда, когда целое число m меньше целого числа n , когда они сравниваются как целые числа без знака.

6.8-Средства ввода и вывода

Библиотека I/O предоставляет два различных стиля для работы с файлами.Первый использует неявные файловые ручки;то есть существуют операции для установки входного файла по умолчанию и выходного файла по умолчанию,и все операции ввода/вывода выполняются над этими файлами по умолчанию.Второй стиль использует явные дескрипторы файлов.

При использовании неявных дескрипторов файлов все операции выполняются таблицей io . При использовании явных дескрипторов файла операция io.open возвращает дескриптор файла, а затем все операции предоставляются как методы дескриптора файла.

Метатаблица для дескрипторов файлов предоставляет __gc для __gc и __close , которые пытаются закрыть файл при вызове.

Таблица io также предоставляет три предопределенных дескриптора файлов с их обычными значениями из C: io.stdin , io.stdout и io.stderr . Библиотека ввода-вывода никогда не закрывает эти файлы.

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

io.close ([file])

Эквивалент file:close() . Без file закрывает выходной файл по умолчанию.

io.flush ()

Эквивалентно io.output():flush() .

io.input ([file])

При вызове с именем файла открывает названный файл (в текстовом режиме)и устанавливает его handle в качестве входного файла по умолчанию.При вызове с хэндлом файла просто устанавливает этот хэндл файла в качестве входного файла по умолчанию.При вызове без аргументов возвращает текущий входной файл по умолчанию.

В случае ошибок эта функция поднимает ошибку,а не возвращает код ошибки.

io.lines ([filename, ···])

Открывает файл с заданным именем в режиме чтения и возвращает функцию итератора, которая работает как file:lines(···) над открытым файлом. Когда функция итератора не может прочитать какое-либо значение, она автоматически закрывает файл. Помимо функции итератора, io.lines возвращает еще три значения: два значения nil в качестве заполнителей и дескриптор созданного файла. Следовательно, при использовании в универсальном цикле for файл закрывается даже в том случае, если цикл прерывается из-за ошибки или прерывания .

Вызов io.lines() (без имени файла) эквивалентен io.input():lines("l") ; то есть он перебирает строки входного файла по умолчанию. В этом случае итератор не закрывает файл по окончании цикла.

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

io.open (filename [, mode])

Эта функция открывает файл в режиме, указанном в строковом mode . В случае успеха возвращает новый дескриптор файла.

mode строка может быть любой из следующих условий :

  • « r »: режим чтения (по умолчанию);
  • « w »: режим записи;
  • « a »: режим добавления;
  • « r+ »: режим обновления, все предыдущие данные сохраняются;
  • « w+ »: режим обновления, все предыдущие данные стираются;
  • « a+ »: добавить режим обновления, предыдущие данные сохраняются, запись разрешена только в конец файла.

mode строка может также иметь « b » в конце, который необходим в некоторых системах , чтобы открыть файл в двоичном режиме.

io.output ([file])

Аналогичен io.input , но работает с выходным файлом по умолчанию.

io.popen (prog [, mode])

Эта функция зависит от системы и доступна не на всех платформах.

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

io.read (···)

Эквивалентно io.input():read(···) .

io.tmpfile ()

В случае успеха возвращает ручку для временного файла.Этот файл открывается в режиме обновления и автоматически удаляется по окончании работы программы.

io.type (obj)

Проверяет, является ли obj допустимым дескриптором файла. Возвращает строку "file" если obj — дескриптор открытого файла, "closed file" если obj — дескриптор закрытого файла, или сбой, если obj не является дескриптором файла.

io.write (···)

Эквивалентно io.output():write(···) .

file:close ()

Закрывает file . Обратите внимание, что файлы автоматически закрываются, когда их дескрипторы собираются сборщиком мусора, но для этого требуется непредсказуемое количество времени.

При закрытии дескриптора файла, созданного с помощью io.popen , file:close возвращает те же значения, что и os.execute .

file:flush ()

Сохраняет все записанные данные в file .

file:lines (···)

Возвращает функцию итератора, которая при каждом вызове читает файл в соответствии с заданными форматами. Если формат не указан, по умолчанию используется « l ». Например, конструкция

for c in file:lines(1) do body end

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

file:read (···)

Читает файл file соответствии с заданными форматами, которые указывают, что читать. Для каждого формата функция возвращает строку или число с прочитанными символами или завершается ошибкой, если не может прочитать данные в указанном формате. (В последнем случае функция не считывает последующие форматы.) При вызове без аргументов она использует формат по умолчанию, который читает следующую строку (см. Ниже).

Доступные форматы

  • « n »: читает число и возвращает его как число с плавающей запятой или целое число, следуя лексическим соглашениям Lua. (У числа могут быть начальные пробелы и знак.) Этот формат всегда считывает самую длинную входную последовательность, которая является допустимым префиксом для числа; если этот префикс не образует допустимое число (например, пустую строку, « 0x » или « 3.4e- ») или слишком длинный (более 200 символов), он отбрасывается, и формат возвращает ошибку .
  • « a »: читает весь файл, начиная с текущей позиции. В конце файла возвращается пустая строка; этот формат никогда не подводит.
  • « l »: читает следующую строку, пропуская конец строки, возвращая ошибку в конце файла. Это формат по умолчанию.
  • « L »: читает следующую строку, сохраняя символ конца строки (если есть), возвращая ошибку в конце файла.
  • число : читает строку до этого числа байтов, возвращая ошибку в конце файла. Если number равно нулю, он ничего не читает и возвращает пустую строку или завершается ошибкой в конце файла.

Форматы « l » и « L » следует использовать только для текстовых файлов.

file:seek ([whence [, offset]])

Устанавливает и получает позицию файла, измеренную от начала файла, до позиции, заданной offset плюс основание, указанное строкой whence , следующим образом:

  • » set «: база — позиция 0 (начало файла);
  • » cur «: база — текущая позиция;
  • « end »: база — это конец файла;

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

Значение по умолчанию для параметра whence"cur" , а для offset — 0. Следовательно, вызов file:seek() возвращает текущую позицию файла, не изменяя ее; file:seek("set") вызова : seek («set») устанавливает позицию в начало файла (и возвращает 0); а file:seek("end") вызова : seek («end») устанавливает позицию в конец файла и возвращает его размер.

file:setvbuf (mode [, size])

Устанавливает режим буферизации для файла.Существует три доступных режима:

  • « no »: без буферизации.
  • » full «: полная буферизация.
  • « line »: буферизация строки.

Для последних двух случаев size — это подсказка о размере буфера в байтах. По умолчанию это подходящий размер.

Конкретное поведение каждого режима непереносимо; проверьте базовую функцию ISO C setvbuf на вашей платформе для получения дополнительных сведений.

file:write (···)

Записывает значение каждого из своих аргументов в file . Аргументы должны быть строками или числами.

В случае успеха эта функция возвращает file .

6.9-Средства операционной системы

Эта библиотека реализована через table os .

os.clock ()

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

os.date ([format [, time]])

Возвращает строку или таблицу, содержащую дату и время, отформатированные в соответствии с заданным строковым format .

Если time аргумент присутствует, это время , чтобы быть отформатированы (см os.time функции для описания этого значения). В противном случае date форматирует текущее время.

Если format начинается с ‘ ! ‘, то дата форматируется в формате всемирного координированного времени. После этого необязательного символа, если format является строка » *t «, то date возвращает таблицу со следующими полями: year , month (1–12), day (1–31), hour (0–23), min ( 0–59), sec (0–61, из-за високосных секунд), wday (день недели, 1–7, воскресенье — 1), yday (день года, 1–366) и isdst (флаг перехода на летнее время, логическое значение). Это последнее поле может отсутствовать, если информация недоступна.

Если format не « *t », то date возвращает дату в виде строки, отформатированной в соответствии с теми же правилами, что и функции ISO C strftime .

Если format отсутствует, по умолчанию используется » %c «, что дает удобочитаемое представление даты и времени с использованием текущего языкового стандарта.

В системах, отличных от POSIX, эта функция может быть небезопасной для потоков из-за ее зависимости от функции C gmtime и функции C localtime .

os.difftime (t2, t1)

Возвращает разницу в секундах между временем t1 и временем t2 (где времена — это значения, возвращаемые os.time ). В POSIX, Windows и некоторых других системах это значение равно t2 t1 .

os.execute ([command])

Эта функция эквивалентна функции ISO C system . Он передает command для выполнения оболочкой операционной системы. Его первый результат — истина, если команда завершилась успешно, или неудачная в противном случае. После этого первого результата функция возвращает строку плюс число, как показано ниже:

  • » exit «: команда завершилась нормально; следующий номер — статус выхода команды.
  • « signal »: команда завершена сигналом; следующий номер — это сигнал о завершении команды.

При вызове без command , os.execute возвращает логическое значение, которое истинно , если оболочка доступна.

os.exit ([code [, close]])

Вызывает функцию exit ISO C для завершения основной программы. Если code является истинным , возвращаемый статус EXIT_SUCCESS ; если code является ложным , возвращаемый статус EXIT_FAILURE ; если code — это число, возвращаемый статус — это число. Значение по умолчанию для codeистина .

Если необязательный второй аргумент close равен true, закрывает состояние Lua перед выходом.

os.getenv (varname)

Возвращает значение переменной среды процесса varname или завершается ошибкой, если переменная не определена.

os.remove (filename)

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

os.rename (oldname, newname)

Переименовывает файл или каталог с именем oldname в newname . Если эта функция завершается неудачно, она возвращает ошибку , а также строку с описанием ошибки и ее код. В противном случае возвращается истина.

os.setlocale (locale [, category])

Устанавливает текущий языковой стандарт программы. locale — это системно-зависимая строка, определяющая языковой стандарт; category — это необязательная строка, описывающая, какую категорию нужно изменить: "all" , "collate" , "ctype" , "monetary" , "numeric" или "time" ; категория по умолчанию — "all" . Функция возвращает имя нового языкового стандарта или завершается ошибкой, если запрос не может быть выполнен.

Если locale является пустой строкой, текущий языковой стандарт установлен на собственный языковой стандарт, определенный реализацией. Если locale представляет собой строку « C », текущий языковой стандарт установлен на стандартный языковой стандарт C.

При вызове с nil в качестве первого аргумента эта функция возвращает только имя текущей локали для данной категории.

Эта функция может быть не поточно из — за своей зависимости от C функции setlocale .

os.time ([table])

Возвращает текущее время при вызове без аргументов или время, представляющее локальную дату и время, указанные в данной таблице. В этой таблице должны быть поля year , month и day , а также могут быть поля: hour (по умолчанию 12), min (по умолчанию 0), sec (по умолчанию 0) и isdst (по умолчанию ноль ). Остальные поля игнорируются. Описание этих полей см. os.date функции os.date .

Когда функция вызывается, значения в этих полях не обязательно должны находиться в допустимых диапазонах. Например, если sec равно -10, это означает, что на 10 секунд раньше времени, указанного в других полях; если hour равен 1000, это означает, что на 1000 часов позже времени, указанного в других полях.

Возвращаемое значение — это число, значение которого зависит от вашей системы. В POSIX, Windows и некоторых других системах это число подсчитывает количество секунд с некоторого заданного времени начала («эпоха»). В других системах значение не указывается, и число, возвращаемое time можно использовать только в качестве аргумента для os.date и os.difftime .

При вызове с таблицей os.time также нормализует все поля, задокументированные в функции os.date , так что они представляют то же время, что и до вызова, но со значениями внутри их допустимых диапазонов.

os.tmpname ()

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

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

По возможности вы можете предпочесть использовать io.tmpfile , который автоматически удаляет файл при завершении программы.

6.10-Библиотека отладки

Эта библиотека обеспечивает функциональность интерфейса отладки ( §4.7 ) для программ Lua. Вы должны проявлять осторожность при использовании этой библиотеки. Некоторые из его функций нарушают базовые предположения о коде Lua (например, что переменные, локальные для функции, не могут быть доступны извне; что метатаблицы пользовательских данных не могут быть изменены кодом Lua; что программы Lua не аварийно завершают работу) и, следовательно, могут поставить под угрозу безопасный код. Кроме того, некоторые функции в этой библиотеке могут работать медленно.

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

debug.debug ()

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

Обратите внимание, что команды для debug.debug лексически не вложены в какую-либо функцию и поэтому не имеют прямого доступа к локальным переменным.

debug.gethook ([thread])

Возвращает текущие настройки ловушки потока в виде трех значений: текущая функция ловушки, текущая маска ловушки и текущее количество debug.sethook , как установлено функцией debug.sethook .

Возврат не выполняется, если нет активного хука.

debug.getinfo ([thread,] f [, what])

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

lua_getinfo таблица может содержать все поля, возвращаемые lua_getinfo , со строкой what , описывающей, какие поля необходимо заполнить. По умолчанию, what должно получить всю доступную информацию, кроме таблицы допустимых строк. Если присутствует, опция ‘ f ‘ добавляет поле с именем func с самой функцией. Если присутствует, опция « L » добавляет поле с именем activelines с таблицей допустимых строк.

Например, выражение debug.getinfo(1,"n").name возвращает имя для текущей функции, если можно найти debug.getinfo(print) имя, а выражение debug.getinfo (print) возвращает таблицу со всей доступной информацией о print функция.

debug.getlocal ([thread,] f, local)

Эта функция возвращает имя и значение локальной переменной с local индексом функции на уровне f стека. Эта функция обращается не только к явным локальным переменным, но также к параметрам и временным значениям.

Первый параметр или локальная переменная имеет индекс 1 и так далее, следуя порядку, в котором они объявлены в коде, с учетом только тех переменных, которые активны в текущей области действия функции. Константы времени компиляции могут не появиться в этом листинге, если они были оптимизированы компилятором. Отрицательные индексы относятся к аргументам vararg; -1 — это первый аргумент vararg. Функция возвращает ошибку, если нет переменной с данным индексом, и вызывает ошибку при вызове с уровнем вне допустимого диапазона. (Вы можете вызвать debug.getinfo , чтобы проверить, действителен ли уровень.)

Имена переменных, начинающиеся с ‘ ( ‘ (открытая скобка), представляют переменные без известных имен (внутренние переменные, такие как переменные управления циклом, и переменные из фрагментов, сохраненных без отладочной информации).

Параметр f также может быть функцией. В этом случае getlocal возвращает только имя параметров функции.

debug.getmetatable (value)

Возвращает метатаблицу заданного value или nil, если у нее нет метатаблицы.

debug.getregistry ()

Возвращает таблицу реестра (см. §4.3 ).

debug.getupvalue (f, up)

Эта функция возвращает имя и значение восходящего значения с индексом up функции f . Функция возвращает ошибку, если нет повышающего значения с данным индексом.

(Для функций Lua повышающие значения — это внешние локальные переменные, которые использует функция и которые, следовательно, включаются в ее закрытие.)

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

Имя переменной ‘ ? ‘(знак вопроса) представляет переменные без известных имен (переменные из блоков, сохраненных без отладочной информации).

debug.getuservalue (u, n)

Возвращает n -ое пользовательское значение, связанное с пользовательскими данными u , плюс логическое значение, false, если пользовательские данные не имеют этого значения.

debug.setcstacklimit (limit)

Устанавливает новый предел для стека C.Это ограничение контролирует глубину вложенных вызовов в Lua,чтобы избежать переполнения стека.Слишком маленькое ограничение бессмысленно ограничивает рекурсивные вызовы;слишком большое ограничение подвергает интерпретатор опасности переполнения стека.К сожалению,не существует способа узнать априори максимальный безопасный предел для платформы.

Каждый вызов,выполненный из кода Lua,стоит одну единицу.Другие операции (например,вызовы из языка C в Lua или возобновление работы coroutine)могут иметь более высокую стоимость.

Эта функция имеет следующие ограничения:

  • Его можно вызвать только из главной корутины (потока);
  • Его нельзя вызывать во время обработки ошибки переполнения стека;
  • limit должен быть меньше 40000;
  • limit не может быть меньше количества используемого стека C.

Если вызов не соблюдает какое-то ограничение,он возвращает ложное значение.В противном случае вызов возвращает старое ограничение.

debug.sethook ([thread,] hook, mask [, count])

Устанавливает данную функцию как отладочную ловушку. mask строки и count чисел описывают, когда будет вызвана ловушка. Строковая маска может иметь любую комбинацию следующих символов с заданным значением:

  • c ‘: ловушка вызывается каждый раз, когда Lua вызывает функцию;
  • r ‘: ловушка вызывается каждый раз, когда Lua возвращается из функции;
  • l ‘: ловушка вызывается каждый раз, когда Lua вводит новую строку кода.

Более того, с count отличным от нуля, ловушка вызывается также после каждой команды count .

При вызове без аргументов debug.sethook отключает ловушку.

Когда ловушка вызывается, ее первым параметром является строка, описывающая событие, вызвавшее ее вызов: "call" , "tail call" , "return" , "line" и "count" . Для событий строки ловушка также получает новый номер строки в качестве второго параметра. Внутри ловушки вы можете вызвать getinfo с уровнем 2, чтобы получить больше информации о запущенной функции. (Уровень 0 — это функция getinfo , а уровень 1 — функция ловушки.)

debug.setlocal ([thread,] level, local, value)

Эта функция присваивает значение value локальной переменной с local индексом функции на level стека. Функция возвращает ошибку, если нет локальной переменной с данным индексом, и вызывает ошибку при вызове с level вне допустимого диапазона. (Вы можете вызвать getinfo , чтобы проверить, действителен ли уровень.) В противном случае он возвращает имя локальной переменной.

См. debug.getlocal для получения дополнительной информации об индексах и именах переменных.

debug.setmetatable (value, table)

Устанавливает метатаблицу для данного value в данную table (которая может быть нулевой ). Возвращает value .

debug.setupvalue (f, up, value)

Эта функция присваивает значение value восходящему значению с индексом up функции f . Функция возвращает ошибку, если нет повышающего значения с данным индексом. В противном случае он возвращает имя повышенного значения.

См. debug.getupvalue для получения дополнительной информации о повышающих значениях.

debug.setuservalue (udata, value, n)

Устанавливает данное value как n -е пользовательское значение, связанное с заданными udata . udata должны быть полными пользовательскими данными.

Возвращает udata или терпит неудачу, если userdata не имеет этого значения.

debug.traceback ([thread,] [message [, level]])

Если message присутствует, но не является ни строкой, ни нулем , эта функция возвращает message без дальнейшей обработки. В противном случае он возвращает строку с обратной трассировкой стека вызовов. Необязательная строка message добавляется в начале трассировки. Необязательный номер level указывает, с какого уровня начать трассировку (по умолчанию 1, функция, вызывающая traceback ).

debug.upvalueid (f, n)

Возвращает уникальный идентификатор (в виде легких пользовательских данных) для повышенного значения с номером n из данной функции.

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

debug.upvaluejoin (f1, n1, f2, n2)

Сделайте n1 -е повышающее значение замыкания Lua f1 ссылкой на n2 -е повышающее значение замыкания Lua f2 .

7 – Lua Standalone

Хотя Lua был разработан как язык расширения для встраивания в хост-программу C, он также часто используется как автономный язык. Интерпретатор Lua как отдельного языка, называемый просто lua , входит в стандартный дистрибутив. Автономный интерпретатор включает в себя все стандартные библиотеки. Его использование:

lua [options] [script [args]]

Опции есть:

  • -e stat : выполнить строку stat ;
  • -i : войти в интерактивный режим после запуска скрипта ;
  • -l mod : «потребовать» мод и присвоить результат глобальному моду ;
  • -v : распечатать информацию о версии;
  • -E : игнорировать переменные среды;
  • -W : включить предупреждения;
  • -- : параметры остановки обработки;
  • - : выполнить stdin как файл и прекратить обработку параметров.

После обработки опций lua запускает данный сценарий . При вызове без аргументов lua ведет себя как lua -v -i , когда стандартный ввод ( stdin ) является терминалом, и как lua - противном случае.

При вызове без опции -E , интерпретатор проверяет переменную среды LUA_INIT_5_4 (или LUA_INIT , если имя версии не определено) перед запуском любого аргумента. Если содержимое переменной имеет формат @filename , то lua выполняет файл. В противном случае lua выполняет саму строку.

При вызове с параметром -E Lua не обращается к переменным среды. В частности, значения package.path и package.cpath устанавливаются с путями по умолчанию, определенными в luaconf.h .

Параметры -e , -l и -W обрабатываются в том порядке, в котором они появляются. Например, такой вызов, как

$ lua -e 'a=1' -llib1 script.lua

сначала установит a в 1, затем потребует библиотеку lib1 и, наконец, запустит файл script.lua без аргументов. (Здесь $ — это приглашение оболочки. Ваше приглашение может быть другим.)

Перед запуском любого кода lua собирает все аргументы командной строки в глобальной таблице с именем arg . Имя скрипта переходит в индекс 0, первый аргумент после имени скрипта переходит в индекс 1 и так далее. Любые аргументы перед именем скрипта (то есть имя интерпретатора плюс его параметры) переходят к отрицательным индексам. Например, в звонке

$ lua -la b.lua t1 t2

стол вот такой:

arg = { [-2] = "lua", [-1] = "-la",
        [0] = "b.lua",
        [1] = "t1", [2] = "t2" }

Если в вызове нет скрипта,то имя интерпретатора переходит в индекс 0,за которым следуют остальные аргументы.Например,вызов

$ lua -e "print(arg[1])"

напечатает » -e «. Если есть скрипт, скрипт вызывается с аргументами arg[1] , ···, arg[#arg] . Как и все фрагменты в Lua, скрипт компилируется как функция с переменным числом аргументов.

В интерактивном режиме Lua многократно подсказывает и ждет строку.После прочтения строки,Lua сначала пытается интерпретировать ее как выражение.Если это удаётся,он печатает своё значение.В противном случае он интерпретирует строку как выражение.Если вы пишете незавершенное выражение,интерпретатор ждет его завершения,выдавая другую подсказку.

Если глобальная переменная _PROMPT содержит строку, то ее значение используется в качестве подсказки. Точно так же, если глобальная переменная _PROMPT2 содержит строку, ее значение используется в качестве вторичного приглашения (выдается во время неполных операторов).

В случае незащищенных ошибок в скрипте интерпретатор сообщает об ошибке в стандартный поток ошибок. Если объект ошибки не является строкой, но имеет __tostring , интерпретатор вызывает этот метаметод для создания окончательного сообщения. В противном случае интерпретатор преобразует объект ошибки в строку и добавляет к нему трассировку стека. Когда предупреждения включены, они просто выводятся на стандартный вывод ошибок.

При нормальном завершении интерпретатор закрывает свое основное состояние Lua (см. lua_close ). Сценарий может избежать этого шага, вызвав os.exit для завершения.

Чтобы разрешить использование Lua в качестве интерпретатора сценариев в системах Unix, Lua пропускает первую строку фрагмента файла, если он начинается с символа # . Следовательно, сценарии Lua можно превратить в исполняемые программы, используя команды chmod +x и #! форма, как в

#!/usr/local/bin/lua

Конечно, расположение интерпретатора Lua на вашем компьютере может быть другим. Если lua находится в вашем PATH , тогда

#!/usr/bin/env lua

является более портативным решением.

8-Несовместимость с предыдущей версией

Здесь мы перечислим несовместимости,которые вы можете обнаружить при переносе программы с Lua 5.3 на Lua 5.4.

Вы можете избежать некоторых несовместимостей, скомпилировав Lua с соответствующими параметрами (см. Файл luaconf.h ). Однако в будущем все эти параметры совместимости будут удалены. Чаще всего проблемы совместимости возникают при удалении этих параметров совместимости. Итак, всякий раз, когда у вас есть возможность, вы должны попробовать протестировать свой код с версией Lua, скомпилированной с отключенными всеми параметрами совместимости. Это упростит переход на новые версии Lua.

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

Аналогично,версии Lua всегда могут изменить внутреннее представление прекомпилированных частей;прекомпилированные части не совместимы между разными версиями Lua.

Стандартные пути в официальном дистрибутиве могут меняться между версиями.

8.1-Несовместимости в языке
  • Приведение строк к числам в арифметических и побитовых операциях было удалено из основного языка. Строковая библиотека выполняет аналогичную работу для арифметических (но не для побитовых) операций с использованием строковых метаметодов. Однако, в отличие от предыдущих версий, новая реализация сохраняет неявный тип числа в строке. Например, результат "1" + "2" теперь является целым числом, а не числом с плавающей запятой.
  • Буквальные десятичные целочисленные константы,которые переполняются,считываются как плавающие числа,а не обводятся вокруг.Вы можете использовать шестнадцатеричную нотацию для таких констант,если хотите вернуть старое поведение (читать их как целые числа с обводкой).
  • Использование __lt для эмуляции __le было удалено. При необходимости этот метаметод должен быть определен явно.
  • Семантика числового цикла for по целым числам изменилась в некоторых деталях. В частности, управляющая переменная никогда не повторяется.
  • Метка для перехода не может быть объявлена ​​там, где видна метка с тем же именем, даже если эта другая метка объявлена ​​во включающем блоке.
  • При финализации объекта Lua не игнорирует __gc , которые не являются функциями. Будет вызываться любое значение, если оно присутствует. (Невозвратные значения будут генерировать предупреждение, как и любая другая ошибка при вызове финализатора.)
8.2-Несовместимости в библиотеках
  • Функция print не вызывает tostring для форматирования своих аргументов; вместо этого у него есть эта функциональная возможность. Вы должны использовать __tostring , чтобы изменить способ печати значений.
  • Генератор псевдослучайных чисел, используемый функцией math.random , теперь начинается с несколько случайного начального числа. Более того, он использует другой алгоритм.
  • По умолчанию функции декодирования в библиотеке utf8 не принимают суррогаты в качестве действительных кодовых точек. Дополнительный параметр в этих функциях делает их более разрешительными.
  • Параметры setpause и setstepmul функции collectgarbage устарели. Вы должны использовать новую опцию « incremental », чтобы установить их.
  • Функция io.lines теперь возвращает четыре значения вместо одного. Это может быть проблемой, когда он используется в качестве единственного аргумента для другой функции, которая имеет необязательные параметры, например, в load(io.lines(filename, "L")) . Чтобы решить эту проблему, вы можете заключить вызов в круглые скобки, чтобы довести количество результатов до одного.
8.3-Несовместимости в API
  • Полные пользовательские данные теперь имеют произвольное количество связанных пользовательских значений. Поэтому функции lua_newuserdata , lua_setuservalue и lua_getuservalue были заменены на lua_newuserdatauv , lua_setiuservalue и lua_getiuservalue , у которых есть дополнительный аргумент.

    Для совместимости старые имена по-прежнему работают как макросы,предполагающие одно единственное пользовательское значение.Однако обратите внимание,что пользовательские данные с нулевым значением пользователя более эффективны с точки зрения памяти.

  • У функции lua_resume есть дополнительный параметр. Этот параметр out возвращает количество значений наверху стека, которые были выданы или возвращены сопрограммой. (В предыдущих версиях этими значениями был весь стек.)
  • Функция lua_version возвращает номер версии вместо адреса номера версии. Ядро Lua должно правильно работать с библиотеками, использующими собственные статические копии одного и того же ядра, поэтому нет необходимости проверять, используют ли они одно и то же адресное пространство.
  • Константа LUA_ERRGCMM удалена. Ошибки в финализаторах никогда не распространяются; вместо этого они генерируют предупреждение.
  • Параметры LUA_GCSETPAUSE и LUA_GCSETSTEPMUL функции lua_gc устарели. Вы должны использовать новую опцию LUA_GCINC , чтобы установить их.

9-Полный синтаксис Lua

Вот полный синтаксис Lua в расширенном BNF. Как обычно в расширенной BNF, {A} означает 0 или более As, а [A] означает необязательный A. (Приоритеты операций см. в §3.4.8 ; описание терминалов Name, Numeral и LiteralString см. в § 3.1 .)

chunk ::= block

block ::= {stat} [retstat]

stat ::=  ‘;’ | 
	 varlist ‘=’ explist | 
	 functioncall | 
	 label | 
	 break | 
	 goto Name | 
	 do block end | 
	 while exp do block end | 
	 repeat block until exp | 
	 if exp then block {elseif exp then block} [else block] end | 
	 for Name ‘=’ exp ‘,’ exp [‘,’ exp] do block end | 
	 for namelist in explist do block end | 
	 function funcname funcbody | 
	 local function Name funcbody | 
	 local attnamelist [‘=’ explist] 

attnamelist ::=  Name attrib {‘,’ Name attrib}

attrib ::= [‘<’ Name ‘>’]

retstat ::= return [explist] [‘;’]

label ::= ‘::’ Name ‘::’

funcname ::= Name {‘.’ Name} [‘:’ Name]

varlist ::= var {‘,’ var}

var ::=  Name | prefixexp ‘[’ exp ‘]’ | prefixexp ‘.’ Name 

namelist ::= Name {‘,’ Name}

explist ::= exp {‘,’ exp}

exp ::=  nil | false | true | Numeral | LiteralString | ‘...’ | functiondef | 
	 prefixexp | tableconstructor | exp binop exp | unop exp 

prefixexp ::= var | functioncall | ‘(’ exp ‘)’

functioncall ::=  prefixexp args | prefixexp ‘:’ Name args 

args ::=  ‘(’ [explist] ‘)’ | tableconstructor | LiteralString 

functiondef ::= function funcbody

funcbody ::= ‘(’ [parlist] ‘)’ block end

parlist ::= namelist [‘,’ ‘...’] | ‘...’

tableconstructor ::= ‘{’ [fieldlist] ‘}’

fieldlist ::= field {fieldsep field} [fieldsep]

field ::= ‘[’ exp ‘]’ ‘=’ exp | Name ‘=’ exp | exp

fieldsep ::= ‘,’ | ‘;’

binop ::=  ‘+’ | ‘-’ | ‘*’ | ‘/’ | ‘
	 ‘&’ | ‘~’ | ‘|’ | ‘>>’ | ‘<<’ | ‘..’ | 
	 ‘<’ | ‘<=’ | ‘>’ | ‘>=’ | ‘==’ | ‘~=’ | 
	 and | or

unop ::= ‘-’ | not | ‘#’ | ‘~’


Lua

5.4

  • Справочное руководство по Lua 5.4

Маленькая книга о Lua

image

Карлу Сегуину — с благодарностью за «маленькую библиотеку».

Введение

Есть прекрасная книга «Программирование на Lua», написанная автором языка. Это настоящий учебник, освещающий все тонкости и особенности языка. Там даже упражнения есть. Будете ли вы её читать просто для ознакомления с еще одним языком программирования? Я думаю, что нет.

Другая крайность — это «Lua за 60 минут». Я видел подобные статьи и не могу однозначно сказать, приносят ли они пользу или причиняют вред. Для меня знакомство с Lua началось именно с этой статьи, но я понял из нее только то, что нуждаюсь в более глубоких источниках, чем прокомментированные сниппеты.

«Маленькие книги» Карла Сегуина настолько точно отвечают на мой запрос, что я набрался смелости присоединиться к жанру. Если моя «маленькая книга» будет хотя бы наполовину настолько хороша, то я сочту задачу выполненной.

Читайте подряд. Последовательность изложения отличается от канонической, зато вам ни разу не встретится раздражающее «вы поймете это потом». Это быстрое чтиво, простое и легкое (надеюсь!), которое поможет понять, стоит ли переходить к более глубокому изучению или уже пора остановиться и больше не тратить время.

Применимость

Применимость — это ответ на вопрос «зачем». Существует совершенно безумное количество языков программирования и у каждого есть свой ответ на этот вопрос. Lua появился в недрах университетской кафедры компьютерной графики как встраиваемый язык для приложений на С.

Описывая Lua, автор называет его расширяемым (то есть умеющим вызывать функции приложения) и расширяющим (то есть умеющим предоставлять свои функции приложению). Будучи сам написан на C, он легко встраивается в C-приложения и взаимодействует с ним. Это совсем не означает, что единственная аудитория языка это программисты на C, но… да, им он полезней всего.

При этом Lua предлагает и самостоятельный интерпретатор, который может использовать внешние динамические библиотеки — как написанные специально для Lua, так и любые другие — с помощью механизма FFI. Во втором случае, правда, дополнительно потребуется библиотека expat или интерпретатор LuaJIT (написанный другим автором, но полностью совместимый с оригинальным Lua), в котором не только реализован FFI, но есть еще и JIT-компиляция, многократно ускоряющий и без того быстрый Lua.

Кстати, о быстродействии. Lua быстр — настолько, что из интерпретаторов с ним могут сравниться лишь Python и JavaScript, а LuaJIT в некоторых задачах их даже опережает (но это спорный момент, поэтому лучше остановимся на «сравним по быстродействию»).

Lua компактен — настолько, что его используют в маршрутизаторах Miktotik, телефонных станциях Asterisk и даже «зашивают» в микросхемы.

И он прост. Его включают в сетевые сканеры nmap и wireshark, он работает внутри баз данных Redis и Tarantool, на нем пишут плагины для медиаплеера Rhythmbox… даже биржевых ботов на платформе Quik. Это немного похоже на «бойцовский клуб» — многие используют Lua, ничего о нем не зная, просто как часть платформы.

Кроме того, на Lua неплохо получаются веб-приложения — благодаря реализованной в проекте OpenResty интеграции c Nginx получаются весьма выносливые к нагрузкам системы. Такие как AliExpress, например. Или CloudFlare.

С легкостью создаются настольные приложения с графическим интерфейсом — с помощью IUP, QT, wxWidgets, FLTK или чего-нибудь еще. Не только под Linux, но и под Windows, MacOS или вообще без графической среды, в «сыром» framebuffer.

Графика, «то, ради чего» Lua писался изначально, открывает дорогу в игровую индустрию. Love2D, специально написанный игровой движок, работает не только в настольных операционных системах, но и на мобильных устройствах. Unity, трехмерный игровой движок, лежит в основе довольно серьезных игровых проектов. Для игр класса AAA, правда, потребуется написать платформу на более «машинном» языке, но внутри MTA, World of Warcraft и S.T.A.L.K.E.R. используется все тот же Lua.

А вот задачи реального времени на Lua делать нельзя, даже если использовать микросхемы NodeMCU. Это интерпретатор для виртуальной машины и доступа к реальному оборудованию у него нет. Не поможет даже написать «подложку» с прямым доступом и управлять ею (в играх так и делается), это будет лишь приближением к желаемому — виртуальная машина асинхронно выполняет свои задачи и вы никогда не сможете выполнить что-то «прямо сейчас». Как бы ни была мала эта задержка, «взрослые» задачи реального времени не для Lua. Оставим это Erlang-у.

Установка

Можно собрать Lua из исходников с сайта lua.org. Это самый суровый путь, но если вы линуксоид, то вам не привыкать. При помощи MinGW, CygWin или Windows Platform SDK вы точно так же можете собрать его и для Windows. Но это необязательно — во многих дистрибутивах Linux бинарные сборки доступны из менеджера пакетов. Для Windows их тоже можно найти и скачать из Интернета. Ну, или установить при помощи Chocolatey — тамошнего аналога пакетного менеджера.

Запуск программ

Если просто запустить интерпретатор — он запустится в интерактивном режиме, где весьма неплох в качестве калькулятора.

$ lua
Lua 5.3.5  Copyright (C) 1994-2018 Lua.org, PUC-Rio
> 2 + 2 * 2
6

В интерактивном режиме можно поэкспериментировать со всеми возможностями языка, но для реального применения лучше все-таки написать программу и передавать имя с файлом программы интерпретатору для выполнения.

$ lua hello.lua
Hello, World!

Содержимое файла hello.lua — каноничная первая программа. Те, кто считает, что первая программа должна быть более осмысленной, упускают самое главное её предназначение — проверить работоспособность установленной среды.

print ("Hello, world!") -- print это функция вывода из стандартной библиотеки

Вы можете использовать Lua в командных файлах Linux, как и любой другой скриптовый язык.

#!/usr/bin/env lua
print "Hello, world!" -- для вывода одной строки можно обойтись без скобок

Сохраните эту программу в файл hello.lua, выполните команду chmod +x hello.lua, и вы сможете запускать её прямо из консоли:

$ ./hello.lua
Hello, world!

Комментарии

Самая бесполезная часть программы — текст комментариев для интерпретатора не существует. Но это еще и самый лучший способ объяснить, что происходит, прямо в коде.

-- это короткий комментарий
--[[ длинные комментарии нужны не только для долгих "лирических отступлений",
     но и позволяют временно "отключить" часть кода, не удаляя его ]]

Переменные

Переменные не нужно специально объявлять или каким-то образом инициализировать: при первой записи они создается, при повторных — перезаписывается, по завершении программы — удаляется.

Также нет необходимости определять тип данных, которые будут хранится в переменной — при каждой записи определяется тип сохраняемого значения и выделяется требуемое количество памяти.

Имена переменных могут содержать латинские буквы, цифры (но не могут с них начинаться) и знак подчеркивания. Нет никаких специальных правил — СamelCase, isHungarianNotation, underscore_delimited_names или любой другой способ могут быть использованы без ограничений и в любом сочетании.

Имена переменных (как и остальные языковые конструкции) регистрозависимы — and является зарезервированным словом и не может использоваться в качестве переменной, а And и AND — могут.

Единственное пожелание автора — не использовать переменные, которые начинаются со знака подчеркивания, за которым следуют заглавные буквы. Внутренние переменные могут совпасть с вашими и программа может повести себя, скажем так, странно.

Выражения

Для записи данных используется операция присваивания. Математически это не равенство, а линейное отображение справа налево. Слева от знака операции должно быть имя переменной, справа — выражение.

4 = a -- это не работает; слева от знака операции только имена переменных

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

a = 4 -- теперь у нас есть переменная "a" и в ней содержится число 2
a, b = 4, 8 -- так тоже можно; это называется множественным присваиванием
a = 2 + 2 * 2-- значение можно записать как результат математической операции
a = b / 2 -- чтение переменных происходит при использовании их в выражениях
a, b = b, a -- простой и элегантный способ поменять значения переменных местами
i = i + 1 -- просто увеличение значения переменной на 1
x = a  = b -- теперь и X, и A равны 4

Когда в переменной пропадает нужда — она уничтожается сборщиком мусора. В общем, все как везде, где произносятся слова «автоматическая сборка мусора»

Пустое значение

Оно всего одно и записывается латинским словом nil, что переводится как «ничего». Это не нуль, не пустая строка и не нулевой указатель. Это ничего. Его не существует.

При чтении несуществующей переменной вы получите nil. При записи в переменную значения nil вы эту переменную уничтожите. А если вы попробуете присвоить nil несуществующей переменной, ничего не произойдет. Вообще.

Логические значения

Их два — true («истина») и false («ложь»).

a, b = true, false -- их можно напрямую присваивать

-- они могут быть результатом логических операций
x = not b -- true; логическое НЕ
x = a and b -- false; логическое И
x = a or b -- true; логическое ИЛИ

--[[ можно выполнять эти операции и с другими типами данных,
     логика в этом случае несколько своеобразная, но она есть ]]

x = not nil -- true; nil аналогичен false
x = not 0 -- false; все остальные значения ведут себя как true, даже 0
x = 4 and 5 -- 5; and возвращает первый аргумент, если он ложный, иначе второй
x = 4 or 5 -- 4; or возвращает первый аргумент, если он НЕ ложный, иначе второй
x = 3 and 4 or 5 -- 4; это аналог тернарной операции "a?b:c" в Си

Числа

Для хранения чисел Lua использует 64-битные блоки памяти. Это аналогично типу double в С. В версии 5.3 появились целые числа, но это мало что меняет. Единственная разница — вы можете явно создать число с плавающей точкой, если используете десятичную точку, после которой может быть и нуль.

n = 42 -- ответ на Главный вопрос жизни, вселенной и всего такого
n = 42.0 -- это значение типа double, а не int
n = 0x2A -- он же в шестнадцатиричной системе счисления
n = 420e-1 -- в экспоненциальной форме
n = 0x2A0p-1 -- или даже в экспоненциальной форме шестнадцатиричного счисления
x = 3.1415926 -- у вещественных чисел дробная часть отделяется точкой
y = .5 -- нуль перед десятичным разделителем необязателен
z = -500 -- как и в случае с отрицательными значениями; фактически это "z = 0 - 500"

Для чисел доступны основные арифметические операции:

a = 2 + 2 -- 4; сложение
a = 2 - 2 -- 0; вычитание
a = 2 * 2 -- 4; умножение
a = 2 ^ 2 -- 4; возведение в степень
a = 5 / 2 -- 2.5; деление
a = 5 //2 -- 2; целочисленной деление (без дробной части)
a = 5 % 2 -- 1; остаток от целочисленного деления
a = 2 + 2 * 2 -- 6; приоритеты операций, как в школе
a =(2 + 2)* 2 -- 8; но его так же можно менять скобками

А также операции сравнения:

a, b = 3, 4

x = a  > b -- false; больше
x = a  < b -- true; меньше
x = a >= b -- false; больше или равно
x = a <= b -- true; меньше или равно
x = a == b -- false; равно
x = a ~= b -- true; не равно

Строки

Строка — это массив байт. Строка может содержать нулевые символы и это не станет признаком конца строки, символы могут быть в любой кодировке или вообще непечатными. В строках можно хранить любые двоичные данные. Между строками в 1 байт и строками в 10 мегабайт нет разницы. И нет ограничений, кроме размера оперативной памяти.

Строки нельзя менять, но можно перезаписывать. То есть нельзя влезть в строку и поменять в ней пятый байт, но можно сформировать такую же строку, но с другим пятым байтом и записать в ту же переменную. Как вы понимаете, это означает копирование строки со всеми накладными расходами этой операции.

s = "Для записи строк используются кавычки"
s = 'одиночные кавычки тоже допустимы'
s = "можно комбинировать 'одиночные' и "двойные" кавычки в любом сочетании"
s = [[А если в тексте много строк,
никто не мешает хранить его в строке целиком.
Да, при помощи двойных квадратных скобок, как в многострочным комментарии.]]

с = #'Hello' -- 5; операция # позволяет узнать длину строки (количество байт, не букв!)
s = "строки"..'можно'..[[объединять]] -- это называется "конкатенация"

w = [[ 
Экранирование специальных символов делается как в Си:
a - звонок (beep)
b - возврат на одну позицию (backspace)
r - перевод страницы
n - перевод строки (newline)
r - возврат каретки (carriage return)
t - горизонтальная табуляция
v - вертикальная табуляция
\ - обратная косая черта (backslash)
" - одиночная кавычка
' - двойная кавычка
]]

-- строки можно сравнивать
x = s == w -- false, строки НЕ равны
y = s ~= w -- true,  строка НЕ равны

Привидение типов

Если к числу применяются строковые операции, оно превращается в строку. И наоборот, если это возможно.

a = 100..500 -- 100500
a = "10" + 7 -- 17
a = 12 + "a" -- ошибка

Это спорная идея. Лучше использовать явные преобразования и не рисковать.

a = tostring( 10 ) -- "10"; строка
b = tonumber("10") --  10 ; число
c = tonumber("XY") --  nil

Таблицы

Используйте таблицы, если вам нужны массивы, словари, структуры, объекты. Таблицы — это всё. Хотя, на самом деле, таблицы это просто способ хранить множество пар «ключ-значение», а все остальное — это то, какие вы выбираете ключи и какие значения.

Если в качестве ключей использовать натуральные числа, то это будет массив.

a = {42,616,999}
a[#a + 1] = "Земля-616" -- функция # возвращает количество элементов
print (a[4]) --> Земля-616

А еще «натуральные» означает, что нумерация индексов начинается с единицы, а не с нуля. Программистам на C нужно всегда об этом помнить.

Массивы не надо объявлять и под них не выделяется пространство. И индексы у них необязательно последовательные. Можно использовать большие числа и не бояться, что закончится память — в таблице будет только те ключи, которые вы внесли. Если ключи в таблице не являются натуральной последовательностью, то это разряженный массив.

a = {}
a[13] = 666
a[100500] = "Alpha Centauri"
a[42] = "The Ultimate Question of Life, the Universe, and Everything answer"
print(#a) --> 0, для разряженных массивов операция # неприменима

Значения элементов таблицы сами могут быть таблицами. Ограничений на вложенность никаких, таблицы могут быть многомерными матрицами.

a = {
    {101,102,103},
    {201,202,203},
    {301,302,303}, -- эта запятая лишняя, но это допустимо
}
print (a[2][3]) --> 203

Индексы могут быть строковыми. С их помощью можно реализовать ассоциативные массивы (их еще называют словарями).

a = {
    ["one"] = 1,["two"] = 2,["three"] = 3, four = 4, five = "пять"
}
print (a.one) --> 1
print (a["four"]) --> 4

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

Фрагменты

У английского «chunk» есть масса смыслов. Если вы во имя точности предпочитаете англицизмы, используйте «чанк» — вполне сложившийся термин (в описании, например, HTTP-протокола). Если нет, то «фрагмент» ничем не хуже. Суть в том, что это просто какое-то количество инструкций языка без начала, конца и какого-то обрамления.

a = 1
print (a) --> 1
a = a + 1
b = a / 2
print (b) --> 1

В программе на Lua не нужно как-то специально оформлять «точку входа», как это делается в C функцией main(). Что касается точки выхода, то её тоже нет — выполнив все инструкции фрагмента, интерпретатор останавливается.

Вы, конечно, можете написать что-то вроде этого:

function main ()
    a = 1
    print (a) --> 1
    a = a + 1
    b = a / 2
    print (b) --> 1
end
main ()

…но особого смысла в этом нет. Да, сначала объявится функция, но её потом все равно надо будет явным образом вызвать после объявления. И интерпретатору совершенно без разницы, какое у нее имя и надо ли её вообще выполнять.

Полученный код выполняется «как есть», все остальное — на ваше усмотрение.

Блоки и области видимости

Несколько инструкций (тот самый «фрагмент») можно разместить между словами do и end. Это то же самое, что фигурные скобки в C/C++ или begin .. end в Pascal. Блок, группирующий инструкции, является отдельной исполнимой сущностью и применим везде, где применима единичная инструкция.

По умолчанию все переменные глобальные, но при помощи слова local можно явным образом определять переменные, доступные только внутри блока.

a = 1
do
    local a = 10
    print(a) --> 10
    b = 2
end
print(a) --> 1
print(b) --> 2

Блоки могут быть вложенными. Во внутренних блоках локальные переменные внешних доступны так же, как и глобальные. При создании внутри блока глобальной переменной она будет доступна везде.

Управление потоком

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

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

Безусловный переход

Есть разные мнения по поводу инструкции goto, но иногда она действительно полезна. Она имеет неудобный синтаксис и массу ограничений — нельзя «впрыгивать» внутрь блока, «выпрыгивать» из функции и «впрыгивать» внутрь области видимости локальной переменной. Это сделано намеренно — чтобы не возникало желания ею пользоваться без насущной необходимости.

do
    a = 0
    ::loop:: -- имя метки подчиняется тем же правилам, что и имена переменных
        a = a + 1 -- это не блок, отступы просто для читаемости
        if a % 2 == 0 then goto continue end
        if a > 100 then goto exit end -- прыгать внутрь области видимости переменной нельзя
        print (a)
        ::continue::
    goto loop
    local b = -a
    ::exit:: 
    -- но если после метки до конца области видимости ничего нет, то можно
end

Условия

Программа не всегда должна делать одно и то же.

В зависимости от условий поток выполнения может разделяться на ветки, поэтому условное выполнение называется ветвлением. Каждая ветка может разделяться ещё на ветки и так далее.

if a > 0 then
    print ("'a' is positive") -- если выполняется уловие
end

if b > 0 then 
    print ("'b' is positive")
else
    print ("'b' is NOT positive") -- есть не выполняется
end

if c > 0 then
    print ("'c' is positive")
elseif c < 0 then -- это вместо switch-case, elseif-ов может быть много
    print ("'c' is negative")
else
    print ("'c' is zero")
end    

Циклы

Циклы нужны для многократного повторения одинаковых действий.

Цикл с предусловием проверяют условие повторения и выполняют блок, пока оно истинно. Циклы с постусловием сначала выполняют блок, а потом проверяют, достигнуто ли условие завершения.

while false do 
    print ('Hello?') 
end -- не выполнится ни разу

repeat 
    print ('yes, hello!') 
until true -- выполнится один раз

Цикл с выходом из середины не имеют граничных условий, поэтому в блоке необходимо явным образом предусмотреть выход. При помощи break можно «выпрыгнуть» из цикла, функции и вообще из любого блока. Нет continue, но его можно реализовать с помощью goto.

a = 0
while true do
    ::continue::
    a = a + 2
    if a == 13 then -- правильно выбирайте условие выхода из цикла!
        break 
    end
    if a % 10 == 0 then goto continue end -- пропускаем всё, кратное 10
    print (a)
end

В цикле со счётчиком некоторая переменная изменяет своё значение от заданного начального значения до конечного значения с некоторым шагом, и для каждого значения этой переменной блок выполняется один раз.

for i = 0,9,1 do -- если шаг равен 1, третий параметр можно пропустить
    print(i)
end
print(i) --> nil; счетчик является локальной переменной и снаружи не доступен

Совместный цикл задает выполнение некоторой операции для объектов из множества.

x = {4, 8, 15, 16, 23, 42}
for k,v in ipairs(x)
    print ('code #'..k..' is '..v) 
end
print(k,v) --> nil    nil

Функции

В последнем примере ipairs() это функция. И не просто функция, а итератор. Она получает таблицу и при первом вызове возвращает её первое значение, а при последующих — второй, третье и так далее.

Работает она примерно так:

x = {4, 8, 15, 16, 23, 42}
function values(t)
    local i = 0
    return function() 
        i = i + 1 
        return t[i] -- мы могли бы возвращать еще и i, но ipairs у нас уже есть
    end
end
for v in values(x) do -- обратите внимание, что здесь мы тоже обходимся без ключа
    print (v)
end

Этот коротенький пример сразу дает нам массу информации.

Во-первых, функции являются значениями первого класса. То есть их можно присваивать переменным, передавать параметром в другие функции и использовать в качестве возвращаемого значения.

sum = function (a,b)
    return a + b
end
print (sum (2,2)) --> 4

function mul (a, b) -- более привычный способ записи всего лишь "семантический сахар"
    return a*b
end
print (mul (2,2)) --> 4

Во-вторых, значение не знает имя переменной, в котором оно содержится. Таким образом все функции анонимны. Но не всегда…

function fact(n)
    if n == 0 then return 1 else return n*fact(n-1) end
end

В-третьих, возвращаемых значений может быть несколько. Не один, не два, а столько, сколько захочет вернуть функция. Если при этом мы используем множественное присваивание, то можем получить все значения. Если имен переменных меньше — то «лишние» значения будут отброшены. А если больше — то они получат nil.

Ну, и четвертых, функция является блоком со своей областью видимости для локальных переменных, имея доступ к переменным глобальным. А, будучи объявлена внутри другого блока, локальные переменные внешнего блока воспринимает как глобальные. Это и позволяет нам создавать замыкания — то есть функции, сохраняющие контекст. Весь контекст, без уточнений. Будьте благоразумны и не создавайте лишние сущности.

Кстати, кроме ipairsв стандартной библиотеке Lua есть еще pairs — более общий итератор, который позволяет работать с любыми таблицами, не только с массивами. Но в случае с массивами мы получим значения не по возрастанию ключей, а произвольно.

Сопрограммы

Прежде, чем мы перейдем к сопрограммам (для вас, любители англицизмов, это «корутины»), несколько слов о многозадачности.

Мы уже говорили об графе состояний, исполнителе и потоке выполнения. В многозадачном алгоритме исполнителей несколько и у каждого из них — свое состояние и свой путь в графе состояний. Многопоточные алгоритмы — просто другое название для многозадачных.

Не так важно, выполняются ли потоки разными физическими процессорами или разными потоками одного, переключаются ли они операционной системой, «главным» потоком или явно передают управление друг другу — главное, что каждый поток (строго говоря «нить», от английского «thread» — для англоманов «тред») имеет свое состояние.

В Lua реализована «совместная многопоточность», когда потоки явно уступают выполнение друг другу и сохраняют состояние до следующего момента, когда выполнение столь же явно будет передано им снова. Никакого разделения на физические процессоры или совместного использования процессорного времени. Никакой вытесняющей многозадачности, неблокирующего доступа, семафором, диспетчеров. Только явная передача управление и сохранение состояния. Это логическая многозадачность — на самом деле в любой момент времени выполняется только один поток. Просто их несколько и они переключаются между собой.

c = coroutine.create(
  function (t)
    local i = coroutine.yield("initialized")
    repeat 
      i = coroutine.yield(t[i])
    until not t[i]
    return "finished"
  end
)
print (c,coroutine.status(c)) --> thread: 0x416e52a8    suspended
s = {2,3,5,7,11,13,17,19}
print (coroutine.resume(c,s)) --> true    initialized
print (coroutine.resume(c,1)) --> true    2
print (coroutine.resume(c,3)) --> true    5
print (coroutine.resume(c,9)) --> true    finished
print (c,coroutine.status(c)) --> thread: 0x416e52a8    dead
print (coroutine.resume(c,5)) --> false   cannot resume dead coroutine

В этом примере описан весь функционал сопрограмм. Давайте разберемся с ним, шаг за шагом.

Вызов corutine.create получает функцию и возвращает спящую («suspended») сопрограмму. Её можно «разбудить» вызовом coroutine.resume и тогда она начинает выполняться.

Выполняется она до тех пор, пока не встретиться вызов coroutine.yield. В этот момент управление возвращается к вызывающему потоку. Следующий вызов coroutine.resume восстановит выполнение сопрограммы, передавая управление ровно в то место, где она была приостановлена.

Сопрограмма может быть вечной — если она время от времени уступает выполнение, то в какой-то момент её можно просто не возобновить. Но она может и завершится и перейти в состояние «dead», возобновить из которого её будет уже невозможно.

Вызовы .resume и .yield могут не только передавать управление, но и обмениваться данными. В примере первый вызов .resume передает сопрограмме таблицу простых чисел, как если бы она передавалась функции в параметре, два других вызова передают данные внутрь сопрограммы, а она, в свою очередь, передает при помощи .yield обратно запрашиваемые значение из таблицы. При попытке получить значение за пределами таблицы сопрограмма заканчивается и возвращает сообщение при помощи return, как самая заурядная функция.

Вот, собственно, и все. Эта простая реализация дает возможность реализовывать многозадачные алгоритмы даже не в многозадачной среде. Впрочем, никто не мешает вам создать на С приложение на с «настоящей» многопоточностью и запустить по виртуальной машине в каждом потоке, предоставив им возможность вызывать специально написанные потокобезопасные функции вашего приложения.

ООП, «которого нет»

Структура с методами это простейший вариант объекта. Метод это функция, сохраненная в элементе таблицы.

a = {
    name = "Nick",
    sayHello = function (t)
        print ("Hello, "..t.name)
    end
}
a.sayHello(a) --> Hello, Nick
a:sayHello() --> Hello, Nick

Обратите внимание на две последние строчки. Они выполняют одно и то же, но по разному.

Чтобы функция знала, с какой таблицей она работает, ей это надо сообщить. В первом случае таблица явно передается параметром, во втором (когда используется двоеточие вместо точки) имя таблицы неявно передается первым параметром.

Есть несколько способов определять методы.

a = {
    name = "Nick",
    whoami = function (t) -- метод можно определить сразу в таблице
        return t.name
    end
}
-- а можно и отдельно от неё
function a.hello(t,name) -- здесь таблица передается в явном виде
    local me = name or t.whoami()
    print("Hello, "..me)
end

function a:bye(name)
    local me = name or self.name -- а здесь появляется "магическая" переменная self
    print("Goodbye, "..me)
end

-- способ вызова метода не зависит от того, как он был определен
a:hello() --> Hello, Nick
a.bye(a) --> Goodbye, Nick
a.hello(a,"John") --> Hello, John
a:bye("John") --> Goodbye, John
print(a:whoami()) --> Nick

Все это тоже семантический сахар.

Метатаблицы

Латинское «meta» буквально означает «после» в том смысле, в каком слово «метафизика» означает «не только физика». Метатаблица способна менять обычное поведение других таблиц.

a,b = {},{}
setmetatable (a,b) -- назначаем одну таблицу метатаблицей для другой
print (getmetatable (a) == b) --> true

b.x = 2

print (a.x) --> 1
print (getmetatable(a).x) --> 2

Что же нам это дает? В описанном примере — практические ничего. Вся сила метатаблиц в метаметодах.

Метаметоды

Это «магические» методы, которые позволяют менять существующее поведение таблицы. «Магические» они потому, что их логика зависит от того, как они называются.

t = {
    a = 42
}
print (t.a) --> 42
print (t.b) --> nil; стандартное поведение таблицы
-- создадим метатаблицу с измененной логикой
mt = {
    -- этот метод вызывается при чтении несуществующей переменной
    __index = function (t,k) 
        return k.." : ключ отсуствует"
    end
}
setmetatable (t,mt) -- задаем метатаблицу для нашей таблицы и повторяем те же действия
-- теперь таблица ведет себя иначе
print (t.a) --> 42
print (t.b) --> b: ключ отсуствует"

Если вы попытаетесь прочесть из таблицы значение по несуществующему ключу, вы получите nil. Но если у таблицы есть метатаблица, а в ней — метод __index, то будет вызван он.

t, mt = {}, {}
t.a.b = 42 -- ошибка: t.a равно nil, а не пустая таблица
-- определяем новую логику
function mt:__index(k)
    self[k] = {}
    setmetatable (self[k], mt)
    return self[k]
end
setmetatable (t,mt) -- и применяем её к нашей таблице
t.a.b.l.e = 42 -- больше никаких проблем с таблицами любой вложенности
print (t.a.b.l.e) --> 42

Наследование:

n = {name = "Nick"}
j = {name = "John"}
m = {
    __index = m, -- если присвоить этому методу таблицу, поиск ключа будет вестить в ней
    hello = function (t)
        print ("Hello, "..t.name)
    end
}
setmetatable(n,m)
setmetatable(j,m)
n:hello() --> ошибка: вы пытаетесь вызвать метод 'hello' (а он равен nil)

Внимание! Это красивый, но неправильный пример.

И дело тут не в том, что __index вместо функции является таблицей (для этого «магического» метода это допустимо). И не в том, что элемент таблицы ссылается на саму таблицу — это тоже нормально. Просто до завершения объявления таблицы она не существует и метод __index не к чему «привязывать».

А вот правильный вариант:

n = {name = "Nick"}
j = {name = "John"}
m = { -- сначала создаем метатаблицу
    hello = function (t)
        print ("Hello, "..t.name)
    end
}
m.__index = m -- потом назначаем её
setmetatable(n,m)
setmetatable(j,m)
n:hello() --> Hello, Nick
j:hello() --> Hello, John

Здесь мы затрагиваем одну интересную особенность. Пока элемент не определен — он недоступен. Возможно, стоило бы разрешить «ранее связывание», чтобы первый вариант тоже был рабочим. Возможно, это даже будет сделано в будущем, но это уж как решит профессор Иерусалемски — автор и «пожизненный великодушный диктор» Lua.

Впрочем, для функций милостиво сделано исключение.

--[[ специально определяем функцию как переменную, 
     чтобы быть увереным, что тут нет никакого "скрытого сахара" ]]
fact = function (n)
    if n == 1 then
        return 1
    else
        return n * fact(n-1) -- формально определение функции еще не завершено
    end
end
print (fact(5)) --> 120; тем не менее, все работает (но только начиная с версии 5.3)

Не индексом единым…

m = {
    __index = function (t,k)
        print ("Чтение "..k)
        return t[k]
    end,
    __nexindex = function (t,k,v)
        print ("Запись "..k)
        t[k] = v
    end
}
a = {x = 12}
setmetatable (a,m)
print (a.x) --> 12
a.y = 1 --[[ операция уходит в бесконечный цикл и завершается, 
             когда интерпретатор это понимает]]

(простите, но это был еще один неправильный пример)

Вопреки ожиданиям, программа ведет себя не так, как ожидалось. Это потому, что при обращении к таблице сначала выполняется обращение к элементам, а потом (если их нет) идет поиск «альтернативной логики» в метатаблице (опять же, если она есть).

Если элементы существуют, интерпретатору нет необходимости обращаться к метаметодам. Но мы можем «вынудить» его это делать.

m = {
    __index = function (t,k)
        print ("Чтение "..k)
        return t.data[k]
    end,
    __newindex = function (t,k,v)
        print ("Запись "..k)
        t.data[k] = v
    end
}
a = {data = {}}

setmetatable (a,m)
a.x = 12    --> Запись x
print (a.x) --> Чтение x
            --> 12
a.y = 1     --> Запись y
print (a.z) --> Чтение z
            --> nil

Мы переносим значения таблицы в таблицу внутри таблицы. Этот прием позволяет перехватывать все операции чтения и записи в таблицу и менять их.

Или не позволять получать элементы, который мы посчитаем закрытыми, как в «классическом» ООП. Хотя на этот счет профессор высказался предельно ясно: «если вам нужны приватные свойства, просто не обращайтесь к ним«.

Арифметические метатметоды

  • __add: сложение (+)
  • __sub: вычитание (-)
  • __mul: умножение (*)
  • __div: деление (/)
  • __mod: остаток от деления (%)
  • __pow: возведение в степень (^)
  • __unm: унарный (одноместный) минус (-)
  • __idiv: целочисленное деление (//)

В общем случае, если операнды не числа и не строки (которые можно преобразовать в числа), то при выполнении операции будут искаться метаметоды сначала в первом (левом) операнде, а затем во втором (правом). Как только метаметод будет найден, ему передадутся оба операнда, а результат выполнения будет обрезан до одного значения. Иначе будет выдана ошибка.

Обратите внимание на то, что если нужный метаматод будет найдет во втором операнде, они все равно будут переданы в том порядке, в котором записаны в выражении. Эту ситуацию нужно предвидеть и корректно обработать.

Логические метаметоды

  • __band: битовое И (&)
  • __bor: битовое ИЛИ (|)
  • __bxor: битовое ИЛИ-НЕ (~)
  • __bnot: битовое одноместное НЕ (~)
  • __shl: битовый сдвиг влево (<<)
  • __shr: битовый сдвиг вправо (>>)

Логика схожая.

Строковые метаметоды

  • __concat: конкатенация (..)
  • __len: длина (#)

Разница в том, что метаметоды будут использоваться, если аргументы не строки и не числа (которые можно привести к строкам). Если в таблице отсутствует реализация __len , то будет вызвана стандартная функция #, а она, как мы помним, не везде применима.

Метаметоды сравнения

  • __eq: равенство (==)
  • __lt: меньше (<)
  • __le: меньше или равно (<=)

Тут немного веселее. Во-первых, оба операнда должны быть таблицами. Во-вторых, при встрече операций «больше» и «больше или равно», они предварительно будут «перевернуты» в «меньше» и «меньше или равно». В-третьих, результат будет преобразован к логическому типу (то есть к значениям true или false)

Метаметоды доступа

  • __index: чтение из таблицы
  • __newindex: запись в таблицу нового значения
  • __call: обращение к таблице как к функции
  • __gc: выполняется перед уничтожением таблицы сборщиком мусора

Тут надо заметить, что первые два метода вызываются только при обращении к отсутствующим элементам таблицы. Эти методы получают в параметрах саму таблицу и ключ.

Третий метод очень удобен в качестве «конструктора» — метода по умолчанию. Он получает в параметрах таблицу, за которой следуют все оригинальные аргументы вызова. Ну, а последний метод можно использовать в качестве «деструктора».

Перегрузка операций

Если при выполнении арифметической операции один из операндов является таблицей, то произойдет ошибка. Но с целой «колодой» метаметодов в рукаве мы можем это изменить.

Если один из операндов сложения является таблицей, интерпретатор будет искать метод __sum в его метатаблице. Если оба операнда отвечают этим требованиям — будет использован метаметод первого (левого) операнда.

odd  = {1,3,5,7,9} -- таблица нечетных чисел
even = {2,4,6,8} -- таблица четных чисел
set  = {
    __add = function (a,b)  -- передаются операдны операции сложения
        if type(b) ~= "table" then -- операнд может не быть таблицей
            a[#a + 1] = b -- тогда просто добавляем его ко множеству
        else -- в противном случае
            for _,v in pairs (b) do
                a[#a + 1] = v -- добавляем по одному все элементы этой таблицы
               end
           end
        return a
    end
}
setmetatable(odd,set) -- превращаем таблицы во "множества"
setmetatable(even,set)
even = even + 10 -- будьте осторожны, ситуацию "even = 10 + even" мы не предусмотрели
for _,v in pairs(odd + even) do
    print(v) -- сумма множеств представляем собой множество всех элементов подмножеств
end

Исходя их постулата «таблица это объект» можно реализовать перегрузку всех арифметических и логических операций, чтения и записи, вызова функции… но все это работает только для таблиц — мета-таблицы нельзя назначать никаким другим типам данных. Это сделано специально, чтобы не давать слишком много возможностей «выстрелить себе в ногу».

Стандартная библиотека

В Lua граница между языком и библиотеками очень четкая. Все, что не касается непосредственно языка, вынесено в стандартную библиотеку. Можно собрать Lua без нее и тогда ваша программа не сможет даже вывести на экран строку «привет, мир». Что является огромным преимуществом при использовании Lua внутри другого приложения в качестве встроенного языка, который должен уметь только то, что ему позволено и не оставит скрипту ни малейшего шанса «выбраться из песочницы».

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

Модули

Принцип повторного использования кода подразумевает, что написанный функционал может быть использован повторно. Примем необязательно автором. Отчуждаемый код — это модули, пакеты, библиотеки, все то, благодаря чему нам не нужно каждый раз писать все самим. Девиз «все уже украдено написано до нас» особенно близок адептам Python-а, но не чужд и нам.

local lunajson = require 'lunajson' -- теперь мы умеет работать с JSON

local jsonstr = '{"Hello":["lunajson",1.5]}'
local t = lunajson.decode(jsonstr)
print(t.Hello[2]) --> 1.5
print(lunajson.encode(t)) --> {"Hello":["lunajson",1.5]}

Разумеется, не все так просто. Для того, чтобы использовать пакет, он должен присутствовать в одном из мест, где его будет искать require.

В переменной package.path содержится строка с вариантами шаблона путей для поиска. Вы можете увидеть из при помощи команды print.

> print (package.path)
/usr/share/lua/5.3/?.lua;/usr/share/lua/5.3/?/init.lua;/usr/lib/lua/5.3/?.lua;/usr/lib/lua/5.3/?/init.lua;./?.lua;./?/init.lua

Подставьте вместо вопросительного знака имя модуля — и у вас будет список всех возможных файлов, который будет пытаться открыть команда require.

Это обычная переменная и её можно переопределить или дополнить прямо в программе. И после этого команда require будет исходить их её нового значения.

Проще всего разместить подключаемый модуль в той же директории, что и ваша программа. Создайте файл с именем module.lua и впишите в него следующее:

local complex = {
    __add = function (x, y)
        return {a = x.a + y.a, b = x.b + y.b}
    end,
    __tostring = function (z) 
        -- этот метаметод вызывается, когда с таблицей пытаются обращаться, как со строкой
        return z.a..'+'..z.b..'i'
    end
}
return function (a, b)
    z = {a = a, b = b}
    setmetatable (z, {
        __index = complex
    })
    return z
end

Теперь в своей программе вы можете написать так:

local complex = require "complex"

x = complex(3,2)
y = complex(4,5)
print (x + y) -- вот здесь перед выводом выполняется метатметод __tostring

Пакеты

Имя модуля может содержать точки. При поиске модуля точка превращается в разделитель директории (прямая косая черта для Linux и обратная — для Windows, операционные системы без иерархической файловой системы могут использовать знак подчеркивания). Пакет — это все дерево модулей в одной директории.

Глубина вложенности не важна, дерево пакета может быть довольно разветвленным. Модули пакета являются автономными и связаны только логически.

А если вы снова внимательно посмотрите на значение переменной package.path, то увидите там такую подстроку:

Это позволяет загружать пакет, в модуле init.lua которого будет выполняться загрузка его компонентов или другие действия инициализации.

Заключение

Теперь вы знаете, что такое Lua. Теперь переходите к «Программирование на Lua», той самой книге, о которой мы говорили в самом начале. Если вы решили включить Lua в свой инструментальный набор, эта книга станет для вас настольной. В том числе и потому, что в ней автор рассказывает, что и почему в Lua реализовано именно так, а не иначе.

А еще — там есть такой громадный пласт материала, как встраивание в приложение на C и взаимодействие к кодом, написанным на C. Я посчитал, что для «маленькой книги» это слишком глубокий материал.

Мы также обошли стороной luarocks — это пакетный менеджер, который Hisham Muhammad написал и поддерживает с 2006 года. Это не единственный менеджер пакетов, но для Lua он стал стандартом «де-факто». Строго говоря, он не является частью языка, поэтому я не стал его описывать. Так же, как ZeroBrane Studio, которая является великолепной IDE и удачным примером приложения, полностью написанного на Lua.

Засим откланиваюсь.
Спасибо, что дочитали.

Documentation for Fandom’s backported version of Scribunto. Mostly based on the MediaWiki version of the Lua reference manual around the time the extension became incompatible with MW 1.20.

Introduction

This manual documents Lua as it is used in MediaWiki with the Scribunto extension. Some parts are derived from the Lua 5.1 reference manual, which is available under an MIT-style license.

Copyright © 1994–2012 Lua.org, PUC-Rio.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the «Software»), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED «AS IS», WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

This derivative manual may also be copied under the terms of the same license.

Getting started

On a MediaWiki wiki with Scribunto enabled, create a page with a title starting with «Module:», for example «Module:Bananas». Into this new page, copy the following text:

local p = {}

function p.hello( frame )
    return "Hello, world!"
end

return p

Save that, then on another (non-module) page, write:

{{#invoke:Bananas|hello}}

Except that you should replace «Bananas» with whatever you called your module. This will call the «hello» function exported from that module. The {{#invoke:Bananas|hello}} will be replaced with the text that the function returned, in this case, «Hello, world!»

It’s generally a good idea to invoke Lua code from the context of a template. This means that from the perspective of a calling page, the syntax is independent of whether the template logic is implemented in Lua or in wikitext. It also avoids the introduction of additional complex syntax into the content namespace of a wiki.

Module structure

The module itself must return a table containing the functions that may be called by {{#invoke:}}. Generally, as shown above, a local variable is declared holding a table, functions are added to this table, and the table is returned at the end of the module code.

Any functions that are not added to this table, whether local or global, will not be accessible by {{#invoke:}}, but globals might be accessible from other modules loaded using require(). It is generally good style for the module to declare all functions and variables local.

Returning text

The module function should usually return a single string; whatever values are returned will be passed through tostring() and then concatenated with no separator. This string is incorporated into the wikitext as the result of the {{#invoke:}}.

At this point in the page parse, templates have already been expanded, parser functions and extension tags have already been processed, and pre-save transforms (e.g. signature tilde expansion and the pipe trick) have already happened. Therefore the module cannot use these features in its output text. For example, if a module returns "Hello, [[world]]! {{welcome}}", the page will read «Hello, world! {{welcome}}».

On the other hand, subst is handled at an earlier stage of processing, so with {{subst:#invoke:}} only other attempted substitutions will not be processed. Since the failed substitution will remain in the wikitext, they will then be processed on the next edit. This should generally be avoided.

Lua language

Tokens


Names (also called identifiers) in Lua can be any string of letters, digits, and underscores, not beginning with a digit. Names are case-sensitive; «foo», «Foo», and «FOO» are all different names.

The following keywords are reserved and may not be used as names:

  • and
  • break
  • do
  • else
  • elseif
  • end
  • false
  • for
  • function
  • if
  • in
  • local
  • nil
  • not
  • or
  • repeat
  • return
  • then
  • true
  • until
  • while

Names starting with an underscore followed by uppercase letters are reserved for internal Lua global variables.

Other tokens are:

  • #
  • %
  • (
  • )
  • *
  • +
  • ,
  • .
  • ..
  • /
  • :
  • ;
  • <
  • <=
  • =
  • ==
  • >
  • >=
  • [
  • ]
  • ^
  • {
  • }
  • ~=

A comment starts with a -- anywhere outside a string. If the -- is immediately followed by an opening long bracket, the comment continues to the corresponding closing long bracket; otherwise the comment runs to the end of the current line.

-- A comment in Lua starts with a double-hyphen and runs to the end of the line.
--[[ Multi-line strings & comments
     are adorned with double square brackets. ]]
--[=[ Comments like this can have other --[[comments]] nested. ]=]

Data types

Lua is a dynamically-typed language, which means that variables and function arguments have no type, only the values assigned to them. All values carry a type.

Lua has eight basic data types, however only six are relevant to the Scribunto extension. The type() function will return the type of a value.

The tostring() function will convert a value to a string. The tonumber() function will convert a value to a number if possible, and otherwise will return nil. There are no explicit functions to convert a value to other data types.

Numbers are automatically converted to strings when used where a string is expected, e.g. when used with the concatenation operator. Strings recognized by tonumber() are automatically converted to numbers when used with arithmetic operators. When a boolean value is expected, all values other than nil and false are considered to be true.

nil

«Nil» is the data type of nil, which exists to represent the absence of a value. Nil may not be used as a key in a table, and there is no difference between an unassigned table key and a key assigned a nil value.

When converted to a string, the result is «nil». When converted to boolean, nil is considered false.

boolean

Boolean values are true and false.

When converted to a string, the result is «true» or «false». Unlike many other languages, boolean values may not be directly converted to numbers. And unlike many other languages, only false and nil are considered false for boolean conversion; the number 0 and the empty string are both considered true.

string

Lua strings are considered a series of 8-bit bytes; it is up to the application to interpret them in any particular encoding.

String literals may be delimited by either single or double quotes (' or "); like JavaScript and unlike PHP, there is no difference between the two. The following escape sequences are recognized: ‘a’ (bell), ‘b’ (backspace), ‘f’ (form feed), ‘n’ (newline), ‘r’ (carriage return), ‘t’ (horizontal tab), ‘v’ (vertical tab), ‘\’ (backslash), ‘»‘ (double quote), and »’ (single quote). A literal newline may also be included in a string by preceding it with a backslash. Bytes may also be specified using an escape sequence ‘ddd‘, where ddd is the decimal value of the byte in the range 0–255. To include Unicode characters using escape sequences, the individual bytes for the UTF-8 encoding must be specified; in general, it will be more straightforward to enter the Unicode characters directly.


Literal strings can also be defined using long brackets. An opening long bracket consists of an opening square bracket followed by zero or more equal signs followed by another opening square bracket, e.g. [[, [=[, or [=====[. The opening long bracket must be matched by the corresponding closing long bracket, e.g. ]], ]=], or ]=====]. Strings delimited by long brackets do not interpret escape sequences. As a special case, if an opening long bracket is immediately followed by a newline then the newline is not included in the string.

-- This long string
foo = [[
bartbaz
]]

-- Is equivalent to this normal string
bar = 'bar\tbazn'

Note that all strings are considered true when converted to boolean. This is unlike most other languages, where the empty string is usually considered false.

number

Lua has only one numeric type, which is typically represented internally as a double-precision floating-point value. In this format, integers between -9007199254740992 and 9007199254740992 may be represented exactly, while higher and lower numbers will suffer from round-off error.

Numbers are specified using a period (.) as a decimal separator and without grouping separators, e.g. 123456.78. Numbers may also be represented using E notation without spaces, e.g. 1.23e-10, 123.45e20, or 1.23E5. Integers may also be specified in hexadecimal notation using a 0x prefix, e.g. 0x3A.

Although NaN and positive and negative infinities are correctly stored and handled, Lua does not provide corresponding literals. The constant math.huge is positive infinity, as is a division such as 1/0, and a division such as 0/0 may be used to quickly generate a NaN.

Note that all numbers are considered true when converted to boolean. This is unlike most other languages, where the number 0 is usually considered false. When converted to a string, finite numbers are represented in decimal, possibly in E notation; NaN is «nan» or «-nan»; and infinities are «inf» or «-inf».

table

Lua tables are associative arrays, much like PHP arrays and JavaScript objects.

Tables are created using curly braces. The empty table is {}. To populate fields on creation, a comma- and/or semicolon-separated list of field specifiers may be included in the braces. These take any of several forms:

  • [expression1] = expression2 uses the (first) value of expression1 as the key and the (first) value of expression2 as the value.
  • name = expression is equivalent to ["name"] = expression
  • expression is roughly equivalent to [i] = expression, where i is an integer starting at 1 and incrementing with each field specification of this form. If this is the last field specifier and the expression has multiple values, all values are used; otherwise only the first is kept.

The fields in a table are accessed using bracket notation, e.g. table[key]. String keys that are also valid names may also be accessed using dot notation, e.g. table.key is equivalent to table['key']. Calling a function that is a value in the table may use colon notation, e.g. table:func( ... ), which is equivalent to table['func']( table, ... ).

sequence


An array (also named a sequence or a list) is a table with non-nil values for all positive integers from 1 to N and no value (nil) for all positive integers greater than N. Many Lua functions operate only on arrays, and ignore non-positive-integer keys.

Unlike PHP or JavaScript, however, any value except nil and NaN may be used as a key and no type conversion is performed. These are all valid and distinct:

-- Create table
t = {}

t["foo"] = "foo"
t.bar = "bar"
t[1] = "one"
t[2] = "two"
t[3] = "three"
t[12] = "the number twelve"
t["12"] = "the string twelve"
t[true] = "true"
t[tonumber] = "yes, even functions may be table keys"
t[t] = "yes, a table may be a table key too. Even in itself."

-- This creates a table roughly equivalent to the above
t2 = {
    foo = "foo",
    bar = "bar",
    "one",
    "two",
    [12] = "the number twelve",
    ["12"] = "the string twelve",
    "three",
    [true] = "true",
    [tonumber] = "yes, even functions may be table keys",
}
t2[t2] = "yes, a table may be a table key too. Even in itself."

Similarly, any value except nil may be stored as a value in a table. Storing nil is equivalent to deleting the key from the table, and accessing any key that has not been set will result in a nil value.

Note that tables are never implicitly copied in Lua; if a table is passed as an argument to the function and the function manipulates the keys or values in the table, those changes will be visible in the caller.

When converted to a string, the usual result is «table» but may be overridden using the __tostring metamethod. Even the empty table is considered true as a boolean.

function

Functions in Lua are first-class values: they may be created anonymously, passed as arguments, assigned to variables, and so on.

Functions are created using the function keyword, and called using parentheses. Syntactic sugar is available for named functions, local functions, and functions that act like member functions to a table. See Function declarations and Function calls below for details.

Lua functions are closures, meaning that they maintain a reference to the scope in which they are declared and can access and manipulate variables in that scope.

Like tables, if a function is assigned to a different variable or passed as an argument to another function, it is still the same underlying «function object» that will be called.

When converted to a string, the result is «function».

Unsupported types


The userdata type is used to hold opaque values for extensions to Lua written in other languages; for example, a userdata might be used to hold a C pointer or struct. To allow for use of Scribunto in hosting environments where custom-compiled code is not allowed, no such extensions are used.


The thread type represents the handles for coroutines, which are not available in Scribunto’s sandbox.

Metatables

Every table may have an associated table known as a metatable. The fields in the metatable are used by some operators and functions to specify different or fallback behavior for the table. The metatable for a table may be accessed using the getmetatable() function, and set with the setmetatable() function.

When being accessed for their meta functions, metatable fields are accessed as if with rawget().

Metatable fields that affect the table itself are:

__index
This is used when a table access t[key] would return nil. If the value of this field is a table, the access will be repeated in that table, i.e. __index[key] (which may invoke that table’s metatable’s __index). If the value of this field is a function, the function will be called as __index( t, key ). The rawget() function bypasses this metamethod.
__newindex
This is used when assigning a key to a table t[key] = value where rawget( t, key ) would return nil. If the value of this field is a table, the assignment will be repeated in that table, i.e. __newindex[key] = value (which may invoke that table’s metatable’s __newindex). If the value of this field is a function, the function will be called as __newindex( t, key, value ). The rawset() function bypasses this metamethod.
__call
This is used when function call syntax is used on a table, t( ··· ). The value must be a function, which is called as something like __call( t, ··· ).
__mode
This is used to make tables holding weak references. The value must be a string. By default, any value that is used as a key or as a value in a table will not be garbage collected. But if this metafield contains the letter ‘k’, keys may be garbage collected if there are no non-weak references, and if it contains ‘v’ values may be; in either case, both the corresponding key and value are removed from the table. Note that behavior is undefined if this field is altered after the table is used as a metatable.

Other metatable fields include:

  • __add
  • __sub
  • __mul
  • __div
  • __mod
  • __pow
  • __unm
  • __concat
  • __eq
  • __lt
  • __le
  • __pairs
  • __ipairs
  • __metatable*
  • __tostring

For binary operators, Lua looks first at the left argument’s metatable (if any) then the right’s when looking for a metamethod to use.

For relational operators, the metamethod is only used if the same function is specified in both arguments’ metatables. Different anonymous functions, even with identical body and closure, may not be considered the same.

Note: In Lua, all strings also share a single metatable, in which __index refers to the string table. This metatable is not accessible in Scribunto, nor is the referenced string table; the string table available to modules is a copy.

Variables

Variables are places that store values. There are three kinds of variables in Lua: global variables, local variables, and table fields.

A name represents a global or local variable (or a function argument, which is just a kind of local variable). Variables are assumed to be global unless explicitly declared as local using the local keyword. Any variable that has not been assigned a value is considered to have a nil value.

Global variables are stored in a standard Lua table called an environment; this table is often available as the global variable _G. It is possible to set a metatable for this global variable table; the __index and __newindex metamethods will be called for accesses of and assignments to global variables just as they would for accesses of and assignments to fields in any other table.

The environment for a function may be accessed using the getfenv() function and changed using the setfenv() function; in Scribunto, these functions are severely restricted if they are available at all.

Local variables are lexically scoped; see Local variable declarations for details.

Expressions

An expression is something that has values: literals (numbers, strings, true, false, nil), anonymous function declarations, table constructors, variable references, function calls, the vararg expression, expressions wrapped in parentheses, unary operators applied to expressions, and expressions combined with binary operators.

Most expressions have one value; function calls and the vararg expression can have any number. Note that wrapping a function call or vararg expression in parentheses will lose all except the first value.


Expression lists are comma-separated lists of expressions. All except the last expression are forced to one value (dropping additional values, or using nil if the expression has no values); all values from the last expression are included in the values of the expression list.

Arithmetic operators

Lua supports the usual arithmetic operators: addition, subtraction, multiplication, division, modulo, exponentiation, and negation.

When all operands are numbers or strings for which tonumber() returns non-nil, the operations have their usual meaning.

If either operand is a table with an appropriate metamethod, the metamethod will be called.

Operator Function Example Metamethod Notes
+ Addition a + b __add
Subtraction a — b __sub
* Multiplication a * b __mul
/ Division a / b __div division by zero is not an error; NaN or infinity will be returned
% Modulo a % b __mod defined as a % b == a - math.floor( a / b ) * b
^ Exponentiation a ^ b __pow non-integer exponents are allowed
Negation -a __unm

Relational operators

The relational operators in Lua are ==, ~=, <, >, <=, and >=. The result of a relational operator is always a boolean.

Equality (==) first compares the types of its operands; if they are different, the result is false. Then it compares the values: nil, boolean, number, and string are compared in the expected manner. Functions are equal if they refer to the exact same function object; function() end == function() end will return false, as it is comparing two different anonymous functions. Tables are by default compared in the same manner, but this may be changed using the __eq metamethod.

Inequality (~=) is the exact negation of equality.

For the ordering operators, if both are numbers or both are strings, they are compared directly. Next, metamethods are checked:

  • a < b uses __lt
  • a <= b uses __le if available, or if __lt is available then it is considered equivalent to not ( b < a )
  • a > b is considered equivalent to b < a
  • a >= b is considered equivalent to b <= a

If the necessary metamethods are not available, an error is raised.

Logical operators

The logical operators are and, or, and not. All use the standard interpretation where nil and false are considered false and anything else is considered true.

For and, if the left operand is considered false then it is returned and the second operand is not evaluated; otherwise the second operand is returned.

For or, if the left operand is considered true then it is returned and the second operand is not evaluated; otherwise the second operand is returned.

For not, the result is always true or false.

Note that and and or short circuit. For example, foo() or bar() will only call bar() if foo() returns false or nil as its first value.

Concatenation operator

The concatenation operator is two dots, used as a .. b. If both operands are numbers or strings, they are converted to strings and concatenated. Otherwise if a __concat metamethod is available, it is used. Otherwise, an error is raised.

Note that Lua strings are immutable and Lua does not provide any sort of «string builder», so a loop that repeatedly does a = a .. b will have to create a new string for each iteration and eventually garbage-collect the old strings. If many strings need concatenating, it may be faster to use string.format() or to insert all the strings into a sequence and use table.concat() at the end.

Length operator

The length operator is #, used as #a. If a is a string, it returns the length in bytes. If a is a sequence table, it returns the length of the sequence.

If a is a table that is not a sequence, the #a may return any value N such that a[N] is not nil and a[N+1] is nil, even if there are non-nil values at higher indexes. For example,

-- This is not a sequence, because a[3] is nil and a[4] is not
a = { 1, 2, nil, 4 }

-- This may output either 2 or 4.
-- And this may change even if the table is not modified.
mw.log( #a )

Operator precedence

Lua’s operator precedence, from highest to lowest:

  • ^
  • not # — (negation)
  • * / %
  • + — (subtraction)
  • ..
  • < > <= >= ~= ==
  • and
  • or

Within a precedence level, most binary operators are left-associative, i.e. a + b + c is interpreted as (a + b) + c. Exponentiation and concatenation are right-associative, i.e. a ^ b ^ c is interpreted as a ^ (b ^ c).

Function calls

Lua function calls look like those in most other languages: a name followed by a list of arguments in parentheses:

func( exp-list )

As is usual with expression lists in Lua, the last expression in the list may supply multiple argument values.

If the function is called with fewer values in the expression list than there are arguments in the function definition, the extra arguments will have a nil value. If the expression list contains more values than there are arguments, the excess values are discarded. It is also possible for a function to take a variable number of arguments; see Function declarations for details.

Lua also allows direct calling of a function return value, i.e. func()(). If an expression more complex than a variable access is needed to determine the function to be called, a parenthesized expression may be used in place of the variable access.

Lua has syntactic sugar for two common cases. The first is when a table is being used as an object, and the function is to be called as a method on the object. The syntax

table:name( exp-list )

is exactly equivalent to

table.name( table, exp-list )


The second common case is Lua’s method of implementing named arguments by passing a table containing the name-to-value mappings as the only positional argument to the function. In this case, the parentheses around the argument list may be omitted. This also works if the function is to be passed a single literal string. For example, the calls

func{ arg1 = exp, arg2 = exp }
func"string"

are equivalent to

func( { arg1 = exp, arg2 = exp } )
func( "string" )

These may be combined; the following calls are equivalent:

table:name{ arg1 = exp, arg2 = exp }
table.name( table, { arg1 = exp, arg2 = exp } )

Function declarations

The syntax for function declaration looks like this:

function ( var-list )
    block
end

All variables in var-list are local to the function, with values assigned from the expression list in the function call. Additional local variables may be declared inside the block.

When the function is called, the statements in block are executed after local variables corresponding to var-list are created and assigned values. If a return statement is reached, the block is exited and the values of the function call expression are those given by the return statement. If execution reaches the end of the function’s block without encountering a return statement, the result of the function call expression has zero values.

Lua functions are lexical closures. A common idiom is to declare «private static» variables as locals in the scope where the function is declared. For example,

-- This returns a function that adds a number to its argument
function makeAdder( n )
    return function( x )
        -- The variable n from the outer scope is available here to be added to x
        return x + n
    end
end

local add5 = makeAdder( 5 )
mw.log( add5( 6 ) )
-- prints 11


A function may be declared to accept a variable number of arguments, by specifying ... as the final item in the var-list:

function ( var-list, ... )
    block
end

Within the block, the varargs expression ... may be used, with the result being all the extra values in the function call. For example,

local join = function ( separator, ... )
    -- get the extra arguments as a table
    local args = { ... }
    -- get the count of extra arguments, correctly
    local n = select( '#', ... )
    return table.concat( args, separator, 1, n )
end

join( ', ', 'foo', 'bar', 'baz' )
-- returns the string "foo, bar, baz"

The select() function is designed to work with the varargs expression; in particular, select( '#', ... ) should be used instead of #{ ... } to count the number of values in the varargs expression.

Lua provides syntactic sugar to combine function declaration and assignment to a variable; see Function declaration statements for details.

Note that this will not work:

local factorial = function ( n )
    if n <= 2 then
        return n
    else
        return n * factorial( n - 1 )
    end
end

Since the function declaration is processed before the local variable assignment statement is complete, «factorial» inside the function body refers to the (probably undefined) global variable of that name. This problem may be avoided by declaring the local variable first and then assigning it in a subsequent statement, or by using the function declaration statement syntax.

Statements

A statement is the basic unit of execution: one assignment, control structure, function call, variable declaration, etc.

A chunk is a sequence of statements, optionally separated by semicolons. A chunk is basically considered the body of an anonymous function, so it can declare local variables, receive arguments, and return values.

A block is also a sequence of statements, just like a chunk. A block can be delimited to create a single statement: do block end. These may be used to limit the scope of local variables, or to add a return or break in the middle of another block.

Assignments

variable-list = expression-list

The variable-list is a comma-separated list of variables; the expression-list is a comma-separated list of one or more expressions. All expressions are evaluated before any assignments are performed, so a, b = b, a will swap the values of a and b.

Local variable declarations

local variable-list

local variable-list = expression-list

Local variables may be declared anywhere within a block. The first form, without an expression list, declares the variables but does not assign a value so all variables have nil as a value. The second form assigns values to the local variables, as described in Assignments above.

Note that visibility of the local variable begins with the statement after the local variable declaration. So a declaration like local x = x declares a local variable x and assigns it the value of x from the outer scope. The local variable remains in scope until the end of the innermost block containing the local variable declaration.

Control structures


while exp do block end

The while statement repeats a block as long as an expression evaluates to a true value.


repeat block until exp

The repeat statement repeats a block until an expression evaluates to a true value. Local variables declared inside the block may be accessed in the expression.


for name = exp1, exp2, exp3 do block end
for name = exp1, exp2 do block end

This first form of the for loop will declare a local variable, and repeat the block for values from exp1 to exp2 adding exp3 on each iteration. Note that exp3 may be omitted entirely, in which case 1 is used, but non-numeric values such as nil and false are an error. All expressions are evaluated once before the loop is started.

This form of the for loop is roughly equivalent to

do
    local var, limit, step = tonumber( exp1 ), tonumber( exp2 ), tonumber( exp3 )
    if not ( var and limit and step ) then error() end
    while ( step > 0 and var <= limit ) or ( step <= 0 and var >= limit ) do
        local name = var
        block
        var = var + step
    end
end

except that the variables var, limit, and step are not accessible anywhere else. Note that the variable name is local to the block; to use the value after the loop, it must be copied to a variable declared outside the loop.


for var-list in exp-list do block end

The second form of the for loop works with iterator functions. As in the first form, the exp-list is evaluated only once before beginning the loop.

This form of the for loop is roughly equivalent to

do
    local func, static, var = exp-list
    while true do
        local var-list = func( static, var )
        var = var1  -- var1 is the first variable in var-list
        if var == nil then break end
        block
    end
end

except that again the variables func, static, and var are not accessible anywhere else. Note that the variables in var-list are local to the block; to use them after the loop, they must be copied to variables declared outside the loop.

Often the exp-list is a single function call that returns the three values. If the iterator function can be written so it only depends on the parameters passed into it, that would be the most efficient. If not, Programming in Lua suggests that a closure be preferred to returning a table as the static variable and updating its members on each iteration.


if exp1 then block1 elseif exp2 then block2 else block3 end

Executes block1 if exp1 returns true, otherwise executes block2 if exp2 returns true, and block3 otherwise. The else block3 portion may be omitted, and the elseif exp2 then block2 portion may be repeated or omitted as necessary.


return expression-list

The return statement is used to return values from a function or a chunk (which is just a function). The expression-list is a comma-separated list of zero or more expressions.

Lua implements tail calls: if expression-list consists of exactly one expression which is a function call, the current stack frame will be reused for the call to that function. This has implication for functions that deal with the call stack, such as getfenv() and debug.traceback().

The return statement must be the last statement in its block. If for some reason a return is needed in the middle of a block, an explicit block do return end may be used.


break

The break statement is used to terminate the execution of a while, repeat, or for loop, skipping to the next statement after the loop.

The break statement must be the last statement in its block. If for some reason a break is needed in the middle of a block, an explicit block do break end may be used.

Function calls as statements

A function call may be used as a statement; in this case, the function is being called only for any side effects it may have (e.g. mw.log() logs values) and any return values are discarded.

Function declaration statements

Lua provides syntactic sugar to make declaring a function and assigning it to a variable more natural. The following pairs of declarations are equivalent

-- Basic declaration
function func( var-list ) block end
func = function ( var-list ) block end
-- Local function
local function func( var-list ) block end
local func; func = function ( var-list ) block end
-- Function as a field in a table
function table.func( var-list ) block end
table.func = function ( var-list ) block end
-- Function as a method in a table
function table:func( var-list ) block end
table.func = function ( self, var-list ) block end

Note the colon notation here parallels the colon notation for function calls, adding an implicit argument named «self» at the beginning of the arguments list.

Error handling

Errors may be «thrown» using the error() and assert() functions. To «catch» errors, use pcall() or xpcall(). Note that certain internal Scribunto errors cannot be caught in Lua code.

Garbage collection

Lua performs automatic memory management. This means that you have to worry neither about allocating memory for new objects nor about freeing it when the objects are no longer needed. Lua manages memory automatically by running a garbage collector from time to time to collect all dead objects (that is, objects that are no longer accessible from Lua) and objects that are only reachable via weak references. All memory used by Lua is subject to automatic management: tables, functions, strings, etc.

Garbage collection happens automatically, and cannot be configured from within Scribunto.

Standard libraries

The standard Lua libraries provide essential services and performance-critical functions to Lua. Only those portions of the standard libraries that are available in Scribunto are documented in this manual. See main standard libraries reference page for a description of the libraries and their methods.

Scribunto libraries

All Scribunto libraries are located in the table mw. See main Scribunto libraries reference page for a description of the libraries and their methods.

Differences from standard Lua

The following functions have been modified:

setfenv()
getfenv()
May not be available, depending on the configuration. If available, attempts to access parent environments will fail.
getmetatable()
Only works on tables as to prevent unauthorized access to parent environments.
tostring()
Pointer addresses of tables and functions are not provided. This is to make memory corruption vulnerabilities more difficult to exploit.
pairs()
ipairs()
Support for the __pairs and __ipairs metamethods (added in Lua 5.2) has been added.
pcall()
xpcall()
Certain internal errors cannot be intercepted.
require()
Can fetch certain built-in modules distributed with Scribunto, as well as modules present in the Module namespace of the wiki. To fetch wiki modules, use the full page name including the namespace. Cannot otherwise access the local filesystem.

The following packages are mostly removed. Only those functions listed are available:

package.*
Filesystem and C library access has been removed. Available functions and tables are:

package.loaded
package.preload
package.loaders
Loaders which access the local filesystem or load C libraries are not present. A loader for Module-namespace pages is added.
package.seeall()
os.*
There are some insecure functions in here, such as os.execute(), which can’t be allowed. Available functions are:

os.clock()
os.date()
os.difftime()
os.time()
debug.*
Most of the functions are insecure. Available functions are:

debug.traceback()

The following functions and packages are not available:

collectgarbage()
module()
coroutine.*
No application is known for us, so it has not been reviewed for security.
dofile()
loadfile()
io.*, file.*
Allows local filesystem access, which is insecure.
load()
loadstring()
These were omitted to allow for static analysis of the Lua source code. Also, allowing these would allow Lua code to be added directly to article and template pages, which was not desired for usability reasons.
print()
This was discussed on wikitech-l and it was decided that it should be omitted in favour of return values, to improve code quality. If necessary, mw.log() may be used to output information to the debug console.
string.dump()
May expose private data from parent environments.

Lua – Обзор

Lua – это расширяемый, легкий язык программирования, написанный на языке C. Он начался как собственный проект в 1993 году Роберто Иерусалимши, Луиса Энрике де Фигейредо и Вальдемара Селеса.

С самого начала оно было разработано как программное обеспечение, которое может быть интегрировано с кодом, написанным на C и других традиционных языках. Эта интеграция приносит много преимуществ. Он не пытается делать то, что C уже может сделать, но стремится предложить то, что C не очень хорошо: хорошее расстояние от аппаратного обеспечения, динамические структуры, отсутствие избыточности, простота тестирования и отладки. Для этого Lua имеет безопасную среду, автоматическое управление памятью и хорошие возможности для обработки строк и других видов данных с динамическим размером.

Характеристики

Lua предоставляет набор уникальных функций, которые отличают его от других языков. К ним относятся –

  • растяжимый
  • просто
  • эффективное
  • портативный
  • Свободно и открыто

Пример кода

print("Hello World!")

Как реализуется Lua?

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

И язык Луа, и его переводчик зрелые, маленькие и быстрые. Он произошел от других языков программирования и высочайших стандартов программного обеспечения. Небольшой размер позволяет запускать его на небольших устройствах с небольшим объемом памяти.

Учим Луа

Самый важный момент при изучении Lua – это сосредоточиться на концепциях, не теряясь в технических деталях.

Цель изучения языка программирования – стать лучшим программистом; то есть, чтобы стать более эффективным в разработке и внедрении новых систем и в поддержании старых.

Некоторые варианты использования Lua

  • Программирование игр

  • Сценарии в автономных приложениях

  • Сценарии в Интернете

  • Расширения и дополнения для баз данных, таких как MySQL Proxy и MySQL WorkBench

  • Системы безопасности, такие как система обнаружения вторжений.

Программирование игр

Сценарии в автономных приложениях

Сценарии в Интернете

Расширения и дополнения для баз данных, таких как MySQL Proxy и MySQL WorkBench

Системы безопасности, такие как система обнаружения вторжений.

Луа – Окружающая среда

Настройка локальной среды

Если вы все еще хотите настроить свою среду для языка программирования Lua, вам потребуются следующие программы, доступные на вашем компьютере: (а) текстовый редактор, (б) интерпретатор Lua и (в) компилятор Lua.

Текстовый редактор

Вам нужен текстовый редактор, чтобы напечатать вашу программу. Примеры нескольких редакторов: Блокнот Windows, команда «Редактирование ОС», Brief, Epsilon, EMACS и vim или vi.

Имя и версия текстового редактора могут различаться в разных операционных системах. Например, Блокнот будет использоваться в Windows, а vim или vi могут использоваться в Windows, а также в Linux или UNIX.

Файлы, которые вы создаете с помощью вашего редактора, называются исходными файлами, и эти файлы содержат исходный код программы. Исходные файлы для программ Lua обычно называются с расширением “.lua” .

Переводчик Lua

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

Компилятор Lua

Когда мы расширяем Lua на другие языки / приложения, нам нужен комплект разработки программного обеспечения с компилятором, совместимым с прикладным программным интерфейсом Lua.

Установка на Windows

Для среды Windows разработана отдельная среда разработки под названием «SciTE», которую можно скачать из https://code.google.com/p/luaforwindows/ раздела загрузки.

Запустите загруженный исполняемый файл, чтобы установить Lua IDE.

Поскольку это IDE, вы можете создавать и создавать код Lua, используя одно и то же.

В случае, если вы заинтересованы в установке Lua в режиме командной строки, вам необходимо установить MinGW или Cygwin, а затем скомпилировать и установить Lua в Windows.

Установка в Linux

Чтобы загрузить и собрать Lua, используйте следующую команду –

$ wget http://www.lua.org/ftp/lua-5.2.3.tar.gz
$ tar zxf lua-5.2.3.tar.gz
$ cd lua-5.2.3
$ make linux test

Чтобы установить на другие платформы, такие как aix, ansi, bsd, generic linux, mingw, posix, solaris, заменив Linux на make Linux, протестируйте его с соответствующим именем платформы.

У нас есть helloWorld.lua, в Lua следующим образом:

print("Hello World!")

Теперь мы можем создать и запустить файл Lua, скажем helloWorld.lua, переключившись на папку, содержащую файл, с помощью cd, а затем с помощью следующей команды:

$ lua helloWorld

Мы можем увидеть следующий вывод.

hello world

Установка в Mac OS X

Чтобы собрать / протестировать Lua в Mac OS X, используйте следующую команду –

$ curl -R -O http://www.lua.org/ftp/lua-5.2.3.tar.gz
$ tar zxf lua-5.2.3.tar.gz
$ cd lua-5.2.3
$ make macosx test

В некоторых случаях вы, возможно, не установили Xcode и инструменты командной строки. В таких случаях вы не сможете использовать команду make. Установите Xcode из магазина приложений Mac. Затем перейдите в «Настройки XCode», а затем переключитесь на «Загрузки» и установите компонент с именем «Инструменты командной строки». Как только процесс будет завершен, вам будет доступна команда make.

Вам не обязательно выполнять инструкцию «make macosx test». Даже без выполнения этой команды вы все равно можете использовать Lua в Mac OS X.

У нас есть helloWorld.lua, в Lua, следующим образом –

print("Hello World!")

Теперь мы можем создать и запустить файл Lua, скажем helloWorld.lua, переключившись на папку, содержащую файл, с помощью cd, а затем с помощью следующей команды:

$ lua helloWorld

Мы можем увидеть следующий вывод –

hello world

Lua IDE

Как упоминалось ранее, для Windows SciTE, IDE Lua является IDE по умолчанию, предоставляемой командой создателей Lua. Доступна альтернативная IDE от ZeroBrane Studio, которая доступна на нескольких платформах, таких как Windows, Mac и Linux.

Есть также плагины для затмения, которые позволяют разработку Lua. Использование IDE облегчает разработку благодаря таким функциям, как завершение кода, и настоятельно рекомендуется. Среда IDE также обеспечивает программирование в интерактивном режиме, аналогичное версии Lua для командной строки.

Lua – основной синтаксис

Давайте начнем создавать нашу первую программу Lua!

Первая программа Lua

Программирование в интерактивном режиме

Lua предоставляет режим, называемый интерактивным режимом. В этом режиме вы можете вводить инструкции одну за другой и получать мгновенные результаты. Это может быть вызвано в оболочке с помощью lua -i или просто команды lua. Как только вы введете это, нажмите Enter, и интерактивный режим будет запущен, как показано ниже.

$ lua -i 
$ Lua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Rio
quit to end; cd, dir and edit also available

Вы можете напечатать что-нибудь, используя следующее утверждение –

print("test")

Как только вы нажмете Enter, вы получите следующий вывод –

test

Программирование в режиме по умолчанию

Вызов интерпретатора с параметром имени файла Lua начинает выполнение файла и продолжается до завершения сценария. Когда сценарий завершен, интерпретатор больше не активен.

Давайте напишем простую программу Lua. Все файлы Lua будут иметь расширение .lua. Поэтому поместите следующий исходный код в файл test.lua.

Live Demo

print("test")

Предполагая, что среда lua настроена правильно, давайте запустим программу, используя следующий код –

$ lua test.lua

Мы получим следующий вывод –

test

Давайте попробуем другой способ выполнить программу Lua. Ниже приведен модифицированный файл test.lua –

Live Demo

#!/usr/local/bin/lua

print("test")

Здесь мы предположили, что в вашем каталоге / usr / local / bin есть интерпретатор Lua. Первая строка игнорируется интерпретатором, если она начинается со знака #. Теперь попробуйте запустить эту программу следующим образом:

$ chmod a+rx test.lua
$./test.lua

Мы получим следующий вывод.

test

Давайте теперь посмотрим на базовую структуру программы Lua, так что вам будет легко понять основные строительные блоки языка программирования Lua.

Жетоны в Луа

Программа Lua состоит из различных токенов, и токен является ключевым словом, идентификатором, константой, строковым литералом или символом. Например, следующий оператор Lua состоит из трех токенов:

io.write("Hello world, from ",_VERSION,"!n")

Отдельные токены –

io.write
(
   "Hello world, from ",_VERSION,"!n"
)

Комментарии

Комментарии подобны тексту помощи в вашей программе Lua, и интерпретатор их игнорирует. Они начинаются с – [[и заканчиваются символами -]], как показано ниже –

--[[ my first program in Lua --]]

Идентификаторы

Lua-идентификатор – это имя, используемое для идентификации переменной, функции или любого другого пользовательского элемента. Идентификатор начинается с буквы «от А до Я» или «от А до Я» или со знака подчеркивания «_», за которым следуют ноль или более букв, подчеркиваний и цифр (от 0 до 9).

Lua не допускает знаки препинания, такие как @, $ и% в идентификаторах. Lua – чувствительный к регистру язык программирования. Таким образом, рабочая сила и рабочая сила – два разных идентификатора в Lua. Вот несколько примеров допустимых идентификаторов:

mohd         zara      abc     move_name    a_123
myname50     _temp     j       a23b9        retVal

Ключевые слова

Следующий список показывает несколько зарезервированных слов в Lua. Эти зарезервированные слова не могут использоваться в качестве констант или переменных или любых других имен идентификаторов.

а также перерыв делать еще
ElseIf конец ложный за
функция если в местный
ноль не или же повторение
вернуть затем правда до тех пор
в то время как

Пробелы в Луа

Строка, содержащая только пробел, возможно, с комментарием, называется пустой строкой, и интерпретатор Lua полностью игнорирует ее.

Пробел – это термин, используемый в Lua для описания пробелов, вкладок, символов новой строки и комментариев. Пробелы отделяют одну часть оператора от другой и позволяют интерпретатору определить, где заканчивается один элемент в выражении, например, int, и начинается следующий элемент. Поэтому в следующем утверждении –

local age

Должен быть хотя бы один пробельный символ (обычно пробел) между местным и возрастом, чтобы переводчик мог их различить. С другой стороны, в следующем утверждении –

fruit = apples + oranges   --get the total fruit

Никаких пробельных символов не требуется между фруктами и = или между = и яблоками, хотя вы можете включить некоторые из них, если хотите, чтобы они были удобочитаемыми.

Lua – переменные

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

Имя переменной может состоять из букв, цифр и символа подчеркивания. Он должен начинаться либо с буквы, либо с подчеркивания. Прописные и строчные буквы различны, потому что Lua чувствителен к регистру. В Lua есть восемь основных типов ценностей:

В Lua, хотя у нас нет переменных типов данных, у нас есть три типа, основанные на области действия переменной.

  • Глобальные переменные – все переменные считаются глобальными, если они явно не объявлены как локальные.

  • Локальные переменные – когда тип указан как локальный для переменной, тогда его область действия ограничена функциями внутри их области.

  • Поля таблицы – это специальный тип переменной, который может содержать все, кроме nil, включая функции.

Глобальные переменные – все переменные считаются глобальными, если они явно не объявлены как локальные.

Локальные переменные – когда тип указан как локальный для переменной, тогда его область действия ограничена функциями внутри их области.

Поля таблицы – это специальный тип переменной, который может содержать все, кроме nil, включая функции.

Определение переменной в Lua

Определение переменной означает сообщить интерпретатору, где и сколько создать хранилище для переменной. Определение переменной имеет необязательный тип и содержит список из одной или нескольких переменных этого типа следующим образом:

type variable_list;

Здесь тип необязательно является локальным, или тип определяется как глобальный, а переменная_лист может состоять из одного или нескольких имен идентификаторов, разделенных запятыми. Некоторые действительные объявления показаны здесь –

local    i, j
local    i
local    a,c

Строка local i, j объявляет и определяет переменные i и j; который указывает интерпретатору создавать переменные с именами i, j и ограничивает область видимости локальным.

Переменные могут быть инициализированы (им присвоено начальное значение) в их объявлении. Инициализатор состоит из знака равенства, за которым следует постоянное выражение:

type variable_list = value_list;

Вот некоторые примеры:

local d , f = 5 ,10     --declaration of d and f as local variables. 
d , f = 5, 10;          --declaration of d and f as global variables. 
d, f = 10               --[[declaration of d and f as global variables. 
                           Here value of f is nil --]]

Для определения без инициализатора: переменные со статической продолжительностью хранения неявно инициализируются значением nil.

Объявление переменных в Lua

Как вы можете видеть в приведенных выше примерах, присваивания для кратных переменных следуют формату variable_list и value_list. В приведенном выше примере локального d, f = 5,10 у нас есть d и f в variable_list и 5 и 10 в списке значений.

Присвоение значения в Lua происходит как первая переменная в variable_list с первым значением в value_list и так далее. Следовательно, значение d равно 5, а значение f равно 10.

пример

Попробуйте следующий пример, где переменные были объявлены сверху, но они были определены и инициализированы внутри основной функции –

Live Demo

-- Variable definition:
local a, b

-- Initialization
a = 10
b = 30

print("value of a:", a)

print("value of b:", b)

-- Swapping of variables
b, a = a, b

print("value of a:", a)

print("value of b:", b)

f = 70.0/3.0
print("value of f", f)

Когда приведенный выше код создается и выполняется, он дает следующий результат –

value of a:	10
value of b:	30
value of a:	30
value of b:	10
value of f	23.333333333333

Lvalues ​​и Rvalues ​​в Lua

В Lua есть два вида выражений:

  • lvalue – Выражения, которые ссылаются на ячейку памяти, называются выражением «lvalue». Lvalue может отображаться как левая или правая сторона задания.

  • rvalue – термин rvalue относится к значению данных, которое хранится по некоторому адресу в памяти. Значение r – это выражение, которому не может быть присвоено значение, что означает, что значение r может появляться в правой части, но не в левой части присваивания.

lvalue – Выражения, которые ссылаются на ячейку памяти, называются выражением «lvalue». Lvalue может отображаться как левая или правая сторона задания.

rvalue – термин rvalue относится к значению данных, которое хранится по некоторому адресу в памяти. Значение r – это выражение, которому не может быть присвоено значение, что означает, что значение r может появляться в правой части, но не в левой части присваивания.

Переменные являются lvalues ​​и могут отображаться в левой части назначения. Числовые литералы являются r-значениями и поэтому не могут быть назначены и не могут отображаться слева. Следующее является действительным утверждением –

g = 20

Но следующее не является действительным утверждением и может привести к ошибке времени сборки –

10 = 20

В языке программирования Lua, помимо вышеупомянутых типов присваивания, можно иметь несколько значений l и r в одном и том же операторе. Это показано ниже.

g,l = 20,30

В приведенном выше утверждении 20 назначено для g и 30 назначено для l.

Lua – Типы данных

Lua – это язык с динамической типизацией, поэтому переменные не имеют типов, только значения имеют типы. Значения могут храниться в переменных, передаваться как параметры и возвращаться как результаты.

В Lua, хотя у нас нет переменных типов данных, но у нас есть типы для значений. Список типов данных для значений приведен ниже.

Sr.No Тип значения и описание
1

ноль

Используется для дифференциации значения от наличия данных или отсутствия (ноль) данных.

2

логический

Включает в себя значения true и false как значения. Обычно используется для проверки состояния.

3

число

Представляет действительные числа (числа с плавающей запятой двойной точности).

4

строка

Представляет массив символов.

5

функция

Представляет метод, который написан на C или Lua.

6

данные пользователя

Представляет произвольные данные Си.

7

нить

Представляет независимые потоки выполнения и используется для реализации сопрограмм.

8

Таблица

Представляет обычные массивы, таблицы символов, наборы, записи, графики, деревья и т. Д. И реализует ассоциативные массивы. Может содержать любое значение (кроме нуля).

ноль

Используется для дифференциации значения от наличия данных или отсутствия (ноль) данных.

логический

Включает в себя значения true и false как значения. Обычно используется для проверки состояния.

число

Представляет действительные числа (числа с плавающей запятой двойной точности).

строка

Представляет массив символов.

функция

Представляет метод, который написан на C или Lua.

данные пользователя

Представляет произвольные данные Си.

нить

Представляет независимые потоки выполнения и используется для реализации сопрограмм.

Таблица

Представляет обычные массивы, таблицы символов, наборы, записи, графики, деревья и т. Д. И реализует ассоциативные массивы. Может содержать любое значение (кроме нуля).

Тип Функция

В Lua есть функция type, которая позволяет нам узнать тип переменной. Некоторые примеры приведены в следующем коде.

Live Demo

print(type("What is my type"))   --> string
t = 10

print(type(5.8*t))               --> number
print(type(true))                --> boolean
print(type(print))               --> function
print(type(nil))                 --> nil
print(type(type(ABC)))           --> string

Когда вы создаете и запускаете вышеупомянутую программу, она дает следующий результат в Linux:

string
number
boolean
function
nil
string

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

Луа – Операторы

Оператор – это символ, который говорит переводчику выполнять определенные математические или логические манипуляции. Язык Lua богат встроенными операторами и предоставляет операторы следующего типа:

  • Арифметические Операторы
  • Операторы отношений
  • Логические Операторы
  • Разные Операторы

Этот урок объяснит один за другим арифметические, реляционные, логические и другие разные операторы.

Арифметические Операторы

Следующая таблица показывает все арифметические операторы, поддерживаемые языком Lua. Предположим, что переменная A содержит 10, а переменная B содержит 20, тогда –

Показать примеры

оператор Описание пример
+ Добавляет два операнда А + Б даст 30
Вычитает второй операнд из первого A – B даст -10
* Умножьте оба операнда А * Б даст 200
/ Разделите числитель на числитель Б / у даст 2
% Оператор модуля и остаток от целочисленного деления B% A даст 0
^ Экспонент Оператор принимает экспоненты А ^ 2 даст 100
Унарный – оператор действует как отрицание -А даст -10

Операторы отношений

Следующая таблица показывает все реляционные операторы, поддерживаемые языком Lua. Предположим, что переменная A содержит 10, а переменная B содержит 20, тогда –

Показать примеры

оператор Описание пример
== Проверяет, равны ли значения двух операндов или нет, если да, тогда условие становится истинным. (A == B) не соответствует действительности.
~ = Проверяет, равны ли значения двух операндов или нет, если значения не равны, тогда условие становится истинным. (A ~ = B) верно.
> Проверяет, больше ли значение левого операнда, чем значение правого операнда, если да, тогда условие становится истинным. (A> B) не соответствует действительности.
< Проверяет, меньше ли значение левого операнда, чем значение правого операнда, если да, тогда условие становится истинным. (A <B) верно.
> = Проверяет, больше ли значение левого операнда или равно значению правого операнда, если да, тогда условие становится истинным. (A> = B) не соответствует действительности.
<= Проверяет, меньше ли значение левого операнда или равно значению правого операнда, если да, тогда условие становится истинным. (A <= B) верно.

Логические Операторы

В следующей таблице приведены все логические операторы, поддерживаемые языком Lua. Предположим, что переменная A имеет значение true, а переменная B содержит значение false тогда –

Показать примеры

оператор Описание пример
а также Называется логический оператор И. Если оба операнда отличны от нуля, условие становится истинным. (А и В) ложно.
или же Вызывается логическим оператором ИЛИ. Если любой из двух операндов отличен от нуля, условие становится истинным. (А или В) это правда.
не Вызывается логическим оператором НЕ. Используйте для изменения логического состояния своего операнда. Если условие истинно, то оператор Логический НЕ будет делать ложь. ! (А и Б) это правда.

Разные Операторы

Различные операторы, поддерживаемые Lua Language, включают конкатенацию и длину .

Показать примеры

оператор Описание пример
.. Объединяет две строки. a..b, где a – «Hello», а b – «World», вернет «Hello World».
# Унарный оператор, который возвращает длину строки или таблицы. # “Привет” вернется 5

Приоритет операторов в Lua

Приоритет оператора определяет группировку терминов в выражении. Это влияет на то, как оценивается выражение. Некоторые операторы имеют более высокий приоритет, чем другие; например, оператор умножения имеет более высокий приоритет, чем оператор сложения –

Например, х = 7 + 3 * 2; Здесь x назначено 13, а не 20, потому что оператор * имеет более высокий приоритет, чем +, поэтому он сначала умножается на 3 * 2, а затем прибавляется к 7.

Здесь операторы с самым высоким приоритетом отображаются вверху таблицы, а операторы с самым низким – внизу. Внутри выражения операторы с более высоким приоритетом будут оцениваться первыми.

Показать примеры

категория оператор Ассоциативность
Одинарный не № – Справа налево
конкатенация .. Справа налево
Multiplicative * /% Слева направо
присадка + – Слева направо
реляционный <> <=> = == ~ = Слева направо
равенство == ~ = Слева направо
Логическое И а также Слева направо
Логическое ИЛИ или же Слева направо

Луа – Петли

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

Языки программирования предоставляют различные управляющие структуры, которые допускают более сложные пути выполнения.

Оператор цикла позволяет нам выполнять оператор или группу операторов несколько раз. Ниже приводится общая форма оператора цикла в большинстве языков программирования:

Петлевая архитектура

Lua предоставляет следующие типы циклов для обработки требований циклов.

Sr.No. Тип и описание петли
1 в то время как цикл

Повторяет оператор или группу операторов, пока данное условие выполняется. Он проверяет условие перед выполнением тела цикла.

2 для цикла

Выполняет последовательность операторов несколько раз и сокращает код, который управляет переменной цикла.

3 повторить … пока не получится

Повторяет операцию группы операторов до тех пор, пока не будет выполнено условие.

4 вложенные циклы

Вы можете использовать один или несколько циклов внутри любого другого цикла while, for или do.. while.

Повторяет оператор или группу операторов, пока данное условие выполняется. Он проверяет условие перед выполнением тела цикла.

Выполняет последовательность операторов несколько раз и сокращает код, который управляет переменной цикла.

Повторяет операцию группы операторов до тех пор, пока не будет выполнено условие.

Вы можете использовать один или несколько циклов внутри любого другого цикла while, for или do.. while.

Loop Control Statement

Оператор управления циклом изменяет выполнение от своей обычной последовательности. Когда выполнение покидает область действия, все автоматические объекты, созданные в этой области, уничтожаются.

Lua поддерживает следующие контрольные операторы.

Sr.No. Контрольное заявление и описание
1 заявление о нарушении

Завершает цикл и передает выполнение оператору сразу после цикла или переключателя.

Завершает цикл и передает выполнение оператору сразу после цикла или переключателя.

Бесконечный цикл

Цикл становится бесконечным, если условие никогда не становится ложным. Цикл while часто используется для этой цели. Поскольку мы прямо выражаем истинность условия, оно выполняется вечно. Мы можем использовать оператор break, чтобы разорвать этот цикл.

while( true )
do
   print("This loop will run forever.")
end

Луа – Принятие решений

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

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

Принятие решений в Lua

Язык программирования Lua предполагает любую комбинацию логических значений true и не-nil как true , и если это либо логическое значение false, либо nil , то оно принимается за значение false . Следует отметить, что в Lua ноль будет считаться истинным.

Язык программирования Lua предоставляет следующие типы операторов принятия решений.

Sr.No. Заявление и описание
1 если заявление

Оператор if состоит из логического выражения, за которым следует одно или несколько операторов.

2 если … еще заявление

За оператором if может следовать необязательный оператор else , который выполняется, когда логическое выражение имеет значение false.

3 вложенные операторы if

Вы можете использовать один оператор if или else if внутри другого оператора if или else if .

Оператор if состоит из логического выражения, за которым следует одно или несколько операторов.

За оператором if может следовать необязательный оператор else , который выполняется, когда логическое выражение имеет значение false.

Вы можете использовать один оператор if или else if внутри другого оператора if или else if .

Lua – Функции

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

Язык Lua предоставляет множество встроенных методов, которые может вызывать ваша программа. Например, метод print () для печати аргумента, переданного в качестве ввода в консоли.

Функция известна под разными именами, например, метод, подпрограмма, процедура и т. Д.

Определение функции

Общая форма определения метода в языке программирования Lua выглядит следующим образом:

optional_function_scope function function_name( argument1, argument2, argument3........, 
argumentn)
function_body
return result_params_comma_separated
end

Определение метода в языке программирования Lua состоит из заголовка метода и тела метода . Вот все части метода –

  • Необязательная область действия функции. Вы можете использовать ключевое слово local, чтобы ограничить область действия функции или игнорировать раздел области действия, что сделает ее глобальной функцией.

  • Имя функции – это фактическое имя функции. Имя функции и список параметров вместе составляют сигнатуру функции.

  • Аргументы – Аргумент похож на заполнитель. Когда вызывается функция, вы передаете значение аргументу. Это значение называется фактическим параметром или аргументом. Список параметров относится к типу, порядку и количеству аргументов метода. Аргументы необязательны; то есть метод может не содержать аргументов.

  • Тело функцииТело метода содержит коллекцию операторов, которые определяют, что делает метод.

  • Return – в Lua можно вернуть несколько значений, следуя ключевому слову return с возвращаемыми значениями через запятую.

Необязательная область действия функции. Вы можете использовать ключевое слово local, чтобы ограничить область действия функции или игнорировать раздел области действия, что сделает ее глобальной функцией.

Имя функции – это фактическое имя функции. Имя функции и список параметров вместе составляют сигнатуру функции.

Аргументы – Аргумент похож на заполнитель. Когда вызывается функция, вы передаете значение аргументу. Это значение называется фактическим параметром или аргументом. Список параметров относится к типу, порядку и количеству аргументов метода. Аргументы необязательны; то есть метод может не содержать аргументов.

Тело функцииТело метода содержит коллекцию операторов, которые определяют, что делает метод.

Return – в Lua можно вернуть несколько значений, следуя ключевому слову return с возвращаемыми значениями через запятую.

пример

Ниже приведен исходный код функции с именем max () . Эта функция принимает два параметра num1 и num2 и возвращает максимум между двумя –

--[[ function returning the max between two numbers --]]
function max(num1, num2)

   if (num1 > num2) then
      result = num1;
   else
      result = num2;
   end

   return result; 
end

Аргументы функции

Если функция должна использовать аргументы, она должна объявлять переменные, которые принимают значения аргументов. Эти переменные называются формальными параметрами функции.

Формальные параметры ведут себя как другие локальные переменные внутри функции и создаются при входе в функцию и уничтожаются при выходе.

Вызов функции

При создании функции Lua вы даете определение того, что должна делать функция. Чтобы использовать метод, вам нужно вызвать эту функцию для выполнения определенной задачи.

Когда программа вызывает функцию, управление программой передается вызываемой функции. Вызываемая функция выполняет определенную задачу, и когда выполняется оператор return или когда достигается конец ее функции, она возвращает управление программой обратно в основную программу.

Чтобы вызвать метод, вам просто нужно передать необходимые параметры вместе с именем метода, и если метод возвращает значение, вы можете сохранить возвращенное значение. Например –

Live Demo

function max(num1, num2)

   if (num1 > num2) then
      result = num1;
   else
      result = num2;
   end

   return result; 
end

-- calling a function
print("The maximum of the two numbers is ",max(10,4))
print("The maximum of the two numbers is ",max(5,6))

Когда мы запустим приведенный выше код, мы получим следующий вывод.

The maximum of the two numbers is 	10
The maximum of the two numbers is 	6

Назначение и передача функций

В Lua мы можем назначить функцию переменным, а также передать их в качестве параметров другой функции. Вот простой пример назначения и передачи функции в качестве параметра в Lua.

Live Demo

myprint = function(param)
   print("This is my print function -   ##",param,"##")
end

function add(num1,num2,functionPrint)
   result = num1 + num2
   functionPrint(result)
end

myprint(10)
add(2,5,myprint)

Когда мы запустим приведенный выше код, мы получим следующий вывод.

This is my print function -   ##	10	##
This is my print function -   ##	7	##

Функция с переменным аргументом

В Lua можно создавать функции с переменными аргументами, используя «…» в качестве параметра. Мы можем понять это, увидев пример, в котором функция возвращает среднее значение и может принимать переменные аргументы.

Live Demo

function average(...)
   result = 0
   local arg = {...}
   for i,v in ipairs(arg) do
      result = result + v
   end
   return result/#arg
end

print("The average is",average(10,5,3,4,5,6))

Когда мы запустим приведенный выше код, мы получим следующий вывод.

The average is	5.5

Луа – Струны

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

  • Символы между одинарными кавычками
  • Символы между двойными кавычками
  • Символы между [[и]]

Пример вышеупомянутых трех форм показан ниже.

Live Demo

string1 = "Lua"
print(""String 1 is"",string1)

string2 = 'Tutorial'
print("String 2 is",string2)

string3 = [["Lua Tutorial"]]
print("String 3 is",string3)

Когда мы запустим вышеуказанную программу, мы получим следующий вывод.

"String 1" is	Lua
String 2 is	Tutorial
String 3 is	"Lua Tutorial"

Символы Escape-последовательности используются в строке для изменения обычной интерпретации символов. Например, чтобы напечатать двойные кавычки (“”), мы использовали “в приведенном выше примере. Экранирующая последовательность и ее использование перечислены ниже в таблице.

Последовательность побега использование
а колокол
б возврат на одну позицию
е Под.стр
п Новая линия
р Возврат каретки
т табуляция
v Вертикальная вкладка
\ бэкслэш
» Двойные кавычки
» Одинарные кавычки
[ Левая квадратная скобка
] Правая квадратная скобка

Манипуляция строк

Lua поддерживает строку для работы со строками –

Sr.No. Метод и цель
1

string.upper (аргумент)

Возвращает заглавное представление аргумента.

2

string.lower (аргумент)

Возвращает строчное представление аргумента.

3

string.gsub (mainString, FindString, replaceString)

Возвращает строку путем замены вхождений findString на replaceString.

4

string.find (mainString, FindString,

optionalStartIndex, optionalEndIndex)

Возвращает начальный индекс и конечный индекс findString в основной строке и nil, если не найден.

5

string.reverse (Arg)

Возвращает строку путем обращения символов переданной строки.

6

String.Format (…)

Возвращает отформатированную строку.

7

string.char (arg) и string.byte (arg)

Возвращает внутренние числовые и символьные представления входного аргумента.

8

string.len (Arg)

Возвращает длину переданной строки.

9

string.rep (string, n))

Возвращает строку, повторяя одну и ту же строку n раз.

10

..

Таким образом, оператор объединяет две строки.

string.upper (аргумент)

Возвращает заглавное представление аргумента.

string.lower (аргумент)

Возвращает строчное представление аргумента.

string.gsub (mainString, FindString, replaceString)

Возвращает строку путем замены вхождений findString на replaceString.

string.find (mainString, FindString,

optionalStartIndex, optionalEndIndex)

Возвращает начальный индекс и конечный индекс findString в основной строке и nil, если не найден.

string.reverse (Arg)

Возвращает строку путем обращения символов переданной строки.

String.Format (…)

Возвращает отформатированную строку.

string.char (arg) и string.byte (arg)

Возвращает внутренние числовые и символьные представления входного аргумента.

string.len (Arg)

Возвращает длину переданной строки.

string.rep (string, n))

Возвращает строку, повторяя одну и ту же строку n раз.

..

Таким образом, оператор объединяет две строки.

Теперь давайте рассмотрим несколько примеров, чтобы точно увидеть, как ведут себя эти функции манипуляции со строками.

Манипуляция делами

Пример кода для управления строками в верхнем и нижнем регистре приведен ниже.

Live Demo

string1 = "Lua";

print(string.upper(string1))
print(string.lower(string1))

Когда мы запустим вышеуказанную программу, мы получим следующий вывод.

LUA
lua

Замена подстроки

Пример кода для замены вхождений одной строки другой приведен ниже.

Live Demo

string = "Lua Tutorial"

-- replacing strings
newstring = string.gsub(string,"Tutorial","Language")
print("The new string is "..newstring)

Когда мы запустим вышеуказанную программу, мы получим следующий вывод.

The new string is Lua Language

Нахождение и Реверс

Пример кода для поиска индекса подстроки и обратной строки приведен ниже.

Live Demo

string = "Lua Tutorial"

-- replacing strings
print(string.find(string,"Tutorial"))
reversedString = string.reverse(string)
print("The new string is",reversedString)

Когда мы запустим вышеуказанную программу, мы получим следующий вывод.

5	12
The new string is	lairotuT auL

Форматирование строк

Много раз в нашем программировании нам может потребоваться печатать строки в отформатированном виде. Вы можете использовать функцию string.format для форматирования вывода, как показано ниже.

Live Demo

string1 = "Lua"
string2 = "Tutorial"

number1 = 10
number2 = 20

-- Basic string formatting
print(string.format("Basic formatting %s %s",string1,string2))

-- Date formatting
date = 2; month = 1; year = 2014
print(string.format("Date formatting %02d/%02d/%03d", date, month, year))

-- Decimal formatting
print(string.format("%.4f",1/3))

Когда мы запустим вышеуказанную программу, мы получим следующий вывод.

Basic formatting Lua Tutorial
Date formatting 02/01/2014
0.3333

Символьные и байтовые представления

Пример кода для символьного и байтового представления, который используется для преобразования строки из строки во внутреннее представление и наоборот.

Live Demo

-- Byte conversion

-- First character
print(string.byte("Lua"))

-- Third character
print(string.byte("Lua",3))

-- first character from last
print(string.byte("Lua",-1))

-- Second character
print(string.byte("Lua",2))

-- Second character from last
print(string.byte("Lua",-2))

-- Internal Numeric ASCII Conversion
print(string.char(97))

Когда мы запустим вышеуказанную программу, мы получим следующий вывод.

76
97
97
117
117
a

Другие общие функции

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

Live Demo

string1 = "Lua"
string2 = "Tutorial"

-- String Concatenations using ..
print("Concatenated string",string1..string2)

-- Length of string
print("Length of string1 is ",string.len(string1))

-- Repeating strings
repeatedString = string.rep(string1,3)
print(repeatedString)

Когда мы запустим вышеуказанную программу, мы получим следующий вывод.

Concatenated string	LuaTutorial
Length of string1 is 	3
LuaLuaLua

Луа – Массивы

Массивы – это упорядоченное расположение объектов, которое может быть одномерным массивом, содержащим набор строк, или многомерным массивом, содержащим несколько строк и столбцов.

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

Одномерный массив

Одномерный массив может быть представлен с использованием простой структуры таблицы и может быть инициализирован и считан с использованием простого цикла for . Пример показан ниже.

Live Demo

array = {"Lua", "Tutorial"}

for i = 0, 2 do
   print(array[i])
end

Когда мы запустим приведенный выше код, мы получим следующий вывод.

nil
Lua
Tutorial

Как видно из приведенного выше кода, когда мы пытаемся получить доступ к элементу в индексе, которого нет в массиве, он возвращает nil. В Lua индексация обычно начинается с индекса 1. Но возможно также создавать объекты с индексом 0 и ниже 0. Массив с использованием отрицательных индексов показан ниже, где мы инициализируем массив с помощью цикла for .

Live Demo

array = {}

for i= -2, 2 do
   array[i] = i *2
end

for i = -2,2 do
   print(array[i])
end

Когда мы запустим приведенный выше код, мы получим следующий вывод.

-4
-2
0
2
4

Многомерный массив

Многомерные массивы могут быть реализованы двумя способами.

  • Массив массивов
  • Одномерный массив путем манипулирования индексами

Пример для многомерного массива 3. 3 показан ниже с использованием массива массивов.

Live Demo

-- Initializing the array
array = {}

for i=1,3 do
   array[i] = {}
	
   for j=1,3 do
      array[i][j] = i*j
   end
	
end

-- Accessing the array

for i=1,3 do

   for j=1,3 do
      print(array[i][j])
   end
	
end

Когда мы запустим приведенный выше код, мы получим следующий вывод.

1
2
3
2
4
6
3
6
9

Пример многомерного массива показан ниже с использованием манипулирования индексами.

Live Demo

-- Initializing the array

array = {}

maxRows = 3
maxColumns = 3

for row=1,maxRows do

   for col=1,maxColumns do
      array[row*maxColumns +col] = row*col
   end
	
end

-- Accessing the array

for row=1,maxRows do

   for col=1,maxColumns do
      print(array[row*maxColumns +col])
   end
	
end

Когда мы запустим приведенный выше код, мы получим следующий вывод.

1
2
3
2
4
6
3
6
9

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

Lua – Итераторы

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

Универсальный для Итератора

Универсальный для итератора предоставляет пары ключ-значение каждого элемента в коллекции. Простой пример приведен ниже.

Live Demo

array = {"Lua", "Tutorial"}

for key,value in ipairs(array) 
do
   print(key, value)
end

Когда мы запустим приведенный выше код, мы получим следующий вывод:

1  Lua
2  Tutorial

В приведенном выше примере используется итератор ipairs по умолчанию, предоставленный Lua.

В Lua мы используем функции для представления итераторов. Основываясь на поддержании состояния в этих функциях итератора, мы имеем два основных типа:

  • Итераторы без состояния
  • Stateful Iterators

Итераторы без состояния

По самому имени мы можем понять, что этот тип функции итератора не сохраняет никакого состояния.

Давайте теперь посмотрим на пример создания нашего собственного итератора, используя простую функцию, которая печатает квадраты n чисел.

Live Demo

function square(iteratorMaxCount,currentNumber)

   if currentNumber<iteratorMaxCount
   then
      currentNumber = currentNumber+1
      return currentNumber, currentNumber*currentNumber
   end
	
end

for i,n in square,3,0
do
   print(i,n)
end

Когда мы запустим вышеуказанную программу, мы получим следующий вывод.

1	1
2	4
3	9

Приведенный выше код может быть слегка изменен, чтобы имитировать работу ipairs функции итераторов. Это показано ниже.

Live Demo

function square(iteratorMaxCount,currentNumber)

   if currentNumber<iteratorMaxCount
   then
      currentNumber = currentNumber+1
      return currentNumber, currentNumber*currentNumber
   end
	
end

function squares(iteratorMaxCount)
   return square,iteratorMaxCount,0
end  

for i,n in squares(3)
do 
   print(i,n)
end

Когда мы запустим вышеуказанную программу, мы получим следующий вывод.

1	1
2	4
3	9

Stateful Iterators

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

Давайте теперь посмотрим на пример создания нашего собственного итератора, в котором мы будем использовать замыкания.

Live Demo

array = {"Lua", "Tutorial"}

function elementIterator (collection)

   local index = 0
   local count = #collection
	
   -- The closure function is returned
	
   return function ()
      index = index + 1
		
      if index <= count
      then
         -- return the current element of the iterator
         return collection[index]
      end
		
   end
	
end

for element in elementIterator(array)
do
   print(element)
end

Когда мы запустим вышеуказанную программу, мы получим следующий вывод.

Lua
Tutorial

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

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

Луа – Столы

Вступление

Таблицы – единственная структура данных, доступная в Lua, которая помогает нам создавать различные типы, такие как массивы и словари. Lua использует ассоциативные массивы, которые можно индексировать не только числами, но и строками, кроме nil. Таблицы не имеют фиксированного размера и могут расти в зависимости от наших потребностей.

Lua использует таблицы во всех представлениях, включая представление пакетов. Когда мы обращаемся к методу string.format, это означает, что мы обращаемся к функции форматирования, доступной в пакете string.

Представление и использование

Таблицы называются объектами и не являются ни значениями, ни переменными. Lua использует выражение конструктора {} для создания пустой таблицы. Должно быть известно, что не существует фиксированной связи между переменной, которая содержит ссылку на таблицу, и самой таблицей.

--sample table initialization
mytable = {}

--simple table value assignment
mytable[1]= "Lua"

--removing reference
mytable = nil

-- lua garbage collection will take care of releasing memory

Когда у нас есть таблица a с набором элементов и если мы присваиваем ее b , и a, и b ссылаются на одну и ту же память. Отдельная память не выделяется отдельно для b. Когда для a установлено значение nil, таблица все еще будет доступна для b. Когда нет ссылки на таблицу, сборщик мусора в Lua позаботится о том, чтобы очистить процесс, чтобы снова использовать эту нереференсную память.

Пример показан ниже для объяснения вышеупомянутых особенностей таблиц.

Live Demo

-- Simple empty table
mytable = {}
print("Type of mytable is ",type(mytable))

mytable[1]= "Lua"
mytable["wow"] = "Tutorial"

print("mytable Element at index 1 is ", mytable[1])
print("mytable Element at index wow is ", mytable["wow"])

-- alternatetable and mytable refers to same table
alternatetable = mytable

print("alternatetable Element at index 1 is ", alternatetable[1])
print("mytable Element at index wow is ", alternatetable["wow"])

alternatetable["wow"] = "I changed it"

print("mytable Element at index wow is ", mytable["wow"])

-- only variable released and and not table
alternatetable = nil
print("alternatetable is ", alternatetable)

-- mytable is still accessible
print("mytable Element at index wow is ", mytable["wow"])

mytable = nil
print("mytable is ", mytable)

Когда мы запустим вышеуказанную программу, мы получим следующий вывод:

Type of mytable is 	table
mytable Element at index 1 is 	Lua
mytable Element at index wow is 	Tutorial
alternatetable Element at index 1 is 	Lua
mytable Element at index wow is 	Tutorial
mytable Element at index wow is 	I changed it
alternatetable is 	nil
mytable Element at index wow is 	I changed it
mytable is 	nil

Таблица Манипуляция

Есть встроенные функции для работы с таблицами, и они перечислены в следующей таблице.

Sr.No. Метод и цель
1

table.concat (table [, sep [, i [, j]]])

Объединяет строки в таблицах на основе заданных параметров. Смотрите пример для деталей.

2

table.insert (таблица, [pos,] значение)

Вставляет значение в таблицу в указанной позиции.

3

table.maxn (таблица)

Возвращает самый большой числовой индекс.

4

table.remove (таблица [, pos])

Удаляет значение из таблицы.

5

table.sort (table [, comp])

Сортирует таблицу на основе необязательного аргумента компаратора.

table.concat (table [, sep [, i [, j]]])

Объединяет строки в таблицах на основе заданных параметров. Смотрите пример для деталей.

table.insert (таблица, [pos,] значение)

Вставляет значение в таблицу в указанной позиции.

table.maxn (таблица)

Возвращает самый большой числовой индекс.

table.remove (таблица [, pos])

Удаляет значение из таблицы.

table.sort (table [, comp])

Сортирует таблицу на основе необязательного аргумента компаратора.

Давайте посмотрим на некоторые примеры вышеуказанных функций.

Конкатенация таблиц

Мы можем использовать функцию concat для объединения двух таблиц, как показано ниже:

Live Demo

fruits = {"banana","orange","apple"}

-- returns concatenated string of table
print("Concatenated string ",table.concat(fruits))

--concatenate with a character
print("Concatenated string ",table.concat(fruits,", "))

--concatenate fruits based on index
print("Concatenated string ",table.concat(fruits,", ", 2,3))

Когда мы запустим вышеуказанную программу, мы получим следующий вывод:

Concatenated string 	bananaorangeapple
Concatenated string 	banana, orange, apple
Concatenated string 	orange, apple

Вставить и удалить

Вставка и удаление элементов в таблицах наиболее распространена при манипулировании таблицами. Это объясняется ниже.

Live Demo

fruits = {"banana","orange","apple"}

-- insert a fruit at the end
table.insert(fruits,"mango")
print("Fruit at index 4 is ",fruits[4])

--insert fruit at index 2
table.insert(fruits,2,"grapes")
print("Fruit at index 2 is ",fruits[2])

print("The maximum elements in table is",table.maxn(fruits))

print("The last element is",fruits[5])

table.remove(fruits)
print("The previous last element is",fruits[5])

Когда мы запустим вышеупомянутую программу, мы получим следующий вывод –

Fruit at index 4 is 	mango
Fruit at index 2 is 	grapes
The maximum elements in table is	5
The last element is	mango
The previous last element is	nil

Таблицы сортировки

Нам часто требуется сортировать таблицу в определенном порядке. Функции сортировки сортируют элементы в таблице по алфавиту. Пример для этого показан ниже.

Live Demo

fruits = {"banana","orange","apple","grapes"}

for k,v in ipairs(fruits) do
   print(k,v)
end

table.sort(fruits)
print("sorted table")

for k,v in ipairs(fruits) do
   print(k,v)
end

Когда мы запустим вышеуказанную программу, мы получим следующий вывод:

1	banana
2	orange
3	apple
4	grapes
sorted table
1	apple
2	banana
3	grapes
4	orange

Lua – модули

Что такое модуль?

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

Специальность модулей Lua

Использование таблиц в модулях помогает нам различными способами и позволяет нам манипулировать модулями так же, как мы манипулируем любой другой таблицей Lua. Благодаря возможности манипулировать модулями, он предоставляет дополнительные функции, для которых другим языкам нужны специальные механизмы. Благодаря этому бесплатному механизму модулей в Lua, пользователь может вызывать функции в Lua несколькими способами. Некоторые из них показаны ниже.

-- Assuming we have a module printFormatter
-- Also printFormatter has a funtion simpleFormat(arg)
-- Method 1
require "printFormatter"
printFormatter.simpleFormat("test")

-- Method 2
local formatter = require "printFormatter"
formatter.simpleFormat("test")

-- Method 3
require "printFormatter"
local formatterFunction = printFormatter.simpleFormat
formatterFunction("test")

В приведенном выше примере кода вы можете увидеть, насколько гибким является программирование на Lua без какого-либо специального дополнительного кода.

Требуемая функция

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

пример

Рассмотрим простой пример, где одна функция имеет математические функции. Давайте назовем этот модуль mymath.lua, а имя файла – mymath.lua. Содержание файла выглядит следующим образом –

local mymath =  {}

function mymath.add(a,b)
   print(a+b)
end

function mymath.sub(a,b)
   print(a-b)
end

function mymath.mul(a,b)
   print(a*b)
end

function mymath.div(a,b)
   print(a/b)
end

return mymath	

Теперь, чтобы получить доступ к этому модулю Lua в другом файле, скажем, moduletutorial.lua, вам нужно использовать следующий сегмент кода.

mymathmodule = require("mymath")
mymathmodule.add(10,20)
mymathmodule.sub(30,20)
mymathmodule.mul(10,20)
mymathmodule.div(30,20)

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

30
10
200
1.5

То, что нужно запомнить

  • Поместите оба модуля и файл, который вы запускаете, в один каталог.

  • Имя модуля и его имя файла должны совпадать.

  • Рекомендуется возвращать модули для функции require, и, следовательно, модуль должен быть предпочтительно реализован, как показано выше, даже если вы можете найти другие типы реализаций в другом месте.

Поместите оба модуля и файл, который вы запускаете, в один каталог.

Имя модуля и его имя файла должны совпадать.

Рекомендуется возвращать модули для функции require, и, следовательно, модуль должен быть предпочтительно реализован, как показано выше, даже если вы можете найти другие типы реализаций в другом месте.

Старый способ реализации модулей

Позвольте мне теперь переписать тот же пример более старым способом, который использует реализацию типа package.seeall. Это использовалось в Lua версий 5.1 и 5.0. Модуль mymath показан ниже.

module("mymath", package.seeall)

function mymath.add(a,b)
   print(a+b)
end

function mymath.sub(a,b)
   print(a-b)
end

function mymath.mul(a,b)
   print(a*b)
end

function mymath.div(a,b)
   print(a/b)
end

Использование модулей в moduletutorial.lua показано ниже.

require("mymath")
mymath.add(10,20)
mymath.sub(30,20)
mymath.mul(10,20)
mymath.div(30,20)

Когда мы запустим вышеупомянутое, мы получим тот же результат. Но рекомендуется использовать более старую версию кода, и предполагается, что она менее безопасна. Многие SDK, которые используют Lua для программирования, такие как Corona SDK, не рекомендовали использовать это.

Lua – Metatables

Метатабельная таблица – это таблица, которая помогает изменить поведение таблицы, к которой она присоединена, с помощью набора ключей и связанных мета-методов. Эти мета-методы являются мощной функциональностью Lua, которая включает такие функции, как –

  • Изменение / добавление функций к операторам на таблицах.

  • Поиск метатаблиц, когда ключ недоступен в таблице, с помощью __index в метатаблице.

Изменение / добавление функций к операторам на таблицах.

Поиск метатаблиц, когда ключ недоступен в таблице, с помощью __index в метатаблице.

Есть два важных метода, которые используются в обработке метатаблиц, которые включают в себя:

  • setmetatable (table, metatable) – этот метод используется для установки метатаблицы для таблицы.

  • getmetatable (table) – этот метод используется для получения метатаблицы таблицы.

setmetatable (table, metatable) – этот метод используется для установки метатаблицы для таблицы.

getmetatable (table) – этот метод используется для получения метатаблицы таблицы.

Давайте сначала посмотрим, как установить одну таблицу как метатабельную к другой. Это показано ниже.

mytable = {}
mymetatable = {}
setmetatable(mytable,mymetatable)

Приведенный выше код может быть представлен в одной строке, как показано ниже.

mytable = setmetatable({},{})

_индекс

Простой пример метатаблицы для поиска мета-таблицы, когда она недоступна в таблице, показан ниже.

Live Demo

mytable = setmetatable({key1 = "value1"}, {
   __index = function(mytable, key)
	
      if key == "key2" then
         return "metatablevalue"
      else
         return mytable[key]
      end
   end
})

print(mytable.key1,mytable.key2)

Когда мы запустим вышеуказанную программу, мы получим следующий вывод.

value1 metatablevalue

Давайте объясним, что произошло в приведенном выше примере, по шагам.

  • Таблица mytable здесь {key1 = “value1”} .

  • Metatable устанавливается для mytable, который содержит функцию для __index, которую мы называем метаметодом.

  • Метаметод выполняет простую работу по поиску индекса «key2», если он найден, он возвращает «metatablevalue», в противном случае возвращает значение mytable для соответствующего индекса.

Таблица mytable здесь {key1 = “value1”} .

Metatable устанавливается для mytable, который содержит функцию для __index, которую мы называем метаметодом.

Метаметод выполняет простую работу по поиску индекса «key2», если он найден, он возвращает «metatablevalue», в противном случае возвращает значение mytable для соответствующего индекса.

У нас может быть упрощенная версия вышеуказанной программы, как показано ниже.

mytable = setmetatable({key1 = "value1"}, 
   { __index = { key2 = "metatablevalue" } })
print(mytable.key1,mytable.key2)

__newindex

Когда мы добавляем __newindex в metatable, если ключи не доступны в таблице, поведение новых ключей будет определяться мета-методами. Простой пример, когда индекс метатаблицы устанавливается, когда индекс не доступен в основной таблице, приведен ниже.

Live Demo

mymetatable = {}
mytable = setmetatable({key1 = "value1"}, { __newindex = mymetatable })

print(mytable.key1)

mytable.newkey = "new value 2"
print(mytable.newkey,mymetatable.newkey)

mytable.key1 = "new  value 1"
print(mytable.key1,mymetatable.newkey1)

Когда вы запускаете вышеуказанную программу, вы получаете следующий вывод.

value1
nil	new value 2
new  value 1	nil

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

Другой пример, который обновляет ту же таблицу с помощью функции rawset, показан ниже.

Live Demo

mytable = setmetatable({key1 = "value1"}, {

   __newindex = function(mytable, key, value)
      rawset(mytable, key, """..value..""")
   end
})

mytable.key1 = "new value"
mytable.key2 = 4

print(mytable.key1,mytable.key2)

Когда мы запустим вышеуказанную программу, мы получим следующий вывод.

new value	"4"

rawset устанавливает значение без использования __newindex для metatable. Точно так же есть rawget, который получает значение без использования __index.

Добавление поведения оператора в таблицы

Простой пример объединения двух таблиц с помощью оператора + показан ниже –

Live Demo

mytable = setmetatable({ 1, 2, 3 }, {
   __add = function(mytable, newtable)
	
      for i = 1, table.maxn(newtable) do
         table.insert(mytable, table.maxn(mytable)+1,newtable[i])
      end
      return mytable
   end
})

secondtable = {4,5,6}

mytable = mytable + secondtable

for k,v in ipairs(mytable) do
   print(k,v)
end

Когда мы запустим вышеуказанную программу, мы получим следующий вывод.

1	1
2	2
3	3
4	4
5	5
6	6

Ключ __add включен в metatable для добавления поведения оператора +. Таблица ключей и соответствующего оператора показана ниже.

Sr.No. Режим и описание
1

__добавлять

Изменяет поведение оператора ‘+’.

2

__sub

Изменяет поведение оператора ‘-‘.

3

__mul

Изменяет поведение оператора ‘*’.

4

__div

Изменяет поведение оператора ‘/’.

5

__mod

Изменяет поведение оператора “%”.

6

__unm

Изменяет поведение оператора ‘-‘.

7

__concat

Изменяет поведение оператора ‘..’.

8

__eq

Изменяет поведение оператора ‘==’.

9

__lt

Изменяет поведение оператора ‘<‘.

10

__le

Изменяет поведение оператора ‘<=’.

__добавлять

Изменяет поведение оператора ‘+’.

__sub

Изменяет поведение оператора ‘-‘.

__mul

Изменяет поведение оператора ‘*’.

__div

Изменяет поведение оператора ‘/’.

__mod

Изменяет поведение оператора “%”.

__unm

Изменяет поведение оператора ‘-‘.

__concat

Изменяет поведение оператора ‘..’.

__eq

Изменяет поведение оператора ‘==’.

__lt

Изменяет поведение оператора ‘<‘.

__le

Изменяет поведение оператора ‘<=’.

__вызов

Добавление поведения вызова метода выполняется с помощью оператора __call. Простой пример, который возвращает сумму значений в основной таблице с переданной таблицей.

Live Demo

mytable = setmetatable({10}, {
   __call = function(mytable, newtable)
   sum = 0
	
      for i = 1, table.maxn(mytable) do
         sum = sum + mytable[i]
      end
	
      for i = 1, table.maxn(newtable) do
         sum = sum + newtable[i]
      end
	
      return sum
   end
})

newtable = {10,20,30}
print(mytable(newtable))

Когда мы запустим вышеуказанную программу, мы получим следующий вывод.

70

__нанизывать

Чтобы изменить поведение оператора print, мы можем использовать метаметод __tostring. Простой пример показан ниже.

Live Demo

mytable = setmetatable({ 10, 20, 30 }, {
   __tostring = function(mytable)
   sum = 0
	
      for k, v in pairs(mytable) do
         sum = sum + v
      end
		
      return "The sum of values in the table is " .. sum
   end
})
print(mytable)

Когда мы запустим вышеуказанную программу, мы получим следующий вывод.

The sum of values in the table is 60

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

Луа – сопрограммы

Вступление

Сопрограммы по своей природе являются совместными, что позволяет двум или более методам выполняться контролируемым образом. С сопрограммами в любой момент времени выполняется только одна сопрограмма, и эта запущенная сопрограмма только приостанавливает свое выполнение, когда она явно запрашивает приостановку.

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

Функции, доступные в сопрограммах

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

Sr.No. Метод и цель
1

coroutine.create (f)

Создает новую сопрограмму с функцией f и возвращает объект типа «поток».

2

coroutine.resume (co [, val1, …])

Возобновляет сопрограмму co и передает параметры, если таковые имеются. Возвращает статус операции и необязательные другие возвращаемые значения.

3

coroutine.running ()

Возвращает запущенную сопрограмму или ноль, если вызывается в основном потоке.

4

coroutine.status (со)

Возвращает одно из значений: запущено, нормально, приостановлено или не работает в зависимости от состояния сопрограммы.

5

coroutine.wrap (f)

Как и coroutine.create, функция coroutine.wrap также создает сопрограмму, но вместо возврата самой сопрограммы она возвращает функцию, которая при вызове возобновляет сопрограмму.

6

coroutine.yield (…)

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

coroutine.create (f)

Создает новую сопрограмму с функцией f и возвращает объект типа «поток».

coroutine.resume (co [, val1, …])

Возобновляет сопрограмму co и передает параметры, если таковые имеются. Возвращает статус операции и необязательные другие возвращаемые значения.

coroutine.running ()

Возвращает запущенную сопрограмму или ноль, если вызывается в основном потоке.

coroutine.status (со)

Возвращает одно из значений: запущено, нормально, приостановлено или не работает в зависимости от состояния сопрограммы.

coroutine.wrap (f)

Как и coroutine.create, функция coroutine.wrap также создает сопрограмму, но вместо возврата самой сопрограммы она возвращает функцию, которая при вызове возобновляет сопрограмму.

coroutine.yield (…)

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

пример

Давайте посмотрим на пример, чтобы понять концепцию сопрограмм.

Live Demo

co = coroutine.create(function (value1,value2)
   local tempvar3 = 10
   print("coroutine section 1", value1, value2, tempvar3)
	
   local tempvar1 = coroutine.yield(value1+1,value2+1)
   tempvar3 = tempvar3 + value1
   print("coroutine section 2",tempvar1 ,tempvar2, tempvar3)
	
   local tempvar1, tempvar2= coroutine.yield(value1+value2, value1-value2)
   tempvar3 = tempvar3 + value1
   print("coroutine section 3",tempvar1,tempvar2, tempvar3)
   return value2, "end"
	
end)

print("main", coroutine.resume(co, 3, 2))
print("main", coroutine.resume(co, 12,14))
print("main", coroutine.resume(co, 5, 6))
print("main", coroutine.resume(co, 10, 20))

Когда мы запустим вышеуказанную программу, мы получим следующий вывод.

coroutine section 1	3	2	10
main	true	4	3
coroutine section 2	12	nil	13
main	true	5	1
coroutine section 3	5	6	16
main	true	2	end
main	false	cannot resume dead coroutine

Что делает приведенный выше пример?

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

  • Сначала мы создаем сопрограмму и присваиваем ей имя переменной co, и сопрограмма принимает в качестве параметров две переменные.

  • Когда мы вызываем первую функцию возобновления, значения 3 и 2 сохраняются во временных переменных value1 и value2 до конца сопрограммы.

  • Чтобы вы поняли это, мы использовали tempvar3, который изначально равен 10, и он обновляется до 13 и 16 последующими вызовами сопрограмм, поскольку значение1 сохраняется как 3 на протяжении всего выполнения сопрограммы.

  • Первый файл coroutine.yield возвращает два значения 4 и 3 в функцию возобновления, которую мы получаем, обновляя входные параметры 3 и 2 в операторе yield. Он также получает истинный / ложный статус выполнения сопрограммы.

  • Еще одна вещь, связанная с сопрограммами, заключается в том, как обрабатываются следующие параметры вызова возобновления в приведенном выше примере; Вы можете видеть, что переменная coroutine.yield получает параметры следующего вызова, что обеспечивает мощный способ выполнения новой операции с сохранением существующих значений параметров.

  • Наконец, как только все операторы в сопрограммах будут выполнены, последующие вызовы вернутся в false и оператор «не может возобновить мертвую сопрограмму» в качестве ответа.

Сначала мы создаем сопрограмму и присваиваем ей имя переменной co, и сопрограмма принимает в качестве параметров две переменные.

Когда мы вызываем первую функцию возобновления, значения 3 и 2 сохраняются во временных переменных value1 и value2 до конца сопрограммы.

Чтобы вы поняли это, мы использовали tempvar3, который изначально равен 10, и он обновляется до 13 и 16 последующими вызовами сопрограмм, поскольку значение1 сохраняется как 3 на протяжении всего выполнения сопрограммы.

Первый файл coroutine.yield возвращает два значения 4 и 3 в функцию возобновления, которую мы получаем, обновляя входные параметры 3 и 2 в операторе yield. Он также получает истинный / ложный статус выполнения сопрограммы.

Еще одна вещь, связанная с сопрограммами, заключается в том, как обрабатываются следующие параметры вызова возобновления в приведенном выше примере; Вы можете видеть, что переменная coroutine.yield получает параметры следующего вызова, что обеспечивает мощный способ выполнения новой операции с сохранением существующих значений параметров.

Наконец, как только все операторы в сопрограммах будут выполнены, последующие вызовы вернутся в false и оператор «не может возобновить мертвую сопрограмму» в качестве ответа.

Другой пример сопрограммы

Давайте посмотрим на простую сопрограмму, которая возвращает число от 1 до 5 с помощью функции yield и функции resume. Он создает сопрограмму, если она недоступна, или возобновляет существующую сопрограмму.

Live Demo

function getNumber()
   local function getNumberHelper()
      co = coroutine.create(function ()
      coroutine.yield(1)
      coroutine.yield(2)
      coroutine.yield(3)
      coroutine.yield(4)
      coroutine.yield(5)
      end)
      return co
   end
	
   if(numberHelper) then
      status, number = coroutine.resume(numberHelper);
		
      if coroutine.status(numberHelper) == "dead" then
         numberHelper = getNumberHelper()
         status, number = coroutine.resume(numberHelper);
      end
		
      return number
   else
      numberHelper = getNumberHelper()
      status, number = coroutine.resume(numberHelper);
      return number
   end
	
end

for index = 1, 10 do
   print(index, getNumber())
end

Когда мы запустим вышеуказанную программу, мы получим следующий вывод.

1	1
2	2
3	3
4	4
5	5
6	1
7	2
8	3
9	4
10	5

Часто происходит сравнение сопрограмм с потоками языков мультипрограммирования, но мы должны понимать, что сопрограммы имеют схожие свойства потоков, но они выполняются только по одному за раз и никогда не выполняются одновременно.

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

Lua – File I / O

Библиотека ввода / вывода используется для чтения и управления файлами в Lua. В Lua существует два вида файловых операций, а именно неявные файловые дескрипторы и явные файловые дескрипторы.

Для следующих примеров мы будем использовать пример файла test.lua, как показано ниже.

-- sample test.lua
-- sample2 test.lua

Простая операция открытия файла использует следующее утверждение.

file = io.open (filename [, mode])

Различные режимы файлов перечислены в следующей таблице.

Sr.No. Режим и описание
1

“р”

Режим только для чтения. Это режим по умолчанию, в котором открывается существующий файл.

2

«ж»

Режим записи включен, который перезаписывает существующий файл или создает новый файл.

3

«а»

Режим добавления, который открывает существующий файл или создает новый файл для добавления.

4

«г +»

Режим чтения и записи для существующего файла.

5

«ш +»

Все существующие данные удаляются, если файл существует или создается новый файл с разрешениями на чтение и запись.

6

«а +»

Режим добавления с включенным режимом чтения, который открывает существующий файл или создает новый файл.

“р”

Режим только для чтения. Это режим по умолчанию, в котором открывается существующий файл.

«ж»

Режим записи включен, который перезаписывает существующий файл или создает новый файл.

«а»

Режим добавления, который открывает существующий файл или создает новый файл для добавления.

«г +»

Режим чтения и записи для существующего файла.

«ш +»

Все существующие данные удаляются, если файл существует или создается новый файл с разрешениями на чтение и запись.

«а +»

Режим добавления с включенным режимом чтения, который открывает существующий файл или создает новый файл.

Неявные файловые дескрипторы

Неявные файловые дескрипторы используют стандартные режимы ввода / вывода или используют один входной и один выходной файл. Пример использования неявных файловых дескрипторов показан ниже.

-- Opens a file in read
file = io.open("test.lua", "r")

-- sets the default input file as test.lua
io.input(file)

-- prints the first line of the file
print(io.read())

-- closes the open file
io.close(file)

-- Opens a file in append mode
file = io.open("test.lua", "a")

-- sets the default output file as test.lua
io.output(file)

-- appends a word test to the last line of the file
io.write("-- End of the test.lua file")

-- closes the open file
io.close(file)

Когда вы запустите программу, вы получите вывод первой строки файла test.lua. Для нашей программы мы получили следующий вывод.

-- Sample test.lua

Это была первая строка утверждения в файле test.lua для нас. Также строка “- Конец файла test.lua” будет добавлена ​​к последней строке кода test.lua.

В приведенном выше примере вы можете увидеть, как неявные дескрипторы работают с файловой системой, используя методы io. “X”. В приведенном выше примере используется io.read () без необязательного параметра. Необязательный параметр может быть любым из следующих.

Sr.No. Режим и описание
1

«* п»

Читает из текущей позиции файла и возвращает число, если существует в позиции файла или возвращает ноль.

2

«* а»

Возвращает все содержимое файла из текущей позиции файла.

3

«* л»

Читает строку из текущей позиции файла и перемещает позицию файла на следующую строку.

4

число

Читает количество байтов, указанных в функции.

«* п»

Читает из текущей позиции файла и возвращает число, если существует в позиции файла или возвращает ноль.

«* а»

Возвращает все содержимое файла из текущей позиции файла.

«* л»

Читает строку из текущей позиции файла и перемещает позицию файла на следующую строку.

число

Читает количество байтов, указанных в функции.

Другие распространенные методы ввода / вывода включают в себя:

  • io.tmpfile () – возвращает временный файл для чтения и записи, который будет удален после завершения работы программы.

  • io.type (file) – возвращает ли файл, закрытый файл или ноль на основе входного файла.

  • io.flush () – очищает выходной буфер по умолчанию.

  • io.lines (необязательное имя файла) – предоставляет универсальный итератор цикла, который циклически просматривает файл и закрывает файл в конце, если указано имя файла или файл по умолчанию используется и не закрывается в конце цикла ,

io.tmpfile () – возвращает временный файл для чтения и записи, который будет удален после завершения работы программы.

io.type (file) – возвращает ли файл, закрытый файл или ноль на основе входного файла.

io.flush () – очищает выходной буфер по умолчанию.

io.lines (необязательное имя файла) – предоставляет универсальный итератор цикла, который циклически просматривает файл и закрывает файл в конце, если указано имя файла или файл по умолчанию используется и не закрывается в конце цикла ,

Явные файловые дескрипторы

Мы часто используем явный файловый дескриптор, который позволяет нам манипулировать несколькими файлами одновременно. Эти функции очень похожи на неявные файловые дескрипторы. Здесь мы используем file: function_name вместо io.function_name. Следующий пример версии файла того же самого примера неявных файловых дескрипторов показан ниже.

-- Opens a file in read mode
file = io.open("test.lua", "r")

-- prints the first line of the file
print(file:read())

-- closes the opened file
file:close()

-- Opens a file in append mode
file = io.open("test.lua", "a")

-- appends a word test to the last line of the file
file:write("--test")

-- closes the open file
file:close()

Когда вы запустите программу, вы получите вывод, аналогичный примеру неявных дескрипторов.

-- Sample test.lua

Все режимы открытия файлов и параметров для чтения для внешних дескрипторов такие же, как и для неявных файловых дескрипторов.

Другие распространенные файловые методы включают в себя:

  • file: seek (необязательный fromce, необязательное смещение) – параметр Fromce имеет значение «set», «cur» или «end». Устанавливает новый указатель файла с обновленной позицией файла от начала файла. Смещения в этой функции начинаются с нуля. Смещение измеряется от начала файла, если первый аргумент «установлен»; из текущей позиции в файле, если это “cur”; или из конца файла, если это «конец». Значения аргумента по умолчанию – «cur» и 0, поэтому текущую позицию файла можно получить, вызвав эту функцию без аргументов.

  • file: flush () – очищает выходной буфер по умолчанию.

  • io.lines (необязательное имя файла) – предоставляет универсальный итератор цикла, который циклически просматривает файл и закрывает файл в конце, если указано имя файла или файл по умолчанию используется и не закрывается в конце цикла ,

file: seek (необязательный fromce, необязательное смещение) – параметр Fromce имеет значение «set», «cur» или «end». Устанавливает новый указатель файла с обновленной позицией файла от начала файла. Смещения в этой функции начинаются с нуля. Смещение измеряется от начала файла, если первый аргумент «установлен»; из текущей позиции в файле, если это “cur”; или из конца файла, если это «конец». Значения аргумента по умолчанию – «cur» и 0, поэтому текущую позицию файла можно получить, вызвав эту функцию без аргументов.

file: flush () – очищает выходной буфер по умолчанию.

io.lines (необязательное имя файла) – предоставляет универсальный итератор цикла, который циклически просматривает файл и закрывает файл в конце, если указано имя файла или файл по умолчанию используется и не закрывается в конце цикла ,

Пример использования метода поиска показан ниже. Он смещает курсор от 25 позиций до конца файла. Функция чтения печатает остаток файла с позиции поиска.

-- Opens a file in read
file = io.open("test.lua", "r")

file:seek("end",-25)
print(file:read("*a"))

-- closes the opened file
file:close()

Вы получите вывод, похожий на следующий.

sample2 test.lua
--test

Вы можете поэкспериментировать со всеми различными режимами и параметрами, чтобы узнать все возможности операций с файлами Lua.

Lua – Обработка ошибок

Необходимость обработки ошибок

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

В любом программировании всегда есть требование для обработки ошибок. Ошибки могут быть двух типов, которые включают в себя,

  • Синтаксические ошибки
  • Ошибки во время выполнения

Синтаксические ошибки

Синтаксические ошибки возникают из-за неправильного использования различных компонентов программы, таких как операторы и выражения. Простой пример синтаксической ошибки показан ниже.

a == 2

Как вы знаете, существует разница между использованием одного «равно» и двойного «равно». Использование одного вместо другого может привести к ошибке. Одно «равно» относится к присвоению, а двойное «равно» относится к сравнению. Точно так же у нас есть выражения и функции, имеющие предопределенные способы реализации.

Другой пример синтаксической ошибки показан ниже –

Live Demo

for a= 1,10
   print(a)
end

Когда мы запустим вышеупомянутую программу, мы получим следующий вывод –

lua: test2.lua:2: 'do' expected near 'print'

Синтаксические ошибки гораздо легче обрабатывать, чем ошибки времени выполнения, поскольку интерпретатор Lua обнаруживает ошибку более четко, чем в случае ошибки времени выполнения. Из вышеприведенной ошибки мы можем легко узнать, что добавление оператора do перед оператором print требуется согласно структуре Lua.

Ошибки времени выполнения

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

Live Demo

function add(a,b)
   return a+b
end

add(10)

Когда мы соберем программу, она будет успешно собрана и запущена. Как только он запускается, показывает ошибку времени выполнения.

lua: test2.lua:2: attempt to perform arithmetic on local 'b' (a nil value)
stack traceback:
	test2.lua:2: in function 'add'
	test2.lua:5: in main chunk
	[C]: ?

Это ошибка времени выполнения, которая произошла из-за отсутствия передачи двух переменных. Ожидается параметр b, и здесь он равен нулю и выдает ошибку.

Функции подтверждения и ошибки

Для обработки ошибок мы часто используем две функции – assert и error . Простой пример показан ниже.

Live Demo

local function add(a,b)
   assert(type(a) == "number", "a is not a number")
   assert(type(b) == "number", "b is not a number")
   return a+b
end

add(10)

Когда мы запустим вышеуказанную программу, мы получим следующий вывод об ошибке.

lua: test2.lua:3: b is not a number
stack traceback:
	[C]: in function 'assert'
	test2.lua:3: in function 'add'
	test2.lua:6: in main chunk
	[C]: ?

Ошибка (сообщение [, уровень]) завершает последнюю вызванную защищенную функцию и возвращает сообщение как сообщение об ошибке. Эта ошибка функции никогда не возвращается. Обычно ошибка добавляет некоторую информацию о позиции ошибки в начале сообщения. Аргумент уровня указывает, как получить позицию ошибки. На уровне 1 (по умолчанию) позиция ошибки – это то место, где была вызвана функция ошибки. Уровень 2 указывает на ошибку, где была вызвана функция, которая вызвала ошибку; и так далее. Пропуск уровня 0 позволяет избежать добавления информации о позиции ошибки в сообщение.

pcall и xpcall

В программировании на Lua, чтобы избежать появления этих ошибок и обработки ошибок, нам нужно использовать функции pcall или xpcall.

Функция pcall (f, arg1, …) вызывает запрошенную функцию в защищенном режиме. Если какая-то ошибка возникает в функции f, она не выдает ошибку. Он просто возвращает статус ошибки. Простой пример использования pcall показан ниже.

Live Demo

function myfunction ()
   n = n/nil
end

if pcall(myfunction) then
   print("Success")
else
	print("Failure")
end

Когда мы запустим вышеуказанную программу, мы получим следующий вывод.

Failure

Функция xpcall (f, err) вызывает запрошенную функцию, а также устанавливает обработчик ошибок. Любая ошибка внутри f не распространяется; вместо этого xpcall перехватывает ошибку, вызывает функцию err с исходным объектом ошибки и возвращает код состояния.

Простой пример для xpcall показан ниже.

Live Demo

function myfunction ()
   n = n/nil
end

function myerrorhandler( err )
   print( "ERROR:", err )
end

status = xpcall( myfunction, myerrorhandler )
print( status)

Когда мы запустим вышеуказанную программу, мы получим следующий вывод.

ERROR:	test2.lua:2: attempt to perform arithmetic on global 'n' (a nil value)
false

Как программист, очень важно, чтобы вы позаботились о правильной обработке ошибок в программах, которые вы пишете. Использование обработки ошибок может гарантировать, что неожиданные условия за пределами граничных условий будут обрабатываться без вмешательства пользователя программы.

Lua – отладка

Lua предоставляет библиотеку отладки, которая предоставляет нам все примитивные функции для создания нашего собственного отладчика. Хотя встроенного отладчика Lua нет, у нас есть много отладчиков для Lua, созданных различными разработчиками, многие из которых являются открытыми.

Функции, доступные в библиотеке отладки Lua, перечислены в следующей таблице вместе с их использованием.

Sr.No. Метод и цель
1

отладки ()

Переходит в интерактивный режим отладки, который остается активным до тех пор, пока мы не введем только строку в строке и не нажмем клавишу ввода Пользователь может проверять переменные в этом режиме, используя другие функции.

2

getfenv (объект)

Возвращает среду объекта.

3

gethook (необязательная тема)

Возвращает текущие настройки ловушек потока в виде трех значений – текущей функции ловушек, текущей маски ловушек и текущего счетчика ловушек.

4

getinfo (необязательный поток, функция или уровень стека, необязательный флаг)

Возвращает таблицу с информацией о функции. Вы можете передать функцию напрямую или указать число в качестве значения функции, что означает, что функция выполняется на уровне функции стека вызовов данного потока – уровень 0 является текущей функцией (сама getinfo); уровень 1 – это функция, которая вызвала getinfo; и так далее. Если функция на число больше, чем количество активных функций, getinfo возвращает nil.

5

getlocal (необязательный поток, уровень стека, локальный индекс)

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

6

GetMetaTable (значение)

Возвращает метатабельность данного объекта или ноль, если у него нет метатаблицы.

7

getregistry ()

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

8

getupvalue (функция, индекс upvalue)

Эта функция возвращает имя и значение upvalue с индексом вверх функции func. Функция возвращает nil, если нет никакого значения с данным индексом.

9

setfenv (функция или поток или пользовательские данные, таблица окружения)

Устанавливает среду данного объекта в данную таблицу. Возвращает объект.

10

sethook (необязательный поток, функция ловушки, строка маски крюка с “c” и / или “r” и / или “l”, необязательный счетчик команд)

Устанавливает данную функцию как хук. Строковая маска и счетчик чисел описывают, когда будет вызываться ловушка. Здесь c, r и l вызываются каждый раз, когда Lua вызывает, возвращает и вводит каждую строку кода в функцию соответственно.

11

setlocal (необязательный поток, уровень стека, локальный индекс, значение)

Назначает значение локальной переменной с индексом local функции на уровне стека. Функция возвращает nil, если нет локальной переменной с данным индексом, и выдает ошибку при вызове с уровнем вне диапазона. В противном случае он возвращает имя локальной переменной.

12

setmetatable (значение, метатабельный)

Устанавливает метатабельность для данного объекта в данной таблице (которая может быть ноль).

13

setupvalue (функция, индекс upvalue, значение)

Эта функция присваивает значение повышающему значению с индексом вверх функции func. Функция возвращает nil, если нет никакого значения с данным индексом. В противном случае он возвращает имя upvalue.

14

traceback (необязательный поток, необязательная строка сообщения, необязательный аргумент уровня)

Создает расширенное сообщение об ошибке с трассировкой.

отладки ()

Переходит в интерактивный режим отладки, который остается активным до тех пор, пока мы не введем только строку в строке и не нажмем клавишу ввода Пользователь может проверять переменные в этом режиме, используя другие функции.

getfenv (объект)

Возвращает среду объекта.

gethook (необязательная тема)

Возвращает текущие настройки ловушек потока в виде трех значений – текущей функции ловушек, текущей маски ловушек и текущего счетчика ловушек.

getinfo (необязательный поток, функция или уровень стека, необязательный флаг)

Возвращает таблицу с информацией о функции. Вы можете передать функцию напрямую или указать число в качестве значения функции, что означает, что функция выполняется на уровне функции стека вызовов данного потока – уровень 0 является текущей функцией (сама getinfo); уровень 1 – это функция, которая вызвала getinfo; и так далее. Если функция на число больше, чем количество активных функций, getinfo возвращает nil.

getlocal (необязательный поток, уровень стека, локальный индекс)

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

GetMetaTable (значение)

Возвращает метатабельность данного объекта или ноль, если у него нет метатаблицы.

getregistry ()

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

getupvalue (функция, индекс upvalue)

Эта функция возвращает имя и значение upvalue с индексом вверх функции func. Функция возвращает nil, если нет никакого значения с данным индексом.

setfenv (функция или поток или пользовательские данные, таблица окружения)

Устанавливает среду данного объекта в данную таблицу. Возвращает объект.

sethook (необязательный поток, функция ловушки, строка маски крюка с “c” и / или “r” и / или “l”, необязательный счетчик команд)

Устанавливает данную функцию как хук. Строковая маска и счетчик чисел описывают, когда будет вызываться ловушка. Здесь c, r и l вызываются каждый раз, когда Lua вызывает, возвращает и вводит каждую строку кода в функцию соответственно.

setlocal (необязательный поток, уровень стека, локальный индекс, значение)

Назначает значение локальной переменной с индексом local функции на уровне стека. Функция возвращает nil, если нет локальной переменной с данным индексом, и выдает ошибку при вызове с уровнем вне диапазона. В противном случае он возвращает имя локальной переменной.

setmetatable (значение, метатабельный)

Устанавливает метатабельность для данного объекта в данной таблице (которая может быть ноль).

setupvalue (функция, индекс upvalue, значение)

Эта функция присваивает значение повышающему значению с индексом вверх функции func. Функция возвращает nil, если нет никакого значения с данным индексом. В противном случае он возвращает имя upvalue.

traceback (необязательный поток, необязательная строка сообщения, необязательный аргумент уровня)

Создает расширенное сообщение об ошибке с трассировкой.

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

Live Demo

function myfunction ()
   print(debug.traceback("Stack trace"))
   print(debug.getinfo(1))
   print("Stack trace end")

   return 10
end

myfunction ()
print(debug.getinfo(1))

Когда мы запустим вышеуказанную программу, мы получим трассировку стека, как показано ниже.

Stack trace
stack traceback:
	test2.lua:2: in function 'myfunction'
	test2.lua:8: in main chunk
	[C]: ?
table: 0054C6C8
Stack trace end

В приведенном выше примере программы трассировка стека печатается с использованием функции debug.trace, доступной в библиотеке отладки. Debug.getinfo получает текущую таблицу функции.

Отладка – Пример

Нам часто нужно знать локальные переменные функции для отладки. Для этой цели мы можем использовать getupvalue, а для установки этих локальных переменных мы используем setupvalue. Простой пример для этого показан ниже.

Live Demo

function newCounter ()
   local n = 0
   local k = 0
	
   return function ()
      k = n
      n = n + 1
      return n
   end
	
end

counter = newCounter ()

print(counter())
print(counter())

local i = 1

repeat
   name, val = debug.getupvalue(counter, i)
	
   if name then
      print ("index", i, name, "=", val)
		
      if(name == "n") then
         debug.setupvalue (counter,2,10)
      end
		
      i = i + 1
   end -- if
	
until not name

print(counter())

Когда мы запустим вышеуказанную программу, мы получим следующий вывод.

1
2
index	1	k	=	1
index	2	n	=	2
11

В этом примере счетчик обновляется по одному при каждом вызове. Мы можем видеть текущее состояние локальной переменной, используя функцию getupvalue. Затем мы устанавливаем локальную переменную в новое значение. Здесь n равно 2 до вызова операции set. Используя функцию setupvalue, она обновляется до 10. Теперь, когда мы вызываем функцию счетчика, она возвращает 11 вместо 3.

Типы отладки

  • Отладка командной строки
  • Графическая отладка

Отладка командной строки

Отладка командной строки – это тип отладки, который использует командную строку для отладки с помощью команд и операторов печати. Для Lua доступно множество отладчиков командной строки, некоторые из которых перечислены ниже.

  • RemDebug – RemDebug является удаленным отладчиком для Lua 5.0 и 5.1. Это позволяет удаленно контролировать выполнение другой программы Lua, устанавливать точки останова и проверять текущее состояние программы. RemDebug также может отлаживать сценарии CGILua.

  • clidebugger – простой отладчик интерфейса командной строки для Lua 5.1, написанный на чистом Lua. Он не зависит ни от чего, кроме стандартных библиотек Lua 5.1. Он был вдохновлен RemDebug, но не имеет своих удаленных средств.

  • ctrace – инструмент для отслеживания вызовов Lua API.

  • xdbLua – простой отладчик командной строки Lua для платформы Windows.

  • LuaInterface – Debugger – Этот проект является расширением отладчика для LuaInterface. Это поднимает встроенный интерфейс отладки Lua на более высокий уровень. Взаимодействие с отладчиком осуществляется посредством событий и вызовов методов.

  • Rldb – это удаленный отладчик Lua через сокет, доступный как в Windows, так и в Linux. Это может дать вам гораздо больше возможностей, чем любой существующий.

  • ModDebug – позволяет удаленно контролировать выполнение другой программы Lua, устанавливать точки останова и проверять текущее состояние программы.

RemDebug – RemDebug является удаленным отладчиком для Lua 5.0 и 5.1. Это позволяет удаленно контролировать выполнение другой программы Lua, устанавливать точки останова и проверять текущее состояние программы. RemDebug также может отлаживать сценарии CGILua.

clidebugger – простой отладчик интерфейса командной строки для Lua 5.1, написанный на чистом Lua. Он не зависит ни от чего, кроме стандартных библиотек Lua 5.1. Он был вдохновлен RemDebug, но не имеет своих удаленных средств.

ctrace – инструмент для отслеживания вызовов Lua API.

xdbLua – простой отладчик командной строки Lua для платформы Windows.

LuaInterface – Debugger – Этот проект является расширением отладчика для LuaInterface. Это поднимает встроенный интерфейс отладки Lua на более высокий уровень. Взаимодействие с отладчиком осуществляется посредством событий и вызовов методов.

Rldb – это удаленный отладчик Lua через сокет, доступный как в Windows, так и в Linux. Это может дать вам гораздо больше возможностей, чем любой существующий.

ModDebug – позволяет удаленно контролировать выполнение другой программы Lua, устанавливать точки останова и проверять текущее состояние программы.

Графическая отладка

Графическая отладка доступна с помощью IDE, где вам предоставляется визуальная отладка различных состояний, таких как значения переменных, трассировка стека и другая связанная информация. Существует визуальное представление и пошаговое управление выполнением с помощью точек останова, перехода, перехода и других кнопок в IDE.

Существует несколько графических отладчиков для Lua, и это включает следующее.

  • SciTE – стандартная Windows IDE для Lua предоставляет несколько средств отладки, таких как точки останова, шаг, шаг, шаг, просмотр переменных и так далее.

  • Decoda – это графический отладчик с поддержкой удаленной отладки.

  • ZeroBrane Studio – Lua IDE со встроенным удаленным отладчиком, просмотром стека, просмотром часов, удаленной консолью, статическим анализатором и многим другим. Работает с LuaJIT, Love2d, Moai и другими двигателями Lua; Windows, OSX и Linux. Открытый исходный код.

  • akdebugger – Отладчик и редактор Lua для Eclipse.

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

SciTE – стандартная Windows IDE для Lua предоставляет несколько средств отладки, таких как точки останова, шаг, шаг, шаг, просмотр переменных и так далее.

Decoda – это графический отладчик с поддержкой удаленной отладки.

ZeroBrane Studio – Lua IDE со встроенным удаленным отладчиком, просмотром стека, просмотром часов, удаленной консолью, статическим анализатором и многим другим. Работает с LuaJIT, Love2d, Moai и другими двигателями Lua; Windows, OSX и Linux. Открытый исходный код.

akdebugger – Отладчик и редактор Lua для Eclipse.

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

Луа – Сборка мусора

Lua использует автоматическое управление памятью, которое использует сборку мусора на основе определенных алгоритмов, встроенных в Lua. В результате автоматического управления памятью, как разработчик –

  • Не нужно беспокоиться о выделении памяти для объектов.
  • Нет необходимости освобождать их, когда они больше не нужны, за исключением установки на ноль.

Lua использует сборщик мусора, который запускается время от времени для сбора мертвых объектов, когда они больше не доступны из программы Lua.

Все объекты, включая таблицы, пользовательские данные, функции, потоки, строки и т. Д., Подлежат автоматическому управлению памятью. Lua использует инкрементный сборщик меток и очистки, который использует два числа для управления циклами сборки мусора, а именно паузу сборщика мусора и множитель шага сборщика мусора . Эти значения в процентах, а значение 100 часто равно 1 внутри.

Сборщик мусора Пауза

Пауза сборщика мусора используется для контроля того, как долго должен ждать сборщик мусора; он снова вызывается автоматическим управлением памятью Lua. Значения меньше 100 означают, что Lua не будет ждать следующего цикла. Аналогично, более высокие значения этого значения приведут к тому, что сборщик мусора будет медленным и менее агрессивным по своей природе. Значение 200 означает, что сборщик ожидает удвоения общего объема используемой памяти, прежде чем начинать новый цикл. Следовательно, в зависимости от характера и скорости приложения может потребоваться изменить это значение, чтобы получить лучшую производительность в приложениях Lua.

Множитель шага сборщика мусора

Этот множитель шага управляет относительной скоростью сборщика мусора и скоростью выделения памяти в программе Lua. Большие значения шага приведут к тому, что сборщик мусора станет более агрессивным, а также увеличит размер шага каждого добавочного шага сборки мусора. Значения меньше 100 часто могут привести к тому, что сборщик мусора не завершит свой цикл, и это обычно не является предпочтительным. Значение по умолчанию равно 200, что означает, что сборщик мусора работает в два раза быстрее, чем скорость выделения памяти.

Функции сборщика мусора

Как разработчики, у нас есть некоторый контроль над автоматическим управлением памятью в Lua. Для этого у нас есть следующие методы.

  • collectgarbage («собирать») – запускает один полный цикл сборки мусора.

  • collectgarbage (“count”) – Возвращает объем памяти, используемой в настоящее время программой в килобайтах.

  • collectgarbage («restart») – Если сборщик мусора был остановлен, он перезапускает его.

  • collectgarbage (“setpause”) – Устанавливает значение, заданное в качестве второго параметра, деленное на 100 для переменной паузы сборщика мусора. Его использование – как обсуждено немного выше.

  • collectgarbage (“setstepmul”) – Устанавливает значение, заданное в качестве второго параметра, деленное на 100 для переменной множителя шага мусора. Его использование – как обсуждено немного выше.

  • collectgarbage («шаг») – Запускает один шаг сборки мусора. Чем больше второй аргумент, тем больше будет этот шаг. Параметр collectgarbage будет возвращать значение true, если запущенный шаг был последним этапом цикла сбора мусора.

  • collectgarbage («стоп») – останавливает сборщик мусора, если он работает.

collectgarbage («собирать») – запускает один полный цикл сборки мусора.

collectgarbage (“count”) – Возвращает объем памяти, используемой в настоящее время программой в килобайтах.

collectgarbage («restart») – Если сборщик мусора был остановлен, он перезапускает его.

collectgarbage (“setpause”) – Устанавливает значение, заданное в качестве второго параметра, деленное на 100 для переменной паузы сборщика мусора. Его использование – как обсуждено немного выше.

collectgarbage (“setstepmul”) – Устанавливает значение, заданное в качестве второго параметра, деленное на 100 для переменной множителя шага мусора. Его использование – как обсуждено немного выше.

collectgarbage («шаг») – Запускает один шаг сборки мусора. Чем больше второй аргумент, тем больше будет этот шаг. Параметр collectgarbage будет возвращать значение true, если запущенный шаг был последним этапом цикла сбора мусора.

collectgarbage («стоп») – останавливает сборщик мусора, если он работает.

Простой пример с использованием примера сборщика мусора показан ниже.

Live Demo

mytable = {"apple", "orange", "banana"}

print(collectgarbage("count"))

mytable = nil

print(collectgarbage("count"))

print(collectgarbage("collect"))

print(collectgarbage("count"))

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

23.1455078125   149
23.2880859375   295
0
22.37109375     380

Вы можете видеть в приведенной выше программе, когда сборка мусора завершена, она уменьшает используемую память. Но это не обязательно называть это. Даже если мы не вызовем их, он будет выполнен автоматически на более позднем этапе интерпретатором Lua после предварительно определенного периода.

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

Lua – объектно-ориентированный

Введение в ООП

Объектно-ориентированное программирование (ООП) – это один из наиболее часто используемых методов программирования, который используется в современную эпоху программирования. Существует ряд языков программирования, которые поддерживают ООП, включая:

  • C ++
  • Джава
  • Objective-C
  • Болтовня
  • C #
  • Рубин

Особенности ООП

  • Класс – класс – это расширяемый шаблон для создания объектов, предоставляющий начальные значения для состояния (переменные-члены) и реализации поведения.

  • Объекты – это экземпляр класса, для которого выделена отдельная память.

  • Наследование – это понятие, посредством которого переменные и функции одного класса наследуются другим классом.

  • Инкапсуляция – это процесс объединения данных и функций внутри класса. Данные могут быть доступны вне класса с помощью функций. Это также известно как абстракция данных.

Класс – класс – это расширяемый шаблон для создания объектов, предоставляющий начальные значения для состояния (переменные-члены) и реализации поведения.

Объекты – это экземпляр класса, для которого выделена отдельная память.

Наследование – это понятие, посредством которого переменные и функции одного класса наследуются другим классом.

Инкапсуляция – это процесс объединения данных и функций внутри класса. Данные могут быть доступны вне класса с помощью функций. Это также известно как абстракция данных.

ООП в Луа

Вы можете реализовать ориентацию объекта в Lua с помощью таблиц и первоклассных функций Lua. Помещая функции и связанные данные в таблицу, формируется объект. Наследование может быть реализовано с помощью метатаблиц, обеспечивающих механизм поиска несуществующих функций (методов) и полей в родительском объекте (ах).

Таблицы в Lua имеют свойства объекта, такие как состояние и идентичность, которые не зависят от его значений. Два объекта (таблицы) с одинаковым значением являются разными объектами, тогда как объект может иметь разные значения в разное время, но это всегда один и тот же объект. Как и у объектов, таблицы имеют жизненный цикл, который не зависит от того, кто их создал или где они были созданы.

Пример из реального мира

Концепция объектной ориентации широко используется, но вам необходимо четко понимать ее для правильной и максимальной выгоды.

Давайте рассмотрим простой математический пример. Мы часто сталкиваемся с ситуациями, когда работаем с разными формами, такими как круг, прямоугольник и квадрат.

Формы могут иметь общее свойство Area. Таким образом, мы можем расширить другие фигуры из формы базового объекта с помощью общей области свойств. Каждая из фигур может иметь свои собственные свойства и функции, например, прямоугольник может иметь свойства length, width, area в качестве своих свойств, а printArea и defineArea в качестве своих функций.

Создание простого класса

Простая реализация класса для прямоугольника с тремя свойствами: площадь, длина и ширина показаны ниже. Он также имеет функцию printArea для печати рассчитанной площади.

-- Meta class
Rectangle = {area = 0, length = 0, breadth = 0}

-- Derived class method new

function Rectangle:new (o,length,breadth)
   o = o or {}
   setmetatable(o, self)
   self.__index = self
   self.length = length or 0
   self.breadth = breadth or 0
   self.area = length*breadth;
   return o
end

-- Derived class method printArea

function Rectangle:printArea ()
   print("The area of Rectangle is ",self.area)
end

Создание объекта

Создание объекта – это процесс выделения памяти для экземпляра класса. Каждый из объектов имеет свою собственную память и разделяет данные общего класса.

r = Rectangle:new(nil,10,20)

Доступ к свойствам

Мы можем получить доступ к свойствам в классе, используя оператор точки, как показано ниже –

print(r.length)

Доступ к функции-члену

Вы можете получить доступ к функции-члену, используя оператор двоеточия с объектом, как показано ниже –

r:printArea()

Память распределяется и устанавливаются начальные значения. Процесс инициализации можно сравнить с конструкторами в других объектно-ориентированных языках. Это не что иное, как функция, которая позволяет устанавливать значения, как показано выше.

Полный пример

Давайте посмотрим на полный пример, используя объектную ориентацию в Lua.

Live Demo

-- Meta class
Shape = {area = 0}

-- Base class method new

function Shape:new (o,side)
   o = o or {}
   setmetatable(o, self)
   self.__index = self
   side = side or 0
   self.area = side*side;
   return o
end

-- Base class method printArea

function Shape:printArea ()
   print("The area is ",self.area)
end

-- Creating an object
myshape = Shape:new(nil,10)

myshape:printArea()

Когда вы запустите вышеуказанную программу, вы получите следующий вывод.

The area is 	100

Наследование в Lua

Наследование – это процесс расширения простых базовых объектов, таких как фигура, на прямоугольники, квадраты и так далее. Он часто используется в реальном мире для обмена и расширения основных свойств и функций.

Давайте посмотрим на простое расширение класса. У нас есть класс, как показано ниже.

-- Meta class
Shape = {area = 0}

-- Base class method new

function Shape:new (o,side)
   o = o or {}
   setmetatable(o, self)
   self.__index = self
   side = side or 0
   self.area = side*side;
   return o
end

-- Base class method printArea

function Shape:printArea ()
   print("The area is ",self.area)
end

Мы можем расширить форму до квадратного класса, как показано ниже.

Square = Shape:new()

-- Derived class method new

function Square:new (o,side)
   o = o or Shape:new(o,side)
   setmetatable(o, self)
   self.__index = self
   return o
end

Базовые функции

Мы можем переопределить функции базового класса, то есть вместо того, чтобы использовать функцию в базовом классе, производный класс может иметь собственную реализацию, как показано ниже –

-- Derived class method printArea

function Square:printArea ()
   print("The area of square is ",self.area)
end

Пример завершения наследования

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

Live Demo

-- Meta class
Shape = {area = 0}

-- Base class method new

function Shape:new (o,side)
   o = o or {}
   setmetatable(o, self)
   self.__index = self
   side = side or 0
   self.area = side*side;
   return o
end

-- Base class method printArea

function Shape:printArea ()
   print("The area is ",self.area)
end

-- Creating an object
myshape = Shape:new(nil,10)
myshape:printArea()

Square = Shape:new()

-- Derived class method new

function Square:new (o,side)
   o = o or Shape:new(o,side)
   setmetatable(o, self)
   self.__index = self
   return o
end

-- Derived class method printArea

function Square:printArea ()
   print("The area of square is ",self.area)
end

-- Creating an object
mysquare = Square:new(nil,10)
mysquare:printArea()

Rectangle = Shape:new()

-- Derived class method new

function Rectangle:new (o,length,breadth)
   o = o or Shape:new(o)
   setmetatable(o, self)
   self.__index = self
   self.area = length * breadth
   return o
end

-- Derived class method printArea

function Rectangle:printArea ()
    print("The area of Rectangle is ",self.area)
end

-- Creating an object

myrectangle = Rectangle:new(nil,10,20)
myrectangle:printArea()

Когда мы запустим вышеупомянутую программу, мы получим следующий вывод –

The area is 	100
The area of square is 	100
The area of Rectangle is 	200

В приведенном выше примере мы создали два производных класса – Rectangle и Square из базового класса Square. Можно переопределить функции базового класса в производном классе. В этом примере производный класс переопределяет функцию printArea.

Lua – веб-программирование

Lua – очень гибкий язык, и он часто используется на разных платформах, включая веб-приложения. Сообщество Kepler, которое было сформировано в 2004 году для предоставления веб-компонентов с открытым исходным кодом в Lua.

Несмотря на то, что существуют другие веб-фреймворки, использующие Lua, мы в первую очередь сосредоточимся на компонентах, предоставляемых сообществом Kepler.

Приложения и рамки

  • Orbit – это веб-фреймворк MVC для Lua, основанный на WSAPI.

  • WSAPI – это API, который абстрагирует сервер веб-хоста от веб-приложений Lua и является основой для многих проектов.

  • Xavante – это веб-сервер Lua, который предлагает интерфейс WSAPI.

  • Sputnik – это вики / CMS, разработанная на основе WSAPI для проекта Kepler, используемая для юмора и развлечений.

  • CGILua предлагает создание веб-страниц LuaPages и LuaScripts на основе WSAPI, но больше не поддерживается. Вместо этого используйте Orbit, Sputnik или WSAPI.

Orbit – это веб-фреймворк MVC для Lua, основанный на WSAPI.

WSAPI – это API, который абстрагирует сервер веб-хоста от веб-приложений Lua и является основой для многих проектов.

Xavante – это веб-сервер Lua, который предлагает интерфейс WSAPI.

Sputnik – это вики / CMS, разработанная на основе WSAPI для проекта Kepler, используемая для юмора и развлечений.

CGILua предлагает создание веб-страниц LuaPages и LuaScripts на основе WSAPI, но больше не поддерживается. Вместо этого используйте Orbit, Sputnik или WSAPI.

В этом руководстве мы постараемся помочь вам понять, что может делать Lua, и узнать больше о его установке и использовании, см. Веб-сайт kepler.

орбита

Orbit – это веб-фреймворк MVC для Lua. Он полностью отказывается от модели «сценариев» CGILua в пользу приложений, где каждое приложение Orbit может помещаться в один файл, но вы можете разбить его на несколько файлов, если хотите.

Все приложения Orbit следуют протоколу WSAPI, поэтому в настоящее время они работают с Xavante, CGI и Fastcgi. Он включает в себя панель запуска, которая позволяет легко запускать экземпляр Xavante для разработки.

Самый простой способ установить Orbit – это использовать LuaRocks. Luarocks install orbit – это команда для установки. Для этого вам нужно сначала установить LuaRocks .

Если вы не установили все зависимости, вот шаги, которые необходимо выполнить для настройки Orbit в среде Unix / Linux.

Установка Apache

Подключитесь к вашему серверу. Установите Apache2, его модули поддержки и включите необходимые модули Apache2, используя –

$ sudo apt-get install apache2 libapache2-mod-fcgid libfcgi-dev build-essential
$ sudo a2enmod rewrite
$ sudo a2enmod fcgid
$ sudo /etc/init.d/apache2 force-reload

Установить LuaRocks

$ sudo apt-get install luarocks

Установите WSAPI, FCGI, Orbit и Xavante

$ sudo luarocks install orbit
$ sudo luarocks install wsapi-xavante
$ sudo luarocks install wsapi-fcgi

Настройка Apache2

$ sudo raj /etc/apache2/sites-available/default

Добавьте этот следующий раздел ниже раздела <Directory / var / www /> файла конфигурации. Если в этом разделе указано «AllowOverride None», вам нужно изменить «None» на «All», чтобы файл .htaccess мог переопределить конфигурацию локально.

<IfModule mod_fcgid.c>

   AddHandler fcgid-script .lua
   AddHandler fcgid-script .ws
   AddHandler fcgid-script .op
	
   FCGIWrapper "/usr/local/bin/wsapi.fcgi" .ws
   FCGIWrapper "/usr/local/bin/wsapi.fcgi" .lua
   FCGIWrapper "/usr/local/bin/op.fcgi" .op
	
   #FCGIServer "/usr/local/bin/wsapi.fcgi" -idle-timeout 60 -processes 1
   #IdleTimeout 60
   #ProcessLifeTime 60
	
</IfModule>

Перезагрузите сервер, чтобы изменения вступили в силу.

Чтобы включить ваше приложение, вам нужно добавить + ExecCGI в файл .htaccess в корне вашего приложения Orbit – в данном случае, / var / www.

Options +ExecCGI
DirectoryIndex index.ws

Простой пример – Орбита

#!/usr/bin/env index.lua

-- index.lua
require"orbit"

-- declaration
module("myorbit", package.seeall, orbit.new)

-- handler

function index(web)
   return my_home_page()
end

-- dispatch
myorbit:dispatch_get(index, "/", "/index")

-- Sample page

function my_home_page()

   return [[
      <head></head>
      <html>
         <h2>First Page</h2>
      </html>
   ]]
	
end

Теперь вы сможете запустить свой веб-браузер. Перейдите на http: // localhost: 8080 /, и вы должны увидеть следующий вывод –

First Page

Orbit предоставляет другой вариант, т. Е. Код Lua может генерировать html.

#!/usr/bin/env index.lua

-- index.lua
require"orbit"

function generate()
   return html {
      head{title "HTML Example"},
		
      body{
         h2{"Here we go again!"}
      }
   }
end

orbit.htmlify(generate)

print(generate())

Создание форм

Простой пример формы показан ниже –

#!/usr/bin/env index.lua
require"orbit"

function wrap (inner)
   return html{ head(), body(inner) }
end

function test ()
   return wrap(form (H'table' {
      tr{td"First name",td( input{type = 'text', name='first'})},
      tr{td"Second name",td(input{type = 'text', name='second'})},
      tr{ td(input{type = 'submit', value = 'Submit!'}),
         td(input{type = 'submit',value = 'Cancel'})
      },
   }))
end

orbit.htmlify(wrap,test)

print(test())

WSAPI

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

  • Windows
  • UNIX-системы

Поддерживаемые серверы и интерфейсы WSAPI включают в себя:

  • CGI
  • FastCGI
  • Xavante

WSAPI предоставляет ряд библиотек, что облегчает нам веб-программирование с использованием Lua. Некоторые из поддерживаемых функций в Lua включают в себя:

  • Обработка запросов
  • Буферизация вывода
  • Аутентификация
  • Загрузка файлов
  • Запросить изоляцию
  • мультиплексирование

Простой пример WSAPI показан ниже –

#!/usr/bin/env wsapi.cgi

module(..., package.seeall)
function run(wsapi_env)
   local headers = { ["Content-type"] = "text/html" }
   
   local function hello_text()
      coroutine.yield("<html><body>")
      coroutine.yield("<p>Hello Wsapi!</p>")
      coroutine.yield("<p>PATH_INFO: " .. wsapi_env.PATH_INFO .. "</p>")
      coroutine.yield("<p>SCRIPT_NAME: " .. wsapi_env.SCRIPT_NAME .. "</p>")
      coroutine.yield("</body></html>")
   end

   return 200, headers, coroutine.wrap(hello_text)
end

В приведенном выше коде вы видите простую HTML-страницу, которая создается и возвращается. Вы можете увидеть использование сопрограмм, которые позволяют возвращать оператор за оператором вызывающей функции. Наконец, возвращается HTML-код состояния (200), заголовки и HTML-страница.

Xavante

Xavante – это веб-сервер Lua HTTP 1.1, использующий модульную архитектуру на основе обработчиков сопоставленных URI. Ксаванте в настоящее время предлагает,

  • Обработчик файлов
  • Обработчик перенаправления
  • Обработчик WSAPI

Обработчик файлов используется для общих файлов. Обработчик перенаправления включает переопределение URI и обработчик WSAPI для обработки с приложениями WSAPI.

Простой пример показан ниже.

require "xavante.filehandler"
require "xavante.cgiluahandler"
require "xavante.redirecthandler"

-- Define here where Xavante HTTP documents scripts are located
local webDir = XAVANTE_WEB

local simplerules = {

   { -- URI remapping example
      match = "^[^%./]*/$",
      with = xavante.redirecthandler,
      params = {"index.lp"}
   }, 

   { -- cgiluahandler example
      match = {"%.lp$", "%.lp/.*$", "%.lua$", "%.lua/.*$" },
      with = xavante.cgiluahandler.makeHandler (webDir)
   },
    
   { -- filehandler example
      match = ".",
      with = xavante.filehandler,
      params = {baseDir = webDir}
   },
} 

xavante.HTTP{
   server = {host = "*", port = 8080},
    
   defaultHost = {
      rules = simplerules
   },
}

Чтобы использовать виртуальные хосты с Xavante, вызов xavante.HTTP будет изменен на что-то вроде следующего:

xavante.HTTP{
   server = {host = "*", port = 8080},
    
   defaultHost = {},
    
   virtualhosts = {
      ["www.sitename.com"] = simplerules
   }
}

Lua Web Components

  • Copas , диспетчер, основанный на сопрограммах, которые могут использоваться серверами TCP / IP.

  • Cosmo , движок «безопасных шаблонов», защищающий ваше приложение от произвольного кода в шаблонах.

  • Coxpcall инкапсулирует Lua нативный pcall и xpcall с сопрограмм-совместимыми.

  • LuaFileSystem , переносимый способ доступа к базовой структуре каталогов и атрибутам файлов.

  • Rings , библиотека, которая обеспечивает способ создания новых состояний Lua из Lua.

Copas , диспетчер, основанный на сопрограммах, которые могут использоваться серверами TCP / IP.

Cosmo , движок «безопасных шаблонов», защищающий ваше приложение от произвольного кода в шаблонах.

Coxpcall инкапсулирует Lua нативный pcall и xpcall с сопрограмм-совместимыми.

LuaFileSystem , переносимый способ доступа к базовой структуре каталогов и атрибутам файлов.

Rings , библиотека, которая обеспечивает способ создания новых состояний Lua из Lua.

Конечная заметка

Для нас доступно так много веб-фреймворков и компонентов, основанных на Lua, и, исходя из потребностей, их можно выбрать. Существуют и другие доступные веб-фреймворки, которые включают следующее:

  • Moonstalk позволяет эффективно разрабатывать и размещать динамически генерируемые веб-проекты, построенные на языке Lua; от базовых страниц до сложных приложений.

  • Lapis , фреймворк для создания веб-приложений с использованием MoonScript (или Lua), который работает внутри настроенной версии Nginx под названием OpenResty.

  • Lua Server Pages , плагин скриптового движка Lua, который отбрасывает любой другой подход к встроенной веб-разработке, предлагает впечатляющий краткий путь к традиционным страницам C-сервера.

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

Lapis , фреймворк для создания веб-приложений с использованием MoonScript (или Lua), который работает внутри настроенной версии Nginx под названием OpenResty.

Lua Server Pages , плагин скриптового движка Lua, который отбрасывает любой другой подход к встроенной веб-разработке, предлагает впечатляющий краткий путь к традиционным страницам C-сервера.

Эти веб-фреймворки могут использовать ваши веб-приложения и помочь вам в выполнении мощных операций.

Lua – доступ к базе данных

Для простых операций с данными мы можем использовать файлы, но иногда эти файловые операции могут быть неэффективными, масштабируемыми и мощными. Для этого мы можем часто переходить на использование баз данных. LuaSQL – это простой интерфейс от Lua к ряду систем управления базами данных. LuaSQL – это библиотека, которая обеспечивает поддержку различных типов SQL. Это включает в себя,

  • SQLite
  • Mysql
  • ODBC

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

Настройка базы данных MySQL

Чтобы использовать следующие примеры для правильной работы, нам нужна начальная настройка БД. Допущения перечислены ниже.

  • Вы установили и настроили MySQL с пользователем по умолчанию в качестве пользователя root и паролем «123456».

  • Вы создали тест базы данных.

  • Вы прошли учебник по MySQL, чтобы понять основы MySQL.

Вы установили и настроили MySQL с пользователем по умолчанию в качестве пользователя root и паролем «123456».

Вы создали тест базы данных.

Вы прошли учебник по MySQL, чтобы понять основы MySQL.

Импорт MySQL

Мы можем использовать простой оператор require для импорта библиотеки sqlite, предполагая, что ваша реализация Lua была выполнена правильно.

mysql = require "luasql.mysql"

Переменная mysql предоставит доступ к функциям, ссылаясь на основную таблицу mysql.

Настройка подключения

Мы можем установить соединение, инициируя среду MySQL, а затем создавая соединение для среды. Это показано ниже.

local env  = mysql.mysql()
local conn = env:connect('test','root','123456')

Вышеуказанное соединение подключится к существующему файлу MySQL и установит соединение с вновь созданным файлом.

Выполнить функцию

В соединении есть простая функция execute, которая поможет нам выполнить все операции с базами данных: создание, вставка, удаление, обновление и так далее. Синтаксис показан ниже –

conn:execute([[ 'MySQLSTATEMENT' ]])

В приведенном выше синтаксисе мы должны убедиться, что conn открыта и существует соединение MySQL, и заменить MySQLSTATEMENT на правильное выражение.

Пример создания таблицы

Простой пример создания таблицы показан ниже. Создает таблицу с двумя параметрами id типа integer и именем типа varchar.

mysql = require "luasql.mysql"

local env  = mysql.mysql()
local conn = env:connect('test','root','123456')

print(env,conn)

status,errorString = conn:execute([[CREATE TABLE sample2 (id INTEGER, name TEXT);]])
print(status,errorString )

Когда вы запустите вышеупомянутую программу, будет создана таблица с именем sample с двумя столбцами, а именно id и name.

MySQL environment (004BB178)	MySQL connection (004BE3C8)
0	nil

В случае какой-либо ошибки вам будет возвращено сообщение об ошибке вместо nil. Простое сообщение об ошибке показано ниже.

LuaSQL: Error executing query. MySQL: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '"id INTEGER, name TEXT)' at line 1

Пример вставки выписки

Оператор вставки для MySQL показан ниже.

conn:execute([[INSERT INTO sample values('11','Raj')]])

Пример обновления оператора

Заявление об обновлении для MySQL показано ниже.

conn:execute([[UPDATE sample3 SET name='John' where id ='12']])

Пример удаления выписки

Оператор удаления для MySQL показан ниже.

conn:execute([[DELETE from sample3 where id ='12']])

Выберите пример выписки

Что касается оператора select, нам нужно пройтись по каждой строке и извлечь необходимые данные. Простой оператор выбора показан ниже.

cursor,errorString = conn:execute([[select * from sample]])
row = cursor:fetch ({}, "a")

while row do
   print(string.format("Id: %s, Name: %s", row.id, row.name))
   -- reusing the table of results
   row = cursor:fetch (row, "a")
end

В приведенном выше коде conn является открытым MySQL-соединением. С помощью курсора, возвращаемого оператором execute, вы можете перебрать ответ таблицы и получить необходимые данные выбора.

Полный пример

Полный пример, включающий все приведенные выше утверждения, приведен ниже.

mysql = require "luasql.mysql"

local env  = mysql.mysql()
local conn = env:connect('test','root','123456')
print(env,conn)

status,errorString = conn:execute([[CREATE TABLE sample3 (id INTEGER, name TEXT)]])
print(status,errorString )

status,errorString = conn:execute([[INSERT INTO sample3 values('12','Raj')]])
print(status,errorString )

cursor,errorString = conn:execute([[select * from sample3]])
print(cursor,errorString)

row = cursor:fetch ({}, "a")

while row do
   print(string.format("Id: %s, Name: %s", row.id, row.name))
   row = cursor:fetch (row, "a")
end

-- close everything
cursor:close()
conn:close()
env:close()

Когда вы запустите вышеуказанную программу, вы получите следующий вывод.

MySQL environment (0037B178)	MySQL connection (0037EBA8)
0	nil
1	nil
MySQL cursor (003778A8)	nil
Id: 12, Name: Raj

Выполнение транзакций

Транзакции – это механизм, который обеспечивает согласованность данных. Транзакции должны иметь следующие четыре свойства –

  • Атомарность – либо транзакция завершена, либо ничего не происходит вообще.

  • Согласованность – транзакция должна начинаться в согласованном состоянии и оставлять систему в согласованном состоянии.

  • Изоляция – промежуточные результаты транзакции не видны за пределами текущей транзакции.

  • Долговечность – после совершения транзакции последствия сохраняются даже после сбоя системы.

Атомарность – либо транзакция завершена, либо ничего не происходит вообще.

Согласованность – транзакция должна начинаться в согласованном состоянии и оставлять систему в согласованном состоянии.

Изоляция – промежуточные результаты транзакции не видны за пределами текущей транзакции.

Долговечность – после совершения транзакции последствия сохраняются даже после сбоя системы.

Транзакция начинается с START TRANSACTION; и заканчивается оператором commit или rollback.

Начать транзакцию

Чтобы инициировать транзакцию, нам нужно выполнить следующую инструкцию в Lua, предполагая, что conn является открытым MySQL-соединением.

conn:execute([[START TRANSACTION;]])

Откат транзакции

Нам нужно выполнить следующую инструкцию, чтобы откатить изменения, сделанные после запуска транзакции.

conn:execute([[ROLLBACK;]])

Совершить транзакцию

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

conn:execute([[COMMIT;]])

Мы знали о MySQL из приведенного выше, а следующий раздел объясняет основные операции SQL. Запомните транзакции, хотя они не объяснены снова для SQLite3, но те же операторы должны работать и для SQLite3.

Импорт SQLite

Мы можем использовать простой оператор require для импорта библиотеки SQLite, предполагая, что ваша реализация Lua была выполнена правильно. Во время установки, папка libsql, которая содержит файлы, связанные с базой данных.

sqlite3 = require "luasql.sqlite3"

Переменная sqlite3 предоставит доступ к функциям, ссылаясь на основную таблицу sqlite3.

Настройка подключения

Мы можем установить соединение, запустив среду SQLite, а затем создав соединение для этой среды. Это показано ниже.

local env  = sqlite3.sqlite3()
local conn = env:connect('mydb.sqlite')

Вышеуказанное соединение подключится к существующему файлу SQLite или создаст новый файл SQLite и установит соединение с вновь созданным файлом.

Выполнить функцию

В соединении есть простая функция execute, которая поможет нам выполнить все операции с базами данных: создание, вставка, удаление, обновление и так далее. Синтаксис показан ниже –

conn:execute([[ 'SQLite3STATEMENT' ]])

В приведенном выше синтаксисе мы должны убедиться, что conn открыта и существует соединение sqlite3, и заменить SQLite3STATEMENT на правильное выражение.

Пример создания таблицы

Простой пример создания таблицы показан ниже. Создает таблицу с двумя параметрами id типа integer и именем типа varchar.

sqlite3 = require "luasql.sqlite3"

local env  = sqlite3.sqlite3()
local conn = env:connect('mydb.sqlite')
print(env,conn)

status,errorString = conn:execute([[CREATE TABLE sample ('id' INTEGER, 'name' TEXT)]])
print(status,errorString )

Когда вы запустите вышеупомянутую программу, будет создана таблица с именем sample с двумя столбцами, а именно id и name.

SQLite3 environment (003EC918)	SQLite3 connection (00421F08)
0	nil

В случае ошибки вы получите сообщение об ошибке вместо nil. Простое сообщение об ошибке показано ниже.

LuaSQL: unrecognized token: ""'id' INTEGER, 'name' TEXT)"

Пример вставки выписки

Оператор вставки для SQLite показан ниже.

 conn:execute([[INSERT INTO sample values('11','Raj')]])

Выберите пример выписки

Что касается оператора select, нам нужно пройтись по каждой строке и извлечь необходимые данные. Простой оператор выбора показан ниже.

cursor,errorString = conn:execute([[select * from sample]])
row = cursor:fetch ({}, "a")

while row do
   print(string.format("Id: %s, Name: %s", row.id, row.name))
   -- reusing the table of results
   row = cursor:fetch (row, "a")
end

В приведенном выше коде conn является открытым соединением sqlite3. С помощью курсора, возвращаемого оператором execute, вы можете перебрать ответ таблицы и получить необходимые данные выбора.

Полный пример

Полный пример, включающий все приведенные выше утверждения, приведен ниже.

sqlite3 = require "luasql.sqlite3"

local env  = sqlite3.sqlite3()
local conn = env:connect('mydb.sqlite')
print(env,conn)

status,errorString = conn:execute([[CREATE TABLE sample ('id' INTEGER, 'name' TEXT)]])
print(status,errorString )

status,errorString = conn:execute([[INSERT INTO sample values('1','Raj')]])
print(status,errorString )

cursor,errorString = conn:execute([[select * from sample]])
print(cursor,errorString)

row = cursor:fetch ({}, "a")

while row do
   print(string.format("Id: %s, Name: %s", row.id, row.name))
   row = cursor:fetch (row, "a")
end

-- close everything
cursor:close()
conn:close()
env:close()

Когда вы запустите вышеуказанную программу, вы получите следующий вывод.

SQLite3 environment (005EC918)	SQLite3 connection (005E77B0)
0	nil
1	nil
SQLite3 cursor (005E9200)	nil
Id: 1, Name: Raj

Мы можем выполнить все доступные запросы с помощью этой библиотеки libsql. Поэтому, пожалуйста, не останавливайтесь на этих примерах. Поэкспериментируйте различные операторы запросов, доступные в соответствующих MySQL, SQLite3 и других поддерживаемых БД в Lua.

Lua – программирование игр

Lua используется во многих игровых движках благодаря своей простой языковой структуре и синтаксису. Функция сборки мусора часто очень полезна в играх, которые потребляют много памяти из-за богатой графики, которая используется. Некоторые игровые движки, которые используют Lua, включают в себя –

  • Corona SDK
  • Гидерос Мобайл
  • ShiVa3D
  • Моаи SDK
  • ЛЮБИТЬ
  • CryEngine

Каждый из этих игровых движков основан на Lua, и в каждом из этих движков доступен богатый набор API. Мы рассмотрим возможности каждого вкратце.

Corona SDK

Corona SDK – это кроссплатформенный движок для мобильных игр, который поддерживает платформы iPhone, iPad и Android. Существует бесплатная версия Corona SDK, которую можно использовать для небольших игр с ограниченными возможностями. При необходимости вы можете перейти на другие версии.

Corona SDK предоставляет ряд функций, которые включают в себя следующее –

  • API для обработки физики и столкновений
  • Веб и сетевые API
  • API игровой сети
  • API объявлений
  • API аналитики
  • API базы данных и файловой системы
  • Крипто и математические API
  • Аудио и медиа API

Легче и быстрее разрабатывать приложения с использованием вышеуказанных API, а не использовать собственные API отдельно для iOS и Android.

Гидерос Мобайл

Gideros предоставляет кроссплатформенный SDK для создания игр для iOS и Android. Его можно использовать с выплеском Gideros. Некоторые из поразительных преимуществ Gideoros включают в себя следующее:

  • Разработка IDE – предоставляет собственную IDE, которая облегчает разработку приложений Gideros.

  • Мгновенное тестирование. При разработке игры ее можно протестировать на реальном устройстве через Wi-Fi всего за 1 секунду. Вам не нужно тратить свое время на процесс экспорта или развертывания.

  • Плагины – Вы можете легко расширить ядро ​​с помощью плагинов. Импортируйте свой существующий (C, C ++, Java или Obj-C) код, свяжите его с Lua и интерпретируйте их напрямую. Десятки плагинов с открытым исходным кодом уже разработаны и готовы к использованию.

  • Чистый ООП подход – Gideros предоставляет собственную систему классов со всеми основными стандартами ООП, что позволяет вам писать чистый и многократно используемый код для любой из ваших будущих игр.

  • Собственная скорость – разработанная на основе C / C ++ и OpenGL, ваша игра работает на родной скорости и полностью использует мощность процессоров и графических процессоров.

Разработка IDE – предоставляет собственную IDE, которая облегчает разработку приложений Gideros.

Мгновенное тестирование. При разработке игры ее можно протестировать на реальном устройстве через Wi-Fi всего за 1 секунду. Вам не нужно тратить свое время на процесс экспорта или развертывания.

Плагины – Вы можете легко расширить ядро ​​с помощью плагинов. Импортируйте свой существующий (C, C ++, Java или Obj-C) код, свяжите его с Lua и интерпретируйте их напрямую. Десятки плагинов с открытым исходным кодом уже разработаны и готовы к использованию.

Чистый ООП подход – Gideros предоставляет собственную систему классов со всеми основными стандартами ООП, что позволяет вам писать чистый и многократно используемый код для любой из ваших будущих игр.

Собственная скорость – разработанная на основе C / C ++ и OpenGL, ваша игра работает на родной скорости и полностью использует мощность процессоров и графических процессоров.

ShiVa3D

ShiVa3D – это один из игровых 3D-движков, который предоставляет графический редактор, предназначенный для создания приложений и видеоигр для Интернета, консолей и мобильных устройств. Он поддерживает несколько платформ, включая Windows, Mac, Linux, iOS, Android, BlackBerry, Palm OS, Wii и WebOS.

Некоторые из основных функций включают в себя

  • Стандартные плагины
  • API модификации сетки
  • IDE
  • Встроенный редактор Terrain, Ocean и анимации
  • Поддержка физического движка ODE
  • Полный контроль над картой света
  • Предварительный просмотр материалов, частиц, следов и HUD
  • Поддержка формата обмена Collada

Веб-версия Shiva3d абсолютно бесплатна, и другие издания, на которые вы подписаны.

Моаи SDK

Moai SDK – это кроссплатформенный движок для мобильных игр, который поддерживает платформы iPhone, iPad и Android. Платформа Moai изначально состояла из Moai SDK, игрового движка с открытым исходным кодом, и Moai Cloud, облачной платформы как службы для размещения и развертывания игровых сервисов. Теперь Moai Cloud отключен и доступен только игровой движок.

Moai SDK работает на нескольких платформах, включая iOS, Android, Chrome, Windows, Mac и Linux.

ЛЮБИТЬ

LOVE – это фреймворк, который вы можете использовать для создания 2D-игр. Это бесплатно и с открытым исходным кодом. Он поддерживает платформы Windows, Mac OS X и Linux.

Он предоставляет несколько функций, которые включают в себя,

  • Аудио API
  • API файловой системы
  • API клавиатуры и джойстика
  • Математический API
  • API окна и мыши
  • Физика API
  • Системные и таймерные API

CryEngine

CryEngine – игровой движок, разработанный немецким разработчиком игр Crytek. Он эволюционировал от поколения 1 до поколения 4 и является передовым решением для разработки. Он поддерживает игры для ПК, Xbox 360, PlayStation3 и WiiU.

Он предоставляет несколько функций, которые включают в себя,

  • Визуальные эффекты, такие как Естественное освещение и Динамические мягкие тени, Динамическое глобальное освещение в реальном времени, Объем распространения света, Затенение частиц, Тесселяция и так далее.

  • Система анимации персонажей и система индивидуализации персонажей.

  • Параметрическая анимация скелета и уникальный специализированный редактор анимации лица

  • Системы искусственного интеллекта, такие как многослойная навигационная сетка и система тактических точек. Также предоставляет Дизайнерскую систему редактирования AI.

  • В микшировании и профилировании игр, управляемой данными звуковой системе, динамических звуках, интерактивной музыке и т. Д.

  • Физические особенности как Процессуальная Деформация и Продвинутая Физика Веревки.

Визуальные эффекты, такие как Естественное освещение и Динамические мягкие тени, Динамическое глобальное освещение в реальном времени, Объем распространения света, Затенение частиц, Тесселяция и так далее.

Система анимации персонажей и система индивидуализации персонажей.

Параметрическая анимация скелета и уникальный специализированный редактор анимации лица

Системы искусственного интеллекта, такие как многослойная навигационная сетка и система тактических точек. Также предоставляет Дизайнерскую систему редактирования AI.

В микшировании и профилировании игр, управляемой данными звуковой системе, динамических звуках, интерактивной музыке и т. Д.

Физические особенности как Процессуальная Деформация и Продвинутая Физика Веревки.

Конечная записка

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

Lua – Стандартные библиотеки

Стандартные библиотеки Lua предоставляют богатый набор функций, которые реализуются непосредственно с C API и встроены в язык программирования Lua. Эти библиотеки предоставляют сервисы на языке программирования Lua, а также сторонние сервисы, такие как операции с файлами и БД.

Эти стандартные библиотеки, встроенные в официальный C API, предоставляются как отдельные модули C. Это включает в себя следующее –

  • Основная библиотека, которая включает в себя подпрограмму сопрограммы
  • Библиотека модулей
  • Струнные манипуляции
  • Таблица манипуляций
  • Математическая библиотека
  • Ввод и вывод файла
  • Средства операционной системы
  • Средства отладки

Основная библиотека

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

Sr.No. Библиотека / Метод и Цель
1

Обработка ошибок

Включает в себя функции обработки ошибок, такие как assert, error, как описано в Lua – Error Errorling .

2

Управление памятью

Включает функции автоматического управления памятью, связанные со сборкой мусора, как описано в Lua – Сборка мусора .

3

dofile ([имя файла])

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

4

Таким образом, глобальная переменная содержит глобальную среду (то есть _G._G = _G). Сам Lua не использует эту переменную.

5

getfenv ([f])

Возвращает текущую среду, используемую функцией. f может быть функцией Lua или числом, которое определяет функцию на этом уровне стека. Уровень 1 – это функция, вызывающая getfenv. Если данная функция не является функцией Lua или если f равно 0, getfenv возвращает глобальную среду. Значением по умолчанию для f является 1.

6

getmetatable (объект)

Если объект не имеет метатаблицы, возвращает ноль. В противном случае, если у метатаблицы объекта есть поле «__metatable», возвращается соответствующее значение. В противном случае возвращает метатаблицу данного объекта.

7

ipairs (t)

Эта функция выбирает индексы и значения таблиц.

8

load (func [, chunkname])

Загружает кусок, используя функцию func, чтобы получить его части. Каждый вызов func должен возвращать строку, которая объединяется с предыдущими результатами.

9

файл загрузки ([имя файла]))

Аналогичен загрузке, но получает фрагмент из имени файла или из стандартного ввода, если имя файла не указано.

10

loadstring (строка [, chunkname])

Аналогично загрузке, но получает фрагмент из заданной строки.

11

следующий (таблица [, индекс])

Позволяет программе пересекать все поля таблицы. Его первый аргумент – это таблица, а второй аргумент – это индекс в этой таблице. next возвращает следующий индекс таблицы и связанное с ней значение.

12

пары (т)

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

13

Распечатать (…)

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

14

rawequal (v1, v2)

Проверяет, равен ли v1 v2, не вызывая метаметод. Возвращает логическое значение.

15

rawget (таблица, индекс)

Получает реальное значение таблицы [index], не вызывая метаметод. таблица должна быть таблицей; Индекс может быть любым значением.

16

rawset (таблица, индекс, значение)

Устанавливает реальное значение таблицы [индекс] в значение, не вызывая метаметод. table должен быть таблицей, индексировать любое значение, отличное от nil, и value любое значение Lua. Эта функция возвращает таблицу.

17

выберите (индекс, …)

Если index является числом, возвращает все аргументы после индекса номера аргумента. В противном случае index должен быть строкой «#», а select возвращает общее количество дополнительных аргументов, которые он получил.

18

setfenv (f, таблица)

Устанавливает среду, которая будет использоваться данной функцией. f может быть функцией Lua или числом, которое определяет функцию на этом уровне стека. Уровень 1 – это функция, вызывающая setfenv. setfenv возвращает данную функцию. В качестве особого случая, когда f равно 0, setfenv изменяет среду работающего потока. В этом случае setfenv не возвращает значений.

19

setmetatable (таблица, метатабельный)

Устанавливает метатаблицу для данной таблицы. (Вы не можете изменить метатабель других типов из Lua, только из C.) Если метатабил равен нулю, удаляет метатабиль данной таблицы. Если исходный метатабль имеет поле «__metatable», возникает ошибка. Эта функция возвращает таблицу.

20

tonumber (e [, base])

Пытается преобразовать свой аргумент в число. Если аргумент уже является числом или строкой, конвертируемой в число, то tonumber возвращает это число; в противном случае возвращается ноль.

21

tostring (e)

Получает аргумент любого типа и преобразует его в строку в приемлемом формате. Для полного контроля над тем, как числа конвертируются, используйте string.format.

22

тип (v)

Возвращает тип единственного аргумента, закодированного в виде строки. Возможные результаты этой функции: «nil» (строка, а не значение nil), «number», «string», «boolean», «table», «function», «thread» и «userdata».

23

распаковать (список [, i [, j]])

Возвращает элементы из данной таблицы.

24

_ВЕРСИЯ

Глобальная переменная (не функция), которая содержит строку, содержащую текущую версию интерпретатора. Текущее содержимое этой переменной – «Lua 5.1».

25

Сопрограммы

Включает функции манипулирования сопрограммой, как описано в Lua – Coroutines .

Обработка ошибок

Включает в себя функции обработки ошибок, такие как assert, error, как описано в Lua – Error Errorling .

Управление памятью

Включает функции автоматического управления памятью, связанные со сборкой мусора, как описано в Lua – Сборка мусора .

dofile ([имя файла])

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

Таким образом, глобальная переменная содержит глобальную среду (то есть _G._G = _G). Сам Lua не использует эту переменную.

getfenv ([f])

Возвращает текущую среду, используемую функцией. f может быть функцией Lua или числом, которое определяет функцию на этом уровне стека. Уровень 1 – это функция, вызывающая getfenv. Если данная функция не является функцией Lua или если f равно 0, getfenv возвращает глобальную среду. Значением по умолчанию для f является 1.

getmetatable (объект)

Если объект не имеет метатаблицы, возвращает ноль. В противном случае, если у метатаблицы объекта есть поле «__metatable», возвращается соответствующее значение. В противном случае возвращает метатаблицу данного объекта.

ipairs (t)

Эта функция выбирает индексы и значения таблиц.

load (func [, chunkname])

Загружает кусок, используя функцию func, чтобы получить его части. Каждый вызов func должен возвращать строку, которая объединяется с предыдущими результатами.

файл загрузки ([имя файла]))

Аналогичен загрузке, но получает фрагмент из имени файла или из стандартного ввода, если имя файла не указано.

loadstring (строка [, chunkname])

Аналогично загрузке, но получает фрагмент из заданной строки.

следующий (таблица [, индекс])

Позволяет программе пересекать все поля таблицы. Его первый аргумент – это таблица, а второй аргумент – это индекс в этой таблице. next возвращает следующий индекс таблицы и связанное с ней значение.

пары (т)

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

Распечатать (…)

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

rawequal (v1, v2)

Проверяет, равен ли v1 v2, не вызывая метаметод. Возвращает логическое значение.

rawget (таблица, индекс)

Получает реальное значение таблицы [index], не вызывая метаметод. таблица должна быть таблицей; Индекс может быть любым значением.

rawset (таблица, индекс, значение)

Устанавливает реальное значение таблицы [индекс] в значение, не вызывая метаметод. table должен быть таблицей, индексировать любое значение, отличное от nil, и value любое значение Lua. Эта функция возвращает таблицу.

выберите (индекс, …)

Если index является числом, возвращает все аргументы после индекса номера аргумента. В противном случае index должен быть строкой «#», а select возвращает общее количество дополнительных аргументов, которые он получил.

setfenv (f, таблица)

Устанавливает среду, которая будет использоваться данной функцией. f может быть функцией Lua или числом, которое определяет функцию на этом уровне стека. Уровень 1 – это функция, вызывающая setfenv. setfenv возвращает данную функцию. В качестве особого случая, когда f равно 0, setfenv изменяет среду работающего потока. В этом случае setfenv не возвращает значений.

setmetatable (таблица, метатабельный)

Устанавливает метатаблицу для данной таблицы. (Вы не можете изменить метатабель других типов из Lua, только из C.) Если метатабил равен нулю, удаляет метатабиль данной таблицы. Если исходный метатабль имеет поле «__metatable», возникает ошибка. Эта функция возвращает таблицу.

tonumber (e [, base])

Пытается преобразовать свой аргумент в число. Если аргумент уже является числом или строкой, конвертируемой в число, то tonumber возвращает это число; в противном случае возвращается ноль.

tostring (e)

Получает аргумент любого типа и преобразует его в строку в приемлемом формате. Для полного контроля над тем, как числа конвертируются, используйте string.format.

тип (v)

Возвращает тип единственного аргумента, закодированного в виде строки. Возможные результаты этой функции: «nil» (строка, а не значение nil), «number», «string», «boolean», «table», «function», «thread» и «userdata».

распаковать (список [, i [, j]])

Возвращает элементы из данной таблицы.

_ВЕРСИЯ

Глобальная переменная (не функция), которая содержит строку, содержащую текущую версию интерпретатора. Текущее содержимое этой переменной – «Lua 5.1».

Сопрограммы

Включает функции манипулирования сопрограммой, как описано в Lua – Coroutines .

Библиотека модулей

Библиотека модулей предоставляет основные функции для загрузки модулей в Lua. Он экспортирует одну функцию напрямую в глобальную среду: требуется. Все остальное экспортируется в пакет таблицы. Подробности о библиотеке модулей описаны в предыдущей главе Lua – Модули .

Струнные манипуляции

Lua предоставляет богатый набор функций для работы со строками. В предыдущем уроке по Lua – Strings это подробно описано.

Таблица манипуляций

Lua зависит от таблиц почти во всех операциях. В предыдущем уроке Lua – Tables это подробно описано.

Ввод и вывод файла

Нам часто требуется средство хранения данных при программировании, и это обеспечивается стандартными библиотечными функциями для файлового ввода-вывода в Lua. Это обсуждалось в предыдущем уроке Lua – File I / O.

Средства отладки

Lua предоставляет библиотеку отладки, которая предоставляет нам все примитивные функции для создания нашего собственного отладчика. Это обсуждалось ранее в Lua – Руководство по отладке .

Lua – математическая библиотека

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

Sr.No. Библиотека / Метод и Цель
1

math.abs (x)

Возвращает абсолютное значение х.

2

math.acos (x)

Возвращает арккосинус от x (в радианах).

3

math.asin (x)

Возвращает арксинус x (в радианах).

4

математика (х)

Возвращает арктангенс х (в радианах).

5

math.atan2 (у, х)

Возвращает арктангенс y / x (в радианах), но использует знаки обоих параметров, чтобы найти квадрант результата. (Он также правильно обрабатывает случай, когда х равен нулю.)

6

math.ceil (x)

Возвращает наименьшее целое число, большее или равное x.

7

math.cos (x)

Возвращает косинус x (предполагается в радианах).

8

math.cosh (x)

Возвращает гиперболический косинус x.

9

math.deg (x)

Возвращает угол x (в радианах) в градусах.

10

math.exp (x)

Возвращает значение e power x.

11

math.floor (x)

Возвращает наибольшее целое число, меньшее или равное x.

12

math.fmod (x, y)

Возвращает остаток от деления x на y, которое округляет частное к нулю.

13

math.frexp (x)

Возвращает m и e, такие что x = m2e, e является целым числом, а абсолютное значение m находится в диапазоне [0,5, 1) (или ноль, когда x равен нулю).

14

math.huge

Значение HUGE_VAL, значение больше или равно любому другому числовому значению.

15

math.ldexp (м, е)

Возвращает m2e (e должно быть целым числом).

16

math.log (x)

Возвращает натуральный логарифм x.

17

math.log10 (x)

Возвращает основание-10 логарифм х.

18

math.max (x, …)

Возвращает максимальное значение среди своих аргументов.

19

math.min (x, …)

Возвращает минимальное значение среди своих аргументов.

20

math.modf (x)

Возвращает два числа, неотъемлемую часть x и дробную часть x.

21

math.pi

Значение пи.

22

math.pow (x, y)

Возвращает ху. (Вы также можете использовать выражение x ^ y для вычисления этого значения.)

23

math.rad (x)

Возвращает угол x (в градусах) в радианах.

24

math.random ([m [, n]])

Эта функция является интерфейсом к простой функции генератора псевдослучайных рандов, предоставляемой ANSI C. При вызове без аргументов возвращает равномерное псевдослучайное действительное число в диапазоне [0,1). При вызове с целым числом m, math.random возвращает равномерное псевдослучайное целое число в диапазоне [1, m]. При вызове с двумя целыми числами m и n math.random возвращает равномерное псевдослучайное целое число в диапазоне [m, n].

25

математика. случайное семя (х)

Устанавливает x в качестве «начального числа» для псевдослучайного генератора: равные начальные числа создают равные последовательности чисел.

26

математика (х)

Возвращает синус х (предполагается в радианах).

27

math.sinh (x)

Возвращает гиперболический синус x.

28

math.sqrt (x)

Возвращает квадратный корень из х. (Вы также можете использовать выражение x ^ 0.5 для вычисления этого значения.)

29

математика (х)

Возвращает тангенс x (предполагается в радианах).

30

математика (х)

Возвращает гиперболический тангенс x.

math.abs (x)

Возвращает абсолютное значение х.

math.acos (x)

Возвращает арккосинус от x (в радианах).

math.asin (x)

Возвращает арксинус x (в радианах).

математика (х)

Возвращает арктангенс х (в радианах).

math.atan2 (у, х)

Возвращает арктангенс y / x (в радианах), но использует знаки обоих параметров, чтобы найти квадрант результата. (Он также правильно обрабатывает случай, когда х равен нулю.)

math.ceil (x)

Возвращает наименьшее целое число, большее или равное x.

math.cos (x)

Возвращает косинус x (предполагается в радианах).

math.cosh (x)

Возвращает гиперболический косинус x.

math.deg (x)

Возвращает угол x (в радианах) в градусах.

math.exp (x)

Возвращает значение e power x.

math.floor (x)

Возвращает наибольшее целое число, меньшее или равное x.

math.fmod (x, y)

Возвращает остаток от деления x на y, которое округляет частное к нулю.

math.frexp (x)

Возвращает m и e, такие что x = m2e, e является целым числом, а абсолютное значение m находится в диапазоне [0,5, 1) (или ноль, когда x равен нулю).

math.huge

Значение HUGE_VAL, значение больше или равно любому другому числовому значению.

math.ldexp (м, е)

Возвращает m2e (e должно быть целым числом).

math.log (x)

Возвращает натуральный логарифм x.

math.log10 (x)

Возвращает основание-10 логарифм х.

math.max (x, …)

Возвращает максимальное значение среди своих аргументов.

math.min (x, …)

Возвращает минимальное значение среди своих аргументов.

math.modf (x)

Возвращает два числа, неотъемлемую часть x и дробную часть x.

math.pi

Значение пи.

math.pow (x, y)

Возвращает ху. (Вы также можете использовать выражение x ^ y для вычисления этого значения.)

math.rad (x)

Возвращает угол x (в градусах) в радианах.

math.random ([m [, n]])

Эта функция является интерфейсом к простой функции генератора псевдослучайных рандов, предоставляемой ANSI C. При вызове без аргументов возвращает равномерное псевдослучайное действительное число в диапазоне [0,1). При вызове с целым числом m, math.random возвращает равномерное псевдослучайное целое число в диапазоне [1, m]. При вызове с двумя целыми числами m и n math.random возвращает равномерное псевдослучайное целое число в диапазоне [m, n].

математика. случайное семя (х)

Устанавливает x в качестве «начального числа» для псевдослучайного генератора: равные начальные числа создают равные последовательности чисел.

математика (х)

Возвращает синус х (предполагается в радианах).

math.sinh (x)

Возвращает гиперболический синус x.

math.sqrt (x)

Возвращает квадратный корень из х. (Вы также можете использовать выражение x ^ 0.5 для вычисления этого значения.)

математика (х)

Возвращает тангенс x (предполагается в радианах).

математика (х)

Возвращает гиперболический тангенс x.

Тригонометрические функции

Простой пример использования тригонометрической функции показан ниже.

Live Demo

radianVal = math.rad(math.pi / 2)

io.write(radianVal,"n")

-- Sin value of 90(math.pi / 2) degrees
io.write(string.format("%.1f ", math.sin(radianVal)),"n")

-- Cos value of 90(math.pi / 2) degrees
io.write(string.format("%.1f ", math.cos(radianVal)),"n")

-- Tan value of 90(math.pi / 2) degrees
io.write(string.format("%.1f ", math.tan(radianVal)),"n")

-- Cosh value of 90(math.pi / 2) degrees
io.write(string.format("%.1f ", math.cosh(radianVal)),"n")

-- Pi Value in degrees
io.write(math.deg(math.pi),"n")

Когда мы запустим вышеуказанную программу, мы получим следующий вывод.

0.027415567780804
0.0 
1.0 
0.0 
1.0 
180

Другие общие математические функции

Простой пример использования общих математических функций показан ниже.

Live Demo

-- Floor
io.write("Floor of 10.5055 is ", math.floor(10.5055),"n")

-- Ceil
io.write("Ceil of 10.5055 is ", math.ceil(10.5055),"n")

-- Square root
io.write("Square root of 16 is ",math.sqrt(16),"n")

-- Power
io.write("10 power 2 is ",math.pow(10,2),"n")
io.write("100 power 0.5 is ",math.pow(100,0.5),"n")

-- Absolute
io.write("Absolute value of -10 is ",math.abs(-10),"n")

--Random
math.randomseed(os.time())
io.write("Random number between 1 and 100 is ",math.random(),"n")

--Random between 1 to 100
io.write("Random number between 1 and 100 is ",math.random(1,100),"n")

--Max
io.write("Maximum in the input array is ",math.max(1,100,101,99,999),"n")

--Min
io.write("Minimum in the input array is ",math.min(1,100,101,99,999),"n")

Когда мы запустим вышеуказанную программу, мы получим следующий вывод.

Floor of 10.5055 is 10
Ceil of 10.5055 is 11
Square root of 16 is 4
10 power 2 is 100
100 power 0.5 is 10
Absolute value of -10 is 10
Random number between 1 and 100 is 0.22876674703207
Random number between 1 and 100 is 7
Maximum in the input array is 999
Minimum in the input array is 1

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

Lua – Возможности операционной системы

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

Sr.No. Библиотека / Метод и Цель
1

os.clock ()

Возвращает приблизительную величину в секундах процессорного времени, используемого программой.

2

os.date ([формат [, время]])

Возвращает строку или таблицу, содержащую дату и время, отформатированные в соответствии с заданным форматом строки.

3

os.difftime (t2, t1)

Возвращает количество секунд от времени t1 до времени t2. В POSIX, Windows и некоторых других системах это значение точно равно t2-t1.

4

os.execute ([команда])

Эта функция эквивалентна системе функций ANSI C. Он передает команду для выполнения оболочкой операционной системы. Его первый результат – true, если команда завершилась успешно, или nil в противном случае.

5

os.exit ([code [, close])

Вызывает выход из функции ANSI C, чтобы завершить программу хоста. Если код равен true, возвращаемый статус – EXIT_SUCCESS; если код ложен, возвращаемый статус – EXIT_FAILURE; если код – число, возвращаемое состояние – это число.

6

os.getenv (varname)

Возвращает значение переменной среды процесса varname или nil, если переменная не определена.

7

os.remove (имя файла)

Удаляет файл (или пустой каталог в системах POSIX) с указанным именем. Если эта функция завершается ошибкой, она возвращает nil плюс строку, описывающую ошибку и код ошибки.

8

os.rename (старое имя, новое имя)

Переименовывает файл или каталог с именем oldname в newname. Если эта функция завершается ошибкой, она возвращает nil плюс строку, описывающую ошибку и код ошибки.

9

os.setlocale (locale [, category])

Устанавливает текущую локаль программы. locale – системно-зависимая строка, определяющая локаль; категория – необязательная строка, описывающая, какую категорию изменить: «all», «collate», «ctype», «денежный», «числовой» или «время»; категория по умолчанию – «все». Функция возвращает имя новой локали или nil, если запрос не может быть выполнен.

10

os.time ([таблица])

Возвращает текущее время при вызове без аргументов или время, представляющее дату и время, указанные в данной таблице. Эта таблица должна содержать поля year, month и day и может иметь поля hour (по умолчанию 12), min (по умолчанию 0), sec (по умолчанию 0) и isdst (по умолчанию nil). Описание этих полей см. В функции os.date.

11

os.tmpname ()

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

os.clock ()

Возвращает приблизительную величину в секундах процессорного времени, используемого программой.

os.date ([формат [, время]])

Возвращает строку или таблицу, содержащую дату и время, отформатированные в соответствии с заданным форматом строки.

os.difftime (t2, t1)

Возвращает количество секунд от времени t1 до времени t2. В POSIX, Windows и некоторых других системах это значение точно равно t2-t1.

os.execute ([команда])

Эта функция эквивалентна системе функций ANSI C. Он передает команду для выполнения оболочкой операционной системы. Его первый результат – true, если команда завершилась успешно, или nil в противном случае.

os.exit ([code [, close])

Вызывает выход из функции ANSI C, чтобы завершить программу хоста. Если код равен true, возвращаемый статус – EXIT_SUCCESS; если код ложен, возвращаемый статус – EXIT_FAILURE; если код – число, возвращаемое состояние – это число.

os.getenv (varname)

Возвращает значение переменной среды процесса varname или nil, если переменная не определена.

os.remove (имя файла)

Удаляет файл (или пустой каталог в системах POSIX) с указанным именем. Если эта функция завершается ошибкой, она возвращает nil плюс строку, описывающую ошибку и код ошибки.

os.rename (старое имя, новое имя)

Переименовывает файл или каталог с именем oldname в newname. Если эта функция завершается ошибкой, она возвращает nil плюс строку, описывающую ошибку и код ошибки.

os.setlocale (locale [, category])

Устанавливает текущую локаль программы. locale – системно-зависимая строка, определяющая локаль; категория – необязательная строка, описывающая, какую категорию изменить: «all», «collate», «ctype», «денежный», «числовой» или «время»; категория по умолчанию – «все». Функция возвращает имя новой локали или nil, если запрос не может быть выполнен.

os.time ([таблица])

Возвращает текущее время при вызове без аргументов или время, представляющее дату и время, указанные в данной таблице. Эта таблица должна содержать поля year, month и day и может иметь поля hour (по умолчанию 12), min (по умолчанию 0), sec (по умолчанию 0) и isdst (по умолчанию nil). Описание этих полей см. В функции os.date.

os.tmpname ()

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

Общие функции ОС

Простой пример использования общих математических функций показан ниже.

Live Demo

-- Date with format
io.write("The date is ", os.date("%m/%d/%Y"),"n")

-- Date and time
io.write("The date and time is ", os.date(),"n")

-- Time
io.write("The OS time is ", os.time(),"n")

-- Wait for some time
for i=1,1000000 do
end

-- Time since Lua started
io.write("Lua started before ", os.clock(),"n")

Когда мы запустим вышеуказанную программу, мы получим вывод, аналогичный следующему.

The date is 01/25/2014
The date and time is 01/25/14 07:38:40
The OS time is 1390615720
Lua started before 0.013

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

logo Lua 5.3 Руководство

by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes

перевел Ведерников Николай, Лысьва.

Copyright © 2015 Lua.org, PUC-Rio. Freely available under the terms of the Lua license.

1 – Введение

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

Как язык расширений, Lua не имеет понятия «главной» программы: он работает только как встроенный в основную программу клиент,встраивающая программа называется хост (host). Встраивающая программа может вызывать функции для запуска кусочков Lua кода, может писать и читать Lua переменные, может регистрировать C-функции чтобы вызывать их из Lua кода. Через использование С-функций Lua может быть расширен для решения различных задач, таким образом созданные адаптированные языки программирования имеют общую синтаксическую базу. Дистрибутив Lua включает простую хост-программу lua, которая использует библиотеку Lua для реализации полного независимого Lua интерпретатора, для интерактивного или пакетного использования.

Lua бесплатное программное обеспечение и предоставляется безо всяких гарантий. Официальный сайт www.lua.org.

Как и любое другое руководство, это руководство местами сухо. Описание решений принятых в основе дизайна 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-битное значение, включая нули (‘‘). Также Lua противник кодировок; никаких предположений о содержимом строки не делается.

Тип number использует два внутренних представления, или два подтипа, один называется integer (целое), второй float (число с плавающей запятой). Lua имеет явные правила о том, когда какое представление использовать, но при необходимости автоматически конвертирует значение между ними (см. §3.4.3). Следовательно, в большистве случаев программист может игнорировать разницу между целыми и реальными числами, или получить полный контроль над представлением каждого числа. Стандартный Lua использует 64-битные целые (integer) и вещественные числа двойной точности (double 64-bit), но также возможно скомпилировать Lua так, чтобы использовались 32-битные целые и/или вещественные числа одинарной точности (float 32-bit). Эта опция с 32 битами для целых и вещественных чисел особенно актуальна для малых машин и встроенных систем. (Смотри макрос LUA_32BITS в файле luaconf.h.)

Lua может вызывать и манипулировать функциями написанными на Lua и на С (см. §3.4.10). Оба типа функций в Lua представлены типом function(функция).

Тип userdata (пользовательские данные) предназначен для хранения произвольных С данных в Lua переменных. Значение userdata представляет блок памяти (raw memory). Существуют два типа пользовательских данных: full userdata (полные пользовательские данные) — объект с блоком памяти, которым управляет Lua, и light userdata (лёгкие пользовательские данные) — простой С указатель. Пользовательские данные не имеют предопределенных операторов в Lua, кроме оператора присвоения и сравнения на идентичность. Используя метатаблицы, программист может определить операции для значений full userdata (см. §2.4). Значения userdata не могут быть созданы или изменены в Lua, это возможно только через C API. Это гарантирует целостность данных, которыми владеет хост-программа.

Тип thread (поток) представляет независимый поток выполнения и используется для реализации сопрограмм (coroutine) (см. §2.6). Lua потоки это не реальные потоки операционной системы. Lua поддерживает сопрограммы на всех системах, даже на тех, где это не поддерживается операционной системой.

Тип table (таблица) реализует ассоциативные массивы, это значит, что массив может быть проиндексирован не только числами, но и любым Lua значением, кроме nil и NaN. (Not a Number специальное значение для представления неопределенных и непредставимых числовых результатов, таких как 0/0.) Таблицы могут быть гетерогенными (разнородными); т.е. могут содержать значения всех типов (кроме nil). Любой ключ со значением nil не считается частью таблицы. И наоборот, любой ключ, не являющийся частью таблицы, имеет ассоциированное значение nil.

Таблицы единственный механизм структурирования данных в Lua; они могут использоваться для представления обычных массивов, последовательностей, таблиц символов, множеств, записей, графов, деревьев и т.п. Для представления записей, Lua использует имена полей как индекс. Язык поддерживает представление a.name, как синтаксическое украшение a["name"]. Существуют различные пути создания таблиц в Lua (см. §3.4.9).

Мы используем термин последовательность (sequence) чтобы обозначить таблицу, где все ключи это натуральные числа {1..n} (1,2,3,…), где n — длина последовательности (см. §3.4.7).

Как и индексы, значения полей в таблице могут быть любого типа. В частности, т.к. функции это первоклассные значения, поля таблицы могут содержать функции. Такие таблицы также могут содержать методы (см. §3.4.11).

Индексирование в таблицах следует принципу «сырого» (raw) равенства в языке. Выражения a[i] и a[j] определяют один и тот же элемент таблицы, если и только если i и j равны (raw equal) (значит, равны без метаметодов). В частности, вещественные числа (float) с целыми значениями равны соответствующим целым (integer), т.е., 1.0 == 1. Во избежание неоднозначностей, любое реальное число с целым значением, которое испльзуется как ключ, конвертируется в соответствующее ему целое число. Например, если написать a[2.0] = true, фактически в таблицу будет вставлен целочисленный (integer) ключ 2. С другой стороны, 2 and «2» разные Lua значения и следовательно обозначают разные данные в таблице.

Таблицы, функции, потоки и пользовательские данные (userdata) — это объекты: переменные фактически не содержат их значений, только ссылкина них. Присвоение, передача параметров и возврат из функций всегда манипулируют ссылками на эти значения; эти операции не подразумевают никакого типа копирования.

Библиотечная функция type возвращает строку с названием переданного ей типа (см. §6.1).

2.2 – Окружения и глобальное окружение

Как будет описано в §3.2 и §3.3.3, любая ссылка на свободное имя (т.е., имя не связанное ни с каким определением) var синтаксически транслируется в _ENV.var. Кроме того, каждый кусок (chunk) компилируется в области внешней локальной переменной, называемой _ENV (см.§3.3.2), таким образом _ENV само никогда не бывает свободным именем в куске.

Несмотря на существование этой внешней переменной _ENV и трансляцию свободных имен, _ENV полностью регулярное имя. В частности, вы можете определить новые переменные и параметры с этим именем. Каждая ссылка на свободное имя использует _ENV, которая видима в данной точке программы, следуя обычным правилам видимости Lua (см. §3.5).

Любая таблица, используемая как значение переменной _ENV, называется окружение (environment).

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 код может явно сгенерировать ошибку, вызвав функцию error. Если вы нуждаетесь в перехвате ошибок в Lua, вы можете использовать pcallили xpcall для вызова функции в защищенном режиме.

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

Когда вы используете xpcall или lua_pcall, вы можете определить обработчик сообщений, который будет вызываться в случае ошибок. Эта функция вызывается с оригинальным сообщением об ошибке и возвращает новое сообщение об ошибке. Она вызывается до раскрутки стека, так она сможет получить больше информации об ошибке, например, проверяя стек и создавая историю стека (stack traceback). Этот обработчик сообщений остается защищенным в защищенном вызове; так, ошибка в обработчике сообщений лишь вызовет его снова. Если этот цикл будет достаточно длинным, Lua прервет его и вернет соответствующее сообщение.

2.4 – Метатаблицы и метаметоды

Каждое значение в Lua может иметь метатаблицу. Эта метатаблица обычная Lua таблица, которая определяет поведение оригинального значения в определенных специальных операциях. Вы можете изменять различные аспекты поведения в операциях со значением, изменяя специфические поля в метатаблице. Например, когда не цифровое значение является операндом в сложении, Lua проверяет есть ли в его метатаблице поле «__add» с функцией. И, если оно существует, Lua вызывает эту функцию для выполнения сложения.

Ключи в метатаблице это производные от имен событий; соответствующие им значения называются метаметоды. В предыдущем примере, событие — "add" (добавить) и метаметод — функция, которая выполняет сложение.

Вы можете запросить метатаблицу любого значения, используя функцию getmetatable.

Вы можете заменить метатаблицу таблицы, используя setmetatable. Нельзя изменять метатаблицы других типов из Lua кода (кроме, как используя библиотеку отладки (§6.10)); для этого вы должны использовать C API.

Таблицы и полные пользовательские данные (full userdata) имеют индивидуальные метатаблицы (хотя таблицы и пользовательские данные могут совместно использовать свои метатаблицы). Значения остальных типов используют одну метатаблицу на тип; т.е, существует одна метатаблица для всех чисел, одна для всех строк и т.д. По умолчанию, значения не имеют метатаблицу, но строковая библиотека создает метатаблицу для строкового типа (см. §6.4).

Метатаблица контролирует, как объект ведет себя в арифметических и битовых операциях, сравнениях при сортировке, конкатенации, определении длины, вызовах и индексировании. Метатаблица также может определять функцию, которая будет вызвана для таблицы или пользовательских данных при уничтожении сборщиком мусора (§2.5).

Детальное описание событий, контролируемых метатаблицами, представлено ниже. Каждая операция идентифицируется соответсвующим именем события. Ключ для каждого события это строка начинающаяся с двух подчеркиваний, ‘__‘; например, ключ для операции «add» строка «__add«. Имейте ввиду, что запросы метаметодов всегда прямые; доступ к метаметоду не запускает других метаметодов

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

  • «add»: + операция. Если любой операнд при сложении не число (и не строка, которую можно преобразовать в число), Lua попробует вызвать метаметод. Сначала, Lua проверит первый операнд (даже если он правильный). Если этот операнд не определяет метаметод для события «__add«, Lua проверит второй операнд. Если Lua найдет метаметод, он будет вызван с двумя операндами в качестве аргументов, и результат вызова (скорректированный до одного значения) будет результатом операции. Иначе будет сгенерирована ошибка.
  • «sub»: - операция (вычитание). Аналогично операции «add».
  • «mul»: * операция (умножение). Аналогично операции «add».
  • «div»: / операция (деление). Аналогично операции «add».
  • «mod»: % операция (остаток от деления). Аналогично операции «add».
  • «pow»: ^ операция (возведение в степень). Аналогично операции «add».
  • «unm»: - операция (одноместный минус). Аналогично операции «add».
  • «idiv»: // операция (целочисленное деление). Аналогично операции «add».
  • «band»: & операция (битовое И). Аналогично операции «add», за исключением того, что Lua будет использовать метаметод, если любой из операндов не целое и не значение приводимое к целому (см. §3.4.3).
  • «bor»: | операция (битовое ИЛИ). Аналогично операции «band».
  • «bxor»: ~ операция (битовое ИЛИ-НЕ). Аналогично операции «band».
  • «bnot»: ~ операция (битовое одноместное НЕ). Аналогично операции «band».
  • «shl»: << операция (битовый сдвиг влево). Аналогично операции «band».
  • «shr»: >> операция (битовый сдвиг вправо). Аналогично операции «band».
  • «concat»: .. операция (конкатенация). Аналогично операции «add», за исключением того, что Lua будет использовать метаметод, если любой из операндов не строка и не число (которое всегда приводимо к строке).
  • «len»: # операция (длина). Если объект не строка, Lua попытается использовать этот метаметод; Если метаметод определен, он будет вызван с объектом в качестве аргумента, и результат вызова (обрезанный до одного значения) будет использован как результат операции. Если метаметод не определен и объект таблица, Lua использует операцию длины таблицы (см. §3.4.7). Иначе, Lua сгенерирует ошибку.
  • «eq»: == операция (равенство). Аналогично операции «add», за исключением того, что Lua будет использовать метаметод, только если оба сравниваемых значения таблицы или полные пользовательские данные и они не примитивно равны. Результат вызова всегда преобразуется к логическому (boolean).
  • «lt»: < операция (меньше). Аналогично операции «add», за исключением того, что Lua будет использовать метаметод, только если оба сравниваемых значения не числа и не строки. Результат вызова всегда преобразуется к логическому (boolean).
  • «le»: <= операция (меньше или равно). В отличие от других операций, операция «<=» может использовать два разных события. Первое, Lua проверяет наличие метаметода «__le» в обоих операндах, также как в операции «lt». Если этот метаметод не найден, Lua попытается использовать событие «__lt«, предполагая, что a <= b эквивалентно not (b < a). Как и у других операторов сравнения, результат всегда логическое значение. (Это использование события «__lt» может быть убрано в следующих версиях, т.к. оно медленнее, чем реальный вызов метаметода «__le«.)
  • «index»: индексированный доступ table[key]. Это событие случается когда table не таблица или когда key не существует в table. Метаметод ищется в объекте table.Несмотря на имя, метаметод для этого события может быть функцией или таблицей. Если это функция, то она вызывается с table и key в качестве аргументов. Если таблица, то конечный результат это результат индексирования этой таблицы с ключом key. Это индексирование регулярное, не прямое, и оно также может вызывать срабатывание другого метаметода.
  • «newindex»: индексированное присваивание table[key] = value. Как и событие «index», это событие случается когда table не таблица или когда key не существует в table. Метаметод ищется в объекте table.Как и для индексированного доступа, метаметод для этого события может быть функцией или таблицей. Если это функция, то она вызывается с table, key и value в качестве аргументов. Если таблица, Lua производит индексированное присваивание для этой таблицы с тем же ключом и значением. Это присваивание регулярное, не прямое, и оно также может вызывать срабатывание другого метаметода.

    Всякий раз, когда срабатывает метаметод «newindex», Lua не выполняет примитивное присваивание. (Если необходимо, метаметод может самостоятельно вызвать rawset для выполнения присваивания.)

  • «call»: операция вызова func(args). Это событие случается когда Lua пытается вызвать значение, не являющееся функцией (т.е., func это не функция). Метаметод ищется в объекте func. Если он существует, то он вызывается с func в качестве первого аргумента, следом идут остальные аргументы из оригинального вызова (args).

Хорошая практика, добавлять все необходимые метаметоды в таблицу перед тем, как назначить её метатаблицей какого-то объекта. В частности, метаметод «__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 – Слабые таблицы

Слабая таблица (weak table) — это таблица, элементы которой это слабые ссылки (weak references). Слабая ссылка игнорируется сборщиком мусора. Другими словами, если на объект существуют только слабые ссылки, то объект будет уничтожен сборщиком мусора.

Слабая таблица может иметь слабые ключи, слабые значения или и то и другое. Таблица со слабыми значениями позволяет уничтожать её значения, но препятствует уничтожению её ключей. Таблица со слабыми значениями и ключами позволяет уничтожать и ключи и значения. В любом случае, если ключ или значение уничтожены, эта пара удаляется из таблицы. Слабость таблицы контролируется полем __mode в её метатаблице. Если поле __mode это строка содержащая символ  ‘k‘, в таблице слабые ключи. Если поле __mode содержит ‘v‘, в таблице слабые значения.

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

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

Только объекты, имеющие явную конструкцию, удаляются из слабых таблиц. Значения, такие как числа и легкие C функции, не являются субъектами для сборки мусора, и следовательно не удаляются из слабых таблиц (пока их ассоциированные значения не удалены). Хотя строки субъекты для сборки мусора, они не имеют явную конструкцию, и следовательно не удаляются из слабых таблиц.

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

Если слабая таблица среди воскрешенных объектов в цикле сборки, она не может быть правильно очищена до следующего цикла сборки.

2.6 – Сопрограммы

Lua поддерживает сопрограммы, так называемую совместную многопоточность. Сопрограмма в Lua представляет независимый поток выполнения. В отличе от потоков в многопоточных системах, сопрограммма прерывает свое исполнение только явным вызовом функции yield (уступить).

Сопрограмма создается функцией coroutine.create. Единственный аргумент функции это главная функция сопрограммы. Функция create только создает сопрограмму и возвращает её описатель (объект типа thread — поток); она не запускает сопрограмму.

Сопрограмма запускается вызовом coroutine.resume. При первом вызове coroutine.resume, в качестве первого аргумента передается поток, возвращенный функцией coroutine.create, сопрограмма начинает свое исполнение с вызова своей главной функции. Дополнительные аргументы, переданные в coroutine.resume, передаются как аргументы этой функции. После запуска сопрограммы, она выполняется пока не будет завершена или не уступит (yield).

Сопрограмма может завершить свое исполнение двумя путями: нормально, когда её главная функция вернет управление (явно или не явно, после последней инструкции); и ненормально, если произойдет незащищенная ошибка. В случае нормального завершения, coroutine.resume вернетtrue и значения, возвращенные главной фунцией сопрограммы. В случае ошибок, coroutine.resume вернет false и сообщение об ошибке.

Сопрограмма уступает, вызывая coroutine.yield. Когда сопрограмма уступает, соответсвующая coroutine.resume немедленно возвращает управление, даже если уступка случилась внутри вложенной функции (т.е., не в главной функции, а в функции прямо или косвенно вызванной из главной функции). В случае уступки, coroutine.resume также возвращает true и значения, переданные в coroutine.yield. В следующий раз, возобновление этой же сопрограммы продолжает её выполнение с точки, где она уступила вызовом coroutine.yield, возвращающим дополнительные аргументы, переданные в coroutine.resume.

Как и coroutine.create, функция coroutine.wrap создает сопрограмму, но вместо сопрограммы возвращает функцию, вызов которой возобновляет сопрограмму. Аргументы, переданные этой функции, идут как дополнительные аргументы в coroutine.resume. coroutine.wrapвозвращает все значения полученные от coroutine.resume, кроме первого (логический код ошибки). В отличие от coroutine.resume,coroutine.wrap не перехватывает ошибки; все ошибки передаются вызывающей стороне.

Для примера работы сопрограммы, рассмотрите следующий код:

     function foo (a)
       print("foo", a)
       return coroutine.yield(2*a)
     end
     
     co = coroutine.create(function (a,b)
           print("co-body", a, b)
           local r = foo(a+1)
           print("co-body", r)
           local r, s = coroutine.yield(a+b, a-b)
           print("co-body", r, s)
           return b, "end"
     end)
     
     print("main", coroutine.resume(co, 1, 10))
     print("main", coroutine.resume(co, "r"))
     print("main", coroutine.resume(co, "x", "y"))
     print("main", coroutine.resume(co, "x", "y"))

Запустив его, вы получите следующий результат:

     co-body 1       10
     foo     2
     main    true    4
     co-body r
     main    true    11      -9
     co-body x       y
     main    true    10      end
     main    false   cannot resume dead coroutine

Вы также можете создавать и манипулировать сопрограммами через C API: см. функции lua_newthread, lua_resume и lua_yield.

3 – Язык

Этот раздел описывает лексику, синтаксис и семантику Lua. Другими словами, этот раздел описывает какие лексемы (tokens) правильны, как они могут быть скомбинированы, и что их комбинации означают.

Языковые конструкции будут объясняться используя обычную расширенную БНФ нотацию, в которой {a} означает 0 или больше a, и [a] означает опциональную a. Нетерминалы показаны как non-terminal, ключевые слова показаны как kword, и другие терминальные символы показаны как ‘=’. Полный синтасис Lua описан в §9 в конце руководства.

3.1 – Лексические соглашения

Lua — это язык свободной формы. Он игнорирует пробелы (включая переходы на новую строку) и комментарии между лексическими элементами, кроме разделителей между именами и ключевыми словами.

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

Следующие ключевые слова зарезервированы и не могут использоваться как имена:

     and       break     do        else      elseif    end
     false     for       function  goto      if        in
     local     nil       not       or        repeat    return
     then      true      until     while

Язык Lua чувствителен к регистру символов: and — зарезервированное слово, но And и AND — два разных, допустимых имени. Как соглашение, программы должны избегать создания имен, которые начинаются с подчеркивания и следующими за ним одной или несколькими прописными буквами (например, _VERSION).

Следующие строки разделяют другие лексемы:

     +     -     *     /     %     ^     #
     &     ~     |     <<    >>    //
     ==    ~=    <=    >=    <     >     =
     (     )     {     }     [     ]     ::
     ;     :     ,     .     ..    ...

Литеральные строки могут быть ограничены сочетающимися одинарными или двойными кавычками, и могут содержать С-подобные управляющие последовательности: ‘a‘ (bell), ‘b‘ (backspace), ‘f‘ (form feed), ‘n‘ (newline), ‘r‘ (carriage return), ‘t‘ (horizontal tab), ‘v‘ (vertical tab), ‘\‘ (backslash), ‘"‘ (двойная кавычка) и ‘'‘ (апостроф [одинарная кавычка]). Обратный слеш, сопровождаемый реальным переходом на новую строку (newline), формирует переход строки (newline) в строке (string). Управляющая последовательность ‘z‘ пропускает следующий за ней диапазон пробелов, включая переходы строки; это особенно полезно, чтобы разбить и отступить длинную литеральную строку на несколько линий без добавления переводов строки и пробелов в содержимое строки.

Строки в Lua могут содержать любое 8-битное значение, влючая встроенные нули, которые могут быть записаны как ‘‘. Более того, возможно описать любой байт в литеральной строке его числовым значением. Это может быть сделано с помощью управляющей последовательности xXX, где XX — это пара шестнадцатиричных цифр, или с помощью ddd, где ddd — последовательность до трех десятичных цифр. (Обратите внимание, что если десятичная управляющая последовательность сопровождается цифрой, то она должна содержать ровно три цифры.)

Unicode-символ в кодировке UTF-8 может быть вставлен в литеральную строку с помощью последовательности u{XXX} (обратите внимание на обязательные фигурные скобки), где XXX — это одна или больше шестнадцатиричных цифр описывающих код символа.

Литеральные строки также могут быть определены используя длинные скобки. Мы определяем открывающую длинную скобку уровня n, как открывающую квадратную скобку, следующие за ней n знаков = и ещё одну открывающую квадратную скобку. Так, открывающая длинная скобка уровня 0 запишется так: [[, для уровня 1 — [=[, и так далее. Закрывающая длинная скобка определяется аналогично; например, закрывающая длинная скобка уровня 4 запишется так: ]====]. Длинный литерал начинается с открывающей длинной скобки любого уровня и завершается на первой закрывающей длинной скобке того же уровня. Это позволяет содержать любой текст, кроме закрывающей скобки того же уровня. Литералы в такой скобочной форме могут занимать несколько линий (строк), управляющие последовательности в таких строках не работают, длинные скобки других уровней игнорируются. Любой вид последовательности завершения строки (r, n, rn или nr) конвертируется в простой перевод строки n.

Любой байт в литеральной строке не подвержен влиянию правил своего представления. Тем не менее, Lua открывает файлы для парсинга в текстовом режиме, и функции системы могут иметь проблемы с некоторыми управляющими символами. Поэтому, для безопасного представления не текстовых данных в строке, следует использовать управляющие последовательности.

Для удобства, когда открывается длинная скобка с непосредственным переводом строки за ней, перевод строки не включается в результирующую строку. Например, в системе использующей ASCII (в которой ‘a‘ кодируется как 97, newline кодируется как 10 и ‘1‘ кодируется как 49), пять литеральных строк ниже кодируют одинаковые строки:

     a = 'alon123"'
     a = "alon123""
     a = '97lo104923"'
     a = [[alo
     123"]]
     a = [==[
     alo
     123"]==]

Числовая константа (или цифра) может быть записана с опциональной дробной частью и опциональной десятичной экспонентой, обозначенной буквой ‘e‘ или ‘E‘. Lua также поддерживает шестнадцатиричные константы, которые начинаются с 0x или 0X. Шестнадцатиричные константы также допускают использование дробной части и бинарной экспоненты, обозначеной буквой ‘p‘ или ‘P‘. Цифровая константа с разделительной точкой или экспонентой означает вещественное число; иначе она означает целое. Примеры допустимых целых чисел:

     3   345   0xff   0xBEBADA

Примеры допустимых вещественных чисел:

     3.0     3.1416     314.16e-2     0.31416E1     34e1
     0x0.1E  0xA23p-4   0X1.921FB54442D18P+1

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

3.2 – Переменные

Переменные — это место где хранятся значения. Существует три вида переменных: глобальные переменные, локальные переменные и поля таблиц.

Одно имя может означать глобальную или локальную переменную (или формальный параметр функции, который является частным случаем локальной переменной):

	var ::= Name

Name означает идентификаторы, как описано в §3.1.

Любое имя переменной предполагается глобальным, пока явно не определено локальным (см. §3.3.7). Локальные переменные лексически ограниченные: локальные переменные свободно доступны функциям, определенным внутри их области видимости (см. §3.5).

Перед первым присваиванием переменной, её значение равно nil.

Квадратные скобки используются для индексирования в таблице:

	var ::= prefixexp ‘[’ exp ‘]

Значение доступа к полям таблицы может быть изменено через метатаблицы. Доступ к индексированной переменной t[i] эквивалентно вызовуgettable_event(t,i). (См. §2.4 для полного описания функции gettable_event. Эта функция не определена и не используется в Lua. Мы используем её только для пояснения.)

Синтаксис var.Name — это лишь семантическое украшение для var["Name"]:

	var ::= prefixexp ‘.’ Name

Доступ к глобальной переменной x эквивалентен _ENV.x. в силу того, что блоки компилируются, _ENV никогда не является глобальным именем (см.§2.2).

3.3 – Выражения

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

3.3.1 – Блоки

Блок — это список выражений, которые выполняются последовательно:

	block ::= {stat}

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

	stat ::= ‘;

Вызовы функций и присваивания могут начинаться с открывающейся скобки. Эта возможность ведет к неоднозначности в грамматике Lua. Рассмотрим следующий фрагмент:

     a = b + c
     (print or io.write)('done')

Грамматика может рассматривать это двумя путями:

     a = b + c(print or io.write)('done')
     
     a = b + c; (print or io.write)('done')

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

     ;(print or io.write)('done')

Блок может быть явно выделен для создания единственного выражения:

	stat ::= do block end

Явные блоки полезны для контроля за областью видимости переменных. Явные блоки также иногда используются для добавления выраженияreturn в середину другого блока (см. §3.3.4).

3.3.2 – Куски

Единица компиляции в Lua называется куском (chunk). Синтаксически, кусок это простой блок:

	chunk ::= block

Lua обрабатывает кусок, как тело анонимной функции с переменным числом аргументов (см. §3.4.11). Как таковой, кусок может определять локальные переменные, получать аргументы и возвращать значения. Более того, такая анонимная функция компилируется в области видимости внешней локальной переменной _ENV (см. §2.2). Результирующая функция всегда имеет _ENV, как только свою upvalue, даже если не использует эту переменную.

Кусок может храниться в файле или в строке внутри хостовой программы. Для запуска куска, Lua сперва загружает его (load), прекомпилируя код куска в инструкции виртуальной машины, и затем запускает скомпилированный код.

Кусок также может быть прекомпилирован в бинарную форму; смотри программу luac и функцию string.dump. Программы в исходном коде и в скомпилированной форме взаимозаменяемы; Lua автоматически определяет тип файла и действует соответственно (см. load).

3.3.3 – Присваивание

Lua позволяет множественные присваивания. Синтаксис присваивания определяет список переменных с левой строны и список выражений с правой стороны. Элементы в обоих списках разделяются запятыми:

	stat ::= varlist ‘=’ explist
	varlist ::= var {‘,’ var}
	explist ::= exp {‘,’ exp}

Выражения обсуждаются в §3.4.

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

Оператор присваивания сперва вычисляет все свои выражения и лишь затем выполняет присваивание. Таким образом код

     i = 3
     i, a[i] = i+1, 20

устанавливает a[3] равным 20, не изменяя a[4], т.к. i в a[i] вычисляется (= 3) до присваивания ему 4. Аналогично, строка

     x, y = y, x

меняет местами значения x и y, и

     x, y, z = y, z, x

циклически переставляет значения x, y и z.

Значение присваиваний глобальным переменным и полям таблиц может быть изменено через метатаблицы. Присваивание индексированной переменной t[i] = val эквивалентно settable_event(t,i,val). (См. §2.4 для полного описания функции settable_event. Эта функция не определена и не используется в Lua. Мы используем её только для пояснения.)

Присванивание глобальной переменной x = val эквивалентно присваиванию _ENV.x = val (см. §2.2).

3.3.4 – Управляющие конструкции

Управляющие конструкции if, while и repeat имеют обычное значение и знакомый синтаксис:

	stat ::= while exp do block end
	stat ::= repeat block until exp
	stat ::= if exp then block {elseif exp then block} [else block] end

Lua также имеет две формы оператора for (см. §3.3.5).

Условное выражение в управляющей конструкции может возвращать любое значение. False и nil рассматриваются как false. Все значения, отличные от nil и false, рассматриваются как true (в частности, число 0 и пустая строка это тоже true).

В цикле repeatuntil, внутренний блок заканчивается после всего условия, а не на ключевом слове until. Так, условие может ссылаться на локальные переменные объявленные внутри цикла.

Оператор goto передает управление на метку. По синтаксическим причинам, метки в Lua тоже считаются выражениями:

	stat ::= goto Name
	stat ::= label
	label ::= ‘::’ Name ‘::

Метка видна в блоке где объявлена, за исключением вложенных блоков, где определена метка с таким же именем и вложенных функций. Goto может переходить на любую видимую метку, так далеко, пока не войдет в область видимости локальной переменной.

Метки и пустые выражения называются пустыми выражениями, так как они не производят дейтсвий.

Выражение break завершает исполнение цикла while, repeat или for, пропуская оставшиеся команды цикла:

	stat ::= break

break завершает самый внутренний цикл.

Выражение return используется для возврата значений из функции или куска (который является анонимной функцией). Функции могут возвращать несколько значений, поэтому синтаксис для выражения return следующий:

	stat ::= return [explist] [‘;’]

Выражение return может быть написано только, как последнее в блоке. Если действительно необходимо иметь return в середине блока, тогда можно использовать явный внутренний блок, как идиома do return end, теперь return это последнее выражение в его (внутреннем) блоке.

3.3.5 – Конструкция For

Конструкция for имеет две формы: цифровую и общую.

Цифровой цикл for повторяет блок кода, пока управляющая переменная изменяется в арифметической прогрессии. Он имеет следующий синтаксис:

	stat ::= for Name ‘=’ exp ‘,’ exp [‘,’ exp] do block end

block повторяется для name начиная с первого значения exp, пока не достигнет значения втрого exp, шагами равными третьему exp. Более точно, выражение for

     for v = e1, e2, e3 do block end

эквивалентно следующему коду:

     do
       local var, limit, step = tonumber(e1), tonumber(e2), tonumber(e3)
       if not (var and limit and step) then error() end
       var = var - step
       while true do
         var = var + step
         if (step >= 0 and var > limit) or (step < 0 and var < limit) then
           break
         end
         local v = var
         block
       end
     end

Имейте ввиду следующее:

  • Все три управляющие выражения вычисляются только один раз, перед тем как начнется цикл. Их результаты должны быть числами.
  • var, limit и step — невидимые переменные. Имена показаны здесь только для пояснения.
  • Если третье выражение (шаг) отсутствует, тогда используется шаг 1.
  • Для выхода из цикла for вы можете использовать break и goto.
  • Переменная цикла v является локальной для тела цикла. Если необходимо использовать её значение после цикла, сохраните его в другой переменной перед выходом из цикла.

Общий for работает через функции, называемые итераторами. На каждой итерации, функция-итератор вызывается чтобы выдать новое значение, остановка происходит, когда новое значение равно nil. Общий цикл for имеет следующий синтаксис:

	stat ::= for namelist in explist do block end
	namelist ::= Name {‘,’ Name}

Выражение for

     for var_1, ···, var_n in explist do block end

эквивалентно следующему коду:

     do
       local f, s, var = explist
       while true do
         local var_1, ···, var_n = f(s, var)
         if var_1 == nil then break end
         var = var_1
         block
       end
     end

Имейте ввиду следующее:

  • explist вычисляется только один раз. Его результат это функция итератор, состояние и начальное значение для первой итерируемой переменной.
  • f, s и var — невидимые переменные. Имена показаны здесь только для пояснения.
  • Для выхода из цикла for вы можете использовать break.
  • Переменная цикла var_i является локальной для тела цикла. Если необходимо использовать её значение после цикла, сохраните его в другой переменной перед выходом из цикла.

3.3.6 – Вызовы функций как выражения

Чтобы позволить побочные эффекты, вызовы функций могут запускаться как выражения:

	stat ::= functioncall

В этом случае все возвращенные значения отбрасываются. Вызовы функций рассматриваются в §3.4.10.

3.3.7 – Локальные определения

Локальные переменные могут быть объявлены в любой части блока. Определение может содержать начальное присваивание (инициализацию):

	stat ::= local namelist [‘=’ explist]

Если есть начальное присваивание, то оно имеет семантику схожую с множественным присваиванием (см. §3.3.3). Иначе, все переменные инициализируются значением nil.

Кусок также является блоком (см. §3.3.2), и следовательно локальные переменные могут быть объявлены в куске вне всякого явного блока.

Правила видимости локальных переменных рассматриваются в §3.5.

3.4 – Выражения

Базовые выражения в Lua следующие:

	exp ::= prefixexp
	exp ::= nil | false | true
	exp ::= Numeral
	exp ::= LiteralString
	exp ::= functiondef
	exp ::= tableconstructor
	exp ::= ‘...’
	exp ::= exp binop exp
	exp ::= unop exp
	prefixexp ::= var | functioncall | ‘(’ exp ‘)

Числа и литеральные строки рассматриваются в §3.1; переменные рассматриваются в §3.2; определения функций рассматриваются в §3.4.11; вызовы функций рассматриваются в §3.4.10; конструкторы таблиц описаны в §3.4.9. Выражения с переменными аргументами, обозначенными тремя точками (‘...‘), могут быть использованы только внутри функции с переменным числом аргументов; они описываются в §3.4.11.

Бинарные операторы, включая арифметические (см. §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()                -- корректируется до 0 результатов
     g(f(), x)          -- f() корректируется до 1 результата
     g(x, f())          -- g получает x и все результаты из f()
     a,b,c = f(), x     -- f() корректируется до 1 результата (c получает nil)
     a,b = ...          -- a получает первый множественный параметр, b получает
                        -- второй (a и b могут получить nil, если в множестве параметров нет
                        -- соответствующего параметра)
     
     a,b,c = x, f()     -- f() корректируется до 2 результатов
     a,b,c = f()        -- f() корректируется до 3 результатов
     return f()         -- возвращает все результаты из f()
     return ...         -- возвращает все полученные переменные параметры
     return x,y,f()     -- возвращает x, y и все результаты из f()
     {f()}              -- создает список с результатами из f()
     {...}              -- создает список со всеми переменными параметрами
     {f(), nil}         -- f() корректируется до 1 результата

Любое выражение, заключенное в скобки, всегда возвращает только одно значение. Т.е., (f(x,y,z)) всегда одно значение, даже если fвозвращает несколько значений. (Значение (f(x,y,z)) это первое из значений возвращенных f или nil, если f не вернет ни одного значения.)

3.4.1 – Арифметические операторы

Lua поддерживает следующие арифметические операторы:

  • +: сложение
  • -: вычитание
  • *: умножение
  • /: деление
  • //: целочисленное деление
  • %: модуль
  • ^: возведение в степень
  • -: одноместный минус

За исключением возведения в степень и деления, арифметические операторы работают следующим образом: Если оба операнда целые, операция производится над целыми и результатом является целое. Иначе, если оба операнда числа или строки, которые могут быть сконвертированы в числа (см. §3.4.3), они конвертируются в числа с плавающей запятой (float), операции производятся согласно обычным правилам арифметики вещественных чисел (обычно стандарт IEEE 754), и результатом будет число с плавающей запятой.

Возведение в степень и деление (/) всегда конвертирует операнды в вещественные числа и результат вещественное число. Возведение в степень использует функцию pow из ISO C, она работает и для не целых экспонент тоже.

Целочисленное деление (//) — это деление, которое округляет частное по отношению к минус беспонечности, т.е. нижнее от деления операндов.

Модуль определено как остаток от деления, которое округляет частное по отношению к минус беспонечности (целочисленное деление).

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

3.4.2 – Битовые операторы

Lua поддерживает следующие битовые операторы:

  • &: битовое И
  • |: битовое ИЛИ
  • ~: битовое ИЛИ НЕ
  • >>: правый сдвиг
  • <<: левый сдвиг
  • ~: одноместное битовое НЕ

Все битовые операторы преобразуют свои операнды в целые (см. §3.4.3), оперируют всеми битами этих целых и результат тоже целое.

Правый и левый сдвиги заполняют свободные биты нулями. Отрицательное смещение сдвигает в противоположном направлении; смещения с абсолютными значениями большими (или равными), чем число бит в целом, дают результат ноль (все биты сдвинуты наружу).

3.4.3 – Приведения и преобразования

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

Lua также конвертирует строки в числа, когда ожидается число.

В преобразовании целого в вещественное, если целое значение имеет точное представление как вещественное, это представление и будет результатом. Иначе, преобразование получает ближайшее большее или ближайшее меньшее представимое значение. Этот тип преобразования всегда успешен.

Преобразование вещественного в целое проверяет, что вещественное имеет точное представление как целое (т.е., вещественное имеет целое значение и в диапазоне представления целых). Если это так, то это представление будет результатом. Иначе, преобразование терпит неудачу.

Преобразование строк в числа идет следующим образом: Первое, строка преобразуется в целое или вещественное, следуя синтаксису и правилам лексера Lua. (Строка может содержать начальные и конечные пробелы и знак.) Затем, получившееся число (целое или вещественное) преобразуется в тип (целое или вещественное), требуемый в данном контексте (т.е., требуемый операцией которая конвертирует принудительно).

Преобразование чисел в строки использует не определенный читабельный формат. Для полного контроля над тем, как числа конвертируются в строки, используйте функцию format из строковой библиотеки (см. string.format).

3.4.4 – Операторы сравнения

Lua поддерживает следующие операторы сравнения:

  • ==: равенство
  • ~=: неравенство
  • <: меньше
  • >: больше
  • <=: меньше или равно
  • >=: больше или равно

Эти операторы всегда возвращают false или true.

Равенство (==) сперва сравнивает типы операндов. Если типы разные, то результат false. Иначе, сравниваются значения операндов. Строки сравниваются очевидным способом. Числа равны, если они обозначают одинаковые математические значения.

Таблицы, пользовательские данные и потоки сравниваются по ссылке: два объекта считаются равными только, если это один и тот же объект. Всегда, когда вы создаете новый объект (таблицу, пользовательские данные или поток), этот новый объект отличен от любого существующего объекта. Замыкания (closure) с одинаковыми ссылками всегда равны. Замыкания с любыми обнаруживаемыми различиями (разное поведение, разное определение) всегда различны.

Используя метаметод «eq», вы можете изменить способ, которым Lua сравнивает таблицы и пользовательские данные (см. §2.4).

Проверка на равенство не конвертирует строки в числа и наоборот. Так, "0"==0 вернет false, t[0] и t["0"] означают разные элементы в таблице.

Оператор ~= это явное отрицание равенства (==).

Операторы упорядочения работают следующим образом. Если оба аргумента числа, то они сравниваются согласно их математическим значениям. (независимо от их подтипов). Иначе, если оба аргумента строки, то их значения сравниваются согласно текущей локали. Иначе, Lua пытается вызвать метаметоды «lt» или «le» (см. §2.4). Сравнение a > b транслируется в b < a и a >= b транслируется в b <= a.

Следуя стандарту 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 используют ленивое вычисление; т.е., второй операнд вычисляется только если необходимо. Несколько примеров:

     10 or 20            --> 10
     10 or error()       --> 10
     nil or "a"          --> "a"
     nil and 10          --> nil
     false and error()   --> false
     false and nil       --> false
     false or nil        --> nil
     10 and 20           --> 20

(В этом руководстве, --> означает результат предыдущего выражения.)

3.4.6 – Конкатенация

Конкатенация строк в Lua обозначается двумя точками (‘..‘). Если оба операнда строки или числа, они конвертируются в строки согласно правилам, описанным в §3.4.3. Иначе, вызывается метаметод __concat (см. §2.4).

3.4.7 – Оператор длины

Оператор длины обозначается одноместным префиксом #. Длина строки это число байт в ней (т.е., обычное значение длины строки, когда каждый символ размером 1 байт).

Программа может модифицировать поведение оператора длины для любого значения, кроме строк, используя метаметод __len (см. §2.4).

Пока метаметод __len не определен, длина таблицы t определена только, если таблица t последовательность, т.е., набор её положительных числовых ключей равен {1..n} для какого-то положительного целого n. В этом случае, n это длина. Имейте ввиду, таблица как

     {10, 20, nil, 40}

это не последовательность, т.к. она имеет ключ 4, но не имеет ключ 3. (Так, там нет n, который в множестве {1..n} равен набору положительных числовых ключей этой таблицы.) Тем не менее, эти не числовые ключи не создают помех с независимой последовательностью в таблице.

3.4.8 – Приоритет

Приоритет операторов в Lua представлен далее, с меньшего к большему приоритету:

     or
     and
     <     >     <=    >=    ~=    ==
     |
     ~
     &
     <<    >>
     ..
     +     -
     *     /     //    %
     unary operators (not   #     -     ~)
     ^

Как обычно, чтобы изменить приоритет в выражении, вы можете использовать скобки. Операторы конкатенации (‘..‘) и возведения в степень (‘^‘) имеют правую ассоциативность. Все остальные бинарные операторы имеют левую ассоциативность.

3.4.9 – Конструкторы таблиц

Конструкторы таблиц — это выражения, которые создают таблицы. При каждом запуске конструктора создается новая таблица. Конструктор может использоваться для создания пустой таблицы или для создания таблицы с инициализацией некоторых её полей. Общий синтаксис конструкторов следующий:

	tableconstructor ::= ‘{’ [fieldlist] ‘}’
	fieldlist ::= field {fieldsep field} [fieldsep]
	field ::= ‘[’ exp ‘]’ ‘=’ exp | Name ‘=’ exp | exp
	fieldsep ::= ‘,’ | ‘;

Каждое поле вида [exp1] = exp2 добавляет новый элемент таблицы с ключем exp1 и значением exp2. Поле вида name = exp эквивалентно записи["name"] = exp. Поля вида exp эквивалентны [i] = exp, где i последовательные целые, начинающиеся с 1; поля в других форматах не влияют на этот счет. Например,

     a = { [f(1)] = g; "x", "y"; x = 1, f(x), [30] = 23; 45 }

эквивалентно

     do
       local t = {}
       t[f(1)] = g
       t[1] = "x"         -- первое exp
       t[2] = "y"         -- второе exp
       t.x = 1            -- t["x"] = 1
       t[3] = f(x)        -- третье exp
       t[30] = 23
       t[4] = 45          -- четвертое exp
       a = t
     end

Порядок присваиваний в конструкторе не определен. (Этот порядок важен только для повторяющихся ключей.)

Если последнее поле в списке имеет вид exp и выражение это вызов функции или обозначение множества аргументов (…), то все значения, возвращенные этим выражением, последовательно включаются в список (см. §3.4.10).

Список полей может иметь опциональный конечный разделитель, для удобства машинно-сгенерированного кода.

3.4.10 – Вызовы функций

Вызов функции в Lua имеет следующий синтаксис:

	functioncall ::= prefixexp args

При вызове функции, сперва вычисляются prefixexp и args. Если значение prefixexp имеет тип function, то вызывается эта функция с данными аргументами. Иначе, для объекта prefixexp вызывается метаметод «call», в качестве первого параметра передается значение prefixexp, затем остальные аргументы вызова. (см. §2.4).

Форма

	functioncall ::= prefixexp ‘:’ Name args

может быть использована для вызова «методов». Вызов v:name(args) это синтаксическое украшение для v.name(v,args), за исключением того, что v вычисляется только один раз.

Аргументы имеют следующий синтаксис:

	args ::= ‘(’ [explist] ‘)’
	args ::= tableconstructor
	args ::= LiteralString

Все выражения в аргументах вычисляются перед вызовом.

Вызов вида f{fields} это синтаксическое украшение для f({fields}); т.е. в качестве аргумента передается одна новая таблица.

Вызов вида f'string' (или f"string" или f[[string]]) это синтаксическое украшение для f('string'); т.е. в качестве аргумента передается одна литеральная строка.

Вызов вида return functioncall называется хвостовым вызовом (tail call). Lua реализует соответствующие хвостовые вызовы (proper tail call) (или соответствующую хвостовую рекурсию): в хвостовом вызове, вызванная функция повторно использует элементы стека вызывающей функции. Следовательно, не существует лимита на число вложенных хвостовых вызовов, выполняемых программой. Тем не менее, хвостовой вызов затирает любую отладочную информацию о вызывающей функции. Имейте ввиду, что хвостовой вызов происходит только с конкретным синтаксисом, где return имеет только один вызов функции в качестве аргумента; при таком синтаксисе вызывающая функция возвращает тоже, что и вызванная функция. Так, в следующих примерах хвостовой вызов не происходит:

     return (f(x))        -- результаты корректируются до 1
     return 2 * f(x)
     return x, f(x)       -- дополнительные результаты
     f(x); return         -- результаты отброшены
     return x or f(x)     -- результаты корректируются до 1

3.4.11 – Определения функций

Синтаксис для определения функции:

	functiondef ::= function funcbody
	funcbody ::= ‘(’ [parlist] ‘)’ block end

Следующее синтаксическое украшение упрощает определение функций:

	stat ::= function funcname funcbody
	stat ::= local function Name funcbody
	funcname ::= Name {‘.’ Name} [‘:’ Name]

Выражение

     function f () body end

транслируется в

     f = function () body end

Выражение

     function t.a.b.c.f () body end

транслируется в

     t.a.b.c.f = function () body end

Выражение

     local function f () body end

транслируется в

     local f; f = function () body end

но, не в

     local f = function () body end

(Это имеет значение, когда тело функции содержит ссылки на f.)

Определение функции — это исполняемое выражение, значение которого имеет тип function. Когда Lua предкомпилирует кусок, все тела функций в нем прекомпилируются тоже. Затем, всякий раз, когда Lua запускает определение функции, функция инстанцируется (или замыкается). Этот экземпляр функции (или замыкание [closure]) будет финальным значением выражения.

Параметры действуют как локальные переменные, инициализированные значениями аргументов:

	parlist ::= namelist [‘,’ ‘...’] | ‘...

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

Например, рассмотрим следующие определения:

     function f(a, b) end
     function g(a, b, ...) end
     function r() return 1,2,3 end

Мы получим следующее соответствие аргументов параметрам и vararg-выражению:

     Вызов            Пааметры
     
     f(3)             a=3, b=nil
     f(3, 4)          a=3, b=4
     f(3, 4, 5)       a=3, b=4
     f(r(), 10)       a=1, b=10
     f(r())           a=1, b=2
     
     g(3)             a=3, b=nil, ... -->  (пусто)
     g(3, 4)          a=3, b=4,   ... -->  (пусто)
     g(3, 4, 5, 8)    a=3, b=4,   ... -->  5  8
     g(5, r())        a=5, b=1,   ... -->  2  3

Результаты возвращаются выражением return (см. §3.3.4). Если управление достигает конца функции без выражения return, то функция не возвращает результатов.

Существует системозависимый предел числа значений, которые может вернуть функция. Этот предел гарантированно больше 1000.

Синтаксис двоеточия используется для определения методов, т.е. функций, которые имеют явный дополнительный параметр self. Таким образом, выражение

     function t.a.b.c:f (params) body end

это синтаксическое украшение для

     t.a.b.c.f = function (self, params) body end

3.5 – Правила видимости

Lua — язык с лексическими областями видимости. Область видимости локальной переменной начинается с первого выражения после её определения и продолжается до последнего не пустого выражения внутреннего блока, включающего определение. Рассмотрим следующий пример:

     x = 10                -- глобальная переменная
     do                    -- новый блок
       local x = x         -- новый 'x', со значением 10
       print(x)            --> 10
       x = x+1
       do                  -- другой блок
         local x = x+1     -- другой 'x'
         print(x)          --> 12
       end
       print(x)            --> 11
     end
     print(x)              --> 10  (глобальная переменная)

Учтите, что в определении вида local x = x, новый x пока вне зоны видимости и, таким образом, второй x ссылается на внешнюю переменную.

Согласно правилам видимости, локальные переменные могут быть свободно доступны функциям, определенным в их зоне видимости. Локальная переменная, которая используется внутренней функцией, внутри данной функции называется upvalue или внешняя локальная переменная.

Обратите внимание, каждое выполнение выражения local определяет новую локальную переменную. Рассмотрим следующий пример:

     a = {}
     local x = 20
     for i=1,10 do
       local y = 0
       a[i] = function () y=y+1; return x+y end
     end

Цикл создает 10 замыканий (т.е., 10 экземпляров анонимной функции). Каждое из этих замыканий использует разные переменные y и общую для всех x.

4 – Программный интерфейс (API)

Этот раздел описывает C API для Lua, т.е. набор C функций, доступный хостовой программе для взаимодействия с Lua. Все API функции и связанные типы и константы определены в заголовочном файле lua.h.

Каждый раз, когда мы используем термин «функция», любая возможность в API может быть реализована как макрос. Везде, где не оговорено обратное, все такие макросы используют каждый свой аргумент только один раз (исключая первый аргумент, который всегда является контекстом Lua) и не генерируют ни каких скрытых побочных эффектов.

Как и в большинстве C библиотек, функции Lua API не проверяют свои аргументы на корректность и согласованность. Тем не менее, вы можете изменить это поведение, скомпилировав Lua с включенным определением LUA_USE_APICHECK.

4.1 – Стек

Чтобы передавать значения из и в С Lua использует виртуальный стек. Каждый элемент этого стека представляет Lua значение (nil, number, string и др.).

Кажды раз, когда Lua вызывает C, вызванная функция получает новый стек, который независим от предыдущих стеков и стеков активных в данный момент C функций. Этот стек изначально содержит все аргументы для C функции, туда же C функция ложит свои результаты, чтобы вернуть вызывающей стороне (см. lua_CFunction).

Для удобства, большинство операций запроса в API не следуют строгой стековой дисциплине. Напротив, они могут ссылаться на любой элемент в стеке, используя его индекс: Положительный индекс представляет абсолютную позицию в стеке (начиная с 1); отрицательный индекс представляет смещение относительно вершины стека. Точнее, если стек имеет n элементов, индекс 1 представляет первый элемент (т.е., элемент, который был положен на стек первым) и индекс n представляет последний элемент; индекс -1 также представляет последний элемент (т.е., элемент на вершине стека) и индекс -n представляет первый элемент.

4.2 – Размер стека

Когда вы работаете с Lua API, вы ответственны за гарантирование согласованности. В частности, вы ответственны за контроль над переполнением стека. Вы можете использовать функцию lua_checkstack чтобы проверять, что стек имеет достаточно места для новых элементов.

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

Когда вы вызываете Lua функцию без определенного числа результатов (см. lua_call), Lua гарантирует, что стек имеет достаточно места для помещения всех результатов, но не гарантирует любое дополнительное пространство. Так, перед тем как положить что-либо на стек после вызова функции, вы должны использовать lua_checkstack.

4.3 – Правильные и допустимые индексы

Любая API функция, получающая стековые индексы, работает только с правильными индексами или допустимыми индексами.

Правильный индекс — это индекс, который ссылается на позицию, содержащую модифицируемое Lua значение. Допустимый диапазон включает стековые индексы между 1 и вершиной стека (1 ≤ abs(index) ≤ top) плюс псевдоиндексы, которые представляют некоторые позиции, доступные для C кода, но не находящиеся в стеке. Псевдоиндексы используются для доступа к реестру (см. §4.5) и к внешним локальным переменным (upvalue) C функции (см. §4.4).

Функции, не нуждающиеся в специфической изменяемой позиции, а нуждающиеся только в значении (т.е., функции запросов), могут быть вызваны с допустимыми индексами. Допустимым индексом может быть любой правильный индекс, но это также может быть любой положительный индекс после вершины стека внутри пространства, выделенного для стека, т.е., индексы выше размера стека. (Учтите, что 0 это всегда недопустимый индекс.) Если не оговорено иное, API функции работают с допустимыми индексами.

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

Для функций, которые могут быть вызваны с допустимыми индексами, любой не правильный индекс, трактуется как индекс к значению виртуального типа LUA_TNONE, которое ведет себя как значение nil.

4.4 – C замыкания

Когда C функция создана, можно ассоциировать с ней несколько значений, таким образом создав C замыкание (closure) (см. lua_pushcclosure); эти значения называются upvalue и доступны функции во время вызова.

При каждом вызове C функции, её upvalue располагаются по специфическим псевдоиндексам. Псевдоиндексы создаются макросомlua_upvalueindex. Первое upvalue, ассоциированное с функцией, располагается по индексу lua_upvalueindex(1), и так далее. Любое обращение к lua_upvalueindex(n), где n больше количества upvalue текущей функции (но не больше 256), создает допустимый, но не правильный индекс.

4.5 – Реестр

Lua предоставляет реестр, предопределенную таблицу, которая доступна C коду для хранения любых Lua значений. Таблица рееста всегда расположена по псевдоидексу LUA_REGISTRYINDEX. Любая C библиотека может хранить данные в этой таблице, но она должна заботиться о выборе уникальных ключей, чтобы избежать коллизий с другими библиотеками. Обычно, вы должны использовать в качестве ключа строку содержащую имя библиотеки, или легкие пользовательские данные (light userdata) с адресом C объекта в вашем коде, или любой Lua объект созданный вашим кодом. Как и имена переменных, ключи, начинающиеся с подчеркивания со следующими за ним прописными буквами, зарезервированы для Lua.

Целочисленные ключи в реестре используются механизмом ссылок (см. luaL_ref) и некоторыми предопределенными значениями. Следовательно, целочисленные ключи не должны использоваться для других целей.

Когда вы создаете новый Lua контекст, его реестр содержит некоторые предопределенные значения. Эти предопределенные значения индексируются целочисленными ключами, определенными как константы в lua.h. Определены следующие константы:

  • LUA_RIDX_MAINTHREAD: По этому индексу в реестре расположен главный поток контекста. (Главный поток создается при создании контекста.)
  • LUA_RIDX_GLOBALS: По этому индексу в реестре расположено глобальное окружение.

4.6 – Обработка ошибок в C

Внутри, для обработки ошибок Lua использует C longjmp. (Lua будет использовать исключения, если вы скомпилируете его как C++; для подробностей ищите LUAI_THROW в исходном коде.) Когда Lua сталкивается с любой ошибкой (такой как ошибка выделения памяти, ошибки типов, синтаксические ошибки и ошибки времени выполнения), он возбуждает ошибку; т.е., делает длинный переход (long jump). Защищенное окружениеиспользует setjmp для установки точки восстановления; любая ошибка переходит к самой последней точке восстановления.

Если ошибка случается за пределами защищенного окружения, Lua вызывает функцию паники (см. lua_atpanic) и затем вызывает abort, завершая хостовое приложение. Ваша функция паники может избежать завершения приложения, если не вернет управление (т.е., сделает длинный переход [long jump] на вашу точку восстановления вне Lua).

Функция паники запускается как обработчик сообщений (см. §2.3); в частности, сообщение об ошибке лежит на вершине стека. Тем не менее, это не гарантирует стековое пространство. Чтобы положить что-либо на стек, функция паники должна сперва проверить доступное место (см. §4.2).

Большинство API функций могут возбуждать ошибки, например при выделении памяти. Описание для каждой функции предупреждает, что она может возбуждать ошибки.

Внутри C функции вы можете сгенерировать ошибку вызовом lua_error.

4.7 – Обработка уступок в C

Внутри, для приостановки сопрограммы Lua использует C longjmp. Следовательно, если C функция foo вызывает функцию API и эта API функция уступает (прямо или опосредованно, вызывая другую функцию, которая уступает), Lua больше не может вернуться к foo, потому что longjmpудаляет свой фрейм из C стека.

Чтобы избежать такой тип проблем, Lua возбуждает ошибку каждый раз, когда происходит уступка через вызов API, за исключением трех функций:lua_yieldk, lua_callk и lua_pcallk. Все эти функции получают функцию продолжения (как параметр k) чтобы продолжить исполнение после уступки.

Чтобы рассмотреть продолжения установим некоторую терминологию. Мы имеем C функцию вызванную из Lua, назовем её оригинальной функцией. Эта оригинальная функция затем вызывает одну из этих трех API функций, которые мы будем называть вызываемой функцией, которая затем уступает текущий поток. (Это может случиться, когда вызываемая функция это lua_yieldk, или когда вызываемая функция любая изlua_callk или lua_pcallk и вызванная ими функция уступает.)

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

Как иллюстрацию, рассмотрим следующую функцию:

     int original_function (lua_State *L) {
       ...     /* code 1 */
       status = lua_pcall(L, n, m, h);  /* calls Lua */
       ...     /* code 2 */
     }

Сейчас мы хотим позволить Lua коду, запущенному через lua_pcall, уступать. Сначала, перепишем нашу функцию как показано ниже:

     int k (lua_State *L, int status, lua_KContext ctx) {
       ...  /* code 2 */
     }
     
     int original_function (lua_State *L) {
       ...     /* code 1 */
       return k(L, lua_pcall(L, n, m, h), ctx);
     }

В этом коде, новая функция k это функция продолжения (с типом lua_KFunction), которая должна делать всю работу, которую оригинальная функция делала после вызова lua_pcall. Мы должны проинформировать Lua о том, что если Lua код, запущенный lua_pcall, будет прерван (ошибки или уступка), то необходимо вызвать k; переписываем код, заменяя lua_pcall на lua_pcallk:

     int original_function (lua_State *L) {
       ...     /* code 1 */
       return k(L, lua_pcallk(L, n, m, h, ctx2, k), ctx1);
     }

Обратите внимание на внешний явный вызов продолжения: Lua будет вызывать продолжение только при необходимости, т.е. в случае ошибок или возобновления после уступки. Если вызванная функция возвратится нормально, без уступок, lua_pcallklua_callk) также возвратятся нормально. (Конечно, в этом случае вместо вызова продолжения, вы можете выполнить эквивалентную работу прямо внутри оригинальной функции.)

Рядом с Lua состоянием, функция продолжения имеет два других параметра: конечный статус вызова и контекстное значение (ctx), которое изначально передается в lua_pcallk. (Lua не использует это контекстное значение; только передает его из оригинальной функции в функцию продолжения.) Для lua_pcallk, статус это тоже значение, которое будет возвращено функцией lua_pcallk, за исключением того, что после выполнения уступки это будет LUA_YIELD, (взамен LUA_OK). Для lua_yieldk и lua_callk, когда Lua вызывает продолжение, статус всегда будет равен LUA_YIELD. (Для этих двух функций в случае ошибок Lua не вызовет продолжение, т.к. они не обрабатывают ошибки.) Аналогично, когда используется lua_callk, вы должны вызывать функцию продолжения со статусом LUA_OK. (Для lua_yieldk, нет смысла в прямом вызове функции продолжения, т.к. lua_yieldk обычно не возвращается.)

Lua обрабатывает функцию продолжения так, как будто это оригинальная функция. Функция продолжения получает тот же Lua стек из оригинальной функции, в том же состоянии, как если бы вызываемая функция вернулась. (Например, после lua_callk функция и её аргументы удалены из стека и заменены результатами вызова.) Она также будет иметь те же upvalue. Результаты, которые она вернет, будут обработаны Lua так, как будто их вернула оригинальная функция.

4.8 – Функции и типы

Здесь представлен список всех функций и типов из C API в алфавитном порядке. Каждая функция имеет индикатор вида:[-o, +p, x]

Первое поле, o, показывает сколько элементов функция снимает со стека. Второе поле, p, показывает сколько элементов функция ложит на стек. (Функции всегда ложат свои результаты после того, как снимут аргументы со стека.) Поле вида x|y означает, что функция может ложить (или снимать) x или y элементов, в зависимости от ситуации; знак вопроса ‘?‘ означает, что по аргументам функции невозможно определить сколько элементов функция ложит/снимает (т.е. функция может зависеть от того, что лежит в стеке). Третье поле, x, показыает может ли функция генерировать ошибки: ‘-‘ означает, что функция никогда не генерирует ошибки; ‘e‘ означает, что функция может генерировать ошибки; ‘v‘ означает, что фунция предназначена для генерации ошибки.

lua_absindex

[-0, +0, –]

int lua_absindex (lua_State *L, int idx);

Конвертирует допустимый индекс idx в эквивалентный абсолютный индекс (который не зависит от вершины стека).

lua_Alloc

typedef void * (*lua_Alloc) (void *ud,
                             void *ptr,
                             size_t osize,
                             size_t nsize);

Тип функции выделения памяти, которая используется состоянием Lua. Функция выделения памяти должна предоставлять функциональность подобную функции realloc, но не точно такую же. Её аргументы ud — непрозрачный указатель, передаваемый в lua_newstate; ptr — указатель на блок для выделения/перераспределения/освобождения; osize — оригинальный размер блока или код, определяющий под что выделяется память;nsize — новый размер блока.

Когда ptr не NULL, osize это размер блока по указателю ptr, т.е. размер полученный при выделении или перераспределении.

Когда ptr = NULL, osize кодирует тип объекта, для которого выделяется память. osize может быть равен LUA_TSTRING, LUA_TTABLE,LUA_TFUNCTION, LUA_TUSERDATA и LUA_TTHREAD, когда (и только когда) Lua создает новый объект данного типа. Когда osize какое-то другое значение, Lua выделяет память для чего-то другого.

Lua предполагает следующее поведение функции выделения памяти:

Когда nsize = 0, функция должна действовать как free и возвращать NULL.

Когда nsize != 0, функция должна действовать как realloc. Функция возвращает NULL только, если не может выполнить запрос. Lua предполагает, что функция выделения памяти не может выдать ошибку при osize >= nsize.

Здесь представлена простая реализация функции выделения памяти. Она используется во вспомогательной библиотеке функцией luaL_newstate.

     static void *l_alloc (void *ud, void *ptr, size_t osize,
                                                size_t nsize) {
       (void)ud;  (void)osize;  /* not used */
       if (nsize == 0) {
         free(ptr);
         return NULL;
       }
       else
         return realloc(ptr, nsize);
     }

Учтите, что стандартный C гарантирует, что free(NULL) не производит действий и realloc(NULL,size) эквивалентно malloc(size). Этот код предполагает, что realloc не вызывает ошибок при уменьшении блока. (Хотя стандартный C не предполагает такого поведения, кажется, это безопасное предположение.)

lua_arith

[-(2|1), +1, e]

void lua_arith (lua_State *L, int op);

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

Значение op должно быть одной из следующих констант:

  • LUA_OPADD: сложение (+)
  • LUA_OPSUB: вычитание (-)
  • LUA_OPMUL: умножение (*)
  • LUA_OPDIV: деление (/)
  • LUA_OPIDIV: целочисленное деление (//)
  • LUA_OPMOD: модуль (%)
  • LUA_OPPOW: возведение в степень (^)
  • LUA_OPUNM: математическое отрицание (одноместный -)
  • LUA_OPBNOT: битовое отрицание (~)
  • LUA_OPBAND: битовое И (&)
  • LUA_OPBOR: битовое ИЛИ (|)
  • LUA_OPBXOR: битовое ИЛИ-НЕ (~)
  • LUA_OPSHL: левый сдвиг (<<)
  • LUA_OPSHR: правый сдвиг (>>)

lua_atpanic

[-0, +0, –]

lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf);

Устанавливает новую функцию паники и возвращает старую (см. §4.6).

lua_call

[-(nargs+1), +nresults, e]

void lua_call (lua_State *L, int nargs, int nresults);

Вызывает функцию.

Для вызова функции вы должны использовать следующий протокол: первое, вызываемая функция должна быть помещена в стек; затем, на стек ложатся аргументы в прямом порядке; т.е., первый аргумент ложится первым. Наконец, производится вызов lua_call; nargs — количество аргументов на стеке. Когда функция вызывается, все аргументы и функция снимаются со стека. Результаты ложатся на стек, когда функция возвращается. Количество результатов корректируется до nresults, если nresults не равно LUA_MULTRET. В этом случае, все результаты из функции ложатся на стек. Lua заботится, чтобы возвращенным значениям хватило места в стеке. Результаты функции ложатся в стек в прямом порядке (первый результат ложится первым), так что после вызова последний результат будет на вершине стека.

Любая ошибка внутри вызванной функции распространяется вверх (с longjmp).

Следующий пример показывает, как хостовая программа может выполнить действия эквивалентные этому Lua коду:

     a = f("how", t.x, 14)

Это же в  C:

     lua_getglobal(L, "f");         /* функция для вызова */
     lua_pushliteral(L, "how");     /* 1-й аргумент */
     lua_getglobal(L, "t");         /* таблица для индексирования */
     lua_getfield(L, -1, "x");      /* положить результат t.x (2-й аргумент) */
     lua_remove(L, -2);             /* удаление 't' из стека */
     lua_pushinteger(L, 14);        /* 3-й аргумент */
     lua_call(L, 3, 1);             /* вызов 'f' с 3 аргументами и 1 результатом */
     lua_setglobal(L, "a");         /* установить глобальную 'a' */

Обратите внимание, что код выше сбалансирован: после его выполнения стек возвращается в первоначальное состояние. Это хорошая практика програмирования.

lua_callk

[-(nargs + 1), +nresults, e]

void lua_callk (lua_State *L,
                int nargs,
                int nresults,
                lua_KContext ctx,
                lua_KFunction k);

Эта функция аналогична lua_call, но позволяет вызываемой функции уступать (см. §4.7).

lua_CFunction

typedef int (*lua_CFunction) (lua_State *L);

Тип для C функций.

Для правильного взаимодействия с Lua, C функция должна использовать следующий протокол, который определяет как передаются параметры и результаты: C функция получает аргументы из Lua в своём стеке в прямом порядке (первый аргумент ложится первым). Так, когда функция стартует, lua_gettop(L) возвращает количество аргументов, полученных функцией. Первый аргумент (если существует) находится по индексу 1, последний аргумент находится по индексу lua_gettop(L). Для возврата значений в Lua, C функция просто ложит их на стек в прямом порядке (первый результат ложится первым) и возвращает число результатов. Любое другое значение в стеке ниже результатов будет сброшено Lua. Как и Lua функция, C функция, вызванная Lua, может возвращать несколько результатов.

Например, следующая функция получает переменное количество числовых аргументов и возвращает их среднее и их сумму:

     static int foo (lua_State *L) {
       int n = lua_gettop(L);          /* количество аргументов */
       lua_Number sum = 0.0;
       int i;
       for (i = 1; i <= n; i++) {
         if (!lua_isnumber(L, i)) {
           lua_pushliteral(L, "incorrect argument");
           lua_error(L);
         }
         sum += lua_tonumber(L, i);
       }
       lua_pushnumber(L, sum/n);       /* 1-й результат */
       lua_pushnumber(L, sum);         /* 2-й результат */
       return 2;                       /* количество результатов */
     }

lua_checkstack

[-0, +0, –]

int lua_checkstack (lua_State *L, int n);

Проверяет, что стек имеет место для как минимум n дополнительных слотов. Функция возвращает false, если не может выполнить запрос, потому что размер стека больше фиксированного максимума (обычно несколько тысяч элементов) или поскольку не может выделить память для дополнительных слотов. Эта функция никогда не уменьшает стек; если стек уже больше чем новый размер, он остаётся без изменений.

lua_close

[-0, +0, –]

void lua_close (lua_State *L);

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

lua_compare

[-0, +0, e]

int lua_compare (lua_State *L, int index1, int index2, int op);

Сравнивает два Lua значения. Возвращает 1, если значение по индексу index1 удовлетворяет op, когда сравнивается со значением по индексуindex2, следуя семантике соответствующего оператора Lua (т.е., могут вызываться метаметоды). Иначе возвращает 0. Также, возвращает 0, если любой из индексов не правильный.

Значение op должно равняться одной из констант:

  • LUA_OPEQ: равенство (==)
  • LUA_OPLT: меньше (<)
  • LUA_OPLE: меньше или равно (<=)

lua_concat

[-n, +1, e]

void lua_concat (lua_State *L, int n);

Производит конкатенацию n значений на вершине стека, снимает их со стека и оставляет результат на вершине стека. Если n = 1, результат это одно значение на стеке (т.е., функция ничего не делает); если n = 0, результат пустая строка. Конкатенация выполняется следуя обычной семантике Lua (см. §3.4.6).

lua_copy

[-0, +0, –]

void lua_copy (lua_State *L, int fromidx, int toidx);

Копирует элемент по индексу fromidx в правильный индекс toidx, заменяя значение на этой позиции. Значения в других позициях не изменяются.

lua_createtable

[-0, +1, e]

void lua_createtable (lua_State *L, int narr, int nrec);

Создает новую пустую таблицу и ложит её на стек. Параметр narr — подсказка, сколько элементов в таблице будет как последовательность; параметр nrec — подсказка, сколько других элементов будет в таблице. Lua может использовать эти подсказки для предварительного выделения памяти для таблицы. Это предварительное выделение памяти полезно для производительности, когда вы заранее знаете сколько элементов будет в таблице. Иначе вы можете использовать функцию lua_newtable.

lua_dump

[-0, +0, e]

int lua_dump (lua_State *L,
                        lua_Writer writer,
                        void *data,
                        int strip);

Сохраняет функцию как бинарный кусок. Получает Lua функцию на вершине стека и выдает её скомпилированной, при повторной загрузке куска, результаты эквивалентны результатам компилируемой функции. По мере выдачи частей куска, для его записи, lua_dump вызывает функцию writer(см. lua_Writer) с полученной переменной data.

Если strip = true, бинарное представление может не включать всю отладочную информацию о функции, для уменьшения размера.

Возвращаемое значение: код ошибки, возвращенный при последнем вызове функции writer; 0 означает нет ошибок.

Эта функция не убирает Lua функцию со стека.

lua_error

[-1, +0, v]

int lua_error (lua_State *L);

Генерирует ошибку Lua, используя значение на вершине стека, как объект ошибки. Эта функция производит длинный переход (long jump) и никогда не возвращается (см. luaL_error).

lua_gc

[-0, +0, e]

int lua_gc (lua_State *L, int what, int data);

Управляет сборщиком мусора.

Эта функция производит различные действия, в зависимости от параметра what:

  • LUA_GCSTOP: останавливает сборщик мусора.
  • LUA_GCRESTART: перезапускает сборщик мусора.
  • LUA_GCCOLLECT: производит полный цикл сборки мусора.
  • LUA_GCCOUNT: возвращает текущий объем памяти (в килобайтах), используемый Lua.
  • LUA_GCCOUNTB: возвращает остаток от деления текущего объема памяти, используемой Lua, в байтах на 1024.
  • LUA_GCSTEP: производит шаг очистки мусора.
  • LUA_GCSETPAUSE: устанавливает data, как новое значение для паузы сборщика (см. §2.5), и возвращает предыдущее значение паузы.
  • LUA_GCSETSTEPMUL: устанавливает data, как новое значение для множителя шагов сборщика (см. §2.5), и возвращает предыдущее значение множителя шагов.
  • LUA_GCISRUNNING: возвращает логическое значение, которое говорит, что сборщик запущен (т.е., не остановлен).

Для более подробного описания опций, см. collectgarbage.

lua_getallocf

[-0, +0, –]

lua_Alloc lua_getallocf (lua_State *L, void **ud);

Возвращает функцию выделения памяти для данного Lua состояния. Если ud не NULL, Lua записывает в *ud непрозрачный указатель, полученный когда устанавливалась функция выделения памяти.

lua_getfield

[-0, +1, e]

int lua_getfield (lua_State *L, int index, const char *k);

Ложит в стек значение t[k], где t — значение по индексу index. Как и в Lua, эта функция может запускать метаметод для события «index» (см. §2.4).

Возвращает тип положенного на стек значения.

lua_getextraspace

[-0, +0, –]

void *lua_getextraspace (lua_State *L);

Возвращает указатель на область «сырой» (raw) памяти, ассоциированную с данным Lua состоянием. Приложение может использовать эту область для любых целей; Lua не использует эту область.

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

По умолчанию, эта область имеет размер пустого указателя [ sizeof(void*) ], но вы можете перекомпилировать Lua с другим размером для этой области (см. LUA_EXTRASPACE в luaconf.h).

lua_getglobal

[-0, +1, e]

int lua_getglobal (lua_State *L, const char *name);

Ложит в стек значение глобальной переменной name. Возвращает тип этого значения.

lua_geti

[-0, +1, e]

int lua_geti (lua_State *L, int index, lua_Integer i);

Ложит в стек значение t[i], где t — значение по индексу index. Как и в Lua, эта функция может запускать метаметод для события «index» (см. §2.4).

Возвращает тип положенного на стек значения.

lua_getmetatable

[-0, +(0|1), –]

int lua_getmetatable (lua_State *L, int index);

Если значение по индексу index имеет метатаблицу, функция ложит эту метатаблицу на стек и возвращает 1. Иначе, функция возвращает 0 и ничего не ложит на стек.

lua_gettable

[-1, +1, e]

int lua_gettable (lua_State *L, int index);

Ложит на стек значение t[k], где t — значение по индексу index и k — значение на вершине стека.

Эта функция снимает ключ со стека и ложит результирующее значение на его место. Как и в Lua, эта функция может запускать метаметод для события «index» (см. §2.4).

Возвращает тип положенного на стек значения.

lua_gettop

[-0, +0, –]

int lua_gettop (lua_State *L);

Возвращает индекс элемента на вершине стека. Т.к. индексы начинаются с 1, результат равен количеству элементов в стеке; в частности, 0 означает, что стек пуст.

lua_getuservalue

[-0, +1, –]

int lua_getuservalue (lua_State *L, int index);

Ложит на стек Lua значение ассоциированное с пользовательскими данными (userdata), находящимися по индексу index.

Возвращает тип положенного на стек значения.

lua_insert

[-1, +1, –]

void lua_insert (lua_State *L, int index);

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

lua_Integer

typedef ... lua_Integer;

Тип целых в Lua.

По умолчанию, это тип long long, (обычно 64-битное целое), но это может быть изменено в long или int (обычно 32-битное целое). (см.LUA_INT_TYPE в luaconf.h.)

Lua также определяет константы LUA_MININTEGER и LUA_MAXINTEGER, с минимальным и максимальным значениями для этого типа.

lua_isboolean

[-0, +0, –]

int lua_isboolean (lua_State *L, int index);

Возвращает 1, если значение по индексу index имеет тип boolean, иначе возвращает 0.

lua_iscfunction

[-0, +0, –]

int lua_iscfunction (lua_State *L, int index);

Возвращает 1, если значение по индексу index это C функция, иначе возвращает 0.

lua_isfunction

[-0, +0, –]

int lua_isfunction (lua_State *L, int index);

Возвращает 1, если значение по индексу index это функция (любая C или Lua), иначе возвращает 0.

lua_isinteger

[-0, +0, –]

int lua_isinteger (lua_State *L, int index);

Возвращает 1, если значение по индексу index это целое (т.е., это число и оно представлено как целое [integer]), иначе возвращает 0.

lua_islightuserdata

[-0, +0, –]

int lua_islightuserdata (lua_State *L, int index);

Возвращает 1, если значение по индексу index это легкие пользовательские данные (light userdata), иначе возвращает 0.

lua_isnil

[-0, +0, –]

int lua_isnil (lua_State *L, int index);

Возвращает 1, если значение по индексу index это nil, иначе возвращает 0.

lua_isnone

[-0, +0, –]

int lua_isnone (lua_State *L, int index);

Возвращает 1, если полученный индекс не правильный, иначе возвращает 0.

lua_isnoneornil

[-0, +0, –]

int lua_isnoneornil (lua_State *L, int index);

Возвращает 1, если полученный индекс не правильный или значение по индексу это nil, иначе возвращает 0.

lua_isnumber

[-0, +0, –]

int lua_isnumber (lua_State *L, int index);

Возвращает 1, если значение по индексу index это число или строка конвертируемая в число, иначе возвращает 0.

lua_isstring

[-0, +0, –]

int lua_isstring (lua_State *L, int index);

Возвращает 1, если значение по индексу index это строка или число (которое всегда можно преобразовать в строку), иначе возвращает 0.

lua_istable

[-0, +0, –]

int lua_istable (lua_State *L, int index);

Возвращает 1, если значение по индексу index это таблица, иначе возвращает 0.

lua_isthread

[-0, +0, –]

int lua_isthread (lua_State *L, int index);

Возвращает 1, если значение по индексу index это поток (thread), иначе возвращает 0.

lua_isuserdata

[-0, +0, –]

int lua_isuserdata (lua_State *L, int index);

Возвращает 1, если значение по индексу index это пользовательские данные (любые полные или легкие), иначе возвращает 0.

lua_isyieldable

[-0, +0, –]

int lua_isyieldable (lua_State *L);

Возвращает 1, если данная сопрограмма может уступить (yield), иначе возвращает 0.

lua_KContext

typedef ... lua_KContext;

Тип для контекста функции продолжения. Он должен быть числовым типом. Этот тип определен как intptr_t, когда intptr_t доступен, так что может содержать и указатели. Иначе, тип определен как ptrdiff_t.

lua_KFunction

typedef int (*lua_KFunction) (lua_State *L, int status, lua_KContext ctx);

Тип для функций продолжения (см. §4.7).

lua_len

[-0, +1, e]

void lua_len (lua_State *L, int index);

Возвращает длину значения по индексу index. Это эквивалент Lua оператору ‘#‘ (см. §3.4.7) и может вызывать метаметод для события «length» (см.§2.4). Результат ложится на стек.

lua_load

[-0, +1, –]

int lua_load (lua_State *L,
              lua_Reader reader,
              void *data,
              const char *chunkname,
              const char *mode);

Загружает Lua кусок без запуска его на исполнение. Если ошибок нет, lua_load ложит на стек скомпилированный кусок, как Lua функцию. Иначе, ложит на стек сообщение об ошибке.

Возвращаемые значения lua_load:

  • LUA_OK: нет ошибок;
  • LUA_ERRSYNTAX: синтаксическая ошибка при компиляции;
  • LUA_ERRMEM: ошибка выделения памяти;
  • LUA_ERRGCMM: ошибка при выполнении метаметода __gc. (Эта ошибка не имеет отношения к загружаемому куску. Она генерируется сборщиком мусора.)

Функция lua_load использует пользовательскую функцию reader для чтения куска (см. lua_Reader). Аргумент data — это непрозрачный указатель, передаваемый функции reader.

Аргумент chunkname дает куску имя, которое используется для сообщений об ошибках и в отладочной информации (см. §4.9).

lua_load автоматически определяет, когда кусок текст или бинарные данные, и соответственно загружает его (см. программу luac). Строка modeработает как и в функции load, с добавлением того, что значение NULL эквивалентно строке «bt«.

lua_load использует стек непосредственно, поэтому функция reader всегда должна оставлять его неизменным после возвращения.

Если результирующая функция имеет внешние локальные переменные (upvalue), её первое upvalue устанавливается в значение глобального окружения, записанное в реестре по индексу LUA_RIDX_GLOBALS (см. §4.5). При загрузке главных кусков, это upvalue будет переменной _ENV (см.§2.2). Остальные upvalue инициализируются значением nil.

lua_newstate

[-0, +0, –]

lua_State *lua_newstate (lua_Alloc f, void *ud);

Создает новый поток, выполняющийся в новом независимом состоянии. Возвращает NULL, если не может создать поток или состояние (из-за нехватки памяти). Аргумент f — функция выделения памяти; Lua выполняет всё выделение памяти для данного состояния через эту функцию. Второй аргумент, ud — это непрозрачный указатель, который Lua передает в функцию выделения памяти при каждом вызове.

lua_newtable

[-0, +1, e]

void lua_newtable (lua_State *L);

Создает новую пустую таблицу и ложит её на стек. Эквивалентно вызову lua_createtable(L, 0, 0).

lua_newthread

[-0, +1, e]

lua_State *lua_newthread (lua_State *L);

Создает новый поток, ложит его на стек и возвращает указатель на lua_State, который представляет этот новый поток. Новый поток использует одно глобальное окружение с оригинальным потоком, но имеет независимый стек исполнения.

Не существует явной функции для закрытия или уничтожения потока. Потоки это субъект для сборки мусора, как и любой Lua объект.

lua_newuserdata

[-0, +1, e]

void *lua_newuserdata (lua_State *L, size_t size);

Функция выделяет новый блок памяти размером size, ложит на стек новый объект full userdata (полные пользовательские данные) с адресом этого блока, и возвращает этот адрес. Хостовая программа может свободно использовать эту память.

lua_next

[-1, +(2|0), e]

int lua_next (lua_State *L, int index);

Снимает ключ со стека, ложит пару ключ-значение из таблицы, находящейся по индексу index («следующая» пара после данного ключа). Если в таблице больше нет элементов, lua_next возвращает 0 (и ничего не ложит на стек).

Типичный перебор элементов таблицы выглядит так:

     /* таблица находится в стеке по индексу 't' */
     lua_pushnil(L);  /* первый ключ */
     while (lua_next(L, t) != 0) {
       /* используем 'ключ' (по индексу -2) и 'значение' (по индексу -1) */
       printf("%s - %sn",
              lua_typename(L, lua_type(L, -2)),
              lua_typename(L, lua_type(L, -1)));
       /* удалаяем 'значение', сохраняя 'ключ' для следующей итерации */
       lua_pop(L, 1);
     }

Когда производится перебор таблицы, не вызывайте lua_tolstring прямо на ключе, пока не убедитесь, что ключ действительно строка. Помните, что lua_tolstring может изменить значение на полученном индексе; это собьет следующий вызов lua_next.

Смотри функцию next для предостережений о модификации таблицы во время её перебора.

lua_Number

typedef ... lua_Number;

Тип вещественных чисел в Lua.

По умолчанию, это тип double, но он может быть изменен в single float или long double (см. LUA_FLOAT_TYPE в luaconf.h).

lua_numbertointeger

int lua_numbertointeger (lua_Number n, lua_Integer *p);

Преобразует вещественное Lua в целое Lua. Этот макрос предполагает, что n имеет целое значение. Если это значение входит в диапазон целых Lua, оно конвертируется в целое и назначается в *p. Макрос возвращает логическое значение, указывающее, что преобразование успешно. (Учтите, что из-за округлений эта проверка диапазона может быть мудрёной, чтобы сделать её корректно без этого макроса.)

Этот макрос может вычислять свои аргументы несколько раз.

lua_pcall

[-(nargs + 1), +(nresults|1), –]

int lua_pcall (lua_State *L, int nargs, int nresults, int msgh);

Вызывает функцию в защищенном режиме.

Оба nargs и nresults имеют тоже значение, что и в lua_call. Если в течение вызова нет ошибок, lua_pcall действует точно как lua_call. Тем не менее, в случае любых ошибок, lua_pcall перехватывает их, ложит одно значение на стек (собщение об ошибке) и возвращает код ошибки. Как иlua_call, lua_pcall всегда удаляет функцию и её аргументы со стека.

Если msgh = 0, сообщение об ошибке, возвращенное на стек, это оригинальное сообщение об ошибке. Иначе, msgh — это стековый индексобработчика ошибок. (Этот индекс не может быть псевдоиндексом.) В случае ошибок выполнения, эта функция будет вызвана с сообщением об ошибке и значение, которое она вернет, будет возвращено на стеке функцией lua_pcall.

Обычно обработчик ошибок используется чтобы добавить больше отладочной информации в сообщение об ошибке, такой как трассировка стека. Эта информация не может быть получена после возврата из lua_pcall, поскольку стек будет ракручен.

Функция lua_pcall возвращает одну из следующих констант (определенны в lua.h):

  • LUA_OK (0): успех.
  • LUA_ERRRUN: ошибка выполнения.
  • LUA_ERRMEM: ошибка выделения памяти. Для таких ошибок Lua не вызывает обработчик ошибок.
  • LUA_ERRERR: ошибка при выполнении обработчика ошибок.
  • LUA_ERRGCMM: ошибка при выполнении метаметода __gc. (Эта ошибка обычно не имеет отношения к вызываемой функции.)

lua_pcallk

[-(nargs + 1), +(nresults|1), –]

int lua_pcallk (lua_State *L,
                int nargs,
                int nresults,
                int msgh,
                lua_KContext ctx,
                lua_KFunction k);

Функция аналогична lua_pcall, но позволяет вызванной функции уступать (см. §4.7).

lua_pop

[-n, +0, –]

void lua_pop (lua_State *L, int n);

Снимает n элементов со стека.

lua_pushboolean

[-0, +1, –]

void lua_pushboolean (lua_State *L, int b);

Ложит на стек логическое значение (boolean) равное b.

lua_pushcclosure

[-n, +1, e]

void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n);

Ложит на стек новое C замыкание.

Когда C функция создана, можно ассоциировать с ней несколько значений, таким образом создав C замыкание (closure) (см. §4.4); эти значения доступны функции во время вызова. Чтобы ассоциировать эти значениея с C функцией, сначала эти значения нужно положить на стек (первое значение ложится первым). Затем вызвать lua_pushcclosure для создания C функции на стеке, с аргументом n, сообщающим сколько значений будет ассоциировано с функцией. lua_pushcclosure снимает эти значения со стека.

Максимальное значение для n это 255.

Когда n = 0, эта функция создает лёгкую C функцию, которая является лишь указателем на C функцию. В этом случае, она никогда не вызывает ошибку памяти.

lua_pushcfunction

[-0, +1, –]

void lua_pushcfunction (lua_State *L, lua_CFunction f);

Ложит C функцию на стек. Эта функция принимает указатель на C функцию и ложит в стек Lua значение типа function, которое при вызове запускает соответствующую C функцию.

Любая функция, чтобы быть работоспособной в Lua, должна следовать корректному протоколу приема параметров и возврата результатов (см.lua_CFunction).

lua_pushfstring

[-0, +1, e]

const char *lua_pushfstring (lua_State *L, const char *fmt, ...);

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

  • Вы не выделяете место для результата: результат Lua строка и Lua заботится о выделении памяти (и её освобождении, через сборку мусора).
  • Спецификаторы преобразований ограничены. Здесь нет флагов, ширины или точности. Спецификаторы могут быть только следующими: ‘%%‘ (вставляет символ ‘%‘), ‘%s‘ (вставляет строку завершаемую нулем, без ограничений по размеру), ‘%f‘ (вставляет lua_Number), ‘%I‘ (вставляетlua_Integer), ‘%p‘ (вставляет указатель как шестнадцатиричное число), ‘%d‘ (вставляет int), ‘%c‘ (вставляет int как однобайтовый символ), ‘%U‘ (вставляет long int как байтовую последовательность UTF-8).

lua_pushglobaltable

[-0, +1, –]

void lua_pushglobaltable (lua_State *L);

Ложит глобальное окружение в стек.

lua_pushinteger

[-0, +1, –]

void lua_pushinteger (lua_State *L, lua_Integer n);

Ложит на стек целое равное n.

lua_pushlightuserdata

[-0, +1, –]

void lua_pushlightuserdata (lua_State *L, void *p);

Ложит на стек легкие пользовательские данные (light userdata).

Пользовательские данные представляют C значения в Lua. Легкие пользовательские данные предсталяют указатель, void*. Это значение (как число): вы не создаете его, оно не имеет индивидуальной метатаблицы, и не уничтожается сборщиком (т.к. никогда не создаётся). Легкие пользовательские данные равны «любым» легким пользовательским данным с тем же C адресом.

lua_pushliteral

[-0, +1, e]

const char *lua_pushliteral (lua_State *L, const char *s);

Этот макрос аналогичен lua_pushstring, но должен использоваться только, когда s это литеральная строка.

lua_pushlstring

[-0, +1, e]

const char *lua_pushlstring (lua_State *L, const char *s, size_t len);

Ложит на стек строку, указанную s, размером len. Lua создает (или использует снова) внутреннюю копию данной строки, так что после завершения функции память по адресу s может быть освобождена или использована снова. Строка может содержать любые бинарные данные, в том числе встроенные нули.

Возвращает указатель на внутреннюю копию строки.

lua_pushnil

[-0, +1, –]

void lua_pushnil (lua_State *L);

Ложит на стек значение nil.

lua_pushnumber

[-0, +1, –]

void lua_pushnumber (lua_State *L, lua_Number n);

Ложит на стек вещественное число равное n.

lua_pushstring

[-0, +1, e]

const char *lua_pushstring (lua_State *L, const char *s);

Ложит на стек завершаемую нулем строку, указанную s. Lua создает (или использует снова) внутреннюю копию данной строки, так что после завершения функции память по адресу s может быть освобождена или использована снова.

Возвращает указатель на внутреннюю копию строки.

Если s = NULL, ложит nil и возвращает NULL.

lua_pushthread

[-0, +1, –]

int lua_pushthread (lua_State *L);

Ложит на стек поток, представленный Lua состоянием L. Возвращает 1, если поток является главным потоком состояния.

lua_pushvalue

[-0, +1, –]

void lua_pushvalue (lua_State *L, int index);

Ложит на стек копию элемента по индексу index.

lua_pushvfstring

[-0, +1, e]

const char *lua_pushvfstring (lua_State *L,
                              const char *fmt,
                              va_list argp);

Аналогично lua_pushfstring, за исключением того, что фунцкция получает va_list вместо переменного числа аргументов.

lua_rawequal

[-0, +0, –]

int lua_rawequal (lua_State *L, int index1, int index2);

Возвращает 1, если два значения по индексам index1 и index2 примитивно равны (т.е. без вызова метаметодов). Иначе возвращает 0. Также возвращает 0, если любой из индексов не правильный.

lua_rawget

[-1, +1, –]

int lua_rawget (lua_State *L, int index);

Аналогично lua_gettable, но производит «сырой» доступ (т.е. без вызова метаметодов).

lua_rawgeti

[-0, +1, –]

int lua_rawgeti (lua_State *L, int index, lua_Integer n);

Ложит на стек значение t[n], где t — таблица по индексу index. Доступ «сырой», т.е. без вызова метаметодов.

Возвращает тип положенного на стек значения.

lua_rawgetp

[-0, +1, –]

int lua_rawgetp (lua_State *L, int index, const void *p);

Ложит на стек значение t[k], где t — таблица по индексу index, k — указатель p, представленный как лёгкие пользовательские данные. Доступ «сырой», т.е. без вызова метаметодов.

Возвращает тип положенного на стек значения.

lua_rawlen

[-0, +0, –]

size_t lua_rawlen (lua_State *L, int index);

Возвращет сырую «длину» значения по индексу index: для строк это длина строки; для таблиц это результат оператора длины (‘#‘) без метаметодов; для пользовательских данных это размер выделенного блока памяти; для остальных значений это  0.

lua_rawset

[-2, +0, e]

void lua_rawset (lua_State *L, int index);

Аналогично lua_settable, но производит «сырое» присваивание (т.е. без вызова метаметодов).

lua_rawseti

[-1, +0, e]

void lua_rawseti (lua_State *L, int index, lua_Integer i);

Действие аналогично t[i] = v, где t — таблица по индексу index, v — значение на вершине стека.

Эта функция снимает значение со стека. Присваивание «сырое», т.е. без вызова метаметодов.

lua_rawsetp

[-1, +0, e]

void lua_rawsetp (lua_State *L, int index, const void *p);

Действие аналогично t[p] = v, где t — таблица по индексу index, p — кодируется как легкие пользовательские данные, v — значение на вершине стека.

Эта функция снимает значение со стека. Присваивание «сырое», т.е. без вызова метаметодов.

lua_Reader

typedef const char * (*lua_Reader) (lua_State *L,
                                    void *data,
                                    size_t *size);

Функция reader использется в lua_load. Каждый раз, когда требуется следующая часть куска, lua_load вызывает функцию reader, передавая ей свой параметр data. Функция reader должна возвращать указатель на блок памяти с новой частью куска и устанавливать size равным размеру блока. Блок должен существовать, пока функция reader не будет вызвана снова. Для сигнала о конце куска, функция должна вернуть NULL или установить size равным 0. Функция reader может возвращать части любого размера больше нуля.

lua_register

[-0, +0, e]

void lua_register (lua_State *L, const char *name, lua_CFunction f);

Устанавливает C функцию f в качестве нового значения глобальной переменной name. Функция определена как макрос:

     #define lua_register(L,n,f) 
            (lua_pushcfunction(L, f), lua_setglobal(L, n))

lua_remove

[-1, +0, –]

void lua_remove (lua_State *L, int index);

Удаляет элемент по данному правильному индексу, сдвигая вниз элементы выше этого индекса, чтобы заполнить промежуток. Эта функция не может быть вызвана с псевдоиндексом, т.к. псевдоиндекс не является действительной позицией в стеке.

lua_replace

[-1, +0, –]

void lua_replace (lua_State *L, int index);

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

lua_resume

[-?, +?, –]

int lua_resume (lua_State *L, lua_State *from, int nargs);

Запускает и продолжает сопрограмму в данном потоке L.

Для запуска подпрограммы, вы ложите в стек потока главную функцию и её аргументы; затем вызываете lua_resume, nargs — количество аргументов. Этот вызов возвращается, когда сопрограмма приостанавливается или завершается. Когда функция возвращается, стек содержит все значения, переданные в lua_yield, или все значения, возвращенные телом функции. lua_resume возвращает LUA_YIELD — если сопрограмма уступила, LUA_OK — если сопрограмма завершила свое исполнение без ошибок, или код ошибки в случае ошибок (см. lua_pcall).

В случае ошибок, стек не раскручивается, так вы можете использовать отладочные API на нём. Сообщение об ошибке находится на вершине стека.

Чтобы продолжить сопрограмму, вы удаляете все результаты из последнего lua_yield, ложите в её стек только значения, передаваемые в качестве результатов из yield, и затем вызываете lua_resume.

Параметр from представляет сопрограмму, которая продолжает L. Если такой сопрограммы нет, этот параметр может быть равен NULL.

lua_rotate

[-0, +0, –]

void lua_rotate (lua_State *L, int idx, int n);

Вращает элементы стека между правильным индексом idx и вершиной стека. Элементы вращаются на n позиций по направлению к вершине стека, для позитивного n; или -n позиций в направлении дна стека, для отрицательного n. Абсолютное значение n должно быть не больше чем размер вырезки для вращения. Эта функция не может быть вызвана с псевдоиндексом, т.к. псевдоиндекс не является действительной позицией в стеке.

lua_setallocf

[-0, +0, –]

void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);

Заменяет функцию выделения памяти данного состояния на функцию f с пользовательскими данными ud.

lua_setfield

[-1, +0, e]

void lua_setfield (lua_State *L, int index, const char *k);

Действие аналогично t[k] = v, где t — таблица по индексу index, v — значение на вершине стека.

Эта функция снимает значение со стека. Как и в Lua, эта функция может запускать метаметод для события «newindex» (см. §2.4).

lua_setglobal

[-1, +0, e]

void lua_setglobal (lua_State *L, const char *name);

Снимает значение со стека и устанавливает его в качестве нового значения глобальной переменной name.

lua_seti

[-1, +0, e]

void lua_seti (lua_State *L, int index, lua_Integer n);

Действие аналогично t[n] = v, где t — значение по индексу index, v — значение на вершине стека.

Эта функция снимает значение со стека. Как и в Lua, эта функция может запускать метаметод для события «newindex» (см. §2.4).

lua_setmetatable

[-1, +0, –]

void lua_setmetatable (lua_State *L, int index);

Снимает таблицу со стека и устанавливает её в качестве новой метатаблицы для значения по индексу index.

lua_settable

[-2, +0, e]

void lua_settable (lua_State *L, int index);

Действие аналогично t[k] = v, где t — значение по индексу index, v — значение на вершине стека, k — значение следующее за верхним.

Эта функция снимает со стека ключ и значение. Как и в Lua, эта функция может запускать метаметод для события «newindex» (см. §2.4).

lua_settop

[-?, +?, –]

void lua_settop (lua_State *L, int index);

Принимает любой индекс или 0, и устанавливает вершину стека равной этому индексу. Если новая вершина больше предыдущей, новые элементы заполняются значением nil. Если index = 0, то все элементы стека удаляются.

lua_setuservalue

[-1, +0, –]

void lua_setuservalue (lua_State *L, int index);

Снимает значение со стека и устанавливает его в качестве нового значения, ассоциированного с пользовальскими данными (userdata) по индексу index.

lua_State

typedef struct lua_State lua_State;

Непрозрачная структура, которая указывает на поток и косвенно (через поток) на целое состояние интерпретатора Lua. Библиотека Lua полностью повторно входимая: она не имеет глобальных переменных. Вся информация о состоянии доступна через эту структуру.

Указатель на эту структуру должен передаваться, как первый аргумент, в каждую функцию в библиотеке, за исключением lua_newstate, которая создает Lua состояние.

lua_status

[-0, +0, –]

int lua_status (lua_State *L);

Возвращает состояние потока L.

Статус может быть 0 (LUA_OK) — для нормального потока, код ошибки — если поток завершил выполнение lua_resume с ошибкой, или LUA_YIELD — если поток приостановлен.

Вы можете вызывать функции только в потоках со статусом LUA_OK. Вы можете продолжать потоки со статусом LUA_OK (для запуска новой сопрограммы) или LUA_YIELD (для продолжения сопрограммы).

lua_stringtonumber

[-0, +1, –]

size_t lua_stringtonumber (lua_State *L, const char *s);

Преобразует завершаемую нулем строку s в число, ложит это число на стек и возвращает общий размер строки, т.е. её длину + 1. Результатом преобразования может быть целое или вещественное число, в соответствии с лексическими соглашениями Lua (см. §3.1). Строка может иметь начальные и конечные пробелы и знак. Если строка не правильное число, функция возвращает 0 и ничего не ложит на стек. (Имейте ввиду, что результат может быть использован как логическое значение, если преобразование успешно, то результат true.)

lua_toboolean

[-0, +0, –]

int lua_toboolean (lua_State *L, int index);

Преобразует Lua значение по индексу index в C boolean (0 или 1). Как и все проверки в Lua, lua_toboolean возвращает true для любого Lua значения отличного от false и nil; иначе, возвращает false. (Если вы хотите принимать только значения типа boolean, используйте lua_isbooleanдля проверки.)

lua_tocfunction

[-0, +0, –]

lua_CFunction lua_tocfunction (lua_State *L, int index);

Преобразует Lua значение по индексу index в C функцию. Это значение должно быть C функцией; иначе, возвращает NULL.

lua_tointeger

[-0, +0, –]

lua_Integer lua_tointeger (lua_State *L, int index);

Эквивалент lua_tointegerx с isnum = NULL.

lua_tointegerx

[-0, +0, –]

lua_Integer lua_tointegerx (lua_State *L, int index, int *isnum);

Преобразует Lua значение по индексу index в целое со знаком типа lua_Integer. Lua значение должно быть целым, или числом или строкой, преобразуемой в целое (см. §3.4.3); иначе, lua_tointegerx возвращает 0.

Если isnum != NULL, он указывает на логическое значение, которое показывает успешность операции.

lua_tolstring

[-0, +0, e]

const char *lua_tolstring (lua_State *L, int index, size_t *len);

Преобразует Lua значение по индексу index в C строку. Если len != NULL, она также устанавливает *len равным длине строки. Lua значение должно быть строкой или числом; иначе, функция возвращает NULL. Если значение число, то lua_tolstring также изменяет действительное значение в стеке в строку. (Это изменение сбивает lua_next, когда lua_tolstring применяется к ключам при переборе таблицы.)

lua_tolstring возвращает полностью выровненный указатель на строку внутри Lua состояния. Эта строка всегда имеет завершающий ноль (‘‘) после последнего символа (как в C), но может содержать другие нули в своем теле.

Т.к. в Lua есть сборка мусора, нет гарантии, что указатель, возвращенный lua_tolstring, будет действителен после удаления соответствующего Lua значения из стека.

lua_tonumber

[-0, +0, –]

lua_Number lua_tonumber (lua_State *L, int index);

Эквивалент lua_tonumberx с isnum = NULL.

lua_tonumberx

[-0, +0, –]

lua_Number lua_tonumberx (lua_State *L, int index, int *isnum);

Преобразует Lua значение по индексу index в C тип lua_Number (см. lua_Number). Lua значение должно быть числом или строкой, преобразуемой в число (см. §3.4.3); иначе, lua_tonumberx возвращает 0.

Если isnum != NULL, он указывает на логическое значение, которое показывает успешность операции.

lua_topointer

[-0, +0, –]

const void *lua_topointer (lua_State *L, int index);

Преобразует Lua значение по индексу index в пустой C указатель (void*). Значение может быть пользовательскими данными, таблицей, потоком или функцией; иначе, lua_topointer возвращает NULL. Разные объекты дадут разные указатели. Не существует способа сконвертировать указатель обратно в оригинальное значение.

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

lua_tostring

[-0, +0, e]

const char *lua_tostring (lua_State *L, int index);

Эквивалент lua_tolstring с len = NULL.

lua_tothread

[-0, +0, –]

lua_State *lua_tothread (lua_State *L, int index);

Преобразует Lua значение по индексу index в Lua поток (представленный как lua_State*). Это значение должно быть потоком; иначе, функция возвращает NULL.

lua_touserdata

[-0, +0, –]

void *lua_touserdata (lua_State *L, int index);

Если значение по индексу index это полные пользовательские данные, возвращает адрес их блока. Если значение это легкие пользовательские данные, возвращает их указатель. Иначе, возвращает NULL.

lua_type

[-0, +0, –]

int lua_type (lua_State *L, int index);

Возвращает тип значения по правильному индексу index, или LUA_TNONE для не правильного (но допустимого) индекса. Типы, возвращаемыеlua_type, кодируются следующими константами (определены в lua.h): LUA_TNIL (0), LUA_TNUMBER, LUA_TBOOLEAN, LUA_TSTRING, LUA_TTABLE,LUA_TFUNCTION, LUA_TUSERDATA, LUA_TTHREAD и LUA_TLIGHTUSERDATA.

lua_typename

[-0, +0, –]

const char *lua_typename (lua_State *L, int tp);

Возвращает имя типа, кодированного значением tp, которое должно быть одним из возвращаемых lua_type.

lua_Unsigned

typedef ... lua_Unsigned;

Беззнаковая версия lua_Integer.

lua_upvalueindex

[-0, +0, –]

int lua_upvalueindex (int i);

Возвращает псевдоиндекс, который представляет i-е upvalue запущенной функции (см. §4.4).

lua_version

[-0, +0, v]

const lua_Number *lua_version (lua_State *L);

Возвращает адрес номера версии, хранящейся в ядре Lua. Когда вызвана с правильным lua_State, возвращает адрес версии, использованной для создания этого состояния. Когда вызвана с NULL, возвращает адрес версии выполнившей вызов.

lua_Writer

typedef int (*lua_Writer) (lua_State *L,
                           const void* p,
                           size_t sz,
                           void* ud);

Тип функции writer, используемой в lua_dump. Каждый раз, когда производится очередная часть куска, lua_dump вызывает функцию writer, передавая ей буфер для записи (p), его размер (sz) и параметр data, переданный в lua_dump.

Функция writer возвращает код ошибки; 0 означает нет ошибок; любое другое значение означает ошибку и останавливает lua_dump от последующих вызовов writer.

lua_xmove

[-?, +?, –]

void lua_xmove (lua_State *from, lua_State *to, int n);

Обмен значениями между разными потоками одного состояния.

Эта функция снимает со стека from n значений и ложит их в стек to.

lua_yield

[-?, +?, e]

int lua_yield (lua_State *L, int nresults);

Функция аналогична lua_yieldk, но она не имеет продолжения (см. §4.7). Следовательно, когда поток продолжается, он продолжает функцию, которая вызвала lua_yield.

lua_yieldk

[-?, +?, e]

int lua_yieldk (lua_State *L,
                int nresults,
                lua_KContext ctx,
                lua_KFunction k);

Устапает сопрограмму (поток).

Когда C функция вызывает lua_yieldk, вызывающая сопрограмма приостанавливает свое исполнение, и вызов lua_resume, который запустил эту сопрограмму, возвращается. Параметр nresults — это количество значений в стеке, которые будут переданы как результаты в lua_resume.

Когда сопрограмма снова возобновится, Lua вызывает переданную функцию продолжения k, для продолжения выполнения C функции, которая уступила (см. §4.7). Эта функция продолжения получает тот же стек из предыдущей функции, но n результатов будут удалены и заменены аргументами, переданными в lua_resume. Кроме того, функция продолжения получает значение ctx, переданное в lua_yieldk.

Обычно эта функция не возвращается; когда сопрограмма в конечном счете возобновляется, она выполняет фукнцию продолжения. Тем не менее, есть один специальный случай, который случается когда функция вызвана из построчного перехватчика (см. §4.9). В этом случает, lua_yieldkдолжна быть вызвана без продолжения (вероятно в форме lua_yield), и перехватчик должен вернуться непосредственно после вызова. Lua уступит и, когда сопрограмма вновь возобновится, она продолжит нормальное исполнение (Lua) функции, которая инициировала перехват.

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

4.9 – Отладочный интерфейс

Lua не имеет встроенных отладочных средств. Взамен, он предлагает специальный интерфейс функций и перехватчиков (hook). Этот интерфейс позволяет строить различные типы отладчиков, профилировщиков и других инструментов, нуждающихся во «внутренней информации» интерпретатора.

lua_Debug

typedef struct lua_Debug {
  int event;
  const char *name;           /* (n) */
  const char *namewhat;       /* (n) */
  const char *what;           /* (S) */
  const char *source;         /* (S) */
  int currentline;            /* (l) */
  int linedefined;            /* (S) */
  int lastlinedefined;        /* (S) */
  unsigned char nups;         /* (u) количество upvalue */
  unsigned char nparams;      /* (u) количество параметров */
  char isvararg;              /* (u) */
  char istailcall;            /* (t) */
  char short_src[LUA_IDSIZE]; /* (S) */
  /* private part */
  other fields
} lua_Debug;

Структура, используемая для хранения различных частей информации о функции или о записи активации. lua_getstack заполняет только приватную часть этой структуры, для последующего использования. Для заполнения остальных полей lua_Debug полезной информацией, вызовитеlua_getinfo.

Поля lua_Debug имеют следующие значения:

  • source: имя куска, который создал функцию. Если source начинается с ‘@‘, это означает, что функция была определена в файле, где имя файла следует за символом ‘@‘. Если source начинается с ‘=‘, остаток его содержимого описывает источник в определяемой пользователем форме. Иначе, функция была определена в строке, где source — эта строка.
  • short_src: «выводимая» (printable) версия source, для использования в сообщениях об ошибках.
  • linedefined: номер строки, где начинается определение функции.
  • lastlinedefined: номер строки, где заканчивается определение функции.
  • what: строка "Lua" — если функция это Lua функция, "C" — если это C функция, "main" — если это главная часть куска.
  • currentline: текущая строка, где полученная функция исполняется. Когда информация о строках не доступна, currentline устанавливается равным -1.
  • name: разумное имя полученной функции. Т.к. функции в Lua это первоклассные значения, они не имеют фиксированных имен: некоторые функции могут быть значениями множества глобальных переменных, тогда как другие могут храниться только в полях таблицы. Чтобы найти подходящее имя lua_getinfo проверяет как функция была вызвана. Если она не может найти имя, то name устанавливается равным NULL.
  • namewhat: поясняет поле name. Значение namewhat может быть "global", "local", "method", "field", "upvalue" или "" (пустая строка), в соответствии с тем как была вызвана функция. (Lua использует пустую строку, когда не может применить ни какую другую опцию.)
  • istailcall: истина, если этот вызов функции хвостовой (tail call). В этом случае, вызывающий этого уровня не на стеке.
  • nups: количество upvalue у функции.
  • nparams: количество фиксированных параметров у функции (всегда 0 для C функций).
  • isvararg: истина, если функция имеет переменное число аргументов (всегда истина для C функций).

lua_gethook

[-0, +0, –]

lua_Hook lua_gethook (lua_State *L);

Возвращает текущую функцию перехватчик.

lua_gethookcount

[-0, +0, –]

int lua_gethookcount (lua_State *L);

Возвращает количество перехватчиков.

lua_gethookmask

[-0, +0, –]

int lua_gethookmask (lua_State *L);

Возвращает текущую маску перехватов.

lua_getinfo

[-(0|1), +(0|1|2), e]

int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);

Предоставляет информацию о специфической функции или о вызове функции.

Для получения информации о вызове функции, параметр ar должен быть правильной записью активации, которая заполняется вызовомlua_getstack или передается как аргумент в перехватчик (см. lua_Hook).

Для получения информации о функции, нужно положить её в стек и начать строку what символом ‘>‘. (В этом случае, lua_getinfo снимет функцию с вершины стека.) Например, чтобы узнать в которой строке определена функция f, вы можете написать следующий код:

     lua_Debug ar;
     lua_getglobal(L, "f");  /* получить глобальную 'f' */
     lua_getinfo(L, ">S", &ar);
     printf("%dn", ar.linedefined);

Каждый символ в строке what выбирает определенные поля в структуре ar для заполнения или значение, передаваемое через стек:

  • n‘: заполняет поля name и namewhat;
  • S‘: заполняет поля source, short_src, linedefined, lastlinedefined и what;
  • l‘: заполняет поле currentline;
  • t‘: заполняет поле istailcall;
  • u‘: заполняет поля nups, nparams и isvararg;
  • f‘: ложит в стек функцию, которая запущена на данном уровне;
  • L‘: ложит в стек таблицу, индексы которой — это номера значимых строк функции. (Значимая строка — это строка с некоторым кодом, т.е. строка, где можно поставить точку останова [break point]. Не значащие строки — это пустые строки и комментарии.)Если эта опция получена вместе с опцией ‘f‘, таблица ложится в стек после функции.

Эта функция возвращает 0 при ошибке (например, при неправильной опции в строке what).

lua_getlocal

[-0, +(0|1), –]

const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n);

Предоставляет информацию о локальной переменной данной записи активации или функции.

В первом случае, параметр ar должен быть правильной записью активации, которая заполнена предыдущим вызовом lua_getstack или передана как аргумент перехватчику (см. lua_Hook). Индекс n выбирает локальную переменную для проверки; см. debug.getlocal для подробностей о индексах и именах переменных.

lua_getlocal ложит в стек значение переменной и возвращает её имя.

Во втором случае, ar должен быть NULL, и функция для проверки должна находиться на вершине стека. В этом случае, видны только параметры Lua функций (т.к. здесь нет информации о том, какие переменные активны) и значения в стек не ложатся.

Возвращает NULL (и ничего не ложит на стек), когда индекс больше чем количество активных локальных переменных.

lua_getstack

[-0, +0, –]

int lua_getstack (lua_State *L, int level, lua_Debug *ar);

Предоставляет информацию о исполняемом (runtime) стеке интерпретатора.

Эта функция заполняет части структуры lua_Debug с индентификацией записи активации функции, выполняемой на данном уровне (level). Уровень 0 — это текущая выполняющаяся функция, уровень n+1 — это функция которая вызывает уровень n (за исключением хвостовых вызовов, которые не считаются на стеке). Когда ошибок нет, lua_getstack возвращает 1; когда вызвана с уровнем больше чем глубина стека, возвращает 0.

lua_getupvalue

[-0, +(0|1), –]

const char *lua_getupvalue (lua_State *L, int funcindex, int n);

Предоставляет информацию о n-ном upvalue замыкания по индексу funcindex. Функция ложит на стек значение upvalue и возвращает его имя. Возвращает NULL (и ничего не ложит на стек), когда индекс n больше количества upvalue.

Для C функций, эта функция использует пустую строку "" в качестве имени для всех upvalue. (Для Lua функций, upvalue — это внешние локальные переменные, которые использует функция, и которые, следовательно, включены в её замыкание.)

Upvalue не имеют конкретного порядка, как они активны внутри функции. Они нумеруются в произвольном порядке.

lua_Hook

typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);

Тип для отладочных функций перехватчиков.

Всякий раз, когда вызывается перехватчик, его аргумент ar имеет поле event, установленное согласно событию, вызвавшему срабатывание перехватчика. Lua идентифицирует эти события следующими константами: LUA_HOOKCALL, LUA_HOOKRET, LUA_HOOKTAILCALL, LUA_HOOKLINE иLUA_HOOKCOUNT. Более того, для событий строк устанавливается поле currentline. Для получения значений остальных полей в ar, перехватчик должен вызвать lua_getinfo.

Для событий вызова, event может быть LUA_HOOKCALL — нормальное значение, или LUA_HOOKTAILCALL — для хвостового вызова; в этом случае, соответствующего события возврата не будет.

Пока Lua выполняет перехватчик, все остальные перехватчики отключаются. Следовательно, если перехватчик вызывает Lua для выполнения функции или куска, это выполнение произойдет без вызова перехватчиков.

Функции перехватчики не могут иметь продолжений, т.е. они не могут вызывать lua_yieldk, lua_pcallk или lua_callk с не нулевым k.

Функции перехватчики могут уступать при следующих условиях: только счетные и события строк могут уступать; для уступки, функция перехватчик должна завершить свое исполнение, вызвав lua_yield с nresults = 0 (т.е. без значений).

lua_sethook

[-0, +0, –]

void lua_sethook (lua_State *L, lua_Hook f, int mask, int count);

Устанавливает отладочную функцию-перехватчик.

Аргумент f — это функция перехватчик. mask — определяет на каких событиях будет вызван перехватчик: формируется битовым ИЛИ константLUA_MASKCALL, LUA_MASKRET, LUA_MASKLINE и LUA_MASKCOUNT. Аргумент count — имеет значение только, когда маска включает LUA_MASKCOUNT. Перехватчик для каждого события объясняется ниже:

  • Перехватчик вызова (call hook): вызывается, когда интерпретатор вызывает функцию. Перехватчик вызывается сразу после того, как Lua войдет в новую функцию, перед тем как функция получит свои аргументы.
  • Перехватчик возврата (return hook): вызывается, когда интерпретатор возвращается из функции. Перехватчик вызывается перед тем, как Lua покинет функцию. Здесь нет стандартного пути для доступа к возвращаемым функцией значениям.
  • Перехватчик строки (line hook): вызывается, когда интерпретатор начинает выполнение новой строки кода, или когда он переходит назад в код (даже в ту же строку). (Это событие случается только пока Lua выполняет Lua функцию.)
  • Счетный перехватчик (count hook): вызывается после того, как интерпретатор запустит count инструкций. (Это событие случается только пока Lua выполняет Lua функцию.)

Перехват отключается установкой mask = 0.

lua_setlocal

[-(0|1), +0, –]

const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n);

Устанавливает значение локальной переменной в данной записи активации (ar). Устанавливает переменной значение с вершины стека и возвращает её имя, затем удаляет значение из стека.

Возвращает NULL (и ничего не удаляет со стека), когда индекс больше количества активных локальных переменных.

Параметры ar и n такие же, как в функции lua_getlocal.

lua_setupvalue

[-(0|1), +0, –]

const char *lua_setupvalue (lua_State *L, int funcindex, int n);

Устанавливает значение для upvalue замыкания. Устанавливает upvalue равным значению с вершины стека и возвращает её имя, затем удаляет значение из стека

Возвращает NULL (и ничего не удаляет со стека), когда индекс больше количества upvalue.

Параметры funcindex и n такие же, как в функции lua_getupvalue.

lua_upvalueid

[-0, +0, –]

void *lua_upvalueid (lua_State *L, int funcindex, int n);

Возвращает уникальный идентификатор для upvalue под номером n из замыкания по индексу funcindex.

Эти уникальные идентификаторы позволяют программе проверить, когда замыкания совместно используют upvalue. Lua замыкания, которые совместно используют upvalue (т.е., обращаются к одной внешней локальной переменной), вернут одинаковые идентификаторы для индексов своих upvalue.

Параметры funcindex и n такие же, как в функции lua_getupvalue, но n не может быть больше количества upvalue.

lua_upvaluejoin

[-0, +0, –]

void lua_upvaluejoin (lua_State *L, int funcindex1, int n1,
                                    int funcindex2, int n2);

Делает n1-ое upvalue Lua замыкания по индексу funcindex1 ссылкой на n2-ое upvalue Lua замыкания по индексу funcindex2.

5 – Вспомогательная библиотека

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

Все функции и типы вспомогательной библиотеки определены в заголовочном файле lauxlib.h и имеют префикс luaL_.

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

Различные функции вспомогательной библиотеки используют внутри несколько дополнительных слотов. Когда функция вспомогательной библиотеки использует меньше пяти слотов, она не проверяет размер стека; она просто предполагает, что там достаточно слотов.

Различные функции вспомогательной библиотеки используются для проверки аргументов C функций. Так как сообщение об ошибке формируется для аргументов (т.е., «bad argument #1«), вы не должны использовать эти функции для других значений стека.

Функции luaL_check* всегда генерируют ошибку, если проверка не удовлетворена.

5.1 – Функции и типы

Здесь представлен список всех функций и типов вспомогательной библиотеки в алфавитном порядке.

luaL_addchar

[-?, +?, e]

void luaL_addchar (luaL_Buffer *B, char c);

Добавляет байт c в буфер B (см. luaL_Buffer).

luaL_addlstring

[-?, +?, e]

void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l);

Добавляет строку по указателю s длиной l в буфер B (см. luaL_Buffer). Строка может содержать встроенные нули.

luaL_addsize

[-?, +?, e]

void luaL_addsize (luaL_Buffer *B, size_t n);

Добавляет в буфер B (см. luaL_Buffer) строку длиной n, прежде скопированную в область буфера (см. luaL_prepbuffer).

luaL_addstring

[-?, +?, e]

void luaL_addstring (luaL_Buffer *B, const char *s);

Добавляет завершаемую нулем строку по указателю s в буфер B (см. luaL_Buffer).

luaL_addvalue

[-1, +?, e]

void luaL_addvalue (luaL_Buffer *B);

Добавляет значение с вершины стека в буфер B (см. luaL_Buffer). Снимает значение со стека.

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

luaL_argcheck

[-0, +0, v]

void luaL_argcheck (lua_State *L,
                    int cond,
                    int arg,
                    const char *extramsg);

Проверяет когда cond истина. Если это не так, генерирует ошибку со стандартным сообщением (см. luaL_argerror).

luaL_argerror

[-0, +0, v]

int luaL_argerror (lua_State *L, int arg, const char *extramsg);

Генерирует ошибку, сообщающую о проблеме с аргументом arg для C функции, которая вызвала luaL_argerror. Используется стандартное сообщение, включающее extramsg как комментарий:

     bad argument #arg to 'funcname' (extramsg)

Эта функция никогда не возвращается.

luaL_Buffer

typedef struct luaL_Buffer luaL_Buffer;

Тип для строкового буфера.

Строковый буфер позволяет C коду строить Lua строки по частям. Обычно он используется следующим образом:

  • Сначала объявляется переменная b типа luaL_Buffer.
  • Затем она инициализируется вызовом luaL_buffinit(L, &b).
  • Затем части строки добавляются в буфер вызовами функций luaL_add*.
  • Завершается вызовом luaL_pushresult(&b). Этот вызов оставляет финальную строку на вершине стека.

Если вы заранее знаете размер результирующей строки, вы можете использовать буфер так:

  • Сначала объявляется переменная b типа luaL_Buffer.
  • Затем вызовом luaL_buffinitsize(L, &b, sz) она инициализируется, и для неё выделяется память размером sz.
  • Затем в эту область копируется строка.
  • Завершается вызовом luaL_pushresultsize(&b, sz), где sz — размер результирующей строки, скопированной в эту область.

При нормальном управлении, строковый буфер использует переменное число слотов стека. Так, пока используется буфер, вы не можете предполагать, что вы знаете где вершина стека. Вы можете использовать стек между успешными вызовами буферных операций, пока он сбалансирован; т.е., когда вы вызываете буферную операцию, стек должен быть на том же уровне, что и непосредственно после предыдущей буферной операции. (Существует только одно исключение, это luaL_addvalue.) После вызова luaL_pushresult стек возвращается на тот уровень, когда был инициализирован буфер, плюс результирующая строка на вершине.

luaL_buffinit

[-0, +0, –]

void luaL_buffinit (lua_State *L, luaL_Buffer *B);

Инициализирует буфер B. Эта функция не выделяет память; буфер должен быть определен как переменная (см. luaL_Buffer).

luaL_buffinitsize

[-?, +?, e]

char *luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz);

Эквивалентно последовательности luaL_buffinit, luaL_prepbuffsize.

luaL_callmeta

[-0, +(0|1), e]

int luaL_callmeta (lua_State *L, int obj, const char *e);

Вызывает метаметод.

Если объект по индексу obj имеет метатаблицу и его метатаблица имеет поле e, эта функция вызывает это поле, передавая объект в качестве первого аргумента. В этом случае функция возвращает true и ложит в стек значение, возвращенное вызовом метаметода. Если метатаблицы или метаметода не существует, функция возвращает false (и ничего не ложит на стек).

luaL_checkany

[-0, +0, v]

void luaL_checkany (lua_State *L, int arg);

Проверяет, что функция имеет аргумент любого типа (включая nil) по индексу arg.

luaL_checkinteger

[-0, +0, v]

lua_Integer luaL_checkinteger (lua_State *L, int arg);

Проверяет, что аргумент функции arg это целое (или может быть преобразован в целое), и возвращает это целое, как lua_Integer.

luaL_checklstring

[-0, +0, v]

const char *luaL_checklstring (lua_State *L, int arg, size_t *l);

Проверяет, что аргумент функции arg это строка, и возвращает эту строку; если l не NULL, пишет в *l длину строки.

Эта функция использует lua_tolstring для получения результата, так все преобразования и предостережения этой функции относятся и сюда.

luaL_checknumber

[-0, +0, v]

lua_Number luaL_checknumber (lua_State *L, int arg);

Проверяет, что аргумент функции arg это число, и возвращает это число.

luaL_checkoption

[-0, +0, v]

int luaL_checkoption (lua_State *L,
                      int arg,
                      const char *def,
                      const char *const lst[]);

Проверяет, что аргумент функции arg это строка, и ищет эту строку в массиве lst (который должен завершаться NULL-символом). Возвращает индекс в массиве, где найдена строка. Генерирует ошибку, если аргумент не строка или строка не найдена в массиве.

Если def не NULL, функция использует def как значение по умолчанию, когда нет аргумента arg или он равен nil.

Эта функция полезна для отображения строк в C перечисления (enum). (Обычно, для выбора опций в Lua библиотеках принято использовать строки вместо чисел.)

luaL_checkstack

[-0, +0, v]

void luaL_checkstack (lua_State *L, int sz, const char *msg);

Увеличивает размер стека до top + sz элементов, вызывает ошибку, если стек не может быть увеличен до этого размера. msg — это дополнительный текст для сообщения об ошибке (или NULL, если его нет).

luaL_checkstring

[-0, +0, v]

const char *luaL_checkstring (lua_State *L, int arg);

Проверяет, что аргумент функции arg это строка, и возвращает эту строку.

Эта функция использует lua_tolstring для получения результата, так все преобразования и предостережения этой функции относятся и сюда.

luaL_checktype

[-0, +0, v]

void luaL_checktype (lua_State *L, int arg, int t);

Проверяет, что аргумент функции arg имеет тип t. См. lua_type для кодировок типов t.

luaL_checkudata

[-0, +0, v]

void *luaL_checkudata (lua_State *L, int arg, const char *tname);

Проверяет, что аргумент функции arg это пользовательские данные типа tname (см. luaL_newmetatable), и возвращает адрес пользовательских данных (см. lua_touserdata).

luaL_checkversion

[-0, +0, –]

void luaL_checkversion (lua_State *L);

Проверяет, что ядро, выполняющее вызов, ядро, создавшее Lua состояние, и код, производящий вызов, все используют одну версию Lua. Также проверяет, что ядро, выполняющее вызов, и ядро, создавшее Lua состояние, используют одно адресное пространство.

luaL_dofile

[-0, +?, e]

int luaL_dofile (lua_State *L, const char *filename);

Загружает и запускает данный файл. Определена как макрос:

     (luaL_loadfile(L, filename) || lua_pcall(L, 0, LUA_MULTRET, 0))

Возвращает false, если ошибок нет, или true в случае ошибок.

luaL_dostring

[-0, +?, –]

int luaL_dostring (lua_State *L, const char *str);

Загружает и запускает переданную строку. Определена как макрос:

     (luaL_loadstring(L, str) || lua_pcall(L, 0, LUA_MULTRET, 0))

Возвращает false, если ошибок нет, или true в случае ошибок.

luaL_error

[-0, +0, v]

int luaL_error (lua_State *L, const char *fmt, ...);

Генерирует ошибку. Сообщение об ошибке форматируется строкой fmt и дополнительными аргументами, следует тем же правилам, что иlua_pushfstring. Также добавляет в начало сообщения имя файла и номер строки, где произошла ошибка, если эта информация доступна.

Эта функция никогда не возвращается, но её идиома для использования в C функциях: return luaL_error(args).

luaL_execresult

[-0, +3, e]

int luaL_execresult (lua_State *L, int stat);

Эта функция выдает возвращаемые значения для связанных с процессами функций стандартной библиотеки (os.execute и io.close).

luaL_fileresult

[-0, +(1|3), e]

int luaL_fileresult (lua_State *L, int stat, const char *fname);

Эта функция выдает возвращаемые значения для связанных с файлами функций стандартной библиотеки (io.open, os.rename, file:seek и др.).

luaL_getmetafield

[-0, +(0|1), e]

int luaL_getmetafield (lua_State *L, int obj, const char *e);

Ложит на стек поле e из метатаблицы объекта по индексу obj и возвращает тип положенного на стек значения. Если объект не имеет метатаблицы или в метатаблице нет этого поля, ничего не ложит на стек и возвращает LUA_TNIL.

luaL_getmetatable

[-0, +1, –]

int luaL_getmetatable (lua_State *L, const char *tname);

Ложит на стек метатаблицу, ассоциированную с именем tname в реестре (см. luaL_newmetatable) (nil, если метатаблицы с таким именем нет). Возвращает тип положенного на стек значения.

luaL_getsubtable

[-0, +1, e]

int luaL_getsubtable (lua_State *L, int idx, const char *fname);

Гарантирует, что значение t[fname] это таблица, и ложит эту таблицу на стек; t — это значение по индексу idx. Возвращает true, если находит существующую таблицу, и false, если создает новую.

luaL_gsub

[-0, +1, e]

const char *luaL_gsub (lua_State *L,
                       const char *s,
                       const char *p,
                       const char *r);

Создает копию строки s, заменяя все вхождения строки p на строку r. Ложит на стек результирующую строку и возвращает её.

luaL_len

[-0, +0, e]

lua_Integer luaL_len (lua_State *L, int index);

Возвращает «длину» значения по индексу index как число; эквивалентна Lua оператору ‘#‘ (см. §3.4.7). Генерирует ошибку, если результат операции не целое. (Это может случиться только через метаметоды.)

luaL_loadbuffer

[-0, +1, –]

int luaL_loadbuffer (lua_State *L,
                     const char *buff,
                     size_t sz,
                     const char *name);

Эквивалентно luaL_loadbufferx с mode = NULL.

luaL_loadbufferx

[-0, +1, –]

int luaL_loadbufferx (lua_State *L,
                      const char *buff,
                      size_t sz,
                      const char *name,
                      const char *mode);

Загружает буфер как Lua кусок. Эта функция использует lua_load для загрузки куска в буфер buff размером sz.

Функция возвращает те же результаты, что и lua_load.

name — имя куска, используемое для отладочной информации и сообщений об ошибках. Строка mode работает как в функции lua_load.

luaL_loadfile

[-0, +1, e]

int luaL_loadfile (lua_State *L, const char *filename);

Эквивалентно luaL_loadfilex с mode = NULL.

luaL_loadfilex

[-0, +1, e]

int luaL_loadfilex (lua_State *L, const char *filename,
                                            const char *mode);

Загружает файл как Lua кусок. Эта функция использует lua_load для загрузки куска из файла filename. Если filename = NULL, загружает кусок из потока стандартного ввода. Первая линия файла игнорируется, если она начинается с #.

Строка mode работает как в функции lua_load.

Эта функция возвращает те же результаты, что и lua_load, но имеет дополнительный код ошибки LUA_ERRFILE, если не может открыть/прочитать файл или файл имеет неверный режим.

Как и lua_load, эта функция только загружает кусок; но не запускает его.

luaL_loadstring

[-0, +1, –]

int luaL_loadstring (lua_State *L, const char *s);

Загружает строку как Lua кусок. Эта функция использует lua_load для загрузки завершаемой нулем строки s.

Эта функция возвращает те же результаты, что и lua_load.

Как и lua_load, эта функция только загружает кусок; но не запускает его.

luaL_newlib

[-0, +1, e]

void luaL_newlib (lua_State *L, const luaL_Reg l[]);

Создает новую таблицу и регистрирует в ней функции из списка l.

Реализована как макрос:

     (luaL_newlibtable(L,l), luaL_setfuncs(L,l,0))

Массив l должен быть фактическим массивом, не указателем на него.

luaL_newlibtable

[-0, +1, e]

void luaL_newlibtable (lua_State *L, const luaL_Reg l[]);

Создает новую таблицу с размером, оптимизированным для хранения всех записей массива l (но фактически не сохраняет их). Она предполагается для использования в связке с luaL_setfuncs (см. luaL_newlib).

Реализована как макрос. Массив l должен быть фактическим массивом, не указателем на него.

luaL_newmetatable

[-0, +1, e]

int luaL_newmetatable (lua_State *L, const char *tname);

Если реестр уже содержит ключ tname, возвращает 0. Иначе, создает новую таблицу для использования в качестве метатаблицы пользовательских данных, добавляет в эту новую таблицу пару __name = tname, добавляет в реестр пару [tname] = new table, и возвращает 1. (Элемент __nameиспользуется некоторыми функциями, сообщающими об ошибках.)

В обоих случаях ложит на стек финальное значение ассоциированное с tname в реестре.

luaL_newstate

[-0, +0, –]

lua_State *luaL_newstate (void);

Создает новое Lua состояние. Вызывает lua_newstate с функцией выделения памяти, базирующейся на стандартной  C функции realloc, и затем устанавливает функцию паники (см. §4.6), которая в случае фатальных ошибок печатает сообщение об ошибке в стандартный поток вывода.

Возвращает новое состояние, или NULL, если не удалось выделить память.

luaL_openlibs

[-0, +0, e]

void luaL_openlibs (lua_State *L);

Открывает все стандартные библиотеки Lua в данное состояние.

luaL_optinteger

[-0, +0, v]

lua_Integer luaL_optinteger (lua_State *L,
                             int arg,
                             lua_Integer d);

Если аргумент функции arg это целое (или может быть преобразован в целое), возвращает это целое. Если аргумент отсутствует или равен nil, возвращает d. Иначе, генерирует ошибку.

luaL_optlstring

[-0, +0, v]

const char *luaL_optlstring (lua_State *L,
                             int arg,
                             const char *d,
                             size_t *l);

Если аргумент функции arg это строка, возвращает эту строку. Если аргумент отсутствует или равен nil, возвращает d. Иначе, генерирует ошибку.

Если l не NULL, записывает в *l длину результата.

luaL_optnumber

[-0, +0, v]

lua_Number luaL_optnumber (lua_State *L, int arg, lua_Number d);

Если аргумент функции arg это число, возвращает это число. Если аргумент отсутствует или равен nil, возвращает d. Иначе, генерирует ошибку.

luaL_optstring

[-0, +0, v]

const char *luaL_optstring (lua_State *L,
                            int arg,
                            const char *d);

Если аргумент функции arg это строка, возвращает эту строку. Если аргумент отсутствует или равен nil, возвращает d. Иначе, генерирует ошибку.

luaL_prepbuffer

[-?, +?, e]

char *luaL_prepbuffer (luaL_Buffer *B);

Эвивалентно luaL_prepbuffsize с предопределенным размером LUAL_BUFFERSIZE.

luaL_prepbuffsize

[-?, +?, e]

char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz);

Возвращает адрес пространства размером sz, куда вы можете скопировать строку, чтобы добавить в буфер B (см. luaL_Buffer). После копирования строки в это пространство, вы должны вызвать luaL_addsize с размером строки, для фактического добавления её в буфер.

luaL_pushresult

[-?, +1, e]

void luaL_pushresult (luaL_Buffer *B);

Завершает использование буфера B, оставляя финальную строку на вершине стека.

luaL_pushresultsize

[-?, +1, e]

void luaL_pushresultsize (luaL_Buffer *B, size_t sz);

Эквивалентно последовательности luaL_addsize, luaL_pushresult.

luaL_ref

[-1, +0, e]

int luaL_ref (lua_State *L, int t);

Создает и возвращает ссылку (reference) в таблице по индексу t, для объекта на вершине стека (и снимает этот объект со стека).

Ссылка это уникальный целый ключ. Пока вы не добавляете целые ключи в таблицу t, luaL_ref гарантирует уникальность возвращаемых ключей. Вы можете извлечь объект по ссылке r, вызвав lua_rawgeti(L, t, r). Функция luaL_unref освобождает ссылку и ассоциированный с ней объект.

Если объект на вершине стека равен nil, luaL_ref возвращает константу LUA_REFNIL. Константа LUA_NOREF всегда отлична от любой другой ссылки, возвращаемой luaL_ref.

luaL_Reg

typedef struct luaL_Reg {
  const char *name;
  lua_CFunction func;
} luaL_Reg;

Тип для массивов функций для регистрации функцией luaL_setfuncs. name — имя функции, func — указатель на функцию. Любой массив luaL_Regдолжен завершаться ключевым элементом, в котором name и func = NULL.

luaL_requiref

[-0, +1, e]

void luaL_requiref (lua_State *L, const char *modname,
                    lua_CFunction openf, int glb);

Если modname ещё не присутствует в package.loaded, вызывает функцию openf со строкой modname в качестве аргумента и пишет результат вызова в package.loaded[modname], как если бы эта функция была бы вызвана через require.

Если glb = true, также сохраняет модуль в глобальную modname.

Оставляет копию модуля на стеке.

luaL_setfuncs

[-nup, +0, e]

void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup);

Регистрирует все функции в массиве l (см. luaL_Reg) в таблицу на вершине стека (ниже опциональных upvalue, см. далее).

Когда nup != 0, все функции создаются, разделяющими nup upvalue, которые должны быть предварительно положены на стек поверх таблицы библиотеки. После регистрации эти значения снимаются со стека.

luaL_setmetatable

[-0, +0, –]

void luaL_setmetatable (lua_State *L, const char *tname);

Устанавливает метатаблицей объекта на вершине стека метатаблицу, ассоциированную с именем tname в реестре (см. luaL_newmetatable).

luaL_Stream

typedef struct luaL_Stream {
  FILE *f;
  lua_CFunction closef;
} luaL_Stream;

Стандартное представление для описателей файлов (handle), которые используются стандартной библиотекой ввода-вывода.

Описатель файла реализован как полные пользовательские данные, с метатаблицей называемой LUA_FILEHANDLE (где LUA_FILEHANDLE — это макрос с фактическим именем метатаблицы). Метатаблица создается библиотекой ввода-вывода (см. luaL_newmetatable).

Эти пользовательские данные должны начинаться со структуры luaL_Stream; они могут содержать другие данные после этой начальной структуры. Поле f — указывает на соответствующий C поток (ими может быть NULL для индикации не полностью созданного описателя). Поле closef — указывает на Lua функцию, которая будет вызвана для закрытия потока, при закрытии или сборке описателя; эта функция получает описатель файла в качестве единственного аргумента и должна вернуть true (в случае успеха) или nil с сообщением об ошибке (в случае ошибки). Как только Lua вызывает это поле, его значение меняется на NULL для сигнализации, что описатель закрыт.

luaL_testudata

[-0, +0, e]

void *luaL_testudata (lua_State *L, int arg, const char *tname);

Эта функция работает как luaL_checkudata, за исключением того, что когда проверка неудачна, она возвращает NULL, вместо генерирования ошибки.

luaL_tolstring

[-0, +1, e]

const char *luaL_tolstring (lua_State *L, int idx, size_t *len);

Конвертирует любое Lua значение по индексу idx в C строку в разумном формате. Результирующая строка ложится на стек и также возвращается функцией. Если len не NULL, функция пишет в *len длину строки.

Если значение имеет метатаблицу с полем "__tostring", то luaL_tolstring вызывает соответствующий метаметод со значением в качестве аргумента и использует результат вызова, как свой результат.

luaL_traceback

[-0, +1, e]

void luaL_traceback (lua_State *L, lua_State *L1, const char *msg,
                     int level);

Создает и ложит на стек трассировку стека L1. Если msg не NULL, оно добавляется в начало трассировки. Параметр level указывает на каком уровне начинать трассировку.

luaL_typename

[-0, +0, –]

const char *luaL_typename (lua_State *L, int index);

Возвращает имя типа для значения по индексу index.

luaL_unref

[-0, +0, –]

void luaL_unref (lua_State *L, int t, int ref);

Освобождает ссылку ref из таблицы по индексу t (см. luaL_ref). Элемент удаляется из таблицы, так что ассоциированный объект может быть собран сборщиком мусора. Ссылка ref также освобождается для повторного использования.

Если ref = LUA_NOREF или LUA_REFNIL, luaL_unref ничего не делает.

luaL_where

[-0, +1, e]

void luaL_where (lua_State *L, int lvl);

Ложит на стек строку, идентифицирующую текущую позицию на управляющем уровне lvl в стеке вызовов. Обычно эта строка имеет следующий формат:

     chunkname:currentline:

Уровень 0 — это текущая выполняемая функция, уровень 1 — это функция, которая вызвала текущую, и так далее.

Эта функция используется для формирования префикса сообщений об ошибках.

6 – Стандартные библиотеки

Стандартные библиотеки Lua предоставляют полезные функции, реализованные напрямую через C API. Некоторые из этих функций предоставляют существенные службы языка (например, type и getmetatable); другие предоставляют доступ к «внешним» сервисам (например, I/O); и другие могут быть реализованы в Lua самостоятельно, но очень полезны и имеют критические требования к производительности, что заслуживает реализации в C (например, table.sort).

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

  • базовая библиотека (§6.1);
  • библиотека сопрограмм (§6.2);
  • библиотека пакетов (§6.3);
  • манипуляции со строками (§6.4);
  • базовая поддержка UTF-8 (§6.5);
  • манипуляции с таблицами (§6.6);
  • математические функции (§6.7) (sin, log и др.);
  • ввод и вывод (§6.8);
  • средства операционной системы (§6.9);
  • отладочные средства (§6.10).

За исключением базовой и пакетной библиотек, каждая библиотека предоставляет все свои функции, как поля глобальной таблицы или методы её объектов.

Для получения доступа к этим библиотекам хоствая C программа должна вызвать функцию luaL_openlibs, которая открывает все стандартные библиотеки. Либо, хостовая программа может открыть их индивидуально, используя luaL_requiref для вызова luaopen_base (для базовой библиотеки), luaopen_package (для библиотеки пакетов), luaopen_coroutine (для библиотеки сопрограмм), luaopen_string (для строковой библиотеки), luaopen_utf8 (для библиотеки UTF8), luaopen_table (для табличной библиотеки), luaopen_math (для математической библиотеки),luaopen_io (для библиотеки ввода-вывода), luaopen_os (для библиотеки операционной системы) и luaopen_debug (для отладочной библиотеки). Все эти функции определены в lualib.h.

6.1 – Базовые функции

Базовая библиотека предоставляет функции ядра для Lua. Если вы не включите эту библиотеку в ваше приложение, вы должны проявлять осторожность, когда будете нуждаться в предоставлении реализаций для некоторых её возможностей.

assert (v [, message])

Вызывает error, если значение аргумента v = false (т.е., nil или false); иначе, возвращает все свои аргументы. В случае ошибки, message — это объект ошибки; когда он отсутствует, его значение по умолчанию «assertion failed!»

collectgarbage ([opt [, arg]])

Эта функция общий интерфейс к сборщику мусора. Она выполняет различные действия в соответствии с её аргументом opt:

  • «collect«: выполняет полный цикл очистки мусора. Это опция по умолчанию.
  • «stop«: останавливает автоматическое выполнение сборщика мусора. Сборщик будет запущен, только когда явно вызван, до вызова его перезапуска.
  • «restart«: перезапускает автоматическое выполнение сборщика мусора.
  • «count«: возвращает общее количество используемой Lua памяти в килобайтах. Это значение имеет дробную часть, так что его произведение на 1024 дает точное количство байт, используемых Lua (за исключением переполнений).
  • «step«: выполняет шаг сборки мусора. «Размер» шага контролируется аргументом arg. С нулевым значением сборщик выполнит один базовый (неделимый) шаг. Для не нулевых значений, сборщик выполнит, как если это количество памяти (в килобайтах) было выделено Lua. Возвращает true, если шаг завершил цикл сборки.
  • «setpause«: устанавливает arg в качестве нового значения для паузы сборщика (см. §2.5). Возвращает предыдущее значение паузы.
  • «setstepmul«: устанавливает arg в качестве нового значения для множителя шагов сборщика (см. §2.5). Возвращает предыдущее значениешага.
  • «isrunning«: возвращает логическое значение, говорящее запущен ли сборщик (т.е. не остановлен).

dofile ([filename])

Открывает файл и запускает его содержимое, как Lua кусок. Когда вызвана без аргументов, запускает содержимое стандартного ввода (stdin). Возвращает все значения, возвращенные куском. В случае ошибок, dofile распространяет ошибку вызывающему коду (т.е. dofile не запускается в защищенном режиме).

error (message [, level])

Завершает последнюю защищенно вызванную функцию и возвращает message, как объект ошибки. Функция error никогда не возвращается.

Обычно error добавляет информацию о позиции ошибки в начало сообщения, если сообщение (message) это строка. Аргумент level определяет как получить позицию ошибки. Когда level = 1 (по умолчанию) — позиция ошибки там, где вызвана функция error. Level = 2 — указывает ошибку там, где вызвана функция, вызвавшая error; и так далее. Передача level = 0 — позиция ошибки не влючается в сообщение.

_G

Глобальная переменная (не функция), которая хранит глобальное окружение (см. §2.2). Lua сама не использует эту переменную; её изменение не влияет на окружение, ни наоборот.

getmetatable (object)

Если object не имеет метатаблицы, возвращает nil. Иначе, если метатаблица объекта имеет поле "__metatable", возвращает ассоциированное с этим полем значение. Иначе, возвращает метатаблицу переданного объекта.

ipairs (t)

Возвращет три значения (функцию итератор, таблицу t и 0), так что конструкция

     for i,v in ipairs(t) do body end

будет перебирать пары ключ–значение (1,t[1]), (2,t[2]), …, до первого значения nil.

load (chunk [, chunkname [, mode [, env]]])

Загружает кусок.

Если chunk это строка, кусок будет этой строкой. Если chunk это функция, load многократно вызывает её, чобы получить части куска. Каждый вызов chunk должен возвращать строку, которая присоединяется к предыдущим результатам. Возврат пустой строки, nil или ничего сигнализирует о конце куска.

Если в куске нет синтаксических ошибок, возвращает скомпилированный кусок, как функцию; иначе, возвращает nil и сообщение об ошибке.

Если результирующая функция имеет upvalue, первое upvalue устанавливается равным env, если этот параметр передан, или в значение глобального окружения. Остальные upvalue инициализируются значением nil. (Когда вы загружаете главный кусок, результирующая функция всегда будет иметь только одно upvalue, переменную _ENV (см. §2.2). Тем не менее, когда вы загружаете бинарный кусок, созданный из функции (см.string.dump), результирующая функция может иметь произвольное количество upvalue.) Все upvalue свежие, т.е. они не разделяются между любыми другими функциями.

chunkname — используется как имя куска, для сообщений об ошибках и отладочной информации (см. §4.9). Когда отсутствует, его значение по умолчанию это сам chunk, если chunk это строка, или «=(load)» иначе.

Строка mode — управляет каким может быть кусок, текстовым или бинарным (т.е. прекомпилированным). Она может быть «b» (только бинарные куски), «t» (только текстовые куски) или «bt» (текстовые и бинарные куски). Значение по умолчанию это «bt«.

Lua не проверяет правильность бинарных кусков. Злонамеренно созданный бинарный кусок может разрушить интерпретатор.

loadfile ([filename [, mode [, env]]])

Аналогично load, но получает кусок из файла filename или из стандартного потока ввода, если имя файла не передано.

next (table [, index])

Позволяет программе просмостреть все поля таблицы. Её первый аргумент — это таблица, второй аргумент — индекс в этой таблице. nextвозвращает следующий индекс таблицы и ассоциированное с ним значение. Когда вызывается с nil в качестве второго аргумента, next возвращает начальный индекс и ассоциированое с ним значение. Когда вызывается с последним индексом, или с nil для пустой таблицы, next возвращает nil. Если второй аргумет отсутствует, то он интерпретируется как nil. В частности, вы можете использовать next(t) для проверки, что таблица пустая.

Порядок перечисления индексов не определен, даже для числовых индексов. (Для просмотра таблицы в числовом порядке, используйте числовойfor.)

Поведение next неопределено, если во время просмотра вы присваиваете любое значение несуществующему полю в таблице. Тем не менее вы можете модифицировать существующие поля. В частности, вы можете очищать существующие поля.

pairs (t)

Если t имеет метаметод __pairs, вызывает его с аргументом t и возвращает первые три результата вызова.

Иначе, возвращает три значения: функцию next, таблицу t и nil, так что конструкция

     for k,v in pairs(t) do body end

будет перебирать все пары ключ–значение в таблице t.

См. функцию next для предострежений о модификации таблицы во время просмотра.

pcall (f [, arg1, ···])

Вызывает функцию f с переданными аргументами в защищенном режиме. Это значит, что любая ошибка внутри f не распространяется; взамен,pcall перехватывает ошибку и возвращает код статуса. Её первый результат — код статуса (логическое значение), которое равно true, если вызов успешен. В этом случае pcall также возвращает все результаты из вызова, после первого результата. В случае ошибки pcall возвращает false и сообщение об ошибке.

print (···)

Получает произвольное количество аргументов и печатает их значения в stdout, используя функцию tostring для преобразования каждого аргумента в строку. print не предназначен для форматированного вывода, только как быстрый способ показать значение, например, для отладки. Для полного контроля над выводом используйте string.format и io.write.

rawequal (v1, v2)

Проверяет, что v1 равен v2, без вызова метаметодов. Возвращает логическое значение.

rawget (table, index)

Возвращает реальное значение table[index], без вызова метаметодов. table должен быть таблицей, index может быть любым значением.

rawlen (v)

Возвращает длину объекта v, который должен быть таблицей или строкой, без вызова метаметодов. Возвращает целое.

rawset (table, index, value)

Устанавливает реальное значение table[index] равным value, без вызова метаметодов. table должен быть таблицей, index — любое значение отличное от nil и NaN, value — любое Lua значение.

Эта функция возвращает table.

select (index, ···)

Если index это число, возвращает все аргументы после аргумента номер index; негативное число индексируется с конца (-1 последний аргумент). Иначе, если index строка "#", select вернет общее количество дополнительных аргументов.

setmetatable (table, metatable)

Устанавливает метатаблицу для данной таблицы. (Вы не можете изменять метатаблицы других типов из Lua, только из C.) Если metatable = nil, удаляет метатаблицу переданной таблицы. Если оригинальная метатаблица имеет поле "__metatable", генерирует ошибку.

Эта функция возвращает table.

tonumber (e [, base])

Когда вызвана без аргумента base, tonumber пытается конвертировать аргумент в число. Если аргумент уже число или строка, которую можно преобразовать в число, то tonumber возвращает это число; иначе, возвращает nil.

Преобразование строк может выдавать в результате целые или вещественные числа, в соответствии с лексическими соглашениями Lua (см. §3.1). (Строка может иметь начальные и конечные пробелы и знак.)

Когда вызвана с аргументом base, то аргумент e должен быть строкой, которая интерпретируется как целое в данной системе счисления. base может быть любым целым от 2 до 36, включительно. При base > 10, символ ‘A‘ (в верхнем или нижнем регистре) представляет 10, ‘B‘ представляет 11 и так далее, с ‘Z‘ представляющим 35. Если строка e не правильное число в данной системе счисления, функция возвращает nil.

tostring (v)

Получает значение любого типа и преобразует его в строку в понятном человеку формате. (Для полного контроля над преобразованием чисел используйте string.format.)

Если метатаблица v имеет поле "__tostring", то tostring вызывает соответствующее значение с v в качестве аргумента и использует результат вызова, как свой результат.

type (v)

Возвращает тип любого аргумента, представленный строкой. Возможные результаты этой функции: «nil» (строка, не значение nil), «number«, «string«, «boolean«, «table«, «function«, «thread» и «userdata«.

_VERSION

Глобальная переменная (не функция), которая содержит строку с текущей версией интерпретатора. Текущее значение этой переменной «Lua 5.3«.

xpcall (f, msgh [, arg1, ···])

Эта функция похожа на pcall, но она устанавливает новый обработчик сообщений msgh.

6.2 – Работа с сопроцессами

Эта библиотека содержит операции для манипуляции с сопроцессами, которые хранятся в таблице coroutine. См. §2.6 для общего описания сопроцессов.

coroutine.create (f)

Создает новый сопроцесс, с телом f. f должен быть функцией. Возвращает этот новый сопроцесс, как объект с типом "thread".

coroutine.isyieldable ()

Возвращает true, когда запущенный сопроцесс может уступить.

Запущенный сопроцесс может уступать, если это не главный поток и он не внутри неприостанавливаемой C функции.

coroutine.resume (co [, val1, ···])

Начинает или продолжает выполнение сопроцесса co. При первом возобновлении сопроцесса запускает его тело. Значение val1, … передаются как аргументы телу сопроцесса (его функции). Если сопроцесс был приостановлен, resume перезапускает его; значниния val1, … передаются как результаты из yield.

Если сопроцесс запущен без ошибок, resume возвращает true и все значения, переданные в yield (когда сопроцесс уступает) или все значения, возвращенные функцией сопроцесса (когда сопроцесс завершается). В случае ошибок, resume возвращает false и сообщение об ошибке.

coroutine.running ()

Возвращает запущенный сопроцесс и логическое значение; true, если сопроцесс это главный поток.

coroutine.status (co)

Возвращает статус сопроцесса co, как строку: "running" — сопроцесс запущен (т.е. он вызвал status); "suspended" — сопроцесс приостановлен в вызове yield или еще не запущен; "normal" — сопроцесс активен, но не выполняется (т.е. он был продолжен другим сопроцессом); "dead" — сопроцесс завершил своё тело или был остановлен с ошибкой.

coroutine.wrap (f)

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

coroutine.yield (···)

Приостанавливает выполнение вызывающего сопроцесса. Все аргументы yield передаются, как дополнительные результаты в resume.

6.3 – Модули

Эта пакетная библиотека предоставляет базовые возможности для загрузки модулей в Lua. Она экспортирует одну функцию напрямую в глобальное окружение: require. Всё остальное экспортируется в таблице package.

require (modname)

Загружает переданный модуль. Функция начинает с просмотра таблицы package.loaded для определения, что модуль modname уже загружен. Если это так, то require возвращает значение, хранящееся в package.loaded[modname]. Иначе, пробует найти загрузчик для модуля.

При поиске загрузчика require руководствуется последовательностью package.searchers. Изменяя эту последовательность, вы можете изменить то, как require ищет модуль. Следующее объяснение базируется на конфигурации по умолчанию для package.searchers.

Сначала require запрашивает package.preload[modname]. Если это значение существует, то это значение (которое может быть функцией) это загрузчик. Иначе require ищет Lua загрузчик, используя путь, хранящийся в package.path. Если это тоже неудачно, она ищет C загрузчик, используя путь, хранящийся в package.cpath. Если и это неудачно, пробует все в одном загрузчик (см. package.searchers).

Как только загрузчик найден, require вызывает загрузчик с двумя аргументами: modname и дополнительное значение, зависящее от того, как получен загрузчик. (Если загрузчик пришел из файла, это дополнительное значение будет именем файла.) Если загрузчик возвращает не-nil значение, require записывает возвращенное значение в package.loaded[modname]. Если загрузчик не вернул не нулевое значение иpackage.loaded[modname] не присвоено никакое значение, то require пишет туда true. В любом случае, require возвращает финальное значениеpackage.loaded[modname].

Если во время загрузки или запуска модуля происходит ошибка, или если не найден ни один загрузчик для модуля, require генерирует ошибку.

package.config

Строка описывающая некоторые конфигурации времени компиляции для пакетов. Эта строка (string) состоит из последовательности строк (line):

  • Первая строка — это строка разделитель директорий. По умолчанию, это ‘‘ для Windows и ‘/‘ для всех остальных систем.
  • Вторая строка — символ, который разделяет шаблоны в пути. По умолчанию это ‘;‘.
  • Третья строка — это строка, которая обозначает точки замены в шаблоне. По умолчанию это ‘?‘.
  • Четвертая строка — это строка, которая в пути в Windows, заменяется на директорию исполняемого файла. По умолчанию это ‘!‘.
  • Пятая строка — это метка для игнорирования всего текста после неё, когда формируется имя функции luaopen_. По умолчанию это ‘-‘.

package.cpath

Этот путь используется require для поиска C загрузчика.

Lua инициализирует C путь package.cpath также, как и Lua путь package.path, используя переменную окружения LUA_CPATH_5_3 или переменную окружения LUA_CPATH или путь по умолчанию, определенный в luaconf.h.

package.loaded

Таблица, используемая require для контроля за тем, какие модули уже загружены. Когда вы загружаете модуль modname иpackage.loaded[modname] не false, require просто возвращает хранящееся там значение.

Эта переменная только ссылка на реальную таблицу; присваивание этой переменной не изменяет таблицу, используемую функцией require.

package.loadlib (libname, funcname)

Динамически связывает (link) хостовую программу с C библиотекой libname.

Если funcname = «*«, то она только связывает с библиотекой, делая экспортируемые библиотекой символы доступными для других динамических библиотек. Иначе, она ищет функцию funcname внутри библиотеки и возвращает эту функцию, как C функцию. Так, funcname должна соответствовать прототипу lua_CFunction (см. lua_CFunction).

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

Эта функция не поддерживается стандартным C. Т.к., она доступна только для некоторых платформ (Windows, Linux, Mac OS X, Solaris, BSD и другие Unix системы, которые поддерживаю стандарт dlfcn).

package.path

Этот путь используется require для поиска Lua загрузчика.

Во время запуска Lua инициализирует эту переменную значением переменной окружения LUA_PATH_5_3 или переменной окружения LUA_PATH, или значением по умолчанию, определенным в luaconf.h, если эти переменные окружения не определены. Любое «;;» в значении переменной окружения заменяется путем по умолчанию.

package.preload

Таблица для хранения загрузчиков для специфических модулей (см. require).

Эта переменная только ссылается на реальную таблицу; присваиваение этой переменной не изменяет таблицу, используемую функцией require.

package.searchers

Таблица, используемая require для контроля над тем, как загружать модули.

Каждый элемент в этой таблице это функция искатель (searcher). Когда ищется модуль, require вызывает каждую из этих функций в возрастающем порядке, с именем модуля (аргумент переданный в require) в качестве единственного параметра. Функция может вернуть другую функцию (загрузчик модуля) и дополнительное значение, которое будет передано загрузчику, или строку, объясняющую, почему модуль не найден (или nil если нечего сказать).

Lua инициализирует эту таблицу четырьмя функциями искателями.

первый искатель просто ищет загрузчик в таблице package.preload.

Втрой искатель ищет загрузчик для Lua библиотеки, используя путь package.path. Поиск производится как описано в функцииpackage.searchpath.

Третий искатель ищет загрузчик для C библиотеки, используя путь package.cpath. Поиск производится как описано в функцииpackage.searchpath. Например, если C путь это строка

     "./?.so;./?.dll;/usr/local/?/init.so"

искатель для модуля foo будет пробовать открыть файлы ./foo.so, ./foo.dll, и /usr/local/foo/init.so, в этом порядке. Когда он найдет C библиотеку, сначала он использует средства динамического связывания с библиотекой. Затем попытается найти в библиотеке C функцию для использования в качестве загрузчика. Имя этой C функции это строка «luaopen_«, склеенная с копией имени модуля, где каждая точка заменена на подчеркивание. Более того, если имя модуля имеет дефис, его суффикс после первого дефиса удаляется (дефис тоже удаляется). Например, если имя модуля a.b.c-v2.1, имя функции будет luaopen_a_b_c.

Четвертый искатель пробует все в одном загрузчик. Он ищет C путь для библиотеки с корневым путем переданного модуля. Например, когда требуется a.b.c, он будет искать C библиотеку a. Если существует, он заглянет в нее для открытия функции подмодуля; в нашем примере, это будет luaopen_a_b_c. С этой возможностью, пакет может упаковывать различные C подмодули в одной библиотеке, где каждый подмодуль имеет свою оригинальную функцию открытия.

Все искатели, за исключением первого (preload), возвращают имя файла, где найден модуль, как дополнительное значение, возвращаемоеpackage.searchpath. Первый искатель не возвращает дополнительное значение.

package.searchpath (name, path [, sep [, rep]])

Ищет имя name в пути path.

Путь — это строка, содержащая последовательность шаблонов, разделенных точкой с запятой (;). Для каждого шаблона, функция заменяет каждый знак вопроса (если существует) копией name, где все случаи sep (точка, по умолчанию) заменяются на rep (системный разделитель директорий, по умолчанию), и пытается открыть результирующее имя файла.

Например, если путь это строка

     "./?.lua;./?.lc;/usr/local/?/init.lua"

поиск имени foo.a будет пытаться открыть файлы ./foo/a.lua, ./foo/a.lc и /usr/local/foo/a/init.lua, в этом порядке.

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

6.4 – Работа со строками

Эта библиотека предоставляет общие функции для работы со строками, такие как поиск, извлечение подстрок и сопоставление шаблонов. Когда индексируются строки в Lua, первый символ находится на позиции 1 (не на 0, как в C). Допускаются негативные индексы, они интерпретируются как индексирование обратно (задом наперед), с конца строки. Таким образом, последний символ находится на позиции -1 и так далее.

Строковая библиотека предоставляет все свои функции в таблице string. Она также устанавливает метатаблицу для строк, где поле __indexуказывает на таблицу string. Следовательно, вы можете использовать строковые функции в объектно-ориентированном стиле. Например, выражение string.byte(s,i) может быть записано как s:byte(i).

Строковая библиотека предполагает кодирование символов одним байтом.

string.byte (s [, i [, j]])

Возвращает внутренние цифровые коды символов s[i], s[i+1], …, s[j]. По умолчанию i = 1; j = i. Эти индексы следуют тем же правилам, что и в функции string.sub.

Цифровые коды не обязательно портабельны между платформами.

string.char (···)

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

Цифровые коды не обязательно портабельны между платформами.

string.dump (function [, strip])

Возвращает строку содержащую бинарное представление (бинарный кусок) переданной функции, так что load для этой строки возвращает копию функции (но с новыми upvalue). Если strip = true, бинарное представление может не включать всю отладочную информацию о функции, для уменьшения размера.

Функции с upvalue сохраняют только количество upvalue. При загрузке, эти upvalue получают свежие экземпляры, содержащие nil. (Вы можете использовать отладочную библиотеку, чтобы сохранить и перезагрузить upvalue функции в том виде, как вам нужно.)

string.find (s, pattern [, init [, plain]])

Ищет первое совпадение шаблона pattern (см. §6.4.1) в строке s. Если совпадение найдено, то find возвращает индексы s, где совпадение начинается и заканчивается; иначе, возвращает nil. Третий опциональный цифровой аргумент init определяет, где начинать поиск; по умолчанию он равен 1 и может быть отрицательным. Значение true в качестве четвертого опционального аргумента plain выключает возможности поиска шаблонов, так функция выполняет плоский поиск подстроки, без магических символов в pattern. Учтите, что если передан plain, то должен быть передан и init.

Если шаблон имеет захваты (capture), то при успешном совпадении захваченные значения также возвращаются, после двух индексов.

string.format (formatstring, ···)

Возвращает форматированную версию переменного количества аргументов, следуя описанию в первом аргументе (должен быть строкой). formatstring — следует тем же правилам, что и в функции sprintf в ISO C. Только отличается тем, что опции/модификаторы *, h, L, l, n и p не поддерживаются, и тем, что имеет дополнительную опцию q. Опция q форматирует строку между двойными кавычками и использует управляющие символы, когда необходимо гарантировать, что строка может быть прочитана Lua интерпретатором обратно. Например, вызов

     string.format('%q', 'a string with "quotes" and n new line')

может выдать строку:

     "a string with "quotes" and 
      new line"

Опции A, a, E, e, f, G и g — все ожидают цифровой аргумент. Оции c, d, i, o, u, X и x — ожидают целое. Опция q — ожидает строку. Опция s — ожидает строку без встроенных нулей; если аргумент не строка, он конвертируется следуя тем же правилам, что и в tostring.

Когда Lua скомпилирована с не C99 компилятором, опции A и a (шестнадцатиричные вещественные числа) не поддерживают модификаторы (флаги, ширина, длина).

string.gmatch (s, pattern)

Возвращает функцию-итератор, которая при каждом вызове возвращает следующие захваченные значения из pattern (см. §6.4.1) по строке s. Если pattern не определяет захватов, то в каждом вызове возвращается целое совпадение.

Например, следующий цикл будет перебирать все слова из строки s, печатая по одному в строке:

     s = "hello world from Lua"
     for w in string.gmatch(s, "%a+") do
       print(w)
     end

Следующий пример собирает в таблице все пары key=value из строки:

     t = {}
     s = "from=world, to=Lua"
     for k, v in string.gmatch(s, "(%w+)=(%w+)") do
       t[k] = v
     end

Для этой функции, символ ‘^‘ в начале шаблона не работает как якорь, т.к. это мешает итерации.

string.gsub (s, pattern, repl [, n])

Возвращает копию s, в которой все (или первые n, если передано) совпадения шаблона pattern (см. §6.4.1) заменены на замещающую строку, определенную параметром repl, который может быть строкой, таблицей или функцией. gsub также возвращает общее число совпадений, как второе значение. Имя gsub происходит от Global SUBstitution (глобальная подстановка).

Если repl это строка, то её значение используется для замены. Символ % работает, как управляющий символ: любая последовательность в repl в виде %d, с d между 1 и 9, соответствует d-ой захваченной подстроке. Последовательность %0 соответствует полному совпадению. Последовательность %% соответствует одному символу %.

Если repl это таблица, то таблица запрашивается для каждого совпадения, используя первое захваченное значение, как ключ.

Если repl это функция, то эта функция вызывается для каждого совпадения, все захваченные подстроки передаются в качестве аргументов, по порядку.

В любом случае, если шаблон не имеет захватов, то он ведет себя так, будто весь шаблон находится в захвате.

Если значение, возвращенное из табличного запроса или из функции, это строка или число, то оно используется, как замещающая строка; иначе, если это false или nil, то замена не производится (т.е. оригинальное содержимое совпадения сохраняется в строке).

Несколько примеров:

     x = string.gsub("hello world", "(%w+)", "%1 %1")
     --> x="hello hello world world"
     
     x = string.gsub("hello world", "%w+", "%0 %0", 1)
     --> x="hello hello world"
     
     x = string.gsub("hello world from Lua", "(%w+)%s*(%w+)", "%2 %1")
     --> x="world hello Lua from"
     
     x = string.gsub("home = $HOME, user = $USER", "%$(%w+)", os.getenv)
     --> x="home = /home/roberto, user = roberto"
     
     x = string.gsub("4+5 = $return 4+5$", "%$(.-)%$", function (s)
           return load(s)()
         end)
     --> x="4+5 = 9"
     
     local t = {name="lua", version="5.3"}
     x = string.gsub("$name-$version.tar.gz", "%$(%w+)", t)
     --> x="lua-5.3.tar.gz"

string.len (s)

Получает строку и возвращает её длину. Пустая строка "" имеет длину 0. Встроенные нули считаются, так "a00bc00" имеет длину 5.

string.lower (s)

Получает строку и возвращает её копию с заменой всех символов в верхнем регистре на символы в нижнем регистре. Остальные символы не изменяются. Определение какие символы в верхнем регистре зависит от текущей локали.

string.match (s, pattern [, init])

Ищет первое совпадение шаблона pattern (см. §6.4.1) в строке s. Если находит, то match возвращает захваченные значения из шаблона; иначе возвращает nil. Если pattern не описывает захватов, то возвращается целое совпадение. Третий опциональный цифровой аргумент initопределяет, где начинать поиск; по умолчанию он равен 1, и может быть отрицательным.

string.pack (fmt, v1, v2, ···)

Возвращает бинарную строку, содержащую значения v1, v2 и т.д. упакованными (т.е. записанными в бинарной форме) согласно форматной строкеfmt (см. §6.4.2).

string.packsize (fmt)

Возвращает размер результирующей строки из string.pack с переданным форматом. Форматная строка не может иметь опций переменной длины ‘s‘ или ‘z‘ (см. §6.4.2).

string.rep (s, n [, sep])

Возвращает строку, которая состоит из слияния n копий строки s, разделенных строкой sep. Значение по умолчанию для sep это пустая строка (т.е. нет разделителя). Возвращает пустую строку, если n отрицательное значение.

string.reverse (s)

Возвращает строку, в которой символы s идут в обратном порядке.

string.sub (s, i [, j])

Возвращает подстроку s, начинающуюся на i и продолжающуюся до j; i и j могут быть отрицательными. Если j отсутствует, то он подразумевается равным -1 (тоже что и длина строки). В частности, вызов string.sub(s,1,j) возвращает префикс s длиной j, и string.sub(s, -i) возвращает суффикс s длиной i.

Если после трансляции отрицательных индексов i < 1, он корректируется до 1. Если j больше длины строки, он корректируется до этой длины. Если после этих преобразований i > j, функция возвращает пустую строку.

string.unpack (fmt, s [, pos])

Возвращает значения, упакованные в строке s (см. string.pack) согласно форматной строке fmt (см. §6.4.2). Опциональный параметр posотмечает, где начинать чтение в s (по умолчанию 1). После чтения значений, эта функция также возвращает индекс первого не прочитанного байта в s.

string.upper (s)

Получает строку и возвращает её копию с заменой всех символов в нижнем регистре на символы в верхнем регистре. Остальные символы не изменяются. Определение какие символы в нижнем регистре зависит от текущей локали.

6.4.1 – Шаблоны

Шаблоны в Lua описываются регулярными строками, которые интерпретируются, как шаблоны, функциями сопоставления шаблонов string.find,string.gmatch, string.gsub и string.match. Этот раздел описывает синтаксис и значение (сопоставление) этих строк.

Символьный класс:

Символьный класс используется для представления набора символов. В описании символьного класса допустимы следующие комбинации:

  • x: (где x — не один из магических символов ^$()%.[]*+-?) представляет символ x непосредственно.
  • .: (точка) представляет все символы.
  • %a: представляет все буквы.
  • %c: представляет все управляющие символы.
  • %d: представляет все цифры.
  • %g: представляет все печатаемые символы, кроме пробела.
  • %l: представляет все буквы в нижнем регистре.
  • %p: представляет все знаки пунктуации.
  • %s: представляет все пробельные символы.
  • %u: представляет все буквы в верхнем регистре.
  • %w: представляет все алфавитно-цифровые символы.
  • %x: представляет все шестнадцатиричные символы.
  • %x: (где x — не алфавитно-цифровой символ) представляет символ x. Это стандартный способ кодирования магических символов. Любой не алфавитно-цифровой символ (включая все знаки пунктуации, даже не магические) могут предваряться ‘%‘, когда используются для представления себя в шаблоне.
  • [набор]: представляет класс, который является объединением всех символов в наборе. Диапазон символов может быть определен отделением конечного символа диапазона, в восходящем порядке, символом ‘-‘. Все классы %x, описанные выше, также могут быть включены в набор, как компоненты. Все остальные символы в наборе представляют непосредственно себя. Например, [%w_] (или [_%w]) представляет все алфавитно-цифровые символы и подчеркивание, [0-7] представляет восьмиричные цифры, [0-7%l%-] представляет восьмиричные цифры, буквы в нижнем регистре и символ ‘-‘.Взаимодействие между диапазонами и классами не определено. Следовательно, шаблоны как [%a-z] или [a-%%] не имеют значения.
  • [^набор]: представляет отрицание набора, где набор интерпретируется, как описано выше.

Для всех классов, представленных одним символом (%a, %c и др.), соответствующие представления с буквой в верхнем регистре отрицают класс. Например, %S представляет все не пробельные символы.

Определения букв, пробелов и других групп символов зависят от текущей локали. В частности, класс [a-z] может не быть эквивалентом %l.

Элемент шаблона:

элементом шаблона может быть

  • односимвольный класс, который соответствует одному символу в классе;
  • односимвольный класс с последующим символом ‘*‘, который соответствует нулю или более повторам символов в классе. Этот повтор элементов всегда будет соответствовать самой длинной возможной последовательности;
  • односимвольный класс с последующим символом ‘+‘, который соответствует одному или более повторам символов в классе. Этот повтор элементов всегда будет соответствовать самой длинной возможной последовательности;
  • односимвольный класс с последующим символом ‘-‘, который соответствует нулю или более повторам символов в классе. В отличие от ‘*‘, этот повтор элементов всегда будет соответствовать самой короткой возможной последовательности;
  • односимвольный класс с последующим символом ‘?‘, который соответствует нулю или одному случаю символа в классе. Он всегда соответсвует одному вхождению, если возможно;
  • %n, для n между 1 и 9; этот элемент соответствует подстроке равной n-й захваченной строке (см. ниже);
  • %bxy, где x и y два четких символа; этот элемент соответствует строкам, которые начинаются с  x и заканчиваются на  y, и где x и yсбалансированы. Это значит, что если при чтении строки слева направо, считать +1 для x и -1 для y, завершающий y это первый y, где счет достигнет 0. Например, элемент %b() соответсвует выражениям в сбалансированных скобках.
  • %f[набор], граничный шаблон; этот элемент соответствует пустой строке в любой позиции такой, что следующий символ принадлежит наборуи предыдущий символ не принадлежит набору. Набор интерпретируется, как описано выше. Начало и конец субъекта обрабатывается, как если там символ ‘‘.

Шаблон:

Шаблон — это последовательность элементов шаблона. Символ ‘^‘ в начале шаблона фиксирует его в начале строки. Символ ‘$‘ в конце шаблона фиксирует его в конце строки. В остальных позициях ‘^‘ и ‘$‘ не имеют специального значения и представляют сами себя.

Захваты (capture):

Шаблон может содержать подшаблоны заключенные в скобки; они описывают захваты. Когда совпадение успешно, подстроки, которые соответсвуют захватам (захваченные), сохраняются для последующего использования. Захваты нумеруются соответственно их левым скобкам. Например, в шаблоне "(a*(.)%w(%s*))", часть строки, соответствующая "a*(.)%w(%s*)", сохраняется как первый захват (и следовательно имеет номер 1); соответствие «.» захватывается с номером 2, и часть соответствующая «%s*» имеет номер 3.

Специальный случай, пустой захват () захватывает текущую позицию в строке (число). Например, если мы применим шаблон "()aa()" к строке"flaaap", будет сделано два захвата: 3 и 5.

6.4.2 – Формат строк для string.pack и string.unpack

Первый аргумент в string.pack, string.packsize и string.unpack это строка формата, которая описывает формат создаваемой или читаемой структуры.

Строка формата — это последовательность опций преобразования. Опции преобразования следующие:

  • <: устанавливает прямой порядок байт (little endian)
  • >: устанавливает обратный порядок байт (big endian)
  • =: устанавливает исконный порядок байт
  • ![n]: устанавливает максимальное выравнивание равным n (по умолчанию, исконное выравнивание)
  • b: знаковый байт (char)
  • B: беззнаковый байт (char)
  • h: знаковый short (исконный размер)
  • H: беззнаковый short (исконный размер)
  • l: знаковый long (исконный размер)
  • L: беззнаковый long (исконный размер)
  • j: lua_Integer
  • J: lua_Unsigned
  • T: size_t (исконный размер)
  • i[n]: знаковый int с n байт (по умолчанию, исконный размер)
  • I[n]: беззнаковый int с n байт (по умолчанию, исконный размер)
  • f: float (исконный размер)
  • d: double (исконный размер)
  • n: lua_Number
  • cn: строка фиксированного размера с n байт
  • z: завершаемая нулем строка
  • s[n]: строка с предваряющим её размером, кодированным как беззнаковое целое с n байт (по умолчанию, это size_t)
  • x: один байт заполнения
  • Xop: пустой элемент, который выравнивает в соответствии с опцией op (которая в противном случае игнорируется)
  • ‘: (пустое пространство) игнорируется

[n]» означает опциональную целую цифру.) Кроме заполнения, пробелов и конфигураций (опции «xX <=>!«), каждая опция соответствует аргументу (в string.pack) или результату (в string.unpack).

Для опций «!n«, «sn«, «in» и «In«, n может быть целым от 1 до 16. Все целые опции проверяют переполнения; string.pack проверяет, что переданное значение поместится в переданный размер; string.unpack проверяет, что прочитанное значение поместится в целое Lua.

Любая строка формата начинается так, будто содержит префикс «!1=«, т.е. с максимальным выравниванием 1 (без выравнивания) и исконным порядком байт.

Выравнивание работает так: для каждой опции формат получает дополнительное заполнение, пока не начнутся данные по смещению, которое равно произведению минимума между размером опции и максимального выравнивания; этот минимум должен быть степенью 2. Опции «c» и «z» не выравниваются; опция «s» следует выравниванию её начального целого.

Все заполнения заполняются нулями в string.pack (и игнорируются в string.unpack).

6.5 – Поддержка UTF-8

Эта библиотека предоставляет базовую поддержку для кодировки UTF-8. Она предоставляет все свои функции в таблице utf8. Эта библиотека не предоставляет другой поддержки для Unicode, кроме обработки кодировки. Все операции, нуждающиеся в значении символа, такие как классификация символов, не входят в эту область.

Пока не установлено иначе, все функции, которые ожидают позицию байта, как параметр, предполагают, что переданная позиция является также началом последовательности байт или позиция плюс длина строки. Как и в строковой библиотеке, отрицательные индексы отсчитываются с конца строки.

utf8.char (···)

Получает ноль или более целых, конвертирует каждое из них в соответствующую последовательность байт UTF-8 и возвращает строку со слиянием всех этих последовательностей.

utf8.charpattern

Шаблон (строка, не функция) «[-x7FxC2-xF4][x80-xBF]*» (см. §6.4.1), который соответствует точно одной последовательности байт UTF-8, предполагается, что субъект это правильная UTF-8 строка.

utf8.codes (s)

Возвращает значения такие, что конструкция

     for p, c in utf8.codes(s) do body end

будет перебирать все символы в строке s, где p — позиция (в байтах) и c — кодовая точка для каждого символа. Функция вызывает ошибку, если встретит неправильную последовательность байт.

utf8.codepoint (s [, i [, j]])

Возвращает кодовые точки (как целые) для всех символов в s, начиная с байта на позиции i и заканчивая j (включительно). По умолчанию, i = 1 иj = i. Функция вызывает ошибку, если встретит неправильную последовательность байт.

utf8.len (s [, i [, j]])

Возвращает количество символов UTF-8 в строке s, начиная с байта на позиции i и заканчивая j (включительно). По умолчанию, i = 1 и j = -1. Если функция встречает неправильную последовательность байт, она возвращает false и позицию первой неправильной последовательности байт.

utf8.offset (s, n [, i])

Возвращает позицию (в байтах), где начинается n-й закодированный символ строки s (счет идет с позиции i). При отрицательном значении n, получает символы перед позицией i. По умолчанию, i = 1, когда n положительное значение, и i = #s + 1 иначе, так utf8.offset(s, -n)получает смещение n-го символа с конца строки. Если определенный символ ни в субъекте, ни справа после его конца, функция возвращает nil.

Специальный случай, когда n = 0, функция возвращает начало закодированного символа, который содержит i-й байт строки s.

Эта функция предполагает, что s это правильная строка UTF-8.

6.6 – Работа с таблицами

Эта библиотека предоставляет базовые функции для работы с таблицами. Она предоставляет все свои функции в таблице table.

Помните, что когда операция нуждается в длине таблицы, таблица должа содержать соответсвующую последовательность или иметь метаметод__len (см. §3.4.7). Все функции игнорируют не цифровые ключи в таблицах, полученных как аргументы.

table.concat (list [, sep [, i [, j]]])

Получает список list, где все элементы строки или числа, возвращает строку list[i]..sep..list[i+1] ··· sep..list[j]. По умолчанию, sep это пустая строка, i = 1 и j = #list. Если i > j, возвращает пустую строку.

table.insert (list, [pos,] value)

Вставляет элемент value на позицию pos в список list, сдвигая элементы вверх list[pos], list[pos+1], ···, list[#list]. По умолчанию,pos = #list+1, так вызов table.insert(t,x) вставляет x в конец списка t.

table.move (a1, f, e, t [,a2])

Перемещает элементы из таблицы a1 в таблицу a2. Эта функция эквивалентна множественному присваиванию: a2[t],··· = a1[f],···,a1[e]. По умолчанию, a2 = a1. Целевой диапазон может перекрываться с диапазоном источником. Количество элементов для перемещения должно помещаться в целое Lua.

table.pack (···)

Возвращает новую таблицу, в которой все параметры сохранены с ключами 1, 2 и т.д. и поле «n» содержит количество параметров. Учтите, что результирующая таблица может не быть последовательностью.

table.remove (list [, pos])

Удаляет из списка list элемент на позиции pos, возвращая значение этого элемента. Когда pos это целое между 1 и #list, функция сдвигает элементы вниз list[pos+1], list[pos+2], ···, list[#list] и стирает элемент list[#list]; Индекс pos может быть 0, когда #list = 0, или#list + 1; в этих случаях функция стирает элемент list[pos].

По умолчанию, pos = #list, так вызов table.remove(l) удаляет последний элемент списка l.

table.sort (list [, comp])

Сортирует элементы полученного списка, на месте, от list[1] до list[#list]. Если передан параметр comp, он должен быть функцией, которая получает два элемента списка и возвращает true, когда первый элемент должен находиться перед вторым в финальном упорядочении (так выражение not comp(list[i+1],list[i]) будет истинным после сортировки). Если параметр comp не передан, то взамен Lua использует стандартный оператор <.

Алгоритм сортировки не стабилен; т.е. элементы, считающиеся равными в этом упорядочении, в результате сортировки могут изменить свои относительные позиции.

table.unpack (list [, i [, j]])

Возвращает элементы из полученного списка. Эта функция эквивалентна

     return list[i], list[i+1], ···, list[j]

По умолчанию, i = 1 и j = #list.

6.7 – Математические функции

Эта библиотека предоставляет базовые математические функции. Она предоставляет все свои функции и константы в таблице math. Функции с комментарием «integer/float» выдают целые результаты для целых аргументов и вещественные результаты для вещественных (или смешанных) аргументов. Функции округления (math.ceil, math.floor и math.modf) возвращают целое, когда результат помещается в диапазон целых, или вещественное иначе.

math.abs (x)

Возвращает абсолютное значение x. (integer/float)

math.acos (x)

Возвращает арккосинус x (в радианах).

math.asin (x)

Возвращает арксинус x (в радианах).

math.atan (y [, x])

Возвращает арктангенс y/x (в радианах), но использует знаки обоих параметров для поиска квадранта результата. (Также корректно обрабатывает случай, когда x = 0.)

По умолчанию x = 1, так вызов math.atan(y) возвращает арктангенс y.

math.ceil (x)

Возвращает наименьшее целое значение, которое больше или равно x.

math.cos (x)

Возвращает косинус x (в радианах).

math.deg (x)

Преобразует угол x из радиан в градусы.

math.exp (x)

Возвращает значение ex (где e — основание натурального логарифма).

math.floor (x)

Возвращает наибольшее значение, которое меньше или равно x.

math.fmod (x, y)

Возвращает остаток от деления x на y, который округляет частное к нулю. (integer/float)

math.huge

Вещественное значение HUGE_VAL, которое больше любого другого числового значения.

math.log (x [, base])

Возвращает логарифм x по основанию base. По умолчанию, base = e (так функция возвращает натуральный логарифм x).

math.max (x, ···)

Возвращает аргумент с максимальным значением, в соответствии с Lua оператором <. (integer/float)

math.maxinteger

Целое с максимальным значением для целого.

math.min (x, ···)

Возвращает аргумент с минимальным значением, в соответствии с Lua оператором <. (integer/float)

math.mininteger

Целое с минимальным значением для целого.

math.modf (x)

Возвращает целую и дробную часть x. Второй результат всегда вещественное число.

math.pi

Значение π.

math.rad (x)

Преобразует угол x из градусов в радианы.

math.random ([m [, n]])

Когда вызвана без аргументов, возвращает псевдослучайное вещественное число с однородным распределением в диапазоне [0,1). Когда вызвана с двумя целыми m и n, math.random возвращает псевдослучайное целое с однородным распределением в диапазоне [m, n]. (Значение m-n не может быть отрицательным и должно помещаться в целое Lua.) Вызов math.random(n) эквивалентен вызову math.random(1,n).

Эта функция является интерфейсом к генератору псевдослучайных чисел, предоставляемому C. Нет гарантий для его статистических свойств.

math.randomseed (x)

Устанавливает x как «затравку» (seed) для генератора псевдослучайных чисел: одинаковые затравки производят одинаковые последовательности чисел.

math.sin (x)

Возвращает синус x (в радианах).

math.sqrt (x)

Возвращает квадратный корень x. (Для вычисления этого значения вы также можете использовать выражение x^0.5.)

math.tan (x)

Возвращает тангенс x (в радианах).

math.tointeger (x)

Если значение x можно преобразовать в целое, возвращает целое. Иначе, возвращает nil.

math.type (x)

Возвращает «integer» — если x целое, «float» — если x вещественное, или nil — если x не число.

math.ult (m, n)

Возвращает логическое значение, true, если целое m ниже целого n, когда они сравниваются как беззнаковые целые.

6.8 – Средства ввода-вывода

Библиотека ввода-вывода предоставляет два разных стиля для файловых манипуляций. Первый использует подразумевающиеся описатели файлов (handle); т.е. там есть операции установки файла ввода и файла вывода по умолчанию, и все операции ввода-вывода используют эти файлы. Второй стиль использует явные описатели файлов.

При использовании неявных описателей файлов, все операции предоставляются в таблице io. При использовании явных описателей, операцияio.open возвращает описатель файла и затем все операции предоставляются, как методы этого описателя.

Таблица io также предоставляет три предопределенных файловых описателя с обычными значениями из C: io.stdin, io.stdout и io.stderr. Библиотека ввода-вывода никогда не закрывает эти файлы.

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

io.close ([file])

Эквивалентно file:close(). Без file, закрывает выходной файл по умолчанию.

io.flush ()

Эквивалентно io.output():flush().

io.input ([file])

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

В случае ошибок эта функция генерирует ошибку, вместо возвращения кода ошибки.

io.lines ([filename ···])

Открывает переданный файл в режиме чтения и возвращает функцию итератор, которая работает подобно file:lines(···) для открытого файла. Когда итератор доходит до конца файла, он ничего не возвращает (для завершения цикла) и автоматически закрывает файл.

Вызов io.lines() (без имени файла) эквивалентно io.input():lines("*l"); т.е. он перебирает линии файла ввода по умолчанию. В этом случае он не закрывает файл при завершении цикла.

В случае ошибок эта функция генерирует ошибку, вместо возвращения кода ошибки.

io.open (filename [, mode])

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

Строка mode может быть следующей:

  • «r«: режим чтения (по умолчанию);
  • «w«: режим записи;
  • «a«: режим добавления;
  • «r+«: режим обновления, все предыдущие данные сохраняются;
  • «w+«: режим обновления, все предыдущие данные стираются;
  • «a+«: режим добавления и обновления, предыдущие данные сохраняются, запись разрешена только в конец файла.

Строка mode также может содержать ‘b‘ в конце, это нужно на некоторых системах для открытия файла в бинарном режиме.

io.output ([file])

Подобно io.input, но для файла вывода по умолчанию.

io.popen (prog [, mode])

Эта функция зависит от системы и не доступна на некоторых платформах.

Запускает программу prog в отдельном процессе и возвращает описатель файла, который вы можете использовать для чтения данных из этой программы (если mode = "r", по умолчанию) или для записи данных в программу (если mode = "w").

io.read (···)

Эквивалентно io.input():read(···).

io.tmpfile ()

Возвращает описатель для временного файла. Этот файл открывается в режиме обновления и автоматически удаляется по завершении программы.

io.type (obj)

Проверяет, что независимый obj это правильный описатель файла. Возвращает строку "file" — если obj открытый описатель файла, "closed file" — если obj закрытый описатель файла, или nil — если obj не является описателем файла.

io.write (···)

Эквивалентно io.output():write(···).

file:close ()

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

Когда закрываемый описатель файла создан функцией io.popen, file:close возвращает те же значения, что и os.execute.

file:flush ()

Сохраняет все записанные данные в file.

file:lines (···)

Возвращает функцию итератор, которая при каждом вызове читает файл в соответствии с переданными форматами. Когда формат не передан, использует «l«, по умолчанию. Например, конструкция

     for c in file:lines(1) do body end

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

В случае ошибок эта функция генерирует ошибку, вместо возвращения кода ошибки.

file:read (···)

Читает файл file, в соответствии с переданными форматами, которые определяют, что читать. Для каждого формата, функция возвращает строку или число с прочитанными символами, или nil, если не может прочитать данные в этом формате. (В этом последнем случае, функция не читает последующие форматы.) Когда вызвана без форматов, использует по умолчанию формат, читающий следующую строку (см. ниже).

Доступны следующие форматы

  • «n«: читает число и возвращает его, как вещественное или целое, следуя лексическим соглашениям Lua. (Число может содержать начальные пробелы и знак.) Этот формат всегда читает самую длинную входную последовательность, которая является правильным префиксом для числа; если префикс не правильный (пустая строка, «0x» или «3.4e-«), он отбрасывается и функция возвращает nil.
  • «a«: читает весь файл, начиная с текущей позиции. В конце файла возвращает пустую строку.
  • «l«: читает следующую строку, пропуская символ конца строки, возвращает nil в конце файла. Это формат по умолчанию.
  • «L«: читает следующую строку, сохраняя символ конца строки (если есть), возвращает nil в конце файла.
  • число: читает строку этой длины в байтах, возвращает nil в конце файла. Если number = 0, ничего не читает и возвращает пустую строку, илиnil в конце файла.

Форматы «l» и «L» должны использоваться только для текстовых файлов.

file:seek ([whence [, offset]])

Устанавливает и возвращает позицию в файле, измеряемую от начала файла до позиции переданной в offset плюс база, определенная строкойwhence:

  • «set«: база на позиции 0 (начало файла);
  • «cur«: база на текущей позиции;
  • «end«: база в конце файла;

В случае успеха, seek возвращает окончательную позицию в файле, измеряемую в байтах от начала файла. При ошибке, возвращает nil и сообщение об ошибке.

По умолчанию whence = "cur", offset = 0. Так вызов file:seek() возвращает текущую позицию, не изменяя её; вызов file:seek("set")устанавливает позицию в начало файла (и возвращает 0); вызов file:seek("end") устанавливает позицию в конец файла и возвращает размер файла.

file:setvbuf (mode [, size])

Устанавливает режим буферизации для выходного файла. Доступны три режима:

  • «no«: без буферизации; результат любой операции вывода проявляется непосредственно.
  • «full«: полная буферизация; операция вывода выполняется только, когда буфер полон или когда вы явно сбрасываете (flush) файл (см.io.flush).
  • «line«: строчная буферизация; выход буферизуется до новой строки в выводе или до любого ввода из специальных файлов (таких как терминал).

Для двух последних случаев size определяет размер буфера, в байтах. По умолчанию это подходящий размер.

file:write (···)

Записывает значение каждого аргумента в file. Аргументы должны быть строками или числами.

В случае успеха функция возвращает file. Иначе, возвращает nil и сообщение об ошибке.

6.9 – Средства операционной системы

Эта библиотека реализована через таблицу os.

os.clock ()

Возвращает апроксимацию количества секунд времени процессора, использованного программой.

os.date ([format [, time]])

Возвращает строку или таблицу, содержащую дату и время, отформатированную в соответствии с переданной строкой format.

Если аргумент time передан, то он является временем для форматирования (см. функцию os.time для описания этого значения). Иначе, dateформатирует текущее время.

Если format начинается с символа ‘!‘, то дата форматируется во всемирном координированном времени (UTC). После этого опционального символа, если format это строка «*t«, то date возвращает таблицу со следующими полями: year — год (четыре цифры), month — месяц (1–12), day — день (1–31), hour — час (0–23), min — минута (0–59), sec — секунда (0–61), wday — день недели (воскресенье = 1), yday — день в году и isdst — летнее время (boolean). Это последнее поле может отсутствовать, если информация недоступна.

Если format не «*t«, то date возвращает дату как строку, форматированную согласно правилам C функции strftime.

Когда вызвана без аргументов, date возвращает разумное представление даты и времени, зависящее от хостовой системы и текущей локали (т.е.os.date() эквивалентно os.date("%c")).

На не POSIX системах эта функция может не быть потокобезопасной, т.к. она использует C функции gmtime и localtime.

os.difftime (t2, t1)

Возвращает разницу, в секундах, от времени t1 до времени t2 (где значения времени возвращены os.time). В POSIX, Windows и некоторых других системах это значение точно t2t1.

os.execute ([command])

Эта функция эквивалентна ISO C функции system. Она передает command для запуска оболочкой операционной системы. Её первый результат равен true, если команда завершена успешно, или nil иначе. После этого первого результата функция возвращает строку и число:

  • «exit«: команда завершена нормально; следующее число это выходной статус команды.
  • «signal«: команда была завершена сигналом; следующее число это сигнал, завершивший команду.

Когда вызвана без command, os.execute возвращет логическое значение, которое равно true, если оболочка (shell) доступна.

os.exit (])

Вызывает ISO C функцию exit для завершения хостовой программы. Если code = true, возвращается статус EXIT_SUCCESS; если code = false, возвращается статус EXIT_FAILURE; если code это число, возвращается статус равный этому числу. По умолчанию, code = true.

Если опциональный второй аргумент close = true, закрывает Lua состояние перед выходом.

os.getenv (varname)

Возвращает значение переменной окружения процесса varname, или nil, если переменная не определена.

os.remove (filename)

Удаляет файл (или пустую директорию, на POSIX системах) с переданным именем. Если функция терпит неудачу, она возвращает nil, сообщение об ошибке и код ошибки.

os.rename (oldname, newname)

Переименовывает файл или директорию oldname в newname. Если функция терпит неудачу, она возвращает nil, сообщение об ошибке и код ошибки.

os.setlocale (locale [, category])

Устанавливает текущую локаль для программы. locale — системозависимая строка, определяющая локаль; category — опциональная строка, описывающая какую категорию изменять: "all", "collate", "ctype", "monetary", "numeric" или "time"; по умолчанию category = "all". Функция возвращает имя новой локали, или nil, если запрос не может быть выполнен.

Если locale это пустая строка, текущая локаль устанавливается в засимую от реализации родную локаль. Если locale это строка «C«, текущая локаль устанавливается в стандартную C локаль.

Когда вызвана с nil в качестве первого аргумента, эта функция только возвращает имя текущей локали для данной категории.

Эта функция может не быть потокобезопасной, т.к. использует C функцию setlocale.

os.time ([table])

Возвращает текущее время, когда вызвана без аргуменов, или время, представляющее локальную дату и время определенные в переданной таблице. Эта таблица должна иметь поля year, month и day, и может иметь поля hour (по умолчанию, 12), min (по умолчанию, 0), sec (по умолчанию, 0) и isdst (по умолчанию, nil). Остальные поля игнорируются. Для описания этих полей, см. функцию os.date.

Значения этих полей могут не быть в своих правильных диапазонах. Например, если sec = -10, то это означает -10 секунд от времени, определенного другими полями; если hour = 1000, это означает +1000 часов от времени, определенного другими полями.

Возвращенное значение это число, значение которого зависит от вашей системы. В POSIX, Windows и некоторых других системах это количество секунд, прошедших с какого-то определенного времени («эпоха»). В других системах, значение не определено, и число, возвращенное функциейtime, может использоваться только, как аргумент для os.date и os.difftime.

os.tmpname ()

Возвращает строку с именем файла, который может быть использован, как временный. Файл должен быть явно открыт перед использованием и явно удален, когда больше не нужен.

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

Когда возможно, предпочтительно использовать функцию io.tmpfile, которая автоматически удаляет файл при завершении программы.

6.10 – Библиотека отладки

Эта библиотека предоставляет Lua программам функциональность отладочного интерфейса (§4.9). Используя эту библиотеку, вы должны проявлять внимательность. Различные функции этой билиотеки нарушают базовые предположения о Lua коде (например, что локальные переменные функции не могут быть доступны снаружи; что метатаблицы пользовательских данных не могут изменяться Lua кодом; что Lua программы не падают) и следовательно могут скомпрометировать защищенный код. Кроме того, некоторые функции в этой библиотеке могут быть медленными.

Все функции в этой библиотеке предоставляются в таблице debug. Все функции, которые оперируют с потоком, имеют опциональный первый аргумент, определяющий поток. По умолчанию, это всегда текущий поток.

debug.debug ()

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

Учтите, что команды для debug.debug не являются лексически вложенными ни в одну функцию и не имеют прямого доступа к локальным переменным.

debug.gethook ([thread])

Возвращает настройки текущего перехватчика потока, как три значения: текущая функция-перехватчик, текущая маска перехвата и текущий счетчик перехвата (как установлено функцией debug.sethook).

debug.getinfo ([thread,] f [, what])

Возвращает таблицу с информацией о функции. Вы можете передать функцию напрямую или можете передать число, как значение f, которое означает функцию, выполняющуюся на уровне f стека вызовов данного потока thread: уровень 0 — текущая функция (непосредственно getinfo); уровень 1 — функция, которая вызвала getinfo (за исключением хвостовых вызовов, которые не считаются на стеке); и так далее. Если число fбольше количества активных функций, то getinfo возвращает nil.

Возвращенная таблица может содержать все поля возвращаемые lua_getinfo, со строкой what, описывающей какие поля заполнены. По умолчанию, what установлена для получения всей доступной информации, кроме таблицы значимых строк. Если передана, опция ‘f‘ добавляет поле func с функцией непосредственно. Если передана, опция ‘L‘ добавляет поле activelines с таблицей значимых строк.

Например, выражение debug.getinfo(1,"n").name возвращает имя текущей функции, если разумное имя существует, и выражениеdebug.getinfo(print) возвращает таблицу со всей доступной информацией о функции print.

debug.getlocal ([thread,] f, local)

Эта функция возвращает имя и значение локальной переменной с индексом local функции на уровне f стека вызовов. Эта функция получает доступ не только к явным локальным переменным, но также к параметрам, временным переменныи и др.

Первый параметр или локальная переменная имеет индекс 1, и так далее, следуя порядку определения в коде, считаются только активные переменные в текущей области функции. Отрицательные индексы ссылаются на переменные (vararg) параметры; -1 первый переменный параметр. Функция возвращает nil, если нет переменной по данному индексу, и вызывает ошибку, когда вызвана с уровнем за пределами диапазона. (Вы можете вызвать debug.getinfo чтобы проверить, какой уровень допустим.)

Имена переменных, начинающиеся с ‘(‘ (открывающая скобка) представляют переменные с неизвестными именами (внутренние переменные, такие как переменные управления циклом, и переменные из кусков, сохраненных без отладочной информации).

Параметр f также может быть функцией. В этом случае getlocal возвращает только имена параметров функции.

debug.getmetatable (value)

Возвращает метатаблицу переданного значения value или nil, если у значения нет метатаблицы.

debug.getregistry ()

Возвращает таблицу реестра (см. §4.5).

debug.getupvalue (f, up)

Эта функция возвращает имя и значение upvalue с индексом up функции f. Функция возвращает nil, если по данному индексу нет upvalue.

Имена переменных, начинающиеся с символа ‘(‘ (открывающая скобка) , представляют переменные с неизвестными именами (переменные из кусков, сохраненных без отладочной информации).

debug.getuservalue (u)

Возвращает Lua значение, ассоциированное с u. Если u не пользовательские данные, возвращает nil.

debug.sethook ([thread,] hook, mask [, count])

Устанавливает переданную функцию, как перехватчик. Строка mask и число count описывают, когда будет вызыван перехватчик. Строка mask может содержать комбинацию следующих символов:

  • c‘: перехватчик вызывается каждый раз, когда Lua вызывает функцию;
  • r‘: перехватчик вызывается каждый раз, когда Lua возвращается из функции;
  • l‘: перехватчик вызывается каждый раз, когда Lua входит на новую линию кода.

Кроме того, с count не равным нулю, перехватчик вызывается также через каждые count инструкций (count в значении «количество»).

Когда вызвана без аргументов, debug.sethook выключает перехват.

Когда вызван перехватчик, его первый параметр — это строка, описывающая событие, которое стало причиной вызова перехватчика: "call" (или"tail call"), "return", "line" и "count". Для событий строк, перехватчик также получает номер строки во втором параметре. Внутри перехватчика вы можете вызвать getinfo с уровнем 2 для получения информации о запущенной функции (уровень 0 — это функция getinfo, уровень 1 — это функция-перехватчик).

debug.setlocal ([thread,] level, local, value)

Эта функция присваивает значение value локальной переменной по индексу local функции на уровне level в стеке вызовов. Функция возвращаетnil, если локальная переменная с данным индексом не существует, и генерирует ошибку, когда вызвана с level вне диапазона. (Вы можете использовать getinfo чтобы проверить какой уровень допустим.) Иначе, возвращает имя локальной переменной.

См. debug.getlocal для дополнительной информации о именах и индексах переменных.

debug.setmetatable (value, table)

Устанавливает table метатаблицей для value (table может быть равно nil). Возвращает value.

debug.setupvalue (f, up, value)

Эта функция присваивает значение value в upvalue с индексом up функции f. Функция возвращает nil, если по данному индексу нет upvalue. Иначе, возвращает имя upvalue.

debug.setuservalue (udata, value)

Устанавливает переданное значение value, как Lua значение, ассоциированное с udata. udata должно быть полными пользовательскими данными.

Возвращает udata.

debug.traceback ([thread,] [message [, level]])

Если message передано, но не строка и не nil, эта функция возвращет message без дальнейшей обработки. Иначе, возвращает строку с трассировкой стека вызовов. Опциональная строка message добавляется в начале трассировки стека. Опциональное число level говорит, на каком уровне начинать трассировку (по умолчанию равен 1 — функция, вызвавшая traceback).

debug.upvalueid (f, n)

Возвращает уникальный идентификатор (как лёгкие пользовательские данные) для upvalue под номером n из переданной функции.

Эти уникальные идентификаторы позволяют программе проверить, когда разные замыкания совместно используют одни upvalue. Lua замыкания, которые совместно используют upvalue (т.е. имеют доступ к одной внешней локальной переменной) вернут одинаковые идентификаторы для этих upvalue.

debug.upvaluejoin (f1, n1, f2, n2)

Заставляет n1-е upvalue Lua замыкания f1 ссылаться на n2-е upvalue Lua замыкания f2.

7 – Интерпретатор Lua

Хотя Lua был разработан, как язык расширений, чтобы встраивать в хостовую C программу, он также часто используется, как автономный язык. Интерпретатор Lua, как автономного языка, называется просто lua и предоставляется в стандартном дистрибутиве. Автономный интерпретатор включает все стандартные библиотеки, в том числе отладочную библиотеку. Синтаксис командной строки:

     lua [options] [script [args]]

Опции:

  • -e stat: запускает строку stat;
  • -l mod: загружает (require) mod;
  • -i: входит в интерактивный режим после запуска script;
  • -v: печатает информацию о версии;
  • -E: игнорирует переменные окружения;
  • --: останавливает обработку опций;
  • -: запускает stdin как файл и останавливает обработку опций.

После обработки опций, lua запускает переданный скрипт (script). Когда вызван без аргументов, lua ведет себя, как lua -v -i, когда стандартный ввод (stdin) это терминал; и как lua - иначе.

Когда вызван без опции -E, интерпретатор проверяет переменную окружения LUA_INIT_5_3 (или LUA_INIT, если предыдущая не определена) перед запуском аргументов. Если содержимое переменной имеет формат @filename, то lua запускает это файл. Иначе, lua запускает непосредственно эту строку.

Когда запущен с опцией -E, вместе с игнорированием LUA_INIT, Lua также игнорирует значения LUA_PATH и LUA_CPATH, устанавливая значенияpackage.path и package.cpath путями по умолчанию, определенными в luaconf.h.

Все опции обрабатываются по порядку, кроме -i и -E. Например, вызов

     $ lua -e'a=1' -e 'print(a)' script.lua

сначала установит a = 1, затем напечатает значение a, и наконец запустит файл script.lua без аргументов. (Здесь $ — это приглашение командной строки. Ваше приглашение может отличаться.)

Перед запуском любого кода lua собирает все аргументы командной строки в глобальной таблице arg. Имя скрипта идет под индексом 0, первый аргумент после имени скрипта идет по индексу 1, и т.д. Все аргументы перед именем скрипта (т.е имя интерпретатора и его опции) находятся по отрицательным индексам. Например, вызов

     $ lua -la b.lua t1 t2

даст таблицу:

     arg = { [-2] = "lua", [-1] = "-la",
             [0] = "b.lua",
             [1] = "t1", [2] = "t2" }

Если в вызове нет скрипта, имя интерпретатора идет по индексу 0, далее идут другие аргументы. Например, вызов

     $ lua -e "print(arg[1])"

напечатает «-e«. Если есть скрипт, то он вызывается с параметрами arg[1], ···, arg[#arg]. (Как все куски в Lua, скрипт компилируется, как функция с переменным числом аргументов.)

В интерактивном режиме, Lua многократно выдает приглащение и ждет ввода строки. После ввода строки, Lua сначала пробует интерпретировать строку как выражение. В случае успеха, печатает её значение. Иначе, интерпретирует строку как оператор. Если вы напишете незавершенное выражение, интерпретатор будет ждать его завершения, выдывая приглашение.

В случае незащищенных ошибок в скрипте, интерпретатор пишет ошибку в стандартный поток ошибок. Если объект ошибки это не строка, но имеет метаметод __tostring, интерпретатор вызывает этот метаметод для выдачи финального сообщения. Иначе, интерпретатор конвертирует объект ошибки в строку и добавляет к нему трассировку стека.

При нормальном завершении интерпретатор закрывает своё главное Lua состояние (см. lua_close). Скрипт может избежать этого шага, вызвавos.exit для завершения.

Чтобы использовать Lua, как интерпретатор скриптов в Unix системах, автономный интерпретатор пропускает первую линию куска, если он начинается с символа #. Следовательно, Lua скрипты могут быть сделаны исполняемыми программами, используя chmod +x и #! форму, например

     #!/usr/local/bin/lua

(Конечно, расположение Lua интерпретатора может быть другим. Если lua в вашей переменной PATH, то

     #!/usr/bin/env lua

более портабельное решение.)

8 – Несовместимости с предыдущей версией

Здесь приведен список несовместимостей, которые вы можете встретить при портировании программы с Lua 5.2 в Lua 5.3. Вы можете избежать некоторые несовместимости, скомпилировав Lua с соответствующими опциями (см. файл luaconf.h). Тем не менее, все эти опции совметимости будут убраны в будущем.

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

Аналогично, версии Lua всегда могут изменить внутреннее представление скомпилированных кусков; скомпилированные куски не совместимы между разными версиями Lua.

Стандартные пути в официальном дистрибутиве могут меняться между версиями.

8.1 – Изменения в языке

  • Главное различие между Lua 5.2 и Lua 5.3 это введение подтипа целых для чисел. Хотя это изменение не влияет на «нормальные» вычисления, некоторые вычисления (главным образом это некоторые типы переполнений) могут давать разные результаты.Вы можете убрать эти отличия, принудительно сделав числа вещественными (в Lua 5.2 все числа вещественные), в частности записывая константы с завершающим .0 или используя x = x + 0.0 для преобразования переменных. (Эта рекомендация только для быстрого исправления редких несовместимостей; это не общая рекомендация для хорошего программирования. Для хорошего программирования, используйте вещественные числа там, где нужны вещественные, и целые там, где нужны целые.)
  • Преобразование вещественных чисел в строку теперь добавляет суффикс .0 в результат, если он выглядит как целое. (Например, вещественное 2.0 будет напечатано как 2.0, не как 2.) Вы всегда должны использовать явный фомат, когда нуждаетесь в специфическом формате для чисел.(Формально, это не несовместимость, т.к. Lua не определяет, как числа форматируются в строки, но некоторые программы предполагают что это специфический формат.)
  • Генерационный режим работы сборщика мусора был удален. (Это была экспериментальная возможность в Lua 5.2.)

8.2 – Изменения в библиотеках

  • Библиотека bit32 стала нежелательной. Легко загрузить совместимую внешнюю библиотеку или лучше заменить её функции соответствующими битовыми операторами. (Помните, что bit32 оперирует с 32-битными целыми, а битовые операторы Lua 5.3 оперируют с целыми Lua, которые по умолчанию имеют 64 бита.)
  • Табличная библиотека теперь уважает метаметоды для установки и получения элементов.
  • Итератор ipairs теперь уважает метаметоды и его метаметод __ipairs стал нежелательным.
  • Имена опций в io.read больше не имеют начального символа ‘*‘. Для совместимости Lua продолжит принимать (и игнорировать) этот символ.
  • Следующие функции стали нежелательными в математической библиотеке: atan2, cosh, sinh, tanh, pow, frexp и ldexp. Вы можете заменитьmath.pow(x,y) на x^y; вы можете заменить math.atan2 на math.atan, который теперь принимает один или два параметра; вы можете заменить math.ldexp(x,exp) на x * 2.0^exp. Для других операций вы можете также использовать внешнюю библиотеку или реализовать их в Lua.
  • Искатель для C загрузчиков, используемый require, изменил способ обработки имен с версиями. Сейчас версия должна идти после имени модуля (как обычно в большинстве других инструментов). Для совместимости, этот искатель все еще пытается использовать старый формат, если не может найти функцию открытия соответствующую новому стилю. (Lua 5.2 уже работает таким способом, но это не документировано.)
  • Вызов collectgarbage("count") сейчас возвращает только один результат. (Вы можете вычислить второй результат из дробной части первого результата.)

8.3 – Изменения в API

  • Функции продолжения сейчас принимают как параметры то, что им нужно было получать через lua_getctx, так функция lua_getctx была удалена. Откорректируйте ваш код соответственно.
  • Функция lua_dump имеет дополнительный параметр strip. Используйте 0 для этого параметра, чтобы получить старое поведение.
  • Функции для вставки/получения беззнаковых целых (lua_pushunsigned, lua_tounsigned, lua_tounsignedx, luaL_checkunsigned,luaL_optunsigned) нежелательны. Используйте их знаковые эквиваленты с преобразованием типа.
  • Макросы для получения нестандартных целых типов (luaL_checkint, luaL_optint, luaL_checklong, luaL_optlong) нежелательны. Используйте их эквиваленты с lua_Integer с преобразованием типов (или, когда возможно, используйте lua_Integer в вашем коде).

9 – Полный синтаксис Lua

Здесь приведен полный синтаксис Lua в БНФ. Как обычно в расширенной БНФ, {A} означает 0 или более A, и [A] означает опциональное A. (Для приоритета операторов, см. §3.4.8; для описания терминалов Name, Numeral и LiteralString, см. §3.1.)

	chunk ::= block

	block ::= {stat} [retstat]

	stat ::=  ‘;’ | 
		 varlist ‘=’ explist | 
		 functioncall | 
		 label | 
		 break | 
		 goto Name | 
		 do block end | 
		 while exp do block end | 
		 repeat block until exp | 
		 if exp then block {elseif exp then block} [else block] end | 
		 for Name ‘=’ exp ‘,’ exp [‘,’ exp] do block end | 
		 for namelist in explist do block end | 
		 function funcname funcbody | 
		 local function Name funcbody | 
		 local namelist [‘=’ explist] 

	retstat ::= return [explist] [‘;’]

	label ::= ‘::’ Name ‘::’

	funcname ::= Name {‘.’ Name} [‘:’ Name]

	varlist ::= var {‘,’ var}

	var ::=  Name | prefixexp ‘[’ exp ‘]’ | prefixexp ‘.’ Name 

	namelist ::= Name {‘,’ Name}

	explist ::= exp {‘,’ exp}

	exp ::=  nil | false | true | Numeral | LiteralString | ‘...’ | functiondef | 
		 prefixexp | tableconstructor | exp binop exp | unop exp 

	prefixexp ::= var | functioncall | ‘(’ exp ‘)’

	functioncall ::=  prefixexp args | prefixexp ‘:’ Name args 

	args ::=  ‘(’ [explist] ‘)’ | tableconstructor | LiteralString 

	functiondef ::= function funcbody

	funcbody ::= ‘(’ [parlist] ‘)’ block end

	parlist ::= namelist [‘,’ ‘...’] | ‘...’

	tableconstructor ::= ‘{’ [fieldlist] ‘}’

	fieldlist ::= field {fieldsep field} [fieldsep]

	field ::= ‘[’ exp ‘]’ ‘=’ exp | Name ‘=’ exp | exp

	fieldsep ::= ‘,’ | ‘;’

	binop ::=  ‘+’ | ‘-’ | ‘*’ | ‘/’ | ‘//’ | ‘^’ | ‘%’ | 
		 ‘&’ | ‘~’ | ‘|’ | ‘>>’ | ‘<<’ | ‘..’ | 
		 ‘<’ | ‘<=’ | ‘>’ | ‘>=’ | ‘==’ | ‘~=’ | 
		 and | or

	unop ::= ‘-’ | not | ‘#’ | ‘~

Понравилась статья? Поделить с друзьями:
  • Orthomol i care инструкция по применению на русском
  • Гербион пастилки от кашля инструкция по применению взрослым
  • Ретро автомобиль из фанеры инструкция по сборке
  • Пертусин или пектусин от кашля инструкция сироп цена отзывы
  • Мануал тойота ипсум асм 26