## 1. 一个简单的例子

local a = {1,2,3}
a[6] = 1
a["aaa"]= 1



# 2.解析出的token是什么

// 我们的例子
local a = {1,2,3}
a[6] = 1
a["aaa"]= 1

268(TK_LOCAL) -> 285(TK_NAME) -> 61('=') -> 123('{') -> 284(TK_NUMBER) -> 44(',') -> 284(TK_NUMBER) -> 44(',') -> 284(TK_NUMBER) -> 125('}')
285(TK_NAME) -> 91('[') -> 284(TK_NUMBER) -> 93(']') -> 61('=') -> 284(TK_NUMBER)
285(TK_NAME) -> 91('[') -> 286(TK_STRING) -> 93(']') -> 61('=') -> 284(TK_NUMBER)



# 3.执行的开始

static int handle_script(gafq_State *L, char **argv, int n)
{
...
status = docall(L, narg, 0); // 这边执行了文件好像
...
}



# 4.执行

void gafqD_call(gafq_State *L, StkId func, int nResults)
{
//好像如果是c方法gafqD_precall这里会执行, gafq方法就gafqV_execute执行
if (gafqD_precall(L, func, nResults) == PCRGAFQ)// 判断是gafq的函数还是c的函数
gafqV_execute(L, 1);
}



# 5.gafqV_execute

gvm.c

void gafqV_execute(gafq_State *L, int nexeccalls)
{
...
for (;;)
{
//取出当前指令 i = 25165834  // 00011000000 00000000000 001010 // 001010是十进制10,这个操作是创建一个新的table
const Instruction i = *pc++;
...
ra = RA(i); // 0x635420
switch (GET_OPCODE(i))
{
case OP_NEWTABLE:
{
int b = GETARG_B(i);
int c = GETARG_C(i);
sethvalue(L, ra, gafqH_new(L, gafqO_fb2int(b), gafqO_fb2int(c)));
Protect(gafqC_checkGC(L));
continue;
}
}
}
}



# 6.gafqV_execute 我们所有的指令i

gvm.c

const Instruction i = *pc++;
i = 25165834    OP_NEWTABLE
i = 25182242    OP_SETLIST
i = 2176843785  OP_SETTABLE
i = 2185232393  OP_SETTABLE
i = 8388638     OP_RETURN



# 7. 初始化table

gtable.c

// 初始化table
Table *gafqH_new(gafq_State *L, int narray, int nhash)
{
Table *t = gafqM_new(L, Table);
t->metatable = NULL;
t->flags = cast_byte(~0);
/* temporary values (kept only if some malloc fails) */
t->array = NULL;
t->sizearray = 0;
t->lsizenode = 0;
t->node = cast(Node *, dummynode);
setarrayvector(L, t, narray); // 初始化数组部分
setnodevector(L, t, nhash);   // 初始化哈希部分
return t;
}

// 初始化数组部分, 我们的例子local a = {1,2,3}这里数组部分size是3
static void setarrayvector(gafq_State *L, Table *t, int size)
{
int i;
gafqM_reallocvector(L, t->array, t->sizearray, size, TValue);
for (i = t->sizearray; i < size; i++)
setnilvalue(&t->array[i]);
t->sizearray = size;
}

//我们的例子local a = {1,2,3}这里的size是0
static void setnodevector(gafq_State *L, Table *t, int size)
{
int lsize;
if (size == 0)
{                                      /* no elements to hash part? */
t->node = cast(Node *, dummynode); /* use common dummynode' */
lsize = 0;
}
else
{   // 新建表有hash的时候的数据
...
}
t->lsizenode = cast_byte(lsize);
t->lastfree = gnode(t, size); /* all positions are free */
}



# 8.看OP_SETLIST操作,对应我们的local a = {1,2,3}

case OP_SETLIST:
{
int n = GETARG_B(i);
int c = GETARG_C(i);
int last;
Table *h;
if (n == 0)
{
n = cast_int(L->top - ra) - 1;
L->top = L->ci->top;
}
if (c == 0)
c = cast_int(*pc++);
runtime_check(L, ttistable(ra));
h = hvalue(ra); // ra放的是我们的table
last = ((c - 1) * LFIELDS_PER_FLUSH) + n;
if (last > h->sizearray) // 判断数组部分的空间够不够
gafqH_resizearray(L, h, last); // 重新弄一下数组部分的空间
for (; n > 0; n--)
{
TValue *val = ra + n;
setobj2t(L, gafqH_setnum(L, h, last--), val);
gafqC_barriert(L, h, val);
}
continue;
}
// 扩大数组部分的空间
void gafqH_resizearray(gafq_State *L, Table *t, int nasize)
{
int nsize = (t->node == dummynode) ? 0 : sizenode(t);
resize(L, t, nasize, nsize);
}

// 重新计算我们的table的大小
static void resize(gafq_State *L, Table *t, int nasize, int nhsize)
{
int i;
int oldasize = t->sizearray;
int oldhsize = t->lsizenode;
Node *nold = t->node;  原本的哈希表部分
if (nasize > oldasize) // 判断数组部分需要增加?
setarrayvector(L, t, nasize);
setnodevector(L, t, nhsize); // 增加哈希部分的空间
if (nasize < oldasize)
{ /* array part must shrink? */
t->sizearray = nasize;
/* re-insert elements from vanishing slice */
for (i = nasize; i < oldasize; i++)
{
if (!ttisnil(&t->array[i]))
setobjt2t(L, gafqH_setnum(L, t, i + 1), &t->array[i]);
}
/* shrink array */
gafqM_reallocvector(L, t->array, oldasize, nasize, TValue);
}
/* re-insert elements from hash part */
for (i = twoto(oldhsize) - 1; i >= 0; i--)
{
Node *old = nold + i;
if (!ttisnil(gval(old)))
setobjt2t(L, gafqH_set(L, t, key2tval(old)), gval(old));
}
if (nold != dummynode)
gafqM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */
}

TValue *gafqH_setnum(gafq_State *L, Table *t, int key)
{
const TValue *p = gafqH_getnum(t, key);
if (p != gafqO_nilobject)
return cast(TValue *, p);
else
{
TValue k;
setnvalue(&k, cast_num(key));
return newkey(L, t, &k);
}
}
// 查找的数字
const TValue *gafqH_getnum(Table *t, int key)
{
// 如果查找的索引在array里面,那么是在数组里面,否则是在哈希表里面
if (cast(unsigned int, key - 1) < cast(unsigned int, t->sizearray))
return &t->array[key - 1];
else
{
gafq_Number nk = cast_num(key);
Node *n = hashnum(t, nk);
do
{ /* check whether key' is somewhere in the chain */
if (ttisnumber(gkey(n)) && gafqi_numeq(nvalue(gkey(n)), nk))
return gval(n); /* that's it */
else
n = gnext(n);
} while (n);
return gafqO_nilobject;
}
}



# 9.看OP_SETTABLE操作

void gafqV_execute(gafq_State *L, int nexeccalls)
{
for (;;)
{
//取出当前指令
const Instruction i = *pc++;
...
switch (GET_OPCODE(i)){
...

case OP_SETTABLE:
{
//但操作的表不在 upvalue 中，而在寄存器里。它们在实现上的区别仅在于，前者b是对 upvalue 的索引，而后者则表示寄存器号。
Protect(gafqV_settable(L, ra, RKB(i), RKC(i)));
continue;
}
}
}
}

//对表结构写操作的封装，同样会引发元方法
void gafqV_settable(gafq_State *L, const TValue *t, TValue *key, StkId val)
{
int loop;
TValue temp;
for (loop = 0; loop < MAXTAGLOOP; loop++) // 避免元表死循环
{
const TValue *tm;
if (ttistable(t))
{   // 我们这里是个table
Table *h = hvalue(t);
TValue *oldval = gafqH_set(L, h, key);
if (!ttisnil(oldval) || (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL)
{   //没有元方法走这里
setobj2t(L, oldval, val);
h->flags = 0;
gafqC_barriert(L, h, val); // 处理垃圾回收
return;
}
/* else will try the tag method */
}
if (ttisfunction(tm))
{
// 有元方法走这里
callTM(L, tm, t, key, val);
return;
}
...
setobj(L, &temp, tm);
t = &temp;
}
gafqG_runerror(L, "loop in settable");
}