Пример #1
0
        private BoundNode RewriteStringConcatenation(BoundBinaryOperator node)
        {
            // UNDONE: We need to make this more sophisticated. For example, we should
            // UNDONE: be rewriting (M() + "A") + ("B" + N()) as
            // UNDONE: String.Concat(M(), "AB", N()).
            // UNDONE: We have many overloads of String.Concat to choose from: that
            // UNDONE: take one, two, three, four strings, that take params arrays
            // UNDONE: in strings and objects, and so on. See the native compiler
            // UNDONE: string rewriter for details.
            // UNDONE: For now, just to get this going let's do it the easy way;
            // UNDONE: we'll just generate calls to String.Concat(string, string)
            // UNDONE: or String.Concat(object, object) as appropriate.

            Debug.Assert(node != null);
            Debug.Assert(node.ConstantValueOpt == null);

            SpecialMember member = (node.OperatorKind == BinaryOperatorKind.StringConcatenation) ?
                                   SpecialMember.System_String__ConcatStringString :
                                   SpecialMember.System_String__ConcatObjectObject;

            var method = (MethodSymbol)this.compilation.Assembly.GetSpecialTypeMember(member);

            // UNDONE: Handle the bizarre error case where we don't have the expected string concat methods.
            Debug.Assert(method != null);

            return(Visit(BoundCall.SynthesizedCall(null, method, node.Left, node.Right)));
        }
Пример #2
0
        private BoundNode RewriteDelegateOperation(BoundBinaryOperator node, SpecialMember member)
        {
            Debug.Assert(node != null);
            var method = (MethodSymbol)this.compilation.Assembly.GetSpecialTypeMember(member);

            // UNDONE: Handle the bizarre error case where we don't have the expected methods.
            Debug.Assert(method != null);
            BoundExpression call   = BoundCall.SynthesizedCall(null, method, node.Left, node.Right);
            BoundExpression result = method.ReturnType.SpecialType == SpecialType.System_Delegate ?
                                     BoundConversion.SynthesizedConversion(call, ConversionKind.ExplicitReference, node.Type) :
                                     call;

            return(Visit(result));
        }
Пример #3
0
        private BoundNode RewriteStringEquality(BoundBinaryOperator node, SpecialMember member)
        {
            Debug.Assert(node != null);
            Debug.Assert(node.ConstantValueOpt == null);

            if (node.Left.ConstantValue == ConstantValue.Null || node.Right.ConstantValue == ConstantValue.Null)
            {
                return(base.VisitBinaryOperator(node));
            }

            var method = (MethodSymbol)this.compilation.Assembly.GetSpecialTypeMember(member);

            Debug.Assert(method != null);

            return(Visit(BoundCall.SynthesizedCall(null, method, node.Left, node.Right)));
        }
Пример #4
0
        public override BoundNode VisitPropertyAccess(BoundPropertyAccess node)
        {
            // Avoid rewriting if node has errors since the accessor may not exist.
            if (node.HasErrors)
            {
                return(base.VisitPropertyAccess(node));
            }

            // Rewrite property access into call to getter.
            var property  = node.PropertySymbol.GetBaseProperty();
            var getMethod = property.GetMethod;

            Debug.Assert(getMethod != null);
            Debug.Assert(getMethod.Parameters.Count == 0);
            Debug.Assert(!getMethod.IsOverride);

            var rewrittenReceiver = (BoundExpression)Visit(node.ReceiverOpt);

            return(BoundCall.SynthesizedCall(rewrittenReceiver, getMethod));
        }
Пример #5
0
        private BoundExpression VisitAssignmentOperator(BoundAssignmentOperator node, bool used)
        {
            // Avoid rewriting if node has errors since at least
            // one of the operands is invalid.
            if (node.HasErrors)
            {
                return(node);
            }

            var propertyAccessor = node.Left as BoundPropertyAccess;

            if (propertyAccessor == null)
            {
                return((BoundExpression)base.VisitAssignmentOperator(node));
            }

            // Rewrite property assignment into call to setter.
            var property  = propertyAccessor.PropertySymbol.GetBaseProperty();
            var setMethod = property.SetMethod;

            Debug.Assert(setMethod != null);
            Debug.Assert(setMethod.Parameters.Count == 1);
            Debug.Assert(!setMethod.IsOverride);

            var rewrittenReceiver = (BoundExpression)Visit(propertyAccessor.ReceiverOpt);
            var rewrittenArgument = (BoundExpression)Visit(node.Right);

            if (used)
            {
                // Save expression value to a temporary before calling the
                // setter, and restore the temporary after the setter, so the
                // assignment can be used as an embedded expression.
                var exprType   = rewrittenArgument.Type;
                var tempSymbol = new TempLocalSymbol(exprType, RefKind.None, containingSymbol);
                var tempLocal  = new BoundLocal(null, null, tempSymbol, null, exprType);
                var saveTemp   = new BoundAssignmentOperator(
                    null,
                    null,
                    tempLocal,
                    rewrittenArgument,
                    exprType);
                var call = BoundCall.SynthesizedCall(
                    rewrittenReceiver,
                    setMethod,
                    saveTemp);
                return(new BoundSequence(
                           node.Syntax,
                           node.SyntaxTree,
                           ReadOnlyArray <LocalSymbol> .CreateFrom(tempSymbol),
                           ReadOnlyArray <BoundExpression> .CreateFrom(call),
                           tempLocal,
                           exprType));
            }
            else
            {
                return(BoundCall.SynthesizedCall(
                           rewrittenReceiver,
                           setMethod,
                           rewrittenArgument));
            }
        }