0x0. 解析


在解析过程中,不管是左值还是右值,我们可以分为两种类型:

  • 变量:lua中的变量是没有类型的,只有作用域,因此变量在lua里面可以分为全局变量,局部变量,upvalue
    • 全局变量:保存在全局的hash表中,也叫环境变量。每个lua线程只有一份。
    • 局部变量:局部变量保存在函数栈中,也叫做寄存器。由于在lua中变量没有类型,所以每个寄存器的大小是一样的。
    • upvalue:upvalue也可以称之为函数环境变量。
  • 常量:常量也就是lua里面的数据类型,有VOID,NIL,字符串,数字 ``c typedef enum { VVOID, /* no value */ VNIL, VTRUE, VFALSE, VK, /* info = index of constant ink’ / VKNUM, / nval = numerical value / VLOCAL, / info = local register / VUPVAL, / info = index of upvalue in upvalues' */ VGLOBAL, /* info = index of table; aux = index of global name ink’ / VINDEXED, / info = table register; aux = index register (or `k’) / VJMP, / info = instruction pc / VRELOCABLE, / info = instruction pc / VNONRELOC, / info = result register / VCALL, / info = instruction pc / VVARARG / info = instruction pc */ } expkind;

typedef struct expdesc { expkind k; union { struct { int info, aux; } s; lua_Number nval; } u; int t; / patch list of `exit when true’ / int f; / patch list of `exit when false’ / } expdesc;

  1. <a name="Yehji"></a>
  2. ## 0x1. 左值
  3. ---
  4. <a name="Miopi"></a>
  5. #### local变量
  6. ```lua
  7. local var = 1

局部变量的解析需要完成两件事:

  • 解析变量名,用于后续的索引。后续可能会读这个变量。
  • 分配寄存器空间用于存储。

下面是创建局部变量的代码,从中可以看出

static void new_localvar (LexState *ls, TString *name, int n) {
  FuncState *fs = ls->fs;
  luaY_checklimit(fs, fs->nactvar+n+1, LUAI_MAXVARS, "local variables");
  fs->actvar[fs->nactvar+n] = cast(unsigned short, registerlocalvar(ls, name));
}

全局变量

var = 1

全局变量的解析需要完成:

  • 解析变量名,并放置到函数常量中,后续根据这个常量索引去访问全局变量

0x2. 右值


局部变量

局部变量的访问比较简单,就是根据名字找到对于的寄存器索引就可以。

全局变量

在lua中由于所有的变量操作都是基于栈进行的,所以要访问全局变量需要将全局变量加载到栈中才能访问。因此在lua中建议多次使用的全局变量保存到局部变量,再用局部变量去访问。