说明:
这个文档是 doc 目录里的 manual.html 文件。
原文版权归原作者所有,这篇翻译只是作为学习之用。如果翻译有不当之处,请参考原文。
-------------------以下是正文-------------------
编程语言 Lua4.0 的参考手册
--------------------------------------
1 简介
--------------------------------------
Lua 是一个扩展编程语言,支持通用编程功能与数据描述功能。作为一个强大,轻量级的配置语言,它被设计用来做为别的程序的配置语言。
Lua 被实现为由 C 语言写成的库。做为一个扩展语言,Lua 没有 "main" 函数的概念;它只能嵌入到宿主运行,叫做嵌入程序。宿主可以调用函数去执行一段 Lua 代码,可以读写 Lua 变量,可以注册被 Lua 代码调用的 C 函数。通过 C 函数的使用,Lua 可以扩展自己以应对不同的领域,从而创建可定制、共享语法框架的编程语言。
Lua 是自由分发的软件,正常提供没有什么保证,如它的版权声明所述。本文档里描述的这个实现可以从下面的地址得到:
http://www.lua.org/
(原文的地址已经过期,这里给出的是当前的官网地址)
如同其它的参考手册一样,这个文档也很枯燥。一些 Lua 设计背后的决策讨论可以参见下面的论文,它们都可以在官网上找到。
> R. Ierusalimschy, L. H. de Figueiredo, and W. Celes. Lua-an extensible extension language. Software: Practice & Experience 26 #6 (1996) 635--652.
> L. H. de Figueiredo, R. Ierusalimschy, and W. Celes. The design and implementation of a language for extending applications. Proceedings of XXI Brazilian Seminar on Software and Hardware (1994) 273--283.
> L. H. de Figueiredo, R. Ierusalimschy, and W. Celes. Lua: an extensible embedded language. Dr. Dobb‘s Journal 21 #12 (Dec 1996) 26--33.
--------------------------------------
2 环境和块
--------------------------------------
Lua 中所有的语句都在一个全局环境中执行。这个环境由嵌入程序调用 lua_open 初始化并一直持续到调用 lua_close 结束,或者到嵌入程序结束时结束。如果必要的话,宿主程序员可以建立多个独立的全局环境,并可以在它们之间自由的切换(参见 5.1 节)。
这个全局环境可以用 Lua 代码或者嵌入程序来管理,可以通过 Lua 的实现库 API 函数来读写全局变量。
Lua 中的全局变量不需要声明。所有的变量被认为是全局的除非明确声明为 local (参见 4.4.6 节)。在第一次赋值之前,全局变量的值为 nil(可以修改这个默认值,参见 4.8 节)。一个表(table)保存所有的全局名字和值(表的解释参见 3 节)。
Lua 的执行单元叫做块(chunk) 。简单地说,一个块就是一个按顺序执行的语句序列。每个语句可以可选的后跟一个分号:
chunk ::= {stat [`;‘]}
语句在 4.4 节描述。(上面的符号标记法是通用的扩展的 BNF,{ a } 表示 0 个或多个 a,[ a ] 表示一个可选的 a,{ a } +(加号是右上角标)表示一个或多个 a。完整的语法描述在本文档的最后面。)
一个模块可以保存在一个文件中或者一个宿主程序的字符串中。当执行一个模块,首先它被预编译为虚拟机的字节码,然后它的语句由模拟的虚拟机顺序执行。模块对于全局环境的所有修改是持久的,这些修改在模块结束后依然可见。
块可被预编译为二进制格式并保存在文件中;参见程序 luac。包含块代码的文本文件和它们的二进制预编译字节码形式是等价的。Lua 可以自动检测文件类型并做相应操作。
--------------------------------------
3 类型和标签(Types and Tags)
--------------------------------------
Lua 是动态类型语言。这意味着变量没有类型;只有值有类型。所以,Lua 语言中没有类型定义。所有值含有自己的类型。除了类型,所有值还有一个标签(tag)。
Lua 中有六种基本数据类型:nil, number, string, function, userdata, 和 table。Nil 是值为 nil 的类型,它的主要性质就是和其它值不同。Number 表示实数(双精浮点型),string 是字符串。Lua 是 8 位的,所以字符串可以包含所有的 8 位字符,包括内部的 0 (‘\0‘)(参见 4.1 节)。type 函数返回描述给定值的类型的字符串(参见 6.1 节)。
Lua 中函数是第一类值(first-class values)。这意味着他们可以存储在变量中,做为参数传递给其他函数或者做为结果返回。Lua 可以调用(和操纵)写在 Lua 或 C 中的函数。这两种函数可以由它们的标签区分:所有的 Lua 函数有相同的标签,所有的 C 函数也有相同的标签,并且不同于 Lua 函数的标签。tag 函数可以返回给定值的标签(参见 6.1 节)。
userdata 类型允许 Lua 变量保存任意的 C 指针(void*)。它相当于 C 语言中的 void* 型指针,所以在 Lua 中除赋值和相等测试操作以外,没有其它预定义的操作。但是,通过使用标签方法(tag methods),程序员可以为 userdata 值定义操作(参见 4.8 节)。
table 类型实现为关联数组,即数组不仅可以用数字索引,也可以用任意值索引(除了 nil)。因此,该类型不仅可用于表示普通数组,也可以用于表示符号表,集合,记录等。表是 Lua 中主要的数据类型。为表示一个记录,Lua 使用字段名为下标。语言通过提供 a.name 这种表示作为 a["name"] 的语法糖。表也可以包含方法。因为函数是第一类的,表字段可以包含函数。t:f(x) 形式是 t.f(t,x) 的语法糖,它调用表 t 中的方法 f ,并把它自己做为第一个参数传入(参见 4.5.9 节)。
注意 table 是对象而非值。变量不能包含 table,只能引用它。赋值,参数传递,返回总是会操作 table 的引用,而不会对 table 进行拷贝。而且,table 必须在使用前显式创建(参见 4.5.7 节)。
每一个类型 nil, number, 和 string 有不同的标签。所有这些类型的值有同样的预定义标签。正如上面解释的一样,类型 function 的值可以有两个不同的标签,根据它们是 Lua 函数或者 C 函数。最后,类型 userdata 和 table 可以有程序员指定的可变的标签(参见 4.8 节)。tag 函数返回给定值的标签。用户标签由函数 newtag 生成。settag 函数用来改变表的标签(参见 6.1 节)。userdata 值的标签只能在 C 中设置(参见 5.7 节)。当有事件发生时,标签主要用来选择标签方法(tag methods)。标签方法是扩展 Lua 语义的主要机制(参见 4.8 节)。
(未完待续)