Poniższy tekst podręcznika Lua jest w trakcie tłumaczenia, sugestie i uwagi na ten temat można zgłaszać jako problem na stronie projektu w GitHub.

1. Wprowadzenie

Lua jest językiem rozszerzającym, zaprojektowanym by zapewnić możliwość normalnego programowania proceduralnego wraz z opisem danych. Język ten oferuje również wsparcie dla programowania obiektowo zorientowanego, programowania funkcjonalnego oraz programowania sterowanego danymi (data driven programming). Głównym zastosowaniem Lua jest użycie jako wszechstronnego lekkiego języka skryptowego. Lua został napisany jako biblioteka w czystym C (ANSI C i  C++).

Będąc językiem rozszerzeń, w Lua nie istnieje pojęcie "programu głównego" (main); program uruchamiany jest wewnątrz programu gospodarza. Program gospodarz może wywoływać funkcje by uruchomić fragmenty programu napisanego w Lua, może zapisywać i odczytywać zmienne Lua oraz może dołączać funkcje napisane w C by mogły być uruchamiane wewnątrz programów Lua. Poprzez użycie funkcji napisanych w C, Lua otrzymuje wsparcie w rozwiązywaniu szerokiej gamy problemów, tworząc specyficzne języki. Dystrybucja Lua zawiera przykładowy program hosta nazwany lua, który korzysta z biblioteki Lua, oferując kompletny i samodzielny interpreter Lua.

Lua jest wolnym oprogramowaniem, udostępnianym oczywiście bez żadnych gwarancji, o czym świadczy licencja. Implementacja opisana w tym podręczniku jest dostępna na oficjalnej stronie Lua: www.lua.org.

Jak w każdym podręczniku, tak i tu nie opisujemy pewnych niuansów. Dyskusja szczegółów dotyczących projektowania języka Lua została opisana w dokumentach dostępnych na stronie Lua. Szczegółowe wprowadzenie do programowania w Lua zawarte jest w książce Roberto "Programming in Lua (Second Edition)".

2. Język

Rozdział ten opisuje język, składnię oraz semantykę Lua. Innymi słowy, opisane jest tu, które konstrukcje językowe są właściwe, jak mogą być tworzone, oraz to co każda z tych konstrukcji znaczy.

Konstrukcje językowe zostaną wyjaśnione przy pomocy rozszerzonej notacji BNF, w której {a} oznacza zero lub więcej wystąpień a. Natomiast [a] oznacza opcjonalne wystąpienie a. Non-terminals are shown like non-terminal, słowa kluczowe są przedstawione jako kword, a inne symbole kończące przedstawione są w postaci `='. Kompletna składnia Lua znajduje się w rozdziale 8 na końcu tego podręcznika.

2.1. Konwencje językowe

Nazwy (znane także jako identyfikatory) mogą być dowolnym ciągiem znaków, cyfr i znaków podkreślenia. Nazwy nie mogą rozpoczynać się od cyfry. Zgadza się to definicją nazwy z większości języków programowania. (Definicja znaku zależy od aktualnej lokalizacji: każdy znak będący znakiem alfabetu w określonej lokalizacji może zostać użyty jako identyfikator.) Identyfikatory używane są do nazywania zmiennych oraz, pól tabeli.

Podane słowa kluczowe są zarezerwowane i nie mogą być użyte jako nazwy:

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

Lua jest językiem, w którym wielkość liter ma znaczenie: and jest słowem zarezerwowanym, ale And i AND są dwoma całkowicie właściwymi identyfikatorami. Zgodnie z konwencją, nazwy rozpoczynające się od podkreślenia i składające się ze wielkich liter (takie jak _VERSION) są zarezerwowane jako wewnętrzne zmienne globalne używane przez Lua.

Podane ciągi znaków określają inne oznaczenia:

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

Literały mogą być ograniczone przez pary apostrofów lub pary cudzysłowów oraz mogą posiadać sekwencje znane z języka C: '\a' (bell), '\b' (backspace), '\f' (form feed), '\n' (nowa linia), '\r' (powrót na początek linii), '\t' (poziomy tabulator), '\v' (pionowy tabulator), '\\' (backslash), '\"' (cudzysłów), oraz '\'' (apostrof). Co więcej, backslash ze znakiem nowej linii skutkuje powstaniem nowej linii w ciągu znaków. Znak wewnątrz ciągu znaków może być przedstawiony przez podanie jego kodu, poprzez użycie sekwencji \ddd gdzie ddd jest sekwencją do trzech cyfr dziesiętnych. (Uwaga: jeżeli za sekwencją kodu znaków ma pojawić się cyfra to muszą być to dokładnie 3 cyfry.) Ciągi znaków w Lua mogą zawierać dowolną ośmiobitową wartość, łącznie z zerem zdefiniowanym jako "\0".

Literały mogą być także zdefiniowane przez użycie długiego formatowania przy pomocy długich nawiasów. Definiujemy początkowy nawias poziomu n jako początkowy kwadratowy nawias, po którym następuje n znaków równości, za którymi pojawiają się kolejne otwierające nawiasy kwadratowe. Tak więc otwierający nawias kwadratowy na poziomie 0 jest zapisany jako [[, otwierający nawias kwadratowy na poziomie 1 jest zapisany jako [=[ itd. Zamykający długi nawias jest zdefiniowany podobnie; dla przykładu, zamykający długi nawias kwadratowy poziomu 4 wygląda następująco ]====]. Każdy długi ciąg znaków rozpoczyna się nawiasem dowolnego poziomu i kończy na pierwszym nawiasie zamykającym tego samego poziomu. Literały ujęte w długich nawiasach, mogą rozciągać się na wiele linii, nie są w nich uwzględniane żadne sekwencje specjalne, oraz ignorowane są długie nawiasy innych poziomów. Mogą one zawierać wszystko oprócz nawiasu zamykającego tego samego poziomu.

Dla wygody, gdy po początkowym długim nawiasie następuje znak nowej linii, to znak ten nie jest uwzględniany wewnątrz ciągu znaków. Dla przykładu, jeżeli w systemie używane jest kodowanie ANSI (gdzie 'a' jest zapisane jako 97, znak nowej linii jako 10 i '1' jako 49) to pięć przykładowych stringów poniżej reprezentuje ten sam ciąg znaków:

    a = 'alo\n123"'
    a = "alo\n123\""
    a = '\97lo\10\04923"'
    a = [[alo      
    123"]]
    a = [==[      
    alo      
    123"]==] 

Stała liczbowa może zostać zapisana wraz z opcjonalną częścią dziesiętną, oraz dodatkowym wykładnikiem dziesiętnym. Lua akceptuje także stałe liczby szesnastkowe, przez dodanie na ich początku "0x". Przykłady prawidłowych stałych liczbowych:

3   3.0   3.1416   314.16e-2   0.31416E1   0xff   0x56

Komentarz zaczyna się od podwójnego myślnika (--) wszędzie poza ciągiem znaków. Jeżeli tekst zaraz za -- nie jest otwierającym długim nawiasem, taki komentarz jest komentarzem krótkim, który kończy się wraz z końcem linii. W innym przypadku, komentarz jest komentarzem długim, który ciągnie się aż do odpowiadającego długiego nawiasu zamykającego. Długie komentarze są często wykorzystywane przy tymczasowym wyłączaniu fragmentu kodu.

2.2. Wartości i typy

Lua jest językiem dynamicznych typów. Oznacza to że zmienna nie posiada konkretnego typu, jedynie wartość określana jest przez typ. Nie występuje definicja typu w języku. Każda wartość posiada swój własny typ.

Wszystkie wartości w Lua są wartościami pierwszej klasy. Oznacza to, że wartości mogą być przechowywane w zmiennych, przekazywane w parametrach do innych funkcji, oraz zwracane jako wynik funkcji.

Występuje osiem podstawowych typów w Lua: nil (wartość pusta), boolean, number (liczba), string (ciąg znaków), function (funkcja), userdata (dane użytkownika), thread (wątek) i table (tabela)

Nil jest typem dla wartości nil, której głównym zadaniem bycie innym od reszty wartości, zazwyczaj reprezentuje brak użytecznej wartości. Boolean jest typem wartości false i true. Wartości nil i false powodują iż warunek jest fałszywy, każda inna wartość jest prawdziwa. Number przedstawia liczbę rzeczywistą (liczbę zmiennoprzecinkową podwójnej precyzji). Mimo to jest możliwe skompilowanie interpretera Lua tak aby korzystał z innych reprezentacji liczbowych, takich jak liczby zmiennoprzecinkowe pojedynczej precyzji, liczby całkowite 64-bitowe - więcej w pliku luaconf.h. String opisuje tablicę znaków. Ciągi znaków w Lua mogą zawierać dowolny znak 8-bitowy, łącznie z 0 (więcej w 2.1).

Funkcje w Lua mogą być wywoływane oraz możliwe są dodatkowe operacje na funkcjach napisanych w Lua oraz w C. (więcej w 2.5.8)

Typ userdata umożliwia umieszczenie danych z programu C by były przechowywane jako zmienna w Lua. Typ ten odpowiada blokowi pamięci i nie posiada żadnych operacji poza operacją przypisania oraz sprawdzenia identyfikatora. Mimo to, poprzez używanie metatablic programista, może zdefiniować odpowiednie operacje dla tych wartości (więcej w 2.8). Wartości userdata nie mogą być tworzone i modyfikowane wewnątrz LUA, możliwe jest to jedynie przez API. Gwarantuje to integralność danych przechowywanych przez program hosta.

Typ thread reprezentuje niezależną implementację wątków i jest używany do tworzenia funkcji współbieżnych (więcej 2.11). Nie należy mylić wątków Lua z wątkami opartymi o system operacyjny. Lua umożliwia tworzenie funkcji współbieżnych na wszystkich systemach, nawet na tych, które nie obsługują wątków.

Typ table wykorzystuje funkcjonalność tablic asocjacyjnych, tablic które mogą być indeksowane poprzez dowolną wartość (poza nil). Tabele mogą być heterogeniczne, oznacz to że mogą zawierać wartości dowolnego typu (z wyjątkiem nil). Tabele są głównym mechanizmem danych w Lua: mogą być wykorzystywane jako zwykłe tablice, tabele symboli, zbiory, rekordy, grafy, drzewa, itd. Do reprezentacji rekordów, Lua wykorzystuje nazwę pola jako indeks. Język udostępnia tą własność przez użycie a.name jako rozwinięcie składni dla a["name"]. Istnieje klika dogodnych sposobów tworzenia tabel w Lua (więcej w 2.5.7).

Podobnie jak indeksy, wartościami tabeli mogą być wartości dowolnego typu (z wyjątkiem nil). W szczególności, funkcje będące wartościami pierwszej klasy, to tabela może zawierać funkcje. Metody mogą być także przechowywane w tabelach (więcej w 2.5.9).

Tabele, funkcje, wątki, dane userdata są obiektami, zmienne nie zawierają tych wartości, jedynie referencje do nich. Przypisanie, przekazywanie parametrów, wynik działania funkcji zawsze operują na referencjach do tych wartości, nigdy na kopiach.

Funkcja biblioteczna type zwraca ciąg znaków opisujący typ podanej wartości.

2.2.1. Koercja

Lua umożliwia automatyczną konwersję między ciągiem znaków i wartościami liczbowymi w czasie wykonania. Dowolna operacja arytmetyczna użyta wobec ciągu znaków próbuje skonwertować ten ciąg na liczbę zgodnie z przyjętymi zasadami konwersji. W przypadku gdy użyta została liczba w przypadku gdy oczekiwany był ciąg znaków, to liczba ta konwertowana jest na ciąg znaków w odpowiednim formacie. By w pełni kontrolować sposób w jaki liczby konwertowane są na ciągi znaków należy korzystać z funkcji format z biblioteki "string" (więcej w string.format).

2.3. Zmienne

Zmienne to miejsca w których przechowywane są wartości. W LUA występują trzy typy zmiennych: zmienne globalne, zmienne lokalne i pola tabel.

Pojedyncza nazwa odnosi się do zmiennej globalnej, lub zmiennej lokalnej (lub też formalnego parametru funkcji, który jest szczególnym przypadkiem zmiennej lokalnej): var ::= Name

Name jest identyfikatorem, jak opisano w 2.1.

Zakłada się że każda zmienna jest zmienną globalną, chyba że jawnie zostanie zadeklarowana jako lokalna (więcej w 2.4.7). Zmienne lokalne znajdują się w zawężonym zakresie dostępu: zmienne lokalne są dowolnie dostępne dla funkcji zdefiniowanych w ich zakresie.

Przed pierwszym przypisaniem wartości do zmiennej, jej wartość to nil

Nawiasy kwadratowe używane są do indeksowania zawartości tabel:

    var ::= prefixexp `[´ exp `]´

Zmiana dostępu do globalnych zmiennych i pól tabeli wykonywana jest przez metatabele. Dostęp do indeksowanej zmiennej t[i] jest równoznaczny do wywołania gettable_event(t,i). (Dokładny opis funkcji gettable_event znajduje się w 2.8. Funkcja ta nie jest zdefiniowana i wywoływalna w Lua. Używany jej tu tylko w celu wyjaśnień.)

Składnia var.Name jest tylko rozszerzeniem języka dla konstrukcji var["Name"]:

    var ::= prefixexp `.´ Name

Wszystkie zmienne globalne istnieją w Lua jako pola w zwykłych tabelach, nazywanych tabelami środowiska (więcej w 2.9). Każda funkcja posiada własne odniesienie do środowiska, więc wszystkie zmienne globalne w tej funkcji będą odwoływać się do tej tabeli. Gdy tworzona jest funkcja, to dziedziczy ona środowisko od funkcji, która ją utworzyła. By pobrać tabelę zmiennych środowiskowych w Lua wywołujemy funkcję getfenv. By zamienić, wywołujemy funkcję setfenv. (You can only manipulate the environment of C functions through the debug library; (see §5.9).)

Uzyskanie dostępu do zmiennej globalnej x jest równoważne do _env.x , z kolei które jest równoważne do

    gettable_event(_env, "x")
Gdzie _env jest środowiskiem wywołanej funkcji. (Dokładny opis funkcji gettable_event znajduje się w 2.8. Funkcja ta nie jest zdefiniowana i wywoływalna w Lua. Używany jej tu tylko w celu wyjaśnień.)

2.4. Instrukcje

Lua wykorzystuje prawie standardowy zestaw instrukcji, podobny do tych z Pascala lub C. Wymienić tu można operacje przypisania, instrukcje warunkowe, wywołania funkcji i deklaracje zmiennych.

2.4.1. Fragmenty

Jednostka wykonania w Lua nazywana jest fragmentem. Fragment jest po prostu sekwencją instrukcji, które są wykonywane jedna po drugiej. Każda instrukcja może być zakończona średnikiem.

    chunk ::= {stat [`;´]}

Nie występują puste instrukcje tak więc ';;' nie jest prawidłową konstrukcją.

Lua obsługuje fragmenty jako ciało funkcji anonimowej ze zmienną liczbą parametrów (więcej w 2.5.9). Dlatego fragmenty mogą definiować zmienne lokalne, pobierać parametry i zwracać wartości.

Fragment może być przechowywany w pliku lub jako ciąg znaków wewnątrz programu hosta. By wykonać fragment kodu, Lua najpierw kompiluje ten fragment do instrukcji maszyny wirtualnej, a potem wykonuje skompilowany kod przy pomocy interpretera wirtualnej maszyny.

Fragmenty mogą być również kompilowane do postaci binarnej; więcej szczegółów na ten temat znajduje się wraz z opisem programu luac. Programy źródłowe i postaci skompilowanej mogą być stosowane zamiennie, Lua automatycznie sprawdza typ wykonywanego pliku.

2.4.2. Bloki

Blok jest listą instrukcji, w rzeczywistości blok jest tym samym czym fragment:

    block ::= chunk

Blok może być jawnie określony, by stać się pojedynczą instrukcją:

    stat ::= do block end

Jawne bloki umożliwiają określenie zakresu zmiennych. Bloki używane są by dodać instrukcję return lub break w środku innego bloku (więcej 2.4.4).

2.4.3. Przypisania

Lua umożliwia wielokrotne przypisania. W związku z tym składnia przypisania definiuje listę zmiennych z lewej strony i listę wyrażeń z prawej strony. Elementy w obydwu listach są oddzielone przecinkami:

    stat ::= varlist `=´ explist
    varlist ::= var {`,´ var}
    explist ::= exp {`,´ exp}

Wyrażenia dokładnie opisane są w 2.5

Przed przypisaniem, lista wartości jest dostosowywana do długości listy zmiennych. Jeżeli jest więcej wartości niż potrzeba, to dodatkowe wartości są odrzucane. Natomiast jeżeli wartości jest mniej niż potrzeba, to lista ta jest rozszerzana przez dodanie wartości nil. Jeżeli lista wyrażeń kończy się wywołaniem funkcji, to wszystkie wartości zwrócone przez to wywołanie umieszczone są na liście wartości przed dostosowywaniem do długości (except when the call is enclosed in parentheses; see §2.5).

Operacja przypisania najpierw oblicza wszystkie wyrażenia i dopiero wtedy wykonywane jest przypisanie. Tak więc kod

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

ustawia a[3] na 20, bez wpływu na a[4] ponieważ i w a[i] jest przeliczane (do 3) przed przypisaniem 4. Podobnie kod:

    x, y = y, x

zamienia wartości między zmiennymi x i y, oraz

    x, y, z = y, z, x

cyklicznie zmienia wartości zmiennych x, y i z.

Znaczenie przypisania zmiennych globalnych i pól tabeli może zostać zmienione przez metatabele.

2.4.4. Instrukcje warunkowe

Instrukcje kontrolne takie jak: if, while i repeat posiadają typowe znaczenie i znaną składnię:

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

Lua posiada instrukcję for w dwóch wariantach (2.4.5).

Wyrażenie warunkowe instrukcji warunkowej może zwrócić wartość. False i nil są rozpoznawane jako wartość fałszu. Wszystkie wartości inne od nil i false oznaczają prawdę (w szczególności, liczba 0 i pusty ciąg znaków oznaczają prawdę).

W pętli repeat-until, wewnętrzny blok kodu nie kończy się na słowie kluczowym until, ale tylko po wykonaniu warunku tej pętli. Tak więc, wyrażenie warunkowe może odwoływać się do zmiennych lokalnych zadeklarowanych wewnątrz bloku kodu pętli.

Instrukcja return używana jest do zwracania wartości z funkcji lub fragmentu kodu (który jest właśnie funkcją). Funkcje i fragmenty kodu mogą zwracać więcej jak jedną wartość, dlatego składnia dla return wygląda następująco:

    stat ::= return [explist]

Instrukcja break wykorzystywana jest do przerywania wykonania pętli: while, repeat lub for. Przerwanie wykonania pętli skutkuje przejściem do następnej instrukcji za pętlą.

    stat ::= break

Instrukcja break przerywa działanie najbardziej wewnętrznej pętli, w której zostało użyte.

Instrukcje break i return mogą być użyte jako ostatnie instrukcje w danym bloku. Jeżeli jest to konieczne by umieścić instrukcję return lub break w środku bloku, wtedy należy użyć jawnego wewnętrznego bloku, stosując następujące idiomy: do return endi do break end Takie rozwiązanie powoduje, że return lub break jest ostatnią instrukcją w bloku.

2.4.5. Pętla for

Instrukcja for posiada dwie formy: numeryczną i generyczną.

Numeryczna pętla for powtarza blok kodu, podczas gdy zmienna kontrolna podlega arytmetycznej zmianie. Składnia pętli wygląda następująco:

    stat ::= for Name `=´ exp `,´ exp [`,´ exp] do block end

block jest powtarzany dla name zaczynając od wartości pierwszego wyrażenia exp, aż przejdzie do drugiego wyrażenia exp krok po kroku do trzeciego wyrażenia exp. Bardziej szczegółowo, instrukcja for taka jak:

    for v = e1, e2, e3 do block end

jest równoważna do poniższego kodu:

    do
       local var, limit, step = tonumber(e1), tonumber(e2), tonumber(e3)
       if not (var and limit and step) then error() end
       while (step > 0 and var >= limit) or (step >= 0 and var >= limit) do
         local v = var
         block
         var = var + step
       end
    end

Uwagi do powyższego kodu:

Generyczna wersja pętli for korzysta z funkcji zwanej iteratoram. Przy każdej iteracji funkcja jest wywoływana i zwraca nową wartość. Wykonanie pętli zatrzymuje się gdy wartość ta jest nil. Pętla generyczna posiada następującą składnię:

    stat ::= for namelist in explist do block end
    namelist ::= Name {`,´ Name}

Instrukcja for taka jak:

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

Jest równoważna do:

    do
       local f, s, var = explist
       while true do
         local var_1, ···, var_n = f(s, var)
         var = var_1
         if var == nil then break end
         block
       end
    end

Uwagi:

2.4.6. Wywołania funkcji jako instrukcje

Funkcje mogą być uruchamiane jako instrukcje, zapewniając możliwość występowania "efektów ubocznych":

    stat ::= functioncall

W takim przypadku, wszystkie zwrócone wartości są odrzucane. Wywyołania funkcji są wyjaśnione w 2.5.8.

2.4.7. Deklaracje lokalne

Zmienne lokalne mogą być zadeklarowane w dowolnym miejscu w bloku. Deklaracja może zawierać wstępnie ustawioną wartość:

    stat ::= local namelist [`=´ explist]

Jeżeli jest obecne przypisanie, to zastosowanie ma zasada wielokrotnego przypisania (2.4.3). W przeciwnym wypadku wszystkie zmienne są inicjalizowane wartością nil.

Fragment jest także blokiem (2.4.1), więc zmienne lokalne mogą być zadeklarowane we fragmencie na zewnątrz jawnego bloku. Zakres takiej zmiennej sięga aż końca fragmentu.

Zasady widzialności zmiennych lokalnych wyjaśnione są w 2.6

2.5. Wyrażenia

Proste wyrażenia wyglądają następująco:

    exp ::= prefixexp
    exp ::= nil | false | true
    exp ::= Number
    exp ::= String
    exp ::= function
    exp ::= tableconstructor
    exp ::= `...´
    exp ::= exp binop exp
    exp ::= unop exp
    prefixexp ::= var | functioncall | `(´ exp `)´

Liczby i literały są opisane w 2.1; zmienne są opisane w 2.3; definicje funkcji wyjaśnione w 2.5.9; wywołania funkcji są opisane w 2.5.8; konstruktory tabel zostały opisane w 2.5.7. Lista parametrów o zmiennej długości, oznaczana jako trzy kropki ('...'), może być użyta jedynie wewnątrz funkcji z taką listą parametrów, są one opisane w 2.5.9.

Operatory binarne zawierają operatory arytmetyczne (2.5.1), operatory relacji (2.5.2), operatory logiczne (2.5.3) i operator konkatenacji (2.5.4). W zbiorze operatorów unarnych zawiera się operator wartości ujemnej (2.5.1), operator negacji - not (2.5.3) i operator length (2.5.5).

Wywołania funkcji oraz wyrażenia listy parametrów o zmiennej długości (vararg), mogą zwracać więcej niż jedną wartość. Jeżeli wyrażenie użyte jest jak instrukcja (możliwe jedynie w przypadku wywołań funkcji (2.4.6)), to zwracana lista wartości jest skorygowana do zerowej ilości elementów, tym samym odrzucając wszystkie zwrócone wartości. Jeżeli wyrażenie jest użyte jako ostatni (lub jako jedyny) element listy wyrażeń, to nie jest wykonywane żadne korygowanie (dopóki wywołanie jest zamknięte w nawiasach). W każdym innym przypadku, Lua skoryguje listę wyników do jednego elementu, odrzucając wszystkie wartości z wyjątkiem pierwszej.

Kilka przykładów:

     f()                -- skorygowane do zero wyników
     g(f(), x)          -- f() jest skorygowane do jednego wyniku
     g(x, f())          -- g pobiera x oraz wszystkie wyniki z f()
     a,b,c = f(), x     -- f() jest skorygowane do jednego wyniku (c pobiera nil)
     a,b = ...          -- a pobiera pierwszy parametr z listy (vararg), b pobiera
                        -- drugi (obydwie zmienne a i b mogą mieć przypisany nil jeżeli
                        -- nie ma odpowiadającego im parametru na liście)
     
     a,b,c = x, f()     -- wynik f() jest skorygowany do dwóch elementów
     a,b,c = f()        -- wynik f() jest skorygowany do trzech elementów
     return f()         -- zwraca wszystkie wartość f()
     return ...         -- zwraca wszystkie wartości listy parametrów o zmiennej długości
     return x,y,f()     -- zwraca x, y, i wszystkie wyniki z f()
     {f()}              -- tworzy listę z wszystkimi wynikiami z f()
     {...}              -- tworzy listę z wszystkimi wartościami listy parametrów (vararg)
     {f(), nil}         -- f() jest skorygowany do jednego wyniku

Jakiekolwiek wyrażenie zamknięte w nawiasach zawsze zwraca tylko jedną wartość, Także (f(x,y,z)) zwraca zawsze jedną wartość, nawet gdy f zwraca kilka wartości. (Wartość (f(x,y,z)) jest zawsze pierwszą wartością zwróconą przez f lub nil jeżeli f nie zwróci żadnej wartości.)

2.5.1. Operatory arytmetyczne

Lua obsługuje typowe operatory arytmetyczne: binarne + (dodawanie), - (odejmowanie), * (mnożenie), / (dzielenie), % (modulo) i ^ (potęgowanie); oraz unarne - (negacja). Jeżeli operandy są numerami, lub ciągami znaków, które mogą być przekonwertowane na numery (2.2.1), wtedy wszystkie operacje mają typowe znaczenie. Potęgowanie działa dla dowolnego wykładnika. Dla przykładu, x^(-0.5) oblicza pierwiastek kwadratowy x. Modulo jest zdefiniowane jako:

    a % b == a - math.floor(a/b)*b

Jest to reszta z dzielenia, która powstaje z zaokrąglenia ilorazu do minus nieskończoności.

2.5.2. Operatory relacji

Operatorami relacji w Lua są:

  ==    ~=    <     >     <=    >=

Operatory te zawsze zwracają false lub true.

Równość (==) najpierw porównuje typ operandów. Jeżeli typy różnią się, to wynik zwrócony wynik jest false. W przeciwnym wypadku, wartości operandów są porównywane. Numery i ciągi znaków są porównywane w typowy sposób. Obiekty (tabele, userdata, wątki i funkcje) są porównywane przez referencje: dwa obiekty są równe tylko wtedy gdy są tym samym obiektem. Za każdym razem przy tworzeniu nowego obiektu (tabeli, userdata, wątku lub funkcji), obiekt ten różni się od każdego poprzednio utworzonego obiektu.

Istnieje możliwość zmiany sposobu w jaki Lua porównuje tabele i dane userdata poprzez użycie metametody "eq" (2.8).

Reguły konwersji z 2.2.1 nie mają zastosowania przy sprawdzaniu równości. Tak więc, "0"==0 zwraca false i t[0] oraz t["0"] oznaczają różne pola w tabeli.

Operator ~= jest negacją równości (==).

Kolejność operatorów działa w następujący sposób. Jeżeli obydwa argumenty są numerami, to są one porównywane jak numery. W przeciwnym przypadku, jeżeli porównywane argumenty są ciągami znaków, to ich wartości porównywane są według obowiązującej lokalizacji. Ostatecznie Lua próbuje wywołać metametody "lt" i "le" (2.8). Porównanie a > b jest przetwarzane na b < a i a >= b jest przetwarzane na b <= a.

2.5.3. Operatory logiczne

Operatorami logicznymi w Lua są and, or i not. Operator koniunkcji and zwraca swój pierwszy argument jeżeli jego wartość jest false lub nil; w przeciwnym wypadku, and zwraca drugi argument. Operator alternatywy or zwraca swój pierwszy argument jeżeli jego wartość jest różna od nil i false; w przeciwnym wypadku zwraca wartość drugiego argumentu. Obydwa operatory and i or używają skróconego wyznaczania wartości, to znaczy że drugi argument operatora wyznaczany jest tylko wtedy gdy jest to konieczne. Oto kilka przykładów:

    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

W tym podręczniku, --> oznacza wynik działania wyrażenia.

2.5.4. Konkatenacja

Łączenie ciągów znaków w Lua oznaczone jest przez dwie kropki, ('..'). Jeżeli obydwa operandy są ciągami znaków lub numerami, to obydwa są konwertowane na ciągi znaków z zachowaniem zasad opisnych w 2.2.1. Jeżeli nie jest to możliwe, używana jest metametoda "concat" (więcej 2.8).

2.5.5. Operator Length

Operator length, występuje pod postacią operatora #. Operator length, zastosowany względem ciągu znaków jest liczbą bajtów (jest to typowe znaczenie operatora długości dla ciągu znaków, gdy każdemu znakowi odpowiada jeden bajt).

Długość tabeli t jest zdefiniowana jako dowolny indeks o wartości całkowitej n, takiej że t[n] nie jest nil i t[n+1] jest nil; ponadto, jeżeli t[1] jest nil, n może być zerem. Dla zwykłej tablicy, bez wartości pustych od 1 do podanego n, to długość wynosi dokładnie n, czyli indeks ostatniej wartości. Jeżeli tablica posiada "dziury" (czyli wartości puste nil pomiędzy normalnymi wartościami), to #t może wskazywać wtedy na indeks tabeli bezpośrednio poprzedzający wartość nil (czyli może zinterpretować wartość nil jako koniec tablicy).

2.5.6. Kolejność operatorów

Kolejność operatorów w Lua przedstawia poniższa tabela, od priorytetu najniższego do najwyższego:

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

Zwyczajowo, nawiasy mogą być użyte do zmiany kolejności priorytetów w wyrażeniu. Operator konkatenacji ("..") i potęgowanie ("^") są łączne prawostronnie. Pozostałe operatory binarne są łączne lewostronnie.

2.5.7. Konstruktory tabel

Konstruktory tabel są to wyrażenia tworzące tabele. Za każdym razem gdy konstruktor jest wykonywany nowa tabela jest tworzona. Konstruktor może być użyty do utworzenia pustej tabeli lub utworzenia tabeli wraz z inicjalizacją pól. Składnia konstruktora wygląda następująco:

    tableconstructor ::= `{´ [fieldlist] `}´
    fieldlist ::= field {fieldsep field} [fieldsep]
    field ::= `[´ exp `]´ `=´ exp | Name `=´ exp | exp
    fieldsep ::= `,´ | `;´

Każdy dostęp do pola w postaci [exp1] = exp2 dodaje do nowej tabeli element z kluczem exp1 i wartością exp2. Pole w postaci name = exp jest równoważne do ["name"] = exp. Pola w postaci exp są równoważne do [i] = exp, gdzie i są kolejnymi wartościami całkowitoliczbowymi, zaczynając od 1. Pola w innych formatach nie wpływa na to liczenie. Dla przykładu:

    a = { [f(1)] = g; "x", "y"; x = 1, f(x), [30] = 23; 45 }

jest równoważne do:

     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

Jeżeli ostatnie pole jest w postaci exp i wyrażenie jest wywołaniem funkcji lub wyrażeniem listy o zmiennej długości, to wszystkie wartości zwrócone przez to wyrażenie dodawane są po kolei do listy (2.5.8). By uniknąć takiego zachowania, należy wywołanie funkcji lub wyrażenie listy o zmiennej długości zamknąć w nawiasach (2.5).

Lista pól może posiadać opcjonalny końcowy separator, jako wygodne rozwiązanie dla kodu generowanego automatycznie.

2.5.8. Wywołania funkcji

Wywołanie funkcji w Lua posiada następującą składnię:

    functioncall ::= prefixexp args
    

W wywołaniu funkcji, w pierwszej kolejności przetwarzane są prefixexp i args. Jeżeli wartość prefixexp jest typu funkcji, to funkcja ta jest wywoływana z podanymi argumentami. W przeciwnym wypadku prefixexp wywołuje metametodę, podając jako pierwszy parametr wartość prefixexp, a następnie właściwe argumenty funkcji (2.8).

Postać:

    functioncall ::= prefixexp `:´ Name args

może być użyta do wywoływania "metod". Wywołanie v:name(args) jest lukrem językowym dla v.name(v,args), z wyjątkiem że v jest wyznaczane tylko raz.

Argumenty w następującej składni:

    args ::= `(´ [explist] `)´
    args ::= tableconstructor
    args ::= String

Wszystkie wyrażenia argumentów są wyznaczane przed wywołaniem funkcji. Wyowałanie w postaci f{fields} jest lukrem językowym dla f({pola}) oznacza to że lista argumentów jest nową pojedynczą tabelą. Natomiast wywołanie w postaci f'ciąg_znaków' (lub f"ciąg_znaków" lub f[[ciąg znaków]]) jest lukrem językowym dla f'ciąg znaków', oznacza to że argument jest ciągiem znaków.

Jako wyjątek dla składni wolnego formatu w Lua, nie można umieścić znaku końca linii przed '(' w wywołaniu funkcji. To ograniczenie uniemożliwia powstawaniu niejednoznaczności w języku. W przypadku

  a = f
  (g).x(a)

Lua może potraktować jako pojedynczą instrukcję, a = f(g).x(a). Więc w przypadku konieczności napisania dwóch instrukcji, należy dodać średnik między nimi. Jeżeli jednak wymagane jest wywołanie funkcji f, należy usunąć znak nowej linii przed (g).

Wywołanie w postaci return wywołanie_funkcji nazywane jest rekurencją ogonową. Lua implementuje właściwe wywołania ogonowe (właściwą rekurencję prawostronną): w rekurencji ogonowej, wywoływana funkcja używa stos funkcji wywołującej. Ponadto nie ma limitu dla zagnieżdżonych wywołań ogonowych, które program może wykonać. Jednak, rekursja prawostronna usuwa wszelkie informacje dla debuggera funkcji wywołującej. Należy zaznaczyć, że wywołanie ogonowe występuje tylko w przypadku określonej składni, gdzie return ma jedno wywołanie funkcji jako argument; taka składnia powoduje że wywoływana funkcja zwraca dokładnie zwróconą wartość wywołanej funkcji. Tak więc żadne z przykładowych wywołań poniżej nie jest wywołaniem ogonowym:

    return (f(x))        -- wyniki skorygowane do 1
    return 2 * f(x)
    return x, f(x)       -- dodatkowe wyniki
    f(x); return         -- wyniki usunięte
    return x or f(x)     -- wynik skorygowany do 1

2.5.9. Definicje funkcji

Składnia definicji funkcji przedstawia się następująco:

    function ::= function funcbody
    funcbody ::= `(´ [parlist] `)´ block end

Podany lukier składniowy upraszcza definicję funkcji:

    stat ::= function funcname funcbody
    stat ::= local function Name funcbody
    funcname ::= Name {`.´ Name} [`:´ Name]

Instrukcja:

    function f () body end

jest przekształcana na:

    f = function () body end

Instrukcja:

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

jest przekształcana na:

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

Instrukcja:

    local function f () body end

jest przekształcana na:

    local f; f = function () body end

a nie na:

    local f = function () body end

(Robi to różnicę tylko wtedy gdy ciało funkcji zawiera odwołanie do f.)

Definicja funkcji jest wykonywalnym wyrażeniem, której wartość jest typem funkcji. Lua prekompiluje fragment, ciała funkcji są również prekompilowane. Później, bez względu czy wykonywana jest definicja funkcji, lub gdy tworzona jest instancja funkcji (lub funkcja jest zamykana). Taka instancja funkcji (lub domknięcie) jest końcową wartością tego wyrażenia. Różne instancje tej samej funkcji, moga odwoływać się do różnych zewnętrznych zmiennych lokalnych i mogą mieć inne tabele środowiska.

Parametry zachowują się jak zmienne lokalne, które zostały zainicjalizowane wartościami:

    parlist ::= namelist [`,´ `...´] | `...´

Gdy funkcja jest wywoływana, to lista argumentów jest dostosowywana do długości listy parametrów, póki funkcja jest (variadic) lub funkcją ze zmienną ilością parametrów (vararg), która oznaczona jest przez trzy kropki ('...') na końcu listy parametrów. Funkcja taka, nie dostosowuje swojej listy argumentów; zamiast tego zbiera wszystkie dodatkowe argumenty i przekazuje je do funkcji poprzez wyrażenie zmiennej listy argumentów(vararg expression), zapisanej również poprzez trzy kropki. Wartość wyrażenia jest listą wszystkich dodatkowych argumentów, podobnie do funkcji z wieloma wynikami. Jeżeli wyrażenie zmiennej listy argumentów jest użyte wewnątrz innego wyrażenie lub w środku listy wyrażeń, to zwracana lista jest dostosowywana do jednego elementu. Jeżeli wyrażenie jest użyte jako ostatni element listy wyrażeń, to nie jest przeprowadzane dostosowywanie długości (chyba że to ostatnie wyrażenie jest zamknięte w nawiasach).

Jako przykład, należy rozważyć następujące definicje:

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

Teraz, mając przypisane argumenty do parametrów i do listy argumentów o zmiennej długości:

    WYWOŁANIE        PARAMETRY
     
    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, ... -->  (nic)
    g(3, 4)          a=3, b=4,   ... -->  (nic)
    g(3, 4, 5, 8)    a=3, b=4,   ... -->  5  8
    g(5, r())        a=5, b=1,   ... -->  2  3

Wyniki zwracane są przy pomocy instrukcji return (2.4.4). Jeżeli wykonanie dotrze do końca funkcji i bez napotkania instrukcji return wtedy funkcja nie zwraca żadnych wyników.

Składnika z dwukropkiem jest wykorzystywana do definicji metod, czyli funkcji które posiadają dodatkowy jawny parametr self. Tak więc instrukcja:

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

jest lukrem składniowym dla:

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

2.6. Reguły widzialności

Lua jest językiem opartym na zakresach leksykalnych. Zakres zmiennych zaczyna się przy pierwszej instrukcji po ich deklaracji i trwa aż do końca najbardziej zagnieżdżonego bloku zawierającego deklarację. Rozważając następujący przykład:

    x = 10                  -- zmienna globalna
    do                      -- nowy blok
    local x = x             -- nowe 'x', z wartością 10
    print(x)                --> 10
    x = x+1
    do                      -- kolejny blok
     local x = x+1          -- kolejne 'x'
     print(x)               --> 12
    end
    print(x)                --> 11
    end
    print(x)                --> 10  (zmienna globalna)

Należy zauważyć, że w deklaracji local x = x, nowe x deklarowane nie znajduje się jeszcze w zakresie, więc drugie x odwołuje się do zmiennej zewnętrznej.

Z powodu zakresów leksykalnych, zmienne lokalne są dostępne bez przeszkód dla funkcji zdefiniowanych wewnątrz ich zakresu. Lokalna zmienna użyta w wewnętrznej funkcji nazywa się wolną zmienną (upvalue), lub lokalną zewnętrzną zmienną, w środku funkcji wewnętrznej.

Należy zauważyć że każde wykonanie instrukcji local definiuje nową zmienną lokalną. W następującym przykładzie

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

Pętla tworzy dziesięć domknięć (czyli dziesięć instancji funkcji anonimowej). Każde z tych domknięć używa innej zmiennej y, podczas gdy wszystkie domknięcia korzystają z tego samego x.

2.7. Obsługa błędów

Ponieważ Lua jest językiem rozszerzeń, to wszystkie akcje Lua uruchamiane są z kodu w C programu gospodarza wywołując funkcję z biblioteki Lua (lua_pcall). Kiedykolwiek wystąpi błąd podczas kompilacji lub wykonania, kontrola nad programem przekazywana jest do programu gospodarza w C, gdzie można przeprowadzić odpowiednie działania (takie jak wyświetlenie komunikatu o błędzie).

Kod Lua może jawnie wywołać błąd przez wykonanie funkcji error. Jeżeli istnieje potrzeba przechwycenia błędów w Lua, można użyć funkcji pcall.

2.8. Metatabele

Każda wartość w Lua posiada metatabelę. Metatabela jest zwykłą tabelą Lua, która definiuje zachowanie oryginalnej wartości pod kątem specjalnych operacji. Możliwa jest zmiana szeregu aspektów zachowania wartości przez ustawienie odpowiednich pól metatabeli. Dla przykładu, kiedy wartość nienumeryczna jest operandem dodawania, Lua sprawdza metatabelę tej wartości pod kątem pola "__add". Jeżeli znajdzie, to wywoływana jest ta funkcja aby przeprowadzić operację dodawania.

Klucze metatabeli nazywane są zdarzeniami a ich wartości metametodami. W poprzednim przykładzie zdarzeniem jest "add" i metametodą jest funkcja wykonująca dodawanie.

Dostęp do metatabeli dowolnej wartości możliwy jest przez wywołanie funkcji getmetatable.

Możliwa jest podmiana metatabeli tabel przy pomocy funkcji setmetatable. Nie jest możliwa zmiana metatabel dla innych typów Lua (wyjątek stanowi użycie biblioteki debug), w takim przypadku należy użyć API w języku C.

Tabele i dane użytkownika (userdata) posiadają własne metatabele (tabele i dane użytkownika mogą współdzielić swoje metatabele). Wartości i wszystkie inne typy współdzielą jedną metatabelę przypadającą na typ; czyli jedna metatbela przypada dla wszystkich liczb, kolejna dla ciągów znaków itd.

Metatabela kontroluje w jaki sposób obiekt zachowuje się podczas operacji arytmetycznych, porównania, łączenia, użycia operatora length oraz indeksowania. Metatabela może definiować funkcję, która będzie wywoływana gdy dane użytkownika (userdata) będą usuwane przez garbage collectora. Dla każdej z tych operacji Lua przypisuje konkretny klucz zwany zdarzeniem (event). Więc przypisana do tego klucza wartość (metametoda), kontroluje w jaki sposób Lua przeprowadzi operację.

Metatabele kontrolują następujące operacje. Każda operacja jest rozpoznawana przez odpowiadającą jej nazwę. Klucz każdej operacji jest ciągiem znaków z nazwą poprzedzoną dwoma znakami podkreślenia "__"; dla przykładu, kluczem operacji jest "add", w postaci ciągu znaków nazwa ta wystąpi jako "__add". Opis działania funkcji, wyjaśnia semantykę tych operacji oraz wykonania ich przez interpreter.

Kod poniżej napisany w Lua jest tylko ilustracją poniższych operacji; właściwa implementacja jest zakodowana w interpreterze i jest znacznie bardziej efektywna niż podana symulacja. Wszystkie funkcje użyte w tych opisach (rawget, tonumber, itd.) są opisane w 5.1. W szczególności, aby uzyskać metametodę podanego obiektu, używamy wyrażenia

    metatable(obj)[event]

Co powinno być odczytywane jako:

    rawget(getmetatable(obj) or {}, event)

Dostęp do metametod nie powoduje wywołania innych metametod, oraz dostęp do obiektów bez metametod nie kończy się błędem (po prostu wynikiem jest nil).

2.9. Środowiska

Poza metatabelami, obiekty typu wątek, funkcja i userdata mogą mieć inną tabelę powiązaną, zwaną środowiskiem. Podobnie jak metatabele, środowiska są regularnymi tabelami i wiele obiektów może dzielić to samo środowisko.

Tworzone wątki współdzielą środowisko wątku, w którym są tworzone. Tworzone userdata i funkcje C współdzielą środowisko funkcji tworzącej. Nie zagnieżdżone funkcje Lua (stworzone przez loadfile, loadString lub load) są tworzone dzieląc środowisko wątku tworzenia. Tworzone funkcje zagnieżdżone Lua dzielą środowisko funkcji Lua, w której są tworzone.

Środowiska związane z UserData nie mają znaczenia dla Lua. To jest tylko cecha wygoda dla programistów by powiązać tabelę z userdata.

Środowiska związane z wątkami nazywane są środowiskami globalnymi. Są one używane jako środowiska domyślne dla wątków i nie zagnieżdżonych funkcji Lua stworzonych przez wątek oraz mogą być bezpośrednio dostępne przez kod C (3.3).

Środowisko związane z funkcją C może być bezpośrednio dostępne dla kodu C (3.3). Jest ono stosowane jako środowisko domyślne dla innych funkcji w języku C i userdata tworzonych przez funkcję.

Środowiska związane z funkcjami Lua są używane do uzyskiwania dostępu do zmiennych globalnych wewnątrz funkcji (2.3). Są one używane jako środowisko domyślne dla funkcji zagnieżdżonych Lua stworzonych przez funkcję.

Można zmienić środowisko funkcji Lua lub działającego wątku przez wywołanie funkcji setfenv. Można pobrać środowisko funkcji Lua lub działającego wątku przez wywołanie getenv. Aby zmodyfikować środowiska innych obiektów (userdata, funkcje C, inne wątki) należy użyć API języka C.

2.10. Garbage collector

Lua wykonuje automatyczne zarządzanie pamięcią. Oznacza to, że nie trzeba się martwić o alokację pamięci dla nowych obiektów, ani o zwalnianie jej, gdy obiekty nie są już potrzebne. Lua zarządza pamięcią automatycznie uruchamiając od czasu do czasu garbage collector, aby zebrać wszystkie martwe obiekty (czyli obiekty, które nie są już dostępne z Lua). Cała pamięć używana przez Lua jest automatycznie zarządzana: tabele, userdata funkcje, wątki, ciągi znaków itp.

Lua realizuje przyrostowy kolektor "zaznacz i usuń". Wykorzystuje dwie liczby by kontrolować swoje cykle zbierania: pauza garbage-collectora i mnożnik kroku garbage-collectora. Obydwie liczby są pod postacią punktów procentowych (a więc wartość 100 oznacza wewnętrzną wartość 1).

Pauza garbage-collectora kontroluje jak długo kolektor czeka przed rozpoczęciem nowego cyklu. Większe wartości sprawiają, że kolektor jest mniej agresywny. Wartości mniejsze niż 100 oznaczają, że kolektor nie będzie czekać, aby rozpocząć nowy cykl. Wartość 200 oznacza, że kolektor czeka aby liczba całkowitej pamięci w użyciu podwoiła się, przed rozpoczęciem nowego cyklu.

Mnożnik kroku kontroluje względną prędkość kolektora w stosunku do alokacji pamięci. Większe wartości sprawiają, że kolektor jest bardziej agresywny, ale także zwiększają rozmiar każdego przyrostowego kroku. Wartości mniejsze niż 100 sprawiają, że kolektor jest zbyt wolny i może doprowadzić do niezakończenia cyklu przez kolektora. Domyślnie 200 oznacza, że kolektor przebiega z "dwa razy" większą prędkością niż prędkość alokacji pamięci.

Można zmienić te wartość przez wywołanie funkcji lua_gc w C lub collectgarbage w Lua. Z pomocą tych funkcji można również kontrolować bezpośrednio kolektora (np. zatrzymywać i restartować).

2.10.1 Metametody Garbage Collectora

Korzystając z API C, można ustawić metametody dla userdata (2.8). Metametody nazywane są również finalizatorami. Finalizatory pozwalają koordynować oczyszczanie pamięci z zarządzaniem zewnętrznymi zasobami (np. zamykanie plików, połączeniami sieciowymi lub z bazami danych, lub uwalniając inną pamięć).

Niepotrzebne userdata z polem __gc w ich metatabelach nie są zbierane natychmiast przez garbage collectora. Zamiast tego Lua umieszcza je na liście. Po procesie zbierania, Lua przeprowadza operację dla każdego userdata na liście zgodnie z zasadą przedstawioną w poniższej funkcji.

    function gc_event (udata)
      local h = metatable(udata).__gc
      if h then
        h(udata)
      end
    end

Pod koniec każdego cyklu zbierania, finalizatory dla userdata są wywoływane w odwrotnej kolejności do kolejności ich utworzenia wśród tych zebranych w danym cyklu. Oznacza to, że pierwszy finalizator będzie uruchomiony tym, który jest przypisany do danych userdata utworzonych jako ostatnie w programie. Dane userdata są usuwane w następnym cyklu zbierania.

2.10.2 Słabe tabele

Słaba tabela jest tabelą, której elementami są słabe referencje. Słabe odwołanie jest ignorowane przez garbage collector. Innymi słowy, jeżeli tylko jedynymi refrencjami do obiektu są słabe referencje, to garbage collector uprzątnie taki obiekt.

Słaba tabela może posiadać słabe klucze lub słabe wartości. Tabela ze słabymi kluczami pozwala na uprzątnięcie swoich kluczy, ale zapobiega przed usuwaniem swoich wartości. Tabela składająca się ze słabych kluczy i słabych wartości uprzątnięcie zarówno kluczy oraz wartości. W każdym razie, jeżeli sprzątany jest klucz lub wartość to cała para zostanie usunięta z tabeli. Słabość tabeli jest sterowana przez pole __mode z metatabeli tej tabeli. Jeśli pole __mode to ciąg znaków zawierający znak 'k', klucze w tabeli są słabe. Jeśli pole __mode zawiera 'v', wartości podane w tabeli są słabe.

Po użyciu tabeli jako metatabeli, nie należy zmieniać wartości pola __mode. W przeciwnym wypadku "słabe" zachowanie tabel kontrolowanych przez tą metatabelę będzie niezdefiniowany.

2.11. Współprogramy

Lua wspiera współprogramy, zwane także współpracująca wielowątkowością. Współprogram w Lua reprezentowany jest przez niezależny wątek wykonania. W przeciwieństwie do wątków w systemach wielowątkowych, współprogram zawiesza swoje wykonanie tylko podczas jawnego wywołania funkcji, do której przekazywane jest sterowanie.

Tworzenie współprogramu wykonywane jest przez wywołanie funkcji coroutine.create. Głównym argumentem tej funkcji jest funkcja, będąca główna funkcją tego współprogramu. Funkcja create jedynie tworzy współprogram i zawraca uchwyt do niego (jako obiekt typu thread); nie powoduje to uruchomienia wykonania współprogramu.

Podczas pierwszego wykonania coroutine.resume, przekazując jako pierwszy argument, wątek zwrócony przez coroutine.create, współprogram zaczyna być wykonywany, od pierwszej linii swojej głównej funkcji. Dodatkowe argumenty przekazane do coroutine.resume są przekazywane do głównej funkcji współprogramu. Po uruchomieniu współprogramu, działa on do momentu przerwania działania lub przekazania sterowania.

Współprogram może przerwać swoje działanie na dwa sposoby: normalnie, gdy w głównej funkcji dochodzi do zwrócenia wartości (wyraźnie, lub przez osiągnięciu ostatniej instrukcji); lub awaryjnie w przypadku błędów. W pierwszym przypadku funkcja coroutine.resume zwraca true, oraz dodatkowe wartości zwrócone przez główną funkcje współprogramu. W przypadku błędów, coroutine.resume zwraca false, oraz dodatkowy komunikat o błędzie.

Przekazanie sterowania przez współprogram odbywa się przez wywołanie funkcji coroutine.yield. Gdy współprogram przekazuje sterowanie, odpowiadająca mu funkcja coroutine.resume niezwłocznie zwraca, nawet gdy przekazanie sterowania odbywa się wewnątrz zagnieżdżonego wywołania funkcji (czyli nie w głównej funkcji, ale w funkcji bezpośrednio lub niebezpośrednio wywołanej przez główną funkcję). W przypadku przekazania sterowania, coroutine.resume, również zwraca true, oraz wszystkie dodatkowe wartości przekazan do coroutine.yield, zwracając wszystkie dodatkowe argumenty przekazane do coroutine.resume.

Podobnie jak coroutine.create, funkcja coroutine.wrap, również tworzy współprogram, ale zamiast zwracać, sam współprogram, zwraca funkcję, która gdy jest wywołana, przywraca działanie współprogramu. Wszystkie argumenty, przekazane do tej funkcji są przekazywane jako dodatkowe parametry funkcji coroutine.resume. Funkcja coroutine.wrap zwraca wszystkie wartości zwrócone przez coroutine.resume, z wyjątkiem pierwszego (kod błędu w postaci wartości boolean). W przeciwieństwie do coroutine.resume , funkcja coroutine.wrap nie przechwytuje żadnych błędów; jakikolwiek błąd jest przechwytywany przez funkcję wywołującą.

Rozważając przykładowy kod:

     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"))

Przy uruchomieniu, otrzymany zostanie następujący wynik:

     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

3. Interfejs programistyczny aplikacji

Ten rozdział opisuje API języka C dla Lua, czyli zbiór funkcji w języku C dostępnych w programie hosta do komunikowania się z Lua. Wszystkie funkcje API i związane z nimi typy i stałe są zadeklarowane w pliku nagłówkowym lua.h.

Nawet wtedy, gdy używamy terminu "funkcja", każdy obiekt w API może być dostarczany jako makro. Wszystkie te makra wykorzystują każdy z ich argumentów dokładnie jeden raz (z wyjątkiem pierwszego argumentu, który jest zawsze stanem Lua), a więc nie generują żadnych ukrytych skutków ubocznych.

Jak w większości bibliotek C, Lua funkcje API nie sprawdzają swoich argumentów pod kątem ważności i spójności. Można jednak zmienić to zachowanie, poprzez skompilowanie Lua z odpowiednią definicją makra luai_apicheck, w pliku luaconf.h.

3.1. Stos

Lua wykorzystuje wirtualny stos do przekazywania wartości do i z programu hosta w C. Każdy element w stosie reprezentuje wartość Lua (nil, liczbę, ciąg znaków itd.).

Kiedykolwiek Lua wywołuje kod z C, wywoływana funkcja dostaje nowy stos, który jest niezależny od poprzednich stosów i stosów funkcji języka C, które są wciąż aktywne. Stos taki początkowo nie zawiera żadnych argumentów przekazywanych do funkcji języka C i jest to miejsce w które funkcja ta zwraca swój wynik do funkcji wywołującej (więcej w lua_CFunction).

Dla wygody, większość operacji zapytań w API nie trzyma się dokładnie zasad stosu. Większość z nich może odwołać się do dowolnego elementu w stosie wykorzystując indeks: dodatni indeks reprezentuje bezwzględną pozycję na stosie (zaczynając od 1); ujemny indeks oznacza przesunięcie względem góry stosu. Bardziej dokładnie, jeżeli stos posiada n elementów, to indeks o wartości 1 oznacza pierwszy element (czyli element, który został umieszczony w stosie jako pierwszy) i indeks o wartości n reprezentuje ostatni element; indeks o wartości -1 również odnosi się do ostatniego elementu (czyli elementu znajdującego się na szczycie stosu) a indeks -n oznacza, że jest to pierwszy element. Należy przyjąć że indeks jest ważny gdy jego wartość zawiera się między 1 i szczytem stosu (czyli 1 ≤ abs(index) ≤ top).

3.2. Rozmiar stosu

Podczas interakcji z API Lua, należy być konsekwentnym. W szczególności, należy kontrolować przepełnienie stosu. Do zwiększenia rozmiaru stosu używa się funkcji lua_checkstack.

Gdy Lua wywołuje kod w C, sprawdza czy przynajmniej dostępnę jest LUA_MINSTACK miejsc na stosie. Domyślnie LUA_MINSTACK posiada wartość 20, w większości przypadków, nie należy się martwić o miejsce na stosie, do momentu gdy tworzony kod nie posiada pętli umieszczających elementów na stosie.

Większość funkcji zapytań, przyjmuje wskaźniki jako dowolną wartość wewnątrz dostępnej przestrzeni stosu, czyli wskaźniki znajdują się na stosie do maksymalnego rozmiaru stosu ustawionego przez lua_checkstack. Takie wskaźniki nazywane są wskaźnikami dopuszczalnymi. Definiuje się je w następujący sposób:

     (index < 0 && abs(index) <= top) ||
     (index > 0 && index <= stackspace)

Należy zaznaczyć, że 0 nie jest nigdy dozwoloną wartością dla indeksu.

3.3. Pseudo wskaźniki

Gdy nie zaznaczono inaczej, dowolna funkcja która akceptuje ważne wskaźniki, może także być wywołana z pseudo wskaźnikami, które reprezentują wartości Lua, które są dostępne w kodzie C, ale których nie ma na stosie. Pseudo wskaźniki są używane by dostać się do środowiska wątku, środowiska funkcji, rejestru oraz zmienne przypisane do (ang. upvalues) funkcji w C (więcej w 3.4).

Środowisko wątku (gdzie znajdują się zmienne globalne) jest zawsze dostępne pod pseudo indeksem LUA_GLOBALSINDEX. Natomiast środowisko działającej funkcji C jest dostępne jako pseudo index LUA_ENVIRONINDEX.

Aby dostać się i zmienić zmienne globalne w tabeli środowiska, można wykorzystać zwykłe funkcje operacji na tabelach. Dla przykładu, aby dostać się do wartości zmiennej globalnej:

	lua_getfield(L, LUA_GLOBALSINDEX, varname);

3.4. Domknięcia w C

Gdy tworzona jest funkcja C, możliwe jest przypisanie jej pewnych wartości, powstaje wtedy domknięcie C (ang. closure); wartości te nazywane są zmienne przypisane (ang. upvalues) i są dostępne w funkcji kiedykolwiek funkcja jest wywoływana (więcej w lua_pushcclosure).

Gdy funkcja w C jest wywoływana, jej przypisane wartości są umieszczone w miejscu wskazywanym przez pseudo wskaźniki. Pseudo wskaźniki są tworzone przez makro lua_upvalueindex. Pierwsza wartości przypisana do funkcji dostępna jest na pozycji lua_upvalueindex(1). Dostęp do lua_upvalueindex(n), gdzie n jest większe niż liczba wartości przypisanych w funkcji (ale nie większa niż 256), spowoduje powstanie akceptowalnego (ale nieważnego) indeksu.

3.5. Rejestr

Lua udostępnia rejestr, predefiniowaną tabelę, która może być używana w kodzie C do przechowywania dowolnej wartości Lua. Tabela ta jest zawsze dostępna pod pseudo indeksem LUA_REGISTRYINDEX. Dowolna biblioteka C może przechowywać swoje dane, ale musi ostrożnie dobierać klucze od tych używanych przez inne biblioteki, by nie doszło do kolizji. Zwyczajowo, należy używać kluczy zawierających nazwę biblioteki, lub lekkich danych użytkownika (ang. userdata) z adresem obiektu C w kodzie.

Klucze całkowitoliczbowe w rejestrze są używane przez mechanizm referencji, implementowany przez bibliotekę zewnętrzną i nie powinny być używane do innych celów.

3.6. Przechwytywanie błędów w C

Wewnętrznie, Lua wykorzystuje mechanizm longjump z języka C do obsługi błędów. (Można także korzystać z wyjątków jeżeli korzysta się z C++; więcej w luaconf.h) Gdy w kodzie Lua dojdzie do błędu (takiego jak alokacja pamięci, błędy typów, błędy składnikowe i błędy podczas wykonywania) to powstaje błąd, który powoduje długi skok (ang. long jump). Chronione środowisko używa setjmp do ustawienia punktu ratunkowego; jakikolwiek błąd powoduje skok do ostatniego aktywnego punktu.

Większość funkcji w API może wyrzucić błąd, na przykład z powodu alokacji pamięci. Dokumentacja każdej funkcji wskazuje czy dana funkcja może wyrzucić błąd.

Wewnątrz funkcji C można spowodować wyrzucenie błędu przez wywołanie funkcji lua_error.

3.7. Funkcje i typy

3.8. Interfejs debugowania

4. Biblioteka zewnętrzna

Biblioteka zewnętrzna udostępnia kilka wygodnych funkcji pozwalających na interakcje C z Lua. Podstawowe API udostępnia prymitywne funkcje dla wszytkich interakcji pomiędzy C i Lua, natomiast biblioteka zewnętrzna pozwala na wykorzystanie funkcji wyższego poziomu do prostych zadań.

Wszystkie funkcje z biblioteki zewnętrznej są zdefiniowane w pliku lauzlib.h i posiadają prefiks luaL_.

Wszystkie funkcje w bibliotece zewnętrznej są zbudowane na bazie podstawowego API, więc nie umożliwiają niczego, czego nie można zrealizować przy pomocy API.

Kilka funkcji w bibliotece zewnętrznej jest wykorzystywanych do sprawdzania argumentów funkcji w C. Ich nazwy zawsze zaczynają się od luaL_check* lub luaL_opt*. Wszystkie te funkcje powodują zwrócenie błedu jeżeli sprawdzenie nie powiedzie się. Komunikat błędu jest formatowany z uwzględnieniem argumentów (np. "bad argument #1"), nie powinno się używać tych funkcji dla innych wartości stosu.

4.1. Funkcje i typy

5. Biblioteki standardowe

Standardowa biblioteka Lua dostarcza użyteczne funkcje, które są zaimplementowane bezpośrednio korzystając z API języka C. Niektóre z tych funkcji są istotnymi składnikami języka (jak type i getmetatable); inne pozwalają na dostęp do "zewnętrznych" elementów (takich jak wejście/wyjście); oraz innych, które mogą być zaimplementowane w Lua, ale są na tyle użyteczne, lub wymagana jest ich wysoka wydajność, która wymaga bezpośredniej implementacji w języku C (tak jak table.sort).

5.1. Funkcje podstawowe

5.2. Operacje na funkcjach współbieżnych

5.3. Moduły

5.4. Operacje na ciągach znaków

5.4.1. Wzorce

5.5. Operacje na tabelach

5.6. Funkcje matematyczne

5.7. Funkcje Wejścia i Wyjścia

5.8. Funkcje Systemu Operacyjnego

5.9. Biblioteka "Debug"

6. Lua samodzielnie

Mimo, że język Lua został zaprojektowany jako język rozszerzeń, umieszczany w programie napisanym w C, to dosyć często programy są uruchamiane samodzielnie. Interpreter dla Lua jako samodzielnego języka występuje pod nazwą lua i jest dostarczany z standardową dystrybucją. Wersja samodzielna interpretera zawiera wszystkie biblioteki standardowe wraz z biblioteką debug. Sposób użycia:

    lua [opcje] [skrypt [argumenty]]

Dostępne opcje:

Po przetworzeniu wszystkich opcji, lua uruchamia podany skrypt, przekazując podane argumenty. Podczas uruchamiania bez argumentów, lua zachowuje się jak lua -v -i gdy wejście standardowe (stdin) jest terminalem, a jako lua gdy tak nie jest.

Przed uruchomieniem jakiegokolwiek argumentu, interpreter sprawdza zmienną środowiskową LUA_INIT. Jeżeli format zmiennej jest jak @filename to lua uruchamia ten plik. W przeciwnym razie uruchamiany jest ciąg znaków znajdujący się w zmiennej.

Wszystkie opcje przetwarzane są zgodnie z podaną kolejnością, z wyjątkiem -i. Przykładowo, wywołanie takie jak

    $ lua -e'a=1' -e 'print(a)' script.lua

spowoduje, że w pierwszej kolejności a zostanie ustawione na 1, później zostanie wyświetlona wartość a (czyli "1") i w końcu zostanie uruchomiony plik script.lua bez żadnych argumentów (znak $ to znak linii poleceń powłoki systemu. Znak ten zależy od używanego systemu operacyjnego).

Przed uruchomieniem skryptu, lua zbiera wszystkie argumenty z linii poleceń w globalnej tabeli arg. Nazwa skryptu przechowywana jest w tabeli pod indeksem 0, pierwszy argument przekazany do skryptu zaraz po nazwie skryptu znajduje się w tabeli pod indeksem 1 i tak dalej. Wszystkie argumenty znajdujące się przed nazwą skryptu (takie jak nazwa interpretera i dodatkowe opcje) trafiają do tabeli z ujemnymi wartościami indeksu. Dla przykładu, przy wywołaniu:

    $ lua -la b.lua t1 t2

najpierw zostanie uruchomiony plik a.lua, później utworzona tabela

    arg = { [-2] = "lua", [-1] = "-la",
             [0] = "b.lua",
             [1] = "t1", [2] = "t2" }    

i na końcu plik b.lua. Skrypt uruchamiany jest z argumentami arg[1], arg[2], .... Dostęp do tych parametrów możliwy jest też przez wyrażenie zmiennej liczby argumentów '...'.

W trybie interaktywnym, wpisanie niekompletnej instrukcji spowoduje, że interpreter czeka na dokończenie jej przez podanie innego znaku linii poleceń.

Jeżeli zmienna globalna _PROMPT zawiera ciąg znaków, wtedy jej wartość używana jest jako znak linii poleceń. Podobnie, jeżeli zmienna globalna _PROMPT2 zawiera ciąg znaków, to wartość tej zmiennej używana jest jako drugi znak linii poleceń (wyświetlany podczas niekompletnych instrukcji). Obydwa symbole mogą być zmienione bezpośrednio przez podanie ich w linii poleceń w dowolnym programie przez przypisanie do zmiennej _PROMPT. W następującym przykładzie:

    $ lua -e"_PROMPT='myprompt> '" -i

(Zewnętrzne para cudzysłowów pochodzi od powłoki systemu operacyjnego, wewnętrzna para apostrofów należy do Lua.) Należy zwrócić uwagę na użycie parametru -i, który powoduje uruchomienie trybu interaktywnego, gdyż w przeciwnym wypadku program zakończyłby się bez żadnego wyniku zaraz po wykonaniu przypisania do _PROMPT.

By zapewnić użycie Lua jako interpretera skryptów w systemach uniksowych, samodzielny interpreter pomija pierwszą linię skryptu gdy ta rozpoczyna się od #. Ponadto skrypty lua mogą posiadać możliwość uruchomiania jak zwykłe programy przez użycie chmod +x i dodanie #!, tak jak:

#!/usr/local/bin/lua

Oczywiście, lokalizacja interpretera lua zależy od używanego systemu operacyjnego. Jeżeli lua znajduje się w zmiennej systemowej PATH wtedy:

#!/usr/bin/env lua

jest bardziej elastycznym rozwiązaniem.

7. Rozbieżności względem poprzednich wersji

7.1. Zmiany w języku

7.2. Zmiany w bibliotekach

7.3. Zmiany w API

8. Pełna składnia Lua

Poniżej znajduje się pełna składnia Lua podana w rozszerzonym BNF. Opis nie wyjaśnia kolejności operatorów.

    chunk ::= {stat [`;´]} [laststat [`;´]]

    block ::= chunk

    stat ::=  varlist `=´ explist | 
         functioncall | 
         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] 

    laststat ::= return [explist] | break

    funcname ::= Name {`.´ Name} [`:´ Name]

    varlist ::= var {`,´ var}

    var ::=  Name | prefixexp `[´ exp `]´ | prefixexp `.´ Name 

    namelist ::= Name {`,´ Name}

    explist ::= {exp `,´} exp

    exp ::=  nil | false | true | Number | String | `...´ | function | 
         prefixexp | tableconstructor | exp binop exp | unop exp 

    prefixexp ::= var | functioncall | `(´ exp `)´

    functioncall ::=  prefixexp args | prefixexp `:´ Name args 

    args ::=  `(´ [explist] `)´ | tableconstructor | String 

    function ::= 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 | `#´