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:
void CheckShiftArguments (EmitContext ec)
{
Expression e;
+ Type assumed_target_type = right.Type;
e = Convert.ImplicitVBConversion (ec, right, TypeManager.int32_type, Location);
if (e == null){
}
left = target_left_expr;
- }
+ } else if (left.Type == TypeManager.null_type)
+ left = Convert.ImplicitVBConversion (ec, left, assumed_target_type, Location);
type = left.Type;
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)
opcode = OpCodes.Shl;
break;
+ case Operator.Is:
case Operator.Equality:
opcode = OpCodes.Ceq;
break;
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)
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){
+ if (oper == Operator.Addition || oper == Operator.Concatenation){
+
//
// If any of the arguments is a string, cast to string
//
if (left is StringConstant && right is StringConstant)
return new StringConstant (((StringConstant) left).Value + ((StringConstant) right).Value);
- if (l == TypeManager.string_type || r == TypeManager.string_type) {
+ if (Type == TypeManager.string_type) {
- if (r == TypeManager.void_type || l == TypeManager.void_type) {
- Error_OperatorCannotBeApplied ();
- return null;
- }
-
// try to fold it in on the left
if (left is StringConcat) {
Expression target_left_expr = left;
Expression target_right_expr = right;
- if (IsShortCircuitedLogicalExpression)
+ if (IsShortCircuitedLogicalExpression || IsExpression)
return null;
if (l != TypeManager.object_type && r != TypeManager.object_type)
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 (" left => " + target_left_expr_type + " right => " + target_right_expr_type);
+ //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)) {
- left = target_left_expr;
- right = target_right_expr;
- type = target_left_expr_type;
- break;
+
+ 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)) {
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)
continue;
}
- if ( !DoOperandPromotions(ec, target_left_expr, target_right_expr)) {
- Error_OperatorCannotBeApplied();
- return;
- }
+ 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) {
break;
+ case Operator.LogicalAndAlso:
+ case Operator.LogicalOrElse:
+ if (t == TypeManager.bool_type)
+ return true;
+ break;
+
case Operator.RightShift:
case Operator.LeftShift:
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;
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");
}
}
+ bool IsExpression {
+ get {
+ return (oper == Operator.Is);
+ }
+ }
+
MethodInfo HelperMethod {
get {
MethodInfo helper_method = null;