blog的源码参考来自于lua5.3.4
lua字节指令处理
脚本指令处理过程一般分为 加载脚本、解析脚本、生成虚拟机能处理的指令、根据生成的指令执行相应的功能。lua虚拟机支持.lua脚本文件加载解析以及lua脚本字符串的解析处理。lua字节码指令加载解析处理的时序如下图
lua加载脚本
lua在API接口层面提供了两种加载脚本的方式:luaL_loadbufferx加载lua脚本字符串,luaL_loadfilex加载*.lua脚本文件。不过两者后面的处理逻辑还是由lua_load来执行,实际的脚本解析功能由函数luaD_protectedparser完成。
脚本解析将脚本抽象成expdesc(表达式)、Labeldesc(goto或者label)、Dyndata(解析器使用的动态结构)。解析所使用的结构如图
实际解析使用的主体由FuncState(进行函数解析)、LexState(语法语义解析) 、BlockCnt(针对代码块的描述结构)合作进行处理得以进行。这几个结构的说明如下图
解析过程在上面的时序图中luaY_parser的相关调用来完成,其中涉及到解析处理的过程就会使用到上图的这些结构。Dyndata的作用之一是存放LexState解析出的goto和label指令的信息,为lexstate处理goto和label提供支持;另一个作用时存放local变量的索引,为快速取得local变量提供支持。总而言之,Dyndata主要的作用时辅助lexstate更好地解析处理脚本。
相关概念的说明
BlockCnt
BlockCnt表示形如
if condition then
dosomething
同时block的概念包含了for以及while循环,当然repeat… until的语句也被视为block, block作为解析过程中完整的一个单元,再由不同的语法来完成对block内部代码的解析。
local vars
local表示形如
local a
这样的变量
upval
引用的不是当前block中的local变量