久久精品国产精品国产精品污,男人扒开添女人下部免费视频,一级国产69式性姿势免费视频,夜鲁夜鲁很鲁在线视频 视频,欧美丰满少妇一区二区三区,国产偷国产偷亚洲高清人乐享,中文 在线 日韩 亚洲 欧美,熟妇人妻无乱码中文字幕真矢织江,一区二区三区人妻制服国产

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Lua 5.1 参考手册

發(fā)布時間:2025/3/21 编程问答 16 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Lua 5.1 参考手册 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Lua 5.1 參考手冊

by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes

云風(fēng) 譯?www.codingnow.com

Copyright?? 2006 Lua.org, PUC-Rio. All rights reserved.


1 -?介紹

Lua 是一個擴展式程序設(shè)計語言,它被設(shè)計成支持通用的過程式編程,并有相關(guān)數(shù)據(jù)描述的設(shè)施。 Lua 也能對面向?qū)ο缶幊?#xff0c;函數(shù)式編程,數(shù)據(jù)驅(qū)動式編程提供很好的支持。 它可以作為一個強大、輕量的腳本語言,供任何需要的程序使用。 Lua 以一個用?clean?C 寫成的庫形式提供。(所謂 Clean C ,指的 ANSI C 和 C++ 中共通的一個子集)

作為一個擴展式語言,Lua 沒有 "main" 程序的概念:它只能?嵌入?一個宿主程序中工作,這個宿主程序被稱作?embedding program?或簡稱為?host?。 宿主程序可以通過調(diào)用函數(shù)執(zhí)行一小段 Lua 代碼,可以讀寫 Lua 變量,可以注入 C 函數(shù)讓 Lua 代碼調(diào)用。 這些擴展的 C 函數(shù),可以大大的擴展了 Lua 可以處理事務(wù)的領(lǐng)域,這樣就可以訂制出各種語言, 而它們共享一個統(tǒng)一的句法格式的框架。 Lua 的官方發(fā)布版就包含了一個叫做?lua?的簡單的宿主程序,它用 Lua 庫提供了一個保證獨立的 Lua 解釋器。

Lua 是一個自由軟件,它的使用許可決定了對它的使用過程一般沒有任何保證。 這份手冊中描述的東西的實現(xiàn),可以在 Lua 的官方網(wǎng)站?www.lua.org?找到,

跟其它的許多參考手冊一樣,這份文檔有些地方比較枯燥。 關(guān)于 Lua 的設(shè)計想法的探討,可以看看 Lua 網(wǎng)站上提供的技術(shù)論文。 有關(guān)用 Lua 編程的細節(jié)介紹,可以讀一下 Roberto 的書,Programming in Lua (Second Edition)?。

2 -?語言

這一節(jié)從詞法、語法、句法上描述 Lua 。 換句話說,這一節(jié)描述了哪些 token (符記)是有效的,它們?nèi)绾伪唤M合起來,這些組合方式有什么含義。

關(guān)于語言的構(gòu)成概念將用常見的擴展 BNF 表達式寫出。也就是這個樣子: {a} 意思是 0 或多個?a?, [a] 意思是一個可選的?a?。 非最終的符號會保留原來的樣子,關(guān)鍵字則看起來像這樣?kword?, 其它最終的符號則寫成 `=′ 。 完整的 Lua 語法可以在本手冊最后找到。

2.1 -?詞法約定

Lua 中用到的?名字(也稱作?標(biāo)識符)可以是任何非數(shù)字開頭的字母、數(shù)字、下劃線組成的字符串。 這符合幾乎所有編程語言中關(guān)于名字的定義。 (字母的定義依賴于當(dāng)前環(huán)境:系統(tǒng)環(huán)境中定義的字母表中的字母都可以被用于標(biāo)識符。) 標(biāo)識符用來命名變量,或作為表的域名。

下面的關(guān)鍵字是保留的,不能用作名字:

and break do else elseifend false for function ifin local nil not orrepeat return then true until while

Lua 是一個大小寫敏感的語言:?and?是一個保留字,但是?And?和?AND?則是兩個不同的合法的名字。 一般約定,以下劃線開頭連接一串大寫字母的名字(比如_VERSION)被保留用于 Lua 內(nèi)部全局變量。

下面這些是其它的 token :

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

字符串既可以用一對單引號引起,也可以是雙引號,里面還可以包含類似 C 的轉(zhuǎn)義符: '\a' (響鈴), '\b' (退格), '\f' (表單), '\n' (換行), '\r' (回車), '\t' (橫向制表), '\v' (縱向制表), '\\' (反斜杠), '\"' (雙引號), 以及 '\'' (單引號)。 而且,如果在一個反斜杠后跟了一個真正的換行符,其結(jié)果就是在字符串中產(chǎn)生一個換行符。 我們還可以用反斜杠加數(shù)字的形式?\ddd?來描述一個字符。這里,?ddd?是一串最多三位的十進制數(shù)字。(注意,如果需要在這種描述方法后接一個是數(shù)字的字符, 那么反斜杠后必須寫滿三個數(shù)字。)Lua 中的字符串可以包含任何 8 位的值。包括用 '\0' 表示的零。

只有在你需要把不同的引號、換行、反斜杠、或是零結(jié)束符這些字符置入字符串時, 你才必須使用轉(zhuǎn)義符。別的任何字符都可以直接寫在文本里。(一些控制符可以會影響文件系統(tǒng)造成某些問題, 但是不會引起 Lua 的任何問題。)

字符串還可以用一種長括號括起來的方式定義。 我們把兩個正的方括號間插入 n 個等號定義為第 n 級正長括號。 就是說,0 級正的長括號寫作?[[?, 一級正的長括號寫作?[=[?,如此等等。 反的長擴展也作類似定義; 舉個例子,4 級反的長括號寫作?]====]?。 一個長字符串可以由任何一級的正的長括號開始,而由第一個碰到的同級反的長括號結(jié)束。 整個詞法分析過程將不受分行限制,不處理任何轉(zhuǎn)意符,并且忽略掉任何不同級別的長括號。 這種方式描述的字符串可以包含任何東西,當(dāng)然特定級別的反長括號除外。

另一個約定是,當(dāng)正的長括號后面立即跟了一個換行符, 這個換行符就不包含在這個字符串內(nèi)。 舉個例子,假設(shè)一個系統(tǒng)使用 ASCII 碼 (這時,'a' 編碼為 97 ,換行符編碼為 10 ,'1' 編碼為 49 ), 下面五種方式描述了完全相同的字符串:

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

數(shù)字常量可以分兩部分寫,十進制底數(shù)部分和十進制的指數(shù)部分。指數(shù)部分是可選的。 Lua 也支持十六進制整數(shù)常量,只需要在前面加上前綴?0x?。 下面是一些合法的數(shù)字常量的例子:

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

注釋可以在除字符串內(nèi)的任何地方是以兩橫 (--) 開始。 如果跟在兩橫后面的不是一個長括號,這就是一個短注釋,它的作用范圍直到行末; 否則就是一個長注釋,其作用范圍直到遇到反的長括號。 長注釋通常被用來臨時屏蔽代碼塊。

2.2 -?值與類型

Lua 是一種?動態(tài)類型語言。 這意味著變量沒有類型,只有值才有類型。 語言中不存在類型定義。而所有的值本身攜帶它們自己的類型信息。

Lua 中的所有值都是一致 (first-class) 的。 這意味著所有的值都可以被放在變量里,當(dāng)作參數(shù)傳遞到另一個函數(shù)中,并被函數(shù)作為結(jié)果返回。

Lua 中有八種基本類型:?nil,?boolean,?number,?string,?function,?userdata,?thread, and?table.?Nil?類型只有一種值?nil?,它的主要用途用于標(biāo)表識和別的任何值的差異; 通常,當(dāng)需要描述一個無意義的值時會用到它。?Boolean?類型只有兩種值:false?和?true。?nil?和?false?都能導(dǎo)致條件為假;而另外所有的值都被當(dāng)作真。?Number?表示實數(shù)(雙精度浮點數(shù))。 (編譯一個其它內(nèi)部數(shù)字類型的 Lua 解釋器是件很容易的事;比如把內(nèi)部數(shù)字類型改作 單精度浮點數(shù)或長整型。參見文件?luaconf.h?。)?String?表示一串字符的數(shù)組。 Lua 是 8-bit clean 的: 字符串可以包含任何 8 位字符, 包括零結(jié)束符 ('\0') (參見?§2.1)。

Lua 可以調(diào)用(和處理)用 Lua 寫的函數(shù)以及用 C 寫的函數(shù)(參見?§2.5.8).

userdata?類型用來將任意 C 數(shù)據(jù)保存在 Lua 變量中。 這個類型相當(dāng)于一塊原生的內(nèi)存,除了賦值和相同性判斷,Lua 沒有為之預(yù)定義任何操作。 然而,通過使用metatable (元表)?,程序員可以為 userdata 自定義一組操作 (參見?§2.8)。 userdata 不能在 Lua 中創(chuàng)建出來,也不能在 Lua 中修改。這樣的操作只能通過 C API。 這一點保證了宿主程序完全掌管其中的數(shù)據(jù)。

thread?類型用來區(qū)別獨立的執(zhí)行線程,它被用來實現(xiàn) coroutine (協(xié)同例程)(參見?§2.11)。 不要把 Lua 線程跟操作系統(tǒng)的線程搞混。 Lua 可以在所有的系統(tǒng)上提供對 coroutine 的支持,即使系統(tǒng)并不支持線程。

table?類型實現(xiàn)了一個關(guān)聯(lián)數(shù)組。也就是說, 數(shù)組可以用任何東西(除了nil)做索引,而不限于數(shù)字。 table 可以以不同類型的值構(gòu)成;它可以包含所有的類型的值(除?nil?外)。 table 是 lua 中唯一的一種數(shù)據(jù)結(jié)構(gòu);它可以用來描述原始的數(shù)組、符號表、集合、 記錄、圖、樹、等等。 用于表述記錄時,lua 使用域名作為索引。 語言本身采用一種語法糖,支持以?a.name?的形式表示?a["name"]。 有很多形式用于在 lua 中創(chuàng)建一個 table (參見?§2.5.7)。

跟索引一樣, table 每個域中的值也可以是任何類型(除?nil外)。 特別的,因為函數(shù)本身也是值,所以 table 的域中也可以放函數(shù)。 這樣 table 中就可以有一些?methods?了 (參見see?§2.5.9)。

table, function ,thread ,和 (full) userdata 這些類型的值是所謂的對象: 變量本身并不會真正的存放它們的值,而只是放了一個對對象的引用。 賦值,參數(shù)傳遞,函數(shù)返回,都是對這些對象的引用進行操作; 這些操作不會做暗地里做任何性質(zhì)的拷貝。

庫函數(shù)?type?可以返回一個描述給定值的類型的字符串。

2.2.1 -?強制轉(zhuǎn)換

Lua 提供運行時字符串到數(shù)字的自動轉(zhuǎn)換。 任何對字符串的數(shù)學(xué)運算操作都會嘗試用一般的轉(zhuǎn)換規(guī)則把這個字符串轉(zhuǎn)換成一個數(shù)字。 相反,無論何時,一個數(shù)字需要作為字符串來使用時,數(shù)字都會以合理的格式轉(zhuǎn)換為字符串。 需要完全控制數(shù)字怎樣轉(zhuǎn)換為字符串,可以使用字符串庫中的?format?函數(shù) (參見?string.format)。

2.3 -?變量

寫上變量的地方意味著當(dāng)以其保存的值來替代之。 Lua 中有三類變量:全局變量,局部變量,還有 table 的域。

一個單一的名字可以表示一個全局變量,也可以表示一個局部變量 (或者是一個函數(shù)的參數(shù),這是一種特殊形式的局部變量):

var ::= Name

Name 就是?§2.1?中所定義的標(biāo)識符。

任何變量都被假定為全局變量,除非顯式的以 local 修飾定義 (參見?§2.4.7)。 局部變量有其作用范圍: 局部變量可以被定義在它作用范圍中的函數(shù)自由使用 (參見?§2.6)。

在變量的首次賦值之前,變量的值均為?nil

方括號被用來對 table 作索引:

var ::= prefixexp `[′ exp `]

對全局變量以及 table 域之訪問的含義可以通過 metatable 來改變。 以取一個變量下標(biāo)指向的量?t[i]?等價于調(diào)用?gettable_event(t,i)。 (參見?§2.8?,有一份完整的關(guān)于?gettable_event?函數(shù)的說明。 這個函數(shù)并沒有在 lua 中定義出來,也不能在 lua 中調(diào)用。 這里我們把它列出來只是方便說明。)

var.Name?這種語法只是一個語法糖,用來表示?var["Name"]:

var ::= prefixexp `.′ Name

所有的全局變量都是放在一個特定 lua table 的諸個域中,這個特定的 table 叫作?environment (環(huán)境)table?或者簡稱為?環(huán)境?(參見?§2.9)。 每個函數(shù)都有對一個環(huán)境的引用, 所以一個函數(shù)中可見的所有全局變量都放在這個函數(shù)所引用的環(huán)境表(environment table)中。 當(dāng)一個函數(shù)被創(chuàng)建出來,它會從創(chuàng)建它的函數(shù)中繼承其環(huán)境,你可以調(diào)用?getfenv?取得其環(huán)境。 如果想改變環(huán)境,可以調(diào)用?setfenv。 (對于 C 函數(shù),你只能通過 debug 庫來改變其環(huán)境; 參見?§5.9)。

對一個全局變量?x?的訪問 等價于?_env.x,而這又可以等價于

gettable_event(_env, "x")

這里,_env?是當(dāng)前運行的函數(shù)的環(huán)境。 (函數(shù)?gettable_event?的完整說明參見?§2.8。 這個函數(shù)并沒有在 lua 中定義出來,也不能調(diào)用。 當(dāng)然,_env?這個變量也同樣沒有在 Lua 中定義出來。 我們在這里使用它們,僅僅只是方便解釋而已。)

2.4 -?語句段(Statement)

Lua 支持慣例形式的語句段,它和 Pascal 或是 C 很相象。 這個集合包括賦值,控制結(jié)構(gòu),函數(shù)調(diào)用,還有變量聲明。

2.4.1 -?Chunk(語句組)

Lua 的一個執(zhí)行單元被稱作?chunk。 一個 chunk 就是一串語句段,它們會被循序的執(zhí)行。 每個語句段可以以一個分號結(jié)束:

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

這兒不允許有空的語句段,所以 ';;' 是非法的。

lua 把一個 chunk 當(dāng)作一個擁有不定參數(shù)的匿名函數(shù) (參見?§2.5.9)處理。 正是這樣,chunk 內(nèi)可以定義局部變量,接收參數(shù),并且返回值。

chunk 可以被保存在一個文件中,也可以保存在宿主程序的一個字符串中。 當(dāng)一個 chunk 被執(zhí)行,首先它會被預(yù)編譯成虛擬機中的指令序列, 然后被虛擬機解釋運行這些指令。

chunk 也可以被預(yù)編譯成二進制形式;細節(jié)參考程序?luac。 用源碼形式提供的程序和被編譯過的二進制形式的程序是可以相互替換的; Lua 會自動識別文件類型并做正確的處理。

2.4.2 -?語句塊

語句塊是一列語句段;從語法上來說,一個語句塊跟一個 chunk 相同:

block ::= chunk

一個語句塊可以被顯式的寫成一個單獨的語句段:

stat ::= do block end

顯式的語句塊對于控制變量的作用范圍很有用。 有時候,顯式的語句塊被用來在另一個語句塊中插入?return?或是?break?(參見?§2.4.4)。

2.4.3 -?賦值

Lua 允許多重賦值。 因此,賦值的語法定義是等號左邊放一系列變量, 而等號右邊放一系列的表達式。 兩邊的元素都用逗號間開:

stat ::= varlist1 `=′ explist1varlist1 ::= var {`,′ var}explist1 ::= exp {`,′ exp}

表達式放在?§2.5?里討論。

在作賦值操作之前, 那一系列的右值會被對齊到左邊變量需要的個數(shù)。 如果右值比需要的更多的話,多余的值就被扔掉。 如果右值的數(shù)量不夠需求, 將會按所需擴展若干個?nil。 如果表達式列表以一個函數(shù)調(diào)用結(jié)束, 這個函數(shù)所返回的所有值都會在對齊操作之前被置入右值序列中。 (除非這個函數(shù)調(diào)用被用括號括了起來;參見?§2.5)。

賦值段首先會做運算完所有的表達式,然后僅僅做賦值操作。 因此,下面這段代碼

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

會把?a[3]?設(shè)置為 20,而不會影響到?a[4]?。 這是因為?a[i]?中的?i?在被賦值為 4 之前就被拿出來了(那時是 3 )。 簡單說 ,這樣一行

x, y = y, x

可以用來交換?x?和?y?中的值。

對全局變量以及 table 中的域的賦值操作的含義可以通過 metatable 來改變。 對變量下標(biāo)指向的賦值,即?t[i] = val?等價于?settable_event(t,i,val)。 (關(guān)于函數(shù)settable_event?的詳細說明,參見?§2.8。 這個函數(shù)并沒有在 Lua 中定義出來,也不可以被調(diào)用。 這里我們列出來,僅僅出于方便解釋的目的)

對于全局變量的賦值?x = val?等價于?_env.x = val,這個又可以等價于

settable_event(_env, "x", val)

這里,_env?指的是正在運行中的函數(shù)的環(huán)境。 (變量?_env?并沒有在 Lua 中定義出來。 我們僅僅出于解釋的目的在這里寫出來。)

2.4.4 -?控制結(jié)構(gòu)

if、?while、以及?repeat?這些控制結(jié)構(gòu)符合通常的意義,而且也有類似的語法:

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

Lua 也有一個?for?語句,它有兩種形式(參見?§2.4.5)。

控制結(jié)構(gòu)中的條件表達式可以返回任何值。?false?和?nil?兩者都被認為是假條件。 所有不同于?nil?和?false?的其它值都被認為是真 (特別需要注意的是,數(shù)字 0 和空字符串也被認為是真)。

在?repeatuntil?循環(huán)中, 內(nèi)部語句塊的結(jié)束點不是在?until?這個關(guān)鍵字處, 它還包括了其后的條件表達式。 因此,條件表達式中可以使用循環(huán)內(nèi)部語句塊中的定義的局部變量。

return?被用于從函數(shù)或是 chunk(其實它就是一個函數(shù))中 返回值。 函數(shù)和 chunk 可以返回不只一個值, 所以?return?的語法為

stat ::= return [explist1]

break?被用來結(jié)束?while、?repeat、或?for?循環(huán), 它將忽略掉循環(huán)中下面的語句段的運行:

stat ::= break

break?跳出最內(nèi)層的循環(huán)。

return?和?break?只能被寫在一個語句塊的最后一句。 如果你真的需要從語句塊的中間?return?或是?break?, 你可以使用顯式的聲名一個內(nèi)部語句塊。 一般寫作do return end?或是?do break end, 可以這樣寫是因為現(xiàn)在?return?或?break?都成了一個語句塊的最后一句了。

2.4.5 -?For 語句

for?有兩種形式:一種是數(shù)字形式,另一種是一般形式。

數(shù)字形式的?for?循環(huán),通過一個數(shù)學(xué)運算不斷的運行內(nèi)部的代碼塊。 下面是它的語法:

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

block?將把?name?作循環(huán)變量。從第一個?exp?開始起,直到第二個?exp?的值為止,其步長為 第三個?exp?。 更確切的說,一個?for?循環(huán)看起來是這個樣子

for v = e1, e2, e3 do block end

這等價于代碼:

dolocal var, limit, step = tonumber(e1), tonumber(e2), tonumber(e3)if not (var and limit and step) then error() endwhile (step > 0 and var <= limit) or (step <= 0 and var >= limit) dolocal v = varblockvar = var + stependend

注意下面這幾點:

  • 所有三個控制表達式都只被運算一次,表達式的計算在循環(huán)開始之前。 這些表達式的結(jié)果必須是數(shù)字。
  • var?、limit?、以及?step?都是一些不可見的變量。 這里給它們起的名字都僅僅用于解釋方便。
  • 如果第三個表達式(步長)沒有給出,會把步長設(shè)為 1 。
  • 你可以用?break?來退出?for?循環(huán)。
  • 循環(huán)變量?v?是一個循環(huán)內(nèi)部的局部變量; 當(dāng)?for?循環(huán)結(jié)束后,你就不能在使用它。 如果你需要這個值,在退出循環(huán)前把它賦給另一個變量。

一般形式的?for?通過一個叫作迭代器(iterators)的函數(shù)工作。 每次迭代,迭代器函數(shù)都會被調(diào)用以產(chǎn)生一個新的值, 當(dāng)這個值為?nil?時,循環(huán)停止。 一般形式的?for?循環(huán)的語法如下:

stat ::= for namelist in explist1 do block endnamelist ::= Name {`,′ Name}

for?語句好似這樣

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

它等價于這樣一段代碼:

dolocal f, s, var = explistwhile true dolocal var_1, ···, var_n = f(s, var)var = var_1if var == nil then break endblockendend

注意以下幾點:

  • explist?只會被計算一次。 它返回三個值, 一個迭代器函數(shù),一個狀態(tài),一個迭代器的初始值。
  • f、?s、 以及?var?都是不可見的變量。 這里給它們起的名字都只是為了解說方便。
  • 你可以使用?break?來跳出?for?循環(huán)。
  • 循環(huán)變量?var_i?對于循環(huán)來說是一個局部變量; 你不可以在?for?循環(huán)結(jié)束后繼續(xù)使用。 如果你需要保留這些值,那么就在循環(huán)結(jié)束前賦值到別的變量里去。

2.4.6 -?把函數(shù)調(diào)用作為語句段

為了允許使用可能的副作用, 函數(shù)調(diào)用可以被作為一個語句段執(zhí)行:

stat ::= functioncall

在這種情況下,所有的返回值都被舍棄。 函數(shù)調(diào)用在?§2.5.8?中解釋。

2.4.7 -?局部變量聲名

局部變量可以在語句塊中任何地方聲名。 聲名可以包含一個初始化賦值操作:

stat ::= local namelist [`=′ explist1]

如果有的話,初始化賦值操作的行為等同于賦值操作(參見?§2.4.3)。 否則,所有的變量將被初始化為?nil

一個 chunk 同時也是一個語句塊(參見?§2.4.1), 所以局部變量可以放在 chunk 中那些顯式注明的語句塊之外。 這些局部變量的作用范圍從聲明起一直延伸到 chunk 末尾。

局部變量的可見規(guī)則在?§2.6?中解釋。

2.5 -?表達式

Lua 中有這些基本表達式:

exp ::= prefixexpexp ::= nil | false | trueexp ::= Numberexp ::= Stringexp ::= functionexp ::= tableconstructorexp ::= `...′exp ::= exp binop expexp ::= unop expprefixexp ::= var | functioncall | `(′ exp `)

數(shù)字和字符串在?§2.1?中解釋; 變量在?§2.3?中解釋; 函數(shù)定義在?§2.5.9?中解釋; 函數(shù)調(diào)用在?§2.5.8?中解釋; table 的構(gòu)造在?§2.5.7?中解釋; 可變參數(shù)的表達式寫作三個點 ('...') ,它只能被用在有可變參數(shù)的函數(shù)中; 這些在?§2.5.9?中解釋。

二元操作符包含有數(shù)學(xué)運算操作符(參見?§2.5.1), 比較操作符(參見?§2.5.2),邏輯操作符(參見?§2.5.3), 以及連接操作符(參見?§2.5.4)。 一元操作符包括負號(參見see?§2.5.1), 取反?not(參見?§2.5.3), 和取長度操作符(參見?§2.5.5)。

函數(shù)調(diào)用和可變參數(shù)表達式都可以放在多重返回值中。 如果表達式作為一個獨立語句段出現(xiàn)(參見?§2.4.6) (這只能是一個函數(shù)調(diào)用), 它們的返回列表將被對齊到零個元素,也就是忽略所有返回值。 如果表達式用于表達式列表的最后(或者是唯一)的元素, 就不會有任何的對齊操作(除非函數(shù)調(diào)用用括號括起來)。 在任何其它的情況下,Lua 將把表達式結(jié)果看成單一元素, 忽略除第一個之外的任何值。

這里有一些例子:

f() -- 調(diào)整到 0 個結(jié)果g(f(), x) -- f() 被調(diào)整到一個結(jié)果g(x, f()) -- g 被傳入 x 加上所有 f() 的返回值a,b,c = f(), x -- f() 被調(diào)整到一個結(jié)果 ( c 在這里被賦為 nil )a,b = ... -- a 被賦值為可變參數(shù)中的第一個,-- b 被賦值為第二個 (如果可變參數(shù)中并沒有對應(yīng)的值,-- 這里 a 和 b 都有可能被賦為 nil)a,b,c = x, f() -- f() 被調(diào)整為兩個結(jié)果a,b,c = f() -- f() 被調(diào)整為三個結(jié)果return f() -- 返回 f() 返回的所有結(jié)果return ... -- 返回所有從可變參數(shù)中接收來的值return x,y,f() -- 返回 x, y, 以及所有 f() 的返回值{f()} -- 用 f() 的所有返回值創(chuàng)建一個列表{...} -- 用可變參數(shù)中的所有值創(chuàng)建一個列表{f(), nil} -- f() 被調(diào)整為一個結(jié)果

被括號括起來的表達式永遠被當(dāng)作一個值。所以,?(f(x,y,z))?即使?f?返回多個值,這個表達式永遠是一個單一值。 ((f(x,y,z))?的值是?f?返回的第一個值。如果?f不返回值的話,那么它的值就是?nil?。)

2.5.1 -?數(shù)學(xué)運算操作符

Lua 支持常見的數(shù)學(xué)運算操作符: 二元操作?+?(加法),?-?(減法),*?(乘法),?/?(除法),?%?(取模),以及?^?(冪); 和一元操作?-?(取負)。 如果對數(shù)字操作,或是可以轉(zhuǎn)換為數(shù)字的字符串(參見?§2.2.1), 所有這些操作都依賴它通常的含義。 冪操作可以對任何冪值都正常工作。比如,?x^(-0.5)?將計算出?x平方根的倒數(shù)。 取模操作被定義為

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

這就是說,其結(jié)果是商相對負無窮圓整后的余數(shù)。(譯注:負數(shù)對正數(shù)取模的結(jié)果為正數(shù))

2.5.2 -?比較操作符

Lua 中的比較操作符有

== ~= < > <= >=

這些操作的結(jié)果不是?false?就是?true

等于操作 (==) 首先比較操作數(shù)的類型。 如果類型不同,結(jié)果就是?false。 否則,繼續(xù)比較值。 數(shù)字和字符串都用常規(guī)的方式比較。 對象 (table ,userdata ,thread ,以及函數(shù))以引用的形式比較: 兩個對象只有在它們指向同一個東西時才認為相等。 每次你創(chuàng)建一個新對象(一個 table 或是 userdata ,thread 函數(shù)), 它們都各不相同,即不同于上次創(chuàng)建的東西。

你可以改變 Lua 比較 table 和 userdata 的方式,這需要使用 "eq" 這個原方法 (參見?§2.8)。

§2.2.1?中提及的轉(zhuǎn)換規(guī)則并不作用于比較操作。 所以,?"0"==0?等于?false, 而且?t[0]?和?t["0"]?描述的是 table 中不同的域。

操作符?~=?完全等價于 (==) 操作的反值。

大小比較操作以以下方式進行。 如果參數(shù)都是數(shù)字,那么就直接做數(shù)字比較。 否則,如果參數(shù)都是字符串,就用字符串比較的方式進行。 再則,Lua 就試著調(diào)用 "lt" 或是 "le" 元方法 (參見?§2.8)。

2.5.3 -?邏輯操作符

Lua 中的邏輯操作符有?and,?or, 以及?not。 和控制結(jié)構(gòu)(參見?§2.4.4)一樣, 所有的邏輯操作符把?false?和?nil?都作為假, 而其它的一切都當(dāng)作真。

取反操作?not?總是返回?false?或?true?中的一個。 與操作符?and?在第一個參數(shù)為?false?或?nil?時 返回這第一個參數(shù); 否則,and?返回第二個參數(shù)。 或操作符or?在第一個參數(shù)不為?nil?也不為?false?時, 返回這第一個參數(shù),否則返回第二個參數(shù)。?and?和?or?都遵循短路規(guī)則; 也就是說,第二個操作數(shù)只在需要的時候去求值。 這里有一些例子:

10 or 20 --> 1010 or error() --> 10nil or "a" --> "a"nil and 10 --> nilfalse and error() --> falsefalse and nil --> falsefalse or nil --> nil10 and 20 --> 20

(在這本手冊中, --> 指前面表達式的結(jié)果。)

2.5.4 -?連接符

Lua 中字符串的連接操作符寫作兩個點 ('..')。 如果兩個操作數(shù)都是字符串或都是數(shù)字,連接操作將以?§2.2.1?中提到的規(guī)則把其轉(zhuǎn)換為字符串。 否則,會取調(diào)用元方法 "concat" (參見?§2.8)。

2.5.5 -?取長度操作符

取長度操作符寫作一元操作?#。 字符串的長度是它的字節(jié)數(shù)(就是以一個字符一個字節(jié)計算的字符串長度)。

table?t?的長度被定義成一個整數(shù)下標(biāo)?n?。 它滿足?t[n]?不是?nil?而?t[n+1]?為?nil; 此外,如果?t[1]?為?nil?,n?就可能是零。 對于常規(guī)的數(shù)組,里面從 1 到?n放著一些非空的值的時候, 它的長度就精確的為?n,即最后一個值的下標(biāo)。 如果數(shù)組有一個“空洞” (就是說,nil?值被夾在非空值之間), 那么?#t?可能是指向任何一個是?nil?值的前一個位置的下標(biāo) (就是說,任何一個?nil?值都有可能被當(dāng)成數(shù)組的結(jié)束)。

2.5.6 -?優(yōu)先級

Lua 中操作符的優(yōu)先級寫在下表中,從低到高優(yōu)先級排序:

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

通常,你可以用括號來改變運算次序。 連接操作符 ('..') 和冪操作 ('^') 是從右至左的。 其它所有的操作都是從左至右。

2.5.7 -?Table 構(gòu)造

table 構(gòu)造子是一個構(gòu)造 table 的表達式。 每次構(gòu)造子被執(zhí)行,都會構(gòu)造出一個新的 table 。 構(gòu)造子可以被用來構(gòu)造一個空的 table, 也可以用來構(gòu)造一個 table 并初始化其中的一些域。 一般的構(gòu)造子的語法如下

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

每個形如?[exp1] = exp2?的域向 table 中增加新的一項, 其鍵值為?exp1?而值為?exp2。 形如?name = exp?的域等價于?["name"] = exp。 最后,形如?exp?的域等價于?[i] = exp?, 這里的?i?是一個從 1 開始不斷增長的數(shù)字。 這這個格式中的其它域不會破壞其記數(shù)。 舉個例子:

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

等價于

dolocal t = {}t[f(1)] = gt[1] = "x" -- 1st expt[2] = "y" -- 2nd expt.x = 1 -- t["x"] = 1t[3] = f(x) -- 3rd expt[30] = 23t[4] = 45 -- 4th expa = tend

如果表單中最后一個域的形式是?exp?, 而且其表達式是一個函數(shù)調(diào)用或者是一個可變參數(shù), 那么這個表達式所有的返回值將連續(xù)的進入列表 (參見?§2.5.8)。 為了避免這一點,你可以用括號把函數(shù)調(diào)用(或是可變參數(shù))括起來 (參見?§2.5)。

初始化域表可以在最后多一個分割符, 這樣設(shè)計可以方便由機器生成代碼。

2.5.8 -?函數(shù)調(diào)用

Lua 中的函數(shù)調(diào)用的語法如下:

functioncall ::= prefixexp args

函數(shù)調(diào)用時,第一步,prefixexp 和 args 先被求值。 如果 prefixexp 的值的類型是?function, 那么這個函數(shù)就被用給出的參數(shù)調(diào)用。 否則 prefixexp 的元方法 "call" 就被調(diào)用, 第一個參數(shù)就是 prefixexp 的值,跟下來的是原來的調(diào)用參數(shù) (參見?§2.8)。

這樣的形式

functioncall ::= prefixexp `:′ Name args

可以用來調(diào)用 "方法"。 這是 Lua 支持的一種語法糖。像?v:name(args)?這個樣子,被解釋成?v.name(v,args), 這里?v?只會被求值一次。

參數(shù)的語法如下:

args ::= `(′ [explist1] `)′args ::= tableconstructorargs ::= String

所有參數(shù)的表達式求值都在函數(shù)調(diào)用之前。 這樣的調(diào)用形式?f{fields}?是一種語法糖用于表示?f({fields}); 這里指參數(shù)列表是一個單一的新創(chuàng)建出來的列表。 而這樣的形式?f'string'?(或是?f"string"?亦或是?f[[string]]) 也是一種語法糖,用于表示?f('string'); 這里指參數(shù)列表是一個單獨的字符串。

因為表達式語法在 Lua 中比較自由, 所以你不能在函數(shù)調(diào)用的 '(' 前換行。 這個限制可以避免語言中的一些歧義。 比如你這樣寫

a = f(g).x(a)

Lua 將把它當(dāng)作一個單一語句段,?a = f(g).x(a)?。 因此,如果你真的想作為成兩個語句段,你必須在它們之間寫上一個分號。 如果你真的想調(diào)用?f, 你必須從?(g)前移去換行。

這樣一種調(diào)用形式:return?functioncall?將觸發(fā)一個尾調(diào)用。 Lua 實現(xiàn)了適當(dāng)?shù)奈膊空{(diào)用(或是適當(dāng)?shù)奈策f歸): 在尾調(diào)用中, 被調(diào)用的函數(shù)重用調(diào)用它的函數(shù)的堆棧項。 因此,對于程序執(zhí)行的嵌套尾調(diào)用的層數(shù)是沒有限制的。 然而,尾調(diào)用將刪除調(diào)用它的函數(shù)的任何調(diào)試信息。 注意,尾調(diào)用只發(fā)生在特定的語法下, 這時,?return?只有單一函數(shù)調(diào)用作為參數(shù); 這種語法使得調(diào)用函數(shù)的結(jié)果可以精確返回。 因此,下面這些例子都不是尾調(diào)用:

return (f(x)) -- 返回值被調(diào)整為一個return 2 * f(x)return x, f(x) -- 最加若干返回值f(x); return -- 無返回值return x or f(x) -- 返回值被調(diào)整為一個

2.5.9 -?函數(shù)定義

函數(shù)定義的語法如下:

function ::= function funcbodyfuncbody ::= `(′ [parlist1] `)′ block end

另外定義了一些語法糖簡化函數(shù)定義的寫法:

stat ::= function funcname funcbodystat ::= local function Name funcbodyfuncname ::= Name {`.′ Name} [`:′ Name]

這樣的寫法:

function f () body end

被轉(zhuǎn)換成

f = function () body end

這樣的寫法:

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

被轉(zhuǎn)換成

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

這樣的寫法:

local function f () body end

被轉(zhuǎn)換成

local f; f = function () body end

注意,并不是轉(zhuǎn)換成

local f = function () body end

(這個差別只在函數(shù)體內(nèi)需要引用?f?時才有。)

一個函數(shù)定義是一個可執(zhí)行的表達式, 執(zhí)行結(jié)果是一個類型為?function?的值。 當(dāng) Lua 預(yù)編譯一個 chunk 的時候, chunk 作為一個函數(shù),整個函數(shù)體也就被預(yù)編譯了。 那么,無論何時 Lua 執(zhí)行了函數(shù)定義, 這個函數(shù)本身就被實例化了(或者說是關(guān)閉了)。 這個函數(shù)的實例(或者說是?closure(閉包)) 是表達式的最終值。 相同函數(shù)的不同實例有可能引用不同的外部局部變量, 也可能擁有不同的環(huán)境表。

形參(函數(shù)定義需要的參數(shù))是一些由實參(實際傳入?yún)?shù))的值初始化的局部變量:

parlist1 ::= namelist [`,′ `...′] | `...

當(dāng)一個函數(shù)被調(diào)用, 如果函數(shù)沒有被定義為接收不定長參數(shù),即在形參列表的末尾注明三個點 ('...'), 那么實參列表就會被調(diào)整到形參列表的長度, 變長參數(shù)函數(shù)不會調(diào)整實參列表; 取而代之的是,它將把所有額外的參數(shù)放在一起通過變長參數(shù)表達式傳遞給函數(shù), 其寫法依舊是三個點。 這個表達式的值是一串實參值的列表,看起來就跟一個可以返回多個結(jié)果的函數(shù)一樣。 如果一個變長參數(shù)表達式放在另一個表達式中使用,或是放在另一串表達式的中間, 那么它的返回值就會被調(diào)整為單個值。 若這個表達式放在了一系列表達式的最后一個,就不會做調(diào)整了(除非用括號給括了起來)。

我們先做如下定義,然后再來看一個例子:

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

下面看看實參到形參數(shù)以及可變長參數(shù)的映射關(guān)系:

CALL PARAMETERSf(3) a=3, b=nilf(3, 4) a=3, b=4f(3, 4, 5) a=3, b=4f(r(), 10) a=1, b=10f(r()) a=1, b=2g(3) a=3, b=nil, ... --> (nothing)g(3, 4) a=3, b=4, ... --> (nothing)g(3, 4, 5, 8) a=3, b=4, ... --> 5 8g(5, r()) a=5, b=1, ... --> 2 3

結(jié)果由?return?來返回(參見?§2.4.4)。 如果執(zhí)行到函數(shù)末尾依舊沒有遇到任何?return?語句, 函數(shù)就不會返回任何結(jié)果。

冒號語法可以用來定義方法, 就是說,函數(shù)可以有一個隱式的形參?self。 因此,如下寫法:

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

是這樣一種寫法的語法糖:

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

2.6 -?可視規(guī)則

Lua 是一個有詞法作用范圍的語言。 變量的作用范圍開始于聲明它們之后的第一個語句段, 結(jié)束于包含這個聲明的最內(nèi)層語句塊的結(jié)束點。 看下面這些例子:

x = 10 -- 全局變量do -- 新的語句塊local x = x -- 新的一個 'x', 它的值現(xiàn)在是 10print(x) --> 10x = x+1do -- 另一個語句塊local x = x+1 -- 又一個 'x'print(x) --> 12endprint(x) --> 11endprint(x) --> 10 (取到的是全局的那一個)

注意這里,類似?local x = x?這樣的聲明, 新的?x?正在被聲明,但是還沒有進入它的作用范圍, 所以第二個?x?指向的是外面一層的變量。

因為有這樣一個詞法作用范圍的規(guī)則, 所以可以在函數(shù)內(nèi)部自由的定義局部變量并使用它們。 當(dāng)一個局部變量被更內(nèi)層的函數(shù)中使用的時候, 它被內(nèi)層函數(shù)稱作upvalue(上值),或是?外部局部變量。

注意,每次執(zhí)行到一個 local 語句都會定義出一個新的局部變量。 看看這樣一個例子:

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

這個循環(huán)創(chuàng)建了十個 closure(這指十個匿名函數(shù)的實例)。 這些 closure 中的每一個都使用了不同的?y?變量, 而它們又共享了同一份?x。

2.7 -?錯誤處理

因為 Lua 是一個嵌入式的擴展語言, 所有的 Lua 動作都是從宿主程序的 C 代碼調(diào)用 Lua 庫 (參見?lua_pcall)中的一個函數(shù)開始的。 在 Lua 編譯或運行的任何時候發(fā)生了錯誤,控制權(quán)都會交還給 C , 而 C 可以來做一些恰當(dāng)?shù)拇胧?#xff08;比如打印出一條錯誤信息)。

Lua 代碼可以顯式的調(diào)用?error?函數(shù)來產(chǎn)生一條錯誤。 如果你需要在 Lua 中捕獲發(fā)生的錯誤, 你可以使用?pcall?函數(shù)。

2.8 -?Metatable(元表)

Lua 中的每個值都可以用一個?metatable。 這個?metatable?就是一個原始的 Lua table , 它用來定義原始值在特定操作下的行為。 你可以通過在 metatable 中的特定域設(shè)一些值來改變擁有這個 metatable 的值 的指定操作之行為。 舉例來說,當(dāng)一個非數(shù)字的值作加法操作的時候, Lua 會檢查它的 metatable 中?"__add"?域中的是否有一個函數(shù)。 如果有這么一個函數(shù)的話,Lua 調(diào)用這個函數(shù)來執(zhí)行一次加法。

我們叫 metatable 中的鍵名為?事件 (event)?,把其中的值叫作?元方法 (metamethod)。 在上個例子中,事件是?"add"?而元方法就是那個執(zhí)行加法操作的函數(shù)。

你可以通過?getmetatable?函數(shù)來查詢到任何一個值的 metatable。

你可以通過?setmetatable?函數(shù)來替換掉 table 的 metatable 。 你不能從 Lua 中改變其它任何類型的值的 metatable (使用 debug 庫例外); 要這樣做的話必須使用 C API 。

每個 table 和 userdata 擁有獨立的 metatable (當(dāng)然多個 table 和 userdata 可以共享一個相同的表作它們的 metatable); 其它所有類型的值,每種類型都分別共享唯一的一個 metatable。 因此,所有的數(shù)字一起只有一個 metatable ,所有的字符串也是,等等。

一個 metatable 可以控制一個對象做數(shù)學(xué)運算操作、比較操作、連接操作、取長度操作、取下標(biāo)操作時的行為, metatable 中還可以定義一個函數(shù),讓 userdata 作垃圾收集時調(diào)用它。 對于這些操作,Lua 都將其關(guān)聯(lián)上一個被稱作事件的指定健。 當(dāng) Lua 需要對一個值發(fā)起這些操作中的一個時, 它會去檢查值中 metatable 中是否有對應(yīng)事件。 如果有的話,鍵名對應(yīng)的值(元方法)將控制 Lua 怎樣做這個操作。

metatable 可以控制的操作已在下面列出來。 每個操作都用相應(yīng)的名字區(qū)分。 每個操作的鍵名都是用操作名字加上兩個下劃線 '__' 前綴的字符串; 舉例來說,"add" 操作的鍵名就是字符串?"__add"。 這些操作的語義用一個 Lua 函數(shù)來描述解釋器如何執(zhí)行更為恰當(dāng)。

這里展示的用 Lua 寫的代碼僅作解說用; 實際的行為已經(jīng)硬編碼在解釋器中,其執(zhí)行效率要遠高于這些模擬代碼。 這些用于描述的的代碼中用到的函數(shù) (?rawget,?tonumber?,等等。) 都可以在?§5.1?中找到。 特別注意,我們使用這樣一個表達式來從給定對象中提取元方法

metatable(obj)[event]

這個應(yīng)該被解讀作

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

這就是說,訪問一個元方法不再會觸發(fā)任何的元方法, 而且訪問一個沒有 metatable 的對象也不會失敗(而只是簡單返回?nil)。

  • "add":?+?操作。

    下面這個?getbinhandler?函數(shù)定義了 Lua 怎樣選擇一個處理器來作二元操作。 首先,Lua 嘗試第一個操作數(shù)。 如果這個東西的類型沒有定義這個操作的處理器,然后 Lua 會嘗試第二個操作數(shù)。

    function getbinhandler (op1, op2, event)return metatable(op1)[event] or metatable(op2)[event]end

    通過這個函數(shù),?op1 + op2?的行為就是

    function add_event (op1, op2)local o1, o2 = tonumber(op1), tonumber(op2)if o1 and o2 then -- 兩個操作數(shù)都是數(shù)字?return o1 + o2 -- 這里的 '+' 是原生的 'add'else -- 至少一個操作數(shù)不是數(shù)字時local h = getbinhandler(op1, op2, "__add")if h then-- 以兩個操作數(shù)來調(diào)用處理器return h(op1, op2)else -- 沒有處理器:缺省行為error(···)endendend

  • "sub":?-?操作。 其行為類似于 "add" 操作。
  • "mul":?*?操作。 其行為類似于 "add" 操作。
  • "div":?/?操作。 其行為類似于 "add" 操作。
  • "mod":?%?操作。 其行為類似于 "add" 操作, 它的原生操作是這樣的?o1 - floor(o1/o2)*o2
  • "pow":?^?(冪)操作。 其行為類似于 "add" 操作, 它的原生操作是調(diào)用?pow?函數(shù)(通過 C math 庫)。
  • "unm":?一元?-?操作。 function unm_event (op)local o = tonumber(op)if o then -- 操作數(shù)是數(shù)字?return -o -- 這里的 '-' 是一個原生的 'unm'else -- 操作數(shù)不是數(shù)字。-- 嘗試從操作數(shù)中得到處理器local h = metatable(op).__unmif h then-- 以操作數(shù)為參數(shù)調(diào)用處理器return h(op)else -- 沒有處理器:缺省行為error(···)endendend

  • "concat":?..?(連接)操作, function concat_event (op1, op2)if (type(op1) == "string" or type(op1) == "number") and(type(op2) == "string" or type(op2) == "number") thenreturn op1 .. op2 -- 原生字符串連接elselocal h = getbinhandler(op1, op2, "__concat")if h thenreturn h(op1, op2)elseerror(···)endendend

  • "len":?#?操作。 function len_event (op)if type(op) == "string" thenreturn strlen(op) -- 原生的取字符串長度elseif type(op) == "table" thenreturn #op -- 原生的取 table 長度elselocal h = metatable(op).__lenif h then-- 調(diào)用操作數(shù)的處理器return h(op)else -- 沒有處理器:缺省行為error(···)endendend

    關(guān)于 table 的長度參見?§2.5.5?。

  • "eq":?==?操作。 函數(shù)?getcomphandler?定義了 Lua 怎樣選擇一個處理器來作比較操作。 元方法僅僅在參于比較的兩個對象類型相同且有對應(yīng)操作相同的元方法時才起效。 function getcomphandler (op1, op2, event)if type(op1) ~= type(op2) then return nil endlocal mm1 = metatable(op1)[event]local mm2 = metatable(op2)[event]if mm1 == mm2 then return mm1 else return nil endend

    "eq" 事件按如下方式定義:

    function eq_event (op1, op2)if type(op1) ~= type(op2) then -- 不同的類型?return false -- 不同的對象endif op1 == op2 then -- 原生的相等比較結(jié)果?return true -- 對象相等end-- 嘗試使用元方法local h = getcomphandler(op1, op2, "__eq")if h thenreturn h(op1, op2)elsereturn falseendend

    a ~= b?等價于?not (a == b)?。

  • "lt":?<?操作。 function lt_event (op1, op2)if type(op1) == "number" and type(op2) == "number" thenreturn op1 < op2 -- 數(shù)字比較elseif type(op1) == "string" and type(op2) == "string" thenreturn op1 < op2 -- 字符串按逐字符比較elselocal h = getcomphandler(op1, op2, "__lt")if h thenreturn h(op1, op2)elseerror(···);endendend

    a > b?等價于?b < a.

  • "le":?<=?操作。 function le_event (op1, op2)if type(op1) == "number" and type(op2) == "number" thenreturn op1 <= op2 -- 數(shù)字比較elseif type(op1) == "string" and type(op2) == "string" thenreturn op1 <= op2 -- 字符串按逐字符比較elselocal h = getcomphandler(op1, op2, "__le")if h thenreturn h(op1, op2)elseh = getcomphandler(op1, op2, "__lt")if h thenreturn not h(op2, op1)elseerror(···);endendendend

    a >= b?等價于?b <= a?。 注意,如果元方法 "le" 沒有提供,Lua 就嘗試 "lt" , 它假定?a <= b?等價于?not (b < a)?。

  • "index":?取下標(biāo)操作用于訪問?table[key]?。 function gettable_event (table, key)local hif type(table) == "table" thenlocal v = rawget(table, key)if v ~= nil then return v endh = metatable(table).__indexif h == nil then return nil endelseh = metatable(table).__indexif h == nil thenerror(···);endendif type(h) == "function" thenreturn h(table, key) -- 調(diào)用處理器else return h[key] -- 或是重復(fù)上述操作endend

  • "newindex":?賦值給指定下標(biāo)?table[key] = value?。 function settable_event (table, key, value)local hif type(table) == "table" thenlocal v = rawget(table, key)if v ~= nil then rawset(table, key, value); return endh = metatable(table).__newindexif h == nil then rawset(table, key, value); return endelseh = metatable(table).__newindexif h == nil thenerror(···);endendif type(h) == "function" thenreturn h(table, key,value) -- 調(diào)用處理器else h[key] = value -- 或是重復(fù)上述操作endend

  • "call":?當(dāng) Lua 調(diào)用一個值時調(diào)用。 function function_event (func, ...)if type(func) == "function" thenreturn func(...) -- 原生的調(diào)用elselocal h = metatable(func).__callif h thenreturn h(func, ...)elseerror(···)endendend

2.9 -?環(huán)境

類型為 thread ,function ,以及 userdata 的對象,除了 metatable 外還可以用另外一個與之關(guān)聯(lián)的被稱作 它們的環(huán)境的一個表, 像 metatable 一樣,環(huán)境也是一個常規(guī)的 table ,多個對象可以共享 同一個環(huán)境。

userdata 的環(huán)境在 Lua 中沒有意義。 這個東西只是為了在程序員想把一個表關(guān)聯(lián)到一個 userdata 上時提供便利。

關(guān)聯(lián)在線程上的環(huán)境被稱作全局環(huán)境。 全局環(huán)境被用作它其中的線程以及線程創(chuàng)建的非嵌套函數(shù) (通過?loadfile?,?loadstring?或是?load?)的缺省環(huán)境。 而且它可以被 C 代碼直接訪問(參見?§3.3)。

關(guān)聯(lián)在 C 函數(shù)上的環(huán)境可以直接被 C 代碼訪問(參見?§3.3)。 它們會作為這個 C 函數(shù)中創(chuàng)建的其它函數(shù)的缺省環(huán)境。

關(guān)聯(lián)在 Lua 函數(shù)上的環(huán)境用來接管在函數(shù)內(nèi)對全局變量(參見?§2.3)的所有訪問。 它們也會作為這個函數(shù)內(nèi)創(chuàng)建的其它函數(shù)的缺省環(huán)境。

你可以通過調(diào)用?setfenv?來改變一個 Lua 函數(shù) 或是正在運行中的線程的環(huán)境。 而想操控其它對象(userdata、C 函數(shù)、其它線程)的環(huán)境的話,就必須使用 C API 。

2.10 -?垃圾收集

Lua 提供了一個自動的內(nèi)存管理。 這就是說你不需要關(guān)心創(chuàng)建新對象的分配內(nèi)存操作,也不需要在這些對象不再需要時的主動釋放內(nèi)存。 Lua 通過運行一個垃圾收集器來自動管理內(nèi)存,以此一遍又一遍的回收死掉的對象 (這是指 Lua 中不再訪問的到的對象)占用的內(nèi)存。 Lua 中所有對象都被自動管理,包括: table, userdata、 函數(shù)、線程、和字符串。

Lua 實現(xiàn)了一個增量標(biāo)記清除的收集器。 它用兩個數(shù)字來控制垃圾收集周期:?garbage-collector pause?和?garbage-collector step multiplier?。

garbage-collector pause 控制了收集器在開始一個新的收集周期之前要等待多久。 隨著數(shù)字的增大就導(dǎo)致收集器工作工作的不那么主動。 小于 1 的值意味著收集器在新的周期開始時不再等待。 當(dāng)值為 2 的時候意味著在總使用內(nèi)存數(shù)量達到原來的兩倍時再開啟新的周期。

step multiplier 控制了收集器相對內(nèi)存分配的速度。 更大的數(shù)字將導(dǎo)致收集器工作的更主動的同時,也使每步收集的尺寸增加。 小于 1 的值會使收集器工作的非常慢,可能導(dǎo)致收集器永遠都結(jié)束不了當(dāng)前周期。 缺省值為 2 ,這意味著收集器將以內(nèi)存分配器的兩倍速運行。

你可以通過在 C 中調(diào)用?lua_gc?或是在 Lua 中調(diào)用?collectgarbage?來改變這些數(shù)字。 兩者都接受百分比數(shù)值(因此傳入?yún)?shù) 100 意味著實際值 1 )。 通過這些函數(shù),你也可以直接控制收集器(例如,停止或是重啟)。

2.10.1 -?垃圾收集的元方法

使用 C API , 你可以給 userdata (參見?§2.8)設(shè)置一個垃圾收集的元方法。 這個元方法也被稱為結(jié)束子。 結(jié)束子允許你用額外的資源管理器和 Lua 的內(nèi)存管理器協(xié)同工作 (比如關(guān)閉文件、網(wǎng)絡(luò)連接、或是數(shù)據(jù)庫連接,也可以說釋放你自己的內(nèi)存)。

一個 userdata 可被回收,若它的 metatable 中有?__gc?這個域 , 垃圾收集器就不立即收回它。 取而代之的是,Lua 把它們放到一個列表中。 最收集結(jié)束后,Lua 針對列表中的每個 userdata 執(zhí)行了下面這個函數(shù)的等價操作:

function gc_event (udata)local h = metatable(udata).__gcif h thenh(udata)endend

在每個垃圾收集周期的結(jié)尾,每個在當(dāng)前周期被收集起來的 userdata 的結(jié)束子會以 它們構(gòu)造時的逆序依次調(diào)用。 也就是說,收集列表中,最后一個在程序中被創(chuàng)建的 userdata 的 結(jié)束子會被第一個調(diào)用。

2.10.2 -?Weak Table(弱表)

weak table?是一個這樣的 table,它其中的元素都被弱引用。 弱引用將被垃圾收集器忽略掉, 換句話說, 如果對一個對象的引用只有弱引用, 垃圾收集器將回收這個對象。

weak table 的鍵和值都可以是 weak 的。 如果一個 table 只有鍵是 weak 的,那么將運行收集器回收它們的鍵, 但是會阻止回收器回收對應(yīng)的值。 而一個 table 的鍵和值都是 weak 時,就即允許收集器回收鍵又允許收回值。 任何情況下,如果鍵和值中任一個被回收了,整個鍵值對就會從 table 中拿掉。 table 的 weak 特性可以通過在它的 metatable 中設(shè)置?__mode?域來改變。 如果?__mode?域中是一個包含有字符 'k' 的字符串時, table 的鍵就是 weak 的。 如果?__mode?域中是一個包含有字符 'v' 的字符串時, table 的值就是 weak 的。

在你把一個 table 當(dāng)作一個 metatable 使用之后, 就不能再修改?__mode?域的值。 否則,受這個 metatable 控制的 table 的 weak 行為就成了未定義的。

2.11 -?Coroutine (協(xié)同例程)

Lua 支持 coroutine ,這個東西也被稱為協(xié)同式多線程 (collaborative multithreading) 。 Lua 為每個 coroutine 提供一個獨立的運行線路。 然而和多線程系統(tǒng)中的線程不同,coroutine 只在顯式的調(diào)用了 yield 函數(shù)時才會掛起。

創(chuàng)建一個 coroutine 需要調(diào)用一次?coroutine.create?。 它只接收單個參數(shù),這個參數(shù)是 coroutine 的主函數(shù)。?create?函數(shù)僅僅創(chuàng)建一個新的 coroutine 然后返回它的控制器 (一個類型為?thread?的對象); 它并不會啟動 coroutine 的運行。

當(dāng)你第一次調(diào)用?coroutine.resume?時, 所需傳入的第一個參數(shù)就是?coroutine.create?的返回值。 這時,coroutine 從主函數(shù)的第一行開始運行。 接下來傳入coroutine.resume?的參數(shù)將被傳進 coroutine 的主函數(shù)。 在 coroutine 開始運行后,它講運行到自身終止或是遇到一個?yields?。

coroutine 可以通過兩種方式來終止運行: 一種是正常退出,指它的主函數(shù)返回(最后一條指令被運行后,無論有沒有顯式的返回指令); 另一種是非正常退出,它發(fā)生在未保護的錯誤發(fā)生的時候。 第一種情況中,?coroutine.resume?返回?true?, 接下來會跟著 coroutine 主函數(shù)的一系列返回值。 第二種發(fā)生錯誤的情況下,coroutine.resume?返回?false?, 緊接著是一條錯誤信息。

coroutine 中切換出去,可以調(diào)用?coroutine.yield。 當(dāng) coroutine 切出,與之配合的?coroutine.resume?就立即返回, 甚至在 yield 發(fā)生在內(nèi)層的函數(shù)調(diào)用中也可以(就是說, 這不限于發(fā)生在主函數(shù)中,也可以是主函數(shù)直接或間接調(diào)用的某個函數(shù)里)。 在 yield 的情況下,coroutine.resume?也是返回?true, 緊跟著那些被傳入coroutine.yield?的參數(shù)。 等到下次你在繼續(xù)同樣的 coroutine ,將從調(diào)用 yield 的斷點處運行下去。 斷點處 yield 的返回值將是?coroutine.resume?傳入的參數(shù)。

類似?coroutine.create?,?coroutine.wrap?這個函數(shù)也將創(chuàng)建一個 coroutine , 但是它并不返回 coroutine 本身,而是返回一個函數(shù)取而代之。一旦你調(diào)用這個返回函數(shù),就會切入 coroutine 運行。 所有傳入這個函數(shù)的參數(shù)等同于傳入?coroutine.resume?的參數(shù)。?coroutine.wrap?會返回所有應(yīng)該由除第一個(錯誤代碼的那個布爾量) 之外的由?coroutine.resume?返回的值。 和?coroutine.resume?不同,?coroutine.wrap?不捕獲任何錯誤; 所有的錯誤都應(yīng)該由調(diào)用者自己傳遞。

看下面這段代碼展示的一個例子:

function foo (a)print("foo", a)return coroutine.yield(2*a)endco = 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"))

當(dāng)你運行它,將得到如下輸出結(jié)果:

co-body 1 10foo 2main true 4co-body rmain true 11 -9co-body x ymain true 10 endmain false cannot resume dead coroutine

3 -?程序接口(API)

這個部分描述了 Lua 的 C API , 也就是宿主程序跟 Lua 通訊用的一組 C 函數(shù)。 所有的 API 函數(shù)按相關(guān)的類型以及常量都聲明在頭文件?lua.h?中。

雖然我們說的是“函數(shù)”,但一部分簡單的 API 是以宏的形式提供的。 所有的這些宏都只使用它們的參數(shù)一次 (除了第一個參數(shù),也就是 lua 狀態(tài)機), 因此你不需擔(dān)心這些宏的展開會引起一些副作用。

在所有的 C 庫中,Lua API 函數(shù)都不去檢查參數(shù)的有效性和堅固性。 然而,你可以在編譯 Lua 時加上打開一個宏開關(guān)來 開啟?luaconf.h?文件中的宏?luai_apicheck?以改變這個行為。

3.1 -?堆棧

Lua 使用一個虛擬棧來和 C 傳遞值。 棧上的的每個元素都是一個 Lua 值 (nil,數(shù)字,字符串,等等)。

無論何時 Lua 調(diào)用 C,被調(diào)用的函數(shù)都得到一個新的棧, 這個棧獨立于 C 函數(shù)本身的堆棧,也獨立于以前的棧。 (譯注:在 C 函數(shù)里,用 Lua API 不能訪問到 Lua 狀態(tài)機中本次調(diào)用之外的堆棧中的數(shù)據(jù)) 它里面包含了 Lua 傳遞給 C 函數(shù)的所有參數(shù), 而 C 函數(shù)則把要返回的結(jié)果也放入堆棧以返回給調(diào)用者 (參見lua_CFunction)。

方便起見,所有針對棧的 API 查詢操作都不嚴格遵循棧的操作規(guī)則。 而是可以用一個索引來指向棧上的任何元素: 正的索引指的是棧上的絕對位置(從一開始); 負的索引則指從棧頂開始的偏移量。 更詳細的說明一下,如果堆棧有 n 個元素, 那么索引 1 表示第一個元素(也就是最先被壓入堆棧的元素) 而索引 n 則指最后一個元素; 索引 -1 也是指最后一個元素(即棧頂?shù)脑?#xff09;, 索引 -n 是指第一個元素。 如果索引在 1 到棧頂之間(也就是,1 ≤ abs(index) ≤ top) 我們就說這是個有效的索引。

3.2 -?堆棧尺寸

當(dāng)你使用 Lua API 時,就有責(zé)任保證其堅固性。 特別需要注意的是,你有責(zé)任控制不要堆棧溢出。 你可以使用?lua_checkstack?這個函數(shù)來擴大可用堆棧的尺寸。

無論何時 Lua 調(diào)用 C , 它都只保證?LUA_MINSTACK?這么多的堆棧空間可以使用。?LUA_MINSTACK?一般被定義為 20 , 因此,只要你不是不斷的把數(shù)據(jù)壓棧,通常你不用關(guān)心堆棧大小。

所有的查詢函數(shù)都可以接收一個索引,只要這個索引是任何棧提供的空間中的值。 棧能提供的最大空間是通過?lua_checkstack?來設(shè)置的。 這些索引被稱作可接受的索引,通常我們把它定義為:

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

注意,0 永遠都不是一個可接受的索引。(譯注:下文中凡提到的索引,沒有特別注明的話,都指可接受的索引。)

3.3 -?偽索引

除了特別聲明外,任何一個函數(shù)都可以接受另一種有效的索引,它們被稱作“偽索引”。 這個可以幫助 C 代碼訪問一些并不在棧上的 Lua 值。 偽索引被用來訪問線程的環(huán)境,函數(shù)的環(huán)境,注冊表,還有 C 函數(shù)的 upvalue (參見?§3.4)。

線程的環(huán)境(也就是全局變量放的地方)通常在偽索引?LUA_GLOBALSINDEX?處。 正在運行的 C 函數(shù)的環(huán)境則放在偽索引?LUA_ENVIRONINDEX?之處。

你可以用常規(guī)的 table 操作來訪問和改變?nèi)肿兞康闹?#xff0c;只需要指定環(huán)境表的位置。 舉例而言,要訪問全局變量的值,這樣做:

lua_getfield(L, LUA_GLOBALSINDEX, varname);

3.4 -?C Closure

當(dāng) C 函數(shù)被創(chuàng)建出來,我們有可能會把一些值關(guān)聯(lián)在一起, 也就是創(chuàng)建一個 C closure ; 這些被關(guān)聯(lián)起來的值被叫做 upvalue , 它們可以在函數(shù)被調(diào)用的時候訪問的到。 (參見?lua_pushcclosure)。

無論何時去調(diào)用 C 函數(shù),函數(shù)的 upvalue 都被放在指定的偽索引處。 我們可以用?lua_upvalueindex?這個宏來生成這些偽索引。 第一個關(guān)聯(lián)到函數(shù)的值放在lua_upvalueindex(1)?位置處,依次類推。 任何情況下都可以用?lua_upvalueindex(n)?產(chǎn)生一個 upvalue 的索引, 即使 n 大于實際的 upvalue 數(shù)量也可以。它都可以產(chǎn)生一個可接受但不一定有效的索引。

3.5 -?注冊表

Lua 提供了一個注冊表,這是一個預(yù)定義出來的表,可以用來保存任何 C 代碼想保存的 Lua 值。 這個表可以用偽索引?LUA_REGISTRYINDEX?來定位。 任何 C 庫都可以在這張表里保存數(shù)據(jù),為了防止沖突,你需要特別小心的選擇鍵名。 一般的用法是,你可以用一個包含你的庫名的字符串做為鍵名,或者可以取你自己 C 代碼 中的一個地址,以 light userdata 的形式做鍵。

注冊表里的整數(shù)健被用于補充庫中實現(xiàn)的引用系統(tǒng)的工作,一般說來不要把它們用于別的用途。

3.6 -?C 中的錯誤處理

在內(nèi)部實現(xiàn)中,Lua 使用了 C 的?longjmp?機制來處理錯誤。 (如果你使用 C++ 的話,也可以選擇換用異常;參見?luaconf.h?文件。) 當(dāng) Lua 碰到任何錯誤(比如內(nèi)存分配錯誤、類型錯誤、語法錯誤、還有一些運行時錯誤) 它都會產(chǎn)生一個錯誤出去; 也就是調(diào)用一個 long jump 。 在保護環(huán)境下,Lua 使用?setjmp?來設(shè)置一個恢復(fù)點; 任何發(fā)生的錯誤都會激活最近的一個恢復(fù)點。

幾乎所有的 API 函數(shù)都可能產(chǎn)生錯誤,例如內(nèi)存分配錯誤。 但下面的一些函數(shù)運行在保護環(huán)境中(也就是說它們創(chuàng)建了一個保護環(huán)境再在其中運行), 因此它們不會產(chǎn)生錯誤出來:?lua_newstate,?lua_close,?lua_load,?lua_pcall, and?lua_cpcall。

在 C 函數(shù)里,你也可以通過調(diào)用?lua_error?產(chǎn)生一個錯誤。

3.7 -?函數(shù)和類型

在這里我們按字母次序列出了所有 C API 中的函數(shù)和類型。


lua_Alloc

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

Lua 狀態(tài)機中使用的內(nèi)存分配器函數(shù)的類型。 內(nèi)存分配函數(shù)必須提供一個功能類似于?realloc?但又不完全相同的函數(shù)。 它的參數(shù)有?ud?,一個由?lua_newstate?傳給它的指針;?ptr?,一個指向已分配出來或是將被重新分配或是要釋放的內(nèi)存塊指針;?osize?,內(nèi)存塊原來的尺寸;?nsize?,新內(nèi)存塊的尺寸。 如果且只有?osize?是零時,ptr?為?NULL?。 當(dāng)?nsize?是零,分配器必須返回?NULL; 如果?osize?不是零,分配器應(yīng)當(dāng)釋放掉?ptr?指向的內(nèi)存塊。 當(dāng)?nsize?不是零,若分配器不能滿足請求時,分配器返回?NULL?。 當(dāng)?nsize?不是零而?osize?是零時,分配器應(yīng)該和?malloc?有相同的行為。 當(dāng)?nsize?和?osize?都不是零時,分配器則應(yīng)和?realloc?保持一樣的行為。 Lua 假設(shè)分配器在?osize >= nsize?時永遠不會失敗。

這里有一個簡單的分配器函數(shù)的實現(xiàn)。 這個實現(xiàn)被放在補充庫中,由?luaL_newstate?提供。

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

這段代碼假設(shè)?free(NULL)?啥也不影響,而且?realloc(NULL, size)?等價于?malloc(size)。 這兩點是 ANSI C 保證的行為。


lua_atpanic

lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf);

設(shè)置一個新的 panic (恐慌) 函數(shù),并返回前一個。

如果在保護環(huán)境之外發(fā)生了任何錯誤, Lua 就會調(diào)用一個 panic 函數(shù),接著調(diào)用?exit(EXIT_FAILURE), 這樣就開始退出宿主程序。 你的 panic 函數(shù)可以永遠不返回(例如作一次長跳轉(zhuǎn))來避免程序退出。

panic 函數(shù)可以從棧頂取到出錯信息。


lua_call

void lua_call (lua_State *L, int nargs, int nresults);

調(diào)用一個函數(shù)。

要調(diào)用一個函數(shù)請遵循以下協(xié)議: 首先,要調(diào)用的函數(shù)應(yīng)該被壓入堆棧; 接著,把需要傳遞給這個函數(shù)的參數(shù)按正序壓棧; 這是指第一個參數(shù)首先壓棧。 最后調(diào)用一下?lua_call;?nargs?是你壓入堆棧的參數(shù)個數(shù)。 當(dāng)函數(shù)調(diào)用完畢后,所有的參數(shù)以及函數(shù)本身都會出棧。 而函數(shù)的返回值這時則被壓入堆棧。 返回值的個數(shù)將被調(diào)整為?nresults?個, 除非?nresults?被設(shè)置成?LUA_MULTRET。 在這種情況下,所有的返回值都被壓入堆棧中。 Lua 會保證返回值都放入棧空間中。 函數(shù)返回值將按正序壓棧(第一個返回值首先壓棧), 因此在調(diào)用結(jié)束后,最后一個返回值將被放在棧頂。

被調(diào)用函數(shù)內(nèi)發(fā)生的錯誤將(通過?longjmp)一直上拋。

下面的例子中,這行 Lua 代碼等價于在宿主程序用 C 代碼做一些工作:

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

這里是 C 里的代碼:

lua_getfield(L, LUA_GLOBALSINDEX, "f"); /* 將調(diào)用的函數(shù) */lua_pushstring(L, "how"); /* 第一個參數(shù) */lua_getfield(L, LUA_GLOBALSINDEX, "t"); /* table 的索引 */lua_getfield(L, -1, "x"); /* 壓入 t.x 的值(第 2 個參數(shù))*/lua_remove(L, -2); /* 從堆棧中移去 't' */lua_pushinteger(L, 14); /* 第 3 個參數(shù) */lua_call(L, 3, 1); /* 調(diào)用 'f',傳入 3 個參數(shù),并索取 1 個返回值 */lua_setfield(L, LUA_GLOBALSINDEX, "a"); /* 設(shè)置全局變量 'a' */

注意上面這段代碼是“平衡”的: 到了最后,堆棧恢復(fù)成原由的配置。 這是一種良好的編程習(xí)慣。


lua_CFunction

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

C 函數(shù)的類型。

為了正確的和 Lua 通訊,C 函數(shù)必須使用下列 定義了參數(shù)以及返回值傳遞方法的協(xié)議: C 函數(shù)通過 Lua 中的堆棧來接受參數(shù),參數(shù)以正序入棧(第一個參數(shù)首先入棧)。 因此,當(dāng)函數(shù)開始的時候,?lua_gettop(L)?可以返回函數(shù)收到的參數(shù)個數(shù)。 第一個參數(shù)(如果有的話)在索引 1 的地方,而最后一個參數(shù)在索引?lua_gettop(L)處。 當(dāng)需要向 Lua 返回值的時候,C 函數(shù)只需要把它們以正序壓到堆棧上(第一個返回值最先壓入), 然后返回這些返回值的個數(shù)。 在這些返回值之下的,堆棧上的東西都會被 Lua 丟掉。 和 Lua 函數(shù)一樣,從 Lua 中調(diào)用 C 函數(shù)也可以有很多返回值。

下面這個例子中的函數(shù)將接收若干數(shù)字參數(shù),并返回它們的平均數(shù)與和:

static int foo (lua_State *L) {int n = lua_gettop(L); /* 參數(shù)的個數(shù) */lua_Number sum = 0;int i;for (i = 1; i <= n; i++) {if (!lua_isnumber(L, i)) {lua_pushstring(L, "incorrect argument");lua_error(L);}sum += lua_tonumber(L, i);}lua_pushnumber(L, sum/n); /* 第一個返回值 */lua_pushnumber(L, sum); /* 第二個返回值 */return 2; /* 返回值的個數(shù) */}

lua_checkstack

int lua_checkstack (lua_State *L, int extra);

確保堆棧上至少有?extra?個空位。 如果不能把堆棧擴展到相應(yīng)的尺寸,函數(shù)返回 false 。 這個函數(shù)永遠不會縮小堆棧; 如果堆棧已經(jīng)比需要的大了,那么就放在那里不會產(chǎn)生變化。


lua_close

void lua_close (lua_State *L);

銷毀指定 Lua 狀態(tài)機中的所有對象(如果有垃圾收集相關(guān)的元方法的話,會調(diào)用它們), 并且釋放狀態(tài)機中使用的所有動態(tài)內(nèi)存。 在一些平臺上,你可以不必調(diào)用這個函數(shù), 因為當(dāng)宿主程序結(jié)束的時候,所有的資源就自然被釋放掉了。 另一方面,長期運行的程序,比如一個后臺程序或是一個 web 服務(wù)器, 當(dāng)不再需要它們的時候就應(yīng)該釋放掉相關(guān)狀態(tài)機。這樣可以避免狀態(tài)機擴張的過大。


lua_concat

void lua_concat (lua_State *L, int n);

連接棧頂?shù)?n?個值, 然后將這些值出棧,并把結(jié)果放在棧頂。 如果?n?為 1 ,結(jié)果就是一個字符串放在棧上(即,函數(shù)什么都不做); 如果?n?為 0 ,結(jié)果是一個空串。 連接依照 Lua 中創(chuàng)建語義完成(參見?§2.5.4?)。


lua_cpcall

int lua_cpcall (lua_State *L, lua_CFunction func, void *ud);

以保護模式調(diào)用 C 函數(shù)?func?。?func?只有能從堆棧上拿到一個參數(shù),就是包含有?ud?的 light userdata。 當(dāng)有錯誤時,?lua_cpcall?返回和?lua_pcall?相同的錯誤代碼, 并在棧頂留下錯誤對象; 否則它返回零,并不會修改堆棧。 所有從?func?內(nèi)返回的值都會被扔掉。


lua_createtable

void lua_createtable (lua_State *L, int narr, int nrec);

創(chuàng)建一個新的空 table 壓入堆棧。 這個新 table 將被預(yù)分配?narr?個元素的數(shù)組空間 以及?nrec?個元素的非數(shù)組空間。 當(dāng)你明確知道表中需要多少個元素時,預(yù)分配就非常有用。 如果你不知道,可以使用函數(shù)?lua_newtable。


lua_dump

int lua_dump (lua_State *L, lua_Writer writer, void *data);

把函數(shù) dump 成二進制 chunk 。 函數(shù)接收棧頂?shù)?Lua 函數(shù)做參數(shù),然后生成它的二進制 chunk 。 若被 dump 出來的東西被再次加載,加載的結(jié)果就相當(dāng)于原來的函數(shù)。 當(dāng)它在產(chǎn)生 chunk 的時候,lua_dump?通過調(diào)用函數(shù)?writer?(參見?lua_Writer) 來寫入數(shù)據(jù),后面的?data?參數(shù)會被傳入?writer?。

最后一次由寫入器 (writer) 返回值將作為這個函數(shù)的返回值返回; 0 表示沒有錯誤。

這個函數(shù)不會把 Lua 返回彈出堆棧。


lua_equal

int lua_equal (lua_State *L, int index1, int index2);

如果依照 Lua 中?==?操作符語義,索引?index1?和?index2?中的值相同的話,返回 1 。 否則返回 0 。 如果任何一個索引無效也會返回 0。


lua_error

int lua_error (lua_State *L);

產(chǎn)生一個 Lua 錯誤。 錯誤信息(實際上可以是任何類型的 Lua 值)必須被置入棧頂。 這個函數(shù)會做一次長跳轉(zhuǎn),因此它不會再返回。 (參見?luaL_error)。


lua_gc

int lua_gc (lua_State *L, int what, int data);

控制垃圾收集器。

這個函數(shù)根據(jù)其參數(shù)?what?發(fā)起幾種不同的任務(wù):

  • LUA_GCSTOP:?停止垃圾收集器。
  • LUA_GCRESTART:?重啟垃圾收集器。
  • LUA_GCCOLLECT:?發(fā)起一次完整的垃圾收集循環(huán)。
  • LUA_GCCOUNT:?返回 Lua 使用的內(nèi)存總量(以 K 字節(jié)為單位)。
  • LUA_GCCOUNTB:?返回當(dāng)前內(nèi)存使用量除以 1024 的余數(shù)。
  • LUA_GCSTEP:?發(fā)起一步增量垃圾收集。 步數(shù)由?data?控制(越大的值意味著越多步), 而其具體含義(具體數(shù)字表示了多少)并未標(biāo)準化。 如果你想控制這個步數(shù),必須實驗性的測試?data?的值。 如果這一步結(jié)束了一個垃圾收集周期,返回返回 1 。
  • LUA_GCSETPAUSE:?把?data/100 設(shè)置為?garbage-collector pause?的新值(參見?§2.10)。 函數(shù)返回以前的值。
  • LUA_GCSETSTEPMUL:?把?arg/100 設(shè)置成?step multiplier?(參見?§2.10)。 函數(shù)返回以前的值。

lua_getallocf

lua_Alloc lua_getallocf (lua_State *L, void **ud);

返回給定狀態(tài)機的內(nèi)存分配器函數(shù)。 如果?ud?不是?NULL?,Lua 把調(diào)用?lua_newstate?時傳入的那個指針放入?*ud?。


lua_getfenv

void lua_getfenv (lua_State *L, int index);

把索引處值的環(huán)境表壓入堆棧。


lua_getfield

void lua_getfield (lua_State *L, int index, const char *k);

把?t[k]?值壓入堆棧, 這里的?t?是指有效索引?index?指向的值。 在 Lua 中,這個函數(shù)可能觸發(fā)對應(yīng) "index" 事件的元方法 (參見?§2.8)。


lua_getglobal

void lua_getglobal (lua_State *L, const char *name);

把全局變量?name?里的值壓入堆棧。 這個是用一個宏定義出來的:

#define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, s)

lua_getmetatable

int lua_getmetatable (lua_State *L, int index);

把給定索引指向的值的元表壓入堆棧。 如果索引無效,或是這個值沒有元表, 函數(shù)將返回 0 并且不會向棧上壓任何東西。


lua_gettable

void lua_gettable (lua_State *L, int index);

把?t[k]?值壓入堆棧, 這里的?t?是指有效索引?index?指向的值, 而?k?則是棧頂放的值。

這個函數(shù)會彈出堆棧上的 key (把結(jié)果放在棧上相同位置)。 在 Lua 中,這個函數(shù)可能觸發(fā)對應(yīng) "index" 事件的元方法 (參見?§2.8)。


lua_gettop

int lua_gettop (lua_State *L);

返回棧頂元素的索引。 因為索引是從 1 開始編號的, 所以這個結(jié)果等于堆棧上的元素個數(shù)(因此返回 0 表示堆棧為空)。


lua_insert

void lua_insert (lua_State *L, int index);

把棧頂元素插入指定的有效索引處, 并依次移動這個索引之上的元素。 不要用偽索引來調(diào)用這個函數(shù), 因為偽索引不是真正指向堆棧上的位置。


lua_Integer

typedef ptrdiff_t lua_Integer;

這個類型被用于 Lua API 接收整數(shù)值。

缺省時這個被定義為?ptrdiff_t?, 這個東西通常是機器能處理的最大整數(shù)類型。


lua_isboolean

int lua_isboolean (lua_State *L, int index);

當(dāng)給定索引的值類型為 boolean 時,返回 1 ,否則返回 0 。


lua_iscfunction

int lua_iscfunction (lua_State *L, int index);

當(dāng)給定索引的值是一個 C 函數(shù)時,返回 1 ,否則返回 0 。


lua_isfunction

int lua_isfunction (lua_State *L, int index);

當(dāng)給定索引的值是一個函數(shù)( C 或 Lua 函數(shù)均可)時,返回 1 ,否則返回 0 。


lua_islightuserdata

int lua_islightuserdata (lua_State *L, int index);

當(dāng)給定索引的值是一個 light userdata 時,返回 1 ,否則返回 0 。


lua_isnil

int lua_isnil (lua_State *L, int index);

當(dāng)給定索引的值是?nil?時,返回 1 ,否則返回 0 。


lua_isnumber

int lua_isnumber (lua_State *L, int index);

當(dāng)給定索引的值是一個數(shù)字,或是一個可轉(zhuǎn)換為數(shù)字的字符串時,返回 1 ,否則返回 0 。


lua_isstring

int lua_isstring (lua_State *L, int index);

當(dāng)給定索引的值是一個字符串或是一個數(shù)字(數(shù)字總能轉(zhuǎn)換成字符串)時,返回 1 ,否則返回 0 。


lua_istable

int lua_istable (lua_State *L, int index);

當(dāng)給定索引的值是一個 table 時,返回 1 ,否則返回 0 。


lua_isthread

int lua_isthread (lua_State *L, int index);

當(dāng)給定索引的值是一個 thread 時,返回 1 ,否則返回 0 。


lua_isuserdata

int lua_isuserdata (lua_State *L, int index);

當(dāng)給定索引的值是一個 userdata (無論是完整的 userdata 還是 light userdata )時,返回 1 ,否則返回 0 。


lua_lessthan

int lua_lessthan (lua_State *L, int index1, int index2);

如果索引?index1?處的值小于 索引?index2?處的值時,返回 1 ; 否則返回 0 。 其語義遵循 Lua 中的?<?操作符(就是說,有可能調(diào)用元方法)。 如果任何一個索引無效,也會返回 0 。


lua_load

int lua_load (lua_State *L,lua_Reader reader,void *data,const char *chunkname);

加載一個 Lua chunk 。 如果沒有錯誤,?lua_load?把一個編譯好的 chunk 作為一個 Lua 函數(shù)壓入堆棧。 否則,壓入出錯信息。?lua_load?的返回值可以是:

  • 0:?沒有錯誤;
  • LUA_ERRSYNTAX:?在預(yù)編譯時碰到語法錯誤;
  • LUA_ERRMEM:?內(nèi)存分配錯誤。

這個函數(shù)僅僅加栽 chunk ;而不會去運行它。

lua_load?會自動檢測 chunk 是文本的還是二進制的, 然后做對應(yīng)的加載操作(參見程序?luac)。

lua_load?函數(shù)使用一個用戶提供的?reader?函數(shù)來 讀取 chunk (參見?lua_Reader)。?data?參數(shù)會被傳入讀取器函數(shù)。

chunkname?這個參數(shù)可以賦予 chunk 一個名字, 這個名字被用于出錯信息和調(diào)試信息(參見?§3.8)。


lua_newstate

lua_State *lua_newstate (lua_Alloc f, void *ud);

創(chuàng)建的一個新的獨立的狀態(tài)機。 如果創(chuàng)建不了(因為內(nèi)存問題)返回?NULL?。 參數(shù)?f?是一個分配器函數(shù); Lua 將通過這個函數(shù)做狀態(tài)機內(nèi)所有的內(nèi)存分配操作。 第二個參數(shù)?ud?,這個指針將在每次調(diào)用分配器時被直接傳入。


lua_newtable

void lua_newtable (lua_State *L);

創(chuàng)建一個空 table ,并將之壓入堆棧。 它等價于?lua_createtable(L, 0, 0)?。


lua_newthread

lua_State *lua_newthread (lua_State *L);

創(chuàng)建一個新線程,并將其壓入堆棧, 并返回維護這個線程的?lua_State?指針。 這個函數(shù)返回的新狀態(tài)機共享原有狀態(tài)機中的所有對象(比如一些 table), 但是它有獨立的執(zhí)行堆棧。

沒有顯式的函數(shù)可以用來關(guān)閉或銷毀掉一個線程。 線程跟其它 Lua 對象一樣是垃圾收集的條目之一。


lua_newuserdata

void *lua_newuserdata (lua_State *L, size_t size);

這個函數(shù)分配分配一塊指定大小的內(nèi)存塊, 把內(nèi)存塊地址作為一個完整的 userdata 壓入堆棧,并返回這個地址。

userdata 代表 Lua 中的 C 值。 完整的 userdata 代表一塊內(nèi)存。 它是一個對象(就像 table 那樣的對象): 你必須創(chuàng)建它,它有著自己的元表,而且它在被回收時,可以被監(jiān)測到。 一個完整的 userdata 只和它自己相等(在等于的原生作用下)。

當(dāng) Lua 通過?gc?元方法回收一個完整的 userdata 時, Lua 調(diào)用這個元方法并把 userdata 標(biāo)記為已終止。 等到這個 userdata 再次被收集的時候,Lua 會釋放掉相關(guān)的內(nèi)存。


lua_next

int lua_next (lua_State *L, int index);

從棧上彈出一個 key(鍵), 然后把索引指定的表中 key-value(健值)對壓入堆棧 (指定 key 后面的下一 (next) 對)。 如果表中以無更多元素, 那么?lua_next將返回 0 (什么也不壓入堆棧)。

典型的遍歷方法是這樣的:

/* table 放在索引 't' 處 */lua_pushnil(L); /* 第一個 key */while (lua_next(L, t) != 0) {/* 用一下 'key' (在索引 -2 處) 和 'value' (在索引 -1 處) */printf("%s - %s\n",lua_typename(L, lua_type(L, -2)),lua_typename(L, lua_type(L, -1)));/* 移除 'value' ;保留 'key' 做下一次迭代 */lua_pop(L, 1);}

在遍歷一張表的時候, 不要直接對 key 調(diào)用?lua_tolstring?, 除非你知道這個 key 一定是一個字符串。 調(diào)用?lua_tolstring?有可能改變給定索引位置的值; 這會對下一次調(diào)用?lua_next?造成影響。


lua_Number

typedef double lua_Number;

Lua 中數(shù)字的類型。 確省是 double ,但是你可以在?luaconf.h?中修改它。

通過修改配置文件你可以改變 Lua 讓它操作其它數(shù)字類型(例如:float 或是 long )。


lua_objlen

size_t lua_objlen (lua_State *L, int index);

返回指定的索引處的值的長度。 對于 string ,那就是字符串的長度; 對于 table ,是取長度操作符 ('#') 的結(jié)果; 對于 userdata ,就是為其分配的內(nèi)存塊的尺寸; 對于其它值,為 0 。


lua_pcall

lua_pcall (lua_State *L, int nargs, int nresults, int errfunc);

以保護模式調(diào)用一個函數(shù)。

nargs?和?nresults?的含義與?lua_call?中的相同。 如果在調(diào)用過程中沒有發(fā)生錯誤,?lua_pcall?的行為和?lua_call?完全一致。 但是,如果有錯誤發(fā)生的話,?lua_pcall會捕獲它, 然后把單一的值(錯誤信息)壓入堆棧,然后返回錯誤碼。 同?lua_call?一樣,?lua_pcall?總是把函數(shù)本身和它的參數(shù)從棧上移除。

如果?errfunc?是 0 , 返回在棧頂?shù)腻e誤信息就和原始錯誤信息完全一致。 否則,errfunc?就被當(dāng)成是錯誤處理函數(shù)在棧上的索引。 (在當(dāng)前的實現(xiàn)里,這個索引不能是偽索引。) 在發(fā)生運行時錯誤時, 這個函數(shù)會被調(diào)用而參數(shù)就是錯誤信息。 錯誤處理函數(shù)的返回值將被?lua_pcall?作為出錯信息返回在堆棧上。

典型的用法中,錯誤處理函數(shù)被用來在出錯信息上加上更多的調(diào)試信息,比如棧跟蹤信息 (stack traceback) 。 這些信息在?lua_pcall?返回后,因為棧已經(jīng)展開 (unwound) , 所以收集不到了。

lua_pcall?函數(shù)在調(diào)用成功時返回 0 , 否則返回以下(定義在?lua.h?中的)錯誤代碼中的一個:

  • LUA_ERRRUN:?運行時錯誤。
  • LUA_ERRMEM:?內(nèi)存分配錯誤。 對于這種錯,Lua 調(diào)用不了錯誤處理函數(shù)。
  • LUA_ERRERR:?在運行錯誤處理函數(shù)時發(fā)生的錯誤。

lua_pop

void lua_pop (lua_State *L, int n);

從堆棧中彈出?n?個元素。


lua_pushboolean

void lua_pushboolean (lua_State *L, int b);

把?b?作為一個 boolean 值壓入堆棧。


lua_pushcclosure

void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n);

把一個新的 C closure 壓入堆棧。

當(dāng)創(chuàng)建了一個 C 函數(shù)后,你可以給它關(guān)聯(lián)一些值,這樣就是在創(chuàng)建一個 C closure (參見?§3.4); 接下來無論函數(shù)何時被調(diào)用,這些值都可以被這個函數(shù)訪問到。 為了將一些值關(guān)聯(lián)到一個 C 函數(shù)上, 首先這些值需要先被壓入堆棧(如果有多個值,第一個先壓)。 接下來調(diào)用?lua_pushcclosure?來創(chuàng)建出 closure 并把這個 C 函數(shù)壓到堆棧上。 參數(shù)?n?告之函數(shù)有多少個值需要關(guān)聯(lián)到函數(shù)上。?lua_pushcclosure?也會把這些值從棧上彈出。


lua_pushcfunction

void lua_pushcfunction (lua_State *L, lua_CFunction f);

將一個 C 函數(shù)壓入堆棧。 這個函數(shù)接收一個 C 函數(shù)指針,并將一個類型為?function?的 Lua 值 壓入堆棧。當(dāng)這個棧頂?shù)闹当徽{(diào)用時,將觸發(fā)對應(yīng)的 C 函數(shù)。

注冊到 Lua 中的任何函數(shù)都必須遵循正確的協(xié)議來接收參數(shù)和返回值 (參見?lua_CFunction)。

lua_pushcfunction?是作為一個宏定義出現(xiàn)的:

#define lua_pushcfunction(L,f) lua_pushcclosure(L,f,0)

lua_pushfstring

const char *lua_pushfstring (lua_State *L, const char *fmt, ...);

把一個格式化過的字符串壓入堆棧,然后返回這個字符串的指針。 它和 C 函數(shù)?sprintf?比較像,不過有一些重要的區(qū)別:

  • 摸你需要為結(jié)果分配空間: 其結(jié)果是一個 Lua 字符串,由 Lua 來關(guān)心其內(nèi)存分配 (同時通過垃圾收集來釋放內(nèi)存)。
  • 這個轉(zhuǎn)換非常的受限。 不支持 flag ,寬度,或是指定精度。 它只支持下面這些: '%%' (插入一個 '%'), '%s' (插入一個帶零終止符的字符串,沒有長度限制), '%f' (插入一個?lua_Number), '%p' (插入一個指針或是一個十六進制數(shù)), '%d' (插入一個?int), '%c' (把一個?int?作為一個字符插入)。

lua_pushinteger

void lua_pushinteger (lua_State *L, lua_Integer n);

把?n?作為一個數(shù)字壓棧。


lua_pushlightuserdata

void lua_pushlightuserdata (lua_State *L, void *p);

把一個 light userdata 壓棧。

userdata 在 Lua 中表示一個 C 值。 light userdata 表示一個指針。 它是一個像數(shù)字一樣的值: 你不需要專門創(chuàng)建它,它也沒有獨立的 metatable , 而且也不會被收集(因為從來不需要創(chuàng)建)。 只要表示的 C 地址相同,兩個 light userdata 就相等。


lua_pushlstring

void lua_pushlstring (lua_State *L, const char *s, size_t len);

把指針?s?指向的長度為?len?的字符串壓棧。 Lua 對這個字符串做一次內(nèi)存拷貝(或是復(fù)用一個拷貝), 因此?s?處的內(nèi)存在函數(shù)返回后,可以釋放掉或是重用于其它用途。 字符串內(nèi)可以保存有零字符。


lua_pushnil

void lua_pushnil (lua_State *L);

把一個 nil 壓棧。


lua_pushnumber

void lua_pushnumber (lua_State *L, lua_Number n);

把一個數(shù)字?n?壓棧。


lua_pushstring

void lua_pushstring (lua_State *L, const char *s);

把指針?s?指向的以零結(jié)尾的字符串壓棧。 Lua 對這個字符串做一次內(nèi)存拷貝(或是復(fù)用一個拷貝), 因此?s?處的內(nèi)存在函數(shù)返回后,可以釋放掉或是重用于其它用途。 字符串中不能包含有零字符;第一個碰到的零字符會認為是字符串的結(jié)束。


lua_pushthread

int lua_pushthread (lua_State *L);

把?L?中提供的線程壓棧。 如果這個線程是當(dāng)前狀態(tài)機的主線程的話,返回 1 。


lua_pushvalue

void lua_pushvalue (lua_State *L, int index);

把堆棧上給定有效處索引處的元素作一個拷貝壓棧。


lua_pushvfstring

const char *lua_pushvfstring (lua_State *L,const char *fmt,va_list argp);

等價于?lua_pushfstring, 不過是用?va_list?接收參數(shù),而不是用可變數(shù)量的實際參數(shù)。


lua_rawequal

int lua_rawequal (lua_State *L, int index1, int index2);

如果兩個索引?index1?和?index2?處的值簡單地相等 (不調(diào)用元方法)則返回 1 。 否則返回 0 。 如果任何一個索引無效也返回 0 。


lua_rawget

void lua_rawget (lua_State *L, int index);

類似于?lua_gettable, 但是作一次直接訪問(不觸發(fā)元方法)。


lua_rawgeti

void lua_rawgeti (lua_State *L, int index, int n);

把?t[n]?的值壓棧, 這里的?t?是指給定索引?index?處的一個值。 這是一個直接訪問;就是說,它不會觸發(fā)元方法。


lua_rawset

void lua_rawset (lua_State *L, int index);

類似于?lua_settable, 但是是作一個直接賦值(不觸發(fā)元方法)。


lua_rawseti

void lua_rawseti (lua_State *L, int index, int n);

等價于?t[n] = v, 這里的?t?是指給定索引?index?處的一個值, 而?v?是棧頂?shù)闹怠?/p>

函數(shù)將把這個值彈出棧。 賦值操作是直接的;就是說,不會觸發(fā)元方法。


lua_Reader

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

lua_load?用到的讀取器函數(shù), 每次它需要一塊新的 chunk 的時候,?lua_load?就調(diào)用讀取器, 每次都會傳入一個參數(shù)?data?。 讀取器需要返回含有新的 chunk 的一塊內(nèi)存的指針, 并把?size?設(shè)為這塊內(nèi)存的大小。 內(nèi)存塊必須在下一次函數(shù)被調(diào)用之前一直存在。 讀取器可以通過返回一個?NULL?來指示 chunk 結(jié)束。 讀取器可能返回多個塊,每個塊可以有任意的大于零的尺寸。


lua_register

void lua_register (lua_State *L,const char *name,lua_CFunction f);

把 C 函數(shù)?f?設(shè)到全局變量?name?中。 它通過一個宏定義:

#define lua_register(L,n,f) \(lua_pushcfunction(L, f), lua_setglobal(L, n))

lua_remove

void lua_remove (lua_State *L, int index);

從給定有效索引處移除一個元素, 把這個索引之上的所有元素移下來填補上這個空隙。 不能用偽索引來調(diào)用這個函數(shù), 因為偽索引并不指向真實的棧上的位置。


lua_replace

void lua_replace (lua_State *L, int index);

把棧頂元素移動到給定位置(并且把這個棧頂元素彈出), 不移動任何元素(因此在那個位置處的值被覆蓋掉)。


lua_resume

int lua_resume (lua_State *L, int narg);

在給定線程中啟動或繼續(xù)一個 coroutine 。

要啟動一個 coroutine 的話,首先你要創(chuàng)建一個新線程 (參見?lua_newthread?); 然后把主函數(shù)和若干參數(shù)壓到新線程的堆棧上; 最后調(diào)用?lua_resume?, 把?narg設(shè)為參數(shù)的個數(shù)。 這次調(diào)用會在 coroutine 掛起時或是結(jié)束運行后返回。 當(dāng)函數(shù)返回時,堆棧中會有傳給?lua_yield?的所有值, 或是主函數(shù)的所有返回值。 如果 coroutine 切換時,lua_resume?返回?LUA_YIELD?, 而當(dāng) coroutine 結(jié)束運行且沒有任何錯誤時,返回 0 。 如果有錯則返回錯誤代碼(參見?lua_pcall)。 在發(fā)生錯誤的情況下, 堆棧沒有展開, 因此你可以使用 debug API 來處理它。 出錯信息放在棧頂。 要繼續(xù)運行一個 coroutine 的話,你把需要傳給?yield?作結(jié)果的返回值壓入堆棧,然后調(diào)用?lua_resume?。


lua_setallocf

void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);

把指定狀態(tài)機的分配器函數(shù)換成帶上指針?ud?的?f?。


lua_setfenv

int lua_setfenv (lua_State *L, int index);

從堆棧上彈出一個 table 并把它設(shè)為指定索引處值的新環(huán)境。 如果指定索引處的值即不是函數(shù)又不是線程或是 userdata ,?lua_setfenv?會返回 0 , 否則返回 1 。


lua_setfield

void lua_setfield (lua_State *L, int index, const char *k);

做一個等價于?t[k] = v?的操作, 這里?t?是給出的有效索引?index?處的值, 而?v?是棧頂?shù)哪莻€值。

這個函數(shù)將把這個值彈出堆棧。 跟在 Lua 中一樣,這個函數(shù)可能觸發(fā)一個 "newindex" 事件的元方法 (參見?§2.8)。


lua_setglobal

void lua_setglobal (lua_State *L, const char *name);

從堆棧上彈出一個值,并將其設(shè)到全局變量?name?中。 它由一個宏定義出來:

#define lua_setglobal(L,s) lua_setfield(L, LUA_GLOBALSINDEX, s)

lua_setmetatable

int lua_setmetatable (lua_State *L, int index);

把一個 table 彈出堆棧,并將其設(shè)為給定索引處的值的 metatable 。


lua_settable

void lua_settable (lua_State *L, int index);

作一個等價于?t[k] = v?的操作, 這里?t?是一個給定有效索引?index?處的值,?v?指棧頂?shù)闹?#xff0c; 而?k?是棧頂之下的那個值。

這個函數(shù)會把鍵和值都從堆棧中彈出。 和在 Lua 中一樣,這個函數(shù)可能觸發(fā) "newindex" 事件的元方法 (參見?§2.8)。


lua_settop

void lua_settop (lua_State *L, int index);

參數(shù)允許傳入任何可接受的索引以及 0 。 它將把堆棧的棧頂設(shè)為這個索引。 如果新的棧頂比原來的大,超出部分的新元素將被填為?nil?。 如果?index?為 0 ,把棧上所有元素移除。


lua_State

typedef struct lua_State lua_State;

一個不透明的結(jié)構(gòu),它保存了整個 Lua 解釋器的狀態(tài)。 Lua 庫是完全可重入的: 它沒有任何全局變量。 (譯注:從 C 語法上來說,也不盡然。例如,在 table 的實現(xiàn)中 用了一個靜態(tài)全局變量 dummynode_ ,但這在正確使用時并不影響可重入性。 只是萬一你錯誤鏈接了 lua 庫,不小心在同一進程空間中存在兩份 lua 庫實現(xiàn)的代碼的話, 多份 dummynode_ 不同的地址會導(dǎo)致一些問題。) 所有的信息都保存在這個結(jié)構(gòu)中。

這個狀態(tài)機的指針必須作為第一個參數(shù)傳遞給每一個庫函數(shù)。?lua_newstate?是一個例外, 這個函數(shù)會從頭創(chuàng)建一個 Lua 狀態(tài)機。


lua_status

int lua_status (lua_State *L);

返回線程?L?的狀態(tài)。

正常的線程狀態(tài)是 0 。 當(dāng)線程執(zhí)行完畢或發(fā)生一個錯誤時,狀態(tài)值是錯誤碼。 如果線程被掛起,狀態(tài)為?LUA_YIELD?。


lua_toboolean

int lua_toboolean (lua_State *L, int index);

把指定的索引處的的 Lua 值轉(zhuǎn)換為一個 C 中的 boolean 值( 0 或是 1 )。 和 Lua 中做的所有測試一樣,?lua_toboolean?會把任何 不同于?false?和?nil?的值當(dāng)作 1 返回; 否則就返回 0 。 如果用一個無效索引去調(diào)用也會返回 0 。 (如果你想只接收真正的 boolean 值,就需要使用?lua_isboolean?來測試值的類型。)


lua_tocfunction

lua_CFunction lua_tocfunction (lua_State *L, int index);

把給定索引處的 Lua 值轉(zhuǎn)換為一個 C 函數(shù)。 這個值必須是一個 C 函數(shù);如果不是就返回?NULL?。


lua_tointeger

lua_Integer lua_tointeger (lua_State *L, int idx);

把給定索引處的 Lua 值轉(zhuǎn)換為?lua_Integer?這樣一個有符號整數(shù)類型。 這個 Lua 值必須是一個數(shù)字或是一個可以轉(zhuǎn)換為數(shù)字的字符串 (參見?§2.2.1); 否則,lua_tointeger?返回 0 。

如果數(shù)字不是一個整數(shù), 截斷小數(shù)部分的方式?jīng)]有被明確定義。


lua_tolstring

const char *lua_tolstring (lua_State *L, int index, size_t *len);

把給定索引處的 Lua 值轉(zhuǎn)換為一個 C 字符串。 如果?len?不為?NULL?, 它還把字符串長度設(shè)到?*len?中。 這個 Lua 值必須是一個字符串或是一個數(shù)字; 否則返回返回?NULL?。 如果值是一個數(shù)字,lua_tolstring?還會把堆棧中的那個值的實際類型轉(zhuǎn)換為一個字符串。 (當(dāng)遍歷一個表的時候,把?lua_tolstring?作用在鍵上,這個轉(zhuǎn)換有可能導(dǎo)致?lua_next?弄錯。)

lua_tolstring?返回 Lua 狀態(tài)機中 字符串的以對齊指針。 這個字符串總能保證 ( C 要求的)最后一個字符為零 ('\0') , 而且它允許在字符串內(nèi)包含多個這樣的零。 因為 Lua 中可能發(fā)生垃圾收集, 所以不保證?lua_tolstring?返回的指針, 在對應(yīng)的值從堆棧中移除后依然有效。


lua_tonumber

lua_Number lua_tonumber (lua_State *L, int index);

把給定索引處的 Lua 值轉(zhuǎn)換為?lua_Number?這樣一個 C 類型(參見?lua_Number?)。 這個 Lua 值必須是一個數(shù)字或是一個可轉(zhuǎn)換為數(shù)字的字符串 (參見?§2.2.1?); 否則,lua_tonumber?返回 0 。


lua_topointer

const void *lua_topointer (lua_State *L, int index);

把給定索引處的值轉(zhuǎn)換為一般的 C 指針 (void*) 。 這個值可以是一個 userdata ,table ,thread 或是一個 function ; 否則,lua_topointer?返回?NULL?。 不同的對象有不同的指針。 不存在把指針再轉(zhuǎn)回原有類型的方法。

這個函數(shù)通常只為產(chǎn)生 debug 信息用。


lua_tostring

const char *lua_tostring (lua_State *L, int index);

等價于?lua_tolstring?,而參數(shù)?len?設(shè)為?NULL?。


lua_tothread

lua_State *lua_tothread (lua_State *L, int index);

把給定索引處的值轉(zhuǎn)換為一個 Lua 線程(由?lua_State*?代表)。 這個值必須是一個線程;否則函數(shù)返回?NULL?。


lua_touserdata

void *lua_touserdata (lua_State *L, int index);

如果給定索引處的值是一個完整的 userdata ,函數(shù)返回內(nèi)存塊的地址。 如果值是一個 light userdata ,那么就返回它表示的指針。 否則,返回?NULL?。


lua_type

int lua_type (lua_State *L, int index);

返回給定索引處的值的類型, 當(dāng)索引無效時則返回?LUA_TNONE?(那是指一個指向堆棧上的空位置的索引)。?lua_type?返回的類型是一些個在?lua.h?中定義的常量:LUA_TNIL?,?LUA_TNUMBER?,?LUA_TBOOLEAN?,?LUA_TSTRING?,?LUA_TTABLE?,?LUA_TFUNCTION?,?LUA_TUSERDATA?,?LUA_TTHREAD?,?LUA_TLIGHTUSERDATA?。


lua_typename

const char *lua_typename (lua_State *L, int tp);

返回?tp?表示的類型名, 這個?tp?必須是?lua_type?可能返回的值中之一。


lua_Writer

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

由?lua_dump?用到的寫入器函數(shù)。 每次?lua_dump?產(chǎn)生了一塊新的 chunk ,它都會調(diào)用寫入器。 傳入要寫入的緩存 (p) 和它的尺寸 (sz) , 還有?lua_dump?的參數(shù)?data。

寫入器會返回一個錯誤碼: 0 表示沒有錯誤; 別的值均表示一個錯誤,并且會讓?lua_dump?停止再次調(diào)用寫入器。


lua_xmove

void lua_xmove (lua_State *from, lua_State *to, int n);

傳遞?同一個?全局狀態(tài)機下不同線程中的值。

這個函數(shù)會從?from?的堆棧中彈出?n?個值, 然后把它們壓入?to?的堆棧中。


lua_yield

int lua_yield (lua_State *L, int nresults);

切出一個 coroutine 。

這個函數(shù)只能在一個 C 函數(shù)的返回表達式中調(diào)用。如下:

return lua_yield (L, nresults);

當(dāng)一個 C 函數(shù)這樣調(diào)用?lua_yield?, 正在運行中的 coroutine 將從運行中掛起, 然后啟動這個 coroutine 用的那次對?lua_resume?的調(diào)用就返回了。 參數(shù)?nresults指的是堆棧中需要返回的結(jié)果個數(shù),這些返回值將被傳遞給?lua_resume?。

3.8 -?調(diào)試接口

Lua 沒有內(nèi)建的調(diào)試設(shè)施。 取而代之的是提供了一些函數(shù)接口和鉤子。 利用這些接口,可以做出一些不同類型的調(diào)試器, 性能分析器,或是其它一些需要從解釋器中取到“內(nèi)部信息”的工具。


lua_Debug

typedef struct lua_Debug {int event;const char *name; /* (n) */const char *namewhat; /* (n) */const char *what; /* (S) */const char *source; /* (S) */int currentline; /* (l) */int nups; /* (u) upvalue 個數(shù) */int linedefined; /* (S) */int lastlinedefined; /* (S) */char short_src[LUA_IDSIZE]; /* (S) *//* 私有部分 */其它域 } lua_Debug;

一個用來攜帶活動中函數(shù)的各種信息的結(jié)構(gòu)。?lua_getstack?僅填寫這個結(jié)構(gòu)中的私有部分, 這些部分以后會用到。 調(diào)用?lua_getinfo?則可以填上?lua_Debug?中有用信息的那些域。

lua_Debug?中的各個域有下列含義:

  • source:?如果函數(shù)是定義在一個字符串中,source?就是這個字符串。 如果函數(shù)定義在一個文件中,?source?是一個以 '@' 開頭的文件名。
  • short_src:?一個“可打印版本”的?source,用于出錯信息。
  • linedefined:?函數(shù)定義開始處的行號。
  • lastlinedefined:?函數(shù)定義結(jié)束處的行號。
  • what:?如果函數(shù)是一個 Lua 函數(shù),則為一個字符串?"Lua"?; 如果是一個 C 函數(shù),則為?"C"; 如果它是一個 chunk 的主體部分,則為?"main"; 如果是一個作了尾調(diào)用的函數(shù),則為?"tail"?。 別的情況下,Lua 沒有關(guān)于函數(shù)的別的信息。
  • currentline:?給定函數(shù)正在執(zhí)行的那一行。 當(dāng)提供不了行號信息的時候,currentline?被設(shè)為 -1 。
  • name:?給定函數(shù)的一個合理的名字。 因為 Lua 中的函數(shù)也是一個值, 所以它們沒有固定的名字: 一些函數(shù)可能是全局復(fù)合變量的值, 另一些可能僅僅只是被保存在一個 table 中。?lua_getinfo?函數(shù)會檢查函數(shù)是這樣被調(diào)用的,以此來找到一個適合的名字。 如果它找不到名字,name?就被設(shè)置為?NULL?。
  • namewhat:?結(jié)實?name?域。?namewhat?的值可以是?"global",?"local",?"method",?"field",?"upvalue", 或是?""?(空串)。 這取決于函數(shù)怎樣被調(diào)用。 (Lua 用空串表示其它選項都不符合)
  • nups:?函數(shù)的 upvalue 的個數(shù)。

lua_gethook

lua_Hook lua_gethook (lua_State *L);

返回當(dāng)前的鉤子函數(shù)。


lua_gethookcount

int lua_gethookcount (lua_State *L);

返回當(dāng)前鉤子記數(shù)。


lua_gethookmask

int lua_gethookmask (lua_State *L);

返回當(dāng)前的鉤子掩碼 (mask) 。


lua_getinfo

int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);

返回一個指定的函數(shù)或函數(shù)調(diào)用的信息。

當(dāng)用于取得一次函數(shù)調(diào)用的信息時, 參數(shù)?ar?必須是一個有效的活動的記錄。 這條記錄可以是前一次調(diào)用?lua_getstack?得到的, 或是一個鉤子 (參見?lua_Hook)得到的參數(shù)。

用于獲取一個函數(shù)的信息時,可以把這個函數(shù)壓入堆棧, 然后把?what?字符串以字符 '>' 起頭。 (這個情況下,lua_getinfo?從棧頂上彈出函數(shù)。) 例如,想知道函數(shù)?f?在哪一行定義的, 你可以下下列代碼:

lua_Debug ar;lua_getfield(L, LUA_GLOBALSINDEX, "f"); /* 取到全局變量 'f' */lua_getinfo(L, ">S", &ar);printf("%d\n", ar.linedefined);

what?字符串中的每個字符都篩選出結(jié)構(gòu)?ar?結(jié)構(gòu)中一些域用于填充,或是把一個值壓入堆棧:

  • 'n':?填充?name?及?namewhat?域;
  • 'S':?填充?source,?short_src,?linedefined,?lastlinedefined,以及?what?域;
  • 'l':?填充?currentline?域;
  • 'u':?填充?nups?域;
  • 'f':?把正在運行中指定級別處函數(shù)壓入堆棧; (譯注:一般用于獲取函數(shù)調(diào)用中的信息, 級別是由 ar 中的私有部分來提供。 如果用于獲取靜態(tài)函數(shù),那么就直接把指定函數(shù)重新壓回堆棧, 但這樣做通常無甚意義。)
  • 'L':?壓一個 table 入棧,這個 table 中的整數(shù)索引用于描述函數(shù)中哪些行是有效行。 (有效行指有實際代碼的行, 即你可以置入斷點的行。 無效行包括空行和只有注釋的行。)

這個函數(shù)出錯會返回 0 (例如,what?中有一個無效選項)。


lua_getlocal

const char *lua_getlocal (lua_State *L, lua_Debug *ar, int n);

從給定活動記錄中獲取一個局部變量的信息。 參數(shù)?ar?必須是一個有效的活動的記錄。 這條記錄可以是前一次調(diào)用?lua_getstack?得到的, 或是一個鉤子 (參見lua_Hook)得到的參數(shù)。 索引?n?用于選擇要檢閱哪個局部變量 ( 1 表示第一個參數(shù)或是激活的第一個局部變量,以此類推,直到最后一個局部變量)。?lua_getlocal把變量的值壓入堆棧并返回它的名字。

以 '(' (正小括號)開始的變量指內(nèi)部變量 (循環(huán)控制變量,臨時變量,C 函數(shù)局部變量)。

當(dāng)索引大于局部變量的個數(shù)時,返回?NULL?(什么也不壓入)。


lua_getstack

int lua_getstack (lua_State *L, int level, lua_Debug *ar);

獲取解釋器的運行時棧的信息。

這個函數(shù)用正在運行中的給定級別處的函數(shù)的活動記錄來填寫?lua_Debug?結(jié)構(gòu)的一部分。 0 級表示當(dāng)前運行的函數(shù), 而 n+1 級處的函數(shù)就是調(diào)用第 n 級函數(shù)的那一個。 如果沒有錯誤,lua_getstack?返回 1 ; 當(dāng)調(diào)用傳入的級別大于堆棧深度的時候,返回 0 。


lua_getupvalue

const char *lua_getupvalue (lua_State *L, int funcindex, int n);

獲取一個 closure 的 upvalue 信息。 (對于 Lua 函數(shù),upvalue 是函數(shù)需要使用的外部局部變量, 因此這些變量被包含在 closure 中。)?lua_getupvalue?獲取第n?個 upvalue , 把這個 upvalue 的值壓入堆棧,并且返回它的名字。?funcindex?指向堆棧上 closure 的位置。 ( 因為 upvalue 在整個函數(shù)中都有效,所以它們沒有特別的次序。 因此,它們以字母次序來編號。)

當(dāng)索引號比 upvalue 數(shù)量大的時候,返回?NULL?(而且不會壓入任何東西) 對于 C 函數(shù),這個函數(shù)用空串?""?表示所有 upvalue 的名字。


lua_Hook

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

用于調(diào)試的鉤子函數(shù)類型。

無論何時鉤子被調(diào)用,它的參數(shù)?ar?中的?event?域 都被設(shè)為觸發(fā)鉤子的事件。 Lua 把這些事件定義為以下常量:?LUA_HOOKCALL,?LUA_HOOKRET,?LUA_HOOKTAILRET,LUA_HOOKLINE, and?LUA_HOOKCOUNT。 除此之外,對于 line 事件,currentline?域也被設(shè)置。 要想獲得?ar?中的其他域, 鉤子必須調(diào)用?lua_getinfo。 對于返回事件,event?的正常值可能是?LUA_HOOKRET, 或者是?LUA_HOOKTAILRET?。 對于后一種情況,Lua 會對一個函數(shù)做的尾調(diào)用也模擬出一個返回事件出來; 對于這個模擬的返回事件,調(diào)用?lua_getinfo?沒有什么作用。

當(dāng) Lua 運行在一個鉤子內(nèi)部時,它將屏蔽掉其它對鉤子的調(diào)用。 也就是說,如果一個鉤子函數(shù)內(nèi)再調(diào)回 Lua 來執(zhí)行一個函數(shù)或是一個 chunk , 這個執(zhí)行操作不會觸發(fā)任何的鉤子。


lua_sethook

int lua_sethook (lua_State *L, lua_Hook f, int mask, int count);

設(shè)置一個調(diào)試用鉤子函數(shù)。

參數(shù)?f?是鉤子函數(shù)。?mask?指定在哪些事件時會調(diào)用: 它由下列一組位常量構(gòu)成?LUA_MASKCALL,?LUA_MASKRET,?LUA_MASKLINE, 以及?LUA_MASKCOUNT。 參數(shù)?count?只在 mask 中包含有?LUA_MASKCOUNT?才有意義。 對于每個事件,鉤子被調(diào)用的情況解釋如下:

  • call hook:?在解釋器調(diào)用一個函數(shù)時被調(diào)用。 鉤子將于 Lua 進入一個新函數(shù)后,函數(shù)獲取參數(shù)前被調(diào)用。
  • return hook:?在解釋器從一個函數(shù)中返回時調(diào)用。 鉤子將于 Lua 離開函數(shù)之前的那一刻被調(diào)用。 你無權(quán)訪問被函數(shù)返回出去的那些值。?(譯注:原文 (You have no access to the values to be returned by the function) 如此。 但“無權(quán)訪問”一詞值得商榷。 某些情況下你可以訪問到一些被命名為 (*temporary) 的局部變量, 那些索引被排在最后的 (*temporary) 變量指的就是返回值。 但是由于 Lua 對特殊情況做了一些優(yōu)化,比如直接返回一個被命名的局部變量, 那么就找不到對應(yīng)的 (*temporary) 變量了。本質(zhì)上,返回值一定存在于此刻的局部變量中, 并且可以訪問它,只是無法確定是哪些罷了。至于這個時候函數(shù)體內(nèi)的其它局部變量, 是不保證有效的。進入 return hook 的那一刻起,實際已經(jīng)退出函數(shù)內(nèi)部的運行環(huán)節(jié), 返回值占用的局部變量空間以后的部分,都有可能因 hook 本身復(fù)用它們而改變。)
  • line hook:?在解釋器準備開始執(zhí)行新的一行代碼時, 或是跳轉(zhuǎn)到這行代碼中時(即使在同一行內(nèi)跳轉(zhuǎn))被調(diào)用。 (這個事件僅僅在 Lua 執(zhí)行一個 Lua 函數(shù)時發(fā)生。)
  • count hook:?在解釋器每執(zhí)行?count?條指令后被調(diào)用。 (這個事件僅僅在 Lua 執(zhí)行一個 Lua 函數(shù)時發(fā)生。)

鉤子可以通過設(shè)置?mask?為零屏蔽。


lua_setlocal

const char *lua_setlocal (lua_State *L, lua_Debug *ar, int n);

設(shè)置給定活動記錄中的局部變量的值。 參數(shù)?ar?與?n?和?lua_getlocal?中的一樣 (參見?lua_getlocal)。?lua_setlocal?把棧頂?shù)闹蒂x給變量然后返回變量的名字。 它會將值從棧頂彈出。

當(dāng)索引大于局部變量的個數(shù)時,返回?NULL?(什么也不彈出)。


lua_setupvalue

const char *lua_setupvalue (lua_State *L, int funcindex, int n);

設(shè)置 closure 的 upvalue 的值。 它把棧頂?shù)闹祻棾霾①x于 upvalue 并返回 upvalue 的名字。 參數(shù)?funcindex?與?n?和?lua_getupvalue?中的一樣 (參見lua_getupvalue)。

當(dāng)索引大于 upvalue 的個數(shù)時,返回?NULL?(什么也不彈出)。

4 -?The Auxiliary Library

The?auxiliary library?provides several convenient functions to interface C with Lua. While the basic API provides the primitive functions for all interactions between C and Lua, the auxiliary library provides higher-level functions for some common tasks.

All functions from the auxiliary library are defined in header file?lauxlib.h?and have a prefix?luaL_.

All functions in the auxiliary library are built on top of the basic API, and so they provide nothing that cannot be done with this API.

Several functions in the auxiliary library are used to check C?function arguments. Their names are always?luaL_check*?or?luaL_opt*. All of these functions raise an error if the check is not satisfied. Because the error message is formatted for arguments (e.g., "bad argument #1"), you should not use these functions for other stack values.

4.1 -?Functions and Types

Here we list all functions and types from the auxiliary library in alphabetical order.


luaL_addchar

void luaL_addchar (luaL_Buffer *B, char c);

Adds the character?c?to the buffer?B?(see?luaL_Buffer).


luaL_addlstring

void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l);

Adds the string pointed to by?s?with length?l?to the buffer?B?(see?luaL_Buffer). The string may contain embedded zeros.


luaL_addsize

void luaL_addsize (luaL_Buffer *B, size_t n);

Adds to the buffer?B?(see?luaL_Buffer) a string of length?n?previously copied to the buffer area (see?luaL_prepbuffer).


luaL_addstring

void luaL_addstring (luaL_Buffer *B, const char *s);

Adds the zero-terminated string pointed to by?s?to the buffer?B?(see?luaL_Buffer). The string may not contain embedded zeros.


luaL_addvalue

void luaL_addvalue (luaL_Buffer *B);

Adds the value at the top of the stack to the buffer?B?(see?luaL_Buffer). Pops the value.

This is the only function on string buffers that can (and must) be called with an extra element on the stack, which is the value to be added to the buffer.


luaL_argcheck

void luaL_argcheck (lua_State *L,int cond,int narg,const char *extramsg);

Checks whether?cond?is true. If not, raises an error with the following message, where?func?is retrieved from the call stack:

bad argument #<narg> to <func> (<extramsg>)

luaL_argerror

int luaL_argerror (lua_State *L, int narg, const char *extramsg);

Raises an error with the following message, where?func?is retrieved from the call stack:

bad argument #<narg> to <func> (<extramsg>)

This function never returns, but it is an idiom to use it in C?functions as?return luaL_argerror(args).


luaL_Buffer

typedef struct luaL_Buffer luaL_Buffer;

Type for a?string buffer.

A string buffer allows C?code to build Lua strings piecemeal. Its pattern of use is as follows:

  • First you declare a variable?b?of type?luaL_Buffer.
  • Then you initialize it with a call?luaL_buffinit(L, &b).
  • Then you add string pieces to the buffer calling any of the?luaL_add*?functions.
  • You finish by calling?luaL_pushresult(&b). This call leaves the final string on the top of the stack.

During its normal operation, a string buffer uses a variable number of stack slots. So, while using a buffer, you cannot assume that you know where the top of the stack is. You can use the stack between successive calls to buffer operations as long as that use is balanced; that is, when you call a buffer operation, the stack is at the same level it was immediately after the previous buffer operation. (The only exception to this rule is?luaL_addvalue.) After calling?luaL_pushresult?the stack is back to its level when the buffer was initialized, plus the final string on its top.


luaL_buffinit

void luaL_buffinit (lua_State *L, luaL_Buffer *B);

Initializes a buffer?B. This function does not allocate any space; the buffer must be declared as a variable (see?luaL_Buffer).


luaL_callmeta

int luaL_callmeta (lua_State *L, int obj, const char *e);

Calls a metamethod.

If the object at index?obj?has a metatable and this metatable has a field?e, this function calls this field and passes the object as its only argument. In this case this function returns 1 and pushes onto the stack the value returned by the call. If there is no metatable or no metamethod, this function returns 0 (without pushing any value on the stack).


luaL_checkany

void luaL_checkany (lua_State *L, int narg);

Checks whether the function has an argument of any type (including?nil) at position?narg.


luaL_checkint

int luaL_checkint (lua_State *L, int narg);

Checks whether the function argument?narg?is a number and returns this number cast to an?int.


luaL_checkinteger

lua_Integer luaL_checkinteger (lua_State *L, int narg);

Checks whether the function argument?narg?is a number and returns this number cast to a?lua_Integer.


luaL_checklong

long luaL_checklong (lua_State *L, int narg);

Checks whether the function argument?narg?is a number and returns this number cast to a?long.


luaL_checklstring

const char *luaL_checklstring (lua_State *L, int narg, size_t *l);

Checks whether the function argument?narg?is a string and returns this string; if?l?is not?NULL?fills?*l?with the string's length.


luaL_checknumber

lua_Number luaL_checknumber (lua_State *L, int narg);

Checks whether the function argument?narg?is a number and returns this number.


luaL_checkoption

int luaL_checkoption (lua_State *L,int narg,const char *def,const char *const lst[]);

Checks whether the function argument?narg?is a string and searches for this string in the array?lst?(which must be NULL-terminated). Returns the index in the array where the string was found. Raises an error if the argument is not a string or if the string cannot be found.

If?def?is not?NULL, the function uses?def?as a default value when there is no argument?narg?or if this argument is?nil.

This is a useful function for mapping strings to C?enums. (The usual convention in Lua libraries is to use strings instead of numbers to select options.)


luaL_checkstack

void luaL_checkstack (lua_State *L, int sz, const char *msg);

Grows the stack size to?top + sz?elements, raising an error if the stack cannot grow to that size.?msg?is an additional text to go into the error message.


luaL_checkstring

const char *luaL_checkstring (lua_State *L, int narg);

Checks whether the function argument?narg?is a string and returns this string.


luaL_checktype

void luaL_checktype (lua_State *L, int narg, int t);

Checks whether the function argument?narg?has type?t.


luaL_checkudata

void *luaL_checkudata (lua_State *L, int narg, const char *tname);

Checks whether the function argument?narg?is a userdata of the type?tname?(see?luaL_newmetatable).


luaL_dofile

int luaL_dofile (lua_State *L, const char *filename);

Loads and runs the given file. It is defined as the following macro:

(luaL_loadfile(L, filename) || lua_pcall(L, 0, LUA_MULTRET, 0))

It returns 0 if there are no errors or 1 in case of errors.


luaL_dostring

int luaL_dostring (lua_State *L, const char *str);

Loads and runs the given string. It is defined as the following macro:

(luaL_loadstring(L, str) || lua_pcall(L, 0, LUA_MULTRET, 0))

It returns 0 if there are no errors or 1 in case of errors.


luaL_error

int luaL_error (lua_State *L, const char *fmt, ...);

Raises an error. The error message format is given by?fmt?plus any extra arguments, following the same rules of?lua_pushfstring. It also adds at the beginning of the message the file name and the line number where the error occurred, if this information is available.

This function never returns, but it is an idiom to use it in C?functions as?return luaL_error(args).


luaL_getmetafield

int luaL_getmetafield (lua_State *L, int obj, const char *e);

Pushes onto the stack the field?e?from the metatable of the object at index?obj. If the object does not have a metatable, or if the metatable does not have this field, returns 0 and pushes nothing.


luaL_getmetatable

void luaL_getmetatable (lua_State *L, const char *tname);

Pushes onto the stack the metatable associated with name?tname?in the registry (see?luaL_newmetatable).


luaL_gsub

const char *luaL_gsub (lua_State *L,const char *s,const char *p,const char *r);

Creates a copy of string?s?by replacing any occurrence of the string?p?with the string?r. Pushes the resulting string on the stack and returns it.


luaL_loadbuffer

int luaL_loadbuffer (lua_State *L,const char *buff,size_t sz,const char *name);

Loads a buffer as a Lua chunk. This function uses?lua_load?to load the chunk in the buffer pointed to by?buff?with size?sz.

This function returns the same results as?lua_load.?name?is the chunk name, used for debug information and error messages.


luaL_loadfile

int luaL_loadfile (lua_State *L, const char *filename);

Loads a file as a Lua chunk. This function uses?lua_load?to load the chunk in the file named?filename. If?filename?is?NULL, then it loads from the standard input. The first line in the file is ignored if it starts with a?#.

This function returns the same results as?lua_load, but it has an extra error code?LUA_ERRFILE?if it cannot open/read the file.

As?lua_load, this function only loads the chunk; it does not run it.


luaL_loadstring

int luaL_loadstring (lua_State *L, const char *s);

Loads a string as a Lua chunk. This function uses?lua_load?to load the chunk in the zero-terminated string?s.

This function returns the same results as?lua_load.

Also as?lua_load, this function only loads the chunk; it does not run it.


luaL_newmetatable

int luaL_newmetatable (lua_State *L, const char *tname);

If the registry already has the key?tname, returns 0. Otherwise, creates a new table to be used as a metatable for userdata, adds it to the registry with key?tname, and returns 1.

In both cases pushes onto the stack the final value associated with?tname?in the registry.


luaL_newstate

lua_State *luaL_newstate (void);

Creates a new Lua state. It calls?lua_newstate?with an allocator based on the standard?C?realloc?function and then sets a panic function (seelua_atpanic) that prints an error message to the standard error output in case of fatal errors.

Returns the new state, or?NULL?if there is a memory allocation error.


luaL_openlibs

void luaL_openlibs (lua_State *L);

Opens all standard Lua libraries into the given state.


luaL_optint

int luaL_optint (lua_State *L, int narg, int d);

If the function argument?narg?is a number, returns this number cast to an?int. If this argument is absent or is?nil, returns?d. Otherwise, raises an error.


luaL_optinteger

lua_Integer luaL_optinteger (lua_State *L,int narg,lua_Integer d);

If the function argument?narg?is a number, returns this number cast to a?lua_Integer. If this argument is absent or is?nil, returns?d. Otherwise, raises an error.


luaL_optlong

long luaL_optlong (lua_State *L, int narg, long d);

If the function argument?narg?is a number, returns this number cast to a?long. If this argument is absent or is?nil, returns?d. Otherwise, raises an error.


luaL_optlstring

const char *luaL_optlstring (lua_State *L,int narg,const char *d,size_t *l);

If the function argument?narg?is a string, returns this string. If this argument is absent or is?nil, returns?d. Otherwise, raises an error.

If?l?is not?NULL, fills the position?*l?with the results's length.


luaL_optnumber

lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number d);

If the function argument?narg?is a number, returns this number. If this argument is absent or is?nil, returns?d. Otherwise, raises an error.


luaL_optstring

const char *luaL_optstring (lua_State *L,int narg,const char *d);

If the function argument?narg?is a string, returns this string. If this argument is absent or is?nil, returns?d. Otherwise, raises an error.


luaL_prepbuffer

char *luaL_prepbuffer (luaL_Buffer *B);

Returns an address to a space of size?LUAL_BUFFERSIZE?where you can copy a string to be added to buffer?B?(see?luaL_Buffer). After copying the string into this space you must call?luaL_addsize?with the size of the string to actually add it to the buffer.


luaL_pushresult

void luaL_pushresult (luaL_Buffer *B);

Finishes the use of buffer?B?leaving the final string on the top of the stack.


luaL_ref

int luaL_ref (lua_State *L, int t);

Creates and returns a?reference, in the table at index?t, for the object at the top of the stack (and pops the object).

A reference is a unique integer key. As long as you do not manually add integer keys into table?t,?luaL_ref?ensures the uniqueness of the key it returns. You can retrieve an object referred by reference?r?by calling?lua_rawgeti(L, t, r). Function?luaL_unref?frees a reference and its associated object.

If the object at the top of the stack is?nil,?luaL_ref?returns the constant?LUA_REFNIL. The constant?LUA_NOREF?is guaranteed to be different from any reference returned by?luaL_ref.


luaL_Reg

typedef struct luaL_Reg {const char *name;lua_CFunction func; } luaL_Reg;

Type for arrays of functions to be registered by?luaL_register.?name?is the function name and?func?is a pointer to the function. Any array of?luaL_Regmust end with an sentinel entry in which both?name?and?func?are?NULL.


luaL_register

void luaL_register (lua_State *L,const char *libname,const luaL_Reg *l);

Opens a library.

When called with?libname?equal to?NULL, it simply registers all functions in the list?l?(see?luaL_Reg) into the table on the top of the stack.

When called with a non-null?libname,?luaL_register?creates a new table?t, sets it as the value of the global variable?libname, sets it as the value ofpackage.loaded[libname], and registers on it all functions in the list?l. If there is a table in?package.loaded[libname]?or in variable?libname, reuses this table instead of creating a new one.

In any case the function leaves the table on the top of the stack.


luaL_typename

const char *luaL_typename (lua_State *L, int idx);

Returns the name of the type of the value at index?idx.


luaL_typerror

int luaL_typerror (lua_State *L, int narg, const char *tname);

Generates an error with a message like the following:

location: bad argument narg to 'func' (tname expected, got rt)

where?location?is produced by?luaL_where,?func?is the name of the current function, and?rt?is the type name of the actual argument.


luaL_unref

void luaL_unref (lua_State *L, int t, int ref);

Releases reference?ref?from the table at index?t?(see?luaL_ref). The entry is removed from the table, so that the referred object can be collected. The reference?ref?is also freed to be used again.

If?ref?is?LUA_NOREF?or?LUA_REFNIL,?luaL_unref?does nothing.


luaL_where

void luaL_where (lua_State *L, int lvl);

Pushes onto the stack a string identifying the current position of the control at level?lvl?in the call stack. Typically this string has the following format:

chunkname:currentline:

Level?0 is the running function, level?1 is the function that called the running function, etc.

This function is used to build a prefix for error messages.

5 -?Standard Libraries

The standard Lua libraries provide useful functions that are implemented directly through the C?API. Some of these functions provide essential services to the language (e.g.,?type?and?getmetatable); others provide access to "outside" services (e.g., I/O); and others could be implemented in Lua itself, but are quite useful or have critical performance requirements that deserve an implementation in C (e.g.,?sort).

All libraries are implemented through the official C?API and are provided as separate C?modules. Currently, Lua has the following standard libraries:

  • basic library;
  • package library;
  • string manipulation;
  • table manipulation;
  • mathematical functions (sin, log, etc.);
  • input and output;
  • operating system facilities;
  • debug facilities.

Except for the basic and package libraries, each library provides all its functions as fields of a global table or as methods of its objects.

To have access to these libraries, the C?host program should call the?luaL_openlibs?function, which opens all standard libraries. Alternatively, it can open them individually by calling?luaopen_base?(for the basic library),?luaopen_package?(for the package library),?luaopen_string?(for the string library),?luaopen_table?(for the table library),?luaopen_math?(for the mathematical library),?luaopen_io?(for the I/O and the Operating System libraries), and?luaopen_debug?(for the debug library). These functions are declared in?lualib.h?and should not be called directly: you must call them like any other Lua C?function, e.g., by using?lua_call.

5.1 -?Basic Functions

The basic library provides some core functions to Lua. If you do not include this library in your application, you should check carefully whether you need to provide implementations for some of its facilities.


assert (v [, message])

Issues an error when the value of its argument? v ?is false (i.e.,? nil ?or? false ); otherwise, returns all its arguments.? message ?is an error message; when absent, it defaults to "assertion failed!"


collectgarbage (opt [, arg])

This function is a generic interface to the garbage collector. It performs different functions according to its first argument,?opt:

  • "stop":?stops the garbage collector.
  • "restart":?restarts the garbage collector.
  • "collect":?performs a full garbage-collection cycle.
  • "count":?returns the total memory in use by Lua (in Kbytes).
  • "step":?performs a garbage-collection step. The step "size" is controlled by?arg?(larger values mean more steps) in a non-specified way. If you want to control the step size you must experimentally tune the value of?arg. Returns?true?if the step finished a collection cycle.
  • "setpause":?sets?arg/100 as the new value for the?pause?of the collector (see?§2.10).
  • "setstepmul":?sets?arg/100 as the new value for the?step multiplier?of the collector (see?§2.10).


dofile (filename)

Opens the named file and executes its contents as a Lua chunk. When called without arguments,? dofile ?executes the contents of the standard input ( stdin ). Returns all values returned by the chunk. In case of errors,? dofile ?propagates the error to its caller (that is,? dofile ?does not run in protected mode).


error (message [, level])

Terminates the last protected function called and returns? message ?as the error message. Function? error ?never returns.

Usually,?error?adds some information about the error position at the beginning of the message. The?level?argument specifies how to get the error position. With level?1 (the default), the error position is where the?error?function was called. Level?2 points the error to where the function that called?error?was called; and so on. Passing a level?0 avoids the addition of error position information to the message.


_G

A global variable (not a function) that holds the global environment (that is,? _G._G = _G ). Lua itself does not use this variable; changing its value does not affect any environment, nor vice-versa. (Use? setfenv ?to change environments.)


getfenv (f)

Returns the current environment in use by the function.? f ?can be a Lua function or a number that specifies the function at that stack level: Level?1 is the function calling? getfenv . If the given function is not a Lua function, or if? f ?is 0,? getfenv ?returns the global environment. The default for? f ?is 1.


getmetatable (object)

If?object?does not have a metatable, returns?nil. Otherwise, if the object's metatable has a?"__metatable"?field, returns the associated value. Otherwise, returns the metatable of the given object.


ipairs (t)

Returns three values: an iterator function, the table?t, and 0, so that the construction

for i,v in ipairs(t) do body end

will iterate over the pairs (1,t[1]), (2,t[2]), ···, up to the first integer key absent from the table.


load (func [, chunkname])

Loads a chunk using function?func?to get its pieces. Each call to?func?must return a string that concatenates with previous results. A return ofnil?(or no value) signals the end of the chunk.

If there are no errors, returns the compiled chunk as a function; otherwise, returns?nil?plus the error message. The environment of the returned function is the global environment.

chunkname?is used as the chunk name for error messages and debug information.


loadfile ([filename])

Similar to?load, but gets the chunk from file?filename?or from the standard input, if no file name is given.


loadstring (string [, chunkname])

Similar to?load, but gets the chunk from the given string.

To load and run a given string, use the idiom

assert(loadstring(s))()


next (table [, index])

Allows a program to traverse all fields of a table. Its first argument is a table and its second argument is an index in this table.?next?returns the next index of the table and its associated value. When called with?nil?as its second argument,?next?returns an initial index and its associated value. When called with the last index, or with?nil?in an empty table,?next?returns?nil. If the second argument is absent, then it is interpreted as?nil. In particular, you can use?next(t)?to check whether a table is empty.

The order in which the indices are enumerated is not specified,?even for numeric indices. (To traverse a table in numeric order, use a numericalfor?or the?ipairs?function.)

The behavior of?next?is?undefined?if, during the traversal, you assign any value to a non-existent field in the table. You may however modify existing fields. In particular, you may clear existing fields.


pairs (t)

Returns three values: the?next?function, the table?t, and?nil, so that the construction

for k,v in pairs(t) do body end

will iterate over all key–value pairs of table?t.

See function?next?for the caveats of modifying the table during its traversal.


pcall (f, arg1, ···)

Calls function?f?with the given arguments in?protected mode. This means that any error inside?f?is not propagated; instead,?pcall?catches the error and returns a status code. Its first result is the status code (a boolean), which is true if the call succeeds without errors. In such case,pcall?also returns all results from the call, after this first result. In case of any error,?pcall?returns?false?plus the error message.


print (···)

Receives any number of arguments, and prints their values to? stdout , using the? tostring ?function to convert them to strings.? print ?is not intended for formatted output, but only as a quick way to show a value, typically for debugging. For formatted output, use? string.format .


rawequal (v1, v2)

Checks whether? v1 ?is equal to? v2 , without invoking any metamethod. Returns a boolean.


rawget (table, index)

Gets the real value of? table[index] , without invoking any metamethod.? table ?must be a table;? index ?may be any value.


rawset (table, index, value)

Sets the real value of? table[index] ?to? value , without invoking any metamethod.? table ?must be a table,? index ?any value different from? nil , and? value ?any Lua value.

This function returns?table.


select (index, ···)

If?index?is a number, returns all arguments after argument number?index. Otherwise,?index?must be the string?"#", and?select?returns the total number of extra arguments it received.


setfenv (f, table)

Sets the environment to be used by the given function.?f?can be a Lua function or a number that specifies the function at that stack level: Level?1 is the function calling?setfenv.?setfenv?returns the given function.

As a special case, when?f?is 0?setfenv?changes the environment of the running thread. In this case,?setfenv?returns no values.


setmetatable (table, metatable)

Sets the metatable for the given table. (You cannot change the metatable of other types from Lua, only from?C.) If?metatable?is?nil, removes the metatable of the given table. If the original metatable has a?"__metatable"?field, raises an error.

This function returns?table.


tonumber (e [, base])

Tries to convert its argument to a number. If the argument is already a number or a string convertible to a number, then? tonumber ?returns this number; otherwise, it returns? nil .

An optional argument specifies the base to interpret the numeral. The base may be any integer between 2 and 36, inclusive. In bases above?10, the letter 'A' (in either upper or lower case) represents?10, 'B' represents?11, and so forth, with 'Z' representing 35. In base 10 (the default), the number may have a decimal part, as well as an optional exponent part (see?§2.1). In other bases, only unsigned integers are accepted.


tostring (e)

Receives an argument of any type and converts it to a string in a reasonable format. For complete control of how numbers are converted, use string.format .

If the metatable of?e?has a?"__tostring"?field, then?tostring?calls the corresponding value with?e?as argument, and uses the result of the call as its result.


type (v)

Returns the type of its only argument, coded as a string. The possible results of this function are " nil " (a string, not the value? nil ), " number ", " string ", " boolean ", " table ", " function ", " thread ", and " userdata ".


unpack (list [, i [, j]])

Returns the elements from the given table. This function is equivalent to return list[i], list[i+1], ···, list[j]

except that the above code can be written only for a fixed number of elements. By default,?i?is?1 and?j?is the length of the list, as defined by the length operator (see?§2.5.5).


_VERSION

A global variable (not a function) that holds a string containing the current interpreter version. The current contents of this variable is " Lua 5.1 ".


xpcall (f, err)

This function is similar to?pcall, except that you can set a new error handler.

xpcall?calls function?f?in protected mode, using?err?as the error handler. Any error inside?f?is not propagated; instead,?xpcall?catches the error, calls the?err?function with the original error object, and returns a status code. Its first result is the status code (a boolean), which is true if the call succeeds without errors. In this case,?xpcall?also returns all results from the call, after this first result. In case of any error,?xpcallreturns?false?plus the result from?err.

5.2 -?Coroutine Manipulation

The operations related to coroutines comprise a sub-library of the basic library and come inside the table?coroutine. See?§2.11?for a general description of coroutines.


coroutine.create (f)

Creates a new coroutine, with body?f.?f?must be a Lua function. Returns this new coroutine, an object with type?"thread".


coroutine.resume (co [, val1, ···])

Starts or continues the execution of coroutine?co. The first time you resume a coroutine, it starts running its body. The values?val1, ··· are passed as the arguments to the body function. If the coroutine has yielded,?resume?restarts it; the values?val1, ··· are passed as the results from the yield.

If the coroutine runs without any errors,?resume?returns?true?plus any values passed to?yield?(if the coroutine yields) or any values returned by the body function (if the coroutine terminates). If there is any error,?resume?returns?false?plus the error message.


coroutine.running ()

Returns the running coroutine, or?nil?when called by the main thread.


coroutine.status (co)

Returns the status of coroutine?co, as a string:?"running", if the coroutine is running (that is, it called?status);?"suspended", if the coroutine is suspended in a call to?yield, or if it has not started running yet;?"normal"?if the coroutine is active but not running (that is, it has resumed another coroutine); and?"dead"?if the coroutine has finished its body function, or if it has stopped with an error.


coroutine.wrap (f)

Creates a new coroutine, with body?f.?f?must be a Lua function. Returns a function that resumes the coroutine each time it is called. Any arguments passed to the function behave as the extra arguments to?resume. Returns the same values returned by?resume, except the first boolean. In case of error, propagates the error.


coroutine.yield (···)

Suspends the execution of the calling coroutine. The coroutine cannot be running a C?function, a metamethod, or an iterator. Any arguments toyield?are passed as extra results to?resume.

5.3 -?Modules

The package library provides basic facilities for loading and building modules in Lua. It exports two of its functions directly in the global environment:?require?and?module. Everything else is exported in a table?package.


module (name [, ···])

Creates a module. If there is a table in?package.loaded[name], this table is the module. Otherwise, if there is a global table?t?with the given name, this table is the module. Otherwise creates a new table?t?and sets it as the value of the global?name?and the value of?package.loaded[name]. This function also initializes?t._NAME?with the given name,?t._M?with the module (t?itself), and?t._PACKAGE?with the package name (the full module name minus last component; see below). Finally,?module?sets?t?as the new environment of the current function and the new value of?package.loaded[name], so that?require?returns?t.

If?name?is a compound name (that is, one with components separated by dots),?module?creates (or reuses, if they already exist) tables for each component. For instance, if?name?is?a.b.c, then?module?stores the module table in field?c?of field?b?of global?a.

This function may receive optional?options?after the module name, where each option is a function to be applied over the module.


require (modname)

Loads the given module. The function starts by looking into the?package.loaded?table to determine whether?modname?is already loaded. If it is, thenrequire?returns the value stored at?package.loaded[modname]. Otherwise, it tries to find a?loader?for the module.

To find a loader, first?require?queries?package.preload[modname]. If it has a value, this value (which should be a function) is the loader. Otherwiserequire?searches for a Lua loader using the path stored in?package.path. If that also fails, it searches for a C?loader using the path stored inpackage.cpath. If that also fails, it tries an?all-in-one?loader (see below).

When loading a C?library,?require?first uses a dynamic link facility to link the application with the library. Then it tries to find a C?function inside this library to be used as the loader. The name of this C?function is the string "luaopen_" concatenated with a copy of the module name where each dot is replaced by an underscore. Moreover, if the module name has a hyphen, its prefix up to (and including) the first hyphen is removed. For instance, if the module name is?a.v1-b.c, the function name will be?luaopen_b_c.

If?require?finds neither a Lua library nor a C?library for a module, it calls the?all-in-one loader. This loader searches the C?path for a library for the root name of the given module. For instance, when requiring?a.b.c, it will search for a C?library for?a. If found, it looks into it for an open function for the submodule; in our example, that would be?luaopen_a_b_c. With this facility, a package can pack several C?submodules into one single library, with each submodule keeping its original open function.

Once a loader is found,?require?calls the loader with a single argument,?modname. If the loader returns any value,?require?assigns the returned value to?package.loaded[modname]. If the loader returns no value and has not assigned any value to?package.loaded[modname], then?require?assigns?true?to this entry. In any case,?require?returns the final value of?package.loaded[modname].

If there is any error loading or running the module, or if it cannot find any loader for the module, then?require?signals an error.


package.cpath

The path used by?require?to search for a C?loader.

Lua initializes the C?path?package.cpath?in the same way it initializes the Lua path?package.path, using the environment variable?LUA_CPATH?(plus another default path defined in?luaconf.h).


package.loaded

A table used by?require?to control which modules are already loaded. When you require a module?modname?and?package.loaded[modname]?is not false,?requiresimply returns the value stored there.


package.loadlib (libname, funcname)

Dynamically links the host program with the C?library?libname. Inside this library, looks for a function?funcname?and returns this function as a C?function. (So,?funcname?must follow the protocol (see?lua_CFunction)).

This is a low-level function. It completely bypasses the package and module system. Unlike?require, it does not perform any path searching and does not automatically adds extensions.?libname?must be the complete file name of the C?library, including if necessary a path and extension.?funcnamemust be the exact name exported by the C?library (which may depend on the C?compiler and linker used).

This function is not supported by ANSI C. As such, it is only available on some platforms (Windows, Linux, Mac OS X, Solaris, BSD, plus other Unix systems that support the?dlfcn?standard).


package.path

The path used by?require?to search for a Lua loader.

At start-up, Lua initializes this variable with the value of the environment variable?LUA_PATH?or with a default path defined in?luaconf.h, if the environment variable is not defined. Any ";;" in the value of the environment variable is replaced by the default path.

A path is a sequence of?templates?separated by semicolons. For each template,?require?will change each interrogation mark in the template byfilename, which is?modname?with each dot replaced by a "directory separator" (such as "/" in Unix); then it will try to load the resulting file name. So, for instance, if the Lua path is

"./?.lua;./?.lc;/usr/local/?/init.lua"

the search for a Lua loader for module?foo?will try to load the files?./foo.lua,?./foo.lc, and?/usr/local/foo/init.lua, in that order.


package.preload

A table to store loaders for specific modules (see?require).


package.seeall (module)

Sets a metatable for?module?with its?__index?field referring to the global environment, so that this module inherits values from the global environment. To be used as an option to function?module.

5.4 -?String Manipulation

This library provides generic functions for string manipulation, such as finding and extracting substrings, and pattern matching. When indexing a string in Lua, the first character is at position?1 (not at?0, as in C). Indices are allowed to be negative and are interpreted as indexing backwards, from the end of the string. Thus, the last character is at position -1, and so on.

The string library provides all its functions inside the table?string. It also sets a metatable for strings where the?__index?field points to thestring?table. Therefore, you can use the string functions in object-oriented style. For instance,?string.byte(s, i)?can be written as?s:byte(i).


string.byte (s [, i [, j]])

Returns the internal numerical codes of the characters? s[i] ,? s[i+1] , ···,? s[j] . The default value for? i ?is?1; the default value for? j ?is? i .

Note that numerical codes are not necessarily portable across platforms.


string.char (···)

Receives zero or more integers. Returns a string with length equal to the number of arguments, in which each character has the internal numerical code equal to its corresponding argument.

Note that numerical codes are not necessarily portable across platforms.


string.dump (function)

Returns a string containing a binary representation of the given function, so that a later?loadstring?on this string returns a copy of the function.function?must be a Lua function without upvalues.


string.find (s, pattern [, init [, plain]])

Looks for the first match of? pattern ?in the string? s . If it finds a match, then? find ?returns the indices of? s ?where this occurrence starts and ends; otherwise, it returns? nil . A third, optional numerical argument? init ?specifies where to start the search; its default value is?1 and may be negative. A value of? true ?as a fourth, optional argument? plain ?turns off the pattern matching facilities, so the function does a plain "find substring" operation, with no characters in? pattern ?being considered "magic". Note that if? plain ?is given, then? init ?must be given as well.

If the pattern has captures, then in a successful match the captured values are also returned, after the two indices.


string.format (formatstring, ···)

Returns a formatted version of its variable number of arguments following the description given in its first argument (which must be a string). The format string follows the same rules as the? printf ?family of standard C?functions. The only differences are that the options/modifiers? * ,? l ,? L , n ,? p , and? h ?are not supported and that there is an extra option,? q . The? q ?option formats a string in a form suitable to be safely read back by the Lua interpreter: the string is written between double quotes, and all double quotes, newlines, embedded zeros, and backslashes in the string are correctly escaped when written. For instance, the call string.format('%q', 'a string with "quotes" and \n new line')

will produce the string:

"a string with \"quotes\" and \new line"

The options?c,?d,?E,?e,?f,?g,?G,?i,?o,?u,?X, and?x?all expect a number as argument, whereas?q?and?s?expect a string.

This function does not accept string values containing embedded zeros.


string.gmatch (s, pattern)

Returns an iterator function that, each time it is called, returns the next captures from? pattern ?over string? s .

If?pattern?specifies no captures, then the whole match is produced in each call.

As an example, the following loop

s = "hello world from Lua"for w in string.gmatch(s, "%a+") doprint(w)end

will iterate over all the words from string?s, printing one per line. The next example collects all pairs?key=value?from the given string into a table:

t = {}s = "from=world, to=Lua"for k, v in string.gmatch(s, "(%w+)=(%w+)") dot[k] = vend


string.gsub (s, pattern, repl [, n])

Returns a copy of? s ?in which all occurrences of the? pattern ?have been replaced by a replacement string specified by? repl , which may be a string, a table, or a function.? gsub ?also returns, as its second value, the total number of substitutions made.

If?repl?is a string, then its value is used for replacement. The character?%?works as an escape character: any sequence in?repl?of the form?%n, with?n?between 1 and 9, stands for the value of the?n-th captured substring (see below). The sequence?%0?stands for the whole match. The sequence%%?stands for a single?%.

If?repl?is a table, then the table is queried for every match, using the first capture as the key; if the pattern specifies no captures, then the whole match is used as the key.

If?repl?is a function, then this function is called every time a match occurs, with all captured substrings passed as arguments, in order; if the pattern specifies no captures, then the whole match is passed as a sole argument.

If the value returned by the table query or by the function call is a string or a number, then it is used as the replacement string; otherwise, if it is?false?or?nil, then there is no replacement (that is, the original match is kept in the string).

The optional last parameter?n?limits the maximum number of substitutions to occur. For instance, when?n?is 1 only the first occurrence of?pattern?is replaced.

Here are some examples:

x = string.gsub("hello world", "(%w+)", "%1 %1")--> x="hello hello world world"x = string.gsub("hello world", "%w+", "%0 %0", 1)--> x="hello hello world"x = string.gsub("hello world from Lua", "(%w+)%s*(%w+)", "%2 %1")--> x="world hello Lua from"x = string.gsub("home = $HOME, user = $USER", "%$(%w+)", os.getenv)--> x="home = /home/roberto, user = roberto"x = string.gsub("4+5 = $return 4+5$", "%$(.-)%$", function (s)return loadstring(s)()end)--> x="4+5 = 9"local t = {name="lua", version="5.1"}x = string.gsub("$name%-$version.tar.gz", "%$(%w+)", t)--> x="lua-5.1.tar.gz"


string.len (s)

Receives a string and returns its length. The empty string? "" ?has length 0. Embedded zeros are counted, so? "a\000bc\000" ?has length 5.


string.lower (s)

Receives a string and returns a copy of this string with all uppercase letters changed to lowercase. All other characters are left unchanged. The definition of what an uppercase letter is depends on the current locale.


string.match (s, pattern [, init])

Looks for the first? match ?of? pattern ?in the string? s . If it finds one, then? match ?returns the captures from the pattern; otherwise it returns? nil . If? pattern ?specifies no captures, then the whole match is returned. A third, optional numerical argument? init ?specifies where to start the search; its default value is?1 and may be negative.


string.rep (s, n)

Returns a string that is the concatenation of? n ?copies of the string? s .


string.reverse (s)

Returns a string that is the string? s ?reversed.


string.sub (s, i [, j])

Returns the substring of? s ?that starts at? i ?and continues until? j ;? i ?and? j ?may be negative. If? j ?is absent, then it is assumed to be equal to -1 (which is the same as the string length). In particular, the call? string.sub(s,1,j) ?returns a prefix of? s ?with length? j , and? string.sub(s, -i) ?returns a suffix of? s ?with length? i .


string.upper (s)

Receives a string and returns a copy of this string with all lowercase letters changed to uppercase. All other characters are left unchanged. The definition of what a lowercase letter is depends on the current locale.

5.4.1 -?Patterns

Character Class:

A?character class?is used to represent a set of characters. The following combinations are allowed in describing a character class:

  • x:?(where?x?is not one of the?magic characters?^$()%.[]*+-?) represents the character?x?itself.
  • .:?(a dot) represents all characters.
  • %a:?represents all letters.
  • %c:?represents all control characters.
  • %d:?represents all digits.
  • %l:?represents all lowercase letters.
  • %p:?represents all punctuation characters.
  • %s:?represents all space characters.
  • %u:?represents all uppercase letters.
  • %w:?represents all alphanumeric characters.
  • %x:?represents all hexadecimal digits.
  • %z:?represents the character with representation 0.
  • %x:?(where?x?is any non-alphanumeric character) represents the character?x. This is the standard way to escape the magic characters. Any punctuation character (even the non magic) can be preceded by a '%' when used to represent itself in a pattern.
  • [set]:?represents the class which is the union of all characters in?set. A range of characters may be specified by separating the end characters of the range with a '-'. All classes?%x?described above may also be used as components in?set. All other characters in?setrepresent themselves. For example,?[%w_]?(or?[_%w]) represents all alphanumeric characters plus the underscore,?[0-7]?represents the octal digits, and?[0-7%l%-]?represents the octal digits plus the lowercase letters plus the '-' character.

    The interaction between ranges and classes is not defined. Therefore, patterns like?[%a-z]?or?[a-%%]?have no meaning.

  • [^set]:?represents the complement of?set, where?set?is interpreted as above.

For all classes represented by single letters (%a,?%c, etc.), the corresponding uppercase letter represents the complement of the class. For instance,?%S?represents all non-space characters.

The definitions of letter, space, and other character groups depend on the current locale. In particular, the class?[a-z]?may not be equivalent to%l.

Pattern Item:

A?pattern item?may be

  • a single character class, which matches any single character in the class;
  • a single character class followed by '*', which matches 0 or more repetitions of characters in the class. These repetition items will always match the longest possible sequence;
  • a single character class followed by '+', which matches 1 or more repetitions of characters in the class. These repetition items will always match the longest possible sequence;
  • a single character class followed by '-', which also matches 0 or more repetitions of characters in the class. Unlike '*', these repetition items will always match the?shortest?possible sequence;
  • a single character class followed by '?', which matches 0 or 1 occurrence of a character in the class;
  • %n, for?n?between 1 and 9; such item matches a substring equal to the?n-th captured string (see below);
  • %bxy, where?x?and?y?are two distinct characters; such item matches strings that start with?x, end with?y, and where the?x?and?y?arebalanced. This means that, if one reads the string from left to right, counting?+1?for an?x?and?-1?for a?y, the ending?y?is the first?y?where the count reaches 0. For instance, the item?%b()?matches expressions with balanced parentheses.

Pattern:

A?pattern?is a sequence of pattern items. A '^' at the beginning of a pattern anchors the match at the beginning of the subject string. A '$' at the end of a pattern anchors the match at the end of the subject string. At other positions, '^' and '$' have no special meaning and represent themselves.

Captures:

A pattern may contain sub-patterns enclosed in parentheses; they describe?captures. When a match succeeds, the substrings of the subject string that match captures are stored (captured) for future use. Captures are numbered according to their left parentheses. For instance, in the pattern"(a*(.)%w(%s*))", the part of the string matching?"a*(.)%w(%s*)"?is stored as the first capture (and therefore has number?1); the character matching "." is captured with number?2, and the part matching "%s*" has number?3.

As a special case, the empty capture?()?captures the current string position (a number). For instance, if we apply the pattern?"()aa()"?on the string?"flaaap", there will be two captures: 3?and?5.

A pattern cannot contain embedded zeros. Use?%z?instead.

5.5 -?Table Manipulation

This library provides generic functions for table manipulation. It provides all its functions inside the table?table.

Most functions in the table library assume that the table represents an array or a list. For these functions, when we talk about the "length" of a table we mean the result of the length operator.


table.concat (table [, sep [, i [, j]]])

Given an array where all elements are strings or numbers, returns? table[i]..sep..table[i+1] ··· sep..table[j] . The default value for? sep ?is the empty string, the default for? i ?is 1, and the default for? j ?is the length of the table. If? i ?is greater than? j , returns the empty string.


table.insert (table, [pos,] value)

Inserts element?value?at position?pos?in?table, shifting up other elements to open space, if necessary. The default value for?pos?is?n+1, where?n?is the length of the table (see?§2.5.5), so that a call?table.insert(t,x)?inserts?x?at the end of table?t.


table.maxn (table)

Returns the largest positive numerical index of the given table, or zero if the table has no positive numerical indices. (To do its job this function does a linear traversal of the whole table.)


table.remove (table [, pos])

Removes from?table?the element at position?pos, shifting down other elements to close the space, if necessary. Returns the value of the removed element. The default value for?pos?is?n, where?n?is the length of the table, so that a call?table.remove(t)?removes the last element of table?t.


table.sort (table [, comp])

Sorts table elements in a given order,? in-place , from? table[1] ?to? table[n] , where? n ?is the length of the table. If? comp ?is given, then it must be a function that receives two table elements, and returns true when the first is less than the second (so that? not comp(a[i+1],a[i]) ?will be true after the sort). If? comp ?is not given, then the standard Lua operator? < ?is used instead.

The sort algorithm is not stable; that is, elements considered equal by the given order may have their relative positions changed by the sort.

5.6 -?Mathematical Functions

This library is an interface to the standard C?math library. It provides all its functions inside the table?math.


math.abs (x)

Returns the absolute value of?x.


math.acos (x)

Returns the arc cosine of?x?(in radians).


math.asin (x)

Returns the arc sine of?x?(in radians).


math.atan (x)

Returns the arc tangent of?x?(in radians).


math.atan2 (x, y)

Returns the arc tangent of?x/y?(in radians), but uses the signs of both parameters to find the quadrant of the result. (It also handles correctly the case of?y?being zero.)


math.ceil (x)

Returns the smallest integer larger than or equal to?x.


math.cos (x)

Returns the cosine of?x?(assumed to be in radians).


math.cosh (x)

Returns the hyperbolic cosine of?x.


math.deg (x)

Returns the angle?x?(given in radians) in degrees.


math.exp (x)

Returns the the value?ex.


math.floor (x)

Returns the largest integer smaller than or equal to?x.


math.fmod (x, y)

Returns the remainder of the division of?x?by?y.


math.frexp (x)

Returns?m?and?e?such that?x = m2e,?e?is an integer and the absolute value of?m?is in the range?[0.5, 1)?(or zero when?x?is zero).


math.huge

The value?HUGE_VAL, a value larger than or equal to any other numerical value.


math.ldexp (m, e)

Returns?m2e?(e?should be an integer).


math.log (x)

Returns the natural logarithm of?x.


math.log10 (x)

Returns the base-10 logarithm of?x.


math.max (x, ···)

Returns the maximum value among its arguments.


math.min (x, ···)

Returns the minimum value among its arguments.


math.modf (x)

Returns two numbers, the integral part of?x?and the fractional part of?x.


math.pi

The value of?pi.


math.pow (x, y)

Returns?xy. (You can also use the expression?x^y?to compute this value.)


math.rad (x)

Returns the angle?x?(given in degrees) in radians.


math.random ([m [, n]])

This function is an interface to the simple pseudo-random generator function?rand?provided by ANSI?C. (No guarantees can be given for its statistical properties.)

When called without arguments, returns a pseudo-random real number in the range?[0,1). When called with a number?m,?math.random?returns a pseudo-random integer in the range?[1, m]. When called with two numbers?m?and?n,?math.random?returns a pseudo-random integer in the range?[m, n].


math.randomseed (x)

Sets?x?as the "seed" for the pseudo-random generator: equal seeds produce equal sequences of numbers.


math.sin (x)

Returns the sine of?x?(assumed to be in radians).


math.sinh (x)

Returns the hyperbolic sine of?x.


math.sqrt (x)

Returns the square root of?x. (You can also use the expression?x^0.5?to compute this value.)


math.tan (x)

Returns the tangent of?x?(assumed to be in radians).


math.tanh (x)

Returns the hyperbolic tangent of?x.

5.7 -?Input and Output Facilities

The I/O library provides two different styles for file manipulation. The first one uses implicit file descriptors; that is, there are operations to set a default input file and a default output file, and all input/output operations are over these default files. The second style uses explicit file descriptors.

When using implicit file descriptors, all operations are supplied by table?io. When using explicit file descriptors, the operation?io.open?returns a file descriptor and then all operations are supplied as methods of the file descriptor.

The table?io?also provides three predefined file descriptors with their usual meanings from C:?io.stdin,?io.stdout, and?io.stderr.

Unless otherwise stated, all I/O functions return?nil?on failure (plus an error message as a second result) and some value different from?nil?on success.


io.close ([file])

Equivalent to?file:close(). Without a?file, closes the default output file.


io.flush ()

Equivalent to?file:flush?over the default output file.


io.input ([file])

When called with a file name, it opens the named file (in text mode), and sets its handle as the default input file. When called with a file handle, it simply sets this file handle as the default input file. When called without parameters, it returns the current default input file.

In case of errors this function raises the error, instead of returning an error code.


io.lines ([filename])

Opens the given file name in read mode and returns an iterator function that, each time it is called, returns a new line from the file. Therefore, the construction

for line in io.lines(filename) do body end

will iterate over all lines of the file. When the iterator function detects the end of file, it returns?nil?(to finish the loop) and automatically closes the file.

The call?io.lines()?(with no file name) is equivalent to?io.input():lines(); that is, it iterates over the lines of the default input file. In this case it does not close the file when the loop ends.


io.open (filename [, mode])

This function opens a file, in the mode specified in the string?mode. It returns a new file handle, or, in case of errors,?nil?plus an error message.

The?mode?string can be any of the following:

  • "r":?read mode (the default);
  • "w":?write mode;
  • "a":?append mode;
  • "r+":?update mode, all previous data is preserved;
  • "w+":?update mode, all previous data is erased;
  • "a+":?append update mode, previous data is preserved, writing is only allowed at the end of file.

The?mode?string may also have a 'b' at the end, which is needed in some systems to open the file in binary mode. This string is exactly what is used in the standard?C function?fopen.


io.output ([file])

Similar to?io.input, but operates over the default output file.


io.popen (prog [, mode])

Starts program?prog?in a separated process and returns a file handle that you can use to read data from this program (if?mode?is?"r", the default) or to write data to this program (if?mode?is?"w").

This function is system dependent and is not available on all platforms.


io.read (···)

Equivalent to?io.input():read.


io.tmpfile ()

Returns a handle for a temporary file. This file is opened in update mode and it is automatically removed when the program ends.


io.type (obj)

Checks whether?obj?is a valid file handle. Returns the string?"file"?if?obj?is an open file handle,?"closed file"?if?obj?is a closed file handle, ornil?if?obj?is not a file handle.


io.write (···)

Equivalent to?io.output():write.


file:close ()

Closes?file. Note that files are automatically closed when their handles are garbage collected, but that takes an unpredictable amount of time to happen.


file:flush ()

Saves any written data to?file.


file:lines ()

Returns an iterator function that, each time it is called, returns a new line from the file. Therefore, the construction

for line in file:lines() do body end

will iterate over all lines of the file. (Unlike?io.lines, this function does not close the file when the loop ends.)


file:read (···)

Reads the file?file, according to the given formats, which specify what to read. For each format, the function returns a string (or a number) with the characters read, or?nil?if it cannot read data with the specified format. When called without formats, it uses a default format that reads the entire next line (see below).

The available formats are

  • "*n":?reads a number; this is the only format that returns a number instead of a string.
  • "*a":?reads the whole file, starting at the current position. On end of file, it returns the empty string.
  • "*l":?reads the next line (skipping the end of line), returning?nil?on end of file. This is the default format.
  • number:?reads a string with up to this number of characters, returning?nil?on end of file. If number is zero, it reads nothing and returns an empty string, or?nil?on end of file.


file:seek ([whence] [, offset])

Sets and gets the file position, measured from the beginning of the file, to the position given by?offset?plus a base specified by the stringwhence, as follows:

  • "set":?base is position 0 (beginning of the file);
  • "cur":?base is current position;
  • "end":?base is end of file;

In case of success, function?seek?returns the final file position, measured in bytes from the beginning of the file. If this function fails, it returns?nil, plus a string describing the error.

The default value for?whence?is?"cur", and for?offset?is 0. Therefore, the call?file:seek()?returns the current file position, without changing it; the call?file:seek("set")?sets the position to the beginning of the file (and returns 0); and the call?file:seek("end")?sets the position to the end of the file, and returns its size.


file:setvbuf (mode [, size])

Sets the buffering mode for an output file. There are three available modes:

  • "no":?no buffering; the result of any output operation appears immediately.
  • "full":?full buffering; output operation is performed only when the buffer is full (or when you explicitly?flush?the file (see?io.flush)).
  • "line":?line buffering; output is buffered until a newline is output or there is any input from some special files (such as a terminal device).

For the last two cases,?sizes?specifies the size of the buffer, in bytes. The default is an appropriate size.


file:write (···)

Writes the value of each of its arguments to the?file. The arguments must be strings or numbers. To write other values, use?tostring?or?string.formatbefore?write.

5.8 -?Operating System Facilities

This library is implemented through table?os.


os.clock ()

Returns an approximation of the amount in seconds of CPU time used by the program.


os.date ([format [, time]])

Returns a string or a table containing date and time, formatted according to the given string?format.

If the?time?argument is present, this is the time to be formatted (see the?os.time?function for a description of this value). Otherwise,?date?formats the current time.

If?format?starts with '!', then the date is formatted in Coordinated Universal Time. After this optional character, if?format?is the string "*t", then?date?returns a table with the following fields:?year?(four digits),?month?(1--12),?day?(1--31),?hour?(0--23),?min?(0--59),?sec?(0--61),?wday(weekday, Sunday is?1),?yday?(day of the year), and?isdst?(daylight saving flag, a boolean).

If?format?is not "*t", then?date?returns the date as a string, formatted according to the same rules as the C?function?strftime.

When called without arguments,?date?returns a reasonable date and time representation that depends on the host system and on the current locale (that is,?os.date()?is equivalent to?os.date("%c")).


os.difftime (t2, t1)

Returns the number of seconds from time?t1?to time?t2. In POSIX, Windows, and some other systems, this value is exactly?t2-t1.


os.execute ([command])

This function is equivalent to the C?function?system. It passes?command?to be executed by an operating system shell. It returns a status code, which is system-dependent. If?command?is absent, then it returns nonzero if a shell is available and zero otherwise.


os.exit ([code])

Calls the C?function?exit, with an optional?code, to terminate the host program. The default value for?code?is the success code.


os.getenv (varname)

Returns the value of the process environment variable?varname, or?nil?if the variable is not defined.


os.remove (filename)

Deletes the file or directory with the given name. Directories must be empty to be removed. If this function fails, it returns?nil, plus a string describing the error.


os.rename (oldname, newname)

Renames file or directory named?oldname?to?newname. If this function fails, it returns?nil, plus a string describing the error.


os.setlocale (locale [, category])

Sets the current locale of the program.?locale?is a string specifying a locale;?category?is an optional string describing which category to change:"all",?"collate",?"ctype",?"monetary",?"numeric", or?"time"; the default category is?"all". The function returns the name of the new locale, or?nil?if the request cannot be honored.

When called with?nil?as the first argument, this function only returns the name of the current locale for the given category.


os.time ([table])

Returns the current time when called without arguments, or a time representing the date and time specified by the given table. This table must have fields?year,?month, and?day, and may have fields?hour,?min,?sec, and?isdst?(for a description of these fields, see the?os.date?function).

The returned value is a number, whose meaning depends on your system. In POSIX, Windows, and some other systems, this number counts the number of seconds since some given start time (the "epoch"). In other systems, the meaning is not specified, and the number returned by?time?can be used only as an argument to?date?and?difftime.


os.tmpname ()

Returns a string with a file name that can be used for a temporary file. The file must be explicitly opened before its use and explicitly removed when no longer needed.

5.9 -?The Debug Library

This library provides the functionality of the debug interface to Lua programs. You should exert care when using this library. The functions provided here should be used exclusively for debugging and similar tasks, such as profiling. Please resist the temptation to use them as a usual programming tool: they can be very slow. Moreover, several of its functions violate some assumptions about Lua code (e.g., that variables local to a function cannot be accessed from outside or that userdata metatables cannot be changed by Lua code) and therefore can compromise otherwise secure code.

All functions in this library are provided inside the?debug?table. All functions that operate over a thread have an optional first argument which is the thread to operate over. The default is always the current thread.


debug.debug ()

Enters an interactive mode with the user, running each string that the user enters. Using simple commands and other debug facilities, the user can inspect global and local variables, change their values, evaluate expressions, and so on. A line containing only the word?cont?finishes this function, so that the caller continues its execution.

Note that commands for?debug.debug?are not lexically nested within any function, and so have no direct access to local variables.


debug.getfenv (o)

Returns the environment of object? o .


debug.gethook ([thread])

Returns the current hook settings of the thread, as three values: the current hook function, the current hook mask, and the current hook count (as set by the?debug.sethook?function).


debug.getinfo ([thread,] function [, what])

Returns a table with information about a function. You can give the function directly, or you can give a number as the value of?function, which means the function running at level?function?of the call stack of the given thread: level?0 is the current function (getinfo?itself); level?1 is the function that called?getinfo; and so on. If?function?is a number larger than the number of active functions, then?getinfo?returns?nil.

The returned table may contain all the fields returned by?lua_getinfo, with the string?what?describing which fields to fill in. The default for?whatis to get all information available, except the table of valid lines. If present, the option 'f' adds a field named?func?with the function itself. If present, the option 'L' adds a field named?activelines?with the table of valid lines.

For instance, the expression?debug.getinfo(1,"n").name?returns a name of the current function, if a reasonable name can be found, and the expressiondebug.getinfo(print)?returns a table with all available information about the?print?function.


debug.getlocal ([thread,] level, local)

This function returns the name and the value of the local variable with index?local?of the function at level?level?of the stack. (The first parameter or local variable has index?1, and so on, until the last active local variable.) The function returns?nil?if there is no local variable with the given index, and raises an error when called with a?level?out of range. (You can call?debug.getinfo?to check whether the level is valid.)

Variable names starting with '(' (open parentheses) represent internal variables (loop control variables, temporaries, and C?function locals).


debug.getmetatable (object)

Returns the metatable of the given?object?or?nil?if it does not have a metatable.


debug.getregistry ()

Returns the registry table (see?§3.5).


debug.getupvalue (func, up)

This function returns the name and the value of the upvalue with index?up?of the function?func. The function returns?nil?if there is no upvalue with the given index.


debug.setfenv (object, table)

Sets the environment of the given?object?to the given?table. Returns?object.


debug.sethook ([thread,] hook, mask [, count])

Sets the given function as a hook. The string?mask?and the number?count?describe when the hook will be called. The string mask may have the following characters, with the given meaning:

  • "c":?The hook is called every time Lua calls a function;
  • "r":?The hook is called every time Lua returns from a function;
  • "l":?The hook is called every time Lua enters a new line of code.

With a?count?different from zero, the hook is called after every?count?instructions.

When called without arguments,?debug.sethook?turns off the hook.

When the hook is called, its first parameter is a string describing the event that has triggered its call:?"call",?"return"?(or?"tail return"),?"line", and?"count". For line events, the hook also gets the new line number as its second parameter. Inside a hook, you can call?getinfo?with level?2 to get more information about the running function (level?0 is the?getinfo?function, and level?1 is the hook function), unless the event is?"tail return". In this case, Lua is only simulating the return, and a call to?getinfo?will return invalid data.


debug.setlocal ([thread,] level, local, value)

This function assigns the value?value?to the local variable with index?local?of the function at level?level?of the stack. The function returns?nil?if there is no local variable with the given index, and raises an error when called with a?level?out of range. (You can call?getinfo?to check whether the level is valid.) Otherwise, it returns the name of the local variable.


debug.setmetatable (object, table)

Sets the metatable for the given?object?to the given?table?(which can be?nil).


debug.setupvalue (func, up, value)

This function assigns the value?value?to the upvalue with index?up?of the function?func. The function returns?nil?if there is no upvalue with the given index. Otherwise, it returns the name of the upvalue.


debug.traceback ([thread,] [message] [, level])

Returns a string with a traceback of the call stack. An optional?message?string is appended at the beginning of the traceback. An optional?levelnumber tells at which level to start the traceback (default is 1, the function calling?traceback).

6 -?Lua Stand-alone

Although Lua has been designed as an extension language, to be embedded in a host C?program, it is also frequently used as a stand-alone language. An interpreter for Lua as a stand-alone language, called simply?lua, is provided with the standard distribution. The stand-alone interpreter includes all standard libraries, including the debug library. Its usage is:

lua [options] [script [args]]

The options are:

  • -e?stat:?executes string?stat;
  • -l?mod:?"requires"?mod;
  • -i:?enters interactive mode after running?script;
  • -v:?prints version information;
  • --:?stops handling options;
  • -:?executes?stdin?as a file and stops handling options.

After handling its options,?lua?runs the given?script, passing to it the given?args?as string arguments. When called without arguments,?lua?behaves as?lua -v -i?when the standard input (stdin) is a terminal, and as?lua -?otherwise.

Before running any argument, the interpreter checks for an environment variable?LUA_INIT. If its format is?@filename, then?lua?executes the file. Otherwise,?lua?executes the string itself.

All options are handled in order, except?-i. For instance, an invocation like

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

will first set?a?to 1, then print the value of?a?(which is '1'), and finally run the file?script.lua?with no arguments. (Here?$?is the shell prompt. Your prompt may be different.)

Before starting to run the script,?lua?collects all arguments in the command line in a global table called?arg. The script name is stored at index 0, the first argument after the script name goes to index 1, and so on. Any arguments before the script name (that is, the interpreter name plus the options) go to negative indices. For instance, in the call

$ lua -la b.lua t1 t2

the interpreter first runs the file?a.lua, then creates a table

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

and finally runs the file?b.lua. The script is called with?arg[1],?arg[2], ··· as arguments; it can also access these arguments with the vararg expression '...'.

In interactive mode, if you write an incomplete statement, the interpreter waits for its completion by issuing a different prompt.

If the global variable?_PROMPT?contains a string, then its value is used as the prompt. Similarly, if the global variable?_PROMPT2?contains a string, its value is used as the secondary prompt (issued during incomplete statements). Therefore, both prompts can be changed directly on the command line. For instance,

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

(the outer pair of quotes is for the shell, the inner pair is for Lua), or in any Lua programs by assigning to?_PROMPT. Note the use of?-i?to enter interactive mode; otherwise, the program would just end silently right after the assignment to?_PROMPT.

To allow the use of Lua as a script interpreter in Unix systems, the stand-alone interpreter skips the first line of a chunk if it starts with?#. Therefore, Lua scripts can be made into executable programs by using?chmod +x?and the?#!?form, as in

#!/usr/local/bin/lua

(Of course, the location of the Lua interpreter may be different in your machine. If?lua?is in your?PATH, then

#!/usr/bin/env lua

is a more portable solution.)

7 -?Incompatibilities with the Previous Version

Here we list the incompatibilities that you may found when moving a program from Lua?5.0 to Lua?5.1. You can avoid most of the incompatibilities compiling Lua with appropriate options (see file?luaconf.h). However, all these compatibility options will be removed in the next version of Lua.

7.1 -?Changes in the Language

  • The vararg system changed from the pseudo-argument?arg?with a table with the extra arguments to the vararg expression. (See compile-time option?LUA_COMPAT_VARARG?in?luaconf.h.)
  • There was a subtle change in the scope of the implicit variables of the?for?statement and for the?repeat?statement.
  • The long string/long comment syntax ([[string]]) does not allow nesting. You can use the new syntax ([=[string]=]) in these cases. (See compile-time option?LUA_COMPAT_LSTR?in?luaconf.h.)

7.2 -?Changes in the Libraries

  • Function?string.gfind?was renamed?string.gmatch. (See compile-time option?LUA_COMPAT_GFIND?in?luaconf.h.)
  • When?string.gsub?is called with a function as its third argument, whenever this function returns?nil?or?false?the replacement string is the whole match, instead of the empty string.
  • Function?table.setn?was deprecated. Function?table.getn?corresponds to the new length operator (#); use the operator instead of the function. (See compile-time option?LUA_COMPAT_GETN?in?luaconf.h.)
  • Function?loadlib?was renamed?package.loadlib. (See compile-time option?LUA_COMPAT_LOADLIB?in?luaconf.h.)
  • Function?math.mod?was renamed?math.fmod. (See compile-time option?LUA_COMPAT_MOD?in?luaconf.h.)
  • Functions?table.foreach?and?table.foreachi?are deprecated. You can use a for loop with?pairs?or?ipairs?instead.
  • There were substantial changes in function?require?due to the new module system. However, the new behavior is mostly compatible with the old, but?require?gets the path from?package.path?instead of from?LUA_PATH.
  • Function?collectgarbage?has different arguments. Function?gcinfo?is deprecated; use?collectgarbage("count")?instead.

7.3 -?Changes in the API

  • The?luaopen_*?functions (to open libraries) cannot be called directly, like a regular C function. They must be called through Lua, like a Lua function.
  • Function?lua_open?was replaced by?lua_newstate?to allow the user to set a memory-allocation function. You can use?luaL_newstate?from the standard library to create a state with a standard allocation function (based on?realloc).
  • Functions?luaL_getn?and?luaL_setn?(from the auxiliary library) are deprecated. Use?lua_objlen?instead of?luaL_getn?and nothing instead of?luaL_setn.
  • Function?luaL_openlib?was replaced by?luaL_register.
  • Function?luaL_checkudata?now throws an error when the given value is not a userdata of the expected type. (In Lua?5.0 it returned?NULL.)

8 -?The Complete Syntax of Lua

Here is the complete syntax of Lua in extended BNF. (It does not describe operator precedences.)

chunk ::= {stat [`;′]} [laststat [`;′]]block ::= chunkstat ::= varlist1 `=′ explist1 | 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 explist1 do block end | function funcname funcbody | local function Name funcbody | local namelist [`=′ explist1] laststat ::= return [explist1] | breakfuncname ::= Name {`.′ Name} [`:′ Name]varlist1 ::= var {`,′ var}var ::= Name | prefixexp `[′ exp `]′ | prefixexp `.′ Name namelist ::= Name {`,′ Name}explist1 ::= {exp `,′} expexp ::= nil | false | true | Number | String | `...′ | function | prefixexp | tableconstructor | exp binop exp | unop exp prefixexp ::= var | functioncall | `(′ exp `)′functioncall ::= prefixexp args | prefixexp `:′ Name args args ::= `(′ [explist1] `)′ | tableconstructor | String function ::= function funcbodyfuncbody ::= `(′ [parlist1] `)′ block endparlist1 ::= namelist [`,′ `...′] | `...′tableconstructor ::= `{′ [fieldlist] `}′fieldlist ::= field {fieldsep field} [fieldsep]field ::= `[′ exp `]′ `=′ exp | Name `=′ exp | expfieldsep ::= `,′ | `;′binop ::= `+′ | `-′ | `*′ | `/′ | `^′ | `%′ | `..′ | `<′ | `<=′ | `>′ | `>=′ | `==′ | `~=′ | and | orunop ::= `-′ | not | `#


Last update: Tue Oct 3 21:27:28 BRT 2006?
譯文最后更新:修改幾處別字 2009年4月7日

總結(jié)

以上是生活随笔為你收集整理的Lua 5.1 参考手册的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

久久久精品国产sm最大网站 | 亚洲人成影院在线无码按摩店 | 宝宝好涨水快流出来免费视频 | 黄网在线观看免费网站 | 午夜男女很黄的视频 | 日本护士xxxxhd少妇 | 亚洲阿v天堂在线 | 国产一区二区三区四区五区加勒比 | 中文字幕人妻无码一区二区三区 | 婷婷丁香六月激情综合啪 | 在线播放免费人成毛片乱码 | 人妻少妇精品视频专区 | 国产做国产爱免费视频 | 久久五月精品中文字幕 | 成人免费视频视频在线观看 免费 | 亚洲中文字幕无码中字 | 色爱情人网站 | 荫蒂添的好舒服视频囗交 | а天堂中文在线官网 | 成人一区二区免费视频 | 无码乱肉视频免费大全合集 | 久久综合色之久久综合 | 免费国产成人高清在线观看网站 | 真人与拘做受免费视频 | 日欧一片内射va在线影院 | 久久久久成人片免费观看蜜芽 | 水蜜桃亚洲一二三四在线 | 激情爆乳一区二区三区 | 日本丰满熟妇videos | 国产卡一卡二卡三 | 久久精品女人天堂av免费观看 | 强开小婷嫩苞又嫩又紧视频 | 久久99精品久久久久久动态图 | 中文字幕av伊人av无码av | 久久精品中文字幕一区 | 狠狠色丁香久久婷婷综合五月 | 国产亲子乱弄免费视频 | 精品成在人线av无码免费看 | 精品久久久无码中文字幕 | 天海翼激烈高潮到腰振不止 | 国产激情综合五月久久 | 日本熟妇人妻xxxxx人hd | 日韩av无码一区二区三区 | 精品无码一区二区三区爱欲 | 曰韩少妇内射免费播放 | 国产又爽又猛又粗的视频a片 | 国产一区二区不卡老阿姨 | a在线观看免费网站大全 | av人摸人人人澡人人超碰下载 | 97夜夜澡人人爽人人喊中国片 | 久久久久国色av免费观看性色 | 国产成人精品优优av | 国产午夜亚洲精品不卡下载 | 欧美成人午夜精品久久久 | 国产麻豆精品精东影业av网站 | 亚洲国产精品毛片av不卡在线 | 欧美 日韩 亚洲 在线 | 日韩在线不卡免费视频一区 | 伊人久久大香线蕉av一区二区 | 国产亚洲精品久久久久久 | 精品人人妻人人澡人人爽人人 | 51国偷自产一区二区三区 | 精品国产国产综合精品 | 国产特级毛片aaaaaa高潮流水 | 日韩精品一区二区av在线 | 女人高潮内射99精品 | 色欲av亚洲一区无码少妇 | 性色欲网站人妻丰满中文久久不卡 | 日韩无码专区 | 蜜臀av在线观看 在线欧美精品一区二区三区 | 激情五月综合色婷婷一区二区 | 久久人妻内射无码一区三区 | 亚洲の无码国产の无码步美 | 亚洲欧美国产精品久久 | 久久国产精品_国产精品 | 日韩亚洲欧美中文高清在线 | 亚洲成a人片在线观看无码3d | 高潮喷水的毛片 | 亚洲精品美女久久久久久久 | 日日鲁鲁鲁夜夜爽爽狠狠 | 国产特级毛片aaaaaaa高清 | 老司机亚洲精品影院 | 中文字幕无码日韩欧毛 | 激情五月综合色婷婷一区二区 | 亚洲午夜无码久久 | 无码精品人妻一区二区三区av | 性生交大片免费看女人按摩摩 | 无码播放一区二区三区 | 中文字幕乱码人妻二区三区 | www国产亚洲精品久久久日本 | 97夜夜澡人人爽人人喊中国片 | 中文字幕乱码人妻二区三区 | 精品无码一区二区三区的天堂 | 未满成年国产在线观看 | 少妇无码av无码专区在线观看 | 欧美人与禽zoz0性伦交 | 精品少妇爆乳无码av无码专区 | 日本精品少妇一区二区三区 | 国产成人一区二区三区在线观看 | 玩弄中年熟妇正在播放 | 免费无码一区二区三区蜜桃大 | 亚洲色在线无码国产精品不卡 | 永久免费观看美女裸体的网站 | 欧美成人家庭影院 | 无码国内精品人妻少妇 | 无码午夜成人1000部免费视频 | 国产偷抇久久精品a片69 | 熟妇女人妻丰满少妇中文字幕 | 日韩精品无码一本二本三本色 | 沈阳熟女露脸对白视频 | 漂亮人妻洗澡被公强 日日躁 | 色五月丁香五月综合五月 | 中文字幕无码人妻少妇免费 | 亚洲国产av精品一区二区蜜芽 | 色欲久久久天天天综合网精品 | 欧美freesex黑人又粗又大 | 人妻少妇被猛烈进入中文字幕 | 亚洲一区二区三区无码久久 | 亚洲天堂2017无码 | 国产在热线精品视频 | 国产美女极度色诱视频www | aa片在线观看视频在线播放 | 55夜色66夜色国产精品视频 | 中文字幕无码av波多野吉衣 | 2020久久超碰国产精品最新 | 少妇无套内谢久久久久 | 国产成人av免费观看 | 色婷婷av一区二区三区之红樱桃 | 国产精品久久久av久久久 | 无码精品国产va在线观看dvd | 无码中文字幕色专区 | 福利一区二区三区视频在线观看 | 人妻插b视频一区二区三区 | 荡女精品导航 | 一二三四在线观看免费视频 | 爆乳一区二区三区无码 | 国产亚洲人成在线播放 | 色综合久久中文娱乐网 | 18无码粉嫩小泬无套在线观看 | 人妻有码中文字幕在线 | 伊人色综合久久天天小片 | 国产乱人伦av在线无码 | 日韩人妻无码中文字幕视频 | 无码一区二区三区在线观看 | 国产成人精品一区二区在线小狼 | 精品久久久久香蕉网 | 国产亚洲人成a在线v网站 | 无码人中文字幕 | 国产激情综合五月久久 | 欧美黑人乱大交 | 人妻熟女一区 | 久久人人97超碰a片精品 | 午夜时刻免费入口 | 亚洲综合另类小说色区 | 色欲综合久久中文字幕网 | 精品无人区无码乱码毛片国产 | 国产熟妇另类久久久久 | 亚洲国产精品一区二区第一页 | 欧美性生交活xxxxxdddd | 国产精品无码一区二区三区不卡 | 日韩av无码中文无码电影 | 99久久人妻精品免费一区 | 久久国语露脸国产精品电影 | yw尤物av无码国产在线观看 | 国产亚洲精品久久久久久国模美 | 国产极品美女高潮无套在线观看 | 性欧美疯狂xxxxbbbb | 久久婷婷五月综合色国产香蕉 | 特级做a爰片毛片免费69 | 日韩无套无码精品 | 国产无遮挡吃胸膜奶免费看 | 熟妇人妻无码xxx视频 | 亚洲国产精品无码久久久久高潮 | 噜噜噜亚洲色成人网站 | 少妇被粗大的猛进出69影院 | 久久精品丝袜高跟鞋 | 人人妻人人澡人人爽人人精品 | av香港经典三级级 在线 | 精品午夜福利在线观看 | 免费人成在线视频无码 | 国内揄拍国内精品少妇国语 | 色综合天天综合狠狠爱 | 国产精品理论片在线观看 | 国产精品福利视频导航 | 久久综合九色综合欧美狠狠 | 国产精品二区一区二区aⅴ污介绍 | 天堂а√在线中文在线 | 精品久久久无码中文字幕 | 成 人 网 站国产免费观看 | 女人被爽到呻吟gif动态图视看 | 麻豆国产97在线 | 欧洲 | 亚洲国产精品久久久天堂 | 国产午夜亚洲精品不卡 | 日本在线高清不卡免费播放 | 377p欧洲日本亚洲大胆 | 夜夜躁日日躁狠狠久久av | 久久久久久久久888 | 欧美真人作爱免费视频 | 亚洲 欧美 激情 小说 另类 | 国产成人午夜福利在线播放 | 麻豆国产人妻欲求不满谁演的 | 无码帝国www无码专区色综合 | 日韩欧美中文字幕在线三区 | 性开放的女人aaa片 | 熟女体下毛毛黑森林 | 沈阳熟女露脸对白视频 | 宝宝好涨水快流出来免费视频 | 久久精品人人做人人综合试看 | 精品成人av一区二区三区 | 婷婷色婷婷开心五月四房播播 | 国产绳艺sm调教室论坛 | 亚洲乱码日产精品bd | 中国女人内谢69xxxxxa片 | 激情爆乳一区二区三区 | 日日碰狠狠躁久久躁蜜桃 | 99久久人妻精品免费二区 | 四虎4hu永久免费 | 中文字幕日产无线码一区 | 久久精品国产日本波多野结衣 | 亚洲中文字幕乱码av波多ji | 亚洲国产午夜精品理论片 | 97夜夜澡人人双人人人喊 | 99视频精品全部免费免费观看 | 国产av人人夜夜澡人人爽麻豆 | 日产国产精品亚洲系列 | 东京热无码av男人的天堂 | 午夜精品一区二区三区的区别 | 妺妺窝人体色www在线小说 | 男人的天堂av网站 | 久久天天躁夜夜躁狠狠 | 无遮挡国产高潮视频免费观看 | 久久精品国产99精品亚洲 | 久久国产自偷自偷免费一区调 | 1000部啪啪未满十八勿入下载 | 中文字幕人妻无码一区二区三区 | 国产真实伦对白全集 | 性欧美牲交在线视频 | 白嫩日本少妇做爰 | 日本精品高清一区二区 | 免费观看又污又黄的网站 | 国产无套内射久久久国产 | 内射爽无广熟女亚洲 | 色婷婷综合中文久久一本 | 亚洲中文字幕久久无码 | 成人无码精品1区2区3区免费看 | 精品人人妻人人澡人人爽人人 | 亚洲天堂2017无码中文 | 蜜臀aⅴ国产精品久久久国产老师 | 欧洲vodafone精品性 | 精品一二三区久久aaa片 | 一二三四在线观看免费视频 | 精品午夜福利在线观看 | 欧美猛少妇色xxxxx | 国产内射老熟女aaaa | 亚洲精品中文字幕久久久久 | 亚洲欧美国产精品久久 | 国产真实乱对白精彩久久 | 欧美真人作爱免费视频 | 99久久久无码国产精品免费 | 精品国产一区二区三区四区在线看 | 人妻少妇精品无码专区二区 | 特大黑人娇小亚洲女 | 中文精品久久久久人妻不卡 | 影音先锋中文字幕无码 | 国产av久久久久精东av | 国产精品久久久久9999小说 | 午夜男女很黄的视频 | 成人一区二区免费视频 | 丰满少妇弄高潮了www | 日本爽爽爽爽爽爽在线观看免 | 性做久久久久久久久 | 久久亚洲国产成人精品性色 | 亚洲国产av精品一区二区蜜芽 | 狂野欧美性猛xxxx乱大交 | 亚洲精品美女久久久久久久 | 亚洲呦女专区 | 老熟妇仑乱视频一区二区 | 伊人久久婷婷五月综合97色 | 免费人成网站视频在线观看 | 亚洲精品欧美二区三区中文字幕 | 综合激情五月综合激情五月激情1 | 日本丰满护士爆乳xxxx | 国产亚洲tv在线观看 | 国内揄拍国内精品少妇国语 | 波多野42部无码喷潮在线 | 国精品人妻无码一区二区三区蜜柚 | 麻豆蜜桃av蜜臀av色欲av | 久久国语露脸国产精品电影 | 国产成人精品一区二区在线小狼 | 性做久久久久久久久 | 女人被男人躁得好爽免费视频 | 免费无码的av片在线观看 | 亚洲一区二区三区播放 | 久久亚洲国产成人精品性色 | 亚洲国产精品毛片av不卡在线 | 亚洲欧美色中文字幕在线 | 中文字幕中文有码在线 | 成人无码精品1区2区3区免费看 | 强伦人妻一区二区三区视频18 | 欧美日本日韩 | 亚洲色大成网站www国产 | 九九久久精品国产免费看小说 | 成人无码精品1区2区3区免费看 | 久久久久久亚洲精品a片成人 | 曰韩少妇内射免费播放 | 色婷婷欧美在线播放内射 | 亚洲狠狠婷婷综合久久 | 精品aⅴ一区二区三区 | 天天做天天爱天天爽综合网 | 久久99精品久久久久久 | 麻豆av传媒蜜桃天美传媒 | 日本护士xxxxhd少妇 | 久久国内精品自在自线 | 少妇被粗大的猛进出69影院 | 亚洲国产精品一区二区第一页 | 久久综合色之久久综合 | 日韩av激情在线观看 | 精品无码av一区二区三区 | 国产xxx69麻豆国语对白 | 亚洲a无码综合a国产av中文 | 欧美freesex黑人又粗又大 | 免费乱码人妻系列无码专区 | 色综合久久久无码网中文 | 色婷婷久久一区二区三区麻豆 | 四十如虎的丰满熟妇啪啪 | 国产亚洲日韩欧美另类第八页 | 亚洲国产欧美日韩精品一区二区三区 | 亚洲一区二区三区在线观看网站 | 扒开双腿吃奶呻吟做受视频 | 国模大胆一区二区三区 | 无码国模国产在线观看 | 三上悠亚人妻中文字幕在线 | 欧美性猛交内射兽交老熟妇 | 亚洲国产一区二区三区在线观看 | 纯爱无遮挡h肉动漫在线播放 | 亚洲综合在线一区二区三区 | 狠狠亚洲超碰狼人久久 | 东京热男人av天堂 | 国产av久久久久精东av | 国产三级久久久精品麻豆三级 | 亚洲熟妇色xxxxx欧美老妇 | 国产精品无码久久av | 亚洲国产精品久久久天堂 | 久久人人爽人人爽人人片ⅴ | 国产超碰人人爽人人做人人添 | 国产激情艳情在线看视频 | 午夜嘿嘿嘿影院 | 无遮无挡爽爽免费视频 | 色欲综合久久中文字幕网 | 国产农村乱对白刺激视频 | 成人aaa片一区国产精品 | 疯狂三人交性欧美 | 中文无码成人免费视频在线观看 | 三上悠亚人妻中文字幕在线 | ass日本丰满熟妇pics | 人妻人人添人妻人人爱 | 日韩精品久久久肉伦网站 | 奇米影视888欧美在线观看 | 又紧又大又爽精品一区二区 | 丰满少妇弄高潮了www | 国产精品久久久久7777 | 天天躁夜夜躁狠狠是什么心态 | 日韩精品a片一区二区三区妖精 | 色妞www精品免费视频 | 国产亚洲欧美日韩亚洲中文色 | 永久免费观看国产裸体美女 | 一本无码人妻在中文字幕免费 | 撕开奶罩揉吮奶头视频 | 国产色xx群视频射精 | 亚洲精品一区二区三区在线观看 | 久久久婷婷五月亚洲97号色 | 欧美精品免费观看二区 | 性生交大片免费看l | 国产人妻久久精品二区三区老狼 | 免费无码肉片在线观看 | 欧美日韩在线亚洲综合国产人 | 麻花豆传媒剧国产免费mv在线 | 亚洲人成人无码网www国产 | 精品夜夜澡人妻无码av蜜桃 | 野狼第一精品社区 | 亚洲精品一区二区三区大桥未久 | 欧美老人巨大xxxx做受 | 狂野欧美激情性xxxx | 久精品国产欧美亚洲色aⅴ大片 | √天堂资源地址中文在线 | 国产乱码精品一品二品 | 国产一区二区三区日韩精品 | 国产又爽又猛又粗的视频a片 | 久久伊人色av天堂九九小黄鸭 | 99er热精品视频 | 国产一区二区三区影院 | 欧美 丝袜 自拍 制服 另类 | 99视频精品全部免费免费观看 | 亚洲日韩中文字幕在线播放 | 国产一区二区三区影院 | 人妻少妇精品视频专区 | 久久99精品国产麻豆蜜芽 | 亚洲国产精品无码久久久久高潮 | 人人妻人人澡人人爽欧美一区 | 亚洲国产欧美在线成人 | 1000部夫妻午夜免费 | 国产精品久久久久影院嫩草 | 久激情内射婷内射蜜桃人妖 | 久久国产精品_国产精品 | 中文无码精品a∨在线观看不卡 | 亚洲人成网站在线播放942 | 精品无码一区二区三区爱欲 | 亚洲精品一区二区三区在线 | 人人妻人人澡人人爽欧美精品 | 人人妻人人澡人人爽欧美一区九九 | 国产精品18久久久久久麻辣 | 在线a亚洲视频播放在线观看 | 亚洲国产精品毛片av不卡在线 | 国产va免费精品观看 | 日日麻批免费40分钟无码 | 99久久无码一区人妻 | 成人无码精品1区2区3区免费看 | 精品一区二区三区波多野结衣 | 国产成人精品视频ⅴa片软件竹菊 | 亚洲国产一区二区三区在线观看 | 99精品无人区乱码1区2区3区 | 久久综合九色综合97网 | 高清国产亚洲精品自在久久 | 未满小14洗澡无码视频网站 | 免费看男女做好爽好硬视频 | 中文精品久久久久人妻不卡 | 成在人线av无码免观看麻豆 | 老子影院午夜伦不卡 | 2019午夜福利不卡片在线 | 久久久久久久女国产乱让韩 | 98国产精品综合一区二区三区 | 性生交大片免费看女人按摩摩 | 国产综合久久久久鬼色 | 国产黄在线观看免费观看不卡 | 国产免费久久精品国产传媒 | 中文字幕久久久久人妻 | 色综合久久久无码网中文 | av无码久久久久不卡免费网站 | 真人与拘做受免费视频 | 精品久久综合1区2区3区激情 | 成人欧美一区二区三区黑人免费 | 久久精品视频在线看15 | 亚洲七七久久桃花影院 | 樱花草在线播放免费中文 | 欧美一区二区三区视频在线观看 | 国产成人久久精品流白浆 | 亚洲精品成人av在线 | 国产精品办公室沙发 | 四虎国产精品一区二区 | 国产国语老龄妇女a片 | 免费看男女做好爽好硬视频 | 午夜精品一区二区三区的区别 | 欧美亚洲日韩国产人成在线播放 | 亚洲欧美色中文字幕在线 | 久久精品无码一区二区三区 | 国产精品久久久久影院嫩草 | 欧洲熟妇色 欧美 | 综合激情五月综合激情五月激情1 | 鲁一鲁av2019在线 | 无码国产激情在线观看 | 图片区 小说区 区 亚洲五月 | 亚洲s色大片在线观看 | 国产99久久精品一区二区 | 国产精品久久久久9999小说 | 香港三级日本三级妇三级 | 亚洲综合在线一区二区三区 | 国产成人一区二区三区在线观看 | 97久久国产亚洲精品超碰热 | 国产精品久久久av久久久 | 欧美成人免费全部网站 | 久久综合九色综合97网 | 亚洲а∨天堂久久精品2021 | 亚洲国产精品成人久久蜜臀 | 成人试看120秒体验区 | 欧美精品在线观看 | 亚洲综合无码久久精品综合 | 又大又硬又爽免费视频 | 又湿又紧又大又爽a视频国产 | 国产精品免费大片 | 欧美成人家庭影院 | 久久精品丝袜高跟鞋 | 国产成人综合色在线观看网站 | 久久综合狠狠综合久久综合88 | 色综合久久久无码中文字幕 | 日韩少妇白浆无码系列 | 又紧又大又爽精品一区二区 | 国产疯狂伦交大片 | 精品欧美一区二区三区久久久 | 亚洲国产精品美女久久久久 | 国产性生大片免费观看性 | 日本www一道久久久免费榴莲 | 18无码粉嫩小泬无套在线观看 | 国产精品爱久久久久久久 | 国产三级久久久精品麻豆三级 | 97精品人妻一区二区三区香蕉 | 国产人妻久久精品二区三区老狼 | 免费观看的无遮挡av | 性色av无码免费一区二区三区 | 欧美日韩视频无码一区二区三 | 精品人人妻人人澡人人爽人人 | 亚洲中文字幕无码中字 | 国产熟妇另类久久久久 | 欧美性猛交内射兽交老熟妇 | 在线精品亚洲一区二区 | 女人被男人躁得好爽免费视频 | 无人区乱码一区二区三区 | 真人与拘做受免费视频 | 天堂一区人妻无码 | 人人澡人人透人人爽 | 婷婷丁香六月激情综合啪 | 少妇人妻av毛片在线看 | 最新版天堂资源中文官网 | 久久精品视频在线看15 | 国产精品二区一区二区aⅴ污介绍 | 老头边吃奶边弄进去呻吟 | 99精品视频在线观看免费 | 真人与拘做受免费视频一 | 少妇无码一区二区二三区 | 在线观看欧美一区二区三区 | 久久成人a毛片免费观看网站 | 中国女人内谢69xxxx | 捆绑白丝粉色jk震动捧喷白浆 | 真人与拘做受免费视频一 | 一本久久伊人热热精品中文字幕 | 十八禁视频网站在线观看 | 蜜臀av无码人妻精品 | 亚洲の无码国产の无码步美 | 国产精品福利视频导航 | 精品一区二区三区无码免费视频 | 日本一卡2卡3卡四卡精品网站 | 麻花豆传媒剧国产免费mv在线 | 色五月五月丁香亚洲综合网 | 亲嘴扒胸摸屁股激烈网站 | 俺去俺来也www色官网 | 日韩精品a片一区二区三区妖精 | 国产人妻久久精品二区三区老狼 | 在线看片无码永久免费视频 | 高潮喷水的毛片 | 日韩无套无码精品 | 色狠狠av一区二区三区 | 日韩av无码一区二区三区不卡 | 99久久久国产精品无码免费 | 成人精品视频一区二区三区尤物 | 激情内射亚州一区二区三区爱妻 | 精品厕所偷拍各类美女tp嘘嘘 | 偷窥日本少妇撒尿chinese | 国产成人精品必看 | 乱码午夜-极国产极内射 | 免费人成在线观看网站 | 成在人线av无码免费 | 亚洲第一网站男人都懂 | 亚洲自偷自偷在线制服 | 欧美人与物videos另类 | 奇米影视7777久久精品 | 九九热爱视频精品 | 色情久久久av熟女人妻网站 | 成年美女黄网站色大免费全看 | 亚洲s色大片在线观看 | 国产成人精品一区二区在线小狼 | 国内精品久久毛片一区二区 | 亚洲国精产品一二二线 | 国产又粗又硬又大爽黄老大爷视 | 在线精品亚洲一区二区 | 无人区乱码一区二区三区 | 精品久久久中文字幕人妻 | 国产卡一卡二卡三 | 午夜无码区在线观看 | 国产口爆吞精在线视频 | 国产乱码精品一品二品 | 国产色精品久久人妻 | 日本丰满熟妇videos | 狂野欧美性猛交免费视频 | 国产精品久久久 | 荡女精品导航 | 精品aⅴ一区二区三区 | 天天拍夜夜添久久精品大 | aⅴ亚洲 日韩 色 图网站 播放 | 又湿又紧又大又爽a视频国产 | 国产猛烈高潮尖叫视频免费 | 久久精品国产99久久6动漫 | 精品国产一区av天美传媒 | 亚洲午夜福利在线观看 | 成人一区二区免费视频 | 午夜精品一区二区三区在线观看 | 国产精品99久久精品爆乳 | 国产av人人夜夜澡人人爽麻豆 | 又湿又紧又大又爽a视频国产 | 性开放的女人aaa片 | 久久亚洲国产成人精品性色 | 国产xxx69麻豆国语对白 | 暴力强奷在线播放无码 | 亚洲欧美精品aaaaaa片 | 日日摸日日碰夜夜爽av | 少妇太爽了在线观看 | 国产在线一区二区三区四区五区 | 国产精品久久久久久久9999 | 日欧一片内射va在线影院 | 十八禁视频网站在线观看 | 欧美精品在线观看 | 亚洲国产精品一区二区第一页 | 性欧美牲交xxxxx视频 | 高清国产亚洲精品自在久久 | 99久久婷婷国产综合精品青草免费 | 成熟女人特级毛片www免费 | 国产精品无码久久av | 成人无码视频免费播放 | 在线 国产 欧美 亚洲 天堂 | 日韩欧美群交p片內射中文 | 国产在线无码精品电影网 | 久久国语露脸国产精品电影 | 国产色视频一区二区三区 | 精品人妻人人做人人爽 | 久久久av男人的天堂 | 色偷偷av老熟女 久久精品人妻少妇一区二区三区 | 色欲久久久天天天综合网精品 | 国产午夜无码视频在线观看 | 免费中文字幕日韩欧美 | 欧美日本日韩 | 在线播放无码字幕亚洲 | 在线亚洲高清揄拍自拍一品区 | 国产成人精品视频ⅴa片软件竹菊 | 中文字幕无码视频专区 | 亚洲色成人中文字幕网站 | 欧美肥老太牲交大战 | 精品午夜福利在线观看 | 水蜜桃色314在线观看 | 大肉大捧一进一出视频出来呀 | 中文亚洲成a人片在线观看 | 六月丁香婷婷色狠狠久久 | 中文字幕+乱码+中文字幕一区 | 蜜桃无码一区二区三区 | av无码电影一区二区三区 | 亚洲aⅴ无码成人网站国产app | 午夜熟女插插xx免费视频 | 国产精品欧美成人 | 国产成人无码av片在线观看不卡 | 国产国产精品人在线视 | 国产 精品 自在自线 | 亚洲午夜福利在线观看 | 四虎影视成人永久免费观看视频 | 国产超级va在线观看视频 | 欧美人与牲动交xxxx | 亚洲精品综合五月久久小说 | 丝袜 中出 制服 人妻 美腿 | 欧美精品免费观看二区 | 亚洲精品综合五月久久小说 | 在线亚洲高清揄拍自拍一品区 | 久久久久99精品成人片 | 99久久精品国产一区二区蜜芽 | 无套内射视频囯产 | 国产suv精品一区二区五 | 国产精品亚洲一区二区三区喷水 | 亚洲精品成人福利网站 | 精品夜夜澡人妻无码av蜜桃 | 亚洲第一网站男人都懂 | 日本大香伊一区二区三区 | 日本爽爽爽爽爽爽在线观看免 | 久激情内射婷内射蜜桃人妖 | 亚洲精品一区二区三区在线 | 久久精品丝袜高跟鞋 | 亚洲国精产品一二二线 | 男女下面进入的视频免费午夜 | 久久人人爽人人爽人人片ⅴ | 少妇无码av无码专区在线观看 | 亚洲国产欧美日韩精品一区二区三区 | 国产成人无码区免费内射一片色欲 | 精品成人av一区二区三区 | 成年美女黄网站色大免费视频 | 久久久久成人片免费观看蜜芽 | 国产人妻久久精品二区三区老狼 | 又色又爽又黄的美女裸体网站 | 精品人妻人人做人人爽夜夜爽 | 亚洲色在线无码国产精品不卡 | 国产精华av午夜在线观看 | 久久精品中文字幕大胸 | 亚洲七七久久桃花影院 | 亚洲熟妇色xxxxx亚洲 | 日本免费一区二区三区最新 | 丁香花在线影院观看在线播放 | 日韩无码专区 | 国产成人精品久久亚洲高清不卡 | 国产成人一区二区三区别 | 亚洲s码欧洲m码国产av | 2020最新国产自产精品 | 中文字幕乱码人妻无码久久 | 亚洲小说春色综合另类 | 天干天干啦夜天干天2017 | 国产av人人夜夜澡人人爽麻豆 | 无码午夜成人1000部免费视频 | 老太婆性杂交欧美肥老太 | 亚洲日韩乱码中文无码蜜桃臀网站 | 中文无码成人免费视频在线观看 | 国产av无码专区亚洲awww | 一本大道伊人av久久综合 | 中文字幕精品av一区二区五区 | 精品久久久无码中文字幕 | 日本丰满护士爆乳xxxx | 人妻无码久久精品人妻 | 久久国产精品偷任你爽任你 | 精品偷自拍另类在线观看 | 亚洲色欲色欲天天天www | 久久久中文字幕日本无吗 | 大乳丰满人妻中文字幕日本 | 人妻体内射精一区二区三四 | 无码乱肉视频免费大全合集 | 国产 浪潮av性色四虎 | 欧美 日韩 亚洲 在线 | 色窝窝无码一区二区三区色欲 | 免费观看激色视频网站 | 国产99久久精品一区二区 | 亚洲小说图区综合在线 | 久久熟妇人妻午夜寂寞影院 | 中文字幕人妻无码一区二区三区 | 无码国产乱人伦偷精品视频 | 国产97人人超碰caoprom | 天堂无码人妻精品一区二区三区 | 亚洲中文字幕在线观看 | 中文字幕无码人妻少妇免费 | 色综合久久久久综合一本到桃花网 | 无码吃奶揉捏奶头高潮视频 | 波多野结衣av一区二区全免费观看 | 亚洲色成人中文字幕网站 | 亚洲精品一区二区三区四区五区 | 99久久精品国产一区二区蜜芽 | 亚洲精品午夜国产va久久成人 | 亚洲人亚洲人成电影网站色 | 欧美成人免费全部网站 | 男人的天堂2018无码 | 色综合久久久无码中文字幕 | 国产va免费精品观看 | 国产精品久久久久久无码 | 天堂亚洲2017在线观看 | 扒开双腿吃奶呻吟做受视频 | 午夜福利试看120秒体验区 | 亚洲国产精品成人久久蜜臀 | 搡女人真爽免费视频大全 | 51国偷自产一区二区三区 | 又紧又大又爽精品一区二区 | 亚洲日韩一区二区 | 亚洲精品中文字幕 | 国产人妖乱国产精品人妖 | 亚洲性无码av中文字幕 | 激情国产av做激情国产爱 | 人人爽人人爽人人片av亚洲 | 亚洲の无码国产の无码影院 | 男女性色大片免费网站 | 久久www免费人成人片 | 捆绑白丝粉色jk震动捧喷白浆 | 少妇性l交大片欧洲热妇乱xxx | 日本大香伊一区二区三区 | 一区二区三区高清视频一 | 亚洲精品中文字幕 | 亚洲国产欧美国产综合一区 | 中文字幕 人妻熟女 | 国产九九九九九九九a片 | 99久久无码一区人妻 | 日本www一道久久久免费榴莲 | 亚洲精品一区三区三区在线观看 | 亚欧洲精品在线视频免费观看 | 久久久久久久久蜜桃 | 免费无码肉片在线观看 | 麻豆av传媒蜜桃天美传媒 | 精品一区二区不卡无码av | 啦啦啦www在线观看免费视频 | 久久亚洲国产成人精品性色 | 欧美老妇交乱视频在线观看 | 欧美自拍另类欧美综合图片区 | 午夜精品一区二区三区的区别 | 国产成人精品优优av | 国内精品久久毛片一区二区 | 亚洲精品无码人妻无码 | 色欲人妻aaaaaaa无码 | 久久人人爽人人人人片 | 欧美性生交xxxxx久久久 | 亚洲第一无码av无码专区 | 男人和女人高潮免费网站 | 麻豆成人精品国产免费 | 中文字幕 亚洲精品 第1页 | 国产亚洲tv在线观看 | 国产成人综合美国十次 | 久久99国产综合精品 | 又粗又大又硬毛片免费看 | 初尝人妻少妇中文字幕 | 色一情一乱一伦 | 中文字幕av日韩精品一区二区 | 国产精品99久久精品爆乳 | 日本护士毛茸茸高潮 | 亚洲精品久久久久avwww潮水 | 亚洲精品久久久久久一区二区 | 爱做久久久久久 | 国产偷自视频区视频 | 成人免费视频在线观看 | 樱花草在线社区www | 麻豆成人精品国产免费 | 午夜不卡av免费 一本久久a久久精品vr综合 | 亚洲gv猛男gv无码男同 | 国产97色在线 | 免 | 欧美精品在线观看 | 国产精品久久久久影院嫩草 | 大屁股大乳丰满人妻 | 国产精品免费大片 | 熟女俱乐部五十路六十路av | 免费观看又污又黄的网站 | 女高中生第一次破苞av | 激情内射亚州一区二区三区爱妻 | 欧美变态另类xxxx | 国产在线精品一区二区高清不卡 | 中文字幕无线码 | 97久久超碰中文字幕 | 蜜臀av无码人妻精品 | 在线观看欧美一区二区三区 | 国内精品人妻无码久久久影院蜜桃 | 精品成在人线av无码免费看 | 日韩av无码一区二区三区不卡 | 国产精品va在线观看无码 | 欧美性生交活xxxxxdddd | 亚洲欧美日韩成人高清在线一区 | 日本欧美一区二区三区乱码 | 无码乱肉视频免费大全合集 | 日本熟妇乱子伦xxxx | 伊人久久大香线蕉午夜 | 国产激情无码一区二区app | 丰满少妇熟乱xxxxx视频 | 国产农村妇女高潮大叫 | 精品久久久无码人妻字幂 | 2020久久香蕉国产线看观看 | 亚洲gv猛男gv无码男同 | 风流少妇按摩来高潮 | 亚洲国产高清在线观看视频 | 日本熟妇乱子伦xxxx | аⅴ资源天堂资源库在线 | 久久精品国产99久久6动漫 | 天天摸天天透天天添 | 夜先锋av资源网站 | 无码人妻av免费一区二区三区 | 精品久久久中文字幕人妻 | 无人区乱码一区二区三区 | 大肉大捧一进一出好爽视频 | 四虎4hu永久免费 | 99国产精品白浆在线观看免费 | 人人妻人人澡人人爽欧美一区九九 | 国产精品久久久久7777 | 亚洲精品无码人妻无码 | 又粗又大又硬又长又爽 | 超碰97人人做人人爱少妇 | 亚洲国产精品毛片av不卡在线 | 久9re热视频这里只有精品 | 久久99精品久久久久久动态图 | 久久99国产综合精品 | 97久久精品无码一区二区 | 日韩欧美群交p片內射中文 | 欧美刺激性大交 | 疯狂三人交性欧美 | 成人动漫在线观看 | 欧美国产亚洲日韩在线二区 | 人妻互换免费中文字幕 | 精品国精品国产自在久国产87 | 午夜嘿嘿嘿影院 | 日本一卡2卡3卡4卡无卡免费网站 国产一区二区三区影院 | 丁香啪啪综合成人亚洲 | 妺妺窝人体色www在线小说 | 中文字幕日产无线码一区 | 国色天香社区在线视频 | 久久综合给久久狠狠97色 | 国模大胆一区二区三区 | 熟妇人妻中文av无码 | 精品无码成人片一区二区98 | 欧美三级不卡在线观看 | 99久久精品日本一区二区免费 | 日韩少妇内射免费播放 | 久久久久免费精品国产 | 国产在线一区二区三区四区五区 | 人妻无码αv中文字幕久久琪琪布 | 国产人妻久久精品二区三区老狼 | 国产凸凹视频一区二区 | 精品一区二区三区无码免费视频 | 亚洲色大成网站www | 99麻豆久久久国产精品免费 | 性史性农村dvd毛片 | 成熟人妻av无码专区 | 国产亚洲精品精品国产亚洲综合 | 久久综合狠狠综合久久综合88 | 精品无码国产自产拍在线观看蜜 | 亚洲人成影院在线无码按摩店 | 双乳奶水饱满少妇呻吟 | 久久五月精品中文字幕 | 国产精品无码一区二区桃花视频 | 丰腴饱满的极品熟妇 | 国产舌乚八伦偷品w中 | 国产偷国产偷精品高清尤物 | 国产精品久久久 | 亚洲欧美国产精品专区久久 | 免费人成网站视频在线观看 | 7777奇米四色成人眼影 | 东京热一精品无码av | 欧洲欧美人成视频在线 | 天天躁日日躁狠狠躁免费麻豆 | 青青青手机频在线观看 | 无人区乱码一区二区三区 | 暴力强奷在线播放无码 | 色欲人妻aaaaaaa无码 | 四虎影视成人永久免费观看视频 | 久久久中文久久久无码 | 九九久久精品国产免费看小说 | 亚洲日本一区二区三区在线 | 300部国产真实乱 | 亚洲色在线无码国产精品不卡 | 亚洲无人区午夜福利码高清完整版 | 暴力强奷在线播放无码 | 欧美黑人巨大xxxxx | 欧美真人作爱免费视频 | 久久久精品人妻久久影视 | 亲嘴扒胸摸屁股激烈网站 | 欧美 日韩 亚洲 在线 | av无码久久久久不卡免费网站 | 久久精品人人做人人综合试看 | 久久99久久99精品中文字幕 | 天天做天天爱天天爽综合网 | 真人与拘做受免费视频一 | 国产内射爽爽大片视频社区在线 | 亚洲经典千人经典日产 | 欧美日韩久久久精品a片 | 荫蒂添的好舒服视频囗交 | 国产香蕉尹人视频在线 | 久在线观看福利视频 | 亚洲国产一区二区三区在线观看 | 亚洲日韩一区二区 | 激情亚洲一区国产精品 | 丝袜美腿亚洲一区二区 | 免费观看黄网站 | 国语自产偷拍精品视频偷 | 大色综合色综合网站 | 国产精品高潮呻吟av久久4虎 | 欧美人与善在线com | 久久久久久a亚洲欧洲av冫 | 亚洲国产成人a精品不卡在线 | 亚洲日韩一区二区 | 久久精品人人做人人综合 | 一个人看的www免费视频在线观看 | 中文字幕中文有码在线 | 国产精品高潮呻吟av久久4虎 | 亚洲自偷自偷在线制服 | 国产精品内射视频免费 | 国产激情综合五月久久 | 成人无码精品1区2区3区免费看 | 人妻少妇精品无码专区二区 | 亚洲阿v天堂在线 | 四虎国产精品免费久久 | 人妻少妇精品无码专区动漫 | 人人妻人人澡人人爽人人精品 | 麻豆蜜桃av蜜臀av色欲av | 男女作爱免费网站 | 亚洲一区av无码专区在线观看 | 午夜精品久久久久久久 | 装睡被陌生人摸出水好爽 | 美女黄网站人色视频免费国产 | 亚洲精品国产第一综合99久久 | 色欲综合久久中文字幕网 | 男女爱爱好爽视频免费看 | www国产亚洲精品久久网站 | 一本加勒比波多野结衣 | 波多野结衣高清一区二区三区 | 国产真实伦对白全集 | 领导边摸边吃奶边做爽在线观看 | 高清国产亚洲精品自在久久 | 国产精品久久国产三级国 | 波多野结衣乳巨码无在线观看 | 人人澡人人透人人爽 | 亚洲中文字幕无码中字 | 97se亚洲精品一区 | 久久97精品久久久久久久不卡 | 欧洲精品码一区二区三区免费看 | 久激情内射婷内射蜜桃人妖 | 亚洲成av人片在线观看无码不卡 | 人人妻人人澡人人爽欧美精品 | 亚洲精品欧美二区三区中文字幕 | 国产精品无码一区二区三区不卡 | 在线播放免费人成毛片乱码 | 亚洲国产精品久久久久久 | 一本大道伊人av久久综合 | 300部国产真实乱 | 国产无套粉嫩白浆在线 | 亚洲日韩av一区二区三区中文 | 午夜理论片yy44880影院 | 全黄性性激高免费视频 | 欧美性生交xxxxx久久久 | ass日本丰满熟妇pics | 狠狠亚洲超碰狼人久久 | 国产极品美女高潮无套在线观看 | 久久99热只有频精品8 | 欧美怡红院免费全部视频 | 免费人成网站视频在线观看 | 成人无码视频免费播放 | 久久综合给久久狠狠97色 | 高潮喷水的毛片 | 男人的天堂av网站 | 成熟女人特级毛片www免费 | 一本加勒比波多野结衣 | 乱码午夜-极国产极内射 | 国产午夜亚洲精品不卡下载 | 麻豆精品国产精华精华液好用吗 | 97色伦图片97综合影院 | 国产特级毛片aaaaaa高潮流水 | 99久久精品国产一区二区蜜芽 | 麻花豆传媒剧国产免费mv在线 | 欧美丰满熟妇xxxx性ppx人交 | 欧美丰满少妇xxxx性 | 国产乱人伦偷精品视频 | 欧美zoozzooz性欧美 | 97人妻精品一区二区三区 | 亚洲日韩一区二区三区 | 亚洲人成人无码网www国产 | 国产又爽又黄又刺激的视频 | 性啪啪chinese东北女人 | 人妻体内射精一区二区三四 | 日韩精品久久久肉伦网站 | 亚洲中文字幕成人无码 | 高潮毛片无遮挡高清免费 | 亚洲熟妇色xxxxx亚洲 | 两性色午夜免费视频 | 少妇久久久久久人妻无码 | 高潮毛片无遮挡高清免费视频 | 奇米综合四色77777久久 东京无码熟妇人妻av在线网址 | 三级4级全黄60分钟 | 欧美老人巨大xxxx做受 | 日韩精品成人一区二区三区 | 亚洲国产欧美国产综合一区 | 亚洲国产精品毛片av不卡在线 | 两性色午夜免费视频 | 99精品视频在线观看免费 | 麻豆果冻传媒2021精品传媒一区下载 | 男女下面进入的视频免费午夜 | 性生交大片免费看l | 免费人成在线观看网站 | 成人欧美一区二区三区黑人免费 | 中文字幕无码免费久久9一区9 | 亚洲国产精品美女久久久久 | 三级4级全黄60分钟 | 动漫av网站免费观看 | 98国产精品综合一区二区三区 | 中文字幕乱妇无码av在线 | 一个人看的www免费视频在线观看 | 日本丰满熟妇videos | 成人片黄网站色大片免费观看 | 性欧美videos高清精品 | 国产亚洲美女精品久久久2020 | 亲嘴扒胸摸屁股激烈网站 | 高清不卡一区二区三区 | 人人超人人超碰超国产 | 国产在线aaa片一区二区99 | 青草视频在线播放 | 国产成人精品三级麻豆 | 国产成人精品久久亚洲高清不卡 | 国内老熟妇对白xxxxhd | 欧美 亚洲 国产 另类 | 久久精品人人做人人综合试看 | 亚洲欧美中文字幕5发布 | 国产舌乚八伦偷品w中 | 激情亚洲一区国产精品 | 中文字幕色婷婷在线视频 | 午夜福利电影 | 欧美性猛交xxxx富婆 | 日本一区二区三区免费高清 | 欧美性生交活xxxxxdddd | 西西人体www44rt大胆高清 | 成人免费视频一区二区 | 精品水蜜桃久久久久久久 | 日本护士xxxxhd少妇 | 亚洲国产综合无码一区 | 国产极品美女高潮无套在线观看 | 亚洲一区av无码专区在线观看 | 久久zyz资源站无码中文动漫 | 欧美日韩人成综合在线播放 | 国产另类ts人妖一区二区 | 无码人妻精品一区二区三区下载 | 国产av人人夜夜澡人人爽麻豆 | 精品人人妻人人澡人人爽人人 | 久久99精品国产麻豆蜜芽 | 又粗又大又硬又长又爽 | 初尝人妻少妇中文字幕 | 亚洲中文字幕乱码av波多ji | 最新国产麻豆aⅴ精品无码 | 午夜免费福利小电影 | 亚洲欧美中文字幕5发布 | 久久久精品欧美一区二区免费 | 成年美女黄网站色大免费视频 | 色噜噜亚洲男人的天堂 | 成人亚洲精品久久久久 | 扒开双腿疯狂进出爽爽爽视频 | 免费观看又污又黄的网站 | 国内揄拍国内精品少妇国语 | 女人色极品影院 | 日韩人妻无码中文字幕视频 | 性欧美熟妇videofreesex | 国产精品无码永久免费888 | 三级4级全黄60分钟 | 97无码免费人妻超级碰碰夜夜 | 欧美性猛交内射兽交老熟妇 | 国产麻豆精品一区二区三区v视界 | 国产人妻精品一区二区三区不卡 | 亚洲人成无码网www | 日本丰满护士爆乳xxxx | 成人免费视频一区二区 | 色综合天天综合狠狠爱 | 久久国产自偷自偷免费一区调 | 欧美日韩综合一区二区三区 | 国产偷自视频区视频 | 性欧美熟妇videofreesex | 丝袜美腿亚洲一区二区 | 国内精品人妻无码久久久影院 | 亚洲毛片av日韩av无码 | 亚洲最大成人网站 | 日韩精品无码一本二本三本色 | 精品人妻中文字幕有码在线 | 亚洲欧美国产精品专区久久 | 国产激情艳情在线看视频 | 久久综合给合久久狠狠狠97色 | 无码精品人妻一区二区三区av | 东京一本一道一二三区 | 国产精品毛多多水多 | 亚洲精品国偷拍自产在线观看蜜桃 | 任你躁在线精品免费 | 免费观看激色视频网站 | 亚洲乱码中文字幕在线 | 日本乱人伦片中文三区 | 国产97在线 | 亚洲 | 天天做天天爱天天爽综合网 | а√天堂www在线天堂小说 | 精品欧美一区二区三区久久久 | 亚洲 高清 成人 动漫 | 国产免费久久精品国产传媒 | 久久午夜无码鲁丝片秋霞 | 无码精品人妻一区二区三区av | 精品人人妻人人澡人人爽人人 | 亚洲成av人综合在线观看 | 亚洲精品久久久久中文第一幕 | 97人妻精品一区二区三区 | 欧美大屁股xxxxhd黑色 | 精品一区二区三区波多野结衣 | 最新国产乱人伦偷精品免费网站 | 亚洲码国产精品高潮在线 | 免费人成网站视频在线观看 | 熟妇人妻无码xxx视频 | 精品国产一区av天美传媒 | 中文字幕乱码人妻无码久久 | 久久精品99久久香蕉国产色戒 | 人人妻人人藻人人爽欧美一区 | 国产在线无码精品电影网 | 国产av剧情md精品麻豆 | 东北女人啪啪对白 | 性欧美牲交xxxxx视频 | 国内少妇偷人精品视频 | 欧美兽交xxxx×视频 | 色欲久久久天天天综合网精品 | 伦伦影院午夜理论片 | 国产区女主播在线观看 | 2020久久超碰国产精品最新 | 亚洲精品综合一区二区三区在线 | 黑人巨大精品欧美黑寡妇 | 亚洲s色大片在线观看 | 人人妻人人藻人人爽欧美一区 | 免费人成在线观看网站 | 欧美性猛交xxxx富婆 | 亚洲の无码国产の无码影院 | 国产精品香蕉在线观看 | 东京一本一道一二三区 | 欧美人与善在线com | 色五月五月丁香亚洲综合网 | 亚洲成a人片在线观看无码3d | 亚洲精品国产第一综合99久久 | 岛国片人妻三上悠亚 | 国产在热线精品视频 | 最近免费中文字幕中文高清百度 | 国产午夜精品一区二区三区嫩草 | 国产性生交xxxxx无码 | 大肉大捧一进一出好爽视频 | 亚洲精品久久久久avwww潮水 | 乌克兰少妇xxxx做受 | 国产成人精品视频ⅴa片软件竹菊 | 国产精品丝袜黑色高跟鞋 | 亚洲综合无码久久精品综合 | 玩弄少妇高潮ⅹxxxyw | 亚洲精品中文字幕久久久久 | 久精品国产欧美亚洲色aⅴ大片 | 国产三级精品三级男人的天堂 | 99久久久无码国产精品免费 | 国产精品成人av在线观看 | 国产在线精品一区二区高清不卡 | 人妻体内射精一区二区三四 | 人妻少妇被猛烈进入中文字幕 | 成年女人永久免费看片 | 曰韩无码二三区中文字幕 | 麻豆国产97在线 | 欧洲 | 99久久人妻精品免费二区 | 国产三级久久久精品麻豆三级 | 黑人粗大猛烈进出高潮视频 | 国产美女极度色诱视频www | 中文字幕+乱码+中文字幕一区 | 性生交片免费无码看人 | 亚洲国产精品无码久久久久高潮 | 欧美精品无码一区二区三区 | 免费网站看v片在线18禁无码 | 亚洲综合色区中文字幕 | 国语自产偷拍精品视频偷 | 久久aⅴ免费观看 | 久久视频在线观看精品 | 亚洲国产欧美在线成人 | 97夜夜澡人人双人人人喊 | 图片小说视频一区二区 | 桃花色综合影院 | 亚洲一区av无码专区在线观看 | 久久综合色之久久综合 | 国产特级毛片aaaaaaa高清 | 国内精品一区二区三区不卡 | 高潮毛片无遮挡高清免费视频 | 熟女体下毛毛黑森林 | 中文字幕人成乱码熟女app | 好男人社区资源 | 搡女人真爽免费视频大全 | 精品国偷自产在线视频 | 国产绳艺sm调教室论坛 | 精品国产一区二区三区四区在线看 | 精品欧洲av无码一区二区三区 | 亚洲乱码日产精品bd | 久久久久成人精品免费播放动漫 | 强伦人妻一区二区三区视频18 | 国产欧美熟妇另类久久久 | 亚洲自偷精品视频自拍 | 精品国产麻豆免费人成网站 | 国产成人无码av在线影院 | 成人无码精品1区2区3区免费看 | 99久久久无码国产aaa精品 | 亚洲欧美国产精品专区久久 | 久久五月精品中文字幕 | 国产又爽又黄又刺激的视频 | 久久精品中文字幕大胸 | 精品无码成人片一区二区98 | 国产精品a成v人在线播放 | 亚洲精品国产a久久久久久 | 国产九九九九九九九a片 | 亚洲狠狠色丁香婷婷综合 | 国産精品久久久久久久 | 性欧美牲交xxxxx视频 | 天海翼激烈高潮到腰振不止 | 18精品久久久无码午夜福利 | 日本精品人妻无码77777 天堂一区人妻无码 | 成 人 网 站国产免费观看 | 强奷人妻日本中文字幕 | 欧美喷潮久久久xxxxx | 理论片87福利理论电影 | 亚洲一区二区三区国产精华液 | 亚洲 a v无 码免 费 成 人 a v | 日韩精品成人一区二区三区 | а√资源新版在线天堂 | 精品一区二区三区波多野结衣 | 天干天干啦夜天干天2017 | 日日麻批免费40分钟无码 | 亚洲精品成a人在线观看 | 成人无码影片精品久久久 | 蜜桃臀无码内射一区二区三区 | 熟妇人妻无乱码中文字幕 | 久久久中文久久久无码 | 女人色极品影院 | 国产超碰人人爽人人做人人添 | 欧美精品免费观看二区 | 亚洲一区二区三区国产精华液 | 夜夜夜高潮夜夜爽夜夜爰爰 | 强开小婷嫩苞又嫩又紧视频 | 一区二区传媒有限公司 | 激情内射日本一区二区三区 | 色欲人妻aaaaaaa无码 | 久久综合久久自在自线精品自 | 国产又粗又硬又大爽黄老大爷视 | 亚洲爆乳精品无码一区二区三区 | 一本色道婷婷久久欧美 | 中文字幕乱码亚洲无线三区 | av无码电影一区二区三区 | 中文字幕乱码亚洲无线三区 | 国产内射老熟女aaaa | 丰满人妻被黑人猛烈进入 | 内射爽无广熟女亚洲 | 精品偷拍一区二区三区在线看 | 久久99精品国产麻豆蜜芽 | 亚洲精品成人av在线 | 国产两女互慰高潮视频在线观看 | 捆绑白丝粉色jk震动捧喷白浆 | 三上悠亚人妻中文字幕在线 | 国产精品久久久 | 精品无码av一区二区三区 | 国产精品无码成人午夜电影 | 国语精品一区二区三区 | 国产av剧情md精品麻豆 | 亚洲一区二区三区在线观看网站 | 东北女人啪啪对白 | 久久亚洲a片com人成 | 国产精品爱久久久久久久 | 亚洲中文字幕在线观看 | 国语精品一区二区三区 | 真人与拘做受免费视频一 | 亚洲狠狠婷婷综合久久 | 红桃av一区二区三区在线无码av | 亚洲日韩中文字幕在线播放 | 久久国产精品二国产精品 | 免费无码一区二区三区蜜桃大 | 一本大道伊人av久久综合 | 亚洲中文字幕在线无码一区二区 | 国产人妻精品一区二区三区不卡 | 老熟妇乱子伦牲交视频 | 青草青草久热国产精品 | 性色欲情网站iwww九文堂 | 伊人久久大香线焦av综合影院 | 鲁大师影院在线观看 | 亚洲中文字幕成人无码 | 久久综合久久自在自线精品自 | 亚洲日韩中文字幕在线播放 | 97久久精品无码一区二区 | 波多野结衣aⅴ在线 | 激情国产av做激情国产爱 | 国产午夜福利亚洲第一 | v一区无码内射国产 | 色婷婷av一区二区三区之红樱桃 | 国产精品美女久久久网av | www成人国产高清内射 | 久久久国产精品无码免费专区 | 日本www一道久久久免费榴莲 | 日韩精品无码免费一区二区三区 | 亚洲国产成人av在线观看 | 亚洲综合在线一区二区三区 | 成人性做爰aaa片免费看不忠 | 亚洲精品成a人在线观看 | 精品人妻人人做人人爽 | 国产明星裸体无码xxxx视频 | 在线看片无码永久免费视频 | 强辱丰满人妻hd中文字幕 | 免费无码肉片在线观看 | 欧美喷潮久久久xxxxx | 中文字幕乱码中文乱码51精品 | 久久精品人人做人人综合 | 国精产品一品二品国精品69xx | 伦伦影院午夜理论片 | 国产乱人伦app精品久久 国产在线无码精品电影网 国产国产精品人在线视 | 无码国产乱人伦偷精品视频 | 无码人妻黑人中文字幕 | 丰满少妇女裸体bbw | 午夜福利电影 | 日韩精品无码免费一区二区三区 | 国产精品久久久久9999小说 | 日韩人妻少妇一区二区三区 | 欧美黑人乱大交 | 国产午夜亚洲精品不卡下载 | 国产精品a成v人在线播放 | 日本丰满熟妇videos | 丰满肥臀大屁股熟妇激情视频 | 成在人线av无码免观看麻豆 | 人妻互换免费中文字幕 | 中文字幕无码人妻少妇免费 | 自拍偷自拍亚洲精品被多人伦好爽 | 无码av免费一区二区三区试看 | 97精品国产97久久久久久免费 | 国产精品a成v人在线播放 | 久久天天躁夜夜躁狠狠 | 婷婷五月综合缴情在线视频 | 精品一区二区三区波多野结衣 | 国产亚洲欧美日韩亚洲中文色 | 性啪啪chinese东北女人 | 一区二区传媒有限公司 | 亚洲欧美综合区丁香五月小说 | 麻豆国产97在线 | 欧洲 | 一本一道久久综合久久 | 久久精品丝袜高跟鞋 | 亚洲综合无码久久精品综合 | 沈阳熟女露脸对白视频 | 国内精品人妻无码久久久影院蜜桃 | 天天做天天爱天天爽综合网 | 亚洲 a v无 码免 费 成 人 a v | 日本精品人妻无码免费大全 | 中文字幕无码av激情不卡 | 欧美乱妇无乱码大黄a片 | 九九综合va免费看 | 成人性做爰aaa片免费看不忠 | 国产精品亚洲一区二区三区喷水 | 国产亚洲精品久久久久久 | 久久亚洲精品成人无码 | 老头边吃奶边弄进去呻吟 | 蜜桃av蜜臀av色欲av麻 999久久久国产精品消防器材 | av无码久久久久不卡免费网站 | 成在人线av无码免费 | 99久久久无码国产aaa精品 | 久久五月精品中文字幕 | 久久亚洲中文字幕无码 | 亚洲a无码综合a国产av中文 | 色欲av亚洲一区无码少妇 | 亚洲欧洲日本综合aⅴ在线 | 欧美丰满老熟妇xxxxx性 | 亚洲精品成a人在线观看 | 免费人成在线观看网站 | 强奷人妻日本中文字幕 | 少妇高潮喷潮久久久影院 | 无码一区二区三区在线观看 | 精品久久久久久人妻无码中文字幕 | 搡女人真爽免费视频大全 | 久久人人97超碰a片精品 | 亚洲精品国偷拍自产在线观看蜜桃 | 樱花草在线社区www | 内射白嫩少妇超碰 | 日本精品久久久久中文字幕 | 国产婷婷色一区二区三区在线 | 精品无人区无码乱码毛片国产 | 日韩精品一区二区av在线 | 蜜臀av无码人妻精品 | 清纯唯美经典一区二区 | 波多野结衣aⅴ在线 | 玩弄人妻少妇500系列视频 | 国产人成高清在线视频99最全资源 | 日韩欧美中文字幕在线三区 | 十八禁视频网站在线观看 | 精品偷拍一区二区三区在线看 | 精品乱子伦一区二区三区 | 正在播放老肥熟妇露脸 | 久久97精品久久久久久久不卡 | 国产亚洲精品久久久久久 | 亚洲熟悉妇女xxx妇女av | 精品久久久久香蕉网 | 国产成人无码av片在线观看不卡 | 最新国产乱人伦偷精品免费网站 | 一本久道久久综合狠狠爱 | 国产超碰人人爽人人做人人添 | 国产乱子伦视频在线播放 | 久久久中文久久久无码 | 99久久精品午夜一区二区 | 国产精品理论片在线观看 | 无码人妻出轨黑人中文字幕 | 精品国产青草久久久久福利 | 中文字幕av无码一区二区三区电影 | 免费看男女做好爽好硬视频 | 强开小婷嫩苞又嫩又紧视频 | 亚洲一区二区观看播放 | 色综合久久久无码网中文 | 1000部夫妻午夜免费 | 亚洲理论电影在线观看 | www成人国产高清内射 | 成人无码视频在线观看网站 | 在线а√天堂中文官网 | 国产凸凹视频一区二区 | 久久www免费人成人片 | 欧美zoozzooz性欧美 | 国产超级va在线观看视频 | 亚洲国产精品一区二区美利坚 | 国产97在线 | 亚洲 | 熟女俱乐部五十路六十路av | 婷婷丁香五月天综合东京热 | 国产在热线精品视频 | 国产又爽又猛又粗的视频a片 | 天堂а√在线中文在线 | 欧美日韩视频无码一区二区三 | www一区二区www免费 | 成人av无码一区二区三区 | 亚洲日韩av一区二区三区中文 | 色窝窝无码一区二区三区色欲 | 无码免费一区二区三区 | 日本高清一区免费中文视频 | 日日夜夜撸啊撸 | 麻豆国产丝袜白领秘书在线观看 | 亚洲国产精品一区二区美利坚 | 亚洲精品一区三区三区在线观看 | 激情人妻另类人妻伦 | 成人试看120秒体验区 | 亚洲精品www久久久 | 综合激情五月综合激情五月激情1 | 国产香蕉尹人视频在线 | 久久婷婷五月综合色国产香蕉 | 精品偷拍一区二区三区在线看 | 亚洲人成人无码网www国产 | 欧美丰满熟妇xxxx | 成人免费无码大片a毛片 | 国产人妻久久精品二区三区老狼 | 黑人玩弄人妻中文在线 | 亚洲精品久久久久avwww潮水 | 玩弄少妇高潮ⅹxxxyw | 女高中生第一次破苞av | www国产精品内射老师 | 久久久久免费看成人影片 | 国产精品内射视频免费 | 国产精品久免费的黄网站 | 欧美人与禽猛交狂配 | 久久久成人毛片无码 | 99久久久国产精品无码免费 | 成人无码影片精品久久久 | 日本大香伊一区二区三区 | 全黄性性激高免费视频 | 99久久精品无码一区二区毛片 | 玩弄中年熟妇正在播放 | 一本久久a久久精品vr综合 | 天天摸天天碰天天添 | 欧洲精品码一区二区三区免费看 | 性色欲情网站iwww九文堂 | 国产美女精品一区二区三区 | 大肉大捧一进一出好爽视频 | 国产精品高潮呻吟av久久 | 一二三四在线观看免费视频 | 国产亚洲精品久久久久久国模美 | 永久免费观看国产裸体美女 | 扒开双腿疯狂进出爽爽爽视频 | 国产精华av午夜在线观看 | 欧美精品在线观看 | 人人妻人人藻人人爽欧美一区 | 亚洲第一网站男人都懂 | 免费网站看v片在线18禁无码 | 亚洲精品无码国产 | 亚洲国产精品久久久天堂 | 日本欧美一区二区三区乱码 | 99久久精品无码一区二区毛片 | 在线 国产 欧美 亚洲 天堂 | 亚洲中文字幕在线观看 | 无码av中文字幕免费放 | 中文精品久久久久人妻不卡 | 中文字幕无码乱人伦 | 国产精品亚洲综合色区韩国 | 老熟女乱子伦 | 极品尤物被啪到呻吟喷水 | 国产亚洲欧美日韩亚洲中文色 | 亚洲精品午夜无码电影网 | 午夜精品一区二区三区的区别 | 狠狠色欧美亚洲狠狠色www | 久久久久av无码免费网 | 奇米影视888欧美在线观看 | 丰满护士巨好爽好大乳 | 国产三级精品三级男人的天堂 | 丝袜美腿亚洲一区二区 | 丝袜人妻一区二区三区 | 亚洲 a v无 码免 费 成 人 a v | 综合激情五月综合激情五月激情1 | 日韩成人一区二区三区在线观看 | 亚洲精品国产a久久久久久 | 国内精品九九久久久精品 | 奇米影视7777久久精品 | aⅴ亚洲 日韩 色 图网站 播放 | 亚洲精品国产第一综合99久久 | 无遮挡国产高潮视频免费观看 | 国产偷抇久久精品a片69 | 狠狠噜狠狠狠狠丁香五月 | 成人综合网亚洲伊人 | 亚洲另类伦春色综合小说 | 人人妻人人澡人人爽精品欧美 | 一本久道高清无码视频 | 久久久婷婷五月亚洲97号色 | 国产一区二区三区精品视频 | 日本爽爽爽爽爽爽在线观看免 | 噜噜噜亚洲色成人网站 | 婷婷综合久久中文字幕蜜桃三电影 | 影音先锋中文字幕无码 | 久久久久久九九精品久 | 亚洲成在人网站无码天堂 | 97久久超碰中文字幕 | 国产偷国产偷精品高清尤物 | 日日天日日夜日日摸 | 国产欧美亚洲精品a | 欧美三级不卡在线观看 | 我要看www免费看插插视频 | 大肉大捧一进一出视频出来呀 | 亚洲国产精品美女久久久久 | 牲欲强的熟妇农村老妇女 | 亚洲男人av香蕉爽爽爽爽 | 精品人妻中文字幕有码在线 | 国产一精品一av一免费 | 日本xxxx色视频在线观看免费 | 亚洲の无码国产の无码影院 | 国产av无码专区亚洲a∨毛片 | 国产明星裸体无码xxxx视频 | 国产人妻久久精品二区三区老狼 | 中文字幕无码视频专区 | 给我免费的视频在线观看 | 久久人人97超碰a片精品 | 亚洲另类伦春色综合小说 | 国产高潮视频在线观看 | 久久综合香蕉国产蜜臀av | 午夜无码区在线观看 | 久久久久亚洲精品中文字幕 | 波多野结衣av在线观看 | 国产亚av手机在线观看 | 99久久精品国产一区二区蜜芽 | 天堂一区人妻无码 | 夜精品a片一区二区三区无码白浆 | 又紧又大又爽精品一区二区 | 亚洲自偷自拍另类第1页 | 狠狠色噜噜狠狠狠7777奇米 | 欧美日本精品一区二区三区 | 国产精品a成v人在线播放 | 精品国产一区二区三区四区 | 十八禁真人啪啪免费网站 | 国产sm调教视频在线观看 | 天天躁日日躁狠狠躁免费麻豆 | 日本高清一区免费中文视频 | 人妻中文无码久热丝袜 | 日本精品人妻无码77777 天堂一区人妻无码 | 最新版天堂资源中文官网 | 国产激情无码一区二区app | 婷婷五月综合激情中文字幕 | 亚洲综合色区中文字幕 | 精品无码av一区二区三区 | 九九在线中文字幕无码 | 成人亚洲精品久久久久软件 | a片在线免费观看 | а√天堂www在线天堂小说 | 中文字幕乱码人妻无码久久 | 少妇人妻偷人精品无码视频 | 少妇性l交大片 | 精品一区二区三区波多野结衣 | 国产欧美熟妇另类久久久 | 精品国产成人一区二区三区 | 国产又粗又硬又大爽黄老大爷视 | 999久久久国产精品消防器材 | 日本xxxx色视频在线观看免费 | 欧美日韩色另类综合 | 麻豆精产国品 | 在线天堂新版最新版在线8 | 中文字幕av日韩精品一区二区 | 在线观看国产一区二区三区 | 骚片av蜜桃精品一区 | 无码人妻丰满熟妇区五十路百度 | 性生交大片免费看l | 噜噜噜亚洲色成人网站 | 欧美日韩人成综合在线播放 | 久久婷婷五月综合色国产香蕉 | 风流少妇按摩来高潮 | 无码人妻久久一区二区三区不卡 | 久久亚洲国产成人精品性色 | 任你躁在线精品免费 | 国产午夜亚洲精品不卡 | 久久久精品欧美一区二区免费 | 亚欧洲精品在线视频免费观看 | 色 综合 欧美 亚洲 国产 | 欧美老人巨大xxxx做受 | 国产精品二区一区二区aⅴ污介绍 | 亚洲欧洲日本无在线码 | 亚无码乱人伦一区二区 | 中文字幕无码av波多野吉衣 | 中文无码精品a∨在线观看不卡 | 老子影院午夜精品无码 | 中文字幕乱妇无码av在线 | 国产高清av在线播放 | 一本久久a久久精品亚洲 | 亚洲日本va中文字幕 | 精品无人区无码乱码毛片国产 | 免费人成在线视频无码 | 久久精品中文字幕大胸 | 久久视频在线观看精品 | 久久99久久99精品中文字幕 | 中文字幕乱码人妻无码久久 | 欧美精品一区二区精品久久 | 精品国产av色一区二区深夜久久 | 色偷偷人人澡人人爽人人模 | 男女性色大片免费网站 | 成人片黄网站色大片免费观看 | 亚洲区小说区激情区图片区 | 久久亚洲精品中文字幕无男同 | 双乳奶水饱满少妇呻吟 | 中文字幕无码免费久久9一区9 | 亚洲а∨天堂久久精品2021 | 亚洲成av人影院在线观看 | 午夜成人1000部免费视频 | 亚洲日本在线电影 | 日韩亚洲欧美中文高清在线 | 中文字幕人妻丝袜二区 | 中文无码成人免费视频在线观看 | 永久免费精品精品永久-夜色 | 精品无码成人片一区二区98 | 欧美35页视频在线观看 | 无码一区二区三区在线 | 中文字幕无码免费久久99 | 精品乱子伦一区二区三区 | 牛和人交xxxx欧美 | 少妇高潮一区二区三区99 | 亚洲精品一区二区三区四区五区 | 亚洲国产精品毛片av不卡在线 | 99精品无人区乱码1区2区3区 |