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


C# CSharp.BoundLocal类代码示例

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


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

示例1: ApplyConversions

        /// <summary>
        /// Applies the conversions.
        /// Adds any new locals to the temps and any new expressions to be evaluated to the stores.
        /// </summary>
        private void ApplyConversions(BoundDeconstructionAssignmentOperator node, ArrayBuilder<LocalSymbol> temps, ArrayBuilder<BoundExpression> stores, ArrayBuilder<BoundValuePlaceholderBase> placeholders)
        {
            int numConversions = node.ConversionSteps.Length;
            var conversionLocals = ArrayBuilder<BoundExpression>.GetInstance();

            foreach (var conversionInfo in node.ConversionSteps)
            {
                // lower the conversions and assignments to locals
                var localSymbol = new SynthesizedLocal(_factory.CurrentMethod, conversionInfo.OutputPlaceholder.Type, SynthesizedLocalKind.LoweringTemp);
                var localBound = new BoundLocal(node.Syntax,
                                               localSymbol,
                                               null,
                                               conversionInfo.OutputPlaceholder.Type)
                { WasCompilerGenerated = true };

                temps.Add(localSymbol);
                conversionLocals.Add(localBound);

                AddPlaceholderReplacement(conversionInfo.OutputPlaceholder, localBound);
                placeholders.Add(conversionInfo.OutputPlaceholder);

                var conversion = VisitExpression(conversionInfo.Assignment);

                stores.Add(conversion);
            }
        }
开发者ID:otawfik-ms,项目名称:roslyn,代码行数:30,代码来源:LocalRewriter_DeconstructionAssignmentOperator.cs

示例2: Create

        public static DecisionTree Create(BoundExpression expression, TypeSymbol type, Symbol enclosingSymbol)
        {
            Debug.Assert(expression.Type == type);
            LocalSymbol temp = null;
            if (expression.ConstantValue == null)
            {
                // Unless it is a constant, the decision tree acts on a copy of the input expression.
                // We create a temp to represent that copy. Lowering will assign into this temp.
                temp = new SynthesizedLocal(enclosingSymbol as MethodSymbol, type, SynthesizedLocalKind.PatternMatchingTemp, expression.Syntax, false, RefKind.None);
                expression = new BoundLocal(expression.Syntax, temp, null, type);
            }

            if (expression.Type.CanBeAssignedNull())
            {
                // We need the ByType decision tree to separate null from non-null values.
                // Note that, for the purpose of the decision tree (and subsumption), we
                // ignore the fact that the input may be a constant, and therefore always
                // or never null.
                return new ByType(expression, type, temp);
            }
            else
            {
                // If it is a (e.g. builtin) value type, we can switch on its (constant) values.
                // If it isn't a builtin, in practice we will only use the Default part of the
                // ByValue.
                return new ByValue(expression, type, temp);
            }
        }
开发者ID:XieShuquan,项目名称:roslyn,代码行数:28,代码来源:DecisionTree.cs

示例3: StoreToTemp

        /// <summary>
        /// Takes an expression and returns the bound local expression "temp" 
        /// and the bound assignment expression "temp = expr".
        /// </summary>
        /// <param name="argument"></param>
        /// <param name="refKind"></param>
        /// <param name="containingMethod"></param>
        /// <returns></returns>
        public static Pair<BoundAssignmentOperator, BoundLocal> StoreToTemp(BoundExpression argument, RefKind refKind, MethodSymbol containingMethod)
        {
            var syntax = argument.Syntax;
            var type = argument.Type;
            var local = new BoundLocal(
                    syntax,
                    // TODO: the following temp local symbol should have its ContainingSymbol set.
                    new TempLocalSymbol(type, refKind, containingMethod),
                    null,
                    type);

            var store = new BoundAssignmentOperator(
                syntax,
                local,
                argument,
                refKind,
                type);

            return Pair.Make(store, local);
        }
开发者ID:Rickinio,项目名称:roslyn,代码行数:28,代码来源:TempHelpers.cs

示例4: VisitDeclarationExpression

        public override BoundNode VisitDeclarationExpression(BoundDeclarationExpression node)
        {
            var local = new BoundLocal(node.Syntax, node.LocalSymbol, null, node.LocalSymbol.Type);

            if (node.InitializerOpt == null)
            {
                return local;
            }

            return new BoundSequence(node.Syntax, 
                                     ImmutableArray<LocalSymbol>.Empty, 
                                     ImmutableArray.Create<BoundExpression>(new BoundAssignmentOperator(
                                                                                                        node.Syntax,
                                                                                                        new BoundLocal(
                                                                                                            local.Syntax,
                                                                                                            local.LocalSymbol,
                                                                                                            null,
                                                                                                            local.Type
                                                                                                        ),
                                                                                                        VisitExpression(node.InitializerOpt),
                                                                                                        local.Type)),
                                     local,
                                     local.Type);
        }
开发者ID:jerriclynsjohn,项目名称:roslyn,代码行数:24,代码来源:LocalRewriter_LocalDeclaration.cs

示例5: RewriteMultiDimensionalArrayForEachStatement

        /// <summary>
        /// Lower a foreach loop that will enumerate a multi-dimensional array.
        /// 
        /// A[...] a = x;
        /// int q_0 = a.GetUpperBound(0), q_1 = a.GetUpperBound(1), ...;
        /// for (int p_0 = a.GetLowerBound(0); p_0 &lt;= q_0; p_0 = p_0 + 1)
        ///     for (int p_1 = a.GetLowerBound(1); p_1 &lt;= q_1; p_1 = p_1 + 1)
        ///         ...
        ///             { V v = (V)a[p_0, p_1, ...]; /* body */ }
        /// </summary>
        /// <remarks>
        /// We will follow Dev10 in diverging from the C# 4 spec by ignoring Array's 
        /// implementation of IEnumerable and just indexing into its elements.
        /// 
        /// NOTE: We're assuming that sequence points have already been generated.
        /// Otherwise, lowering to nested for-loops would generated spurious ones.
        /// </remarks>
        private BoundStatement RewriteMultiDimensionalArrayForEachStatement(BoundForEachStatement node)
        {
            ForEachStatementSyntax forEachSyntax = (ForEachStatementSyntax)node.Syntax;

            BoundExpression collectionExpression = GetUnconvertedCollectionExpression(node);
            Debug.Assert(collectionExpression.Type.IsArray());

            ArrayTypeSymbol arrayType = (ArrayTypeSymbol)collectionExpression.Type;

            int rank = arrayType.Rank;
            Debug.Assert(!arrayType.IsSZArray);

            TypeSymbol intType = _compilation.GetSpecialType(SpecialType.System_Int32);
            TypeSymbol boolType = _compilation.GetSpecialType(SpecialType.System_Boolean);

            // Values we'll use every iteration
            MethodSymbol getLowerBoundMethod = GetSpecialTypeMethod(forEachSyntax, SpecialMember.System_Array__GetLowerBound);
            MethodSymbol getUpperBoundMethod = GetSpecialTypeMethod(forEachSyntax, SpecialMember.System_Array__GetUpperBound);

            BoundExpression rewrittenExpression = (BoundExpression)Visit(collectionExpression);
            BoundStatement rewrittenBody = (BoundStatement)Visit(node.Body);

            // A[...] a
            LocalSymbol arrayVar = _factory.SynthesizedLocal(arrayType, syntax: forEachSyntax, kind: SynthesizedLocalKind.ForEachArray);
            BoundLocal boundArrayVar = MakeBoundLocal(forEachSyntax, arrayVar, arrayType);

            // A[...] a = /*node.Expression*/;
            BoundStatement arrayVarDecl = MakeLocalDeclaration(forEachSyntax, arrayVar, rewrittenExpression);

            AddForEachExpressionSequencePoint(forEachSyntax, ref arrayVarDecl);

            // NOTE: dev10 initializes all of the upper bound temps before entering the loop (as opposed to
            // initializing each one at the corresponding level of nesting).  Doing it at the same time as
            // the lower bound would make this code a bit simpler, but it would make it harder to compare
            // the roslyn and dev10 IL.

            // int q_0, q_1, ...
            LocalSymbol[] upperVar = new LocalSymbol[rank];
            BoundLocal[] boundUpperVar = new BoundLocal[rank];
            BoundStatement[] upperVarDecl = new BoundStatement[rank];
            for (int dimension = 0; dimension < rank; dimension++)
            {
                // int q_dimension
                upperVar[dimension] = _factory.SynthesizedLocal(intType, syntax: forEachSyntax, kind: SynthesizedLocalKind.ForEachArrayLimit);
                boundUpperVar[dimension] = MakeBoundLocal(forEachSyntax, upperVar[dimension], intType);

                ImmutableArray<BoundExpression> dimensionArgument = ImmutableArray.Create(
                    MakeLiteral(forEachSyntax,
                        constantValue: ConstantValue.Create(dimension, ConstantValueTypeDiscriminator.Int32),
                        type: intType));

                // a.GetUpperBound(dimension)
                BoundExpression currentDimensionUpperBound = BoundCall.Synthesized(forEachSyntax, boundArrayVar, getUpperBoundMethod, dimensionArgument);

                // int q_dimension = a.GetUpperBound(dimension);
                upperVarDecl[dimension] = MakeLocalDeclaration(forEachSyntax, upperVar[dimension], currentDimensionUpperBound);
            }

            // int p_0, p_1, ...
            LocalSymbol[] positionVar = new LocalSymbol[rank];
            BoundLocal[] boundPositionVar = new BoundLocal[rank];
            for (int dimension = 0; dimension < rank; dimension++)
            {
                positionVar[dimension] = _factory.SynthesizedLocal(intType, syntax: forEachSyntax, kind: SynthesizedLocalKind.ForEachArrayIndex);
                boundPositionVar[dimension] = MakeBoundLocal(forEachSyntax, positionVar[dimension], intType);
            }

            // V v
            LocalSymbol iterationVar = node.IterationVariable;
            TypeSymbol iterationVarType = iterationVar.Type;

            // (V)a[p_0, p_1, ...]
            BoundExpression iterationVarInitValue = MakeConversion(
                syntax: forEachSyntax,
                rewrittenOperand: new BoundArrayAccess(forEachSyntax,
                    expression: boundArrayVar,
                    indices: ImmutableArray.Create((BoundExpression[])boundPositionVar),
                    type: arrayType.ElementType),
                conversion: node.ElementConversion,
                rewrittenType: iterationVarType,
                @checked: node.Checked);

            // V v = (V)a[p_0, p_1, ...];
//.........这里部分代码省略.........
开发者ID:CAPCHIK,项目名称:roslyn,代码行数:101,代码来源:LocalRewriter_ForEachStatement.cs

示例6: VisitLvalue

 protected override void VisitLvalue(BoundLocal node)
 {
     VisitLocal(node);
 }
开发者ID:XieShuquan,项目名称:roslyn,代码行数:4,代码来源:VariablesDeclaredWalker.cs

示例7: RewriteUsingStatementTryFinally

        private BoundStatement RewriteUsingStatementTryFinally(CSharpSyntaxNode syntax, BoundBlock tryBlock, BoundLocal local)
        {
            // SPEC: When ResourceType is a non-nullable value type, the expansion is:
            // SPEC: 
            // SPEC: { 
            // SPEC:   ResourceType resource = expr; 
            // SPEC:   try { statement; } 
            // SPEC:   finally { ((IDisposable)resource).Dispose(); }
            // SPEC: }
            // SPEC:
            // SPEC: Otherwise, when Resource type is a nullable value type or
            // SPEC: a reference type other than dynamic, the expansion is:
            // SPEC: 
            // SPEC: { 
            // SPEC:   ResourceType resource = expr; 
            // SPEC:   try { statement; } 
            // SPEC:   finally { if (resource != null) ((IDisposable)resource).Dispose(); }
            // SPEC: }
            // SPEC: 
            // SPEC: Otherwise, when ResourceType is dynamic, the expansion is:
            // SPEC: { 
            // SPEC:   dynamic resource = expr; 
            // SPEC:   IDisposable d = (IDisposable)resource;
            // SPEC:   try { statement; } 
            // SPEC:   finally { if (d != null) d.Dispose(); }
            // SPEC: }
            // SPEC: 
            // SPEC: An implementation is permitted to implement a given using statement 
            // SPEC: differently -- for example, for performance reasons -- as long as the 
            // SPEC: behavior is consistent with the above expansion.
            //
            // And we do in fact generate the code slightly differently than precisely how it is 
            // described above.
            //
            // First: if the type is a non-nullable value type then we do not do the 
            // *boxing conversion* from the resource to IDisposable. Rather, we do
            // a *constrained virtual call* that elides the boxing if possible. 
            //
            // Now, you might wonder if that is legal; isn't skipping the boxing producing
            // an observable difference? Because if the value type is mutable and the Dispose
            // mutates it, then skipping the boxing means that we are now mutating the original,
            // not the boxed copy. But this is never observable. Either (1) we have "using(R r = x){}"
            // and r is out of scope after the finally, so it is not possible to observe the mutation,
            // or (2) we have "using(x) {}". But that has the semantics of "using(R temp = x){}",
            // so again, we are not mutating x to begin with; we're always mutating a copy. Therefore
            // it doesn't matter if we skip making *a copy of the copy*.
            //
            // This is what the dev10 compiler does, and we do so as well.
            //
            // Second: if the type is a nullable value type then we can similarly elide the boxing.
            // We can generate
            //
            // { 
            //   ResourceType resource = expr; 
            //   try { statement; } 
            //   finally { if (resource.HasValue) resource.GetValueOrDefault().Dispose(); }
            // }
            //
            // Where again we do a constrained virtual call to Dispose, rather than boxing
            // the value to IDisposable.
            //
            // Note that this optimization is *not* what the native compiler does; in this case
            // the native compiler behavior is to test for HasValue, then *box* and convert
            // the boxed value to IDisposable. There's no need to do that.
            //
            // Third: if we have "using(x)" and x is dynamic then obviously we need not generate
            // "{ dynamic temp1 = x; IDisposable temp2 = (IDisposable) temp1; ... }". Rather, we elide
            // the completely unnecessary first temporary. 

            BoundExpression disposedExpression;
            bool isNullableValueType = local.Type.IsNullableType();

            if (isNullableValueType)
            {
                MethodSymbol getValueOrDefault = GetNullableMethod(syntax, local.Type, SpecialMember.System_Nullable_T_GetValueOrDefault);
                // local.GetValueOrDefault()
                disposedExpression = BoundCall.Synthesized(syntax, local, getValueOrDefault);
            }
            else
            {
                // local
                disposedExpression = local;
            }

            // local.Dispose()
            BoundExpression disposeCall;

            MethodSymbol disposeMethodSymbol;
            if (TryGetSpecialTypeMember(syntax, SpecialMember.System_IDisposable__Dispose, out disposeMethodSymbol))
            {
                disposeCall = BoundCall.Synthesized(syntax, disposedExpression, disposeMethodSymbol);
            }
            else
            {
                disposeCall = new BoundBadExpression(syntax, LookupResultKind.NotInvocable, ImmutableArray<Symbol>.Empty, ImmutableArray.Create<BoundNode>(disposedExpression), ErrorTypeSymbol.UnknownResultType);
            }

            // local.Dispose();
            BoundStatement disposeStatement = new BoundExpressionStatement(syntax, disposeCall);

//.........这里部分代码省略.........
开发者ID:EkardNT,项目名称:Roslyn,代码行数:101,代码来源:LocalRewriter_UsingStatement.cs

示例8: CallDeconstruct

        /// <summary>
        /// Prepares local variables to be used in Deconstruct call
        /// Adds a invocation of Deconstruct with those as out parameters onto the 'stores' sequence
        /// Returns the expressions for those out parameters
        /// </summary>
        private void CallDeconstruct(BoundDeconstructionAssignmentOperator node, BoundDeconstructionDeconstructStep deconstruction, ArrayBuilder<LocalSymbol> temps, ArrayBuilder<BoundExpression> stores, ArrayBuilder<BoundValuePlaceholderBase> placeholders)
        {
            Debug.Assert((object)deconstruction.DeconstructInvocationOpt != null);

            CSharpSyntaxNode syntax = node.Syntax;

            // prepare out parameters for Deconstruct
            var deconstructParameters = deconstruction.OutputPlaceholders;
            var outParametersBuilder = ArrayBuilder<BoundExpression>.GetInstance(deconstructParameters.Length);

            for (var i = 0; i < deconstructParameters.Length; i++)
            {
                var deconstructParameter = deconstructParameters[i];
                var localSymbol = new SynthesizedLocal(_factory.CurrentMethod, deconstructParameter.Type, SynthesizedLocalKind.LoweringTemp);

                var localBound = new BoundLocal(syntax,
                                                localSymbol,
                                                null,
                                                deconstructParameter.Type
                                                )
                { WasCompilerGenerated = true };

                temps.Add(localSymbol);
                outParametersBuilder.Add(localBound);

                AddPlaceholderReplacement(deconstruction.OutputPlaceholders[i], localBound);
                placeholders.Add(deconstruction.OutputPlaceholders[i]);
            }

            var outParameters = outParametersBuilder.ToImmutableAndFree();

            // invoke Deconstruct with placeholders replaced by locals
            stores.Add(VisitExpression(deconstruction.DeconstructInvocationOpt));
        }
开发者ID:Rickinio,项目名称:roslyn,代码行数:39,代码来源:LocalRewriter_DeconstructionAssignmentOperator.cs

示例9: BindCatchBlock

        private BoundCatchBlock BindCatchBlock(CatchClauseSyntax node, ArrayBuilder<BoundCatchBlock> previousBlocks, DiagnosticBag diagnostics)
        {
            bool hasError = false;
            TypeSymbol type = null;
            BoundExpression boundFilter = null;
            var declaration = node.Declaration;
            if (declaration != null)
            {
                // Note: The type is being bound twice: here and in LocalSymbol.Type. Currently,
                // LocalSymbol.Type ignores diagnostics so it seems cleaner to bind the type here
                // as well. However, if LocalSymbol.Type is changed to report diagnostics, we'll
                // need to avoid binding here since that will result in duplicate diagnostics.
                type = this.BindType(declaration.Type, diagnostics);
                Debug.Assert((object)type != null);

                if (type.IsErrorType())
                {
                    hasError = true;
                }
                else
                {
                    HashSet<DiagnosticInfo> useSiteDiagnostics = null;
                    TypeSymbol effectiveType = type.EffectiveType(ref useSiteDiagnostics);
                    if (!Compilation.IsExceptionType(effectiveType, ref useSiteDiagnostics))
                    {
                        // "The type caught or thrown must be derived from System.Exception"
                        Error(diagnostics, ErrorCode.ERR_BadExceptionType, declaration.Type);
                        hasError = true;
                        diagnostics.Add(declaration.Type, useSiteDiagnostics);
                    }
                }
            }

            var filter = node.Filter;
            if (filter != null)
            {
                var filterBinder = this.GetBinder(filter);
                boundFilter = filterBinder.BindCatchFilter(filter, diagnostics);
                hasError |= boundFilter.HasAnyErrors;
            }

            if (!hasError)
            {
                // TODO: Loop is O(n), caller is O(n^2).  Perhaps we could iterate in reverse order (since it's easier to find
                // base types than to find derived types).
                Debug.Assert(((object)type == null) || !type.IsErrorType());
                foreach (var previousBlock in previousBlocks)
                {
                    var previousType = previousBlock.ExceptionTypeOpt;

                    // If the previous type is a generic parameter we don't know what exception types it's gonna catch exactly.
                    // If it is a class-type we know it's gonna catch all exception types of its type and types that are derived from it.
                    // So if the current type is a class-type (or an effective base type of a generic parameter) 
                    // that derives from the previous type the current catch is unreachable.

                    if (previousBlock.ExceptionFilterOpt == null && (object)previousType != null && !previousType.IsErrorType())
                    {
                        if ((object)type != null)
                        {
                            HashSet<DiagnosticInfo> useSiteDiagnostics = null;

                            if (Conversions.HasIdentityOrImplicitReferenceConversion(type, previousType, ref useSiteDiagnostics))
                            {
                                // "A previous catch clause already catches all exceptions of this or of a super type ('{0}')"
                                Error(diagnostics, ErrorCode.ERR_UnreachableCatch, declaration.Type, previousType);
                                diagnostics.Add(declaration.Type, useSiteDiagnostics);
                                hasError = true;
                                break;
                            }

                            diagnostics.Add(declaration.Type, useSiteDiagnostics);
                        }
                        else if (previousType == Compilation.GetWellKnownType(WellKnownType.System_Exception) &&
                                 Compilation.SourceAssembly.RuntimeCompatibilityWrapNonExceptionThrows)
                        {
                            // If the RuntimeCompatibility(WrapNonExceptionThrows = false) is applied on the source assembly or any referenced netmodule.
                            // an empty catch may catch exceptions that don't derive from System.Exception.

                            // "A previous catch clause already catches all exceptions..."
                            Error(diagnostics, ErrorCode.WRN_UnreachableGeneralCatch, node.CatchKeyword);
                            break;
                        }
                    }
                }
            }

            BoundExpression exceptionSource = null;
            LocalSymbol local = this.Locals.FirstOrDefault();
            if ((object)local != null)
            {
                Debug.Assert(this.Locals.Length == 1);

                // Check for local variable conflicts in the *enclosing* binder, not the *current* binder;
                // obviously we will find a local of the given name in the current binder.
                hasError |= this.ValidateDeclarationNameConflictsInScope(local, diagnostics);

                exceptionSource = new BoundLocal(declaration, local, ConstantValue.NotAvailable, local.Type);
            }

            var block = this.BindBlock(node.Block, diagnostics);
//.........这里部分代码省略.........
开发者ID:elemk0vv,项目名称:roslyn-1,代码行数:101,代码来源:Binder_Statements.cs

示例10: EmitFinallyFrame

        /// <summary>
        /// Produces a Try/Finally if frame has a handler (otherwise a regular block).
        /// Handler goes into the Finally.
        /// If there are nested frames, they are emitted into the try block.
        /// This way the handler for the current frame is guaranteed to run even if 
        /// nested handlers throw exceptions.
        /// 
        /// {
        ///     switch(state)
        ///     {
        ///         case state1:
        ///         case state2:
        ///         case state3:
        ///         case state4:
        ///             try
        ///             {
        ///                 switch(state)
        ///                 {
        ///                     case state3:
        ///                     case state4:
        ///                         try
        ///                         {
        ///                             ... more nested state dispatches if any ....
        ///                         }
        ///                         finally
        ///                         {
        ///                             // handler for a try where state3 and state4 can be observed
        ///                             handler_3_4()
        ///                         }
        ///                         break;
        ///                  }
        ///             }
        ///             finally
        ///             {
        ///                 // handler for a try where state1 and state2 can be observed
        ///                 handler_1_2()
        ///             }
        ///             break;
        ///             
        ///         case state5:
        ///             ... another dispatch of nested states to their finally blocks ...
        ///             break;
        ///     }
        /// }
        /// 
        /// </summary>
        private BoundStatement EmitFinallyFrame(IteratorFinallyFrame frame, BoundLocal state)
        {
            BoundStatement body = null;
            if (frame.knownStates != null)
            {
                var breakLabel = F.GenerateLabel("break");
                var sections = from ft in frame.knownStates
                               group ft.Key by ft.Value into g
                               select F.SwitchSection(
                                    new List<int>(g),
                                    EmitFinallyFrame(g.Key, state),
                                    F.Goto(breakLabel));

                body = F.Block(
                    F.Switch(state, sections),
                    F.Label(breakLabel));
            }

            if (!frame.IsRoot())
            {
                var tryBlock = body != null ? F.Block(body) : F.Block();
                body = F.Try(
                    tryBlock,
                    ImmutableArray<BoundCatchBlock>.Empty,
                    F.Block(F.ExpressionStatement(F.Call(F.This(), frame.handler))));
            }

            Debug.Assert(body != null, "we should have either sub-dispatch or a handler");
            return body;
        }
开发者ID:daking2014,项目名称:roslyn,代码行数:76,代码来源:IteratorMethodToStateMachineRewriter.cs

示例11: VisitIncrementOperator

        /// <summary>
        /// The rewrites are as follows: suppose the operand x is a variable of type X. The
        /// chosen increment/decrement operator is modelled as a static method on a type T,
        /// which takes a value of type T and returns the result of incrementing or decrementing
        /// that value.
        /// 
        /// x++
        ///     X temp = x
        ///     x = (X)(T.Increment((T)temp))
        ///     return temp
        /// x--
        ///     X temp = x
        ///     x = (X)(T.Decrement((T)temp))
        ///     return temp
        /// ++x
        ///     X temp = (X)(T.Increment((T)x))
        ///     x = temp
        ///     return temp
        /// --x
        ///     X temp = (X)(T.Decrement((T)x))
        ///     x = temp
        ///     return temp
        /// 
        /// Note: 
        /// Dev11 implements dynamic prefix operators incorrectly.
        /// 
        ///   result = ++x.P  is emitted as  result = SetMember{"P"}(t, UnaryOperation{Inc}(GetMember{"P"}(x)))
        /// 
        /// The difference is that Dev11 relies on SetMember returning the same value as it was given as an argument.
        /// Failing to do so changes the semantics of ++/-- operator which is undesirable. We emit the same pattern for
        /// both dynamic and static operators.
        ///    
        /// For example, we might have a class X with user-defined implicit conversions
        /// to and from short, but no user-defined increment or decrement operators. We
        /// would bind x++ as "X temp = x; x = (X)(short)((int)(short)temp + 1); return temp;"
        /// </summary>
        /// <param name="node">The unary operator expression representing the increment/decrement.</param>
        /// <returns>A bound sequence that uses a temp to achieve the correct side effects and return value.</returns>
        public override BoundNode VisitIncrementOperator(BoundIncrementOperator node)
        {
            bool isPrefix = IsPrefix(node);
            bool isDynamic = node.OperatorKind.IsDynamic();
            bool isChecked = node.OperatorKind.IsChecked();

            ArrayBuilder<LocalSymbol> tempSymbols = ArrayBuilder<LocalSymbol>.GetInstance();
            ArrayBuilder<BoundExpression> tempInitializers = ArrayBuilder<BoundExpression>.GetInstance();

            CSharpSyntaxNode syntax = node.Syntax;

            // This will be filled in with the LHS that uses temporaries to prevent
            // double-evaluation of side effects.
            BoundExpression transformedLHS = TransformCompoundAssignmentLHS(node.Operand, tempInitializers, tempSymbols, isDynamic);
            TypeSymbol operandType = transformedLHS.Type; //type of the variable being incremented
            Debug.Assert(operandType == node.Type);

            LocalSymbol tempSymbol = _factory.SynthesizedLocal(operandType);
            tempSymbols.Add(tempSymbol);
            // Not adding an entry to tempInitializers because the initial value depends on the case.

            BoundExpression boundTemp = new BoundLocal(
                syntax: syntax,
                localSymbol: tempSymbol,
                constantValueOpt: null,
                type: operandType);

            // prefix:  (X)(T.Increment((T)operand)))
            // postfix: (X)(T.Increment((T)temp)))
            var newValue = MakeIncrementOperator(node, rewrittenValueToIncrement: (isPrefix ? MakeRValue(transformedLHS) : boundTemp));

            // there are two strategies for completing the rewrite.
            // The reason is that indirect assignments read the target of the assignment before evaluating 
            // of the assignment value and that may cause reads of operand and boundTemp to cross which 
            // in turn would require one of them to be a real temp (not a stack local)
            //
            // To avoid this issue, in a case of ByRef operand, we perform a "nested sequence" rewrite.
            //
            // Ex: 
            //    Seq{..., operand = Seq{temp = operand + 1, temp}, ...}       
            //  instead of 
            //    Seq{.... temp = operand + 1, operand = temp, ...}              
            //
            // Such rewrite will nest reads of boundTemp relative to reads of operand so both 
            // operand and boundTemp could be optimizable (subject to all other conditions of course).
            //
            // In a case of the non-byref operand we use a single-sequence strategy as it results in shorter 
            // overall life time of temps and as such more appropriate. (problem of crossed reads does not affect that case)
            //
            if (IsIndirectOrInstanceField(transformedLHS))
            {
                return RewriteWithRefOperand(isPrefix, isChecked, tempSymbols, tempInitializers, syntax, transformedLHS, operandType, boundTemp, newValue);
            }
            else
            {
                return RewriteWithNotRefOperand(isPrefix, isChecked, tempSymbols, tempInitializers, syntax, transformedLHS, operandType, boundTemp, newValue);
            }
        }
开发者ID:Rickinio,项目名称:roslyn,代码行数:96,代码来源:LocalRewriter_UnaryOperator.cs

示例12: CheckOutVarDeclaration

 private void CheckOutVarDeclaration(BoundLocal node)
 {
     if (IsInside &&
         !node.WasCompilerGenerated && node.Syntax.Kind() == SyntaxKind.Argument &&
         ((ArgumentSyntax)node.Syntax).Identifier == node.LocalSymbol.IdentifierToken)
     {
         _variablesDeclared.Add(node.LocalSymbol);
     }
 }
开发者ID:vslsnap,项目名称:roslyn,代码行数:9,代码来源:VariablesDeclaredWalker.cs

示例13: VisitLvalue

 protected override void VisitLvalue(BoundLocal node)
 {
     CheckOutVarDeclaration(node);
     base.VisitLvalue(node);
 }
开发者ID:vslsnap,项目名称:roslyn,代码行数:5,代码来源:VariablesDeclaredWalker.cs

示例14: AddByType

        private DecisionTree AddByType(DecisionTree.ByType byType, TypeSymbol type, DecisionMaker makeDecision)
        {
            if (byType.Default != null)
            {
                try
                {
                    return AddByType(byType.Default, type, makeDecision);
                }
                finally
                {
                    if (byType.Default.MatchIsComplete)
                    {
                        byType.MatchIsComplete = true;
                    }
                }
            }
            foreach (var kvp in byType.TypeAndDecision)
            {
                var MatchedType = kvp.Key;
                var Decision = kvp.Value;
                // See if matching Type matches this value
                switch (ExpressionOfTypeMatchesPatternType(type, MatchedType, ref _useSiteDiagnostics))
                {
                    case true:
                        if (Decision.MatchIsComplete)
                        {
                            return null;
                        }

                        continue;
                    case false:
                        continue;
                    case null:
                        continue;
                }
            }

            var localSymbol = new SynthesizedLocal(_enclosingSymbol as MethodSymbol, type, SynthesizedLocalKind.PatternMatchingTemp, Syntax, false, RefKind.None);
            var expression = new BoundLocal(Syntax, localSymbol, null, type);
            var result = makeDecision(expression, type);
            Debug.Assert(result.Temp == null);
            result.Temp = localSymbol;
            byType.TypeAndDecision.Add(new KeyValuePair<TypeSymbol, DecisionTree>(type, result));
            if (ExpressionOfTypeMatchesPatternType(byType.Type, type, ref _useSiteDiagnostics) == true &&
                result.MatchIsComplete &&
                byType.WhenNull?.MatchIsComplete == true)
            {
                byType.MatchIsComplete = true;
            }

            return result;
        }
开发者ID:genlu,项目名称:roslyn,代码行数:52,代码来源:DecisionTreeBuilder.cs

示例15: AddByValue

        private DecisionTree AddByValue(DecisionTree.ByType byType, BoundConstantPattern value, DecisionMaker makeDecision)
        {
            if (byType.Default != null)
            {
                try
                {
                    return AddByValue(byType.Default, value, makeDecision);
                }
                finally
                {
                    if (byType.Default.MatchIsComplete)
                    {
                        byType.MatchIsComplete = true;
                    }
                }
            }

            if (value.ConstantValue == ConstantValue.Null)
            {
                return byType.Expression.ConstantValue?.IsNull == false
                    ? null : AddByNull((DecisionTree)byType, makeDecision);
            }

            foreach (var kvp in byType.TypeAndDecision)
            {
                var matchedType = kvp.Key;
                var decision = kvp.Value;

                // See if the test is already subsumed
                switch (ExpressionOfTypeMatchesPatternType(value.Value.Type, matchedType, ref _useSiteDiagnostics))
                {
                    case true:
                        if (decision.MatchIsComplete)
                        {
                            return null;
                        }

                        continue;
                    case false:
                    case null:
                        continue;
                }
            }

            DecisionTree forType = null;

            // Find an existing decision tree for the expression's type. Since this new test
            // should logically be last, we look for the last one we can piggy-back it onto.
            for (int i = byType.TypeAndDecision.Count - 1; i >= 0 && forType == null; i--)
            {
                var kvp = byType.TypeAndDecision[i];
                var matchedType = kvp.Key;
                var decision = kvp.Value;
                if (matchedType.TupleUnderlyingTypeOrSelf() == value.Value.Type.TupleUnderlyingTypeOrSelf())
                {
                    forType = decision;
                    break;
                }
                else if (ExpressionOfTypeMatchesPatternType(value.Value.Type, matchedType, ref _useSiteDiagnostics) != false)
                {
                    break;
                }
            }

            if (forType == null)
            {
                var type = value.Value.Type;
                var localSymbol = new SynthesizedLocal(_enclosingSymbol as MethodSymbol, type, SynthesizedLocalKind.PatternMatchingTemp, Syntax, false, RefKind.None);
                var narrowedExpression = new BoundLocal(Syntax, localSymbol, null, type);
                forType = new DecisionTree.ByValue(narrowedExpression, value.Value.Type.TupleUnderlyingTypeOrSelf(), localSymbol);
                byType.TypeAndDecision.Add(new KeyValuePair<TypeSymbol, DecisionTree>(value.Value.Type, forType));
            }

            return AddByValue(forType, value, makeDecision);
        }
开发者ID:genlu,项目名称:roslyn,代码行数:75,代码来源:DecisionTreeBuilder.cs


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