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
}
IVariable variable = Expr as IVariable;
- if (!ec.InFixedInitializer && ((variable == null) || !variable.VerifyFixed (false))) {
+ bool is_fixed = variable != null && variable.VerifyFixed (false);
+
+ if (!ec.InFixedInitializer && !is_fixed) {
Error (212, "You can only take the address of an unfixed expression inside " +
"of a fixed statement initializer");
return null;
}
- if (ec.InFixedInitializer && ((variable != null) && variable.VerifyFixed (false))) {
+ if (ec.InFixedInitializer && is_fixed) {
Error (213, "You can not fix an already fixed expression");
return null;
}
if (Expr == null)
return null;
+ if (TypeManager.IsNullableType (Expr.Type))
+ return new Nullable.LiftedUnaryOperator (Oper, Expr, loc).Resolve (ec);
+
eclass = ExprClass.Value;
return ResolveOperator (ec);
}
// after semantic analysis (this is so we can take the address
// of an indirection).
//
- public class Indirection : Expression, IMemoryLocation, IAssignMethod {
+ public class Indirection : Expression, IMemoryLocation, IAssignMethod, IVariable {
Expression expr;
LocalTemporary temporary;
bool prepared;
{
return "*(" + expr + ")";
}
+
+ #region IVariable Members
+
+ public VariableInfo VariableInfo {
+ get {
+ return null;
+ }
+ }
+
+ public bool VerifyFixed (bool is_expression)
+ {
+ return true;
+ }
+
+ #endregion
}
/// <summary>
return null;
eclass = ExprClass.Value;
+
+ if (TypeManager.IsNullableType (expr.Type))
+ return new Nullable.LiftedUnaryMutator (mode, expr, loc).Resolve (ec);
+
return ResolveOperator (ec);
}
this.is_expr = is_expr;
((IAssignMethod) expr).EmitAssign (ec, this, is_expr && (mode == Mode.PreIncrement || mode == Mode.PreDecrement), true);
}
-
public override void Emit (EmitContext ec)
{
/// </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,
- LogicalAnd,
- LogicalOr,
TOP
}
Operator oper;
Expression left, right;
+ Expression intermediate;
// This must be kept in sync with Operator!!!
public static readonly string [] oper_names;
oper_names [(int) Operator.BitwiseAnd] = "op_BitwiseAnd";
oper_names [(int) Operator.BitwiseOr] = "op_BitwiseOr";
oper_names [(int) Operator.ExclusiveOr] = "op_ExclusiveOr";
- oper_names [(int) Operator.LogicalOr] = "op_LogicalOr";
- oper_names [(int) Operator.LogicalAnd] = "op_LogicalAnd";
+ oper_names [(int) Operator.LogicalOrElse] = "op_LogicalOr";
+ oper_names [(int) Operator.LogicalAndAlso] = "op_LogicalAnd";
}
public Binary (Operator oper, Expression left, Expression right, Location loc)
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 "^";
- case Operator.LogicalOr:
- return "||";
- case Operator.LogicalAnd:
- return "&&";
+ return "Xor";
+ case Operator.LogicalOrElse:
+ return "OrElse";
+ case Operator.LogicalAndAlso:
+ return "AndAlso";
}
return oper.ToString ();
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;
}
+ bool left_is_null = left is NullLiteral;
+ bool right_is_null = right is NullLiteral;
+ if (left_is_null || right_is_null) {
+ if (oper == Operator.Equality)
+ return new BoolLiteral (left_is_null == right_is_null);
+ else
+ return new BoolLiteral (left_is_null != right_is_null);
+ }
+
//
// operator != (object a, object b)
// operator == (object a, object b)
(r == TypeManager.anonymous_method_type))){
if ((RootContext.Version != LanguageVersion.ISO_1)){
Expression tmp = Convert.WideningConversionRequired (ec, right, l, loc);
- if (tmp == null)
- return null;
- right = tmp;
- r = right.Type;
- }
+ if (tmp == null)
+ return null;
+ right = tmp;
+ r = right.Type;
+ }
}
if (TypeManager.IsDelegateType (r)){
- MethodInfo method;
- ArrayList args = new ArrayList (2);
+ MethodInfo method;
+ ArrayList args = new ArrayList (2);
- args = new ArrayList (2);
- args.Add (new Argument (left, Argument.AType.Expression));
- args.Add (new Argument (right, Argument.AType.Expression));
+ args = new ArrayList (2);
+ args.Add (new Argument (left, Argument.AType.Expression));
+ args.Add (new Argument (right, Argument.AType.Expression));
- if (oper == Operator.Addition)
- method = TypeManager.delegate_combine_delegate_delegate;
- else
- method = TypeManager.delegate_remove_delegate_delegate;
+ if (oper == Operator.Addition)
+ method = TypeManager.delegate_combine_delegate_delegate;
+ else
+ method = TypeManager.delegate_remove_delegate_delegate;
- if (l != r) {
- Error_OperatorCannotBeApplied ();
- return null;
- }
+ if (!TypeManager.IsEqual (l, r)) {
+ Error_OperatorCannotBeApplied ();
+ return null;
+ }
- return new BinaryDelegate (l, method, args);
- }
+ return new BinaryDelegate (l, method, args);
+ }
}
//
if (oper == Operator.LeftShift || oper == Operator.RightShift)
return CheckShiftArguments (ec);
- if (oper == Operator.LogicalOr || oper == Operator.LogicalAnd){
+ if (oper == Operator.LogicalOrElse || oper == Operator.LogicalAndAlso){
if (l == TypeManager.bool_type && r == TypeManager.bool_type) {
type = TypeManager.bool_type;
return this;
}
Expression e = new ConditionalLogicalOperator (
- oper == Operator.LogicalAnd, left, right, l, loc);
+ oper == Operator.LogicalAndAlso, left, right, l, loc);
return e.Resolve (ec);
}
return this;
}
+#endif
public override Expression DoResolve (EmitContext ec)
{
Constant lc = left as Constant;
if (lc != null && lc.Type == TypeManager.bool_type &&
- ((oper == Operator.LogicalAnd && (bool)lc.GetValue () == false) ||
- (oper == Operator.LogicalOr && (bool)lc.GetValue () == true))) {
+ ((oper == Operator.LogicalAndAlso && (bool)lc.GetValue () == false) ||
+ (oper == Operator.LogicalOrElse && (bool)lc.GetValue () == true))) {
// TODO: make a sense to resolve unreachable expression as we do for statement
Report.Warning (429, 4, loc, "Unreachable expression code detected");
return e;
}
- return ResolveOperator (ec);
+ if (TypeManager.IsNullableType (left.Type) || TypeManager.IsNullableType (right.Type))
+ return new Nullable.LiftedBinaryOperator (oper, left, right, loc).Resolve (ec);
+
+ return ResolveVisualBasicOperator (ec);
}
/// <remarks>
return;
}
- } else if (oper == Operator.LogicalAnd) {
+ } else if (oper == Operator.LogicalAndAlso) {
if (onTrue) {
Label tests_end = ig.DefineLabel ();
return;
- } else if (oper == Operator.LogicalOr){
+ } else if (oper == Operator.LogicalOrElse){
if (onTrue) {
left.EmitBranchable (ec, target, true);
right.EmitBranchable (ec, target, true);
ILGenerator ig = ec.ig;
Type l = left.Type;
OpCode opcode;
+ OpCode opcode1 = OpCodes.Nop;
//
// Handle short-circuit operators differently
// than the rest
//
- if (oper == Operator.LogicalAnd) {
+ if (oper == Operator.LogicalAndAlso) {
Label load_zero = ig.DefineLabel ();
Label end = ig.DefineLabel ();
ig.Emit (OpCodes.Ldc_I4_0);
ig.MarkLabel (end);
return;
- } else if (oper == Operator.LogicalOr) {
+ } else if (oper == Operator.LogicalOrElse) {
Label load_one = ig.DefineLabel ();
Label end = ig.DefineLabel ();
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;
+ }
}
}
//
left.Emit (ec);
ig.Emit (OpCodes.Conv_I);
- right.Emit (ec);
- if (size != 1){
- if (size == 0)
- ig.Emit (OpCodes.Sizeof, element);
- else
- IntLiteral.EmitInt (ig, size);
- if (rtype == TypeManager.int64_type)
- ig.Emit (OpCodes.Conv_I8);
- else if (rtype == TypeManager.uint64_type)
- ig.Emit (OpCodes.Conv_U8);
- ig.Emit (OpCodes.Mul);
+
+ Constant right_const = right as Constant;
+ if (right_const != null && size != 0) {
+ Expression ex = ConstantFold.BinaryFold (ec, Binary.Operator.Multiply, new IntConstant (size), right_const, loc);
+ if (ex == null)
+ return;
+ ex.Emit (ec);
+ } else {
+ right.Emit (ec);
+ if (size != 1){
+ if (size == 0)
+ ig.Emit (OpCodes.Sizeof, element);
+ else
+ IntLiteral.EmitInt (ig, size);
+ if (rtype == TypeManager.int64_type)
+ ig.Emit (OpCodes.Conv_I8);
+ else if (rtype == TypeManager.uint64_type)
+ ig.Emit (OpCodes.Conv_U8);
+ ig.Emit (OpCodes.Mul);
+ }
}
if (rtype == TypeManager.int64_type || rtype == TypeManager.uint64_type)
if (expr == null)
return null;
+
+ if (TypeManager.IsNullableType (expr.Type))
+ return new Nullable.LiftedConditional (expr, trueExpr, falseExpr, loc).Resolve (ec);
if (expr.Type != TypeManager.bool_type){
expr = Expression.ResolveBoolean (
/// <summary>
/// Invocation of methods or delegates.
/// </summary>
- public class Invocation : ExpressionStatement {
+ public class Invocation : ExpressionStatement {
public readonly ArrayList Arguments;
public Expression expr;
// If we are dealing with a struct, get the
// address of it, so we can store it.
//
- if ((dims == 1) &&
- etype.IsSubclassOf (TypeManager.value_type) &&
+ if ((dims == 1) && etype.IsValueType &&
(!TypeManager.IsBuiltinOrEnum (etype) ||
etype == TypeManager.decimal_type)) {
if (e is New){
object real_value = ((Constant) c.Expr).GetValue ();
- return Constantify (real_value, t);
+ Expression exp = Constantify (real_value, t);
+
+ if (left_is_explicit && !left_is_type && !IdenticalNameAndTypeName (ec, left_original, left, loc)) {
+ Report.SymbolRelatedToPreviousError (c);
+ error176 (loc, c.GetSignatureForError ());
+ return null;
+ }
+
+ return exp;
}
}
}
public override FullNamedExpression ResolveAsTypeStep (EmitContext ec)
+ {
+ return ResolveNamespaceOrType (ec, false);
+ }
+
+ public FullNamedExpression ResolveNamespaceOrType (EmitContext ec, bool silent)
{
FullNamedExpression new_expr = expr.ResolveAsTypeStep (ec);
FullNamedExpression retval = ns.Lookup (ec.DeclSpace, lookup_id, loc);
if ((retval != null) && (args != null))
retval = new ConstructedType (retval, args, loc).ResolveAsTypeStep (ec);
- if (retval == null)
+ if (!silent && retval == null)
Report.Error (234, loc, "The type or namespace name `{0}' could not be found in namespace `{1}'", Identifier, ns.FullName);
return retval;
}
Expression member_lookup;
member_lookup = MemberLookupFinal (ec, expr_type, expr_type, lookup_id, loc);
- if (member_lookup == null) {
+ if (!silent && member_lookup == null) {
Report.Error (234, loc, "The type name `{0}' could not be found in type `{1}'",
Identifier, new_expr.FullName);
return null;
return null;
}
+ if ((dim.Length > 0) && (dim [0] == '?')) {
+ TypeExpr nullable = new NullableType (left, loc);
+ if (dim.Length > 1)
+ nullable = new ComposedCast (nullable, dim.Substring (1), loc);
+ return nullable.ResolveAsTypeTerminal (ec);
+ }
+
int pos = 0;
while ((pos < dim.Length) && (dim [pos] == '[')) {
pos++;
return this;
}
- //
- // ltype.Fullname is already fully qualified, so we can skip
- // a lot of probes, and go directly to TypeManager.LookupType
- //
- string fname = ltype.FullName != null ? ltype.FullName : ltype.Name;
- string cname = fname + dim;
- type = TypeManager.LookupTypeDirect (cname);
- if (type == null){
- //
- // For arrays of enumerations we are having a problem
- // with the direct lookup. Need to investigate.
+ if (dim != "") {
//
- // For now, fall back to the full lookup in that case.
+ // ltype.Fullname is already fully qualified, so we can skip
+ // a lot of probes, and go directly to TypeManager.LookupType
//
- FullNamedExpression e = ec.DeclSpace.LookupType (cname, false, loc);
- if (e is TypeExpr)
- type = ((TypeExpr) e).ResolveType (ec);
- if (type == null)
- return null;
+ string fname = ltype.FullName != null ? ltype.FullName : ltype.Name;
+ string cname = fname + dim;
+ type = TypeManager.LookupTypeDirect (cname);
+ if (type == null){
+ //
+ // For arrays of enumerations we are having a problem
+ // with the direct lookup. Need to investigate.
+ //
+ // For now, fall back to the full lookup in that case.
+ //
+ FullNamedExpression e = ec.DeclSpace.LookupType (cname, false, loc);
+ if (e is TypeExpr)
+ type = ((TypeExpr) e).ResolveType (ec);
+ if (type == null)
+ return null;
+ }
+ } else {
+ type = ltype;
}
if (!ec.InUnsafe && type.IsPointer){