- 语法分析
语法分析表达式过程中处理数值定义
static void simpleexp (LexState *ls, expdesc *v) {
FuncState *fs = ls->fs;
switch (ls->t.token) {
case TK_NUMBER: { /* simpleexp -> NUMBER */
Number r = ls->t.seminfo.r;
next(ls);
luaK_number(fs, r); //定义数字
break;
}
- 类型判定
void luaK_number (FuncState *fs, Number f) {
if (f <= (Number)MAXARG_S && (Number)(int)f == f)
luaK_code1(fs, OP_PUSHINT, (int)f); //处理短整数short integer
else
luaK_code1(fs, OP_PUSHNUM, number_constant(fs, f)); //处理浮点数等其他数字
}
如果不是整型,那么从函数Proto.knum[]数组中查找是否有过同数字定义,如果有则返回序号,没有则添加并返回序号,同时将该数组大小加一:
static int number_constant (FuncState *fs, Number r) {
Proto *f = fs->f;
int c = f->nknum;
int lim = c < LOOKBACKNUMS ? 0 : c-LOOKBACKNUMS;
while (--c >= lim) //寻找是否有过同数值定义
if (f->knum[c] == r) return c;
luaM_growvector(fs->L, f->knum, f->nknum, 1, Number,
"constant table overflow", MAXARG_U);
c = f->nknum++; //数组大小增加
f->knum[c] = r; //将数值赋值进新的数组元素
return c;
}
代码生成
代码生成主要是调用luaK_code2,主要流程:
//获取前面一条指令,主要供优化使用
Instruction i = previous_instruction(fs);
//从luaK_opproperties结构体定义中获取该条指令对堆栈大小的影响
int delta = luaK_opproperties[o].push - luaK_opproperties[o].pop;
//代码优化开关,初始为不优化
int optm = 0
//这里根据指令类型,处理delta等,同时判定是否需要对该条指令进行优化
switch (o) {
case OP_CLOSURE: {
delta = -arg2+1;
break;
}
}
//这个函数用来修正FuncState结构中关于本函数的堆栈大小数值
//包括stacklevel和proto结构中的maxstacksize
luaK_deltastack(fs, delta);
//如果需要优化,这里将上一条指令覆盖为优化代码
if (optm) { /* optimize: put instruction in place of last one */
fs->f->code[fs->pc-1] = i; /* change previous instruction */
return fs->pc-1; /* do not generate new instruction */
}
//代码不需要优化,根据代码类型,生成指令
switch ((enum Mode)luaK_opproperties[o].mode) {
case iO: i = CREATE_0(o); break;
case iU: i = CREATE_U(o, arg1); break;
case iS: i = CREATE_S(o, arg1); break;
case iAB: i = CREATE_AB(o, arg1, arg2); break;
}
//扩展代码内存大小,填充新生成的指令
luaM_growvector(fs->L, fs->f->code, fs->pc, 1, Instruction,
"code size overflow", MAX_INT);
fs->f->code[fs->pc] = i;