/// <summary> /// Generates CIL for the addition operation. /// </summary> /// <param name="generator"> The generator to output the CIL to. </param> /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param> private void GenerateAdd(ILGenerator generator, OptimizationInfo optimizationInfo) { // Get the statically-determined types of the left and right operands. Type leftType = this.Left.GetResultType(optimizationInfo); Type rightType = this.Right.GetResultType(optimizationInfo); // The add operator adds two strings together if at least one of the operands // is a string, otherwise it adds two numbers. if (PrimitiveTypeUtilities.IsString(leftType) || PrimitiveTypeUtilities.IsString(rightType)) { // If at least one of the operands is a string, then the add operator concatenates. // Load the left-hand side onto the stack. this.Left.GenerateCode(generator, optimizationInfo); // Convert the operand to a concatenated string. EmitConversion.ToPrimitive(generator, leftType, PrimitiveTypeHint.None); EmitConversion.ToConcatenatedString(generator, leftType); // Load the right-hand side onto the stack. this.Right.GenerateCode(generator, optimizationInfo); if (rightType == typeof(string)) { // Concatenate the two strings. generator.Call(ReflectionHelpers.ConcatenatedString_Concatenate_String); } else if (rightType == typeof(ConcatenatedString)) { // Concatenate the two strings. generator.Call(ReflectionHelpers.ConcatenatedString_Concatenate_ConcatenatedString); } else { // Convert the operand to an object. EmitConversion.ToPrimitive(generator, rightType, PrimitiveTypeHint.None); EmitConversion.ToAny(generator, rightType); // Concatenate the two strings. generator.Call(ReflectionHelpers.ConcatenatedString_Concatenate_Object); } } else if (leftType != typeof(object) && leftType != typeof(Library.ObjectInstance) && rightType != typeof(object) && rightType != typeof(Library.ObjectInstance)) { // Neither of the operands are strings. // If the two types are numeric integers, retain the one with the most accuracy. Type numeric = TypeConverter.MostAccurateInteger(leftType, rightType); if (numeric == null) { // Load the left hand side onto the stack. this.Left.GenerateCode(generator, optimizationInfo); // Convert the operand to a number. EmitConversion.ToNumber(generator, leftType); // Load the right hand side onto the stack. this.Right.GenerateCode(generator, optimizationInfo); // Convert the operand to a number. EmitConversion.ToNumber(generator, rightType); // Add the two numbers. generator.Add(); } else { // Use them both converted to 'numeric' // Load the left hand side onto the stack. this.Left.GenerateCode(generator, optimizationInfo); // Convert the operand to a number. EmitConversion.ToNumber(generator, leftType, numeric); // Load the right hand side onto the stack. this.Right.GenerateCode(generator, optimizationInfo); // Convert the operand to a number. EmitConversion.ToNumber(generator, rightType, numeric); // Add the two numbers. generator.Add(); } } else { // It is unknown whether the operands are strings. // Load the left hand side onto the stack. this.Left.GenerateCode(generator, optimizationInfo); EmitConversion.ToAny(generator, leftType); // Load the right hand side onto the stack. this.Right.GenerateCode(generator, optimizationInfo); EmitConversion.ToAny(generator, rightType); // Add the two objects. generator.Call(ReflectionHelpers.TypeUtilities_Add); } }