TranslateToStringWithSpecialCaseForNull() private static method

private static TranslateToStringWithSpecialCaseForNull ( ILGenerator il, AST operand ) : void
il System.Reflection.Emit.ILGenerator
operand AST
return void
        private int TranslateToILArrayOfStrings(ILGenerator il, int n)
        {
            int len = n + 2;

            if (this.operand1 is Plus && this.type1 == Typeob.String)
            {
                len = ((Plus)this.operand1).TranslateToILArrayOfStrings(il, n + 1);
            }
            else
            {
                ConstantWrapper.TranslateToILInt(il, len);
                il.Emit(OpCodes.Newarr, Typeob.String);
                il.Emit(OpCodes.Dup);
                il.Emit(OpCodes.Ldc_I4_0);
                Plus.TranslateToStringWithSpecialCaseForNull(il, this.operand1);
                il.Emit(OpCodes.Stelem_Ref);
            }
            il.Emit(OpCodes.Dup);
            ConstantWrapper.TranslateToILInt(il, len - 1 - n);
            Plus.TranslateToStringWithSpecialCaseForNull(il, this.operand2);
            il.Emit(OpCodes.Stelem_Ref);
            return(len);
        }
        internal override void TranslateToIL(ILGenerator il, Type rtype)
        {
            Type type = Convert.ToType(this.InferType(null));

            if (this.metaData == null)
            {
                Type rt = Typeob.Object;
                if (rtype == Typeob.Double)
                {
                    rt = rtype;
                }
                else if (this.type1 == Typeob.Char && this.type2 == Typeob.Char)
                {
                    rt = Typeob.String;
                }
                else if (Convert.IsPrimitiveNumericType(rtype) && Convert.IsPromotableTo(this.type1, rtype) && Convert.IsPromotableTo(this.type2, rtype))
                {
                    rt = rtype;
                }
                else if (this.type1 != Typeob.String && this.type2 != Typeob.String) //Both will be converted to numbers
                {
                    rt = Typeob.Double;                                              //Won't get here unless InferType returned Typeob.Double.
                }
                else
                {
                    rt = Typeob.String;
                }
                if (rt == Typeob.SByte || rt == Typeob.Int16)
                {
                    rt = Typeob.Int32;
                }
                else if (rt == Typeob.Byte || rt == Typeob.UInt16 || rt == Typeob.Char)
                {
                    rt = Typeob.UInt32;
                }
                if (rt == Typeob.String)
                {
                    if (this.operand1 is Plus && this.type1 == rt)
                    {
                        Plus op1 = (Plus)this.operand1;
                        if (op1.operand1 is Plus && op1.type1 == rt)
                        {
                            Plus op11 = (Plus)op1.operand1;
                            if (op11.operand1 is Plus && op11.type1 == rt)
                            {
                                int len = op1.TranslateToILArrayOfStrings(il, 1);
                                il.Emit(OpCodes.Dup);
                                ConstantWrapper.TranslateToILInt(il, len - 1);
                                this.operand2.TranslateToIL(il, rt);
                                il.Emit(OpCodes.Stelem_Ref);
                                il.Emit(OpCodes.Call, CompilerGlobals.stringConcatArrMethod);
                                Convert.Emit(this, il, rt, rtype);
                                return;
                            }
                            Plus.TranslateToStringWithSpecialCaseForNull(il, op11.operand1);
                            Plus.TranslateToStringWithSpecialCaseForNull(il, op11.operand2);
                            Plus.TranslateToStringWithSpecialCaseForNull(il, op1.operand2);
                            Plus.TranslateToStringWithSpecialCaseForNull(il, this.operand2);
                            il.Emit(OpCodes.Call, CompilerGlobals.stringConcat4Method);
                            Convert.Emit(this, il, rt, rtype);
                            return;
                        }
                        Plus.TranslateToStringWithSpecialCaseForNull(il, op1.operand1);
                        Plus.TranslateToStringWithSpecialCaseForNull(il, op1.operand2);
                        Plus.TranslateToStringWithSpecialCaseForNull(il, this.operand2);
                        il.Emit(OpCodes.Call, CompilerGlobals.stringConcat3Method);
                        Convert.Emit(this, il, rt, rtype);
                        return;
                    }
                    Plus.TranslateToStringWithSpecialCaseForNull(il, this.operand1);
                    Plus.TranslateToStringWithSpecialCaseForNull(il, this.operand2);
                    il.Emit(OpCodes.Call, CompilerGlobals.stringConcat2Method);
                    Convert.Emit(this, il, rt, rtype);
                    return;
                }
                this.operand1.TranslateToIL(il, rt);
                this.operand2.TranslateToIL(il, rt);
                if (rt == Typeob.Object)
                {
                    il.Emit(OpCodes.Call, CompilerGlobals.plusDoOpMethod);
                }
                else if (rt == Typeob.Double || rt == Typeob.Single)
                {
                    il.Emit(OpCodes.Add);
                }
                else if (rt == Typeob.Int32 || rt == Typeob.Int64)
                {
                    il.Emit(OpCodes.Add_Ovf);
                }
                else
                {
                    il.Emit(OpCodes.Add_Ovf_Un);
                }

                if (type == Typeob.Char)
                {
                    Convert.Emit(this, il, rt, Typeob.Char);
                    Convert.Emit(this, il, Typeob.Char, rtype);
                }
                else
                {
                    Convert.Emit(this, il, rt, rtype);
                }
                return;
            }
            if (this.metaData is MethodInfo)
            {
                MethodInfo      oper = (MethodInfo)this.metaData;
                ParameterInfo[] pars = oper.GetParameters();
                this.operand1.TranslateToIL(il, pars[0].ParameterType);
                this.operand2.TranslateToIL(il, pars[1].ParameterType);
                il.Emit(OpCodes.Call, oper);
                Convert.Emit(this, il, oper.ReturnType, rtype);
                return;
            }
            //Getting here is just too bad. We do not know until the code runs whether or not to call an overloaded operator method.
            //Compile operands to objects and devolve the decision making to run time thunks
            //Also get here when dealing with Int64 and UInt64. These cannot always be converted to doubles. The late-bound code checks for this.
            il.Emit(OpCodes.Ldloc, (LocalBuilder)this.metaData);
            this.operand1.TranslateToIL(il, Typeob.Object);
            this.operand2.TranslateToIL(il, Typeob.Object);
            il.Emit(OpCodes.Callvirt, CompilerGlobals.evaluatePlusMethod);
            Convert.Emit(this, il, Typeob.Object, rtype);
        }