public override ValueExpression Evaluate(IParserContext context) { ValueExpression[] values = new[] { Left.Evaluate(context), Right.Evaluate(context) }; Type type1 = values[0].Type; Type type2 = values[1].Type; bool nullable1 = type1.IsGenericType && type1.GetGenericTypeDefinition() == typeof(Nullable <>); bool nullable2 = type2.IsGenericType && type2.GetGenericTypeDefinition() == typeof(Nullable <>); type1 = Nullable.GetUnderlyingType(type1) ?? type1; type2 = Nullable.GetUnderlyingType(type2) ?? type2; bool isNullable = (nullable1 || nullable2); OperatorMethod operatorMethod = FindOperatorMethod(type1, type2); if (operatorMethod == null) { Type promotionType = null; if (type1 == typeof(decimal) || type2 == typeof(decimal)) { promotionType = typeof(decimal); } else if (type1 == typeof(double) || type2 == typeof(double)) { promotionType = typeof(double); } else if (type1 == typeof(float) || type2 == typeof(float)) { promotionType = typeof(float); } else if (type1 == typeof(ulong) || type2 == typeof(ulong)) { promotionType = typeof(ulong); } else if (type1 == typeof(long) || type2 == typeof(long)) { promotionType = typeof(long); } else if (type1 == typeof(uint) || type2 == typeof(uint) && (type1 == typeof(sbyte) || type2 == typeof(sbyte) || type1 == typeof(short) || type2 == typeof(short) || type1 == typeof(int) || type2 == typeof(int))) { promotionType = typeof(long); } else if (type1 == typeof(uint) || type2 == typeof(uint)) { promotionType = typeof(uint); } else if (type1.IsPrimitive && type2.IsPrimitive && type1 != typeof(bool) && type2 != typeof(bool)) { promotionType = typeof(int); } if (promotionType != null) { type1 = promotionType; type2 = promotionType; } operatorMethod = FindOperatorMethod(type1, type2); } if (operatorMethod == null) { MethodInfo customOperatorMethod = type1.GetMethod(_operatorOverloadNames[_operator], new[] { type1, type2 }); if (customOperatorMethod != null) { return(new ValueExpression(TokenPosition, customOperatorMethod.Invoke(null, new[] { values[0].Value, values[1].Value }), customOperatorMethod.ReturnType)); } if (_operator == "==" || _operator == "!=") { return(new ValueExpression(TokenPosition, BinaryExpressionHelper.CalcObject(_operator, values[0].Value, values[1].Value, context.StringComparison, this), typeof(bool))); } throw new IllegalOperandsException("Operator " + _operator + " is not supported on " + values[0] + " and " + values[1], this); } Type returnType = operatorMethod.ReturnType; if (isNullable) { returnType = typeof(Nullable <>).MakeGenericType(returnType); //TODO: check specs for bool? values if (values[0].Value == null || values[1].Value == null) { return(new ValueExpression(TokenPosition, null, returnType)); } } object value1 = Convert.ChangeType(values[0].Value, operatorMethod.Type1); object value2 = Convert.ChangeType(values[1].Value, operatorMethod.Type2); return(new ValueExpression(TokenPosition, operatorMethod.Function(_operator, value1, value2, context.StringComparison, this), returnType)); }
public override ValueExpression Evaluate(ITemplateContext context) { ValueExpression[] values = new ValueExpression[] { Left.Evaluate(context), Right.Evaluate(context) }; Type type1 = values[0].Type; Type type2 = values[1].Type; bool nullable1 = type1.IsGenericType && type1.GetGenericTypeDefinition() == typeof(Nullable <>); bool nullable2 = type2.IsGenericType && type2.GetGenericTypeDefinition() == typeof(Nullable <>); type1 = Nullable.GetUnderlyingType(type1) ?? type1; type2 = Nullable.GetUnderlyingType(type2) ?? type2; bool isNullable = (nullable1 || nullable2); OperatorMethod operatorMethod = FindOperatorMethod(type1, type2); if (operatorMethod == null) { Type promotionType = null; if (type1 == typeof(decimal) || type2 == typeof(decimal)) { promotionType = typeof(decimal); } else if (type1 == typeof(double) || type2 == typeof(double)) { promotionType = typeof(double); } else if (type1 == typeof(float) || type2 == typeof(float)) { promotionType = typeof(float); } else if (type1 == typeof(ulong) || type2 == typeof(ulong)) { promotionType = typeof(ulong); } else if (type1 == typeof(long) || type2 == typeof(long)) { promotionType = typeof(long); } else if (type1 == typeof(uint) || type2 == typeof(uint) && (type1 == typeof(sbyte) || type2 == typeof(sbyte) || type1 == typeof(short) || type2 == typeof(short) || type1 == typeof(int) || type2 == typeof(int))) { promotionType = typeof(long); } else if (type1 == typeof(uint) || type2 == typeof(uint)) { promotionType = typeof(uint); } else if (type1.IsPrimitive && type2.IsPrimitive && type1 != typeof(bool) && type2 != typeof(bool)) { promotionType = typeof(int); } if (promotionType != null) { type1 = promotionType; type2 = promotionType; } operatorMethod = FindOperatorMethod(type1, type2); } if (operatorMethod == null) { if (_operator == "==" || _operator == "!=") { return(new ValueExpression(BEH.CalcObject(_operator, values[0].Value, values[1].Value), typeof(bool))); } throw new ArithmeticException(); } Type returnType = operatorMethod.ReturnType; if (isNullable) { returnType = typeof(Nullable <>).MakeGenericType(returnType); //TODO: check specs for bool? values if (values[0].Value == null || values[1].Value == null) { return(new ValueExpression(null, returnType)); } } object value1 = Convert.ChangeType(values[0].Value, operatorMethod.Type1); object value2 = Convert.ChangeType(values[1].Value, operatorMethod.Type2); return(new ValueExpression(operatorMethod.Function(_operator, value1, value2), returnType)); }