protected MethodInfo GetOperator(IReflect ir1, IReflect ir2) { if (ir1 is ClassScope) { ir1 = ((ClassScope)ir1).GetUnderlyingTypeIfEnum(); } if (ir2 is ClassScope) { ir2 = ((ClassScope)ir2).GetUnderlyingTypeIfEnum(); } Type t1 = ir1 is Type ? (Type)ir1 : Typeob.Object; Type t2 = ir2 is Type ? (Type)ir2 : Typeob.Object; if (this.type1 == t1 && this.type2 == t2) { return(this.operatorMeth); } this.type1 = t1; this.type2 = t2; this.operatorMeth = null; if (t1 == Typeob.String || Convert.IsPrimitiveNumericType(ir1) || Typeob.JSObject.IsAssignableFrom(t1)) { t1 = null; } if (t2 == Typeob.String || Convert.IsPrimitiveNumericType(ir2) || Typeob.JSObject.IsAssignableFrom(t2)) { t2 = null; } if (t1 == null && t2 == null) { return(null); } //One of the operands is an object of a type that might have a user defined operator. String name = "op_NoSuchOp"; switch (this.operatorTok) { case JSToken.BitwiseAnd: name = "op_BitwiseAnd"; break; case JSToken.BitwiseOr: name = "op_BitwiseOr"; break; case JSToken.BitwiseXor: name = "op_ExclusiveOr"; break; case JSToken.Divide: name = "op_Division"; break; case JSToken.Equal: name = "op_Equality"; break; case JSToken.GreaterThan: name = "op_GreaterThan"; break; case JSToken.GreaterThanEqual: name = "op_GreaterThanOrEqual"; break; case JSToken.LeftShift: name = "op_LeftShift"; break; case JSToken.LessThan: name = "op_LessThan"; break; case JSToken.LessThanEqual: name = "op_LessThanOrEqual"; break; case JSToken.Minus: name = "op_Subtraction"; break; case JSToken.Modulo: name = "op_Modulus"; break; case JSToken.Multiply: name = "op_Multiply"; break; case JSToken.NotEqual: name = "op_Inequality"; break; case JSToken.Plus: name = "op_Addition"; break; case JSToken.RightShift: name = "op_RightShift"; break; } Type[] types = new Type[] { this.type1, this.type2 }; if (t1 == t2) { MethodInfo op = t1.GetMethod(name, BindingFlags.Public | BindingFlags.Static, JSBinder.ob, types, null); if (op != null && (op.Attributes & MethodAttributes.SpecialName) != 0 && op.GetParameters().Length == 2) { this.operatorMeth = op; } } else { //Search both operand types, but only if there is a possibility that they might have operators defined on them MethodInfo op1 = t1 == null ? null : t1.GetMethod(name, BindingFlags.Public | BindingFlags.Static, JSBinder.ob, types, null); MethodInfo op2 = t2 == null ? null : t2.GetMethod(name, BindingFlags.Public | BindingFlags.Static, JSBinder.ob, types, null); this.operatorMeth = JSBinder.SelectOperator(op1, op2, this.type1, this.type2); //Choose the better of the two } if (this.operatorMeth != null) { this.operatorMeth = new JSMethodInfo(this.operatorMeth); } return(this.operatorMeth); }
protected MethodInfo GetOperator(IReflect ir1, IReflect ir2) { if (ir1 is ClassScope) { ir1 = ((ClassScope)ir1).GetUnderlyingTypeIfEnum(); } if (ir2 is ClassScope) { ir2 = ((ClassScope)ir2).GetUnderlyingTypeIfEnum(); } Type c = (ir1 is Type) ? ((Type)ir1) : Typeob.Object; Type type2 = (ir2 is Type) ? ((Type)ir2) : Typeob.Object; if ((this.type1 != c) || (this.type2 != type2)) { this.type1 = c; this.type2 = type2; this.operatorMeth = null; if (((c == Typeob.String) || Microsoft.JScript.Convert.IsPrimitiveNumericType(ir1)) || Typeob.JSObject.IsAssignableFrom(c)) { c = null; } if (((type2 == Typeob.String) || Microsoft.JScript.Convert.IsPrimitiveNumericType(ir2)) || Typeob.JSObject.IsAssignableFrom(type2)) { type2 = null; } if ((c == null) && (type2 == null)) { return(null); } string name = "op_NoSuchOp"; switch (this.operatorTok) { case JSToken.FirstBinaryOp: name = "op_Addition"; break; case JSToken.Minus: name = "op_Subtraction"; break; case JSToken.BitwiseOr: name = "op_BitwiseOr"; break; case JSToken.BitwiseXor: name = "op_ExclusiveOr"; break; case JSToken.BitwiseAnd: name = "op_BitwiseAnd"; break; case JSToken.Equal: name = "op_Equality"; break; case JSToken.NotEqual: name = "op_Inequality"; break; case JSToken.GreaterThan: name = "op_GreaterThan"; break; case JSToken.LessThan: name = "op_LessThan"; break; case JSToken.LessThanEqual: name = "op_LessThanOrEqual"; break; case JSToken.GreaterThanEqual: name = "op_GreaterThanOrEqual"; break; case JSToken.LeftShift: name = "op_LeftShift"; break; case JSToken.RightShift: name = "op_RightShift"; break; case JSToken.Multiply: name = "op_Multiply"; break; case JSToken.Divide: name = "op_Division"; break; case JSToken.Modulo: name = "op_Modulus"; break; } Type[] types = new Type[] { this.type1, this.type2 }; if (c == type2) { MethodInfo info = c.GetMethod(name, BindingFlags.Public | BindingFlags.Static, JSBinder.ob, types, null); if (((info != null) && ((info.Attributes & MethodAttributes.SpecialName) != MethodAttributes.PrivateScope)) && (info.GetParameters().Length == 2)) { this.operatorMeth = info; } } else { MethodInfo info2 = (c == null) ? null : c.GetMethod(name, BindingFlags.Public | BindingFlags.Static, JSBinder.ob, types, null); MethodInfo info3 = (type2 == null) ? null : type2.GetMethod(name, BindingFlags.Public | BindingFlags.Static, JSBinder.ob, types, null); this.operatorMeth = JSBinder.SelectOperator(info2, info3, this.type1, this.type2); } if (this.operatorMeth != null) { this.operatorMeth = new JSMethodInfo(this.operatorMeth); } } return(this.operatorMeth); }