protected override Expression DoResolve(ResolveContext ec) { unwrap = Unwrap.Create(Expr, false); if (unwrap == null) { return(null); } Expression res = base.ResolveOperator(ec, unwrap); if (res == null) { Error_OperatorCannotBeApplied(ec, loc, OperName(Oper), Expr.Type); return(null); } if (res != this) { if (user_operator == null) { return(res); } } else { res = Expr = LiftExpression(ec, Expr); } if (res == null) { return(null); } eclass = ExprClass.Value; type = res.Type; return(this); }
public override Expression DoResolve(ResolveContext ec) { if (eclass != ExprClass.Invalid) { return(this); } unwrap = Unwrap.Create(Expr, false); if (unwrap == null) { return(null); } Expression res = base.ResolveOperator(ec, unwrap); if (res != this) { if (user_operator == null) { return(res); } } else { res = Expr = LiftExpression(ec, Expr); } if (res == null) { return(null); } eclass = ExprClass.Value; type = res.Type; return(this); }
Expression ConvertExpression(ResolveContext ec) { // TODO: ImplicitConversionExists should take care of this if (left.eclass == ExprClass.MethodGroup) { return(null); } TypeSpec ltype = left.Type; // // If left is a nullable type and an implicit conversion exists from right to underlying type of left, // the result is underlying type of left // if (ltype.IsNullableType) { unwrap = Unwrap.Create(left, false); if (unwrap == null) { return(null); } // // Reduce (left ?? null) to left // if (right.IsNull) { return(ReducedExpression.Create(left, this)); } Expression conv; if (right.Type.IsNullableType) { conv = right.Type == ltype ? right : Convert.ImplicitNulableConversion(ec, right, ltype); if (conv != null) { right = conv; type = ltype; return(this); } } else { conv = Convert.ImplicitConversion(ec, right, unwrap.Type, loc); if (conv != null) { left = unwrap; ltype = left.Type; // // If right is a dynamic expression, the result type is dynamic // if (right.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { type = right.Type; // Need to box underlying value type left = Convert.ImplicitBoxingConversion(left, ltype, type); return(this); } right = conv; type = ltype; return(this); } } } else if (TypeSpec.IsReferenceType(ltype)) { if (Convert.ImplicitConversionExists(ec, right, ltype)) { // // If right is a dynamic expression, the result type is dynamic // if (right.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { type = right.Type; return(this); } // // Reduce ("foo" ?? expr) to expression // Constant lc = left as Constant; if (lc != null && !lc.IsDefaultValue) { return(ReducedExpression.Create(lc, this, false)); } // // Reduce (left ?? null) to left OR (null-constant ?? right) to right // if (right.IsNull || lc != null) { // // Special case null ?? null // if (right.IsNull && ltype == right.Type) { return(null); } return(ReducedExpression.Create(lc != null ? right : left, this, false)); } right = Convert.ImplicitConversion(ec, right, ltype, loc); type = ltype; return(this); } } else { return(null); } TypeSpec rtype = right.Type; if (!Convert.ImplicitConversionExists(ec, unwrap ?? left, rtype) || right.eclass == ExprClass.MethodGroup) { return(null); } // // Reduce (null ?? right) to right // if (left.IsNull) { return(ReducedExpression.Create(right, this, false).Resolve(ec)); } left = Convert.ImplicitConversion(ec, unwrap ?? left, rtype, loc); user_conversion_left = left is UserCast; type = rtype; return(this); }
Expression ConvertExpression(ResolveContext ec) { // TODO: ImplicitConversionExists should take care of this if (left.eclass == ExprClass.MethodGroup) { return(null); } Type ltype = left.Type; // // If left is a nullable type and an implicit conversion exists from right to underlying type of left, // the result is underlying type of left // if (TypeManager.IsNullableType(ltype)) { unwrap = Unwrap.Create(left, false); if (unwrap == null) { return(null); } if (Convert.ImplicitConversionExists(ec, right, unwrap.Type)) { left = unwrap; type = left.Type; right = Convert.ImplicitConversion(ec, right, type, loc); return(this); } } else if (TypeManager.IsReferenceType(ltype)) { if (Convert.ImplicitConversionExists(ec, right, ltype)) { // // Reduce (constant ?? expr) to constant // Constant lc = left as Constant; if (lc != null && !lc.IsDefaultValue) { return(new SideEffectConstant(lc, right, loc).Resolve(ec)); } // // Reduce (left ?? null) to left OR (null-constant ?? right) to right // if (right.IsNull || lc != null) { return(ReducedExpression.Create(lc != null ? right : left, this).Resolve(ec)); } right = Convert.ImplicitConversion(ec, right, ltype, loc); type = left.Type; return(this); } } else { return(null); } Type rtype = right.Type; if (!Convert.ImplicitConversionExists(ec, unwrap != null ? unwrap : left, rtype) || right.eclass == ExprClass.MethodGroup) { return(null); } // // Reduce (null ?? right) to right // if (left.IsNull) { return(ReducedExpression.Create(right, this).Resolve(ec)); } left = Convert.ImplicitConversion(ec, unwrap != null ? unwrap : left, rtype, loc); type = rtype; return(this); }