示例#1
0
 public override Expression Simplify()
 {
     Base = Base.Simplify();
     for (int i = 0; i < Arguments.Count; i++)
         Arguments[i] = Arguments[i].Simplify();
     return this;
 }
示例#2
0
        public override Expression Simplify()
        {
            Base = base.Simplify();
            Index = Index.Simplify();

            return this;
        }
示例#3
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);
        }
示例#4
0
        void DoExpr(Expression e)
        {
            if (e is AnonymousFunctionExpr) // function() ... end
                ;
            else if (e is BinOpExpr)
                ;
            else if (e is BoolExpr)
                ;
            else if (e is CallExpr && (!(e is StringCallExpr) && !(e is TableCallExpr)))
                ;
            else if (e is StringCallExpr)
                ;
            else if (e is TableCallExpr)
                ;
            else if (e is IndexExpr)
                ;
            else if (e is InlineFunctionExpression) // |<args>| -> <exprs>
                ;
            else if (e is TableConstructorKeyExpr)
                ;
            else if (e is MemberExpr)
                ;
            else if (e is NilExpr)
                ;
            else if (e is NumberExpr)
                ;
            else if (e is StringExpr)
                ;
            else if (e is TableConstructorStringKeyExpr)
                ;
            else if (e is TableConstructorExpr)
                ;
            else if (e is UnOpExpr)
                ;
            else if (e is TableConstructorValueExpr)
                ;
            else if (e is VarargExpr)
                ;
            else if (e is VariableExpression)
                ;

            throw new NotImplementedException(e.GetType().Name + " is not implemented");
        }
示例#5
0
        public override Expression Simplify()
        {
            Rhs = Rhs.Simplify();
            UnaryOperator unop = GetOperator();
            if (Rhs is NumberExpr)
            {
                if (unop == UnaryOperator.Negate)
                    return new NumberExpr("-" + ((NumberExpr)Rhs).Value);
                else if (unop == UnaryOperator.UnNegate)
                {
                    double res;
                    if (Lua.luaO_str2d(((NumberExpr)Rhs).Value, out res) == 1)
                    {
                        return new NumberExpr(Math.Abs(res));
                    }
                }
            }
            else if (Rhs is BoolExpr)
                if (unop == UnaryOperator.Not)
                    return new BoolExpr(!((BoolExpr)Rhs).Value);

            return this;
        }
示例#6
0
        /// <summary>
        /// Extract strings from AST chunk.
        /// </summary>
        /// <param name="expr">Expression, which is found in the chunk.</param>
        /// <returns>String, which is in the expression.</returns>
        private string getExpressionAsString(Expression expr)
		{
			string result = "";

            if (expr is VariableExpression)
			{
				result = ( (VariableExpression) expr ).Var.Name;
			}
			if ( expr is BoolExpr )
			{
				result = ( (BoolExpr) expr ).Value ? "true" : "false";
			}
			if ( expr is CallExpr && ( (CallExpr) expr ).Base is MemberExpr )
			{
				expr = ( (CallExpr) expr ).Base;
			}
            // Inserted this, because Earwigo used WWB_multiplatform_string. If this is gone, we could remove this
            if (expr is CallExpr && ((CallExpr)expr).Arguments[0] is StringExpr)
            {
                expr = ((CallExpr)expr).Arguments[0];
            }
            if (expr is MemberExpr && ((MemberExpr)expr).Base is VariableExpression)
			{
				result = getExpressionAsString ( ( (MemberExpr) expr ).Base ) + "." + ( (MemberExpr) expr ).Ident;
			}
			if ( expr is StringExpr )
			{
				StringExpr str = (StringExpr) expr;
				result = str.Value;
			}

			return result;
		}
示例#7
0
        static List<CompletionItem> DoExpr(Expression e)
        {
            List<CompletionItem> ret = new List<CompletionItem>();
            if (e is AnonymousFunctionExpr)
            {
                AnonymousFunctionExpr f = e as AnonymousFunctionExpr;
                for (int i = 0; i < f.Arguments.Count; i++)
                    ret.Add(new CompletionItem(f.Arguments[i].Name));
                ret.AddRange(DoChunk(f.Body));
            }
            else if (e is BinOpExpr)
            {
            }
            else if (e is BoolExpr)
            {
            }
            else if (e is CallExpr && (!(e is StringCallExpr) && !(e is TableCallExpr)))
            {
            }
            else if (e is StringCallExpr)
            {
                ret.AddRange(DoExpr(((StringCallExpr)e).Base));
            }
            else if (e is TableCallExpr)
            {
                ret.AddRange(DoExpr(((StringCallExpr)e).Base));
            }
            else if (e is IndexExpr)
            {
                ret.AddRange(DoExpr(((IndexExpr)e).Base));
                ret.AddRange(DoExpr(((IndexExpr)e).Index));
            }
            else if (e is InlineFunctionExpression) // |<args>| -> <exprs>
            {
                InlineFunctionExpression ife = e as InlineFunctionExpression;
                for (int i = 0; i < ife.Arguments.Count; i++)
                    ret.Add(new CompletionItem(ife.Arguments[i].Name));
            }
            else if (e is TableConstructorKeyExpr)
            {
                TableConstructorKeyExpr t = e as TableConstructorKeyExpr;
                ret.AddRange(DoExpr(t.Key));
                ret.AddRange(DoExpr(t.Value));
            }
            else if (e is MemberExpr)
            {
                MemberExpr m = e as MemberExpr;
                ret.AddRange(DoExpr(m.Base));
                ret.Add(new CompletionItem(m.Ident));
            }
            else if (e is NilExpr)
            {
            }
            else if (e is NumberExpr)
            {
            }
            else if (e is StringExpr)
            {
                StringExpr se = e as StringExpr;
            }
            else if (e is TableConstructorStringKeyExpr)
            {
                TableConstructorStringKeyExpr tcske = e as TableConstructorStringKeyExpr;
                ret.Add(new CompletionItem(tcske.Key));
                ret.AddRange(DoExpr(tcske.Value));
            }
            else if (e is TableConstructorExpr)
            {
                TableConstructorExpr t = e as TableConstructorExpr;
                for (int i = 0; i < t.EntryList.Count; i++)
                    ret.AddRange(DoExpr(t.EntryList[i]));
            }
            else if (e is UnOpExpr)
            {
            }
            else if (e is TableConstructorValueExpr)
                ret.AddRange(DoExpr((e as TableConstructorValueExpr).Value));
            else if (e is VarargExpr)
            {
            }
            else if (e is VariableExpression)
                ret.Add(new CompletionItem((e as VariableExpression).Var.Name));

            return ret;
        }
示例#8
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);
        }
示例#9
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");
        }
示例#10
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;
 }
示例#11
0
        internal string DoExpr(Expression e, List<Token> tok, ref int index, Scope s)
        {
            int startP = index;
            for (int i = 0; i < e.ParenCount; i++)
                index++;

            string ret = null;
            if (e is AnonymousFunctionExpr) // function() ... end
            {
                AnonymousFunctionExpr f = e as AnonymousFunctionExpr;
                StringBuilder sb = new StringBuilder();

                sb.Append(fromToken(tok[index++], s)); // 'function'
                sb.Append(fromToken(tok[index++], s)); // '('
                for (int i2 = 0; i2 < f.Arguments.Count; i2++)
                {
                    sb.Append(fromToken(tok[index++], s));
                    if (i2 != f.Arguments.Count - 1 || f.IsVararg)
                        sb.Append(fromToken(tok[index++], s)); // ','
                }
                if (f.IsVararg)
                    sb.Append(fromToken(tok[index++], s));
                sb.Append(fromToken(tok[index++], s)); // ')'

                sb.Append(DoChunk(f.Body));

                //sb.Append(fromToken(tok[tok.Count - 1], s)); // <end>
                string str = fromToken(tok[tok.Count - 1], s);
                sb.Append(str);

                ret = sb.ToString();
            }
            else if (e is BinOpExpr)
            {
                //int i = 0;
                string left = DoExpr((e as BinOpExpr).Lhs, tok, ref index, s);
                string op = fromToken(tok[index++], s);
                string right = DoExpr((e as BinOpExpr).Rhs, tok, ref index, s);
                ret = string.Format("{0}{1}{2}", left, op, right);
            }
            else if (e is BoolExpr)
            {
                ret = fromToken(tok[index++], s);
            }
            else if (e is CallExpr && (!(e is StringCallExpr) && !(e is TableCallExpr)))
            {
                CallExpr c = e as CallExpr;
                StringBuilder sb = new StringBuilder();
                sb.Append(DoExpr(c.Base, tok, ref index, s) // <base>
                          + fromToken(tok[index++], s)); // '('
                for (int i = 0; i < c.Arguments.Count; i++)
                {
                    sb.Append(DoExpr(c.Arguments[i], tok, ref index, s));
                    if (i != c.Arguments.Count - 1)
                        sb.Append(fromToken(tok[index++], s)); // ', '
                }
                sb.Append(fromToken(tok[index++], s)); // ')'
                ret = sb.ToString();
            }
            else if (e is StringCallExpr)
            {
                StringCallExpr sc = e as StringCallExpr;
                ret = string.Format("{0}{1}", DoExpr(sc.Base, tok, ref index, s), DoExpr(sc.Arguments[0], tok, ref index, s));
            }
            else if (e is TableCallExpr)
            {
                TableCallExpr sc = e as TableCallExpr;
                ret = string.Format("{0}{1}", DoExpr(sc.Base, tok, ref index, s), DoExpr(sc.Arguments[0], tok, ref index, s));
            }
            else if (e is IndexExpr)
            {
                IndexExpr i = e as IndexExpr;
                ret = string.Format("{0}{1}{2}{3}", DoExpr(i.Base, tok, ref index, s), fromToken(tok[index++], s), DoExpr(i.Index, tok, ref index, s), fromToken(tok[index++], s));
            }
            else if (e is InlineFunctionExpression) // |<args>| -> <exprs>
            {
                InlineFunctionExpression ife = e as InlineFunctionExpression;
                StringBuilder sb = new StringBuilder();
                sb.Append(fromToken(tok[index++], s)); // '|;
                for (int i = 0; i < ife.Arguments.Count; i++)
                {
                    sb.Append(fromToken(tok[index++], s)); // <arg name>
                    if (i != ife.Arguments.Count - 1 || ife.IsVararg)
                        sb.Append(fromToken(tok[index++], s)); // ','
                }
                if (ife.IsVararg)
                    sb.Append(fromToken(tok[index++], s)); // '...'
                sb.Append(fromToken(tok[index++], s)); // '|'
                sb.Append(fromToken(tok[index++], s)); // '->'
                for (int i2 = 0; i2 < ife.Expressions.Count; i2++)
                {
                    sb.Append(DoExpr(ife.Expressions[i2], tok, ref index, s));
                    if (i2 != ife.Expressions.Count - 1)
                        sb.Append(fromToken(tok[index++], s)); // ','
                }
                ret = sb.ToString();
            }
            else if (e is TableConstructorKeyExpr)
            {
                TableConstructorKeyExpr t = e as TableConstructorKeyExpr;
                ret = fromToken(tok[index++], s) + DoExpr(t.Key, tok, ref index, s) + fromToken(tok[index++], s) + fromToken(tok[index++], s) + DoExpr(t.Value, tok, ref index, s);
            }
            else if (e is MemberExpr)
            {
                MemberExpr m = e as MemberExpr;
                ret = DoExpr(m.Base, tok, ref index, s) + fromToken(tok[index++], s) + fromToken(tok[index++], s);
            }
            else if (e is NilExpr)
                ret = fromToken(tok[index++], s);
            else if (e is NumberExpr)
                ret = fromToken(tok[index++], s);
            else if (e is StringExpr)
                ret = fromToken(tok[index++], s);
            else if (e is TableConstructorStringKeyExpr)
            {
                TableConstructorStringKeyExpr tcske = e as TableConstructorStringKeyExpr;
                ret = fromToken(tok[index++], s); // key
                ret += fromToken(tok[index++], s); // '='
                ret += DoExpr(tcske.Value, tok, ref index, s); // value
            }
            else if (e is TableConstructorExpr)
            {
                TableConstructorExpr t = e as TableConstructorExpr;
                StringBuilder sb = new StringBuilder();
                sb.Append(fromToken(tok[index++], s)); // '{'
                for (int i = 0; i < t.EntryList.Count; i++)
                {
                    sb.Append(DoExpr(t.EntryList[i], tok, ref index, s));
                    if (i != t.EntryList.Count - 1)
                        sb.Append(fromToken(tok[index++], s)); // ','
                }
                sb.Append(fromToken(tok[index++], s)); // '}'
                ret = sb.ToString();
            }
            else if (e is UnOpExpr)
            {
                string sc = fromToken(tok[index++], s);
                ret = sc + DoExpr((e as UnOpExpr).Rhs, tok, ref index, s);
            }
            else if (e is TableConstructorValueExpr)
                ret = DoExpr(((TableConstructorValueExpr)e).Value, tok, ref index, s);
            else if (e is VarargExpr)
                ret = fromToken(tok[index++], s);
            else if (e is VariableExpression)
                ret = fromToken(tok[index++], s);
            else if (e is TableConstructorNamedFunctionExpr)
                ret = DoStatement(((TableConstructorNamedFunctionExpr)e).Value);

            if (ret != null)
            {
                if (e.ParenCount > 0)
                {
                    StringBuilder sb = new StringBuilder();
                    for (int i = 0; i < e.ParenCount; i++)
                        sb.Append(fromToken(tok[startP++], s));
                    sb.Append(ret);
                    for (int i = 0; i < e.ParenCount; i++)
                        sb.Append(fromToken(tok[index++], s));
                    return sb.ToString();
                }
                else
                    return ret;
            }
            //return string.Format("{0}{1}{2}", "(".Repeat(e.ParenCount), ret, ")".Repeat(e.ParenCount));

            throw new NotImplementedException(e.GetType().Name + " is not implemented");
        }
示例#12
0
 public override Expression Simplify()
 {
     Base = Base.Simplify();
     return this;
 }
 public override Expression Simplify()
 {
     Value = Value.Simplify();
     return this;
 }
示例#14
0
        internal string DoExpr(Expression e)
        {
            string ret = null;
            if (e is AnonymousFunctionExpr) // function() ... end
            {
                // TODO: optimize into InlineFunctionExpr?
                // it would be much smaller than function() return <...> end 

                AnonymousFunctionExpr f = e as AnonymousFunctionExpr;
                StringBuilder sb = new StringBuilder();
                sb.Append("function(");
                for (int i = 0; i < f.Arguments.Count; i++)
                {
                    sb.Append(f.Arguments[i].Name);
                    if (i != f.Arguments.Count - 1 || f.IsVararg)
                        sb.Append(",");
                }
                if (f.IsVararg)
                    sb.Append("...");
                sb.Append(")");
                sb.Append(DoChunk(f.Body));
                sb.Append("end");

                ret = sb.ToString();
            }
            else if (e is BinOpExpr)
            {
                string left = DoExpr((e as BinOpExpr).Lhs);
                string op = (e as BinOpExpr).Op;
                string right = DoExpr((e as BinOpExpr).Rhs);
                ret = string.Format("{0}{1}{2}", left, op, right);
            }
            else if (e is BoolExpr)
            {
                bool val = (e as BoolExpr).Value;
                ret = val ? "true" : "false";
            }
            else if (e is CallExpr && (!(e is StringCallExpr) && !(e is TableCallExpr)))
            {
                CallExpr c = e as CallExpr;
                StringBuilder sb = new StringBuilder();
                sb.Append(DoExpr(c.Base) + "(");
                for (int i = 0; i < c.Arguments.Count; i++)
                {
                    sb.Append(DoExpr(c.Arguments[i]));
                    if (i != c.Arguments.Count - 1)
                        sb.Append(",");
                }
                sb.Append(")");
                ret = sb.ToString();
            }
            else if (e is StringCallExpr)
            {
                StringCallExpr s = e as StringCallExpr;
                ret = string.Format("{0}{1}", DoExpr(s.Base), DoExpr(s.Arguments[0]));
            }
            else if (e is TableCallExpr)
            {
                TableCallExpr s = e as TableCallExpr;
                ret = string.Format("{0}{1}", DoExpr(s.Base), DoExpr(s.Arguments[0]));
            }
            else if (e is IndexExpr)
            {
                IndexExpr i = e as IndexExpr;
                ret = string.Format("{0}[{1}]", DoExpr(i.Base), DoExpr(i.Index));
            }
            else if (e is InlineFunctionExpression) // |<args>| -> <exprs>
            {
                InlineFunctionExpression ife = e as InlineFunctionExpression;
                StringBuilder sb = new StringBuilder();
                sb.Append("|");
                for (int i = 0; i < ife.Arguments.Count; i++)
                {
                    sb.Append(ife.Arguments[i].Name);
                    if (i != ife.Arguments.Count - 1 || ife.IsVararg)
                        sb.Append(", ");
                }
                if (ife.IsVararg)
                    sb.Append("...");
                sb.Append("|->");
                for (int i2 = 0; i2 < ife.Expressions.Count; i2++)
                {
                    sb.Append(DoExpr(ife.Expressions[i2]));
                    if (i2 != ife.Expressions.Count - 1)
                        sb.Append(",");
                }
                ret = sb.ToString();
            }
            else if (e is TableConstructorKeyExpr)
            {
                TableConstructorKeyExpr t = e as TableConstructorKeyExpr;
                ret = "[" + DoExpr(t.Key) + "]=" + DoExpr(t.Value);
            }
            else if (e is MemberExpr)
            {
                MemberExpr m = e as MemberExpr;
                ret = DoExpr(m.Base) + m.Indexer + m.Ident;
            }
            else if (e is NilExpr)
                ret = "nil";
            else if (e is NumberExpr)
                ret = (e as NumberExpr).Value;
            else if (e is StringExpr)
            {
                StringExpr se = e as StringExpr;
                string delim = se.StringType == TokenType.SingleQuoteString ? "'" : (se.StringType == TokenType.DoubleQuoteString ? "\"" : "[");
                if (delim == "[")
                {
                    // Long strings keep their [=*[
                    ret = se.Value;
                }
                else
                    ret = delim + se.Value + delim;
            }
            else if (e is TableConstructorStringKeyExpr)
            {
                TableConstructorStringKeyExpr tcske = e as TableConstructorStringKeyExpr;
                ret = tcske.Key + "=" + DoExpr(tcske.Value);
            }
            else if (e is TableConstructorExpr)
            {
                TableConstructorExpr t = e as TableConstructorExpr;
                StringBuilder sb = new StringBuilder();
                sb.Append("{");
                for (int i = 0; i < t.EntryList.Count; i++)
                {
                    sb.Append(DoExpr(t.EntryList[i]));
                    if (i != t.EntryList.Count - 1)
                        sb.Append(",");
                }
                sb.Append("}");
                ret = sb.ToString();
            }
            else if (e is UnOpExpr)
            {
                string op = (e as UnOpExpr).Op;
                string s = op;
                if (s.Length != 1)
                    s += " ";
                ret = s + DoExpr((e as UnOpExpr).Rhs);
            }
            else if (e is TableConstructorValueExpr)
                ret = DoExpr((e as TableConstructorValueExpr).Value);
            else if (e is VarargExpr)
                ret = "...";
            else if (e is VariableExpression)
                ret = (e as VariableExpression).Var.Name;
            else if (e is TableConstructorNamedFunctionExpr)
                ret = DoStatement(((TableConstructorNamedFunctionExpr)e).Value);

            if (ret != null)
                return string.Format("{0}{1}{2}", "(".Repeat(e.ParenCount), ret, ")".Repeat(e.ParenCount));

            throw new NotImplementedException(e.GetType().Name + " is not implemented");
        }
示例#15
0
        public override Expression Simplify()
        {
            Lhs = Lhs.Simplify();
            Rhs = Rhs.Simplify();

            double a, b;
            int isNumA = Lua.luaO_str2d(((NumberExpr)Lhs).Value, out a);
            int isNumB = Lua.luaO_str2d(((NumberExpr)Rhs).Value, out b);
            bool isNum = false;
            isNum = isNumA == 1 && isNumB == 1;

            switch (GetOperator())
            {
                case BinaryOperator.Add:
                    if (isNum)
                        return new NumberExpr(a + b);
                    break;
                case BinaryOperator.Subtract:
                    if (isNum)
                        return new NumberExpr(a - b);
                    break;
                case BinaryOperator.Multiply:
                    if (isNum)
                        return new NumberExpr(a * b);
                    break;
                case BinaryOperator.Divide:
                    if (isNum)
                        return new NumberExpr(a / b);
                    break;
                case BinaryOperator.Power:
                    if (isNum)
                        return new NumberExpr(Math.Pow(a, b));
                    break;
                case BinaryOperator.Modulus:
                    if (isNum)
                        return new NumberExpr(a % b);
                    break;
                case BinaryOperator.LessThan:
                    if (isNum)
                        return new BoolExpr(a < b);
                    break;
                case BinaryOperator.LessThanOrEqualTo:
                    if (isNum)
                        return new BoolExpr(a <= b);
                    break;
                case BinaryOperator.GreaterThan:
                    if (isNum)
                        return new BoolExpr(a > b);
                    break;
                case BinaryOperator.GreaterThanOrEqualTo:
                    if (isNum)
                        return new BoolExpr(a >= b);
                    break;
                case BinaryOperator.NotEqual:
                    if (Lhs is BoolExpr && Rhs is BoolExpr)
                        return new BoolExpr(((BoolExpr)Lhs).Value != ((BoolExpr)Rhs).Value);
                    else if (isNum)
                        return new BoolExpr(a != b);
                    break;
                case BinaryOperator.Equals:
                    if (Lhs is BoolExpr && Rhs is BoolExpr)
                        return new BoolExpr(((BoolExpr)Lhs).Value == ((BoolExpr)Rhs).Value);
                    else if (isNum)
                        return new BoolExpr(a == b);
                    break;
                case BinaryOperator.And:
                    if (Lhs is BoolExpr && Rhs is BoolExpr)
                        return new BoolExpr(((BoolExpr)Lhs).Value && ((BoolExpr)Rhs).Value);
                    break;
                case BinaryOperator.Or:
                    if (Lhs is BoolExpr && Rhs is BoolExpr)
                        return new BoolExpr(((BoolExpr)Lhs).Value || ((BoolExpr)Rhs).Value);
                    break;
                case BinaryOperator.ShiftRight:
                case BinaryOperator.ShiftLeft:
                case BinaryOperator.Xor:
                case BinaryOperator.BitAnd:
                case BinaryOperator.BitOr:
                case BinaryOperator.BitNot:
                case BinaryOperator.Concat:
                case BinaryOperator.NONE:
                default:
                    break;
            }

            return base.Simplify();
        }
        internal string DoExpr(Expression e, Scope s)
        {
            int startP = index;
            index += e.ParenCount;

            string ret = null;
            if (e is AnonymousFunctionExpr) // function() ... end
            {
                AnonymousFunctionExpr f = e as AnonymousFunctionExpr;
                StringBuilder sb = new StringBuilder();

                sb.Append(fromToken(tok[index++], s)); // 'function'
                sb.Append(fromToken(tok[index++], s)); // '('
                for (int i2 = 0; i2 < f.Arguments.Count; i2++)
                {
                    sb.Append(fromToken(tok[index++], s));
                    if (i2 != f.Arguments.Count - 1 || f.IsVararg)
                        sb.Append(fromToken(tok[index++], s) + " ");
                }
                if (f.IsVararg)
                    sb.Append(fromToken(tok[index++], s));
                sb.Append(fromToken(tok[index++], s)); // ')'

                if (f.Body.Count > 1)
                {
                    sb.Append(options.EOL);
                    indent++;
                    sb.Append(DoChunk(f.Body));
                    sb.Append(nldedent());
                }
                else if (f.Body.Count == 0)
                {
                    sb.Append(" ");
                }
                else
                {
                    sb.Append(" " + DoStatement(f.Body[0]));
                    sb.Append(" ");
                }

                sb.Append(fromToken(tok[index++], s)); // <end>

                ret = sb.ToString();
            }
            else if (e is BinOpExpr)
            {
                //int i = 0;
                string left = DoExpr((e as BinOpExpr).Lhs, s);
                string op = fromToken(tok[index++], s);
                string right = DoExpr((e as BinOpExpr).Rhs, s);
                ret = string.Format("{0} {1} {2}", left, op, right);
            }
            else if (e is BoolExpr)
            {
                ret = fromToken(tok[index++], s);
            }
            else if (e is CallExpr && (!(e is StringCallExpr) && !(e is TableCallExpr)))
            {
                CallExpr c = e as CallExpr;
                StringBuilder sb = new StringBuilder();
                sb.Append(DoExpr(c.Base, s) // <base>
                          + fromToken(tok[index++], s)); // '('
                for (int i = 0; i < c.Arguments.Count; i++)
                {
                    sb.Append(DoExpr(c.Arguments[i], s));
                    if (i != c.Arguments.Count - 1)
                    {
                        sb.Append(fromToken(tok[index++], s)); // ', '
                        sb.Append(" ");
                    }
                }
                sb.Append(fromToken(tok[index++], s)); // ')'
                ret = sb.ToString();
            }
            else if (e is StringCallExpr)
            {
                StringCallExpr sc = e as StringCallExpr;
                ret = string.Format("{0} {1}", DoExpr(sc.Base, s), DoExpr(sc.Arguments[0], s));
            }
            else if (e is TableCallExpr)
            {
                TableCallExpr sc = e as TableCallExpr;
                ret = string.Format("{0} {1}", DoExpr(sc.Base, s), DoExpr(sc.Arguments[0], s));
            }
            else if (e is IndexExpr)
            {
                IndexExpr i = e as IndexExpr;
                ret = string.Format("{0}{1}{2}{3}", DoExpr(i.Base, s), fromToken(tok[index++], s), DoExpr(i.Index, s), fromToken(tok[index++], s));
            }
            else if (e is InlineFunctionExpression) // |<args>| -> <exprs>
            {
                InlineFunctionExpression ife = e as InlineFunctionExpression;
                StringBuilder sb = new StringBuilder();
                sb.Append(fromToken(tok[index++], s)); // '|;
                for (int i = 0; i < ife.Arguments.Count; i++)
                {
                    sb.Append(fromToken(tok[index++], s)); // <arg name>
                    if (i != ife.Arguments.Count - 1 || ife.IsVararg)
                    {
                        sb.Append(fromToken(tok[index++], s)); // ','
                        sb.Append(" ");
                    }
                }
                if (ife.IsVararg)
                {
                    sb.Append(fromToken(tok[index++], s)); // '...'
                    sb.Append(" ");
                }
                sb.Append(fromToken(tok[index++], s)); // '|'
                sb.Append(" ");
                sb.Append(fromToken(tok[index++], s)); // '->'
                sb.Append(" ");
                for (int i2 = 0; i2 < ife.Expressions.Count; i2++)
                {
                    sb.Append(DoExpr(ife.Expressions[i2], s));
                    if (i2 != ife.Expressions.Count - 1)
                    {
                        sb.Append(fromToken(tok[index++], s)); // ','
                        sb.Append(" ");
                    }
                }
                ret = sb.ToString();
            }
            else if (e is TableConstructorKeyExpr)
            {
                TableConstructorKeyExpr t = e as TableConstructorKeyExpr;
                ret =
                    fromToken(tok[index++], s)
                    + DoExpr(t.Key, s)
                    + fromToken(tok[index++], s)
                    + " "
                    + fromToken(tok[index++], s)
                    + " "
                    + DoExpr(t.Value, s);
            }
            else if (e is MemberExpr)
            {
                MemberExpr m = e as MemberExpr;
                ret = DoExpr(m.Base, s) + fromToken(tok[index++], s) + fromToken(tok[index++], s);
            }
            else if (e is NilExpr)
                ret = fromToken(tok[index++], s);
            else if (e is NumberExpr)
                ret = fromToken(tok[index++], s);
            else if (e is StringExpr)
                ret = fromToken(tok[index++], s);
            else if (e is TableConstructorStringKeyExpr)
            {
                TableConstructorStringKeyExpr tcske = e as TableConstructorStringKeyExpr;
                ret = fromToken(tok[index++], s); // key
                ret += " ";
                ret += fromToken(tok[index++], s); // '='
                ret += " ";
                ret += DoExpr(tcske.Value, s); // value
            }
            else if (e is TableConstructorExpr)
            {
                TableConstructorExpr t = e as TableConstructorExpr;
                StringBuilder sb = new StringBuilder();
                sb.Append(fromToken(tok[index++], s)); // '{'
                sb.Append(" ");
                bool needNewLines = false;
                if (t.EntryList.Count > 4)
                    needNewLines = true;
                for (int i = 0; i < t.EntryList.Count; i++)
                {
                    string tmp = DoExpr(t.EntryList[i], s);
                    if (tmp.Length > 10)
                        needNewLines = true;
                    sb.Append(tmp);
                    
                    if (i != t.EntryList.Count - 1)
                    {
                        sb.Append(fromToken(tok[index++], s)); // ','
                        sb.Append(" ");
                    }
                }
                if (t.EntryList.Count > 0) // empty table constructor is just { }
                    sb.Append(" ");
                sb.Append(fromToken(tok[index++], s)); // '}'
                ret = sb.ToString();
            }
            else if (e is UnOpExpr)
            {
                UnOpExpr u = e as UnOpExpr;
                string sc = fromToken(tok[index++], s);
                if (u.Op.Length != 1)
                    sc += " ";
                ret = sc + DoExpr(u.Rhs, s);
            }
            else if (e is TableConstructorValueExpr)
                ret = DoExpr(((TableConstructorValueExpr)e).Value, s);
            else if (e is VarargExpr)
                ret = fromToken(tok[index++], s);
            else if (e is VariableExpression)
                ret = fromToken(tok[index++], s);
            else if (e is TableConstructorNamedFunctionExpr)
                ret = DoStatement(((TableConstructorNamedFunctionExpr)e).Value);

            if (ret != null)
            {
                if (e.ParenCount > 0)
                {
                    StringBuilder sb = new StringBuilder();
                    for (int i = 0; i < e.ParenCount; i++)
                        sb.Append(fromToken(tok[startP++], s));
                    sb.Append(ret);
                    for (int i = 0; i < e.ParenCount; i++)
                        sb.Append(fromToken(tok[index++], s));
                    return sb.ToString();
                }
                else
                    return ret;
            }
            //return string.Format("{0}{1}{2}", "(".Repeat(e.ParenCount), ret, ")".Repeat(e.ParenCount));

            throw new NotImplementedException(e.GetType().Name + " is not implemented");
        }
示例#17
0
        string DoExpr(Expression e)
        {
            string ret = "";
            if (e is AnonymousFunctionExpr) // function() ... end
            {
                AnonymousFunctionExpr f = e as AnonymousFunctionExpr;
                StringBuilder sb = new StringBuilder();
                sb.Append("function(");
                for (int i = 0; i < f.Arguments.Count; i++)
                {
                    sb.Append(f.Arguments[i].Name);
                    if (i != f.Arguments.Count - 1 || f.IsVararg)
                        sb.Append(", ");
                }
                if (f.IsVararg)
                    sb.Append("...");
                sb.Append(")");
                if (f.Body.Count > 1)
                {
                    sb.Append(EOL);
                    indent++;
                    sb.Append(DoChunk(f.Body));
                    sb.Append(nldedent());
                    sb.Append("end");
                }
                else if (f.Body.Count == 0)
                {
                    sb.Append(" end");
                }
                else
                {
                    sb.Append(" " + DoStatement(f.Body[0]));
                    sb.Append(" end");
                }

                ret = sb.ToString();
            }
            else if (e is BinOpExpr)
            {
                BinOpExpr b = e as BinOpExpr;
                string left = DoExpr(b.Lhs);
                string op = b.Op;
                string right = DoExpr(b.Rhs);
                if (op == "!=")
                    op = "~=";

                if (op == ">>")
                {
                    ret = string.Format("bit.rshift({0}, {1})", left, right);
                }
                else if (op == "<<")
                {
                    ret = string.Format("bit.lshift({0}, {1})", left, right);
                }
                else if (op == "&")
                {
                    ret = string.Format("bit.band({0}, {1})", left, right);
                }
                else if (op == "|")
                {
                    ret = string.Format("bit.bor({0}, {1})", left, right);
                }
                else if (op == "^^")
                {
                    ret = string.Format("bit.bxor({0}, {1})", left, right);
                }
                else
                    ret = string.Format("{0} {1} {2}", left, op, right);
            }
            else if (e is BoolExpr)
            {
                bool val = (e as BoolExpr).Value;
                ret = val ? "true" : "false";
            }
            else if (e is CallExpr && (!(e is StringCallExpr) && !(e is TableCallExpr)))
            {
                CallExpr c = e as CallExpr;
                StringBuilder sb = new StringBuilder();
                sb.Append(DoExpr(c.Base) + "(");
                for (int i = 0; i < c.Arguments.Count; i++)
                {
                    sb.Append(DoExpr(c.Arguments[i]));
                    if (i != c.Arguments.Count - 1)
                        sb.Append(", ");
                }
                sb.Append(")");
                ret = sb.ToString();
            }
            else if (e is StringCallExpr)
            {
                StringCallExpr s = e as StringCallExpr;
                ret = string.Format("{0} {1}", DoExpr(s.Base), DoExpr(s.Arguments[0]));
            }
            else if (e is TableCallExpr)
            {
                TableCallExpr s = e as TableCallExpr;
                ret = string.Format("{0} {1}", DoExpr(s.Base), DoExpr(s.Arguments[0]));
            }
            else if (e is IndexExpr)
            {
                IndexExpr i = e as IndexExpr;
                ret = string.Format("{0}[{1}]", DoExpr(i.Base), DoExpr(i.Index));
            }
            else if (e is InlineFunctionExpression) // |<args>| -> <exprs>
            {
                InlineFunctionExpression ife = e as InlineFunctionExpression;
                StringBuilder sb = new StringBuilder();
                sb.Append("function(");
                for (int i = 0; i < ife.Arguments.Count; i++)
                {
                    sb.Append(ife.Arguments[i].Name);
                    if (i != ife.Arguments.Count - 1 || ife.IsVararg)
                        sb.Append(", ");
                }
                if (ife.IsVararg)
                    sb.Append("...");
                sb.Append(") return ");
                for (int i2 = 0; i2 < ife.Expressions.Count; i2++)
                {
                    sb.Append(DoExpr(ife.Expressions[i2]));
                    if (i2 != ife.Expressions.Count - 1)
                        sb.Append(", ");
                }
                sb.Append(" end");
                ret = sb.ToString();
            }
            else if (e is TableConstructorKeyExpr)
            {
                TableConstructorKeyExpr t = e as TableConstructorKeyExpr;
                ret = "[" + DoExpr(t.Key) + "] = " + DoExpr(t.Value);
            }
            else if (e is MemberExpr)
            {
                MemberExpr m = e as MemberExpr;
                ret = DoExpr(m.Base) + m.Indexer + m.Ident;
            }
            else if (e is NilExpr)
                ret = "nil";
            else if (e is NumberExpr)
            {
                ret = (e as NumberExpr).Value;
                ret = ret.Replace("_", "");
            }
            else if (e is StringExpr)
            {
                StringExpr se = e as StringExpr;
                string delim = se.StringType == TokenType.SingleQuoteString ? "'" : se.StringType == TokenType.DoubleQuoteString ? "\"" : "[";
                if (delim == "[")
                {
                    // Long strings keep their [=*[
                    ret = se.Value;
                }
                else
                    ret = delim + se.Value + delim;
            }
            else if (e is TableConstructorStringKeyExpr)
            {
                TableConstructorStringKeyExpr tcske = e as TableConstructorStringKeyExpr;
                ret = tcske.Key + " = " + DoExpr(tcske.Value);
            }
            else if (e is TableConstructorExpr)
            {
                TableConstructorExpr t = e as TableConstructorExpr;
                StringBuilder sb = new StringBuilder();
                sb.Append("{ ");
                for (int i = 0; i < t.EntryList.Count; i++)
                {
                    sb.Append(DoExpr(t.EntryList[i]));
                    if (i != t.EntryList.Count - 1)
                        sb.Append(", ");
                }
                sb.Append("} ");
                ret = sb.ToString();
            }
            else if (e is UnOpExpr)
            {
                string op = (e as UnOpExpr).Op;
                if (op == "!")
                    op = "not";
                string s = op;
                if (s == "~")
                {
                    ret = "bit.bnot(" + DoExpr((e as UnOpExpr).Rhs) + ")";
                }
                else if (s == "+")
                {
                    ret = "math.abs(" + DoExpr((e as UnOpExpr).Rhs) + ")";
                }
                else
                {
                    if (s.Length != 1)
                        s += " ";
                    ret = s + DoExpr((e as UnOpExpr).Rhs);
                }
            }
            else if (e is TableConstructorValueExpr)
                ret = DoExpr((e as TableConstructorValueExpr).Value);
            else if (e is VarargExpr)
                ret = "...";
            else if (e is VariableExpression)
                ret = (e as VariableExpression).Var.Name;
            else if (e is TableConstructorNamedFunctionExpr)
            {
                TableConstructorNamedFunctionExpr fs = e as TableConstructorNamedFunctionExpr;
                AnonymousFunctionExpr a = new AnonymousFunctionExpr();
                a.Arguments = fs.Value.Arguments;
                a.Arguments.Insert(0, new Variable() { Name = "self", IsGlobal = false, References = -1 });
                a.Body = fs.Value.Body;
                a.IsVararg = fs.Value.IsVararg;
                ret = DoExpr(fs.Value.Name) + " = " + DoExpr(a);
            }

            return string.Format("{0}{1}{2}", oparens(e.ParenCount), ret, cparens(e.ParenCount));

            throw new NotImplementedException(e.GetType().Name + " is not implemented");
        }