public override DynamicMetaObject FallbackUnaryOperation(DynamicMetaObject target, DynamicMetaObject errorSuggestion) { var arg = Expression.Convert(target.Expression, target.LimitType); var restrictions = BindingRestrictionsHelpers.GetRuntimeTypeRestriction(target); Expression res = null; switch (Operation) { case ExpressionType.Decrement: if (Binders.IsFloatingPoint(target.LimitType)) { res = Expression.Decrement(_context.Convert(arg, typeof(double))); } else { res = Expression.Decrement(_context.Convert(arg, typeof(long))); } break; case ExpressionType.Increment: if (Binders.IsFloatingPoint(target.LimitType)) { res = Expression.Increment(_context.Convert(arg, typeof(double))); } else { res = Expression.Increment(_context.Convert(arg, typeof(long))); } break; case ExpressionType.Negate: if (Binders.IsFloatingPoint(target.LimitType)) { res = Expression.Negate(_context.Convert(arg, typeof(double))); } else { res = Expression.Negate(_context.Convert(arg, typeof(long))); } break; case ExpressionType.Not: res = Expression.Condition(_context.Convert(arg, typeof(bool)), Expression.Constant(0L), Expression.Constant(1L)); break; case ExpressionType.OnesComplement: res = Expression.OnesComplement(_context.Convert(arg, typeof(long))); break; case ExpressionType.UnaryPlus: if (Binders.IsFloatingPoint(target.LimitType)) { res = _context.Convert(arg, typeof(double)); } else if (Binders.IsInteger(target.LimitType)) { res = _context.Convert(arg, typeof(long)); } else if (target.LimitType == typeof(string)) { res = Expression.Call(new Func <string, object>(Binders.ConvertNumber).Method, arg); } break; } if (res != null) { if (res.Type != typeof(object)) { return(new DynamicMetaObject(Expression.Convert(res, typeof(object)), restrictions)); } else { return(new DynamicMetaObject(res, restrictions)); } } else { return(errorSuggestion ?? new DynamicMetaObject(Expression.Throw(Expression.Constant(new InvalidOperationException("不正な単項演算です。")), typeof(object)), restrictions)); } }
public override DynamicMetaObject FallbackBinaryOperation(DynamicMetaObject target, DynamicMetaObject arg, DynamicMetaObject errorSuggestion) { var left = Expression.Convert(target.Expression, target.LimitType); var right = Expression.Convert(arg.Expression, arg.LimitType); Expression res = null; switch (Operation) { case ExpressionType.Add: if (target.LimitType == typeof(string) || arg.LimitType == typeof(string)) { res = Expression.Call(new Func <string, string, string>(string.Concat).Method, _context.Convert(left, typeof(string)), _context.Convert(right, typeof(string))); } else if (Binders.IsFloatingPoint(target.LimitType) || Binders.IsFloatingPoint(arg.LimitType)) { res = Expression.Add(_context.Convert(left, typeof(double)), _context.Convert(right, typeof(double))); } else { res = Expression.Add(_context.Convert(left, typeof(long)), _context.Convert(right, typeof(long))); } break; case ExpressionType.And: res = Expression.And(_context.Convert(left, typeof(long)), _context.Convert(right, typeof(long))); break; case ExpressionType.Divide: res = Expression.Divide(_context.Convert(left, typeof(double)), _context.Convert(right, typeof(double))); break; case ExpressionType.Equal: res = Expression.Condition(Equal(left, right), Expression.Constant(1L), Expression.Constant(0L)); break; case ExpressionType.ExclusiveOr: res = Expression.ExclusiveOr(_context.Convert(left, typeof(long)), _context.Convert(right, typeof(long))); break; case ExpressionType.GreaterThan: { Expression exp; if (target.LimitType == typeof(string) && arg.LimitType == typeof(string)) { exp = Expression.GreaterThan(Expression.Call(new Func <string, string, int>(string.CompareOrdinal).Method, left, right), Expression.Constant(0)); } else if (Binders.IsFloatingPoint(target.LimitType) || Binders.IsFloatingPoint(arg.LimitType)) { exp = Expression.GreaterThan(_context.Convert(left, typeof(double)), _context.Convert(right, typeof(double))); } else { exp = Expression.GreaterThan(_context.Convert(left, typeof(long)), _context.Convert(right, typeof(long))); } res = Expression.Condition(exp, Expression.Constant(1L), Expression.Constant(0L)); } break; case ExpressionType.GreaterThanOrEqual: { Expression exp; if (target.LimitType == typeof(string) && arg.LimitType == typeof(string)) { exp = Expression.GreaterThanOrEqual(Expression.Call(new Func <string, string, int>(string.CompareOrdinal).Method, left, right), Expression.Constant(0)); } else if (Binders.IsFloatingPoint(target.LimitType) || Binders.IsFloatingPoint(arg.LimitType)) { exp = Expression.GreaterThanOrEqual(_context.Convert(left, typeof(double)), _context.Convert(right, typeof(double))); } else { exp = Expression.GreaterThanOrEqual(_context.Convert(left, typeof(long)), _context.Convert(right, typeof(long))); } res = Expression.Condition(exp, Expression.Constant(1L), Expression.Constant(0L)); } break; case ExpressionType.LeftShift: res = Expression.LeftShift(_context.Convert(left, typeof(long)), _context.Convert(right, typeof(int))); break; case ExpressionType.LessThan: { Expression exp; if (target.LimitType == typeof(string) && arg.LimitType == typeof(string)) { exp = Expression.LessThan(Expression.Call(new Func <string, string, int>(string.CompareOrdinal).Method, left, right), Expression.Constant(0)); } else if (Binders.IsFloatingPoint(target.LimitType) || Binders.IsFloatingPoint(arg.LimitType)) { exp = Expression.LessThan(_context.Convert(left, typeof(double)), _context.Convert(right, typeof(double))); } else { exp = Expression.LessThan(_context.Convert(left, typeof(long)), _context.Convert(right, typeof(long))); } res = Expression.Condition(exp, Expression.Constant(1L), Expression.Constant(0L)); } break; case ExpressionType.LessThanOrEqual: { Expression exp; if (target.LimitType == typeof(string) && arg.LimitType == typeof(string)) { exp = Expression.LessThanOrEqual(Expression.Call(new Func <string, string, int>(string.CompareOrdinal).Method, left, right), Expression.Constant(0)); } else if (Binders.IsFloatingPoint(target.LimitType) || Binders.IsFloatingPoint(arg.LimitType)) { exp = Expression.LessThanOrEqual(_context.Convert(left, typeof(double)), _context.Convert(right, typeof(double))); } else { exp = Expression.LessThanOrEqual(_context.Convert(left, typeof(long)), _context.Convert(right, typeof(long))); } res = Expression.Condition(exp, Expression.Constant(1L), Expression.Constant(0L)); } break; case ExpressionType.Modulo: res = Expression.Modulo(_context.Convert(left, typeof(long)), _context.Convert(right, typeof(long))); break; case ExpressionType.Multiply: if (Binders.IsFloatingPoint(target.LimitType) || Binders.IsFloatingPoint(arg.LimitType)) { res = Expression.Multiply(_context.Convert(left, typeof(double)), _context.Convert(right, typeof(double))); } else { res = Expression.Multiply(_context.Convert(left, typeof(long)), _context.Convert(right, typeof(long))); } break; case ExpressionType.NotEqual: res = Expression.Condition(Equal(left, right), Expression.Constant(0L), Expression.Constant(1L)); break; case ExpressionType.Or: res = Expression.Or(_context.Convert(left, typeof(long)), _context.Convert(right, typeof(long))); break; case ExpressionType.RightShift: res = Expression.RightShift(_context.Convert(left, typeof(long)), _context.Convert(right, typeof(int))); break; case ExpressionType.Subtract: if (Binders.IsFloatingPoint(target.LimitType) || Binders.IsFloatingPoint(arg.LimitType)) { res = Expression.Subtract(_context.Convert(left, typeof(double)), _context.Convert(right, typeof(double))); } else { res = Expression.Subtract(_context.Convert(left, typeof(long)), _context.Convert(right, typeof(long))); } break; } var restrictions = BindingRestrictionsHelpers.GetRuntimeTypeRestriction(target).Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(arg)); if (res != null) { return(new DynamicMetaObject(Expression.Convert(res, typeof(object)), restrictions)); } else { return(errorSuggestion ?? new DynamicMetaObject(Expression.Throw(Expression.Constant(new InvalidOperationException("不正な二項演算です。")), typeof(object)), restrictions)); } }