Пример #1
0
        public LuaFile Compile(Ast.Chunk c, string name)
        {
            file = new LuaFile();
            block = new Block();
            block.Chunk.Name = name;
            block.Chunk.ArgumentCount = 0;
            block.Chunk.Vararg = 2;

            DoChunk(c);

            file.Main = block.Chunk;
            file.Main.ArgumentCount = 0;
            file.Main.Vararg = 2;
            file.Main.UpvalueCount = file.Main.Upvalues.Count;
            bool addRet = file.Main.Instructions.Count == 0;
            if (addRet == false)
                addRet = file.Main.Instructions[file.Main.Instructions.Count - 1].Opcode != Instruction.LuaOpcode.RETURN;
            if (addRet)
            {
                Instruction ret = new Instruction("RETURN");
                ret.A = 0;
                ret.B = 1;
                ret.C = 0;
                file.Main.Instructions.Add(ret);
            }
            return file;
        }
Пример #2
0
 public static Instruction From(uint binary)
 {
     int opcode = (int)Lua.GET_OPCODE(binary);
     //(int)Bit.Get(op, 1, 6);
     Instruction instr = new Instruction(opcode, 0);
     if (instr.OpcodeType == OpcodeType.ABC)
     {
         instr.A = Lua.GETARG_A(binary);
         instr.B = Lua.GETARG_B(binary);
         instr.C = Lua.GETARG_C(binary);
         //instr.A = Bit.Get(op, 7, 14);
         //instr.B = Bit.Get(op, 24, 32);
         //instr.C = Bit.Get(op, 15, 23);
     }
     else if (instr.OpcodeType == OpcodeType.ABx)
     {
         instr.A = Lua.GETARG_A(binary);
         instr.Bx = Lua.GETARG_Bx(binary);
         //instr.A = Bit.Get(op, 7, 14);
         //instr.Bx = Bit.Get(op, 15, 32);
     }
     else if (instr.OpcodeType == OpcodeType.AsBx)
     {
         instr.A = Lua.GETARG_A(binary);
         instr.sBx = Lua.GETARG_sBx(binary);
         //instr.A = Bit.Get(op, 7, 14);
         //instr.sBx = Bit.Get(op, 15, 32) - 131071;
     }
     return instr;
 }
Пример #3
0
        void unOp(string opname, Expression expr)
        {
            // this and the variable reg2 are saved so that we can use the locations in
            // args B and C to the opcode
            int reg1 = block.regnum;
            DoExpr(expr);
            Instruction i = new Instruction(opname);

            // We no longer need reg1 through the top, so we can overwrite them
            block.regnum = reg1;

            i.A = block.getreg();

            // >256 is const

            i.B = reg1;
            emit(i);
        }
Пример #4
0
 void emit(Instruction i)
 {
     block.Chunk.Instructions.Add(i);
 }
Пример #5
0
        void binOp(string opname, Expression left, Expression right)
        {
            // this and the variable reg2 are saved so that we can use the locations in
            // args B and C to the opcode

            int reg1, reg2;

            double result;
            if (constfolding(left, right, opname, out result) == false)
            {
                if (left is NumberExpr == false)
                {
                    reg1 = block.regnum;
                    DoExpr(left);
                }
                else
                    reg1 = 256 + block.K[number(((NumberExpr)left).Value)];
                if (right is NumberExpr == false)
                {
                    reg2 = block.regnum;
                    DoExpr(right);
                }
                else
                    reg2 = 256 + block.K[number(((NumberExpr)right).Value)];
            }
            else
            {
                DoExpr(new NumberExpr() { Value = result.ToString() });
                return;
            }

            Instruction i = new Instruction(opname);
            // We no longer need reg1 through the top, so we can overwrite them
            block.regnum = reg1;

            i.A = block.getreg();

            // >256 is const

            i.B = reg1;
            i.C = reg2;
            emit(i);
        }
Пример #6
0
        void DoStatement(Statement s)
        {
            line = s.LineNumber;
            if (s is AssignmentStatement && !(s is AugmentedAssignmentStatement))
            {
                AssignmentStatement a = s as AssignmentStatement;
                if (a.IsLocal == false)
                {

                    for (int i = a.Rhs.Count; i > 0; i--)
                        DoExpr(a.Rhs[i - 1], false, a.Lhs.Count);

                    for (int i = a.Lhs.Count; i > 0; i--)
                        DoExpr(a.Lhs[i - 1], true);

                    return;
                }
                else
                {
                    for (int i = a.Rhs.Count; i > 0; i--)
                        DoExpr(a.Rhs[i - 1], false, a.Lhs.Count);

                    for (int i = a.Lhs.Count; i > 0; i--)
                        DoExpr(a.Lhs[i - 1], true);

                    return;
                }
            }
            else if (s is AugmentedAssignmentStatement)
            {
                AugmentedAssignmentStatement aas = s as AugmentedAssignmentStatement;
                StringBuilder sb = new StringBuilder();
                //sb.Append(DoExpr(a.Lhs[0]));
                if (aas.IsLocal)
                    throw new LuaSourceException(s.LineNumber, 0, "Local assignment cannot have augmented operators");

                DoExpr(aas.Rhs[0], true, 1);
                DoExpr(aas.Lhs[0], true, 1);
                return;
            }
            else if (s is BreakStatement)
            {
                bool hadLoop = false;
                while (block != null)
                {
                    if (block.IsLoop)
                    {
                        hadLoop = true;
                        break;
                    }
                    block = block.PreviousBlock;
                }
                if (!hadLoop)
                    throw new LuaSourceException(s.LineNumber, 0, "No loop to break");

                Instruction i = new Instruction("JMP");
                i.A = 0;
                i.sBx = -1; // Infinite loop ;)
                emit(i);
                patchSbx.Push(i);
                return;
            }
            else if (s is ContinueStatement)
            {
            }
            else if (s is CallStatement)
            {
                CallStatement cs = s as CallStatement;
                DoExpr(cs.Expression);
                return;
            }
            else if (s is DoStatement)
            {
            }
            else if (s is GenericForStatement)
            {
            }
            else if (s is NumericForStatement)
            {
            }
            else if (s is FunctionStatement)
            {

            }
            else if (s is GotoStatement)
                ;
            else if (s is IfStmt)
            {
            }
            else if (s is LabelStatement)
                ;
            else if (s is RepeatStatement)
            {
            }
            else if (s is ReturnStatement)
            {
            }
            else if (s is UsingStatement)
            {
            }
            else if (s is WhileStatement)
            {
                WhileStatement ws = s as WhileStatement;

                int start = block.Chunk.Instructions.Count;

                DoExpr(ws.Condition);

                Instruction t = new Instruction("TEST");
                t.A = block.regnum;
                t.C = 0;
                emit(t);

                DoChunk(ws.Body, true);

                Instruction i = new Instruction("JMP");
                i.A = 0;
                i.sBx = -(block.Chunk.Instructions.Count - start) - 1;
                emit(i);

                while (patchSbx.Count > 0)
                    patchSbx.Pop().sBx = Math.Abs(block.Chunk.Instructions.Count + i.sBx - 1);

                //return;
            }

            throw new NotImplementedException(s.GetType().Name + " is not implemented");
        }
Пример #7
0
        void DoExpr(Expression e, bool setVar = false, int setVarLhsCount = -1, bool onlyCheckConsts = false)
        {
            if (e is AnonymousFunctionExpr) // function() ... end
            {
            }
            else if (e is BinOpExpr)
            {
                BinOpExpr boe = e as BinOpExpr;
                switch (boe.GetOperator())
                {
                    case BinaryOperator.Add:
                        binOp("ADD", boe.Lhs, boe.Rhs);
                        return;
                    case BinaryOperator.Subtract:
                        binOp("SUB", boe.Lhs, boe.Rhs);
                        return;
                    case BinaryOperator.Multiply:
                        binOp("MUL", boe.Lhs, boe.Rhs);
                        return;
                    case BinaryOperator.Divide:
                        binOp("DIV", boe.Lhs, boe.Rhs);
                        return;
                    case BinaryOperator.Power:
                        binOp("POW", boe.Lhs, boe.Rhs);
                        return;
                    case BinaryOperator.Modulus:
                        binOp("MOD", boe.Lhs, boe.Rhs);
                        return;
                    case BinaryOperator.Concat:
                        binOp("CONCAT", boe.Lhs, boe.Rhs);
                        return;
                    case BinaryOperator.And:
                        break;
                    case BinaryOperator.Or:
                        break;
                    case BinaryOperator.LessThan:
                        break;
                    case BinaryOperator.LessThanOrEqualTo:
                        break;
                    case BinaryOperator.GreaterThan:
                        break;
                    case BinaryOperator.GreaterThanOrEqualTo:
                        break;
                    case BinaryOperator.NotEqual:
                        break;
                    case BinaryOperator.ShiftRight:
                        CallExpr ce = new CallExpr();
                        ce.Arguments.Add(boe.Lhs);
                        ce.Arguments.Add(boe.Rhs);
                        ce.Base = new MemberExpr()
                        {
                            Base = new VariableExpression() { Var = new Variable() { Name = "bit", IsGlobal = true } },
                            Ident = "rshift",
                            Indexer = ".",
                        };
                        DoExpr(ce);
                        return;
                    case BinaryOperator.ShiftLeft:
                        ce = new CallExpr();
                        ce.Arguments.Add(boe.Lhs);
                        ce.Arguments.Add(boe.Rhs);
                        ce.Base = new MemberExpr()
                        {
                            Base = new VariableExpression() { Var = new Variable() { Name = "bit", IsGlobal = true } },
                            Ident = "lshift",
                            Indexer = ".",
                        };
                        DoExpr(ce);
                        return;
                    case BinaryOperator.Xor:
                        ce = new CallExpr();
                        ce.Arguments.Add(boe.Lhs);
                        ce.Arguments.Add(boe.Rhs);
                        ce.Base = new MemberExpr()
                        {
                            Base = new VariableExpression() { Var = new Variable() { Name = "bit", IsGlobal = true } },
                            Ident = "bxor",
                            Indexer = ".",
                        };
                        DoExpr(ce);
                        return;
                    case BinaryOperator.BitAnd:
                        ce = new CallExpr();
                        ce.Arguments.Add(boe.Lhs);
                        ce.Arguments.Add(boe.Rhs);
                        ce.Base = new MemberExpr()
                        {
                            Base = new VariableExpression() { Var = new Variable() { Name = "bit", IsGlobal = true } },
                            Ident = "band",
                            Indexer = ".",
                        };
                        DoExpr(ce);
                        return;
                    case BinaryOperator.BitOr:
                        ce = new CallExpr();
                        ce.Arguments.Add(boe.Lhs);
                        ce.Arguments.Add(boe.Rhs);
                        ce.Base = new MemberExpr()
                        {
                            Base = new VariableExpression() { Var = new Variable() { Name = "bit", IsGlobal = true } },
                            Ident = "bor",
                            Indexer = ".",
                        };
                        DoExpr(ce);
                        return;
                    case BinaryOperator.BitNot:
                        ce = new CallExpr();
                        ce.Arguments.Add(boe.Lhs);
                        ce.Arguments.Add(boe.Rhs);
                        ce.Base = new MemberExpr()
                        {
                            Base = new VariableExpression() { Var = new Variable() { Name = "bit", IsGlobal = true } },
                            Ident = "bnot",
                            Indexer = ".",
                        };
                        DoExpr(ce);
                        return;
                    case BinaryOperator.NONE:
                    default:
                        throw new Exception("Unknown binary operator '" + boe.Op + "'");
                }
            }
            else if (e is BoolExpr)
            {
                bool v = ((BoolExpr)e).Value;
                Instruction i = new Instruction("LOADBOOL");
                i.A = block.getreg();
                i.B = v ? 1 : 0;
                i.C = 0;
                emit(i);
                return;
            }
            else if (e is CallExpr)//&& (!(e is StringCallExpr) && !(e is TableCallExpr)))
            {
                CallExpr ce = e as CallExpr;
                int breg = ++block.regnum;
                DoExpr(ce.Base);
                bool isZero = false;
                bool isMethod = false;
                Expression ex = ce.Base;
                while (ex != null)
                {
                    if (ex is IndexExpr)
                        ex = ((IndexExpr)ex).Index;
                    else if (ex is MemberExpr)
                    {
                        MemberExpr me = ex as MemberExpr;
                        if (me.Indexer == ":")
                        {
                            isMethod = true;
                            break;
                        }
                        else
                            break;
                        //ex = me.Ident;
                    }
                    else
                        break;
                }

                foreach (Expression e2 in ce.Arguments)
                {
                    DoExpr(e2);
                    if (e2 is CallExpr || block.Chunk.Instructions[block.Chunk.Instructions.Count - 1].Opcode == Instruction.LuaOpcode.CALL)
                    {
                        isZero = true;
                        Instruction i_ = block.Chunk.Instructions[block.Chunk.Instructions.Count - 1];
                        Debug.Assert(i_.Opcode == Instruction.LuaOpcode.CALL);
                        i_.C = 0;
                    }
                }

                Instruction i = new Instruction("CALL");
                i.A = breg;
                if (isMethod)
                    //i.B++;
                    i.B = isZero ? 2 : (ce.Arguments.Count > 0 ? 2 + ce.Arguments.Count : 2);
                else
                    i.B = isZero ? 0 : (ce.Arguments.Count > 0 ? 1 + ce.Arguments.Count : 1);

                i.C = setVarLhsCount == 0 || setVarLhsCount == -1 ?
                    1 : //(isZero ? 0 : 1) :
                    1 + setVarLhsCount; // (isZero ? 0 : 1 + setVarLhsCount);
                //i.C = setVarLhsCount == 0 || setVarLhsCount == -1 ? 1 : 1 + setVarLhsCount;
                emit(i);
                return;
            }
            else if (e is StringCallExpr)
            {
                throw new Exception();
            }
            else if (e is TableCallExpr)
            {
                throw new Exception();
            }
            else if (e is IndexExpr)
            {
                IndexExpr ie = e as IndexExpr;
                int regnum = block.regnum;
                DoExpr(ie.Base);
                DoExpr(ie.Index);
                Instruction i = new Instruction("GETTABLE");
                i.A = regnum;
                i.B = regnum;
                i.C = block.regnum - 1;// block.getreg();
                emit(i);
                block.regnum = regnum + 1;
                return;
            }
            else if (e is InlineFunctionExpression) // |<args>| -> <exprs>
            {
                InlineFunctionExpression i = e as InlineFunctionExpression;
                AnonymousFunctionExpr af = new AnonymousFunctionExpr();
                af.Arguments = i.Arguments;
                af.IsVararg = i.IsVararg;
                af.Body = new List<Statement>()
                {
                    new ReturnStatement
                    {
                        Arguments = i.Expressions
                    }
                };
                DoExpr(af);
            }
            else if (e is MemberExpr)
            {
                MemberExpr me = e as MemberExpr;
                if (me.Indexer == ".")
                {
                    int regnum = block.regnum;
                    DoExpr(me.Base);
                    DoExpr(new StringExpr(me.Ident), false, -1, true);
                    Instruction i = new Instruction("GETTABLE");
                    i.A = regnum;
                    i.B = regnum;
                    i.C = 256 + block.K[me.Ident];
                    //i.C = block.regnum - 1;// block.getreg();
                    emit(i);
                    block.regnum = regnum + 1;
                    return;
                }
                else if (me.Indexer == ":")
                {
                    int regnum = block.regnum;
                    DoExpr(me.Base);
                    DoExpr(new StringExpr(me.Ident), false, -1, true);
                    Instruction i = new Instruction("SELF");
                    i.A = regnum;
                    i.B = regnum;
                    i.C = 256 + block.K[me.Ident];
                    //i.C = block.regnum - 1;// block.getreg();
                    emit(i);
                    block.regnum = regnum + 1;
                    return;

                }
                else
                    throw new Exception("Unknown member indexer '" + me.Indexer + "'");
            }
            else if (e is NilExpr)
            {
                Instruction i = new Instruction("LOADNIL");
                i.A = block.getreg();
                i.B = setVarLhsCount == -1 ? i.A : setVarLhsCount - 1;
                i.C = 0;
                emit(i);
                return;
            }
            else if (e is NumberExpr)
            {
                NumberExpr ne = e as NumberExpr;

                // TODO: this can optimized into a Dictionary to avoid re-parsing numbers each time
                double r;
                int x = Lua.luaO_str2d(ne.Value.Replace("_", ""), out r);
                if (x == 0)
                    throw new LuaSourceException(line, 0, "Invalid number");

                if (onlyCheckConsts == false)
                {
                    Instruction i = new Instruction("loadk");
                    i.A = block.getreg();
                    i.Bx = block.K[r];
                    emit(i);
                }
                else
                    block.K.Check(r);
                return;
            }
            else if (e is StringExpr)
            {

                StringExpr se = e as StringExpr;
                string s = se.Value;
                if (se.StringType != TokenType.LongString)
                    s = Unescaper.Unescape(s);
                else
                {
                    int i = 1;
                    while (s[i] != '[')
                        i++;
                    i++;
                    s = s.Substring(i, s.Length - i - 2);
                }

                if (onlyCheckConsts == false)
                {
                    Instruction i2 = new Instruction("loadk");
                    i2.A = block.getreg();
                    i2.Bx = block.K[s];
                    emit(i2);
                }
                else
                    block.K.Check(s);
                return;
            }
            else if (e is TableConstructorExpr)
            {
                Instruction i = new Instruction("NEWTABLE");
                int tblA = block.regnum;
                i.A = block.getreg();
                i.B = 0;
                i.C = 0;
                emit(i);

                TableConstructorExpr tce = e as TableConstructorExpr;
                if (tce.EntryList.Count == 0)
                    return;

                int b = 0;
                bool wasLastCall = false;
                foreach (Expression e2 in tce.EntryList)
                {
                    if (e2 is TableConstructorKeyExpr)
                    {
                        TableConstructorKeyExpr tcke = e2 as TableConstructorKeyExpr;
                        DoExpr(tcke.Key);
                        DoExpr(tcke.Value);
                    }
                    else if (e2 is TableConstructorNamedFunctionExpr)
                    {
                        TableConstructorNamedFunctionExpr tcnfe = e2 as TableConstructorNamedFunctionExpr;
                    }
                    else if (e2 is TableConstructorStringKeyExpr)
                    {
                        TableConstructorStringKeyExpr tcske = e2 as TableConstructorStringKeyExpr;
                        DoExpr(new StringExpr(tcske.Key));
                        DoExpr(tcske.Value);
                    }
                    else if (e2 is TableConstructorValueExpr)
                    {
                        TableConstructorValueExpr tcve = e2 as TableConstructorValueExpr;
                        DoExpr(tcve.Value);
                        if (tcve.Value is VarargExpr || tcve.Value is CallExpr)
                            wasLastCall = true;
                        else
                            wasLastCall = false;
                    }

                    b++;
                }

                i.B = b;

                i = new Instruction("SETLIST");
                i.A = tblA;
                if (wasLastCall)
                    i.B = 0;
                else
                    i.B = block.regnum - 1;
                i.C = tblA + 1;
                emit(i);
                block.regnum = tblA;
                return;
            }
            else if (e is UnOpExpr)
            {
                UnOpExpr uoe = e as UnOpExpr;
                switch (uoe.GetOperator())
                {
                    case UnaryOperator.Not:
                        unOp("NOT", uoe.Rhs);
                        return;
                    case UnaryOperator.Length:
                        unOp("LEN", uoe.Rhs);
                        return;
                    case UnaryOperator.BitNot:
                        CallExpr ce = new CallExpr();
                        ce.Arguments.Add(uoe.Rhs);
                        ce.Base = new MemberExpr()
                        {
                            Base = new VariableExpression() { Var = new Variable() { Name = "bit", IsGlobal = true } },
                            Ident = "bnot",
                            Indexer = ".",
                        };
                        DoExpr(ce);
                        return;
                    case UnaryOperator.Negate:
                        unOp("UNM", uoe.Rhs);
                        return;
                    case UnaryOperator.UnNegate:
                        ce = new CallExpr();
                        ce.Arguments.Add(uoe.Rhs);
                        ce.Base = new MemberExpr()
                        {
                            Base = new VariableExpression() { Var = new Variable() { Name = "math", IsGlobal = true } },
                            Ident = "abs",
                            Indexer = ".",
                        };
                        DoExpr(ce);
                        return;
                    case UnaryOperator.NONE:
                    default:
                        throw new Exception("Unknown unary operator '" + uoe.Op + "'");
                }
            }
            else if (e is VarargExpr)
            {
                if (block.Chunk.Vararg == 0)
                    throw new LuaSourceException(0, 0, "Cannot use varargs (...) outside of a vararg function");
                Instruction i = new Instruction("VARARG");
                i.A = block.getreg();
                if (setVar)
                {
                    i.B = setVarLhsCount == -1 ? 0 : 1 + setVarLhsCount;
                }
                else
                {
                    i.B = 0;
                }
                emit(i);
                return;
            }
            else if (e is VariableExpression)
            {
                VariableExpression ve = e as VariableExpression;
                if (ve.Var.IsGlobal == false)
                { // local
                    if (setVar)
                    {
                        //Instruction i = new Instruction("move");
                        //i.B = block.V[ve.Var.Name]; // moved into here
                        //i.A = block.getreg(); // from here
                        //emit(i);

                        int _TMP_001_ = block.V[ve.Var.Name]; // Should probably just add a Check method in Var2Reg
                        block.CheckLocalName(ve.Var.Name);
                    }
                    else
                    {
                        Instruction i = new Instruction("move");
                        i.B = block.V[ve.Var.Name]; // moved into here
                        i.A = block.getreg(); // from here
                        emit(i);
                    }
                }
                else
                { // global
                    Instruction i = null;
                    if (setVar)
                    {
                        i = new Instruction("setglobal");
                        i.A = block.regnum - 1; // ret
                    }
                    else
                    {
                        i = new Instruction("getglobal");
                        i.A = block.getreg(); // ret
                    }

                    i.Bx = block.K[ve.Var.Name]; // const
                    emit(i);
                }
                return;
            }

            throw new NotImplementedException(e.GetType().Name + " is not implemented");
        }
Пример #8
0
 bool constfolding(Expression a, Expression b, string opcode1, out double ret)
 {
     ret = 0;
     if (a is NumberExpr == false || b is NumberExpr == false)
         return false;
     double l = number(((NumberExpr)a).Value);
     double r = number(((NumberExpr)b).Value);
     Instruction opcode = new Instruction(opcode1);
     switch (opcode.Opcode)
     {
         case Instruction.LuaOpcode.ADD:
             ret = l + r;
             return true;
         case Instruction.LuaOpcode.SUB:
             ret = l - r;
             return true;
             break;
         case Instruction.LuaOpcode.MUL:
             ret = l * r;
             return true;
         case Instruction.LuaOpcode.DIV:
             if (l == 0 || r == 0)
                 return false;
             ret = l / r;
             return true;
         case Instruction.LuaOpcode.MOD:
             if (l == 0 || r == 0)
                 return false;
             ret = l % r;
             return true;
         case Instruction.LuaOpcode.POW:
             if (l == 0 || r == 0)
                 return false;
             ret = System.Math.Pow(l, r);
             return true;
         case Instruction.LuaOpcode.CONCAT:
             break;
         case Instruction.LuaOpcode.EQ:
             break;
         case Instruction.LuaOpcode.LT:
             break;
         case Instruction.LuaOpcode.LE:
             break;
         default:
             break;
     }
     return false;
 }
Пример #9
0
        public LuaFile Parse(string t)
        {
            this.text = t;

            file = new LuaFile();
            index = 0;
            lineNumber = 1;
            func = file.Main;
            file.Main.Vararg = 2;
            file.Main.Name = "LASM Chunk";
            funcStack = new Stack<Chunk>();

            readWhitespace();
            while (text.Length > index)
            {
                readWhitespace();
                string line = "";
                while (true)
                {
                    if (text.Length <= index)
                        break;
                    char c = text[index];
                    if (c == '\r')
                    {
                        index++;
                        if (text[index] == '\n')
                            index++;
                        break;
                    }
                    else if (c == '\n')
                    {
                        index++;
                        break;
                    }
                    else
                        line += c;
                    index++;
                }
                line = line.Trim();
                if (string.IsNullOrEmpty(line) || line[0] == ';')
                { } // do nothing.
                else if (line[0] == '.')
                    parseControl(line);
                else
                {
                    Instruction op = parseOpcode(line);
                    op.LineNumber = lineNumber;
                    func.Instructions.Add(op);
                }
                lineNumber++;
            }

            Instruction instr1 = func.Instructions.Count > 0 ? func.Instructions[func.Instructions.Count - 1] : null;
            Instruction instr2 = new Instruction("RETURN");
            instr2.A = 0;
            instr2.B = 1;
            instr2.C = 0;
            //getmetatable(func.Instructions).__newindex(func.Instructions, func.Instructions.Count, op)
            if (instr1 == null || instr1.Opcode != Instruction.LuaOpcode.RETURN)
                func.Instructions.Add(instr2);
            return file;
        }
Пример #10
0
        void parseControl(string line)
        {
            string ll = line.ToLower();
            if (ll.Substring(0, 6) == ".const")
            {
                string l = line.Substring(6);
                l = l.Trim();
                object value = readValue(l);
                if (value == null)
                    func.Constants.Add(new Constant(ConstantType.Nil, null));
                else if (value is bool)
                    func.Constants.Add(new Constant(ConstantType.Bool, (bool)value));
                else if (value is double)
                    func.Constants.Add(new Constant(ConstantType.Number, (double)value));
                else if (value is string)
                    func.Constants.Add(new Constant(ConstantType.String, (string)value));
            }
            else if (ll.Substring(0, 5) == ".name")
            {
                /// Im lazy :P
                string l = line.Substring(5);
                l = l.Trim();
                if (l[0] == '"')
                    func.Name = (string)readValue(l);
                else
                    func.Name = l;
            }
            else if (ll.Substring(0, 8) == ".options")
            {
                string l = line.Substring(8);
                l = l.Trim();
                List<int> nums = new List<int>();
                // Pattern matching time!
                Regex r = new Regex("\\d+");
                foreach (Match m in r.Matches(l))
                    nums.Add(int.Parse(m.Value));
                func.UpvalueCount = nums.Count > 0 ? nums[0] : func.UpvalueCount;
                func.ArgumentCount = nums.Count > 1 ? nums[1] : func.ArgumentCount;
                func.Vararg = nums.Count > 2 ? nums[2] : func.Vararg;
                func.MaxStackSize = nums.Count > 3 ? (uint)nums[3] : func.MaxStackSize;
            }
            else if (ll.Substring(0, 6) == ".local")
            {
                string l = line.Substring(6).Trim();
                if (l[0] == '"')
                    func.Locals.Add(new Local((string)readValue(l), 0, 0));
                else
                    func.Locals.Add(new Local(l, 0, 0));
            }
            else if (ll.Substring(0, 6) == ".upval")
            {
                string l = line.Substring(6).Trim();
                if (l[0] == '"')
                    func.Upvalues.Add(new Upvalue((string)readValue(l)));
                else
                    func.Upvalues.Add(new Upvalue(l));
            }
            else if (ll.Substring(0, 8) == ".upvalue")
            {
                string l = line.Substring(8).Trim();
                if (l[0] == '"')
                    func.Upvalues.Add(new Upvalue((string)readValue(l)));
                else
                    func.Upvalues.Add(new Upvalue(l));
            }
            else if (ll.Substring(0, 10) == ".stacksize")
            {
                string l = line.Substring(10).Trim();
                uint n = uint.Parse(l);
                func.MaxStackSize = n;
            }
            else if (ll.Substring(0, 13) == ".maxstacksize")
            {
                string l = line.Substring(13).Trim();
                uint n = uint.Parse(l);
                func.MaxStackSize = n;
            }
            else if (ll.Substring(0, 7) == ".vararg")
            {
                string l = line.Substring(7).Trim();
                int n = int.Parse(l);
                func.Vararg = n;
            }
            else if (ll.Substring(0, 9) == ".function")
            {
                string l = line.Substring(9).Trim();
                Chunk n = new Chunk();
                n.FirstLine = (uint)lineNumber;
                if (l.Length > 0)
                    if (l[0] == '"')
                        n.Name = (string)readValue(l);
                    else
                        n.Name = l;
                func.Protos.Add(n);
                funcStack.Push(func);
                func = n;
            }
            else if (ll.Substring(0, 5) == ".func")
            {
                string l = line.Substring(5).Trim();
                Chunk n = new Chunk();
                n.FirstLine = (uint)lineNumber;
                if (l.Length > 0)
                    if (l[0] == '"')
                        n.Name = (string)readValue(l);
                    else
                        n.Name = l;
                func.Protos.Add(n);
                funcStack.Push(func);
                func = n;
            }
            else if (ll.Substring(0, 4) == ".end")
            {
                Chunk f = funcStack.Pop();
                func.LastLine = (ulong)lineNumber;
                Instruction instr1 = func.Instructions.Count > 0 ? func.Instructions[func.Instructions.Count - 1] : null;
                Instruction instr2 = new Instruction("RETURN");
                instr2.A = 0;
                instr2.B = 1;
                instr2.C = 0;
                if (instr1 != null && instr1.Opcode == Instruction.LuaOpcode.RETURN)
                { } //func.Instructions.Add(instr2);
                else
                    func.Instructions.Add(instr2);

                func = f;
            }
            else
                throw new Exception("Invalid Control Label");
        }
Пример #11
0
        Instruction parseOpcode(string line)
        {
            string op = "";
            int i = 0;
            string l = line.ToLower();
            while (true)
            {
                if (i >= l.Length)
                    break;
                if (!char.IsLetter(l[i]))
                    break;
                else
                    op += l[i++];
            }
            Instruction instr = new Instruction(op, 0);

            line = line.Substring(i).Trim();
            i = 0;

            switch (instr.OpcodeType)
            {
                case OpcodeType.ABC:
                    string a = "", b = "", c = "";
                    bool inA = true, inB = false;
                    while (true)
                    {
                        if (line.Length <= i)
                            break;

                        char ch = line[i];
                        if (ch == '\t' || ch == ' ')
                            if (inA)
                            {
                                inB = true;
                                inA = false;
                            }
                            else if (inB)
                                inB = false;
                            else
                                break;
                        else
                            if (inA)
                                a = a + ch;
                            else if (inB)
                                b = b + ch;
                            else
                                c = c + ch;
                        i++;
                    }
                    c = c == "" ? "0" : c;
                    instr.A = tonumber(a);
                    instr.B = tonumber(b);
                    instr.C = tonumber(c);
                    break;
                case OpcodeType.ABx:
                    string bx = "";
                    a = "";
                    inA = true;
                    while (true)
                    {
                        if (line.Length <= i)
                            break;

                        char ch = line[i];
                        if (ch == '\t' || ch == ' ')
                            if (inA)
                                inA = false;
                            else
                                break;
                        else
                            if (inA)
                                a = a + ch;
                            else
                                bx = bx + ch;
                        i++;
                    }
                    instr.A = tonumber(a);
                    instr.Bx = tonumber(bx);
                    break;
                case OpcodeType.AsBx:
                    string sbx = "";
                    a = "";
                    inA = true;
                    while (true)
                    {
                        if (line.Length <= i)
                            break;

                        char ch = line[i];
                        if (ch == '\t' || ch == ' ')
                            if (inA)
                                inA = false;
                            else
                                break;
                        else
                            if (inA)
                                a = a + ch;
                            else
                                sbx = sbx + ch;
                        i++;
                    }
                    instr.A = tonumber(a);
                    instr.sBx = tonumber(sbx);
                    break;
                default:
                    break;
            }
            return instr;
        }
Пример #12
0
 public static string Opcode(Instruction op)
 {
     long c0, c1, c2, c3;
     if (op.OpcodeType == OpcodeType.AsBx)
     {
         long Bx = op.sBx + 131071;
         long C = Bit.keep(Bx, 9);
         long B = Bit.srb(Bx, 9);
         c0 = op.OpcodeNumber + Bit.slb(Bit.keep(op.A, 2), 6);
         c1 = Bit.srb(op.A, 2) + Bit.slb(Bit.keep(C, 2), 6);
         c2 = Bit.srb(C, 2) + Bit.slb(Bit.keep(B, 1), 7);
         c3 = Bit.srb(B, 1);
     }
     else if (op.OpcodeType == OpcodeType.ABx)
     {
         long C = Bit.keep(op.Bx, 9);
         long B = Bit.srb(op.Bx, 9);
         c0 = op.OpcodeNumber + Bit.slb(Bit.keep(op.A, 2), 6);
         c1 = Bit.srb(op.A, 2) + Bit.slb(Bit.keep(C, 2), 6);
         c2 = Bit.srb(C, 2) + Bit.slb(Bit.keep(B, 1), 7);
         c3 = Bit.srb(B, 1);
     }
     else
     {
         c0 = op.OpcodeNumber + Bit.slb(Bit.keep(op.A, 2), 6);
         c1 = Bit.srb(op.A, 2) + Bit.slb(Bit.keep(op.C, 2), 6);
         c2 = Bit.srb(op.C, 2) + Bit.slb(Bit.keep(op.B, 1), 7);
         c3 = Bit.srb(op.B, 1);
     }
     StringBuilder sb = new StringBuilder();
     sb.Append((char)c0);
     sb.Append((char)c1);
     sb.Append((char)c2);
     sb.Append((char)c3);
     return sb.ToString();
 }