using System.Reflection;
using System.Reflection.Emit;
using System.Text;
+ using Microsoft.VisualBasic;
/// <summary>
/// This is just a helper class, it is generated by Unary, UnaryMutator
/// </summary>
public class Binary : Expression {
public enum Operator : byte {
- Multiply, Division, Modulus,
+ Exponentiation,
+ Multiply, Division,
+ IntegerDivision,
+ Modulus,
Addition, Subtraction,
+ Concatenation,
LeftShift, RightShift,
- LessThan, GreaterThan, LessThanOrEqual, GreaterThanOrEqual,
- Equality, Inequality,
- BitwiseAnd,
+ Equality, Inequality, LessThan, GreaterThan, LessThanOrEqual, GreaterThanOrEqual, Like, Is,
+ BitwiseAnd, LogicalAndAlso,
+ BitwiseOr, LogicalOrElse,
ExclusiveOr,
- BitwiseOr,
- LogicalAndAlso,
- LogicalOrElse,
TOP
}
Operator oper;
Expression left, right;
+ Expression intermediate;
// This must be kept in sync with Operator!!!
public static readonly string [] oper_names;
static string OperName (Operator oper)
{
switch (oper){
+ case Operator.Exponentiation:
+ return "^";
case Operator.Multiply:
return "*";
case Operator.Division:
return "/";
+ case Operator.IntegerDivision:
+ return "\\";
case Operator.Modulus:
- return "%";
+ return "Mod";
case Operator.Addition:
return "+";
case Operator.Subtraction:
case Operator.GreaterThanOrEqual:
return ">=";
case Operator.Equality:
- return "==";
+ return "=";
case Operator.Inequality:
- return "!=";
+ return "<>";
+ case Operator.Like:
+ return "Like";
case Operator.BitwiseAnd:
- return "&";
+ return "And";
case Operator.BitwiseOr:
- return "|";
+ return "Or";
case Operator.ExclusiveOr:
- return "^";
+ return "Xor";
case Operator.LogicalOrElse:
return "OrElse";
case Operator.LogicalAndAlso:
return (left != null) && (right != null);
}
+ public void Error_OperatorCannotBeAppliedToObjectOperands ()
+ {
+ Report.Error (30038, loc,
+ "Operator " + OperName (oper) + " cannot be applied to operands of type `" +
+ TypeManager.CSharpName (TypeManager.object_type) + "'");
+ }
+
static public void Error_OperatorCannotBeApplied (Location loc, string name, Type l, Type r)
{
Report.Error (19, loc,
return null;
}
- Expression CheckShiftArguments (EmitContext ec)
+ void CheckShiftArguments (EmitContext ec)
{
Expression e;
+ Type assumed_target_type = right.Type;
- e = ForceConversion (ec, right, TypeManager.int32_type);
+ e = Convert.ImplicitVBConversion (ec, right, TypeManager.int32_type, Location);
if (e == null){
Error_OperatorCannotBeApplied ();
- return null;
+ return;
}
right = e;
- if (((e = Convert.WideningConversion (ec, left, TypeManager.int32_type, loc)) != null) ||
- ((e = Convert.WideningConversion (ec, left, TypeManager.uint32_type, loc)) != null) ||
- ((e = Convert.WideningConversion (ec, left, TypeManager.int64_type, loc)) != null) ||
- ((e = Convert.WideningConversion (ec, left, TypeManager.uint64_type, loc)) != null)){
- left = e;
- type = e.Type;
+ if ( !IsOperatorDefinedForType (left.Type)) {
+ Expression target_left_expr = ConvertOperandToDefinedType(ec, left);
- if (type == TypeManager.int32_type || type == TypeManager.uint32_type){
- right = new Binary (Binary.Operator.BitwiseAnd, right, new IntLiteral (31), loc);
- right = right.DoResolve (ec);
- } else {
- right = new Binary (Binary.Operator.BitwiseAnd, right, new IntLiteral (63), loc);
- right = right.DoResolve (ec);
+ if (target_left_expr == null) {
+ Error_OperatorCannotBeApplied();
+ return;
}
- return this;
- }
- Error_OperatorCannotBeApplied ();
- return null;
+ left = target_left_expr;
+ } else if (left.Type == TypeManager.null_type)
+ left = Convert.ImplicitVBConversion (ec, left, assumed_target_type, Location);
+
+ type = left.Type;
+
+ int mask = 0x1f;
+
+ if (type == TypeManager.byte_type)
+ mask = 0x7;
+ else if (type == TypeManager.short_type)
+ mask = 0xf;
+ else if (type == TypeManager.int32_type)
+ mask = 0x1f;
+ else if (type == TypeManager.int64_type)
+ mask = 0x3f;
+ else
+ throw new Exception ("This should not happen");
+
+ right = new Binary (Binary.Operator.BitwiseAnd, right, new IntLiteral (mask), loc);
+ right = right.DoResolve (ec);
}
+ void CheckIsArguments (EmitContext ec)
+ {
+ Type l = left.Type;
+ Type r = right.Type;
+ Type = TypeManager.bool_type;
+
+ bool left_is_null = left is NullLiteral;
+ bool right_is_null = right is NullLiteral;
+
+ if (left_is_null || right_is_null)
+ return;
+
+ if (l.IsValueType || r.IsValueType) {
+ Error_OperatorCannotBeApplied ();
+ return;
+ }
+
+
+ if (l == r)
+ return;
+
+ if (l.IsSubclassOf (r) || r.IsSubclassOf (l))
+ return;
+
+ if (!(Convert.WideningStandardConversionExists (ec, left, right.Type) ||
+ Convert.WideningStandardConversionExists (ec, right, left.Type))){
+ Error_OperatorCannotBeApplied ();
+ return;
+ }
+
+ if (left.Type != TypeManager.object_type)
+ left = new EmptyCast (left, TypeManager.object_type);
+ if (right.Type != TypeManager.object_type)
+ right = new EmptyCast (right, TypeManager.object_type);
+
+ return;
+ }
+
+
+#if false
Expression ResolveOperator (EmitContext ec)
{
Type l = left.Type;
return this;
}
+#endif
public override Expression DoResolve (EmitContext ec)
{
if (TypeManager.IsNullableType (left.Type) || TypeManager.IsNullableType (right.Type))
return new Nullable.LiftedBinaryOperator (oper, left, right, loc).Resolve (ec);
- return ResolveOperator (ec);
+ return ResolveVisualBasicOperator (ec);
}
/// <remarks>
ILGenerator ig = ec.ig;
Type l = left.Type;
OpCode opcode;
+ OpCode opcode1 = OpCodes.Nop;
//
// Handle short-circuit operators differently
return;
}
- left.Emit (ec);
- right.Emit (ec);
+ if (intermediate != null) {
+ intermediate.Emit (ec);
+ ig.Emit (OpCodes.Ldc_I4_0);
+ }
+ else {
+ left.Emit (ec);
+ right.Emit (ec);
+ }
- bool isUnsigned = is_unsigned (left.Type);
+ bool is_int32_or_int64_type = (Type == TypeManager.int32_type) || (Type == TypeManager.int64_type);
switch (oper){
case Operator.Multiply:
if (ec.CheckState){
- if (l == TypeManager.int32_type || l == TypeManager.int64_type)
+ if (is_int32_or_int64_type)
opcode = OpCodes.Mul_Ovf;
- else if (isUnsigned)
- opcode = OpCodes.Mul_Ovf_Un;
else
opcode = OpCodes.Mul;
} else
break;
case Operator.Division:
- if (isUnsigned)
- opcode = OpCodes.Div_Un;
- else
- opcode = OpCodes.Div;
+ case Operator.IntegerDivision:
+ opcode = OpCodes.Div;
break;
case Operator.Modulus:
- if (isUnsigned)
- opcode = OpCodes.Rem_Un;
- else
- opcode = OpCodes.Rem;
+ opcode = OpCodes.Rem;
break;
case Operator.Addition:
if (ec.CheckState){
- if (l == TypeManager.int32_type || l == TypeManager.int64_type)
+ if (is_int32_or_int64_type)
opcode = OpCodes.Add_Ovf;
- else if (isUnsigned)
- opcode = OpCodes.Add_Ovf_Un;
else
opcode = OpCodes.Add;
} else
case Operator.Subtraction:
if (ec.CheckState){
- if (l == TypeManager.int32_type || l == TypeManager.int64_type)
+ if (is_int32_or_int64_type)
opcode = OpCodes.Sub_Ovf;
- else if (isUnsigned)
- opcode = OpCodes.Sub_Ovf_Un;
else
opcode = OpCodes.Sub;
} else
break;
case Operator.RightShift:
- if (isUnsigned)
- opcode = OpCodes.Shr_Un;
- else
- opcode = OpCodes.Shr;
+ opcode = OpCodes.Shr;
break;
case Operator.LeftShift:
opcode = OpCodes.Shl;
break;
+ case Operator.Is:
case Operator.Equality:
opcode = OpCodes.Ceq;
break;
break;
case Operator.LessThan:
- if (isUnsigned)
- opcode = OpCodes.Clt_Un;
- else
- opcode = OpCodes.Clt;
+ opcode = OpCodes.Clt;
break;
case Operator.GreaterThan:
- if (isUnsigned)
- opcode = OpCodes.Cgt_Un;
- else
- opcode = OpCodes.Cgt;
+ opcode = OpCodes.Cgt;
break;
case Operator.LessThanOrEqual:
- Type lt = left.Type;
-
- if (isUnsigned || (lt == TypeManager.double_type || lt == TypeManager.float_type))
- ig.Emit (OpCodes.Cgt_Un);
- else
- ig.Emit (OpCodes.Cgt);
+ ig.Emit (OpCodes.Cgt);
ig.Emit (OpCodes.Ldc_I4_0);
opcode = OpCodes.Ceq;
break;
case Operator.GreaterThanOrEqual:
- Type le = left.Type;
-
- if (isUnsigned || (le == TypeManager.double_type || le == TypeManager.float_type))
- ig.Emit (OpCodes.Clt_Un);
- else
- ig.Emit (OpCodes.Clt);
-
+ ig.Emit (OpCodes.Clt);
ig.Emit (OpCodes.Ldc_I4_0);
opcode = OpCodes.Ceq;
}
ig.Emit (opcode);
+
+ if (!IsArithmeticExpression && !IsShiftExpression)
+ return;
+
+ if (type == TypeManager.byte_type)
+ ig.Emit (ec.CheckState && ! IsShiftExpression ? OpCodes.Conv_Ovf_U1 : OpCodes.Conv_U1);
+
+ if (type == TypeManager.short_type)
+ ig.Emit (ec.CheckState && ! IsShiftExpression ? OpCodes.Conv_Ovf_I2 : OpCodes.Conv_I2);
+ }
+
+ Expression ResolveVisualBasicOperator (EmitContext ec)
+ {
+ int errors;
+ Expression ret_expr;
+
+ Type l = left.Type;
+ Type r = right.Type;
+
+ //Console.WriteLine (OperName (oper) +"< "+ l + ", " + r + ">");
+
+ errors = Report.Errors;
+ ret_expr = HandleObjectOperands (ec);
+ if (Report.Errors > errors)
+ return null;
+ if (ret_expr != null)
+ return ret_expr;
+
+ errors = Report.Errors;
+ CheckArguments (ec);
+ if (Report.Errors > errors)
+ return null;
+
+ if (oper == Operator.Exponentiation)
+ return new HelperMethodInvocation (ec, Location, TypeManager.double_type,
+ TypeManager.math_pow_double_double, left, right);
+
+ if (type == TypeManager.decimal_type) {
+ MethodInfo helper_method = null;
+ switch (oper) {
+ case Operator.Addition:
+ helper_method = TypeManager.decimal_add_decimal_decimal;
+ break;
+ case Operator.Subtraction:
+ helper_method = TypeManager.decimal_subtract_decimal_decimal;
+ break;
+ case Operator.Multiply:
+ helper_method = TypeManager.decimal_multiply_decimal_decimal;
+ break;
+ case Operator.Division:
+ helper_method = TypeManager.decimal_divide_decimal_decimal;
+ break;
+ case Operator.Modulus:
+ helper_method = TypeManager.decimal_remainder_decimal_decimal;
+ break;
+
+ }
+ return new HelperMethodInvocation (ec, Location, TypeManager.decimal_type,
+ helper_method, left, right);
+ }
+
+ if (IsRelationalExpression) {
+ Type = TypeManager.bool_type;
+ if (left.Type == TypeManager.string_type) {
+ Expression is_text_mode;
+
+ is_text_mode = new BoolConstant (RootContext.StringComparisonMode == CompareMethod.Text);
+ intermediate = new HelperMethodInvocation (ec, Location, TypeManager.int32_type,
+ TypeManager.msvbcs_stringtype_strcmp_string_string_boolean,
+ left, right, is_text_mode);
+ return this;
+ }
+ if (left.Type == TypeManager.decimal_type) {
+ intermediate = new HelperMethodInvocation (ec, Location, TypeManager.int32_type,
+ TypeManager.decimal_compare_decimal_decimal, left, right);
+ return this;
+ }
+ if (left.Type == TypeManager.date_type) {
+ intermediate = new HelperMethodInvocation (ec, Location, TypeManager.int32_type,
+ TypeManager.datetime_compare_datetime_datetime, left, right);
+ return this;
+ }
+ }
+
+ if (IsShiftExpression)
+ return this;
+
+ if (IsShortCircuitedLogicalExpression)
+ return this;
+
+ if (oper == Operator.Like) {
+ Type = TypeManager.bool_type;
+ Expression compare_mode = new EnumConstant (new IntConstant ((int) RootContext.StringComparisonMode),
+ typeof (Microsoft.VisualBasic.CompareMethod));
+ return new HelperMethodInvocation (ec, Location, TypeManager.bool_type, TypeManager.msvbcs_stringtype_strlike_string_string_comparemethod, left, right, compare_mode);
+ }
+
+
+ //
+ // Step 0: String concatenation (because overloading will get this wrong)
+ //
+ if (oper == Operator.Addition || oper == Operator.Concatenation){
+
+ //
+ // If any of the arguments is a string, cast to string
+ //
+
+ // Simple constant folding
+ if (left is StringConstant && right is StringConstant)
+ return new StringConstant (((StringConstant) left).Value + ((StringConstant) right).Value);
+
+ if (Type == TypeManager.string_type) {
+
+ // try to fold it in on the left
+ if (left is StringConcat) {
+
+ //
+ // We have to test here for not-null, since we can be doubly-resolved
+ // take care of not appending twice
+ //
+ if (type == null){
+ type = TypeManager.string_type;
+ ((StringConcat) left).Append (ec, right);
+ return left.Resolve (ec);
+ } else {
+ return left;
+ }
+ }
+
+ // Otherwise, start a new concat expression
+ return new StringConcat (ec, loc, left, right).Resolve (ec);
+ }
+
+ //
+ // Transform a + ( - b) into a - b
+ //
+ if (right is Unary){
+ Unary right_unary = (Unary) right;
+
+ if (right_unary.Oper == Unary.Operator.UnaryNegation){
+ oper = Operator.Subtraction;
+ right = right_unary.Expr;
+ r = right.Type;
+ }
+ }
+ }
+
+ return this;
+ }
+
+ Expression HandleObjectOperands (EmitContext ec)
+ {
+ Type l = left.Type;
+ Type r = right.Type;
+
+ Expression target_left_expr = left;
+ Expression target_right_expr = right;
+
+ if (IsShortCircuitedLogicalExpression || IsExpression)
+ return null;
+
+ if (l != TypeManager.object_type && r != TypeManager.object_type)
+ return null;
+
+ if (RootContext.StricterTypeChecking)
+ if (oper != Operator.Equality &&
+ oper != Operator.Inequality && oper != Operator.Is) {
+ Error_OperatorCannotBeAppliedToObjectOperands ();
+ return null;
+ }
+
+ if (l != TypeManager.object_type && ! IsOperatorDefinedForType (l) && ConvertOperandToDefinedType(ec, target_left_expr) == null) {
+ Error_OperatorCannotBeApplied ();
+ return null;
+ }
+ if (!IsShiftExpression && r != TypeManager.object_type && ! IsOperatorDefinedForType (r) && ConvertOperandToDefinedType(ec, target_right_expr) == null) {
+ Error_OperatorCannotBeApplied ();
+ return null;
+ }
+
+ if (l != TypeManager.object_type)
+ left = Convert.ImplicitVBConversionRequired (ec, left, TypeManager.object_type, Location);
+
+ if (IsShiftExpression) {
+ if (r != TypeManager.int32_type) {
+ target_right_expr = Convert.ImplicitVBConversionRequired (ec, right, TypeManager.int32_type, Location);
+ if (target_right_expr == null) {
+ Error_OperatorCannotBeApplied ();
+ return null;
+ }
+ right = target_right_expr;
+ }
+
+ } else if (r != TypeManager.object_type) {
+ right = Convert.ImplicitVBConversionRequired (ec, right, TypeManager.object_type, Location);
+ }
+
+
+ Type = TypeManager.object_type;
+ if (IsRelationalExpression) {
+ Type = TypeManager.bool_type;
+ Expression is_text_mode = new BoolConstant (RootContext.StringComparisonMode == CompareMethod.Text);
+ intermediate = new HelperMethodInvocation (ec, Location, TypeManager.int32_type, HelperMethod, left, right, is_text_mode);
+ return this;
+ }
+
+ if (oper == Operator.Like) {
+ Type = TypeManager.bool_type;
+ Expression compare_mode = new EnumConstant (new IntConstant ((int) RootContext.StringComparisonMode),
+ typeof (Microsoft.VisualBasic.CompareMethod));
+ return new HelperMethodInvocation (ec, Location, TypeManager.bool_type, HelperMethod, left, right, compare_mode);
+ }
+
+ if (IsShiftExpression)
+ return new HelperMethodInvocation (ec, Location, TypeManager.object_type, HelperMethod, left, right);
+
+ return new HelperMethodInvocation (ec, Location, TypeManager.object_type, HelperMethod, left, right);
+ }
+
+ void CheckArguments (EmitContext ec)
+ {
+ int step = 0;
+
+ Type l = left.Type;
+ Type r = right.Type;
+
+ Expression target_left_expr = left;
+ Expression target_right_expr = right;
+
+ Type target_left_expr_type = target_left_expr.Type;
+ Type target_right_expr_type = target_right_expr.Type;
+
+
+ if (IsShiftExpression) {
+ CheckShiftArguments (ec);
+ return;
+ }
+
+ if (IsExpression) {
+ CheckIsArguments (ec);
+ return;
+ }
+
+ while (true) {
+ ++step;
+
+ if (step > 10)
+ throw new Exception ("FIXME: An Infinite loop when resolving <" + l + "> " + OperName (oper) + " <" + r + ">");
+
+ //Console.WriteLine (" STEP " + step + ":");
+ //Console.WriteLine (" " + "<" + target_left_expr_type + ", " + target_right_expr_type + ">");
+
+ if ((target_left_expr_type == target_right_expr_type) &&
+ IsOperatorDefinedForType (target_left_expr_type)) {
+
+ if (target_left_expr_type == TypeManager.null_type) {
+ target_left_expr = target_right_expr = new IntConstant (0);
+ Type = TypeManager.int32_type;
+ return;
+ } else {
+ left = target_left_expr;
+ right = target_right_expr;
+ type = target_left_expr_type;
+ return;
+ }
+ }
+
+ if ( !IsOperatorDefinedForType (target_left_expr_type)) {
+ target_left_expr = ConvertOperandToDefinedType(ec, target_left_expr);
+
+ if (target_left_expr == null) {
+ Error_OperatorCannotBeApplied();
+ return;
+ }
+
+ target_left_expr_type = target_left_expr.Type;
+ continue;
+ }
+
+ if ( !IsOperatorDefinedForType(target_right_expr_type)) {
+ target_right_expr = ConvertOperandToDefinedType(ec, target_right_expr);
+
+ if(target_right_expr == null) {
+ Error_OperatorCannotBeApplied();
+ return;
+ }
+
+ target_right_expr_type = target_right_expr.Type;
+ continue;
+ }
+
+ if (target_left_expr_type == TypeManager.null_type ||
+ target_right_expr_type == TypeManager.null_type)
+ break;
+
+ if (target_left_expr_type == TypeManager.string_type) {
+ Type target_type;
+ if (target_right_expr_type == TypeManager.date_type)
+ target_type = TypeManager.date_type;
+ else if (target_right_expr_type == TypeManager.bool_type)
+ target_type = TypeManager.bool_type;
+ else
+ target_type = TypeManager.double_type;
+
+ if (l == target_type)
+ target_left_expr = left;
+ else
+ target_left_expr = Convert.ImplicitVBConversionRequired (ec, left, target_type, Location);
+
+ if (target_left_expr == null) {
+ Error_OperatorCannotBeApplied();
+ return;
+ }
+
+ target_left_expr_type = target_left_expr.Type;
+ continue;
+ }
+
+ if (target_right_expr_type == TypeManager.string_type) {
+ Type target_type;
+ if (target_left_expr_type == TypeManager.date_type)
+ target_type = TypeManager.date_type;
+ else if (target_left_expr_type == TypeManager.bool_type)
+ target_type = TypeManager.bool_type;
+ else
+ target_type = TypeManager.double_type;
+
+ if (r == target_type)
+ target_right_expr = right;
+ else
+ target_right_expr = Convert.ImplicitVBConversionRequired (ec, right, target_type, Location);
+
+ if (target_right_expr == null) {
+ Error_OperatorCannotBeApplied();
+ return;
+ }
+
+ target_right_expr_type = target_right_expr.Type;
+ continue;
+ }
+
+ break;
+ }
+
+ if ( !DoOperandPromotions(ec, target_left_expr, target_right_expr))
+ Error_OperatorCannotBeApplied();
+
+ return;
+ }
+
+ bool IsOperatorDefinedForType (Type t)
+ {
+ if (t == TypeManager.null_type)
+ return true;
+
+ switch (oper) {
+
+ case Operator.Exponentiation:
+ if (t == TypeManager.double_type)
+ return true;
+ break;
+
+ case Operator.Concatenation:
+ case Operator.Like:
+ if (t == TypeManager.string_type)
+ return true;
+
+ break;
+
+ case Operator.BitwiseAnd:
+ case Operator.BitwiseOr:
+ case Operator.ExclusiveOr:
+ if (t == TypeManager.bool_type ||
+ TypeManager.IsFixedNumericType (t))
+ return true;
+
+ break;
+
+ case Operator.LogicalAndAlso:
+ case Operator.LogicalOrElse:
+ if (t == TypeManager.bool_type)
+ return true;
+ break;
+
+ case Operator.RightShift:
+ case Operator.LeftShift:
+
+ if (TypeManager.IsFixedNumericType (t))
+ return true;
+
+ break;
+
+ case Operator.Equality:
+ case Operator.Inequality:
+ case Operator.LessThan:
+ case Operator.LessThanOrEqual:
+ case Operator.GreaterThan:
+ case Operator.GreaterThanOrEqual:
+ if (t == TypeManager.bool_type ||
+ t == TypeManager.date_type ||
+ t == TypeManager.char_type ||
+ t == TypeManager.string_type ||
+ TypeManager.IsNumericType (t))
+ return true;
+
+ break;
+
+ case Operator.Addition:
+ if (t == TypeManager.string_type ||
+ TypeManager.IsNumericType (t))
+ return true;
+ break;
+
+ case Operator.Subtraction:
+ case Operator.Multiply:
+ case Operator.Division:
+ case Operator.Modulus:
+ if (TypeManager.IsNumericType (t))
+ return true;
+ break;
+
+ case Operator.IntegerDivision:
+ if (TypeManager.IsFixedNumericType (t))
+ return true;
+
+ break;
+ }
+
+ return false;
+ }
+
+
+ Expression ConvertOperandToDefinedType (EmitContext ec, Expression expr)
+ {
+ Type target_type = null;
+ Type operand_type = expr.Type;
+
+ if (IsOperatorDefinedForType (operand_type))
+ return expr;
+
+ switch (oper) {
+ case Operator.Addition:
+ case Operator.Subtraction:
+ case Operator.Multiply:
+ if (operand_type == TypeManager.bool_type)
+ target_type = TypeManager.short_type;
+
+ if (operand_type == TypeManager.char_type)
+ target_type = TypeManager.string_type;
+
+ if (operand_type == TypeManager.date_type)
+ target_type = TypeManager.string_type;
+
+ break;
+
+ case Operator.Like:
+ case Operator.Concatenation:
+ return Convert.ExplicitVBConversion(ec, expr, TypeManager.string_type, expr.Location);
+ break;
+
+ case Operator.LogicalAndAlso:
+ case Operator.LogicalOrElse:
+ return Convert.ExplicitVBConversion(ec, expr, TypeManager.bool_type, expr.Location);
+ break;
+
+ case Operator.Exponentiation:
+ return Convert.ExplicitVBConversion(ec, expr, TypeManager.double_type, expr.Location);
+ break;
+
+ }
+
+ if (target_type != null)
+ return Convert.ImplicitVBConversion(ec, expr, target_type, expr.Location);
+
+ return null;
+ }
+
+ static Type GetWiderOfTypes (Type t1, Type t2)
+ {
+ // char array and Nothing should be handled here ?
+
+
+ if (t1 == t2)
+ return t1;
+
+ if(t1 == TypeManager.null_type)
+ return t2;
+
+ if (t2 == TypeManager.null_type)
+ return t1;
+
+ if (t1 == TypeManager.date_type || t1 == TypeManager.char_type) {
+ if (t2 == TypeManager.string_type)
+ return t2;
+ else
+ return null;
+ }
+
+ if (t2 == TypeManager.date_type || t2 == TypeManager.char_type) {
+ if (t1 == TypeManager.string_type)
+ return t1;
+ else
+ return null;
+ }
+
+ object order1 = TypeManager.relative_type_order[t1];
+ if (order1 == null)
+ return null;
+
+ object order2 = TypeManager.relative_type_order[t2];
+
+ if (order2 == null)
+ return null;
+
+ if ((int) order1 > (int) order2)
+ return t1;
+ else
+ return t2;
+
+ }
+
+ bool DoOperandPromotions (EmitContext ec, Expression target_left_expr, Expression target_right_expr)
+ {
+ Type l = target_left_expr.Type;
+ Type r = target_right_expr.Type;
+
+ Type target_type = GetWiderOfTypes(l, r);
+
+ //Console.WriteLine (" DoingOperandPromotions");
+ //Console.WriteLine (" left => " + l + " right => " + r);
+ //Console.WriteLine (" target_type => " + target_type);
+
+ if (target_type == null) {
+ throw new Exception ("Types " + l + " " + r +" cannot be compared");
+ }
+
+ if (r != target_type) {
+ target_right_expr = Convert.ImplicitVBConversion (ec, target_right_expr, target_type, Location);
+
+ if (target_right_expr == null)
+ return false;
+
+ }
+
+ if (l != target_type) {
+ target_left_expr = Convert.ImplicitVBConversion (ec, target_left_expr, target_type, Location);
+
+ if (target_left_expr == null)
+ return false;
+ }
+
+ left = target_left_expr;
+ right = target_right_expr;
+ type = target_type;
+ return true;
+ }
+
+ bool IsArithmeticExpression {
+ get {
+ if (oper == Operator.Addition|| oper == Operator.Subtraction||
+ oper == Operator.Multiply|| oper == Operator.Division||
+ oper == Operator.IntegerDivision|| oper == Operator.Modulus)
+ return true;
+
+ return false;
+ }
+ }
+
+ bool IsRelationalExpression {
+ get {
+ if (oper == Operator.Equality || oper == Operator.Inequality ||
+ oper == Operator.LessThan || oper == Operator.LessThanOrEqual ||
+ oper == Operator.GreaterThan || oper == Operator.GreaterThanOrEqual)
+ return true;
+
+ return false;
+ }
+ }
+
+ bool IsShiftExpression {
+ get {
+ if (oper == Operator.LeftShift || oper == Operator.RightShift)
+ return true;
+
+ return false;
+ }
+ }
+
+ bool IsShortCircuitedLogicalExpression {
+ get {
+ if (oper == Operator.LogicalAndAlso|| oper == Operator.LogicalOrElse)
+ return true;
+
+ return false;
+ }
+ }
+
+ bool IsExpression {
+ get {
+ return (oper == Operator.Is);
+ }
+ }
+
+ MethodInfo HelperMethod {
+ get {
+ MethodInfo helper_method = null;
+ switch (oper) {
+ case Operator.Multiply:
+ helper_method = TypeManager.msvbcs_objecttype_mulobj_object_object;
+ break;
+ case Operator.Division:
+ helper_method = TypeManager.msvbcs_objecttype_divobj_object_object;
+ break;
+ case Operator.IntegerDivision:
+ helper_method = TypeManager.msvbcs_objecttype_idivobj_object_object;
+ break;
+ case Operator.Modulus:
+ helper_method = TypeManager.msvbcs_objecttype_modobj_object_object;
+ break;
+ case Operator.Addition:
+ helper_method = TypeManager.msvbcs_objecttype_addobj_object_object;
+ break;
+ case Operator.Subtraction:
+ helper_method = TypeManager.msvbcs_objecttype_subobj_object_object;
+ break;
+ case Operator.LessThan:
+ case Operator.GreaterThan:
+ case Operator.LessThanOrEqual:
+ case Operator.GreaterThanOrEqual:
+ case Operator.Equality:
+ case Operator.Inequality:
+ helper_method = TypeManager.msvbcs_objecttype_objtst_object_object_boolean;
+ break;
+ case Operator.BitwiseAnd:
+ helper_method = TypeManager.msvbcs_objecttype_bitandobj_object_object;
+ break;
+ case Operator.BitwiseOr:
+ helper_method = TypeManager.msvbcs_objecttype_bitorobj_object_object;
+ break;
+ case Operator.ExclusiveOr:
+ helper_method = TypeManager.msvbcs_objecttype_bitxorobj_object_object;
+ break;
+
+ case Operator.Like:
+ helper_method = TypeManager.msvbcs_objecttype_likeobj_object_object_comparemethod;
+ break;
+
+ case Operator.Concatenation:
+ helper_method = TypeManager.msvbcs_objecttype_strcatobj_object_object;
+ break;
+
+ case Operator.Exponentiation:
+ helper_method = TypeManager.msvbcs_objecttype_powobj_object_object;
+ break;
+ case Operator.LeftShift:
+ helper_method = TypeManager.msvbcs_objecttype_shiftleftobj_object_int32;
+ break;
+ case Operator.RightShift:
+ helper_method = TypeManager.msvbcs_objecttype_shiftrightobj_object_int32;
+ break;
+
+ }
+
+ return helper_method;
+ }
}
}