4 - 調試接口 The Debug Interface
Lua 沒(méi)有內置的調試設施。它使用一種特殊的接口,這種接口依賴(lài)函數和 鉤子(hooks)。該接口允許構造不同種類(lèi)的調試器,分析器以及其他工具用以從解釋器得到所需的信息。
4.1 - 堆棧及函數信息 Stack and Function Information
得到解釋程序運行時(shí)堆棧信息的主要函數是:
int lua_getstack (lua_State *L, int level, lua_Debug *ar);
這個(gè)函數用一個(gè)指定等級的函數的 activation record 的標示符填充一個(gè) lua_Debug 結構,等級 0 是當前運行函數,然而等級 n+1 是在等級 n 上調用的函數。當沒(méi)有錯誤發(fā)生時(shí),lua_getstack 返回 1;當在比棧更深的等級上調用的時(shí)候,它返回 0;
lua_Debug 結構被用來(lái)攜帶一個(gè)處于活動(dòng)狀態(tài)的函數的各種信息:
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);
這個(gè)函數發(fā)生錯誤是返回 0 (舉個(gè)例子,一個(gè)無(wú)效的 what 選項)。what 字符串中的每個(gè)字符選擇填充一些 ar 結構的字段,把上面在 lua_Debug 定義中用圓括號括起來(lái)的字母作為指示: `S′ 填充在 source, linedefined 和 what 字段中;`l′ 填充在 currentline 字段中,等等...。而且,`f′ 將正在運?性謁燃渡系暮谷攵顏弧?
想要從一個(gè)不處于活動(dòng)狀態(tài)的函數那得到信息(就是不在棧上的函數),你需要將其壓入棧并且用 >′ 作為 what 字符串的開(kāi)始。舉個(gè)例子,要知道函數 f 定義在第幾行,你需要這樣寫(xiě)
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 如果函數在一個(gè)字符串中定義,那么 source 就是那個(gè)字符串。如果函數定義在一個(gè)文件中,source 開(kāi)始于一個(gè) `@′ 后面跟隨文件名。
short_src 一個(gè)可打印版的 source,用于錯誤信息。
linedefined 函數定義起始的行號。
what 如果這是一個(gè)Lua函數,顯示 "Lua" 字符串, "C" 為C 函數,"main" 如果這是一個(gè)語(yǔ)句段的main部分,"tail" 如果這是一個(gè)做了尾部調用的函數。在后面的情況里,Lua 沒(méi)有其他關(guān)于這個(gè)函部的信息。
currentline 代表當前函數執行到的行數。如果沒(méi)有行信息可用,currentline 被設置為 -1。
name 一個(gè)所給函數合理的函數名。因為函數在Lua中屬于第一類(lèi)值,它們沒(méi)有固定的名字:一些函數可能是多個(gè)全局變量的值,其他的可能只儲存在一個(gè)表字段里。lua_getinfo 函數檢測函數如何被調用或者是否為一個(gè)全局變量的值以尋找一個(gè)合適的名字。如果找不到合適的名字,name 被設置為 NULL。
namewhat name 字段的解釋。根據函數如何被調用,namewhat 的值可以是 "global", "local", "method", "field" 或者 "" (空字符串)。(當沒(méi)有其他可選項的時(shí)候Lua使用空字符串代替)
nups 函數上值的數量。
4.2 - 操作局部變量和上值 Manipulating Local Variables and Upvalues
為了更多的操作局部變量和上值,調試接口使用索引:第一個(gè)參數或者局部變量索引為 1,以此類(lèi)推,直到最后一個(gè)活動(dòng)的局部變量。整個(gè)函數中的活動(dòng)的上值沒(méi)有特定的順序。
下面的函數允許操作一個(gè)所給激活記錄的局部變量:
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 必須是一個(gè)被前一個(gè) lua_getstack 調用填充的有效的激活記錄或者作為一個(gè)鉤子函數的參數(見(jiàn) 4.3)。lua_getlocal 獲得一個(gè)局部變量的索引 n,將變量的值壓入棧,并且返回變量名。lua_setlocal 從棧頂分配一個(gè)值給變量并且返回變量名。當索引超過(guò)活動(dòng)的局部變量的數量時(shí),兩個(gè)函數都返回 NULL。
以下的函部可以操作所給函數的上值(不像局部變量,函數的上值即使在函數不處于活動(dòng)狀態(tài)的時(shí)候都可以被訪(fǎng)問(wèn)):
const char *lua_getupvalue (lua_State *L, int funcindex, int n); const char *lua_setupvalue (lua_State *L, int funcindex, int n);
這些函數可以作為L(cháng)ua 函數使用也可以作為C 函數使用。(作為L(cháng)ua 函數,上值是函數外部使用的局部變量,因此它被包含在函數閉包中。)funcindex 指向棧中的一個(gè)函數。lua_getupvalue 得到一個(gè)上值的索引 n,將上值的值壓入棧,并返回其變量名。lua_setupvalue 從棧頂分配一個(gè)值給上值并返回變量名。當索引大于上值數量時(shí),兩個(gè)函數都返回 NULL。對于C 函數來(lái)說(shuō),這些函數使用空字符串作為所有上值的變量名。
作為一個(gè)例子,下面的函數列舉了所給等級的棧中的函數的所有局部變量名和上值變量名:
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 functionsthat are called during the program execution. A hook may be called infour 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 aboutto start the execution of a new line of code, or when it jumps back inthe code (even to the same line). (This event only happens while Lua isexecuting 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.
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 ofomitting several names, we also thank the following individuals forsupporting, contributing to, and spreading the word about Lua: AlanWatson. André Clinio, André Costa, Antonio Scuri, Asko Kauppi, BretMogilefsky, 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, NormanRamsey, Philippe Lhoste, Renata Ratton, Renato Borges, RenatoCerqueira, Reuben Thomas, Stephan Herrmann, Steve Dekorte, ThatcherUlrich, Tomás Gorham, Vincent Penquerc'h. Thank you!
與以前版本的不兼容性 Incompatibilities with Previous Versions
Lua 5.0 是一個(gè)主版本,所有與 Lua 4.0 有一些地方不兼容。
與 v4.0 的不兼容性 Incompatibilities with version 4.0
語(yǔ)言上的變動(dòng)
整個(gè)標簽方法模式被元表所替代。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 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 上的改動(dòng)
lua_open 不再需要堆棧大小作為參數(堆棧是動(dòng)態(tài)的)。
lua_pushuserdata 已經(jīng)被廢除了。使用 lua_newuserdata 或 lua_pushlightuserdata 來(lái)代替它。
Lua 完整語(yǔ)法參考
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 | local function 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
21:51 |
添加評論 |
發(fā)送消息 |
固定鏈接 |
查看引用通告 (0) | |
LuaLua - 獨立程序6 - Lua 獨立程序 Lua Stand-alone
盡管Lua被設計為一種內嵌于C 語(yǔ)言宿主程序中的擴展語(yǔ)言,它還是經(jīng)常被用作一個(gè)獨立程序語(yǔ)言。一個(gè)Lua的解釋程序將Lua作為一個(gè)獨立的語(yǔ)言,我們稱(chēng)之為簡(jiǎn)化的 lua,它提供了標準的發(fā)行版本。獨立的解釋器包含了所有標準庫加上反射性的調試接口。它的使用方式如下:
lua [options] [script [args]]
options 可以是以下內容:
- 將 標準輸入(stdin) 當作文件執行;
-e stat 執行字符串 stat;
-l file “需要”file 文件;
-i 在運行腳本后進(jìn)入交互模式;
-v 打印版本信息;
-- 停止處理選項。
在停止處理選項后,lua 運行所給的腳本,傳遞所給參數 args。當無(wú)參數調用時(shí),lua 就像 stdin 是程序的終結時(shí) 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 ngets the number of arguments after the script name. Any argumentsbefore 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.
在交互模式中,如果你寫(xiě)入了一個(gè)不完整的語(yǔ)句,解釋器將等待你的完成。
If the global variable _PROMPT is defined as astring, then its value is used as the prompt. Therefore, the prompt canbe 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 將其變成可執行程序,并且通過(guò) #! 形式,例如
#!/usr/local/bin/lua
(當然,Lua解釋器的位置可能有所不同,如果 lua 在你的 PATH 中,那么
#!/usr/bin/env lua
就是一個(gè)更通用的解決方案。)
21:48 |
添加評論 |
發(fā)送消息 |
固定鏈接 |
查看引用通告 (0) | |
LuaLua - 標準庫5 - 標準庫
The standard libraries provide useful functions that are implementeddirectly through the C API. Some of these functions provide essentialservices to the language (e.g., type and getmetatable);others provide access to "outside" services (e.g., I/O); and otherscould be implemented in Lua itself, but are quite useful or havecritical performance to deserve an implementation in C (e.g., sort).
All libraries are implemented through the official C API and areprovided as separate C modules. Currently, Lua has the followingstandard libraries:
基本庫 basic library;
字符串操作 string manipulation;
表操作 table manipulation;
數學(xué)函數 (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 notinclude this library in your application, you should check carefullywhether you need to provide some alternative implementation for some ofits 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 smallerthan 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).
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.
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 Luais 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 noerrors, 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 onlyavailable on some platforms (Windows, Linux, Solaris, BSD, plus otherUnix systems that support the dlfcn standard).
loadstring (string [, chunkname])
Loads a string as a Lua chunk (without running it). If there are noerrors, 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 firstargument 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.
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 tostringfunction to convert them to strings. This function is not intended forformatted output, but only as a quick way to show a value, typicallyfor 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 requirereturns 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.
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 thenumeral. The base may be any integer between 2 and 36, inclusive. Inbases 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 areasonable 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.
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 containingthe 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 errfunction with the original error object, and returns a status code. Itsfirst result is the status code (a boolean), which is true if the callsucceeds 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. fmust be a Lua function. Returns a function that resumes the coroutineeach time it is called. Any arguments passed to the function behave asthe 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 coroutinecannot be running neither a C function, nor a metamethod, nor aniterator. 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. Whenindexing a string in Lua, the first character is at position 1 (notat 0, as in C). Indices are allowed to be negative and are interpretedas indexing backwards, from the end of the string. Thus, the lastcharacter 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 tothe number of arguments, in which each character has the internalnumerical 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 alluppercase letters changed to lowercase. All other characters are leftunchanged. The definition of what is an uppercase letter depends on thecurrent 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 alllowercase letters changed to uppercase. All other characters are leftunchanged. The definition of what is a lowercase letter depends on thecurrent locale.
Returns a formatted version of its variable number of argumentsfollowing the description given in its first argument (which must be astring). 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 qoption formats a string in a form suitable to be safely read back bythe Lua interpreter: The string is written between double quotes, andall double quotes, newlines, and backslashes in the string arecorrectly 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 endstring.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 calledevery time a match occurs, with all captured substrings passed asarguments, in order; if the pattern specifies no captures, then thewhole match is passed as a sole argument. If the value returned by thisfunction 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 `*′, whichmatches 0 or more repetitions of characters in the class. Theserepetition items will always match the longest possible sequence;
a single character class followed by `+′, whichmatches 1 or more repetitions of characters in the class. Theserepetition 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 s 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 tablerepresents an array or a list. For those functions, an importantconcept 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.
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 compis 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. Returnsthe 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 thestandard C math library. (Some have slightly different names.) Itprovides 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 onlyinterfaces to the corresponding functions in the C library. Alltrigonometric functions work in radians (previous versions of Lua useddegrees). 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 areoperations to set a default input file and a default output file, andall input/output operations are over those default files. The secondstyle 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 textmode), and sets its handle as the default input file. When called witha file handle, it simply sets that file handle as the default inputfile. When called without parameters, it returns the current defaultinput 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 iteratorfunction that, each time it is called, returns a new line from thefile. 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 theend, 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 astring (or a number) with the characters read, or nil if itcannot read data with the specified format. When called withoutformats, it uses a default format that reads the entire next line (seebelow).
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 timerepresenting the date and time specified by the given table. This tablemust 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 yoursystem. In Posix, Windows, and some other systems, this number countsthe number of seconds since some given start time (the "epoch"). Inother systems, the meaning is not specified, and the number returned bytime 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 temporaryfile. The file must be explicitly opened before its use and removedwhen no longer needed.
This function is equivalent to the tmpnamC function, and many people (and even some compilers!) advise againstits use, because between the time you call this function and the timeyou open the file, it is possible for another process to create a filewith the same name.
5.8 - The Reflexive Debug Interface
The debug library provides the functionality of thedebug interface to Lua programs. You should exert care when using thislibrary. The functions provided here should be used exclusively fordebugging and similar tasks, such as profiling. Please resist thetemptation to use them as a usual programming tool: They can be veryslow. 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 thatthe user enters. Using simple commands and other debug facilities, theuser can inspect global and local variables, change their values,evaluate s, 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 hookfunction, the current hook mask, and the current hook count (as set bythe debug.sethook function).
debug.getinfo (function [, what])
This function returns a table with information about a function. Youcan give the function directly, or you can give a number as the valueof 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 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 levelof the stack. (The first parameter or local variable has index 1, andso 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.
21:43 |
添加評論 |
發(fā)送消息 |
固定鏈接 |
查看引用通告 (0) | |
LuaLua - 調試接口4 - 調試接口 The Debug Interface
Lua 沒(méi)有內置的調試設施。它使用一種特殊的接口,這種接口依賴(lài)函數和 鉤子(hooks)。該接口允許構造不同種類(lèi)的調試器,分析器以及其他工具用以從解釋器得到所需的信息。
4.1 - 堆棧及函數信息 Stack and Function Information
得到解釋程序運行時(shí)堆棧信息的主要函數是:
int lua_getstack (lua_State *L, int level, lua_Debug *ar);
這個(gè)函數用一個(gè)指定等級的函數的 activation record 的標示符填充一個(gè) lua_Debug 結構,等級 0 是當前運行函數,然而等級 n+1 是在等級 n 上調用的函數。當沒(méi)有錯誤發(fā)生時(shí),lua_getstack 返回 1;當在比棧更深的等級上調用的時(shí)候,它返回 0;
lua_Debug 結構被用來(lái)攜帶一個(gè)處于活動(dòng)狀態(tài)的函數的各種信息:
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);
這個(gè)函數發(fā)生錯誤是返回 0 (舉個(gè)例子,一個(gè)無(wú)效的 what 選項)。what 字符串中的每個(gè)字符選擇填充一些 ar 結構的字段,把上面在 lua_Debug 定義中用圓括號括起來(lái)的字母作為指示: `S′ 填充在 source, linedefined 和 what 字段中;`l′ 填充在 currentline 字段中,等等...。而且,`f′ 將正在運?性謁燃渡系暮谷攵顏弧?
想要從一個(gè)不處于活動(dòng)狀態(tài)的函數那得到信息(就是不在棧上的函數),你需要將其壓入棧并且用 >′ 作為 what 字符串的開(kāi)始。舉個(gè)例子,要知道函數 f 定義在第幾行,你需要這樣寫(xiě)
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 如果函數在一個(gè)字符串中定義,那么 source 就是那個(gè)字符串。如果函數定義在一個(gè)文件中,source 開(kāi)始于一個(gè) `@′ 后面跟隨文件名。
short_src 一個(gè)可打印版的 source,用于錯誤信息。
linedefined 函數定義起始的行號。
what 如果這是一個(gè)Lua函數,顯示 "Lua" 字符串, "C" 為C 函數,"main" 如果這是一個(gè)語(yǔ)句段的main部分,"tail" 如果這是一個(gè)做了尾部調用的函數。在后面的情況里,Lua 沒(méi)有其他關(guān)于這個(gè)函部的信息。
currentline 代表當前函數執行到的行數。如果沒(méi)有行信息可用,currentline 被設置為 -1。
name 一個(gè)所給函數合理的函數名。因為函數在Lua中屬于第一類(lèi)值,它們沒(méi)有固定的名字:一些函數可能是多個(gè)全局變量的值,其他的可能只儲存在一個(gè)表字段里。lua_getinfo 函數檢測函數如何被調用或者是否為一個(gè)全局變量的值以尋找一個(gè)合適的名字。如果找不到合適的名字,name 被設置為 NULL。
namewhat name 字段的解釋。根據函數如何被調用,namewhat 的值可以是 "global", "local", "method", "field" 或者 "" (空字符串)。(當沒(méi)有其他可選項的時(shí)候Lua使用空字符串代替)
nups 函數上值的數量。
4.2 - 操作局部變量和上值 Manipulating Local Variables and Upvalues
為了更多的操作局部變量和上值,調試接口使用索引:第一個(gè)參數或者局部變量索引為 1,以此類(lèi)推,直到最后一個(gè)活動(dòng)的局部變量。整個(gè)函數中的活動(dòng)的上值沒(méi)有特定的順序。
下面的函數允許操作一個(gè)所給激活記錄的局部變量:
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 必須是一個(gè)被前一個(gè) lua_getstack 調用填充的有效的激活記錄或者作為一個(gè)鉤子函數的參數(見(jiàn) 4.3)。lua_getlocal 獲得一個(gè)局部變量的索引 n,將變量的值壓入棧,并且返回變量名。lua_setlocal 從棧頂分配一個(gè)值給變量并且返回變量名。當索引超過(guò)活動(dòng)的局部變量的數量時(shí),兩個(gè)函數都返回 NULL。
以下的函部可以操作所給函數的上值(不像局部變量,函數的上值即使在函數不處于活動(dòng)狀態(tài)的時(shí)候都可以被訪(fǎng)問(wèn)):
const char *lua_getupvalue (lua_State *L, int funcindex, int n); const char *lua_setupvalue (lua_State *L, int funcindex, int n);
這些函數可以作為L(cháng)ua 函數使用也可以作為C 函數使用。(作為L(cháng)ua 函數,上值是函數外部使用的局部變量,因此它被包含在函數閉包中。)funcindex 指向棧中的一個(gè)函數。lua_getupvalue 得到一個(gè)上值的索引 n,將上值的值壓入棧,并返回其變量名。lua_setupvalue 從棧頂分配一個(gè)值給上值并返回變量名。當索引大于上值數量時(shí),兩個(gè)函數都返回 NULL。對于C 函數來(lái)說(shuō),這些函數使用空字符串作為所有上值的變量名。
作為一個(gè)例子,下面的函數列舉了所給等級的棧中的函數的所有局部變量名和上值變量名:
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 functionsthat are called during the program execution. A hook may be called infour 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 aboutto start the execution of a new line of code, or when it jumps back inthe code (even to the same line). (This event only happens while Lua isexecuting 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.
21:41 |
添加評論 |
發(fā)送消息 |
固定鏈接 |
查看引用通告 (0) | |
LuaLua - API3 - 應用程序接口
這一節描述Lua中的C API,這是對于宿主程序可用的C函數集合,用以和Lua通訊。所有的API函數及其相關(guān)類(lèi)型和常量都聲明在頭文件lua.h中。
即便每次我都使用“函數”這個(gè)詞,任何設施在A(yíng)PI里面都可能被一個(gè)宏所替代。所有這些宏(macro)都只使用一次它的參數(除了第一個(gè)參數、這個(gè)每次總是一個(gè)Lua狀態(tài)),所以不會(huì )產(chǎn)生隱藏的副作用。
3.1 - 狀態(tài)
Lua庫是可重入的(reentrant)的:它沒(méi)有全局變量。整個(gè)Lua解釋器的狀態(tài)(全局變量、棧、等等)儲存在一個(gè)動(dòng)態(tài)分配的 lua_State 結構類(lèi)型中。一個(gè)指向這個(gè)狀態(tài)的指針必須作為庫中每一個(gè)函數的第一個(gè)參數,除了 lua_open 這個(gè)函數。該函數從最開(kāi)始創(chuàng )建一個(gè)Lua狀態(tài)。
在調用任何API函數之前,你必須通過(guò)調用 lua_open 創(chuàng )建一個(gè)狀態(tài):
lua_State *lua_open (void);
調用 lua_close 去釋放這個(gè)由 lua_open 創(chuàng )建的狀態(tài):
void lua_close (lua_State *L);
這個(gè)函數銷(xiāo)毀所有被給予Lua狀態(tài)的對象(調用相應的垃圾收集元方法)并且釋放那個(gè)狀態(tài)使用的所有動(dòng)態(tài)內存。在個(gè)別的平臺上,你或許不需要調用這個(gè)函數,因為當宿主程序結束的時(shí)候會(huì )自然的釋放所有的資源。另一方面,長(cháng)時(shí)間運行的程序,像一些守護進(jìn)程或者Web服務(wù)器,可能需要立即釋放那些不需要的狀態(tài)資源,以避免占用太多內存。
3.2 - 堆棧和索引
Lua使用一個(gè)來(lái)自于C語(yǔ)言的 虛擬棧(virtual stack) 傳遞值。棧里面的每一個(gè)元素都代表一個(gè)Lua值 (nil, number, string, etc.)。
只要Lua調用C語(yǔ)言函數,這個(gè)所調用的函數將得到一個(gè)新的棧,這個(gè)棧將獨立于先前的棧以及那些仍然活躍的C函數的棧。這個(gè)棧最初包含了C函數的所有參數,并且這也會(huì )存放C函數的返回值(見(jiàn) 3.16)。
為了方便起見(jiàn),大多數查詢(xún)操作的API不需要遵守一個(gè)嚴格的棧定義(注:即不需要遵循FILO)。他們可以使用 索引(index) 引用任何棧中元素:一個(gè)正數索引代表了棧中的絕對位置(從1開(kāi)始);一個(gè)負數索引代表了從棧頂的偏移量。更特別的是,如果棧有 n 個(gè)元素,那么索引 1 代表第一個(gè)元素(這就是說(shuō),這個(gè)元素首先入棧)并且索引 n 代表了最后一個(gè)元素;索引 -1 也代表了最后一個(gè)元素(也就是棧頂)并且索引 -n 代表了第一個(gè)元素。我們說(shuō)一個(gè)索引存在于 1 和棧頂之間是有效的,換句話(huà)說(shuō),如果 1 <= abs(index) <= top。
在任何時(shí)間里,你可以調用 lua_gettop 得到棧頂元素的索引:
int lua_gettop (lua_State *L);
因為索引從 1 開(kāi)始,lua_gettop 的結果等于棧中的元素數量(如果是0就意味著(zhù)棧為空)。
當你與Lua API交互的時(shí)候,你有責任控制堆棧以避免溢出。。這個(gè)函數
int lua_checkstack (lua_State *L, int extra);
使棧的大小增長(cháng)為 top + extra 個(gè)元素;如果無(wú)法將棧增加到那個(gè)大小將返回false。這個(gè)函數從不對棧進(jìn)行收縮;如果棧已經(jīng)比新的大小更大,它將不產(chǎn)生任何作用那個(gè)。
只要Lua調用C 函數,它必須至少保證 LUA_MINSTACK 這個(gè)棧中的位置是可用的。LUA_MINSTACK 定義在 lua.h 中,它的值是 20,所以你不需要總擔心??臻g除非你的代碼通過(guò)循環(huán)將元素壓入棧。
大多數插敘函數接受指向有效??臻g的索引,那就是說(shuō),索引達到??臻g的最大值是你需要使用 lua_checkstack。這樣的索引稱(chēng)為可接受索引(acceptable indices)。更正規的說(shuō)法,我們給出一個(gè)嚴格的定義如下:
(index < 0 && abs(index) <= top) || (index > 0 && index <= stackspace)
注意,0永遠不是一個(gè)可接受索引。
除非另外說(shuō)明,任何函數接受有效索引可以被稱(chēng)為是 偽索引(pseudo-indices),這些索引代表一些Lua值可以被C 代碼訪(fǎng)問(wèn)但是卻不存在于棧中。假索引通常用于訪(fǎng)問(wèn)全局環(huán)境變量,注冊表,和一個(gè)C 函數的上值(見(jiàn) 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,那么所有棧元素會(huì )被清除。在 lua.h 里面定義了一個(gè)有用的宏
#define lua_pop(L,n) lua_settop(L, -(n)-1)
用以從棧中彈出 n 個(gè)元素。
lua_pushvalue 將一個(gè)索引指向的元素的拷貝壓入棧。 lua_remove 刪除指定位置的元素,將該元素上方的所有元素下移以填滿(mǎn)空缺。lua_insert 將棧頂元素移動(dòng)到指定位置,將該位置以上的元素上移。lua_replace 將棧頂元素移動(dòng)到指定位置而不移動(dòng)其他任何其他元素(因此替代了給定位置的元素的值)。所有這些函數只接受有效的索引。(你不能使用偽索引調用 lua_remove 或 lua_insert,因為他們不代表棧中的位置。)
舉個(gè)例子,如果棧開(kāi)始于 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 - 堆棧查詢(xún)
下面的函數可以用來(lái)檢測棧內元素的類(lèi)型:
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 返回棧中元素值的類(lèi)型,如果所有索引無(wú)效則返回 LUA_TNONE(就是說(shuō)如果棧為空)。這些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 當對象與所給類(lèi)型兼容的時(shí)候,其他情況返回 0。 lua_isboolean 是一個(gè)例外:它只針對布爾值時(shí)才會(huì )成功(否則將是無(wú)用的,因為任何值都是一個(gè)布爾值)。這些函數對于無(wú)效引用返回 0。 lua_isnumber 接受數字和用數字表示的字符串;lua_isstring 接受字符串和數字(見(jiàn) 2.2.1);lua_isfunction 接受Lua函數和C函數; lua_isuserdata 接受完整的和輕量的用戶(hù)數據。要區分C 函數和Lua 函數,你可以使用 lua_iscfunction。要區分用戶(hù)數據,你可以使用 lua_islightuserdata。要區分數字還是用數字表示的字符串,你可以使用 lua_type。
這些API還包含了用于比較棧中的兩個(gè)值的操作:
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_equal 和 lua_lessthan 在比較他們的副本的時(shí)候是等效的(見(jiàn) 2.5.2)。 lua_rawequal 用于比較基本類(lèi)型但不包括元方法。如果有任何形式的無(wú)效索引,這些函數都返回 0(false)。
3.5 - 堆棧取值
為了將一個(gè)棧中的值轉變?yōu)橹付ǖ腃語(yǔ)言類(lèi)型,你需要使用以下的轉換函數:
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);
這些函數由任何可接受索引作為參數進(jìn)行調用。當遇到一個(gè)無(wú)效索引,函數表現為就好像接受了一個(gè)錯誤類(lèi)型的值。
lua_toboolean 將索引指向的Lua值轉換為C語(yǔ)言類(lèi)型的布爾值(0 或 1)。就像所有Lua中的測試一樣,任何不等于 false 或者 nil 的Lua值通過(guò) lua_toboolean 都將返回 1;否則將返回 0。當然,如果是一個(gè)無(wú)效索引,也將返回 0。(如果你只想接受真實(shí)的布爾值,使用 lua_isboolean 去測試值的類(lèi)型。)
lua_tonumber 將索引指向的Lua值轉換成一個(gè)數字(默認情況下,lua_Number 是 double類(lèi)型)。Lua值必須是一個(gè)數字或者可轉化為數字的字符串(見(jiàn) 2.2.1);否則,lua_tonumber 返回 0。
lua_tostring 將索引指向的Lua值轉換成字符串(const char*)。Lua值必須是一個(gè)字符串或者數字;否則,函數返回 NULL。如果值是一個(gè)數字,lua_tostring 會(huì )將棧中的真實(shí)值變成一個(gè)字符串類(lèi)型。(當 lua_tostring 應用于鍵時(shí)這個(gè)改變將引起 lua_next 的混亂。)lua_tostring 在Lua 狀態(tài)內部返回一個(gè)字符串的指針。這個(gè)字符串總是以 0('/0')結尾,就像C 語(yǔ)言里的一樣,但是也可能包含其他 0 在其中。如果你不知道一個(gè)字符串中是否存在 0 ,你可以使用 lua_strlen 得到它的實(shí)際長(cháng)度。因為L(cháng)ua具有垃圾收集機制,所以不能保證 lua_tostring 返回的指針仍然有效,當相應的值從棧中刪除之后。如果你在當前函數返回之后還需要這個(gè)字符串,你需要復制它并且將它存入注冊表(見(jiàn) 3.18)。
lua_tocfunction 將棧中的值轉換為C 函數。這個(gè)值必須是一個(gè)C 函數;否則,lua_tocfunction 返回 NULL。類(lèi)型 lua_CFunction 在 3.16 中有詳細解釋。
lua_tothread 將棧中的值轉換為L(cháng)ua線(xiàn)程(被描繪成 lua_State *)。這個(gè)值必須是一個(gè)線(xiàn)程;否則;lua_tothread 返回 NULL。
lua_topointer 將棧中?鬧底晃ㄓ玫腃 語(yǔ)言指針(void *)。這個(gè)值可能是一個(gè)用戶(hù)數據、表、線(xiàn)程、或者函數;否則,lua_topointer 返回 NULL。Lua保證同種類(lèi)型的不同對象將返回不同指針。沒(méi)有直接的方法將指針轉換回原來(lái)的值。這個(gè)函數通常用于調試。
lua_touserdata 在 3.8 中有詳細解釋。
3.6 - 將值壓入堆棧
以下的API函數將C 語(yǔ)言值壓入棧:
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);
這些函數接受一個(gè)C 語(yǔ)言值,將其轉換成相應的Lua 值,并且將結果壓入棧。需要特別注意的是,lua_pushlstring 和 lua_pushstring 將對所給的字符串做一個(gè)內部拷貝。lua_pushstring 只能壓入合適的C 語(yǔ)言字符串(也就是說(shuō),字符串要以 '/0' 結尾,并且不能包含內嵌的 0);否則,你需要使用更通用的 lua_pushlstring 函數,它可以接受一個(gè)指定的大小。
你可以壓入“格式化的”字符串:
const char *lua_pushfstring (lua_State *L, const char *fmt, ...); const char *lua_pushvfstring (lua_State *L, const char *fmt, va_list argp);
這些函數將格式化的字符串壓入棧并且返回這個(gè)字符串的指針。它們和 sprintf、vsprintf 類(lèi)似,但是有一些重要的不同之處:
你不需要為結果分配空間:結果是Lua字符串并且Lua會(huì )關(guān)心內存分配問(wèn)題(和內存釋放問(wèn)題,通過(guò)垃圾收集機制)。
轉換受到限制。這里沒(méi)有標志、寬度或精度。轉換操作的修飾符可以是簡(jiǎn)單的`%%′(在字符串中插入一個(gè)`%′),`%s′(插入一個(gè)沒(méi)有大小限制的以 0 結尾的字符串),`%f′(插入一個(gè) lua_Number),`%d′(插入一個(gè) int),`%c′(插入一個(gè) int 作為一個(gè)字符)。
這個(gè)函數
void lua_concat (lua_State *L, int n);
連接棧頂的 n 個(gè)值,將它們彈出,并且將結果留在棧頂。如果 n 為 1,結果是單個(gè)字符串(也就是說(shuō),函數什么也不做);如果 n 是 0,結果是空字符串。連接的完成依據Lua的語(yǔ)義(見(jiàn) 2.5.4)。
3.7 - 控制垃圾收集
Lua使用兩個(gè)數字控制垃圾收集循環(huán)。一個(gè)數字表示Lua使用的動(dòng)態(tài)內存的字節數,另一個(gè)是閥值。(見(jiàn) 2.9)。一個(gè)數字表示Lua使用的動(dòng)態(tài)內存的字節數,另一個(gè)是閥值。當內存字節數到達閥值時(shí),Lua就運行垃圾收集器,來(lái)釋放死對象的空間。一旦字節計數器被調整,那么閥值就會(huì )被設為字節計數器新值的兩倍。
你可以通過(guò)以下的函數得到這兩個(gè)量的當前值:
int lua_getgccount (lua_State *L); int lua_getgcthreshold (lua_State *L);
它們的返回值的單位都是千字節(K bytes)。你可以通過(guò)下面的函數改變閥值
void lua_setgcthreshold (lua_State *L, int newthreshold);
然后,新的閥值得單位也是千字節。當你調用這個(gè)函數,Lua設置閥新值并且和字節計數器作比較。如果新的閥值小于字節計數器,Lua將立刻運行垃圾收集器。特別是 lua_setgcthreshold(L,0) 強迫進(jìn)行垃圾收集。在這之后,一個(gè)新值根據先前的規則被設置。
3.8 - 用戶(hù)數據類(lèi)型 (Userdata)
用戶(hù)數據代表了Lua中使用的C語(yǔ)言值。Lua支持兩種用戶(hù)數據:完整用戶(hù)數據(full userdata) 和 輕量用戶(hù)數據(light userdata)。
一個(gè)完整用戶(hù)數據代表了一塊內存。它是一個(gè)對象(像一個(gè)表):你必須創(chuàng )建它,它有自己的元表,當它被回收的時(shí)候你可以檢測到。一個(gè)完整用戶(hù)數據只能與自己相等(基于原始的相等規則)。
一個(gè)輕量用戶(hù)數據代表一個(gè)指針。它是?桓鮒擔ㄏ褚桓鍪鄭耗悴⒚揮寫(xiě)唇ㄋ?,它也脫]性懟?,它不能睋Q厥眨ㄒ蛭游幢淮唇ǎ?。菎埧記](méi)菹嗟鵲奶跫侵剛脛趕虻牡刂廢嗤?
在Lua 代碼里,沒(méi)辦法測試用戶(hù)數據類(lèi)型是完整的還是輕量的;兩者都是 用戶(hù)數據類(lèi)型。在C 代碼里,如果是完整用戶(hù)數據,lua_type 返回 LUA_TUSERDATA,反之,返回 LUA_TLIGHTUSERDATA。
你可以通過(guò)下面的函數創(chuàng )建完整用戶(hù)數據:
void *lua_newuserdata (lua_State *L, size_t size);
這個(gè)函數根據指定大小分配一個(gè)內存塊,將用戶(hù)數據的地址壓入棧并且返回這個(gè)地址。
要將輕量用戶(hù)數據壓入棧,你需要使用 lua_pushlightuserdata(見(jiàn) 3.6)。
lua_touserdata (見(jiàn) 3.5)用來(lái)取回用戶(hù)數據的值。當你用在完整用戶(hù)數據的時(shí)候,它返回這個(gè)塊的地址,當你用在輕量用戶(hù)數據的時(shí)候,它返回它的指針,當你用在非用數據的時(shí)候,返回 NULL。
當Lua回收一個(gè)完整用戶(hù)數據,它調用該用戶(hù)數據的 gc 元方法,然后釋放該用戶(hù)數據相應的內存。
3.9 - 元表 (Metatables)
下面的函數允許你操作對象的元表:
int lua_getmetatable (lua_State *L, int index); int lua_setmetatable (lua_State *L, int index);
lua_getmetatable 將所給對象的元表壓入棧。如果索引無(wú)效,或這個(gè)對象不含有元表,該函數返回 0 并且不對棧進(jìn)行任何操作。
lua_setmetatable 從棧中彈出一張表并且為所給對象設置一個(gè)新的元表。當無(wú)法給所給對象設置元表的時(shí)候該函數返回 0(也就是說(shuō),這個(gè)對象既不是一個(gè)用戶(hù)數據也不是一張表);盡管那樣,它仍從棧中彈出這張表。
3.10 - 加載Lua語(yǔ)句段
你可以通過(guò) lua_load 加載一個(gè)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 --- 沒(méi)有錯誤
LUA_ERRSYNTAX --- 預編譯時(shí)句法錯誤
LUA_ERRMEM --- 內存分配錯誤
如果沒(méi)有錯誤,lua_load 將編譯過(guò)的語(yǔ)句段作為L(cháng)ua 函數壓入棧頂。否則,它將壓入一個(gè)錯誤信息。
lua_load 自動(dòng)檢測語(yǔ)句段的類(lèi)型是文本還是二進(jìn)制數據,并且根據類(lèi)型將其載入(見(jiàn)程序 luac)。
lua_load 使用一個(gè)用戶(hù)提供的 reader 函數讀取語(yǔ)句段的內容。當需要調用其它段時(shí),lua_load 調用 reader,傳遞其 data 參數。必須返回指向語(yǔ)句段所在的新內存塊的指針,并將段大小設置為 0。為了標志塊尾,reader 必須返回 NULL。reader 函數可以返回任何大于零的值。
在當前的實(shí)現中,reader 函數不能調用任何Lua 函數;為了保證這一點(diǎn),它總是會(huì )得到為 NULL 的Lua狀態(tài)。
語(yǔ)句段名(chunkname) 用于錯誤信息和調試信息(見(jiàn) 4)。
參考輔助庫 (lauxlib.c) 了解如何使用 lua_load 以及如何使用現成的函數從文件和字符串中加載語(yǔ)句段。
3.11 - 表操作
通過(guò)調用以下函數可以創(chuàng )建表:
void lua_newtable (lua_State *L);
這個(gè)函數創(chuàng )建一張新的空表,并將其壓入棧。
要從棧中的表里讀取值,使用:
void lua_gettable (lua_State *L, int index);
index 代表表的位置。lua_gettable 從棧中彈出一個(gè)鍵,并且返回該鍵對應的值,表仍然留在堆棧中。在Lua中,這個(gè)函數可能觸發(fā)一個(gè)針對 index 事件的元方法(見(jiàn) 2.8)。想要在不調用任何元方法的情況下得到表主鍵所對應的真實(shí)值,使用這個(gè)原始(raw)版本:
void lua_rawget (lua_State *L, int index);
要將一個(gè)值儲存到棧中的一張表中,你需要將鍵壓入棧,再將值壓入棧,調用:
void lua_settable (lua_State *L, int index);
index 代表表的位置。lua_settable 從棧中彈出主鍵和值。表仍然留在棧中。在Lua中,這個(gè)操作可能觸發(fā)針對 settable 或者 newindex 事件的元方法。想要不受這些元方法的影響并且為任意表設置值,使用這個(gè)原始(raw)版本:
void lua_rawset (lua_State *L, int index);
你可以通過(guò)這個(gè)函數遍歷一張表:
int lua_next (lua_State *L, int index);
index 指向需要被遍歷的表。這個(gè)函數從堆棧中彈出一個(gè)鍵,從表中取一對鍵-值壓入棧(所給鍵的下一對)。如果沒(méi)有更多的元素,lua_next 返回 0(對棧不進(jìn)行操作)。使用一個(gè) nil 鍵標示遍歷的開(kāi)始。
一個(gè)典型的遍歷操作看起來(lái)像這樣:
/* 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 */ }
當遍歷一張表的時(shí)候,不要在鍵上直接調用 lua_tostring,除非你知道這個(gè)鍵確實(shí)是一個(gè)字符串。再次調用 lua_tostring 改變了所給索引指向的值;這使 lua_next 的調用發(fā)生混亂。
3.12 - 環(huán)境變量操作 (Manipulating Environments)
所有的全局變量保存在普通的Lua 表中,叫做環(huán)境變量。初始的環(huán)境變量被稱(chēng)作全局環(huán)境變量。這張表總是在 LUA_GLOBALSINDEX 這個(gè)偽索引處。
要訪(fǎng)問(wèn)或改變全局變量的值,你可以對環(huán)境變量表使用常規的表操作。舉個(gè)例子,存取一個(gè)全局變量的值:
lua_pushstring(L, varname); lua_gettable(L, LUA_GLOBALSINDEX);
你可以改變一個(gè)Lua 線(xiàn)程的全局環(huán)境變量通過(guò) lua_replace 函數。
以下的函數提供獲取、設置Lua函數的環(huán)境變量的功能:
void lua_getfenv (lua_State *L, int index); int lua_setfenv (lua_State *L, int index);
lua_getfenv 將堆棧中 index 索引指向的函數的環(huán)境變量表壓入棧。如果函數是一個(gè)C 函數,lua_getfenv 將全局環(huán)境變量壓入棧。lua_setfenv 從棧中彈出一張表并且將其設置為棧中 index 索引處的函數的新環(huán)境變量。如果給定索引處的對象不是一個(gè)Lua 函數,lua_setfenv 返回 0。
3.13 - 將表作為數組使用 Using Tables as Arrays
有一些 API 能夠幫助我們將Lua 表作為數組使用,也就是說(shuō),表只由數字作為索引:
void lua_rawgeti (lua_State *L, int index, int n); void lua_rawseti (lua_State *L, int index, int n);
lua_rawgeti 將表中的第 n 個(gè)元素放入堆棧中的指定位置 index。lua_rawseti 將堆棧中指定位置 index 處的表中的第 n 個(gè)元素的值設定為棧頂的值,并將原來(lái)的值從棧中刪除。
3.14 - 調用函數
定義在Lua 中的函數和C語(yǔ)言函數經(jīng)過(guò)注冊就可以被宿主程序調用。這些調用必須遵循以下協(xié)議:首先,被調用的函數被壓入棧;然后,函數的參數必須順序(direct order)輸入,也就是說(shuō),第一個(gè)參數需要被第一個(gè)輸入。最后,函數通過(guò)下面的方法調用:
void lua_call (lua_State *L, int nargs, int nresults);
nargs 是你壓入棧的參數的數量。所有參數和函數值從堆棧中彈出,并且函數結果被壓入棧。返回值的數量被調整為 nresults,除非 nresults 是 LUA_MULTRET。在那種情況下,所有函數結果都被壓入棧。Lua 會(huì )檢測返回值是否適合??臻g。函數返回值按順序被壓入棧(第一個(gè)返回值首先入棧),所以調用結束后最后一個(gè)返回值在棧頂。
下面的例子展示宿主程序如何可以和這個(gè)Lua 代碼等效:
a = f("how", t.x, 14)
這里是C 語(yǔ)言里的做法:
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 */
注意上面的代碼是“平衡的”:在它結束時(shí),堆棧返回原來(lái)的配置。這個(gè)被認為是良好的編程實(shí)踐。
(為了展示細節,我們只用Lua 提供的原始 API 完成這個(gè)例子。通常程序員定義并使用幾個(gè)宏和輔助庫函數在Lua 中提供高級存取功能。請參考例子中標準庫函數的源代碼。)
3.15 - 受保護調用 Protected Calls
當你通過(guò) lua_call 調用一個(gè)函數,所調用函數內部產(chǎn)生的錯誤將向上傳遞(通過(guò)一個(gè) longjmp)。如果你需要處理錯誤,你應該使用 lua_pcall:
int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc);
nargs 和 nresults 在 lua_call 中有相同的意義。如果調用過(guò)程中沒(méi)有錯誤,lua_pcall 的行為非常像 lua_call 。然而,如果有錯誤,lua_call 會(huì )捕獲它,將一個(gè)單一值(錯誤信息)壓入棧,并且返回錯誤代碼。像 lua_call ,lua_pcall 總是從棧中刪除函數和它的參數。
如果 errfunc 是 0,所返回的錯誤信息就是原始的錯誤信息。另外,errfunc 給出一個(gè)指向錯誤處理函數(error handler function)的棧索引。(在當前的實(shí)現中,索引不能為偽索引。)假設運行時(shí)錯誤,函數將和錯誤信息一起被調用,并且他的返回值將是 lua_pcall 返回的信息。
錯誤處理函數被用來(lái)為錯誤信息增加更多的調試信息,例如棧的記錄。這樣的信息在 lua_pcall 調用返回后將不能被收集,因此棧已經(jīng)被解開(kāi)了。
如果 lua_pcall 函數調用成功返回 0,否則返回以下的一個(gè)錯誤代碼(定義在 lua.h):
LUA_ERRRUN --- 運行時(shí)錯誤
LUA_ERRMEM --- 內存分配錯誤。這樣的錯誤下,Lua 不調用錯誤處理函數
LUA_ERRERR --- 運行錯誤處理函數時(shí)發(fā)生的錯誤
3.16 - 定義C 函數
Lua可以通過(guò)C 語(yǔ)言寫(xiě)的函數進(jìn)行擴展,這些函數必須是 lua_CFunction 類(lèi)型的,作為以下定義:
typedef int (*lua_CFunction) (lua_State *L);
一個(gè)C 函數接收一個(gè)Lua 狀態(tài)并且返回一個(gè)整數,數值需要返回給Lua。
為了正確的和Lua 通訊,C 函數必須遵循以下協(xié)議,它定義了參數和返回值傳遞的方法:一個(gè)C函數在它的堆棧中從Lua獲取順序(第一個(gè)參數首先入棧)參數。所以,當函數開(kāi)始時(shí),第一個(gè)參數在索引位置 1。為了將返回值傳遞給Lua,一個(gè)C函數將它們順序壓入棧,并且返回它們的數量。任何在堆棧中位于返回值以下的值都將被Lua 適當的解除。就像Lua 函數一樣,一個(gè)C 函數被Lua調用也可以返回很多結果。
作為一個(gè)例子,下面的函數接收一個(gè)任意數量的數字參數并且返回它們的平均值和總合:
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 */ }
下面是一些便利的宏用來(lái)在Lua中注冊一個(gè)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 中的函數名和一個(gè)指向函數的指針。這樣,上面的C 函數foo可以在Lua中被注冊為 average 并被調用。
lua_register(L, "average", foo);
3.17 - 定義C 函數關(guān)閉 Defining C Closures
當一個(gè)C 函數被創(chuàng )建后,它可以與一些值關(guān)聯(lián),這樣創(chuàng )建了一個(gè) C 閉包(C closure);這些值可以被隨時(shí)被函數訪(fǎng)問(wèn)。為了使值和C 函數關(guān)聯(lián),首先這些值要被壓入棧(有多個(gè)值時(shí),第一個(gè)值先入),然后這個(gè)函數
void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n);
被用來(lái)將C 函數壓入棧,通過(guò)參數 n 告知應該有多少個(gè)值和該函數關(guān)聯(lián)(lua_pushcclosure 將這些值從堆棧中彈出);事實(shí)上,這個(gè)宏 lua_pushcfunction 被定義作為 lua_pushcfunction 將 n 設置為 0。
然后,無(wú)論何時(shí)C 函數被調用,那些值被定為于指定的偽索引處。那些偽索引有一個(gè)宏 lua_upvalueindex 產(chǎn)生。第一個(gè)和函數關(guān)聯(lián)的值在 lua_upvalueindex(1) 處,其他的以此類(lèi)推。當 n 比當前函數的上值大時(shí),lua_upvalueindex(n) 會(huì )產(chǎn)生一個(gè)可接受的索引(但是無(wú)效)。
C語(yǔ)言函數和關(guān)閉的例子,請參考Lua官方發(fā)行版中的標準庫(src/lib/*.c)。
3.18 - 注冊表 Registry
Lua提供了一個(gè)注冊表,一張可以被所有C 代碼用來(lái)儲存任何需要儲存的Lua值的預定義表,特別是如果C 代碼需要維護C 函數以外存活的Lua值。這張表總是位于 LUA_REGISTRYINDEX 這個(gè)為索引處。任何C 語(yǔ)言庫可以將數據儲存在這張表中,只要它選擇的鍵和其他庫不同。典型的做法是你應該使用字符串作為主鍵包含你的庫名或者在你的代碼中使用一個(gè)包含C 對象地址的輕量用戶(hù)數據。
在注冊表中的整數鍵被引用機制所使用,由輔助庫實(shí)現,因此不應該被用作其它用途。
3.19 - C 中的錯誤處理 Error Handling in C
總的來(lái)說(shuō),Lua使用C longjmp 機制來(lái)處理錯誤。當Lua面對任何錯誤(例如內存分配錯誤,類(lèi)型錯誤,句法錯誤)它 升起(raises) 一個(gè)錯誤,也就是說(shuō),它做了一個(gè)長(cháng)跳躍。一個(gè)受保護的環(huán)境使用 setjmp 設置一個(gè)恢復點(diǎn);任何錯誤跳至最近最活躍的恢復點(diǎn)。
如果錯誤發(fā)生在任何受保護的環(huán)境,Lua調用 panic 函數 并且隨后調用exit(EXIT_FAILURE)。你可以將panic 函數變?yōu)橐韵聝热荨?div style="height:15px;">
你的新panic 函數可以避免程序因為沒(méi)有返回(例如通過(guò)一個(gè)長(cháng)跳躍)而退出。否則,相應的Lua 狀態(tài)將不一致;唯一安全的操作就是關(guān)閉它。
幾乎所有的API 函數都可能引起錯誤,例如導致一個(gè)內存分配錯誤。:lua_open, lua_close, lua_load 和 lua_pcall 這些的函數運行在保護模式下(也就是說(shuō),它們創(chuàng )建了一個(gè)受保護的環(huán)境并在其中運行),所以它們從不會(huì )引起錯誤。
lua_cpcall 在保護模式下調用 func。func 由一個(gè)包含 ud 的輕量用戶(hù)數據開(kāi)始。在錯誤問(wèn)題上,lua_cpcall 像 lua_pcall 一樣返回相同的錯誤代碼(見(jiàn) 3.15),加上在棧頂的一個(gè)錯誤對象;否則,返回 0,并且不對堆棧進(jìn)行任何操作。任何由 func 返回的值都被丟棄。
錯誤信息(實(shí)際上可以是任何類(lèi)型的對象)必須在棧頂。這個(gè)函數進(jìn)行一個(gè)長(cháng)跳躍,因此從來(lái)不會(huì )返回。
Lua 提供了操作線(xiàn)程的部分支?幀H綣閿卸嘞叱灘僮韉腃 語(yǔ)言庫,那么Lua能夠與其協(xié)作并且在Lua中實(shí)現相同的機制。同樣,Lua在線(xiàn)程之上實(shí)現自己的協(xié)同程序系統。以下函數用來(lái)在Lua中創(chuàng )建一個(gè)線(xiàn)程:
這個(gè)函數將線(xiàn)程壓入棧并且返回代表新線(xiàn)程的 lua_State 指針。這個(gè)返回的新?tīng)顟B(tài)與所有全局對象(例如表)共享初始狀態(tài),但是有一個(gè)獨立的運行時(shí)堆棧。
每個(gè)線(xiàn)程都有自己獨立的全局環(huán)境表。當你創(chuàng )建一個(gè)線(xiàn)程,這張表就和所給狀態(tài)一樣,但是你可以獨自更改它們。
int lua_resume (lua_State *L, int narg); int lua_yield (lua_State *L, int nresults);
你需要創(chuàng )建一個(gè)線(xiàn)程以便啟動(dòng)協(xié)同程序;然后你將函數體和事件參數壓入堆棧;然后調用 lua_resume,narg 的值代表參數的數量。當同步程序暫?;蛘呓Y束執行,函數將返回。當它返回后,棧中包含的所有值傳遞給 lua_yield,或者有主體函數返回。如果同步程序運行無(wú)誤,lua_resume 返回 0,否則返回一個(gè)錯誤代碼(見(jiàn) 3.15)。對于錯誤,堆棧只包含錯誤信息。要重起同步程序,將作為結果傳遞給 yield 的值壓入堆棧,并且調用 lua_resume。
如果C 函數像這樣調用 lua_yield,正在運行的同步程序暫停它的執行,并且調用 lua_resume 開(kāi)始讓這個(gè)協(xié)同程序返回。nresults 這個(gè)參數代表了在堆棧中作為結果傳遞給 lua_resume 的值的數量。
這一章將描述Lua的詞法、語(yǔ)法和語(yǔ)義結構。換句話(huà)說(shuō),這一章會(huì )講什么標記是合法的,他們是如何組合的,以及他們的組合是什么含義。
語(yǔ)言結構會(huì )使用常用的擴展BNF范式來(lái)解釋?zhuān)鐊a} 表示0或多個(gè)a, [a] 表示a是可選的(0個(gè)或1個(gè))。非終端字體(不能顯示的)用 斜體表示,關(guān)鍵字是粗體,其他終端符號用typewriter(等寬)字體,并用單引號引出。
Lua中的標識符(Identifiers)可以是任意的數字、字符和下劃線(xiàn)“_”,但不能以數字開(kāi)頭。這條規則符合大多數編程語(yǔ)言中的標識符的定義。(字符的具體定義要根據系統的地區設置:任何區域設置可以認同的字母表中的字母都可以用在標識符中。)
and break do else elseif end false for function if in local nil not or repeat return then true until while
Lua對大小寫(xiě)敏感:and是一個(gè)保留字,但是 And 和 AND 是兩個(gè)不一樣的、但都合法的標識符。習慣上來(lái)說(shuō),以下劃線(xiàn)開(kāi)始且后面跟著(zhù)大寫(xiě)字母的標識符 (例如 _VERSION) 是為L(cháng)ua內部變量所保留的。
+ - * / ^ = ~= <= >= < > == ( ) { } [ ] ; : , . .. ...
另外,一個(gè) `/newline′ (一個(gè)反斜杠加上一個(gè)真正的換行符)會(huì )導致字符串內的分行。字符串中的字符也可以使用轉義字符`/ddd′通過(guò)數字值來(lái)指定。ddd 是最多為3個(gè)十進(jìn)制數字的序列。Lua中的字符串也可以包含8進(jìn)制數字,包括嵌入零,它可以表示為 `/0′。
字符串也可以用雙方括號來(lái)定界[[ · · · ]]。這種括號方式的語(yǔ)法,字符串可以跨越多行,也可以包含嵌套的,同時(shí)不會(huì )轉義任何序列。方便起見(jiàn),當開(kāi)始的 `[[′ 后面緊跟著(zhù)一個(gè)換行符的話(huà),這個(gè)換行符不會(huì )包括在字符串內。舉個(gè)例子:在一個(gè)使用ASCII編碼(其中`a′ 的編碼是 97,換行符是 10,字符`1′ 是 49)的系統中,以下四種格式得到的都是同一個(gè)字符串:
注釋?zhuān)–omments) 可以在任何地方出現,必須在最前面加上雙減號 (--)。如果緊接著(zhù) -- 的文本不是 [[,那么會(huì )認為是一個(gè) 短注釋?zhuān)╯hort comment), 這一行往后到行尾都是注釋。否則,會(huì )認為是一個(gè) 常注釋?zhuān)╨ong comment),注釋直到相應的 ]]結束。長(cháng)注釋可以跨越多行,同時(shí)可以包含嵌套的 [[ · · · ]] 括號對。
Lua是一種 動(dòng)態(tài)類(lèi)型語(yǔ)言(dynamically typed language)。這意味著(zhù)變量是沒(méi)有類(lèi)型的;只有值才有。語(yǔ)言中沒(méi)有類(lèi)型定義。所有的值都包含他自身的類(lèi)型。
Lua中有八種基本類(lèi)型:nil, boolean, number, string, function, userdata, thread 和 table。 Nil 空類(lèi)型只對應 nil值,他的屬性和其他任何值都有區別;通常它代表沒(méi)有有效的值。 Boolean 布爾類(lèi)型有兩種不同的值 false and true。在Lua中, nil and false 代表成假條件;其他任何值都代表成真條件。 Number 數字類(lèi)型表示實(shí)數(雙精度浮點(diǎn)數)。(構建Lua解釋器時(shí)也可以很容易地用其他內部的表示方式表示數字,如單精度浮點(diǎn)數或者長(cháng)整型)。 String 字符串類(lèi)型表示一個(gè)字符的序列。Lua 字符串可以包含8位字符,包括嵌入的 ('/0') (見(jiàn) 2.1)。
函數是Lua中的 第一類(lèi)值(first-class values)。也就是說(shuō)函數可以保存在變量中,當作參數傳遞給其他函數,或者被當作結果返回。Lua可以調用(和處理)Lua寫(xiě)的函數和C寫(xiě)的函數 (見(jiàn) 2.5.7)。
用戶(hù)數據類(lèi)型(userdata) 提供了讓任意C數據儲存在Lua變量中的功能。這種類(lèi)型直接對應著(zhù)一塊內存,Lua中也沒(méi)有任何預先定義的操作,除了賦值和一致性比較。然而,通過(guò)使用 元表(metatables),程序員可以定義處理userdata的操作。(見(jiàn) 2.8)。 Userdata 值不能在Lua中建立或者修改,只能通過(guò) C API。這保證了宿主程序的數據完整性。
表(table) 類(lèi)型實(shí)現了聯(lián)合數組,也就是說(shuō),數組不僅可以使用數字,還能使用其他的值(除了 nil)。 而且,tables 可以是 互異的(heterogeneous),他們可以保存任何類(lèi)型的值(除了 nil)。 Tables 是Lua中唯一的數據結構機制;他們可以用來(lái)表示一般數組,特征表,集合,記錄,圖,樹(shù)等等。如果要表示記錄,Lua使用字段名作為索引。語(yǔ)言支持 a.name 這種比較優(yōu)美的表示方式,還有 a["name"]。在Lua中有幾種建立表的簡(jiǎn)便方法 (見(jiàn) 2.5.6)。
就像索引一樣,表字段的值也可以是任何類(lèi)型(除了 nil)。特別需要注意地是,由于函數是第一型的值,表字段也可以包含函數。這樣表也可以支持 方法(methods) (見(jiàn) 2.5.8)。
表,函數,和用戶(hù)數據類(lèi)型的值都是 對象(objects):變量不會(huì )包含他們的實(shí)際值,只是一個(gè)他們的引用(references)。 賦值,參數傳遞和函數返回只是操作這些值的引用,這些操作不會(huì )暗含任何拷貝。
Lua提供運行時(shí)的數字和字符串值得自動(dòng)轉換。任何對字符串的算術(shù)操作都會(huì )現嘗試把字符串轉換成數字,使用一般規則轉換。反過(guò)來(lái),當一個(gè)數值用在需要字符串的地方時(shí),數字會(huì )自動(dòng)轉換成字符串,遵循一種合理的格式。如果要指定數值如何轉換成字符串,請使用字符串庫中的 format 函數(見(jiàn) 5.3)。
Lua假設變量是全局變量,除非明確地用local進(jìn)行聲明 (見(jiàn) 2.4.7)。局部變量有 詞義范圍(lexically scoped):局部變量可以被在它們范圍內的函數自由訪(fǎng)問(wèn) (見(jiàn) 2.6)。
第一個(gè)表達式 (prefixexp)結果必須是表;第二個(gè)表達式 (exp) 識別表中一個(gè)特定條目。給出表的表達式有一個(gè)限制語(yǔ)法;詳細見(jiàn) 2.5。
訪(fǎng)問(wèn)全局變量和表字段的實(shí)質(zhì)可以通過(guò)元表進(jìn)行改變。對索引變量 t[i] 的訪(fǎng)問(wèn)等同于調用 gettable_event(t,i)。(關(guān)于 gettable_event 的完整描述見(jiàn) 2.8。這個(gè)函數并沒(méi)有在Lua中定義,也無(wú)法調用。我們在這里僅僅用來(lái)解釋原理)。
所有的全局變量存在一個(gè)普?ǖ腖ua表中,稱(chēng)之為 環(huán)境變量表(environment tables) 或簡(jiǎn)稱(chēng) 環(huán)境(environments)。由C寫(xiě)的并導入到Lua中的函數 (C 函數) 全部共享一個(gè)通用 全局環(huán)境(global environment)。Lua寫(xiě)的每個(gè)函數 (a Lua 函數) 都有一個(gè)它自己的環(huán)境的引用,這樣這個(gè)函數中的所有的全局變量都會(huì )指向這個(gè)環(huán)境變量表。當新創(chuàng )建一個(gè)函數時(shí),它會(huì )繼承創(chuàng )建它的函數的環(huán)境。要改變或者獲得Lua函數的環(huán)境表,可以調用 setfenv or getfenv (見(jiàn) 5.1)。
Lua執行的最小單元稱(chēng)之為一個(gè) 段(chunk)。一段語(yǔ)句就是簡(jiǎn)單的語(yǔ)句的序列,以順序執行。每一個(gè)語(yǔ)句后面都可以加上一個(gè)分號(可選):
一段語(yǔ)句可以?xún)Υ嬖谖募然蛘咚拗鞒绦虻囊粋€(gè)字符串中。當語(yǔ)句段被執行時(shí),他首先被預編譯成虛擬機使用的字節碼,然后虛擬機用一個(gè)解釋器執行被編譯的代碼。
語(yǔ)句段也可以被預編譯為二進(jìn)制代碼;詳情參看 luac 程序。源代碼和編譯形態(tài)可以互相轉換;Lua自動(dòng)監測文件類(lèi)型然后作相應操作。
顯式語(yǔ)句塊可以很好地控制變量的聲明范圍。顯示語(yǔ)句塊有時(shí)也常會(huì )在另一個(gè)語(yǔ)句塊的中間添加 return 或 break 語(yǔ)句 (見(jiàn) 2.4.4)。
Lua允許多重賦值。因此,賦值的語(yǔ)法定義為:等號左邊是一個(gè)變量表,右邊是一個(gè)表達式表。兩邊的表中的元素都用逗號分隔開(kāi)來(lái):
stat ::= varlist1 `=′ explist1 varlist1 ::= var {`,′ var} explist1 ::= exp {`,′ exp}
在賦值之前,值的表長(cháng)度會(huì )被 調整 為和變量的表一樣。如果值比需要的多,多出的值就會(huì )被扔掉。如果值的數量不夠,就會(huì )用足夠多的 nil 來(lái)填充表直到滿(mǎn)足數量要求。如果表達式表以一個(gè)函數調用結束,那么在賦值之前,函數返回的所有的值都會(huì )添加到值的表中(除非把函數調用放在括號里面;見(jiàn) 2.5)。
對全局變量和表字段的賦值可以看作是通過(guò)元表進(jìn)行的。對一個(gè)索引變量的賦值 t[i] = val 等同于 settable_event(t,i,val)。 (settable_event詳細介紹參看 2.8 ,Lua中并未定義該函數,他也無(wú)法直接調用。我們這里只是用它來(lái)進(jìn)行解釋。)
stat ::= while exp do block end stat ::= repeat block until exp stat ::= if exp then block {elseif exp then block} [else block] end
語(yǔ)句 return 用來(lái)從函數或者是語(yǔ)句段中返回一個(gè)值。函數和語(yǔ)句段都可以返回多個(gè)值,所以 return 語(yǔ)句的語(yǔ)法為:
由于語(yǔ)法的原因, return 和 break 語(yǔ)句只能作為語(yǔ)句塊的 最后一個(gè) 語(yǔ)句。如果確實(shí)需要在語(yǔ)句塊的中間使用 return 或者 break,需要使用一個(gè)顯示語(yǔ)句塊: `do return end′ 和 `do break end′,這樣現在 return 和 break 就成為他們(內部)語(yǔ)句塊中的最后一個(gè)語(yǔ)句了。實(shí)際上,這兩種用法一般只用在調試中。
block 語(yǔ)句塊根據 name 以第一個(gè) exp 的值開(kāi)始,直到他以第三個(gè) exp 為步長(cháng)達到了第二個(gè) exp。一個(gè)這樣的 for 語(yǔ)句:
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
循環(huán)變量 var 是局部變量;你不可以在 for 循環(huán)結束之后繼續使用。如果你需要使用這個(gè)值,請在退出循環(huán)之前把它們傳給其他變量。
for 的語(yǔ)句的一般形式是操作于函數之上的,稱(chēng)之為迭代器(iterators)。每一個(gè)迭代過(guò)程,它調用迭代函數來(lái)產(chǎn)生新的值,直到新的值是 nil 。一般形式 for 循環(huán)有如下語(yǔ)法:
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
循環(huán)變量 var_i 是局部變量;你不可以在 for 循環(huán)結束之后繼續使用。如果你需要使用這個(gè)值,請在退出循環(huán)之前把它們傳給其他變量。
一個(gè)語(yǔ)句段也是一個(gè)語(yǔ)句塊(見(jiàn) 2.4.1),所以語(yǔ)句段之內的任何顯式語(yǔ)句塊之外也可以聲明局部變量。這種局部變量在語(yǔ)句段結束就會(huì )銷(xiāo)毀。
exp ::= prefixexp exp ::= nil | false | true exp ::= Number exp ::= Literal exp ::= function exp ::= tableconstructor prefixexp ::= var | functioncall | `(′ exp `)′
數字和字符串已經(jīng)在 2.1 中解釋?zhuān)蛔兞吭?2.3 中解釋?zhuān)缓瘮刀x在 2.5.8;函數調用在 2.5.7;表構造器在 2.5.6。
一個(gè)用括號括起的表達式只會(huì )返回一個(gè)值。這樣,(f(x,y,z)) 將只會(huì )返回單一的一個(gè)值,即使 f 可以返回多個(gè)值,((f(x,y,z)) 的值將是 f 返回的第一個(gè)值或者如果 f 沒(méi)有返回任何值就是 nil )。
Lua支持常見(jiàn)的幾種運算符:二元 + (加), - (減), * (乘), / (除), 以及 ^ (指數運算); 一元 - (負號)。如果操作數是數字,或者是可以轉換成數字的字符串(見(jiàn) 2.2.1),那么所有的操作都和算術(shù)意義上的運算一致(除了指數)。指數運算其實(shí)是調用一個(gè)全局函數 __pow,否則一個(gè)合適的元方法將會(huì )被調用(見(jiàn) 2.8)。標準數學(xué)庫定義了函數 __pow,給出了指數運算的定義(見(jiàn) 5.5)。
等于 (==) 先比較操作數的類(lèi)型。如果類(lèi)型不一樣,結果便是 false。否則,再比較操作數的值。對象(表,用戶(hù)數據,線(xiàn)程,和函數)是按照引用進(jìn)行比較:只有兩個(gè)對象是同一個(gè)對象的時(shí)候,才認為是相等。每次你創(chuàng )建一個(gè)新的對象(表,用戶(hù)數據,或者是函數)。這個(gè)新的對象將不同于前面存在的任何對象。
T操作符的執行順序如下。如果兩個(gè)參數都是數字,那么它們就直接進(jìn)行比較。如果,兩個(gè)參數都是字符串,那么它們的值會(huì )根據當前的區域設置進(jìn)行比較。否則,Lua嘗試調用"lt"或者 "le" 元方法(見(jiàn) 2.8)。
合取運算 and 如果第一個(gè)參數是 false 或者 nil 則返回第一個(gè)參數;否則 and 返回第二個(gè)參數。析取運算 or 如果第一個(gè)參數不是 nil 或 false 則返回第一個(gè)參數,否則 or 返回第二個(gè)參數。 and 和 or 都使用截取計算,也就是,只有有必要的情況下才計算第二個(gè)參數。例如:
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
在Lua中字符串連接操作符是兩個(gè)點(diǎn) (`..′)。如果兩邊的操作數都是字符或者數字,他們就都會(huì )按照 2.2.1的規則被轉換成字符串。否則,將調用 "concat" 元方法(見(jiàn) 2.8)。
or and < > <= >= ~= == .. + - * / not - (unary) ^
表構造器是創(chuàng )建表的表達式。當計算構造器的時(shí)候,就會(huì )創(chuàng )建一個(gè)新的表。構造器可以用來(lái)創(chuàng )建空的表,或者創(chuàng )建表并初始化一些字段。一般的語(yǔ)法如下:
tableconstructor ::= `{′ [fieldlist] `}′ fieldlist ::= field {fieldsep field} [fieldsep] field ::= `[′ exp `]′ `=′ exp | Name `=′ exp | exp fieldsep ::= `,′ | `;′
[exp1] = exp2 形式的每一個(gè)添加到新表中的字段條目以 exp1 為鍵并以 exp2 為值。name = exp 形式的字段,等同于 ["name"] = exp。最后,exp 形式的字段等同于 [i] = exp 其中 i 是連續的整數,從1開(kāi)始。其它格式的字段不會(huì )影響它的計數。例如:
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
如果列表中最后一個(gè)字段的形式是 exp 同時(shí)表達式又是一個(gè)函數調用,那么調用返回的所有值會(huì )依次進(jìn)入列表(見(jiàn) 2.5.7)。如果要避免這種情況,在函數調用兩邊加上括號(見(jiàn) 2.5)。
在函數調用中,首先會(huì )計算 prefixexp 和 args 。如果 prefixexp 的值是 function 類(lèi)型,那么那個(gè)函數就會(huì )被調用,同時(shí)使用給出的參數。否則,他的 "call" 元方法就會(huì )被調用,第一個(gè)參數是 prefixexp 的值,接下來(lái)是原來(lái)的調用參數(見(jiàn) 2.8)。
可以用來(lái)調用“方法”("methods")。調用 v:name(...) 語(yǔ)法上比 v.name(v,...),要好一些,除非表達式 v 只計算一次。
所有的參數表達式都會(huì )在實(shí)際調用之前進(jìn)行計算。f{...} 的調用形式在語(yǔ)法上較 f({...}) 要好,是因為,參數列表示一個(gè)單獨的新表。 f'...' (或者 f"..." 或者 f[[...]]) 較 f('...') 要好,是因為參數列表是一個(gè)單獨的字符串。
因為函數可以返回任意個(gè)結果(見(jiàn) 2.4.4),結果的數量必須在使用它們前進(jìn)行調整。如果函數按照語(yǔ)句進(jìn)行調用(見(jiàn) 2.4.6),那么它的返回列表就會(huì )被調整為零個(gè)元素,這樣就舍棄了所有的返回值。如果調用函數時(shí),他是一個(gè)表達式列表的最后一個(gè)元素,那么不會(huì )做調整(除非調用時(shí)加了括號)。
f() -- 調整為0個(gè)結果 g(f(), x) -- f() 被調整成1個(gè)結果 g(x, f()) -- g 獲得 x 加上f()返回的所有值 a,b,c = f(), x -- f() 被調整成1個(gè)結果(此時(shí)c獲得nil值) a,b,c = x, f() -- f() 被調整為兩個(gè)結果 a,b,c = f() -- f() 被調整為3個(gè)結果 return f() -- 返回所有 f() 返回的值 return x,y,f() -- 建立一個(gè)表包含所有 f() 返回的值 {f()} -- creates a list with all values returned by f() {f(), nil} -- f() 被調整為一個(gè)結果
return x,y,(f()) -- returns x, y, and the first value from f() {(f())} -- creates a table with exactly one element
作為L(cháng)ua語(yǔ)法自由格式的一個(gè)例外,你不能在函數調用的 `(′ 前面加入一個(gè)換行。這個(gè)限制可以避免語(yǔ)言中的一些二義性。如果你寫(xiě):
Lua會(huì )讀作 a = f(g).x(a)。這樣,如果你想執行為兩條語(yǔ)句,你必須在中間加分號。如果你實(shí)際上想調用 f,你就必須刪除 (g) 前面的換行。
return functioncall 的調用格式稱(chēng)之為 尾部調用(tail call)。Lua實(shí)現了proper tail calls;在一個(gè)尾部調用中,被調用的函數將會(huì )重新使用調用程序的棧。因此,程序執行對嵌套尾部調用的次數沒(méi)有任何限制。然而,尾部調用會(huì )清楚調用函數的調試信息。注意尾部調用只有在特殊的語(yǔ)法中才能出現,也就是 return 只有一個(gè)函數調用作為參數,這種語(yǔ)法保證了調用函數確切返回被調用函數的返回值。所以,下面的例子都不是尾部調用:
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
stat ::= function funcname funcbody stat ::= local function 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
一個(gè)函數定義是一個(gè)可執行的表達式,他的類(lèi)型為 函數(function) 。當Lua預編譯語(yǔ)句段的時(shí)候,他的函數體也會(huì )被預編譯。這樣,當Lua執行函數定義的時(shí)候,函數被 實(shí)例化 (封裝 closed)。這個(gè)函數實(shí)例(或閉包 closure)是表達式的最終結果。同一個(gè)函數的不同的實(shí)例可以引用不同的外部局部變量也可以有不同的環(huán)境表。
當調用一個(gè)函數時(shí),實(shí)參表會(huì )調整為和形參一樣的長(cháng)度,除非函數是 variadic 或者 變長(cháng)參數函數(vararg function)。變長(cháng)參數函數在其參數列表最后有三個(gè)點(diǎn) (`...′)。 變長(cháng)參數函數不會(huì )對參數列表進(jìn)行調整;而是,它把所有的額外實(shí)參放到一個(gè)隱含的形參 arg中。 的值是一個(gè)表,包含一個(gè)字段 `n′ 表示額外參數的個(gè)數,位置 1, 2, ..., n是額外的參數。
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 語(yǔ)句返回(見(jiàn) 2.4.4)。如果控制到達了函數尾部而沒(méi)有遇到 return 語(yǔ)句,那么函數沒(méi)有返回值。
冒號(:) 語(yǔ)法是用來(lái)定義 methods 的,也就是,函數有一個(gè)隱含的額外參數 self. 。這樣,語(yǔ)句:
function t.a.b.c:f (...) ... end
t.a.b.c.f = function (self, ...) ... end
Lua是一個(gè)有詞法范圍的語(yǔ)言。變量的范圍從聲明語(yǔ)句后的第一個(gè)語(yǔ)句開(kāi)始到包含聲明的最內部的語(yǔ)句塊為止。例如:
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)
注意每個(gè) local 語(yǔ)句執行時(shí)會(huì )定義一個(gè)新的局部變量??匆韵吕樱?div style="height:15px;">