Example #1
0
 private static void assignment(LexState ls, LHS_assign lh, int nvars)
 {
     expdesc e = new expdesc();
     check_condition(ls, expkind.VLOCAL <= lh.v.k && lh.v.k <= expkind.VINDEXED,
                     "syntax error");
     if (testnext(ls, ',') != 0)
     {  /* assignment . `,' primaryexp assignment */
         LHS_assign nv = new LHS_assign();
         nv.prev = lh;
         primaryexp(ls, nv.v);
         if (nv.v.k == expkind.VLOCAL)
             check_conflict(ls, lh, nv.v);
         luaY_checklimit(ls.fs, nvars, Lua.LUAI_MAXCCALLS - ls.L.nCcalls,
                         "variables in assignment");
         assignment(ls, nv, nvars + 1);
     }
     else
     {  /* assignment . `=' explist1 */
         int nexps;
         checknext(ls, '=');
         nexps = explist1(ls, e);
         if (nexps != nvars)
         {
             adjust_assign(ls, nvars, nexps, e);
             if (nexps > nvars)
                 ls.fs.freereg -= nexps - nvars;  /* remove extra values */
         }
         else
         {
             Lua.luaK_setoneret(ls.fs, e);  /* close last expression */
             Lua.luaK_storevar(ls.fs, lh.v, e);
             return;  /* avoid default */
         }
     }
     init_exp(e, expkind.VNONRELOC, ls.fs.freereg - 1);  /* default assignment */
     Lua.luaK_storevar(ls.fs, lh.v, e);
 }
Example #2
0
 private static void primaryexp(LexState ls, expdesc v)
 {
     /* primaryexp .
         prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */
     FuncState fs = ls.fs;
     prefixexp(ls, v);
     for (; ; )
     {
         switch (ls.t.token)
         {
             case '.':
                 {  /* field */
                     field(ls, v);
                     break;
                 }
             case '[':
                 {  /* `[' exp1 `]' */
                     expdesc key = new expdesc();
                     Lua.luaK_exp2anyreg(fs, v);
                     yindex(ls, key);
                     Lua.luaK_indexed(fs, v, key);
                     break;
                 }
             case ':':
                 {  /* `:' NAME funcargs */
                     expdesc key = new expdesc();
                     Lua.luaX_next(ls);
                     checkname(ls, key);
                     Lua.luaK_self(fs, v, key);
                     funcargs(ls, v);
                     break;
                 }
             case '(':
             case (int)RESERVED.TK_STRING:
             case '{':
                 {  /* funcargs */
                     Lua.luaK_exp2nextreg(fs, v);
                     funcargs(ls, v);
                     break;
                 }
             default: return;
         }
     }
 }
Example #3
0
        public const int UNARY_PRIORITY = 8;  /* priority for unary operators */

        /*
         ** subexpr . (simpleexp | unop subexpr) { binop subexpr }
         ** where `binop' is any binary operator with a priority higher than `limit'
         */

        private static BinOpr subexpr(LexState ls, expdesc v, uint limit)
        {
            BinOpr op = new BinOpr();
            UnOpr uop = new UnOpr();
            enterlevel(ls);
            uop = getunopr(ls.t.token);
            if (uop != UnOpr.OPR_NOUNOPR)
            {
                Lua.luaX_next(ls);
                subexpr(ls, v, UNARY_PRIORITY);
                Lua.luaK_prefix(ls.fs, uop, v);
            }
            else
                simpleexp(ls, v);
            /* expand while operators have priorities higher than `limit' */
            op = getbinopr(ls.t.token);
            while (op != BinOpr.OPR_NOBINOPR && priority[(int)op].left > limit)
            {
                expdesc v2 = new expdesc();
                BinOpr nextop;
                Lua.luaX_next(ls);
                Lua.luaK_infix(ls.fs, op, v);
                /* read sub-expression with higher priority */
                nextop = subexpr(ls, v2, priority[(int)op].right);
                Lua.luaK_posfix(ls.fs, op, v, v2);
                op = nextop;
            }
            leavelevel(ls);
            return op;  /* return first untreated operator */
        }
Example #4
0
 private static void body(LexState ls, expdesc e, int needself, int line)
 {
     /* body .  `(' parlist `)' chunk END */
     FuncState new_fs = new FuncState();
     open_func(ls, new_fs);
     new_fs.f.linedefined = line;
     checknext(ls, '(');
     if (needself != 0)
     {
         new_localvarliteral(ls, "self", 0);
         adjustlocalvars(ls, 1);
     }
     parlist(ls);
     checknext(ls, ')');
     chunk(ls);
     new_fs.f.lastlinedefined = ls.linenumber;
     check_match(ls, (int)RESERVED.TK_END, (int)RESERVED.TK_FUNCTION, line);
     close_func(ls);
     pushclosure(ls, new_fs, e);
 }
Example #5
0
        private static void funcargs(LexState ls, expdesc f)
        {
            FuncState fs = ls.fs;
            expdesc args = new expdesc();
            int base_, nparams;
            int line = ls.linenumber;
            switch (ls.t.token)
            {
                case '(':
                    {  /* funcargs . `(' [ explist1 ] `)' */
                        if (line != ls.lastline)
                            Lua.luaX_syntaxerror(ls, "ambiguous syntax (function call x new statement)");
                        Lua.luaX_next(ls);
                        if (ls.t.token == ')')  /* arg list is empty? */
                            args.k = expkind.VVOID;
                        else
                        {
                            explist1(ls, args);
                            Lua.luaK_setmultret(fs, args);
                        }
                        check_match(ls, ')', '(', line);
                        break;
                    }
                case '{':
                    {  /* funcargs . constructor */
                        constructor(ls, args);
                        break;
                    }
                case (int)RESERVED.TK_STRING:
                    {  /* funcargs . STRING */
                        codestring(ls, args, ls.t.seminfo.ts);
                        Lua.luaX_next(ls);  /* must use `seminfo' before `next' */
                        break;
                    }
                default:
                    {
                        Lua.luaX_syntaxerror(ls, "function arguments expected");
                        return;
                    }
            }
            Lua.lua_assert(f.k == expkind.VNONRELOC);
            base_ = f.u.s.info;  /* base_ register for call */
            if (hasmultret(args.k) != 0)
                nparams = Lua.LUA_MULTRET;  /* open call */
            else
            {
                if (args.k != expkind.VVOID)
                    Lua.luaK_exp2nextreg(fs, args);  /* close last argument */
                nparams = fs.freereg - (base_ + 1);
            }
            init_exp(f, expkind.VCALL, Lua.luaK_codeABC(fs, OpCode.OP_CALL, base_, nparams + 1, 2));
            Lua.luaK_fixline(fs, line);
            fs.freereg = base_ + 1;  /* call remove function and arguments and leaves
									(unless changed) one result */
        }
Example #6
0
        /*============================================================*/
        /* GRAMMAR RULES */
        /*============================================================*/

        private static void field(LexState ls, expdesc v)
        {
            /* field . ['.' | ':'] NAME */
            FuncState fs = ls.fs;
            expdesc key = new expdesc();
            Lua.luaK_exp2anyreg(fs, v);
            Lua.luaX_next(ls);  /* skip the dot or colon */
            checkname(ls, key);
            Lua.luaK_indexed(fs, v, key);
        }
Example #7
0
 private static void recfield(LexState ls, ConsControl cc)
 {
     /* recfield . (NAME | `['exp1`]') = exp1 */
     /* recfield -> FUNCTION funcname body */
     FuncState fs = ls.fs;
     int reg = ls.fs.freereg;
     expdesc key = new expdesc(), val = new expdesc();
     int rkkey;
     if (ls.t.token == (int)RESERVED.TK_NAME)
     {
         luaY_checklimit(fs, cc.nh, Lua.MAX_INT, "items in a constructor");
         checkname(ls, key);
     }
     else  /* ls.t.token == '[' */
         yindex(ls, key);
     cc.nh++;
     checknext(ls, '=');
     rkkey = Lua.luaK_exp2RK(fs, key);
     expr(ls, val);
     Lua.luaK_codeABC(fs, OpCode.OP_SETTABLE, cc.t.u.s.info, rkkey, Lua.luaK_exp2RK(fs, val));
     fs.freereg = reg;  /* free registers */
 }
Example #8
0
 private static void checkname(LexState ls, expdesc e)
 {
     codestring(ls, e, str_checkname(ls));
 }
Example #9
0
 private static void localfunc(LexState ls)
 {
     expdesc v = new expdesc(), b = new expdesc();
     FuncState fs = ls.fs;
     new_localvar(ls, str_checkname(ls), 0);
     init_exp(v, expkind.VLOCAL, fs.freereg);
     Lua.luaK_reserveregs(fs, 1);
     adjustlocalvars(ls, 1);
     body(ls, b, 0, ls.linenumber);
     Lua.luaK_storevar(fs, v, b);
     /* debug information will only see the variable after this point! */
     getlocvar(fs, fs.nactvar - 1).startpc = fs.pc;
 }
Example #10
0
 private static void codestring(LexState ls, expdesc e, TString s)
 {
     init_exp(e, expkind.VK, Lua.luaK_stringK(ls.fs, s));
 }
Example #11
0
 private static void forlist(LexState ls, TString indexname)
 {
     /* forlist . NAME {,NAME} IN explist1 forbody */
     FuncState fs = ls.fs;
     expdesc e = new expdesc();
     int nvars = 0;
     int line;
     int base_ = fs.freereg;
     /* create control variables */
     new_localvarliteral(ls, "(for generator)", nvars++);
     new_localvarliteral(ls, "(for state)", nvars++);
     new_localvarliteral(ls, "(for control)", nvars++);
     /* create declared variables */
     new_localvar(ls, indexname, nvars++);
     while (testnext(ls, ',') != 0)
         new_localvar(ls, str_checkname(ls), nvars++);
     checknext(ls, (int)RESERVED.TK_IN);
     line = ls.linenumber;
     adjust_assign(ls, 3, explist1(ls, e), e);
     Lua.luaK_checkstack(fs, 3);  /* extra space to call generator */
     forbody(ls, base_, line, nvars - 3, 0);
 }
Example #12
0
 private static int exp1(LexState ls)
 {
     expdesc e = new expdesc();
     int k;
     expr(ls, e);
     k = (int)e.k;
     Lua.luaK_exp2nextreg(ls.fs, e);
     return k;
 }
Example #13
0
 private static void init_exp(expdesc e, expkind k, int i)
 {
     e.f = e.t = Lua.NO_JUMP;
     e.k = k;
     e.u.s.info = i;
 }
Example #14
0
 private static int cond(LexState ls)
 {
     /* cond . exp */
     expdesc v = new expdesc();
     expr(ls, v);  /* read condition */
     if (v.k == expkind.VNIL)
         v.k = expkind.VFALSE;  /* `falses' are all equal here */
     Lua.luaK_goiftrue(ls.fs, v);
     return v.f;
 }
Example #15
0
 private static void adjust_assign(LexState ls, int nvars, int nexps, expdesc e)
 {
     FuncState fs = ls.fs;
     int extra = nvars - nexps;
     if (hasmultret(e.k) != 0)
     {
         extra++;  /* includes call itself */
         if (extra < 0) extra = 0;
         Lua.luaK_setreturns(fs, e, extra);  /* last exp. provides the difference */
         if (extra > 1) Lua.luaK_reserveregs(fs, extra - 1);
     }
     else
     {
         if (e.k != expkind.VVOID) Lua.luaK_exp2nextreg(fs, e);  /* close last expression */
         if (extra > 0)
         {
             int reg = fs.freereg;
             Lua.luaK_reserveregs(fs, extra);
             Lua.luaK_nil(fs, reg, extra);
         }
     }
 }
Example #16
0
 private static void localstat(LexState ls)
 {
     /* stat . LOCAL NAME {`,' NAME} [`=' explist1] */
     int nvars = 0;
     int nexps;
     expdesc e = new expdesc();
     do
     {
         new_localvar(ls, str_checkname(ls), nvars++);
     } while (testnext(ls, ',') != 0);
     if (testnext(ls, '=') != 0)
         nexps = explist1(ls, e);
     else
     {
         e.k = expkind.VVOID;
         nexps = 0;
     }
     adjust_assign(ls, nvars, nexps, e);
     adjustlocalvars(ls, nvars);
 }
Example #17
0
 private static void pushclosure(LexState ls, FuncState func, expdesc v)
 {
     FuncState fs = ls.fs;
     Proto f = fs.f;
     int oldsize = f.sizep;
     int i;
     Lua.luaM_growvector(ls.L, ref f.p, fs.np, ref f.sizep,
                     Lua.MAXARG_Bx, "constant table overflow");
     while (oldsize < f.sizep) f.p[oldsize++] = null;
     f.p[fs.np++] = func.f;
     Lua.luaC_objbarrier(ls.L, f, func.f);
     init_exp(v, expkind.VRELOCABLE, Lua.luaK_codeABx(fs, OpCode.OP_CLOSURE, 0, fs.np - 1));
     for (i = 0; i < func.f.nups; i++)
     {
         OpCode o = ((int)func.upvalues[i].k == (int)expkind.VLOCAL) ? OpCode.OP_MOVE : OpCode.OP_GETUPVAL;
         Lua.luaK_codeABC(fs, o, 0, func.upvalues[i].info, 0);
     }
 }
Example #18
0
 private static int funcname(LexState ls, expdesc v)
 {
     /* funcname . NAME {field} [`:' NAME] */
     int needself = 0;
     singlevar(ls, v);
     while (ls.t.token == '.')
         field(ls, v);
     if (ls.t.token == ':')
     {
         needself = 1;
         field(ls, v);
     }
     return needself;
 }
Example #19
0
        private static void yindex(LexState ls, expdesc v)
        {
            /* index . '[' expr ']' */

            //luaX_next(ls);  /* skip the '[' */
            //expr(ls, v);
            //luaK_exp2val(ls.fs, v);
            //checknext(ls, ']');

            Lua.luaX_next(ls); /* skip the '[' */
            do
            {
                expr(ls, v);
                Lua.luaK_exp2val(ls.fs, v);

                //yindex(ls, key);
                //luaK_indexed(ls.fs, v, key);
            } while (testnext(ls, ',') == 1);
            checknext(ls, ']');
        }
Example #20
0
 private static void funcstat(LexState ls, int line)
 {
     /* funcstat . FUNCTION funcname body */
     int needself;
     expdesc v = new expdesc(), b = new expdesc();
     Lua.luaX_next(ls);  /* skip FUNCTION */
     needself = funcname(ls, v);
     body(ls, b, needself, line);
     Lua.luaK_storevar(ls.fs, v, b);
     Lua.luaK_fixline(ls.fs, line);  /* definition `happens' in the first line */
 }
Example #21
0
 private static void constructor(LexState ls, expdesc t)
 {
     /* constructor . ?? */
     FuncState fs = ls.fs;
     int line = ls.linenumber;
     int pc = Lua.luaK_codeABC(fs, OpCode.OP_NEWTABLE, 0, 0, 0);
     ConsControl cc = new ConsControl();
     cc.na = cc.nh = cc.tostore = 0;
     cc.t = t;
     init_exp(t, expkind.VRELOCABLE, pc);
     init_exp(cc.v, expkind.VVOID, 0);  /* no value (yet) */
     Lua.luaK_exp2nextreg(ls.fs, t);  /* fix it at stack top (for gc) */
     checknext(ls, '{');
     do
     {
         Lua.lua_assert(cc.v.k == expkind.VVOID || cc.tostore > 0);
         if (ls.t.token == '}') break;
         closelistfield(fs, cc);
         switch (ls.t.token)
         {
             case (int)RESERVED.TK_NAME:
                 {  /* may be listfields or recfields */
                     Lua.luaX_lookahead(ls);
                     if (ls.lookahead.token != '=')  /* expression? */
                         listfield(ls, cc);
                     else
                         recfield(ls, cc);
                     break;
                 }
             case '[':
                 {  /* constructor_item . recfield */
                     recfield(ls, cc);
                     break;
                 }
             default:
                 {  /* constructor_part . listfield */
                     listfield(ls, cc);
                     break;
                 }
         }
     } while ((testnext(ls, ',') != 0) || (testnext(ls, ';') != 0));
     check_match(ls, '}', '{', line);
     lastlistfield(fs, cc);
     Lua.SETARG_B(new InstructionPtr(fs.f.code, pc), Lua.luaO_int2fb((uint)cc.na)); /* set initial array size */
     Lua.SETARG_C(new InstructionPtr(fs.f.code, pc), Lua.luaO_int2fb((uint)cc.nh));  /* set initial table size */
 }
Example #22
0
 private static void retstat(LexState ls)
 {
     /* stat . RETURN explist */
     FuncState fs = ls.fs;
     expdesc e = new expdesc();
     int first, nret;  /* registers with returned values */
     Lua.luaX_next(ls);  /* skip RETURN */
     if ((block_follow(ls.t.token) != 0) || ls.t.token == ';')
         first = nret = 0;  /* return no values */
     else
     {
         nret = explist1(ls, e);  /* optional return values */
         if (hasmultret(e.k) != 0)
         {
             Lua.luaK_setmultret(fs, e);
             if (e.k == expkind.VCALL && nret == 1)
             {  /* tail call? */
                 Lua.SET_OPCODE(Lua.getcode(fs, e), OpCode.OP_TAILCALL);
                 Lua.lua_assert(Lua.GETARG_A(Lua.getcode(fs, e)) == fs.nactvar);
             }
             first = fs.nactvar;
             nret = Lua.LUA_MULTRET;  /* return all values */
         }
         else
         {
             if (nret == 1)  /* only one single value? */
                 first = Lua.luaK_exp2anyreg(fs, e);
             else
             {
                 Lua.luaK_exp2nextreg(fs, e);  /* values must go to the `stack' */
                 first = fs.nactvar;  /* return all `active' values */
                 Lua.lua_assert(nret == fs.freereg - first);
             }
         }
     }
     Lua.luaK_ret(fs, first, nret);
 }
Example #23
0
 private static int explist1(LexState ls, expdesc v)
 {
     /* explist1 . expr { `,' expr } */
     int n = 1;  /* at least one expression */
     expr(ls, v);
     while (testnext(ls, ',') != 0)
     {
         Lua.luaK_exp2nextreg(ls.fs, v);
         expr(ls, v);
         n++;
     }
     return n;
 }
Example #24
0
 private static int indexupvalue(FuncState fs, TString name, expdesc v)
 {
     int i;
     Proto f = fs.f;
     int oldsize = f.sizeupvalues;
     for (i = 0; i < f.nups; i++)
     {
         if ((int)fs.upvalues[i].k == (int)v.k && fs.upvalues[i].info == v.u.s.info)
         {
             Lua.lua_assert(f.upvalues[i] == name);
             return i;
         }
     }
     /* new one */
     luaY_checklimit(fs, f.nups + 1, Lua.LUAI_MAXUPVALUES, "upvalues");
     Lua.luaM_growvector(fs.L, ref f.upvalues, f.nups, ref f.sizeupvalues, Lua.MAX_INT, "");
     while (oldsize < f.sizeupvalues) f.upvalues[oldsize++] = null;
     f.upvalues[f.nups] = name;
     Lua.luaC_objbarrier(fs.L, f, name);
     Lua.lua_assert(v.k == expkind.VLOCAL || v.k == expkind.VUPVAL);
     fs.upvalues[f.nups].k = Lua.cast_byte(v.k);
     fs.upvalues[f.nups].info = Lua.cast_byte(v.u.s.info);
     return f.nups++;
 }
Example #25
0
        /*
         ** {======================================================================
         ** Expression parsing
         ** =======================================================================
         */

        private static void prefixexp(LexState ls, expdesc v)
        {
            /* prefixexp . NAME | '(' expr ')' */
            switch (ls.t.token)
            {
                case '(':
                    {
                        int line = ls.linenumber;
                        Lua.luaX_next(ls);
                        expr(ls, v);
                        check_match(ls, ')', '(', line);
                        Lua.luaK_dischargevars(ls.fs, v);
                        return;
                    }
                case (int)RESERVED.TK_NAME:
                    {
                        singlevar(ls, v);
                        return;
                    }
                default:
                    {
                        Lua.luaX_syntaxerror(ls, "unexpected symbol");
                        return;
                    }
            }
        }
Example #26
0
 private static expkind singlevaraux(FuncState fs, TString n, expdesc var, int base_)
 {
     if (fs == null)
     {  /* no more levels? */
         init_exp(var, expkind.VGLOBAL, Lua.NO_REG);  /* default is global variable */
         return expkind.VGLOBAL;
     }
     else
     {
         int v = searchvar(fs, n);  /* look up at current level */
         if (v >= 0)
         {
             init_exp(var, expkind.VLOCAL, v);
             if (base_ == 0)
                 markupval(fs, v);  /* local will be used as an upval */
             return expkind.VLOCAL;
         }
         else
         {  /* not found at current level; try upper one */
             if (singlevaraux(fs.prev, n, var, 0) == expkind.VGLOBAL)
                 return expkind.VGLOBAL;
             var.u.s.info = indexupvalue(fs, n, var);  /* else was LOCAL or UPVAL */
             var.k = expkind.VUPVAL;  /* upvalue in this level */
             return expkind.VUPVAL;
         }
     }
 }
Example #27
0
 private static void simpleexp(LexState ls, expdesc v)
 {
     /* simpleexp . NUMBER | STRING | NIL | true | false | ... |
                   constructor | FUNCTION body | primaryexp */
     switch (ls.t.token)
     {
         case (int)RESERVED.TK_NUMBER:
             {
                 init_exp(v, expkind.VKNUM, 0);
                 v.u.nval = ls.t.seminfo.r;
                 break;
             }
         case (int)RESERVED.TK_STRING:
             {
                 codestring(ls, v, ls.t.seminfo.ts);
                 break;
             }
         case (int)RESERVED.TK_NIL:
             {
                 init_exp(v, expkind.VNIL, 0);
                 break;
             }
         case (int)RESERVED.TK_TRUE:
             {
                 init_exp(v, expkind.VTRUE, 0);
                 break;
             }
         case (int)RESERVED.TK_FALSE:
             {
                 init_exp(v, expkind.VFALSE, 0);
                 break;
             }
         case (int)RESERVED.TK_DOTS:
             {  /* vararg */
                 FuncState fs = ls.fs;
                 check_condition(ls, fs.f.is_vararg != 0,
                                 "cannot use " + Lua.LUA_QL("...") + " outside a vararg function");
                 fs.f.is_vararg &= unchecked((lu_byte)(~Lua.VARARG_NEEDSARG));  /* don't need 'arg' */
                 init_exp(v, expkind.VVARARG, Lua.luaK_codeABC(fs, OpCode.OP_VARARG, 0, 1, 0));
                 break;
             }
         case '{':
             {  /* constructor */
                 constructor(ls, v);
                 return;
             }
         case (int)RESERVED.TK_FUNCTION:
             {
                 Lua.luaX_next(ls);
                 body(ls, v, 0, ls.linenumber);
                 return;
             }
         default:
             {
                 primaryexp(ls, v);
                 return;
             }
     }
     Lua.luaX_next(ls);
 }
Example #28
0
 private static void singlevar(LexState ls, expdesc var)
 {
     TString varname = str_checkname(ls);
     FuncState fs = ls.fs;
     if (singlevaraux(fs, varname, var, 1) == expkind.VGLOBAL)
         var.u.s.info = Lua.luaK_stringK(fs, varname);  /* info points to global name */
 }
Example #29
0
 private static void expr(LexState ls, expdesc v)
 {
     subexpr(ls, v, 0);
 }
Example #30
0
        /*
         ** check whether, in an assignment to a local variable, the local variable
         ** is needed in a previous assignment (to a table). If so, save original
         ** local value in a safe place and use this safe copy in the previous
         ** assignment.
         */

        private static void check_conflict(LexState ls, LHS_assign lh, expdesc v)
        {
            FuncState fs = ls.fs;
            int extra = fs.freereg;  /* eventual position to save local variable */
            int conflict = 0;
            for (; lh != null; lh = lh.prev)
            {
                if (lh.v.k == expkind.VINDEXED)
                {
                    if (lh.v.u.s.info == v.u.s.info)
                    {  /* conflict? */
                        conflict = 1;
                        lh.v.u.s.info = extra;  /* previous assignment will use safe copy */
                    }
                    if (lh.v.u.s.aux == v.u.s.info)
                    {  /* conflict? */
                        conflict = 1;
                        lh.v.u.s.aux = extra;  /* previous assignment will use safe copy */
                    }
                }
            }
            if (conflict != 0)
            {
                Lua.luaK_codeABC(fs, OpCode.OP_MOVE, fs.freereg, v.u.s.info, 0);  /* make copy */
                Lua.luaK_reserveregs(fs, 1);
            }
        }