public CycleStatement()
        {
            Step = new Expression();
            Step.IntValue = 1;
            Step.IsLeaf = true;
            Step.LeafType = ExpressionLeafType.Constant;
            Step.ResultType = VariableType.IntType;
            Step.OpType = OperationType.None;

            DeclareVariable = String.Empty;
        }
        private static ILExpression ConstructILExpression(Expression expr)
        {
            if (expr.OpType == OperationType.And || expr.OpType == OperationType.Or)
                throw new InvalidOperationException("And an Or doesn't supported yet");

            if (expr == null)
                return null;

            //Binary ops
            if (expr.IsLeaf == false)
            {
                ILExpression ilExpr = new ILExpression();

                ilExpr.LeftNode = ConstructILExpression(expr.LeftNode);
                ilExpr.RightNode = ConstructILExpression(expr.RightNode);

                //+, -, *, /, mod, pow, xor
                if (expr.OpType == OperationType.Plus)
                    ilExpr.Type = ILExpressionType.Plus;
                if (expr.OpType == OperationType.Minus)
                    ilExpr.Type = ILExpressionType.Minus;
                if (expr.OpType == OperationType.Mult)
                    ilExpr.Type = ILExpressionType.Mul;
                if (expr.OpType == OperationType.Div)
                    ilExpr.Type = ILExpressionType.Div;
                if (expr.OpType == OperationType.Mod)
                    ilExpr.Type = ILExpressionType.Mod;
                if (expr.OpType == OperationType.Power)
                    ilExpr.Type = ILExpressionType.Pow;
                if (expr.OpType == OperationType.Xor)
                    ilExpr.Type = ILExpressionType.Xor;
                //>,>=,<,<=,=,<>
                if (expr.OpType == OperationType.Gr)
                    ilExpr.Type = ILExpressionType.Gr;
                if (expr.OpType == OperationType.Greq)
                    ilExpr.Type = ILExpressionType.Greq;
                if (expr.OpType == OperationType.Le)
                    ilExpr.Type = ILExpressionType.Leeq;
                if (expr.OpType == OperationType.Equals)
                    ilExpr.Type = ILExpressionType.Eq;
                if (expr.OpType == OperationType.NotEquals)
                    ilExpr.Type = ILExpressionType.NotEq;
                //UNot, Uminus
                if (expr.OpType == OperationType.UNot)
                    ilExpr.Type = ILExpressionType.Unot;
                if (expr.OpType == OperationType.UMinus)
                    ilExpr.Type = ILExpressionType.Uminus;
                //ArrayAccess
                if (expr.OpType == OperationType.ArrayAccess)
                    ilExpr.Type = ILExpressionType.ArrayAccess;
                //Assign
                if (expr.OpType == OperationType.Assign)
                    ilExpr.Type = ILExpressionType.Assign;

                return ilExpr;
            }
            else
            {
                ILExpression ilExpr = new ILExpression();

                if (expr.LeafType == ExpressionLeafType.Constant)
                {
                    ilExpr.Type = ILExpressionType.Const;
                    if (expr.ResultType == VariableType.IntType)
                        ilExpr.Const = expr.IntValue;
                    else if (expr.ResultType == VariableType.BoolType)
                        ilExpr.Const = expr.BoolValue;
                    else
                        ilExpr.Const = expr.Value;
                }
                else if (expr.LeafType == ExpressionLeafType.VariableAccess)
                {
                    ilExpr.Type = ILExpressionType.VariableAccess;
                    ilExpr.Const = expr.Value;
                }
                else if (expr.LeafType == ExpressionLeafType.FunctionCall)
                {
                    ilExpr.Type = ILExpressionType.FunctionCall;
                    ilExpr.Const = expr.Value;
                    ilExpr.VAList = new List<ILExpression>();
                    foreach (var expression in expr.VAList)
                        ilExpr.VAList.Add(ConstructILExpression(expression));
                    ilExpr.Function = FindFunction((string)ilExpr.Const, expr.VAList);
                }
                else
                {
                    ilExpr.LeftNode = ConstructILExpression(expr.LeftNode);

                    if (expr.LeafType == ExpressionLeafType.ArrayLength)
                        ilExpr.Type = ILExpressionType.ArrayLength;
                    if (expr.LeafType == ExpressionLeafType.ArrayAlloc)
                        ilExpr.Type = ILExpressionType.Alloc;
                }

                return ilExpr;
            }
        }
 public static void EmitExpression(Expression expr, List<ILInstuction> il)
 {
     ILExpression ilExpr = ConstructILExpression(expr);
     ilExpr.Line = GetLabel();
     il.Add(ilExpr);
 }
        public static string _EmitExpression(Expression expr, List<ILInstuction> il)
        {
            if (expr.IsLeaf) {
                //Variable access
                if (expr.LeafType == ExpressionLeafType.VariableAccess) {

                    CurrentFunction.AddLocal(expr.Value.ToString(), expr.ResultType);

                    return expr.Value.ToString();
                } else if (expr.LeafType == ExpressionLeafType.Constant) {
                    var resultVariable = GetVariableName();
                    object c;
                    if (expr.ResultType == VariableType.IntType)
                        c = expr.IntValue;
                    else if (expr.ResultType == VariableType.BoolType)
                        c = expr.BoolValue;
                    else
                        c = expr.Value;
                    var ilExpr = _constructAssignExpressionToConst(resultVariable, c);
                    il.Add(ilExpr);

                    //ilExpr.OriginalType = expr.ResultType;
                    CurrentFunction.AddLocal(resultVariable, expr.ResultType);

                    return resultVariable;

                } else if (expr.LeafType == ExpressionLeafType.FunctionCall) {
                    var ilExpr = new ILExpression();
                    ilExpr.Type = ILExpressionType.FunctionCall;
                    ilExpr.Const = expr.Value;
                    ilExpr.VAList = new List<ILExpression>();
                    foreach (var expression in expr.VAList) {
                        var parameterVariable = _EmitExpression(expression, il);
                        ilExpr.VAList.Add(_constructVariableAccess(parameterVariable));
                    }
                    ilExpr.Function = FindFunction((string)ilExpr.Const, expr.VAList);
                    //TODO: Add support for void functions;

                    //ilExpr.OriginalType = expr.ResultType;

                    if (ilExpr.Function.IsVoidReturn) {
                        il.Add(ilExpr);
                        return "void";
                    } else {
                        var resultVariable = GetVariableName();
                        var resultExpr = _constructAssignExpression(resultVariable, ilExpr);
                        il.Add(resultExpr);

                        CurrentFunction.AddLocal(resultVariable, expr.ResultType);

                        return resultVariable;
                    }

                } else if (expr.LeafType == ExpressionLeafType.ArrayLength) {
                    var leftOp = _EmitExpression(expr.LeftNode, il);
                    var ilExpr = new ILExpression();
                    ilExpr.Type = ILExpressionType.ArrayLength;
                    ilExpr.LeftNode = _constructVariableAccess(leftOp);
                    var resultVariable = GetVariableName();
                    var resultExpr = _constructAssignExpression(resultVariable, ilExpr);
                    il.Add(resultExpr);

                    //resultExpr.OriginalType = expr.ResultType;
                    CurrentFunction.AddLocal(resultVariable, expr.ResultType);

                    return resultVariable;

                } else if (expr.LeafType == ExpressionLeafType.ArrayAlloc) {
                    var leftOp = _EmitExpression(expr.LeftNode, il);
                    var ilExpr = new ILExpression();
                    ilExpr.Type = ILExpressionType.Alloc;
                    ilExpr.OriginalType = expr.ResultType;

                    ilExpr.LeftNode = _constructVariableAccess(leftOp);
                    var resultVariable = GetVariableName();
                    var resultExpr = _constructAssignExpression(resultVariable, ilExpr);
                    il.Add(resultExpr);

                    CurrentFunction.AddLocal(resultVariable, expr.ResultType);

                    return resultVariable;
                }
            } else {
                if (expr.OpType == OperationType.Assign) {
                    var rightOp = _EmitExpression(expr.RightNode, il);
                    if (expr.LeftNode.LeafType == ExpressionLeafType.VariableAccess) {
                        var leftOp = _EmitExpression(expr.LeftNode, il);
                        il.Add(_constructAssignExpression(leftOp, rightOp));

                        CurrentFunction.AddLocal(leftOp, expr.ResultType);

                        return leftOp;
                    } else if (expr.LeftNode.OpType == OperationType.ArrayAccess) {

                        // Emit ( E1[E2] = E3) =
                        // Emit (E3) --> R
                        // Emit (E1) --> A
                        // Emit (E2) --> I
                        // A[I] = R
                        // return R;

                        var arrLeftOp = _EmitExpression(expr.LeftNode.LeftNode, il);
                        var arrIndexOp = _EmitExpression(expr.LeftNode.RightNode, il);
                        var arrAccess = _constructBinaryExpressionFromVars(arrLeftOp, arrIndexOp, OperationType.ArrayAccess);

                        var assignExpr = _constructAssignExpression(arrAccess, rightOp);
                        il.Add(assignExpr);

            //						assignExprstring resultVar = GetVariableName();
            //						var secondAssignExpr = _constructAssignExpression(resultVar, arrAccess);
            //						il.Add(secondAssignExpr);
                        return rightOp;
                    } else {
                        throw new InvalidOperationException("Bad assign construction!");
                    }
                } else if (expr.OpType == OperationType.And) {
                    var leftOp = _EmitExpression(expr.LeftNode, il);

                    CurrentFunction.AddLocal(leftOp, expr.ResultType);

                    var branch = new ILBranch();
                    branch.Line = GetLabel();
                    branch.Condition = _constructVariableAccess(leftOp);
                    var succ = new ILDummy();
                    succ.Line = GetLabel();
                    var fail = new ILDummy();
                    fail.Line = GetLabel();
                    var end = new ILDummy();
                    end.Line = GetLabel();
                    var gotoEnd = new ILGoto(end.Line);
                    branch.SuccessJump = succ.Line;
                    branch.FailJump = fail.Line;

                    var resultVariable = GetVariableName();
                    il.Add(branch);
                    il.Add(succ);
                    var rightOp = _EmitExpression(expr.RightNode, il);

                    CurrentFunction.AddLocal(rightOp, expr.ResultType);

                    il.Add(_constructAssignExpression(resultVariable, rightOp));
                    il.Add(gotoEnd);
                    il.Add(fail);
                    il.Add(_constructAssignExpressionToConst(resultVariable, false));
                    il.Add(end);

                    CurrentFunction.AddLocal(resultVariable, expr.ResultType);

                    return resultVariable;
                } else if (expr.OpType == OperationType.Or) {
                    var leftOp = _EmitExpression(expr.LeftNode, il);

                    CurrentFunction.AddLocal(leftOp, expr.ResultType);

                    var branch = new ILBranch();
                    branch.Line = GetLabel();
                    branch.Condition = _constructVariableAccess(leftOp);
                    var succ = new ILDummy();
                    succ.Line = GetLabel();
                    var fail = new ILDummy();
                    fail.Line = GetLabel();
                    var end = new ILDummy();
                    end.Line = GetLabel();
                    var gotoEnd = new ILGoto(end.Line);
                    branch.SuccessJump = succ.Line;
                    branch.FailJump = fail.Line;

                    var resultVariable = GetVariableName();
                    il.Add(branch);
                    il.Add(fail);
                    var rightOp = _EmitExpression(expr.RightNode, il);

                    CurrentFunction.AddLocal(rightOp, expr.ResultType);

                    il.Add(_constructAssignExpression(resultVariable, rightOp));
                    il.Add(gotoEnd);
                    il.Add(succ);
                    il.Add(_constructAssignExpressionToConst(resultVariable, true));
                    il.Add(end);

                    CurrentFunction.AddLocal(resultVariable, expr.ResultType);

                    return resultVariable;
                }
                else if (expr.OpType == OperationType.UNot || expr.OpType == OperationType.UMinus) {
                    var op1 = _EmitExpression(expr.LeftNode, il);
                    string varName=  GetVariableName();
                    var ilExpr = _constructBinaryExpressionFromVars(op1, "", expr.OpType);
                    il.Add(_constructAssignExpression(varName, ilExpr));

                    CurrentFunction.AddLocal(varName, expr.ResultType);

                    return varName;
                }
                else {
                    var op1 = _EmitExpression(expr.LeftNode, il);
                    var op2 = _EmitExpression(expr.RightNode, il);
                    string varName = GetVariableName();
                    var ilExpr = _constructBinaryExpressionFromVars(op1, op2, expr.OpType);
                    il.Add(_constructAssignExpression(varName, ilExpr));

                    CurrentFunction.AddLocal(varName, expr.ResultType);

                    return varName;
                }
            }

            throw new InvalidOperationException("Bad expression! " + expr.ToString());
        }
 private static string m_renderConst(Expression expr)
 {
     if (expr.ResultType == VariableType.IntType) {
         return Convert.ToString(expr.IntValue);
     }
     if (expr.ResultType == VariableType.BoolType) {
         if (expr.BoolValue) {
             return "T";
         } else {
             return "F";
         }
     }
     if (expr.ResultType == VariableType.NullType) {
         return "NULL";
     }
     if (expr.ResultType.Equals(VariableType.StrType)) {
         return "\"" + expr.Value.ToString() + "\"";
     }
     //TODO: Add array constants
     return "<<CONST>>";
 }
 //Prior(type) > Prior(subExpression.type), return false is subExpression is LEAF
 private static bool m_greaterPriority(OperationType type, Expression subExpression)
 {
     if (subExpression.IsLeaf) {
         return false;
     } else {
         int priorType = m_getPriority(type);
         int priorExpr = m_getPriority(subExpression.OpType);
         return priorType > priorExpr;
     }
 }
 private static string m_getPreparedString(OperationType opType, Expression expr)
 {
     if (m_greaterPriority(opType, expr))
         return "(" + expr.ToString() + ")";
     else
         return expr.ToString();
 }
        public static void EmitUnaryExpression(Expression expr, SymbolTable table, ILGenerator ilGen)
        {
            System.Diagnostics.Debug.Assert(expr.IsLeaf);

            #region Const

            if (expr.LeafType == ExpressionLeafType.Constant)
            {
                if (expr.ResultType.TypeEnum == VariableTypeEnum.Integer)
                {
                    ilGen.Emit(OpCodes.Ldc_I4, expr.IntValue);
                }
                if (expr.ResultType.TypeEnum == VariableTypeEnum.Char)
                {
                    ilGen.Emit(OpCodes.Ldc_I4, (int)expr.CharValue);
                }
                if (expr.ResultType.TypeEnum == VariableTypeEnum.Bool)
                {
                    ilGen.Emit(OpCodes.Ldc_I4, Convert.ToInt32(expr.BoolValue));
                }
                if (expr.ResultType.TypeEnum == VariableTypeEnum.Array)
                {
                    string s = expr.Value.ToString();
                    ilGen.Emit(OpCodes.Ldstr, s);
                    ilGen.Emit(OpCodes.Call, GetStrArr());
                }

                System.Diagnostics.Debug.Assert(expr.ResultType.TypeEnum != VariableTypeEnum.NULL);
                //System.Diagnostics.Debug.Assert(expr.ResultType.TypeEnum != VariableTypeEnum.Array);
            }

            #endregion

            #region Variable

            if (expr.LeafType == ExpressionLeafType.VariableAccess)
            {
                Symbol symbol = table.FindSymbol(expr.Value.ToString());
                if (symbol.IsParameter)
                {
                    ilGen.Emit(OpCodes.Ldarg, symbol.ParameterIndex);
                }
                else
                {
                    ilGen.Emit(OpCodes.Ldloc, symbol.LocalBuilder);
                }
            }

            #endregion

            #region FunctionCall

            if (expr.LeafType == ExpressionLeafType.FunctionCall)
            {
                List<VariableType> argumentTypes = new List<VariableType>();
                foreach (Expression e in expr.VAList)
                {
                    Type t = GetTypeForCompilerType(e.ResultType);
                    EmitExpression(e, table, ilGen);
                    argumentTypes.Add(e.ResultType);
                }
                MethodInfo mi = GetMethodForFunctionNameAndArgumentTypes(
                    expr.Value.ToString(),
                    argumentTypes.ToArray(),
                    expr.Location);
                ilGen.Emit(OpCodes.Call, mi);

                if (mi.ReturnType == typeof(void))
                    wasVoidFuncCalled = true;
            }

            #endregion

            #region New array

            if (expr.LeafType == ExpressionLeafType.ArrayAlloc)
            {
                Type arrayType = GetTypeForCompilerType(expr.ResultType);
                EmitExpression(expr.LeftNode, table, ilGen);
                ilGen.Emit(OpCodes.Newobj, GetArrayCtor(arrayType));
            }

            #endregion

            #region Array length

            if (expr.LeafType == ExpressionLeafType.ArrayLength)
            {
                Type arrayType = GetTypeForCompilerType(expr.LeftNode.ResultType);
                EmitExpression(expr.LeftNode, table, ilGen);
                ilGen.Emit(OpCodes.Call, GetArrayLengthGetter(arrayType));
            }

            #endregion
        }
        public static void EmitBinaryExpression(Expression expr, SymbolTable table, ILGenerator ilGen)
        {
            System.Diagnostics.Debug.Assert(!expr.IsLeaf);

            #region +

            if (expr.OpType == OperationType.Plus)
            {
                EmitExpression(expr.LeftNode, table, ilGen);
                EmitExpression(expr.RightNode, table, ilGen);
                ilGen.Emit(OpCodes.Add);
                if (expr.LeftNode.ResultType.TypeEnum == VariableTypeEnum.Char ||
                    expr.RightNode.ResultType.TypeEnum == VariableTypeEnum.Char)
                {
                    ilGen.Emit(OpCodes.Conv_U2);
                }
            }

            #endregion

            #region -

            if (expr.OpType == OperationType.Minus)
            {
                EmitExpression(expr.LeftNode, table, ilGen);
                EmitExpression(expr.RightNode, table, ilGen);
                ilGen.Emit(OpCodes.Sub);
                if (expr.LeftNode.ResultType.TypeEnum == VariableTypeEnum.Char)
                {
                    ilGen.Emit(OpCodes.Conv_U2);
                }
            }

            #endregion

            #region **, *, /, mod

            if (expr.OpType == OperationType.Power)
            {
                EmitExpression(expr.LeftNode, table, ilGen);
                EmitExpression(expr.RightNode, table, ilGen);
                ilGen.Emit(OpCodes.Call, GetDeg());
            }

            if (expr.OpType == OperationType.Mult)
            {
                EmitExpression(expr.LeftNode, table, ilGen);
                EmitExpression(expr.RightNode, table, ilGen);
                ilGen.Emit(OpCodes.Mul);
            }

            if (expr.OpType == OperationType.Div)
            {
                EmitExpression(expr.LeftNode, table, ilGen);
                EmitExpression(expr.RightNode, table, ilGen);
                ilGen.Emit(OpCodes.Div);
            }
            if (expr.OpType == OperationType.Mod)
            {
                EmitExpression(expr.LeftNode, table, ilGen);
                EmitExpression(expr.RightNode, table, ilGen);
                ilGen.Emit(OpCodes.Rem);
            }

            #endregion

            #region unary -

            if (expr.OpType == OperationType.UMinus)
            {
                EmitExpression(expr.LeftNode, table, ilGen);
                ilGen.Emit(OpCodes.Neg);
            }

            #endregion

            #region unary not

            if (expr.OpType == OperationType.UNot)
            {
                EmitExpression(expr.LeftNode, table, ilGen);
                //ilGen.Emit(OpCodes.Not);
                ilGen.Emit(OpCodes.Ldc_I4_0);
                ilGen.Emit(OpCodes.Ceq);
            }

            #endregion

            #region and, or, xor

            if (expr.OpType == OperationType.And)
            {
                Label label = ilGen.DefineLabel();
                EmitExpression(expr.LeftNode, table, ilGen);
                ilGen.Emit(OpCodes.Dup);
                ilGen.Emit(OpCodes.Brfalse, label);
                EmitExpression(expr.RightNode, table, ilGen);
                ilGen.Emit(OpCodes.And);
                ilGen.MarkLabel(label);
            }

            if (expr.OpType == OperationType.Or)
            {
                Label label = ilGen.DefineLabel();
                EmitExpression(expr.LeftNode, table, ilGen);
                ilGen.Emit(OpCodes.Dup);
                ilGen.Emit(OpCodes.Brtrue, label);
                EmitExpression(expr.RightNode, table, ilGen);
                ilGen.Emit(OpCodes.Or);
                ilGen.MarkLabel(label);
            }

            if (expr.OpType == OperationType.Xor)
            {
                EmitExpression(expr.LeftNode, table, ilGen);
                EmitExpression(expr.RightNode, table, ilGen);
                ilGen.Emit(OpCodes.Xor);
            }

            #endregion

            #region <, >, <=, >=

            if (expr.OpType == OperationType.Le)
            {
                EmitExpression(expr.LeftNode, table, ilGen);
                EmitExpression(expr.RightNode, table, ilGen);
                ilGen.Emit(OpCodes.Clt);
            }

            if (expr.OpType == OperationType.Leeq)
            {
                EmitExpression(expr.LeftNode, table, ilGen);
                EmitExpression(expr.RightNode, table, ilGen);
                ilGen.Emit(OpCodes.Cgt);
                ilGen.Emit(OpCodes.Ldc_I4_0);
                ilGen.Emit(OpCodes.Ceq);
            }

            if (expr.OpType == OperationType.Gr)
            {
                EmitExpression(expr.LeftNode, table, ilGen);
                EmitExpression(expr.RightNode, table, ilGen);
                ilGen.Emit(OpCodes.Cgt);
            }

            if (expr.OpType == OperationType.Greq)
            {
                EmitExpression(expr.LeftNode, table, ilGen);
                EmitExpression(expr.RightNode, table, ilGen);
                ilGen.Emit(OpCodes.Clt);
                ilGen.Emit(OpCodes.Ldc_I4_0);
                ilGen.Emit(OpCodes.Ceq);
            }

            #endregion

            #region =, <>

            if (expr.OpType == OperationType.Equals)
            {
                if (expr.LeftNode.ResultType.TypeEnum == VariableTypeEnum.NULL &&
                    expr.RightNode.ResultType.TypeEnum == VariableTypeEnum.NULL)
                {
                    ilGen.Emit(OpCodes.Ldc_I4_1);
                }
                else if (expr.LeftNode.ResultType.TypeEnum == VariableTypeEnum.NULL)
                {
                    Type arrayType = GetTypeForCompilerType(expr.RightNode.ResultType);
                    EmitExpression(expr.RightNode, table, ilGen);
                    ilGen.Emit(OpCodes.Call, GetArrayNullGetter(arrayType));
                    ilGen.Emit(OpCodes.Ceq);
                }
                else if (expr.RightNode.ResultType.TypeEnum == VariableTypeEnum.NULL)
                {
                    Type arrayType = GetTypeForCompilerType(expr.LeftNode.ResultType);
                    EmitExpression(expr.LeftNode, table, ilGen);
                    ilGen.Emit(OpCodes.Call, GetArrayNullGetter(arrayType));
                    ilGen.Emit(OpCodes.Ceq);
                }
                else
                {
                    EmitExpression(expr.LeftNode, table, ilGen);
                    EmitExpression(expr.RightNode, table, ilGen);
                    ilGen.Emit(OpCodes.Ceq);
                }
            }

            if (expr.OpType == OperationType.NotEquals)
            {
                if (expr.LeftNode.ResultType.TypeEnum == VariableTypeEnum.NULL &&
                    expr.RightNode.ResultType.TypeEnum == VariableTypeEnum.NULL)
                {
                    ilGen.Emit(OpCodes.Ldc_I4_1);
                }
                else if (expr.LeftNode.ResultType.TypeEnum == VariableTypeEnum.NULL)
                {
                    Type arrayType = GetTypeForCompilerType(expr.RightNode.ResultType);
                    EmitExpression(expr.RightNode, table, ilGen);
                    ilGen.Emit(OpCodes.Call, GetArrayNullGetter(arrayType));
                    ilGen.Emit(OpCodes.Ceq);
                }
                else if (expr.RightNode.ResultType.TypeEnum == VariableTypeEnum.NULL)
                {
                    Type arrayType = GetTypeForCompilerType(expr.LeftNode.ResultType);
                    EmitExpression(expr.LeftNode, table, ilGen);
                    ilGen.Emit(OpCodes.Call, GetArrayNullGetter(arrayType));
                    ilGen.Emit(OpCodes.Ceq);
                }
                else
                {
                    EmitExpression(expr.LeftNode, table, ilGen);
                    EmitExpression(expr.RightNode, table, ilGen);
                    ilGen.Emit(OpCodes.Ceq);
                }
                ilGen.Emit(OpCodes.Ldc_I4_0);
                ilGen.Emit(OpCodes.Ceq);
            }

            #endregion

            #region []

            if (expr.OpType == OperationType.ArrayAccess)
            {
                Type arrayType = GetTypeForCompilerType(expr.LeftNode.ResultType);
                EmitExpression(expr.LeftNode, table, ilGen);
                EmitExpression(expr.RightNode, table, ilGen);
                ilGen.Emit(OpCodes.Call, GetArrayGetter(arrayType));
            }

            #endregion

            #region Assign

            if (expr.OpType == OperationType.Assign)
            {
                if (expr.LeftNode.OpType == OperationType.ArrayAccess)
                {
                    Type arrayType = GetTypeForCompilerType(expr.LeftNode.LeftNode.ResultType);
                    //Array
                    EmitExpression(expr.LeftNode.LeftNode, table, ilGen);
                    //Index
                    EmitExpression(expr.LeftNode.RightNode, table, ilGen);
                    //Value
                    EmitExpression(expr.RightNode, table, ilGen);
                    //Setter call
                    ilGen.Emit(OpCodes.Call, GetArraySetter(arrayType));
                    //Banditism: after setter call - there is specified value on the stack's top
                }
                else if (expr.LeftNode.LeafType == ExpressionLeafType.VariableAccess)
                {
                    Symbol symbol = table.FindSymbol(expr.LeftNode.Value.ToString());
                    //Reight part
                    if (expr.RightNode.ResultType.TypeEnum == VariableTypeEnum.NULL)
                    {
                        ilGen.Emit(OpCodes.Call, GetArrayNullGetter(symbol.Type));
                        ilGen.Emit(OpCodes.Dup);
                    }
                    else
                    {
                        EmitExpression(expr.RightNode, table, ilGen);
                        ilGen.Emit(OpCodes.Dup);
                    }
                    //Setter for variable
                    if (symbol.IsParameter)
                    {
                        ilGen.Emit(OpCodes.Starg, symbol.ParameterIndex);
                    }
                    else
                    {
                        ilGen.Emit(OpCodes.Stloc, symbol.LocalBuilder);
                    }
                }
                else
                {
                    System.Diagnostics.Debug.Fail("Bad compiler error: bad assign construction");
                }
            }

            #endregion
        }
 public static void EmitExpression(Expression expr, SymbolTable table, ILGenerator ilGen)
 {
     if (expr.IsLeaf)
     {
         EmitUnaryExpression(expr, table, ilGen);
     }
     else
     {
         EmitBinaryExpression(expr, table, ilGen);
     }
 }