Lua 5.3 Справочник по языку
от Роберто Иерусалимский, Луис Энрике де Фигейредо, Валдемар Селес
1 – Введение
Lua — это мощный, эффективный, легкий, встраиваемый скриптовый язык программирования. Он поддерживает процедурное программирование, объектно-ориентированное программирование, функциональное программирование, программирование, ориентированное на данные, и описание данных.
Lua объединяет простой процедурный синтаксис с мощными конструкциями описания данных, основанными на ассоциативных массивах и расширяемых семантиках. Lua динамически типизирован, выполняется путем интерпретации байткода с использованием регистровой виртуальной машины и имеет автоматическое управление памятью с инкрементной сборкой мусора, что делает его идеальным для конфигурирования, скриптинга и быстрого прототипирования.
Lua реализован как библиотека, написанная на чистом C, общем подмножестве Стандартного C и C++. Дистрибутив Lua включает программу-хост, называемую lua, которая использует библиотеку Lua для предоставления полного автономного интерпретатора Lua для интерактивного или пакетного использования. Lua предназначен для использования как мощного, легкого, встраиваемого скриптового языка для любой программы, которая его нуждается, так и как мощного, но легкого и эффективного автономного языка.
Как язык расширений, Lua не имеет понятия о программе «main»: он работает встроенным в клиент-хост, называемый программой-встраивающей программой или просто хостом. (Часто этот хост — это автономная lua программа.) Программа-хост может вызывать функции для выполнения фрагмента кода Lua, может записывать и читать переменные Lua, а также регистрировать функции C, которые будут вызываться кодом Lua. С помощью функций C Lua может быть дополнен для работы с широким спектром различных областей, создавая таким образом настраиваемые языки программирования, разделяющие синтаксический каркас.
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 делают условие ложным; любое другое значение делает его истинным. Тип number представляет целые числа и вещественные (с плавающей точкой) числа. Тип string представляет неизменяемые последовательности байтов. Lua полностью 8-битный: строки могут содержать любое 8-битное значение, включая встраиваемые нули ('\0'). Lua также независим от кодировки; он не делает никаких предположений о содержимом строки.
Тип number использует две внутренние представления, или два подтипа, один называется integer, а другой — float. Lua имеет явные правила относительно того, когда используется каждое представление, но также автоматически преобразует между ними по мере необходимости (см. §3.4.3). Поэтому программист может либо в основном игнорировать разницу между целыми числами и числами с плавающей точкой, либо полностью контролировать представление каждого числа. Стандартный Lua использует 64-битные целые числа и числа с двойной точностью (64-битные) с плавающей точкой, но вы также можете скомпилировать Lua так, чтобы он использовал 32-битные целые числа и/или числа с одинарной точностью (32-битные) с плавающей точкой. Вариант с 32 битами как для целых, так и для чисел с плавающей точкой особенно привлекателен для небольших машин и встраиваемых систем. (См. макрос LUA_32BITS в файле luaconf.h.)
Lua может вызывать (и управлять) функциями, написанными на Lua и функциями, написанными на C (см. §3.4.10). Оба представляются типом function.
Тип userdata предназначен для хранения произвольных данных C в переменных Lua. Значение userdata представляет собой блок сырой памяти. Существуют два вида userdata: полное userdata, которое является объектом с блоком памяти, управляемым Lua, и легкое userdata, которое просто является значением указателя C. Userdata не имеет предопределенных операций в Lua, за исключением присваивания и проверки тождества. Используя метатаблицы, программист может определить операции для значений полного userdata (см. §2.4). Значения userdata нельзя создавать или изменять в Lua, только через API C. Это гарантирует целостность данных, принадлежащих программе-хосту.
Тип thread представляет независимые потоки выполнения и используется для реализации сопроцедур (см. §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).
Как и индексы, значения полей таблиц могут быть любого типа. В частности, поскольку функции являются значениями первого класса, поля таблиц могут содержать функции. Таким образом, таблицы также могут содержать методы (см. §3.4.11).
Индексация таблиц соответствует определению «сырого» равенства в языке. Выражения a[i] и a[j] обозначают один и тот же элемент таблицы тогда и только тогда, когда i и j имеют сырое равенство (то есть равны без метаметодов). В частности, числа с плавающей точкой с целочисленными значениями равны соответствующим целым числам (например, 1.0 == 1). Для избежания неоднозначностей любое число с плавающей точкой с целочисленным значением, используемое в качестве ключа, преобразуется в соответствующее целое число. Например, если вы напишите a[2.0] = true, фактический ключ, вставленный в таблицу, будет целым числом 2. (С другой стороны, 2 и "2" — это разные значения Lua и, следовательно, обозначают разные записи в таблице.)
Таблицы, функции, потоки и (полные) значения userdata являются объектами: переменные на самом деле не содержат эти значения, а только ссылки на них. Присваивание, передача параметров и возвращение функций всегда манипулируют ссылками на такие значения; эти операции не подразумевают никакого копирования.
Функция библиотеки type возвращает строку, описывающую тип данного значения (см. §6.1).
2.2 – Среды и глобальная среда
Как будет обсуждаться в §3.2 и §3.3.3, любая ссылка на свободное имя (то есть имя, не связанное с каким-либо объявлением) var синтаксически преобразуется в _ENV.var. Кроме того, каждый фрагмент компилируется в области внешней локальной переменной, названной _ENV (см. §3.3.2), поэтому _ENV само по себе никогда не является свободным именем в фрагменте.
Несмотря на существование этой внешней переменной _ENV и преобразования свободных имен, _ENV — это совершенно обычное имя. В частности, вы можете определять новые переменные и параметры с этим именем. Каждая ссылка на свободное имя использует _ENV , видимое в этой точке программы, следуя обычным правилам видимости Lua (см. §3.5).
Любая таблица, используемая в качестве значения _ENV, называется средой.
Lua хранит выделенную среду, называемую глобальной средой. Это значение хранится в специальном индексе в C-регистре (см. §4.5). В Lua глобальная переменная _G инициализируется тем же самым значением. (_G никогда не используется во внутренней работе.)
Когда Lua загружает фрагмент, значение по умолчанию для его _ENV замыкания — это глобальная среда (см. load). Поэтому по умолчанию свободные имена в коде Lua ссылаются на записи в глобальной среде (и, следовательно, они также называются глобальными переменными). Кроме того, все стандартные библиотеки загружаются в глобальную среду, и некоторые функции там работают с этой средой. Вы можете использовать load (или loadfile), чтобы загрузить фрагмент с другой средой. (В C вам нужно загрузить фрагмент, а затем изменить значение его первого замыкания.)
2.3 – Обработка ошибок
Поскольку Lua — это встроенный язык расширений, все действия Lua начинаются с кода C в программе-хосте, вызывающем функцию из библиотеки Lua. (Когда вы используете Lua автономно, приложение lua является программой-хостом.) Всякий раз, когда возникает ошибка при компиляции или выполнении фрагмента Lua, управление возвращается хосту, который может принять соответствующие меры (например, вывести сообщение об ошибке).
Код Lua может явно сгенерировать ошибку, вызвав функцию error. Если вам нужно перехватить ошибки в Lua, вы можете использовать pcall или xpcall для вызова данной функции в защищенном режиме.
Всякий раз, когда возникает ошибка, распространяется объект ошибки (также называемый сообщением об ошибке) с информацией об ошибке. Сам Lua генерирует только ошибки, у которых объект ошибки — это строка, но программы могут генерировать ошибки с любым значением в качестве объекта ошибки. От программы Lua или ее хоста зависит обработка таких объектов ошибок.
END_OF_DOCUMENT_MARKER При использовании xpcall или lua_pcall, вы можете указать обработчик сообщений, который будет вызываться в случае возникновения ошибок. Эта функция вызывается с исходным объектом ошибки и возвращает новый объект ошибки. Она вызывается до того, как ошибка размотает стек, чтобы она могла собрать больше информации об ошибке, например, проверив стек и создав трассировку стека. Этот обработчик сообщений по-прежнему защищен защищенным вызовом; таким образом, ошибка внутри обработчика сообщений снова вызовет обработчик сообщений. Если эта петля продолжается слишком долго, Lua прерывает её и возвращает соответствующее сообщение. (Обработчик сообщений вызывается только для обычных ошибок во время выполнения. Он не вызывается для ошибок выделения памяти и не вызывается при запуске финализаторов.)
2.4 – Метатаблицы и метаметоды
Любое значение в Lua может иметь метатаблицу. Эта метатаблица — обычная таблица Lua, которая определяет поведение исходного значения при определённых специальных операциях. Вы можете изменить несколько аспектов поведения операций над значением, установив определённые поля в его метатаблице. Например, когда нечисловое значение является операндом сложения, Lua проверяет наличие функции в поле "__add" метатаблицы значения. Если она найдена, Lua вызывает эту функцию для выполнения сложения.
Ключом для каждого события в метатаблице является строка с именем события, префикс которой — два подчёркивания; соответствующие значения называются метаметодами. В предыдущем примере ключ — "__add", а метаметодом является функция, выполняющая сложение. Если не указано иное, метаметоды должны быть значениями функций.
Вы можете получить доступ к метатаблице любого значения с помощью функции getmetatable. Lua обращается к метаметодам в метатаблицах с использованием прямого доступа (см. rawget). Таким образом, чтобы получить метаметод для события ev в объекте o, Lua выполняет эквивалент следующего кода:
rawget(getmetatable(o) or {}, "__ev") Вы можете заменить метатаблицу таблиц с помощью функции setmetatable. Вы не можете изменить метатаблицу других типов из кода Lua (кроме использования библиотеки отладки (§6.10)); для этого следует использовать API на C.
У таблиц и полных пользовательских данных есть отдельные метатаблицы (хотя несколько таблиц и пользовательских данных могут использовать общие метатаблицы). Значения всех других типов используют одну единственную метатаблицу на тип; то есть существует одна единственная метатаблица для всех чисел, одна для всех строк и т.д. По умолчанию значение не имеет метатаблицы, но библиотека строк устанавливает метатаблицу для типа строка (см. §6.4).
Метатаблица контролирует поведение объекта в арифметических операциях, побитовых операциях, сравнениях порядка, конкатенации, операции длины, вызовах и индексировании. Метатаблица также может определить функцию, которая будет вызываться при сборе мусора для пользовательских данных или таблицы (§2.5).
Для унарных операторов (отрицание, длина и побитовое НЕ), метаметод вычисляется и вызывается с дополнительным вторым операндом, равным первому. Этот дополнительный операнд служит только для упрощения внутренней работы Lua (путем превращения этих операторов в бинарные операции) и может быть удален в будущих версиях. (Для большинства применений этот дополнительный операнд не имеет значения.)
Далее приведён подробный список событий, контролируемых метатаблицами. Каждая операция идентифицируется соответствующим ключом.
-
__add: операция сложения (+). Если какой-либо операнд для сложения не является числом (ни строкой, приводимой к числу), Lua попытается вызвать метаметод. Сначала Lua проверит первый операнд (даже если он валиден). Если этот операнд не определяет метаметод для__add, то 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: операция меньше или равно (<=) . В отличие от других операций, операция меньше или равно может использовать два разных события. Сначала Lua ищет метаметод__leв обоих операндах, как в операции меньше. Если такой метаметод не найден, то он попытается найти метаметод__lt, предполагая, чтоa <= bэквивалентноnot (b < a). Как и с другими операторами сравнения, результат всегда является булевым значением. (Это использование события__ltможет быть удалено в будущих версиях; оно также медленнее, чем реальный метаметод__le) -
__index: Операция индексирования доступаtable[key]. Это событие происходит, когдаtableне является таблицей или когдаkeyотсутствует вtable. Метаметод ищется вtable.Несмотря на название, метаметод для этого события может быть либо функцией, либо таблицей. Если это функция, она вызывается с
tableиkeyв качестве аргументов, и результат вызова (приведённый к одному значению) является результатом операции. Если это таблица, окончательный результат — результат индексирования этой таблицы сkey. (Это индексирование является обычным, а не прямым, и поэтому может вызывать другой метаметод.) -
__newindex: Операция присваивания по индексуtable[key] = value. Как и событие индекса, это событие происходит, когдаtableне является таблицей или когдаkeyотсутствует вtable. Метаметод ищется вtable.Как и с индексированием, метаметод для этого события может быть либо функцией, либо таблицей. Если это функция, она вызывается с
table,key, иvalueв качестве аргументов. Если это таблица, Lua выполняет присваивание по индексу в этой таблице с тем же ключом и значением. (Это присваивание является обычным, а не прямым, и поэтому может вызывать другой метаметод.)Всякий раз, когда есть метаметод
__newindex, Lua не выполняет примитивное присваивание. (Если необходимо, сам метаметод может вызватьrawsetдля выполнения присваивания.) -
__call: Операция вызоваfunc(args). Это событие происходит, когда Lua пытается вызвать значение, которое не является функцией (то естьfuncне является функцией). Метаметод ищется вfunc. Если он присутствует, метаметод вызывается сfuncв качестве первого аргумента, за которым следуют аргументы исходного вызова (args). Все результаты вызова — результат операции. (Это единственный метаметод, который допускает несколько результатов.)
Хорошей практикой является добавление всех необходимых метаметодов в таблицу перед её установкой в качестве метатаблицы какого-либо объекта. В частности, метаметод __gc работает только в том случае, если этот порядок соблюдается (см. §2.5.1).
Поскольку метатаблицы являются обычными таблицами, они могут содержать произвольные поля, а не только имена событий, определённые выше. Некоторые функции в стандартной библиотеке (например, tostring) используют другие поля в метатаблицах для собственных целей.
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). Эти метаметоды также называются финализаторами. Финализаторы позволяют вам координировать сборку мусора Lua с управлением внешними ресурсами (такими как закрытие файлов, сетевых или баз данных подключений или освобождение вашей собственной памяти).
Для того, чтобы объект (таблица или пользовательские данные) был финализирован при сборке, необходимо пометить его для финализации. Вы помечаете объект для финализации, когда вы устанавливаете его метатаблицу, и в метатаблице есть поле, индексированное строкой "__gc". Обратите внимание, что если вы установили метатаблицу без поля __gc, а затем создали это поле в метатаблице, объект не будет помечен для финализации.
Когда помеченный объект становится мусором, он не собирается сразу же сборщиком мусора. Вместо этого Lua помещает его в список. После завершения сборки Lua проходит по этому списку. Для каждого объекта в списке он проверяет метаметод объекта __gc: если это функция, Lua вызывает её с объектом в качестве единственного аргумента; если метаметод не является функцией, Lua просто игнорирует его.
В конце каждого цикла сборки мусора финализаторы для объектов вызываются в обратном порядке помечания объектов для финализации, среди тех, что были собраны в данном цикле; то есть, первый финализатор, который будет вызван, — это финализатор, связанный с объектом, помеченным последним в программе. Выполнение каждого финализатора может происходить в любой момент во время выполнения обычного кода.
Поскольку объект, который собирается, должен по-прежнему использоваться финализатором, этот объект (и другие объекты, доступные только через него) должен быть восстановлен Lua. Обычно это восстановление временное, и память объекта освобождается в следующем цикле сборки мусора. Однако, если финализатор сохраняет объект в каком-то глобальном месте (например, в глобальной переменной), то восстановление является постоянным. Более того, если финализатор помечает объект для финализации повторно, его финализатор будет вызван снова в следующем цикле, где объект недоступен. В любом случае, память объекта освобождается только в цикле GC, где объект недоступен и не помечен для финализации.
При закрытии состояния (см. lua_close), Lua вызывает финализаторы всех объектов, помеченных для финализации, в обратном порядке, в котором они были помечены. Если какой-либо финализатор помечает объекты для сбора во время этой фазы, эти метки не имеют эффекта.
2.5.2 – Слабые таблицы
Слабая таблица — это таблица, элементы которой являются слабыми ссылками. Слабая ссылка игнорируется сборщиком мусора. Другими словами, если единственные ссылки на объект — это слабые ссылки, то сборщик мусора соберет этот объект.
Слабая таблица может иметь слабые ключи, слабые значения или оба. Таблица со слабыми значениями позволяет собирать её значения, но предотвращает сборку ключей. Таблица с обоими слабыми ключами и слабыми значениями позволяет собирать и ключи, и значения. В любом случае, если либо ключ, либо значение собираются, вся пара удаляется из таблицы. Слабость таблицы контролируется полем __mode её метатаблицы. Если поле __mode — это строка, содержащая символ 'k', ключи в таблице являются слабыми. Если __mode содержит 'v', значения в таблице являются слабыми.
Таблица со слабыми ключами и сильными значениями также называется эфемеронной таблицей. В эфемеронной таблице значение считается достижимым только в том случае, если его ключ является достижимым. В частности, если единственная ссылка на ключ происходит через его значение, пара удаляется.
Любое изменение слабости таблицы может вступить в силу только в следующем цикле сбора. В частности, если вы измените слабость на более сильный режим, 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 плюс объект ошибки.
Корутина уступает управление, вызывая 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. Другими словами, этот раздел описывает, какие токены являются допустимыми, как они могут быть объединены и что означают их комбинации.
Конструкции языка будут объяснены с использованием обычного расширенного обозначения БНФ, в котором {a} означает 0 или более a, а [a] — необязательное a. Нетерминалы показаны как нетерминал, ключевые слова показаны как ключевое слово, а другие терминальные символы — как «=». Полный синтаксис Lua можно найти в §9 в конце этого руководства.
3.1 – Лексические соглашения
Lua — это язык с свободной формой. Он игнорирует пробелы (включая новые строки) и комментарии между лексическими элементами (токенами), за исключением случаев, когда они служат разделителями между именами и ключевыми словами.
Имена (также называемые идентификаторами) в 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).
Следующие строки обозначают другие токены:
+ - * / % ^ #
& ~ | << >> //
== ~= <= >= < > =
( ) { } [ ] ::
; : , . .. ... Короткая строковая литерал может быть ограничена одинарными или двойными кавычками и может содержать следующие escape-последовательности в стиле C: '\a' (звонок), '\b' (ввод с пробелом назад), '\f' (форма подачи), '\n' (новая строка), '\r' (возврат каретки), '\t' (горизонтальная табуляция), '\v' (вертикальная табуляция), '\\' (обратный слэш), '\"' (двойная кавычка) и '\'' (одинарная кавычка). Обратный слэш, за которым следует перевод строки, приводит к новой строке в строке. Escape-последовательность '\z' пропускает следующий блок символов пробела, включая переводы строк; это особенно полезно для разбиения и отступа длинной строковой литерал на несколько строк без добавления переходов на новую строку и пробелов в содержимое строки. Короткая строковая литерал не может содержать неэкранированных переходов на новую строку или экранирования, не образующие допустимую escape-последовательность.
Любой байт в короткой строковой литерал можно указать по его числовому значению (включая вставленные нули). Это можно сделать с помощью escape-последовательности \xXX, где XX — последовательность ровно двух шестнадцатеричных цифр, или с помощью escape-последовательности \ddd, где ddd — последовательность не более трёх десятичных цифр. (Обратите внимание, что если десятичная escape-последовательность должна следовать за цифрой, она должна быть выражена ровно тремя цифрами.)
UTF-8 кодирование Unicode символа можно вставить в строковую литерал с помощью escape-последовательности \u{XXX} (обратите внимание на обязательные окружающие скобки), где XXX — последовательность одной или более шестнадцатеричных цифр, представляющих кодовую точку символа.
Строковые литералы также могут быть определены с использованием длинного формата, заключённого в длинные скобки. Мы определяем открывающую длинную скобку уровня n как открывающую квадратную скобку, за которой следуют n знаков равенства, за которыми следует ещё одна открывающая квадратная скобка. Итак, открывающая длинная скобка уровня 0 записывается как [[, открывающая длинная скобка уровня 1 записывается как [=[, и так далее. Закрывающая длинная скобка определяется аналогично; например, закрывающая длинная скобка уровня 4 записывается как ]====]. Длинная литерал начинается с открывающей длинной скобки любого уровня и заканчивается первой закрывающей длинной скобкой того же уровня. Она может содержать любой текст, кроме закрывающей скобки того же уровня. Литералы в этом скобочном формате могут занимать несколько строк, не интерпретируют никакие escape-последовательности и игнорируют длинные скобки любого другого уровня. Любой тип последовательности конца строки (возврат каретки, новая строка, возврат каретки, за которым следует новая строка или новая строка, за которой следует возврат каретки) преобразуется в простую новую строку.
Для удобства, когда открывающая длинная скобка непосредственно следует за новой строкой, новая строка не включается в строку. Например, в системе, использующей ASCII (в которой 'a' закодирован как 97, новая строка закодирована как 10, а '1' закодирован как 49), пять строковых литералов ниже обозначают одну и ту же строку:
a = 'alo\n123"' a = "alo\n123\"" a = '\97lo\10\04923"' a = [[alo 123"]] a = [==[ alo 123"]==]
Любой байт в строковой литерале, на который не влияют предыдущие правила, представляет сам себя. Однако Lua открывает файлы для парсинга в текстовом режиме, и функции системных файлов могут иметь проблемы с некоторыми управляющими символами. Поэтому безопаснее представлять нетекстовые данные как строковую литерал с явными escape-последовательностями для нетекстовых символов.
Числовая константа (или числовое значение) может быть записана с необязательной дробной частью и необязательным десятичным показателем, помеченным буквой '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).
Перед первым присвоением значения переменной её значение равно nil.
Квадратные скобки используются для индексирования таблицы:
var ::= prefixexp ‘[’ exp ‘]’
Значение доступа к полям таблицы может быть изменено с помощью метатаблиц (см. §2.4).
Синтаксис 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 ::= block
Lua обрабатывает блок кода как тело анонимной функции с переменным числом аргументов (см. §3.4.11). Как таковая, блоки кода могут определять локальные переменные, получать аргументы и возвращать значения. Кроме того, такая анонимная функция компилируется в области видимости внешней локальной переменной, называемой _ENV (см. §2.2). Результирующая функция всегда имеет _ENV в качестве единственного значения, даже если она не использует эту переменную.
Блок кода может храниться в файле или в строке внутри программы-хоста. Для выполнения блока кода Lua сначала загружает его, предварительно компилируя код блока в инструкции для виртуальной машины, а затем Lua выполняет скомпилированный код с интерпретатором для виртуальной машины.
Блоки кода также могут быть предварительно скомпилированы в двоичном формате; см. программу 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.
Присвоение глобальному имени 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).
Выражение условия управляющей структуры может возвращать любое значение. И false, и nil считаются ложными. Все значения, отличные от nil и false, считаются истинными (в частности, число 0 и пустая строка также являются истинными).
В цикле repeat–until внутренний блок не заканчивается на ключевом слове 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.
- Вы можете использовать break и goto для выхода из цикла for.
- Переменная цикла
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являются невидимыми переменными. Имена здесь указаны только для наглядности. - Вы можете использовать break для выхода из цикла for.
- Переменные цикла
var_iлокальны для цикла; вы не можете использовать их значения после завершения оператора for. Если вам нужны эти значения, присвойте их другим переменным перед прерыванием или выходом из цикла.
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. Выражения Vararg, обозначаемые тремя точками ('...'), могут использоваться только непосредственно внутри функции vararg; они описаны в §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).
Как вызовы функций, так и выражения vararg могут возвращать несколько значений. Если вызов функции используется как оператор (см. §3.3.6), список его возвращаемых значений корректируется до нуля элементов, таким образом, все возвращаемые значения отбрасываются. Если выражение используется в качестве последнего (или единственного) элемента списка выражений, корректировка не выполняется (за исключением случаев, когда выражение заключено в скобки). Во всех остальных случаях Lua корректирует список результатов до одного элемента, либо отбрасывая все значения, кроме первого, либо добавляя единственный nil, если значений нет.
Вот несколько примеров:
f() -- adjusted to 0 results
g(f(), x) -- f() is adjusted to 1 result
g(x, f()) -- g gets x plus all results from f()
a,b,c = f(), x -- f() is adjusted to 1 result (c gets nil)
a,b = ... -- a gets the first vararg argument, b gets
-- the second (both a and b can get nil if there
-- is no corresponding vararg argument)
a,b,c = x, f() -- f() is adjusted to 2 results
a,b,c = f() -- f() is adjusted to 3 results
return f() -- returns all results from f()
return ... -- returns all received vararg arguments
return x,y,f() -- returns x, y, and all results from f()
{f()} -- creates a list with all results from f()
{...} -- creates a list with all vararg arguments
{f(), nil} -- f() is adjusted to 1 result Любое выражение, заключенное в скобки, всегда возвращает только одно значение. Таким образом, (f(x,y,z)) всегда является единственным значением, даже если f возвращает несколько значений. (Значение (f(x,y,z)) – это первое значение, возвращенное f, или nil, если f не возвращает никаких значений.)
3.4.1 – Арифметические операторы
Lua поддерживает следующие арифметические операторы:
-
+: сложение -
-: вычитание -
*: умножение -
/: деление с плавающей точкой -
//: целочисленное деление -
%: модуль -
^: возведение в степень -
-: унарный минус
За исключением возведения в степень и деления с плавающей точкой, арифметические операторы работают следующим образом: если оба операнда – целые числа, операция выполняется над целыми числами, и результат – целое число. В противном случае, если оба операнда – числа или строки, которые могут быть преобразованы в числа (см. §3.4.3), они преобразуются в числа с плавающей точкой, операция выполняется в соответствии с обычными правилами арифметики с плавающей точкой (обычно стандарт IEEE 754), и результатом является число с плавающей точкой.
Возведение в степень и деление с плавающей точкой (/) всегда преобразуют свои операнды в числа с плавающей точкой, и результат всегда является числом с плавающей точкой. Возведение в степень использует функцию ISO C pow, так что она работает и для нецелых показателей степени.
Целочисленное деление (//) – это деление, которое округляет частное до минус бесконечности, то есть до целой части результата.
Модуль определяется как остаток от деления, который округляет частное до минус бесконечности (целочисленное деление).
В случае переполнения в целочисленной арифметике все операции зацикливаются в соответствии с обычными правилами арифметики с дополнительным кодом. (Другими словами, они возвращают единственное представимое целое число, равное по модулю 264 математическому результату.)
3.4.2 – Побитовые операторы
Lua поддерживает следующие побитовые операторы:
-
&: побитовое И -
|: побитовое ИЛИ -
~: побитовое исключающее ИЛИ -
>>: сдвиг вправо -
<<: сдвиг влево -
~: унарный побитовый НЕ
Все побитовые операции преобразуют свои операнды в целые числа (см. §3.4.3), работают со всеми битами этих целых чисел и дают в результате целое число.
При сдвиге вправо и влево пустые биты заполняются нулями. Отрицательные сдвиги сдвигаются в другую сторону; сдвиги с абсолютными значениями, равными или большими числу битов в целочисленном представлении, приводят к нулю (так как все биты выходят за пределы).
3.4.3 – Преобразования типов
Lua обеспечивает некоторые автоматические преобразования между некоторыми типами и представлениями во время выполнения. Побитовые операторы всегда преобразуют операнды с плавающей точкой в целые числа. Возведение в степень и деление с плавающей точкой всегда преобразуют целые операнды в числа с плавающей точкой. Все остальные арифметические операции, примененные к смешанным числам (целым и с плавающей точкой), преобразуют целые операнды в числа с плавающей точкой; это называется обычным правилом. API C также преобразует целые числа в числа с плавающей точкой и числа с плавающей точкой в целые числа по мере необходимости. Кроме того, конкатенация строк принимает в качестве аргументов числа помимо строк.
Lua также преобразует строки в числа, когда ожидается число.
При преобразовании целого числа в число с плавающей точкой, если значение целого числа имеет точное представление в виде числа с плавающей точкой, то это и будет результатом. В противном случае преобразование выбирает ближайшее более высокое или ближайшее меньшее представимое значение. Такое преобразование никогда не терпит неудачи.
Преобразование числа с плавающей точкой в целое проверяет, имеет ли число с плавающей точкой точное представление в виде целого числа (то есть, число с плавающей точкой имеет целую часть и находится в диапазоне представления целых чисел). Если да, то это представление и есть результат. В противном случае преобразование терпит неудачу.
Преобразование строк в числа выполняется следующим образом: сначала строка преобразуется в целое или число с плавающей точкой в соответствии с ее синтаксисом и правилами лексического анализа Lua. (Строка может иметь также ведущие и хвостовые пробелы и знак.) Затем полученное число (с плавающей точкой или целое) преобразуется в требуемый тип (с плавающей точкой или целое) в зависимости от контекста (например, операции, которая потребовала преобразования).
Все преобразования из строк в числа принимают как точку, так и текущий локальный символ разделителя как разделитель разрядов. (Однако лексический анализатор Lua принимает только точку.)
Преобразование чисел в строки использует не указанный человекочитаемый формат. Для полного управления тем, как числа преобразуются в строки, используйте функцию format из библиотеки строк (см. string.format).
3.4.4 – Операторы сравнения
Lua поддерживает следующие операторы сравнения:
-
==: равенство -
~=: неравенство -
<: меньше -
>: больше -
<=: меньше или равно -
>=: больше или равно
Эти операторы всегда возвращают false или true.
Равенство (==) сначала сравнивает тип своих операндов. Если типы разные, результат – false. В противном случае сравниваются значения операндов. Строки сравниваются очевидным образом. Числа равны, если они обозначают одно и то же математическое значение.
Таблицы, userdata и потоки сравниваются по ссылке: два объекта считаются равными только если они являются одним и тем же объектом. Каждый раз при создании нового объекта (таблицы, userdata или потока) этот новый объект отличается от любого ранее существовавшего объекта. Замкнутая функция всегда равна сама себе. Замкнутые функции с любым обнаружимым различием (различное поведение, различное определение) всегда различаются. Замкнутые функции, созданные в разное время, но без обнаруживаемых различий, могут быть классифицированы как равные или не равные (в зависимости от внутренних деталей кэширования).
Вы можете изменить способ сравнения Lua таблиц и пользовательских данных, используя метаметод "eq" (см. §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 как ложные, а всё остальное — как истинное.
Оператор отрицания 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 – Оператор длины
Оператор длины обозначается префиксным унарным оператором #.
Длина строки — это число её байтов (то есть обычное значение длины строки, когда каждый символ имеет один байт).
Оператор длины, применённый к таблице, возвращает границу в этой таблице. Граница в таблице t — это любое натуральное число, которое удовлетворяет следующему условию:
(border == 0 or t[border] ~= nil) and t[border + 1] == nil
Другими словами, граница — это любой (натуральный) индекс в таблице, где за ненулевым значением следует значение nil (или ноль, если индекс 1 равен nil).
Таблица с ровно одной границей называется последовательностью. Например, таблица {10, 20, 30, 40, 50} — последовательность, так как у неё только одна граница (5). Таблица {10, 20, 30, nil, 50} имеет две границы (3 и 5), поэтому она не является последовательностью. Таблица {nil, 20, 30, nil, nil, 60, nil} имеет три границы (0, 3 и 6), поэтому она тоже не является последовательностью. Таблица {} — последовательность с границей 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; "x", "y"; x = 1, f(x), [30] = 23; 45 }
эквивалентно
do
local t = {}
t[f(1)] = g
t[1] = "x" -- 1st exp
t[2] = "y" -- 2nd exp
t.x = 1 -- t["x"] = 1
t[3] = f(x) -- 3rd exp
t[30] = 23
t[4] = 45 -- 4th exp
a = t
end Порядок присваиваний в конструкторе не определён. (Этот порядок был бы релевантен только при наличии повторяющихся ключей.)
Если последнее поле в списке имеет вид exp, а выражение — вызов функции или выражение vararg, то все значения, возвращаемые этим выражением, вводятся в список последовательно (см. §3.4.10).
Список полей может иметь необязательный заключительный разделитель в качестве удобства для сгенерированного кода.
3.4.10 – Вызовы функций
Вызов функции в Lua имеет следующий синтаксис:
functioncall ::= prefixexp args
При вызове функции сначала вычисляются prefixexp и args. Если значение prefixexp имеет тип функция, то эта функция вызывается с заданными аргументами. В противном случае вызывается метаметод "call" prefixexp, принимающий в качестве первого аргумента значение 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 называется хвостовым вызовом. Lua реализует правильные хвостовые вызовы (или правильную рекурсию хвоста): при хвостовом вызове вызываемая функция использует запись стека вызывающей функции. Поэтому нет ограничений на количество вложенных хвостовых вызовов, которые может выполнить программа. Однако хвостовой вызов стирает любую информацию отладки о вызывающей функции. Обратите внимание, что хвостовой вызов происходит только с определённым синтаксисом, где return имеет один единственный вызов функции в качестве аргумента; этот синтаксис делает так, что вызывающая функция возвращает точно то, что возвращает вызываемая функция. Таким образом, ни один из следующих примеров не является хвостовым вызовом:
return (f(x)) -- results adjusted to 1 return 2 * f(x) return x, f(x) -- additional results f(x); return -- results discarded return x or f(x) -- results adjusted to 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.)
Определение функции — это исполняемое выражение, значение которого имеет тип функция. Когда Lua предварительно компилирует блок кода, все его тела функций также предварительно компилируются. Затем, всякий раз, когда Lua выполняет определение функции, функция инициализируется (или закрывается). Эта функция экземпляра (или замыкание) — это конечное значение выражения.
Параметры действуют как локальные переменные, которые инициализируются значениями аргументов:
parlist ::= namelist [‘,’ ‘...’] | ‘...’
Когда функция вызывается, список аргументов корректируется под длину списка параметров, если только функция не является функцией с переменным числом аргументов, что обозначается тремя точками ('...') в конце списка параметров. Функция с переменным числом аргументов не корректирует свой список аргументов; вместо этого она собирает все дополнительные аргументы и предоставляет их функции через выражение с переменным числом аргументов, которое также записывается как три точки. Значение этого выражения — список всех фактических дополнительных аргументов, аналогично функции с несколькими результатами. Если выражение с переменным числом аргументов используется внутри другого выражения или посредине списка выражений, то его список возвращаемых значений корректируется до одного элемента. Если выражение используется в качестве последнего элемента списка выражений, то корректировка не производится (если это последнее выражение не заключено в скобки).
В качестве примера рассмотрим следующие определения:
function f(a, b) end function g(a, b, ...) end function r() return 1,2,3 end
Тогда у нас есть следующее соответствие между аргументами, параметрами и выражением с переменным числом аргументов:
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, ... --> (nothing) g(3, 4) a=3, b=4, ... --> (nothing) 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 -- global variable
do -- new block
local x = x -- new 'x', with value 10
print(x) --> 10
x = x+1
do -- another block
local x = x+1 -- another 'x'
print(x) --> 12
end
print(x) --> 11
end
print(x) --> 10 (the global one) Обратите внимание, что в объявлении, таком как local x = x, новое x ещё не находится в области видимости, поэтому второе x относится к переменной вне области видимости.
Из-за правил лексического охвата локальные переменные могут свободно использоваться функциями, определенными внутри их области видимости. Локальная переменная, используемая внутренней функцией, называется свободной переменной или внешней локальной переменной внутри внутренней функции.
Обратите внимание, что каждое выполнение оператора local определяет новые локальные переменные. Рассмотрим следующий пример:
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 и из C. Каждый элемент этого стека представляет собой значение Lua (nil, число, строка и т. д.). Функции API могут получить доступ к этому стеку через параметр состояния Lua, который они получают.
Всякий раз, когда Lua вызывает C, вызываемая функция получает новый стек, который независим от предыдущих стеков и стеков функций C, которые все еще активны. Этот стек изначально содержит любые аргументы функции C, и именно в нем функция C может хранить временные значения Lua и должна помещать свои результаты в стек, чтобы они были возвращены вызывающей стороне (см. 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) и к замыканиям (upvalues) функции C (см. §4.4).
Функции, которым не нужна конкретная изменяемая позиция, а только значение (например, функции запроса), могут быть вызваны с допустимыми индексами. Допустимый индекс может быть любым валидным индексом, но также может быть любым положительным индексом после вершины стека в выделенном для стека пространстве, то есть индексы до размера стека. (Обратите внимание, что 0 никогда не является допустимым индексом.) За исключением случаев, оговоренных отдельно, функции API работают с допустимыми индексами.
Допустимые индексы служат для избежания дополнительных проверок вершины стека при запросе стека. Например, функция C может запросить свой третий аргумент, не проверяя предварительно, есть ли третий аргумент, то есть без необходимости проверки, является ли 3 валидным индексом.
Для функций, которые могут быть вызваны с допустимыми индексами, любой невалидный индекс обрабатывается так, как будто он содержит значение виртуального типа LUA_TNONE, который ведет себя как значение nil.
4.4 – C-замыкания
Когда создается функция C, можно ассоциировать с ней некоторые значения, создавая тем самым C-замыкание (см. lua_pushcclosure); эти значения называются замыканиями (upvalues) и доступны функции всякий раз, когда она вызывается.
Всякий раз, когда вызывается функция C, ее замыкания (upvalues) находятся в определенных псевдо-индексах. Эти псевдо-индексы генерируются макросом lua_upvalueindex. Первое замыкание (upvalue), ассоциированное с функцией, находится по индексу lua_upvalueindex(1), и так далее. Любой доступ к lua_upvalueindex(n), где n больше числа замыканий (upvalues) текущей функции (но не больше 256, что равно одному плюс максимальное количество замыканий в замыкании), приводит к допустимому, но невалидному индексу.
4.5 – Регистр
Lua предоставляет регистр, предопределённую таблицу, которую любой код C может использовать для хранения любых значений Lua, которые ему нужно хранить. Таблица реестра всегда находится в псевдо-индексе LUA_REGISTRYINDEX. Любая библиотека C может хранить данные в этой таблице, но она должна позаботиться о том, чтобы выбрать ключи, отличные от используемых другими библиотеками, чтобы избежать коллизий. Как правило, вы должны использовать в качестве ключа строку, содержащую имя вашей библиотеки, или легкий пользовательский тип данных с адресом объекта 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 сталкивается с ошибкой (например, с ошибкой выделения памяти или ошибкой типа), она выбрасывает ошибку; то есть, делает длинный переход. Защищённая среда использует setjmp для установки точки восстановления; любая ошибка переходит к самой последней активной точке восстановления.
Внутри функции C вы можете выбросить ошибку, вызвав lua_error.
Большинство функций API могут выбросить ошибку, например, из-за ошибки выделения памяти. Документация по каждой функции указывает, может ли она выбросить ошибки.
Если ошибка произойдёт вне любой защищённой среды, Lua вызовет функцию panic (см. lua_atpanic), а затем вызовет abort, тем самым завершив приложение-хост. Ваша функция panic может избежать этого завершения, если никогда не вернётся (например, сделав длинный переход в свою собственную точку восстановления вне Lua).
Функция panic, как следует из названия, является механизмом последней надежды. Программы должны избегать её использования. Как общее правило, когда функция C вызывается Lua с состоянием Lua, она может делать всё, что угодно с этим состоянием Lua, поскольку оно должно быть уже защищено. Однако, когда код C работает с другими состояниями Lua (например, аргументом Lua в функции, состоянием Lua, хранящимся в регистре, или результатом lua_newthread), он должен использовать их только в вызовах API, которые не могут выбросить ошибки.
Функция panic выполняется так, как будто она является обработчиком сообщений (см. §2.3); в частности, объект ошибки находится в верхней части стека. Однако нет гарантии относительно пространства стека. Чтобы поместить что-либо в стек, функция panic должна сначала проверить доступное пространство (см. §4.2).
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, которую мы назовем исходной функцией. Затем эта исходная функция вызывает одну из этих трёх функций C 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, что он должен вызвать k в случае прерывания выполнения Lua-кода, выполняемого lua_pcall (ошибки или приостановки), поэтому мы переписываем код, заменяя 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_pcallk (и lua_callk) также вернутся нормально. (Конечно, вместо вызова функции продолжения в этом случае вы можете выполнить эквивалентную работу непосредственно внутри исходной функции.)
Помимо состояния Lua, функция продолжения имеет ещё два параметра: конечный статус вызова плюс значение контекста (ctx) , которое было передано изначально в lua_pcallk. (Lua не использует это значение контекста; оно только передаёт его из исходной функции в функцию продолжения.) Для lua_pcallk статус совпадает со значением, которое вернул бы lua_pcallk, за исключением того, что он равен LUA_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.8 – Функции и типы[-o, +p, x]
Здесь мы перечисляем все функции и типы из C API в алфавитном порядке. Каждая функция имеет индикатор такого вида:
Первый элемент, o, — количество элементов, извлекаемых функцией из стека. Второй элемент, p, — количество элементов, которые функция помещает в стек. (Любая функция всегда помещает свои результаты после извлечения аргументов.) Элемент вида x|y означает, что функция может поместить (или извлечь) x или y элементов в зависимости от ситуации; знак вопроса '?' означает, что количество извлекаемых/помещаемых элементов невозможно определить только по её аргументам (например, они могут зависеть от содержимого стека). Третий элемент, x, указывает, может ли функция вызвать ошибки: '-' — функция никогда не вызывает ошибок; 'm' — функция может вызвать ошибки недостатка памяти и ошибки при выполнении метаметода __gc; 'e' — функция может вызвать любые ошибки (она может выполнять произвольный Lua-код, как напрямую, так и через метаметоды); '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 кодирует тип объекта, который Lua выделяет. osize может принимать значения LUA_TSTRING, LUA_TTABLE, LUA_TFUNCTION, LUA_TUSERDATA или LUA_TTHREAD, когда (и только когда) Lua создаёт новый объект этого типа. Если osize имеет другое значение, Lua выделяет память для чего-то другого.
Lua предполагает следующее поведение от функции-аллокатора:
Когда nsize равно нулю, аллокатор должен вести себя как free и возвращать NULL.
Когда nsize не равно нулю, аллокатор должен вести себя как 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);
Выполняет арифметическую или поразрядную операцию над двумя значениями (или одним в случае унарных операций) на вершине стека, при этом значение на вершине стека является вторым операндом, удаляет эти значения и помещает результат операции. Функция следует семантике соответствующего 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.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"); /* function to be called */ lua_pushliteral(L, "how"); /* 1st argument */ lua_getglobal(L, "t"); /* table to be indexed */ lua_getfield(L, -1, "x"); /* push result of t.x (2nd arg) */ lua_remove(L, -2); /* remove 't' from the stack */ lua_pushinteger(L, 14); /* 3rd argument */ lua_call(L, 3, 1); /* call 'f' with 3 arguments and 1 result */ lua_setglobal(L, "a"); /* set global '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); /* number of arguments */
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); /* first result */
lua_pushnumber(L, sum); /* second result */
return 2; /* number of results */
}
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 истинно, двоичное представление может не включать всю отладочную информацию о функции, чтобы сэкономить место.
Возвращаемое значение — код ошибки, возвращённый последним вызовом записи; 0 означает отсутствие ошибок.
Эта функция не извлекает функцию Lua из стека.
lua_error[-1, +0, v]
int lua_error (lua_State *L);
Генерирует ошибку Lua, используя значение в верхней части стека в качестве объекта ошибки. Эта функция выполняет длинный прыжок и поэтому никогда не возвращается (см. luaL_error).
lua_gc[-0, +0, m]
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);
Возвращает функцию выделения памяти заданного состояния. Если 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).
Возвращает тип помещенного значения.
lua_getextraspace[-0, +0, –]
void *lua_getextraspace (lua_State *L);
Возвращает указатель на сырое область памяти, связанную с данным состоянием Lua. Приложение может использовать эту область для любых целей; 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_getuservalue[-0, +1, –]
int lua_getuservalue (lua_State *L, int index);
Помещает в стек значение Lua, связанное с полным пользовательским данными на данном индексе.
Возвращает тип помещенного значения.
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, если значение на данном индексе является булевым, и 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, если значение в заданном индексе является 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, если значение в заданном индексе является числом или строкой, преобразуемой в число, и 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.7).
lua_len[-0, +1, e]
void lua_len (lua_State *L, int index);
Возвращает длину значения в заданном индексе. Она эквивалентна оператору '#' в Lua (см. §3.4.7) и может вызвать метаметод для события "длина" (см. §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 — это неявное значение, передаваемое функции чтения.
Аргумент chunkname присваивает имя фрагменту, которое используется для сообщений об ошибках и в отладочной информации (см. §4.9).
lua_load автоматически определяет, является ли фрагмент текстовым или двоичным и загружает его соответствующим образом (см. программу luac). Строка mode работает так же, как в функции load, с дополнением, что значение NULL эквивалентно строке "bt".
lua_load использует стек внутри, поэтому функция чтения должна всегда оставлять стек неизменным при возврате.
Если результирующая функция имеет замыкания, её первое замыкание устанавливается на значение глобальной среды, хранящейся в индексе LUA_RIDX_GLOBALS в реестре (см. §4.5). При загрузке основных фрагментов это замыкание будет переменной _ENV (см. §2.2). Другие замыкания инициализируются значением 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_newuserdata[-0, +1, m]
void *lua_newuserdata (lua_State *L, size_t size);
Эта функция выделяет новый блок памяти заданного размера, помещает в стек новый полный пользовательский тип данных с адресом блока и возвращает этот адрес. Прикладная программа может свободно использовать эту память.
lua_next[-1, +(2|0), e]
int lua_next (lua_State *L, int index);
Извлекает ключ со стека и помещает пару ключ–значение из таблицы по заданному индексу (следующую пару после данного ключа). Если в таблице больше нет элементов, то lua_next возвращает 0 (и ничего не помещает).
Типичное обход выглядит так:
/* table is in the stack at index 't' */
lua_pushnil(L); /* first key */
while (lua_next(L, t) != 0) {
/* uses 'key' (at index -2) and 'value' (at index -1) */
printf("%s - %s\n",
lua_typename(L, lua_type(L, -2)),
lua_typename(L, lua_type(L, -1)));
/* removes 'value'; keeps 'key' for next iteration */
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 не вызывает обработчик сообщений (так как этот вид ошибок, как правило, не связан с вызываемой функцией).
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);
Помещает булево значение со значением b в стек.
lua_pushcclosure[-n, +1, m]
void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n);
Помещает новую C замыкание в стек.
При создании функции C, можно связать с ней некоторые значения, создавая тем самым замыкание C (см. §4.4); эти значения затем доступны функции при её вызове. Чтобы связать значения с функцией C, сначала эти значения необходимо поместить в стек (если значений несколько, сначала помещается первое значение). Затем вызывается lua_pushcclosure для создания и помещения функции C в стек, с аргументом n, указывающим количество значений, которые будут связаны с функцией. lua_pushcclosure также извлекает эти значения из стека.
Максимальное значение для n составляет 255.
Когда n равно нулю, эта функция создаёт лёгкую 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).
В отличие от других функций push, эта функция проверяет необходимый объём стека, включая слот для её результата.
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. Лёгкие пользовательские данные представляют указатель, void*. Это значение (как число): вы его не создаёте, оно не имеет индивидуального метатаблицы и не собирается (поскольку никогда не создавалось). Лёгкие пользовательские данные равны "любым" лёгким пользовательским данным с тем же адресом C.
lua_pushliteral[-0, +1, m]
const char *lua_pushliteral (lua_State *L, const char *s);
Этот макрос эквивалентен lua_pushstring, но должен использоваться только тогда, когда s является литеральной строкой.
lua_pushlstring[-0, +1, m]
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, m]
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);
Помещает поток, представленный L в стек. Возвращает 1, если этот поток является главным потоком своего состояния.
lua_pushvalue[-0, +1, –]
void lua_pushvalue (lua_State *L, int index);
Помещает копию элемента по данному индексу в стек.
lua_pushvfstring[-0, +1, m]
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.
Возвращает тип помещённого значения.
lua_rawgetp[-0, +1, –]
int lua_rawgetp (lua_State *L, int index, const void *p);
Помещает в стек значение t[k], где t – таблица по заданному индексу, а k – указатель p , представленный как лёгкие пользовательские данные. Доступ прямой, то есть он не вызывает метаметод __index.
Возвращает тип помещённого значения.
lua_rawlen[-0, +0, –]
size_t 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.
lua_rawsetp[-1, +0, m]
void lua_rawsetp (lua_State *L, int index, const void *p);
Выполняет эквивалент t[p] = v, где t – таблица по заданному индексу, p закодирован как лёгкие пользовательские данные, а v – значение вверху стека.
Функция извлекает значение из стека. Присваивание выполняется без метаметода __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_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 - значение по заданному индексу, и 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 - значение по заданному индексу, и v - значение на вершине стека.
Эта функция извлекает значение со стека. Как и в Lua, эта функция может вызвать метаметод для события "newindex" (см. §2.4).
lua_setmetatable[-1, +0, –]
void lua_setmetatable (lua_State *L, int index);
Извлекает таблицу со стека и устанавливает ее как новое метатаблицу для значения по заданному индексу.
lua_settable[-2, +0, e]
void lua_settable (lua_State *L, int index);
Выполняет эквивалент t[k] = v, где t - значение по заданному индексу, 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 по заданному индексу.
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 в число, помещает это число в стек и возвращает общий размер строки, то есть ее длину плюс один. Преобразование может привести к целому или вещественному числу в соответствии с лексическими соглашениями Lua (см. §3.1). Строка может содержать начальные и конечные пробелы и знак. Если строка не является допустимым числом, возвращает 0 и ничего не помещает в стек. (Обратите внимание, что результат может использоваться как булев, true, если преобразование выполняется успешно.)
lua_toboolean[-0, +0, –]
int lua_toboolean (lua_State *L, int index);
Преобразует значение Lua по заданному индексу в значение C boolean (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_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. Эта строка всегда имеет ноль ('\0') после последнего символа (как в 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 по заданному индексу в тип 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*). Значение может быть userdata, таблицей, потоком или функцией; в противном случае 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);
Если значение по заданному индексу является полным userdata, возвращает адрес его блока. Если значение является легким userdata, возвращает его указатель. В противном случае возвращает NULL.
lua_type[-0, +0, –]
int lua_type (lua_State *L, int 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-й замыкание выполняемой функции (см. §4.4).
lua_version[-0, +0, –]
const lua_Number *lua_version (lua_State *L);
Возвращает адрес номера версии (статической переменной C), хранящейся в ядре Lua. При вызове с допустимым lua_State, возвращает адрес версии, использованной для создания этого состояния. При вызове с NULL, возвращает адрес версии, выполняющей вызов.
lua_Writer
typedef int (*lua_Writer) (lua_State *L,
const void* p,
size_t sz,
void* ud); Тип функции-записывателя, используемой функцией lua_dump. Каждый раз, когда она генерирует еще один фрагмент блока, lua_dump вызывает функцию-записыватель, передавая буфер для записи (p), его размер (sz) и параметр data, переданный функции lua_dump.
Функция-записыватель возвращает код ошибки: 0 означает отсутствие ошибок; любое другое значение означает ошибку и останавливает lua_dump от повторного вызова функции-записывателя.
lua_xmove[-?, +?, –]
void lua_xmove (lua_State *from, lua_State *to, int n);
Обмен значениями между различными потоками одного и того же состояния.
Эта функция извлекает n значения со стека from, и помещает их на стек 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 не имеет встроенных средств отладки. Вместо этого он предоставляет специальный интерфейс с помощью функций и зацепок. Этот интерфейс позволяет создавать различные типы отладчиков, профилировщиков и другие инструменты, которые нуждаются в "внутренней информации" от интерпретатора.
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) number of upvalues */
unsigned char nparams; /* (u) number of parameters */
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: "печать" версии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: количество upvalues функции. -
nparams: количество фиксированных параметров функции (всегда 0 для функций C). -
isvararg: true, если функция является функцией vararg (всегда true для функций 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"); /* get global 'f' */
lua_getinfo(L, ">S", &ar);
printf("%d\n", 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 возвращает 1; при вызове с уровнем, превышающим глубину стека, возвращает 0.
lua_getupvalue[-0, +(0|1), –]
const char *lua_getupvalue (lua_State *L, int funcindex, int n);
Получает информацию об n-м замыкании в замыкании по индексу funcindex. Он помещает значение замыкания на стек и возвращает его имя. Возвращает NULL (и ничего не помещает на стек), когда индекс n больше числа замыканий.
Для функций C эта функция использует пустую строку "" в качестве имени для всех замыканий. (Для функций Lua замыкания — это внешние локальные переменные, которые использует функция, и которые, следовательно, включены в её замыкание.)
Замыкания не имеют определенного порядка, так как они активны в течение всей функции. Они пронумерованы в произвольном порядке.
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 равным нулю (то есть без значений).
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);
Устанавливает значение замыкания замыкания. Он присваивает значение сверху стека замыканию и возвращает его имя. Также удаляет значение со стека.
Возвращает NULL (и ничего не удаляет со стека), когда индекс n больше числа замыканий.
Параметры funcindex и n такие же, как в функции lua_getupvalue.
lua_upvalueid[-0, +0, –]
void *lua_upvalueid (lua_State *L, int funcindex, int n);
Возвращает уникальный идентификатор замыкания с номером n из замыкания по индексу funcindex.
Эти уникальные идентификаторы позволяют программе проверить, имеют ли разные замыкания общие замыкания. Замыкания 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_addlstring[-?, +?, m]
void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l);
Добавляет строку, на которую указывает s с длиной l в буфер B (см. luaL_Buffer). Строка может содержать вложенные нули.
luaL_addsize[-?, +?, –]
void luaL_addsize (luaL_Buffer *B, size_t n);
Добавляет в буфер B (см. luaL_Buffer) строку длиной 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[-0, +0, v]
int luaL_argerror (lua_State *L, int arg, const char *extramsg);
Вызывает ошибку, сообщая о проблеме с аргументом arg функции C, которая её вызвала, используя стандартное сообщение, которое включает 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. - Затем инициализируйте её и предварительно выделите место размером
szс помощью вызоваluaL_buffinitsize(L, &b, 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[-?, +?, m]
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 (который должен быть завершен нулём). Возвращает индекс в массиве, где была найдена строка. Вызывает ошибку, если аргумент не является строкой или строка не найдена.
Если 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. Также проверяет, используют ли ядро, выполняющее вызов, и ядро, которое создало состояние 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, m]
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), m]
int luaL_getmetafield (lua_State *L, int obj, const char *e);
Помещает на стек поле e из метатаблицы объекта по индексу obj и возвращает тип помещённого значения. Если у объекта нет метатаблицы или метатаблица не имеет этого поля, ничего не помещает и возвращает 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, является таблицей, и помещает эту таблицу на стек. Возвращает true, если находит там предыдущую таблицу, и false, если создаёт новую таблицу.
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. (Запись __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_opt[-0, +0, e]
T luaL_opt (L, func, arg, dflt);
Этот макрос определён следующим образом:
(lua_isnoneornil(L,(arg)) ? (dflt) : func(L,(arg)))
Другими словами, если аргумент arg равен nil или отсутствует, макрос возвращает значение по умолчанию dflt. В противном случае он возвращает результат вызова func со состоянием L и индексом аргумента arg в качестве аргументов. Обратите внимание, что он вычисляет выражение dflt только при необходимости.
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 длиной результата. Если результат равен NULL (возможно только при возвращении d и d == NULL), его длина считается нулевой.
Эта функция использует lua_tolstring для получения результата, поэтому все преобразования и замечания этой функции применимы здесь.
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[-?, +?, 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_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 освобождает ссылку и связанный с ней объект.
Если объект вверху стека равен 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 истинно, также сохраняет модуль в глобальную переменную modname.
Оставляет копию модуля на стеке.
luaL_setfuncs[-nup, +0, m]
void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup);
Регистрирует все функции в массиве l (см. luaL_Reg) в таблице вверху стека (ниже необязательных верхних уровней, см. дальше).
Когда nup не равно нулю, все функции создаются с общими 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 — макрос с фактическим именем метатаблицы). Метатаблица создаётся библиотекой ввода/вывода (см. luaL_newmetatable).
Эти пользовательские данные должны начинаться со структуры luaL_Stream; они могут содержать другие данные после этой начальной структуры. Поле f указывает на соответствующий C поток (или может быть NULL, чтобы указать на недостроенный дескриптор). Поле closef указывает на функцию Lua, которая будет вызываться для закрытия потока при закрытии или сборе дескриптора; эта функция получает дескриптор файла в качестве единственного аргумента и должна вернуть либо true (в случае успеха), либо nil плюс сообщение об ошибке (в случае ошибки). После того, как Lua вызовет это поле, оно изменит значение поля на NULL, чтобы сигнализировать о закрытии дескриптора.
luaL_testudata[-0, +0, m]
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 по данному индексу в C-строку в приемлемом формате. Результирующая строка помещается на стек и также возвращается функцией. Если 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_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 также освобождается, чтобы быть повторно использованой.
Если ref равно LUA_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 API. Некоторые из этих функций обеспечивают основные службы языка (например, type и getmetatable); другие обеспечивают доступ к «внешним» службам (например, вводу-выводу); а другие могли бы быть реализованы в самом 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 ложно (т. е. 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. При вызове без аргументов, dofile выполняет содержимое стандартного ввода (stdin). Возвращает все значения, возвращённые фрагментом. В случае ошибок, dofile передаёт ошибку своему вызывающему элементу (т. е. dofile не выполняется в защищённом режиме).
error (message [, level])
Прерывает последнюю защищённую функцию, вызываемую, и возвращает message в качестве объекта ошибки. Функция error никогда не возвращает значение. Обычно, error добавляет некоторую информацию о позиции ошибки в начале сообщения, если сообщение является строкой. Аргумент level определяет, как получить позицию ошибки. При уровне 1 (по умолчанию) позиция ошибки — это место, где была вызвана функция error. Уровень 2 указывает ошибку на то место, где была вызвана функция, вызвавшая error; и так далее. Передача уровня 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 плюс сообщение об ошибке.
Если получившаяся функция имеет upvalues, первое upvalue устанавливается в значение env, если этот параметр задан, или в значение глобальной среды. Другие upvalues инициализируются nil. (При загрузке главного фрагмента получившаяся функция всегда будет иметь ровно одно upvalue, переменную _ENV (см. §2.2). Однако, при загрузке бинарного фрагмента, созданного из функции (см. string.dump), получившаяся функция может иметь любое количество upvalues.) Все upvalues новые, то есть они не разделяются ни с какой другой функцией.
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 ловит ошибку и возвращает код состояния. Его первый результат — код состояния (логическое значение), который является истинным, если вызов завершается без ошибок. В таком случае, pcall также возвращает все результаты вызова после этого первого результата. В случае любой ошибки, pcall возвращает false плюс сообщение об ошибке.
print (···)
Принимает любое количество аргументов и выводит их значения в stdout, используя функцию tostring для преобразования каждого аргумента в строку. print не предназначен для форматированного вывода, но только как быстрый способ показать значение, например, для отладки. Для полного контроля над выводом, используйте string.format и io.write.
rawequal (v1, v2)
Проверяет, равно ли v1 значению v2, без вызова метаметода __eq. Возвращает булево значение.
rawget (table, index)
Получает фактическое значение table[index], без вызова метаметода __index. table должно быть таблицей; index может быть любым значением.
rawlen (v)
Возвращает длину объекта v, который должен быть таблицей или строкой, без вызова метаметода __len. Возвращает целое число.
rawset (table, index, value)
Устанавливает фактическое значение table[index] в value, без вызова метаметода __newindex. table должно быть таблицей, index любым значением, отличным от nil и NaN, а value любым значением Lua. Эта функция возвращает table.
select (index, ···)
Если index является числом, возвращает все аргументы после аргумента с номером index; отрицательное число индексирует с конца (-1 — последний аргумент). В противном случае, index должно быть строкой "#", и select возвращает общее количество дополнительных аргументов.
setmetatable (table, metatable)
Устанавливает метатаблицу для данной таблицы. (Чтобы изменить метатаблицу других типов из кода Lua, необходимо использовать библиотеку debug (§6.10).) Если metatable равно nil, удаляет метатаблицу данной таблицы. Если у исходной метатаблицы есть поле __metatable, возникает ошибка.
Эта функция возвращает table.
tonumber (e [, base])
При вызове без base, tonumber пытается преобразовать свой аргумент в число. Если аргумент уже является числом или строкой, преобразуемой в число, то tonumber возвращает это число; в противном случае — nil.
Преобразование строк может привести к целым числам или числам с плавающей запятой в соответствии с лексическими соглашениями Lua (см. §3.1). (Строка может иметь ведущие и хвостовые пробелы и знак.)
При вызове с base, тогда e должна быть строкой, интерпретируемой как целое число в указанной системе счисления. Основание может быть любым целым числом от 2 до 36 включительно. В системах счисления с основанием более 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. Текущее значение этой переменной — "Lua 5.3".
xpcall (f, msgh [, arg1, ···])
Эта функция похожа на pcall, за исключением того, что она устанавливает новый обработчик сообщений msgh.
6.2 – Управление корутинами
Эта библиотека включает операции по управлению корутинами, которые находятся в таблице coroutine. См. §2.6 для общего описания корутин.
coroutine.create (f)
Создаёт новую корутину с телом f. f должно быть функцией. Возвращает эту новую корутину, объект типа "thread".
coroutine.isyieldable ()
Возвращает true, когда текущая корутина может сделать yield.
Текущая корутина является yieldable, если она не является основным потоком и не находится внутри не-yieldable функции C.
coroutine.resume (co [, val1, ···])
Запускает или продолжает выполнение корутины co. В первый раз при возобновлении корутина начинает выполнять своё тело. Значения val1, ... передаются в качестве аргументов функции тела. Если корутина сделала yield, resume перезапускает её; значения val1, ... передаются в качестве результатов от yield.
Если корутина выполняется без ошибок, resume возвращает true вместе со значениями, переданными в yield (когда корутина делает 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 и дополнительным значением, зависящим от того, как был найден загрузчик. (Если загрузчик был найден в файле, это дополнительное значение — имя файла.) Если загрузчик возвращает любое ненулевое значение, require присваивает возвращённое значение package.loaded[modname]. Если загрузчик не возвращает ненулевого значения и не присвоил значения package.loaded[modname], то require присваивает true этой записи. В любом случае require возвращает конечное значение package.loaded[modname].
Если при загрузке или выполнении модуля возникает ошибка, или если не найден загрузчик, то require вызывает ошибку.
package.config
Строка, описывающая некоторые конфигурации, установленные во время компиляции для пакетов. Эта строка состоит из строк:
- Первая строка — строка разделителя каталогов. По умолчанию это '
\' для 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] не ложно, 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).
package.path
Путь, используемый require для поиска загрузчика Lua.
При запуске Lua инициализирует эту переменную значением переменной среды LUA_PATH_5_3 или переменной среды LUA_PATH, или с помощью пути по умолчанию, определенного в luaconf.h, если эти переменные среды не определены. Любой ";;" в значении переменной среды заменяется путём по умолчанию.
package.preload
Таблица для хранения загрузчиков для определённых модулей (см. require).
Эта переменная является лишь ссылкой на реальную таблицу; присваивания этой переменной не изменяют таблицу, используемую require.
package.searchers
Таблица, используемая require для управления загрузкой модулей.
Каждый элемент этой таблицы — это функция-поисковик. При поиске модуля 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 по этой строке возвращает копию функции (но с новыми значениями). Если strip имеет истинное значение, двоичное представление может не включать всю отладочную информацию о функции, чтобы сэкономить место.
Функции с значениями имеют сохранённое только количество значений. При (пере)загрузке эти значения получают новые экземпляры, содержащие nil. (Вы можете использовать библиотеку отладки для сериализации и перезагрузки значений функции таким образом, который соответствует вашим потребностям.)
string.find (s, pattern [, init [, plain]])
Ищет первое вхождение pattern (см. §6.4.1) в строке s. Если находит совпадение, то find возвращает индексы s, где это вхождение начинается и заканчивается; в противном случае возвращает nil. Третий, необязательный числовой аргумент init указывает, с какой позиции начать поиск; его значение по умолчанию — 1, и оно может быть отрицательным. Значение true в качестве четвёртого, необязательного аргумента plain отключает средства сопоставления с шаблоном, поэтому функция выполняет простое нахождение подстроки без того, чтобы символы в pattern считались магическими. Обратите внимание, что если plain задан, то init также должен быть задан.
Если шаблон имеет захваты, то при успешном совпадении захваченные значения также возвращаются после двух индексов.
string.format (formatstring, ···)
Возвращает отформатированную версию своих аргументов, следуя описанию, указанному в первом аргументе (который должен быть строкой). Строка формата следует тем же правилам, что и функция ISO C sprintf. Единственные различия заключаются в том, что варианты/модификаторы *, 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 ожидают целое число. Когда Lua скомпилирован с компилятором C89, варианты A и a (шестнадцатеричные числа с плавающей точкой) не поддерживают никаких модификаторов (флаги, ширина, длина).
Вариант s ожидает строку; если его аргумент не является строкой, он преобразуется в строку, следуя тем же правилам, что и tostring. Если у варианта есть модификаторы (флаги, ширина, длина), аргумент-строка не должна содержать встроенных нулей.
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. Вложенные нули учитываются, так что "a\000bc\000" имеет длину 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) (для положительного 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. Это стандартный способ экранирования магических символов. Любой небуквенно-цифровой символ (включая все знаки препинания, даже не магические) может предшествовать символу '%', когда используется для представления самого себя в шаблоне. -
[set]: представляет класс, который является объединением всех символов в множестве. Диапазон символов можно указать, разделяя конечные символы диапазона в возрастающем порядке с помощью '-'. Все классы%x, описанные выше, также могут использоваться как компоненты в множестве. Все остальные символы в множестве представляют сами себя. Например,[%w_](или[_%w]) представляет все буквенно-цифровые символы плюс символ подчёркивания,[0-7]представляет восьмеричные цифры, и[0-7%l%-]представляет восьмеричные цифры плюс строчные буквы плюс символ '-'.Вы можете поместить закрывающую квадратную скобку в множество, расположив её в качестве первого символа в множестве. Вы можете поместить дефис в множество, расположив его в качестве первого или последнего символа в множестве. (Вы также можете использовать экранирование для обоих случаев.)
Взаимодействие между диапазонами и классами не определено. Поэтому шаблоны, такие как
[%a-z]или[a-%%], не имеют смысла. -
[^set]: представляет дополнение к множеству, где множество интерпретируется как описано выше.
Для всех классов, представленных одиночными буквами (%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[set], фронтирный шаблон; такой элемент сопоставляет пустую строку в любой позиции, такой, что следующий символ принадлежит множеству, а предыдущий символ не принадлежит множеству. Множество множество интерпретируется как описано ранее. Начало и конец темы обрабатываются так, как будто они были символом '\0'.
Шаблон:
Шаблон - это последовательность элементов шаблона. Каретка '^' в начале шаблона фиксирует совпадение в начале строки-субъекта. Символ '$' в конце шаблона фиксирует совпадение в конце строки-субъекта. В других позициях '^' и '$' не имеют специального значения и представляют сами себя.
Захваты:
Шаблон может содержать подшаблоны, заключённые в скобки; они описывают захваты. При успешном совпадении подстроки строки-субъекта, которые соответствуют захватам, сохраняются (захватываются) для дальнейшего использования. Захваты нумеруются в соответствии с их левыми скобками. Например, в шаблоне "(a*(.)%w(%s*))", часть строки, соответствующая "a*(.)%w(%s*)", сохраняется как первый захват (и поэтому имеет номер 1); символ, соответствующий ".", захватывается с номером 2, а часть, соответствующая "%s*", имеет номер 3.
В качестве специального случая, пустая захват () захватывает текущую позицию строки (число). Например, если мы применим шаблон "()aa()" к строке "flaaap", будут два захвата: 3 и 5.
6.4.2 – Форматы строк для упаковки и распаковки
Первый аргумент для 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 (без выравнивания) и порядком байтов по умолчанию.
Выравнивание работает следующим образом: для каждого параметра формат получает дополнительное заполнение, пока данные не начнут с смещения, кратного минимальному из размера параметра и максимального выравнивания; это минимальное значение должно быть степенью двойки. Параметры "c" и "z" не выравниваются; параметр "s" следует выравниванию своего начального целого числа.
Всё заполнение заполняется нулями функцией string.pack (и игнорируется функцией string.unpack).
6.5 – Поддержка UTF-8
Эта библиотека предоставляет базовую поддержку кодировки UTF-8. Все её функции находятся внутри таблицы utf8. Эта библиотека не поддерживает Unicode, кроме обработки кодировки. Любая операция, которая нуждается в значении символа, например, классификация символов, выходит за её рамки.
Если не указано иное, все функции, которые ожидают байтовую позицию в качестве параметра, предполагают, что заданная позиция является либо началом последовательности байтов, либо на единицу больше длины строки. Как и в библиотеке строк, отрицательные индексы отсчитываются от конца строки.
utf8.char (···)
Принимает ноль или более целых чисел, преобразует каждое из них в соответствующую последовательность байтов UTF-8 и возвращает строку, являющуюся конкатенацией всех этих последовательностей.
utf8.charpattern
Шаблон (строка, а не функция) "[\0-\x7F\xC2-\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. Если она найдёт недопустимую последовательность байтов, вернёт ложное значение плюс позицию первого недопустимого байта.
utf8.offset (s, n [, i])
Возвращает позицию (в байтах), где начинается кодировка n-го символа s (считая с позиции i). Отрицательное n получает символы перед позицией i. По умолчанию i — 1, если n неотрицательно, и #s + 1 в противном случае, так что utf8.offset(s, -n) получает смещение n-го символа от конца строки. Если указанный символ не находится ни в строке, ни сразу за её концом, функция возвращает nil. В качестве специального случая, когда 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; в этих случаях функция удаляет элемент list[pos].
Значение по умолчанию для pos — #list, так что вызов table.remove(l) удаляет последний элемент списка l.
table.sort (list [, comp])
Сортирует элементы списка в заданном порядке, на месте, от list[1] до list[#list]. Если comp задано, то оно должно быть функцией, принимающей два элемента списка и возвращающей true, когда первый элемент должен предшествовать второму в окончательном порядке (так что после сортировки 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. (целое/дробное)
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)
Возвращает значение ex (где 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]. (Значение n-m не может быть отрицательным и должно помещаться в целое число Lua.) Вызов math.random(n) эквивалентен math.random(1,n).
Эта функция является интерфейсом к функции генерации псевдослучайных чисел, предоставляемой C.
math.randomseed (x)
Устанавливает x в качестве "семени" для генератора псевдослучайных чисел: одинаковые семена производят одинаковые последовательности чисел.
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", если это вещественное число, или nil, если x не является числом.
math.ult (m, n)
Возвращает булево значение, true тогда и только тогда, когда целое число m меньше целого числа n при сравнении как целые числа без знака.
6.8 – Средства ввода и вывода
Библиотека ввода-вывода предоставляет два различных стиля для работы с файлами. Первый использует неявные дескрипторы файлов; то есть, существуют операции для установки файла по умолчанию для ввода и файла по умолчанию для вывода, и все операции ввода-вывода выполняются над этими файлами по умолчанию. Второй стиль использует явные дескрипторы файлов.
При использовании неявных дескрипторов файлов все операции предоставляются таблицей 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. В случае успеха возвращает новый дескриптор файла.
Строка 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 в конце файла. -
number: считывает строку до указанного числа байтов, возвращает nil в конце файла. Если
numberравно нулю, он ничего не считывает и возвращает пустую строку или nil в конце файла.
Форматы "l" и "L" следует использовать только для текстовых файлов.
file:seek ([whence [, offset]])
Устанавливает и получает позицию файла, измеряемую с начала файла, до позиции, заданной offset плюс основание, заданное строкой whence, следующим образом:
- "
set": основание — позиция 0 (начало файла); - "
cur": основание — текущая позиция; - "
end": основание — конец файла;
В случае успеха seek возвращает конечную позицию файла, измеряемую в байтах с начала файла. Если 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 начинается с '!', то дата форматируется в координированном универсальном времени. После этого необязательного символа, если 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.
При вызове без аргументов date возвращает разумное представление даты и времени, которое зависит от системного хоста и текущего локали. (Более конкретно, os.date() эквивалентно os.date("%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 для выполнения оболочкой операционной системы. Первый результат — true, если команда завершилась успешно, или nil в противном случае. После этого первого результата функция возвращает строку и число следующим образом:
- "
exit": команда завершилась нормально; следующее число — код завершения команды. - "
signal": команда была завершена сигналом; следующее число — сигнал, который завершил команду.
При вызове без command, os.execute возвращает булево значение, равное true, если оболочка доступна.
os.exit ([code [, close]])
Вызывает функцию 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 плюс строку, описывающую ошибку, и код ошибки. В противном случае возвращает true.
os.rename (oldname, newname)
Переименовывает файл или каталог с именем oldname в newname. Если эта функция завершается ошибкой, она возвращает nil плюс строку, описывающую ошибку, и код ошибки. В противном случае возвращает true.
os.setlocale (locale [, category])
Устанавливает текущий локали программы. locale — это зависящая от системы строка, определяющая локали; category — необязательная строка, описывающая, какую категорию изменить: "all", "collate", "ctype", "monetary", "numeric", или "time"; категория по умолчанию — "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 – Библиотека отладки
Эта библиотека предоставляет функциональность интерфейса отладки (§4.9) для программ Lua. Следует проявлять осторожность при использовании этой библиотеки. Несколько её функций нарушают базовые предположения о коде Lua (например, что переменные, локальные для функции, не могут быть доступны извне; что метатаблицы userdata не могут быть изменены кодом Lua; что программы Lua не аварийно завершаются) и поэтому могут поставить под угрозу в противном случае безопасный код. Кроме того, некоторые функции в этой библиотеке могут быть медленными.
Все функции этой библиотеки предоставляются внутри таблицы debug. Все функции, которые работают с потоком, имеют необязательный первый аргумент, который является потоком, над которым нужно работать. По умолчанию всегда используется текущий поток.
debug.debug ()
Входит в интерактивный режим с пользователем, выполняя каждую введённую строку. Используя простые команды и другие средства отладки, пользователь может инспектировать глобальные и локальные переменные, изменять их значения, вычислять выражения и так далее. Строка, содержащая только слово cont, завершает эту функцию, так что вызывающая её функция продолжает своё выполнение.
Обратите внимание, что команды для debug.debug не вложены лексически ни в одну функцию и поэтому не имеют прямого доступа к локальным переменным.
debug.gethook ([thread])
Возвращает текущие настройки хука потока в виде трёх значений: текущую функцию хука, текущую маску хука и текущее количество вызовов хука (установленное функцией debug.sethook).
debug.getinfo ([thread,] f [, what])
Возвращает таблицу с информацией о функции. Вы можете указать функцию напрямую или число как значение f, что означает функцию, выполняющуюся на уровне f стека вызовов данного потока: уровень 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 — это первый аргумент vararg. Функция возвращает 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 не является полным userdata, возвращает nil.
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 стека. Функция возвращает nil, если локальной переменной с данным индексом нет, и генерирует ошибку при вызове с level вне допустимого диапазона. (Вы можете вызвать getinfo , чтобы проверить, является ли уровень допустимым.) В противном случае она возвращает имя локальной переменной.
См. debug.getlocal для получения более подробной информации об индексах и именах переменных.
debug.setmetatable (value, 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 должен быть полным userdata.
Возвращает udata.
debug.traceback ([thread,] [message [, level]])
Если message присутствует, но не является строкой и не равно nil, эта функция возвращает message без дальнейшей обработки. В противном случае она возвращает строку со стеком вызовов. Необязательная строка message добавляется в начало стека вызовов. Необязательное число level указывает, на каком уровне начать трассировку стека (по умолчанию 1, функция, вызвавшая traceback).
debug.upvalueid (f, n)
Возвращает уникальный идентификатор (как лёгкий userdata) для upvalue с номером n из заданной функции.
Эти уникальные идентификаторы позволяют программе проверять, разделяют ли различные замыкания upvalues. Lua-замыкания, которые разделяют upvalue (то есть, которые обращаются к одной и той же внешней локальной переменной), будут возвращать идентичные id для этих индексов upvalue.
debug.upvaluejoin (f1, n1, f2, n2)
Делает n1-ю upvalue Lua-замыкания f1 ссылающейся на n2-ю upvalue Lua-замыкания f2.
7 – Lua Standalone
Хотя Lua был разработан как язык расширений, который нужно встраивать в программу на C, его часто используют также как автономный язык. В стандартной дистрибуции предоставляется интерпретатор Lua для автономного использования, который называется просто lua. Автономный интерпретатор включает все стандартные библиотеки, включая библиотеку отладки. Его использование выглядит так:
lua [options] [script [args]]
Опции:
-
-e stat: выполняет строку stat; -
-l mod: «требует» mod и присваивает результат глобальной переменной @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, скрипт компилируется как функция vararg.)
В интерактивном режиме Lua многократно запрашивает и ожидает ввода строки. После считывания строки Lua сначала пытается интерпретировать ее как выражение. Если это удается, он выводит его значение. В противном случае он интерпретирует строку как оператор. Если вы напишете неполный оператор, интерпретатор ждет его завершения, выдав другой запрос.
Если глобальная переменная _PROMPT содержит строку, то ее значение используется в качестве запроса. Аналогично, если глобальная переменная _PROMPT2 содержит строку, ее значение используется в качестве дополнительного запроса (выводится во время неполных операторов).
В случае неохраняемых ошибок в скрипте интерпретатор сообщает об ошибке в поток стандартной ошибки. Если объект ошибки не является строкой, но имеет метаметод __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. Всегда перекомпилируйте клиенты API Lua при использовании новой версии.
Аналогично, версии 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 в расширенном BNF. Как обычно в расширенном BNF, {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 | ‘#’ | ‘~’
© 1994–2020 Lua.org, PUC-Rio.
Licensed under the MIT License.
https://www.lua.org/manual/5.3/manual.html