private BoundExpression MakeAsOperator( BoundAsOperator oldNode, SyntaxNode syntax, BoundExpression rewrittenOperand, BoundTypeExpression rewrittenTargetType, Conversion conversion, TypeSymbol rewrittenType) { // TODO: Handle dynamic operand type and target type Debug.Assert(rewrittenTargetType.Type.Equals(rewrittenType)); // target type cannot be a non-nullable value type Debug.Assert(!rewrittenType.IsValueType || rewrittenType.IsNullableType()); if (!_inExpressionLambda) { ConstantValue constantValue = Binder.GetAsOperatorConstantResult(rewrittenOperand.Type, rewrittenType, conversion.Kind, rewrittenOperand.ConstantValue); if (constantValue != null) { Debug.Assert(constantValue.IsNull); BoundExpression result = rewrittenType.IsNullableType() ? new BoundDefaultExpression(syntax, rewrittenType) : MakeLiteral(syntax, constantValue, rewrittenType); if (rewrittenOperand.ConstantValue != null) { // No need to preserve any side-effects from the operand. // We also can keep the "constant" notion of the result, which // enables some optimizations down the road. return(result); } return(new BoundSequence( syntax: syntax, locals: ImmutableArray <LocalSymbol> .Empty, sideEffects: ImmutableArray.Create <BoundExpression>(rewrittenOperand), value: result, type: rewrittenType)); } if (conversion.IsImplicit) { // Operand with bound implicit conversion to target type. // We don't need a runtime check, generate a conversion for the operand instead. return(MakeConversionNode(syntax, rewrittenOperand, conversion, rewrittenType, @checked: false)); } } return(oldNode.Update(rewrittenOperand, rewrittenTargetType, conversion, rewrittenType)); }
private BoundExpression MakeIsOperator( BoundIsOperator oldNode, SyntaxNode syntax, BoundExpression rewrittenOperand, BoundTypeExpression rewrittenTargetType, Conversion conversion, TypeSymbol rewrittenType) { if (rewrittenOperand.Kind == BoundKind.MethodGroup) { var methodGroup = (BoundMethodGroup)rewrittenOperand; BoundExpression receiver = methodGroup.ReceiverOpt; if (receiver != null && receiver.Kind != BoundKind.ThisReference) { // possible side-effect return(RewriteConstantIsOperator(receiver.Syntax, receiver, ConstantValue.False, rewrittenType)); } else { return(MakeLiteral(syntax, ConstantValue.False, rewrittenType)); } } var operandType = rewrittenOperand.Type; var targetType = rewrittenTargetType.Type; Debug.Assert((object)operandType != null || rewrittenOperand.ConstantValue.IsNull); Debug.Assert((object)targetType != null); // TODO: Handle dynamic operand type and target type if (!_inExpressionLambda) { ConstantValue constantValue = Binder.GetIsOperatorConstantResult(operandType, targetType, conversion.Kind, rewrittenOperand.ConstantValue); if (constantValue != null) { return(RewriteConstantIsOperator(syntax, rewrittenOperand, constantValue, rewrittenType)); } else if (conversion.IsImplicit) { // operand is a reference type with bound identity or implicit conversion // We can replace the "is" instruction with a null check return(MakeNullCheck(syntax, rewrittenOperand, BinaryOperatorKind.NotEqual)); } } return(oldNode.Update(rewrittenOperand, rewrittenTargetType, conversion, rewrittenType)); }