Пример #1
0
        public static void StoreVar(FuncState fs, ExpDesc v, ExpDesc e)
        {
            switch (v.Kind)
            {
            case ExpKind.VLOCAL: {
                FreeExp(fs, e);
                Exp2Reg(fs, e, v.Info);
                break;
            }

            case ExpKind.VUPVAL: {
                int c = Exp2AnyReg(fs, e);
                CodeABC(fs, OpCode.OP_SETUPVAL, c, v.Info, 0);
                break;
            }

            case ExpKind.VINDEXED: {
                OpCode op = (v.Ind.Vt == ExpKind.VLOCAL)
                                                ? OpCode.OP_SETTABLE
                                                : OpCode.OP_SETTABUP;
                int c = Exp2RK(fs, e);
                CodeABC(fs, op, v.Ind.T, v.Ind.Idx, c);
                break;
            }

            default:
            {
                throw new NotImplementedException("invalid var kind to store");
            }
            }
            FreeExp(fs, e);
        }
Пример #2
0
 public static void Exp2AnyRegUp(FuncState fs, ExpDesc e)
 {
     if (e.Kind != ExpKind.VUPVAL || HasJumps(e))
     {
         Exp2AnyReg(fs, e);
     }
 }
Пример #3
0
 public static void Exp2NextReg(FuncState fs, ExpDesc e)
 {
     DischargeVars(fs, e);
     FreeExp(fs, e);
     ReserveRegs(fs, 1);
     Exp2Reg(fs, e, fs.FreeReg - 1);
 }
Пример #4
0
 private static void FreeExp(FuncState fs, ExpDesc e)
 {
     if (e.Kind == ExpKind.VNONRELOC)
     {
         FreeReg(fs, e.Info);
     }
 }
Пример #5
0
        private static void CodeArith(FuncState fs, OpCode op,
                                      ExpDesc e1, ExpDesc e2, int line)
        {
            if (ConstFolding(op, e1, e2))
            {
                return;
            }

            int o2 = (op != OpCode.OP_UNM && op != OpCode.OP_LEN)
                                ? Exp2RK(fs, e2) : 0;
            int o1 = Exp2RK(fs, e1);

            if (o1 > o2)
            {
                FreeExp(fs, e1);
                FreeExp(fs, e2);
            }
            else
            {
                FreeExp(fs, e2);
                FreeExp(fs, e1);
            }
            e1.Info = CodeABC(fs, op, 0, o1, o2);
            e1.Kind = ExpKind.VRELOCABLE;
            FixLine(fs, line);
        }
Пример #6
0
        private static void Exp2Reg(FuncState fs, ExpDesc e, int reg)
        {
            Discharge2Reg(fs, e, reg);
            if (e.Kind == ExpKind.VJMP)
            {
                e.ExitTrue = Concat(fs, e.ExitTrue, e.Info);
            }

            if (HasJumps(e))
            {
                int p_f = NO_JUMP;
                int p_t = NO_JUMP;
                if (NeedValue(fs, e.ExitTrue) || NeedValue(fs, e.ExitFalse))
                {
                    int fj = (e.Kind == ExpKind.VJMP) ? NO_JUMP : Jump(fs);
                    p_f = CodeLabel(fs, reg, 0, 1);
                    p_t = CodeLabel(fs, reg, 1, 0);
                    PatchToHere(fs, fj);
                }

                // position after whole expression
                int final = GetLabel(fs);
                PatchListAux(fs, e.ExitFalse, final, reg, p_f);
                PatchListAux(fs, e.ExitTrue, final, reg, p_t);
            }

            e.ExitFalse = NO_JUMP;
            e.ExitTrue  = NO_JUMP;
            e.Info      = reg;
            e.Kind      = ExpKind.VNONRELOC;
        }
Пример #7
0
        public static void GoIfTrue(FuncState fs, ExpDesc e)
        {
            int pc;             // pc of last jump

            DischargeVars(fs, e);
            switch (e.Kind)
            {
            case ExpKind.VJMP:
                InvertJump(fs, e);
                pc = e.Info;
                break;

            case ExpKind.VK:
            case ExpKind.VKNUM:
            case ExpKind.VTRUE:
                pc = NO_JUMP;
                break;

            default:
                pc = JumpOnCond(fs, e, false);
                break;
            }

            // insert last jump in `f' list
            e.ExitFalse = Concat(fs, e.ExitFalse, pc);
            PatchToHere(fs, e.ExitTrue);
            e.ExitTrue = NO_JUMP;
        }
Пример #8
0
        public static void GoIfFalse(FuncState fs, ExpDesc e)
        {
            int pc;             // pc of last jump

            DischargeVars(fs, e);
            switch (e.Kind)
            {
            case ExpKind.VJMP:
                pc = e.Info;
                break;

            case ExpKind.VNIL:
            case ExpKind.VFALSE:
                pc = NO_JUMP;
                break;

            default:
                pc = JumpOnCond(fs, e, true);
                break;
            }

            // insert last jump in `t' list
            e.ExitTrue = Concat(fs, e.ExitTrue, pc);
            PatchToHere(fs, e.ExitFalse);
            e.ExitFalse = NO_JUMP;
        }
Пример #9
0
        public static void DischargeVars(FuncState fs, ExpDesc e)
        {
            switch (e.Kind)
            {
            case ExpKind.VLOCAL:
                e.Kind = ExpKind.VNONRELOC;
                break;

            case ExpKind.VUPVAL:
                e.Info = CodeABC(fs, OpCode.OP_GETUPVAL, 0, e.Info, 0);
                e.Kind = ExpKind.VRELOCABLE;
                break;

            case ExpKind.VINDEXED:
                OpCode op = OpCode.OP_GETTABUP;
                FreeReg(fs, e.Ind.Idx);
                if (e.Ind.Vt == ExpKind.VLOCAL)
                {
                    FreeReg(fs, e.Ind.T);
                    op = OpCode.OP_GETTABLE;
                }
                e.Info = CodeABC(fs, op, 0, e.Ind.T, e.Ind.Idx);
                e.Kind = ExpKind.VRELOCABLE;
                break;

            case ExpKind.VVARARG:
            case ExpKind.VCALL:
                SetOneRet(fs, e);
                break;

            default: break;
            }
        }
Пример #10
0
        public static void Infix(FuncState fs, BinOpr op, ExpDesc e)
        {
            switch (op)
            {
            case BinOpr.AND: {
                GoIfTrue(fs, e);
            } break;

            case BinOpr.OR: {
                GoIfFalse(fs, e);
            } break;

            case BinOpr.CONCAT: {
                Exp2NextReg(fs, e);                           // operand must be on the `stack'
            } break;

            case BinOpr.ADD:
            case BinOpr.SUB:
            case BinOpr.MUL:
            case BinOpr.DIV:
            case BinOpr.MOD:
            case BinOpr.POW: {
                if (!IsNumeral(e))
                {
                    Exp2RK(fs, e);
                }
            } break;

            default: {
                Exp2RK(fs, e);
            } break;
            }
        }
Пример #11
0
 private static void Discharge2AnyReg(FuncState fs, ExpDesc e)
 {
     if (e.Kind != ExpKind.VNONRELOC)
     {
         ReserveRegs(fs, 1);
         Discharge2Reg(fs, e, fs.FreeReg - 1);
     }
 }
Пример #12
0
 public static void Indexed(FuncState fs, ExpDesc t, ExpDesc k)
 {
     t.Ind.T   = t.Info;
     t.Ind.Idx = Exp2RK(fs, k);
     t.Ind.Vt  = (t.Kind == ExpKind.VUPVAL) ? ExpKind.VUPVAL
                                                                                           : ExpKind.VLOCAL; // FIXME
     t.Kind = ExpKind.VINDEXED;
 }
Пример #13
0
        private static void InvertJump(FuncState fs, ExpDesc e)
        {
            InstructionPtr pc = GetJumpControl(fs, e.Info);

            Utl.Assert(TestTMode(pc.Value.GET_OPCODE()) &&
                       pc.Value.GET_OPCODE() != OpCode.OP_TESTSET &&
                       pc.Value.GET_OPCODE() != OpCode.OP_TEST);
            pc.Value = pc.Value.SETARG_A(pc.Value.GETARG_A() == 0 ? 1 : 0);
        }
Пример #14
0
        private static void Discharge2Reg(FuncState fs, ExpDesc e, int reg)
        {
            DischargeVars(fs, e);
            switch (e.Kind)
            {
            case ExpKind.VNIL:
            {
                CodeNil(fs, reg, 1);
                break;
            }

            case ExpKind.VFALSE:
            case ExpKind.VTRUE:
            {
                CodeABC(fs, OpCode.OP_LOADBOOL, reg,
                        (e.Kind == ExpKind.VTRUE ? 1 : 0), 0);
                break;
            }

            case ExpKind.VK:
            {
                CodeK(fs, reg, e.Info);
                break;
            }

            case ExpKind.VKNUM:
            {
                CodeK(fs, reg, NumberK(fs, e.NumberValue));
                break;
            }

            case ExpKind.VRELOCABLE:
            {
                InstructionPtr pi = fs.GetCode(e);
                pi.Value = pi.Value.SETARG_A(reg);
                break;
            }

            case ExpKind.VNONRELOC:
            {
                if (reg != e.Info)
                {
                    CodeABC(fs, OpCode.OP_MOVE, reg, e.Info, 0);
                }
                break;
            }

            default:
            {
                Utl.Assert(e.Kind == ExpKind.VVOID || e.Kind == ExpKind.VJMP);
                return;         // nothing to do...
            }
            }
            e.Info = reg;
            e.Kind = ExpKind.VNONRELOC;
        }
Пример #15
0
 public static void Exp2Val(FuncState fs, ExpDesc e)
 {
     if (HasJumps(e))
     {
         Exp2AnyReg(fs, e);
     }
     else
     {
         DischargeVars(fs, e);
     }
 }
Пример #16
0
        public static void Self(FuncState fs, ExpDesc e, ExpDesc key)
        {
            Exp2AnyReg(fs, e);
            int ereg = e.Info;             // register where `e' is placed

            FreeExp(fs, e);
            e.Info = fs.FreeReg;             // base register for op_self
            e.Kind = ExpKind.VNONRELOC;
            ReserveRegs(fs, 2);
            CodeABC(fs, OpCode.OP_SELF, e.Info, ereg, Coder.Exp2RK(fs, key));
            FreeExp(fs, key);
        }
Пример #17
0
 public static void SetReturns(FuncState fs, ExpDesc e, int nResults)
 {
     if (e.Kind == ExpKind.VCALL)                // expression is an open function call?
     {
         var pi = fs.GetCode(e);
         pi.Value = pi.Value.SETARG_C(nResults + 1);
     }
     else if (e.Kind == ExpKind.VVARARG)
     {
         var pi = fs.GetCode(e);
         pi.Value = pi.Value.SETARG_B(nResults + 1).SETARG_A(fs.FreeReg);
         ReserveRegs(fs, 1);
     }
 }
Пример #18
0
        private static bool ConstFolding(OpCode op, ExpDesc e1, ExpDesc e2)
        {
            if (!IsNumeral(e1) || !IsNumeral(e2))
            {
                return(false);
            }

            if ((op == OpCode.OP_DIV || op == OpCode.OP_MOD) &&
                e2.NumberValue == 0.0)
            {
                return(false);                // do not attempt to divide by 0
            }

            switch (op)
            {
            case OpCode.OP_ADD:
                e1.NumberValue = e1.NumberValue + e2.NumberValue;
                break;

            case OpCode.OP_SUB:
                e1.NumberValue = e1.NumberValue - e2.NumberValue;
                break;

            case OpCode.OP_MUL:
                e1.NumberValue = e1.NumberValue * e2.NumberValue;
                break;

            case OpCode.OP_DIV:
                e1.NumberValue = e1.NumberValue / e2.NumberValue;
                break;

            case OpCode.OP_MOD:
                e1.NumberValue = Utl.LuaMod(e1.NumberValue, e2.NumberValue);
                break;

            case OpCode.OP_POW:
                e1.NumberValue = Math.Pow(e1.NumberValue, e2.NumberValue);
                break;

            case OpCode.OP_UNM:
                e1.NumberValue = -e1.NumberValue;
                break;

            default:
                throw new Exception("ConstFolding unknown op" + op);
            }

            return(true);
        }
Пример #19
0
 public static void SetOneRet(FuncState fs, ExpDesc e)
 {
     // expression is an open function call?
     if (e.Kind == ExpKind.VCALL)
     {
         e.Kind = ExpKind.VNONRELOC;
         e.Info = (fs.GetCode(e)).Value.GETARG_A();
     }
     else if (e.Kind == ExpKind.VVARARG)
     {
         var pi = fs.GetCode(e);
         pi.Value = pi.Value.SETARG_B(2);
         e.Kind   = ExpKind.VRELOCABLE;               // can relocate its simple result
     }
 }
Пример #20
0
        public static int Exp2RK(FuncState fs, ExpDesc e)
        {
            Exp2Val(fs, e);
            switch (e.Kind)
            {
            case ExpKind.VTRUE:
            case ExpKind.VFALSE:
            case ExpKind.VNIL:
            {
                // constant fits in RK operand?
                if (fs.Proto.K.Count <= Instruction.MAXINDEXRK)
                {
                    e.Info = (e.Kind == ExpKind.VNIL) ? NilK(fs)
                                : BoolK(fs, (e.Kind == ExpKind.VTRUE));
                    e.Kind = ExpKind.VK;
                    return(Instruction.RKASK(e.Info));
                }
                else
                {
                    break;
                }
            }

            case ExpKind.VKNUM:
            case ExpKind.VK:
            {
                if (e.Kind == ExpKind.VKNUM)
                {
                    e.Info = NumberK(fs, e.NumberValue);
                    e.Kind = ExpKind.VK;
                }

                if (e.Info <= Instruction.MAXINDEXRK)
                {
                    return(Instruction.RKASK(e.Info));
                }
                else
                {
                    break;
                }
            }

            default: break;
            }

            return(Exp2AnyReg(fs, e));
        }
Пример #21
0
 private static int JumpOnCond(FuncState fs, ExpDesc e, bool cond)
 {
     if (e.Kind == ExpKind.VRELOCABLE)
     {
         Instruction ie = fs.GetCode(e).Value;
         if (ie.GET_OPCODE() == OpCode.OP_NOT)
         {
             fs.Pc--;                     // remove previous OP_NOT
             return(CondJump(fs, OpCode.OP_TEST, ie.GETARG_B(), 0,
                             (cond ? 0 : 1)));
         }
         // else go through
     }
     Discharge2AnyReg(fs, e);
     FreeExp(fs, e);
     return(CondJump(fs, OpCode.OP_TESTSET, NO_REG, e.Info,
                     (cond ? 1 : 0)));
 }
Пример #22
0
        private static void CodeComp(FuncState fs, OpCode op, int cond,
                                     ExpDesc e1, ExpDesc e2)
        {
            int o1 = Exp2RK(fs, e1);
            int o2 = Exp2RK(fs, e2);

            FreeExp(fs, e2);
            FreeExp(fs, e1);

            // exchange args to replace by `<' or `<='
            if (cond == 0 && op != OpCode.OP_EQ)
            {
                int temp;
                temp = o1; o1 = o2; o2 = temp;                 // o1 <==> o2
                cond = 1;
            }
            e1.Info = CondJump(fs, op, cond, o1, o2);
            e1.Kind = ExpKind.VJMP;
        }
Пример #23
0
        public static void Prefix(FuncState fs, UnOpr op, ExpDesc e, int line)
        {
            ExpDesc e2 = new ExpDesc();

            e2.ExitTrue    = NO_JUMP;
            e2.ExitFalse   = NO_JUMP;
            e2.Kind        = ExpKind.VKNUM;
            e2.NumberValue = 0.0;

            switch (op)
            {
            case UnOpr.MINUS:
            {
                if (IsNumeral(e))         // minus constant?
                {
                    e.NumberValue = -e.NumberValue;
                }
                else
                {
                    Exp2AnyReg(fs, e);
                    CodeArith(fs, OpCode.OP_UNM, e, e2, line);
                }
            }
            break;

            case UnOpr.NOT:
            {
                CodeNot(fs, e);
            }
            break;

            case UnOpr.LEN:
            {
                Exp2AnyReg(fs, e);         // cannot operate on constants
                CodeArith(fs, OpCode.OP_LEN, e, e2, line);
            }
            break;

            default:
                throw new Exception("[Coder]Prefix Unknown UnOpr:" + op);
            }
        }
Пример #24
0
        public static int Exp2AnyReg(FuncState fs, ExpDesc e)
        {
            DischargeVars(fs, e);
            if (e.Kind == ExpKind.VNONRELOC)
            {
                // exp is already in a register
                if (!HasJumps(e))
                {
                    return(e.Info);
                }

                // reg. is not a local?
                if (e.Info >= fs.NumActVar)
                {
                    Exp2Reg(fs, e, e.Info);
                    return(e.Info);
                }
            }
            Exp2NextReg(fs, e);               // default
            return(e.Info);
        }
Пример #25
0
        private static void CodeNot(FuncState fs, ExpDesc e)
        {
            DischargeVars(fs, e);
            switch (e.Kind)
            {
            case ExpKind.VNIL:
            case ExpKind.VFALSE:
                e.Kind = ExpKind.VTRUE;
                break;

            case ExpKind.VK:
            case ExpKind.VKNUM:
            case ExpKind.VTRUE:
                e.Kind = ExpKind.VFALSE;
                break;

            case ExpKind.VJMP:
                InvertJump(fs, e);
                break;

            case ExpKind.VRELOCABLE:
            case ExpKind.VNONRELOC:
                Discharge2AnyReg(fs, e);
                FreeExp(fs, e);
                e.Info = CodeABC(fs, OpCode.OP_NOT, 0, e.Info, 0);
                e.Kind = ExpKind.VRELOCABLE;
                break;

            default:
                throw new Exception("CodeNot unknown e.Kind:" + e.Kind);
            }

            // interchange true and false lists
            { int temp = e.ExitFalse; e.ExitFalse = e.ExitTrue; e.ExitTrue = temp; }

            RemoveValues(fs, e.ExitFalse);
            RemoveValues(fs, e.ExitTrue);
        }
Пример #26
0
		public static void DischargeVars( FuncState fs, ExpDesc e )
		{
			switch( e.Kind )
			{
				case ExpKind.VLOCAL:
					e.Kind = ExpKind.VNONRELOC;
					break;

				case ExpKind.VUPVAL:
					e.Info = CodeABC( fs, OpCode.OP_GETUPVAL, 0, e.Info, 0 );
					e.Kind = ExpKind.VRELOCABLE;
					break;

				case ExpKind.VINDEXED:
					OpCode op = OpCode.OP_GETTABUP;
					FreeReg( fs, e.Ind.Idx );
					if( e.Ind.Vt == ExpKind.VLOCAL )
					{
						FreeReg( fs, e.Ind.T );
						op = OpCode.OP_GETTABLE;
					}
					e.Info = CodeABC( fs, op, 0, e.Ind.T, e.Ind.Idx );
					e.Kind = ExpKind.VRELOCABLE;
					break;

				case ExpKind.VVARARG:
				case ExpKind.VCALL:
					SetOneRet( fs, e );
					break;

				default: break;
			}
		}
Пример #27
0
		public static void Exp2AnyRegUp( FuncState fs, ExpDesc e )
		{
			if( e.Kind != ExpKind.VUPVAL || HasJumps( e ) )
			{
				Exp2AnyReg( fs, e );
			}
		}
Пример #28
0
 public static void SetMultiRet(FuncState fs, ExpDesc e)
 {
     SetReturns(fs, e, LuaDef.LUA_MULTRET);
 }
Пример #29
0
 private static bool IsNumeral(ExpDesc e)
 {
     return(e.Kind == ExpKind.VKNUM &&
            e.ExitTrue == NO_JUMP &&
            e.ExitFalse == NO_JUMP);
 }
Пример #30
0
		private static int JumpOnCond( FuncState fs, ExpDesc e, bool cond )
		{
			// Debug.Log("--------------- 2 ----------JumpOnCond k:" + e.Kind );
			if( e.Kind == ExpKind.VRELOCABLE )
			{
				Instruction ie = fs.GetCode( e ).Value;
				if( ie.GET_OPCODE() == OpCode.OP_NOT )
				{
					fs.Pc--; // remove previous OP_NOT
					return CondJump( fs, OpCode.OP_TEST, ie.GETARG_B(), 0,
						(cond ? 0 : 1) );
				}
				// else go through
			}
			Discharge2AnyReg( fs, e );
			FreeExp( fs, e );
			return CondJump( fs, OpCode.OP_TESTSET, NO_REG, e.Info,
				(cond ? 1 : 0) );
		}
Пример #31
0
		private static void CodeArith( FuncState fs, OpCode op,
			ExpDesc e1, ExpDesc e2, int line )
		{
			if( ConstFolding( op, e1, e2 ) )
				return;

			int o2 = ( op != OpCode.OP_UNM && op != OpCode.OP_LEN )
				? Exp2RK( fs, e2 ) : 0;
			int o1 = Exp2RK( fs, e1 );
			// Debug.Log("CODE ARITH o1:" + o1 + " o2:" + o2 +
			// 	" fs.FreeReg:" + fs.FreeReg +
			// 	"\ne1.k:" + e1.Kind +
			// 	"\ne2.k:" + e2.Kind);
			if( o1 > o2 )
			{
				FreeExp( fs, e1 );
				FreeExp( fs, e2 );
			}
			else
			{
				FreeExp( fs, e2 );
				FreeExp( fs, e1 );
			}
			e1.Info = CodeABC( fs, op, 0, o1, o2 );
			e1.Kind = ExpKind.VRELOCABLE;
			FixLine( fs, line );
		}
Пример #32
0
		private static bool IsNumeral( ExpDesc e )
		{
			return e.Kind == ExpKind.VKNUM
				&& e.ExitTrue == NO_JUMP
				&& e.ExitFalse == NO_JUMP;
		}
Пример #33
0
		public static void Self( FuncState fs, ExpDesc e, ExpDesc key )
		{
			Exp2AnyReg( fs, e );
			int ereg = e.Info; // register where `e' is placed
			FreeExp( fs, e );
			e.Info = fs.FreeReg; // base register for op_self
			e.Kind = ExpKind.VNONRELOC;
			ReserveRegs( fs, 2 );
			CodeABC( fs, OpCode.OP_SELF, e.Info, ereg, Coder.Exp2RK(fs, key) );
			FreeExp( fs, key );
		}
Пример #34
0
		public static void SetOneRet( FuncState fs, ExpDesc e )
		{
			// expression is an open function call?
			if( e.Kind == ExpKind.VCALL )
			{
				e.Kind = ExpKind.VNONRELOC;
				e.Info = ( fs.GetCode( e ) ).Value.GETARG_A();
			}
			else if( e.Kind == ExpKind.VVARARG )
			{
				var pi = fs.GetCode( e );
				pi.Value = pi.Value.SETARG_B( 2 );
				e.Kind = ExpKind.VRELOCABLE; // can relocate its simple result
			}
		}
Пример #35
0
		public static void SetReturns( FuncState fs, ExpDesc e, int nResults )
		{
			if( e.Kind == ExpKind.VCALL ) { // expression is an open function call?
				var pi = fs.GetCode(e);
				pi.Value = pi.Value.SETARG_C( nResults+1 );
			}
			else if( e.Kind == ExpKind.VVARARG ) {
				var pi = fs.GetCode(e);
				pi.Value = pi.Value.SETARG_B( nResults+1 ).SETARG_A( fs.FreeReg );
				ReserveRegs( fs, 1 );
			}
		}
Пример #36
0
		// stat -> LOCAL NAME {`,' NAME} [`=' explist]
		private void LocalStat()
		{
			int nvars = 0;
			int nexps;
			var e = new ExpDesc();
			do {
				var v = NewLocalVar( CheckName() );
				ActVars.Add(v);
				++nvars;
			} while( TestNext( (int)',' ) );

			if( TestNext( (int)'=' ) )
				nexps = ExpList( e );
			else
			{
				e.Kind = ExpKind.VVOID;
				nexps = 0;
			}
			AdjustAssign( nvars, nexps, e );
			AdjustLocalVars( nvars );
		}
Пример #37
0
		public static void SetMultiRet( FuncState fs, ExpDesc e )
		{
			SetReturns( fs, e, LuaDef.LUA_MULTRET );
		}
Пример #38
0
		public static void Indexed( FuncState fs, ExpDesc t, ExpDesc k )
		{
			t.Ind.T = t.Info;
			t.Ind.Idx = Exp2RK( fs, k );
			t.Ind.Vt = (t.Kind == ExpKind.VUPVAL) ? ExpKind.VUPVAL
												  : ExpKind.VLOCAL; // FIXME
			t.Kind = ExpKind.VINDEXED;
		}
Пример #39
0
		public static void StoreVar( FuncState fs, ExpDesc v, ExpDesc e )
		{
			switch( v.Kind )
			{
				case ExpKind.VLOCAL: {
					FreeExp( fs, e );
					Exp2Reg( fs, e, v.Info );
					break;
				}

				case ExpKind.VUPVAL: {
					int c = Exp2AnyReg( fs, e );
					// Debug.Log("SETUPVAL " + c + " " + v.Info);
					CodeABC( fs, OpCode.OP_SETUPVAL, c, v.Info, 0 );
					break;
				}

				case ExpKind.VINDEXED: {
					OpCode op = (v.Ind.Vt == ExpKind.VLOCAL)
						? OpCode.OP_SETTABLE
						: OpCode.OP_SETTABUP;
					int c = Exp2RK( fs, e );
					CodeABC( fs, op, v.Ind.T, v.Ind.Idx, c );
					break;
				}

				default:
				{
					throw new NotImplementedException("invalid var kind to store");
				}
			}
			FreeExp( fs, e );
		}
Пример #40
0
		private static void Discharge2Reg( FuncState fs, ExpDesc e, int reg )
		{
			DischargeVars( fs, e );
			switch( e.Kind )
			{
				case ExpKind.VNIL: {
					CodeNil( fs, reg, 1 );
					break;
				}
				case ExpKind.VFALSE:
				case ExpKind.VTRUE: {
					CodeABC( fs, OpCode.OP_LOADBOOL, reg,
						(e.Kind == ExpKind.VTRUE ? 1 : 0), 0 );
					break;
				}
				case ExpKind.VK: {
					CodeK( fs, reg, e.Info );
					break;
				}
				case ExpKind.VKNUM: {
					CodeK( fs, reg, NumberK( fs, e.NumberValue ) );
					break;
				}
				case ExpKind.VRELOCABLE: {
					InstructionPtr pi = fs.GetCode(e);
					pi.Value = pi.Value.SETARG_A(reg);
					break;
				}
				case ExpKind.VNONRELOC: {
					if( reg != e.Info )
						CodeABC( fs, OpCode.OP_MOVE, reg, e.Info, 0 );
					break;
				}
				default: {
					Utl.Assert( e.Kind == ExpKind.VVOID || e.Kind == ExpKind.VJMP );
					return; // nothing to do...
				}
			}
			e.Info = reg;
			e.Kind = ExpKind.VNONRELOC;
		}
Пример #41
0
		private static void FreeExp( FuncState fs, ExpDesc e )
		{
			// Debug.Log("--------------- 3 ----------FreeExp k:" + e.Kind );
			if( e.Kind == ExpKind.VNONRELOC )
			{
				FreeReg( fs, e.Info );
			}
		}
Пример #42
0
		private static void Exp2Reg( FuncState fs, ExpDesc e, int reg )
		{
			Discharge2Reg( fs, e, reg );
			if( e.Kind == ExpKind.VJMP )
			{
				e.ExitTrue = Concat( fs, e.ExitTrue, e.Info );
			}

			if( HasJumps(e) )
			{
				int p_f = NO_JUMP;
				int p_t = NO_JUMP;
				if( NeedValue( fs, e.ExitTrue ) || NeedValue( fs, e.ExitFalse ) )
				{
					int fj = (e.Kind == ExpKind.VJMP) ? NO_JUMP : Jump( fs );
					p_f = CodeLabel( fs, reg, 0, 1 );
					p_t = CodeLabel( fs, reg, 1, 0 );
					PatchToHere( fs, fj );
				}

				// position after whole expression
				int final = GetLabel( fs );
				PatchListAux( fs, e.ExitFalse, final, reg, p_f );
				PatchListAux( fs, e.ExitTrue,  final, reg, p_t );
			}

			e.ExitFalse = NO_JUMP;
			e.ExitTrue  = NO_JUMP;
			e.Info = reg;
			e.Kind = ExpKind.VNONRELOC;
		}
Пример #43
0
		private static bool ConstFolding( OpCode op, ExpDesc e1, ExpDesc e2 )
		{
			if( !IsNumeral(e1) || !IsNumeral(e2) )
				return false;

			if( (op == OpCode.OP_DIV || op == OpCode.OP_MOD)
				&& e2.NumberValue == 0.0 )
			{
				return false; // do not attempt to divide by 0
			}

			switch( op )
			{
				case OpCode.OP_ADD:
					e1.NumberValue = e1.NumberValue + e2.NumberValue;
					break;
				case OpCode.OP_SUB:
					e1.NumberValue = e1.NumberValue - e2.NumberValue;
					break;
				case OpCode.OP_MUL:
					e1.NumberValue = e1.NumberValue * e2.NumberValue;
					break;
				case OpCode.OP_DIV:
					e1.NumberValue = e1.NumberValue / e2.NumberValue;
					break;
				case OpCode.OP_MOD:
					e1.NumberValue = e1.NumberValue % e2.NumberValue;
					break;
				case OpCode.OP_POW:
					e1.NumberValue = Math.Pow( e1.NumberValue, e2.NumberValue );
					break;
				case OpCode.OP_UNM:
					e1.NumberValue = -e1.NumberValue;
					break;
				default:
					throw new Exception("ConstFolding unknown op" + op);
			}

			return true;
		}
Пример #44
0
		public static void GoIfFalse( FuncState fs, ExpDesc e )
		{
			// Debug.Log("GoIfFalse k:" + e.Kind );
			int pc; // pc of last jump
			DischargeVars( fs, e );
			switch( e.Kind )
			{
				case ExpKind.VJMP:
					pc = e.Info;
					break;

				case ExpKind.VNIL:
				case ExpKind.VFALSE:
					pc = NO_JUMP;
					break;

				default:
					pc = JumpOnCond( fs, e, true );
					break;
			}

			// insert last jump in `t' list
			e.ExitTrue = Concat( fs, e.ExitTrue, pc );
			PatchToHere( fs, e.ExitFalse );
			e.ExitFalse = NO_JUMP;
		}
Пример #45
0
		private static void InvertJump( FuncState fs, ExpDesc e )
		{
			InstructionPtr pc = GetJumpControl( fs, e.Info );
			Utl.Assert( TestTMode( pc.Value.GET_OPCODE() )
				&& pc.Value.GET_OPCODE() != OpCode.OP_TESTSET
				&& pc.Value.GET_OPCODE() != OpCode.OP_TEST );
			pc.Value = pc.Value.SETARG_A( pc.Value.GETARG_A() == 0 ? 1 : 0 );
		}
Пример #46
0
		private static void CodeComp( FuncState fs, OpCode op, int cond,
			ExpDesc e1, ExpDesc e2 )
		{
			int o1 = Exp2RK( fs, e1 );
			int o2 = Exp2RK( fs, e2 );
			FreeExp( fs, e2 );
			FreeExp( fs, e1 );

			// exchange args to replace by `<' or `<='
			if( cond == 0 && op != OpCode.OP_EQ ) {
				int temp;
				temp = o1; o1 = o2; o2 = temp; // o1 <==> o2
				cond = 1;
			}
			e1.Info = CondJump( fs, op, cond, o1, o2 );
			e1.Kind = ExpKind.VJMP;
		}
Пример #47
0
		public static void GoIfTrue( FuncState fs, ExpDesc e )
		{
			// Debug.Log("--------------- 1 ----------GoIfTrue k:" + e.Kind );
			int pc; // pc of last jump
			DischargeVars( fs, e );
			switch( e.Kind )
			{
				case ExpKind.VJMP:
					InvertJump( fs, e );
					pc = e.Info;
					break;

				case ExpKind.VK:
				case ExpKind.VKNUM:
				case ExpKind.VTRUE:
					pc = NO_JUMP;
					break;

				default:
					pc = JumpOnCond( fs, e, false );
					break;
			}

			// insert last jump in `f' list
			e.ExitFalse = Concat( fs, e.ExitFalse, pc );
			PatchToHere( fs, e.ExitTrue );
			e.ExitTrue = NO_JUMP;
		}
Пример #48
0
		public static void Infix( FuncState fs, BinOpr op, ExpDesc e )
		{
			// Debug.Log(">> INFIX op:" + op);
			switch( op )
			{
				case BinOpr.AND: {
					GoIfTrue( fs, e );
				} break;

				case BinOpr.OR: {
					GoIfFalse( fs, e );
				} break;

				case BinOpr.CONCAT: {
					Exp2NextReg( fs, e ); // operand must be on the `stack'
				} break;

				case BinOpr.ADD:
				case BinOpr.SUB:
				case BinOpr.MUL:
				case BinOpr.DIV:
				case BinOpr.MOD:
				case BinOpr.POW: {
					if( !IsNumeral(e) )
						Exp2RK( fs, e );
				} break;

				default: {
					Exp2RK( fs, e );
				} break;
			}
		}
Пример #49
0
		private static void CodeNot( FuncState fs, ExpDesc e )
		{
			DischargeVars( fs, e );
			switch( e.Kind )
			{
				case ExpKind.VNIL:
				case ExpKind.VFALSE:
					e.Kind = ExpKind.VTRUE;
					break;

				case ExpKind.VK:
				case ExpKind.VKNUM:
				case ExpKind.VTRUE:
					e.Kind = ExpKind.VFALSE;
					break;

				case ExpKind.VJMP:
					InvertJump( fs, e );
					break;

				case ExpKind.VRELOCABLE:
				case ExpKind.VNONRELOC:
					Discharge2AnyReg( fs, e );
					FreeExp( fs, e );
					e.Info = CodeABC( fs, OpCode.OP_NOT, 0, e.Info, 0 );
					e.Kind = ExpKind.VRELOCABLE;
					break;

				default:
					throw new Exception("CodeNot unknown e.Kind:" + e.Kind);
			}

			// interchange true and false lists
			{ int temp = e.ExitFalse; e.ExitFalse = e.ExitTrue; e.ExitTrue = temp; }

			RemoveValues( fs, e.ExitFalse );
			RemoveValues( fs, e.ExitTrue  );
		}
Пример #50
0
		public static void Exp2Val( FuncState fs, ExpDesc e )
		{
			if( HasJumps(e) )
				Exp2AnyReg( fs, e );
			else
				DischargeVars( fs, e );
		}
Пример #51
0
		public static void Prefix( FuncState fs, UnOpr op, ExpDesc e, int line )
		{
			ExpDesc e2 = new ExpDesc();
			e2.ExitTrue = NO_JUMP;
			e2.ExitFalse = NO_JUMP;
			e2.Kind = ExpKind.VKNUM;
			e2.NumberValue = 0.0;

			switch( op )
			{
				case UnOpr.MINUS: {
					if( IsNumeral( e ) ) // minus constant?
					{
						e.NumberValue = -e.NumberValue;
					}
					else
					{
						Exp2AnyReg( fs, e );
						CodeArith( fs, OpCode.OP_UNM, e, e2, line );
					}
				} break;

				case UnOpr.NOT: {
					CodeNot( fs, e );
				} break;

				case UnOpr.LEN: {
					Exp2AnyReg( fs, e ); // cannot operate on constants
					CodeArith( fs, OpCode.OP_LEN, e, e2, line );
				} break;

				default:
					throw new Exception("[Coder]Prefix Unknown UnOpr:" + op);
			}
		}
Пример #52
0
		public static int Exp2RK( FuncState fs, ExpDesc e )
		{
			Exp2Val( fs, e );
			switch( e.Kind )
			{
				case ExpKind.VTRUE:
				case ExpKind.VFALSE:
				case ExpKind.VNIL: {
					// constant fits in RK operand?
					if( fs.Proto.K.Count <= Instruction.MAXINDEXRK )
					{
						e.Info = (e.Kind == ExpKind.VNIL) ? NilK(fs)
							: BoolK( fs, (e.Kind == ExpKind.VTRUE ) );
						e.Kind = ExpKind.VK;
						return Instruction.RKASK( e.Info );
					}
					else break;
				}
				case ExpKind.VKNUM:
				case ExpKind.VK:
				{
					if( e.Kind == ExpKind.VKNUM )
					{
						e.Info = NumberK( fs, e.NumberValue );
						e.Kind = ExpKind.VK;
					}

					if( e.Info <= Instruction.MAXINDEXRK )
						return Instruction.RKASK( e.Info );
					else break;
				}

				default: break;
			}

			return Exp2AnyReg( fs, e );
		}
Пример #53
0
		public static void Posfix( FuncState fs, BinOpr op,
			ExpDesc e1, ExpDesc e2, int line )
		{
			// Debug.Log(">> POSFIX op:" + op);
			switch( op )
			{
				case BinOpr.AND: {
					Utl.Assert( e1.ExitTrue == NO_JUMP );
					DischargeVars( fs, e2 );
					e2.ExitFalse = Concat( fs, e2.ExitFalse, e1.ExitFalse );
					e1.CopyFrom( e2 );
					break;
				}
				case BinOpr.OR: {
					Utl.Assert( e1.ExitFalse == NO_JUMP );
					DischargeVars( fs, e2 );
					e2.ExitTrue = Concat( fs, e2.ExitTrue, e1.ExitTrue );
					e1.CopyFrom( e2 );
					break;
				}
				case BinOpr.CONCAT: {
					Exp2Val( fs, e2 );
					var pe2 = fs.GetCode( e2 );
					if( e2.Kind == ExpKind.VRELOCABLE &&
						pe2.Value.GET_OPCODE() == OpCode.OP_CONCAT )
					{
						Utl.Assert( e1.Info == pe2.Value.GETARG_B()-1 );
						FreeExp( fs, e1 );
						pe2.Value = pe2.Value.SETARG_B( e1.Info );
						e1.Kind = ExpKind.VRELOCABLE;
						e1.Info = e2.Info;
					}
					else
					{
						// operand must be on the `stack'
						Exp2NextReg( fs, e2 );
						CodeArith( fs, OpCode.OP_CONCAT, e1, e2, line );
					}
					break;
				}
				case BinOpr.ADD: {
					CodeArith( fs, OpCode.OP_ADD, e1, e2, line);
					break;
				}
				case BinOpr.SUB: {
					CodeArith( fs, OpCode.OP_SUB, e1, e2, line);
					break;
				}
				case BinOpr.MUL: {
					CodeArith( fs, OpCode.OP_MUL, e1, e2, line);
					break;
				}
				case BinOpr.DIV: {
					CodeArith( fs, OpCode.OP_DIV, e1, e2, line);
					break;
				}
				case BinOpr.MOD: {
					CodeArith( fs, OpCode.OP_MOD, e1, e2, line);
					break;
				}
				case BinOpr.POW: {
					CodeArith( fs, OpCode.OP_POW, e1, e2, line);
					break;
				}
				case BinOpr.EQ: {
					CodeComp( fs, OpCode.OP_EQ, 1, e1, e2 );
					break;
				}
				case BinOpr.LT: {
					CodeComp( fs, OpCode.OP_LT, 1, e1, e2 );
					break;
				}
				case BinOpr.LE: {
					CodeComp( fs, OpCode.OP_LE, 1, e1, e2 );
					break;
				}
				case BinOpr.NE: {
					CodeComp( fs, OpCode.OP_EQ, 0, e1, e2 );
					break;
				}
				case BinOpr.GT: {
					CodeComp( fs, OpCode.OP_LT, 0, e1, e2 );
					break;
				}
				case BinOpr.GE: {
					CodeComp( fs, OpCode.OP_LE, 0, e1, e2 );
					break;
				}
				default: Utl.Assert(false); break;
			}
		}
Пример #54
0
		public static int Exp2AnyReg( FuncState fs, ExpDesc e )
		{
			// Debug.Log("Exp2AnyReg k:" + e.Kind +
			// 	" hasjump:" + HasJumps(e) +
			// 	" info:" + e.Info +
			// 	" nactvar:" + fs.NumActVar);
			DischargeVars( fs, e );
			if( e.Kind == ExpKind.VNONRELOC )
			{
				// exp is already in a register
				if( ! HasJumps( e ) )
					return e.Info;

				// reg. is not a local?
				if( e.Info >= fs.NumActVar )
				{
					Exp2Reg( fs, e, e.Info );
					return e.Info;
				}
			}
			Exp2NextReg( fs, e ); // default
			return e.Info;
		}
Пример #55
0
		private static bool HasJumps( ExpDesc e )
		{
			return e.ExitTrue != e.ExitFalse;
		}
Пример #56
0
        public static void Posfix(FuncState fs, BinOpr op,
                                  ExpDesc e1, ExpDesc e2, int line)
        {
            switch (op)
            {
            case BinOpr.AND: {
                Utl.Assert(e1.ExitTrue == NO_JUMP);
                DischargeVars(fs, e2);
                e2.ExitFalse = Concat(fs, e2.ExitFalse, e1.ExitFalse);
                e1.CopyFrom(e2);
                break;
            }

            case BinOpr.OR: {
                Utl.Assert(e1.ExitFalse == NO_JUMP);
                DischargeVars(fs, e2);
                e2.ExitTrue = Concat(fs, e2.ExitTrue, e1.ExitTrue);
                e1.CopyFrom(e2);
                break;
            }

            case BinOpr.CONCAT: {
                Exp2Val(fs, e2);
                var pe2 = fs.GetCode(e2);
                if (e2.Kind == ExpKind.VRELOCABLE &&
                    pe2.Value.GET_OPCODE() == OpCode.OP_CONCAT)
                {
                    Utl.Assert(e1.Info == pe2.Value.GETARG_B() - 1);
                    FreeExp(fs, e1);
                    pe2.Value = pe2.Value.SETARG_B(e1.Info);
                    e1.Kind   = ExpKind.VRELOCABLE;
                    e1.Info   = e2.Info;
                }
                else
                {
                    // operand must be on the `stack'
                    Exp2NextReg(fs, e2);
                    CodeArith(fs, OpCode.OP_CONCAT, e1, e2, line);
                }
                break;
            }

            case BinOpr.ADD: {
                CodeArith(fs, OpCode.OP_ADD, e1, e2, line);
                break;
            }

            case BinOpr.SUB: {
                CodeArith(fs, OpCode.OP_SUB, e1, e2, line);
                break;
            }

            case BinOpr.MUL: {
                CodeArith(fs, OpCode.OP_MUL, e1, e2, line);
                break;
            }

            case BinOpr.DIV: {
                CodeArith(fs, OpCode.OP_DIV, e1, e2, line);
                break;
            }

            case BinOpr.MOD: {
                CodeArith(fs, OpCode.OP_MOD, e1, e2, line);
                break;
            }

            case BinOpr.POW: {
                CodeArith(fs, OpCode.OP_POW, e1, e2, line);
                break;
            }

            case BinOpr.EQ: {
                CodeComp(fs, OpCode.OP_EQ, 1, e1, e2);
                break;
            }

            case BinOpr.LT: {
                CodeComp(fs, OpCode.OP_LT, 1, e1, e2);
                break;
            }

            case BinOpr.LE: {
                CodeComp(fs, OpCode.OP_LE, 1, e1, e2);
                break;
            }

            case BinOpr.NE: {
                CodeComp(fs, OpCode.OP_EQ, 0, e1, e2);
                break;
            }

            case BinOpr.GT: {
                CodeComp(fs, OpCode.OP_LT, 0, e1, e2);
                break;
            }

            case BinOpr.GE: {
                CodeComp(fs, OpCode.OP_LE, 0, e1, e2);
                break;
            }

            default:
                throw new NotImplementedException(string.Format("opcode {0}({1}, {2}) @line:{3}", op, e1, e2, line));
            }
        }
Пример #57
0
		private static void Discharge2AnyReg( FuncState fs, ExpDesc e )
		{
			if( e.Kind != ExpKind.VNONRELOC )
			{
				ReserveRegs( fs, 1 );
				Discharge2Reg( fs, e, fs.FreeReg-1 );
			}
		}
Пример #58
0
 private static bool HasJumps(ExpDesc e)
 {
     return(e.ExitTrue != e.ExitFalse);
 }
Пример #59
0
		public static void Exp2NextReg( FuncState fs, ExpDesc e )
		{
			DischargeVars( fs, e );
			FreeExp( fs, e );
			ReserveRegs( fs, 1 );
			Exp2Reg( fs, e, fs.FreeReg-1 );
		}
Пример #60
0
 public Pointer <Instruction> GetCode(ExpDesc e)
 {
     return(new Pointer <Instruction>(Proto.Code, e.Info));
 }