Hlavní navigace

LuaJIT – Just in Time překladač pro programovací jazyk Lua (4)

4. 11. 2014
Doba čtení: 28 minut

Sdílet

Čtvrtá část článku o Just in Time překladači nazvaném LuaJIT bude věnována problematice volání funkcí, předávání parametrů do funkcí a taktéž způsobu vracení hodnoty či většího množství hodnot z volaných funkcí. Seznámíme se i s dalšími instrukcemi mezijazyka využívaného LuaJITem.

Obsah

1. LuaJIT – Just in Time překladač pro programovací jazyk Lua (4)

2. Volání funkci, předávání parametrů a vracení hodnot z volaných funkcí v IR LuaJITu

3. Demonstrační příklad test19.lua: volání funkce print() s předáním různého počtu parametrů

  3.1 Zdrojový kód příkladu test19.lua

  3.2 Překlad příkladu test19.lua do mezijazyka LuaJITu

4. Demonstrační příklad test20.lua: překlad a volání uživatelských funkcí

  4.1 Zdrojový kód příkladu test20.lua

  4.2 Překlad příkladu test20.lua do mezijazyka LuaJITu

5. Demonstrační příklad test21.lua: volání „statických metod“

  5.1 Zdrojový kód příkladu test21.lua

  5.2 Překlad příkladu test21.lua do mezijazyka LuaJITu

6. Demonstrační příklad test22.lua: volání „metod“

  6.1 Zdrojový kód příkladu test22.lua

  6.2 Překlad příkladu test22.lua do mezijazyka LuaJITu

7. Demonstrační příklad test23.lua: způsob vracení parametrů z volaných funkcí

  7.1 Zdrojový kód příkladu test23.lua

  7.2 Překlad příkladu test23.lua do mezijazyka LuaJITu

8. Repositář se zdrojovými kódy všech pěti dnešních demonstračních příkladů

9. Odkazy na Internetu

1. LuaJIT – Just in Time překladač pro programovací jazyk Lua (4)

Ve čtvrté části článku o velmi zajímavém a přitom poměrně jednoduchém Just in Time překladači nazvaném LuaJIT se budeme zabývat problematikou volání funkcí v programovacím jazyku Lua, přesněji řečeno způsobem překladu volání funkcí do mezijazyka (IR) využívaného LuaJITem. Taktéž si řekneme a na demonstračních příkladech i prakticky ukážeme, jakým způsobem se do volaných funkcí předávají parametry a jak se naopak z volaných funkcí vrací hodnota či hodnoty do té části programu, z něhož je daná funkce volána. Voláním funkcí jsme se poměrně podrobně zabývali již při vzájemném porovnávání bajtkódů JVM, Lua VM a Python VM, takže si jen stručně připomeňme, že Lua jakožto dynamicky typovaný programovací jazyk vyhodnocuje typy předávaných hodnot až v době běhu aplikace (tj. při volání konkrétní funkce či metody).

Navíc se v programovacím jazyku Lua nemusí při volání funkcí dodržet přesný počet parametrů – nadbytečné parametry nejsou využity a naopak, pokud se při volání uvede menší počet parametrů, než by odpovídalo počtu argumentů volané funkce (uvedené v její hlavičce), jsou tyto argumenty automaticky nastaveny na hodnotu nil. Aby byla situace ještě poněkud komplikovanější, je v Lua možné, aby funkce vracely více než jednu hodnotu a z funkcí lze i s (na)vázanými proměnnými vytvořit uzávěr (closure).

2. Volání funkci, předávání parametrů a vracení hodnot z volaných funkcí v IR LuaJITu

V demonstračních příkladech, které budou popsány v navazujících kapitolách, se při jejich překladu do mezijazyka LuaJITu vyskytuje větší množství nových či nově použitých instrukcí. Tyto instrukce jsou stručně popsány v tabulce pod tímto odstavcem:

# Instrukce Operandy Popis
1 GSET var, str uložení nové položky do globální tabulky _G, použito při deklaraci funkcí
2 GGET dst, str přečtení položky z globální tabulky _G, použito před voláním funkcí
       
3 FNEW dst, func vytvoření uzávěru (closure) z prototypu funkce
       
4 CALL base, lit, lit volání funkce s předáním parametrů (standardní forma volání)
5 CALLM base, lit, lit volání funkce s předáním parametrů (speciální forma volání)
       
5 RET0 A, D návrat z funkce bez předání návratového hodnoty (A a D se ignorují)
6 RET1 A, D návrat z funkce s předáním jedné návratové hodnoty A (D se ignoruje)
7 RET A, D návrat z funkce s předáním jedné návratových hodnot A, A+1, … A+D-2
       
8 TNEW A, D vytvoření nové tabulky o velikosti zapsané v D
9 TSETS var, var, str uložení prvku do tabulky (klíčem je řetězec)
10 TGETS dst, var, str přečtení prvku z tabulky (klíčem je řetězec)

3. Demonstrační příklad test19.lua: volání funkce print() s předáním různého počtu parametrů

V dnešním prvním demonstračním příkladu si ukážeme, jakým způsobem je možné volat funkci print(), která je součástí standardní knihovny programovacího jazyka Lua. Tuto funkci lze volat bez parametrů – v tom případě se na standardní výstup jednoduše zapíše nový řádek (provede se odřádkování). Pokud se tato funkce zavolá s jedním parametrem, je na standardní výstup poslána textová reprezentace hodnoty parametru, v případě většího počtu parametrů jsou tyto parametry taktéž zkonvertovány na text a vypsány na stejný řádek standardního výstupu. Díky tomuto chování funkce print() si můžeme ukázat, jak lze volat funkci akceptující proměnný počet parametrů. V tomto příkladu je taktéž vytvořena uživatelská funkce main(), která musí být v době běhu programu vytvořena z prototypu, následně uložena do globální tabulky _G a posléze zavolána.

3.1 Zdrojový kód příkladu test19.lua

Zdrojový kód prvního demonstračního příkladu je velmi jednoduchý:

--
-- LuaJIT: demonstrační příklad číslo 19
--
-- Volání funkci v programovacím jazyce Lua.
--
 
 
 
--
-- Spuštění testu.
--
function main()
    print()
    print(nil)
    print(42)
    print(1, 2)
    print("xyzzy")
end
 
 
 
main()
 
 
-- finito

3.2 Překlad příkladu test19.lua do mezijazyka LuaJITu

V sekvenci instrukcí vzniklých přeložením příkladu test19.lua do mezijazyka LuaJITu můžeme najít volání funkce print() realizované instrukcemi GGETCALL. První z těchto instrukcí načte reference na funkci z globální tabulky _G, druhá instrukce obstará volání:

; Překlad demonstračního příkladu test19.lua
; do IR využívaného virtuálním strojem a JIT
; překladačem LuaJIT.
 
-- BYTECODE -- test19.lua:12-18
; function main()
 
; print()
0001    GGET     0   0        ; získání reference na funkci se jménem "print"
0002    CALL     0   1   1    ; volání funkce print()
 
; print(nil)
0003    GGET     0   0        ; získání reference na funkci se jménem "print"
0004    KPRI     1   0        ; uložení primitivní hodnoty nil do slotu číslo 1
0005    CALL     0   1   2    ; volání funkce print()
 
; print(42)
0006    GGET     0   0        ; získání reference na funkci se jménem "print"
0007    KSHORT   1  42        ; uložení numerické hodnoty 42 do slotu číslo 1
0008    CALL     0   1   2    ; volání funkce print()
 
; print(1,2)
0009    GGET     0   0        ; získání reference na funkci se jménem "print"
0010    KSHORT   1   1        ; uložení numerické hodnoty 1 do slotu číslo 1
0011    KSHORT   2   2        ; uložení numerické hodnoty 2 do slotu číslo 2
0012    CALL     0   1   3    ; volání funkce print()
 
; print("xyzzy")
0013    GGET     0   0        ; získání reference na funkci se jménem "print"
0014    KSTR     1   1        ; uložení reference na řetězec "xyzzy" do slotu číslo 1
0015    CALL     0   1   2    ; volání funkce print()
 
0016    RET0     0   1        ; návrat z funkce main

Důležitá je i sekvence instrukcí použitá pro vytvoření a registraci funkce main(). Najdeme zde především dvě instrukce FNEWGSET, kde první instrukce vytvoří uzávěr z prototypu funkce a druhá instrukce uloží tento uzávěr do globální tabulky _G:

-- BYTECODE -- test19.lua:0-27
 
; main()
; vytvoření, "registrace" a následné volání funkce main()
0001    FNEW     0   0        ; vytvoření uzávěru tvořeného funkcí "main" s uložením do slotu číslo 0
0002    GSET     0   1        ; uložení uzávěru do globální tabulky _G pod jménem "main"
0003    GGET     0   1        ; získání reference na funkci se jménem "main"
0004    CALL     0   1   1    ; zavolání funkce main()
0005    RET0     0   1        ; návrat z programu
 
; konec

4. Demonstrační příklad test20.lua: překlad a volání uživatelských funkcí

Dnešní druhý demonstrační příklad, který je nazvaný test20.lua, je, podobně jako příklad předchozí, stále velmi jednoduchý. Jsou v něm implementovány funkce se jmény function1(), function2()function3(), přičemž první funkce pojmenovaná function1() neočekává žádné argumenty, funkce se jménem function2() očekává jeden argument a konečně funkce function3() očekává dva argumenty, které jsou sečteny (v případě, že argumenty nejsou typu celé či reálné číslo, vznikne při běhu programu chyba, to však při překladu do IR neuvidíme). Všechny tři zmíněné funkce jsou volány z kódu, který je implementován v další trojici funkcí nazvaných callFunction1(), callFunction2()callFunction3(). Povšimněte si, že se nikde nekontroluje ani počet ani typ skutečně předávaných parametrů, což je pro jazyk Lua a současně i pro několik dalších dynamicky typovaných programovacích jazyků typická vlastnost:

4.1 Zdrojový kód příkladu test20.lua

Podívejme se na zdrojový kód demonstračního příkladu test20.lua:

--
-- LuaJIT: demonstrační příklad číslo 20
--
-- Volání funkci v programovacím jazyce Lua.
--
 
 
 
--
-- Funkce bez parametrů.
--
function function1()
end
 
 
 
--
-- Funkce s jedním parametrem.
--
function function2(x)
    return x
end
 
 
 
--
-- Funkce se dvěma parametry.
--
function function3(x, y)
    if x and y then
        return x+y
    else
        return nil
    end
end
 
 
 
--
-- Volání funkce function1().
--
function callFunction1()
    function1()
    function1(nil)
    function1(42)
    function3(1, 2)
    function1("xyzzy")
end
 
 
 
--
-- Volání funkce function2().
--
function callFunction2()
    function2()
    function2(nil)
    function2(42)
    function3(1, 2)
    function2("xyzzy")
end
 
 
 
--
-- Volání funkce function3().
--
function callFunction3()
    function3()
    function3(nil)
    function3(42)
    function3(1, 2)
    function3("xyzzy")
end
 
 
 
--
-- Spuštění testu.
--
function main()
    callFunction1()
    callFunction2()
    callFunction3()
end
 
 
 
main()
 
 
-- finito

4.2 Překlad příkladu test20.lua do mezijazyka LuaJITu

V přeloženém příkladu test20.lua stojí za povšimnutí několik zajímavostí. Především se zde nepoužívá jediná instrukce RET, ale dvě různé instrukce RET0RET1. Instrukce RET0 zajišťuje návrat z volané funkce do funkce volající, ovšem bez předání návratové hodnoty. Naproti tomu instrukce RET1 dokáže do volající funkce předat jednu hodnotu, konkrétně hodnotu uloženou ve slotu, jehož index je uložen přímo v instrukčním slovu:

; Překlad demonstračního příkladu test20.lua
; do IR využívaného virtuálním strojem a JIT
; překladačem LuaJIT.
 
 
 
-- BYTECODE -- test20.lua:12-13
; function function1()
 
; end
0001    RET0     0   1        ; návrat z funkce
 
-- BYTECODE -- test20.lua:20-22
; function function2(x)
 
; return x
0001    RET1     0   2        ; návrat z funkce + předání návratové hodnoty
 
 
 
-- BYTECODE -- test20.lua:29-35
; function function3(x, y)
 
; if x and y then
0001    ISF          0        ; test, zda není první parametr funkce false či nil
0002    JMP      2 => 0008    ; + podmíněný skok
0003    ISF          1        ; test, zda není druhý parametr funkce false či nil
0004    JMP      2 => 0008    ; + podmíněný skok
 
; return x+y
0005    ADDVV    2   0   1    ; výpočet návratové hodnoty
0006    RET1     2   2        ; návrat z funkce + předání návratové hodnoty
 
; else
0007    JMP      2 => 0010    ; nepodmíněný skok
 
; return nil
0008 => KPRI     2   0        ; návratová hodnota
0009    RET1     2   2        ; návrat z funkce + předání návratové hodnoty
0010 => RET0     0   1        ; návrat z funkce
 
 
 
-- BYTECODE -- test20.lua:42-48
; function callFunction1()
 
; function1()
0001    GGET     0   0        ; získání reference na funkci se jménem "function1"
0002    CALL     0   1   1    ; volání funkce
 
; function1(nil)
0003    GGET     0   0        ; získání reference na funkci se jménem "function1"
0004    KPRI     1   0
0005    CALL     0   1   2    ; volání funkce
 
; function1(42)
0006    GGET     0   0        ; získání reference na funkci se jménem "function1"
0007    KSHORT   1  42
0008    CALL     0   1   2    ; volání funkce
 
; function1(1, 2)
0009    GGET     0   1        ; získání reference na funkci se jménem "function1"
0010    KSHORT   1   1
0011    KSHORT   2   2
0012    CALL     0   1   3    ; volání funkce
 
; function1("xyzzy")
0013    GGET     0   0        ; "function1"
0014    KSTR     1   2        ; "xyzzy"
0015    CALL     0   1   2    ; volání funkce
 
; end
0016    RET0     0   1        ; návrat z funkce
 
 
 
-- BYTECODE -- test20.lua:55-61
; function callFunction2()
 
; function2()
0001    GGET     0   0        ; získání reference na funkci se jménem "function2"
0002    CALL     0   1   1    ; volání funkce
 
; function2(nil)
0003    GGET     0   0        ; získání reference na funkci se jménem "function2"
0004    KPRI     1   0
0005    CALL     0   1   2    ; volání funkce
 
; function2(42)
0006    GGET     0   0        ; získání reference na funkci se jménem "function2"
0007    KSHORT   1  42
0008    CALL     0   1   2    ; volání funkce
 
; function2(1, 2)
0009    GGET     0   1        ; získání reference na funkci se jménem "function2"
0010    KSHORT   1   1
0011    KSHORT   2   2
0012    CALL     0   1   3    ; volání funkce
 
; function2("xyzzy")
0013    GGET     0   0        ; získání reference na funkci se jménem "function2"
0014    KSTR     1   2        ; "xyzzy"
0015    CALL     0   1   2    ; volání funkce
0016    RET0     0   1        ; návrat z funkce
 
 
 
-- BYTECODE -- test20.lua:68-74
; function callFunction3()
 
; function3()
0001    GGET     0   0        ; získání reference na funkci se jménem "function3"
0002    CALL     0   1   1    ; volání funkce
 
; function3(nil)
0003    GGET     0   0        ; získání reference na funkci se jménem "function3"
0004    KPRI     1   0
0005    CALL     0   1   2    ; volání funkce
 
; function3(42)
0006    GGET     0   0        ; získání reference na funkci se jménem "function3"
0007    KSHORT   1  42
0008    CALL     0   1   2    ; volání funkce
 
; function3(1, 2)
0009    GGET     0   0        ; získání reference na funkci se jménem "function3"
0010    KSHORT   1   1
0011    KSHORT   2   2
0012    CALL     0   1   3    ; volání funkce
 
; function3("xyzzy")
0013    GGET     0   0        ; získání reference na funkci se jménem "function3"
0014    KSTR     1   1        ; "xyzzy"
0015    CALL     0   1   2    ; volání funkce
0016    RET0     0   1        ; návrat z funkce
 
 
 
-- BYTECODE -- test20.lua:81-85
; function main()
 
; callFunction1()
0001    GGET     0   0        ; získání reference na funkci se jménem "callFunction1"
0002    CALL     0   1   1    ; volání funkce
 
; callFunction2()
0003    GGET     0   1        ; získání reference na funkci se jménem "callFunction2"
0004    CALL     0   1   1    ; volání funkce
 
; callFunction3()
0005    GGET     0   2        ; získání reference na funkci se jménem "callFunction3"
0006    CALL     0   1   1    ; volání funkce
 
; end
0007    RET0     0   1        ; návrat z funkce
 
 
 
-- BYTECODE -- test20.lua:0-94
 
; main()
; vytvoření, "registrace" a následné volání funkce main()
0001    FNEW     0   0        ; vytvoření uzávěru z prototypu začínajícího na řádku test20.lua:12
0002    GSET     0   1        ; uložení uzávěru do globální tabulky _G pod jménem "function1"
 
0003    FNEW     0   2        ; vytvoření uzávěru z prototypu začínajícího na řádku test20.lua:20
0004    GSET     0   3        ; uložení uzávěru do globální tabulky _G pod jménem "function2"
 
0005    FNEW     0   4        ; vytvoření uzávěru z prototypu začínajícího na řádku test20.lua:29
0006    GSET     0   5        ; uložení uzávěru do globální tabulky _G pod jménem "function3"
 
0007    FNEW     0   6        ; vytvoření uzávěru z prototypu začínajícího na řádku test20.lua:42
0008    GSET     0   7        ; uložení uzávěru do globální tabulky _G pod jménem "callFunction1"
 
0009    FNEW     0   8        ; vytvoření uzávěru z prototypu začínajícího na řádku test20.lua:55
0010    GSET     0   9        ; uložení uzávěru do globální tabulky _G pod jménem "callFunction2"
 
0011    FNEW     0  10        ; vytvoření uzávěru z prototypu začínajícího na řádku test20.lua:68
0012    GSET     0  11        ; uložení uzávěru do globální tabulky _G pod jménem "callFunction3"
 
0013    FNEW     0  12        ; vytvoření uzávěru z prototypu začínajícího na řádku test20.lua:81
0014    GSET     0  13        ; uložení uzávěru do globální tabulky _G pod jménem "main"
 
0015    GGET     0  13        ; získání reference na funkci se jménem "main"
0016    CALL     0   1   1    ; zavolání funkce main()
 
0017    RET0     0   1        ; návrat z programu
 
; konec

5. Demonstrační příklad test21.lua: volání „statických metod“

Díky tomu, že funkce jsou v programovacím jazyku Lua plnohodnotným datovým typem, je možné odkazy/reference na funkce vkládat i do tabulek (což je vlastně jediný strukturovaný datový typ tohoto jazyka). Tímto způsobem je možné v Lue vytvořit objekty, přičemž funkce vložené do tabulek lze chápat jako obdobu „statických metod“. „Statické metody“ jsou běžné funkce, při jejichž deklaraci je mezi jménem tabulky a jménem funkce použita tečka, která je též použita při volání této funkce. Podívejme se na příklad test21.lua, který je přímo odvozen od dnešního druhého příkladu test20.lua až na ten rozdíl, že původní funkce function1(), function2()function3() jsou uloženy do tabulky nazvané testClass.

5.1 Zdrojový kód příkladu test21.lua

--
-- demonstrační příklad číslo 21.
--
-- Volání "statických metod" v programovacím jazyce Lua.
--
 
 
 
testClass = {}
 
--
-- Funkce/statická metoda bez parametrů.
--
function testClass.function1()
end
 
 
 
--
-- Funkce/statická metoda s jedním parametrem.
--
function testClass.function2(x)
    return x
end
 
 
 
--
-- Funkce/statická metoda se dvěma parametry.
--
function testClass.function3(x, y)
    if x and y then
        return x+y
    else
        return nil
    end
end
 
 
 
--
-- Volání funkcí/statických metod.
--
function callFunction1()
    testClass.function1()
    testClass.function1(nil)
    testClass.function1(42)
    testClass.function3(1, 2)
    testClass.function1("xyzzy")
end
 
 
 
--
-- Volání funkce function2().
--
function callFunction2()
    testClass.function2()
    testClass.function2(nil)
    testClass.function2(42)
    testClass.function3(1, 2)
    testClass.function2("xyzzy")
end
 
 
 
--
-- Volání funkce function3().
--
function callFunction3()
    testClass.function3()
    testClass.function3(nil)
    testClass.function3(42)
    testClass.function3(1, 2)
    testClass.function3("xyzzy")
end
 
 
 
--
-- Spuštění testu.
--
function main()
    callFunction1()
    callFunction2()
    callFunction3()
end
 
 
 
main()
 
 
 
--
-- Finito.
--

5.2 Překlad příkladu test21.lua do mezijazyka LuaJITu

V sekvenci instrukcí přeloženého demonstračního příkladu test21.lua můžeme mj. vidět následující trojici instrukcí použitou pro zavolání vybrané statické metody:

; testClass.function1()
0001    GGET     0   0        ; přečtení reference na tabulku "testClass" z globální tabulky _G
0002    TGETS    0   0   1    ; získání reference na funkci se jménem "function1"
0003    CALL     0   1   1    ; volání funkce/metody

Z této sekvence je patrné, že se nejdříve získá reference na tabulku nazvanou „testClass“ z globální tabulky _G a následně se přečte reference na vybranou funkci. Pro čtení z obou tabulek se používají klíče, které jsou typu řetězec. Tato funkce je následně zavolána.

; Překlad demonstračního příkladu test21.lua
; do IR využívaného virtuálním strojem a JIT
; překladačem LuaJIT.
 
 
 
-- BYTECODE -- test21.lua:14-15
; function testClass.function1()
 
; end
0001    RET0     0   1        ; návrat z funkce
 
 
 
-- BYTECODE -- test21.lua:22-24
; function testClass.function2()
 
; return x
0001    RET1     0   2        ; návrat z funkce + předání návratové hodnoty
 
 
 
-- BYTECODE -- test21.lua:31-37
; function testClass.function3(x, y)
 
; if x and y then
0001    ISF          0        ; test, zda není první parametr funkce false či nil
0002    JMP      2 => 0008    ; + podmíněný skok
0003    ISF          1        ; test, zda není druhý parametr funkce false či nil
0004    JMP      2 => 0008    ; + podmíněný skok
 
; return x+y
0005    ADDVV    2   0   1    ; výpočet návratové hodnoty
0006    RET1     2   2        ; návrat z funkce + předání návratové hodnoty
 
; else
0007    JMP      2 => 0010    ; nepodmíněný skok
 
; return nil
0008 => KPRI     2   0        ; návratová hodnota
0009    RET1     2   2        ; návrat z funkce + předání návratové hodnoty
0010 => RET0     0   1        ; návrat z funkce
 
 
 
-- BYTECODE -- test21.lua:44-50
; function callFunction1()
 
; testClass.function1()
0001    GGET     0   0        ; přečtení reference na tabulku "testClass" z globální tabulky _G
0002    TGETS    0   0   1    ; získání reference na funkci se jménem "function1"
0003    CALL     0   1   1    ; volání funkce/metody
 
; testClass.function1(nil)
0004    GGET     0   0        ; přečtení reference na tabulku "testClass" z globální tabulky _G
0005    TGETS    0   0   1    ; získání reference na funkci se jménem "function1"
0006    KPRI     1   0        ; parametr volané funkce - hodnota nil
0007    CALL     0   1   2    ; volání funkce/metody
 
; testClass.function1(42)
0008    GGET     0   0        ; přečtení reference na tabulku "testClass" z globální tabulky _G
0009    TGETS    0   0   1    ; získání reference na funkci se jménem "function1"
0010    KSHORT   1  42        ; parametr volané funkce - hodnota 42
0011    CALL     0   1   2    ; volání funkce/metody
 
; testClass.function1(1, 2)
0012    GGET     0   0        ; přečtení reference na tabulku "testClass" z globální tabulky _G
0013    TGETS    0   0   2    ; získání reference na funkci se jménem "function1"
0014    KSHORT   1   1        ; první parametr volané funkce - hodnota 1
0015    KSHORT   2   2        ; druhý parametr volané funkce - hodnota 2
0016    CALL     0   1   3    ; volání funkce/metody
 
; testClass.function1("xyzzy")
0017    GGET     0   0        ; přečtení reference na tabulku "testClass" z globální tabulky _G
0018    TGETS    0   0   1    ; získání reference na funkci se jménem "function1"
0019    KSTR     1   3        ; první parametr volané funkce - odkaz na řetězec "xyzzy"
0020    CALL     0   1   2    ; volání funkce/metody
 
; end
0021    RET0     0   1        ; návrat z funkce
 
 
 
-- BYTECODE -- test21.lua:57-63
; function callFunction2()
 
; testClass.function2()
0001    GGET     0   0        ; přečtení reference na tabulku "testClass" z globální tabulky _G
0002    TGETS    0   0   1    ; získání reference na funkci se jménem "function2"
0003    CALL     0   1   1    ; volání funkce/metody
 
; testClass.function2(nil)
0004    GGET     0   0        ; přečtení reference na tabulku "testClass" z globální tabulky _G
0005    TGETS    0   0   1    ; získání reference na funkci se jménem "function2"
0006    KPRI     1   0        ; parametr volané funkce - hodnota nil
0007    CALL     0   1   2    ; volání funkce/metody
 
; testClass.function2(42)
0008    GGET     0   0        ; přečtení reference na tabulku "testClass" z globální tabulky _G
0009    TGETS    0   0   1    ; získání reference na funkci se jménem "function2"
0010    KSHORT   1  42        ; parametr volané funkce - hodnota 42
0011    CALL     0   1   2    ; volání funkce/metody
 
; testClass.function2(1, 2)
0012    GGET     0   0        ; přečtení reference na tabulku "testClass" z globální tabulky _G
0013    TGETS    0   0   2    ; získání reference na funkci se jménem "function2"
0014    KSHORT   1   1        ; první parametr volané funkce - hodnota 1
0015    KSHORT   2   2        ; druhý parametr volané funkce - hodnota 2
0016    CALL     0   1   3    ; volání funkce/metody
 
; testClass.function2("xyzzy")
0017    GGET     0   0        ; přečtení reference na tabulku "testClass" z globální tabulky _G
0018    TGETS    0   0   1    ; získání reference na funkci se jménem "function2"
0019    KSTR     1   3        ; první parametr volané funkce - odkaz na řetězec "xyzzy"
0020    CALL     0   1   2    ; volání funkce/metody
 
; end
0021    RET0     0   1        ; návrat z funkce
 
 
 
-- BYTECODE -- test21.lua:70-76
; function callFunction3()
 
; testClass.function3()
0001    GGET     0   0        ; přečtení reference na tabulku "testClass" z globální tabulky _G
0002    TGETS    0   0   1    ; získání reference na funkci se jménem "function3"
0003    CALL     0   1   1    ; volání funkce/metody
 
; testClass.function3(nil)
0004    GGET     0   0        ; přečtení reference na tabulku "testClass" z globální tabulky _G
0005    TGETS    0   0   1    ; získání reference na funkci se jménem "function3"
0006    KPRI     1   0        ; parametr volané funkce - hodnota nil
0007    CALL     0   1   2    ; volání funkce/metody
 
; testClass.function3(42)
0008    GGET     0   0        ; přečtení reference na tabulku "testClass" z globální tabulky _G
0009    TGETS    0   0   1    ; získání reference na funkci se jménem "function3"
0010    KSHORT   1  42        ; parametr volané funkce - hodnota 42
0011    CALL     0   1   2    ; volání funkce/metody
 
; testClass.function3(1, 2)
0012    GGET     0   0        ; přečtení reference na tabulku "testClass" z globální tabulky _G
0013    TGETS    0   0   1    ; získání reference na funkci se jménem "function3"
0014    KSHORT   1   1        ; první parametr volané funkce - hodnota 1
0015    KSHORT   2   2        ; druhý parametr volané funkce - hodnota 2
0016    CALL     0   1   3    ; volání funkce/metody
 
; testClass.function3("xyzzy")
0017    GGET     0   0        ; přečtení reference na tabulku "testClass" z globální tabulky _G
0018    TGETS    0   0   1    ; získání reference na funkci se jménem "function3"
0019    KSTR     1   2        ; první parametr volané funkce - odkaz na řetězec "xyzzy"
0020    CALL     0   1   2    ; volání funkce/metody
 
; end
0021    RET0     0   1        ; návrat z funkce
 
 
 
-- BYTECODE -- test21.lua:83-87
; function main()
 
; callFunction1()
0001    GGET     0   0        ; získání reference na funkci se jménem "callFunction1"
0002    CALL     0   1   1    ; volání funkce
 
; callFunction2()
0003    GGET     0   1        ; získání reference na funkci se jménem "callFunction2"
0004    CALL     0   1   1    ; volání funkce
 
; callFunction3()
0005    GGET     0   2        ; získání reference na funkci se jménem "callFunction3"
0006    CALL     0   1   1    ; volání funkce
 
; end
0007    RET0     0   1        ; návrat z funkce
 
 
 
-- BYTECODE -- test21.lua:0-99
 
; main()
; vytvoření, "registrace" a následné volání funkce main(), inicializace třídy testClass
0001    TNEW     0   0        ; vytvoření nové tabulky
0002    GSET     0   0        ; uložení tabulky do _G pod jménem "testClass"
 
0003    GGET     0   0        ; přečtení reference na tabulku "testClass"
0004    FNEW     1   2        ; vytvoření uzávěru z prototypu začínajícího na řádku test21.lua:14
0005    TSETS    1   0   1    ; uložení uzávěru do vybrané tabulky _G pod jménem "function1"
 
0006    GGET     0   0        ; přečtení reference na tabulku "testClass"
0007    FNEW     1   4        ; vytvoření uzávěru z prototypu začínajícího na řádku test21.lua:22
0008    TSETS    1   0   3    ; uložení uzávěru do vybrané tabulky _G pod jménem "function2"
 
0009    GGET     0   0        ; přečtení reference na tabulku "testClass"
0010    FNEW     1   6        ; vytvoření uzávěru z prototypu začínajícího na řádku test21.lua:31
0011    TSETS    1   0   5    ; uložení uzávěru do vybrané tabulky _G pod jménem "function3"
 
0012    FNEW     0   7        ; vytvoření uzávěru z prototypu začínajícího na řádku  test21.lua:44
0013    GSET     0   8        ; uložení uzávěru do globální tabulky _G pod jménem "callFunction1"
 
0014    FNEW     0   9        ; vytvoření uzávěru z prototypu začínajícího na řádku  test21.lua:57
0015    GSET     0  10        ; uložení uzávěru do globální tabulky _G pod jménem "callFunction2"
 
0016    FNEW     0  11        ; vytvoření uzávěru z prototypu začínajícího na řádku  test21.lua:70
0017    GSET     0  12        ; uložení uzávěru do globální tabulky _G pod jménem "callFunction3"
 
0018    FNEW     0  13        ; vytvoření uzávěru z prototypu začínajícího na řádku  test21.lua:83
0019    GSET     0  14        ; uložení uzávěru do globální tabulky _G pod jménem "main"
 
0020    GGET     0  14        ; získání reference na funkci se jménem "main"
0021    CALL     0   1   1    ; zavolání funkce main()
 
0022    RET0     0   1        ; návrat z programu
 
; konec

6. Demonstrační příklad test22.lua: volání „metod“

V programovacím jazyku Lua je možné funkce vkládat do tabulek i s využitím dvojtečky namísto tečky. Tento malý syntaktický rozdíl však vede k vytvoření sémanticky odlišného kódu – takto vytvořená funkce totiž bude mít navíc jeden parametr, v němž se předá odkaz na objekt, tedy hodnota, která se v jiných programovacích jazycích označuje klíčovým slovem self nebo this. Odlišné je pak i volání takových funkcí, které lze podle jejich vlastností již nazývat „metodami“.

6.1 Zdrojový kód příkladu test22.lua

--
-- demonstrační příklad číslo 22.
--
-- Volání "metod" v programovacím jazyce Lua.
--
 
 
 
testClass = {}
 
--
-- Funkce/metoda bez parametrů.
--
function testClass:function1()
end
 
 
 
--
-- Funkce/metoda s jedním parametrem.
--
function testClass:function2(x)
    return x
end
 
 
 
--
-- Funkce/metoda se dvěma parametry.
--
function testClass:function3(x, y)
    if x and y then
        return x+y
    else
        return nil
    end
end
 
 
 
--
-- Volání funkce function1().
--
function callFunction1()
    testClass:function1()
    testClass:function1(nil)
    testClass:function1(42)
    testClass:function3(1, 2)
    testClass:function1("xyzzy")
end
 
 
 
--
-- Volání funkce function2().
--
function callFunction2()
    testClass:function2()
    testClass:function2(nil)
    testClass:function2(42)
    testClass:function3(1, 2)
    testClass:function2("xyzzy")
end
 
 
 
--
-- Volání funkce function3().
--
function callFunction3()
    testClass:function3()
    testClass:function3(nil)
    testClass:function3(42)
    testClass:function3(1, 2)
    testClass:function3("xyzzy")
end
 
 
 
--
-- Spuštění testu.
--
function main()
    callFunction1()
    callFunction2()
    callFunction3()
end
 
 
 
main()
 
 
 
--
-- Finito.
--

6.2 Překlad příkladu test22.lua do mezijazyka LuaJITu

V předchozím příkladu se pro zavolání statické metody používal tento kód:

; testClass.function1()
0001    GGET     0   0        ; přečtení reference na tabulku "testClass" z globální tabulky _G
0002    TGETS    0   0   1    ; získání reference na funkci se jménem "function1"
0003    CALL     0   1   1    ; volání funkce/metody

Pro zavolání metody nestatické musíme zpracovat i parametr this/self:

; testClass.function1()
0001    GGET     0   0        ; přečtení reference na tabulku "testClass" z globální tabulky _G
0002    MOV      1   0        ; při volání se použije i skrytý parametr this/self
0003    TGETS    0   0   1    ; získání reference na funkci se jménem "function1"
0004    CALL     0   1   2    ; volání funkce/metody

Tento rozdíl je hned několikrát vidět i v úplném výpisu IR:

; Překlad demonstračního příkladu test22.lua
; do IR využívaného virtuálním strojem a JIT
; překladačem LuaJIT.
 
 
 
-- BYTECODE -- test22.lua:14-15
; function testClass.function1()
 
; end
0001    RET0     0   1        ; návrat z funkce
 
 
 
-- BYTECODE -- test22.lua:22-24
; function testClass.function2()
 
; return x
0001    RET1     1   2        ; návrat z funkce + předání návratové hodnoty
 
 
 
-- BYTECODE -- test22.lua:31-37
; function testClass.function3(x, y)
 
; if x and y then
0001    ISF          1        ; test, zda není první parametr funkce false či nil
0002    JMP      3 => 0008    ; + podmíněný skok
0003    ISF          2        ; test, zda není druhý parametr funkce false či nil
0004    JMP      3 => 0008    ; + podmíněný skok
 
; return x+y
0005    ADDVV    3   1   2    ; výpočet návratové hodnoty
0006    RET1     3   2        ; návrat z funkce + předání návratové hodnoty
 
; else
0007    JMP      3 => 0010    ; nepodmíněný skok
 
; return nil
0008 => KPRI     3   0        ; návratová hodnota
0009    RET1     3   2        ; návrat z funkce + předání návratové hodnoty
0010 => RET0     0   1        ; návrat z funkce
 
 
 
-- BYTECODE -- test22.lua:44-50
; function callFunction1()
 
; testClass.function1()
0001    GGET     0   0        ; přečtení reference na tabulku "testClass" z globální tabulky _G
0002    MOV      1   0        ; při volání se použije i skrytý parametr this/self
0003    TGETS    0   0   1    ; získání reference na funkci se jménem "function1"
0004    CALL     0   1   2    ; volání funkce/metody
 
; testClass.function1(nil)
0005    GGET     0   0        ; přečtení reference na tabulku "testClass" z globální tabulky _G
0006    MOV      1   0        ; při volání se použije i skrytý parametr this/self
0007    TGETS    0   0   1    ; získání reference na funkci se jménem "function1"
0008    KPRI     2   0        ; parametr volané funkce - hodnota nil
0009    CALL     0   1   3    ; volání funkce/metody
 
; testClass.function1(42)
0010    GGET     0   0        ; přečtení reference na tabulku "testClass" z globální tabulky _G
0011    MOV      1   0        ; při volání se použije i skrytý parametr this/self
0012    TGETS    0   0   1    ; získání reference na funkci se jménem "function1"
0013    KSHORT   2  42        ; parametr volané funkce - hodnota 42
0014    CALL     0   1   3    ; volání funkce/metody
 
; testClass.function1(1, 2)
0015    GGET     0   0        ; přečtení reference na tabulku "testClass" z globální tabulky _G
0016    MOV      1   0        ; při volání se použije i skrytý parametr this/self
0017    TGETS    0   0   2    ; získání reference na funkci se jménem "function1"
0018    KSHORT   2   1        ; první parametr volané funkce - hodnota 1
0019    KSHORT   3   2        ; druhý parametr volané funkce - hodnota 2
0020    CALL     0   1   4    ; volání funkce/metody
 
; testClass.function1("xyzzy")
0021    GGET     0   0        ; přečtení reference na tabulku "testClass" z globální tabulky _G
0022    MOV      1   0        ; při volání se použije i skrytý parametr this/self
0023    TGETS    0   0   1    ; získání reference na funkci se jménem "function1"
0024    KSTR     2   3        ; první parametr volané funkce - odkaz na řetězec "xyzzy"
0025    CALL     0   1   3    ; volání funkce/metody
 
; end
0026    RET0     0   1
 
 
 
-- BYTECODE -- test22.lua:57-63
; function callfunction2()
 
; testClass.function2()
0001    GGET     0   0        ; přečtení reference na tabulku "testClass" z globální tabulky _G
0002    MOV      1   0        ; při volání se použije i skrytý parametr this/self
0003    TGETS    0   0   1    ; získání reference na funkci se jménem "function2"
0004    CALL     0   1   2    ; volání funkce/metody
 
; testClass.function2(nil)
0005    GGET     0   0        ; přečtení reference na tabulku "testClass" z globální tabulky _G
0006    MOV      1   0        ; při volání se použije i skrytý parametr this/self
0007    TGETS    0   0   1    ; získání reference na funkci se jménem "function2"
0008    KPRI     2   0        ; parametr volané funkce - hodnota nil
0009    CALL     0   1   3    ; volání funkce/metody
 
; testClass.function2(42)
0010    GGET     0   0        ; přečtení reference na tabulku "testClass" z globální tabulky _G
0011    MOV      1   0        ; při volání se použije i skrytý parametr this/self
0012    TGETS    0   0   1    ; získání reference na funkci se jménem "function2"
0013    KSHORT   2  42        ; parametr volané funkce - hodnota 42
0014    CALL     0   1   3    ; volání funkce/metody
 
; testClass.function2(1, 2)
0015    GGET     0   0        ; přečtení reference na tabulku "testClass" z globální tabulky _G
0016    MOV      1   0        ; při volání se použije i skrytý parametr this/self
0017    TGETS    0   0   2    ; získání reference na funkci se jménem "function2"
0018    KSHORT   2   1        ; první parametr volané funkce - hodnota 1
0019    KSHORT   3   2        ; druhý parametr volané funkce - hodnota 2
0020    CALL     0   1   4    ; volání funkce/metody
 
; testClass.function2("xyzzy")
0021    GGET     0   0        ; přečtení reference na tabulku "testClass" z globální tabulky _G
0022    MOV      1   0        ; při volání se použije i skrytý parametr this/self
0023    TGETS    0   0   1    ; získání reference na funkci se jménem "function2"
0024    KSTR     2   3        ; první parametr volané funkce - odkaz na řetězec "xyzzy"
0025    CALL     0   1   3    ; volání funkce/metody
 
; end
0026    RET0     0   1
 
 
 
-- BYTECODE -- test22.lua:70-76
; function callfunction3()
 
; testClass.function3()
0001    GGET     0   0        ; přečtení reference na tabulku "testClass" z globální tabulky _G
0002    MOV      1   0        ; při volání se použije i skrytý parametr this/self
0003    TGETS    0   0   1    ; získání reference na funkci se jménem "function3"
0004    CALL     0   1   2    ; volání funkce/metody
 
; testClass.function3(nil)
0005    GGET     0   0        ; přečtení reference na tabulku "testClass" z globální tabulky _G
0006    MOV      1   0        ; při volání se použije i skrytý parametr this/self
0007    TGETS    0   0   1    ; získání reference na funkci se jménem "function3"
0008    KPRI     2   0        ; parametr volané funkce - hodnota nil
0009    CALL     0   1   3    ; volání funkce/metody
 
; testClass.function3(42)
0010    GGET     0   0        ; přečtení reference na tabulku "testClass" z globální tabulky _G
0011    MOV      1   0        ; při volání se použije i skrytý parametr this/self
0012    TGETS    0   0   1    ; získání reference na funkci se jménem "function3"
0013    KSHORT   2  42        ; parametr volané funkce - hodnota 42
0014    CALL     0   1   3    ; volání funkce/metody
 
; testClass.function3(1, 2)
0015    GGET     0   0        ; přečtení reference na tabulku "testClass" z globální tabulky _G
0016    MOV      1   0        ; při volání se použije i skrytý parametr this/self
0017    TGETS    0   0   1    ; získání reference na funkci se jménem "function3"
0018    KSHORT   2   1        ; první parametr volané funkce - hodnota 1
0019    KSHORT   3   2        ; druhý parametr volané funkce - hodnota 2
0020    CALL     0   1   4    ; volání funkce/metody
 
; testClass.function3("xyzzy")
0021    GGET     0   0        ; přečtení reference na tabulku "testClass" z globální tabulky _G
0022    MOV      1   0        ; při volání se použije i skrytý parametr this/self
0023    TGETS    0   0   1    ; získání reference na funkci se jménem "function3"
0024    KSTR     2   2        ; první parametr volané funkce - odkaz na řetězec "xyzzy"
0025    CALL     0   1   3    ; volání funkce/metody
 
; end
0026    RET0     0   1
 
 
 
-- BYTECODE -- test22.lua:83-87
; function main()
 
; callFunction1()
0001    GGET     0   0        ; získání reference na funkci se jménem "callFunction1"
0002    CALL     0   1   1    ; volání funkce
 
; callFunction2()
0003    GGET     0   1        ; získání reference na funkci se jménem "callFunction2"
0004    CALL     0   1   1    ; volání funkce
 
; callFunction3()
0005    GGET     0   2        ; získání reference na funkci se jménem "callFunction3"
0006    CALL     0   1   1    ; volání funkce
 
; end
0007    RET0     0   1        ; návrat z funkce
 
 
 
-- BYTECODE -- test22.lua:0-99
 
; main()
; vytvoření, "registrace" a následné volání funkce main(), inicializace třídy testClass
0001    TNEW     0   0        ; vytvoření nové tabulky
0002    GSET     0   0        ; uložení tabulky do _G pod jménem "testClass"
 
0003    GGET     0   0        ; přečtení reference na tabulku "testClass"
0004    FNEW     1   2        ; vytvoření uzávěru z prototypu začínajícího na řádku test22.lua:14
0005    TSETS    1   0   1    ; uložení uzávěru do vybrané tabulky _G pod jménem "function1"
 
0006    GGET     0   0        ; přečtení reference na tabulku "testClass"
0007    FNEW     1   4        ; vytvoření uzávěru z prototypu začínajícího na řádku test22.lua:22
0008    TSETS    1   0   3    ; uložení uzávěru do vybrané tabulky _G pod jménem "function2"
 
0009    GGET     0   0        ; přečtení reference na tabulku "testClass"
0010    FNEW     1   6        ; vytvoření uzávěru z prototypu začínajícího na řádku test22.lua:31
0011    TSETS    1   0   5    ; uložení uzávěru do vybrané tabulky _G pod jménem "function3"
 
0012    FNEW     0   7        ; vytvoření uzávěru z prototypu začínajícího na řádku test22.lua:44
0013    GSET     0   8        ; uložení uzávěru do globální tabulky _G pod jménem "callFunction1"
 
0014    FNEW     0   9        ; vytvoření uzávěru z prototypu začínajícího na řádku test22.lua:57
0015    GSET     0  10        ; uložení uzávěru do globální tabulky _G pod jménem "callFunction2"
 
0016    FNEW     0  11        ; vytvoření uzávěru z prototypu začínajícího na řádku test22.lua:70
0017    GSET     0  12        ; uložení uzávěru do globální tabulky _G pod jménem "callFunction3"
 
0018    FNEW     0  13        ; vytvoření uzávěru z prototypu začínajícího na řádku test22.lua:83
0019    GSET     0  14        ; uložení uzávěru do globální tabulky _G pod jménem "main"
 
0020    GGET     0  14        ; získání reference na funkci se jménem "main"
0021    CALL     0   1   1    ; zavolání funkce main()
 
0022    RET0     0   1        ; návrat z programu
 
; konec

7. Demonstrační příklad test23.lua: způsob vracení parametrů z volaných funkcí

V pátém a současně i v dnešním posledním demonstračním příkladu nazvaném test23.lua si vysvětlíme způsob vracení parametrů z volaných funkcí. Taktéž si ukážeme, jak LuaJIT optimalizuje volání typu print(funcX()) v případě, že se z funkce funcX() vrací větší počet hodnot. Technika využívaná LuaJITem se v mnoha ohledech odlišuje od technik, které najdeme v jiných překladačích popř. v odlišných bajtkódech.

7.1 Zdrojový kód příkladu test23.lua

Nejprve si ukažme zdrojový kód pátého demonstračního příkladu, v němž můžeme vidět deklaraci čtyř funkcí nazvaných function1function4. Funkce vrací různý počet i typ parametrů. Tyto funkce jsou následně volány stylem print(function1()), což znamená, že hodnota či hodnoty vrácené funkcí jsou ihned předány do další funkce:

--
-- LuaJIT: demonstrační příklad číslo 23
--
-- Volání funkci v programovacím jazyce Lua
-- a vraceni hodnot z funkci.
--
 
 
 
--
-- Funkce nevracející žádnou hodnotu.
--
function function1()
end
 
 
 
--
-- Funkce vracející jednu hodnotu.
--
function function2()
    return 42
end
 
 
 
--
-- Funkce vracející dvě hodnoty
--
function function3()
    return 1,2
end
 
 
 
--
-- Další funkce vracející dvě hodnoty
--
function function4()
    return 1,nil
end
 
 
 
--
-- Spuštění testu.
--
function main()
    print(function1());
    print(function2());
    print(function3());
    print(function4());
end
 
 
 
main()
 
 
-- finito

7.2 Překlad příkladu test23.lua do mezijazyka LuaJITu

V IR dnešního posledního demonstračního příkladu je patrné, jak se překládá příkaz print(function1()) a samozřejmě i všechny podobné příkazy. Využívá se zde dvojice instrukcí CALL+CALLM, přičemž druhá zmíněná instrukce dokáže zpracovat libovolný počet hodnot předaných přes sloty:

0001    GGET     0   0        ; přečtení reference na funkci "print"
0002    GGET     1   1        ; přečtení reference na funkci "function1"
0003    CALL     1   0   1    ; zavolání funkce function1()
0004    CALLM    0   1   0    ; zavolání funkce print() s parametry vrácenými předchozí funkcí

Následuje výpis celého IR:

; Překlad demonstračního příkladu test23.lua
; do IR využívaného virtuálním strojem a JIT
; překladačem LuaJIT.
 
-- BYTECODE -- test23.lua:13-14
; function function1()
 
; end
0001    RET0     0   1        ; návrat z funkce
 
 
 
-- BYTECODE -- test23.lua:21-23
; function function2()
 
; return 42
0001    KSHORT   0  42        ; do slotu 0 uložit konstantu
0002    RET1     0   2        ; návrat z funkce + předání návratové hodnoty
 
 
 
-- BYTECODE -- test23.lua:30-32
; function function3()
 
; return 1,2
0001    KSHORT   0   1        ; do slotu 0 uložit konstantu
0002    KSHORT   1   2        ; do slotu 1 uložit konstantu
0003    RET      0   3        ; návrat z funkce + předání návratových hodnot
 
 
 
-- BYTECODE -- test23.lua:39-41
; function function4()
0001    KSHORT   0   1        ; do slotu 0 uložit konstantu
0002    KPRI     1   0        ; do slotu 1 uložit konstantu
0003    RET      0   3        ; návrat z funkce + předání návratových hodnot
 
 
 
-- BYTECODE -- test23.lua:48-53
; function main()
 
0001    GGET     0   0        ; přečtení reference na funkci "print"
0002    GGET     1   1        ; přečtení reference na funkci "function1"
0003    CALL     1   0   1    ; zavolání funkce function1()
0004    CALLM    0   1   0    ; zavolání funkce print() s parametry vrácenými předchozí funkcí
 
0005    GGET     0   0        ; přečtení reference na funkci "print"
0006    GGET     1   2        ; přečtení reference na funkci "function2"
0007    CALL     1   0   1    ; zavolání funkce function2()
0008    CALLM    0   1   0    ; zavolání funkce print() s parametry vrácenými předchozí funkcí
 
0009    GGET     0   0        ; přečtení reference na funkci "print"
0010    GGET     1   3        ; přečtení reference na funkci "function3"
0011    CALL     1   0   1    ; zavolání funkce function3()
0012    CALLM    0   1   0    ; zavolání funkce print() s parametry vrácenými předchozí funkcí
 
0013    GGET     0   0        ; přečtení reference na funkci "print"
0014    GGET     1   4        ; přečtení reference na funkci "function4"
0015    CALL     1   0   1    ; zavolání funkce function4()
0016    CALLM    0   1   0    ; zavolání funkce print() s parametry vrácenými předchozí funkcí
 
0017    RET0     0   1        ; návrat z funkce
 
 
 
-- BYTECODE -- test23.lua:0-62
; main()
; vytvoření a "registrace" všech funkcí
0001    FNEW     0   0        ; vytvoření uzávěru z prototypu začínajícího na řádku test23.lua:13
0002    GSET     0   1        ; "uložení uzávěru do globální tabulky _G pod jménem function1"
 
0003    FNEW     0   2        ; vytvoření uzávěru z prototypu začínajícího na řádku test23.lua:21
0004    GSET     0   3        ; uložení uzávěru do globální tabulky _G pod jménem "function2"
 
0005    FNEW     0   4        ; vytvoření uzávěru z prototypu začínajícího na řádku test23.lua:30
0006    GSET     0   5        ; uložení uzávěru do globální tabulky _G pod jménem "function3"
 
0007    FNEW     0   6        ; vytvoření uzávěru z prototypu začínajícího na řádku test23.lua:39
0008    GSET     0   7        ; uložení uzávěru do globální tabulky _G pod jménem "function4"
 
0009    FNEW     0   8        ; vytvoření uzávěru z prototypu začínajícího na řádku test23.lua:48
0010    GSET     0   9        ; uložení uzávěru do globální tabulky _G pod jménem "main"
 
0011    GGET     0   9        ; získání reference na funkci se jménem "main"
0012    CALL     0   1   1    ; zavolání funkce main()
 
0013    RET0     0   1        ; návrat z programu
 
; konec

8. Repositář se zdrojovými kódy všech pěti dnešních demonstračních příkladů

Všech pět dnes popsaných a taktéž „disasemblovaných“ demonstračních příkladů bylo uloženo do Git repositáře umístěného na adrese https://github.com/tisnik/luajit-examples. Odkazy na prozatím poslední verze těchto pěti příkladů naleznete v tabulce umístěné pod tímto odstavcem:

9. Odkazy na Internetu

  1. Wikipedia: Mezijazyk
    http://cs.wikipedia.org/wi­ki/Mezijazyk
  2. The LuaJIT Project
    http://luajit.org/index.html
  3. LuaJIT FAQ
    http://luajit.org/faq.html
  4. LuaJIT Performance Comparison
    http://luajit.org/performance.html
  5. LuaJIT 2.0 intellectual property disclosure and research opportunities
    http://article.gmane.org/gma­ne.comp.lang.lua.general/58908
  6. LuaJIT Wiki
    http://wiki.luajit.org/Home
  7. LuaJIT 2.0 Bytecode Instructions
    http://wiki.luajit.org/Bytecode-2.0
  8. Programming in Lua 9.1 – Coroutine Basics,
    http://www.lua.org/pil/9.1.html
  9. Programming in Lua (first edition)
    http://www.lua.org/pil/contents.html
  10. Programming in Lua: 6 – More about Functions
    http://www.lua.org/pil/6.html
  11. Lua Lanes
    http://kotisivu.dnainternet­.net/askok/bin/lanes/
  12. Programming in Lua: 6.1 – Closures
    http://www.lua.org/pil/6.1.html
  13. Programming in Lua: 9.1 – Coroutine Basics
    http://www.lua.org/pil/9.1.html
  14. Programming in Lua: Numeric for
    http://www.lua.org/pil/4.3.4.html
  15. Programming in Lua: break and return
    http://www.lua.org/pil/4.4.html
  16. Programming in Lua: Tables
    http://www.lua.org/pil/2.5.html
  17. Programming in Lua: Table Constructors
    http://www.lua.org/pil/3.6.html
  18. Programovací jazyk Lua
    http://palmknihy.cz/web/kni­ha/programovaci-jazyk-lua-12651.htm
  19. Lua: Tables Tutorial
    http://lua-users.org/wiki/TablesTutorial
  20. Lua: Control Structure Tutorial
    http://lua-users.org/wiki/ControlStruc­tureTutorial
  21. Lua Types Tutorial
    http://lua-users.org/wiki/LuaTypesTutorial
  22. Goto Statement in Lua
    http://lua-users.org/wiki/GotoStatement
  23. Lua 5.2 sources
    http://www.lua.org/source/5.2/
  24. Lua 5.2 sources – lopcodes.h
    http://www.lua.org/source/5­.2/lopcodes.h.html
  25. Lua 5.2 sources – lopcodes.c
    http://www.lua.org/source/5­.2/lopcodes.c.html
  26. Lambda the Ultimate: Coroutines in Lua,
    http://lambda-the-ultimate.org/node/438
  27. Coroutines Tutorial,
    http://lua-users.org/wiki/CoroutinesTutorial
  28. Lua Coroutines Versus Python Generators,
    http://lua-users.org/wiki/LuaCorouti­nesVersusPythonGenerators