Lua (язык программирования) - Lua (programming language)

Lua
Lua-Logo.svg
Парадигма Мультипарадигма : сценарии , императивные ( процедурные , прототипные , объектно-ориентированные ), функциональные.
Разработано Роберто Иерусалимши
Вальдемар Селес
Луис Энрике де Фигейредо
Впервые появился 1993 ; 28 лет назад ( 1993 )
Стабильный выпуск
5.4.3  Отредактируйте это в Викиданных / 29 марта 2021 г . ; 5 месяцев назад ( 29 марта 2021 г. )
Печатная дисциплина Динамичный , сильный , утка
Язык реализации ANSI C
Операционные системы Кроссплатформенность
Лицензия Лицензия MIT
Расширения имени файла .lua
Веб-сайт www .lua .org
Основные реализации
Lua , LuaJIT , LuaVela , MoonSharp , Luvit , LuaRT
Диалекты
Metalua , холостой ход , GSL Shell , Луау
Под влиянием
C ++ , CLU , Модула , Схема , СНОБОЛ
Под влиянием
GameMonkey , Io , JavaScript , Julia , MiniD, Red , Ring, Ruby , Squirrel , MoonScript, C--

Луа ( / л ¯u ə / ЛОО ; от португальцев : Lua [ˈLu. (W) ɐ], что означает луна ) - это легкий , высокоуровневый , многопарадигмальный язык программирования, разработанный в первую очередь для встроенного использования в приложениях. Lua является кросс-платформенным , так как интерпретатор из скомпилированных байт - кода записывается в ANSI C и Lua имеет относительно простой C API , чтобы встроить его в приложение.

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

История

Lua был создан в 1993 году Роберто Иерусалимши , Луисом Энрике де Фигейредо и Вальдемаром Селесом, членами Технологической группы компьютерной графики (Tecgraf) Папского католического университета Рио-де-Жанейро в Бразилии .

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

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

В The Evolution of Lua авторы языка писали:

В 1993 году единственным реальным соперником был Tcl , который был специально разработан для встраивания в приложения. Однако Tcl имел незнакомый синтаксис, не предлагал хорошей поддержки описания данных и работал только на платформах Unix. Мы не рассматривали LISP или Scheme из-за их недружественного синтаксиса. Python все еще находился в зачаточном состоянии. В свободной атмосфере самостоятельности, которая тогда царила в Tecgraf, было вполне естественно, что мы должны попытаться разработать наш собственный язык сценариев ... Поскольку многие потенциальные пользователи языка не были профессиональными программистами, язык должен избегать загадочных синтаксис и семантика. Реализация нового языка должна быть легко переносимой, потому что клиенты Tecgraf имеют очень разнообразный набор компьютерных платформ. Наконец, поскольку мы ожидали, что другие продукты Tecgraf также должны будут включать язык сценариев, новый язык должен следовать примеру SOL и предоставляться в виде библиотеки с C API.

Lua 1.0 был разработан таким образом, что его конструкторы объектов, которые тогда немного отличались от текущего легкого и гибкого стиля, включали синтаксис описания данных SOL (отсюда и название Lua: Sol, означающее «Солнце» на португальском языке, и Lua, означающее "Луна"). Lua синтаксис для управляющих структурами в основном заимствован из Modula ( if, while, repeat/ until), но и взяли влияние от CLU (несколько заданий и несколько возвращения из вызовов функций, как более простой альтернатива ссылочных параметров или явных указатели ), C ++ ( "аккуратной идеи разрешить объявление локальной переменной только там, где она нам нужна »), SNOBOL и AWK (ассоциативные массивы). В статье, опубликованной в журнале доктора Добба , создатели Lua также заявляют, что LISP и Scheme с их единым повсеместным механизмом структуры данных ( список ) оказали большое влияние на их решение разработать таблицу в качестве основной структуры данных Lua.

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

Версии Lua до версии 5.0 были выпущены под лицензией, аналогичной лицензии BSD . Начиная с версии 5.0, Lua лицензируется по лицензии MIT . Обе являются разрешительными лицензиями свободных программ и почти идентичны.

Функции

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

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

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

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

Синтаксис

Классический "Hello, World!" программу можно записать так:

print("Hello, World!")

или как:

print 'Hello, World!'

Комментарий в Lua начинается с двойным дефисом и бежит к концу линии, подобно Ada , Eiffel , Haskell , SQL и VHDL . Многострочные строки и комментарии заключаются в двойные квадратные скобки.

В этом примере факториальная функция реализована как функция:

function factorial(n)
  local x = 1
  for i = 2, n do
    x = x * i
  end
  return x
end

Поток управления

В Lua есть четыре типа циклов : whileцикл , repeatцикл (аналогичный do whileциклу ), числовой forцикл и общий forцикл.

--condition = true

while condition do
  --statements
end

repeat
  --statements
until condition

for i = first, last, delta do  --delta may be negative, allowing the for loop to count down or up
  --statements
  --example: print(i)
end

Общий forцикл:

for key, value in pairs(_G) do
  print(key, value)
end

будет перебирать таблицу, _Gиспользуя стандартную функцию итератора pairs, до тех пор, пока она не вернется nil.

Циклы также могут быть вложенными (помещенными в другой цикл).

local grid = {
  { 11, 12, 13 },
  { 21, 22, 23 },
  { 31, 32, 33 }
}

for y, row in ipairs(grid) do
  for x, value in ipairs(row) do
    print(x, y, value)
  end
end

Функции

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

do
  local oldprint = print
  -- Store current print function as oldprint
  function print(s)
    --[[ Redefine print function. The usual print function can still be used
      through oldprint. The new one has only one argument.]]
    oldprint(s == "foo" and "bar" or s)
  end
end

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

Lua также поддерживает замыкания , как показано ниже:

function addto(x)
  -- Return a new function that adds x to the argument
  return function(y)
    --[=[ When we refer to the variable x, which is outside the current
      scope and whose lifetime would be shorter than that of this anonymous
      function, Lua creates a closure.]=]
    return x + y
  end
end
fourplus = addto(4)
print(fourplus(3))  -- Prints 7

--This can also be achieved by calling the function in the following way:
print(addto(4)(3))
--[[ This is because we are calling the returned function from 'addto(4)' with the argument '3' directly.
  This also helps to reduce data cost and up performance if being called iteratively.
]]

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

Таблицы

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

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

Таблицы создаются с использованием {}синтаксиса конструктора.

a_table = {} -- Creates a new, empty table

Таблицы всегда передаются по ссылке (см. Вызов путем совместного использования ).

Ключ (индекс) может быть любое значение , кроме nilи NaN , в том числе функций.

a_table = {x = 10}  -- Creates a new table, with one entry mapping "x" to the number 10.
print(a_table["x"]) -- Prints the value associated with the string key, in this case 10.
b_table = a_table
b_table["x"] = 20   -- The value in the table has been changed to 20.
print(b_table["x"]) -- Prints 20.
print(a_table["x"]) -- Also prints 20, because a_table and b_table both refer to the same table.

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

point = { x = 10, y = 20 }   -- Create new table
print(point["x"])            -- Prints 10
print(point.x)               -- Has exactly the same meaning as line above. The easier-to-read dot notation is just syntactic sugar.

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

Point = {}

Point.new = function(x, y)
  return {x = x, y = y}  --  return {["x"] = x, ["y"] = y}
end

Point.set_x = function(point, x)
  point.x = x  --  point["x"] = x;
end

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

Цифровой ключ 1отличается от строкового ключа "1".

array = { "a", "b", "c", "d" }   -- Indices are assigned automatically.
print(array[2])                  -- Prints "b". Automatic indexing in Lua starts at 1.
print(#array)                    -- Prints 4.  # is the length operator for tables and strings.
array[0] = "z"                   -- Zero is a legal index.
print(#array)                    -- Still prints 4, as Lua arrays are 1-based.

Длина таблицы tопределяется как любой целочисленный индекс, nтакой t[n]как нет nilи t[n+1]есть nil; кроме того, если t[1]есть nil, nможет быть нулевым. Для обычного массива с ненулевыми значениями от 1 до заданного nего длина в точности равна nиндексу его последнего значения. Если в массиве есть «дыры» (то есть, значения nil между другими значениями, отличными от nil), тогда #tможет быть любой из индексов, который непосредственно предшествует nilзначению (то есть любое такое значение nil может рассматриваться как конец массива. ).

ExampleTable =
{
  {1, 2, 3, 4},
  {5, 6, 7, 8}
}
print(ExampleTable[1][3]) -- Prints "3"
print(ExampleTable[2][4]) -- Prints "8"

Таблица может быть массивом объектов.

function Point(x, y)        -- "Point" object constructor
  return { x = x, y = y }   -- Creates and returns a new object (table)
end
array = { Point(10, 20), Point(30, 40), Point(50, 60) }   -- Creates array of points
                        -- array = { { x = 10, y = 20 }, { x = 30, y = 40 }, { x = 50, y = 60 } };
print(array[2].y)                                         -- Prints 40

Использование хэш-карты для имитации массива обычно медленнее, чем использование реального массива; однако таблицы Lua оптимизированы для использования в качестве массивов, чтобы избежать этой проблемы.

Метатаблицы

Расширяемая семантика - ключевая особенность Lua, а концепция метатаблиц позволяет мощно настраивать таблицы. В следующем примере демонстрируется «бесконечная» таблица. Для любого n, fibs[n]даст nее число Фибоначчей с помощью динамического программирования и запоминания .

fibs = { 1, 1 }                                -- Initial values for fibs[1] and fibs[2].
setmetatable(fibs, {
  __index = function(values, n)                --[[__index is a function predefined by Lua, 
                                                   it is called if key "n" does not exist.]]
    values[n] = values[n - 1] + values[n - 2]  -- Calculate and memorize fibs[n].
    return values[n]
  end
})

Объектно-ориентированное программирование

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

У этих техник нет такого понятия, как «класс»; скорее используются прототипы , аналогичные Self или JavaScript . Новые объекты создаются либо фабричным методом (который создает новые объекты с нуля), либо путем клонирования существующего объекта.

Создание базового векторного объекта:

local Vector = {}
local VectorMeta = { __index = Vector}

function Vector.new(x, y, z)    -- The constructor
  return setmetatable({x = x, y = y, z = z}, VectorMeta)
end

function Vector.magnitude(self)     -- Another method
  return math.sqrt(self.x^2 + self.y^2 + self.z^2)
end

local vec = Vector.new(0, 1, 0) -- Create a vector
print(vec.magnitude(vec))       -- Call a method (output: 1)
print(vec.x)                    -- Access a member variable (output: 0)

Здесь setmetatableговорит Lua искать элемент в Vectorтаблице, если он отсутствует в vecтаблице. , что эквивалентно , сначала ищет элемент в таблице . В таблице нет элемента, но его метатаблицы делегируют таблицу для элемента, когда он не найден в таблице. vec.magnitudevec["magnitude"]vecmagnitudevecmagnitudeVectormagnitudevec

Lua предоставляет некоторый синтаксический сахар для облегчения объектной ориентации. Чтобы объявить функции-члены внутри таблицы прототипов, можно использовать , что эквивалентно . При вызове методов класса также используется двоеточие: эквивалентно . function table:func(args)function table.func(self, args)object:func(args)object.func(object, args)

Имея это в виду, вот соответствующий класс с :синтаксическим сахаром:

local Vector = {}
Vector.__index = Vector

function Vector:new(x, y, z)    -- The constructor
  -- Since the function definition uses a colon, 
  -- its first argument is "self" which refers
  -- to "Vector"
  return setmetatable({x = x, y = y, z = z}, self)
end

function Vector:magnitude()     -- Another method
  -- Reference the implicit object using self
  return math.sqrt(self.x^2 + self.y^2 + self.z^2)
end

local vec = Vector:new(0, 1, 0) -- Create a vector
print(vec:magnitude())          -- Call a method (output: 1)
print(vec.x)                    -- Access a member variable (output: 0)

Наследование

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

local Vector = {}
Vector.__index = Vector

function Vector:new(x, y, z)    -- The constructor
  -- Here, self refers to whatever class's "new"
  -- method we call.  In a derived class, self will
  -- be the derived class; in the Vector class, self
  -- will be Vector
  return setmetatable({x = x, y = y, z = z}, self)
end

function Vector:magnitude()     -- Another method
  -- Reference the implicit object using self
  return math.sqrt(self.x^2 + self.y^2 + self.z^2)
end

-- Example of class inheritance
local VectorMult = {}
VectorMult.__index = VectorMult
setmetatable(VectorMult, Vector) -- Make VectorMult a child of Vector

function VectorMult:multiply(value) 
  self.x = self.x * value
  self.y = self.y * value
  self.z = self.z * value
  return self
end

local vec = VectorMult:new(0, 1, 0) -- Create a vector
print(vec:magnitude())          -- Call a method (output: 1)
print(vec.y)                    -- Access a member variable (output: 1)
vec:multiply(2)                 -- Multiply all components of vector by 2
print(vec.y)                    -- Access member again (output: 2)

Lua также поддерживает множественное наследование ; __indexможет быть функцией или таблицей. Также возможна перегрузка оператора ; Lua метатаблица может иметь такие элементы, как __add, __subи так далее.

Реализация

Программы Lua не интерпретируются напрямую из текстового файла Lua, а компилируются в байт-код, который затем запускается на виртуальной машине Lua . Процесс компиляции обычно невидим для пользователя и выполняется во время выполнения , особенно когда используется JIT-компилятор , но его можно выполнять в автономном режиме, чтобы повысить производительность загрузки или уменьшить объем памяти, занимаемый средой хоста, не обращая внимания на компилятор. Байт-код Lua также может быть создан и выполнен из Lua, используя dumpфункцию из строковой библиотеки и load/loadstring/loadfileфункции. Lua версии 5.3.4 реализован примерно в 24 000 строк кода C.

Как и большинство процессоров, и в отличие от большинства виртуальных машин (которые основаны на стеке ), виртуальная машина Lua основана на регистрах и, следовательно, больше напоминает реальную конструкцию оборудования. Архитектура регистров позволяет избежать чрезмерного копирования значений и уменьшить общее количество инструкций на функцию. Виртуальная машина Lua 5 - одна из первых чистых виртуальных машин на основе регистров, получивших широкое распространение. Parrot и Android «s Dalvik являются двумя другими известными на основе регистров виртуальных машин. Виртуальная машина PCScheme также была основана на регистрах.

Этот пример представляет собой список байт-кода функции факториала, определенной выше (как показано luacкомпилятором 5.1):

function <factorial.lua:1,7> (9 instructions, 36 bytes at 0x8063c60)
1 param, 6 slots, 0 upvalues, 6 locals, 2 constants, 0 functions
	1	[2]	LOADK    	1 -1	; 1
	2	[3]	LOADK    	2 -2	; 2
	3	[3]	MOVE     	3 0
	4	[3]	LOADK    	4 -1	; 1
	5	[3]	FORPREP  	2 1	; to 7
	6	[4]	MUL      	1 1 5
	7	[3]	FORLOOP  	2 -2	; to 6
	8	[6]	RETURN   	1 2
	9	[7]	RETURN   	0 1

C API

Lua предназначен для встраивания в другие приложения и предоставляет для этого C API . API разделен на две части: ядро ​​Lua и вспомогательную библиотеку Lua. Дизайн Lua API устраняет необходимость ручного управления ссылками в коде C, в отличие от API Python . API, как и язык, минималистичен. Расширенная функциональность обеспечивается вспомогательной библиотекой, которая в основном состоит из макросов препроцессора, помогающих выполнять сложные операции с таблицами.

Lua C API основан на стеке . Lua предоставляет функции для проталкивания и извлечения большинства простых типов данных C (целые числа, числа с плавающей запятой и т. Д.) В стек и из стека, а также функции для управления таблицами через стек. Стек Lua несколько отличается от традиционного стека; например, стек можно индексировать напрямую. Отрицательные индексы указывают смещения от вершины стека. Например, -1 - это верхнее значение (последнее выдвинутое значение), а положительные индексы указывают смещение снизу (самое старое значение). Маршалинг данных между функциями C и Lua также выполняется с помощью стека. Чтобы вызвать функцию Lua, аргументы помещаются в стек, а затем lua_callиспользуется для вызова фактической функции. При написании функции C для прямого вызова из Lua аргументы считываются из стека.

Вот пример вызова функции Lua из C:

#include <stdio.h>
#include <lua.h> // Lua main library (lua_*)
#include <lauxlib.h> // Lua auxiliary library (luaL_*)

int main(void)
{
    // create a Lua state
    lua_State *L = luaL_newstate();

    // load and execute a string
    if (luaL_dostring(L, "function foo (x,y) return x+y end")) {
        lua_close(L);
        return -1;
    }

    // push value of global "foo" (the function defined above)
    // to the stack, followed by integers 5 and 3
    lua_getglobal(L, "foo");
    lua_pushinteger(L, 5);
    lua_pushinteger(L, 3);
    lua_call(L, 2, 1); // call a function with two arguments and one return value
    printf("Result: %d\n", lua_tointeger(L, -1)); // print integer value of item at stack top
    lua_pop(L, 1); // return stack to original state
    lua_close(L); // close Lua state
    return 0;
}

Выполнение этого примера дает:

$ cc -o example example.c -llua
$ ./example
Result: 8

C API также предоставляет некоторые специальные таблицы, расположенные в различных «псевдоиндексах» в стеке Lua. В LUA_GLOBALSINDEXверсиях, предшествующих Lua 5.2, есть таблица глобальных переменных _Gиз Lua, которая является основным пространством имен . Также существует реестр, в LUA_REGISTRYINDEXкотором программы на C могут хранить значения Lua для последующего извлечения.

Можно писать модули расширения с помощью Lua API. Модули расширения - это общие объекты, которые можно использовать для расширения функциональности интерпретатора, предоставляя собственные возможности сценариям Lua. Со стороны Lua такой модуль выглядит как таблица пространства имен, содержащая его функции и переменные. Сценарии Lua могут загружать модули расширения с использованием require, как и модули, написанные на самом Lua. Растущая коллекция модулей, известных как камни , доступна через систему управления пакетами под названием LuaRocks , в духе CPAN , RubyGems и Python egg . Предварительно написанные привязки Lua существуют для большинства популярных языков программирования, включая другие языки сценариев. Для C ++ существует ряд подходов на основе шаблонов и несколько генераторов автоматической привязки.

Приложения

В разработке видеоигр , Lua широко используется как язык сценариев с помощью программистов , в основном из - за его предполагаемой легкости врезать, быстрое выполнение и короткой кривой обучения . Одна из примечательных игровых платформ - Roblox, в которой их собственный диалект, Luau, используется для написания сценариев быстрой разработки игр. Другой - World of Warcraft, который также использует уменьшенную версию Lua.

В 2003 году опрос, проведенный GameDev.net, показал, что Lua был самым популярным языком сценариев для программирования игр. 12 января 2012 года Lua был объявлен победителем Front Line Award 2011 от журнала Game Developer в категории «Инструменты программирования».

Большое количество неигровых приложений также используют Lua для расширения, такие как LuaTeX , реализация языка набора текста TeX , Redis , база данных «ключ-значение» , Neovim , текстовый редактор, и Nginx , веб-сервер .

Благодаря расширению Scribunto Lua доступен как язык сценариев на стороне сервера в программном обеспечении MediaWiki, которое поддерживает Википедию и другие вики. Среди его применений - возможность интеграции данных из Викиданных в статьи и обеспечение работы автоматизированной системы таксобоксов .

Производные языки

Языки, компилируемые в Lua

  • MoonScript является динамическим , пробельные , чувствительными к скриптовый язык вдохновлен CoffeeScript , который составляется в Lua. Это означает, что вместо использования doи end(или {и }) для разделения разделов кода он использует разрывы строк и стиль отступа . Заметным использование MoonScript является распространение видео веб - сайт игра Itch.io .
  • Haxe поддерживает компиляцию в цель Lua, поддерживая Lua 5.1-5.3, а также LuaJIT 2.0 и 2.1.
  • Фенхель, диалект Лиспа, ориентированный на Lua.
  • Урн, диалект Лиспа , построенный на Lua.
  • Амулет, ML -как функционального языка , которого компилятор выходы Lua файлы.

Диалекты

  • LuaJIT (см. Ниже), язык Lua 5.1 с поддержкой JIT goto(начиная с Lua 5.2) и C FFI .
  • Luau от Roblox , язык Lua 5.1 с постепенным набором текста и эргономическими дополнениями.
  • Ravi, язык Lua 5.3 с поддержкой JIT и дополнительной статической типизацией. JIT руководствуется информацией о типе.
  • Shine, форк LuaJIT с множеством расширений, включая модульную систему и макросистему.

Кроме того, сообщество пользователей Lua предоставляет некоторые исправления мощности поверх эталонной реализации C.

LuaJIT

LuaJIT
Разработчики) Майк Полл
Стабильный выпуск
2.0.5 / 1 мая 2017 г . ; 4 года назад ( 2017-05-01 )
Репозиторий репо .или .cz / w / luajit-2 .0 .git
Написано в C , Lua
Операционная система см. список
Тип Компилятор как раз вовремя
Лицензия Лицензия MIT
Веб-сайт LuaJIT .org

LuaJIT - своевременный компилятор для Lua. Он использовался для встраивания или для общих целей. В версии 2.0 LuaJIT проект был переписан для лучшей оптимизации производительности.

История

Проект LuaJIT был запущен в 2005 году разработчиком Майком Полом и выпущен под лицензией MIT с открытым исходным кодом. Последний выпуск, 2.0.5, выпущен в 2017 году. С тех пор проект в настоящее время не поддерживается другими разработчиками, кроме участников.

Установка

LuaJIT является открытым исходным кодом, и для его использования проект должен быть скомпилирован. Репозиторий необходимо будет загрузить с помощью Git или других методов загрузки репозиториев. Затем он компилируется с помощью любого компилятора C, обычно с помощью GNU make , но доступны и другие варианты. Наконец, исполняемый файл LuaJIT и библиотека Lua 5.1 должны находиться в одном каталоге, чтобы можно было использовать компилятор LuaJIT.

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

Представление

По сравнению с другими средами выполнения Lua, LuaJIT часто является самым быстрым компилятором Lua.

Платформы

LuaJIT можно использовать в:

Его можно скомпилировать с помощью GCC , Clang или MSVC .

Примеры

Библиотеку FFi можно использовать для вызова функций C и использования структур данных C из Lua Code. LuaJIT предоставляет руководство по использованию этой библиотеки. Таким образом, существует несколько привязок LuaJIT к библиотекам C, которые используют библиотеку FFI. Этот пример вызовет функцию C printf из чистого кода Lua и выведет Hello world! .

local ffi = require("ffi")
ffi.cdef[[
int printf(const char *fmt, ...);
]]
ffi.C.printf("Hello world!\n")

Компилятор LuaJIT также добавил некоторые расширения в Lua C API. Этот пример, написанный на C ++ , будет использоваться для отладки .

#include <exception>
#include "lua.hpp"

// Catch C++ exceptions and convert them to Lua error messages.
// Customize as needed for your own exception classes.
static int wrap_exceptions(lua_State *L, lua_CFunction f)
{
  try {
    return f(L);  // Call wrapped function and return result.
  } catch (const char *s) {  // Catch and convert exceptions.
    lua_pushstring(L, s);
  } catch (std::exception& e) {
    lua_pushstring(L, e.what());
  } catch (...) {
    lua_pushliteral(L, "caught (...)");
  }
  return lua_error(L);  // Rethrow as a Lua error.
}

static int myinit(lua_State *L)
{
  ...
  // Define wrapper function and enable it.
  lua_pushlightuserdata(L, (void *)wrap_exceptions);
  luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC|LUAJIT_MODE_ON);
  lua_pop(L, 1);
  ...
}

Смотрите также

Примечания

использованная литература

дальнейшее чтение

внешние ссылки