public void CastDynamicArgs(ResolveContext rc) { for (int i = 0; i < args.Count; ++i) { Argument a = args[i]; // remove dynamic a.Expr = EmptyCast.RemoveDynamic(rc, a.Expr); } }
protected override Expression ResolveConversions(ResolveContext ec) { source = EmptyCast.Create(source, target.Type); return(this); }
Expression ResolveOperator (EmitContext ec) { Type l = left.Type; Type r = right.Type; bool overload_failed = false; // // Special cases: string comapred to null // if (oper == Operator.Equality || oper == Operator.Inequality){ if ((l == TypeManager.string_type && (right is NullLiteral)) || (r == TypeManager.string_type && (left is NullLiteral))){ Type = TypeManager.bool_type; return this; } } // // Do not perform operator overload resolution when both sides are // built-in types // if (!(TypeManager.IsCLRType (l) && TypeManager.IsCLRType (r))){ // // Step 1: Perform Operator Overload location // Expression left_expr, right_expr; string op = oper_names [(int) oper]; MethodGroupExpr union; left_expr = MemberLookup (ec, l, op, MemberTypes.Method, AllBindingFlags, loc); if (r != l){ right_expr = MemberLookup ( ec, r, op, MemberTypes.Method, AllBindingFlags, loc); union = Invocation.MakeUnionSet (left_expr, right_expr, loc); } else union = (MethodGroupExpr) left_expr; if (union != null) { Arguments = new ArrayList (); Arguments.Add (new Argument (left, Argument.AType.Expression)); Arguments.Add (new Argument (right, Argument.AType.Expression)); method = Invocation.OverloadResolve (ec, union, Arguments, Location.Null); if (method != null) { MethodInfo mi = (MethodInfo) method; type = mi.ReturnType; return this; } else { overload_failed = true; } } } // // Step 2: Default operations on CLI native types. // // // Step 0: String concatenation (because overloading will get this wrong) // if (oper == Operator.Addition){ // // If any of the arguments is a string, cast to string // if (l == TypeManager.string_type){ if (r == TypeManager.void_type) { Error_OperatorCannotBeApplied (); return null; } if (r == TypeManager.string_type){ if (left is Constant && right is Constant){ StringConstant ls = (StringConstant) left; StringConstant rs = (StringConstant) right; return new StringConstant ( ls.Value + rs.Value); } if (left is Binary){ Binary b = (Binary) left; // // Call String.Concat (string, string, string) or // String.Concat (string, string, string, string) // if possible. // if (b.oper == Operator.Addition && (b.method == TypeManager.string_concat_string_string_string || b.method == TypeManager.string_concat_string_string_string_string)){ ArrayList bargs = b.Arguments; int count = bargs.Count; if (count == 2){ Arguments = bargs; Arguments.Add (new Argument (right, Argument.AType.Expression)); type = TypeManager.string_type; method = TypeManager.string_concat_string_string_string; return this; } else if (count == 3){ Arguments = bargs; Arguments.Add (new Argument (right, Argument.AType.Expression)); type = TypeManager.string_type; method = TypeManager.string_concat_string_string_string_string; return this; } } } // string + string method = TypeManager.string_concat_string_string; } else { // string + object method = TypeManager.string_concat_object_object; right = ConvertImplicit (ec, right, TypeManager.object_type, loc); if (right == null){ Error_OperatorCannotBeApplied (loc, OperName (oper), l, r); return null; } } type = TypeManager.string_type; Arguments = new ArrayList (); Arguments.Add (new Argument (left, Argument.AType.Expression)); Arguments.Add (new Argument (right, Argument.AType.Expression)); return this; } else if (r == TypeManager.string_type){ // object + string if (l == TypeManager.void_type) { Error_OperatorCannotBeApplied (); return null; } method = TypeManager.string_concat_object_object; left = ConvertImplicit (ec, left, TypeManager.object_type, loc); if (left == null){ Error_OperatorCannotBeApplied (loc, OperName (oper), l, r); return null; } Arguments = new ArrayList (); Arguments.Add (new Argument (left, Argument.AType.Expression)); Arguments.Add (new Argument (right, Argument.AType.Expression)); type = TypeManager.string_type; return this; } // // 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; } } } if (oper == Operator.Equality || oper == Operator.Inequality){ if (l == TypeManager.bool_type || r == TypeManager.bool_type){ if (r != TypeManager.bool_type || l != TypeManager.bool_type){ Error_OperatorCannotBeApplied (); return null; } type = TypeManager.bool_type; return this; } // // operator != (object a, object b) // operator == (object a, object b) // // For this to be used, both arguments have to be reference-types. // Read the rationale on the spec (14.9.6) // // Also, if at compile time we know that the classes do not inherit // one from the other, then we catch the error there. // if (!(l.IsValueType || r.IsValueType)){ type = TypeManager.bool_type; if (l == r) return this; if (l.IsSubclassOf (r) || r.IsSubclassOf (l)) return this; // // Also, a standard conversion must exist from either one // if (!(StandardConversionExists (left, r) || StandardConversionExists (right, l))){ Error_OperatorCannotBeApplied (); return null; } // // We are going to have to convert to an object to compare // if (l != TypeManager.object_type) left = new EmptyCast (left, TypeManager.object_type); if (r != TypeManager.object_type) right = new EmptyCast (right, TypeManager.object_type); // // FIXME: CSC here catches errors cs254 and cs252 // return this; } // // One of them is a valuetype, but the other one is not. // if (!l.IsValueType || !r.IsValueType) { Error_OperatorCannotBeApplied (); return null; } } // Only perform numeric promotions on: // +, -, *, /, %, &, |, ^, ==, !=, <, >, <=, >= // if (oper == Operator.Addition || oper == Operator.Subtraction) { if (l.IsSubclassOf (TypeManager.delegate_type) && r.IsSubclassOf (TypeManager.delegate_type)) { Arguments = new ArrayList (); Arguments.Add (new Argument (left, Argument.AType.Expression)); Arguments.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 (l != r) { Error_OperatorCannotBeApplied (); return null; } DelegateOperation = true; type = l; return this; } // // Pointer arithmetic: // // T* operator + (T* x, int y); // T* operator + (T* x, uint y); // T* operator + (T* x, long y); // T* operator + (T* x, ulong y); // // T* operator + (int y, T* x); // T* operator + (uint y, T *x); // T* operator + (long y, T *x); // T* operator + (ulong y, T *x); // // T* operator - (T* x, int y); // T* operator - (T* x, uint y); // T* operator - (T* x, long y); // T* operator - (T* x, ulong y); // // long operator - (T* x, T *y) // if (l.IsPointer){ if (r.IsPointer && oper == Operator.Subtraction){ if (r == l) return new PointerArithmetic ( false, left, right, TypeManager.int64_type, loc); } else if (is_32_or_64 (r)) return new PointerArithmetic ( oper == Operator.Addition, left, right, l, loc); } else if (r.IsPointer && is_32_or_64 (l) && oper == Operator.Addition) return new PointerArithmetic ( true, right, left, r, loc); } // // Enumeration operators // bool lie = TypeManager.IsEnumType (l); bool rie = TypeManager.IsEnumType (r); if (lie || rie){ Expression temp; // U operator - (E e, E f) if (lie && rie && oper == Operator.Subtraction){ if (l == r){ type = TypeManager.EnumToUnderlying (l); return this; } Error_OperatorCannotBeApplied (); return null; } // // operator + (E e, U x) // operator - (E e, U x) // if (oper == Operator.Addition || oper == Operator.Subtraction){ Type enum_type = lie ? l : r; Type other_type = lie ? r : l; Type underlying_type = TypeManager.EnumToUnderlying (enum_type); ; if (underlying_type != other_type){ Error_OperatorCannotBeApplied (); return null; } type = enum_type; return this; } if (!rie){ temp = ConvertImplicit (ec, right, l, loc); if (temp != null) right = temp; else { Error_OperatorCannotBeApplied (); return null; } } if (!lie){ temp = ConvertImplicit (ec, left, r, loc); if (temp != null){ left = temp; l = r; } else { Error_OperatorCannotBeApplied (); return null; } } if (oper == Operator.Equality || oper == Operator.Inequality || oper == Operator.LessThanOrEqual || oper == Operator.LessThan || oper == Operator.GreaterThanOrEqual || oper == Operator.GreaterThan){ type = TypeManager.bool_type; return this; } if (oper == Operator.BitwiseAnd || oper == Operator.BitwiseOr || oper == Operator.ExclusiveOr){ type = l; return this; } Error_OperatorCannotBeApplied (); return null; } if (oper == Operator.LeftShift || oper == Operator.RightShift) return CheckShiftArguments (ec); if (oper == Operator.LogicalOr || oper == Operator.LogicalAnd){ if (l != TypeManager.bool_type || r != TypeManager.bool_type){ Error_OperatorCannotBeApplied (); return null; } type = TypeManager.bool_type; return this; } // // operator & (bool x, bool y) // operator | (bool x, bool y) // operator ^ (bool x, bool y) // if (l == TypeManager.bool_type && r == TypeManager.bool_type){ if (oper == Operator.BitwiseAnd || oper == Operator.BitwiseOr || oper == Operator.ExclusiveOr){ type = l; return this; } } // // Pointer comparison // if (l.IsPointer && r.IsPointer){ if (oper == Operator.Equality || oper == Operator.Inequality || oper == Operator.LessThan || oper == Operator.LessThanOrEqual || oper == Operator.GreaterThan || oper == Operator.GreaterThanOrEqual){ type = TypeManager.bool_type; return this; } } // // We are dealing with numbers // if (overload_failed){ Error_OperatorCannotBeApplied (); return null; } // // This will leave left or right set to null if there is an error // bool check_user_conv = is_user_defined (l) && is_user_defined (r); DoNumericPromotions (ec, l, r, check_user_conv); if (left == null || right == null){ Error_OperatorCannotBeApplied (loc, OperName (oper), l, r); return null; } // // reload our cached types if required // l = left.Type; r = right.Type; if (oper == Operator.BitwiseAnd || oper == Operator.BitwiseOr || oper == Operator.ExclusiveOr){ if (l == r){ if (!((l == TypeManager.int32_type) || (l == TypeManager.uint32_type) || (l == TypeManager.int64_type) || (l == TypeManager.uint64_type))) type = l; } else { Error_OperatorCannotBeApplied (); return null; } } if (oper == Operator.Equality || oper == Operator.Inequality || oper == Operator.LessThanOrEqual || oper == Operator.LessThan || oper == Operator.GreaterThanOrEqual || oper == Operator.GreaterThan){ type = TypeManager.bool_type; } return this; }