《Lua 5.0的实现》第二章 - Lua的设计和实现概述

来源:互联网 发布:酷我音乐有mac 编辑:程序博客网 时间:2024/06/16 18:54

我们在前面的介绍中已经提到了Lua的设计理念:

简洁:我们寻找最简单的语言提供给大家,并用最简单的C代码来实现这门语言。这意味着需要一种较小的语言结构和简单的语法,并且和传统的用法很接近。
高效:我们寻求Lua语言的快速编译和运行。这意味着需要提供一个即快又小,一次编译的编译器,和高速的虚拟机。
可移植:我们希望Lua可以在更多的平台上运行,并且无需修改Lua的核心代码,就可以在各个平台上进行编译;希望有一个相配备的虚拟机,让Lua的程序无需修改就能在各个平台上运行。这表明我们需要一种简洁的ANSI C,它有很好的可移植性,例如它没有其他C语言和库函数的死角,它能确保其编译如C++一样的简洁。我们要的是没有告警的编译过程。
嵌入性:Lua是一种扩展语言;为大型项目提供脚本的便利是它的设计方向。这目标意味着需要有很多的C API,它们简洁、强大,而且它们只依赖于C的内置类型。
嵌入代价低:我们想要Lua可以很容易的添加到一个程序去,而不让程序的体积变大。这需要很紧凑的C代码和很小的Lua内核,可以像其它库一样进行添加。

    这些理念似乎有点自相矛盾。例如,Lua经常被用作数据描述语言,来存储配置文件,有时也用于较大的数据库(Lua程序去操作MB数量级的文件是很常见的事情)。这使得我们需要一个更快的Lua编译器。另外,我们要Lua程序有很快的速度。这使得我们需要一个很轻快的编译器,能够给虚拟机提供高质量的指令代码。因此,Lua编译器的实现要兼顾这两个需求。然而,编译器又不能太大,否则它会使程序的体积变大。针对那些对内存要求很高的程序——如嵌入式系统,它们可以嵌入不带编译器的Lua。这需要Lua程序预先在线下进行编译,然后在运行时载入这个已经编译好的小模块(载入过程也很快,因为模块只是二进制文件)。

    Lua使用手写的扫描器和手写的递归下降解析器。在Lua 3.0版本以前,我们还在用yacc提供的解析功能,它提供一个可以量化的工具来测试语言语法的稳定性。但是手写的解析器更小、更高效、有更高的可移植性,函数全部可重入。同时它能更好提供错误信息。
    Lua编译器使用非中间的表示法。它在解析一个程序的时候飞快的向虚拟机发送指令。不过它的确做了一些优化。例如,它对类似于变量和常量等基础表达式,做了代码延迟生成的处理。当它解析类似的表达式的时候,它没有产生代码,而是使用简单的结构体来表示它们。因此,它很容易判断一个指令的操作数是常量或者局部变量,然后将这些值直接用到指令中去,所以它避免了一些不必要的操作和移动数据的消耗(参考第三章)。

    为了使它能够跨C编译器和跨平台,Lua不能使用其他编译器常用的一些技巧,例如直线程代码(direct threaded code)。而Lua使用标准的while-switch调度循环。这样就导致了有些地方C代码看上去过于复杂,但是复杂的代码是为了保证可移植性。这些年来通过在不同编译器不同平台(包括64位和16位的平台)上的使用,Lua的可移植性的实现变得越来越好了。

    我觉得我们已经完成了我们的设计和实现的目标。Lua是一种可移植性很好的语言:只需要一个ANSI C编译器,Lua就可以在所有的机器上运行,不管是嵌入式系统还是大型机。Lua非常的轻量级:例如在Linux上,Lua的标准独立解析器就算用上所有的标准库,也不超过150K的大小;它的代码量少于100K。Lua是高效的:第三方的测评程序现实Lua是所有脚本语言中最快的一个(脚本语言指的是解析和动态类型的语言)。我也认为Lua是一门简单的语言,语句的风格和Pascal类似,语法与Scheme接近,但这只是一家之言。


原创粉丝点击