示例#1
0
        protected override Expression DoResolve(ResolveContext rc)
        {
            if (rc.HasSet(ResolveContext.Options.LockScope))
            {
                rc.Report.Error(1996, loc,
                                "The `await' operator cannot be used in the body of a lock statement");
            }

            if (rc.IsUnsafe)
            {
                rc.Report.Error(4004, loc,
                                "The `await' operator cannot be used in an unsafe context");
            }

            var bc = (BlockContext)rc;

            stmt = new AwaitStatement(expr, loc);
            if (!stmt.Resolve(bc))
            {
                return(null);
            }

            type   = stmt.ResultType;
            eclass = ExprClass.Variable;
            return(this);
        }
示例#2
0
        public Expression CreateCallSiteBinder(ResolveContext ec, Arguments args)
        {
            Arguments binder_args = new Arguments(3);

            flags |= ec.HasSet(ResolveContext.Options.CheckedScope) ? CSharpBinderFlags.CheckedContext : 0;

            binder_args.Add(new Argument(new BinderFlags(flags, this)));
            binder_args.Add(new Argument(new TypeOf(type, loc)));
            binder_args.Add(new Argument(new TypeOf(ec.CurrentType, loc)));
            return(new Invocation(GetBinder("Convert", loc), binder_args));
        }
示例#3
0
        public BlockContext(ResolveContext rc, ExplicitBlock block, TypeSpec returnType)
            : this(rc.MemberContext, block, returnType)
        {
            if (rc.IsUnsafe)
            {
                flags |= ResolveContext.Options.UnsafeScope;
            }

            if (rc.HasSet(ResolveContext.Options.CheckedScope))
            {
                flags |= ResolveContext.Options.CheckedScope;
            }

            if (!rc.ConstantCheckState)
            {
                flags &= ~Options.ConstantCheckState;
            }

            if (rc.IsInProbingMode)
            {
                flags |= ResolveContext.Options.ProbingMode;
            }

            if (rc.HasSet(ResolveContext.Options.FieldInitializerScope))
            {
                flags |= ResolveContext.Options.FieldInitializerScope;
            }

            if (rc.HasSet(ResolveContext.Options.ExpressionTreeConversion))
            {
                flags |= ResolveContext.Options.ExpressionTreeConversion;
            }

            if (rc.HasSet(ResolveContext.Options.BaseInitializer))
            {
                flags |= ResolveContext.Options.BaseInitializer;
            }
        }
示例#4
0
        public Expression CreateCallSiteBinder(ResolveContext ec, Arguments args)
        {
            Arguments binder_args = new Arguments(4);

            MemberAccess sle = new MemberAccess(new MemberAccess(
                                                    new QualifiedAliasMember(QualifiedAliasMember.GlobalAlias, "System", loc), "Linq", loc), "Expressions", loc);

            var flags = ec.HasSet(ResolveContext.Options.CheckedScope) ? CSharpBinderFlags.CheckedContext : 0;

            binder_args.Add(new Argument(new BinderFlags(flags, this)));
            binder_args.Add(new Argument(new MemberAccess(new MemberAccess(sle, "ExpressionType", loc), name, loc)));
            binder_args.Add(new Argument(new TypeOf(ec.CurrentType, loc)));
            binder_args.Add(new Argument(new ImplicitlyTypedArrayCreation(args.CreateDynamicBinderArguments(ec), loc)));

            return(new Invocation(GetBinder("UnaryOperation", loc), binder_args));
        }
示例#5
0
		/// <summary>
		///   Constant expression folder for binary operations.
		///
		///   Returns null if the expression can not be folded.
		/// </summary>
		static public Constant BinaryFold (ResolveContext ec, Binary.Operator oper,
						     Constant left, Constant right, Location loc)
		{
			Constant result = null;

			if (left is EmptyConstantCast)
				return BinaryFold (ec, oper, ((EmptyConstantCast)left).child, right, loc);

			if (left is SideEffectConstant) {
				result = BinaryFold (ec, oper, ((SideEffectConstant) left).value, right, loc);
				if (result == null)
					return null;
				return new SideEffectConstant (result, left, loc);
			}

			if (right is EmptyConstantCast)
				return BinaryFold (ec, oper, left, ((EmptyConstantCast)right).child, loc);

			if (right is SideEffectConstant) {
				result = BinaryFold (ec, oper, left, ((SideEffectConstant) right).value, loc);
				if (result == null)
					return null;
				return new SideEffectConstant (result, right, loc);
			}

			TypeSpec lt = left.Type;
			TypeSpec rt = right.Type;
			bool bool_res;

			if (lt.BuiltinType == BuiltinTypeSpec.Type.Bool && lt == rt) {
				bool lv = (bool) left.GetValue ();
				bool rv = (bool) right.GetValue ();			
				switch (oper) {
				case Binary.Operator.BitwiseAnd:
				case Binary.Operator.LogicalAnd:
					return new BoolConstant (ec.BuiltinTypes, lv && rv, left.Location);
				case Binary.Operator.BitwiseOr:
				case Binary.Operator.LogicalOr:
					return new BoolConstant (ec.BuiltinTypes, lv || rv, left.Location);
				case Binary.Operator.ExclusiveOr:
					return new BoolConstant (ec.BuiltinTypes, lv ^ rv, left.Location);
				case Binary.Operator.Equality:
					return new BoolConstant (ec.BuiltinTypes, lv == rv, left.Location);
				case Binary.Operator.Inequality:
					return new BoolConstant (ec.BuiltinTypes, lv != rv, left.Location);
				}
				return null;
			}

			//
			// During an enum evaluation, none of the rules are valid
			// Not sure whether it is bug in csc or in documentation
			//
			if (ec.HasSet (ResolveContext.Options.EnumScope)){
				if (left is EnumConstant)
					left = ((EnumConstant) left).Child;
				
				if (right is EnumConstant)
					right = ((EnumConstant) right).Child;
			} else if (left is EnumConstant && rt == lt) {
				switch (oper){
					///
					/// E operator |(E x, E y);
					/// E operator &(E x, E y);
					/// E operator ^(E x, E y);
					/// 
					case Binary.Operator.BitwiseOr:
					case Binary.Operator.BitwiseAnd:
					case Binary.Operator.ExclusiveOr:
						result = BinaryFold (ec, oper, ((EnumConstant)left).Child, ((EnumConstant)right).Child, loc);
						if (result != null)
							result = result.Reduce (ec, lt);
						return result;

					///
					/// U operator -(E x, E y);
					/// 
					case Binary.Operator.Subtraction:
						result = BinaryFold (ec, oper, ((EnumConstant)left).Child, ((EnumConstant)right).Child, loc);
						if (result != null)
							result = result.Reduce (ec, EnumSpec.GetUnderlyingType (lt));
						return result;

					///
					/// bool operator ==(E x, E y);
					/// bool operator !=(E x, E y);
					/// bool operator <(E x, E y);
					/// bool operator >(E x, E y);
					/// bool operator <=(E x, E y);
					/// bool operator >=(E x, E y);
					/// 
					case Binary.Operator.Equality:				
					case Binary.Operator.Inequality:
					case Binary.Operator.LessThan:				
					case Binary.Operator.GreaterThan:
					case Binary.Operator.LessThanOrEqual:				
					case Binary.Operator.GreaterThanOrEqual:
						return BinaryFold(ec, oper, ((EnumConstant)left).Child, ((EnumConstant)right).Child, loc);
				}
				return null;
			}

			switch (oper){
			case Binary.Operator.BitwiseOr:
				//
				// bool? operator |(bool? x, bool? y);
				//
				if ((lt.BuiltinType == BuiltinTypeSpec.Type.Bool && right is NullLiteral) ||
					(rt.BuiltinType == BuiltinTypeSpec.Type.Bool && left is NullLiteral)) {
					var b = new Binary (oper, left, right).ResolveOperator (ec);

					// false | null => null
					// null | false => null
					if ((right is NullLiteral && left.IsDefaultValue) || (left is NullLiteral && right.IsDefaultValue))
						return Nullable.LiftedNull.CreateFromExpression (ec, b);

					// true | null => true
					// null | true => true
					return ReducedExpression.Create (new BoolConstant (ec.BuiltinTypes, true, loc), b);					
				}

				if (!DoBinaryNumericPromotions (ec, ref left, ref right))
					return null;

				if (left is IntConstant){
					int res = ((IntConstant) left).Value | ((IntConstant) right).Value;

					return new IntConstant (ec.BuiltinTypes, res, left.Location);
				}
				if (left is UIntConstant){
					uint res = ((UIntConstant)left).Value | ((UIntConstant)right).Value;

					return new UIntConstant (ec.BuiltinTypes, res, left.Location);
				}
				if (left is LongConstant){
					long res = ((LongConstant)left).Value | ((LongConstant)right).Value;

					return new LongConstant (ec.BuiltinTypes, res, left.Location);
				}
				if (left is ULongConstant){
					ulong res = ((ULongConstant)left).Value |
						((ULongConstant)right).Value;

					return new ULongConstant (ec.BuiltinTypes, res, left.Location);
				}
				break;
				
			case Binary.Operator.BitwiseAnd:
				//
				// bool? operator &(bool? x, bool? y);
				//
				if ((lt.BuiltinType == BuiltinTypeSpec.Type.Bool && right is NullLiteral) ||
					(rt.BuiltinType == BuiltinTypeSpec.Type.Bool && left is NullLiteral)) {
					var b = new Binary (oper, left, right).ResolveOperator (ec);

					// false & null => false
					// null & false => false
					if ((right is NullLiteral && left.IsDefaultValue) || (left is NullLiteral && right.IsDefaultValue))
						return ReducedExpression.Create (new BoolConstant (ec.BuiltinTypes, false, loc), b);

					// true & null => null
					// null & true => null
					return Nullable.LiftedNull.CreateFromExpression (ec, b);
				}

				if (!DoBinaryNumericPromotions (ec, ref left, ref right))
					return null;
				
				///
				/// int operator &(int x, int y);
				/// uint operator &(uint x, uint y);
				/// long operator &(long x, long y);
				/// ulong operator &(ulong x, ulong y);
				///
				if (left is IntConstant){
					int res = ((IntConstant) left).Value & ((IntConstant) right).Value;
					return new IntConstant (ec.BuiltinTypes, res, left.Location);
				}
				if (left is UIntConstant){
					uint res = ((UIntConstant)left).Value & ((UIntConstant)right).Value;
					return new UIntConstant (ec.BuiltinTypes, res, left.Location);
				}
				if (left is LongConstant){
					long res = ((LongConstant)left).Value & ((LongConstant)right).Value;
					return new LongConstant (ec.BuiltinTypes, res, left.Location);
				}
				if (left is ULongConstant){
					ulong res = ((ULongConstant)left).Value &
						((ULongConstant)right).Value;

					return new ULongConstant (ec.BuiltinTypes, res, left.Location);
				}
				break;

			case Binary.Operator.ExclusiveOr:
				if (!DoBinaryNumericPromotions (ec, ref left, ref right))
					return null;
				
				if (left is IntConstant){
					int res = ((IntConstant) left).Value ^ ((IntConstant) right).Value;
					return new IntConstant (ec.BuiltinTypes, res, left.Location);
				}
				if (left is UIntConstant){
					uint res = ((UIntConstant)left).Value ^ ((UIntConstant)right).Value;

					return new UIntConstant (ec.BuiltinTypes, res, left.Location);
				}
				if (left is LongConstant){
					long res = ((LongConstant)left).Value ^ ((LongConstant)right).Value;

					return new LongConstant (ec.BuiltinTypes, res, left.Location);
				}
				if (left is ULongConstant){
					ulong res = ((ULongConstant)left).Value ^
						((ULongConstant)right).Value;

					return new ULongConstant (ec.BuiltinTypes, res, left.Location);
				}
				break;

			case Binary.Operator.Addition:
				//
				// If both sides are strings, then concatenate
				//
				// string operator + (string x, string y)
				//
				if (lt.BuiltinType == BuiltinTypeSpec.Type.String || rt.BuiltinType == BuiltinTypeSpec.Type.String){
					if (lt == rt)
						return new StringConstant (ec.BuiltinTypes, (string)left.GetValue () + (string)right.GetValue (),
							left.Location);

					if (lt == InternalType.NullLiteral || left.IsNull)
						return new StringConstant (ec.BuiltinTypes, "" + right.GetValue (), left.Location);

					if (rt == InternalType.NullLiteral || right.IsNull)
						return new StringConstant (ec.BuiltinTypes, left.GetValue () + "", left.Location);

					return null;
				}

				//
				// string operator + (string x, object y)
				//
				if (lt == InternalType.NullLiteral) {
					if (rt.BuiltinType == BuiltinTypeSpec.Type.Object)
						return new StringConstant (ec.BuiltinTypes, "" + right.GetValue (), left.Location);

					if (lt == rt) {
						ec.Report.Error (34, loc, "Operator `{0}' is ambiguous on operands of type `{1}' and `{2}'",
							"+", lt.GetSignatureForError (), rt.GetSignatureForError ());
						return null;
					}

					return right;
				}

				//
				// string operator + (object x, string y)
				//
				if (rt == InternalType.NullLiteral) {
					if (lt.BuiltinType == BuiltinTypeSpec.Type.Object)
						return new StringConstant (ec.BuiltinTypes, right.GetValue () + "", left.Location);
	
					return left;
				}

				//
				// handle "E operator + (E x, U y)"
				// handle "E operator + (Y y, E x)"
				//
				EnumConstant lc = left as EnumConstant;
				EnumConstant rc = right as EnumConstant;
				if (lc != null || rc != null){
					if (lc == null) {
						lc = rc;
						lt = lc.Type;
						right = left;
					}

					// U has to be implicitly convetible to E.base
					right = right.ConvertImplicitly (lc.Child.Type);
					if (right == null)
						return null;

					result = BinaryFold (ec, oper, lc.Child, right, loc);
					if (result == null)
						return null;

					result = result.Reduce (ec, lt);
					if (result == null || lt.IsEnum)
						return result;

					return new EnumConstant (result, lt);
				}

				if (!DoBinaryNumericPromotions (ec, ref left, ref right))
					return null;

				try {
					if (left is DoubleConstant){
						double res;
						
						if (ec.ConstantCheckState)
							res = checked (((DoubleConstant) left).Value +
								       ((DoubleConstant) right).Value);
						else
							res = unchecked (((DoubleConstant) left).Value +
									 ((DoubleConstant) right).Value);

						return new DoubleConstant (ec.BuiltinTypes, res, left.Location);
					}
					if (left is FloatConstant){
						double a, b, res;
						a = ((FloatConstant) left).DoubleValue;
						b = ((FloatConstant) right).DoubleValue;

						if (ec.ConstantCheckState)
							res = checked (a + b);
						else
							res = unchecked (a + b);

						result = new FloatConstant (ec.BuiltinTypes, res, left.Location);
					} else if (left is ULongConstant){
						ulong res;
						
						if (ec.ConstantCheckState)
							res = checked (((ULongConstant) left).Value +
								       ((ULongConstant) right).Value);
						else
							res = unchecked (((ULongConstant) left).Value +
									 ((ULongConstant) right).Value);

						result = new ULongConstant (ec.BuiltinTypes, res, left.Location);
					} else if (left is LongConstant){
						long res;
						
						if (ec.ConstantCheckState)
							res = checked (((LongConstant) left).Value +
								       ((LongConstant) right).Value);
						else
							res = unchecked (((LongConstant) left).Value +
									 ((LongConstant) right).Value);

						result = new LongConstant (ec.BuiltinTypes, res, left.Location);
					} else if (left is UIntConstant){
						uint res;
						
						if (ec.ConstantCheckState)
							res = checked (((UIntConstant) left).Value +
								       ((UIntConstant) right).Value);
						else
							res = unchecked (((UIntConstant) left).Value +
									 ((UIntConstant) right).Value);

						result = new UIntConstant (ec.BuiltinTypes, res, left.Location);
					} else if (left is IntConstant){
						int res;

						if (ec.ConstantCheckState)
							res = checked (((IntConstant) left).Value +
								       ((IntConstant) right).Value);
						else
							res = unchecked (((IntConstant) left).Value +
									 ((IntConstant) right).Value);

						result = new IntConstant (ec.BuiltinTypes, res, left.Location);
					} else if (left is DecimalConstant) {
						decimal res;

						if (ec.ConstantCheckState)
							res = checked (((DecimalConstant) left).Value +
								((DecimalConstant) right).Value);
						else
							res = unchecked (((DecimalConstant) left).Value +
								((DecimalConstant) right).Value);

						result = new DecimalConstant (ec.BuiltinTypes, res, left.Location);
					}
				} catch (OverflowException){
					Error_CompileTimeOverflow (ec, loc);
				}

				return result;

			case Binary.Operator.Subtraction:
				//
				// handle "E operator - (E x, U y)"
				// handle "E operator - (Y y, E x)"
				//
				lc = left as EnumConstant;
				rc = right as EnumConstant;
				if (lc != null || rc != null){
					if (lc == null) {
						lc = rc;
						lt = lc.Type;
						right = left;
					}

					// U has to be implicitly convetible to E.base
					right = right.ConvertImplicitly (lc.Child.Type);
					if (right == null)
						return null;

					result = BinaryFold (ec, oper, lc.Child, right, loc);
					if (result == null)
						return null;

					result = result.Reduce (ec, lt);
					if (result == null)
						return null;

					return new EnumConstant (result, lt);
				}

				if (left is NullLiteral && right is NullLiteral) {
					var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc);
					lifted_int.ResolveAsType (ec);
					return (Constant) new Binary (oper, lifted_int, right).ResolveOperator (ec);
				}

				if (!DoBinaryNumericPromotions (ec, ref left, ref right))
					return null;

				try {
					if (left is DoubleConstant){
						double res;
						
						if (ec.ConstantCheckState)
							res = checked (((DoubleConstant) left).Value -
								       ((DoubleConstant) right).Value);
						else
							res = unchecked (((DoubleConstant) left).Value -
									 ((DoubleConstant) right).Value);

						result = new DoubleConstant (ec.BuiltinTypes, res, left.Location);
					} else if (left is FloatConstant){
						double a, b, res;
						a = ((FloatConstant) left).DoubleValue;
						b = ((FloatConstant) right).DoubleValue;

						if (ec.ConstantCheckState)
							res = checked (a - b);
						else
							res = unchecked (a - b);

						result = new FloatConstant (ec.BuiltinTypes, res, left.Location);
					} else if (left is ULongConstant){
						ulong res;
						
						if (ec.ConstantCheckState)
							res = checked (((ULongConstant) left).Value -
								       ((ULongConstant) right).Value);
						else
							res = unchecked (((ULongConstant) left).Value -
									 ((ULongConstant) right).Value);

						result = new ULongConstant (ec.BuiltinTypes, res, left.Location);
					} else if (left is LongConstant){
						long res;
						
						if (ec.ConstantCheckState)
							res = checked (((LongConstant) left).Value -
								       ((LongConstant) right).Value);
						else
							res = unchecked (((LongConstant) left).Value -
									 ((LongConstant) right).Value);

						result = new LongConstant (ec.BuiltinTypes, res, left.Location);
					} else if (left is UIntConstant){
						uint res;
						
						if (ec.ConstantCheckState)
							res = checked (((UIntConstant) left).Value -
								       ((UIntConstant) right).Value);
						else
							res = unchecked (((UIntConstant) left).Value -
									 ((UIntConstant) right).Value);

						result = new UIntConstant (ec.BuiltinTypes, res, left.Location);
					} else if (left is IntConstant){
						int res;

						if (ec.ConstantCheckState)
							res = checked (((IntConstant) left).Value -
								       ((IntConstant) right).Value);
						else
							res = unchecked (((IntConstant) left).Value -
									 ((IntConstant) right).Value);

						result = new IntConstant (ec.BuiltinTypes, res, left.Location);
					} else if (left is DecimalConstant) {
						decimal res;

						if (ec.ConstantCheckState)
							res = checked (((DecimalConstant) left).Value -
								((DecimalConstant) right).Value);
						else
							res = unchecked (((DecimalConstant) left).Value -
								((DecimalConstant) right).Value);

						return new DecimalConstant (ec.BuiltinTypes, res, left.Location);
					} else {
						throw new Exception ( "Unexepected subtraction input: " + left);
					}
				} catch (OverflowException){
					Error_CompileTimeOverflow (ec, loc);
				}

				return result;
				
			case Binary.Operator.Multiply:
				if (left is NullLiteral && right is NullLiteral) {
					var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc);
					lifted_int.ResolveAsType (ec);
					return (Constant) new Binary (oper, lifted_int, right).ResolveOperator (ec);
				}

				if (!DoBinaryNumericPromotions (ec, ref left, ref right))
					return null;

				try {
					if (left is DoubleConstant){
						double res;
						
						if (ec.ConstantCheckState)
							res = checked (((DoubleConstant) left).Value *
								((DoubleConstant) right).Value);
						else
							res = unchecked (((DoubleConstant) left).Value *
								((DoubleConstant) right).Value);

						return new DoubleConstant (ec.BuiltinTypes, res, left.Location);
					} else if (left is FloatConstant){
						double a, b, res;
						a = ((FloatConstant) left).DoubleValue;
						b = ((FloatConstant) right).DoubleValue;

						if (ec.ConstantCheckState)
							res = checked (a * b);
						else
							res = unchecked (a * b);

						return new FloatConstant (ec.BuiltinTypes, res, left.Location);
					} else if (left is ULongConstant){
						ulong res;
						
						if (ec.ConstantCheckState)
							res = checked (((ULongConstant) left).Value *
								((ULongConstant) right).Value);
						else
							res = unchecked (((ULongConstant) left).Value *
								((ULongConstant) right).Value);

						return new ULongConstant (ec.BuiltinTypes, res, left.Location);
					} else if (left is LongConstant){
						long res;
						
						if (ec.ConstantCheckState)
							res = checked (((LongConstant) left).Value *
								((LongConstant) right).Value);
						else
							res = unchecked (((LongConstant) left).Value *
								((LongConstant) right).Value);

						return new LongConstant (ec.BuiltinTypes, res, left.Location);
					} else if (left is UIntConstant){
						uint res;
						
						if (ec.ConstantCheckState)
							res = checked (((UIntConstant) left).Value *
								((UIntConstant) right).Value);
						else
							res = unchecked (((UIntConstant) left).Value *
								((UIntConstant) right).Value);

						return new UIntConstant (ec.BuiltinTypes, res, left.Location);
					} else if (left is IntConstant){
						int res;

						if (ec.ConstantCheckState)
							res = checked (((IntConstant) left).Value *
								((IntConstant) right).Value);
						else
							res = unchecked (((IntConstant) left).Value *
								((IntConstant) right).Value);

						return new IntConstant (ec.BuiltinTypes, res, left.Location);
					} else if (left is DecimalConstant) {
						decimal res;

						if (ec.ConstantCheckState)
							res = checked (((DecimalConstant) left).Value *
								((DecimalConstant) right).Value);
						else
							res = unchecked (((DecimalConstant) left).Value *
								((DecimalConstant) right).Value);

						return new DecimalConstant (ec.BuiltinTypes, res, left.Location);
					} else {
						throw new Exception ( "Unexepected multiply input: " + left);
					}
				} catch (OverflowException){
					Error_CompileTimeOverflow (ec, loc);
				}
				break;

			case Binary.Operator.Division:
				if (left is NullLiteral && right is NullLiteral) {
					var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc);
					lifted_int.ResolveAsType (ec);
					return (Constant) new Binary (oper, lifted_int, right).ResolveOperator (ec);
				}

				if (!DoBinaryNumericPromotions (ec, ref left, ref right))
					return null;

				try {
					if (left is DoubleConstant){
						double res;
						
						if (ec.ConstantCheckState)
							res = checked (((DoubleConstant) left).Value /
								((DoubleConstant) right).Value);
						else
							res = unchecked (((DoubleConstant) left).Value /
								((DoubleConstant) right).Value);

						return new DoubleConstant (ec.BuiltinTypes, res, left.Location);
					} else if (left is FloatConstant){
						double a, b, res;
						a = ((FloatConstant) left).DoubleValue;
						b = ((FloatConstant) right).DoubleValue;

						if (ec.ConstantCheckState)
							res = checked (a / b);
						else
							res = unchecked (a / b);

						return new FloatConstant (ec.BuiltinTypes, res, left.Location);
					} else if (left is ULongConstant){
						ulong res;
						
						if (ec.ConstantCheckState)
							res = checked (((ULongConstant) left).Value /
								((ULongConstant) right).Value);
						else
							res = unchecked (((ULongConstant) left).Value /
								((ULongConstant) right).Value);

						return new ULongConstant (ec.BuiltinTypes, res, left.Location);
					} else if (left is LongConstant){
						long res;
						
						if (ec.ConstantCheckState)
							res = checked (((LongConstant) left).Value /
								((LongConstant) right).Value);
						else
							res = unchecked (((LongConstant) left).Value /
								((LongConstant) right).Value);

						return new LongConstant (ec.BuiltinTypes, res, left.Location);
					} else if (left is UIntConstant){
						uint res;
						
						if (ec.ConstantCheckState)
							res = checked (((UIntConstant) left).Value /
								((UIntConstant) right).Value);
						else
							res = unchecked (((UIntConstant) left).Value /
								((UIntConstant) right).Value);

						return new UIntConstant (ec.BuiltinTypes, res, left.Location);
					} else if (left is IntConstant){
						int res;

						if (ec.ConstantCheckState)
							res = checked (((IntConstant) left).Value /
								((IntConstant) right).Value);
						else
							res = unchecked (((IntConstant) left).Value /
								((IntConstant) right).Value);

						return new IntConstant (ec.BuiltinTypes, res, left.Location);
					} else if (left is DecimalConstant) {
						decimal res;

						if (ec.ConstantCheckState)
							res = checked (((DecimalConstant) left).Value /
								((DecimalConstant) right).Value);
						else
							res = unchecked (((DecimalConstant) left).Value /
								((DecimalConstant) right).Value);

						return new DecimalConstant (ec.BuiltinTypes, res, left.Location);
					} else {
						throw new Exception ( "Unexepected division input: " + left);
					}
				} catch (OverflowException){
					Error_CompileTimeOverflow (ec, loc);

				} catch (DivideByZeroException) {
					ec.Report.Error (20, loc, "Division by constant zero");
				}
				
				break;
				
			case Binary.Operator.Modulus:
				if (left is NullLiteral && right is NullLiteral) {
					var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc);
					lifted_int.ResolveAsType (ec);
					return (Constant) new Binary (oper, lifted_int, right).ResolveOperator (ec);
				}

				if (!DoBinaryNumericPromotions (ec, ref left, ref right))
					return null;

				try {
					if (left is DoubleConstant){
						double res;
						
						if (ec.ConstantCheckState)
							res = checked (((DoubleConstant) left).Value %
								       ((DoubleConstant) right).Value);
						else
							res = unchecked (((DoubleConstant) left).Value %
									 ((DoubleConstant) right).Value);

						return new DoubleConstant (ec.BuiltinTypes, res, left.Location);
					} else if (left is FloatConstant){
						double a, b, res;
						a = ((FloatConstant) left).DoubleValue;
						b = ((FloatConstant) right).DoubleValue;
						
						if (ec.ConstantCheckState)
							res = checked (a % b);
						else
							res = unchecked (a % b);

						return new FloatConstant (ec.BuiltinTypes, res, left.Location);
					} else if (left is ULongConstant){
						ulong res;
						
						if (ec.ConstantCheckState)
							res = checked (((ULongConstant) left).Value %
								       ((ULongConstant) right).Value);
						else
							res = unchecked (((ULongConstant) left).Value %
									 ((ULongConstant) right).Value);

						return new ULongConstant (ec.BuiltinTypes, res, left.Location);
					} else if (left is LongConstant){
						long res;
						
						if (ec.ConstantCheckState)
							res = checked (((LongConstant) left).Value %
								       ((LongConstant) right).Value);
						else
							res = unchecked (((LongConstant) left).Value %
									 ((LongConstant) right).Value);

						return new LongConstant (ec.BuiltinTypes, res, left.Location);
					} else if (left is UIntConstant){
						uint res;
						
						if (ec.ConstantCheckState)
							res = checked (((UIntConstant) left).Value %
								       ((UIntConstant) right).Value);
						else
							res = unchecked (((UIntConstant) left).Value %
									 ((UIntConstant) right).Value);

						return new UIntConstant (ec.BuiltinTypes, res, left.Location);
					} else if (left is IntConstant){
						int res;

						if (ec.ConstantCheckState)
							res = checked (((IntConstant) left).Value %
								       ((IntConstant) right).Value);
						else
							res = unchecked (((IntConstant) left).Value %
									 ((IntConstant) right).Value);

						return new IntConstant (ec.BuiltinTypes, res, left.Location);
					}

					if (left is DecimalConstant) {
						decimal res;

						if (ec.ConstantCheckState)
							res = checked (((DecimalConstant) left).Value %
								((DecimalConstant) right).Value);
						else
							res = unchecked (((DecimalConstant) left).Value %
								((DecimalConstant) right).Value);

						return new DecimalConstant (ec.BuiltinTypes, res, left.Location);
					}

					throw new Exception ( "Unexepected modulus input: " + left);
				} catch (DivideByZeroException){
					ec.Report.Error (20, loc, "Division by constant zero");
				} catch (OverflowException){
					Error_CompileTimeOverflow (ec, loc);
				}
				break;

				//
				// There is no overflow checking on left shift
				//
			case Binary.Operator.LeftShift:
				if (left is NullLiteral && right is NullLiteral) {
					var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc);
					lifted_int.ResolveAsType (ec);
					return (Constant) new Binary (oper, lifted_int, right).ResolveOperator (ec);
				}

				IntConstant ic = right.ConvertImplicitly (ec.BuiltinTypes.Int) as IntConstant;
				if (ic == null){
					return null;
				}

				int lshift_val = ic.Value;
				switch (left.Type.BuiltinType) {
				case BuiltinTypeSpec.Type.ULong:
					return new ULongConstant (ec.BuiltinTypes, ((ULongConstant) left).Value << lshift_val, left.Location);
				case BuiltinTypeSpec.Type.Long:
					return new LongConstant (ec.BuiltinTypes, ((LongConstant) left).Value << lshift_val, left.Location);
				case BuiltinTypeSpec.Type.UInt:
					return new UIntConstant (ec.BuiltinTypes, ((UIntConstant) left).Value << lshift_val, left.Location);
				}

				// null << value => null
				if (left is NullLiteral)
					return (Constant) new Binary (oper, left, right).ResolveOperator (ec);

				left = left.ConvertImplicitly (ec.BuiltinTypes.Int);
				if (left.Type.BuiltinType == BuiltinTypeSpec.Type.Int)
					return new IntConstant (ec.BuiltinTypes, ((IntConstant) left).Value << lshift_val, left.Location);

				return null;

				//
				// There is no overflow checking on right shift
				//
			case Binary.Operator.RightShift:
				if (left is NullLiteral && right is NullLiteral) {
					var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc);
					lifted_int.ResolveAsType (ec);
					return (Constant) new Binary (oper, lifted_int, right).ResolveOperator (ec);
				}

				IntConstant sic = right.ConvertImplicitly (ec.BuiltinTypes.Int) as IntConstant;
				if (sic == null){
					return null;
				}
				int rshift_val = sic.Value;
				switch (left.Type.BuiltinType) {
				case BuiltinTypeSpec.Type.ULong:
					return new ULongConstant (ec.BuiltinTypes, ((ULongConstant) left).Value >> rshift_val, left.Location);
				case BuiltinTypeSpec.Type.Long:
					return new LongConstant (ec.BuiltinTypes, ((LongConstant) left).Value >> rshift_val, left.Location);
				case BuiltinTypeSpec.Type.UInt:
					return new UIntConstant (ec.BuiltinTypes, ((UIntConstant) left).Value >> rshift_val, left.Location);
				}

				// null >> value => null
				if (left is NullLiteral)
					return (Constant) new Binary (oper, left, right).ResolveOperator (ec);

				left = left.ConvertImplicitly (ec.BuiltinTypes.Int);
				if (left.Type.BuiltinType == BuiltinTypeSpec.Type.Int)
					return new IntConstant (ec.BuiltinTypes, ((IntConstant) left).Value >> rshift_val, left.Location);

				return null;

			case Binary.Operator.Equality:
				if (TypeSpec.IsReferenceType (lt) && TypeSpec.IsReferenceType (rt) ||
					(left is Nullable.LiftedNull && right.IsNull) ||
					(right is Nullable.LiftedNull && left.IsNull)) {
					if (left.IsNull || right.IsNull) {
						return ReducedExpression.Create (
							new BoolConstant (ec.BuiltinTypes, left.IsNull == right.IsNull, left.Location),
							new Binary (oper, left, right));
					}

					if (left is StringConstant && right is StringConstant)
						return new BoolConstant (ec.BuiltinTypes,
							((StringConstant) left).Value == ((StringConstant) right).Value, left.Location);

					return null;
				}

				if (!DoBinaryNumericPromotions (ec, ref left, ref right))
					return null;

				bool_res = false;
				if (left is DoubleConstant)
					bool_res = ((DoubleConstant) left).Value ==
						((DoubleConstant) right).Value;
				else if (left is FloatConstant)
					bool_res = ((FloatConstant) left).DoubleValue ==
						((FloatConstant) right).DoubleValue;
				else if (left is ULongConstant)
					bool_res = ((ULongConstant) left).Value ==
						((ULongConstant) right).Value;
				else if (left is LongConstant)
					bool_res = ((LongConstant) left).Value ==
						((LongConstant) right).Value;
				else if (left is UIntConstant)
					bool_res = ((UIntConstant) left).Value ==
						((UIntConstant) right).Value;
				else if (left is IntConstant)
					bool_res = ((IntConstant) left).Value ==
						((IntConstant) right).Value;
				else
					return null;

				return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location);

			case Binary.Operator.Inequality:
				if (TypeSpec.IsReferenceType (lt) && TypeSpec.IsReferenceType (rt) ||
					(left is Nullable.LiftedNull && right.IsNull) ||
					(right is Nullable.LiftedNull && left.IsNull)) {
					if (left.IsNull || right.IsNull) {
						return ReducedExpression.Create (
							new BoolConstant (ec.BuiltinTypes, left.IsNull != right.IsNull, left.Location),
							new Binary (oper, left, right));
					}

					if (left is StringConstant && right is StringConstant)
						return new BoolConstant (ec.BuiltinTypes,
							((StringConstant) left).Value != ((StringConstant) right).Value, left.Location);

					return null;
				}

				if (!DoBinaryNumericPromotions (ec, ref left, ref right))
					return null;

				bool_res = false;
				if (left is DoubleConstant)
					bool_res = ((DoubleConstant) left).Value !=
						((DoubleConstant) right).Value;
				else if (left is FloatConstant)
					bool_res = ((FloatConstant) left).DoubleValue !=
						((FloatConstant) right).DoubleValue;
				else if (left is ULongConstant)
					bool_res = ((ULongConstant) left).Value !=
						((ULongConstant) right).Value;
				else if (left is LongConstant)
					bool_res = ((LongConstant) left).Value !=
						((LongConstant) right).Value;
				else if (left is UIntConstant)
					bool_res = ((UIntConstant) left).Value !=
						((UIntConstant) right).Value;
				else if (left is IntConstant)
					bool_res = ((IntConstant) left).Value !=
						((IntConstant) right).Value;
				else
					return null;

				return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location);

			case Binary.Operator.LessThan:
				if (right is NullLiteral) {
					if (left is NullLiteral) {
						var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc);
						lifted_int.ResolveAsType (ec);
						return (Constant) new Binary (oper, lifted_int, right).ResolveOperator (ec);
					}
				}

				if (!DoBinaryNumericPromotions (ec, ref left, ref right))
					return null;

				bool_res = false;
				if (left is DoubleConstant)
					bool_res = ((DoubleConstant) left).Value <
						((DoubleConstant) right).Value;
				else if (left is FloatConstant)
					bool_res = ((FloatConstant) left).DoubleValue <
						((FloatConstant) right).DoubleValue;
				else if (left is ULongConstant)
					bool_res = ((ULongConstant) left).Value <
						((ULongConstant) right).Value;
				else if (left is LongConstant)
					bool_res = ((LongConstant) left).Value <
						((LongConstant) right).Value;
				else if (left is UIntConstant)
					bool_res = ((UIntConstant) left).Value <
						((UIntConstant) right).Value;
				else if (left is IntConstant)
					bool_res = ((IntConstant) left).Value <
						((IntConstant) right).Value;
				else
					return null;

				return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location);
				
			case Binary.Operator.GreaterThan:
				if (right is NullLiteral) {
					if (left is NullLiteral) {
						var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc);
						lifted_int.ResolveAsType (ec);
						return (Constant) new Binary (oper, lifted_int, right).ResolveOperator (ec);
					}
				}

				if (!DoBinaryNumericPromotions (ec, ref left, ref right))
					return null;

				bool_res = false;
				if (left is DoubleConstant)
					bool_res = ((DoubleConstant) left).Value >
						((DoubleConstant) right).Value;
				else if (left is FloatConstant)
					bool_res = ((FloatConstant) left).DoubleValue >
						((FloatConstant) right).DoubleValue;
				else if (left is ULongConstant)
					bool_res = ((ULongConstant) left).Value >
						((ULongConstant) right).Value;
				else if (left is LongConstant)
					bool_res = ((LongConstant) left).Value >
						((LongConstant) right).Value;
				else if (left is UIntConstant)
					bool_res = ((UIntConstant) left).Value >
						((UIntConstant) right).Value;
				else if (left is IntConstant)
					bool_res = ((IntConstant) left).Value >
						((IntConstant) right).Value;
				else
					return null;

				return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location);

			case Binary.Operator.GreaterThanOrEqual:
				if (right is NullLiteral) {
					if (left is NullLiteral) {
						var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc);
						lifted_int.ResolveAsType (ec);
						return (Constant) new Binary (oper, lifted_int, right).ResolveOperator (ec);
					}
				}

				if (!DoBinaryNumericPromotions (ec, ref left, ref right))
					return null;

				bool_res = false;
				if (left is DoubleConstant)
					bool_res = ((DoubleConstant) left).Value >=
						((DoubleConstant) right).Value;
				else if (left is FloatConstant)
					bool_res = ((FloatConstant) left).DoubleValue >=
						((FloatConstant) right).DoubleValue;
				else if (left is ULongConstant)
					bool_res = ((ULongConstant) left).Value >=
						((ULongConstant) right).Value;
				else if (left is LongConstant)
					bool_res = ((LongConstant) left).Value >=
						((LongConstant) right).Value;
				else if (left is UIntConstant)
					bool_res = ((UIntConstant) left).Value >=
						((UIntConstant) right).Value;
				else if (left is IntConstant)
					bool_res = ((IntConstant) left).Value >=
						((IntConstant) right).Value;
				else
					return null;

				return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location);

			case Binary.Operator.LessThanOrEqual:
				if (right is NullLiteral) {
					if (left is NullLiteral) {
						var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc);
						lifted_int.ResolveAsType (ec);
						return (Constant) new Binary (oper, lifted_int, right).ResolveOperator (ec);
					}
				}

				if (!DoBinaryNumericPromotions (ec, ref left, ref right))
					return null;

				bool_res = false;
				if (left is DoubleConstant)
					bool_res = ((DoubleConstant) left).Value <=
						((DoubleConstant) right).Value;
				else if (left is FloatConstant)
					bool_res = ((FloatConstant) left).DoubleValue <=
						((FloatConstant) right).DoubleValue;
				else if (left is ULongConstant)
					bool_res = ((ULongConstant) left).Value <=
						((ULongConstant) right).Value;
				else if (left is LongConstant)
					bool_res = ((LongConstant) left).Value <=
						((LongConstant) right).Value;
				else if (left is UIntConstant)
					bool_res = ((UIntConstant) left).Value <=
						((UIntConstant) right).Value;
				else if (left is IntConstant)
					bool_res = ((IntConstant) left).Value <=
						((IntConstant) right).Value;
				else
					return null;

				return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location);
			}

			return null;
		}
示例#6
0
        protected override Expression DoResolve(ResolveContext ec)
        {
            right = right.Resolve(ec);
            if (right == null)
            {
                return(null);
            }

            MemberAccess ma = target as MemberAccess;

            using (ec.Set(ResolveContext.Options.CompoundAssignmentScope)) {
                target = target.Resolve(ec);
            }

            if (target == null)
            {
                return(null);
            }

            if (target is MethodGroupExpr)
            {
                ec.Report.Error(1656, loc,
                                "Cannot assign to `{0}' because it is a `{1}'",
                                ((MethodGroupExpr)target).Name, target.ExprClassName);
                return(null);
            }

            var event_expr = target as EventExpr;

            if (event_expr != null)
            {
                source = Convert.ImplicitConversionRequired(ec, right, target.Type, loc);
                if (source == null)
                {
                    return(null);
                }

                Expression rside;
                if (op == Binary.Operator.Addition)
                {
                    rside = EmptyExpression.EventAddition;
                }
                else if (op == Binary.Operator.Subtraction)
                {
                    rside = EmptyExpression.EventSubtraction;
                }
                else
                {
                    rside = null;
                }

                target = target.ResolveLValue(ec, rside);
                if (target == null)
                {
                    return(null);
                }

                eclass = ExprClass.Value;
                type   = event_expr.Operator.ReturnType;
                return(this);
            }

            //
            // Only now we can decouple the original source/target
            // into a tree, to guarantee that we do not have side
            // effects.
            //
            if (left == null)
            {
                left = new TargetExpression(target);
            }

            source = new Binary(op, left, right, true);

            if (target is DynamicMemberAssignable)
            {
                Arguments targs = ((DynamicMemberAssignable)target).Arguments;
                source = source.Resolve(ec);

                Arguments args = new Arguments(targs.Count + 1);
                args.AddRange(targs);
                args.Add(new Argument(source));

                var binder_flags = CSharpBinderFlags.ValueFromCompoundAssignment;

                //
                // Compound assignment does target conversion using additional method
                // call, set checked context as the binary operation can overflow
                //
                if (ec.HasSet(ResolveContext.Options.CheckedScope))
                {
                    binder_flags |= CSharpBinderFlags.CheckedContext;
                }

                if (target is DynamicMemberBinder)
                {
                    source = new DynamicMemberBinder(ma.Name, binder_flags, args, loc).Resolve(ec);

                    // Handles possible event addition/subtraction
                    if (op == Binary.Operator.Addition || op == Binary.Operator.Subtraction)
                    {
                        args = new Arguments(targs.Count + 1);
                        args.AddRange(targs);
                        args.Add(new Argument(right));
                        string method_prefix = op == Binary.Operator.Addition ?
                                               Event.AEventAccessor.AddPrefix : Event.AEventAccessor.RemovePrefix;

                        var invoke = DynamicInvocation.CreateSpecialNameInvoke(
                            new MemberAccess(right, method_prefix + ma.Name, loc), args, loc).Resolve(ec);

                        args = new Arguments(targs.Count);
                        args.AddRange(targs);
                        source = new DynamicEventCompoundAssign(ma.Name, args,
                                                                (ExpressionStatement)source, (ExpressionStatement)invoke, loc).Resolve(ec);
                    }
                }
                else
                {
                    source = new DynamicIndexBinder(binder_flags, args, loc).Resolve(ec);
                }

                return(source);
            }

            return(base.DoResolve(ec));
        }
示例#7
0
		public Expression CreateCallSiteBinder (ResolveContext ec, Arguments args)
		{
			Arguments binder_args = new Arguments (4);

			MemberAccess sle = new MemberAccess (new MemberAccess (
				new QualifiedAliasMember (QualifiedAliasMember.GlobalAlias, "System", loc), "Linq", loc), "Expressions", loc);

			var flags = ec.HasSet (ResolveContext.Options.CheckedScope) ? CSharpBinderFlags.CheckedContext : 0;

			binder_args.Add (new Argument (new BinderFlags (flags, this)));
			binder_args.Add (new Argument (new MemberAccess (new MemberAccess (sle, "ExpressionType", loc), name, loc)));
			binder_args.Add (new Argument (new TypeOf (ec.CurrentType, loc)));
			binder_args.Add (new Argument (new ImplicitlyTypedArrayCreation (args.CreateDynamicBinderArguments (ec), loc)));

			return new Invocation (GetBinder ("UnaryOperation", loc), binder_args);
		}
示例#8
0
		public Expression CreateCallSiteBinder (ResolveContext ec, Arguments args)
		{
			Arguments binder_args = new Arguments (3);

			flags |= ec.HasSet (ResolveContext.Options.CheckedScope) ? CSharpBinderFlags.CheckedContext : 0;

			binder_args.Add (new Argument (new BinderFlags (flags, this)));
			binder_args.Add (new Argument (new TypeOf (type, loc)));
			binder_args.Add (new Argument (new TypeOf (ec.CurrentType, loc)));
			return new Invocation (GetBinder ("Convert", loc), binder_args);
		}
示例#9
0
		public BlockContext (ResolveContext rc, ExplicitBlock block, TypeSpec returnType)
			: this (rc.MemberContext, block, returnType)
		{
			if (rc.IsUnsafe)
				flags |= ResolveContext.Options.UnsafeScope;

			if (rc.HasSet (ResolveContext.Options.CheckedScope))
				flags |= ResolveContext.Options.CheckedScope;

			if (!rc.ConstantCheckState)
				flags &= ~Options.ConstantCheckState;

			if (rc.IsInProbingMode)
				flags |= ResolveContext.Options.ProbingMode;

			if (rc.HasSet (ResolveContext.Options.FieldInitializerScope))
				flags |= ResolveContext.Options.FieldInitializerScope;

			if (rc.HasSet (ResolveContext.Options.ExpressionTreeConversion))
				flags |= ResolveContext.Options.ExpressionTreeConversion;

			if (rc.HasSet (ResolveContext.Options.BaseInitializer))
				flags |= ResolveContext.Options.BaseInitializer;
		}
示例#10
0
        protected override Expression DoResolve(ResolveContext ec)
        {
            constructor_method = Delegate.GetConstructor(type);

            var invoke_method = Delegate.GetInvokeMethod(type);

            if (!ec.HasSet(ResolveContext.Options.ConditionalAccessReceiver))
            {
                if (method_group.HasConditionalAccess())
                {
                    conditional_access_receiver = true;
                    ec.Set(ResolveContext.Options.ConditionalAccessReceiver);
                }
            }

            Arguments arguments = CreateDelegateMethodArguments(ec, invoke_method.Parameters, invoke_method.Parameters.Types, loc);

            method_group = method_group.OverloadResolve(ec, ref arguments, this, OverloadResolver.Restrictions.CovariantDelegate);

            if (conditional_access_receiver)
            {
                ec.With(ResolveContext.Options.ConditionalAccessReceiver, false);
            }

            if (method_group == null)
            {
                return(null);
            }

            var delegate_method = method_group.BestCandidate;

            if (delegate_method.DeclaringType.IsNullableType)
            {
                ec.Report.Error(1728, loc, "Cannot create delegate from method `{0}' because it is a member of System.Nullable<T> type",
                                delegate_method.GetSignatureForError());
                return(null);
            }

            if (!AllowSpecialMethodsInvocation)
            {
                Invocation.IsSpecialMethodInvocation(ec, delegate_method, loc);
            }

            ExtensionMethodGroupExpr emg = method_group as ExtensionMethodGroupExpr;

            if (emg != null)
            {
                method_group.InstanceExpression = emg.ExtensionExpression;
                TypeSpec e_type = emg.ExtensionExpression.Type;
                if (TypeSpec.IsValueType(e_type))
                {
                    ec.Report.Error(1113, loc, "Extension method `{0}' of value type `{1}' cannot be used to create delegates",
                                    delegate_method.GetSignatureForError(), e_type.GetSignatureForError());
                }
            }

            TypeSpec rt = method_group.BestCandidateReturnType;

            if (rt.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
            {
                rt = ec.BuiltinTypes.Object;
            }

            if (!Delegate.IsTypeCovariant(ec, rt, invoke_method.ReturnType))
            {
                Expression ret_expr = new TypeExpression(delegate_method.ReturnType, loc);
                Error_ConversionFailed(ec, delegate_method, ret_expr);
            }

            if (method_group.IsConditionallyExcluded)
            {
                ec.Report.SymbolRelatedToPreviousError(delegate_method);
                MethodOrOperator m = delegate_method.MemberDefinition as MethodOrOperator;
                if (m != null && m.IsPartialDefinition)
                {
                    ec.Report.Error(762, loc, "Cannot create delegate from partial method declaration `{0}'",
                                    delegate_method.GetSignatureForError());
                }
                else
                {
                    ec.Report.Error(1618, loc, "Cannot create delegate with `{0}' because it has a Conditional attribute",
                                    TypeManager.CSharpSignature(delegate_method));
                }
            }

            var expr = method_group.InstanceExpression;

            if (expr != null && (expr.Type.IsGenericParameter || !TypeSpec.IsReferenceType(expr.Type)))
            {
                method_group.InstanceExpression = new BoxedCast(expr, ec.BuiltinTypes.Object);
            }

            eclass = ExprClass.Value;
            return(this);
        }
示例#11
0
		protected override Expression DoResolve (ResolveContext ec)
		{
			constructor_method = Delegate.GetConstructor (type);

			var invoke_method = Delegate.GetInvokeMethod (type);

			if (!ec.HasSet (ResolveContext.Options.ConditionalAccessReceiver)) {
				if (method_group.HasConditionalAccess ()) {
					conditional_access_receiver = true;
					ec.Set (ResolveContext.Options.ConditionalAccessReceiver);
				}
			}

			Arguments arguments = CreateDelegateMethodArguments (ec, invoke_method.Parameters, invoke_method.Parameters.Types, loc);
			method_group = method_group.OverloadResolve (ec, ref arguments, this, OverloadResolver.Restrictions.CovariantDelegate);

			if (conditional_access_receiver)
				ec.With (ResolveContext.Options.ConditionalAccessReceiver, false);

			if (method_group == null)
				return null;

			var delegate_method = method_group.BestCandidate;
			
			if (delegate_method.DeclaringType.IsNullableType) {
				ec.Report.Error (1728, loc, "Cannot create delegate from method `{0}' because it is a member of System.Nullable<T> type",
					delegate_method.GetSignatureForError ());
				return null;
			}		
			
			if (!AllowSpecialMethodsInvocation)
				Invocation.IsSpecialMethodInvocation (ec, delegate_method, loc);

			ExtensionMethodGroupExpr emg = method_group as ExtensionMethodGroupExpr;
			if (emg != null) {
				method_group.InstanceExpression = emg.ExtensionExpression;
				TypeSpec e_type = emg.ExtensionExpression.Type;
				if (TypeSpec.IsValueType (e_type)) {
					ec.Report.Error (1113, loc, "Extension method `{0}' of value type `{1}' cannot be used to create delegates",
						delegate_method.GetSignatureForError (), e_type.GetSignatureForError ());
				}
			}

			TypeSpec rt = method_group.BestCandidateReturnType;
			if (rt.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
				rt = ec.BuiltinTypes.Object;

			if (!Delegate.IsTypeCovariant (ec, rt, invoke_method.ReturnType)) {
				Expression ret_expr = new TypeExpression (delegate_method.ReturnType, loc);
				Error_ConversionFailed (ec, delegate_method, ret_expr);
			}

			if (method_group.IsConditionallyExcluded) {
				ec.Report.SymbolRelatedToPreviousError (delegate_method);
				MethodOrOperator m = delegate_method.MemberDefinition as MethodOrOperator;
				if (m != null && m.IsPartialDefinition) {
					ec.Report.Error (762, loc, "Cannot create delegate from partial method declaration `{0}'",
						delegate_method.GetSignatureForError ());
				} else {
					ec.Report.Error (1618, loc, "Cannot create delegate with `{0}' because it has a Conditional attribute",
						TypeManager.CSharpSignature (delegate_method));
				}
			}

			var expr = method_group.InstanceExpression;
			if (expr != null && (expr.Type.IsGenericParameter || !TypeSpec.IsReferenceType (expr.Type)))
				method_group.InstanceExpression = new BoxedCast (expr, ec.BuiltinTypes.Object);

			eclass = ExprClass.Value;
			return this;
		}
示例#12
0
		public AnonymousExpression Compatible (ResolveContext ec, AnonymousExpression ae)
		{
			if (block.Resolved)
				return this;

			// TODO: Implement clone
			BlockContext aec = new BlockContext (ec, block, ReturnType);
			aec.CurrentAnonymousMethod = ae;

			var am = this as AnonymousMethodBody;

			if (ec.HasSet (ResolveContext.Options.InferReturnType) && am != null) {
				am.ReturnTypeInference = new TypeInferenceContext ();
			}

			var bc = ec as BlockContext;

			if (bc != null) {
				aec.AssignmentInfoOffset = bc.AssignmentInfoOffset;
				aec.EnclosingLoop = bc.EnclosingLoop;
				aec.EnclosingLoopOrSwitch = bc.EnclosingLoopOrSwitch;
				aec.Switch = bc.Switch;
			}

			var errors = ec.Report.Errors;

			bool res = Block.Resolve (aec);

			if (res && errors == ec.Report.Errors) {
				MarkReachable (new Reachability ());

				if (!CheckReachableExit (ec.Report)) {
					return null;
				}

				if (bc != null)
					bc.AssignmentInfoOffset = aec.AssignmentInfoOffset;
			}

			if (am != null && am.ReturnTypeInference != null) {
				am.ReturnTypeInference.FixAllTypes (ec);
				ReturnType = am.ReturnTypeInference.InferredTypeArguments [0];
				am.ReturnTypeInference = null;

				//
				// If e is synchronous the inferred return type is T
				// If e is asynchronous and the body of F is either an expression classified as nothing
				// or a statement block where no return statements have expressions, the inferred return type is Task
				// If e is async and has an inferred result type T, the inferred return type is Task<T>
				//
				if (block.IsAsync && ReturnType != null) {
					ReturnType = ReturnType.Kind == MemberKind.Void ?
						ec.Module.PredefinedTypes.Task.TypeSpec :
						ec.Module.PredefinedTypes.TaskGeneric.TypeSpec.MakeGenericType (ec, new [] { ReturnType });
				}
			}

			if (res && errors != ec.Report.Errors)
				return null;

			return res ? this : null;
		}
示例#13
0
		protected override Expression DoResolve (ResolveContext rc)
		{
			if (rc.HasSet (ResolveContext.Options.ConstantScope)) {
				rc.Report.Error (1706, loc, "Anonymous methods and lambda expressions cannot be used in the current context");
				return null;
			}

			//
			// Update top-level block generated duting parsing with actual top-level block
			//
			if (rc.HasAny (ResolveContext.Options.FieldInitializerScope | ResolveContext.Options.BaseInitializer) && rc.CurrentMemberDefinition.Parent.PartialContainer.PrimaryConstructorParameters != null) {
				var tb = rc.ConstructorBlock.ParametersBlock.TopBlock;
				if (Block.TopBlock != tb) {
					Block b = Block;
					while (b.Parent != Block.TopBlock && b != Block.TopBlock)
						b = b.Parent;

					b.Parent = tb;
					tb.IncludeBlock (Block, Block.TopBlock);
					b.ParametersBlock.TopBlock = tb;
				}
			}

			eclass = ExprClass.Value;

			//
			// This hack means `The type is not accessible
			// anywhere', we depend on special conversion
			// rules.
			// 
			type = InternalType.AnonymousMethod;

			if (!DoResolveParameters (rc))
				return null;

			return this;
		}
示例#14
0
		//
		// Returns AnonymousMethod container if this anonymous method
		// expression can be implicitly converted to the delegate type `delegate_type'
		//
		public Expression Compatible (ResolveContext ec, TypeSpec type)
		{
			Expression am;
			if (compatibles.TryGetValue (type, out am))
				return am;

			TypeSpec delegate_type = CompatibleChecks (ec, type);
			if (delegate_type == null)
				return null;

			//
			// At this point its the first time we know the return type that is 
			// needed for the anonymous method.  We create the method here.
			//

			var invoke_mb = Delegate.GetInvokeMethod (delegate_type);
			TypeSpec return_type = invoke_mb.ReturnType;

			//
			// Second: the return type of the delegate must be compatible with 
			// the anonymous type.   Instead of doing a pass to examine the block
			// we satisfy the rule by setting the return type on the EmitContext
			// to be the delegate type return type.
			//

			var body = CompatibleMethodBody (ec, null, return_type, delegate_type);
			if (body == null)
				return null;

			bool etree_conversion = delegate_type != type;

			try {
				if (etree_conversion) {
					if (ec.HasSet (ResolveContext.Options.ExpressionTreeConversion)) {
						//
						// Nested expression tree lambda use same scope as parent
						// lambda, this also means no variable capturing between this
						// and parent scope
						//
						am = body.Compatible (ec, ec.CurrentAnonymousMethod);

						//
						// Quote nested expression tree
						//
						if (am != null)
							am = new Quote (am);
					} else {
						int errors = ec.Report.Errors;

						if (Block.IsAsync) {
							ec.Report.Error (1989, loc, "Async lambda expressions cannot be converted to expression trees");
						}

						using (ec.Set (ResolveContext.Options.ExpressionTreeConversion)) {
							am = body.Compatible (ec);
						}

						//
						// Rewrite expressions into expression tree when targeting Expression<T>
						//
						if (am != null && errors == ec.Report.Errors)
							am = CreateExpressionTree (ec, delegate_type);
					}
				} else {
					am = body.Compatible (ec);

					if (body.DirectMethodGroupConversion != null) {
						var errors_printer = new SessionReportPrinter ();
						var old = ec.Report.SetPrinter (errors_printer);
						var expr = new ImplicitDelegateCreation (delegate_type, body.DirectMethodGroupConversion, loc) {
							AllowSpecialMethodsInvocation = true
						}.Resolve (ec);
						ec.Report.SetPrinter (old);
						if (expr != null && errors_printer.ErrorsCount == 0)
							am = expr;
					}
				}
			} catch (CompletionResult) {
				throw;
			} catch (FatalException) {
				throw;
			} catch (Exception e) {
				throw new InternalErrorException (e, loc);
			}

			if (!ec.IsInProbingMode && !etree_conversion) {
				compatibles.Add (type, am ?? EmptyExpression.Null);
			}

			return am;
		}
示例#15
0
		protected override Expression DoResolve (ResolveContext ec)
		{
			right = right.Resolve (ec);
			if (right == null)
				return null;

			MemberAccess ma = target as MemberAccess;
			using (ec.Set (ResolveContext.Options.CompoundAssignmentScope)) {
				target = target.Resolve (ec);
			}
			
			if (target == null)
				return null;

			if (target is MethodGroupExpr){
				ec.Report.Error (1656, loc,
					"Cannot assign to `{0}' because it is a `{1}'",
					((MethodGroupExpr)target).Name, target.ExprClassName);
				return null;
			}

			var event_expr = target as EventExpr;
			if (event_expr != null) {
				source = Convert.ImplicitConversionRequired (ec, right, target.Type, loc);
				if (source == null)
					return null;

				Expression rside;
				if (op == Binary.Operator.Addition)
					rside = EmptyExpression.EventAddition;
				else if (op == Binary.Operator.Subtraction)
					rside = EmptyExpression.EventSubtraction;
				else
					rside = null;

				target = target.ResolveLValue (ec, rside);
				if (target == null)
					return null;

				eclass = ExprClass.Value;
				type = event_expr.Operator.ReturnType;
				return this;
			}

			//
			// Only now we can decouple the original source/target
			// into a tree, to guarantee that we do not have side
			// effects.
			//
			if (left == null)
				left = new TargetExpression (target);

			source = new Binary (op, left, right, true);

			if (target is DynamicMemberAssignable) {
				Arguments targs = ((DynamicMemberAssignable) target).Arguments;
				source = source.Resolve (ec);

				Arguments args = new Arguments (targs.Count + 1);
				args.AddRange (targs);
				args.Add (new Argument (source));

				var binder_flags = CSharpBinderFlags.ValueFromCompoundAssignment;

				//
				// Compound assignment does target conversion using additional method
				// call, set checked context as the binary operation can overflow
				//
				if (ec.HasSet (ResolveContext.Options.CheckedScope))
					binder_flags |= CSharpBinderFlags.CheckedContext;

				if (target is DynamicMemberBinder) {
					source = new DynamicMemberBinder (ma.Name, binder_flags, args, loc).Resolve (ec);

					// Handles possible event addition/subtraction
					if (op == Binary.Operator.Addition || op == Binary.Operator.Subtraction) {
						args = new Arguments (targs.Count + 1);
						args.AddRange (targs);
						args.Add (new Argument (right));
						string method_prefix = op == Binary.Operator.Addition ?
							Event.AEventAccessor.AddPrefix : Event.AEventAccessor.RemovePrefix;

						var invoke = DynamicInvocation.CreateSpecialNameInvoke (
							new MemberAccess (right, method_prefix + ma.Name, loc), args, loc).Resolve (ec);

						args = new Arguments (targs.Count);
						args.AddRange (targs);
						source = new DynamicEventCompoundAssign (ma.Name, args,
							(ExpressionStatement) source, (ExpressionStatement) invoke, loc).Resolve (ec);
					}
				} else {
					source = new DynamicIndexBinder (binder_flags, args, loc).Resolve (ec);
				}

				return source;
			}

			return base.DoResolve (ec);
		}