• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            李錦俊(mybios)的blog

            游戲開發 C++ Cocos2d-x OpenGL DirectX 數學 計算機圖形學 SQL Server

              C++博客 :: 首頁 :: 聯系 :: 聚合  :: 管理
              86 Posts :: 0 Stories :: 370 Comments :: 0 Trackbacks

            公告

            QQ:30743734
            EMain:mybios@qq.com

            常用鏈接

            留言簿(16)

            我參與的團隊

            最新隨筆

            搜索

            •  

            積分與排名

            • 積分 - 370257
            • 排名 - 67

            最新評論

            閱讀排行榜

            評論排行榜

            Lua logo Lua 5.0 參考手冊

            作者: Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes

            Copyright ? 2003 Tecgraf, PUC-Rio. All rights reserved.

            譯者:ShiningRay Nicholas @ NirvanaStudio

            給予支持

            1 - 緒論

            Lua是一種為支持有數據描述機制的一般過程式編程語言而設計的擴展編程語言。它同樣可以對面向對象語言、函數式程序設計(Functional Programming,如Lisp)以及數據驅動編程(data-driven programming)提供很好的支持。它的目標是被用作一種強大的、輕型的配置語言。Lua目前已經被實現為一個擴展庫,是用clean C (ANSI C/C++的一個通用子集)編寫的。

            作為一個擴展語言,Lua沒有"Main"函數的概念:它僅僅是嵌入一個宿主程序進行工作,可以稱之為 嵌入式編程 或者簡單的說是 宿主編程。這個宿主程序可以調用函數來執行Lua的代碼片斷,可以設置和讀取Lua的變量,可以注冊C函數讓Lua代碼調用。Lua的能力可以擴展到更大范圍,在不同的領域內,這樣就在同樣的語法框架下創建了你自定義的編程語言。

            Lua的發行版包括一個獨立的嵌入式程序,lua,他使用Lua的擴展庫來提供一個完全的Lua解釋器。

            Lua是自由軟件,通常不提供任何擔保,如它的版權說明中敘述的那樣。 手冊中描述的實現在Lua的官方網站可以找到,www.lua.org

            如果需要知道Lua設計背后的一些決定和討論,可以參考以下論文,它們都可以在Lua的網站上找到。

            • R.?Ierusalimschy, L.?H.?de Figueiredo, and W.?Celes. Lua---an extensible extension language. Software: Practice & Experience26 #6 (1996) 635-652.
            • L.?H.?de Figueiredo, R.?Ierusalimschy, and W.?Celes. The design and implementation of a language for extending applications. Proceedings of XXI Brazilian Seminar on Software and Hardware (1994) 273-283.
            • L.?H.?de Figueiredo, R.?Ierusalimschy, and W.?Celes. Lua: an extensible embedded language. Dr. Dobb's Journal21 #12 (Dec 1996) 26-33.
            • R.?Ierusalimschy, L.?H.?de Figueiredo, and W.?Celes. The evolution of an extension language: a history of Lua, Proceedings of V Brazilian Symposium on Programming Languages (2001) B-14-B-28.

            Lua在葡萄牙語中的意思是“月亮”,發音是 LOO-ah。

            2 - 語言

            這一章將描述Lua的詞法、語法和語義結構。換句話說,這一章會講什么標記是合法的,他們是如何組合的,以及他們的組合是什么含義。

            語言結構會使用常用的擴展BNF范式來解釋,如{a}?表示0或多個a, [a]?表示a是可選的(0個或1個)。非終端字體(不能顯示的)用 斜體表示,關鍵字是粗體,其他終端符號用typewriter(等寬)字體,并用單引號引出。

            2.1 - 詞法約定

            Lua中的標識符(Identifiers)可以是任意的數字、字符和下劃線“_”,但不能以數字開頭。這條規則符合大多數編程語言中的標識符的定義。(字符的具體定義要根據系統的地區設置:任何區域設置可以認同的字母表中的字母都可以用在標識符中。)

            下面的關鍵字(keywords)為保留關鍵字不可以作為標識符出現:

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

            Lua對大小寫敏感:and是一個保留字,但是 AndAND 是兩個不一樣的、但都合法的標識符。習慣上來說,以下劃線開始且后面跟著大寫字母的標識符 (例如 _VERSION) 是為Lua內部變量所保留的。

            下面的字符(串)是其他的一些標記:

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

            字符串(Literal strings) 以單引號或者雙引號定界,同時可以包含以下C語言風格的轉義字符:

            • \a --- 鈴聲(bell)
            • \b --- 回退(backspace)
            • \f --- form feed
            • \n --- 新行(newline)
            • \r --- 回車(carriage return)
            • \t --- 水平制表符(horizontal tab)
            • \v --- 垂直制表符(vertical tab)
            • \\ --- 反斜杠(backslash)
            • \" --- 雙引號(quotation mark)
            • \' --- 單引號(apostrophe)
            • \[ --- 左方括號(left square bracket)
            • \] --- 右方括號(right square bracket)

            另外,一個 `\newline′ (一個反斜杠加上一個真正的換行符)會導致字符串內的分行。字符串中的字符也可以使用轉義字符`\ddd′通過數字值來指定。ddd 是最多為3個十進制數字的序列。Lua中的字符串也可以包含8進制數字,包括嵌入零,它可以表示為 `\0′。

            字符串也可以用雙方括號來定界[[ · · · ]]。這種括號方式的語法,字符串可以跨越多行,也可以包含嵌套的,同時不會轉義任何序列。方便起見,當開始的 `[[′ 后面緊跟著一個換行符的話,這個換行符不會包括在字符串內。舉個例子:在一個使用ASCII編碼(其中`a′ 的編碼是?97,換行符是?10,字符`1′ 是?49)的系統中,以下四種格式得到的都是同一個字符串:

                  (1)   "alo\n123\""
                  (2)   '\97lo\10\04923"'
                  (3)   [[alo
                        123"]]
                  (4)   [[
                        alo
                        123"]]
            
            

            數值常量(Numerical constants) 可以有一個可選的底數部分和一個可選的指數部分。以下是有效的數值常量:

                   3     3.0     3.1416  314.16e-2   0.31416E1
            

            注釋(Comments) 可以在任何地方出現,必須在最前面加上雙減號 (--)。如果緊接著 -- 的文本不是 [[,那么會認為是一個 短注釋(short comment), 這一行往后到行尾都是注釋。否則,會認為是一個 常注釋(long comment),注釋直到相應的 ]]結束。長注釋可以跨越多行,同時可以包含嵌套的 [[ · · · ]] 括號對。

            為了方便起見,文件的第一行如果是以#開始,這個機制允許Lua在Unix系統中用做一個腳本解釋器(見 6)。

            2.2 - 值和類型

            Lua是一種 動態類型語言(dynamically typed language)。這意味著變量是沒有類型的;只有值才有。語言中沒有類型定義。所有的值都包含他自身的類型。

            Lua中有八種基本類型:nil, boolean, number, string, function, userdata, threadtableNil 空類型只對應 nil值,他的屬性和其他任何值都有區別;通常它代表沒有有效的值。 Boolean 布爾類型有兩種不同的值 false and true。在Lua中, nil and false 代表成假條件;其他任何值都代表成真條件。 Number 數字類型表示實數(雙精度浮點數)。(構建Lua解釋器時也可以很容易地用其他內部的表示方式表示數字,如單精度浮點數或者長整型)。 String 字符串類型表示一個字符的序列。Lua 字符串可以包含8位字符,包括嵌入的 ('\0') (見 2.1)。

            函數是Lua中的 第一類值(first-class values)。也就是說函數可以保存在變量中,當作參數傳遞給其他函數,或者被當作結果返回。Lua可以調用(和處理)Lua寫的函數和C寫的函數 (見 2.5.7)。

            用戶數據類型(userdata) 提供了讓任意C數據儲存在Lua變量中的功能。這種類型直接對應著一塊內存,Lua中也沒有任何預先定義的操作,除了賦值和一致性比較。然而,通過使用 元表(metatables),程序員可以定義處理userdata的操作。(見 2.8)。 Userdata 值不能在Lua中建立或者修改,只能通過 C?API。這保證了宿主程序的數據完整性。

            線程(thread) 類型代表了相互獨立的執行線程,用來實現同步程序。

            表(table) 類型實現了聯合數組,也就是說,數組不僅可以使用數字,還能使用其他的值(除了 nil)。 而且,tables 可以是 互異的(heterogeneous),他們可以保存任何類型的值(除了 nil)。 Tables 是Lua中唯一的數據結構機制;他們可以用來表示一般數組,特征表,集合,記錄,圖,樹等等。如果要表示記錄,Lua使用字段名作為索引。語言支持 a.name 這種比較優美的表示方式,還有 a["name"]。在Lua中有幾種建立表的簡便方法 (見 2.5.6)。

            就像索引一樣,表字段的值也可以是任何類型(除了 nil)。特別需要注意地是,由于函數是第一型的值,表字段也可以包含函數。這樣表也可以支持 方法(methods) (見 2.5.8)。

            表,函數,和用戶數據類型的值都是 對象(objects):變量不會包含他們的實際值,只是一個他們的引用(references)。 賦值,參數傳遞和函數返回只是操作這些值的引用,這些操作不會暗含任何拷貝。

            庫函數 type 返回一個字符串描述給出值所表示的類型 (見 5.1)。

            2.2.1 - 類型轉換

            Lua提供運行時的數字和字符串值得自動轉換。任何對字符串的算術操作都會現嘗試把字符串轉換成數字,使用一般規則轉換。反過來,當一個數值用在需要字符串的地方時,數字會自動轉換成字符串,遵循一種合理的格式。如果要指定數值如何轉換成字符串,請使用字符串庫中的 format 函數(見 5.3)。

            2.3 - 變量

            變量是儲存值的地方。Lua中有三種不同的變量:全局變量,局部變量和表字段。

            一個名稱可以表示全局變量或局部變量(或者一個函數的正式參數,一種局部變量的特殊形式):

            	var ::= Name
            

            Lua假設變量是全局變量,除非明確地用local進行聲明 (見 2.4.7)。局部變量有 詞義范圍(lexically scoped):局部變量可以被在它們范圍內的函數自由訪問 (見 2.6)。

            在變量第一次賦值之前,它的值是 nil

            方括號用于對表進行檢索:

            	var ::= prefixexp `[′ exp `]

            第一個表達式 (prefixexp)結果必須是表;第二個表達式 (exp) 識別表中一個特定條目。給出表的表達式有一個限制語法;詳細見 2.5。

            var.NAME 語法是 var["NAME"] 的較好形式:

            	var ::= prefixexp `.′ Name
            
            

            訪問全局變量和表字段的實質可以通過元表進行改變。對索引變量 t[i] 的訪問等同于調用 gettable_event(t,i)。(關于 gettable_event 的完整描述見 2.8。這個函數并沒有在Lua中定義,也無法調用。我們在這里僅僅用來解釋原理)。

            所有的全局變量存在一個普?ǖ腖ua表中,稱之為 環境變量表(environment tables) 或簡稱 環境(environments)。由C寫的并導入到Lua中的函數 (C 函數) 全部共享一個通用 全局環境(global environment)。Lua寫的每個函數 (a Lua 函數) 都有一個它自己的環境的引用,這樣這個函數中的所有的全局變量都會指向這個環境變量表。當新創建一個函數時,它會繼承創建它的函數的環境。要改變或者獲得Lua函數的環境表,可以調用 setfenv or getfenv (見 5.1)。

            訪問全局變量 x 等同于 _env.x,又等同于

                   gettable_event(_env, "x")
            

            _env 是運行的函數的環境。(_env 變量并沒有在Lua中定義。我們這里僅僅用來解釋原理)

            2.4 - 語句

            Lua支持一種很通俗的語句集,和Pascal或者C中的很相似。他包括賦值,控制結構,過程調用,表構造和變量聲明。

            2.4.1 - 語句段

            Lua執行的最小單元稱之為一個 段(chunk)。一段語句就是簡單的語句的序列,以順序執行。每一個語句后面都可以加上一個分號(可選):

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

            Lua將語句段作為一個匿名函數 (見 2.5.8) 的本體進行處理。這樣,語句段可以定義局部變量或者返回值。

            一段語句可以儲存在文件內或者宿主程序的一個字符串中。當語句段被執行時,他首先被預編譯成虛擬機使用的字節碼,然后虛擬機用一個解釋器執行被編譯的代碼。

            語句段也可以被預編譯為二進制代碼;詳情參看 luac 程序。源代碼和編譯形態可以互相轉換;Lua自動監測文件類型然后作相應操作。

            2.4.2 - 語句塊

            一個語句塊是一系列語句;從語句構成上來看,語句塊等同于語句段:

            	block ::= chunk
            

            一個語句塊可以明確定界來替換單個語句:

            	stat ::= do block end

            顯式語句塊可以很好地控制變量的聲明范圍。顯示語句塊有時也常會在另一個語句塊的中間添加 returnbreak 語句 (見 2.4.4)。

            2.4.3 - 賦值

            Lua允許多重賦值。因此,賦值的語法定義為:等號左邊是一個變量表,右邊是一個表達式表。兩邊的表中的元素都用逗號分隔開來:

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

            我們將在 2.5 討論表達式。

            在賦值之前,值的表長度會被 調整 為和變量的表一樣。如果值比需要的多,多出的值就會被扔掉。如果值的數量不夠,就會用足夠多的 nil 來填充表直到滿足數量要求。如果表達式表以一個函數調用結束,那么在賦值之前,函數返回的所有的值都會添加到值的表中(除非把函數調用放在括號里面;見 2.5)。

            賦值語句首先計算出所有的表達式,然后才會執行賦值,所以代碼:

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

            設置 a[3] 為 20,但不影響 a[4]。因為在 a[i] 中的 i 在賦值為4之前是等于3。同樣的,下面這行:

                   x, y = y, x
            
            

            可以交換 xy 的值。

            對全局變量和表字段的賦值可以看作是通過元表進行的。對一個索引變量的賦值 t[i] = val 等同于 settable_event(t,i,val)。 (settable_event詳細介紹參看 2.8 ,Lua中并未定義該函數,他也無法直接調用。我們這里只是用它來進行解釋。)

            對全局變量的賦值 x = val 等同于賦值語句 _env.x = val,像前面也等同于:

                   settable_event(_env, "x", val)
            

            _env 是運行函數的環境。(_env 變量并未在Lua中定義。我們這里只是用來進行解釋。)

            2.4.4 - 控制結構

            控制結構 if, whilerepeat 具有通用的含義和類似的語法:

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

            Lua也有 for 語句,有兩種格式 (見 2.4.5)。

            控制結構的條件表達式 exp 可以返回任意值。falsenil 都表示假。所有其他的值都認為是真(特別要說明的:數字0和空字符串也表示真)。

            語句 return 用來從函數或者是語句段中返回一個值。函數和語句段都可以返回多個值,所以 return 語句的語法為:

            	stat ::= return [explist1]
            

            break 語句可以用來終止while, repeat 或者 for 循環的執行,直接跳到循環后面的語句。

            	stat ::= break

            break 結束最里面的一個循環。

            由于語法的原因, returnbreak 語句只能作為語句塊的 最后一個 語句。如果確實需要在語句塊的中間使用 return 或者 break,需要使用一個顯示語句塊: `do return end′ 和 `do break end′,這樣現在 returnbreak 就成為他們(內部)語句塊中的最后一個語句了。實際上,這兩種用法一般只用在調試中。

            2.4.5 - For 語句

            for 語句有兩種形式:數值形式和一般形式。

            數值形式的 for 循環根據一個控制變量用算術過程重復一語句塊。語法如下:

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

            block 語句塊根據 name 以第一個 exp 的值開始,直到他以第三個 exp 為步長達到了第二個 exp。一個這樣的 for 語句:

                   for var = e1, e2, e3 do block end
            

            等價于一下代碼:

                   do
                     local var, _limit, _step = tonumber(e1), tonumber(e2), tonumber(e3)
                     if not (var and _limit and _step) then error() end
                     while (_step>0 and var<=_limit) or (_step<=0 and var>=_limit) do
                       block
                       var = var + _step
                     end
                   end
            

            注意:

            • 三種控制表達式只會被計算一次,在循環開始之前。他們的結果必須是數值。
            • _limit_step 是不可見的變量。這里只是為了進行解釋。
            • 如果你在程序塊內給 var 賦值,結果行為將會不確定。
            • 如果沒有給出第三個表達式(步長),那么默認為1。
            • 你可以使用 break 來退出 for 循環。
            • 循環變量 var 是局部變量;你不可以在 for 循環結束之后繼續使用。如果你需要使用這個值,請在退出循環之前把它們傳給其他變量。

            for 的語句的一般形式是操作于函數之上的,稱之為迭代器(iterators)。每一個迭代過程,它調用迭代函數來產生新的值,直到新的值是 nil 。一般形式 for 循環有如下語法:

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

            一個這樣的 for 語句

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

            等同于以下代碼:

                   do
                     local _f, _s, var_1 = explist
                     local var_2, ... , var_n
                     while true do
                       var_1, ..., var_n = _f(_s, var_1)
                       if var_1 == nil then break end
                       block
                     end
                   end
            

            注意:

            • explist 只會計算一次。他的結果是一個 迭代 函數,一個 狀態,和給第一個 迭代變量的一個初始值。
            • _f_s 是不可見的變量。這里只是用來進行解釋說明。
            • 如果你在語句塊中給 var_1 賦值,那么行為就會變得不確定。
            • 你可以使用 break 來退出 for 循環。
            • 循環變量 var_i 是局部變量;你不可以在 for 循環結束之后繼續使用。如果你需要使用這個值,請在退出循環之前把它們傳給其他變量。

            2.4.6 - 語句式函數調用

            如果要忽略可能的影響,函數調用可以按照語句執行:

            	stat ::= functioncall
            

            I在這里,所有的返回值都會被忽略。函數調用將在 2.5.7 詳細解釋。

            2.4.7 - 局部變量聲明

            局部變量可以在語句塊中任何地方聲明。聲明時也可以添加一個初始賦值:

            	stat ::= local namelist [`=′ explist1]
            	namelist ::= Name {`,′ Name}
            

            如果出現初始賦值,他的語法和多重賦值語句一樣(見 2.4.3)。否則,所有的變量都會初始化為 nil

            一個語句段也是一個語句塊(見 2.4.1),所以語句段之內的任何顯式語句塊之外也可以聲明局部變量。這種局部變量在語句段結束就會銷毀。

            局部變量的可見規則會在 2.6解釋。

            2.5 - 表達式

            Lua中有以下幾種基本表達式:

            	exp ::= prefixexp
            	exp ::= nil | false | true
            
            	exp ::= Number
            	exp ::= Literal
            	exp ::= function
            	exp ::= tableconstructor
            	prefixexp ::= var | functioncall | `(′ exp `)

            數字和字符串已經在 2.1 中解釋;變量在 2.3 中解釋;函數定義在 2.5.8;函數調用在 2.5.7;表構造器在 2.5.6。

            一個用括號括起的表達式只會返回一個值。這樣,(f(x,y,z)) 將只會返回單一的一個值,即使 f 可以返回多個值,((f(x,y,z)) 的值將是 f 返回的第一個值或者如果 f 沒有返回任何值就是 nil )。

            表達式也可以使用各種算術運算符,關系運算符和邏輯運算符,下面幾節就會講到。

            2.5.1 - 算術運算符

            Lua支持常見的幾種運算符:二元 + (加), - (減), * (乘), / (除), 以及 ^ (指數運算); 一元 - (負號)。如果操作數是數字,或者是可以轉換成數字的字符串(見 2.2.1),那么所有的操作都和算術意義上的運算一致(除了指數)。指數運算其實是調用一個全局函數 __pow,否則一個合適的元方法將會被調用(見 2.8)。標準數學庫定義了函數 __pow,給出了指數運算的定義(見 5.5)。

            2.5.2 - 關系運算符

            Lua中的關系運算符有

                   ==    ~=    <     >     <=    >=
            

            這些運算只會產生 falsetrue值。

            等于 (==) 先比較操作數的類型。如果類型不一樣,結果便是 false。否則,再比較操作數的值。對象(表,用戶數據,線程,和函數)是按照引用進行比較:只有兩個對象是同一個對象的時候,才認為是相等。每次你創建一個新的對象(表,用戶數據,或者是函數)。這個新的對象將不同于前面存在的任何對象。

            你可以用"eq"元方法改變Lua比較表的方式(見 2.8)。

            2.2.1 的轉換規則 不適用 于相等比較。這樣," "0"==0 結果是 false ,同樣 t[0]t["0"] 給出的是表中不同的字段。

            而操作符 ~= 是等于 (==) 的相反的操作。

            T操作符的執行順序如下。如果兩個參數都是數字,那么它們就直接進行比較。如果,兩個參數都是字符串,那么它們的值會根據當前的區域設置進行比較。否則,Lua嘗試調用"lt"或者 "le" 元方法(見 2.8)。

            2.5.3 - 邏輯運算符

            Lua中的邏輯運算符是:

                   and   or    not
            
            

            和控制結構一樣(見 2.4.4),所有的邏輯操作符認為 falsenil 都?羌伲淥鬧刀際欽妗?

            not 操作符總是返回 falsetrue

            合取運算 and 如果第一個參數是 false 或者 nil 則返回第一個參數;否則 and 返回第二個參數。析取運算 or 如果第一個參數不是 nilfalse 則返回第一個參數,否則 or 返回第二個參數。 andor 都使用截取計算,也就是,只有有必要的情況下才計算第二個參數。例如:

                   10 or error()       -> 10
                   nil or "a"          -> "a"
                   nil and 10          -> nil
                   false and error()   -> false
                   false and nil       -> false
                   false or nil        -> nil
                   10 and 20           -> 20
            
            

            2.5.4 - 串聯接

            在Lua中字符串連接操作符是兩個點 (`..′)。如果兩邊的操作數都是字符或者數字,他們就都會按照 2.2.1的規則被轉換成字符串。否則,將調用 "concat" 元方法(見 2.8)。

            2.5.5 - 優先級

            Lua中的操作符的優先級如下表所示,從低到高優先級:

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

            表達式中,你可以使用括號來改變優先順序。串聯接符 (`..′) 和指數符 (`^′) 都是右結合的。其他二元操作都是左結合的。

            2.5.6 - 表構造器

            表構造器是創建表的表達式。當計算構造器的時候,就會創建一個新的表。構造器可以用來創建空的表,或者創建表并初始化一些字段。一般的語法如下:

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

            [exp1] = exp2 形式的每一個添加到新表中的字段條目以 exp1 為鍵并以 exp2 為值。name = exp 形式的字段,等同于 ["name"] = exp。最后,exp 形式的字段等同于 [i] = exp 其中 i 是連續的整數,從1開始。其它格式的字段不會影響它的計數。例如:

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

            等同于:

                   do
                     local temp = {}
                     temp[f(1)] = g
                     temp[1] = "x"         -- 1st exp
                     temp[2] = "y"         -- 2nd exp
                     temp.x = 1            -- temp["x"] = 1
                     temp[3] = f(x)        -- 3rd exp
                     temp[30] = 23
                     temp[4] = 45          -- 4th exp
                     a = temp
                   end
            

            如果列表中最后一個字段的形式是 exp 同時表達式又是一個函數調用,那么調用返回的所有值會依次進入列表(見 2.5.7)。如果要避免這種情況,在函數調用兩邊加上括號(見 2.5)。

            字段列表可以有一個結尾的分隔符,這個對由機器生成的列表十分方便。

            2.5.7 - 函數調用

            Lua中的一個函數調用有如下語法:

            	functioncall ::= prefixexp args
            

            在函數調用中,首先會計算 prefixexpargs 。如果 prefixexp 的值是 function 類型,那么那個函數就會被調用,同時使用給出的參數。否則,他的 "call" 元方法就會被調用,第一個參數是 prefixexp 的值,接下來是原來的調用參數(見 2.8)。

            形式

            	functioncall ::= prefixexp `:′ Name args
            

            可以用來調用“方法”("methods")。調用 v:name(...) 語法上比 v.name(v,...),要好一些,除非表達式 v 只計算一次。

            參數可以有以下幾種語法:

            	args ::= `(′ [explist1] `)′
            	args ::= tableconstructor
            	args ::= Literal
            

            所有的參數表達式都會在實際調用之前進行計算。f{...} 的調用形式在語法上較 f({...}) 要好,是因為,參數列表示一個單獨的新表。 f'...' (或者 f"..." 或者 f[[...]]) 較 f('...') 要好,是因為參數列表是一個單獨的字符串。

            因為函數可以返回任意個結果(見 2.4.4),結果的數量必須在使用它們前進行調整。如果函數按照語句進行調用(見 2.4.6),那么它的返回列表就會被調整為零個元素,這樣就舍棄了所有的返回值。如果調用函數時,他是一個表達式列表的最后一個元素,那么不會做調整(除非調用時加了括號)。

            以下是一些例子:

                   f()                -- 調整為0個結果
                   g(f(), x)          -- f() 被調整成1個結果
                   g(x, f())          -- g 獲得 x 加上f()返回的所有值
                   a,b,c = f(), x     -- f() 被調整成1個結果(此時c獲得nil值)
                   a,b,c = x, f()     -- f() 被調整為兩個結果
                   a,b,c = f()        -- f() 被調整為3個結果
                   return f()         -- 返回所有 f() 返回的值
                   return x,y,f()     -- 建立一個表包含所有 f() 返回的值
                   {f()}              -- creates a list with all values returned by f()
                   {f(), nil}         -- f() 被調整為一個結果
            
            

            如果你用括號括起調用的函數,那么它就會被調整為返回一個值。

                   return x,y,(f())   -- returns x, y, and the first value from f()
                   {(f())}            -- creates a table with exactly one element
            

            作為Lua語法自由格式的一個例外,你不能在函數調用的 `(′ 前面加入一個換行。這個限制可以避免語言中的一些二義性。如果你寫:

                   a = f
                   (g).x(a)
            

            Lua會讀作 a = f(g).x(a)。這樣,如果你想執行為兩條語句,你必須在中間加分號。如果你實際上想調用 f,你就必須刪除 (g) 前面的換行。

            return functioncall 的調用格式稱之為 尾部調用(tail call)。Lua實現了proper tail calls;在一個尾部調用中,被調用的函數將會重新使用調用程序的棧。因此,程序執行對嵌套尾部調用的次數沒有任何限制。然而,尾部調用會清楚調用函數的調試信息。注意尾部調用只有在特殊的語法中才能出現,也就是 return 只有一個函數調用作為參數,這種語法保證了調用函數確切返回被調用函數的返回值。所以,下面的例子都不是尾部調用:

              return (f(x))        -- results adjusted to 1
              return 2 * f(x)
              return x, f(x)       -- additional results
              f(x); return         -- results discarded
              return x or f(x)     -- results adjusted to 1
            

            2.5.8 - 函數定義

            函數定義的語法是:

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

            下面較好的語法簡化了函數定義:

            	stat ::= function funcname funcbody
            	stat ::= localfunction Name funcbody
            	funcname ::= Name {`.′ Name} [`:′ Name]
            
            

            語句

                   function f () ... end
            

            會被翻譯為

                   f = function () ... end
            

            語句

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

            會被翻譯為

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

            語句

                   local function f () ... end
            

            會被翻譯為

                   local f; f = function () ... end
            

            一個函數定義是一個可執行的表達式,他的類型為 函數(function) 。當Lua預編譯語句段的時候,他的函數體也會被預編譯。這樣,當Lua執行函數定義的時候,函數被 實例化封裝 closed)。這個函數實例(或閉包 closure)是表達式的最終結果。同一個函數的不同的實例可以引用不同的外部局部變量也可以有不同的環境表。

            形式參數(代表參數的變量,簡稱形參)就像用實際參數值(簡稱實參)初始化的局部變量一樣。

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

            當調用一個函數時,實參表會調整為和形參一樣的長度,除非函數是 variadic 或者 變長參數函數(vararg function)。變長參數函數在其參數列表最后有三個點 (`...′)。 變長參數函數不會對參數列表進行調整;而是,它把所有的額外實參放到一個隱含的形參 arg中。 arg 的值是一個表,包含一個字段?`n′ 表示額外參數的個數,位置 1,?2,?...,?n是額外的參數。

            請思考以下函數定義的例子:

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

            然后,我們有以下實參到形參的對應關系:

                   CALL            PARAMETERS
            
                   f(3)             a=3, b=nil
                   f(3, 4)          a=3, b=4
                   f(3, 4, 5)       a=3, b=4
                   f(r(), 10)       a=1, b=10
                   f(r())           a=1, b=2
            
                   g(3)             a=3, b=nil, arg={n=0}
                   g(3, 4)          a=3, b=4,   arg={n=0}
                   g(3, 4, 5, 8)    a=3, b=4,   arg={5, 8; n=2}
                   g(5, r())        a=5, b=1,   arg={2, 3; n=2}
            

            結果使用 return 語句返回(見 2.4.4)。如果控制到達了函數尾部而沒有遇到 return 語句,那么函數沒有返回值。

            冒號(:) 語法是用來定義 methods 的,也就是,函數有一個隱含的額外參數 self. 。這樣,語句:

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

            相對以下是較好的形式:

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

            2.6 - 可見性規則

            Lua是一個有詞法范圍的語言。變量的范圍從聲明語句后的第一個語句開始到包含聲明的最內部的語句塊為止。例如:

              x = 10                -- global variable
              do                    -- new block
                local x = x         -- new `x', with value 10
                print(x)            --> 10
                x = x+1
                do                  -- another block
                  local x = x+1     -- another `x'
                  print(x)          --> 12
                end
                print(x)            --> 11
              end
              print(x)              --> 10  (the global one)
            
            

            注意:在類似 local x = x,正在聲明的新的 x 尚未進入范圍,所以第二個 x 指代的是外面的變量。

            由于詞法范圍的規則,在局部變量的范圍內定義的函數可以任意訪問這些變量。例如:

              local counter = 0
              function inc (x)
                counter = counter + x
                return counter
              end
            

            內部函數使用的局部變量在函數內部稱之為 上值(upvalue),或者 外局部變量(external local variable)

            注意每個 local 語句執行時會定義一個新的局部變量。看以下例子:

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

            循環產生了十個閉包(也就是,十個匿名函數的實例)。每個閉包使用不同的 y 變量,但他們共享同一個 x 變量。

            2.7 - 錯誤處理

            因為Lua是一個擴展語言,所有的Lua動作都是從宿主程序中調用Lua庫中函數的C代碼開始的(見 3.15)。無論錯誤發生在Lua編譯過程時或執行時,控制返回C,然后可以做相應的處理(比如打印一個錯誤)。

            Lua代碼可以通過調用error函數來產生一個錯誤(見 5.1)。如果你要在Lua中捕獲錯誤,你可以使用 pcall 函數(見 5.1)。

            2.8 - 元表 (Metatables)

            Lua中的每一個表和用戶數據都可以擁有一個 元表(metatable)。這個 元表 是一個普通的Lua表,定義了在特定操作下原始表和用戶數據的行為。你可以通過設置一個對象的元表中的特定字段來更改它某些方面的行為。例如,當一個對象是一個加法的操作數時,Lua檢查它的元表中的 "__add" 字段是不是一個函數。如果是,Lua調用它來執行加法。

            我們稱元表中的鍵(字段名,key)為 事件(events) ,值為 元方法(metamethods)。在上一個例子中, "add" 是事件,執行加法的函數是元方法。

            你可以通過 set/getmetatable 函數來查詢和更改一個對象的元表(見 5.1)。

            元表可以控制對象在算術操作、比較、串連接、索引取值中如何運行。元表也可以定義一個函數當收集內存垃圾時調用。每一個操作這里Lua都用一個特定的鍵關聯,稱之為事件。當Lua對一個表或是一個用戶數據執行上面中的一個操作時,它先檢查元表控制的操作已經羅列在下面。每個操作有一個相應的名稱,代表了他的含義。他們在元表中的鍵是由名稱前加上兩條下劃線;如,操作 "add" 的鍵是 "__add"。這些操作的語義

            這里給出的Lua代碼僅僅是說明性的;真正的行為是硬編碼在解釋器中的,比下面的的模擬的效率要高很多。描述中用到的函數 (rawget, tonumber, 等等) 在 5.1 中會對他們進行描述。特別地,要獲得一個給定對象的元方法,我們使用這個表達式:

              metatable(obj)[event]
            

            這個要讀作:

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

            也就是,訪問元方法時不會調用其它元方法,同時調用沒有元表的對象不會出錯(它返回一個 nil值)。

            • "add": + 加法操作。

              下面的 getbinhandler 函數定義了Lua如何給一個二元操作選擇一個處理器。首先,Lua嘗試第一個操作數。如果它的類型沒有定義這個操作的處理器,那么然后Lua嘗試第二個操作數。

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

              利用該函數,op1 + op2 的行為方式可看作是

               function add_event (op1, op2)
                 local o1, o2 = tonumber(op1), tonumber(op2)
                 if o1 and o2 then  -- both operands are numeric?
                   return o1 + o2   -- `+' here is the primitive `add'
                 else  -- at least one of the operands is not numeric
                   local h = getbinhandler(op1, op2, "__add")
                   if h then
                     -- call the handler with both operands
                     return h(op1, op2)
                   else  -- no handler available: default behavior
                     error("...")
                   end
                 end
               end
              
            • "sub": - 操作。行為方式類似 "add" 操作。
            • "mul": * 操作。行為方式類似 "add" 操作。
            • "div": / 操作。行為方式類似 "add" 操作。
            • "pow": ^ (指數) 操作

               function pow_event (op1, op2)
                 local o1, o2 = tonumber(op1), tonumber(op2)
                 if o1 and o2 then  -- both operands are numeric?
                   return __pow(o1, o2)   -- call global `__pow'
                 else  -- at least one of the operands is not numeric
                   local h = getbinhandler(op1, op2, "__pow")
                   if h then
                     -- call the handler with both operands
                     return h(op1, op2)
                   else  -- no handler available: default behavior
                     error("...")
                   end
                 end
                end
              
            • "unm": 一元取負 - 操作。

               function unm_event (op)
                 local o = tonumber(op)
                 if o then  -- operand is numeric?
                   return -o  -- `-' here is the primitive `unm'
                 else  -- the operand is not numeric.
                   -- Try to get a handler from the operand
                   local h = metatable(op).__unm
                   if h then
                     -- call the handler with the operand and nil
                     return h(op, nil)
                   else  -- no handler available: default behavior
                     error("...")
                   end
                 end
               end
              
            • "concat": .. (串連接)操作。

               function concat_event (op1, op2)
                 if (type(op1) == "string" or type(op1) == "number") and
                    (type(op2) == "string" or type(op2) == "number") then
                   return op1 .. op2  -- primitive string concatenation
                 else
                   local h = getbinhandler(op1, op2, "__concat")
                   if h then
                     return h(op1, op2)
                   else
                     error("...")
                   end
                 end
               end
              
            • "eq": == 操作。函數 getcomphandler 定義了Lua是如何為比較操作選擇一個元方法的。只有當參與比較的兩個對象屬于同一類型而且需要的元方法一樣時,才會選擇這個元方法。

               function getcomphandler (op1, op2, event)
                 if type(op1) ~= type(op2) then return nil end
                 local mm1 = metatable(op1)[event]
                 local mm2 = metatable(op2)[event]
                 if mm1 == mm2 then return mm1 else return nil end
               end
              

              事件如下定義:

               function eq_event (op1, op2)
                 if type(op1) ~= type(op2) then  -- different types?
                   return false   -- different objects
                 end
                 if op1 == op2 then   -- primitive equal?
                   return true   -- objects are equal
                 end
                 -- try metamethod
                 local h = getcomphandler(op1, op2, "__eq")
                 if h then
                   return h(op1, op2)
                 else
                   return false
                 end
               end
              

              a ~= b is equivalent to not (a == b).

            • "lt": < 操作。

               function lt_event (op1, op2)
                 if type(op1) == "number" and type(op2) == "number" then
                   return op1 < op2   -- numeric comparison
                 elseif type(op1) == "string" and type(op2) == "string" then
                   return op1 < op2   -- lexicographic comparison
                 else
                   local h = getcomphandler(op1, op2, "__lt")
                   if h then
                     return h(op1, op2)
                   else
                     error("...");
                   end
                 end
               end
              
              

              a > b is equivalent to b < a.

            • "le": <= 操作。

               function le_event (op1, op2)
                 if type(op1) == "number" and type(op2) == "number" then
                   return op1 <= op2   -- numeric comparison
                 elseif type(op1) == "string" and type(op2) == "string" then
                   return op1 <= op2   -- lexicographic comparison
                 else
                   local h = getcomphandler(op1, op2, "__le")
                   if h then
                     return h(op1, op2)
                   else
                     h = getcomphandler(op1, op2, "__lt")
                     if h then
                       return not h(op2, op1)
                     else
                       error("...");
                     end
                   end
                 end
               end
              

              a >= b is equivalent to b <= a. Note that, in the absence of a "le" metamethod, Lua tries the "lt", assuming that a <= b is equivalent to not (b < a).

            • "index": 通過索引訪問 table[key]

               function gettable_event (table, key)
                 local h
                 if type(table) == "table" then
                   local v = rawget(table, key)
                   if v ~= nil then return v end
                   h = metatable(table).__index
                   if h == nil then return nil end
                 else
                   h = metatable(table).__index
                   if h == nil then
                     error("...");
                   end
                 end
                 if type(h) == "function" then
                   return h(table, key)      -- call the handler
                 else return h[key]          -- or repeat operation on it
               end
              
            • "newindex": 給表的索引賦值 table[key] = value

               function settable_event (table, key, value)
                 local h
                 if type(table) == "table" then
                   local v = rawget(table, key)
                   if v ~= nil then rawset(table, key, value); return end
                   h = metatable(table).__newindex
                   if h == nil then rawset(table, key, value); return end
                 else
                   h = metatable(table).__newindex
                   if h == nil then
                     error("...");
                   end
                 end
                 if type(h) == "function" then
                   return h(table, key,value)    -- call the handler
                 else h[key] = value             -- or repeat operation on it
               end
              
              
            • "call": 當Lua調用某個值時調用。

               function function_event (func, ...)
                 if type(func) == "function" then
                   return func(unpack(arg))   -- primitive call
                 else
                   local h = metatable(func).__call
                   if h then
                     return h(func, unpack(arg))
                   else
                     error("...")
                   end
                 end
               end
              

            2.9 - 垃圾收集

            Lua 會自動進行內存管理。這意味著你不需要擔心新對象的內存分配問題,也不需要釋放不用的對象。Lua 通過不斷地運行 垃圾收集器 收集 dead objects (也就是那些Lua中無法訪問的對象)來自動管理內存。Lua中所有的對象都是自動管理的目標:表,用戶數據,函數,線程,和字符串。Lua使用兩個數字控制垃圾收集循環。一個數字表示Lua使用的動態內存的字節數,另一個是閥值。當內存字節數到達閥值時,Lua就運行垃圾收集器,來釋放死對象的空間。一旦字節計數器被調整,那么閥值就會被設為字節計數器新值的兩倍。

            通過C API,你可以查詢和更改閥值(見 3.7)。將閥值設為零時會強制立刻進行垃圾收集,同時把他設為足夠大就可以停止垃圾收集。僅使用Lua代碼中的 gcinfocollectgarbage 函數 (見 5.1)可以獲得一定程度上對垃圾收集循環的控制。

            2.9.1 - 垃圾收集元方法 (Garbage-Collection Metamethods)

            使用 C?API,你可以對用戶數據設置一個垃圾收集元方法(見 2.8)。這些元方法也稱為 終結器(finalizers)。終結器允許你用外部的資源管理來調整Lua的垃圾收集(如關閉文件,網絡或數據庫連接,或者釋放你自己的內存。

            用元表中包含 __gc 字段的自由用戶數據不會立即被垃圾收集器回收。而是,Lua把它們放在一個列表中。收集完畢之后,Lua會對這個列表中的用戶數據執行和以下函數相等的操作:

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

            在每個垃圾收集過程最后,調用用戶數據的終結器的順序,將按照他們在收集過程中添加到列表中的相反順序進行。也就是,第一個被調用的終結器是和在程序中創建的最后一個用戶數據相關的那個終結器。

            2.9.2 - 弱表

            一個 弱表(weak table) 是一個包含的元素是 弱引用(weak references)的表。垃圾收集器會忽略弱引用。換句話說,如果指向一個對象的引用只有弱引用,那么這個對象還是要被垃圾收集器回收。

            弱表可以包含弱的鍵,弱的值,或者兩者皆有。一個包含弱鍵的表允許它的鍵被回收,但值不可以。一個同時包含弱鍵和弱值的表允許鍵和值的回收。無論哪種情況,只要鍵或者值中的一個被回收了,那么這一對鍵值將會從表中刪除。這個表的弱屬性是由它的元表的 __mode 字段控制的。如果 __mode 字段是一個包含字符?`k′的字符串,那么表中的鍵是弱鍵。如果 __mode 字段是一個包含字符 `v′ 的字符串,那么表中的值是弱值。

            在你將表用作元表之后,你不應該更改 __mode 字段的值。否則,這個元表控制的表的弱表行為將會不確定。

            2.10 - 同步程序

            Lua支持同步程序,也稱為 半同步程序(semi-coroutines)協同多線程(collaborative multithreading)。Lua中的一個同步程序代表了一個獨立的執行線程。然而,不像在多線程系統中的線程那樣,一個同步程序只有在調用了一個yield(產生結果)函數才能掛起它的執行。

            你可以調用 coroutine.create 來創建一個同步程序。它唯一的一個參數是一個函數,代表同步程序的主函數。create 函數僅僅建立一個新的同步程序然后返回一個它的句柄 (一個線程 thread 類型的對象);它不會啟動該同步程序。

            當你第一次調用 coroutine.resume,將 coroutine.create 返回的線程對象作為第一個參數傳遞給它,然后同步程序就啟動了,從它的主函數的第一行開始。傳給 coroutine.resume 的額外的參數會作為同步程序主函數的參數傳遞過去。在同步程序開始執行之后,它一直運行到它結束或產生結果。

            一個同步程序通過兩種方式結束它的運行:正常情況下,當它的主函數返回(顯式地或隱式的,在最后一個指令之后)時結束;異常地,如果有未保護的錯誤。第一各情況下,coroutine.resume 返回 true,加上同步程序主函數返回的其它值。在有錯誤的情況下,coroutine.resume 返回 false ,并附上錯誤信息。

            一個同步程序通過調用 coroutine.yield 來產生結果。當一個同步程序產生結果,相應的 coroutine.resume 就立刻返回,即使操作發生在嵌套函數調用中(也就是,不在主函數中,而在被主函數直接或間接調用的函數中)。在這種情況下, coroutine.resume 也返回 true,以及傳給 coroutine.yield。的所有參數。下次你繼續同一個同步程序時,它會從它原來yield的地方繼續執行,而 coroutine.yield 將返回給主程序傳給 coroutine.resume 的額外參數。

            coroutine.wrap 函數創建一個和 coroutine.create 一樣的同步程序,但它不返回同步程序本身,而是返回一個繼續同步程序的函數(當調用的時候)。傳遞給這個函數的參數作為繼續resume的額外參數。函數將返回resume返回的所有值,出除了第一個(布爾值的錯誤代碼)。不像 coroutine.resume,這個函數不捕獲錯誤;出現任何錯誤都傳回給調用者。

            請考慮以下例子:

            function foo1 (a)
              print("foo", a)
              return coroutine.yield(2*a)
            end
            
            co = coroutine.create(function (a,b)
                  print("co-body", a, b)
                  local r = foo1(a+1)
                  print("co-body", r)
                  local r, s = coroutine.yield(a+b, a-b)
                  print("co-body", r, s)
                  return b, "end"
            end)
                   
            a, b = coroutine.resume(co, 1, 10)
            print("main", a, b)
            a, b, c = coroutine.resume(co, "r")
            print("main", a, b, c)
            a, b, c = coroutine.resume(co, "x", "y")
            print("main", a, b, c)
            a, b = coroutine.resume(co, "x", "y")
            print("main", a, b)
            

            當你運行它的時候,它會產生以下輸出結果:

            co-body 1       10
            foo     2
            main    true    4
            co-body r
            main    true    11      -9
            co-body x       y
            main    true    10      end
            main    false   cannot resume dead coroutine
            
            

            3 - 應用程序接口

            這一節描述Lua中的C API,這是對于宿主程序可用的C函數集合,用以和Lua通訊。所有的API函數及其相關類型和常量都聲明在頭文件lua.h中。

            即便每次我都使用“函數”這個詞,任何設施在API里面都可能被一個宏所替代。所有這些宏(macro)都只使用一次它的參數(除了第一個參數、這個每次總是一個Lua狀態),所以不會產生隱藏的副作用。

            3.1 - 狀態

            Lua庫是可重入的(reentrant)的:它沒有全局變量。整個Lua解釋器的狀態(全局變量、棧、等等)儲存在一個動態分配的 lua_State 結構類型中。一個指向這個狀態的指針必須作為庫中每一個函數的第一個參數,除了 lua_open 這個函數。該函數從最開始創建一個Lua狀態。

            在調用任何API函數之前,你必須通過調用 lua_open 創建一個狀態:

                   lua_State *lua_open (void);
            

            調用 lua_close 去釋放這個由 lua_open 創建的狀態:

                   void lua_close (lua_State *L);
            

            這個函數銷毀所有被給予Lua狀態的對象(調用相應的垃圾收集元方法)并且釋放那個狀態使用的所有動態內存。在個別的平臺上,你或許不需要調用這個函數,因為當宿主程序結束的時候會自然的釋放所有的資源。另一方面,長時間運行的程序,像一些守護進程或者Web服務器,可能需要立即釋放那些不需要的狀態資源,以避免占用太多內存。

            3.2 - 堆棧和索引

            Lua使用一個來自于C語言的 虛擬棧(virtual stack) 傳遞值。棧里面的每一個元素都代表一個Lua值 (nil, number, string, etc.)。

            只要Lua調用C語言函數,這個所調用的函數將得到一個新的棧,這個棧將獨立于先前的棧以及那些仍然活躍的C函數的棧。這個棧最初包含了C函數的所有參數,并且這也會存放C函數的返回值(見 3.16)。

            為了方便起見,大多數查詢操作的API不需要遵守一個嚴格的棧定義(注:即不需要遵循FILO)。他們可以使用 索引(index) 引用任何棧中元素:一個正數索引代表了棧中的絕對位置(從1開始);一個負數索引代表了從棧頂的偏移量。更特別的是,如果棧有 n 個元素,那么索引 1 代表第一個元素(這就是說,這個元素首先入棧)并且索引 n 代表了最后一個元素;索引 -1 也代表了最后一個元素(也就是棧頂)并且索引 -n 代表了第一個元素。我們說一個索引存在于 1 和棧頂之間是有效的,換句話說,如果 1 <= abs(index) <= top

            在任何時間里,你可以調用 lua_gettop 得到棧頂元素的索引:

                   int lua_gettop (lua_State *L);
            

            因為索引從 1 開始,lua_gettop 的結果等于棧中的元素數量(如果是0就意味著棧為空)。

            當你與Lua API交互的時候,你有責任控制堆棧以避免溢出。。這個函數

                   int lua_checkstack (lua_State *L, int extra);
            

            使棧的大小增長為 top + extra 個元素;如果無法將棧增加到那個大小將返回false。這個函數從不對棧進行收縮;如果棧已經比新的大小更大,它將不產生任何作用那個。

            只要Lua調用C 函數,它必須至少保證 LUA_MINSTACK 這個棧中的位置是可用的。LUA_MINSTACK 定義在 lua.h 中,它的值是 20,所以你不需要總擔心棧空間除非你的代碼通過循環將元素壓入棧。

            大多數插敘函數接受指向有效棧空間的索引,那就是說,索引達到棧空間的最大值是你需要使用 lua_checkstack。這樣的索引稱為可接受索引(acceptable indices)。更正規的說法,我們給出一個嚴格的定義如下:

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

            注意,0永遠不是一個可接受索引。

            除非另外說明,任何函數接受有效索引可以被稱為是 偽索引(pseudo-indices),這些索引代表一些Lua值可以被C 代碼訪問但是卻不存在于棧中。假索引通常用于訪問全局環境變量,注冊表,和一個C 函數的上值(見 3.17)。

            3.3 - 堆棧操作

            一下的API提供了基本的棧操作:

                   void lua_settop    (lua_State *L, int index);
                   void lua_pushvalue (lua_State *L, int index);
                   void lua_remove    (lua_State *L, int index);
                   void lua_insert    (lua_State *L, int index);
                   void lua_replace   (lua_State *L, int index);
            

            lua_settop 接受任何可接受的索引,或者0,并且將該索引設置為棧頂。如果新的棧頂比舊的更大,那么新元素被填上 nil 值。如果索引為 0,那么所有棧元素會被清除。在 lua.h 里面定義了一個有用的宏

                   #define lua_pop(L,n)   lua_settop(L, -(n)-1)
            

            用以從棧中彈出 n 個元素。

            lua_pushvalue 將一個索引指向的元素的拷貝壓入棧。 lua_remove 刪除指定位置的元素,將該元素上方的所有元素下移以填滿空缺。lua_insert 將棧頂元素移動到指定位置,將該位置以上的元素上移。lua_replace 將棧頂元素移動到指定位置而不移動其他任何其他元素(因此替代了給定位置的元素的值)。所有這些函數只接受有效的索引。(你不能使用偽索引調用 lua_removelua_insert,因為他們不代表棧中的位置。)

            舉個例子,如果棧開始于 10 20 30 40 50*(自底向上;`*′ 標記了棧頂),那么:

                   lua_pushvalue(L, 3)    --> 10 20 30 40 50 30*
                   lua_pushvalue(L, -1)   --> 10 20 30 40 50 30 30*
                   lua_remove(L, -3)      --> 10 20 30 40 30 30*
                   lua_remove(L,  6)      --> 10 20 30 40 30*
                   lua_insert(L,  1)      --> 30 10 20 30 40*
                   lua_insert(L, -1)      --> 30 10 20 30 40*  (no effect)
                   lua_replace(L, 2)      --> 30 40 20 30*
                   lua_settop(L, -3)      --> 30 40*
                   lua_settop(L,  6)      --> 30 40 nil nil nil nil*
            
            

            3.4 - 堆棧查詢

            下面的函數可以用來檢測棧內元素的類型:

                   int lua_type            (lua_State *L, int index);
                   int lua_isnil           (lua_State *L, int index);
                   int lua_isboolean       (lua_State *L, int index);
                   int lua_isnumber        (lua_State *L, int index);
                   int lua_isstring        (lua_State *L, int index);
                   int lua_istable         (lua_State *L, int index);
                   int lua_isfunction      (lua_State *L, int index);
                   int lua_iscfunction     (lua_State *L, int index);
                   int lua_isuserdata      (lua_State *L, int index);
                   int lua_islightuserdata (lua_State *L, int index);
            

            這些函數只能使用可接受的索引。

            lua_type 返回棧中元素值的類型,如果所有索引無效則返回 LUA_TNONE(就是說如果棧為空)。這些lua_type 代表的返回值作為常量定義在 lua.h 中:LUA_TNIL, LUA_TNUMBER, LUA_TBOOLEAN, LUA_TSTRING, LUA_TTABLE, LUA_TFUNCTION, LUA_TUSERDATA, LUA_TTHREAD, LUA_TLIGHTUSERDATA。下面的函數將這些常量轉換成字符串:

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

            lua_is* 函數返回 1 當對象與所給類型兼容的時候,其他情況返回 0。 lua_isboolean 是一個例外:它只針對布爾值時才會成功(否則將是無用的,因為任何值都是一個布爾值)。這些函數對于無效引用返回 0。 lua_isnumber 接受數字和用數字表示的字符串;lua_isstring 接受字符串和數字(見 2.2.1);lua_isfunction 接受Lua函數和C函數; lua_isuserdata 接受完整的和輕量的用戶數據。要區分C 函數和Lua 函數,你可以使用 lua_iscfunction。要區分用戶數據,你可以使用 lua_islightuserdata。要區分數字還是用數字表示的字符串,你可以使用 lua_type

            這些API還包含了用于比較棧中的兩個值的操作:

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

            lua_equallua_lessthan 在比較他們的副本的時候是等效的(見 2.5.2)。 lua_rawequal 用于比較基本類型但不包括元方法。如果有任何形式的無效索引,這些函數都返回 0(false)。

            3.5 - 堆棧取值

            為了將一個棧中的值轉變為指定的C語言類型,你需要使用以下的轉換函數:

                   int            lua_toboolean   (lua_State *L, int index);
                   lua_Number     lua_tonumber    (lua_State *L, int index);
                   const char    *lua_tostring    (lua_State *L, int index);
                   size_t         lua_strlen      (lua_State *L, int index);
                   lua_CFunction  lua_tocfunction (lua_State *L, int index);
                   void          *lua_touserdata  (lua_State *L, int index);
                   lua_State     *lua_tothread    (lua_State *L, int index);
                   void          *lua_topointer   (lua_State *L, int index);
            

            這些函數由任何可接受索引作為參數進行調用。當遇到一個無效索引,函數表現為就好像接受了一個錯誤類型的值。

            lua_toboolean 將索引指向的Lua值轉換為C語言類型的布爾值(0 或 1)。就像所有Lua中的測試一樣,任何不等于 false 或者 nil 的Lua值通過 lua_toboolean 都將返回 1;否則將返回 0。當然,如果是一個無效索引,也將返回 0。(如果你只想接受真實的布爾值,使用 lua_isboolean 去測試值的類型。)

            lua_tonumber 將索引指向的Lua值轉換成一個數字(默認情況下,lua_Numberdouble類型)。Lua值必須是一個數字或者可轉化為數字的字符串(見 2.2.1);否則,lua_tonumber 返回 0。

            lua_tostring 將索引指向的Lua值轉換成字符串(const char*)。Lua值必須是一個字符串或者數字;否則,函數返回 NULL。如果值是一個數字,lua_tostring 會將棧中的真實值變成一個字符串類型。(當 lua_tostring 應用于鍵時這個改變將引起 lua_next 的混亂。)lua_tostring 在Lua 狀態內部返回一個字符串的指針。這個字符串總是以 0('\0')結尾,就像C 語言里的一樣,但是也可能包含其他 0 在其中。如果你不知道一個字符串中是否存在 0 ,你可以使用 lua_strlen 得到它的實際長度。因為Lua具有垃圾收集機制,所以不能保證 lua_tostring 返回的指針仍然有效,當相應的值從棧中刪除之后。如果你在當前函數返回之后還需要這個字符串,你需要復制它并且將它存入注冊表(見 3.18)。

            lua_tocfunction 將棧中的值轉換為C 函數。這個值必須是一個C 函數;否則,lua_tocfunction 返回 NULL。類型 lua_CFunction3.16 中有詳細解釋。

            lua_tothread 將棧中的值轉換為Lua線程(被描繪成 lua_State *)。這個值必須是一個線程;否則;lua_tothread 返回 NULL

            lua_topointer 將棧中?鬧底晃ㄓ玫腃 語言指針(void *)。這個值可能是一個用戶數據、表、線程、或者函數;否則,lua_topointer 返回 NULL。Lua保證同種類型的不同對象將返回不同指針。沒有直接的方法將指針轉換回原來的值。這個函數通常用于調試。

            lua_touserdata3.8 中有詳細解釋。

            3.6 - 將值壓入堆棧

            以下的API函數將C 語言值壓入棧:

                   void lua_pushboolean       (lua_State *L, int b);
                   void lua_pushnumber        (lua_State *L, lua_Number n);
                   void lua_pushlstring       (lua_State *L, const char *s, size_t len);
                   void lua_pushstring        (lua_State *L, const char *s);
                   void lua_pushnil           (lua_State *L);
                   void lua_pushcfunction     (lua_State *L, lua_CFunction f);
                   void lua_pushlightuserdata (lua_State *L, void *p);
            

            這些函數接受一個C 語言值,將其轉換成相應的Lua 值,并且將結果壓入棧。需要特別注意的是,lua_pushlstringlua_pushstring 將對所給的字符串做一個內部拷貝。lua_pushstring 只能壓入合適的C 語言字符串(也就是說,字符串要以 '\0' 結尾,并且不能包含內嵌的 0);否則,你需要使用更通用的 lua_pushlstring 函數,它可以接受一個指定的大小。

            你可以壓入“格式化的”字符串:

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

            這些函數將格式化的字符串壓入棧并且返回這個字符串的指針。它們和 sprintfvsprintf 類似,但是有一些重要的不同之處:

            • 你不需要為結果分配空間:結果是Lua字符串并且Lua會關心內存分配問題(和內存釋放問題,通過垃圾收集機制)。
            • 轉換受到限制。這里沒有標志、寬度或精度。轉換操作的修飾符可以是簡單的`%%′(在字符串中插入一個`%′),`%s′(插入一個沒有大小限制的以 0 結尾的字符串),`%f′(插入一個 lua_Number),`%d′(插入一個 int),`%c′(插入一個 int 作為一個字符)。

            這個函數

                   void lua_concat (lua_State *L, int n);
            

            連接棧頂的 n 個值,將它們彈出,并且將結果留在棧頂。如果 n 為 1,結果是單個字符串(也就是說,函數什么也不做);如果 n 是 0,結果是空字符串。連接的完成依據Lua的語義(見 2.5.4)。

            3.7 - 控制垃圾收集

            Lua使用兩個數字控制垃圾收集循環。一個數字表示Lua使用的動態內存的字節數,另一個是閥值。(見 2.9)。一個數字表示Lua使用的動態內存的字節數,另一個是閥值。當內存字節數到達閥值時,Lua就運行垃圾收集器,來釋放死對象的空間。一旦字節計數器被調整,那么閥值就會被設為字節計數器新值的兩倍。

            你可以通過以下的函數得到這兩個量的當前值:

                   int  lua_getgccount     (lua_State *L);
                   int  lua_getgcthreshold (lua_State *L);
            

            它們的返回值的單位都是千字節(K bytes)。你可以通過下面的函數改變閥值

                   void  lua_setgcthreshold (lua_State *L, int newthreshold);
            
            

            然后,新的閥值得單位也是千字節。當你調用這個函數,Lua設置閥新值并且和字節計數器作比較。如果新的閥值小于字節計數器,Lua將立刻運行垃圾收集器。特別是 lua_setgcthreshold(L,0) 強迫進行垃圾收集。在這之后,一個新值根據先前的規則被設置。

            3.8 - 用戶數據類型 (Userdata)

            用戶數據代表了Lua中使用的C語言值。Lua支持兩種用戶數據:完整用戶數據(full userdata)輕量用戶數據(light userdata)

            一個完整用戶數據代表了一塊內存。它是一個對象(像一個表):你必須創建它,它有自己的元表,當它被回收的時候你可以檢測到。一個完整用戶數據只能與自己相等(基于原始的相等規則)。

            一個輕量用戶數據代表一個指針。它是?桓鮒擔ㄏ褚桓鍪鄭耗悴⒚揮寫唇ㄋ裁揮性懟ⅲ荒鼙換厥眨ㄒ蛭游幢淮唇ǎG崍坑沒菹嗟鵲奶跫侵剛脛趕虻牡刂廢嗤?

            在Lua 代碼里,沒辦法測試用戶數據類型是完整的還是輕量的;兩者都是 用戶數據類型。在C 代碼里,如果是完整用戶數據,lua_type 返回 LUA_TUSERDATA,反之,返回 LUA_TLIGHTUSERDATA

            你可以通過下面的函數創建完整用戶數據:

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

            這個函數根據指定大小分配一個內存塊,將用戶數據的地址壓入棧并且返回這個地址。

            要將輕量用戶數據壓入棧,你需要使用 lua_pushlightuserdata(見 3.6)。

            lua_touserdata (見 3.5)用來取回用戶數據的值。當你用在完整用戶數據的時候,它返回這個塊的地址,當你用在輕量用戶數據的時候,它返回它的指針,當你用在非用數據的時候,返回 NULL

            當Lua回收一個完整用戶數據,它調用該用戶數據的 gc 元方法,然后釋放該用戶數據相應的內存。

            3.9 - 元表 (Metatables)

            下面的函數允許你操作對象的元表:

                   int lua_getmetatable (lua_State *L, int index);
                   int lua_setmetatable (lua_State *L, int index);
            

            lua_getmetatable 將所給對象的元表壓入棧。如果索引無效,或這個對象不含有元表,該函數返回 0 并且不對棧進行任何操作。

            lua_setmetatable 從棧中彈出一張表并且為所給對象設置一個新的元表。當無法給所給對象設置元表的時候該函數返回 0(也就是說,這個對象既不是一個用戶數據也不是一張表);盡管那樣,它仍從棧中彈出這張表。

            3.10 - 加載Lua語句段

            你可以通過 lua_load 加載一個Lua塊:

                   typedef const char * (*lua_Chunkreader)
                                            (lua_State *L, void *data, size_t *size);
            
                   int lua_load (lua_State *L, lua_Chunkreader reader, void *data,
                                               const char *chunkname);
            

            lua_load 的返回值是:

            • 0 --- 沒有錯誤
            • LUA_ERRSYNTAX --- 預編譯時句法錯誤
            • LUA_ERRMEM --- 內存分配錯誤

            如果沒有錯誤,lua_load 將編譯過的語句段作為Lua 函數壓入棧頂。否則,它將壓入一個錯誤信息。

            lua_load 自動檢測語句段的類型是文本還是二進制數據,并且根據類型將其載入(見程序 luac)。

            lua_load 使用一個用戶提供的 reader 函數讀取語句段的內容。當需要調用其它段時,lua_load 調用 reader,傳遞其 data 參數。必須返回指向語句段所在的新內存塊的指針,并將段大小設置為 0。為了標志塊尾,reader 必須返回 NULL。reader 函數可以返回任何大于零的值。

            在當前的實現中,reader 函數不能調用任何Lua 函數;為了保證這一點,它總是會得到為 NULL 的Lua狀態。

            語句段名(chunkname) 用于錯誤信息和調試信息(見 4)。

            參考輔助庫 (lauxlib.c) 了解如何使用 lua_load 以及如何使用現成的函數從文件和字符串中加載語句段。

            3.11 - 表操作

            通過調用以下函數可以創建表:

                   void lua_newtable (lua_State *L);
            

            這個函數創建一張新的空表,并將其壓入棧。

            要從棧中的表里讀取值,使用:

                   void lua_gettable (lua_State *L, int index);
            

            index 代表表的位置。lua_gettable 從棧中彈出一個鍵,并且返回該鍵對應的值,表仍然留在堆棧中。在Lua中,這個函數可能觸發一個針對 index 事件的元方法(見 2.8)。想要在不調用任何元方法的情況下得到表主鍵所對應的真實值,使用這個原始(raw)版本:

                   void lua_rawget (lua_State *L, int index);
            

            要將一個值儲存到棧中的一張表中,你需要將鍵壓入棧,再將值壓入棧,調用:

                   void lua_settable (lua_State *L, int index);
            
            

            index 代表表的位置。lua_settable 從棧中彈出主鍵和值。表仍然留在棧中。在Lua中,這個操作可能觸發針對 settable 或者 newindex 事件的元方法。想要不受這些元方法的影響并且為任意表設置值,使用這個原始(raw)版本:

                   void lua_rawset (lua_State *L, int index);
            

            你可以通過這個函數遍歷一張表:

                   int lua_next (lua_State *L, int index);
            

            index 指向需要被遍歷的表。這個函數從堆棧中彈出一個鍵,從表中取一對鍵-值壓入棧(所給鍵的下一對)。如果沒有更多的元素,lua_next 返回 0(對棧不進行操作)。使用一個 nil 鍵標示遍歷的開始。

            一個典型的遍歷操作看起來像這樣:

                   /* table is in the stack at index `t' */
                   lua_pushnil(L);  /* first key */
                   while (lua_next(L, t) != 0) {
                     /* `key' is at index -2 and `value' at index -1 */
                     printf("%s - %s\n",
                       lua_typename(L, lua_type(L, -2)), lua_typename(L, lua_type(L, -1)));
                     lua_pop(L, 1);  /* removes `value'; keeps `key' for next iteration */
                   }
            
            

            當遍歷一張表的時候,不要在鍵上直接調用 lua_tostring,除非你知道這個鍵確實是一個字符串。再次調用 lua_tostring 改變了所給索引指向的值;這使 lua_next 的調用發生混亂。

            3.12 - 環境變量操作 (Manipulating Environments)

            所有的全局變量保存在普通的Lua 表中,叫做環境變量。初始的環境變量被稱作全局環境變量。這張表總是在 LUA_GLOBALSINDEX 這個偽索引處。

            要訪問或改變全局變量的值,你可以對環境變量表使用常規的表操作。舉個例子,存取一個全局變量的值:

                   lua_pushstring(L, varname);
                   lua_gettable(L, LUA_GLOBALSINDEX);
            

            你可以改變一個Lua 線程的全局環境變量通過 lua_replace 函數。

            以下的函數提供獲取、設置Lua函數的環境變量的功能:

                   void lua_getfenv (lua_State *L, int index);
                   int  lua_setfenv (lua_State *L, int index);
            

            lua_getfenv 將堆棧中 index 索引指向的函數的環境變量表壓入棧。如果函數是一個C 函數,lua_getfenv 將全局環境變量壓入棧。lua_setfenv 從棧中彈出一張表并且將其設置為棧中 index 索引處的函數的新環境變量。如果給定索引處的對象不是一個Lua 函數,lua_setfenv 返回 0。

            3.13 - 將表作為數組使用 Using Tables as Arrays

            有一些 API 能夠幫助我們將Lua 表作為數組使用,也就是說,表只由數字作為索引:

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

            lua_rawgeti 將表中的第 n 個元素放入堆棧中的指定位置 indexlua_rawseti 將堆棧中指定位置 index 處的表中的第 n 個元素的值設定為棧頂的值,并將原來的值從棧中刪除。

            3.14 - 調用函數

            定義在Lua 中的函數和C語言函數經過注冊就可以被宿主程序調用。這些調用必須遵循以下協議:首先,被調用的函數被壓入棧;然后,函數的參數必須順序(direct order)輸入,也就是說,第一個參數需要被第一個輸入。最后,函數通過下面的方法調用:

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

            nargs 是你壓入棧的參數的數量。所有參數和函數值從堆棧中彈出,并且函數結果被壓入棧。返回值的數量被調整為 nresults,除非 nresultsLUA_MULTRET。在那種情況下,所有函數結果都被壓入棧。Lua 會檢測返回值是否適合棧空間。函數返回值按順序被壓入棧(第一個返回值首先入棧),所以調用結束后最后一個返回值在棧頂。

            下面的例子展示宿主程序如何可以和這個Lua 代碼等效:

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

            這里是C 語言里的做法:

                lua_pushstring(L, "t");
                lua_gettable(L, LUA_GLOBALSINDEX);          /* global `t' (for later use) */
                lua_pushstring(L, "a");                                       /* var name */
                lua_pushstring(L, "f");                                  /* function name */
                lua_gettable(L, LUA_GLOBALSINDEX);               /* function to be called */
                lua_pushstring(L, "how");                                 /* 1st argument */
                lua_pushstring(L, "x");                            /* push the string "x" */
                lua_gettable(L, -5);                      /* push result of t.x (2nd arg) */
                lua_pushnumber(L, 14);                                    /* 3rd argument */
                lua_call(L, 3, 1);         /* call function with 3 arguments and 1 result */
                lua_settable(L, LUA_GLOBALSINDEX);             /* set global variable `a' */
                lua_pop(L, 1);                               /* remove `t' from the stack */
            

            注意上面的代碼是“平衡的”:在它結束時,堆棧返回原來的配置。這個被認為是良好的編程實踐。

            (為了展示細節,我們只用Lua 提供的原始 API 完成這個例子。通常程序員定義并使用幾個宏和輔助庫函數在Lua 中提供高級存取功能。請參考例子中標準庫函數的源代碼。)

            3.15 - 受保護調用 Protected Calls

            當你通過 lua_call 調用一個函數,所調用函數內部產生的錯誤將向上傳遞(通過一個 longjmp)。如果你需要處理錯誤,你應該使用 lua_pcall

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

            nargsnresultslua_call 中有相同的意義。如果調用過程中沒有錯誤,lua_pcall 的行為非常像 lua_call 。然而,如果有錯誤,lua_call 會捕獲它,將一個單一值(錯誤信息)壓入棧,并且返回錯誤代碼。像 lua_calllua_pcall 總是從棧中刪除函數和它的參數。

            如果 errfunc 是 0,所返回的錯誤信息就是原始的錯誤信息。另外,errfunc 給出一個指向錯誤處理函數(error handler function)的棧索引。(在當前的實現中,索引不能為偽索引。)假設運行時錯誤,函數將和錯誤信息一起被調用,并且他的返回值將是 lua_pcall 返回的信息。

            錯誤處理函數被用來為錯誤信息增加更多的調試信息,例如棧的記錄。這樣的信息在 lua_pcall 調用返回后將不能被收集,因此棧已經被解開了。

            如果 lua_pcall 函數調用成功返回 0,否則返回以下的一個錯誤代碼(定義在 lua.h):

            • LUA_ERRRUN --- 運行時錯誤
            • LUA_ERRMEM --- 內存分配錯誤。這樣的錯誤下,Lua 不調用錯誤處理函數
            • LUA_ERRERR --- 運行錯誤處理函數時發生的錯誤

            3.16 - 定義C 函數

            Lua可以通過C 語言寫的函數進行擴展,這些函數必須是 lua_CFunction 類型的,作為以下定義:

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

            一個C 函數接收一個Lua 狀態并且返回一個整數,數值需要返回給Lua。

            為了正確的和Lua 通訊,C 函數必須遵循以下協議,它定義了參數和返回值傳遞的方法:一個C 函數在它的堆棧中從Lua獲取順序(第一個參數首先入棧)參數。所以,當函數開始時,第一個參數在索引位置 1。為了將返回值傳遞給Lua,一個C 函數將它們順序壓入棧,并且返回它們的數量。任何在堆棧中位于返回值以下的值都將被Lua 適當的解除。就像Lua 函數一樣,一個C 函數被Lua 調用也可以返回很多結果。

            作為一個例子,下面的函數接收一個任意數量的數字參數并且返回它們的平均值和總合:

                   static int foo (lua_State *L) {
                     int n = lua_gettop(L);    /* number of arguments */
                     lua_Number sum = 0;
                     int i;
                     for (i = 1; i <= n; i++) {
                       if (!lua_isnumber(L, i)) {
                         lua_pushstring(L, "incorrect argument to function `average'");
                         lua_error(L);
                       }
                       sum += lua_tonumber(L, i);
                     }
                     lua_pushnumber(L, sum/n);        /* first result */
                     lua_pushnumber(L, sum);         /* second result */
                     return 2;                   /* number of results */
                   }
            

            下面是一些便利的宏用來在Lua中注冊一個C 函數:

                   #define lua_register(L,n,f) \
                           (lua_pushstring(L, n), \
                            lua_pushcfunction(L, f), \
                            lua_settable(L, LUA_GLOBALSINDEX))
                 /* lua_State *L;    */
                 /* const char *n;   */
                 /* lua_CFunction f; */
            

            它接收Lua 中的函數名和一個指向函數的指針。這樣,上面的C 函數foo可以在Lua中被注冊為 average 并被調用。

                   lua_register(L, "average", foo);
            

            3.17 - 定義C 函數關閉 Defining C Closures

            當一個C 函數被創建后,它可以與一些值關聯,這樣創建了一個 C 閉包(C?closure);這些值可以被隨時被函數訪問。為了使值和C 函數關聯,首先這些值要被壓入棧(有多個值時,第一個值先入),然后這個函數

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

            被用來將C 函數壓入棧,通過參數 n 告知應該有多少個值和該函數關聯(lua_pushcclosure 將這些值從堆棧中彈出);事實上,這個宏 lua_pushcfunction 被定義作為 lua_pushcfunctionn 設置為 0。

            然后,無論何時C 函數被調用,那些值被定為于指定的偽索引處。那些偽索引有一個宏 lua_upvalueindex 產生。第一個和函數關聯的值在 lua_upvalueindex(1) 處,其他的以此類推。當 n 比當前函數的上值大時,lua_upvalueindex(n) 會產生一個可接受的索引(但是無效)。

            C語言函數和關閉的例子,請參考Lua官方發行版中的標準庫(src/lib/*.c)。

            3.18 - 注冊表 Registry

            Lua提供了一個注冊表,一張可以被所有C 代碼用來儲存任何需要儲存的Lua值的預定義表,特別是如果C 代碼需要維護C 函數以外存活的Lua值。這張表總是位于 LUA_REGISTRYINDEX 這個為索引處。任何C 語言庫可以將數據儲存在這張表中,只要它選擇的鍵和其他庫不同。典型的做法是你應該使用字符串作為主鍵包含你的庫名或者在你的代碼中使用一個包含C 對象地址的輕量用戶數據。

            在注冊表中的整數鍵被引用機制所使用,由輔助庫實現,因此不應該被用作其它用途。

            3.19 - C 中的錯誤處理 Error Handling in C

            總的來說,Lua使用C longjmp 機制來處理錯誤。當Lua面對任何錯誤(例如內存分配錯誤,類型錯誤,句法錯誤)它 升起(raises) 一個錯誤,也就是說,它做了一個長跳躍。一個受保護的環境使用 setjmp 設置一個恢復點;任何錯誤跳至最近最活躍的恢復點。

            如果錯誤發生在任何受保護的環境,Lua調用 panic 函數 并且隨后調用exit(EXIT_FAILURE)。你可以將panic 函數變為以下內容。

                   lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf);
            

            你的新panic 函數可以避免程序因為沒有返回(例如通過一個長跳躍)而退出。否則,相應的Lua 狀態將不一致;唯一安全的操作就是關閉它。

            幾乎所有的API 函數都可能引起錯誤,例如導致一個內存分配錯誤。:lua_open, lua_close, lua_loadlua_pcall 這些的函數運行在保護模式下(也就是說,它們創建了一個受保護的環境并在其中運行),所以它們從不會引起錯誤。

            有另外一個函數將所給的C 函數運行在保護模式下:

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

            lua_cpcall 在保護模式下調用 funcfunc 由一個包含 ud 的輕量用戶數據開始。在錯誤問題上,lua_cpcalllua_pcall 一樣返回相同的錯誤代碼(見 3.15),加上在棧頂的一個錯誤對象;否則,返回 0,并且不對堆棧進行任何操作。任何由 func 返回的值都被丟棄。

            C 代碼可以通過調用下面的函數產生一個Lua錯誤:

                   void lua_error (lua_State *L);
            

            錯誤信息(實際上可以是任何類型的對象)必須在棧頂。這個函數進行一個長跳躍,因此從來不會返回。

            3.20 - 線程

            Lua 提供了操作線程的部分支?幀H綣閿卸嘞叱灘僮韉腃 語言庫,那么Lua能夠與其協作并且在Lua中實現相同的機制。同樣,Lua在線程之上實現自己的協同程序系統。以下函數用來在Lua中創建一個線程:

                   lua_State *lua_newthread (lua_State *L);
            

            這個函數將線程壓入棧并且返回代表新線程的 lua_State 指針。這個返回的新狀態與所有全局對象(例如表)共享初始狀態,但是有一個獨立的運行時堆棧。

            每個線程都有自己獨立的全局環境表。當你創建一個線程,這張表就和所給狀態一樣,但是你可以獨自更改它們。

            沒有明確的函數可以關閉或者銷毀一個線程。線程和其他Lua對象一樣受垃圾收集程序的支配:

            要像協同程序一樣操作線程,Lua提供了以下函數:

                   int lua_resume (lua_State *L, int narg);
                   int lua_yield  (lua_State *L, int nresults);
            

            你需要創建一個線程以便啟動協同程序;然后你將函數體和事件參數壓入堆棧;然后調用 lua_resumenarg 的值代表參數的數量。當同步程序暫停或者結束執行,函數將返回。當它返回后,棧中包含的所有值傳遞給 lua_yield,或者有主體函數返回。如果同步程序運行無誤,lua_resume 返回 0,否則返回一個錯誤代碼(見 3.15)。對于錯誤,堆棧只包含錯誤信息。要重起同步程序,將作為結果傳遞給 yield 的值壓入堆棧,并且調用 lua_resume

            lua_yield 函數只能像C 函數的返回表達式一樣被調用,就像下面所展示的:

                   return lua_yield (L, nresults);
            

            如果C 函數像這樣調用 lua_yield,正在運行的同步程序暫停它的執行,并且調用 lua_resume 開始讓這個協同程序返回。nresults 這個參數代表了在堆棧中作為結果傳遞給 lua_resume 的值的數量。

            要在不同線程中交換值,你可以使用 lua_xmove

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

            它從堆棧 from 中彈出 n 個值,并將其壓入堆棧 to

            4 - 調試接口 The Debug Interface

            Lua 沒有內置的調試設施。它使用一種特殊的接口,這種接口依賴函數和 鉤子(hooks)。該接口允許構造不同種類的調試器,分析器以及其他工具用以從解釋器得到所需的信息。

            4.1 - 堆棧及函數信息 Stack and Function Information

            得到解釋程序運行時堆棧信息的主要函數是:

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

            這個函數用一個指定等級的函數的 activation record 的標示符填充一個 lua_Debug 結構,等級 0 是當前運行函數,然而等級 n+1 是在等級 n 上調用的函數。當沒有錯誤發生時,lua_getstack 返回 1;當在比棧更深的等級上調用的時候,它返回 0;

            lua_Debug 結構被用來攜帶一個處于活動狀態的函數的各種信息:

                  typedef struct lua_Debug {
                    int event;
                    const char *name;      /* (n) */
                    const char *namewhat;  /* (n) `global', `local', `field', `method' */
                    const char *what;      /* (S) `Lua' function, `C' function, Lua `main' */
                    const char *source;    /* (S) */
                    int currentline;       /* (l) */
                    int nups;              /* (u) number of upvalues */
                    int linedefined;       /* (S) */
                    char short_src[LUA_IDSIZE]; /* (S) */
            
                    /* private part */
                    ...
                  } lua_Debug;
            

            lua_getstack 只填充結構的私有部分以備之后使用。要填充 lua_Debug 其他有用信息,調用

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

            這個函數發生錯誤是返回 0 (舉個例子,一個無效的 what 選項)。what 字符串中的每個字符選擇填充一些 ar 結構的字段,把上面在 lua_Debug 定義中用圓括號括起來的字母作為指示: `S′ 填充在 source, linedefinedwhat 字段中;`l′ 填充在 currentline 字段中,等等...。而且,`f′ 將正在運?性謁燃渡系暮谷攵顏弧?

            想要從一個不處于活動狀態的函數那得到信息(就是不在棧上的函數),你需要將其壓入棧并且用 >′ 作為 what 字符串的開始。舉個例子,要知道函數 f 定義在第幾行,你需要這樣寫

                   lua_Debug ar;
                   lua_pushstring(L, "f");
                   lua_gettable(L, LUA_GLOBALSINDEX);  /* get global `f' */
                   lua_getinfo(L, ">S", &ar);
                   printf("%d\n", ar.linedefined);
            

            lua_Debug 的字段有如下的含義:

            • source 如果函數在一個字符串中定義,那么 source 就是那個字符串。如果函數定義在一個文件中,source 開始于一個 `@′ 后面跟隨文件名。
            • short_src 一個可打印版的 source,用于錯誤信息。
            • linedefined 函數定義起始的行號。
            • what 如果這是一個Lua函數,顯示 "Lua" 字符串, "C" 為C 函數,"main" 如果這是一個語句段的main部分,"tail" 如果這是一個做了尾部調用的函數。在后面的情況里,Lua 沒有其他關于這個函部的信息。
            • currentline 代表當前函數執行到的行數。如果沒有行信息可用,currentline 被設置為 -1
            • name 一個所給函數合理的函數名。因為函數在Lua中屬于第一類值,它們沒有固定的名字:一些函數可能是多個全局變量的值,其他的可能只儲存在一個表字段里。lua_getinfo 函數檢測函數如何被調用或者是否為一個全局變量的值以尋找一個合適的名字。如果找不到合適的名字,name 被設置為 NULL
            • namewhat name 字段的解釋。根據函數如何被調用,namewhat 的值可以是 "global", "local", "method", "field" 或者 "" (空字符串)。(當沒有其他可選項的時候Lua使用空字符串代替)
            • nups 函數上值的數量。

            4.2 - 操作局部變量和上值 Manipulating Local Variables and Upvalues

            為了更多的操作局部變量和上值,調試接口使用索引:第一個參數或者局部變量索引為 1,以此類推,直到最后一個活動的局部變量。整個函數中的活動的上值沒有特定的順序。

            下面的函數允許操作一個所給激活記錄的局部變量:

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

            參數 ar 必須是一個被前一個 lua_getstack 調用填充的有效的激活記錄或者作為一個鉤子函數的參數(見 4.3)。lua_getlocal 獲得一個局部變量的索引 n,將變量的值壓入棧,并且返回變量名。lua_setlocal 從棧頂分配一個值給變量并且返回變量名。當索引超過活動的局部變量的數量時,兩個函數都返回 NULL

            以下的函部可以操作所給函數的上值(不像局部變量,函數的上值即使在函數不處于活動狀態的時候都可以被訪問):

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

            這些函數可以作為Lua 函數使用也可以作為C 函數使用。(作為Lua 函數,上值是函數外部使用的局部變量,因此它被包含在函數閉包中。)funcindex 指向棧中的一個函數。lua_getupvalue 得到一個上值的索引 n,將上值的值壓入棧,并返回其變量名。lua_setupvalue 從棧頂分配一個值給上值并返回變量名。當索引大于上值數量時,兩個函數都返回 NULL。對于C 函數來說,這些函數使用空字符串作為所有上值的變量名。

            作為一個例子,下面的函數列舉了所給等級的棧中的函數的所有局部變量名和上值變量名:

                   int listvars (lua_State *L, int level) {
                     lua_Debug ar;
                     int i;
                     const char *name;
                     if (lua_getstack(L, level, &ar) == 0)
                       return 0;  /* failure: no such level in the stack */
                     i = 1;
                     while ((name = lua_getlocal(L, &ar, i++)) != NULL) {
                       printf("local %d %s\n", i-1, name);
                       lua_pop(L, 1);  /* remove variable value */
                     }
                     lua_getinfo(L, "f", &ar);  /* retrieves function */
                     i = 1;
                     while ((name = lua_getupvalue(L, -1, i++)) != NULL) {
                       printf("upvalue %d %s\n", i-1, name);
                       lua_pop(L, 1);  /* remove upvalue value */
                     }
                     return 1;
                   }
            

            4.3 - 鉤子 Hooks

            Lua offers a mechanism of hooks, which are user-defined C functions that are called during the program execution. A hook may be called in four different events: a call event, when Lua calls a function; a return event, when Lua returns from a function; a line event, when Lua starts executing a new line of code; and a count event, which happens every "count" instructions. Lua identifies these events with the following constants: LUA_HOOKCALL, LUA_HOOKRET (or LUA_HOOKTAILRET, see below), LUA_HOOKLINE, and LUA_HOOKCOUNT.

            A hook has type lua_Hook, defined as follows:

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

            You can set the hook with the following function:

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

            func is the hook. mask specifies on which events the hook will be called: It is formed by a disjunction of the constants LUA_MASKCALL, LUA_MASKRET, LUA_MASKLINE, and LUA_MASKCOUNT. The count argument is only meaningful when the mask includes LUA_MASKCOUNT. For each event, the hook is called as explained below:

            • The call hook is called when the interpreter calls a function. The hook is called just after Lua enters the new function.
            • The return hook is called when the interpreter returns from a function. The hook is called just before Lua leaves the function.
            • The line hook is called when the interpreter is about to start the execution of a new line of code, or when it jumps back in the code (even to the same line). (This event only happens while Lua is executing a Lua function.)
            • The count hook is called after the interpreter executes every count instructions. (This event only happens while Lua is executing a Lua function.)

            A hook is disabled by setting mask to zero.

            You can get the current hook, the current mask, and the current count with the following functions:

                   lua_Hook lua_gethook      (lua_State *L);
                   int      lua_gethookmask  (lua_State *L);
                   int      lua_gethookcount (lua_State *L);
            

            Whenever a hook is called, its ar argument has its field event set to the specific event that triggered the hook. Moreover, for line events, the field currentline is also set. To get the value of any other field in ar, the hook must call lua_getinfo. For return events, event may be LUA_HOOKRET, the normal value, or LUA_HOOKTAILRET. In the latter case, Lua is simulating a return from a function that did a tail call; in this case, it is useless to call lua_getinfo.

            While Lua is running a hook, it disables other calls to hooks. Therefore, if a hook calls back Lua to execute a function or a chunk, that execution occurs without any calls to hooks.

            5 - 標準庫

            The standard 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 to 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;
            • 字符串操作 string manipulation;
            • 表操作 table manipulation;
            • 數學函數 (sin, log 等等)mathematical functions (sin, log, etc.);
            • 輸入輸出 input and output;
            • 操作系統機制 operating system facilities;
            • 調試機制 debug facilities.

            Except for the basic library, 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 must first call the functions luaopen_base (for the basic 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.

            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 some alternative implementation for some of its facilities.

            assert (v [, message])

            Issues an error when the value of its argument v is nil or false; otherwise, returns this value. message is an error message; when absent, it defaults to "assertion failed!"

            collectgarbage ([limit])

            Sets the garbage-collection threshold to the given limit (in Kbytes) and checks it against the byte counter. If the new threshold is smaller than the byte counter, then Lua immediately runs the garbage collector (see 2.9). If limit is absent, it defaults to zero (thus forcing a garbage-collection cycle).

            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 any value returned by the chunk. In case of errors, dofile propagates the error to its caller (that is, it 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.

            The level argument specifies where the error message points the error. 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.

            _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. (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, which 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.

            If the environment has a "__fenv" field, returns the associated value, instead of the environment.

            getmetatable (object)

            If the 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.

            gcinfo ()

            Returns two results: the number of Kbytes of dynamic memory that Lua is using and the current garbage collector threshold (also in Kbytes).

            ipairs (t)

            Returns an iterator function, the table t, and 0, so that the construction

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

            will iterate over the pairs (1,t[1]), (2,t[2]), ..., up to the first integer key with a nil value in the table.

            loadfile (filename)

            Loads a file as a Lua chunk (without running it). 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.

            loadlib (libname, funcname)

            Links the program with the dynamic C library libname. Inside this library, looks for a function funcname and returns this function as a C function.

            libname must be the complete file name of the C library, including any eventual path and extension.

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

            loadstring (string [, chunkname])

            Loads a string as a Lua chunk (without running it). 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.

            The optional parameter chunkname is the name to be used in error messages and debug information.

            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 the value associated with the index. When called with nil as its second argument, next returns the first index of the table 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.

            Lua has no declaration of fields; There is no difference between a field not present in a table or a field with value nil. Therefore, next only considers fields with non-nil values. The order in which the indices are enumerated is not specified, even for numeric indices. (To traverse a table in numeric order, use a numerical for 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.

            pairs (t)

            Returns the next function and the table t (plus a nil), so that the construction

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

            will iterate over all key-value pairs of table t.

            pcall (f, arg1, arg2, ...)

            Calls function f with the given arguments in protected mode. That 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 (e1, e2, ...)

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

            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 is any value different from nil.

            rawset (table, index, value)

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

            require (packagename)

            Loads the given package. The function starts by looking into the table _LOADED to determine whether packagename is already loaded. If it is, then require returns the value that the package returned when it was first loaded. Otherwise, it searches a path looking for a file to load.

            If the global variable LUA_PATH is a string, this string is the path. Otherwise, require tries the environment variable LUA_PATH. As a last resort, it uses the predefined path "?;?.lua".

            The path is a sequence of templates separated by semicolons. For each template, require will change each interrogation mark in the template to packagename, and then will try to load the resulting file name. So, for instance, if the path is

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

            a require "mod" will try to load the files ./mod.lua, ./mod.lc, /usr/local/mod/mod.lua, and /lasttry, in that order.

            The function stops the search as soon as it can load a file, and then it runs the file. After that, it associates, in table _LOADED, the package name with the value that the package returned, and returns that value. If the package returns nil (or no value), require converts this value to true. If the package returns false, require also returns false. However, as the mark in table _LOADED is false, any new attempt to reload the file will happen as if the package was not loaded (that is, the package will be loaded again).

            If there is any error loading or running the file, or if it cannot find any file in the path, then require signals an error.

            While running a file, require defines the global variable _REQUIREDNAME with the package name. The package being loaded always runs within the global environment.

            setfenv (f, table)

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

            As a special case, when f is 0 setfenv changes the global environment of the running thread.

            If the original environment has a "__fenv" field, setfenv raises an error.

            setmetatable (table, metatable)

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

            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 that 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.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 format (see 5.3).

            If the metatable of e has a "__tostring" field, 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)

            Returns all elements from the given list. This function is equivalent to

              return list[1], list[2], ..., list[n]
            
            

            except that the above code can be written only for a fixed n. The number n is the size of the list, as defined for the table.getn function.

            _VERSION

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

            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 such case, xpcall also returns all results from the call, after this first result. In case of any error, xpcall returns 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.10 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 arguments val1, ... go as the arguments to the body function. If the coroutine has yielded, resume restarts it; the arguments val1, ... go 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.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; 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 (val1, ...)

            Suspends the execution of the calling coroutine. The coroutine cannot be running neither a C function, nor a metamethod, nor an iterator. Any arguments to yield go as extra results to resume.

            5.3 - 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.

            string.byte (s [, i])

            Returns the internal numerical code of the i-th character of s, or nil if the index is out of range. If i is absent, then it is assumed to be?1. i may be negative.

            Note that numerical codes are not necessarily portable across platforms.

            string.char (i1, i2, ...)

            Receives 0 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 correspondent argument.

            Note that numerical codes are not necessarily portable across platforms.

            string.dump (function)

            Returns a binary representation of the given function, so that a later loadstring on that 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 one, then find returns the indices of?s where this occurrence starts and ends; otherwise, it returns nil. If the pattern specifies captures (see string.gsub below), the captured strings are returned as extra results. A third, optional numerical argument init specifies where to start the search; it may be negative and its default value is?1. 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 too.

            string.len (s)

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

            string.lower (s)

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

            string.rep (s, n)

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

            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 that string with all lowercase letters changed to uppercase. All other characters are left unchanged. The definition of what is a lowercase letter depends on the current locale.

            string.format (formatstring, e1, e2, ...)

            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 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, 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. The * modifier can be simulated by building the appropriate format string. For example, "%*g" can be simulated with "%"..width.."g".

            String values to be formatted with %s cannot contain embedded zeros.

            string.gfind (s, pat)

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

            If pat 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.gfind(s, "%a+") do
                print(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.gfind(s, "(%w+)=(%w+)") do
                t[k] = v
              end
            

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

            Returns a copy of s in which all occurrences of the pattern pat have been replaced by a replacement string specified by repl. gsub also returns, as a second value, the total number of substitutions made.

            If repl is a string, then its value is used for replacement. 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).

            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 this function is a string, then it is used as the replacement string; otherwise, the replacement string is the empty 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 pat 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+)", "%1 %1", 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.0"}
               x = string.gsub("$name_$version.tar.gz", "%$(%w+)", function (v)
                     return t[v]
                   end)
               --> x="lua_5.0.tar.gz"
            

            Patterns

            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 set represent 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. The second form should be preferred for portability.

            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 are balanced. 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.

            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.

            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.4 - 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 those functions, an important concept is the size of the array. There are three ways to specify that size:

            • the field "n" --- When the table has a field "n" with a numerical value, that value is assumed as its size.
            • setn --- You can call the table.setn function to explicitly set the size of a table.
            • implicit size --- Otherwise, the size of the object is one less the first integer index with a nil value.

            For more details, see the descriptions of the table.getn and table.setn functions.

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

            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 size of the table. If i is greater than j, returns the empty string.

            table.foreach (table, f)

            Executes the given f over all elements of table. For each element, f is called with the index and respective value as arguments. If f returns a non-nil value, then the loop is broken, and this value is returned as the final value of foreach.

            See the next function for extra information about table traversals.

            table.foreachi (table, f)

            Executes the given f over the numerical indices of table. For each index, f is called with the index and respective value as arguments. Indices are visited in sequential order, from?1 to n, where n is the size of the table (see 5.4). If f returns a non-nil value, then the loop is broken and this value is returned as the result of foreachi.

            table.getn (table)

            Returns the size of a table, when seen as a list. If the table has an n field with a numeric value, this value is the size of the table. Otherwise, if there was a previous call to table.setn over this table, the respective value is returned. Otherwise, the size is one less the first integer index with a nil value.

            table.sort (table [, comp])

            Sorts table elements in a given order, in-place, from table[1] to table[n], where n is the size of the table (see 5.4). 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.

            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 size of the table (see 5.4), so that a call table.insert(t,x) inserts x at the end of table t. This function also updates the size of the table by calling table.setn(table, n+1).

            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 size of the table (see 5.4), so that a call table.remove(t) removes the last element of table t. This function also updates the size of the table by calling table.setn(table, n-1).

            table.setn (table, n)

            Updates the size of a table. If the table has a field "n" with a numerical value, that value is changed to the given n. Otherwise, it updates an internal state so that subsequent calls to table.getn(table) return n.

            5.5 - Mathematical Functions

            This library is an interface to most of the functions of the standard C?math library. (Some have slightly different names.) It provides all its functions inside the table math. In addition, it registers the global __pow for the binary exponentiation operator ^, so that x^y returns xy. The library provides the following functions:

                   math.abs     math.acos    math.asin    math.atan    math.atan2
                   math.ceil    math.cos     math.deg     math.exp     math.floor
                   math.log     math.log10   math.max     math.min     math.mod
                   math.pow     math.rad     math.sin     math.sqrt    math.tan
                   math.frexp   math.ldexp   math.random  math.randomseed
            

            plus a variable math.pi. Most of them are only interfaces to the corresponding functions in the C?library. All trigonometric functions work in radians (previous versions of Lua used degrees). The functions math.deg and math.rad convert between radians and degrees.

            The function math.max returns the maximum value of its numeric arguments. Similarly, math.min computes the minimum. Both can be used with 1, 2, or more arguments.

            The functions math.random and math.randomseed are interfaces to the simple random generator functions rand and srand that are provided by ANSI?C. (No guarantees can be given for their statistical properties.) When called without arguments, math.random returns a pseudo-random real number in the range [0,1). When called with a number n, math.random returns a pseudo-random integer in the range [1,n]. When called with two arguments, l and u, math.random returns a pseudo-random integer in the range [l,u]. The math.randomseed function sets a "seed" for the pseudo-random generator: Equal seeds produce equal sequences of numbers.

            5.6 - 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 those 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 by 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.

            A file handle is a userdata containing the file stream (FILE*), with a distinctive metatable created by the I/O library.

            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 that 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 ... 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() (without a file name) is equivalent to io.input():lines(), that is, it iterates over the lines of the default input file.

            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.read (format1, ...)

            Equivalent to io.input():read.

            io.tmpfile ()

            Returns a handle for a temporary file. This file is open 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, and nil if obj is not a file handle.

            io.write (value1, ...)

            Equivalent to io.output():write.

            file:close ()

            Closes file.

            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 ... 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 (format1, ...)

            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 that 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 string whence, 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:write (value1, ...)

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

            5.7 - Operating System Facilities

            This library is implemented through table os.

            os.clock ()

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

            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 that optional character, if format is *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.

            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 with the given name. If this function fails, it returns nil, plus a string describing the error.

            os.rename (oldname, newname)

            Renames file 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.

            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 removed when no longer needed.

            This function is equivalent to the tmpnam C?function, and many people (and even some compilers!) advise against its use, because between the time you call this function and the time you open the file, it is possible for another process to create a file with the same name.

            5.8 - The Reflexive Debug Interface

            The debug 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, setlocal and getlocal violate the privacy of local variables and therefore can compromise some otherwise secure code.

            All functions in this library are provided inside a debug table.

            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 with any function, so they have no direct access to local variables.

            debug.gethook ()

            Returns the current hook settings, 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 (function [, what])

            This function 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: 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 contains all the fields returned by lua_getinfo, with the string what describing which fields to fill in. The default for what is to get all information available. If present, the option `f′ adds a field named func with the function itself.

            For instance, the expression debug.getinfo(1,"n").name returns the name of the current function, if a reasonable name can be found, and debug.getinfo(print) returns a table with all available information about the print function.

            debug.getlocal (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.)

            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.setlocal (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.)

            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.

            debug.sethook (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, the debug.sethook function turns off the hook.

            When the hook is called, its first parameter is always a string describing the event that triggered its call: "call", "return" (or "tail return"), "line", and "count". Moreover, for line events, it also gets as its second parameter the new line number. 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.traceback ([message])

            Returns a string with a traceback of the call stack. An optional message string is appended at the beginning of the traceback. This function is typically used with xpcall to produce better error messages.

            6 - Lua 獨立程序 Lua Stand-alone

            盡管Lua被設計為一種內嵌于C 語言宿主程序中的擴展語言,它還是經常被用作一個獨立程序語言。一個Lua的解釋程序將Lua作為一個獨立的語言,我們稱之為簡化的 lua,它提供了標準的發行版本。獨立的解釋器包含了所有標準庫加上反射性的調試接口。它的使用方式如下:

                  lua [options] [script [args]]
            

            options 可以是以下內容:

            • - 標準輸入(stdin) 當作文件執行;
            • -e stat 執行字符串 stat
            • -l file “需要”file 文件;
            • -i 在運行腳本后進入交互模式;
            • -v 打印版本信息;
            • -- 停止處理選項。

            在停止處理選項后,lua 運行所給的腳本,傳遞所給參數 args。當無參數調用時,lua 就像 stdin 是程序的終結時 lua -v -i 所表現的一樣,而且還與 lua- 一樣。

            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 a, and finally run the file script.lua. (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 in index 0, the first argument after the script name goes to index 1, and so on. The field n gets the number of arguments after the script name. 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.lua b.lua t1 t2
            

            the interpreter first runs the file a.lua, then creates a table

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

            and finally runs the file b.lua.

            在交互模式中,如果你寫入了一個不完整的語句,解釋器將等待你的完成。

            If the global variable _PROMPT is defined as a string, then its value is used as the prompt. Therefore, the prompt can be changed directly on the command line:

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

            (the outer pair of quotes is for the shell, the inner 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 end just after the assignment to _PROMPT.

            在Unix系統中,Lua腳本可以用 chmod +x 將其變成可執行程序,并且通過 #! 形式,例如

            #!/usr/local/bin/lua
            
            

            (當然,Lua解釋器的位置可能有所不同,如果 lua 在你的 PATH 中,那么

            #!/usr/bin/env lua
            

            就是一個更通用的解決方案。)

            致謝

            The Lua team is grateful to Tecgraf for its continued support to Lua. We thank everyone at Tecgraf, specially the head of the group, Marcelo Gattass. At the risk of omitting several names, we also thank the following individuals for supporting, contributing to, and spreading the word about Lua: Alan Watson. André Clinio, André Costa, Antonio Scuri, Asko Kauppi, Bret Mogilefsky, Cameron Laird, Carlos Cassino, Carlos Henrique Levy, Claudio Terra, David Jeske, Ed Ferguson, Edgar Toernig, Erik Hougaard, Jim Mathies, John Belmonte, John Passaniti, John Roll, Jon Erickson, Jon Kleiser, Mark Ian Barlow, Nick Trout, Noemi Rodriguez, Norman Ramsey, Philippe Lhoste, Renata Ratton, Renato Borges, Renato Cerqueira, Reuben Thomas, Stephan Herrmann, Steve Dekorte, Thatcher Ulrich, Tomás Gorham, Vincent Penquerc'h. Thank you!


            與以前版本的不兼容性 Incompatibilities with Previous Versions

            Lua 5.0 是一個主版本,所有與 Lua 4.0 有一些地方不兼容。

            與 v4.0 的不兼容性 Incompatibilities with version 4.0

            語言上的變動

            • 整個標簽方法模式被元表所替代。The whole tag-method scheme was replaced by metatables.
            • Function calls written between parentheses result in exactly one value.
            • A function call as the last expression in a list constructor (like {a,b,f()}) has all its return values inserted in the list.
            • The precedence of or is smaller than the precedence of and.
            • in, false, and true are reserved words.
            • The old construction for k,v in t, where t is a table, is deprecated (although it is still supported). Use for k,v in pairs(t) instead.
            • When a literal string of the form [[...]] starts with a newline, this newline is ignored.
            • Upvalues in the form %var are obsolete; use external local variables instead.

            庫的變更

            • Most library functions now are defined inside tables. There is a compatibility script (compat.lua) that redefines most of them as global names.
            • In the math library, angles are expressed in radians. With the compatibility script (compat.lua), functions still work in degrees.
            • The call function is deprecated. Use f(unpack(tab)) instead of call(f, tab) for unprotected calls, or the new pcall function for protected calls.
            • dofile does not handle errors, but simply propagates them.
            • dostring is deprecated. Use loadstring instead.
            • The read option *w is obsolete.
            • The format option %n$ is obsolete.

            API 上的改動

            • lua_open 不再需要堆棧大小作為參數(堆棧是動態的)。
            • lua_pushuserdata 已經被廢除了。使用 lua_newuserdatalua_pushlightuserdata 來代替它。

            Lua 完整語法參考

            chunk ::= {stat [`;′]} block ::= chunk stat ::= 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 | return [explist1] | break | for Name `=′ exp `,′ exp [`,′ exp] do block end | for Name {`,′ Name} in explist1 do block end | function funcname funcbody | localfunction Name funcbody | local namelist [init] funcname ::= Name {`.′ Name} [`:′ Name] varlist1 ::= var {`,′ var} var ::= Name | prefixexp `[′ exp `]′ | prefixexp `.′ Name namelist ::= Name {`,′ Name} init ::= `=′ explist1 explist1 ::= {exp `,′} exp exp ::= nil | false | true | Number | Literal | function | prefixexp | tableconstructor | exp binop exp | unop exp prefixexp ::= var | functioncall | `(′ exp `)′ functioncall ::= prefixexp args | prefixexp `:′ Name args args ::= `(′ [explist1] `)′ | tableconstructor | Literal function ::= function funcbody funcbody ::= `(′ [parlist1] `)′ block end parlist1 ::= Name {`,′ Name} [`,′ `...′] | `...′ tableconstructor ::= `{′ [fieldlist] `}′ fieldlist ::= field {fieldsep field} [fieldsep] field ::= `[′ exp `]′ `=′ exp | name `=′ exp | exp fieldsep ::= `,′ | `;′ binop ::= `+′ | `-′ | `*′ | `/′ | `^′ | `..′ | `<′ | `<=′ | `>′ | `>=′ | `==′ | `~=′ | and | or unop ::= `-′ | not
            posted on 2006-11-18 09:37 李錦俊(mybios) 閱讀(3496) 評論(2)  編輯 收藏 引用 所屬分類: LUA

            Feedback

            # re: 【轉貼】Lua 5.0 參考手冊 2006-11-18 11:41 江水獸
            盡管你轉載的這篇文章不錯 但是轉貼也發到首頁原創區貌似不好呵!  回復  更多評論
              

            # re: 【轉貼】Lua 5.0 參考手冊 2006-11-18 12:03 李錦俊
            哦,我是習慣性選第一個。但是我看到很多人都是選第一個。如果覺得不好的話我下次就不選這個。改的話就太麻煩了。呵呵!  回復  更多評論
              

            亚洲中文字幕无码久久精品1 | 色婷婷久久综合中文久久蜜桃av| 久久99精品久久久久子伦| 久久人人爽人人爽人人片AV东京热| 人妻精品久久无码区| 青青青国产成人久久111网站| 无码超乳爆乳中文字幕久久 | avtt天堂网久久精品| 国产精品99久久久久久猫咪| 麻豆成人久久精品二区三区免费| 精品国产福利久久久| 精品国产VA久久久久久久冰| 久久播电影网| 国产午夜精品久久久久九九电影| 成人综合久久精品色婷婷| 午夜精品久久久久9999高清| 久久精品成人欧美大片| 久久久久国产视频电影| 久久青青草原精品国产| 久久不见久久见免费视频7| 久久久久无码专区亚洲av| 久久精品国产精品亚洲毛片| 色天使久久综合网天天| 久久国产精品99久久久久久老狼| 国产成人无码精品久久久性色| 国产真实乱对白精彩久久| 国产精品女同久久久久电影院| 久久综合伊人77777麻豆| 欧美日韩中文字幕久久伊人| 99国产欧美精品久久久蜜芽| 久久精品国产91久久麻豆自制 | 久久国产精品-久久精品| 久久亚洲精品成人AV| 国产色综合久久无码有码| 人人狠狠综合久久亚洲高清| 久久电影网| 国产精品欧美久久久久天天影视| 精品国产VA久久久久久久冰| 久久天堂AV综合合色蜜桃网| 欧美牲交A欧牲交aⅴ久久| 亚洲AV日韩精品久久久久久久|