• ## 2.1 statement中的forstat类别
  1. for 语句的解析
    • for的构成一般由以下例子构成
        for i = 1, 10 do
        end
        for i = 1, 10, 2 do
        end
    
        for a,b in ipairs({}) do
    
        end
        for a,b in pairs({}) do
    
        end
    
  2. forstat解析
    static void forstat(LexState *ls, int line)
    {
    
    
        varname = str_checkname(ls); // 第一个变量名
        switch (ls->t.token)
        {
        case '=':
            fornum(ls, varname, line);
            break;
        case ',':
        case TK_IN:
            forlist(ls, varname);
            break;
        }
        check_match(ls, TK_END, TK_FOR, line);
        leaveblock(fs); /* loop scope (`break' jumps to this point) */
    }
    
    
  3. 当值是 fornum 的时候
        static void fornum(LexState *ls, TString *varname, int line)
    {
        FuncState *fs = ls->fs;
        int base = fs->freereg;
        new_localvarliteral(ls, "(for index)", 0);
        new_localvarliteral(ls, "(for limit)", 1);
        new_localvarliteral(ls, "(for step)", 2);
        new_localvar(ls, varname, 3);
        checknext(ls, '=');
        exp1(ls); /* initial value */
        checknext(ls, ',');
        exp1(ls); /* limit */
        if (testnext(ls, ','))
            exp1(ls); /* optional step */
        else
        { /* default step = 1 */
            gafqK_codeABx(fs, OP_LOADK, fs->freereg, gafqK_numberK(fs, 1));
            gafqK_reserveregs(fs, 1);
        }
        forbody(ls, base, line, 1, 1);
    }
    
  4. 解析新的local变量
    • 注册一个新的local变量,会先检查local变量的数量,然后将变量放入proto的locvars中,然后返回 当前本地变量的数量
    // 解析新的local变量
        static void new_localvar(LexState *ls, TString *name, int n)
        {
            FuncState *fs = ls->fs;
            gafqY_checklimit(fs, fs->nactvar + n + 1, GAFQI_MAXVARS, "local variables");
            fs->actvar[fs->nactvar + n] = cast(unsigned short, registerlocalvar(ls, name));
        }
    
        static int registerlocalvar(LexState *ls, TString *varname)
    {
        FuncState *fs = ls->fs;
        Proto *f = fs->f;
        int oldsize = f->sizelocvars;
        gafqM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars, LocVar, SHRT_MAX, "too many local variables");
        while (oldsize < f->sizelocvars)
            f->locvars[oldsize++].varname = NULL;
        f->locvars[fs->nlocvars].varname = varname;
        gafqC_objbarrier(ls->L, f, varname);
        return fs->nlocvars++;
    }
    
  5. 解析表达式exp1
    static int exp1(LexState *ls)
    {
        expdesc e;
        int k;
        expr(ls, &e);
        k = e.k;
        gafqK_exp2nextreg(ls->fs, &e);
        return k;
    }
    
    void gafqK_exp2nextreg(FuncState *fs, expdesc *e)
    {
        gafqK_dischargevars(fs, e);
        freeexp(fs, e);
        gafqK_reserveregs(fs, 1);
        exp2reg(fs, e, fs->freereg - 1);
    }
    
    // 把表达式放进寄存器中
    static void exp2reg(FuncState *fs, expdesc *e, int reg)
    {
        discharge2reg(fs, e, reg);
        e->f = e->t = NO_JUMP;
        e->u.s.info = reg;
        e->k = VNONRELOC;
    }
    
    // reg是要被使用的寄存器的位置
    static void discharge2reg(FuncState *fs, expdesc *e, int reg)
    {
        gafqK_dischargevars(fs, e);
        switch (e->k)
        {
        case VKNUM:
        {
            gafqK_codeABx(fs, OP_LOADK, reg, gafqK_numberK(fs, e->u.nval)); // 这里生成一个操作指令, 把值存到常量k里面去
            break;
        }
        }
        e->u.s.info = reg;
        e->k = VNONRELOC;
    }
    
  6. 解析循环的body
    // isnum 是否是数字类型的循环 for i = 1, 10 do
    static void forbody(LexState *ls, int base, int line, int nvars, int isnum)
    {
    
        checknext(ls, TK_DO);
        prep = isnum ? gafqK_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : gafqK_jump(fs);
        enterblock(fs, &bl, 0);
        adjustlocalvars(ls, nvars);
        gafqK_reserveregs(fs, nvars);
        block(ls);
        leaveblock(fs); /* end of scope for declared variables */
        gafqK_patchtohere(fs, prep);
        endfor = (isnum) ? gafqK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP) : gafqK_codeABC(fs, OP_TFORLOOP, base, 0, nvars);
        gafqK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */
        gafqK_patchlist(fs, (isnum ? endfor : gafqK_jump(fs)), prep + 1);
    }
    
    

发表评论