Inheritance: BinaryOp
 internal EnumDeclaration(Context context, IdentifierLiteral id, TypeExpression baseType, Block body, FieldAttributes attributes, CustomAttributeList customAttributes) : base(context, id, new TypeExpression(new ConstantWrapper(Typeob.Enum, null)), new TypeExpression[0], body, attributes, false, false, true, false, customAttributes)
 {
     this.baseType = (baseType != null) ? baseType : new TypeExpression(new ConstantWrapper(Typeob.Int32, null));
     base.needsEngine = false;
     base.attributes &= TypeAttributes.NestedFamORAssem;
     TypeExpression expression = new TypeExpression(new ConstantWrapper(base.classob, base.context));
     AST ast = new ConstantWrapper(-1, null);
     AST ast2 = new ConstantWrapper(1, null);
     JSMemberField[] fields = base.fields;
     for (int i = 0; i < fields.Length; i++)
     {
         FieldInfo info = fields[i];
         JSVariableField field = (JSVariableField) info;
         field.attributeFlags = FieldAttributes.Literal | FieldAttributes.Static | FieldAttributes.Public;
         field.type = expression;
         if (field.value == null)
         {
             field.value = ast = new Plus(ast.context, ast, ast2);
         }
         else
         {
             ast = (AST) field.value;
         }
         field.value = new DeclaredEnumValue(field.value, field.Name, base.classob);
     }
 }
 internal override AST PartiallyEvaluate(){
   this.operand1 = this.operand1.PartiallyEvaluateAsReference();
   this.operand2 = this.operand2.PartiallyEvaluate();
   this.binOp = new Plus(this.context, this.operand1, this.operand2);
   this.operand1.SetPartialValue(this.binOp);
   if (this.Engine.doFast){
     Binding b = this.operand1 as Binding;
     if (b != null && b.member is JSVariableField){
       TypeExpression te = ((JSVariableField)b.member).type;
       if (te != null && te.InferType(null) == Typeob.String)
         this.operand1.context.HandleError(JSError.StringConcatIsSlow);
     }
   }
   return this;
 }
Example #3
0
 internal EnumDeclaration(Context context, IdentifierLiteral id, TypeExpression baseType, Block body, FieldAttributes attributes, CustomAttributeList customAttributes)
   : base(context, id, new TypeExpression(new ConstantWrapper(typeof(Enum), null)), new TypeExpression[0], body, attributes, false, false, true, false, customAttributes){
   this.baseType = baseType != null ? baseType : new TypeExpression(new ConstantWrapper(Typeob.Int32, null));
   this.needsEngine = false;
   this.attributes &= TypeAttributes.VisibilityMask;
   TypeExpression thisType = new TypeExpression(new ConstantWrapper(this.classob, this.context));
   AST currentValue = new ConstantWrapper(-1, null);
   AST one = new ConstantWrapper(1, null);
   foreach (FieldInfo f in this.fields){
     JSVariableField field = (JSVariableField)f;
     field.attributeFlags = FieldAttributes.Public|FieldAttributes.Static|FieldAttributes.Literal;
     field.type = thisType;
     if (field.value == null)
       field.value = currentValue = new Plus(currentValue.context, currentValue, one);
     else
       currentValue = (AST)field.value;
     field.value = new EnumWrapper(field.value, field.Name, this.classob);
   }
 }
 internal override AST PartiallyEvaluate()
 {
     base.operand1 = base.operand1.PartiallyEvaluateAsReference();
     base.operand2 = base.operand2.PartiallyEvaluate();
     this.binOp = new Plus(base.context, base.operand1, base.operand2);
     base.operand1.SetPartialValue(this.binOp);
     if (base.Engine.doFast)
     {
         Binding binding = base.operand1 as Binding;
         if ((binding != null) && (binding.member is JSVariableField))
         {
             TypeExpression type = ((JSVariableField) binding.member).type;
             if ((type != null) && (type.InferType(null) == Typeob.String))
             {
                 base.operand1.context.HandleError(JSError.StringConcatIsSlow);
             }
         }
     }
     return this;
 }
 internal PlusAssign(Context context, AST operand1, AST operand2) : base(context, operand1, operand2, JSToken.FirstBinaryOp)
 {
     this.binOp = new Plus(context, operand1, operand2);
     this.metaData = null;
 }
 internal PlusAssign(Context context, AST operand1, AST operand2) : base(context, operand1, operand2, JSToken.FirstBinaryOp)
 {
     this.binOp    = new Plus(context, operand1, operand2);
     this.metaData = null;
 }
        internal override void TranslateToIL(ILGenerator il, Type rtype)
        {
            Type type = Microsoft.JScript.Convert.ToType(this.InferType(null));

            if (this.metaData == null)
            {
                Type type2 = Typeob.Object;
                if (rtype == Typeob.Double)
                {
                    type2 = rtype;
                }
                else if ((base.type1 == Typeob.Char) && (base.type2 == Typeob.Char))
                {
                    type2 = Typeob.String;
                }
                else if ((Microsoft.JScript.Convert.IsPrimitiveNumericType(rtype) && Microsoft.JScript.Convert.IsPromotableTo((IReflect)base.type1, (IReflect)rtype)) && Microsoft.JScript.Convert.IsPromotableTo((IReflect)base.type2, (IReflect)rtype))
                {
                    type2 = rtype;
                }
                else if ((base.type1 != Typeob.String) && (base.type2 != Typeob.String))
                {
                    type2 = Typeob.Double;
                }
                else
                {
                    type2 = Typeob.String;
                }
                if ((type2 == Typeob.SByte) || (type2 == Typeob.Int16))
                {
                    type2 = Typeob.Int32;
                }
                else if (((type2 == Typeob.Byte) || (type2 == Typeob.UInt16)) || (type2 == Typeob.Char))
                {
                    type2 = Typeob.UInt32;
                }
                if (type2 == Typeob.String)
                {
                    if ((base.operand1 is Plus) && (base.type1 == type2))
                    {
                        Plus plus = (Plus)base.operand1;
                        if ((plus.operand1 is Plus) && (plus.type1 == type2))
                        {
                            Plus plus2 = (Plus)plus.operand1;
                            if ((plus2.operand1 is Plus) && (plus2.type1 == type2))
                            {
                                int num = plus.TranslateToILArrayOfStrings(il, 1);
                                il.Emit(OpCodes.Dup);
                                ConstantWrapper.TranslateToILInt(il, num - 1);
                                base.operand2.TranslateToIL(il, type2);
                                il.Emit(OpCodes.Stelem_Ref);
                                il.Emit(OpCodes.Call, CompilerGlobals.stringConcatArrMethod);
                                Microsoft.JScript.Convert.Emit(this, il, type2, rtype);
                            }
                            else
                            {
                                TranslateToStringWithSpecialCaseForNull(il, plus2.operand1);
                                TranslateToStringWithSpecialCaseForNull(il, plus2.operand2);
                                TranslateToStringWithSpecialCaseForNull(il, plus.operand2);
                                TranslateToStringWithSpecialCaseForNull(il, base.operand2);
                                il.Emit(OpCodes.Call, CompilerGlobals.stringConcat4Method);
                                Microsoft.JScript.Convert.Emit(this, il, type2, rtype);
                            }
                        }
                        else
                        {
                            TranslateToStringWithSpecialCaseForNull(il, plus.operand1);
                            TranslateToStringWithSpecialCaseForNull(il, plus.operand2);
                            TranslateToStringWithSpecialCaseForNull(il, base.operand2);
                            il.Emit(OpCodes.Call, CompilerGlobals.stringConcat3Method);
                            Microsoft.JScript.Convert.Emit(this, il, type2, rtype);
                        }
                    }
                    else
                    {
                        TranslateToStringWithSpecialCaseForNull(il, base.operand1);
                        TranslateToStringWithSpecialCaseForNull(il, base.operand2);
                        il.Emit(OpCodes.Call, CompilerGlobals.stringConcat2Method);
                        Microsoft.JScript.Convert.Emit(this, il, type2, rtype);
                    }
                }
                else
                {
                    base.operand1.TranslateToIL(il, type2);
                    base.operand2.TranslateToIL(il, type2);
                    if (type2 == Typeob.Object)
                    {
                        il.Emit(OpCodes.Call, CompilerGlobals.plusDoOpMethod);
                    }
                    else if ((type2 == Typeob.Double) || (type2 == Typeob.Single))
                    {
                        il.Emit(OpCodes.Add);
                    }
                    else if ((type2 == Typeob.Int32) || (type2 == Typeob.Int64))
                    {
                        il.Emit(OpCodes.Add_Ovf);
                    }
                    else
                    {
                        il.Emit(OpCodes.Add_Ovf_Un);
                    }
                    if (type == Typeob.Char)
                    {
                        Microsoft.JScript.Convert.Emit(this, il, type2, Typeob.Char);
                        Microsoft.JScript.Convert.Emit(this, il, Typeob.Char, rtype);
                    }
                    else
                    {
                        Microsoft.JScript.Convert.Emit(this, il, type2, rtype);
                    }
                }
            }
            else if (this.metaData is MethodInfo)
            {
                MethodInfo      metaData   = (MethodInfo)this.metaData;
                ParameterInfo[] parameters = metaData.GetParameters();
                base.operand1.TranslateToIL(il, parameters[0].ParameterType);
                base.operand2.TranslateToIL(il, parameters[1].ParameterType);
                il.Emit(OpCodes.Call, metaData);
                Microsoft.JScript.Convert.Emit(this, il, metaData.ReturnType, rtype);
            }
            else
            {
                il.Emit(OpCodes.Ldloc, (LocalBuilder)this.metaData);
                base.operand1.TranslateToIL(il, Typeob.Object);
                base.operand2.TranslateToIL(il, Typeob.Object);
                il.Emit(OpCodes.Callvirt, CompilerGlobals.evaluatePlusMethod);
                Microsoft.JScript.Convert.Emit(this, il, Typeob.Object, rtype);
            }
        }
Example #8
0
        private Object EvaluatePlus2(Object v1, Object v2)
        {
            IConvertible ic1 = Convert.GetIConvertible(v1);
            IConvertible ic2 = Convert.GetIConvertible(v2);
            TypeCode     t1  = Convert.GetTypeCode(v1, ic1);
            TypeCode     t2  = Convert.GetTypeCode(v2, ic2);

            switch (t1)
            {
            case TypeCode.Empty:
                return(Plus.DoOp(v1, v2));

            case TypeCode.DBNull:
                switch (t2)
                {
                case TypeCode.Empty:
                    return(Double.NaN);

                case TypeCode.DBNull:
                    return(0);

                case TypeCode.Boolean:
                case TypeCode.Char:
                case TypeCode.SByte:
                case TypeCode.Byte:
                case TypeCode.Int16:
                case TypeCode.UInt16:
                case TypeCode.Int32:
                    return(ic2.ToInt32(null));

                case TypeCode.UInt32:
                    return(ic2.ToUInt32(null));

                case TypeCode.Int64:
                    return(ic2.ToInt64(null));

                case TypeCode.UInt64:
                    return(ic2.ToUInt64(null));

                case TypeCode.Single:
                case TypeCode.Double:
                    return(ic2.ToDouble(null));

                case TypeCode.Object:
                case TypeCode.Decimal:
                case TypeCode.DateTime:
                    break;

                case TypeCode.String:
                    return("null" + ic2.ToString(null));
                }
                break;

            case TypeCode.Char:
            { int val = ic1.ToInt32(null);
              switch (t2)
              {
              case TypeCode.Empty:
                  return(Double.NaN);

              case TypeCode.DBNull:
                  return(val);

              case TypeCode.Boolean:
              case TypeCode.SByte:
              case TypeCode.Byte:
              case TypeCode.Int16:
              case TypeCode.UInt16:
              case TypeCode.Int32:
                  return(((IConvertible)Plus.DoOp(val, ic2.ToInt32(null))).ToChar(null));

              case TypeCode.UInt32:
              case TypeCode.Int64:
                  return(((IConvertible)Plus.DoOp((long)val, ic2.ToInt64(null))).ToChar(null));

              case TypeCode.UInt64:
                  return(((IConvertible)Plus.DoOp((ulong)val, ic2.ToUInt64(null))).ToChar(null));

              case TypeCode.Single:
              case TypeCode.Double:
                  checked { return((char)(int)(Convert.CheckIfDoubleIsInteger((double)Plus.DoOp((double)val, ic2.ToDouble(null))))); }

              case TypeCode.Object:
              case TypeCode.Decimal:
              case TypeCode.DateTime:
                  return(Plus.DoOp(v1, v2));

              case TypeCode.Char:
              case TypeCode.String:
                  return(ic1.ToString(null) + ic2.ToString(null));
              }
              break; }

            case TypeCode.Boolean:
            case TypeCode.SByte:
            case TypeCode.Byte:
            case TypeCode.Int16:
            case TypeCode.UInt16:
            case TypeCode.Int32:
            { int val = ic1.ToInt32(null);
              switch (t2)
              {
              case TypeCode.Empty:
                  return(Double.NaN);

              case TypeCode.DBNull:
                  return(val);

              case TypeCode.Char:
                  return(((IConvertible)Plus.DoOp(val, ic2.ToInt32(null))).ToChar(null));

              case TypeCode.Boolean:
              case TypeCode.SByte:
              case TypeCode.Byte:
              case TypeCode.Int16:
              case TypeCode.UInt16:
              case TypeCode.Int32:
                  return(Plus.DoOp(val, ic2.ToInt32(null)));

              case TypeCode.UInt32:
              case TypeCode.Int64:
                  return(Plus.DoOp((long)val, ic2.ToInt64(null)));

              case TypeCode.UInt64:
                  if (val >= 0)
                  {
                      return(Plus.DoOp((ulong)val, ic2.ToUInt64(null)));
                  }
                  else
                  {
                      return(Plus.DoOp((double)val, ic2.ToDouble(null)));
                  }

              case TypeCode.Single:
              case TypeCode.Double:
                  return(Plus.DoOp((double)val, ic2.ToDouble(null)));

              case TypeCode.Object:
              case TypeCode.Decimal:
              case TypeCode.DateTime:
                  break;

              case TypeCode.String:
                  return(Convert.ToString(v1) + ic2.ToString(null));
              }
              break; }

            case TypeCode.UInt32:
            { uint val = ic1.ToUInt32(null);
              switch (t2)
              {
              case TypeCode.Empty:
                  return(Double.NaN);

              case TypeCode.DBNull:
                  return(val);

              case TypeCode.SByte:
              case TypeCode.Byte:
              case TypeCode.Int16:
              case TypeCode.Int32:
                  int val2 = ic2.ToInt32(null);
                  if (val2 >= 0)
                  {
                      return(Plus.DoOp(val, (uint)val2));
                  }
                  else
                  {
                      return(Plus.DoOp((long)val, (long)val2));
                  }

              case TypeCode.Int64:
                  return(Plus.DoOp((long)val, ic2.ToInt64(null)));

              case TypeCode.Char:
                  return(((IConvertible)Plus.DoOp(val, ic2.ToUInt32(null))).ToChar(null));

              case TypeCode.Boolean:
              case TypeCode.UInt16:
              case TypeCode.UInt32:
                  return(Plus.DoOp(val, ic2.ToUInt32(null)));

              case TypeCode.UInt64:
                  return(Plus.DoOp((ulong)val, ic2.ToUInt64(null)));

              case TypeCode.Single:
              case TypeCode.Double:
                  return(Plus.DoOp((double)val, ic2.ToDouble(null)));

              case TypeCode.Object:
              case TypeCode.Decimal:
              case TypeCode.DateTime:
                  break;

              case TypeCode.String:
                  return(Convert.ToString(v1) + ic2.ToString(null));
              }
              break; }

            case TypeCode.Int64:
            { long val = ic1.ToInt64(null);
              switch (t2)
              {
              case TypeCode.Empty:
                  return(Double.NaN);

              case TypeCode.DBNull:
                  return(val);

              case TypeCode.Char:
                  return(((IConvertible)Plus.DoOp(val, ic2.ToInt64(null))).ToChar(null));

              case TypeCode.Boolean:
              case TypeCode.SByte:
              case TypeCode.Byte:
              case TypeCode.Int16:
              case TypeCode.UInt16:
              case TypeCode.Int32:
              case TypeCode.UInt32:
              case TypeCode.Int64:
                  return(Plus.DoOp(val, ic2.ToInt64(null)));

              case TypeCode.UInt64:
                  if (val >= 0)
                  {
                      return(Plus.DoOp((ulong)val, ic2.ToUInt64(null)));
                  }
                  else
                  {
                      return(Plus.DoOp((double)val, ic2.ToDouble(null)));
                  }

              case TypeCode.Single:
              case TypeCode.Double:
                  return(Plus.DoOp((double)val, ic2.ToDouble(null)));

              case TypeCode.Object:
              case TypeCode.Decimal:
              case TypeCode.DateTime:
                  break;

              case TypeCode.String:
                  return(Convert.ToString(v1) + ic2.ToString(null));
              }
              break; }

            case TypeCode.UInt64:
            { ulong val = ic1.ToUInt64(null);
              switch (t2)
              {
              case TypeCode.Empty:
                  return(Double.NaN);

              case TypeCode.DBNull:
                  return(val);

              case TypeCode.SByte:
              case TypeCode.Byte:
              case TypeCode.Int16:
              case TypeCode.Int32:
              case TypeCode.Int64:
                  long val2 = ic2.ToInt64(null);
                  if (val2 >= 0)
                  {
                      return(Plus.DoOp(val, (ulong)val2));
                  }
                  else
                  {
                      return(Plus.DoOp((double)val, (double)val2));
                  }

              case TypeCode.Char:
                  return(((IConvertible)Plus.DoOp(val, ic2.ToUInt64(null))).ToChar(null));

              case TypeCode.UInt16:
              case TypeCode.Boolean:
              case TypeCode.UInt32:
              case TypeCode.UInt64:
                  return(Plus.DoOp(val, ic2.ToUInt64(null)));

              case TypeCode.Single:
              case TypeCode.Double:
                  return(Plus.DoOp((double)val, ic2.ToDouble(null)));

              case TypeCode.Object:
              case TypeCode.Decimal:
              case TypeCode.DateTime:
                  break;

              case TypeCode.String:
                  return(Convert.ToString(v1) + ic2.ToString(null));
              }
              break; }

            case TypeCode.Single:
            case TypeCode.Double: {
                double d = ic1.ToDouble(null);
                switch (t2)
                {
                case TypeCode.Empty:
                    return(Double.NaN);

                case TypeCode.DBNull:
                    return(ic1.ToDouble(null));

                case TypeCode.Char:
                    return(System.Convert.ToChar(System.Convert.ToInt32((d + (double)ic2.ToInt32(null)))));

                case TypeCode.Boolean:
                case TypeCode.SByte:
                case TypeCode.Byte:
                case TypeCode.Int16:
                case TypeCode.UInt16:
                case TypeCode.Int32:
                    return(d + (double)ic2.ToInt32(null));

                case TypeCode.UInt32:
                case TypeCode.Int64:
                case TypeCode.UInt64:
                case TypeCode.Single:
                case TypeCode.Double:
                    return(d + ic2.ToDouble(null));

                case TypeCode.Object:
                case TypeCode.Decimal:
                case TypeCode.DateTime:
                    break;

                case TypeCode.String:
                    return(new ConcatString(Convert.ToString(d), ic2.ToString(null)));
                }
                break;
            }

            case TypeCode.Object:
            case TypeCode.Decimal:
            case TypeCode.DateTime:
                break;

            case TypeCode.String:
                switch (t2)
                {
                case TypeCode.Object:
                    break;

                case TypeCode.String:
                    if (v1 is ConcatString)
                    {
                        return(new ConcatString((ConcatString)v1, ic2.ToString(null)));
                    }
                    else
                    {
                        return(new ConcatString(ic1.ToString(null), ic2.ToString(null)));
                    }

                default:
                    if (v1 is ConcatString)
                    {
                        return(new ConcatString((ConcatString)v1, Convert.ToString(v2)));
                    }
                    else
                    {
                        return(new ConcatString(ic1.ToString(null), Convert.ToString(v2)));
                    }
                }
                break;
            }
            MethodInfo oper = this.GetOperator(v1 == null ? Typeob.Empty : v1.GetType(), v2 == null ? Typeob.Empty : v2.GetType());

            if (oper != null)
            {
                return(oper.Invoke(null, (BindingFlags)0, JSBinder.ob, new Object[] { v1, v2 }, null));
            }
            else
            {
                return(Plus.DoOp(v1, v2));
            }
        }
Example #9
0
        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);
        }