寒夏摸鱼站

Live your dream, and share your passion.

Lua 源代码阅读 #1

什么是 Lua

Lua 是一种简单而强大的脚本语言,适用于游戏开发、嵌入式系统和脚本编写等领域。它以其灵活性和可扩展性而闻名。

Lua 语言具有清晰的语法和直观的语义,易于学习和使用。
它支持面向过程和函数式编程范式,并具备动态类型和自动内存管理的特性。
Lua 还提供了强大的协程支持,使并发编程变得简单。

Lua 的轻量级设计使其在资源受限的环境中表现出色。
此外,Lua 还具备与其他语言(如C/C++)的良好互操作性,可以轻松嵌入到不同的应用中。

获取 Lua

Lua 的源代码可以在 官方网站 下载,目前的最新版本是 Lua 5.4.6

如果你不想自己编译 Lua,那么可以去官方维护的 Source Forge 下载二进制分发。

当然,因为 Lua 是纯 ANSI C 编写的,所以你可以很轻易地使用任何一种 C 语言编译器与 Makefile 一起编译一份 Lua 二进制。

Lua 系统概览

Lua 源代码文件下每个 .c 文件都是一个 Lua 编译单元,每个单元各自实现一部分 Lua 的功能,整个 Lua 一共有 33 个编译单元,主要功能分别如图:

(长图注意,点 这里 跳转到图片底部)

Lua Lua lapi.c\nLua API 辅助函数 lapi.c Lua API 辅助函数 Lua->lapi.c\nLua API 辅助函数 lauxlib.c\nLua 编译辅助函数 lauxlib.c Lua 编译辅助函数 Lua->lauxlib.c\nLua 编译辅助函数 lbaselib.c\nLua 基本语言库 lbaselib.c Lua 基本语言库 Lua->lbaselib.c\nLua 基本语言库 lcode.c\nLua 字节码生成器 lcode.c Lua 字节码生成器 Lua->lcode.c\nLua 字节码生成器 lcorolib.c\n协程库 lcorolib.c 协程库 Lua->lcorolib.c\n协程库 lctype.c\nC 类型相关函数库 lctype.c C 类型相关函数库 Lua->lctype.c\nC 类型相关函数库 ldblib.c\nLua 调试接口库 ldblib.c Lua 调试接口库 Lua->ldblib.c\nLua 调试接口库 ldebug.c\nLua 调试接口 ldebug.c Lua 调试接口 Lua->ldebug.c\nLua 调试接口 ldo.c\nLua 堆栈与调用系统 ldo.c Lua 堆栈与调用系统 Lua->ldo.c\nLua 堆栈与调用系统 ldump.c\n预编译 Lua 字节码保存库 ldump.c 预编译 Lua 字节码保存库 Lua->ldump.c\n预编译 Lua 字节码保存库 lfunc.c\nLua 原型与闭包操作辅助函数库 lfunc.c Lua 原型与闭包操作辅助函数库 Lua->lfunc.c\nLua 原型与闭包操作辅助函数库 lgc.c\nLua 垃圾回收系统 lgc.c Lua 垃圾回收系统 Lua->lgc.c\nLua 垃圾回收系统 linit.c\n初始化系统 linit.c 初始化系统 Lua->linit.c\n初始化系统 liolib.c\n标准 IO 库 liolib.c 标准 IO 库 Lua->liolib.c\n标准 IO 库 llex.c\n词法分析器 llex.c 词法分析器 Lua->llex.c\n词法分析器 lmathlib.c\n标准数学库 lmathlib.c 标准数学库 Lua->lmathlib.c\n标准数学库 lmem.c\n内存管理器接口 lmem.c 内存管理器接口 Lua->lmem.c\n内存管理器接口 loadlib.c\nLua 动态链接库加载器 loadlib.c Lua 动态链接库加载器 Lua->loadlib.c\nLua 动态链接库加载器 lobject.c\nLua 对象通用函数库 lobject.c Lua 对象通用函数库 Lua->lobject.c\nLua 对象通用函数库 lopcodes.c\nLua 虚拟机字节码库 lopcodes.c Lua 虚拟机字节码库 Lua->lopcodes.c\nLua 虚拟机字节码库 loslib.c\n标准 OS 库 loslib.c 标准 OS 库 Lua->loslib.c\n标准 OS 库 lparser.c\n语法分析器 lparser.c 语法分析器 Lua->lparser.c\n语法分析器 lstate.c\n全局状态库 lstate.c 全局状态库 Lua->lstate.c\n全局状态库 lstring.c\nLua 字符串表 lstring.c Lua 字符串表 Lua->lstring.c\nLua 字符串表 lstrlib.c\n标准字符串操作库 lstrlib.c 标准字符串操作库 Lua->lstrlib.c\n标准字符串操作库 ltable.c\nLua 表(哈希表)库 ltable.c Lua 表(哈希表)库 Lua->ltable.c\nLua 表(哈希表)库 ltablib.c\nLua 表管理库 ltablib.c Lua 表管理库 Lua->ltablib.c\nLua 表管理库 ltm.c\nLua 元方法库 ltm.c Lua 元方法库 Lua->ltm.c\nLua 元方法库 lua.c\nLua 独立解释器库 lua.c Lua 独立解释器库 Lua->lua.c\nLua 独立解释器库 luac.c\nLua 编译器 luac.c Lua 编译器 Lua->luac.c\nLua 编译器 lundump.c\n预编译 Lua 字节码加载库 lundump.c 预编译 Lua 字节码加载库 Lua->lundump.c\n预编译 Lua 字节码加载库 lutf8lib.c\n标准 UTF-8 处理库 lutf8lib.c 标准 UTF-8 处理库 Lua->lutf8lib.c\n标准 UTF-8 处理库 lvm.c\nLua 虚拟机 lvm.c Lua 虚拟机 Lua->lvm.c\nLua 虚拟机 lzio.c\nLua 带缓存流处理库 lzio.c Lua 带缓存流处理库 Lua->lzio.c\nLua 带缓存流处理库

看起来非常复杂对吧(
所以我们需要先按照 Lua 的实现系统先将这些单元进行划分,得到如下一张新的图:

(长图注意,点 这里 跳转到图片底部)

Lua Lua 脚本系统 脚本系统 Lua->脚本系统 标准库 标准库 Lua->标准库 虚拟机系统 虚拟机系统 Lua->虚拟机系统 语言功能系统 语言功能系统 Lua->语言功能系统 辅助库 辅助库 Lua->辅助库 lcode.c\nLua 字节码生成器 lcode.c Lua 字节码生成器 脚本系统->lcode.c\nLua 字节码生成器 ldump.c\n预编译 Lua 字节码保存库 ldump.c 预编译 Lua 字节码保存库 脚本系统->ldump.c\n预编译 Lua 字节码保存库 llex.c\n词法分析器 llex.c 词法分析器 脚本系统->llex.c\n词法分析器 lopcodes.c\nLua 虚拟机字节码库 lopcodes.c Lua 虚拟机字节码库 脚本系统->lopcodes.c\nLua 虚拟机字节码库 lparser.c\n语法分析器 lparser.c 语法分析器 脚本系统->lparser.c\n语法分析器 luac.c\nLua 编译器 luac.c Lua 编译器 脚本系统->luac.c\nLua 编译器 lundump.c\n预编译 Lua 字节码加载库 lundump.c 预编译 Lua 字节码加载库 脚本系统->lundump.c\n预编译 Lua 字节码加载库 lbaselib.c\nLua 基本语言库 lbaselib.c Lua 基本语言库 标准库->lbaselib.c\nLua 基本语言库 lcorolib.c\n协程库 lcorolib.c 协程库 标准库->lcorolib.c\n协程库 ldblib.c\nLua 调试接口库 ldblib.c Lua 调试接口库 标准库->ldblib.c\nLua 调试接口库 liolib.c\n标准 IO 库 liolib.c 标准 IO 库 标准库->liolib.c\n标准 IO 库 lmathlib.c\n标准数学库 lmathlib.c 标准数学库 标准库->lmathlib.c\n标准数学库 loslib.c\n标准 OS 库 loslib.c 标准 OS 库 标准库->loslib.c\n标准 OS 库 lstrlib.c\n标准字符串操作库 lstrlib.c 标准字符串操作库 标准库->lstrlib.c\n标准字符串操作库 ltablib.c\nLua 表管理库 ltablib.c Lua 表管理库 标准库->ltablib.c\nLua 表管理库 lutf8lib.c\n标准 UTF-8 处理库 lutf8lib.c 标准 UTF-8 处理库 标准库->lutf8lib.c\n标准 UTF-8 处理库 ldo.c\nLua 堆栈与调用系统 ldo.c Lua 堆栈与调用系统 虚拟机系统->ldo.c\nLua 堆栈与调用系统 lgc.c\nLua 垃圾回收系统 lgc.c Lua 垃圾回收系统 虚拟机系统->lgc.c\nLua 垃圾回收系统 linit.c\n初始化系统 linit.c 初始化系统 虚拟机系统->linit.c\n初始化系统 loadlib.c\nLua 动态链接库加载器 loadlib.c Lua 动态链接库加载器 虚拟机系统->loadlib.c\nLua 动态链接库加载器 lstate.c\n全局状态库 lstate.c 全局状态库 虚拟机系统->lstate.c\n全局状态库 lstring.c\nLua 字符串表 lstring.c Lua 字符串表 虚拟机系统->lstring.c\nLua 字符串表 lua.c\nLua 独立解释器库 lua.c Lua 独立解释器库 虚拟机系统->lua.c\nLua 独立解释器库 lvm.c\nLua 虚拟机 lvm.c Lua 虚拟机 虚拟机系统->lvm.c\nLua 虚拟机 lfunc.c\nLua 原型与闭包操作辅助函数库 lfunc.c Lua 原型与闭包操作辅助函数库 语言功能系统->lfunc.c\nLua 原型与闭包操作辅助函数库 lobject.c\nLua 对象通用函数库 lobject.c Lua 对象通用函数库 语言功能系统->lobject.c\nLua 对象通用函数库 ltable.c\nLua 表(哈希表)库 ltable.c Lua 表(哈希表)库 语言功能系统->ltable.c\nLua 表(哈希表)库 ltm.c\nLua 元方法库 ltm.c Lua 元方法库 语言功能系统->ltm.c\nLua 元方法库 lapi.c\nLua API 辅助函数 lapi.c Lua API 辅助函数 辅助库->lapi.c\nLua API 辅助函数 lauxlib.c\nLua 编译辅助函数 lauxlib.c Lua 编译辅助函数 辅助库->lauxlib.c\nLua 编译辅助函数 lctype.c\nC 类型相关函数库 lctype.c C 类型相关函数库 辅助库->lctype.c\nC 类型相关函数库 ldebug.c\nLua 调试接口 ldebug.c Lua 调试接口 辅助库->ldebug.c\nLua 调试接口 lmem.c\n内存管理器接口 lmem.c 内存管理器接口 辅助库->lmem.c\n内存管理器接口 lzio.c\nLua 带缓存流处理库 lzio.c Lua 带缓存流处理库 辅助库->lzio.c\nLua 带缓存流处理库

至此,我们可以将 Lua 系统大致拆分为 5 个模块。
除了这 5 大模块,我们还可以进一步细分模块以更好地进行代码阅读:

(长图注意,点 这里 跳转到图片底部)

Lua Lua 脚本系统 脚本系统 Lua->脚本系统 标准库 标准库 Lua->标准库 虚拟机系统 虚拟机系统 Lua->虚拟机系统 语言功能系统 语言功能系统 Lua->语言功能系统 辅助库 辅助库 Lua->辅助库 脚本解析 脚本解析 脚本系统->脚本解析 字节码处理 字节码处理 脚本系统->字节码处理 C 标准库 C 标准库 标准库->C 标准库 Lua 标准库 Lua 标准库 标准库->Lua 标准库 虚拟机核心 虚拟机核心 虚拟机系统->虚拟机核心 虚拟机辅助 虚拟机辅助 虚拟机系统->虚拟机辅助 Lua 表系统 Lua 表系统 语言功能系统->Lua 表系统 其他语言功能 其他语言功能 语言功能系统->其他语言功能 底层辅助系统 底层辅助系统 辅助库->底层辅助系统 其他辅助系统 其他辅助系统 辅助库->其他辅助系统 llex.c\n词法分析器 llex.c 词法分析器 脚本解析->llex.c\n词法分析器 lparser.c\n语法分析器 lparser.c 语法分析器 脚本解析->lparser.c\n语法分析器 lcode.c\nLua 字节码生成器 lcode.c Lua 字节码生成器 字节码处理->lcode.c\nLua 字节码生成器 ldump.c\n预编译 Lua 字节码保存库 ldump.c 预编译 Lua 字节码保存库 字节码处理->ldump.c\n预编译 Lua 字节码保存库 lopcodes.c\nLua 虚拟机字节码库 lopcodes.c Lua 虚拟机字节码库 字节码处理->lopcodes.c\nLua 虚拟机字节码库 luac.c\nLua 编译器 luac.c Lua 编译器 字节码处理->luac.c\nLua 编译器 lundump.c\n预编译 Lua 字节码加载库 lundump.c 预编译 Lua 字节码加载库 字节码处理->lundump.c\n预编译 Lua 字节码加载库 liolib.c\n标准 IO 库 liolib.c 标准 IO 库 C 标准库->liolib.c\n标准 IO 库 lmathlib.c\n标准数学库 lmathlib.c 标准数学库 C 标准库->lmathlib.c\n标准数学库 loslib.c\n标准 OS 库 loslib.c 标准 OS 库 C 标准库->loslib.c\n标准 OS 库 lbaselib.c\nLua 基本语言库 lbaselib.c Lua 基本语言库 Lua 标准库->lbaselib.c\nLua 基本语言库 lcorolib.c\n协程库 lcorolib.c 协程库 Lua 标准库->lcorolib.c\n协程库 ldblib.c\nLua 调试接口库 ldblib.c Lua 调试接口库 Lua 标准库->ldblib.c\nLua 调试接口库 lstrlib.c\n标准字符串操作库 lstrlib.c 标准字符串操作库 Lua 标准库->lstrlib.c\n标准字符串操作库 ltablib.c\nLua 表管理库 ltablib.c Lua 表管理库 Lua 标准库->ltablib.c\nLua 表管理库 lutf8lib.c\n标准 UTF-8 处理库 lutf8lib.c 标准 UTF-8 处理库 Lua 标准库->lutf8lib.c\n标准 UTF-8 处理库 ldo.c\nLua 堆栈与调用系统 ldo.c Lua 堆栈与调用系统 虚拟机核心->ldo.c\nLua 堆栈与调用系统 lgc.c\nLua 垃圾回收系统 lgc.c Lua 垃圾回收系统 虚拟机核心->lgc.c\nLua 垃圾回收系统 loadlib.c\nLua 动态链接库加载器 loadlib.c Lua 动态链接库加载器 虚拟机核心->loadlib.c\nLua 动态链接库加载器 lstate.c\n全局状态库 lstate.c 全局状态库 虚拟机核心->lstate.c\n全局状态库 lstring.c\nLua 字符串表 lstring.c Lua 字符串表 虚拟机核心->lstring.c\nLua 字符串表 lvm.c\nLua 虚拟机 lvm.c Lua 虚拟机 虚拟机核心->lvm.c\nLua 虚拟机 linit.c\n初始化系统 linit.c 初始化系统 虚拟机辅助->linit.c\n初始化系统 lua.c\nLua 独立解释器库 lua.c Lua 独立解释器库 虚拟机辅助->lua.c\nLua 独立解释器库 ltable.c\nLua 表(哈希表)库 ltable.c Lua 表(哈希表)库 Lua 表系统->ltable.c\nLua 表(哈希表)库 ltm.c\nLua 元方法库 ltm.c Lua 元方法库 Lua 表系统->ltm.c\nLua 元方法库 lfunc.c\nLua 原型与闭包操作辅助函数库 lfunc.c Lua 原型与闭包操作辅助函数库 其他语言功能->lfunc.c\nLua 原型与闭包操作辅助函数库 lobject.c\nLua 对象通用函数库 lobject.c Lua 对象通用函数库 其他语言功能->lobject.c\nLua 对象通用函数库 lctype.c\nC 类型相关函数库 lctype.c C 类型相关函数库 底层辅助系统->lctype.c\nC 类型相关函数库 lmem.c\n内存管理器接口 lmem.c 内存管理器接口 底层辅助系统->lmem.c\n内存管理器接口 lzio.c\nLua 带缓存流处理库 lzio.c Lua 带缓存流处理库 底层辅助系统->lzio.c\nLua 带缓存流处理库 lapi.c\nLua API 辅助函数 lapi.c Lua API 辅助函数 其他辅助系统->lapi.c\nLua API 辅助函数 lauxlib.c\nLua 编译辅助函数 lauxlib.c Lua 编译辅助函数 其他辅助系统->lauxlib.c\nLua 编译辅助函数 ldebug.c\nLua 调试接口 ldebug.c Lua 调试接口 其他辅助系统->ldebug.c\nLua 调试接口

那么一个基础的大纲基本上也就形成了,当然这还不够,因为编译单元之间仍会出现互相引用的情况,从一个只有 C 标准头文件引用的系统开始阅读往往是最好的,因为不需要其他 Lua 相关的前置知识,所以我们还需要一张依赖图:

(长图注意,点 这里 跳转到图片底部)

c0 lapi.c h16 lprefix.h c0->h16 h21 lua.h c0->h21 h0 lapi.h c0->h0 h4 ldebug.h c0->h4 h5 ldo.h c0->h5 h6 lfunc.h c0->h6 h7 lgc.h c0->h7 h11 lmem.h c0->h11 h12 lobject.h c0->h12 h17 lstate.h c0->h17 h18 lstring.h c0->h18 h19 ltable.h c0->h19 h20 ltm.h c0->h20 h25 lundump.h c0->h25 h26 lvm.h c0->h26 h23 luaconf.h h21->h23 h0->h17 h10 llimits.h h0->h10 h4->h17 h5->h12 h5->h17 h27 lzio.h h5->h27 h5->h10 h6->h12 h7->h12 h7->h17 h11->h21 h11->h10 h12->h21 h12->h10 h17->h21 h17->h12 h17->h20 h17->h27 h18->h7 h18->h12 h18->h17 h19->h12 h20->h12 h20->h17 h25->h12 h25->h27 h25->h10 h26->h5 h26->h12 h26->h20 c1 lauxlib.c c1->h16 c1->h21 h1 lauxlib.h c1->h1 h1->h21 h1->h23 c2 lbaselib.c c2->h16 c2->h21 c2->h1 h24 lualib.h c2->h24 h24->h21 c3 lcode.c c3->h16 c3->h21 c3->h4 c3->h5 c3->h7 c3->h11 c3->h12 c3->h18 c3->h19 c3->h26 h2 lcode.h c3->h2 h9 llex.h c3->h9 h13 lopcodes.h c3->h13 h15 lparser.h c3->h15 h2->h12 h2->h9 h2->h13 h2->h15 h9->h12 h9->h27 h13->h10 h15->h12 h15->h27 h15->h10 c4 lcorolib.c c4->h16 c4->h21 c4->h1 c4->h24 c5 lctype.c c5->h16 h3 lctype.h c5->h3 h3->h21 c6 ldblib.c c6->h16 c6->h21 c6->h1 c6->h24 c7 ldebug.c c7->h16 c7->h21 c7->h0 c7->h4 c7->h5 c7->h6 c7->h12 c7->h17 c7->h18 c7->h19 c7->h20 c7->h26 c7->h2 c7->h13 c8 ldo.c c8->h16 c8->h21 c8->h0 c8->h4 c8->h5 c8->h6 c8->h7 c8->h11 c8->h12 c8->h17 c8->h18 c8->h19 c8->h20 c8->h25 c8->h26 c8->h13 c8->h15 c8->h27 h27->h21 h27->h11 c9 ldump.c c9->h16 c9->h21 c9->h12 c9->h17 c9->h25 c10 lfunc.c c10->h16 c10->h21 c10->h4 c10->h5 c10->h6 c10->h7 c10->h11 c10->h12 c10->h17 c11 lgc.c c11->h16 c11->h21 c11->h4 c11->h5 c11->h6 c11->h7 c11->h11 c11->h12 c11->h17 c11->h18 c11->h19 c11->h20 c12 linit.c c12->h16 c12->h21 c12->h1 c12->h24 c13 liolib.c c13->h16 c13->h21 c13->h1 c13->h24 c14 llex.c c14->h16 c14->h21 c14->h4 c14->h5 c14->h6 c14->h7 c14->h12 c14->h17 c14->h18 c14->h19 c14->h9 c14->h15 c14->h3 c14->h27 c15 lmathlib.c c15->h16 c15->h21 c15->h1 c15->h24 c16 lmem.c c16->h16 c16->h21 c16->h4 c16->h5 c16->h7 c16->h11 c16->h12 c16->h17 c17 loadlib.c c17->h16 c17->h21 c17->h1 c17->h24 c18 lobject.c c18->h16 c18->h21 c18->h4 c18->h5 c18->h11 c18->h12 c18->h17 c18->h18 c18->h26 c18->h3 c19 lopcodes.c c19->h16 c19->h13 c20 loslib.c c20->h16 c20->h21 c20->h1 c20->h24 c21 lparser.c c21->h16 c21->h21 c21->h4 c21->h5 c21->h6 c21->h11 c21->h12 c21->h17 c21->h18 c21->h19 c21->h9 c21->h13 c21->h15 c21->h3 c22 lstate.c c22->h16 c22->h21 c22->h0 c22->h4 c22->h5 c22->h6 c22->h7 c22->h11 c22->h17 c22->h18 c22->h19 c22->h20 c22->h9 c23 lstring.c c23->h16 c23->h21 c23->h4 c23->h5 c23->h11 c23->h12 c23->h17 c23->h18 c24 lstrlib.c c24->h16 c24->h21 c24->h1 c24->h24 c25 ltable.c c25->h16 c25->h21 c25->h4 c25->h5 c25->h7 c25->h11 c25->h12 c25->h17 c25->h18 c25->h19 c25->h20 c26 ltablib.c c26->h16 c26->h21 c26->h1 c26->h24 c27 ltm.c c27->h16 c27->h21 c27->h4 c27->h5 c27->h7 c27->h12 c27->h17 c27->h18 c27->h19 c27->h20 c27->h26 c28 lua.c c28->h16 c28->h21 c28->h1 c28->h24 c29 luac.c c29->h16 c29->h21 c29->h4 c29->h12 c29->h17 c29->h25 c29->h1 c29->h13 h14 lopnames.h c29->h14 c30 lundump.c c30->h16 c30->h21 c30->h4 c30->h5 c30->h6 c30->h11 c30->h12 c30->h18 c30->h25 c30->h27 c31 lutf8lib.c c31->h16 c31->h21 c31->h1 c31->h24 c32 lvm.c c32->h16 c32->h21 c32->h4 c32->h5 c32->h6 c32->h7 c32->h12 c32->h17 c32->h18 c32->h19 c32->h20 c32->h26 c32->h13 c33 lzio.c c33->h16 c33->h21 c33->h11 c33->h17 c33->h26 c33->h10 h10->h21 h8 ljumptab.h h22 lua.hpp h22->h21 h22->h1 h22->h24

虽然这张依赖图也是又臭又长,且看起来似乎还有循环依赖的关系,但是它为我们揭示了真正的阅读顺序,即从左到右的 拓扑排序

由于 C 源文件对于头文件之间是单向依赖,因此 C 源文件之间不会产生循环依赖,而头文件之间则可能产生循环依赖,因此我们应该先阅读头文件,然后再阅读源文件。
根据拓扑序,我们可以得到如下的头文件阅读顺序:

  1. ljumptab.h
  2. lopnames.h
  3. lprefix.h
  4. luaconf.h
  5. lua.h
  6. lualib.h
  7. llimits.h
  8. lctype.h
  9. lauxlib.h
  10. lopcodes.h
  11. lobject.h
  12. lmem.h
  13. lua.hpp
  14. ltable.h
  15. lfunc.h
  16. lzio.h
  17. lundump.h
  18. lparser.h
  19. llex.h
  20. lcode.h

同时,由于循环依赖的存在,部分头文件是不能纳入拓扑排序的,因此,根据依赖数量,对循环依赖项进行排序,得到如下补充顺序:

  1. lapi.h
  2. ldebug.h
  3. ldo.h
  4. lgc.h
  5. lstate.h
  6. ltm.h
  7. lstring.h
  8. lvm.h

在阅读完头文件之后,再阅读源文件就可以事半功倍了,源文件阅读顺序就作为下一阶段进行展示。

评论系统加载中

Capoo Sad

评论系统无响应

请尝试 刷新 页面或向 管理员 反馈

Capoo Sad

留下一条友好的评论

昵称

电子邮箱

主页网址

留言

你的评论需要经过 审核 之后才会显示,一般需要等待 数分钟到数小时,请勿重复提交