首页>参考读物>计算机科学与技术>软件与程序设计

自己动手实现Lua:虚拟机、编译器和标准库
作者 : 张秀宏 著
丛书名 : "自己动手系列"
出版日期 : 2018-09-26
ISBN : 978-7-111-61022-9
定价 : 89.00元
扩展资源下载
扩展信息
语种 : 简体中文
页数 : 425
开本 : 16
原书名 :
原出版社:
属性分类: 店面
包含CD : 无CD
绝版 : 未绝版
图书简介

内容简介
本书是一本面向Lua程序员和脚本语言爱好者的语言自制指南和实战宝典。
全书将带给读者3个维度的收获:
维度1:深入理解Lua语言本身
作者融合自己丰富的工程实践经验,详细阐述了Lua语言的核心语法和实现原理,深入探讨了Lua虚拟机、编译器和标准库的实现,并给出了实际可以编译执行的代码。
维度2:从零开始实现一门脚本语言
本书以Lua语言为例,系统、完整地(涵盖虚拟机、编译器和标准库)讲解了如何零基础编写一门脚本语言,帮助读者彻底理解脚本语言的工作原理。
维度3:提升Go和Java语言编程能力
本书分别用Go语言和Java语言来实现Lua,包含大量对Go和Java的使用,有很多巧妙的设计,能帮助读者提升Go和Java的编程能力。
全书共21章,分为3个部分:
第一部分(第1-13章) 主要讲解Lua API和虚拟机的实现,包括二进制chunk格式、Lua虚拟机指令集、元编程、错误处理等。
第二部分(第14-17章) 主要讨论Lua语法和编译器的实现,包括词法分析、语法分析、代码优化、代码生成等。
第三部分(第18-21章) 主要讲解Lua辅助API和标准库实现,包括基础库、实用工具库、包和模块、协程等。

图书特色

《自己动手写Java虚拟机》作者耗时2年撰写,用Go和Java从零开始实现一门完整的脚本语言
深入阐述Lua语言的虚拟机、编译器、标准库以及核心语法的实现原理,全方位展示Lua内部工作机制
自己动手实现Lua
虚拟机、编译器和标准库
张秀宏  著
Wrtie Your own Lua
VM、Compiler and Standard Library

图书前言

为什么编写本书
Lua是一门强大、高效、轻量、可嵌入的脚本语言。Lua语言设计十分精巧,在一个很小的内核上可以支持函数式编程、面向对象编程、元编程等多种编程范式。以本书完稿时的最新版本Lua 5.3.4为例,全部代码(包括Lua虚拟机、编译器、标准库等)仅有2万多行,这其中还包括注释和空行。
Lua语言大约于1993年诞生于巴西PUC-Rio大学,之后在游戏领域大放异彩,被很多游戏客户端选为脚本语言,比如知名游戏《魔兽世界》《模拟城市4》《愤怒的小鸟》等。很多流行的游戏引擎也选择Lua作为脚本语言,比如CryENGINE2、Cocos2d-x及Corona SDK等。另外,也有很多游戏服务端采用C/C++搭配Lua的开发模式。除了游戏领域,Lua语言在其他地方也有很多应用,例如被广泛使用的NoSQL数据库Redis就使用Lua作为脚本语言扩展其能力。
相信自己动手设计并实现一门编程语言是每个程序员都会有的一个梦想,目前国内也已经出版或引进了一些指导读者自己实现编程语言的书籍。不过这些书籍要么只介绍了语言实现环节中的一小部分,无法纵观全局;要么只讨论某种大幅裁减后的简化语言,离真正的工业语言还有一定距离。例如,我自己的《自己动手写Java虚拟机》,只讨论了Java虚拟机实现,没有涉及Java编译器和Java标准库。
如上所述,之所以选择Lua语言,就是因为它足够小巧,并且有很好的流行度。麻雀虽小,五脏俱全,这使得我们可以在一本书的篇幅范围内覆盖虚拟机、编译器、标准库这三个方面的内容。希望读者可以通过本书完整体验一门编程语言的实现过程,为将来打造属于自己的语言做好准备。这正是本书的与众不同之处。
本书主要内容
本书主要内容可以分为四个部分:第一部分(第1章)为准备工作;第二部分(第2~ 13章)主要讨论Lua虚拟机和Lua API;第三部分(第14~17章)主要讨论Lua语法和编译器,第四部分(第18~21章)主要讨论Lua标准库。
全书共21章,各章内容安排如下:
第一部分(准备)
第1章:准备工作。
准备编程环境,编写“Hello,World!”程序。
第二部分(Lua虚拟机和Lua API)
第2章:二进制chunk。
介绍Lua二进制chuck文件格式,编写代码解析二进制chunk文件。
第3章:指令集
介绍Lua虚拟机指令集和指令编码格式,编写代码对指令进行解码。
第4章:Lua API
初步介绍Lua API和Lua State,实现栈相关API方法。
第5章:Lua运算符
介绍Lua语言运算符,给Lua API添加运算符相关方法。
第6章:虚拟机雏形
初步实现Lua虚拟机,可以解释执行大约一半的Lua虚拟机指令。
第7章:表
介绍并实现Lua表、表相关API方法,以及表相关指令。
第8章:函数调用
介绍并实现Lua函数调用。
第9章:Go函数调用
介绍如何在Lua中调用Go语言函数。
第10章:闭包和Upvalue
介绍并实现闭包和Upvalue,以及Upvalue相关指令。
第11章:元编程
介绍并实现Lua元表、元方法及元编程。
第12章:迭代器
介绍并实现Lua迭代器。
第13章:异常和错误处理
介绍Lua异常和错误处理机制。
第三部分(Lua语法和编译器)
第14章:词法分析
介绍Lua语言词法规则,实现词法分析器。
第15章:抽象语法树
初步介绍Lua语言语法规则,定义抽象语法树。
第16章:语法分析
进一步介绍Lua语言语法规则,编写语法分析器。
第17章:代码生成
编写代码生成器。
第四部分(Lua标准库)
第18章:辅助API和基础库
介绍Lua辅助API和标准库,实现基础库。
第19章:工具库
介绍并实现数学、表、字符串、UTF-8、OS等标准库。
第20章:包和模块
介绍Lua包和模块机制,实现package标准库。
第21章:协程
介绍Lua协程,实现coroutine标准库。
本书面向的读者
本书假定读者已经了解Go语言和Lua语言,所以不会对这两种语言的语法进行专门介绍。本书使用Go语言实现Lua解释器,但并没有用到特别高深的技术,加之Go语言语法比较简单,相信有C系列语言(比如C、C++、C#、Java等)基础的程序员都可以轻松读懂书中的代码。此外,如果读者更加熟悉Java语言,本书也提供了Java版实现代码。简而言之,本书主要面向以下三类读者:
对脚本语言实现原理感兴趣的读者。
对编译原理和高级语言虚拟机感兴趣的读者。
对Lua语言感兴趣,想探究其内部实现的读者。
如何阅读本书
本书内容主要围绕代码对Lua虚拟机、编译器和标准库展开讨论。本书代码经过精心安排,除第1章外,每一章都建立在前一章的基础之上,但每一章又都可以单独编译和运行。建议读者从第1章开始,按顺序阅读本书并学习每一章的代码。但也可以直接跳到感兴趣的章节进行阅读,必要时再阅读其他章节。
参考资料
相比C/C++、Java、Python等主流语言,Lua算是较为小众的语言,因此能够找到的介绍其内部实现原理和细节的资料并不多,这也是本书写作的动机之一。除了Lua官方实现的源代码,本书在写作过程中主要参考了下面这些资料:
《Programming in Lua, Fourth Edition》
《Lua 5.3 Reference Manual》
《The Evolution of Lua》
《The Implementation of Lua 5.0》
《A No-Frills Introduction to Lua 5.1 VM Instructions》
《Lua 5.3 Bytecode Reference》
除此之外,笔者在本书的写作过程中还查阅了网络上(特别是StackOverflow和Wikipedia)的各种相关资料,这里就不一一罗列了。如果读者需要了解Go语法和标准库,请访问https://golang.google.cn/ 。
获取本书源代码
本书源代码可以从https://github.com/zxh0/luago-book 获取,代码分为Go、Java和Lua三部分,总体目录结构如下:
https://github.com/zxh0/luago-book/code/
go/
ch01/src/luago/
ch02/src/luago/
...
ch21/src/luago/
java/
ch02/
...
ch18/
lua/
ch02/
...
ch21/
其中Go语言部分是Lua解释器实现代码,每章为一个子目录,可以单独编译和运行(详见第1章)。Lua语言部分也是每章一个目录,里面包含每一章的Lua示例代码和测试脚本。Java语言部分是Lua解释器的Java版实现代码,仅供读者参考。Java版实现只提供了前18章的代表,剩下的3章留给读者作为练习。
如果读者对Git比较熟悉,希望每次将注意力集中在某一章的代码上,也可以使用git checkout命令单独检出某一章的代码。本书为每一章都创建了对应的分支,例如,第1章的代码在ch01分支里,以此类推。
勘误和支持
受笔者技术水平和表达能力所限,本书并非尽善尽美,如有不合理之处,恳请读者批评指正。由于时间仓促,书中也难免会存在一些疏漏之处,还请读者谅解。
本书的勘误将通过https://github.com/zxh0/luago-book/blob/master/errata.md 发布和更新。如果读者发现书中的错误、有改进意见,或者有任何问题需要和作者讨论,都可以在本书的Github项目上创建Issue。另外,也可以加入QQ群(311942068)和本书作者以及其他读者进行交流。
致谢
首先感谢家人。为了尽快完成这本书,在过去一年多的写作过程中,我不得不在咖啡厅里度过几十个周末。这些时间本应该用来陪伴家人,或者陪孩子玩耍。没有家人的理解和支持,这本书就不可能这么快问世,谢谢你们!
其次要感谢朋友和同事。感谢乐元素CTO凌聪的大力帮助,同时也感谢R大、窦建伟、田生彩、张飞、王世华、杨兵、蔡晓均等阅读本书初稿并提出宝贵意见。特别感谢武岳为本书每一章绘制可爱的鼹鼠图。此外还有许多人也为我写作本书提供了帮助和鼓励,这里无法一一列出,但同样感谢各位。
最后感谢机械工业出版社华章分社的各位编辑,你们的认真负责是本书质量的保证。

上架指导

计算机\程序设计

封底文字

Lua被广泛应用于游戏开发,是一种非常简单有效的脚本语言,但国内深入讲解Lua虚拟机的书籍几乎没有。秀宏用扎实的技术能力,不仅对Lua从语法、数据结构到原理进行了深度的分析,还使用Go语言一步一步地教会读者还原一个Lua VM的实现过程。在区块链和DSL流行的当下,VM作为底层技术架构的重要性凸显,而这本书对于VM的开发来说是非常好的教材。赶紧阅读此书、下载代码、开始动手属于自己的VM吧!这个过程一定能让你受益匪浅!
——凌聪 乐元素CTO

Go语言诞生10年有余,日渐成熟。Go在云计算和区块连等领域成为事实上的首选语言,七牛云几乎所有基础设施都是使用Go语言构建的。《自己动手实现Lua》一本难得的Go语言实战的图书,通过它你将一步步学习和掌握如何用Go去构建一门商业成熟的语言。
——许式伟 七牛云创始人

脚本语言,从源代码到真正执行指定功能,到底经历了什么样的过程?你是不是探究过?编译原理教程很多,不过多以理论为主。本书以Lua语言为研究对象,以Go为实现工具,步步为营,带我们完整实现了Lua虚拟机、编译器和标准库,让读者能知其然,而且知其所以然。相信读完之后,一方面,你能对Lua背后的机制了如指掌,另一方面,再看其他脚本语言应该也不会感觉神秘了。说不定,你也能设计并实现一门自己的脚本语言。
——臧秀涛 InfoQ副总编

Lua是一种轻量小巧的脚本语言,非常非常适合超高性能的Web网关型服务、轻量级Web应用、Web页面渲染类应用等,搭建超高性能和并发服务。实际场景中,我们使用OpenResty和Lua语言构建过百亿级接口类服务和十亿级页面渲染类服务,且实现了复杂的业务逻辑,在用Lua实现时我们也踩了很多坑。本书教大家如何动手实现Lua语言,知其所以然,能让大家更好地使用Lua这把瑞士军刀解决更多场景的问题。市面上的Lua书籍本身就少,大家可以在学习Lua的过程中配合本书以达到更好的学习效果。
——张开涛 《亿级流量网站架构》作者

作者简介

张秀宏 著:作者简介
张秀宏
资深服务器开发工程师,有多年的Java和游戏服务器开发和架构经验,对高级语言虚拟机有非常深入的研究。曾在EA、乐元素等游戏公司担任高级服务器工程师,现任某创业公司架构师。
曾于2016年6月出版《自己动手写Java虚拟机》一书,广受读者好评,并多次重印。《自己动手实现Lua:虚拟机、编译器、标准库》是他时隔两年之后推出的又一力作。

图书目录

前言
第一部分 准备
第1章 准备工作 3
1.1 准备开发环境 3
1.1.1 操作系统 3
1.1.2 安装Lua 4
1.1.3 安装Go 4
1.2 准备目录结构 4
1.3 本章小结 6
第二部分 Lua虚拟机和Lua API
第2章 二进制chunk 9
2.1 什么是二进制chunk 10
2.2 luac命令介绍 11
2.2.1 编译Lua源文件 11
2.2.2 查看二进制chunk 13
2.3 二进制chunk格式 15
2.3.1 数据类型 16
2.3.2 总体结构 17
2.3.3 头部 18
2.3.4 函数原型 22
2.4 解析二进制chunk 27
2.4.1 读取基本数据类型 28
2.4.2 检查头部 29
2.4.3 读取函数原型 30
2.5 测试本章代码 33
2.6 本章小结 36
第3章 指令集 37
3.1 指令集介绍 37
3.2 指令编码格式 38
3.2.1 编码模式 38
3.2.2 操作码 39
3.2.3 操作数 40
3.2.4 指令表 41
3.3 指令解码 42
3.4 测试本章代码 44
3.5 本章小结 47
第4章 Lua API 49
4.1 Lua API介绍 49
4.2 Lua栈 51
4.2.1 Lua数据类型和值 51
4.2.2 栈索引 54
4.2.3 定义luaStack结构体 54
4.3 Lua State 57
4.3.1 定义LuaState接口 57
4.3.2 定义luaState结构体 58
4.3.3 基础栈操纵方法 59
4.3.4 Push方法 64
4.3.5 Access方法 65
4.4 测试本章代码 69
4.5 本章小结 70
第5章 Lua运算符 71
5.1 Lua运算符介绍 71
5.2 自动类型转换 75
5.3 扩展LuaState接口 79
5.3.1 Arith()方法 80
5.3.2 Compare()方法 83
5.3.3 Len()方法 85
5.3.4 Concat()方法 86
5.4 测试本章代码 87
5.5 本章小结 88
第6章 虚拟机雏形 89
6.1 添加LuaVM接口 89
6.1.1 定义LuaVM接口 91
6.1.2 改造luaState结构体 92
6.1.3 实现LuaVM接口 93
6.2 实现Lua虚拟机指令 94
6.2.1 移动和跳转指令 94
6.2.2 加载指令 96
6.2.3 算术运算指令 101
6.2.4 长度和拼接指令 103
6.2.5 比较指令 106
6.2.6 逻辑运算指令 107
6.2.7 for循环指令 110
6.3 指令分派 113
6.4 测试本章代码 115
6.5 本章小结 118
第7章 表 119
7.1 表介绍 119
7.2 表内部实现 121
7.3 表相关API 125
7.3.1 Get方法 126
7.3.2 Set方法 129
7.4 表相关指令 131
7.4.1 NEWTABLE 131
7.4.2 GETTABLE 133
7.4.3 SETTABLE 135
7.4.4 SETLIST 136
7.5 测试本章代码 138
7.6 本章小结 140
第8章 函数调用 141
8.1 函数调用介绍 141
8.2 函数调用栈 143
8.2.1 调用帧实现 144
8.2.2 调用栈实现 145
8.3 函数调用API 147
8.3.1 Load() 148
8.3.2 Call() 149
8.4 函数调用指令 152
8.4.1 CLOSURE 152
8.4.2 CALL 153
8.4.3 RETURN 157
8.4.4 VARARG 158
8.4.5 TAILCALL 159
8.4.6 SELF 160
8.4.7 扩展LuaVM接口 162
8.4.8 改进SETLIST指令 163
8.5 测试本章代码 164
8.6 本章小结 166
第9章 Go函数调用 167
9.1 Go函数登场 167
9.1.1 添加Go函数类型 168
9.1.2 扩展Lua API 169
9.1.3 调用Go函数 170
9.2 Lua注册表 172
9.2.1 添加注册表 172
9.2.2 操作注册表 173
9.3 全局环境 175
9.3.1 使用API操作全局环境 175
9.3.2 在Lua里访问全局环境 178
9.4 测试本章代码 179
9.5 本章小结 181
第10章 闭包和Upvalue 183
10.1 闭包和Upvalue介绍 183
10.1.1 背景知识 183
10.1.2 Upvalue介绍 185
10.1.3 全局变量 187
10.2 Upvalue底层支持 189
10.2.1 修改closure结构体 189
10.2.2 Lua闭包支持 191
10.2.3 Go闭包支持 192
10.3 Upvalue相关指令 195
10.3.1 GETUPVAL 195
10.3.2 SETUPVAL 196
10.3.3 GETTABUP 197
10.3.4 SETTABUP 199
10.3.5 JMP 200
10.4 测试本章代码 202
10.5 本章小结 203
第11章 元编程 205
11.1 元表和元方法介绍 205
11.1.1 元表 206
11.1.2 元方法 206
11.2 支持元表 207
11.3 调用元方法 208
11.3.1 算术元方法 209
11.3.2 长度元方法 211
11.3.3 拼接元方法 211
11.3.4 比较元方法 212
11.3.5 索引元方法 214
11.3.6 函数调用元方法 216
11.4 扩展Lua API 217
11.4.1 GetMetatable() 218
11.4.2 SetMetatable() 218
11.5 测试本章代码 219
11.6 本章小结 222
第12章 迭代器 223
12.1 迭代器介绍 223
12.2 next()函数 226
12.2.1 修改luaTable结构体 227
12.2.2 扩展Lua API 228
12.2.3 实现next()函数 229
12.3 通用for循环指令 229
12.4 测试本章代码 232
12.5 本章小结 234
第13章 异常和错误处理 235
13.1 异常和错误处理介绍 235
13.2 异常和错误处理API 237
13.2.1 Error() 238
13.2.2 PCall() 239
13.3 error()和pcall()函数 240
13.4 测试本章代码 241
13.5 本章小结 242
第三部分 Lua语法和编译器
第14章 词法分析 245
14.1 编译器介绍 245
14.2 Lua词法介绍 247
14.3 实现词法分析器 251
14.3.1 定义Token类型 252
14.3.2 空白字符 254
14.3.3 注释 256
14.3.4 分隔符和运算符 256
14.3.5 长字符串字面量 258
14.3.6 短字符串字面量 259
14.3.7 数字字面量 262
14.3.8 标识符和关键字 263
14.4 LookAhead()和其他方法 264
14.5 测试本章代码 265
14.6 本章小结 267
第15章 抽象语法树 269
15.1 抽象语法树介绍 269
15.2 Chunk和块 270
15.3 语句 272
15.3.1 简单语句 273
15.3.2 while和repeat语句 273
15.3.3 if语句 274
15.3.4 数值for循环语句 275
15.3.5 通用for循环语句 275
15.3.6 局部变量声明语句 276
15.3.7 赋值语句 277
15.3.8 非局部函数定义语句 278
15.3.9 局部函数定义语句 279
15.4 表达式 280
15.4.1 简单表达式 280
15.4.2 运算符表达式 281
15.4.3 表构造表达式 281
15.4.4 函数定义表达式 282
15.4.5 前缀表达式 283
15.4.6 圆括号表达式 284
15.4.7 表访问表达式 284
15.4.8 函数调用表达式 285
15.5 本章小结 286
第16章 语法分析 287
16.1 语法分析介绍 287
16.1.1 歧义 288
16.1.2 前瞻和回溯 289
16.1.3 解析方式 290
16.2 解析块 290
16.3 解析语句 293
16.3.1 简单语句 294
16.3.2 if语句 296
16.3.3 for循环语句 297
16.3.4 局部变量声明和函数定义语句 299
16.3.5 赋值和函数调用语句 300
16.3.6 非局部函数定义语句 302
16.4 解析表达式 303
16.4.1 运算符表达式 304
16.4.2 非运算符表达式 306
16.4.3 函数定义表达式 307
16.4.4 表构造表达式 308
16.4.5 前缀表达式 310
16.4.6 圆括号表达式 311
16.4.7 函数调用表达式 312
16.4.8 表达式优化 313
16.5 测试本章代码 315
16.6 本章小结 316
第17章 代码生成 317
17.1 定义funcInfo结构体 317
17.1.1 常量表 318
17.1.2 寄存器分配 319
17.1.3 局部变量表 320
17.1.4 Break表 323
17.1.5 Upvalue表 324
17.1.6 字节码 325
17.1.7 其他信息 327
17.2 编译块 327
17.3 编译语句 329
17.3.1 简单语句 330
17.3.2 while和repeat语句 331
17.3.3 if语句 333
17.3.4 for循环语句 334
17.3.5 局部变量声明语句 335
17.3.6 赋值语句 337
17.4 编译表达式 339
17.4.1 函数定义表达式 340
17.4.2 表构造表达式 341
17.4.3 运算符表达式 343
17.4.4 名字和表访问表达式 345
17.4.5 函数调用表达式 346
17.5 生成函数原型 347
17.6 使用编译器 349
17.7 测试本章代码 350
17.8 本章小结 350
第四部分 Lua标准库
第18章 辅助API和基础库 353
18.1 Lua标准库介绍 353
18.2 辅助API 355
18.2.1 增强版方法 357
18.2.2 加载方法 358
18.2.3 参数检查方法 359
18.2.4 标准库开启方法 360
18.3 基础库 361
18.3.1 基础库介绍 362
18.3.2 基础库实现 362
18.4 测试本章代码 365
18.5 本章小结 366
第19章 工具库 367
19.1 数学库 367
19.2 表库 369
19.3 字符串库 372
19.4 UTF-8库 374
19.5 OS库 376
19.6 本章小结 379
第20章 包和模块 381
20.1 包和模块介绍 381
20.2 实现包库 386
20.3 测试本章代码 391
20.4 本章小结 392
第21章 协程 393
21.1 协程介绍 393
21.2 协程API 396
21.2.1 支持线程类型 396
21.2.2 支持协程操作 398
21.3 实现协程库 400
21.4 测试本章代码 403
21.5 本章小结 404
附录A Lua虚拟机指令集 405
附录B Lua语法EBNF描述 407
后记 409

教学资源推荐
作者: Charles N.Fischer, Richard J.LeBlanc
作者: Keith D.Cooper, Linda Torczon
参考读物推荐
作者: (芬)Lasse Koskela 著
作者: Cay S.Horstmann, Gary Cornell
作者: [德] 彼得?普林茨(Peter Prinz),托尼?克劳福德(Tony Crawford)著