当前位置: 首页>>代码示例>>C#>>正文


C# BoundAssignmentOperator类代码示例

本文整理汇总了C#中BoundAssignmentOperator的典型用法代码示例。如果您正苦于以下问题:C# BoundAssignmentOperator类的具体用法?C# BoundAssignmentOperator怎么用?C# BoundAssignmentOperator使用的例子?那么恭喜您, 这里精选的类代码示例或许可以为您提供帮助。


BoundAssignmentOperator类属于命名空间,在下文中一共展示了BoundAssignmentOperator类的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C#代码示例。

示例1: RewriteLocalDeclaration

        private static void RewriteLocalDeclaration(
            CSharpCompilation compilation,
            EENamedTypeSymbol container,
            HashSet<LocalSymbol> declaredLocals,
            ArrayBuilder<BoundStatement> statements,
            BoundLocalDeclaration node)
        {
            Debug.Assert(node.ArgumentsOpt.IsDefault);

            var local = node.LocalSymbol;
            var syntax = node.Syntax;

            declaredLocals.Add(local);

            var typeType = compilation.GetWellKnownType(WellKnownType.System_Type);
            var stringType = compilation.GetSpecialType(SpecialType.System_String);

            // CreateVariable(Type type, string name)
            var method = PlaceholderLocalSymbol.GetIntrinsicMethod(compilation, ExpressionCompilerConstants.CreateVariableMethodName);
            var type = new BoundTypeOfOperator(syntax, new BoundTypeExpression(syntax, aliasOpt: null, type: local.Type), null, typeType);
            var name = new BoundLiteral(syntax, ConstantValue.Create(local.Name), stringType);
            var call = BoundCall.Synthesized(
                syntax,
                receiverOpt: null,
                method: method,
                arguments: ImmutableArray.Create<BoundExpression>(type, name));
            statements.Add(new BoundExpressionStatement(syntax, call));

            var initializer = node.InitializerOpt;
            if (initializer != null)
            {
                // Generate assignment to local. The assignment will
                // be rewritten in PlaceholderLocalRewriter.
                var assignment = new BoundAssignmentOperator(
                    syntax,
                    new BoundLocal(syntax, local, constantValueOpt: null, type: local.Type),
                    initializer,
                    RefKind.None,
                    local.Type);
                statements.Add(new BoundExpressionStatement(syntax, assignment));
            }
        }
开发者ID:ehsansajjad465,项目名称:roslyn,代码行数:42,代码来源:LocalDeclarationRewriter.cs

示例2: RewriteLocalDeclaration

        private static void RewriteLocalDeclaration(
            ArrayBuilder<BoundStatement> statements,
            BoundLocalDeclaration node)
        {
            Debug.Assert(node.ArgumentsOpt.IsDefault);

            var initializer = node.InitializerOpt;
            if (initializer != null)
            {
                var local = node.LocalSymbol;
                var syntax = node.Syntax;

                // Generate assignment to local. The assignment will
                // be rewritten in PlaceholderLocalRewriter.
                var assignment = new BoundAssignmentOperator(
                    syntax,
                    new BoundLocal(syntax, local, constantValueOpt: null, type: local.Type),
                    initializer,
                    RefKind.None,
                    local.Type);
                statements.Add(new BoundExpressionStatement(syntax, assignment));
            }
        }
开发者ID:tvsonar,项目名称:roslyn,代码行数:23,代码来源:LocalDeclarationRewriter.cs

示例3: EmitAssignmentPreamble

        private bool EmitAssignmentPreamble(BoundAssignmentOperator assignmentOperator)
        {
            var assignmentTarget = assignmentOperator.Left;
            bool lhsUsesStack = false;

            switch (assignmentTarget.Kind)
            {
                case BoundKind.RefValueOperator:
                    EmitRefValueAddress((BoundRefValueOperator)assignmentTarget);
                    break;

                case BoundKind.FieldAccess:
                    {
                        var left = (BoundFieldAccess)assignmentTarget;
                        if (!left.FieldSymbol.IsStatic)
                        {
                            var temp = EmitReceiverRef(left.ReceiverOpt);
                            Debug.Assert(temp == null, "temp is unexpected when assigning to a field");
                            lhsUsesStack = true;
                        }
                    }
                    break;

                case BoundKind.Parameter:
                    {
                        var left = (BoundParameter)assignmentTarget;
                        if (left.ParameterSymbol.RefKind != RefKind.None)
                        {
                            _builder.EmitLoadArgumentOpcode(ParameterSlot(left));
                            lhsUsesStack = true;
                        }
                    }
                    break;

                case BoundKind.Local:
                    {
                        var left = (BoundLocal)assignmentTarget;

                        // Again, consider our earlier case:
                        //
                        // ref int addr = ref N().s;
                        // int sum = addr + 10; 
                        // addr = sum;
                        //
                        // There are three different ways we could be assigning to a local.
                        //
                        // In the first case, we want to simply call N(), take the address
                        // of s, and then store that address in addr.
                        //
                        // In the second case again we simply want to compute the sum and
                        // store the result in sum.
                        //
                        // In the third case however we want to first load the contents of
                        // addr -- the address of field s -- then put the sum on the stack,
                        // and then do an indirect store. In that case we need to have the
                        // contents of addr on the stack.

                        if (left.LocalSymbol.RefKind != RefKind.None && assignmentOperator.RefKind == RefKind.None)
                        {
                            if (!IsStackLocal(left.LocalSymbol))
                            {
                                LocalDefinition localDefinition = GetLocal(left);
                                _builder.EmitLocalLoad(localDefinition);
                            }
                            else
                            {
                                // this is a case of indirect assignment to a stack temp.
                                // currently byref temp can only be a stack local in scenarios where 
                                // there is only one assignment and it is the last one. 
                                // I do not yet know how to support cases where we assign more than once. 
                                // That where Dup of LHS would be needed, but as a general scenario 
                                // it is not always possible to handle. Fortunately all the cases where we
                                // indirectly assign to a byref temp come from rewriter and all
                                // they all are write-once cases.
                                //
                                // For now analyzer asserts that indirect writes are final reads of 
                                // a ref local. And we never need a dup here.

                                // builder.EmitOpCode(ILOpCode.Dup);
                            }

                            lhsUsesStack = true;
                        }
                    }
                    break;

                case BoundKind.ArrayAccess:
                    {
                        var left = (BoundArrayAccess)assignmentTarget;
                        EmitExpression(left.Expression, used: true);
                        EmitArrayIndices(left.Indices);
                        lhsUsesStack = true;
                    }
                    break;

                case BoundKind.ThisReference:
                    {
                        var left = (BoundThisReference)assignmentTarget;

                        var temp = EmitAddress(left, AddressKind.Writeable);
//.........这里部分代码省略.........
开发者ID:tvsonar,项目名称:roslyn,代码行数:101,代码来源:EmitExpression.cs

示例4: TryEmitAssignmentInPlace

        // sometimes it is possible and advantageous to get an address of the lHS and 
        // perform assignment as an in-place initialization via initobj or constructor invocation.
        //
        // 1) initobj 
        //    is used when assigning default value to T that is not a verifier reference.
        //
        // 2) in-place ctor call 
        //    is used when assigning a freshly created struct. "x = new S(arg)" can be
        //    replaced by x.S(arg) as long as partial assignment cannot be observed -
        //    i.e. target must not be on the heap and we should not be in a try block.
        private bool TryEmitAssignmentInPlace(BoundAssignmentOperator assignmentOperator, bool used)
        {
            var left = assignmentOperator.Left;

            // if result is used, and lives on heap, we must keep RHS value on the stack.
            // otherwise we can try conjuring up the RHS value directly where it belongs.
            if (used && !TargetIsNotOnHeap(left))
            {
                return false;
            }

            if (!SafeToGetWriteableReference(left))
            {
                // cannot take a ref
                return false;
            }

            var right = assignmentOperator.Right;
            var rightType = right.Type;

            // in-place is not advantageous for reference types or constants
            if (!rightType.IsTypeParameter())
            {
                if (rightType.IsReferenceType || (right.ConstantValue != null && rightType.SpecialType != SpecialType.System_Decimal))
                {
                    return false;
                }
            }

            if (right.IsDefaultValue())
            {
                InPlaceInit(left, used);
                return true;
            }

            if (right.Kind == BoundKind.ObjectCreationExpression)
            {
                // It is desirable to do in-place ctor call if possible.
                // we could do newobj/stloc, but in-place call 
                // produces same or better code in current JITs 
                if (PartialCtorResultCannotEscape(left))
                {
                    var objCreation = (BoundObjectCreationExpression)right;
                    InPlaceCtorCall(left, objCreation, used);
                    return true;
                }
            }

            return false;
        }
开发者ID:tvsonar,项目名称:roslyn,代码行数:60,代码来源:EmitExpression.cs

示例5: EmitAssignmentExpression

        private void EmitAssignmentExpression(BoundAssignmentOperator assignmentOperator, UseKind useKind)
        {
            if (TryEmitAssignmentInPlace(assignmentOperator, useKind != UseKind.Unused))
            {
                Debug.Assert(assignmentOperator.RefKind == RefKind.None);
                return;
            }

            // Assignment expression codegen has the following parts:
            //
            // * PreRHS: We need to emit instructions before the load of the right hand side if:
            //   - If the left hand side is a ref local or ref formal parameter and the right hand 
            //     side is a value then we must put the ref on the stack early so that we can store 
            //     indirectly into it.
            //   - If the left hand side is an array slot then we must evaluate the array and indices
            //     before we evaluate the right hand side. We ensure that the array and indices are 
            //     on the stack when the store is executed.
            //   - Similarly, if the left hand side is a non-static field then its receiver must be
            //     evaluated before the right hand side.
            //
            // * RHS: There are three possible ways to do an assignment with respect to "refness", 
            //   and all are found in the lowering of:
            //
            //   N().s += 10;
            //
            //   That expression is realized as 
            //
            //   ref int addr = ref N().s;   // Assign a ref on the right hand side to the left hand side.
            //   int sum = addr + 10;        // No refs at all; assign directly to sum.
            //   addr = sum;                 // Assigns indirectly through the address.
            //
            //   - If we are in the first case then assignmentOperator.RefKind is Ref and the left hand side is a 
            //     ref local temporary. We simply assign the ref on the RHS to the storage on the LHS with no indirection.
            //
            //   - If we are in the second case then nothing is ref; we have a value on one side an a local on the other.
            //     Again, there is no indirection.
            // 
            //   - If we are in the third case then we have a ref on the left and a value on the right. We must compute the
            //     value of the right hand side and then store it into the left hand side.
            //
            // * Duplication: The result of an assignment operation is the value that was assigned. It is possible that 
            //   later codegen is expecting this value to be on the stack when we're done here. This is controlled by
            //   the "used" formal parameter. There are two possible cases:
            //   - If the preamble put stuff on the stack for the usage of the store, then we must not put an extra copy
            //     of the right hand side value on the stack; that will be between the value and the stuff needed to 
            //     do the storage. In that case we put the right hand side value in a temporary and restore it later.
            //   - Otherwise we can just do a dup instruction; there's nothing before the dup on the stack that we'll need.
            // 
            // * Storage: Either direct or indirect, depending. See the RHS section above for details.
            // 
            // * Post-storage: If we stashed away the duplicated value in the temporary, we need to restore it back to the stack.

            bool lhsUsesStack = EmitAssignmentPreamble(assignmentOperator);
            EmitAssignmentValue(assignmentOperator);
            LocalDefinition temp = EmitAssignmentDuplication(assignmentOperator, useKind, lhsUsesStack);
            EmitStore(assignmentOperator);
            EmitAssignmentPostfix(assignmentOperator, temp, useKind);
        }
开发者ID:tvsonar,项目名称:roslyn,代码行数:58,代码来源:EmitExpression.cs

示例6: IsIndirectOrInstanceFieldAssignment

        private static bool IsIndirectOrInstanceFieldAssignment(BoundAssignmentOperator node)
        {
            var lhs = node.Left;
            if (lhs.Kind == BoundKind.FieldAccess)
            {
                return !((BoundFieldAccess)lhs).FieldSymbol.IsStatic;
            }

            return IsIndirectAssignment(node);
        }
开发者ID:rosslyn-cuongle,项目名称:roslyn,代码行数:10,代码来源:Optimizer.cs

示例7: IsIndirectAssignment

        // indirect assignment is assignment to a value referenced indirectly
        // it may only happen if 
        //      1) lhs is a reference (must be a parameter or a local)
        //      2) it is not a ref/out assignment where the reference itself would be assigned
        private static bool IsIndirectAssignment(BoundAssignmentOperator node)
        {
            var lhs = node.Left;
            switch (lhs.Kind)
            {
                case BoundKind.ThisReference:
                    Debug.Assert(lhs.Type.IsValueType && node.RefKind == RefKind.None);
                    return true;

                case BoundKind.Parameter:
                    if (((BoundParameter)lhs).ParameterSymbol.RefKind != RefKind.None)
                    {
                        bool isIndirect = node.RefKind == RefKind.None;
                        Debug.Assert(isIndirect, "direct assignment to a ref/out parameter is highly suspicious");
                        return isIndirect;
                    }

                    break;

                case BoundKind.Local:
                    if (((BoundLocal)lhs).LocalSymbol.RefKind != RefKind.None)
                    {
                        bool isIndirect = node.RefKind == RefKind.None;
                        return isIndirect;
                    }

                    break;
            }

            Debug.Assert(node.RefKind == RefKind.None, "this is not something that can be assigned indirectly");
            return false;
        }
开发者ID:rosslyn-cuongle,项目名称:roslyn,代码行数:36,代码来源:Optimizer.cs

示例8: VisitAssignmentOperator

 public override BoundNode VisitAssignmentOperator(BoundAssignmentOperator node)
 {
     // Assume value of expression is used.
     return VisitAssignmentOperator(node, used: true);
 }
开发者ID:modulexcite,项目名称:pattern-matching-csharp,代码行数:5,代码来源:CallRewriter.cs

示例9: EmitStore

        private void EmitStore(BoundAssignmentOperator assignment)
        {
            BoundExpression expression = assignment.Left;
            switch (expression.Kind)
            {
                case BoundKind.FieldAccess:
                    EmitFieldStore((BoundFieldAccess)expression);
                    break;

                case BoundKind.Local:
                    // If we are doing a 'normal' local assignment like 'int t = 10;', or
                    // if we are initializing a temporary like 'ref int t = ref M().s;' then
                    // we just emit a local store. If we are doing an assignment through
                    // a ref local temporary then we assume that the instruction to load
                    // the address is already on the stack, and we must indirect through it.

                    // See the comments in EmitAssignmentExpression above for details.
                    BoundLocal local = (BoundLocal)expression;
                    if (local.LocalSymbol.RefKind != RefKind.None && assignment.RefKind == RefKind.None)
                    {
                        EmitIndirectStore(local.LocalSymbol.Type, local.Syntax);
                    }
                    else
                    {
                        if (IsStackLocal(local.LocalSymbol))
                        {
                            // assign to stack var == leave original value on stack
                            break;
                        }
                        else
                        {
                            _builder.EmitLocalStore(GetLocal(local));
                        }
                    }
                    break;

                case BoundKind.ArrayAccess:
                    var array = ((BoundArrayAccess)expression).Expression;
                    var arrayType = (ArrayTypeSymbol)array.Type;
                    EmitArrayElementStore(arrayType, expression.Syntax);
                    break;

                case BoundKind.ThisReference:
                    EmitThisStore((BoundThisReference)expression);
                    break;

                case BoundKind.Parameter:
                    EmitParameterStore((BoundParameter)expression);
                    break;

                case BoundKind.Dup:
                    Debug.Assert(((BoundDup)expression).RefKind != RefKind.None);
                    EmitIndirectStore(expression.Type, expression.Syntax);
                    break;

                case BoundKind.RefValueOperator:
                case BoundKind.PointerIndirectionOperator:
                case BoundKind.PseudoVariable:
                    EmitIndirectStore(expression.Type, expression.Syntax);
                    break;

                case BoundKind.Sequence:
                    {
                        var sequence = (BoundSequence)expression;
                        EmitStore(assignment.Update(sequence.Value, assignment.Right, assignment.RefKind, assignment.Type));

                        var notReleased = DigForValueLocal(sequence);
                        if (notReleased != null)
                        {
                            FreeLocal(notReleased);
                        }
                    }
                    break;

                case BoundKind.Call:
                    Debug.Assert(((BoundCall)expression).Method.RefKind != RefKind.None);
                    EmitIndirectStore(expression.Type, expression.Syntax);
                    break;

                case BoundKind.ModuleVersionId:
                    EmitModuleVersionIdStore((BoundModuleVersionId)expression);
                    break;

                case BoundKind.InstrumentationPayloadRoot:
                    EmitInstrumentationPayloadRootStore((BoundInstrumentationPayloadRoot)expression);
                    break;

                case BoundKind.PreviousSubmissionReference:
                // Script references are lowered to a this reference and a field access.
                default:
                    throw ExceptionUtilities.UnexpectedValue(expression.Kind);
            }
        }
开发者ID:tvsonar,项目名称:roslyn,代码行数:93,代码来源:EmitExpression.cs

示例10: VisitAssignmentOperator

        public override BoundNode VisitAssignmentOperator(BoundAssignmentOperator node)
        {
            BoundExpression originalLeft = node.Left;

            if (originalLeft.Kind != BoundKind.Local)
            {
                return base.VisitAssignmentOperator(node);
            }

            var leftLocal = (BoundLocal)originalLeft;

            BoundExpression originalRight = node.Right;

            if (leftLocal.LocalSymbol.RefKind != RefKind.None &&
                node.RefKind != RefKind.None &&
                NeedsProxy(leftLocal.LocalSymbol))
            {
                Debug.Assert(!proxies.ContainsKey(leftLocal.LocalSymbol));
                Debug.Assert(!IsStackAlloc(originalRight));
                //spilling ref local variables
                throw ExceptionUtilities.Unreachable;
            }

            if (NeedsProxy(leftLocal.LocalSymbol) && !proxies.ContainsKey(leftLocal.LocalSymbol))
            {
                Debug.Assert(leftLocal.LocalSymbol.DeclarationKind == LocalDeclarationKind.None);
                // spilling temp variables
                throw ExceptionUtilities.Unreachable;
            }

            BoundExpression rewrittenLeft = (BoundExpression)this.Visit(leftLocal);
            BoundExpression rewrittenRight = (BoundExpression)this.Visit(originalRight);
            TypeSymbol rewrittenType = VisitType(node.Type);

            // Check if we're assigning the result of stackalloc to a hoisted local.
            // If we are, we need to store the result in a temp local and then assign
            // the value of the local to the field corresponding to the hoisted local.
            // If the receiver of the field is on the stack when the stackalloc happens,
            // popping it will free the memory (?) or otherwise cause verification issues.
            // DevDiv Bugs 59454
            if (rewrittenLeft.Kind != BoundKind.Local && IsStackAlloc(originalRight))
            {
                // From ILGENREC::genAssign:
                // DevDiv Bugs 59454: Handle hoisted local initialized with a stackalloc
                // NOTE: Need to check for cast of stackalloc on RHS.
                // If LHS isLocal, then genAddr is a noop so regular case works fine.

                SyntheticBoundNodeFactory factory = new SyntheticBoundNodeFactory(this.CurrentMethod, rewrittenLeft.Syntax, this.CompilationState, this.Diagnostics);
                BoundAssignmentOperator tempAssignment;
                BoundLocal tempLocal = factory.StoreToTemp(rewrittenRight, out tempAssignment);

                Debug.Assert(node.RefKind == RefKind.None);
                BoundAssignmentOperator rewrittenAssignment = node.Update(rewrittenLeft, tempLocal, node.RefKind, rewrittenType);

                return new BoundSequence(
                    node.Syntax,
                    ImmutableArray.Create<LocalSymbol>(tempLocal.LocalSymbol),
                    ImmutableArray.Create<BoundExpression>(tempAssignment),
                    rewrittenAssignment,
                    rewrittenType);
            }

            return node.Update(rewrittenLeft, rewrittenRight, node.RefKind, rewrittenType);
        }
开发者ID:XieShuquan,项目名称:roslyn,代码行数:64,代码来源:MethodToClassRewriter.cs

示例11: VisitAssignmentOperator

 public override BoundNode VisitAssignmentOperator(BoundAssignmentOperator node)
 {
     return this.SetMayHaveSideEffects();
 }
开发者ID:XieShuquan,项目名称:roslyn,代码行数:4,代码来源:MayHaveSideEffectsVisitor.cs

示例12: IsIndirectAssignment

        // indirect assignment is assignment to a value referenced indirectly
        // it may only happen if 
        //      1) lhs is a reference (must be a parameter or a local)
        //      2) it is not a ref/out assignment where the reference itself would be assigned
        private static bool IsIndirectAssignment(BoundAssignmentOperator node)
        {
            var lhs = node.Left;

            Debug.Assert(node.RefKind == RefKind.None || (lhs as BoundLocal)?.LocalSymbol.RefKind == RefKind.Ref,
                                "only ref locals can be a target of a ref assignment");
            
            switch (lhs.Kind)
            {
                case BoundKind.ThisReference:
                    Debug.Assert(lhs.Type.IsValueType, "'this' is assignable only in structs");
                    return true;

                case BoundKind.Parameter:
                    if (((BoundParameter)lhs).ParameterSymbol.RefKind != RefKind.None)
                    {
                        bool isIndirect = node.RefKind == RefKind.None;
                        return isIndirect;
                    }

                    return false;

                case BoundKind.Local:
                    if (((BoundLocal)lhs).LocalSymbol.RefKind != RefKind.None)
                    {
                        bool isIndirect = node.RefKind == RefKind.None;
                        return isIndirect;
                    }

                    return false;

                case BoundKind.Call:
                    Debug.Assert(((BoundCall)lhs).Method.RefKind == RefKind.Ref, "only ref returning methods are assignable");
                    return true;

                case BoundKind.AssignmentOperator:
                    Debug.Assert(((BoundAssignmentOperator)lhs).RefKind == RefKind.Ref, "only ref assignments are assignable");
                    return true;

                case BoundKind.Sequence:
                    Debug.Assert(!IsIndirectAssignment(node.Update(((BoundSequence)node.Left).Value, node.Right, node.RefKind, node.Type)), 
                        "indirect assignment to a sequence is unexpected");
                    return false;

                case BoundKind.RefValueOperator:
                case BoundKind.PointerIndirectionOperator:
                case BoundKind.PseudoVariable:
                    return true;

                case BoundKind.ModuleVersionId:
                case BoundKind.InstrumentationPayloadRoot:
                    // these are just stores into special static fields
                    goto case BoundKind.FieldAccess;

                case BoundKind.FieldAccess:
                case BoundKind.ArrayAccess:
                    // always symbolic stores
                    return false;

                default:
                    throw ExceptionUtilities.UnexpectedValue(lhs.Kind);
            }
        }
开发者ID:TyOverby,项目名称:roslyn,代码行数:67,代码来源:Optimizer.cs

示例13: EmitAssignmentValue

 private void EmitAssignmentValue(BoundAssignmentOperator assignmentOperator)
 {
     if (assignmentOperator.RefKind == RefKind.None)
     {
         EmitExpression(assignmentOperator.Right, used: true);
     }
     else
     {
         // LEAKING A TEMP IS OK HERE
         // Once a reference is assigned to a byref local, there is no easy way to figure when 
         // reference is no longer in use.
         // Therefore if we had to create a temp while producing a reference, we do not know when 
         // the temp slot can be reused so we must leak it.
         var temp = EmitAddress(assignmentOperator.Right, AddressKind.Writeable);
     }
 }
开发者ID:riversky,项目名称:roslyn,代码行数:16,代码来源:EmitExpression.cs

示例14: VisitCompoundAssignmentOperator


//.........这里部分代码省略.........
                // UNDONE:
                // UNDONE: For now, we'll punt on both problems, as indexers are not implemented yet anyway.
                // UNDONE: We'll just generate one temporary for each argument. This will work, but in the
                // UNDONE: subsequent rewritings will generate more unnecessary temporaries. 

                var transformedArguments = ArrayBuilder<BoundExpression>.GetInstance();
                foreach (var argument in indexer.Arguments)
                {
                    var rewrittenArgument = (BoundExpression)Visit(argument);
                    var argumentTemp = TempHelpers.StoreToTemp(rewrittenArgument, RefKind.None, containingSymbol);
                    transformedArguments.Add(argumentTemp.Item2);
                    stores.Add(argumentTemp.Item1);
                    temps.Add(argumentTemp.Item2.LocalSymbol);
                }

                transformedLHS = new BoundIndexerAccess(indexer.Syntax, indexer.SyntaxTree, transformedArguments.ToReadOnlyAndFree(), transformedReceiver,
                    indexer.IndexerSymbol, indexer.Type);
            }
            else if (node.Left.Kind == BoundKind.Local || node.Left.Kind == BoundKind.Parameter)
            {
                // No temporaries are needed. Just generate local = local + value
                transformedLHS = node.Left;
            }
            else if (node.Left.Kind == BoundKind.FieldAccess)
            {
                // * If the field is static then no temporaries are needed. 
                // * If the field is not static and the receiver is of reference type then generate t = r; t.f = t.f + value
                // * If the field is not static and the receiver is a variable of value type then we'll fall into the
                //   general variable case below.

                var fieldAccess = (BoundFieldAccess)node.Left;
                if (fieldAccess.ReceiverOpt == null)
                {
                    transformedLHS = fieldAccess;
                }
                else if (!fieldAccess.ReceiverOpt.Type.IsValueType)
                {
                    var rewrittenReceiver = (BoundExpression)Visit(fieldAccess.ReceiverOpt);
                    var receiverTemp = TempHelpers.StoreToTemp(rewrittenReceiver, RefKind.None, containingSymbol);
                    stores.Add(receiverTemp.Item1);
                    temps.Add(receiverTemp.Item2.LocalSymbol);
                    transformedLHS = new BoundFieldAccess(fieldAccess.Syntax, fieldAccess.SyntaxTree, receiverTemp.Item2, fieldAccess.FieldSymbol, null);
                }
            }

            if (transformedLHS == null)
            {
                // We made no transformation above. Either we have array[index] += value or 
                // structVariable.field += value; either way we have a potentially complicated variable-
                // producing expression on the left. Generate
                // ref temp = ref variable; temp = temp + value
                var rewrittenVariable = (BoundExpression)Visit(node.Left);
                var variableTemp = TempHelpers.StoreToTemp(rewrittenVariable, RefKind.Ref, containingSymbol);
                stores.Add(variableTemp.Item1);
                temps.Add(variableTemp.Item2.LocalSymbol);
                transformedLHS = variableTemp.Item2;
            }

            // OK, we now have the temporary declarations, the temporary stores, and the transformed left hand side.
            // We need to generate 
            //
            // xlhs = (FINAL)((LEFT)xlhs op rhs)
            //
            // And then wrap it up with the generated temporaries.
            //
            // (The right hand side has already been converted to the type expected by the operator.)

            BoundExpression opLHS = BoundConversion.SynthesizedConversion(transformedLHS, node.LeftConversion, node.Operator.LeftType);
            Debug.Assert(node.Right.Type == node.Operator.RightType);
            BoundExpression op = new BoundBinaryOperator(null, null, node.Operator.Kind, opLHS, node.Right, null, node.Operator.ReturnType);
            BoundExpression opFinal = BoundConversion.SynthesizedConversion(op, node.FinalConversion, node.Left.Type);
            BoundExpression assignment = new BoundAssignmentOperator(null, null, transformedLHS, opFinal, node.Left.Type);

            // OK, at this point we have:
            //
            // * temps evaluating and storing portions of the LHS that must be evaluated only once.
            // * the "transformed" left hand side, rebuilt to use temps where necessary
            // * the assignment "xlhs = (FINAL)((LEFT)xlhs op (RIGHT)rhs)"
            // 
            // Notice that we have recursively rewritten the bound nodes that are things stored in
            // the temps, but we might have more rewriting to do on the assignment. There are three
            // conversions in there that might be lowered to method calls, an operator that might
            // be lowered to delegate combine, string concat, and so on, and don't forget, we 
            // haven't lowered the right hand side at all! Let's rewrite all these things at once.

            BoundExpression rewrittenAssignment = (BoundExpression)Visit(assignment);

            BoundExpression result = (temps.Count == 0) ?
                rewrittenAssignment :
                new BoundSequence(null,
                    null,
                    temps.ToReadOnly(),
                    stores.ToReadOnly(),
                    rewrittenAssignment,
                    rewrittenAssignment.Type);

            temps.Free();
            stores.Free();
            return result;
        }
开发者ID:modulexcite,项目名称:pattern-matching-csharp,代码行数:101,代码来源:OperatorRewriter.cs

示例15: EmitAssignmentValue

        private void EmitAssignmentValue(BoundAssignmentOperator assignmentOperator)
        {
            if (assignmentOperator.RefKind == RefKind.None)
            {
                EmitExpression(assignmentOperator.Right, used: true);
            }
            else
            {
                // LEAKING A TEMP IS OK HERE 
                // generally taking a ref for the purpose of ref assignment should not be done on homeless values
                // however, there are very rare cases when we need to get a ref off a copy in synthetic code and we have to leak those.
                // fortunately these are very short-lived temps that should not cause value sharing.
                var temp = EmitAddress(assignmentOperator.Right, AddressKind.Writeable);
#if DEBUG
                Debug.Assert(temp == null || ((SynthesizedLocal)assignmentOperator.Left.ExpressionSymbol).SynthesizedKind == SynthesizedLocalKind.LoweringTemp);
#endif
            }
        }
开发者ID:tvsonar,项目名称:roslyn,代码行数:18,代码来源:EmitExpression.cs


注:本文中的BoundAssignmentOperator类示例由纯净天空整理自Github/MSDocs等开源代码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。