构建Lua解释器Part12:Weaktable

前言         本章我开始论述lua的弱表(weaktable)机制,到目前为止,我已经完成了弱表的设计和实现了,读者可以在dummylua的对应章节目录,找到对应的代码工程。本章,我首先会介绍什么是弱表,它的用途,最后分别介绍弱键、弱值以及完全弱引用。 什么是弱表?         弱表是什么?按照官方的定义,弱表是用来告诉Lua虚拟机,被弱表引用的对象,不应该阻止他们被gc回收[1]。与弱表相对的是强表。对于强表来说,所有被强表引用到的gc对象,都会被标记,从而不会被gc机制回收,哪怕这些变量再也没被使用到。因此,对于强表来说,如果你希望被它引用的对象能够被gc回收,那么你需要将它的值设置为nil。对于弱表来说,但凡被设置为弱引用的对象,均不会被gc标记,当再也没有其他地方引用该对象时,它们会从弱表中被清除。         前面讨论了弱表的概念,现在来讨论一下,弱表中,弱引用的类别。弱引用一共有3种,第一种是弱键,第二种是弱值,第三种是完整弱引用。我们来看一下它们的设置方式。 local mt = {__mode = "k"} local tbl = setmetatable({}, mt) 在上面的例子中,mt是tbl的元表,mt的__mode域设置了值k,这表明了,我们的tbl表是个弱表,并且是个只包含弱键的弱表。接下来,我们来看一下弱值的设置方式: local mt = {__mode = "v"} local tbl = setmetatable({}, mt) 本例和前面一个例子的区别是,元表mt的__mode域,被设置为了v,而mt又是tbl的元表,此时tbl是个只包含弱值的弱表。相对应的,完全弱引用的弱表设置方式如下所示: local mt = {__mode = "kv"} local tbl = setmetatable({}, mt) 弱表的用途         前面我们论述了,什么是弱表,那么它又有什么用途呢?一种比较合适的用途,就是为缓存机制添加自动回收功能,比如如下的代码: local mt = {__mode="v"} local tbl = setmetable({}, mt) local function getFromCache(key) if tbl[key] then return tbl[key] end tbl[key] = loadFromDB(key) return tbl[key] end 我们可以看到,当外部通过getFromCache获取到tbl[key]的值之后,如果一直持有,那么这个值就会一直在tbl缓存中,如果外部不再引用tbl[key]值时,那么它会在下一轮gc的时候从tbl被清理。这样,我们就不用去实现相对复杂的LRU机制,来对tbl的内存进行限制和处理了。         当然,这里只是讨论了弱表使用的其中一个例子,其他的使用范例,交给读者自己去探索。 弱键         前面我们已经讨论了什么是弱表,以及不同模式的弱引用的设置方式。本节将讨论的是弱键,当一个表被设置为弱键时,在gc阶段,它会被扫描,并且有着其自身的标记规则。在开始讨论标记规则之前,我们首先简要回顾一下Lua GC机制的几个极端。我们的Lua GC一共需要经历如下几个阶段:pause、propagate mark、atomic和sweep阶段,实际的实现逻辑,要比这几个阶段更细,目前我们只是简单回顾一下,更多的内容,可以回顾Garbage Collection基础架构。现在分别来对这几个阶段,进行简要回顾: [Read More]

构建Lua解释器Part11:Upvalue

前言

        本章,我将深入探讨lua的upvalue机制。在写这篇博客之前,我已经自己动手实现了这个机制,并且将其提交到了github仓库dummylua上了。为了专注于upvalue机制本身的讨论,本章不会展示大量的代码细节,尽量在抽象层面来论述。

[Read More]

构建Lua解释器Part10:userdata

前言

        本章节,我开始对dummylua的userdata的设计与实现,进行论述。它的大体设计与实现,仍然是仿照了lua5.3的标准,由于,所有的内容,都是我自己理解后,重新实现,因此在一些实现细节上略有不同,但是整体设计思路遵循了lua的设计思想。本章的篇幅不会很长,因为userdata这个部分并不是非常复杂,因此我这里也会速战速决,将userdata的一些核心思想论述清楚,就将本章完结。

[Read More]

构建Lua解释器Part9:metatable

前言

        本章,我们将进入到metatable的探索之中。由于这块本身比较简单,而且我也不打算罗列代码细节,因此本章的篇幅不会很大。只是对一些我认为比较关键的部分,进行说明。首先,本章的主要任务,首先是简要介绍metatable是做什么的,然后简要说明一下,它如何被设置,接着介绍metatable的访问域,双目运算操作域、单目运算操作域等。最后会告诉读者,本章的实现逻辑位于dummylua工程的哪些部位。

[Read More]

构建Lua解释器Part8:构建完整的语法分析器(下)

前言

        前面,我已经用3篇blog的巨大篇幅,详细论述了Lua编译模块的一些基本知识。其中,Part5通过一个简单的打印hello world的例子,论述了编译出来的虚拟机指令,如何存到Proto结构中,最后再通过虚拟机执行的流程。Part6详细论述了,词法分析器的设计与实现。而Part7则论述了,expression的编译流程。本章,将作为Lua内置编译器论述的最后一个部分。往后的部分,将不再涉及编译相关的内容。当然,经历这篇,相信读者能够完全理解Lua内置编译器的设计与实现,个人认为完整度还是比较高的。

[Read More]

构建Lua解释器Part7:构建完整的语法分析器(上)

前言

        在上一章里,我完成了词法分析器的设计与实现的论述,接下来我要继续论述语法分析器的设计与实现。限于篇幅,我将会把语法分析器分为两个部分来论述,本章为上部,下一章为下部。本章将会重新复习编译器的构造,并且论述编译流程,以及lua的parser所涉及的编译相关的内容,最后通过阐述虚拟机相关指令的实现,作为结尾。本章所涉及的代码,全部在dummylua工程里,欢迎star。另外,如果你喜欢我写的文章,喜欢讨论技术,欢迎加入我创建的群:QQ185017593

[Read More]

构建Lua解释器Part6:词法分析器设计与实现

前言

        构建Lua解释器Part5,对Lua解释器进行了整体介绍,并且以一个hello world程序为例子,给读者一个初步的概念。通过那一篇,我们知道了编译器至少要包括词法分析其和语法分析器,而本篇,我将集中时间和精力,用来介绍和讲解Lua词法分析器的设计与实现,实际上,它是对Part5词法分析器部分的一个补充。本文所指的词法分析器,是参照Lua-5.3这个版本的源码,并且亲自动手实现和测试过,它也已经被整合到dummylua这个工程中,欢迎大家star。由于整个词法分析是我自己重新实现,因此不会在所有的细节上和官方lua保持一致,最后由于本人水平有限,如有写的不正确的地方,欢迎大家批评指正。此外,我已经建了一个qq群(QQ:185017593),有兴趣参与技术讨论的同学可以加进来。

[Read More]

构建Lua解释器Part5:脚本运行基础架构的设计与实现

前言

        在经过漫长的准备,我终于完成了《构建Lua解释器》系列的第五部分的代码编写,并且通过了预定的测试。本篇我将对dummylua项目中的脚本运行基础架构的设计与实现进行介绍和解析,它包括了lua编译器基础架构以及虚拟机基础架构。过去4个部分的开发,为本部分提供了坚实且必要的基础,本篇将为编译与运行lua脚本搭建最基础的架构,后续内容将在此架构上继续填充与丰富,本部分,我们的目标是编译并运行如下所示的一段脚本代码:

[Read More]

构建Lua解释器Part4:Table设计与实现

前言

        本篇我将对dummylua中Table的设计和实现进行介绍和说明。本文的目的旨在梳理清dummylua项目Table的数据结构和运作流程,该部分深度参考了lua-5.3.4的Table设计与实现,由于所有的细节是我自己根据理解重新实现,因此不会在所有的设计细节上和官方lua保持一致,但是遵循了基本的设计思路。
        Table是Lua语言中举足轻重的组成部分,掌握和理解它具有战略意义,这也是实现Lua虚拟机的基础所在,本文首先介绍dummylua项目Table的数据结构,然后在概念上介绍一些基本的操作流程,如创建、resize、查询、插入和迭代等操作。

[Read More]

构建Lua解释器Part3:String设计与实现

前言

        上一章节我介绍了dummylua项目的gc的设计原理和实现方式,该部分我基本是仿造了官方lua-5.3.4的做法。本章节,我将为大家带来dummylua项目TString的设计实现讲解。和以往任何一篇一样,本篇我也是基本遵循lua-5.3的设计思想,但由于实现是我凭理解自己手动实现,因此不会在所有的细节上和官方lua保持一致。
        任何一门语言都要支持字符串,lua也一样,本章将从lua string的数据结构开始阐述,然后深入其他细节进行阐述,并试图揭露这些设计的历史背景和原因,由于本人能力有限,如有不当之处想要指明,或是想和我一起讨论,欢迎加Q群与我讨论(QQ185017593),我是群主,欢迎大家的到来。

[Read More]