1 Star 0 Fork 0

Jaesoon/luaEngine

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
lparser.h 14.06 KB
一键复制 编辑 原始数据 按行查看 历史
jaesonzhang 提交于 2024-07-16 20:56 . 注释代码提交
/*
** $Id: lparser.h,v 1.76.1.1 2017/04/19 17:20:42 roberto Exp $
** Lua Parser
** See Copyright Notice in lua.h
*/
#ifndef lparser_h
#define lparser_h
#include "llimits.h"
#include "lobject.h"
#include "lzio.h"
/*
** 表达式和变量描述符。
** 为了允许优化,变量和表达式的代码生成可以被延迟;一个 'expdesc' 结构描述了一个可能被延迟的
** 变量/表达式。它包含了其“主要”值的描述,加上一个条件跳转列表,这些跳转也可以生成其值(由
** 短路运算符 'and'/'or' 生成)。
*/
/**
*这段话是关于编程中的一个概念,特别是在编译器设计或解释器实现中的一个特定结构的描述。
* 这个结构被称为 expdesc,它用于描述变量或表达式。这里的关键点如下:
* 1. 延迟代码生成:通常,在编译或解释代码时,每个变量或表达式都会立即生成相应的机器码或中间代码。
* 然而,为了进行优化,比如减少生成的代码量或提高执行效率,有时会延迟这个代码生成的过程。
* 这意味着编译器或解释器会等待,直到有更多的信息可用,或者直到确定了最优的生成方式。
* 2. expdesc 结构:这是一个数据结构,用于描述一个可能被延迟处理的变量或表达式。这个结构包含了两个主要部分:
· 主要值的描述:这是变量或表达式的直接值的描述,即在没有任何条件跳转发生时,它应该产生的值。
· 条件跳转列表:这个列表包含了一系列的条件跳转指令,这些指令是由于使用了短路运算符 and 或 or 而生成的。
在逻辑运算中,短路运算符允许表达式的评估提前结束,如果已经可以确定整个表达式的结果。
例如,在表达式 A and B 中,如果 A 为假,则无需评估 B,因为整个表达式的结果已经确定为假。
这种优化可以减少不必要的计算。
综上所述,这段话描述的是一个用于编译器或解释器中的结构,该结构用于跟踪和管理变量和表达式的代码生成,特别是在涉及优化和延迟处理时。
*
*/
/*
** Expression and variable descriptor.
** Code generation for variables and expressions can be delayed to allow
** optimizations; An 'expdesc' structure describes a potentially-delayed
** variable/expression. It has a description of its "main" value plus a
** list of conditional jumps that can also produce its value (generated
** by short-circuit operators 'and'/'or').
*/
/* kinds of variables/expressions
* 这段代码定义了一个枚举类型expkind,它用于在Lua虚拟机中表示不同种类的变量和表达式。每个枚举值代表了表达式描述符expdesc可以具有的不同状态。
* */
typedef enum {
VVOID, /* when 'expdesc' describes the last expression a list,
this kind means an empty list (so, no expression)
'expdesc' 描述列表中的最后一个表达式时,这个种类意味着一个空列表(即,没有表达式)*/
VNIL, /* constant nil 常量 nil */
VTRUE, /* constant true 常量 true */
VFALSE, /* constant false 常量 false*/
VK, /* constant in 'k'; info = index of constant in 'k' 常量在 'k' 中;info = 常量在 'k' 中的索引 */
VKFLT, /* floating constant; nval = numerical float value 浮点常量;nval = 数值浮点值 */
VKINT, /* integer constant; nval = numerical integer value 型常量;nval = 数值整数值 */
VNONRELOC, /* expression has its value in a fixed register;
info = result register
表达式的值在一个固定的寄存器中;
info = 结果寄存器 */
VLOCAL, /* local variable; info = local register 局部变量;info = 局部寄存器 */
VUPVAL, /* upvalue variable; info = index of upvalue in 'upvalues' 上值变量;info = 'upvalues' 中上值的索引 */
VINDEXED, /* indexed variable;
ind.vt = whether 't' is register or upvalue;
ind.t = table register or upvalue;
ind.idx = key's R/K index
索引变量;
ind.vt = 't' 是寄存器还是上值;
ind.t = 表的寄存器或上值;
ind.idx = 键的 R/K 索引
*/
VJMP, /* expression is a test/comparison;
info = pc of corresponding jump instruction
表达式是一个测试/比较;
info = 对应跳转指令的 pc
*/
VRELOCABLE, /* expression can put result in any register;
info = instruction pc
表达式可以将结果放在任何寄存器中;
info = 指令 pc*/
VCALL, /* expression is a function call; info = instruction pc 表达式是一个函数调用;info = 指令 pc */
VVARARG /* vararg expression; info = instruction pc 可变参数表达式;info = 指令 pc */
} expkind;
///* 变量/表达式的种类 */
//typedef enum {
// VVOID, /* 当 'expdesc' 描述一个列表的最后一个表达式时,
// 这个类型意味着一个空列表(所以,没有表达式) */
// VNIL, /* 常量 nil */
// VTRUE, /* 常量 true */
// VFALSE, /* 常量 false */
// VK, /* 'k' 中的常量;info = 常量在 'k' 中的索引 */
// VKFLT, /* 浮点常量;nval = 数值型浮点值 */
// VKINT, /* 整数常量;nval = 数值型整数值 */
// VNONRELOC, /* 表达式的值在一个固定寄存器中;
// info = 结果寄存器 */
// VLOCAL, /* 局部变量;info = 局部寄存器 */
// VUPVAL, /* upvalue 变量;info = upvalue 在 'upvalues' 中的索引 */
// VINDEXED, /* 索引变量;
// ind.vt = 't' 是寄存器还是 upvalue;
// ind.t = 表寄存器或 upvalue;
// ind.idx = 键的 R/K 索引 */
// VJMP, /* 表达式是一个测试/比较;
// info = 对应跳转指令的 pc */
// VRELOCABLE, /* 表达式可以将结果放在任何寄存器;
// info = 指令 pc */
// VCALL, /* 表达式是一个函数调用;info = 指令 pc */
// VVARARG /* vararg 表达式;info = 指令 pc */
//} expkind;
#define vkisvar(k) (VLOCAL <= (k) && (k) <= VINDEXED)
#define vkisinreg(k) ((k) == VNONRELOC || (k) == VLOCAL)
// 它在 Lua 编译器的实现中用于描述表达式的不同方面。
// expdesc 结构体包含了表达式的类型、可能的值以及与表达式相关的一些额外信息。
/**
* expkind k;:这是一个枚举类型,表示表达式的种类。expkind 可能定义了不同的表达式类型,如变量、常量、跳转等。
* union { ... } u;:这是一个联合体,它允许 u 成员根据表达式的类型 k 存储不同的数据类型。
* lua_Integer ival;:当表达式是一个整数常量(可能由 expkind 中的 VKINT 表示)时,ival 被用来存储整数值。
* lua_Number nval;:当表达式是一个浮点数常量(可能由 expkind 中的 VKFLT 表示)时,nval 被用来存储浮点数值。
* int info;:一个通用的整数字段,用于存储表达式的其他信息或标志。
* struct { ... } ind;:当表达式涉及索引操作(如访问表中的元素,可能由 expkind 中的 VINDEXED 表示)时,
* 这个匿名结构体被用来存储索引信息。
* short idx;:表示索引值,可能用于访问寄存器或上值数组中的元素。
* lu_byte t;:表示索引的表,可以是一个寄存器索引或指向一个上值。
* lu_byte vt;:指示 t 是指向一个局部变量(VLOCAL)还是一个上值(VUPVAL)。
* int t;:表示当表达式为真时应该跳转到的代码位置的补丁列表。
* 这通常用于条件语句和循环语句,其中需要根据表达式的真值来决定程序的流程。
* int f;:表示当表达式为假时应该跳转到的代码位置的补丁列表。与 t 类似,f 用于控制程序流程,特别是在处理条件分支时。
*/
typedef struct expdesc {
expkind k;
union {
lua_Integer ival; /* for VKINT */
lua_Number nval; /* for VKFLT */
int info; /* for generic use */
struct { /* for indexed variables (VINDEXED) */
short idx; /* index (R/K) */
lu_byte t; /* table (register or upvalue) */
lu_byte vt; /* whether 't' is register (VLOCAL) or upvalue (VUPVAL) */
} ind;
} u;
int t; /* patch list of 'exit when true' */
int f; /* patch list of 'exit when false' */
} expdesc;
/* description of active local variable */
typedef struct Vardesc {
short idx; /* variable index in stack */
} Vardesc;
/* description of pending goto statements and label statements */
typedef struct Labeldesc {
TString *name; /* label identifier */
int pc; /* position in code */
int line; /* line where it appeared */
lu_byte nactvar; /* local level where it appears in current block */
} Labeldesc;
/* list of labels or gotos */
typedef struct Labellist {
Labeldesc *arr; /* array */
int n; /* number of entries in use */
int size; /* array size */
} Labellist;
/* dynamic structures used by the parser
* 它在 Lua 编译器的实现中用于存储动态数据,这些数据通常与当前函数的局部变量、待处理的跳转(goto)语句
* 以及活动标签有关。结构体 Dyndata 包含三个主要部分:actvar、gt 和 label。
* 下面是对 Dyndata 结构体中每个字段的解释:
* actvar:这是一个匿名结构体,用于管理当前函数中的活动局部变量(即当前在作用域内的局部变量)。
* Vardesc *arr;:指向 Vardesc 类型的数组的指针,Vardesc 是一种描述局部变量的辅助结构体。
* arr 数组存储了当前函数所有活动局部变量的信息。
* int n;:表示 arr 数组中当前的元素数量,即当前有多少个局部变量是活动的。
* int size;:表示 arr 数组的总容量,即它可以存储的局部变量的最大数量。
* gt:Labellist 类型的成员,用于存储当前函数中所有待处理的跳转(goto)语句的信息。
* Labellist 是可能定义了的另一种结构体,用于管理跳转语句的标签。
* label:也是 Labellist 类型的成员,用于存储当前函数中所有活动标签的信息。
* 活动标签是指那些在代码中已经定义,并且可能被跳转语句引用的标签。
* 这个结构体是 Lua 编译器在编译函数时用来跟踪和处理动态作用域数据的一种工具。
* 局部变量、跳转语句和标签是程序控制流的重要组成部分,Dyndata 结构体使得编译器能够有效地管理这些元素。
*/
typedef struct Dyndata {
struct { /* list of active local variables */
Vardesc *arr;
int n;
int size;
} actvar;
Labellist gt; /* list of pending gotos */
Labellist label; /* list of active labels */
} Dyndata;
/* control of blocks */
struct BlockCnt; /* defined in lparser.c */
/* state needed to generate code for a given function */
typedef struct FuncState {
Proto *f; /* current function header */
struct FuncState *prev; /* enclosing function */
struct LexState *ls; /* lexical state */
struct BlockCnt *bl; /* chain of current blocks */
int pc; /* next position to code (equivalent to 'ncode') */
int lasttarget; /* 'label' of last 'jump label' */
int jpc; /* list of pending jumps to 'pc' */
int nk; /* number of elements in 'k' 意思是 Proto f 中的数组k(常量)的长度*/
int np; /* number of elements in 'p' */
int firstlocal; /* index of first local var (in Dyndata array) */
short nlocvars; /* number of elements in 'f->locvars' */
lu_byte nactvar; /* number of active local variables */
lu_byte nups; /* number of upvalues */
lu_byte freereg; /* first free register */
} FuncState;
/**
* nactvar: number of active local variables
* 在 Lua 的源码中,nactvar 字段(代表活动局部变量的数量)在多个地方被使用,主要是在编译和执行阶段。以下是一些具体的使用场景:
* 函数编译:当编译器遇到一个新的局部变量声明时,nactvar 会增加,表示活动局部变量的数量增加。当局部变量离开其作用域时,nactvar 会减少。
* 寄存器分配:编译器在生成字节码时,需要为每个活动局部变量分配一个寄存器。nactvar 用于确定当前需要多少个寄存器。
* 作用域分析:在词法分析和作用域分析期间,nactvar 帮助编译器跟踪当前作用域内有多少局部变量是可见的。
* 代码生成:在生成字节码指令时,如 LOADVAR(加载局部变量)、STOREVAR(存储局部变量)等,编译器会根据 nactvar 来确定指向哪个局部变量。
* 调试器接口:Lua 的调试器接口可能使用 nactvar 来提供当前函数的活动局部变量信息,这有助于调试器展示当前的局部变量及其值。
* 错误处理:当执行过程中发生错误,如引用了一个未初始化的变量,编译器或运行时系统可能利用 nactvar 来确定哪个局部变量是未初始化的。
* 垃圾收集优化:虽然 nactvar 主要用于编译阶段,但它间接地影响垃圾收集。例如,如果一个局部变量不再被引用,
* 并且 nactvar 的值表明它已经不在活动列表中,那么对应的值可能就不再被需要,可以被垃圾收集器回收。
* 函数调用:在函数调用时,nactvar 有助于确定需要传递多少个局部变量给被调用的函数。
* 闭包创建:当创建闭包时,nactvar 可以帮助确定多少个局部变量需要捕获为上值。
*/
LUAI_FUNC LClosure *luaY_parser(lua_State *L, ZIO *z, Mbuffer *buff,
Dyndata *dyd, const char *name, int firstchar);
#endif
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/jaesoon/lua-engine.git
[email protected]:jaesoon/lua-engine.git
jaesoon
lua-engine
luaEngine
master

搜索帮助